diff --git a/Controls/00-Default.ctl b/Controls/00-Default.ctl new file mode 100644 index 0000000..ef259ee --- /dev/null +++ b/Controls/00-Default.ctl @@ -0,0 +1,271 @@ +Button + Name: TTRS Move Forward + Key1: W + Key2: Arrow Up + Pressed: ctl_bMoveForward = 1; + Released: ctl_bMoveForward = 0; + +Button + Name: TTRS Move Backward + Key1: S + Key2: Arrow Down + Pressed: ctl_bMoveBackward = 1; + Released: ctl_bMoveBackward = 0; + +Button + Name: TTRS Strafe Left + Key1: A + Key2: Q + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; + +Button + Name: TTRS Strafe Right + Key1: D + Key2: E + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; + +Button + Name: TTRS Up/Jump + Key1: Space + Key2: R + Pressed: ctl_bMoveUp = 1; + Released: ctl_bMoveUp = 0; + +Button + Name: TTRS Down/Duck + Key1: F + Key2: C + Pressed: ctl_bMoveDown = 1; + Released: ctl_bMoveDown = 0; + +Button + Name: TTRS Turn Left + Key1: None + Key2: None + Pressed: ctl_bTurnLeft = 1; + Released: ctl_bTurnLeft = 0; + +Button + Name: TTRS Turn Right + Key1: None + Key2: None + Pressed: ctl_bTurnRight = 1; + Released: ctl_bTurnRight = 0; + +Button + Name: TTRS Look Up + Key1: Mouse Button 4 + Key2: None + Pressed: ctl_bTurnUp = 1; + Released: ctl_bTurnUp = 0; + +Button + Name: TTRS Look Down + Key1: Mouse Button 5 + Key2: None + Pressed: ctl_bTurnDown = 1; + Released: ctl_bTurnDown = 0; + +Button + Name: TTRS Center View + Key1: Home + Key2: None + Pressed: ctl_bCenterView = 1; + Released: ctl_bCenterView = 0; + +Button + Name: TTRS Walk + Key1: Left Shift + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ctl_bWalk = !ctl_bWalk; + +Button + Name: TTRS Walk/Run Toggle + Key1: Caps Lock + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ; + +Button + Name: TTRS Strafe + Key1: None + Key2: None + Pressed: ctl_bStrafe = 1; + Released: ctl_bStrafe = 0; + +Button + Name: TTRS Fire + Key1: Mouse Button 1 + Key2: Left Control + Pressed: ctl_bFire = 1; + Released: ctl_bFire = 0; + +Button + Name: TTRS Reload + Key1: Left Alt + Key2: None + Pressed: ctl_bReload = 1; + Released: ctl_bReload = 0; + +Button + Name: TTRS 3rd Person View + Key1: H + Key2: None + Pressed: ctl_b3rdPersonView = 1; + Released: ctl_b3rdPersonView = 0; + +Button + Name: TTRS Use/Invoke NETRICSA/Sniper Zoom + Key1: Mouse Button 2 + Key2: Enter + Pressed: ctl_bUseOrComputer = 1; + Released: ctl_bUseOrComputer = 0; + +Button + Name: TTRS Use/Sniper Zoom + Key1: None + Key2: None + Pressed: ctl_bUse = 1; + Released: ctl_bUse = 0; + +Button + Name: TTRS Invoke NETRICSA + Key1: None + Key2: None + Pressed: ctl_bComputer = 1; + Released: ctl_bComputer = 0; + +Button + Name: TTRS Talk + Key1: T + Key2: None + Pressed: con_bTalk=1; + Released: + +Button + Name: TTRS Previous Weapon + Key1: Mouse Wheel Up + Key2: [ + Pressed: ctl_bWeaponPrev = 1; + Released: ctl_bWeaponPrev = 0; + +Button + Name: TTRS Next Weapon + Key1: Mouse Wheel Down + Key2: ] + Pressed: ctl_bWeaponNext = 1; + Released: ctl_bWeaponNext = 0; + +Button + Name: TTRS Flip Weapon + Key1: Mouse Button 3 + Key2: None + Pressed: ctl_bWeaponFlip = 1; + Released: ctl_bWeaponFlip = 0; + +Button + Name: TTRS Knife/Chainsaw + Key1: 1 + Key2: None + Pressed: ctl_bSelectWeapon[1] = 1; + Released: ctl_bSelectWeapon[1] = 0; + +Button + Name: TTRS Colt/Two Colts + Key1: 2 + Key2: None + Pressed: ctl_bSelectWeapon[2] = 1; + Released: ctl_bSelectWeapon[2] = 0; + +Button + Name: TTRS Single/Double Shotgun + Key1: 3 + Key2: None + Pressed: ctl_bSelectWeapon[3] = 1; + Released: ctl_bSelectWeapon[3] = 0; + +Button + Name: TTRS Tommygun/Minigun + Key1: 4 + Key2: None + Pressed: ctl_bSelectWeapon[4] = 1; + Released: ctl_bSelectWeapon[4] = 0; + +Button + Name: TTRS Rocket Launcher/Grenade Launcher + Key1: 5 + Key2: None + Pressed: ctl_bSelectWeapon[5] = 1; + Released: ctl_bSelectWeapon[5] = 0; + +Button + Name: TTRS Flamethrower/Sniper + Key1: 6 + Key2: None + Pressed: ctl_bSelectWeapon[6] = 1; + Released: ctl_bSelectWeapon[6] = 0; + +Button + Name: TTRS Laser + Key1: 7 + Key2: None + Pressed: ctl_bSelectWeapon[7] = 1; + Released: ctl_bSelectWeapon[7] = 0; + +Button + Name: TTRS Cannon + Key1: 8 + Key2: None + Pressed: ctl_bSelectWeapon[8] = 1; + Released: ctl_bSelectWeapon[8] = 0; + +Button + Name: TTRS Serious Bomb + Key1: 0 + Key2: None + Pressed: ctl_bFireBomb = 1; + Released: ctl_bFireBomb = 0; + +Button + Name: TTRS Strafe Left + Key1: Arrow Left + Key2: None + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; + +Button + Name: TTRS Strafe Right + Key1: Arrow Right + Key2: None + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; + +Button + Name: TTRS Sniper Zoom + + Key1: X + Key2: None + Pressed: ctl_bSniperZoomIn = 1; + Released: ctl_bSniperZoomIn = 0; + +Button + Name: TTRS Sniper Zoom - + Key1: Z + Key2: None + Pressed: ctl_bSniperZoomOut = 1; + Released: ctl_bSniperZoomOut = 0; + +Axis "move u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move f/b" "None" 50 0 NotInverted Absolute NotSmooth +Axis "look u/d" "mouse Y" 50 0 NotInverted Relative NotSmooth +Axis "turn l/r" "mouse X" 50 0 NotInverted Relative NotSmooth +Axis "banking" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view banking" "None" 50 0 NotInverted Absolute NotSmooth +GlobalDontInvertLook +GlobalSmoothAxes +GlobalSensitivity 50 diff --git a/Controls/00-Default.des b/Controls/00-Default.des new file mode 100644 index 0000000..a88bf63 --- /dev/null +++ b/Controls/00-Default.des @@ -0,0 +1,2 @@ +Default controls +this will revert current controls to defaults \ No newline at end of file diff --git a/Controls/Controls0.ctl b/Controls/Controls0.ctl new file mode 100644 index 0000000..7a4b765 --- /dev/null +++ b/Controls/Controls0.ctl @@ -0,0 +1,234 @@ +Button + Name: TTRS Move Forward + Key1: W + Key2: Arrow Up + Pressed: ctl_bMoveForward = 1; + Released: ctl_bMoveForward = 0; +Button + Name: TTRS Move Backward + Key1: S + Key2: Arrow Down + Pressed: ctl_bMoveBackward = 1; + Released: ctl_bMoveBackward = 0; +Button + Name: TTRS Strafe Left + Key1: A + Key2: Q + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: D + Key2: E + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Up/Jump + Key1: Space + Key2: R + Pressed: ctl_bMoveUp = 1; + Released: ctl_bMoveUp = 0; +Button + Name: TTRS Down/Duck + Key1: F + Key2: C + Pressed: ctl_bMoveDown = 1; + Released: ctl_bMoveDown = 0; +Button + Name: TTRS Turn Left + Key1: None + Key2: None + Pressed: ctl_bTurnLeft = 1; + Released: ctl_bTurnLeft = 0; +Button + Name: TTRS Turn Right + Key1: None + Key2: None + Pressed: ctl_bTurnRight = 1; + Released: ctl_bTurnRight = 0; +Button + Name: TTRS Look Up + Key1: Mouse Button 4 + Key2: None + Pressed: ctl_bTurnUp = 1; + Released: ctl_bTurnUp = 0; +Button + Name: TTRS Look Down + Key1: Mouse Button 5 + Key2: None + Pressed: ctl_bTurnDown = 1; + Released: ctl_bTurnDown = 0; +Button + Name: TTRS Center View + Key1: Home + Key2: None + Pressed: ctl_bCenterView = 1; + Released: ctl_bCenterView = 0; +Button + Name: TTRS Walk + Key1: Left Shift + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ctl_bWalk = !ctl_bWalk; +Button + Name: TTRS Walk/Run Toggle + Key1: Caps Lock + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ; +Button + Name: TTRS Strafe + Key1: None + Key2: None + Pressed: ctl_bStrafe = 1; + Released: ctl_bStrafe = 0; +Button + Name: TTRS Fire + Key1: Mouse Button 1 + Key2: Left Control + Pressed: ctl_bFire = 1; + Released: ctl_bFire = 0; +Button + Name: TTRS Reload + Key1: Left Alt + Key2: None + Pressed: ctl_bReload = 1; + Released: ctl_bReload = 0; +Button + Name: TTRS 3rd Person View + Key1: H + Key2: None + Pressed: ctl_b3rdPersonView = 1; + Released: ctl_b3rdPersonView = 0; +Button + Name: TTRS Use/Invoke NETRICSA/Sniper Zoom + Key1: Mouse Button 2 + Key2: Enter + Pressed: ctl_bUseOrComputer = 1; + Released: ctl_bUseOrComputer = 0; +Button + Name: TTRS Use/Sniper Zoom + Key1: None + Key2: None + Pressed: ctl_bUse = 1; + Released: ctl_bUse = 0; +Button + Name: TTRS Invoke NETRICSA + Key1: None + Key2: None + Pressed: ctl_bComputer = 1; + Released: ctl_bComputer = 0; +Button + Name: TTRS Talk + Key1: T + Key2: None + Pressed: con_bTalk=1; + Released: +Button + Name: TTRS Previous Weapon + Key1: Mouse Wheel Up + Key2: [ + Pressed: ctl_bWeaponPrev = 1; + Released: ctl_bWeaponPrev = 0; +Button + Name: TTRS Next Weapon + Key1: Mouse Wheel Down + Key2: ] + Pressed: ctl_bWeaponNext = 1; + Released: ctl_bWeaponNext = 0; +Button + Name: TTRS Flip Weapon + Key1: Mouse Button 3 + Key2: None + Pressed: ctl_bWeaponFlip = 1; + Released: ctl_bWeaponFlip = 0; +Button + Name: TTRS Knife/Chainsaw + Key1: 1 + Key2: None + Pressed: ctl_bSelectWeapon[1] = 1; + Released: ctl_bSelectWeapon[1] = 0; +Button + Name: TTRS Colt/Two Colts + Key1: 2 + Key2: None + Pressed: ctl_bSelectWeapon[2] = 1; + Released: ctl_bSelectWeapon[2] = 0; +Button + Name: TTRS Single/Double Shotgun + Key1: 3 + Key2: None + Pressed: ctl_bSelectWeapon[3] = 1; + Released: ctl_bSelectWeapon[3] = 0; +Button + Name: TTRS Tommygun/Minigun + Key1: 4 + Key2: None + Pressed: ctl_bSelectWeapon[4] = 1; + Released: ctl_bSelectWeapon[4] = 0; +Button + Name: TTRS Rocket Launcher/Grenade Launcher + Key1: 5 + Key2: None + Pressed: ctl_bSelectWeapon[5] = 1; + Released: ctl_bSelectWeapon[5] = 0; +Button + Name: TTRS Flamethrower/Sniper + Key1: 6 + Key2: None + Pressed: ctl_bSelectWeapon[6] = 1; + Released: ctl_bSelectWeapon[6] = 0; +Button + Name: TTRS Laser + Key1: 7 + Key2: None + Pressed: ctl_bSelectWeapon[7] = 1; + Released: ctl_bSelectWeapon[7] = 0; +Button + Name: TTRS Cannon + Key1: 8 + Key2: None + Pressed: ctl_bSelectWeapon[8] = 1; + Released: ctl_bSelectWeapon[8] = 0; +Button + Name: TTRS Serious Bomb + Key1: 0 + Key2: None + Pressed: ctl_bFireBomb = 1; + Released: ctl_bFireBomb = 0; +Button + Name: TTRS Strafe Left + Key1: Arrow Left + Key2: None + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: Arrow Right + Key2: None + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Sniper Zoom + + Key1: X + Key2: None + Pressed: ctl_bSniperZoomIn = 1; + Released: ctl_bSniperZoomIn = 0; +Button + Name: TTRS Sniper Zoom - + Key1: Z + Key2: None + Pressed: ctl_bSniperZoomOut = 1; + Released: ctl_bSniperZoomOut = 0; +Axis "move u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move f/b" "None" 50 0 NotInverted Absolute NotSmooth +Axis "look u/d" "mouse Y" 50 0 NotInverted Relative NotSmooth +Axis "turn l/r" "mouse X" 50 0 NotInverted Relative NotSmooth +Axis "banking" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view banking" "None" 50 0 NotInverted Absolute NotSmooth +GlobalDontInvertLook +GlobalSmoothAxes +GlobalSensitivity 50 diff --git a/Controls/Controls1.ctl b/Controls/Controls1.ctl new file mode 100644 index 0000000..7a4b765 --- /dev/null +++ b/Controls/Controls1.ctl @@ -0,0 +1,234 @@ +Button + Name: TTRS Move Forward + Key1: W + Key2: Arrow Up + Pressed: ctl_bMoveForward = 1; + Released: ctl_bMoveForward = 0; +Button + Name: TTRS Move Backward + Key1: S + Key2: Arrow Down + Pressed: ctl_bMoveBackward = 1; + Released: ctl_bMoveBackward = 0; +Button + Name: TTRS Strafe Left + Key1: A + Key2: Q + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: D + Key2: E + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Up/Jump + Key1: Space + Key2: R + Pressed: ctl_bMoveUp = 1; + Released: ctl_bMoveUp = 0; +Button + Name: TTRS Down/Duck + Key1: F + Key2: C + Pressed: ctl_bMoveDown = 1; + Released: ctl_bMoveDown = 0; +Button + Name: TTRS Turn Left + Key1: None + Key2: None + Pressed: ctl_bTurnLeft = 1; + Released: ctl_bTurnLeft = 0; +Button + Name: TTRS Turn Right + Key1: None + Key2: None + Pressed: ctl_bTurnRight = 1; + Released: ctl_bTurnRight = 0; +Button + Name: TTRS Look Up + Key1: Mouse Button 4 + Key2: None + Pressed: ctl_bTurnUp = 1; + Released: ctl_bTurnUp = 0; +Button + Name: TTRS Look Down + Key1: Mouse Button 5 + Key2: None + Pressed: ctl_bTurnDown = 1; + Released: ctl_bTurnDown = 0; +Button + Name: TTRS Center View + Key1: Home + Key2: None + Pressed: ctl_bCenterView = 1; + Released: ctl_bCenterView = 0; +Button + Name: TTRS Walk + Key1: Left Shift + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ctl_bWalk = !ctl_bWalk; +Button + Name: TTRS Walk/Run Toggle + Key1: Caps Lock + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ; +Button + Name: TTRS Strafe + Key1: None + Key2: None + Pressed: ctl_bStrafe = 1; + Released: ctl_bStrafe = 0; +Button + Name: TTRS Fire + Key1: Mouse Button 1 + Key2: Left Control + Pressed: ctl_bFire = 1; + Released: ctl_bFire = 0; +Button + Name: TTRS Reload + Key1: Left Alt + Key2: None + Pressed: ctl_bReload = 1; + Released: ctl_bReload = 0; +Button + Name: TTRS 3rd Person View + Key1: H + Key2: None + Pressed: ctl_b3rdPersonView = 1; + Released: ctl_b3rdPersonView = 0; +Button + Name: TTRS Use/Invoke NETRICSA/Sniper Zoom + Key1: Mouse Button 2 + Key2: Enter + Pressed: ctl_bUseOrComputer = 1; + Released: ctl_bUseOrComputer = 0; +Button + Name: TTRS Use/Sniper Zoom + Key1: None + Key2: None + Pressed: ctl_bUse = 1; + Released: ctl_bUse = 0; +Button + Name: TTRS Invoke NETRICSA + Key1: None + Key2: None + Pressed: ctl_bComputer = 1; + Released: ctl_bComputer = 0; +Button + Name: TTRS Talk + Key1: T + Key2: None + Pressed: con_bTalk=1; + Released: +Button + Name: TTRS Previous Weapon + Key1: Mouse Wheel Up + Key2: [ + Pressed: ctl_bWeaponPrev = 1; + Released: ctl_bWeaponPrev = 0; +Button + Name: TTRS Next Weapon + Key1: Mouse Wheel Down + Key2: ] + Pressed: ctl_bWeaponNext = 1; + Released: ctl_bWeaponNext = 0; +Button + Name: TTRS Flip Weapon + Key1: Mouse Button 3 + Key2: None + Pressed: ctl_bWeaponFlip = 1; + Released: ctl_bWeaponFlip = 0; +Button + Name: TTRS Knife/Chainsaw + Key1: 1 + Key2: None + Pressed: ctl_bSelectWeapon[1] = 1; + Released: ctl_bSelectWeapon[1] = 0; +Button + Name: TTRS Colt/Two Colts + Key1: 2 + Key2: None + Pressed: ctl_bSelectWeapon[2] = 1; + Released: ctl_bSelectWeapon[2] = 0; +Button + Name: TTRS Single/Double Shotgun + Key1: 3 + Key2: None + Pressed: ctl_bSelectWeapon[3] = 1; + Released: ctl_bSelectWeapon[3] = 0; +Button + Name: TTRS Tommygun/Minigun + Key1: 4 + Key2: None + Pressed: ctl_bSelectWeapon[4] = 1; + Released: ctl_bSelectWeapon[4] = 0; +Button + Name: TTRS Rocket Launcher/Grenade Launcher + Key1: 5 + Key2: None + Pressed: ctl_bSelectWeapon[5] = 1; + Released: ctl_bSelectWeapon[5] = 0; +Button + Name: TTRS Flamethrower/Sniper + Key1: 6 + Key2: None + Pressed: ctl_bSelectWeapon[6] = 1; + Released: ctl_bSelectWeapon[6] = 0; +Button + Name: TTRS Laser + Key1: 7 + Key2: None + Pressed: ctl_bSelectWeapon[7] = 1; + Released: ctl_bSelectWeapon[7] = 0; +Button + Name: TTRS Cannon + Key1: 8 + Key2: None + Pressed: ctl_bSelectWeapon[8] = 1; + Released: ctl_bSelectWeapon[8] = 0; +Button + Name: TTRS Serious Bomb + Key1: 0 + Key2: None + Pressed: ctl_bFireBomb = 1; + Released: ctl_bFireBomb = 0; +Button + Name: TTRS Strafe Left + Key1: Arrow Left + Key2: None + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: Arrow Right + Key2: None + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Sniper Zoom + + Key1: X + Key2: None + Pressed: ctl_bSniperZoomIn = 1; + Released: ctl_bSniperZoomIn = 0; +Button + Name: TTRS Sniper Zoom - + Key1: Z + Key2: None + Pressed: ctl_bSniperZoomOut = 1; + Released: ctl_bSniperZoomOut = 0; +Axis "move u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move f/b" "None" 50 0 NotInverted Absolute NotSmooth +Axis "look u/d" "mouse Y" 50 0 NotInverted Relative NotSmooth +Axis "turn l/r" "mouse X" 50 0 NotInverted Relative NotSmooth +Axis "banking" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view banking" "None" 50 0 NotInverted Absolute NotSmooth +GlobalDontInvertLook +GlobalSmoothAxes +GlobalSensitivity 50 diff --git a/Controls/Controls2.ctl b/Controls/Controls2.ctl new file mode 100644 index 0000000..7a4b765 --- /dev/null +++ b/Controls/Controls2.ctl @@ -0,0 +1,234 @@ +Button + Name: TTRS Move Forward + Key1: W + Key2: Arrow Up + Pressed: ctl_bMoveForward = 1; + Released: ctl_bMoveForward = 0; +Button + Name: TTRS Move Backward + Key1: S + Key2: Arrow Down + Pressed: ctl_bMoveBackward = 1; + Released: ctl_bMoveBackward = 0; +Button + Name: TTRS Strafe Left + Key1: A + Key2: Q + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: D + Key2: E + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Up/Jump + Key1: Space + Key2: R + Pressed: ctl_bMoveUp = 1; + Released: ctl_bMoveUp = 0; +Button + Name: TTRS Down/Duck + Key1: F + Key2: C + Pressed: ctl_bMoveDown = 1; + Released: ctl_bMoveDown = 0; +Button + Name: TTRS Turn Left + Key1: None + Key2: None + Pressed: ctl_bTurnLeft = 1; + Released: ctl_bTurnLeft = 0; +Button + Name: TTRS Turn Right + Key1: None + Key2: None + Pressed: ctl_bTurnRight = 1; + Released: ctl_bTurnRight = 0; +Button + Name: TTRS Look Up + Key1: Mouse Button 4 + Key2: None + Pressed: ctl_bTurnUp = 1; + Released: ctl_bTurnUp = 0; +Button + Name: TTRS Look Down + Key1: Mouse Button 5 + Key2: None + Pressed: ctl_bTurnDown = 1; + Released: ctl_bTurnDown = 0; +Button + Name: TTRS Center View + Key1: Home + Key2: None + Pressed: ctl_bCenterView = 1; + Released: ctl_bCenterView = 0; +Button + Name: TTRS Walk + Key1: Left Shift + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ctl_bWalk = !ctl_bWalk; +Button + Name: TTRS Walk/Run Toggle + Key1: Caps Lock + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ; +Button + Name: TTRS Strafe + Key1: None + Key2: None + Pressed: ctl_bStrafe = 1; + Released: ctl_bStrafe = 0; +Button + Name: TTRS Fire + Key1: Mouse Button 1 + Key2: Left Control + Pressed: ctl_bFire = 1; + Released: ctl_bFire = 0; +Button + Name: TTRS Reload + Key1: Left Alt + Key2: None + Pressed: ctl_bReload = 1; + Released: ctl_bReload = 0; +Button + Name: TTRS 3rd Person View + Key1: H + Key2: None + Pressed: ctl_b3rdPersonView = 1; + Released: ctl_b3rdPersonView = 0; +Button + Name: TTRS Use/Invoke NETRICSA/Sniper Zoom + Key1: Mouse Button 2 + Key2: Enter + Pressed: ctl_bUseOrComputer = 1; + Released: ctl_bUseOrComputer = 0; +Button + Name: TTRS Use/Sniper Zoom + Key1: None + Key2: None + Pressed: ctl_bUse = 1; + Released: ctl_bUse = 0; +Button + Name: TTRS Invoke NETRICSA + Key1: None + Key2: None + Pressed: ctl_bComputer = 1; + Released: ctl_bComputer = 0; +Button + Name: TTRS Talk + Key1: T + Key2: None + Pressed: con_bTalk=1; + Released: +Button + Name: TTRS Previous Weapon + Key1: Mouse Wheel Up + Key2: [ + Pressed: ctl_bWeaponPrev = 1; + Released: ctl_bWeaponPrev = 0; +Button + Name: TTRS Next Weapon + Key1: Mouse Wheel Down + Key2: ] + Pressed: ctl_bWeaponNext = 1; + Released: ctl_bWeaponNext = 0; +Button + Name: TTRS Flip Weapon + Key1: Mouse Button 3 + Key2: None + Pressed: ctl_bWeaponFlip = 1; + Released: ctl_bWeaponFlip = 0; +Button + Name: TTRS Knife/Chainsaw + Key1: 1 + Key2: None + Pressed: ctl_bSelectWeapon[1] = 1; + Released: ctl_bSelectWeapon[1] = 0; +Button + Name: TTRS Colt/Two Colts + Key1: 2 + Key2: None + Pressed: ctl_bSelectWeapon[2] = 1; + Released: ctl_bSelectWeapon[2] = 0; +Button + Name: TTRS Single/Double Shotgun + Key1: 3 + Key2: None + Pressed: ctl_bSelectWeapon[3] = 1; + Released: ctl_bSelectWeapon[3] = 0; +Button + Name: TTRS Tommygun/Minigun + Key1: 4 + Key2: None + Pressed: ctl_bSelectWeapon[4] = 1; + Released: ctl_bSelectWeapon[4] = 0; +Button + Name: TTRS Rocket Launcher/Grenade Launcher + Key1: 5 + Key2: None + Pressed: ctl_bSelectWeapon[5] = 1; + Released: ctl_bSelectWeapon[5] = 0; +Button + Name: TTRS Flamethrower/Sniper + Key1: 6 + Key2: None + Pressed: ctl_bSelectWeapon[6] = 1; + Released: ctl_bSelectWeapon[6] = 0; +Button + Name: TTRS Laser + Key1: 7 + Key2: None + Pressed: ctl_bSelectWeapon[7] = 1; + Released: ctl_bSelectWeapon[7] = 0; +Button + Name: TTRS Cannon + Key1: 8 + Key2: None + Pressed: ctl_bSelectWeapon[8] = 1; + Released: ctl_bSelectWeapon[8] = 0; +Button + Name: TTRS Serious Bomb + Key1: 0 + Key2: None + Pressed: ctl_bFireBomb = 1; + Released: ctl_bFireBomb = 0; +Button + Name: TTRS Strafe Left + Key1: Arrow Left + Key2: None + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: Arrow Right + Key2: None + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Sniper Zoom + + Key1: X + Key2: None + Pressed: ctl_bSniperZoomIn = 1; + Released: ctl_bSniperZoomIn = 0; +Button + Name: TTRS Sniper Zoom - + Key1: Z + Key2: None + Pressed: ctl_bSniperZoomOut = 1; + Released: ctl_bSniperZoomOut = 0; +Axis "move u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move f/b" "None" 50 0 NotInverted Absolute NotSmooth +Axis "look u/d" "mouse Y" 50 0 NotInverted Relative NotSmooth +Axis "turn l/r" "mouse X" 50 0 NotInverted Relative NotSmooth +Axis "banking" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view banking" "None" 50 0 NotInverted Absolute NotSmooth +GlobalDontInvertLook +GlobalSmoothAxes +GlobalSensitivity 50 diff --git a/Controls/Controls3.ctl b/Controls/Controls3.ctl new file mode 100644 index 0000000..7a4b765 --- /dev/null +++ b/Controls/Controls3.ctl @@ -0,0 +1,234 @@ +Button + Name: TTRS Move Forward + Key1: W + Key2: Arrow Up + Pressed: ctl_bMoveForward = 1; + Released: ctl_bMoveForward = 0; +Button + Name: TTRS Move Backward + Key1: S + Key2: Arrow Down + Pressed: ctl_bMoveBackward = 1; + Released: ctl_bMoveBackward = 0; +Button + Name: TTRS Strafe Left + Key1: A + Key2: Q + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: D + Key2: E + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Up/Jump + Key1: Space + Key2: R + Pressed: ctl_bMoveUp = 1; + Released: ctl_bMoveUp = 0; +Button + Name: TTRS Down/Duck + Key1: F + Key2: C + Pressed: ctl_bMoveDown = 1; + Released: ctl_bMoveDown = 0; +Button + Name: TTRS Turn Left + Key1: None + Key2: None + Pressed: ctl_bTurnLeft = 1; + Released: ctl_bTurnLeft = 0; +Button + Name: TTRS Turn Right + Key1: None + Key2: None + Pressed: ctl_bTurnRight = 1; + Released: ctl_bTurnRight = 0; +Button + Name: TTRS Look Up + Key1: Mouse Button 4 + Key2: None + Pressed: ctl_bTurnUp = 1; + Released: ctl_bTurnUp = 0; +Button + Name: TTRS Look Down + Key1: Mouse Button 5 + Key2: None + Pressed: ctl_bTurnDown = 1; + Released: ctl_bTurnDown = 0; +Button + Name: TTRS Center View + Key1: Home + Key2: None + Pressed: ctl_bCenterView = 1; + Released: ctl_bCenterView = 0; +Button + Name: TTRS Walk + Key1: Left Shift + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ctl_bWalk = !ctl_bWalk; +Button + Name: TTRS Walk/Run Toggle + Key1: Caps Lock + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ; +Button + Name: TTRS Strafe + Key1: None + Key2: None + Pressed: ctl_bStrafe = 1; + Released: ctl_bStrafe = 0; +Button + Name: TTRS Fire + Key1: Mouse Button 1 + Key2: Left Control + Pressed: ctl_bFire = 1; + Released: ctl_bFire = 0; +Button + Name: TTRS Reload + Key1: Left Alt + Key2: None + Pressed: ctl_bReload = 1; + Released: ctl_bReload = 0; +Button + Name: TTRS 3rd Person View + Key1: H + Key2: None + Pressed: ctl_b3rdPersonView = 1; + Released: ctl_b3rdPersonView = 0; +Button + Name: TTRS Use/Invoke NETRICSA/Sniper Zoom + Key1: Mouse Button 2 + Key2: Enter + Pressed: ctl_bUseOrComputer = 1; + Released: ctl_bUseOrComputer = 0; +Button + Name: TTRS Use/Sniper Zoom + Key1: None + Key2: None + Pressed: ctl_bUse = 1; + Released: ctl_bUse = 0; +Button + Name: TTRS Invoke NETRICSA + Key1: None + Key2: None + Pressed: ctl_bComputer = 1; + Released: ctl_bComputer = 0; +Button + Name: TTRS Talk + Key1: T + Key2: None + Pressed: con_bTalk=1; + Released: +Button + Name: TTRS Previous Weapon + Key1: Mouse Wheel Up + Key2: [ + Pressed: ctl_bWeaponPrev = 1; + Released: ctl_bWeaponPrev = 0; +Button + Name: TTRS Next Weapon + Key1: Mouse Wheel Down + Key2: ] + Pressed: ctl_bWeaponNext = 1; + Released: ctl_bWeaponNext = 0; +Button + Name: TTRS Flip Weapon + Key1: Mouse Button 3 + Key2: None + Pressed: ctl_bWeaponFlip = 1; + Released: ctl_bWeaponFlip = 0; +Button + Name: TTRS Knife/Chainsaw + Key1: 1 + Key2: None + Pressed: ctl_bSelectWeapon[1] = 1; + Released: ctl_bSelectWeapon[1] = 0; +Button + Name: TTRS Colt/Two Colts + Key1: 2 + Key2: None + Pressed: ctl_bSelectWeapon[2] = 1; + Released: ctl_bSelectWeapon[2] = 0; +Button + Name: TTRS Single/Double Shotgun + Key1: 3 + Key2: None + Pressed: ctl_bSelectWeapon[3] = 1; + Released: ctl_bSelectWeapon[3] = 0; +Button + Name: TTRS Tommygun/Minigun + Key1: 4 + Key2: None + Pressed: ctl_bSelectWeapon[4] = 1; + Released: ctl_bSelectWeapon[4] = 0; +Button + Name: TTRS Rocket Launcher/Grenade Launcher + Key1: 5 + Key2: None + Pressed: ctl_bSelectWeapon[5] = 1; + Released: ctl_bSelectWeapon[5] = 0; +Button + Name: TTRS Flamethrower/Sniper + Key1: 6 + Key2: None + Pressed: ctl_bSelectWeapon[6] = 1; + Released: ctl_bSelectWeapon[6] = 0; +Button + Name: TTRS Laser + Key1: 7 + Key2: None + Pressed: ctl_bSelectWeapon[7] = 1; + Released: ctl_bSelectWeapon[7] = 0; +Button + Name: TTRS Cannon + Key1: 8 + Key2: None + Pressed: ctl_bSelectWeapon[8] = 1; + Released: ctl_bSelectWeapon[8] = 0; +Button + Name: TTRS Serious Bomb + Key1: 0 + Key2: None + Pressed: ctl_bFireBomb = 1; + Released: ctl_bFireBomb = 0; +Button + Name: TTRS Strafe Left + Key1: Arrow Left + Key2: None + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: Arrow Right + Key2: None + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Sniper Zoom + + Key1: X + Key2: None + Pressed: ctl_bSniperZoomIn = 1; + Released: ctl_bSniperZoomIn = 0; +Button + Name: TTRS Sniper Zoom - + Key1: Z + Key2: None + Pressed: ctl_bSniperZoomOut = 1; + Released: ctl_bSniperZoomOut = 0; +Axis "move u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move f/b" "None" 50 0 NotInverted Absolute NotSmooth +Axis "look u/d" "mouse Y" 50 0 NotInverted Relative NotSmooth +Axis "turn l/r" "mouse X" 50 0 NotInverted Relative NotSmooth +Axis "banking" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view banking" "None" 50 0 NotInverted Absolute NotSmooth +GlobalDontInvertLook +GlobalSmoothAxes +GlobalSensitivity 50 diff --git a/Controls/Controls4.ctl b/Controls/Controls4.ctl new file mode 100644 index 0000000..7a4b765 --- /dev/null +++ b/Controls/Controls4.ctl @@ -0,0 +1,234 @@ +Button + Name: TTRS Move Forward + Key1: W + Key2: Arrow Up + Pressed: ctl_bMoveForward = 1; + Released: ctl_bMoveForward = 0; +Button + Name: TTRS Move Backward + Key1: S + Key2: Arrow Down + Pressed: ctl_bMoveBackward = 1; + Released: ctl_bMoveBackward = 0; +Button + Name: TTRS Strafe Left + Key1: A + Key2: Q + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: D + Key2: E + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Up/Jump + Key1: Space + Key2: R + Pressed: ctl_bMoveUp = 1; + Released: ctl_bMoveUp = 0; +Button + Name: TTRS Down/Duck + Key1: F + Key2: C + Pressed: ctl_bMoveDown = 1; + Released: ctl_bMoveDown = 0; +Button + Name: TTRS Turn Left + Key1: None + Key2: None + Pressed: ctl_bTurnLeft = 1; + Released: ctl_bTurnLeft = 0; +Button + Name: TTRS Turn Right + Key1: None + Key2: None + Pressed: ctl_bTurnRight = 1; + Released: ctl_bTurnRight = 0; +Button + Name: TTRS Look Up + Key1: Mouse Button 4 + Key2: None + Pressed: ctl_bTurnUp = 1; + Released: ctl_bTurnUp = 0; +Button + Name: TTRS Look Down + Key1: Mouse Button 5 + Key2: None + Pressed: ctl_bTurnDown = 1; + Released: ctl_bTurnDown = 0; +Button + Name: TTRS Center View + Key1: Home + Key2: None + Pressed: ctl_bCenterView = 1; + Released: ctl_bCenterView = 0; +Button + Name: TTRS Walk + Key1: Left Shift + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ctl_bWalk = !ctl_bWalk; +Button + Name: TTRS Walk/Run Toggle + Key1: Caps Lock + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ; +Button + Name: TTRS Strafe + Key1: None + Key2: None + Pressed: ctl_bStrafe = 1; + Released: ctl_bStrafe = 0; +Button + Name: TTRS Fire + Key1: Mouse Button 1 + Key2: Left Control + Pressed: ctl_bFire = 1; + Released: ctl_bFire = 0; +Button + Name: TTRS Reload + Key1: Left Alt + Key2: None + Pressed: ctl_bReload = 1; + Released: ctl_bReload = 0; +Button + Name: TTRS 3rd Person View + Key1: H + Key2: None + Pressed: ctl_b3rdPersonView = 1; + Released: ctl_b3rdPersonView = 0; +Button + Name: TTRS Use/Invoke NETRICSA/Sniper Zoom + Key1: Mouse Button 2 + Key2: Enter + Pressed: ctl_bUseOrComputer = 1; + Released: ctl_bUseOrComputer = 0; +Button + Name: TTRS Use/Sniper Zoom + Key1: None + Key2: None + Pressed: ctl_bUse = 1; + Released: ctl_bUse = 0; +Button + Name: TTRS Invoke NETRICSA + Key1: None + Key2: None + Pressed: ctl_bComputer = 1; + Released: ctl_bComputer = 0; +Button + Name: TTRS Talk + Key1: T + Key2: None + Pressed: con_bTalk=1; + Released: +Button + Name: TTRS Previous Weapon + Key1: Mouse Wheel Up + Key2: [ + Pressed: ctl_bWeaponPrev = 1; + Released: ctl_bWeaponPrev = 0; +Button + Name: TTRS Next Weapon + Key1: Mouse Wheel Down + Key2: ] + Pressed: ctl_bWeaponNext = 1; + Released: ctl_bWeaponNext = 0; +Button + Name: TTRS Flip Weapon + Key1: Mouse Button 3 + Key2: None + Pressed: ctl_bWeaponFlip = 1; + Released: ctl_bWeaponFlip = 0; +Button + Name: TTRS Knife/Chainsaw + Key1: 1 + Key2: None + Pressed: ctl_bSelectWeapon[1] = 1; + Released: ctl_bSelectWeapon[1] = 0; +Button + Name: TTRS Colt/Two Colts + Key1: 2 + Key2: None + Pressed: ctl_bSelectWeapon[2] = 1; + Released: ctl_bSelectWeapon[2] = 0; +Button + Name: TTRS Single/Double Shotgun + Key1: 3 + Key2: None + Pressed: ctl_bSelectWeapon[3] = 1; + Released: ctl_bSelectWeapon[3] = 0; +Button + Name: TTRS Tommygun/Minigun + Key1: 4 + Key2: None + Pressed: ctl_bSelectWeapon[4] = 1; + Released: ctl_bSelectWeapon[4] = 0; +Button + Name: TTRS Rocket Launcher/Grenade Launcher + Key1: 5 + Key2: None + Pressed: ctl_bSelectWeapon[5] = 1; + Released: ctl_bSelectWeapon[5] = 0; +Button + Name: TTRS Flamethrower/Sniper + Key1: 6 + Key2: None + Pressed: ctl_bSelectWeapon[6] = 1; + Released: ctl_bSelectWeapon[6] = 0; +Button + Name: TTRS Laser + Key1: 7 + Key2: None + Pressed: ctl_bSelectWeapon[7] = 1; + Released: ctl_bSelectWeapon[7] = 0; +Button + Name: TTRS Cannon + Key1: 8 + Key2: None + Pressed: ctl_bSelectWeapon[8] = 1; + Released: ctl_bSelectWeapon[8] = 0; +Button + Name: TTRS Serious Bomb + Key1: 0 + Key2: None + Pressed: ctl_bFireBomb = 1; + Released: ctl_bFireBomb = 0; +Button + Name: TTRS Strafe Left + Key1: Arrow Left + Key2: None + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: Arrow Right + Key2: None + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Sniper Zoom + + Key1: X + Key2: None + Pressed: ctl_bSniperZoomIn = 1; + Released: ctl_bSniperZoomIn = 0; +Button + Name: TTRS Sniper Zoom - + Key1: Z + Key2: None + Pressed: ctl_bSniperZoomOut = 1; + Released: ctl_bSniperZoomOut = 0; +Axis "move u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move f/b" "None" 50 0 NotInverted Absolute NotSmooth +Axis "look u/d" "mouse Y" 50 0 NotInverted Relative NotSmooth +Axis "turn l/r" "mouse X" 50 0 NotInverted Relative NotSmooth +Axis "banking" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view banking" "None" 50 0 NotInverted Absolute NotSmooth +GlobalDontInvertLook +GlobalSmoothAxes +GlobalSensitivity 50 diff --git a/Controls/Controls5.ctl b/Controls/Controls5.ctl new file mode 100644 index 0000000..7a4b765 --- /dev/null +++ b/Controls/Controls5.ctl @@ -0,0 +1,234 @@ +Button + Name: TTRS Move Forward + Key1: W + Key2: Arrow Up + Pressed: ctl_bMoveForward = 1; + Released: ctl_bMoveForward = 0; +Button + Name: TTRS Move Backward + Key1: S + Key2: Arrow Down + Pressed: ctl_bMoveBackward = 1; + Released: ctl_bMoveBackward = 0; +Button + Name: TTRS Strafe Left + Key1: A + Key2: Q + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: D + Key2: E + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Up/Jump + Key1: Space + Key2: R + Pressed: ctl_bMoveUp = 1; + Released: ctl_bMoveUp = 0; +Button + Name: TTRS Down/Duck + Key1: F + Key2: C + Pressed: ctl_bMoveDown = 1; + Released: ctl_bMoveDown = 0; +Button + Name: TTRS Turn Left + Key1: None + Key2: None + Pressed: ctl_bTurnLeft = 1; + Released: ctl_bTurnLeft = 0; +Button + Name: TTRS Turn Right + Key1: None + Key2: None + Pressed: ctl_bTurnRight = 1; + Released: ctl_bTurnRight = 0; +Button + Name: TTRS Look Up + Key1: Mouse Button 4 + Key2: None + Pressed: ctl_bTurnUp = 1; + Released: ctl_bTurnUp = 0; +Button + Name: TTRS Look Down + Key1: Mouse Button 5 + Key2: None + Pressed: ctl_bTurnDown = 1; + Released: ctl_bTurnDown = 0; +Button + Name: TTRS Center View + Key1: Home + Key2: None + Pressed: ctl_bCenterView = 1; + Released: ctl_bCenterView = 0; +Button + Name: TTRS Walk + Key1: Left Shift + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ctl_bWalk = !ctl_bWalk; +Button + Name: TTRS Walk/Run Toggle + Key1: Caps Lock + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ; +Button + Name: TTRS Strafe + Key1: None + Key2: None + Pressed: ctl_bStrafe = 1; + Released: ctl_bStrafe = 0; +Button + Name: TTRS Fire + Key1: Mouse Button 1 + Key2: Left Control + Pressed: ctl_bFire = 1; + Released: ctl_bFire = 0; +Button + Name: TTRS Reload + Key1: Left Alt + Key2: None + Pressed: ctl_bReload = 1; + Released: ctl_bReload = 0; +Button + Name: TTRS 3rd Person View + Key1: H + Key2: None + Pressed: ctl_b3rdPersonView = 1; + Released: ctl_b3rdPersonView = 0; +Button + Name: TTRS Use/Invoke NETRICSA/Sniper Zoom + Key1: Mouse Button 2 + Key2: Enter + Pressed: ctl_bUseOrComputer = 1; + Released: ctl_bUseOrComputer = 0; +Button + Name: TTRS Use/Sniper Zoom + Key1: None + Key2: None + Pressed: ctl_bUse = 1; + Released: ctl_bUse = 0; +Button + Name: TTRS Invoke NETRICSA + Key1: None + Key2: None + Pressed: ctl_bComputer = 1; + Released: ctl_bComputer = 0; +Button + Name: TTRS Talk + Key1: T + Key2: None + Pressed: con_bTalk=1; + Released: +Button + Name: TTRS Previous Weapon + Key1: Mouse Wheel Up + Key2: [ + Pressed: ctl_bWeaponPrev = 1; + Released: ctl_bWeaponPrev = 0; +Button + Name: TTRS Next Weapon + Key1: Mouse Wheel Down + Key2: ] + Pressed: ctl_bWeaponNext = 1; + Released: ctl_bWeaponNext = 0; +Button + Name: TTRS Flip Weapon + Key1: Mouse Button 3 + Key2: None + Pressed: ctl_bWeaponFlip = 1; + Released: ctl_bWeaponFlip = 0; +Button + Name: TTRS Knife/Chainsaw + Key1: 1 + Key2: None + Pressed: ctl_bSelectWeapon[1] = 1; + Released: ctl_bSelectWeapon[1] = 0; +Button + Name: TTRS Colt/Two Colts + Key1: 2 + Key2: None + Pressed: ctl_bSelectWeapon[2] = 1; + Released: ctl_bSelectWeapon[2] = 0; +Button + Name: TTRS Single/Double Shotgun + Key1: 3 + Key2: None + Pressed: ctl_bSelectWeapon[3] = 1; + Released: ctl_bSelectWeapon[3] = 0; +Button + Name: TTRS Tommygun/Minigun + Key1: 4 + Key2: None + Pressed: ctl_bSelectWeapon[4] = 1; + Released: ctl_bSelectWeapon[4] = 0; +Button + Name: TTRS Rocket Launcher/Grenade Launcher + Key1: 5 + Key2: None + Pressed: ctl_bSelectWeapon[5] = 1; + Released: ctl_bSelectWeapon[5] = 0; +Button + Name: TTRS Flamethrower/Sniper + Key1: 6 + Key2: None + Pressed: ctl_bSelectWeapon[6] = 1; + Released: ctl_bSelectWeapon[6] = 0; +Button + Name: TTRS Laser + Key1: 7 + Key2: None + Pressed: ctl_bSelectWeapon[7] = 1; + Released: ctl_bSelectWeapon[7] = 0; +Button + Name: TTRS Cannon + Key1: 8 + Key2: None + Pressed: ctl_bSelectWeapon[8] = 1; + Released: ctl_bSelectWeapon[8] = 0; +Button + Name: TTRS Serious Bomb + Key1: 0 + Key2: None + Pressed: ctl_bFireBomb = 1; + Released: ctl_bFireBomb = 0; +Button + Name: TTRS Strafe Left + Key1: Arrow Left + Key2: None + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: Arrow Right + Key2: None + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Sniper Zoom + + Key1: X + Key2: None + Pressed: ctl_bSniperZoomIn = 1; + Released: ctl_bSniperZoomIn = 0; +Button + Name: TTRS Sniper Zoom - + Key1: Z + Key2: None + Pressed: ctl_bSniperZoomOut = 1; + Released: ctl_bSniperZoomOut = 0; +Axis "move u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move f/b" "None" 50 0 NotInverted Absolute NotSmooth +Axis "look u/d" "mouse Y" 50 0 NotInverted Relative NotSmooth +Axis "turn l/r" "mouse X" 50 0 NotInverted Relative NotSmooth +Axis "banking" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view banking" "None" 50 0 NotInverted Absolute NotSmooth +GlobalDontInvertLook +GlobalSmoothAxes +GlobalSensitivity 50 diff --git a/Controls/Controls6.ctl b/Controls/Controls6.ctl new file mode 100644 index 0000000..7a4b765 --- /dev/null +++ b/Controls/Controls6.ctl @@ -0,0 +1,234 @@ +Button + Name: TTRS Move Forward + Key1: W + Key2: Arrow Up + Pressed: ctl_bMoveForward = 1; + Released: ctl_bMoveForward = 0; +Button + Name: TTRS Move Backward + Key1: S + Key2: Arrow Down + Pressed: ctl_bMoveBackward = 1; + Released: ctl_bMoveBackward = 0; +Button + Name: TTRS Strafe Left + Key1: A + Key2: Q + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: D + Key2: E + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Up/Jump + Key1: Space + Key2: R + Pressed: ctl_bMoveUp = 1; + Released: ctl_bMoveUp = 0; +Button + Name: TTRS Down/Duck + Key1: F + Key2: C + Pressed: ctl_bMoveDown = 1; + Released: ctl_bMoveDown = 0; +Button + Name: TTRS Turn Left + Key1: None + Key2: None + Pressed: ctl_bTurnLeft = 1; + Released: ctl_bTurnLeft = 0; +Button + Name: TTRS Turn Right + Key1: None + Key2: None + Pressed: ctl_bTurnRight = 1; + Released: ctl_bTurnRight = 0; +Button + Name: TTRS Look Up + Key1: Mouse Button 4 + Key2: None + Pressed: ctl_bTurnUp = 1; + Released: ctl_bTurnUp = 0; +Button + Name: TTRS Look Down + Key1: Mouse Button 5 + Key2: None + Pressed: ctl_bTurnDown = 1; + Released: ctl_bTurnDown = 0; +Button + Name: TTRS Center View + Key1: Home + Key2: None + Pressed: ctl_bCenterView = 1; + Released: ctl_bCenterView = 0; +Button + Name: TTRS Walk + Key1: Left Shift + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ctl_bWalk = !ctl_bWalk; +Button + Name: TTRS Walk/Run Toggle + Key1: Caps Lock + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ; +Button + Name: TTRS Strafe + Key1: None + Key2: None + Pressed: ctl_bStrafe = 1; + Released: ctl_bStrafe = 0; +Button + Name: TTRS Fire + Key1: Mouse Button 1 + Key2: Left Control + Pressed: ctl_bFire = 1; + Released: ctl_bFire = 0; +Button + Name: TTRS Reload + Key1: Left Alt + Key2: None + Pressed: ctl_bReload = 1; + Released: ctl_bReload = 0; +Button + Name: TTRS 3rd Person View + Key1: H + Key2: None + Pressed: ctl_b3rdPersonView = 1; + Released: ctl_b3rdPersonView = 0; +Button + Name: TTRS Use/Invoke NETRICSA/Sniper Zoom + Key1: Mouse Button 2 + Key2: Enter + Pressed: ctl_bUseOrComputer = 1; + Released: ctl_bUseOrComputer = 0; +Button + Name: TTRS Use/Sniper Zoom + Key1: None + Key2: None + Pressed: ctl_bUse = 1; + Released: ctl_bUse = 0; +Button + Name: TTRS Invoke NETRICSA + Key1: None + Key2: None + Pressed: ctl_bComputer = 1; + Released: ctl_bComputer = 0; +Button + Name: TTRS Talk + Key1: T + Key2: None + Pressed: con_bTalk=1; + Released: +Button + Name: TTRS Previous Weapon + Key1: Mouse Wheel Up + Key2: [ + Pressed: ctl_bWeaponPrev = 1; + Released: ctl_bWeaponPrev = 0; +Button + Name: TTRS Next Weapon + Key1: Mouse Wheel Down + Key2: ] + Pressed: ctl_bWeaponNext = 1; + Released: ctl_bWeaponNext = 0; +Button + Name: TTRS Flip Weapon + Key1: Mouse Button 3 + Key2: None + Pressed: ctl_bWeaponFlip = 1; + Released: ctl_bWeaponFlip = 0; +Button + Name: TTRS Knife/Chainsaw + Key1: 1 + Key2: None + Pressed: ctl_bSelectWeapon[1] = 1; + Released: ctl_bSelectWeapon[1] = 0; +Button + Name: TTRS Colt/Two Colts + Key1: 2 + Key2: None + Pressed: ctl_bSelectWeapon[2] = 1; + Released: ctl_bSelectWeapon[2] = 0; +Button + Name: TTRS Single/Double Shotgun + Key1: 3 + Key2: None + Pressed: ctl_bSelectWeapon[3] = 1; + Released: ctl_bSelectWeapon[3] = 0; +Button + Name: TTRS Tommygun/Minigun + Key1: 4 + Key2: None + Pressed: ctl_bSelectWeapon[4] = 1; + Released: ctl_bSelectWeapon[4] = 0; +Button + Name: TTRS Rocket Launcher/Grenade Launcher + Key1: 5 + Key2: None + Pressed: ctl_bSelectWeapon[5] = 1; + Released: ctl_bSelectWeapon[5] = 0; +Button + Name: TTRS Flamethrower/Sniper + Key1: 6 + Key2: None + Pressed: ctl_bSelectWeapon[6] = 1; + Released: ctl_bSelectWeapon[6] = 0; +Button + Name: TTRS Laser + Key1: 7 + Key2: None + Pressed: ctl_bSelectWeapon[7] = 1; + Released: ctl_bSelectWeapon[7] = 0; +Button + Name: TTRS Cannon + Key1: 8 + Key2: None + Pressed: ctl_bSelectWeapon[8] = 1; + Released: ctl_bSelectWeapon[8] = 0; +Button + Name: TTRS Serious Bomb + Key1: 0 + Key2: None + Pressed: ctl_bFireBomb = 1; + Released: ctl_bFireBomb = 0; +Button + Name: TTRS Strafe Left + Key1: Arrow Left + Key2: None + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: Arrow Right + Key2: None + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Sniper Zoom + + Key1: X + Key2: None + Pressed: ctl_bSniperZoomIn = 1; + Released: ctl_bSniperZoomIn = 0; +Button + Name: TTRS Sniper Zoom - + Key1: Z + Key2: None + Pressed: ctl_bSniperZoomOut = 1; + Released: ctl_bSniperZoomOut = 0; +Axis "move u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move f/b" "None" 50 0 NotInverted Absolute NotSmooth +Axis "look u/d" "mouse Y" 50 0 NotInverted Relative NotSmooth +Axis "turn l/r" "mouse X" 50 0 NotInverted Relative NotSmooth +Axis "banking" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view banking" "None" 50 0 NotInverted Absolute NotSmooth +GlobalDontInvertLook +GlobalSmoothAxes +GlobalSensitivity 50 diff --git a/Controls/Controls7.ctl b/Controls/Controls7.ctl new file mode 100644 index 0000000..7a4b765 --- /dev/null +++ b/Controls/Controls7.ctl @@ -0,0 +1,234 @@ +Button + Name: TTRS Move Forward + Key1: W + Key2: Arrow Up + Pressed: ctl_bMoveForward = 1; + Released: ctl_bMoveForward = 0; +Button + Name: TTRS Move Backward + Key1: S + Key2: Arrow Down + Pressed: ctl_bMoveBackward = 1; + Released: ctl_bMoveBackward = 0; +Button + Name: TTRS Strafe Left + Key1: A + Key2: Q + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: D + Key2: E + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Up/Jump + Key1: Space + Key2: R + Pressed: ctl_bMoveUp = 1; + Released: ctl_bMoveUp = 0; +Button + Name: TTRS Down/Duck + Key1: F + Key2: C + Pressed: ctl_bMoveDown = 1; + Released: ctl_bMoveDown = 0; +Button + Name: TTRS Turn Left + Key1: None + Key2: None + Pressed: ctl_bTurnLeft = 1; + Released: ctl_bTurnLeft = 0; +Button + Name: TTRS Turn Right + Key1: None + Key2: None + Pressed: ctl_bTurnRight = 1; + Released: ctl_bTurnRight = 0; +Button + Name: TTRS Look Up + Key1: Mouse Button 4 + Key2: None + Pressed: ctl_bTurnUp = 1; + Released: ctl_bTurnUp = 0; +Button + Name: TTRS Look Down + Key1: Mouse Button 5 + Key2: None + Pressed: ctl_bTurnDown = 1; + Released: ctl_bTurnDown = 0; +Button + Name: TTRS Center View + Key1: Home + Key2: None + Pressed: ctl_bCenterView = 1; + Released: ctl_bCenterView = 0; +Button + Name: TTRS Walk + Key1: Left Shift + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ctl_bWalk = !ctl_bWalk; +Button + Name: TTRS Walk/Run Toggle + Key1: Caps Lock + Key2: None + Pressed: ctl_bWalk = !ctl_bWalk; + Released: ; +Button + Name: TTRS Strafe + Key1: None + Key2: None + Pressed: ctl_bStrafe = 1; + Released: ctl_bStrafe = 0; +Button + Name: TTRS Fire + Key1: Mouse Button 1 + Key2: Left Control + Pressed: ctl_bFire = 1; + Released: ctl_bFire = 0; +Button + Name: TTRS Reload + Key1: Left Alt + Key2: None + Pressed: ctl_bReload = 1; + Released: ctl_bReload = 0; +Button + Name: TTRS 3rd Person View + Key1: H + Key2: None + Pressed: ctl_b3rdPersonView = 1; + Released: ctl_b3rdPersonView = 0; +Button + Name: TTRS Use/Invoke NETRICSA/Sniper Zoom + Key1: Mouse Button 2 + Key2: Enter + Pressed: ctl_bUseOrComputer = 1; + Released: ctl_bUseOrComputer = 0; +Button + Name: TTRS Use/Sniper Zoom + Key1: None + Key2: None + Pressed: ctl_bUse = 1; + Released: ctl_bUse = 0; +Button + Name: TTRS Invoke NETRICSA + Key1: None + Key2: None + Pressed: ctl_bComputer = 1; + Released: ctl_bComputer = 0; +Button + Name: TTRS Talk + Key1: T + Key2: None + Pressed: con_bTalk=1; + Released: +Button + Name: TTRS Previous Weapon + Key1: Mouse Wheel Up + Key2: [ + Pressed: ctl_bWeaponPrev = 1; + Released: ctl_bWeaponPrev = 0; +Button + Name: TTRS Next Weapon + Key1: Mouse Wheel Down + Key2: ] + Pressed: ctl_bWeaponNext = 1; + Released: ctl_bWeaponNext = 0; +Button + Name: TTRS Flip Weapon + Key1: Mouse Button 3 + Key2: None + Pressed: ctl_bWeaponFlip = 1; + Released: ctl_bWeaponFlip = 0; +Button + Name: TTRS Knife/Chainsaw + Key1: 1 + Key2: None + Pressed: ctl_bSelectWeapon[1] = 1; + Released: ctl_bSelectWeapon[1] = 0; +Button + Name: TTRS Colt/Two Colts + Key1: 2 + Key2: None + Pressed: ctl_bSelectWeapon[2] = 1; + Released: ctl_bSelectWeapon[2] = 0; +Button + Name: TTRS Single/Double Shotgun + Key1: 3 + Key2: None + Pressed: ctl_bSelectWeapon[3] = 1; + Released: ctl_bSelectWeapon[3] = 0; +Button + Name: TTRS Tommygun/Minigun + Key1: 4 + Key2: None + Pressed: ctl_bSelectWeapon[4] = 1; + Released: ctl_bSelectWeapon[4] = 0; +Button + Name: TTRS Rocket Launcher/Grenade Launcher + Key1: 5 + Key2: None + Pressed: ctl_bSelectWeapon[5] = 1; + Released: ctl_bSelectWeapon[5] = 0; +Button + Name: TTRS Flamethrower/Sniper + Key1: 6 + Key2: None + Pressed: ctl_bSelectWeapon[6] = 1; + Released: ctl_bSelectWeapon[6] = 0; +Button + Name: TTRS Laser + Key1: 7 + Key2: None + Pressed: ctl_bSelectWeapon[7] = 1; + Released: ctl_bSelectWeapon[7] = 0; +Button + Name: TTRS Cannon + Key1: 8 + Key2: None + Pressed: ctl_bSelectWeapon[8] = 1; + Released: ctl_bSelectWeapon[8] = 0; +Button + Name: TTRS Serious Bomb + Key1: 0 + Key2: None + Pressed: ctl_bFireBomb = 1; + Released: ctl_bFireBomb = 0; +Button + Name: TTRS Strafe Left + Key1: Arrow Left + Key2: None + Pressed: ctl_bMoveLeft = 1; + Released: ctl_bMoveLeft = 0; +Button + Name: TTRS Strafe Right + Key1: Arrow Right + Key2: None + Pressed: ctl_bMoveRight = 1; + Released: ctl_bMoveRight = 0; +Button + Name: TTRS Sniper Zoom + + Key1: X + Key2: None + Pressed: ctl_bSniperZoomIn = 1; + Released: ctl_bSniperZoomIn = 0; +Button + Name: TTRS Sniper Zoom - + Key1: Z + Key2: None + Pressed: ctl_bSniperZoomOut = 1; + Released: ctl_bSniperZoomOut = 0; +Axis "move u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "move f/b" "None" 50 0 NotInverted Absolute NotSmooth +Axis "look u/d" "mouse Y" 50 0 NotInverted Relative NotSmooth +Axis "turn l/r" "mouse X" 50 0 NotInverted Relative NotSmooth +Axis "banking" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view u/d" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view l/r" "None" 50 0 NotInverted Absolute NotSmooth +Axis "view banking" "None" 50 0 NotInverted Absolute NotSmooth +GlobalDontInvertLook +GlobalSmoothAxes +GlobalSensitivity 50 diff --git a/Controls/System/Common.ctl b/Controls/System/Common.ctl new file mode 100644 index 0000000..ceb6a20 --- /dev/null +++ b/Controls/System/Common.ctl @@ -0,0 +1,202 @@ +Button + Name: TTRS Menu Save + Key1: F2 + Key2: None + Pressed: sam_bMenuSave=1; + Released: + +Button + Name: TTRS Menu Load + Key1: F3 + Key2: None + Pressed: sam_bMenuLoad=1; + Released: + +Button + Name: TTRS Menu Controls + Key1: F4 + Key2: None + Pressed: sam_bMenuControls=1; + Released: + +Button + Name: TTRS Quick Save + Key1: F6 + Key2: None + Pressed: gam_bQuickSave=1; + Released: + +Button + Name: TTRS Quick Load + Key1: F9 + Key2: None + Pressed: gam_bQuickLoad=1; + Released: + +Button + Name: TTRS Screenshot + Key1: F11 + Key2: None + Pressed: SaveScreenShot(); + Released: + +Button + Name: TTRS StartDemoRecording + Key1: F7 + Key2: None + Pressed: StartDemoRecording(); + Released: + +Button + Name: TTRS StopDemoRecording + Key1: F8 + Key2: None + Pressed: StopDemoRecording(); + Released: + + +Button + Name: TTRS Toggle frame rate + Key1: None + Key2: None + Pressed: hud_iStats=(hud_iStats+1)%3; + Released: + +Button + Name: TTRS Show elapsed time and/or crosshair coordinates + Key1: None + Key2: None + Pressed: extern FLOAT fTmp=hud_bShowTime*2+hud_bShowCoords; fTmp = (fTmp+1)%4; hud_bShowCoords=fTmp%2; hud_bShowTime=(fTmp-hud_bShowCoords)/2; + Released: + +Button + Name: TTRS Toggle Triangles + Key1: None + Key2: None + Pressed: wld_bShowTriangles=!wld_bShowTriangles; + Released: + +Button + Name: TTRS Breakpoint + Key1: None + Key2: None + Pressed: dbg_bBreak = 1; + Released: + + +Button + Name: TTRS Observe No Players + Key1: Num 0 + Key2: None + Pressed: gam_iObserverConfig=0; + Released: + +Button + Name: TTRS Observe 1 Player + Key1: Num 1 + Key2: None + Pressed: gam_iObserverConfig=1; + Released: + +Button + Name: TTRS Observe 2 Players + Key1: Num 2 + Key2: None + Pressed: gam_iObserverConfig=2; + Released: + +Button + Name: TTRS Observe 3 Players + Key1: Num 3 + Key2: None + Pressed: gam_iObserverConfig=3; + Released: + +Button + Name: TTRS Observe 4 Players + Key1: Num 4 + Key2: None + Pressed: gam_iObserverConfig=4; + Released: + +Button + Name: TTRS Observe Next + Key1: Num + + Key2: None + Pressed: gam_iObserverOffset=(gam_iObserverOffset+1)%16; + Released: + +Button + Name: TTRS Observe Prev + Key1: Num - + Key2: None + Pressed: gam_iObserverOffset=(gam_iObserverOffset+16-1)%16; + Released: + + +Button + Name: TTRS Demo FWD one tick + Key1: None + Key2: None + Pressed: dem_tmTimer=dem_tmTimer+0.05; + Released: + +Button + Name: TTRS Demo Jogg + Key1: None + Key2: None + Pressed: dem_fSyncRate=0.05; + Released: dem_fSyncRate=-1.0; + +Button + Name: TTRS Demo PLAY + Key1: None + Key2: None + Pressed: dem_fSyncRate=0.0; + Released: + +Button + Name: TTRS Demo PAUSE + Key1: None + Key2: None + Pressed: dem_fSyncRate=-1.0; + Released: + +Button + Name: TTRS Demo Toggle OSD + Key1: None + Key2: None + Pressed: dem_bOnScreenDisplay=!dem_bOnScreenDisplay; + Released: + + +Button + Name: TTRS Demo Fast + Key1: None + Key2: None + Pressed: dem_fRealTimeFactor=4.0f; + Released: dem_fRealTimeFactor=1.0f; + +Button + Name: TTRS Demo Super Fast + Key1: ' + Key2: None + Pressed: dem_fRealTimeFactor=16.0f; + Released: dem_fRealTimeFactor=1.0f; + + + +Button + Name: TTRS Time slower + Key1: None + Key2: None + Pressed: gam_fRealTimeFactor = gam_fRealTimeFactor / 2; + Released: + +Button + Name: TTRS Time faster + Key1: None + Key2: None + Pressed: gam_fRealTimeFactor = gam_fRealTimeFactor * 2; + Released: + diff --git a/Data/Default.ifr b/Data/Default.ifr new file mode 100644 index 0000000..f1447f3 Binary files /dev/null and b/Data/Default.ifr differ diff --git a/Data/Defaults/WorldEditor.reg b/Data/Defaults/WorldEditor.reg new file mode 100644 index 0000000..2fb407c --- /dev/null +++ b/Data/Defaults/WorldEditor.reg @@ -0,0 +1,233 @@ +REGEDIT4 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor] + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General] +"Browser width"=dword:000000a2 +"Browser height"=dword:00000158 +"Property width"=dword:000000a2 +"Property height"=dword:0000007e + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar0] +"BarID"=dword:0000e800 +"XPos"=dword:fffffffe +"YPos"=dword:fffffffe +"MRUWidth"=dword:000000c4 +"Docking"=dword:00000001 +"MRUDockID"=dword:0000e81b +"MRUDockLeftPos"=dword:fffffffe +"MRUDockTopPos"=dword:fffffffe +"MRUDockRightPos"=dword:000000cd +"MRUDockBottomPos"=dword:00000018 +"MRUFloatStyle"=dword:00002000 +"MRUFloatXPos"=dword:000000be +"MRUFloatYPos"=dword:00000118 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar1] +"BarID"=dword:0000e803 +"XPos"=dword:0000014f +"YPos"=dword:0000002e +"MRUWidth"=dword:00000073 +"Docking"=dword:00000001 +"MRUDockID"=dword:0000e81b +"MRUDockLeftPos"=dword:0000014f +"MRUDockTopPos"=dword:0000002e +"MRUDockRightPos"=dword:00000229 +"MRUDockBottomPos"=dword:00000048 +"MRUFloatStyle"=dword:00002000 +"MRUFloatXPos"=dword:000000d9 +"MRUFloatYPos"=dword:00000118 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar10] +"BarID"=dword:0000e808 +"XPos"=dword:fffffffe +"YPos"=dword:0000007a +"Docking"=dword:00000001 +"MRUDockID"=dword:0000e81c +"MRUDockLeftPos"=dword:fffffffe +"MRUDockTopPos"=dword:0000007a +"MRUDockRightPos"=dword:000000a0 +"MRUDockBottomPos"=dword:000001d2 +"MRUFloatStyle"=dword:00002000 +"MRUFloatXPos"=dword:000000ac +"MRUFloatYPos"=dword:00000063 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar11] +"BarID"=dword:0000e809 +"XPos"=dword:fffffffe +"YPos"=dword:fffffffe +"Docking"=dword:00000001 +"MRUDockID"=dword:0000e81c +"MRUDockLeftPos"=dword:fffffffe +"MRUDockTopPos"=dword:fffffffe +"MRUDockRightPos"=dword:000000a0 +"MRUDockBottomPos"=dword:0000007c +"MRUFloatStyle"=dword:00002000 +"MRUFloatXPos"=dword:000000e5 +"MRUFloatYPos"=dword:00000062 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar12] +"BarID"=dword:0000e81b +"Bars"=dword:0000000d +"Bar#0"=dword:00000000 +"Bar#1"=dword:0000e800 +"Bar#2"=dword:0000e805 +"Bar#3"=dword:0000e80b +"Bar#4"=dword:0000e806 +"Bar#5"=dword:00000000 +"Bar#6"=dword:0000e802 +"Bar#7"=dword:0000e80a +"Bar#8"=dword:00000000 +"Bar#9"=dword:0000e804 +"Bar#10"=dword:0000e803 +"Bar#11"=dword:0000e807 +"Bar#12"=dword:00000000 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar13] +"BarID"=dword:0000e81c +"Bars"=dword:00000004 +"Bar#0"=dword:00000000 +"Bar#1"=dword:0000e809 +"Bar#2"=dword:0000e808 +"Bar#3"=dword:00000000 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar15] +"BarID"=dword:0000e81f +"Horz"=dword:00000001 +"Floating"=dword:00000001 +"XPos"=dword:000000dc +"YPos"=dword:00000127 +"Bars"=dword:00000003 +"Bar#0"=dword:00000000 +"Bar#1"=dword:0000e803 +"Bar#2"=dword:00000000 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar16] +"BarID"=dword:0000e81f +"Horz"=dword:00000001 +"Floating"=dword:00000001 +"XPos"=dword:000000c8 +"YPos"=dword:000000ec +"Bars"=dword:00000003 +"Bar#0"=dword:00000000 +"Bar#1"=dword:0000e804 +"Bar#2"=dword:00000000 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar17] +"BarID"=dword:0000e81f +"Horz"=dword:00000001 +"Floating"=dword:00000001 +"XPos"=dword:000000b0 +"YPos"=dword:00000077 +"Bars"=dword:00000003 +"Bar#0"=dword:00000000 +"Bar#1"=dword:0000e808 +"Bar#2"=dword:00000000 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar2] +"BarID"=dword:0000e801 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar3] +"BarID"=dword:0000e802 +"XPos"=dword:fffffffe +"YPos"=dword:00000016 +"Docking"=dword:00000001 +"MRUDockID"=dword:0000e81b +"MRUDockLeftPos"=dword:fffffffe +"MRUDockTopPos"=dword:00000016 +"MRUDockRightPos"=dword:00000264 +"MRUDockBottomPos"=dword:00000030 +"MRUFloatStyle"=dword:00002004 +"MRUFloatXPos"=dword:9c000000 +"MRUFloatYPos"=dword:d8c8c8c8 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar4] +"BarID"=dword:0000e807 +"XPos"=dword:00000227 +"YPos"=dword:0000002e +"MRUWidth"=dword:000000c4 +"Docking"=dword:00000001 +"MRUDockID"=dword:0000e81b +"MRUDockLeftPos"=dword:00000227 +"MRUDockTopPos"=dword:0000002e +"MRUDockRightPos"=dword:000002f6 +"MRUDockBottomPos"=dword:00000048 +"MRUFloatStyle"=dword:00002000 +"MRUFloatXPos"=dword:00000216 +"MRUFloatYPos"=dword:0000008e + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar5] +"BarID"=dword:0000e804 +"XPos"=dword:fffffffe +"YPos"=dword:0000002e +"MRUWidth"=dword:00000148 +"Docking"=dword:00000001 +"MRUDockID"=dword:0000e81b +"MRUDockLeftPos"=dword:fffffffe +"MRUDockTopPos"=dword:0000002e +"MRUDockRightPos"=dword:00000151 +"MRUDockBottomPos"=dword:00000048 +"MRUFloatStyle"=dword:00002000 +"MRUFloatXPos"=dword:000000c5 +"MRUFloatYPos"=dword:000000dc + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar6] +"BarID"=dword:0000e805 +"XPos"=dword:000000cb +"YPos"=dword:fffffffe +"Docking"=dword:00000001 +"MRUDockID"=dword:0000e81b +"MRUDockLeftPos"=dword:000000cb +"MRUDockTopPos"=dword:fffffffe +"MRUDockRightPos"=dword:0000011b +"MRUDockBottomPos"=dword:00000018 +"MRUFloatStyle"=dword:00002004 +"MRUFloatXPos"=dword:9c000000 +"MRUFloatYPos"=dword:d8c8c8c8 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar7] +"BarID"=dword:0000e80a +"XPos"=dword:00000262 +"YPos"=dword:00000016 +"Docking"=dword:00000001 +"MRUDockID"=dword:0000e81b +"MRUDockLeftPos"=dword:00000262 +"MRUDockTopPos"=dword:00000016 +"MRUDockRightPos"=dword:000002db +"MRUDockBottomPos"=dword:00000030 +"MRUFloatStyle"=dword:00002004 +"MRUFloatXPos"=dword:9c000000 +"MRUFloatYPos"=dword:d8c8c8c8 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar8] +"BarID"=dword:0000e80b +"XPos"=dword:00000119 +"YPos"=dword:fffffffe +"Docking"=dword:00000001 +"MRUDockID"=dword:0000e81b +"MRUDockLeftPos"=dword:00000119 +"MRUDockTopPos"=dword:fffffffe +"MRUDockRightPos"=dword:000001ae +"MRUDockBottomPos"=dword:00000018 +"MRUFloatStyle"=dword:00002004 +"MRUFloatXPos"=dword:9c000000 +"MRUFloatYPos"=dword:d8c8c8c8 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Bar9] +"BarID"=dword:0000e806 +"XPos"=dword:000001ac +"YPos"=dword:fffffffe +"Docking"=dword:00000001 +"MRUDockID"=dword:0000e81b +"MRUDockLeftPos"=dword:000001ac +"MRUDockTopPos"=dword:fffffffe +"MRUDockRightPos"=dword:000002e2 +"MRUDockBottomPos"=dword:00000018 +"MRUFloatStyle"=dword:00002004 +"MRUFloatXPos"=dword:9c000000 +"MRUFloatYPos"=dword:d8c8c8c8 + +[HKEY_CURRENT_USER\Software\CroTeam\WorldEditor\General-Summary] +"Bars"=dword:0000000e +"ScreenCX"=dword:00000320 +"ScreenCY"=dword:00000258 diff --git a/Data/IFeel.txt b/Data/IFeel.txt new file mode 100644 index 0000000..b359c27 --- /dev/null +++ b/Data/IFeel.txt @@ -0,0 +1,5 @@ +"Default" "Data\Default.ifr" +"HP Force Feedback Mouse" "Data\Default.ifr" +"Primax FX" "Data\Default.ifr" +"Logitech iFeel Mouse" "Data\Logitech.ifr" +"Nostromo n30 Game Mouse" "Data\Default.ifr" diff --git a/Data/Logitech.ifr b/Data/Logitech.ifr new file mode 100644 index 0000000..568d539 Binary files /dev/null and b/Data/Logitech.ifr differ diff --git a/Data/NoCRC.lst b/Data/NoCRC.lst new file mode 100644 index 0000000..6be376d --- /dev/null +++ b/Data/NoCRC.lst @@ -0,0 +1,10 @@ +*.dll +*.wav +*.des +*.txt +*.fnt +*.tex +*.lst +*.tbn +*.ogg +*.mp3 diff --git a/Data/SED_TipOfTheDay.txt b/Data/SED_TipOfTheDay.txt new file mode 100644 index 0000000..0b01676 --- /dev/null +++ b/Data/SED_TipOfTheDay.txt @@ -0,0 +1,57 @@ +Serious Editor is a very powerful tool, but you will need to get acustomized with its interface to be able to use it well. +It is recommended that you read at least the overview section in the help file and go through the tutorials before you start working. +$ +By pressing 'Q', you can toggle the tool window on or off manually. +$ +By pressing 'Z', you can toggle selection rendering (colored filters) on or off. +$ +Use DataTips! +In Info mode, you can point to an entity, polygon, or sector to view information about it. Info mode is toggled with 'I'. +This works on selections too. +$ +The 'A' key is used for aligning. It will align view to selected entities, polygons or sectors. In volume mode, it will align selection volume to the view. +$ +The character next to an entity property name shows its shortcut key. Press Shift and that key to quickly select that property. +$ +'Alt+Shift+A' selects parent entity property, 'Alt+Shift+S' selects spawn flags entity property. +$ +Press 'W' to view or set virtual directory keyboard shortcuts. +$ +'Ctrl+A' will select all entities in volume. In Primitive mode, it will align primitive to view. +$ +You can remember two view positions in world by pressing 'Ctrl+Home' or 'Ctrl+End'. To jump to the remembered positions, press 'Home' or 'End'. +$ +'Tab'/'Shift+Tab' rotates an entity or polygon texture by 90 degrees in current view. Use 'Left Arrow'/'Right Arrow' to rotate by 15 degrees. +$ +Press 'N' or 'Ctrl+Shift+A' to browse all entities in current selection, current volume, or entire world by their names, classes, descriptions and positions. +$ +Use '[' and ']' keys or mouse wheel to circle through selected polygons or entities in current volume. +You can browse through custom selection of entities by pressing 'Feed to Volume' in the Entity Browser dialog (invoked by 'N' or 'Ctrl+Shift+A' ). +$ +By pressing the tilde key ('~'), you deselect current selection (polygons, sectors or entities, depending on the current mode). +If you press that key twice quickly (double-click it), all selections are deselected (polygons, sectors and entities). +$ +Pressing 'Alt+~' maximizes the view under mouse pointer to entire window, or restores the window configuration back. +$ +Undo buffer remembers each CSG operation as one Undo/Redo step. In Preferences, you can configure number of Undo/Redo steps remembered and select whether you want entity deletion to be remembered too. +$ +You can use 'Ctrl+W' to remember an Undo/Redo step manually while performing other tasks besides CSG, (for example when you are texturizing), so that you can Undo those actions too. +$ +Most operations like copying, mapping adjustment, etc. work on selection, or on the object you point to with the mouse. +For example, you can select a few polygons, point to some unselected polygon, copy properties from it, then point to the selection and paste the properties there. +$ +If you press 'Ctrl+C' in entity or sector mode, currently selected entities are copied. In none is selected, entire world is copied. +$ +To copy sectors without entities, press 'Ctrl+Shift+C'. +$ +You can paste entities from clipboard to second layer by 'Ctrl+Shift+V'. This way you can safely adjust their position as a group, without them beeing snapped to the grid. +$ +Use ','/'K' to copy/paste texture in current texture layer. +$ +'Ctrl+Shift+V' in polygon mode will paste all polygon properties except textures. +$ +Use 'M'/'J' to copy/paste mapping in current texture layer. +'U' will paste mapping projected from the original position that it was copied from. +$ +'Ctrl+Shift+V' in polygon mode will paste all polygon properties except textures. +$ \ No newline at end of file diff --git a/GameAgent/GameAgent.txt b/GameAgent/GameAgent.txt new file mode 100644 index 0000000..7206c6f --- /dev/null +++ b/GameAgent/GameAgent.txt @@ -0,0 +1,90 @@ +GameAgent is the replacement for gameserver management, such as the serverlist. + +The masterserver runs on master1.croteam.org on port 9005. + +Querying the masterserver can be done using UDP packets the following way: + + UDP Masterserver:9005 { + char 'e' + } + +This will make the masterserver respond with a list of servers currently joined and alive in the following way: + + UDP { + char 's' + 4 bytes of the IP (0x7F 0x00 0x00 0x01 would be 127.0.0.1) + short of the port + } + +To query gameservers for their current status, use their enumeration port (server port + 1): + + UDP Gameserver:25601 { + byte 0x02 + } + +An example response would be: + + UDP { + char '0' + string ";players;8" + string ";maxplayers;16" + string ";level;Yodeller" + string ";gametype;Fragmatch" + string ";version;1.10" + string ";gamename;serioussamse" + string ";sessionname;Awesome Server" + } + +Note: strings in this documentation are not null terminated unless pointed out otherwise. + +This particular server would be a fragmatch server called "Awesome Server", having 8 out of 16 players, playing on Yodeller running on version 1.10. + +To query a gameserver for the players, you would do the following: + + UDP Gameserver:25601 { + byte 0x03 + } + +An example response would be: + + UDP { + byte 0x01 + + "players" + byte 0x02 + "8" + byte 0x03 + + { // for each player + "player_0" + byte 0x02 + "Angelo" + byte 0x03 + + "frags_0" + byte 0x02 + "14" + byte 0x03 + + "ping_0" + byte 0x02 + "80" + byte 0x03 + } + + byte 0x04 + } + +Where "0" after the "player_" and "frags_" is the index of the player in the server, not a counter. + +Note: Players can be sent in multiple packets. Wait for the last 0x04 byte in a packet. + +The player querying is done differently than the server status query to work around issues with seperator characters in player names. + +Some useful things to remember when working with this packet: + Byte 0x01 in ASCII is SOH; start of header. + Byte 0x02 in ASCII is STX; start of text. + Byte 0x03 in ASCII is ETX; end of text. + Byte 0x04 in ASCII IS EOT; end of transmission. + +Invalid player names are indicated by either byte 0x11 or 0x12 as the player name (in "player_0"). \ No newline at end of file diff --git a/GameAgent/main.py b/GameAgent/main.py new file mode 100644 index 0000000..cfb2433 --- /dev/null +++ b/GameAgent/main.py @@ -0,0 +1,107 @@ +#!/usr/bin/python -u + +# GameAgent +import socket +import random +import struct +import time +import re + +# global user/server arrays +servers = {} +players = {} + +# load user thread +execfile("user.py") +execfile("server.py") + +# listen on socket +sockListen = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +sockListen.bind(("0.0.0.0", 9005)) +print("Listening on UDP port 9005.") + +def sendto(data, addr): + sockListen.sendto(data, addr) + +# format address +def fmta(addr): + return addr[0] + ":" + str(addr[1]) + +def server_join(data, addr): + if(servers.has_key(fmta(addr))): + print("Join request from server already joined!") + print("Server join from " + fmta(addr)) + s = Server() + s.addr = addr + s.join() + servers[fmta(addr)] = s + +def server_challengeresponse(data, addr): + if(servers.has_key(fmta(addr))): + servers[fmta(addr)].challengeresponse(data) + else: + # server didn't join yet, make server join + server_join(data, addr) + +def server_statechanged(data, addr): + if(servers.has_key(fmta(addr))): + if(servers[fmta(addr)].visible): + servers[fmta(addr)].statechanged(data) + else: + if(servers[fmta(addr)].prejoinactions > 5): + servers.pop(fmta(addr)) + print("Server sent too many pre join actions, removing!") + else: + servers[fmta(addr)].prejoinactions += 1 + else: + print("State change from server who didn't join yet!") + # server didn't join yet, make server join + server_join(data, addr) + +def enum_trigger(data, addr): + p = Player() + p.addr = addr + + buffer = "s" + topop = "" + for key in servers: + server = servers[key] + if(time.time() - server.lastheartbeat > 300): + # 5m have passed since last heartbeat + # server sends a heartbeat every 2.5 minutes + # we'll kick the server out because he's not doing this + print("Server " + fmta(server.addr) + " hasn't given a heartbeat since " + time.strftime("%c", time.gmtime(server.lastheartbeat)) + ", kicking!") + topop += key + "," + continue + if(not server.visible): + continue + if(len(buffer) + 6 > 1024): + sendto(buffer, addr) + buffer = "s" + parse = server.addr[0].split(".") + buffer += struct.pack("BBBBH", int(parse[0]), int(parse[1]), int(parse[2]), int(parse[3]), server.port) + sendto(buffer, addr) + for key in topop.split(","): + if(servers.has_key(key)): + servers.pop(key) + +# masterserver main loop +while True: + data, addr = sockListen.recvfrom(1024) + + packets = { + 'q': server_join, + '0': server_challengeresponse, + 'u': server_statechanged, + + 'e': enum_trigger, + } + + packetID = data[0] + if(packets.has_key(packetID)): + packets[packetID](data[1:], addr) + else: + print("Packet from " + addr[0] + " denied because of unknown packet " + str(ord(packetID))) + +# server died +print("Server shutting down.") diff --git a/GameAgent/run b/GameAgent/run new file mode 100644 index 0000000..07865e9 --- /dev/null +++ b/GameAgent/run @@ -0,0 +1,2 @@ +#!/bin/sh +python -u main.py \ No newline at end of file diff --git a/GameAgent/server.py b/GameAgent/server.py new file mode 100644 index 0000000..2bd97ef --- /dev/null +++ b/GameAgent/server.py @@ -0,0 +1,43 @@ +class Server: + def __init__(self): + self.challenge = 0 + self.addr = ("0.0.0.0", 0) + self.port = 25600 + self.prejoinactions = 0 + self.product = "" + self.params = {} + self.paramsallowed = "port;players;maxplayers;level;gametype;version" + self.visible = False + self.lastheartbeat = time.time() + + def join(self): + self.challenge = random.randint(0x00000000, 0x7FFFFFFF) + self.port = self.addr[1] - 1 + sendto("\1" + struct.pack("i", self.challenge), addr) + + def challengeresponse(self, data): + params = re.findall(";(\w+);([^;]*)", data) + valid = False + for param in params: + key = param[0] + val = param[1] + if(key == "challenge"): + if(val == str(self.challenge)): + valid = True + continue + if(key == "product"): + self.product = val + continue + try: + self.paramsallowed.split(";").index(key) + self.params[key] = val + except: + pass + if(not self.visible): + if(valid): + self.visible = True + else: + self.lastheartbeat = time.time() + + def statechanged(self, data): + print("state changed: " + data) \ No newline at end of file diff --git a/GameAgent/user.py b/GameAgent/user.py new file mode 100644 index 0000000..a00bb99 --- /dev/null +++ b/GameAgent/user.py @@ -0,0 +1,3 @@ +class Player: + def __init__(self): + self.addr = ("0.0.0.0", 0) \ No newline at end of file diff --git a/Help/seriouseditorcontext.hlk b/Help/seriouseditorcontext.hlk new file mode 100644 index 0000000..cbab9ca --- /dev/null +++ b/Help/seriouseditorcontext.hlk @@ -0,0 +1,2 @@ +CHM +Help\serious_editor_item_by_item.chm \ No newline at end of file diff --git a/ModEXT.txt b/ModEXT.txt new file mode 100644 index 0000000..a05adbd --- /dev/null +++ b/ModEXT.txt @@ -0,0 +1 @@ +MP \ No newline at end of file diff --git a/Players/about_this_directory.txt b/Players/about_this_directory.txt new file mode 100644 index 0000000..d84ce91 --- /dev/null +++ b/Players/about_this_directory.txt @@ -0,0 +1 @@ +Player files (Player0.plr, Player1.plr etc) are generated automatically in this folder. They are used for identification of players in multiplayer mode. You should not distribute .plr files together with any engine build because it might result in connection errors among network players. \ No newline at end of file diff --git a/SE1_10.gro b/SE1_10.gro new file mode 100644 index 0000000..52e2a83 Binary files /dev/null and b/SE1_10.gro differ diff --git a/Scripts/Dedicated_startup.ini b/Scripts/Dedicated_startup.ini new file mode 100644 index 0000000..6df78e1 --- /dev/null +++ b/Scripts/Dedicated_startup.ini @@ -0,0 +1,38 @@ +// startup script for dedicated server + +// make all textures and shadows as low quality as possible - this effectively makes it take almost no memory +tex_iNormalQuality=11; +tex_iAnimationQuality=11; +tex_fNormalSize=1; +tex_fAnimationSize=1; +tex_fEffectSize=1; +tex_fForceLowQuality=1; +tex_fForceHighQuality=0; +tex_bFineEffect=0; +shd_fStaticSize=1; +shd_fDynamicSize=1; +shd_bFineQuality=0; +shd_bCacheAll=0; + +// here we put extra settings for GameSpy that users will be able to see in their browsers +// it is best that you fill-in this info, so users can see what they are connecting to +// example would be: +// gam_strGameSpyExtras = "\\dedicatedserver\\yes\\system\\PIII@500/512MB/Win2k\\connection\\T1\\admin\\sam@hotmail.com"; +// just take care to format those backslashes right and always add the settings in pairs key-value + +gam_strGameSpyExtras = "\\dedicatedserver\\yes\\connection\\\\admin\\"; + + +// if you are running on a multihomed computer, you'll have to +// setup the ip on which you want the server to be visible here, +// in this syntax: +// net_strLocalHost = "server.ip.goes.here"; + +// also, you might want to manually setup your location description, +// so that people know how far your server is from them +// if you don't set it up, it will automatically read your country code +// from locale settings in Windows, but you might want to put exact +// country and city where you are +// here is an example: +// net_strLocationCode="Zagreb, Croatia"; + diff --git a/Scripts/NetSettings/56-normal.des b/Scripts/NetSettings/56-normal.des new file mode 100644 index 0000000..731cd2d --- /dev/null +++ b/Scripts/NetSettings/56-normal.des @@ -0,0 +1,2 @@ +56k modem - average connection +if you have 56k modem and the connection is average \ No newline at end of file diff --git a/Scripts/NetSettings/56-normal.ini b/Scripts/NetSettings/56-normal.ini new file mode 100644 index 0000000..19b5d66 --- /dev/null +++ b/Scripts/NetSettings/56-normal.ini @@ -0,0 +1,4 @@ +cli_bPrediction = 1; +cli_iBufferActions = 5; +cli_iMinBPS = 3000; +cli_iMaxBPS = 5000; diff --git a/Scripts/NetSettings/56k-quality.des b/Scripts/NetSettings/56k-quality.des new file mode 100644 index 0000000..30cedad --- /dev/null +++ b/Scripts/NetSettings/56k-quality.des @@ -0,0 +1,2 @@ +56k modem - high quality connection +if you have 56k modem and the connection is above average \ No newline at end of file diff --git a/Scripts/NetSettings/56k-quality.ini b/Scripts/NetSettings/56k-quality.ini new file mode 100644 index 0000000..5ce0169 --- /dev/null +++ b/Scripts/NetSettings/56k-quality.ini @@ -0,0 +1,4 @@ +cli_bPrediction = 1; +cli_iBufferActions = 3; +cli_iMinBPS = 3000; +cli_iMaxBPS = 5000; diff --git a/Scripts/NetSettings/DSLCable.des b/Scripts/NetSettings/DSLCable.des new file mode 100644 index 0000000..027a761 --- /dev/null +++ b/Scripts/NetSettings/DSLCable.des @@ -0,0 +1,2 @@ +xDSL or Cable modem +if you have any kind of DSL or cable modem \ No newline at end of file diff --git a/Scripts/NetSettings/DSLCable.ini b/Scripts/NetSettings/DSLCable.ini new file mode 100644 index 0000000..5358b20 --- /dev/null +++ b/Scripts/NetSettings/DSLCable.ini @@ -0,0 +1,4 @@ +cli_bPrediction = 1; +cli_iBufferActions = 2; +cli_iMinBPS = 6000; +cli_iMaxBPS = 10000; diff --git a/Scripts/NetSettings/ISDN.des b/Scripts/NetSettings/ISDN.des new file mode 100644 index 0000000..b2cd578 --- /dev/null +++ b/Scripts/NetSettings/ISDN.des @@ -0,0 +1,2 @@ +ISDN +if you have an ISDN link \ No newline at end of file diff --git a/Scripts/NetSettings/ISDN.ini b/Scripts/NetSettings/ISDN.ini new file mode 100644 index 0000000..3ccef41 --- /dev/null +++ b/Scripts/NetSettings/ISDN.ini @@ -0,0 +1,4 @@ +cli_bPrediction = 1; +cli_iBufferActions = 2; +cli_iMinBPS = 5000; +cli_iMaxBPS = 10000; diff --git a/Scripts/NetSettings/LAN.des b/Scripts/NetSettings/LAN.des new file mode 100644 index 0000000..567f1b7 --- /dev/null +++ b/Scripts/NetSettings/LAN.des @@ -0,0 +1,2 @@ +LAN gaming +use this when playing in LAN \ No newline at end of file diff --git a/Scripts/NetSettings/LAN.ini b/Scripts/NetSettings/LAN.ini new file mode 100644 index 0000000..5a2f713 --- /dev/null +++ b/Scripts/NetSettings/LAN.ini @@ -0,0 +1,4 @@ +cli_bPrediction = 0; // turn off prediction +cli_iBufferActions = 1; // no buffering == maximum responsiveness +cli_iMinBPS = 6000; +cli_iMaxBPS = 100000; diff --git a/Scripts/NetSettings/OldModem.des b/Scripts/NetSettings/OldModem.des new file mode 100644 index 0000000..f56fe49 --- /dev/null +++ b/Scripts/NetSettings/OldModem.des @@ -0,0 +1,2 @@ +33.6k modem or older +if you have a old modem, slower than 56k \ No newline at end of file diff --git a/Scripts/NetSettings/OldModem.ini b/Scripts/NetSettings/OldModem.ini new file mode 100644 index 0000000..9b39fe5 --- /dev/null +++ b/Scripts/NetSettings/OldModem.ini @@ -0,0 +1,4 @@ +cli_bPrediction = 1; +cli_iBufferActions = 5; +cli_iMinBPS = 2500; +cli_iMaxBPS = 2500; diff --git a/Scripts/PersistentSymbols.ini b/Scripts/PersistentSymbols.ini new file mode 100644 index 0000000..d61e379 --- /dev/null +++ b/Scripts/PersistentSymbols.ini @@ -0,0 +1,443 @@ +// automatically saved persistent symbols: +persistent extern user INDEX con_iLastLines=(INDEX)5; +tmp_af[0]=(FLOAT)0; +tmp_af[1]=(FLOAT)0; +tmp_af[2]=(FLOAT)0; +tmp_af[3]=(FLOAT)0; +tmp_af[4]=(FLOAT)0; +tmp_af[5]=(FLOAT)0; +tmp_af[6]=(FLOAT)0; +tmp_af[7]=(FLOAT)0; +tmp_af[8]=(FLOAT)0; +tmp_af[9]=(FLOAT)0; +tmp_ai[0]=(INDEX)0; +tmp_ai[1]=(INDEX)0; +tmp_ai[2]=(INDEX)0; +tmp_ai[3]=(INDEX)0; +tmp_ai[4]=(INDEX)0; +tmp_ai[5]=(INDEX)0; +tmp_ai[6]=(INDEX)0; +tmp_ai[7]=(INDEX)0; +tmp_ai[8]=(INDEX)0; +tmp_ai[9]=(INDEX)0; +persistent extern user INDEX tmp_i=(INDEX)0; +persistent extern user FLOAT tmp_fAdd=(FLOAT)0; +persistent extern user INDEX fil_bPreferZips=(INDEX)0; +persistent extern user INDEX ogl_bUseCompiledVertexArrays=(INDEX)101; +persistent extern user INDEX ogl_bExclusive=(INDEX)1; +persistent extern user INDEX ogl_bAllowQuadArrays=(INDEX)0; +persistent extern user INDEX ogl_iTextureCompressionType=(INDEX)1; +persistent extern user INDEX ogl_iMaxBurstSize=(INDEX)0; +persistent extern user INDEX ogl_bGrabDepthBuffer=(INDEX)0; +persistent extern user INDEX ogl_iFinish=(INDEX)1; +persistent extern user INDEX ogl_iTBufferEffect=(INDEX)0; +persistent extern user INDEX ogl_iTBufferSamples=(INDEX)2; +persistent extern user INDEX ogl_bTruformLinearNormals=(INDEX)1; +persistent extern user INDEX ogl_bAlternateClipPlane=(INDEX)0; +persistent extern user INDEX d3d_bUseHardwareTnL=(INDEX)1; +persistent extern user INDEX d3d_iMaxBurstSize=(INDEX)0; +persistent extern user INDEX d3d_iVertexBuffersSize=(INDEX)1024; +persistent extern user INDEX d3d_iVertexRangeTreshold=(INDEX)99; +persistent extern user INDEX d3d_bAlternateDepthReads=(INDEX)0; +persistent extern INDEX d3d_bFastUpload=(INDEX)1; +persistent extern user INDEX d3d_iFinish=(INDEX)0; +persistent extern user INDEX gap_iUseTextureUnits=(INDEX)4; +persistent extern user INDEX gap_iTextureFiltering=(INDEX)21; +persistent extern user INDEX gap_iTextureAnisotropy=(INDEX)1; +persistent extern user FLOAT gap_fTextureLODBias=(FLOAT)0; +persistent extern user INDEX gap_bAllowGrayTextures=(INDEX)1; +persistent extern user INDEX gap_bAllowSingleMipmap=(INDEX)1; +persistent extern user INDEX gap_bOptimizeStateChanges=(INDEX)1; +persistent extern user INDEX gap_iOptimizeDepthReads=(INDEX)1; +persistent extern user INDEX gap_iOptimizeClipping=(INDEX)2; +persistent extern user INDEX gap_iSwapInterval=(INDEX)0; +persistent extern user INDEX gap_iRefreshRate=(INDEX)0; +persistent extern user INDEX gap_iDithering=(INDEX)2; +persistent extern user INDEX gap_bForceTruform=(INDEX)0; +persistent extern user INDEX gap_iTruformLevel=(INDEX)0; +persistent extern user INDEX gap_iDepthBits=(INDEX)0; +persistent extern user INDEX gap_iStencilBits=(INDEX)0; +persistent extern user FLOAT mdl_fLODMul=(FLOAT)1; +persistent extern user FLOAT mdl_fLODAdd=(FLOAT)0; +persistent extern user INDEX mdl_iLODDisappear=(INDEX)1; +persistent extern user INDEX mdl_bRenderDetail=(INDEX)1; +persistent extern user INDEX mdl_bRenderSpecular=(INDEX)1; +persistent extern user INDEX mdl_bRenderReflection=(INDEX)1; +persistent extern user INDEX mdl_bAllowOverbright=(INDEX)1; +persistent extern user INDEX mdl_bFineQuality=(INDEX)1; +persistent extern user INDEX mdl_iShadowQuality=(INDEX)1; +persistent extern user FLOAT ska_fLODMul=(FLOAT)1; +persistent extern user FLOAT ska_fLODAdd=(FLOAT)0; +persistent extern user FLOAT gfx_tmProbeDecay=(FLOAT)30; +persistent extern user INDEX gfx_iProbeSize=(INDEX)256; +persistent extern user INDEX gfx_bClearScreen=(INDEX)0; +persistent extern user INDEX gfx_bDisableMultiMonSupport=(INDEX)1; +persistent extern user INDEX gfx_bDisableWindowsKeys=(INDEX)1; +persistent extern user INDEX gfx_bDecoratedText=(INDEX)1; +persistent extern user INDEX tex_iNormalQuality=(INDEX)22; +persistent extern user INDEX tex_iAnimationQuality=(INDEX)11; +persistent extern user INDEX tex_bFineEffect=(INDEX)0; +persistent extern user INDEX tex_bFineFog=(INDEX)1; +persistent extern user INDEX tex_iNormalSize=(INDEX)9; +persistent extern user INDEX tex_iAnimationSize=(INDEX)7; +persistent extern user INDEX tex_iEffectSize=(INDEX)7; +persistent extern user INDEX tex_iFogSize=(INDEX)7; +persistent extern user INDEX tex_bCompressAlphaChannel=(INDEX)0; +persistent extern user INDEX tex_bAlternateCompression=(INDEX)0; +persistent extern user INDEX tex_bDynamicMipmaps=(INDEX)0; +persistent extern user INDEX tex_iDithering=(INDEX)3; +persistent extern user INDEX tex_iFiltering=(INDEX)0; +persistent extern user INDEX tex_iEffectFiltering=(INDEX)4; +persistent extern user INDEX tex_bProgressiveFilter=(INDEX)0; +persistent extern user INDEX shd_iStaticSize=(INDEX)8; +persistent extern user INDEX shd_iDynamicSize=(INDEX)8; +persistent extern user INDEX shd_bFineQuality=(INDEX)1; +persistent extern user INDEX shd_iAllowDynamic=(INDEX)1; +persistent extern user INDEX shd_bDynamicMipmaps=(INDEX)1; +persistent extern user INDEX shd_iFiltering=(INDEX)3; +persistent extern user INDEX shd_iDithering=(INDEX)1; +persistent extern user FLOAT shd_tmFlushDelay=(FLOAT)30; +persistent extern user FLOAT shd_fCacheSize=(FLOAT)8; +persistent extern user INDEX shd_bCacheAll=(INDEX)0; +persistent extern user INDEX shd_bAllowFlats=(INDEX)1; +persistent extern INDEX shd_iForceFlats=(INDEX)0; +persistent extern user INDEX gfx_iLensFlareQuality=(INDEX)3; +persistent extern user INDEX wld_bTextureLayers=(INDEX)111; +persistent extern user INDEX wld_bRenderMirrors=(INDEX)1; +persistent extern user FLOAT wld_fEdgeOffsetI=(FLOAT)0; +persistent extern user FLOAT wld_fEdgeAdjustK=(FLOAT)1; +persistent extern user INDEX wld_iDetailRemovingBias=(INDEX)3; +persistent extern user INDEX wed_bUseBaseForReplacement=(INDEX)0; +persistent extern user INDEX tex_iHueShift=(INDEX)0; +persistent extern user FLOAT tex_fSaturation=(FLOAT)1; +persistent extern user INDEX shd_iHueShift=(INDEX)0; +persistent extern user FLOAT shd_fSaturation=(FLOAT)1; +persistent extern user INDEX gfx_iHueShift=(INDEX)0; +persistent extern user FLOAT gfx_fSaturation=(FLOAT)1; +persistent extern user FLOAT gfx_fBrightness=(FLOAT)0; +persistent extern user FLOAT gfx_fContrast=(FLOAT)1; +persistent extern user FLOAT gfx_fGamma=(FLOAT)1; +persistent extern user FLOAT gfx_fBiasR=(FLOAT)1; +persistent extern user FLOAT gfx_fBiasG=(FLOAT)1; +persistent extern user FLOAT gfx_fBiasB=(FLOAT)1; +persistent extern user INDEX gfx_iLevels=(INDEX)256; +persistent extern user INDEX gfx_iStereo=(INDEX)0; +persistent extern user INDEX gfx_bStereoInvert=(INDEX)0; +persistent extern user INDEX gfx_iStereoOffset=(INDEX)10; +persistent extern user FLOAT gfx_fStereoSeparation=(FLOAT)0.25; +persistent extern user FLOAT snd_fEarsDistance=(FLOAT)0.2; +persistent extern user FLOAT snd_fDelaySoundSpeed=(FLOAT)1e+010; +persistent extern user FLOAT snd_fDopplerSoundSpeed=(FLOAT)330; +persistent extern user FLOAT snd_fPanStrength=(FLOAT)0.1; +persistent extern user FLOAT snd_fLRFilter=(FLOAT)3; +persistent extern user FLOAT snd_fBFilter=(FLOAT)5; +persistent extern user FLOAT snd_fUFilter=(FLOAT)1; +persistent extern user FLOAT snd_fDFilter=(FLOAT)3; +persistent extern user FLOAT snd_fSoundVolume=(FLOAT)1; +persistent extern user FLOAT snd_fMusicVolume=(FLOAT)1; +persistent extern user FLOAT snd_fNormalizer=(FLOAT)0.9; +persistent extern user FLOAT snd_tmMixAhead=(FLOAT)0.2; +persistent extern user INDEX snd_iInterface=(INDEX)1; +persistent extern user INDEX snd_iDevice=(INDEX)-1; +persistent extern user INDEX snd_iFormat=(INDEX)3; +persistent extern user INDEX snd_iMaxExtraChannels=(INDEX)32; +persistent extern user INDEX snd_iMaxOpenRetries=(INDEX)3; +persistent extern user FLOAT snd_tmOpenFailDelay=(FLOAT)0.5; +persistent extern user FLOAT snd_fEAXPanning=(FLOAT)0; +persistent extern user INDEX gam_bPretouch=(INDEX)0; +persistent extern user CTString cmd_cmdOnTick=""; +persistent extern user CTString cmd_cmdOnChat=""; +persistent extern user INDEX ent_bReportSpawnInWall=(INDEX)0; +persistent extern user FLOAT ser_tmSyncCheckFrequency=(FLOAT)1; +persistent extern user INDEX ser_iSyncCheckBuffer=(INDEX)60; +persistent extern user INDEX cli_bLerpActions=(INDEX)0; +persistent extern user INDEX cli_bReportPredicted=(INDEX)0; +persistent extern user INDEX net_iExactTimer=(INDEX)2; +persistent extern user CTString net_strLocalHost=""; +persistent extern user CTString net_strLocationCode=""; +persistent extern user INDEX ser_iExtensiveSyncCheck=(INDEX)0; +persistent extern user INDEX net_bLookupHostNames=(INDEX)0; +persistent extern user INDEX net_iCompression=(INDEX)1; +persistent extern user INDEX net_bReportPackets=(INDEX)0; +persistent extern user INDEX net_iMaxSendRetries=(INDEX)10; +persistent extern user FLOAT net_fSendRetryWait=(FLOAT)0.5; +persistent extern user INDEX net_bReportTraffic=(INDEX)0; +persistent extern user INDEX net_bReportICMPErrors=(INDEX)0; +persistent extern user INDEX net_bReportMiscErrors=(INDEX)0; +persistent extern user INDEX net_bLerping=(INDEX)1; +persistent extern user INDEX ser_bClientsMayPause=(INDEX)1; +persistent extern user INDEX ser_bEnumeration=(INDEX)1; +persistent extern user INDEX ser_bPingGameAgent=(INDEX)1; +persistent extern user FLOAT ser_tmKeepAlive=(FLOAT)0.1; +persistent extern user FLOAT ser_tmPingUpdate=(FLOAT)3; +persistent extern user INDEX ser_bWaitFirstPlayer=(INDEX)0; +persistent extern user INDEX ser_iMaxAllowedBPS=(INDEX)8000; +persistent extern user CTString ser_strIPMask=""; +persistent extern user CTString ser_strNameMask=""; +persistent extern user INDEX ser_bInverseBanning=(INDEX)0; +persistent extern user CTString ser_strMOTD=""; +persistent extern user INDEX cli_bAutoAdjustSettings=(INDEX)0; +persistent extern user FLOAT cli_tmAutoAdjustThreshold=(FLOAT)2; +persistent extern user INDEX cli_bPrediction=(INDEX)0; +persistent extern user INDEX cli_iMaxPredictionSteps=(INDEX)10; +persistent extern user INDEX cli_bPredictIfServer=(INDEX)0; +persistent extern user INDEX cli_bPredictLocalPlayers=(INDEX)1; +persistent extern user INDEX cli_bPredictRemotePlayers=(INDEX)0; +persistent extern user FLOAT cli_fPredictEntitiesRange=(FLOAT)20; +persistent extern user FLOAT cli_fPredictionFilter=(FLOAT)0.5; +persistent extern user INDEX cli_iSendBehind=(INDEX)3; +persistent extern user INDEX cli_iPredictionFlushing=(INDEX)1; +persistent extern user INDEX cli_iBufferActions=(INDEX)1; +persistent extern user INDEX cli_iMaxBPS=(INDEX)4000; +persistent extern user INDEX cli_iMinBPS=(INDEX)100; +persistent extern user INDEX net_iGraphBuffer=(INDEX)100; +persistent extern user INDEX gam_iPrecachePolicy=(INDEX)1; +persistent extern user INDEX inp_iKeyboardReadingMethod=(INDEX)2; +persistent extern user INDEX inp_bAllowMouseAcceleration=(INDEX)1; +persistent extern user FLOAT inp_fMouseSensitivity=(FLOAT)1; +persistent extern user INDEX inp_bMousePrecision=(INDEX)0; +persistent extern user FLOAT inp_fMousePrecisionFactor=(FLOAT)4; +persistent extern user FLOAT inp_fMousePrecisionThreshold=(FLOAT)10; +persistent extern user FLOAT inp_fMousePrecisionTimeout=(FLOAT)0.25; +persistent extern user INDEX inp_bInvertMouse=(INDEX)0; +persistent extern user INDEX inp_bFilterMouse=(INDEX)0; +persistent extern user INDEX inp_bAllowPrescan=(INDEX)1; +persistent extern user INDEX inp_i2ndMousePort=(INDEX)0; +persistent extern user INDEX inp_bInvert2ndMouse=(INDEX)0; +persistent extern user INDEX inp_bFilter2ndMouse=(INDEX)0; +persistent extern user FLOAT inp_f2ndMouseSensitivity=(FLOAT)1; +persistent extern user INDEX inp_b2ndMousePrecision=(INDEX)0; +persistent extern user FLOAT inp_f2ndMousePrecisionFactor=(FLOAT)4; +persistent extern user FLOAT inp_f2ndMousePrecisionThreshold=(FLOAT)10; +persistent extern user FLOAT inp_f2ndMousePrecisionTimeout=(FLOAT)0.25; +persistent extern user INDEX inp_bMsgDebugger=(INDEX)0; +persistent extern user INDEX inp_iMButton4Up=(INDEX)131072; +persistent extern user INDEX inp_iMButton4Dn=(INDEX)131136; +persistent extern user INDEX inp_iMButton5Up=(INDEX)65536; +persistent extern user INDEX inp_iMButton5Dn=(INDEX)65568; +persistent extern user INDEX inp_ctJoysticksAllowed=(INDEX)8; +persistent extern user INDEX inp_bForceJoystickPolling=(INDEX)0; +persistent extern user INDEX inp_bAutoDisableJoysticks=(INDEX)0; +persistent extern user INDEX wed_bUseGenericTextureReplacement=(INDEX)0; +persistent extern user FLOAT ctl_tmComputerDoubleClick=(FLOAT)0.5; +persistent extern user FLOAT ctl_fButtonRotationSpeedH=(FLOAT)300; +persistent extern user FLOAT ctl_fButtonRotationSpeedP=(FLOAT)150; +persistent extern user FLOAT ctl_fButtonRotationSpeedB=(FLOAT)150; +persistent extern user FLOAT ctl_fAxisStrafingModifier=(FLOAT)1; +persistent extern user FLOAT cli_fPredictPlayersRange=(FLOAT)0; +persistent extern user FLOAT cli_fPredictItemsRange=(FLOAT)3; +persistent extern user FLOAT cli_tmPredictFoe=(FLOAT)10; +persistent extern user FLOAT cli_tmPredictAlly=(FLOAT)10; +persistent extern user FLOAT cli_tmPredictEnemy=(FLOAT)10; +persistent extern user INDEX hud_bShowLatency=(INDEX)0; +persistent extern user INDEX hud_iShowPlayers=(INDEX)-1; +persistent extern user INDEX hud_iSortPlayers=(INDEX)-1; +persistent extern user INDEX hud_bShowWeapon=(INDEX)1; +persistent extern user INDEX hud_bShowMessages=(INDEX)1; +persistent extern user FLOAT hud_fScaling=(FLOAT)1; +persistent extern user FLOAT hud_fOpacity=(FLOAT)0.9; +persistent extern user FLOAT hud_tmWeaponsOnScreen=(FLOAT)3; +persistent extern user FLOAT hud_tmLatencySnapshot=(FLOAT)1; +persistent extern user FLOAT plr_fBreathingStrength=(FLOAT)0; +persistent extern user INDEX hud_bShowMatchInfo=(INDEX)1; +wpn_fRecoilSpeed[0]=(FLOAT)0; +wpn_fRecoilSpeed[1]=(FLOAT)0; +wpn_fRecoilSpeed[2]=(FLOAT)0; +wpn_fRecoilSpeed[3]=(FLOAT)0; +wpn_fRecoilSpeed[4]=(FLOAT)0; +wpn_fRecoilSpeed[5]=(FLOAT)0; +wpn_fRecoilSpeed[6]=(FLOAT)0; +wpn_fRecoilSpeed[7]=(FLOAT)0; +wpn_fRecoilSpeed[8]=(FLOAT)0; +wpn_fRecoilSpeed[9]=(FLOAT)0; +wpn_fRecoilSpeed[10]=(FLOAT)0; +wpn_fRecoilSpeed[11]=(FLOAT)0; +wpn_fRecoilSpeed[12]=(FLOAT)0; +wpn_fRecoilSpeed[13]=(FLOAT)0; +wpn_fRecoilSpeed[14]=(FLOAT)0; +wpn_fRecoilSpeed[15]=(FLOAT)0; +wpn_fRecoilSpeed[16]=(FLOAT)0; +wpn_fRecoilLimit[0]=(FLOAT)0; +wpn_fRecoilLimit[1]=(FLOAT)0; +wpn_fRecoilLimit[2]=(FLOAT)0; +wpn_fRecoilLimit[3]=(FLOAT)0; +wpn_fRecoilLimit[4]=(FLOAT)0; +wpn_fRecoilLimit[5]=(FLOAT)0; +wpn_fRecoilLimit[6]=(FLOAT)0; +wpn_fRecoilLimit[7]=(FLOAT)0; +wpn_fRecoilLimit[8]=(FLOAT)0; +wpn_fRecoilLimit[9]=(FLOAT)0; +wpn_fRecoilLimit[10]=(FLOAT)0; +wpn_fRecoilLimit[11]=(FLOAT)0; +wpn_fRecoilLimit[12]=(FLOAT)0; +wpn_fRecoilLimit[13]=(FLOAT)0; +wpn_fRecoilLimit[14]=(FLOAT)0; +wpn_fRecoilLimit[15]=(FLOAT)0; +wpn_fRecoilLimit[16]=(FLOAT)0; +wpn_fRecoilDampUp[0]=(FLOAT)0; +wpn_fRecoilDampUp[1]=(FLOAT)0; +wpn_fRecoilDampUp[2]=(FLOAT)0; +wpn_fRecoilDampUp[3]=(FLOAT)0; +wpn_fRecoilDampUp[4]=(FLOAT)0; +wpn_fRecoilDampUp[5]=(FLOAT)0; +wpn_fRecoilDampUp[6]=(FLOAT)0; +wpn_fRecoilDampUp[7]=(FLOAT)0; +wpn_fRecoilDampUp[8]=(FLOAT)0; +wpn_fRecoilDampUp[9]=(FLOAT)0; +wpn_fRecoilDampUp[10]=(FLOAT)0; +wpn_fRecoilDampUp[11]=(FLOAT)0; +wpn_fRecoilDampUp[12]=(FLOAT)0; +wpn_fRecoilDampUp[13]=(FLOAT)0; +wpn_fRecoilDampUp[14]=(FLOAT)0; +wpn_fRecoilDampUp[15]=(FLOAT)0; +wpn_fRecoilDampUp[16]=(FLOAT)0; +wpn_fRecoilDampDn[0]=(FLOAT)0; +wpn_fRecoilDampDn[1]=(FLOAT)0; +wpn_fRecoilDampDn[2]=(FLOAT)0; +wpn_fRecoilDampDn[3]=(FLOAT)0; +wpn_fRecoilDampDn[4]=(FLOAT)0; +wpn_fRecoilDampDn[5]=(FLOAT)0; +wpn_fRecoilDampDn[6]=(FLOAT)0; +wpn_fRecoilDampDn[7]=(FLOAT)0; +wpn_fRecoilDampDn[8]=(FLOAT)0; +wpn_fRecoilDampDn[9]=(FLOAT)0; +wpn_fRecoilDampDn[10]=(FLOAT)0; +wpn_fRecoilDampDn[11]=(FLOAT)0; +wpn_fRecoilDampDn[12]=(FLOAT)0; +wpn_fRecoilDampDn[13]=(FLOAT)0; +wpn_fRecoilDampDn[14]=(FLOAT)0; +wpn_fRecoilDampDn[15]=(FLOAT)0; +wpn_fRecoilDampDn[16]=(FLOAT)0; +wpn_fRecoilOffset[0]=(FLOAT)0; +wpn_fRecoilOffset[1]=(FLOAT)0; +wpn_fRecoilOffset[2]=(FLOAT)0; +wpn_fRecoilOffset[3]=(FLOAT)0; +wpn_fRecoilOffset[4]=(FLOAT)0; +wpn_fRecoilOffset[5]=(FLOAT)0; +wpn_fRecoilOffset[6]=(FLOAT)0; +wpn_fRecoilOffset[7]=(FLOAT)0; +wpn_fRecoilOffset[8]=(FLOAT)0; +wpn_fRecoilOffset[9]=(FLOAT)0; +wpn_fRecoilOffset[10]=(FLOAT)0; +wpn_fRecoilOffset[11]=(FLOAT)0; +wpn_fRecoilOffset[12]=(FLOAT)0; +wpn_fRecoilOffset[13]=(FLOAT)0; +wpn_fRecoilOffset[14]=(FLOAT)0; +wpn_fRecoilOffset[15]=(FLOAT)0; +wpn_fRecoilOffset[16]=(FLOAT)0; +wpn_fRecoilFactorP[0]=(FLOAT)0; +wpn_fRecoilFactorP[1]=(FLOAT)0; +wpn_fRecoilFactorP[2]=(FLOAT)0; +wpn_fRecoilFactorP[3]=(FLOAT)0; +wpn_fRecoilFactorP[4]=(FLOAT)0; +wpn_fRecoilFactorP[5]=(FLOAT)0; +wpn_fRecoilFactorP[6]=(FLOAT)0; +wpn_fRecoilFactorP[7]=(FLOAT)0; +wpn_fRecoilFactorP[8]=(FLOAT)0; +wpn_fRecoilFactorP[9]=(FLOAT)0; +wpn_fRecoilFactorP[10]=(FLOAT)0; +wpn_fRecoilFactorP[11]=(FLOAT)0; +wpn_fRecoilFactorP[12]=(FLOAT)0; +wpn_fRecoilFactorP[13]=(FLOAT)0; +wpn_fRecoilFactorP[14]=(FLOAT)0; +wpn_fRecoilFactorP[15]=(FLOAT)0; +wpn_fRecoilFactorP[16]=(FLOAT)0; +wpn_fRecoilFactorZ[0]=(FLOAT)0; +wpn_fRecoilFactorZ[1]=(FLOAT)0; +wpn_fRecoilFactorZ[2]=(FLOAT)0; +wpn_fRecoilFactorZ[3]=(FLOAT)0; +wpn_fRecoilFactorZ[4]=(FLOAT)0; +wpn_fRecoilFactorZ[5]=(FLOAT)0; +wpn_fRecoilFactorZ[6]=(FLOAT)0; +wpn_fRecoilFactorZ[7]=(FLOAT)0; +wpn_fRecoilFactorZ[8]=(FLOAT)0; +wpn_fRecoilFactorZ[9]=(FLOAT)0; +wpn_fRecoilFactorZ[10]=(FLOAT)0; +wpn_fRecoilFactorZ[11]=(FLOAT)0; +wpn_fRecoilFactorZ[12]=(FLOAT)0; +wpn_fRecoilFactorZ[13]=(FLOAT)0; +wpn_fRecoilFactorZ[14]=(FLOAT)0; +wpn_fRecoilFactorZ[15]=(FLOAT)0; +wpn_fRecoilFactorZ[16]=(FLOAT)0; +persistent extern user FLOAT plr_fFOV=(FLOAT)90; +persistent extern user FLOAT plr_fFrontClipDistance=(FLOAT)0.25; +persistent extern user INDEX plr_bRenderPicked=(INDEX)0; +persistent extern user INDEX plr_bRenderPickedParticles=(INDEX)0; +persistent extern user INDEX plr_bOnlySam=(INDEX)0; +persistent extern user INDEX ent_bReportBrokenChains=(INDEX)0; +persistent extern user FLOAT ent_tmMentalIn=(FLOAT)0.5; +persistent extern user FLOAT ent_tmMentalOut=(FLOAT)0.75; +persistent extern user FLOAT ent_tmMentalFade=(FLOAT)0.5; +persistent extern user FLOAT gfx_fEnvParticlesDensity=(FLOAT)1; +persistent extern user FLOAT gfx_fEnvParticlesRange=(FLOAT)1; +persistent extern user INDEX hud_bCrosshairFixed=(INDEX)0; +persistent extern user INDEX hud_bCrosshairColoring=(INDEX)1; +persistent extern user FLOAT hud_fCrosshairScale=(FLOAT)1; +persistent extern user FLOAT hud_fCrosshairRatio=(FLOAT)0.5; +persistent extern user FLOAT hud_fCrosshairOpacity=(FLOAT)1; +persistent extern user INDEX hud_bShowPlayerName=(INDEX)1; +persistent extern user INDEX hud_bShowCoords=(INDEX)0; +persistent extern user FLOAT plr_tmSnoopingTime=(FLOAT)1; +persistent extern user FLOAT plr_tmSnoopingDelay=(FLOAT)1; +persistent extern user FLOAT inp_fIFeelGain=(FLOAT)1; +persistent extern INDEX sam_bFullScreen=(INDEX)0; +persistent extern INDEX sam_iScreenSizeI=(INDEX)1024; +persistent extern INDEX sam_iScreenSizeJ=(INDEX)768; +persistent extern INDEX sam_iDisplayDepth=(INDEX)0; +persistent extern INDEX sam_iDisplayAdapter=(INDEX)0; +persistent extern INDEX sam_iGfxAPI=(INDEX)0; +persistent extern INDEX sam_bFirstStarted=(INDEX)0; +persistent extern INDEX sam_bAutoAdjustAudio=(INDEX)1; +persistent extern user INDEX sam_bWideScreen=(INDEX)0; +persistent extern user FLOAT sam_fPlayerOffset=(FLOAT)0; +persistent extern user INDEX sam_bAutoPlayDemos=(INDEX)1; +persistent extern user INDEX sam_iMaxFPSActive=(INDEX)500; +persistent extern user INDEX sam_iMaxFPSInactive=(INDEX)10; +persistent extern user INDEX sam_bPauseOnMinimize=(INDEX)1; +persistent extern user FLOAT sam_tmDisplayModeReport=(FLOAT)5; +persistent extern user CTString sam_strNetworkSettings=""; +persistent extern user CTString sam_strIntroLevel="Levels\\LevelsMP\\Intro.wld"; +persistent extern user CTString sam_strGameName="serioussamse"; +persistent extern INDEX sam_bShowAllLevels=(INDEX)0; +persistent extern INDEX sam_bMentalActivated=(INDEX)0; +persistent extern user INDEX sam_iVideoSetup=(INDEX)3; +persistent extern user INDEX hud_bShowTime=(INDEX)0; +persistent extern user INDEX hud_bShowClock=(INDEX)0; +persistent extern user INDEX dem_iProfileRate=(INDEX)5; +persistent extern user INDEX hud_bShowNetGraph=(INDEX)0; +persistent extern user FLOAT gam_fManaTransferFactor=(FLOAT)0.5; +persistent extern user FLOAT gam_fExtraEnemyStrength=(FLOAT)0; +persistent extern user FLOAT gam_fExtraEnemyStrengthPerPlayer=(FLOAT)0; +persistent extern user INDEX gam_iInitialMana=(INDEX)100; +persistent extern user INDEX gam_iScoreLimit=(INDEX)100000; +persistent extern user INDEX gam_iFragLimit=(INDEX)20; +persistent extern user INDEX gam_iTimeLimit=(INDEX)0; +persistent extern user INDEX gam_ctMaxPlayers=(INDEX)8; +persistent extern user INDEX gam_bWaitAllPlayers=(INDEX)0; +persistent extern user INDEX gam_bFriendlyFire=(INDEX)0; +persistent extern user INDEX gam_bPlayEntireGame=(INDEX)1; +persistent extern user INDEX gam_bWeaponsStay=(INDEX)1; +persistent extern user INDEX gam_bAmmoStays=(INDEX)1; +persistent extern user INDEX gam_bHealthArmorStays=(INDEX)1; +persistent extern user INDEX gam_bAllowHealth=(INDEX)1; +persistent extern user INDEX gam_bAllowArmor=(INDEX)1; +persistent extern user INDEX gam_bInfiniteAmmo=(INDEX)0; +persistent extern user INDEX gam_bRespawnInPlace=(INDEX)1; +persistent extern user INDEX gam_iCredits=(INDEX)-1; +persistent extern user FLOAT gam_tmSpawnInvulnerability=(FLOAT)3; +persistent extern user INDEX gam_iBlood=(INDEX)2; +persistent extern user INDEX gam_bGibs=(INDEX)1; +persistent extern user INDEX gam_bUseExtraEnemies=(INDEX)1; +persistent extern user INDEX gam_iStartDifficulty=(INDEX)1; +persistent extern user INDEX gam_iStartMode=(INDEX)-1; +persistent extern user CTString gam_strGameAgentExtras=""; +persistent extern user CTString gam_strCustomLevel=""; +persistent extern user CTString gam_strSessionName="Unnamed session"; +persistent extern user CTString gam_strJoinAddress="serveraddress"; +persistent extern user INDEX gam_bEnableAdvancedObserving=(INDEX)0; +persistent extern user FLOAT con_fHeightFactor=(FLOAT)0.5; +persistent extern user FLOAT con_tmLastLines=(FLOAT)5; +persistent extern user INDEX wed_iMaxFPSActive=(INDEX)500; +persistent extern user FLOAT wed_fFrontClipDistance=(FLOAT)0.5; +persistent extern CTString sam_strLastRenderer="none"; +persistent extern INDEX sam_iLastSetup=(INDEX)1; diff --git a/Scripts/menu/ApplyShadowmaps.ini b/Scripts/menu/ApplyShadowmaps.ini new file mode 100644 index 0000000..30df6d7 --- /dev/null +++ b/Scripts/menu/ApplyShadowmaps.ini @@ -0,0 +1,2 @@ +sam_iVideoSetup=3; +RecacheShadows(); diff --git a/Scripts/menu/ApplyTextures.ini b/Scripts/menu/ApplyTextures.ini new file mode 100644 index 0000000..f60e548 --- /dev/null +++ b/Scripts/menu/ApplyTextures.ini @@ -0,0 +1,2 @@ +sam_iVideoSetup=3; +RefreshTextures(); diff --git a/Scripts/menu/ApplyVideo.ini b/Scripts/menu/ApplyVideo.ini new file mode 100644 index 0000000..46a5f15 --- /dev/null +++ b/Scripts/menu/ApplyVideo.ini @@ -0,0 +1 @@ +ApplyVideoMode(); diff --git a/Scripts/menu/GameOptions.cfg b/Scripts/menu/GameOptions.cfg new file mode 100644 index 0000000..188489a --- /dev/null +++ b/Scripts/menu/GameOptions.cfg @@ -0,0 +1,271 @@ + +// +Gadget: TTRS Deathmatch options +Type: Separator +// +Gadget: +Type: Separator + + +// +Gadget: TTRS Time limit +Tip: TTRS game length (minutes) +Type: Toggle +Var: gam_iTimeLimit + +String: TTRS None +Value: 0 +String: 1 +Value: 1 +String: 2 +Value: 2 +String: 5 +Value: 5 +String: 10 +Value: 10 +String: 15 +Value: 15 +String: 20 +Value: 20 +String: 30 +Value: 30 +String: 45 +Value: 45 +String: 60 +Value: 60 +String: 90 +Value: 90 +String: 120 +Value: 120 + +// +Gadget: TTRS Kill limit +Tip: TTRS for Deathmatch only +Type: Toggle +Var: gam_iFragLimit + +String: TTRS None +Value: 0 +String: 5 +Value: 5 +String: 10 +Value: 10 +String: 15 +Value: 15 +String: 20 +Value: 20 +String: 25 +Value: 25 +String: 30 +Value: 30 +String: 40 +Value: 40 +String: 50 +Value: 50 +String: 75 +Value: 75 +String: 100 +Value: 100 + +// +Gadget: TTRS Allow health +Tip: TTRS enable/disable health items +Type: Toggle +Var: gam_bAllowHealth + +String: TTRS No +Value: 0 +String: TTRS Yes +Value: 1 + + +// +Gadget: +Type: Separator +// +Gadget: TTRS Cooperative options +Type: Separator +// +Gadget: +Type: Separator + + +// +Gadget: TTRS Weapons stay +Type: Toggle +Tip: TTRS whether weapons disappear after picking +Var: gam_bWeaponsStay + +String: TTRS No +Value: 0 +String: TTRS Yes +Value: 1 + +// +Gadget: TTRS Ammo stays +Tip: TTRS whether ammo disappears after picking +Type: Toggle +Var: gam_bAmmoStays + +String: TTRS No +Value: 0 +String: TTRS Yes +Value: 1 + +// +Gadget: TTRS Health/armor stays +Tip: TTRS whether health and armor disappears after picking +Type: Toggle +Var: gam_bHealthArmorStays + +String: TTRS No +Value: 0 +String: TTRS Yes +Value: 1 + +// +Gadget: TTRS Friendly fire +Type: Toggle +Tip: TTRS enable/disable damaging of other players +Var: gam_bFriendlyFire + +String: TTRS Off +Value: 0 +String: TTRS On +Value: 1 + +// +Gadget: TTRS Extra enemy strength +Type: Toggle +Tip: TTRS make enemies tougher by given percentage +Var: gam_fExtraEnemyStrength + +String: TTRS None +Value: 0 +String: 25% +Value: 0.25 +String: 50% +Value: 0.5 +String: 75% +Value: 0.75 +String: 100% +Value: 1 +String: 150% +Value: 1.5 +String: 200% +Value: 2 +String: 300% +Value: 3 +String: 400% +Value: 4 + +// +Gadget: TTRS Enemy strength per player +Type: Toggle +Tip: TTRS make enemies tougher as new players join +Var: gam_fExtraEnemyStrengthPerPlayer + +String: TTRS None +Value: 0 +String: 10% +Value: 0.1 +String: 20% +Value: 0.2 +String: 30% +Value: 0.3 +String: 50% +Value: 0.5 +String: 75% +Value: 0.75 +String: 100% +Value: 1 +String: 200% +Value: 2 + +// +Gadget: TTRS Play entire game +Tip: TTRS continue from level to level +Type: Toggle +Var: gam_bPlayEntireGame + +String: TTRS No +Value: 0 +String: TTRS Yes +Value: 1 + + +// +Gadget: +Type: Separator +// +Gadget: TTRS Common options +Type: Separator +// +Gadget: +Type: Separator + + +// +Gadget: TTRS Invulnerable after spawning (sec) +Tip: TTRS protect players from being killed immediately after appearing +Type: Toggle +Var: gam_tmSpawnInvulnerability + +String: TTRS None +Value: 0 +String: 1 +Value: 1 +String: 2 +Value: 2 +String: 3 +Value: 3 +String: 5 +Value: 5 + + +// +Gadget: TTRS Infinite ammo +Tip: TTRS if on, you don't need ammo to use weapons +Type: Toggle +Var: gam_bInfiniteAmmo + +String: TTRS No +Value: 0 +String: TTRS Yes +Value: 1 + +// +Gadget: TTRS Clients may pause +Tip: TTRS if off, only server may pause the game +Type: Toggle +Var: ser_bClientsMayPause + +String: TTRS No +Value: 0 +String: TTRS Yes +Value: 1 + + +// +Gadget: +Type: Separator +// +Gadget: TTRS Violence options +Type: Separator +// +Gadget: +Type: Separator + + +// +Gadget: TTRS Gibs +Type: Toggle +Tip: TTRS enable/disable gibbing of enemies and players +Var: gam_bGibs + +String: TTRS No +Value: 0 +String: TTRS Yes +Value: 1 + +MenuEnd diff --git a/Scripts/menu/RenderingOptions.cfg b/Scripts/menu/RenderingOptions.cfg new file mode 100644 index 0000000..266cb99 --- /dev/null +++ b/Scripts/menu/RenderingOptions.cfg @@ -0,0 +1,136 @@ + +// +Gadget: TTRS Texture size +Tip: TTRS set size for textures +Type: Toggle +Var: tex_iNormalSize +Schedule: TFNM scripts\menu\ApplyTextures.ini +Slider: Fill + +String: TTRS (tiny) +Value: 6.5 +String: TTRS (small) +Value: 7 +String: TTRS (normal) +Value: 8 +String: TTRS (large) +Value: 8.5 +String: TTRS (huge) +Value: 9 + + +// +Gadget: TTRS Texture quality +Tip: TTRS set quality for textures +Type: Toggle +Var: tex_iNormalQuality +Schedule: TFNM scripts\menu\ApplyTextures.ini +Filter: sys_bHas32bitTextures + +String: TTRS Optimal +Value: 0 +String: TTRS 16-bit +Value: 11 +String: TTRS 32-bit +Value: 22 +String: TTRS Compressed +Value: 33 + + +// +Gadget: TTRS Detail textures +Tip: TTRS enable/disable rendering of detail textures in world +Type: Toggle +Var: wld_bTextureLayers + +String: TTRS Disabled +Value: 110 +String: TTRS Enabled +Value: 111 + + +// +Gadget: TTRS Shadowmap size +Tip: TTRS set size of shadowmap textures in level +Type: Toggle +Var: shd_iStaticSize +Schedule: TFNM scripts\menu\ApplyShadowmaps.ini +Slider: Fill + +String: TTRS (tiny) +Value: 5 +String: TTRS (small) +Value: 6 +String: TTRS (normal) +Value: 7 +String: TTRS (large) +Value: 7.5 +String: TTRS (huge) +Value: 8 + + +// +Gadget: TTRS Lens flares +Tip: TTRS select type of rendering for lens flares +Type: Toggle +Var: gfx_iLensFlareQuality + +String: TTRS Disabled +Value: 0 +String: TTRS Simple +Value: 1 +String: TTRS Standard +Value: 3 + + +// +Gadget: TTRS Gamma correction +Tip: TTRS specify display gamma +Type: Toggle +Var: gfx_fGamma +Filter: sys_bHasAdjustableGamma +Slider: Ratio + +String: TTRS (dark) +Value: 0.2 +String: TTRS (dark) +Value: 0.5 +String: TTRS (dark) +Value: 0.8 +String: TTRS (normal) +Value: 1 +String: TTRS (bright) +Value: 1.1 +String: TTRS (bright) +Value: 1.3 +String: TTRS (bright) +Value: 1.5 + + +// +Gadget: TTRS Wait vertical retrace +Tip: TTRS synchronize frame change with monitor refresh rate +Type: Toggle +Var: gap_iSwapInterval +Filter: sys_bHasSwapInterval + +String: TTRS No +Value: 0 +String: TTRS Yes +Value: 1 + + +// +Gadget: TTRS Wide screen +Tip: TTRS enable/disable wide screen mode (4:3 or 16:9 ratio) +Type: Toggle +Var: sam_bWideScreen +Schedule: TFNM scripts\menu\ApplyVideo.ini + +String: TTRS Off +Value: 0 +String: TTRS On +Value: 1 + + +MenuEnd diff --git a/Scripts/menu/SPOptions.cfg b/Scripts/menu/SPOptions.cfg new file mode 100644 index 0000000..57b5b47 --- /dev/null +++ b/Scripts/menu/SPOptions.cfg @@ -0,0 +1,13 @@ +// +Gadget: TTRS Gibs +Type: Toggle +Tip: TTRS enable/disable gibbing of enemies and players +Var: gam_bGibs +InGame: No + +String: TTRS No +Value: 0 +String: TTRS Yes +Value: 1 + +MenuEnd diff --git a/Sources/All.sln b/Sources/All.sln new file mode 100644 index 0000000..f6f0e28 --- /dev/null +++ b/Sources/All.sln @@ -0,0 +1,206 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DecodeReport", "DecodeReport\DecodeReport.vcxproj", "{FF6F3C9B-689C-D26F-0563-9D12D6F6565B}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DedicatedServer", "DedicatedServer\DedicatedServer.vcxproj", "{072EF3A9-482A-79A5-D364-2ECDD95B8029}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10} = {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10} + {4410EEB1-AFAD-A936-2168-716C245D36D5} = {4410EEB1-AFAD-A936-2168-716C245D36D5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Depend", "Depend\Depend.vcxproj", "{8AE1F6E0-5806-D5E5-31B6-466EFE0290B3}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ecc", "Ecc\Ecc.vcxproj", "{1F46FD81-1A15-7E2C-7C68-84AB43BC0B05}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Engine", "Engine\Engine.vcxproj", "{4B6F587C-7C59-4481-FBB9-CA44380D0CBF}" + ProjectSection(ProjectDependencies) = postProject + {1F46FD81-1A15-7E2C-7C68-84AB43BC0B05} = {1F46FD81-1A15-7E2C-7C68-84AB43BC0B05} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EngineGUI", "EngineGUI\EngineGUI.vcxproj", "{870758F3-5C2F-D196-2A89-CC336EBE7779}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EntitiesMP", "EntitiesMP\EntitiesMP.vcxproj", "{D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + {1F46FD81-1A15-7E2C-7C68-84AB43BC0B05} = {1F46FD81-1A15-7E2C-7C68-84AB43BC0B05} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameGUIMP", "GameGUIMP\GameGUIMP.vcxproj", "{3EC2357F-FA36-9DF7-FFC4-AF9C03777DBE}" + ProjectSection(ProjectDependencies) = postProject + {4410EEB1-AFAD-A936-2168-716C245D36D5} = {4410EEB1-AFAD-A936-2168-716C245D36D5} + {870758F3-5C2F-D196-2A89-CC336EBE7779} = {870758F3-5C2F-D196-2A89-CC336EBE7779} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameMP", "GameMP\GameMP.vcxproj", "{4410EEB1-AFAD-A936-2168-716C245D36D5}" + ProjectSection(ProjectDependencies) = postProject + {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10} = {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "LWSkaExporter", "LWSkaExporter\LWSkaExporter.vcxproj", "{ACF94A1E-A365-0A7E-A849-CBA468D5EFCF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MakeFONT", "MakeFONT\MakeFONT.vcxproj", "{ABD12F55-02CD-418D-3393-CF6F09A415F2}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Modeler", "Modeler\Modeler.vcxproj", "{9E0BA4A5-61AD-9CF5-AC0D-50DAB6639605}" + ProjectSection(ProjectDependencies) = postProject + {870758F3-5C2F-D196-2A89-CC336EBE7779} = {870758F3-5C2F-D196-2A89-CC336EBE7779} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RCon", "RCon\RCon.vcxproj", "{BD59BFB2-B39D-6348-273D-48385E685C3D}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SeriousSam", "SeriousSam\SeriousSam.vcxproj", "{F0E01B8A-1C93-85CB-693E-B9CA24A27168}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10} = {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10} + {4410EEB1-AFAD-A936-2168-716C245D36D5} = {4410EEB1-AFAD-A936-2168-716C245D36D5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SeriousSkaStudio", "SeriousSkaStudio\SeriousSkaStudio.vcxproj", "{CC94A769-3B63-008D-0B03-525791C804D1}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + {AC040397-6FEA-E9B2-2B28-5BB08E1607A1} = {AC040397-6FEA-E9B2-2B28-5BB08E1607A1} + {870758F3-5C2F-D196-2A89-CC336EBE7779} = {870758F3-5C2F-D196-2A89-CC336EBE7779} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Shaders", "Shaders\Shaders.vcxproj", "{AC040397-6FEA-E9B2-2B28-5BB08E1607A1}" + ProjectSection(ProjectDependencies) = postProject + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} = {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WorldEditor", "WorldEditor\WorldEditor.vcxproj", "{DC47DA88-14E2-0634-61C5-7CEEC46A45C2}" + ProjectSection(ProjectDependencies) = postProject + {3EC2357F-FA36-9DF7-FFC4-AF9C03777DBE} = {3EC2357F-FA36-9DF7-FFC4-AF9C03777DBE} + {AC040397-6FEA-E9B2-2B28-5BB08E1607A1} = {AC040397-6FEA-E9B2-2B28-5BB08E1607A1} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Template|Win32 = Template|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FF6F3C9B-689C-D26F-0563-9D12D6F6565B}.Debug|Win32.ActiveCfg = Debug|Win32 + {FF6F3C9B-689C-D26F-0563-9D12D6F6565B}.Debug|Win32.Build.0 = Debug|Win32 + {FF6F3C9B-689C-D26F-0563-9D12D6F6565B}.Release|Win32.ActiveCfg = Release|Win32 + {FF6F3C9B-689C-D26F-0563-9D12D6F6565B}.Release|Win32.Build.0 = Release|Win32 + {FF6F3C9B-689C-D26F-0563-9D12D6F6565B}.Template|Win32.ActiveCfg = Template|Win32 + {FF6F3C9B-689C-D26F-0563-9D12D6F6565B}.Template|Win32.Build.0 = Template|Win32 + {072EF3A9-482A-79A5-D364-2ECDD95B8029}.Debug|Win32.ActiveCfg = Debug|Win32 + {072EF3A9-482A-79A5-D364-2ECDD95B8029}.Debug|Win32.Build.0 = Debug|Win32 + {072EF3A9-482A-79A5-D364-2ECDD95B8029}.Release|Win32.ActiveCfg = Release|Win32 + {072EF3A9-482A-79A5-D364-2ECDD95B8029}.Release|Win32.Build.0 = Release|Win32 + {072EF3A9-482A-79A5-D364-2ECDD95B8029}.Template|Win32.ActiveCfg = Template|Win32 + {072EF3A9-482A-79A5-D364-2ECDD95B8029}.Template|Win32.Build.0 = Template|Win32 + {8AE1F6E0-5806-D5E5-31B6-466EFE0290B3}.Debug|Win32.ActiveCfg = Debug|Win32 + {8AE1F6E0-5806-D5E5-31B6-466EFE0290B3}.Debug|Win32.Build.0 = Debug|Win32 + {8AE1F6E0-5806-D5E5-31B6-466EFE0290B3}.Release|Win32.ActiveCfg = Release|Win32 + {8AE1F6E0-5806-D5E5-31B6-466EFE0290B3}.Release|Win32.Build.0 = Release|Win32 + {8AE1F6E0-5806-D5E5-31B6-466EFE0290B3}.Template|Win32.ActiveCfg = Template|Win32 + {8AE1F6E0-5806-D5E5-31B6-466EFE0290B3}.Template|Win32.Build.0 = Template|Win32 + {1F46FD81-1A15-7E2C-7C68-84AB43BC0B05}.Debug|Win32.ActiveCfg = Debug|Win32 + {1F46FD81-1A15-7E2C-7C68-84AB43BC0B05}.Debug|Win32.Build.0 = Debug|Win32 + {1F46FD81-1A15-7E2C-7C68-84AB43BC0B05}.Release|Win32.ActiveCfg = Release|Win32 + {1F46FD81-1A15-7E2C-7C68-84AB43BC0B05}.Release|Win32.Build.0 = Release|Win32 + {1F46FD81-1A15-7E2C-7C68-84AB43BC0B05}.Template|Win32.ActiveCfg = Template|Win32 + {1F46FD81-1A15-7E2C-7C68-84AB43BC0B05}.Template|Win32.Build.0 = Template|Win32 + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF}.Debug|Win32.ActiveCfg = Debug|Win32 + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF}.Debug|Win32.Build.0 = Debug|Win32 + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF}.Release|Win32.ActiveCfg = Release|Win32 + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF}.Release|Win32.Build.0 = Release|Win32 + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF}.Template|Win32.ActiveCfg = Template|Win32 + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF}.Template|Win32.Build.0 = Template|Win32 + {870758F3-5C2F-D196-2A89-CC336EBE7779}.Debug|Win32.ActiveCfg = Debug|Win32 + {870758F3-5C2F-D196-2A89-CC336EBE7779}.Debug|Win32.Build.0 = Debug|Win32 + {870758F3-5C2F-D196-2A89-CC336EBE7779}.Release|Win32.ActiveCfg = Release|Win32 + {870758F3-5C2F-D196-2A89-CC336EBE7779}.Release|Win32.Build.0 = Release|Win32 + {870758F3-5C2F-D196-2A89-CC336EBE7779}.Template|Win32.ActiveCfg = Template|Win32 + {870758F3-5C2F-D196-2A89-CC336EBE7779}.Template|Win32.Build.0 = Template|Win32 + {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10}.Debug|Win32.ActiveCfg = Debug|Win32 + {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10}.Debug|Win32.Build.0 = Debug|Win32 + {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10}.Release|Win32.ActiveCfg = Release|Win32 + {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10}.Release|Win32.Build.0 = Release|Win32 + {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10}.Template|Win32.ActiveCfg = Template|Win32 + {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10}.Template|Win32.Build.0 = Template|Win32 + {3EC2357F-FA36-9DF7-FFC4-AF9C03777DBE}.Debug|Win32.ActiveCfg = Debug|Win32 + {3EC2357F-FA36-9DF7-FFC4-AF9C03777DBE}.Debug|Win32.Build.0 = Debug|Win32 + {3EC2357F-FA36-9DF7-FFC4-AF9C03777DBE}.Release|Win32.ActiveCfg = Release|Win32 + {3EC2357F-FA36-9DF7-FFC4-AF9C03777DBE}.Release|Win32.Build.0 = Release|Win32 + {3EC2357F-FA36-9DF7-FFC4-AF9C03777DBE}.Template|Win32.ActiveCfg = Template|Win32 + {3EC2357F-FA36-9DF7-FFC4-AF9C03777DBE}.Template|Win32.Build.0 = Template|Win32 + {4410EEB1-AFAD-A936-2168-716C245D36D5}.Debug|Win32.ActiveCfg = Debug|Win32 + {4410EEB1-AFAD-A936-2168-716C245D36D5}.Debug|Win32.Build.0 = Debug|Win32 + {4410EEB1-AFAD-A936-2168-716C245D36D5}.Release|Win32.ActiveCfg = Release|Win32 + {4410EEB1-AFAD-A936-2168-716C245D36D5}.Release|Win32.Build.0 = Release|Win32 + {4410EEB1-AFAD-A936-2168-716C245D36D5}.Template|Win32.ActiveCfg = Template|Win32 + {4410EEB1-AFAD-A936-2168-716C245D36D5}.Template|Win32.Build.0 = Template|Win32 + {ACF94A1E-A365-0A7E-A849-CBA468D5EFCF}.Debug|Win32.ActiveCfg = Debug|Win32 + {ACF94A1E-A365-0A7E-A849-CBA468D5EFCF}.Debug|Win32.Build.0 = Debug|Win32 + {ACF94A1E-A365-0A7E-A849-CBA468D5EFCF}.Release|Win32.ActiveCfg = Release|Win32 + {ACF94A1E-A365-0A7E-A849-CBA468D5EFCF}.Release|Win32.Build.0 = Release|Win32 + {ACF94A1E-A365-0A7E-A849-CBA468D5EFCF}.Template|Win32.ActiveCfg = Template|Win32 + {ACF94A1E-A365-0A7E-A849-CBA468D5EFCF}.Template|Win32.Build.0 = Template|Win32 + {ABD12F55-02CD-418D-3393-CF6F09A415F2}.Debug|Win32.ActiveCfg = Debug|Win32 + {ABD12F55-02CD-418D-3393-CF6F09A415F2}.Debug|Win32.Build.0 = Debug|Win32 + {ABD12F55-02CD-418D-3393-CF6F09A415F2}.Release|Win32.ActiveCfg = Release|Win32 + {ABD12F55-02CD-418D-3393-CF6F09A415F2}.Release|Win32.Build.0 = Release|Win32 + {ABD12F55-02CD-418D-3393-CF6F09A415F2}.Template|Win32.ActiveCfg = Template|Win32 + {ABD12F55-02CD-418D-3393-CF6F09A415F2}.Template|Win32.Build.0 = Template|Win32 + {9E0BA4A5-61AD-9CF5-AC0D-50DAB6639605}.Debug|Win32.ActiveCfg = Debug|Win32 + {9E0BA4A5-61AD-9CF5-AC0D-50DAB6639605}.Debug|Win32.Build.0 = Debug|Win32 + {9E0BA4A5-61AD-9CF5-AC0D-50DAB6639605}.Release|Win32.ActiveCfg = Release|Win32 + {9E0BA4A5-61AD-9CF5-AC0D-50DAB6639605}.Release|Win32.Build.0 = Release|Win32 + {9E0BA4A5-61AD-9CF5-AC0D-50DAB6639605}.Template|Win32.ActiveCfg = Template|Win32 + {9E0BA4A5-61AD-9CF5-AC0D-50DAB6639605}.Template|Win32.Build.0 = Template|Win32 + {BD59BFB2-B39D-6348-273D-48385E685C3D}.Debug|Win32.ActiveCfg = Debug|Win32 + {BD59BFB2-B39D-6348-273D-48385E685C3D}.Debug|Win32.Build.0 = Debug|Win32 + {BD59BFB2-B39D-6348-273D-48385E685C3D}.Release|Win32.ActiveCfg = Release|Win32 + {BD59BFB2-B39D-6348-273D-48385E685C3D}.Release|Win32.Build.0 = Release|Win32 + {BD59BFB2-B39D-6348-273D-48385E685C3D}.Template|Win32.ActiveCfg = Template|Win32 + {BD59BFB2-B39D-6348-273D-48385E685C3D}.Template|Win32.Build.0 = Template|Win32 + {F0E01B8A-1C93-85CB-693E-B9CA24A27168}.Debug|Win32.ActiveCfg = Debug|Win32 + {F0E01B8A-1C93-85CB-693E-B9CA24A27168}.Debug|Win32.Build.0 = Debug|Win32 + {F0E01B8A-1C93-85CB-693E-B9CA24A27168}.Release|Win32.ActiveCfg = Release|Win32 + {F0E01B8A-1C93-85CB-693E-B9CA24A27168}.Release|Win32.Build.0 = Release|Win32 + {F0E01B8A-1C93-85CB-693E-B9CA24A27168}.Template|Win32.ActiveCfg = Template|Win32 + {F0E01B8A-1C93-85CB-693E-B9CA24A27168}.Template|Win32.Build.0 = Template|Win32 + {CC94A769-3B63-008D-0B03-525791C804D1}.Debug|Win32.ActiveCfg = Debug|Win32 + {CC94A769-3B63-008D-0B03-525791C804D1}.Debug|Win32.Build.0 = Debug|Win32 + {CC94A769-3B63-008D-0B03-525791C804D1}.Release|Win32.ActiveCfg = Release|Win32 + {CC94A769-3B63-008D-0B03-525791C804D1}.Release|Win32.Build.0 = Release|Win32 + {CC94A769-3B63-008D-0B03-525791C804D1}.Template|Win32.ActiveCfg = Template|Win32 + {CC94A769-3B63-008D-0B03-525791C804D1}.Template|Win32.Build.0 = Template|Win32 + {AC040397-6FEA-E9B2-2B28-5BB08E1607A1}.Debug|Win32.ActiveCfg = Debug|Win32 + {AC040397-6FEA-E9B2-2B28-5BB08E1607A1}.Debug|Win32.Build.0 = Debug|Win32 + {AC040397-6FEA-E9B2-2B28-5BB08E1607A1}.Release|Win32.ActiveCfg = Release|Win32 + {AC040397-6FEA-E9B2-2B28-5BB08E1607A1}.Release|Win32.Build.0 = Release|Win32 + {AC040397-6FEA-E9B2-2B28-5BB08E1607A1}.Template|Win32.ActiveCfg = Template|Win32 + {AC040397-6FEA-E9B2-2B28-5BB08E1607A1}.Template|Win32.Build.0 = Template|Win32 + {DC47DA88-14E2-0634-61C5-7CEEC46A45C2}.Debug|Win32.ActiveCfg = Debug|Win32 + {DC47DA88-14E2-0634-61C5-7CEEC46A45C2}.Debug|Win32.Build.0 = Debug|Win32 + {DC47DA88-14E2-0634-61C5-7CEEC46A45C2}.Release|Win32.ActiveCfg = Release|Win32 + {DC47DA88-14E2-0634-61C5-7CEEC46A45C2}.Release|Win32.Build.0 = Release|Win32 + {DC47DA88-14E2-0634-61C5-7CEEC46A45C2}.Template|Win32.ActiveCfg = Template|Win32 + {DC47DA88-14E2-0634-61C5-7CEEC46A45C2}.Template|Win32.Build.0 = Template|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Sources/DecodeReport/DecodeReport.cpp b/Sources/DecodeReport/DecodeReport.cpp new file mode 100644 index 0000000..09e2569 --- /dev/null +++ b/Sources/DecodeReport/DecodeReport.cpp @@ -0,0 +1,137 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DecodeReport.cpp : Defines the entry point for the console application. +// + +#include "stdafx.h" + +void SubMain( int argc, char *argv[]); + +int main( int argc, char *argv[]) +{ + CTSTREAM_BEGIN { + SubMain(argc, argv); + } CTSTREAM_END; + return 0; +} + +void FindInMapFile(const CTFileName &fnSymbols, const CTString &strImage, ULONG ulSeg, ULONG ulOff, CTString &strFunction, SLONG &slDelta) +{ + CTFileName fnmImage = strImage; + CTFileName fnmMap = fnSymbols+fnmImage.FileName()+".map"; + strFunction = CTString(""; + + try { + CTFileStream strmMap; + strmMap.Open_t(fnmMap, CTStream::OM_READ); + // find beginning of functions in map file + for(;;) { + if (strmMap.AtEOF()) { + return; + } + // read the line + CTString strLine; + strmMap.GetLine_t(strLine); + if (strncmp(strLine, " Address", 9)==0) { + break; + } + } + + CTString strEmpty; + strmMap.GetLine_t(strEmpty); + + while (!strmMap.AtEOF()) { + // read the line + CTString strLine; + strmMap.GetLine_t(strLine); + char strFunctionLine[1024]; + strFunctionLine[0]=0; + ULONG ulSegLine=-1; + ULONG ulOfsLine=-1; + strLine.ScanF("%x:%x %s", &ulSegLine, &ulOfsLine, strFunctionLine); + if (ulSegLine!=ulSeg) { + continue; + } + if (ulOfsLine>ulOff) { + return; + } + strFunction = strFunctionLine; + slDelta = ulOff-ulOfsLine; + } + + } catch (char *strError) { + (void)strError; + return; + } +} + +void SubMain( int argc, char *argv[]) +{ + printf("\nDecodeReport - '.RPT' file decoder V1.0\n"); + printf( " (C)1999 CROTEAM Ltd\n\n"); + + if( argc!=3+1) + { + printf( "USAGE:\nDecodeReport \n"); + exit( EXIT_FAILURE); + } + + // initialize engine + SE_InitEngine(""); + _fnmApplicationPath = CTString(""); + + + CTFileName fnSrc = CTString(argv[1]); + CTFileName fnDst = CTString(argv[2]); + CTFileName fnSymbols = CTString(argv[3]); + + try + { + if (fnSrc==fnDst) { + throw "Use different files!"; + } + + CTFileStream strmSrc; + strmSrc.Open_t(fnSrc, CTStream::OM_READ); + CTFileStream strmDst; + strmDst.Create_t(fnDst); + + // while there is some line in src + while(!strmSrc.AtEOF()) { + // read the line + CTString strLine; + strmSrc.GetLine_t(strLine); + + // try to find address marker in it + const char *strAdr = strstr(strLine, "$adr:"); + // if there is no marker + if (strAdr==NULL) { + // just copy the line + strmDst.PutLine_t(strLine); + + // if there is marker + } else { + // parse the line + char strImage[1024]; + strImage[0]=0; + ULONG ulSegment=-1; + ULONG ulOffset=-1; + sscanf(strAdr, "$adr: %s %x:%x", strImage, &ulSegment, &ulOffset); + // find the function + CTString strFunction; + SLONG slDelta; + FindInMapFile(fnSymbols, CTString(strImage), ulSegment, ulOffset, strFunction, slDelta); + // out put the result + CTString strResult; + strResult.PrintF("%s (%s+0X%X)", strLine, strFunction, slDelta); + strmDst.PutLine_t(strResult); + } + } + } + catch(char *strError) + { + printf("\nError: %s\n", strError); + exit(EXIT_FAILURE); + } +} + diff --git a/Sources/DecodeReport/DecodeReport.vcxproj b/Sources/DecodeReport/DecodeReport.vcxproj new file mode 100644 index 0000000..b4696d0 --- /dev/null +++ b/Sources/DecodeReport/DecodeReport.vcxproj @@ -0,0 +1,179 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + + + MFCProj + {FF6F3C9B-689C-D26F-0563-9D12D6F6565B} + + + + Application + v120 + Unicode + + + Application + Dynamic + Unicode + v120 + + + Application + Dynamic + Unicode + v120 + + + + + + + + + + + + + + + + + + Debug\ + Debug\ + false + $(SolutionDir)..\Tools.Win32;$(SolutionDir)..\Bin\Debug;$(ExecutablePath) + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin\Debug;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + Release\ + Release\ + false + $(SolutionDir)..\Tools.Win32;$(SolutionDir)..\Bin;$(ExecutablePath) + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + WIN32;_DEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + Debug\ + .\Debug\DecodeReport.pch + Use + stdafx.h + Debug\ + Debug\ + EnableFastChecks + 4996;4333 + + + .\Debug\DecodeReport.tlb + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\DecodeReport.bsc + + + true + true + Console + Debug\DecodeReport.exe + true + + + copy Debug\$(TargetName).exe $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(SolutionDir)..\Bin\Debug\$(TargetName).exe + + + + + MultiThreadedDLL + OnlyExplicitInline + false + MaxSpeed + true + Level3 + Speed + true + false + true + WIN32;NDEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\DecodeReport.pch + Use + stdafx.h + Release\ + Release\ + 4996;4333 + + + .\Release\DecodeReport.tlb + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\DecodeReport.bsc + + + true + true + Console + Release\DecodeReport.exe + true + + + copy Release\$(TargetName).exe $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin + $(SolutionDir)..\Bin\$(TargetName).exe + + + + + + Create + stdafx.h + Create + stdafx.h + + + + + + + + + \ No newline at end of file diff --git a/Sources/DecodeReport/DecodeReport.vcxproj.filters b/Sources/DecodeReport/DecodeReport.vcxproj.filters new file mode 100644 index 0000000..80ac986 --- /dev/null +++ b/Sources/DecodeReport/DecodeReport.vcxproj.filters @@ -0,0 +1,30 @@ + + + + + {b72ef112-1822-4995-a4b2-ce6a2ebd5544} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {d354ff58-3d39-4727-a8d0-90bf71f4f976} + h;hpp;hxx;hm;inl + + + {25310c72-4b16-4223-b6ac-1c93f9823c29} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/Sources/DecodeReport/DecodeReport.vcxproj.user b/Sources/DecodeReport/DecodeReport.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/Sources/DecodeReport/DecodeReport.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Sources/DecodeReport/StdAfx.cpp b/Sources/DecodeReport/StdAfx.cpp new file mode 100644 index 0000000..2f616ae --- /dev/null +++ b/Sources/DecodeReport/StdAfx.cpp @@ -0,0 +1,10 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// stdafx.cpp : source file that includes just the standard includes +// DecodeReport.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Sources/DecodeReport/StdAfx.h b/Sources/DecodeReport/StdAfx.h new file mode 100644 index 0000000..9fcb04c --- /dev/null +++ b/Sources/DecodeReport/StdAfx.h @@ -0,0 +1,3 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include diff --git a/Sources/DedicatedServer/DedicatedServer.cpp b/Sources/DedicatedServer/DedicatedServer.cpp new file mode 100644 index 0000000..c651abb --- /dev/null +++ b/Sources/DedicatedServer/DedicatedServer.cpp @@ -0,0 +1,452 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdAfx.h" +#include +#define DECL_DLL + +#if 0 /* rcg10042001 Doesn't seem to exist. */ +#include +#endif + +// application state variables +extern BOOL _bRunning = TRUE; +static BOOL _bForceRestart = FALSE; +static BOOL _bForceNextMap = FALSE; + +extern CTString _strSamVersion = "no version information"; +extern INDEX ded_iMaxFPS = 100; +extern CTString ded_strConfig = ""; +extern CTString ded_strLevel = ""; +extern INDEX ded_bRestartWhenEmpty = TRUE; +extern FLOAT ded_tmTimeout = -1; +extern CGame *_pGame = NULL; +extern CTString sam_strFirstLevel = "Levels\\KarnakDemo.wld"; +extern CTString sam_strIntroLevel = "Levels\\Intro.wld"; +extern CTString sam_strGameName = "serioussam"; + +CTimerValue _tvLastLevelEnd(-1i64); + +void InitializeGame(void) +{ + try { + #ifndef NDEBUG + #define GAMEDLL _fnmApplicationExe.FileDir()+"Game"+_strModExt+"D.dll" + #else + #define GAMEDLL _fnmApplicationExe.FileDir()+"Game"+_strModExt+".dll" + #endif + CTFileName fnmExpanded; + ExpandFilePath(EFP_READ, CTString(GAMEDLL), fnmExpanded); + + CPrintF(TRANS("Loading game library '%s'...\n"), (const char *)fnmExpanded); + HMODULE hGame = LoadLibraryA(fnmExpanded); + if (hGame==NULL) { + ThrowF_t("%s", GetWindowsError(GetLastError())); + } + CGame* (*GAME_Create)(void) = (CGame* (*)(void))GetProcAddress(hGame, "GAME_Create"); + if (GAME_Create==NULL) { + ThrowF_t("%s", GetWindowsError(GetLastError())); + } + _pGame = GAME_Create(); + + } catch (char *strError) { + FatalError("%s", strError); + } + // init game - this will load persistent symbols + _pGame->Initialize(CTString("Data\\DedicatedServer.gms")); +} + +static void QuitGame(void) +{ + _bRunning = FALSE; +} + +static void RestartGame(void) +{ + _bForceRestart = TRUE; +} +static void NextMap(void) +{ + _bForceNextMap = TRUE; +} + + +void End(void); + +// limit current frame rate if neeeded + +void LimitFrameRate(void) +{ + // measure passed time for each loop + static CTimerValue tvLast(-1.0f); + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + TIME tmCurrentDelta = (tvNow-tvLast).GetSeconds(); + + // limit maximum frame rate + ded_iMaxFPS = ClampDn( ded_iMaxFPS, 1L); + TIME tmWantedDelta = 1.0f / ded_iMaxFPS; + if( tmCurrentDeltaGetHighPrecisionTimer(); +} + +// break/close handler +BOOL WINAPI HandlerRoutine( + DWORD dwCtrlType // control signal type +) +{ + if (dwCtrlType == CTRL_C_EVENT + || dwCtrlType == CTRL_BREAK_EVENT + || dwCtrlType == CTRL_CLOSE_EVENT + || dwCtrlType == CTRL_LOGOFF_EVENT + || dwCtrlType == CTRL_SHUTDOWN_EVENT) { + _bRunning = FALSE; + } + return TRUE; +} + +#define REFRESHTIME (0.1f) + +static void LoadingHook_t(CProgressHookInfo *pphi) +{ + // measure time since last call + static CTimerValue tvLast(0I64); + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + + if (!_bRunning) { + ThrowF_t(TRANS("User break!")); + } + // if not first or final update, and not enough time passed + if (pphi->phi_fCompleted!=0 && pphi->phi_fCompleted!=1 && + (tvNow-tvLast).GetSeconds() < REFRESHTIME) { + // do nothing + return; + } + tvLast = tvNow; + + // print status text + CTString strRes; + printf("\r "); + printf("\r%s : %3.0f%%\r", pphi->phi_strDescription, pphi->phi_fCompleted*100); +} + +// loading hook functions +void EnableLoadingHook(void) +{ + printf("\n"); + SetProgressHook(LoadingHook_t); +} + +void DisableLoadingHook(void) +{ + SetProgressHook(NULL); + printf("\n"); +} + +BOOL StartGame(CTString &strLevel) +{ + _pGame->gm_aiStartLocalPlayers[0] = -1; + _pGame->gm_aiStartLocalPlayers[1] = -1; + _pGame->gm_aiStartLocalPlayers[2] = -1; + _pGame->gm_aiStartLocalPlayers[3] = -1; + + _pGame->gam_strCustomLevel = strLevel; + + _pGame->gm_strNetworkProvider = "TCP/IP Server"; + CUniversalSessionProperties sp; + _pGame->SetMultiPlayerSession(sp); + return _pGame->NewGame( _pGame->gam_strSessionName, strLevel, sp); +} + +void ExecScript(const CTString &str) +{ + CPrintF("Executing: '%s'\n", str); + CTString strCmd; + strCmd.PrintF("include \"%s\"", str); + _pShell->Execute(strCmd); +} + +BOOL Init(int argc, char* argv[]) +{ + _bDedicatedServer = TRUE; + + if (argc!=1+1 && argc!=2+1) { + // NOTE: this cannot be translated - translations are not loaded yet + printf("Usage: DedicatedServer []\n" + "This starts a server reading configs from directory 'Scripts\\Dedicated\\\\'\n"); + getch(); + exit(0); + } + + SetConsoleTitleA(argv[1]); + + ded_strConfig = CTString("Scripts\\Dedicated\\")+argv[1]+"\\"; + + if (argc==2+1) { + _fnmMod = CTString("Mods\\")+argv[2]+"\\"; + } + + + _strLogFile = CTString("Dedicated_")+argv[1]; + + // initialize engine + SE_InitEngine(sam_strGameName); + +// ParseCommandLine(strCmdLine); + + // load all translation tables + InitTranslation(); + CTFileName fnmTransTable; + try { + fnmTransTable = CTFILENAME("Data\\Translations\\Engine.txt"); + AddTranslationTable_t(fnmTransTable); + fnmTransTable = CTFILENAME("Data\\Translations\\Game.txt"); + AddTranslationTable_t(fnmTransTable); + fnmTransTable = CTFILENAME("Data\\Translations\\Entities.txt"); + AddTranslationTable_t(fnmTransTable); + fnmTransTable = CTFILENAME("Data\\Translations\\SeriousSam.txt"); + AddTranslationTable_t(fnmTransTable); + fnmTransTable = CTFILENAME("Data\\Translations\\Levels.txt"); + AddTranslationTable_t(fnmTransTable); + + FinishTranslationTable(); + } catch (char *strError) { + FatalError("%s %s", CTString(fnmTransTable), strError); + } + + // always disable all warnings when in serious sam + _pShell->Execute( "con_bNoWarnings=1;"); + + // declare shell symbols + _pShell->DeclareSymbol("persistent user INDEX ded_iMaxFPS;", &ded_iMaxFPS); + _pShell->DeclareSymbol("user void Quit(void);", &QuitGame); + _pShell->DeclareSymbol("user CTString ded_strLevel;", &ded_strLevel); + _pShell->DeclareSymbol("user FLOAT ded_tmTimeout;", &ded_tmTimeout); + _pShell->DeclareSymbol("user INDEX ded_bRestartWhenEmpty;", &ded_bRestartWhenEmpty); + _pShell->DeclareSymbol("user void Restart(void);", &RestartGame); + _pShell->DeclareSymbol("user void NextMap(void);", &NextMap); + _pShell->DeclareSymbol("persistent user CTString sam_strIntroLevel;", &sam_strIntroLevel); + _pShell->DeclareSymbol("persistent user CTString sam_strGameName;", &sam_strGameName); + _pShell->DeclareSymbol("user CTString sam_strFirstLevel;", &sam_strFirstLevel); + + // init game - this will load persistent symbols + InitializeGame(); + _pNetwork->md_strGameID = sam_strGameName; + + LoadStringVar(CTString("Data\\Var\\Sam_Version.var"), _strSamVersion); + CPrintF(TRANS("Serious Sam version: %s\n"), _strSamVersion); + + SetConsoleCtrlHandler(HandlerRoutine, TRUE); + + // if there is a mod + if (_fnmMod!="") { + // execute the mod startup script + _pShell->Execute(CTString("include \"Scripts\\Mod_startup.ini\";")); + } + + return TRUE; +} +void End(void) +{ + + // cleanup level-info subsystem +// ClearDemosList(); + + // end game + _pGame->End(); + + // end engine + SE_EndEngine(); +} + +static INDEX iRound = 1; +static BOOL _bHadPlayers = 0; +static BOOL _bRestart = 0; +CTString strBegScript; +CTString strEndScript; + +void RoundBegin(void) +{ + // repeat generate script names + FOREVER { + strBegScript.PrintF("%s%d_begin.ini", ded_strConfig, iRound); + strEndScript.PrintF("%s%d_end.ini", ded_strConfig, iRound); + // if start script exists + if (FileExists(strBegScript)) { + // stop searching + break; + + // if start script doesn't exist + } else { + // if this is first round + if (iRound==1) { + // error + CPrintF(TRANS("No scripts present!\n")); + _bRunning = FALSE; + return; + } + // try again with first round + iRound = 1; + } + } + + // run start script + ExecScript(strBegScript); + + // start the level specified there + if (ded_strLevel=="") { + CPrintF(TRANS("ERROR: No next level specified!\n")); + _bRunning = FALSE; + } else { + EnableLoadingHook(); + StartGame(ded_strLevel); + _bHadPlayers = 0; + _bRestart = 0; + DisableLoadingHook(); + _tvLastLevelEnd = CTimerValue(-1i64); + CPrintF(TRANS("\nALL OK: Dedicated server is now running!\n")); + CPrintF(TRANS("Use Ctrl+C to shutdown the server.\n")); + CPrintF(TRANS("DO NOT use the 'Close' button, it might leave the port hanging!\n\n")); + } +} + +void ForceNextMap(void) +{ + EnableLoadingHook(); + StartGame(ded_strLevel); + _bHadPlayers = 0; + _bRestart = 0; + DisableLoadingHook(); + _tvLastLevelEnd = CTimerValue(-1i64); +} + +void RoundEnd(void) +{ + CPrintF("end of round---------------------------\n"); + + ExecScript(strEndScript); + iRound++; +} + +// do the main game loop and render screen +void DoGame(void) +{ + // do the main game loop + if( _pGame->gm_bGameOn) { + _pGame->GameMainLoop(); + + // if any player is connected + if (_pGame->GetPlayersCount()) { + if (!_bHadPlayers) { + // unpause server + if (_pNetwork->IsPaused()) { + _pNetwork->TogglePause(); + } + } + // remember that + _bHadPlayers = 1; + // if no player is connected, + } else { + // if was before + if (_bHadPlayers) { + // make it restart + _bRestart = TRUE; + // if never had any player yet + } else { + // keep the server paused + if (!_pNetwork->IsPaused()) { + _pNetwork->TogglePause(); + } + } + } + + // if game is not started + } else { + // just handle broadcast messages + _pNetwork->GameInactive(); + } + + // limit current frame rate if needed + LimitFrameRate(); +} + +int SubMain(int argc, char* argv[]) +{ + + // initialize + if( !Init(argc, argv)) { + End(); + return -1; + } + + // initialy, application is running + _bRunning = TRUE; + + // execute dedicated server startup script + ExecScript(CTFILENAME("Scripts\\Dedicated_startup.ini")); + // execute startup script for this config + ExecScript(ded_strConfig+"init.ini"); + // start first round + RoundBegin(); + + // while it is still running + while( _bRunning) + { + // do the main game loop + DoGame(); + + // if game is finished + if (_pNetwork->IsGameFinished()) { + // if not yet remembered end of level + if (_tvLastLevelEnd.tv_llValue<0) { + // remember end of level + _tvLastLevelEnd = _pTimer->GetHighPrecisionTimer(); + // finish this round + RoundEnd(); + // if already remembered + } else { + // if time is out + if ((_pTimer->GetHighPrecisionTimer()-_tvLastLevelEnd).GetSeconds()>ded_tmTimeout) { + // start next round + RoundBegin(); + } + } + } + + if (_bRestart||_bForceRestart) { + if (ded_bRestartWhenEmpty||_bForceRestart) { + _bForceRestart = FALSE; + _bRestart = FALSE; + RoundEnd(); + CPrintF(TRANS("\nNOTE: Restarting server!\n\n")); + RoundBegin(); + } else { + _bRestart = FALSE; + _bHadPlayers = FALSE; + } + } + if (_bForceNextMap) { + ForceNextMap(); + _bForceNextMap = FALSE; + } + + } // end of main application loop + + _pGame->StopGame(); + + End(); + + return 0; +} + + +int main(int argc, char* argv[]) +{ + int iResult; + CTSTREAM_BEGIN { + iResult = SubMain(argc, argv); + } CTSTREAM_END; + + return iResult; +} + diff --git a/Sources/DedicatedServer/DedicatedServer.rc b/Sources/DedicatedServer/DedicatedServer.rc new file mode 100644 index 0000000..7117aaf --- /dev/null +++ b/Sources/DedicatedServer/DedicatedServer.rc @@ -0,0 +1,72 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON ICON DISCARDABLE "icon1.ico" + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Sources/DedicatedServer/DedicatedServer.vcxproj b/Sources/DedicatedServer/DedicatedServer.vcxproj new file mode 100644 index 0000000..89aacab --- /dev/null +++ b/Sources/DedicatedServer/DedicatedServer.vcxproj @@ -0,0 +1,184 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + + + {072EF3A9-482A-79A5-D364-2ECDD95B8029} + + + + Application + v120 + Unicode + + + Application + false + Unicode + v120 + + + Application + false + Unicode + v120 + + + + + + + + + + + + + + + + + + Debug\ + Debug\ + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin\Debug;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + Release\ + Release\ + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + WIN32;_DEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Debug\ + .\Debug\DedicatedServer.pch + Use + stdafx.h + .\Debug\ + .\Debug\ + EnableFastChecks + 4996;4333 + + + .\Debug\DedicatedServer.tlb + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\DedicatedServer.bsc + + + true + true + Console + gamed.dll gamempd.lib;%(IgnoreSpecificDefaultLibraries) + Debug\DedicatedServer.exe + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + + + copy Debug\$(TargetName).exe $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(ENGINE_DIR)\Bin\Debug\$(InputName).exe;%(Outputs) + + + + + MultiThreadedDLL + OnlyExplicitInline + true + true + MaxSpeed + true + Level3 + WIN32;NDEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\DedicatedServer.pch + Use + stdafx.h + .\Release\ + .\Release\ + 4996;4333 + + + .\Release\DedicatedServer.tlb + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\DedicatedServer.bsc + + + true + true + Console + game.dll gamemp.lib;%(IgnoreSpecificDefaultLibraries) + .\Release\DedicatedServer.exe + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + + + copy Release\$(TargetName).exe $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin + $(ENGINE_DIR)\Bin\$(InputName).exe;%(Outputs) + + + + + + Create + stdafx.h + Create + stdafx.h + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Sources/DedicatedServer/DedicatedServer.vcxproj.filters b/Sources/DedicatedServer/DedicatedServer.vcxproj.filters new file mode 100644 index 0000000..12d33a8 --- /dev/null +++ b/Sources/DedicatedServer/DedicatedServer.vcxproj.filters @@ -0,0 +1,41 @@ + + + + + {3a912290-4852-4d73-ba9b-6d52a7c95379} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {76cc8123-f0c6-4914-8a8f-8c3f06306d27} + h;hpp;hxx;hm;inl + + + {322898e6-3b58-4251-8e4c-d2330dbaa9a6} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + + \ No newline at end of file diff --git a/Sources/DedicatedServer/DedicatedServer.vcxproj.user b/Sources/DedicatedServer/DedicatedServer.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/Sources/DedicatedServer/DedicatedServer.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Sources/DedicatedServer/ReadMe.txt b/Sources/DedicatedServer/ReadMe.txt new file mode 100644 index 0000000..ac9fa2e --- /dev/null +++ b/Sources/DedicatedServer/ReadMe.txt @@ -0,0 +1,34 @@ +======================================================================== + CONSOLE APPLICATION : DedicatedServer +======================================================================== + + +AppWizard has created this DedicatedServer application for you. + +This file contains a summary of what you will find in each of the files that +make up your DedicatedServer application. + +DedicatedServer.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +DedicatedServer.cpp + This is the main application source file. + + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named DedicatedServer.pch and a precompiled types file named StdAfx.obj. + + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/Sources/DedicatedServer/StdAfx.cpp b/Sources/DedicatedServer/StdAfx.cpp new file mode 100644 index 0000000..077800d --- /dev/null +++ b/Sources/DedicatedServer/StdAfx.cpp @@ -0,0 +1,10 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// stdafx.cpp : source file that includes just the standard includes +// DedicatedServer.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Sources/DedicatedServer/StdAfx.h b/Sources/DedicatedServer/StdAfx.h new file mode 100644 index 0000000..6427857 --- /dev/null +++ b/Sources/DedicatedServer/StdAfx.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include +#include +#include +#include + +/* rcg10042001 protect against Visual C-isms. */ +#ifdef _MSC_VER +#define DECL_DLL _declspec(dllimport) +#endif + +#ifdef PLATFORM_UNIX +#define DECL_DLL +#endif + + +#include +#include +#include +#include + +#undef DECL_DLL diff --git a/Sources/DedicatedServer/icon1.ico b/Sources/DedicatedServer/icon1.ico new file mode 100644 index 0000000..68d0584 Binary files /dev/null and b/Sources/DedicatedServer/icon1.ico differ diff --git a/Sources/DedicatedServer/resource.h b/Sources/DedicatedServer/resource.h new file mode 100644 index 0000000..84da295 --- /dev/null +++ b/Sources/DedicatedServer/resource.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by DedicatedServer.rc +// +#define IDI_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Sources/Depend/Depend.vcxproj b/Sources/Depend/Depend.vcxproj new file mode 100644 index 0000000..585a38b --- /dev/null +++ b/Sources/Depend/Depend.vcxproj @@ -0,0 +1,184 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + + + MFCProj + {8AE1F6E0-5806-D5E5-31B6-466EFE0290B3} + + + + Application + v120 + Unicode + + + Application + Dynamic + Unicode + v120 + + + Application + Dynamic + Unicode + v120 + + + + + + + + + + + + + + + + + + Debug\ + Debug\ + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin\Debug;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + Release\ + Release\ + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + WIN32;_DEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Debug\ + .\Debug\Depend.pch + .\Debug\ + .\Debug\ + 4996;4333 + + + .\Debug\Depend.tlb + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\Depend.bsc + + + true + true + Console + Debug\Depend.exe + true + + + copy Debug\$(TargetName).exe $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(SolutionDir)..\Bin\Debug\$(TargetName).exe;%(Outputs) + + + + + MultiThreadedDLL + OnlyExplicitInline + false + MaxSpeed + true + Level3 + Speed + true + false + true + WIN32;NDEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\Depend.pch + .\Release\ + .\Release\ + 4996;4333 + + + .\Release\Depend.tlb + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\Depend.bsc + + + true + true + Console + .\Release\Depend.exe + true + + + copy Release\$(TargetName).exe $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin + $(SolutionDir)..\Bin\$(TargetName).exe;%(Outputs) + + + + + Use + StdH.h + Use + StdH.h + + + Create + StdH.h + Create + StdH.h + + + Use + StdH.h + Use + StdH.h + + + + + + + + + + \ No newline at end of file diff --git a/Sources/Depend/Depend.vcxproj.filters b/Sources/Depend/Depend.vcxproj.filters new file mode 100644 index 0000000..feb4a6f --- /dev/null +++ b/Sources/Depend/Depend.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + {fe5c9d04-bd48-46c9-a53c-cdec2710268a} + cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90 + + + {35dbd032-f72b-4d4e-8a14-b9dd3610bab8} + h;hpp;hxx;hm;inl;fi;fd + + + {8bc7607a-1165-4c3c-9775-61fbdccad572} + ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe + + + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/Sources/Depend/Depend.vcxproj.user b/Sources/Depend/Depend.vcxproj.user new file mode 100644 index 0000000..237782e --- /dev/null +++ b/Sources/Depend/Depend.vcxproj.user @@ -0,0 +1,13 @@ + + + + + + WindowsLocalDebugger + $(ProjectDir)..\..\Bin\Debug\$(TargetFileName) + + + $(ProjectDir)..\..\Bin\$(TargetFileName) + WindowsLocalDebugger + + \ No newline at end of file diff --git a/Sources/Depend/Dependency.cpp b/Sources/Depend/Dependency.cpp new file mode 100644 index 0000000..17f4e94 --- /dev/null +++ b/Sources/Depend/Dependency.cpp @@ -0,0 +1,570 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" +#include "Dependency.h" +#include + +// adjust file path automatically for application path prefix +void AdjustFilePath_t(CTFileName &fnm) +{ + // if filename contains a colon or double backslash + if (strchr(fnm, ':')!=NULL + ||strstr(fnm, "\\\\")!=NULL) { + // it must be prefixed with application path + fnm.RemoveApplicationPath_t(); + } +} + +// class constructor +CDependInfo::CDependInfo(CTFileName fnFileName, CTFileName fnParent) +{ + // copy file name + di_fnFileName = fnFileName; + di_fnParent = fnParent; +} + +BOOL CDependInfo::IsFileOnDiskUpdated(void) +{ + int file_handle; + // try to open file for reading + file_handle = _open( _fnmApplicationPath + di_fnFileName, _O_RDONLY | _O_BINARY); + // mark as it is not updated + BOOL bUpdated = FALSE; + // if opened succesefully + if( file_handle != -1) + { + struct stat statFileStatus; + // get file status + fstat( file_handle, &statFileStatus); + ASSERT(statFileStatus.st_mtime<=time(NULL)); + + // if last modification time is same as remembered in dependency info object + if( difftime( statFileStatus.st_mtime, di_tTime) >= 0) + { + // mark file as updated + bUpdated = TRUE; + } + } + if(file_handle!=-1) { + _close(file_handle); + } + + return bUpdated; +} + +// if given file allready has its own DependInfo object linked in list +BOOL CDependencyList::ExistsInList(CListHead &lh, CTFileName fnTestName) const +{ + // for all members in depend list + FOREACHINLIST( CDependInfo, di_Node, lh, itDependInfo) + { + // if this DependInfo is describing searching file + if( itDependInfo->di_fnFileName == fnTestName) + { + // return true + return TRUE; + } + } + // if none of linked DepenInfo objects represent our testing file + return FALSE; +} + +// extract all dependencies from list +void CDependencyList::ExtractDependencies() +{ + int file_handle; + volatile ULONG ulDFNM = 'NFD'; + volatile ULONG ulTFNM = 'NFT'; + volatile ULONG ulEFNM = 'NFE'; + char strDFNM[]="DFNM"; + char strTFNM[]="TFNM"; + char strEFNM[]="EFNM"; + + ulDFNM |= ULONG('M')<<24; + ulTFNM |= ULONG('M')<<24; + ulEFNM |= ULONG('M')<<24; + + // for all list members + CListHead lhToProcess; + lhToProcess.MoveList(dl_ListHead); + while(!lhToProcess.IsEmpty()) { + CDependInfo *pdi = LIST_HEAD(lhToProcess, CDependInfo, di_Node); + + pdi->di_Node.Remove(); + dl_ListHead.AddTail(pdi->di_Node); + + CTFileName fnFileName = pdi->di_fnFileName; + // try to open file for reading + file_handle = _open( _fnmApplicationPath + fnFileName, _O_RDONLY | _O_BINARY); + // if an error occured + if( file_handle == -1) + { + // if file is not available remove it from list + //FatalError( "File %s can't be opened!", (CTString&)(_fnmApplicationPath + fnFileName)); + printf( "warning, cannot open: %s (referenced from %s)\n", (CTString&)(fnFileName), (CTString&)(pdi->di_fnParent)); + delete pdi; + } + // if file is opened properly + else + { + struct stat statFileStatus; + // get file status + fstat( file_handle, &statFileStatus); + pdi->di_tTime = statFileStatus.st_mtime; + ASSERT(pdi->di_tTime<=time(NULL)); + // get size + SLONG ulSize = statFileStatus.st_size; + // read file into memory + char *pFileInMemory = (char *) AllocMemory( ulSize); + // must be allocated properly + ASSERT( pFileInMemory != NULL); + // read file + if( _read( file_handle, pFileInMemory, ulSize) != ulSize) + { + FatalError( "Fatal error ocured while reading file: %s.", (CTString&)pdi->di_fnFileName); + } + if(file_handle!=-1) { + _close(file_handle); + } + + // find all file name indentifiers in memory file ("EFNM" or "DFNM") + for( INDEX charCt=0; charCt 254) { + continue; + } + // if found file name does not yet exists in dependacy list + if( (fnTestName!="") && + (!ExistsInList(dl_ListHead, fnTestName)) && + (!ExistsInList(lhToProcess, fnTestName))) + { + // create new depend info object + CDependInfo *pDI = new CDependInfo( fnTestName, fnFileName); + // add it at tail of dependency list + lhToProcess.AddTail( pDI->di_Node); + } + } + // if we found file name inside data file (notice little-big indian convetion) + else if( ulMemValue == ulDFNM) + { + char chrFileName[ 256]; + INDEX iStringLenght = *(INDEX *)(pFileInMemory + charCt + 4); + if( iStringLenght > 254 || iStringLenght<0) { + continue; + } + memcpy( chrFileName, pFileInMemory + charCt + 8, iStringLenght); + chrFileName[ iStringLenght] = 0; + // create full file name + CTFileName fnTestName = CTString(chrFileName); + if( fnTestName!="" && + (!ExistsInList(dl_ListHead, fnTestName)) && + (!ExistsInList(lhToProcess, fnTestName))) + { + // create new depend info object + // NOTICE: string containing file name starts after ULONG determing its lenght (+8!) + CDependInfo *pDI = new CDependInfo( fnTestName, fnFileName); + // add it at tail of dependency list + lhToProcess.AddTail( pDI->di_Node); + } + } + // if we found file name inside text file (notice little-big indian convetion) + else if( ulMemValue == ulTFNM) + { + // after describing long and one space we will find file name + pchrDependentFile = pFileInMemory + charCt + 4 + 1; + // copy file name from the file, until newline + char chrFileName[ 256]; + char *chrSrc = pchrDependentFile; + char *chrDst = chrFileName; + while(*chrSrc!='\n' && *chrSrc!='\r' && chrSrc-pchrDependentFile<254) { + *chrDst++ = *chrSrc++; + } + *chrDst = 0; + CTFileName fnTestName = CTString(chrFileName); + if( strlen(fnTestName) > 254) { + continue; + } + // if found file name does not yet exists in dependacy list + if( (fnTestName!="") && + (!ExistsInList(dl_ListHead, fnTestName)) && + (!ExistsInList(lhToProcess, fnTestName))) + { + // create new depend info object + CDependInfo *pDI = new CDependInfo( fnTestName, fnFileName); + // add it at tail of dependency list + lhToProcess.AddTail( pDI->di_Node); + } + } + } + // free file from memory + FreeMemory(pFileInMemory); + } + } +} + +// substracts given dependecy list from this +void CDependencyList::Substract( CDependencyList &dlToSubstract) +{ + // for all files in this dependency + FORDELETELIST( CDependInfo, di_Node, dl_ListHead, itThis) + { + // see if file exists in other dependency + FOREACHINLIST( CDependInfo, di_Node, dlToSubstract.dl_ListHead, itOther) + { + // if we found same file in other dependency list + if( itThis->di_fnFileName == itOther->di_fnFileName) + { + // if file is updated + if( itOther->IsUpdated( *itThis)) + { + // remove it from list + delete &itThis.Current(); + break; + } + // if file to substract is newer than this one + else if( itThis->IsOlder( *itOther)) + { + FatalError( "File \"%s\" is newer in substracting dependency file.", + (CTString&)itThis->di_fnFileName); + } + } + } + } +} + +// create list from ascii file +void CDependencyList::ImportASCII( CTFileName fnAsciiFile) +{ + char chrOneLine[ 256]; + CTFileStream file; + int file_handle; + + // try to + try + { + // open file list for reading + file.Open_t( fnAsciiFile); + } + catch( char *pError) + { + FatalError( "Error opening file %s. Error: %s.", (CTString&)fnAsciiFile, pError); + } + + // loop loading lines until EOF reached ("catched") + FOREVER + { + try { + // load one line from file + file.GetLine_t( chrOneLine, 256); + // create file name from loaded line + CTFileName fnFileName = CTString(chrOneLine); + AdjustFilePath_t(fnFileName); + // try to open file for reading + file_handle = _open( _fnmApplicationPath+fnFileName, _O_RDONLY | _O_BINARY); + + // if opened succesefully + if( file_handle != -1) { + // create new depend info object + CDependInfo *pDI = new CDependInfo( fnFileName, fnAsciiFile); + struct stat statFileStatus; + // get file status + fstat( file_handle, &statFileStatus); + // obtain last modification time + pDI->di_tTime = statFileStatus.st_mtime; + ASSERT(pDI->di_tTime<=time(NULL)); + // add it at tail of dependency list + dl_ListHead.AddTail( pDI->di_Node); + // close file + _close( file_handle); + } else { + CPrintF("cannot open file '%s'\n", chrOneLine); + } + } + // error, EOF catched + catch( char *pFinished) + { + if (!file.AtEOF()) { + CPrintF("%s\n", pFinished); + } + break; + } + } +} + +// remove updated files from list +void CDependencyList::RemoveUpdatedFiles() +{ + // for all list members + FORDELETELIST( CDependInfo, di_Node, dl_ListHead, itDependInfo) + { + // if file is updated + if( itDependInfo->IsFileOnDiskUpdated()) + { + // remove it from list + delete &itDependInfo.Current(); + } + } +} + +// clear dependency list +void CDependencyList::Clear( void) +{ + // for all list members + FORDELETELIST( CDependInfo, di_Node, dl_ListHead, itDependInfo) + { + // delete member + delete &itDependInfo.Current(); + } +} + +// export list members into ascii file in form sutable for archivers +void CDependencyList::ExportASCII_t( CTFileName fnAsciiFile) +{ + CTFileStream strmFile; + char line[ 256]; + + // try to + try + { + // create exporting text file + strmFile.Create_t( fnAsciiFile); + } + catch( char *pError) + { + FatalError( "Error creating file %s. Error: %s.", (CTString&)fnAsciiFile, pError); + } + + // for all members in depend list + FOREACHINLIST( CDependInfo, di_Node, dl_ListHead, itDependInfo) + { + // prepare line of text + sprintf( line, "%s\n", (CTString&)itDependInfo->di_fnFileName); + // write text line into file + strmFile.Write_t( line, strlen( line)); + } +} + + +// dynamic array of translation pairs +CDynamicArray _atpPairs; + +// add one string to array +static void AddStringForTranslation(const CTString &str) +{ + // for each existing pair + _atpPairs.Lock(); + INDEX ct = _atpPairs.Count(); + for(INDEX i=0; i 254 || iStrLen<0) { + continue; + } + memcpy( achr, pub + 8, iStrLen); + achr[ iStrLen] = 0; + // get it + CTString str = achr; + // add it + AddStringForTranslation(str); + // if text translatable string is here + } else if (*pul=='SRTT') { + + // after describing long and one space we will find file name + char *pchrStart = (char*)pub + 4 + 1; + // copy file name from the file, until newline + char chrString[ 256]; + char *chrSrc = pchrStart; + char *chrDst = chrString; + while(*chrSrc!='\n' && *chrSrc!='\r' && chrSrc-pchrStart<254) { + *chrDst++ = *chrSrc++; + } + *chrDst = 0; + CTString str = CTString(chrString); + if( strlen(str) > 254) { + continue; + } + // add it + AddStringForTranslation(str); + } + } + + // free file from memory + FreeMemory(pubFile); + } + + // count used pairs + _atpPairs.Lock(); + INDEX ctUsedPairs = 0; + {INDEX ct = _atpPairs.Count(); + for(INDEX i=0; i\n"); + WriteTranslationString_t(strm, tp.tp_strDst); + }} + _atpPairs.Unlock(); + // write eof token + WriteTranslationToken_t(strm, "\n\\0\\$\n"); +} + +// read operation +void CDependencyList::Read_t( CTStream *istrFile) +{ + // count of files + INDEX ctFiles; + // expect file ID + istrFile->ExpectID_t( CChunkID( "DEPD")); + // read number of entries in list + *istrFile >> ctFiles; + // load all list members + for( INDEX i=0; iGetDescription()); + // read dependency object + pDI->Read_t( istrFile); + // add it at tail of dependency list + dl_ListHead.AddTail( pDI->di_Node); + } +} + +// write opertaion +void CDependencyList::Write_t( CTStream *ostrFile) +{ + // write file ID + ostrFile->WriteID_t( CChunkID( "DEPD")); + // write number of entries in list + *ostrFile << dl_ListHead.Count(); + // for all members in dependency list + FOREACHINLIST( CDependInfo, di_Node, dl_ListHead, itDependInfo) + { + // write one depend info object + itDependInfo->Write_t( ostrFile); + } +} + +// make a new directory recursively +static void MakeDirectory_t(const CTFileName &fnm) +{ + if (fnm=="") { + return; + } + // remove trailing backslash + CTFileName fnmDir = fnm; + ((char *)(const char*)fnmDir)[strlen(fnmDir)-1] = 0; + // get the path part + CTFileName fnmDirPath = fnmDir.FileDir(); + // if there is a path part + if (fnmDirPath!="") { + // create that first + MakeDirectory_t(fnmDirPath); + } + // try to create the directory + int iRes = _mkdir(_fnmApplicationPath+fnmDir); +} + diff --git a/Sources/Depend/Dependency.h b/Sources/Depend/Dependency.h new file mode 100644 index 0000000..41d8ce0 --- /dev/null +++ b/Sources/Depend/Dependency.h @@ -0,0 +1,70 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_DEPENDENCY_H +#define SE_INCL_DEPENDENCY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// adjust file path automatically for application path prefix +void AdjustFilePath_t(CTFileName &fnm); + +class CDependInfo { +public: + // atributes + CListNode di_Node; + CTFileName di_fnFileName; + time_t di_tTime; + CTFileName di_fnParent; + + // default constructor + CDependInfo( CTFileName fnFileName, CTFileName fnParent); + // if this file is updated + BOOL IsFileOnDiskUpdated(void); + // if time of given file is same + inline BOOL IsUpdated(const CDependInfo &diOther) { + return( diOther.di_tTime == di_tTime);}; + // if given file is older + inline BOOL IsOlder(const CDependInfo &diOther) { + return( di_tTime < diOther.di_tTime);}; + // Comparison operator. + inline BOOL operator==(const CDependInfo &diOther) const { + return( diOther.di_fnFileName == di_fnFileName);}; + // read and write opertaions + inline void Read_t( CTStream *istrFile) { + *istrFile >> di_fnFileName; + istrFile->Read_t( &di_tTime, sizeof( time_t)); + }; + inline void Write_t( CTStream *ostrFile) const { + *ostrFile << di_fnFileName; + ostrFile->Write_t( &di_tTime, sizeof( time_t)); + }; +}; + +class CDependencyList { +public: + CListHead dl_ListHead; + // operations + void ExtractDependencies(); + // remove updated files from list + void RemoveUpdatedFiles(); + // create list from ascii file + void ImportASCII( CTFileName fnAsciiFile); + // export list members into ascii file in form sutable for archivers + void ExportASCII_t( CTFileName fnAsciiFile); + // substracts given list from this + void Substract( CDependencyList &dlToSubstract); + // extract translation strings from all files in list + void ExtractTranslations_t( const CTFileName &fnTranslations); + // clear dependency list + void Clear( void); + // if given file allready has its own DependInfo object linked in list + BOOL ExistsInList(CListHead &lh, CTFileName fnTestName) const; + // read and write opertaions + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Depend/StdH.cpp b/Sources/Depend/StdH.cpp new file mode 100644 index 0000000..a0fb0be --- /dev/null +++ b/Sources/Depend/StdH.cpp @@ -0,0 +1,3 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" \ No newline at end of file diff --git a/Sources/Depend/StdH.h b/Sources/Depend/StdH.h new file mode 100644 index 0000000..218930b --- /dev/null +++ b/Sources/Depend/StdH.h @@ -0,0 +1,13 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include diff --git a/Sources/Depend/UtilityDepend.cpp b/Sources/Depend/UtilityDepend.cpp new file mode 100644 index 0000000..4d23cf8 --- /dev/null +++ b/Sources/Depend/UtilityDepend.cpp @@ -0,0 +1,156 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" +#include "Dependency.h" + +// Depend - extract dependencies and create group file utility + +#define ACHR_OPTION argv[1] +#define ACHR_APP_DIR argv[2] + +void PrintUsage() +{ + printf( + "\nUSAGE:\n" + "Depend d \n" + " make difference beetween two dependency files (result = file 1 - file 2)\n" + "Depend i \n" + " create dependencies for files listed in given list file\n" + "Depend u \n" + " remove updated files from dependency file\n" + "Depend e \n" + " export dependency file to ascii list file\n" + "Depend t \n" + " export strings for translation\n" + "\n"); + exit( EXIT_FAILURE); +} + +void SubMain( int argc, char *argv[]); + +int main( int argc, char *argv[]) +{ + CTSTREAM_BEGIN { + SubMain(argc, argv); + } CTSTREAM_END; + return 0; +} + +void SubMain( int argc, char *argv[]) +{ + // there must be 4 or 6 parameters (first is depend.exe file name) + if( (argc < 4) || (argc > 6) ) + { + PrintUsage(); + } + + // initialize engine + SE_InitEngine(""); + // get application path from cmd line + _fnmApplicationPath = CTString(ACHR_APP_DIR); + // if not ending with backslash + if (_fnmApplicationPath[strlen(_fnmApplicationPath)-1]!='\\') { + _fnmApplicationPath += "\\"; + } + + // get all filenames from command line + CTFileName afnFiles[3]; + INDEX ctFiles = argc-3; + if (ctFiles>ARRAYCOUNT(afnFiles)) { + PrintUsage(); + } + for (INDEX iFile=0; iFile + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + + + {1F46FD81-1A15-7E2C-7C68-84AB43BC0B05} + + + + Application + v120 + Unicode + + + Application + false + Unicode + v120 + + + Application + false + Unicode + v120 + + + + + + + + + + + + + + + + + + Debug\ + Debug\ + false + $(SolutionDir)..\Tools.Win32;$(ExecutablePath) + $(SolutionDir);$(ProjectDir);$(IncludePath) + $(SolutionDir)Ecc;$(SourcePath) + + + Release\ + Release\ + false + $(SolutionDir)..\Tools.Win32;$(ExecutablePath) + $(SolutionDir);$(ProjectDir);$(IncludePath) + $(SolutionDir)Ecc;$(SourcePath) + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + WIN32;_DEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Debug\ + .\Debug\Ecc.pch + .\Debug\ + .\Debug\ + 4996;4333 + + + .\Debug\Ecc.tlb + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\Ecc.bsc + + + true + true + Console + .\Debug\Ecc.exe + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + + + mkdir $(SolutionDir)..\Bin 2>nul +mkdir $(SolutionDir)..\Bin\Debug 2>nul +copy Debug\$(TargetName).exe $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to \Bin\Debug + $(SolutionDir)..\Bin\Debug\$(TargetName).exe;%(Outputs) + + + + + MultiThreadedDLL + OnlyExplicitInline + false + MaxSpeed + true + Level3 + Speed + true + false + true + WIN32;NDEBUG;_CONSOLE;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\Ecc.pch + .\Release\ + .\Release\ + 4996;4333 + + + .\Release\Ecc.tlb + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\Ecc.bsc + + + true + true + Console + .\Release\Ecc.exe + odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + true + + + mkdir $(SolutionDir)..\Bin 2>nul +copy Release\$(TargetName).exe $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to \Bin + $(SolutionDir)..\Bin\$(TargetName).exe;%(Outputs) + + + + + mkdir $(SolutionDir)..\Bin 2>nul +copy Debug\%(Filename).exe $(SolutionDir)..\Bin\ >nul +copy Debug\%(Filename).map $(SolutionDir)..\Bin\ >nul + + + + + Document + pushd $(SolutionDir) +bison -o$(ProjectName)/Parser.c $(ProjectName)/Parser.y -d +popd +copy %(RootDir)%(Directory)\Parser.c %(RootDir)%(Directory)\Parser.cpp +del %(RootDir)%(Directory)\Parser.c /q + Creating parser source + %(RootDir)%(Directory)\Parser.cpp;%(RootDir)%(Directory)\Parser.h;%(Outputs) + pushd $(SolutionDir) +bison -o$(ProjectName)/Parser.c $(ProjectName)/Parser.y -d +popd +copy %(RootDir)%(Directory)\Parser.c %(RootDir)%(Directory)\Parser.cpp +del %(RootDir)%(Directory)\Parser.c /q + Creating parser source + %(RootDir)%(Directory)\Parser.cpp;%(RootDir)%(Directory)\Parser.h;%(Outputs) + + + Document + flex -o%(RootDir)%(Directory)\Scanner.cpp %(RootDir)%(Directory)\Scanner.l + Creating scanner source + .\Scanner.cpp;%(Outputs) + flex -o%(RootDir)%(Directory)\Scanner.cpp %(RootDir)%(Directory)\Scanner.l + .\Scanner.cpp;%(Outputs) + + + + + true + true + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Sources/Ecc/Ecc.vcxproj.filters b/Sources/Ecc/Ecc.vcxproj.filters new file mode 100644 index 0000000..18fab06 --- /dev/null +++ b/Sources/Ecc/Ecc.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + {acd5aeef-9312-4c06-9a18-ffc69148b586} + cpp + + + {97120739-0d00-462f-bb75-be637f0e69f3} + + + {414eb5ab-c891-41f1-85bb-3594afce7081} + c + + + {aebfcf57-f684-490f-baf9-b3c0fd748e23} + h;hpp;hxx;hm;inl;fi;fd + + + {cf15f1a2-66f9-41f7-872d-8fbaa310a5e2} + ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe + + + + + Source Files\Dummy + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files\Grammar files + + + Source Files\Grammar files + + + \ No newline at end of file diff --git a/Sources/Ecc/Ecc.vcxproj.user b/Sources/Ecc/Ecc.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/Sources/Ecc/Ecc.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Sources/Ecc/Main.cpp b/Sources/Ecc/Main.cpp new file mode 100644 index 0000000..596ab13 --- /dev/null +++ b/Sources/Ecc/Main.cpp @@ -0,0 +1,333 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" +#include "Main.h" + +FILE *_fInput; +int _iLinesCt = 1; +char *_strInputFileName; +int _bTrackLineInformation=0; // this is set if #line should be inserted in tokens +bool _bRemoveLineDirective = 0; + + +FILE *_fImplementation; +FILE *_fDeclaration; +FILE *_fTables; +FILE *_fExports; +char *_strFileNameBase; +char *_strFileNameBaseIdentifier; + +extern FILE *yyin; + +extern "C" int yywrap(void) +{ + return 1; +} +int ctErrors = 0; + +char *stradd(char *str1, char *str2) +{ + char *strResult; + strResult = (char*)malloc(strlen(str1)+strlen(str2)+1); + strcpy(strResult, str1); + strcat(strResult, str2); + return strResult; +} +char *stradd(char *str1, char *str2, char *str3) +{ + char *strResult; + strResult = (char*)malloc(strlen(str1)+strlen(str2)+strlen(str3)+1); + strcpy(strResult, str1); + strcat(strResult, str2); + strcat(strResult, str3); + return strResult; +} + +char *LineDirective(int i) +{ + char str[256]; + sprintf(str, "\n#line %d %s\n", i, _strInputFileName); + return strdup(str); +} + +SType SType::operator+(const SType &other) +{ + SType sum; + sum.strString = stradd(strString, other.strString); + sum.iLine = -1; + sum.bCrossesStates = bCrossesStates||other.bCrossesStates; + return sum; +}; + +/* + * Function used for reporting errors. + */ +void yyerror(char *s) +{ + fprintf( stderr, "%s(%d): Error: %s\n", _strInputFileName, _iLinesCt, s); + ctErrors++; +} + +/* + * Change the extension of the filename. + */ +char *ChangeFileNameExtension(char *strFileName, char *strNewExtension) +{ + char *strChanged = (char*)malloc(strlen(strFileName)+strlen(strNewExtension)+2); + strcpy(strChanged, strFileName); + char *pchDot = strrchr(strChanged, '.'); + if (pchDot==NULL) { + pchDot = strChanged+strlen(strChanged); + } + strcpy(pchDot, strNewExtension); + return strChanged; +} + +/* + * Open a file and report an error if failed. + */ +FILE *FOpen(const char *strFileName, char *strMode) +{ + // open the input file + FILE *f = fopen(strFileName, strMode); + // if not successful + if (f==NULL) { + // report error + fprintf(stderr, "Can't open file '%s': %s\n", strFileName, strerror(errno)); + //quit + exit(EXIT_FAILURE); + } + return f; +} + +/* + * Print a header to an output file. + */ +static void PrintHeader(FILE *f) +{ + fprintf(f, "/*\n"); + fprintf(f, " * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98\n"); + fprintf(f, " */\n"); + fprintf(f, "\n"); +} + +void TranslateBackSlashes(char *str) +{ + char *strNextSlash = str; + while((strNextSlash = strchr(strNextSlash, '\\'))!=NULL) { + *strNextSlash = '/'; + } +} + +#define READSIZE 1024 +/* Relpace File and remove #line directive from file */ +void ReplaceFileRL(const char *strOld, const char *strNew) +{ + char strOldBuff[READSIZE*3+1]; + char strNewBuff[READSIZE+1]; + int iOldch=0; + FILE *pfNew = NULL; + FILE *pfOld = NULL; + bool bQuotes = 0; + bool bComment = 0; + + // open files + pfNew = fopen(strNew,"rb"); + if(!pfNew) goto Error; + pfOld = fopen(strOld,"wb"); + if(!pfOld) goto Error; + + // until eof + while(!feof(pfNew)) + { + // clear buffers + memset(&strOldBuff,0,sizeof(strOldBuff)); + memset(&strNewBuff,0,sizeof(strNewBuff)); + + iOldch = 0; + bQuotes = 0; + bComment = 0; + + // read one line from file + int iRead = fread(strNewBuff,1,READSIZE,pfNew); + char *chLineEnd = strchr(strNewBuff,13); + if(chLineEnd) *(chLineEnd+2) = 0; + // get line length + int ctch = strlen(strNewBuff); + int iSeek = -iRead+ctch; + // seek file for extra characters read + if(iSeek!=0) fseek(pfNew,iSeek ,SEEK_CUR); + if(strncmp(strNewBuff,"#line",5)==0) + { + continue; + } + + // process each charachter + for(int ich=0;ich0) && (*(pchNew-1)=='\\')) { } + else bQuotes = !bQuotes; + } + else if((*pchNew == '/') && (*(pchNew+1) == '/')) + { + // if this is comment + bComment = 1; + } + strOldBuff[iOldch++] = strNewBuff[ich]; + } + fwrite(&strOldBuff,1,iOldch,pfOld); + } + + if(pfNew) fclose(pfNew); + if(pfOld) fclose(pfOld); + remove(strNew); + return; +Error: + if(pfNew) fclose(pfNew); + if(pfOld) fclose(pfOld); +} + +/* Replace a file with a new file. */ +void ReplaceFile(const char *strOld, const char *strNew) +{ + if(_bRemoveLineDirective) + { + ReplaceFileRL(strOld,strNew); + return; + } + remove(strOld); + rename(strNew, strOld); +} +/* Replace a file with a new file if they are different. + * Used to keep .h files from constantly changing when you change the implementation. + */ +void ReplaceIfChanged(const char *strOld, const char *strNew) +{ + int iChanged = 1; + FILE *fOld = fopen(strOld, "r"); + if (fOld!=NULL) { + iChanged = 0; + FILE *fNew = FOpen(strNew, "r"); + while (!feof(fOld)) { + char strOldLine[4096] = "#l"; + char strNewLine[4096] = "#l"; + + // skip #line directives + while(strNewLine[0]=='#' && strNewLine[1]=='l' && !feof(fNew)) { + fgets(strNewLine, sizeof(strNewLine)-1, fNew); + } + while(strOldLine[0]=='#' && strOldLine[1]=='l' && !feof(fOld)) { + fgets(strOldLine, sizeof(strOldLine)-1, fOld); + } + if (strcmp(strNewLine, strOldLine)!=0) { + iChanged = 1; + break; + } + } + fclose(fNew); + fclose(fOld); + } + + if (iChanged) { + remove(strOld); + rename(strNew, strOld); + } else { + remove(strNew); + } +} + +int main(int argc, char *argv[]) +{ + // if there is not one argument on the command line + if (argc<1+1) { + // print usage + printf("Usage: Ecc \n -line\n"); + //quit + return EXIT_FAILURE; + } + if(argc>2) + { + if(strcmp(argv[2],"-line")==0) + { + _bRemoveLineDirective=1; + } + } + // open the input file + _fInput = FOpen(argv[1], "r"); + //printf("%s\n", argv[1]); + // open all the output files + char *strImplementation = ChangeFileNameExtension(argv[1], ".cpp_tmp"); + char *strImplementationOld = ChangeFileNameExtension(argv[1], ".cpp"); + char *strDeclaration = ChangeFileNameExtension(argv[1], ".h_tmp"); + char *strDeclarationOld = ChangeFileNameExtension(argv[1], ".h"); + char *strTables = ChangeFileNameExtension(argv[1], "_tables.h_tmp"); + char *strTablesOld = ChangeFileNameExtension(argv[1], "_tables.h"); + + _fImplementation = FOpen(strImplementation, "w"); + _fDeclaration = FOpen(strDeclaration , "w"); + _fTables = FOpen(strTables , "w"); + // get the filename as preprocessor usable identifier + _strFileNameBase = ChangeFileNameExtension(argv[1], ""); + _strFileNameBaseIdentifier = strdup(_strFileNameBase); + {char *strNextSlash = _strFileNameBaseIdentifier; + while((strNextSlash = strchr(strNextSlash, '/'))!=NULL) { + *strNextSlash = '_'; + }} + {char *strNextSlash = _strFileNameBaseIdentifier; + while((strNextSlash = strchr(strNextSlash, '\\'))!=NULL) { + *strNextSlash = '_'; + }} + // print their headers + PrintHeader(_fImplementation ); + PrintHeader(_fDeclaration ); + PrintHeader(_fTables ); + + // remember input filename + char strFullInputName[MAXPATHLEN]; + _fullpath(strFullInputName, argv[1], MAXPATHLEN); + _strInputFileName = strFullInputName; + TranslateBackSlashes(_strInputFileName); + // make lex use the input file + yyin = _fInput; + + // parse input file and generate the output files + yyparse(); + + // close all files + fclose(_fImplementation); + fclose(_fDeclaration); + fclose(_fTables); + + // if there were no errors + if (ctErrors==0) { + // update the files that have changed + ReplaceFile(strImplementationOld, strImplementation); + ReplaceIfChanged(strDeclarationOld, strDeclaration); + ReplaceIfChanged(strTablesOld, strTables); + + return EXIT_SUCCESS; + // if there were errors + } else { + // delete all files (the old declaration file is left intact!) + remove(strImplementation); + remove(strDeclaration ); + remove(strTables ); + return EXIT_FAILURE; + } +} \ No newline at end of file diff --git a/Sources/Ecc/Main.h b/Sources/Ecc/Main.h new file mode 100644 index 0000000..6945373 --- /dev/null +++ b/Sources/Ecc/Main.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +/* rcg10042001 */ +#ifdef PLATFORM_WIN32 +#define alloca _alloca +#endif + +#ifndef MAXPATHLEN +#define MAXPATHLEN 256 +#endif + +extern int yylex(void); +extern void yyerror(char *s); +extern int yyparse(void); + +extern FILE *_fInput; +extern int _iLinesCt; +extern int _bTrackLineInformation; // this is set if #line should be inserted in tokens +extern char *_strInputFileName; + +extern FILE *_fImplementation; +extern FILE *_fDeclaration; +extern FILE *_fTables; +extern FILE *_fExports; +extern char *_strFileNameBase; +extern char *_strFileNameBaseIdentifier; + +struct SType { + char *strString; + int bCrossesStates; + int iLine; + + SType(void) { + strString = strdup(""); + bCrossesStates = 0; + iLine = -1; + }; + SType(const char *str) { + strString = strdup(str); + bCrossesStates = 0; + iLine = -1; + }; + SType(const SType &other) { + strString = strdup(other.strString); + bCrossesStates = other.bCrossesStates; + iLine = other.iLine; + }; + const SType &operator=(const SType &other) { + strString = strdup(other.strString); + bCrossesStates = other.bCrossesStates; + iLine = other.iLine; + return *this; + }; + const SType &operator=(char *str) { + strString = strdup(str); + bCrossesStates = 0; + iLine = -1; + return *this; + }; + SType operator+(const SType &other); +}; + +#define YYSTYPE SType diff --git a/Sources/Ecc/Parser.cpp b/Sources/Ecc/Parser.cpp new file mode 100644 index 0000000..c328e48 --- /dev/null +++ b/Sources/Ecc/Parser.cpp @@ -0,0 +1,3508 @@ + +/* A Bison parser, made from ecc/parser.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define c_char 258 +#define c_int 259 +#define c_float 260 +#define c_bool 261 +#define c_string 262 +#define identifier 263 +#define cppblock 264 +#define k_while 265 +#define k_for 266 +#define k_if 267 +#define k_else 268 +#define k_enum 269 +#define k_switch 270 +#define k_case 271 +#define k_class 272 +#define k_do 273 +#define k_void 274 +#define k_const 275 +#define k_inline 276 +#define k_static 277 +#define k_virtual 278 +#define k_return 279 +#define k_autowait 280 +#define k_autocall 281 +#define k_waitevent 282 +#define k_event 283 +#define k_name 284 +#define k_thumbnail 285 +#define k_features 286 +#define k_uses 287 +#define k_export 288 +#define k_texture 289 +#define k_sound 290 +#define k_model 291 +#define k_properties 292 +#define k_components 293 +#define k_functions 294 +#define k_procedures 295 +#define k_wait 296 +#define k_on 297 +#define k_otherwise 298 +#define k_call 299 +#define k_jump 300 +#define k_stop 301 +#define k_resume 302 +#define k_pass 303 +#define k_CTString 304 +#define k_CTStringTrans 305 +#define k_CTFileName 306 +#define k_CTFileNameNoDep 307 +#define k_BOOL 308 +#define k_COLOR 309 +#define k_FLOAT 310 +#define k_INDEX 311 +#define k_RANGE 312 +#define k_CEntityPointer 313 +#define k_CModelObject 314 +#define k_CModelInstance 315 +#define k_CAnimObject 316 +#define k_CSoundObject 317 +#define k_CPlacement3D 318 +#define k_FLOATaabbox3D 319 +#define k_FLOATmatrix3D 320 +#define k_FLOATquat3D 321 +#define k_ANGLE 322 +#define k_FLOAT3D 323 +#define k_ANGLE3D 324 +#define k_FLOATplane3D 325 +#define k_ANIMATION 326 +#define k_ILLUMINATIONTYPE 327 +#define k_FLAGS 328 + +#line 1 "ecc/parser.y" + +// rcg10042001 Changed to specify Ecc directory... +#include "Ecc/StdH.h" +#include "Ecc/Main.h" + +static char *_strCurrentClass; +static int _iCurrentClassID; +static char *_strCurrentBase; +static char *_strCurrentDescription; +static char *_strCurrentThumbnail; +static char *_strCurrentEnum; +static int _bClassIsExported = 0; + +static char *_strCurrentPropertyID; +static char *_strCurrentPropertyIdentifier; +static char *_strCurrentPropertyPropertyType; +static char *_strCurrentPropertyEnumType; +static char *_strCurrentPropertyDataType; +static char *_strCurrentPropertyName; +static char *_strCurrentPropertyShortcut; +static char *_strCurrentPropertyColor; +static char *_strCurrentPropertyFlags; +static char *_strCurrentPropertyDefaultCode; + +static char *_strCurrentComponentIdentifier; +static char *_strCurrentComponentType; +static char *_strCurrentComponentID; +static char *_strCurrentComponentFileName; + +static int _ctInProcedureHandler = 0; +static char _strLastProcedureName[256]; + +static char _strInWaitName[256]; +static char _strAfterWaitName[256]; +static char _strInWaitID[256]; +static char _strAfterWaitID[256]; + +static char _strInLoopName[256]; +static char _strAfterLoopName[256]; +static char _strInLoopID[256]; +static char _strAfterLoopID[256]; +static char _strCurrentStateID[256]; + +static int _bInProcedure; // set if currently compiling a procedure +static int _bInHandler; +static int _bHasOtherwise; // set if current 'wait' block has an 'otherwise' statement + +static char *_strCurrentEvent; +static int _bFeature_AbstractBaseClass; +static int _bFeature_ImplementsOnInitClass; +static int _bFeature_ImplementsOnEndClass; +static int _bFeature_ImplementsOnPrecache; +static int _bFeature_ImplementsOnWorldInit; +static int _bFeature_ImplementsOnWorldEnd; +static int _bFeature_ImplementsOnWorldTick; +static int _bFeature_ImplementsOnWorldRender; +static int _bFeature_CanBePredictable; + +static int _iNextFreeID; +inline int CreateID(void) { + return _iNextFreeID++; +} + +static int _ctBraces = 0; +void OpenBrace(void) { + _ctBraces++; +} +void CloseBrace(void) { + _ctBraces--; +} +SType Braces(int iBraces) { + static char strBraces[50]; + memset(strBraces, '}', sizeof(strBraces)); + strBraces[iBraces] = 0; + return SType(strBraces); +} +char *RemoveLineDirective(char *str) +{ + if (str[0]=='\n' && str[1]=='#') { + return strchr(str+2, '\n')+1; + } else { + return str; + } +} +char *GetLineDirective(SType &st) +{ + char *str = st.strString; + if (str[0]=='\n' && str[1]=='#' && str[2]=='l') { + char *strResult = strdup(str); + strchr(strResult+3,'\n')[1] = 0; + return strResult; + } else { + return ""; + } +} +void AddHandlerFunction(char *strProcedureName, int iStateID) +{ + fprintf(_fDeclaration, " BOOL %s(const CEntityEvent &__eeInput);\n", strProcedureName); + fprintf(_fTables, " {0x%08x, -1, CEntity::pEventHandler(&%s::%s), " + "DEBUGSTRING(\"%s::%s\")},\n", + iStateID, _strCurrentClass, strProcedureName, _strCurrentClass, strProcedureName); +} + + +void AddHandlerFunction(char *strProcedureName, char *strStateID, char *strBaseStateID) +{ + fprintf(_fDeclaration, " BOOL %s(const CEntityEvent &__eeInput);\n", strProcedureName); + fprintf(_fTables, " {%s, %s, CEntity::pEventHandler(&%s::%s)," + "DEBUGSTRING(\"%s::%s\")},\n", + strStateID, strBaseStateID, _strCurrentClass, strProcedureName, + _strCurrentClass, RemoveLineDirective(strProcedureName)); + strcpy(_strLastProcedureName, RemoveLineDirective(strProcedureName)); + _ctInProcedureHandler = 0; +} + +void CreateInternalHandlerFunction(char *strFunctionName, char *strID) +{ + int iID = CreateID(); + _ctInProcedureHandler++; + sprintf(strID, "0x%08x", iID); + sprintf(strFunctionName, "H0x%08x_%s_%02d", iID, _strLastProcedureName, _ctInProcedureHandler); + AddHandlerFunction(strFunctionName, iID); +} + +void DeclareFeatureProperties(void) +{ + if (_bFeature_CanBePredictable) { + fprintf(_fTables, " CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x%08x<<8)+%s, offsetof(%s, %s), %s, %s, %s, %s),\n", + _iCurrentClassID, + "255", + _strCurrentClass, + "m_penPrediction", + "\"\"", + "0", + "0", + "0"); + fprintf(_fDeclaration, " %s %s;\n", + "CEntityPointer", + "m_penPrediction" + ); + fprintf(_fImplementation, " m_penPrediction = NULL;\n"); + } +} + +#undef YYERROR_VERBOSE + + +#ifndef YYLTYPE +typedef + struct yyltype + { + int timestamp; + int first_line; + int first_column; + int last_line; + int last_column; + char *text; + } + yyltype; + +#define YYLTYPE yyltype +#endif + +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 490 +#define YYFLAG -32768 +#define YYNTBASE 98 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 328 ? yytranslate[x] : 204) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 89, 2, 2, 2, 92, 85, 2, 79, + 80, 84, 88, 77, 82, 96, 91, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 78, 74, 86, + 81, 87, 97, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 94, 2, 95, 93, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 75, 90, 76, 83, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 1, 2, 3, 4, 5, 17, 18, 20, 21, + 24, 28, 29, 32, 35, 36, 45, 46, 48, 50, + 54, 58, 59, 68, 69, 71, 73, 77, 80, 81, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 126, + 128, 131, 132, 133, 138, 140, 144, 146, 147, 151, + 152, 155, 159, 161, 164, 166, 170, 171, 178, 180, + 182, 185, 188, 190, 192, 194, 196, 198, 200, 202, + 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, + 224, 226, 228, 230, 232, 234, 236, 237, 241, 242, + 244, 245, 250, 251, 256, 257, 260, 262, 264, 266, + 268, 270, 272, 277, 282, 285, 289, 291, 294, 296, + 300, 301, 306, 308, 310, 312, 314, 316, 318, 320, + 321, 324, 338, 339, 341, 342, 344, 345, 347, 348, + 350, 351, 353, 354, 356, 358, 360, 364, 367, 369, + 371, 373, 375, 378, 381, 384, 387, 390, 393, 396, + 399, 404, 405, 408, 409, 415, 416, 427, 428, 430, + 433, 435, 437, 439, 441, 443, 445, 447, 449, 451, + 453, 455, 457, 459, 461, 463, 465, 467, 469, 471, + 473, 475, 477, 479, 481, 483, 485, 488, 491, 494, + 497, 500, 503, 506, 509, 512, 515, 518, 521, 524, + 527, 530, 533, 536, 539, 542, 545, 548, 551, 555, + 559, 563, 566, 568, 570, 572, 574, 576, 578, 580, + 582, 584, 586, 588, 590, 592, 594, 596, 598, 600, + 602, 604, 606, 608, 610, 612, 614, 616, 618, 620, + 622, 624, 626, 628, 630, 631, 634, 637, 645, 649, + 653, 658, 660, 662, 664, 666, 668, 670, 672, 674, + 676, 678, 680, 682, 684, 686, 688, 690, 698, 708, + 709, 718, 719, 730, 731, 744, 745, 752, 756, 762, + 763, 765, 774, 777, 781, 788, 795, 797, 798, 800, + 805, 808, 811, 814, 818, 819, 821, 831, 841, 842 +}; + +static const short yyrhs[] = { -1, + 0, 0, 0, 0, 4, 99, 104, 100, 105, 101, + 107, 102, 104, 103, 118, 0, 0, 9, 0, 0, + 105, 106, 0, 32, 7, 74, 0, 0, 107, 108, + 0, 107, 113, 0, 0, 14, 8, 109, 75, 111, + 110, 76, 74, 0, 0, 77, 0, 112, 0, 111, + 77, 112, 0, 4, 8, 7, 0, 0, 28, 8, + 114, 75, 115, 110, 76, 74, 0, 0, 116, 0, + 117, 0, 115, 77, 117, 0, 167, 8, 0, 0, + 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 127, 8, 78, 8, 75, 29, 7, 74, 30, 7, + 74, 120, 128, 121, 37, 78, 135, 122, 132, 123, + 38, 78, 148, 124, 39, 78, 156, 125, 40, 78, + 168, 126, 76, 74, 0, 17, 0, 17, 33, 0, + 0, 0, 31, 129, 130, 74, 0, 131, 0, 130, + 77, 131, 0, 7, 0, 0, 75, 133, 76, 0, + 0, 133, 134, 0, 167, 8, 74, 0, 137, 0, + 136, 110, 0, 138, 0, 136, 77, 138, 0, 0, + 139, 141, 140, 142, 146, 145, 0, 4, 0, 8, + 0, 14, 8, 0, 73, 8, 0, 49, 0, 50, + 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, + 0, 56, 0, 57, 0, 58, 0, 59, 0, 60, + 0, 61, 0, 62, 0, 63, 0, 64, 0, 65, + 0, 66, 0, 67, 0, 69, 0, 68, 0, 70, + 0, 72, 0, 71, 0, 0, 7, 143, 144, 0, + 0, 3, 0, 0, 54, 79, 173, 80, 0, 0, + 31, 79, 173, 80, 0, 0, 81, 147, 0, 4, + 0, 5, 0, 6, 0, 3, 0, 7, 0, 8, + 0, 8, 79, 173, 80, 0, 174, 79, 173, 80, + 0, 82, 147, 0, 79, 173, 80, 0, 150, 0, + 149, 110, 0, 151, 0, 149, 77, 151, 0, 0, + 152, 155, 153, 154, 0, 4, 0, 8, 0, 7, + 0, 36, 0, 34, 0, 35, 0, 17, 0, 0, + 156, 157, 0, 159, 161, 166, 158, 8, 79, 163, + 80, 160, 75, 176, 76, 162, 0, 0, 83, 0, + 0, 33, 0, 0, 20, 0, 0, 23, 0, 0, + 74, 0, 0, 19, 0, 164, 0, 165, 0, 164, + 77, 165, 0, 167, 8, 0, 167, 0, 19, 0, + 174, 0, 8, 0, 14, 8, 0, 167, 84, 0, + 167, 85, 0, 19, 84, 0, 20, 167, 0, 21, + 167, 0, 22, 167, 0, 17, 167, 0, 8, 86, + 167, 87, 0, 0, 168, 170, 0, 0, 78, 8, + 78, 78, 8, 0, 0, 8, 79, 172, 80, 169, + 171, 75, 176, 76, 162, 0, 0, 8, 0, 8, + 8, 0, 4, 0, 5, 0, 6, 0, 3, 0, + 7, 0, 8, 0, 174, 0, 81, 0, 88, 0, + 82, 0, 86, 0, 87, 0, 89, 0, 90, 0, + 85, 0, 84, 0, 91, 0, 92, 0, 93, 0, + 94, 0, 95, 0, 78, 0, 77, 0, 96, 0, + 97, 0, 83, 0, 79, 80, 0, 88, 88, 0, + 82, 82, 0, 82, 87, 0, 78, 78, 0, 85, + 85, 0, 90, 90, 0, 93, 93, 0, 87, 87, + 0, 86, 86, 0, 81, 81, 0, 89, 81, 0, + 87, 81, 0, 86, 81, 0, 85, 81, 0, 90, + 81, 0, 93, 81, 0, 88, 81, 0, 82, 81, + 0, 91, 81, 0, 92, 81, 0, 84, 81, 0, + 87, 87, 81, 0, 86, 86, 81, 0, 79, 173, + 80, 0, 173, 173, 0, 49, 0, 50, 0, 51, + 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, + 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, + 0, 62, 0, 63, 0, 64, 0, 65, 0, 66, + 0, 67, 0, 71, 0, 72, 0, 69, 0, 68, + 0, 70, 0, 20, 0, 22, 0, 4, 0, 5, + 0, 6, 0, 3, 0, 7, 0, 8, 0, 0, + 176, 177, 0, 173, 74, 0, 15, 79, 173, 80, + 75, 176, 76, 0, 16, 175, 78, 0, 75, 176, + 76, 0, 173, 75, 176, 76, 0, 180, 0, 182, + 0, 184, 0, 178, 0, 179, 0, 186, 0, 188, + 0, 189, 0, 194, 0, 191, 0, 197, 0, 198, + 0, 199, 0, 200, 0, 193, 0, 74, 0, 12, + 79, 173, 80, 75, 176, 76, 0, 12, 79, 173, + 80, 75, 176, 76, 13, 177, 0, 0, 10, 79, + 173, 80, 181, 75, 176, 76, 0, 0, 18, 75, + 176, 76, 183, 10, 79, 173, 80, 74, 0, 0, + 11, 79, 173, 74, 173, 74, 173, 80, 185, 75, + 176, 76, 0, 0, 41, 192, 187, 75, 203, 76, + 0, 25, 192, 74, 0, 27, 192, 8, 190, 74, + 0, 0, 8, 0, 26, 196, 79, 195, 80, 8, + 190, 74, 0, 79, 80, 0, 79, 173, 80, 0, + 45, 196, 79, 195, 80, 74, 0, 44, 196, 79, + 195, 80, 74, 0, 173, 0, 0, 8, 0, 8, + 78, 78, 8, 0, 46, 74, 0, 47, 74, 0, + 48, 74, 0, 24, 201, 74, 0, 0, 173, 0, + 42, 79, 172, 80, 78, 75, 176, 76, 162, 0, + 43, 79, 172, 80, 78, 75, 176, 76, 162, 0, + 0, 203, 202, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 246, 256, 259, 264, 265, 266, 276, 277, 281, 282, + 285, 294, 295, 296, 302, 307, 313, 313, 315, 316, + 320, 330, 345, 353, 354, 358, 359, 363, 373, 374, + 378, 379, 393, 398, 402, 403, 409, 412, 413, 478, + 479, 483, 484, 494, 497, 498, 501, 544, 545, 548, + 549, 552, 562, 569, 578, 579, 582, 586, 609, 610, + 613, 618, 623, 628, 633, 638, 643, 648, 653, 658, + 663, 668, 673, 678, 683, 688, 693, 698, 703, 708, + 713, 718, 723, 728, 733, 738, 746, 751, 756, 759, + 764, 767, 771, 774, 779, 801, 810, 810, 810, 810, + 810, 811, 812, 813, 814, 815, 822, 828, 836, 837, + 840, 844, 857, 858, 859, 862, 863, 864, 865, 872, + 873, 877, 896, 897, 901, 902, 912, 913, 916, 917, + 920, 921, 924, 925, 926, 929, 930, 933, 937, 938, + 942, 943, 944, 945, 946, 947, 948, 949, 950, 951, + 952, 960, 961, 965, 966, 972, 1003, 1010, 1013, 1016, + 1022, 1022, 1022, 1022, 1022, 1023, 1024, 1025, 1025, 1025, + 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, 1025, + 1025, 1025, 1025, 1025, 1025, 1025, 1026, 1027, 1028, 1029, + 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, + 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, + 1050, 1051, 1054, 1054, 1054, 1054, 1055, 1055, 1055, 1055, + 1055, 1056, 1056, 1056, 1056, 1056, 1057, 1057, 1057, 1057, + 1057, 1057, 1057, 1058, 1058, 1058, 1059, 1060, 1063, 1063, + 1063, 1063, 1063, 1064, 1071, 1072, 1075, 1076, 1077, 1078, + 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, + 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1100, 1116, 1138, + 1142, 1163, 1168, 1189, 1193, 1206, 1214, 1240, 1264, 1289, + 1292, 1297, 1321, 1324, 1330, 1339, 1351, 1354, 1360, 1363, + 1369, 1375, 1380, 1385, 1399, 1400, 1404, 1413, 1423, 1424 +}; + +static const char * const yytname[] = { "$","error","$undefined.","c_char", +"c_int","c_float","c_bool","c_string","identifier","cppblock","k_while","k_for", +"k_if","k_else","k_enum","k_switch","k_case","k_class","k_do","k_void","k_const", +"k_inline","k_static","k_virtual","k_return","k_autowait","k_autocall","k_waitevent", +"k_event","k_name","k_thumbnail","k_features","k_uses","k_export","k_texture", +"k_sound","k_model","k_properties","k_components","k_functions","k_procedures", +"k_wait","k_on","k_otherwise","k_call","k_jump","k_stop","k_resume","k_pass", +"k_CTString","k_CTStringTrans","k_CTFileName","k_CTFileNameNoDep","k_BOOL","k_COLOR", +"k_FLOAT","k_INDEX","k_RANGE","k_CEntityPointer","k_CModelObject","k_CModelInstance", +"k_CAnimObject","k_CSoundObject","k_CPlacement3D","k_FLOATaabbox3D","k_FLOATmatrix3D", +"k_FLOATquat3D","k_ANGLE","k_FLOAT3D","k_ANGLE3D","k_FLOATplane3D","k_ANIMATION", +"k_ILLUMINATIONTYPE","k_FLAGS","';'","'{'","'}'","','","':'","'('","')'","'='", +"'-'","'~'","'*'","'&'","'<'","'>'","'+'","'!'","'|'","'/'","'%'","'^'","'['", +"']'","'.'","'?'","program","@1","@2","@3","@4","@5","opt_global_cppblock","uses_list", +"uses_statement","enum_and_event_declarations_list","enum_declaration","@6", +"opt_comma","enum_values_list","enum_value","event_declaration","@7","event_members_list", +"non_empty_event_members_list","event_member","opt_class_declaration","class_declaration", +"@8","@9","@10","@11","@12","@13","@14","class_optexport","opt_features","@15", +"features_list","feature","opt_internal_properties","internal_property_list", +"internal_property","property_declaration_list","nonempty_property_declaration_list", +"empty_property_declaration_list","property_declaration","property_id","property_identifier", +"property_type","property_wed_name_opt","property_shortcut_opt","property_color_opt", +"property_flags_opt","property_default_opt","property_default_expression","component_declaration_list", +"nonempty_component_declaration_list","empty_component_declaration_list","component_declaration", +"component_id","component_identifier","component_filename","component_type", +"function_list","function_implementation","opt_tilde","opt_export","opt_const", +"opt_virtual","opt_semicolon","parameters_list","non_void_parameters_list","parameter_declaration", +"return_type","any_type","procedure_list","opt_override","procedure_implementation", +"@16","event_specification","expression","type_keyword","case_constant_expression", +"statements","statement","statement_if","statement_if_else","statement_while", +"@17","statement_dowhile","@18","statement_for","@19","statement_wait","@20", +"statement_autowait","statement_waitevent","opt_eventvar","statement_autocall", +"wait_expression","statement_jump","statement_call","event_expression","jumptarget", +"statement_stop","statement_resume","statement_pass","statement_return","opt_expression", +"handler","handlers_list","" +}; +#endif + +static const short yyr1[] = { 0, + 99, 100, 101, 102, 103, 98, 104, 104, 105, 105, + 106, 107, 107, 107, 109, 108, 110, 110, 111, 111, + 112, 114, 113, 115, 115, 116, 116, 117, 118, 118, + 119, 120, 121, 122, 123, 124, 125, 126, 119, 127, + 127, 128, 129, 128, 130, 130, 131, 132, 132, 133, + 133, 134, 135, 135, 136, 136, 137, 138, 139, 140, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 142, 142, 143, 143, + 144, 144, 145, 145, 146, 146, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 148, 148, 149, 149, + 150, 151, 152, 153, 154, 155, 155, 155, 155, 156, + 156, 157, 158, 158, 159, 159, 160, 160, 161, 161, + 162, 162, 163, 163, 163, 164, 164, 165, 166, 166, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 168, 168, 169, 169, 171, 170, 172, 172, 172, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, + 173, 173, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 175, 175, + 175, 175, 175, 175, 176, 176, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, + 177, 177, 177, 177, 177, 177, 177, 178, 179, 181, + 180, 183, 182, 185, 184, 187, 186, 188, 189, 190, + 190, 191, 192, 192, 193, 194, 195, 195, 196, 196, + 197, 198, 199, 200, 201, 201, 202, 202, 203, 203 +}; + +static const short yyr2[] = { 0, + 0, 0, 0, 0, 0, 11, 0, 1, 0, 2, + 3, 0, 2, 2, 0, 8, 0, 1, 1, 3, + 3, 0, 8, 0, 1, 1, 3, 2, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 34, 1, + 2, 0, 0, 4, 1, 3, 1, 0, 3, 0, + 2, 3, 1, 2, 1, 3, 0, 6, 1, 1, + 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 0, 3, 0, 1, + 0, 4, 0, 4, 0, 2, 1, 1, 1, 1, + 1, 1, 4, 4, 2, 3, 1, 2, 1, 3, + 0, 4, 1, 1, 1, 1, 1, 1, 1, 0, + 2, 13, 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 1, 1, 3, 2, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, + 4, 0, 2, 0, 5, 0, 10, 0, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, + 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 2, 2, 7, 3, 3, + 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 7, 9, 0, + 8, 0, 10, 0, 12, 0, 6, 3, 5, 0, + 1, 8, 2, 3, 6, 6, 1, 0, 1, 4, + 2, 2, 2, 3, 0, 1, 9, 9, 0, 2 +}; + +static const short yydefact[] = { 0, + 1, 7, 8, 2, 9, 3, 0, 12, 10, 0, + 4, 11, 0, 0, 7, 13, 14, 15, 22, 5, + 0, 0, 29, 0, 24, 40, 6, 30, 0, 0, + 17, 19, 142, 0, 0, 0, 237, 0, 238, 213, + 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 235, 234, + 236, 232, 233, 17, 25, 26, 0, 141, 41, 0, + 0, 18, 0, 0, 143, 150, 146, 147, 148, 149, + 18, 0, 28, 144, 145, 0, 21, 20, 0, 0, + 27, 0, 0, 16, 151, 23, 0, 0, 0, 0, + 0, 0, 32, 42, 43, 33, 0, 0, 47, 0, + 45, 0, 44, 0, 57, 46, 59, 34, 17, 53, + 55, 0, 48, 18, 54, 0, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + 77, 78, 79, 80, 81, 83, 82, 84, 86, 85, + 0, 0, 50, 35, 56, 61, 62, 60, 87, 0, + 0, 89, 95, 49, 51, 0, 0, 90, 91, 0, + 93, 0, 111, 0, 88, 100, 97, 98, 99, 101, + 102, 237, 238, 0, 0, 96, 0, 0, 58, 52, + 113, 36, 17, 107, 109, 0, 0, 0, 164, 161, + 162, 163, 165, 166, 183, 182, 0, 168, 170, 186, + 176, 175, 171, 172, 169, 173, 174, 177, 178, 179, + 180, 181, 184, 185, 0, 167, 105, 0, 0, 0, + 18, 108, 119, 117, 118, 116, 0, 0, 0, 191, + 187, 0, 197, 205, 189, 190, 208, 201, 192, 200, + 196, 199, 195, 204, 188, 198, 202, 193, 206, 207, + 203, 194, 106, 212, 0, 0, 0, 110, 114, 0, + 92, 103, 211, 210, 209, 104, 94, 120, 115, 112, + 125, 126, 0, 121, 129, 0, 130, 0, 152, 140, + 123, 139, 38, 124, 0, 0, 0, 153, 0, 158, + 0, 133, 159, 0, 39, 134, 0, 135, 136, 0, + 160, 154, 127, 0, 138, 0, 156, 128, 0, 137, + 0, 0, 245, 0, 245, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 295, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 267, 245, 131, 0, 246, 255, + 256, 252, 253, 254, 257, 258, 259, 261, 266, 260, + 262, 263, 264, 265, 155, 131, 0, 0, 0, 0, + 242, 239, 240, 241, 243, 244, 0, 245, 296, 0, + 0, 0, 289, 0, 0, 276, 0, 0, 291, 292, + 293, 0, 132, 122, 247, 245, 157, 0, 0, 0, + 0, 249, 0, 294, 283, 0, 278, 0, 288, 280, + 0, 288, 288, 250, 0, 270, 0, 0, 0, 272, + 284, 0, 287, 0, 281, 0, 299, 0, 0, 251, + 0, 0, 245, 245, 0, 290, 0, 279, 0, 0, + 0, 245, 0, 0, 0, 0, 280, 0, 0, 277, + 300, 286, 285, 0, 0, 268, 248, 0, 0, 158, + 158, 271, 274, 0, 0, 282, 0, 0, 0, 269, + 0, 0, 0, 245, 273, 0, 0, 0, 245, 245, + 275, 0, 0, 131, 131, 297, 298, 0, 0, 0 +}; + +static const short yydefgoto[] = { 488, + 2, 5, 8, 15, 23, 4, 6, 9, 11, 16, + 21, 73, 31, 32, 17, 22, 64, 65, 66, 27, + 28, 104, 108, 123, 161, 230, 283, 297, 29, 106, + 107, 110, 111, 154, 160, 165, 118, 119, 120, 121, + 122, 159, 152, 163, 169, 175, 189, 171, 186, 192, + 193, 194, 195, 196, 270, 280, 237, 281, 284, 295, + 285, 319, 288, 394, 307, 308, 309, 291, 67, 293, + 317, 298, 322, 304, 264, 226, 377, 326, 349, 350, + 351, 352, 431, 353, 435, 354, 469, 355, 411, 356, + 357, 426, 358, 382, 359, 360, 424, 384, 361, 362, + 363, 364, 380, 451, 439 +}; + +static const short yypact[] = { -3, +-32768, 0,-32768,-32768,-32768, -13, 44,-32768,-32768, -1, + -2,-32768, 102, 111, 0,-32768,-32768,-32768,-32768,-32768, + 50, 51, 113, 127, 3207, 99,-32768,-32768, 125, 126, + 58,-32768, 52, 129, 3207, 55, 3207, 3207, 3207,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768, 63,-32768,-32768, 17,-32768,-32768, 67, + 134, 127, 70, 3207,-32768, 15,-32768, 15, 15, 15, + 3207, 71,-32768,-32768,-32768, 140,-32768,-32768, 75, 22, +-32768, 76, 79,-32768,-32768,-32768, 130, 148, 82, 131, + 153, 88,-32768, 132,-32768,-32768, 157, 128,-32768, -35, +-32768, 89,-32768, 157, 162,-32768,-32768,-32768, 92,-32768, +-32768, 3320, 95, 162,-32768, 163,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + 164, 165,-32768,-32768,-32768,-32768,-32768,-32768, 167, 3142, + 137, 173, 96,-32768,-32768, 19, 100,-32768, 133, 26, + 149, 105, 177, 103,-32768,-32768,-32768,-32768,-32768,-32768, + 109,-32768,-32768, 3052, 26,-32768, 110, 112,-32768,-32768, +-32768,-32768, 115,-32768,-32768, 18, 3052, 3052,-32768,-32768, +-32768,-32768,-32768,-32768,-32768, 116, 1532, 114, -21,-32768, + 117, -22, -31, -70, -45, 118, -43, 119, 120, -53, +-32768,-32768,-32768,-32768, 1627,-32768,-32768, 3052, 3052, 151, + 177,-32768,-32768,-32768,-32768,-32768, 185, 1722, 1817,-32768, +-32768, 1912,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + 121,-32768, 122,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768, 3052, 2007, 2102, 135,-32768,-32768, 189, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + 25,-32768, 166,-32768, 181, 136,-32768, 3231,-32768, 55, + 124, 15, 197,-32768, 201, 138, 139,-32768, 141, 202, + 142, 3296, 203, 143,-32768, 55, 144, 145,-32768, 29, +-32768, 152, 192, 3207,-32768, 210,-32768,-32768, 146,-32768, + 154, 159,-32768, 158,-32768, 297, 218, 392, 156, 160, + 161, 168, 64, 169, 3052, 170, 219, 170, 170, 219, + 219, 171, 172, 174,-32768,-32768, 176, 1437,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768, 176, 3052, 3052, 3052, 3052, +-32768,-32768,-32768,-32768,-32768,-32768, 175,-32768, 3052, 178, + 2197, 180, 179, 183, 229,-32768, 184, 186,-32768,-32768, +-32768, 487,-32768,-32768,-32768,-32768,-32768, 2292, 2387, 2482, + 2577,-32768, 582,-32768,-32768, 2672,-32768, 188, 3052, 230, + 193, 3052, 3052,-32768, 677,-32768, 3052, 198, 200,-32768, +-32768, 233, 3052, 187,-32768, 182,-32768, 196, 199,-32768, + 207, 2767,-32768,-32768, 232,-32768, 235,-32768, -27, 190, + 204,-32768, 3052, 772, 867, 205, 230, 208, 209,-32768, +-32768,-32768,-32768, 962, 2862, 238,-32768, 3052, 212, 202, + 202,-32768,-32768, 1342, 2957,-32768, 211, 213, 214,-32768, + 216, 194, 217,-32768,-32768, 221, 231, 1057,-32768,-32768, +-32768, 1152, 1247, 176, 176,-32768,-32768, 258, 277,-32768 +}; + +static const short yypgoto[] = {-32768, +-32768,-32768,-32768,-32768,-32768, 268,-32768,-32768,-32768,-32768, +-32768, -57,-32768, 220,-32768,-32768,-32768,-32768, 237,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768, 206,-32768,-32768,-32768,-32768,-32768,-32768, 215, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 147,-32768, +-32768,-32768, 80,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768,-32768,-32768, -356,-32768,-32768, -4,-32768, -33,-32768, +-32768,-32768,-32768, -345, -184, -17,-32768, -322, -150,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768, -131,-32768, -221,-32768,-32768, -291, -217,-32768,-32768, +-32768,-32768,-32768,-32768,-32768 +}; + + +#define YYLAST 3393 + + +static const short yytable[] = { 225, + 1, 76, 328, 78, 79, 80, 82, 68, 3, 397, + 252, 13, 238, 239, 448, 449, 253, 68, 7, 68, + 68, 68, 242, 392, 83, 14, 172, 261, 176, 177, + 178, 179, 180, 181, 233, 254, 315, 257, 113, 262, + 90, 114, 255, 265, 266, 182, 258, 183, 450, 250, + 10, 234, 235, 236, 251, 403, 68, 282, 248, 244, + 245, 125, 249, 68, -37, 246, 371, 372, 373, 374, + 375, 376, 12, 415, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 84, 85, + 84, 85, 84, 85, 184, 84, 85, 185, 95, 18, + 444, 445, 84, 85, 467, 468, 385, 386, 19, 454, + 428, 429, 387, 388, 24, 25, 166, 486, 487, 26, + 30, 69, 70, 71, 72, 232, 75, 74, 77, 81, + 87, 348, 68, 348, 86, 89, 92, 93, 94, 96, + 379, 478, 187, 97, 99, 100, 482, 483, 98, 102, + 101, 103, 105, 109, 112, 117, 115, 187, 124, 153, + 156, 157, 158, 162, 167, 168, 170, 173, 190, 188, + 191, 197, 398, 399, 400, 401, 174, 198, 228, 267, + 229, 231, 269, 240, 243, 279, 406, 247, 256, 259, + 260, 274, 275, 287, 296, 286, 294, 348, 299, 303, + 311, 318, 278, 289, 301, 305, 300, 321, 348, 302, + 323, 314, 312, 313, 423, 365, 383, 423, 423, 316, + 348, 324, 432, 325, 367, 327, 410, 425, 368, 369, + 436, 446, 447, 378, 389, 390, 370, 391, 381, 393, + 464, 404, 402, 407, 292, 438, 408, 489, 455, 348, + 348, 409, 412, 452, 413, 422, 437, 427, 310, 348, + 68, 476, 433, 465, 434, 440, 490, 453, 441, 348, + 310, 442, 20, 458, 68, 466, 460, 461, 474, 475, + 472, 88, 473, 348, 477, 479, 68, 348, 348, 199, + 200, 201, 202, 203, 204, 480, 329, 330, 331, 320, + 268, 332, 333, 470, 334, 459, 182, 91, 183, 116, + 335, 336, 337, 338, 0, 0, 0, 0, 0, 0, + 0, 227, 0, 0, 0, 0, 0, 339, 155, 0, + 340, 341, 342, 343, 344, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 345, 346, 347, 205, 206, 207, 0, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 329, 330, 331, 0, 0, 332, 333, 0, 334, + 0, 182, 0, 183, 0, 335, 336, 337, 338, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 339, 0, 0, 340, 341, 342, 343, 344, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 345, 346, 366, 205, 206, + 207, 0, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 329, 330, 331, 0, + 0, 332, 333, 0, 334, 0, 182, 0, 183, 0, + 335, 336, 337, 338, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, + 340, 341, 342, 343, 344, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 345, 346, 414, 205, 206, 207, 0, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 329, 330, 331, 0, 0, 332, 333, 0, 334, + 0, 182, 0, 183, 0, 335, 336, 337, 338, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 339, 0, 0, 340, 341, 342, 343, 344, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 345, 346, 420, 205, 206, + 207, 0, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 329, 330, 331, 0, + 0, 332, 333, 0, 334, 0, 182, 0, 183, 0, + 335, 336, 337, 338, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, + 340, 341, 342, 343, 344, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 345, 346, 430, 205, 206, 207, 0, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 329, 330, 331, 0, 0, 332, 333, 0, 334, + 0, 182, 0, 183, 0, 335, 336, 337, 338, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 339, 0, 0, 340, 341, 342, 343, 344, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 345, 346, 456, 205, 206, + 207, 0, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 329, 330, 331, 0, + 0, 332, 333, 0, 334, 0, 182, 0, 183, 0, + 335, 336, 337, 338, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, + 340, 341, 342, 343, 344, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 345, 346, 457, 205, 206, 207, 0, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 329, 330, 331, 0, 0, 332, 333, 0, 334, + 0, 182, 0, 183, 0, 335, 336, 337, 338, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 339, 0, 0, 340, 341, 342, 343, 344, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 345, 346, 462, 205, 206, + 207, 0, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 329, 330, 331, 0, + 0, 332, 333, 0, 334, 0, 182, 0, 183, 0, + 335, 336, 337, 338, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, + 340, 341, 342, 343, 344, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 345, 346, 481, 205, 206, 207, 0, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 329, 330, 331, 0, 0, 332, 333, 0, 334, + 0, 182, 0, 183, 0, 335, 336, 337, 338, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 339, 0, 0, 340, 341, 342, 343, 344, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 345, 346, 484, 205, 206, + 207, 0, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 329, 330, 331, 0, + 0, 332, 333, 0, 334, 0, 182, 0, 183, 0, + 335, 336, 337, 338, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 339, 0, 0, + 340, 341, 342, 343, 344, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 345, 346, 485, 205, 206, 207, 0, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 329, 330, 331, 0, 0, 332, 333, 0, 334, + 0, 182, 0, 183, 0, 335, 336, 337, 338, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 339, 0, 0, 340, 341, 342, 343, 344, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 345, 346, 0, 205, 206, + 207, 0, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 182, 0, 183, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 395, 396, 0, 205, 206, 207, 0, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 182, 0, 183, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 0, 0, 0, 205, 206, + 207, 241, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 182, 0, 183, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 0, 0, 0, 205, 206, 207, 263, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 182, 0, 183, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 0, 0, 0, 205, 206, + 207, 271, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 182, 0, 183, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 0, 0, 0, 205, 206, 207, 272, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 182, 0, 183, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 0, 0, 0, 205, 206, + 207, 273, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 182, 0, 183, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 0, 0, 0, 205, 206, 207, 276, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 182, 0, 183, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 0, 0, 0, 205, 206, + 207, 277, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 182, 0, 183, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 0, 0, 0, 205, 206, 207, 405, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 182, 0, 183, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 0, 0, 0, 205, 206, + 207, 416, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 182, 0, 183, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 417, 0, 0, 205, 206, 207, 0, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 182, 0, 183, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 0, 0, 0, 205, 206, + 207, 418, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 182, 0, 183, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 0, 0, 0, 205, 206, 207, 419, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 182, 0, 183, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 0, 0, 0, 205, 206, + 207, 421, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 182, 0, 183, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 443, 0, 0, 205, 206, 207, 0, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 182, 0, 183, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 0, 0, 0, 205, 206, + 207, 463, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 199, + 200, 201, 202, 203, 204, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 182, 0, 183, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 0, 0, 0, 205, 206, 207, 471, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 199, 200, 201, 202, 203, 204, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 182, 0, 183, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 0, 0, 0, 0, 205, 206, + 207, 0, 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, 224, 33, + 0, 0, 0, 0, 0, 34, 0, 0, 35, 0, + 36, 37, 38, 39, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 33, 0, 0, 164, 0, 0, + 34, 0, 0, 35, 0, 36, 37, 38, 39, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 0, 0, 34, 0, 0, 35, 0, 290, + 37, 38, 39, 0, 0, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 33, 0, 0, 0, 0, 0, 34, + 0, 0, 35, 0, 306, 37, 38, 39, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 126, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, + 149, 150, 151 +}; + +static const short yycheck[] = { 184, + 4, 35, 325, 37, 38, 39, 64, 25, 9, 366, + 81, 14, 197, 198, 42, 43, 87, 35, 32, 37, + 38, 39, 207, 346, 8, 28, 8, 81, 3, 4, + 5, 6, 7, 8, 17, 81, 8, 81, 74, 93, + 74, 77, 88, 228, 229, 20, 90, 22, 76, 81, + 7, 34, 35, 36, 86, 378, 74, 33, 81, 81, + 82, 119, 85, 81, 40, 87, 3, 4, 5, 6, + 7, 8, 74, 396, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 84, 85, + 84, 85, 84, 85, 79, 84, 85, 82, 87, 8, + 433, 434, 84, 85, 460, 461, 338, 339, 8, 442, + 412, 413, 340, 341, 75, 75, 160, 484, 485, 17, + 4, 33, 8, 8, 77, 193, 8, 86, 84, 77, + 7, 326, 160, 328, 78, 76, 76, 8, 74, 74, + 335, 474, 170, 75, 7, 74, 479, 480, 29, 7, + 30, 74, 31, 7, 37, 4, 78, 185, 77, 75, + 8, 8, 8, 7, 38, 3, 81, 78, 74, 31, + 4, 79, 367, 368, 369, 370, 54, 79, 79, 39, + 79, 77, 8, 78, 81, 7, 381, 81, 81, 81, + 81, 81, 81, 23, 8, 40, 83, 392, 8, 8, + 8, 20, 78, 78, 76, 74, 79, 8, 403, 79, + 75, 77, 80, 80, 409, 8, 8, 412, 413, 78, + 415, 78, 417, 75, 79, 78, 8, 8, 79, 79, + 8, 10, 8, 75, 74, 74, 79, 74, 79, 74, + 13, 74, 78, 74, 288, 74, 78, 0, 443, 444, + 445, 79, 79, 74, 79, 78, 80, 75, 302, 454, + 288, 78, 75, 458, 75, 80, 0, 74, 80, 464, + 314, 75, 15, 79, 302, 74, 79, 79, 75, 74, + 80, 72, 80, 478, 78, 75, 314, 482, 483, 3, + 4, 5, 6, 7, 8, 75, 10, 11, 12, 314, + 231, 15, 16, 464, 18, 447, 20, 81, 22, 114, + 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, + -1, 185, -1, -1, -1, -1, -1, 41, 124, -1, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + 74, 75, 76, 77, 78, 79, -1, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, 10, 11, 12, -1, -1, 15, 16, -1, 18, + -1, 20, -1, 22, -1, 24, 25, 26, 27, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 41, -1, -1, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, 74, 75, 76, 77, 78, + 79, -1, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, 10, 11, 12, -1, + -1, 15, 16, -1, 18, -1, 20, -1, 22, -1, + 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + 74, 75, 76, 77, 78, 79, -1, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, 10, 11, 12, -1, -1, 15, 16, -1, 18, + -1, 20, -1, 22, -1, 24, 25, 26, 27, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 41, -1, -1, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, 74, 75, 76, 77, 78, + 79, -1, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, 10, 11, 12, -1, + -1, 15, 16, -1, 18, -1, 20, -1, 22, -1, + 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + 74, 75, 76, 77, 78, 79, -1, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, 10, 11, 12, -1, -1, 15, 16, -1, 18, + -1, 20, -1, 22, -1, 24, 25, 26, 27, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 41, -1, -1, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, 74, 75, 76, 77, 78, + 79, -1, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, 10, 11, 12, -1, + -1, 15, 16, -1, 18, -1, 20, -1, 22, -1, + 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + 74, 75, 76, 77, 78, 79, -1, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, 10, 11, 12, -1, -1, 15, 16, -1, 18, + -1, 20, -1, 22, -1, 24, 25, 26, 27, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 41, -1, -1, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, 74, 75, 76, 77, 78, + 79, -1, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, 10, 11, 12, -1, + -1, 15, 16, -1, 18, -1, 20, -1, 22, -1, + 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + 74, 75, 76, 77, 78, 79, -1, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, 10, 11, 12, -1, -1, 15, 16, -1, 18, + -1, 20, -1, 22, -1, 24, 25, 26, 27, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 41, -1, -1, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, 74, 75, 76, 77, 78, + 79, -1, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, 10, 11, 12, -1, + -1, 15, 16, -1, 18, -1, 20, -1, 22, -1, + 24, 25, 26, 27, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + 74, 75, 76, 77, 78, 79, -1, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, 10, 11, 12, -1, -1, 15, 16, -1, 18, + -1, 20, -1, 22, -1, 24, 25, 26, 27, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 41, -1, -1, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, 74, 75, -1, 77, 78, + 79, -1, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + 74, 75, -1, 77, 78, 79, -1, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 20, -1, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, -1, -1, -1, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 20, -1, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, -1, -1, -1, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 20, -1, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, -1, -1, -1, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 20, -1, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, -1, -1, -1, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 20, -1, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, -1, -1, -1, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + 74, -1, -1, 77, 78, 79, -1, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 20, -1, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, -1, -1, -1, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 20, -1, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, -1, -1, -1, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + 74, -1, -1, 77, 78, 79, -1, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 20, -1, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, -1, -1, -1, 77, 78, + 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 3, + 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, -1, + -1, -1, -1, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + 94, 95, 96, 97, 3, 4, 5, 6, 7, 8, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 20, -1, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, -1, -1, -1, -1, 77, 78, + 79, -1, 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, 97, 8, + -1, -1, -1, -1, -1, 14, -1, -1, 17, -1, + 19, 20, 21, 22, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 8, -1, -1, 76, -1, -1, + 14, -1, -1, 17, -1, 19, 20, 21, 22, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 8, -1, + -1, -1, -1, -1, 14, -1, -1, 17, -1, 19, + 20, 21, 22, -1, -1, 49, 50, 51, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + 70, 71, 72, 8, -1, -1, -1, -1, -1, 14, + -1, -1, 17, -1, 19, 20, 21, 22, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 14, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#undef YYERROR_VERBOSE +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 192 "bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +int +yyparse(YYPARSE_PARAM) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 1: +#line 246 "ecc/parser.y" +{ + int iID = atoi(yyvsp[0].strString); + if(iID>32767) { + yyerror("Maximum allowed id for entity source file is 32767"); + } + _iCurrentClassID = iID; + _iNextFreeID = iID<<16; + fprintf(_fDeclaration, "#ifndef _%s_INCLUDED\n", _strFileNameBaseIdentifier); + fprintf(_fDeclaration, "#define _%s_INCLUDED 1\n", _strFileNameBaseIdentifier); + + ; + break;} +case 2: +#line 256 "ecc/parser.y" +{ + + //fprintf(_fImplementation, "\n#undef DECL_DLL\n#define DECL_DLL _declspec(dllimport)\n"); + ; + break;} +case 3: +#line 259 "ecc/parser.y" +{ + //fprintf(_fImplementation, "\n#undef DECL_DLL\n#define DECL_DLL _declspec(dllexport)\n"); + + fprintf(_fImplementation, "#include <%s.h>\n", _strFileNameBase); + fprintf(_fImplementation, "#include <%s_tables.h>\n", _strFileNameBase); + ; + break;} +case 4: +#line 264 "ecc/parser.y" +{ + ; + break;} +case 5: +#line 265 "ecc/parser.y" +{ + ; + break;} +case 6: +#line 266 "ecc/parser.y" +{ + fprintf(_fDeclaration, "#endif // _%s_INCLUDED\n", _strFileNameBaseIdentifier); + ; + break;} +case 8: +#line 277 "ecc/parser.y" +{ fprintf(_fImplementation, "%s\n", yyvsp[0].strString); ; + break;} +case 11: +#line 285 "ecc/parser.y" +{ + char *strUsedFileName = strdup(yyvsp[-1].strString); + strUsedFileName[strlen(strUsedFileName)-1] = 0; + fprintf(_fDeclaration, "#include <%s.h>\n", strUsedFileName+1); + ; + break;} +case 15: +#line 302 "ecc/parser.y" +{ + _strCurrentEnum = yyvsp[0].strString; + fprintf(_fTables, "EP_ENUMBEG(%s)\n", _strCurrentEnum ); + fprintf(_fDeclaration, "extern DECL_DLL CEntityPropertyEnumType %s_enum;\n", _strCurrentEnum ); + fprintf(_fDeclaration, "enum %s {\n", _strCurrentEnum ); + ; + break;} +case 16: +#line 307 "ecc/parser.y" +{ + fprintf(_fTables, "EP_ENUMEND(%s);\n\n", _strCurrentEnum); + fprintf(_fDeclaration, "};\n"); + fprintf(_fDeclaration, "DECL_DLL inline void ClearToDefault(%s &e) { e = (%s)0; } ;\n", _strCurrentEnum, _strCurrentEnum); + ; + break;} +case 21: +#line 320 "ecc/parser.y" +{ + fprintf(_fTables, " EP_ENUMVALUE(%s, %s),\n", yyvsp[-1].strString, yyvsp[0].strString); + fprintf(_fDeclaration, " %s = %s,\n", yyvsp[-1].strString, yyvsp[-2].strString); + ; + break;} +case 22: +#line 330 "ecc/parser.y" +{ + _strCurrentEvent = yyvsp[0].strString; + int iID = CreateID(); + fprintf(_fDeclaration, "#define EVENTCODE_%s 0x%08x\n", _strCurrentEvent, iID); + fprintf(_fDeclaration, "class DECL_DLL %s : public CEntityEvent {\npublic:\n", + _strCurrentEvent); + fprintf(_fDeclaration, "%s();\n", _strCurrentEvent ); + fprintf(_fDeclaration, "CEntityEvent *MakeCopy(void);\n"); + fprintf(_fImplementation, + "CEntityEvent *%s::MakeCopy(void) { " + "CEntityEvent *peeCopy = new %s(*this); " + "return peeCopy;}\n", + _strCurrentEvent, _strCurrentEvent); + fprintf(_fImplementation, "%s::%s() : CEntityEvent(EVENTCODE_%s) {;\n", + _strCurrentEvent, _strCurrentEvent, _strCurrentEvent); + ; + break;} +case 23: +#line 345 "ecc/parser.y" +{ + fprintf(_fImplementation, "};\n"); + fprintf(_fDeclaration, "};\n"); + fprintf(_fDeclaration, "DECL_DLL inline void ClearToDefault(%s &e) { e = %s(); } ;\n", _strCurrentEvent, _strCurrentEvent); + ; + break;} +case 28: +#line 363 "ecc/parser.y" +{ + fprintf(_fDeclaration, "%s %s;\n", yyvsp[-1].strString, yyvsp[0].strString); + fprintf(_fImplementation, " ClearToDefault(%s);\n", yyvsp[0].strString); + ; + break;} +case 32: +#line 381 "ecc/parser.y" +{ + _strCurrentClass = yyvsp[-9].strString; + _strCurrentBase = yyvsp[-7].strString; + _strCurrentDescription = yyvsp[-4].strString; + _strCurrentThumbnail = yyvsp[-1].strString; + + fprintf(_fTables, "#define ENTITYCLASS %s\n\n", _strCurrentClass); + fprintf(_fDeclaration, "extern \"C\" DECL_DLL CDLLEntityClass %s_DLLClass;\n", + _strCurrentClass); + fprintf(_fDeclaration, "%s %s : public %s {\npublic:\n", + yyvsp[-10].strString, _strCurrentClass, _strCurrentBase); + + ; + break;} +case 33: +#line 393 "ecc/parser.y" +{ + fprintf(_fDeclaration, " %s virtual void SetDefaultProperties(void);\n", _bClassIsExported?"":"DECL_DLL"); + fprintf(_fImplementation, "void %s::SetDefaultProperties(void) {\n", _strCurrentClass); + fprintf(_fTables, "CEntityProperty %s_properties[] = {\n", _strCurrentClass); + + ; + break;} +case 34: +#line 398 "ecc/parser.y" +{ + fprintf(_fImplementation, " %s::SetDefaultProperties();\n}\n", _strCurrentBase); + + fprintf(_fTables, "CEntityComponent %s_components[] = {\n", _strCurrentClass); + ; + break;} +case 35: +#line 402 "ecc/parser.y" +{ + ; + break;} +case 36: +#line 403 "ecc/parser.y" +{ + _bTrackLineInformation = 1; + fprintf(_fTables, "CEventHandlerEntry %s_handlers[] = {\n", _strCurrentClass); + + _bInProcedure = 0; + _bInHandler = 0; + ; + break;} +case 37: +#line 409 "ecc/parser.y" +{ + + _bInProcedure = 1; + ; + break;} +case 38: +#line 412 "ecc/parser.y" +{ + ; + break;} +case 39: +#line 413 "ecc/parser.y" +{ + fprintf(_fTables, "};\n#define %s_handlersct ARRAYCOUNT(%s_handlers)\n", + _strCurrentClass, _strCurrentClass); + fprintf(_fTables, "\n"); + + if (_bFeature_AbstractBaseClass) { + fprintf(_fTables, "CEntity *%s_New(void) { return NULL; };\n", + _strCurrentClass); + } else { + fprintf(_fTables, "CEntity *%s_New(void) { return new %s; };\n", + _strCurrentClass, _strCurrentClass); + } + + if (!_bFeature_ImplementsOnInitClass) { + fprintf(_fTables, "void %s_OnInitClass(void) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnInitClass(void);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnEndClass) { + fprintf(_fTables, "void %s_OnEndClass(void) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnEndClass(void);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnPrecache) { + fprintf(_fTables, "void %s_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnPrecache(CDLLEntityClass *pdec, INDEX iUser);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnWorldEnd) { + fprintf(_fTables, "void %s_OnWorldEnd(CWorld *pwo) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnWorldEnd(CWorld *pwo);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnWorldInit) { + fprintf(_fTables, "void %s_OnWorldInit(CWorld *pwo) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnWorldInit(CWorld *pwo);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnWorldTick) { + fprintf(_fTables, "void %s_OnWorldTick(CWorld *pwo) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnWorldTick(CWorld *pwo);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnWorldRender) { + fprintf(_fTables, "void %s_OnWorldRender(CWorld *pwo) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnWorldRender(CWorld *pwo);\n", _strCurrentClass); + } + + fprintf(_fTables, "ENTITY_CLASSDEFINITION(%s, %s, %s, %s, 0x%08x);\n", + _strCurrentClass, _strCurrentBase, + _strCurrentDescription, _strCurrentThumbnail, _iCurrentClassID); + fprintf(_fTables, "DECLARE_CTFILENAME(_fnm%s_tbn, %s);\n", _strCurrentClass, _strCurrentThumbnail); + + fprintf(_fDeclaration, "};\n"); + ; + break;} +case 40: +#line 478 "ecc/parser.y" +{ yyval = yyvsp[0]; _bClassIsExported = 0; ; + break;} +case 41: +#line 479 "ecc/parser.y" +{ yyval = yyvsp[-1]+" DECL_DLL "; _bClassIsExported = 1; ; + break;} +case 43: +#line 484 "ecc/parser.y" +{ + _bFeature_ImplementsOnWorldInit = 0; + _bFeature_ImplementsOnWorldEnd = 0; + _bFeature_ImplementsOnWorldTick = 0; + _bFeature_ImplementsOnWorldRender = 0; + _bFeature_ImplementsOnInitClass = 0; + _bFeature_ImplementsOnEndClass = 0; + _bFeature_ImplementsOnPrecache = 0; + _bFeature_AbstractBaseClass = 0; + _bFeature_CanBePredictable = 0; + ; + break;} +case 47: +#line 501 "ecc/parser.y" +{ + if (strcmp(yyvsp[0].strString, "\"AbstractBaseClass\"")==0) { + _bFeature_AbstractBaseClass = 1; + } else if (strcmp(yyvsp[0].strString, "\"IsTargetable\"")==0) { + fprintf(_fDeclaration, "virtual BOOL IsTargetable(void) const { return TRUE; };\n"); + } else if (strcmp(yyvsp[0].strString, "\"IsImportant\"")==0) { + fprintf(_fDeclaration, "virtual BOOL IsImportant(void) const { return TRUE; };\n"); + } else if (strcmp(yyvsp[0].strString, "\"HasName\"")==0) { + fprintf(_fDeclaration, + "virtual const CTString &GetName(void) const { return m_strName; };\n"); + } else if (strcmp(yyvsp[0].strString, "\"CanBePredictable\"")==0) { + fprintf(_fDeclaration, + "virtual CEntity *GetPredictionPair(void) { return m_penPrediction; };\n"); + fprintf(_fDeclaration, + "virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; };\n"); + _bFeature_CanBePredictable = 1; + } else if (strcmp(yyvsp[0].strString, "\"HasDescription\"")==0) { + fprintf(_fDeclaration, + "virtual const CTString &GetDescription(void) const { return m_strDescription; };\n"); + } else if (strcmp(yyvsp[0].strString, "\"HasTarget\"")==0) { + fprintf(_fDeclaration, + "virtual CEntity *GetTarget(void) const { return m_penTarget; };\n"); + } else if (strcmp(yyvsp[0].strString, "\"ImplementsOnInitClass\"")==0) { + _bFeature_ImplementsOnInitClass = 1; + } else if (strcmp(yyvsp[0].strString, "\"ImplementsOnEndClass\"")==0) { + _bFeature_ImplementsOnEndClass = 1; + } else if (strcmp(yyvsp[0].strString, "\"ImplementsOnPrecache\"")==0) { + _bFeature_ImplementsOnPrecache = 1; + } else if (strcmp(yyvsp[0].strString, "\"ImplementsOnWorldInit\"")==0) { + _bFeature_ImplementsOnWorldInit = 1; + } else if (strcmp(yyvsp[0].strString, "\"ImplementsOnWorldEnd\"")==0) { + _bFeature_ImplementsOnWorldEnd = 1; + } else if (strcmp(yyvsp[0].strString, "\"ImplementsOnWorldTick\"")==0) { + _bFeature_ImplementsOnWorldTick = 1; + } else if (strcmp(yyvsp[0].strString, "\"ImplementsOnWorldRender\"")==0) { + _bFeature_ImplementsOnWorldRender = 1; + } else { + yyerror((SType("Unknown feature: ")+yyvsp[0]).strString); + } + ; + break;} +case 52: +#line 552 "ecc/parser.y" +{ + fprintf(_fDeclaration, "%s %s;\n", yyvsp[-2].strString, yyvsp[-1].strString); + ; + break;} +case 53: +#line 562 "ecc/parser.y" +{ + DeclareFeatureProperties(); // this won't work, but at least it will generate an error!!!! + fprintf(_fTables, " CEntityProperty()\n};\n"); + fprintf(_fTables, "#define %s_propertiesct 0\n", _strCurrentClass); + fprintf(_fTables, "\n"); + fprintf(_fTables, "\n"); + ; + break;} +case 54: +#line 569 "ecc/parser.y" +{ + DeclareFeatureProperties(); + fprintf(_fTables, "};\n"); + fprintf(_fTables, "#define %s_propertiesct ARRAYCOUNT(%s_properties)\n", + _strCurrentClass, _strCurrentClass); + fprintf(_fTables, "\n"); + ; + break;} +case 58: +#line 586 "ecc/parser.y" +{ + fprintf(_fTables, " CEntityProperty(%s, %s, (0x%08x<<8)+%s, offsetof(%s, %s), %s, %s, %s, %s),\n", + _strCurrentPropertyPropertyType, + _strCurrentPropertyEnumType, + _iCurrentClassID, + _strCurrentPropertyID, + _strCurrentClass, + _strCurrentPropertyIdentifier, + _strCurrentPropertyName, + _strCurrentPropertyShortcut, + _strCurrentPropertyColor, + _strCurrentPropertyFlags); + fprintf(_fDeclaration, " %s %s;\n", + _strCurrentPropertyDataType, + _strCurrentPropertyIdentifier + ); + + if (strlen(_strCurrentPropertyDefaultCode)>0) { + fprintf(_fImplementation, " %s\n", _strCurrentPropertyDefaultCode); + } + ; + break;} +case 59: +#line 609 "ecc/parser.y" +{ _strCurrentPropertyID = yyvsp[0].strString; ; + break;} +case 60: +#line 610 "ecc/parser.y" +{ _strCurrentPropertyIdentifier = yyvsp[0].strString; ; + break;} +case 61: +#line 613 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ENUM"; + _strCurrentPropertyEnumType = (SType("&")+yyvsp[0]+"_enum").strString; + _strCurrentPropertyDataType = (SType("enum ")+yyvsp[0].strString).strString; + ; + break;} +case 62: +#line 618 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLAGS"; + _strCurrentPropertyEnumType = (SType("&")+yyvsp[0]+"_enum").strString; + _strCurrentPropertyDataType = "ULONG"; + ; + break;} +case 63: +#line 623 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_STRING"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CTString"; + ; + break;} +case 64: +#line 628 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_STRINGTRANS"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CTStringTrans"; + ; + break;} +case 65: +#line 633 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FILENAME"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CTFileName"; + ; + break;} +case 66: +#line 638 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FILENAMENODEP"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CTFileNameNoDep"; + ; + break;} +case 67: +#line 643 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_BOOL"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "BOOL"; + ; + break;} +case 68: +#line 648 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_COLOR"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "COLOR"; + ; + break;} +case 69: +#line 653 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOAT"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOAT"; + ; + break;} +case 70: +#line 658 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_INDEX"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "INDEX"; + ; + break;} +case 71: +#line 663 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_RANGE"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "RANGE"; + ; + break;} +case 72: +#line 668 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ENTITYPTR"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CEntityPointer"; + ; + break;} +case 73: +#line 673 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_MODELOBJECT"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CModelObject"; + ; + break;} +case 74: +#line 678 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_MODELINSTANCE"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CModelInstance"; + ; + break;} +case 75: +#line 683 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ANIMOBJECT"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CAnimObject"; + ; + break;} +case 76: +#line 688 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_SOUNDOBJECT"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CSoundObject"; + ; + break;} +case 77: +#line 693 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_PLACEMENT3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CPlacement3D"; + ; + break;} +case 78: +#line 698 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOATAABBOX3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOATaabbox3D"; + ; + break;} +case 79: +#line 703 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOATMATRIX3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOATmatrix3D"; + ; + break;} +case 80: +#line 708 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOATQUAT3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOATquat3D"; + ; + break;} +case 81: +#line 713 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ANGLE"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "ANGLE"; + ; + break;} +case 82: +#line 718 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ANGLE3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "ANGLE3D"; + ; + break;} +case 83: +#line 723 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOAT3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOAT3D"; + ; + break;} +case 84: +#line 728 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOATplane3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOATplane3D"; + ; + break;} +case 85: +#line 733 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ILLUMINATIONTYPE"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "ILLUMINATIONTYPE"; + ; + break;} +case 86: +#line 738 "ecc/parser.y" +{ + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ANIMATION"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "ANIMATION"; + ; + break;} +case 87: +#line 746 "ecc/parser.y" +{ + _strCurrentPropertyName = "\"\""; + _strCurrentPropertyShortcut = "0"; + _strCurrentPropertyColor = "0"; // this won't be rendered anyway + ; + break;} +case 88: +#line 751 "ecc/parser.y" +{ + _strCurrentPropertyName = yyvsp[-2].strString; + ; + break;} +case 89: +#line 756 "ecc/parser.y" +{ + _strCurrentPropertyShortcut = "0"; + ; + break;} +case 90: +#line 759 "ecc/parser.y" +{ + _strCurrentPropertyShortcut = yyvsp[0].strString; + ; + break;} +case 91: +#line 764 "ecc/parser.y" +{ + _strCurrentPropertyColor = "0x7F0000FFUL"; // dark red + ; + break;} +case 92: +#line 767 "ecc/parser.y" +{ + _strCurrentPropertyColor = yyvsp[-1].strString; + ; + break;} +case 93: +#line 771 "ecc/parser.y" +{ + _strCurrentPropertyFlags = "0"; // dark red + ; + break;} +case 94: +#line 774 "ecc/parser.y" +{ + _strCurrentPropertyFlags = yyvsp[-1].strString; + ; + break;} +case 95: +#line 779 "ecc/parser.y" +{ + if (strcmp(_strCurrentPropertyDataType,"CEntityPointer")==0) { + _strCurrentPropertyDefaultCode = (SType(_strCurrentPropertyIdentifier)+" = NULL;").strString; + } else if (strcmp(_strCurrentPropertyDataType,"CModelObject")==0) { + _strCurrentPropertyDefaultCode = + (SType(_strCurrentPropertyIdentifier)+".SetData(NULL);\n"+ + _strCurrentPropertyIdentifier+".mo_toTexture.SetData(NULL);").strString; + } else if (strcmp(_strCurrentPropertyDataType,"CModelInstance")==0) { + _strCurrentPropertyDefaultCode = + (SType(_strCurrentPropertyIdentifier)+".Clear();\n").strString; + } else if (strcmp(_strCurrentPropertyDataType,"CAnimObject")==0) { + _strCurrentPropertyDefaultCode = + (SType(_strCurrentPropertyIdentifier)+".SetData(NULL);\n").strString; + } else if (strcmp(_strCurrentPropertyDataType,"CSoundObject")==0) { + _strCurrentPropertyDefaultCode = + (SType(_strCurrentPropertyIdentifier)+".SetOwner(this);\n"+ + _strCurrentPropertyIdentifier+".Stop_internal();").strString; + } else { + yyerror("this kind of property must have default value"); + _strCurrentPropertyDefaultCode = ""; + } + ; + break;} +case 96: +#line 801 "ecc/parser.y" +{ + if (strcmp(_strCurrentPropertyDataType,"CEntityPointer")==0) { + yyerror("CEntityPointer type properties always default to NULL"); + } else { + _strCurrentPropertyDefaultCode = (SType(_strCurrentPropertyIdentifier)+" = "+yyvsp[0].strString+";").strString; + } + ; + break;} +case 102: +#line 811 "ecc/parser.y" +{yyval = yyvsp[0] + " ";; + break;} +case 103: +#line 812 "ecc/parser.y" +{yyval = yyvsp[-3]+yyvsp[-2]+yyvsp[-1]+yyvsp[0];; + break;} +case 104: +#line 813 "ecc/parser.y" +{yyval = yyvsp[-3]+yyvsp[-2]+yyvsp[-1]+yyvsp[0];; + break;} +case 105: +#line 814 "ecc/parser.y" +{yyval = yyvsp[-1]+yyvsp[0];; + break;} +case 106: +#line 815 "ecc/parser.y" +{yyval = yyvsp[-2]+yyvsp[-1]+yyvsp[0];; + break;} +case 107: +#line 822 "ecc/parser.y" +{ + fprintf(_fTables, " CEntityComponent()\n};\n"); + fprintf(_fTables, "#define %s_componentsct 0\n", _strCurrentClass); + fprintf(_fTables, "\n"); + fprintf(_fTables, "\n"); + ; + break;} +case 108: +#line 828 "ecc/parser.y" +{ + fprintf(_fTables, "};\n"); + fprintf(_fTables, "#define %s_componentsct ARRAYCOUNT(%s_components)\n", + _strCurrentClass, _strCurrentClass); + fprintf(_fTables, "\n"); + ; + break;} +case 112: +#line 844 "ecc/parser.y" +{ + fprintf(_fTables, "#define %s ((0x%08x<<8)+%s)\n", + _strCurrentComponentIdentifier, + _iCurrentClassID, + _strCurrentComponentID); + fprintf(_fTables, " CEntityComponent(%s, %s, \"%s%s\" %s),\n", + _strCurrentComponentType, + _strCurrentComponentIdentifier, + "EF","NM", + _strCurrentComponentFileName); + ; + break;} +case 113: +#line 857 "ecc/parser.y" +{ _strCurrentComponentID = yyvsp[0].strString; ; + break;} +case 114: +#line 858 "ecc/parser.y" +{ _strCurrentComponentIdentifier = yyvsp[0].strString; ; + break;} +case 115: +#line 859 "ecc/parser.y" +{ _strCurrentComponentFileName = yyvsp[0].strString; ; + break;} +case 116: +#line 862 "ecc/parser.y" +{ _strCurrentComponentType = "ECT_MODEL"; ; + break;} +case 117: +#line 863 "ecc/parser.y" +{ _strCurrentComponentType = "ECT_TEXTURE"; ; + break;} +case 118: +#line 864 "ecc/parser.y" +{ _strCurrentComponentType = "ECT_SOUND"; ; + break;} +case 119: +#line 865 "ecc/parser.y" +{ _strCurrentComponentType = "ECT_CLASS"; ; + break;} +case 120: +#line 872 "ecc/parser.y" +{ yyval = "";; + break;} +case 121: +#line 873 "ecc/parser.y" +{yyval = yyvsp[-1]+yyvsp[0];; + break;} +case 122: +#line 878 "ecc/parser.y" +{ + char *strReturnType = yyvsp[-10].strString; + char *strFunctionHeader = (yyvsp[-9]+yyvsp[-8]+yyvsp[-7]+yyvsp[-6]+yyvsp[-5]+yyvsp[-4]).strString; + char *strFunctionBody = (yyvsp[-3]+yyvsp[-2]+yyvsp[-1]).strString; + if (strcmp(yyvsp[-8].strString, _strCurrentClass)==0) { + if (strcmp(strReturnType+strlen(strReturnType)-4, "void")==0 ) { + strReturnType = ""; + } else { + yyerror("use 'void' as return type for constructors"); + } + } + fprintf(_fDeclaration, " %s %s %s %s;\n", + yyvsp[-12].strString, yyvsp[-11].strString, strReturnType, strFunctionHeader); + fprintf(_fImplementation, " %s %s::%s %s\n", + strReturnType, _strCurrentClass, strFunctionHeader, strFunctionBody); + ; + break;} +case 123: +#line 896 "ecc/parser.y" +{ yyval = "";; + break;} +case 124: +#line 897 "ecc/parser.y" +{ yyval = " ~ "; ; + break;} +case 125: +#line 901 "ecc/parser.y" +{ yyval = "";; + break;} +case 126: +#line 902 "ecc/parser.y" +{ + if (_bClassIsExported) { + yyval = ""; + } else { + yyval = " DECL_DLL "; + } + ; + break;} +case 127: +#line 912 "ecc/parser.y" +{ yyval = "";; + break;} +case 128: +#line 913 "ecc/parser.y" +{ yyval = yyvsp[0]; ; + break;} +case 129: +#line 916 "ecc/parser.y" +{ yyval = "";; + break;} +case 130: +#line 917 "ecc/parser.y" +{ yyval = yyvsp[0]; ; + break;} +case 133: +#line 924 "ecc/parser.y" +{ yyval = "";; + break;} +case 137: +#line 930 "ecc/parser.y" +{yyval = yyvsp[-2]+yyvsp[-1]+yyvsp[0];; + break;} +case 138: +#line 933 "ecc/parser.y" +{ yyval=yyvsp[-1]+" "+yyvsp[0]; ; + break;} +case 143: +#line 944 "ecc/parser.y" +{ yyval=yyvsp[-1]+" "+yyvsp[0]; ; + break;} +case 144: +#line 945 "ecc/parser.y" +{ yyval=yyvsp[-1]+" "+yyvsp[0]; ; + break;} +case 145: +#line 946 "ecc/parser.y" +{ yyval=yyvsp[-1]+" "+yyvsp[0]; ; + break;} +case 146: +#line 947 "ecc/parser.y" +{ yyval=yyvsp[-1]+" "+yyvsp[0]; ; + break;} +case 147: +#line 948 "ecc/parser.y" +{ yyval=yyvsp[-1]+" "+yyvsp[0]; ; + break;} +case 148: +#line 949 "ecc/parser.y" +{ yyval=yyvsp[-1]+" "+yyvsp[0]; ; + break;} +case 149: +#line 950 "ecc/parser.y" +{ yyval=yyvsp[-1]+" "+yyvsp[0]; ; + break;} +case 150: +#line 951 "ecc/parser.y" +{ yyval=yyvsp[-1]+" "+yyvsp[0]; ; + break;} +case 151: +#line 952 "ecc/parser.y" +{ yyval=yyvsp[-3]+" "+yyvsp[-2]+" "+yyvsp[-1]+" "+yyvsp[0]; ; + break;} +case 152: +#line 960 "ecc/parser.y" +{ yyval = "";; + break;} +case 153: +#line 961 "ecc/parser.y" +{yyval = yyvsp[-1]+yyvsp[0];; + break;} +case 154: +#line 965 "ecc/parser.y" +{ yyval = "-1"; ; + break;} +case 155: +#line 966 "ecc/parser.y" +{ + yyval = SType("STATE_")+yyvsp[-3]+"_"+yyvsp[0]; + ; + break;} +case 156: +#line 972 "ecc/parser.y" +{ + char *strProcedureName = yyvsp[-4].strString; + char strInputEventType[80]; + char strInputEventName[80]; + sscanf(yyvsp[-2].strString, "%s %s", strInputEventType, strInputEventName); + + char strStateID[256]; + char *strBaseStateID = "-1"; + if(strcmp(RemoveLineDirective(strProcedureName), "Main")==0){ + strcpy(strStateID, "1"); + if(strncmp(strInputEventType, "EVoid", 4)!=0 && _strCurrentThumbnail[2]!=0) { + yyerror("procedure 'Main' can take input parameters only in classes without thumbnails"); + } + } else { + sprintf(strStateID, "0x%08x", CreateID()); + } + + sprintf(_strCurrentStateID, "STATE_%s_%s", + _strCurrentClass, RemoveLineDirective(strProcedureName)); + fprintf(_fDeclaration, "#define %s %s\n", _strCurrentStateID, strStateID); + AddHandlerFunction(strProcedureName, strStateID, yyvsp[0].strString); + fprintf(_fImplementation, + "BOOL %s::%s(const CEntityEvent &__eeInput) {\n#undef STATE_CURRENT\n#define STATE_CURRENT %s\n", + _strCurrentClass, strProcedureName, _strCurrentStateID); + fprintf(_fImplementation, + " ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_%s, \"%s::%s expects '%s' as input!\");", + strInputEventType, _strCurrentClass, RemoveLineDirective(strProcedureName), + strInputEventType); + fprintf(_fImplementation, " const %s &%s = (const %s &)__eeInput;", + strInputEventType, strInputEventName, strInputEventType); + + ; + break;} +case 157: +#line 1003 "ecc/parser.y" +{ + char *strFunctionBody = yyvsp[-2].strString; + fprintf(_fImplementation, "%s ASSERT(FALSE); return TRUE;};", strFunctionBody); + ; + break;} +case 158: +#line 1010 "ecc/parser.y" +{ + yyval="EVoid e"; + ; + break;} +case 159: +#line 1013 "ecc/parser.y" +{ + yyval=yyvsp[0]+" e"; + ; + break;} +case 160: +#line 1016 "ecc/parser.y" +{ + yyval=yyvsp[-1]+" "+yyvsp[0]; + ; + break;} +case 166: +#line 1023 "ecc/parser.y" +{yyval = yyvsp[0] + " ";; + break;} +case 187: +#line 1026 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 188: +#line 1027 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 189: +#line 1028 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 190: +#line 1029 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 191: +#line 1030 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 192: +#line 1031 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 193: +#line 1032 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 194: +#line 1033 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 195: +#line 1034 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 196: +#line 1035 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 197: +#line 1036 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 198: +#line 1037 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 199: +#line 1038 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 200: +#line 1039 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 201: +#line 1040 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 202: +#line 1041 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 203: +#line 1042 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 204: +#line 1043 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 205: +#line 1044 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 206: +#line 1045 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 207: +#line 1046 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 208: +#line 1047 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 209: +#line 1048 "ecc/parser.y" +{yyval=yyvsp[-2]+yyvsp[-1]+yyvsp[0];; + break;} +case 210: +#line 1049 "ecc/parser.y" +{yyval=yyvsp[-2]+yyvsp[-1]+yyvsp[0];; + break;} +case 211: +#line 1050 "ecc/parser.y" +{yyval = yyvsp[-2]+yyvsp[-1]+yyvsp[0];; + break;} +case 212: +#line 1051 "ecc/parser.y" +{yyval = yyvsp[-1]+" "+yyvsp[0];; + break;} +case 244: +#line 1064 "ecc/parser.y" +{yyval = yyvsp[0] + " ";; + break;} +case 245: +#line 1071 "ecc/parser.y" +{ yyval = "";; + break;} +case 246: +#line 1072 "ecc/parser.y" +{ yyval = yyvsp[-1]+yyvsp[0]; ; + break;} +case 247: +#line 1075 "ecc/parser.y" +{yyval=yyvsp[-1]+yyvsp[0];; + break;} +case 248: +#line 1076 "ecc/parser.y" +{yyval=yyvsp[-6]+yyvsp[-5]+yyvsp[-4]+yyvsp[-3]+yyvsp[-2]+yyvsp[-1]+yyvsp[0]; + break;} +case 249: +#line 1077 "ecc/parser.y" +{yyval=yyvsp[-2]+" "+yyvsp[-1]+yyvsp[0]+" ";; + break;} +case 250: +#line 1078 "ecc/parser.y" +{yyval=yyvsp[-2]+yyvsp[-1]+yyvsp[0];; + break;} +case 251: +#line 1079 "ecc/parser.y" +{yyval=yyvsp[-3]+yyvsp[-2]+yyvsp[-1]+yyvsp[0];; + break;} +case 268: +#line 1100 "ecc/parser.y" +{ + if (yyvsp[-1].bCrossesStates) { + char strAfterIfName[80], strAfterIfID[11]; + CreateInternalHandlerFunction(strAfterIfName, strAfterIfID); + yyval = yyvsp[-6]+"(!"+yyvsp[-5]+yyvsp[-4]+yyvsp[-3]+"){ Jump(STATE_CURRENT,"+strAfterIfID+", FALSE, EInternal());return TRUE;}"+yyvsp[-1]+ + "Jump(STATE_CURRENT,"+strAfterIfID+", FALSE, EInternal());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+strAfterIfName+"(const CEntityEvent &__eeInput){"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+strAfterIfID+"\n"; + } else { + yyval = yyvsp[-6]+yyvsp[-5]+yyvsp[-4]+yyvsp[-3]+yyvsp[-2]+yyvsp[-1]+yyvsp[0]; + } + ; + break;} +case 269: +#line 1116 "ecc/parser.y" +{ + if (yyvsp[-3].bCrossesStates || yyvsp[0].bCrossesStates) { + char strAfterIfName[80], strAfterIfID[11]; + char strElseName[80], strElseID[11]; + CreateInternalHandlerFunction(strAfterIfName, strAfterIfID); + CreateInternalHandlerFunction(strElseName, strElseID); + yyval = yyvsp[-8]+"(!"+yyvsp[-7]+yyvsp[-6]+yyvsp[-5]+"){ Jump(STATE_CURRENT,"+strElseID+", FALSE, EInternal());return TRUE;}"+ + yyvsp[-3]+"Jump(STATE_CURRENT,"+strAfterIfID+", FALSE, EInternal());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+strElseName+"(const CEntityEvent &__eeInput){"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+strElseID+"\n"+ + yyvsp[0]+"Jump(STATE_CURRENT,"+strAfterIfID+", FALSE, EInternal());return TRUE;}\n"+ + "BOOL "+_strCurrentClass+"::"+strAfterIfName+"(const CEntityEvent &__eeInput){"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+strAfterIfID+"\n"; + } else { + yyval = yyvsp[-8]+yyvsp[-7]+yyvsp[-6]+yyvsp[-5]+yyvsp[-4]+yyvsp[-3]+yyvsp[-2]+yyvsp[-1]+" "+yyvsp[0]; + } + ; + break;} +case 270: +#line 1138 "ecc/parser.y" +{ + if (strlen(_strInLoopName)>0) { + yyerror("Nested loops are not implemented yet"); + } + ; + break;} +case 271: +#line 1142 "ecc/parser.y" +{ + if (yyvsp[-1].bCrossesStates) { + CreateInternalHandlerFunction(_strInLoopName, _strInLoopID); + CreateInternalHandlerFunction(_strAfterLoopName, _strAfterLoopID); + yyval = SType(GetLineDirective(yyvsp[-7]))+"Jump(STATE_CURRENT,"+_strInLoopID+", FALSE, EInternal());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInLoopName+"(const CEntityEvent &__eeInput)"+yyvsp[-2]+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInLoopID+"\n"+ + "if(!"+yyvsp[-6]+yyvsp[-5]+yyvsp[-4]+"){ Jump(STATE_CURRENT,"+_strAfterLoopID+", FALSE, EInternal());return TRUE;}"+ + yyvsp[-1]+"Jump(STATE_CURRENT,"+_strInLoopID+", FALSE, EInternal());return TRUE;"+yyvsp[0]+ + "BOOL "+_strCurrentClass+"::"+_strAfterLoopName+"(const CEntityEvent &__eeInput) {"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterLoopID+"\n"; + } else { + yyval = yyvsp[-7]+yyvsp[-6]+yyvsp[-5]+yyvsp[-4]+yyvsp[-2]+yyvsp[-1]+yyvsp[0]; + } + _strInLoopName[0] = 0; + ; + break;} +case 272: +#line 1163 "ecc/parser.y" +{ + if (strlen(_strInLoopName)>0) { + yyerror("Nested loops are not implemented yet"); + } + _strInLoopName[0] = 0; + ; + break;} +case 273: +#line 1168 "ecc/parser.y" +{ + if (yyvsp[-7].bCrossesStates) { + CreateInternalHandlerFunction(_strInLoopName, _strInLoopID); + CreateInternalHandlerFunction(_strAfterLoopName, _strAfterLoopID); + yyval = SType(GetLineDirective(yyvsp[-9]))+"Jump(STATE_CURRENT,"+_strInLoopID+", FALSE, EInternal());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInLoopName+"(const CEntityEvent &__eeInput)"+yyvsp[-8]+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInLoopID+"\n"+yyvsp[-7]+ + "if(!"+yyvsp[-3]+yyvsp[-2]+yyvsp[-1]+"){ Jump(STATE_CURRENT,"+_strAfterLoopID+", FALSE, EInternal());return TRUE;}"+ + "Jump(STATE_CURRENT,"+_strInLoopID+", FALSE, EInternal());return TRUE;"+yyvsp[-6]+ + "BOOL "+_strCurrentClass+"::"+_strAfterLoopName+"(const CEntityEvent &__eeInput) {"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterLoopID+"\n"; + } else { + yyval = yyvsp[-9]+yyvsp[-8]+yyvsp[-7]+yyvsp[-6]+yyvsp[-4]+yyvsp[-3]+yyvsp[-2]+yyvsp[-1]+yyvsp[0]; + } + _strInLoopName[0] = 0; + ; + break;} +case 274: +#line 1189 "ecc/parser.y" +{ + if (strlen(_strInLoopName)>0) { + yyerror("Nested loops are not implemented yet"); + } + ; + break;} +case 275: +#line 1193 "ecc/parser.y" +{ + if (yyvsp[-1].bCrossesStates) { + CreateInternalHandlerFunction(_strInLoopName, _strInLoopID); + CreateInternalHandlerFunction(_strAfterLoopName, _strAfterLoopID); + yyerror("For loops across states are not supported"); + } else { + yyval = yyvsp[-11]+yyvsp[-10]+yyvsp[-9]+yyvsp[-8]+yyvsp[-7]+yyvsp[-6]+yyvsp[-5]+yyvsp[-4]+yyvsp[-2]+yyvsp[-1]+yyvsp[0]; + } + _strInLoopName[0] = 0; + ; + break;} +case 276: +#line 1206 "ecc/parser.y" +{ + if (!_bInProcedure) { + yyerror("Cannot have 'wait' in functions"); + } + CreateInternalHandlerFunction(_strInWaitName, _strInWaitID); + CreateInternalHandlerFunction(_strAfterWaitName, _strAfterWaitID); + _bHasOtherwise = 0; + _bInHandler = 1; + ; + break;} +case 277: +#line 1214 "ecc/parser.y" +{ + if (yyvsp[-1].bCrossesStates) { + yyerror("'wait' statements must not be nested"); + yyval = ""; + } else { + SType stDefault; + if (!_bHasOtherwise) { + stDefault = SType("default: return FALSE; break;"); + } else { + stDefault = SType(""); + } + + yyval = SType(GetLineDirective(yyvsp[-5]))+yyvsp[-4]+";\n"+ + "Jump(STATE_CURRENT, "+_strInWaitID+", FALSE, EBegin());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInWaitName+"(const CEntityEvent &__eeInput) {"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInWaitID+"\n"+ + "switch(__eeInput.ee_slEvent)"+yyvsp[-2]+yyvsp[-1]+stDefault+yyvsp[0]+ + "return TRUE;}BOOL "+_strCurrentClass+"::"+_strAfterWaitName+"(const CEntityEvent &__eeInput){"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterWaitID+"\n"; + yyval.bCrossesStates = 1; + _bInHandler = 0; + } + ; + break;} +case 278: +#line 1240 "ecc/parser.y" +{ + if (!_bInProcedure) { + yyerror("Cannot have 'autowait' in functions"); + } + CreateInternalHandlerFunction(_strInWaitName, _strInWaitID); + CreateInternalHandlerFunction(_strAfterWaitName, _strAfterWaitID); + _bHasOtherwise = 0; + + yyval = SType(GetLineDirective(yyvsp[-2]))+yyvsp[-1]+";\n"+ + "Jump(STATE_CURRENT, "+_strInWaitID+", FALSE, EBegin());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInWaitName+"(const CEntityEvent &__eeInput) {"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInWaitID+"\n"+ + "switch(__eeInput.ee_slEvent) {"+ + "case EVENTCODE_EBegin: return TRUE;"+ + "case EVENTCODE_ETimer: Jump(STATE_CURRENT,"+_strAfterWaitID+", FALSE, EInternal()); return TRUE;"+ + "default: return FALSE; }}"+ + "BOOL "+_strCurrentClass+"::"+_strAfterWaitName+"(const CEntityEvent &__eeInput){"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterWaitID+"\n"+yyvsp[0]; + yyval.bCrossesStates = 1; + ; + break;} +case 279: +#line 1264 "ecc/parser.y" +{ + if (!_bInProcedure) { + yyerror("Cannot have 'autocall' in functions"); + } + CreateInternalHandlerFunction(_strInWaitName, _strInWaitID); + CreateInternalHandlerFunction(_strAfterWaitName, _strAfterWaitID); + _bHasOtherwise = 0; + + yyval = SType(GetLineDirective(yyvsp[-4]))+yyvsp[-3]+";\n"+ + "Jump(STATE_CURRENT, "+_strInWaitID+", FALSE, EBegin());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInWaitName+"(const CEntityEvent &__eeInput) {"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInWaitID+"\n"+ + "switch(__eeInput.ee_slEvent) {"+ + "case EVENTCODE_EBegin: return TRUE;"+ + "case EVENTCODE_"+yyvsp[-2]+": Jump(STATE_CURRENT,"+_strAfterWaitID+", FALSE, __eeInput); return TRUE;"+ + "default: return FALSE; }}"+ + "BOOL "+_strCurrentClass+"::"+_strAfterWaitName+"(const CEntityEvent &__eeInput){"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterWaitID+"\n"+ + "const "+yyvsp[-2]+"&"+yyvsp[-1]+"= ("+yyvsp[-2]+"&)__eeInput;\n"+yyvsp[0]; + yyval.bCrossesStates = 1; + ; + break;} +case 280: +#line 1289 "ecc/parser.y" +{ + yyval = SType("__e"); + ; + break;} +case 281: +#line 1292 "ecc/parser.y" +{ + yyval = yyvsp[0]; + ; + break;} +case 282: +#line 1297 "ecc/parser.y" +{ + if (!_bInProcedure) { + yyerror("Cannot have 'autocall' in functions"); + } + CreateInternalHandlerFunction(_strInWaitName, _strInWaitID); + CreateInternalHandlerFunction(_strAfterWaitName, _strAfterWaitID); + _bHasOtherwise = 0; + + yyval = SType(GetLineDirective(yyvsp[-7]))+yyvsp[-6]+";\n"+ + "Jump(STATE_CURRENT, "+_strInWaitID+", FALSE, EBegin());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInWaitName+"(const CEntityEvent &__eeInput) {"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInWaitID+"\n"+ + "switch(__eeInput.ee_slEvent) {"+ + "case EVENTCODE_EBegin: Call"+yyvsp[-5]+"STATE_CURRENT, "+yyvsp[-6]+", "+yyvsp[-4]+yyvsp[-3]+";return TRUE;"+ + "case EVENTCODE_"+yyvsp[-2]+": Jump(STATE_CURRENT,"+_strAfterWaitID+", FALSE, __eeInput); return TRUE;"+ + "default: return FALSE; }}"+ + "BOOL "+_strCurrentClass+"::"+_strAfterWaitName+"(const CEntityEvent &__eeInput){"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterWaitID+"\n"+ + "const "+yyvsp[-2]+"&"+yyvsp[-1]+"= ("+yyvsp[-2]+"&)__eeInput;\n"+yyvsp[0]; + yyval.bCrossesStates = 1; + ; + break;} +case 283: +#line 1321 "ecc/parser.y" +{ + yyval = SType("SetTimerAt(THINKTIME_NEVER)"); + ; + break;} +case 284: +#line 1324 "ecc/parser.y" +{ + yyval = SType("SetTimerAfter")+yyvsp[-2]+yyvsp[-1]+yyvsp[0]; + ; + break;} +case 285: +#line 1330 "ecc/parser.y" +{ + if (!_bInProcedure) { + yyerror("Cannot have 'jump' in functions"); + } + yyval = SType(GetLineDirective(yyvsp[-5]))+"Jump"+yyvsp[-3]+"STATE_CURRENT, "+yyvsp[-4]+", "+yyvsp[-2]+yyvsp[-1]+";return TRUE;"; + ; + break;} +case 286: +#line 1339 "ecc/parser.y" +{ + if (!_bInProcedure) { + yyerror("Cannot have 'call' in functions"); + } + if (!_bInHandler) { + yyerror("'call' must be inside a 'wait' statement"); + } + yyval = SType(GetLineDirective(yyvsp[-5]))+"Call"+yyvsp[-3]+"STATE_CURRENT, "+yyvsp[-4]+", "+yyvsp[-2]+yyvsp[-1]+";return TRUE;"; + ; + break;} +case 287: +#line 1351 "ecc/parser.y" +{ + yyval = yyvsp[0]; + ; + break;} +case 288: +#line 1354 "ecc/parser.y" +{ + yyval = SType("EVoid()"); + ; + break;} +case 289: +#line 1360 "ecc/parser.y" +{ + yyval = SType("STATE_")+_strCurrentClass+"_"+yyvsp[0]+", TRUE"; + ; + break;} +case 290: +#line 1363 "ecc/parser.y" +{ + yyval = SType("STATE_")+yyvsp[-3]+"_"+yyvsp[0]+", FALSE"; + ; + break;} +case 291: +#line 1369 "ecc/parser.y" +{ + yyval = SType(GetLineDirective(yyvsp[-1]))+"UnsetTimer();Jump(STATE_CURRENT," + +_strAfterWaitID+", FALSE, EInternal());"+"return TRUE"+yyvsp[0]; + ; + break;} +case 292: +#line 1375 "ecc/parser.y" +{ + yyval = SType(GetLineDirective(yyvsp[-1]))+"return TRUE"+yyvsp[0]; + ; + break;} +case 293: +#line 1380 "ecc/parser.y" +{ + yyval = SType(GetLineDirective(yyvsp[-1]))+"return FALSE"+yyvsp[0]; + ; + break;} +case 294: +#line 1385 "ecc/parser.y" +{ + if (!_bInProcedure) { + yyval = yyvsp[-2]+" "+yyvsp[-1]+yyvsp[0]; + } else { + if (strlen(yyvsp[-1].strString)==0) { + yyvsp[-1] = SType("EVoid()"); + } + yyval = SType(GetLineDirective(yyvsp[-2])) + +"Return(STATE_CURRENT,"+yyvsp[-1]+");" + +yyvsp[-2]+" TRUE"+yyvsp[0]; + } + ; + break;} +case 295: +#line 1399 "ecc/parser.y" +{yyval = "";; + break;} +case 297: +#line 1404 "ecc/parser.y" +{ + char strInputEventType[80]; + char strInputEventName[80]; + sscanf(yyvsp[-6].strString, "%s %s", strInputEventType, strInputEventName); + + yyval = SType("case")+yyvsp[-7]+"EVENTCODE_"+strInputEventType+yyvsp[-5]+yyvsp[-4]+yyvsp[-3]+ + "const "+strInputEventType+"&"+strInputEventName+"= ("+ + strInputEventType+"&)__eeInput;\n"+yyvsp[-2]+yyvsp[-1]+"ASSERT(FALSE);break;"; + ; + break;} +case 298: +#line 1413 "ecc/parser.y" +{ + char strInputEventType[80]; + char strInputEventName[80]; + sscanf(yyvsp[-6].strString, "%s %s", strInputEventType, strInputEventName); + + yyval = SType("default")+yyvsp[-4]+yyvsp[-3]+yyvsp[-2]+yyvsp[-1]+"ASSERT(FALSE);break;"; + _bHasOtherwise = 1; + ; + break;} +case 299: +#line 1423 "ecc/parser.y" +{ yyval = "";; + break;} +case 300: +#line 1424 "ecc/parser.y" +{ yyval = yyvsp[-1]+yyvsp[0]; ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 487 "bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 1427 "ecc/parser.y" + diff --git a/Sources/Ecc/Parser.y b/Sources/Ecc/Parser.y new file mode 100644 index 0000000..aa676f9 --- /dev/null +++ b/Sources/Ecc/Parser.y @@ -0,0 +1,1427 @@ +%{ +// rcg10042001 Changed to specify Ecc directory... +#include "Ecc/StdH.h" +#include "Ecc/Main.h" + +static char *_strCurrentClass; +static int _iCurrentClassID; +static char *_strCurrentBase; +static char *_strCurrentDescription; +static char *_strCurrentThumbnail; +static char *_strCurrentEnum; +static int _bClassIsExported = 0; + +static char *_strCurrentPropertyID; +static char *_strCurrentPropertyIdentifier; +static char *_strCurrentPropertyPropertyType; +static char *_strCurrentPropertyEnumType; +static char *_strCurrentPropertyDataType; +static char *_strCurrentPropertyName; +static char *_strCurrentPropertyShortcut; +static char *_strCurrentPropertyColor; +static char *_strCurrentPropertyFlags; +static char *_strCurrentPropertyDefaultCode; + +static char *_strCurrentComponentIdentifier; +static char *_strCurrentComponentType; +static char *_strCurrentComponentID; +static char *_strCurrentComponentFileName; + +static int _ctInProcedureHandler = 0; +static char _strLastProcedureName[256]; + +static char _strInWaitName[256]; +static char _strAfterWaitName[256]; +static char _strInWaitID[256]; +static char _strAfterWaitID[256]; + +static char _strInLoopName[256]; +static char _strAfterLoopName[256]; +static char _strInLoopID[256]; +static char _strAfterLoopID[256]; +static char _strCurrentStateID[256]; + +static int _bInProcedure; // set if currently compiling a procedure +static int _bInHandler; +static int _bHasOtherwise; // set if current 'wait' block has an 'otherwise' statement + +static char *_strCurrentEvent; +static int _bFeature_AbstractBaseClass; +static int _bFeature_ImplementsOnInitClass; +static int _bFeature_ImplementsOnEndClass; +static int _bFeature_ImplementsOnPrecache; +static int _bFeature_ImplementsOnWorldInit; +static int _bFeature_ImplementsOnWorldEnd; +static int _bFeature_ImplementsOnWorldTick; +static int _bFeature_ImplementsOnWorldRender; +static int _bFeature_CanBePredictable; + +static int _iNextFreeID; +inline int CreateID(void) { + return _iNextFreeID++; +} + +static int _ctBraces = 0; +void OpenBrace(void) { + _ctBraces++; +} +void CloseBrace(void) { + _ctBraces--; +} +SType Braces(int iBraces) { + static char strBraces[50]; + memset(strBraces, '}', sizeof(strBraces)); + strBraces[iBraces] = 0; + return SType(strBraces); +} +char *RemoveLineDirective(char *str) +{ + if (str[0]=='\n' && str[1]=='#') { + return strchr(str+2, '\n')+1; + } else { + return str; + } +} +char *GetLineDirective(SType &st) +{ + char *str = st.strString; + if (str[0]=='\n' && str[1]=='#' && str[2]=='l') { + char *strResult = strdup(str); + strchr(strResult+3,'\n')[1] = 0; + return strResult; + } else { + return ""; + } +} +void AddHandlerFunction(char *strProcedureName, int iStateID) +{ + fprintf(_fDeclaration, " BOOL %s(const CEntityEvent &__eeInput);\n", strProcedureName); + fprintf(_fTables, " {0x%08x, -1, CEntity::pEventHandler(&%s::%s), " + "DEBUGSTRING(\"%s::%s\")},\n", + iStateID, _strCurrentClass, strProcedureName, _strCurrentClass, strProcedureName); +} + + +void AddHandlerFunction(char *strProcedureName, char *strStateID, char *strBaseStateID) +{ + fprintf(_fDeclaration, " BOOL %s(const CEntityEvent &__eeInput);\n", strProcedureName); + fprintf(_fTables, " {%s, %s, CEntity::pEventHandler(&%s::%s)," + "DEBUGSTRING(\"%s::%s\")},\n", + strStateID, strBaseStateID, _strCurrentClass, strProcedureName, + _strCurrentClass, RemoveLineDirective(strProcedureName)); + strcpy(_strLastProcedureName, RemoveLineDirective(strProcedureName)); + _ctInProcedureHandler = 0; +} + +void CreateInternalHandlerFunction(char *strFunctionName, char *strID) +{ + int iID = CreateID(); + _ctInProcedureHandler++; + sprintf(strID, "0x%08x", iID); + sprintf(strFunctionName, "H0x%08x_%s_%02d", iID, _strLastProcedureName, _ctInProcedureHandler); + AddHandlerFunction(strFunctionName, iID); +} + +void DeclareFeatureProperties(void) +{ + if (_bFeature_CanBePredictable) { + fprintf(_fTables, " CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x%08x<<8)+%s, offsetof(%s, %s), %s, %s, %s, %s),\n", + _iCurrentClassID, + "255", + _strCurrentClass, + "m_penPrediction", + "\"\"", + "0", + "0", + "0"); + fprintf(_fDeclaration, " %s %s;\n", + "CEntityPointer", + "m_penPrediction" + ); + fprintf(_fImplementation, " m_penPrediction = NULL;\n"); + } +} + +#undef YYERROR_VERBOSE + +%} + +/* BISON Declarations */ + +/* different type of constants */ +%token c_char +%token c_int +%token c_float +%token c_bool +%token c_string + +/* the standard cpp identifier */ +%token identifier + +/* specially bracketed cpp blocks */ +%token cppblock + +/* standard cpp-keywords */ +%token k_while +%token k_for +%token k_if +%token k_else +%token k_enum +%token k_switch +%token k_case +%token k_class +%token k_do +%token k_void +%token k_const +%token k_inline +%token k_static +%token k_virtual +%token k_return +%token k_autowait +%token k_autocall +%token k_waitevent + +/* aditional keywords */ +%token k_event +%token k_name +%token k_thumbnail +%token k_features +%token k_uses +%token k_export + +%token k_texture +%token k_sound +%token k_model + +%token k_properties +%token k_components +%token k_functions +%token k_procedures + +%token k_wait +%token k_on +%token k_otherwise + +%token k_call +%token k_jump +%token k_stop +%token k_resume +%token k_pass + +/* special data types */ +%token k_CTString +%token k_CTStringTrans +%token k_CTFileName +%token k_CTFileNameNoDep +%token k_BOOL +%token k_COLOR +%token k_FLOAT +%token k_INDEX +%token k_RANGE +%token k_CEntityPointer +%token k_CModelObject +%token k_CModelInstance +%token k_CAnimObject +%token k_CSoundObject +%token k_CPlacement3D +%token k_FLOATaabbox3D +%token k_FLOATmatrix3D +%token k_FLOATquat3D +%token k_ANGLE +%token k_FLOAT3D +%token k_ANGLE3D +%token k_FLOATplane3D +%token k_ANIMATION +%token k_ILLUMINATIONTYPE +%token k_FLAGS + +%start program + +%% + +/*///////////////////////////////////////////////////////// + * Global structure of the source file. + */ +program + : c_int { + int iID = atoi($1.strString); + if(iID>32767) { + yyerror("Maximum allowed id for entity source file is 32767"); + } + _iCurrentClassID = iID; + _iNextFreeID = iID<<16; + fprintf(_fDeclaration, "#ifndef _%s_INCLUDED\n", _strFileNameBaseIdentifier); + fprintf(_fDeclaration, "#define _%s_INCLUDED 1\n", _strFileNameBaseIdentifier); + + } opt_global_cppblock { + + //fprintf(_fImplementation, "\n#undef DECL_DLL\n#define DECL_DLL _declspec(dllimport)\n"); + } uses_list { + //fprintf(_fImplementation, "\n#undef DECL_DLL\n#define DECL_DLL _declspec(dllexport)\n"); + + fprintf(_fImplementation, "#include <%s.h>\n", _strFileNameBase); + fprintf(_fImplementation, "#include <%s_tables.h>\n", _strFileNameBase); + } enum_and_event_declarations_list { + } opt_global_cppblock { + } opt_class_declaration { + fprintf(_fDeclaration, "#endif // _%s_INCLUDED\n", _strFileNameBaseIdentifier); + } + ; + + +/* + * Prolog cpp code. + */ +opt_global_cppblock + : /* null */ + | cppblock { fprintf(_fImplementation, "%s\n", $1.strString); } + ; + +uses_list + : /* null */ + | uses_list uses_statement + ; +uses_statement + : k_uses c_string ';' { + char *strUsedFileName = strdup($2.strString); + strUsedFileName[strlen(strUsedFileName)-1] = 0; + fprintf(_fDeclaration, "#include <%s.h>\n", strUsedFileName+1); + } + ; + + +enum_and_event_declarations_list + : /* null */ + | enum_and_event_declarations_list enum_declaration + | enum_and_event_declarations_list event_declaration + ; +/*///////////////////////////////////////////////////////// + * Enum types declarations + */ +enum_declaration + : k_enum identifier { + _strCurrentEnum = $2.strString; + fprintf(_fTables, "EP_ENUMBEG(%s)\n", _strCurrentEnum ); + fprintf(_fDeclaration, "extern DECL_DLL CEntityPropertyEnumType %s_enum;\n", _strCurrentEnum ); + fprintf(_fDeclaration, "enum %s {\n", _strCurrentEnum ); + } '{' enum_values_list opt_comma '}' ';' { + fprintf(_fTables, "EP_ENUMEND(%s);\n\n", _strCurrentEnum); + fprintf(_fDeclaration, "};\n"); + fprintf(_fDeclaration, "DECL_DLL inline void ClearToDefault(%s &e) { e = (%s)0; } ;\n", _strCurrentEnum, _strCurrentEnum); + } + ; +opt_comma : /*null*/ | ','; +enum_values_list + : enum_value + | enum_values_list ',' enum_value + ; + +enum_value + : c_int identifier c_string { + fprintf(_fTables, " EP_ENUMVALUE(%s, %s),\n", $2.strString, $3.strString); + fprintf(_fDeclaration, " %s = %s,\n", $2.strString, $1.strString); + } + ; + +/*///////////////////////////////////////////////////////// + * Event declarations + */ +event_declaration + : k_event identifier { + _strCurrentEvent = $2.strString; + int iID = CreateID(); + fprintf(_fDeclaration, "#define EVENTCODE_%s 0x%08x\n", _strCurrentEvent, iID); + fprintf(_fDeclaration, "class DECL_DLL %s : public CEntityEvent {\npublic:\n", + _strCurrentEvent); + fprintf(_fDeclaration, "%s();\n", _strCurrentEvent ); + fprintf(_fDeclaration, "CEntityEvent *MakeCopy(void);\n"); + fprintf(_fImplementation, + "CEntityEvent *%s::MakeCopy(void) { " + "CEntityEvent *peeCopy = new %s(*this); " + "return peeCopy;}\n", + _strCurrentEvent, _strCurrentEvent); + fprintf(_fImplementation, "%s::%s() : CEntityEvent(EVENTCODE_%s) {;\n", + _strCurrentEvent, _strCurrentEvent, _strCurrentEvent); + } '{' event_members_list opt_comma '}' ';' { + fprintf(_fImplementation, "};\n"); + fprintf(_fDeclaration, "};\n"); + fprintf(_fDeclaration, "DECL_DLL inline void ClearToDefault(%s &e) { e = %s(); } ;\n", _strCurrentEvent, _strCurrentEvent); + } + ; + +event_members_list + : /* null */ + | non_empty_event_members_list + ; + +non_empty_event_members_list + : event_member + | event_members_list ',' event_member + ; + +event_member + : any_type identifier { + fprintf(_fDeclaration, "%s %s;\n", $1.strString, $2.strString); + fprintf(_fImplementation, " ClearToDefault(%s);\n", $2.strString); + } + ; + +/*///////////////////////////////////////////////////////// + * The class declaration structure. + */ +opt_class_declaration + : /* null */ + | class_declaration + ; + +class_declaration + : /* null */ + | class_optexport identifier ':' identifier '{' + k_name c_string ';' + k_thumbnail c_string ';' { + _strCurrentClass = $2.strString; + _strCurrentBase = $4.strString; + _strCurrentDescription = $7.strString; + _strCurrentThumbnail = $10.strString; + + fprintf(_fTables, "#define ENTITYCLASS %s\n\n", _strCurrentClass); + fprintf(_fDeclaration, "extern \"C\" DECL_DLL CDLLEntityClass %s_DLLClass;\n", + _strCurrentClass); + fprintf(_fDeclaration, "%s %s : public %s {\npublic:\n", + $1.strString, _strCurrentClass, _strCurrentBase); + + } opt_features { + fprintf(_fDeclaration, " %s virtual void SetDefaultProperties(void);\n", _bClassIsExported?"":"DECL_DLL"); + fprintf(_fImplementation, "void %s::SetDefaultProperties(void) {\n", _strCurrentClass); + fprintf(_fTables, "CEntityProperty %s_properties[] = {\n", _strCurrentClass); + + } k_properties ':' property_declaration_list { + fprintf(_fImplementation, " %s::SetDefaultProperties();\n}\n", _strCurrentBase); + + fprintf(_fTables, "CEntityComponent %s_components[] = {\n", _strCurrentClass); + } opt_internal_properties { + } k_components ':' component_declaration_list { + _bTrackLineInformation = 1; + fprintf(_fTables, "CEventHandlerEntry %s_handlers[] = {\n", _strCurrentClass); + + _bInProcedure = 0; + _bInHandler = 0; + } k_functions ':' function_list { + + _bInProcedure = 1; + } k_procedures ':' procedure_list { + } '}' ';' { + fprintf(_fTables, "};\n#define %s_handlersct ARRAYCOUNT(%s_handlers)\n", + _strCurrentClass, _strCurrentClass); + fprintf(_fTables, "\n"); + + if (_bFeature_AbstractBaseClass) { + fprintf(_fTables, "CEntity *%s_New(void) { return NULL; };\n", + _strCurrentClass); + } else { + fprintf(_fTables, "CEntity *%s_New(void) { return new %s; };\n", + _strCurrentClass, _strCurrentClass); + } + + if (!_bFeature_ImplementsOnInitClass) { + fprintf(_fTables, "void %s_OnInitClass(void) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnInitClass(void);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnEndClass) { + fprintf(_fTables, "void %s_OnEndClass(void) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnEndClass(void);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnPrecache) { + fprintf(_fTables, "void %s_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnPrecache(CDLLEntityClass *pdec, INDEX iUser);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnWorldEnd) { + fprintf(_fTables, "void %s_OnWorldEnd(CWorld *pwo) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnWorldEnd(CWorld *pwo);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnWorldInit) { + fprintf(_fTables, "void %s_OnWorldInit(CWorld *pwo) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnWorldInit(CWorld *pwo);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnWorldTick) { + fprintf(_fTables, "void %s_OnWorldTick(CWorld *pwo) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnWorldTick(CWorld *pwo);\n", _strCurrentClass); + } + + if (!_bFeature_ImplementsOnWorldRender) { + fprintf(_fTables, "void %s_OnWorldRender(CWorld *pwo) {};\n", _strCurrentClass); + } else { + fprintf(_fTables, "void %s_OnWorldRender(CWorld *pwo);\n", _strCurrentClass); + } + + fprintf(_fTables, "ENTITY_CLASSDEFINITION(%s, %s, %s, %s, 0x%08x);\n", + _strCurrentClass, _strCurrentBase, + _strCurrentDescription, _strCurrentThumbnail, _iCurrentClassID); + fprintf(_fTables, "DECLARE_CTFILENAME(_fnm%s_tbn, %s);\n", _strCurrentClass, _strCurrentThumbnail); + + fprintf(_fDeclaration, "};\n"); + } + ; + +class_optexport + : k_class { $$ = $1; _bClassIsExported = 0; } + | k_class k_export { $$ = $1+" DECL_DLL "; _bClassIsExported = 1; } + ; + +opt_features + : /*null */ + | k_features { + _bFeature_ImplementsOnWorldInit = 0; + _bFeature_ImplementsOnWorldEnd = 0; + _bFeature_ImplementsOnWorldTick = 0; + _bFeature_ImplementsOnWorldRender = 0; + _bFeature_ImplementsOnInitClass = 0; + _bFeature_ImplementsOnEndClass = 0; + _bFeature_ImplementsOnPrecache = 0; + _bFeature_AbstractBaseClass = 0; + _bFeature_CanBePredictable = 0; + }features_list ';' + ; +features_list + : feature + | features_list ',' feature + ; +feature + : c_string { + if (strcmp($1.strString, "\"AbstractBaseClass\"")==0) { + _bFeature_AbstractBaseClass = 1; + } else if (strcmp($1.strString, "\"IsTargetable\"")==0) { + fprintf(_fDeclaration, "virtual BOOL IsTargetable(void) const { return TRUE; };\n"); + } else if (strcmp($1.strString, "\"IsImportant\"")==0) { + fprintf(_fDeclaration, "virtual BOOL IsImportant(void) const { return TRUE; };\n"); + } else if (strcmp($1.strString, "\"HasName\"")==0) { + fprintf(_fDeclaration, + "virtual const CTString &GetName(void) const { return m_strName; };\n"); + } else if (strcmp($1.strString, "\"CanBePredictable\"")==0) { + fprintf(_fDeclaration, + "virtual CEntity *GetPredictionPair(void) { return m_penPrediction; };\n"); + fprintf(_fDeclaration, + "virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; };\n"); + _bFeature_CanBePredictable = 1; + } else if (strcmp($1.strString, "\"HasDescription\"")==0) { + fprintf(_fDeclaration, + "virtual const CTString &GetDescription(void) const { return m_strDescription; };\n"); + } else if (strcmp($1.strString, "\"HasTarget\"")==0) { + fprintf(_fDeclaration, + "virtual CEntity *GetTarget(void) const { return m_penTarget; };\n"); + } else if (strcmp($1.strString, "\"ImplementsOnInitClass\"")==0) { + _bFeature_ImplementsOnInitClass = 1; + } else if (strcmp($1.strString, "\"ImplementsOnEndClass\"")==0) { + _bFeature_ImplementsOnEndClass = 1; + } else if (strcmp($1.strString, "\"ImplementsOnPrecache\"")==0) { + _bFeature_ImplementsOnPrecache = 1; + } else if (strcmp($1.strString, "\"ImplementsOnWorldInit\"")==0) { + _bFeature_ImplementsOnWorldInit = 1; + } else if (strcmp($1.strString, "\"ImplementsOnWorldEnd\"")==0) { + _bFeature_ImplementsOnWorldEnd = 1; + } else if (strcmp($1.strString, "\"ImplementsOnWorldTick\"")==0) { + _bFeature_ImplementsOnWorldTick = 1; + } else if (strcmp($1.strString, "\"ImplementsOnWorldRender\"")==0) { + _bFeature_ImplementsOnWorldRender = 1; + } else { + yyerror((SType("Unknown feature: ")+$1).strString); + } + } + ; + +opt_internal_properties + : /* null */ + | '{' internal_property_list '}' + ; +internal_property_list + : /* null */ + | internal_property_list internal_property + ; +internal_property + : any_type identifier ';' { + fprintf(_fDeclaration, "%s %s;\n", $1.strString, $2.strString); + } + ; + +/*///////////////////////////////////////////////////////// + * Property declarations + */ + +property_declaration_list + : empty_property_declaration_list { + DeclareFeatureProperties(); // this won't work, but at least it will generate an error!!!! + fprintf(_fTables, " CEntityProperty()\n};\n"); + fprintf(_fTables, "#define %s_propertiesct 0\n", _strCurrentClass); + fprintf(_fTables, "\n"); + fprintf(_fTables, "\n"); + } + | nonempty_property_declaration_list opt_comma { + DeclareFeatureProperties(); + fprintf(_fTables, "};\n"); + fprintf(_fTables, "#define %s_propertiesct ARRAYCOUNT(%s_properties)\n", + _strCurrentClass, _strCurrentClass); + fprintf(_fTables, "\n"); + } + ; +nonempty_property_declaration_list + : property_declaration + | nonempty_property_declaration_list ',' property_declaration + ; +empty_property_declaration_list + : /* null */ + ; + +property_declaration + : property_id property_type property_identifier property_wed_name_opt property_default_opt property_flags_opt { + fprintf(_fTables, " CEntityProperty(%s, %s, (0x%08x<<8)+%s, offsetof(%s, %s), %s, %s, %s, %s),\n", + _strCurrentPropertyPropertyType, + _strCurrentPropertyEnumType, + _iCurrentClassID, + _strCurrentPropertyID, + _strCurrentClass, + _strCurrentPropertyIdentifier, + _strCurrentPropertyName, + _strCurrentPropertyShortcut, + _strCurrentPropertyColor, + _strCurrentPropertyFlags); + fprintf(_fDeclaration, " %s %s;\n", + _strCurrentPropertyDataType, + _strCurrentPropertyIdentifier + ); + + if (strlen(_strCurrentPropertyDefaultCode)>0) { + fprintf(_fImplementation, " %s\n", _strCurrentPropertyDefaultCode); + } + } + ; + +property_id : c_int { _strCurrentPropertyID = $1.strString; }; +property_identifier : identifier { _strCurrentPropertyIdentifier = $1.strString; }; + +property_type + : k_enum identifier { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ENUM"; + _strCurrentPropertyEnumType = (SType("&")+$2+"_enum").strString; + _strCurrentPropertyDataType = (SType("enum ")+$2.strString).strString; + } + | k_FLAGS identifier { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLAGS"; + _strCurrentPropertyEnumType = (SType("&")+$2+"_enum").strString; + _strCurrentPropertyDataType = "ULONG"; + } + | k_CTString { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_STRING"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CTString"; + } + | k_CTStringTrans { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_STRINGTRANS"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CTStringTrans"; + } + | k_CTFileName { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FILENAME"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CTFileName"; + } + | k_CTFileNameNoDep { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FILENAMENODEP"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CTFileNameNoDep"; + } + | k_BOOL { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_BOOL"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "BOOL"; + } + | k_COLOR { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_COLOR"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "COLOR"; + } + | k_FLOAT { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOAT"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOAT"; + } + | k_INDEX { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_INDEX"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "INDEX"; + } + | k_RANGE { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_RANGE"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "RANGE"; + } + | k_CEntityPointer { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ENTITYPTR"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CEntityPointer"; + } + | k_CModelObject { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_MODELOBJECT"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CModelObject"; + } + | k_CModelInstance { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_MODELINSTANCE"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CModelInstance"; + } + | k_CAnimObject { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ANIMOBJECT"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CAnimObject"; + } + | k_CSoundObject { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_SOUNDOBJECT"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CSoundObject"; + } + | k_CPlacement3D { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_PLACEMENT3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "CPlacement3D"; + } + | k_FLOATaabbox3D { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOATAABBOX3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOATaabbox3D"; + } + | k_FLOATmatrix3D { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOATMATRIX3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOATmatrix3D"; + } + | k_FLOATquat3D { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOATQUAT3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOATquat3D"; + } + | k_ANGLE { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ANGLE"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "ANGLE"; + } + | k_ANGLE3D { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ANGLE3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "ANGLE3D"; + } + | k_FLOAT3D { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOAT3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOAT3D"; + } + | k_FLOATplane3D { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_FLOATplane3D"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "FLOATplane3D"; + } + | k_ILLUMINATIONTYPE { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ILLUMINATIONTYPE"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "ILLUMINATIONTYPE"; + } + | k_ANIMATION { + _strCurrentPropertyPropertyType = "CEntityProperty::EPT_ANIMATION"; + _strCurrentPropertyEnumType = "NULL"; + _strCurrentPropertyDataType = "ANIMATION"; + } + ; + +property_wed_name_opt + : /* null */ { + _strCurrentPropertyName = "\"\""; + _strCurrentPropertyShortcut = "0"; + _strCurrentPropertyColor = "0"; // this won't be rendered anyway + } + | c_string property_shortcut_opt property_color_opt { + _strCurrentPropertyName = $1.strString; + } + ; +property_shortcut_opt + : /* null */ { + _strCurrentPropertyShortcut = "0"; + } + | c_char { + _strCurrentPropertyShortcut = $1.strString; + } + +property_color_opt + : /* null */ { + _strCurrentPropertyColor = "0x7F0000FFUL"; // dark red + } + | k_COLOR '(' expression ')' { + _strCurrentPropertyColor = $3.strString; + } +property_flags_opt + : /* null */ { + _strCurrentPropertyFlags = "0"; // dark red + } + | k_features '(' expression ')' { + _strCurrentPropertyFlags = $3.strString; + } + +property_default_opt + : /* null */ { + if (strcmp(_strCurrentPropertyDataType,"CEntityPointer")==0) { + _strCurrentPropertyDefaultCode = (SType(_strCurrentPropertyIdentifier)+" = NULL;").strString; + } else if (strcmp(_strCurrentPropertyDataType,"CModelObject")==0) { + _strCurrentPropertyDefaultCode = + (SType(_strCurrentPropertyIdentifier)+".SetData(NULL);\n"+ + _strCurrentPropertyIdentifier+".mo_toTexture.SetData(NULL);").strString; + } else if (strcmp(_strCurrentPropertyDataType,"CModelInstance")==0) { + _strCurrentPropertyDefaultCode = + (SType(_strCurrentPropertyIdentifier)+".Clear();\n").strString; + } else if (strcmp(_strCurrentPropertyDataType,"CAnimObject")==0) { + _strCurrentPropertyDefaultCode = + (SType(_strCurrentPropertyIdentifier)+".SetData(NULL);\n").strString; + } else if (strcmp(_strCurrentPropertyDataType,"CSoundObject")==0) { + _strCurrentPropertyDefaultCode = + (SType(_strCurrentPropertyIdentifier)+".SetOwner(this);\n"+ + _strCurrentPropertyIdentifier+".Stop_internal();").strString; + } else { + yyerror("this kind of property must have default value"); + _strCurrentPropertyDefaultCode = ""; + } + } + | '=' property_default_expression { + if (strcmp(_strCurrentPropertyDataType,"CEntityPointer")==0) { + yyerror("CEntityPointer type properties always default to NULL"); + } else { + _strCurrentPropertyDefaultCode = (SType(_strCurrentPropertyIdentifier)+" = "+$2.strString+";").strString; + } + } + ; +property_default_expression + : c_int|c_float|c_bool|c_char|c_string + | identifier {$$ = $1 + " ";} + | identifier '(' expression ')' {$$ = $1+$2+$3+$4;} + | type_keyword '(' expression ')' {$$ = $1+$2+$3+$4;} + | '-' property_default_expression {$$ = $1+$2;} + | '(' expression ')' {$$ = $1+$2+$3;} + ; + +/*///////////////////////////////////////////////////////// + * Component declarations + */ +component_declaration_list + : empty_component_declaration_list { + fprintf(_fTables, " CEntityComponent()\n};\n"); + fprintf(_fTables, "#define %s_componentsct 0\n", _strCurrentClass); + fprintf(_fTables, "\n"); + fprintf(_fTables, "\n"); + } + | nonempty_component_declaration_list opt_comma { + fprintf(_fTables, "};\n"); + fprintf(_fTables, "#define %s_componentsct ARRAYCOUNT(%s_components)\n", + _strCurrentClass, _strCurrentClass); + fprintf(_fTables, "\n"); + } + ; +nonempty_component_declaration_list + : component_declaration + | nonempty_component_declaration_list ',' component_declaration + ; +empty_component_declaration_list + : /* null */ + ; + +component_declaration + : component_id component_type component_identifier component_filename { + fprintf(_fTables, "#define %s ((0x%08x<<8)+%s)\n", + _strCurrentComponentIdentifier, + _iCurrentClassID, + _strCurrentComponentID); + fprintf(_fTables, " CEntityComponent(%s, %s, \"%s%s\" %s),\n", + _strCurrentComponentType, + _strCurrentComponentIdentifier, + "EF","NM", + _strCurrentComponentFileName); + } + ; + +component_id : c_int { _strCurrentComponentID = $1.strString; }; +component_identifier : identifier { _strCurrentComponentIdentifier = $1.strString; }; +component_filename : c_string { _strCurrentComponentFileName = $1.strString; }; + +component_type + : k_model { _strCurrentComponentType = "ECT_MODEL"; } + | k_texture { _strCurrentComponentType = "ECT_TEXTURE"; } + | k_sound { _strCurrentComponentType = "ECT_SOUND"; } + | k_class { _strCurrentComponentType = "ECT_CLASS"; } + ; + +/*///////////////////////////////////////////////////////// + * Functions + */ +function_list + : { $$ = "";} + | function_list function_implementation {$$ = $1+$2;} + ; + +function_implementation + : opt_export opt_virtual return_type opt_tilde identifier '(' parameters_list ')' opt_const + '{' statements '}' opt_semicolon { + char *strReturnType = $3.strString; + char *strFunctionHeader = ($4+$5+$6+$7+$8+$9).strString; + char *strFunctionBody = ($10+$11+$12).strString; + if (strcmp($5.strString, _strCurrentClass)==0) { + if (strcmp(strReturnType+strlen(strReturnType)-4, "void")==0 ) { + strReturnType = ""; + } else { + yyerror("use 'void' as return type for constructors"); + } + } + fprintf(_fDeclaration, " %s %s %s %s;\n", + $1.strString, $2.strString, strReturnType, strFunctionHeader); + fprintf(_fImplementation, " %s %s::%s %s\n", + strReturnType, _strCurrentClass, strFunctionHeader, strFunctionBody); + } + ; +opt_tilde + : { $$ = "";} + | '~' { $$ = " ~ "; } + ; + +opt_export + : { $$ = "";} + | k_export { + if (_bClassIsExported) { + $$ = ""; + } else { + $$ = " DECL_DLL "; + } + } + ; + +opt_const + : { $$ = "";} + | k_const { $$ = $1; } + ; +opt_virtual + : { $$ = "";} + | k_virtual { $$ = $1; } + ; +opt_semicolon + : /* null */ + | ';' + ; +parameters_list + : { $$ = "";} + | k_void + | non_void_parameters_list + ; +non_void_parameters_list + : parameter_declaration + | non_void_parameters_list ',' parameter_declaration {$$ = $1+$2+$3;} + ; +parameter_declaration + : any_type identifier { $$=$1+" "+$2; } + ; + +return_type + : any_type + | k_void + ; + +any_type + : type_keyword + | identifier + | k_enum identifier { $$=$1+" "+$2; } + | any_type '*' { $$=$1+" "+$2; } + | any_type '&' { $$=$1+" "+$2; } + | k_void '*' { $$=$1+" "+$2; } + | k_const any_type { $$=$1+" "+$2; } + | k_inline any_type { $$=$1+" "+$2; } + | k_static any_type { $$=$1+" "+$2; } + | k_class any_type { $$=$1+" "+$2; } + | identifier '<' any_type '>' { $$=$1+" "+$2+" "+$3+" "+$4; } + ; + + +/*///////////////////////////////////////////////////////// + * Procedures + */ +procedure_list + : { $$ = "";} + | procedure_list procedure_implementation {$$ = $1+$2;} + ; + +opt_override + : { $$ = "-1"; } + | ':' identifier ':' ':' identifier { + $$ = SType("STATE_")+$2+"_"+$5; + } + ; + +procedure_implementation + : identifier '(' event_specification ')' opt_override { + char *strProcedureName = $1.strString; + char strInputEventType[80]; + char strInputEventName[80]; + sscanf($3.strString, "%s %s", strInputEventType, strInputEventName); + + char strStateID[256]; + char *strBaseStateID = "-1"; + if(strcmp(RemoveLineDirective(strProcedureName), "Main")==0){ + strcpy(strStateID, "1"); + if(strncmp(strInputEventType, "EVoid", 4)!=0 && _strCurrentThumbnail[2]!=0) { + yyerror("procedure 'Main' can take input parameters only in classes without thumbnails"); + } + } else { + sprintf(strStateID, "0x%08x", CreateID()); + } + + sprintf(_strCurrentStateID, "STATE_%s_%s", + _strCurrentClass, RemoveLineDirective(strProcedureName)); + fprintf(_fDeclaration, "#define %s %s\n", _strCurrentStateID, strStateID); + AddHandlerFunction(strProcedureName, strStateID, $5.strString); + fprintf(_fImplementation, + "BOOL %s::%s(const CEntityEvent &__eeInput) {\n#undef STATE_CURRENT\n#define STATE_CURRENT %s\n", + _strCurrentClass, strProcedureName, _strCurrentStateID); + fprintf(_fImplementation, + " ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_%s, \"%s::%s expects '%s' as input!\");", + strInputEventType, _strCurrentClass, RemoveLineDirective(strProcedureName), + strInputEventType); + fprintf(_fImplementation, " const %s &%s = (const %s &)__eeInput;", + strInputEventType, strInputEventName, strInputEventType); + + } '{' statements '}' opt_semicolon { + char *strFunctionBody = $8.strString; + fprintf(_fImplementation, "%s ASSERT(FALSE); return TRUE;};", strFunctionBody); + } + ; + +event_specification + : { + $$="EVoid e"; + } + | identifier { + $$=$1+" e"; + } + | identifier identifier { + $$=$1+" "+$2; + } + ; + +expression + : c_int|c_float|c_bool|c_char|c_string + | identifier {$$ = $1 + " ";} + | type_keyword + | '='|'+'|'-'|'<'|'>'|'!'|'|'|'&'|'*'|'/'|'%'|'^'|'['|']'|':'|','|'.'|'?'|'~' + | '(' ')' {$$=$1+$2;} + | '+' '+' {$$=$1+$2;} + | '-' '-' {$$=$1+$2;} + | '-' '>' {$$=$1+$2;} + | ':' ':' {$$=$1+$2;} + | '&' '&' {$$=$1+$2;} + | '|' '|' {$$=$1+$2;} + | '^' '^' {$$=$1+$2;} + | '>' '>' {$$=$1+$2;} + | '<' '<' {$$=$1+$2;} + | '=' '=' {$$=$1+$2;} + | '!' '=' {$$=$1+$2;} + | '>' '=' {$$=$1+$2;} + | '<' '=' {$$=$1+$2;} + | '&' '=' {$$=$1+$2;} + | '|' '=' {$$=$1+$2;} + | '^' '=' {$$=$1+$2;} + | '+' '=' {$$=$1+$2;} + | '-' '=' {$$=$1+$2;} + | '/' '=' {$$=$1+$2;} + | '%' '=' {$$=$1+$2;} + | '*' '=' {$$=$1+$2;} + | '>' '>' '=' {$$=$1+$2+$3;} + | '<' '<' '=' {$$=$1+$2+$3;} + | '(' expression ')' {$$ = $1+$2+$3;} + | expression expression {$$ = $1+" "+$2;} + ; +type_keyword + : k_CTString|k_CTStringTrans|k_CTFileName|k_CTFileNameNoDep + | k_BOOL|k_COLOR|k_FLOAT|k_INDEX|k_RANGE + | k_CEntityPointer|k_CModelObject|k_CModelInstance|k_CAnimObject|k_CSoundObject + | k_CPlacement3D | k_FLOATaabbox3D|k_FLOATmatrix3D| k_FLOATquat3D|k_ANGLE|k_ANIMATION|k_ILLUMINATIONTYPE + | k_ANGLE3D|k_FLOAT3D|k_FLOATplane3D + | k_const + | k_static + ; +case_constant_expression + : c_int|c_float|c_bool|c_char|c_string + | identifier {$$ = $1 + " ";} + ; + + +/* Simple statements: + */ +statements + : { $$ = "";} + | statements statement { $$ = $1+$2; } + ; +statement + : expression ';' {$$=$1+$2;} + | k_switch '(' expression ')' '{' statements '}' {$$=$1+$2+$3+$4+$5+$6+$7} + | k_case case_constant_expression ':' {$$=$1+" "+$2+$3+" ";} + | '{' statements '}' {$$=$1+$2+$3;} + | expression '{' statements '}' {$$=$1+$2+$3+$4;} + | statement_while + | statement_dowhile + | statement_for + | statement_if + | statement_if_else + | statement_wait + | statement_autowait + | statement_waitevent + | statement_call + | statement_autocall + | statement_stop + | statement_resume + | statement_pass + | statement_return + | statement_jump + | ';' + ; + + +statement_if + : k_if '(' expression ')' '{' statements '}' { + if ($6.bCrossesStates) { + char strAfterIfName[80], strAfterIfID[11]; + CreateInternalHandlerFunction(strAfterIfName, strAfterIfID); + $$ = $1+"(!"+$2+$3+$4+"){ Jump(STATE_CURRENT,"+strAfterIfID+", FALSE, EInternal());return TRUE;}"+$6+ + "Jump(STATE_CURRENT,"+strAfterIfID+", FALSE, EInternal());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+strAfterIfName+"(const CEntityEvent &__eeInput){"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+strAfterIfID+"\n"; + } else { + $$ = $1+$2+$3+$4+$5+$6+$7; + } + } + ; + +statement_if_else + : k_if '(' expression ')' '{' statements '}' k_else statement { + if ($6.bCrossesStates || $9.bCrossesStates) { + char strAfterIfName[80], strAfterIfID[11]; + char strElseName[80], strElseID[11]; + CreateInternalHandlerFunction(strAfterIfName, strAfterIfID); + CreateInternalHandlerFunction(strElseName, strElseID); + $$ = $1+"(!"+$2+$3+$4+"){ Jump(STATE_CURRENT,"+strElseID+", FALSE, EInternal());return TRUE;}"+ + $6+"Jump(STATE_CURRENT,"+strAfterIfID+", FALSE, EInternal());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+strElseName+"(const CEntityEvent &__eeInput){"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+strElseID+"\n"+ + $9+"Jump(STATE_CURRENT,"+strAfterIfID+", FALSE, EInternal());return TRUE;}\n"+ + "BOOL "+_strCurrentClass+"::"+strAfterIfName+"(const CEntityEvent &__eeInput){"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+strAfterIfID+"\n"; + } else { + $$ = $1+$2+$3+$4+$5+$6+$7+$8+" "+$9; + } + } + ; + +statement_while + : k_while '(' expression ')' { + if (strlen(_strInLoopName)>0) { + yyerror("Nested loops are not implemented yet"); + } + } '{' statements '}' { + if ($7.bCrossesStates) { + CreateInternalHandlerFunction(_strInLoopName, _strInLoopID); + CreateInternalHandlerFunction(_strAfterLoopName, _strAfterLoopID); + $$ = SType(GetLineDirective($1))+"Jump(STATE_CURRENT,"+_strInLoopID+", FALSE, EInternal());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInLoopName+"(const CEntityEvent &__eeInput)"+$6+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInLoopID+"\n"+ + "if(!"+$2+$3+$4+"){ Jump(STATE_CURRENT,"+_strAfterLoopID+", FALSE, EInternal());return TRUE;}"+ + $7+"Jump(STATE_CURRENT,"+_strInLoopID+", FALSE, EInternal());return TRUE;"+$8+ + "BOOL "+_strCurrentClass+"::"+_strAfterLoopName+"(const CEntityEvent &__eeInput) {"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterLoopID+"\n"; + } else { + $$ = $1+$2+$3+$4+$6+$7+$8; + } + _strInLoopName[0] = 0; + } + ; + +statement_dowhile + : k_do '{' statements '}' { + if (strlen(_strInLoopName)>0) { + yyerror("Nested loops are not implemented yet"); + } + _strInLoopName[0] = 0; + } k_while '(' expression ')' ';' { + if ($3.bCrossesStates) { + CreateInternalHandlerFunction(_strInLoopName, _strInLoopID); + CreateInternalHandlerFunction(_strAfterLoopName, _strAfterLoopID); + $$ = SType(GetLineDirective($1))+"Jump(STATE_CURRENT,"+_strInLoopID+", FALSE, EInternal());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInLoopName+"(const CEntityEvent &__eeInput)"+$2+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInLoopID+"\n"+$3+ + "if(!"+$7+$8+$9+"){ Jump(STATE_CURRENT,"+_strAfterLoopID+", FALSE, EInternal());return TRUE;}"+ + "Jump(STATE_CURRENT,"+_strInLoopID+", FALSE, EInternal());return TRUE;"+$4+ + "BOOL "+_strCurrentClass+"::"+_strAfterLoopName+"(const CEntityEvent &__eeInput) {"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterLoopID+"\n"; + } else { + $$ = $1+$2+$3+$4+$6+$7+$8+$9+$10; + } + _strInLoopName[0] = 0; + } + ; + +statement_for + : k_for '(' expression ';' expression ';' expression ')' { + if (strlen(_strInLoopName)>0) { + yyerror("Nested loops are not implemented yet"); + } + } '{' statements '}' { + if ($11.bCrossesStates) { + CreateInternalHandlerFunction(_strInLoopName, _strInLoopID); + CreateInternalHandlerFunction(_strAfterLoopName, _strAfterLoopID); + yyerror("For loops across states are not supported"); + } else { + $$ = $1+$2+$3+$4+$5+$6+$7+$8+$10+$11+$12; + } + _strInLoopName[0] = 0; + } + ; + +statement_wait + : k_wait wait_expression { + if (!_bInProcedure) { + yyerror("Cannot have 'wait' in functions"); + } + CreateInternalHandlerFunction(_strInWaitName, _strInWaitID); + CreateInternalHandlerFunction(_strAfterWaitName, _strAfterWaitID); + _bHasOtherwise = 0; + _bInHandler = 1; + } '{' handlers_list '}' { + if ($5.bCrossesStates) { + yyerror("'wait' statements must not be nested"); + $$ = ""; + } else { + SType stDefault; + if (!_bHasOtherwise) { + stDefault = SType("default: return FALSE; break;"); + } else { + stDefault = SType(""); + } + + $$ = SType(GetLineDirective($1))+$2+";\n"+ + "Jump(STATE_CURRENT, "+_strInWaitID+", FALSE, EBegin());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInWaitName+"(const CEntityEvent &__eeInput) {"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInWaitID+"\n"+ + "switch(__eeInput.ee_slEvent)"+$4+$5+stDefault+$6+ + "return TRUE;}BOOL "+_strCurrentClass+"::"+_strAfterWaitName+"(const CEntityEvent &__eeInput){"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterWaitID+"\n"; + $$.bCrossesStates = 1; + _bInHandler = 0; + } + } + ; +statement_autowait + : k_autowait wait_expression ';' { + if (!_bInProcedure) { + yyerror("Cannot have 'autowait' in functions"); + } + CreateInternalHandlerFunction(_strInWaitName, _strInWaitID); + CreateInternalHandlerFunction(_strAfterWaitName, _strAfterWaitID); + _bHasOtherwise = 0; + + $$ = SType(GetLineDirective($1))+$2+";\n"+ + "Jump(STATE_CURRENT, "+_strInWaitID+", FALSE, EBegin());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInWaitName+"(const CEntityEvent &__eeInput) {"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInWaitID+"\n"+ + "switch(__eeInput.ee_slEvent) {"+ + "case EVENTCODE_EBegin: return TRUE;"+ + "case EVENTCODE_ETimer: Jump(STATE_CURRENT,"+_strAfterWaitID+", FALSE, EInternal()); return TRUE;"+ + "default: return FALSE; }}"+ + "BOOL "+_strCurrentClass+"::"+_strAfterWaitName+"(const CEntityEvent &__eeInput){"+ + "\nASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal);"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterWaitID+"\n"+$3; + $$.bCrossesStates = 1; + } + ; + +statement_waitevent + : k_waitevent wait_expression identifier opt_eventvar ';' { + if (!_bInProcedure) { + yyerror("Cannot have 'autocall' in functions"); + } + CreateInternalHandlerFunction(_strInWaitName, _strInWaitID); + CreateInternalHandlerFunction(_strAfterWaitName, _strAfterWaitID); + _bHasOtherwise = 0; + + $$ = SType(GetLineDirective($1))+$2+";\n"+ + "Jump(STATE_CURRENT, "+_strInWaitID+", FALSE, EBegin());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInWaitName+"(const CEntityEvent &__eeInput) {"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInWaitID+"\n"+ + "switch(__eeInput.ee_slEvent) {"+ + "case EVENTCODE_EBegin: return TRUE;"+ + "case EVENTCODE_"+$3+": Jump(STATE_CURRENT,"+_strAfterWaitID+", FALSE, __eeInput); return TRUE;"+ + "default: return FALSE; }}"+ + "BOOL "+_strCurrentClass+"::"+_strAfterWaitName+"(const CEntityEvent &__eeInput){"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterWaitID+"\n"+ + "const "+$3+"&"+$4+"= ("+$3+"&)__eeInput;\n"+$5; + $$.bCrossesStates = 1; + } + ; + + +opt_eventvar + : { + $$ = SType("__e"); + } + | identifier { + $$ = $1; + } + +statement_autocall + : k_autocall jumptarget '(' event_expression ')' identifier opt_eventvar ';' { + if (!_bInProcedure) { + yyerror("Cannot have 'autocall' in functions"); + } + CreateInternalHandlerFunction(_strInWaitName, _strInWaitID); + CreateInternalHandlerFunction(_strAfterWaitName, _strAfterWaitID); + _bHasOtherwise = 0; + + $$ = SType(GetLineDirective($1))+$2+";\n"+ + "Jump(STATE_CURRENT, "+_strInWaitID+", FALSE, EBegin());return TRUE;}"+ + "BOOL "+_strCurrentClass+"::"+_strInWaitName+"(const CEntityEvent &__eeInput) {"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strInWaitID+"\n"+ + "switch(__eeInput.ee_slEvent) {"+ + "case EVENTCODE_EBegin: Call"+$3+"STATE_CURRENT, "+$2+", "+$4+$5+";return TRUE;"+ + "case EVENTCODE_"+$6+": Jump(STATE_CURRENT,"+_strAfterWaitID+", FALSE, __eeInput); return TRUE;"+ + "default: return FALSE; }}"+ + "BOOL "+_strCurrentClass+"::"+_strAfterWaitName+"(const CEntityEvent &__eeInput){"+ + "\n#undef STATE_CURRENT\n#define STATE_CURRENT "+_strAfterWaitID+"\n"+ + "const "+$6+"&"+$7+"= ("+$6+"&)__eeInput;\n"+$8; + $$.bCrossesStates = 1; + } + ; + +wait_expression + : '(' ')' { + $$ = SType("SetTimerAt(THINKTIME_NEVER)"); + } + | '(' expression ')' { + $$ = SType("SetTimerAfter")+$1+$2+$3; + } + ; + +statement_jump + : k_jump jumptarget '(' event_expression ')' ';' { + if (!_bInProcedure) { + yyerror("Cannot have 'jump' in functions"); + } + $$ = SType(GetLineDirective($1))+"Jump"+$3+"STATE_CURRENT, "+$2+", "+$4+$5+";return TRUE;"; + } + ; + +statement_call + : k_call jumptarget '(' event_expression')' ';' { + if (!_bInProcedure) { + yyerror("Cannot have 'call' in functions"); + } + if (!_bInHandler) { + yyerror("'call' must be inside a 'wait' statement"); + } + $$ = SType(GetLineDirective($1))+"Call"+$3+"STATE_CURRENT, "+$2+", "+$4+$5+";return TRUE;"; + } + ; + +event_expression + : expression { + $$ = $1; + } + | { + $$ = SType("EVoid()"); + } + ; + +jumptarget + : identifier { + $$ = SType("STATE_")+_strCurrentClass+"_"+$1+", TRUE"; + } + | identifier ':' ':' identifier { + $$ = SType("STATE_")+$1+"_"+$4+", FALSE"; + } + ; + +statement_stop + : k_stop ';' { + $$ = SType(GetLineDirective($1))+"UnsetTimer();Jump(STATE_CURRENT," + +_strAfterWaitID+", FALSE, EInternal());"+"return TRUE"+$2; + } + ; +statement_resume + : k_resume ';' { + $$ = SType(GetLineDirective($1))+"return TRUE"+$2; + } + ; +statement_pass + : k_pass ';' { + $$ = SType(GetLineDirective($1))+"return FALSE"+$2; + } + ; +statement_return + : k_return opt_expression ';' { + if (!_bInProcedure) { + $$ = $1+" "+$2+$3; + } else { + if (strlen($2.strString)==0) { + $2 = SType("EVoid()"); + } + $$ = SType(GetLineDirective($1)) + +"Return(STATE_CURRENT,"+$2+");" + +$1+" TRUE"+$3; + } + } + ; +opt_expression + : {$$ = "";} + | expression + ; + +handler + : k_on '(' event_specification ')' ':' '{' statements '}' opt_semicolon { + char strInputEventType[80]; + char strInputEventName[80]; + sscanf($3.strString, "%s %s", strInputEventType, strInputEventName); + + $$ = SType("case")+$2+"EVENTCODE_"+strInputEventType+$4+$5+$6+ + "const "+strInputEventType+"&"+strInputEventName+"= ("+ + strInputEventType+"&)__eeInput;\n"+$7+$8+"ASSERT(FALSE);break;"; + } + | k_otherwise '(' event_specification ')' ':' '{' statements '}' opt_semicolon { + char strInputEventType[80]; + char strInputEventName[80]; + sscanf($3.strString, "%s %s", strInputEventType, strInputEventName); + + $$ = SType("default")+$5+$6+$7+$8+"ASSERT(FALSE);break;"; + _bHasOtherwise = 1; + } + ; +handlers_list + : { $$ = "";} + | handlers_list handler { $$ = $1+$2; } + ; + +%% diff --git a/Sources/Ecc/Scanner.cpp b/Sources/Ecc/Scanner.cpp new file mode 100644 index 0000000..d31f14b --- /dev/null +++ b/Sources/Ecc/Scanner.cpp @@ -0,0 +1,2211 @@ +#line 2 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.cpp" +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.85 95/04/24 10:48:47 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 84 +#define YY_END_OF_BUFFER 85 +static yyconst short int yy_accept[415] = + { 0, + 0, 0, 0, 0, 76, 76, 85, 83, 81, 82, + 65, 83, 65, 83, 65, 66, 66, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 79, 79, 76, 75, 76, 81, 0, 70, 73, + 0, 71, 77, 0, 68, 66, 0, 0, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 9, 72, 72, 72, + 72, 72, 72, 72, 72, 5, 72, 72, 72, 72, + 33, 72, 72, 72, 72, 72, 72, 72, 72, 72, + + 72, 72, 72, 72, 72, 78, 76, 74, 0, 80, + 68, 68, 0, 69, 67, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 4, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 69, 72, 72, 44, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 35, 3, 72, 72, 72, 6, 7, 72, 72, + 72, 72, 72, 72, 36, 72, 20, 72, 39, 72, + + 72, 72, 72, 72, 72, 37, 72, 72, 72, 23, + 72, 10, 32, 72, 58, 72, 72, 72, 72, 45, + 72, 72, 72, 72, 46, 72, 47, 48, 72, 72, + 8, 72, 11, 19, 72, 72, 64, 72, 72, 27, + 72, 72, 72, 72, 72, 26, 72, 72, 72, 72, + 72, 72, 1, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 24, 72, 72, 12, 72, 72, 72, 38, 15, + 13, 2, 72, 72, 72, 72, 62, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 61, 72, 72, 72, + + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 25, 72, 14, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 40, 72, 72, 72, 72, 72, 17, 16, + 72, 22, 72, 72, 72, 72, 72, 72, 59, 72, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 72, 72, 72, 30, 34, 72, 72, 21, 18, 72, + 72, 72, 72, 72, 72, 42, 72, 72, 72, 72, + 72, 72, 29, 31, 28, 52, 72, 72, 72, 72, + 72, 72, 72, 72, 72, 72, 57, 72, 72, 72, + 50, 54, 53, 72, 72, 72, 72, 63, 72, 72, + + 72, 72, 41, 55, 56, 72, 49, 51, 72, 72, + 43, 72, 60, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 1, 1, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, + 19, 18, 18, 18, 18, 18, 18, 20, 21, 22, + 23, 24, 25, 1, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 33, 33, 35, 36, 37, 38, 39, + 33, 40, 41, 42, 43, 33, 33, 44, 45, 33, + 46, 1, 47, 48, 33, 1, 49, 50, 51, 52, + + 53, 54, 55, 56, 57, 58, 33, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 33, 73, 74, 75, 76, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[77] = + { 0, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 3, 3, 3, 1, + 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 1, 1, 1, 3, 3, + 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 1, 1, 1, 1 + } ; + +static yyconst short int yy_base[423] = + { 0, + 0, 0, 74, 75, 76, 77, 511, 512, 508, 512, + 512, 504, 435, 499, 73, 73, 78, 469, 467, 68, + 0, 469, 64, 477, 434, 53, 439, 52, 65, 68, + 432, 437, 449, 20, 51, 444, 58, 61, 430, 73, + 83, 512, 479, 0, 512, 419, 491, 487, 512, 512, + 483, 512, 512, 487, 119, 128, 142, 0, 0, 108, + 451, 427, 426, 424, 450, 425, 421, 110, 444, 446, + 451, 442, 411, 89, 428, 92, 0, 410, 407, 421, + 410, 423, 422, 405, 408, 0, 409, 407, 414, 405, + 0, 408, 397, 400, 96, 393, 108, 403, 388, 390, + + 404, 391, 398, 397, 396, 512, 0, 0, 449, 512, + 147, 512, 150, 157, 0, 416, 414, 414, 391, 380, + 394, 407, 395, 375, 385, 374, 414, 396, 408, 405, + 374, 376, 381, 367, 369, 365, 377, 369, 367, 365, + 359, 370, 0, 373, 366, 359, 368, 367, 366, 352, + 120, 349, 348, 354, 347, 350, 345, 344, 350, 343, + 341, 355, 339, 346, 512, 374, 377, 0, 342, 344, + 347, 359, 347, 336, 337, 330, 352, 357, 348, 361, + 128, 0, 0, 324, 327, 321, 0, 0, 320, 321, + 317, 318, 316, 321, 0, 322, 0, 315, 0, 326, + + 325, 317, 311, 323, 317, 0, 322, 304, 321, 0, + 302, 0, 316, 315, 348, 324, 327, 297, 304, 0, + 309, 309, 307, 302, 161, 324, 0, 0, 308, 307, + 0, 294, 0, 0, 287, 288, 0, 295, 298, 0, + 280, 297, 283, 294, 285, 0, 294, 288, 278, 281, + 292, 271, 0, 310, 304, 287, 264, 148, 275, 296, + 296, 271, 302, 281, 280, 269, 259, 289, 266, 267, + 270, 0, 269, 259, 0, 263, 251, 251, 0, 0, + 0, 0, 264, 267, 256, 261, 0, 275, 254, 272, + 249, 259, 255, 257, 257, 250, 0, 254, 236, 253, + + 252, 274, 240, 231, 236, 230, 234, 228, 228, 235, + 0, 234, 0, 229, 252, 235, 225, 220, 227, 223, + 225, 222, 239, 230, 214, 217, 210, 234, 0, 0, + 208, 0, 208, 220, 219, 218, 211, 202, 0, 217, + 210, 199, 212, 197, 210, 209, 196, 198, 202, 205, + 238, 222, 189, 0, 0, 188, 187, 0, 0, 185, + 184, 190, 184, 204, 171, 183, 170, 147, 146, 197, + 186, 176, 0, 0, 0, 0, 146, 151, 142, 179, + 140, 144, 144, 185, 184, 173, 0, 162, 144, 145, + 0, 0, 0, 166, 128, 164, 163, 0, 149, 125, + + 136, 134, 0, 0, 0, 140, 0, 0, 121, 95, + 0, 89, 0, 512, 225, 229, 233, 237, 239, 243, + 247, 102 + } ; + +static yyconst short int yy_def[423] = + { 0, + 414, 1, 415, 415, 416, 416, 414, 414, 414, 414, + 414, 417, 414, 418, 414, 414, 414, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 414, 414, 420, 414, 420, 414, 417, 414, 414, + 418, 414, 414, 421, 414, 414, 414, 422, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + + 419, 419, 419, 419, 419, 414, 420, 420, 421, 414, + 414, 414, 414, 414, 422, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 414, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + + 419, 419, 419, 419, 419, 419, 419, 419, 419, 419, + 419, 419, 419, 0, 414, 414, 414, 414, 414, 414, + 414, 414 + } ; + +static yyconst short int yy_nxt[589] = + { 0, + 8, 9, 10, 11, 12, 13, 11, 14, 11, 11, + 11, 11, 11, 11, 11, 15, 16, 17, 17, 11, + 11, 11, 11, 11, 11, 18, 19, 20, 21, 21, + 22, 21, 21, 23, 21, 21, 21, 21, 21, 24, + 21, 21, 21, 21, 21, 11, 11, 11, 25, 21, + 26, 27, 28, 29, 21, 21, 30, 31, 21, 32, + 33, 34, 35, 21, 36, 37, 38, 39, 40, 41, + 21, 21, 11, 11, 11, 11, 10, 10, 45, 45, + 91, 46, 46, 53, 43, 43, 92, 55, 54, 56, + 56, 56, 55, 62, 56, 56, 56, 63, 70, 93, + + 71, 74, 57, 64, 115, 65, 66, 57, 67, 68, + 78, 75, 79, 99, 76, 94, 100, 82, 413, 96, + 80, 86, 81, 83, 97, 57, 84, 98, 87, 102, + 57, 104, 85, 412, 103, 111, 111, 111, 105, 116, + 125, 117, 55, 58, 56, 56, 56, 132, 57, 112, + 126, 135, 136, 113, 133, 113, 155, 57, 114, 114, + 114, 152, 153, 111, 111, 111, 114, 114, 114, 156, + 200, 57, 112, 114, 114, 114, 57, 112, 229, 263, + 57, 291, 201, 411, 410, 292, 409, 165, 408, 407, + 406, 405, 404, 403, 402, 401, 400, 230, 399, 57, + + 112, 398, 397, 396, 395, 394, 393, 392, 391, 264, + 165, 390, 389, 388, 387, 386, 385, 384, 383, 382, + 265, 381, 380, 266, 267, 42, 42, 42, 42, 44, + 44, 44, 44, 48, 379, 48, 48, 51, 378, 51, + 51, 59, 59, 107, 377, 107, 107, 109, 109, 109, + 109, 376, 375, 374, 373, 372, 371, 370, 369, 368, + 367, 366, 365, 364, 363, 362, 361, 360, 359, 358, + 357, 356, 355, 354, 353, 352, 351, 350, 349, 348, + 347, 346, 345, 344, 343, 342, 341, 340, 339, 338, + 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, + + 327, 326, 325, 324, 323, 322, 321, 320, 319, 318, + 317, 316, 315, 314, 313, 312, 311, 310, 309, 308, + 307, 306, 305, 304, 303, 302, 301, 300, 299, 298, + 297, 296, 295, 294, 293, 290, 289, 288, 287, 286, + 285, 284, 283, 282, 281, 280, 279, 278, 277, 276, + 275, 274, 273, 272, 271, 270, 269, 268, 262, 261, + 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, + 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, + 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, + 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, + + 218, 217, 216, 215, 214, 213, 212, 211, 210, 209, + 208, 207, 206, 205, 204, 203, 202, 199, 198, 197, + 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, + 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, + 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, + 166, 110, 164, 163, 162, 161, 160, 159, 158, 157, + 154, 151, 150, 149, 148, 147, 146, 145, 144, 143, + 142, 141, 140, 139, 138, 137, 134, 131, 130, 129, + 128, 127, 124, 123, 122, 121, 120, 119, 118, 110, + 52, 49, 47, 108, 106, 101, 95, 90, 89, 88, + + 77, 73, 72, 69, 61, 60, 52, 50, 49, 47, + 414, 7, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414 + } ; + +static yyconst short int yy_chk[589] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 3, 4, 5, 6, + 34, 5, 6, 15, 3, 4, 34, 16, 15, 16, + 16, 16, 17, 20, 17, 17, 17, 20, 23, 35, + + 23, 26, 16, 20, 422, 20, 20, 17, 20, 20, + 28, 26, 28, 38, 26, 35, 38, 29, 412, 37, + 28, 30, 28, 29, 37, 16, 29, 37, 30, 40, + 17, 41, 29, 410, 40, 55, 55, 55, 41, 60, + 68, 60, 56, 16, 56, 56, 56, 74, 55, 55, + 68, 76, 76, 57, 74, 57, 97, 56, 57, 57, + 57, 95, 95, 111, 111, 111, 113, 113, 113, 97, + 151, 55, 55, 114, 114, 114, 111, 111, 181, 225, + 56, 258, 151, 409, 406, 258, 402, 114, 401, 400, + 399, 397, 396, 395, 394, 390, 389, 181, 388, 111, + + 111, 386, 385, 384, 383, 382, 381, 380, 379, 225, + 114, 378, 377, 372, 371, 370, 369, 368, 367, 366, + 225, 365, 364, 225, 225, 415, 415, 415, 415, 416, + 416, 416, 416, 417, 363, 417, 417, 418, 362, 418, + 418, 419, 419, 420, 361, 420, 420, 421, 421, 421, + 421, 360, 357, 356, 353, 352, 351, 350, 349, 348, + 347, 346, 345, 344, 343, 342, 341, 340, 338, 337, + 336, 335, 334, 333, 331, 328, 327, 326, 325, 324, + 323, 322, 321, 320, 319, 318, 317, 316, 315, 314, + 312, 310, 309, 308, 307, 306, 305, 304, 303, 302, + + 301, 300, 299, 298, 296, 295, 294, 293, 292, 291, + 290, 289, 288, 286, 285, 284, 283, 278, 277, 276, + 274, 273, 271, 270, 269, 268, 267, 266, 265, 264, + 263, 262, 261, 260, 259, 257, 256, 255, 254, 252, + 251, 250, 249, 248, 247, 245, 244, 243, 242, 241, + 239, 238, 236, 235, 232, 230, 229, 226, 224, 223, + 222, 221, 219, 218, 217, 216, 215, 214, 213, 211, + 209, 208, 207, 205, 204, 203, 202, 201, 200, 198, + 196, 194, 193, 192, 191, 190, 189, 186, 185, 184, + 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, + + 170, 169, 167, 166, 164, 163, 162, 161, 160, 159, + 158, 157, 156, 155, 154, 153, 152, 150, 149, 148, + 147, 146, 145, 144, 142, 141, 140, 139, 138, 137, + 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, + 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, + 116, 109, 105, 104, 103, 102, 101, 100, 99, 98, + 96, 94, 93, 92, 90, 89, 88, 87, 85, 84, + 83, 82, 81, 80, 79, 78, 75, 73, 72, 71, + 70, 69, 67, 66, 65, 64, 63, 62, 61, 54, + 51, 48, 47, 46, 43, 39, 36, 33, 32, 31, + + 27, 25, 24, 22, 19, 18, 14, 13, 12, 9, + 7, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414, 414, 414, + 414, 414, 414, 414, 414, 414, 414, 414 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *yytext; +#line 1 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +#define INITIAL 0 +#line 2 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +// rcg10042001 Changed to specify Ecc directory... +#include "Ecc/StdH.h" +#include "Ecc/Main.h" +#include "Ecc/Parser.h" + +#define YY_NEVER_INTERACTIVE 1 + + +int iLastLine = -1; + +#define RETURN(symbolname) \ + if (iLastLine==_iLinesCt || !_bTrackLineInformation){\ + yylval = yytext; \ + } else { \ + char strLine[200]; \ + sprintf(strLine, "\n#line %d \"%s\"\n", _iLinesCt, _strInputFileName);\ + yylval = SType(strLine)+yytext; \ + iLastLine=_iLinesCt; \ + } \ + return symbolname; + +char *_strCppBlock; + +#define COMMENT 1 + +#define CPPBLOCK 2 + +#line 660 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.cpp" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 38 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" + + + /* standard cpp-keywords */ +#line 811 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.cpp" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 415 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 512 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 41 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_while);} + YY_BREAK +case 2: +YY_RULE_SETUP +#line 42 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_switch);} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 43 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_case);} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 44 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_for);} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 45 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_if);} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 46 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_else);} + YY_BREAK +case 7: +YY_RULE_SETUP +#line 47 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_enum);} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 48 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_class);} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 49 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_do);} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 50 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_void);} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 51 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_const);} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 52 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_inline);} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 53 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_static);} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 54 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_virtual);} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 55 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_return);} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 56 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_autowait);} + YY_BREAK +case 17: +YY_RULE_SETUP +#line 57 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_autocall);} + YY_BREAK +case 18: +YY_RULE_SETUP +#line 58 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_waitevent);} + YY_BREAK +/* aditional keywords */ +case 19: +YY_RULE_SETUP +#line 61 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_event);} + YY_BREAK +case 20: +YY_RULE_SETUP +#line 62 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_name);} + YY_BREAK +case 21: +YY_RULE_SETUP +#line 63 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_thumbnail);} + YY_BREAK +case 22: +YY_RULE_SETUP +#line 64 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_features);} + YY_BREAK +case 23: +YY_RULE_SETUP +#line 65 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_uses);} + YY_BREAK +case 24: +YY_RULE_SETUP +#line 66 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_export);} + YY_BREAK +case 25: +YY_RULE_SETUP +#line 68 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_texture);} + YY_BREAK +case 26: +YY_RULE_SETUP +#line 69 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_sound);} + YY_BREAK +case 27: +YY_RULE_SETUP +#line 70 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_model);} + YY_BREAK +case 28: +YY_RULE_SETUP +#line 72 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_properties);} + YY_BREAK +case 29: +YY_RULE_SETUP +#line 73 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_components);} + YY_BREAK +case 30: +YY_RULE_SETUP +#line 74 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_functions);} + YY_BREAK +case 31: +YY_RULE_SETUP +#line 75 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_procedures);} + YY_BREAK +case 32: +YY_RULE_SETUP +#line 77 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_wait );} + YY_BREAK +case 33: +YY_RULE_SETUP +#line 78 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_on );} + YY_BREAK +case 34: +YY_RULE_SETUP +#line 79 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_otherwise);} + YY_BREAK +case 35: +YY_RULE_SETUP +#line 81 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_call );} + YY_BREAK +case 36: +YY_RULE_SETUP +#line 82 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_jump );} + YY_BREAK +case 37: +YY_RULE_SETUP +#line 83 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_stop );} + YY_BREAK +case 38: +YY_RULE_SETUP +#line 84 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_resume );} + YY_BREAK +case 39: +YY_RULE_SETUP +#line 85 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_pass );} + YY_BREAK +/* special data types */ +case 40: +YY_RULE_SETUP +#line 88 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_CTString);} + YY_BREAK +case 41: +YY_RULE_SETUP +#line 89 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_CTStringTrans);} + YY_BREAK +case 42: +YY_RULE_SETUP +#line 90 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_CTFileName);} + YY_BREAK +case 43: +YY_RULE_SETUP +#line 91 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_CTFileNameNoDep);} + YY_BREAK +case 44: +YY_RULE_SETUP +#line 92 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_BOOL);} + YY_BREAK +case 45: +YY_RULE_SETUP +#line 93 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_COLOR);} + YY_BREAK +case 46: +YY_RULE_SETUP +#line 94 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_FLOAT);} + YY_BREAK +case 47: +YY_RULE_SETUP +#line 95 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_INDEX);} + YY_BREAK +case 48: +YY_RULE_SETUP +#line 96 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_RANGE);} + YY_BREAK +case 49: +YY_RULE_SETUP +#line 97 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_CEntityPointer);} + YY_BREAK +case 50: +YY_RULE_SETUP +#line 98 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_CModelObject);} + YY_BREAK +case 51: +YY_RULE_SETUP +#line 99 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_CModelInstance);} + YY_BREAK +case 52: +YY_RULE_SETUP +#line 100 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_CAnimObject);} + YY_BREAK +case 53: +YY_RULE_SETUP +#line 101 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_CSoundObject);} + YY_BREAK +case 54: +YY_RULE_SETUP +#line 102 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_CPlacement3D);} + YY_BREAK +case 55: +YY_RULE_SETUP +#line 103 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_FLOATaabbox3D);} + YY_BREAK +case 56: +YY_RULE_SETUP +#line 104 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_FLOATmatrix3D);} + YY_BREAK +case 57: +YY_RULE_SETUP +#line 105 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_FLOATquat3D);} + YY_BREAK +case 58: +YY_RULE_SETUP +#line 106 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_ANGLE);}; + YY_BREAK +case 59: +YY_RULE_SETUP +#line 107 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_ANIMATION);}; + YY_BREAK +case 60: +YY_RULE_SETUP +#line 108 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_ILLUMINATIONTYPE);}; + YY_BREAK +case 61: +YY_RULE_SETUP +#line 109 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_FLOAT3D);}; + YY_BREAK +case 62: +YY_RULE_SETUP +#line 110 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_ANGLE3D);}; + YY_BREAK +case 63: +YY_RULE_SETUP +#line 111 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_FLOATplane3D);}; + YY_BREAK +case 64: +YY_RULE_SETUP +#line 112 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(k_FLAGS);}; + YY_BREAK +/* single character operators and punctuations */ +case 65: +YY_RULE_SETUP +#line 115 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ + RETURN(yytext[0]);} + YY_BREAK +/* constants */ +case 66: +YY_RULE_SETUP +#line 119 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ RETURN(c_int); } + YY_BREAK +case 67: +YY_RULE_SETUP +#line 120 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ RETURN(c_int)}; + YY_BREAK +case 68: +YY_RULE_SETUP +#line 121 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ RETURN(c_int); } + YY_BREAK +case 69: +YY_RULE_SETUP +#line 122 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ RETURN(c_int); } + YY_BREAK +case 70: +YY_RULE_SETUP +#line 123 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ RETURN(c_string); } + YY_BREAK +case 71: +YY_RULE_SETUP +#line 124 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ RETURN(c_char); } + YY_BREAK +/* identifier */ +case 72: +YY_RULE_SETUP +#line 127 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{RETURN(identifier);} + YY_BREAK +/* specially bracketed cpp blocks */ +case 73: +YY_RULE_SETUP +#line 130 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ + char strLine[80]; + sprintf(strLine, "#line %d \"%s\"\n", _iLinesCt, _strInputFileName ); + _strCppBlock = strdup(strLine); + BEGIN(CPPBLOCK); +} + YY_BREAK +case 74: +YY_RULE_SETUP +#line 136 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ + BEGIN(INITIAL); + yylval = SType(_strCppBlock); + return cppblock; +} + YY_BREAK +case 75: +YY_RULE_SETUP +#line 141 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ + _iLinesCt++; + _strCppBlock = (SType(_strCppBlock)+yytext).strString; + } + YY_BREAK +case 76: +YY_RULE_SETUP +#line 145 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ + _strCppBlock = (SType(_strCppBlock)+yytext).strString; +} + YY_BREAK +/* eat up comments */ +case 77: +YY_RULE_SETUP +#line 150 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ BEGIN(COMMENT); } + YY_BREAK +case 78: +YY_RULE_SETUP +#line 151 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ BEGIN(INITIAL); } + YY_BREAK +case 79: +YY_RULE_SETUP +#line 152 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{} + YY_BREAK +case 80: +YY_RULE_SETUP +#line 153 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ _iLinesCt++; } + YY_BREAK +/* eat up whitespace */ +case 81: +YY_RULE_SETUP +#line 156 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ +} + YY_BREAK +/* eat up linefeeds and count lines in all conditions */ +case 82: +YY_RULE_SETUP +#line 159 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ + _iLinesCt++; + } + YY_BREAK +/* for all unrecognized characters */ +case 83: +YY_RULE_SETUP +#line 163 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +{ + // report an error + char strError[80]; + sprintf(strError, "Unrecognized character '%c' (ASCII 0x%02x)\n", + yytext[0], yytext[0] ); + yyerror(strError); +} + YY_BREAK +case 84: +YY_RULE_SETUP +#line 171 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" +ECHO; + YY_BREAK +#line 1348 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.cpp" +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMENT): +case YY_STATE_EOF(CPPBLOCK): + yyterminate(); + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 415 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 415 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 414); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +yyconst char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 171 "D:\\SE1_GPL\\Sources\\Ecc\\\\Scanner.l" + + diff --git a/Sources/Ecc/Scanner.l b/Sources/Ecc/Scanner.l new file mode 100644 index 0000000..3fa9a01 --- /dev/null +++ b/Sources/Ecc/Scanner.l @@ -0,0 +1,172 @@ +%{ +// rcg10042001 Changed to specify Ecc directory... +#include "Ecc/StdH.h" +#include "Ecc/Main.h" +#include "Ecc/Parser.h" + +#define YY_NEVER_INTERACTIVE 1 + + +int iLastLine = -1; + +#define RETURN(symbolname) \ + if (iLastLine==_iLinesCt || !_bTrackLineInformation){\ + yylval = yytext; \ + } else { \ + char strLine[200]; \ + sprintf(strLine, "\n#line %d \"%s\"\n", _iLinesCt, _strInputFileName);\ + yylval = SType(strLine)+yytext; \ + iLastLine=_iLinesCt; \ + } \ + return symbolname; + +char *_strCppBlock; + +%} + +%x COMMENT +%x CPPBLOCK + +DIGIT [0-9] +HEXDIGIT [0-9A-Fa-f] +IDENTIFIERFIRST [A-Za-z_] +IDENTIFIEROTHER [A-Za-z0-9_] +DOUBLEQUOTE \" +NONEXP_FLT ({DIGIT}+"."{DIGIT}*) +EXP_FLT (({DIGIT}+("."({DIGIT}*)?)?)("E"|"e")("+"|"-")?{DIGIT}+) + +%% + + /* standard cpp-keywords */ +"while" {RETURN(k_while);} +"switch" {RETURN(k_switch);} +"case" {RETURN(k_case);} +"for" {RETURN(k_for);} +"if" {RETURN(k_if);} +"else" {RETURN(k_else);} +"enum" {RETURN(k_enum);} +"class" {RETURN(k_class);} +"do" {RETURN(k_do);} +"void" {RETURN(k_void);} +"const" {RETURN(k_const);} +"inline" {RETURN(k_inline);} +"static" {RETURN(k_static);} +"virtual" {RETURN(k_virtual);} +"return" {RETURN(k_return);} +"autowait" {RETURN(k_autowait);} +"autocall" {RETURN(k_autocall);} +"waitevent" {RETURN(k_waitevent);} + + /* aditional keywords */ +"event" {RETURN(k_event);} +"name" {RETURN(k_name);} +"thumbnail" {RETURN(k_thumbnail);} +"features" {RETURN(k_features);} +"uses" {RETURN(k_uses);} +"export" {RETURN(k_export);} + +"texture" {RETURN(k_texture);} +"sound" {RETURN(k_sound);} +"model" {RETURN(k_model);} + +"properties" {RETURN(k_properties);} +"components" {RETURN(k_components);} +"functions" {RETURN(k_functions);} +"procedures" {RETURN(k_procedures);} + +"wait" {RETURN(k_wait );} +"on" {RETURN(k_on );} +"otherwise" {RETURN(k_otherwise);} + +"call" {RETURN(k_call );} +"jump" {RETURN(k_jump );} +"stop" {RETURN(k_stop );} +"resume" {RETURN(k_resume );} +"pass" {RETURN(k_pass );} + + /* special data types */ +"CTString" {RETURN(k_CTString);} +"CTStringTrans" {RETURN(k_CTStringTrans);} +"CTFileName" {RETURN(k_CTFileName);} +"CTFileNameNoDep" {RETURN(k_CTFileNameNoDep);} +"BOOL" {RETURN(k_BOOL);} +"COLOR" {RETURN(k_COLOR);} +"FLOAT" {RETURN(k_FLOAT);} +"INDEX" {RETURN(k_INDEX);} +"RANGE" {RETURN(k_RANGE);} +"CEntityPointer" {RETURN(k_CEntityPointer);} +"CModelObject" {RETURN(k_CModelObject);} +"CModelInstance" {RETURN(k_CModelInstance);} +"CAnimObject" {RETURN(k_CAnimObject);} +"CSoundObject" {RETURN(k_CSoundObject);} +"CPlacement3D" {RETURN(k_CPlacement3D);} +"FLOATaabbox3D" {RETURN(k_FLOATaabbox3D);} +"FLOATmatrix3D" {RETURN(k_FLOATmatrix3D);} +"FLOATquat3D" {RETURN(k_FLOATquat3D);} +"ANGLE" {RETURN(k_ANGLE);}; +"ANIMATION" {RETURN(k_ANIMATION);}; +"ILLUMINATIONTYPE" {RETURN(k_ILLUMINATIONTYPE);}; +"FLOAT3D" {RETURN(k_FLOAT3D);}; +"ANGLE3D" {RETURN(k_ANGLE3D);}; +"FLOATplane3D" {RETURN(k_FLOATplane3D);}; +"flags" {RETURN(k_FLAGS);}; + + /* single character operators and punctuations */ +";"|"("|")"|"{"|"}"|"="|"+"|"-"|"<"|">"|"!"|"|"|"&"|"*"|"/"|"%"|"^"|"["|"]"|":"|","|"."|"?"|"~" { + RETURN(yytext[0]);} + + /* constants */ +{DIGIT}+ { RETURN(c_int); } +"0x"{HEXDIGIT}+ { RETURN(c_int)}; +{NONEXP_FLT}("f"|"F")? { RETURN(c_int); } +{EXP_FLT}("f"|"F")? { RETURN(c_int); } +(\"[^\n"]+\")|(\"\") { RETURN(c_string); } +(\'[^\n']+\')|(\'\') { RETURN(c_char); } + + /* identifier */ +{IDENTIFIERFIRST}{IDENTIFIEROTHER}* {RETURN(identifier);} + + /* specially bracketed cpp blocks */ +"%{" { + char strLine[80]; + sprintf(strLine, "#line %d \"%s\"\n", _iLinesCt, _strInputFileName ); + _strCppBlock = strdup(strLine); + BEGIN(CPPBLOCK); +} +"%}" { + BEGIN(INITIAL); + yylval = SType(_strCppBlock); + return cppblock; +} +\n { + _iLinesCt++; + _strCppBlock = (SType(_strCppBlock)+yytext).strString; + } +.* { + _strCppBlock = (SType(_strCppBlock)+yytext).strString; +} + + /* eat up comments */ +"/*" { BEGIN(COMMENT); } +"*/" { BEGIN(INITIAL); } +. {} +"//"[^\n]*\n { _iLinesCt++; } + + /* eat up whitespace */ +[ \t]+ { +} + /* eat up linefeeds and count lines in all conditions */ +<*>\n { + _iLinesCt++; + } + /* for all unrecognized characters */ +. { + // report an error + char strError[80]; + sprintf(strError, "Unrecognized character '%c' (ASCII 0x%02x)\n", + yytext[0], yytext[0] ); + yyerror(strError); +} + +%% + diff --git a/Sources/Ecc/StdH.h b/Sources/Ecc/StdH.h new file mode 100644 index 0000000..4ecb9f0 --- /dev/null +++ b/Sources/Ecc/StdH.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef PLATFORM_UNIX +#include +#include +#include +#define _fullpath(x, y, z) realpath(y, x) +#endif + diff --git a/Sources/Ecc/bison.simple b/Sources/Ecc/bison.simple new file mode 100644 index 0000000..0fb74ce --- /dev/null +++ b/Sources/Ecc/bison.simple @@ -0,0 +1,686 @@ +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 192 "bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +int +yyparse(YYPARSE_PARAM) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + +$ /* the action file gets copied in in place of this dollarsign */ +#line 487 "bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} diff --git a/Sources/Ecc/parser.h b/Sources/Ecc/parser.h new file mode 100644 index 0000000..d07179f --- /dev/null +++ b/Sources/Ecc/parser.h @@ -0,0 +1,77 @@ +#ifndef YYSTYPE +#define YYSTYPE int +#endif +#define c_char 258 +#define c_int 259 +#define c_float 260 +#define c_bool 261 +#define c_string 262 +#define identifier 263 +#define cppblock 264 +#define k_while 265 +#define k_for 266 +#define k_if 267 +#define k_else 268 +#define k_enum 269 +#define k_switch 270 +#define k_case 271 +#define k_class 272 +#define k_do 273 +#define k_void 274 +#define k_const 275 +#define k_inline 276 +#define k_static 277 +#define k_virtual 278 +#define k_return 279 +#define k_autowait 280 +#define k_autocall 281 +#define k_waitevent 282 +#define k_event 283 +#define k_name 284 +#define k_thumbnail 285 +#define k_features 286 +#define k_uses 287 +#define k_export 288 +#define k_texture 289 +#define k_sound 290 +#define k_model 291 +#define k_properties 292 +#define k_components 293 +#define k_functions 294 +#define k_procedures 295 +#define k_wait 296 +#define k_on 297 +#define k_otherwise 298 +#define k_call 299 +#define k_jump 300 +#define k_stop 301 +#define k_resume 302 +#define k_pass 303 +#define k_CTString 304 +#define k_CTStringTrans 305 +#define k_CTFileName 306 +#define k_CTFileNameNoDep 307 +#define k_BOOL 308 +#define k_COLOR 309 +#define k_FLOAT 310 +#define k_INDEX 311 +#define k_RANGE 312 +#define k_CEntityPointer 313 +#define k_CModelObject 314 +#define k_CModelInstance 315 +#define k_CAnimObject 316 +#define k_CSoundObject 317 +#define k_CPlacement3D 318 +#define k_FLOATaabbox3D 319 +#define k_FLOATmatrix3D 320 +#define k_FLOATquat3D 321 +#define k_ANGLE 322 +#define k_FLOAT3D 323 +#define k_ANGLE3D 324 +#define k_FLOATplane3D 325 +#define k_ANIMATION 326 +#define k_ILLUMINATIONTYPE 327 +#define k_FLAGS 328 + + +extern YYSTYPE yylval; diff --git a/Sources/Ecc/unistd.h b/Sources/Ecc/unistd.h new file mode 100644 index 0000000..80f9f8e --- /dev/null +++ b/Sources/Ecc/unistd.h @@ -0,0 +1,3 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include \ No newline at end of file diff --git a/Sources/Engine/Base/Anim.cpp b/Sources/Engine/Base/Anim.cpp new file mode 100644 index 0000000..98c51f5 --- /dev/null +++ b/Sources/Engine/Base/Anim.cpp @@ -0,0 +1,1104 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include + +#include + +#include +#include + +/* + * One animation of an animateable object + */ +class COneAnim { +public: + COneAnim(); + ~COneAnim(); + // copy constructor + COneAnim &operator=(const COneAnim &oaAnim); + NAME oa_Name; + TIME oa_SecsPerFrame; // speed of this animation + INDEX oa_NumberOfFrames; + INDEX *oa_FrameIndices; // array of frame indices +}; + +/* + * Node used for linking ptrs to COneAnim objects while loading + * script file before turning them into an array + * Class is used only for loading script files + */ +class COneAnimNode +{ +public: + ~COneAnimNode(); + COneAnimNode(COneAnim *AnimToInsert, CListHead *LH); + CListNode coan_Node; + COneAnim *coan_OneAnim; +}; +COneAnimNode::~COneAnimNode() +{ + ASSERT( coan_OneAnim != NULL); + delete coan_OneAnim; +} + +/* + * This temporary list head class is used for automatic deleting of temporary list on exit + */ +class CTmpListHead : public CListHead +{ +public: + ~CTmpListHead(); +}; + +CTmpListHead::~CTmpListHead() +{ + FORDELETELIST(COneAnimNode, coan_Node, *this, it) + delete &it.Current(); +}; + +// Remember ptr to animation and add this node at the end of given animation list +COneAnimNode::COneAnimNode(COneAnim *AnimToInsert, CListHead *LH) +{ + coan_OneAnim = AnimToInsert; + LH->AddTail( coan_Node); +}; + +// Constructor sets invalid data +COneAnim::COneAnim() +{ + oa_FrameIndices = NULL; +}; + +// Free allocated frame indices array for this animation +COneAnim::~COneAnim() +{ + ASSERT(oa_FrameIndices != NULL); + FreeMemory( oa_FrameIndices); + oa_FrameIndices = NULL; +}; + +/* + * Copy constructor. + */ +COneAnim &COneAnim::operator=(const COneAnim &oaAnim) +{ + ASSERT( oaAnim.oa_NumberOfFrames > 0); + strcpy(oa_Name, oaAnim.oa_Name); + oa_SecsPerFrame = oaAnim.oa_SecsPerFrame; + oa_NumberOfFrames = oaAnim.oa_NumberOfFrames; + if( oa_FrameIndices != NULL) + { + FreeMemory(oa_FrameIndices); + } + oa_FrameIndices = (INDEX *) AllocMemory( sizeof(INDEX) * oa_NumberOfFrames); + for( INDEX iFrame = 0; iFrame0); + strcpy( cfnn_FileName, NewFileName); + LH->AddTail( cfnn_Node); +}; + +CAnimData::CAnimData() +{ + ad_Anims = NULL; + ad_NumberOfAnims = 0; +}; + +CAnimData::~CAnimData() +{ + Clear(); +}; + +void CAnimData::Clear() +{ + if(ad_Anims != NULL) + delete[] ad_Anims; + ad_Anims = NULL; + ad_NumberOfAnims = 0; + + // clear serial object + CSerial::Clear(); +}; + +// get amount of memory used by this object +SLONG CAnimData::GetUsedMemory(void) +{ + SLONG slUsed = sizeof(*this)+sizeof(COneAnim)*ad_NumberOfAnims; + slUsed += strlen(GetName())+1; + + for(INDEX iAnim=0; iAnimRelease(this); +}; + +// creates given number of default animations (1 frame, given name and speed) +void CAnimData::CreateAnimations( INDEX ctAnimations, CTString strName/*="None"*/, + INDEX iDefaultFrame/*=0*/, TIME tmSpeed/*=0.02f*/) +{ + ASSERT(strlen(strName)oa_Name,"OnlyAnim"); + ad_Anims->oa_SecsPerFrame = (TIME) 0.02; + ad_Anims->oa_NumberOfFrames = 1; + ad_Anims->oa_FrameIndices = (INDEX *) AllocMemory( sizeof(INDEX)); + ad_Anims->oa_FrameIndices[0] = 0; +}; + +// Returns index of given frame name in global frame names list. If it is not found +// new CFileNameObject is added into frames list +INDEX FindFrameIndex( CListHead *pFrameFileList, const char *pFileName) +{ + UWORD i=0; + + FOREACHINLIST(CFileNameNode, cfnn_Node, *pFrameFileList, it) { + if( strcmpi(it->cfnn_FileName, pFileName) == 0) + return( i); + i++; + } + new CFileNameNode( pFileName, pFrameFileList); + return( i); +}; + +CTString GetFrameFileName( CListHead *pFrameFileList, INDEX iMemberInList) +{ + ASSERT( iMemberInListCount()); + UWORD iMember=0; + FOREACHINLIST(CFileNameNode, cfnn_Node, *pFrameFileList, it) + { + if( iMember == iMemberInList) return CTString( it->cfnn_FileName); + iMember++; + } + ASSERTALWAYS( "Frame with given index is not found in list of frames"); + return ""; +} + +// If found given word at the beginning of curently loaded line +#define EQUAL_SUB_STR( str) (strnicmp( ld_line, str, strlen(str)) == 0) + +// Loads part of given script file until word AnimEnd is reached +// Fills ACanimData (its instance) with apropriate data (animations and their frame indices) +// and fills given list head with string nodes containing file names representing frames +// needed to be loaded by a parent object +void CAnimData::LoadFromScript_t( CTStream *File, CListHead *pFrameFileList) // throw char * +{ + UWORD i; + char error_str[ 256]; + char key_word[ 256]; + char base_path[ PATH_MAX] = ""; + char file_name[ PATH_MAX]; + char anim_name[ 256]; + char full_path[ PATH_MAX]; + char ld_line[ 128]; + CTmpListHead TempAnimationList; + SLONG lc; + BOOL ret_val; + + //ASSERT( ad_Anims == NULL); + // clears possible animations + CAnimData::Clear(); + + ret_val = TRUE; + FOREVER + { + // Repeat reading of one line of script file until it is not empty or comment + do + { + File->GetLine_t(ld_line, 128); + } + while( (strlen( ld_line)== 0) || (ld_line[0]==';')); + + // If key-word is "/*", search end of comment block + if( EQUAL_SUB_STR( "/*")) + { + do + { + File->GetLine_t(ld_line, 128); + } + while( !EQUAL_SUB_STR( "*/")); + } + // If key-word is "DIRECTORY", remember it and add "\" character at the end of new path + // if it is not yet there + else if( EQUAL_SUB_STR( "DIRECTORY")) + { + _strupr( ld_line); + sscanf( ld_line, "DIRECTORY %s", base_path); + if( base_path[ strlen( base_path) - 1] != '\\') + strcat( base_path,"\\"); + } + // Key-word animation must follow its name (in same line), + // its speed and its number of frames (new lines) + else if( EQUAL_SUB_STR( "ANIMATION")) + { + if( strlen( ld_line) <= (strlen( "ANIMATION") + 1)) + { + throw("You have to give descriptive name to every animation."); + } + // Create new animation + COneAnim *poaOneAnim = new COneAnim; + _strupr( ld_line); + sscanf( ld_line, "ANIMATION %s", poaOneAnim->oa_Name); + File->GetLine_t(ld_line, 128); + if( !EQUAL_SUB_STR( "SPEED")) + { + throw("Expecting key word \"SPEED\" after key word \"ANIMATION\"."); + } + _strupr( ld_line); + sscanf( ld_line, "SPEED %f", &poaOneAnim->oa_SecsPerFrame); + + CDynamicArray astrFrames; + SLONG slLastPos; + FOREVER + { + slLastPos = File->GetPos_t(); + File->GetLine_t(ld_line, 128); + _strupr( ld_line); + // jump over old key word "FRAMES" and comments + if( EQUAL_SUB_STR( "FRAMES") || (ld_line[0]==';') ) continue; + // key words that start or end animations or empty line breaks frame reading + if( (EQUAL_SUB_STR( "ANIMATION")) || + (strlen( ld_line)== 0) || + (EQUAL_SUB_STR( "ANIM_END")) ) break; + + sscanf( ld_line, "%s", key_word); + if( key_word == CTString( "ANIM")) + { + // read file name from line and add it at the end of last path string loaded + sscanf( ld_line, "%s %s", error_str, anim_name); + // search trough all allready readed animations for macro one + FOREACHINLIST(COneAnimNode, coan_Node, TempAnimationList, itOAN) + { + if( itOAN->coan_OneAnim->oa_Name == CTString( anim_name)) + { + CTString *pstrMacroFrames = astrFrames.New( itOAN->coan_OneAnim->oa_NumberOfFrames); + for( INDEX iMacroFrame = 0; iMacroFramecoan_OneAnim->oa_NumberOfFrames; iMacroFrame++) + { + *pstrMacroFrames = GetFrameFileName( pFrameFileList, itOAN->coan_OneAnim->oa_FrameIndices[iMacroFrame]); + pstrMacroFrames++; + } + } + } + } + else + { + // read file name from line and add it at the end of last path string loaded + sscanf( ld_line, "%s", file_name); + sprintf( full_path, "%s%s", base_path, file_name); + CTString *pstrNewFile = astrFrames.New(1); + *pstrNewFile = CTString( full_path); + } + } + if( astrFrames.Count() == 0) + { + ThrowF_t( "Can't find any frames for animation %s.\nThere must be at least 1 frame " + "per animation.\nList of frames must start at line after line containing key" + "word SPEED.", poaOneAnim->oa_Name); + } + // set position before last line readed + File->SetPos_t( slLastPos); + // Allocate array of indices + poaOneAnim->oa_NumberOfFrames = astrFrames.Count(); + poaOneAnim->oa_FrameIndices = (INDEX *) AllocMemory( poaOneAnim->oa_NumberOfFrames * sizeof( INDEX)); + + INDEX iFrame = 0; + FOREACHINDYNAMICARRAY( astrFrames, CTString, itStrFrame) + { + // find existing index (of insert new one) for this file name into FileNameList + poaOneAnim->oa_FrameIndices[ iFrame] = FindFrameIndex( pFrameFileList, *itStrFrame); + iFrame++; + } + // clear used array + astrFrames.Clear(); + // Add this new animation instance to temporary animation list + new COneAnimNode( poaOneAnim, &TempAnimationList); + ad_NumberOfAnims ++; + } + else if( EQUAL_SUB_STR( "ANIM_END")) + break; + else + { + sprintf(error_str, "Incorrect word readed from script file.\n"); + strcat(error_str, "Probable cause: missing \"ANIM_END\" key-word at end of animation list."); + throw(error_str); + } + } + + lc = TempAnimationList.Count(); + ASSERT(lc!=0); + + // create array of OneAnim object containing members as many as temporary list + ad_Anims = new COneAnim[ lc]; + + // copy list to array + lc=0; + FOREACHINLIST(COneAnimNode, coan_Node, TempAnimationList, it2) + { + strcpy( ad_Anims[ lc].oa_Name, it2->coan_OneAnim->oa_Name); + ad_Anims[ lc].oa_SecsPerFrame = it2->coan_OneAnim->oa_SecsPerFrame; + ad_Anims[ lc].oa_NumberOfFrames = it2->coan_OneAnim->oa_NumberOfFrames; + ad_Anims[ lc].oa_FrameIndices = (INDEX *) AllocMemory( ad_Anims[ lc].oa_NumberOfFrames * + sizeof(INDEX)); + for( i=0; icoan_OneAnim->oa_NumberOfFrames; i++) + ad_Anims[ lc].oa_FrameIndices[ i] = it2->coan_OneAnim->oa_FrameIndices[ i]; + lc++; + } + FORDELETELIST( COneAnimNode, coan_Node, TempAnimationList, litDel) + delete &litDel.Current(); + +}; + +void CAnimData::Write_t( CTStream *ostrFile) // throw char * +{ + SLONG i; + // First we save main ID + ostrFile->WriteID_t( CChunkID( "ADAT")); + // Then we save number of how many animations do we have and then save them all + ostrFile->Write_t( &ad_NumberOfAnims, sizeof( INDEX)); + for( i=0; iWrite_t( &ad_Anims[i].oa_Name, sizeof( NAME)); + ostrFile->Write_t( &ad_Anims[i].oa_SecsPerFrame, sizeof( TIME)); + ostrFile->Write_t( &ad_Anims[i].oa_NumberOfFrames, sizeof( INDEX)); + ostrFile->Write_t( ad_Anims[i].oa_FrameIndices, + ad_Anims[i].oa_NumberOfFrames * sizeof( INDEX)); + } +}; + +// print #define lines for all animations into given file +void CAnimData::ExportAnimationNames_t( CTStream *ostrFile, CTString strAnimationPrefix) // throw char * +{ + char chrLine[ 256]; + // for each animation + for( INDEX iAnimation=0; iAnimationPutLine_t( chrLine); + } +} + +// Get info about some animation +void CAnimData::GetAnimInfo(INDEX iAnimNo, CAnimInfo &aiInfo) const +{ + if(iAnimNo>=ad_NumberOfAnims) { + iAnimNo = 0; + } + strcpy( aiInfo.ai_AnimName, ad_Anims[ iAnimNo].oa_Name); + aiInfo.ai_SecsPerFrame = ad_Anims[ iAnimNo].oa_SecsPerFrame; + aiInfo.ai_NumberOfFrames = ad_Anims[ iAnimNo].oa_NumberOfFrames; +} + +// Add animation +void CAnimData::AddAnimation(void) +{ + COneAnim *pNewAnims = new COneAnim[ ad_NumberOfAnims+1]; + for( INDEX iOldAnim=0; iOldAnimExpectID_t( CChunkID( "ADAT")); + // Then we load and create number of animations + istrFile->Read_t( &ad_NumberOfAnims, sizeof( INDEX)); + ad_Anims = new COneAnim[ ad_NumberOfAnims]; + for( i=0; iRead_t( &ad_Anims[i].oa_Name, sizeof( NAME)); + istrFile->Read_t( &ad_Anims[i].oa_SecsPerFrame, sizeof( TIME)); + istrFile->Read_t( &ad_Anims[i].oa_NumberOfFrames, sizeof( INDEX)); + ad_Anims[i].oa_FrameIndices = (INDEX *) + AllocMemory( ad_Anims[i].oa_NumberOfFrames * sizeof( INDEX)); + istrFile->Read_t( ad_Anims[i].oa_FrameIndices, + ad_Anims[i].oa_NumberOfFrames * sizeof( INDEX)); + } +}; + +/* + * Default constructor. + */ +CAnimObject::CAnimObject(void) +{ + // set invalid data for validation check + ao_AnimData = NULL; + ao_tmAnimStart = 0.0f; + ao_iCurrentAnim = -1; + ao_iLastAnim = -1; + ao_ulFlags = AOF_PAUSED; +}; + +/* Destructor. */ +CAnimObject::~CAnimObject(void) +{ + ao_AnimData->RemReference(); +}; + +// copy from another object of same class +ENGINE_API void CAnimObject::Copy(CAnimObject &aoOther) +{ + SetData(aoOther.GetData()); + ao_tmAnimStart = aoOther.ao_tmAnimStart; + ao_iCurrentAnim = aoOther.ao_iCurrentAnim; + ao_iLastAnim = aoOther.ao_iLastAnim; + ao_ulFlags = aoOther.ao_ulFlags; +} +// synchronize with another animation object (set same anim and frames) +ENGINE_API void CAnimObject::Synchronize(CAnimObject &aoOther) +{ + // copy animations, time and flags + INDEX ctAnims = GetAnimsCt(); + ao_tmAnimStart = aoOther.ao_tmAnimStart; + ao_iCurrentAnim = ClampUp(aoOther.ao_iCurrentAnim, ctAnims-1L); + ao_iLastAnim = ClampUp(aoOther.ao_iLastAnim, ctAnims-1L); + ao_ulFlags = aoOther.ao_ulFlags; +} + +/* + * Get animation's lenght. + */ +FLOAT CAnimObject::GetAnimLength(INDEX iAnim) const +{ + if(ao_AnimData == NULL) return 1.0f; + ASSERT( ao_AnimData != NULL); + if(iAnim>=ao_AnimData->ad_NumberOfAnims) { + iAnim = 0; + } + ASSERT( (iAnim >= 0) && (iAnim < ao_AnimData->ad_NumberOfAnims) ); + COneAnim *pCOA = &ao_AnimData->ad_Anims[iAnim]; + return pCOA->oa_NumberOfFrames*pCOA->oa_SecsPerFrame; +}; + +FLOAT CAnimObject::GetCurrentAnimLength(void) const +{ + return GetAnimLength(ao_iCurrentAnim); +} + + +/* + * Calculate frame that coresponds to given time. + */ +INDEX CAnimObject::FrameInTime(TIME time) const +{ + ASSERT( ao_AnimData != NULL); + ASSERT( (ao_iCurrentAnim >= 0) && (ao_iCurrentAnim < ao_AnimData->ad_NumberOfAnims) ); + INDEX iFrameInAnim; + + COneAnim *pCOA = &ao_AnimData->ad_Anims[ao_iCurrentAnim]; + if( ao_ulFlags&AOF_PAUSED) { + // return index of paused frame inside global frame array + iFrameInAnim = ClipFrame(pCOA->oa_NumberOfFrames + ClipFrame( FloatToInt(ao_tmAnimStart/pCOA->oa_SecsPerFrame))); + } else { + // return index of frame inside global frame array of frames in given moment + iFrameInAnim = ClipFrame( FloatToInt((time - ao_tmAnimStart)/pCOA->oa_SecsPerFrame)); + } + return pCOA->oa_FrameIndices[iFrameInAnim]; +} + + +/* + * Pauses animation + */ +void CAnimObject::PauseAnim(void) +{ + if( ao_ulFlags&AOF_PAUSED) return; // dont pause twice + ao_ulFlags |= AOF_PAUSED; + ao_tmAnimStart = _pTimer->CurrentTick() - ao_tmAnimStart; // set difference from current time as start time, + MarkChanged(); // so get frame will get correct current frame +} + +/* + * Continues paused animation + */ +void CAnimObject::ContinueAnim(void){ + if( !(ao_ulFlags&AOF_PAUSED)) return; + // calculate freezed frame index inside current animation (not in global list of frames!) + COneAnim *pCOA = &ao_AnimData->ad_Anims[ao_iCurrentAnim]; + if (pCOA->oa_NumberOfFrames<=0) { + return; + } + INDEX iStoppedFrame = (pCOA->oa_NumberOfFrames + (SLONG)(ao_tmAnimStart/pCOA->oa_SecsPerFrame) + % pCOA->oa_NumberOfFrames) % pCOA->oa_NumberOfFrames; + // using current frame index calculate time so animation continues from same frame + ao_tmAnimStart = _pTimer->CurrentTick() - pCOA->oa_SecsPerFrame * iStoppedFrame; + ao_ulFlags &= ~AOF_PAUSED; + MarkChanged(); +} + +/* + * Offsets the animation phase + */ +void CAnimObject::OffsetPhase(TIME tm){ + ao_tmAnimStart += tm; +} + + +/* + * Loop anims forward + */ +void CAnimObject::NextAnim(){ + ASSERT( ao_iCurrentAnim != -1); + ASSERT( ao_AnimData != NULL); + ao_iCurrentAnim = (ao_iCurrentAnim + 1) % ao_AnimData->ad_NumberOfAnims; + ao_iLastAnim = ao_iCurrentAnim; + ao_tmAnimStart = _pTimer->CurrentTick(); + MarkChanged(); +}; + +/* + * Loop anims backward + */ +void CAnimObject::PrevAnim(){ + ASSERT( ao_iCurrentAnim != -1); + ASSERT( ao_AnimData != NULL); + ao_iCurrentAnim = (ao_AnimData->ad_NumberOfAnims + ao_iCurrentAnim - 1) % + ao_AnimData->ad_NumberOfAnims; + ao_iLastAnim = ao_iCurrentAnim; + ao_tmAnimStart = _pTimer->CurrentTick(); + MarkChanged(); +}; + +/* + * Selects frame for given time offset from animation start (0) + */ +void CAnimObject::SelectFrameInTime(TIME tmOffset) +{ + ao_tmAnimStart = tmOffset; // set fixed start time + MarkChanged(); +} + +void CAnimObject::FirstFrame(void) +{ + SelectFrameInTime(0.0f); +} + +void CAnimObject::LastFrame(void) +{ + class COneAnim *pCOA = &ao_AnimData->ad_Anims[ao_iCurrentAnim]; + SelectFrameInTime(GetAnimLength(ao_iCurrentAnim)-pCOA->oa_SecsPerFrame); +} + +/* + * Loop frames forward + */ +void CAnimObject::NextFrame(){ + ASSERT( ao_iCurrentAnim != -1); + ASSERT( ao_AnimData != NULL); + ASSERT( ao_ulFlags&AOF_PAUSED); + ao_tmAnimStart += ao_AnimData->ad_Anims[ ao_iCurrentAnim].oa_SecsPerFrame; + MarkChanged(); +}; + +/* + * Loop frames backward + */ +void CAnimObject::PrevFrame(){ + ASSERT( ao_iCurrentAnim != -1); + ASSERT( ao_AnimData != NULL); + ASSERT( ao_ulFlags&AOF_PAUSED); + ao_tmAnimStart -= ao_AnimData->ad_Anims[ ao_iCurrentAnim].oa_SecsPerFrame; + MarkChanged(); +}; + +/* + * Retrieves paused flag + */ +BOOL CAnimObject::IsPaused(){ + return ao_ulFlags&AOF_PAUSED; +}; + +/* + * Test if some updateable object is up to date with this anim object. + */ +BOOL CAnimObject::IsUpToDate(const CUpdateable &ud) const +{ + // if the object itself has changed, or its data has changed + if (!CChangeable::IsUpToDate(ud) || !ao_AnimData->IsUpToDate(ud)) { + // something has changed + return FALSE; + } + // otherwise, nothing has changed + return TRUE; +} + +/* + * Attach data to this object. + */ +void CAnimObject::SetData(CAnimData *pAD) { + // mark new data as referenced once more + pAD->AddReference(); + // mark old data as referenced once less + ao_AnimData->RemReference(); + // remember new data + ao_AnimData = pAD; + if( pAD != NULL) StartAnim( 0); + // mark that something has changed + MarkChanged(); +} + +// obtain anim and set it for this object +void CAnimObject::SetData_t(const CTFileName &fnmAnim) // throw char * +{ + // if the filename is empty + if (fnmAnim=="") { + // release current anim + SetData(NULL); + + // if the filename is not empty + } else { + // obtain it (adds one reference) + CAnimData *pad = _pAnimStock->Obtain_t(fnmAnim); + // set it as data (adds one more reference, and remove old reference) + SetData(pad); + // release it (removes one reference) + _pAnimStock->Release(pad); + // total reference count +1+1-1 = +1 for new data -1 for old data + } +} + + +/* + * Sets new animation (but doesn't starts it). + */ +void CAnimObject::SetAnim(INDEX iNew) { + if(ao_AnimData == NULL) return; + // clamp animation + if( iNew >= GetAnimsCt() ) + { + iNew = 0; + } + // if new animation + if (ao_iCurrentAnim!=iNew) { + // remember starting time + ao_tmAnimStart = _pTimer->CurrentTick(); + } + // set new animation number + ao_iCurrentAnim=iNew; + ao_iLastAnim=iNew; + // mark that something has changed + MarkChanged(); +}; + +/* + * Start new animation. + */ +void CAnimObject::StartAnim(INDEX iNew) { + if(ao_AnimData == NULL) return; + // set new animation + SetAnim( iNew); + // set pause off, looping on + ao_ulFlags = AOF_LOOPING; +}; + +/* Start playing an animation. */ +void CAnimObject::PlayAnim(INDEX iNew, ULONG ulFlags) +{ + if(ao_AnimData == NULL) return; + // clamp animation + if( iNew >= GetAnimsCt() ) { + iNew = 0; + } + + // if anim needs to be reset at start + if (!(ulFlags&AOF_NORESTART) || ao_iCurrentAnim!=iNew) { + + // if smooth transition + if (ulFlags&AOF_SMOOTHCHANGE) { + // calculate time to end of the current anim + class COneAnim *pCOA = &ao_AnimData->ad_Anims[ao_iCurrentAnim]; + TIME tmNow = _pTimer->CurrentTick(); + TIME tmLength = GetCurrentAnimLength(); + FLOAT fFrame = ((_pTimer->CurrentTick() - ao_tmAnimStart)/pCOA->oa_SecsPerFrame); + INDEX iFrame = INDEX(fFrame); + FLOAT fFract = fFrame-iFrame; + iFrame = ClipFrame(iFrame); + TIME tmPassed = (iFrame+fFract)*pCOA->oa_SecsPerFrame; + TIME tmLeft = tmLength-tmPassed; + // set time ahead to end of the current animation + ao_tmAnimStart = _pTimer->CurrentTick()+tmLeft; + // remember last animation + ao_iLastAnim = ao_iCurrentAnim; + // set new animation number + ao_iCurrentAnim = iNew; + + // if normal transition + } else { + ao_iLastAnim = iNew; + ao_iCurrentAnim = iNew; + // remember starting time + ao_tmAnimStart = _pTimer->CurrentTick(); + } + // if anim doesn't need be reset at start + } else { + // do nothing + NOTHING; + } + // set pause off, looping flag from flags + ao_ulFlags = ulFlags&(AOF_LOOPING|AOF_PAUSED); + + // mark that something has changed + MarkChanged(); +}; + +/* Seamlessly continue playing another animation from same point. */ +void CAnimObject::SwitchToAnim(INDEX iNew) +{ + if(ao_AnimData == NULL) return; + // clamp animation + if( iNew >= GetAnimsCt() ) + { + iNew = 0; + } + // set new animation number + ao_iCurrentAnim=iNew; + ao_iLastAnim = ao_iCurrentAnim; +} + +/* + * Reset anim (restart) + */ +void CAnimObject::ResetAnim() { + if(ao_AnimData == NULL) return; + // remember starting time + ao_tmAnimStart = _pTimer->CurrentTick(); + // mark that something has changed + MarkChanged(); +}; + +// Get info about some animation +void CAnimObject::GetAnimInfo(INDEX iAnimNo, CAnimInfo &aiInfo) const +{ + if (iAnimNo >= ao_AnimData->ad_NumberOfAnims) { + iAnimNo = 0; + } + ASSERT( iAnimNo < ao_AnimData->ad_NumberOfAnims); + strcpy( aiInfo.ai_AnimName, ao_AnimData->ad_Anims[ iAnimNo].oa_Name); + aiInfo.ai_SecsPerFrame = ao_AnimData->ad_Anims[ iAnimNo].oa_SecsPerFrame; + aiInfo.ai_NumberOfFrames = ao_AnimData->ad_Anims[ iAnimNo].oa_NumberOfFrames; +} + +// clip frame index to be inside valid range (wrap around for looping anims) +INDEX CAnimObject::ClipFrame(INDEX iFrame) const +{ + if (ao_AnimData->ad_NumberOfAnims==0) { + return 0; + } + class COneAnim *pCOA = &ao_AnimData->ad_Anims[ao_iCurrentAnim]; + // if looping + if (ao_ulFlags&AOF_LOOPING) { + // wrap-around + if (pCOA->oa_NumberOfFrames<=0) { + return 0; + } + return ULONG(iFrame)%pCOA->oa_NumberOfFrames; + // if not looping + } else { + // clamp + if (iFrame<0) { + return 0; + } else if (iFrame>=pCOA->oa_NumberOfFrames) { + return pCOA->oa_NumberOfFrames-1; + } else { + return iFrame; + } + } +} + +// Get info about time passed until now in current animation +TIME CAnimObject::GetPassedTime(void) const +{ + if(ao_AnimData == NULL) return 0.0f; + INDEX iStoppedFrame; + class COneAnim *pCOA = &ao_AnimData->ad_Anims[ao_iCurrentAnim]; + if( !(ao_ulFlags&AOF_PAUSED)) + iStoppedFrame = ClipFrame((INDEX)((_pTimer->CurrentTick() - ao_tmAnimStart)/pCOA->oa_SecsPerFrame)); + else + iStoppedFrame = ClipFrame((INDEX)(ao_tmAnimStart/pCOA->oa_SecsPerFrame)); + return( iStoppedFrame * pCOA->oa_SecsPerFrame); +} + +/* + * If animation is finished + */ +BOOL CAnimObject::IsAnimFinished(void) const +{ + if(ao_AnimData == NULL) return FALSE; + if(ao_ulFlags&AOF_LOOPING) return FALSE; + + INDEX iStoppedFrame; + class COneAnim *pCOA = &ao_AnimData->ad_Anims[ao_iCurrentAnim]; + if( !(ao_ulFlags&AOF_PAUSED)) + iStoppedFrame = ClipFrame((INDEX)((_pTimer->CurrentTick() - ao_tmAnimStart)/pCOA->oa_SecsPerFrame)); + else + iStoppedFrame = ClipFrame((INDEX)(ao_tmAnimStart/pCOA->oa_SecsPerFrame)); + return( iStoppedFrame == pCOA->oa_NumberOfFrames-1); +} + +// get number of animations in curent anim data +INDEX CAnimObject::GetAnimsCt(void) const +{ + if(ao_AnimData == NULL) return 1; + ASSERT( ao_AnimData != NULL); + return( ao_AnimData->ad_NumberOfAnims); +}; + +// get index of current animation +INDEX CAnimObject::GetAnim(void) const +{ + return( ao_iCurrentAnim); +}; + + +/* + * Gets the number of current frame. + */ +INDEX CAnimObject::GetFrame(void) const +{ + return FrameInTime(_pTimer->CurrentTick()); // return frame index that coresponds to current moment +} + +/* Gets number of frames in current anim. */ +INDEX CAnimObject::GetFramesInCurrentAnim(void) const { + ASSERT( ao_AnimData != NULL); + return ao_AnimData->ad_Anims[ao_iCurrentAnim].oa_NumberOfFrames; +}; + +/* + * Get information for linear interpolation beetween frames. + */ +void CAnimObject::GetFrame( INDEX &iFrame0, INDEX &iFrame1, FLOAT &fRatio) const +{ + if(ao_AnimData == NULL || + ao_AnimData->ad_NumberOfAnims<=0 || + ao_AnimData->ad_Anims[ao_iCurrentAnim].oa_NumberOfFrames<=0) + { + iFrame0 = 0; + iFrame1 = 0; + fRatio =0.0f; + return; + } + ASSERT( ao_AnimData != NULL); + ASSERT( (ao_iCurrentAnim >= 0) && (ao_iCurrentAnim < ao_AnimData->ad_NumberOfAnims) ); + TIME tmNow = _pTimer->CurrentTick() + _pTimer->GetLerpFactor()*_pTimer->TickQuantum; + + if( ao_ulFlags&AOF_PAUSED) + { + // return index of paused frame inside global frame array + class COneAnim *pCOA = &ao_AnimData->ad_Anims[ao_iCurrentAnim]; + INDEX iStoppedFrame = ClipFrame((SLONG)(ao_tmAnimStart/pCOA->oa_SecsPerFrame)); + iFrame0 = iFrame1 = pCOA->oa_FrameIndices[ iStoppedFrame]; + fRatio = 0.0f; + } + else + { + // return index of frame inside global frame array of frames in given moment + TIME tmCurrentRelative = tmNow - ao_tmAnimStart; + if (tmCurrentRelative>=0) { + class COneAnim *pOA0 = &ao_AnimData->ad_Anims[ao_iCurrentAnim]; + float fFrameNow = (tmCurrentRelative)/pOA0->oa_SecsPerFrame; + iFrame0 = pOA0->oa_FrameIndices[ ClipFrame(ULONG(fFrameNow))]; + iFrame1 = pOA0->oa_FrameIndices[ ClipFrame(ULONG(fFrameNow+1))]; + fRatio = fFrameNow - (float)floor(fFrameNow); + } else { + class COneAnim *pOA0 = &ao_AnimData->ad_Anims[ao_iLastAnim]; + class COneAnim *pOA1 = &ao_AnimData->ad_Anims[ao_iCurrentAnim]; + INDEX iAnim = ao_iCurrentAnim; + ((CAnimObject*)this)->ao_iCurrentAnim = ao_iLastAnim; + float fFrameNow = tmCurrentRelative/pOA0->oa_SecsPerFrame+pOA0->oa_NumberOfFrames; + iFrame0 = pOA0->oa_FrameIndices[ Clamp(SLONG(fFrameNow), 0L, pOA0->oa_NumberOfFrames-1L)]; + INDEX iFrameNext = SLONG(fFrameNow+1); + if (iFrameNext>=pOA0->oa_NumberOfFrames) { + iFrame1 = pOA1->oa_FrameIndices[0]; + } else { + iFrame1 = pOA0->oa_FrameIndices[ Clamp(iFrameNext, 0L, pOA0->oa_NumberOfFrames-1L)]; + } + ((CAnimObject*)this)->ao_iCurrentAnim = iAnim; + fRatio = fFrameNow - (float)floor(fFrameNow); + } + } +} + +void CAnimObject::Write_t( CTStream *pstr) // throw char * +{ + (*pstr).WriteID_t("ANOB"); + (*pstr).WriteRawChunk_t( &ao_tmAnimStart, sizeof( TIME)); + (*pstr).WriteRawChunk_t( &ao_iCurrentAnim, sizeof( INDEX)); + (*pstr).WriteRawChunk_t( &ao_iLastAnim, sizeof( INDEX)); + (*pstr).WriteRawChunk_t( &ao_ulFlags, sizeof( INDEX)); +}; + +void CAnimObject::Read_t( CTStream *pstr) // throw char * +{ + if ((*pstr).PeekID_t()==CChunkID("ANOB")) { + (*pstr).ExpectID_t("ANOB"); + (*pstr).ReadRawChunk_t( &ao_tmAnimStart, sizeof( TIME)); + (*pstr).ReadRawChunk_t( &ao_iCurrentAnim, sizeof( INDEX)); + (*pstr).ReadRawChunk_t( &ao_iLastAnim, sizeof( INDEX)); + (*pstr).ReadRawChunk_t( &ao_ulFlags, sizeof( INDEX)); + } else { + (*pstr).ReadRawChunk_t( &ao_tmAnimStart, sizeof( TIME)); + (*pstr).ReadRawChunk_t( &ao_iCurrentAnim, sizeof( INDEX)); + ao_iLastAnim = ao_iCurrentAnim; + ao_ulFlags = 0; + } + + // clamp animation + if (ao_AnimData==NULL || ao_iCurrentAnim >= GetAnimsCt() ) + { + ao_iCurrentAnim = 0; + } + // clamp animation + if (ao_AnimData==NULL || ao_iLastAnim >= GetAnimsCt() ) + { + ao_iLastAnim = 0; + } +}; diff --git a/Sources/Engine/Base/Anim.h b/Sources/Engine/Base/Anim.h new file mode 100644 index 0000000..849048d --- /dev/null +++ b/Sources/Engine/Base/Anim.h @@ -0,0 +1,211 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ANIM_H +#define SE_INCL_ANIM_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +#include + +#define NAME_SIZE 32 +typedef char NAME[NAME_SIZE]; +#define PATH_MAX 260 +typedef char FILE_NAME[PATH_MAX]; + +/* + * An object used for obtaining animation's information + */ +class CAnimInfo { +public: + NAME ai_AnimName; + TIME ai_SecsPerFrame; // speed of this animation + INDEX ai_NumberOfFrames; +}; + +/* + * Node used for linking file names representing frames. + * Nodes of this kind are returned result of LoadFromScript function. + */ +class ENGINE_API CFileNameNode { +public: + FILE_NAME cfnn_FileName; + CListNode cfnn_Node; + CFileNameNode(const char *NewFileName, CListHead *LH); +}; + +/* + * Animation data for a class of animateable objects + */ +class CAnimData : public CSerial { +public: + INDEX ad_NumberOfAnims; + class COneAnim *ad_Anims; // array of animations + +public: + + // fill member variables with invalid data + ENGINE_API CAnimData(); + // Free allocated data (ad_Anims array), check invalid data + ENGINE_API ~CAnimData(); + // clears animation data object + ENGINE_API void Clear(); + // check if this kind of objects is auto-freed + virtual BOOL IsAutoFreed(void); + // reference counting functions + virtual void RemReference_internal(void); + + // get amount of memory used by this object + SLONG GetUsedMemory(void); + + // reference counting functions + void AddReference(void); + void RemReference(void); + + // creates given number of default animations (1 frame, given name and apeed) + ENGINE_API void CreateAnimations( INDEX ctAnimations, CTString strName="None", + INDEX iDefaultFrame=0,TIME tmSpeed=0.02f); + // replaces frames array with given one + ENGINE_API void SetFrames( INDEX iAnimation, INDEX ctFrames, INDEX *pNewFrames); + // replaces requested animation's name with given one + ENGINE_API void SetName( INDEX iAnimation, CTString strNewName); + // replaces requested animation's speed with given one + ENGINE_API void SetSpeed( INDEX iAnimation, TIME tmSpeed); + // obtains frame index for given place in array representing given animation + ENGINE_API INDEX GetFrame( INDEX iAnimation, INDEX iFramePlace); + // sets frame index for given place in array representing given animation + ENGINE_API void SetFrame( INDEX iAnimation, INDEX iFramePlace, INDEX iNewFrame); + // fill animation data object vith valid data containing one animation, one frame + ENGINE_API void DefaultAnimation(); + /* Get animation's info. */ + ENGINE_API void GetAnimInfo(INDEX iAnimNo, CAnimInfo &aiInfo) const; + /* Add animation */ + ENGINE_API void AddAnimation(void); + /* Delete animation */ + ENGINE_API void DeleteAnimation(INDEX iAnim); + /* Get number of animations. */ + ENGINE_API INDEX GetAnimsCt(void) const; + // load list of frames from script file + ENGINE_API void LoadFromScript_t( CTStream *File, CListHead *FrameFileList); // throw char * + // print #define lines for all animations into given file + void ExportAnimationNames_t( CTStream *ostrFile, CTString strAnimationPrefix); // throw char * + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * +}; + + +/* + * An instance of animateable object + */ +#define AOF_PAUSED (1L<<0) // current animation is paused +#define AOF_LOOPING (1L<<1) // anim object is playing a looping animation +#define AOF_NORESTART (1L<<2) // don't restart anim (used for PlayAnim()) +#define AOF_SMOOTHCHANGE (1L<<3) // smoothly change between anims + +class CAnimObject : public CChangeable { +public: + TIME ao_tmAnimStart; // time when current anim was started + INDEX ao_iCurrentAnim; // index of active animation + ULONG ao_ulFlags; // flags + INDEX ao_iLastAnim; // index of last animation (for smooth transition) + + /* Calculate frame that coresponds to given time. */ + INDEX FrameInTime(TIME time) const; + +public: + CAnimData *ao_AnimData; + +public: + + // some of usual smart pointer functions are implemented, because AnimObjects + // behave as smart pointers to AnimData objects + /* Default constructor. */ + ENGINE_API CAnimObject(void); + /* Destructor. */ + ENGINE_API ~CAnimObject(void); + // copy from another object of same class + ENGINE_API void Copy(CAnimObject &aoOther); + // synchronize with another animation object (set same anim and frames) + ENGINE_API void Synchronize(CAnimObject &aoOther); + + // copying of AnimObjects is not allowed + inline CAnimObject(const CAnimObject &aoOther) { + ASSERT(FALSE); }; + inline const CAnimObject &operator=(const CAnimObject &aoOther) { + ASSERT(FALSE); return *this;}; + + // clip frame index to be inside valid range (wrap around for looping anims) + INDEX ClipFrame(INDEX iFrame) const; + /* Loop anims forward */ + ENGINE_API void NextAnim(void); + /* Loop anims backward */ + ENGINE_API void PrevAnim(void); + /* Loop frames forward */ + ENGINE_API void NextFrame(void); + /* Loop frames backward */ + ENGINE_API void PrevFrame(void); + /* Select frame in given time offset */ + ENGINE_API void SelectFrameInTime(TIME tmOffset); + /* Select first frame */ + ENGINE_API void FirstFrame(void); + /* Select last frame */ + ENGINE_API void LastFrame(void); + /* Test if some updateable object is up to date with this anim object. */ + ENGINE_API BOOL IsUpToDate(const CUpdateable &ud) const; + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * + + /* Get animation's info. */ + ENGINE_API void GetAnimInfo(INDEX iAnimNo, CAnimInfo &aiInfo) const; + + /* Attach data to this object. */ + ENGINE_API void SetData(CAnimData *pAD); + // obtain animation and set it for this object + ENGINE_API void SetData_t(const CTFileName &fnmAnim); // throw char * + + /* Get current anim data ptr. */ + __forceinline CAnimData *GetData() { return ao_AnimData; }; + + /* Get animation's length. */ + ENGINE_API FLOAT GetCurrentAnimLength(void) const; + ENGINE_API FLOAT GetAnimLength(INDEX iAnim) const; + /* Get number of animations in current anim data */ + ENGINE_API INDEX GetAnimsCt() const; + /* If animation has finished */ + ENGINE_API BOOL IsAnimFinished(void) const; + /* Get passed time from start of animation */ + ENGINE_API TIME GetPassedTime(void) const; + + /* Start new animation -- obsolete. */ + ENGINE_API void StartAnim(INDEX iNew); + /* Start playing an animation. */ + ENGINE_API void PlayAnim(INDEX iNew, ULONG ulFlags); + /* Seamlessly continue playing another animation from same point. */ + ENGINE_API void SwitchToAnim(INDEX iNew); + /* Set new animation but doesn't starts it. */ + ENGINE_API void SetAnim(INDEX iNew); + /* Reset anim (restart) */ + ENGINE_API void ResetAnim(); + /* Pauses current animation. */ + ENGINE_API void PauseAnim(); + /* Continues paused animation. */ + ENGINE_API void ContinueAnim(); + /* Offsets the animation phase */ + ENGINE_API void OffsetPhase(TIME tm); + /* Retrieves paused flag */ + ENGINE_API BOOL IsPaused(void); + /* Gets the number of current animation */ + ENGINE_API INDEX GetAnim(void) const; + /* Gets the number of current frame. */ + ENGINE_API INDEX GetFrame(void) const; + /* Gets number of frames in current anim. */ + ENGINE_API INDEX GetFramesInCurrentAnim(void) const; + /* Get information for linear interpolation beetween frames. */ + ENGINE_API void GetFrame( INDEX &iFrame0, INDEX &iFrame1, FLOAT &fRatio) const; +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Assert.h b/Sources/Engine/Base/Assert.h new file mode 100644 index 0000000..189fde9 --- /dev/null +++ b/Sources/Engine/Base/Assert.h @@ -0,0 +1,108 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ASSERT_H +#define SE_INCL_ASSERT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#ifdef _MSC_VER /* rcg10042001 */ + +#ifdef __cplusplus + extern "C" { +#endif + + /* original VC definition of _assert */ + _CRTIMP void __cdecl _assert(void *, void *, unsigned); + +#ifdef __cplusplus + } +#endif + +#endif + + +#ifdef PLATFORM_UNIX /* rcg10042001 */ +#include +#include +#define _assert(x, y, z) assert(0) +#endif + + +#ifdef NDEBUG + #ifndef ASSERT + #define ASSERT(__ignore) ((void)0) + #endif + #define ASSERTMSG(__ignore1, __ignore2) ((void)0) + #define ASSERTALWAYS(__ignore) ((void)0) + #define BREAKPOINT ((void)0) + #define SAFEBREAKPOINT ((void)0) + #define IFDEBUG(__ignore) ((void)0) + #define DEBUGSTRING(__ignore) ("") +#else + +/* From VisualC assert.h: Define _CRTIMP */ + #ifndef _CRTIMP + #ifdef _NTSDK + /* definition compatible with NT SDK */ + #define _CRTIMP + #else /* ndef _NTSDK */ + /* current definition */ + #ifdef _DLL + #define _CRTIMP __declspec(dllimport) + #else /* ndef _DLL */ + #define _CRTIMP + #endif /* _DLL */ + #endif /* _NTSDK */ + #endif /* _CRTIMP */ +/* End: Define _CRTIMP */ + + // this breakpoint doesn't cause exceptions if not in debugger + #ifdef _MSC_VER /* rcg10042001 */ + #define SAFEBREAKPOINT try { _asm { int 3 }; } catch(...) {;} + #endif + + #ifdef PLATFORM_UNIX /* rcg10042001 */ + #define SAFEBREAKPOINT raise(SIGTRAP) + #endif + + /* CT break point macro */ + #define BREAKPOINT \ + if (1) { \ + SAFEBREAKPOINT; \ + _assert("hard-coded breakpoint (CroTeam)",__FILE__,__LINE__); \ + } else NOTHING + + /* CT DEBUG macro -- the expression is executed only in debug version */ + #ifndef IFDEBUG + #define IFDEBUG(expr) \ + expr + #endif + + /* CT assertion macros */ + #ifndef ASSERT + #define ASSERT(expr) \ + if(!(expr)) { \ + /*SAFEBREAKPOINT;*/ \ + _assert(#expr,__FILE__,__LINE__); \ + } else NOTHING + #endif + + #define ASSERTALWAYS(msg) \ + if (1) { \ + /*SAFEBREAKPOINT;*/ \ + _assert(msg,__FILE__,__LINE__); \ + } else NOTHING + + #define ASSERTMSG(expr, msg) \ + if(!(expr)) { \ + /*SAFEBREAKPOINT;*/ \ + _assert(msg,__FILE__,__LINE__); \ + } else NOTHING + #define DEBUGSTRING(str) (str) +#endif + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Base.h b/Sources/Engine/Base/Base.h new file mode 100644 index 0000000..8b3b763 --- /dev/null +++ b/Sources/Engine/Base/Base.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +/* + * rcg10042001 In case these don't get defined in the project file, try to + * catch them here... + */ +#ifdef _MSC_VER + #ifndef PLATFORM_WIN32 + #define PLATFORM_WIN32 + #endif + + #ifndef PRAGMA_ONCE + #define PRAGMA_ONCE + #endif + + // disable problematic warnings + + #pragma warning(disable: 4251) // dll interfacing problems + #pragma warning(disable: 4275) // dll interfacing problems + #pragma warning(disable: 4018) // signed/unsigned mismatch + #pragma warning(disable: 4244) // type conversion warnings + #pragma warning(disable: 4284) // using -> for UDT + #pragma warning(disable: 4355) // 'this' : used in base member initializer list + #pragma warning(disable: 4660) // template-class specialization is already instantiated + #pragma warning(disable: 4723) // potential divide by 0 + + // define engine api exporting declaration specifiers + #ifdef ENGINE_EXPORTS + #define ENGINE_API __declspec(dllexport) + #else + #define ENGINE_API __declspec(dllimport) + + #ifdef NDEBUG + #pragma comment(lib, "Engine.lib") + #else + #pragma comment(lib, "EngineD.lib") + #endif + #endif + +#endif // defined _MSC_VER + + +#ifdef PLATFORM_UNIX /* rcg10042001 */ + #define ENGINE_API +#endif + diff --git a/Sources/Engine/Base/CRC.cpp b/Sources/Engine/Base/CRC.cpp new file mode 100644 index 0000000..7ad1488 --- /dev/null +++ b/Sources/Engine/Base/CRC.cpp @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +// Note: this CRC calculation algorithm, although originating from MSDN examples, +// is in fact identical to the Adler32 used in ZIP's CRC calculation. + +ENGINE_API ULONG crc_aulCRCTable[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, + 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, + 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, + 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, + 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, + 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, + 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, + 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, + 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, + 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, + 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, + 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, + 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, + 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, + 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, + 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, + 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, + 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, + 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, + 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, + 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, + 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; diff --git a/Sources/Engine/Base/CRC.h b/Sources/Engine/Base/CRC.h new file mode 100644 index 0000000..b1e1ae0 --- /dev/null +++ b/Sources/Engine/Base/CRC.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_CRC_H +#define SE_INCL_CRC_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +extern ENGINE_API ULONG crc_aulCRCTable[256]; + +// begin crc calculation +inline void CRC_Start(ULONG &ulCRC) { ulCRC = 0xFFFFFFFF; }; + +// add data to a crc value +inline void CRC_AddBYTE( ULONG &ulCRC, UBYTE ub) +{ + ulCRC = (ulCRC>>8)^crc_aulCRCTable[UBYTE(ulCRC)^ub]; +}; + +inline void CRC_AddWORD( ULONG &ulCRC, UBYTE uw) +{ + CRC_AddBYTE(ulCRC, UBYTE(uw>> 8)); + CRC_AddBYTE(ulCRC, UBYTE(uw>> 0)); +}; + +inline void CRC_AddLONG( ULONG &ulCRC, ULONG ul) +{ + CRC_AddBYTE(ulCRC, UBYTE(ul>>24)); + CRC_AddBYTE(ulCRC, UBYTE(ul>>16)); + CRC_AddBYTE(ulCRC, UBYTE(ul>> 8)); + CRC_AddBYTE(ulCRC, UBYTE(ul>> 0)); +}; + +inline void CRC_AddFLOAT(ULONG &ulCRC, FLOAT f) +{ + CRC_AddLONG(ulCRC, *(ULONG*)&f); +}; + +// add memory block to a CRC value +inline void CRC_AddBlock(ULONG &ulCRC, UBYTE *pubBlock, ULONG ulSize) +{ + for( INDEX i=0; i +#include +#include +#include +#include +#include + +extern INDEX net_bReportCRC; + +class CCRCEntry { +public: + CTFileName ce_fnmFile; // the file that CRC is for + ULONG ce_ulCRC; // CRC of the file + BOOL ce_bActive; // set if the file is now active for CRC checking + + // filename is its name (used for storing in nametable) + inline const CTFileName &GetName(void) { return ce_fnmFile; }; + void Clear(void) + { + ce_fnmFile.Clear(); + ce_ulCRC = 0; + ce_bActive = FALSE; + } +}; + +extern CDynamicStackArray _afnmNoCRC; +extern BOOL FileMatchesList(CDynamicStackArray &afnm, const CTFileName &fnm); + +#ifndef SE_INCL_CRCTABLE_CPP +#define SE_INCL_CRCTABLE_CPP +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#define TYPE CCRCEntry +#define CNameTable_TYPE CNameTable_CCRCEntry +#define CNameTableSlot_TYPE CNameTableSlot_CCRCEntry +#include +#include +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +static CDynamicStackArray _aceEntries; +static CNameTable_CCRCEntry _ntEntries; + +extern BOOL CRCT_bGatherCRCs = FALSE; // set while gathering CRCs of all loaded files + +// init CRC table +void CRCT_Init(void) +{ + _ntEntries.SetAllocationParameters(50, 10, 10); +} + +// check if a file is added +BOOL CRCT_IsFileAdded(const CTFileName &fnm) +{ + return _ntEntries.Find(fnm)!=NULL; +} + +// add one file to active list and get its crc +void CRCT_AddFile_t(const CTFileName &fnm, ULONG ulCRC/*=0*/) // throw char * +{ + // if not gathering CRCs now + if (!CRCT_bGatherCRCs) { + // do nothing + return; + } + + // try to find it in table + CCRCEntry *pce = _ntEntries.Find(fnm); + + BOOL bNew = FALSE; + // if found + if (pce!=NULL) { + // just activate it + bNew = !pce->ce_bActive; + pce->ce_bActive = TRUE; + // if crc is given + if (ulCRC!=0) { + // force it + pce->ce_ulCRC = ulCRC; + } + // if not found + } else { + // calculate checksum + if (ulCRC==0) { + + if (FileMatchesList(_afnmNoCRC, fnm)) { + ulCRC = 0x12345678; + } else { + ulCRC = GetFileCRC32_t(fnm); + } + } + // add to the table + pce = &_aceEntries.Push(); + pce->ce_fnmFile = fnm; + pce->ce_ulCRC = ulCRC; + pce->ce_bActive = TRUE; + _ntEntries.Add(pce); + bNew = TRUE; + } + if (bNew && net_bReportCRC) { + CPrintF("CRC %08x: '%s'\n", pce->ce_ulCRC, (const char*)pce->ce_fnmFile); + } +} + +// free all memory used by the crc cache +void CRCT_Clear(void) +{ + _ntEntries.Clear(); + _aceEntries.Clear(); +} + +// reset all files to not active +void CRCT_ResetActiveList(void) +{ + for(INDEX ice=0; ice<_aceEntries.Count(); ice++) { + _aceEntries[ice].ce_bActive = FALSE; + } +} + + +static INDEX GetNumberOfActiveEntries(void) +{ + INDEX ctActive = 0; + for(INDEX ice=0; ice<_aceEntries.Count(); ice++) { + if (_aceEntries[ice].ce_bActive) { + ctActive++; + } + } + return ctActive; +} + +// dump list of all active files to the stream +void CRCT_MakeFileList_t(CTStream &strmFiles) // throw char * +{ + // save number of active entries + INDEX ctActive = GetNumberOfActiveEntries(); + strmFiles<>ctFiles; + // for each one + for(INDEX i=0; i>strName; + // try to find it in table + CCRCEntry *pce = _ntEntries.Find(strName); + // if not there + if (pce==NULL) { + CRCT_AddFile_t(strName); + // add it now + pce = _ntEntries.Find(strName); + } + // add the crc + CRC_AddLONG(ulCRC, pce->ce_ulCRC); + } + CRCT_bGatherCRCs = bOld; + CRC_Finish(ulCRC); + return ulCRC; +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/CRCTable.h b/Sources/Engine/Base/CRCTable.h new file mode 100644 index 0000000..e5dbcad --- /dev/null +++ b/Sources/Engine/Base/CRCTable.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_CRCTABLE_H +#define SE_INCL_CRCTABLE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +extern BOOL CRCT_bGatherCRCs; // set while gathering CRCs of all loaded files + +// init CRC table +void CRCT_Init(void); +// add one file to active list +void CRCT_AddFile_t(const CTFileName &fnm, ULONG ulCRC=0);// throw char * +// check if a file is added +BOOL CRCT_IsFileAdded(const CTFileName &fnm); +// reset all files to not active +void CRCT_ResetActiveList(void); +// free all memory used by the crc cache +void CRCT_Clear(void); +// dump list of all active files to the stream +void CRCT_MakeFileList_t(CTStream &strmFiles); // throw char * +// dump checksums for all files from the list +ULONG CRCT_MakeCRCForFiles_t(CTStream &strmFiles); // throw char * + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/CTString.cpp b/Sources/Engine/Base/CTString.cpp new file mode 100644 index 0000000..d7c4a70 --- /dev/null +++ b/Sources/Engine/Base/CTString.cpp @@ -0,0 +1,714 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include + + +/* + * Equality comparison. + */ +BOOL CTString::operator==(const CTString &strOther) const +{ + ASSERT(IsValid() && strOther.IsValid()); + + return stricmp( str_String, strOther.str_String) == 0; +} +BOOL CTString::operator==(const char *strOther) const +{ + ASSERT(IsValid() && strOther!=NULL); + + return stricmp( str_String, strOther) == 0; +} + BOOL operator==(const char *strThis, const CTString &strOther) +{ + ASSERT(strOther.IsValid() && strThis!=NULL); + + return strOther == strThis; +} + +/* + * Inequality comparison. + */ +BOOL CTString::operator!=(const CTString &strOther) const +{ + ASSERT(IsValid() && strOther.IsValid()); + + return !( *this == strOther ); +} +BOOL CTString::operator!=(const char *strOther) const +{ + ASSERT(IsValid() && strOther!=NULL); + + return !( *this == strOther ); +} + BOOL operator!=(const char *strThis, const CTString &strOther) +{ + ASSERT(strOther.IsValid() && strThis!=NULL); + + return !( strOther == strThis); +} + + +/* + * String concatenation. + */ +CTString CTString::operator+(const CTString &strSecond) const +{ + ASSERT(IsValid() && strSecond.IsValid()); + + return(CTString(*this)+=strSecond); +} +CTString operator+(const char *strFirst, const CTString &strSecond) +{ + ASSERT(strFirst!=NULL && strSecond.IsValid()); + + return(CTString(strFirst)+=strSecond); +} +CTString &CTString::operator+=(const CTString &strSecond) +{ + ASSERT(IsValid() && strSecond.IsValid()); + + GrowMemory( (void **)&str_String, strlen( str_String) + strlen( strSecond) + 1 ); + strcat(str_String, strSecond.str_String); + return *this; +} + +/* + * Remove given prefix string from this string + */ +BOOL CTString::RemovePrefix( const CTString &strPrefix) +{ + INDEX lenPrefix = strlen( strPrefix); + INDEX lenDest = strlen( str_String) - lenPrefix; + + if( strnicmp( str_String, strPrefix, lenPrefix) != 0) + return FALSE; + CTString strTemp = CTString( &str_String[ lenPrefix]); + ShrinkMemory( (void **)&str_String, lenDest+1); + strcpy( str_String, strTemp.str_String); + return TRUE; +} +/* Check if has given prefix */ +BOOL CTString::HasPrefix( const CTString &strPrefix) const +{ + INDEX lenPrefix = strlen( strPrefix); + if( strnicmp( str_String, strPrefix, lenPrefix) != 0) + return FALSE; + return TRUE; +} + +/* Find index of a substring in a string (returns -1 if not found). */ +INDEX CTString::FindSubstr(const CTString &strSub) +{ + INDEX ct = Length(); + INDEX ctSub = strSub.Length(); + for (INDEX i=0; istr_String; chr--) { + // if the character is not space + if (!IsSpace(*chr)) { + // stop searching + break; + } + } + // trim to that character + return TrimRight(chr-str_String+1); +} + + +// retain only first line of the string +void CTString::OnlyFirstLine(void) +{ + // get position of first line end + const char *pchNL = strchr(str_String, '\n'); + // if none + if (pchNL==NULL) { + // do nothing + return; + } + // trim everything after that char + TrimRight(pchNL-str_String); +} + + +/* Calculate hashing value for the string. */ +ULONG CTString::GetHash(void) const +{ + ULONG ulKey = 0; + INDEX len = strlen(str_String); + + for(INDEX i=0; i>(CTStream &strmStream, CTString &strString) +{ + ASSERT(strString.IsValid()); + + // read length + INDEX iLength; + strmStream>>iLength; + ASSERT(iLength>=0); + // allocate that much memory + FreeMemory(strString.str_String); + strString.str_String = (char *) AllocMemory(iLength+1); // take end-marker in account + // if the string is not empty + if (iLength>0) { + // read string + strmStream.Read_t( strString.str_String, iLength); // without end-marker + } + // set end-marker + strString.str_String[iLength] = 0; + + return strmStream; +} + + +void CTString::ReadFromText_t(CTStream &strmStream, + const CTString &strKeyword="") // throw char * +{ + ASSERT(IsValid()); + + // keyword must be present + strmStream.ExpectKeyword_t(strKeyword); + + // read the string from the file + char str[1024]; + strmStream.GetLine_t(str, sizeof(str)); + + // copy it here + (*this) = str; +} + +/* + * Write to stream. + */ +CTStream &operator<<(CTStream &strmStream, const CTString &strString) +{ + ASSERT(strString.IsValid()); + + // calculate size + INDEX iStringLen = strlen( strString); + // write size + strmStream<0) { + // write string + strmStream.Write_t(strString.str_String, iStringLen); // without end-marker + } + + return strmStream; +} + + +#ifndef NDEBUG +/* + * Check if string data is valid. + */ +BOOL CTString::IsValid(void) const +{ + ASSERT(this!=NULL && str_String!=NULL); + return TRUE; +} +#endif // NDEBUG + + +/* Load an entire text file into a string. */ +void CTString::ReadUntilEOF_t(CTStream &strmFile) // throw char * +{ + // get the file size + SLONG slFileSize = strmFile.GetStreamSize()-strmFile.GetPos_t(); + + // allocate that much memory + FreeMemory(str_String); + str_String = (char *) AllocMemory(slFileSize+1); // take end-marker in account + // read the entire file there + if (slFileSize>0) { + strmFile.Read_t( str_String, slFileSize); + } + // add end marker + str_String[slFileSize] = 0; + + // rewrite entire string + char *pchRead=str_String; + char *pchWrite=str_String; + while(*pchRead!=0) { + // skip the '\r' characters + if (*pchRead!='\r') { + *pchWrite++ = *pchRead++; + } else { + pchRead++; + } + } + *pchWrite = 0; +} + + +void CTString::Load_t(const class CTFileName &fnmFile) // throw char * +{ + ASSERT(IsValid()); + + // open the file for reading + CTFileStream strmFile; + strmFile.Open_t(fnmFile); + + // read string until end of file + ReadUntilEOF_t(strmFile); +} + + +void CTString::LoadKeepCRLF_t(const class CTFileName &fnmFile) // throw char * +{ + ASSERT(IsValid()); + + // open the file for reading + CTFileStream strmFile; + strmFile.Open_t(fnmFile); + // get the file size + SLONG slFileSize = strmFile.GetStreamSize(); + + // allocate that much memory + FreeMemory(str_String); + str_String = (char *) AllocMemory(slFileSize+1); // take end-marker in account + // read the entire file there + if (slFileSize>0) { + strmFile.Read_t( str_String, slFileSize); + } + // add end marker + str_String[slFileSize] = 0; +} + +/* Save an entire string into a text file. */ +void CTString::Save_t(const class CTFileName &fnmFile) // throw char * +{ + // open the file for writing + CTFileStream strmFile; + strmFile.Create_t(fnmFile); + // save the string to the file + strmFile.PutString_t(*this); +} +void CTString::SaveKeepCRLF_t(const class CTFileName &fnmFile) // throw char * +{ + // open the file for writing + CTFileStream strmFile; + strmFile.Create_t(fnmFile); + // save the string to the file + if (strlen(str_String)>0) { + strmFile.Write_t(str_String, strlen(str_String)); + } +} + + +// Print formatted to a string +INDEX CTString::PrintF(const char *strFormat, ...) +{ + va_list arg; + va_start(arg, strFormat); + return VPrintF(strFormat, arg); +} + + +INDEX CTString::VPrintF(const char *strFormat, va_list arg) +{ + + static INDEX _ctBufferSize = 0; + static char *_pchBuffer = NULL; + + // if buffer was not allocated yet + if (_ctBufferSize==0) { + // allocate it + _ctBufferSize = 256; + _pchBuffer = (char*)AllocMemory(_ctBufferSize); + } + + // repeat + INDEX iLen; + FOREVER { + // print to the buffer + iLen = _vsnprintf(_pchBuffer, _ctBufferSize, strFormat, arg); + // if printed ok + if (iLen!=-1) { + // stop + break; + } + // increase the buffer size + _ctBufferSize += 256; + GrowMemory((void**)&_pchBuffer, _ctBufferSize); + } + + (*this) = _pchBuffer; + return iLen; +} + + + +static void *psscanf = &sscanf; +// Scan formatted from a string +__declspec(naked) INDEX CTString::ScanF(const char *strFormat, ...) +{ + __asm { + push eax + mov eax,dword ptr [esp+8] + mov eax,dword ptr [eax] + mov dword ptr [esp+8], eax + pop eax + jmp dword ptr [psscanf] + } +} + + + // split string in two strings at specified position (char AT splitting position goes to str2) +void CTString::Split( INDEX iPos, CTString &str1, CTString &str2) +{ + str1 = str_String; + str2 = str_String; + str1.TrimRight(iPos); + str2.TrimLeft(strlen(str2)-iPos); +} + + +// insert one character in string at specified pos +void CTString::InsertChar( INDEX iPos, char cChr) +{ + // clamp position + INDEX ctChars = strlen(str_String); + if( iPos>ctChars) iPos=ctChars; + else if( iPos<0) iPos=0; + // grow memory used by string + GrowMemory( (void**)&str_String, ctChars+2); + // copy part of string to make room for char to insert + memmove( &str_String[iPos+1], &str_String[iPos], ctChars+1-iPos); + str_String[iPos] = cChr; +} + + +// delete one character from string at specified pos +void CTString::DeleteChar( INDEX iPos) +{ + // clamp position + INDEX ctChars = strlen(str_String); + if (ctChars==0) { + return; + } + if( iPos>ctChars) iPos=ctChars; + else if( iPos<0) iPos=0; + // copy part of string + memmove( &str_String[iPos], &str_String[iPos+1], ctChars-iPos+1); + // shrink memory used by string over deleted char + ShrinkMemory( (void**)&str_String, ctChars); +} + + + +// wild card comparison +BOOL CTString::Matches(const CTString &strOther) const +{ + return Matches(strOther.str_String); +} + + +BOOL CTString::Matches(const char *strOther) const +{ +// pattern matching code from sourceforge.net codesnippet archive +// adjusted a bit to match in/out parameters +#define MAX_CALLS 200 + int calls=0, wild=0, q=0; + const char *mask=strOther, *name=str_String; + const char *m=mask, *n=name, *ma=mask, *na=name; + + for(;;) { + if (++calls > MAX_CALLS) { + return FALSE; + } + if (*m == '*') { + while (*m == '*') ++m; + wild = 1; + ma = m; + na = n; + } + + if (!*m) { + if (!*n) { + return TRUE; + } + + for (--m; (m > mask) && (*m == '?'); --m) ; + + if ((*m == '*') && (m > mask) && + (m[-1] != '\\')) { + return TRUE; + } + if (!wild) { + return FALSE; + } + m = ma; + } else if (!*n) { + while(*m == '*') ++m; + if (*m != 0) { + return FALSE; + } else { + return TRUE; + } + } + if ((*m == '\\') && ((m[1] == '*') || (m[1] == '?'))) { + ++m; + q = 1; + } else { + q = 0; + } + + if ((tolower(*m) != tolower(*n)) && ((*m != '?') || q)) { + if (!wild) { + return FALSE; + } + m = ma; + n = ++na; + } else { + if (*m) ++m; + if (*n) ++n; + } + } +} + + +// variable management functions +void CTString::LoadVar(const class CTFileName &fnmFile) +{ + try { + CTString str; + str.Load_t(fnmFile); + *this = str; + } catch (char *strError) { + CPrintF(TRANS("Cannot load variable from '%s':\n%s\n"), (CTString&)fnmFile, strError); + } +} + +void CTString::SaveVar(const class CTFileName &fnmFile) +{ + try { + Save_t(fnmFile); + } catch (char *strError) { + CPrintF(TRANS("Cannot save variable to '%s':\n%s\n"), (CTString&)fnmFile, strError); + } +} + + +// general variable functions +void LoadStringVar(const CTFileName &fnmVar, CTString &strVar) +{ + strVar.LoadVar(fnmVar); +} + +void SaveStringVar(const CTFileName &fnmVar, CTString &strVar) +{ + strVar.SaveVar(fnmVar); +} + + +void LoadIntVar(const CTFileName &fnmVar, INDEX &iVar) +{ + CTString strVar; + strVar.LoadVar(fnmVar); + if (strVar!="") { + CTString strHex = strVar; + if (strHex.RemovePrefix("0x")) { + strHex.ScanF("%x", &iVar); + } else { + strVar.ScanF("%d", &iVar); + } + } +} + +void SaveIntVar(const CTFileName &fnmVar, INDEX &iVar) +{ + CTString strVar; + strVar.PrintF("%d", iVar); + strVar.SaveVar(fnmVar); +} + + + +// remove special codes from string +CTString RemoveSpecialCodes( const CTString &str) +{ + CTString strRet=str; + char *pcSrc = (char*)(const char*)strRet; + char *pcDst = (char*)(const char*)strRet; + // copy char inside string skipping special codes + while( *pcSrc != 0) + { + if( *pcSrc != '^') + { // advance to next char + *pcDst = *pcSrc; + pcSrc++; + pcDst++; + } + else + { // skip some characters + pcSrc++; + switch( *pcSrc) { + case 'c': pcSrc+=FindZero((UBYTE*)pcSrc,7); continue; + case 'a': pcSrc+=FindZero((UBYTE*)pcSrc,3); continue; + case 'f': pcSrc+=FindZero((UBYTE*)pcSrc,2); continue; + case 'b': case 'i': case 'r': case 'o': + case 'C': case 'A': case 'F': case 'B': case 'I': pcSrc+=1; continue; + // if we get here this means that ^ or an unrecognized special code was specified + default: continue; + } + } + } + // terminate string + *pcDst = 0; + return strRet; +} diff --git a/Sources/Engine/Base/CTString.h b/Sources/Engine/Base/CTString.h new file mode 100644 index 0000000..06faab1 --- /dev/null +++ b/Sources/Engine/Base/CTString.h @@ -0,0 +1,131 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_CTSTRING_H +#define SE_INCL_CTSTRING_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Main string class + */ +class ENGINE_API CTString { +public: + char *str_String; // pointer to memory holding the character string +public: + /* Default constructor. */ + inline CTString(void); + /* Copy constructor. */ + inline CTString(const CTString &strOriginal); + /* Constructor from character string. */ + inline CTString(const char *pString); + /* Constructor with formatting. */ + inline CTString(INDEX iDummy, const char *strFormat, ...); + /* Destructor. */ + inline ~CTString(); + /* Clear the object. */ + inline void Clear(void); + + /* Conversion into character string. */ + inline operator const char*() const; + + /* Assignment. */ + inline CTString &operator=(const char *strCharString); + inline CTString &operator=(const CTString &strOther); + + /* Check if string data is valid. */ + BOOL IsValid(void) const; + + // return length of the string + inline INDEX Length(void) const { return strlen(str_String); }; + INDEX LengthNaked(void) const; + + // strip decorations from the string + CTString Undecorated(void) const; + + /* Find index of a substring in a string (returns -1 if not found). */ + INDEX FindSubstr(const CTString &strSub); + /* Replace a substring in a string. */ + BOOL ReplaceSubstr(const CTString &strSub, const CTString &strNewSub); + /* Check if has given prefix */ + BOOL HasPrefix( const CTString &strPrefix) const; + /* Remove given prefix string from this string */ + BOOL RemovePrefix( const CTString &strPrefix); + /* Trim the string to contain at most given number of characters. */ + INDEX TrimLeft( INDEX ctCharacters); + INDEX TrimRight( INDEX ctCharacters); + /* Trim the string from spaces. */ + INDEX TrimSpacesLeft(void); + INDEX TrimSpacesRight(void); + /* Calcuate hashing value for the string. */ + ULONG GetHash(void) const; + // retain only first line of the string + void OnlyFirstLine(void); + + /* Equality comparison. */ + BOOL operator==(const CTString &strOther) const; + BOOL operator==(const char *strOther) const; + ENGINE_API friend BOOL operator==(const char *strThis, const CTString &strOther); + /* Inequality comparison. */ + BOOL operator!=(const CTString &strOther) const; + BOOL operator!=(const char *strOther) const; + ENGINE_API friend BOOL operator!=(const char *strThis, const CTString &strOther); + // wild card comparison (other string may contain wildcards) + BOOL Matches(const CTString &strOther) const; + BOOL Matches(const char *strOther) const; + + /* String concatenation. */ + CTString operator+(const CTString &strSecond) const; + CTString &operator+=(const CTString &strSecond); + ENGINE_API friend CTString operator+(const char *strFirst, const CTString &strSecond); + + // split string in two strings at specified position (char AT splitting position goes to str2) + void Split( INDEX iPos, CTString &str1, CTString &str2); + void InsertChar( INDEX iPos, char cChr); // insert char at position + void DeleteChar( INDEX iPos); // delete char at position + + /* Throw exception */ + void Throw_t(void); + + /* Read from stream. */ + ENGINE_API friend CTStream &operator>>(CTStream &strmStream, CTString &strString); + void ReadFromText_t(CTStream &strmStream, const CTString &strKeyword); // throw char * + /* Write to stream. */ + ENGINE_API friend CTStream &operator<<(CTStream &strmStream, const CTString &strString); + + /* Load an entire text file into a string. */ + void Load_t(const class CTFileName &fnmFile); // throw char * + void LoadKeepCRLF_t(const class CTFileName &fnmFile); // throw char * + void ReadUntilEOF_t(CTStream &strmStream); // throw char * + /* Save an entire string into a text file. */ + void Save_t(const class CTFileName &fnmFile); // throw char * + void SaveKeepCRLF_t(const class CTFileName &fnmFile); // throw char * + + // Print formatted to a string + INDEX PrintF(const char *strFormat, ...); + INDEX VPrintF(const char *strFormat, va_list arg); + // Scan formatted from a string + INDEX ScanF(const char *strFormat, ...); + + // variable management functions + void LoadVar(const CTFileName &fnmFile); + void SaveVar(const CTFileName &fnmFile); +}; + + +// general variable functions +ENGINE_API void LoadStringVar( const CTFileName &fnmVar, CTString &strVar); +ENGINE_API void SaveStringVar( const CTFileName &fnmVar, CTString &strVar); +ENGINE_API void LoadIntVar( const CTFileName &fnmVar, INDEX &iVar); +ENGINE_API void SaveIntVar( const CTFileName &fnmVar, INDEX &iVar); + +ENGINE_API CTString RemoveSpecialCodes( const CTString &str); + + +#include + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/CTString.inl b/Sources/Engine/Base/CTString.inl new file mode 100644 index 0000000..e6283b6 --- /dev/null +++ b/Sources/Engine/Base/CTString.inl @@ -0,0 +1,118 @@ +#ifndef SE_INCL_CTSTRING_INL +#define SE_INCL_CTSTRING_INL +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* + * Default constructor. + */ +ENGINE_API CTString::CTString(void) +{ + str_String = StringDuplicate(""); +} + +/* + * Copy constructor. + */ +ENGINE_API CTString::CTString(const CTString &strOriginal) +{ + ASSERT(strOriginal.IsValid()); + + // make string duplicate + str_String = StringDuplicate(strOriginal.str_String); +} + +/* + * Constructor from character string. + */ +ENGINE_API CTString::CTString( const char *strCharString) +{ + ASSERT(strCharString!=NULL); + + // make string duplicate + str_String = StringDuplicate( strCharString); +} + +/* Constructor with formatting. */ +ENGINE_API CTString::CTString(INDEX iDummy, const char *strFormat, ...) +{ + str_String = StringDuplicate(""); + va_list arg; + va_start(arg, strFormat); + VPrintF(strFormat, arg); +} + +/* + * Destructor. + */ +ENGINE_API CTString::~CTString() +{ + // check that it is valid + ASSERT(IsValid()); + // free memory + FreeMemory(str_String); +} + +/* + * Clear the object. + */ +ENGINE_API void CTString::Clear(void) +{ + operator=(""); +} + +/* + * Conversion into character string. + */ +ENGINE_API CTString::operator const char*() const +{ + ASSERT(IsValid()); + + return str_String; +} + +/* + * Assignment. + */ +ENGINE_API CTString &CTString::operator=(const char *strCharString) +{ + ASSERT(IsValid()); + ASSERT(strCharString!=NULL); + + /* The other string must be copied _before_ this memory is freed, since it could be same + pointer! + */ + // make a copy of character string + char *strCopy = StringDuplicate(strCharString); + // empty this string + FreeMemory(str_String); + // assign it the copy of the character string + str_String = strCopy; + + return *this; +} +ENGINE_API CTString &CTString::operator=(const CTString &strOther) +{ + ASSERT(IsValid()); + ASSERT(strOther.IsValid()); + + /* The other string must be copied _before_ this memory is freed, since it could be same + pointer! + */ + // make a copy of character string + char *strCopy = StringDuplicate(strOther.str_String); + // empty this string + FreeMemory(str_String); + // assign it the copy of the character string + str_String = strCopy; + + return *this; +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Changeable.cpp b/Sources/Engine/Base/Changeable.cpp new file mode 100644 index 0000000..ef48385 --- /dev/null +++ b/Sources/Engine/Base/Changeable.cpp @@ -0,0 +1,58 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include + +/* + * Constructor. + */ +CChangeable::CChangeable(void) +{ + ch_LastChangeTime = TIME(-1); +} + +/* + * Mark that something has changed in this object. + */ +void CChangeable::MarkChanged(void) +{ + ch_LastChangeTime = _pTimer->CurrentTick(); +} + +/* + * Test if some updateable object is up to date with this changeable. + */ +BOOL CChangeable::IsUpToDate(const CUpdateable &ud) const +{ + return ch_LastChangeTime < ud.LastUpdateTime(); +} + +/* + * Constructor. + */ +CChangeableRT::CChangeableRT(void) +{ + ch_LastChangeTime = TIME(-1); +} + +/* + * Mark that something has changed in this object. + */ +void CChangeableRT::MarkChanged(void) +{ + ch_LastChangeTime = _pTimer->GetRealTimeTick(); +} + +/* + * Test if some updateable object is up to date with this changeable. + */ +BOOL CChangeableRT::IsUpToDate(const CUpdateableRT &ud) const +{ + return ch_LastChangeTime < ud.LastUpdateTime(); +} + diff --git a/Sources/Engine/Base/Changeable.h b/Sources/Engine/Base/Changeable.h new file mode 100644 index 0000000..f7f6960 --- /dev/null +++ b/Sources/Engine/Base/Changeable.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_CHANGEABLE_H +#define SE_INCL_CHANGEABLE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* + * Object that can change in time. + */ +class ENGINE_API CChangeable { +private: + TIME ch_LastChangeTime; // last time this object has been changed +public: + /* Constructor. */ + CChangeable(void); + /* Mark that something has changed in this object. */ + void MarkChanged(void); + /* Test if some updateable object is up to date with this changeable. */ + BOOL IsUpToDate(const CUpdateable &ud) const; +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/ChangeableRT.h b/Sources/Engine/Base/ChangeableRT.h new file mode 100644 index 0000000..6e2ad60 --- /dev/null +++ b/Sources/Engine/Base/ChangeableRT.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_CHANGEABLERT_H +#define SE_INCL_CHANGEABLERT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* + * Object that can change in time. + */ +class ENGINE_API CChangeableRT { +private: + TIME ch_LastChangeTime; // last time this object has been changed +public: + /* Constructor. */ + CChangeableRT(void); + /* Mark that something has changed in this object. */ + void MarkChanged(void); + /* Test if some updateable object is up to date with this changeable. */ + BOOL IsUpToDate(const CUpdateableRT &ud) const; +}; + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Console.cpp b/Sources/Engine/Base/Console.cpp new file mode 100644 index 0000000..71f0b00 --- /dev/null +++ b/Sources/Engine/Base/Console.cpp @@ -0,0 +1,327 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include + +extern CConsole *_pConsole = NULL; + +extern INDEX con_iLastLines; +extern BOOL con_bCapture = FALSE; +extern CTString con_strCapture = ""; + + +// Constructor. +CConsole::CConsole(void) +{ + con_strBuffer = NULL; + con_strLineBuffer = NULL; + con_atmLines = NULL; + con_fLog = NULL; +} +// Destructor. +CConsole::~CConsole(void) +{ + if (this==NULL) { + return; + } + if (con_fLog!=NULL) { + fclose(con_fLog); + con_fLog = NULL; + } + if (con_strBuffer!=NULL) { + FreeMemory(con_strBuffer); + } + if (con_strLineBuffer!=NULL) { + FreeMemory(con_strLineBuffer); + } + if (con_atmLines!=NULL) { + FreeMemory(con_atmLines); + } +} + +// Initialize the console. +void CConsole::Initialize(const CTFileName &fnmLog, INDEX ctCharsPerLine, INDEX ctLines) +{ + con_csConsole.cs_iIndex = -1; + // synchronize access to console + CTSingleLock slConsole(&con_csConsole, TRUE); + + // allocate the buffer + con_ctCharsPerLine = ctCharsPerLine; + con_ctLines = ctLines; + con_ctLinesPrinted = 0; + // note: we add +1 for '\n' perline and +1 '\0' at the end of buffer + con_strBuffer = (char *)AllocMemory((ctCharsPerLine+1)*ctLines+1); + con_strLineBuffer = (char *)AllocMemory(ctCharsPerLine+2); // includes '\n' and '\0' + con_atmLines = (TIME*)AllocMemory((ctLines+1)*sizeof(TIME)); + // make it empty + for(INDEX iLine=0; iLine=con_ctLinesPrinted) { + return ""; + } + ASSERT(iLine>=0 && iLine=0 && iLineGetRealTimeTick():0.0f; +} + +// scroll buffer up, discarding lines at the start +void CConsole::ScrollBufferUp(INDEX ctLines) +{ + if (this==NULL) { + return; + } + ASSERT(ctLines>0 && ctLinesPutString(strBuffer); +} + +// Add a string of text to console +void CPutString(const char *strString) +{ + if (_pConsole==NULL) { + return; + } + _pConsole->PutString(strString); +} + +// Get number of lines newer than given time +INDEX CON_NumberOfLinesAfter(TIME tmLast) +{ + if (_pConsole==NULL) { + return 0; + } + return _pConsole->NumberOfLinesAfter(tmLast); +} +// Get one of last lines +CTString CON_GetLastLine(INDEX iLine) +{ + if (_pConsole==NULL) { + return ""; + } + return _pConsole->GetLastLine(iLine); +} +// Discard timing info for last lines +void CON_DiscardLastLineTimes(void) +{ + if (_pConsole==NULL) { + return; + } + _pConsole->DiscardLastLineTimes(); +} +// Get current console buffer. +const char *CON_GetBuffer(void) +{ + if (_pConsole==NULL) { + return ""; + } + return _pConsole->GetBuffer(); +} +INDEX CON_GetBufferSize(void) +{ + if (_pConsole==NULL) { + return 1; + } + return _pConsole->GetBufferSize(); +} diff --git a/Sources/Engine/Base/Console.h b/Sources/Engine/Base/Console.h new file mode 100644 index 0000000..984cfdd --- /dev/null +++ b/Sources/Engine/Base/Console.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_CONSOLE_H +#define SE_INCL_CONSOLE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// Print formated text to the main console. +ENGINE_API extern void CPrintF(const char *strFormat, ...); +// Add a string of text to console +ENGINE_API void CPutString(const char *strString); + +// Get number of lines newer than given time +ENGINE_API INDEX CON_NumberOfLinesAfter(TIME tmLast); +// Get one of last lines +ENGINE_API CTString CON_GetLastLine(INDEX iLine); +// Discard timing info for last lines +ENGINE_API void CON_DiscardLastLineTimes(void); +// Get current console buffer. +ENGINE_API const char *CON_GetBuffer(void); +ENGINE_API INDEX CON_GetBufferSize(void); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Console_internal.h b/Sources/Engine/Base/Console_internal.h new file mode 100644 index 0000000..0e190e5 --- /dev/null +++ b/Sources/Engine/Base/Console_internal.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_CONSOLE_INTERNAL_H +#define SE_INCL_CONSOLE_INTERNAL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +// Object that takes care of game console. +#define CONSOLE_MAXLASTLINES 15 // how many last-line times to remember +class CConsole { +public: +// implementation: + CTCriticalSection con_csConsole; // critical section for access to console data + char *con_strBuffer; // the allocated buffer + char *con_strCurrent; // next char to print + char *con_strLastLine; // start of last line in buffer + char *con_strLineBuffer; // one-line-sized buffer for temp usage + INDEX con_ctCharsPerLine; // number of characters per line + INDEX con_ctLines; // number of total lines + TIME *con_atmLines; // time stamp for each line + INDEX con_ctLinesPrinted; // number of lines printed + FILE *con_fLog; // log file for streaming the console to + + // clear line buffer + void ClearLineBuffer(); + // clear one given line in buffer + void ClearLine(INDEX iLine); + // scroll buffer up, discarding lines at the start + void ScrollBufferUp(INDEX ctBytesToFree); + // Move last line times one place back and add new time + void NewLastTime(TIME tmNew); + +// interface: + + // Constructor. + CConsole(void); + // Destructor. + ~CConsole(void); + + // Initialize the console. + void Initialize(const CTFileName &fnmLog, INDEX ctCharsPerLine, INDEX ctLines); + + // Get current console buffer. + ENGINE_API const char *GetBuffer(void); + ENGINE_API INDEX GetBufferSize(void); + // Add a string of text to console + void PutString(const char *strString); + // Close console log file buffers (call only when force-exiting!) + void CloseLog(void); + + // Get number of lines newer than given time + INDEX NumberOfLinesAfter(TIME tmLast); + // Get one of last lines + CTString GetLastLine(INDEX iLine); + // Discard timing info for last lines + void DiscardLastLineTimes(void); +}; + +ENGINE_API extern CConsole *_pConsole; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Directory.cpp b/Sources/Engine/Base/Directory.cpp new file mode 100644 index 0000000..dfe87d2 --- /dev/null +++ b/Sources/Engine/Base/Directory.cpp @@ -0,0 +1,170 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include +#include +#include + +extern CDynamicStackArray _afnmBaseBrowseInc; +extern CDynamicStackArray _afnmBaseBrowseExc; + +class CDirToRead { +public: + CListNode dr_lnNode; + CTString dr_strDir; +}; + +int qsort_CompareCTFileName(const void *elem1, const void *elem2 ) +{ + const CTFileName &fnm1 = **(CTFileName **)elem1; + const CTFileName &fnm2 = **(CTFileName **)elem2; + return strcmp(fnm1, fnm2); +} + +extern BOOL FileMatchesList(CDynamicStackArray &afnm, const CTFileName &fnm); + +void FillDirList_internal(const CTFileName &fnmBasePath, + CDynamicStackArray &afnm, const CTFileName &fnmDir, const CTString &strPattern, BOOL bRecursive, + CDynamicStackArray *pafnmInclude, CDynamicStackArray *pafnmExclude) +{ + // add the directory to list of directories to search + CListHead lhDirs; + CDirToRead *pdrFirst = new CDirToRead; + pdrFirst->dr_strDir = fnmDir; + lhDirs.AddTail(pdrFirst->dr_lnNode); + + // while the list of directories is not empty + while (!lhDirs.IsEmpty()) { + // take the first one + CDirToRead *pdr = LIST_HEAD(lhDirs, CDirToRead, dr_lnNode); + CTFileName fnmDir = pdr->dr_strDir; + delete pdr; + + // if the dir is not allowed + if (pafnmInclude!=NULL && + (!FileMatchesList(*pafnmInclude, fnmDir) || FileMatchesList(*pafnmExclude, fnmDir)) ) { + // skip it + continue; + } + + // start listing the directory + struct _finddata_t c_file; long hFile; + hFile = _findfirst( (const char *)(fnmBasePath+fnmDir+"*"), &c_file ); + + // for each file in the directory + for ( + BOOL bFileExists = hFile!=-1; + bFileExists; + bFileExists = _findnext( hFile, &c_file )==0) { + + // if dummy dir (this dir, parent dir, or any dir starting with '.') + if (c_file.name[0]=='.') { + // skip it + continue; + } + + // get the file's filepath + CTFileName fnm = fnmDir+c_file.name; + + // if it is a directory + if (c_file.attrib&_A_SUBDIR) { + // if recursive reading + if (bRecursive) { + // add it to the list of directories to search + CDirToRead *pdrNew = new CDirToRead; + pdrNew->dr_strDir = fnm+"\\"; + lhDirs.AddTail(pdrNew->dr_lnNode); + } + // if it matches the pattern + } else if (strPattern=="" || fnm.Matches(strPattern)) { + // add that file + afnm.Push() = fnm; + } + } + } +} + + +// make a list of all files in a directory +ENGINE_API void MakeDirList( + CDynamicStackArray &afnmDir, const CTFileName &fnmDir, const CTString &strPattern, ULONG ulFlags) +{ + afnmDir.PopAll(); + BOOL bRecursive = ulFlags&DLI_RECURSIVE; + BOOL bSearchCD = ulFlags&DLI_SEARCHCD; + + // make one temporary array + CDynamicStackArray afnm; + + if (_fnmMod!="") { + FillDirList_internal(_fnmApplicationPath, afnm, fnmDir, strPattern, bRecursive, + &_afnmBaseBrowseInc, &_afnmBaseBrowseExc); + if (bSearchCD) { + FillDirList_internal(_fnmCDPath, afnm, fnmDir, strPattern, bRecursive, + &_afnmBaseBrowseInc, &_afnmBaseBrowseExc); + } + FillDirList_internal(_fnmApplicationPath+_fnmMod, afnm, fnmDir, strPattern, bRecursive, NULL, NULL); + } else { + FillDirList_internal(_fnmApplicationPath, afnm, fnmDir, strPattern, bRecursive, NULL, NULL); + if (bSearchCD) { + FillDirList_internal(_fnmCDPath, afnm, fnmDir, strPattern, bRecursive, NULL, NULL); + } + } + + // for each file in zip archives + CTString strDirPattern = fnmDir; + INDEX ctFilesInZips = UNZIPGetFileCount(); + for(INDEX iFileInZip=0; iFileInZip +#include +#include + +#include +#include +#include +#include + +#include + +INDEX con_bNoWarnings = 0; + +// global handle for application window in full-screen mode +extern HWND _hwndMain; +extern BOOL _bFullScreen; + + +/* + * Report error and terminate program. + */ +static BOOL _bInFatalError = FALSE; +void FatalError(const char *strFormat, ...) +{ + // disable recursion + if (_bInFatalError) return; + _bInFatalError = TRUE; + + // reset default windows display mode first + // (this is a low overhead and shouldn't allocate memory) + CDS_ResetMode(); + + // hide fullscreen window if any + if( _bFullScreen) { + // must do minimize first - don't know why :( + ShowWindow( _hwndMain, SW_MINIMIZE); + ShowWindow( _hwndMain, SW_HIDE); + } + + // format the message in buffer + va_list arg; + va_start(arg, strFormat); + CTString strBuffer; + strBuffer.VPrintF(strFormat, arg); + + if (_pConsole!=NULL) { + // print the buffer to the console + CPutString(TRANS("FatalError:\n")); + CPutString(strBuffer); + // make sure the console log was written safely + _pConsole->CloseLog(); + } + + // create message box with just OK button + MessageBoxA(NULL, strBuffer, TRANS("Fatal Error"), + MB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL); + + _bInFatalError = FALSE; + + extern void EnableWindowsKeys(void); + EnableWindowsKeys(); + // exit program + exit(EXIT_FAILURE); +} + +/* + * Report warning without terminating program (stops program until user responds). + */ +void WarningMessage(const char *strFormat, ...) +{ + // format the message in buffer + va_list arg; + va_start(arg, strFormat); + CTString strBuffer; + strBuffer.VPrintF(strFormat, arg); + + // print it to console + CPrintF("%s\n", strBuffer); + // if warnings are enabled + if( !con_bNoWarnings) { + // create message box + MessageBoxA(NULL, strBuffer, TRANS("Warning"), MB_OK|MB_ICONEXCLAMATION|MB_SETFOREGROUND|MB_TASKMODAL); + } +} + +void InfoMessage(const char *strFormat, ...) +{ + // format the message in buffer + va_list arg; + va_start(arg, strFormat); + CTString strBuffer; + strBuffer.VPrintF(strFormat, arg); + + // print it to console + CPrintF("%s\n", strBuffer); + // create message box + MessageBoxA(NULL, strBuffer, TRANS("Information"), MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND|MB_TASKMODAL); +} + +/* Ask user for yes/no answer(stops program until user responds). */ +BOOL YesNoMessage(const char *strFormat, ...) +{ + // format the message in buffer + va_list arg; + va_start(arg, strFormat); + CTString strBuffer; + strBuffer.VPrintF(strFormat, arg); + + // print it to console + CPrintF("%s\n", strBuffer); + // create message box + return MessageBoxA(NULL, strBuffer, TRANS("Question"), MB_YESNO|MB_ICONQUESTION|MB_SETFOREGROUND|MB_TASKMODAL)==IDYES; +} + +/* + * Throw an exception of formatted string. + */ +void ThrowF_t(char *strFormat, ...) // throws char * +{ + const SLONG slBufferSize = 256; + char strBuffer[slBufferSize+1]; + // format the message in buffer + va_list arg; + va_start(arg, strFormat); // variable arguments start after this argument + _vsnprintf(strBuffer, slBufferSize, strFormat, arg); + throw strBuffer; +} + +/* + * Get the name string for error code. + */ + const char *ErrorName(const struct ErrorTable *pet, SLONG ulErrCode) +{ + for (INDEX i=0; iet_Count; i++) { + if (pet->et_Errors[i].ec_Code == ulErrCode) { + return pet->et_Errors[i].ec_Name; + } + } + return TRANS("CROTEAM_UNKNOWN"); +} + +/* + * Get the description string for error code. + */ + const char *ErrorDescription(const struct ErrorTable *pet, SLONG ulErrCode) +{ + for (INDEX i=0; iet_Count; i++) { + if (pet->et_Errors[i].ec_Code == ulErrCode) { + return pet->et_Errors[i].ec_Description; + } + } + return TRANS("Unknown error"); +} + +/* + * Get the description string for windows error code. + */ + extern const CTString GetWindowsError(DWORD dwWindowsErrorCode) +{ + // buffer to receive error description + LPVOID lpMsgBuf; + // call function that will prepare text abount given windows error code + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, dwWindowsErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL ); + // create result CTString from prepared message + CTString strResultMessage = (char *)lpMsgBuf; + // Free the buffer. + LocalFree( lpMsgBuf ); + return strResultMessage; +} + +// must be in separate function to disable stupid optimizer +extern void Breakpoint(void) +{ + __asm int 0x03; +} diff --git a/Sources/Engine/Base/ErrorReporting.h b/Sources/Engine/Base/ErrorReporting.h new file mode 100644 index 0000000..f78d7b6 --- /dev/null +++ b/Sources/Engine/Base/ErrorReporting.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ERRORREPORTING_H +#define SE_INCL_ERRORREPORTING_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* Throw an exception of formatted string. */ +ENGINE_API extern void ThrowF_t(char *strFormat, ...); // throws char * +/* Report error and terminate program. */ +ENGINE_API extern void FatalError(const char *strFormat, ...); +/* Report warning without terminating program (stops program until user responds). */ +ENGINE_API extern void WarningMessage(const char *strFormat, ...); +/* Report information message to user (stops program until user responds). */ +ENGINE_API extern void InfoMessage(const char *strFormat, ...); +/* Ask user for yes/no answer(stops program until user responds). */ +ENGINE_API extern BOOL YesNoMessage(const char *strFormat, ...); +/* Get the description string for windows error code. */ +ENGINE_API extern const CTString GetWindowsError(DWORD dwWindowsErrorCode); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/ErrorTable.h b/Sources/Engine/Base/ErrorTable.h new file mode 100644 index 0000000..e104352 --- /dev/null +++ b/Sources/Engine/Base/ErrorTable.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ERRORTABLE_H +#define SE_INCL_ERRORTABLE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +struct ErrorCode { + SLONG ec_Code; // error code value + char *ec_Name; // error code constant name (in .h files) + char *ec_Description; // error description (in help files) +}; + +struct ErrorTable { + INDEX et_Count; // number of errors + struct ErrorCode *et_Errors; // array of error codes +}; + +// macro for defining error codes +#define ERRORCODE(code, description) {code, #code, description} +// macro for defining error table +#define ERRORTABLE(errorcodes) {sizeof(errorcodes)/sizeof(struct ErrorCode), errorcodes} +/* Get the name string for error code. */ +ENGINE_API extern const char *ErrorName(const struct ErrorTable *pet, SLONG slErrCode); +/* Get the description string for error code. */ +ENGINE_API extern const char *ErrorDescription(const struct ErrorTable *pet, SLONG slErrCode); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/FLEX.skl b/Sources/Engine/Base/FLEX.skl new file mode 100644 index 0000000..2ee3fc5 --- /dev/null +++ b/Sources/Engine/Base/FLEX.skl @@ -0,0 +1,1496 @@ +#include "StdH.h" + +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.81 95/03/20 14:02:24 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +%- +#include +%* + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +//#ifdef c_plusplus +//#ifndef __cplusplus +//#define __cplusplus +//#endif +//#endif + +#if 1 //def __cplusplus + + #include +%+ + class istream; +%* + + /* Use prototypes in function declarations. */ + #define YY_USE_PROTOS + + /* The "const" storage-class-modifier is valid. */ + #define YY_USE_CONST + +#else /* ! __cplusplus */ + + #if __STDC__ + + #define YY_USE_PROTOS + #define YY_USE_CONST + + #endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +%- +extern FILE *yyin, *yyout; +%* + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { +%- + FILE *yy_input_file; +%+ + istream* yy_input_file; +%* + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +%- Standard (non-C++) definition +static YY_BUFFER_STATE yy_current_buffer = 0; +%* + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +%- Standard (non-C++) definition +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( const char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( const char *bytes, int len )); +%* + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +%% yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +//static + void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, const char *, int )); +#endif + +#ifndef YY_NO_INPUT +%- Standard (non-C++) definition +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +%* +#endif + +%- Standard (non-C++) definition +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( const char msg[] )); +%* + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ +%% code to fiddle yytext and yyleng for yymore() goes here + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ +%% code to copy yytext_ptr to yytext[] goes here, if %array + yy_c_buf_p = yy_cp; + +%% data tables for the DFA and the user's section 1 definitions go here + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifdef YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +%- Standard (non-C++) definition +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +%+ C++ definition +#define ECHO LexerOutput( yytext, yyleng ) +%* +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +%% fread()/read() definition of YY_INPUT goes here unless we're doing C++ +%+ C++ definition + if ( (result = LexerInput( (char *) buf, max_size )) < 0 ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +%* +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +%- +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +%+ +#define YY_FATAL_ERROR(msg) LexerError( msg ) +%* +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +%- Standard (non-C++) definition +#define YY_DECL int yylex YY_PROTO(( void )) +%+ C++ definition +#define YY_DECL int yyFlexLexer::yylex() +%* +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +%% YY_RULE_SETUP definition goes here + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +%% user's declarations go here + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) +%- + yyin = stdin; +%+ + yyin = &cin; +%* + + if ( ! yyout ) +%- + yyout = stdout; +%+ + yyout = &cout; +%* + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { +%% yymore()-related code goes here + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + +%% code to set up and find next match goes here + +yy_find_action: +%% code to find the action number goes here + + YY_DO_BEFORE_ACTION; + +%% code for yylineno update goes here + +do_action: /* This label is used only to access EOF actions. */ + +%% debug code goes here + + switch ( yy_act ) + { /* beginning of action switch */ +%% actions go here + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { +%% code to do back-up for compressed tables and set up yy_cp goes here + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + +%+ +yyFlexLexer::yyFlexLexer( istream* arg_yyin, ostream* arg_yyout ) + { + yyin = arg_yyin; + yyout = arg_yyout; + yy_c_buf_p = 0; + yy_init = 1; + yy_start = 0; + yy_flex_debug = 0; + yylineno = 1; // this will only get updated if %option yylineno + + yy_did_buffer_switch_on_eof = 0; + + yy_looking_for_trail_begin = 0; + yy_more_flag = 0; + yy_more_len = 0; + + yy_start_stack_ptr = yy_start_stack_depth = 0; + yy_start_stack = 0; + + yy_current_buffer = 0; + +#ifdef YY_USES_REJECT + yy_state_buf = new yy_state_type[YY_BUF_SIZE + 2]; +#else + yy_state_buf = 0; +#endif + } + +yyFlexLexer::~yyFlexLexer() + { + delete yy_state_buf; + yy_delete_buffer( yy_current_buffer ); + } + +void yyFlexLexer::switch_streams( istream* new_in, ostream* new_out ) + { + if ( new_in ) + { + yy_delete_buffer( yy_current_buffer ); + yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE ) ); + } + + if ( new_out ) + yyout = new_out; + } + +#ifdef YY_INTERACTIVE +int yyFlexLexer::LexerInput( char* buf, int /* max_size */ ) +#else +int yyFlexLexer::LexerInput( char* buf, int max_size ) +#endif + { + if ( yyin->eof() || yyin->fail() ) + return 0; + +#ifdef YY_INTERACTIVE + yyin->get( buf[0] ); + + if ( yyin->eof() ) + return 0; + + if ( yyin->bad() ) + return -1; + + return 1; + +#else + (void) yyin->read( buf, max_size ); + + if ( yyin->bad() ) + return -1; + else + return yyin->gcount(); +#endif + } + +void yyFlexLexer::LexerOutput( const char* buf, int size ) + { + (void) yyout->write( buf, size ); + } +%* + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +%- +static int yy_get_next_buffer() +%+ +int yyFlexLexer::yy_get_next_buffer() +%* + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +%- +static yy_state_type yy_get_previous_state() +%+ +yy_state_type yyFlexLexer::yy_get_previous_state() +%* + { + register yy_state_type yy_current_state; + register char *yy_cp; + +%% code to get the start state into yy_current_state goes here + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { +%% code to find the next state goes here + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +%- +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif +%+ +yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state ) +%* + { + register int yy_is_jam; +%% code to find the next state, and perhaps do backing up, goes here + + return yy_is_jam ? 0 : yy_current_state; + } + + +%- +#ifdef YY_USE_PROTOS +//static + void yyunput( int c, register char *yy_bp ) +#else +//static + void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif +%+ +void yyFlexLexer::yyunput( int c, register char* yy_bp ) +%* + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + +%% update yylineno here + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } + + +%- +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif +%+ +int yyFlexLexer::yyinput() +%* + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + +%% update BOL and yylineno + + return c; + } + + +%- +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif +%+ +void yyFlexLexer::yyrestart( istream* input_file ) +%* + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +%- +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif +%+ +void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +%* + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +%- +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif +%+ +void yyFlexLexer::yy_load_buffer_state() +%* + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +%- +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif +%+ +YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( istream* file, int size ) +%* + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +%- +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif +%+ +void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b ) +%* + { + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +%- +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + +%+ +extern "C" int isatty YY_PROTO(( int )); +void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, istream* file ) +%* + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +%- +#ifdef YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#ifdef YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif +%+ + b->yy_is_interactive = 0; +%* + } + + +%- +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + +%+ +void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b ) +%* + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } +%* + + +#ifndef YY_NO_SCAN_BUFFER +%- +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +%* +#endif + + +#ifndef YY_NO_SCAN_STRING +%- +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( const char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +const char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +%* +#endif + + +#ifndef YY_NO_SCAN_BYTES +%- +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( const char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +const char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +%* +#endif + + +#ifndef YY_NO_PUSH_STATE +%- +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif +%+ +void yyFlexLexer::yy_push_state( int new_state ) +%* + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +%- +static void yy_pop_state() +%+ +void yyFlexLexer::yy_pop_state() +%* + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +%- +static int yy_top_state() +%+ +int yyFlexLexer::yy_top_state() +%* + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +%- +#ifdef YY_USE_PROTOS +static void yy_fatal_error( const char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + +%+ + +void yyFlexLexer::LexerError( const char msg[] ) + { + cerr << msg << '\n'; + exit( YY_EXIT_FAILURE ); + } +%* + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, const char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +const char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + return (void *) realloc( ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#ifdef YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif diff --git a/Sources/Engine/Base/FileName.cpp b/Sources/Engine/Base/FileName.cpp new file mode 100644 index 0000000..13cdef5 --- /dev/null +++ b/Sources/Engine/Base/FileName.cpp @@ -0,0 +1,255 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include + +template CDynamicArray; +template CDynamicStackArray; +#include +template CStaticStackArray; + +/* + * Get directory part of a filename. + */ +CTFileName CTFileName::FileDir() const +{ + ASSERT(IsValid()); + + // make a temporary copy of string + CTFileName strPath(*this); + // find last backlash in it + char *pPathBackSlash = strrchr( strPath.str_String, '\\'); + // if there is no backslash + if( pPathBackSlash == NULL) { + // return emptystring as directory + return( CTFileName("")); + } + // set end of string after where the backslash was + pPathBackSlash[1] = 0; + // return a copy of temporary string + return( CTFileName( strPath)); +} + +CTFileName &CTFileName::operator=(const char *strCharString) +{ + ASSERTALWAYS( "Use CTFILENAME for conversion from char *!"); + return *this; +} + +/* + * Get name part of a filename. + */ +CTFileName CTFileName::FileName() const +{ + ASSERT(IsValid()); + + // make a temporary copy of string + CTFileName strPath(*this); + // find last dot in it + char *pDot = strrchr( strPath.str_String, '.'); + // if there is a dot + if( pDot != NULL) { + // set end of string there + pDot[0] = 0; + } + + // find last backlash in what's left + char *pBackSlash = strrchr( strPath.str_String, '\\'); + // if there is no backslash + if( pBackSlash == NULL) { + // return it all as filename + return( CTFileName(strPath)); + } + // return a copy of temporary string, starting after the backslash + return( CTFileName( pBackSlash+1)); +} + +/* + * Get extension part of a filename. + */ +CTFileName CTFileName::FileExt() const +{ + ASSERT(IsValid()); + + // find last dot in the string + char *pExtension = strrchr( str_String, '.'); + // if there is no dot + if( pExtension == NULL) { + // return no extension + return( CTFileName("")); + } + // return a copy of the extension part, together with the dot + return( CTFileName( pExtension)); +} + +CTFileName CTFileName::NoExt() const +{ + return FileDir()+FileName(); +} + +static INDEX GetSlashPosition(const CHAR* pszString) +{ + for (INDEX iPos = 0; '\0' != *pszString; ++iPos, ++pszString) { + if (('\\' == *pszString) || ('/' == *pszString)) { + return iPos; + } + } + return -1; +} + +/* + * Set path to the absolute path, taking \.. and /.. into account. + */ +void CTFileName::SetAbsolutePath(void) +{ + // Collect path parts + CTString strRemaining(*this); + CStaticStackArray astrParts; + INDEX iSlashPos = GetSlashPosition(strRemaining); + if (0 > iSlashPos) { + return; // Invalid path + } + for (;;) { + CTString &strBeforeSlash = astrParts.Push(); + CTString strAfterSlash; + strRemaining.Split(iSlashPos, strBeforeSlash, strAfterSlash); + strAfterSlash.TrimLeft(strAfterSlash.Length() - 1); + strRemaining = strAfterSlash; + iSlashPos = GetSlashPosition(strRemaining); + if (0 > iSlashPos) { + astrParts.Push() = strRemaining; + break; + } + } + // Remove certain path parts + for (INDEX iPart = 0; iPart < astrParts.Count(); ++iPart) { + if (CTString("..") != astrParts[iPart]) { + continue; + } + if (0 == iPart) { + return; // Invalid path + } + // Remove ordered + CStaticStackArray astrShrinked; + astrShrinked.Push(astrParts.Count() - 2); + astrShrinked.PopAll(); + for (INDEX iCopiedPart = 0; iCopiedPart < astrParts.Count(); ++iCopiedPart) { + if ((iCopiedPart != iPart - 1) && (iCopiedPart != iPart)) { + astrShrinked.Push() = astrParts[iCopiedPart]; + } + } + astrParts.MoveArray(astrShrinked); + iPart -= 2; + } + // Set new content + strRemaining.Clear(); + for (INDEX iPart = 0; iPart < astrParts.Count(); ++iPart) { + strRemaining += astrParts[iPart]; + if (iPart < astrParts.Count() - 1) { +#ifdef PLATFORM_WIN32 + strRemaining += CTString("\\"); +#else + strRemaining += CTString("/"); +#endif + } + } + (*this) = strRemaining; +} + +/* + * Remove application path from a file name and returns TRUE if it's a relative path. + */ +BOOL CTFileName::RemoveApplicationPath_t(void) // throws char * +{ + CTFileName fnmApp = _fnmApplicationPath; + fnmApp.SetAbsolutePath(); + // remove the path string from beginning of the string + BOOL bIsRelative = RemovePrefix(fnmApp); + if (_fnmMod!="") { + RemovePrefix(_fnmApplicationPath+_fnmMod); + } + return bIsRelative; +} + +/* + * Read from stream. + */ + CTStream &operator>>(CTStream &strmStream, CTFileName &fnmFileName) +{ + // if dictionary is enabled + if (strmStream.strm_dmDictionaryMode == CTStream::DM_ENABLED) { + // read the index in dictionary + INDEX iFileName; + strmStream>>iFileName; + // get that file from the dictionary + fnmFileName = strmStream.strm_afnmDictionary[iFileName]; + + // if dictionary is processing or not active + } else { + char strTag[] = "_FNM"; strTag[0] = 'D'; // must create tag at run-time! + // skip dependency catcher header + strmStream.ExpectID_t(strTag); // data filename + // read the string + strmStream>>(CTString &)fnmFileName; + fnmFileName.fnm_pserPreloaded = NULL; + } + + return strmStream; +} + +/* + * Write to stream. + */ + CTStream &operator<<(CTStream &strmStream, const CTFileName &fnmFileName) +{ + // if dictionary is enabled + if (strmStream.strm_dmDictionaryMode == CTStream::DM_ENABLED) { + // try to find the filename in dictionary + CTFileName *pfnmExisting = strmStream.strm_ntDictionary.Find(fnmFileName); + // if not existing + if (pfnmExisting==NULL) { + // add it + pfnmExisting = &strmStream.strm_afnmDictionary.Push(); + *pfnmExisting = fnmFileName; + strmStream.strm_ntDictionary.Add(pfnmExisting); + } + // write its index + strmStream< + +/* + * Special kind of string, dedicated to storing filenames. + */ +class ENGINE_API CTFileName : public CTString { +public: + class CSerial *fnm_pserPreloaded; // pointer to already loaded object if available +private: + /* Constructor from character string. */ + inline CTFileName(const char *pString) : CTString(pString), fnm_pserPreloaded(NULL) {}; +public: + /* Default constructor. */ + inline CTFileName(void) : fnm_pserPreloaded(NULL) {}; + /* Copy constructor. */ + inline CTFileName(const CTString &strOriginal) : CTString(strOriginal), fnm_pserPreloaded(NULL) {}; + /* Constructor from character string for insertion in exe-file. */ + inline CTFileName(const char *pString, int i) : CTString(pString+i), fnm_pserPreloaded(NULL) {}; + + /* Assignment. */ + CTFileName &operator=(const char *strCharString); + inline void operator=(const CTString &strOther) { + CTString::operator=(strOther); + fnm_pserPreloaded = NULL; + }; + + /* Get directory part of a filename. */ + CTFileName FileDir(void) const; + /* Get name part of a filename. */ + CTFileName FileName(void) const; + /* Get extension part of a filename. */ + CTFileName FileExt(void) const; + /* Get path and file name without extension. */ + CTFileName NoExt(void) const; + /* Set path to the absolute path, taking \.. and /.. into account. */ + void SetAbsolutePath(void); + /* Remove application path from a file name. */ + BOOL RemoveApplicationPath_t(void); // throw char * + + // filename is its own name (used for storing in nametable) + inline const CTFileName &GetName(void) { return *this; }; + + void ReadFromText_t(CTStream &strmStream, const CTString &strKeyword=""); // throw char * + + /* Read from stream. */ + ENGINE_API friend CTStream &operator>>(CTStream &strmStream, CTFileName &fnmFileName); + /* Write to stream. */ + ENGINE_API friend CTStream &operator<<(CTStream &strmStream, const CTFileName &fnmFileName); +}; + +// macro for defining a literal filename in code (EFNM = exe-filename) +#define CTFILENAME(string) CTFileName("EFNM" string, 4) +#define DECLARE_CTFILENAME(name, string) CTFileName name("EFNM" string, 4) + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/GroupFile.h b/Sources/Engine/Base/GroupFile.h new file mode 100644 index 0000000..d788207 --- /dev/null +++ b/Sources/Engine/Base/GroupFile.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_GROUPFILE_H +#define SE_INCL_GROUPFILE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Class containing info about files inside group file + */ +class ENGINE_API CGroupFileFileInfo { +public: + CTFileName gffi_fnFileName; // full name of the file (relative to application path) + ULONG gffi_ulFileDataOffset; // file data block offset from beginning of the file + ULONG gffi_ulFileSize; // size of sub group file + /* Read one file info from stream. */ + void Read_t(CTStream *istr); // throw char * + /* Write one file info into stream. */ + void Write_t(CTStream *ostr); // throw char * +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/IFeel.cpp b/Sources/Engine/Base/IFeel.cpp new file mode 100644 index 0000000..a1e5fb7 --- /dev/null +++ b/Sources/Engine/Base/IFeel.cpp @@ -0,0 +1,203 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include +#include +#include + +//Imm_GetProductName +HINSTANCE _hLib = NULL; +BOOL (*immCreateDevice)(HINSTANCE &hInstance, HWND &hWnd) = NULL; +void (*immDeleteDevice)(void) = NULL; +BOOL (*immProductName)(char *strProduct,int iMaxCount) = NULL; +BOOL (*immLoadFile)(const char *fnFile) = NULL; +void (*immUnloadFile)(void) = NULL; +void (*immPlayEffect)(const char *pstrEffectName) = NULL; +void (*immStopEffect)(const char *pstrEffectName) = NULL; +void (*immChangeGain)(const float fGain) = NULL; + +FLOAT ifeel_fGain = 1.0f; +INDEX ifeel_bEnabled = FALSE; + +#ifndef NDEBUG + #define IFEEL_DLL_NAME "Bin/Debug/ImmWrapper.dll" +#else + #define IFEEL_DLL_NAME "Bin/ImmWrapper.dll" +#endif + +void ifeel_GainChange(void *ptr) +{ + IFeel_ChangeGain(ifeel_fGain); +} + +CTString IFeel_GetProductName() +{ + char strProduct[MAX_PATH]; + if(immProductName != NULL) + { + if(immProductName(strProduct,MAX_PATH)) + { + return strProduct; + } + } + return ""; +} + +CTString IFeel_GetProjectFileName() +{ + CTString strIFeelTable; + CTFileName fnIFeelTable = (CTString)"Data\\IFeel.txt"; + CTString strDefaultProjectFile = "Data\\Default.ifr"; + // get product name + CTString strProduct = IFeel_GetProductName(); + try + { + strIFeelTable.Load_t(fnIFeelTable); + } + catch(char *strErr) + { + CPrintF("%s\n",strErr); + return ""; + } + + CTString strLine; + // read up to 1000 devices + for(INDEX idev=0;idev<1000;idev++) + { + char strDeviceName[256]; + char strProjectFile[256]; + strLine = strIFeelTable; + // read first line + strLine.OnlyFirstLine(); + if(strLine==strIFeelTable) + { + break; + } + // remove that line + strIFeelTable.RemovePrefix(strLine); + strIFeelTable.DeleteChar(0); + // read device name and project file name + strIFeelTable.ScanF("\"%256[^\"]\" \"%256[^\"]\"",&strDeviceName,&strProjectFile); + // check if this is default + if(strcmp(strDeviceName,"Default")==0) strDefaultProjectFile = strProjectFile; + // check if this is current device + if(strProduct == strDeviceName) return strProjectFile; + } + // device was not found, return default project file + CPrintF("No project file specified for device '%s'.\nUsing default project file\n",strProduct); + return strDefaultProjectFile; +} + +// inits imm ifeel device +BOOL IFeel_InitDevice(HINSTANCE &hInstance, HWND &hWnd) +{ + _pShell->DeclareSymbol("void inp_IFeelGainChange(INDEX);", &ifeel_GainChange); + _pShell->DeclareSymbol("persistent user FLOAT inp_fIFeelGain post:inp_IFeelGainChange;", &ifeel_fGain); + _pShell->DeclareSymbol("const user INDEX sys_bIFeelEnabled;", &ifeel_bEnabled); + IFeel_ChangeGain(ifeel_fGain); + + // load iFeel lib + CTFileName fnmExpanded; + ExpandFilePath(EFP_READ | EFP_NOZIPS,(CTString)IFEEL_DLL_NAME,fnmExpanded); + if(_hLib!=NULL) return FALSE; + + UINT iOldErrorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); + _hLib = LoadLibraryA(fnmExpanded); + SetErrorMode(iOldErrorMode); + if(_hLib==NULL) + { + CPrintF("Error loading ImmWraper.dll.\n\tIFeel disabled\n"); + return FALSE; + } + + // take func pointers + immCreateDevice = (BOOL(*)(HINSTANCE &hInstance, HWND &hWnd)) GetProcAddress(_hLib,"Imm_CreateDevice"); + immDeleteDevice = (void(*)(void)) GetProcAddress(_hLib,"Imm_DeleteDevice"); + immProductName = (BOOL(*)(char *strProduct,int iMaxCount)) GetProcAddress(_hLib,"Imm_GetProductName"); + immLoadFile = (BOOL(*)(const char *fnFile))GetProcAddress(_hLib,"Imm_LoadFile"); + immUnloadFile = (void(*)(void))GetProcAddress(_hLib,"immUnloadFile"); + immPlayEffect = (void(*)(const char *pstrEffectName))GetProcAddress(_hLib,"Imm_PlayEffect"); + immStopEffect = (void(*)(const char *pstrEffectName))GetProcAddress(_hLib,"Imm_StopEffect"); + immChangeGain = (void(*)(const float fGain))GetProcAddress(_hLib,"Imm_ChangeGain"); + + // create device + if(immCreateDevice == NULL) + { + return FALSE; + } + BOOL hr = immCreateDevice(hInstance,hWnd); + if(!hr) + { + CPrintF("IFeel mouse not found.\n"); + IFeel_DeleteDevice(); + return FALSE; + } + CPrintF("IFeel mouse '%s' initialized\n",(const char*)IFeel_GetProductName()); + ifeel_bEnabled = TRUE; + return TRUE; +} +// delete imm ifeel device +void IFeel_DeleteDevice() +{ + if(immDeleteDevice != NULL) immDeleteDevice(); + immCreateDevice = NULL; + immDeleteDevice = NULL; + immProductName = NULL; + immLoadFile = NULL; + immUnloadFile = NULL; + immPlayEffect = NULL; + immStopEffect = NULL; + immChangeGain = NULL; + + if(_hLib != NULL) FreeLibrary(_hLib); + _hLib = NULL; +} +// loads project file +BOOL IFeel_LoadFile(CTFileName fnFile) +{ + CTFileName fnmExpanded; + ExpandFilePath(EFP_READ | EFP_NOZIPS,fnFile,fnmExpanded); + + if(immLoadFile!=NULL) + { + BOOL hr = immLoadFile((const char*)fnmExpanded); + if(hr) + { + CPrintF("IFeel project file '%s' loaded\n", fnFile); + return TRUE; + } + else + { + CPrintF("Error loading IFeel project file '%s'\n", fnFile); + return FALSE; + } + } + return FALSE; +} +// unloads project file +void IFeel_UnloadFile() +{ + if(immUnloadFile!=NULL) immUnloadFile(); +} +// plays effect from ifr file +void IFeel_PlayEffect(char *pstrEffectName) +{ + IFeel_ChangeGain(ifeel_fGain); + if(immPlayEffect!=NULL) immPlayEffect(pstrEffectName); +} +// stops effect from ifr file +void IFeel_StopEffect(char *pstrEffectName) +{ + if(immStopEffect!=NULL) immStopEffect(pstrEffectName); +} +// change gain +void IFeel_ChangeGain(FLOAT fGain) +{ + if(immChangeGain!=NULL) + { + immChangeGain(fGain); + //CPrintF("Changing IFeel gain to '%g'\n",fGain); + } +} diff --git a/Sources/Engine/Base/IFeel.h b/Sources/Engine/Base/IFeel.h new file mode 100644 index 0000000..56a01d6 --- /dev/null +++ b/Sources/Engine/Base/IFeel.h @@ -0,0 +1,19 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_IFEEL_H +#define SE_INCL_IFEEL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +ENGINE_API BOOL IFeel_InitDevice(HINSTANCE &hInstance, HWND &hWnd); +ENGINE_API void IFeel_DeleteDevice(); +ENGINE_API CTString IFeel_GetProductName(); +ENGINE_API CTString IFeel_GetProjectFileName(); +ENGINE_API BOOL IFeel_LoadFile(CTFileName fnFile); +ENGINE_API void IFeel_UnLoadFile(); +ENGINE_API void IFeel_PlayEffect(char *pstrEffectName); +ENGINE_API void IFeel_StopEffect(char *pstrEffectName); +ENGINE_API void IFeel_ChangeGain(FLOAT fGain); + +#endif /* include-once check. */ diff --git a/Sources/Engine/Base/Input.cpp b/Sources/Engine/Base/Input.cpp new file mode 100644 index 0000000..2e7597a --- /dev/null +++ b/Sources/Engine/Base/Input.cpp @@ -0,0 +1,1202 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern INDEX inp_iKeyboardReadingMethod; +extern FLOAT inp_fMouseSensitivity; +extern INDEX inp_bAllowMouseAcceleration; +extern INDEX inp_bMousePrecision; +extern FLOAT inp_fMousePrecisionFactor; +extern FLOAT inp_fMousePrecisionThreshold; +extern FLOAT inp_fMousePrecisionTimeout; +extern FLOAT inp_bInvertMouse; +extern INDEX inp_bFilterMouse; +extern INDEX inp_bAllowPrescan; + +extern INDEX inp_i2ndMousePort; +extern FLOAT inp_f2ndMouseSensitivity; +extern INDEX inp_b2ndMousePrecision; +extern FLOAT inp_f2ndMousePrecisionThreshold; +extern FLOAT inp_f2ndMousePrecisionTimeout; +extern FLOAT inp_f2ndMousePrecisionFactor; +extern INDEX inp_bFilter2ndMouse; +extern INDEX inp_bInvert2ndMouse; + +extern INDEX inp_iMButton4Dn = 0x20040; +extern INDEX inp_iMButton4Up = 0x20000; +extern INDEX inp_iMButton5Dn = 0x10020; +extern INDEX inp_iMButton5Up = 0x10000; +extern INDEX inp_bMsgDebugger = FALSE; +extern INDEX inp_bForceJoystickPolling = 0; +extern INDEX inp_ctJoysticksAllowed = 8; +extern INDEX inp_bAutoDisableJoysticks = 0; + +static CTString inp_astrAxisTran[MAX_OVERALL_AXES];// translated names for axis + +/* + +NOTE: Three different types of key codes are used here: + 1) kid - engine internal type - defined in KeyNames.h + 2) scancode - raw PC keyboard scancodes as returned in keydown/keyup messages + 3) virtkey - virtual key codes used by windows + +*/ + +// name that is not translated (international) +#define INTNAME(str) str, "" +// name that is translated +#define TRANAME(str) str, "ETRS" str + +// basic key conversion table +static struct KeyConversion { + INDEX kc_iKID; + INDEX kc_iVirtKey; + INDEX kc_iScanCode; + char *kc_strName; + char *kc_strNameTrans; +} _akcKeys[] = { + + // reserved for 'no-key-pressed' + { KID_NONE, -1, -1, TRANAME("None")}, + +// numbers row + { KID_1 , '1', 2, INTNAME("1")}, + { KID_2 , '2', 3, INTNAME("2")}, + { KID_3 , '3', 4, INTNAME("3")}, + { KID_4 , '4', 5, INTNAME("4")}, + { KID_5 , '5', 6, INTNAME("5")}, + { KID_6 , '6', 7, INTNAME("6")}, + { KID_7 , '7', 8, INTNAME("7")}, + { KID_8 , '8', 9, INTNAME("8")}, + { KID_9 , '9', 10, INTNAME("9")}, + { KID_0 , '0', 11, INTNAME("0")}, + { KID_MINUS , 189, 12, INTNAME("-")}, + { KID_EQUALS , 187, 13, INTNAME("=")}, + +// 1st alpha row + { KID_Q , 'Q', 16, INTNAME("Q")}, + { KID_W , 'W', 17, INTNAME("W")}, + { KID_E , 'E', 18, INTNAME("E")}, + { KID_R , 'R', 19, INTNAME("R")}, + { KID_T , 'T', 20, INTNAME("T")}, + { KID_Y , 'Y', 21, INTNAME("Y")}, + { KID_U , 'U', 22, INTNAME("U")}, + { KID_I , 'I', 23, INTNAME("I")}, + { KID_O , 'O', 24, INTNAME("O")}, + { KID_P , 'P', 25, INTNAME("P")}, + { KID_LBRACKET , 219, 26, INTNAME("[")}, + { KID_RBRACKET , 221, 27, INTNAME("]")}, + { KID_BACKSLASH , 220, 43, INTNAME("\\")}, + +// 2nd alpha row + { KID_A , 'A', 30, INTNAME("A")}, + { KID_S , 'S', 31, INTNAME("S")}, + { KID_D , 'D', 32, INTNAME("D")}, + { KID_F , 'F', 33, INTNAME("F")}, + { KID_G , 'G', 34, INTNAME("G")}, + { KID_H , 'H', 35, INTNAME("H")}, + { KID_J , 'J', 36, INTNAME("J")}, + { KID_K , 'K', 37, INTNAME("K")}, + { KID_L , 'L', 38, INTNAME("L")}, + { KID_SEMICOLON , 186, 39, INTNAME(";")}, + { KID_APOSTROPHE , 222, 40, INTNAME("'")}, +// 3rd alpha row + { KID_Z , 'Z', 44, INTNAME("Z")}, + { KID_X , 'X', 45, INTNAME("X")}, + { KID_C , 'C', 46, INTNAME("C")}, + { KID_V , 'V', 47, INTNAME("V")}, + { KID_B , 'B', 48, INTNAME("B")}, + { KID_N , 'N', 49, INTNAME("N")}, + { KID_M , 'M', 50, INTNAME("M")}, + { KID_COMMA , 190, 51, INTNAME(",")}, + { KID_PERIOD , 188, 52, INTNAME(".")}, + { KID_SLASH , 191, 53, INTNAME("/")}, + +// row with F-keys + { KID_F1 , VK_F1, 59, INTNAME("F1")}, + { KID_F2 , VK_F2, 60, INTNAME("F2")}, + { KID_F3 , VK_F3, 61, INTNAME("F3")}, + { KID_F4 , VK_F4, 62, INTNAME("F4")}, + { KID_F5 , VK_F5, 63, INTNAME("F5")}, + { KID_F6 , VK_F6, 64, INTNAME("F6")}, + { KID_F7 , VK_F7, 65, INTNAME("F7")}, + { KID_F8 , VK_F8, 66, INTNAME("F8")}, + { KID_F9 , VK_F9, 67, INTNAME("F9")}, + { KID_F10 , VK_F10, 68, INTNAME("F10")}, + { KID_F11 , VK_F11, 87, INTNAME("F11")}, + { KID_F12 , VK_F12, 88, INTNAME("F12")}, + +// extra keys + { KID_ESCAPE , VK_ESCAPE, 1, TRANAME("Escape")}, + { KID_TILDE , -1, 41, TRANAME("Tilde")}, + { KID_BACKSPACE , VK_BACK, 14, TRANAME("Backspace")}, + { KID_TAB , VK_TAB, 15, TRANAME("Tab")}, + { KID_CAPSLOCK , VK_CAPITAL, 58, TRANAME("Caps Lock")}, + { KID_ENTER , VK_RETURN, 28, TRANAME("Enter")}, + { KID_SPACE , VK_SPACE, 57, TRANAME("Space")}, + +// modifier keys + { KID_LSHIFT , VK_LSHIFT , 42, TRANAME("Left Shift")}, + { KID_RSHIFT , VK_RSHIFT , 54, TRANAME("Right Shift")}, + { KID_LCONTROL , VK_LCONTROL, 29, TRANAME("Left Control")}, + { KID_RCONTROL , VK_RCONTROL, 256+29, TRANAME("Right Control")}, + { KID_LALT , VK_LMENU , 56, TRANAME("Left Alt")}, + { KID_RALT , VK_RMENU , 256+56, TRANAME("Right Alt")}, + +// navigation keys + { KID_ARROWUP , VK_UP, 256+72, TRANAME("Arrow Up")}, + { KID_ARROWDOWN , VK_DOWN, 256+80, TRANAME("Arrow Down")}, + { KID_ARROWLEFT , VK_LEFT, 256+75, TRANAME("Arrow Left")}, + { KID_ARROWRIGHT , VK_RIGHT, 256+77, TRANAME("Arrow Right")}, + { KID_INSERT , VK_INSERT, 256+82, TRANAME("Insert")}, + { KID_DELETE , VK_DELETE, 256+83, TRANAME("Delete")}, + { KID_HOME , VK_HOME, 256+71, TRANAME("Home")}, + { KID_END , VK_END, 256+79, TRANAME("End")}, + { KID_PAGEUP , VK_PRIOR, 256+73, TRANAME("Page Up")}, + { KID_PAGEDOWN , VK_NEXT, 256+81, TRANAME("Page Down")}, + { KID_PRINTSCR , VK_SNAPSHOT, 256+55, TRANAME("Print Screen")}, + { KID_SCROLLLOCK , VK_SCROLL, 70, TRANAME("Scroll Lock")}, + { KID_PAUSE , VK_PAUSE, 69, TRANAME("Pause")}, + +// numpad numbers + { KID_NUM0 , VK_NUMPAD0, 82, INTNAME("Num 0")}, + { KID_NUM1 , VK_NUMPAD1, 79, INTNAME("Num 1")}, + { KID_NUM2 , VK_NUMPAD2, 80, INTNAME("Num 2")}, + { KID_NUM3 , VK_NUMPAD3, 81, INTNAME("Num 3")}, + { KID_NUM4 , VK_NUMPAD4, 75, INTNAME("Num 4")}, + { KID_NUM5 , VK_NUMPAD5, 76, INTNAME("Num 5")}, + { KID_NUM6 , VK_NUMPAD6, 77, INTNAME("Num 6")}, + { KID_NUM7 , VK_NUMPAD7, 71, INTNAME("Num 7")}, + { KID_NUM8 , VK_NUMPAD8, 72, INTNAME("Num 8")}, + { KID_NUM9 , VK_NUMPAD9, 73, INTNAME("Num 9")}, + { KID_NUMDECIMAL , VK_DECIMAL, 83, INTNAME("Num .")}, + +// numpad gray keys + { KID_NUMLOCK , VK_NUMLOCK, 256+69, INTNAME("Num Lock")}, + { KID_NUMSLASH , VK_DIVIDE, 256+53, INTNAME("Num /")}, + { KID_NUMMULTIPLY , VK_MULTIPLY, 55, INTNAME("Num *")}, + { KID_NUMMINUS , VK_SUBTRACT, 74, INTNAME("Num -")}, + { KID_NUMPLUS , VK_ADD, 78, INTNAME("Num +")}, + { KID_NUMENTER , VK_SEPARATOR, 256+28, TRANAME("Num Enter")}, + +// mouse buttons + { KID_MOUSE1 , VK_LBUTTON, -1, TRANAME("Mouse Button 1")}, + { KID_MOUSE2 , VK_RBUTTON, -1, TRANAME("Mouse Button 2")}, + { KID_MOUSE3 , VK_MBUTTON, -1, TRANAME("Mouse Button 3")}, + { KID_MOUSE4 , -1, -1, TRANAME("Mouse Button 4")}, + { KID_MOUSE5 , -1, -1, TRANAME("Mouse Button 5")}, + { KID_MOUSEWHEELUP , -1, -1, TRANAME("Mouse Wheel Up")}, + { KID_MOUSEWHEELDOWN , -1, -1, TRANAME("Mouse Wheel Down")}, + +// 2nd mouse buttons + { KID_2MOUSE1 , -1, -1, TRANAME("2nd Mouse Button 1")}, + { KID_2MOUSE2 , -1, -1, TRANAME("2nd Mouse Button 2")}, + { KID_2MOUSE3 , -1, -1, TRANAME("2nd Mouse Button 3")}, +}; + + +// autogenerated fast conversion tables +static INDEX _aiScanToKid[512]; +static INDEX _aiVirtToKid[256]; + +// make fast conversion tables from the general table +static void MakeConversionTables(void) +{ + // clear conversion tables + memset(_aiScanToKid, -1, sizeof(_aiScanToKid)); + memset(_aiVirtToKid, -1, sizeof(_aiVirtToKid)); + + // for each Key + for (INDEX iKey=0; iKey=0) { + _aiScanToKid[iScan] = iKID; + } + if (iVirt>=0) { + _aiVirtToKid[iVirt] = iKID; + } + } +} + +// variables for message interception +static HHOOK _hGetMsgHook = NULL; +static HHOOK _hSendMsgHook = NULL; +static int _iMouseZ = 0; +static BOOL _bWheelUp = FALSE; +static BOOL _bWheelDn = FALSE; + +CTCriticalSection csInput; + +// which keys are pressed, as recorded by message interception (by KIDs) +static UBYTE _abKeysPressed[256]; + +// set a key according to a keydown/keyup message +static void SetKeyFromMsg(MSG *pMsg, BOOL bDown) +{ + INDEX iKID = -1; + // if capturing scan codes + if (inp_iKeyboardReadingMethod==2) { + // get scan code + INDEX iScan = (pMsg->lParam>>16)&0x1FF; // (we use the extended bit too!) + // convert scan code to kid + iKID = _aiScanToKid[iScan]; + // if capturing virtual key codes + } else if (inp_iKeyboardReadingMethod==1) { + // get virtualkey + INDEX iVirt = (pMsg->wParam)&0xFF; + + if (iVirt == VK_SHIFT) { + iVirt = VK_LSHIFT; + } + if (iVirt == VK_CONTROL) { + iVirt = VK_LCONTROL; + } + if (iVirt == VK_MENU) { + iVirt = VK_LMENU; + } + // convert virtualkey to kid + iKID = _aiVirtToKid[iVirt]; + // if not capturing + } else { + // do nothing + return; + } + if (iKID>=0 && iKIDinp_strButtonNames[iKID], bDown); + _abKeysPressed[iKID] = bDown; + } +} + +static void CheckMessage(MSG *pMsg) +{ + if ( pMsg->message == WM_LBUTTONUP) { + _abKeysPressed[KID_MOUSE1] = FALSE; + } else if ( pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_LBUTTONDBLCLK) { + _abKeysPressed[KID_MOUSE1] = TRUE; + } else if ( pMsg->message == WM_RBUTTONUP) { + _abKeysPressed[KID_MOUSE2] = FALSE; + } else if ( pMsg->message == WM_RBUTTONDOWN || pMsg->message == WM_RBUTTONDBLCLK) { + _abKeysPressed[KID_MOUSE2] = TRUE; + } else if ( pMsg->message == WM_MBUTTONUP) { + _abKeysPressed[KID_MOUSE3] = FALSE; + } else if ( pMsg->message == WM_MBUTTONDOWN || pMsg->message == WM_MBUTTONDBLCLK) { + _abKeysPressed[KID_MOUSE3] = TRUE; + + } else if ( pMsg->message == inp_iMButton4Dn) { + _abKeysPressed[KID_MOUSE4] = TRUE; + } else if ( pMsg->message == inp_iMButton4Up) { + _abKeysPressed[KID_MOUSE4] = FALSE; + + } else if ( pMsg->message == inp_iMButton5Dn) { + _abKeysPressed[KID_MOUSE5] = TRUE; + } else if ( pMsg->message == inp_iMButton5Up) { + _abKeysPressed[KID_MOUSE5] = FALSE; + + } else if (pMsg->message==WM_KEYUP || pMsg->message==WM_SYSKEYUP) { + SetKeyFromMsg(pMsg, FALSE); + } else if (pMsg->message==WM_KEYDOWN || pMsg->message==WM_SYSKEYDOWN) { + SetKeyFromMsg(pMsg, TRUE); + } else if (inp_bMsgDebugger && pMsg->message >= 0x10000) { + CPrintF("%08x(%d)\n", pMsg->message, pMsg->message); + } +} + + +// procedure called when message is retreived +LRESULT CALLBACK GetMsgProc( + int nCode, // hook code + WPARAM wParam, // message identifier + LPARAM lParam) // mouse coordinates +{ + MSG *pMsg = (MSG*)lParam; + CheckMessage(pMsg); + + LRESULT retValue = 0; + retValue = CallNextHookEx( _hGetMsgHook, nCode, wParam, lParam ); + +#ifndef WM_MOUSEWHEEL + #define WM_MOUSEWHEEL 0x020A +#endif + + if (wParam == PM_NOREMOVE) { + return retValue; + } + + if ( pMsg->message == WM_MOUSEWHEEL) { + _iMouseZ += SWORD(UWORD(HIWORD(pMsg->wParam))); + } + + return retValue; +} + + +// procedure called when message is sent +LRESULT CALLBACK SendMsgProc( + int nCode, // hook code + WPARAM wParam, // message identifier + LPARAM lParam) // mouse coordinates +{ + MSG *pMsg = (MSG*)lParam; + CheckMessage(pMsg); + + LRESULT retValue = 0; + retValue = CallNextHookEx( _hSendMsgHook, nCode, wParam, lParam ); + + return retValue; +} + + + +// --------- 2ND MOUSE HANDLING + +#define MOUSECOMBUFFERSIZE 256L +static HANDLE _h2ndMouse = NONE; +static BOOL _bIgnoreMouse2 = TRUE; +static INDEX _i2ndMouseX, _i2ndMouseY, _i2ndMouseButtons; +static INDEX _iByteNum = 0; +static UBYTE _aubComBytes[4] = {0,0,0,0}; +static INDEX _iLastPort = -1; + + + +static void Poll2ndMouse(void) +{ + // reset (mouse reading is relative) + _i2ndMouseX = 0; + _i2ndMouseY = 0; + if( _h2ndMouse==NONE) return; + + // check + COMSTAT csComStat; + DWORD dwErrorFlags; + ClearCommError( _h2ndMouse, &dwErrorFlags, &csComStat); + DWORD dwLength = Min( MOUSECOMBUFFERSIZE, (INDEX)csComStat.cbInQue); + if( dwLength<=0) return; + + // readout + UBYTE aubMouseBuffer[MOUSECOMBUFFERSIZE]; + INDEX iRetries = 999; + while( iRetries>0 && !ReadFile( _h2ndMouse, aubMouseBuffer, dwLength, &dwLength, NULL)) iRetries--; + if( iRetries<=0) return; // what, didn't make it? + + // parse the mouse packets + for( INDEX i=0; i>4; + } + // axes ? + else if( _iByteNum==3) { + char iDX = ((_aubComBytes[0] & 3) <<6) + _aubComBytes[1]; + char iDY = ((_aubComBytes[0] & 12) <<4) + _aubComBytes[2]; + _i2ndMouseX += iDX; + _i2ndMouseY += iDY; + } + // 3rd button? + else if( _iByteNum==4) { + _i2ndMouseButtons &= ~4; + if( aubMouseBuffer[i]&32) _i2ndMouseButtons |= 4; + } + } + + // ignore pooling? + if( _bIgnoreMouse2) { + if( _i2ndMouseX!=0 || _i2ndMouseY!=0) _bIgnoreMouse2 = FALSE; + _i2ndMouseX = 0; + _i2ndMouseY = 0; + _i2ndMouseButtons = 0; + return; + } +} + + +static void Startup2ndMouse(INDEX iPort) +{ + // skip if disabled + ASSERT( iPort>=0 && iPort<=4); + if( iPort==0) return; + // determine port string + CTString str2ndMousePort( 0, "COM%d", iPort); + + // create COM handle if needed + if( _h2ndMouse==NONE) { + _h2ndMouse = CreateFileA( str2ndMousePort, GENERIC_READ|GENERIC_WRITE, 0, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if( _h2ndMouse==INVALID_HANDLE_VALUE) { + // failed! :( + INDEX iError = GetLastError(); +/* + if( iError==5) CPrintF( "Cannot open %s (access denied).\n" + "The port is probably already used by another device (mouse, modem...)\n", + str2ndMousePort); + else CPrintF( "Cannot open %s (error %d).\n", str2ndMousePort, iError); + */ + _h2ndMouse = NONE; + return; + } + } + // setup and purge buffers + SetupComm( _h2ndMouse, MOUSECOMBUFFERSIZE, MOUSECOMBUFFERSIZE); + PurgeComm( _h2ndMouse, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); + + // setup port to 1200 7N1 + DCB dcb; + dcb.DCBlength = sizeof(DCB); + GetCommState( _h2ndMouse, &dcb); + dcb.BaudRate = CBR_1200; + dcb.ByteSize = 7; + dcb.Parity = NOPARITY; + dcb.StopBits = ONESTOPBIT; + dcb.fDtrControl = DTR_CONTROL_ENABLE; + dcb.fRtsControl = RTS_CONTROL_ENABLE; + dcb.fBinary = TRUE; + dcb.fParity = TRUE; + SetCommState( _h2ndMouse, &dcb); + + // reset + _iByteNum = 0; + _aubComBytes[0] = _aubComBytes[1] = _aubComBytes[2] = _aubComBytes[3] = 0; + _bIgnoreMouse2 = TRUE; // ignore mouse polling until 1 after non-0 readout + _iLastPort = iPort; + //CPrintF( "STARTUP M2!\n"); +} + + +static void Shutdown2ndMouse(void) +{ + // skip if already disabled + if( _h2ndMouse==NONE) return; + + // disable! + SetCommMask( _h2ndMouse, 0); + EscapeCommFunction( _h2ndMouse, CLRDTR); + EscapeCommFunction( _h2ndMouse, CLRRTS); + PurgeComm( _h2ndMouse, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); + // close port if changed + if( _iLastPort != inp_i2ndMousePort) { + CloseHandle( _h2ndMouse); + _h2ndMouse = NONE; + } // over and out + _bIgnoreMouse2 = TRUE; +} + + + + +// pointer to global input object +CInput *_pInput = NULL; + +// deafult constructor +CInput::CInput(void) +{ + // disable control scaning + inp_bInputEnabled = FALSE; + inp_bPollJoysticks = FALSE; + inp_bLastPrescan = FALSE; + // clear key buffer + for( INDEX iButton=0; iButtonvp_hWnd); +} + + +void CInput::EnableInput(HWND hwnd) +{ + // skip if already enabled + if( inp_bInputEnabled) return; + + // get window rectangle + RECT rectClient; + GetClientRect(hwnd, &rectClient); + POINT pt; + pt.x=0; + pt.y=0; + ClientToScreen(hwnd, &pt); + OffsetRect(&rectClient, pt.x, pt.y); + + // remember mouse pos + GetCursorPos( &inp_ptOldMousePos); + // set mouse clip region + ClipCursor(&rectClient); + // determine screen center position + inp_slScreenCenterX = (rectClient.left + rectClient.right) / 2; + inp_slScreenCenterY = (rectClient.top + rectClient.bottom) / 2; + + // clear mouse from screen + while (ShowCursor(FALSE) >= 0); + // save system mouse settings + SystemParametersInfo(SPI_GETMOUSE, 0, &inp_mscMouseSettings, 0); + // set new mouse speed + if (!inp_bAllowMouseAcceleration) { + MouseSpeedControl mscNewSetting = { 0, 0, 0}; + SystemParametersInfo(SPI_SETMOUSE, 0, &mscNewSetting, 0); + } + // set cursor position to screen center + SetCursorPos(inp_slScreenCenterX, inp_slScreenCenterY); + + _hGetMsgHook = SetWindowsHookEx(WH_GETMESSAGE, &GetMsgProc, NULL, GetCurrentThreadId()); + _hSendMsgHook = SetWindowsHookEx(WH_CALLWNDPROC, &SendMsgProc, NULL, GetCurrentThreadId()); + + // if required, try to enable 2nd mouse + Shutdown2ndMouse(); + inp_i2ndMousePort = Clamp( inp_i2ndMousePort, 0L, 4L); + Startup2ndMouse(inp_i2ndMousePort); + + // clear button's buffer + memset( _abKeysPressed, 0, sizeof( _abKeysPressed)); + + // This can be enabled to pre-read the state of currently pressed keys + // for snooping methods, since they only detect transitions. + // That has effect of detecting key presses for keys that were held down before + // enabling. + // the entire thing is disabled because it caused last menu key to re-apply in game. +#if 0 + // for each Key + {for (INDEX iKey=0; iKey=0) { + // transcribe if modifier + if (iVirt == VK_LSHIFT) { + iVirt = VK_SHIFT; + } + if (iVirt == VK_LCONTROL) { + iVirt = VK_CONTROL; + } + if (iVirt == VK_LMENU) { + iVirt = VK_MENU; + } + // is state is pressed + if (GetAsyncKeyState(iVirt)&0x8000) { + // mark it as pressed + _abKeysPressed[iKID] = 0xFF; + } + } + }} +#endif + + // remember current status + inp_bInputEnabled = TRUE; + inp_bPollJoysticks = FALSE; +} + + +/* + * Disable direct input + */ +void CInput::DisableInput( void) +{ + // skip if allready disabled + if( !inp_bInputEnabled) return; + + UnhookWindowsHookEx(_hGetMsgHook); + UnhookWindowsHookEx(_hSendMsgHook); + + // set mouse clip region to entire screen + ClipCursor(NULL); + // restore mouse pos + SetCursorPos( inp_ptOldMousePos.x, inp_ptOldMousePos.y); + + // show mouse on screen + while (ShowCursor(TRUE) < 0); + // set system mouse settings + SystemParametersInfo(SPI_SETMOUSE, 0, &inp_mscMouseSettings, 0); + + // eventually disable 2nd mouse + Shutdown2ndMouse(); + + // remember current status + inp_bInputEnabled = FALSE; + inp_bPollJoysticks = FALSE; +} + + +/* + * Scan states of all available input sources + */ +void CInput::GetInput(BOOL bPreScan) +{ +// CTSingleLock sl(&csInput, TRUE); + + if (!inp_bInputEnabled) { + return; + } + + if (bPreScan && !inp_bAllowPrescan) { + return; + } + + // if not pre-scanning + if (!bPreScan) { + // clear button's buffer + memset( inp_ubButtonsBuffer, 0, sizeof( inp_ubButtonsBuffer)); + + // for each Key + {for (INDEX iKey=0; iKey=0) { + // transcribe if modifier + if (iVirt == VK_LSHIFT) { + iVirt = VK_SHIFT; + } + if (iVirt == VK_LCONTROL) { + iVirt = VK_CONTROL; + } + if (iVirt == VK_LMENU) { + iVirt = VK_MENU; + } + // is state is pressed + if (GetAsyncKeyState(iVirt)&0x8000) { + // mark it as pressed + inp_ubButtonsBuffer[iKID] = 0xFF; + } + } + + // if snooping messages + } else { + // if snooped that key is pressed + if (_abKeysPressed[iKID]) { + // mark it as pressed + inp_ubButtonsBuffer[iKID] = 0xFF; + } + } + }} + } + + // read mouse position + POINT pntMouse; + if( GetCursorPos( &pntMouse)) + { + FLOAT fDX = FLOAT( SLONG(pntMouse.x) - inp_slScreenCenterX); + FLOAT fDY = FLOAT( SLONG(pntMouse.y) - inp_slScreenCenterY); + + FLOAT fSensitivity = inp_fMouseSensitivity; + if( inp_bAllowMouseAcceleration) fSensitivity *= 0.25f; + + FLOAT fD = Sqrt(fDX*fDX+fDY*fDY); + if (inp_bMousePrecision) { + static FLOAT _tmTime = 0.0f; + if( fDinp_fMousePrecisionTimeout) fSensitivity /= inp_fMousePrecisionFactor; + } + + static FLOAT fDXOld; + static FLOAT fDYOld; + static TIME tmOldDelta; + static CTimerValue tvBefore; + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + TIME tmNowDelta = (tvNow-tvBefore).GetSeconds(); + if (tmNowDelta<0.001f) { + tmNowDelta = 0.001f; + } + tvBefore = tvNow; + + FLOAT fDXSmooth = (fDXOld*tmOldDelta+fDX*tmNowDelta)/(tmOldDelta+tmNowDelta); + FLOAT fDYSmooth = (fDYOld*tmOldDelta+fDY*tmNowDelta)/(tmOldDelta+tmNowDelta); + fDXOld = fDX; + fDYOld = fDY; + tmOldDelta = tmNowDelta; + if (inp_bFilterMouse) { + fDX = fDXSmooth; + fDY = fDYSmooth; + } + + // get final mouse values + FLOAT fMouseRelX = +fDX*fSensitivity; + FLOAT fMouseRelY = -fDY*fSensitivity; + if (inp_bInvertMouse) { + fMouseRelY = -fMouseRelY; + } + FLOAT fMouseRelZ = _iMouseZ; + + // just interpret values as normal + inp_caiAllAxisInfo[1].cai_fReading = fMouseRelX; + inp_caiAllAxisInfo[2].cai_fReading = fMouseRelY; + inp_caiAllAxisInfo[3].cai_fReading = fMouseRelZ; + + // if not pre-scanning + if (!bPreScan) { + // detect wheel up/down movement + _bWheelDn = FALSE; + if (_iMouseZ>0) { + if (_bWheelUp) { + inp_ubButtonsBuffer[KID_MOUSEWHEELUP] = 0x00; + } else { + inp_ubButtonsBuffer[KID_MOUSEWHEELUP] = 0xFF; + _iMouseZ = ClampDn(_iMouseZ-120, 0); + } + } + _bWheelUp = inp_ubButtonsBuffer[KID_MOUSEWHEELUP]; + if (_iMouseZ<0) { + if (_bWheelDn) { + inp_ubButtonsBuffer[KID_MOUSEWHEELDOWN] = 0x00; + } else { + inp_ubButtonsBuffer[KID_MOUSEWHEELDOWN] = 0xFF; + _iMouseZ = ClampUp(_iMouseZ+120, 0); + } + } + _bWheelDn = inp_ubButtonsBuffer[KID_MOUSEWHEELDOWN]; + } + } + inp_bLastPrescan = bPreScan; + + // set cursor position to screen center + if (pntMouse.x!=inp_slScreenCenterX || pntMouse.y!=inp_slScreenCenterY) { + SetCursorPos(inp_slScreenCenterX, inp_slScreenCenterY); + } + + // readout 2nd mouse if enabled + if( _h2ndMouse!=NONE) + { + Poll2ndMouse(); + //CPrintF( "m2X: %4d, m2Y: %4d, m2B: 0x%02X\n", _i2ndMouseX, _i2ndMouseY, _i2ndMouseButtons); + + // handle 2nd mouse buttons + if( _i2ndMouseButtons & 2) inp_ubButtonsBuffer[KID_2MOUSE1] = 0xFF; + if( _i2ndMouseButtons & 1) inp_ubButtonsBuffer[KID_2MOUSE2] = 0xFF; + if( _i2ndMouseButtons & 4) inp_ubButtonsBuffer[KID_2MOUSE3] = 0xFF; + + // handle 2nd mouse movement + FLOAT fDX = _i2ndMouseX; + FLOAT fDY = _i2ndMouseY; + FLOAT fSensitivity = inp_f2ndMouseSensitivity; + + FLOAT fD = Sqrt(fDX*fDX+fDY*fDY); + if( inp_b2ndMousePrecision) { + static FLOAT _tm2Time = 0.0f; + if( fDinp_f2ndMousePrecisionTimeout) fSensitivity /= inp_f2ndMousePrecisionFactor; + } + + static FLOAT f2DXOld; + static FLOAT f2DYOld; + static TIME tm2OldDelta; + static CTimerValue tv2Before; + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + TIME tmNowDelta = (tvNow-tv2Before).GetSeconds(); + if( tmNowDelta<0.001f) tmNowDelta = 0.001f; + tv2Before = tvNow; + + FLOAT fDXSmooth = (f2DXOld*tm2OldDelta+fDX*tmNowDelta) / (tm2OldDelta+tmNowDelta); + FLOAT fDYSmooth = (f2DYOld*tm2OldDelta+fDY*tmNowDelta) / (tm2OldDelta+tmNowDelta); + f2DXOld = fDX; + f2DYOld = fDY; + tm2OldDelta = tmNowDelta; + if( inp_bFilter2ndMouse) { + fDX = fDXSmooth; + fDY = fDYSmooth; + } + + // get final mouse values + FLOAT fMouseRelX = +fDX*fSensitivity; + FLOAT fMouseRelY = -fDY*fSensitivity; + if( inp_bInvert2ndMouse) fMouseRelY = -fMouseRelY; + + // just interpret values as normal + inp_caiAllAxisInfo[4].cai_fReading = fMouseRelX; + inp_caiAllAxisInfo[5].cai_fReading = fMouseRelY; + } + + + // if joystick polling is enabled + if (inp_bPollJoysticks || inp_bForceJoystickPolling) { + // scan all available joysticks + for( INDEX iJoy=0; iJoy + +// number of key ids reserved (in KeyNames.h) +#define KID_TOTALCOUNT 256 + +// defines for offsets of empty axis ("NONE" key) and mouse axis +#define AXIS_NONE 0 +#define MOUSE_X_AXIS 1 +#define MOUSE_Y_AXIS 2 + +#define MAX_JOYSTICKS 8 +#define MAX_AXES_PER_JOYSTICK 6 // (XYZRUV) +#define FIRST_JOYAXIS (1+3+2) // one dummy, 3 axis for windows mouse (3rd is scroller), 2 axis for serial mouse +#define MAX_OVERALL_AXES (FIRST_JOYAXIS+MAX_JOYSTICKS*MAX_AXES_PER_JOYSTICK) +#define MAX_BUTTONS_PER_JOYSTICK (32+4) // 32 buttons and 4 POV directions +#define FIRST_JOYBUTTON (KID_TOTALCOUNT) +#define MAX_OVERALL_BUTTONS (KID_TOTALCOUNT+MAX_JOYSTICKS*MAX_BUTTONS_PER_JOYSTICK) + + +/* + * Mouse speed control structure + */ +struct MouseSpeedControl +{ + int msc_iThresholdX; + int msc_iThresholdY; + int msc_iSpeed; +}; + +/* + * One axis descriptive information + */ +struct ENGINE_API ControlAxisInfo +{ + CTString cai_strAxisName; // name of this axis + FLOAT cai_fReading; // current reading of this axis + BOOL cai_bExisting; // set if the axis exists (for joystick axes) + SLONG cai_slMax; // max/min info for joysticks + SLONG cai_slMin; +}; + +/* + * Class responsible for dealing with DirectInput + */ +class ENGINE_API CInput { +public: +// Attributes + + BOOL inp_bLastPrescan; + BOOL inp_bInputEnabled; + BOOL inp_bPollJoysticks; + struct ControlAxisInfo inp_caiAllAxisInfo[ MAX_OVERALL_AXES];// info for all available axis + CTString inp_strButtonNames[ MAX_OVERALL_BUTTONS];// individual button names + CTString inp_strButtonNamesTra[ MAX_OVERALL_BUTTONS];// individual button names (translated) + UBYTE inp_ubButtonsBuffer[ MAX_OVERALL_BUTTONS]; // statuses for all buttons (KEY & 128 !=0) + BOOL inp_abJoystickOn[MAX_JOYSTICKS]; // set if a joystick is valid for reading + BOOL inp_abJoystickHasPOV[MAX_JOYSTICKS]; // set if a joystick has a POV hat + + SLONG inp_slScreenCenterX; // screen center X in pixels + SLONG inp_slScreenCenterY; // screen center Y in pixels + RECT inp_rectOldClip; // old cursor clip rectangle in pixels + POINT inp_ptOldMousePos; // old mouse position + struct MouseSpeedControl inp_mscMouseSettings; // system mouse settings + + void SetKeyNames( void); // sets name for every key + // check if a joystick exists + BOOL CheckJoystick(INDEX iJoy); + // adds axis and buttons for given joystick + void AddJoystickAbbilities(INDEX iJoy); + BOOL ScanJoystick(INDEX iJoyNo, BOOL bPreScan);// scans axis and buttons for given joystick +public: +// Operations + CInput(); + ~CInput(); + // Initializes all available devices and enumerates available controls + void Initialize(void); + // Enable input inside one viewport, or window + void EnableInput(CViewPort *pvp); + void EnableInput(HWND hWnd); + // Disable input + void DisableInput(void); + // enable/disable joystick polling (it can be slow to poll if user doesn't realy use the joystick) + void SetJoyPolling(BOOL bPoll); + // Test input activity + BOOL IsInputEnabled( void) const { return inp_bInputEnabled; }; + // Scan states of all available input sources + void GetInput(BOOL bPreScan); + // Clear all input states (keys become not pressed, axes are reset to zero) + void ClearInput( void); + // Get count of available axis + inline const INDEX GetAvailableAxisCount( void) const { + return MAX_OVERALL_AXES;}; + // Get count of available buttons + inline const INDEX GetAvailableButtonsCount( void) const { + return MAX_OVERALL_BUTTONS;}; + // Get name of given axis + inline const CTString &GetAxisName( INDEX iAxisNo) const { + return inp_caiAllAxisInfo[ iAxisNo].cai_strAxisName;}; + const CTString &GetAxisTransName( INDEX iAxisNo) const; + // Get current position of given axis + inline float GetAxisValue( INDEX iAxisNo) const { + return inp_caiAllAxisInfo[ iAxisNo].cai_fReading;}; + // Get given button's name + inline const CTString &GetButtonName( INDEX iButtonNo) const { + return inp_strButtonNames[ iButtonNo];}; + // Get given button's name translated + inline const CTString &GetButtonTransName( INDEX iButtonNo) const { + return inp_strButtonNamesTra[ iButtonNo];}; + // Get given button's current state + inline BOOL GetButtonState( INDEX iButtonNo) const { + return (inp_ubButtonsBuffer[ iButtonNo] & 128) != 0;}; +}; + +// pointer to global input object +ENGINE_API extern CInput *_pInput; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/KeyNames.h b/Sources/Engine/Base/KeyNames.h new file mode 100644 index 0000000..1423e6e --- /dev/null +++ b/Sources/Engine/Base/KeyNames.h @@ -0,0 +1,224 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_KEYNAMES_H +#define SE_INCL_KEYNAMES_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// key defines for all keys + +// reserved for 'no-key-pressed' +#define KID_NONE 0x00 + +// numbers row +#define KID_1 0x11 +#define KID_2 0x12 +#define KID_3 0x13 +#define KID_4 0x14 +#define KID_5 0x15 +#define KID_6 0x16 +#define KID_7 0x17 +#define KID_8 0x18 +#define KID_9 0x19 +#define KID_0 0x1A +#define KID_MINUS 0x1B +#define KID_EQUALS 0x1C + +// 1st alpha row +#define KID_Q 0x20 +#define KID_W 0x21 +#define KID_E 0x22 +#define KID_R 0x23 +#define KID_T 0x24 +#define KID_Y 0x25 +#define KID_U 0x26 +#define KID_I 0x27 +#define KID_O 0x28 +#define KID_P 0x29 +#define KID_LBRACKET 0x2A +#define KID_RBRACKET 0x2B +#define KID_BACKSLASH 0x2C + +// 2nd alpha row +#define KID_A 0x30 +#define KID_S 0x31 +#define KID_D 0x32 +#define KID_F 0x33 +#define KID_G 0x34 +#define KID_H 0x35 +#define KID_J 0x36 +#define KID_K 0x37 +#define KID_L 0x38 +#define KID_SEMICOLON 0x39 +#define KID_APOSTROPHE 0x3A + +// 3rd alpha row +#define KID_Z 0x40 +#define KID_X 0x41 +#define KID_C 0x42 +#define KID_V 0x43 +#define KID_B 0x44 +#define KID_N 0x45 +#define KID_M 0x46 +#define KID_COMMA 0x47 +#define KID_PERIOD 0x48 +#define KID_SLASH 0x49 + +// row with F-keys +#define KID_F1 0x51 +#define KID_F2 0x52 +#define KID_F3 0x53 +#define KID_F4 0x54 +#define KID_F5 0x55 +#define KID_F6 0x56 +#define KID_F7 0x57 +#define KID_F8 0x58 +#define KID_F9 0x59 +#define KID_F10 0x5A +#define KID_F11 0x5B +#define KID_F12 0x5C + +// extra keys +#define KID_ESCAPE 0x60 +#define KID_TILDE 0x61 +#define KID_BACKSPACE 0x62 +#define KID_TAB 0x63 +#define KID_CAPSLOCK 0x64 +#define KID_ENTER 0x65 +#define KID_SPACE 0x66 + +// modifier keys +#define KID_LSHIFT 0x70 +#define KID_RSHIFT 0x71 +#define KID_LCONTROL 0x72 +#define KID_RCONTROL 0x73 +#define KID_LALT 0x74 +#define KID_RALT 0x75 + +// navigation keys +#define KID_ARROWUP 0x80 +#define KID_ARROWDOWN 0x81 +#define KID_ARROWLEFT 0x82 +#define KID_ARROWRIGHT 0x83 +#define KID_INSERT 0x84 +#define KID_DELETE 0x85 +#define KID_HOME 0x86 +#define KID_END 0x87 +#define KID_PAGEUP 0x88 +#define KID_PAGEDOWN 0x89 +#define KID_PRINTSCR 0x8A +#define KID_SCROLLLOCK 0x8B +#define KID_PAUSE 0x8C + +// numpad numbers +#define KID_NUM0 0x90 +#define KID_NUM1 0x91 +#define KID_NUM2 0x92 +#define KID_NUM3 0x93 +#define KID_NUM4 0x94 +#define KID_NUM5 0x95 +#define KID_NUM6 0x96 +#define KID_NUM7 0x97 +#define KID_NUM8 0x98 +#define KID_NUM9 0x99 +#define KID_NUMDECIMAL 0x9A + +// numpad gray keys +#define KID_NUMLOCK 0xA0 +#define KID_NUMSLASH 0xA1 +#define KID_NUMMULTIPLY 0xA2 +#define KID_NUMMINUS 0xA3 +#define KID_NUMPLUS 0xA4 +#define KID_NUMENTER 0xA5 + +// mouse buttons +#define KID_MOUSE1 0xC0 +#define KID_MOUSE2 0xC1 +#define KID_MOUSE3 0xC2 +#define KID_MOUSE4 0xC3 +#define KID_MOUSE5 0xC4 +#define KID_MOUSEWHEELUP 0xC5 +#define KID_MOUSEWHEELDOWN 0xC6 + +// 2nd mouse buttons +#define KID_2MOUSE1 0xD0 +#define KID_2MOUSE2 0xD1 +#define KID_2MOUSE3 0xD2 + +// Mouse device controls +#define CID_MOUSE_AXIS_XP 0 +#define CID_MOUSE_AXIS_XN 1 +#define CID_MOUSE_AXIS_YP 2 +#define CID_MOUSE_AXIS_YN 3 +#define CID_MOUSE_WHEEL_UP 4 +#define CID_MOUSE_WHEEL_DOWN 5 +#define CID_MOUSE_BUTTON1 6 +#define CID_MOUSE_BUTTON2 7 +#define CID_MOUSE_BUTTON3 8 +#define CID_MOUSE_BUTTON4 9 +#define CID_MOUSE_BUTTON5 10 + +// Second mouse device controls +#define CID_MOUSE2_AXIS_XP 0 +#define CID_MOUSE2_AXIS_XN 1 +#define CID_MOUSE2_AXIS_YP 2 +#define CID_MOUSE2_AXIS_YN 3 +#define CID_MOUSE2_BUTTON1 4 +#define CID_MOUSE2_BUTTON2 5 +#define CID_MOUSE2_BUTTON3 6 + +// Joystick controls +#define CID_JOY_AXIS_XP 0 +#define CID_JOY_AXIS_XN 1 +#define CID_JOY_AXIS_YP 2 +#define CID_JOY_AXIS_YN 3 +#define CID_JOY_AXIS_ZP 4 +#define CID_JOY_AXIS_ZN 5 +#define CID_JOY_AXIS_RP 6 +#define CID_JOY_AXIS_RN 7 +#define CID_JOY_AXIS_UP 8 +#define CID_JOY_AXIS_UN 9 +#define CID_JOY_AXIS_VP 10 +#define CID_JOY_AXIS_VN 11 + +#define CID_JOY_BUTTON1 12 +#define CID_JOY_BUTTON2 13 +#define CID_JOY_BUTTON3 14 +#define CID_JOY_BUTTON4 15 +#define CID_JOY_BUTTON5 16 +#define CID_JOY_BUTTON6 17 +#define CID_JOY_BUTTON7 18 +#define CID_JOY_BUTTON8 19 +#define CID_JOY_BUTTON9 20 +#define CID_JOY_BUTTON10 21 +#define CID_JOY_BUTTON11 22 +#define CID_JOY_BUTTON12 23 +#define CID_JOY_BUTTON13 24 +#define CID_JOY_BUTTON14 25 +#define CID_JOY_BUTTON15 26 +#define CID_JOY_BUTTON16 27 +#define CID_JOY_BUTTON17 28 +#define CID_JOY_BUTTON18 29 +#define CID_JOY_BUTTON19 30 +#define CID_JOY_BUTTON20 31 +#define CID_JOY_BUTTON21 32 +#define CID_JOY_BUTTON22 33 +#define CID_JOY_BUTTON23 34 +#define CID_JOY_BUTTON24 35 +#define CID_JOY_BUTTON25 36 +#define CID_JOY_BUTTON26 37 +#define CID_JOY_BUTTON27 38 +#define CID_JOY_BUTTON28 39 +#define CID_JOY_BUTTON29 40 +#define CID_JOY_BUTTON30 41 +#define CID_JOY_BUTTON31 42 +#define CID_JOY_BUTTON32 43 + +#define CID_JOY_POV_N 44 +#define CID_JOY_POV_E 45 +#define CID_JOY_POV_S 46 +#define CID_JOY_POV_W 47 + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/ListIterator.inl b/Sources/Engine/Base/ListIterator.inl new file mode 100644 index 0000000..c750ab6 --- /dev/null +++ b/Sources/Engine/Base/ListIterator.inl @@ -0,0 +1,99 @@ + +#ifndef SE_INCL_LISTITERATOR_INL +#define SE_INCL_LISTITERATOR_INL +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* simple list iterator: 4 bytes structure, all functions are inline */ +template +class CListIter { +private: + CListNode *li_CurrentNode; +public: + /* default constructor - no list attached */ + CListIter(void) { + li_CurrentNode = NULL; + }; + /* constructor with list attaching */ + CListIter(const CListHead &lhHead) { + li_CurrentNode = &lhHead.IterationHead(); + }; + /* constructor to start from given node */ + CListIter(CListNode &lnNode) { + ASSERT(lnNode.IsLinked()); + li_CurrentNode = &lnNode; + }; + /* start iterating */ + void Reset(const CListHead &lhHead) { + li_CurrentNode = &lhHead.IterationHead(); + }; + /* move to next node */ + void MoveToNext(void) { + li_CurrentNode = &li_CurrentNode->IterationSucc(); + }; + /* move to previous node */ + void MoveToPrev(void) { + li_CurrentNode = &li_CurrentNode->IterationPred(); + }; + /* check if finished */ + BOOL IsPastEnd(void) { + return li_CurrentNode->IsTailMarker(); + }; + /* Insert a node after current one. */ + inline void InsertAfterCurrent(CListNode &lnNew) { + li_CurrentNode->IterationInsertAfter(lnNew); + }; + /* Insert a node before current one. */ + inline void InsertBeforeCurrent(CListNode &lnNew) { + li_CurrentNode->IterationInsertBefore(lnNew); + }; + + /* Get current element. */ + Cbase &Current(void) { return *((Cbase*)((UBYTE *)li_CurrentNode - iOffset)); } + Cbase &operator*(void) { return *((Cbase*)((UBYTE *)li_CurrentNode - iOffset)); } + operator Cbase *(void) { return ((Cbase*)((UBYTE *)li_CurrentNode - iOffset)); } + Cbase *operator->(void) { return ((Cbase*)((UBYTE *)li_CurrentNode - iOffset)); } +}; + +// taken from stddef.h +//#ifndef offsetof +//#define offsetof(s,m) (size_t)&(((s *)0)->m) +//#endif + +// declare a list iterator for a class with a CListNode member +#define LISTITER(baseclass, member) CListIter + +// make 'for' construct for walking a list +#define FOREACHINLIST(baseclass, member, head, iter) \ + for ( LISTITER(baseclass, member) iter(head); !iter.IsPastEnd(); iter.MoveToNext() ) + +// make 'for' construct for walking a list, keeping the iterator for later use +#define FOREACHINLISTKEEP(baseclass, member, head, iter) \ + LISTITER(baseclass, member) iter(head); \ + for (; !iter.IsPastEnd(); iter.MoveToNext() ) + +// make 'for' construct for deleting a list +#define FORDELETELIST(baseclass, member, head, iter) \ + for ( LISTITER(baseclass, member) iter(head), iter##next; \ + iter##next=iter, iter##next.IsPastEnd() || (iter##next.MoveToNext(),1), !iter.IsPastEnd(); \ + iter = iter##next) + +// get the pointer to the first element in the list +#define LIST_HEAD(listhead, baseclass, member) \ + ( (baseclass *) ( ((UBYTE *)(&(listhead).Head())) - offsetof(baseclass, member) ) ) +// get the pointer to the last element in the list +#define LIST_TAIL(listhead, baseclass, member) \ + ( (baseclass *) ( ((UBYTE *)(&(listhead).Tail())) - offsetof(baseclass, member) ) ) + +// get the pointer to the predecessor of the element +#define LIST_PRED(element, baseclass, member) \ + ( (baseclass *) ( ((UBYTE *)(&(element).member.Pred())) - offsetof(baseclass, member) ) ) +// get the pointer to the successor of the element +#define LIST_SUCC(element, baseclass, member) \ + ( (baseclass *) ( ((UBYTE *)(&(element).member.Succ())) - offsetof(baseclass, member) ) ) + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Lists.cpp b/Sources/Engine/Base/Lists.cpp new file mode 100644 index 0000000..6061051 --- /dev/null +++ b/Sources/Engine/Base/Lists.cpp @@ -0,0 +1,277 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include + +///////////////////////////////////////////////////////////////////// +// CListHead implementation + +/* + * Initialize a list head. + */ +void CListHead::Clear(void) +{ + ASSERT(this!=NULL); + lh_Head = (CListNode *) &(lh_NULL); + lh_NULL = (CListNode *) NULL; + lh_Tail = (CListNode *) &(lh_Head); +} + +/* + * Check if list head is valid. + */ +BOOL CListHead::IsValid(void) const +{ + ASSERT(this!=NULL); + ASSERT(lh_NULL == NULL); + ASSERT((lh_Head == (CListNode *) &lh_NULL) && (lh_Tail == (CListNode *) &lh_Head) + || lh_Tail->IsValid() && lh_Head->IsValid() ); + return TRUE; +} + +/* + * Check if list is empty. + */ +BOOL CListHead::IsEmpty(void) const +{ + ASSERT(IsValid()); + return( lh_Head == (CListNode *) &lh_NULL ); +} + +/* + * Add a node to head of list. + */ +void CListHead::AddHead(CListNode &element) +{ + ASSERT(IsValid()&& !element.IsLinked()); + + CListNode &first = *lh_Head; + + lh_Head = &element; + element.ln_Succ = &first; + element.ln_Pred = first.ln_Pred; + first.ln_Pred = &element; +} + +/* + * Add a node to tail of list. + */ +void CListHead::AddTail(CListNode &element) +{ + ASSERT(IsValid()&& !element.IsLinked()); + CListNode &last = *lh_Tail; + + lh_Tail = &element; + element.ln_Succ = last.ln_Succ; + element.ln_Pred = &last; + last.ln_Succ = &element; +} + +/* + * Remove a node from head of list. + */ +void CListHead::RemHead(void) +{ + ASSERT(!IsEmpty()); + lh_Head->Remove(); +} + +/* + * Remove a node from tail of list. + */ +void CListHead::RemTail(void) +{ + ASSERT(!IsEmpty()); + lh_Tail->Remove(); +} + +/* Remove all elements from list. */ +void CListHead::RemAll(void) +{ + // for each element + for ( CListIter iter(*this), iternext; + iternext=iter, iternext.IsPastEnd() || (iternext.MoveToNext(),1), !iter.IsPastEnd(); + iter = iternext) { + // remove it + iter->Remove(); + } +} + +/* + * Move all elements of another list into this one. + */ +void CListHead::MoveList(CListHead &lhOther) +{ + ASSERT(IsValid() && lhOther.IsValid()); + + // if the second list is empty + if (lhOther.IsEmpty()) { + // no moving + return; + } + + // get first element in other list + CListNode &lnOtherFirst = *lhOther.lh_Head; + // get last element in other list + CListNode &lnOtherLast = *lhOther.lh_Tail; + + // get last element in this list + CListNode &lnThisLast = *lh_Tail; + + // relink elements + lnOtherLast.ln_Succ = lnThisLast.ln_Succ; + lnThisLast.ln_Succ = &lnOtherFirst; + lnOtherFirst.ln_Pred = &lnThisLast; + lh_Tail = &lnOtherLast; + + // clear the other list + lhOther.Clear(); +} + +/* + * Return the number of elements in list. + */ +INDEX CListHead::Count(void) const +{ + INDEX slCount = 0; + // walk the list -- modification of FOREACHINLIST that works with base CListNode class + for ( CListIter iter(*this); !iter.IsPastEnd(); iter.MoveToNext() ) { + slCount++; + } + return slCount; +} + + /* Sort the list. */ +void CListHead::Sort(int (*pCompare)(const void *p0, const void *p1), int iNodeOffset) +{ + // get number of elements + INDEX ctCount = Count(); + // if none + if (ctCount==0) { + // do not sort + } + + // create array of that much integers (the array will hold pointers to the list) + ULONG *aulPointers = new ULONG[ctCount]; + // fill it + INDEX i=0; + for ( CListIter iter(*this); !iter.IsPastEnd(); iter.MoveToNext() ) { + aulPointers[i] = ((ULONG)&*iter)-iNodeOffset; + i++; + } + + // sort it + qsort(aulPointers, ctCount, sizeof(SLONG), pCompare); + + // make temporary list + CListHead lhTmp; + // for each pointer + {for(INDEX i=0; iRemove(); + // add it to the end of new list + lhTmp.AddTail(*pln); + }} + + // free the pointer array + delete[] aulPointers; + + // move the sorted list here + MoveList(lhTmp); +} + +///////////////////////////////////////////////////////////////////// +// CListNode implementation + +/* + * Check if list node is valid. + */ +BOOL CListNode::IsValid(void) const +{ + ASSERT(this!=NULL); + ASSERT((ln_Pred==NULL && ln_Succ==NULL) || (ln_Pred!=NULL && ln_Succ!=NULL)); + // it is valid if it is cleared or if it is linked + return (ln_Pred==NULL && ln_Succ==NULL) + || (ln_Pred->ln_Succ == this) && (ln_Succ->ln_Pred == this); +} + +/* + * Check is linked in some list. + */ +BOOL CListNode::IsLinked(void) const +{ + ASSERT(IsValid()); + return ln_Pred != NULL; +} + +/* + * Remove a node from list. + */ +void CListNode::Remove(void) +{ + ASSERT(IsLinked()); + CListNode &next = *ln_Succ; + CListNode &prev = *ln_Pred; + ASSERT(next.IsTailMarker() || next.IsLinked()); + ASSERT(prev.IsHeadMarker() || prev.IsLinked()); + + next.ln_Pred = &prev; + prev.ln_Succ = &next; + // make a non-linked node + ln_Succ = NULL; + ln_Pred = NULL; +} + +/* + * Add a node after this node. + */ +void CListNode::AddAfter(CListNode &lnToAdd) +{ + ASSERT(IsLinked() && !lnToAdd.IsLinked()); + + CListNode &succ = IterationSucc(); + CListNode &pred = *this; + + succ.ln_Pred = &lnToAdd; + pred.ln_Succ = &lnToAdd; + lnToAdd.ln_Succ = ≻ + lnToAdd.ln_Pred = &pred; +} + +/* + * Add a node before this node. + */ +void CListNode::AddBefore(CListNode &lnToAdd) +{ + ASSERT(IsLinked() && !lnToAdd.IsLinked()); + + CListNode &succ = *this; + CListNode &pred = IterationPred(); + + succ.ln_Pred = &lnToAdd; + pred.ln_Succ = &lnToAdd; + lnToAdd.ln_Succ = ≻ + lnToAdd.ln_Pred = &pred; +} + +/* + * Find the head of the list that this node is in. + */ +CListHead &CListNode::GetHead(void) +{ + // start at this node + CListNode *pln = this; + // while current node is not pointer to list.lh_Head + while(pln->ln_Pred != NULL) { + // go backwards + pln = pln->ln_Pred; + } + // return the head pointer + return *(CListHead*)pln; +} diff --git a/Sources/Engine/Base/Lists.h b/Sources/Engine/Base/Lists.h new file mode 100644 index 0000000..a816c99 --- /dev/null +++ b/Sources/Engine/Base/Lists.h @@ -0,0 +1,118 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +#ifndef SE_INCL_LISTS_H +#define SE_INCL_LISTS_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* structures for doubly linked lists */ +/* list node */ +class ENGINE_API CListNode { +//implementation: +public: + CListNode *ln_Succ; /* pointer to previous node (successor) */ + CListNode *ln_Pred; /* pointer to next node (predecessor) */ + + /* Check if list node is valid. */ + BOOL IsValid(void) const; +//interface: +public: + /* Default constructor */ + inline CListNode(void); + /* Copy constructor */ + inline CListNode(const CListNode &lnOriginal); + /* Destructor */ + inline ~CListNode(void); + /* Assignment. */ + inline CListNode &operator=(const CListNode &lnOriginal); + /* Check that this list node is linked in some list. */ + BOOL IsLinked(void) const; + /* Add a node after this node. */ + void AddAfter(CListNode &node); + /* Add a node before this node. */ + void AddBefore(CListNode &node); + /* Remove this node from list. */ + void Remove(void); + /* Check if this list node is head marker of list. */ + inline BOOL IsHeadMarker(void) const; + /* Check if this list node is tail marker of list. */ + inline BOOL IsTailMarker(void) const; + /* Check if this list node is at the head of list. */ + inline BOOL IsHead(void) const; + /* Check if this list node is at the tail of list. */ + inline BOOL IsTail(void) const; + /* Get successor of this node. */ + inline CListNode &Succ(void) const; + /* Get predeccessor of this node. */ + inline CListNode &Pred(void) const; + + /* Get successor of this node for iteration. */ + inline CListNode &IterationSucc(void) const; + /* Get predecessor of this node for iteration. */ + inline CListNode &IterationPred(void) const; + /* Insert a node before current one during iteration. */ + inline void IterationInsertBefore(CListNode &lnNew); + /* Insert a node after current one during iteration. */ + inline void IterationInsertAfter(CListNode &lnNew); + + /* Find the head of the list that this node is in. */ + CListHead &GetHead(void); +}; +/* list head */ +class ENGINE_API CListHead { +//implementation: +public: + CListNode *lh_Head; /* pointer to first node (head) */ + CListNode *lh_NULL; /* lh_HeadPred and lh_TailSucc at the same time */ + CListNode *lh_Tail; /* pointer to last node (tail) */ + + /* Check if this list head is valid. */ + BOOL IsValid(void) const; + /* Clear the list head. */ + void Clear(); +//interface: +public: + /* Default constructor. */ + inline CListHead() { Clear(); }; + /* Copy constructor. */ + inline CListHead(const CListHead &lh) {ASSERTALWAYS("Don't copy list heads!");}; + /* Assignment. */ + inline void operator=(const CListHead &lh) {ASSERTALWAYS("Don't copy list heads!");}; + /* Get list head. */ + inline CListNode &Head(void) const; + /* Get list tail. */ + inline CListNode &Tail(void) const; + /* Get list head for iteration. */ + inline CListNode &IterationHead(void) const; + /* Get list tail for iteration. */ + inline CListNode &IterationTail(void) const; + /* Add a new element to head of list. */ + void AddHead(CListNode &node); + /* Add a new element to tail of list. */ + void AddTail(CListNode &node); + /* Remove first element from list. */ + void RemHead(void); + /* Remove last element from list. */ + void RemTail(void); + /* Remove all elements from list. */ + void RemAll(void); + /* Test if list is empty. */ + BOOL IsEmpty(void) const; + /* Move all elements of another list into this one. */ + void MoveList(CListHead &lhOther); + /* Return the number of elements in list. */ + INDEX Count(void) const; + /* Sort the list. */ + void Sort(int (*pCompare)(const void *p0, const void *p1), int iNodeOffset); +}; + +#include + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Lists.inl b/Sources/Engine/Base/Lists.inl new file mode 100644 index 0000000..88d37aa --- /dev/null +++ b/Sources/Engine/Base/Lists.inl @@ -0,0 +1,163 @@ +#ifndef SE_INCL_LISTS_INL +#define SE_INCL_LISTS_INL +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* Default constructor */ +inline CListNode::CListNode(void) +{ + // make a non-linked node + ln_Succ = NULL; + ln_Pred = NULL; +} +/* Copy constructor */ +inline CListNode::CListNode(const CListNode &lnOriginal) +{ + (void) lnOriginal; + // make a non-linked node + ln_Succ = NULL; + ln_Pred = NULL; +} +/* Destructor */ +inline CListNode::~CListNode(void) +{ + // if node is linked + if (IsLinked()) { + // remove it from list + Remove(); + } +} +/* Assignment. */ +inline CListNode &CListNode::operator=(const CListNode &lnOriginal) +{ + (void) lnOriginal; + // make a non-linked node + ln_Succ = NULL; + ln_Pred = NULL; + return *this; +} +/* Get successor of this node. */ +inline CListNode &CListNode::Succ(void) const +{ + ASSERT(IsLinked() && ln_Succ->IsLinked()); + return *ln_Succ; +} +/* Get predeccessor of this node. */ +inline CListNode &CListNode::Pred(void) const +{ + ASSERT(IsLinked() && ln_Pred->IsLinked()); + return *ln_Pred; +} +/* Get successor of this node for iteration. */ +inline CListNode &CListNode::IterationSucc(void) const +{ + ASSERT(ln_Succ->IsTailMarker() || ln_Succ->IsLinked()); + return *ln_Succ; +} +/* Get predecessor of this node for iteration. */ +inline CListNode &CListNode::IterationPred(void) const +{ + ASSERT(ln_Pred->IsHeadMarker() || ln_Pred->IsLinked()); + return *ln_Pred; +} +/* Insert a node after current one during iteration. */ +inline void CListNode::IterationInsertAfter(CListNode &lnNew) +{ + ASSERT(!lnNew.IsLinked()); + ASSERT(ln_Succ->IsTailMarker() || ln_Succ->IsLinked()); + ln_Succ->ln_Pred = &lnNew; + lnNew.ln_Succ = ln_Succ; + lnNew.ln_Pred = this; + ln_Succ = &lnNew; +} +/* Insert a node before current one during iteration. */ +inline void CListNode::IterationInsertBefore(CListNode &lnNew) +{ + ASSERT(!lnNew.IsLinked()); + ASSERT(ln_Pred->IsHeadMarker() || ln_Pred->IsLinked()); + ln_Pred->ln_Succ = &lnNew; + lnNew.ln_Pred = ln_Pred; + lnNew.ln_Succ = this; + ln_Pred = &lnNew; +} + +/* Check that this list node is head marker of list. */ +inline BOOL CListNode::IsHeadMarker(void) const +{ + // if this is in fact pointer to list.lh_Head + if (ln_Pred == NULL ) { + // it is end marker + return TRUE; + // otherwise + } else { + // it must be somewhere inside the list + ASSERT(IsLinked()); + return FALSE; + } +} + +/* Check that this list node is tail marker of list. */ +inline BOOL CListNode::IsTailMarker(void) const +{ + // if this is in fact pointer to list.lh_NULL + if (ln_Succ == NULL ) { + // it is end marker + return TRUE; + // otherwise + } else { + // it must be somewhere inside the list + ASSERT(IsLinked()); + return FALSE; + } +} + +/* Check if this list node is head of list. */ +inline BOOL CListNode::IsHead(void) const +{ + // it must be somewhere inside the list + ASSERT(IsLinked()); + + // if previous is list.lh_Head + return ln_Pred->ln_Pred == NULL; +} + +/* Check that this list node is tail of list. */ +inline BOOL CListNode::IsTail(void) const +{ + // it must be somewhere inside the list + ASSERT(IsLinked()); + + // if next is list.lh_NULL + return ln_Succ->ln_Succ == NULL; +} +///////////////////////////////////////////////////////////////////// +// CListHead implementations +/* Get list head. */ +inline CListNode &CListHead::Head(void) const +{ + ASSERT(IsValid() && lh_Head->IsLinked()); + return *lh_Head; +} +/* Get list tail. */ +inline CListNode &CListHead::Tail(void) const +{ + ASSERT(IsValid() && lh_Tail->IsLinked()); + return *lh_Tail; +} +/* Get list head for iteration. */ +inline CListNode &CListHead::IterationHead(void) const +{ + ASSERT(IsValid() && (lh_Head->IsTailMarker() || lh_Head->IsLinked())); + return *lh_Head; +} +/* Get list tail for iteration. */ +inline CListNode &CListHead::IterationTail(void) const +{ + ASSERT(IsValid() && (lh_Tail->IsHeadMarker() || lh_Tail->IsLinked())); + return *lh_Tail; +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Memory.cpp b/Sources/Engine/Base/Memory.cpp new file mode 100644 index 0000000..cbb0678 --- /dev/null +++ b/Sources/Engine/Base/Memory.cpp @@ -0,0 +1,159 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +#include +#include + +extern FLOAT _bCheckAllAllocations = FALSE; + +/* + * Declarations for setting up the 'new_handler'. + */ +_CRTIMP int __cdecl _query_new_mode( void ); +_CRTIMP int __cdecl _set_new_mode( int ); + +#ifndef _PNH_DEFINED +typedef int (__cdecl * _PNH)( size_t ); +#define _PNH_DEFINED +#endif + +/*_CRTIMP _PNH __cdecl _query_new_handler( void ); +_CRTIMP _PNH __cdecl _set_new_handler( _PNH );*/ + +#ifndef NDEBUG +// include this for debug version of operator new +#pragma comment (lib, "msvcrtd.lib") +#endif + +// include user32 library (because of message box) +#pragma comment (lib, "user32.lib") + +// if not enough memory +int NewHandler(size_t size) +{ + // terminate program + FatalError(TRANS("Not enough memory (%d bytes needed)!"), size); + return 0; +} + +/* Static class used for initializing memory handlers. */ +static class CMemHandlerInit { +public: + // constructor + CMemHandlerInit(void); +} MemHandlerInit; + +CMemHandlerInit::CMemHandlerInit(void) +{ + // set our not-enough-memory handler + _set_new_handler(NewHandler); + // make malloc use that handler + _set_new_mode(1); +} + +#undef AllocMemory + +void *AllocMemory( SLONG memsize ) +{ + void *pmem; + ASSERTMSG(memsize>0, "AllocMemory: Block size is less or equal zero."); + if (_bCheckAllAllocations) { + _CrtCheckMemory(); + } + pmem = malloc( memsize); + // memory handler asures no null results here?! + if (pmem==NULL) { + _CrtCheckMemory(); + FatalError(TRANS("Not enough memory (%d bytes needed)!"), memsize); + } + return pmem; +} + +#ifndef NDEBUG +void *_debug_AllocMemory( SLONG memsize, int iType, const char *strFile, int iLine) +{ + void *pmem; + ASSERTMSG(memsize>0, "AllocMemory: Block size is less or equal zero."); + + if (_bCheckAllAllocations) { + _CrtCheckMemory(); + } + pmem = _malloc_dbg( memsize, iType, strFile, iLine); + // memory handler asures no null results here?! + if (pmem==NULL) { + _CrtCheckMemory(); + FatalError(TRANS("Not enough memory (%d bytes needed)!"), memsize); + } + return pmem; +} +#endif + +void *AllocMemoryAligned( SLONG memsize, SLONG slAlignPow2) +{ + ULONG ulMem = (ULONG)AllocMemory(memsize+slAlignPow2*2); + ULONG ulMemAligned = ((ulMem+slAlignPow2-1) & ~(slAlignPow2-1)) + slAlignPow2; + ((ULONG *)ulMemAligned)[-1] = ulMem; + return (void*)ulMemAligned; +} +void FreeMemoryAligned( void *memory) +{ + FreeMemory((void*) ( ( (ULONG*)memory )[-1] ) ); +} + +void FreeMemory( void *memory ) +{ + ASSERTMSG(memory!=NULL, "FreeMemory: NULL pointer input."); + free( (char *)memory); +} + +void ResizeMemory( void **ppv, SLONG slSize ) +{ + if (_bCheckAllAllocations) { + _CrtCheckMemory(); + } + void *pv = realloc(*ppv, slSize); + // memory handler asures no null results here?! + if (pv==NULL) { + _CrtCheckMemory(); + FatalError(TRANS("Not enough memory (%d bytes needed)!"), slSize); + } + *ppv = pv; +} + +void GrowMemory( void **ppv, SLONG newSize ) +{ + ResizeMemory(ppv, newSize); +} + +void ShrinkMemory( void **ppv, SLONG newSize ) +{ + ResizeMemory(ppv, newSize); +} + + +/* + * Allocate a copy of a string. - fatal error if not enough memory. + */ +char *StringDuplicate(const char *strOriginal) { + // get the size + SLONG slSize = strlen(strOriginal)+1; + // allocate that much memory + char *strCopy = (char *)AllocMemory(slSize); + // copy it there + memcpy(strCopy, strOriginal, slSize); + // result is the pointer to the copied string + return strCopy; +} + + + +// return position where we encounter zero byte or iBytes +INDEX FindZero( UBYTE *pubMemory, INDEX iBytes) +{ + for( INDEX i=0; i + +// global memory management functions + +/* Get amount of free memory in system. */ +ENGINE_API extern SLONG GetFreeMemory( void ); + +/* Allocate a block of memory - fatal error if not enough memory. */ +ENGINE_API extern void *AllocMemory( SLONG memsize ); +ENGINE_API extern void *_debug_AllocMemory( SLONG memsize, int iType, const char *strFile, int iLine); +ENGINE_API extern void *AllocMemoryAligned( SLONG memsize, SLONG slAlignPow2); +/* Free a block of memory. */ +ENGINE_API extern void FreeMemory( void *memory); +ENGINE_API extern void FreeMemoryAligned( void *memory); + +ENGINE_API extern void ResizeMemory( void **memory, SLONG memsize ); +ENGINE_API extern void GrowMemory( void **memory, SLONG memsize ); +ENGINE_API extern void ShrinkMemory( void **memory,SLONG memsize ); + +/* Allocate a copy of a string. - fatal error if not enough memory. */ +ENGINE_API extern char *StringDuplicate(const char *strOriginal); + +ENGINE_API extern BOOL MemoryConsistencyCheck( void ); +ENGINE_API extern BOOL AllMemoryFreed( void ); + +// return position (offset) where we encounter zero byte or iBytes +ENGINE_API extern INDEX FindZero( UBYTE *pubMemory, INDEX iBytes); + + +#ifdef _MSC_VER /* rcg10042001 */ +#ifndef NDEBUG + +// use debug version of operator new +#include +/*void * __cdecl operator new( + unsigned int, + int, + const char *, + int + );*/ +#define DEBUG_NEW_CT new(_NORMAL_BLOCK, __FILE__, __LINE__) +#define new DEBUG_NEW_CT +#define DEBUG_ALLOC(size) _debug_AllocMemory(size, _NORMAL_BLOCK, __FILE__, __LINE__) +#define AllocMemory(size) DEBUG_ALLOC(size) +#define ReportLostMemory _CrtDumpMemoryLeaks + +#else +#define ReportLostMemory() ((void)0) + +#endif // NDEBUG +#endif // _MSC_VER + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Parser.cpp b/Sources/Engine/Base/Parser.cpp new file mode 100644 index 0000000..830dea6 --- /dev/null +++ b/Sources/Engine/Base/Parser.cpp @@ -0,0 +1,2157 @@ + +/* A Bison parser, made from engine/base/parser.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define c_float 258 +#define c_int 259 +#define c_string 260 +#define c_char 261 +#define identifier 262 +#define k_INDEX 263 +#define k_FLOAT 264 +#define k_CTString 265 +#define k_void 266 +#define k_const 267 +#define k_user 268 +#define k_persistent 269 +#define k_extern 270 +#define k_pre 271 +#define k_post 272 +#define k_help 273 +#define k_if 274 +#define k_else 275 +#define k_else_if 276 +#define SHL 277 +#define SHR 278 +#define EQ 279 +#define NEQ 280 +#define GEQ 281 +#define LEQ 282 +#define LOGAND 283 +#define LOGOR 284 +#define block_beg 285 +#define block_end 286 +#define TYPECAST 287 +#define SIGN 288 + +#line 1 "engine/base/parser.y" + +#include "StdH.h" + +#include +#include +#include "ParsingSymbols.h" + +#include +#include + +#line 13 "engine/base/parser.y" + +#define YYERROR_VERBOSE 1 +// if error occurs in parsing +void yyerror(char *str) +{ + // just report the string + _pShell->ErrorF("%s", str); +}; + +static BOOL _bExecNextElse = FALSE; +FLOAT fDummy = -666.0f; + +static INDEX _iStack = 0; +static UBYTE _ubStack[1024]; + +INDEX PushExpression(value &v) +{ + if (v.sttType==STT_FLOAT) { + FLOAT f = v.fFloat; + memcpy(_ubStack+_iStack, &f, sizeof(f)); + _iStack+=sizeof(f); + return sizeof(f); + } else if (v.sttType==STT_INDEX) { + INDEX i = v.iIndex; + memcpy(_ubStack+_iStack, &i, sizeof(i)); + _iStack+=sizeof(i); + return sizeof(i); + } else if (v.sttType==STT_STRING) { + CTString &str = _shell_astrTempStrings.Push(); + str = v.strString; + CTString *pstr = &str; + memcpy(_ubStack+_iStack, &pstr, sizeof(pstr)); + _iStack+=sizeof(pstr); + return sizeof(pstr); + } else { + return 0; + } +} + +BOOL MatchTypes(value &v1, value &v2) +{ + if (v1.sttType==STT_FLOAT && v2.sttType==STT_FLOAT) { + return TRUE; + } else if (v1.sttType==STT_STRING && v2.sttType==STT_STRING) { + return TRUE; + } else if (v1.sttType==STT_INDEX && v2.sttType==STT_INDEX) { + return TRUE; + } else { + v1.sttType = STT_ILLEGAL; + v2.sttType = STT_ILLEGAL; + _pShell->ErrorF("Type mismatch"); + return FALSE; + } +} + +void Declaration( + ULONG ulQualifiers, INDEX istType, CShellSymbol &ssNew, + INDEX (*pPreFunc)(INDEX), void (*pPostFunc)(INDEX)) +{ + // if external + if (ulQualifiers&SSF_EXTERNAL) { + // get it a new value + if (_shell_ast[istType].st_sttType==STT_INDEX + ||_shell_ast[istType].st_sttType==STT_FLOAT) { + _pvNextToDeclare = &_shell_afExtFloats.Push(); + } else if (_shell_ast[istType].st_sttType==STT_STRING) { + _pvNextToDeclare = &_shell_astrExtStrings.Push(); + } else { + NOTHING; + } + } + + // if not parsing an external declaration + if (_pvNextToDeclare==NULL) { + // error + _pShell->ErrorF("Only external declarations are supported"); + return; + } + + // if the symbol is declared already + if (ssNew.IsDeclared()) { + // if the declaration is not identical + if (!ShellTypeIsSame(ssNew.ss_istType, istType) || + ((ssNew.ss_ulFlags&SSF_CONSTANT)!=(ulQualifiers&SSF_CONSTANT))) { + // error + _pShell->ErrorF("Symbol '%s' is already declared diferrently", ssNew.ss_strName); + return; + } + + // copy its value + if (_shell_ast[ssNew.ss_istType].st_sttType==STT_INDEX) { + *(INDEX*)_pvNextToDeclare = *(INDEX*)ssNew.ss_pvValue; + } else if (_shell_ast[ssNew.ss_istType].st_sttType==STT_FLOAT) { + *(FLOAT*)_pvNextToDeclare = *(FLOAT*)ssNew.ss_pvValue; + } else if (_shell_ast[ssNew.ss_istType].st_sttType==STT_STRING) { + *(CTString*)_pvNextToDeclare = *(CTString*)ssNew.ss_pvValue; + } else if (_shell_ast[ssNew.ss_istType].st_sttType==STT_ARRAY) { + NOTHING; // array values are not retained + } else if (_shell_ast[ssNew.ss_istType].st_sttType==STT_FUNCTION) { + NOTHING; // function values are not retained + } else { + // error + _pShell->ErrorF("'%s': old value couldn't be retained", ssNew.ss_strName); + return; + } + } + + // set the type to given type + if (!ssNew.IsDeclared()) { + ssNew.ss_istType = ShellTypeMakeDuplicate(istType); + } + // set the value for the external symbol if not already set + if (ssNew.ss_pvValue==NULL || !(ulQualifiers&SSF_EXTERNAL)) { + ssNew.ss_pvValue = _pvNextToDeclare; + } + // remember qualifiers (if already predeclared - keep old flags) + ssNew.ss_ulFlags |= ulQualifiers; + // remember pre and post functions + if (ssNew.ss_pPreFunc==NULL) { + ssNew.ss_pPreFunc = (BOOL (*)(void *))pPreFunc; + } + if (ssNew.ss_pPostFunc==NULL) { + ssNew.ss_pPostFunc = (void (*)(void *))pPostFunc; + } +} + +void DoComparison(value &vRes, value &v0, value &v1, int token) +{ + MatchTypes(v0, v1); + + vRes.sttType = STT_INDEX; + if (v0.sttType == STT_FLOAT) { + switch (token) { + case '<': vRes.iIndex = v0.fFloat ': vRes.iIndex = v0.fFloat >v1.fFloat; break; + case '=': vRes.iIndex = v0.fFloat==v1.fFloat; break; + case '!': vRes.iIndex = v0.fFloat!=v1.fFloat; break; + case '}': vRes.iIndex = v0.fFloat>=v1.fFloat; break; + case '{': vRes.iIndex = v0.fFloat<=v1.fFloat; break; + default: ASSERT(FALSE); + vRes.sttType = STT_INDEX; + vRes.iIndex = 0; + } + } else if (v0.sttType == STT_INDEX) { + switch (token) { + case '<': vRes.iIndex = v0.iIndex ': vRes.iIndex = v0.iIndex >v1.iIndex; break; + case '=': vRes.iIndex = v0.iIndex==v1.iIndex; break; + case '!': vRes.iIndex = v0.iIndex!=v1.iIndex; break; + case '}': vRes.iIndex = v0.iIndex>=v1.iIndex; break; + case '{': vRes.iIndex = v0.iIndex<=v1.iIndex; break; + default: ASSERT(FALSE); + vRes.sttType = STT_INDEX; + vRes.iIndex = 0; + } + } else if (v0.sttType == STT_STRING) { + switch (token) { + case '<': vRes.iIndex = stricmp(v0.strString, v1.strString) < 0; break; + case '>': vRes.iIndex = stricmp(v0.strString, v1.strString) > 0; break; + case '=': vRes.iIndex = stricmp(v0.strString, v1.strString) == 0; break; + case '!': vRes.iIndex = stricmp(v0.strString, v1.strString) != 0; break; + case '}': vRes.iIndex = stricmp(v0.strString, v1.strString) >= 0; break; + case '{': vRes.iIndex = stricmp(v0.strString, v1.strString) <= 0; break; + default: ASSERT(FALSE); + vRes.sttType = STT_INDEX; + vRes.iIndex = 0; + } + } else { + vRes.sttType = STT_INDEX; + vRes.iIndex = 0; + } +} + +#line 192 "engine/base/parser.y" +typedef union { + value val; // for constants and expressions + arguments arg; // for function input arguments + ULONG ulFlags; // for declaration qualifiers + INDEX istType; // for types + CShellSymbol *pssSymbol; // for symbols + struct LValue lvLValue; + INDEX (*pPreFunc)(INDEX); // pre-set function for a variable + void (*pPostFunc)(INDEX); // post-set function for a variable +} YYSTYPE; +#line 203 "engine/base/parser.y" + + extern int yylex(YYSTYPE *lvalp); + +#ifndef YYLTYPE +typedef + struct yyltype + { + int timestamp; + int first_line; + int first_column; + int last_line; + int last_column; + char *text; + } + yyltype; + +#define YYLTYPE yyltype +#endif + +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 156 +#define YYFLAG -32768 +#define YYNTBASE 53 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 288 ? yytranslate[x] : 75) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 45, 2, 2, 2, 42, 33, 2, 49, + 50, 40, 39, 47, 38, 2, 41, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 46, 48, 36, + 32, 37, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 51, 2, 52, 34, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 35, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 43, 44 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 2, 4, 8, 12, 13, 16, 17, 20, 23, + 26, 29, 30, 32, 34, 36, 38, 40, 41, 45, + 46, 50, 51, 53, 55, 59, 67, 76, 87, 89, + 91, 94, 99, 106, 109, 114, 119, 120, 121, 130, + 131, 132, 133, 142, 143, 147, 149, 154, 155, 157, + 159, 163, 165, 167, 169, 171, 175, 179, 183, 187, + 191, 195, 199, 203, 207, 211, 215, 219, 223, 227, + 231, 235, 239, 243, 246, 249, 252, 257, 262, 267, + 272 +}; + +static const short yyrhs[] = { 63, + 0, 55, 0, 30, 55, 31, 0, 30, 55, 31, + 0, 0, 64, 55, 0, 0, 56, 12, 0, 56, + 13, 0, 56, 14, 0, 56, 15, 0, 0, 5, + 0, 9, 0, 8, 0, 10, 0, 11, 0, 0, + 16, 46, 7, 0, 0, 17, 46, 7, 0, 0, + 62, 0, 58, 0, 62, 47, 58, 0, 56, 58, + 7, 59, 60, 57, 48, 0, 56, 58, 7, 49, + 61, 50, 57, 48, 0, 56, 58, 7, 51, 74, + 52, 59, 60, 57, 48, 0, 48, 0, 54, 0, + 74, 48, 0, 71, 32, 74, 48, 0, 56, 58, + 7, 32, 74, 48, 0, 18, 7, 0, 18, 7, + 49, 50, 0, 18, 7, 51, 52, 0, 0, 0, + 19, 49, 74, 50, 65, 54, 66, 67, 0, 0, + 0, 0, 21, 49, 74, 50, 68, 54, 69, 67, + 0, 0, 20, 70, 54, 0, 7, 0, 7, 51, + 74, 52, 0, 0, 73, 0, 74, 0, 73, 47, + 74, 0, 3, 0, 4, 0, 5, 0, 71, 0, + 74, 22, 74, 0, 74, 23, 74, 0, 74, 33, + 74, 0, 74, 35, 74, 0, 74, 34, 74, 0, + 74, 28, 74, 0, 74, 29, 74, 0, 74, 39, + 74, 0, 74, 38, 74, 0, 74, 40, 74, 0, + 74, 41, 74, 0, 74, 42, 74, 0, 74, 36, + 74, 0, 74, 37, 74, 0, 74, 24, 74, 0, + 74, 25, 74, 0, 74, 26, 74, 0, 74, 27, + 74, 0, 38, 74, 0, 39, 74, 0, 45, 74, + 0, 49, 9, 50, 74, 0, 49, 8, 50, 74, + 0, 49, 10, 50, 74, 0, 7, 49, 72, 50, + 0, 49, 74, 50, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 270, 271, 275, 276, 280, 281, 285, 288, 291, 294, + 297, 302, 305, 312, 315, 318, 321, 326, 329, 342, + 345, 358, 362, 368, 376, 387, 391, 400, 410, 413, + 416, 430, 468, 502, 506, 510, 514, 524, 528, 531, + 533, 549, 554, 554, 556, 562, 587, 627, 632, 638, + 643, 650, 654, 658, 662, 680, 693, 707, 721, 735, + 751, 765, 780, 799, 815, 831, 853, 869, 872, 875, + 878, 881, 884, 890, 904, 916, 929, 943, 957, 974, + 1046 +}; + +static const char * const yytname[] = { "$","error","$undefined.","c_float", +"c_int","c_string","c_char","identifier","k_INDEX","k_FLOAT","k_CTString","k_void", +"k_const","k_user","k_persistent","k_extern","k_pre","k_post","k_help","k_if", +"k_else","k_else_if","SHL","SHR","EQ","NEQ","GEQ","LEQ","LOGAND","LOGOR","block_beg", +"block_end","'='","'&'","'^'","'|'","'<'","'>'","'-'","'+'","'*'","'/'","'%'", +"TYPECAST","SIGN","'!'","':'","','","';'","'('","')'","'['","']'","program", +"block","statements","declaration_qualifiers","opt_string","type_specifier", +"pre_func_opt","post_func_opt","parameter_list_opt","parameter_list","declaration", +"statement","@1","@2","opt_else","@3","@4","@5","lvalue","argument_expression_list_opt", +"argument_expression_list","expression","" +}; +#endif + +static const short yyr1[] = { 0, + 53, 53, 54, 54, 55, 55, 56, 56, 56, 56, + 56, 57, 57, 58, 58, 58, 58, 59, 59, 60, + 60, 61, 61, 62, 62, 63, 63, 63, 64, 64, + 64, 64, 64, 64, 64, 64, 65, 66, 64, 67, + 68, 69, 67, 70, 67, 71, 71, 72, 72, 73, + 73, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, + 74 +}; + +static const short yyr2[] = { 0, + 1, 1, 3, 3, 0, 2, 0, 2, 2, 2, + 2, 0, 1, 1, 1, 1, 1, 0, 3, 0, + 3, 0, 1, 1, 3, 7, 8, 10, 1, 1, + 2, 4, 6, 2, 4, 4, 0, 0, 8, 0, + 0, 0, 8, 0, 3, 1, 4, 0, 1, 1, + 3, 1, 1, 1, 1, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 2, 2, 2, 4, 4, 4, 4, + 3 +}; + +static const short yydefact[] = { 7, + 52, 53, 54, 46, 0, 0, 7, 0, 0, 0, + 29, 0, 30, 2, 0, 1, 7, 55, 0, 48, + 0, 34, 0, 0, 0, 55, 74, 75, 76, 0, + 0, 0, 0, 15, 14, 16, 17, 8, 9, 10, + 11, 0, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 31, 0, 49, 50, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 81, 18, 0, 56, 57, + 70, 71, 72, 73, 61, 62, 58, 60, 59, 68, + 69, 64, 63, 65, 66, 67, 80, 0, 47, 35, + 36, 37, 0, 78, 77, 79, 0, 0, 22, 0, + 20, 32, 51, 0, 0, 0, 24, 0, 23, 0, + 0, 12, 38, 19, 33, 12, 0, 18, 0, 13, + 0, 40, 0, 25, 20, 21, 26, 44, 0, 39, + 27, 12, 0, 0, 0, 45, 0, 28, 41, 0, + 42, 40, 43, 0, 0, 0 +}; + +static const short yydefgoto[] = { 154, + 13, 14, 25, 131, 42, 111, 122, 118, 119, 16, + 17, 114, 132, 140, 150, 152, 143, 26, 64, 65, + 19 +}; + +static const short yypact[] = { 110, +-32768,-32768,-32768, -44, 4, -19, 134, 81, 81, 81, +-32768, 19,-32768,-32768, 434,-32768, 73, 0, 291, 81, + 81, -41, 81, 3, 434,-32768,-32768,-32768,-32768, -15, + 10, 11, 204,-32768,-32768,-32768,-32768,-32768,-32768,-32768, +-32768, 52,-32768, 81, 81, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 81, 81,-32768, 24, 28, 372, 162, 31, 37, 233, +-32768, 75, 81, 81, 81,-32768, 47, 318, 93, 104, + 128, 128, 128, 128, 393, 393, 414, 414, 414, 128, + 128, 30, 30,-32768,-32768,-32768,-32768, 81,-32768,-32768, +-32768,-32768, 51,-32768,-32768,-32768, 48, 81, 9, 81, + 76,-32768, 372, 65, 90, 345,-32768, 49, 54, 183, + 60, 102,-32768,-32768,-32768, 102, 9, 92, 116,-32768, + 61, 35, 77,-32768, 76,-32768,-32768,-32768, 78,-32768, +-32768, 102, 65, 81, 99,-32768, 262,-32768,-32768, 65, +-32768, 35,-32768, 124, 154,-32768 +}; + +static const short yypgoto[] = {-32768, + -81, -1, 156, -117, -22, 29, 25,-32768,-32768,-32768, +-32768,-32768,-32768, 22,-32768,-32768,-32768, 14,-32768,-32768, + -8 +}; + + +#define YYLAST 456 + + +static const short yytable[] = { 27, + 28, 29, 72, 33, 20, 24, 21, 68, 133, 69, + 22, 66, 67, 18, 70, 43, 34, 35, 36, 37, + 18, 1, 2, 3, 145, 4, 30, 31, 32, 23, + 18, 44, 123, 71, 73, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 138, 139, 8, 9, 77, 74, + 75, 146, 107, 10, 104, 105, 106, 12, 151, 60, + 61, 62, -5, 97, 98, 1, 2, 3, 108, 4, + 100, 103, 108, 1, 2, 3, 117, 4, 101, 113, + 5, 6, 121, 115, 7, 109, 124, 110, 126, 116, + 127, 120, 7, -5, 134, 129, 130, 107, 137, -5, + 8, 9, 1, 2, 3, 46, 4, 10, 8, 9, + 11, 12, 136, 155, 141, 10, 144, 5, 6, 12, + 58, 59, 60, 61, 62, 147, 1, 2, 3, 7, + 4, 58, 59, 60, 61, 62, 148, 8, 9, 45, + 46, 5, 6, 156, 10, 15, 135, 11, 12, 142, + 0, 0, 0, 7, -5, 58, 59, 60, 61, 62, + 0, 8, 9, 153, 0, 0, 0, 0, 10, 0, + 0, 11, 12, 45, 46, 47, 48, 49, 50, 51, + 52, 0, 0, 0, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 45, 46, 47, 48, 49, 50, + 51, 52, 0, 99, 0, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 45, 46, 47, 48, 49, + 50, 51, 52, 0, 128, 0, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 0, 0, 0, 0, + 0, 0, 0, 76, 45, 46, 47, 48, 49, 50, + 51, 52, 0, 0, 0, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, + 0, 0, 102, 45, 46, 47, 48, 49, 50, 51, + 52, 0, 0, 0, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, + 0, 149, 45, 46, 47, 48, 49, 50, 51, 52, + 0, 0, 0, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 0, 0, 0, 0, 0, 63, 45, + 46, 47, 48, 49, 50, 51, 52, 0, 0, 0, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 0, 0, 0, 0, 0, 112, 45, 46, 47, 48, + 49, 50, 51, 52, 0, 0, 0, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 0, 0, 0, + 0, 0, 125, 45, 46, 47, 48, 49, 50, 51, + 52, 0, 0, 0, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 45, 46, 47, 48, 49, 50, + 0, 0, 0, 0, 0, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 45, 46, 47, 48, 49, + 50, 34, 35, 36, 37, 38, 39, 40, 41, 56, + 57, 58, 59, 60, 61, 62 +}; + +static const short yycheck[] = { 8, + 9, 10, 25, 12, 49, 7, 51, 49, 126, 51, + 7, 20, 21, 0, 23, 17, 8, 9, 10, 11, + 7, 3, 4, 5, 142, 7, 8, 9, 10, 49, + 17, 32, 114, 31, 50, 44, 45, 46, 47, 48, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 20, 21, 38, 39, 7, 50, + 50, 143, 16, 45, 73, 74, 75, 49, 150, 40, + 41, 42, 0, 50, 47, 3, 4, 5, 32, 7, + 50, 7, 32, 3, 4, 5, 109, 7, 52, 98, + 18, 19, 17, 46, 30, 49, 7, 51, 50, 108, + 47, 110, 30, 31, 127, 46, 5, 16, 48, 0, + 38, 39, 3, 4, 5, 23, 7, 45, 38, 39, + 48, 49, 7, 0, 48, 45, 49, 18, 19, 49, + 38, 39, 40, 41, 42, 144, 3, 4, 5, 30, + 7, 38, 39, 40, 41, 42, 48, 38, 39, 22, + 23, 18, 19, 0, 45, 0, 128, 48, 49, 135, + -1, -1, -1, 30, 31, 38, 39, 40, 41, 42, + -1, 38, 39, 152, -1, -1, -1, -1, 45, -1, + -1, 48, 49, 22, 23, 24, 25, 26, 27, 28, + 29, -1, -1, -1, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 22, 23, 24, 25, 26, 27, + 28, 29, -1, 52, -1, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 22, 23, 24, 25, 26, + 27, 28, 29, -1, 52, -1, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, -1, -1, -1, -1, + -1, -1, -1, 50, 22, 23, 24, 25, 26, 27, + 28, 29, -1, -1, -1, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, -1, -1, -1, -1, -1, + -1, -1, 50, 22, 23, 24, 25, 26, 27, 28, + 29, -1, -1, -1, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, -1, -1, -1, -1, -1, -1, + -1, 50, 22, 23, 24, 25, 26, 27, 28, 29, + -1, -1, -1, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, -1, -1, -1, -1, -1, 48, 22, + 23, 24, 25, 26, 27, 28, 29, -1, -1, -1, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + -1, -1, -1, -1, -1, 48, 22, 23, 24, 25, + 26, 27, 28, 29, -1, -1, -1, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, -1, -1, -1, + -1, -1, 48, 22, 23, 24, 25, 26, 27, 28, + 29, -1, -1, -1, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 22, 23, 24, 25, 26, 27, + -1, -1, -1, -1, -1, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 22, 23, 24, 25, 26, + 27, 8, 9, 10, 11, 12, 13, 14, 15, 36, + 37, 38, 39, 40, 41, 42 +}; +#define YYPURE 1 + +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#undef YYERROR_VERBOSE +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 192 "bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +int +yyparse(YYPARSE_PARAM) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 7: +#line 285 "engine/base/parser.y" +{ + yyval.ulFlags = 0; +; + break;} +case 8: +#line 288 "engine/base/parser.y" +{ + yyval.ulFlags = yyvsp[-1].ulFlags | SSF_CONSTANT; +; + break;} +case 9: +#line 291 "engine/base/parser.y" +{ + yyval.ulFlags = yyvsp[-1].ulFlags | SSF_USER; +; + break;} +case 10: +#line 294 "engine/base/parser.y" +{ + yyval.ulFlags = yyvsp[-1].ulFlags | SSF_PERSISTENT; +; + break;} +case 11: +#line 297 "engine/base/parser.y" +{ + yyval.ulFlags = yyvsp[-1].ulFlags | SSF_EXTERNAL; +; + break;} +case 12: +#line 302 "engine/base/parser.y" +{ + yyval.val.strString = ""; +; + break;} +case 13: +#line 305 "engine/base/parser.y" +{ + // !!!! remove this option + //_pShell->ErrorF("Warning: symbol comments are not supported"); + yyval.val.strString = yyvsp[0].val.strString; +; + break;} +case 14: +#line 312 "engine/base/parser.y" +{ + yyval.istType = ShellTypeNewFloat(); +; + break;} +case 15: +#line 315 "engine/base/parser.y" +{ + yyval.istType = ShellTypeNewIndex(); +; + break;} +case 16: +#line 318 "engine/base/parser.y" +{ + yyval.istType = ShellTypeNewString(); +; + break;} +case 17: +#line 321 "engine/base/parser.y" +{ + yyval.istType = ShellTypeNewVoid(); +; + break;} +case 18: +#line 326 "engine/base/parser.y" +{ + yyval.pPreFunc = NULL; +; + break;} +case 19: +#line 329 "engine/base/parser.y" +{ + if (_shell_ast[yyvsp[0].pssSymbol->ss_istType].st_sttType!=STT_FUNCTION + ||_shell_ast[_shell_ast[yyvsp[0].pssSymbol->ss_istType].st_istBaseType].st_sttType!=STT_INDEX + ||_shell_ast[yyvsp[0].pssSymbol->ss_istType].st_istFirstArgument!=_shell_ast[yyvsp[0].pssSymbol->ss_istType].st_istLastArgument + ||_shell_ast[_shell_ast[yyvsp[0].pssSymbol->ss_istType].st_istFirstArgument].st_sttType!=STT_INDEX) { + _pShell->ErrorF("'%s' must return 'INDEX' and take 'INDEX' as input", yyvsp[0].pssSymbol->ss_strName); + } else { + void *pv = yyvsp[0].pssSymbol->ss_pvValue; + yyval.pPreFunc = (INDEX(*)(INDEX))yyvsp[0].pssSymbol->ss_pvValue; + } +; + break;} +case 20: +#line 342 "engine/base/parser.y" +{ + yyval.pPostFunc = NULL; +; + break;} +case 21: +#line 345 "engine/base/parser.y" +{ + if (_shell_ast[yyvsp[0].pssSymbol->ss_istType].st_sttType!=STT_FUNCTION + ||_shell_ast[_shell_ast[yyvsp[0].pssSymbol->ss_istType].st_istBaseType].st_sttType!=STT_VOID + ||_shell_ast[yyvsp[0].pssSymbol->ss_istType].st_istFirstArgument!=_shell_ast[yyvsp[0].pssSymbol->ss_istType].st_istLastArgument + ||_shell_ast[_shell_ast[yyvsp[0].pssSymbol->ss_istType].st_istFirstArgument].st_sttType!=STT_INDEX) { + _pShell->ErrorF("'%s' must return 'void' and take 'INDEX' as input", yyvsp[0].pssSymbol->ss_strName); + } else { + yyval.pPostFunc = (void(*)(INDEX))yyvsp[0].pssSymbol->ss_pvValue; + } +; + break;} +case 22: +#line 358 "engine/base/parser.y" +{ + yyval.istType = ShellTypeNewFunction(0); + ShellTypeAddFunctionArgument(yyval.istType, ShellTypeNewVoid()); +; + break;} +case 23: +#line 362 "engine/base/parser.y" +{ + yyval.istType = yyvsp[0].istType; +; + break;} +case 24: +#line 368 "engine/base/parser.y" +{ + yyval.istType = ShellTypeNewFunction(0); + ShellTypeAddFunctionArgument(yyval.istType, yyvsp[0].istType); +; + break;} +case 25: +#line 376 "engine/base/parser.y" +{ + yyval.istType = yyvsp[-2].istType; + ShellTypeAddFunctionArgument(yyval.istType, yyvsp[0].istType); +; + break;} +case 26: +#line 387 "engine/base/parser.y" +{ + Declaration(yyvsp[-6].ulFlags, yyvsp[-5].istType, *yyvsp[-4].pssSymbol, yyvsp[-3].pPreFunc, yyvsp[-2].pPostFunc); + ShellTypeDelete(yyvsp[-5].istType); +; + break;} +case 27: +#line 391 "engine/base/parser.y" +{ + // take function from the parameter list and set its return type + _shell_ast[yyvsp[-3].istType].st_istBaseType = yyvsp[-6].istType; + yyvsp[-6].istType = yyvsp[-3].istType; + // declare it + Declaration(yyvsp[-7].ulFlags, yyvsp[-6].istType, *yyvsp[-5].pssSymbol, NULL, NULL); + // free the type (declaration will make a copy) + ShellTypeDelete(yyvsp[-6].istType); +; + break;} +case 28: +#line 400 "engine/base/parser.y" +{ + if (yyvsp[-5].val.sttType!=STT_INDEX) { + _pShell->ErrorF("Array size is not integral"); + } + yyvsp[-8].istType = ShellTypeNewArray(yyvsp[-8].istType, yyvsp[-5].val.iIndex); + Declaration(yyvsp[-9].ulFlags, yyvsp[-8].istType, *yyvsp[-7].pssSymbol, NULL, NULL); + ShellTypeDelete(yyvsp[-8].istType); +; + break;} +case 29: +#line 410 "engine/base/parser.y" +{ + // dummy +; + break;} +case 30: +#line 413 "engine/base/parser.y" +{ + // dummy +; + break;} +case 31: +#line 416 "engine/base/parser.y" +{ + // print its value + if (yyvsp[-1].val.sttType == STT_VOID) { + NOTHING; + } else if (yyvsp[-1].val.sttType == STT_FLOAT) { + CPrintF("%g\n", yyvsp[-1].val.fFloat); + } else if (yyvsp[-1].val.sttType == STT_STRING) { + CPrintF("\"%s\"\n", yyvsp[-1].val.strString); + } else if (yyvsp[-1].val.sttType == STT_INDEX) { + CPrintF("%d(0x%08X)\n", yyvsp[-1].val.iIndex, yyvsp[-1].val.iIndex); + } else { + _pShell->ErrorF("Expression cannot be printed"); + } +; + break;} +case 32: +#line 430 "engine/base/parser.y" +{ + // if it is constant + if (yyvsp[-3].lvLValue.lv_pssSymbol->ss_ulFlags&SSF_CONSTANT) { + _pShell->ErrorF("Symbol '%s' is a constant", yyvsp[-3].lvLValue.lv_pssSymbol->ss_strName); + // if it is not constant + } else { + // if it can be changed + if (yyvsp[-3].lvLValue.lv_pssSymbol->ss_pPreFunc==NULL || yyvsp[-3].lvLValue.lv_pssSymbol->ss_pPreFunc(yyvsp[-3].lvLValue.lv_pvAddress)) { + // if floats + if (yyvsp[-3].lvLValue.lv_sttType == STT_FLOAT && yyvsp[-1].val.sttType==STT_FLOAT) { + // assign value + *(FLOAT*)yyvsp[-3].lvLValue.lv_pvAddress = yyvsp[-1].val.fFloat; + // if indices + } else if (yyvsp[-3].lvLValue.lv_sttType == STT_INDEX && yyvsp[-1].val.sttType==STT_INDEX) { + // assign value + *(INDEX*)yyvsp[-3].lvLValue.lv_pvAddress = yyvsp[-1].val.iIndex; + + // if strings + } else if (yyvsp[-3].lvLValue.lv_sttType == STT_STRING && yyvsp[-1].val.sttType==STT_STRING) { + // assign value + *(CTString*)yyvsp[-3].lvLValue.lv_pvAddress = yyvsp[-1].val.strString; + + // if assigning index to float + } else if (yyvsp[-3].lvLValue.lv_sttType == STT_FLOAT && yyvsp[-1].val.sttType==STT_INDEX) { + *(FLOAT*)yyvsp[-3].lvLValue.lv_pvAddress = yyvsp[-1].val.iIndex; + // otherwise + } else { + // error + _pShell->ErrorF("Cannot assign: different types"); + } + + // call post-change function + if (yyvsp[-3].lvLValue.lv_pssSymbol->ss_pPostFunc!=NULL) { + yyvsp[-3].lvLValue.lv_pssSymbol->ss_pPostFunc(yyvsp[-3].lvLValue.lv_pvAddress); + } + } + } +; + break;} +case 33: +#line 468 "engine/base/parser.y" +{ + Declaration(yyvsp[-5].ulFlags, yyvsp[-4].istType, *yyvsp[-3].pssSymbol, NULL, NULL); + ShellTypeDelete(yyvsp[-4].istType); + + CShellSymbol &ssSymbol = *yyvsp[-3].pssSymbol; + // if it is constant + if (ssSymbol.ss_ulFlags&SSF_CONSTANT) { + // error + _pShell->ErrorF("Symbol '%s' is a constant", ssSymbol.ss_strName); + } + + // get symbol type + ShellTypeType stt = _shell_ast[yyvsp[-4].istType].st_sttType; + + // if floats + if (stt == STT_FLOAT && yyvsp[-1].val.sttType==STT_FLOAT) { + // assign value + *(FLOAT*)ssSymbol.ss_pvValue = yyvsp[-1].val.fFloat; + // if indices + } else if (stt == STT_INDEX && yyvsp[-1].val.sttType==STT_INDEX) { + // assign value + *(INDEX*)ssSymbol.ss_pvValue = yyvsp[-1].val.iIndex; + // if strings + } else if (stt == STT_STRING && yyvsp[-1].val.sttType==STT_STRING) { + // assign value + *(CTString*)ssSymbol.ss_pvValue = yyvsp[-1].val.strString; + // !!!! remove this conversion + } else if (stt == STT_FLOAT && yyvsp[-1].val.sttType==STT_INDEX) { + _pShell->ErrorF("Warning: assigning INDEX to FLOAT!"); + *(FLOAT*)ssSymbol.ss_pvValue = yyvsp[-1].val.iIndex; + } else { + _pShell->ErrorF("Symbol '%s' and its initializer have different types", ssSymbol.ss_strName); + } +; + break;} +case 34: +#line 502 "engine/base/parser.y" +{ +extern void PrintShellSymbolHelp(const CTString &strSymbol); + PrintShellSymbolHelp(yyvsp[0].pssSymbol->ss_strName); +; + break;} +case 35: +#line 506 "engine/base/parser.y" +{ +extern void PrintShellSymbolHelp(const CTString &strSymbol); + PrintShellSymbolHelp(yyvsp[-2].pssSymbol->ss_strName); +; + break;} +case 36: +#line 510 "engine/base/parser.y" +{ +extern void PrintShellSymbolHelp(const CTString &strSymbol); + PrintShellSymbolHelp(yyvsp[-2].pssSymbol->ss_strName); +; + break;} +case 37: +#line 514 "engine/base/parser.y" +{ + _bExecNextBlock = FALSE; + if (yyvsp[-1].val.sttType == STT_INDEX) { + _bExecNextBlock = yyvsp[-1].val.iIndex!=0; + } else if (yyvsp[-1].val.sttType == STT_FLOAT) { + _bExecNextBlock = yyvsp[-1].val.fFloat!=0; + } else { + _pShell->ErrorF("If expression is not integral"); + } + yyvsp[-3].ulFlags = _bExecNextBlock; +; + break;} +case 38: +#line 524 "engine/base/parser.y" +{ + _bExecNextElse = !yyvsp[-5].ulFlags; + _bExecNextBlock = TRUE; +; + break;} +case 41: +#line 533 "engine/base/parser.y" +{ + if (_bExecNextElse) { + _bExecNextBlock = FALSE; + if (yyvsp[-1].val.sttType == STT_INDEX) { + _bExecNextBlock = yyvsp[-1].val.iIndex!=0; + } else if (yyvsp[-1].val.sttType == STT_FLOAT) { + _bExecNextBlock = yyvsp[-1].val.fFloat!=0; + } else { + _pShell->ErrorF("If expression is not integral"); + } + yyvsp[-3].ulFlags = _bExecNextBlock; + } else { + _bExecNextBlock = FALSE; + _bExecNextElse = FALSE; + yyvsp[-3].ulFlags = TRUE; + } +; + break;} +case 42: +#line 549 "engine/base/parser.y" +{ + _bExecNextElse = !yyvsp[-5].ulFlags; + _bExecNextBlock = TRUE; +; + break;} +case 44: +#line 554 "engine/base/parser.y" +{ + _bExecNextBlock = _bExecNextElse; +; + break;} +case 45: +#line 556 "engine/base/parser.y" +{ + _bExecNextBlock = TRUE; +; + break;} +case 46: +#line 562 "engine/base/parser.y" +{ + CShellSymbol &ssSymbol = *yyvsp[0].pssSymbol; + const ShellType &stType = _shell_ast[ssSymbol.ss_istType]; + + yyval.lvLValue.lv_pssSymbol = &ssSymbol; + if (!ssSymbol.IsDeclared()) { + // error + _pShell->ErrorF("Identifier '%s' is not declared", yyvsp[0].pssSymbol->ss_strName); + fDummy = -666; + yyval.lvLValue.lv_sttType = STT_VOID; + yyval.lvLValue.lv_pvAddress = &fDummy; + // if the identifier is a float, int or string + } else if (stType.st_sttType==STT_FLOAT || stType.st_sttType==STT_INDEX || stType.st_sttType==STT_STRING) { + // get its value and type + yyval.lvLValue.lv_sttType = stType.st_sttType; + yyval.lvLValue.lv_pvAddress = ssSymbol.ss_pvValue; + // if the identifier is something else + } else { + // error + _pShell->ErrorF("'%s' doesn't have a value", yyvsp[0].pssSymbol->ss_strName); + fDummy = -666.0f; + yyval.lvLValue.lv_sttType = STT_VOID; + yyval.lvLValue.lv_pvAddress = &fDummy; + } +; + break;} +case 47: +#line 587 "engine/base/parser.y" +{ + CShellSymbol &ssSymbol = *yyvsp[-3].pssSymbol; + const ShellType &stType = _shell_ast[ssSymbol.ss_istType]; + yyval.lvLValue.lv_pssSymbol = &ssSymbol; + + int iIndex = 0; + // if subscript is index + if (yyvsp[-1].val.sttType==STT_INDEX) { + // get the index + iIndex = yyvsp[-1].val.iIndex; + // if subscript is not index + } else { + // error + _pShell->ErrorF("Array subscript is not integral"); + } + // if the symbol is array + if (stType.st_sttType==STT_ARRAY) { + const ShellType &stBase = _shell_ast[stType.st_istBaseType]; + // if it is float or int array + if (stBase.st_sttType==STT_FLOAT || stBase.st_sttType==STT_INDEX) { + // if the index is out of range + if (iIndex<0 || iIndex>=stType.st_ctArraySize) { + _pShell->ErrorF("Array member out of range"); + fDummy = -666.0f; + yyval.lvLValue.lv_pvAddress = &fDummy; + } else { + // get its value and type + yyval.lvLValue.lv_sttType = stBase.st_sttType; + yyval.lvLValue.lv_pvAddress = (FLOAT*)ssSymbol.ss_pvValue+iIndex; + } + } + } else { + _pShell->ErrorF("'%s[]' doesn't have a value", yyvsp[-3].pssSymbol->ss_strName); + fDummy = -666.0f; + yyval.lvLValue.lv_pvAddress = &fDummy; + } +; + break;} +case 48: +#line 627 "engine/base/parser.y" +{ + yyval.arg.istType = ShellTypeNewFunction(ShellTypeNewVoid()); + ShellTypeAddFunctionArgument(yyval.arg.istType, ShellTypeNewVoid()); + yyval.arg.ctBytes = 0; +; + break;} +case 49: +#line 632 "engine/base/parser.y" +{ + yyval.arg = yyvsp[0].arg; +; + break;} +case 50: +#line 638 "engine/base/parser.y" +{ + yyval.arg.istType = ShellTypeNewFunction(ShellTypeNewVoid()); + ShellTypeAddFunctionArgument(yyval.arg.istType, ShellTypeNewByType(yyvsp[0].val.sttType)); + yyval.arg.ctBytes = PushExpression(yyvsp[0].val); +; + break;} +case 51: +#line 643 "engine/base/parser.y" +{ + yyval.arg = yyvsp[-2].arg; + ShellTypeAddFunctionArgument(yyval.arg.istType, ShellTypeNewByType(yyvsp[0].val.sttType)); + yyval.arg.ctBytes += PushExpression(yyvsp[0].val); +; + break;} +case 52: +#line 650 "engine/base/parser.y" +{ + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = yyvsp[0].val.fFloat; +; + break;} +case 53: +#line 654 "engine/base/parser.y" +{ + yyval.val.sttType = STT_INDEX; + yyval.val.iIndex = yyvsp[0].val.iIndex; +; + break;} +case 54: +#line 658 "engine/base/parser.y" +{ + yyval.val.sttType = STT_STRING; + yyval.val.strString = yyvsp[0].val.strString; +; + break;} +case 55: +#line 662 "engine/base/parser.y" +{ + // get its value + yyval.val.sttType = yyvsp[0].lvLValue.lv_sttType; + if (yyvsp[0].lvLValue.lv_sttType==STT_VOID) { + NOTHING; + } else if (yyvsp[0].lvLValue.lv_sttType==STT_FLOAT) { + yyval.val.fFloat = *(FLOAT*)yyvsp[0].lvLValue.lv_pvAddress; + } else if (yyvsp[0].lvLValue.lv_sttType==STT_INDEX) { + yyval.val.iIndex = *(INDEX*)yyvsp[0].lvLValue.lv_pvAddress; + } else if (yyvsp[0].lvLValue.lv_sttType==STT_STRING) { + yyval.val.strString = (const char*)*(CTString*)yyvsp[0].lvLValue.lv_pvAddress; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + _pShell->ErrorF("'%s' is of wrong type", yyvsp[0].lvLValue.lv_pssSymbol->ss_strName); + } +; + break;} +case 56: +#line 680 "engine/base/parser.y" +{ + + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[-2].val.iIndex<ErrorF("Wrong arguments for '<<'"); + yyval.val.sttType = STT_INDEX; + yyval.val.iIndex = -666; + } +; + break;} +case 57: +#line 693 "engine/base/parser.y" +{ + + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[-2].val.iIndex>>yyvsp[0].val.iIndex; + } else { + _pShell->ErrorF("Wrong arguments for '>>'"); + yyval.val.sttType = STT_INDEX; + yyval.val.iIndex = -666; + } +; + break;} +case 58: +#line 707 "engine/base/parser.y" +{ + + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_FLOAT) { + _pShell->ErrorF("'&' is illegal for FLOAT values"); + } else if (yyvsp[-2].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[-2].val.iIndex&yyvsp[0].val.iIndex; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } +; + break;} +case 59: +#line 721 "engine/base/parser.y" +{ + + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_FLOAT) { + _pShell->ErrorF("'|' is illegal for FLOAT values"); + } else if (yyvsp[-2].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[-2].val.iIndex|yyvsp[0].val.iIndex; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } +; + break;} +case 60: +#line 735 "engine/base/parser.y" +{ + + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_FLOAT) { + _pShell->ErrorF("'^' is illegal for FLOAT values"); + } else if (yyvsp[-2].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[-2].val.iIndex^yyvsp[0].val.iIndex; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } +; + break;} +case 61: +#line 751 "engine/base/parser.y" +{ + + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_FLOAT) { + _pShell->ErrorF("'&&' is illegal for FLOAT values"); + } else if (yyvsp[-2].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[-2].val.iIndex&&yyvsp[0].val.iIndex; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } +; + break;} +case 62: +#line 765 "engine/base/parser.y" +{ + + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_FLOAT) { + _pShell->ErrorF("'||' is illegal for FLOAT values"); + } else if (yyvsp[-2].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[-2].val.iIndex||yyvsp[0].val.iIndex; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } +; + break;} +case 63: +#line 780 "engine/base/parser.y" +{ + + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_FLOAT) { + yyval.val.fFloat = yyvsp[-2].val.fFloat+yyvsp[0].val.fFloat; + } else if (yyvsp[-2].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[-2].val.iIndex+yyvsp[0].val.iIndex; + } else if (yyvsp[-2].val.sttType == STT_STRING) { + CTString &strNew = _shell_astrTempStrings.Push(); + strNew = CTString(yyvsp[-2].val.strString)+yyvsp[0].val.strString; + yyval.val.strString = (const char*)strNew; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } +; + break;} +case 64: +#line 799 "engine/base/parser.y" +{ + + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_FLOAT) { + yyval.val.fFloat = yyvsp[-2].val.fFloat-yyvsp[0].val.fFloat; + } else if (yyvsp[-2].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[-2].val.iIndex-yyvsp[0].val.iIndex; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } +; + break;} +case 65: +#line 815 "engine/base/parser.y" +{ + + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_FLOAT) { + yyval.val.fFloat = yyvsp[-2].val.fFloat*yyvsp[0].val.fFloat; + } else if (yyvsp[-2].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[-2].val.iIndex*yyvsp[0].val.iIndex; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } + +; + break;} +case 66: +#line 831 "engine/base/parser.y" +{ + + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_FLOAT) { + yyval.val.fFloat = yyvsp[-2].val.fFloat/yyvsp[0].val.fFloat; + } else if (yyvsp[-2].val.sttType == STT_INDEX) { + if (yyvsp[0].val.iIndex==0) { + _pShell->ErrorF("Division by zero!\n"); + yyval.val.iIndex = 0; + } else { + yyval.val.iIndex = yyvsp[-2].val.iIndex/yyvsp[0].val.iIndex; + } + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } + +; + break;} +case 67: +#line 853 "engine/base/parser.y" +{ + MatchTypes(yyvsp[-2].val, yyvsp[0].val); + + yyval.val.sttType = yyvsp[-2].val.sttType; + if (yyvsp[-2].val.sttType == STT_FLOAT) { + _pShell->ErrorF("'%' is illegal for FLOAT values"); + } else if (yyvsp[-2].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[-2].val.iIndex%yyvsp[0].val.iIndex; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } + +; + break;} +case 68: +#line 869 "engine/base/parser.y" +{ + DoComparison(yyval.val, yyvsp[-2].val, yyvsp[0].val, '<'); +; + break;} +case 69: +#line 872 "engine/base/parser.y" +{ + DoComparison(yyval.val, yyvsp[-2].val, yyvsp[0].val, '>'); +; + break;} +case 70: +#line 875 "engine/base/parser.y" +{ + DoComparison(yyval.val, yyvsp[-2].val, yyvsp[0].val, '='); +; + break;} +case 71: +#line 878 "engine/base/parser.y" +{ + DoComparison(yyval.val, yyvsp[-2].val, yyvsp[0].val, '!'); +; + break;} +case 72: +#line 881 "engine/base/parser.y" +{ + DoComparison(yyval.val, yyvsp[-2].val, yyvsp[0].val, '}'); +; + break;} +case 73: +#line 884 "engine/base/parser.y" +{ + DoComparison(yyval.val, yyvsp[-2].val, yyvsp[0].val, '{'); +; + break;} +case 74: +#line 890 "engine/base/parser.y" +{ + yyval.val.sttType = yyvsp[0].val.sttType; + if (yyvsp[0].val.sttType == STT_FLOAT) { + yyval.val.fFloat = -yyvsp[0].val.fFloat; + } else if (yyvsp[0].val.sttType == STT_INDEX) { + yyval.val.iIndex = -yyvsp[0].val.iIndex; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } +; + break;} +case 75: +#line 904 "engine/base/parser.y" +{ + yyval.val.sttType = yyvsp[0].val.sttType; + if (yyvsp[0].val.sttType == STT_FLOAT) { + yyval.val.fFloat = yyvsp[0].val.fFloat; + } else if (yyvsp[0].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[0].val.iIndex; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } +; + break;} +case 76: +#line 916 "engine/base/parser.y" +{ + yyval.val.sttType = yyvsp[0].val.sttType; + if (yyvsp[0].val.sttType == STT_FLOAT) { + _pShell->ErrorF("'!' is illegal for FLOAT values"); + yyval.val.fFloat = yyvsp[0].val.fFloat; + } else if (yyvsp[0].val.sttType == STT_INDEX) { + yyval.val.iIndex = !yyvsp[0].val.iIndex; + } else { + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } +; + break;} +case 77: +#line 929 "engine/base/parser.y" +{ + yyval.val.sttType = STT_FLOAT; + if (yyvsp[0].val.sttType == STT_FLOAT) { + yyval.val.fFloat = yyvsp[0].val.fFloat; + } else if (yyvsp[0].val.sttType == STT_INDEX) { + yyval.val.fFloat = FLOAT(yyvsp[0].val.iIndex); + } else if (yyvsp[0].val.sttType == STT_STRING) { + yyval.val.fFloat = atof(yyvsp[0].val.strString); + } else { + _pShell->ErrorF("Cannot convert to FLOAT"); + yyval.val.sttType = STT_VOID; + } +; + break;} +case 78: +#line 943 "engine/base/parser.y" +{ + yyval.val.sttType = STT_INDEX; + if (yyvsp[0].val.sttType == STT_FLOAT) { + yyval.val.iIndex = INDEX(yyvsp[0].val.fFloat); + } else if (yyvsp[0].val.sttType == STT_INDEX) { + yyval.val.iIndex = yyvsp[0].val.iIndex; + } else if (yyvsp[0].val.sttType == STT_STRING) { + yyval.val.iIndex = atol(yyvsp[0].val.strString); + } else { + _pShell->ErrorF("Cannot convert to INDEX"); + yyval.val.sttType = STT_VOID; + } +; + break;} +case 79: +#line 957 "engine/base/parser.y" +{ + CTString &strNew = _shell_astrTempStrings.Push(); + yyval.val.sttType = STT_STRING; + if (yyvsp[0].val.sttType == STT_FLOAT) { + strNew.PrintF("%g", yyvsp[0].val.fFloat); + } else if (yyvsp[0].val.sttType == STT_INDEX) { + strNew.PrintF("%d", yyvsp[0].val.iIndex); + } else if (yyvsp[0].val.sttType == STT_STRING) { + strNew = yyvsp[0].val.strString; + } else { + _pShell->ErrorF("Cannot convert to CTString"); + yyval.val.sttType = STT_VOID; + } + yyval.val.strString = (const char*)strNew; +; + break;} +case 80: +#line 974 "engine/base/parser.y" +{ + // if the identifier is not declared + if (!yyvsp[-3].pssSymbol->IsDeclared()) { + // error + _pShell->ErrorF("Identifier '%s' is not declared", yyvsp[-3].pssSymbol->ss_strName); + // if the identifier is declared + } else { + // get its type + ShellType &stFunc = _shell_ast[yyvsp[-3].pssSymbol->ss_istType]; + + // if the identifier is a function + if (stFunc.st_sttType==STT_FUNCTION) { + // determine result type + ShellType &stResult = _shell_ast[stFunc.st_istBaseType]; + // match argument list result to that result + _shell_ast[_shell_ast[yyvsp[-1].arg.istType].st_istBaseType].st_sttType = stResult.st_sttType; + // if types are same + if (ShellTypeIsSame(yyvsp[-1].arg.istType, yyvsp[-3].pssSymbol->ss_istType)) { + +#define PUSHPARAMS \ + memcpy(_alloca(yyvsp[-1].arg.ctBytes), _ubStack+_iStack-yyvsp[-1].arg.ctBytes, yyvsp[-1].arg.ctBytes); + + // if void + if (stResult.st_sttType==STT_VOID) { + // just call the function + yyval.val.sttType = STT_VOID; + //PUSHPARAMS; + ((void (*)(void*))yyvsp[-3].pssSymbol->ss_pvValue)(_ubStack+_iStack-yyvsp[-1].arg.ctBytes); + // if index + } else if (stResult.st_sttType==STT_INDEX) { + // call the function and return result + yyval.val.sttType = STT_INDEX; + PUSHPARAMS; + yyval.val.iIndex = ((INDEX (*)(void))yyvsp[-3].pssSymbol->ss_pvValue)(); + // if float + } else if (stResult.st_sttType==STT_FLOAT) { + // call the function and return result + yyval.val.sttType = STT_FLOAT; + PUSHPARAMS; + yyval.val.fFloat = ((FLOAT (*)(void))yyvsp[-3].pssSymbol->ss_pvValue)(); + // if string + } else if (stResult.st_sttType==STT_STRING) { + // call the function and return result + yyval.val.sttType = STT_STRING; + CTString &strNew = _shell_astrTempStrings.Push(); + PUSHPARAMS; + strNew = ((CTString (*)(void))yyvsp[-3].pssSymbol->ss_pvValue)(); + yyval.val.strString = (const char*)strNew; + } else { + ASSERT(FALSE); + yyval.val.sttType = STT_FLOAT; + yyval.val.fFloat = -666.0f; + } + // if types are different + } else { + // error + yyval.val.sttType = STT_VOID; + _pShell->ErrorF("Wrong parameters for '%s'", yyvsp[-3].pssSymbol->ss_strName); + } + // if the identifier is something else + } else { + // error + yyval.val.sttType = STT_VOID; + _pShell->ErrorF("Can't call '%s'", yyvsp[-3].pssSymbol->ss_strName); + } + } + + // pop arguments and free type info + _iStack-=yyvsp[-1].arg.ctBytes; + ShellTypeDelete(yyvsp[-1].arg.istType); +; + break;} +case 81: +#line 1046 "engine/base/parser.y" +{ + yyval.val = yyvsp[-1].val; +; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 487 "bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 1051 "engine/base/parser.y" + diff --git a/Sources/Engine/Base/Parser.y b/Sources/Engine/Base/Parser.y new file mode 100644 index 0000000..1138ac4 --- /dev/null +++ b/Sources/Engine/Base/Parser.y @@ -0,0 +1,1051 @@ +%{ +#include "StdH.h" + +#include +#include +#include "ParsingSymbols.h" + +#include +#include + +%} + +%{ +#define YYERROR_VERBOSE 1 +// if error occurs in parsing +void yyerror(char *str) +{ + // just report the string + _pShell->ErrorF("%s", str); +}; + +static BOOL _bExecNextElse = FALSE; +FLOAT fDummy = -666.0f; + +static INDEX _iStack = 0; +static UBYTE _ubStack[1024]; + +INDEX PushExpression(value &v) +{ + if (v.sttType==STT_FLOAT) { + FLOAT f = v.fFloat; + memcpy(_ubStack+_iStack, &f, sizeof(f)); + _iStack+=sizeof(f); + return sizeof(f); + } else if (v.sttType==STT_INDEX) { + INDEX i = v.iIndex; + memcpy(_ubStack+_iStack, &i, sizeof(i)); + _iStack+=sizeof(i); + return sizeof(i); + } else if (v.sttType==STT_STRING) { + CTString &str = _shell_astrTempStrings.Push(); + str = v.strString; + CTString *pstr = &str; + memcpy(_ubStack+_iStack, &pstr, sizeof(pstr)); + _iStack+=sizeof(pstr); + return sizeof(pstr); + } else { + return 0; + } +} + +BOOL MatchTypes(value &v1, value &v2) +{ + if (v1.sttType==STT_FLOAT && v2.sttType==STT_FLOAT) { + return TRUE; + } else if (v1.sttType==STT_STRING && v2.sttType==STT_STRING) { + return TRUE; + } else if (v1.sttType==STT_INDEX && v2.sttType==STT_INDEX) { + return TRUE; + } else { + v1.sttType = STT_ILLEGAL; + v2.sttType = STT_ILLEGAL; + _pShell->ErrorF("Type mismatch"); + return FALSE; + } +} + +void Declaration( + ULONG ulQualifiers, INDEX istType, CShellSymbol &ssNew, + INDEX (*pPreFunc)(INDEX), void (*pPostFunc)(INDEX)) +{ + // if external + if (ulQualifiers&SSF_EXTERNAL) { + // get it a new value + if (_shell_ast[istType].st_sttType==STT_INDEX + ||_shell_ast[istType].st_sttType==STT_FLOAT) { + _pvNextToDeclare = &_shell_afExtFloats.Push(); + } else if (_shell_ast[istType].st_sttType==STT_STRING) { + _pvNextToDeclare = &_shell_astrExtStrings.Push(); + } else { + NOTHING; + } + } + + // if not parsing an external declaration + if (_pvNextToDeclare==NULL) { + // error + _pShell->ErrorF("Only external declarations are supported"); + return; + } + + // if the symbol is declared already + if (ssNew.IsDeclared()) { + // if the declaration is not identical + if (!ShellTypeIsSame(ssNew.ss_istType, istType) || + ((ssNew.ss_ulFlags&SSF_CONSTANT)!=(ulQualifiers&SSF_CONSTANT))) { + // error + _pShell->ErrorF("Symbol '%s' is already declared diferrently", ssNew.ss_strName); + return; + } + + // copy its value + if (_shell_ast[ssNew.ss_istType].st_sttType==STT_INDEX) { + *(INDEX*)_pvNextToDeclare = *(INDEX*)ssNew.ss_pvValue; + } else if (_shell_ast[ssNew.ss_istType].st_sttType==STT_FLOAT) { + *(FLOAT*)_pvNextToDeclare = *(FLOAT*)ssNew.ss_pvValue; + } else if (_shell_ast[ssNew.ss_istType].st_sttType==STT_STRING) { + *(CTString*)_pvNextToDeclare = *(CTString*)ssNew.ss_pvValue; + } else if (_shell_ast[ssNew.ss_istType].st_sttType==STT_ARRAY) { + NOTHING; // array values are not retained + } else if (_shell_ast[ssNew.ss_istType].st_sttType==STT_FUNCTION) { + NOTHING; // function values are not retained + } else { + // error + _pShell->ErrorF("'%s': old value couldn't be retained", ssNew.ss_strName); + return; + } + } + + // set the type to given type + if (!ssNew.IsDeclared()) { + ssNew.ss_istType = ShellTypeMakeDuplicate(istType); + } + // set the value for the external symbol if not already set + if (ssNew.ss_pvValue==NULL || !(ulQualifiers&SSF_EXTERNAL)) { + ssNew.ss_pvValue = _pvNextToDeclare; + } + // remember qualifiers (if already predeclared - keep old flags) + ssNew.ss_ulFlags |= ulQualifiers; + // remember pre and post functions + if (ssNew.ss_pPreFunc==NULL) { + ssNew.ss_pPreFunc = (BOOL (*)(void *))pPreFunc; + } + if (ssNew.ss_pPostFunc==NULL) { + ssNew.ss_pPostFunc = (void (*)(void *))pPostFunc; + } +} + +void DoComparison(value &vRes, value &v0, value &v1, int token) +{ + MatchTypes(v0, v1); + + vRes.sttType = STT_INDEX; + if (v0.sttType == STT_FLOAT) { + switch (token) { + case '<': vRes.iIndex = v0.fFloat ': vRes.iIndex = v0.fFloat >v1.fFloat; break; + case '=': vRes.iIndex = v0.fFloat==v1.fFloat; break; + case '!': vRes.iIndex = v0.fFloat!=v1.fFloat; break; + case '}': vRes.iIndex = v0.fFloat>=v1.fFloat; break; + case '{': vRes.iIndex = v0.fFloat<=v1.fFloat; break; + default: ASSERT(FALSE); + vRes.sttType = STT_INDEX; + vRes.iIndex = 0; + } + } else if (v0.sttType == STT_INDEX) { + switch (token) { + case '<': vRes.iIndex = v0.iIndex ': vRes.iIndex = v0.iIndex >v1.iIndex; break; + case '=': vRes.iIndex = v0.iIndex==v1.iIndex; break; + case '!': vRes.iIndex = v0.iIndex!=v1.iIndex; break; + case '}': vRes.iIndex = v0.iIndex>=v1.iIndex; break; + case '{': vRes.iIndex = v0.iIndex<=v1.iIndex; break; + default: ASSERT(FALSE); + vRes.sttType = STT_INDEX; + vRes.iIndex = 0; + } + } else if (v0.sttType == STT_STRING) { + switch (token) { + case '<': vRes.iIndex = stricmp(v0.strString, v1.strString) < 0; break; + case '>': vRes.iIndex = stricmp(v0.strString, v1.strString) > 0; break; + case '=': vRes.iIndex = stricmp(v0.strString, v1.strString) == 0; break; + case '!': vRes.iIndex = stricmp(v0.strString, v1.strString) != 0; break; + case '}': vRes.iIndex = stricmp(v0.strString, v1.strString) >= 0; break; + case '{': vRes.iIndex = stricmp(v0.strString, v1.strString) <= 0; break; + default: ASSERT(FALSE); + vRes.sttType = STT_INDEX; + vRes.iIndex = 0; + } + } else { + vRes.sttType = STT_INDEX; + vRes.iIndex = 0; + } +} +%} + +/* BISON Declarations */ + +// we need to be reentrant! +%pure_parser + +%union { + value val; // for constants and expressions + arguments arg; // for function input arguments + ULONG ulFlags; // for declaration qualifiers + INDEX istType; // for types + CShellSymbol *pssSymbol; // for symbols + struct LValue lvLValue; + INDEX (*pPreFunc)(INDEX); // pre-set function for a variable + void (*pPostFunc)(INDEX); // post-set function for a variable +} + +%{ + extern int yylex(YYSTYPE *lvalp); +%} + +%token c_float +%token c_int +%token c_string +%token c_char + +%token identifier + +%token k_INDEX +%token k_FLOAT +%token k_CTString +%token k_void +%token k_const +%token k_user +%token k_persistent +%token k_extern +%token k_pre +%token k_post +%token k_help +%token k_if +%token k_else +%token k_else_if +%token SHL +%token SHR +%token EQ +%token NEQ +%token GEQ +%token LEQ +%token LOGAND +%token LOGOR +%token block_beg +%token block_end + +%type lvalue +%type expression +%type declaration_qualifiers +%type opt_string +%type type_specifier +%type parameter_list +%type parameter_list_opt +%type pre_func_opt +%type post_func_opt +%type argument_expression_list_opt +%type argument_expression_list + +%right '=' +%left LOGAND LOGOR +%left '&' '^' '|' +%left '<' '>' EQ NEQ LEQ GEQ +%left SHL +%left SHR +%left '-' '+' +%left '*' '/' '%' +%left TYPECAST +%left SIGN '!' + +%start program + +%% + +/*///////////////////////////////////////////////////////// + * Global structure of the source file. + */ +program +: declaration +| statements +; + +block +: block_beg statements block_end +| block_beg statements block_end +; + +statements +: /* null */ +| statement statements +; + +declaration_qualifiers +: /* nothing */ { + $$ = 0; +} +| declaration_qualifiers k_const { + $$ = $1 | SSF_CONSTANT; +} +| declaration_qualifiers k_user { + $$ = $1 | SSF_USER; +} +| declaration_qualifiers k_persistent { + $$ = $1 | SSF_PERSISTENT; +} +| declaration_qualifiers k_extern { + $$ = $1 | SSF_EXTERNAL; +} + +opt_string +: /* nothing */ { + $$.strString = ""; +} +| c_string { + // !!!! remove this option + //_pShell->ErrorF("Warning: symbol comments are not supported"); + $$.strString = $1.strString; +} + +type_specifier +: k_FLOAT { + $$ = ShellTypeNewFloat(); +} +| k_INDEX { + $$ = ShellTypeNewIndex(); +} +| k_CTString { + $$ = ShellTypeNewString(); +} +| k_void { + $$ = ShellTypeNewVoid(); +} + +pre_func_opt +: { + $$ = NULL; +} +| k_pre ':' identifier { + if (_shell_ast[$3->ss_istType].st_sttType!=STT_FUNCTION + ||_shell_ast[_shell_ast[$3->ss_istType].st_istBaseType].st_sttType!=STT_INDEX + ||_shell_ast[$3->ss_istType].st_istFirstArgument!=_shell_ast[$3->ss_istType].st_istLastArgument + ||_shell_ast[_shell_ast[$3->ss_istType].st_istFirstArgument].st_sttType!=STT_INDEX) { + _pShell->ErrorF("'%s' must return 'INDEX' and take 'INDEX' as input", $3->ss_strName); + } else { + void *pv = $3->ss_pvValue; + $$ = (INDEX(*)(INDEX))$3->ss_pvValue; + } +} + +post_func_opt +: { + $$ = NULL; +} +| k_post ':' identifier { + if (_shell_ast[$3->ss_istType].st_sttType!=STT_FUNCTION + ||_shell_ast[_shell_ast[$3->ss_istType].st_istBaseType].st_sttType!=STT_VOID + ||_shell_ast[$3->ss_istType].st_istFirstArgument!=_shell_ast[$3->ss_istType].st_istLastArgument + ||_shell_ast[_shell_ast[$3->ss_istType].st_istFirstArgument].st_sttType!=STT_INDEX) { + _pShell->ErrorF("'%s' must return 'void' and take 'INDEX' as input", $3->ss_strName); + } else { + $$ = (void(*)(INDEX))$3->ss_pvValue; + } +} +; + +parameter_list_opt +: /* nothing */ { + $$ = ShellTypeNewFunction(0); + ShellTypeAddFunctionArgument($$, ShellTypeNewVoid()); +} +| parameter_list { + $$ = $1; +} +; + +parameter_list +: type_specifier { + $$ = ShellTypeNewFunction(0); + ShellTypeAddFunctionArgument($$, $1); +} +/*| identifier type_specifier { + $$ = ShellTypeNewFunction(0); + ShellTypeAddFunctionArgument($$, $2); +}*/ +| parameter_list ',' type_specifier { + $$ = $1; + ShellTypeAddFunctionArgument($$, $3); +} +/*| parameter_list ',' identifier type_specifier { + $$ = $1; + ShellTypeAddFunctionArgument($$, $4); +} */ +; + +declaration +: declaration_qualifiers type_specifier identifier pre_func_opt post_func_opt opt_string ';' { + Declaration($1, $2, *$3, $4, $5); + ShellTypeDelete($2); +} +| declaration_qualifiers type_specifier identifier '(' parameter_list_opt ')' opt_string ';' { + // take function from the parameter list and set its return type + _shell_ast[$5].st_istBaseType = $2; + $2 = $5; + // declare it + Declaration($1, $2, *$3, NULL, NULL); + // free the type (declaration will make a copy) + ShellTypeDelete($2); +} +| declaration_qualifiers type_specifier identifier '[' expression ']' pre_func_opt post_func_opt opt_string ';' { + if ($5.sttType!=STT_INDEX) { + _pShell->ErrorF("Array size is not integral"); + } + $2 = ShellTypeNewArray($2, $5.iIndex); + Declaration($1, $2, *$3, NULL, NULL); + ShellTypeDelete($2); +} + +statement +: ';' { + // dummy +} +| block { + // dummy +} +| expression ';' { + // print its value + if ($1.sttType == STT_VOID) { + NOTHING; + } else if ($1.sttType == STT_FLOAT) { + CPrintF("%g\n", $1.fFloat); + } else if ($1.sttType == STT_STRING) { + CPrintF("\"%s\"\n", $1.strString); + } else if ($1.sttType == STT_INDEX) { + CPrintF("%d(0x%08X)\n", $1.iIndex, $1.iIndex); + } else { + _pShell->ErrorF("Expression cannot be printed"); + } +} +| lvalue '=' expression ';' { + // if it is constant + if ($1.lv_pssSymbol->ss_ulFlags&SSF_CONSTANT) { + _pShell->ErrorF("Symbol '%s' is a constant", $1.lv_pssSymbol->ss_strName); + // if it is not constant + } else { + // if it can be changed + if ($1.lv_pssSymbol->ss_pPreFunc==NULL || $1.lv_pssSymbol->ss_pPreFunc($1.lv_pvAddress)) { + // if floats + if ($1.lv_sttType == STT_FLOAT && $3.sttType==STT_FLOAT) { + // assign value + *(FLOAT*)$1.lv_pvAddress = $3.fFloat; + // if indices + } else if ($1.lv_sttType == STT_INDEX && $3.sttType==STT_INDEX) { + // assign value + *(INDEX*)$1.lv_pvAddress = $3.iIndex; + + // if strings + } else if ($1.lv_sttType == STT_STRING && $3.sttType==STT_STRING) { + // assign value + *(CTString*)$1.lv_pvAddress = $3.strString; + + // if assigning index to float + } else if ($1.lv_sttType == STT_FLOAT && $3.sttType==STT_INDEX) { + *(FLOAT*)$1.lv_pvAddress = $3.iIndex; + // otherwise + } else { + // error + _pShell->ErrorF("Cannot assign: different types"); + } + + // call post-change function + if ($1.lv_pssSymbol->ss_pPostFunc!=NULL) { + $1.lv_pssSymbol->ss_pPostFunc($1.lv_pvAddress); + } + } + } +} +| declaration_qualifiers type_specifier identifier '=' expression ';' { + Declaration($1, $2, *$3, NULL, NULL); + ShellTypeDelete($2); + + CShellSymbol &ssSymbol = *$3; + // if it is constant + if (ssSymbol.ss_ulFlags&SSF_CONSTANT) { + // error + _pShell->ErrorF("Symbol '%s' is a constant", ssSymbol.ss_strName); + } + + // get symbol type + ShellTypeType stt = _shell_ast[$2].st_sttType; + + // if floats + if (stt == STT_FLOAT && $5.sttType==STT_FLOAT) { + // assign value + *(FLOAT*)ssSymbol.ss_pvValue = $5.fFloat; + // if indices + } else if (stt == STT_INDEX && $5.sttType==STT_INDEX) { + // assign value + *(INDEX*)ssSymbol.ss_pvValue = $5.iIndex; + // if strings + } else if (stt == STT_STRING && $5.sttType==STT_STRING) { + // assign value + *(CTString*)ssSymbol.ss_pvValue = $5.strString; + // !!!! remove this conversion + } else if (stt == STT_FLOAT && $5.sttType==STT_INDEX) { + _pShell->ErrorF("Warning: assigning INDEX to FLOAT!"); + *(FLOAT*)ssSymbol.ss_pvValue = $5.iIndex; + } else { + _pShell->ErrorF("Symbol '%s' and its initializer have different types", ssSymbol.ss_strName); + } +} +| k_help identifier { +extern void PrintShellSymbolHelp(const CTString &strSymbol); + PrintShellSymbolHelp($2->ss_strName); +} +| k_help identifier '(' ')' { +extern void PrintShellSymbolHelp(const CTString &strSymbol); + PrintShellSymbolHelp($2->ss_strName); +} +| k_help identifier '[' ']' { +extern void PrintShellSymbolHelp(const CTString &strSymbol); + PrintShellSymbolHelp($2->ss_strName); +} +| k_if '(' expression ')' { + _bExecNextBlock = FALSE; + if ($3.sttType == STT_INDEX) { + _bExecNextBlock = $3.iIndex!=0; + } else if ($3.sttType == STT_FLOAT) { + _bExecNextBlock = $3.fFloat!=0; + } else { + _pShell->ErrorF("If expression is not integral"); + } + $1 = _bExecNextBlock; +} block { + _bExecNextElse = !$1; + _bExecNextBlock = TRUE; +} opt_else +; + +opt_else +: /* nothing */ + +| k_else_if '(' expression ')' { + if (_bExecNextElse) { + _bExecNextBlock = FALSE; + if ($3.sttType == STT_INDEX) { + _bExecNextBlock = $3.iIndex!=0; + } else if ($3.sttType == STT_FLOAT) { + _bExecNextBlock = $3.fFloat!=0; + } else { + _pShell->ErrorF("If expression is not integral"); + } + $1 = _bExecNextBlock; + } else { + _bExecNextBlock = FALSE; + _bExecNextElse = FALSE; + $1 = TRUE; + } +} block { + _bExecNextElse = !$1; + _bExecNextBlock = TRUE; +} opt_else + +| k_else { + _bExecNextBlock = _bExecNextElse; +} block { + _bExecNextBlock = TRUE; +} +; + +lvalue +: identifier { + CShellSymbol &ssSymbol = *$1; + const ShellType &stType = _shell_ast[ssSymbol.ss_istType]; + + $$.lv_pssSymbol = &ssSymbol; + if (!ssSymbol.IsDeclared()) { + // error + _pShell->ErrorF("Identifier '%s' is not declared", $1->ss_strName); + fDummy = -666; + $$.lv_sttType = STT_VOID; + $$.lv_pvAddress = &fDummy; + // if the identifier is a float, int or string + } else if (stType.st_sttType==STT_FLOAT || stType.st_sttType==STT_INDEX || stType.st_sttType==STT_STRING) { + // get its value and type + $$.lv_sttType = stType.st_sttType; + $$.lv_pvAddress = ssSymbol.ss_pvValue; + // if the identifier is something else + } else { + // error + _pShell->ErrorF("'%s' doesn't have a value", $1->ss_strName); + fDummy = -666.0f; + $$.lv_sttType = STT_VOID; + $$.lv_pvAddress = &fDummy; + } +} +| identifier '[' expression ']' { + CShellSymbol &ssSymbol = *$1; + const ShellType &stType = _shell_ast[ssSymbol.ss_istType]; + $$.lv_pssSymbol = &ssSymbol; + + int iIndex = 0; + // if subscript is index + if ($3.sttType==STT_INDEX) { + // get the index + iIndex = $3.iIndex; + // if subscript is not index + } else { + // error + _pShell->ErrorF("Array subscript is not integral"); + } + // if the symbol is array + if (stType.st_sttType==STT_ARRAY) { + const ShellType &stBase = _shell_ast[stType.st_istBaseType]; + // if it is float or int array + if (stBase.st_sttType==STT_FLOAT || stBase.st_sttType==STT_INDEX) { + // if the index is out of range + if (iIndex<0 || iIndex>=stType.st_ctArraySize) { + _pShell->ErrorF("Array member out of range"); + fDummy = -666.0f; + $$.lv_pvAddress = &fDummy; + } else { + // get its value and type + $$.lv_sttType = stBase.st_sttType; + $$.lv_pvAddress = (FLOAT*)ssSymbol.ss_pvValue+iIndex; + } + } + } else { + _pShell->ErrorF("'%s[]' doesn't have a value", $1->ss_strName); + fDummy = -666.0f; + $$.lv_pvAddress = &fDummy; + } +} +; + +argument_expression_list_opt +: /* nothing */ { + $$.istType = ShellTypeNewFunction(ShellTypeNewVoid()); + ShellTypeAddFunctionArgument($$.istType, ShellTypeNewVoid()); + $$.ctBytes = 0; +} +| argument_expression_list { + $$ = $1; +} +; + +argument_expression_list +: expression { + $$.istType = ShellTypeNewFunction(ShellTypeNewVoid()); + ShellTypeAddFunctionArgument($$.istType, ShellTypeNewByType($1.sttType)); + $$.ctBytes = PushExpression($1); +} +| argument_expression_list ',' expression { + $$ = $1; + ShellTypeAddFunctionArgument($$.istType, ShellTypeNewByType($3.sttType)); + $$.ctBytes += PushExpression($3); +} + +expression +: c_float { + $$.sttType = STT_FLOAT; + $$.fFloat = $1.fFloat; +} +| c_int { + $$.sttType = STT_INDEX; + $$.iIndex = $1.iIndex; +} +| c_string { + $$.sttType = STT_STRING; + $$.strString = $1.strString; +} +| lvalue { + // get its value + $$.sttType = $1.lv_sttType; + if ($1.lv_sttType==STT_VOID) { + NOTHING; + } else if ($1.lv_sttType==STT_FLOAT) { + $$.fFloat = *(FLOAT*)$1.lv_pvAddress; + } else if ($1.lv_sttType==STT_INDEX) { + $$.iIndex = *(INDEX*)$1.lv_pvAddress; + } else if ($1.lv_sttType==STT_STRING) { + $$.strString = (const char*)*(CTString*)$1.lv_pvAddress; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + _pShell->ErrorF("'%s' is of wrong type", $1.lv_pssSymbol->ss_strName); + } +} +/* shift */ +| expression SHL expression { + + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_INDEX) { + $$.iIndex = $1.iIndex<<$3.iIndex; + } else { + _pShell->ErrorF("Wrong arguments for '<<'"); + $$.sttType = STT_INDEX; + $$.iIndex = -666; + } +} +| expression SHR expression { + + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_INDEX) { + $$.iIndex = $1.iIndex>>$3.iIndex; + } else { + _pShell->ErrorF("Wrong arguments for '>>'"); + $$.sttType = STT_INDEX; + $$.iIndex = -666; + } +} +/* bitwise operators */ +| expression '&' expression { + + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_FLOAT) { + _pShell->ErrorF("'&' is illegal for FLOAT values"); + } else if ($1.sttType == STT_INDEX) { + $$.iIndex = $1.iIndex&$3.iIndex; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } +} +| expression '|' expression { + + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_FLOAT) { + _pShell->ErrorF("'|' is illegal for FLOAT values"); + } else if ($1.sttType == STT_INDEX) { + $$.iIndex = $1.iIndex|$3.iIndex; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } +} +| expression '^' expression { + + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_FLOAT) { + _pShell->ErrorF("'^' is illegal for FLOAT values"); + } else if ($1.sttType == STT_INDEX) { + $$.iIndex = $1.iIndex^$3.iIndex; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } +} + +/* logical operators */ +| expression LOGAND expression { + + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_FLOAT) { + _pShell->ErrorF("'&&' is illegal for FLOAT values"); + } else if ($1.sttType == STT_INDEX) { + $$.iIndex = $1.iIndex&&$3.iIndex; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } +} +| expression LOGOR expression { + + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_FLOAT) { + _pShell->ErrorF("'||' is illegal for FLOAT values"); + } else if ($1.sttType == STT_INDEX) { + $$.iIndex = $1.iIndex||$3.iIndex; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } +} +/* addition */ +| expression '+' expression { + + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_FLOAT) { + $$.fFloat = $1.fFloat+$3.fFloat; + } else if ($1.sttType == STT_INDEX) { + $$.iIndex = $1.iIndex+$3.iIndex; + } else if ($1.sttType == STT_STRING) { + CTString &strNew = _shell_astrTempStrings.Push(); + strNew = CTString($1.strString)+$3.strString; + $$.strString = (const char*)strNew; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } +} +/* substraction */ +| expression '-' expression { + + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_FLOAT) { + $$.fFloat = $1.fFloat-$3.fFloat; + } else if ($1.sttType == STT_INDEX) { + $$.iIndex = $1.iIndex-$3.iIndex; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } +} + +/* multiplication */ +| expression '*' expression { + + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_FLOAT) { + $$.fFloat = $1.fFloat*$3.fFloat; + } else if ($1.sttType == STT_INDEX) { + $$.iIndex = $1.iIndex*$3.iIndex; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } + +} +/* division */ +| expression '/' expression { + + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_FLOAT) { + $$.fFloat = $1.fFloat/$3.fFloat; + } else if ($1.sttType == STT_INDEX) { + if ($3.iIndex==0) { + _pShell->ErrorF("Division by zero!\n"); + $$.iIndex = 0; + } else { + $$.iIndex = $1.iIndex/$3.iIndex; + } + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } + +} + +/* modulo */ +| expression '%' expression { + MatchTypes($1, $3); + + $$.sttType = $1.sttType; + if ($1.sttType == STT_FLOAT) { + _pShell->ErrorF("'%' is illegal for FLOAT values"); + } else if ($1.sttType == STT_INDEX) { + $$.iIndex = $1.iIndex%$3.iIndex; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } + +} + +/* comparisons */ +| expression '<' expression { + DoComparison($$, $1, $3, '<'); +} +| expression '>' expression { + DoComparison($$, $1, $3, '>'); +} +| expression EQ expression { + DoComparison($$, $1, $3, '='); +} +| expression NEQ expression { + DoComparison($$, $1, $3, '!'); +} +| expression GEQ expression { + DoComparison($$, $1, $3, '}'); +} +| expression LEQ expression { + DoComparison($$, $1, $3, '{'); +} + +// unary minus + +| '-' expression %prec SIGN { + $$.sttType = $2.sttType; + if ($2.sttType == STT_FLOAT) { + $$.fFloat = -$2.fFloat; + } else if ($2.sttType == STT_INDEX) { + $$.iIndex = -$2.iIndex; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } +} + +// unary plus + +| '+' expression %prec SIGN { + $$.sttType = $2.sttType; + if ($2.sttType == STT_FLOAT) { + $$.fFloat = $2.fFloat; + } else if ($2.sttType == STT_INDEX) { + $$.iIndex = $2.iIndex; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } +} + +| '!' expression %prec SIGN { + $$.sttType = $2.sttType; + if ($2.sttType == STT_FLOAT) { + _pShell->ErrorF("'!' is illegal for FLOAT values"); + $$.fFloat = $2.fFloat; + } else if ($2.sttType == STT_INDEX) { + $$.iIndex = !$2.iIndex; + } else { + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } +} + +| '(' k_FLOAT ')' expression %prec TYPECAST { + $$.sttType = STT_FLOAT; + if ($4.sttType == STT_FLOAT) { + $$.fFloat = $4.fFloat; + } else if ($4.sttType == STT_INDEX) { + $$.fFloat = FLOAT($4.iIndex); + } else if ($4.sttType == STT_STRING) { + $$.fFloat = atof($4.strString); + } else { + _pShell->ErrorF("Cannot convert to FLOAT"); + $$.sttType = STT_VOID; + } +} + +| '(' k_INDEX ')' expression %prec TYPECAST { + $$.sttType = STT_INDEX; + if ($4.sttType == STT_FLOAT) { + $$.iIndex = INDEX($4.fFloat); + } else if ($4.sttType == STT_INDEX) { + $$.iIndex = $4.iIndex; + } else if ($4.sttType == STT_STRING) { + $$.iIndex = atol($4.strString); + } else { + _pShell->ErrorF("Cannot convert to INDEX"); + $$.sttType = STT_VOID; + } +} + +| '(' k_CTString ')' expression %prec TYPECAST { + CTString &strNew = _shell_astrTempStrings.Push(); + $$.sttType = STT_STRING; + if ($4.sttType == STT_FLOAT) { + strNew.PrintF("%g", $4.fFloat); + } else if ($4.sttType == STT_INDEX) { + strNew.PrintF("%d", $4.iIndex); + } else if ($4.sttType == STT_STRING) { + strNew = $4.strString; + } else { + _pShell->ErrorF("Cannot convert to CTString"); + $$.sttType = STT_VOID; + } + $$.strString = (const char*)strNew; +} + +// function call +| identifier '(' argument_expression_list_opt ')' { + // if the identifier is not declared + if (!$1->IsDeclared()) { + // error + _pShell->ErrorF("Identifier '%s' is not declared", $1->ss_strName); + // if the identifier is declared + } else { + // get its type + ShellType &stFunc = _shell_ast[$1->ss_istType]; + + // if the identifier is a function + if (stFunc.st_sttType==STT_FUNCTION) { + // determine result type + ShellType &stResult = _shell_ast[stFunc.st_istBaseType]; + // match argument list result to that result + _shell_ast[_shell_ast[$3.istType].st_istBaseType].st_sttType = stResult.st_sttType; + // if types are same + if (ShellTypeIsSame($3.istType, $1->ss_istType)) { + +#define PUSHPARAMS \ + memcpy(_alloca($3.ctBytes), _ubStack+_iStack-$3.ctBytes, $3.ctBytes); + + // if void + if (stResult.st_sttType==STT_VOID) { + // just call the function + $$.sttType = STT_VOID; + //PUSHPARAMS; + ((void (*)(void*))$1->ss_pvValue)(_ubStack+_iStack-$3.ctBytes); + // if index + } else if (stResult.st_sttType==STT_INDEX) { + // call the function and return result + $$.sttType = STT_INDEX; + PUSHPARAMS; + $$.iIndex = ((INDEX (*)(void))$1->ss_pvValue)(); + // if float + } else if (stResult.st_sttType==STT_FLOAT) { + // call the function and return result + $$.sttType = STT_FLOAT; + PUSHPARAMS; + $$.fFloat = ((FLOAT (*)(void))$1->ss_pvValue)(); + // if string + } else if (stResult.st_sttType==STT_STRING) { + // call the function and return result + $$.sttType = STT_STRING; + CTString &strNew = _shell_astrTempStrings.Push(); + PUSHPARAMS; + strNew = ((CTString (*)(void))$1->ss_pvValue)(); + $$.strString = (const char*)strNew; + } else { + ASSERT(FALSE); + $$.sttType = STT_FLOAT; + $$.fFloat = -666.0f; + } + // if types are different + } else { + // error + $$.sttType = STT_VOID; + _pShell->ErrorF("Wrong parameters for '%s'", $1->ss_strName); + } + // if the identifier is something else + } else { + // error + $$.sttType = STT_VOID; + _pShell->ErrorF("Can't call '%s'", $1->ss_strName); + } + } + + // pop arguments and free type info + _iStack-=$3.ctBytes; + ShellTypeDelete($3.istType); +} +// brackets +| '(' expression ')' { + $$ = $2; +} +; + +%% diff --git a/Sources/Engine/Base/ParsingSymbols.h b/Sources/Engine/Base/ParsingSymbols.h new file mode 100644 index 0000000..f9ec8a2 --- /dev/null +++ b/Sources/Engine/Base/ParsingSymbols.h @@ -0,0 +1,96 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include +#include + +// needed for parser and scanner +#define alloca _alloca +extern void yyerror(char *s); +extern int yyparse(void); + +typedef struct yy_buffer_state *YY_BUFFER_STATE; +YY_BUFFER_STATE yy_scan_string(const char *str); +void yy_delete_buffer(YY_BUFFER_STATE b); + +// declarations for recursive shell script parsing +#define SHELL_MAX_INCLUDE_LEVEL 64 // this is both for includes _and_ nested parsing! + +extern int _bExecNextBlock; + +#define YY_NEVER_INTERACTIVE 1 + +// used for communication between CShell and parser +// value for declaring external symbol (defined in exe or dll code) +extern void *_pvNextToDeclare; + +extern const char * _shell_strFileName; +// temporary values for parsing +extern CDynamicStackArray _shell_astrTempStrings; +// values for extern declarations +extern CDynamicStackArray _shell_astrExtStrings; +extern CDynamicStackArray _shell_afExtFloats; + + +// all types are allocated here +extern CAllocationArray _shell_ast; +extern INDEX _shell_istUndeclared; + +// make a new type for a basic type +INDEX ShellTypeNewVoid(void); +INDEX ShellTypeNewIndex(void); +INDEX ShellTypeNewFloat(void); +INDEX ShellTypeNewString(void); +INDEX ShellTypeNewByType(enum ShellTypeType stt); + +// make a new pointer type +INDEX ShellTypeNewPointer(INDEX istBaseType); +// make a new array type +INDEX ShellTypeNewArray(INDEX istMemberType, int iArraySize); +// make a new function type +INDEX ShellTypeNewFunction(INDEX istReturnType); + +// add an argument to a function from the left +void ShellTypeAddFunctionArgument(INDEX istFunction, INDEX istArgument); + +// make a copy of a type tree +INDEX ShellTypeMakeDuplicate(INDEX istOriginal); + +// compare two types +BOOL ShellTypeIsSame(INDEX ist1, INDEX ist2); + +// delete an entire type tree +void ShellTypeDelete(INDEX istToDelete); + +// print c-like syntax description of the type +char *ShellTypeSPrintF(char *strDestination, char *strDeclarator, INDEX istToPrint); + +BOOL ShellTypeIsPointer(INDEX ist); +BOOL ShellTypeIsArray(INDEX ist); +BOOL ShellTypeIsIntegral(INDEX ist); + +struct LValue { + enum ShellTypeType lv_sttType; + CShellSymbol *lv_pssSymbol; + void *lv_pvAddress; +}; + +struct value { + enum ShellTypeType sttType; + float fFloat; // for float constants + INDEX iIndex; // for index constants + const char *strString; // for string constants +}; + +struct arguments { + INDEX istType; // type of arguments + INDEX ctBytes; // total number of bytes taken by arguments on stack +}; + +void ShellPushBuffer(const char *strName, const char *strBuffer, BOOL bParserEnd); +BOOL ShellPopBuffer(void); +const char *ShellGetBufferName(void); +int ShellGetBufferLineNumber(void); +const char *ShellGetBufferContents(void); +int ShellGetBufferStackDepth(void); + +void ShellCountOneLine(void); diff --git a/Sources/Engine/Base/Priority.inl b/Sources/Engine/Base/Priority.inl new file mode 100644 index 0000000..7f90861 --- /dev/null +++ b/Sources/Engine/Base/Priority.inl @@ -0,0 +1,24 @@ +class CSetPriority { +public: + DWORD sp_dwProcessOld; + int sp_iThreadOld; + HANDLE sp_hThread; + HANDLE sp_hProcess; + CSetPriority(DWORD dwProcess, int iThread) + { + sp_hProcess = GetCurrentProcess(); + sp_hThread = GetCurrentThread(); + + sp_dwProcessOld = GetPriorityClass(sp_hProcess); + sp_iThreadOld = GetThreadPriority(sp_hThread); + BOOL bSuccessProcess = SetPriorityClass(sp_hProcess, dwProcess); + BOOL bSuccessThread = SetThreadPriority(sp_hThread, iThread); + ASSERT(bSuccessProcess && bSuccessThread); + } + ~CSetPriority(void) + { + BOOL bSuccessProcess = SetPriorityClass(sp_hProcess, sp_dwProcessOld); + BOOL bSuccessThread = SetThreadPriority(sp_hThread, sp_iThreadOld); + ASSERT(bSuccessProcess && bSuccessThread); + } +}; diff --git a/Sources/Engine/Base/Profiling.cpp b/Sources/Engine/Base/Profiling.cpp new file mode 100644 index 0000000..f2ef4ac --- /dev/null +++ b/Sources/Engine/Base/Profiling.cpp @@ -0,0 +1,358 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +template CStaticArray; +template CStaticArray; + + +static inline __int64 ReadTSC_profile(void) +{ + __int64 mmRet; + __asm { + rdtsc + mov dword ptr [mmRet+0],eax + mov dword ptr [mmRet+4],edx + } + return mmRet; +} + + +///////////////////////////////////////////////////////////////////// +// CProfileForm +// how much it takes to start a profiling timer +CTimerValue _tvStartEpsilon; +// how much it takes to stop a profiling timer +CTimerValue _tvStopEpsilon; +// how much it takes to just start and stop a profiling timer (measure zero time) +CTimerValue _tvStartStopEpsilon; + +// total sum of all timing offsets induced by all Starts and Stops so far +CTimerValue _tvCurrentProfilingEpsilon; + +// Measure profiling errors and set epsilon corrections. +static CTimerValue _tvTest; +void CProfileForm::CalibrateProfilingTimers(void) +{ + enum Epsilons { + ETI_TOTAL, + ETI_STARTSTOP, + ETI_START, + ETI_STOP, + ETI_DUMMY, + ETI_COUNT + }; + + CProfileForm pfCalibration("", "", 0, ETI_COUNT); + // set all epsilons to zero, so that they don't interfere with the measuring + _tvStartEpsilon.Clear(); + _tvStopEpsilon.Clear(); + _tvStartStopEpsilon.Clear(); + _tvCurrentProfilingEpsilon.Clear(); + + /* NOTE: we must use one more counter (ETI_TOTAL), so that we don't overestimate + * time spent in StartTimer(), StopTimer() if it is the first timer started. + */ + +#define REPEATCOUNT 10000 + // measure how much it takes to start and stop timer + __int64 llMinStartStopTime(0x7fffffffffffffff); + {for (INDEX i=0; ipt_tvElapsed.Clear(); + itpt->pt_tvStarted.tv_llValue = -__int64(1); + itpt->pt_ctAveraging = 0; + } +} + +void CProfileForm::Clear(void) +{ + pf_strTitle.Clear(); + pf_strAveragingUnits.Clear(); + + pf_apcCounters.Clear(); + pf_aptTimers.Clear(); +} + +/* + * Get name of a counter. + */ +const CTString &CProfileForm::GetCounterName(INDEX iCounter) +{ + return pf_apcCounters[iCounter].pc_strName; +} + +/* + * Get name of a timer. + */ +const CTString &CProfileForm::GetTimerName(INDEX iTimer) +{ + return pf_aptTimers[iTimer].pt_strName; +} + +/* Start a timer. */ +void CProfileForm::StartTimer_internal(INDEX iTimer) +{ + CProfileTimer &pt = pf_aptTimers[iTimer]; + //ASSERT(pt.pt_tvStarted.tv_llValue<0); + CTimerValue tvNow = CTimerValue(ReadTSC_profile())-_tvCurrentProfilingEpsilon; + pt.pt_tvStarted = tvNow; + pf_ctRunningTimers++; + if (pf_ctRunningTimers==1) { + pf_tvOverAllStarted = tvNow; + } + _tvCurrentProfilingEpsilon += _tvStartEpsilon; +} + +/* Stop a timer. */ +void CProfileForm::StopTimer_internal(INDEX iTimer) +{ + CProfileTimer &pt = pf_aptTimers[iTimer]; + //ASSERT(pt.pt_tvStarted.tv_llValue>0); + CTimerValue tvNow = CTimerValue(ReadTSC_profile())-_tvCurrentProfilingEpsilon; + pt.pt_tvElapsed += + tvNow - pf_aptTimers[iTimer].pt_tvStarted - _tvStartStopEpsilon + _tvStartEpsilon; + pf_ctRunningTimers--; + if (pf_ctRunningTimers==0) { + pf_tvOverAllElapsed += tvNow-pf_tvOverAllStarted; + } + IFDEBUG(pt.pt_tvStarted.tv_llValue = -__int64(1)); + _tvCurrentProfilingEpsilon += _tvStopEpsilon; +} + +/* Get current value of a counter. */ +INDEX CProfileForm::GetCounterCount(INDEX iCounter) { + return pf_apcCounters[iCounter].pc_ctCount; +}; + +// override to provide external averaging +INDEX CProfileForm::GetAveragingCounter(void) +{ + return pf_ctAveragingCounter; +} + +/* Get current value of a timer in seconds or in percentage of module time. */ +double CProfileForm::GetTimerAverageTime(INDEX iTimer) { + // must not report while some timers are active! + ASSERT(pf_ctRunningTimers==0); + return pf_aptTimers[iTimer].pt_tvElapsed.GetSeconds()/GetAveragingCounter(); +} +double CProfileForm::GetTimerPercentageOfModule(INDEX iTimer) { + // must not report while some timers are active! + ASSERT(pf_ctRunningTimers==0); + return pf_aptTimers[iTimer].pt_tvElapsed.GetSeconds() + /pf_tvOverAllElapsed.GetSeconds()*100; +} + +/* Get percentage of module time in application time. */ +double CProfileForm::GetModulePercentage(void) { + // must not report while some timers are active! + ASSERT(pf_ctRunningTimers==0); + // calculate total application time since profile form was reset + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + CTimerValue tvApplicationElapsed = tvNow-pf_tvLastReset; + return pf_tvOverAllElapsed.GetSeconds()/tvApplicationElapsed.GetSeconds()*100; +} + +/* + * Reset all profiling values. + */ +void CProfileForm::Reset(void) +{ + // must not reset profiling form while some timers are active! + //ASSERT(pf_ctRunningTimers==0); + + // remember time when form was reset + pf_tvLastReset = _pTimer->GetHighPrecisionTimer(); + + // clear global entries + pf_tvOverAllElapsed.Clear(); + pf_ctAveragingCounter = 0; + + // for all counters + FOREACHINSTATICARRAY(pf_apcCounters, CProfileCounter, itpc) { + // clear the counter + itpc->pc_ctCount = 0; + } + // for all timers + FOREACHINSTATICARRAY(pf_aptTimers, CProfileTimer, itpt) { + // clear the timer + itpt->pt_tvElapsed.Clear(); + itpt->pt_tvStarted.tv_llValue = -__int64(1); + itpt->pt_ctAveraging = 0; + } +} + +/* Print one counter in report. */ +void CProfileCounter::Report(char *&strBuffer, INDEX ctAveragingCount) +{ + if (ctAveragingCount==0) { + ctAveragingCount = 1; + } + strBuffer += sprintf(strBuffer, "%-45s: %7d %7.2f\n", + pc_strName, pc_ctCount, (double)pc_ctCount/ctAveragingCount); +} + +/* Print one timer in report. */ +void CProfileTimer::Report(char *&strBuffer, + INDEX ctAveragingCount, + CTimerValue tvAppElapsed, CTimerValue tvModElapsed) +{ + if (ctAveragingCount==0) { + ctAveragingCount = 1; + } + + if (pt_strAveragingName=="") { + strBuffer += sprintf(strBuffer, "%-45s: %6.2f%% %6.2f%% %6.2f ms\n", + pt_strName, + pt_tvElapsed.GetSeconds()/tvAppElapsed.GetSeconds()*100, + pt_tvElapsed.GetSeconds()/tvModElapsed.GetSeconds()*100, + pt_tvElapsed.GetSeconds()/ctAveragingCount*1000 + ); + } else { + INDEX ctLocalAveraging = pt_ctAveraging; + if (ctLocalAveraging==0) { + ctLocalAveraging = 1; + } + strBuffer += sprintf(strBuffer, "%-45s: %6.2f%% %6.2f%% %6.2f ms (%4.0fc/%s x%d)\n", + pt_strName, + pt_tvElapsed.GetSeconds()/tvAppElapsed.GetSeconds()*100, + pt_tvElapsed.GetSeconds()/tvModElapsed.GetSeconds()*100, + pt_tvElapsed.GetSeconds()/ctAveragingCount*1000, + pt_tvElapsed.GetSeconds()/ctLocalAveraging*_pTimer->tm_llCPUSpeedHZ, + pt_strAveragingName, + pt_ctAveraging/ctAveragingCount + ); + } +} +/* + * Report profiling results. + */ +void CProfileForm::Report(CTString &strReport) +{ + static char aBuffer[16000]; + char *strBuffer = aBuffer; + + // must not report profiling form while some timers are active! + if (pf_ctRunningTimers!=0) { + strBuffer += sprintf(strBuffer, + "WARNING: Some timers are still active - the results are wrong!\n"); + } + //ASSERT(pf_ctRunningTimers==0); + + // calculate total application time since profile form was reset + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + CTimerValue tvApplicationElapsed = tvNow-pf_tvLastReset; + // calculate total time spent in profiled module + CTimerValue tvModuleElapsed = pf_tvOverAllElapsed; + // print the main header + strBuffer += sprintf(strBuffer, "%s profile for last %d %s:\n", + pf_strTitle, GetAveragingCounter(), pf_strAveragingUnits); + + // print header for timers + strBuffer += sprintf(strBuffer, + "Module time: %6.2f%% of application time. Average time: %6.2fms\n", + tvModuleElapsed.GetSeconds()/tvApplicationElapsed.GetSeconds()*100.0, + tvModuleElapsed.GetSeconds()/GetAveragingCounter()*1000.0 + ); + + strBuffer += sprintf(strBuffer, "\n"); + // for all timers + FOREACHINSTATICARRAY(pf_aptTimers, CProfileTimer, itpt) { + // print the timer + itpt->Report(strBuffer, GetAveragingCounter(), tvApplicationElapsed, tvModuleElapsed); + } + + strBuffer += sprintf(strBuffer, "\n"); + // for all counters + FOREACHINSTATICARRAY(pf_apcCounters, CProfileCounter, itpc) { + // print the counter + itpc->Report(strBuffer, GetAveragingCounter()); + } + // print the footer + strBuffer += sprintf(strBuffer, "--------------------\n"); + + // return the buffer + strReport = aBuffer; +} diff --git a/Sources/Engine/Base/Profiling.h b/Sources/Engine/Base/Profiling.h new file mode 100644 index 0000000..4318d22 --- /dev/null +++ b/Sources/Engine/Base/Profiling.h @@ -0,0 +1,182 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PROFILING_H +#define SE_INCL_PROFILING_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#if ENGINE_INTERNAL + +#include +#include +#include + +#include + +/* + * Profiling counter. + */ +class CProfileCounter { +friend class CProfileForm; +private: + CTString pc_strName; // name of this counter + INDEX pc_ctCount; // the counter itself + + /* Print one counter in report. */ + void Report(char *&strBuffer, INDEX ctAveragingCount); +}; + +/* + * Profiling timer. + */ +class CProfileTimer { +friend class CProfileForm; +private: + CTString pt_strName; // name of this timer + CTimerValue pt_tvStarted; // time when the timer was started last time + CTimerValue pt_tvElapsed; // total elapsed time of the timer + CTString pt_strAveragingName; // name of averaging counter + INDEX pt_ctAveraging; // averaging counter for this timer + + /* Print one timer in report. */ + void Report(char *&strBuffer, INDEX ctAveragingCount, + CTimerValue tvAppElapsed, CTimerValue tvModElapsed); +}; + +// this file just defines TIMER_PROFILING as 1 or 0 +#include + +#endif ENGINE_INTERNAL + +/* + * Class for gathering and reporting profiling information. + */ +class CProfileForm { +public: + +#if ENGINE_INTERNAL +// implementation: + CTString pf_strTitle; // main title of the profiling form + CTString pf_strAveragingUnits; // name for averaging units + + CStaticArray pf_apcCounters; // profiling counters + CStaticArray pf_aptTimers; // profiling timers + + CTimerValue pf_tvOverAllStarted; // timer when overall timer was started last time + CTimerValue pf_tvOverAllElapsed; // total elapsed time of the overall timer + INDEX pf_ctRunningTimers; // counter of currently running timers + + INDEX pf_ctAveragingCounter; // counter for calculating average results + // override to provide external averaging + virtual INDEX GetAveragingCounter(void); + + CTimerValue pf_tvLastReset; // time when profile form was last reset + + /* Start a timer. */ + void StartTimer_internal(INDEX iTimer); + /* Stop a timer. */ + void StopTimer_internal(INDEX iTimer); + +// interface: + /* Constructor for profile form with given number of counters and timers. + * NOTE: Reset() must be called on a profile form before using it! + */ + CProfileForm(const CTString &strTitle, const CTString &strAveragingUnits, + INDEX ctCounters, INDEX ctTimers); + void Clear(void); + + // set/test profiling activation flag + static void SetProfilingActive(BOOL bActive); + static BOOL GetProfilingActive(void); + + // Measure profiling errors and set epsilon corrections. + static void CalibrateProfilingTimers(void); + + /* Increment averaging counter by given count. */ + inline void IncrementAveragingCounter(INDEX ctAdd=1) { + pf_ctAveragingCounter += ctAdd; + }; + + /* Increment counter by given count. */ + inline void IncrementCounter(INDEX iCounter, INDEX ctAdd=1) { + pf_apcCounters[iCounter].pc_ctCount += ctAdd; + }; + /* Get current value of a counter. */ + INDEX GetCounterCount(INDEX iCounter); + +#if TIMER_PROFILING + /* Start a timer. */ + inline void StartTimer(INDEX iTimer) { + StartTimer_internal(iTimer); + }; + /* Stop a timer. */ + inline void StopTimer(INDEX iTimer) { + StopTimer_internal(iTimer); + }; + /* Increment averaging counter for a timer by given count. */ + inline void IncrementTimerAveragingCounter(INDEX iTimer, INDEX ctAdd=1) { + pf_aptTimers[iTimer].pt_ctAveraging += ctAdd; + }; + /* Set name of a counter. */ + void SetCounterName_internal(INDEX iCounter, const CTString &strName) + { + pf_apcCounters[iCounter].pc_strName = strName; + } + /* Set name of a timer. */ + void SetTimerName_internal(INDEX iTimer, const CTString &strName, const CTString &strAveragingName) + { + pf_aptTimers[iTimer].pt_strName = strName; + pf_aptTimers[iTimer].pt_strAveragingName = strAveragingName; + } + #define SETCOUNTERNAME(a,b) SetCounterName_internal(a,b) + #define SETTIMERNAME(a,b,c) SetTimerName_internal(a,b,c) + +#else //TIMER_PROFILING + inline void StartTimer(INDEX iTimer) {}; + inline void StopTimer(INDEX iTimer) {}; + inline void IncrementTimerAveragingCounter(INDEX iTimer, INDEX ctAdd=1) {}; + inline void SetCounterName_internal(INDEX iCounter, const CTString &strName) {}; + inline void SetTimerName_internal(INDEX iTimer, const CTString &strName, const CTString &strAveragingName) {}; + #define SETCOUNTERNAME(a,b) SetCounterName_internal(a,"") + #define SETTIMERNAME(a,b,c) SetTimerName_internal(a,"","") +#endif + + /* Get current value of a timer in seconds or in percentage of module time. */ + double GetTimerPercentageOfModule(INDEX iTimer); + double GetTimerAverageTime(INDEX iTimer); + /* Get name of a counter. */ + const CTString &GetCounterName(INDEX iCounter); + /* Get name of a timer. */ + const CTString &GetTimerName(INDEX iTimer); + + /* Get percentage of module time in application time. */ + double GetModulePercentage(void); + +#endif // ENGINE_INTERNAL + + /* Reset all profiling values. */ + ENGINE_API void Reset(void); + + /* Report profiling results. */ + ENGINE_API void Report(CTString &strReport); +}; + +// profile form for profiling gfx +ENGINE_API extern CProfileForm &_pfGfxProfile; +// profile form for profiling model rendering +ENGINE_API extern CProfileForm &_pfModelProfile; +// profile form for profiling sound +ENGINE_API extern CProfileForm &_pfSoundProfile; +// profile form for profiling network +ENGINE_API extern CProfileForm &_pfNetworkProfile; +// profile form for profiling rendering +ENGINE_API extern CProfileForm &_pfRenderProfile; +// profile form for profiling world editing +ENGINE_API extern CProfileForm &_pfWorldEditingProfile; +// profile form for profiling phisics +ENGINE_API extern CProfileForm &_pfPhysicsProfile; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/ProfilingEnabled.h b/Sources/Engine/Base/ProfilingEnabled.h new file mode 100644 index 0000000..72ce493 --- /dev/null +++ b/Sources/Engine/Base/ProfilingEnabled.h @@ -0,0 +1,3 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#define TIMER_PROFILING 0 diff --git a/Sources/Engine/Base/ProgressHook.cpp b/Sources/Engine/Base/ProgressHook.cpp new file mode 100644 index 0000000..75b3f43 --- /dev/null +++ b/Sources/Engine/Base/ProgressHook.cpp @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" +#include +#include +#include +#include + +static void (*_pLoadingHook_t)(CProgressHookInfo *pgli) = NULL; // hook for loading/connecting +static CProgressHookInfo _phiLoadingInfo; // info passed to the hook +BOOL _bRunNetUpdates = FALSE; +static CTimerValue tvLastUpdate; +static BOOL bTimeInitialized = FALSE; +extern FLOAT net_fSendRetryWait; + +// set hook for loading/connecting +void SetProgressHook(void (*pHook)(CProgressHookInfo *pgli)) +{ + _pLoadingHook_t = pHook; +} +// call loading/connecting hook +void SetProgressDescription(const CTString &strDescription) +{ + _phiLoadingInfo.phi_strDescription = strDescription; +} + +void CallProgressHook_t(FLOAT fCompleted) +{ + if (_pLoadingHook_t!=NULL) { + _phiLoadingInfo.phi_fCompleted = fCompleted; + _pLoadingHook_t(&_phiLoadingInfo); + + + if (!bTimeInitialized) { + tvLastUpdate = _pTimer->GetHighPrecisionTimer(); + bTimeInitialized = TRUE; + } + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + if ((tvNow-tvLastUpdate) > CTimerValue(net_fSendRetryWait*1.1)) { + if (_pNetwork->ga_IsServer) { + // handle server messages + _cmiComm.Server_Update(); + } else { + // handle client messages + _cmiComm.Client_Update(); + } + tvLastUpdate = _pTimer->GetHighPrecisionTimer(); + } + + } +} + diff --git a/Sources/Engine/Base/ProgressHook.h b/Sources/Engine/Base/ProgressHook.h new file mode 100644 index 0000000..ca47664 --- /dev/null +++ b/Sources/Engine/Base/ProgressHook.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PROGRESSHOOK_H +#define SE_INCL_PROGRESSHOOK_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// structure describing current state during loading, passed to loading hook +class CProgressHookInfo { +public: + CTString phi_strDescription; // world/savegame/session that is loading/connecting, etc. + FLOAT phi_fCompleted; // completed ratio [0..1] +}; + +// set hook for loading/connecting +extern ENGINE_API void SetProgressHook(void (*pHook_t)(CProgressHookInfo *pgli)); +// call loading/connecting hook +extern ENGINE_API void SetProgressDescription(const CTString &strDescription); +extern ENGINE_API void CallProgressHook_t(FLOAT fCompleted); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Protection.cpp b/Sources/Engine/Base/Protection.cpp new file mode 100644 index 0000000..ffe5d20 --- /dev/null +++ b/Sources/Engine/Base/Protection.cpp @@ -0,0 +1,407 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include + +#pragma warning (disable: 4244) + +/* + * Author : Paul Kocher + * E-mail : pck@netcom.com + * Date : 1997 + * Description: C implementation of the Blowfish algorithm. + */ + +#define MAXKEYBYTES 56 /* 448 bits */ + +#define N 16 + +static unsigned long F(BLOWFISH_CTX *ctx, unsigned long x); + +static const unsigned long ORIG_P[16 + 2] = { + 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, + 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, + 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, + 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, + 0x9216D5D9L, 0x8979FB1BL +}; + +static const unsigned long ORIG_S[4][256] = { + { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, + 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, + 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, + 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, + 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, + 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, + 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, + 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, + 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, + 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, + 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, + 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, + 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, + 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, + 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, + 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, + 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, + 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, + 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, + 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, + 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, + 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, + 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, + 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, + 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, + 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, + 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, + 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, + 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, + 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, + 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, + 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, + 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, + 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, + 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, + 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, + 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, + 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, + 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, + 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, + 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, + 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, + 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, + 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, + 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, + 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, + 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, + 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, + 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, + 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, + 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, + 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, + 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, + 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, + 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, + 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, + 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, + 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, + 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, + 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, + 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, + 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, + 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, + 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, + { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, + 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, + 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, + 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, + 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, + 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, + 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, + 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, + 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, + 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, + 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, + 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, + 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, + 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, + 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, + 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, + 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, + 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, + 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, + 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, + 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, + 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, + 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, + 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, + 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, + 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, + 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, + 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, + 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, + 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, + 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, + 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, + 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, + 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, + 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, + 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, + 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, + 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, + 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, + 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, + 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, + 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, + 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, + 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, + 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, + 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, + 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, + 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, + 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, + 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, + 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, + 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, + 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, + 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, + 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, + 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, + 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, + 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, + 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, + 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, + 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, + 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, + 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, + 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, + { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, + 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, + 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, + 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, + 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, + 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, + 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, + 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, + 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, + 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, + 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, + 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, + 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, + 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, + 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, + 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, + 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, + 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, + 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, + 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, + 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, + 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, + 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, + 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, + 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, + 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, + 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, + 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, + 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, + 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, + 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, + 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, + 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, + 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, + 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, + 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, + 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, + 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, + 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, + 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, + 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, + 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, + 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, + 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, + 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, + 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, + 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, + 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, + 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, + 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, + 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, + 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, + 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, + 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, + 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, + 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, + 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, + 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, + 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, + 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, + 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, + 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, + 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, + 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, + { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, + 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, + 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, + 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, + 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, + 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, + 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, + 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, + 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, + 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, + 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, + 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, + 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, + 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, + 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, + 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, + 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, + 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, + 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, + 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, + 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, + 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, + 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, + 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, + 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, + 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, + 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, + 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, + 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, + 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, + 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, + 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, + 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, + 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, + 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, + 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, + 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, + 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, + 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, + 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, + 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, + 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, + 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, + 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, + 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, + 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, + 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, + 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, + 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, + 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, + 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, + 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, + 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, + 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, + 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, + 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, + 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, + 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, + 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, + 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, + 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, + 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, + 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, + 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } +}; + + +unsigned long F(BLOWFISH_CTX *ctx, unsigned long x) +{ + unsigned short a, b, c, d; + unsigned long y; + + d = x & 0x00FF; + x >>= 8; + c = x & 0x00FF; + x >>= 8; + b = x & 0x00FF; + x >>= 8; + a = x & 0x00FF; + y = ctx->S[0][a] + ctx->S[1][b]; + y = y ^ ctx->S[2][c]; + y = y + ctx->S[3][d]; + + return y; +} + +void Blowfish_Decrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long *xr) { + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = N + 1; i > 1; --i) { + Xl = Xl ^ ctx->P[i]; + Xr = F(ctx, Xl) ^ Xr; + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + } + + /* Exchange Xl and Xr */ + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[1]; + Xl = Xl ^ ctx->P[0]; + + *xl = Xl; + *xr = Xr; +} + +void Blowfish_Encrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long *xr) { + + unsigned long Xl; + unsigned long Xr; + unsigned long temp; + short i; + + Xl = *xl; + Xr = *xr; + + for (i = 0; i < N; ++i) { + Xl = Xl ^ ctx->P[i]; + Xr = F(ctx, Xl) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[N]; + Xl = Xl ^ ctx->P[N + 1]; + + *xl = Xl; + *xr = Xr; +} + + + +void Blowfish_Init(BLOWFISH_CTX *ctx, unsigned char *key, int keyLen) { + int i, j, k; + unsigned long data, datal, datar; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 256; j++) + ctx->S[i][j] = ORIG_S[i][j]; + } + + j = 0; + for (i = 0; i < N + 2; ++i) { + data = 0x00000000; + for (k = 0; k < 4; ++k) { + data = (data << 8) | key[j]; + j = j + 1; + if (j >= keyLen) + j = 0; + } + ctx->P[i] = ORIG_P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for (i = 0; i < N + 2; i += 2) { + Blowfish_Encrypt(ctx, &datal, &datar); + ctx->P[i] = datal; + ctx->P[i + 1] = datar; + } + + for (i = 0; i < 4; ++i) { + for (j = 0; j < 256; j += 2) { + Blowfish_Encrypt(ctx, &datal, &datar); + ctx->S[i][j] = datal; + ctx->S[i][j + 1] = datar; + } + } +} diff --git a/Sources/Engine/Base/Protection.h b/Sources/Engine/Base/Protection.h new file mode 100644 index 0000000..276baf2 --- /dev/null +++ b/Sources/Engine/Base/Protection.h @@ -0,0 +1,19 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PROTECTION_H +#define SE_INCL_PROTECTION_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +typedef struct { + unsigned long P[16 + 2]; + unsigned long S[4][256]; +} BLOWFISH_CTX; + +extern void Blowfish_Init(BLOWFISH_CTX *ctx, unsigned char *key, int keyLen); +extern void Blowfish_Decrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long *xr); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Registry.cpp b/Sources/Engine/Base/Registry.cpp new file mode 100644 index 0000000..67536eb --- /dev/null +++ b/Sources/Engine/Base/Registry.cpp @@ -0,0 +1,116 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include + +static void ParseKeyName(const CTString &strKey, HKEY &hKeyRoot, CTString &strKeyPath, CTString &strKeyName) +{ + CTString strRemain = strKey; + // separate key into the value part and path + strKeyName = CTFileName(strRemain).FileName(); + strRemain = CTFileName(strRemain).FileDir(); + strRemain.TrimRight(strlen(strRemain)-1); // removes trailing backslash + // try to find root key value + + if (strRemain.RemovePrefix("HKEY_CLASSES_ROOT\\")) { + hKeyRoot = HKEY_CLASSES_ROOT; + } else if (strRemain.RemovePrefix("HKEY_CURRENT_CONFIG\\")) { + hKeyRoot = HKEY_CURRENT_CONFIG; + } else if (strRemain.RemovePrefix("HKEY_CURRENT_USER\\")) { + hKeyRoot = HKEY_CURRENT_USER; + } else if (strRemain.RemovePrefix("HKEY_LOCAL_MACHINE\\")) { + hKeyRoot = HKEY_LOCAL_MACHINE; + } else if (strRemain.RemovePrefix("HKEY_USERS\\")) { + hKeyRoot = HKEY_USERS; + } else { + ASSERT(FALSE); + hKeyRoot = HKEY_CURRENT_USER; + } + + strKeyPath = strRemain; +} + +ENGINE_API BOOL REG_GetString(const CTString &strKey, CTString &strString) +{ + // parse the key name + HKEY hKeyRoot; CTString strKeyPath; CTString strKeyName; + ParseKeyName(strKey, hKeyRoot, strKeyPath, strKeyName); + + // open the key + HKEY hkey; + LONG lRes = RegOpenKeyExA(hKeyRoot, strKeyPath, 0, KEY_READ, &hkey); + if (lRes!=ERROR_SUCCESS) { + return FALSE; + } + + // get the value + char achrKeyValue[1024]; + ULONG ctType; + ULONG ctLength = sizeof(achrKeyValue); + LONG lResult = RegQueryValueExA(hkey, strKeyName, 0, &ctType, (unsigned char *)achrKeyValue, &ctLength); + if(lResult != ERROR_SUCCESS) { + return FALSE; + } + + // close the key + RegCloseKey(hkey); + + strString = CTString( achrKeyValue); + return TRUE; +} + +ENGINE_API BOOL REG_GetLong(const CTString &strKey, ULONG &ulLong) +{ + // parse the key name + HKEY hKeyRoot; CTString strKeyPath; CTString strKeyName; + ParseKeyName(strKey, hKeyRoot, strKeyPath, strKeyName); + + // open the key + HKEY hkey; + LONG lRes = RegOpenKeyExA(hKeyRoot, strKeyPath, 0, KEY_READ, &hkey); + if (lRes!=ERROR_SUCCESS) { + return FALSE; + } + + // get the value + ULONG ulKeyValue; + ULONG ctType; + ULONG ctLength = sizeof(ulKeyValue); + LONG lResult = RegQueryValueExA(hkey, strKeyName, 0, &ctType, (unsigned char *)&ulKeyValue, &ctLength); + if(lResult != ERROR_SUCCESS) { + return FALSE; + } + + // close the key + RegCloseKey(hkey); + + ulLong = ulKeyValue; + return TRUE; +} + +ENGINE_API BOOL REG_SetString(const CTString &strKey, const CTString &strString) +{ + // parse the key name + HKEY hKeyRoot; CTString strKeyPath; CTString strKeyName; + ParseKeyName(strKey, hKeyRoot, strKeyPath, strKeyName); + + // create the registry key + HKEY hkey; + DWORD dwDisposition; + LONG lRes = RegCreateKeyExA(hKeyRoot, (const char*)strKeyPath, 0, + "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwDisposition); + if (lRes!=ERROR_SUCCESS) { + return FALSE; + } + + // set the value + lRes = RegSetValueExA(hkey, strKeyName, 0, REG_SZ, (const UBYTE*)(const char*)strString, strlen(strString)); + + // close the key + RegCloseKey(hkey); + + return lRes==ERROR_SUCCESS; +} + diff --git a/Sources/Engine/Base/Registry.h b/Sources/Engine/Base/Registry.h new file mode 100644 index 0000000..155eab7 --- /dev/null +++ b/Sources/Engine/Base/Registry.h @@ -0,0 +1,15 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_REGISTRY_H +#define SE_INCL_REGISTRY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +ENGINE_API BOOL REG_GetString(const CTString &strKey, CTString &strString); +ENGINE_API BOOL REG_SetString(const CTString &strKey, const CTString &strString); +ENGINE_API BOOL REG_GetLong(const CTString &strKey, ULONG &ulLong); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Relations.cpp b/Sources/Engine/Base/Relations.cpp new file mode 100644 index 0000000..3de736b --- /dev/null +++ b/Sources/Engine/Base/Relations.cpp @@ -0,0 +1,109 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include + + +///////////////////////////////////////////////////////////////////// +// CRelationSrc + +// Construction/destruction. +CRelationSrc::CRelationSrc(void) +{ +} + +CRelationSrc::~CRelationSrc(void) +{ + Clear(); +} + +void CRelationSrc::Clear(void) +{ + // just delete all links, they will unlink on destruction + FORDELETELIST(CRelationLnk, rl_lnSrc, *this, itlnk) { + delete &*itlnk; + } +} + +///////////////////////////////////////////////////////////////////// +// CRelationDst + +// Construction/destruction. +CRelationDst::CRelationDst(void) +{ +} + +CRelationDst::~CRelationDst(void) +{ + Clear(); +} + +void CRelationDst::Clear(void) +{ + // just delete all links, they will unlink on destruction + FORDELETELIST(CRelationLnk, rl_lnDst, *this, itlnk) { + delete &*itlnk; + } +} + +///////////////////////////////////////////////////////////////////// +// CRelationLnk + +// Construction/destruction. +CRelationLnk::CRelationLnk(void) +{ +} + +CRelationLnk::~CRelationLnk(void) +{ + // unlink from both domain and codomain members + rl_lnSrc.Remove(); + rl_lnDst.Remove(); +} + +// Get the domain member of this pair. +CRelationSrc &CRelationLnk::GetSrc(void) +{ + return *rl_prsSrc; +} + +// Get the codomain member of this pair. +CRelationDst &CRelationLnk::GetDst(void) +{ + return *rl_prdDst; +} + +// Global functions for creating relations. +void AddRelationPair(CRelationSrc &rsSrc, CRelationDst &rdDst) +{ + // create a new link + CRelationLnk &lnk = *new CRelationLnk; + lnk.rl_prsSrc = &rsSrc; + lnk.rl_prdDst = &rdDst; + // add the link to the domain and codomain members + rsSrc.AddTail(lnk.rl_lnSrc); + rdDst.AddTail(lnk.rl_lnDst); +} +void AddRelationPairTailTail(CRelationSrc &rsSrc, CRelationDst &rdDst) +{ + // create a new link + CRelationLnk &lnk = *new CRelationLnk; + lnk.rl_prsSrc = &rsSrc; + lnk.rl_prdDst = &rdDst; + // add the link to the domain and codomain members + rsSrc.AddTail(lnk.rl_lnSrc); + rdDst.AddTail(lnk.rl_lnDst); +} +void AddRelationPairHeadHead(CRelationSrc &rsSrc, CRelationDst &rdDst) +{ + // create a new link + CRelationLnk &lnk = *new CRelationLnk; + lnk.rl_prsSrc = &rsSrc; + lnk.rl_prdDst = &rdDst; + // add the link to the domain and codomain members + rsSrc.AddHead(lnk.rl_lnSrc); + rdDst.AddHead(lnk.rl_lnDst); +} diff --git a/Sources/Engine/Base/Relations.h b/Sources/Engine/Base/Relations.h new file mode 100644 index 0000000..47c861a --- /dev/null +++ b/Sources/Engine/Base/Relations.h @@ -0,0 +1,82 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_RELATIONS_H +#define SE_INCL_RELATIONS_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +// Object representing a link at the member of relation domain. +class CRelationSrc : public CListHead { +public: +// implementation: +// interface: + // Construction/destruction. + ENGINE_API CRelationSrc(void); + ENGINE_API ~CRelationSrc(void); + void Clear(void); +}; + +// Object representing a link at the member of relation codomain. +class CRelationDst : public CListHead { +public: +// implementation: +// interface: + // Construction/destruction. + ENGINE_API CRelationDst(void); + ENGINE_API ~CRelationDst(void); + void Clear(void); +}; + +// Object representing a link between a domain member and a codomain member. +class CRelationLnk { +public: +// implementation: + CRelationSrc *rl_prsSrc; // domain member + CRelationDst *rl_prdDst; // codomain member + CListNode rl_lnSrc; // node in list of links in domain member + CListNode rl_lnDst; // node in list of links in codomain member +// interface: + // Construction/destruction. + CRelationLnk(void); + ~CRelationLnk(void); + // Get the domain member of this pair. + ENGINE_API CRelationSrc &GetSrc(void); + // Get the codomain member of this pair. + ENGINE_API CRelationDst &GetDst(void); +}; + +// Global functions for creating relations. +void ENGINE_API AddRelationPair(CRelationSrc &rsSrc, CRelationDst &rdDst); +void ENGINE_API AddRelationPairTailTail(CRelationSrc &rsSrc, CRelationDst &rdDst); +void ENGINE_API AddRelationPairHeadHead(CRelationSrc &rsSrc, CRelationDst &rdDst); + +// make 'for' construct for walking a list in domain member +#define FOREACHSRCLINK(head, iter) \ + for ( LISTITER(CRelationLnk, rl_lnSrc) iter(head); !iter.IsPastEnd(); iter.MoveToNext() ) +// make 'for' construct for walking a list in codomain member +#define FOREACHDSTLINK(head, iter) \ + for ( LISTITER(CRelationLnk, rl_lnDst) iter(head); !iter.IsPastEnd(); iter.MoveToNext() ) + +// get a domain member related to a codomain member through a link +#define DST(plink, dstclass, dstmember) \ + ( (dstclass *) ( ((UBYTE *)(&(plink->GetDst()))) - offsetof(dstclass, dstmember) ) ) +// get a codomain member that a domain member is related to through a link +#define SRC(plink, srcclass, srcmember) \ + ( (srcclass *) ( ((UBYTE *)(&(plink->GetSrc()))) - offsetof(srcclass, srcmember) ) ) + +// make 'for' construct for walking all codomain members related to a domain member +#define FOREACHDSTOFSRC(srchead, dstclass, dstmember, pdst) \ + FOREACHSRCLINK(srchead, pdst##_iter) { \ + dstclass *pdst = DST(pdst##_iter, dstclass, dstmember); +// make 'for' construct for walking all domain members related to a codomain member +#define FOREACHSRCOFDST(dsthead, srcclass, srcmember, psrc) \ + FOREACHDSTLINK(dsthead, psrc##_iter) { \ + srcclass *psrc = SRC(psrc##_iter, srcclass, srcmember); +#define ENDFOR } + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/ReplaceFile.cpp b/Sources/Engine/Base/ReplaceFile.cpp new file mode 100644 index 0000000..97d6888 --- /dev/null +++ b/Sources/Engine/Base/ReplaceFile.cpp @@ -0,0 +1,923 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#include + +#define FILTER_TEX "Textures (*.tex)\0*.tex\0" +#define FILTER_MDL "Models (*.mdl)\0*.mdl\0" +#define FILTER_ANI "Animations (*.ani)\0*.ani\0" +#define FILTER_END "\0" + +BOOL _bFileReplacingApplied; + +#ifndef NDEBUG + #define ENGINEGUI_DLL_NAME "EngineGUID.dll" +#else + #define ENGINEGUI_DLL_NAME "EngineGUI.dll" +#endif + +extern INDEX wed_bUseBaseForReplacement; + +static CTFileName CallFileRequester(char *achrTitle, char *achrSelectedFile, char *pFilter) +{ + typedef CTFileName FileRequester_t( + char *pchrTitle, + char *pchrFilters, + char *pchrRegistry, + char *pchrDefaultFileSelected); + + HMODULE hGUI = GetModuleHandleA(ENGINEGUI_DLL_NAME); + if (hGUI==NULL) { + WarningMessage(TRANS("Cannot load %s:\n%s\nCannot replace files!"), + ENGINEGUI_DLL_NAME, GetWindowsError(GetLastError())); + return CTString(""); + } + FileRequester_t *pFileRequester = (FileRequester_t*)GetProcAddress(hGUI, + "?FileRequester@@YA?AVCTFileName@@PAD000@Z"); + if (pFileRequester==NULL) { + WarningMessage(TRANS("Error in %s:\nFileRequester() function not found\nCannot replace files!"), + ENGINEGUI_DLL_NAME); + return CTString(""); + } + + return pFileRequester( achrTitle, pFilter, "Replace file directory", achrSelectedFile); +} + +BOOL GetReplacingFile(CTFileName fnSourceFile, CTFileName &fnReplacingFile, + char *pFilter) +{ + // don't replace files if this console variable is set + if (!wed_bUseBaseForReplacement) { + return FALSE; + } + + CTString strBaseForReplacingFiles; + // try to find replacing texture in base + try + { + char achrLine[ 256]; + char achrSource[ 256]; + char achrRemap[ 256]; + + // open file containing file names for replacing textures + CTFileStream fsBase; + CTFileName fnBaseName = CTString("Data\\BaseForReplacingFiles.txt"); + fsBase.Open_t( fnBaseName); + while( !fsBase.AtEOF()) + { + fsBase.GetLine_t( achrLine, 256); + sscanf( achrLine, "\"%[^\"]\" \"%[^\"]\"", achrSource, achrRemap); + if (CTString( achrSource) == achrRemap) { + continue; // skip remaps to self + } + if( CTString( achrSource) == fnSourceFile) + { + fnReplacingFile = CTString( achrRemap); + return TRUE; + } + } + fsBase.Close(); + } + // if file containing base can't be opened + catch(char *strError) + { + (void) strError; + } + CTString strTitle; + strTitle.PrintF(TRANS("For:\"%s\""), (CTString&)fnSourceFile); + // call file requester for substituting file + CTString strDefaultFile; + strDefaultFile = fnSourceFile.FileName() + fnSourceFile.FileExt(); + fnReplacingFile = CallFileRequester((char*)(const char*)strTitle, (char*)(const char*)strDefaultFile, pFilter); + if( fnReplacingFile == "") return FALSE; + + try + { + // add new remap to end of remapping base file + CTFileName fnBaseName = CTString("Data\\BaseForReplacingFiles.txt"); + CTString strBase; + if( FileExists( fnBaseName)) + { + strBase.Load_t( fnBaseName); + } + CTString strNewRemap; + strNewRemap.PrintF( "\"%s\" \"%s\"\n", (CTString&)fnSourceFile, (CTString&)fnReplacingFile); + strBase += strNewRemap; + strBase.Save_t( fnBaseName); + } + catch( char *strError) + { + WarningMessage( strError); + return FALSE; + } + return TRUE; +} + + +void SetTextureWithPossibleReplacing_t(CTextureObject &to, CTFileName &fnmTexture) +{ + // try to load texture + for(;;) + { + try + { + to.SetData_t(fnmTexture); + break; + } + catch( char *strError) + { + (void) strError; + // if texture was not found, ask for replacing texture + CTFileName fnReplacingTexture; + if( GetReplacingFile( fnmTexture, fnReplacingTexture, FILTER_TEX FILTER_END)) + { + // if replacing texture was provided, repeat reading of polygon's textures + fnmTexture = fnReplacingTexture; + } + else + { + if(_pShell->GetINDEX("wed_bUseGenericTextureReplacement")) { + fnmTexture = CTString("Textures\\Editor\\Default.tex"); + to.SetData_t(fnmTexture); + } else { + ThrowF_t( TRANS("Unable to load world because texture \"%s\" can't be found."), + (CTString&)fnmTexture); + } + } + } + } +} + +// read/write a texture object +void ReadTextureObject_t(CTStream &strm, CTextureObject &to) +{ + // read model texture data filename + CTFileName fnTexture; + strm>>fnTexture; + // try to load texture + for(;;) { + try { + // set the texture data + to.SetData_t(fnTexture); + break; + } catch( char *strError) { + (void) strError; + // if texture was not found, ask for replacing texture + CTFileName fnReplacingTexture; + if( GetReplacingFile( fnTexture, fnReplacingTexture, FILTER_TEX FILTER_END)) { + // replacing texture was provided + fnTexture = fnReplacingTexture; + } else { + ThrowF_t( TRANS("Cannot find substitution for \"%s\""), (CTString&)fnTexture); + } + } + } + // read main texture anim object + to.Read_t(&strm); +} +void SkipTextureObject_t(CTStream &strm) +{ + // skip texture filename + CTFileName fnDummy; + strm>>fnDummy; + // skip texture object + CTextureObject toDummy; + toDummy.Read_t(&strm); +} +void WriteTextureObject_t(CTStream &strm, CTextureObject &to) +{ + // write model texture filename + CTextureData *ptd = (CTextureData *)to.GetData(); + if (ptd!=NULL) { + strm<GetName(); + } else { + strm<>fnModel; + // try to load model + for(;;) { + try { + // set the model data + mo.SetData_t(fnModel); + break; + } catch( char *strError) { + (void) strError; + // if model was not found, ask for replacing model + CTFileName fnReplacingModel; + if( GetReplacingFile( fnModel, fnReplacingModel, FILTER_MDL FILTER_END)) { + // replacing model was provided + fnModel = fnReplacingModel; + } else { + ThrowF_t( TRANS("Cannot find substitution for \"%s\""), (CTString&)fnModel); + } + } + } + // read model anim object + mo.Read_t(&strm); + + // if model object has multiple textures + if (strm.PeekID_t() == CChunkID("MTEX")) { // 'multi-texturing' + // read all textures + strm.ExpectID_t("MTEX"); // 'multi-texturing'' + ReadTextureObject_t(strm, mo.mo_toTexture); + ReadTextureObject_t(strm, mo.mo_toBump); + ReadTextureObject_t(strm, mo.mo_toReflection); + ReadTextureObject_t(strm, mo.mo_toSpecular); + + // if model has single texture (old format) + } else { + // read main texture + ReadTextureObject_t(strm, mo.mo_toTexture); + } + + // if model object has attachments + if (strm.PeekID_t() == CChunkID("ATCH")) { // 'attachments' + // read attachments header + strm.ExpectID_t("ATCH"); // 'attachments' + INDEX ctAttachments; + strm>>ctAttachments; + // for each attachment + for(INDEX iAttachment=0; iAttachment>iPosition; + CAttachmentModelObject *pamo = mo.AddAttachmentModel(iPosition); + if (pamo!=NULL) { + // read its placement and model + strm>>pamo->amo_plRelative; + ReadModelObject_t(strm, pamo->amo_moModelObject); + } else { + // skip its placement and model + CPlacement3D plDummy; + strm>>plDummy; + SkipModelObject_t(strm); + } + } + } +} + +void SkipModelObject_t(CTStream &strm) +{ + CTFileName fnDummy; + CModelObject moDummy; + // skip model data filename + strm>>fnDummy; + // skip model object + moDummy.Read_t(&strm); + + // if model object has multiple textures + if (strm.PeekID_t() == CChunkID("MTEX")) { // 'multi-texturing' + // skip all textures + strm.ExpectID_t("MTEX"); // 'multi-texturing'' + SkipTextureObject_t(strm); // texture + SkipTextureObject_t(strm); // bump + SkipTextureObject_t(strm); // reflection + SkipTextureObject_t(strm); // specular + + // if model has single texture (old format) + } else { + // skip main texture + SkipTextureObject_t(strm); + } + + // if model object has attachments + if (strm.PeekID_t() == CChunkID("ATCH")) { // 'attachments' + // read attachments header + strm.ExpectID_t("ATCH"); // 'attachments' + INDEX ctAttachments; + strm>>ctAttachments; + // for each attachment + for(INDEX iAttachment=0; iAttachment>iPosition; + CPlacement3D plDummy; + strm>>plDummy; + SkipModelObject_t(strm); + } + } +} + +void WriteModelObject_t(CTStream &strm, CModelObject &mo) +{ + // write model data filename + CAnimData *pad = (CAnimData *)mo.GetData(); + if (pad!=NULL) { + strm<GetName(); + } else { + strm<amo_iAttachedPosition; + strm<amo_plRelative; + WriteModelObject_t(strm, pamo->amo_moModelObject); + } + } +} + +void WriteMeshInstances_t(CTStream &strm, CModelInstance &mi) +{ + // write mesh instance header + strm.WriteID_t("MSHI"); + // write all mesh instances for this model instance + INDEX ctmshi=mi.mi_aMeshInst.Count(); + strm<GetName(); + strm.WriteID_t("MESH"); + // write binary mesh file name + strm<GetName(); + CTString strTexID = ska_GetStringFromTable(ti.GetID()); + strm.WriteID_t("TITX"); + strm<GetName(); + strm<>strModelInstanceName; + mi.SetName(strModelInstanceName); + + // read all mesh instances for this model instance + INDEX ctmshi = 0; // mesh instance count + INDEX ctti = 0; // texture instance count + INDEX ctas = 0; // animset count + INDEX ctcb = 0; // colision boxes count + INDEX ctal = 0; // anim lists count + INDEX ctpa = 0; // played anims count + INDEX ctcmi = 0; // child model instance count + + strm>>ctmshi; + mi.mi_aMeshInst.New(ctmshi); + + // for each mesh + for(INDEX imshi=0;imshi>fnMesh; + mshi.mi_pMesh = _pMeshStock->Obtain_t(fnMesh); + + // read texture instances for this mesh instance + strm>>ctti; + mshi.mi_tiTextures.New(ctti); + // for each texture instance + for(INDEX iti=0;iti>fnTex; + strm>>strTexID; + + ti.SetName(strTexID); + ti.ti_toTexture.SetData_t(fnTex); + } + } + + // read this model instance skeleton binary file name + BOOL bHasSkeleton; + mi.mi_psklSkeleton = NULL; + + strm>>bHasSkeleton; + if(bHasSkeleton) { + CTFileName fnSkeleton; + strm>>fnSkeleton; + mi.mi_psklSkeleton = _pSkeletonStock->Obtain_t(fnSkeleton); + } + + // read animsets file names + strm>>ctas; + // for each animset in model instance + for(INDEX ias=0;ias>fnAnimSet; + CAnimSet *pas = _pAnimSetStock->Obtain_t(fnAnimSet); + mi.mi_aAnimSet.Add(pas); + } + + // read colision boxes + strm>>ctcb; + mi.mi_cbAABox.New(ctcb); + // for each colision box + for(INDEX icb=0;icb>cb.Min(); + strm>>cb.Max(); + } + + // read index of current colision box + strm>>mi.mi_iCurentBBox; + + // read stretch + strm>>mi.mi_vStretch; + // read color + strm>>mi.mi_colModelColor; + + // read animation queue + AnimQueue &aq = mi.mi_aqAnims; + strm>>ctal; + if(ctal>0) aq.aq_Lists.Push(ctal); + // for each anim list + for(INDEX ial=0;ial>al.al_fStartTime; + strm>>al.al_fFadeTime; + strm>>ctpa; + if(ctpa>0) al.al_PlayedAnims.Push(ctpa); + // for each played anim + for(INDEX ipa=0;ipa>pa.pa_fStartTime; + strm>>pa.pa_ulFlags; + strm>>pa.pa_Strength; + strm>>pa.pa_GroupID; + CTString strPlayedAnimID; + strm>>strPlayedAnimID; + pa.pa_iAnimID = ska_GetIDFromStringTable(strPlayedAnimID); + } + } + + // read model instance offset and parent bone + strm.Read_t(&mi.mi_qvOffset,sizeof(QVect)); + CTString strParenBoneID; + strm>>strParenBoneID; + mi.mi_iParentBoneID = ska_GetIDFromStringTable(strParenBoneID); + + // read model instance children + strm>>ctcmi; + // for each child model instance + for(INDEX icmi=0;icmi>ctmshi; + mi.mi_aMeshInst.New(ctmshi); + // for each mesh + for(INDEX imshi=0;imshi>fnMesh; + mshi.mi_pMesh = _pMeshStock->Obtain_t(fnMesh); + + // read texture instances for this mesh instance + strm.ExpectID_t("MITS"); // mesh instance texture instance + strm>>ctti; + mshi.mi_tiTextures.New(ctti); + // for each texture instance + for(INDEX iti=0;iti>fnTex; + strm>>strTexID; + + ti.SetName(strTexID); + ti.ti_toTexture.SetData_t(fnTex); + } + } +} + +void ReadSkeleton_t(CTStream &strm, CModelInstance &mi) +{ + // read this model instance skeleton binary file name + BOOL bHasSkeleton; + mi.mi_psklSkeleton = NULL; + + strm.ExpectID_t("SKEL"); + strm>>bHasSkeleton; + if(bHasSkeleton) { + CTFileName fnSkeleton; + strm>>fnSkeleton; + mi.mi_psklSkeleton = _pSkeletonStock->Obtain_t(fnSkeleton); + } +} + +void ReadAnimSets_t(CTStream &strm, CModelInstance &mi) +{ + INDEX ctas = 0; + strm.ExpectID_t("ANAS"); + // read animsets file names + strm>>ctas; + // for each animset in model instance + for(INDEX ias=0;ias>fnAnimSet; + CAnimSet *pas = _pAnimSetStock->Obtain_t(fnAnimSet); + mi.mi_aAnimSet.Add(pas); + } +} + +void ReadAnimQueue_t(CTStream &strm, CModelInstance &mi) +{ + INDEX ctal = 0; + INDEX ctpa = 0; + strm.ExpectID_t("MIAQ"); // model instance animation queue + // read animation queue + AnimQueue &aq = mi.mi_aqAnims; + strm>>ctal; + if(ctal>0) aq.aq_Lists.Push(ctal); + // for each anim list + for(INDEX ial=0;ial>al.al_fStartTime; + strm>>al.al_fFadeTime; + strm>>ctpa; + if(ctpa>0) al.al_PlayedAnims.Push(ctpa); + // for each played anim + for(INDEX ipa=0;ipa>pa.pa_fStartTime; + strm>>pa.pa_ulFlags; + strm>>pa.pa_Strength; + strm>>pa.pa_GroupID; + CTString strPlayedAnimID; + strm>>strPlayedAnimID; + pa.pa_iAnimID = ska_GetIDFromStringTable(strPlayedAnimID); + if(strm.PeekID_t()==CChunkID("PASP")) { + strm.ExpectID_t("PASP"); // played animation speed + strm>>pa.pa_fSpeedMul; + } + } + } +} + +void ReadColisionBoxes_t(CTStream &strm, CModelInstance &mi) +{ + INDEX ctcb = 0; + strm.ExpectID_t("MICB"); // model instance colision boxes + // read colision boxes + strm>>ctcb; + mi.mi_cbAABox.New(ctcb); + // for each colision box + for(INDEX icb=0;icb>cb.Min(); + strm>>cb.Max(); + strm>>strName; + cb.SetName(strName); + } + strm.ExpectID_t("AFBB"); // all frames bounding box + // read all frames bounding box + strm>>mi.mi_cbAllFramesBBox.Min(); + strm>>mi.mi_cbAllFramesBBox.Max(); +} + +void ReadOffsetAndChildren_t(CTStream &strm, CModelInstance &mi) +{ + INDEX ctcmi = 0; + strm.ExpectID_t("MIOF"); // model instance offset + // read model instance offset and parent bone + strm.Read_t(&mi.mi_qvOffset,sizeof(QVect)); + CTString strParenBoneID; + strm>>strParenBoneID; + mi.mi_iParentBoneID = ska_GetIDFromStringTable(strParenBoneID); + + strm.ExpectID_t("MICH"); // model instance child + // read model instance children + strm>>ctcmi; + // for each child model instance + for(INDEX icmi=0;icmi>strModelInstanceName; + mi.SetName(strModelInstanceName); + + // read index of current colision box + strm>>mi.mi_iCurentBBox; + // read stretch + strm>>mi.mi_vStretch; + // read color + strm>>mi.mi_colModelColor; + + ReadMeshInstances_t(strm,mi); + ReadSkeleton_t(strm, mi); + ReadAnimSets_t(strm, mi); + ReadAnimQueue_t(strm, mi); + ReadColisionBoxes_t(strm, mi); + ReadOffsetAndChildren_t(strm, mi); + strm.ExpectID_t("ME03"); // model instance end 02 +} + +void ReadModelInstance_t(CTStream &strm, CModelInstance &mi) +{ + // is model instance writen in old format + if(strm.PeekID_t() == CChunkID("SKMI")) { + ReadModelInstanceOld_t(strm, mi); + // is model instance writen in new format + } else if(strm.PeekID_t() == CChunkID("MI03")) { + ReadModelInstanceNew_t(strm, mi); + // unknown format + } else { + strm.Throw_t("Unknown model instance format"); + ASSERT(FALSE); + } +} + +void SkipModelInstance_t(CTStream &strm) +{ + CModelInstance miDummy; + ReadModelInstance_t(strm,miDummy); +} + +// read an anim object from a file together with its anim data filename +void ReadAnimObject_t(CTStream &strm, CAnimObject &ao) +{ + // read anim data filename + CTFileName fnAnim; + strm>>fnAnim; + // try to load anim + for(;;) { + try { + // set the anim data + ao.SetData_t(fnAnim); + break; + } catch( char *strError) { + (void) strError; + // if anim was not found, ask for replacing anim + CTFileName fnReplacingAnim; + if( GetReplacingFile( fnAnim, fnReplacingAnim, FILTER_ANI FILTER_END)) { + // replacing anim was provided + fnAnim = fnReplacingAnim; + } else { + ThrowF_t( TRANS("Cannot find substitution for \"%s\""), (CTString&)fnAnim); + } + } + } + // read anim object + ao.Read_t(&strm); +} + +void SkipAnimObject_t(CTStream &strm) +{ + CTFileName fnDummy; + CAnimObject aoDummy; + // skip anim data filename + strm>>fnDummy; + // skip anim object + aoDummy.Read_t(&strm); +} + +void WriteAnimObject_t(CTStream &strm, CAnimObject &ao) +{ + // write anim data filename + CAnimData *pad = (CAnimData *)ao.GetData(); + if (pad!=NULL) { + strm<GetName(); + } else { + strm< + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +//#ifdef c_plusplus +//#ifndef __cplusplus +//#define __cplusplus +//#endif +//#endif + +#if 1 //def __cplusplus + + #include + + /* Use prototypes in function declarations. */ + #define YY_USE_PROTOS + + /* The "const" storage-class-modifier is valid. */ + #define YY_USE_CONST + +#else /* ! __cplusplus */ + + #if __STDC__ + + #define YY_USE_PROTOS + #define YY_USE_CONST + + #endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( const char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( const char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +//static + void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, const char *, int )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( const char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 50 +#define YY_END_OF_BUFFER 51 +static yyconst short int yy_accept[165] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, + 51, 49, 47, 48, 29, 49, 49, 29, 29, 49, + 29, 30, 30, 29, 29, 29, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 38, 29, 39, + 45, 45, 42, 40, 41, 4, 4, 48, 2, 5, + 5, 6, 49, 6, 5, 47, 24, 0, 34, 0, + 37, 27, 0, 0, 43, 0, 32, 30, 0, 0, + 26, 21, 23, 22, 25, 36, 36, 36, 36, 36, + 36, 36, 36, 18, 36, 36, 36, 36, 36, 36, + 28, 44, 0, 3, 0, 2, 5, 5, 5, 0, + + 5, 0, 34, 37, 35, 35, 0, 46, 32, 32, + 0, 33, 31, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 15, 36, 36, 5, 33, 36, 36, + 36, 36, 19, 36, 17, 36, 36, 16, 12, 10, + 36, 7, 8, 11, 0, 36, 36, 36, 36, 36, + 0, 20, 14, 36, 36, 36, 20, 1, 36, 9, + 36, 36, 13, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 5, 6, 1, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 21, 22, 23, + 24, 25, 26, 1, 27, 28, 29, 30, 31, 32, + 33, 33, 34, 33, 33, 35, 33, 36, 37, 33, + 33, 33, 38, 39, 33, 33, 33, 40, 33, 33, + 41, 42, 43, 44, 33, 1, 28, 28, 45, 46, + + 47, 48, 49, 50, 51, 33, 33, 52, 33, 53, + 54, 55, 33, 56, 57, 58, 59, 60, 33, 61, + 33, 33, 62, 63, 64, 65, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[66] = + { 0, + 1, 1, 2, 2, 1, 2, 1, 1, 1, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, + 1, 2, 1, 1, 1, 1, 5, 5, 5, 5, + 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, + 1, 1, 1, 1, 5, 5, 5, 5, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 1, 1, 1, 1 + } ; + +static yyconst short int yy_base[179] = + { 0, + 0, 0, 63, 64, 65, 66, 68, 76, 81, 89, + 323, 324, 71, 324, 298, 75, 0, 324, 312, 278, + 76, 79, 85, 77, 295, 82, 0, 279, 282, 280, + 261, 36, 267, 60, 65, 256, 258, 324, 248, 324, + 324, 292, 324, 324, 324, 303, 116, 302, 324, 265, + 131, 324, 103, 324, 82, 132, 324, 108, 324, 109, + 0, 324, 296, 295, 324, 301, 122, 127, 141, 0, + 324, 324, 324, 324, 324, 0, 265, 265, 271, 247, + 242, 240, 245, 0, 251, 239, 237, 246, 245, 240, + 324, 324, 284, 324, 160, 324, 247, 121, 135, 137, + + 324, 142, 143, 0, 324, 278, 284, 324, 156, 324, + 148, 161, 0, 228, 258, 253, 226, 235, 234, 225, + 206, 187, 150, 0, 151, 159, 150, 324, 146, 162, + 160, 140, 148, 141, 0, 137, 144, 0, 0, 0, + 143, 0, 0, 0, 155, 143, 137, 143, 129, 130, + 134, 0, 0, 131, 114, 122, 324, 0, 118, 0, + 85, 32, 0, 324, 209, 215, 221, 227, 233, 235, + 241, 244, 250, 256, 262, 265, 271, 274 + } ; + +static yyconst short int yy_def[179] = + { 0, + 164, 1, 165, 165, 166, 166, 167, 167, 168, 168, + 164, 164, 164, 164, 164, 169, 170, 164, 164, 171, + 164, 164, 164, 164, 164, 164, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 164, 164, 164, + 164, 164, 164, 164, 164, 173, 173, 173, 164, 174, + 174, 164, 175, 164, 174, 164, 164, 169, 164, 169, + 176, 164, 164, 164, 164, 177, 164, 164, 164, 178, + 164, 164, 164, 164, 164, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 164, 164, 173, 164, 173, 164, 174, 174, 174, 175, + + 164, 175, 169, 176, 164, 164, 177, 164, 164, 164, + 164, 164, 178, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 175, 164, 172, 172, + 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, + 172, 172, 172, 172, 164, 172, 172, 172, 172, 172, + 164, 172, 172, 172, 172, 172, 164, 172, 172, 172, + 172, 172, 172, 0, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164 + } ; + +static yyconst short int yy_nxt[390] = + { 0, + 12, 13, 14, 13, 15, 16, 17, 18, 19, 20, + 18, 18, 18, 18, 18, 18, 18, 21, 22, 23, + 18, 18, 24, 25, 26, 18, 27, 27, 28, 27, + 27, 29, 27, 30, 27, 27, 27, 27, 27, 27, + 18, 12, 18, 18, 31, 27, 32, 27, 27, 33, + 34, 27, 27, 27, 35, 27, 27, 27, 36, 37, + 27, 38, 39, 40, 18, 14, 14, 14, 14, 47, + 48, 47, 56, 49, 56, 42, 42, 47, 48, 47, + 59, 49, 51, 52, 13, 97, 53, 81, 65, 163, + 51, 52, 13, 66, 53, 67, 82, 68, 68, 71, + + 72, 67, 54, 68, 68, 74, 75, 84, 101, 69, + 54, 86, 85, 59, 103, 69, 60, 95, 87, 95, + 88, 96, 55, 98, 97, 69, 44, 44, 45, 45, + 55, 69, 99, 56, 56, 56, 99, 162, 56, 70, + 109, 109, 101, 67, 102, 68, 68, 127, 59, 60, + 60, 145, 69, 110, 111, 101, 111, 69, 145, 112, + 112, 95, 98, 95, 161, 96, 112, 112, 69, 110, + 160, 159, 98, 69, 109, 109, 98, 158, 102, 112, + 112, 157, 156, 102, 60, 155, 69, 110, 154, 153, + 152, 102, 128, 150, 149, 148, 147, 144, 146, 143, + + 142, 141, 69, 110, 140, 151, 139, 138, 128, 41, + 41, 41, 41, 41, 41, 43, 43, 43, 43, 43, + 43, 46, 46, 46, 46, 46, 46, 50, 50, 50, + 50, 50, 50, 58, 58, 58, 58, 58, 58, 61, + 61, 63, 63, 137, 63, 63, 63, 76, 76, 76, + 93, 93, 93, 93, 93, 93, 97, 136, 97, 97, + 97, 97, 100, 100, 100, 100, 100, 100, 104, 104, + 104, 107, 107, 107, 107, 107, 107, 113, 113, 135, + 134, 133, 132, 131, 130, 129, 108, 105, 98, 94, + 126, 125, 124, 123, 122, 121, 120, 119, 118, 117, + + 116, 115, 114, 108, 106, 105, 98, 94, 94, 92, + 91, 90, 89, 83, 80, 79, 78, 77, 73, 64, + 62, 57, 164, 11, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164 + } ; + +static yyconst short int yy_chk[390] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 4, 5, 6, 7, + 7, 7, 13, 7, 13, 3, 4, 8, 8, 8, + 16, 8, 9, 9, 9, 55, 9, 32, 21, 162, + 10, 10, 10, 21, 10, 22, 32, 22, 22, 24, + + 24, 23, 9, 23, 23, 26, 26, 34, 53, 22, + 10, 35, 34, 58, 60, 23, 16, 47, 35, 47, + 35, 47, 9, 55, 98, 22, 5, 6, 5, 6, + 10, 23, 51, 56, 51, 56, 99, 161, 99, 22, + 67, 67, 100, 68, 53, 68, 68, 102, 103, 58, + 60, 133, 67, 67, 69, 127, 69, 68, 145, 69, + 69, 95, 98, 95, 159, 95, 111, 111, 67, 67, + 156, 155, 51, 68, 109, 109, 99, 154, 100, 112, + 112, 151, 150, 102, 103, 149, 109, 109, 148, 147, + 146, 127, 112, 141, 137, 136, 134, 132, 133, 131, + + 130, 129, 109, 109, 126, 145, 125, 123, 112, 165, + 165, 165, 165, 165, 165, 166, 166, 166, 166, 166, + 166, 167, 167, 167, 167, 167, 167, 168, 168, 168, + 168, 168, 168, 169, 169, 169, 169, 169, 169, 170, + 170, 171, 171, 122, 171, 171, 171, 172, 172, 172, + 173, 173, 173, 173, 173, 173, 174, 121, 174, 174, + 174, 174, 175, 175, 175, 175, 175, 175, 176, 176, + 176, 177, 177, 177, 177, 177, 177, 178, 178, 120, + 119, 118, 117, 116, 115, 114, 107, 106, 97, 93, + 90, 89, 88, 87, 86, 85, 83, 82, 81, 80, + + 79, 78, 77, 66, 64, 63, 50, 48, 46, 42, + 39, 37, 36, 33, 31, 30, 29, 28, 25, 20, + 19, 15, 11, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, + 164, 164, 164, 164, 164, 164, 164, 164, 164 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *yytext; +#line 1 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +#define INITIAL 0 +#line 2 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +#include "ParsingSymbols.h" +#include "Parser.h" + +#include +#include +#include +#include +#include + +#include + +#define YY_DECL int yylex (YYSTYPE *lvalp) +#define yylval (*lvalp) + +int yywrap(void) +{ + // no more bufers + return 1; +}; + +static int _iBlockDepth = 0; +static int _iDummyDepth = 0; +static CTString _strCmd = ""; // currently parsed command +static int _ctCmdParam = 1; // current parameter index +static BOOL _bCmdParamCountErrorReported = FALSE; + +void TranscriptEsc(CTString &str) +{ + char *pchSrc = (char *)(const char *)str; + char *pchDst = (char *)(const char *)str; + // if quoted + if (pchDst[0] == '"') { + int len = strlen(pchDst); + pchDst[len-1] = 0; + memmove(pchDst, pchDst+1, len-1); + } + for (;;pchSrc++, pchDst++) { + if (*pchSrc==0) { + break; + } + if (*pchSrc!='\\') { + *pchDst = *pchSrc; + continue; + } + pchSrc++; + switch(*pchSrc) { + case 'n': *pchDst = 10; break; + case 'r': *pchDst = 13; break; + default: *pchDst = *pchSrc; break; + } + } + *pchDst=0; +} + +#define COMMENT 1 + +#define DUMMYBLOCK 2 + +#define INCLUDE 3 + +#define COMMAND 4 + +#line 591 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.cpp" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifdef YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 75 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" + + + /*\0 yyterminate();*/ + + /* Include file parsing. */ +#line 720 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.cpp" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 165 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 324 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 80 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +BEGIN(INCLUDE); + YY_BREAK +case 2: +YY_RULE_SETUP +#line 82 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +/* eat the whitespace until first quote */ + YY_BREAK +case 3: +YY_RULE_SETUP +#line 83 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ /* get the include file name until second quote */ + if (ShellGetBufferStackDepth() >= SHELL_MAX_INCLUDE_LEVEL) { + _pShell->ErrorF("Script files nested too deeply"); + } + char strFileName[256]; + strcpy(strFileName, yytext); + strFileName[strlen(strFileName)-1] = 0; + + CTString strIncludeFile; + try { + strIncludeFile.Load_t(CTString(strFileName)); + ShellPushBuffer(strFileName, strIncludeFile, FALSE); + + } catch(char *strError) { + _pShell->ErrorF("Cannot load script file '%s': %s", yytext, strError); + } + BEGIN(INITIAL); +} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 101 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ /* something unrecognized inside include statement */ + _pShell->ErrorF("Wrong syntax for include statement"); + BEGIN(INITIAL); +} + YY_BREAK +/* command parsing */ +case 5: +YY_RULE_SETUP +#line 107 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ // for each parameter + _ctCmdParam++; + CTString strParam = yytext; + TranscriptEsc(strParam); + // insert the parameter in the command string + CTString strParamNo = CTString(1, "%%%d", _ctCmdParam); + if (strParam.FindSubstr(strParamNo)!=-1) { + _pShell->ErrorF("Parameter substitution recursion detected!"); + } else { + INDEX ctFound=0; + for(;; ctFound++) { + if (!_strCmd.ReplaceSubstr(strParamNo, strParam)) { + break; + } + } + // if not found and parameter count error not reported yet + if (ctFound==0 && !_bCmdParamCountErrorReported) { + // report error + _bCmdParamCountErrorReported = TRUE; + _pShell->ErrorF("Too many parameters for command expansion"); + } + } +} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 130 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ + // at the end of the command + + // switch to the new input buffer with that command + ShellPushBuffer(ShellGetBufferName(), _strCmd, FALSE); + BEGIN(INITIAL); +} + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMENT): +case YY_STATE_EOF(DUMMYBLOCK): +case YY_STATE_EOF(INCLUDE): +case YY_STATE_EOF(COMMAND): +#line 138 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ + if (ShellPopBuffer()) { + yyterminate(); + } +} + YY_BREAK +/* special data types */ +case 7: +YY_RULE_SETUP +#line 145 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_FLOAT);} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 146 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_INDEX);} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 147 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_CTString);} + YY_BREAK +/* keywords */ +case 10: +YY_RULE_SETUP +#line 150 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_void); } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 151 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_const); } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 152 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_user); } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 153 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_persistent); } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 154 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_extern); } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 155 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_pre); } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 156 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_post); } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 157 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_help); } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 158 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_if); } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 159 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_else); } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 160 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(k_else_if); } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 162 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return (LEQ); } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 163 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return (GEQ); } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 164 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return (EQ); } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 165 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return (NEQ); } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 167 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return (SHR); } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 168 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return (SHL); } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 170 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return (LOGAND); } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 171 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return (LOGOR); } + YY_BREAK +/* single character operators and punctuations */ +case 29: +YY_RULE_SETUP +#line 174 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ + return(yytext[0]);} + YY_BREAK +/* constants */ +case 30: +YY_RULE_SETUP +#line 178 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ yylval.val.iIndex = atoi(yytext); return(c_int); } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 179 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ yylval.val.iIndex = strtoul(yytext+2, NULL, 16); return(c_int); } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 180 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ yylval.val.fFloat = (float) atof(yytext); return(c_float); } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 181 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ yylval.val.fFloat = (float) atof(yytext); return(c_float); } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 182 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ + CTString &strNew = _shell_astrTempStrings.Push(); + // remove double-quotes + strNew = yytext; + // parse escape symbols and remove double quotes + TranscriptEsc(strNew); + yylval.val.strString = (const char*)strNew; + return(c_string); +} + YY_BREAK +case 35: +YY_RULE_SETUP +#line 191 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ return(c_char); } + YY_BREAK +/* identifier */ +case 36: +YY_RULE_SETUP +#line 194 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ + // get the symbol + yylval.pssSymbol = _pShell->GetSymbol(yytext, FALSE); + BOOL bCommand = FALSE; + // if it is string + if (_shell_ast[yylval.pssSymbol->ss_istType].st_sttType==STT_STRING) { + // get the value + CTString str = *(CTString*)yylval.pssSymbol->ss_pvValue; + // if the value tells that it is a command + if (str.RemovePrefix("!command ")) { + // parse the command + bCommand = TRUE; + _strCmd = str; + _ctCmdParam = 0; + _bCmdParamCountErrorReported = FALSE; + BEGIN(COMMAND); + } + } + // normally, just return the identifier + if (!bCommand) { + return(identifier); + } +} + YY_BREAK +case 37: +YY_RULE_SETUP +#line 217 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ // special case of identifier, used to bypass command parsing + // get the symbol + yylval.pssSymbol = _pShell->GetSymbol(yytext+1, FALSE); + return(identifier); +} + YY_BREAK +/* eat up or execute blocks */ +case 38: +YY_RULE_SETUP +#line 224 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ + _iBlockDepth++; + if (!_bExecNextBlock) { + _iDummyDepth++; + BEGIN(DUMMYBLOCK); + } + return block_beg; +} + YY_BREAK +case 39: +YY_RULE_SETUP +#line 233 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ + _iBlockDepth--; + if (_iBlockDepth<0) { + _pShell->ErrorF("Mismatched '}'"); + } + return block_end; +} + YY_BREAK +case 40: +YY_RULE_SETUP +#line 240 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ + _iBlockDepth++; + _iDummyDepth++; +} + YY_BREAK +case 41: +YY_RULE_SETUP +#line 244 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ + _iBlockDepth--; + _iDummyDepth--; + if (_iDummyDepth==0) { + BEGIN(INITIAL); + return block_end; + } +} + YY_BREAK +case 42: +YY_RULE_SETUP +#line 252 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{} + YY_BREAK +/* eat up comments */ +case 43: +YY_RULE_SETUP +#line 255 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ BEGIN(COMMENT); } + YY_BREAK +case 44: +YY_RULE_SETUP +#line 256 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ BEGIN(INITIAL); } + YY_BREAK +case 45: +YY_RULE_SETUP +#line 257 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{} + YY_BREAK +case 46: +YY_RULE_SETUP +#line 258 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ ShellCountOneLine(); } + YY_BREAK +/* eat up whitespace */ +case 47: +YY_RULE_SETUP +#line 262 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ +} + YY_BREAK +/* eat up linefeeds and count lines in all conditions */ +case 48: +YY_RULE_SETUP +#line 265 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ + ShellCountOneLine(); +} + YY_BREAK +/* for all unrecognized characters */ +case 49: +YY_RULE_SETUP +#line 270 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +{ + // report an error + _pShell->ErrorF("Unrecognized character '%c' (ASCII 0x%02x)", yytext[0], yytext[0] ); +} + YY_BREAK +case 50: +YY_RULE_SETUP +#line 275 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" +ECHO; + YY_BREAK +#line 1188 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.cpp" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 165 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 165 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 164); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifdef YY_USE_PROTOS +//static + void yyunput( int c, register char *yy_bp ) +#else +//static + void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#ifdef YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#ifdef YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( const char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +const char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( const char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +const char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( const char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, const char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +const char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + return (void *) realloc( ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#ifdef YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 275 "D:\\SE1_GPL\\Sources\\Engine\\Base\\\\Scanner.l" + + diff --git a/Sources/Engine/Base/Scanner.l b/Sources/Engine/Base/Scanner.l new file mode 100644 index 0000000..fe991d3 --- /dev/null +++ b/Sources/Engine/Base/Scanner.l @@ -0,0 +1,276 @@ +%{ +#include "ParsingSymbols.h" +#include "Parser.h" + +#include +#include +#include +#include +#include + +#include + +#define YY_DECL int yylex (YYSTYPE *lvalp) +#define yylval (*lvalp) + +int yywrap(void) +{ + // no more bufers + return 1; +}; + +static int _iBlockDepth = 0; +static int _iDummyDepth = 0; +static CTString _strCmd = ""; // currently parsed command +static int _ctCmdParam = 1; // current parameter index +static BOOL _bCmdParamCountErrorReported = FALSE; + +void TranscriptEsc(CTString &str) +{ + char *pchSrc = (char *)(const char *)str; + char *pchDst = (char *)(const char *)str; + // if quoted + if (pchDst[0] == '"') { + int len = strlen(pchDst); + pchDst[len-1] = 0; + memmove(pchDst, pchDst+1, len-1); + } + for (;;pchSrc++, pchDst++) { + if (*pchSrc==0) { + break; + } + if (*pchSrc!='\\') { + *pchDst = *pchSrc; + continue; + } + pchSrc++; + switch(*pchSrc) { + case 'n': *pchDst = 10; break; + case 'r': *pchDst = 13; break; + default: *pchDst = *pchSrc; break; + } + } + *pchDst=0; +} + +%} + +%x COMMENT +%x DUMMYBLOCK +%x INCLUDE +%x COMMAND + +DIGIT [0-9] +HEXDIGIT [0-9A-Fa-f] +IDENTIFIERFIRST [A-Za-z_] +IDENTIFIEROTHER [A-Za-z0-9_] +DOUBLEQUOTE \" +STRINGCONTENT ([^\"]|(\\\")) +CHARCONTENT ([^\']|(\\\')) +NONEXP_FLT ({DIGIT}+"."{DIGIT}*) +EXP_FLT (({DIGIT}+("."({DIGIT}*)?)?)("E"|"e")("+"|"-")?{DIGIT}+) + +PARAMCONTENT ([^\ \n\";]|(\\\ )) + +%% + + /*\0 yyterminate();*/ + + /* Include file parsing. */ +"include" BEGIN(INCLUDE); + +[ \t]*"\"" /* eat the whitespace until first quote */ +[^"\""]*"\"" { /* get the include file name until second quote */ + if (ShellGetBufferStackDepth() >= SHELL_MAX_INCLUDE_LEVEL) { + _pShell->ErrorF("Script files nested too deeply"); + } + char strFileName[256]; + strcpy(strFileName, yytext); + strFileName[strlen(strFileName)-1] = 0; + + CTString strIncludeFile; + try { + strIncludeFile.Load_t(CTString(strFileName)); + ShellPushBuffer(strFileName, strIncludeFile, FALSE); + + } catch(char *strError) { + _pShell->ErrorF("Cannot load script file '%s': %s", yytext, strError); + } + BEGIN(INITIAL); +} +. { /* something unrecognized inside include statement */ + _pShell->ErrorF("Wrong syntax for include statement"); + BEGIN(INITIAL); +} + + /* command parsing */ +{PARAMCONTENT}*|"\""{STRINGCONTENT}*"\"" { // for each parameter + _ctCmdParam++; + CTString strParam = yytext; + TranscriptEsc(strParam); + // insert the parameter in the command string + CTString strParamNo = CTString(1, "%%%d", _ctCmdParam); + if (strParam.FindSubstr(strParamNo)!=-1) { + _pShell->ErrorF("Parameter substitution recursion detected!"); + } else { + INDEX ctFound=0; + for(;; ctFound++) { + if (!_strCmd.ReplaceSubstr(strParamNo, strParam)) { + break; + } + } + // if not found and parameter count error not reported yet + if (ctFound==0 && !_bCmdParamCountErrorReported) { + // report error + _bCmdParamCountErrorReported = TRUE; + _pShell->ErrorF("Too many parameters for command expansion"); + } + } +} +\n|; { + // at the end of the command + + // switch to the new input buffer with that command + ShellPushBuffer(ShellGetBufferName(), _strCmd, FALSE); + BEGIN(INITIAL); +} + +<> { + if (ShellPopBuffer()) { + yyterminate(); + } +} + + /* special data types */ +"FLOAT" { return(k_FLOAT);} +"INDEX" { return(k_INDEX);} +"CTString" { return(k_CTString);} + + /* keywords */ +"void" { return(k_void); } +"const" { return(k_const); } +"user" { return(k_user); } +"persistent" { return(k_persistent); } +"extern" { return(k_extern); } +"pre" { return(k_pre); } +"post" { return(k_post); } +"help" { return(k_help); } +"if" { return(k_if); } +"else" { return(k_else); } +"else"" "*"if" { return(k_else_if); } + +"<=" { return (LEQ); } +">=" { return (GEQ); } +"==" { return (EQ); } +"!=" { return (NEQ); } + +">>" { return (SHR); } +"<<" { return (SHL); } + +"&&" { return (LOGAND); } +"||" { return (LOGOR); } + + /* single character operators and punctuations */ +";"|"("|")"|"="|"+"|"-"|"<"|">"|"!"|"|"|"&"|"*"|"/"|"%"|"^"|"["|"]"|":"|","|"."|"?"|"~" { + return(yytext[0]);} + + /* constants */ +{DIGIT}+ { yylval.val.iIndex = atoi(yytext); return(c_int); } +"0x"{HEXDIGIT}+ { yylval.val.iIndex = strtoul(yytext+2, NULL, 16); return(c_int); } +{NONEXP_FLT}("f"|"F")? { yylval.val.fFloat = (float) atof(yytext); return(c_float); } +{EXP_FLT}("f"|"F")? { yylval.val.fFloat = (float) atof(yytext); return(c_float); } +"\""{STRINGCONTENT}*"\"" { + CTString &strNew = _shell_astrTempStrings.Push(); + // remove double-quotes + strNew = yytext; + // parse escape symbols and remove double quotes + TranscriptEsc(strNew); + yylval.val.strString = (const char*)strNew; + return(c_string); +} +"'"{CHARCONTENT}"'" { return(c_char); } + + /* identifier */ +{IDENTIFIERFIRST}{IDENTIFIEROTHER}* { + // get the symbol + yylval.pssSymbol = _pShell->GetSymbol(yytext, FALSE); + BOOL bCommand = FALSE; + // if it is string + if (_shell_ast[yylval.pssSymbol->ss_istType].st_sttType==STT_STRING) { + // get the value + CTString str = *(CTString*)yylval.pssSymbol->ss_pvValue; + // if the value tells that it is a command + if (str.RemovePrefix("!command ")) { + // parse the command + bCommand = TRUE; + _strCmd = str; + _ctCmdParam = 0; + _bCmdParamCountErrorReported = FALSE; + BEGIN(COMMAND); + } + } + // normally, just return the identifier + if (!bCommand) { + return(identifier); + } +} +${IDENTIFIERFIRST}{IDENTIFIEROTHER}* { // special case of identifier, used to bypass command parsing + // get the symbol + yylval.pssSymbol = _pShell->GetSymbol(yytext+1, FALSE); + return(identifier); +} + + /* eat up or execute blocks */ +"{" { + _iBlockDepth++; + if (!_bExecNextBlock) { + _iDummyDepth++; + BEGIN(DUMMYBLOCK); + } + return block_beg; +} + +"}" { + _iBlockDepth--; + if (_iBlockDepth<0) { + _pShell->ErrorF("Mismatched '}'"); + } + return block_end; +} +"{" { + _iBlockDepth++; + _iDummyDepth++; +} +"}" { + _iBlockDepth--; + _iDummyDepth--; + if (_iDummyDepth==0) { + BEGIN(INITIAL); + return block_end; + } +} +. {} + + /* eat up comments */ +"/*" { BEGIN(COMMENT); } +"*/" { BEGIN(INITIAL); } +. {} +"//"[^\n]*\n { ShellCountOneLine(); } + + + /* eat up whitespace */ +[ \t]+ { +} + /* eat up linefeeds and count lines in all conditions */ +<*>\n { + ShellCountOneLine(); +} + + /* for all unrecognized characters */ +. { + // report an error + _pShell->ErrorF("Unrecognized character '%c' (ASCII 0x%02x)", yytext[0], yytext[0] ); +} + +%% + diff --git a/Sources/Engine/Base/Serial.cpp b/Sources/Engine/Base/Serial.cpp new file mode 100644 index 0000000..378f7f7 --- /dev/null +++ b/Sources/Engine/Base/Serial.cpp @@ -0,0 +1,149 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include + +/* + * Default constructor. + */ +CSerial::CSerial( void) : ser_ctUsed(0) // not used initially +{ +} + +/* + * Destructor. + */ +CSerial::~CSerial( void) +{ + // must not be used at all + ASSERT(ser_ctUsed == 0); // look at _strLastCleared for possible name +} + +/* + * Clear the object. + */ +void CSerial::Clear(void) +{ + // mark that you have changed + MarkChanged(); + + // clear the filename + ser_FileName.Clear(); +} + +/* Get the description of this object. */ +CTString CSerial::GetDescription(void) +{ + return ""; +} + +/* + * Load from file. + */ +void CSerial::Load_t(const CTFileName fnFileName) // throw char * +{ + ASSERT(!IsUsed()); + // mark that you have changed + MarkChanged(); + + // open a stream + CTFileStream istrFile; + istrFile.Open_t(fnFileName); + // read object from stream + Read_t(&istrFile); + // if still here (no exceptions raised) + // remember filename + ser_FileName = fnFileName; +} + +/* + * Reload from file. + */ +void CSerial::Reload(void) +{ + // mark that you have changed + MarkChanged(); + + CTFileName fnmOldName = ser_FileName; + Clear(); + // try to + //try { + // open a stream + CTFileStream istrFile; + istrFile.Open_t(fnmOldName); + // read object from stream + Read_t(&istrFile); + + // if there is some error while reloading + //} catch (char *strError) { + // quit the application with error explanation + //FatalError(TRANS("Cannot reload file '%s':\n%s"), (CTString&)fnmOldName, strError); + //} + + // if still here (no exceptions raised) + // remember filename + ser_FileName = fnmOldName; +} + +/* + * Save to file. + */ +void CSerial::Save_t(const CTFileName fnFileName) // throw char * +{ + // open a stream + CTFileStream ostrFile; + ostrFile.Create_t(fnFileName); + // write object to stream + Write_t(&ostrFile); + // if still here (no exceptions raised) + // remember new filename + ser_FileName = fnFileName; +} + +/* + * Mark that object is used once more. + */ +void CSerial::MarkUsed(void) +{ + // use count must not have dropped below zero + ASSERT(ser_ctUsed>=0); + // increment use count + ser_ctUsed++; +} + +/* + * Mark that object is used once less. + */ +void CSerial::MarkUnused(void) +{ + // decrement use count + ser_ctUsed--; + // use count must not have dropped below zero + ASSERT(ser_ctUsed>=0); +} + +/* + * Check if object is used at least once. + */ +BOOL CSerial::IsUsed(void) +{ + // use count must not have dropped below zero + ASSERT(ser_ctUsed>=0); + + return ser_ctUsed>0; +} +INDEX CSerial::GetUsedCount(void) +{ + return ser_ctUsed; +} + +// gather the CRC of the file +void CSerial::AddToCRCTable(void) +{ + // add the file to CRC table + CRCT_AddFile_t(ser_FileName); +} diff --git a/Sources/Engine/Base/Serial.h b/Sources/Engine/Base/Serial.h new file mode 100644 index 0000000..80816bd --- /dev/null +++ b/Sources/Engine/Base/Serial.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SERIAL_H +#define SE_INCL_SERIAL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + + /* + * Abstract base class for objects that can be saved and loaded. + */ +class ENGINE_API CSerial : public CChangeable { +public: + INDEX ser_ctUsed; // use count + CTFileName ser_FileName; // last file name loaded + +public: + /* Default constructor. */ + CSerial(void); + /* Destructor. */ + virtual ~CSerial( void); + + /* Get the file name of this object. */ + inline const CTFileName &GetName(void) { return ser_FileName; }; + /* Get the description of this object. */ + virtual CTString GetDescription(void); + /* Load from file. */ + void Load_t( const CTFileName fnFileName); // throw char * + /* Save to file. */ + void Save_t( const CTFileName fnFileName); // throw char * + /* Reload from file. */ + void Reload(void); + /* Mark that object is used once more. */ + void MarkUsed(void); + /* Mark that object is used once less. */ + void MarkUnused(void); + /* Check if object is used at least once. */ + BOOL IsUsed(void); + INDEX GetUsedCount(void); + + /* Clear the object. */ + virtual void Clear(void); + /* Read from stream. */ + virtual void Read_t( CTStream *istrFile)=0; // throw char * + /* Write to stream. */ + virtual void Write_t( CTStream *ostrFile)=0; // throw char * + // check if this kind of objects is auto-freed + virtual BOOL IsAutoFreed(void) { return TRUE; }; + // get amount of memory used by this object + virtual SLONG GetUsedMemory(void) { return -1; }; + // gather the CRC of the file + virtual void AddToCRCTable(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Shell.cpp b/Sources/Engine/Base/Shell.cpp new file mode 100644 index 0000000..b6c1ff3 --- /dev/null +++ b/Sources/Engine/Base/Shell.cpp @@ -0,0 +1,897 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include "ParsingSymbols.h" + +#include +#include +#include + +#include +#include +#include + +template CDynamicArray; + +// shell type used for undeclared symbols +extern INDEX _shell_istUndeclared = -1; + +// pointer to global shell object +CShell *_pShell = NULL; +void *_pvNextToDeclare=NULL; // != NULL if declaring external symbol defined in exe code + +// define console variable for number of last console lines +extern INDEX con_iLastLines = 5; + +extern void yy_switch_to_buffer(YY_BUFFER_STATE); + +// declarations for recursive shell script parsing +struct BufferStackEntry { + YY_BUFFER_STATE bse_bs; + const char *bse_strName; + const char *bse_strContents; + int bse_iLineCt; + BOOL bse_bParserEnd; +}; + +static BufferStackEntry _abseBufferStack[SHELL_MAX_INCLUDE_LEVEL]; +static int _ibsBufferStackTop = -1; + +BOOL _bExecNextBlock = 1; + +void ShellPushBuffer(const char *strName, const char *strBuffer, BOOL bParserEnd) +{ + _ibsBufferStackTop++; + + _abseBufferStack[_ibsBufferStackTop].bse_strContents = strdup(strBuffer); + _abseBufferStack[_ibsBufferStackTop].bse_strName = strdup(strName); + _abseBufferStack[_ibsBufferStackTop].bse_iLineCt = 1; + _abseBufferStack[_ibsBufferStackTop].bse_bParserEnd = bParserEnd; + + _abseBufferStack[_ibsBufferStackTop].bse_bs = yy_scan_string((char*)(const char*)strBuffer); + + yy_switch_to_buffer(_abseBufferStack[_ibsBufferStackTop].bse_bs); +} +BOOL ShellPopBuffer(void) +{ + yy_delete_buffer( _abseBufferStack[_ibsBufferStackTop].bse_bs); + free((void*)_abseBufferStack[_ibsBufferStackTop].bse_strName); + free((void*)_abseBufferStack[_ibsBufferStackTop].bse_strContents); + BOOL bParserEnd = _abseBufferStack[_ibsBufferStackTop].bse_bParserEnd; + + _ibsBufferStackTop--; + + if (_ibsBufferStackTop>=0) { + yy_switch_to_buffer(_abseBufferStack[_ibsBufferStackTop].bse_bs); + } + return bParserEnd; +} +const char *ShellGetBufferName(void) +{ + return _abseBufferStack[_ibsBufferStackTop].bse_strName; +} +int ShellGetBufferLineNumber(void) +{ + return _abseBufferStack[_ibsBufferStackTop].bse_iLineCt; +} +int ShellGetBufferStackDepth(void) +{ + return _ibsBufferStackTop; +} +const char *ShellGetBufferContents(void) +{ + return _abseBufferStack[_ibsBufferStackTop].bse_strContents; +} +void ShellCountOneLine(void) +{ + _abseBufferStack[_ibsBufferStackTop].bse_iLineCt++; +} + + +// temporary values for parsing +CDynamicStackArray _shell_astrTempStrings; +// values for extern declarations +CDynamicStackArray _shell_astrExtStrings; +CDynamicStackArray _shell_afExtFloats; + +static const char *strCommandLine = ""; + +ENGINE_API extern FLOAT tmp_af[10] = { 0 }; +ENGINE_API extern INDEX tmp_ai[10] = { 0 }; +ENGINE_API extern INDEX tmp_fAdd = 0.0f; +ENGINE_API extern INDEX tmp_i = 0; + +void CShellSymbol::Clear(void) +{ + ss_istType = -1; + ss_strName.Clear(); + ss_ulFlags = 0; +}; +BOOL CShellSymbol::IsDeclared(void) +{ + return ss_istType>=0 && ss_istType!=_shell_istUndeclared; +} + +CTString CShellSymbol::GetCompletionString(void) const +{ + // get its type + ShellType &st = _shell_ast[ss_istType]; + + // get its name + if (st.st_sttType==STT_FUNCTION) { + return ss_strName + "()"; + } else if (st.st_sttType==STT_ARRAY) { + return ss_strName + "[]"; + } else { + return ss_strName; + } +} + +// Constructor. +CShell::CShell(void) +{ + // allocate undefined symbol + _shell_istUndeclared = _shell_ast.Allocate(); +}; +CShell::~CShell(void) +{ + _shell_astrExtStrings.Clear(); + _shell_afExtFloats.Clear(); +}; + +static const INDEX _bTRUE = TRUE; +static const INDEX _bFALSE = FALSE; + +CTString ScriptEsc(const CTString &str) +{ + CTString strResult = ""; + + const char *pchSrc = (const char *)str; + char buf[2]; + buf[1] = 0; + + while (*pchSrc!=0) { + switch(*pchSrc) { + case 10: strResult+="\\n"; break; + case 13: strResult+="\\r"; break; + case '\\': strResult+="\\\\"; break; + case '"': strResult+="\\\""; break; + default: buf[0] = *pchSrc; strResult+=buf; break; + } + pchSrc++; + } + return strResult; +} + +#pragma inline_depth(0) +void MakeAccessViolation(void* pArgs) +{ + INDEX bDont = NEXTARGUMENT(INDEX); + if( bDont) return; + char *p=NULL; + *p=1; +} + +extern int _a=123; +void MakeStackOverflow(void* pArgs) +{ + INDEX bDont = NEXTARGUMENT(INDEX); + if( bDont) return; + int a[1000]; + a[999] = _a; + MakeStackOverflow(0); + _a=a[999]; +} + +void MakeFatalError(void* pArgs) +{ + INDEX bDont = NEXTARGUMENT(INDEX); + if( bDont) return; + FatalError( "MakeFatalError()"); +} + + +extern void ReportGlobalMemoryStatus(void) +{ + CPrintF(TRANS("Global memory status...\n")); + + MEMORYSTATUS ms; + GlobalMemoryStatus(&ms); + +#define MB (1024*1024) + CPrintF(TRANS(" Physical memory used: %4d/%4dMB\n"), (ms.dwTotalPhys -ms.dwAvailPhys )/MB, ms.dwTotalPhys /MB); + CPrintF(TRANS(" Page file used: %4d/%4dMB\n"), (ms.dwTotalPageFile-ms.dwAvailPageFile)/MB, ms.dwTotalPageFile/MB); + CPrintF(TRANS(" Virtual memory used: %4d/%4dMB\n"), (ms.dwTotalVirtual -ms.dwAvailVirtual )/MB, ms.dwTotalVirtual /MB); + CPrintF(TRANS(" Memory load: %3d%%\n"), ms.dwMemoryLoad); + + DWORD dwMin; + DWORD dwMax; + GetProcessWorkingSetSize(GetCurrentProcess(), &dwMin, &dwMax); + CPrintF(TRANS(" Process working set: %dMB-%dMB\n\n"), dwMin/(1024*1024), dwMax/(1024*1024)); +} + +static void MemoryInfo(void) +{ + ReportGlobalMemoryStatus(); + + _HEAPINFO hinfo; + int heapstatus; + hinfo._pentry = NULL; + SLONG slTotalUsed = 0; + SLONG slTotalFree = 0; + INDEX ctUsed = 0; + INDEX ctFree = 0; + + CPrintF( "Walking heap...\n"); + while( ( heapstatus = _heapwalk( &hinfo ) ) == _HEAPOK ) + { + if (hinfo._useflag == _USEDENTRY ) { + slTotalUsed+=hinfo._size; + ctUsed++; + } else { + slTotalFree+=hinfo._size; + ctFree++; + } + } + switch( heapstatus ) { + case _HEAPEMPTY: CPrintF( "Heap empty?!?\n" ); break; + case _HEAPEND: CPrintF( "Heap ok.\n" ); break; + case _HEAPBADPTR: CPrintF( "ERROR - bad pointer to heap\n" ); break; + case _HEAPBADBEGIN: CPrintF( "ERROR - bad start of heap\n" ); break; + case _HEAPBADNODE: CPrintF( "ERROR - bad node in heap\n" ); break; + } + CPrintF( "Total used: %d bytes (%.2f MB) in %d blocks\n", slTotalUsed, slTotalUsed/1024.0f/1024.0f, ctUsed); + CPrintF( "Total free: %d bytes (%.2f MB) in %d blocks\n", slTotalFree, slTotalFree/1024.0f/1024.0f, ctFree); +} + +// get help for a shell symbol +extern CTString GetShellSymbolHelp_t(const CTString &strSymbol) +{ + CTString strPattern = strSymbol+"*"; + // open the symbol help file + CTFileStream strm; + strm.Open_t(CTString("Help\\ShellSymbols.txt")); + + // while not at the end of file + while (!strm.AtEOF()) { + // read the symbol name and its help + CTString strSymbolInFile; + strm.GetLine_t(strSymbolInFile, ':'); + strSymbolInFile.TrimSpacesLeft(); + strSymbolInFile.TrimSpacesRight(); + CTString strHelpInFile; + strm.GetLine_t(strHelpInFile, '$'); + strHelpInFile.TrimSpacesLeft(); + strHelpInFile.TrimSpacesRight(); + // if that is the one + if( strSymbolInFile.Matches(strPattern)) { + // print the help + return strHelpInFile; + } + } + return ""; +} + +// check if there is help for a shell symbol +extern BOOL CheckShellSymbolHelp(const CTString &strSymbol) +{ + try { + return GetShellSymbolHelp_t(strSymbol)!=""; + } catch(char *strError) { + (void)strError; + return FALSE; + } +} + +// print help for a shell symbol +extern void PrintShellSymbolHelp(const CTString &strSymbol) +{ + // try to + try { + CTString strHelp = GetShellSymbolHelp_t(strSymbol); + if (strHelp!="") { + CPrintF("%s\n", strHelp); + } else { + CPrintF( TRANS("No help found for '%s'.\n"), strSymbol); + } + // if failed + } catch(char *strError) { + // just print the error + CPrintF( TRANS("Cannot print help for '%s': %s\n"), strSymbol, strError); + } +} + +extern void ListSymbolsByPattern(CTString strPattern) +{ + // synchronize access to global shell + CTSingleLock slShell(&_pShell->sh_csShell, TRUE); + + // for each of symbols in the shell + FOREACHINDYNAMICARRAY(_pShell->sh_assSymbols, CShellSymbol, itss) { + CShellSymbol &ss = *itss; + + // if it is not visible to user, or not matching + if (!(ss.ss_ulFlags&SSF_USER) || !ss.ss_strName.Matches(strPattern)) { + // skip it + continue; + } + + // get its type + ShellType &st = _shell_ast[ss.ss_istType]; + + if (ss.ss_ulFlags & SSF_CONSTANT) { + CPrintF("const "); + } + if (ss.ss_ulFlags & SSF_PERSISTENT) { + CPrintF("persistent "); + } + + // print its declaration to the console + if (st.st_sttType == STT_FUNCTION) { + CPrintF("void %s(void)", ss.ss_strName); + + } else if (st.st_sttType == STT_STRING) { + CPrintF("CTString %s = \"%s\"", ss.ss_strName, *(CTString*)ss.ss_pvValue); + } else if (st.st_sttType == STT_FLOAT) { + CPrintF("FLOAT %s = %g", ss.ss_strName, *(FLOAT*)ss.ss_pvValue); + } else if (st.st_sttType == STT_INDEX) { + CPrintF("INDEX %s = %d (0x%08x)", ss.ss_strName, *(INDEX*)ss.ss_pvValue, *(INDEX*)ss.ss_pvValue); + } else if (st.st_sttType == STT_ARRAY) { + // get base type + ShellType &stBase = _shell_ast[st.st_istBaseType]; + if (stBase.st_sttType == STT_FLOAT) { + CPrintF("FLOAT %s[%d]", ss.ss_strName, st.st_ctArraySize); + } else if (stBase.st_sttType == STT_INDEX) { + CPrintF("INDEX %s[%d]", ss.ss_strName, st.st_ctArraySize); + } else if (stBase.st_sttType == STT_STRING) { + CPrintF("CTString %s[%d]", ss.ss_strName, st.st_ctArraySize); + } else { + ASSERT(FALSE); + } + } else { + ASSERT(FALSE); + } + + if (!CheckShellSymbolHelp(ss.ss_strName)) { + CPrintF( TRANS(" help N/A")); + } + CPrintF("\n"); + } +} + +// Print a list of all symbols in global shell to console. +static void ListSymbols(void) +{ + // print header + CPrintF( TRANS("Useful symbols:\n")); + + // list all symbols + ListSymbolsByPattern("*"); +} + + +// output any string to console +void Echo(void* pArgs) +{ + CTString str = *NEXTARGUMENT(CTString*); + CPrintF("%s", str); +} + + + +CTString UndecorateString(void* pArgs) +{ + CTString strString = *NEXTARGUMENT(CTString*); + return strString.Undecorated(); +} +BOOL MatchStrings(void* pArgs) +{ + CTString strString = *NEXTARGUMENT(CTString*); + CTString strPattern = *NEXTARGUMENT(CTString*); + return strString.Matches(strPattern); +} +CTString MyLoadString(void* pArgs) +{ + CTString strFileName = *NEXTARGUMENT(CTString*); + try { + CTString strString; + strString.Load_t(strFileName); + return strString; + } catch (char *strError) { + (void)strError; + return ""; + } +} +void MySaveString(void* pArgs) +{ + CTString strFileName = *NEXTARGUMENT(CTString*); + CTString strString = *NEXTARGUMENT(CTString*); + try { + strString.Save_t(strFileName); + } catch (char *strError) { + (void)strError; + } +} + +// load command batch files +void LoadCommands(void) +{ + // list all command files + CDynamicStackArray afnmCmds; + MakeDirList( afnmCmds, CTString("Scripts\\Commands\\"), "*.ini", DLI_RECURSIVE); + // for each file + for(INDEX i=0; iGetSymbol(strName, FALSE); + Declaration(SSF_EXTERNAL|SSF_USER, iType, ssNew, NULL, NULL); + ShellTypeDelete(iType); + + // get symbol type + ShellTypeType stt = _shell_ast[ssNew.ss_istType].st_sttType; + + // if the symbol is ok + if (stt == STT_STRING && !(ssNew.ss_ulFlags&SSF_CONSTANT)) { + // assign value + *(CTString*)ssNew.ss_pvValue = "!command "+strCmd; + } else { + _pShell->ErrorF("Symbol '%s' is not suitable to be a command", ssNew.ss_strName); + } + } +} + +CTString ToUpper(const CTString &strResult) +{ + char *pch = (char*)(const char *)strResult; + for(INDEX i=0; i", strDeclaration, TRUE); + yyparse(); +// ShellPopBuffer(); + + _bExecNextBlock = old_bExecNextBlock; + + _iParsing--; + if (_iParsing<=0) { + _shell_astrTempStrings.PopAll(); + } + + // don't use that value for parsing any more + _pvNextToDeclare = NULL; +}; + +// Execute command(s). +void CShell::Execute(const CTString &strCommands) +{ + // synchronize access to shell + CTSingleLock slShell(&sh_csShell, TRUE); + +// ASSERT(_iParsing==0); + _iParsing++; + + // parse the string + const BOOL old_bExecNextBlock = _bExecNextBlock; + _bExecNextBlock = 1; + + ShellPushBuffer("", strCommands, TRUE); + yyparse(); + //ShellPopBuffer(); + + _bExecNextBlock = old_bExecNextBlock; + + _iParsing--; + if (_iParsing<=0) { + _shell_astrTempStrings.PopAll(); + } +}; + +// Get a shell symbol by its name. +CShellSymbol *CShell::GetSymbol(const CTString &strName, BOOL bDeclaredOnly) +{ + // synchronize access to shell + CTSingleLock slShell(&sh_csShell, TRUE); + + // for each of symbols in the shell + FOREACHINDYNAMICARRAY(sh_assSymbols, CShellSymbol, itss) { + // if it is the right one + if (itss->ss_strName==strName) { + // return it + return itss; + } + } + // if none is found... + + // if only declared symbols are allowed + if (bDeclaredOnly) { + // return nothing + return NULL; + + // if undeclared symbols are allowed + } else { + // create a new one with that name and undefined type + CShellSymbol &ssNew = *sh_assSymbols.New(1); + ssNew.ss_strName = strName; + ssNew.ss_istType = _shell_istUndeclared; + ssNew.ss_pvValue = NULL; + ssNew.ss_ulFlags = 0; + ssNew.ss_pPreFunc = NULL; + ssNew.ss_pPostFunc = NULL; + return &ssNew; + } +}; + +FLOAT CShell::GetFLOAT(const CTString &strName) +{ + // get the symbol + CShellSymbol *pss = GetSymbol(strName, TRUE); + + // if it doesn't exist or is not of given type + if (pss==NULL || _shell_ast[pss->ss_istType].st_sttType!=STT_FLOAT) { + // error + ASSERT(FALSE); + return -666.0f; + } + // get it + return *(FLOAT*)pss->ss_pvValue; +} + +void CShell::SetFLOAT(const CTString &strName, FLOAT fValue) +{ + CShellSymbol *pss = GetSymbol(strName, TRUE); + + // if it doesn't exist or is not of given type + if (pss==NULL || _shell_ast[pss->ss_istType].st_sttType!=STT_FLOAT) { + // error + ASSERT(FALSE); + return; + } + // set it + *(FLOAT*)pss->ss_pvValue = fValue; +} + +INDEX CShell::GetINDEX(const CTString &strName) +{ + // get the symbol + CShellSymbol *pss = GetSymbol(strName, TRUE); + + // if it doesn't exist or is not of given type + if (pss==NULL || _shell_ast[pss->ss_istType].st_sttType!=STT_INDEX) { + // error + ASSERT(FALSE); + return -666; + } + // get it + return *(INDEX*)pss->ss_pvValue; +} + +void CShell::SetINDEX(const CTString &strName, INDEX iValue) +{ + CShellSymbol *pss = GetSymbol(strName, TRUE); + + // if it doesn't exist or is not of given type + if (pss==NULL || _shell_ast[pss->ss_istType].st_sttType!=STT_INDEX) { + // error + ASSERT(FALSE); + return; + } + // set it + *(INDEX*)pss->ss_pvValue = iValue; +} + +CTString CShell::GetString(const CTString &strName) +{ + // get the symbol + CShellSymbol *pss = GetSymbol(strName, TRUE); + + // if it doesn't exist or is not of given type + if (pss==NULL || _shell_ast[pss->ss_istType].st_sttType!=STT_STRING) { + // error + ASSERT(FALSE); + return ""; + } + // get it + return *(CTString*)pss->ss_pvValue; +} + +void CShell::SetString(const CTString &strName, const CTString &strValue) +{ + CShellSymbol *pss = GetSymbol(strName, TRUE); + + // if it doesn't exist or is not of given type + if (pss==NULL || _shell_ast[pss->ss_istType].st_sttType!=STT_STRING) { + // error + ASSERT(FALSE); + return; + } + // set it + *(CTString*)pss->ss_pvValue = strValue; +} + + +CTString CShell::GetValue(const CTString &strName) +{ + // get the symbol + CShellSymbol *pss = GetSymbol(strName, TRUE); + + // if it doesn't exist + if (pss==NULL) { + // error + ASSERT(FALSE); + return ""; + } + + // get it + ShellTypeType stt = _shell_ast[pss->ss_istType].st_sttType; + CTString strValue; + switch(stt) { + case STT_STRING: + strValue = *(CTString*)pss->ss_pvValue; + break; + case STT_INDEX: + strValue.PrintF("%d", *(INDEX*)pss->ss_pvValue); + break; + case STT_FLOAT: + strValue.PrintF("%g", *(FLOAT*)pss->ss_pvValue); + break; + default: + ASSERT(FALSE); + return ""; + } + + return strValue; +} + +void CShell::SetValue(const CTString &strName, const CTString &strValue) +{ + // get the symbol + CShellSymbol *pss = GetSymbol(strName, TRUE); + + // if it doesn't exist + if (pss==NULL) { + // error + ASSERT(FALSE); + return; + } + // get it + ShellTypeType stt = _shell_ast[pss->ss_istType].st_sttType; + switch(stt) { + case STT_STRING: + *(CTString*)pss->ss_pvValue = strValue; + break; + case STT_INDEX: + ((CTString&)strValue).ScanF("%d", (INDEX*)pss->ss_pvValue); + break; + case STT_FLOAT: + ((CTString&)strValue).ScanF("%g", (FLOAT*)pss->ss_pvValue); + break; + default: + ASSERT(FALSE); + } + + return; +} + +/* + * Report error in shell script processing. + */ +void CShell::ErrorF(const char *strFormat, ...) +{ + // synchronize access to shell + CTSingleLock slShell(&sh_csShell, TRUE); + + // print the error file and line + const char *strName = ShellGetBufferName(); + int iLine = ShellGetBufferLineNumber(); + if (strName[0] == '<') { + CPrintF("%s\n%s(%d): ", ShellGetBufferContents(), strName, iLine); + } else { + CPrintF("%s(%d): ", strName, iLine); + } + + // format the message in buffer + va_list arg; + va_start(arg, strFormat); + CTString strBuffer; + strBuffer.VPrintF(strFormat, arg); + + // print it to the main console + CPrintF(strBuffer); + // go to new line + CPrintF("\n"); +} + +// Save shell commands to restore persistent symbols to a script file +void CShell::StorePersistentSymbols(const CTFileName &fnScript) +{ + // synchronize access to global shell + CTSingleLock slShell(&sh_csShell, TRUE); + + try { + // open the file + CTFileStream fScript; + fScript.Create_t(fnScript); + + // print header + fScript.FPrintF_t("// automatically saved persistent symbols:\n"); + // for each of symbols in the shell + FOREACHINDYNAMICARRAY(sh_assSymbols, CShellSymbol, itss) { + CShellSymbol &ss = *itss; + + // if it is not persistent + if (! (ss.ss_ulFlags & SSF_PERSISTENT)) { + // skip it + continue; + } + + char *strUser = (ss.ss_ulFlags & SSF_USER)?"user ":""; + + // get its type + ShellType &st = _shell_ast[ss.ss_istType]; + // if array + if (st.st_sttType==STT_ARRAY) { + // get base type + ShellType &stBase = _shell_ast[st.st_istBaseType]; + CTString strType; + // if float + if (stBase.st_sttType==STT_FLOAT) { + // dump all members as floats + for(INDEX i=0; i + +#include +#include + +#define NEXTARGUMENT(type) ( *((type*&)pArgs)++ ) + +// Object that takes care of shell functions, variables, macros etc. +class ENGINE_API CShell { +public: +// implementation: + CTCriticalSection sh_csShell; // critical section for access to shell data + CDynamicArray sh_assSymbols; // all defined symbols + + // Get a shell symbol by its name. + CShellSymbol *GetSymbol(const CTString &strName, BOOL bDeclaredOnly); + // Report error in shell script processing. + void ErrorF(const char *strFormat, ...); + +// interface: + + // Constructor. + CShell(void); + ~CShell(void); + + // Initialize the shell. + void Initialize(void); + + // Declare a symbol in the shell. + void DeclareSymbol(const CTString &strDeclaration, void *pvValue); + // Execute command(s). + void Execute(const CTString &strCommands); + // Save shell commands to restore persistent symbols to a script file + void StorePersistentSymbols(const CTFileName &fnScript); + + // get/set symbols + FLOAT GetFLOAT(const CTString &strName); + void SetFLOAT(const CTString &strName, FLOAT fValue); + INDEX GetINDEX(const CTString &strName); + void SetINDEX(const CTString &strName, INDEX iValue); + CTString GetString(const CTString &strName); + void SetString(const CTString &strName, const CTString &strValue); + + CTString GetValue(const CTString &strName); + void SetValue(const CTString &strName, const CTString &strValue); +}; + +// pointer to global shell object +ENGINE_API extern CShell *_pShell; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/ShellTypes.cpp b/Sources/Engine/Base/ShellTypes.cpp new file mode 100644 index 0000000..03b1207 --- /dev/null +++ b/Sources/Engine/Base/ShellTypes.cpp @@ -0,0 +1,248 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include "ParsingSymbols.h" + +#include + +#include +#include +#include + +// all types are allocated here +CAllocationArray _shell_ast; + +// make a new type +INDEX ShellTypeNew(void) +{ + INDEX ist = _shell_ast.Allocate(); + ShellType &st = _shell_ast[ist]; + + st.st_sttType = STT_ILLEGAL; + st.st_ctArraySize = -1; + st.st_istBaseType = -1; + st.st_istFirstArgument = -1; + st.st_istLastArgument = -1; + st.st_istNextInArguments = -1; + st.st_istPrevInArguments = -1; + + return ist; +} + +// make a new type for a basic type +INDEX ShellTypeNewVoid(void) +{ + INDEX ist = ShellTypeNew(); + ShellType &st = _shell_ast[ist]; + st.st_sttType = STT_VOID; + return ist; +} + +INDEX ShellTypeNewIndex(void) +{ + INDEX ist = ShellTypeNew(); + ShellType &st = _shell_ast[ist]; + st.st_sttType = STT_INDEX; + return ist; +} + +INDEX ShellTypeNewFloat(void) +{ + INDEX ist = ShellTypeNew(); + ShellType &st = _shell_ast[ist]; + st.st_sttType = STT_FLOAT; + return ist; +} + +INDEX ShellTypeNewString(void) +{ + INDEX ist = ShellTypeNew(); + ShellType &st = _shell_ast[ist]; + st.st_sttType = STT_STRING; + return ist; +} +INDEX ShellTypeNewByType(enum ShellTypeType stt) +{ + switch(stt) { + default: ASSERT(FALSE); + case STT_VOID: return ShellTypeNewVoid(); + case STT_INDEX: return ShellTypeNewIndex(); + case STT_FLOAT: return ShellTypeNewFloat(); + case STT_STRING: return ShellTypeNewString(); + } +} + +// make a new pointer type +INDEX ShellTypeNewPointer(INDEX istBaseType) +{ + INDEX ist = ShellTypeNew(); + ShellType &st = _shell_ast[ist]; + st.st_sttType = STT_POINTER; + st.st_istBaseType = istBaseType; + return ist; +} + +// make a new array type +INDEX ShellTypeNewArray(INDEX istMemberType, int iArraySize) +{ + INDEX ist = ShellTypeNew(); + ShellType &st = _shell_ast[ist]; + st.st_sttType = STT_ARRAY; + st.st_ctArraySize = iArraySize; + st.st_istBaseType = istMemberType; + return ist; +} + +// make a new function type +INDEX ShellTypeNewFunction(INDEX istReturnType) +{ + INDEX ist = ShellTypeNew(); + ShellType &st = _shell_ast[ist]; + st.st_sttType = STT_FUNCTION; + st.st_istBaseType = istReturnType; + st.st_istFirstArgument = -1; + st.st_istLastArgument = -1; + return ist; +} + +// add an argument to a function from the left +void ShellTypeAddFunctionArgument(INDEX istFunction,INDEX istArgument) +{ + ShellType &stFunction = _shell_ast[istFunction]; + ShellType &stArgument = _shell_ast[istArgument]; + if (stFunction.st_istFirstArgument == -1) { + stFunction.st_istLastArgument = istArgument; + } else { + _shell_ast[stFunction.st_istFirstArgument].st_istPrevInArguments = istArgument; + } + stArgument.st_istNextInArguments = stFunction.st_istFirstArgument; + stArgument.st_istPrevInArguments = -1; + stFunction.st_istFirstArgument = istArgument; +} + +// This mess is neccessary to prevent code optimizer to create aliases +// to _shell_ast array across recursive function calls, since the array can be +// reallocated! +// The problem is in the evaluation order created by VisualC6 optimizer. +#pragma optimize("", off) +#pragma optimize("w", off) +static volatile INDEX iTmp; +#define stDuplicate _shell_ast[istDuplicate] +#define stOriginal _shell_ast[istOriginal] + +// make a copy of a type tree +INDEX ShellTypeMakeDuplicate(INDEX istOriginal) +{ + INDEX istDuplicate = ShellTypeNew(); + + // copy values of the original structure + stDuplicate.st_sttType = stOriginal.st_sttType; + + // check type + switch (stOriginal.st_sttType) { + // if pointer + case STT_POINTER: + // copy what it points to + iTmp = ShellTypeMakeDuplicate(stOriginal.st_istBaseType); + stDuplicate.st_istBaseType = iTmp; + break; + + // if an array + case STT_ARRAY: + // copy the member type + stDuplicate.st_ctArraySize = stOriginal.st_ctArraySize; + iTmp = ShellTypeMakeDuplicate(stOriginal.st_istBaseType); + stDuplicate.st_istBaseType = iTmp; + break; + + // if a function + case STT_FUNCTION: { + // copy return type + iTmp = ShellTypeMakeDuplicate(stOriginal.st_istBaseType); + stDuplicate.st_istBaseType = iTmp; + + // for each argument (backwards) + INDEX istArgOrg, istArgDup; + for (istArgOrg=stOriginal.st_istLastArgument; + istArgOrg!=-1; + istArgOrg = _shell_ast[istArgOrg].st_istPrevInArguments) { + // copy it + istArgDup = ShellTypeMakeDuplicate(istArgOrg); + // add it + ShellTypeAddFunctionArgument(istDuplicate, istArgDup); + } + } break; + } + + return istDuplicate; +} +#undef stDuplicate +#undef stOriginal +#pragma optimize("", on) + +BOOL ShellTypeIsSame(INDEX ist1, INDEX ist2) +{ + // if both are end of list + if (ist1==-1 && ist2==-1) { + // same + return TRUE; + } + // if only one is end of list + if (ist1==-1 || ist2==-1) { + // different + return FALSE; + } + + // get the types + ShellType &st1 = _shell_ast[ist1]; + ShellType &st2 = _shell_ast[ist2]; + + // if types or base types or sizes don't match + if (st1.st_sttType!=st2.st_sttType || + !ShellTypeIsSame(st1.st_istBaseType, st2.st_istBaseType) + ||st1.st_ctArraySize!=st2.st_ctArraySize) { + // different + return FALSE; + } + + // match arguments recursively + return + ShellTypeIsSame(st1.st_istFirstArgument, st2.st_istFirstArgument) && + ShellTypeIsSame(st1.st_istNextInArguments, st2.st_istNextInArguments); +} + +// delete an entire type tree +void ShellTypeDelete(INDEX istToDelete) +{ + ShellType &st = _shell_ast[istToDelete]; + + if (st.st_istBaseType>0) { + ShellTypeDelete(st.st_istBaseType); + } + if (st.st_istFirstArgument>0) { + ShellTypeDelete(st.st_istFirstArgument); + } + if (st.st_istNextInArguments>0) { + ShellTypeDelete(st.st_istNextInArguments); + } + + _shell_ast.Free(istToDelete); +} + +BOOL ShellTypeIsPointer(INDEX ist) +{ + return _shell_ast[ist].st_sttType == STT_POINTER; +} + +BOOL ShellTypeIsArray(INDEX ist) +{ + return _shell_ast[ist].st_sttType == STT_ARRAY; +} + +BOOL ShellTypeIsIntegral(INDEX ist) +{ + return _shell_ast[ist].st_sttType == STT_INDEX; +} diff --git a/Sources/Engine/Base/Shell_internal.h b/Sources/Engine/Base/Shell_internal.h new file mode 100644 index 0000000..7989de4 --- /dev/null +++ b/Sources/Engine/Base/Shell_internal.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SHELL_INTERNAL_H +#define SE_INCL_SHELL_INTERNAL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +// basic data type types +enum ShellTypeType { + STT_ILLEGAL , + STT_POINTER , + STT_FUNCTION , + STT_ARRAY , + STT_VOID , + STT_INDEX , + STT_FLOAT , + STT_STRING , +}; + + +// data type structure +struct ShellType { + enum ShellTypeType st_sttType; + + INDEX st_ctArraySize; // number of members if an array + + INDEX st_istBaseType; // type pointed to by a pointer, or member of array + // or result of a function + + INDEX st_istFirstArgument; // first argument in function + INDEX st_istLastArgument; // last argument in function + INDEX st_istNextInArguments; // next argument in function + INDEX st_istPrevInArguments; // previous argument in function +}; + +// symbol flags +#define SSF_CONSTANT (1L<<0) // the symbol cannot be changed +#define SSF_USER (1L<<1) // the symbol is visible to user (with ListSymbols() ) +#define SSF_PERSISTENT (1L<<2) // the symbol is saved when exiting +#define SSF_EXTERNAL (1L<<3) // the symbol was declared externally (in a script) + +// A symbol defined for using in shell. +class CShellSymbol { +public: +// implementation: + INDEX ss_istType; // type of the symbol + CTString ss_strName; // symbol name + void *ss_pvValue; // symbol value + BOOL (*ss_pPreFunc)(void *); + void (*ss_pPostFunc)(void *); + ULONG ss_ulFlags; // various flags + // Clear function. + void Clear(void); + // check if declared + BOOL IsDeclared(void); +// interface: + // get string for 'tab' completion in console + ENGINE_API CTString GetCompletionString(void) const; +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/StackDump.cpp b/Sources/Engine/Base/StackDump.cpp new file mode 100644 index 0000000..915fc92 --- /dev/null +++ b/Sources/Engine/Base/StackDump.cpp @@ -0,0 +1,372 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include + +extern ULONG _ulEngineBuildMajor; +extern ULONG _ulEngineBuildMinor; + +//========================================== +// Matt Pietrek +// Microsoft Systems Journal, May 1997 +// FILE: MSJEXHND.CPP + +class MSJExceptionHandler +{ + public: + + MSJExceptionHandler( ); + ~MSJExceptionHandler( ); + + void SetLogFileName(const char* pszLogFileName ); + + private: + + // entry point where control comes on an unhandled exception + static LONG WINAPI MSJUnhandledExceptionFilter( + PEXCEPTION_POINTERS pExceptionInfo ); + + // where report info is extracted and generated + static void GenerateExceptionReport( PEXCEPTION_POINTERS pExceptionInfo ); + + // Helper functions + static const char* GetExceptionString( DWORD dwCode ); + static BOOL GetLogicalAddress(PVOID addr, char* szModule, DWORD len, + DWORD& section, DWORD& offset ); + static void IntelStackWalk( PCONTEXT pContext ); + static int __cdecl _tprintf(const char * format, ...); + + // Variables used by the class + static char m_szLogFileName[MAX_PATH]; + static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter; + static HANDLE m_hReportFile; + +}; + +//extern MSJExceptionHandler g_MSJExceptionHandler; // global instance of class + +MSJExceptionHandler g_MSJExceptionHandler; // Declare global instance of class + +//============================== Global Variables ============================= + +// +// Declare the static variables of the MSJExceptionHandler class +// +char MSJExceptionHandler::m_szLogFileName[MAX_PATH]; +LPTOP_LEVEL_EXCEPTION_FILTER MSJExceptionHandler::m_previousFilter; +HANDLE MSJExceptionHandler::m_hReportFile; + +//============================== Class Methods ============================= + +//============= +// Constructor +//============= +MSJExceptionHandler::MSJExceptionHandler( ) +{ + // Install the unhandled exception filter function + m_previousFilter = SetUnhandledExceptionFilter(MSJUnhandledExceptionFilter); + + // Figure out what the report file will be named, and store it away + GetModuleFileNameA( 0, m_szLogFileName, MAX_PATH ); + + // Look for the '.' before the "EXE" extension. Replace the extension + // with "RPT" + char* pszDot = strrchr( m_szLogFileName, '.' ); + if ( pszDot ) + { + pszDot++; // Advance past the '.' + if ( strlen(pszDot) >= 3 ) + strcpy( pszDot, "RPT" ); // "RPT" -> "Report" + } +} + +//============ +// Destructor +//============ +MSJExceptionHandler::~MSJExceptionHandler( ) +{ + SetUnhandledExceptionFilter( m_previousFilter ); +} + +//============================================================== +// Lets user change the name of the report file to be generated +//============================================================== +void MSJExceptionHandler::SetLogFileName(const char* pszLogFileName ) +{ + strcpy( m_szLogFileName, pszLogFileName ); +} + +//=========================================================== +// Entry point where control comes on an unhandled exception +//=========================================================== +LONG WINAPI MSJExceptionHandler::MSJUnhandledExceptionFilter( + PEXCEPTION_POINTERS pExceptionInfo ) +{ + m_hReportFile = CreateFileA( m_szLogFileName, + GENERIC_WRITE, + 0, + 0, + OPEN_ALWAYS, + FILE_FLAG_WRITE_THROUGH, + 0 ); + + if ( m_hReportFile ) + { + SetFilePointer( m_hReportFile, 0, 0, FILE_END ); + + GenerateExceptionReport( pExceptionInfo ); + + CloseHandle( m_hReportFile ); + m_hReportFile = 0; + } + + // make sure the console log was written safely + if (_pConsole!=NULL) { + _pConsole->CloseLog(); + } + extern void EnableWindowsKeys(void); + EnableWindowsKeys(); + + if ( m_previousFilter ) + return m_previousFilter( pExceptionInfo ); + else + return EXCEPTION_CONTINUE_SEARCH; +} + +//=========================================================================== +// Open the report file, and write the desired information to it. Called by +// MSJUnhandledExceptionFilter +//=========================================================================== +void MSJExceptionHandler::GenerateExceptionReport( + PEXCEPTION_POINTERS pExceptionInfo ) +{ + // Start out with a banner + _tprintf( "//=====================================================\n" ); + char strTime[80]; + _strtime(strTime); + char strDate[80]; + _strdate(strDate); + _tprintf( "Crashed at: %s %s\n", strDate, strTime); + _tprintf( "Version: %d.%d%s%s\n", _ulEngineBuildMajor, _ulEngineBuildMinor, _SE_BUILD_EXTRA, _SE_DEMO?"-demo":""); + + PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord; + + // First print information about the type of fault + _tprintf( "Exception code: %08X %s\n", + pExceptionRecord->ExceptionCode, + GetExceptionString(pExceptionRecord->ExceptionCode) ); + + // Now print information about where the fault occured + char szFaultingModule[MAX_PATH]; + DWORD section, offset; + GetLogicalAddress( pExceptionRecord->ExceptionAddress, + szFaultingModule, + sizeof( szFaultingModule ), + section, offset ); + + _tprintf( "Fault address: %08X %02X:%08X %s\n", + pExceptionRecord->ExceptionAddress, + section, offset, szFaultingModule ); + + PCONTEXT pCtx = pExceptionInfo->ContextRecord; + + // Show the registers + #ifdef _M_IX86 // Intel Only! + _tprintf( "\nRegisters:\n" ); + + _tprintf("EAX:%08X\nEBX:%08X\nECX:%08X\nEDX:%08X\nESI:%08X\nEDI:%08X\n", + pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, pCtx->Esi, pCtx->Edi ); + + _tprintf( "CS:EIP:%04X:%08X\n", pCtx->SegCs, pCtx->Eip ); + _tprintf( "SS:ESP:%04X:%08X EBP:%08X\n", + pCtx->SegSs, pCtx->Esp, pCtx->Ebp ); + _tprintf( "DS:%04X ES:%04X FS:%04X GS:%04X\n", + pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs ); + _tprintf( "Flags:%08X\n", pCtx->EFlags ); + + #endif + + #ifdef _M_IX86 // Intel Only! + // Walk the stack using x86 specific code + IntelStackWalk( pCtx ); + #endif + + _tprintf( "\n" ); +} + +//====================================================================== +// Given an exception code, returns a pointer to a static string with a +// description of the exception +//====================================================================== +const char* MSJExceptionHandler::GetExceptionString( DWORD dwCode ) +{ + #define EXCEPTION( x ) case EXCEPTION_##x: return #x; + + switch ( dwCode ) + { + EXCEPTION( ACCESS_VIOLATION ) + EXCEPTION( DATATYPE_MISALIGNMENT ) + case EXCEPTION_BREAKPOINT: return "BREAKPOINT"; + //EXCEPTION( BREAKPOINT ) + EXCEPTION( SINGLE_STEP ) + EXCEPTION( ARRAY_BOUNDS_EXCEEDED ) + EXCEPTION( FLT_DENORMAL_OPERAND ) + EXCEPTION( FLT_DIVIDE_BY_ZERO ) + EXCEPTION( FLT_INEXACT_RESULT ) + EXCEPTION( FLT_INVALID_OPERATION ) + EXCEPTION( FLT_OVERFLOW ) + EXCEPTION( FLT_STACK_CHECK ) + EXCEPTION( FLT_UNDERFLOW ) + EXCEPTION( INT_DIVIDE_BY_ZERO ) + EXCEPTION( INT_OVERFLOW ) + EXCEPTION( PRIV_INSTRUCTION ) + EXCEPTION( IN_PAGE_ERROR ) + EXCEPTION( ILLEGAL_INSTRUCTION ) + EXCEPTION( NONCONTINUABLE_EXCEPTION ) + EXCEPTION( STACK_OVERFLOW ) + EXCEPTION( INVALID_DISPOSITION ) + EXCEPTION( GUARD_PAGE ) + EXCEPTION( INVALID_HANDLE ) + } + + // If not one of the "known" exceptions, try to get the string + // from NTDLL.DLL's message table. + + static char szBuffer[512] = { 0 }; + + FormatMessageA( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, + GetModuleHandleA( "NTDLL.DLL" ), + dwCode, 0, szBuffer, sizeof( szBuffer ), 0 ); + + return szBuffer; +} + +//============================================================================== +// Given a linear address, locates the module, section, and offset containing +// that address. +// +// Note: the szModule paramater buffer is an output buffer of length specified +// by the len parameter (in characters!) +//============================================================================== +BOOL MSJExceptionHandler::GetLogicalAddress( + PVOID addr, char* szModule, DWORD len, DWORD& section, DWORD& offset ) +{ + MEMORY_BASIC_INFORMATION mbi; + + if ( !VirtualQuery( addr, &mbi, sizeof(mbi) ) ) + return FALSE; + + DWORD hMod = (DWORD)mbi.AllocationBase; + + if ( !GetModuleFileNameA( (HMODULE)hMod, szModule, len ) ) + return FALSE; + + // Point to the DOS header in memory + PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod; + + // From the DOS header, find the NT (PE) header + PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + pDosHdr->e_lfanew); + + PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION( pNtHdr ); + + DWORD rva = (DWORD)addr - hMod; // RVA is offset from module load address + + // Iterate through the section table, looking for the one that encompasses + // the linear address. + for ( unsigned i = 0; + i < pNtHdr->FileHeader.NumberOfSections; + i++, pSection++ ) + { + DWORD sectionStart = pSection->VirtualAddress; + DWORD sectionEnd = sectionStart + + max(pSection->SizeOfRawData, pSection->Misc.VirtualSize); + + // Is the address in this section??? + if ( (rva >= sectionStart) && (rva <= sectionEnd) ) + { + // Yes, address is in the section. Calculate section and offset, + // and store in the "section" & "offset" params, which were + // passed by reference. + section = i+1; + offset = rva - sectionStart; + return TRUE; + } + } + + return FALSE; // Should never get here! +} + +//============================================================ +// Walks the stack, and writes the results to the report file +//============================================================ +void MSJExceptionHandler::IntelStackWalk( PCONTEXT pContext ) +{ + _tprintf( "\nmanual stack frame walk begin:\n" ); + + _tprintf( "Address Frame Logical addr Module\n" ); + + DWORD pc = pContext->Eip; + PDWORD pFrame, pPrevFrame; + + pFrame = (PDWORD)pContext->Ebp; + + + for(INDEX iDepth=0; iDepth<100; iDepth++) + { + char szModule[MAX_PATH] = ""; + DWORD section = 0, offset = 0; + + _tprintf( "%08X %08X ", pc, pFrame); + + DWORD symDisplacement = 0; // Displacement of the input address, + // relative to the start of the symbol + + GetLogicalAddress((PVOID)pc, szModule,sizeof(szModule),section,offset ); + + _tprintf( "$adr: %s %04X:%08X", szModule, section, offset); + + + _tprintf( "\n"); + + pc = pFrame[1]; + + pPrevFrame = pFrame; + + pFrame = (PDWORD)pFrame[0]; // proceed to next higher frame on stack + + if ( (DWORD)pFrame & 3 ) // Frame pointer must be aligned on a + break; // DWORD boundary. Bail if not so. + + if ( pFrame <= pPrevFrame ) + break; + + // Can two DWORDs be read from the supposed frame address? + if ( IsBadWritePtr(pFrame, sizeof(PVOID)*2) ) + break; + + }; + _tprintf( "\nmanual stack frame walk end:\n" ); +} + +//============================================================================ +// Helper function that writes to the report file, and allows the user to use +// printf style formating +//============================================================================ +int __cdecl MSJExceptionHandler::_tprintf(const char * format, ...) +{ + char szBuff[1024]; + int retValue; + DWORD cbWritten; + va_list argptr; + + va_start( argptr, format ); + retValue = wvsprintfA( szBuff, format, argptr ); + va_end( argptr ); + + WriteFile( m_hReportFile, szBuff, retValue * sizeof(char), &cbWritten, 0 ); + + return retValue; +} diff --git a/Sources/Engine/Base/Statistics.cpp b/Sources/Engine/Base/Statistics.cpp new file mode 100644 index 0000000..927897d --- /dev/null +++ b/Sources/Engine/Base/Statistics.cpp @@ -0,0 +1,184 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +#include +#include + +template CStaticArray; +template CStaticArray; +template CStaticArray; + +// one globaly used stats report +CStatForm _sfStats; + +CStatForm::CStatForm() +{ + sf_ascCounters.New(SCI_COUNT); + sf_astTimers.New(STI_COUNT); + sf_aslLabels.New(SLI_COUNT); + + InitCounter( SCI_SCENE_TRIANGLES, 101, "^c00DF00tris=%.0f", 1); + InitCounter( SCI_SCENE_TRIANGLEPASSES, 101, "\ntpas=%.0f", 1); + InitCounter( SCI_SECTORS, 101, "\nsecs=%.0f", 1); + InitCounter( SCI_POLYGONS, 101, "\nplys=%.0f+", 1); + InitCounter( SCI_DETAILPOLYGONS, 101, "%.0f", 1); + InitCounter( SCI_POLYGONEDGES, 101, "\npled=%.0f", 1); + InitCounter( SCI_EDGETRANSITIONS, 101, "\nedtr=%.0f", 1); + InitCounter( SCI_SOUNDSMIXING, 101, "^cDFDFAF\nsnds=%.0f", 1); + InitCounter( SCI_SOUNDSACTIVE, 101, "/%.0f", 1); + + InitCounter( SCI_CACHEDSHADOWS, 101, "^cDFDF00\n\ncsh=%3.0f+", 1); + InitCounter( SCI_FLATSHADOWS, 101, "%2.0f", 1); + InitCounter( SCI_CACHEDSHADOWBYTES, 101, "/%.0fK", 1/1024.0f); + InitCounter( SCI_DYNAMICSHADOWS, 101, "\ndyn=%3.0f", 1); + InitCounter( SCI_DYNAMICSHADOWBYTES, 101, "/%.0fK", 1/1024.0f); + + InitCounter( SCI_SHADOWBINDS, 101, "^cEFEF00\nshd=%3.0f", 1); + InitCounter( SCI_SHADOWBINDBYTES, 101, "/%.0fK", 1/1024.0f); + InitCounter( SCI_TEXTUREBINDS, 101, "\ntex=%3.0f", 1); + InitCounter( SCI_TEXTUREBINDBYTES, 101, "/%.0fK", 1/1024.0f); + InitCounter( SCI_TEXTUREUPLOADS, 101, "\nupl=%3.0f", 1); + InitCounter( SCI_TEXTUREUPLOADBYTES, 101, "/%.0fK", 1/1024.0f); + + InitCounter( SCI_PARTICLES, 101, "^c00EFEF\n\npart=%.0f", 1); + InitCounter( SCI_MODELS, 101, "^c00DFDF\nmdls=%.0f", 1); + InitCounter( SCI_MODELSHADOWS, 101, "\nshds=%.0f", 1); + InitCounter( SCI_TRIANGLES_USEDMIP, 101, "\ntris=%.0f", 1); + InitCounter( SCI_TRIANGLES_FIRSTMIP, 101, "/%.0f", 1); + InitCounter( SCI_SHADOWTRIANGLES_USEDMIP, 101, "\nstri=%.0f", 1); + InitCounter( SCI_SHADOWTRIANGLES_FIRSTMIP, 101, "/%.0f", 1); + + InitTimer( STI_WORLDTRANSFORM, 101, "^C\n\nwldtra=%2.0f ms", 1000.0f); + InitTimer( STI_WORLDVISIBILITY, 101, "\nwldvis=%2.0f ms", 1000.0f); + InitTimer( STI_WORLDRENDERING, 101, "\nwldren=%2.0f ms", 1000.0f); + InitTimer( STI_MODELSETUP, 101, "^c00FFFF\nmdlset=%2.0f ms", 1000.0f); + InitTimer( STI_MODELRENDERING, 101, "\nmdlren=%2.0f ms", 1000.0f); + InitTimer( STI_PARTICLERENDERING, 101, "\npartic=%2.0f ms", 1000.0f); + InitTimer( STI_FLARESRENDERING, 101, "\nflares=%2.0f ms", 1000.0f); + + InitTimer( STI_SOUNDUPDATE, 101, "^cFFFFCF\nsndupd=%2.0f ms", 1000.0f); + InitTimer( STI_SOUNDMIXING, 101, "\nsndmix=%2.0f ms", 1000.0f); + InitTimer( STI_TIMER, 101, "\ntimer =%2.0f ms", 1000.0f); + InitTimer( STI_MAINLOOP, 101, "\nmainlp=%2.0f ms", 1000.0f); + InitTimer( STI_RAYCAST, 101, "\nraycst=%2.0f ms", 1000.0f); + + InitTimer( STI_SHADOWUPDATE, 101, "^cFFFF00\nshdupd=%2.0f ms", 1000.0f); + InitTimer( STI_EFFECTRENDER, 101, "\nefftex=%2.0f ms", 1000.0f); + InitTimer( STI_BINDTEXTURE, 101, "\nbindtx=%2.0f ms", 1000.0f); + + InitTimer( STI_GFXAPI, 101, "^cFFFFFF\n\ngfxapi=%2.0f ms", 1000.0f); + InitTimer( STI_SWAPBUFFERS, 101, "\nswpbuf=%2.0f ms^C", 1000.0f); +} + + +void CStatForm::Clear(void) +{ + sf_ascCounters.Clear(); + sf_astTimers.Clear(); + sf_aslLabels.Clear(); +} + + +// make a new report +void CStatForm::Report(CTString &strReport) +{ + // clear the report initially + strReport = ""; + + // add all entries to print to a container + CDynamicContainer cse; + for (INDEX iCounter = 0; iCounterReport(); + }} +} + +// initialize component +void CStatForm::InitCounter(INDEX iCounter, INDEX iOrder, const char *strFormat, FLOAT fFactor) +{ + CStatCounter &sc = sf_ascCounters[iCounter]; + sc.se_iOrder = iOrder; + sc.sc_fCount = 0; + sc.sc_fFactor = fFactor; + sc.sc_strFormat = strFormat; +} + +void CStatForm::InitTimer(INDEX iTimer, INDEX iOrder, const char *strFormat, FLOAT fFactor) +{ + CStatTimer &st = sf_astTimers[iTimer]; + st.se_iOrder = iOrder; + st.st_tvElapsed.Clear(); + st.st_tvStarted.tv_llValue = -1; + st.st_fFactor = fFactor; + st.st_strFormat = strFormat; +} + +void CStatForm::InitLabel(INDEX iLabel, INDEX iOrder, const char *strFormat) +{ + CStatLabel &sl = sf_aslLabels[iLabel]; + sl.se_iOrder = iOrder; + sl.sl_strFormat = strFormat; +} + +// Reset all profiling values +void CStatForm::Reset(void) +{ + // for each counter + for (INDEX iCounter = 0; iCounter +#include +#include + +class CStatEntry { +public: + INDEX se_iOrder; // order in output + virtual CTString Report(void) = 0; +}; + +/* + * Statistics counter. + */ +class CStatCounter : public CStatEntry { +public: + CTString sc_strFormat; // printing format (must contain one %f or %g or %e) + FLOAT sc_fCount; // the counter itself + FLOAT sc_fFactor; // printout factor + inline void Clear(void) {}; + virtual CTString Report(void); +}; + +/* + * Statistics timer. + */ +class CStatTimer : public CStatEntry { +public: + CTString st_strFormat; // printing format (must contain one %f or %g or %e) + CTimerValue st_tvStarted; // time when the timer was started last time + CTimerValue st_tvElapsed; // total elapsed time of the timer + FLOAT st_fFactor; // printout factor + inline void Clear(void) {}; + virtual CTString Report(void); +}; + +/* + * Statistics label. + */ +class CStatLabel : public CStatEntry { +public: + CTString sl_strFormat; // printing format + inline void Clear(void) {}; + virtual CTString Report(void); +}; + +/* + * Class for gathering and reporting statistics information. + */ +class CStatForm { +public: +// implementation: + CStaticArray sf_ascCounters; // profiling counters + CStaticArray sf_astTimers; // profiling timers + CStaticArray sf_aslLabels; // profiling labels + +// interface: + enum StatLabelIndex + { + SLI_COUNT + }; + enum StatTimerIndex + { + STI_WORLDTRANSFORM, + STI_WORLDVISIBILITY, + STI_WORLDRENDERING, + STI_MODELSETUP, + STI_MODELRENDERING, + STI_PARTICLERENDERING, + STI_FLARESRENDERING, + + STI_SOUNDUPDATE, + STI_SOUNDMIXING, + STI_TIMER, + STI_MAINLOOP, + STI_RAYCAST, + + STI_SHADOWUPDATE, + STI_EFFECTRENDER, + STI_BINDTEXTURE, + + STI_GFXAPI, + STI_SWAPBUFFERS, + + STI_COUNT + }; + enum StatCounterIndex + { + SCI_SCENE_TRIANGLES, + SCI_SCENE_TRIANGLEPASSES, + SCI_SECTORS, + SCI_POLYGONS, + SCI_DETAILPOLYGONS, + SCI_POLYGONEDGES, + SCI_EDGETRANSITIONS, + + SCI_SOUNDSMIXING, + SCI_SOUNDSACTIVE, + + SCI_CACHEDSHADOWS, + SCI_FLATSHADOWS, + SCI_CACHEDSHADOWBYTES, + SCI_DYNAMICSHADOWS, + SCI_DYNAMICSHADOWBYTES, + SCI_SHADOWBINDS, + SCI_SHADOWBINDBYTES, + + SCI_TEXTUREBINDS, + SCI_TEXTUREBINDBYTES, + SCI_TEXTUREUPLOADS, + SCI_TEXTUREUPLOADBYTES, + + SCI_PARTICLES, + SCI_MODELS, + SCI_MODELSHADOWS, + SCI_TRIANGLES_USEDMIP, + SCI_TRIANGLES_FIRSTMIP, + SCI_SHADOWTRIANGLES_USEDMIP, + SCI_SHADOWTRIANGLES_FIRSTMIP, + + SCI_COUNT + }; + + CStatForm(void); + void Clear(void); + + /* Increment counter by given count. */ + inline void IncrementCounter(INDEX iCounter, FLOAT fAdd=1) { + sf_ascCounters[iCounter].sc_fCount += fAdd; + }; + + /* Start a timer. */ + inline void StartTimer(INDEX iTimer) { + CStatTimer &st = sf_astTimers[iTimer]; + ASSERT( sf_astTimers[iTimer].st_tvStarted.tv_llValue == -1); + st.st_tvStarted = _pTimer->GetHighPrecisionTimer(); + }; + /* Stop a timer. */ + inline void StopTimer(INDEX iTimer) { + CStatTimer &st = sf_astTimers[iTimer]; + ASSERT( sf_astTimers[iTimer].st_tvStarted.tv_llValue != -1); + st.st_tvElapsed += _pTimer->GetHighPrecisionTimer()-st.st_tvStarted; + st.st_tvStarted.tv_llValue = -1; + }; + + /* Check whether the timer is counting. */ + inline BOOL CheckTimer(INDEX iTimer) { + CStatTimer &st = sf_astTimers[iTimer]; + return (st.st_tvStarted.tv_llValue != -1); + }; + + // initialize component + void InitCounter(INDEX iCounter, INDEX iOrder, const char *strFormat, FLOAT fFactor); + void InitTimer(INDEX iTimer, INDEX iOrder, const char *strFormat, FLOAT fFactor); + void InitLabel(INDEX iLabel, INDEX iOrder, const char *strFormat); + + // reset all values + void Reset(void); + // make a new report + void Report(CTString &strReport); +}; + +// one globaly used stats report +ENGINE_API extern CStatForm _sfStats; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Stream.cpp b/Sources/Engine/Base/Stream.cpp new file mode 100644 index 0000000..dd68da9 --- /dev/null +++ b/Sources/Engine/Base/Stream.cpp @@ -0,0 +1,1598 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +// default size of page used for stream IO operations (4Kb) +ULONG _ulPageSize = 0; +// maximum lenght of file that can be saved (default: 128Mb) +ULONG _ulMaxLenghtOfSavingFile = (1UL<<20)*128; +extern INDEX fil_bPreferZips = FALSE; + +// set if current thread has currently enabled stream handling +static _declspec(thread) BOOL _bThreadCanHandleStreams = FALSE; +// list of currently opened streams +static _declspec(thread) CListHead *_plhOpenedStreams = NULL; + +ULONG _ulVirtuallyAllocatedSpace = 0; +ULONG _ulVirtuallyAllocatedSpaceTotal = 0; + +// global string with application path +CTFileName _fnmApplicationPath; +// global string with filename of the started application +CTFileName _fnmApplicationExe; +// global string with current MOD path +CTFileName _fnmMod; +// global string with current name (the parameter that is passed on cmdline) +CTString _strModName; +// global string with url to be shown to users that don't have the mod installed +// (should be set by game.dll) +CTString _strModURL; +// global string with current MOD extension (for adding to dlls) +CTString _strModExt; +// global string with CD path (for minimal installations) +CTFileName _fnmCDPath; + +// include/exclude lists for base dir writing/browsing +CDynamicStackArray _afnmBaseWriteInc; +CDynamicStackArray _afnmBaseWriteExc; +CDynamicStackArray _afnmBaseBrowseInc; +CDynamicStackArray _afnmBaseBrowseExc; +// list of paths or patterns that are not included when making CRCs for network connection +// this is used to enable connection between different localized versions +CDynamicStackArray _afnmNoCRC; + + +// load a filelist +static BOOL LoadFileList(CDynamicStackArray &afnm, const CTFileName &fnmList) +{ + afnm.PopAll(); + try { + CTFileStream strm; + strm.Open_t(fnmList); + while(!strm.AtEOF()) { + CTString strLine; + strm.GetLine_t(strLine); + strLine.TrimSpacesLeft(); + strLine.TrimSpacesRight(); + if (strLine!="") { + afnm.Push() = strLine; + } + } + return TRUE; + } catch(char *strError) { + CPrintF("%s\n", strError); + return FALSE; + } +} + +extern BOOL FileMatchesList(CDynamicStackArray &afnm, const CTFileName &fnm) +{ + for(INDEX i=0; i"):(CTString&)_fnmMod); + // if there is a mod active + if (_fnmMod!="") { + // load mod's include/exclude lists + CPrintF(TRANS("Loading mod include/exclude lists...\n")); + BOOL bOK = FALSE; + bOK |= LoadFileList(_afnmBaseWriteInc , CTString("BaseWriteInclude.lst")); + bOK |= LoadFileList(_afnmBaseWriteExc , CTString("BaseWriteExclude.lst")); + bOK |= LoadFileList(_afnmBaseBrowseInc, CTString("BaseBrowseInclude.lst")); + bOK |= LoadFileList(_afnmBaseBrowseExc, CTString("BaseBrowseExclude.lst")); + + // if none found + if (!bOK) { + // the mod is not valid + _fnmMod = CTString(""); + CPrintF(TRANS("Error: MOD not found!\n")); + // if mod is ok + } else { + // remember mod name (the parameter that is passed on cmdline) + _strModName = _fnmMod; + _strModName.DeleteChar(_strModName.Length()-1); + _strModName = CTFileName(_strModName).FileName(); + } + } + // find eventual extension for the mod's dlls + _strModExt = ""; + LoadStringVar(CTString("ModExt.txt"), _strModExt); + + + CPrintF(TRANS("Loading group files...\n")); + + // for each group file in base directory + struct _finddata_t c_file; + long hFile; + hFile = _findfirst(_fnmApplicationPath+"*.gro", &c_file); + BOOL bOK = (hFile!=-1); + while(bOK) { + if (CTString(c_file.name).Matches("*.gro")) { + // add it to active set + UNZIPAddArchive(_fnmApplicationPath+c_file.name); + } + bOK = _findnext(hFile, &c_file)==0; + } + _findclose( hFile ); + + // if there is a mod active + if (_fnmMod!="") { + // for each group file in mod directory + struct _finddata_t c_file; + long hFile; + hFile = _findfirst(_fnmApplicationPath+_fnmMod+"*.gro", &c_file); + BOOL bOK = (hFile!=-1); + while(bOK) { + if (CTString(c_file.name).Matches("*.gro")) { + // add it to active set + UNZIPAddArchive(_fnmApplicationPath+_fnmMod+c_file.name); + } + bOK = _findnext(hFile, &c_file)==0; + } + _findclose( hFile ); + } + + // if there is a CD path + if (_fnmCDPath!="") { + // for each group file on the CD + struct _finddata_t c_file; + long hFile; + hFile = _findfirst(_fnmCDPath+"*.gro", &c_file); + BOOL bOK = (hFile!=-1); + while(bOK) { + if (CTString(c_file.name).Matches("*.gro")) { + // add it to active set + UNZIPAddArchive(_fnmCDPath+c_file.name); + } + bOK = _findnext(hFile, &c_file)==0; + } + _findclose( hFile ); + + // if there is a mod active + if (_fnmMod!="") { + // for each group file in mod directory + struct _finddata_t c_file; + long hFile; + hFile = _findfirst(_fnmCDPath+_fnmMod+"*.gro", &c_file); + BOOL bOK = (hFile!=-1); + while(bOK) { + if (CTString(c_file.name).Matches("*.gro")) { + // add it to active set + UNZIPAddArchive(_fnmCDPath+_fnmMod+c_file.name); + } + bOK = _findnext(hFile, &c_file)==0; + } + _findclose( hFile ); + } + } + + // try to + try { + // read the zip directories + UNZIPReadDirectoriesReverse_t(); + // if failed + } catch( char *strError) { + // report warning + CPrintF( TRANS("There were group file errors:\n%s"), strError); + } + CPrintF("\n"); + + LoadFileList(_afnmNoCRC, CTFILENAME("Data\\NoCRC.lst")); + + _pShell->SetINDEX(CTString("sys")+"_iCPU"+"Misc", 1); +} + +void EndStreams(void) +{ +} + + +void UseApplicationPath(void) +{ + _fnmApplicationPath = _fnmApp; +} + +void IgnoreApplicationPath(void) +{ + _fnmApplicationPath = CTString(""); +} + + +///////////////////////////////////////////////////////////////////////////// +// Helper functions + +/* Static function enable stream handling. */ +void CTStream::EnableStreamHandling(void) +{ + ASSERT(!_bThreadCanHandleStreams && _plhOpenedStreams == NULL); + + _bThreadCanHandleStreams = TRUE; + _plhOpenedStreams = new CListHead; +} + +/* Static function disable stream handling. */ +void CTStream::DisableStreamHandling(void) +{ + ASSERT(_bThreadCanHandleStreams && _plhOpenedStreams != NULL); + + _bThreadCanHandleStreams = FALSE; + delete _plhOpenedStreams; + _plhOpenedStreams = NULL; +} + +int CTStream::ExceptionFilter(DWORD dwCode, _EXCEPTION_POINTERS *pExceptionInfoPtrs) +{ + // If the exception is not a page fault, exit. + if( dwCode != EXCEPTION_ACCESS_VIOLATION) + { + return EXCEPTION_CONTINUE_SEARCH; + } + + // obtain access violation virtual address + UBYTE *pIllegalAdress = (UBYTE *)pExceptionInfoPtrs->ExceptionRecord->ExceptionInformation[1]; + + CTStream *pstrmAccessed = NULL; + + // search for stream that was accessed + FOREACHINLIST( CTStream, strm_lnListNode, (*_plhOpenedStreams), itStream) + { + // if access violation happened inside curently testing stream + if(itStream.Current().PointerInStream(pIllegalAdress)) + { + // remember accesed stream ptr + pstrmAccessed = &itStream.Current(); + // stream found, stop searching + break; + } + } + + // if none of our streams was accessed, real access violation occured + if( pstrmAccessed == NULL) + { + // so continue default exception handling + return EXCEPTION_CONTINUE_SEARCH; + } + + // Continue execution where the page fault occurred + return EXCEPTION_CONTINUE_EXECUTION; +} + +/* + * Static function to report fatal exception error. + */ +void CTStream::ExceptionFatalError(void) +{ + FatalError( GetWindowsError( GetLastError()) ); +} + +/* + * Throw an exception of formatted string. + */ +void CTStream::Throw_t(char *strFormat, ...) // throws char * +{ + const SLONG slBufferSize = 256; + char strFormatBuffer[slBufferSize]; + char strBuffer[slBufferSize]; + // add the stream description to the format string + _snprintf(strFormatBuffer, slBufferSize, "%s (%s)", strFormat, strm_strStreamDescription); + // format the message in buffer + va_list arg; + va_start(arg, strFormat); // variable arguments start after this argument + _vsnprintf(strBuffer, slBufferSize, strFormatBuffer, arg); + throw strBuffer; +} + +///////////////////////////////////////////////////////////////////////////// +// Binary access methods + +/* Get CRC32 of stream */ +ULONG CTStream::GetStreamCRC32_t(void) +{ + // remember where stream is now + SLONG slOldPos = GetPos_t(); + // go to start of file + SetPos_t(0); + // get size of file + SLONG slFileSize = GetStreamSize(); + + ULONG ulCRC; + CRC_Start(ulCRC); + + // for each block in file + const SLONG slBlockSize = 4096; + for(SLONG slPos=0; slPos0); + // check that the stream can be read + ASSERT(IsReadable()); + // letters slider + INDEX iLetters = 0; + // test if EOF reached + if(AtEOF()) { + ThrowF_t(TRANS("EOF reached, file %s"), strm_strStreamDescription); + } + // get line from istream + FOREVER + { + char c; + Read_t(&c, 1); + + if(AtEOF()) { + // cut off + strBuffer[ iLetters] = 0; + break; + } + + // don't read "\r" characters but rather act like they don't exist + if( c != '\r') { + strBuffer[ iLetters] = c; + // stop reading when delimiter loaded + if( strBuffer[ iLetters] == cDelimiter) { + // convert delimiter to zero + strBuffer[ iLetters] = 0; + // jump over delimiter + //Seek_t(1, SD_CUR); + break; + } + // jump to next destination letter + iLetters++; + } + // test if maximum buffer lenght reached + if( iLetters==slBufferSize) { + return; + } + } +} + +void CTStream::GetLine_t(CTString &strLine, char cDelimiter/*='\n'*/) // throw char * +{ + char strBuffer[1024]; + GetLine_t(strBuffer, sizeof(strBuffer)-1, cDelimiter); + strLine = strBuffer; +} + + +/* Put a line of text into file. */ +void CTStream::PutLine_t(const char *strBuffer) // throws char * +{ + // check parameters + ASSERT(strBuffer!=NULL); + // check that the stream is writteable + ASSERT(IsWriteable()); + // get string length + INDEX iStringLength = strlen(strBuffer); + // put line into stream + Write_t(strBuffer, iStringLength); + // write "\r\n" into stream + Write_t("\r\n", 2); +} + +void CTStream::PutString_t(const char *strString) // throw char * +{ + // check parameters + ASSERT(strString!=NULL); + // check that the stream is writteable + ASSERT(IsWriteable()); + // get string length + INDEX iStringLength = strlen(strString); + // put line into stream + for( INDEX iLetter=0; iLetter>chKeywordChar; + if (chKeywordChar!=strKeyword[iKeywordChar]) { + ThrowF_t(TRANS("Expected keyword %s not found"), strKeyword); + } + } +} + + +SLONG CTStream::GetSize_t(void) // throws char * +{ + SLONG chunkSize; + + Read_t( (char *) &chunkSize, sizeof( SLONG)); + return( chunkSize); +} + +void CTStream::ReadRawChunk_t(void *pvBuffer, SLONG slSize) // throws char * +{ + Read_t((char *)pvBuffer, slSize); +} + +void CTStream::ReadChunk_t(void *pvBuffer, SLONG slExpectedSize) // throws char * +{ + if( slExpectedSize != GetSize_t()) + throw TRANS("Chunk size not equal as expected size"); + Read_t((char *)pvBuffer, slExpectedSize); +} + +void CTStream::ReadFullChunk_t(const CChunkID &cidExpected, void *pvBuffer, + SLONG slExpectedSize) // throws char * +{ + ExpectID_t( cidExpected); + ReadChunk_t( pvBuffer, slExpectedSize); +}; + +void* CTStream::ReadChunkAlloc_t(SLONG slSize) // throws char * +{ + UBYTE *buffer; + SLONG chunkSize; + + if( slSize != 0) + chunkSize = slSize; + else + chunkSize = GetSize_t(); // throws char * + buffer = (UBYTE *) AllocMemory( chunkSize); + if( buffer == NULL) + throw TRANS("ReadChunkAlloc: Unable to allocate needed amount of memory."); + Read_t((char *)buffer, chunkSize); // throws char * + return buffer; +} +void CTStream::ReadStream_t(CTStream &strmOther) // throw char * +{ + // implement this !!!! @@@@ +} + +void CTStream::WriteID_t(const CChunkID &cidSave) // throws char * +{ + Write_t( &cidSave.cid_ID[0], CID_LENGTH); +} + +void CTStream::WriteSize_t(SLONG slSize) // throws char * +{ + Write_t( (char *)&slSize, sizeof( SLONG)); +} + +void CTStream::WriteRawChunk_t(void *pvBuffer, SLONG slSize) // throws char * +{ + Write_t( (char *)pvBuffer, slSize); +} + +void CTStream::WriteChunk_t(void *pvBuffer, SLONG slSize) // throws char * +{ + WriteSize_t( slSize); + WriteRawChunk_t( pvBuffer, slSize); +} + +void CTStream::WriteFullChunk_t(const CChunkID &cidSave, void *pvBuffer, + SLONG slSize) // throws char * +{ + WriteID_t( cidSave); // throws char * + WriteChunk_t( pvBuffer, slSize); // throws char * +} +void CTStream::WriteStream_t(CTStream &strmOther) // throw char * +{ + // implement this !!!! @@@@ +} + +// whether or not the given pointer is coming from this stream (mainly used for exception handling) +BOOL CTStream::PointerInStream(void* pPointer) +{ + // safe to return FALSE, we're using virtual functions anyway + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// filename dictionary operations + +// enable dictionary in writable file from this point +void CTStream::DictionaryWriteBegin_t(const CTFileName &fnmImportFrom, SLONG slImportOffset) +{ + ASSERT(strm_slDictionaryPos==0); + ASSERT(strm_dmDictionaryMode == DM_NONE); + strm_ntDictionary.SetAllocationParameters(100, 5, 5); + strm_ctDictionaryImported = 0; + + // if importing an existing dictionary to start with + if (fnmImportFrom!="") { + // open that file + CTFileStream strmOther; + strmOther.Open_t(fnmImportFrom); + // read the dictionary in that stream + strmOther.ReadDictionary_intenal_t(slImportOffset); + // copy the dictionary here + CopyDictionary(strmOther); + // write dictionary importing data + WriteID_t("DIMP"); // dictionary import + *this<0); + // remember the dictionary position chunk position + SLONG slDictPos = strm_slDictionaryPos; + // mark that now saving dictionary + strm_slDictionaryPos = -1; + // remember where dictionary begins + SLONG slDictBegin = GetPos_t(); + // start dictionary processing + strm_dmDictionaryMode = DM_PROCESSING; + + WriteID_t("DICT"); // dictionary + // write number of used filenames + INDEX ctFileNames = strm_afnmDictionary.Count(); + INDEX ctFileNamesNew = ctFileNames-strm_ctDictionaryImported; + *this<>ctFileNamesNew; + // if there are any new filenames + if (ctFileNamesNew>0) { + // create that much space + strm_afnmDictionary.Push(ctFileNamesNew); + // for each filename + for(INDEX iFileName=ctFileNamesOld; iFileName>strm_afnmDictionary[iFileName]; + } + } + ExpectID_t("DEND"); // dictionary end + + // remember where end of dictionary is + strm_slDictionaryPos = GetPos_t(); + + // return to continuing position + SetPos_t(slContinue); +} + +// copy filename dictionary from another stream +void CTStream::CopyDictionary(CTStream &strmOther) +{ + strm_afnmDictionary = strmOther.strm_afnmDictionary; + for (INDEX i=0; i>fnmImportFrom>>slImportOffset; + + // open that file + CTFileStream strmOther; + strmOther.Open_t(fnmImportFrom); + // read the dictionary in that stream + strmOther.ReadDictionary_intenal_t(slImportOffset); + // copy the dictionary here + CopyDictionary(strmOther); + } + + // if the dictionary is not here + if (PeekID_t()!=CChunkID("DPOS")) { // dictionary position + // do nothing + return 0; + } + + // read dictionary position + ExpectID_t("DPOS"); // dictionary position + SLONG slDictBeg; + *this>>slDictBeg; + + // read the dictionary from that offset in file + ReadDictionary_intenal_t(slDictBeg); + + // stop dictionary processing - go to dictionary using + strm_dmDictionaryMode = DM_ENABLED; + + // return offset of dictionary for later cross-file importing + if (slImportOffset!=0) { + return slImportOffset; + } else { + return slDictBeg; + } +} + +void CTStream::DictionaryReadEnd_t(void) +{ + if (strm_dmDictionaryMode == DM_ENABLED) { + ASSERT(strm_slDictionaryPos>0); + // just skip the dictionary (it was already read) + SetPos_t(strm_slDictionaryPos); + strm_slDictionaryPos=0; + strm_dmDictionaryMode = DM_NONE; + strm_ntDictionary.Clear(); + + // for each filename + INDEX ctFileNames = strm_afnmDictionary.Count(); + for(INDEX iFileName=0; iFileNameRelease((CTextureData*)fnm.fnm_pserPreloaded); + } else if (strExt==".mdl") { + _pModelStock->Release((CModelData*)fnm.fnm_pserPreloaded); + } + } + + strm_afnmDictionary.Clear(); + } +} +void CTStream::DictionaryPreload_t(void) +{ + INDEX ctFileNames = strm_afnmDictionary.Count(); + // for each filename + for(INDEX iFileName=0; iFileNameObtain_t(fnm); + } else if (strExt==".mdl") { + fnm.fnm_pserPreloaded = _pModelStock->Obtain_t(fnm); + } + } catch (char *strError) { + CPrintF( TRANS("Cannot preload %s: %s\n"), (CTString&)fnm, strError); + } + } +} + +///////////////////////////////////////////////////////////////////////////// +// General construction/destruction + +/* Default constructor. */ +CTStream::CTStream(void) : strm_ntDictionary(*new CNameTable_CTFileName) +{ + strm_strStreamDescription = ""; + strm_slDictionaryPos = 0; + strm_dmDictionaryMode = DM_NONE; +} + +/* Destructor. */ +CTStream::~CTStream(void) +{ + strm_ntDictionary.Clear(); + strm_afnmDictionary.Clear(); + + delete &strm_ntDictionary; +} + +///////////////////////////////////////////////////////////////////////////// +// File stream opening/closing methods + +/* + * Default constructor. + */ +CTFileStream::CTFileStream(void) +{ + fstrm_pFile = NULL; + // mark that file is created for writing + fstrm_bReadOnly = TRUE; + fstrm_iZipHandle = -1; + fstrm_iZipLocation = 0; + fstrm_pubZipBuffer = NULL; +} + +/* + * Destructor. + */ +CTFileStream::~CTFileStream(void) +{ + // close stream + if (fstrm_pFile != NULL || fstrm_iZipHandle!=-1) { + Close(); + } +} + +/* + * Open an existing file. + */ +// throws char * +void CTFileStream::Open_t(const CTFileName &fnFileName, CTStream::OpenMode om/*=OM_READ*/) +{ + // if current thread has not enabled stream handling + if (!_bThreadCanHandleStreams) { + // error + ::ThrowF_t(TRANS("Cannot open file `%s', stream handling is not enabled for this thread"), + (CTString&)fnFileName); + } + + // check parameters + ASSERT(strlen(fnFileName)>0); + // check that the file is not open + ASSERT(fstrm_pFile==NULL && fstrm_iZipHandle==-1); + + // expand the filename to full path + CTFileName fnmFullFileName; + INDEX iFile = ExpandFilePath((om == OM_READ)?EFP_READ:EFP_WRITE, fnFileName, fnmFullFileName); + + // if read only mode requested + if( om == OM_READ) { + // initially, no physical file + fstrm_pFile = NULL; + // if zip file + if( iFile==EFP_MODZIP || iFile==EFP_BASEZIP) { + // open from zip + fstrm_iZipHandle = UNZIPOpen_t(fnmFullFileName); + fstrm_slZipSize = UNZIPGetSize(fstrm_iZipHandle); + // load the file from the zip in the buffer + fstrm_pubZipBuffer = (UBYTE*)VirtualAlloc(NULL, fstrm_slZipSize, MEM_COMMIT, PAGE_READWRITE); + UNZIPReadBlock_t(fstrm_iZipHandle, (UBYTE*)fstrm_pubZipBuffer, 0, fstrm_slZipSize); + // if it is a physical file + } else if (iFile==EFP_FILE) { + // open file in read only mode + fstrm_pFile = fopen(fnmFullFileName, "rb"); + } + fstrm_bReadOnly = TRUE; + + // if write mode requested + } else if( om == OM_WRITE) { + // open file for reading and writing + fstrm_pFile = fopen(fnmFullFileName, "rb+"); + fstrm_bReadOnly = FALSE; + // if unknown mode + } else { + FatalError(TRANS("File stream opening requested with unknown open mode: %d\n"), om); + } + + // if openning operation was not successfull + if(fstrm_pFile == NULL && fstrm_iZipHandle==-1) { + // throw exception + Throw_t(TRANS("Cannot open file `%s' (%s)"), (CTString&)fnmFullFileName, + strerror(errno)); + } + + // if file opening was successfull, set stream description to file name + strm_strStreamDescription = fnmFullFileName; + // add this newly opened file into opened stream list + _plhOpenedStreams->AddTail( strm_lnListNode); +} + +/* + * Create a new file or overwrite existing. + */ +void CTFileStream::Create_t(const CTFileName &fnFileName, + enum CTStream::CreateMode cm) // throws char * +{ + (void)cm; // OBSOLETE! + + CTFileName fnFileNameAbsolute = fnFileName; + fnFileNameAbsolute.SetAbsolutePath(); + + // if current thread has not enabled stream handling + if (!_bThreadCanHandleStreams) { + // error + ::ThrowF_t(TRANS("Cannot create file `%s', stream handling is not enabled for this thread"), + (CTString&)fnFileNameAbsolute); + } + + CTFileName fnmFullFileName; + INDEX iFile = ExpandFilePath(EFP_WRITE, fnFileNameAbsolute, fnmFullFileName); + + // check parameters + ASSERT(strlen(fnFileNameAbsolute)>0); + // check that the file is not open + ASSERT(fstrm_pFile == NULL); + + // create the directory for the new file if it doesn't exist yet + MakeSureDirectoryPathExists(fnmFullFileName); + + // open file stream for writing (destroy file context if file existed before) + fstrm_pFile = fopen(fnmFullFileName, "wb+"); + // if not successfull + if(fstrm_pFile == NULL) + { + // throw exception + Throw_t(TRANS("Cannot create file `%s' (%s)"), (CTString&)fnmFullFileName, + strerror(errno)); + } + // if file creation was successfull, set stream description to file name + strm_strStreamDescription = fnFileNameAbsolute; + // mark that file is created for writing + fstrm_bReadOnly = FALSE; + // add this newly created file into opened stream list + _plhOpenedStreams->AddTail( strm_lnListNode); +} + +/* + * Close an open file. + */ +void CTFileStream::Close(void) +{ + // if file is not open + if (fstrm_pFile==NULL && fstrm_iZipHandle==-1) { + ASSERT(FALSE); + return; + } + + // clear stream description + strm_strStreamDescription = ""; + // remove file from list of curently opened streams + strm_lnListNode.Remove(); + + // if file on disk + if (fstrm_pFile != NULL) { + // close file + fclose( fstrm_pFile); + fstrm_pFile = NULL; + // if file in zip + } else if (fstrm_iZipHandle>=0) { + // close zip entry + UNZIPClose(fstrm_iZipHandle); + fstrm_iZipHandle = -1; + + VirtualFree(fstrm_pubZipBuffer, 0, MEM_RELEASE); + + _ulVirtuallyAllocatedSpace -= fstrm_slZipSize; + //CPrintF("Freed virtual memory with size ^c00ff00%d KB^C (now %d KB)\n", (fstrm_slZipSize / 1000), (_ulVirtuallyAllocatedSpace / 1000)); + } + + // clear dictionary vars + strm_dmDictionaryMode = DM_NONE; + strm_ntDictionary.Clear(); + strm_afnmDictionary.Clear(); + strm_slDictionaryPos=0; +} + +/* Get CRC32 of stream */ +ULONG CTFileStream::GetStreamCRC32_t(void) +{ + // if file on disk + if (fstrm_pFile != NULL) { + // use base class implementation (really calculates the CRC) + return CTStream::GetStreamCRC32_t(); + // if file in zip + } else if (fstrm_iZipHandle >=0) { + return UNZIPGetCRC(fstrm_iZipHandle); + } else { + ASSERT(FALSE); + return 0; + } +} + +/* Read a block of data from stream. */ +void CTFileStream::Read_t(void *pvBuffer, SLONG slSize) +{ + if(fstrm_iZipHandle != -1) { + memcpy(pvBuffer, fstrm_pubZipBuffer + fstrm_iZipLocation, slSize); + fstrm_iZipLocation += slSize; + return; + } + + fread(pvBuffer, slSize, 1, fstrm_pFile); +} + +/* Write a block of data to stream. */ +void CTFileStream::Write_t(const void *pvBuffer, SLONG slSize) +{ + if(fstrm_bReadOnly || fstrm_iZipHandle != -1) { + throw "Stream is read-only!"; + } + + fwrite(pvBuffer, slSize, 1, fstrm_pFile); +} + +/* Seek in stream. */ +void CTFileStream::Seek_t(SLONG slOffset, enum SeekDir sd) +{ + if(fstrm_iZipHandle != -1) { + switch(sd) { + case SD_BEG: fstrm_iZipLocation = slOffset; break; + case SD_CUR: fstrm_iZipLocation += slOffset; break; + case SD_END: fstrm_iZipLocation = GetSize_t() + slOffset; break; + } + } else { + fseek(fstrm_pFile, slOffset, sd); + } +} + +/* Set absolute position in stream. */ +void CTFileStream::SetPos_t(SLONG slPosition) +{ + Seek_t(slPosition, SD_BEG); +} + +/* Get absolute position in stream. */ +SLONG CTFileStream::GetPos_t(void) +{ + if(fstrm_iZipHandle != -1) { + return fstrm_iZipLocation; + } else { + return ftell(fstrm_pFile); + } +} + +/* Get size of stream */ +SLONG CTFileStream::GetStreamSize(void) +{ + if(fstrm_iZipHandle != -1) { + return UNZIPGetSize(fstrm_iZipHandle); + } else { + long lCurrentPos = ftell(fstrm_pFile); + fseek(fstrm_pFile, 0, SD_END); + long lRet = ftell(fstrm_pFile); + fseek(fstrm_pFile, lCurrentPos, SD_BEG); + return lRet; + } +} + +/* Check if file position points to the EOF */ +BOOL CTFileStream::AtEOF(void) +{ + if(fstrm_iZipHandle != -1) { + return fstrm_iZipLocation >= fstrm_slZipSize; + } else { + int eof = feof(fstrm_pFile); + return eof != 0; + } +} + +// whether or not the given pointer is coming from this stream (mainly used for exception handling) +BOOL CTFileStream::PointerInStream(void* pPointer) +{ + // we're not using virtual allocation buffers so it's fine to return FALSE here. + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// Memory stream construction/destruction + +/* + * Create dynamically resizing stream for reading/writing. + */ +CTMemoryStream::CTMemoryStream(void) +{ + // if current thread has not enabled stream handling + if (!_bThreadCanHandleStreams) { + // error + ::FatalError(TRANS("Can create memory stream, stream handling is not enabled for this thread")); + } + + mstrm_ctLocked = 0; + mstrm_bReadable = TRUE; + mstrm_bWriteable = TRUE; + mstrm_slLocation = 0; + // set stream description + strm_strStreamDescription = "dynamic memory stream"; + // add this newly created memory stream into opened stream list + _plhOpenedStreams->AddTail( strm_lnListNode); + // allocate amount of memory needed to hold maximum allowed file length (when saving) + mstrm_pubBuffer = (UBYTE*)VirtualAlloc(NULL, _ulMaxLenghtOfSavingFile, MEM_COMMIT, PAGE_READWRITE); + mstrm_pubBufferEnd = mstrm_pubBuffer + _ulMaxLenghtOfSavingFile; + mstrm_pubBufferMax = mstrm_pubBuffer; +} + +/* + * Create static stream from given buffer. + */ +CTMemoryStream::CTMemoryStream(void *pvBuffer, SLONG slSize, + CTStream::OpenMode om /*= CTStream::OM_READ*/) +{ + // if current thread has not enabled stream handling + if (!_bThreadCanHandleStreams) { + // error + ::FatalError(TRANS("Can create memory stream, stream handling is not enabled for this thread")); + } + + // allocate amount of memory needed to hold maximum allowed file length (when saving) + mstrm_pubBuffer = (UBYTE*)VirtualAlloc(NULL, _ulMaxLenghtOfSavingFile, MEM_COMMIT, PAGE_READWRITE); + mstrm_pubBufferEnd = mstrm_pubBuffer + _ulMaxLenghtOfSavingFile; + mstrm_pubBufferMax = mstrm_pubBuffer + slSize; + // copy given block of memory into memory file + memcpy( mstrm_pubBuffer, pvBuffer, slSize); + + mstrm_ctLocked = 0; + mstrm_bReadable = TRUE; + mstrm_slLocation = 0; + // if stram is opened in read only mode + if( om == OM_READ) + { + mstrm_bWriteable = FALSE; + } + // otherwise, write is enabled + else + { + mstrm_bWriteable = TRUE; + } + // set stream description + strm_strStreamDescription = "dynamic memory stream"; + // add this newly created memory stream into opened stream list + _plhOpenedStreams->AddTail( strm_lnListNode); +} + +/* Destructor. */ +CTMemoryStream::~CTMemoryStream(void) +{ + ASSERT(mstrm_ctLocked==0); + VirtualFree(mstrm_pubBuffer, 0, MEM_RELEASE); + // remove memory stream from list of curently opened streams + strm_lnListNode.Remove(); +} + +///////////////////////////////////////////////////////////////////////////// +// Memory stream buffer operations + +/* + * Lock the buffer contents and it's size. + */ +void CTMemoryStream::LockBuffer(void **ppvBuffer, SLONG *pslSize) +{ + mstrm_ctLocked++; + ASSERT(mstrm_ctLocked>0); + + *ppvBuffer = mstrm_pubBuffer; + *pslSize = GetSize_t(); +} + +/* + * Unlock buffer. + */ +void CTMemoryStream::UnlockBuffer() +{ + mstrm_ctLocked--; + ASSERT(mstrm_ctLocked>=0); +} + +///////////////////////////////////////////////////////////////////////////// +// Memory stream overrides from CTStream + +BOOL CTMemoryStream::IsReadable(void) +{ + return mstrm_bReadable && (mstrm_ctLocked==0); +} +BOOL CTMemoryStream::IsWriteable(void) +{ + return mstrm_bWriteable && (mstrm_ctLocked==0); +} +BOOL CTMemoryStream::IsSeekable(void) +{ + return TRUE; +} + +/* Read a block of data from stream. */ +void CTMemoryStream::Read_t(void *pvBuffer, SLONG slSize) +{ + memcpy(pvBuffer, mstrm_pubBuffer + mstrm_slLocation, slSize); + mstrm_slLocation += slSize; +} + +/* Write a block of data to stream. */ +void CTMemoryStream::Write_t(const void *pvBuffer, SLONG slSize) +{ + memcpy(mstrm_pubBuffer + mstrm_slLocation, pvBuffer, slSize); + mstrm_slLocation += slSize; + + if(mstrm_pubBuffer + mstrm_slLocation > mstrm_pubBufferMax) { + mstrm_pubBufferMax = mstrm_pubBuffer + mstrm_slLocation; + } +} + +/* Seek in stream. */ +void CTMemoryStream::Seek_t(SLONG slOffset, enum SeekDir sd) +{ + switch(sd) { + case SD_BEG: mstrm_slLocation = slOffset; break; + case SD_CUR: mstrm_slLocation += slOffset; break; + case SD_END: mstrm_slLocation = GetStreamSize() + slOffset; break; + } +} + +/* Set absolute position in stream. */ +void CTMemoryStream::SetPos_t(SLONG slPosition) +{ + mstrm_slLocation = slPosition; +} + +/* Get absolute position in stream. */ +SLONG CTMemoryStream::GetPos_t(void) +{ + return mstrm_slLocation; +} + +/* Get size of stream. */ +SLONG CTMemoryStream::GetSize_t(void) +{ + return GetStreamSize(); +} + +/* Get size of stream */ +SLONG CTMemoryStream::GetStreamSize(void) +{ + return mstrm_pubBufferMax - mstrm_pubBuffer; +} + +/* Get CRC32 of stream */ +ULONG CTMemoryStream::GetStreamCRC32_t(void) +{ + return CTStream::GetStreamCRC32_t(); +} + +/* Check if file position points to the EOF */ +BOOL CTMemoryStream::AtEOF(void) +{ + return mstrm_slLocation >= GetStreamSize(); +} + +// whether or not the given pointer is coming from this stream (mainly used for exception handling) +BOOL CTMemoryStream::PointerInStream(void* pPointer) +{ + return pPointer >= mstrm_pubBuffer && pPointer < mstrm_pubBufferEnd; +} + +// Test if a file exists. +BOOL FileExists(const CTFileName &fnmFile) +{ + // if no file + if (fnmFile=="") { + // it doesn't exist + return FALSE; + } + // try to + try { + // open the file for reading + CTFileStream strmFile; + strmFile.Open_t(fnmFile); + // if successful, it means that it exists, + return TRUE; + // if failed, it means that it doesn't exist + } catch (char *strError) { + (void) strError; + return FALSE; + } +} + +// Test if a file exists for writing. +// (this is can be diferent than normal FileExists() if a mod uses basewriteexclude.lst +BOOL FileExistsForWriting(const CTFileName &fnmFile) +{ + // if no file + if (fnmFile=="") { + // it doesn't exist + return FALSE; + } + // expand the filename to full path for writing + CTFileName fnmFullFileName; + INDEX iFile = ExpandFilePath(EFP_WRITE, fnmFile, fnmFullFileName); + + // check if it exists + FILE *f = fopen(fnmFullFileName, "rb"); + if (f!=NULL) { + fclose(f); + return TRUE; + } else { + return FALSE; + } +} + +// Get file timestamp +SLONG GetFileTimeStamp_t(const CTFileName &fnm) +{ + // expand the filename to full path + CTFileName fnmExpanded; + INDEX iFile = ExpandFilePath(EFP_READ, fnm, fnmExpanded); + if (iFile!=EFP_FILE) { + return FALSE; + } + + int file_handle; + // try to open file for reading + file_handle = _open( fnmExpanded, _O_RDONLY | _O_BINARY); + if(file_handle==-1) { + ThrowF_t(TRANS("Cannot open file '%s' for reading"), CTString(fnm)); + return -1; + } + struct stat statFileStatus; + // get file status + fstat( file_handle, &statFileStatus); + _close( file_handle); + ASSERT(statFileStatus.st_mtime<=time(NULL)); + return statFileStatus.st_mtime; +} + +// Get CRC32 of a file +ULONG GetFileCRC32_t(const CTFileName &fnmFile) // throw char * +{ + // open the file + CTFileStream fstrm; + fstrm.Open_t(fnmFile); + // return the checksum + return fstrm.GetStreamCRC32_t(); +} + +// Test if a file is read only (also returns FALSE if file does not exist) +BOOL IsFileReadOnly(const CTFileName &fnm) +{ + // expand the filename to full path + CTFileName fnmExpanded; + INDEX iFile = ExpandFilePath(EFP_READ, fnm, fnmExpanded); + if (iFile!=EFP_FILE) { + return FALSE; + } + + int file_handle; + // try to open file for reading + file_handle = _open( fnmExpanded, _O_RDONLY | _O_BINARY); + if(file_handle==-1) { + return FALSE; + } + struct stat statFileStatus; + // get file status + fstat( file_handle, &statFileStatus); + _close( file_handle); + ASSERT(statFileStatus.st_mtime<=time(NULL)); + return !(statFileStatus.st_mode&_S_IWRITE); +} + +// Delete a file +BOOL RemoveFile(const CTFileName &fnmFile) +{ + // expand the filename to full path + CTFileName fnmExpanded; + INDEX iFile = ExpandFilePath(EFP_WRITE, fnmFile, fnmExpanded); + if (iFile==EFP_FILE) { + int ires = remove(fnmExpanded); + return ires==0; + } else { + return FALSE; + } +} + + +static BOOL IsFileReadable_internal(CTFileName &fnmFullFileName) +{ + FILE *pFile = fopen(fnmFullFileName, "rb"); + if (pFile!=NULL) { + fclose(pFile); + return TRUE; + } else { + return FALSE; + } +} + +// check for some file extensions that can be substituted +static BOOL SubstExt_internal(CTFileName &fnmFullFileName) +{ + if (fnmFullFileName.FileExt()==".mp3") { + fnmFullFileName = fnmFullFileName.NoExt()+".ogg"; + return TRUE; + } else if (fnmFullFileName.FileExt()==".ogg") { + fnmFullFileName = fnmFullFileName.NoExt()+".mp3"; + return TRUE; + } else { + return TRUE; + } +} + + +static INDEX ExpandFilePath_read(ULONG ulType, const CTFileName &fnmFile, CTFileName &fnmExpanded) +{ + // search for the file in zips + INDEX iFileInZip = UNZIPGetFileIndex(fnmFile); + + // if a mod is active + if (_fnmMod!="") { + + // first try in the mod's dir + if (!fil_bPreferZips) { + fnmExpanded = _fnmApplicationPath+_fnmMod+fnmFile; + if (IsFileReadable_internal(fnmExpanded)) { + return EFP_FILE; + } + } + + // if not disallowing zips + if (!(ulType&EFP_NOZIPS)) { + // if exists in mod's zip + if (iFileInZip>=0 && UNZIPIsFileAtIndexMod(iFileInZip)) { + // use that one + fnmExpanded = fnmFile; + return EFP_MODZIP; + } + } + + // try in the mod's dir after + if (fil_bPreferZips) { + fnmExpanded = _fnmApplicationPath+_fnmMod+fnmFile; + if (IsFileReadable_internal(fnmExpanded)) { + return EFP_FILE; + } + } + } + + // try in the app's base dir + if (!fil_bPreferZips) { + CTFileName fnmAppPath = _fnmApplicationPath; + fnmAppPath.SetAbsolutePath(); + + if(fnmFile.HasPrefix(fnmAppPath)) { + fnmExpanded = fnmFile; + } else { + fnmExpanded = _fnmApplicationPath+fnmFile; + } + + if (IsFileReadable_internal(fnmExpanded)) { + return EFP_FILE; + } + } + + // if not disallowing zips + if (!(ulType&EFP_NOZIPS)) { + // if exists in any zip + if (iFileInZip>=0) { + // use that one + fnmExpanded = fnmFile; + return EFP_BASEZIP; + } + } + + // try in the app's base dir + if (fil_bPreferZips) { + fnmExpanded = _fnmApplicationPath+fnmFile; + if (IsFileReadable_internal(fnmExpanded)) { + return EFP_FILE; + } + } + + // finally, try in the CD path + if (_fnmCDPath!="") { + + // if a mod is active + if (_fnmMod!="") { + // first try in the mod's dir + fnmExpanded = _fnmCDPath+_fnmMod+fnmFile; + if (IsFileReadable_internal(fnmExpanded)) { + return EFP_FILE; + } + } + + fnmExpanded = _fnmCDPath+fnmFile; + if (IsFileReadable_internal(fnmExpanded)) { + return EFP_FILE; + } + } + return EFP_NONE; +} + +// Expand a file's filename to full path +INDEX ExpandFilePath(ULONG ulType, const CTFileName &fnmFile, CTFileName &fnmExpanded) +{ + CTFileName fnmFileAbsolute = fnmFile; + fnmFileAbsolute.SetAbsolutePath(); + + // if writing + if (ulType&EFP_WRITE) { + // if should write to mod dir + if (_fnmMod!="" && (!FileMatchesList(_afnmBaseWriteInc, fnmFileAbsolute) || FileMatchesList(_afnmBaseWriteExc, fnmFileAbsolute))) { + // do that + fnmExpanded = _fnmApplicationPath+_fnmMod+fnmFileAbsolute; + fnmExpanded.SetAbsolutePath(); + return EFP_FILE; + // if should not write to mod dir + } else { + // write to base dir + fnmExpanded = _fnmApplicationPath+fnmFileAbsolute; + fnmExpanded.SetAbsolutePath(); + return EFP_FILE; + } + + // if reading + } else if (ulType&EFP_READ) { + + // check for expansions for reading + INDEX iRes = ExpandFilePath_read(ulType, fnmFileAbsolute, fnmExpanded); + // if not found + if (iRes==EFP_NONE) { + //check for some file extensions that can be substituted + CTFileName fnmSubst = fnmFileAbsolute; + if (SubstExt_internal(fnmSubst)) { + iRes = ExpandFilePath_read(ulType, fnmSubst, fnmExpanded); + } + } + + fnmExpanded.SetAbsolutePath(); + + if (iRes!=EFP_NONE) { + return iRes; + } + + // in other cases + } else { + ASSERT(FALSE); + fnmExpanded = _fnmApplicationPath+fnmFileAbsolute; + fnmExpanded.SetAbsolutePath(); + return EFP_FILE; + } + + fnmExpanded = _fnmApplicationPath+fnmFileAbsolute; + fnmExpanded.SetAbsolutePath(); + return EFP_NONE; +} diff --git a/Sources/Engine/Base/Stream.h b/Sources/Engine/Base/Stream.h new file mode 100644 index 0000000..1f0a584 --- /dev/null +++ b/Sources/Engine/Base/Stream.h @@ -0,0 +1,386 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +#ifndef SE_INCL_STREAM_H +#define SE_INCL_STREAM_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include + +// maximum length of file that can be saved (default: 8Mb) +ENGINE_API extern ULONG _ulMaxLengthOfSavingFile; + +#define CTSTREAM_BEGIN CTStream::EnableStreamHandling(); __try +#define CTSTREAM_END __except( CTStream::ExceptionFilter( GetExceptionCode(),\ + GetExceptionInformation()) )\ + {\ + CTStream::ExceptionFatalError();\ + }; CTStream::DisableStreamHandling(); + +/* + * Chunk ID class + */ +#define CID_LENGTH 4 +class ENGINE_API CChunkID { +public: + char cid_ID[CID_LENGTH+1]; +public: + /* Default constructor and string constructor. */ + inline CChunkID(const char *strString = " "); + /* Comparison operator. */ + inline int operator==(const CChunkID &cidOther) const; + inline int operator!=(const CChunkID &cidOther) const; + inline operator const char *(void) const { return cid_ID; } + inline operator char *(void) { return cid_ID; } +}; + +// inline implementations +/* Default constructor and string constructor. */ +inline CChunkID::CChunkID(const char *strString /*= " "*/) { + ASSERT(strlen(strString)==CID_LENGTH); + memcpy(cid_ID, strString, CID_LENGTH+1); +}; +/* Comparison operator. */ +inline int CChunkID::operator==(const CChunkID &cidOther) const { + return (*((ULONG *)&cid_ID[0]) == *((ULONG *)&cidOther.cid_ID[0])); +}; +inline int CChunkID::operator!=(const CChunkID &cidOther) const { + return (*((ULONG *)&cid_ID[0]) != *((ULONG *)&cidOther.cid_ID[0])); +}; + +/* + * CroTeam stream class -- abstract base class + */ +class ENGINE_API CTStream { +public: + CListNode strm_lnListNode; // for linking into main library's list of opened streams +public: + CTString strm_strStreamDescription; // descriptive string + + enum DictionaryMode { + DM_NONE, // no dictionary on this file (yet) + DM_ENABLED, // dictionary is enabled, reading/writing rest of file + DM_PROCESSING, // reading/writing the dictionary itself + } strm_dmDictionaryMode; // dictionary mode of operation on this file + SLONG strm_slDictionaryPos; // dictionary position in file (0 for no dictionary) + INDEX strm_ctDictionaryImported; // how many filenames were imported + class CNameTable_CTFileName &strm_ntDictionary; // name table for the dictionary + CDynamicStackArray strm_afnmDictionary; // dictionary is stored here + + /* Throw an exception of formatted string. */ + void Throw_t(char *strFormat, ...); // throw char * + // read the dictionary from given offset in file (internal function) + void ReadDictionary_intenal_t(SLONG slOffset); + // copy filename dictionary from another stream + void CopyDictionary(CTStream &strmOther); +public: + // modes for opening streams + enum OpenMode { + OM_READ = 1, + OM_WRITE = 2, + OM_READTEXT = OM_READ , + OM_WRITETEXT = OM_WRITE, + OM_READBINARY = OM_READ , + OM_WRITEBINARY = OM_WRITE, + }; + enum CreateMode { // OBSOLETE! + CM_TEXT = 1, + CM_BINARY = 2, + }; + // direction for seeking + enum SeekDir { + SD_BEG = SEEK_SET, + SD_END = SEEK_END, + SD_CUR = SEEK_CUR, + }; + + /* Static function enable stream handling. */ + static void EnableStreamHandling(void); + /* Static function disable stream handling. */ + static void DisableStreamHandling(void); + +#ifdef PLATFORM_WIN32 /* rcg10042001 !!! FIXME */ + /* Static function to filter exceptions and intercept access violation */ + static int ExceptionFilter(DWORD dwCode, _EXCEPTION_POINTERS *pExceptionInfoPtrs); +#endif + + /* Static function to report fatal exception error. */ + static void ExceptionFatalError(void); + + /* Default constructor. */ + CTStream(void); + /* Destruction. */ + virtual ~CTStream(void); + + /* Check if the stream can be read. -- used mainly for assertions */ + virtual BOOL IsReadable(void) = 0; + /* Check if the stream can be written. -- used mainly for assertions */ + virtual BOOL IsWriteable(void) = 0; + /* Check if the stream can be seeked. -- used mainly for assertions */ + virtual BOOL IsSeekable(void) = 0; + + /* Read a block of data from stream. */ + virtual void Read_t(void *pvBuffer, SLONG slSize) = 0; // throw char * + /* Write a block of data to stream. */ + virtual void Write_t(const void *pvBuffer, SLONG slSize) = 0; // throw char * + + /* Seek in stream. */ + virtual void Seek_t(SLONG slOffset, enum SeekDir sd) = 0; // throw char * + /* Set absolute position in stream. */ + virtual void SetPos_t(SLONG slPosition) = 0; // throw char * + /* Get absolute position in stream. */ + virtual SLONG GetPos_t(void) = 0; // throw char * + /* Get size of stream */ + virtual SLONG GetStreamSize(void) = 0; + /* Get CRC32 of stream */ + virtual ULONG GetStreamCRC32_t(void) = 0; + /* Check if file position points to the EOF */ + virtual BOOL AtEOF(void) = 0; + + /* Get description of this stream (e.g. filename for a CFileStream). */ + inline CTString &GetDescription(void) { return strm_strStreamDescription; }; + + /* Read an object from stream. */ + inline CTStream &operator>>(float &f) { Read_t( &f, sizeof( f)); return *this; } // throw char * + inline CTStream &operator>>(double &d) { Read_t( &d, sizeof( d)); return *this; } // throw char * + inline CTStream &operator>>(ULONG &ul) { Read_t(&ul, sizeof(ul)); return *this; } // throw char * + inline CTStream &operator>>(UWORD &uw) { Read_t(&uw, sizeof(uw)); return *this; } // throw char * + inline CTStream &operator>>(UBYTE &ub) { Read_t(&ub, sizeof(ub)); return *this; } // throw char * + inline CTStream &operator>>(SLONG &sl) { Read_t(&sl, sizeof(sl)); return *this; } // throw char * + inline CTStream &operator>>(SWORD &sw) { Read_t(&sw, sizeof(sw)); return *this; } // throw char * + inline CTStream &operator>>(SBYTE &sb) { Read_t(&sb, sizeof(sb)); return *this; } // throw char * + inline CTStream &operator>>(BOOL &b) { Read_t( &b, sizeof( b)); return *this; } // throw char * + /* Write an object into stream. */ + inline CTStream &operator<<(const float &f) { Write_t( &f, sizeof( f)); return *this; } // throw char * + inline CTStream &operator<<(const double &d) { Write_t( &d, sizeof( d)); return *this; } // throw char * + inline CTStream &operator<<(const ULONG &ul) { Write_t(&ul, sizeof(ul)); return *this; } // throw char * + inline CTStream &operator<<(const UWORD &uw) { Write_t(&uw, sizeof(uw)); return *this; } // throw char * + inline CTStream &operator<<(const UBYTE &ub) { Write_t(&ub, sizeof(ub)); return *this; } // throw char * + inline CTStream &operator<<(const SLONG &sl) { Write_t(&sl, sizeof(sl)); return *this; } // throw char * + inline CTStream &operator<<(const SWORD &sw) { Write_t(&sw, sizeof(sw)); return *this; } // throw char * + inline CTStream &operator<<(const SBYTE &sb) { Write_t(&sb, sizeof(sb)); return *this; } // throw char * + inline CTStream &operator<<(const BOOL &b) { Write_t( &b, sizeof( b)); return *this; } // throw char * + + // CTFileName reading/writing + ENGINE_API friend CTStream &operator>>(CTStream &strmStream, CTFileName &fnmFileName); + ENGINE_API friend CTStream &operator<<(CTStream &strmStream, const CTFileName &fnmFileName); + + /* Put a line of text into stream. */ + virtual void PutLine_t(const char *strBuffer); // throw char * + virtual void PutString_t(const char *strString); // throw char * + virtual void FPrintF_t(const char *strFormat, ...); // throw char * + /* Get a line of text from stream. */ + virtual void GetLine_t(char *strBuffer, SLONG slBufferSize, char cDelimiter='\n'); // throw char * + virtual void GetLine_t(CTString &strLine, char cDelimiter='\n'); // throw char * + + virtual CChunkID GetID_t(void); // throw char * + virtual CChunkID PeekID_t(void); // throw char * + virtual void ExpectID_t(const CChunkID &cidExpected); // throw char * + virtual void ExpectKeyword_t(const CTString &strKeyword); // throw char * + virtual SLONG GetSize_t(void); // throw char * + virtual void ReadRawChunk_t(void *pvBuffer, SLONG slSize); // throw char * + virtual void ReadChunk_t(void *pvBuffer, SLONG slExpectedSize); // throw char * + virtual void ReadFullChunk_t(const CChunkID &cidExpected, void *pvBuffer, SLONG slExpectedSize); // throw char * + virtual void *ReadChunkAlloc_t(SLONG slSize=0); // throw char * + virtual void ReadStream_t(CTStream &strmOther); // throw char * + + virtual void WriteID_t(const CChunkID &cidSave); // throw char * + virtual void WriteSize_t(SLONG slSize); // throw char * + virtual void WriteRawChunk_t(void *pvBuffer, SLONG slSize); // throw char * // doesn't write length + virtual void WriteChunk_t(void *pvBuffer, SLONG slSize); // throw char * + virtual void WriteFullChunk_t(const CChunkID &cidSave, void *pvBuffer, SLONG slSize); // throw char * + virtual void WriteStream_t(CTStream &strmOther); // throw char * + + // whether or not the given pointer is coming from this stream (mainly used for exception handling) + virtual BOOL PointerInStream(void* pPointer); + + // filename dictionary operations + + // start writing a with a dictionary + void DictionaryWriteBegin_t(const CTFileName &fnmImportFrom, SLONG slImportOffset); + // stop writing a with a dictionary + void DictionaryWriteEnd_t(void); + // start reading a with a dictionary + SLONG DictionaryReadBegin_t(void); // returns offset of dictionary for cross-file importing + // stop reading a with a dictionary + void DictionaryReadEnd_t(void); + // preload all files mentioned in the dictionary + void DictionaryPreload_t(void); +}; + +/* + * CroTeam file stream class + */ +class ENGINE_API CTFileStream : public CTStream { +private: + FILE *fstrm_pFile; // ptr to opened file + + INDEX fstrm_iZipHandle; // handle of zip-file entry + INDEX fstrm_iZipLocation; // location in zip-file entry + UBYTE* fstrm_pubZipBuffer; // buffer for zip-file entry + SLONG fstrm_slZipSize; // size of the zip-file entry + + BOOL fstrm_bReadOnly; // set if file is opened in read-only mode +public: + /* Default constructor. */ + CTFileStream(void); + /* Destructor. */ + virtual ~CTFileStream(void); + + /* Open an existing file. */ + void Open_t(const CTFileName &fnFileName, enum CTStream::OpenMode om=CTStream::OM_READ); // throw char * + /* Create a new file or overwrite existing. */ + void Create_t(const CTFileName &fnFileName, enum CTStream::CreateMode cm=CTStream::CM_BINARY); // throw char * + /* Close an open file. */ + void Close(void); + /* Get CRC32 of stream */ + ULONG GetStreamCRC32_t(void); + + /* Read a block of data from stream. */ + void Read_t(void *pvBuffer, SLONG slSize); // throw char * + /* Write a block of data to stream. */ + void Write_t(const void *pvBuffer, SLONG slSize); // throw char * + + /* Seek in stream. */ + void Seek_t(SLONG slOffset, enum SeekDir sd); // throw char * + /* Set absolute position in stream. */ + void SetPos_t(SLONG slPosition); // throw char * + /* Get absolute position in stream. */ + SLONG GetPos_t(void); // throw char * + /* Get size of stream */ + SLONG GetStreamSize(void); + /* Check if file position points to the EOF */ + BOOL AtEOF(void); + + // whether or not the given pointer is coming from this stream (mainly used for exception handling) + virtual BOOL PointerInStream(void* pPointer); + + // from CTStream + inline virtual BOOL IsWriteable(void){ return !fstrm_bReadOnly;}; + inline virtual BOOL IsReadable(void){ return TRUE;}; + inline virtual BOOL IsSeekable(void){ return TRUE;}; +}; + +/* + * CroTeam memory stream class + */ +class ENGINE_API CTMemoryStream : public CTStream { +public: + BOOL mstrm_bReadable; // set if stream is readable + BOOL mstrm_bWriteable; // set if stream is writeable + INDEX mstrm_ctLocked; // counter for buffer locking + + UBYTE* mstrm_pubBuffer; // buffer of the stream + UBYTE* mstrm_pubBufferEnd; // pointer to the end of the stream buffer + SLONG mstrm_slLocation; // location in the stream + UBYTE* mstrm_pubBufferMax; // furthest that the stream location has ever gotten +public: + /* Create dynamically resizing stream for reading/writing. */ + CTMemoryStream(void); + /* Create static stream from given buffer. */ + CTMemoryStream(void *pvBuffer, SLONG slSize, CTStream::OpenMode om = CTStream::OM_READ); + /* Destructor. */ + virtual ~CTMemoryStream(void); + + /* Lock the buffer contents and it's size. */ + void LockBuffer(void **ppvBuffer, SLONG *pslSize); + /* Unlock buffer. */ + void UnlockBuffer(void); + + /* Read a block of data from stream. */ + void Read_t(void *pvBuffer, SLONG slSize); // throw char * + /* Write a block of data to stream. */ + void Write_t(const void *pvBuffer, SLONG slSize); // throw char * + + /* Seek in stream. */ + void Seek_t(SLONG slOffset, enum SeekDir sd); // throw char * + /* Set absolute position in stream. */ + void SetPos_t(SLONG slPosition); // throw char * + /* Get absolute position in stream. */ + SLONG GetPos_t(void); // throw char * + /* Get size of stream. */ + SLONG GetSize_t(void); // throw char * + /* Get size of stream */ + SLONG GetStreamSize(void); + /* Get CRC32 of stream */ + ULONG GetStreamCRC32_t(void); + /* Check if file position points to the EOF */ + BOOL AtEOF(void); + + // whether or not the given pointer is coming from this stream (mainly used for exception handling) + virtual BOOL PointerInStream(void* pPointer); + + // memory stream can be opened only for reading and writing + virtual BOOL IsWriteable(void); + virtual BOOL IsReadable(void); + virtual BOOL IsSeekable(void); +}; + +// Test if a file exists. +ENGINE_API BOOL FileExists(const CTFileName &fnmFile); +// Test if a file exists for writing. +// (this is can be diferent than normal FileExists() if a mod uses basewriteexclude.lst +ENGINE_API BOOL FileExistsForWriting(const CTFileName &fnmFile); +// Get file timestamp +ENGINE_API SLONG GetFileTimeStamp_t(const CTFileName &fnmFile); // throw char * +// Get CRC32 of a file +ENGINE_API ULONG GetFileCRC32_t(const CTFileName &fnmFile); // throw char * +// Test if a file is read only (also returns FALSE if file does not exist) +ENGINE_API BOOL IsFileReadOnly(const CTFileName &fnmFile); +// Delete a file (called 'remove' to avid name clashes with win32) +ENGINE_API BOOL RemoveFile(const CTFileName &fnmFile); + +// Expand a file's filename to full path + +// these are input flags for describing what you need the file for +#define EFP_READ (1UL<<0) // will open for reading +#define EFP_WRITE (1UL<<1) // will open for writing +#define EFP_NOZIPS (1UL<<31) // add this flag to forbid searching in zips +// these are return values +#define EFP_NONE 0 // doesn't exist +#define EFP_FILE 1 // generic file on disk +#define EFP_BASEZIP 2 // file in one of base zips +#define EFP_MODZIP 3 // file in one of mod zips +ENGINE_API INDEX ExpandFilePath(ULONG ulType, const CTFileName &fnmFile, CTFileName &fnmExpanded); + +// these are input flags for directory reading +#define DLI_RECURSIVE (1UL<<0) // recurse into subdirs +#define DLI_SEARCHCD (1UL<<1) // search the CD path also +// make a list of all files in a directory +ENGINE_API void MakeDirList( + CDynamicStackArray &adeDir, + const CTFileName &fnmDir, // directory to list + const CTString &strPattern, // pattern for each file to match ("" matches all) + ULONG ulFlags // additional flags +); + +// global string with application path +ENGINE_API extern CTFileName _fnmApplicationPath; +// global string with current MOD path +ENGINE_API extern CTFileName _fnmMod; +// global string with current name (the parameter that is passed on cmdline) +ENGINE_API extern CTString _strModName; +// global string with url to be shown to users that don't have the mod installed +// (should be set by game.dll) +ENGINE_API extern CTString _strModURL; +// global string with current MOD extension (for adding to dlls) +ENGINE_API extern CTString _strModExt; +// global string with CD path (for minimal installations) +ENGINE_API extern CTFileName _fnmCDPath; +// global string with filename of the started application +ENGINE_API extern CTFileName _fnmApplicationExe; + +// application path usage funtions +ENGINE_API void UseApplicationPath(void); +ENGINE_API void IgnoreApplicationPath(void); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Synchronization.cpp b/Sources/Engine/Base/Synchronization.cpp new file mode 100644 index 0000000..681415c --- /dev/null +++ b/Sources/Engine/Base/Synchronization.cpp @@ -0,0 +1,305 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" + +#include + + +/* +This is implementation of OPTEX (optimized mutex), +originally from MSDN Periodicals 1996, by Jeffrey Richter. + +It is updated for clearer comments, shielded with tons of asserts, +and modified to support TryToEnter() function. The original version +had timeout parameter, bu it didn't work. + +NOTES: +- TryToEnter() was not tested with more than one thread, and perhaps + there might be some problems with the final decrementing and eventual event resetting + when lock fails. Dunno. + +- take care to center the lock tests around 0 (-1 means not locked). that is + neccessary because win95 returns only <0, ==0 and >0 results from interlocked + functions, so testing against any other number than 0 doesn't work. +*/ + +// The opaque OPTEX data structure +typedef struct { + LONG lLockCount; // note: must center all tests around 0 for win95 compatibility! + DWORD dwThreadId; + LONG lRecurseCount; + HANDLE hEvent; +} OPTEX, *POPTEX; + +_declspec(thread) INDEX _iLastLockedMutex = 0; + +BOOL OPTEX_Initialize (POPTEX poptex) { + + poptex->lLockCount = -1; // No threads have enterred the OPTEX + poptex->dwThreadId = 0; // The OPTEX is unowned + poptex->lRecurseCount = 0; // The OPTEX is unowned + poptex->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + return(poptex->hEvent != NULL); // TRUE if the event is created +} + +VOID OPTEX_Delete (POPTEX poptex) { + + // No in-use check + CloseHandle(poptex->hEvent); // Close the event +} + +INDEX OPTEX_Enter (POPTEX poptex) +{ + + DWORD dwThreadId = GetCurrentThreadId(); // The calling thread's ID + + // increment lock counter + INDEX ctLocked = InterlockedIncrement(&poptex->lLockCount); + ASSERT(poptex->lLockCount>=0); + + // if this is first thread that entered + if (ctLocked == 0) { + + // mark that we own it, exactly once + ASSERT(poptex->dwThreadId==0); + ASSERT(poptex->lRecurseCount==0); + poptex->dwThreadId = dwThreadId; + poptex->lRecurseCount = 1; + + // if already owned + } else { + + // if owned by this thread + if (poptex->dwThreadId == dwThreadId) { + // just mark that we own it once more + poptex->lRecurseCount++; + ASSERT(poptex->lRecurseCount>1); + + // if owned by some other thread + } else { + + // wait for the owning thread to release the OPTEX + DWORD dwRet = WaitForSingleObject(poptex->hEvent, INFINITE); + ASSERT(dwRet == WAIT_OBJECT_0); + + // mark that we own it, exactly once + ASSERT(poptex->dwThreadId==0); + ASSERT(poptex->lRecurseCount==0); + poptex->dwThreadId = dwThreadId; + poptex->lRecurseCount = 1; + } + } + ASSERT(poptex->lRecurseCount>=1); + ASSERT(poptex->lLockCount>=0); + return poptex->lRecurseCount; +} + +INDEX OPTEX_TryToEnter (POPTEX poptex) +{ + ASSERT(poptex->lLockCount>=-1); + DWORD dwThreadId = GetCurrentThreadId(); // The calling thread's ID + + // increment lock counter + INDEX ctLocked = InterlockedIncrement(&poptex->lLockCount); + ASSERT(poptex->lLockCount>=0); + + // if this is first thread that entered + if (ctLocked == 0) { + + // mark that we own it, exactly once + ASSERT(poptex->dwThreadId==0); + ASSERT(poptex->lRecurseCount==0); + poptex->dwThreadId = dwThreadId; + poptex->lRecurseCount = 1; + // lock succeeded + return poptex->lRecurseCount; + + // if already owned + } else { + + // if owned by this thread + if (poptex->dwThreadId == dwThreadId) { + + // just mark that we own it once more + poptex->lRecurseCount++; + ASSERT(poptex->lRecurseCount>=1); + + // lock succeeded + return poptex->lRecurseCount; + + // if owned by some other thread + } else { + + // give up taking it + INDEX ctLocked = InterlockedDecrement(&poptex->lLockCount); + ASSERT(poptex->lLockCount>=-1); + + // if unlocked in the mean time + if (ctLocked<0) { + // NOTE: this has not been tested! + // ignore sent the signal + ResetEvent(poptex->hEvent); + } + + // lock failed + return 0; + } + } +} + +INDEX OPTEX_Leave (POPTEX poptex) +{ + + ASSERT(poptex->dwThreadId==GetCurrentThreadId()); + + // we own in one time less + poptex->lRecurseCount--; + ASSERT(poptex->lRecurseCount>=0); + INDEX ctResult = poptex->lRecurseCount; + + // if more multiple locks from this thread + if (poptex->lRecurseCount > 0) { + + // just decrement the lock count + InterlockedDecrement(&poptex->lLockCount); + ASSERT(poptex->lLockCount>=-1); + + // if no more multiple locks from this thread + } else { + + // mark that this thread doesn't own it + poptex->dwThreadId = 0; + // decrement the lock count + INDEX ctLocked = InterlockedDecrement(&poptex->lLockCount); + ASSERT(poptex->lLockCount>=-1); + // if some threads are waiting for it + if ( ctLocked >= 0) { + // wake one of them + SetEvent(poptex->hEvent); + } + } + + ASSERT(poptex->lRecurseCount>=0); + ASSERT(poptex->lLockCount>=-1); + return ctResult; +} + +// these are just wrapper classes for locking/unlocking + +CTCriticalSection::CTCriticalSection(void) +{ + // index must be set before using the mutex + cs_iIndex = -2; + cs_pvObject = new OPTEX; + OPTEX_Initialize((OPTEX*)cs_pvObject); +} +CTCriticalSection::~CTCriticalSection(void) +{ + OPTEX_Delete((OPTEX*)cs_pvObject); + delete (OPTEX*)cs_pvObject; +} +INDEX CTCriticalSection::Lock(void) +{ + return OPTEX_Enter((OPTEX*)cs_pvObject); +} +INDEX CTCriticalSection::TryToLock(void) +{ + return OPTEX_TryToEnter((OPTEX*)cs_pvObject); +} +INDEX CTCriticalSection::Unlock(void) +{ + return OPTEX_Leave((OPTEX*)cs_pvObject); +} + +CTSingleLock::CTSingleLock(CTCriticalSection *pcs, BOOL bLock) : sl_cs(*pcs) +{ + // initially not locked + sl_bLocked = FALSE; + sl_iLastLockedIndex = -2; + // critical section must have index assigned + ASSERT(sl_cs.cs_iIndex>=1||sl_cs.cs_iIndex==-1); + // if should lock immediately + if (bLock) { + Lock(); + } +} +CTSingleLock::~CTSingleLock(void) +{ + // if locked + if (sl_bLocked) { + // unlock + Unlock(); + } +} +void CTSingleLock::Lock(void) +{ + // must not be locked + ASSERT(!sl_bLocked); + ASSERT(sl_iLastLockedIndex==-2); + + // if not locked + if (!sl_bLocked) { + // lock + INDEX ctLocks = sl_cs.Lock(); + // if this mutex was not locked already + if (ctLocks==1) { + // check that locking in given order + if (sl_cs.cs_iIndex!=-1) { + ASSERT(_iLastLockedMutex=1) { + sl_bLocked = TRUE; + + // if this mutex was not locked already + if (ctLocks==1) { + // check that locking in given order + if (sl_cs.cs_iIndex!=-1) { + ASSERT(_iLastLockedMutex +#include +#include + +#include +#include +#include +#include + +#include +#include + +// Read the Pentium TimeStampCounter +static inline __int64 ReadTSC(void) +{ + __int64 mmRet; + __asm { + rdtsc + mov dword ptr [mmRet+0],eax + mov dword ptr [mmRet+4],edx + } + return mmRet; +} + + +// link with Win-MultiMedia +#pragma comment(lib, "winmm.lib") + +// current game time always valid for the currently active task +static _declspec(thread) TIME _CurrentTickTimer = 0.0f; + +// CTimer implementation + +// pointer to global timer object +CTimer *_pTimer = NULL; + +const TIME CTimer::TickQuantum = TIME(1/20.0); // 20 ticks per second + +/* + * Timer interrupt callback function. + */ +/* + NOTE: + This function is a bit more complicated than it could be, because + it has to deal with a feature in the windows multimedia timer that + is undesired here. + That is the fact that, if the timer function is stalled for a while, + because some other thread or itself took too much time, the timer function + is called more times to catch up with the hardware clock. + This can cause complete lockout if timer handlers constantly consume more + time than is available between two calls of timer function. + As a workaround, this function measures hardware time and refuses to call + the handlers if it is not on time. + + In effect, if some timer handler starts spending too much time, the + handlers are called at lower frequency until the application (hopefully) + stabilizes. + + When such a catch-up situation occurs, 'real time' timer still keeps + more or less up to date with the hardware time, but the timer handlers + skip some ticks. E.g. if timer handlers start spending twice more time + than is tick quantum, they get called approx. every two ticks. + + EXTRA NOTE: + Had to disable that, because it didn't work well (caused jerking) on + Win95 osr2 with no patches installed! +*/ +void CTimer_TimerFunc_internal(void) +{ +// Access to stream operations might be invoked in timer handlers, but +// this is disabled for now. Should also synchronize access to list of +// streams and to group file before enabling that! +// CTSTREAM_BEGIN { + + // increment the 'real time' timer + _pTimer->tm_RealTimeTimer += _pTimer->TickQuantum; + + // get the current time for real and in ticks + CTimerValue tvTimeNow = _pTimer->GetHighPrecisionTimer(); + TIME tmTickNow = _pTimer->tm_RealTimeTimer; + // calculate how long has passed since we have last been on time + TIME tmTimeDelay = (TIME)(tvTimeNow - _pTimer->tm_tvLastTimeOnTime).GetSeconds(); + TIME tmTickDelay = (tmTickNow - _pTimer->tm_tmLastTickOnTime); + + _sfStats.StartTimer(CStatForm::STI_TIMER); + // if we are keeping up to time (more or less) +// if (tmTimeDelay>=_pTimer->TickQuantum*0.9f) { + + // for all hooked handlers + FOREACHINLIST(CTimerHandler, th_Node, _pTimer->tm_lhHooks, itth) { + // handle + itth->HandleTimer(); + } +// } + _sfStats.StopTimer(CStatForm::STI_TIMER); + + // remember that we have been on time now + _pTimer->tm_tvLastTimeOnTime = tvTimeNow; + _pTimer->tm_tmLastTickOnTime = tmTickNow; + +// } CTSTREAM_END; +} +void __stdcall CTimer_TimerFunc(UINT uID, UINT uMsg, ULONG dwUser, ULONG dw1, ULONG dw2) +{ + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + // handle all timers + CTimer_TimerFunc_internal(); +} + + +#pragma inline_depth() + +#define MAX_MEASURE_TRIES 5 +static INDEX _aiTries[MAX_MEASURE_TRIES]; + +// Get processor speed in Hertz +static __int64 GetCPUSpeedHz(void) +{ + // get the frequency of the 'high' precision timer + __int64 llTimerFrequency; + BOOL bPerformanceCounterPresent = QueryPerformanceFrequency((LARGE_INTEGER*)&llTimerFrequency); + // fail if the performance counter is not available on this system + if( !bPerformanceCounterPresent) { + CPrintF( TRANS("PerformanceTimer is not available!\n")); + return 1; + } + + INDEX iSpeed, iTry; + INDEX ctTotalFaults=0; + __int64 llTimeLast, llTimeNow; + __int64 llCPUBefore, llCPUAfter; + __int64 llTimeBefore, llTimeAfter; + __int64 llSpeedMeasured; + + // try to measure 10 times + INDEX iSet=0; + for( ; iSet<10; iSet++) + { // one time has several tries + for( iTry=0; iTry iTolerance) ctFaults++; + } + // done if no faults + if( ctFaults==0) break; + Sleep(1000); + } + + // fail if couldn't readout CPU speed + if( iSet==10) { + CPrintF( TRANS("PerformanceTimer is not vaild!\n")); + //return 1; + // NOTE: this function must never fail, or the engine will crash! + // if this failed, the speed will be read from registry (only happens on Win2k) + } + + // keep readout speed and read speed from registry + const SLONG slSpeedRead = _aiTries[0]; + SLONG slSpeedReg = 0; + BOOL bFoundInReg = REG_GetLong("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\~MHz", (ULONG&)slSpeedReg); + + // if not found in registry + if( !bFoundInReg) { + // use measured + CPrintF(TRANS(" CPU speed not found in registry, using calculated value\n\n")); + return (__int64)slSpeedRead*1000000; + // if found in registry + } else { + // if different than measured + const INDEX iTolerance = slSpeedRead *1/100; // %1 tolerance should be enough + if( abs(slSpeedRead-slSpeedReg) > iTolerance) { + // report warning and use registry value + CPrintF(TRANS(" WARNING: calculated CPU speed different than stored in registry!\n\n")); + return (__int64)slSpeedReg*1000000; + } + // use measured value + return (__int64)slSpeedRead*1000000; + } +} + + +/* + * Constructor. + */ +CTimer::CTimer(BOOL bInterrupt /*=TRUE*/) +{ + tm_csHooks.cs_iIndex = 1000; + // set global pointer + ASSERT(_pTimer == NULL); + _pTimer = this; + tm_bInterrupt = bInterrupt; + + { // this part of code must be executed as precisely as possible + CSetPriority sp(REALTIME_PRIORITY_CLASS, THREAD_PRIORITY_TIME_CRITICAL); + tm_llCPUSpeedHZ = GetCPUSpeedHz(); + tm_llPerformanceCounterFrequency = tm_llCPUSpeedHZ; + + // measure profiling errors and set epsilon corrections + CProfileForm::CalibrateProfilingTimers(); + } + + // clear counters + _CurrentTickTimer = TIME(0); + tm_RealTimeTimer = TIME(0); + + tm_tmLastTickOnTime = TIME(0); + tm_tvLastTimeOnTime = GetHighPrecisionTimer(); + // disable lerping by default + tm_fLerpFactor = 1.0f; + tm_fLerpFactor2 = 1.0f; + + // start interrupt (eventually) + if( tm_bInterrupt) + { + tm_TimerID = timeSetEvent( + ULONG(TickQuantum*1000.0f), // period value [ms] + 0, // resolution (0==max. possible) + &CTimer_TimerFunc, // callback + 0, // user + TIME_PERIODIC); // event type + + // check that interrupt was properly started + if( tm_TimerID==NULL) FatalError(TRANS("Cannot initialize multimedia timer!")); + + // make sure that timer interrupt is ticking + INDEX iTry=1; + for( ; iTry<=3; iTry++) { + const TIME tmTickBefore = GetRealTimeTick(); + Sleep(1000* iTry*3 *TickQuantum); + const TIME tmTickAfter = GetRealTimeTick(); + if( tmTickBefore!=tmTickAfter) break; + Sleep(1000*iTry); + } + // report fatal + if( iTry>3) FatalError(TRANS("Problem with initializing multimedia timer - please try again.")); + } +} + +/* + * Destructor. + */ +CTimer::~CTimer(void) +{ + ASSERT(_pTimer == this); + + // destroy timer + if (tm_bInterrupt) { + ASSERT(tm_TimerID!=NULL); + ULONG rval = timeKillEvent(tm_TimerID); + ASSERT(rval == TIMERR_NOERROR); + } + // check that all handlers have been removed + ASSERT(tm_lhHooks.IsEmpty()); + + // clear global pointer + _pTimer = NULL; +} + +/* + * Add a timer handler. + */ +void CTimer::AddHandler(CTimerHandler *pthNew) +{ + // access to the list of handlers must be locked + CTSingleLock slHooks(&tm_csHooks, TRUE); + + ASSERT(this!=NULL); + tm_lhHooks.AddTail(pthNew->th_Node); +} + +/* + * Remove a timer handler. + */ +void CTimer::RemHandler(CTimerHandler *pthOld) +{ + // access to the list of handlers must be locked + CTSingleLock slHooks(&tm_csHooks, TRUE); + + ASSERT(this!=NULL); + pthOld->th_Node.Remove(); +} + +/* Handle timer handlers manually. */ +void CTimer::HandleTimerHandlers(void) +{ + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + // handle all timers + CTimer_TimerFunc_internal(); +} + + +/* + * Set the real time tick value. + */ +void CTimer::SetRealTimeTick(TIME tNewRealTimeTick) +{ + ASSERT(this!=NULL); + tm_RealTimeTimer = tNewRealTimeTick; +} + +/* + * Get the real time tick value. + */ +TIME CTimer::GetRealTimeTick(void) const +{ + ASSERT(this!=NULL); + return tm_RealTimeTimer; +} + +/* + * Set the current game tick used for time dependent tasks (animations etc.). + */ +void CTimer::SetCurrentTick(TIME tNewCurrentTick) { + ASSERT(this!=NULL); + _CurrentTickTimer = tNewCurrentTick; +} + +/* + * Get current game time, always valid for the currently active task. + */ +const TIME CTimer::CurrentTick(void) const { + ASSERT(this!=NULL); + return _CurrentTickTimer; +} +const TIME CTimer::GetLerpedCurrentTick(void) const { + ASSERT(this!=NULL); + return _CurrentTickTimer+tm_fLerpFactor*TickQuantum; +} +// Set factor for lerping between ticks. +void CTimer::SetLerp(FLOAT fFactor) // sets both primary and secondary +{ + ASSERT(this!=NULL); + tm_fLerpFactor = fFactor; + tm_fLerpFactor2 = fFactor; +} +void CTimer::SetLerp2(FLOAT fFactor) // sets only secondary +{ + ASSERT(this!=NULL); + tm_fLerpFactor2 = fFactor; +} +// Disable lerping factor (set both factors to 1) +void CTimer::DisableLerp(void) +{ + ASSERT(this!=NULL); + tm_fLerpFactor =1.0f; + tm_fLerpFactor2=1.0f; +} + +// convert a time value to a printable string (hh:mm:ss) +CTString TimeToString(FLOAT fTime) +{ + CTString strTime; + int iSec = floor(fTime); + int iMin = iSec/60; + iSec = iSec%60; + int iHou = iMin/60; + iMin = iMin%60; + strTime.PrintF("%02d:%02d:%02d", iHou, iMin, iSec); + return strTime; +} diff --git a/Sources/Engine/Base/Timer.h b/Sources/Engine/Base/Timer.h new file mode 100644 index 0000000..396af8f --- /dev/null +++ b/Sources/Engine/Base/Timer.h @@ -0,0 +1,140 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TIMER_H +#define SE_INCL_TIMER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#ifndef _MT +#error Multithreading support is required! +#endif + +#include +#include + +/* + * Class that holds and manipulates with high-precision timer values. + */ +class CTimerValue { +public: + __int64 tv_llValue; // 64 bit integer (MSVC specific!) + /* Constructor from quad integer. */ + inline CTimerValue(__int64 llValue) : tv_llValue(llValue) {}; +public: + /* Constructor. */ + inline CTimerValue(void) {}; + /* Constructor from seconds. */ + inline CTimerValue(double dSeconds); + /* Clear timer value (set it to zero). */ + inline void Clear(void); + /* Addition. */ + inline CTimerValue &operator+=(const CTimerValue &tvOther); + inline CTimerValue operator+(const CTimerValue &tvOther) const; + /* Substraction. */ + inline CTimerValue &operator-=(const CTimerValue &tvOther); + inline CTimerValue operator-(const CTimerValue &tvOther) const; + /* Comparisons. */ + inline BOOL operator<(const CTimerValue &tvOther) const; + inline BOOL operator>(const CTimerValue &tvOther) const; + inline BOOL operator<=(const CTimerValue &tvOther) const; + inline BOOL operator>=(const CTimerValue &tvOther) const; + /* Get the timer value in seconds. - use for time spans only! */ + inline double GetSeconds(void); + /* Get the timer value in milliseconds as integral value. */ + inline __int64 GetMilliseconds(void); +}; +// a base class for hooking on timer interrupt +class CTimerHandler { +public: + CListNode th_Node; +public: + virtual ~CTimerHandler(void) {} /* rcg10042001 */ + /* This is called every TickQuantum seconds. */ + ENGINE_API virtual void HandleTimer(void)=0; +}; + +// class for an object that maintains global timer(s) +class ENGINE_API CTimer { +// implementation: +public: + + __int64 tm_llPerformanceCounterFrequency; // frequency of Win32 performance counter + __int64 tm_llCPUSpeedHZ; // CPU speed in HZ + + CTimerValue tm_tvLastTimeOnTime; // last time when timer was on time + TIME tm_tmLastTickOnTime; // last tick when timer was on time + + TIME tm_RealTimeTimer; // this really ticks at 1/TickQuantum frequency + FLOAT tm_fLerpFactor; // factor used for lerping between frames + FLOAT tm_fLerpFactor2; // secondary lerp-factor used for unpredicted movement + + ULONG tm_TimerID; // windows timer ID + + CTCriticalSection tm_csHooks; // access to timer hooks + CListHead tm_lhHooks; // a list head for timer hooks + BOOL tm_bInterrupt; // set if interrupt is added + +// interface: +public: + // interval defining frequency of the game ticker + static const TIME TickQuantum; // 20 ticks per second + + /* Constructor. */ + CTimer(BOOL bInterrupt=TRUE); + /* Destructor. */ + ~CTimer(void); + /* Add a timer handler. */ + void AddHandler(CTimerHandler *pthNew); + /* Remove a timer handler. */ + void RemHandler(CTimerHandler *pthOld); + /* Handle timer handlers manually. */ + void HandleTimerHandlers(void); + + /* Set the real time tick value. */ + void SetRealTimeTick(TIME tNewRealTimeTick); + /* Get the real time tick value. */ + TIME GetRealTimeTick(void) const; + + /* NOTE: CurrentTick is local to each thread, and every thread must take + care to increment the current tick or copy it from real time tick if + it wants to make animations and similar to work. */ + + /* Set the current game tick used for time dependent tasks (animations etc.). */ + void SetCurrentTick(TIME tNewCurrentTick); + /* Get current game time, always valid for the currently active task. */ + const TIME CurrentTick(void) const; + /* Get lerped game time. */ + const TIME GetLerpedCurrentTick(void) const; + + // Set factor for lerping between ticks. + void SetLerp(FLOAT fLerp); // sets both primary and secondary + void SetLerp2(FLOAT fLerp); // sets only secondary + // Disable lerping factor (set both factors to 1) + void DisableLerp(void); + // Get current factor used for lerping between game ticks. + inline FLOAT GetLerpFactor(void) const { return tm_fLerpFactor; }; + // Get current factor used for lerping between game ticks. + inline FLOAT GetLerpFactor2(void) const { return tm_fLerpFactor2; }; + + /* Get current timer value of high precision timer. */ + inline CTimerValue GetHighPrecisionTimer(void) { + __int64 mmRet; + _asm rdtsc + _asm mov dword ptr [mmRet+0],eax + _asm mov dword ptr [mmRet+4],edx + return mmRet; + }; +}; + +// pointer to global timer object +ENGINE_API extern CTimer *_pTimer; + +// convert a time value to a printable string (hh:mm:ss) +ENGINE_API CTString TimeToString(FLOAT fTime); + +#include + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Timer.inl b/Sources/Engine/Base/Timer.inl new file mode 100644 index 0000000..eb17b9a --- /dev/null +++ b/Sources/Engine/Base/Timer.inl @@ -0,0 +1,57 @@ +#ifndef SE_INCL_TIMER_INL +#define SE_INCL_TIMER_INL +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* Constructor from seconds. */ +inline CTimerValue::CTimerValue(double fSeconds) +{ + tv_llValue = __int64(fSeconds*_pTimer->tm_llPerformanceCounterFrequency); +} +/* Clear timer value (set it to zero). */ +inline void CTimerValue::Clear(void) +{ + tv_llValue = 0; +} +/* Addition. */ +inline CTimerValue &CTimerValue::operator+=(const CTimerValue &tvOther) { + tv_llValue+=tvOther.tv_llValue; + return *this; +}; +inline CTimerValue CTimerValue::operator+(const CTimerValue &tvOther) const { + return CTimerValue(*this)+=tvOther; +}; +/* Substraction. */ +inline CTimerValue &CTimerValue::operator-=(const CTimerValue &tvOther) { + tv_llValue-=tvOther.tv_llValue; + return *this; +}; +inline CTimerValue CTimerValue::operator-(const CTimerValue &tvOther) const { + return CTimerValue(*this)-=tvOther; +}; +/* Comparisons. */ +inline BOOL CTimerValue::operator<(const CTimerValue &tvOther) const { + return tv_llValue(const CTimerValue &tvOther) const { + return tv_llValue>tvOther.tv_llValue; +} +inline BOOL CTimerValue::operator<=(const CTimerValue &tvOther) const { + return tv_llValue<=tvOther.tv_llValue; +} +inline BOOL CTimerValue::operator>=(const CTimerValue &tvOther) const { + return tv_llValue>=tvOther.tv_llValue; +} +/* Get the timer value in seconds. - use for time spans only! */ +inline double CTimerValue::GetSeconds(void) { + return ((double)tv_llValue)/_pTimer->tm_llPerformanceCounterFrequency; +}; +/* Get the timer value in milliseconds as integral value. */ +inline __int64 CTimerValue::GetMilliseconds(void) { + return tv_llValue/(_pTimer->tm_llPerformanceCounterFrequency/1000); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Translation.cpp b/Sources/Engine/Base/Translation.cpp new file mode 100644 index 0000000..1bbb88a --- /dev/null +++ b/Sources/Engine/Base/Translation.cpp @@ -0,0 +1,208 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +// table of translations +static CNameTable_CTranslationPair _nttpPairs; +static CDynamicArray _atpPairs; +static int _iLine; + +#define CHAR_EOF -1 +#define CHAR_SRC -2 +#define CHAR_DST -3 + +static int ReadOneChar_t(CTStream &strm) +{ + // skip line breaks and count them + unsigned char c; + do { + strm>>c; + if (c=='\n') { + _iLine++; + } + } while (c=='\n' || c=='\r'); + + // if start of control token + if (c=='\\') { + // read next char + strm>>c; + // decode token + switch (c) { + case '\\': return '\\'; + // eol + case 'n': return '\n'; + // string end + case '0': return 0; + // source string + case '<': return CHAR_SRC; + // destination string + case '>': return CHAR_DST; + // file end + case '$': return CHAR_EOF; + // other + default: + if (isprint(c)) { + ThrowF_t(TRANS("%d: unknown token '%c'"), _iLine, c); + } else { + ThrowF_t(TRANS("%d: unknown token ascii: 0x%02x"), _iLine, c); + } + } + } + + return c; +} +// read one translation string from file +static CTString ReadOneString_t(CTStream &strm) +{ + // start with empty string + CTString str; + + // read characters + FOREVER{ + int i = ReadOneChar_t(strm); + if (i==0) { + return str; + } else { + char c[2]; + c[1] = 0; + c[0] = i; + str+=c; + } + } +} + +// init translation routines with given translation table +ENGINE_API void InitTranslation(void) +{ + // init tables + _atpPairs.Clear(); + _nttpPairs.Clear(); + _nttpPairs.SetAllocationParameters(100, 5, 5); +} + +ENGINE_API void ReadTranslationTable_t( + CDynamicArray &atpPairs, const CTFileName &fnmTable) // throw char * +{ + _iLine = 0; + + CTFileStream strm; + strm.Open_t(fnmTable); + + // read number of pairs + INDEX ctPairs; + CTString strPairs = ReadOneString_t(strm); + strPairs.ScanF("%d", &ctPairs); + + // instance that much + CTranslationPair *atp = atpPairs.New(ctPairs); + + // for each pair + for(INDEX iPair=0; iPair, premature EOF in line #%d!"), + (const char *)fnmTable, _iLine); + } else { + ThrowF_t(TRANS("error in file <%s>, line #%d (pair #%d): expected '<' but found '%c'"), + (const char *)fnmTable, _iLine, iPair, iToken); + } + } + // read source + tp.tp_strSrc = ReadOneString_t(strm); + // next token must be destination + if (ReadOneChar_t(strm)!=CHAR_DST) { + if (iToken==CHAR_EOF) { + ThrowF_t(TRANS("error in file <%s>, premature EOF in line #%d!"), + (const char *)fnmTable, _iLine); + } else { + ThrowF_t(TRANS("error in file <%s>, line #%d (pair #%d): expected '>' but found '%c'"), + (const char *)fnmTable, _iLine, iPair, iToken); + } + } + // read destination + tp.tp_strDst = ReadOneString_t(strm); + }; + // last token must be eof + if (ReadOneChar_t(strm)!=CHAR_EOF) { + ThrowF_t(TRANS("error in file <%s>: end of file marker not found in line #%d!"), (const char *)fnmTable, _iLine); + } +} + +// finish translation table building +ENGINE_API void FinishTranslationTable(void) +{ + INDEX ctPairs = _atpPairs.Count(); + // for each pair + _atpPairs.Lock(); + for(INDEX iPair=0; iPairSetKeyNames(); +} + +// add given translation table +ENGINE_API void AddTranslationTable_t(const CTFileName &fnmTable) // throw char * +{ + // just read it to global array + ReadTranslationTable_t(_atpPairs, fnmTable); +} + +// add several tables from a directory using wildcards +ENGINE_API void AddTranslationTablesDir_t(const CTFileName &fnmDir, const CTFileName &fnmPattern) // throw char * +{ + // list the translation tables matching given pattern + CDynamicStackArray afnmTables; + MakeDirList(afnmTables, fnmDir, fnmPattern, 0); + for(INDEX i=0; i=iOffset) { + str+=iOffset; + } else { + ASSERT(FALSE); + } + // find translation pair + CTranslationPair *ptp = NULL; + if (_atpPairs.Count()>0) { + ptp = _nttpPairs.Find(str); + } + // if not found + if (ptp==NULL) { + // return original string + return str; + // if found + } else { + // return translation + return ptp->tp_strDst; + } +} diff --git a/Sources/Engine/Base/Translation.h b/Sources/Engine/Base/Translation.h new file mode 100644 index 0000000..0fbc2f8 --- /dev/null +++ b/Sources/Engine/Base/Translation.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TRANSLATION_H +#define SE_INCL_TRANSLATION_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// init translation routines with given translation table +ENGINE_API void InitTranslation(void); +// add given translation table +ENGINE_API void AddTranslationTable_t(const CTFileName &fnmTable); // throw char * +// add several tables from a directory using wildcards +ENGINE_API void AddTranslationTablesDir_t(const CTFileName &fnmDir, const CTFileName &fnmPattern); // throw char * +// finish translation table building +ENGINE_API void FinishTranslationTable(void); + +// read given translation table from file - for internal use +ENGINE_API void ReadTranslationTable_t( + CDynamicArray &atpPairs, const CTFileName &fnmTable); // throw char * + +// translate a string +ENGINE_API char * Translate(char *str, INDEX iOffset=0); +ENGINE_API const char * TranslateConst(const char *str, INDEX iOffset=0); + +// macro for inserting a string for translation into executables +#define TRANS(str) Translate("ETRS" str, 4) +// macro for translating a variable string (usually can be CTString) +#define TRANSV(str) TranslateConst(str, 0) + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/TranslationPair.h b/Sources/Engine/Base/TranslationPair.h new file mode 100644 index 0000000..788914f --- /dev/null +++ b/Sources/Engine/Base/TranslationPair.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TRANSLATIONPAIR_H +#define SE_INCL_TRANSLATIONPAIR_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +class CTranslationPair { +public: + BOOL m_bUsed; // for internal use while building the table + CTString tp_strSrc; // original string + CTString tp_strDst; // translated string + + CTranslationPair(void) : m_bUsed(FALSE) {}; + + inline void Clear(void) { + tp_strSrc.Clear(); + tp_strDst.Clear(); + }; + + // getname function for addinf to nametable + inline const CTString &GetName(void) const { return tp_strSrc; }; +}; + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Types.h b/Sources/Engine/Base/Types.h new file mode 100644 index 0000000..bdc196c --- /dev/null +++ b/Sources/Engine/Base/Types.h @@ -0,0 +1,410 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TYPES_H +#define SE_INCL_TYPES_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +typedef signed long int SLONG; +typedef signed short int SWORD; +typedef signed char SBYTE; +typedef signed int SINT; + +typedef unsigned long int ULONG; +typedef unsigned short int UWORD; +typedef unsigned char UBYTE; +typedef unsigned int UINT; + + +#ifdef PLATFORM_UNIX /* rcg10042001 */ + #define __forceinline inline + + #if (!defined MAX_PATH) + #define MAX_PATH 256 + #endif + + typedef long long __int64; + typedef unsigned long int DWORD; + typedef signed long int LONG; + + typedef void *HWND; /* !!! FIXME this sucks. */ + typedef void *HINSTANCE; /* !!! FIXME this sucks. */ + typedef void *HGLRC; /* !!! FIXME this sucks. */ + typedef ULONG COLORREF; /* !!! FIXME this sucks. */ + + typedef struct + { + LONG x; + LONG y; + } POINT; + + typedef struct + { + LONG left; + LONG top; + LONG right; + LONG bottom; + } RECT; +#endif + + +#define MAX_SLONG ((SLONG)0x7FFFFFFFL) +#define MAX_SWORD ((UWORD)0x7FFF) +#define MAX_SBYTE ((SBYTE)0x7F) + +#define MIN_SLONG ((SLONG)0x80000000L) +#define MIN_SWORD ((SWORD)0x8000) +#define MIN_SBYTE ((SBYTE)0x80) + +#define MIN_ULONG ((ULONG)0x00000000L) +#define MIN_UWORD ((UWORD)0x0000) +#define MIN_UBYTE ((UBYTE)0x00) + +#define MAX_ULONG ((ULONG)0xFFFFFFFFL) +#define MAX_UWORD ((UWORD)0xFFFF) +#define MAX_UBYTE ((UBYTE)0xFF) + +typedef int BOOL; // this is for TRUE/FALSE +typedef long int RESULT; // for error codes +typedef long int INDEX; // for indexed values and quantities + +#define FALSE 0 +#define TRUE 1 + +#define NONE 0 +#define NOTHING ((void) 0) +#define FOREVER for(;;) + +#define DECLARE_NOCOPYING(classname) \ + classname(const classname &c); \ + classname &operator=(const classname &c); +#define IMPLEMENT_NOCOPYING(classname) \ + classname::classname(const classname &c) { ASSERT(FALSE); }; \ + classname &classname::operator=(const classname &c){ ASSERT(FALSE); return *this; }; + +// standard angles +#define ANGLE_0 ( 0.0f) +#define ANGLE_90 ( 90.0f) +#define ANGLE_180 (180.0f) +#define ANGLE_270 (270.0f) +#define ANGLE_360 (360.0f) + +// you need for this! +#define structptr(structure, member, ptr) \ +( (struct structure *) ( ((UBYTE *)(ptr)) - \ + offsetof(struct structure, member)) ) + +// standard types + +// simple types +typedef SLONG PIX; // pixel coordinates +typedef SLONG TEX; // texel coordinates +typedef SLONG MEX; // texels in mip-level 0 +typedef float FLOAT; +typedef double DOUBLE; +typedef float ANGLE; +typedef float TIME; +typedef FLOAT RANGE; +typedef ULONG COLOR; // color is always in 32 bit true-color format + +// macros for windows/croteam true color conversion +#define CLRF_CLR(clr) ( ((clr & 0xff000000) >> 24) | \ + ((clr & 0x00ff0000) >> 8) | \ + ((clr & 0x0000ff00) << 8)) +#define CLR_CLRF(clrref) ( ((clrref & 0x000000ff) << 24) | \ + ((clrref & 0x0000ff00) << 8) | \ + ((clrref & 0x00ff0000) >> 8)) + +// z-buffer depth constants +#define ZBUF_FRONT (0.0f) +#define ZBUF_BACK (1.0f) + +// alpha factor constants +#define CT_OPAQUE MAX_UBYTE +#define CT_TRANSPARENT MIN_UBYTE + +// line types (masks) +#define _FULL_ 0xFFFFFFFF +#define _SYMMET16_ 0xFF88FF88 +#define _SYMMET32_ 0xFFFF0180 +#define _POINT_ 0xAAAAAAAA + +#define _DOT2_ 0xCCCCCCCC +#define _DOT4_ 0xF0F0F0F0 +#define _DOT8_ 0xFF00FF00 +#define _DOT16_ 0xFFFF0000 + +#define _TY31_ 0xEEEEEEEE +#define _TY62_ 0xFCFCFCFC +#define _TY124_ 0xFFF0FFF0 +#define _TY13_ 0x88888888 +#define _TY26_ 0xC0C0C0C0 +#define _TY412_ 0xF000F000 + +// some mexels constants +#define MAX_MEX_LOG2 10 +#define MIN_MEX_LOG2 0 +#define MAX_MEX (1L< class CListIter; +template class CDynamicArray; +template class CDynamicStackArray; +template class CDynamicArrayIterator; +template class CStaticArray; +template class CStaticStackArray; +template class CStaticArrayIterator; +template class CLinearAllocator; +template class CDynamicContainer; +template class Matrix; +template class AABBox; +template class Vector; +template class Plane; +template class OBBox; +template class Quaternion; +template class FixInt; + +template class BSPVertex; +template class BSPVertexContainer; +template class BSPEdge; +template class BSPNode; +template class BSPPolygon; +template class BSPTree; +template class BSPCutter; + +typedef FixInt<16,16> FIX16_16; + +// vectors +typedef Vector PIX2D; +typedef Vector MEX2D; +typedef Vector PIX3D; +typedef Vector ANGLE3D; +typedef Vector FLOAT2D; +typedef Vector FLOAT3D; +typedef Vector DOUBLE2D; +typedef Vector DOUBLE3D; + +// planes +typedef Plane FLOATplane3D; +typedef Plane DOUBLEplane3D; + +// axis-aligned bounding boxes +typedef AABBox MEXaabbox2D; +typedef AABBox PIXaabbox2D; +typedef AABBox FLOATaabbox2D; +typedef AABBox FLOATaabbox3D; +typedef AABBox DOUBLEaabbox2D; +typedef AABBox DOUBLEaabbox3D; + +// oriented bounding boxes +typedef OBBox FLOATobbox3D; +typedef OBBox DOUBLEobbox3D; + +// matrices +typedef Matrix PIXmatrix2D; +typedef Matrix PIXmatrix3D; +typedef Matrix ANGLEmatrix3D; +typedef Matrix FLOATmatrix2D; +typedef Matrix FLOATmatrix3D; +typedef Matrix DOUBLEmatrix3D; +typedef FLOAT Matrix12[12]; + +// quaternions +typedef Quaternion FLOATquat3D; +typedef Quaternion DOUBLEquat3D; + +// BSP types +typedef BSPVertex DOUBLEbspvertex3D; +typedef BSPVertexContainer DOUBLEbspvertexcontainer3D; +typedef BSPEdge DOUBLEbspedge3D; +typedef BSPNode DOUBLEbspnode3D; +typedef BSPPolygon DOUBLEbsppolygon3D; +typedef BSPTree DOUBLEbsptree3D; +typedef BSPCutter DOUBLEbspcutter3D; + +typedef BSPVertex FLOATbspvertex3D; +typedef BSPVertexContainer FLOATbspvertexcontainer3D; +typedef BSPEdge FLOATbspedge3D; +typedef BSPNode FLOATbspnode3D; +typedef BSPPolygon FLOATbsppolygon3D; +typedef BSPTree FLOATbsptree3D; +typedef BSPCutter FLOATbspcutter3D; + +// general clearing functions +template +inline void Clear(cType &t) { t.cType::Clear(); }; + +// specific clearing functions for built-in types +inline void Clear(signed long int sli) {}; +inline void Clear(unsigned long int uli) {}; +inline void Clear(int i) {}; +inline void Clear(float i) {}; +inline void Clear(double i) {}; +inline void Clear(void *pv) {}; + +#define SYMBOLLOCATOR(symbol) + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Unzip.cpp b/Sources/Engine/Base/Unzip.cpp new file mode 100644 index 0000000..a985fc5 --- /dev/null +++ b/Sources/Engine/Base/Unzip.cpp @@ -0,0 +1,783 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// unzip.cpp : Defines the entry point for the console application. +// + +#include "stdh.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +extern CTCriticalSection zip_csLock; // critical section for access to zlib functions + +#pragma pack(1) + +// before each file in the zip +#define SIGNATURE_LFH 0x04034b50 +struct LocalFileHeader { + SWORD lfh_swVersionToExtract; + SWORD lfh_swGPBFlag; + SWORD lfh_swCompressionMethod; + SWORD lfh_swModFileTime; + SWORD lfh_swModFileDate; + SLONG lfh_slCRC32; + SLONG lfh_slCompressedSize; + SLONG lfh_slUncompressedSize; + SWORD lfh_swFileNameLen; + SWORD lfh_swExtraFieldLen; + +// follows: +// filename (variable size) +// extra field (variable size) +}; + +// after file data, only if compressed from a non-seekable stream +// this exists only if bit 3 in GPB flag is set +#define SIGNATURE_DD 0x08074b50 +struct DataDescriptor { + SLONG dd_slCRC32; + SLONG dd_slCompressedSize; + SLONG dd_slUncompressedSize; +}; + +// one file in central dir +#define SIGNATURE_FH 0x02014b50 +struct FileHeader { + SWORD fh_swVersionMadeBy; + SWORD fh_swVersionToExtract; + SWORD fh_swGPBFlag; + SWORD fh_swCompressionMethod; + SWORD fh_swModFileTime; + SWORD fh_swModFileDate; + SLONG fh_slCRC32; + SLONG fh_slCompressedSize; + SLONG fh_slUncompressedSize; + SWORD fh_swFileNameLen; + SWORD fh_swExtraFieldLen; + SWORD fh_swFileCommentLen; + SWORD fh_swDiskNoStart; + SWORD fh_swInternalFileAttributes; + SLONG fh_swExternalFileAttributes; + SLONG fh_slLocalHeaderOffset; + +// follows: +// filename (variable size) +// extra field (variable size) +// file comment (variable size) +}; + +// at the end of entire zip file +#define SIGNATURE_EOD 0x06054b50 +struct EndOfDir { + SWORD eod_swDiskNo; + SWORD eod_swDirStartDiskNo; + SWORD eod_swEntriesInDirOnThisDisk; + SWORD eod_swEntriesInDir; + SLONG eod_slSizeOfDir; + SLONG eod_slDirOffsetInFile; + SWORD eod_swCommentLenght; +// follows: +// zipfile comment (variable size) +}; + +#pragma pack() + +// one entry (a zipped file) in a zip archive +class CZipEntry { +public: + CTFileName *ze_pfnmArchive; // path of the archive + CTFileName ze_fnm; // file name with path inside archive + SLONG ze_slCompressedSize; // size of file in the archive + SLONG ze_slUncompressedSize; // size when uncompressed + SLONG ze_slDataOffset; // position of compressed data inside archive + ULONG ze_ulCRC; // checksum of the file + BOOL ze_bStored; // set if file is not compressed, but stored + BOOL ze_bMod; // set if from a mod's archive + + void Clear(void) + { + ze_pfnmArchive = NULL; + ze_fnm.Clear(); + } +}; + +// an open instance of a file inside a zip +class CZipHandle { +public: + BOOL zh_bOpen; // set if the handle is used + CZipEntry zh_zeEntry; // the entry itself + z_stream zh_zstream; // zlib filestream for decompression + FILE *zh_fFile; // open handle of the archive +#define BUF_SIZE 1024 + UBYTE *zh_pubBufIn; // input buffer + + CZipHandle(void); + void Clear(void); + void ThrowZLIBError_t(int ierr, const CTString &strDescription); +}; + +// get error string for a zlib error +CTString GetZlibError(int ierr) +{ + switch(ierr) { + case Z_OK : return TRANS("Z_OK "); break; + case Z_STREAM_END : return TRANS("Z_STREAM_END "); break; + case Z_NEED_DICT : return TRANS("Z_NEED_DICT "); break; + case Z_STREAM_ERROR : return TRANS("Z_STREAM_ERROR "); break; + case Z_DATA_ERROR : return TRANS("Z_DATA_ERROR "); break; + case Z_MEM_ERROR : return TRANS("Z_MEM_ERROR "); break; + case Z_BUF_ERROR : return TRANS("Z_BUF_ERROR "); break; + case Z_VERSION_ERROR: return TRANS("Z_VERSION_ERROR"); break; + case Z_ERRNO : { + CTString strError; + strError.PrintF(TRANS("Z_ERRNO: %s"), strerror(errno)); + return strError; + } break; + default: { + CTString strError; + strError.PrintF(TRANS("Unknown ZLIB error: %d"), ierr); + return strError; + } break; + } +} + +CZipHandle::CZipHandle(void) +{ + zh_bOpen = FALSE; + zh_fFile = NULL; + zh_pubBufIn = NULL; + memset(&zh_zstream, 0, sizeof(zh_zstream)); +} +void CZipHandle::Clear(void) +{ + zh_bOpen = FALSE; + zh_zeEntry.Clear(); + + // clear the zlib stream + CTSingleLock slZip(&zip_csLock, TRUE); + inflateEnd(&zh_zstream); + memset(&zh_zstream, 0, sizeof(zh_zstream)); + + // free buffers + if (zh_pubBufIn!=NULL) { + FreeMemory(zh_pubBufIn); + zh_pubBufIn = NULL; + } + // close the zip archive file + if (zh_fFile!=NULL) { + fclose(zh_fFile); + zh_fFile = NULL; + } +} +void CZipHandle::ThrowZLIBError_t(int ierr, const CTString &strDescription) +{ + ThrowF_t(TRANS("(%s/%s) %s - ZLIB error: %s - %s"), + (const CTString&)*zh_zeEntry.ze_pfnmArchive, + (const CTString&)zh_zeEntry.ze_fnm, + strDescription, GetZlibError(ierr), zh_zstream.msg); +} + +// all files in all active zip archives +static CStaticStackArray _azeFiles; +// handles for currently open files +static CStaticStackArray _azhHandles; +// filenames of all archives +static CStaticStackArray _afnmArchives; + +// convert slashes to backslashes in a file path +void ConvertSlashes(char *p) +{ + while (*p!=0) { + if (*p=='/') { + *p = '\\'; + } + p++; + } +} + +// read directory of a zip archive and add all files in it to active set +void ReadZIPDirectory_t(CTFileName *pfnmZip) +{ + + FILE *f = fopen(*pfnmZip, "rb"); + if (f==NULL) { + ThrowF_t(TRANS("%s: Cannot open file (%s)"), (CTString&)*pfnmZip, strerror(errno)); + } + // start at the end of file, minus expected minimum overhead + fseek(f, 0, SEEK_END); + int iPos = ftell(f)-sizeof(long)-sizeof(EndOfDir)+2; + // do not search more than 128k (should be around 65k at most) + int iMinPos = iPos-128*1024; + if (iMinPos<0) { + iMinPos = 0; + } + + EndOfDir eod; + BOOL bEODFound = FALSE; + // while not at beginning + for(; iPos>iMinPos; iPos--) { + // read signature + fseek(f, iPos, SEEK_SET); + int slSig; + fread(&slSig, sizeof(slSig), 1, f); + // if this is the sig + if (slSig==SIGNATURE_EOD) { + // read directory end + fread(&eod, sizeof(eod), 1, f); + // if multi-volume zip + if (eod.eod_swDiskNo!=0||eod.eod_swDirStartDiskNo!=0 + ||eod.eod_swEntriesInDirOnThisDisk!=eod.eod_swEntriesInDir) { + // fail + ThrowF_t(TRANS("%s: Multi-volume zips are not supported"), (CTString&)*pfnmZip); + } + // check against empty zips + if (eod.eod_swEntriesInDir<=0) { + // fail + ThrowF_t(TRANS("%s: Empty zip"), (CTString&)*pfnmZip); + } + // all ok + bEODFound = TRUE; + break; + } + } + // if eod not found + if (!bEODFound) { + // fail + ThrowF_t(TRANS("%s: Cannot find 'end of central directory'"), (CTString&)*pfnmZip); + } + + // check if the zip is from a mod + BOOL bMod = + pfnmZip->HasPrefix(_fnmApplicationPath+"Mods\\") || + pfnmZip->HasPrefix(_fnmCDPath+"Mods\\"); + + // go to the beginning of the central dir + fseek(f, eod.eod_slDirOffsetInFile, SEEK_SET); + INDEX ctFiles = 0; + // for each file + for (INDEX iFile=0; iFileslMaxFileName) { + ThrowF_t(TRANS("%s: Too long filepath in zip"), (CTString&)*pfnmZip); + } + if (fh.fh_swFileNameLen<=0) { + ThrowF_t(TRANS("%s: Invalid filepath length in zip"), (CTString&)*pfnmZip); + } + fread(strBuffer, fh.fh_swFileNameLen, 1, f); + + // skip eventual comment and extra fields + if (fh.fh_swFileCommentLen+fh.fh_swExtraFieldLen>0) { + fseek(f, fh.fh_swFileCommentLen+fh.fh_swExtraFieldLen, SEEK_CUR); + } + + // if the file is directory + if (strBuffer[strlen(strBuffer)-1]=='/') { + // check size + if (fh.fh_slUncompressedSize!=0 + ||fh.fh_slCompressedSize!=0) { + ThrowF_t(TRANS("%s/%s: Invalid directory"), + (CTString&)*pfnmZip, strBuffer); + } + + // if the file is real file + } else { + ctFiles++; + // convert filename + ConvertSlashes(strBuffer); + // create a new entry + CZipEntry &ze = _azeFiles.Push(); + // remember the file's data + ze.ze_fnm = CTString(strBuffer); + ze.ze_pfnmArchive = pfnmZip; + ze.ze_slCompressedSize = fh.fh_slCompressedSize; + ze.ze_slUncompressedSize = fh.fh_slUncompressedSize; + ze.ze_slDataOffset = fh.fh_slLocalHeaderOffset; + ze.ze_ulCRC = fh.fh_slCRC32; + ze.ze_bMod = bMod; + // check for compressopn + if (fh.fh_swCompressionMethod==0) { + ze.ze_bStored = TRUE; + } else if (fh.fh_swCompressionMethod==8) { + ze.ze_bStored = FALSE; + } else { + ThrowF_t(TRANS("%s/%s: Only 'deflate' compression is supported"), + (CTString&)*ze.ze_pfnmArchive, ze.ze_fnm); + } + } + } + + // if error reading + if (ferror(f)) { + // fail + ThrowF_t(TRANS("%s: Error reading central directory"), (CTString&)*pfnmZip); + } + + // report that file was read + CPrintF(TRANS(" %s: %d files\n"), (CTString&)*pfnmZip, ctFiles++); +} + +// add one zip archive to current active set +void UNZIPAddArchive(const CTFileName &fnm) +{ + // remember its filename + CTFileName &fnmNew = _afnmArchives.Push(); + fnmNew = fnm; +} + +// read directory of an archive +void ReadOneArchiveDir_t(CTFileName &fnm) +{ + // remember current number of files + INDEX ctOrgFiles = _azeFiles.Count(); + + // try to + try { + // read the directory and add all files + ReadZIPDirectory_t(&fnm); + // if failed + } catch (char *) { + // if some files were added + if (ctOrgFiles<_azeFiles.Count()) { + // remove them + if (ctOrgFiles==0) { + _azeFiles.PopAll(); + } else { + _azeFiles.PopUntil(ctOrgFiles-1); + } + } + // cascade the error + throw; + } +} + +int qsort_ArchiveCTFileName_reverse(const void *elem1, const void *elem2 ) +{ + // get the filenames + const CTFileName &fnm1 = *(CTFileName *)elem1; + const CTFileName &fnm2 = *(CTFileName *)elem2; + // find if any is in a mod or on CD + BOOL bMod1 = fnm1.HasPrefix(_fnmApplicationPath+"Mods\\"); + BOOL bCD1 = fnm1.HasPrefix(_fnmCDPath); + BOOL bModCD1 = fnm1.HasPrefix(_fnmCDPath+"Mods\\"); + BOOL bMod2 = fnm2.HasPrefix(_fnmApplicationPath+"Mods\\"); + BOOL bCD2 = fnm2.HasPrefix(_fnmCDPath); + BOOL bModCD2 = fnm2.HasPrefix(_fnmCDPath+"Mods\\"); + + // calculate priorities based on location of gro file + INDEX iPriority1 = 0; + if (bMod1) { + iPriority1 = 3; + } else if (bModCD1) { + iPriority1 = 2; + } else if (bCD1) { + iPriority1 = 0; + } else { + iPriority1 = 1; + } + + INDEX iPriority2 = 0; + if (bMod2) { + iPriority2 = 3; + } else if (bModCD2) { + iPriority2 = 2; + } else if (bCD2) { + iPriority2 = 0; + } else { + iPriority2 = 1; + } + + // find sorting order + if (iPriority1iPriority2) { + return -1; + } else { + return -stricmp(fnm1, fnm2); + } +} +// read directories of all currently added archives, in reverse alphabetical order +void UNZIPReadDirectoriesReverse_t(void) +{ + // if no archives + if (_afnmArchives.Count()==0) { + // do nothing + return; + } + + // sort the archive filenames reversely + qsort(&_afnmArchives[0], _afnmArchives.Count(), sizeof(CTFileName), + qsort_ArchiveCTFileName_reverse); + + CTString strAllErrors = ""; + // for each archive + for (INDEX iArchive=0; iArchive<_afnmArchives.Count(); iArchive++) { + //try to + try { + // read its directory + ReadOneArchiveDir_t(_afnmArchives[iArchive]); + // if failed + } catch (char *strError) { + // remember the error + strAllErrors += strError; + strAllErrors += "\n"; + } + } + + // if there were errors + if (strAllErrors!="") { + // report them + ThrowF_t("%s", strAllErrors); + } +} + +// check if a zip file entry exists +BOOL UNZIPFileExists(const CTFileName &fnm) +{ + // for each file + for(INDEX iFile=0; iFile<_azeFiles.Count(); iFile++) { + // if it is that one + if (_azeFiles[iFile].ze_fnm == fnm) { + return TRUE; + } + } + return FALSE; +} + +// enumeration for all files in all zips +INDEX UNZIPGetFileCount(void) +{ + return _azeFiles.Count(); +} +const CTFileName &UNZIPGetFileAtIndex(INDEX i) +{ + return _azeFiles[i].ze_fnm; +} + +BOOL UNZIPIsFileAtIndexMod(INDEX i) +{ + return _azeFiles[i].ze_bMod; +} + +// get index of a file (-1 for no file) +INDEX UNZIPGetFileIndex(const CTFileName &fnm) +{ + // for each file + for(INDEX iFile=0; iFile<_azeFiles.Count(); iFile++) { + // if it is that one + if (_azeFiles[iFile].ze_fnm == fnm) { + return iFile; + } + } + return -1; +} + +// get info on a zip file entry +void UNZIPGetFileInfo(INDEX iHandle, CTFileName &fnmZip, + SLONG &slOffset, SLONG &slSizeCompressed, SLONG &slSizeUncompressed, + BOOL &bCompressed) +{ + // check handle number + if(iHandle<0 || iHandle>=_azhHandles.Count()) { + ASSERT(FALSE); + return; + } + // get the handle + CZipHandle &zh = _azhHandles[iHandle]; + // check the handle + if (!zh.zh_bOpen) { + ASSERT(FALSE); + return; + } + + // get parameters + fnmZip = *zh.zh_zeEntry.ze_pfnmArchive; + bCompressed = !zh.zh_zeEntry.ze_bStored; + slOffset = zh.zh_zeEntry.ze_slDataOffset; + slSizeCompressed = zh.zh_zeEntry.ze_slCompressedSize; + slSizeUncompressed = zh.zh_zeEntry.ze_slUncompressedSize; +} + +// open a zip file entry for reading +INDEX UNZIPOpen_t(const CTFileName &fnm) +{ + CZipEntry *pze = NULL; + // for each file + for(INDEX iFile=0; iFile<_azeFiles.Count(); iFile++) { + // if it is that one + if (_azeFiles[iFile].ze_fnm == fnm) { + // stop searching + pze = &_azeFiles[iFile]; + break; + } + } + + // if not found + if (pze==NULL) { + // fail + ThrowF_t(TRANS("File not found: %s"), (const CTString&)fnm); + } + + // for each existing handle + BOOL bHandleFound = FALSE; + INDEX iHandle=1; + for (; iHandle<_azhHandles.Count(); iHandle++) { + // if unused + if (!_azhHandles[iHandle].zh_bOpen) { + // use that one + bHandleFound = TRUE; + break; + } + } + // if no free handle found + if (!bHandleFound) { + // create a new one + iHandle = _azhHandles.Count(); + _azhHandles.Push(1); + } + + // get the handle + CZipHandle &zh = _azhHandles[iHandle]; + ASSERT(!zh.zh_bOpen); + zh.zh_zeEntry = *pze; + + // open zip archive for reading + zh.zh_fFile = fopen(*pze->ze_pfnmArchive, "rb"); + // if failed to open it + if (zh.zh_fFile==NULL) { + // clear the handle + zh.Clear(); + // fail + ThrowF_t(TRANS("Cannot open '%s': %s"), (const CTString&)*pze->ze_pfnmArchive, + strerror(errno)); + } + // seek to the local header of the entry + fseek(zh.zh_fFile, zh.zh_zeEntry.ze_slDataOffset, SEEK_SET); + // read the sig + int slSig; + fread(&slSig, sizeof(slSig), 1, zh.zh_fFile); + // if this is not the expected sig + if (slSig!=SIGNATURE_LFH) { + // fail + ThrowF_t(TRANS("%s/%s: Wrong signature for 'local file header'"), + (CTString&)*zh.zh_zeEntry.ze_pfnmArchive, zh.zh_zeEntry.ze_fnm); + } + // read the header + LocalFileHeader lfh; + fread(&lfh, sizeof(lfh), 1, zh.zh_fFile); + // determine exact compressed data position + zh.zh_zeEntry.ze_slDataOffset = + ftell(zh.zh_fFile)+lfh.lfh_swFileNameLen+lfh.lfh_swExtraFieldLen; + // seek there + fseek(zh.zh_fFile, zh.zh_zeEntry.ze_slDataOffset, SEEK_SET); + + // allocate buffers + zh.zh_pubBufIn = (UBYTE*)AllocMemory(BUF_SIZE); + + // initialize zlib stream + CTSingleLock slZip(&zip_csLock, TRUE); + zh.zh_zstream.next_out = NULL; + zh.zh_zstream.avail_out = 0; + zh.zh_zstream.next_in = NULL; + zh.zh_zstream.avail_in = 0; + zh.zh_zstream.zalloc = (alloc_func)Z_NULL; + zh.zh_zstream.zfree = (free_func)Z_NULL; + int err = inflateInit2(&zh.zh_zstream, -15); // 32k windows + // if failed + if (err!=Z_OK) { + // clean up what is possible + FreeMemory(zh.zh_pubBufIn ); + zh.zh_pubBufIn = NULL; + fclose(zh.zh_fFile); + zh.zh_fFile = NULL; + // throw error + zh.ThrowZLIBError_t(err, TRANS("Cannot init inflation")); + } + + // return the handle successfully + zh.zh_bOpen = TRUE; + return iHandle; +} + +// get uncompressed size of a file +SLONG UNZIPGetSize(INDEX iHandle) +{ + // check handle number + if(iHandle<0 || iHandle>=_azhHandles.Count()) { + ASSERT(FALSE); + return 0; + } + // get the handle + CZipHandle &zh = _azhHandles[iHandle]; + // check the handle + if (!zh.zh_bOpen) { + ASSERT(FALSE); + return 0; + } + + return zh.zh_zeEntry.ze_slUncompressedSize; +} + +// get CRC of a file +ULONG UNZIPGetCRC(INDEX iHandle) +{ + // check handle number + if(iHandle<0 || iHandle>=_azhHandles.Count()) { + ASSERT(FALSE); + return 0; + } + // get the handle + CZipHandle &zh = _azhHandles[iHandle]; + // check the handle + if (!zh.zh_bOpen) { + ASSERT(FALSE); + return 0; + } + + return zh.zh_zeEntry.ze_ulCRC; +} + +// read a block from zip file +void UNZIPReadBlock_t(INDEX iHandle, UBYTE *pub, SLONG slStart, SLONG slLen) +{ + // check handle number + if(iHandle<0 || iHandle>=_azhHandles.Count()) { + ASSERT(FALSE); + return; + } + // get the handle + CZipHandle &zh = _azhHandles[iHandle]; + // check the handle + if (!zh.zh_bOpen) { + ASSERT(FALSE); + return; + } + + // if behind the end of file + if (slStart>=zh.zh_zeEntry.ze_slUncompressedSize) { + // do nothing + return; + } + + // clamp length to end of the entry data + slLen = Min(slLen, zh.zh_zeEntry.ze_slUncompressedSize-slStart); + + // if not compressed + if (zh.zh_zeEntry.ze_bStored) { + // just read from file + fseek(zh.zh_fFile, zh.zh_zeEntry.ze_slDataOffset+slStart, SEEK_SET); + fread(pub, 1, slLen, zh.zh_fFile); + return; + } + + CTSingleLock slZip(&zip_csLock, TRUE); + + // if behind the current pointer + if (slStartzh.zh_zstream.total_out) { + // if zlib has no more input + while(zh.zh_zstream.avail_in==0) { + // read more to it + SLONG slRead = fread(zh.zh_pubBufIn, 1, BUF_SIZE, zh.zh_fFile); + if (slRead<=0) { + return; // !!!! + } + // tell zlib that there is more to read + zh.zh_zstream.next_in = zh.zh_pubBufIn; + zh.zh_zstream.avail_in = slRead; + } + // read dummy data from the output + #define DUMMY_SIZE 256 + UBYTE aubDummy[DUMMY_SIZE]; + // decode to output + zh.zh_zstream.avail_out = Min(SLONG(slStart-zh.zh_zstream.total_out), SLONG(DUMMY_SIZE)); + zh.zh_zstream.next_out = aubDummy; + int ierr = inflate(&zh.zh_zstream, Z_SYNC_FLUSH); + if (ierr!=Z_OK && ierr!=Z_STREAM_END) { + zh.ThrowZLIBError_t(ierr, TRANS("Error seeking in zip")); + } + } + + // if not streaming continuously + if (slStart!=zh.zh_zstream.total_out) { + // this should not happen + ASSERT(FALSE); + // read empty + memset(pub, 0, slLen); + return; + } + + // set zlib for writing to the block + zh.zh_zstream.avail_out = slLen; + zh.zh_zstream.next_out = pub; + + // while there is something to write to given block + while (zh.zh_zstream.avail_out>0) { + // if zlib has no more input + while(zh.zh_zstream.avail_in==0) { + // read more to it + SLONG slRead = fread(zh.zh_pubBufIn, 1, BUF_SIZE, zh.zh_fFile); + if (slRead<=0) { + return; // !!!! + } + // tell zlib that there is more to read + zh.zh_zstream.next_in = zh.zh_pubBufIn; + zh.zh_zstream.avail_in = slRead; + } + // decode to output + int ierr = inflate(&zh.zh_zstream, Z_SYNC_FLUSH); + if (ierr!=Z_OK && ierr!=Z_STREAM_END) { + zh.ThrowZLIBError_t(ierr, TRANS("Error reading from zip")); + } + } +} + +// close a zip file entry +void UNZIPClose(INDEX iHandle) +{ + // check handle number + if(iHandle<0 || iHandle>=_azhHandles.Count()) { + ASSERT(FALSE); + return; + } + // get the handle + CZipHandle &zh = _azhHandles[iHandle]; + // check the handle + if (!zh.zh_bOpen) { + ASSERT(FALSE); + return; + } + // clear it + zh.Clear(); +} diff --git a/Sources/Engine/Base/Unzip.h b/Sources/Engine/Base/Unzip.h new file mode 100644 index 0000000..7d91ad8 --- /dev/null +++ b/Sources/Engine/Base/Unzip.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_UNZIP_H +#define SE_INCL_UNZIP_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// add one zip archive to current active set +void UNZIPAddArchive(const CTFileName &fnm); +// read directories of all currently added archives, in reverse alphabetical order +void UNZIPReadDirectoriesReverse_t(void); +// check if a zip file entry exists +BOOL UNZIPFileExists(const CTFileName &fnm); +// open a zip file entry for reading +INDEX UNZIPOpen_t(const CTFileName &fnm); +// get uncompressed size of a file +SLONG UNZIPGetSize(INDEX iHandle); +// get CRC of a file +ULONG UNZIPGetCRC(INDEX iHandle); +// read a block from zip file +void UNZIPReadBlock_t(INDEX iHandle, UBYTE *pub, SLONG slStart, SLONG slLen); +// close a zip file entry +void UNZIPClose(INDEX iHandle); +// get info on a zip file entry +void UNZIPGetFileInfo(INDEX iHandle, CTFileName &fnmZip, + SLONG &slOffset, SLONG &slSizeCompressed, SLONG &slSizeUncompressed, + BOOL &bCompressed); +// enumeration for all files in all zips +INDEX UNZIPGetFileCount(void); +const CTFileName &UNZIPGetFileAtIndex(INDEX i); + +// get index of a file (-1 for no file) +INDEX UNZIPGetFileIndex(const CTFileName &fnm); +// check if a file is from a mod's zip +BOOL UNZIPIsFileAtIndexMod(INDEX i); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/Updateable.cpp b/Sources/Engine/Base/Updateable.cpp new file mode 100644 index 0000000..6795c89 --- /dev/null +++ b/Sources/Engine/Base/Updateable.cpp @@ -0,0 +1,67 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include + +/* + * Constructor. + */ +CUpdateable::CUpdateable(void) +{ + ud_LastUpdateTime = TIME(-1); +} + +/* + * Mark that the object has been updated. + */ +void CUpdateable::MarkUpdated(void) +{ + ud_LastUpdateTime = _pTimer->CurrentTick(); +} + +/* + * Get time when last updated. + */ +TIME CUpdateable::LastUpdateTime(void) const +{ + return ud_LastUpdateTime; +} + +/* Mark that the object has become invalid in spite of its time stamp. */ +void CUpdateable::Invalidate(void) +{ + ud_LastUpdateTime = TIME(-1); +} + +/* + * Constructor. + */ +CUpdateableRT::CUpdateableRT(void) +{ + ud_LastUpdateTime = TIME(-1); +} + +/* + * Mark that the object has been updated. + */ +void CUpdateableRT::MarkUpdated(void) +{ + ud_LastUpdateTime = _pTimer->GetRealTimeTick(); +} + +/* + * Get time when last updated. + */ +TIME CUpdateableRT::LastUpdateTime(void) const +{ + return ud_LastUpdateTime; +} + +/* Mark that the object has become invalid in spite of its time stamp. */ +void CUpdateableRT::Invalidate(void) +{ + ud_LastUpdateTime = TIME(-1); +} diff --git a/Sources/Engine/Base/Updateable.h b/Sources/Engine/Base/Updateable.h new file mode 100644 index 0000000..90b7601 --- /dev/null +++ b/Sources/Engine/Base/Updateable.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_UPDATEABLE_H +#define SE_INCL_UPDATEABLE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* + * Object that can be updated to reflect changes in some changeable object(s). + */ +class ENGINE_API CUpdateable { +private: + TIME ud_LastUpdateTime; // last time this object has been updated +public: + /* Constructor. */ + CUpdateable(void); + /* Get time when last updated. */ + TIME LastUpdateTime(void) const ; + /* Mark that the object has been updated. */ + void MarkUpdated(void); + /* Mark that the object has become invalid in spite of its time stamp. */ + void Invalidate(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/UpdateableRT.h b/Sources/Engine/Base/UpdateableRT.h new file mode 100644 index 0000000..af75477 --- /dev/null +++ b/Sources/Engine/Base/UpdateableRT.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_UPDATEABLERT_H +#define SE_INCL_UPDATEABLERT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* + * Object that can be updated to reflect changes in some changeable object(s). + */ +class ENGINE_API CUpdateableRT { +private: + TIME ud_LastUpdateTime; // last time this object has been updated +public: + /* Constructor. */ + CUpdateableRT(void); + /* Get time when last updated. */ + TIME LastUpdateTime(void) const ; + /* Mark that the object has been updated. */ + void MarkUpdated(void); + /* Mark that the object has become invalid in spite of its time stamp. */ + void Invalidate(void); +}; + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Base/bison.simple b/Sources/Engine/Base/bison.simple new file mode 100644 index 0000000..bbdaa97 --- /dev/null +++ b/Sources/Engine/Base/bison.simple @@ -0,0 +1,687 @@ +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#undef YYERROR_VERBOSE +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 192 "bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +int +yyparse(YYPARSE_PARAM) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + +$ /* the action file gets copied in in place of this dollarsign */ +#line 487 "bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} diff --git a/Sources/Engine/Base/parser.h b/Sources/Engine/Base/parser.h new file mode 100644 index 0000000..63fb21c --- /dev/null +++ b/Sources/Engine/Base/parser.h @@ -0,0 +1,42 @@ +typedef union { + value val; // for constants and expressions + arguments arg; // for function input arguments + ULONG ulFlags; // for declaration qualifiers + INDEX istType; // for types + CShellSymbol *pssSymbol; // for symbols + struct LValue lvLValue; + INDEX (*pPreFunc)(INDEX); // pre-set function for a variable + void (*pPostFunc)(INDEX); // post-set function for a variable +} YYSTYPE; +#define c_float 258 +#define c_int 259 +#define c_string 260 +#define c_char 261 +#define identifier 262 +#define k_INDEX 263 +#define k_FLOAT 264 +#define k_CTString 265 +#define k_void 266 +#define k_const 267 +#define k_user 268 +#define k_persistent 269 +#define k_extern 270 +#define k_pre 271 +#define k_post 272 +#define k_help 273 +#define k_if 274 +#define k_else 275 +#define k_else_if 276 +#define SHL 277 +#define SHR 278 +#define EQ 279 +#define NEQ 280 +#define GEQ 281 +#define LEQ 282 +#define LOGAND 283 +#define LOGOR 284 +#define block_beg 285 +#define block_end 286 +#define TYPECAST 287 +#define SIGN 288 + diff --git a/Sources/Engine/Brushes/Brush.cpp b/Sources/Engine/Brushes/Brush.cpp new file mode 100644 index 0000000..7c60c31 --- /dev/null +++ b/Sources/Engine/Brushes/Brush.cpp @@ -0,0 +1,270 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// constructor +CBrush3D::CBrush3D(void) +{ + br_penEntity = NULL; + br_pfsFieldSettings = NULL; + br_ulFlags = 0; +} + +// destructor +CBrush3D::~CBrush3D(void) +{ +} + +/* Delete a brush mip with given factor. */ +void CBrush3D::DeleteBrushMip(CBrushMip *pbmToDelete) +{ + ASSERT(pbmToDelete!=NULL); + ASSERT(pbmToDelete->bm_pbrBrush == this); + // if there is only one brush mip + if (br_lhBrushMips.Count()<=1) { + // do nothing; + return; + } + // remove it from list + pbmToDelete->bm_lnInBrush.Remove(); + // destroy it + delete pbmToDelete; +} + +/* Create a new brush mip. */ +CBrushMip *CBrush3D::NewBrushMipAfter(CBrushMip *pbmOld, BOOL bCopy) +{ + ASSERT(pbmOld!=NULL); + ASSERT(pbmOld->bm_pbrBrush == this); + + // create one brush mip + CBrushMip *pbmNew = new CBrushMip; + pbmNew->bm_pbrBrush = this; + // add it to the brush + pbmOld->bm_lnInBrush.AddAfter(pbmNew->bm_lnInBrush); + // copy the original to it + if (bCopy) { + pbmNew->Copy(*pbmOld, 1.0f, FALSE); + } + // respread the mips after old one + pbmOld->SpreadFurtherMips(); + + return pbmNew; +} +CBrushMip *CBrush3D::NewBrushMipBefore(CBrushMip *pbmOld, BOOL bCopy) +{ + ASSERT(pbmOld!=NULL); + ASSERT(pbmOld->bm_pbrBrush == this); + + // create one brush mip + CBrushMip *pbmNew = new CBrushMip; + pbmNew->bm_pbrBrush = this; + // add it to the brush + pbmOld->bm_lnInBrush.AddBefore(pbmNew->bm_lnInBrush); + // copy the original to it + if (bCopy) { + // copy the original to it + pbmNew->Copy(*pbmOld, 1.0f, FALSE); + } + + // get factor of mip before the new one + FLOAT fFactorBefore = 0.0f; + CBrushMip *pbmBefore = pbmNew->GetPrev(); + if (pbmBefore!=NULL) { + fFactorBefore = pbmBefore->bm_fMaxDistance; + } + + // calculate factor for new one to be between those two + pbmNew->bm_fMaxDistance = (fFactorBefore+pbmOld->bm_fMaxDistance)/2.0f; + + return pbmNew; +} + +// make 'for' construct for walking a list reversely +#define FOREACHINLIST_R(baseclass, member, head, iter) \ + for ( LISTITER(baseclass, member) iter(head.IterationTail()); \ + !iter->member.IsHeadMarker(); iter.MoveToPrev() ) + +/* + * Get a brush mip for given mip-factor. + */ +CBrushMip *CBrush3D::GetBrushMipByDistance(FLOAT fMipDistance) +{ + // initially there is no brush mip + CBrushMip *pbmLastGood=NULL; + // for all brush mips in brush reversely + FOREACHINLIST_R(CBrushMip, bm_lnInBrush, br_lhBrushMips, itbm) { + CBrushMip &bm = *itbm; + // if this mip cannot be of given factor + if (bm.bm_fMaxDistancebm_lnInBrush); + pbmBrushMip->bm_pbrBrush = this; + + // copy the brush mip from original + pbmBrushMip->Copy(*itbmOther, fStretch, bMirrorX); + } +} + +/* + * Prepare a projection from brush space to absolute space. + */ +void CBrush3D::PrepareRelativeToAbsoluteProjection( + CSimpleProjection3D_DOUBLE &prRelativeToAbsolute) +{ + // brush that does not have an entity is initialized at origin + if(br_penEntity==NULL) { + prRelativeToAbsolute.ObjectPlacementL().pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f); + prRelativeToAbsolute.ObjectPlacementL().pl_OrientationAngle = ANGLE3D(0, 0, 0); + } else { + prRelativeToAbsolute.ObjectPlacementL() = br_penEntity->en_plPlacement; + } + prRelativeToAbsolute.ViewerPlacementL().pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f); + prRelativeToAbsolute.ViewerPlacementL().pl_OrientationAngle = ANGLE3D(0, 0, 0); + prRelativeToAbsolute.Prepare(); +} + +/* + * Calculate bounding boxes in all brush mips. + */ +void CBrush3D::CalculateBoundingBoxes(void) +{ + CalculateBoundingBoxesForOneMip(NULL); +} +void CBrush3D::CalculateBoundingBoxesForOneMip(CBrushMip *pbmOnly) // for only one mip +{ + // set FPU to double precision + CSetFPUPrecision FPUPrecision(FPT_53BIT); + + // prepare a projection from brush space to absolute space + CSimpleProjection3D_DOUBLE prBrushToAbsolute; + PrepareRelativeToAbsoluteProjection(prBrushToAbsolute); + // for all brush mips + FOREACHINLIST(CBrushMip, bm_lnInBrush, br_lhBrushMips, itbm) { + CBrushMip *pbm = itbm; + if (pbmOnly==NULL || pbm==pbmOnly) { + // calculate its boxes + pbm->CalculateBoundingBoxes(prBrushToAbsolute); + } + } + // if this brush is zoning + if (br_penEntity!=NULL && (br_penEntity->en_ulFlags&ENF_ZONING)) { + // portal links must be updated also + extern BOOL _bPortalSectorLinksPreLoaded; + extern BOOL _bDontDiscardLinks; + br_penEntity->en_pwoWorld->wo_bPortalLinksUpToDate = _bPortalSectorLinksPreLoaded||_bDontDiscardLinks; + } + + br_penEntity->UpdateSpatialRange(); +} + +// switch from zoning to non-zoning +void CBrush3D::SwitchToNonZoning(void) +{ + CalculateBoundingBoxes(); + + // for all brush mips + FOREACHINLIST(CBrushMip, bm_lnInBrush, br_lhBrushMips, itbm) { + // for all sectors in the mip + {FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // unset spatial clasification + itbsc->bsc_rsEntities.Clear(); + }} + } +} + +// switch from non-zoning to zoning +void CBrush3D::SwitchToZoning(void) +{ + CalculateBoundingBoxes(); + + // for all brush mips + FOREACHINLIST(CBrushMip, bm_lnInBrush, br_lhBrushMips, itbm) { + // for all sectors in the mip + {FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // find entities in sector + itbsc->FindEntitiesInSector(); + }} + } +} diff --git a/Sources/Engine/Brushes/Brush.h b/Sources/Engine/Brushes/Brush.h new file mode 100644 index 0000000..252e658 --- /dev/null +++ b/Sources/Engine/Brushes/Brush.h @@ -0,0 +1,779 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_BRUSH_H +#define SE_INCL_BRUSH_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// a vertex in brush +#define BVXF_DRAWNINWIREFRAME (1L<<0) // vertex is already drawn in wireframe +#define BVXF_SELECTED (1L<<1) // vertex is selected +class ENGINE_API CBrushVertex { +public: + class CWorkingVertex *bvx_pwvxWorking; // used for rendering and ray casting + FLOAT3D bvx_vAbsolute; + FLOAT3D bvx_vRelative; // relative coordinates used for collision + DOUBLE3D bvx_vdPreciseRelative; // precise relative coordinates used for editing + DOUBLE3D *bvx_pvdPreciseAbsolute; // precise vertex coordinates in absolute space + ULONG bvx_ulFlags; // flags + CBrushSector *bvx_pbscSector; // back-pointer to sector + + /* Default constructor. */ + inline CBrushVertex(void) : bvx_pwvxWorking(NULL), bvx_ulFlags(0) {}; + /* Clear the object. */ + inline void Clear(void) {}; + + // vertices may be selected + IMPLEMENT_SELECTING(bvx_ulFlags) + + // set new absolute position for the vertex + void SetAbsolutePosition(const DOUBLE3D &vAbsolute); + + // get amount of memory used by this object + inline SLONG GetUsedMemory(void) { return sizeof(CBrushVertex); }; +}; + + +// selection of brush vertices +typedef CSelection CBrushVertexSelection; + +// a plane in brush +class ENGINE_API CBrushPlane { +public: + class CWorkingPlane *bpl_pwplWorking; // use for rendering and ray casting + FLOATplane3D bpl_plAbsolute; + FLOATplane3D bpl_plRelative; // relative coordinates used for collision + DOUBLEplane3D *bpl_ppldPreciseAbsolute; // precise relative plane coordinates in absolute space + DOUBLEplane3D bpl_pldPreciseRelative; // precise coordinates used for editing + INDEX bpl_iPlaneMajorAxis1; // major axes of the plane in apsolute space + INDEX bpl_iPlaneMajorAxis2; + + /* Default constructor. */ + inline CBrushPlane(void) : bpl_pwplWorking(NULL) {}; + /* Clear the object. */ + inline void Clear(void) {}; + + // get amount of memory used by this object + inline SLONG GetUsedMemory(void) { return sizeof(CBrushPlane); }; +}; + + +// an edge in brush +class ENGINE_API CBrushEdge { +public: + CBrushVertex *bed_pbvxVertex0; // start vertex + CBrushVertex *bed_pbvxVertex1; // end vertex + CWorkingEdge *bed_pwedWorking; // pointer to screen edge if active in rendering + + /* Default constructor. */ + inline CBrushEdge(void) : bed_pwedWorking(NULL) {}; + /* Constructor with two vertices. */ + inline CBrushEdge(CBrushVertex *pbvx0, CBrushVertex *pbvx1) + : bed_pwedWorking(NULL), bed_pbvxVertex0(pbvx0), bed_pbvxVertex1(pbvx1) {}; + /* Clear the object. */ + inline void Clear(void) {}; + /* Test if this edge touches another one. */ + BOOL TouchesInSameSector(CBrushEdge &bedOther); + BOOL TouchesInAnySector(CBrushEdge &bedOther); + + // get amount of memory used by this object + inline SLONG GetUsedMemory(void) { return sizeof(CBrushEdge); }; +}; + +// a reference to edge used in brush polygon +class ENGINE_API CBrushPolygonEdge { +public: + CBrushEdge *bpe_pbedEdge; // pointer to the edge + BOOL bpe_bReverse; // true if the vertex0 and vertex1 must be swapped + + /* Clear the object. */ + inline void Clear(void) {}; + /* Get coordinates of the end vertices. */ + inline void GetVertices(CBrushVertex *&pbvx0, CBrushVertex *&pbvx1) { + if (bpe_bReverse) { + pbvx0 = bpe_pbedEdge->bed_pbvxVertex1; + pbvx1 = bpe_pbedEdge->bed_pbvxVertex0; + } else { + pbvx0 = bpe_pbedEdge->bed_pbvxVertex0; + pbvx1 = bpe_pbedEdge->bed_pbvxVertex1; + } + } + inline void GetVertexCoordinatesAbsolute(FLOAT3D &v0, FLOAT3D &v1) { + if (bpe_bReverse) { + v0 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + v1 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + } else { + v0 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + v1 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + } + }; + inline void GetVertexCoordinatesRelative(FLOAT3D &v0, FLOAT3D &v1) { + if (bpe_bReverse) { + v0 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vRelative; + v1 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vRelative; + } else { + v0 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vRelative; + v1 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vRelative; + } + }; + inline void GetVertexCoordinatesPreciseRelative(DOUBLE3D &v0, DOUBLE3D &v1) { + if (bpe_bReverse) { + v0 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vdPreciseRelative; + v1 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vdPreciseRelative; + } else { + v0 = bpe_pbedEdge->bed_pbvxVertex0->bvx_vdPreciseRelative; + v1 = bpe_pbedEdge->bed_pbvxVertex1->bvx_vdPreciseRelative; + } + }; + inline void GetVertexCoordinatesPreciseAbsolute(DOUBLE3D &v0, DOUBLE3D &v1) { + if (bpe_bReverse) { + v0 = *bpe_pbedEdge->bed_pbvxVertex1->bvx_pvdPreciseAbsolute; + v1 = *bpe_pbedEdge->bed_pbvxVertex0->bvx_pvdPreciseAbsolute; + } else { + v0 = *bpe_pbedEdge->bed_pbvxVertex0->bvx_pvdPreciseAbsolute; + v1 = *bpe_pbedEdge->bed_pbvxVertex1->bvx_pvdPreciseAbsolute; + } + }; +}; + + +// one layer on brush shadow map (cross link between brush shadow map and light source) +#define BSLF_CALCULATED (1L<<0) +#define BSLF_RECTANGLE (1L<<1) // new version of layer with only influenced rectangle +#define BSLF_ALLDARK (1L<<2) // polygon is not lighted by the light at all +#define BSLF_ALLLIGHT (1L<<3) // whole polygon is lighted by the light (there are no shadows) +class ENGINE_API CBrushShadowLayer { +public: +// implementation: + ULONG bsl_ulFlags; // flags + CListNode bsl_lnInShadowMap; // node in list of all layers of a shadow map + CListNode bsl_lnInLightSource; // node in list of all layers of a light source + class CBrushShadowMap *bsl_pbsmShadowMap; // the shadow map + class CLightSource *bsl_plsLightSource; // the light source + PIX bsl_pixMinU; // rectangle where the light influences the polygon + PIX bsl_pixMinV; + PIX bsl_pixSizeU; + PIX bsl_pixSizeV; + SLONG bsl_slSizeInPixels; // size of bit mask in pixels (with all mip-maps) + UBYTE *bsl_pubLayer; // bit mask set where the polygon is lighted + COLOR bsl_colLastAnim; // last animating color cached + +// interface: + CBrushShadowLayer(); + ~CBrushShadowLayer(void); + // discard shadows but keep the layer + void DiscardShadows(void); + // get shadow/light percentage at given coordinates in shadow layer + FLOAT GetLightStrength(PIX pixU, PIX pixV, FLOAT fLt, FLOAT fUp); + + // get amount of memory used by this object + SLONG GetUsedMemory(void); +}; + + +class ENGINE_API CBrushShadowMap : public CShadowMap { +public: +// implementation: + // for linking in list of all shadow maps that need calculation + CListNode bsm_lnInUncalculatedShadowMaps; + + CListHead bsm_lhLayers; // list of all layers of this shadow map + UBYTE *bsm_pubPolygonMask; // bit packed polygon mask + + // get pointer to embedding brush polygon + inline CBrushPolygon *GetBrushPolygon(void); + + // overrides from CShadowMap: + // mix all layers into cached shadow map + virtual void MixLayers(INDEX iFirstMip, INDEX iLastMip, BOOL bDynamic=FALSE); // iFirstMip &bspo); + void CreateBSPPolygonNonPrecise(BSPPolygon &bspo); + /* Create shadow map for the polygon. */ + void MakeShadowMap(CWorld *pwoWorld, BOOL bDoDirectionalLights); + /* Initialize shadow map for the polygon. */ + void InitializeShadowMap(void); + // discard all cached shading info for models + void DiscardShadingInfos(void); + // move edges from another polygon into this one + void MovePolygonEdges(CBrushPolygon &bpoSource); + /* Test if this polygon touches another one. */ + BOOL TouchesInSameSector(CBrushPolygon &bpoOther); + BOOL TouchesInAnySector(CBrushPolygon &bpoOther); + // make triangular representation of the polygon + void Triangulate(void); +public: +// interface: + CBrushPlane *bpo_pbplPlane; // plane of this polygon + CStaticArray bpo_abpePolygonEdges; // edges in this polygon + CStaticArray bpo_apbvxTriangleVertices; // triangle vertices + CStaticArray bpo_aiTriangleElements; // element indices inside vertex arrays + CBrushPolygonTexture bpo_abptTextures[3]; // texture on this polygon + COLOR bpo_colColor; // color of this polygon + ULONG bpo_ulFlags; // flags + COLOR bpo_colShadow; // color of shadow on this polygon + CBrushShadowMap bpo_smShadowMap; // shadow map of this polygon + CMappingDefinition bpo_mdShadow; // mapping of shadow on polygon + CBrushPolygonProperties bpo_bppProperties; // additional properties + class CScreenPolygon *bpo_pspoScreenPolygon; // used in rendering + + FLOATaabbox3D bpo_boxBoundingBox; // bounding box + CBrushSector *bpo_pbscSector; // sector of this polygon + + CRelationSrc bpo_rsOtherSideSectors; // relation to sectors on other side of portal + CListHead bpo_lhShadingInfos; // for linking shading infos of entities + INDEX bpo_iInWorld; // index of the polygon in entire world + + /* Default constructor. */ + inline CBrushPolygon(void) : bpo_ulFlags(0) {}; + /* Clear the object. */ + void Clear(void); + /* Destructor. */ + inline ~CBrushPolygon(void) { Clear(); }; + CBrushPolygon &CopyPolygon(CBrushPolygon &bp); + /* Copy polygon within same sector. */ + void CopyFromSameSector(CBrushPolygon &bpoOriginal); + + /* Copy polygon properties */ + CBrushPolygon &CopyProperties(CBrushPolygon &bpoOther, BOOL bCopyMapping = TRUE); + /* Copy polygon properties without texture */ + CBrushPolygon &CopyPropertiesWithoutTexture(CBrushPolygon &bpoOther); + /* Copy polygon's textures */ + CBrushPolygon &CopyTextures(CBrushPolygon &bpoOther); + + // polygons may be selected + IMPLEMENT_SELECTING(bpo_ulFlags) + + /* Select group of adjacent polygons with same color. */ + void SelectSimilarByColor(CSelection &selbpoSimilar); + /* Select group of adjacent polygons with same texture. */ + void SelectSimilarByTexture(CSelection &selbpoSimilar, INDEX iTexture); + /* Select all polygons in sector with same texture. */ + void SelectByTextureInSector(CSelection &selbpoSimilar, INDEX iTexture); + /* Select all polygons in sector with same color. */ + void SelectByColorInSector(CSelection &selbpoSimilar); + + /* Discard shadows on the polygon. */ + void DiscardShadows(void); + + // find minimum distance of a given point from the polygon edges + FLOAT GetDistanceFromEdges(const FLOAT3D &v); + + // get amount of memory used by this object + SLONG GetUsedMemory(void); +}; + + +// get pointer to embedding brush polygon +inline CBrushPolygon *CBrushShadowMap::GetBrushPolygon(void) { + return (CBrushPolygon *) ((UBYTE*)this-offsetof(CBrushPolygon, bpo_smShadowMap)); +} + + +// selection of brush polygons +typedef CSelection CBrushPolygonSelection; +// selection of brush polygons used for CSG +typedef CSelection CBrushPolygonSelectionForCSG; + +// sector flags +#define BSCF_SELECTED (1L<<0) // set if the sector is selected +#define BSCF_HIDDEN (1L<<1) // set if the sector is hidden (for editing) +#define BSCF_SELECTEDFORCSG (1L<<2) // set if the sector is selected for CSG +#define BSCF_OPENSECTOR (1L<<3) // set if the sector polygons are facing outwards +#define BSCF_NEARTESTED (1L<<4) // already tested for near polygon +#define BSCF_INVISIBLE (1L<<5) // active, but not visible +#define BSCF_RAYTESTED (1L<<6) // already tested by ray +#define BSCF_NEEDSCLIPPING (1L<<7) // set if its polygons needs clipping +#define BSCB_CONTENTTYPE 24 // upper 8 bits are used for sector content type +#define BSCB_FORCETYPE 16 // next 8 bits are used for sector gravity type +#define BSCB_FOGTYPE 12 // 4 bits for fog +#define BSCB_HAZETYPE 8 // 4 bits for haze + +#define BSCB2_ENVIRONMENTTYPE 0 // 8 bits for environment sound effects (EAX and similar) +#define BSCF2_VISIBILITYINCLUDE (1<<8) // toggle include/exclude for visibility (exclude is default) + +// vis flags +#define VISM_INCLUDEEXCLUDE (0x0000FFFF) // for visibility include/exclude +#define VISM_DONTCLASSIFY (0xFFFF0000) // to disable classification in certain sectors + +// NOTE on how visibility tweaks are implemented +// - low 16 bits determine visibility from current sector +// if BSCF2_VISIBILITYINCLUDE is on, entity is visible from sector only if EntityVisTweaks&SectorVisFlags&VISM_INCLUDEEXCLUDE +// if BSCF2_VISIBILITYINCLUDE is off, entity is visible from sector only if !(EntityVisTweaks&SectorVisFlags&VISM_INCLUDEEXCLUDE) +// - high 16 bits limit entity classification to sectors +// if EntityVisTweaks&SectorVisFlags&VISM_DONTCLASSIFY, entity is treated as if not classified to that sector + +// temporary flags +#define BSCTF_PRELOADEDBSP (1L<<0) // bsp is loaded, no need to calculate it +#define BSCTF_PRELOADEDLINKS (1L<<1) // portallinks are loaded, no need to calculate them + +// a sector in brush +class ENGINE_API CBrushSector { +public: +// implementation: + /* Fill an object sector from a sector in brush. */ + void ToObjectSector(CObjectSector &osc); + /* Fill a brush sector from a sector in object3d. */ + void FromObjectSector_t(CObjectSector &osc); // throw char * + // recalculate planes for polygons from their vertices + void MakePlanesFromVertices(); + // update changed sector's data after dragging vertices or importing + void UpdateSector(void); + + /* Calculate volume of the sector. */ + DOUBLE CalculateVolume(void); + // make triangular representation of the polygons in the sector + void Triangulate(void); +public: +// implementation: + CStaticArray bsc_abvxVertices; // vertices + CStaticArray bsc_abedEdges; // edges + CStaticArray bsc_abplPlanes; // planes + CStaticArray bsc_abpoPolygons; // polygons + + CStaticArray bsc_awvxVertices; // working vertices + CStaticArray bsc_awplPlanes; // working planes + CStaticArray bsc_awedEdges; // working edges + + class CBrushMip *bsc_pbmBrushMip; // pointer to brush mip of this sector + COLOR bsc_colColor; // color of this sector + COLOR bsc_colAmbient; // ambient light for that sector + ULONG bsc_ulFlags; // flags + ULONG bsc_ulFlags2; // second set of flags + ULONG bsc_ulTempFlags; // flags that are not saved + ULONG bsc_ulVisFlags; // special visibility flags + FLOATaabbox3D bsc_boxBoundingBox; // bounding box in absolute space + FLOATaabbox3D bsc_boxRelative; // bounding box in relative space + CListNode bsc_lnInActiveSectors; // node in sectors active in some operation (e.g. rendering) + DOUBLEbsptree3D &bsc_bspBSPTree; // the local bsp tree of the sector + CRelationDst bsc_rdOtherSidePortals; // relation to portals pointing to this sector + CRelationSrc bsc_rsEntities; // relation to all entities in this sector + CTString bsc_strName; // sector name + INDEX bsc_iInWorld; // index of the sector in entire world + CRelationLnk *bsc_prlLink; // for optimized link removal + INDEX bsc_ispo0; // screen polygons used in rendering + INDEX bsc_ctspo; + INDEX bsc_ivvx0; // view vertices used in rendering + + /* Default constructor. */ + CBrushSector(void); + ~CBrushSector(void); + DECLARE_NOCOPYING(CBrushSector); + + /* Clear the object. */ + void Clear(void); + /* Lock all arrays. */ + void LockAll(void); + /* Unlock all arrays. */ + void UnlockAll(void); + + /* Update sector after moving vertices */ + void UpdateVertexChanges(void); + // triangularize given polygon + void TriangularizePolygon( CBrushPolygon *pbpo); + /* Triangularize polygons contining vertices from selection */ + void TriangularizeForVertices( CBrushVertexSelection &selVertex); + // Triangularize marked polygons + void TriangularizeMarkedPolygons( void); + // Subdivide given triangles + void SubdivideTriangles( CBrushPolygonSelection &selPolygon); + // Insert given vertex into triangle + void InsertVertexIntoTriangle( CBrushPolygonSelection &selPolygon, FLOAT3D vVertex); + // Retriple two triangles given trough selection + BOOL IsReTripleAvailable( CBrushPolygonSelection &selPolygon); + void ReTriple( CBrushPolygonSelection &selPolygon); + + /* Calculate bounding boxes of all polygons. */ + void CalculateBoundingBoxes(CSimpleProjection3D_DOUBLE &prRelativeToAbsolute); + + // sectors may be selected + IMPLEMENT_SELECTING(bsc_ulFlags) + + // overrides from CSerial + /* Read from stream. */ + void Read_t( CTStream *istrFile); // throw char * + /* Write to stream. */ + void Write_t( CTStream *ostrFile); // throw char * + + /* Uncache lightmaps on all shadows on the sector. */ + void UncacheLightMaps(void); + /* Find and remember all entities in this sector. */ + void FindEntitiesInSector(void); + + /* Get/set properties. */ + inline INDEX GetContentType(void) { + return (bsc_ulFlags>>BSCB_CONTENTTYPE)&0xff; + } + void SetContentType(INDEX iNewContent) + { + iNewContent&=0xff; + bsc_ulFlags &= ~(0xff<>BSCB_FORCETYPE)&0xff; + } + void SetForceType(INDEX iNewForce) { + iNewForce&=0xff; + bsc_ulFlags &= ~(0xff<>BSCB_FOGTYPE)&0xf; + } + void SetFogType(INDEX iNewForce) { + iNewForce&=0xf; + bsc_ulFlags &= ~(0xf<>BSCB_HAZETYPE)&0xf; + } + void SetHazeType(INDEX iNewForce) { + iNewForce&=0xf; + bsc_ulFlags &= ~(0xf<>BSCB2_ENVIRONMENTTYPE)&0xFF; + } + void SetEnvironmentType(INDEX iNewEnvironment) + { + iNewEnvironment&=0xFF; + bsc_ulFlags2 &= ~(0xFF< CBrushSectorSelection; +// selection of brush sectors used for CSG +typedef CSelection CBrushSectorSelectionForCSG; + +/* + * One detail level of a brush. + */ +class ENGINE_API CBrushMip { +public: +// implementation: + CDynamicArray bm_abscSectors; // sectors + CBrush3D *bm_pbrBrush; // pointer to brush + + /* Select all sectors within a range. */ + void SelectSectorsInRange(CBrushSectorSelectionForCSG &selbscInRange, FLOATaabbox3D boxRange); + void SelectSectorsInRange(CBrushSectorSelection &selbscInRange, FLOATaabbox3D boxRange); + /* Select all sectors in brush. */ + void SelectAllSectors(CBrushSectorSelectionForCSG &selbscAll); + void SelectAllSectors(CBrushSectorSelection &selbscAll); + /* Select open sector in brush. */ + void SelectOpenSector(CBrushSectorSelectionForCSG &selbscOpen); + /* Select closed sectors in brush. */ + void SelectClosedSectors(CBrushSectorSelectionForCSG &selbscClosed); + /* Fill a 3d object from a selection in a brush. */ + void ToObject3D(CObject3D &ob, CBrushSectorSelection &selbscToCopy); + void ToObject3D(CObject3D &ob, CBrushSectorSelectionForCSG &selbscToCopy); + /* Add an object3d to brush. (returns pointer to the first created sector) */ + CBrushSector *AddFromObject3D_t(CObject3D &ob); // throw char * + /* Delete all sectors in a selection. */ + void DeleteSelectedSectors(CBrushSectorSelectionForCSG &selbscToDelete); + /* Spread all brush mips after this one. */ + void SpreadFurtherMips(void); + /* Reoptimize all sectors in the brush mip. */ + void Reoptimize(void); + /* Find all portals that have no links and kill their portal flag. */ + void RemoveDummyPortals(BOOL bClearPortalFlags); +public: +// interface: + CListNode bm_lnInBrush; // for linking in list of mip-brushes for a brush + FLOAT bm_fMaxDistance; // distance after which this mip-brush is not displayed + FLOATaabbox3D bm_boxBoundingBox; // bounding box of entire mip-brush in absolute space + FLOATaabbox3D bm_boxRelative; // bounding box of entire mip-brush in relative space + + /* Constructor. */ + CBrushMip(void); + /* Free all memory and leave empty brush mip. */ + void Clear(void); + /* Fill a brush mip from 3d object. */ + void FromObject3D_t(CObject3D &ob); // throw char * + /* Copy brush mip from another brush mip. */ + void Copy(CBrushMip &bmOther, FLOAT fStretch, BOOL bMirrorX); + + /* Set mip distance of this mip, spread all that are further. */ + void SetMipDistance(FLOAT fMipDistance); + /* Get mip factor of this mip. */ + FLOAT GetMipDistance(void); + /* Get mip index of this mip. */ + INDEX GetMipIndex(void); + // get next brush mip + CBrushMip *GetNext(void); + // get previous brush mip + CBrushMip *GetPrev(void); + // check if this is the first mip in this brush + inline BOOL IsFirstMip(void); + + // overrides from CSerial + /* Read from stream. */ + void Read_new_t( CTStream *istrFile); // throw char * + void Read_old_t( CTStream *istrFile); // throw char * + /* Write to stream. */ + void Write_t( CTStream *ostrFile); // throw char * + + /* Update bounding box from bounding boxes of all sectors. */ + void UpdateBoundingBox(void); + /* Calculate bounding boxes in all sectors. */ + void CalculateBoundingBoxes(CSimpleProjection3D_DOUBLE &prRelativeToAbsolute); +}; + +/* + * Brush class -- a piece of level that can be moved independently + */ +#define BRF_DRAWSELECTED (1L<<0) // internal marker for rendering selected brushes +#define BRF_DRAWFIRSTMIP (1L<<1) // viewer is inside this brush + +class ENGINE_API CBrush3D : public CBrushBase { +public: +// implementation: + CListNode br_lnInActiveBrushes; // for linking in list of active brushes in renderer + CAnyProjection3D br_prProjection; // projection currently used by this brush + CEntity *br_penEntity; // back pointer from brush to its entity + class CFieldSettings *br_pfsFieldSettings;// field settings for field brushes + ULONG br_ulFlags; // brush flags + + /* Wrapper for CObject3D::Optimize(), updates profiling information. */ + static void OptimizeObject3D(CObject3D &ob); + + /* Prepare a projection from brush space to absolute space. */ + void PrepareRelativeToAbsoluteProjection(CSimpleProjection3D_DOUBLE &prRelativeToAbsolute); + /* Calculate bounding boxes in all brush mips. */ + void CalculateBoundingBoxes(void); + void CalculateBoundingBoxesForOneMip(CBrushMip *pbmOnly); // for only one mip + INDEX GetBrushType() { return CBrushBase::BT_BRUSH3D; } // this is brush not terrain + +public: +// interface: + CListHead br_lhBrushMips; // mip brushes in this brush + + // constructor + CBrush3D(void); + // destructor + ~CBrush3D(void); + + /* Free all memory and leave empty brush. */ + void Clear(void); + /* Fill a brush from 3d object. */ + void FromObject3D_t(CObject3D &ob); // throw char * + void AddMipBrushFromObject3D_t(CObject3D &ob, FLOAT fSwitchDistance); // throw char * + /* Copy brush from another brush with possible mirror and stretch. */ + void Copy(CBrush3D &brOther, FLOAT fStretch, BOOL bMirrorX); + + /* Delete a brush mip with given factor. */ + void DeleteBrushMip(CBrushMip *pbmToDelete); + /* Create a new brush mip. */ + CBrushMip *NewBrushMipAfter(CBrushMip *pbm, BOOL bCopy); + CBrushMip *NewBrushMipBefore(CBrushMip *pbm, BOOL bCopy); + /* Get a brush mip for given mip-factor. */ + CBrushMip *GetBrushMipByDistance(FLOAT fDistance); + /* Get a brush mip by its given index. */ + CBrushMip *GetBrushMipByIndex(INDEX iMip); + // get first brush mip + CBrushMip *GetFirstMip(void); + // get last brush mip + CBrushMip *GetLastMip(void); + + // switch from zoning to non-zoning + void SwitchToNonZoning(void); + // switch from non-zoning to zoning + void SwitchToZoning(void); + + // overrides from CSerial + /* Read from stream. */ + void Read_t( CTStream *istrFile); // throw char * + void Read_new_t( CTStream *istrFile); // throw char * + void Read_old_t( CTStream *istrFile); // throw char * + /* Write to stream. */ + void Write_t( CTStream *ostrFile); // throw char * +}; + +// check if this is the first mip in this brush +inline BOOL CBrushMip::IsFirstMip(void) { + return &bm_pbrBrush->br_lhBrushMips.IterationHead() == &bm_lnInBrush; +}; + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Brushes/BrushArchive.cpp b/Sources/Engine/Brushes/BrushArchive.cpp new file mode 100644 index 0000000..b7cabc3 --- /dev/null +++ b/Sources/Engine/Brushes/BrushArchive.cpp @@ -0,0 +1,491 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +template CDynamicArray; + +extern BOOL _bPortalSectorLinksPreLoaded = FALSE; +extern BOOL _bEntitySectorLinksPreLoaded = FALSE; + +/* + * Calculate bounding boxes in all brushes. + */ +void CBrushArchive::CalculateBoundingBoxes(void) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_CALCULATEBOUNDINGBOXES); + // for each of the brushes + FOREACHINDYNAMICARRAY(ba_abrBrushes, CBrush3D, itbr) { + // if the brush has no entity + if (itbr->br_penEntity==NULL) { + // skip it + continue; + } + // calculate its boxes + itbr->CalculateBoundingBoxes(); + } + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CALCULATEBOUNDINGBOXES); +} + +/* Make indices for all brush elements. */ +void CBrushArchive::MakeIndices(void) +{ + // NOTE: Mips and brushes don't have indices, because it is not needed yet. + // Polygon and sector indices are needed for loading/saving of portal-sector links. + + INDEX ctBrushes=0; + INDEX ctMips=0; + INDEX ctSectors=0; + INDEX ctPolygons=0; + // for each brush + FOREACHINDYNAMICARRAY(ba_abrBrushes, CBrush3D, itbr) { + // for each mip in the brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, itbr->br_lhBrushMips, itbm) { + // for each sector in the brush mip + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // for each polygon in the sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + itbpo->bpo_iInWorld = ctPolygons; + ctPolygons++; + } + itbsc->bsc_iInWorld = ctSectors; + ctSectors++; + } + ctMips++; + } + ctBrushes++; + } + + // make arrays of pointers to sectors and polygons + ba_apbpo.Clear(); + ba_apbpo.New(ctPolygons); + ba_apbsc.Clear(); + ba_apbsc.New(ctSectors); + {FOREACHINDYNAMICARRAY(ba_abrBrushes, CBrush3D, itbr) { + FOREACHINLIST(CBrushMip, bm_lnInBrush, itbr->br_lhBrushMips, itbm) { + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + ba_apbsc[itbsc->bsc_iInWorld] = itbsc; + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + ba_apbpo[itbpo->bpo_iInWorld] = itbpo; + } + } + } + }} +} + +#define DISTANCE_EPSILON 0.1f +/* Create links between portals and sectors on their other side. */ +void CBrushArchive::LinkPortalsAndSectors(void) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_LINKPORTALSANDSECTORS); + ASSERT(GetFPUPrecision()==FPT_53BIT); + + // for each of the zoning brushes + FOREACHINDYNAMICARRAY(ba_abrBrushes, CBrush3D, itbr1) { + if (itbr1->br_penEntity==NULL || !(itbr1->br_penEntity->en_ulFlags&ENF_ZONING)) { + continue; + } + // for each mip + FOREACHINLIST(CBrushMip, bm_lnInBrush, itbr1->br_lhBrushMips, itbm1) { + // for each sector in the brush mip + FOREACHINDYNAMICARRAY(itbm1->bm_abscSectors, CBrushSector, itbsc1) { + + // for each of the zoning brushes + FOREACHINDYNAMICARRAY(ba_abrBrushes, CBrush3D, itbr2) { + if (itbr2->br_penEntity==NULL || !(itbr2->br_penEntity->en_ulFlags&ENF_ZONING)) { + continue; + } + // for each mip that might have contact with the sector + FOREACHINLIST(CBrushMip, bm_lnInBrush, itbr2->br_lhBrushMips, itbm2) { + if (!itbm2->bm_boxBoundingBox.HasContactWith(itbsc1->bsc_boxBoundingBox, DISTANCE_EPSILON)) { + continue; + } + // for each sector in the brush mip that might have contact, except current one + FOREACHINDYNAMICARRAY(itbm2->bm_abscSectors, CBrushSector, itbsc2) { + if (&*itbsc1==&*itbsc2) { + continue; + } + if (!itbsc2->bsc_boxBoundingBox.HasContactWith(itbsc1->bsc_boxBoundingBox, DISTANCE_EPSILON)) { + continue; + } + // for all portals in this sector that might have contact + FOREACHINSTATICARRAY(itbsc2->bsc_abpoPolygons, CBrushPolygon, itbpo2) { + if (!(itbpo2->bpo_ulFlags&(BPOF_PORTAL|BPOF_PASSABLE))) { + continue; + } + if (!itbpo2->bpo_boxBoundingBox.HasContactWith(itbsc1->bsc_boxBoundingBox, DISTANCE_EPSILON)) { + continue; + } + // create a BSP polygon from the brush polygon + CBrushPolygon &brpo2 = *itbpo2; + BSPPolygon bspo2; + brpo2.CreateBSPPolygonNonPrecise(bspo2); + // split the polygon with the BSP of the sector + DOUBLEbspcutter3D bcCutter(bspo2, *itbsc1->bsc_bspBSPTree.bt_pbnRoot); + // if anything remains on the border looking outside + if (bcCutter.bc_abedInside.Count()>0 + ||bcCutter.bc_abedBorderInside.Count()>0 + ||bcCutter.bc_abedBorderOutside.Count()>0) { + // relate the sector to the portal + AddRelationPair( + itbpo2->bpo_rsOtherSideSectors, + itbsc1->bsc_rdOtherSidePortals); + } + } + } + } + } + } + } + } + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_LINKPORTALSANDSECTORS); +} + + +// remove shadow layers without valid light source in all brushes +void CBrushArchive::RemoveDummyLayers(void) +{ + // for each brush + FOREACHINDYNAMICARRAY(ba_abrBrushes, CBrush3D, itbr) { // for each mip + if( itbr->br_penEntity==NULL) continue; // skip brush without entity + FOREACHINLIST(CBrushMip, bm_lnInBrush, itbr->br_lhBrushMips, itbm) { // for each sector in the brush mip + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { // for each polygon in the sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + CBrushPolygon &bpo = *itbpo; + bpo.bpo_smShadowMap.RemoveDummyLayers(); // remove shadow layers without valid light source + } + } + } + } +} + + +// cache all shadowmaps +void CBrushArchive::CacheAllShadowmaps(void) +{ + // count all shadowmaps + INDEX ctShadowMaps=0; + {FOREACHINDYNAMICARRAY( ba_abrBrushes, CBrush3D, itbr) { // for each mip + if( itbr->br_penEntity==NULL) continue; // skip brush without entity + FOREACHINLIST( CBrushMip, bm_lnInBrush, itbr->br_lhBrushMips, itbm) { // for each sector in the brush mip + FOREACHINDYNAMICARRAY( itbm->bm_abscSectors, CBrushSector, itbsc) { // for each polygon in the sector + FOREACHINSTATICARRAY( itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + if( !itbpo->bpo_smShadowMap.bsm_lhLayers.IsEmpty()) ctShadowMaps++; // count shadowmap if the one exist + } + } + } + }} + + try { + SetProgressDescription( TRANS("caching shadowmaps")); + CallProgressHook_t(0.0f); + // for each brush + INDEX iCurrentShadowMap=0; + {FOREACHINDYNAMICARRAY( ba_abrBrushes, CBrush3D, itbr) { // for each mip + if( itbr->br_penEntity==NULL) continue; // skip brush without entity + FOREACHINLIST( CBrushMip, bm_lnInBrush, itbr->br_lhBrushMips, itbm) { // for each sector in the brush mip + FOREACHINDYNAMICARRAY( itbm->bm_abscSectors, CBrushSector, itbsc) { // for each polygon in the sector + FOREACHINSTATICARRAY( itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + // cache shadowmap if the one exist + CBrushShadowMap &bsm = itbpo->bpo_smShadowMap; + if( bsm.bsm_lhLayers.IsEmpty()) continue; + bsm.CheckLayersUpToDate(); + bsm.Prepare(); + bsm.SetAsCurrent(); + iCurrentShadowMap++; + CallProgressHook_t( (FLOAT)iCurrentShadowMap/ctShadowMaps); + } + } + } + }} + // all done + CallProgressHook_t(1.0f); + } + catch( char*) { NOTHING; } +} + + +void CBrushArchive::ReadPortalSectorLinks_t( CTStream &strm) // throw char * +{ + // links are not ok if they fail loading + _bPortalSectorLinksPreLoaded = FALSE; + + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_READPORTALSECTORLINKS); + // first make indices for all sectors and polygons + MakeIndices(); + + // if the chunk is not there + if (!(strm.PeekID_t()==CChunkID("PSLS"))) { // portal-sector links + // do nothing; + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_READPORTALSECTORLINKS); + return; + } + + // read the version + strm.ExpectID_t("PSLS"); // portal-sector links + INDEX iVersion; + strm>>iVersion; + ASSERT(iVersion==1); + // read chunk size + SLONG slChunkSizePos = strm.GetPos_t(); + SLONG slChunkSize; + strm>>slChunkSize; + + // repeat + FOREVER { + // read sector index + INDEX iSector; + strm>>iSector; + // if end marker + if (iSector==-1) { + // stop loading + break; + } + // get the sector + CBrushSector *pbsc = ba_apbsc[iSector]; + ASSERT(pbsc->bsc_iInWorld==iSector); + // read number of links + INDEX ctLinks; + strm>>ctLinks; + // for each link + for(INDEX iLink=0; iLink>iPolygon; + CBrushPolygon *pbpo = ba_apbpo[iPolygon]; + ASSERT(pbpo->bpo_iInWorld==iPolygon); + // relate the sector to the portal + AddRelationPair( + pbpo->bpo_rsOtherSideSectors, + pbsc->bsc_rdOtherSidePortals); + } + pbsc->bsc_ulTempFlags|=BSCTF_PRELOADEDLINKS; + } + + // check chunk size + ASSERT(strm.GetPos_t()-slChunkSizePos-sizeof(INDEX)==slChunkSize); + // check end id + strm.ExpectID_t("PSLE"); // portal-sector links end + // mark that links are ok + _bPortalSectorLinksPreLoaded = TRUE; + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_READPORTALSECTORLINKS); +} + +void CBrushArchive::ReadEntitySectorLinks_t( CTStream &strm) // throw char * +{ + // links are not ok if they fail loading + _bEntitySectorLinksPreLoaded = FALSE; + + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_READPORTALSECTORLINKS); + // first make indices for all sectors and polygons + MakeIndices(); + + // if the chunk is not there + if (!(strm.PeekID_t()==CChunkID("ESL2"))) { // entity-sector links v2 + // do nothing; + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_READPORTALSECTORLINKS); + return; + } + + // read the version + strm.ExpectID_t("ESL2"); // entity-sector links v2 + INDEX iVersion; + strm>>iVersion; + ASSERT(iVersion==1); + // read chunk size + SLONG slChunkSizePos = strm.GetPos_t(); + SLONG slChunkSize; + strm>>slChunkSize; + + // repeat + FOREVER { + // read sector index + INDEX iSector; + strm>>iSector; + // if end marker + if (iSector==-1) { + // stop loading + break; + } + // get the sector + CBrushSector *pbsc = ba_apbsc[iSector]; + ASSERT(pbsc->bsc_iInWorld==iSector); + // read number of links + INDEX ctLinks; + strm>>ctLinks; + // for each link + for(INDEX iLink=0; iLink>iEntity; + CEntity *pen = ba_pwoWorld->EntityFromID(iEntity); + // relate the sector to the entity + AddRelationPair(pbsc->bsc_rsEntities, pen->en_rdSectors); + } + } + + // check chunk size + ASSERT(strm.GetPos_t()-slChunkSizePos-sizeof(INDEX)==slChunkSize); + // check end id + strm.ExpectID_t("ESLE"); // entity-sector links end + + // mark that links are ok + _bEntitySectorLinksPreLoaded = TRUE; + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_READPORTALSECTORLINKS); +} + +void CBrushArchive::WritePortalSectorLinks_t( CTStream &strm) // throw char * +{ + // first make indices for all sectors and polygons + MakeIndices(); + + // write chunk id and current version + strm.WriteID_t("PSLS"); // portal-sector links + strm<br_lhBrushMips, itbm) { + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + CBrushSector *pbsc = itbsc; + // get number of portal links that it has + INDEX ctLinks = pbsc->bsc_rdOtherSidePortals.Count(); + // if it has no links + if (ctLinks==0) { + // skip it + continue; + } + // write sector index and number of links + strm<bsc_iInWorld<bsc_rdOtherSidePortals, CBrushPolygon, bpo_rsOtherSideSectors, pbpo) + // write the polygon index + strm<bpo_iInWorld; + ENDFOR} + } + } + }} + // write sector index -1 as end marker + strm<br_lhBrushMips, itbm) { + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + CBrushSector *pbsc = itbsc; + // get number of entity links that it has + INDEX ctLinks = pbsc->bsc_rsEntities.Count(); + // if it has no links + if (ctLinks==0) { + // skip it + continue; + } + // write sector index and number of links + strm<bsc_iInWorld<bsc_rsEntities, CEntity, en_rdSectors, pen) + // write the entity index + strm<en_ulID; + ENDFOR} + } + } + }} + // write sector index -1 as end marker + strm<ExpectID_t("BRAR"); // brush archive + + INDEX ctBrushes; + // read number of brushes + (*istrFile)>>ctBrushes; + + // if there are some brushes + if (ctBrushes!=0) { + // create that much brushes + CBrush3D *abrBrushes = ba_abrBrushes.New(ctBrushes); + // for each of the new brushes + for (INDEX iBrush=0; iBrushExpectID_t("EOAR"); // end of archive +} + +/* + * Write to stream. + */ +void CBrushArchive::Write_t( CTStream *ostrFile) // throw char * +{ + ostrFile->WriteID_t("BRAR"); // brush archive + + // write the number of brushes + (*ostrFile)<Write_t(ostrFile); + } + + // write links + WritePortalSectorLinks_t(*ostrFile); + ostrFile->WriteID_t("EOAR"); // end of archive +} diff --git a/Sources/Engine/Brushes/BrushArchive.h b/Sources/Engine/Brushes/BrushArchive.h new file mode 100644 index 0000000..5f22064 --- /dev/null +++ b/Sources/Engine/Brushes/BrushArchive.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_BRUSHARCHIVE_H +#define SE_INCL_BRUSHARCHIVE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include + +/* + * Brush archive class -- a collection of brushes used by a level. + */ +class ENGINE_API CBrushArchive : public CSerial { +public: + CDynamicArray ba_abrBrushes; // all the brushes in archive + // lists of all shadow maps that need calculation + CListHead ba_lhUncalculatedShadowMaps; + CWorld *ba_pwoWorld; // the world + // pointers to all polygons and sectors + CStaticArray ba_apbpo; + CStaticArray ba_apbsc; + + // overrides from CSerial + /* Read/write to/from stream. */ + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * + void ReadPortalSectorLinks_t( CTStream &strm); // throw char * + void WritePortalSectorLinks_t( CTStream &strm); // throw char * + void ReadEntitySectorLinks_t( CTStream &strm); // throw char * + void WriteEntitySectorLinks_t( CTStream &strm); // throw char * + + /* Calculate bounding boxes in all brushes. */ + void CalculateBoundingBoxes(void); + /* Create links between portals and sectors on their other side. */ + void LinkPortalsAndSectors(void); + /* Make indices for all brush elements. */ + void MakeIndices(void); + // remove shadow layers without valid light source in all brushes + void RemoveDummyLayers(void); + // cache all shadowmaps (upon loading of world) + void CacheAllShadowmaps(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Brushes/BrushBase.h b/Sources/Engine/Brushes/BrushBase.h new file mode 100644 index 0000000..d18d5e8 --- /dev/null +++ b/Sources/Engine/Brushes/BrushBase.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_BRUSH_BASE_H +#define SE_INCL_BRUSH_BASE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// this is base class for brushes and terrains +class ENGINE_API CBrushBase { +public: + virtual INDEX GetBrushType() { + ASSERT(FALSE); + return BT_NONE; + }; + + enum BrushType { + BT_NONE = 0, // none + BT_BRUSH3D = 1, // this is Brush3D + BT_TERRAIN = 2, // this is Terrain + }; +}; + +#endif \ No newline at end of file diff --git a/Sources/Engine/Brushes/BrushExport.cpp b/Sources/Engine/Brushes/BrushExport.cpp new file mode 100644 index 0000000..1c0139f --- /dev/null +++ b/Sources/Engine/Brushes/BrushExport.cpp @@ -0,0 +1,197 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include + +/* + * Fill a 3d object from a selection in a brush mip. + */ +void CBrushMip::ToObject3D( + CObject3D &ob, + CBrushSectorSelection &selbscToCopy) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + // get number of sectors in the selection + INDEX ctSectors = selbscToCopy.Count(); + // create that much sectors in the object + CObjectSector *poscSectors = ob.ob_aoscSectors.New(ctSectors); + // for each sector in the selection mip + FOREACHINDYNAMICCONTAINER(selbscToCopy, CBrushSector, itbsc) { + // fill corresponding sector in object from it + itbsc->ToObjectSector(*poscSectors++); + } + + // optimize the object, to remove unused elements +// CBrush3D::OptimizeObject3D(ob); +} + +/* + * Fill a 3d object from a selection in a brush mip. + */ +void CBrushMip::ToObject3D( + CObject3D &ob, + CBrushSectorSelectionForCSG &selbscToCopy) +{ + CSetFPUPrecision sfp(FPT_53BIT); + // get number of sectors in the selection + INDEX ctSectors = selbscToCopy.Count(); + // create that much sectors in the object + CObjectSector *poscSectors = ob.ob_aoscSectors.New(ctSectors); + // for each sector in the selection mip + FOREACHINDYNAMICCONTAINER(selbscToCopy, CBrushSector, itbsc) { + // fill corresponding sector in object from it + itbsc->ToObjectSector(*poscSectors++); + } + + // optimize the object, to remove unused elements +// CBrush3D::OptimizeObject3D(ob); +} + +/* + * Fill an object sector from a sector in brush. + */ +void CBrushSector::ToObjectSector(CObjectSector &osc) +{ + // copy sector color and ambient + osc.osc_colColor = bsc_colColor; + osc.osc_colAmbient = bsc_colAmbient; + osc.osc_ulFlags[0] = bsc_ulFlags; + osc.osc_ulFlags[1] = bsc_ulFlags2; + osc.osc_ulFlags[2] = bsc_ulVisFlags; + osc.osc_strName = bsc_strName; + // lock the object elements + osc.LockAll(); + // lock the brush elements + LockAll(); + + /* Copy vertices. */ + + // get the number of vertices in brush + INDEX ctVertices = bsc_abvxVertices.Count(); + // create that much vertices in object + osc.osc_aovxVertices.New(ctVertices); + // copy all vertices + for(INDEX iVertex=0; iVertex=sizePolygonProperties+3*sizeTextureProperties); + UBYTE *pubUserData = (UBYTE*)&opo.opo_ubUserData; + memcpy(pubUserData, &bpo.bpo_bppProperties, sizePolygonProperties); + memcpy(pubUserData+sizePolygonProperties+0*sizeTextureProperties, + &bpo.bpo_abptTextures[0].bpt_auProperties, + sizeTextureProperties); + memcpy(pubUserData+sizePolygonProperties+1*sizeTextureProperties, + &bpo.bpo_abptTextures[1].bpt_auProperties, + sizeTextureProperties); + memcpy(pubUserData+sizePolygonProperties+2*sizeTextureProperties, + &bpo.bpo_abptTextures[2].bpt_auProperties, + sizeTextureProperties); + *(ULONG*)(pubUserData+sizePolygonProperties+3*sizeTextureProperties) = bpo.bpo_colShadow; + + opo.opo_PolygonEdges.Lock(); + // get the number of edges in brush polygon + INDEX ctPolygonEdges = bpo.bpo_abpePolygonEdges.Count(); + // create that much edges in object polygon + opo.opo_PolygonEdges.New(ctPolygonEdges); + + // for all edges in brush polygon + INDEX iPolygonEdge=0; + FOREACHINSTATICARRAY(bpo.bpo_abpePolygonEdges, CBrushPolygonEdge, itbpe) { + // get corresponding polygon edge in object polygon + CObjectPolygonEdge &ope = opo.opo_PolygonEdges[iPolygonEdge]; + // set edge reference + ope.ope_Edge = &osc.osc_aoedEdges[bsc_abedEdges.Index(itbpe->bpe_pbedEdge)]; + // set backward flag + ope.ope_Backward = itbpe->bpe_bReverse; + + iPolygonEdge++; + } + opo.opo_PolygonEdges.Unlock(); + } + + // unlock the object elements + osc.UnlockAll(); + // unlock the brush elements + UnlockAll(); +} diff --git a/Sources/Engine/Brushes/BrushIO.cpp b/Sources/Engine/Brushes/BrushIO.cpp new file mode 100644 index 0000000..a77bdd9 --- /dev/null +++ b/Sources/Engine/Brushes/BrushIO.cpp @@ -0,0 +1,619 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const INDEX _iSupportedVersion = 14; + +static INDEX _ctPolygonsLoaded; + +#define BPOV_OLD 0 +#define BPOV_WITHHYPERTEXTURES 1 +#define BPOV_MULTITEXTURING 2 +#define BPOV_FAKEPORTALFLAG 3 +#define BPOV_TRIANGLES 4 +#define BPOV_CURRENT BPOV_TRIANGLES + +#define BSCV_OLD 0 +#define BSCV_WITHNAME 1 +#define BSCV_WITHFLAGS2 2 +#define BSCV_WITHVISFLAGS 3 +#define BSCV_CURRENT BSCV_WITHVISFLAGS + +/* + * Write to stream. + */ +void CBrush3D::Write_t( CTStream *postrm) // throw char * +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + (*postrm).WriteID_t("BR3D"); // 'brush 3D' + // write the brush version + (*postrm)<<_iSupportedVersion; + + // write number of brush mips + (*postrm)<Write_t(postrm); + } + + (*postrm).WriteID_t("BREN"); // 'brush 3D end' +} + +/* + * Read from stream. + */ +void CBrush3D::Read_t( CTStream *pistrm) // throw char * +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + (*pistrm).ExpectID_t("BR3D"); // 'brush 3D' + // read the version number + INDEX iSavedVersion; + (*pistrm)>>iSavedVersion; + + // if the version number is the newest + if(iSavedVersion==_iSupportedVersion) { + // read current version + Read_new_t(pistrm); + + // if the version number is not the newest + } else { + // if the version can be converted + if (iSavedVersion==_iSupportedVersion-1) { + // show warning + WarningMessage( + TRANS("The brush version was %d.\n" + "Auto-converting to version %d."), + iSavedVersion, _iSupportedVersion); + // read previous version + Read_old_t(pistrm); + } else { + // report error + ThrowF_t( + TRANS("The brush version on disk is %d.\n" + "Current supported version is %d."), + iSavedVersion, _iSupportedVersion); + } + } +} + +/* + * Read from stream -- previous version. + */ +void CBrush3D::Read_old_t( CTStream *pistrm) // throw char * +{ + _ctPolygonsLoaded = 0; + // read number of brush mips + INDEX ctMips; + (*pistrm)>>ctMips; + // for each mip + for(INDEX iMip=0; iMipbm_lnInBrush); + // read it from stream + pbmMip->Read_old_t(pistrm); + // set back-pointer to the brush + pbmMip->bm_pbrBrush = this; + } + (*pistrm).ExpectID_t("BREN"); // 'brush 3D end' + _RPT1(_CRT_WARN, "Polygons in brush: %d\n", _ctPolygonsLoaded); +} + +/* + * Read from stream -- current version. + */ +void CBrush3D::Read_new_t( CTStream *pistrm) // throw char * +{ + _ctPolygonsLoaded = 0; + // read number of brush mips + INDEX ctMips; + (*pistrm)>>ctMips; + // for each mip + for(INDEX iMip=0; iMipbm_lnInBrush); + // set back-pointer to the brush + pbmMip->bm_pbrBrush = this; + // read it from stream + pbmMip->Read_new_t(pistrm); + } + (*pistrm).ExpectID_t("BREN"); // 'brush 3D end' + _RPT1(_CRT_WARN, "Polygons in brush: %d\n", _ctPolygonsLoaded); +} + +/* + * Write to stream. + */ +void CBrushMip::Write_t( CTStream *postrm) // throw char * +{ + // write the mip factor + postrm->WriteID_t("BRMP"); + (*postrm)<Write_t(postrm); + } +} + +/* + * Read from stream -- previous version. + */ +void CBrushMip::Read_old_t( CTStream *pistrm) // throw char * +{ + // read number of sectors + INDEX ctSectors; + (*pistrm)>>ctSectors; + // create that much sectors + bm_abscSectors.New(ctSectors); + bm_abscSectors.Lock(); + // for each sector + for(INDEX iSector=0; iSectorPeekID_t()==CChunkID("BRMP")) { + pistrm->ExpectID_t("BRMP"); + bWithMipDistance = TRUE; + } + (*pistrm)>>bm_fMaxDistance; + // if old mip-factor instead max distance + if (!bWithMipDistance) { + // convert from factor to distance + if (bm_fMaxDistance==100.0f) { + bm_fMaxDistance = 1E6f; + } else { + FLOAT fPerspectiveRatio = 640/(2.0f*Tan(90.0f/2)); + bm_fMaxDistance = fPerspectiveRatio*pow(2, bm_fMaxDistance)/1024; + } + } + + // read number of sectors + INDEX ctSectors; + (*pistrm)>>ctSectors; + // create that much sectors + bm_abscSectors.New(ctSectors); + bm_abscSectors.Lock(); + // for each sector + for(INDEX iSector=0; iSector>fnmTexture; + SetTextureWithPossibleReplacing_t(bpt_toTexture, fnmTexture); + // gather CRC of that texture + if (bpt_toTexture.GetData()!=NULL) { + bpt_toTexture.GetData()->AddToCRCTable(); + } + strm.Read_t(&bpt_mdMapping, sizeof(bpt_mdMapping)); + strm>>s.bpt_ubScroll; + strm>>s.bpt_ubBlend; + strm>>s.bpt_ubFlags; + strm>>s.bpt_ubDummy; + strm>>s.bpt_colColor; +} +void CBrushPolygonTexture::Write_t( CTStream &strm) // throw char * +{ + strm<Write_t(&itbvx->bvx_vdPreciseRelative, sizeof(DOUBLE3D)); + }} + + (*postrm).WriteID_t("PLNs"); // 'planes' + // write the number of planes in brush + (*postrm)<Write_t(&itbpl->bpl_pldPreciseRelative, sizeof(DOUBLEplane3D)); + }} + + (*postrm).WriteID_t("EDGs"); // 'edges' + // write the number of edges in brush + (*postrm)<bed_pbvxVertex0); + (*postrm)<bed_pbvxVertex1); + }} + + (*postrm).WriteID_t("BPOs"); // 'brush polygons' + (*postrm)<bpe_pbedEdge); + // if it is reverse edge + if (itbpe->bpe_bReverse) { + // set highest bit in the index + iEdge |= 0x80000000; + } + // write the index + (*postrm)<0) { + (*postrm).Write_t(&bpo.bpo_aiTriangleElements[0], ctElements*sizeof(INDEX)); + } + + // write the shadow-map (if it exists) + bpo.bpo_smShadowMap.Write_t(postrm); + // write shadow color + (*postrm)<>iBSCVersion; + if (iBSCVersion=BSCV_WITHNAME) { + (*pistrm)>>bsc_strName; + } + + // read sector color and ambient light + (*pistrm)>>bsc_colColor; + (*pistrm)>>bsc_colAmbient; + // read sector flags + (*pistrm)>>bsc_ulFlags; + if (iBSCVersion>=BSCV_WITHFLAGS2) { + (*pistrm)>>bsc_ulFlags2; + } + if (iBSCVersion>=BSCV_WITHVISFLAGS) { + (*pistrm)>>bsc_ulVisFlags; + } + // clear sector flags for selection + bsc_ulFlags &= ~(BSCF_SELECTED | BSCF_SELECTEDFORCSG); + // no temp flags initially + bsc_ulTempFlags = 0; + + (*pistrm).ExpectID_t("VTXs"); // 'vertices' + // read the number of vertices in brush + INDEX ctVertices; + (*pistrm)>>ctVertices; + // create that much vertices + bsc_abvxVertices.New(ctVertices); + bsc_awvxVertices.New(ctVertices); + // for each vertex + {FOREACHINSTATICARRAY(bsc_abvxVertices, CBrushVertex, itbvx) { + // read precise vertex coordinates + pistrm->Read_t(&itbvx->bvx_vdPreciseRelative, sizeof(DOUBLE3D)); + // remember sector pointer + itbvx->bvx_pbscSector = this; + }} + + (*pistrm).ExpectID_t("PLNs"); // 'planes' + // read the number of planes in brush + INDEX ctPlanes; + (*pistrm)>>ctPlanes; + // create that much planes + bsc_abplPlanes.New(ctPlanes); + bsc_awplPlanes.New(ctPlanes); + // for each plane + {FOREACHINSTATICARRAY(bsc_abplPlanes, CBrushPlane, itbpl) { + // read precise plane coordinates + pistrm->Read_t(&itbpl->bpl_pldPreciseRelative, sizeof(DOUBLEplane3D)); + }} + + (*pistrm).ExpectID_t("EDGs"); // 'edges' + // read the number of edges in brush + INDEX ctEdges; + (*pistrm)>>ctEdges; + // create that much edges + bsc_abedEdges.New(ctEdges); + bsc_awedEdges.New(ctEdges); + // for all edges in object + {for(INDEX iEdge=0; iEdge>iVertex0; + INDEX iVertex1; + (*pistrm)>>iVertex1; + // set vertex pointers + bed.bed_pbvxVertex0 = &bsc_abvxVertices[iVertex0]; + bed.bed_pbvxVertex1 = &bsc_abvxVertices[iVertex1]; + // set the working edge + bed.bed_pwedWorking = &wed; + wed.wed_iwvx0 = iVertex0; + wed.wed_iwvx1 = iVertex1; + }} + + INDEX iBPOVersion; + (*pistrm).ExpectID_t("BPOs"); // 'brush polygons' + (*pistrm)>>iBPOVersion; + if (iBPOVersion>ctPolygons; + _ctPolygonsLoaded += ctPolygons; + // create that much polygons + bsc_abpoPolygons.New(ctPolygons); + // for each polygon + {FOREACHINSTATICARRAY(bsc_abpoPolygons, CBrushPolygon, itbpo) { + CBrushPolygon &bpo = *itbpo; + // read index of the plane + INDEX iPlane; + (*pistrm)>>iPlane; + // set plane pointer + bpo.bpo_pbplPlane = &bsc_abplPlanes[iPlane]; + + if (iBPOVersion>=BPOV_MULTITEXTURING) { + // read polygon color + (*pistrm)>>bpo.bpo_colColor; + // read polygon flags + (*pistrm)>>bpo.bpo_ulFlags; + // read all textures + bpo.bpo_abptTextures[0].Read_t(*pistrm); + bpo.bpo_abptTextures[1].Read_t(*pistrm); + bpo.bpo_abptTextures[2].Read_t(*pistrm); + + // read other polygon properties + (*pistrm).Read_t(&bpo.bpo_bppProperties, sizeof(bpo.bpo_bppProperties)); + + } else { + // read textures + CTFileName fnmTexture; + (*pistrm)>>fnmTexture; + SetTextureWithPossibleReplacing_t(bpo.bpo_abptTextures[0].bpt_toTexture, fnmTexture); + CTFileName fnmHyperTexture; + (*pistrm)>>fnmHyperTexture; + SetTextureWithPossibleReplacing_t(bpo.bpo_abptTextures[1].bpt_toTexture, fnmHyperTexture); + // read polygon color + (*pistrm)>>bpo.bpo_colColor; + // read polygon flags + (*pistrm)>>bpo.bpo_ulFlags; + // read texture mapping + bpo.bpo_mdShadow.ReadOld_t(*pistrm); + // read other polygon properties + (*pistrm).Read_t(&bpo.bpo_bppProperties, sizeof(bpo.bpo_bppProperties)); + + // adjust polygon and texture properties + bpo.bpo_abptTextures[0].bpt_mdMapping = bpo.bpo_mdShadow; + bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_OPAQUE; + bpo.bpo_abptTextures[0].s.bpt_colColor = C_WHITE|CT_OPAQUE; + + bpo.bpo_abptTextures[1].bpt_mdMapping = bpo.bpo_mdShadow; + bpo.bpo_abptTextures[1].s.bpt_ubBlend = BPT_BLEND_SHADE; + bpo.bpo_abptTextures[1].s.bpt_colColor = C_WHITE|CT_OPAQUE; + + bpo.bpo_abptTextures[2].bpt_mdMapping = bpo.bpo_mdShadow; + bpo.bpo_abptTextures[2].s.bpt_ubBlend = BPT_BLEND_SHADE; + bpo.bpo_abptTextures[2].s.bpt_colColor = C_WHITE|CT_OPAQUE; + + bpo.bpo_bppProperties.bpp_ubShadowBlend = BPT_BLEND_SHADE; + + if (bpo.bpo_ulFlags&BPOF_PORTAL) { + bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_BLEND; + bpo.bpo_abptTextures[1].s.bpt_ubBlend = BPT_BLEND_ADD; + bpo.bpo_bppProperties.bpp_ubShadowBlend = BPT_BLEND_ADD; + } + } + // if version before fake protal flag + if(iBPOVersion>ctPolygonEdges; + // create that much polygons edges + bpo.bpo_abpePolygonEdges.New(ctPolygonEdges); + // for each polygon edge + {FOREACHINSTATICARRAY(bpo.bpo_abpePolygonEdges, CBrushPolygonEdge, itbpe) { + // read its edge index + INDEX iEdge; + (*pistrm)>>iEdge; + // if the highest bit is set + if (iEdge & 0x80000000) { + // mark that it is reverse edge + itbpe->bpe_bReverse = TRUE; + // clear the highest bit + iEdge &= ~0x80000000; + } else { + // mark that it is not reverse edge + itbpe->bpe_bReverse = FALSE; + } + // set edge pointer + itbpe->bpe_pbedEdge = &bsc_abedEdges[iEdge]; + }} + + // if triangles are saved + if (iBPOVersion>=BPOV_TRIANGLES) { + // read number of triangle vertices + INDEX ctVertices; + (*pistrm)>>ctVertices; + // allocate them + bpo.bpo_apbvxTriangleVertices.New(ctVertices); + // for each triangle vertex + {FOREACHINSTATICARRAY(bpo.bpo_apbvxTriangleVertices, CBrushVertex *, itpbvx) { + // read its index + INDEX ivx; + (*pistrm)>>ivx; + *itpbvx = &bsc_abvxVertices[ivx]; + }} + + // read number of triangle elements + INDEX ctElements; + (*pistrm)>>ctElements; + // allocate them + bpo.bpo_aiTriangleElements.New(ctElements); + // read all element indices + if (ctElements>0) { + (*pistrm).Read_t(&bpo.bpo_aiTriangleElements[0], ctElements*sizeof(INDEX)); + } + } + + // read the shadow-map (if it exists) + bpo.bpo_smShadowMap.Read_t(pistrm); + if (iBPOVersion>=BPOV_MULTITEXTURING) { + // read shadow color + (*pistrm)>>bpo.bpo_colShadow; + } else { + // read shadow animation object index + UBYTE ubDummy; + (*pistrm)>>ubDummy; + bpo.bpo_colShadow = C_WHITE|CT_OPAQUE; + } + }} + + // unlock the brush elements + UnlockAll(); + + // calculate the volume of the sector + CalculateVolume(); + + bsc_ulTempFlags&=~BSCTF_PRELOADEDBSP; + // if there is current version of bsp saved + if ((*pistrm).PeekID_t()==CChunkID("BSP0")) { + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_READBSP); + (*pistrm).ExpectID_t("BSP0"); + // read it + bsc_bspBSPTree.Read_t(*pistrm); + // if read ok + if (bsc_bspBSPTree.bt_abnNodes.Count()>0) { + // mark that tree doesn't have to be recalculated + bsc_ulTempFlags|=BSCTF_PRELOADEDBSP; + } + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_READBSP); + } +} diff --git a/Sources/Engine/Brushes/BrushImport.cpp b/Sources/Engine/Brushes/BrushImport.cpp new file mode 100644 index 0000000..897dd6f --- /dev/null +++ b/Sources/Engine/Brushes/BrushImport.cpp @@ -0,0 +1,281 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Add 3d object as new mip brush. + */ +void CBrush3D::AddMipBrushFromObject3D_t(CObject3D &ob, FLOAT fSwitchDistance) // throw char * +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + // create one brush mip + CBrushMip *pbmBrushMip = new CBrushMip; + // add it to the brush + br_lhBrushMips.AddTail(pbmBrushMip->bm_lnInBrush); + pbmBrushMip->bm_pbrBrush = this; + pbmBrushMip->bm_fMaxDistance = fSwitchDistance; + + // add the object to the brush mip + pbmBrushMip->AddFromObject3D_t(ob); +} + +/* + * Fill a brush from 3d object. + */ +void CBrush3D::FromObject3D_t(CObject3D &ob) // throw char * +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + // clear this brush in case there is something in it + Clear(); + + // create one brush mip + CBrushMip *pbmBrushMip = new CBrushMip; + // add it to the brush + br_lhBrushMips.AddTail(pbmBrushMip->bm_lnInBrush); + pbmBrushMip->bm_pbrBrush = this; + + // add the object to the brush mip + pbmBrushMip->AddFromObject3D_t(ob); +} + +/* + * Add an object3d to brush. (returns pointer to the first created sector) + */ +CBrushSector *CBrushMip::AddFromObject3D_t(CObject3D &ob) // throw char * +{ + CSetFPUPrecision sfp(FPT_53BIT); + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_ADDFROMOBJECT3D); + // optimize the object, to remove replicated and unused elements and find edge inverses + CBrush3D::OptimizeObject3D(ob); + +// turn this on to dump result of all CSG operations +#ifndef NDEBUG +// ob.DebugDump(); +#endif //NDEBUG + + // create as much new sectors in brush mip as there are sectors in object + CBrushSector *pbscSectors = bm_abscSectors.New(ob.ob_aoscSectors.Count()); + CBrushSector *pbscFirstSector = pbscSectors; + // for each sector in the object + FOREACHINDYNAMICARRAY(ob.ob_aoscSectors, CObjectSector, itosc) { + // set brush sector's pointer to the brush + pbscSectors->bsc_pbmBrushMip = this; + // fill one brush sector from it + pbscSectors->FromObjectSector_t(*itosc); + + pbscSectors++; + } + + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_ADDFROMOBJECT3D); + // return pointer to first created sector + return pbscFirstSector; +} + +/* + * Fill a brush sector from a sector in object3d. + */ +void CBrushSector::FromObjectSector_t(CObjectSector &osc) // throw char * +{ + // copy sector color + bsc_colColor = osc.osc_colColor; + bsc_colAmbient = osc.osc_colAmbient; + bsc_ulFlags = osc.osc_ulFlags[0] & ~(BSCF_SELECTED|BSCF_SELECTEDFORCSG); + bsc_ulFlags2 = osc.osc_ulFlags[1]; + bsc_ulVisFlags = osc.osc_ulFlags[2]; + bsc_strName = osc.osc_strName; + + // lock the object elements + osc.LockAll(); + // lock the brush elements + LockAll(); + + /* Copy vertices. */ + + // get the number of vertices in object + INDEX ctVertices = osc.osc_aovxVertices.Count(); + // create that much vertices in brush + bsc_abvxVertices.New(ctVertices); + bsc_awvxVertices.New(ctVertices); + // copy all vertices and set their indices + for(INDEX iVertex=0; iVertexovx_Index]; + bed.bed_pbvxVertex1 = &bsc_abvxVertices[oed.oed_Vertex1->ovx_Index]; + // set the working edge + bed.bed_pwedWorking = &wed; + wed.wed_iwvx0 = oed.oed_Vertex0->ovx_Index; + wed.wed_iwvx1 = oed.oed_Vertex1->ovx_Index; + // set object edge index + oed.oed_Index = iEdge; + } + + /* Copy polygons. */ + + // get the number of polygons in object + INDEX ctPolygons = osc.osc_aopoPolygons.Count(); + // create that much polygons in brush + bsc_abpoPolygons.New(ctPolygons); + + // copy all polygons and set their indices + for(INDEX iPolygon=0; iPolygonopl_Index]; + // get texture from object material + bpo.bpo_abptTextures[0].bpt_toTexture.SetData_t(opo.opo_Material->omt_Name); + bpo.bpo_abptTextures[1].bpt_toTexture.SetData_t(opo.opo_Material->omt_strName2); + bpo.bpo_abptTextures[2].bpt_toTexture.SetData_t(opo.opo_Material->omt_strName3); + // set polygon index + opo.opo_Index = iPolygon; + // set polygon color + bpo.bpo_colColor = opo.opo_colorColor; + // set polygon mapping + bpo.bpo_abptTextures[0].bpt_mdMapping = opo.opo_amdMappings[0]; + bpo.bpo_abptTextures[1].bpt_mdMapping = opo.opo_amdMappings[1]; + bpo.bpo_abptTextures[2].bpt_mdMapping = opo.opo_amdMappings[2]; + bpo.bpo_mdShadow = opo.opo_amdMappings[3]; + // set sector pointer + bpo.bpo_pbscSector = this; + + // copy polygon properties + const int sizeTextureProperties = sizeof(bpo.bpo_abptTextures[0].bpt_auProperties); + const int sizePolygonProperties = sizeof(CBrushPolygonProperties); + ASSERT(sizeof(opo.opo_ubUserData)>=sizePolygonProperties+3*sizeTextureProperties); + UBYTE *pubUserData = (UBYTE*)&opo.opo_ubUserData; + memcpy(&bpo.bpo_bppProperties, pubUserData, sizePolygonProperties); + memcpy(&bpo.bpo_abptTextures[0].bpt_auProperties, + pubUserData+sizePolygonProperties+0*sizeTextureProperties, + sizeTextureProperties); + memcpy(&bpo.bpo_abptTextures[1].bpt_auProperties, + pubUserData+sizePolygonProperties+1*sizeTextureProperties, + sizeTextureProperties); + memcpy(&bpo.bpo_abptTextures[2].bpt_auProperties, + pubUserData+sizePolygonProperties+2*sizeTextureProperties, + sizeTextureProperties); + bpo.bpo_colShadow = *(ULONG*)(pubUserData+sizePolygonProperties+3*sizeTextureProperties), + + // set polygon flags + bpo.bpo_ulFlags = opo.opo_ulFlags & ~(OPOF_IGNOREDBYCSG|BPOF_SELECTED); + + // if the polygon was just created + if(!(bpo.bpo_ulFlags&BPOF_WASBRUSHPOLYGON)) { + // initialize its textures and properties properly + bpo.bpo_bppProperties.bpp_ubShadowBlend = 1; + bpo.bpo_colShadow = C_WHITE|CT_OPAQUE; + + bpo.bpo_abptTextures[0].s.bpt_colColor = C_WHITE|CT_OPAQUE; + bpo.bpo_abptTextures[0].s.bpt_ubFlags = BPTF_DISCARDABLE; + bpo.bpo_abptTextures[0].s.bpt_ubScroll = 0; + bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_OPAQUE; + + bpo.bpo_abptTextures[1].s.bpt_colColor = C_WHITE|CT_OPAQUE; + bpo.bpo_abptTextures[1].s.bpt_ubFlags = BPTF_DISCARDABLE; + bpo.bpo_abptTextures[1].s.bpt_ubScroll = 0; + bpo.bpo_abptTextures[1].s.bpt_ubBlend = BPT_BLEND_SHADE; + + bpo.bpo_abptTextures[2].s.bpt_colColor = C_WHITE|CT_OPAQUE; + bpo.bpo_abptTextures[2].s.bpt_ubFlags = BPTF_DISCARDABLE; + bpo.bpo_abptTextures[2].s.bpt_ubScroll = 0; + bpo.bpo_abptTextures[2].s.bpt_ubBlend = BPT_BLEND_SHADE; + + bpo.bpo_ulFlags|=BPOF_WASBRUSHPOLYGON; + } + + // if it was a wall, but it became a portal now + if (!(bpo.bpo_ulFlags&BPOF_WASPORTAL) && (bpo.bpo_ulFlags&OPOF_PORTAL)) { + // turn on usual portal flags + bpo.bpo_ulFlags |= (BPOF_PASSABLE|BPOF_PORTAL); + // make its first texture translucent + bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_BLEND; + // make its shadow additive + bpo.bpo_bppProperties.bpp_ubShadowBlend = BPT_BLEND_ADD; + + // if it was a portal, but it became a wall now + } else if ((bpo.bpo_ulFlags&BPOF_WASPORTAL) && !(bpo.bpo_ulFlags&OPOF_PORTAL)) { + // turn off usual portal flags + bpo.bpo_ulFlags &= ~(BPOF_PASSABLE|BPOF_PORTAL); + // make its first texture opaque + bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_OPAQUE; + // make its shadow shading + bpo.bpo_bppProperties.bpp_ubShadowBlend = BPT_BLEND_SHADE; + } + + // get the brush of this sector + CBrush3D *pbr = bsc_pbmBrushMip->bm_pbrBrush; + ASSERT(pbr!=NULL); + // if the brush is field + if (pbr->br_pfsFieldSettings!=NULL) { + // set polygon flags for fields + bpo.bpo_ulFlags|=BPOF_PORTAL|BPOF_PASSABLE; + } + + // get the number of edges in object polygon + INDEX ctPolygonEdges = opo.opo_PolygonEdges.Count(); + // create that much edges in brush polygon + bpo.bpo_abpePolygonEdges.New(ctPolygonEdges); + + // for all edges in object polygon + INDEX iPolygonEdge=0; + FOREACHINDYNAMICARRAY(opo.opo_PolygonEdges, CObjectPolygonEdge, itope) { + // get corresponding polygon edge in brush polygon + CBrushPolygonEdge &bpe = bpo.bpo_abpePolygonEdges[iPolygonEdge]; + // set edge reference + bpe.bpe_pbedEdge = &bsc_abedEdges[itope->ope_Edge->oed_Index]; + // set backward flag + bpe.bpe_bReverse = itope->ope_Backward; + + iPolygonEdge++; + } + } + + // unlock the object elements + osc.UnlockAll(); + // unlock the brush elements + UnlockAll(); + + // update changed sector's data after dragging vertices or importing + UpdateSector(); +} diff --git a/Sources/Engine/Brushes/BrushMip.cpp b/Sources/Engine/Brushes/BrushMip.cpp new file mode 100644 index 0000000..d20ea14 --- /dev/null +++ b/Sources/Engine/Brushes/BrushMip.cpp @@ -0,0 +1,393 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +template CDynamicArray; + +// tolerance value for csg selection +#define CSG_RANGE_EPSILON (0.25f) + +/* + * Select all sectors within a range. + */ +void CBrushMip::SelectSectorsInRange( + CBrushSectorSelectionForCSG &selbscInRange, + FLOATaabbox3D boxRange + ) +{ + // for all sectors in the brush + {FOREACHINDYNAMICARRAY(bm_abscSectors, CBrushSector, itbsc) { + // if the sector is in the range + if ( itbsc->bsc_boxBoundingBox.HasContactWith(boxRange, CSG_RANGE_EPSILON) ) { + // select it + selbscInRange.Select(itbsc.Current()); + } + }} +} +void CBrushMip::SelectSectorsInRange( + CBrushSectorSelection &selbscInRange, + FLOATaabbox3D boxRange + ) +{ + // for all sectors in the brush + {FOREACHINDYNAMICARRAY(bm_abscSectors, CBrushSector, itbsc) { + // if the sector is in the range + if ( itbsc->bsc_boxBoundingBox.HasContactWith(boxRange, CSG_RANGE_EPSILON) ) { + // select it + selbscInRange.Select(itbsc.Current()); + } + }} +} + +/* + * Select open sector in brush. + */ +void CBrushMip::SelectOpenSector(CBrushSectorSelectionForCSG &selbscOpen) +{ + // for all sectors in the brush + {FOREACHINDYNAMICARRAY(bm_abscSectors, CBrushSector, itbsc) { + // if the sector is open + if (itbsc->bsc_ulFlags & BSCF_OPENSECTOR) { + // select it + selbscOpen.Select(itbsc.Current()); + } + }} + // there must be at most one open sector in a brush mip + ASSERT(selbscOpen.Count()<=1); +} + +/* + * Select closed sectors in brush. + */ +void CBrushMip::SelectClosedSectors(CBrushSectorSelectionForCSG &selbscClosed) +{ + // for all sectors in the brush + {FOREACHINDYNAMICARRAY(bm_abscSectors, CBrushSector, itbsc) { + // if the sector is closed + if (!(itbsc->bsc_ulFlags & BSCF_OPENSECTOR)) { + // select it + selbscClosed.Select(itbsc.Current()); + } + }} + // there must be at most one open sector in a brush mip + ASSERT(bm_abscSectors.Count()-selbscClosed.Count()<=1); +} + +/* + * Select all sectors in brush. + */ +void CBrushMip::SelectAllSectors(CBrushSectorSelectionForCSG &selbscAll) +{ + // for all sectors in the brush + {FOREACHINDYNAMICARRAY(bm_abscSectors, CBrushSector, itbsc) { + // select it + selbscAll.Select(itbsc.Current()); + }} +} +void CBrushMip::SelectAllSectors(CBrushSectorSelection &selbscAll) +{ + // for all sectors in the brush + {FOREACHINDYNAMICARRAY(bm_abscSectors, CBrushSector, itbsc) { + // select it + selbscAll.Select(itbsc.Current()); + }} +} + +/* + * Delete all sectors in a selection. + */ +void CBrushMip::DeleteSelectedSectors(CBrushSectorSelectionForCSG &selbscToDelete) +{ + // for each sector in the selection + {FOREACHINDYNAMICCONTAINER(selbscToDelete, CBrushSector, itbsc) { + // delete it from the brush mip + bm_abscSectors.Delete(itbsc); + }} + + /* NOTE: we must not clear the selection directly, since the sectors + contained there are already freed and deselecting them would make an access + violation. + */ + // clear the selection on the container level + selbscToDelete.CDynamicContainer::Clear(); +} + +/* Constructor. */ +CBrushMip::CBrushMip(void) : bm_fMaxDistance(1E6f) +{ +} + +/* + * Copy brush mip from another brush mip. + */ +void CBrushMip::Copy(CBrushMip &bmOther, FLOAT fStretch, BOOL bMirrorX) +{ + // clear this brush mip + Clear(); + // copy the mip factor + bm_fMaxDistance = bmOther.bm_fMaxDistance; + // create an object 3d from the source brush mip + CObject3D obOther; + CBrushSectorSelectionForCSG selbscAll; + bmOther.SelectAllSectors(selbscAll); + bmOther.ToObject3D(obOther, selbscAll); + + // if there is some mirror or stretch + if (fStretch!=1.0f || bMirrorX) { + CSimpleProjection3D_DOUBLE prMirrorAndStretch; + prMirrorAndStretch.ObjectPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + prMirrorAndStretch.ViewerPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + if (bMirrorX) { + prMirrorAndStretch.ObjectStretchL() = FLOAT3D(-fStretch, fStretch, fStretch); + } else { + prMirrorAndStretch.ObjectStretchL() = FLOAT3D(fStretch, fStretch, fStretch); + } + prMirrorAndStretch.Prepare(); + obOther.Project(prMirrorAndStretch); + } + + // try to + try { + // fill this brush mip from the object 3d + AddFromObject3D_t(obOther); + + // if failed + } catch(char *strError) { + // ignore the error + (void) strError; + ASSERT(FALSE); // this should not happen + return; + } + + bm_pbrBrush->CalculateBoundingBoxesForOneMip(this); +} + +/* + * Free all memory and leave empty brush mip. + */ +void CBrushMip::Clear(void) +{ + // clear the sectors + bm_abscSectors.Clear(); +} + +/* Update bounding box from bounding boxes of all sectors. */ +void CBrushMip::UpdateBoundingBox(void) +{ + // clear the bounding box of the mip + bm_boxBoundingBox = FLOATaabbox3D(); + bm_boxRelative = FLOATaabbox3D(); + // for all sectors in the brush mip + {FOREACHINDYNAMICARRAY(bm_abscSectors, CBrushSector, itbsc) { + // discard portal-sector links to this sector + itbsc->bsc_rdOtherSidePortals.Clear(); + {FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + itbpo->bpo_rsOtherSideSectors.Clear(); + }} + // add the box of the sector to the box of mip + bm_boxBoundingBox|=itbsc->bsc_boxBoundingBox; + bm_boxRelative|=itbsc->bsc_boxRelative; + }} + + // if this brush is zoning + if (bm_pbrBrush->br_penEntity!=NULL && (bm_pbrBrush->br_penEntity->en_ulFlags&ENF_ZONING)) { + // portal links must be updated also + bm_pbrBrush->br_penEntity->en_pwoWorld->wo_bPortalLinksUpToDate = FALSE; + } +} + +/* + * Calculate bounding boxes in all sectors. + */ +void CBrushMip::CalculateBoundingBoxes(CSimpleProjection3D_DOUBLE &prBrushToAbsolute) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + // clear the bounding box of the mip + bm_boxBoundingBox = FLOATaabbox3D(); + bm_boxRelative = FLOATaabbox3D(); + // if there are no sectors + if (bm_abscSectors.Count()==0) { + // just make a small bounding box around brush center + bm_boxBoundingBox = FLOATaabbox3D( + prBrushToAbsolute.ObjectPlacementR().pl_PositionVector, + 0.01f); + bm_boxRelative = FLOATaabbox3D(FLOAT3D(0,0,0), 0.01f); + return; + } + // for all sectors in the brush mip + {FOREACHINDYNAMICARRAY(bm_abscSectors, CBrushSector, itbsc) { + // calculate bounding boxes in that sector + itbsc->CalculateBoundingBoxes(prBrushToAbsolute); + // add the box of the sector to the box of mip + bm_boxBoundingBox|=itbsc->bsc_boxBoundingBox; + bm_boxRelative|=itbsc->bsc_boxRelative; + }} +} + +/* Reoptimize all sectors in the brush mip. */ +void CBrushMip::Reoptimize(void) +{ + // create an object 3d from the source brush mip + CObject3D ob; + { // NOTE: This is in a block to destroy the selection before brush mip is cleared! + CBrushSectorSelectionForCSG selbscAll; + SelectAllSectors(selbscAll); + ToObject3D(ob, selbscAll); + } + // clear this brush mip + Clear(); + + // try to + try { + // fill this brush mip from the object 3d + AddFromObject3D_t(ob); // this will optimize the object3d first + + // if failed + } catch(char *strError) { + // ignore the error + (void) strError; + ASSERT(FALSE); // this should not happen + return; + } +} + +/* Find all portals that have no links and kill their portal flag. */ +void CBrushMip::RemoveDummyPortals(BOOL bClearPortalFlags) +{ + // for all sectors in the brush mip + {FOREACHINDYNAMICARRAY(bm_abscSectors, CBrushSector, itbsc) { + // for each portal polygon in sector + {FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + CBrushPolygon &bpo = *itbpo; + if (!(bpo.bpo_ulFlags&OPOF_PORTAL)) { + continue; + } + // find if it has at least one link in this same mip + BOOL bHasLink = FALSE; + // for all entities in the sector + {FOREACHDSTOFSRC(bpo.bpo_rsOtherSideSectors, CBrushSector, bsc_rdOtherSidePortals, pbsc) + if (pbsc->bsc_pbmBrushMip==this) { + bHasLink = TRUE; + break; + } + ENDFOR} + // if there is none + if (!bHasLink) { + // assume that it should not be portal + bpo.bpo_ulFlags&=~OPOF_PORTAL; + + // also start rendering as a wall so that user can see that + if(bClearPortalFlags) + { + bpo.bpo_ulFlags &= ~(BPOF_PASSABLE|BPOF_PORTAL); + } + bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_OPAQUE; + bpo.bpo_bppProperties.bpp_ubShadowBlend = BPT_BLEND_SHADE; + + // remove all of its links + bpo.bpo_rsOtherSideSectors.Clear(); + // world's links are not up to date anymore + bm_pbrBrush->br_penEntity->en_pwoWorld->wo_bPortalLinksUpToDate = FALSE; + } + }} + }} +} + +/* Spread all brush mips after this one. */ +void CBrushMip::SpreadFurtherMips(void) +{ + // get the brush of this mip + CBrush3D *pbr = bm_pbrBrush; + // current mip factor is the mip factor of this mip + FLOAT fMipFactor = bm_fMaxDistance; + // initially skip + BOOL bSkip = TRUE; + // for each mip in the brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, pbr->br_lhBrushMips, itbm) { + // if not skipping + if (!bSkip) { + // increase the mip factor double as far + fMipFactor*=2; + // set the mip factor + itbm->bm_fMaxDistance = fMipFactor; + } + // if it is this mip + if (this==&*itbm) { + // stop skipping + bSkip = FALSE; + } + } +} + +/* Set mip factor of this mip, spread all that are further. */ +void CBrushMip::SetMipDistance(FLOAT fMaxDistance) +{ + // set the factor + bm_fMaxDistance = fMaxDistance; + // spread all brush mips after this one + SpreadFurtherMips(); +} + +/* Get mip factor of this mip. */ +FLOAT CBrushMip::GetMipDistance(void) +{ + return bm_fMaxDistance; +} + +/* Get mip index of this mip. */ +INDEX CBrushMip::GetMipIndex(void) +{ + // get the brush of this mip + CBrush3D *pbr = bm_pbrBrush; + // count each mip in the brush + INDEX iIndex = 0; + FOREACHINLIST(CBrushMip, bm_lnInBrush, pbr->br_lhBrushMips, itbm) { + iIndex++; + // until this one + if (this==&*itbm) { + return iIndex; + } + } + ASSERT(FALSE); + return 1; +} + +// get next brush mip +CBrushMip *CBrushMip::GetNext(void) +{ + // if this is last mip + if (bm_lnInBrush.IsTail()) { + // there is no next mip + return NULL; + } + + // otherwise, return next one + return LIST_SUCC(*this, CBrushMip, bm_lnInBrush); +} + +// get previous brush mip +CBrushMip *CBrushMip::GetPrev(void) +{ + // if this is first mip + if (bm_lnInBrush.IsHead()) { + // there is no previous mip + return NULL; + } + + // otherwise, return previous one + return LIST_PRED(*this, CBrushMip, bm_lnInBrush); +} diff --git a/Sources/Engine/Brushes/BrushPolygon.cpp b/Sources/Engine/Brushes/BrushPolygon.cpp new file mode 100644 index 0000000..c1975a9 --- /dev/null +++ b/Sources/Engine/Brushes/BrushPolygon.cpp @@ -0,0 +1,517 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +template CStaticArray; +template CStaticArray; +template CStaticArray; + +// set new absolute position for the vertex +void CBrushVertex::SetAbsolutePosition(const DOUBLE3D &vAbsolute) +{ + // get its brush entity + CEntity *pen = bvx_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + if (pen==NULL) { + ASSERT(FALSE); + return; + } + // back-transform to relative coordinates + DOUBLE3D vRelative = vAbsolute-FLOATtoDOUBLE(pen->en_plPlacement.pl_PositionVector); + vRelative *= FLOATtoDOUBLE(!pen->en_mRotation); + + // remember new coordinates + bvx_vdPreciseRelative = vRelative; + bvx_vAbsolute = DOUBLEtoFLOAT(vAbsolute); + bvx_vRelative = DOUBLEtoFLOAT(vRelative); + if(bvx_pwvxWorking!=NULL) + { + bvx_pwvxWorking->wvx_vRelative = bvx_vRelative; + } +} + +/* + * Calculate bounding box of this polygon. + */ +void CBrushPolygon::CalculateBoundingBox(void) +{ + // NOTE: vertices are already transformed to absolute space + // discard portal-sector links to this polygon + extern BOOL _bDontDiscardLinks; + if (!(bpo_pbscSector->bsc_ulTempFlags&BSCTF_PRELOADEDLINKS)&&!_bDontDiscardLinks) { + bpo_rsOtherSideSectors.Clear(); + } + + // clear the bounding box + bpo_boxBoundingBox = FLOATaabbox3D(); + // for all edges in polygon + {FOREACHINSTATICARRAY(bpo_abpePolygonEdges, CBrushPolygonEdge, itbpe) { + // add the edges vertices to the bounding box + bpo_boxBoundingBox |= itbpe->bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + bpo_boxBoundingBox |= itbpe->bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + }} +} + + +/* Create a BSP polygon from this polygon. */ +void CBrushPolygon::CreateBSPPolygon(BSPPolygon &bspo) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + CBrushPolygon &brpo = *this; + + // set the plane of the bsp polygon + ((DOUBLEplane3D &)bspo) = *brpo.bpo_pbplPlane->bpl_ppldPreciseAbsolute; + bspo.bpo_ulPlaneTag = (ULONG)brpo.bpo_pbscSector->bsc_abplPlanes.Index(brpo.bpo_pbplPlane); + + // create the array of edges in the bsp polygon + INDEX ctEdges = brpo.bpo_abpePolygonEdges.Count(); + bspo.bpo_abedPolygonEdges.New(ctEdges); + + // for all edges in the polygon + bspo.bpo_abedPolygonEdges.Lock(); + {for(INDEX iEdge=0; iEdge &bed = bspo.bpo_abedPolygonEdges[iEdge]; + // create the bsp edge in the bsp polygon + brped.GetVertexCoordinatesPreciseAbsolute(bed.bed_vVertex0, bed.bed_vVertex1); + }} + bspo.bpo_abedPolygonEdges.Unlock(); +} +void CBrushPolygon::CreateBSPPolygonNonPrecise(BSPPolygon &bspo) +{ + CBrushPolygon &brpo = *this; + + // offset for epsilon testing + const DOUBLE fOffset = -0.01; + + // set the plane of the bsp polygon + ((DOUBLEplane3D &)bspo) = FLOATtoDOUBLE(brpo.bpo_pbplPlane->bpl_plAbsolute); + bspo.bpo_ulPlaneTag = (ULONG)brpo.bpo_pbscSector->bsc_abplPlanes.Index(brpo.bpo_pbplPlane); + // calculate offset for points + DOUBLE3D vOffset = FLOATtoDOUBLE(((FLOAT3D&)brpo.bpo_pbplPlane->bpl_plAbsolute))*-fOffset; + // offset the plane + bspo.Offset(fOffset); + + // create the array of edges in the bsp polygon + INDEX ctEdges = brpo.bpo_abpePolygonEdges.Count(); + bspo.bpo_abedPolygonEdges.New(ctEdges); + + // for all edges in the polygon + bspo.bpo_abedPolygonEdges.Lock(); + {for(INDEX iEdge=0; iEdge &bed = bspo.bpo_abedPolygonEdges[iEdge]; + // create the offseted bsp edge in the bsp polygon + FLOAT3D v0, v1; + brped.GetVertexCoordinatesAbsolute(v0, v1); + bed.bed_vVertex0 = FLOATtoDOUBLE(v0)+vOffset; + bed.bed_vVertex1 = FLOATtoDOUBLE(v1)+vOffset; + }} + bspo.bpo_abedPolygonEdges.Unlock(); +} + +/* + * Select adjacent polygons with same color as this one. + */ +void CBrushPolygon::SelectSimilarByColor(CBrushPolygonSelection &selbpoSimilar) +{ + // if this polygon is not selected + if (!IsSelected(BPOF_SELECTED)) { + // select this polygon + selbpoSimilar.Select(*this); + } + + // for all other unselected walls in brush mip that have same color + FOREACHINDYNAMICARRAY(bpo_pbscSector->bsc_pbmBrushMip->bm_abscSectors, CBrushSector, itbsc) { + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpoOther) { + if ((!(itbpoOther->bpo_ulFlags&BPOF_PORTAL)||(itbpoOther->bpo_ulFlags&(BPOF_TRANSLUCENT|BPOF_TRANSPARENT))) && + !itbpoOther->IsSelected(BPOF_SELECTED) && + itbpoOther->bpo_colColor == bpo_colColor) { + // if the other polygon touches this one + if (TouchesInAnySector(*itbpoOther)) { + // recursively select the other polygon + itbpoOther->SelectSimilarByColor(selbpoSimilar); + } + } + } + } +} + +/* + * Select adjacent polygons with same texture as this one. + */ +void CBrushPolygon::SelectSimilarByTexture( + CBrushPolygonSelection &selbpoSimilar, INDEX iTexture) +{ + // if this polygon is not selected + if (!IsSelected(BPOF_SELECTED)) { + // select this polygon + selbpoSimilar.Select(*this); + } + + // for all other unselected walls in brush mip that have same texture + FOREACHINDYNAMICARRAY(bpo_pbscSector->bsc_pbmBrushMip->bm_abscSectors, CBrushSector, itbsc) { + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpoOther) { + if ((!(itbpoOther->bpo_ulFlags&BPOF_PORTAL)||(itbpoOther->bpo_ulFlags&(BPOF_TRANSLUCENT|BPOF_TRANSPARENT))) && + !itbpoOther->IsSelected(BPOF_SELECTED) && + itbpoOther->bpo_abptTextures[iTexture].bpt_toTexture.GetData() + == bpo_abptTextures[iTexture].bpt_toTexture.GetData()) { + // if the other polygon touches this one + if (TouchesInAnySector(*itbpoOther)) { + // recursively select the other polygon + itbpoOther->SelectSimilarByTexture(selbpoSimilar, iTexture); + } + } + } + } +} + +/* + * Select all polygons in sector with same texture as this one. + */ +void CBrushPolygon::SelectByTextureInSector(CBrushPolygonSelection &selbpoSimilar, INDEX iTexture) +{ + // for all other unselected walls in sector that have same texture + FOREACHINSTATICARRAY(bpo_pbscSector->bsc_abpoPolygons, CBrushPolygon, itbpo) { + if ((!(itbpo->bpo_ulFlags&BPOF_PORTAL)||(itbpo->bpo_ulFlags&(BPOF_TRANSLUCENT|BPOF_TRANSPARENT)))&& + !itbpo->IsSelected(BPOF_SELECTED) && + itbpo->bpo_abptTextures[iTexture].bpt_toTexture.GetData() + == bpo_abptTextures[iTexture].bpt_toTexture.GetData()) + { + // select this polygon + selbpoSimilar.Select(*itbpo); + } + } +} + +/* + * Select all polygons in sector with same color as this one. + */ +void CBrushPolygon::SelectByColorInSector(CBrushPolygonSelection &selbpoSimilar) +{ + // for all other unselected walls in sector that have same color + FOREACHINSTATICARRAY(bpo_pbscSector->bsc_abpoPolygons, CBrushPolygon, itbpo) { + if ((!(itbpo->bpo_ulFlags&BPOF_PORTAL)||(itbpo->bpo_ulFlags&(BPOF_TRANSLUCENT|BPOF_TRANSPARENT))) && + !itbpo->IsSelected(BPOF_SELECTED) && + itbpo->bpo_colColor == bpo_colColor) + { + // select this polygon + selbpoSimilar.Select(*itbpo); + } + } +} + +/* Clear the object. */ +void CBrushPolygon::Clear(void) +{ + bpo_abpePolygonEdges.Clear(); + bpo_smShadowMap.Clear(); + bpo_abptTextures[0].Clear(); + bpo_abptTextures[1].Clear(); + bpo_abptTextures[2].Clear(); + DiscardShadingInfos(); +}; +// discard all cached shading info for models +void CBrushPolygon::DiscardShadingInfos(void) +{ + FORDELETELIST( CShadingInfo, si_lnInPolygon, bpo_lhShadingInfos, itsi) { + itsi->si_penEntity->en_ulFlags &= ~ENF_VALIDSHADINGINFO; + itsi->si_lnInPolygon.Remove(); + itsi->si_pbpoPolygon = NULL; + } +} + +/* + * Copy polygon within same sector. + */ +void CBrushPolygon::CopyFromSameSector(CBrushPolygon &bpoOriginal) +{ + // copy simple data + bpo_pbplPlane = bpoOriginal.bpo_pbplPlane; + bpo_colColor = bpoOriginal.bpo_colColor; + bpo_ulFlags = bpoOriginal.bpo_ulFlags; + BOOL bCopyMapping = TRUE; + bpo_abptTextures[0].CopyTextureProperties( bpoOriginal.bpo_abptTextures[0], bCopyMapping); + bpo_abptTextures[1].CopyTextureProperties( bpoOriginal.bpo_abptTextures[1], bCopyMapping); + bpo_abptTextures[2].CopyTextureProperties( bpoOriginal.bpo_abptTextures[2], bCopyMapping); + bpo_mdShadow = bpoOriginal.bpo_mdShadow; + bpo_pbscSector = bpoOriginal.bpo_pbscSector; + + // copy all edges + bpo_abpePolygonEdges = bpoOriginal.bpo_abpePolygonEdges; +} + +/* Copy polygon properties */ +CBrushPolygon &CBrushPolygon::CopyProperties(CBrushPolygon &bpoOther, BOOL bCopyMapping) { + bpo_ulFlags &= ~BPOF_MASK_FOR_COPYING; + bpo_ulFlags |= (bpoOther.bpo_ulFlags&BPOF_MASK_FOR_COPYING); + bpo_bppProperties = bpoOther.bpo_bppProperties; + bpo_colShadow = bpoOther.bpo_colShadow; + bpo_abptTextures[0].CopyTextureProperties( bpoOther.bpo_abptTextures[0], bCopyMapping); + bpo_abptTextures[1].CopyTextureProperties( bpoOther.bpo_abptTextures[1], bCopyMapping); + bpo_abptTextures[2].CopyTextureProperties( bpoOther.bpo_abptTextures[2], bCopyMapping); + return *this; +}; + +/* Copy polygon properties without texture */ +CBrushPolygon &CBrushPolygon::CopyPropertiesWithoutTexture(CBrushPolygon &bpoOther) { + bpo_ulFlags &= ~BPOF_MASK_FOR_COPYING; + bpo_ulFlags |= (bpoOther.bpo_ulFlags&BPOF_MASK_FOR_COPYING); + bpo_bppProperties = bpoOther.bpo_bppProperties; + bpo_colShadow = bpoOther.bpo_colShadow; + return *this; +}; + +/* Copy polygon's textures */ +CBrushPolygon &CBrushPolygon::CopyTextures(CBrushPolygon &bpoOther) { + bpo_abptTextures[0].CopyTextureProperties( bpoOther.bpo_abptTextures[0], TRUE); + bpo_abptTextures[1].CopyTextureProperties( bpoOther.bpo_abptTextures[1], TRUE); + bpo_abptTextures[2].CopyTextureProperties( bpoOther.bpo_abptTextures[2], TRUE); + return *this; +}; + +/* + * Calculate area of the polygon. + */ +DOUBLE CBrushPolygon::CalculateArea(void) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + DOUBLE3D vArea = DOUBLE3D(0.0, 0.0, 0.0); + // for each polygon edge + {FOREACHINSTATICARRAY(bpo_abpePolygonEdges, CBrushPolygonEdge, itbpe) { + DOUBLE3D v0, v1; + itbpe->GetVertexCoordinatesPreciseRelative(v0, v1); + // add the area of triangle that the edge closes with the origin + vArea += v0*v1; + }} + return ( ((DOUBLE3D&)bpo_pbplPlane->bpl_pldPreciseRelative)%vArea ) / 2.0; +} + +// move edges from another polygon into this one +void CBrushPolygon::MovePolygonEdges(CBrushPolygon &bpoSource) +{ + ASSERT(bpo_pbplPlane==bpoSource.bpo_pbplPlane); + INDEX ctEdgesThis = bpo_abpePolygonEdges.Count(); + INDEX ctEdgesSource = bpoSource.bpo_abpePolygonEdges.Count(); + // create an array to hold all edges + CStaticArray abpeNew; + abpeNew.New(ctEdgesThis+ctEdgesSource); + INDEX ibpeNew = 0; + // copy edges of this polygon + {for(INDEX ibpeThis=0; ibpeThisbvx_vRelative-bed_pbvxVertex1->bvx_vRelative).Length(); + FLOAT fB0B1 = (bedOther.bed_pbvxVertex0->bvx_vRelative-bedOther.bed_pbvxVertex1->bvx_vRelative).Length(); + FLOAT fA0B0 = (bed_pbvxVertex0->bvx_vRelative-bedOther.bed_pbvxVertex0->bvx_vRelative).Length(); + FLOAT fA0B1 = (bed_pbvxVertex0->bvx_vRelative-bedOther.bed_pbvxVertex1->bvx_vRelative).Length(); + FLOAT fA1B0 = (bed_pbvxVertex1->bvx_vRelative-bedOther.bed_pbvxVertex0->bvx_vRelative).Length(); + FLOAT fA1B1 = (bed_pbvxVertex1->bvx_vRelative-bedOther.bed_pbvxVertex1->bvx_vRelative).Length(); + FLOAT fB0A0 = (bedOther.bed_pbvxVertex0->bvx_vRelative-bed_pbvxVertex0->bvx_vRelative).Length(); + FLOAT fB0A1 = (bedOther.bed_pbvxVertex0->bvx_vRelative-bed_pbvxVertex1->bvx_vRelative).Length(); + FLOAT fB1A0 = (bedOther.bed_pbvxVertex1->bvx_vRelative-bed_pbvxVertex0->bvx_vRelative).Length(); + FLOAT fB1A1 = (bedOther.bed_pbvxVertex1->bvx_vRelative-bed_pbvxVertex1->bvx_vRelative).Length(); + + return + Abs(fB0B1-fA0B0-fA0B1)bvx_vRelative==bedOther.bed_pbvxVertex0->bvx_vRelative || + bed_pbvxVertex0->bvx_vRelative==bedOther.bed_pbvxVertex1->bvx_vRelative || + bed_pbvxVertex1->bvx_vRelative==bedOther.bed_pbvxVertex0->bvx_vRelative || + bed_pbvxVertex1->bvx_vRelative==bedOther.bed_pbvxVertex1->bvx_vRelative) { + return TRUE; + // if they have no common vertices + } else if( !wed_bIgnoreTJunctions) { + // test if some vertex is on the other edge + FLOAT fA0A1 = (bed_pbvxVertex0->bvx_vRelative-bed_pbvxVertex1->bvx_vRelative).Length(); + FLOAT fB0B1 = (bedOther.bed_pbvxVertex0->bvx_vRelative-bedOther.bed_pbvxVertex1->bvx_vRelative).Length(); + FLOAT fA0B0 = (bed_pbvxVertex0->bvx_vRelative-bedOther.bed_pbvxVertex0->bvx_vRelative).Length(); + FLOAT fA0B1 = (bed_pbvxVertex0->bvx_vRelative-bedOther.bed_pbvxVertex1->bvx_vRelative).Length(); + FLOAT fA1B0 = (bed_pbvxVertex1->bvx_vRelative-bedOther.bed_pbvxVertex0->bvx_vRelative).Length(); + FLOAT fA1B1 = (bed_pbvxVertex1->bvx_vRelative-bedOther.bed_pbvxVertex1->bvx_vRelative).Length(); + FLOAT fB0A0 = (bedOther.bed_pbvxVertex0->bvx_vRelative-bed_pbvxVertex0->bvx_vRelative).Length(); + FLOAT fB0A1 = (bedOther.bed_pbvxVertex0->bvx_vRelative-bed_pbvxVertex1->bvx_vRelative).Length(); + FLOAT fB1A0 = (bedOther.bed_pbvxVertex1->bvx_vRelative-bed_pbvxVertex0->bvx_vRelative).Length(); + FLOAT fB1A1 = (bedOther.bed_pbvxVertex1->bvx_vRelative-bed_pbvxVertex1->bvx_vRelative).Length(); + + return + Abs(fB0B1-fA0B0-fA0B1)bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + const FLOAT3D &vB = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + // compute general vectors needed + FLOAT3D vAC = vC-vA; + FLOAT3D vAB = vB-vA; + // get parameter of the P - orthogonal projection of C onto AB + FLOAT fR = (vAC%vAB)/(vAB%vAB); + FLOAT fD2 = 0.0f; + // if before A + if (fR<0) { + // get squared distance AC + fD2 = vAC%vAC; + // if after B + } else if (fR>1) { + // get squared distance BC + FLOAT3D vBC = vC-vB; + fD2 = vBC%vBC; + // if between + } else { + // find PC + FLOAT3D vBC = vC-vB; + FLOAT3D vPC = vAC+(vBC-vAC)*fR; + // get squared distance PC + fD2 = vPC%vPC; + } + // update minimal squared distance + if (fD2 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//template CDynamicArray; + +CBrushSector::CBrushSector(const CBrushSector &c) +: bsc_bspBSPTree(*new DOUBLEbsptree3D) +{ + ASSERT(FALSE); +}; + +CBrushSector &CBrushSector::operator=(const CBrushSector &c) +{ + ASSERT(FALSE); + return *this; +}; + +extern void AssureFPT_53(void); + +/* Default constructor. */ +CBrushSector::CBrushSector(void) +: bsc_ulFlags(0) +, bsc_ulFlags2(0) +, bsc_ulTempFlags(0) +, bsc_ulVisFlags(0) +, bsc_strName("") +, bsc_bspBSPTree(*new DOUBLEbsptree3D) +{ + +}; +CBrushSector::~CBrushSector(void) +{ + delete &bsc_bspBSPTree; +} + +/* + * Calculate bounding boxs of polygons in this sector. + */ +void CBrushSector::CalculateBoundingBoxes(CSimpleProjection3D_DOUBLE &prRelativeToAbsolute) +{ + // assure that floating point precision is 53 bits + AssureFPT_53(); + + // discard portal-sector links to this sector + extern BOOL _bDontDiscardLinks; + if (!(bsc_ulTempFlags&BSCTF_PRELOADEDLINKS) && !_bDontDiscardLinks) { + bsc_rdOtherSidePortals.Clear(); + } + + // create an array of precise vertices in absolute space + CStaticArray avdAbsoluteVertices; + avdAbsoluteVertices.New(bsc_abvxVertices.Count()); + bsc_boxRelative = FLOATaabbox3D(); + + // for each vertex in sector + for(INDEX ivx=0; ivx apldAbsolutePlanes; + apldAbsolutePlanes.New(bsc_abplPlanes.Count()); + + // for each plane in sector + for(INDEX ipl=0; iplCalculateBoundingBox(); + // add the polygon's bounding box to sector's bounding box + bsc_boxBoundingBox |= itbpo->bpo_boxBoundingBox; + }} + + // if the bsp tree is not preloaded + if (!(bsc_ulTempFlags&BSCTF_PRELOADEDBSP)) { + // clear BSP tree of the sector + bsc_bspBSPTree.Destroy(); + // if the brush is zoning or field + CEntity *pen = bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + if (pen!=NULL && + ((pen->en_ulFlags&ENF_ZONING) || pen->en_RenderType==CEntity::RT_FIELDBRUSH) ) { + // create an array of bsp polygons for sector polygons + INDEX ctPolygons = bsc_abpoPolygons.Count(); + CDynamicArray< BSPPolygon > arbpoPolygons; + arbpoPolygons.New(ctPolygons); + + // for all polygons in this sector + arbpoPolygons.Lock(); + {for(INDEX iPolygon=0; iPolygon &bspo = arbpoPolygons[iPolygon]; + brpo.CreateBSPPolygon(bspo); + }} + arbpoPolygons.Unlock(); + + // create the bsp tree from the bsp polygons + bsc_bspBSPTree.Create(arbpoPolygons); + } + } + // clear preloading flags + bsc_ulTempFlags&=~BSCTF_PRELOADEDBSP; + bsc_ulTempFlags&=~BSCTF_PRELOADEDLINKS; + +// if in debug version +#ifndef NDEBUG + // for each vertex in sector + {for(INDEX ivx=0; ivxbpo_smShadowMap.Uncache(); + }} +} +/* Find and remember all entities in this sector. */ +void CBrushSector::FindEntitiesInSector(void) +{ + // assure that floating point precision is 53 bits + CSetFPUPrecision sfp(FPT_53BIT); + + // get the entity of this sector's brush + CEntity *penEntity = bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + // if the brush entity is not zoning + if (penEntity==NULL || !(penEntity->en_ulFlags&ENF_ZONING)) { + // do nothing + return; + } + + // unset spatial clasification + bsc_rsEntities.Clear(); + + // remember sectors obbox + FLOATobbox3D boxSector(bsc_boxBoundingBox); + + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(penEntity->en_pwoWorld->wo_cenEntities, CEntity, iten) { + // if not in spatial clasification + if (iten->en_fSpatialClassificationRadius<0) { + // skip it + continue; + } + // get bounding sphere + FLOAT fSphereRadius = iten->en_fSpatialClassificationRadius; + const FLOAT3D &vSphereCenter = iten->en_plPlacement.pl_PositionVector; + // if the sector's bounding box has contact with the sphere + if(bsc_boxBoundingBox.TouchesSphere(vSphereCenter, fSphereRadius)) { + + // if the sphere is inside the sector + if (bsc_bspBSPTree.TestSphere( + FLOATtoDOUBLE(vSphereCenter), FLOATtoDOUBLE(fSphereRadius))>=0) { + // make oriented bounding box of the entity + FLOATobbox3D boxEntity(iten->en_boxSpatialClassification, + iten->en_plPlacement.pl_PositionVector, iten->en_mRotation); + + // if the box is inside the sector + if (boxSector.HasContactWith(boxEntity) && + bsc_bspBSPTree.TestBox(FLOATtoDOUBLE(boxEntity))>=0) { + // relate the entity to the sector + if (iten->en_RenderType==CEntity::RT_BRUSH + ||iten->en_RenderType==CEntity::RT_FIELDBRUSH + ||iten->en_RenderType==CEntity::RT_TERRAIN) { // brushes first + AddRelationPairHeadHead(bsc_rsEntities, iten->en_rdSectors); + } else { + AddRelationPairTailTail(bsc_rsEntities, iten->en_rdSectors); + } + } + } + } + }} +} + +/* + * Clear the object. + */ +void CBrushSector::Clear(void) +{ + bsc_abvxVertices.Clear(); + bsc_awvxVertices.Clear(); + bsc_abedEdges.Clear(); + bsc_awedEdges.Clear(); + bsc_abplPlanes.Clear(); + bsc_awplPlanes.Clear(); + bsc_abpoPolygons.Clear(); + bsc_rdOtherSidePortals.Clear(); + bsc_rsEntities.Clear(); + bsc_strName.Clear(); +// bsc_bspBSPTree.Destroy(); +} + +/* + * Lock all arrays. + */ +void CBrushSector::LockAll(void) +{ + /* this function does nothing, because in current implementation all + arrays in brush sector are static arrays + */ +} + +/* + * Unlock all arrays. + */ +void CBrushSector::UnlockAll(void) +{ + /* this function does nothing, because in current implementation all + arrays in brush sector are static arrays + */ +} + +/* + * Calculate volume of the sector (all polygons must be triangularized). + */ +DOUBLE CBrushSector::CalculateVolume(void) +{ + // assure that floating point precision is 53 bits + AssureFPT_53(); + + DOUBLE fSectorVolume = 0.0; + // for each polygon + {FOREACHINSTATICARRAY(bsc_abpoPolygons, CBrushPolygon, itbpo) { + // calculate the area of the polygon + DOUBLE fPolygonArea = itbpo->CalculateArea(); + // add the volume of the pyramid that the polygon closes with origin + fSectorVolume += fPolygonArea * itbpo->bpo_pbplPlane->bpl_pldPreciseRelative.Distance() / 3.0; + }} + + // if the volume is positive + if (fSectorVolume>=0.0) { + // remember that the sector is open + bsc_ulFlags |= BSCF_OPENSECTOR; + // if the sector belongs to a field brush + CBrush3D *pbr = bsc_pbmBrushMip->bm_pbrBrush; + ASSERT(pbr!=NULL); + if (pbr->br_pfsFieldSettings!=NULL) { + // report a warning + CPrintF("Warning: Open sector in a field brush!\n"); + } + // if the volume is negative + } else { + // remember that the sector is closed + bsc_ulFlags &= ~BSCF_OPENSECTOR; + } + Triangulate(); + return fSectorVolume; +} +void CBrushSector::Triangulate(void) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_TRIANGULATE); + // for each polygon + {FOREACHINSTATICARRAY(bsc_abpoPolygons, CBrushPolygon, itbpo) { + itbpo->Triangulate(); + }} + + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_TRIANGULATE); +} +// update changed sector's data after dragging vertices or importing +void CBrushSector::UpdateSector(void) +{ + // calculate the bounding box of the brush sector + CSimpleProjection3D_DOUBLE prBrushToAbsolute; + bsc_pbmBrushMip->bm_pbrBrush->PrepareRelativeToAbsoluteProjection(prBrushToAbsolute); + CalculateBoundingBoxes(prBrushToAbsolute); + // calculate the volume of the sector + CalculateVolume(); + + // for each polygon + INDEX ctPolygons = bsc_abpoPolygons.Count(); + {for(INDEX iPolygon=0; iPolygonbm_pbrBrush->br_penEntity->en_pwoWorld; + pwo->ClearMarkedForUseFlag(); + + pbpo->bpo_ulFlags |= BPOF_MARKED_FOR_USE; + TriangularizeMarkedPolygons(); + UpdateVertexChanges(); +} + +// Triangularize polygons that continin vertices from selection +void CBrushSector::TriangularizeForVertices( CBrushVertexSelection &selVertex) +{ + // clear marked for use flag on all polygons in world + CWorld *pwo=bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->en_pwoWorld; + pwo->ClearMarkedForUseFlag(); + + // ---------- Mark polygons in this sector that contain any of the selected vertices + // for all polygons in this sector + {FOREACHINSTATICARRAY(bsc_abpoPolygons, CBrushPolygon, itbpo) + { + // if polygon is already marked for triangularization + if( itbpo->bpo_ulFlags & BPOF_MARKED_FOR_USE) + { + // no need to test it again + continue; + } + // if this polygon is triangle + if( itbpo->bpo_aiTriangleElements.Count() == 3) + { + // skip it + continue; + } + // for all vertices in this polygon + {FOREACHINSTATICARRAY(itbpo->bpo_apbvxTriangleVertices, CBrushVertex *, itpbvx) + { + // if any of polygon's vertices is selected + if( (*itpbvx)->bvx_ulFlags&BVXF_SELECTED) + { + // mark for triangularized + itbpo->bpo_ulFlags |= BPOF_MARKED_FOR_USE; + // no need to test other vertices in this polygon + break; + } + }} + }} + + // triangularize marked polygons + TriangularizeMarkedPolygons(); +} + +void CBrushSector::TriangularizeMarkedPolygons( void) +{ + // for marked polygons: count how many there are and how many new triangles will be created + INDEX ctPolygonsToRemove = 0; + INDEX ctNewTriangles = 0; + + // for all polygons in this sector + {FOREACHINSTATICARRAY(bsc_abpoPolygons, CBrushPolygon, itbpo) + { + // if this polygon is triangle + if( itbpo->bpo_aiTriangleElements.Count() == 3) + { + // skip it + continue; + } + // if polygon is already marked for triangularization + if( itbpo->bpo_ulFlags & BPOF_MARKED_FOR_USE) + { + // count polygon + ctPolygonsToRemove++; + // and its triangles + ctNewTriangles+=itbpo->bpo_aiTriangleElements.Count()/3; + } + }} + + // if all marked polygons are already triangularized + if( ctPolygonsToRemove == 0) + { + // don't do anything + return; + } + + // create new edge and polygon arrays + CStaticArray abedEdgesNew; + CStaticArray abpoPolygonsNew; + + INDEX ctOldEdges = bsc_abedEdges.Count(); + INDEX ctOldPolygons = bsc_abpoPolygons.Count(); + + abedEdgesNew.New( ctOldEdges+ctNewTriangles*3); + abpoPolygonsNew.New( ctOldPolygons-ctPolygonsToRemove+ctNewTriangles); + + // copy old edges to new edge array + INDEX iEdge; + for( iEdge=0; iEdgebpo_ulFlags & BPOF_MARKED_FOR_USE)) + { + CBrushPolygon &bpoNew = abpoPolygonsNew[ iNewPolygons]; + // copy the old polygon + bpoNew.bpo_pbplPlane = itbpo->bpo_pbplPlane; + + bpoNew.bpo_abptTextures[0].CopyTextureProperties( itbpo->bpo_abptTextures[0], TRUE); + bpoNew.bpo_abptTextures[1].CopyTextureProperties( itbpo->bpo_abptTextures[1], TRUE); + bpoNew.bpo_abptTextures[2].CopyTextureProperties( itbpo->bpo_abptTextures[2], TRUE); + + bpoNew.bpo_colColor = itbpo->bpo_colColor; + bpoNew.bpo_ulFlags = itbpo->bpo_ulFlags & ~(BPOF_MARKED_FOR_USE|BPOF_SELECTED); + bpoNew.bpo_colShadow = itbpo->bpo_colShadow; + bpoNew.bpo_bppProperties = itbpo->bpo_bppProperties; + bpoNew.bpo_pbscSector = itbpo->bpo_pbscSector; + + // remap brush polygon edges to point to edges of new array + INDEX ctEdgesToRemap = itbpo->bpo_abpePolygonEdges.Count(); + // allocate new polygon edges + bpoNew.bpo_abpePolygonEdges.New(ctEdgesToRemap); + // for each edge in polygon + for( INDEX iRemapEdge=0; iRemapEdgebpo_abpePolygonEdges[iRemapEdge]; + CBrushPolygonEdge &bpeNew = bpoNew.bpo_abpePolygonEdges[iRemapEdge]; + + // get index of the edge for old edge array + INDEX iOldIndex = bsc_abedEdges.Index( bpeOld.bpe_pbedEdge); + + // use same index, but point to edge in new edge array + bpeNew.bpe_pbedEdge = &abedEdgesNew[iOldIndex]; + // set edge direction + bpeNew.bpe_bReverse = bpeOld.bpe_bReverse; + } + + bpoNew.bpo_apbvxTriangleVertices = bpoOld.bpo_apbvxTriangleVertices; + bpoNew.bpo_aiTriangleElements = bpoOld.bpo_aiTriangleElements; + + // initialize shadow map + bpoNew.InitializeShadowMap(); + + iNewPolygons++; + } + // if polygon is marked for triangularization + else + { + INDEX ctTriangles = itbpo->bpo_aiTriangleElements.Count()/3; + // for each triangle in old polygon + for( INDEX iTriangle=0; iTrianglebpo_aiTriangleElements[iTriangle*3+0]; + INDEX iVtx1 = itbpo->bpo_aiTriangleElements[iTriangle*3+1]; + INDEX iVtx2 = itbpo->bpo_aiTriangleElements[iTriangle*3+2]; + + CBrushVertex *pbvtx0 = itbpo->bpo_apbvxTriangleVertices[ iVtx0]; + CBrushVertex *pbvtx1 = itbpo->bpo_apbvxTriangleVertices[ iVtx1]; + CBrushVertex *pbvtx2 = itbpo->bpo_apbvxTriangleVertices[ iVtx2]; + + // setup edge 0 + abedEdgesNew[iEdge+0].bed_pbvxVertex0 = pbvtx0; + abedEdgesNew[iEdge+0].bed_pbvxVertex1 = pbvtx1; + + // setup edge 1 + abedEdgesNew[iEdge+1].bed_pbvxVertex0 = pbvtx1; + abedEdgesNew[iEdge+1].bed_pbvxVertex1 = pbvtx2; + + // setup edge 2 + abedEdgesNew[iEdge+2].bed_pbvxVertex0 = pbvtx2; + abedEdgesNew[iEdge+2].bed_pbvxVertex1 = pbvtx0; + + // allocate and set polygon edges for new triangle + bpoNew.bpo_abpePolygonEdges.New(3); + bpoNew.bpo_abpePolygonEdges[0].bpe_pbedEdge = &abedEdgesNew[iEdge+0]; + bpoNew.bpo_abpePolygonEdges[0].bpe_bReverse = FALSE; + bpoNew.bpo_abpePolygonEdges[1].bpe_pbedEdge = &abedEdgesNew[iEdge+1]; + bpoNew.bpo_abpePolygonEdges[1].bpe_bReverse = FALSE; + bpoNew.bpo_abpePolygonEdges[2].bpe_pbedEdge = &abedEdgesNew[iEdge+2]; + bpoNew.bpo_abpePolygonEdges[2].bpe_bReverse = FALSE; + + CBrushEdge &edg0 = *bpoNew.bpo_abpePolygonEdges[0].bpe_pbedEdge; + CBrushEdge &edg1 = *bpoNew.bpo_abpePolygonEdges[1].bpe_pbedEdge; + CBrushEdge &edg2 = *bpoNew.bpo_abpePolygonEdges[2].bpe_pbedEdge; + + // set brush vertex ptrs + bpoNew.bpo_apbvxTriangleVertices.New(3); + bpoNew.bpo_apbvxTriangleVertices[0] = pbvtx0; + bpoNew.bpo_apbvxTriangleVertices[1] = pbvtx1; + bpoNew.bpo_apbvxTriangleVertices[2] = pbvtx2; + + // setup fixed trinagle element indices + bpoNew.bpo_aiTriangleElements.New(3); + bpoNew.bpo_aiTriangleElements[0] = 0; + bpoNew.bpo_aiTriangleElements[1] = 1; + bpoNew.bpo_aiTriangleElements[2] = 2; + + // copy parameters from old polygon + bpoNew.bpo_pbplPlane = itbpo->bpo_pbplPlane; + + bpoNew.bpo_abptTextures[0].CopyTextureProperties( itbpo->bpo_abptTextures[0], TRUE); + bpoNew.bpo_abptTextures[1].CopyTextureProperties( itbpo->bpo_abptTextures[1], TRUE); + bpoNew.bpo_abptTextures[2].CopyTextureProperties( itbpo->bpo_abptTextures[2], TRUE); + + bpoNew.bpo_colColor = itbpo->bpo_colColor; + bpoNew.bpo_ulFlags = itbpo->bpo_ulFlags & ~(BPOF_MARKED_FOR_USE|BPOF_SELECTED); + bpoNew.bpo_colShadow = itbpo->bpo_colShadow; + bpoNew.bpo_bppProperties = itbpo->bpo_bppProperties; + bpoNew.bpo_pbscSector = itbpo->bpo_pbscSector; + + // initialize shadow map + bpoNew.InitializeShadowMap(); + + // skip created edges + iEdge+=3; + // next triangle + iNewPolygons++; + } + } + }} + + // copy new arrays over old ones + bsc_abedEdges.MoveArray( abedEdgesNew); + bsc_abpoPolygons.MoveArray( abpoPolygonsNew); + + // create array of working edges + INDEX cted = bsc_abedEdges.Count(); + bsc_awedEdges.Clear(); + bsc_awedEdges.New(cted); + // for each edge + for (INDEX ied=0; iedSetAbsolutePosition( FLOATtoDOUBLE(vVertex)); +} + +void CBrushSector::SubdivideTriangles( CBrushPolygonSelection &selPolygon) +{ + INDEX ctPolygonsToRemove = selPolygon.Count(); + INDEX ctNewTriangles = ctPolygonsToRemove*3; + + // clear marked for use flag on all polygons in world + CWorld *pwo=bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->en_pwoWorld; + pwo->ClearMarkedForUseFlag(); + + // for all polygons in selection + {FOREACHINDYNAMICCONTAINER(selPolygon, CBrushPolygon, itbpo) + { + // mark them for use + itbpo->bpo_ulFlags |= BPOF_MARKED_FOR_USE; + if( itbpo->bpo_aiTriangleElements.Count() != 3) + { + return; + } + }} + + // clear the selection + selPolygon.Clear(); + + // create new arrays + CStaticArray awvxVerticesNew; + CStaticArray abvxVerticesNew; + CStaticArray abedEdgesNew; + CStaticArray abpoPolygonsNew; + + INDEX ctOldVertices = bsc_abvxVertices.Count(); + INDEX ctOldEdges = bsc_abedEdges.Count(); + INDEX ctOldPolygons = bsc_abpoPolygons.Count(); + + // allocate arrays + abvxVerticesNew.New( ctOldVertices+ctPolygonsToRemove); + awvxVerticesNew.New( ctOldVertices+ctPolygonsToRemove); + abedEdgesNew.New( ctOldEdges+ctPolygonsToRemove*6); + abpoPolygonsNew.New( ctOldPolygons-ctPolygonsToRemove+ctNewTriangles); + + // copy old vertices to new vertex array + INDEX iVtx; + for( iVtx=0; iVtxbpo_ulFlags & BPOF_MARKED_FOR_USE)) + { + // copy the old polygon + CBrushPolygon &bpoNew = abpoPolygonsNew[ iNewPolygons]; + bpoNew.bpo_pbplPlane = bpoOld.bpo_pbplPlane; + + bpoNew.bpo_abptTextures[0].CopyTextureProperties( bpoOld.bpo_abptTextures[0], TRUE); + bpoNew.bpo_abptTextures[1].CopyTextureProperties( bpoOld.bpo_abptTextures[1], TRUE); + bpoNew.bpo_abptTextures[2].CopyTextureProperties( bpoOld.bpo_abptTextures[2], TRUE); + + bpoNew.bpo_colColor = bpoOld.bpo_colColor; + bpoNew.bpo_ulFlags = bpoOld.bpo_ulFlags & ~(BPOF_MARKED_FOR_USE|BPOF_SELECTED); + bpoNew.bpo_colShadow = bpoOld.bpo_colShadow; + bpoNew.bpo_bppProperties = bpoOld.bpo_bppProperties; + bpoNew.bpo_pbscSector = bpoOld.bpo_pbscSector; + + // remap brush polygon edges to point to edges of new array + INDEX ctEdgesToRemap = bpoOld.bpo_abpePolygonEdges.Count(); + // allocate new polygon edges + bpoNew.bpo_abpePolygonEdges.New(ctEdgesToRemap); + // for each edge in polygon + for( INDEX iRemapEdge=0; iRemapEdgebvx_pbscSector = this; + + // calculate and set middle point of the triangle + DOUBLE3D vCenter = FLOATtoDOUBLE( + pbvtx0->bvx_vAbsolute + + pbvtx1->bvx_vAbsolute + + pbvtx2->bvx_vAbsolute)/3.0; + pbvtx3->SetAbsolutePosition( vCenter); + + // add new edges + // setup edge 0 (copy of old edge) + abedEdgesNew[iEdge+0].bed_pbvxVertex0 = pbvtx0; + abedEdgesNew[iEdge+0].bed_pbvxVertex1 = pbvtx1; + // setup edge 1 (copy of old edge) + abedEdgesNew[iEdge+1].bed_pbvxVertex0 = pbvtx1; + abedEdgesNew[iEdge+1].bed_pbvxVertex1 = pbvtx2; + // setup edge 2 (copy of old edge) + abedEdgesNew[iEdge+2].bed_pbvxVertex0 = pbvtx2; + abedEdgesNew[iEdge+2].bed_pbvxVertex1 = pbvtx0; + // setup edge 3 + abedEdgesNew[iEdge+3].bed_pbvxVertex0 = pbvtx0; + abedEdgesNew[iEdge+3].bed_pbvxVertex1 = pbvtx3; + // setup edge 4 + abedEdgesNew[iEdge+4].bed_pbvxVertex0 = pbvtx1; + abedEdgesNew[iEdge+4].bed_pbvxVertex1 = pbvtx3; + // setup edge 5 + abedEdgesNew[iEdge+5].bed_pbvxVertex0 = pbvtx2; + abedEdgesNew[iEdge+5].bed_pbvxVertex1 = pbvtx3; + + // ---------------- Create first sub-triangle + CBrushPolygon &bpoNew1 = abpoPolygonsNew[ iNewPolygons+0]; + // allocate and set polygon edges + bpoNew1.bpo_abpePolygonEdges.New(3); + bpoNew1.bpo_abpePolygonEdges[0].bpe_pbedEdge = &abedEdgesNew[iEdge+0]; + bpoNew1.bpo_abpePolygonEdges[0].bpe_bReverse = FALSE; + bpoNew1.bpo_abpePolygonEdges[1].bpe_pbedEdge = &abedEdgesNew[iEdge+4]; + bpoNew1.bpo_abpePolygonEdges[1].bpe_bReverse = FALSE; + bpoNew1.bpo_abpePolygonEdges[2].bpe_pbedEdge = &abedEdgesNew[iEdge+3]; + bpoNew1.bpo_abpePolygonEdges[2].bpe_bReverse = TRUE; + + // set brush vertex ptrs + bpoNew1.bpo_apbvxTriangleVertices.New(3); + bpoNew1.bpo_apbvxTriangleVertices[0] = pbvtx0; + bpoNew1.bpo_apbvxTriangleVertices[1] = pbvtx1; + bpoNew1.bpo_apbvxTriangleVertices[2] = pbvtx3; + + // setup fixed trinagle element indices + bpoNew1.bpo_aiTriangleElements.New(3); + bpoNew1.bpo_aiTriangleElements[0] = 0; + bpoNew1.bpo_aiTriangleElements[1] = 1; + bpoNew1.bpo_aiTriangleElements[2] = 2; + + // copy parameters from old polygon + bpoNew1.bpo_pbplPlane = bpoOld.bpo_pbplPlane; + bpoNew1.bpo_abptTextures[0].CopyTextureProperties( bpoOld.bpo_abptTextures[0], TRUE); + bpoNew1.bpo_abptTextures[1].CopyTextureProperties( bpoOld.bpo_abptTextures[1], TRUE); + bpoNew1.bpo_abptTextures[2].CopyTextureProperties( bpoOld.bpo_abptTextures[2], TRUE); + bpoNew1.bpo_colColor = bpoOld.bpo_colColor; + bpoNew1.bpo_ulFlags = bpoOld.bpo_ulFlags & ~(BPOF_MARKED_FOR_USE|BPOF_SELECTED); + bpoNew1.bpo_colShadow = bpoOld.bpo_colShadow; + bpoNew1.bpo_bppProperties = bpoOld.bpo_bppProperties; + bpoNew1.bpo_pbscSector = bpoOld.bpo_pbscSector; + + // initialize shadow map + bpoNew1.InitializeShadowMap(); + + // ---------------- Create second sub-triangle + CBrushPolygon &bpoNew2 = abpoPolygonsNew[ iNewPolygons+1]; + // allocate and set polygon edges + bpoNew2.bpo_abpePolygonEdges.New(3); + bpoNew2.bpo_abpePolygonEdges[0].bpe_pbedEdge = &abedEdgesNew[iEdge+1]; + bpoNew2.bpo_abpePolygonEdges[0].bpe_bReverse = FALSE; + bpoNew2.bpo_abpePolygonEdges[1].bpe_pbedEdge = &abedEdgesNew[iEdge+5]; + bpoNew2.bpo_abpePolygonEdges[1].bpe_bReverse = FALSE; + bpoNew2.bpo_abpePolygonEdges[2].bpe_pbedEdge = &abedEdgesNew[iEdge+4]; + bpoNew2.bpo_abpePolygonEdges[2].bpe_bReverse = TRUE; + + // set brush vertex ptrs + bpoNew2.bpo_apbvxTriangleVertices.New(3); + bpoNew2.bpo_apbvxTriangleVertices[0] = pbvtx1; + bpoNew2.bpo_apbvxTriangleVertices[1] = pbvtx2; + bpoNew2.bpo_apbvxTriangleVertices[2] = pbvtx3; + + // setup fixed trinagle element indices + bpoNew2.bpo_aiTriangleElements.New(3); + bpoNew2.bpo_aiTriangleElements[0] = 0; + bpoNew2.bpo_aiTriangleElements[1] = 1; + bpoNew2.bpo_aiTriangleElements[2] = 2; + + // copy parameters from old polygon + bpoNew2.bpo_pbplPlane = bpoOld.bpo_pbplPlane; + bpoNew2.bpo_abptTextures[0].CopyTextureProperties( bpoOld.bpo_abptTextures[0], TRUE); + bpoNew2.bpo_abptTextures[1].CopyTextureProperties( bpoOld.bpo_abptTextures[1], TRUE); + bpoNew2.bpo_abptTextures[2].CopyTextureProperties( bpoOld.bpo_abptTextures[2], TRUE); + bpoNew2.bpo_colColor = bpoOld.bpo_colColor; + bpoNew2.bpo_ulFlags = bpoOld.bpo_ulFlags & ~(BPOF_MARKED_FOR_USE|BPOF_SELECTED); + bpoNew2.bpo_colShadow = bpoOld.bpo_colShadow; + bpoNew2.bpo_bppProperties = bpoOld.bpo_bppProperties; + bpoNew2.bpo_pbscSector = bpoOld.bpo_pbscSector; + + // initialize shadow map + bpoNew2.InitializeShadowMap(); + + // ---------------- Create third sub-triangle + CBrushPolygon &bpoNew3 = abpoPolygonsNew[ iNewPolygons+2]; + // allocate and set polygon edges + bpoNew3.bpo_abpePolygonEdges.New(3); + bpoNew3.bpo_abpePolygonEdges[0].bpe_pbedEdge = &abedEdgesNew[iEdge+2]; + bpoNew3.bpo_abpePolygonEdges[0].bpe_bReverse = FALSE; + bpoNew3.bpo_abpePolygonEdges[1].bpe_pbedEdge = &abedEdgesNew[iEdge+3]; + bpoNew3.bpo_abpePolygonEdges[1].bpe_bReverse = FALSE; + bpoNew3.bpo_abpePolygonEdges[2].bpe_pbedEdge = &abedEdgesNew[iEdge+5]; + bpoNew3.bpo_abpePolygonEdges[2].bpe_bReverse = TRUE; + + // set brush vertex ptrs + bpoNew3.bpo_apbvxTriangleVertices.New(3); + bpoNew3.bpo_apbvxTriangleVertices[0] = pbvtx2; + bpoNew3.bpo_apbvxTriangleVertices[1] = pbvtx0; + bpoNew3.bpo_apbvxTriangleVertices[2] = pbvtx3; + + // setup fixed trinagle element indices + bpoNew3.bpo_aiTriangleElements.New(3); + bpoNew3.bpo_aiTriangleElements[0] = 0; + bpoNew3.bpo_aiTriangleElements[1] = 1; + bpoNew3.bpo_aiTriangleElements[2] = 2; + + // copy parameters from old polygon + bpoNew3.bpo_pbplPlane = bpoOld.bpo_pbplPlane; + bpoNew3.bpo_abptTextures[0].CopyTextureProperties( bpoOld.bpo_abptTextures[0], TRUE); + bpoNew3.bpo_abptTextures[1].CopyTextureProperties( bpoOld.bpo_abptTextures[1], TRUE); + bpoNew3.bpo_abptTextures[2].CopyTextureProperties( bpoOld.bpo_abptTextures[2], TRUE); + bpoNew3.bpo_colColor = bpoOld.bpo_colColor; + bpoNew3.bpo_ulFlags = bpoOld.bpo_ulFlags & ~(BPOF_MARKED_FOR_USE|BPOF_SELECTED); + bpoNew3.bpo_colShadow = bpoOld.bpo_colShadow; + bpoNew3.bpo_bppProperties = bpoOld.bpo_bppProperties; + bpoNew3.bpo_pbscSector = bpoOld.bpo_pbscSector; + + // initialize shadow map + bpoNew3.InitializeShadowMap(); + + // skip newly created vertex + iVtx++; + // skip created edges + iEdge+=6; + // next triangle + iNewPolygons += 3; + } + }} + + // copy new arrays over old ones + bsc_awvxVertices.MoveArray( awvxVerticesNew); + bsc_abvxVertices.MoveArray( abvxVerticesNew); + bsc_abedEdges.MoveArray( abedEdgesNew); + bsc_abpoPolygons.MoveArray( abpoPolygonsNew); + + // create array of working edges + INDEX cted = bsc_abedEdges.Count(); + bsc_awedEdges.Clear(); + bsc_awedEdges.New(cted); + // for each edge + for (INDEX ied=0; iedbpo_abpePolygonEdges[iFirst].bpe_pbedEdge == + pbpo1->bpo_abpePolygonEdges[iSecond].bpe_pbedEdge ) + { + pse = pbpo0->bpo_abpePolygonEdges[iFirst].bpe_pbedEdge; + return; + } + } + } + pse = NULL; +} + +BOOL CBrushSector::IsReTripleAvailable( CBrushPolygonSelection &selPolygon) +{ + // we must have two polygons in selection + if( selPolygon.Count() != 2) return FALSE; + + // obtain polygons + CBrushPolygon *pbpoOld0 = selPolygon.sa_Array[0]; + CBrushPolygon *pbpoOld1 = selPolygon.sa_Array[1]; + + // must be in the same sector + if( pbpoOld0->bpo_pbscSector != pbpoOld1->bpo_pbscSector) return FALSE; + + // both of them must be triangles + if( pbpoOld0->bpo_aiTriangleElements.Count() != 3) return FALSE; + if( pbpoOld1->bpo_aiTriangleElements.Count() != 3) return FALSE; + + // triangles must share an edge + CBrushEdge *pse = NULL; + GetSharedEdge( pbpoOld0, pbpoOld1, pse); + return(pse != NULL); +} + +void GetNonSharedEdgesContainingVtx(CBrushPolygon *pbpo0, CBrushPolygon *pbpo1, + CBrushEdge *pse, CBrushVertex *pvtx, + CBrushPolygonEdge *&pbpe0, CBrushPolygonEdge *&pbpe1) +{ + // set invalid ptrs + pbpe0 = NULL; + pbpe1 = NULL; + + // for first triangle + for( INDEX itri0=0; itri0<3; itri0++) + { + CBrushPolygonEdge *pbpeTest = &pbpo0->bpo_abpePolygonEdges[itri0]; + if( ( pbpeTest->bpe_pbedEdge != pse) && // if it is not shared edge + ((pbpeTest->bpe_pbedEdge->bed_pbvxVertex0 == pvtx) || // and contains given vertex + (pbpeTest->bpe_pbedEdge->bed_pbvxVertex1 == pvtx)) ) + { + pbpe0 = pbpeTest; + } + } + // for second triangle + for( INDEX itri1=0; itri1<3; itri1++) + { + CBrushPolygonEdge *pbpeTest = &pbpo1->bpo_abpePolygonEdges[itri1]; + if( ( pbpeTest->bpe_pbedEdge != pse) && // if it is not shared edge + ((pbpeTest->bpe_pbedEdge->bed_pbvxVertex0 == pvtx) || // and contains given vertex + (pbpeTest->bpe_pbedEdge->bed_pbvxVertex1 == pvtx)) ) + { + pbpe1 = pbpeTest; + } + } + + // both must be found + ASSERT( pbpe0 != NULL); + ASSERT( pbpe1 != NULL); + return; +} + +void CBrushSector::ReTriple( CBrushPolygonSelection &selPolygon) +{ + // we must have two polygons in selection + if( selPolygon.Count() != 2) return; + + // obtain polygons + CBrushPolygon *pbpoOld0 = selPolygon.sa_Array[0]; + CBrushPolygon *pbpoOld1 = selPolygon.sa_Array[1]; + + // both of them must be triangles + if( pbpoOld0->bpo_aiTriangleElements.Count() != 3) return; + if( pbpoOld1->bpo_aiTriangleElements.Count() != 3) return; + + // clear marked for use flag on all polygons in world + CWorld *pwo=bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->en_pwoWorld; + pwo->ClearMarkedForUseFlag(); + + // mark them for use + pbpoOld0->bpo_ulFlags |= BPOF_MARKED_FOR_USE; + pbpoOld1->bpo_ulFlags |= BPOF_MARKED_FOR_USE; + + // clear the selection (polygons will be erased) + selPolygon.Clear(); + + // create new arrays + CStaticArray abedEdgesNew; + CStaticArray abpoPolygonsNew; + + INDEX ctOldEdges = bsc_abedEdges.Count(); + INDEX ctOldPolygons = bsc_abpoPolygons.Count(); + + // allocate arrays + abedEdgesNew.New( ctOldEdges+1); + abpoPolygonsNew.New( ctOldPolygons); + + // copy old edges to new edge array + INDEX iEdge; + for( iEdge=0; iEdgebpo_ulFlags & BPOF_MARKED_FOR_USE)) + { + // copy the old polygon + CBrushPolygon &bpoNew = abpoPolygonsNew[ iNewPolygons]; + bpoNew.bpo_pbplPlane = bpoOld.bpo_pbplPlane; + + bpoNew.bpo_abptTextures[0].CopyTextureProperties( bpoOld.bpo_abptTextures[0], TRUE); + bpoNew.bpo_abptTextures[1].CopyTextureProperties( bpoOld.bpo_abptTextures[1], TRUE); + bpoNew.bpo_abptTextures[2].CopyTextureProperties( bpoOld.bpo_abptTextures[2], TRUE); + + bpoNew.bpo_colColor = bpoOld.bpo_colColor; + bpoNew.bpo_ulFlags = bpoOld.bpo_ulFlags & ~(BPOF_MARKED_FOR_USE|BPOF_SELECTED); + bpoNew.bpo_colShadow = bpoOld.bpo_colShadow; + bpoNew.bpo_bppProperties = bpoOld.bpo_bppProperties; + bpoNew.bpo_pbscSector = bpoOld.bpo_pbscSector; + + // remap brush polygon edges to point to edges of new array + INDEX ctEdgesToRemap = bpoOld.bpo_abpePolygonEdges.Count(); + // allocate new polygon edges + bpoNew.bpo_abpePolygonEdges.New(ctEdgesToRemap); + // for each edge in polygon + for( INDEX iRemapEdge=0; iRemapEdgebed_pbvxVertex0; + CBrushVertex *pv1se = pse->bed_pbvxVertex1; + + // they will form first two edges of retripled polygon (each edge will be from different polygon) + CBrushPolygonEdge *pbpev0e0; + CBrushPolygonEdge *pbpev0e1; + // from two given polygons, extract edges different from shared edge that contain given vertex of shared edge + GetNonSharedEdgesContainingVtx( pbpoOld0, pbpoOld1, pse, pv0se, pbpev0e0, pbpev0e1); + +#define REMAP_EDGE( pedg) \ + {INDEX iIndex = bsc_abedEdges.Index( pedg->bpe_pbedEdge);\ + pedg->bpe_pbedEdge = &abedEdgesNew[iIndex];} + + REMAP_EDGE( pbpev0e0); + REMAP_EDGE( pbpev0e1); + + // get two other edges, for second retripled triangle + CBrushPolygonEdge *pbpev1e0; + CBrushPolygonEdge *pbpev1e1; + GetNonSharedEdgesContainingVtx( pbpoOld0, pbpoOld1, pse, pv1se, pbpev1e0, pbpev1e1); + + REMAP_EDGE( pbpev1e0); + REMAP_EDGE( pbpev1e1); + + // find edges that exit and enter shared edge's vertex 0 + CBrushPolygonEdge *pbpeExit; + CBrushPolygonEdge *pbpeEnter; + if( ((pbpev0e0->bpe_pbedEdge->bed_pbvxVertex0 == pv0se) && !pbpev0e0->bpe_bReverse) || + ((pbpev0e0->bpe_pbedEdge->bed_pbvxVertex1 == pv0se) && pbpev0e0->bpe_bReverse) ) + { + pbpeExit = pbpev0e0; + pbpeEnter = pbpev0e1; + } + else + { + pbpeExit = pbpev0e1; + pbpeEnter = pbpev0e0; + } + + // find start vertex of new edge + CBrushVertex *pvNew0; + if( pbpeExit->bpe_pbedEdge->bed_pbvxVertex0 != pv0se) + { + pvNew0 = pbpeExit->bpe_pbedEdge->bed_pbvxVertex0; + } + else + { + pvNew0 = pbpeExit->bpe_pbedEdge->bed_pbvxVertex1; + } + // find end vertex of new edge + CBrushVertex *pvNew1; + if( pbpeEnter->bpe_pbedEdge->bed_pbvxVertex0 != pv0se) + { + pvNew1 = pbpeEnter->bpe_pbedEdge->bed_pbvxVertex0; + } + else + { + pvNew1 = pbpeEnter->bpe_pbedEdge->bed_pbvxVertex1; + } + + // add new edge + abedEdgesNew[iEdge].bed_pbvxVertex0 = pvNew0; + abedEdgesNew[iEdge].bed_pbvxVertex1 = pvNew1; + + // --------------- Create retripled triangle 1 + { + // copy the old polygon + CBrushPolygon &bpoNew = abpoPolygonsNew[ iNewPolygons+0]; + CBrushPolygon &bpoOld = *pbpoOld0; + bpoNew.bpo_pbplPlane = bpoOld.bpo_pbplPlane; + + bpoNew.bpo_abptTextures[0].CopyTextureProperties( bpoOld.bpo_abptTextures[0], TRUE); + bpoNew.bpo_abptTextures[1].CopyTextureProperties( bpoOld.bpo_abptTextures[1], TRUE); + bpoNew.bpo_abptTextures[2].CopyTextureProperties( bpoOld.bpo_abptTextures[2], TRUE); + + bpoNew.bpo_colColor = bpoOld.bpo_colColor; + bpoNew.bpo_ulFlags = bpoOld.bpo_ulFlags & ~(BPOF_MARKED_FOR_USE|BPOF_SELECTED); + bpoNew.bpo_colShadow = bpoOld.bpo_colShadow; + bpoNew.bpo_bppProperties = bpoOld.bpo_bppProperties; + bpoNew.bpo_pbscSector = bpoOld.bpo_pbscSector; + + // allocate polygon edges + bpoNew.bpo_abpePolygonEdges.New(3); + // set edges data + bpoNew.bpo_abpePolygonEdges[0].bpe_pbedEdge = pbpev0e0->bpe_pbedEdge; + bpoNew.bpo_abpePolygonEdges[0].bpe_bReverse = pbpev0e0->bpe_bReverse; + bpoNew.bpo_abpePolygonEdges[1].bpe_pbedEdge = pbpev0e1->bpe_pbedEdge; + bpoNew.bpo_abpePolygonEdges[1].bpe_bReverse = pbpev0e1->bpe_bReverse; + bpoNew.bpo_abpePolygonEdges[2].bpe_pbedEdge = &abedEdgesNew[iEdge]; + bpoNew.bpo_abpePolygonEdges[2].bpe_bReverse = FALSE; + + // allocate and set vertex pointers + bpoNew.bpo_apbvxTriangleVertices.New(3); + bpoNew.bpo_apbvxTriangleVertices[0] = pv0se; + bpoNew.bpo_apbvxTriangleVertices[1] = pvNew0; + bpoNew.bpo_apbvxTriangleVertices[2] = pvNew1; + + // copy triangle and triangle elements arrays + bpoNew.bpo_aiTriangleElements.New(3); + bpoNew.bpo_aiTriangleElements[0] = 0; + bpoNew.bpo_aiTriangleElements[1] = 1; + bpoNew.bpo_aiTriangleElements[2] = 2; + + // initialize shadow map + bpoNew.InitializeShadowMap(); + } + + // --------------- Create retripled triangle 2 + { + // copy the old polygon + CBrushPolygon &bpoNew = abpoPolygonsNew[ iNewPolygons+1]; + CBrushPolygon &bpoOld = *pbpoOld1; + bpoNew.bpo_pbplPlane = bpoOld.bpo_pbplPlane; + + bpoNew.bpo_abptTextures[0].CopyTextureProperties( bpoOld.bpo_abptTextures[0], TRUE); + bpoNew.bpo_abptTextures[1].CopyTextureProperties( bpoOld.bpo_abptTextures[1], TRUE); + bpoNew.bpo_abptTextures[2].CopyTextureProperties( bpoOld.bpo_abptTextures[2], TRUE); + + bpoNew.bpo_colColor = bpoOld.bpo_colColor; + bpoNew.bpo_ulFlags = bpoOld.bpo_ulFlags & ~(BPOF_MARKED_FOR_USE|BPOF_SELECTED); + bpoNew.bpo_colShadow = bpoOld.bpo_colShadow; + bpoNew.bpo_bppProperties = bpoOld.bpo_bppProperties; + bpoNew.bpo_pbscSector = bpoOld.bpo_pbscSector; + + // allocate polygon edges + bpoNew.bpo_abpePolygonEdges.New(3); + // set edges data + bpoNew.bpo_abpePolygonEdges[0].bpe_pbedEdge = pbpev1e0->bpe_pbedEdge; + bpoNew.bpo_abpePolygonEdges[0].bpe_bReverse = pbpev1e0->bpe_bReverse; + bpoNew.bpo_abpePolygonEdges[1].bpe_pbedEdge = pbpev1e1->bpe_pbedEdge; + bpoNew.bpo_abpePolygonEdges[1].bpe_bReverse = pbpev1e1->bpe_bReverse; + bpoNew.bpo_abpePolygonEdges[2].bpe_pbedEdge = &abedEdgesNew[iEdge]; + bpoNew.bpo_abpePolygonEdges[2].bpe_bReverse = TRUE; + + // allocate and set vertex pointers + bpoNew.bpo_apbvxTriangleVertices.New(3); + bpoNew.bpo_apbvxTriangleVertices[0] = pv1se; + bpoNew.bpo_apbvxTriangleVertices[1] = pvNew1; + bpoNew.bpo_apbvxTriangleVertices[2] = pvNew0; + + // copy triangle and triangle elements arrays + bpoNew.bpo_aiTriangleElements.New(3); + bpoNew.bpo_aiTriangleElements[0] = 0; + bpoNew.bpo_aiTriangleElements[1] = 1; + bpoNew.bpo_aiTriangleElements[2] = 2; + + // initialize shadow map + bpoNew.InitializeShadowMap(); + } + + // copy new arrays over old ones + bsc_abedEdges.MoveArray( abedEdgesNew); + bsc_abpoPolygons.MoveArray( abpoPolygonsNew); + + // create array of working edges + INDEX cted = bsc_abedEdges.Count(); + bsc_awedEdges.Clear(); + bsc_awedEdges.New(cted); + // for each edge + for (INDEX ied=0; ied +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define VERSION_CURRENT 1 + +// max allowed size of shadowmap in pixels +#define MAX_SHADOWMAP_SIZE 65536 + + +CBrushShadowLayer::CBrushShadowLayer() +{ + bsl_ulFlags = 0; + bsl_pbsmShadowMap = NULL; + bsl_plsLightSource = NULL; + bsl_pixMinU = 0; + bsl_pixMinV = 0; + bsl_pixSizeU = 0; + bsl_pixSizeV = 0; + bsl_slSizeInPixels = 0; + bsl_pubLayer = NULL; + bsl_colLastAnim = C_BLACK; +} + +// destructor +CBrushShadowLayer::~CBrushShadowLayer(void) +{ + DiscardShadows(); +} + + +// discard shadows but keep the layer +void CBrushShadowLayer::DiscardShadows(void) +{ + // if the layer is calculated + if (bsl_pubLayer!=NULL) { + // free its memory + FreeMemory(bsl_pubLayer); + bsl_pubLayer = NULL; + bsl_slSizeInPixels = 0; + } + bsl_ulFlags&=~(BSLF_CALCULATED|BSLF_ALLDARK|BSLF_ALLLIGHT); +} + + +/* + * Discard shadow on the polygon. + */ +void CBrushPolygon::DiscardShadows(void) +{ + bpo_smShadowMap.DiscardAllLayers(); + InitializeShadowMap(); +} + + +/* Initialize shadow map for the polygon. */ +void CBrushPolygon::InitializeShadowMap(void) +{ + // reset shadow mapping to be default for its plane + bpo_mdShadow = CMappingDefinition(); + // init the bounding box of the shadow map as empty + MEXaabbox2D boxPolygonMap; + // for each edge in polygon + FOREACHINSTATICARRAY(bpo_abpePolygonEdges, CBrushPolygonEdge, itbpe) { + // find coordinates for first vertex + FLOAT3D v0, v1; + itbpe->GetVertexCoordinatesRelative(v0, v1); + // find mapping coordinates for first vertex + MEX2D vTexture; + bpo_mdShadow.GetTextureCoordinates( + bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, v0, vTexture); + // add the vertex to the box + boxPolygonMap |= vTexture; + } + + // extract mexel dimensions from the bounding box + MEX2D vmexShadowMin = boxPolygonMap.Min(); + MEX mexMinU = vmexShadowMin(1); + MEX mexMinV = vmexShadowMin(2); + MEX2D vmexShadowSize = boxPolygonMap.Size(); + MEX mexSizeU = vmexShadowSize(1); + MEX mexSizeV = vmexShadowSize(2); + + // mip level is initially minimum mip level that generates needed precision for the polygon + // (size=(2^ub)*0.5m) (-1 is for *0.5m) + INDEX iMipLevel = (MAX_MEX_LOG2+bpo_bppProperties.bpp_sbShadowClusterSize-1); + + // expand shadow map for the sake of dark corners + if( bpo_ulFlags&BPOF_DARKCORNERS) { + mexSizeU += 2<>iMipLevel; + PIX pixSizeV = mexSizeV>>iMipLevel; + INDEX iMipAdj = ClampTextureSize( MAX_SHADOWMAP_SIZE, _pGfx->gl_pixMaxTextureDimension, pixSizeU, pixSizeV); + pixSizeU = ClampDn( pixSizeU>>iMipAdj, 1L); + pixSizeV = ClampDn( pixSizeV>>iMipAdj, 1L); + iMipLevel += iMipAdj; + + // move shadow map offset for the sake of dark corners + if( bpo_ulFlags&BPOF_DARKCORNERS) { + mexMinU -= 1<>iMipLevel)+3), pixSizeU); + bpo_smShadowMap.sm_pixPolygonSizeV = Min( (PIX)((vmexShadowSize(2)>>iMipLevel)+3), pixSizeV); + // safety check + ASSERT( bpo_smShadowMap.sm_pixPolygonSizeU <= _pGfx->gl_pixMaxTextureDimension && + bpo_smShadowMap.sm_pixPolygonSizeV <= _pGfx->gl_pixMaxTextureDimension && + (bpo_smShadowMap.sm_pixPolygonSizeU*bpo_smShadowMap.sm_pixPolygonSizeV) <= MAX_SHADOWMAP_SIZE); + + // initialize the shadow map + bpo_smShadowMap.Initialize(iMipLevel, mexOffsetU, mexOffsetV, mexSizeU, mexSizeV); + // discard polygon mask if calculated + if (bpo_smShadowMap.bsm_pubPolygonMask != NULL) { + FreeMemory(bpo_smShadowMap.bsm_pubPolygonMask); + bpo_smShadowMap.bsm_pubPolygonMask = NULL; + } + + // discard all cached shading infos for models + DiscardShadingInfos(); +} + +// get shadow/light percentage at given coordinates in shadow layer +FLOAT CBrushShadowLayer::GetLightStrength(PIX pixU, PIX pixV, FLOAT fLRRatio, FLOAT fUDRatio) +{ + // if full dark layer + if (bsl_ulFlags&BSLF_ALLDARK) { + // full dark + return 0.0f; + } + // if there is no layer mask, full light layer or the coordinates are out of the layer + if (bsl_pubLayer==NULL || (bsl_ulFlags&BSLF_ALLLIGHT) || + (pixU=bsl_pixMinU+bsl_pixSizeU) || (pixV>=bsl_pixMinV+bsl_pixSizeV)) { + // full light + return 1.0f; + } + + // get the coordinates of the four pixels + PIX pixU0 = pixU-bsl_pixMinU; PIX pixU1 = Min(pixU0+1, bsl_pixSizeU-1); + PIX pixV0 = pixV-bsl_pixMinV; PIX pixV1 = Min(pixV0+1, bsl_pixSizeV-1); + ULONG ulOffsetUL = pixU0+pixV0*bsl_pixSizeU; + ULONG ulOffsetUR = pixU1+pixV0*bsl_pixSizeU; + ULONG ulOffsetDL = pixU0+pixV1*bsl_pixSizeU; + ULONG ulOffsetDR = pixU1+pixV1*bsl_pixSizeU; + // get light at the four pixels + FLOAT fUL=0.0f, fUR=0.0f, fDL=0.0f, fDR=0.0f; + if (bsl_pubLayer[ulOffsetUL/8]&(1<<(ulOffsetUL%8))) { fUL = 1.0f; }; + if (bsl_pubLayer[ulOffsetUR/8]&(1<<(ulOffsetUR%8))) { fUR = 1.0f; }; + if (bsl_pubLayer[ulOffsetDL/8]&(1<<(ulOffsetDL%8))) { fDL = 1.0f; }; + if (bsl_pubLayer[ulOffsetDR/8]&(1<<(ulOffsetDR%8))) { fDR = 1.0f; }; + + // return interpolated value + return Lerp( Lerp(fUL, fUR, fLRRatio), Lerp(fDL, fDR, fLRRatio), fUDRatio); +} + +void CBrushShadowMap::ReadLayers_t( CTStream *pstrm) // throw char * +{ + BOOL bUncalculated = FALSE; + // if the old version of layers information is really saved here + if (pstrm->PeekID_t()==CChunkID("SHLY")) { // shadow layers + pstrm->ExpectID_t("SHLY"); + + // read number of layers + INDEX ctLayers; + *pstrm>>ctLayers; + // for each shadow layer + for(INDEX iLayer=0; iLayerbsl_colLastAnim = 0x12345678; + // attach it to the shadow map + bsm_lhLayers.AddTail(pbsl->bsl_lnInShadowMap); + // make the layer point to its shadow map + pbsl->bsl_pbsmShadowMap = this; + // make the light pointer dummy (it is set while loading lights) + pbsl->bsl_plsLightSource = NULL; + + // read the layer data + *pstrm>>pbsl->bsl_ulFlags; // flags + // if it is new version + if (pbsl->bsl_ulFlags&BSLF_RECTANGLE) { + SLONG slLayerSize; + *pstrm>>slLayerSize; + if (slLayerSize != 0) { + pbsl->bsl_pubLayer = (UBYTE *)AllocMemory(slLayerSize); + pstrm->Read_t(pbsl->bsl_pubLayer, slLayerSize); // the bit packed layer mask + } else { + bUncalculated = TRUE; + pbsl->bsl_pubLayer = NULL; + } + // read layer rectangle + *pstrm>>pbsl->bsl_pixMinU; + *pstrm>>pbsl->bsl_pixMinV; + *pstrm>>pbsl->bsl_pixSizeU; + *pstrm>>pbsl->bsl_pixSizeV; + // if it is old version + } else { + // skip it + SLONG slLayerSize; + *pstrm>>slLayerSize; + if (slLayerSize != 0) { + pstrm->Seek_t(slLayerSize, CTStream::SD_CUR); + pbsl->bsl_pubLayer = NULL; + bUncalculated = TRUE; + } else { + bUncalculated = TRUE; + pbsl->bsl_pubLayer = NULL; + } + // destroy it + pbsl->bsl_lnInShadowMap.Remove(); + delete pbsl; + } + } + // if the new version of layers information is really saved here + } else if (pstrm->PeekID_t()==CChunkID("SHLA")) { // shadow layers + pstrm->ExpectID_t("SHLA"); + // read polygon size + *pstrm>>sm_pixPolygonSizeU; + *pstrm>>sm_pixPolygonSizeV; + + // read number of layers + INDEX ctLayers; + *pstrm>>ctLayers; + // for each shadow layer + for(INDEX iLayer=0; iLayerbsl_colLastAnim = 0x12345678; + // attach it to the shadow map + bsm_lhLayers.AddTail(pbsl->bsl_lnInShadowMap); + // make the layer point to its shadow map + pbsl->bsl_pbsmShadowMap = this; + // make the light pointer dummy (it is set while loading lights) + pbsl->bsl_plsLightSource = NULL; + + // read the layer data + *pstrm>>pbsl->bsl_ulFlags; // flags + SLONG slLayerSize; + *pstrm>>slLayerSize; + if (slLayerSize != 0) { + pstrm->Seek_t(slLayerSize, CTStream::SD_CUR); + } + bUncalculated = TRUE; + pbsl->bsl_pubLayer = NULL; + pbsl->bsl_ulFlags&=~BSLF_CALCULATED; + // read layer rectangle + *pstrm>>pbsl->bsl_pixMinU; + *pstrm>>pbsl->bsl_pixMinV; + *pstrm>>pbsl->bsl_pixSizeU; + *pstrm>>pbsl->bsl_pixSizeV; + + } + // if the new version of layers information is really saved here + } else if (pstrm->PeekID_t()==CChunkID("SHAL")) { // shadow layers + pstrm->ExpectID_t("SHAL"); + // read version number + INDEX iVersion; + *pstrm>>iVersion; + ASSERT(iVersion==VERSION_CURRENT); + // read polygon size + *pstrm>>sm_pixPolygonSizeU; + *pstrm>>sm_pixPolygonSizeV; + + // read number of layers + INDEX ctLayers; + *pstrm>>ctLayers; + // for each shadow layer + for(INDEX iLayer=0; iLayerbsl_colLastAnim = 0x12345678; + // attach it to the shadow map + bsm_lhLayers.AddTail(pbsl->bsl_lnInShadowMap); + // make the layer point to its shadow map + pbsl->bsl_pbsmShadowMap = this; + // make the light pointer dummy (it is set while loading lights) + pbsl->bsl_plsLightSource = NULL; + + // read the layer data + *pstrm>>pbsl->bsl_ulFlags; // flags + *pstrm>>pbsl->bsl_slSizeInPixels; + if (pbsl->bsl_slSizeInPixels != 0) { + SLONG slLayerSize = (pbsl->bsl_slSizeInPixels+7)/8; + pbsl->bsl_pubLayer = (UBYTE *)AllocMemory(slLayerSize); + pstrm->Read_t(pbsl->bsl_pubLayer, slLayerSize); // the bit packed layer mask + } else { + bUncalculated = TRUE; + pbsl->bsl_pubLayer = NULL; + } + // read layer rectangle + *pstrm>>pbsl->bsl_pixMinU; + *pstrm>>pbsl->bsl_pixMinV; + *pstrm>>pbsl->bsl_pixSizeU; + *pstrm>>pbsl->bsl_pixSizeV; + + // fixup for old levels before alllight and alldark flags + if ((pbsl->bsl_ulFlags&BSLF_CALCULATED) + && (pbsl->bsl_pubLayer==NULL) + &&!(pbsl->bsl_ulFlags&BSLF_ALLLIGHT) + &&!(pbsl->bsl_ulFlags&BSLF_ALLDARK)) { + pbsl->bsl_ulFlags|=BSLF_ALLLIGHT; + } + } + } + + // if some layers are uncalculated + if (bUncalculated) { + extern CWorld *_pwoCurrentLoading; // world that is currently loading + // add the shadow map for calculation + _pwoCurrentLoading->wo_baBrushes.ba_lhUncalculatedShadowMaps + .AddTail(bsm_lnInUncalculatedShadowMaps); + } +} + +void CBrushShadowMap::WriteLayers_t( CTStream *pstrm) // throw char * +{ + pstrm->WriteID_t("SHAL"); // shadow layers + // write version number + *pstrm<bsl_plsLightSource->ls_ulFlags&LSF_NONPERSISTENT) { + continue; + } + ctLayers++; + }} + *pstrm<bsl_plsLightSource->ls_ulFlags&LSF_NONPERSISTENT) { + continue; + } + // write the layer data + *pstrm<Write_t(bsl.bsl_pubLayer, slLayerSize); // the bit packed layer mask + } + // write layer rectangle + *pstrm<DiscardShadows(); + } +} + + +// remove shadow layers without valid light source +void CBrushShadowMap::RemoveDummyLayers(void) +{ + // for each shadow layer + FORDELETELIST(CBrushShadowLayer, bsl_lnInShadowMap, bsm_lhLayers, itbsl) { + // if dummy + if (itbsl->bsl_plsLightSource==NULL) { + // remove it + delete &*itbsl; + } + } +} + +// destructor +CBrushShadowMap::~CBrushShadowMap(void) +{ + // discard all layers before deleting the object itself + DiscardAllLayers(); + // discard polygon mask if calculated + if (bsm_pubPolygonMask != NULL) { + FreeMemory(bsm_pubPolygonMask); + bsm_pubPolygonMask = NULL; + } +} + +// queue the shadow map for calculation +void CBrushShadowMap::QueueForCalculation(void) +{ + // if not already queued + if (!bsm_lnInUncalculatedShadowMaps.IsLinked()) { + // find the world of the polygon + CBrushPolygon *pbpo = GetBrushPolygon(); + CBrushSector *pbsc = pbpo->bpo_pbscSector; + CBrushMip *pbm = pbsc->bsc_pbmBrushMip; + CBrush3D *pbr = pbm->bm_pbrBrush; + CWorld *pwo = pbr->br_penEntity->GetWorld(); + // queue the shadow map in the world + pwo->wo_baBrushes.ba_lhUncalculatedShadowMaps.AddTail(bsm_lnInUncalculatedShadowMaps); + } +} + + +// calculate the rectangle where a light influences the shadow map +void CBrushShadowMap::FindLightRectangle(CLightSource &ls, class CLightRectangle &lr) +{ + // get needed data + CBrushPolygon &bpoPolygon = *GetBrushPolygon(); + const FLOATplane3D &plPlane = bpoPolygon.bpo_pbplPlane->bpl_plAbsolute; + INDEX iMipLevel = sm_iFirstMipLevel; + FLOAT3D vLight; + PIX pixMinU, pixMinV, pixMaxU, pixMaxV; + + // if the light is directional + if( ls.ls_ulFlags&LSF_DIRECTIONAL) + { + pixMinU = 0; + pixMinV = 0; + // rectangle is around entire shadowmap + // pixMaxU = PIX(sm_mexWidth >>iMipLevel); + // pixMaxV = PIX(sm_mexHeight>>iMipLevel); + // rectangle is around entire polygon + pixMaxU = Min( sm_pixPolygonSizeU+16L, sm_mexWidth >>iMipLevel); + pixMaxV = Min( sm_pixPolygonSizeV+16L, sm_mexHeight>>iMipLevel); + } + // if the light is point + else + { + // light position is at the light entity + vLight = ls.ls_penEntity->GetPlacement().pl_PositionVector; + // find the point where the light is closest to the polygon + FLOAT3D vHotPoint = plPlane.ProjectPoint(vLight); + lr.lr_fLightPlaneDistance = plPlane.PointDistance(vLight); + + CEntity *penWithPolygon = bpoPolygon.bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + ASSERT(penWithPolygon!=NULL); + const FLOATmatrix3D &mPolygonRotation = penWithPolygon->en_mRotation; + const FLOAT3D &vPolygonTranslation = penWithPolygon->GetPlacement().pl_PositionVector; + + vHotPoint = (vHotPoint-vPolygonTranslation)*!mPolygonRotation; + + Vector vmexHotPoint; + bpoPolygon.bpo_mdShadow.GetTextureCoordinates( + bpoPolygon.bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, vHotPoint, vmexHotPoint); + + if( !(bpoPolygon.bpo_ulFlags&BPOF_DARKCORNERS)) { + lr.lr_fpixHotU = FLOAT(vmexHotPoint(1)+sm_mexOffsetX+(1<>iMipLevel); + pixMinV = ((vmexHotPoint(2)+sm_mexOffsetY-mexFallOff)>>iMipLevel); + pixMaxU = ((vmexHotPoint(1)+sm_mexOffsetX+mexFallOff)>>iMipLevel)+1; + pixMaxV = ((vmexHotPoint(2)+sm_mexOffsetY+mexFallOff)>>iMipLevel)+1; + // clamp the rectangle to the size of shadow map + // pixMinU = Min( Max(pixMinU, 0L), sm_mexWidth >>iMipLevel); + // pixMinV = Min( Max(pixMinV, 0L), sm_mexHeight>>iMipLevel); + // pixMaxU = Min( Max(pixMaxU, 0L), sm_mexWidth >>iMipLevel); + // pixMaxV = Min( Max(pixMaxV, 0L), sm_mexHeight>>iMipLevel); + // clamp the rectangle to the size of polygon + pixMinU = Min( Max(pixMinU, 0L), Min(sm_pixPolygonSizeU+16L, sm_mexWidth >>iMipLevel)); + pixMinV = Min( Max(pixMinV, 0L), Min(sm_pixPolygonSizeV+16L, sm_mexHeight>>iMipLevel)); + pixMaxU = Min( Max(pixMaxU, 0L), Min(sm_pixPolygonSizeU+16L, sm_mexWidth >>iMipLevel)); + pixMaxV = Min( Max(pixMaxV, 0L), Min(sm_pixPolygonSizeV+16L, sm_mexHeight>>iMipLevel)); + } + // all done + lr.lr_pixMinU = pixMinU; + lr.lr_pixMinV = pixMinV; + lr.lr_pixSizeU = pixMaxU-pixMinU; + lr.lr_pixSizeV = pixMaxV-pixMinV; + ASSERT(lr.lr_pixSizeU>=0); + ASSERT(lr.lr_pixSizeV>=0); +} + + +// check if all layers are up to date +void CBrushShadowMap::CheckLayersUpToDate(void) +{ + // do nothing if the shadow map is not cached at all or hasn't got any animating lights + if( ((sm_pulDynamicShadowMap==NULL || (sm_ulFlags&SMF_DYNAMICBLACK)) + && !(sm_ulFlags&SMF_ANIMATINGLIGHTS)) + || sm_pulCachedShadowMap==NULL) return; + + // for each layer + FOREACHINLIST( CBrushShadowLayer, bsl_lnInShadowMap, bsm_lhLayers, itbsl) + { // ignore if the layer is all dark + CBrushShadowLayer &bsl = *itbsl; + if( bsl.bsl_ulFlags&BSLF_ALLDARK) continue; + // light source must be valid + CLightSource &ls = *bsl.bsl_plsLightSource; + ASSERT( &ls!=NULL); + if( &ls==NULL) continue; + // if the layer is not up to date + if( bsl.bsl_colLastAnim != ls.GetLightColor()) { + // invalidate entire shadow map + Invalidate( ls.ls_ulFlags&LSF_DYNAMIC); + if( !(ls.ls_ulFlags&LSF_DYNAMIC)) return; + } + } +} + + +// test if there is any dynamic layer +BOOL CBrushShadowMap::HasDynamicLayers(void) +{ + // for each layer + FOREACHINLIST( CBrushShadowLayer, bsl_lnInShadowMap, bsm_lhLayers, itbsl) + { // light source must be valid + CLightSource &ls = *itbsl->bsl_plsLightSource; + ASSERT( &ls!=NULL); + if( &ls==NULL) continue; + // if the layer is dynamic, it has + if( ls.ls_ulFlags&LSF_DYNAMIC) return TRUE; + } + // hasn't + return FALSE; +} + + + +// returns TRUE if shadowmap is all flat along with colFlat variable set to that color +BOOL CBrushShadowMap::IsShadowFlat( COLOR &colFlat) +{ + // fail if flat shadows are not allowed + extern INDEX shd_bAllowFlats; + extern INDEX shd_iForceFlats; + shd_iForceFlats = Clamp( shd_iForceFlats, 0L, 2L); + if( !shd_bAllowFlats && shd_iForceFlats<1) return FALSE; + + COLOR col; + UBYTE ubR,ubG,ubB, ubR1,ubG1,ubB1; + SLONG slR=0,slG=0,slB=0; + INDEX ctPointLights=0; + CBrushPolygon *pbpo = GetBrushPolygon(); + + // if the shadowmap is not using the shading mode + if (pbpo->bpo_bppProperties.bpp_ubShadowBlend != BPT_BLEND_SHADE) { + // it must not be flat + return FALSE; + } + + // initial color is sector color + col = AdjustColor( pbpo->bpo_pbscSector->bsc_colAmbient, _slShdHueShift, _slShdSaturation); + ColorToRGB( col, ubR,ubG,ubB); + slR += ubR; slG += ubG; slB += ubB; + + // if gradient layer is present + const ULONG ulGradientType = pbpo->bpo_bppProperties.bpp_ubGradientType; + if( ulGradientType>0) + { + CGradientParameters gp; + CEntity *pen = pbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + if( pen!=NULL && pen->GetGradient( ulGradientType, gp)) { + // shadowmap cannot be flat + if( shd_iForceFlats<1) return FALSE; + // unless it has been forced + ColorToRGB( gp.gp_col0, ubR, ubG, ubB); + ColorToRGB( gp.gp_col1, ubR1,ubG1,ubB1); + const SLONG slAvgR = ((ULONG)ubR + ubR1) /2; + const SLONG slAvgG = ((ULONG)ubG + ubG1) /2; + const SLONG slAvgB = ((ULONG)ubB + ubB1) /2; + if( gp.gp_bDark) { slR -= slAvgR; slG -= slAvgR; slB -= slAvgR; } + else { slR += slAvgR; slG += slAvgR; slB += slAvgR; } + } + } + + // for each layer + BOOL bDirLightApplied = FALSE; + FOREACHINLIST( CBrushShadowLayer, bsl_lnInShadowMap, bsm_lhLayers, itbsl) + { + // skip dynamic layers + CBrushShadowLayer &bsl = *itbsl; + CLightSource &ls = *bsl.bsl_plsLightSource; + if( ls.ls_ulFlags&LSF_DYNAMIC) continue; + + // if light is directional + if( ls.ls_ulFlags&LSF_DIRECTIONAL) + { + // fail if calculated and not all dark or all light + if( (bsl.bsl_ulFlags&BSLF_CALCULATED) && !(bsl.bsl_ulFlags&(BSLF_ALLDARK|BSLF_ALLLIGHT))) { + // but only if flats have not been forced! + if( shd_iForceFlats<1) return FALSE; + } + + // if polygon allows directional light ambient component + if( pbpo->bpo_ulFlags&BPOF_HASDIRECTIONALAMBIENT) { + // mix in ambient color + col = AdjustColor( ls.GetLightAmbient(), _slShdHueShift, _slShdSaturation); + ColorToRGB( col, ubR,ubG,ubB); + slR += ubR; slG += ubG; slB += ubB; + } + // done with this layer if it's all dark, or all light but without directional component + if( (bsl.bsl_ulFlags&BSLF_ALLDARK) || !(pbpo->bpo_ulFlags&BPOF_HASDIRECTIONALLIGHT)) continue; + + // layer is all light, so calculate intensity + col = ls.GetLightColor(); + if( !(pbpo->bpo_ulFlags&BPOF_NOPLANEDIFFUSION)) { + FLOAT3D vLightDirection; + AnglesToDirectionVector( ls.ls_penEntity->GetPlacement().pl_OrientationAngle, vLightDirection); + const FLOAT fIntensity = -((pbpo->bpo_pbplPlane->bpl_plAbsolute)%vLightDirection); + // done if polygon is turn away from light source (we already added ambient component) + if( fIntensity<0.01f) continue; + ULONG ulIntensity = NormFloatToByte(fIntensity); + ulIntensity = (ulIntensity<0 && !bDirLightApplied) { + FLOAT3D vLightDir; + vLightDir(1) = -3.0f; + vLightDir(2) = -2.0f; + vLightDir(3) = -1.0f; + vLightDir.Normalize(); + const FLOAT fIntensity = -((pbpo->bpo_pbplPlane->bpl_plAbsolute)%vLightDir); + if( fIntensity>0.01f) { + const UBYTE ubGray = NormFloatToByte(fIntensity*0.49f); + slR += ubGray; slG += ubGray; slB += ubGray; + } + } + // done - phew, layer is flat + slR = Clamp( slR, 0L, 255L); + slG = Clamp( slG, 0L, 255L); + slB = Clamp( slB, 0L, 255L); + colFlat = RGBToColor(slR,slG,slB); + return TRUE; +} + + + +// get amount of memory used by this object +SLONG CBrushShadowMap::GetUsedMemory(void) +{ + // basic size of class + SLONG slUsedMemory = sizeof(CBrushShadowMap); + + // add polyhon mask (if any) + if( bsm_pubPolygonMask!=NULL) { + // loop and add mip-maps + SLONG slPolyMaskSize = 0; + PIX pixPolySizeU = sm_pixPolygonSizeU; + PIX pixPolySizeV = sm_pixPolygonSizeV; + while( pixPolySizeU>0 && pixPolySizeV>0) { + slPolyMaskSize += pixPolySizeU * pixPolySizeV; + pixPolySizeU >>= 1; + pixPolySizeV >>= 1; + } + // sum it up + slUsedMemory += (slPolyMaskSize+8) /8; // bit mask! + } + + // loop thru layers and add 'em too + FOREACHINLIST( CBrushShadowLayer, bsl_lnInShadowMap, bsm_lhLayers, itbsl) { // count shadow layers + CBrushShadowLayer &bsl = *itbsl; + slUsedMemory += sizeof(CBrushShadowLayer); + if( bsl.bsl_pubLayer!=NULL) slUsedMemory += bsl.bsl_pixSizeU * bsl.bsl_pixSizeV /8; + } + + // done + return slUsedMemory; +} diff --git a/Sources/Engine/Brushes/BrushTransformed.h b/Sources/Engine/Brushes/BrushTransformed.h new file mode 100644 index 0000000..b9316ea --- /dev/null +++ b/Sources/Engine/Brushes/BrushTransformed.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_BRUSHTRANSFORMED_H +#define SE_INCL_BRUSHTRANSFORMED_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#undef ALIGNED_NEW_AND_DELETE +#ifdef NDEBUG +#define ALIGNED_NEW_AND_DELETE(align) \ + void *operator new[] (size_t size) { return AllocMemoryAligned(size, align); }; \ + void operator delete[] (void* ptr) { FreeMemoryAligned(ptr); }; +#else +#define ALIGNED_NEW_AND_DELETE(align) +#endif + +#include +#include +#include + +/* + * Cached transformed vertex. + */ +class CWorkingVertex { +public: + FLOAT3D wvx_vRelative; // coordinates in brush space + ALIGNED_NEW_AND_DELETE(32); + /* Clear the object. */ + inline void Clear(void) {}; +}; + +/* + * Cached transformed plane. + */ +class CWorkingPlane { +public: + FLOATplane3D wpl_plRelative; // coordinates in brush space + CMappingVectors wpl_mvRelative; // mapping vectors in brush space + FLOATplane3D wpl_plView; // coordinates in view space + CMappingVectors wpl_mvView; // mapping vectors in view space + CPlanarGradients wpl_pgOoK; // plane gradients in default mapping + BOOL wpl_bVisible; // set if the plane is visible + /* Clear the object. */ + inline void Clear(void) {}; +}; + +/* + * Cached transformed edge. + */ +class CWorkingEdge { +public: + INDEX wed_iwvx0; // working vertices in sector + INDEX wed_iwvx1; + /* Clear the object. */ + inline void Clear(void) {}; +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Brushes/BrushTriangularize.cpp b/Sources/Engine/Brushes/BrushTriangularize.cpp new file mode 100644 index 0000000..1f74d78 --- /dev/null +++ b/Sources/Engine/Brushes/BrushTriangularize.cpp @@ -0,0 +1,958 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +// define this to dump all triangularization steps to debugging output +//#define DUMP_ALLSTEPS 1 + +//#define OPERATEIN2D 1 + +// this must not be caught by the dependency catcher! +static CTFileName _fnmDebugOutput(CTString("Temp\\Triangularization.out")); +// set if debug output file is open +static BOOL _bDebugOutputOpen = FALSE; +// file where debugging output is written to +static CTFileStream _strmDebugOutput; + +// edge splitting epsilon +//#define EPSILON 0.0 +//#define EPSILON (1.0/8388608.0) // 1/2^23 +#define EPSILON (1.0f/65536.0f) // 1/2^16 +//#define EPSILON DOUBLE(0.00390625) // 1/2^8 +//#define EPSILON 0.0009765625f // 1/2^10 +//#define EPSILON 0.03125f // 1/2^5 +//#define EPSILON 0.00390625f // 1/2^8 + +// minimum triangle quality that is trivially accepted +#define QUALITY_ACCEPTTRIVIALLY DOUBLE(0.01) + +// this function is here to satisfy compiler's weird need when compiling +// the template for CDynamicArray +inline void Clear(CBrushVertex *pbvx) { + (void)pbvx; +}; + +/* +Algorithm used: + +We take each edge and each vertex that is left of that edge, and try to find out +if the edge and the vertex can span a triangle on the polygon without itersecting +any other edges. + +A simple convex BSP is used for testing intersection. The triangle edges are +represented by planes oriented outwards (to the right side of the edge). + +Triangle quality is defined as division of the area and square of the length of +the longest edge. We always try to extract the triangle with the best quality. Note +that clockwise triangles will have negative area. + +Also we remember if there is left and/or right edge that connects +the edge and the vertex. That makes it posible to geometricaly remove the triangle +from the array of edges if it satisfies. + +Although it is teoretically true that every polygon can be triangularized this way, +it is not always possible to find triangle with positive area that doesn't intersect +any edges in the polygon. This is due to the numerical inprecisions created during CSG +or similar operations. +Therefore, we define comparation between two triangles this way: + (1) Triangle that doesn't intersect any edges is better than one that does. + (2) When (1) is indeterminate, the one with greater quality is considered better. + +Note that a triangle with negative area can be found best. In such case, it is not really +created, but only removed from the polygon. This is mostly the case with some small +degenerate parts of polygons. This way, the problematic case is just eliminated without +loosing too much precision in the triangularized representation of the polygon. + +This method can diverge by adding and removing same triangle repeatedly. Therefore, +we don't always start at testing at the first edge in polygon, but move the starting +point when we find some triangle, 'shuffling' the choices of new triangles that way. +*/ + +// a class that handles triangularization of a polygon +class CTriangularizer { +public: + DOUBLE3D tr_vPolygonNormal; + // reference to original polygon (just for debugging) + CBrushPolygon &tr_bpoOriginalPolygon; + // reference to original array of polygon edges + CStaticArray &tr_abpeOriginalEdges; + // temporary array of edges + CDynamicArray tr_abedEdges; + + // major axes of the polygon plane + INDEX tr_iAxis0; + INDEX tr_iAxis1; + + // these describe the triangle curently considered + CBrushEdge *tr_pbedLeft; // left edge of the triangle if found + CBrushEdge *tr_pbedRight; // right edge of the triangle if found + CBrushEdge *tr_pbedBottom; // bottom edge of the triangle + CBrushVertex *tr_pbvxTopVertex; // top vertex of the triangle + DOUBLEplane3D tr_plLeft; // splitter plane of left edge + DOUBLEplane3D tr_plRight; // splitter plane of right edge + DOUBLEplane3D tr_plBottom; // splitter plane of bottom edge + DOUBLEplane3D tr_plEdgeConsidered; // splitter plane of the edge considered bottom + + // these describe the best triangle found yet + DOUBLE tr_fQualityBest; // quality of the best triangle + BOOL tr_bIntersectedBest; // set if best triangle intersects some edges + CBrushEdge *tr_pbedLeftBest; // left edge of the triangle if found + CBrushEdge *tr_pbedRightBest; // right edge of the triangle if found + CBrushEdge *tr_pbedBottomBest; // bottom edge of the triangle + CBrushVertex *tr_pbvxTopVertexBest; // top vertex of the triangle + + // get a vertex coordinates + inline DOUBLE3D GetVertex(CBrushVertex *pbvx) const; + + /* Create a splitter plane for an edge. */ + inline void EdgeToPlane(const DOUBLE3D &vVertex0, const DOUBLE3D &vVertex1, + DOUBLEplane3D &plPlane) const; + /* Clip edge to a plane and check if something remains behind. */ + BOOL ClipEdge(DOUBLE3D &vVertex0, DOUBLE3D &vVertex1, const DOUBLEplane3D &plPlane) const; + /* Check if an edge is entirely or partially inside considered triangle. */ + BOOL EdgeInsideTriangle(const CBrushEdge *pbed) const; + /* Calculate the quality of currently considered triangle. */ + DOUBLE TriangleQuality(void) const; + + /* Check that duplicate or reverse edges do not exist. */ + void CheckForInvalidEdges(void); + /* Add given edge to temporary array. */ + void AddEdge(CBrushVertex *pbvxVertex0, CBrushVertex *pbvxVertex1); + + /* Create an array of forward oriented edges from polygon edges of a polygon. */ + void MakeEdgesForTriangularization(void); + /* Test all edges for intersection with considered triangle. */ + BOOL CheckTriangleAgainstEdges(void); + /* Find best triangle in array of edges. */ + void FindBestTriangle(void); + /* Find if left/right triangle edges already exist. */ + void FindExistingTriangleEdges(void); + /* Remove best triangle from edges. */ + void RemoveBestTriangleFromPolygon(void); + /* Add best triangle to triangles. */ + void AddBestTriangleToTriangles(void); + + /* Print a statement to debugging output file. */ + void DPrintF(char *strFormat, ...); + /* Dump triangle edges to debug output. */ + void DumpEdges(void); + + // find vertices used without duplication + void FindVerticesUsed(void); + // build array of element indices + void MakeElements(void); + +public: + // target array for resulting triangles + CDynamicArray tr_apbvxTriangleVertices; + // array for vertices without duplicates + CStaticStackArray tr_apbvxVertices; + // array for triangle elements + CStaticArray tr_aiElements; + + /* Constructor - do triangularization for a polygon. */ + CTriangularizer(CBrushPolygon &bpoOriginalPolygon); + + INDEX tr_iError; +}; +// get a vertex coordinates +inline DOUBLE3D CTriangularizer::GetVertex(CBrushVertex *pbvx) const +{ +#ifdef OPERATEIN2D + return DOUBLE3D( + pbvx->bvx_vdPreciseRelative(tr_iAxis0), + pbvx->bvx_vdPreciseRelative(tr_iAxis1), + 0); +#else + return pbvx->bvx_vdPreciseRelative; +#endif +} + +/* + * Create a splitter plane for an edge. + */ +inline void CTriangularizer::EdgeToPlane(const DOUBLE3D &vVertex0, const DOUBLE3D &vVertex1, + DOUBLEplane3D &plPlane) const +{ + // make a plane containing the edge, perpendicular to the polygon plane, looking + // to the right of the edge + plPlane = DOUBLEplane3D((vVertex1-vVertex0)*tr_vPolygonNormal, vVertex0); +} + +/* + * Clip edge to a plane and check if something remains behind. + */ +BOOL CTriangularizer::ClipEdge(DOUBLE3D &vVertex0, DOUBLE3D &vVertex1, + const DOUBLEplane3D &plPlane) const +{ + // calculate point distances from clip plane + DOUBLE fDistance0 = plPlane.PointDistance(vVertex0); + DOUBLE fDistance1 = plPlane.PointDistance(vVertex1); + + /* ---- first point behind plane ---- */ + if (fDistance0 < -EPSILON) { + + // if both are back + if (fDistance1 < -EPSILON) { + // whole edge is behind + return TRUE; + + // if first is back, second front + } else if (fDistance1 > +EPSILON) { + // calculate intersection coordinates + vVertex1 = vVertex0-(vVertex0-vVertex1)*fDistance0/(fDistance0-fDistance1); + // the remaining part is behind + return TRUE; + + // if first is back, second on the plane + } else { + // the whole edge is back + return TRUE; + } + + /* ---- first point in front of plane ---- */ + } else if (fDistance0 > +EPSILON) { + + // if first is front, second back + if (fDistance1 < -EPSILON) { + // calculate intersection coordinates + vVertex0 = vVertex1-(vVertex1-vVertex0)*fDistance1/(fDistance1-fDistance0); + // the remaining part is behind + return TRUE; + + // if both are front + } else if (fDistance1 > +EPSILON) { + // whole edge is front + return FALSE; + + // if first is front, second on the plane + } else { + // whole edge is front + return FALSE; + } + + /* ---- first point on the plane ---- */ + } else { + // if first is on the plane, second back + if (fDistance1 < -EPSILON) { + // the whole edge is back + return TRUE; + + // if first is on the plane, second front + } else if (fDistance1 > +EPSILON) { + // whole edge is front + return FALSE; + + // if both are on the plane + } else { + // assume the whole edge is back (!!!! is this correct?) + return TRUE; + } + } +} + +/* + * Check if an edge is entirely or partially inside considered triangle. + */ +BOOL CTriangularizer::EdgeInsideTriangle(const CBrushEdge *pbed) const +{ + // copy edge vertices + DOUBLE3D vVertex0, vVertex1; + vVertex0 = GetVertex(pbed->bed_pbvxVertex0); + vVertex1 = GetVertex(pbed->bed_pbvxVertex1); + + // try to clip it to each triangle edge in turn, + // if anything remains behind - it is inside + return (ClipEdge(vVertex0, vVertex1, tr_plLeft) + &&ClipEdge(vVertex0, vVertex1, tr_plRight) + &&ClipEdge(vVertex0, vVertex1, tr_plBottom)); +} + +/* + * Calculate the quality of currently considered triangle. + */ +DOUBLE CTriangularizer::TriangleQuality(void) const +{ + DOUBLE3D vEdgeBottom = GetVertex(tr_pbedBottom->bed_pbvxVertex1) + - GetVertex(tr_pbedBottom->bed_pbvxVertex0); + + DOUBLE3D vEdgeLeft = GetVertex(tr_pbedBottom->bed_pbvxVertex0) + - GetVertex(tr_pbvxTopVertex); + + DOUBLE3D vEdgeRight = GetVertex(tr_pbvxTopVertex) + - GetVertex(tr_pbedBottom->bed_pbvxVertex1); + + // calculate triangle normal as cross product of two edges + DOUBLE3D vNormal = vEdgeLeft*(-vEdgeRight); + // calculate area as half the length of the normal + DOUBLE fArea = vNormal.Length()/ DOUBLE(2.0); + // area must be initially positive + ASSERT(fArea>=0); + // if triangle normal is opposite to the polygon normal + if (vNormal%tr_vPolygonNormal<0) { + // make area negative + fArea = -fArea; + } + + // find length of all edges + DOUBLE fLengthBottom = vEdgeBottom.Length(); + DOUBLE fLengthLeft = vEdgeLeft .Length(); + DOUBLE fLengthRight = vEdgeRight .Length(); + // find maximum length + DOUBLE fLengthMax = Max(fLengthBottom, Max(fLengthLeft, fLengthRight)); + // maximum length must be positive + ASSERT(fLengthMax>0.0f); + + // quality is division of the area and square of the length of the longest edge + return fArea/(fLengthMax*fLengthMax); +} + +/* + * Create an array of forward oriented edges from polygon edges of a polygon. + */ +void CTriangularizer::MakeEdgesForTriangularization(void) +{ + // get number of edges in polygon + INDEX ctEdges = tr_abpeOriginalEdges.Count(); + // create that much edges in the array + CBrushEdge *pbedEdges = tr_abedEdges.New(ctEdges); + + tr_abedEdges.Lock(); + + // for each edge + for(INDEX iEdge=0; iEdgebed_pbvxVertex1; + bed.bed_pbvxVertex1 = bpe.bpe_pbedEdge->bed_pbvxVertex0; + // if polygon edge is not reversed + } else { + // make edge in array normal + bed.bed_pbvxVertex0 = bpe.bpe_pbedEdge->bed_pbvxVertex0; + bed.bed_pbvxVertex1 = bpe.bpe_pbedEdge->bed_pbvxVertex1; + } + } + + tr_abedEdges.Unlock(); +} + +/* + * Add given edge to temporary array. + */ +void CTriangularizer::AddEdge(CBrushVertex *pbvxVertex0, CBrushVertex *pbvxVertex1) +{ + #ifndef NDEBUG + // for each edge + {FOREACHINDYNAMICARRAY(tr_abedEdges, CBrushEdge, itbed) { + + // must not exist + if (itbed->bed_pbvxVertex0 == pbvxVertex0 + &&itbed->bed_pbvxVertex1 == pbvxVertex1) { + return; + } + ASSERT(itbed->bed_pbvxVertex0 != pbvxVertex0 + ||itbed->bed_pbvxVertex1 != pbvxVertex1); + + // must not have reverse + ASSERT(itbed->bed_pbvxVertex0 != pbvxVertex1 + ||itbed->bed_pbvxVertex1 != pbvxVertex0); + }} + #endif + + // add new edge + CBrushEdge *pbedNew = tr_abedEdges.New(1); + pbedNew->bed_pbvxVertex0 = pbvxVertex0; + pbedNew->bed_pbvxVertex1 = pbvxVertex1; +} + +/* + * Check that duplicate or reverse edges do not exist. + */ +void CTriangularizer::CheckForInvalidEdges(void) +{ + // for each edge + {FOREACHINDYNAMICARRAY(tr_abedEdges, CBrushEdge, itbed1) { + // for each edge + {FOREACHINDYNAMICARRAY(tr_abedEdges, CBrushEdge, itbed2) { + // if same edge + if (&*itbed1 == &*itbed2) { + // skip + continue; + } + CBrushEdge *pbed1 = itbed1; + CBrushEdge *pbed2 = itbed2; + + // must not exist + ASSERT(pbed1->bed_pbvxVertex0 != pbed2->bed_pbvxVertex0 + ||pbed1->bed_pbvxVertex1 != pbed2->bed_pbvxVertex1); + + // must not have reverse + ASSERT(pbed1->bed_pbvxVertex0 != pbed2->bed_pbvxVertex1 + ||pbed1->bed_pbvxVertex1 != pbed2->bed_pbvxVertex0); + }} + }} +} + +/* + * Add best triangle to triangles. + */ +void CTriangularizer::AddBestTriangleToTriangles(void) +{ + // add the triangle to triangles + CBrushVertex **ppbvxTriangle = tr_apbvxTriangleVertices.New(3); + ppbvxTriangle[0] = tr_pbedBottomBest->bed_pbvxVertex0; + ppbvxTriangle[1] = tr_pbedBottomBest->bed_pbvxVertex1; + ppbvxTriangle[2] = tr_pbvxTopVertexBest; +} + +/* + * Remove best triangle from edges. + */ +void CTriangularizer::RemoveBestTriangleFromPolygon(void) +{ + tr_pbedBottom = tr_pbedBottomBest; + tr_pbvxTopVertex = tr_pbvxTopVertexBest; + FindExistingTriangleEdges(); + + tr_pbedLeftBest = tr_pbedLeft; + tr_pbedRightBest = tr_pbedRight; + tr_pbedBottomBest = tr_pbedBottom; + tr_pbvxTopVertexBest = tr_pbvxTopVertex; + + // if left edge was found + if (tr_pbedLeftBest!=NULL) { + // remove the left edge from the edges + tr_abedEdges.Delete(tr_pbedLeftBest); + // if left edge was not found + } else { + // add reverse of the left edge to the edges + AddEdge(tr_pbedBottomBest->bed_pbvxVertex0, tr_pbvxTopVertexBest); + } + + // if right edge was found + if (tr_pbedRightBest!=NULL) { + // remove the right edge from the edges + tr_abedEdges.Delete(tr_pbedRightBest); + // if right edge was not found + } else { + // add reverse of the right edge to the edges + AddEdge(tr_pbvxTopVertexBest, tr_pbedBottomBest->bed_pbvxVertex1); + } + + // remove the base edge from the edges + tr_abedEdges.Delete(tr_pbedBottomBest); +} + +/* + * Find if left/right triangle edges already exist. + */ +void CTriangularizer::FindExistingTriangleEdges(void) +{ + // initialize left edge as not existing + tr_pbedLeft = NULL; + // initialize right edge as not existing + tr_pbedRight = NULL; + + // for each edge + FOREACHINDYNAMICARRAY(tr_abedEdges, CBrushEdge, itbed) { + CBrushEdge *pbed = itbed; + + // if it is the bottom edge of the triangle + if (tr_pbedBottom == itbed) { + // do not test it for intersection + NOTHING; + + // if it is not bottom edge of triangle + } else { + ASSERT(itbed->bed_pbvxVertex0 != tr_pbedBottom->bed_pbvxVertex0 + ||itbed->bed_pbvxVertex1 != tr_pbedBottom->bed_pbvxVertex1); + + // if it is the left edge of the triangle + if (itbed->bed_pbvxVertex1 == tr_pbedBottom->bed_pbvxVertex0 + &&itbed->bed_pbvxVertex0 == tr_pbvxTopVertex) { + // remember it as the left edge + ASSERT(tr_pbedLeft==NULL); + tr_pbedLeft = itbed; + + // if it is the right edge of the triangle + } else if (itbed->bed_pbvxVertex0 == tr_pbedBottom->bed_pbvxVertex1 + &&itbed->bed_pbvxVertex1 == tr_pbvxTopVertex) { + // remember it as the right edge + ASSERT(tr_pbedRight==NULL); + tr_pbedRight = itbed; + } + } + } +} + +/* + * Test all edges for intersection with considered triangle. + */ +BOOL CTriangularizer::CheckTriangleAgainstEdges(void) +{ + // for each edge + FOREACHINDYNAMICARRAY(tr_abedEdges, CBrushEdge, itbed) { + CBrushEdge *pbed = itbed; + + // if it is the bottom edge of the triangle + if (tr_pbedBottom == itbed) { + // do not test it for intersection + NOTHING; + + // if it is not bottom edge of triangle + } else { + ASSERT(itbed->bed_pbvxVertex0 != tr_pbedBottom->bed_pbvxVertex0 + ||itbed->bed_pbvxVertex1 != tr_pbedBottom->bed_pbvxVertex1); + + // if it is the left edge of the triangle + if (itbed->bed_pbvxVertex1 == tr_pbedBottom->bed_pbvxVertex0 + &&itbed->bed_pbvxVertex0 == tr_pbvxTopVertex) { + // do not test it for intersection + NOTHING; + + // if it is the right edge of the triangle + } else if (itbed->bed_pbvxVertex0 == tr_pbedBottom->bed_pbvxVertex1 + &&itbed->bed_pbvxVertex1 == tr_pbvxTopVertex) { + // do not test it for intersection + NOTHING; + + // if it is neither of triangle edges + } else { + // if this edge intersects with any of the triangle edges + if (EdgeInsideTriangle(itbed)) { + return TRUE; + } + } + } + } + // if no intersections are found + return FALSE; +} + +// calculate edge direction (COPIED FROM CTMATH!) +void EdgeDir(const DOUBLE3D &vPoint0, const DOUBLE3D &vPoint1, + DOUBLE3D &vDirection, DOUBLE3D &vReferencePoint) +{ + // if the vertices are reversed +/* if (CompareVertices(vPoint0, vPoint1)<0) { + // swap them + Swap(vPoint0, vPoint1); + // mark edge as reversed + edx_bReverse = TRUE; + + // if the vertices are not reversed + } else { + // mark edge as not reversed + edx_bReverse = FALSE; + } + */ + + // normalize the direction + vDirection = (vPoint1-vPoint0).Normalize(); + /* calculate the reference point on the line from any point on line (p) and direction (d): + r = p - ((p.d)/(d.d))*d + */ + vReferencePoint = vPoint0 - + vDirection * ((vPoint0 % vDirection))/(vDirection % vDirection); +} + +/* + * Print a statement to debugging output file. + */ +void CTriangularizer::DPrintF(char *strFormat, ...) +{ + char strBuffer[256]; + // format the message in buffer + va_list arg; + va_start(arg, strFormat); + vsprintf(strBuffer, strFormat, arg); + + // if the debug output file is not open + if (!_bDebugOutputOpen) { + // open it + try { + _strmDebugOutput.Create_t(_fnmDebugOutput, CTStream::CM_TEXT); + _bDebugOutputOpen = TRUE; + // if not successful + } catch (char *strError) { + (void) strError; + // print nothing + return; + } + } + // write the message to the file + _strmDebugOutput.Write_t(strBuffer, strlen(strBuffer)); +} + +/* + * Dump triangle edges to debug output. + */ +void CTriangularizer::DumpEdges(void) +{ + DPrintF("%d\n", tr_abedEdges.Count()); + FOREACHINDYNAMICARRAY(tr_abedEdges, CBrushEdge, itbed) { + DPrintF("(%f, %f) ->", + GetVertex(itbed->bed_pbvxVertex0)(1), + GetVertex(itbed->bed_pbvxVertex0)(2)); + DPrintF(" (%f, %f) ", + GetVertex(itbed->bed_pbvxVertex1)(1), + GetVertex(itbed->bed_pbvxVertex1)(2)); + + DOUBLE3D vDirection, vReferencePoint; + EdgeDir( + GetVertex(itbed->bed_pbvxVertex0), GetVertex(itbed->bed_pbvxVertex1), + vDirection, vReferencePoint); + + DPrintF("[(%f, %f), ", + vDirection(1), + vDirection(2)); + DPrintF("(%f, %f)]\n", + vReferencePoint(1), + vReferencePoint(2)); + } +} + +// edge offsets used to 'shuffle' triangularization +static INDEX iBottomEdgeOffset; +static INDEX iTopEdgeOffset; + +/* + * Find best triangle in array of edges. + */ +/* NOTE: Currently only searching for first acceptable triangle. +*/ +void CTriangularizer::FindBestTriangle(void) +{ + // clear best triangle description + tr_fQualityBest = DOUBLE(-1E30); + tr_bIntersectedBest = TRUE; + tr_pbedLeftBest = NULL; + tr_pbedRightBest = NULL; + tr_pbedBottomBest = NULL; + tr_pbvxTopVertexBest = NULL; + + iBottomEdgeOffset++; + // for each edge + tr_abedEdges.Lock(); + INDEX ctEdges = tr_abedEdges.Count(); + for(INDEX ibedBottom=0; ibedBottombed_pbvxVertex0 != tr_pbedBottom->bed_pbvxVertex1); + // create bottom splitter + EdgeToPlane(GetVertex(tr_pbedBottom->bed_pbvxVertex0), + GetVertex(tr_pbedBottom->bed_pbvxVertex1), tr_plEdgeConsidered); + + iTopEdgeOffset++; + // for each edge + for(INDEX ibedTop=0; ibedTopbed_pbvxVertex0 + || tr_pbvxTopVertex == tr_pbedBottom->bed_pbvxVertex1) { + // skip this triangle + continue; + } + + // create bottom splitter from the bottom edge splitter + tr_plBottom = tr_plEdgeConsidered; + // create left splitter + EdgeToPlane(GetVertex(tr_pbvxTopVertex), + GetVertex(tr_pbedBottom->bed_pbvxVertex0), tr_plLeft); + // create right splitter + EdgeToPlane(GetVertex(tr_pbedBottom->bed_pbvxVertex1), + GetVertex(tr_pbvxTopVertex), tr_plRight); + + // calculate its quality + DOUBLE fCurrentQuality = TriangleQuality(); + // if triangle is clockwise + if (fCurrentQuality<0) { + continue; + // reverse its splitters + tr_plLeft.Flip(); + tr_plRight.Flip(); + tr_plBottom.Flip(); + } + // check if no edges intersect with considered triangle + BOOL bCurrentIntersected = CheckTriangleAgainstEdges(); + + // if the current triangle is better than the best triangle yet + if ((tr_bIntersectedBest && !bCurrentIntersected) + ||(tr_bIntersectedBest==bCurrentIntersected && fCurrentQuality>tr_fQualityBest)) { + + // find if left/right triangle edges already exist. + FindExistingTriangleEdges(); + // set current triangle as best triangle + tr_bIntersectedBest = bCurrentIntersected; + tr_fQualityBest = fCurrentQuality; + tr_pbedLeftBest = tr_pbedLeft; + tr_pbedRightBest = tr_pbedRight; + tr_pbedBottomBest = tr_pbedBottom; + tr_pbvxTopVertexBest = tr_pbvxTopVertex; + // if the triangle is trivially acceptable + if (!bCurrentIntersected && fCurrentQuality>=QUALITY_ACCEPTTRIVIALLY) { + // finish searching + tr_abedEdges.Unlock(); + return; + } + } + } + } + tr_abedEdges.Unlock(); + +#if 0 + // if no acceptable triangles have been found + if (tr_fQualityBestbsc_abvxVertices, + CBrushVertex, itbvx) { + DPrintF("(0x%p, %f, %f, %f)\n", &(*itbvx), + (*itbvx)(1), (*itbvx)(2), (*itbvx)(3)); + } + */ + + // dump remaining edges + DPrintF("Triangularization failed!\n"); + DPrintF("best quality found: %f\n", tr_fQualityBest); + DPrintF("Remaining edges:\n"); + DumpEdges(); +/* // dump all edges + tr_abedEdges.Clear(); + MakeEdgesForTriangularization(); + DumpEdges(); + */ + + // error! + ASSERTALWAYS("No acceptable triangles found for triangularization!"); + FatalError("No acceptable triangles found for triangularization!\n" + "Debugging information written to file '%s'.", _fnmDebugOutput); + } +#endif +} + + +// find vertices used without duplication +void CTriangularizer::FindVerticesUsed(void) +{ + // make an empty array that will contain the vertices + tr_apbvxVertices.PopAll(); + // for each triangle vertex + tr_apbvxTriangleVertices.Lock(); + for(INDEX ipbvx=0; ipbvxbpl_pldPreciseRelative.GetMaxNormal(); + INDEX iMaxSign = Sgn(bpoOriginalPolygon.bpo_pbplPlane->bpl_pldPreciseRelative(iMaxNormal)); + ASSERT(iMaxSign!=0); + switch(iMaxNormal) { + case 1: + if (iMaxSign==-1) { + tr_iAxis0 = 3; tr_iAxis1 = 2; tr_vPolygonNormal = DOUBLE3D(-1,0,0); + } else { + tr_iAxis0 = 2; tr_iAxis1 = 3; tr_vPolygonNormal = DOUBLE3D(1,0,0); + } + break; + case 2: + if (iMaxSign==-1) { + tr_iAxis0 = 1; tr_iAxis1 = 3; tr_vPolygonNormal = DOUBLE3D(0,-1,0); + } else { + tr_iAxis0 = 3; tr_iAxis1 = 1; tr_vPolygonNormal = DOUBLE3D(0,1,0); + } + break; + case 3: + if (iMaxSign==-1) { + tr_iAxis0 = 2; tr_iAxis1 = 1; tr_vPolygonNormal = DOUBLE3D(0,0,-1); + } else { + tr_iAxis0 = 1; tr_iAxis1 = 2; tr_vPolygonNormal = DOUBLE3D(0,0,1); + } + break; + default: + ASSERT(FALSE); + tr_iAxis0 = 2; tr_iAxis1 = 3; tr_vPolygonNormal = DOUBLE3D(1,0,0); + } + tr_vPolygonNormal = DOUBLE3D(0,0,1); +#else + tr_iAxis0 = -1; tr_iAxis1 = -1; tr_vPolygonNormal = bpoOriginalPolygon.bpo_pbplPlane->bpl_pldPreciseRelative; +#endif + + // create a dynamic array of edges + MakeEdgesForTriangularization(); + tr_iError = -1; + + // estimate max number of triangles + INDEX ctOrgEdges = tr_abpeOriginalEdges.Count(); + INDEX ctMaxHoles = ctOrgEdges; + INDEX ctMaxTriangles = ctOrgEdges-2+2*ctMaxHoles; + + iBottomEdgeOffset = 0; + iTopEdgeOffset = 0; + + #ifdef DUMP_ALLSTEPS + DPrintF("PolygonBegin\n"); + #endif + +// ASSERT(tr_abedEdges.Count()!=8); + // while the array of edges is not empty +//* + INDEX iPasses = 0; + while (tr_abedEdges.Count()>0) { + // if total number of triangles is too large, or searching too long + INDEX ctTriangles = tr_apbvxTriangleVertices.Count()/3; + if (ctTriangles>ctMaxTriangles*2 || iPasses>ctMaxTriangles*2) { + // error, quit triangulation + tr_iError = 2; + return; + } + + #ifdef DUMP_ALLSTEPS + // dump remaining edges + DumpEdges(); + #endif + + // find best triangle + FindBestTriangle(); + #ifdef DUMP_ALLSTEPS + DPrintF("BestQuality=%f\n", tr_fQualityBest); + #endif + // if no triangle is found + if (tr_fQualityBest<0.0) { + // quit searching + tr_iError = 1; + return; + } + if (tr_bIntersectedBest) { + // quit searching + tr_iError = 3; + return; + } + + // if best triangle has positive quality + if (tr_fQualityBest>0.0) { + // add it to triangles + AddBestTriangleToTriangles(); + } + // remove best triangle from edges + RemoveBestTriangleFromPolygon(); + + #ifndef NDEBUG + // check that there are no invalid edges after creating + CheckForInvalidEdges(); + #endif + iPasses++; + } + tr_iError = 0; +//*/ +} + +/* + * Make triangular representation of the polygon. + */ +void CBrushPolygon::Triangulate(void) +{ + // if already triangulated + if (bpo_apbvxTriangleVertices.Count()>0) { + // do nothing + return; + } + + // triangularize the polygon + CTriangularizer tr(*this); + + // find vertices used without duplication + tr.FindVerticesUsed(); + // build array of element indices + tr.MakeElements(); + + // if there was an error + if (tr.tr_iError!=0) { + // report it + // CPrintF( TRANS("Cannot properly triangulate a polygon: error %d!\n"), tr.tr_iError); + // mark the polygon + bpo_ulFlags|=BPOF_INVALIDTRIANGLES; + // if there no errors + } else { + // mark the polygon as triangulated well + bpo_ulFlags&=~BPOF_INVALIDTRIANGLES; + } + + // copy dynamic array of triangles to the triangular representation of the polygon + INDEX ctVertices = tr.tr_apbvxVertices.Count(); + bpo_apbvxTriangleVertices.Clear(); + bpo_apbvxTriangleVertices.New(ctVertices); + for (INDEX iVertex=0; iVertex + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/ChangeLog.txt b/Sources/Engine/ChangeLog.txt new file mode 100644 index 0000000..d25268c --- /dev/null +++ b/Sources/Engine/ChangeLog.txt @@ -0,0 +1,37 @@ +======================================================================== + DYNAMIC LINK LIBRARY : Engine +======================================================================== + + +AppWizard has created this Engine DLL for you. + +This file contains a summary of what you will find in each of the files that +make up your Engine application. + +Engine.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +Engine.cpp + This is the main DLL source file. + +Engine.h + This file contains your DLL exports. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named Engine.pch and a precompiled types file named StdAfx.obj. + + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + + +///////////////////////////////////////////////////////////////////////////// diff --git a/Sources/Engine/Classes/BaseEvents.cpp b/Sources/Engine/Classes/BaseEvents.cpp new file mode 100644 index 0000000..5f28117 --- /dev/null +++ b/Sources/Engine/Classes/BaseEvents.cpp @@ -0,0 +1,80 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/Engine/Classes/BaseEvents.es" + +#include "StdH.h" +#define DECL_DLL ENGINE_API +#include +#include +#include +#include +#include + +#include +#include +CEntityEvent *EInternal::MakeCopy(void) { CEntityEvent *peeCopy = new EInternal(*this); return peeCopy;} +EInternal::EInternal() : CEntityEvent(EVENTCODE_EInternal) {; +}; +CEntityEvent *EVoid::MakeCopy(void) { CEntityEvent *peeCopy = new EVoid(*this); return peeCopy;} +EVoid::EVoid() : CEntityEvent(EVENTCODE_EVoid) {; +}; +CEntityEvent *EReturn::MakeCopy(void) { CEntityEvent *peeCopy = new EReturn(*this); return peeCopy;} +EReturn::EReturn() : CEntityEvent(EVENTCODE_EReturn) {; +}; +CEntityEvent *EBegin::MakeCopy(void) { CEntityEvent *peeCopy = new EBegin(*this); return peeCopy;} +EBegin::EBegin() : CEntityEvent(EVENTCODE_EBegin) {; +}; +CEntityEvent *ETimer::MakeCopy(void) { CEntityEvent *peeCopy = new ETimer(*this); return peeCopy;} +ETimer::ETimer() : CEntityEvent(EVENTCODE_ETimer) {; +}; +CEntityEvent *ETouch::MakeCopy(void) { CEntityEvent *peeCopy = new ETouch(*this); return peeCopy;} +ETouch::ETouch() : CEntityEvent(EVENTCODE_ETouch) {; + ClearToDefault(penOther); + ClearToDefault(bThisMoved); + ClearToDefault(plCollision); +}; +CEntityEvent *EPass::MakeCopy(void) { CEntityEvent *peeCopy = new EPass(*this); return peeCopy;} +EPass::EPass() : CEntityEvent(EVENTCODE_EPass) {; + ClearToDefault(penOther); + ClearToDefault(bThisMoved); +}; +CEntityEvent *EBlock::MakeCopy(void) { CEntityEvent *peeCopy = new EBlock(*this); return peeCopy;} +EBlock::EBlock() : CEntityEvent(EVENTCODE_EBlock) {; + ClearToDefault(penOther); + ClearToDefault(plCollision); +}; +CEntityEvent *EWouldFall::MakeCopy(void) { CEntityEvent *peeCopy = new EWouldFall(*this); return peeCopy;} +EWouldFall::EWouldFall() : CEntityEvent(EVENTCODE_EWouldFall) {; +}; +CEntityEvent *ETeleport::MakeCopy(void) { CEntityEvent *peeCopy = new ETeleport(*this); return peeCopy;} +ETeleport::ETeleport() : CEntityEvent(EVENTCODE_ETeleport) {; +}; +CEntityEvent *EPreLevelChange::MakeCopy(void) { CEntityEvent *peeCopy = new EPreLevelChange(*this); return peeCopy;} +EPreLevelChange::EPreLevelChange() : CEntityEvent(EVENTCODE_EPreLevelChange) {; + ClearToDefault(iUserData); +}; +CEntityEvent *EPostLevelChange::MakeCopy(void) { CEntityEvent *peeCopy = new EPostLevelChange(*this); return peeCopy;} +EPostLevelChange::EPostLevelChange() : CEntityEvent(EVENTCODE_EPostLevelChange) {; + ClearToDefault(iUserData); +}; +CEntityEvent *EFirstWorldBase::MakeCopy(void) { CEntityEvent *peeCopy = new EFirstWorldBase(*this); return peeCopy;} +EFirstWorldBase::EFirstWorldBase() : CEntityEvent(EVENTCODE_EFirstWorldBase) {; +}; +CEntityEvent *EDamage::MakeCopy(void) { CEntityEvent *peeCopy = new EDamage(*this); return peeCopy;} +EDamage::EDamage() : CEntityEvent(EVENTCODE_EDamage) {; + ClearToDefault(penInflictor); + ClearToDefault(vDirection); + ClearToDefault(vHitPoint); + ClearToDefault(fAmount); + ClearToDefault(dmtType); +}; +CEntityEvent *EDeath::MakeCopy(void) { CEntityEvent *peeCopy = new EDeath(*this); return peeCopy;} +EDeath::EDeath() : CEntityEvent(EVENTCODE_EDeath) {; + ClearToDefault(eLastDamage); +}; +CEntityEvent *ETakingBreath::MakeCopy(void) { CEntityEvent *peeCopy = new ETakingBreath(*this); return peeCopy;} +ETakingBreath::ETakingBreath() : CEntityEvent(EVENTCODE_ETakingBreath) {; + ClearToDefault(fBreathDelay); +}; diff --git a/Sources/Engine/Classes/BaseEvents.es b/Sources/Engine/Classes/BaseEvents.es new file mode 100644 index 0000000..930b46c --- /dev/null +++ b/Sources/Engine/Classes/BaseEvents.es @@ -0,0 +1,89 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +5 +%{ +#include "StdH.h" +#define DECL_DLL ENGINE_API +#include +#include +#include +#include +#include +%} + +/* + * These events are used globally + */ +event EInternal { // internal jumping event - do not use +}; +event EVoid { // general void type +}; +event EReturn { // sub procedure return notify +}; +event EBegin { // sent to wait handler when started +}; +event ETimer { // timer elapsed +}; +event ETouch { // one entity touched another while moving + CEntityPointer penOther, // other entity + BOOL bThisMoved, // if this entity has touched other entity + FLOATplane3D plCollision, // plane of collision +}; +event EPass { // one entity passed through another while moving + CEntityPointer penOther, // other entity + BOOL bThisMoved, // if this entity has touched other entity +}; +event EBlock { // ONBLOCK_PUSH or ONBLOCK_STOP entity is blocked + CEntityPointer penOther, // other entity + FLOATplane3D plCollision, // plane of collision +}; +event EWouldFall { // entity cannot move or it would fall over an edge +}; +event ETeleport { // teleport has been activated in your vicinity +}; +event EPreLevelChange { // notifying an entity that a level is about to change + INDEX iUserData, +}; +event EPostLevelChange { // notifying an entity that a level has just changed + INDEX iUserData, +}; +event EFirstWorldBase { // notifying an entity that it is the first worldbase in the world +}; + +enum DamageType { + 1 DMT_EXPLOSION "Explosion", // caused by dynamites, rockets and other ordinary explosives + 2 DMT_PROJECTILE "Projectile", // caused by projectile (non exploding) + 3 DMT_CLOSERANGE "Close range", // caused by close range weapon (chainsaw, head-saw, ...) + 4 DMT_BULLET "Bullets", // caused by ordinary bullets from pistols, rifles etc. + 5 DMT_DROWNING "Drowning", // caused by being without air for too long + 6 DMT_IMPACT "Impact", // caused by impact with some object at high relative velocity + 7 DMT_BRUSH "Brush", // caused by moving brush + 8 DMT_BURNING "Burning", // caused by being burned by fire or lava + 9 DMT_ACID "Acid", // caused by being burned by acid + 10 DMT_TELEPORT "Teleport", // applied to entities in teleport destination + 11 DMT_FREEZING "Freezing", // caused by freezing in cold water + 12 DMT_CANNONBALL "Cannon ball", // caused by cannon ball + 13 DMT_CANNONBALL_EXPLOSION "Cannon ball explosion", // when cannonball explodes + 14 DMT_SPIKESTAB "Spike stab", // stabbed by spikes (usually content type) + 15 DMT_ABYSS "Abyss", // when someone falls off a high ledge into the void + 16 DMT_HEAT "Heat", // walking under open sun too long + 17 DMT_DAMAGER "Damager", // caused by damager + 18 DMT_CHAINSAW "Chain saw", // caused by chainsaw +9999 DMT_NONE "no damage", // internal +}; + +event EDamage { // entity has been damaged + CEntityPointer penInflictor, // entity that inflicted the damage + FLOAT3D vDirection, // where the damage came from (in absolute space) + FLOAT3D vHitPoint, // where the damage hit the entity (in absolute space) + FLOAT fAmount, // amount of damage done + enum DamageType dmtType, // type of damage +}; + +event EDeath { // when this entity dies (health reaches zero) + EDamage eLastDamage, // the damage event that caused the death +}; + +event ETakingBreath { // when this entity takes air after being without it for some time + FLOAT fBreathDelay, // how long it was without air (0=little, 1=drowning) +}; diff --git a/Sources/Engine/Classes/BaseEvents.h b/Sources/Engine/Classes/BaseEvents.h new file mode 100644 index 0000000..f8a28bb --- /dev/null +++ b/Sources/Engine/Classes/BaseEvents.h @@ -0,0 +1,158 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _Engine_Classes_BaseEvents_INCLUDED +#define _Engine_Classes_BaseEvents_INCLUDED 1 +#define EVENTCODE_EInternal 0x00050000 +class DECL_DLL EInternal : public CEntityEvent { +public: +EInternal(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EInternal &e) { e = EInternal(); } ; +#define EVENTCODE_EVoid 0x00050001 +class DECL_DLL EVoid : public CEntityEvent { +public: +EVoid(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EVoid &e) { e = EVoid(); } ; +#define EVENTCODE_EReturn 0x00050002 +class DECL_DLL EReturn : public CEntityEvent { +public: +EReturn(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EReturn &e) { e = EReturn(); } ; +#define EVENTCODE_EBegin 0x00050003 +class DECL_DLL EBegin : public CEntityEvent { +public: +EBegin(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EBegin &e) { e = EBegin(); } ; +#define EVENTCODE_ETimer 0x00050004 +class DECL_DLL ETimer : public CEntityEvent { +public: +ETimer(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(ETimer &e) { e = ETimer(); } ; +#define EVENTCODE_ETouch 0x00050005 +class DECL_DLL ETouch : public CEntityEvent { +public: +ETouch(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOther; +BOOL bThisMoved; +FLOATplane3D plCollision; +}; +DECL_DLL inline void ClearToDefault(ETouch &e) { e = ETouch(); } ; +#define EVENTCODE_EPass 0x00050006 +class DECL_DLL EPass : public CEntityEvent { +public: +EPass(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOther; +BOOL bThisMoved; +}; +DECL_DLL inline void ClearToDefault(EPass &e) { e = EPass(); } ; +#define EVENTCODE_EBlock 0x00050007 +class DECL_DLL EBlock : public CEntityEvent { +public: +EBlock(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOther; +FLOATplane3D plCollision; +}; +DECL_DLL inline void ClearToDefault(EBlock &e) { e = EBlock(); } ; +#define EVENTCODE_EWouldFall 0x00050008 +class DECL_DLL EWouldFall : public CEntityEvent { +public: +EWouldFall(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EWouldFall &e) { e = EWouldFall(); } ; +#define EVENTCODE_ETeleport 0x00050009 +class DECL_DLL ETeleport : public CEntityEvent { +public: +ETeleport(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(ETeleport &e) { e = ETeleport(); } ; +#define EVENTCODE_EPreLevelChange 0x0005000a +class DECL_DLL EPreLevelChange : public CEntityEvent { +public: +EPreLevelChange(); +CEntityEvent *MakeCopy(void); +INDEX iUserData; +}; +DECL_DLL inline void ClearToDefault(EPreLevelChange &e) { e = EPreLevelChange(); } ; +#define EVENTCODE_EPostLevelChange 0x0005000b +class DECL_DLL EPostLevelChange : public CEntityEvent { +public: +EPostLevelChange(); +CEntityEvent *MakeCopy(void); +INDEX iUserData; +}; +DECL_DLL inline void ClearToDefault(EPostLevelChange &e) { e = EPostLevelChange(); } ; +#define EVENTCODE_EFirstWorldBase 0x0005000c +class DECL_DLL EFirstWorldBase : public CEntityEvent { +public: +EFirstWorldBase(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EFirstWorldBase &e) { e = EFirstWorldBase(); } ; +extern DECL_DLL CEntityPropertyEnumType DamageType_enum; +enum DamageType { + DMT_EXPLOSION = 1, + DMT_PROJECTILE = 2, + DMT_CLOSERANGE = 3, + DMT_BULLET = 4, + DMT_DROWNING = 5, + DMT_IMPACT = 6, + DMT_BRUSH = 7, + DMT_BURNING = 8, + DMT_ACID = 9, + DMT_TELEPORT = 10, + DMT_FREEZING = 11, + DMT_CANNONBALL = 12, + DMT_CANNONBALL_EXPLOSION = 13, + DMT_SPIKESTAB = 14, + DMT_ABYSS = 15, + DMT_HEAT = 16, + DMT_DAMAGER = 17, + DMT_CHAINSAW = 18, + DMT_NONE = 9999, +}; +DECL_DLL inline void ClearToDefault(DamageType &e) { e = (DamageType)0; } ; +#define EVENTCODE_EDamage 0x0005000d +class DECL_DLL EDamage : public CEntityEvent { +public: +EDamage(); +CEntityEvent *MakeCopy(void); +CEntityPointer penInflictor; +FLOAT3D vDirection; +FLOAT3D vHitPoint; +FLOAT fAmount; +enum DamageType dmtType; +}; +DECL_DLL inline void ClearToDefault(EDamage &e) { e = EDamage(); } ; +#define EVENTCODE_EDeath 0x0005000e +class DECL_DLL EDeath : public CEntityEvent { +public: +EDeath(); +CEntityEvent *MakeCopy(void); +EDamage eLastDamage; +}; +DECL_DLL inline void ClearToDefault(EDeath &e) { e = EDeath(); } ; +#define EVENTCODE_ETakingBreath 0x0005000f +class DECL_DLL ETakingBreath : public CEntityEvent { +public: +ETakingBreath(); +CEntityEvent *MakeCopy(void); +FLOAT fBreathDelay; +}; +DECL_DLL inline void ClearToDefault(ETakingBreath &e) { e = ETakingBreath(); } ; +#endif // _Engine_Classes_BaseEvents_INCLUDED diff --git a/Sources/Engine/Classes/BaseEvents_tables.h b/Sources/Engine/Classes/BaseEvents_tables.h new file mode 100644 index 0000000..b3d6923 --- /dev/null +++ b/Sources/Engine/Classes/BaseEvents_tables.h @@ -0,0 +1,26 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(DamageType) + EP_ENUMVALUE(DMT_EXPLOSION, "Explosion"), + EP_ENUMVALUE(DMT_PROJECTILE, "Projectile"), + EP_ENUMVALUE(DMT_CLOSERANGE, "Close range"), + EP_ENUMVALUE(DMT_BULLET, "Bullets"), + EP_ENUMVALUE(DMT_DROWNING, "Drowning"), + EP_ENUMVALUE(DMT_IMPACT, "Impact"), + EP_ENUMVALUE(DMT_BRUSH, "Brush"), + EP_ENUMVALUE(DMT_BURNING, "Burning"), + EP_ENUMVALUE(DMT_ACID, "Acid"), + EP_ENUMVALUE(DMT_TELEPORT, "Teleport"), + EP_ENUMVALUE(DMT_FREEZING, "Freezing"), + EP_ENUMVALUE(DMT_CANNONBALL, "Cannon ball"), + EP_ENUMVALUE(DMT_CANNONBALL_EXPLOSION, "Cannon ball explosion"), + EP_ENUMVALUE(DMT_SPIKESTAB, "Spike stab"), + EP_ENUMVALUE(DMT_ABYSS, "Abyss"), + EP_ENUMVALUE(DMT_HEAT, "Heat"), + EP_ENUMVALUE(DMT_DAMAGER, "Damager"), + EP_ENUMVALUE(DMT_CHAINSAW, "Chain saw"), + EP_ENUMVALUE(DMT_NONE, "no damage"), +EP_ENUMEND(DamageType); + diff --git a/Sources/Engine/Classes/MovableBrushEntity.cpp b/Sources/Engine/Classes/MovableBrushEntity.cpp new file mode 100644 index 0000000..3244474 --- /dev/null +++ b/Sources/Engine/Classes/MovableBrushEntity.cpp @@ -0,0 +1,41 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 8 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" + +#include "StdH.h" +#include + +#include +#include +void CMovableBrushEntity::SetDefaultProperties(void) { + CMovableEntity::SetDefaultProperties(); +} + void CMovableBrushEntity::DoMoving(void) +#line 23 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +{ +#line 24 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +CMovableEntity :: DoMoving (); +#line 27 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +} + void CMovableBrushEntity::Read_t(CTStream * istr) +#line 37 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +{ +#line 38 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +CMovableEntity :: Read_t (istr ); +#line 39 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +} + void CMovableBrushEntity::Write_t(CTStream * ostr) +#line 42 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +{ +#line 43 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +CMovableEntity :: Write_t (ostr ); +#line 44 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +} +BOOL CMovableBrushEntity:: +#line 48 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +Dummy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMovableBrushEntity_Dummy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMovableBrushEntity::Dummy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/Engine/Classes/MovableBrushEntity.es b/Sources/Engine/Classes/MovableBrushEntity.es new file mode 100644 index 0000000..366b9bc --- /dev/null +++ b/Sources/Engine/Classes/MovableBrushEntity.es @@ -0,0 +1,49 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +/* + * Brush entity that can move. + */ + +3 +%{ +#include "StdH.h" +#include +%} + +class export CMovableBrushEntity : CMovableEntity { +name "MovableBrushEntity"; +thumbnail ""; +properties: +components: +functions: + /* + * Calculate physics for moving. + */ + export void DoMoving(void) // override from CMovableEntity + { + CMovableEntity::DoMoving(); + // recalculate all bounding boxes relative to new position +// en_pbrBrush->CalculateBoundingBoxes(); // !!! why here (its done in SetPlacement()?) + } + + /* Copy entity from another entity of same class. */ + /*CMovableBrushEntity &operator=(CMovableBrushEntity &enOther) + { + CMovableEntity::operator=(enOther); + return *this; + }*/ + /* Read from stream. */ + export void Read_t( CTStream *istr) // throw char * + { + CMovableEntity::Read_t(istr); + } + /* Write to stream. */ + export void Write_t( CTStream *ostr) // throw char * + { + CMovableEntity::Write_t(ostr); + } + +procedures: + // must have at least one procedure per class + Dummy() {}; +}; diff --git a/Sources/Engine/Classes/MovableBrushEntity.h b/Sources/Engine/Classes/MovableBrushEntity.h new file mode 100644 index 0000000..cc047ef --- /dev/null +++ b/Sources/Engine/Classes/MovableBrushEntity.h @@ -0,0 +1,19 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _Engine_Classes_MovableBrushEntity_INCLUDED +#define _Engine_Classes_MovableBrushEntity_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CMovableBrushEntity_DLLClass; +class DECL_DLL CMovableBrushEntity : public CMovableEntity { +public: + virtual void SetDefaultProperties(void); + void DoMoving(void); + void Read_t(CTStream * istr); + void Write_t(CTStream * ostr); +#define STATE_CMovableBrushEntity_Dummy 0x00030000 + BOOL +#line 48 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +Dummy(const CEntityEvent &__eeInput); +}; +#endif // _Engine_Classes_MovableBrushEntity_INCLUDED diff --git a/Sources/Engine/Classes/MovableBrushEntity_tables.h b/Sources/Engine/Classes/MovableBrushEntity_tables.h new file mode 100644 index 0000000..8f8b9ad --- /dev/null +++ b/Sources/Engine/Classes/MovableBrushEntity_tables.h @@ -0,0 +1,35 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CMovableBrushEntity + +CEntityProperty CMovableBrushEntity_properties[] = { + CEntityProperty() +}; +#define CMovableBrushEntity_propertiesct 0 + + +CEntityComponent CMovableBrushEntity_components[] = { + CEntityComponent() +}; +#define CMovableBrushEntity_componentsct 0 + + +CEventHandlerEntry CMovableBrushEntity_handlers[] = { + {0x00030000, -1, CEntity::pEventHandler(&CMovableBrushEntity:: +#line 48 "D:/SE1_GPL/Sources/Engine/Classes/MovableBrushEntity.es" +Dummy),DEBUGSTRING("CMovableBrushEntity::Dummy")}, +}; +#define CMovableBrushEntity_handlersct ARRAYCOUNT(CMovableBrushEntity_handlers) + +CEntity *CMovableBrushEntity_New(void) { return new CMovableBrushEntity; }; +void CMovableBrushEntity_OnInitClass(void) {}; +void CMovableBrushEntity_OnEndClass(void) {}; +void CMovableBrushEntity_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMovableBrushEntity_OnWorldEnd(CWorld *pwo) {}; +void CMovableBrushEntity_OnWorldInit(CWorld *pwo) {}; +void CMovableBrushEntity_OnWorldTick(CWorld *pwo) {}; +void CMovableBrushEntity_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMovableBrushEntity, CMovableEntity, "MovableBrushEntity", "", 0x00000003); +DECLARE_CTFILENAME(_fnmCMovableBrushEntity_tbn, ""); diff --git a/Sources/Engine/Classes/MovableEntity.cpp b/Sources/Engine/Classes/MovableEntity.cpp new file mode 100644 index 0000000..9944ac6 --- /dev/null +++ b/Sources/Engine/Classes/MovableEntity.cpp @@ -0,0 +1,3885 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 7 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" + +#include "StdH.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define CLEARMEM(var) memset(&var, 0, sizeof(var)) + + +#include +#include +#line 36 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" + + +#define ANYEXCEPTION ... +template CStaticStackArray; + +#define MAXCOLLISIONRETRIES 4*4 +extern FLOAT phy_fCollisionCacheAhead; +extern FLOAT phy_fCollisionCacheAround; +extern FLOAT cli_fPredictionFilter; + +// force breakpoint (debug) +extern INDEX dbg_bBreak; +// must be in separate function to disable stupid optimizer +extern void Breakpoint(void); + +CEntity *GetPredictedSafe(CEntity *pen) +{ + if ((pen->en_ulFlags&(ENF_PREDICTOR|ENF_TEMPPREDICTOR)) == ENF_PREDICTOR) { + return pen->GetPredicted(); + } else { + return pen; + } +} + +// add acceleration to velocity +static inline void AddAcceleration( + FLOAT3D &vCurrentVelocity, const FLOAT3D &vDesiredVelocity, + FLOAT fAcceleration, FLOAT fDecceleration) +{ + // if desired velocity is smaller than current velocity + if (vDesiredVelocity.Length()fAcceleration) { + vCurrentVelocity += vDelta*(fAcceleration/fDelta); + } else { + vCurrentVelocity = vDesiredVelocity; + } +} + +// add gravity acceleration to velocity along an axis +static inline void AddGAcceleration( + FLOAT3D &vCurrentVelocity, const FLOAT3D &vGDir, + FLOAT fGA, FLOAT fGV) +{ + // disassemble speed + FLOAT3D vCurrentParallel, vCurrentOrthogonal; + GetParallelAndNormalComponents(vCurrentVelocity, vGDir, vCurrentOrthogonal, vCurrentParallel); + +/* +IMPORTANT: +This is how this piece of code should look like: + + // if not already going down at max speed + if (! (vCurrentOrthogonal%vGDir>=fGV)) { + // add accelleration to parallel speed + vCurrentOrthogonal+=vGDir*fGA; + + // if going down at max speed + if (vCurrentOrthogonal%vGDir>=fGV) { + // clamp + vCurrentOrthogonal = vGDir*fGV; + } + } + +But, due to need for compatibility with older versions and bad VC code generator, we use this kludge: + */ + +// KLUDGE_BEGIN + + if (_pNetwork->ga_ulDemoMinorVersion<=2) { + Swap(vCurrentOrthogonal, vCurrentParallel); + } + + FLOAT3D vCurrentOrthogonalOrg=vCurrentOrthogonal; + // add accelleration to parallel speed + vCurrentOrthogonal+=vGDir*fGA; + + // if going down at max speed + if (vCurrentOrthogonal%vGDir>=fGV) { + // clamp + vCurrentOrthogonal = vGDir*fGV; + } else { + vCurrentOrthogonalOrg = vCurrentOrthogonal; + } + + if (_pNetwork->ga_ulDemoMinorVersion>2) { + vCurrentOrthogonal=vCurrentOrthogonalOrg; + } +// KLUDGE_END + + // assemble speed back + vCurrentVelocity = vCurrentParallel+vCurrentOrthogonal; +} + +// NOTE: +// this is pulled out into a separate function because, otherwise, VC6 generates +// invalid code when optimizing this. no clue why is that so. + +#pragma inline_depth(0) +static void CheckAndAddGAcceleration(CMovableEntity *pen, FLOAT3D &vTranslationAbsolute, FLOAT fTickQuantum) +{ + // if there is forcefield involved + if (pen->en_fForceA>0.01f) { + // add force acceleration + FLOAT fGV=pen->en_fForceV*fTickQuantum; + FLOAT fGA=pen->en_fForceA*fTickQuantum*fTickQuantum; + AddGAcceleration(vTranslationAbsolute, pen->en_vForceDir, fGA, fGV); + } +} +#pragma inline_depth() // see important note above + + +// add acceleration to velocity, but only along a plane +static inline void AddAccelerationOnPlane( + FLOAT3D &vCurrentVelocity, const FLOAT3D &vDesiredVelocity, + FLOAT fAcceleration, FLOAT fDecceleration, + const FLOAT3D &vPlaneNormal) +{ + FLOAT3D vCurrentParallel, vCurrentOrthogonal; + GetParallelAndNormalComponents(vCurrentVelocity, vPlaneNormal, vCurrentOrthogonal, vCurrentParallel); + FLOAT3D vDesiredParallel; + GetNormalComponent(vDesiredVelocity, vPlaneNormal, vDesiredParallel); + AddAcceleration(vCurrentParallel, vDesiredParallel, fAcceleration, fDecceleration); + vCurrentVelocity = vCurrentParallel+vCurrentOrthogonal; +} + +// add acceleration to velocity, for roller-coaster slope -- slow! +static inline void AddAccelerationOnPlane2( + FLOAT3D &vCurrentVelocity, const FLOAT3D &vDesiredVelocity, + FLOAT fAcceleration, FLOAT fDecceleration, + const FLOAT3D &vPlaneNormal, const FLOAT3D &vGravity) +{ + // get down and horizontal direction + FLOAT3D vDn; + GetNormalComponent(vGravity, vPlaneNormal, vDn); + vDn.Normalize(); + FLOAT3D vRt = vPlaneNormal*vDn; + vRt.Normalize(); + + // add only horizontal acceleration + FLOAT3D vCurrentParallel, vCurrentOrthogonal; + GetParallelAndNormalComponents(vCurrentVelocity, vRt, vCurrentParallel, vCurrentOrthogonal); + FLOAT3D vDesiredParallel; + GetParallelComponent(vDesiredVelocity, vRt, vDesiredParallel); + AddAcceleration(vCurrentParallel, vDesiredParallel, fAcceleration, fDecceleration); + vCurrentVelocity = vCurrentParallel+vCurrentOrthogonal; +} + +// max number of retries during movement +static INDEX _ctTryToMoveCheckCounter; +static INDEX _ctSliding; +static FLOAT3D _vSlideOffDir; // move away direction for sliding +static FLOAT3D _vSlideDir; +static void InitTryToMove(void) +{ + _ctTryToMoveCheckCounter = MAXCOLLISIONRETRIES; + _ctSliding = 0; + _vSlideOffDir = FLOAT3D(0,0,0); + _vSlideDir = FLOAT3D(0,0,0); +} + +// array of forces for current entity +class CEntityForce { +public: + CEntityPointer ef_penEntity; + INDEX ef_iForceType; + FLOAT ef_fRatio; // how much of entity this force gets [0-1] + inline void Clear(void) { + ef_penEntity = NULL; + }; + ~CEntityForce(void) { + Clear(); + }; +}; +static CStaticStackArray _aefForces; + +void ClearMovableEntityCaches(void) +{ + _aefForces.Clear(); +} + + +void CMovableEntity::SetDefaultProperties(void) { + en_vDesiredTranslationRelative = FLOAT3D(0.0f , 0.0f , 0.0f); + en_aDesiredRotationRelative = ANGLE3D(0 , 0 , 0); + en_vCurrentTranslationAbsolute = FLOAT3D(0.0f , 0.0f , 0.0f); + en_aCurrentRotationAbsolute = ANGLE3D(0 , 0 , 0); + en_penReference = NULL; + en_vReferencePlane = FLOAT3D(0.0f , 0.0f , 0.0f); + en_iReferenceSurface = 0; + en_penLastValidReference = NULL; + en_tmLastSignificantVerticalMovement = 0.0f; + en_tmLastBreathed = 0; + en_tmMaxHoldBreath = 5.0f; + en_fDensity = 5000.0f; + en_tmLastSwimDamage = 0; + en_iUpContent = 0; + en_iDnContent = 0; + en_fImmersionFactor = 1.0f; + en_vGravityDir = FLOAT3D(0 , - 1 , 0); + en_fGravityA = 0.0f; + en_fGravityV = 0.0f; + en_vForceDir = FLOAT3D(1 , 0 , 0); + en_fForceA = 0.0f; + en_fForceV = 0.0f; + en_tmJumped = 0; + en_tmMaxJumpControl = 0.5f; + en_fJumpControlMultiplier = 0.5f; + en_fAcceleration = 200.0f; + en_fDeceleration = 40.0f; + en_fStepUpHeight = 1.0f; + en_fStepDnHeight = -1.0f; + en_fBounceDampParallel = 0.5f; + en_fBounceDampNormal = 0.5f; + en_fCollisionSpeedLimit = 20.0f; + en_fCollisionDamageFactor = 20.0f; + en_boxMovingEstimate = FLOATaabbox3D(FLOAT3D (0 , 0 , 0) , 0.01f); + en_boxNearCached = FLOATaabbox3D(FLOAT3D (0 , 0 , 0) , 0.01f); + en_vIntendedTranslation = FLOAT3D(0 , 0 , 0); + en_mIntendedRotation = FLOATmatrix3D(0); + CRationalEntity::SetDefaultProperties(); +} + +#line 319 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::ResetPredictionFilter(void) +#line 320 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 321 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmLastPredictionHead = - 2; +#line 322 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vLastHead = en_plPlacement . pl_PositionVector ; +#line 323 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vPredError = en_vPredErrorLast = FLOAT3D (0 , 0 , 0); +#line 324 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + CMovableEntity::CMovableEntity(void) +#line 328 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 329 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = NULL ; +#line 330 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_apbpoNearPolygons . SetAllocationStep (5); +#line 331 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ResetPredictionFilter (); +#line 332 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + CMovableEntity:: ~ CMovableEntity(void) +#line 334 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 335 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::OnInitialize(const CEntityEvent & eeInput) +#line 339 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 340 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRationalEntity :: OnInitialize (eeInput ); +#line 341 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ClearTemporaryData (); +#line 342 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vIntendedTranslation = FLOAT3D (0 , 0 , 0); +#line 343 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mIntendedRotation . Diagonal (1.0f); +#line 344 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxNearCached = FLOATaabbox3D (); +#line 345 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxMovingEstimate = FLOATaabbox3D (); +#line 346 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = NULL ; +#line 347 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::OnEnd(void) +#line 350 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 352 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_lnInMovers . IsLinked ()){ +#line 353 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_lnInMovers . Remove (); +#line 354 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 355 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ClearTemporaryData (); +#line 356 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxNearCached = FLOATaabbox3D (); +#line 357 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxMovingEstimate = FLOATaabbox3D (); +#line 358 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRationalEntity :: OnEnd (); +#line 359 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::Copy(CEntity & enOther,ULONG ulFlags) +#line 361 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 362 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRationalEntity :: Copy (enOther , ulFlags ); +#line 363 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * pmenOther = (CMovableEntity *) (& enOther ); +#line 365 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(ulFlags & COPY_PREDICTOR ){ +#line 366 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plLastPlacement = pmenOther -> en_plLastPlacement ; +#line 367 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vNextPosition = pmenOther -> en_vNextPosition ; +#line 368 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mNextRotation = pmenOther -> en_mNextRotation ; +#line 371 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vAppliedTranslation = pmenOther -> en_vAppliedTranslation ; +#line 372 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mAppliedRotation = pmenOther -> en_mAppliedRotation ; +#line 373 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxNearCached = pmenOther -> en_boxNearCached ; +#line 374 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxMovingEstimate = pmenOther -> en_boxMovingEstimate ; +#line 375 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = pmenOther -> en_pbpoStandOn ; +#line 376 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_apbpoNearPolygons = pmenOther -> en_apbpoNearPolygons ; +#line 377 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 378 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ClearTemporaryData (); +#line 379 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxNearCached = FLOATaabbox3D (); +#line 380 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxMovingEstimate = FLOATaabbox3D (); +#line 381 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = NULL ; +#line 382 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 384 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ResetPredictionFilter (); +#line 385 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plLastPlacement = pmenOther -> en_plLastPlacement ; +#line 386 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(pmenOther -> en_lnInMovers . IsLinked ()){ +#line 387 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddToMovers (); +#line 388 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 389 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 391 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::ClearTemporaryData(void) +#line 392 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 393 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plLastPlacement = en_plPlacement ; +#line 395 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vNextPosition = en_plPlacement . pl_PositionVector ; +#line 396 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mNextRotation = en_mRotation ; +#line 399 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vAppliedTranslation = FLOAT3D (0 , 0 , 0); +#line 400 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mAppliedRotation . Diagonal (1.0f); +#line 401 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ResetPredictionFilter (); +#line 407 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::ChecksumForSync(ULONG & ulCRC,INDEX iExtensiveSyncCheck) +#line 411 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 412 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRationalEntity :: ChecksumForSync (ulCRC , iExtensiveSyncCheck ); +#line 413 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(iExtensiveSyncCheck > 0){ +#line 414 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pbpoStandOn != NULL ){ +#line 415 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRC_AddLONG (ulCRC , en_pbpoStandOn -> bpo_iInWorld ); +#line 416 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 417 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRC_AddFLOAT (ulCRC , en_apbpoNearPolygons . Count ()); +#line 418 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(iExtensiveSyncCheck > 2){ +#line 419 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +for(INDEX i = 0;i < en_apbpoNearPolygons . Count ();i ++){ +#line 420 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRC_AddLONG (ulCRC , en_apbpoNearPolygons [ i ] -> bpo_iInWorld ); +#line 421 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 422 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 423 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRC_AddBlock (ulCRC , (UBYTE *) & en_vReferencePlane , sizeof (en_vReferencePlane )); +#line 424 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRC_AddBlock (ulCRC , (UBYTE *) & en_vDesiredTranslationRelative , sizeof (en_vDesiredTranslationRelative )); +#line 425 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRC_AddBlock (ulCRC , (UBYTE *) & en_aDesiredRotationRelative , sizeof (en_aDesiredRotationRelative )); +#line 426 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRC_AddBlock (ulCRC , (UBYTE *) & en_vCurrentTranslationAbsolute , sizeof (en_vCurrentTranslationAbsolute )); +#line 427 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRC_AddBlock (ulCRC , (UBYTE *) & en_aCurrentRotationAbsolute , sizeof (en_aCurrentRotationAbsolute )); +#line 428 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 429 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck) +#line 433 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 434 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRationalEntity :: DumpSync_t (strm , iExtensiveSyncCheck ); +#line 435 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(iExtensiveSyncCheck > 0){ +#line 436 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("standon polygon: "); +#line 437 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pbpoStandOn != NULL ){ +#line 438 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("%d\n" , en_pbpoStandOn -> bpo_iInWorld ); +#line 439 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 440 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("\n"); +#line 441 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 442 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("near polygons: %d - " , en_apbpoNearPolygons . Count ()); +#line 443 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(iExtensiveSyncCheck > 2){ +#line 444 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +for(INDEX i = 0;i < en_apbpoNearPolygons . Count ();i ++){ +#line 445 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("%d, " , en_apbpoNearPolygons [ i ] -> bpo_iInWorld ); +#line 446 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 447 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 448 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("\n"); +#line 449 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("desired translation: %g, %g, %g (%08X %08X %08X)\n" , +#line 450 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vDesiredTranslationRelative (1) , +#line 451 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vDesiredTranslationRelative (2) , +#line 452 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vDesiredTranslationRelative (3) , +#line 453 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_vDesiredTranslationRelative (1) , +#line 454 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_vDesiredTranslationRelative (2) , +#line 455 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_vDesiredTranslationRelative (3)); +#line 456 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("desired rotation: %g, %g, %g (%08X %08X %08X)\n" , +#line 457 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative (1) , +#line 458 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative (2) , +#line 459 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative (3) , +#line 460 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_aDesiredRotationRelative (1) , +#line 461 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_aDesiredRotationRelative (2) , +#line 462 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_aDesiredRotationRelative (3)); +#line 463 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("current translation: %g, %g, %g (%08X %08X %08X)\n" , +#line 464 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute (1) , +#line 465 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute (2) , +#line 466 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute (3) , +#line 467 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_vCurrentTranslationAbsolute (1) , +#line 468 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_vCurrentTranslationAbsolute (2) , +#line 469 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_vCurrentTranslationAbsolute (3)); +#line 470 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("current rotation: %g, %g, %g (%08X %08X %08X)\n" , +#line 471 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aCurrentRotationAbsolute (1) , +#line 472 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aCurrentRotationAbsolute (2) , +#line 473 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aCurrentRotationAbsolute (3) , +#line 474 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_aCurrentRotationAbsolute (1) , +#line 475 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_aCurrentRotationAbsolute (2) , +#line 476 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_aCurrentRotationAbsolute (3)); +#line 477 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("reference plane: %g, %g, %g (%08X %08X %08X)\n" , +#line 478 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane (1) , +#line 479 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane (2) , +#line 480 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane (3) , +#line 481 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_vReferencePlane (1) , +#line 482 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_vReferencePlane (2) , +#line 483 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ULONG &) en_vReferencePlane (3)); +#line 484 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("reference surface: %d\n" , en_iReferenceSurface ); +#line 485 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("reference entity: "); +#line 486 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference != NULL ){ +#line 487 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("id: %08X\n" , en_penReference -> en_ulID ); +#line 488 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 489 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +strm . FPrintF_t ("none\n"); +#line 490 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 491 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 492 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::Read_t(CTStream * istr) +#line 496 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 497 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRationalEntity :: Read_t (istr ); +#line 499 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ClearTemporaryData (); +#line 502 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(istr -> PeekID_t () == CChunkID ("MENT")){ +#line 503 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +istr -> ExpectID_t ("MENT"); +#line 505 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX ibpo ; +#line 506 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(* istr ) >> ibpo ; +#line 507 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = GetWorldPolygonPointer (ibpo ); +#line 509 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bAnyNULLs = FALSE ; +#line 510 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX ctbpoNear ; +#line 511 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(* istr ) >> ctbpoNear ; +#line 512 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(ctbpoNear > 0){ +#line 513 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_apbpoNearPolygons . PopAll (); +#line 514 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_apbpoNearPolygons . Push (ctbpoNear ); +#line 515 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +for(INDEX i = 0;i < ctbpoNear ;i ++){ +#line 516 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX ibpo ; +#line 517 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(* istr ) >> ibpo ; +#line 518 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_apbpoNearPolygons [ i ] = GetWorldPolygonPointer (ibpo ); +#line 519 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_apbpoNearPolygons [ i ] == NULL ){ +#line 520 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bAnyNULLs = TRUE ; +#line 521 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 522 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 523 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bAnyNULLs ){ +#line 524 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CPrintF ("NULL saved for near polygon!\n"); +#line 525 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_apbpoNearPolygons . PopAll (); +#line 526 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 527 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 528 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 531 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bWasMoving ; +#line 532 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(* istr ) >> bWasMoving ; +#line 533 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bWasMoving ){ +#line 535 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddToMovers (); +#line 536 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 537 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::Write_t(CTStream * ostr) +#line 540 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 541 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CRationalEntity :: Write_t (ostr ); +#line 543 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ostr -> WriteID_t ("MENT"); +#line 545 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX ibpo ; +#line 546 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ibpo = GetWorldPolygonIndex (en_pbpoStandOn ); +#line 547 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(* ostr ) << ibpo ; +#line 549 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX ctbpoNear = en_apbpoNearPolygons . Count (); +#line 550 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(* ostr ) << ctbpoNear ; +#line 551 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +for(INDEX i = 0;i < ctbpoNear ;i ++){ +#line 552 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX ibpo ; +#line 553 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ibpo = GetWorldPolygonIndex (en_apbpoNearPolygons [ i ]); +#line 554 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(* ostr ) << ibpo ; +#line 555 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 559 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(* ostr ) << en_lnInMovers . IsLinked (); +#line 560 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + CPlacement3D CMovableEntity::GetLerpedPlacement(void)const +#line 564 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 566 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fLerpFactor ; +#line 567 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(IsPredictor ()){ +#line 568 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fLerpFactor = _pTimer -> GetLerpFactor (); +#line 569 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 570 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fLerpFactor = _pTimer -> GetLerpFactor2 (); +#line 571 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 572 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CPlacement3D plLerped ; +#line 573 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +plLerped . Lerp (en_plLastPlacement , en_plPlacement , fLerpFactor ); +#line 574 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penTail = (CMovableEntity *) GetPredictedSafe ((CEntity *) this ); +#line 576 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +extern BOOL _bPredictionActive ; +#line 577 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(_bPredictionActive ){ +#line 579 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vError = penTail -> en_vPredError ; +#line 580 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vError *= pow (cli_fPredictionFilter , fLerpFactor ); +#line 585 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +plLerped . pl_PositionVector -= vError ; +#line 586 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 587 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return plLerped ; +#line 588 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::AddToMovers(void) +#line 591 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 592 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! en_lnInMovers . IsLinked ()){ +#line 593 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pwoWorld -> wo_lhMovers . AddTail (en_lnInMovers ); +#line 594 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 595 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::AddToMoversDuringMoving(void) +#line 598 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 600 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_lnInMovers . IsLinked ()){ +#line 602 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ; +#line 603 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 605 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddToMovers (); +#line 607 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags |= EPF_FORCEADDED ; +#line 608 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::SetDesiredRotation(const ANGLE3D & aRotation) +#line 612 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 613 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative = aRotation ; +#line 614 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddToMovers (); +#line 615 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + const ANGLE3D & CMovableEntity::GetDesiredRotation(void)const {return en_aDesiredRotationRelative ;} + void CMovableEntity::SetDesiredTranslation(const FLOAT3D & vTranslation) +#line 620 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 621 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vDesiredTranslationRelative = vTranslation ; +#line 622 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddToMovers (); +#line 623 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + const FLOAT3D & CMovableEntity::GetDesiredTranslation(void)const {return en_vDesiredTranslationRelative ;} + void CMovableEntity::GiveImpulseTranslationRelative(const FLOAT3D & vImpulseSpeedRelative) +#line 628 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 629 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CPlacement3D plImpulseSpeedAbsolute (vImpulseSpeedRelative , ANGLE3D (0 , 0 , 0)); +#line 630 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +plImpulseSpeedAbsolute . RelativeToAbsolute ( +#line 631 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CPlacement3D (FLOAT3D (0.0f , 0.0f , 0.0f) , en_plPlacement . pl_OrientationAngle )); +#line 632 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute += plImpulseSpeedAbsolute . pl_PositionVector ; +#line 633 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddToMovers (); +#line 634 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::GiveImpulseTranslationAbsolute(const FLOAT3D & vImpulseSpeed) +#line 636 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 637 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute += vImpulseSpeed ; +#line 638 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddToMovers (); +#line 639 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::LaunchAsPropelledProjectile(const FLOAT3D & vImpulseSpeedRelative, +#line 642 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penLauncher) +#line 643 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 644 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vDesiredTranslationRelative = vImpulseSpeedRelative ; +#line 645 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute += vImpulseSpeedRelative * en_mRotation ; +#line 647 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddToMovers (); +#line 648 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::LaunchAsFreeProjectile(const FLOAT3D & vImpulseSpeedRelative, +#line 650 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penLauncher) +#line 651 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 652 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute += vImpulseSpeedRelative * en_mRotation ; +#line 655 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddToMovers (); +#line 656 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::ForceStopTranslation(void) { +#line 660 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vDesiredTranslationRelative = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 661 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 662 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vAppliedTranslation = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 663 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::ForceStopRotation(void) { +#line 667 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative = ANGLE3D (0 , 0 , 0); +#line 668 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aCurrentRotationAbsolute = ANGLE3D (0 , 0 , 0); +#line 669 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mAppliedRotation . Diagonal (1.0f); +#line 670 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::ForceFullStop(void) { +#line 674 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ForceStopTranslation (); +#line 675 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ForceStopRotation (); +#line 676 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::FakeJump(const FLOAT3D & vOrgSpeed,const FLOAT3D & vDirection,FLOAT fStrength, +#line 680 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fParallelMultiplier,FLOAT fNormalMultiplier,FLOAT fMaxExitSpeed,TIME tmControl) +#line 681 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 683 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmJumped = _pTimer -> CurrentTick () - en_tmMaxJumpControl + tmControl ; +#line 686 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vCurrentNormal ; +#line 687 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vCurrentParallel ; +#line 688 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +GetParallelAndNormalComponents (vOrgSpeed , vDirection , vCurrentParallel , vCurrentNormal ); +#line 697 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute = +#line 698 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vCurrentParallel * fParallelMultiplier + +#line 699 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vCurrentNormal * fNormalMultiplier + +#line 700 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDirection * fStrength ; +#line 703 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fLength = en_vCurrentTranslationAbsolute . Length (); +#line 704 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fLength > fMaxExitSpeed ) +#line 705 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 706 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute = +#line 707 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute / fLength * fMaxExitSpeed ; +#line 708 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 716 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_penReference = NULL ; +#line 717 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = NULL ; +#line 718 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 719 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_iReferenceSurface = 0; +#line 722 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddToMovers (); +#line 723 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + ANGLE CMovableEntity::GetRelativeHeading(const FLOAT3D & vDirection) { +#line 727 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ASSERT (Abs (vDirection . Length () - 1) < 0.001f); +#line 729 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fFront = +#line 730 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +- vDirection (1) * en_mRotation (1 , 3) +#line 731 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +- vDirection (2) * en_mRotation (2 , 3) +#line 732 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +- vDirection (3) * en_mRotation (3 , 3); +#line 734 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fLeft = +#line 735 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +- vDirection (1) * en_mRotation (1 , 1) +#line 736 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +- vDirection (2) * en_mRotation (2 , 1) +#line 737 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +- vDirection (3) * en_mRotation (3 , 1); +#line 739 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ATan2 (fLeft , fFront ); +#line 740 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + ANGLE CMovableEntity::GetRelativePitch(const FLOAT3D & vDirection) { +#line 742 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ASSERT (Abs (vDirection . Length () - 1) < 0.001f); +#line 744 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fFront = +#line 745 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +- vDirection (1) * en_mRotation (1 , 3) +#line 746 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +- vDirection (2) * en_mRotation (2 , 3) +#line 747 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +- vDirection (3) * en_mRotation (3 , 3); +#line 749 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fUp = +#line 750 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" ++ vDirection (1) * en_mRotation (1 , 2) +#line 751 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" ++ vDirection (2) * en_mRotation (2 , 2) +#line 752 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" ++ vDirection (3) * en_mRotation (3 , 2); +#line 754 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ATan2 (fUp , fFront ); +#line 755 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::GetReferenceHeadingDirection(const FLOAT3D & vReference,ANGLE aH,FLOAT3D & vDirection) { +#line 759 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ASSERT (Abs (vReference . Length () - 1) < 0.001f); +#line 760 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vY (en_mRotation (1 , 2) , en_mRotation (2 , 2) , en_mRotation (3 , 2)); +#line 761 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vX = (vY * vReference ) . Normalize (); +#line 762 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vMZ = vY * vX ; +#line 763 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDirection = - vX * Sin (aH ) + vMZ * Cos (aH ); +#line 764 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::GetHeadingDirection(ANGLE aH,FLOAT3D & vDirection) { +#line 768 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vX (en_mRotation (1 , 1) , en_mRotation (2 , 1) , en_mRotation (3 , 1)); +#line 769 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vZ (en_mRotation (1 , 3) , en_mRotation (2 , 3) , en_mRotation (3 , 3)); +#line 770 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDirection = - vX * Sin (aH ) - vZ * Cos (aH ); +#line 771 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::GetPitchDirection(ANGLE aH,FLOAT3D & vDirection) { +#line 775 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vY (en_mRotation (1 , 2) , en_mRotation (2 , 2) , en_mRotation (3 , 2)); +#line 776 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vZ (en_mRotation (1 , 3) , en_mRotation (2 , 3) , en_mRotation (3 , 3)); +#line 777 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDirection = - vZ * Cos (aH ) + vY * Sin (aH ); +#line 778 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 781 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CEntity * CMovableEntity::MiscDamageInflictor(void) +#line 782 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 785 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penLastValidReference != NULL ){ +#line 786 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return en_penLastValidReference ; +#line 787 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 788 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CBrushSector * pbsc = GetFirstSector (); +#line 789 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(pbsc == NULL ){ +#line 790 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return this ; +#line 791 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 792 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return pbsc -> bsc_pbmBrushMip -> bm_pbrBrush -> br_penEntity ; +#line 793 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 794 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 795 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 798 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::UpdateOneSectorForce(CBrushSector & bsc,FLOAT fRatio) +#line 799 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 801 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fRatio < 0.01f){ +#line 803 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ; +#line 804 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 805 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX iForceType = bsc . GetForceType (); +#line 806 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CEntity * penEntity = bsc . bsc_pbmBrushMip -> bm_pbrBrush -> br_penEntity ; +#line 826 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CEntityForce * pef = NULL ; +#line 827 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +for(INDEX iForce = 0;iForce < _aefForces . Count ();iForce ++){ +#line 828 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(penEntity == _aefForces [ iForce ] . ef_penEntity +#line 829 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& iForceType == _aefForces [ iForce ] . ef_iForceType ){ +#line 830 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +pef = & _aefForces [ iForce ]; +#line 831 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +break ; +#line 832 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 833 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 836 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(pef == NULL ){ +#line 838 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +pef = _aefForces . Push (1); +#line 839 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +pef -> ef_penEntity = penEntity ; +#line 840 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +pef -> ef_iForceType = iForceType ; +#line 841 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +pef -> ef_fRatio = 0.0f; +#line 842 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 843 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +pef -> ef_fRatio += fRatio ; +#line 844 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 847 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::TestFields(INDEX & iUpContent,INDEX & iDnContent,FLOAT & fImmersionFactor) +#line 848 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 850 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ASSERT (en_RenderType == RT_MODEL || en_RenderType == RT_EDITORMODEL || en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL ); +#line 851 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +iUpContent = 0; +#line 852 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +iDnContent = 0; +#line 853 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fUp = 0.0f; +#line 854 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fDn = 0.0f; +#line 856 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D & vOffset = en_plPlacement . pl_PositionVector ; +#line 857 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATmatrix3D & mRotation = en_mRotation ; +#line 859 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vMin = FLOAT3D (0 , en_pciCollisionInfo -> ci_fMinHeight , 0); +#line 860 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vMax = FLOAT3D (0 , en_pciCollisionInfo -> ci_fMaxHeight , 0); +#line 861 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vMin = vMin * mRotation + vOffset ; +#line 862 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vMax = vMax * mRotation + vOffset ; +#line 864 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CStaticArray < CMovingSphere > & absSpheres = en_pciCollisionInfo -> ci_absSpheres ; +#line 865 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FOREACHINSTATICARRAY (absSpheres , CMovingSphere , itms ){ +#line 866 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +itms -> ms_vRelativeCenter0 = itms -> ms_vCenter * mRotation + vOffset ; +#line 867 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 870 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_aefForces . PopAll (); +#line 872 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{FOREACHSRCOFDST (en_rdSectors , CBrushSector , bsc_rsEntities , pbsc ) +#line 873 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CBrushSector & bsc = * pbsc ; +#line 875 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! bsc . bsc_pbmBrushMip -> IsFirstMip ()){ +#line 877 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +continue ; +#line 878 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 880 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CEntity * penSector = bsc . bsc_pbmBrushMip -> bm_pbrBrush -> br_penEntity ; +#line 883 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(penSector -> en_RenderType != RT_BRUSH ){ +#line 885 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +continue ; +#line 886 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 889 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +double dMin , dMax ; +#line 890 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bsc . bsc_bspBSPTree . FindLineMinMax (FLOATtoDOUBLE (vMin ) , FLOATtoDOUBLE (vMax ) , dMin , dMax ); +#line 893 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX iContent = bsc . GetContentType (); +#line 894 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(iContent != 0){ +#line 896 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(dMax > 0.0f && dMin < 1.0f){ +#line 899 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(dMin < 0.01f){ +#line 901 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +iDnContent = iContent ; +#line 902 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fDn = Max (fDn , FLOAT (dMax )); +#line 903 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 905 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(dMax > 0.99f){ +#line 907 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +iUpContent = iContent ; +#line 908 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fUp = Max (fUp , 1 - FLOAT (dMin )); +#line 909 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 910 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 911 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 914 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +UpdateOneSectorForce (bsc , dMax - dMin ); +#line 916 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ENDFOR ;} +#line 920 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(iUpContent == iDnContent ){ +#line 922 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fImmersionFactor = 1.0f; +#line 924 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 926 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(iUpContent == 0){ +#line 927 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fImmersionFactor = fDn ; +#line 928 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if(iDnContent == 0){ +#line 929 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fImmersionFactor = 1 - fUp ; +#line 930 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 931 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fImmersionFactor = Max (fDn , 1 - fUp ); +#line 932 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 934 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fImmersionFactor < 0.01f){ +#line 935 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fImmersionFactor = 1.0f; +#line 936 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +iDnContent = iUpContent ; +#line 937 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if(fImmersionFactor > 0.99f){ +#line 938 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fImmersionFactor = 1.0f; +#line 939 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +iUpContent = iDnContent ; +#line 940 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 941 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 944 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vGravityA (0 , 0 , 0); +#line 945 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vGravityV (0 , 0 , 0); +#line 946 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vForceA (0 , 0 , 0); +#line 947 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vForceV (0 , 0 , 0); +#line 948 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fRatioSum = 0.0f; +#line 950 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{for(INDEX iForce = 0;iForce < _aefForces . Count ();iForce ++){ +#line 951 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CForceStrength fsGravity ; +#line 952 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CForceStrength fsField ; +#line 953 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_aefForces [ iForce ] . ef_penEntity -> GetForce ( +#line 954 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_aefForces [ iForce ] . ef_iForceType , en_plPlacement . pl_PositionVector , +#line 955 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fsGravity , fsField ); +#line 956 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fRatio = _aefForces [ iForce ] . ef_fRatio ; +#line 957 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fRatioSum += fRatio ; +#line 958 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vGravityA += fsGravity . fs_vDirection * fsGravity . fs_fAcceleration * fRatio ; +#line 959 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vGravityV += fsGravity . fs_vDirection * fsGravity . fs_fVelocity * fRatio ; +#line 960 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fsField . fs_fAcceleration > 0){ +#line 961 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vForceA += fsField . fs_vDirection * fsField . fs_fAcceleration * fRatio ; +#line 962 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vForceV += fsField . fs_vDirection * fsField . fs_fVelocity * fRatio ; +#line 963 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 964 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_aefForces [ iForce ] . Clear (); +#line 965 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}} +#line 966 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fRatioSum > 0){ +#line 967 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vGravityA /= fRatioSum ; +#line 968 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vGravityV /= fRatioSum ; +#line 969 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vForceA /= fRatioSum ; +#line 970 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vForceV /= fRatioSum ; +#line 971 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 972 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_fGravityA = vGravityA . Length (); +#line 973 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_fGravityA < 0.01f){ +#line 974 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_fGravityA = 0; +#line 975 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 976 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_fGravityV = vGravityV . Length (); +#line 977 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vGravityDir = vGravityA / en_fGravityA ; +#line 978 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 979 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_fForceA = vForceA . Length (); +#line 980 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_fForceA < 0.01f){ +#line 981 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_fForceA = 0; +#line 982 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 983 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_fForceV = vForceV . Length (); +#line 984 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vForceDir = vForceA / en_fForceA ; +#line 985 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 986 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_aefForces . PopAll (); +#line 987 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 990 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::TestBreathing(CContentType & ctUp) +#line 991 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 993 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! (en_ulPhysicsFlags & (EPF_HASLUNGS | EPF_HASGILLS ))){ +#line 995 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ; +#line 996 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 998 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bCanBreathe = +#line 999 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ctUp . ct_ulFlags & CTF_BREATHABLE_LUNGS ) && (en_ulPhysicsFlags & EPF_HASLUNGS ) || +#line 1000 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ctUp . ct_ulFlags & CTF_BREATHABLE_GILLS ) && (en_ulPhysicsFlags & EPF_HASGILLS ); +#line 1001 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 1002 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TIME tmBreathDelay = tmNow - en_tmLastBreathed ; +#line 1004 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bCanBreathe ){ +#line 1006 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmLastBreathed = tmNow ; +#line 1008 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(tmBreathDelay > _pTimer -> TickQuantum * 2){ +#line 1010 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ETakingBreath eTakingBreath ; +#line 1011 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +eTakingBreath . fBreathDelay = tmBreathDelay / en_tmMaxHoldBreath ; +#line 1012 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SendEvent (eTakingBreath ); +#line 1013 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1015 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1017 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(tmBreathDelay > en_tmMaxHoldBreath ){ +#line 1019 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +InflictDirectDamage (this , MiscDamageInflictor () , DMT_DROWNING , ctUp . ct_fDrowningDamageAmount , +#line 1020 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plPlacement . pl_PositionVector , - en_vGravityDir ); +#line 1022 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmLastBreathed = tmNow - en_tmMaxHoldBreath + ctUp . ct_tmDrowningDamageDelay ; +#line 1023 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1024 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1025 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1026 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::TestContentDamage(CContentType & ctDn,FLOAT fImmersion) +#line 1027 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1029 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(ctDn . ct_fSwimDamageAmount > 0){ +#line 1030 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 1032 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(ctDn . ct_tmSwimDamageDelay > 0){ +#line 1034 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(tmNow - en_tmLastSwimDamage > ctDn . ct_tmSwimDamageDelay + _pTimer -> TickQuantum ){ +#line 1036 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmLastSwimDamage = tmNow + ctDn . ct_tmSwimDamageDelay ; +#line 1037 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ; +#line 1038 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1039 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1041 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(tmNow - en_tmLastSwimDamage > ctDn . ct_tmSwimDamageFrequency ){ +#line 1043 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +InflictDirectDamage (this , MiscDamageInflictor () , +#line 1044 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(DamageType ) ctDn . ct_iSwimDamageType , ctDn . ct_fSwimDamageAmount * fImmersion , +#line 1045 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plPlacement . pl_PositionVector , - en_vGravityDir ); +#line 1046 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmLastSwimDamage = tmNow ; +#line 1047 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1048 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1050 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(ctDn . ct_fKillImmersion > 0 && fImmersion >= ctDn . ct_fKillImmersion +#line 1051 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& (en_ulFlags & ENF_ALIVE )){ +#line 1053 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +InflictDirectDamage (this , MiscDamageInflictor () , +#line 1054 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(DamageType ) ctDn . ct_iKillDamageType , GetHealth () * 10.0f , +#line 1055 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plPlacement . pl_PositionVector , - en_vGravityDir ); +#line 1056 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1057 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1059 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::TestSurfaceDamage(CSurfaceType & stDn) +#line 1060 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1062 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(stDn . st_fWalkDamageAmount > 0){ +#line 1063 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 1065 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(stDn . st_tmWalkDamageDelay > 0){ +#line 1067 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(tmNow - en_tmLastSwimDamage > stDn . st_tmWalkDamageDelay + _pTimer -> TickQuantum ){ +#line 1069 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmLastSwimDamage = tmNow + stDn . st_tmWalkDamageDelay ; +#line 1070 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ; +#line 1071 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1072 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1074 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(tmNow - en_tmLastSwimDamage > stDn . st_tmWalkDamageFrequency ){ +#line 1076 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +InflictDirectDamage (this , MiscDamageInflictor () , +#line 1077 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(DamageType ) stDn . st_iWalkDamageType , stDn . st_fWalkDamageAmount , +#line 1078 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plPlacement . pl_PositionVector , - en_vGravityDir ); +#line 1079 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmLastSwimDamage = tmNow ; +#line 1080 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1081 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1082 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1085 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::SendTouchEvent(const CClipMove & cmMove) +#line 1086 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1087 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ETouch etouchThis ; +#line 1088 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ETouch etouchOther ; +#line 1089 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +etouchThis . penOther = cmMove . cm_penHit ; +#line 1090 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +etouchThis . bThisMoved = FALSE ; +#line 1091 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +etouchThis . plCollision = cmMove . cm_plClippedPlane ; +#line 1092 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +etouchOther . penOther = this ; +#line 1093 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +etouchOther . bThisMoved = TRUE ; +#line 1094 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +etouchOther . plCollision = cmMove . cm_plClippedPlane ; +#line 1095 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SendEvent (etouchThis ); +#line 1096 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +cmMove . cm_penHit -> SendEvent (etouchOther ); +#line 1097 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1100 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::SendBlockEvent(CClipMove & cmMove) +#line 1101 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1102 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +EBlock eBlock ; +#line 1103 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +eBlock . penOther = cmMove . cm_penHit ; +#line 1104 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +eBlock . plCollision = cmMove . cm_plClippedPlane ; +#line 1105 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SendEvent (eBlock ); +#line 1106 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1108 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL CMovableEntity::IsStandingOnPolygon(CBrushPolygon * pbpo) +#line 1109 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1110 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StartTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1112 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pciCollisionInfo == NULL +#line 1113 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +|| ! (en_pciCollisionInfo -> ci_ulFlags & CIF_CANSTANDONHANDLE )){ +#line 1115 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1116 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1117 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1120 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pbpoStandOn -> bpo_pbscSector -> bsc_pbmBrushMip -> bm_pbrBrush -> br_penEntity -> en_ulCollisionFlags == 0){ +#line 1122 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1123 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1125 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOATplane3D & plPolygon = pbpo -> bpo_pbplPlane -> bpl_plAbsolute ; +#line 1127 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vHandle = en_plPlacement . pl_PositionVector ; +#line 1128 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vHandle (1) += en_pciCollisionInfo -> ci_fHandleY * en_mRotation (1 , 2); +#line 1129 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vHandle (2) += en_pciCollisionInfo -> ci_fHandleY * en_mRotation (2 , 2); +#line 1130 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vHandle (3) += en_pciCollisionInfo -> ci_fHandleY * en_mRotation (3 , 2); +#line 1131 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vHandle -= ((FLOAT3D &) plPolygon ) * en_pciCollisionInfo -> ci_fHandleR ; +#line 1134 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(plPolygon . PointDistance (vHandle ) > 0.01f){ +#line 1136 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1137 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1138 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1141 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX iMajorAxis1 , iMajorAxis2 ; +#line 1142 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +GetMajorAxesForPlane (plPolygon , iMajorAxis1 , iMajorAxis2 ); +#line 1145 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CIntersector isIntersector (vHandle (iMajorAxis1 ) , vHandle (iMajorAxis2 )); +#line 1147 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FOREACHINSTATICARRAY (pbpo -> bpo_abpePolygonEdges , CBrushPolygonEdge , itbpePolygonEdge ){ +#line 1149 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOAT3D & vVertex0 = itbpePolygonEdge -> bpe_pbedEdge -> bed_pbvxVertex0 -> bvx_vAbsolute ; +#line 1150 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOAT3D & vVertex1 = itbpePolygonEdge -> bpe_pbedEdge -> bed_pbvxVertex1 -> bvx_vAbsolute ; +#line 1152 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +isIntersector . AddEdge ( +#line 1153 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vVertex0 (iMajorAxis1 ) , vVertex0 (iMajorAxis2 ) , +#line 1154 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vVertex1 (iMajorAxis1 ) , vVertex1 (iMajorAxis2 )); +#line 1155 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1158 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(isIntersector . IsIntersecting ()){ +#line 1160 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1161 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return TRUE ; +#line 1163 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1165 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1166 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1167 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1168 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1171 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL CMovableEntity::IsPolygonBelowPoint(CBrushPolygon * pbpo,const FLOAT3D & vPoint,FLOAT fMaxDist) +#line 1172 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1173 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StartTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1176 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((pbpo -> bpo_ulFlags & BPOF_PASSABLE ) +#line 1177 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +|| ! AllowForGroundPolygon (pbpo )){ +#line 1179 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1180 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1181 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1184 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOATplane3D & plPolygon = pbpo -> bpo_pbplPlane -> bpl_plAbsolute ; +#line 1187 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fCos = ((const FLOAT3D &) plPolygon ) % en_vGravityDir ; +#line 1189 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fCos > - 0.01f){ +#line 1191 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1192 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1193 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1196 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CSurfaceType & stReference = en_pwoWorld -> wo_astSurfaceTypes [ pbpo -> bpo_bppProperties . bpp_ubSurfaceType ]; +#line 1197 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fCos >= - stReference . st_fClimbSlopeCos && fCos < 0 +#line 1198 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +|| stReference . st_ulFlags & STF_SLIDEDOWNSLOPE ){ +#line 1200 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1201 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1202 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1205 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fD = plPolygon . PointDistance (vPoint ); +#line 1207 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fD < - 0.01f){ +#line 1209 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1210 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1211 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1214 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fDistance = - fD / fCos ; +#line 1216 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fDistance > fMaxDist ){ +#line 1218 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1219 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1220 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1222 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vProjected = vPoint + en_vGravityDir * fDistance ; +#line 1225 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX iMajorAxis1 , iMajorAxis2 ; +#line 1226 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +GetMajorAxesForPlane (plPolygon , iMajorAxis1 , iMajorAxis2 ); +#line 1229 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CIntersector isIntersector (vProjected (iMajorAxis1 ) , vProjected (iMajorAxis2 )); +#line 1231 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FOREACHINSTATICARRAY (pbpo -> bpo_abpePolygonEdges , CBrushPolygonEdge , itbpePolygonEdge ){ +#line 1233 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOAT3D & vVertex0 = itbpePolygonEdge -> bpe_pbedEdge -> bed_pbvxVertex0 -> bvx_vAbsolute ; +#line 1234 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOAT3D & vVertex1 = itbpePolygonEdge -> bpe_pbedEdge -> bed_pbvxVertex1 -> bvx_vAbsolute ; +#line 1236 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +isIntersector . AddEdge ( +#line 1237 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vVertex0 (iMajorAxis1 ) , vVertex0 (iMajorAxis2 ) , +#line 1238 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vVertex1 (iMajorAxis1 ) , vVertex1 (iMajorAxis2 )); +#line 1239 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1242 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(isIntersector . IsIntersecting ()){ +#line 1244 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1245 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return TRUE ; +#line 1247 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1249 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_ISSTANDINGONPOLYGON ); +#line 1250 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1251 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1252 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + BOOL CMovableEntity::AllowForGroundPolygon(CBrushPolygon * pbpo) +#line 1256 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1257 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return TRUE ; +#line 1258 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1261 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL CMovableEntity::IsSomeNearPolygonBelowPoint(const FLOAT3D & vPoint,FLOAT fMaxDist) +#line 1262 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1264 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1265 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1268 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL CMovableEntity::IsSomeSectorPolygonBelowPoint(CBrushSector * pbsc,const FLOAT3D & vPoint,FLOAT fMaxDist) +#line 1269 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1271 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FOREACHINSTATICARRAY (pbsc -> bsc_abpoPolygons , CBrushPolygon , itbpo ){ +#line 1272 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CBrushPolygon * pbpo = itbpo ; +#line 1274 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(IsPolygonBelowPoint (pbpo , vPoint , fMaxDist )){ +#line 1276 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return TRUE ; +#line 1277 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1278 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1280 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1281 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1284 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL CMovableEntity::WouldFallInNextPosition(void) +#line 1285 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1287 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_fStepDnHeight < 0){ +#line 1289 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1290 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1293 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pbpoStandOn != NULL && +#line 1294 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +IsPolygonBelowPoint (en_pbpoStandOn , en_vNextPosition , en_fStepDnHeight )){ +#line 1296 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1297 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1300 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CListHead lhActiveSectors ; +#line 1302 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CStaticStackArray < CBrushPolygon * > & apbpo = en_apbpoNearPolygons ; +#line 1304 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +for(INDEX iPolygon = 0;iPolygon < apbpo . Count ();iPolygon ++){ +#line 1305 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CBrushPolygon * pbpo = apbpo [ iPolygon ]; +#line 1307 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(IsPolygonBelowPoint (pbpo , en_vNextPosition , en_fStepDnHeight )){ +#line 1309 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +lhActiveSectors . RemAll (); +#line 1310 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1311 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1313 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! pbpo -> bpo_pbscSector -> bsc_lnInActiveSectors . IsLinked ()){ +#line 1315 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +lhActiveSectors . AddTail (pbpo -> bpo_pbscSector -> bsc_lnInActiveSectors ); +#line 1316 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1317 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1322 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference != NULL && en_penReference -> en_RenderType == RT_BRUSH +#line 1323 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& ! (en_penReference -> en_ulFlags & ENF_ZONING ) +#line 1324 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& en_penReference -> en_pbrBrush != NULL ){ +#line 1326 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CBrushMip * pbmMip = en_penReference -> en_pbrBrush -> GetFirstMip (); +#line 1328 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FOREACHINDYNAMICARRAY (pbmMip -> bm_abscSectors , CBrushSector , itbsc ){ +#line 1330 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! itbsc -> bsc_lnInActiveSectors . IsLinked ()){ +#line 1332 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +lhActiveSectors . AddTail (itbsc -> bsc_lnInActiveSectors ); +#line 1333 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1334 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1335 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1338 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{FOREACHSRCOFDST (en_rdSectors , CBrushSector , bsc_rsEntities , pbsc ); +#line 1340 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! pbsc -> bsc_lnInActiveSectors . IsLinked ()){ +#line 1342 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +lhActiveSectors . AddTail (pbsc -> bsc_lnInActiveSectors ); +#line 1343 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1344 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ENDFOR ;} +#line 1347 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bSupportFound = FALSE ; +#line 1348 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FOREACHINLIST (CBrushSector , bsc_lnInActiveSectors , lhActiveSectors , itbsc ){ +#line 1349 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CBrushSector * pbsc = itbsc ; +#line 1351 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(pbsc -> bsc_pbmBrushMip -> bm_pbrBrush -> br_penEntity -> en_ulFlags & ENF_ZONING ){ +#line 1353 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{FOREACHDSTOFSRC (pbsc -> bsc_rsEntities , CEntity , en_rdSectors , pen ); +#line 1354 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(pen -> en_RenderType == CEntity :: RT_TERRAIN ){ +#line 1355 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(IsTerrainBelowPoint (pen -> en_ptrTerrain , en_vNextPosition , en_fStepDnHeight , en_vGravityDir )){ +#line 1356 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bSupportFound = TRUE ; +#line 1357 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +goto out ; +#line 1358 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1359 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +continue ; +#line 1360 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1361 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(pen -> en_RenderType != CEntity :: RT_BRUSH && +#line 1362 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +pen -> en_RenderType != CEntity :: RT_FIELDBRUSH ){ +#line 1363 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +break ; +#line 1364 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1366 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CBrushMip * pbmMip = pen -> en_pbrBrush -> GetFirstMip (); +#line 1368 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FOREACHINDYNAMICARRAY (pbmMip -> bm_abscSectors , CBrushSector , itbscInMip ){ +#line 1370 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! itbscInMip -> bsc_lnInActiveSectors . IsLinked ()){ +#line 1372 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +lhActiveSectors . AddTail (itbscInMip -> bsc_lnInActiveSectors ); +#line 1373 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1374 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1375 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ENDFOR ;} +#line 1376 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1378 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(IsSomeSectorPolygonBelowPoint (itbsc , en_vNextPosition , en_fStepDnHeight )){ +#line 1380 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bSupportFound = TRUE ; +#line 1381 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +break ; +#line 1382 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1383 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1384 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +out :; +#line 1387 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +lhActiveSectors . RemAll (); +#line 1390 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ! bSupportFound ; +#line 1391 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1394 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::ClearNextPosition(void) +#line 1395 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1396 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vNextPosition = en_plPlacement . pl_PositionVector ; +#line 1397 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mNextRotation = en_mRotation ; +#line 1398 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1400 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::SetPlacementFromNextPosition(void) +#line 1401 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1402 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StartTimer (CPhysicsProfile :: PTI_SETPLACEMENTFROMNEXTPOSITION ); +#line 1404 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementTimerAveragingCounter (CPhysicsProfile :: PTI_SETPLACEMENTFROMNEXTPOSITION ); +#line 1405 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CPlacement3D plNew ; +#line 1406 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +plNew . pl_PositionVector = en_vNextPosition ; +#line 1407 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +DecomposeRotationMatrixNoSnap (plNew . pl_OrientationAngle , en_mNextRotation ); +#line 1408 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATmatrix3D mRotation ; +#line 1409 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +MakeRotationMatrixFast (mRotation , plNew . pl_OrientationAngle ); +#line 1410 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SetPlacement_internal (plNew , mRotation , TRUE ); +#line 1424 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_SETPLACEMENTFROMNEXTPOSITION ); +#line 1425 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1427 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL CMovableEntity::TryToGoUpstairs(const FLOAT3D & vTranslationAbsolute,const CSurfaceType & stHit, +#line 1428 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bHitStairsOrg) +#line 1429 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1430 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StartTimer (CPhysicsProfile :: PTI_TRYTOGOUPSTAIRS ); +#line 1431 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementTimerAveragingCounter (CPhysicsProfile :: PTI_TRYTOGOUPSTAIRS ); +#line 1434 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vTranslationHorizontal ; +#line 1435 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +GetNormalComponent (vTranslationAbsolute , en_vGravityDir , vTranslationHorizontal ); +#line 1439 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(vTranslationHorizontal . Length () < 0.001f){ +#line 1442 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOGOUPSTAIRS ); +#line 1443 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1444 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1445 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vTranslationHorizontalOrg = vTranslationHorizontal ; +#line 1447 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! bHitStairsOrg ){ +#line 1449 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationHorizontal . Normalize (); +#line 1450 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationHorizontal *= 0.5f; +#line 1451 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1454 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CPlacement3D plOriginal = en_plPlacement ; +#line 1457 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fStairsHeight = 0; +#line 1458 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(stHit . st_fStairsHeight > 0){ +#line 1459 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fStairsHeight = Max (stHit . st_fStairsHeight , en_fStepUpHeight ); +#line 1460 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if(stHit . st_fStairsHeight < 0){ +#line 1461 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fStairsHeight = Min (stHit . st_fStairsHeight , en_fStepUpHeight ); +#line 1462 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1464 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CContentType & ctDn = en_pwoWorld -> wo_actContentTypes [ en_iDnContent ]; +#line 1465 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CContentType & ctUp = en_pwoWorld -> wo_actContentTypes [ en_iUpContent ]; +#line 1468 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bGettingOutOfWater = FALSE ; +#line 1469 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((ctDn . ct_ulFlags & CTF_SWIMABLE ) && ! (ctUp . ct_ulFlags & CTF_SWIMABLE ) +#line 1470 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& en_fImmersionFactor > 0.3f){ +#line 1472 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pciCollisionInfo != NULL ){ +#line 1473 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fStairsHeight = fStairsHeight * 2 + en_fImmersionFactor * +#line 1474 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(en_pciCollisionInfo -> ci_fMaxHeight - en_pciCollisionInfo -> ci_fMinHeight ); +#line 1476 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bGettingOutOfWater = TRUE ; +#line 1477 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1478 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1481 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D avTranslation [ 3 ]; +#line 1482 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +avTranslation [ 0 ] = en_vGravityDir * - fStairsHeight ; +#line 1483 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +avTranslation [ 1 ] = vTranslationHorizontal ; +#line 1484 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +avTranslation [ 2 ] = en_vGravityDir * fStairsHeight ; +#line 1487 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +for(INDEX iStep = 0;iStep < 3;iStep ++){ +#line 1488 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bStepOK = TRUE ; +#line 1490 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vNextPosition = en_plPlacement . pl_PositionVector + avTranslation [ iStep ]; +#line 1491 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mNextRotation = en_mRotation ; +#line 1493 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CClipMove cm (this ); +#line 1494 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pwoWorld -> ClipMove (cm ); +#line 1497 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(cm . cm_fMovementFraction < 1.0f){ +#line 1499 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX iSurfaceHit = 0; +#line 1500 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bHitStairsNow = FALSE ; +#line 1501 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(cm . cm_pbpoHit != NULL ){ +#line 1502 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bHitStairsNow = cm . cm_pbpoHit -> bpo_ulFlags & BPOF_STAIRS ; +#line 1503 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +iSurfaceHit = cm . cm_pbpoHit -> bpo_bppProperties . bpp_ubSurfaceType ; +#line 1504 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1505 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CSurfaceType & stHit = en_pwoWorld -> wo_astSurfaceTypes [ iSurfaceHit ]; +#line 1509 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOAT3D & vHitPlane = cm . cm_plClippedPlane ; +#line 1510 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fPlaneDotG = vHitPlane % en_vGravityDir ; +#line 1511 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fPlaneDotGAbs = Abs (fPlaneDotG ); +#line 1513 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bSlidingAllowed = (fPlaneDotGAbs > - 0.01f && fPlaneDotGAbs < 0.99f) && bHitStairsOrg ; +#line 1515 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bEarlyClipAllowed = +#line 1517 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +iStep == 0 || +#line 1519 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +iStep == 1 && bHitStairsNow || +#line 1521 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +iStep == 2 && +#line 1522 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(vHitPlane % en_vGravityDir < - stHit . st_fClimbSlopeCos || +#line 1523 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bHitStairsNow ); +#line 1526 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bEarlyClipAllowed || bSlidingAllowed ){ +#line 1528 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vNextPosition = en_plPlacement . pl_PositionVector + +#line 1529 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +avTranslation [ iStep ] * (cm . cm_fMovementFraction * 0.98f); +#line 1530 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bSlidingAllowed && iStep != 2){ +#line 1531 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vSliding = cm . cm_plClippedPlane . ProjectDirection ( +#line 1532 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +avTranslation [ iStep ] * (1.0f - cm . cm_fMovementFraction )) + +#line 1533 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vHitPlane * (ClampUp (avTranslation [ iStep ] . Length () , 0.5f) / 100.0f); +#line 1534 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vNextPosition += vSliding ; +#line 1535 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1536 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CClipMove cm (this ); +#line 1537 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pwoWorld -> ClipMove (cm ); +#line 1539 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(cm . cm_fMovementFraction <= 1.0f){ +#line 1541 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bStepOK = FALSE ; +#line 1542 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1544 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1546 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bStepOK = FALSE ; +#line 1547 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1548 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1551 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bStepOK ){ +#line 1553 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SetPlacementFromNextPosition (); +#line 1555 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1557 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vNextPosition = plOriginal . pl_PositionVector ; +#line 1558 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SetPlacementFromNextPosition (); +#line 1560 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOGOUPSTAIRS ); +#line 1562 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1563 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1565 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1571 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! bGettingOutOfWater ){ +#line 1572 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vAppliedTranslation += vTranslationHorizontalOrg ; +#line 1573 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1575 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOGOUPSTAIRS ); +#line 1577 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return TRUE ; +#line 1578 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 1581 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL CMovableEntity::TryToMove(CMovableEntity * penPusher,BOOL bTranslate,BOOL bRotate) +#line 1582 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1585 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(penPusher != NULL ){ +#line 1586 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_ctTryToMoveCheckCounter --; +#line 1587 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1588 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_ctTryToMoveCheckCounter -= 4; +#line 1589 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1591 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(_ctTryToMoveCheckCounter < 0){ +#line 1593 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1594 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1595 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StartTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1596 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementTimerAveragingCounter (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1597 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_TRYTOMOVE ); +#line 1600 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bTranslate ){ +#line 1601 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vNextPosition = en_plPlacement . pl_PositionVector + en_vMoveTranslation ; +#line 1618 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1619 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vNextPosition = en_plPlacement . pl_PositionVector ; +#line 1620 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1621 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bRotate ){ +#line 1623 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mNextRotation = en_mMoveRotation * en_mRotation ; +#line 1624 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1625 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mNextRotation = en_mRotation ; +#line 1626 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1629 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ULONG ulCIFlags = en_pciCollisionInfo -> ci_ulFlags ; +#line 1630 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bIgnoreRotation = ! bRotate || +#line 1631 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +((ulCIFlags & CIF_IGNOREROTATION ) || +#line 1632 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +((ulCIFlags & CIF_IGNOREHEADING ) && +#line 1633 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(en_mMoveRotation (1 , 2) == 0 && en_mMoveRotation (2 , 2) == 1 && en_mMoveRotation (3 , 2) == 0))); +#line 1636 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CClipMove cmMove (this ); +#line 1638 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! bTranslate && bIgnoreRotation ){ +#line 1639 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +cmMove . cm_fMovementFraction = 2.0f; +#line 1640 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_TRYTOMOVE_FAST ); +#line 1641 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1642 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pwoWorld -> ClipMove (cmMove ); +#line 1643 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1646 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(cmMove . cm_fMovementFraction > 1.0f){ +#line 1650 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bTranslate && en_penReference != NULL && +#line 1651 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(en_ulPhysicsFlags & EPF_TRANSLATEDBYGRAVITY ) && +#line 1652 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +! (en_ulPhysicsFlags & (EPF_ONSTEEPSLOPE | EPF_ORIENTINGTOGRAVITY | EPF_FLOATING )) && +#line 1653 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penPusher == NULL && WouldFallInNextPosition ()){ +#line 1655 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SendEvent (EWouldFall ()); +#line 1657 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1658 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1660 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SetPlacementFromNextPosition (); +#line 1661 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bTranslate ){ +#line 1662 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vAppliedTranslation += en_vMoveTranslation ; +#line 1663 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1664 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bRotate ){ +#line 1665 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mAppliedRotation = en_mMoveRotation * en_mAppliedRotation ; +#line 1666 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1668 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_TRYTOMOVE_PASS ); +#line 1669 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1671 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return TRUE ; +#line 1674 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1675 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_TRYTOMOVE_CLIP ); +#line 1695 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(_ctTryToMoveCheckCounter <= 0){ +#line 1697 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1698 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1699 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1702 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(cmMove . cm_pbpoHit != NULL ){ +#line 1704 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((cmMove . cm_pbpoHit -> bpo_ulFlags & BPOF_STAIRS ) +#line 1705 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& ((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_CLIMBORSLIDE )){ +#line 1707 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +cmMove . cm_plClippedPlane = FLOATplane3D (- en_vGravityDir , 0); +#line 1708 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1710 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +INDEX iSurface = cmMove . cm_pbpoHit -> bpo_bppProperties . bpp_ubSurfaceType ; +#line 1711 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pwoWorld -> wo_astSurfaceTypes [ iSurface ] . st_ulFlags & STF_NOIMPACT ){ +#line 1713 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags |= EPF_NOIMPACTTHISTICK ; +#line 1714 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1715 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1719 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((en_ulPhysicsFlags & EPF_TRANSLATEDBYGRAVITY ) && ! (en_ulPhysicsFlags & EPF_FLOATING ) +#line 1720 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& ( +#line 1721 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +((en_vGravityDir % (FLOAT3D &) cmMove . cm_plClippedPlane ) +#line 1722 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +< (en_vGravityDir % en_vReferencePlane )))){ +#line 1724 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_penReference = cmMove . cm_penHit ; +#line 1726 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane = (FLOAT3D &) cmMove . cm_plClippedPlane ; +#line 1727 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = cmMove . cm_pbpoHit ; +#line 1728 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(cmMove . cm_pbpoHit == NULL ){ +#line 1729 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_iReferenceSurface = 0; +#line 1730 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1731 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_iReferenceSurface = cmMove . cm_pbpoHit -> bpo_bppProperties . bpp_ubSurfaceType ; +#line 1732 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1733 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1736 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SendTouchEvent (cmMove ); +#line 1739 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(cmMove . cm_penHit -> en_ulPhysicsFlags & EPF_NOIMPACT ){ +#line 1741 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags |= EPF_NOIMPACTTHISTICK ; +#line 1742 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1745 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vBounce ; +#line 1746 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bBounce = FALSE ; +#line 1747 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_BOUNCE ) && bTranslate ){ +#line 1749 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vParallel , vNormal ; +#line 1750 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +GetParallelAndNormalComponents (en_vMoveTranslation , cmMove . cm_plClippedPlane , +#line 1751 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vNormal , vParallel ); +#line 1752 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vNormal *= - en_fBounceDampNormal ; +#line 1753 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vParallel *= + en_fBounceDampParallel ; +#line 1754 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vBounce = vNormal + vParallel ; +#line 1756 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(vNormal . Length () > 0.1f){ +#line 1758 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bBounce = TRUE ; +#line 1759 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1761 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative *= en_fBounceDampParallel ; +#line 1762 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_aDesiredRotationRelative . Length () < 10){ +#line 1763 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative = ANGLE3D (0 , 0 , 0); +#line 1764 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1765 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1768 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(penPusher != NULL && (cmMove . cm_penHit -> en_ulPhysicsFlags & EPF_PUSHABLE )){ +#line 1769 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableModelEntity * penBlocking = ((CMovableModelEntity *) cmMove . cm_penHit ); +#line 1771 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vRadius = cmMove . cm_penHit -> en_plPlacement . pl_PositionVector - +#line 1772 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penPusher -> en_plPlacement . pl_PositionVector ; +#line 1773 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vPush = (vRadius * penPusher -> en_mMoveRotation - vRadius ); +#line 1775 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vPush += penPusher -> en_vMoveTranslation ; +#line 1778 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penBlocking -> en_vMoveTranslation = vPush ; +#line 1779 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penBlocking -> en_mMoveRotation = penPusher -> en_mMoveRotation ; +#line 1782 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penBlocking -> AddToMoversDuringMoving (); +#line 1784 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1785 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bUnblocked = penBlocking -> TryToMove (penPusher , bTranslate , bRotate ); +#line 1786 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StartTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1788 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bUnblocked ){ +#line 1790 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ClearNextPosition (); +#line 1791 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1792 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return TryToMove (penPusher , bTranslate , bRotate ); +#line 1793 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1795 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SendBlockEvent (cmMove ); +#line 1796 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ClearNextPosition (); +#line 1797 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1798 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1799 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1801 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if( +#line 1802 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_SLIDE ) || +#line 1803 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_BOUNCE ) || +#line 1804 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_CLIMBORSLIDE ) || +#line 1805 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_STOPEXACT )){ +#line 1808 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bTranslate ){ +#line 1811 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vSliding ; +#line 1813 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(_ctSliding == 0){ +#line 1815 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_vSlideOffDir = cmMove . cm_plClippedPlane ; +#line 1817 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vSliding = cmMove . cm_plClippedPlane . ProjectDirection ( +#line 1818 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vMoveTranslation * (1.0f - cmMove . cm_fMovementFraction )); +#line 1819 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_ctSliding ++; +#line 1821 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if(_ctSliding == 1){ +#line 1823 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_vSlideOffDir += cmMove . cm_plClippedPlane ; +#line 1825 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_vSlideDir = _vSlideOffDir * (FLOAT3D &) cmMove . cm_plClippedPlane ; +#line 1826 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(_vSlideDir . Length () > 0.001f){ +#line 1827 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_vSlideDir . Normalize (); +#line 1828 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1829 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_ctSliding ++; +#line 1831 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +GetParallelComponent (en_vMoveTranslation * (1.0f - cmMove . cm_fMovementFraction ) , +#line 1832 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_vSlideDir , vSliding ); +#line 1834 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1836 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_vSlideOffDir += cmMove . cm_plClippedPlane ; +#line 1838 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_vSlideDir = cmMove . cm_plClippedPlane . ProjectDirection (_vSlideDir ); +#line 1839 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_ctSliding ++; +#line 1841 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +GetParallelComponent (en_vMoveTranslation * (1.0f - cmMove . cm_fMovementFraction ) , +#line 1842 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_vSlideDir , vSliding ); +#line 1843 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1844 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ASSERT (IsValidFloat (vSliding (1))); +#line 1845 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ASSERT (IsValidFloat (_vSlideDir (1))); +#line 1846 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ASSERT (IsValidFloat (_vSlideOffDir (1))); +#line 1849 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(cmMove . cm_pbpoHit != NULL ){ +#line 1850 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CSurfaceType & stHit = en_pwoWorld -> wo_astSurfaceTypes [ +#line 1851 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +cmMove . cm_pbpoHit -> bpo_bppProperties . bpp_ubSurfaceType ]; +#line 1853 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(penPusher == NULL +#line 1854 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& (en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_CLIMBORSLIDE ){ +#line 1862 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D & vHitPlane = (FLOAT3D &) cmMove . cm_plClippedPlane ; +#line 1863 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bHitStairs = cmMove . cm_pbpoHit -> bpo_ulFlags & BPOF_STAIRS ; +#line 1866 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((vHitPlane % en_vGravityDir > - stHit . st_fClimbSlopeCos ) +#line 1867 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +|| bHitStairs ){ +#line 1870 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fSlidingVertical2 = en_vMoveTranslation % en_vGravityDir ; +#line 1871 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fSlidingVertical2 *= fSlidingVertical2 ; +#line 1872 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fSliding2 = en_vMoveTranslation % en_vMoveTranslation ; +#line 1873 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((2 * fSlidingVertical2 <= fSliding2 ) +#line 1875 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& TryToGoUpstairs (en_vMoveTranslation , stHit , bHitStairs )){ +#line 1877 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1878 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1879 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1880 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1881 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1882 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1884 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_STOPEXACT ){ +#line 1886 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vSliding = FLOAT3D (0 , 0 , 0); +#line 1887 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1889 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ASSERT (IsValidFloat (vSliding (1))); +#line 1892 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vSliding += _vSlideOffDir * +#line 1893 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ClampUp (en_vMoveTranslation . Length () , 0.5f) / 100.0f); +#line 1896 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_vMoveTranslation . Length () > 0.001f && cmMove . cm_fMovementFraction > 0.002f){ +#line 1898 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vSliding += en_vMoveTranslation * (cmMove . cm_fMovementFraction * 0.985f); +#line 1899 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1902 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(vSliding . ManhattanNorm () < 0.001f){ +#line 1903 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1904 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1905 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1908 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vMoveTranslation = vSliding ; +#line 1909 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ClearNextPosition (); +#line 1910 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1911 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TryToMove (penPusher , bTranslate , bRotate ); +#line 1913 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bBounce ){ +#line 1915 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vAppliedTranslation = vBounce ; +#line 1917 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_penReference = NULL ; +#line 1918 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 1919 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_iReferenceSurface = 0; +#line 1920 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1923 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1926 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if(bRotate ){ +#line 1928 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_BOUNCE ){ +#line 1930 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative *= en_fBounceDampParallel ; +#line 1931 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_aDesiredRotationRelative . Length () < 10){ +#line 1932 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative = ANGLE3D (0 , 0 , 0); +#line 1933 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1934 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1936 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1937 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1939 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vMoveTranslation = cmMove . cm_vClippedLine * - 1.2f; +#line 1941 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ClearNextPosition (); +#line 1942 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1943 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TryToMove (penPusher , TRUE , bRotate ); +#line 1945 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1946 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1948 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1949 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1952 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 1954 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SendBlockEvent (cmMove ); +#line 1955 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ClearNextPosition (); +#line 1956 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_TRYTOTRANSLATE ); +#line 1957 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return FALSE ; +#line 1958 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1959 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 1960 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::ClearMovingTemp(void) +#line 1984 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 1988 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ClearNextPosition (); +#line 1989 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CLEARMEM (en_vMoveTranslation ); +#line 1990 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CLEARMEM (en_mMoveRotation ); +#line 1991 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CLEARMEM (en_vAppliedTranslation ); +#line 1992 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CLEARMEM (en_mAppliedRotation ); +#line 1993 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::PreMoving(void) +#line 1997 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 2006 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(_pNetwork -> ga_ulDemoMinorVersion <= 5){ +#line 2007 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +PreMovingOld (); +#line 2008 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2009 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +PreMovingNew (); +#line 2010 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2011 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 2012 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::PreMovingNew(void) +#line 2013 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 2014 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pciCollisionInfo == NULL ){ +#line 2015 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ; +#line 2016 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2022 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StartTimer (CPhysicsProfile :: PTI_PREMOVING ); +#line 2023 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementTimerAveragingCounter (CPhysicsProfile :: PTI_PREMOVING ); +#line 2026 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plLastPlacement = en_plPlacement ; +#line 2029 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , itenChild ){ +#line 2031 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((itenChild -> en_ulPhysicsFlags & EPF_MOVABLE ) +#line 2032 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& ! ((CMovableEntity *) & * itenChild ) -> en_lnInMovers . IsLinked ()){ +#line 2033 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penChild = ((CMovableEntity *) & * itenChild ); +#line 2035 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penChild -> en_plLastPlacement = penChild -> en_plPlacement ; +#line 2036 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2037 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}} +#line 2039 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fTickQuantum = _pTimer -> TickQuantum ; +#line 2042 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(dbg_bBreak ){ +#line 2043 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +dbg_bBreak = FALSE ; +#line 2044 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +try { +#line 2045 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +Breakpoint (); +#line 2046 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}catch (ANYEXCEPTION ){ +#line 2047 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CPrintF ("Breakpoint!\n"); +#line 2048 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}; +#line 2049 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2057 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOAT fMaxSpeed = 300.0f; +#line 2058 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute (1) = Clamp (en_vCurrentTranslationAbsolute (1) , - fMaxSpeed , + fMaxSpeed ); +#line 2059 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute (2) = Clamp (en_vCurrentTranslationAbsolute (2) , - fMaxSpeed , + fMaxSpeed ); +#line 2060 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute (3) = Clamp (en_vCurrentTranslationAbsolute (3) , - fMaxSpeed , + fMaxSpeed ); +#line 2063 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_RenderType == RT_MODEL || en_RenderType == RT_EDITORMODEL || +#line 2064 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL ){ +#line 2066 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TestFields (en_iUpContent , en_iDnContent , en_fImmersionFactor ); +#line 2068 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_ulPhysicsFlags & EPF_STICKYFEET ){ +#line 2070 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vPoint ; +#line 2071 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATplane3D plPlane ; +#line 2072 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fDistanceToEdge ; +#line 2073 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(GetNearestPolygon (vPoint , plPlane , fDistanceToEdge )){ +#line 2074 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vGravityDir = - (FLOAT3D &) plPlane ; +#line 2075 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2076 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2077 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2078 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CContentType & ctDn = en_pwoWorld -> wo_actContentTypes [ en_iDnContent ]; +#line 2079 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CContentType & ctUp = en_pwoWorld -> wo_actContentTypes [ en_iUpContent ]; +#line 2082 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TestBreathing (ctUp ); +#line 2084 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TestContentDamage (ctDn , en_fImmersionFactor ); +#line 2086 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference != NULL ){ +#line 2087 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CSurfaceType & stReference = en_pwoWorld -> wo_astSurfaceTypes [ en_iReferenceSurface ]; +#line 2088 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TestSurfaceDamage (stReference ); +#line 2089 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2092 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fBouyancy = (1 - +#line 2093 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ctDn . ct_fDensity / en_fDensity ) * en_fImmersionFactor - +#line 2094 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ctUp . ct_fDensity / en_fDensity ) * (1 - en_fImmersionFactor )); +#line 2095 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fSpeedModifier = +#line 2096 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctDn . ct_fSpeedMultiplier * en_fImmersionFactor + +#line 2097 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctUp . ct_fSpeedMultiplier * (1 - en_fImmersionFactor ); +#line 2098 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fFluidFriction = +#line 2099 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctDn . ct_fFluidFriction * en_fImmersionFactor + +#line 2100 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctUp . ct_fFluidFriction * (1 - en_fImmersionFactor ); +#line 2101 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fControlMultiplier = +#line 2102 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctDn . ct_fControlMultiplier * en_fImmersionFactor + +#line 2103 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctUp . ct_fControlMultiplier * (1 - en_fImmersionFactor ); +#line 2106 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vDesiredTranslationAbsolute = en_vDesiredTranslationRelative ; +#line 2108 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! (en_ulPhysicsFlags & EPF_ABSOLUTETRANSLATE )){ +#line 2109 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute *= en_mRotation ; +#line 2110 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2112 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute *= fTickQuantum ; +#line 2113 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ANGLE3D aRotationRelative ; +#line 2114 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +aRotationRelative (1) = en_aDesiredRotationRelative (1) * fTickQuantum ; +#line 2115 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +aRotationRelative (2) = en_aDesiredRotationRelative (2) * fTickQuantum ; +#line 2116 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +aRotationRelative (3) = en_aDesiredRotationRelative (3) * fTickQuantum ; +#line 2118 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATmatrix3D mRotationAbsolute ; +#line 2120 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_PUSH ){ +#line 2121 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATmatrix3D mNewRotation ; +#line 2122 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +MakeRotationMatrixFast (mNewRotation , en_plPlacement . pl_OrientationAngle + aRotationRelative ); +#line 2123 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mRotationAbsolute = mNewRotation * ! en_mRotation ; +#line 2125 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2126 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +MakeRotationMatrixFast (mRotationAbsolute , aRotationRelative ); +#line 2127 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mRotationAbsolute = en_mRotation * (mRotationAbsolute * ! en_mRotation ); +#line 2128 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2131 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute *= fSpeedModifier ; +#line 2134 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fJump = - en_mRotation . GetColumn (2) % vDesiredTranslationAbsolute ; +#line 2136 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bReferenceMovingInY = FALSE ; +#line 2137 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bReferenceRotatingNonY = FALSE ; +#line 2139 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference != NULL && (en_penReference -> en_ulPhysicsFlags & EPF_MOVABLE )){ +#line 2140 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penReference = (CMovableEntity *) (CEntity *) en_penReference ; +#line 2142 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOAT3D & vReferenceTranslation = penReference -> en_vIntendedTranslation ; +#line 2143 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOATmatrix3D & mReferenceRotation = penReference -> en_mIntendedRotation ; +#line 2145 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vRadius = en_plPlacement . pl_PositionVector +#line 2146 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +- penReference -> en_plPlacement . pl_PositionVector ; +#line 2147 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vReferenceDelta = vReferenceTranslation + vRadius * mReferenceRotation - vRadius ; +#line 2149 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute += vReferenceDelta ; +#line 2150 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mRotationAbsolute = mReferenceRotation * mRotationAbsolute ; +#line 2153 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bReferenceMovingInY = (vReferenceDelta % en_vGravityDir != 0.0f); +#line 2154 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bReferenceRotatingNonY = ((en_vGravityDir * mReferenceRotation ) % en_vGravityDir ) > 0.01f; +#line 2155 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2157 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vTranslationAbsolute = en_vCurrentTranslationAbsolute * fTickQuantum ; +#line 2160 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags &= ~ EPF_ORIENTINGTOGRAVITY ; +#line 2162 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_ulPhysicsFlags & EPF_ORIENTEDBYGRAVITY ){ +#line 2164 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vDown ; +#line 2165 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDown (1) = - en_mRotation (1 , 2); +#line 2166 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDown (2) = - en_mRotation (2 , 2); +#line 2167 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDown (3) = - en_mRotation (3 , 2); +#line 2170 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fCos = vDown % en_vGravityDir ; +#line 2172 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fCos < 0.99999f){ +#line 2174 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags |= EPF_ORIENTINGTOGRAVITY ; +#line 2177 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ANGLE a = ACos (fCos ); +#line 2178 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(Abs (a ) > 20){ +#line 2179 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +a = 20 * Sgn (a ); +#line 2180 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2181 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fRad = RadAngle (a ); +#line 2184 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vAxis = vDown * en_vGravityDir ; +#line 2185 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fLen = vAxis . Length (); +#line 2186 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fLen < 0.01f){ +#line 2187 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vAxis (1) = en_mRotation (1 , 3); +#line 2188 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vAxis (2) = en_mRotation (2 , 3); +#line 2189 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vAxis (3) = en_mRotation (3 , 3); +#line 2192 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if(! bReferenceRotatingNonY ){ +#line 2193 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fRad /= fLen ; +#line 2194 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2195 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vAxis *= fRad ; +#line 2198 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATmatrix3D mGRotation ; +#line 2199 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mGRotation (1 , 1) = 1;mGRotation (1 , 2) = - vAxis (3);mGRotation (1 , 3) = vAxis (2); +#line 2200 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mGRotation (2 , 1) = vAxis (3);mGRotation (2 , 2) = 1;mGRotation (2 , 3) = - vAxis (1); +#line 2201 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mGRotation (3 , 1) = - vAxis (2);mGRotation (3 , 2) = vAxis (1);mGRotation (3 , 3) = 1; +#line 2202 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +OrthonormalizeRotationMatrix (mGRotation ); +#line 2205 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mRotationAbsolute = mGRotation * mRotationAbsolute ; +#line 2206 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2207 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2210 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags &= ~ EPF_FLOATING ; +#line 2212 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT ACC = en_fAcceleration * fTickQuantum * fTickQuantum ; +#line 2213 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT DEC = en_fDeceleration * fTickQuantum * fTickQuantum ; +#line 2215 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! (en_ulPhysicsFlags & EPF_TRANSLATEDBYGRAVITY )){ +#line 2217 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_ulPhysicsFlags & EPF_NOACCELERATION ){ +#line 2218 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute = vDesiredTranslationAbsolute ; +#line 2219 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2220 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAcceleration (vTranslationAbsolute , vDesiredTranslationAbsolute , +#line 2221 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ACC * fControlMultiplier , +#line 2222 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +DEC * fControlMultiplier ); +#line 2223 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2225 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if((fBouyancy * en_fGravityA < 0.5f && (ctDn . ct_ulFlags & (CTF_SWIMABLE | CTF_FLYABLE )))){ +#line 2227 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags |= EPF_FLOATING ; +#line 2229 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_ulPhysicsFlags & EPF_NOACCELERATION ){ +#line 2230 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute = vDesiredTranslationAbsolute ; +#line 2231 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2232 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAcceleration (vTranslationAbsolute , vDesiredTranslationAbsolute , +#line 2233 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ACC * fControlMultiplier , +#line 2234 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +DEC * fControlMultiplier ); +#line 2235 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2238 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fBouyancy < - 0.1f){ +#line 2239 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGV = en_fGravityV * fTickQuantum * fSpeedModifier ; +#line 2240 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGA = (en_fGravityA * - fBouyancy ) * fTickQuantum * fTickQuantum ; +#line 2241 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAcceleration (vTranslationAbsolute , en_vGravityDir * - fGV , fGA , fGA ); +#line 2242 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if(fBouyancy > + 0.1f){ +#line 2243 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGV = en_fGravityV * fTickQuantum * fSpeedModifier ; +#line 2244 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGA = (en_fGravityA * fBouyancy ) * fTickQuantum * fTickQuantum ; +#line 2245 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAcceleration (vTranslationAbsolute , en_vGravityDir * fGV , fGA , fGA ); +#line 2246 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2249 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2250 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bGravityAlongPolygon = TRUE ; +#line 2252 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pbpoStandOn == NULL || ! IsStandingOnPolygon (en_pbpoStandOn ) || bReferenceMovingInY +#line 2253 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +|| (en_ulPhysicsFlags & EPF_ORIENTINGTOGRAVITY )){ +#line 2255 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = NULL ; +#line 2256 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference == NULL || bReferenceMovingInY ){ +#line 2257 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bGravityAlongPolygon = FALSE ; +#line 2258 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2259 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2262 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! bGravityAlongPolygon ){ +#line 2263 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_GRAVITY_NONTRIVIAL ); +#line 2266 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGV = en_fGravityV * fTickQuantum * fSpeedModifier ; +#line 2267 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGA = (en_fGravityA * fBouyancy ) * fTickQuantum * fTickQuantum ; +#line 2268 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddGAcceleration (vTranslationAbsolute , en_vGravityDir , fGA , fGV ); +#line 2270 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2271 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_GRAVITY_TRIVIAL ); +#line 2274 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vPolygonDir = - en_vReferencePlane ; +#line 2276 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vGParallel , vGNormal ; +#line 2277 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +GetParallelAndNormalComponents (en_vGravityDir , vPolygonDir , vGNormal , vGParallel ); +#line 2279 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fFactor = vGParallel . Length (); +#line 2281 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fFactor > 0.001f){ +#line 2282 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGV = en_fGravityV * fTickQuantum * fSpeedModifier ; +#line 2283 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGA = (en_fGravityA * fBouyancy ) * fTickQuantum * fTickQuantum ; +#line 2284 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddGAcceleration (vTranslationAbsolute , vGParallel / fFactor , fGA * fFactor , fGV * fFactor ); +#line 2285 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2288 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fPolyGA = (vPolygonDir % en_vGravityDir ) * en_fGravityA ; +#line 2289 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fYSpeed = vPolygonDir % vTranslationAbsolute ; +#line 2290 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fYSpeed > 0 && fYSpeed < fPolyGA ){ +#line 2291 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute -= vPolygonDir * fYSpeed ; +#line 2292 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2295 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_BOUNCE ){ +#line 2297 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative *= en_fJumpControlMultiplier ; +#line 2298 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_aDesiredRotationRelative . Length () < 10){ +#line 2299 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative = ANGLE3D (0 , 0 , 0); +#line 2300 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2301 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2302 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2304 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CSurfaceType & stReference = en_pwoWorld -> wo_astSurfaceTypes [ en_iReferenceSurface ]; +#line 2307 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference != NULL ){ +#line 2308 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fPlaneY = (en_vGravityDir % en_vReferencePlane ); +#line 2309 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fPlaneYAbs = Abs (fPlaneY ); +#line 2310 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fFriction = stReference . st_fFriction ; +#line 2312 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fPlaneY >= - stReference . st_fClimbSlopeCos && fPlaneY < 0 +#line 2313 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +|| (stReference . st_ulFlags & STF_SLIDEDOWNSLOPE ) && fPlaneY > - 0.99f){ +#line 2314 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags |= EPF_ONSTEEPSLOPE ; +#line 2316 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAccelerationOnPlane2 ( +#line 2317 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute , +#line 2318 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute , +#line 2319 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ACC * fPlaneYAbs * fPlaneYAbs * fFriction * fControlMultiplier , +#line 2320 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +DEC * fPlaneYAbs * fPlaneYAbs * fFriction * fControlMultiplier , +#line 2321 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane , +#line 2322 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vGravityDir ); +#line 2324 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2325 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags &= ~ EPF_ONSTEEPSLOPE ; +#line 2327 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAccelerationOnPlane ( +#line 2328 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute , +#line 2329 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute , +#line 2330 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ACC * fPlaneYAbs * fPlaneYAbs * fFriction * fControlMultiplier , +#line 2331 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +DEC * fPlaneYAbs * fPlaneYAbs * fFriction * fControlMultiplier , +#line 2332 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane ); +#line 2333 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2335 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fJump < - 0.01f && (fPlaneY < - stReference . st_fJumpSlopeCos +#line 2336 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +|| _pTimer -> CurrentTick () > en_tmLastSignificantVerticalMovement + 0.25f)){ +#line 2338 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute += en_vGravityDir * fJump ; +#line 2339 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmJumped = _pTimer -> CurrentTick (); +#line 2340 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = NULL ; +#line 2341 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2344 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2346 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(_pTimer -> CurrentTick () - en_tmJumped < en_tmMaxJumpControl ){ +#line 2348 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAccelerationOnPlane ( +#line 2349 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute , +#line 2350 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute , +#line 2351 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ACC * fControlMultiplier * en_fJumpControlMultiplier , +#line 2352 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +DEC * fControlMultiplier * en_fJumpControlMultiplier , +#line 2353 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATplane3D (en_vGravityDir , 0)); +#line 2354 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2357 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fJump < - 0.01f && +#line 2358 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pTimer -> CurrentTick () > en_tmLastSignificantVerticalMovement + 0.25f){ +#line 2360 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute += en_vGravityDir * fJump ; +#line 2361 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmJumped = _pTimer -> CurrentTick (); +#line 2362 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = NULL ; +#line 2363 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2364 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2365 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2369 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CheckAndAddGAcceleration (this , vTranslationAbsolute , fTickQuantum ); +#line 2372 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fFluidFriction > 0.01f){ +#line 2374 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAcceleration (vTranslationAbsolute , FLOAT3D (0.0f , 0.0f , 0.0f) , +#line 2375 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +0.0f , DEC * fFluidFriction ); +#line 2376 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2379 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((en_ulPhysicsFlags & EPF_CANFADESPINNING ) && +#line 2380 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +((ctDn . ct_ulFlags & CTF_FADESPINNING ) || (ctUp . ct_ulFlags & CTF_FADESPINNING ))){ +#line 2382 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative *= (1 - fSpeedModifier * 0.05f); +#line 2383 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_aDesiredRotationRelative . Length () < 10){ +#line 2384 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative = ANGLE3D (0 , 0 , 0); +#line 2385 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2386 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2389 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pbpoStandOn == NULL && (vTranslationAbsolute . ManhattanNorm () > 1E-5f || +#line 2390 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane % en_vGravityDir < 0.0f)){ +#line 2391 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_penReference = NULL ; +#line 2392 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 2393 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_iReferenceSurface = 0; +#line 2394 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2396 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vIntendedTranslation = vTranslationAbsolute ; +#line 2397 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mIntendedRotation = mRotationAbsolute ; +#line 2402 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATaabbox3D box ; +#line 2403 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pciCollisionInfo -> MakeBoxAtPlacement (FLOAT3D (0 , 0 , 0) , en_mRotation , box ); +#line 2405 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{CLightSource * pls = GetLightSource (); +#line 2406 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(pls != NULL && ! (pls -> ls_ulFlags & LSF_LENSFLAREONLY )){ +#line 2408 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ASSERT (! (pls -> ls_ulFlags & LSF_DIRECTIONAL )); +#line 2409 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +box |= FLOATaabbox3D (FLOAT3D (0 , 0 , 0) , pls -> ls_rFallOff ); +#line 2410 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}} +#line 2412 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +box . ExpandByFactor (phy_fCollisionCacheAround - 1.0f); +#line 2414 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +box += en_plPlacement . pl_PositionVector ; +#line 2415 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxMovingEstimate = box ; +#line 2416 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +box += en_vIntendedTranslation * phy_fCollisionCacheAhead ; +#line 2417 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxMovingEstimate |= box ; +#line 2420 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vAppliedTranslation = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 2421 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mAppliedRotation . Diagonal (1.0f); +#line 2422 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_PREMOVING ); +#line 2424 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 2428 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void CMovableEntity::PreMovingOld(void) +#line 2429 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 2430 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pciCollisionInfo == NULL ){ +#line 2431 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ; +#line 2432 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2438 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StartTimer (CPhysicsProfile :: PTI_PREMOVING ); +#line 2439 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementTimerAveragingCounter (CPhysicsProfile :: PTI_PREMOVING ); +#line 2442 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plLastPlacement = en_plPlacement ; +#line 2445 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , itenChild ){ +#line 2447 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((itenChild -> en_ulPhysicsFlags & EPF_MOVABLE ) +#line 2448 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& ! ((CMovableEntity *) & * itenChild ) -> en_lnInMovers . IsLinked ()){ +#line 2449 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penChild = ((CMovableEntity *) & * itenChild ); +#line 2451 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penChild -> en_plLastPlacement = penChild -> en_plPlacement ; +#line 2452 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2453 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}} +#line 2455 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fTickQuantum = _pTimer -> TickQuantum ; +#line 2458 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(dbg_bBreak ){ +#line 2459 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +dbg_bBreak = FALSE ; +#line 2460 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +try { +#line 2461 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +Breakpoint (); +#line 2462 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}catch (ANYEXCEPTION ){ +#line 2463 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CPrintF ("Breakpoint!\n"); +#line 2464 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}; +#line 2465 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2473 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOAT fMaxSpeed = 300.0f; +#line 2474 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute (1) = Clamp (en_vCurrentTranslationAbsolute (1) , - fMaxSpeed , + fMaxSpeed ); +#line 2475 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute (2) = Clamp (en_vCurrentTranslationAbsolute (2) , - fMaxSpeed , + fMaxSpeed ); +#line 2476 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute (3) = Clamp (en_vCurrentTranslationAbsolute (3) , - fMaxSpeed , + fMaxSpeed ); +#line 2479 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_RenderType == RT_MODEL || en_RenderType == RT_EDITORMODEL ){ +#line 2481 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TestFields (en_iUpContent , en_iDnContent , en_fImmersionFactor ); +#line 2483 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_ulPhysicsFlags & EPF_STICKYFEET ){ +#line 2485 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vPoint ; +#line 2486 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATplane3D plPlane ; +#line 2487 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fDistanceToEdge ; +#line 2488 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(GetNearestPolygon (vPoint , plPlane , fDistanceToEdge )){ +#line 2489 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vGravityDir = - (FLOAT3D &) plPlane ; +#line 2490 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2491 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2492 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2493 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CContentType & ctDn = en_pwoWorld -> wo_actContentTypes [ en_iDnContent ]; +#line 2494 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CContentType & ctUp = en_pwoWorld -> wo_actContentTypes [ en_iUpContent ]; +#line 2497 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TestBreathing (ctUp ); +#line 2499 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TestContentDamage (ctDn , en_fImmersionFactor ); +#line 2501 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference != NULL ){ +#line 2502 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CSurfaceType & stReference = en_pwoWorld -> wo_astSurfaceTypes [ en_iReferenceSurface ]; +#line 2503 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TestSurfaceDamage (stReference ); +#line 2504 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2507 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fBouyancy = (1 - +#line 2508 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ctDn . ct_fDensity / en_fDensity ) * en_fImmersionFactor - +#line 2509 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(ctUp . ct_fDensity / en_fDensity ) * (1 - en_fImmersionFactor )); +#line 2510 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fSpeedModifier = +#line 2511 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctDn . ct_fSpeedMultiplier * en_fImmersionFactor + +#line 2512 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctUp . ct_fSpeedMultiplier * (1 - en_fImmersionFactor ); +#line 2513 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fFluidFriction = +#line 2514 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctDn . ct_fFluidFriction * en_fImmersionFactor + +#line 2515 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctUp . ct_fFluidFriction * (1 - en_fImmersionFactor ); +#line 2516 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fControlMultiplier = +#line 2517 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctDn . ct_fControlMultiplier * en_fImmersionFactor + +#line 2518 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ctUp . ct_fControlMultiplier * (1 - en_fImmersionFactor ); +#line 2521 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vDesiredTranslationAbsolute = en_vDesiredTranslationRelative ; +#line 2523 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! (en_ulPhysicsFlags & EPF_ABSOLUTETRANSLATE )){ +#line 2524 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute *= en_mRotation ; +#line 2525 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2527 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute *= fTickQuantum ; +#line 2528 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ANGLE3D aRotationRelative ; +#line 2529 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +aRotationRelative (1) = en_aDesiredRotationRelative (1) * fTickQuantum ; +#line 2530 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +aRotationRelative (2) = en_aDesiredRotationRelative (2) * fTickQuantum ; +#line 2531 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +aRotationRelative (3) = en_aDesiredRotationRelative (3) * fTickQuantum ; +#line 2533 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATmatrix3D mRotationAbsolute ; +#line 2535 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_PUSH ){ +#line 2536 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATmatrix3D mNewRotation ; +#line 2537 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +MakeRotationMatrixFast (mNewRotation , en_plPlacement . pl_OrientationAngle + aRotationRelative ); +#line 2538 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mRotationAbsolute = mNewRotation * ! en_mRotation ; +#line 2540 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2541 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +MakeRotationMatrixFast (mRotationAbsolute , aRotationRelative ); +#line 2542 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mRotationAbsolute = en_mRotation * (mRotationAbsolute * ! en_mRotation ); +#line 2543 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2546 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute *= fSpeedModifier ; +#line 2549 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fJump = - en_mRotation . GetColumn (2) % vDesiredTranslationAbsolute ; +#line 2551 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bReferenceMovingInY = FALSE ; +#line 2552 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bReferenceRotatingNonY = FALSE ; +#line 2554 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference != NULL && (en_penReference -> en_ulPhysicsFlags & EPF_MOVABLE )){ +#line 2555 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penReference = (CMovableEntity *) (CEntity *) en_penReference ; +#line 2557 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOAT3D & vReferenceTranslation = penReference -> en_vIntendedTranslation ; +#line 2558 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +const FLOATmatrix3D & mReferenceRotation = penReference -> en_mIntendedRotation ; +#line 2560 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vRadius = en_plPlacement . pl_PositionVector +#line 2561 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +- penReference -> en_plPlacement . pl_PositionVector ; +#line 2562 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vReferenceDelta = vReferenceTranslation + vRadius * mReferenceRotation - vRadius ; +#line 2564 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute += vReferenceDelta ; +#line 2565 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mRotationAbsolute = mReferenceRotation * mRotationAbsolute ; +#line 2568 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bReferenceMovingInY = (vReferenceDelta % en_vGravityDir != 0.0f); +#line 2569 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bReferenceRotatingNonY = ((en_vGravityDir * mReferenceRotation ) % en_vGravityDir ) > 0.01f; +#line 2570 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2572 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vTranslationAbsolute = en_vCurrentTranslationAbsolute * fTickQuantum ; +#line 2575 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags &= ~ EPF_ORIENTINGTOGRAVITY ; +#line 2577 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_ulPhysicsFlags & EPF_ORIENTEDBYGRAVITY ){ +#line 2579 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vDown ; +#line 2580 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDown (1) = - en_mRotation (1 , 2); +#line 2581 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDown (2) = - en_mRotation (2 , 2); +#line 2582 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDown (3) = - en_mRotation (3 , 2); +#line 2585 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fCos = vDown % en_vGravityDir ; +#line 2587 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fCos < 0.99999f){ +#line 2589 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags |= EPF_ORIENTINGTOGRAVITY ; +#line 2592 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ANGLE a = ACos (fCos ); +#line 2593 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(Abs (a ) > 20){ +#line 2594 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +a = 20 * Sgn (a ); +#line 2595 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2596 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fRad = RadAngle (a ); +#line 2599 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vAxis = vDown * en_vGravityDir ; +#line 2600 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fLen = vAxis . Length (); +#line 2601 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fLen < 0.01f){ +#line 2602 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vAxis (1) = en_mRotation (1 , 3); +#line 2603 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vAxis (2) = en_mRotation (2 , 3); +#line 2604 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vAxis (3) = en_mRotation (3 , 3); +#line 2607 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if(! bReferenceRotatingNonY ){ +#line 2608 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +fRad /= fLen ; +#line 2609 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2610 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vAxis *= fRad ; +#line 2613 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATmatrix3D mGRotation ; +#line 2614 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mGRotation (1 , 1) = 1;mGRotation (1 , 2) = - vAxis (3);mGRotation (1 , 3) = vAxis (2); +#line 2615 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mGRotation (2 , 1) = vAxis (3);mGRotation (2 , 2) = 1;mGRotation (2 , 3) = - vAxis (1); +#line 2616 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mGRotation (3 , 1) = - vAxis (2);mGRotation (3 , 2) = vAxis (1);mGRotation (3 , 3) = 1; +#line 2617 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +OrthonormalizeRotationMatrix (mGRotation ); +#line 2620 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +mRotationAbsolute = mGRotation * mRotationAbsolute ; +#line 2621 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2622 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2625 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags &= ~ EPF_FLOATING ; +#line 2627 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT ACC = en_fAcceleration * fTickQuantum * fTickQuantum ; +#line 2628 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT DEC = en_fDeceleration * fTickQuantum * fTickQuantum ; +#line 2630 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! (en_ulPhysicsFlags & EPF_TRANSLATEDBYGRAVITY )){ +#line 2632 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_ulPhysicsFlags & EPF_NOACCELERATION ){ +#line 2633 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute = vDesiredTranslationAbsolute ; +#line 2634 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2635 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAcceleration (vTranslationAbsolute , vDesiredTranslationAbsolute , +#line 2636 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ACC * fControlMultiplier , +#line 2637 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +DEC * fControlMultiplier ); +#line 2638 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2640 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if((fBouyancy * en_fGravityA < 0.5f && (ctDn . ct_ulFlags & (CTF_SWIMABLE | CTF_FLYABLE )))){ +#line 2642 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags |= EPF_FLOATING ; +#line 2644 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_ulPhysicsFlags & EPF_NOACCELERATION ){ +#line 2645 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute = vDesiredTranslationAbsolute ; +#line 2646 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2647 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAcceleration (vTranslationAbsolute , vDesiredTranslationAbsolute , +#line 2648 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ACC * fControlMultiplier , +#line 2649 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +DEC * fControlMultiplier ); +#line 2650 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2653 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fBouyancy < - 0.1f){ +#line 2654 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGV = en_fGravityV * fTickQuantum * fSpeedModifier ; +#line 2655 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGA = (en_fGravityA * - fBouyancy ) * fTickQuantum * fTickQuantum ; +#line 2656 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAcceleration (vTranslationAbsolute , en_vGravityDir * - fGV , fGA , fGA ); +#line 2657 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if(fBouyancy > + 0.1f){ +#line 2658 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGV = en_fGravityV * fTickQuantum * fSpeedModifier ; +#line 2659 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGA = (en_fGravityA * fBouyancy ) * fTickQuantum * fTickQuantum ; +#line 2660 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAcceleration (vTranslationAbsolute , en_vGravityDir * fGV , fGA , fGA ); +#line 2661 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2664 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2665 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bGravityAlongPolygon = TRUE ; +#line 2667 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pbpoStandOn == NULL || ! IsStandingOnPolygon (en_pbpoStandOn ) || bReferenceMovingInY +#line 2668 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +|| (en_ulPhysicsFlags & EPF_ORIENTINGTOGRAVITY )){ +#line 2670 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = NULL ; +#line 2671 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference == NULL || bReferenceMovingInY ){ +#line 2672 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +bGravityAlongPolygon = FALSE ; +#line 2673 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2674 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2677 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! bGravityAlongPolygon ){ +#line 2678 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_GRAVITY_NONTRIVIAL ); +#line 2681 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGV = en_fGravityV * fTickQuantum * fSpeedModifier ; +#line 2682 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGA = (en_fGravityA * fBouyancy ) * fTickQuantum * fTickQuantum ; +#line 2683 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddGAcceleration (vTranslationAbsolute , en_vGravityDir , fGA , fGV ); +#line 2685 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2686 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_GRAVITY_TRIVIAL ); +#line 2689 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vPolygonDir = - en_vReferencePlane ; +#line 2691 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vGParallel , vGNormal ; +#line 2692 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +GetParallelAndNormalComponents (en_vGravityDir , vPolygonDir , vGNormal , vGParallel ); +#line 2694 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fFactor = vGParallel . Length (); +#line 2696 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fFactor > 0.001f){ +#line 2697 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGV = en_fGravityV * fTickQuantum * fSpeedModifier ; +#line 2698 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fGA = (en_fGravityA * fBouyancy ) * fTickQuantum * fTickQuantum ; +#line 2699 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddGAcceleration (vTranslationAbsolute , vGParallel / fFactor , fGA * fFactor , fGV * fFactor ); +#line 2700 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2703 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fPolyGA = (vPolygonDir % en_vGravityDir ) * en_fGravityA ; +#line 2704 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fYSpeed = vPolygonDir % vTranslationAbsolute ; +#line 2705 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fYSpeed > 0 && fYSpeed < fPolyGA ){ +#line 2706 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute -= vPolygonDir * fYSpeed ; +#line 2707 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2710 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_BOUNCE ){ +#line 2712 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative *= en_fJumpControlMultiplier ; +#line 2713 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_aDesiredRotationRelative . Length () < 10){ +#line 2714 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative = ANGLE3D (0 , 0 , 0); +#line 2715 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2716 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2717 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2719 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CSurfaceType & stReference = en_pwoWorld -> wo_astSurfaceTypes [ en_iReferenceSurface ]; +#line 2722 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference != NULL ){ +#line 2723 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fPlaneY = (en_vGravityDir % en_vReferencePlane ); +#line 2724 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fPlaneYAbs = Abs (fPlaneY ); +#line 2725 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fFriction = stReference . st_fFriction ; +#line 2727 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fPlaneY >= - stReference . st_fClimbSlopeCos && fPlaneY < 0 +#line 2728 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +|| (stReference . st_ulFlags & STF_SLIDEDOWNSLOPE ) && fPlaneY > - 0.99f){ +#line 2729 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags |= EPF_ONSTEEPSLOPE ; +#line 2731 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAccelerationOnPlane2 ( +#line 2732 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute , +#line 2733 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute , +#line 2734 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ACC * fPlaneYAbs * fPlaneYAbs * fFriction * fControlMultiplier , +#line 2735 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +DEC * fPlaneYAbs * fPlaneYAbs * fFriction * fControlMultiplier , +#line 2736 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane , +#line 2737 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vGravityDir ); +#line 2739 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2740 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags &= ~ EPF_ONSTEEPSLOPE ; +#line 2742 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAccelerationOnPlane ( +#line 2743 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute , +#line 2744 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute , +#line 2745 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ACC * fPlaneYAbs * fPlaneYAbs * fFriction * fControlMultiplier , +#line 2746 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +DEC * fPlaneYAbs * fPlaneYAbs * fFriction * fControlMultiplier , +#line 2747 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane ); +#line 2748 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2750 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fJump < - 0.01f && (fPlaneY < - stReference . st_fJumpSlopeCos +#line 2751 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +|| _pTimer -> CurrentTick () > en_tmLastSignificantVerticalMovement + 0.25f)){ +#line 2753 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute += en_vGravityDir * fJump ; +#line 2754 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmJumped = _pTimer -> CurrentTick (); +#line 2755 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = NULL ; +#line 2756 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2759 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2761 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(_pTimer -> CurrentTick () - en_tmJumped < en_tmMaxJumpControl ){ +#line 2763 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAccelerationOnPlane ( +#line 2764 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute , +#line 2765 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vDesiredTranslationAbsolute , +#line 2766 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ACC * fControlMultiplier * en_fJumpControlMultiplier , +#line 2767 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +DEC * fControlMultiplier * en_fJumpControlMultiplier , +#line 2768 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATplane3D (en_vGravityDir , 0)); +#line 2769 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2772 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fJump < - 0.01f && +#line 2773 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pTimer -> CurrentTick () > en_tmLastSignificantVerticalMovement + 0.25f){ +#line 2775 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +vTranslationAbsolute += en_vGravityDir * fJump ; +#line 2776 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmJumped = _pTimer -> CurrentTick (); +#line 2777 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pbpoStandOn = NULL ; +#line 2778 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2779 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2780 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2784 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CheckAndAddGAcceleration (this , vTranslationAbsolute , fTickQuantum ); +#line 2787 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fFluidFriction > 0.01f){ +#line 2789 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +AddAcceleration (vTranslationAbsolute , FLOAT3D (0.0f , 0.0f , 0.0f) , +#line 2790 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +0.0f , DEC * fFluidFriction ); +#line 2791 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2794 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((en_ulPhysicsFlags & EPF_CANFADESPINNING ) && +#line 2795 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +((ctDn . ct_ulFlags & CTF_FADESPINNING ) || (ctUp . ct_ulFlags & CTF_FADESPINNING ))){ +#line 2797 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative *= (1 - fSpeedModifier * 0.05f); +#line 2798 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_aDesiredRotationRelative . Length () < 10){ +#line 2799 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_aDesiredRotationRelative = ANGLE3D (0 , 0 , 0); +#line 2800 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2801 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2804 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pbpoStandOn == NULL ){ +#line 2805 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_penReference = NULL ; +#line 2806 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vReferencePlane = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 2807 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_iReferenceSurface = 0; +#line 2808 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2810 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vIntendedTranslation = vTranslationAbsolute ; +#line 2811 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mIntendedRotation = mRotationAbsolute ; +#line 2816 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOATaabbox3D box ; +#line 2817 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_pciCollisionInfo -> MakeBoxAtPlacement (FLOAT3D (0 , 0 , 0) , en_mRotation , box ); +#line 2819 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{CLightSource * pls = GetLightSource (); +#line 2820 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(pls != NULL && ! (pls -> ls_ulFlags & LSF_LENSFLAREONLY )){ +#line 2822 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ASSERT (! (pls -> ls_ulFlags & LSF_DIRECTIONAL )); +#line 2823 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +box |= FLOATaabbox3D (FLOAT3D (0 , 0 , 0) , pls -> ls_rFallOff ); +#line 2824 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}} +#line 2826 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +box . ExpandByFactor (phy_fCollisionCacheAround - 1.0f); +#line 2828 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +box += en_plPlacement . pl_PositionVector ; +#line 2829 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxMovingEstimate = box ; +#line 2830 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +box += en_vIntendedTranslation * phy_fCollisionCacheAhead ; +#line 2831 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_boxMovingEstimate |= box ; +#line 2834 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vAppliedTranslation = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 2835 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mAppliedRotation . Diagonal (1.0f); +#line 2836 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_PREMOVING ); +#line 2838 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::DoMoving(void) +#line 2842 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 2843 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pciCollisionInfo == NULL || (en_ulPhysicsFlags & EPF_FORCEADDED )){ +#line 2844 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ; +#line 2845 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2848 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StartTimer (CPhysicsProfile :: PTI_DOMOVING ); +#line 2849 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementTimerAveragingCounter (CPhysicsProfile :: PTI_DOMOVING ); +#line 2851 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_DOMOVING ); +#line 2853 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fTickQuantum = _pTimer -> TickQuantum ; +#line 2856 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_ulPhysicsFlags & EPF_RT_SYNCHRONIZED ){ +#line 2857 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_DOMOVING_SYNC ); +#line 2860 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vMoveTranslation = en_vIntendedTranslation - en_vAppliedTranslation ; +#line 2861 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mMoveRotation = en_mIntendedRotation * ! en_mAppliedRotation ; +#line 2863 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +InitTryToMove (); +#line 2864 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penPusher = NULL ; +#line 2865 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) == EPF_ONBLOCK_PUSH ){ +#line 2866 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penPusher = this ; +#line 2867 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2868 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bMoveSuccessfull = TryToMove (penPusher , TRUE , TRUE ); +#line 2871 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2872 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ASSERT ((en_ulPhysicsFlags & EPF_ONBLOCK_MASK ) != EPF_ONBLOCK_PUSH ); +#line 2873 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_DOMOVING_ASYNC ); +#line 2876 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference == NULL ){ +#line 2877 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_DOMOVING_ASYNC_SYNCTRY ); +#line 2880 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vMoveTranslation = en_vIntendedTranslation - en_vAppliedTranslation ; +#line 2881 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mMoveRotation = en_mIntendedRotation * ! en_mAppliedRotation ; +#line 2882 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +InitTryToMove (); +#line 2883 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_ctTryToMoveCheckCounter = 4; +#line 2884 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bMoveSuccessfull = TryToMove (NULL , TRUE , TRUE ); +#line 2886 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(bMoveSuccessfull ){ +#line 2888 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_DOMOVING_ASYNC_SYNCPASS ); +#line 2889 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_DOMOVING ); +#line 2891 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ; +#line 2892 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2893 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2895 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_DOMOVING_ASYNC_TRANSLATE ); +#line 2897 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vMoveTranslation = en_vIntendedTranslation - en_vAppliedTranslation ; +#line 2898 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +InitTryToMove (); +#line 2899 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TryToMove (NULL , TRUE , FALSE ); +#line 2902 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mMoveRotation = en_mIntendedRotation * ! en_mAppliedRotation ; +#line 2903 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if( +#line 2904 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mMoveRotation (1 , 1) != 1 || en_mMoveRotation (1 , 2) != 0 || en_mMoveRotation (1 , 3) != 0 || +#line 2905 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mMoveRotation (2 , 1) != 0 || en_mMoveRotation (2 , 2) != 1 || en_mMoveRotation (2 , 3) != 0 || +#line 2906 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_mMoveRotation (3 , 1) != 0 || en_mMoveRotation (3 , 2) != 0 || en_mMoveRotation (3 , 3) != 1){ +#line 2907 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementCounter (CPhysicsProfile :: PCI_DOMOVING_ASYNC_ROTATE ); +#line 2908 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +InitTryToMove (); +#line 2909 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TryToMove (NULL , FALSE , TRUE ); +#line 2910 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2911 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2913 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_DOMOVING ); +#line 2915 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::PostMoving(void) +#line 2919 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 2920 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_pciCollisionInfo == NULL ){ +#line 2922 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulFlags |= ENF_INRENDERING ; +#line 2923 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ; +#line 2924 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2926 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_ulPhysicsFlags & EPF_FORCEADDED ){ +#line 2927 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags &= ~ EPF_FORCEADDED ; +#line 2928 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return ; +#line 2929 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2933 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StartTimer (CPhysicsProfile :: PTI_POSTMOVING ); +#line 2934 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . IncrementTimerAveragingCounter (CPhysicsProfile :: PTI_POSTMOVING ); +#line 2937 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference != NULL ){ +#line 2938 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_penLastValidReference = en_penReference ; +#line 2939 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2942 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vOldTranslation = en_vCurrentTranslationAbsolute ; +#line 2943 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fTickQuantum = _pTimer -> TickQuantum ; +#line 2945 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vCurrentTranslationAbsolute = en_vAppliedTranslation / fTickQuantum ; +#line 2948 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(Abs (en_vCurrentTranslationAbsolute % en_vGravityDir ) > 0.1f){ +#line 2949 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_tmLastSignificantVerticalMovement = _pTimer -> CurrentTick (); +#line 2950 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2952 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +ClearNextPosition (); +#line 2955 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT3D vSpeedDelta = en_vIntendedTranslation - en_vAppliedTranslation ; +#line 2956 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fSpeedDelta = vSpeedDelta . Length () / fTickQuantum ; +#line 2959 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(fSpeedDelta > en_fCollisionSpeedLimit && +#line 2960 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +! (en_ulPhysicsFlags & EPF_NOIMPACTTHISTICK )){ +#line 2962 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fDamage = ((fSpeedDelta - en_fCollisionSpeedLimit ) / en_fCollisionSpeedLimit ) * en_fCollisionDamageFactor ; +#line 2963 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +InflictDirectDamage (this , MiscDamageInflictor () , DMT_IMPACT , fDamage , +#line 2964 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plPlacement . pl_PositionVector , - vSpeedDelta . Normalize ()); +#line 2965 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2966 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulPhysicsFlags &= ~ EPF_NOIMPACTTHISTICK ; +#line 2969 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_vIntendedTranslation = vOldTranslation ; +#line 2972 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_vCurrentTranslationAbsolute . ManhattanNorm () < 0.001f +#line 2973 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& (en_vDesiredTranslationRelative . ManhattanNorm () == 0 || en_fAcceleration == 0) +#line 2974 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +&& en_aDesiredRotationRelative . ManhattanNorm () == 0){ +#line 2977 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference != NULL ){ +#line 2979 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_penReference -> en_ulPhysicsFlags & EPF_MOVABLE ){ +#line 2980 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penReference = (CMovableEntity *) (CEntity *) en_penReference ; +#line 2982 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(! penReference -> en_lnInMovers . IsLinked ()){ +#line 2984 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulFlags |= ENF_INRENDERING ; +#line 2985 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2987 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2989 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulFlags |= ENF_INRENDERING ; +#line 2990 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 2993 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else { +#line 2995 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if( +#line 2996 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +(! (en_ulPhysicsFlags & (EPF_TRANSLATEDBYGRAVITY | EPF_ORIENTEDBYGRAVITY )) +#line 2997 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +|| en_fGravityA == 0.0f)){ +#line 2999 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_ulFlags |= ENF_INRENDERING ; +#line 3000 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3001 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3004 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_ulFlags & ENF_INRENDERING ){ +#line 3006 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plLastPlacement = en_plPlacement ; +#line 3007 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3008 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3011 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(en_plpLastPositions != NULL ){ +#line 3012 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plpLastPositions -> AddPosition (en_vNextPosition ); +#line 3013 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3017 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +extern BOOL _bPredictionActive ; +#line 3018 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(_bPredictionActive && (IsPredictable () || IsPredictor ())){ +#line 3019 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penTail = (CMovableEntity *) GetPredictedSafe (this ); +#line 3020 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 3022 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(penTail -> en_tmLastPredictionHead < - 1){ +#line 3023 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vLastHead = en_plPlacement . pl_PositionVector ; +#line 3024 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vPredError = FLOAT3D (0 , 0 , 0); +#line 3025 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vPredErrorLast = FLOAT3D (0 , 0 , 0); +#line 3026 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3029 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(IsPredictor ()){ +#line 3031 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(penTail -> en_tmLastPredictionHead == tmNow || penTail -> en_tmLastPredictionHead < 0){ +#line 3033 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vPredErrorLast = penTail -> en_vPredError ; +#line 3034 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vPredError += +#line 3035 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plPlacement . pl_PositionVector - penTail -> en_vLastHead ; +#line 3037 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vLastHead = en_plPlacement . pl_PositionVector ; +#line 3039 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(IsPredictionHead ()){ +#line 3041 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_tmLastPredictionHead = tmNow ; +#line 3042 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3045 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if(tmNow > penTail -> en_tmLastPredictionHead ){ +#line 3047 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vLastHead = en_plPlacement . pl_PositionVector ; +#line 3048 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_tmLastPredictionHead = tmNow ; +#line 3049 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3052 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +}else if(! (en_ulFlags & ENF_WILLBEPREDICTED )){ +#line 3054 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(penTail -> en_tmLastPredictionHead > 0){ +#line 3056 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vPredErrorLast = penTail -> en_vPredError ; +#line 3057 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vPredError += +#line 3058 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +en_plPlacement . pl_PositionVector - penTail -> en_vLastHead ; +#line 3059 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3061 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vLastHead = en_plPlacement . pl_PositionVector ; +#line 3062 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_tmLastPredictionHead = - 1; +#line 3063 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3065 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +if(IsPredictionHead ()){ +#line 3067 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vPredErrorLast = penTail -> en_vPredError ; +#line 3068 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +penTail -> en_vPredError *= cli_fPredictionFilter ; +#line 3073 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3074 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +#line 3077 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +_pfPhysicsProfile . StopTimer (CPhysicsProfile :: PTI_POSTMOVING ); +#line 3080 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + void CMovableEntity::CacheNearPolygons(void) +#line 3084 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 3085 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CClipMove cm (this ); +#line 3086 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +cm . CacheNearPolygons (); +#line 3087 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} + +#line 3091 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SLONG CMovableEntity::GetUsedMemory(void) +#line 3092 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +{ +#line 3094 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SLONG slUsedMemory = sizeof (CMovableEntity ) - sizeof (CRationalEntity ) + CRationalEntity :: GetUsedMemory (); +#line 3096 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +slUsedMemory += en_apbpoNearPolygons . sa_Count * sizeof (CBrushPolygon *); +#line 3097 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +return slUsedMemory ; +#line 3098 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +} +BOOL CMovableEntity:: +#line 3105 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +Dummy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMovableEntity_Dummy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMovableEntity::Dummy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/Engine/Classes/MovableEntity.es b/Sources/Engine/Classes/MovableEntity.es new file mode 100644 index 0000000..8166394 --- /dev/null +++ b/Sources/Engine/Classes/MovableEntity.es @@ -0,0 +1,3106 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +/* + * Entity that can move and obey physics. + */ +1 +%{ +#include "StdH.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define CLEARMEM(var) memset(&var, 0, sizeof(var)) + +%} + + +%{ + +#define ANYEXCEPTION ... +template CStaticStackArray; + +#define MAXCOLLISIONRETRIES 4*4 +extern FLOAT phy_fCollisionCacheAhead; +extern FLOAT phy_fCollisionCacheAround; +extern FLOAT cli_fPredictionFilter; + +// force breakpoint (debug) +extern INDEX dbg_bBreak; +// must be in separate function to disable stupid optimizer +extern void Breakpoint(void); + +CEntity *GetPredictedSafe(CEntity *pen) +{ + if ((pen->en_ulFlags&(ENF_PREDICTOR|ENF_TEMPPREDICTOR)) == ENF_PREDICTOR) { + return pen->GetPredicted(); + } else { + return pen; + } +} + +// add acceleration to velocity +static inline void AddAcceleration( + FLOAT3D &vCurrentVelocity, const FLOAT3D &vDesiredVelocity, + FLOAT fAcceleration, FLOAT fDecceleration) +{ + // if desired velocity is smaller than current velocity + if (vDesiredVelocity.Length()fAcceleration) { + vCurrentVelocity += vDelta*(fAcceleration/fDelta); + } else { + vCurrentVelocity = vDesiredVelocity; + } +} + +// add gravity acceleration to velocity along an axis +static inline void AddGAcceleration( + FLOAT3D &vCurrentVelocity, const FLOAT3D &vGDir, + FLOAT fGA, FLOAT fGV) +{ + // disassemble speed + FLOAT3D vCurrentParallel, vCurrentOrthogonal; + GetParallelAndNormalComponents(vCurrentVelocity, vGDir, vCurrentOrthogonal, vCurrentParallel); + +/* +IMPORTANT: +This is how this piece of code should look like: + + // if not already going down at max speed + if (! (vCurrentOrthogonal%vGDir>=fGV)) { + // add accelleration to parallel speed + vCurrentOrthogonal+=vGDir*fGA; + + // if going down at max speed + if (vCurrentOrthogonal%vGDir>=fGV) { + // clamp + vCurrentOrthogonal = vGDir*fGV; + } + } + +But, due to need for compatibility with older versions and bad VC code generator, we use this kludge: + */ + +// KLUDGE_BEGIN + + if (_pNetwork->ga_ulDemoMinorVersion<=2) { + Swap(vCurrentOrthogonal, vCurrentParallel); + } + + FLOAT3D vCurrentOrthogonalOrg=vCurrentOrthogonal; + // add accelleration to parallel speed + vCurrentOrthogonal+=vGDir*fGA; + + // if going down at max speed + if (vCurrentOrthogonal%vGDir>=fGV) { + // clamp + vCurrentOrthogonal = vGDir*fGV; + } else { + vCurrentOrthogonalOrg = vCurrentOrthogonal; + } + + if (_pNetwork->ga_ulDemoMinorVersion>2) { + vCurrentOrthogonal=vCurrentOrthogonalOrg; + } +// KLUDGE_END + + // assemble speed back + vCurrentVelocity = vCurrentParallel+vCurrentOrthogonal; +} + +// NOTE: +// this is pulled out into a separate function because, otherwise, VC6 generates +// invalid code when optimizing this. no clue why is that so. + +#pragma inline_depth(0) +static void CheckAndAddGAcceleration(CMovableEntity *pen, FLOAT3D &vTranslationAbsolute, FLOAT fTickQuantum) +{ + // if there is forcefield involved + if (pen->en_fForceA>0.01f) { + // add force acceleration + FLOAT fGV=pen->en_fForceV*fTickQuantum; + FLOAT fGA=pen->en_fForceA*fTickQuantum*fTickQuantum; + AddGAcceleration(vTranslationAbsolute, pen->en_vForceDir, fGA, fGV); + } +} +#pragma inline_depth() // see important note above + + +// add acceleration to velocity, but only along a plane +static inline void AddAccelerationOnPlane( + FLOAT3D &vCurrentVelocity, const FLOAT3D &vDesiredVelocity, + FLOAT fAcceleration, FLOAT fDecceleration, + const FLOAT3D &vPlaneNormal) +{ + FLOAT3D vCurrentParallel, vCurrentOrthogonal; + GetParallelAndNormalComponents(vCurrentVelocity, vPlaneNormal, vCurrentOrthogonal, vCurrentParallel); + FLOAT3D vDesiredParallel; + GetNormalComponent(vDesiredVelocity, vPlaneNormal, vDesiredParallel); + AddAcceleration(vCurrentParallel, vDesiredParallel, fAcceleration, fDecceleration); + vCurrentVelocity = vCurrentParallel+vCurrentOrthogonal; +} + +// add acceleration to velocity, for roller-coaster slope -- slow! +static inline void AddAccelerationOnPlane2( + FLOAT3D &vCurrentVelocity, const FLOAT3D &vDesiredVelocity, + FLOAT fAcceleration, FLOAT fDecceleration, + const FLOAT3D &vPlaneNormal, const FLOAT3D &vGravity) +{ + // get down and horizontal direction + FLOAT3D vDn; + GetNormalComponent(vGravity, vPlaneNormal, vDn); + vDn.Normalize(); + FLOAT3D vRt = vPlaneNormal*vDn; + vRt.Normalize(); + + // add only horizontal acceleration + FLOAT3D vCurrentParallel, vCurrentOrthogonal; + GetParallelAndNormalComponents(vCurrentVelocity, vRt, vCurrentParallel, vCurrentOrthogonal); + FLOAT3D vDesiredParallel; + GetParallelComponent(vDesiredVelocity, vRt, vDesiredParallel); + AddAcceleration(vCurrentParallel, vDesiredParallel, fAcceleration, fDecceleration); + vCurrentVelocity = vCurrentParallel+vCurrentOrthogonal; +} + +// max number of retries during movement +static INDEX _ctTryToMoveCheckCounter; +static INDEX _ctSliding; +static FLOAT3D _vSlideOffDir; // move away direction for sliding +static FLOAT3D _vSlideDir; +static void InitTryToMove(void) +{ + _ctTryToMoveCheckCounter = MAXCOLLISIONRETRIES; + _ctSliding = 0; + _vSlideOffDir = FLOAT3D(0,0,0); + _vSlideDir = FLOAT3D(0,0,0); +} + +// array of forces for current entity +class CEntityForce { +public: + CEntityPointer ef_penEntity; + INDEX ef_iForceType; + FLOAT ef_fRatio; // how much of entity this force gets [0-1] + inline void Clear(void) { + ef_penEntity = NULL; + }; + ~CEntityForce(void) { + Clear(); + }; +}; +static CStaticStackArray _aefForces; + +void ClearMovableEntityCaches(void) +{ + _aefForces.Clear(); +} + +%} + +class export CMovableEntity : CRationalEntity { +name "MovableEntity"; +thumbnail ""; + +properties: + + // NOTE: all properties that are not marked as 'adjustable' should be threated read-only + + // translation and rotation speed that this entity would like to have (in relative system) + 1 FLOAT3D en_vDesiredTranslationRelative = FLOAT3D(0.0f,0.0f,0.0f), + 2 ANGLE3D en_aDesiredRotationRelative = ANGLE3D(0,0,0), + + // translation and rotation speed that this entity currently has in absolute system + 3 FLOAT3D en_vCurrentTranslationAbsolute = FLOAT3D(0.0f,0.0f,0.0f), + 4 ANGLE3D en_aCurrentRotationAbsolute = ANGLE3D(0,0,0), + + 6 CEntityPointer en_penReference, // reference entity (for standing on) + 7 FLOAT3D en_vReferencePlane = FLOAT3D(0.0f,0.0f,0.0f), // reference plane (only for standing on) + 8 INDEX en_iReferenceSurface = 0, // surface on reference entity + 9 CEntityPointer en_penLastValidReference, // last valid reference entity (for impact damage) + 14 FLOAT en_tmLastSignificantVerticalMovement = 0.0f, // last time entity moved significantly up/down + // swimming parameters + 10 FLOAT en_tmLastBreathed = 0, // last time when entity took some air + 11 FLOAT en_tmMaxHoldBreath = 5.0f, // how long can entity be without air (adjustable) + 12 FLOAT en_fDensity = 5000.0f, // density of the body [kg/m3] - defines buoyancy (adjustable) + 13 FLOAT en_tmLastSwimDamage = 0, // last time when entity was damaged by swimming + // content immersion parameters + 20 INDEX en_iUpContent = 0, + 21 INDEX en_iDnContent = 0, + 22 FLOAT en_fImmersionFactor = 1.0f, + // force parameters + 25 FLOAT3D en_vGravityDir = FLOAT3D(0,-1,0), + 26 FLOAT en_fGravityA = 0.0f, + 27 FLOAT en_fGravityV = 0.0f, + 66 FLOAT3D en_vForceDir = FLOAT3D(1,0,0), + 67 FLOAT en_fForceA = 0.0f, + 68 FLOAT en_fForceV = 0.0f, + // jumping parameters + 30 FLOAT en_tmJumped = 0, // time when entity jumped + 31 FLOAT en_tmMaxJumpControl = 0.5f, // how long after jump can have control in the air [s] (adjustable) + 32 FLOAT en_fJumpControlMultiplier = 0.5f, // how good is control when jumping (adjustable) + // movement parameters + 35 FLOAT en_fAcceleration = 200.0f, // acc/decc [m/s2] in ideal situation (adjustable) + 36 FLOAT en_fDeceleration = 40.0f, + + 37 FLOAT en_fStepUpHeight = 1.0f, // how high can entity step upstairs (adjustable) + 42 FLOAT en_fStepDnHeight = -1.0f, // how low can entity step (negative means don't check) (adjustable) + 38 FLOAT en_fBounceDampParallel = 0.5f, // damping parallel to plane at each bounce (adjustable) + 39 FLOAT en_fBounceDampNormal = 0.5f, // damping normal to plane damping at each bounce (adjustable) + // collision damage control + 40 FLOAT en_fCollisionSpeedLimit = 20.0f, // max. collision speed without damage (adjustable) + 41 FLOAT en_fCollisionDamageFactor = 20.0f, // collision damage ammount multiplier (adjustable) + + 51 FLOATaabbox3D en_boxMovingEstimate = FLOATaabbox3D(FLOAT3D(0,0,0), 0.01f), // overestimate of movement in next few ticks + 52 FLOATaabbox3D en_boxNearCached = FLOATaabbox3D(FLOAT3D(0,0,0), 0.01f), // box in which the polygons are cached + + // intended movement in this tick + 64 FLOAT3D en_vIntendedTranslation = FLOAT3D(0,0,0), // can be read on receiving a touch event, holds last velocity before touch + 65 FLOATmatrix3D en_mIntendedRotation = FLOATmatrix3D(0), + +{ +// these are not saved via the property system + + CPlacement3D en_plLastPlacement; // placement in last tick (used for lerping) (not saved) + CListNode en_lnInMovers; // node in list of moving entities (saved as bool) + + CBrushPolygon *en_pbpoStandOn; // cached last polygon standing on, just for optimization + // used for caching near polygons of zoning brushes for fast collision detection + CStaticStackArray en_apbpoNearPolygons; // cached polygons + + FLOAT en_tmLastPredictionHead; + FLOAT3D en_vLastHead; + FLOAT3D en_vPredError; + FLOAT3D en_vPredErrorLast; + + // these are really temporary - should never be used across ticks + // next placement for collision detection + FLOAT3D en_vNextPosition; + FLOATmatrix3D en_mNextRotation; + + // delta for this movement + FLOAT3D en_vMoveTranslation; + FLOATmatrix3D en_mMoveRotation; + // aplied movement in this tick + FLOAT3D en_vAppliedTranslation; + FLOATmatrix3D en_mAppliedRotation; +} + + +components: + + +functions: + + + void ResetPredictionFilter(void) + { + en_tmLastPredictionHead = -2; + en_vLastHead = en_plPlacement.pl_PositionVector; + en_vPredError = en_vPredErrorLast = FLOAT3D(0,0,0); + } + + /* Constructor. */ + export void CMovableEntity(void) + { + en_pbpoStandOn = NULL; + en_apbpoNearPolygons.SetAllocationStep(5); + ResetPredictionFilter(); + } + export void ~CMovableEntity(void) + { + } + + /* Initialization. */ + export void OnInitialize(const CEntityEvent &eeInput) + { + CRationalEntity::OnInitialize(eeInput); + ClearTemporaryData(); + en_vIntendedTranslation = FLOAT3D(0,0,0); + en_mIntendedRotation.Diagonal(1.0f); + en_boxNearCached = FLOATaabbox3D(); + en_boxMovingEstimate = FLOATaabbox3D(); + en_pbpoStandOn = NULL; + } + /* Called before releasing entity. */ + export void OnEnd(void) + { + // remove from movers if active + if (en_lnInMovers.IsLinked()) { + en_lnInMovers.Remove(); + } + ClearTemporaryData(); + en_boxNearCached = FLOATaabbox3D(); + en_boxMovingEstimate = FLOATaabbox3D(); + CRationalEntity::OnEnd(); + } + export void Copy(CEntity &enOther, ULONG ulFlags) + { + CRationalEntity::Copy(enOther, ulFlags); + CMovableEntity *pmenOther = (CMovableEntity *)(&enOther); + + if (ulFlags©_PREDICTOR) { + en_plLastPlacement = pmenOther->en_plLastPlacement ; + en_vNextPosition = pmenOther->en_vNextPosition ; + en_mNextRotation = pmenOther->en_mNextRotation ; +///*!*/ en_vIntendedTranslation = pmenOther->en_vIntendedTranslation ; +///*!*/ en_mIntendedRotation = pmenOther->en_mIntendedRotation ; + en_vAppliedTranslation = pmenOther->en_vAppliedTranslation ; + en_mAppliedRotation = pmenOther->en_mAppliedRotation ; + en_boxNearCached = pmenOther->en_boxNearCached ; + en_boxMovingEstimate = pmenOther->en_boxMovingEstimate ; + en_pbpoStandOn = pmenOther->en_pbpoStandOn ; + en_apbpoNearPolygons = pmenOther->en_apbpoNearPolygons ; + } else { + ClearTemporaryData(); + en_boxNearCached = FLOATaabbox3D(); + en_boxMovingEstimate = FLOATaabbox3D(); + en_pbpoStandOn = NULL; + } + + ResetPredictionFilter(); + en_plLastPlacement = pmenOther->en_plLastPlacement; + if (pmenOther->en_lnInMovers.IsLinked()) { + AddToMovers(); + } + } + + void ClearTemporaryData(void) + { + en_plLastPlacement = en_plPlacement; + // init moving parameters so that they are valid for collision if entity is not moving + en_vNextPosition = en_plPlacement.pl_PositionVector; + en_mNextRotation = en_mRotation; +///*!*/ en_vIntendedTranslation = FLOAT3D(0,0,0); +///*!*/ en_mIntendedRotation.Diagonal(1.0f); + en_vAppliedTranslation = FLOAT3D(0,0,0); + en_mAppliedRotation.Diagonal(1.0f); + ResetPredictionFilter(); + +// !!!! is this ok? +// en_pbpoStandOn = NULL; +// en_apbpoNearPolygons.Clear(); +// en_apbpoNearPolygons.SetAllocationStep(5); + } + + // create a checksum value for sync-check + export void ChecksumForSync(ULONG &ulCRC, INDEX iExtensiveSyncCheck) + { + CRationalEntity::ChecksumForSync(ulCRC, iExtensiveSyncCheck); + if (iExtensiveSyncCheck>0) { + if (en_pbpoStandOn!=NULL) { + CRC_AddLONG(ulCRC, en_pbpoStandOn->bpo_iInWorld); + } + CRC_AddFLOAT(ulCRC, en_apbpoNearPolygons.Count()); + if (iExtensiveSyncCheck>2) { + for (INDEX i=0; ibpo_iInWorld); + } + } + CRC_AddBlock(ulCRC, (UBYTE*)&en_vReferencePlane, sizeof(en_vReferencePlane)); + CRC_AddBlock(ulCRC, (UBYTE*)&en_vDesiredTranslationRelative, sizeof(en_vDesiredTranslationRelative)); + CRC_AddBlock(ulCRC, (UBYTE*)&en_aDesiredRotationRelative, sizeof(en_aDesiredRotationRelative)); + CRC_AddBlock(ulCRC, (UBYTE*)&en_vCurrentTranslationAbsolute, sizeof(en_vCurrentTranslationAbsolute)); + CRC_AddBlock(ulCRC, (UBYTE*)&en_aCurrentRotationAbsolute, sizeof(en_aCurrentRotationAbsolute)); + } + } + + // dump sync data to text file + export void DumpSync_t(CTStream &strm, INDEX iExtensiveSyncCheck) // throw char * + { + CRationalEntity::DumpSync_t(strm, iExtensiveSyncCheck); + if (iExtensiveSyncCheck>0) { + strm.FPrintF_t("standon polygon: "); + if (en_pbpoStandOn!=NULL) { + strm.FPrintF_t("%d\n", en_pbpoStandOn->bpo_iInWorld); + } else { + strm.FPrintF_t("\n"); + } + strm.FPrintF_t("near polygons: %d - ", en_apbpoNearPolygons.Count()); + if (iExtensiveSyncCheck>2) { + for (INDEX i=0; ibpo_iInWorld); + } + } + strm.FPrintF_t("\n"); + strm.FPrintF_t("desired translation: %g, %g, %g (%08X %08X %08X)\n", + en_vDesiredTranslationRelative(1), + en_vDesiredTranslationRelative(2), + en_vDesiredTranslationRelative(3), + (ULONG&)en_vDesiredTranslationRelative(1), + (ULONG&)en_vDesiredTranslationRelative(2), + (ULONG&)en_vDesiredTranslationRelative(3)); + strm.FPrintF_t("desired rotation: %g, %g, %g (%08X %08X %08X)\n", + en_aDesiredRotationRelative(1), + en_aDesiredRotationRelative(2), + en_aDesiredRotationRelative(3), + (ULONG&)en_aDesiredRotationRelative(1), + (ULONG&)en_aDesiredRotationRelative(2), + (ULONG&)en_aDesiredRotationRelative(3)); + strm.FPrintF_t("current translation: %g, %g, %g (%08X %08X %08X)\n", + en_vCurrentTranslationAbsolute(1), + en_vCurrentTranslationAbsolute(2), + en_vCurrentTranslationAbsolute(3), + (ULONG&)en_vCurrentTranslationAbsolute(1), + (ULONG&)en_vCurrentTranslationAbsolute(2), + (ULONG&)en_vCurrentTranslationAbsolute(3)); + strm.FPrintF_t("current rotation: %g, %g, %g (%08X %08X %08X)\n", + en_aCurrentRotationAbsolute(1), + en_aCurrentRotationAbsolute(2), + en_aCurrentRotationAbsolute(3), + (ULONG&)en_aCurrentRotationAbsolute(1), + (ULONG&)en_aCurrentRotationAbsolute(2), + (ULONG&)en_aCurrentRotationAbsolute(3)); + strm.FPrintF_t("reference plane: %g, %g, %g (%08X %08X %08X)\n", + en_vReferencePlane(1), + en_vReferencePlane(2), + en_vReferencePlane(3), + (ULONG&)en_vReferencePlane(1), + (ULONG&)en_vReferencePlane(2), + (ULONG&)en_vReferencePlane(3)); + strm.FPrintF_t("reference surface: %d\n", en_iReferenceSurface); + strm.FPrintF_t("reference entity: "); + if (en_penReference!=NULL) { + strm.FPrintF_t("id: %08X\n", en_penReference->en_ulID); + } else { + strm.FPrintF_t("none\n"); + } + } + } + + /* Read from stream. */ + export void Read_t( CTStream *istr) // throw char * + { + CRationalEntity::Read_t(istr); + // last placement is not saved to disk - it is not neccessary! + ClearTemporaryData(); + + // old version didn't load this + if (istr->PeekID_t()==CChunkID("MENT")) { // 'movable entity' + istr->ExpectID_t("MENT"); // 'movable entity' + + INDEX ibpo; + (*istr)>>ibpo; + en_pbpoStandOn = GetWorldPolygonPointer(ibpo); + + BOOL bAnyNULLs = FALSE; + INDEX ctbpoNear; + (*istr)>>ctbpoNear; + if (ctbpoNear>0) { + en_apbpoNearPolygons.PopAll(); + en_apbpoNearPolygons.Push(ctbpoNear); + for(INDEX i=0; i>ibpo; + en_apbpoNearPolygons[i] = GetWorldPolygonPointer(ibpo); + if (en_apbpoNearPolygons[i]==NULL) { + bAnyNULLs = TRUE; + } + } + if (bAnyNULLs) { + CPrintF("NULL saved for near polygon!\n"); + en_apbpoNearPolygons.PopAll(); + } + } + } + + // if entity was in list of movers when saving + BOOL bWasMoving; + (*istr)>>bWasMoving; + if (bWasMoving) { + // add it to movers + AddToMovers(); + } + } + /* Write to stream. */ + export void Write_t( CTStream *ostr) // throw char * + { + CRationalEntity::Write_t(ostr); + + ostr->WriteID_t("MENT"); // 'movable entity' + + INDEX ibpo; + ibpo = GetWorldPolygonIndex(en_pbpoStandOn); + (*ostr)<GetLerpFactor(); + } else { + fLerpFactor = _pTimer->GetLerpFactor2(); + } + CPlacement3D plLerped; + plLerped.Lerp(en_plLastPlacement, en_plPlacement, fLerpFactor); + CMovableEntity *penTail = (CMovableEntity *)GetPredictedSafe((CEntity*)this); + // if should filter predictions + extern BOOL _bPredictionActive; + if (_bPredictionActive) { + // add the smoothed error + FLOAT3D vError = penTail->en_vPredError; + vError*=pow(cli_fPredictionFilter, fLerpFactor); +// FLOAT fErrLen = vError.Length(); +// if (fErrLen>0) { +// vError = vError/fErrLen*ClampDn(fErrLen-cli_fPredictionCorrection*fLerpFactor, 0.0f); +// } + plLerped.pl_PositionVector -= vError; + } + return plLerped; + } + /* Add yourself to list of movers. */ + export void AddToMovers(void) + { + if (!en_lnInMovers.IsLinked()) { + en_pwoWorld->wo_lhMovers.AddTail(en_lnInMovers); + } + } + + export void AddToMoversDuringMoving(void) // used for recursive adding + { + // if already added + if (en_lnInMovers.IsLinked()) { + // do nothing + return; + } + // add it + AddToMovers(); + // mark that it was forced to add + en_ulPhysicsFlags|=EPF_FORCEADDED; + } + + /* Set desired rotation speed of movable entity. */ + export void SetDesiredRotation(const ANGLE3D &aRotation) + { + en_aDesiredRotationRelative = aRotation; + AddToMovers(); + } + export const ANGLE3D &GetDesiredRotation(void) const { return en_aDesiredRotationRelative; }; + + /* Set desired translation speed of movable entity. */ + export void SetDesiredTranslation(const FLOAT3D &vTranslation) + { + en_vDesiredTranslationRelative = vTranslation; + AddToMovers(); + } + export const FLOAT3D &GetDesiredTranslation(void) const { return en_vDesiredTranslationRelative; }; + + /* Add an impulse to the current speed of the entity (used for instantaneous launching). */ + export void GiveImpulseTranslationRelative(const FLOAT3D &vImpulseSpeedRelative) + { + CPlacement3D plImpulseSpeedAbsolute( vImpulseSpeedRelative, ANGLE3D(0,0,0)); + plImpulseSpeedAbsolute.RelativeToAbsolute( + CPlacement3D(FLOAT3D(0.0f,0.0f,0.0f), en_plPlacement.pl_OrientationAngle)); + en_vCurrentTranslationAbsolute += plImpulseSpeedAbsolute.pl_PositionVector; + AddToMovers(); + } + export void GiveImpulseTranslationAbsolute(const FLOAT3D &vImpulseSpeed) + { + en_vCurrentTranslationAbsolute += vImpulseSpeed; + AddToMovers(); + } + + export void LaunchAsPropelledProjectile(const FLOAT3D &vImpulseSpeedRelative, + CMovableEntity *penLauncher) + { + en_vDesiredTranslationRelative = vImpulseSpeedRelative; + en_vCurrentTranslationAbsolute += vImpulseSpeedRelative*en_mRotation; +// en_vCurrentTranslationAbsolute += penLauncher->en_vCurrentTranslationAbsolute; + AddToMovers(); + } + export void LaunchAsFreeProjectile(const FLOAT3D &vImpulseSpeedRelative, + CMovableEntity *penLauncher) + { + en_vCurrentTranslationAbsolute += vImpulseSpeedRelative*en_mRotation; +// en_vCurrentTranslationAbsolute += penLauncher->en_vCurrentTranslationAbsolute; +// en_fAcceleration = en_fDeceleration = 0.0f; + AddToMovers(); + } + + /* Stop all translation */ + export void ForceStopTranslation(void) { + en_vDesiredTranslationRelative = FLOAT3D(0.0f,0.0f,0.0f); + en_vCurrentTranslationAbsolute = FLOAT3D(0.0f,0.0f,0.0f); + en_vAppliedTranslation = FLOAT3D(0.0f,0.0f,0.0f); + } + + /* Stop all rotation */ + export void ForceStopRotation(void) { + en_aDesiredRotationRelative = ANGLE3D(0,0,0); + en_aCurrentRotationAbsolute = ANGLE3D(0,0,0); + en_mAppliedRotation.Diagonal(1.0f); + } + + /* Stop at once in place */ + export void ForceFullStop(void) { + ForceStopTranslation(); + ForceStopRotation(); + } + + /* Fake that the entity jumped (for jumppads) */ + export void FakeJump(const FLOAT3D &vOrgSpeed, const FLOAT3D &vDirection, FLOAT fStrength, + FLOAT fParallelMultiplier, FLOAT fNormalMultiplier, FLOAT fMaxExitSpeed, TIME tmControl) + { + // fixup jump time for right control + en_tmJumped = _pTimer->CurrentTick()-en_tmMaxJumpControl+tmControl; + + // apply parallel and normal component multipliers + FLOAT3D vCurrentNormal; + FLOAT3D vCurrentParallel; + GetParallelAndNormalComponents(vOrgSpeed, vDirection, vCurrentParallel, vCurrentNormal); + + /* + CPrintF( "\nCurrent translation absolute before: %g, %g, %g\n", + vOrgSpeed(1), + vOrgSpeed(2), + vOrgSpeed(3));*/ + + // compile translation vector + en_vCurrentTranslationAbsolute = + vCurrentParallel*fParallelMultiplier + + vCurrentNormal*fNormalMultiplier + + vDirection*fStrength; + + // clamp translation speed + FLOAT fLength = en_vCurrentTranslationAbsolute.Length(); + if( fLength > fMaxExitSpeed) + { + en_vCurrentTranslationAbsolute = + en_vCurrentTranslationAbsolute/fLength*fMaxExitSpeed; + } + + /*CPrintF( "Current translation absolute after: %g, %g, %g\n\n", + en_vCurrentTranslationAbsolute(1), + en_vCurrentTranslationAbsolute(2), + en_vCurrentTranslationAbsolute(3));*/ + + // no reference while bouncing + en_penReference = NULL; + en_pbpoStandOn = NULL; + en_vReferencePlane = FLOAT3D(0.0f, 0.0f, 0.0f); + en_iReferenceSurface = 0; + + // add to movers + AddToMovers(); + } + + /* Get relative angles from direction angles. */ + export ANGLE GetRelativeHeading(const FLOAT3D &vDirection) { + ASSERT(Abs(vDirection.Length()-1)<0.001f); // must be normalized! + // get front component of vector + FLOAT fFront = + -vDirection(1)*en_mRotation(1,3) + -vDirection(2)*en_mRotation(2,3) + -vDirection(3)*en_mRotation(3,3); + // get left component of vector + FLOAT fLeft = + -vDirection(1)*en_mRotation(1,1) + -vDirection(2)*en_mRotation(2,1) + -vDirection(3)*en_mRotation(3,1); + // relative heading is arctan of angle between front and left + return ATan2(fLeft, fFront); + } + export ANGLE GetRelativePitch(const FLOAT3D &vDirection) { + ASSERT(Abs(vDirection.Length()-1)<0.001f); // must be normalized! + // get front component of vector + FLOAT fFront = + -vDirection(1)*en_mRotation(1,3) + -vDirection(2)*en_mRotation(2,3) + -vDirection(3)*en_mRotation(3,3); + // get up component of vector + FLOAT fUp = + +vDirection(1)*en_mRotation(1,2) + +vDirection(2)*en_mRotation(2,2) + +vDirection(3)*en_mRotation(3,2); + // relative pitch is arctan of angle between front and up + return ATan2(fUp, fFront); + } + + /* Get absolute direction for a heading relative to another direction. */ + export void GetReferenceHeadingDirection(const FLOAT3D &vReference, ANGLE aH, FLOAT3D &vDirection) { + ASSERT(Abs(vReference.Length()-1)<0.001f); // must be normalized! + FLOAT3D vY(en_mRotation(1,2), en_mRotation(2,2), en_mRotation(3,2)); + FLOAT3D vX = (vY*vReference).Normalize(); + FLOAT3D vMZ = vY*vX; + vDirection = -vX*Sin(aH)+vMZ*Cos(aH); + } + + /* Get absolute direction for a heading relative to current direction. */ + export void GetHeadingDirection(ANGLE aH, FLOAT3D &vDirection) { + FLOAT3D vX(en_mRotation(1,1), en_mRotation(2,1), en_mRotation(3,1)); + FLOAT3D vZ(en_mRotation(1,3), en_mRotation(2,3), en_mRotation(3,3)); + vDirection = -vX*Sin(aH)-vZ*Cos(aH); + } + + /* Get absolute direction for a pitch relative to current direction. */ + export void GetPitchDirection(ANGLE aH, FLOAT3D &vDirection) { + FLOAT3D vY(en_mRotation(1,2), en_mRotation(2,2), en_mRotation(3,2)); + FLOAT3D vZ(en_mRotation(1,3), en_mRotation(2,3), en_mRotation(3,3)); + vDirection = -vZ*Cos(aH)+vY*Sin(aH); + } + + // get a valid inflictor for misc damage (last brush or this) + CEntity *MiscDamageInflictor(void) + { + // NOTE: must be damaged by some brush if possible, because enemies are set up so + // that they cannot harm themselves. + if (en_penLastValidReference!=NULL) { + return en_penLastValidReference; + } else { + CBrushSector *pbsc = GetFirstSector(); + if (pbsc==NULL) { + return this; + } else { + return pbsc->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + } + } + } + + // add the sector force + void UpdateOneSectorForce(CBrushSector &bsc, FLOAT fRatio) + { + // if not significantly + if (fRatio<0.01f) { + // just ignore it + return; + } + INDEX iForceType = bsc.GetForceType(); + CEntity *penEntity = bsc.bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + +/* + BOOL bAnyIn = FALSE; + CStaticArray &absSpheres = en_pciCollisionInfo->ci_absSpheres; + // for each sphere + for(INDEX iSphere=0; iSphere=0) { + bAnyIn = TRUE; + break; + } + } + if (!bAnyIn) { + return; + }*/ + + // try to find the force in container + CEntityForce *pef = NULL; + for(INDEX iForce=0; iForce<_aefForces.Count(); iForce++) { + if (penEntity ==_aefForces[iForce].ef_penEntity + &&iForceType==_aefForces[iForce].ef_iForceType) { + pef = &_aefForces[iForce]; + break; + } + } + + // if field is not found + if (pef==NULL) { + // add a new one + pef = _aefForces.Push(1); + pef->ef_penEntity = penEntity; + pef->ef_iForceType = iForceType; + pef->ef_fRatio = 0.0f; + } + pef->ef_fRatio+=fRatio; + } + + // test for field containment + void TestFields(INDEX &iUpContent, INDEX &iDnContent, FLOAT &fImmersionFactor) + { + // this works only for models + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL || en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL); + iUpContent = 0; + iDnContent = 0; + FLOAT fUp = 0.0f; + FLOAT fDn = 0.0f; + + FLOAT3D &vOffset = en_plPlacement.pl_PositionVector; + FLOATmatrix3D &mRotation = en_mRotation; + // project height min/max in the entity to absolute space + FLOAT3D vMin = FLOAT3D(0, en_pciCollisionInfo->ci_fMinHeight, 0); + FLOAT3D vMax = FLOAT3D(0, en_pciCollisionInfo->ci_fMaxHeight, 0); + vMin = vMin*mRotation+vOffset; + vMax = vMax*mRotation+vOffset; + // project all spheres in the entity to absolute space (for touch field testing) + CStaticArray &absSpheres = en_pciCollisionInfo->ci_absSpheres; + FOREACHINSTATICARRAY(absSpheres, CMovingSphere, itms) { + itms->ms_vRelativeCenter0 = itms->ms_vCenter*mRotation+vOffset; + } + + // clear forces + _aefForces.PopAll(); + // for each sector that this entity is in + {FOREACHSRCOFDST(en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + CBrushSector &bsc = *pbsc; + // if this sector is not in first mip + if (!bsc.bsc_pbmBrushMip->IsFirstMip()) { + // skip it + continue; + } + // get entity of the sector + CEntity *penSector = bsc.bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + + // if not real brush + if (penSector->en_RenderType!=RT_BRUSH) { + // skip it + continue; + } + + // get min/max parameters of entity inside sector + double dMin, dMax; + bsc.bsc_bspBSPTree.FindLineMinMax(FLOATtoDOUBLE(vMin), FLOATtoDOUBLE(vMax), dMin, dMax); + + // if sector content is not default + INDEX iContent = bsc.GetContentType(); + if (iContent!=0) { + // if inside sector at all + if (dMax>0.0f && dMin<1.0f) { + //CPrintF("%s: %lf %lf ", bsc.bsc_strName, dMin, dMax); + // if minimum is small + if (dMin<0.01f) { + // update down content + iDnContent = iContent; + fDn = Max(fDn, FLOAT(dMax)); + } + // if maximum is large + if (dMax>0.99f) { + // update up content + iUpContent = iContent; + fUp = Max(fUp, 1-FLOAT(dMin)); + } + } + } + + // add the sector force + UpdateOneSectorForce(bsc, dMax-dMin); + + ENDFOR;} + //CPrintF("%f %d %f %d\n", fDn, iDnContent, fUp, iUpContent); + + // if same contents + if (iUpContent == iDnContent) { + // trivial case + fImmersionFactor = 1.0f; + // if different contents + } else { + // calculate immersion factor + if (iUpContent==0) { + fImmersionFactor = fDn; + } else if (iDnContent==0) { + fImmersionFactor = 1-fUp; + } else { + fImmersionFactor = Max(fDn, 1-fUp); + } + // eliminate degenerate cases + if (fImmersionFactor<0.01f) { + fImmersionFactor = 1.0f; + iDnContent = iUpContent; + } else if (fImmersionFactor>0.99f) { + fImmersionFactor = 1.0f; + iUpContent = iDnContent; + } + } + + // clear force container and calculate average forces + FLOAT3D vGravityA(0,0,0); + FLOAT3D vGravityV(0,0,0); + FLOAT3D vForceA(0,0,0); + FLOAT3D vForceV(0,0,0); + FLOAT fRatioSum = 0.0f; + + {for(INDEX iForce=0; iForce<_aefForces.Count(); iForce++) { + CForceStrength fsGravity; + CForceStrength fsField; + _aefForces[iForce].ef_penEntity->GetForce( + _aefForces[iForce].ef_iForceType, en_plPlacement.pl_PositionVector, + fsGravity, fsField); + FLOAT fRatio = _aefForces[iForce].ef_fRatio; + fRatioSum+=fRatio; + vGravityA+=fsGravity.fs_vDirection*fsGravity.fs_fAcceleration*fRatio; + vGravityV+=fsGravity.fs_vDirection*fsGravity.fs_fVelocity*fRatio; + if (fsField.fs_fAcceleration>0) { + vForceA+=fsField.fs_vDirection*fsField.fs_fAcceleration*fRatio; + vForceV+=fsField.fs_vDirection*fsField.fs_fVelocity*fRatio; + } + _aefForces[iForce].Clear(); + }} + if (fRatioSum>0) { + vGravityA/=fRatioSum; + vGravityV/=fRatioSum; + vForceA/=fRatioSum; + vForceV/=fRatioSum; + } + en_fGravityA = vGravityA.Length(); + if (en_fGravityA<0.01f) { + en_fGravityA = 0; + } else { + en_fGravityV = vGravityV.Length(); + en_vGravityDir = vGravityA/en_fGravityA; + } + en_fForceA = vForceA.Length(); + if (en_fForceA<0.01f) { + en_fForceA = 0; + } else { + en_fForceV = vForceV.Length(); + en_vForceDir = vForceA/en_fForceA; + } + _aefForces.PopAll(); + } + + // test entity breathing + void TestBreathing(CContentType &ctUp) + { + // if this entity doesn't breathe + if (!(en_ulPhysicsFlags&(EPF_HASLUNGS|EPF_HASGILLS))) { + // do nothing + return; + } + // find current breathing parameters + BOOL bCanBreathe = + (ctUp.ct_ulFlags&CTF_BREATHABLE_LUNGS) && (en_ulPhysicsFlags&EPF_HASLUNGS) || + (ctUp.ct_ulFlags&CTF_BREATHABLE_GILLS) && (en_ulPhysicsFlags&EPF_HASGILLS); + TIME tmNow = _pTimer->CurrentTick(); + TIME tmBreathDelay = tmNow-en_tmLastBreathed; + // if entity can breathe now + if (bCanBreathe) { + // update breathing time + en_tmLastBreathed = tmNow; + // if it was without air for some time + if (tmBreathDelay>_pTimer->TickQuantum*2) { + // notify entity that it has take air now + ETakingBreath eTakingBreath; + eTakingBreath.fBreathDelay = tmBreathDelay/en_tmMaxHoldBreath; + SendEvent(eTakingBreath); + } + // if entity can not breathe now + } else { + // if it was without air for too long + if (tmBreathDelay>en_tmMaxHoldBreath) { + // inflict drowning damage + InflictDirectDamage(this, MiscDamageInflictor(), DMT_DROWNING, ctUp.ct_fDrowningDamageAmount, + en_plPlacement.pl_PositionVector, -en_vGravityDir); + // prolongue breathing a bit, so not to come here every frame + en_tmLastBreathed = tmNow-en_tmMaxHoldBreath+ctUp.ct_tmDrowningDamageDelay; + } + } + } + void TestContentDamage(CContentType &ctDn, FLOAT fImmersion) + { + // if the content can damage by swimming + if (ctDn.ct_fSwimDamageAmount>0) { + TIME tmNow = _pTimer->CurrentTick(); + // if there is a delay + if (ctDn.ct_tmSwimDamageDelay>0) { + // if not yet delayed + if (tmNow-en_tmLastSwimDamage>ctDn.ct_tmSwimDamageDelay+_pTimer->TickQuantum) { + // delay + en_tmLastSwimDamage = tmNow+ctDn.ct_tmSwimDamageDelay; + return; + } + } + + if (tmNow-en_tmLastSwimDamage>ctDn.ct_tmSwimDamageFrequency) { + // inflict drowning damage + InflictDirectDamage(this, MiscDamageInflictor(), + (DamageType)ctDn.ct_iSwimDamageType, ctDn.ct_fSwimDamageAmount*fImmersion, + en_plPlacement.pl_PositionVector, -en_vGravityDir); + en_tmLastSwimDamage = tmNow; + } + } + // if the content kills + if (ctDn.ct_fKillImmersion>0 && fImmersion>=ctDn.ct_fKillImmersion + &&(en_ulFlags&ENF_ALIVE)) { + // inflict killing damage + InflictDirectDamage(this, MiscDamageInflictor(), + (DamageType)ctDn.ct_iKillDamageType, GetHealth()*10.0f, + en_plPlacement.pl_PositionVector, -en_vGravityDir); + } + } + + void TestSurfaceDamage(CSurfaceType &stDn) + { + // if the surface can damage by walking + if (stDn.st_fWalkDamageAmount>0) { + TIME tmNow = _pTimer->CurrentTick(); + // if there is a delay + if (stDn.st_tmWalkDamageDelay>0) { + // if not yet delayed + if (tmNow-en_tmLastSwimDamage>stDn.st_tmWalkDamageDelay+_pTimer->TickQuantum) { + // delay + en_tmLastSwimDamage = tmNow+stDn.st_tmWalkDamageDelay; + return; + } + } + + if (tmNow-en_tmLastSwimDamage>stDn.st_tmWalkDamageFrequency) { + // inflict walking damage + InflictDirectDamage(this, MiscDamageInflictor(), + (DamageType)stDn.st_iWalkDamageType, stDn.st_fWalkDamageAmount, + en_plPlacement.pl_PositionVector, -en_vGravityDir); + en_tmLastSwimDamage = tmNow; + } + } + } + + // send touch event to this entity and touched entity + void SendTouchEvent(const CClipMove &cmMove) + { + ETouch etouchThis; + ETouch etouchOther; + etouchThis.penOther = cmMove.cm_penHit; + etouchThis.bThisMoved = FALSE; + etouchThis.plCollision = cmMove.cm_plClippedPlane; + etouchOther.penOther = this; + etouchOther.bThisMoved = TRUE; + etouchOther.plCollision = cmMove.cm_plClippedPlane; + SendEvent(etouchThis); + cmMove.cm_penHit->SendEvent(etouchOther); + } + + // send block event to this entity + void SendBlockEvent(CClipMove &cmMove) + { + EBlock eBlock; + eBlock.penOther = cmMove.cm_penHit; + eBlock.plCollision = cmMove.cm_plClippedPlane; + SendEvent(eBlock); + } + + BOOL IsStandingOnPolygon(CBrushPolygon *pbpo) + { + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + // if cannot optimize for standing on handle + if (en_pciCollisionInfo==NULL + ||!(en_pciCollisionInfo->ci_ulFlags&CIF_CANSTANDONHANDLE)) { + // not standing on polygon + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + + // if polygon is not valid for standing on any more (brush turned off collision) + if (en_pbpoStandOn->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->en_ulCollisionFlags==0) { + // not standing on polygon + return FALSE; + } + + const FLOATplane3D &plPolygon = pbpo->bpo_pbplPlane->bpl_plAbsolute; + // get stand-on handle + FLOAT3D vHandle = en_plPlacement.pl_PositionVector; + vHandle(1)+=en_pciCollisionInfo->ci_fHandleY*en_mRotation(1,2); + vHandle(2)+=en_pciCollisionInfo->ci_fHandleY*en_mRotation(2,2); + vHandle(3)+=en_pciCollisionInfo->ci_fHandleY*en_mRotation(3,2); + vHandle-=((FLOAT3D&)plPolygon)*en_pciCollisionInfo->ci_fHandleR; + + // if handle is not on the plane + if (plPolygon.PointDistance(vHandle)>0.01f) { + // not standing on polygon + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + + // find major axes of the polygon plane + INDEX iMajorAxis1, iMajorAxis2; + GetMajorAxesForPlane(plPolygon, iMajorAxis1, iMajorAxis2); + + // create an intersector + CIntersector isIntersector(vHandle(iMajorAxis1), vHandle(iMajorAxis2)); + // for all edges in the polygon + FOREACHINSTATICARRAY(pbpo->bpo_abpePolygonEdges, CBrushPolygonEdge, itbpePolygonEdge) { + // get edge vertices (edge direction is irrelevant here!) + const FLOAT3D &vVertex0 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + const FLOAT3D &vVertex1 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + // pass the edge to the intersector + isIntersector.AddEdge( + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2), + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2)); + } + + // if the point is inside polygon + if (isIntersector.IsIntersecting()) { + // entity is standing on polygon + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return TRUE; + // if the point is outside polygon + } else { + // entity is not standing on polygon + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + } + + // check whether a polygon is below given point, but not too far away + BOOL IsPolygonBelowPoint(CBrushPolygon *pbpo, const FLOAT3D &vPoint, FLOAT fMaxDist) + { + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + + // if passable or not allowed as ground + if ((pbpo->bpo_ulFlags&BPOF_PASSABLE) + ||!AllowForGroundPolygon(pbpo)) { + // it cannot be below + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + + // get polygon plane + const FLOATplane3D &plPolygon = pbpo->bpo_pbplPlane->bpl_plAbsolute; + + // determine polygon orientation relative to gravity + FLOAT fCos = ((const FLOAT3D &)plPolygon)%en_vGravityDir; + // if polygon is vertical or upside down + if (fCos>-0.01f) { + // it cannot be below + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + + // if polygon's steepness is too high + CSurfaceType &stReference = en_pwoWorld->wo_astSurfaceTypes[pbpo->bpo_bppProperties.bpp_ubSurfaceType]; + if (fCos>=-stReference.st_fClimbSlopeCos&&fCos<0 + ||stReference.st_ulFlags&STF_SLIDEDOWNSLOPE) { + // it cannot be below + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + + // get distance from point to the plane + FLOAT fD = plPolygon.PointDistance(vPoint); + // if the point is behind the plane + if (fD<-0.01f) { + // it cannot be below + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + + // find distance of point from the polygon along gravity vector + FLOAT fDistance = -fD/fCos; + // if too far away + if (fDistance > fMaxDist) { + // it cannot be below + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + // project point to the polygon along gravity vector + FLOAT3D vProjected = vPoint + en_vGravityDir*fDistance; + + // find major axes of the polygon plane + INDEX iMajorAxis1, iMajorAxis2; + GetMajorAxesForPlane(plPolygon, iMajorAxis1, iMajorAxis2); + + // create an intersector + CIntersector isIntersector(vProjected(iMajorAxis1), vProjected(iMajorAxis2)); + // for all edges in the polygon + FOREACHINSTATICARRAY(pbpo->bpo_abpePolygonEdges, CBrushPolygonEdge, itbpePolygonEdge) { + // get edge vertices (edge direction is irrelevant here!) + const FLOAT3D &vVertex0 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + const FLOAT3D &vVertex1 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + // pass the edge to the intersector + isIntersector.AddEdge( + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2), + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2)); + } + + // if the point is inside polygon + if (isIntersector.IsIntersecting()) { + // it is below + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return TRUE; + // if the point is outside polygon + } else { + // it is not below + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + } + + // override this to make filtering for what can entity stand on + export virtual BOOL AllowForGroundPolygon(CBrushPolygon *pbpo) + { + return TRUE; + } + + // check whether any cached near polygon is below given point + BOOL IsSomeNearPolygonBelowPoint(const FLOAT3D &vPoint, FLOAT fMaxDist) + { + // otherwise, there is none + return FALSE; + } + + // check whether any polygon in a sector is below given point + BOOL IsSomeSectorPolygonBelowPoint(CBrushSector *pbsc, const FLOAT3D &vPoint, FLOAT fMaxDist) + { + // for each polygon in the sector + FOREACHINSTATICARRAY(pbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + CBrushPolygon *pbpo = itbpo; + // if it is below + if (IsPolygonBelowPoint(pbpo, vPoint, fMaxDist)) { + // there is some + return TRUE; + } + } + // otherwise, there is none + return FALSE; + } + + // check whether entity would fall if standing on next position + BOOL WouldFallInNextPosition(void) + { + // if entity doesn't care for falling + if (en_fStepDnHeight<0) { + // don't check + return FALSE; + } + + // if the stand-on polygon is near below + if (en_pbpoStandOn!=NULL && + IsPolygonBelowPoint(en_pbpoStandOn, en_vNextPosition, en_fStepDnHeight)) { + // it won't fall + return FALSE; + } + + // make empty list of extra sectors to check + CListHead lhActiveSectors; + + CStaticStackArray &apbpo = en_apbpoNearPolygons; + // for each cached near polygon + for(INDEX iPolygon=0; iPolygonbpo_pbscSector->bsc_lnInActiveSectors.IsLinked()) { + // add it + lhActiveSectors.AddTail(pbpo->bpo_pbscSector->bsc_lnInActiveSectors); + } + } + + // NOTE: We add non-zoning reference first (if existing), + // to speed up cases when standing on moving brushes. + // if the reference is a non-zoning brush + if (en_penReference!=NULL && en_penReference->en_RenderType==RT_BRUSH + &&!(en_penReference->en_ulFlags&ENF_ZONING) + && en_penReference->en_pbrBrush!=NULL) { + // get first mip of the brush + CBrushMip *pbmMip = en_penReference->en_pbrBrush->GetFirstMip(); + // for each sector in the brush mip + FOREACHINDYNAMICARRAY(pbmMip->bm_abscSectors, CBrushSector, itbsc) { + // if it is not added yet + if (!itbsc->bsc_lnInActiveSectors.IsLinked()) { + // add it + lhActiveSectors.AddTail(itbsc->bsc_lnInActiveSectors); + } + } + } + + // for each zoning sector that this entity is in + {FOREACHSRCOFDST(en_rdSectors, CBrushSector, bsc_rsEntities, pbsc); + // if it is not added yet + if (!pbsc->bsc_lnInActiveSectors.IsLinked()) { + // add it + lhActiveSectors.AddTail(pbsc->bsc_lnInActiveSectors); + } + ENDFOR;} + + // for each active sector + BOOL bSupportFound = FALSE; + FOREACHINLIST(CBrushSector, bsc_lnInActiveSectors, lhActiveSectors, itbsc) { + CBrushSector *pbsc = itbsc; + // if the sector is zoning + if (pbsc->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->en_ulFlags&ENF_ZONING) { + // for non-zoning brush entities in the sector + {FOREACHDSTOFSRC(pbsc->bsc_rsEntities, CEntity, en_rdSectors, pen); + if (pen->en_RenderType==CEntity::RT_TERRAIN) { + if (IsTerrainBelowPoint(pen->en_ptrTerrain, en_vNextPosition, en_fStepDnHeight, en_vGravityDir)) { + bSupportFound = TRUE; + goto out; + } + continue; + } + if (pen->en_RenderType!=CEntity::RT_BRUSH&& + pen->en_RenderType!=CEntity::RT_FIELDBRUSH) { + break; // brushes are sorted first in list + } + // get first mip of the brush + CBrushMip *pbmMip = pen->en_pbrBrush->GetFirstMip(); + // for each sector in the brush mip + FOREACHINDYNAMICARRAY(pbmMip->bm_abscSectors, CBrushSector, itbscInMip) { + // if it is not added yet + if (!itbscInMip->bsc_lnInActiveSectors.IsLinked()) { + // add it + lhActiveSectors.AddTail(itbscInMip->bsc_lnInActiveSectors); + } + } + ENDFOR;} + } + // if there is a polygon below in that sector + if (IsSomeSectorPolygonBelowPoint(itbsc, en_vNextPosition, en_fStepDnHeight)) { + // it won't fall + bSupportFound = TRUE; + break; + } + } +out:; + + // clear list of active sectors + lhActiveSectors.RemAll(); + + // if no support, it surely would fall + return !bSupportFound; + } + + // clear next position to current placement + void ClearNextPosition(void) + { + en_vNextPosition = en_plPlacement.pl_PositionVector; + en_mNextRotation = en_mRotation; + } + // set current placement from next position + void SetPlacementFromNextPosition(void) + { + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_SETPLACEMENTFROMNEXTPOSITION); + + _pfPhysicsProfile.IncrementTimerAveragingCounter(CPhysicsProfile::PTI_SETPLACEMENTFROMNEXTPOSITION); + CPlacement3D plNew; + plNew.pl_PositionVector = en_vNextPosition; + DecomposeRotationMatrixNoSnap(plNew.pl_OrientationAngle, en_mNextRotation); + FLOATmatrix3D mRotation; + MakeRotationMatrixFast(mRotation, plNew.pl_OrientationAngle); + SetPlacement_internal(plNew, mRotation, TRUE /* try to optimize for small movements */); + + // use this for collision code debugging only not useful in real conditions +/* + // check that we have not ended inside a wall + if (GetRenderType()==RT_MODEL) { + extern BOOL CanEntityChangeCollisionBox(CEntity *pen, INDEX iNewCollisionBox, CEntity **ppenObstacle); + CEntity *penObstacle; + if (!CanEntityChangeCollisionBox(this, GetCollisionBoxIndex(), &penObstacle)) { + CPrintF("*** COLLISION!!!!\n"); + } + } + */ + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_SETPLACEMENTFROMNEXTPOSITION); + } + + BOOL TryToGoUpstairs(const FLOAT3D &vTranslationAbsolute, const CSurfaceType &stHit, + BOOL bHitStairsOrg) + { + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_TRYTOGOUPSTAIRS); + _pfPhysicsProfile.IncrementTimerAveragingCounter(CPhysicsProfile::PTI_TRYTOGOUPSTAIRS); + + // use only horizontal components of the movement + FLOAT3D vTranslationHorizontal; + GetNormalComponent(vTranslationAbsolute, en_vGravityDir, vTranslationHorizontal); + + //CPrintF("Trying: (%g) ", vTranslationHorizontal(3)); + // if the movement has no substantial value + if(vTranslationHorizontal.Length()<0.001f) { + //CPrintF("no value\n"); + // don't do it + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOGOUPSTAIRS); + return FALSE; + } + FLOAT3D vTranslationHorizontalOrg = vTranslationHorizontal; + // if the surface that is climbed on is not really stairs + if (!bHitStairsOrg) { + // keep minimum speed + vTranslationHorizontal.Normalize(); + vTranslationHorizontal*=0.5f; + } + + // remember original placement + CPlacement3D plOriginal = en_plPlacement; + + // take stairs height + FLOAT fStairsHeight = 0; + if (stHit.st_fStairsHeight>0) { + fStairsHeight = Max(stHit.st_fStairsHeight, en_fStepUpHeight); + } else if (stHit.st_fStairsHeight<0) { + fStairsHeight = Min(stHit.st_fStairsHeight, en_fStepUpHeight); + } + + CContentType &ctDn = en_pwoWorld->wo_actContentTypes[en_iDnContent]; + CContentType &ctUp = en_pwoWorld->wo_actContentTypes[en_iUpContent]; + + // if in partially in water + BOOL bGettingOutOfWater = FALSE; + if ((ctDn.ct_ulFlags&CTF_SWIMABLE) && !(ctUp.ct_ulFlags&CTF_SWIMABLE) + && en_fImmersionFactor>0.3f) { + // add immersion height to up step + if (en_pciCollisionInfo!=NULL) { + fStairsHeight=fStairsHeight*2+en_fImmersionFactor* + (en_pciCollisionInfo->ci_fMaxHeight-en_pciCollisionInfo->ci_fMinHeight); + // remember that we are trying to get out of water + bGettingOutOfWater = TRUE; + } + } + + // calculate the 3 translation directions (up, forward and down) + FLOAT3D avTranslation[3]; + avTranslation[0] = en_vGravityDir*-fStairsHeight; + avTranslation[1] = vTranslationHorizontal; + avTranslation[2] = en_vGravityDir*fStairsHeight; + + // for each translation step + for(INDEX iStep=0; iStep<3; iStep++) { + BOOL bStepOK = TRUE; + // create new placement with the translation step + en_vNextPosition = en_plPlacement.pl_PositionVector+avTranslation[iStep]; + en_mNextRotation = en_mRotation; + // clip the movement to the entity's world + CClipMove cm(this); + en_pwoWorld->ClipMove(cm); + + // if not passed + if (cm.cm_fMovementFraction<1.0f) { + // find hit surface + INDEX iSurfaceHit = 0; + BOOL bHitStairsNow = FALSE; + if (cm.cm_pbpoHit!=NULL) { + bHitStairsNow = cm.cm_pbpoHit->bpo_ulFlags&BPOF_STAIRS; + iSurfaceHit = cm.cm_pbpoHit->bpo_bppProperties.bpp_ubSurfaceType; + } + CSurfaceType &stHit = en_pwoWorld->wo_astSurfaceTypes[iSurfaceHit]; + + + // check if hit a slope while climbing stairs + const FLOAT3D &vHitPlane = cm.cm_plClippedPlane; + FLOAT fPlaneDotG = vHitPlane%en_vGravityDir; + FLOAT fPlaneDotGAbs = Abs(fPlaneDotG); + + BOOL bSlidingAllowed = (fPlaneDotGAbs>-0.01f && fPlaneDotGAbs<0.99f)&&bHitStairsOrg; + + BOOL bEarlyClipAllowed = + // going up or + iStep==0 || + // going forward and hit stairs or + iStep==1 && bHitStairsNow || + // going down and ends on something that is not high slope + iStep==2 && + (vHitPlane%en_vGravityDir<-stHit.st_fClimbSlopeCos || + bHitStairsNow); + + // if early clip is allowed + if (bEarlyClipAllowed || bSlidingAllowed) { + // try to go to where it is clipped (little bit before) + en_vNextPosition = en_plPlacement.pl_PositionVector + + avTranslation[iStep]*(cm.cm_fMovementFraction*0.98f); + if (bSlidingAllowed && iStep!=2) { + FLOAT3D vSliding = cm.cm_plClippedPlane.ProjectDirection( + avTranslation[iStep]*(1.0f-cm.cm_fMovementFraction))+ + vHitPlane*(ClampUp(avTranslation[iStep].Length(), 0.5f)/100.0f); + en_vNextPosition += vSliding; + } + CClipMove cm(this); + en_pwoWorld->ClipMove(cm); + // if it failed + if (cm.cm_fMovementFraction<=1.0f) { + // mark that this step is unsuccessful + bStepOK = FALSE; + } + // if early clip is not allowed + } else { + // mark that this step is unsuccessful + bStepOK = FALSE; + } + } + + // if the step is successful + if (bStepOK) { + // use that position + SetPlacementFromNextPosition(); + // if the step failed + } else { + // restore original placement + en_vNextPosition = plOriginal.pl_PositionVector; + SetPlacementFromNextPosition(); + // move is unsuccessful + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOGOUPSTAIRS); + //CPrintF("FAILED\n"); + return FALSE; + } + + } // end of steps loop + + // all steps passed, use the final position + + // NOTE: must not keep the speed when getting out of water, + // or the player gets launched out too fast + if (!bGettingOutOfWater) { + en_vAppliedTranslation += vTranslationHorizontalOrg; + } + // move is successful + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOGOUPSTAIRS); + //CPrintF("done\n"); + return TRUE; + } + + /* Try to translate the entity. Slide, climb or push others if needed. */ + BOOL TryToMove(CMovableEntity *penPusher, BOOL bTranslate, BOOL bRotate) + { + //CPrintF("TryToMove(%d)\n", _ctTryToMoveCheckCounter); + // decrement the recursion counter + if (penPusher!=NULL) { + _ctTryToMoveCheckCounter--; + } else { + _ctTryToMoveCheckCounter-=4; + } + // if recursing too deep + if (_ctTryToMoveCheckCounter<0) { + // fail the move + return FALSE; + } + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + _pfPhysicsProfile.IncrementTimerAveragingCounter(CPhysicsProfile::PTI_TRYTOTRANSLATE); + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_TRYTOMOVE); + + // create new placement with movement + if (bTranslate) { + en_vNextPosition = en_plPlacement.pl_PositionVector+en_vMoveTranslation; +/* STREAMDUMP START + if(GetRenderType()==RT_MODEL) + { + try + { + CTMemoryStream &strm = *GetDumpStream(); + DUMPVECTOR2("Move transl:", en_vMoveTranslation); + DUMPVECTOR2("Next pos:", en_vNextPosition); + } + catch( char *strError) + { + strError; + } + } + STREAMDUMP END */ + + } else { + en_vNextPosition = en_plPlacement.pl_PositionVector; + } + if (bRotate) { +// CPrintF(" r:???\n"); + en_mNextRotation = en_mMoveRotation*en_mRotation; + } else { + en_mNextRotation = en_mRotation; + } + + // test if rotation can be ignored + ULONG ulCIFlags = en_pciCollisionInfo->ci_ulFlags; + BOOL bIgnoreRotation = !bRotate || + ((ulCIFlags&CIF_IGNOREROTATION)|| + ( (ulCIFlags&CIF_IGNOREHEADING) && + (en_mMoveRotation(1,2)==0&&en_mMoveRotation(2,2)==1&&en_mMoveRotation(3,2)==0) )); + + // create movement towards the new placement + CClipMove cmMove(this); + // clip the movement to the entity's world + if (!bTranslate && bIgnoreRotation) { + cmMove.cm_fMovementFraction = 2.0f; + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_TRYTOMOVE_FAST); + } else { + en_pwoWorld->ClipMove(cmMove); + } + + // if the move passes + if (cmMove.cm_fMovementFraction>1.0f) { +// CPrintF(" passed\n"); + //CPrintF("%d\n", MAXCOLLISIONRETRIES-(_ctTryToMoveCheckCounter+1)); + // if entity is in walking control now, but it might fall of an edge + if (bTranslate && en_penReference!=NULL && + (en_ulPhysicsFlags&EPF_TRANSLATEDBYGRAVITY) && + !(en_ulPhysicsFlags&(EPF_ONSTEEPSLOPE|EPF_ORIENTINGTOGRAVITY|EPF_FLOATING)) && + penPusher==NULL && WouldFallInNextPosition()) { + // fail the movement + SendEvent(EWouldFall()); + //CPrintF(" wouldfall\n"); + return FALSE; + } + // make entity use its new placement + SetPlacementFromNextPosition(); + if (bTranslate) { + en_vAppliedTranslation += en_vMoveTranslation; + } + if (bRotate) { + en_mAppliedRotation = en_mMoveRotation*en_mAppliedRotation; + } + // move is successful + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_TRYTOMOVE_PASS); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + //CPrintF(" successful\n"); + return TRUE; + + // if the move is clipped + } else { + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_TRYTOMOVE_CLIP); + + /* STREAMDUMP START + if(GetRenderType()==RT_MODEL) + { + try + { + CTMemoryStream &strm = *GetDumpStream(); + strm.FPrintF_t( "Movm Fract: %g\n", cmMove.cm_fMovementFraction); + strm.FPrintF_t( "En : ID:%08x %s\n", cmMove.cm_penHit->en_ulID, (const char*) GetName() ); + DUMPVECTOR2("Pl col:", cmMove.cm_plClippedPlane); + } + catch( char *strError) + { + strError; + } + } + STREAMDUMP END */ + + // if must not retry + if (_ctTryToMoveCheckCounter<=0) { + // fail + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + return FALSE; + } + + // if hit brush + if (cmMove.cm_pbpoHit!=NULL) { + // if polygon is stairs, and the entity can climb stairs + if ((cmMove.cm_pbpoHit->bpo_ulFlags&BPOF_STAIRS) + &&((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_CLIMBORSLIDE)) { + // adjust against sliding upwards + cmMove.cm_plClippedPlane = FLOATplane3D(-en_vGravityDir, 0); + } + // if cannot be damaged by impact + INDEX iSurface = cmMove.cm_pbpoHit->bpo_bppProperties.bpp_ubSurfaceType; + if (en_pwoWorld->wo_astSurfaceTypes[iSurface].st_ulFlags&STF_NOIMPACT) { + // remember that + en_ulPhysicsFlags|=EPF_NOIMPACTTHISTICK; + } + } + + // if entity is translated by gravity and + // the hit plane is more orthogonal to the gravity than the last one found + if ((en_ulPhysicsFlags&EPF_TRANSLATEDBYGRAVITY) && !(en_ulPhysicsFlags&EPF_FLOATING) + && ( + ((en_vGravityDir%(FLOAT3D&)cmMove.cm_plClippedPlane) + <(en_vGravityDir%en_vReferencePlane)) ) ) { + // remember touched entity as stand-on reference + en_penReference = cmMove.cm_penHit; +// CPrintF(" newreference id%08x\n", en_penReference->en_ulID); + en_vReferencePlane = (FLOAT3D&)cmMove.cm_plClippedPlane; + en_pbpoStandOn = cmMove.cm_pbpoHit; // is NULL if not hit a brush + if (cmMove.cm_pbpoHit==NULL) { + en_iReferenceSurface = 0; + } else { + en_iReferenceSurface = cmMove.cm_pbpoHit->bpo_bppProperties.bpp_ubSurfaceType; + } + } + + // send touch event to this entity and to touched entity + SendTouchEvent(cmMove); + + // if cannot be damaged by impact + if (cmMove.cm_penHit->en_ulPhysicsFlags&EPF_NOIMPACT) { + // remember that + en_ulPhysicsFlags|=EPF_NOIMPACTTHISTICK; + } + + // if entity bounces when blocked + FLOAT3D vBounce; + BOOL bBounce = FALSE; + if ( ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_BOUNCE) && bTranslate) { + // create translation speed for bouncing off clipping plane + FLOAT3D vParallel, vNormal; + GetParallelAndNormalComponents(en_vMoveTranslation, cmMove.cm_plClippedPlane, + vNormal, vParallel); + vNormal *= -en_fBounceDampNormal; + vParallel *= +en_fBounceDampParallel; + vBounce = vNormal+vParallel; + // if not too small bounce + if (vNormal.Length()>0.1f) { + // do bounce + bBounce = TRUE; + } + // rotate slower + en_aDesiredRotationRelative *= en_fBounceDampParallel; + if (en_aDesiredRotationRelative.Length()<10) { + en_aDesiredRotationRelative = ANGLE3D(0,0,0); + } + } + + // if entity pushes when blocked and the blocking entity is pushable + if (penPusher!=NULL&&(cmMove.cm_penHit->en_ulPhysicsFlags&EPF_PUSHABLE)) { + CMovableModelEntity *penBlocking = ((CMovableModelEntity *)cmMove.cm_penHit); + // create push translation to account for rotating radius + FLOAT3D vRadius = cmMove.cm_penHit->en_plPlacement.pl_PositionVector- + penPusher->en_plPlacement.pl_PositionVector; + FLOAT3D vPush=(vRadius*penPusher->en_mMoveRotation-vRadius); + //*(1.01f-cmMove.cm_fMovementFraction); + vPush += penPusher->en_vMoveTranslation; + //*(1.01f-cmMove.cm_fMovementFraction); + + penBlocking->en_vMoveTranslation = vPush; + penBlocking->en_mMoveRotation = penPusher->en_mMoveRotation; + + // make sure it is added to the movers list + penBlocking->AddToMoversDuringMoving(); + // push the blocking entity + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + BOOL bUnblocked = penBlocking->TryToMove(penPusher, bTranslate, bRotate); + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + // if it has removed itself + if (bUnblocked) { + // retry the movement + ClearNextPosition(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + return TryToMove(penPusher, bTranslate, bRotate); + } else { + // move is unsuccessful + SendBlockEvent(cmMove); + ClearNextPosition(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + return FALSE; + } + // if entity slides if blocked + } else if ( + ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_SLIDE)|| + ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_BOUNCE)|| + ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_CLIMBORSLIDE)|| + ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_STOPEXACT) ){ + + // if translating + if (bTranslate) { + + // create translation for sliding along clipping plane + FLOAT3D vSliding; + // if sliding along one plane + if (_ctSliding==0) { + // remember sliding parameters from the plane + _vSlideOffDir = cmMove.cm_plClippedPlane; + // get sliding velocity + vSliding = cmMove.cm_plClippedPlane.ProjectDirection( + en_vMoveTranslation*(1.0f-cmMove.cm_fMovementFraction)); + _ctSliding++; + // if second plane + } else if (_ctSliding==1) { + // off direction is away from both planes + _vSlideOffDir+=cmMove.cm_plClippedPlane; + // sliding direction is along both planes + _vSlideDir = _vSlideOffDir*(FLOAT3D&)cmMove.cm_plClippedPlane; + if (_vSlideDir.Length()>0.001f) { + _vSlideDir.Normalize(); + } + _ctSliding++; + // get sliding velocity + GetParallelComponent(en_vMoveTranslation*(1.0f-cmMove.cm_fMovementFraction), + _vSlideDir, vSliding); + // if more than two planes + } else { + // off direction is away from all planes + _vSlideOffDir+=cmMove.cm_plClippedPlane; + // sliding direction is along all planes + _vSlideDir = cmMove.cm_plClippedPlane.ProjectDirection(_vSlideDir); + _ctSliding++; + // get sliding velocity + GetParallelComponent(en_vMoveTranslation*(1.0f-cmMove.cm_fMovementFraction), + _vSlideDir, vSliding); + } + ASSERT(IsValidFloat(vSliding(1))); + ASSERT(IsValidFloat(_vSlideDir(1))); + ASSERT(IsValidFloat(_vSlideOffDir(1))); + + // if entity hit a brush polygon + if (cmMove.cm_pbpoHit!=NULL) { + CSurfaceType &stHit = en_pwoWorld->wo_astSurfaceTypes[ + cmMove.cm_pbpoHit->bpo_bppProperties.bpp_ubSurfaceType]; + // if it is not beeing pushed, and it can climb stairs + if (penPusher==NULL + &&(en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_CLIMBORSLIDE) { + // NOTE: originally, the polygon's plane was considered here. + // due to sphere-polygon collision algo, it is possible for the collision + // plane to be even orthogonal to the polygon plane. + // considering polygon's plane prevented climbing up the stairs. + // so now, the collision plane is considered. + // if there are any further problems, i recommend choosing + // the plane that is more orthogonal to the movement direction. + FLOAT3D &vHitPlane = (FLOAT3D&)cmMove.cm_plClippedPlane;//cmMove.cm_pbpoHit->bpo_pbplPlane->bpl_plAbsolute; + BOOL bHitStairs = cmMove.cm_pbpoHit->bpo_ulFlags&BPOF_STAIRS; + // if the plane hit is steep enough to climb on it + // (cannot climb low slopes as if those were stairs) + if ((vHitPlane%en_vGravityDir>-stHit.st_fClimbSlopeCos) + ||bHitStairs) { + // if sliding along it would be mostly horizontal + // (i.e. cannot climb up the slope) + FLOAT fSlidingVertical2 = en_vMoveTranslation%en_vGravityDir; + fSlidingVertical2*=fSlidingVertical2; + FLOAT fSliding2 = en_vMoveTranslation%en_vMoveTranslation; + if ((2*fSlidingVertical2<=fSliding2) + // if can go upstairs + && TryToGoUpstairs(en_vMoveTranslation, stHit, bHitStairs)) { + // movement is ok + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + return FALSE; + } + } + } + } + // entity shouldn't really slide + if ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_STOPEXACT) { + // kill sliding + vSliding = FLOAT3D(0,0,0); + } + + ASSERT(IsValidFloat(vSliding(1))); + + // add a component perpendicular to the sliding plane + vSliding += _vSlideOffDir* + (ClampUp(en_vMoveTranslation.Length(), 0.5f)/100.0f); + + // if initial movement has some substantial value + if(en_vMoveTranslation.Length()>0.001f && cmMove.cm_fMovementFraction>0.002f) { + // go to where it is clipped (little bit before) + vSliding += en_vMoveTranslation*(cmMove.cm_fMovementFraction*0.985f); + } + + // ignore extremely small sliding + if (vSliding.ManhattanNorm()<0.001f) { + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + return FALSE; + } + + // recurse + en_vMoveTranslation = vSliding; + ClearNextPosition(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + TryToMove(penPusher, bTranslate, bRotate); + // if bouncer + if (bBounce) { + // remember bouncing speed for next tick + en_vAppliedTranslation = vBounce; + // no reference while bouncing + en_penReference = NULL; + en_vReferencePlane = FLOAT3D(0.0f, 0.0f, 0.0f); + en_iReferenceSurface = 0; + } + + // move is not entirely successful + return FALSE; + + // if rotating + } else if (bRotate) { + // if bouncing entity + if ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_BOUNCE) { + // rotate slower + en_aDesiredRotationRelative *= en_fBounceDampParallel; + if (en_aDesiredRotationRelative.Length()<10) { + en_aDesiredRotationRelative = ANGLE3D(0,0,0); + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + // move is not successful + return FALSE; + } + // create movement getting away from the collision point + en_vMoveTranslation = cmMove.cm_vClippedLine*-1.2f; + // recurse + ClearNextPosition(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + TryToMove(penPusher, TRUE, bRotate); + // move is not entirely successful + return FALSE; + } + // not translating and not rotating? - move is unsuccessful + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + return FALSE; + + // if entity has some other behaviour when blocked + } else { + // move is unsuccessful (EPF_ONBLOCK_STOP is assumed) + SendBlockEvent(cmMove); + ClearNextPosition(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_TRYTOTRANSLATE); + return FALSE; + } + } + } + + + /* STREAMDUMP START + void ExportEntityPlacementAndSpeed(CMovableEntity &en, CTString strDes) + { + try + { + CTMemoryStream &strm = *GetDumpStream(); + strm.FPrintF_t("%s : %s .................\n", strDes, (const char*) GetName()); + DUMPPLACEMENT("En pl:", en.en_plPlacement); + DUMPVECTOR2("DesTraRel:", en.en_vDesiredTranslationRelative); + DUMPVECTOR2("CurTraAbs:", en.en_vCurrentTranslationAbsolute); + DUMPVECTOR2("IntendTra:", en.en_vIntendedTranslation); + } + catch( char *strError) + { + strError; + } + } + STREAMDUMP END */ + + // clear eventual temporary variables that are not persistent + export void ClearMovingTemp(void) + { +// return; +// CLEARMEM(en_vIntendedTranslation); +// CLEARMEM(en_mIntendedRotation); + ClearNextPosition(); + CLEARMEM(en_vMoveTranslation); + CLEARMEM(en_mMoveRotation); + CLEARMEM(en_vAppliedTranslation); + CLEARMEM(en_mAppliedRotation); + } + + // prepare parameters for moving in this tick + export void PreMoving(void) + { + // + // NOTE: + // This is one more cludge for bad VC6 code generator creating sync errors in older demos. + // We are getting rid of the whole virtual actions system ASAP when the network is recoded. + // + // FOR LICENSEES: Since you don't need to replay old demos from SSam, you may remove the whole + // PreMovingOld() function. + // + if (_pNetwork->ga_ulDemoMinorVersion<=5) { + PreMovingOld(); + } else { + PreMovingNew(); + } + } + void PreMovingNew(void) + { + if (en_pciCollisionInfo==NULL) { + return; + } + + /* STREAMDUMP START + ExportEntityPlacementAndSpeed( *(CMovableEntity *)this, "Pre moving (start of function)"); + STREAMDUMP END */ + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_PREMOVING); + _pfPhysicsProfile.IncrementTimerAveragingCounter(CPhysicsProfile::PTI_PREMOVING); + + // remember old placement for lerping + en_plLastPlacement = en_plPlacement; + + // for each child of the mover + {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { + // if the child is movable, yet not in movers list + if ((itenChild->en_ulPhysicsFlags&EPF_MOVABLE) + &&!((CMovableEntity*)&*itenChild)->en_lnInMovers.IsLinked()) { + CMovableEntity *penChild = ((CMovableEntity*)&*itenChild); + // remember old placement for lerping + penChild->en_plLastPlacement = penChild->en_plPlacement; + } + }} + + FLOAT fTickQuantum=_pTimer->TickQuantum; // used for normalizing from SI units to game ticks + + // trig break point if required + if( dbg_bBreak) { + dbg_bBreak = FALSE; // auto turn off breakpoint when triggered + try { + Breakpoint(); + } catch (ANYEXCEPTION) { + CPrintF("Breakpoint!\n"); + }; + } + + // NOTE: this limits maximum velocity of any entity in game. + // it is absolutely neccessary in order to prevent extreme slowdowns in physics. + // if you plan to increase this one radically, consider decreasing + // collision grid cell size! + // currently limited to a bit less than speed of sound (not that it is any specificaly + // relevant constant, but it is just handy) + const FLOAT fMaxSpeed = 300.0f; + en_vCurrentTranslationAbsolute(1)=Clamp(en_vCurrentTranslationAbsolute(1), -fMaxSpeed, +fMaxSpeed); + en_vCurrentTranslationAbsolute(2)=Clamp(en_vCurrentTranslationAbsolute(2), -fMaxSpeed, +fMaxSpeed); + en_vCurrentTranslationAbsolute(3)=Clamp(en_vCurrentTranslationAbsolute(3), -fMaxSpeed, +fMaxSpeed); + + // if the entity is a model + if (en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL || + en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL) { + // test for field containment + TestFields(en_iUpContent, en_iDnContent, en_fImmersionFactor); + // if entity has sticky feet + if (en_ulPhysicsFlags & EPF_STICKYFEET) { + // find gravity towards nearest polygon + FLOAT3D vPoint; + FLOATplane3D plPlane; + FLOAT fDistanceToEdge; + if (GetNearestPolygon(vPoint, plPlane, fDistanceToEdge)) { + en_vGravityDir = -(FLOAT3D&)plPlane; + } + } + } + CContentType &ctDn = en_pwoWorld->wo_actContentTypes[en_iDnContent]; + CContentType &ctUp = en_pwoWorld->wo_actContentTypes[en_iUpContent]; + + // test entity breathing + TestBreathing(ctUp); + // test content damage + TestContentDamage(ctDn, en_fImmersionFactor); + // test surface damage + if (en_penReference!=NULL) { + CSurfaceType &stReference = en_pwoWorld->wo_astSurfaceTypes[en_iReferenceSurface]; + TestSurfaceDamage(stReference); + } + + // calculate content fluid factors + FLOAT fBouyancy = (1- + (ctDn.ct_fDensity/en_fDensity)*en_fImmersionFactor- + (ctUp.ct_fDensity/en_fDensity)*(1-en_fImmersionFactor)); + FLOAT fSpeedModifier = + ctDn.ct_fSpeedMultiplier*en_fImmersionFactor+ + ctUp.ct_fSpeedMultiplier*(1-en_fImmersionFactor); + FLOAT fFluidFriction = + ctDn.ct_fFluidFriction*en_fImmersionFactor+ + ctUp.ct_fFluidFriction*(1-en_fImmersionFactor); + FLOAT fControlMultiplier = + ctDn.ct_fControlMultiplier*en_fImmersionFactor+ + ctUp.ct_fControlMultiplier*(1-en_fImmersionFactor); + + // transform relative desired translation into absolute + FLOAT3D vDesiredTranslationAbsolute = en_vDesiredTranslationRelative; + // relative absolute + if (!(en_ulPhysicsFlags & EPF_ABSOLUTETRANSLATE)) { + vDesiredTranslationAbsolute *= en_mRotation; + } + // transform translation and rotation into tick time units + vDesiredTranslationAbsolute*=fTickQuantum; + ANGLE3D aRotationRelative; + aRotationRelative(1) = en_aDesiredRotationRelative(1)*fTickQuantum; + aRotationRelative(2) = en_aDesiredRotationRelative(2)*fTickQuantum; + aRotationRelative(3) = en_aDesiredRotationRelative(3)*fTickQuantum; + // make absolute matrix rotation from relative angle rotation + FLOATmatrix3D mRotationAbsolute; + + if ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_PUSH) { + FLOATmatrix3D mNewRotation; + MakeRotationMatrixFast(mNewRotation, en_plPlacement.pl_OrientationAngle+aRotationRelative); + mRotationAbsolute = mNewRotation*!en_mRotation; + + } else { + MakeRotationMatrixFast(mRotationAbsolute, aRotationRelative); + mRotationAbsolute = en_mRotation*(mRotationAbsolute*!en_mRotation); + } + + // modify desired speed for fluid parameters + vDesiredTranslationAbsolute*=fSpeedModifier; + + // remember jumping strength (if any) + FLOAT fJump = -en_mRotation.GetColumn(2)%vDesiredTranslationAbsolute; + + BOOL bReferenceMovingInY = FALSE; + BOOL bReferenceRotatingNonY = FALSE; + // if we have a CMovableEntity for a reference entity + if (en_penReference!=NULL && (en_penReference->en_ulPhysicsFlags&EPF_MOVABLE)) { + CMovableEntity *penReference = (CMovableEntity *)(CEntity*)en_penReference; + // get reference deltas for this tick + const FLOAT3D &vReferenceTranslation = penReference->en_vIntendedTranslation; + const FLOATmatrix3D &mReferenceRotation = penReference->en_mIntendedRotation; + // calculate radius of this entity relative to reference + FLOAT3D vRadius = en_plPlacement.pl_PositionVector + -penReference->en_plPlacement.pl_PositionVector; + FLOAT3D vReferenceDelta = vReferenceTranslation + vRadius*mReferenceRotation - vRadius; + // add the deltas to this entity + vDesiredTranslationAbsolute += vReferenceDelta; + mRotationAbsolute = mReferenceRotation*mRotationAbsolute; + + // remember if reference is moving in y + bReferenceMovingInY = (vReferenceDelta%en_vGravityDir != 0.0f); + bReferenceRotatingNonY = ((en_vGravityDir*mReferenceRotation)%en_vGravityDir)>0.01f; + } + + FLOAT3D vTranslationAbsolute = en_vCurrentTranslationAbsolute*fTickQuantum; + + // initially not orienting + en_ulPhysicsFlags&=~EPF_ORIENTINGTOGRAVITY; + // if the entity is rotated by gravity + if (en_ulPhysicsFlags&EPF_ORIENTEDBYGRAVITY) { + // find entity's down vector + FLOAT3D vDown; + vDown(1) = -en_mRotation(1,2); + vDown(2) = -en_mRotation(2,2); + vDown(3) = -en_mRotation(3,2); + + // find angle entities down and gravity down + FLOAT fCos = vDown%en_vGravityDir; + // if substantial + if (fCos<0.99999f) { + // mark + en_ulPhysicsFlags|=EPF_ORIENTINGTOGRAVITY; + + // limit the angle rotation + ANGLE a = ACos(fCos); + if (Abs(a)>20) { + a = 20*Sgn(a); + } + FLOAT fRad =RadAngle(a); + + // make rotation axis + FLOAT3D vAxis = vDown*en_vGravityDir; + FLOAT fLen = vAxis.Length(); + if (fLen<0.01f) { + vAxis(1) = en_mRotation(1,3); + vAxis(2) = en_mRotation(2,3); + vAxis(3) = en_mRotation(3,3); + // NOTE: must have this patch for smooth rocking on moving brushes + // (should infact do fRad/=fLen always) + } else if (!bReferenceRotatingNonY) { + fRad/=fLen; + } + vAxis*=fRad; + + // make rotation matrix + FLOATmatrix3D mGRotation; + mGRotation(1,1) = 1; mGRotation(1,2) = -vAxis(3); mGRotation(1,3) = vAxis(2); + mGRotation(2,1) = vAxis(3); mGRotation(2,2) = 1; mGRotation(2,3) = -vAxis(1); + mGRotation(3,1) = -vAxis(2); mGRotation(3,2) = vAxis(1); mGRotation(3,3) = 1; + OrthonormalizeRotationMatrix(mGRotation); + + // add the gravity rotation + mRotationAbsolute = mGRotation*mRotationAbsolute; + } + } + + // initially not floating + en_ulPhysicsFlags&=~EPF_FLOATING; + + FLOAT ACC=en_fAcceleration*fTickQuantum*fTickQuantum; + FLOAT DEC=en_fDeceleration*fTickQuantum*fTickQuantum; + // if the entity is not affected by gravity + if (!(en_ulPhysicsFlags&EPF_TRANSLATEDBYGRAVITY)) { + // accellerate towards desired absolute translation + if (en_ulPhysicsFlags&EPF_NOACCELERATION) { + vTranslationAbsolute = vDesiredTranslationAbsolute; + } else { + AddAcceleration(vTranslationAbsolute, vDesiredTranslationAbsolute, + ACC*fControlMultiplier, + DEC*fControlMultiplier); + } + // if swimming + } else if ((fBouyancy*en_fGravityA<0.5f && (ctDn.ct_ulFlags&(CTF_SWIMABLE|CTF_FLYABLE)))) { + // mark that + en_ulPhysicsFlags|=EPF_FLOATING; + // accellerate towards desired absolute translation + if (en_ulPhysicsFlags&EPF_NOACCELERATION) { + vTranslationAbsolute = vDesiredTranslationAbsolute; + } else { + AddAcceleration(vTranslationAbsolute, vDesiredTranslationAbsolute, + ACC*fControlMultiplier, + DEC*fControlMultiplier); + } + + // add gravity acceleration + if (fBouyancy<-0.1f) { + FLOAT fGV=en_fGravityV*fTickQuantum*fSpeedModifier; + FLOAT fGA=(en_fGravityA*-fBouyancy)*fTickQuantum*fTickQuantum; + AddAcceleration(vTranslationAbsolute, en_vGravityDir*-fGV, fGA, fGA); + } else if (fBouyancy>+0.1f) { + FLOAT fGV=en_fGravityV*fTickQuantum*fSpeedModifier; + FLOAT fGA=(en_fGravityA*fBouyancy)*fTickQuantum*fTickQuantum; + AddAcceleration(vTranslationAbsolute, en_vGravityDir*fGV, fGA, fGA); + } + + // if the entity is affected by gravity + } else { + BOOL bGravityAlongPolygon = TRUE; + // if there is no fixed remembered stand-on polygon or the entity is not on it anymore + if (en_pbpoStandOn==NULL || !IsStandingOnPolygon(en_pbpoStandOn) || bReferenceMovingInY + || (en_ulPhysicsFlags&EPF_ORIENTINGTOGRAVITY)) { + // clear the stand on polygon + en_pbpoStandOn=NULL; + if (en_penReference == NULL || bReferenceMovingInY) { + bGravityAlongPolygon = FALSE; + } + } + + // if gravity can cause the entity to fall + if (!bGravityAlongPolygon) { + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_GRAVITY_NONTRIVIAL); + + // add gravity acceleration + FLOAT fGV=en_fGravityV*fTickQuantum*fSpeedModifier; + FLOAT fGA=(en_fGravityA*fBouyancy)*fTickQuantum*fTickQuantum; + AddGAcceleration(vTranslationAbsolute, en_vGravityDir, fGA, fGV); + // if entity can only slide down its stand-on polygon + } else { + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_GRAVITY_TRIVIAL); + + // disassemble gravity to parts parallel and normal to plane + FLOAT3D vPolygonDir = -en_vReferencePlane; + // NOTE: normal to plane=paralel to plane normal vector! + FLOAT3D vGParallel, vGNormal; + GetParallelAndNormalComponents(en_vGravityDir, vPolygonDir, vGNormal, vGParallel); + // add gravity part parallel to plane + FLOAT fFactor = vGParallel.Length(); + + if (fFactor>0.001f) { + FLOAT fGV=en_fGravityV*fTickQuantum*fSpeedModifier; + FLOAT fGA=(en_fGravityA*fBouyancy)*fTickQuantum*fTickQuantum; + AddGAcceleration(vTranslationAbsolute, vGParallel/fFactor, fGA*fFactor, fGV*fFactor); + } + + // kill your normal-to-polygon speed if towards polygon and small + FLOAT fPolyGA = (vPolygonDir%en_vGravityDir)*en_fGravityA; + FLOAT fYSpeed = vPolygonDir%vTranslationAbsolute; + if (fYSpeed>0 && fYSpeed < fPolyGA) { + vTranslationAbsolute -= vPolygonDir*fYSpeed; + } + + // if a bouncer + if ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_BOUNCE) { + // rotate slower + en_aDesiredRotationRelative *= en_fJumpControlMultiplier; + if (en_aDesiredRotationRelative.Length()<10) { + en_aDesiredRotationRelative = ANGLE3D(0,0,0); + } + } + } + + CSurfaceType &stReference = en_pwoWorld->wo_astSurfaceTypes[en_iReferenceSurface]; + + // if it has a reference entity + if (en_penReference!=NULL) { + FLOAT fPlaneY = (en_vGravityDir%en_vReferencePlane); + FLOAT fPlaneYAbs = Abs(fPlaneY); + FLOAT fFriction = stReference.st_fFriction; + // if on a steep slope + if (fPlaneY>=-stReference.st_fClimbSlopeCos&&fPlaneY<0 + ||(stReference.st_ulFlags&STF_SLIDEDOWNSLOPE)&&fPlaneY>-0.99f) { + en_ulPhysicsFlags|=EPF_ONSTEEPSLOPE; + // accellerate horizontaly towards desired absolute translation + AddAccelerationOnPlane2( + vTranslationAbsolute, + vDesiredTranslationAbsolute, + ACC*fPlaneYAbs*fPlaneYAbs*fFriction*fControlMultiplier, + DEC*fPlaneYAbs*fPlaneYAbs*fFriction*fControlMultiplier, + en_vReferencePlane, + en_vGravityDir); + // if not on a steep slope + } else { + en_ulPhysicsFlags&=~EPF_ONSTEEPSLOPE; + // accellerate on plane towards desired absolute translation + AddAccelerationOnPlane( + vTranslationAbsolute, + vDesiredTranslationAbsolute, + ACC*fPlaneYAbs*fPlaneYAbs*fFriction*fControlMultiplier, + DEC*fPlaneYAbs*fPlaneYAbs*fFriction*fControlMultiplier, + en_vReferencePlane); + } + // if wants to jump and can jump + if (fJump<-0.01f && (fPlaneY<-stReference.st_fJumpSlopeCos + || _pTimer->CurrentTick()>en_tmLastSignificantVerticalMovement+0.25f) ) { + // jump + vTranslationAbsolute += en_vGravityDir*fJump; + en_tmJumped = _pTimer->CurrentTick(); + en_pbpoStandOn = NULL; + } + + // if it doesn't have a reference entity + } else {//if (en_penReference==NULL) + // if can control after jump + if (_pTimer->CurrentTick()-en_tmJumpedCurrentTick()>en_tmLastSignificantVerticalMovement+0.25f) { + // jump + vTranslationAbsolute += en_vGravityDir*fJump; + en_tmJumped = _pTimer->CurrentTick(); + en_pbpoStandOn = NULL; + } + } + } + + // check for force-field acceleration + // NOTE: pulled out because of a bug in VC code generator, see function comments above + CheckAndAddGAcceleration(this, vTranslationAbsolute, fTickQuantum); + + // if there is fluid friction involved + if (fFluidFriction>0.01f) { + // slow down + AddAcceleration(vTranslationAbsolute, FLOAT3D(0.0f, 0.0f, 0.0f), + 0.0f, DEC*fFluidFriction); + } + + // if may slow down spinning + if ( (en_ulPhysicsFlags& EPF_CANFADESPINNING) && + ( (ctDn.ct_ulFlags&CTF_FADESPINNING) || (ctUp.ct_ulFlags&CTF_FADESPINNING) ) ) { + // reduce desired rotation + en_aDesiredRotationRelative *= (1-fSpeedModifier*0.05f); + if (en_aDesiredRotationRelative.Length()<10) { + en_aDesiredRotationRelative = ANGLE3D(0,0,0); + } + } + + // discard reference entity (will be recalculated) + if (en_pbpoStandOn==NULL && (vTranslationAbsolute.ManhattanNorm()>1E-5f || + en_vReferencePlane%en_vGravityDir<0.0f)) { + en_penReference = NULL; + en_vReferencePlane = FLOAT3D(0.0f, 0.0f, 0.0f); + en_iReferenceSurface = 0; + } + + en_vIntendedTranslation = vTranslationAbsolute; + en_mIntendedRotation = mRotationAbsolute; + + //-- estimate future movements for collision caching + + // make box of the entity for its current rotation + FLOATaabbox3D box; + en_pciCollisionInfo->MakeBoxAtPlacement(FLOAT3D(0,0,0), en_mRotation, box); + // if it is a light source + {CLightSource *pls = GetLightSource(); + if (pls!=NULL && !(pls->ls_ulFlags&LSF_LENSFLAREONLY)) { + // expand the box to be sure that it contains light range + ASSERT(!(pls->ls_ulFlags&LSF_DIRECTIONAL)); + box |= FLOATaabbox3D(FLOAT3D(0,0,0), pls->ls_rFallOff); + }} + // add a bit around it + box.ExpandByFactor( phy_fCollisionCacheAround-1.0f); + // make box go few ticks ahead of the entity + box += en_plPlacement.pl_PositionVector; + en_boxMovingEstimate = box; + box += en_vIntendedTranslation*phy_fCollisionCacheAhead; + en_boxMovingEstimate |= box; + + // clear applied movement to be updated during movement + en_vAppliedTranslation = FLOAT3D(0.0f, 0.0f, 0.0f); + en_mAppliedRotation.Diagonal(1.0f); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_PREMOVING); +// STREAMDUMP ExportEntityPlacementAndSpeed( *(CMovableEntity *)this, "Pre moving (end of function)"); + } + + // VC6 KLUDGE - do not change this function + // See note above in PreMoving() +/* old */ void PreMovingOld(void) +/* old */ { +/* old */ if (en_pciCollisionInfo==NULL) { +/* old */ return; +/* old */ } +/* old */ +/* old */ //STREAMDUMP START +/* old */ // ExportEntityPlacementAndSpeed( *(CMovableEntity *)this, "Pre moving (start of function)"); +/* old */ //STREAMDUMP END +/* old */ +/* old */ _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_PREMOVING); +/* old */ _pfPhysicsProfile.IncrementTimerAveragingCounter(CPhysicsProfile::PTI_PREMOVING); +/* old */ +/* old */ // remember old placement for lerping +/* old */ en_plLastPlacement = en_plPlacement; +/* old */ +/* old */ // for each child of the mover +/* old */ {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { +/* old */ // if the child is movable, yet not in movers list +/* old */ if ((itenChild->en_ulPhysicsFlags&EPF_MOVABLE) +/* old */ &&!((CMovableEntity*)&*itenChild)->en_lnInMovers.IsLinked()) { +/* old */ CMovableEntity *penChild = ((CMovableEntity*)&*itenChild); +/* old */ // remember old placement for lerping +/* old */ penChild->en_plLastPlacement = penChild->en_plPlacement; +/* old */ } +/* old */ }} +/* old */ +/* old */ FLOAT fTickQuantum=_pTimer->TickQuantum; // used for normalizing from SI units to game ticks +/* old */ +/* old */ // trig break point if required +/* old */ if( dbg_bBreak) { +/* old */ dbg_bBreak = FALSE; // auto turn off breakpoint when triggered +/* old */ try { +/* old */ Breakpoint(); +/* old */ } catch (ANYEXCEPTION) { +/* old */ CPrintF("Breakpoint!\n"); +/* old */ }; +/* old */ } +/* old */ +/* old */ // NOTE: this limits maximum velocity of any entity in game. +/* old */ // it is absolutely neccessary in order to prevent extreme slowdowns in physics. +/* old */ // if you plan to increase this one radically, consider decreasing +/* old */ // collision grid cell size! +/* old */ // currently limited to a bit less than speed of sound (not that it is any specificaly +/* old */ // relevant constant, but it is just handy) +/* old */ const FLOAT fMaxSpeed = 300.0f; +/* old */ en_vCurrentTranslationAbsolute(1)=Clamp(en_vCurrentTranslationAbsolute(1), -fMaxSpeed, +fMaxSpeed); +/* old */ en_vCurrentTranslationAbsolute(2)=Clamp(en_vCurrentTranslationAbsolute(2), -fMaxSpeed, +fMaxSpeed); +/* old */ en_vCurrentTranslationAbsolute(3)=Clamp(en_vCurrentTranslationAbsolute(3), -fMaxSpeed, +fMaxSpeed); +/* old */ +/* old */ // if the entity is a model +/* old */ if (en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL) { +/* old */ // test for field containment +/* old */ TestFields(en_iUpContent, en_iDnContent, en_fImmersionFactor); +/* old */ // if entity has sticky feet +/* old */ if (en_ulPhysicsFlags & EPF_STICKYFEET) { +/* old */ // find gravity towards nearest polygon +/* old */ FLOAT3D vPoint; +/* old */ FLOATplane3D plPlane; +/* old */ FLOAT fDistanceToEdge; +/* old */ if (GetNearestPolygon(vPoint, plPlane, fDistanceToEdge)) { +/* old */ en_vGravityDir = -(FLOAT3D&)plPlane; +/* old */ } +/* old */ } +/* old */ } +/* old */ CContentType &ctDn = en_pwoWorld->wo_actContentTypes[en_iDnContent]; +/* old */ CContentType &ctUp = en_pwoWorld->wo_actContentTypes[en_iUpContent]; +/* old */ +/* old */ // test entity breathing +/* old */ TestBreathing(ctUp); +/* old */ // test content damage +/* old */ TestContentDamage(ctDn, en_fImmersionFactor); +/* old */ // test surface damage +/* old */ if (en_penReference!=NULL) { +/* old */ CSurfaceType &stReference = en_pwoWorld->wo_astSurfaceTypes[en_iReferenceSurface]; +/* old */ TestSurfaceDamage(stReference); +/* old */ } +/* old */ +/* old */ // calculate content fluid factors +/* old */ FLOAT fBouyancy = (1- +/* old */ (ctDn.ct_fDensity/en_fDensity)*en_fImmersionFactor- +/* old */ (ctUp.ct_fDensity/en_fDensity)*(1-en_fImmersionFactor)); +/* old */ FLOAT fSpeedModifier = +/* old */ ctDn.ct_fSpeedMultiplier*en_fImmersionFactor+ +/* old */ ctUp.ct_fSpeedMultiplier*(1-en_fImmersionFactor); +/* old */ FLOAT fFluidFriction = +/* old */ ctDn.ct_fFluidFriction*en_fImmersionFactor+ +/* old */ ctUp.ct_fFluidFriction*(1-en_fImmersionFactor); +/* old */ FLOAT fControlMultiplier = +/* old */ ctDn.ct_fControlMultiplier*en_fImmersionFactor+ +/* old */ ctUp.ct_fControlMultiplier*(1-en_fImmersionFactor); +/* old */ +/* old */ // transform relative desired translation into absolute +/* old */ FLOAT3D vDesiredTranslationAbsolute = en_vDesiredTranslationRelative; +/* old */ // relative absolute +/* old */ if (!(en_ulPhysicsFlags & EPF_ABSOLUTETRANSLATE)) { +/* old */ vDesiredTranslationAbsolute *= en_mRotation; +/* old */ } +/* old */ // transform translation and rotation into tick time units +/* old */ vDesiredTranslationAbsolute*=fTickQuantum; +/* old */ ANGLE3D aRotationRelative; +/* old */ aRotationRelative(1) = en_aDesiredRotationRelative(1)*fTickQuantum; +/* old */ aRotationRelative(2) = en_aDesiredRotationRelative(2)*fTickQuantum; +/* old */ aRotationRelative(3) = en_aDesiredRotationRelative(3)*fTickQuantum; +/* old */ // make absolute matrix rotation from relative angle rotation +/* old */ FLOATmatrix3D mRotationAbsolute; +/* old */ +/* old */ if ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_PUSH) { +/* old */ FLOATmatrix3D mNewRotation; +/* old */ MakeRotationMatrixFast(mNewRotation, en_plPlacement.pl_OrientationAngle+aRotationRelative); +/* old */ mRotationAbsolute = mNewRotation*!en_mRotation; +/* old */ +/* old */ } else { +/* old */ MakeRotationMatrixFast(mRotationAbsolute, aRotationRelative); +/* old */ mRotationAbsolute = en_mRotation*(mRotationAbsolute*!en_mRotation); +/* old */ } +/* old */ +/* old */ // modify desired speed for fluid parameters +/* old */ vDesiredTranslationAbsolute*=fSpeedModifier; +/* old */ +/* old */ // remember jumping strength (if any) +/* old */ FLOAT fJump = -en_mRotation.GetColumn(2)%vDesiredTranslationAbsolute; +/* old */ +/* old */ BOOL bReferenceMovingInY = FALSE; +/* old */ BOOL bReferenceRotatingNonY = FALSE; +/* old */ // if we have a CMovableEntity for a reference entity +/* old */ if (en_penReference!=NULL && (en_penReference->en_ulPhysicsFlags&EPF_MOVABLE)) { +/* old */ CMovableEntity *penReference = (CMovableEntity *)(CEntity*)en_penReference; +/* old */ // get reference deltas for this tick +/* old */ const FLOAT3D &vReferenceTranslation = penReference->en_vIntendedTranslation; +/* old */ const FLOATmatrix3D &mReferenceRotation = penReference->en_mIntendedRotation; +/* old */ // calculate radius of this entity relative to reference +/* old */ FLOAT3D vRadius = en_plPlacement.pl_PositionVector +/* old */ -penReference->en_plPlacement.pl_PositionVector; +/* old */ FLOAT3D vReferenceDelta = vReferenceTranslation + vRadius*mReferenceRotation - vRadius; +/* old */ // add the deltas to this entity +/* old */ vDesiredTranslationAbsolute += vReferenceDelta; +/* old */ mRotationAbsolute = mReferenceRotation*mRotationAbsolute; +/* old */ +/* old */ // remember if reference is moving in y +/* old */ bReferenceMovingInY = (vReferenceDelta%en_vGravityDir != 0.0f); +/* old */ bReferenceRotatingNonY = ((en_vGravityDir*mReferenceRotation)%en_vGravityDir)>0.01f; +/* old */ } +/* old */ +/* old */ FLOAT3D vTranslationAbsolute = en_vCurrentTranslationAbsolute*fTickQuantum; +/* old */ +/* old */ // initially not orienting +/* old */ en_ulPhysicsFlags&=~EPF_ORIENTINGTOGRAVITY; +/* old */ // if the entity is rotated by gravity +/* old */ if (en_ulPhysicsFlags&EPF_ORIENTEDBYGRAVITY) { +/* old */ // find entity's down vector +/* old */ FLOAT3D vDown; +/* old */ vDown(1) = -en_mRotation(1,2); +/* old */ vDown(2) = -en_mRotation(2,2); +/* old */ vDown(3) = -en_mRotation(3,2); +/* old */ +/* old */ // find angle entities down and gravity down +/* old */ FLOAT fCos = vDown%en_vGravityDir; +/* old */ // if substantial +/* old */ if (fCos<0.99999f) { +/* old */ // mark +/* old */ en_ulPhysicsFlags|=EPF_ORIENTINGTOGRAVITY; +/* old */ +/* old */ // limit the angle rotation +/* old */ ANGLE a = ACos(fCos); +/* old */ if (Abs(a)>20) { +/* old */ a = 20*Sgn(a); +/* old */ } +/* old */ FLOAT fRad =RadAngle(a); +/* old */ +/* old */ // make rotation axis +/* old */ FLOAT3D vAxis = vDown*en_vGravityDir; +/* old */ FLOAT fLen = vAxis.Length(); +/* old */ if (fLen<0.01f) { +/* old */ vAxis(1) = en_mRotation(1,3); +/* old */ vAxis(2) = en_mRotation(2,3); +/* old */ vAxis(3) = en_mRotation(3,3); +/* old */ // NOTE: must have this patch for smooth rocking on moving brushes +/* old */ // (should infact do fRad/=fLen always) +/* old */ } else if (!bReferenceRotatingNonY) { +/* old */ fRad/=fLen; +/* old */ } +/* old */ vAxis*=fRad; +/* old */ +/* old */ // make rotation matrix +/* old */ FLOATmatrix3D mGRotation; +/* old */ mGRotation(1,1) = 1; mGRotation(1,2) = -vAxis(3); mGRotation(1,3) = vAxis(2); +/* old */ mGRotation(2,1) = vAxis(3); mGRotation(2,2) = 1; mGRotation(2,3) = -vAxis(1); +/* old */ mGRotation(3,1) = -vAxis(2); mGRotation(3,2) = vAxis(1); mGRotation(3,3) = 1; +/* old */ OrthonormalizeRotationMatrix(mGRotation); +/* old */ +/* old */ // add the gravity rotation +/* old */ mRotationAbsolute = mGRotation*mRotationAbsolute; +/* old */ } +/* old */ } +/* old */ +/* old */ // initially not floating +/* old */ en_ulPhysicsFlags&=~EPF_FLOATING; +/* old */ +/* old */ FLOAT ACC=en_fAcceleration*fTickQuantum*fTickQuantum; +/* old */ FLOAT DEC=en_fDeceleration*fTickQuantum*fTickQuantum; +/* old */ // if the entity is not affected by gravity +/* old */ if (!(en_ulPhysicsFlags&EPF_TRANSLATEDBYGRAVITY)) { +/* old */ // accellerate towards desired absolute translation +/* old */ if (en_ulPhysicsFlags&EPF_NOACCELERATION) { +/* old */ vTranslationAbsolute = vDesiredTranslationAbsolute; +/* old */ } else { +/* old */ AddAcceleration(vTranslationAbsolute, vDesiredTranslationAbsolute, +/* old */ ACC*fControlMultiplier, +/* old */ DEC*fControlMultiplier); +/* old */ } +/* old */ // if swimming +/* old */ } else if ((fBouyancy*en_fGravityA<0.5f && (ctDn.ct_ulFlags&(CTF_SWIMABLE|CTF_FLYABLE)))) { +/* old */ // mark that +/* old */ en_ulPhysicsFlags|=EPF_FLOATING; +/* old */ // accellerate towards desired absolute translation +/* old */ if (en_ulPhysicsFlags&EPF_NOACCELERATION) { +/* old */ vTranslationAbsolute = vDesiredTranslationAbsolute; +/* old */ } else { +/* old */ AddAcceleration(vTranslationAbsolute, vDesiredTranslationAbsolute, +/* old */ ACC*fControlMultiplier, +/* old */ DEC*fControlMultiplier); +/* old */ } +/* old */ +/* old */ // add gravity acceleration +/* old */ if (fBouyancy<-0.1f) { +/* old */ FLOAT fGV=en_fGravityV*fTickQuantum*fSpeedModifier; +/* old */ FLOAT fGA=(en_fGravityA*-fBouyancy)*fTickQuantum*fTickQuantum; +/* old */ AddAcceleration(vTranslationAbsolute, en_vGravityDir*-fGV, fGA, fGA); +/* old */ } else if (fBouyancy>+0.1f) { +/* old */ FLOAT fGV=en_fGravityV*fTickQuantum*fSpeedModifier; +/* old */ FLOAT fGA=(en_fGravityA*fBouyancy)*fTickQuantum*fTickQuantum; +/* old */ AddAcceleration(vTranslationAbsolute, en_vGravityDir*fGV, fGA, fGA); +/* old */ } +/* old */ +/* old */ // if the entity is affected by gravity +/* old */ } else { +/* old */ BOOL bGravityAlongPolygon = TRUE; +/* old */ // if there is no fixed remembered stand-on polygon or the entity is not on it anymore +/* old */ if (en_pbpoStandOn==NULL || !IsStandingOnPolygon(en_pbpoStandOn) || bReferenceMovingInY +/* old */ || (en_ulPhysicsFlags&EPF_ORIENTINGTOGRAVITY)) { +/* old */ // clear the stand on polygon +/* old */ en_pbpoStandOn=NULL; +/* old */ if (en_penReference == NULL || bReferenceMovingInY) { +/* old */ bGravityAlongPolygon = FALSE; +/* old */ } +/* old */ } +/* old */ +/* old */ // if gravity can cause the entity to fall +/* old */ if (!bGravityAlongPolygon) { +/* old */ _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_GRAVITY_NONTRIVIAL); +/* old */ +/* old */ // add gravity acceleration +/* old */ FLOAT fGV=en_fGravityV*fTickQuantum*fSpeedModifier; +/* old */ FLOAT fGA=(en_fGravityA*fBouyancy)*fTickQuantum*fTickQuantum; +/* old */ AddGAcceleration(vTranslationAbsolute, en_vGravityDir, fGA, fGV); +/* old */ // if entity can only slide down its stand-on polygon +/* old */ } else { +/* old */ _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_GRAVITY_TRIVIAL); +/* old */ +/* old */ // disassemble gravity to parts parallel and normal to plane +/* old */ FLOAT3D vPolygonDir = -en_vReferencePlane; +/* old */ // NOTE: normal to plane=paralel to plane normal vector! +/* old */ FLOAT3D vGParallel, vGNormal; +/* old */ GetParallelAndNormalComponents(en_vGravityDir, vPolygonDir, vGNormal, vGParallel); +/* old */ // add gravity part parallel to plane +/* old */ FLOAT fFactor = vGParallel.Length(); +/* old */ +/* old */ if (fFactor>0.001f) { +/* old */ FLOAT fGV=en_fGravityV*fTickQuantum*fSpeedModifier; +/* old */ FLOAT fGA=(en_fGravityA*fBouyancy)*fTickQuantum*fTickQuantum; +/* old */ AddGAcceleration(vTranslationAbsolute, vGParallel/fFactor, fGA*fFactor, fGV*fFactor); +/* old */ } +/* old */ +/* old */ // kill your normal-to-polygon speed if towards polygon and small +/* old */ FLOAT fPolyGA = (vPolygonDir%en_vGravityDir)*en_fGravityA; +/* old */ FLOAT fYSpeed = vPolygonDir%vTranslationAbsolute; +/* old */ if (fYSpeed>0 && fYSpeed < fPolyGA) { +/* old */ vTranslationAbsolute -= vPolygonDir*fYSpeed; +/* old */ } +/* old */ +/* old */ // if a bouncer +/* old */ if ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_BOUNCE) { +/* old */ // rotate slower +/* old */ en_aDesiredRotationRelative *= en_fJumpControlMultiplier; +/* old */ if (en_aDesiredRotationRelative.Length()<10) { +/* old */ en_aDesiredRotationRelative = ANGLE3D(0,0,0); +/* old */ } +/* old */ } +/* old */ } +/* old */ +/* old */ CSurfaceType &stReference = en_pwoWorld->wo_astSurfaceTypes[en_iReferenceSurface]; +/* old */ +/* old */ // if it has a reference entity +/* old */ if (en_penReference!=NULL) { +/* old */ FLOAT fPlaneY = (en_vGravityDir%en_vReferencePlane); +/* old */ FLOAT fPlaneYAbs = Abs(fPlaneY); +/* old */ FLOAT fFriction = stReference.st_fFriction; +/* old */ // if on a steep slope +/* old */ if (fPlaneY>=-stReference.st_fClimbSlopeCos&&fPlaneY<0 +/* old */ ||(stReference.st_ulFlags&STF_SLIDEDOWNSLOPE)&&fPlaneY>-0.99f) { +/* old */ en_ulPhysicsFlags|=EPF_ONSTEEPSLOPE; +/* old */ // accellerate horizontaly towards desired absolute translation +/* old */ AddAccelerationOnPlane2( +/* old */ vTranslationAbsolute, +/* old */ vDesiredTranslationAbsolute, +/* old */ ACC*fPlaneYAbs*fPlaneYAbs*fFriction*fControlMultiplier, +/* old */ DEC*fPlaneYAbs*fPlaneYAbs*fFriction*fControlMultiplier, +/* old */ en_vReferencePlane, +/* old */ en_vGravityDir); +/* old */ // if not on a steep slope +/* old */ } else { +/* old */ en_ulPhysicsFlags&=~EPF_ONSTEEPSLOPE; +/* old */ // accellerate on plane towards desired absolute translation +/* old */ AddAccelerationOnPlane( +/* old */ vTranslationAbsolute, +/* old */ vDesiredTranslationAbsolute, +/* old */ ACC*fPlaneYAbs*fPlaneYAbs*fFriction*fControlMultiplier, +/* old */ DEC*fPlaneYAbs*fPlaneYAbs*fFriction*fControlMultiplier, +/* old */ en_vReferencePlane); +/* old */ } +/* old */ // if wants to jump and can jump +/* old */ if (fJump<-0.01f && (fPlaneY<-stReference.st_fJumpSlopeCos +/* old */ || _pTimer->CurrentTick()>en_tmLastSignificantVerticalMovement+0.25f) ) { +/* old */ // jump +/* old */ vTranslationAbsolute += en_vGravityDir*fJump; +/* old */ en_tmJumped = _pTimer->CurrentTick(); +/* old */ en_pbpoStandOn = NULL; +/* old */ } +/* old */ +/* old */ // if it doesn't have a reference entity +/* old */ } else {//if (en_penReference==NULL) +/* old */ // if can control after jump +/* old */ if (_pTimer->CurrentTick()-en_tmJumpedCurrentTick()>en_tmLastSignificantVerticalMovement+0.25f) { +/* old */ // jump +/* old */ vTranslationAbsolute += en_vGravityDir*fJump; +/* old */ en_tmJumped = _pTimer->CurrentTick(); +/* old */ en_pbpoStandOn = NULL; +/* old */ } +/* old */ } +/* old */ } +/* old */ +/* old */ // check for force-field acceleration +/* old */ // NOTE: pulled out because of a bug in VC code generator, see function comments above +/* old */ CheckAndAddGAcceleration(this, vTranslationAbsolute, fTickQuantum); +/* old */ +/* old */ // if there is fluid friction involved +/* old */ if (fFluidFriction>0.01f) { +/* old */ // slow down +/* old */ AddAcceleration(vTranslationAbsolute, FLOAT3D(0.0f, 0.0f, 0.0f), +/* old */ 0.0f, DEC*fFluidFriction); +/* old */ } +/* old */ +/* old */ // if may slow down spinning +/* old */ if ( (en_ulPhysicsFlags& EPF_CANFADESPINNING) && +/* old */ ( (ctDn.ct_ulFlags&CTF_FADESPINNING) || (ctUp.ct_ulFlags&CTF_FADESPINNING) ) ) { +/* old */ // reduce desired rotation +/* old */ en_aDesiredRotationRelative *= (1-fSpeedModifier*0.05f); +/* old */ if (en_aDesiredRotationRelative.Length()<10) { +/* old */ en_aDesiredRotationRelative = ANGLE3D(0,0,0); +/* old */ } +/* old */ } +/* old */ +/* old */ // discard reference entity (will be recalculated) +/* old */ if (en_pbpoStandOn==NULL) { +/* old */ en_penReference = NULL; +/* old */ en_vReferencePlane = FLOAT3D(0.0f, 0.0f, 0.0f); +/* old */ en_iReferenceSurface = 0; +/* old */ } +/* old */ +/* old */ en_vIntendedTranslation = vTranslationAbsolute; +/* old */ en_mIntendedRotation = mRotationAbsolute; +/* old */ +/* old */ //-- estimate future movements for collision caching +/* old */ +/* old */ // make box of the entity for its current rotation +/* old */ FLOATaabbox3D box; +/* old */ en_pciCollisionInfo->MakeBoxAtPlacement(FLOAT3D(0,0,0), en_mRotation, box); +/* old */ // if it is a light source +/* old */ {CLightSource *pls = GetLightSource(); +/* old */ if (pls!=NULL && !(pls->ls_ulFlags&LSF_LENSFLAREONLY)) { +/* old */ // expand the box to be sure that it contains light range +/* old */ ASSERT(!(pls->ls_ulFlags&LSF_DIRECTIONAL)); +/* old */ box |= FLOATaabbox3D(FLOAT3D(0,0,0), pls->ls_rFallOff); +/* old */ }} +/* old */ // add a bit around it +/* old */ box.ExpandByFactor( phy_fCollisionCacheAround-1.0f); +/* old */ // make box go few ticks ahead of the entity +/* old */ box += en_plPlacement.pl_PositionVector; +/* old */ en_boxMovingEstimate = box; +/* old */ box += en_vIntendedTranslation*phy_fCollisionCacheAhead; +/* old */ en_boxMovingEstimate |= box; +/* old */ +/* old */ // clear applied movement to be updated during movement +/* old */ en_vAppliedTranslation = FLOAT3D(0.0f, 0.0f, 0.0f); +/* old */ en_mAppliedRotation.Diagonal(1.0f); +/* old */ _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_PREMOVING); +/* old */// STREAMDUMP ExportEntityPlacementAndSpeed( *(CMovableEntity *)this, "Pre moving (end of function)"); +/* old */ } + + /* Calculate physics for moving. */ + export void DoMoving(void) + { + if (en_pciCollisionInfo==NULL || (en_ulPhysicsFlags&EPF_FORCEADDED)) { + return; + } +// STREAMDUMP ExportEntityPlacementAndSpeed(*(CMovableEntity *)this, "Do moving (start of function)"); + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_DOMOVING); + _pfPhysicsProfile.IncrementTimerAveragingCounter(CPhysicsProfile::PTI_DOMOVING); + + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_DOMOVING); + + FLOAT fTickQuantum=_pTimer->TickQuantum; // used for normalizing from SI units to game ticks + + // if rotation and translation are synchronized + if (en_ulPhysicsFlags&EPF_RT_SYNCHRONIZED) { + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_DOMOVING_SYNC); + + // move both in translation and rotation + en_vMoveTranslation = en_vIntendedTranslation-en_vAppliedTranslation; + en_mMoveRotation = en_mIntendedRotation*!en_mAppliedRotation; + + InitTryToMove(); + CMovableEntity *penPusher = NULL; + if ((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_PUSH) { + penPusher = this; + } + BOOL bMoveSuccessfull = TryToMove(penPusher, TRUE, TRUE); + + // if rotation and translation are asynchronious + } else { + ASSERT((en_ulPhysicsFlags&EPF_ONBLOCK_MASK)!=EPF_ONBLOCK_PUSH); + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_DOMOVING_ASYNC); + + // if there is no reference + if (en_penReference == NULL) { + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_DOMOVING_ASYNC_SYNCTRY); + + // try to do simple move both in translation and rotation + en_vMoveTranslation = en_vIntendedTranslation-en_vAppliedTranslation; + en_mMoveRotation = en_mIntendedRotation*!en_mAppliedRotation; + InitTryToMove(); + _ctTryToMoveCheckCounter = 4; // no retries + BOOL bMoveSuccessfull = TryToMove(NULL, TRUE, TRUE); + // if it passes + if (bMoveSuccessfull) { + // finish + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_DOMOVING_ASYNC_SYNCPASS); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_DOMOVING); +// STREAMDUMP ExportEntityPlacementAndSpeed(*(CMovableEntity *)this, "Do moving (return: if it passes)"); + return; + } + } + + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_DOMOVING_ASYNC_TRANSLATE); + // translate + en_vMoveTranslation = en_vIntendedTranslation-en_vAppliedTranslation; + InitTryToMove(); + TryToMove(NULL, TRUE, FALSE); + + // rotate + en_mMoveRotation = en_mIntendedRotation*!en_mAppliedRotation; + if ( + en_mMoveRotation(1,1)!=1 || en_mMoveRotation(1,2)!=0 || en_mMoveRotation(1,3)!=0 || + en_mMoveRotation(2,1)!=0 || en_mMoveRotation(2,2)!=1 || en_mMoveRotation(2,3)!=0 || + en_mMoveRotation(3,1)!=0 || en_mMoveRotation(3,2)!=0 || en_mMoveRotation(3,3)!=1) { + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_DOMOVING_ASYNC_ROTATE); + InitTryToMove(); + TryToMove(NULL, FALSE, TRUE); + } + } + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_DOMOVING); +// STREAMDUMP ExportEntityPlacementAndSpeed(*(CMovableEntity *)this, "Do moving (end of function)"); + } + + // calculate consequences of moving/not moving in this tick + export void PostMoving(void) + { + if (en_pciCollisionInfo==NULL) { + // mark for removing from list of movers + en_ulFlags |= ENF_INRENDERING; + return; + } + + if (en_ulPhysicsFlags&EPF_FORCEADDED) { + en_ulPhysicsFlags&=~EPF_FORCEADDED; + return; + } + +// STREAMDUMP ExportEntityPlacementAndSpeed(*(CMovableEntity *)this, "Post moving (start of function)"); + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_POSTMOVING); + _pfPhysicsProfile.IncrementTimerAveragingCounter(CPhysicsProfile::PTI_POSTMOVING); + + // remember valid reference if valid + if (en_penReference!=NULL) { + en_penLastValidReference = en_penReference; + } + + // remember original translation + FLOAT3D vOldTranslation = en_vCurrentTranslationAbsolute; + FLOAT fTickQuantum=_pTimer->TickQuantum; // used for normalizing from SI units to game ticks + // calculate current velocity from movements applied in this tick + en_vCurrentTranslationAbsolute = en_vAppliedTranslation/fTickQuantum; + + // remember significant movements + if (Abs(en_vCurrentTranslationAbsolute%en_vGravityDir)>0.1f) { + en_tmLastSignificantVerticalMovement = _pTimer->CurrentTick(); + } + + ClearNextPosition(); + + // calculate speed change between needed and possible (in m/s) + FLOAT3D vSpeedDelta = en_vIntendedTranslation - en_vAppliedTranslation; + FLOAT fSpeedDelta = vSpeedDelta.Length()/fTickQuantum; + + // if it is large change and can be damaged by impact + if (fSpeedDelta>en_fCollisionSpeedLimit && + !(en_ulPhysicsFlags&EPF_NOIMPACTTHISTICK)) { + // inflict impact damage + FLOAT fDamage = ((fSpeedDelta-en_fCollisionSpeedLimit)/en_fCollisionSpeedLimit)*en_fCollisionDamageFactor; + InflictDirectDamage(this, MiscDamageInflictor(), DMT_IMPACT, fDamage, + en_plPlacement.pl_PositionVector, -vSpeedDelta.Normalize()); + } + en_ulPhysicsFlags&=~EPF_NOIMPACTTHISTICK; + + // remember old speed for Touch reactions + en_vIntendedTranslation = vOldTranslation; + + // if not moving anymore + if (en_vCurrentTranslationAbsolute.ManhattanNorm()<0.001f + &&(en_vDesiredTranslationRelative.ManhattanNorm()==0 || en_fAcceleration==0) + &&en_aDesiredRotationRelative.ManhattanNorm()==0) { + + // if there is a reference + if (en_penReference!=NULL) { + // it the reference is movable + if (en_penReference->en_ulPhysicsFlags&EPF_MOVABLE) { + CMovableEntity *penReference = (CMovableEntity *)(CEntity*)en_penReference; + // if the reference is not in the list of movers + if (!penReference->en_lnInMovers.IsLinked()) { + // mark for removing from list of movers + en_ulFlags |= ENF_INRENDERING; + } + // if the reference is not movable + } else { + // mark for removing from list of movers + en_ulFlags |= ENF_INRENDERING; + } + + // if there is no reference + } else { + // if no gravity and no forces can affect this entity + if ( + (!(en_ulPhysicsFlags&(EPF_TRANSLATEDBYGRAVITY|EPF_ORIENTEDBYGRAVITY)) + || en_fGravityA==0.0f)) { // !!!! test for forces also when implemented + // mark for removing from list of movers + en_ulFlags |= ENF_INRENDERING; + } + } + + // if should remove from movers list + if (en_ulFlags&ENF_INRENDERING) { + // clear last placement + en_plLastPlacement = en_plPlacement; + } + } + + // remember new position for particles + if (en_plpLastPositions!=NULL) { + en_plpLastPositions->AddPosition(en_vNextPosition); + } + + + // if should filter predictions + extern BOOL _bPredictionActive; + if (_bPredictionActive && (IsPredictable() || IsPredictor())) { + CMovableEntity *penTail = (CMovableEntity *)GetPredictedSafe(this); + TIME tmNow = _pTimer->CurrentTick(); + + if (penTail->en_tmLastPredictionHead<-1) { + penTail->en_vLastHead = en_plPlacement.pl_PositionVector; + penTail->en_vPredError = FLOAT3D(0,0,0); + penTail->en_vPredErrorLast = FLOAT3D(0,0,0); + } + + // if this is a predictor + if (IsPredictor()) { + // if a new prediction of old prediction head, or just started prediction + if (penTail->en_tmLastPredictionHead==tmNow || penTail->en_tmLastPredictionHead<0) { + // remember error + penTail->en_vPredErrorLast = penTail->en_vPredError; + penTail->en_vPredError += + en_plPlacement.pl_PositionVector-penTail->en_vLastHead; + // remember last head + penTail->en_vLastHead = en_plPlacement.pl_PositionVector; + // if this is really head of prediction chain + if (IsPredictionHead()) { + // remember the time + penTail->en_tmLastPredictionHead = tmNow; + } + + // if newer than last prediction head + } else if (tmNow>penTail->en_tmLastPredictionHead) { + // just remember head and time + penTail->en_vLastHead = en_plPlacement.pl_PositionVector; + penTail->en_tmLastPredictionHead = tmNow; + } + + // if prediction is of for this entity + } else if (!(en_ulFlags&ENF_WILLBEPREDICTED)) { + // if it was on before + if (penTail->en_tmLastPredictionHead>0) { + // remember error + penTail->en_vPredErrorLast = penTail->en_vPredError; + penTail->en_vPredError += + en_plPlacement.pl_PositionVector-penTail->en_vLastHead; + } + // remember this as head + penTail->en_vLastHead = en_plPlacement.pl_PositionVector; + penTail->en_tmLastPredictionHead = -1; + } + // if this is head of chain + if (IsPredictionHead()) { + // fade error + penTail->en_vPredErrorLast = penTail->en_vPredError; + penTail->en_vPredError *= cli_fPredictionFilter; +// FLOAT fErrLen = penTail->en_vPredError.Length(); +// if (fErrLen>0) { +// penTail->en_vPredError=penTail->en_vPredError/fErrLen*ClampDn(fErrLen-cli_fPredictionCorrection, 0.0f); +// } + } + } + + //CPrintF("\n%f", _pTimer->CurrentTick()); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_POSTMOVING); + +// STREAMDUMP ExportEntityPlacementAndSpeed(*(CMovableEntity *)this, "Post moving (end of function)"); + } + + // call this if you move without collision + export void CacheNearPolygons(void) + { + CClipMove cm(this); + cm.CacheNearPolygons(); + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // init + SLONG slUsedMemory = sizeof(CMovableEntity) - sizeof(CRationalEntity) + CRationalEntity::GetUsedMemory(); + // add some more + slUsedMemory += en_apbpoNearPolygons.sa_Count * sizeof(CBrushPolygon*); + return slUsedMemory; + } + + +procedures: + + + // must have at least one procedure per class + Dummy() {}; +}; diff --git a/Sources/Engine/Classes/MovableEntity.h b/Sources/Engine/Classes/MovableEntity.h new file mode 100644 index 0000000..b5ececf --- /dev/null +++ b/Sources/Engine/Classes/MovableEntity.h @@ -0,0 +1,176 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _Engine_Classes_MovableEntity_INCLUDED +#define _Engine_Classes_MovableEntity_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CMovableEntity_DLLClass; +class DECL_DLL CMovableEntity : public CRationalEntity { +public: + virtual void SetDefaultProperties(void); + FLOAT3D en_vDesiredTranslationRelative; + ANGLE3D en_aDesiredRotationRelative; + FLOAT3D en_vCurrentTranslationAbsolute; + ANGLE3D en_aCurrentRotationAbsolute; + CEntityPointer en_penReference; + FLOAT3D en_vReferencePlane; + INDEX en_iReferenceSurface; + CEntityPointer en_penLastValidReference; + FLOAT en_tmLastSignificantVerticalMovement; + FLOAT en_tmLastBreathed; + FLOAT en_tmMaxHoldBreath; + FLOAT en_fDensity; + FLOAT en_tmLastSwimDamage; + INDEX en_iUpContent; + INDEX en_iDnContent; + FLOAT en_fImmersionFactor; + FLOAT3D en_vGravityDir; + FLOAT en_fGravityA; + FLOAT en_fGravityV; + FLOAT3D en_vForceDir; + FLOAT en_fForceA; + FLOAT en_fForceV; + FLOAT en_tmJumped; + FLOAT en_tmMaxJumpControl; + FLOAT en_fJumpControlMultiplier; + FLOAT en_fAcceleration; + FLOAT en_fDeceleration; + FLOAT en_fStepUpHeight; + FLOAT en_fStepDnHeight; + FLOAT en_fBounceDampParallel; + FLOAT en_fBounceDampNormal; + FLOAT en_fCollisionSpeedLimit; + FLOAT en_fCollisionDamageFactor; + FLOATaabbox3D en_boxMovingEstimate; + FLOATaabbox3D en_boxNearCached; + FLOAT3D en_vIntendedTranslation; + FLOATmatrix3D en_mIntendedRotation; +CPlacement3D en_plLastPlacement; +CListNode en_lnInMovers; +CBrushPolygon * en_pbpoStandOn; +CStaticStackArray < CBrushPolygon * > en_apbpoNearPolygons; +FLOAT en_tmLastPredictionHead; +FLOAT3D en_vLastHead; +FLOAT3D en_vPredError; +FLOAT3D en_vPredErrorLast; +FLOAT3D en_vNextPosition; +FLOATmatrix3D en_mNextRotation; +FLOAT3D en_vMoveTranslation; +FLOATmatrix3D en_mMoveRotation; +FLOAT3D en_vAppliedTranslation; +FLOATmatrix3D en_mAppliedRotation; + +#line 319 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void ResetPredictionFilter(void); + CMovableEntity(void); + ~ CMovableEntity(void); + void OnInitialize(const CEntityEvent & eeInput); + void OnEnd(void); + void Copy(CEntity & enOther,ULONG ulFlags); + +#line 391 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void ClearTemporaryData(void); + void ChecksumForSync(ULONG & ulCRC,INDEX iExtensiveSyncCheck); + void DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck); + void Read_t(CTStream * istr); + void Write_t(CTStream * ostr); + CPlacement3D GetLerpedPlacement(void)const; + void AddToMovers(void); + void AddToMoversDuringMoving(void); + void SetDesiredRotation(const ANGLE3D & aRotation); + const ANGLE3D & GetDesiredRotation(void)const; + void SetDesiredTranslation(const FLOAT3D & vTranslation); + const FLOAT3D & GetDesiredTranslation(void)const; + void GiveImpulseTranslationRelative(const FLOAT3D & vImpulseSpeedRelative); + void GiveImpulseTranslationAbsolute(const FLOAT3D & vImpulseSpeed); + void LaunchAsPropelledProjectile(const FLOAT3D & vImpulseSpeedRelative, +#line 642 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penLauncher); + void LaunchAsFreeProjectile(const FLOAT3D & vImpulseSpeedRelative, +#line 650 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CMovableEntity * penLauncher); + void ForceStopTranslation(void); + void ForceStopRotation(void); + void ForceFullStop(void); + void FakeJump(const FLOAT3D & vOrgSpeed,const FLOAT3D & vDirection,FLOAT fStrength, +#line 680 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +FLOAT fParallelMultiplier,FLOAT fNormalMultiplier,FLOAT fMaxExitSpeed,TIME tmControl); + ANGLE GetRelativeHeading(const FLOAT3D & vDirection); + ANGLE GetRelativePitch(const FLOAT3D & vDirection); + void GetReferenceHeadingDirection(const FLOAT3D & vReference,ANGLE aH,FLOAT3D & vDirection); + void GetHeadingDirection(ANGLE aH,FLOAT3D & vDirection); + void GetPitchDirection(ANGLE aH,FLOAT3D & vDirection); + +#line 781 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +CEntity * MiscDamageInflictor(void); + +#line 798 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void UpdateOneSectorForce(CBrushSector & bsc,FLOAT fRatio); + +#line 847 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void TestFields(INDEX & iUpContent,INDEX & iDnContent,FLOAT & fImmersionFactor); + +#line 990 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void TestBreathing(CContentType & ctUp); + +#line 1026 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void TestContentDamage(CContentType & ctDn,FLOAT fImmersion); + +#line 1059 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void TestSurfaceDamage(CSurfaceType & stDn); + +#line 1085 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void SendTouchEvent(const CClipMove & cmMove); + +#line 1100 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void SendBlockEvent(CClipMove & cmMove); + +#line 1108 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL IsStandingOnPolygon(CBrushPolygon * pbpo); + +#line 1171 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL IsPolygonBelowPoint(CBrushPolygon * pbpo,const FLOAT3D & vPoint,FLOAT fMaxDist); + virtual BOOL AllowForGroundPolygon(CBrushPolygon * pbpo); + +#line 1261 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL IsSomeNearPolygonBelowPoint(const FLOAT3D & vPoint,FLOAT fMaxDist); + +#line 1268 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL IsSomeSectorPolygonBelowPoint(CBrushSector * pbsc,const FLOAT3D & vPoint,FLOAT fMaxDist); + +#line 1284 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL WouldFallInNextPosition(void); + +#line 1394 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void ClearNextPosition(void); + +#line 1400 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void SetPlacementFromNextPosition(void); + +#line 1427 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL TryToGoUpstairs(const FLOAT3D & vTranslationAbsolute,const CSurfaceType & stHit, +#line 1428 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL bHitStairsOrg); + +#line 1581 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +BOOL TryToMove(CMovableEntity * penPusher,BOOL bTranslate,BOOL bRotate); + void ClearMovingTemp(void); + void PreMoving(void); + +#line 2012 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void PreMovingNew(void); + +#line 2428 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +void PreMovingOld(void); + void DoMoving(void); + void PostMoving(void); + void CacheNearPolygons(void); + +#line 3091 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +SLONG GetUsedMemory(void); +#define STATE_CMovableEntity_Dummy 0x00010000 + BOOL +#line 3105 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +Dummy(const CEntityEvent &__eeInput); +}; +#endif // _Engine_Classes_MovableEntity_INCLUDED diff --git a/Sources/Engine/Classes/MovableEntity_tables.h b/Sources/Engine/Classes/MovableEntity_tables.h new file mode 100644 index 0000000..c99a74c --- /dev/null +++ b/Sources/Engine/Classes/MovableEntity_tables.h @@ -0,0 +1,70 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CMovableEntity + +CEntityProperty CMovableEntity_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000001<<8)+1, offsetof(CMovableEntity, en_vDesiredTranslationRelative), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x00000001<<8)+2, offsetof(CMovableEntity, en_aDesiredRotationRelative), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000001<<8)+3, offsetof(CMovableEntity, en_vCurrentTranslationAbsolute), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x00000001<<8)+4, offsetof(CMovableEntity, en_aCurrentRotationAbsolute), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000001<<8)+6, offsetof(CMovableEntity, en_penReference), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000001<<8)+7, offsetof(CMovableEntity, en_vReferencePlane), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000001<<8)+8, offsetof(CMovableEntity, en_iReferenceSurface), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000001<<8)+9, offsetof(CMovableEntity, en_penLastValidReference), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+14, offsetof(CMovableEntity, en_tmLastSignificantVerticalMovement), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+10, offsetof(CMovableEntity, en_tmLastBreathed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+11, offsetof(CMovableEntity, en_tmMaxHoldBreath), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+12, offsetof(CMovableEntity, en_fDensity), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+13, offsetof(CMovableEntity, en_tmLastSwimDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000001<<8)+20, offsetof(CMovableEntity, en_iUpContent), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000001<<8)+21, offsetof(CMovableEntity, en_iDnContent), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+22, offsetof(CMovableEntity, en_fImmersionFactor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000001<<8)+25, offsetof(CMovableEntity, en_vGravityDir), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+26, offsetof(CMovableEntity, en_fGravityA), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+27, offsetof(CMovableEntity, en_fGravityV), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000001<<8)+66, offsetof(CMovableEntity, en_vForceDir), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+67, offsetof(CMovableEntity, en_fForceA), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+68, offsetof(CMovableEntity, en_fForceV), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+30, offsetof(CMovableEntity, en_tmJumped), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+31, offsetof(CMovableEntity, en_tmMaxJumpControl), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+32, offsetof(CMovableEntity, en_fJumpControlMultiplier), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+35, offsetof(CMovableEntity, en_fAcceleration), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+36, offsetof(CMovableEntity, en_fDeceleration), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+37, offsetof(CMovableEntity, en_fStepUpHeight), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+42, offsetof(CMovableEntity, en_fStepDnHeight), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+38, offsetof(CMovableEntity, en_fBounceDampParallel), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+39, offsetof(CMovableEntity, en_fBounceDampNormal), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+40, offsetof(CMovableEntity, en_fCollisionSpeedLimit), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000001<<8)+41, offsetof(CMovableEntity, en_fCollisionDamageFactor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATAABBOX3D, NULL, (0x00000001<<8)+51, offsetof(CMovableEntity, en_boxMovingEstimate), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATAABBOX3D, NULL, (0x00000001<<8)+52, offsetof(CMovableEntity, en_boxNearCached), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000001<<8)+64, offsetof(CMovableEntity, en_vIntendedTranslation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATMATRIX3D, NULL, (0x00000001<<8)+65, offsetof(CMovableEntity, en_mIntendedRotation), "", 0, 0, 0), +}; +#define CMovableEntity_propertiesct ARRAYCOUNT(CMovableEntity_properties) + +CEntityComponent CMovableEntity_components[] = { + CEntityComponent() +}; +#define CMovableEntity_componentsct 0 + + +CEventHandlerEntry CMovableEntity_handlers[] = { + {0x00010000, -1, CEntity::pEventHandler(&CMovableEntity:: +#line 3105 "D:/SE1_GPL/Sources/Engine/Classes/MovableEntity.es" +Dummy),DEBUGSTRING("CMovableEntity::Dummy")}, +}; +#define CMovableEntity_handlersct ARRAYCOUNT(CMovableEntity_handlers) + +CEntity *CMovableEntity_New(void) { return new CMovableEntity; }; +void CMovableEntity_OnInitClass(void) {}; +void CMovableEntity_OnEndClass(void) {}; +void CMovableEntity_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMovableEntity_OnWorldEnd(CWorld *pwo) {}; +void CMovableEntity_OnWorldInit(CWorld *pwo) {}; +void CMovableEntity_OnWorldTick(CWorld *pwo) {}; +void CMovableEntity_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMovableEntity, CRationalEntity, "MovableEntity", "", 0x00000001); +DECLARE_CTFILENAME(_fnmCMovableEntity_tbn, ""); diff --git a/Sources/Engine/Classes/MovableModelEntity.cpp b/Sources/Engine/Classes/MovableModelEntity.cpp new file mode 100644 index 0000000..c288da9 --- /dev/null +++ b/Sources/Engine/Classes/MovableModelEntity.cpp @@ -0,0 +1,218 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 8 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" + +#include "StdH.h" +#include +#include +#include +#include +#include + +#include +#include +void CMovableModelEntity::SetDefaultProperties(void) { + en_iCollisionBox = 0; + en_iWantedCollisionBox = 0; + CMovableEntity::SetDefaultProperties(); +} + void CMovableModelEntity::ChecksumForSync(ULONG & ulCRC,INDEX iExtensiveSyncCheck) +#line 32 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 33 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +CMovableEntity :: ChecksumForSync (ulCRC , iExtensiveSyncCheck ); +#line 34 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +if(iExtensiveSyncCheck > 0){ +#line 35 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +CRC_AddLONG (ulCRC , en_iCollisionBox ); +#line 36 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +CRC_AddLONG (ulCRC , en_iWantedCollisionBox ); +#line 37 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} +#line 38 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + void CMovableModelEntity::DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck) +#line 41 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 42 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +CMovableEntity :: DumpSync_t (strm , iExtensiveSyncCheck ); +#line 43 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +if(iExtensiveSyncCheck > 0){ +#line 44 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +strm . FPrintF_t ("collision box: %d(%d)\n" , en_iCollisionBox , en_iWantedCollisionBox ); +#line 45 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} +#line 46 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + void CMovableModelEntity::PreMoving(void) +#line 50 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 52 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +if(en_iCollisionBox != en_iWantedCollisionBox ){ +#line 54 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +ChangeCollisionBoxIndexNow (en_iWantedCollisionBox ); +#line 55 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} +#line 57 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +CMovableEntity :: PreMoving (); +#line 58 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + void CMovableModelEntity::DoMoving(void) +#line 60 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 61 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +CMovableEntity :: DoMoving (); +#line 62 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + INDEX CMovableModelEntity::GetCollisionBoxIndex(void) +#line 66 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 67 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +return en_iCollisionBox ; +#line 68 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + BOOL CMovableModelEntity::CheckForCollisionNow(INDEX iNewCollisionBox,CEntity * * ppenObstacle) +#line 72 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 74 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +extern BOOL CanEntityChangeCollisionBox (CEntity * pen , INDEX iNewCollisionBox , CEntity * * ppenObstacle ); +#line 75 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +return ! CanEntityChangeCollisionBox (this , en_iCollisionBox , ppenObstacle ); +#line 76 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + BOOL CMovableModelEntity::ChangeCollisionBoxIndexNow(INDEX iNewCollisionBox,CEntity * * ppenObstacle) +#line 80 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 82 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +if(iNewCollisionBox == en_iCollisionBox ){ +#line 84 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +return TRUE ; +#line 85 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} +#line 89 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +extern BOOL CanEntityChangeCollisionBox (CEntity * pen , INDEX iNewCollisionBox , CEntity * * ppenObstacle ); +#line 90 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +BOOL bCanChange = CanEntityChangeCollisionBox (this , iNewCollisionBox , ppenObstacle ); +#line 93 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +if(! bCanChange ){ +#line 96 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +return FALSE ; +#line 97 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} +#line 100 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +if(en_RenderType == CEntity :: RT_SKAMODEL || en_RenderType == CEntity :: RT_SKAEDITORMODEL ){ +#line 101 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +if(GetModelInstance () != NULL ){ +#line 103 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +GetModelInstance () -> mi_iCurentBBox = iNewCollisionBox ; +#line 104 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} +#line 105 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} +#line 107 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +en_iCollisionBox = iNewCollisionBox ; +#line 108 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +en_iWantedCollisionBox = iNewCollisionBox ; +#line 111 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +ModelChangeNotify (); +#line 114 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +return TRUE ; +#line 115 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + BOOL CMovableModelEntity::ChangeCollisionBoxIndexNow(INDEX iNewCollisionBox) +#line 119 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 120 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +CEntity * penDummy ; +#line 121 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +return ChangeCollisionBoxIndexNow (iNewCollisionBox , & penDummy ); +#line 122 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + void CMovableModelEntity::ForceCollisionBoxIndexChange(INDEX iNewCollisionBox) +#line 126 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 128 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +if(en_RenderType == CEntity :: RT_SKAMODEL || en_RenderType == CEntity :: RT_SKAEDITORMODEL ){ +#line 129 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +if(GetModelInstance () != NULL ){ +#line 131 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +GetModelInstance () -> mi_iCurentBBox = iNewCollisionBox ; +#line 132 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} +#line 133 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} +#line 135 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +en_iCollisionBox = iNewCollisionBox ; +#line 136 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +en_iWantedCollisionBox = iNewCollisionBox ; +#line 139 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +ModelChangeNotify (); +#line 140 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + void CMovableModelEntity::ChangeCollisionBoxIndexWhenPossible(INDEX iNewCollisionBox) +#line 144 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 145 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +en_iWantedCollisionBox = iNewCollisionBox ; +#line 146 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + void CMovableModelEntity::Read_t(CTStream * istr) +#line 156 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 157 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +CMovableEntity :: Read_t (istr ); +#line 158 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + void CMovableModelEntity::Write_t(CTStream * ostr) +#line 161 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 162 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +CMovableEntity :: Write_t (ostr ); +#line 163 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} + +#line 166 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +SLONG CMovableModelEntity::GetUsedMemory(void) +#line 167 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +{ +#line 168 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +return (sizeof (CMovableModelEntity ) - sizeof (CMovableEntity ) + CMovableEntity :: GetUsedMemory ()); +#line 169 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +} +BOOL CMovableModelEntity:: +#line 176 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +Dummy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMovableModelEntity_Dummy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMovableModelEntity::Dummy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; ASSERT(FALSE); return TRUE;};BOOL CMovableModelEntity:: +#line 179 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +WaitUntilScheduledAnimStarts(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMovableModelEntity::WaitUntilScheduledAnimStarts expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 181 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +ASSERT (en_RenderType == CEntity :: RT_MODEL || en_RenderType == CEntity :: RT_EDITORMODEL ); +#line 182 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +FLOAT fToWait = GetModelObject () -> ao_tmAnimStart - _pTimer -> CurrentTick (); +#line 183 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +if(!(fToWait > 0)){ Jump(STATE_CURRENT,0x00020004, FALSE, EInternal());return TRUE;} +#line 185 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +SetTimerAfter(fToWait + _pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x00020002, FALSE, EBegin());return TRUE;}BOOL CMovableModelEntity::H0x00020002_WaitUntilScheduledAnimStarts_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00020002 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00020003, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CMovableModelEntity::H0x00020003_WaitUntilScheduledAnimStarts_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00020003 +;Jump(STATE_CURRENT,0x00020004, FALSE, EInternal());return TRUE;}BOOL CMovableModelEntity::H0x00020004_WaitUntilScheduledAnimStarts_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00020004 + +#line 187 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +Return(STATE_CURRENT,EReturn ()); +#line 187 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/Engine/Classes/MovableModelEntity.es b/Sources/Engine/Classes/MovableModelEntity.es new file mode 100644 index 0000000..584287e --- /dev/null +++ b/Sources/Engine/Classes/MovableModelEntity.es @@ -0,0 +1,189 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +/* + * Model entity that can move. + */ + +2 +%{ +#include "StdH.h" +#include +#include +#include +#include +#include +%} + +class export CMovableModelEntity : CMovableEntity { +name "MovableModelEntity"; +thumbnail ""; +properties: + 1 INDEX en_iCollisionBox = 0, // current collision box for model entities + 2 INDEX en_iWantedCollisionBox = 0, // collision box to change to + + +components: + + +functions: + + // create a checksum value for sync-check + export void ChecksumForSync(ULONG &ulCRC, INDEX iExtensiveSyncCheck) + { + CMovableEntity::ChecksumForSync(ulCRC, iExtensiveSyncCheck); + if (iExtensiveSyncCheck>0) { + CRC_AddLONG(ulCRC, en_iCollisionBox); + CRC_AddLONG(ulCRC, en_iWantedCollisionBox); + } + } + // dump sync data to text file + export void DumpSync_t(CTStream &strm, INDEX iExtensiveSyncCheck) // throw char * + { + CMovableEntity::DumpSync_t(strm, iExtensiveSyncCheck); + if (iExtensiveSyncCheck>0) { + strm.FPrintF_t("collision box: %d(%d)\n", en_iCollisionBox, en_iWantedCollisionBox); + } + } + + // prepare parameters for moving in this tick + export void PreMoving(void) // override from CMovableEntity + { + // if collision box should be changed + if (en_iCollisionBox != en_iWantedCollisionBox) { + // change if possible + ChangeCollisionBoxIndexNow(en_iWantedCollisionBox); + } + + CMovableEntity::PreMoving(); + } + export void DoMoving(void) // override from CMovableEntity + { + CMovableEntity::DoMoving(); + } + + /* Get current collision box index for this entity. */ + export INDEX GetCollisionBoxIndex(void) + { + return en_iCollisionBox; + } + + /* Check if collision box touches any brush near. */ + export BOOL CheckForCollisionNow(INDEX iNewCollisionBox, CEntity **ppenObstacle) + { + // test if an entity can change to the new collision box without intersecting anything + extern BOOL CanEntityChangeCollisionBox(CEntity *pen, INDEX iNewCollisionBox, CEntity **ppenObstacle); + return !CanEntityChangeCollisionBox(this, en_iCollisionBox, ppenObstacle); + } + + /* Change current collision box. */ + export BOOL ChangeCollisionBoxIndexNow(INDEX iNewCollisionBox, CEntity **ppenObstacle) + { + // if same as current + if (iNewCollisionBox == en_iCollisionBox) { + // do nothing + return TRUE; + } + + //CPrintF("changing box %d-%d...", en_iCollisionBox, iNewCollisionBox); + // test if an entity can change to the new collision box without intersecting anything + extern BOOL CanEntityChangeCollisionBox(CEntity *pen, INDEX iNewCollisionBox, CEntity **ppenObstacle); + BOOL bCanChange = CanEntityChangeCollisionBox(this, iNewCollisionBox, ppenObstacle); + + // if it cannot + if (!bCanChange) { + // fail + //CPrintF("failed\n"); + return FALSE; + } + + // if this is ska model + if(en_RenderType == CEntity::RT_SKAMODEL || en_RenderType == CEntity::RT_SKAEDITORMODEL) { + if(GetModelInstance()!=NULL) { + // change his colision box index + GetModelInstance()->mi_iCurentBBox = iNewCollisionBox; + } + } + // remember new collision box + en_iCollisionBox = iNewCollisionBox; + en_iWantedCollisionBox = iNewCollisionBox; + + // recalculate collision info + ModelChangeNotify(); + + //CPrintF("succeeded\n"); + return TRUE; + } + + /* Change current collision box. */ + export BOOL ChangeCollisionBoxIndexNow(INDEX iNewCollisionBox) + { + CEntity *penDummy; + return ChangeCollisionBoxIndexNow(iNewCollisionBox, &penDummy); + } + + /* Force immediate changing of collision box. */ + export void ForceCollisionBoxIndexChange(INDEX iNewCollisionBox) + { + // if this is ska model + if(en_RenderType == CEntity::RT_SKAMODEL || en_RenderType == CEntity::RT_SKAEDITORMODEL) { + if(GetModelInstance()!=NULL) { + // change his colision box index + GetModelInstance()->mi_iCurentBBox = iNewCollisionBox; + } + } + // remember new collision box + en_iCollisionBox = iNewCollisionBox; + en_iWantedCollisionBox = iNewCollisionBox; + + // recalculate collision info + ModelChangeNotify(); + } + + /* Change current collision box next time when possible. */ + export void ChangeCollisionBoxIndexWhenPossible(INDEX iNewCollisionBox) + { + en_iWantedCollisionBox = iNewCollisionBox; + } + + /* Copy entity from another entity of same class. */ + /*CMovableModelEntity &operator=(CMovableModelEntity &enOther) + { + CMovableEntity::operator=(enOther); + return *this; + } */ + /* Read from stream. */ + export void Read_t( CTStream *istr) // throw char * + { + CMovableEntity::Read_t(istr); + } + /* Write to stream. */ + export void Write_t( CTStream *ostr) // throw char * + { + CMovableEntity::Write_t(ostr); + } + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + return( sizeof(CMovableModelEntity) - sizeof(CMovableEntity) + CMovableEntity::GetUsedMemory()); + } + + +procedures: + + + // must have at least one procedure per class + Dummy() {}; + + // wait here until scheduled animation starts + WaitUntilScheduledAnimStarts(EVoid) + { + ASSERT(en_RenderType == CEntity::RT_MODEL || en_RenderType == CEntity::RT_EDITORMODEL); + FLOAT fToWait = GetModelObject()->ao_tmAnimStart-_pTimer->CurrentTick(); + if( fToWait>0) + { + autowait(fToWait+_pTimer->TickQuantum); + } + return EReturn(); + } +}; diff --git a/Sources/Engine/Classes/MovableModelEntity.h b/Sources/Engine/Classes/MovableModelEntity.h new file mode 100644 index 0000000..61bfacb --- /dev/null +++ b/Sources/Engine/Classes/MovableModelEntity.h @@ -0,0 +1,40 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _Engine_Classes_MovableModelEntity_INCLUDED +#define _Engine_Classes_MovableModelEntity_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CMovableModelEntity_DLLClass; +class DECL_DLL CMovableModelEntity : public CMovableEntity { +public: + virtual void SetDefaultProperties(void); + INDEX en_iCollisionBox; + INDEX en_iWantedCollisionBox; + void ChecksumForSync(ULONG & ulCRC,INDEX iExtensiveSyncCheck); + void DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck); + void PreMoving(void); + void DoMoving(void); + INDEX GetCollisionBoxIndex(void); + BOOL CheckForCollisionNow(INDEX iNewCollisionBox,CEntity * * ppenObstacle); + BOOL ChangeCollisionBoxIndexNow(INDEX iNewCollisionBox,CEntity * * ppenObstacle); + BOOL ChangeCollisionBoxIndexNow(INDEX iNewCollisionBox); + void ForceCollisionBoxIndexChange(INDEX iNewCollisionBox); + void ChangeCollisionBoxIndexWhenPossible(INDEX iNewCollisionBox); + void Read_t(CTStream * istr); + void Write_t(CTStream * ostr); + +#line 166 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +SLONG GetUsedMemory(void); +#define STATE_CMovableModelEntity_Dummy 0x00020000 + BOOL +#line 176 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +Dummy(const CEntityEvent &__eeInput); +#define STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts 0x00020001 + BOOL +#line 179 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +WaitUntilScheduledAnimStarts(const CEntityEvent &__eeInput); + BOOL H0x00020002_WaitUntilScheduledAnimStarts_01(const CEntityEvent &__eeInput); + BOOL H0x00020003_WaitUntilScheduledAnimStarts_02(const CEntityEvent &__eeInput); + BOOL H0x00020004_WaitUntilScheduledAnimStarts_03(const CEntityEvent &__eeInput); +}; +#endif // _Engine_Classes_MovableModelEntity_INCLUDED diff --git a/Sources/Engine/Classes/MovableModelEntity_tables.h b/Sources/Engine/Classes/MovableModelEntity_tables.h new file mode 100644 index 0000000..2211e6c --- /dev/null +++ b/Sources/Engine/Classes/MovableModelEntity_tables.h @@ -0,0 +1,41 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CMovableModelEntity + +CEntityProperty CMovableModelEntity_properties[] = { + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000002<<8)+1, offsetof(CMovableModelEntity, en_iCollisionBox), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000002<<8)+2, offsetof(CMovableModelEntity, en_iWantedCollisionBox), "", 0, 0, 0), +}; +#define CMovableModelEntity_propertiesct ARRAYCOUNT(CMovableModelEntity_properties) + +CEntityComponent CMovableModelEntity_components[] = { + CEntityComponent() +}; +#define CMovableModelEntity_componentsct 0 + + +CEventHandlerEntry CMovableModelEntity_handlers[] = { + {0x00020000, -1, CEntity::pEventHandler(&CMovableModelEntity:: +#line 176 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +Dummy),DEBUGSTRING("CMovableModelEntity::Dummy")}, + {0x00020001, -1, CEntity::pEventHandler(&CMovableModelEntity:: +#line 179 "D:/SE1_GPL/Sources/Engine/Classes/MovableModelEntity.es" +WaitUntilScheduledAnimStarts),DEBUGSTRING("CMovableModelEntity::WaitUntilScheduledAnimStarts")}, + {0x00020002, -1, CEntity::pEventHandler(&CMovableModelEntity::H0x00020002_WaitUntilScheduledAnimStarts_01), DEBUGSTRING("CMovableModelEntity::H0x00020002_WaitUntilScheduledAnimStarts_01")}, + {0x00020003, -1, CEntity::pEventHandler(&CMovableModelEntity::H0x00020003_WaitUntilScheduledAnimStarts_02), DEBUGSTRING("CMovableModelEntity::H0x00020003_WaitUntilScheduledAnimStarts_02")}, + {0x00020004, -1, CEntity::pEventHandler(&CMovableModelEntity::H0x00020004_WaitUntilScheduledAnimStarts_03), DEBUGSTRING("CMovableModelEntity::H0x00020004_WaitUntilScheduledAnimStarts_03")}, +}; +#define CMovableModelEntity_handlersct ARRAYCOUNT(CMovableModelEntity_handlers) + +CEntity *CMovableModelEntity_New(void) { return new CMovableModelEntity; }; +void CMovableModelEntity_OnInitClass(void) {}; +void CMovableModelEntity_OnEndClass(void) {}; +void CMovableModelEntity_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMovableModelEntity_OnWorldEnd(CWorld *pwo) {}; +void CMovableModelEntity_OnWorldInit(CWorld *pwo) {}; +void CMovableModelEntity_OnWorldTick(CWorld *pwo) {}; +void CMovableModelEntity_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMovableModelEntity, CMovableEntity, "MovableModelEntity", "", 0x00000002); +DECLARE_CTFILENAME(_fnmCMovableModelEntity_tbn, ""); diff --git a/Sources/Engine/Classes/PlayerEntity.cpp b/Sources/Engine/Classes/PlayerEntity.cpp new file mode 100644 index 0000000..cd719b7 --- /dev/null +++ b/Sources/Engine/Classes/PlayerEntity.cpp @@ -0,0 +1,150 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 7 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" + +#include "StdH.h" +#include +#include +#include + +#include +#include +void CPlayerEntity::SetDefaultProperties(void) { + en_tmPing = 0.0f; + CMovableModelEntity::SetDefaultProperties(); +} + CTString CPlayerEntity::GetPlayerName(void) +#line 29 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +{ +#line 30 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +return en_pcCharacter . GetNameForPrinting (); +#line 31 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} + const CTString & CPlayerEntity::GetName(void)const +#line 33 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +{ +#line 34 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +return en_pcCharacter . GetName (); +#line 35 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} + INDEX CPlayerEntity::GetMyPlayerIndex(void) +#line 38 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +{ +#line 39 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +CEntity * penMe = this ; +#line 40 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +if(IsPredictor ()){ +#line 41 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +penMe = GetPredicted (); +#line 42 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} +#line 43 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +for(INDEX iPlayer = 0;iPlayer < GetMaxPlayers ();iPlayer ++){ +#line 45 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +if(GetPlayerEntity (iPlayer ) == penMe ){ +#line 46 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +return iPlayer ; +#line 47 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} +#line 48 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} +#line 50 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +return 15; +#line 51 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} + void CPlayerEntity::DoMoving(void) +#line 55 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +{ +#line 56 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +CMovableModelEntity :: DoMoving (); +#line 57 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} + void CPlayerEntity::Copy(CEntity & enOther,ULONG ulFlags) +#line 61 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +{ +#line 62 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +CMovableModelEntity :: Copy (enOther , ulFlags ); +#line 64 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +CPlayerEntity * ppenOther = (CPlayerEntity *) (& enOther ); +#line 65 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +en_pcCharacter = ppenOther -> en_pcCharacter ; +#line 66 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +en_plViewpoint = ppenOther -> en_plViewpoint ; +#line 67 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +en_plLastViewpoint = ppenOther -> en_plLastViewpoint ; +#line 68 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} + void CPlayerEntity::Read_t(CTStream * istr) +#line 80 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +{ +#line 81 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +CMovableModelEntity :: Read_t (istr ); +#line 82 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +(* istr ) >> en_pcCharacter >> en_plViewpoint ; +#line 83 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +en_plLastViewpoint = en_plViewpoint ; +#line 84 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} + void CPlayerEntity::Write_t(CTStream * ostr) +#line 87 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +{ +#line 88 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +CMovableModelEntity :: Write_t (ostr ); +#line 89 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +(* ostr ) << en_pcCharacter << en_plViewpoint ; +#line 90 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} + void CPlayerEntity::ApplyAction(const CPlayerAction & pa,FLOAT tmLatency) {} + void CPlayerEntity::Disconnect(void) {} + void CPlayerEntity::CharacterChanged(const CPlayerCharacter & pcNew) {en_pcCharacter = pcNew ;} + void CPlayerEntity::GetGameAgentPlayerInfo(INDEX iPlayer,CTString & strOut) {} + void CPlayerEntity::ChecksumForSync(ULONG & ulCRC,INDEX iExtensiveSyncCheck) +#line 104 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +{ +#line 105 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +CMovableModelEntity :: ChecksumForSync (ulCRC , iExtensiveSyncCheck ); +#line 106 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +CRC_AddBlock (ulCRC , en_pcCharacter . pc_aubGUID , sizeof (en_pcCharacter . pc_aubGUID )); +#line 107 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +CRC_AddBlock (ulCRC , en_pcCharacter . pc_aubAppearance , sizeof (en_pcCharacter . pc_aubAppearance )); +#line 108 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} + void CPlayerEntity::DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck) +#line 111 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +{ +#line 112 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +CMovableModelEntity :: DumpSync_t (strm , iExtensiveSyncCheck ); +#line 113 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +strm . FPrintF_t ("player: %s\n" , +#line 114 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +en_pcCharacter . GetName ()); +#line 115 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +strm . FPrintF_t ("GUID: "); +#line 116 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +{for(INDEX i = 0;i < sizeof (en_pcCharacter . pc_aubGUID );i ++){ +#line 117 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +strm . FPrintF_t ("%02X" , en_pcCharacter . pc_aubGUID [ i ]); +#line 118 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +}} +#line 119 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +strm . FPrintF_t ("\n"); +#line 120 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +strm . FPrintF_t ("appearance: "); +#line 121 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +{for(INDEX i = 0;i < MAX_PLAYERAPPEARANCE ;i ++){ +#line 122 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +strm . FPrintF_t ("%02X" , en_pcCharacter . pc_aubAppearance [ i ]); +#line 123 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +}} +#line 124 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +strm . FPrintF_t ("\n"); +#line 125 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +} +BOOL CPlayerEntity:: +#line 128 "D:/SE1_GPL/Sources/Engine/Classes/PlayerEntity.es" +Dummy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerEntity_Dummy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerEntity::Dummy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/Engine/Classes/PlayerEntity.es b/Sources/Engine/Classes/PlayerEntity.es new file mode 100644 index 0000000..49ed97a --- /dev/null +++ b/Sources/Engine/Classes/PlayerEntity.es @@ -0,0 +1,129 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +/* + * Player entity. + */ +4 +%{ +#include "StdH.h" +#include +#include +#include +%} + +class export CPlayerEntity : CMovableModelEntity { +name "PlayerEntity"; +thumbnail ""; +features "AbstractBaseClass"; +properties: + 1 FLOAT en_tmPing = 0.0f, // ping value in seconds (determined by derived class and distributed by the engine) +{ + CPlayerCharacter en_pcCharacter; // character of the player + CPlacement3D en_plViewpoint; // placement of view point relative to the entity + CPlacement3D en_plLastViewpoint; // last view point (used for lerping) +} +components: +functions: + /* Get name of this player. */ + export CTString GetPlayerName(void) + { + return en_pcCharacter.GetNameForPrinting(); + } + export const CTString &GetName(void) const + { + return en_pcCharacter.GetName(); + } + /* Get index of this player in the game. */ + export INDEX GetMyPlayerIndex(void) + { + CEntity *penMe = this; + if (IsPredictor()) { + penMe = GetPredicted(); + } + for (INDEX iPlayer=0; iPlayeren_pcCharacter; + en_plViewpoint = ppenOther->en_plViewpoint; + en_plLastViewpoint = ppenOther->en_plLastViewpoint; + } + + /* Copy entity from another entity of same class. */ + /*CPlayerEntity &operator=(CPlayerEntity &enOther) + { + CMovableModelEntity::operator=(enOther); + en_pcCharacter = enOther.en_pcCharacter; + en_plViewpoint = enOther.en_plViewpoint; + return *this; + }*/ + /* Read from stream. */ + export void Read_t( CTStream *istr) // throw char * + { + CMovableModelEntity::Read_t(istr); + (*istr)>>en_pcCharacter>>en_plViewpoint; + en_plLastViewpoint = en_plViewpoint; + } + /* Write to stream. */ + export void Write_t( CTStream *ostr) // throw char * + { + CMovableModelEntity::Write_t(ostr); + (*ostr)< +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// this version string can be referenced from outside the engine +ENGINE_API CTString _strEngineBuild = ""; +ENGINE_API ULONG _ulEngineBuildMajor = _SE_BUILD_MAJOR; +ENGINE_API ULONG _ulEngineBuildMinor = _SE_BUILD_MINOR; + +ENGINE_API BOOL _bDedicatedServer = FALSE; +ENGINE_API BOOL _bWorldEditorApp = FALSE; +ENGINE_API CTString _strLogFile = ""; + +// global handle for application window +extern HWND _hwndMain = NULL; +extern BOOL _bFullScreen = FALSE; + +// critical section for access to zlib functions +CTCriticalSection zip_csLock; + +// to keep system gamma table +static UWORD auwSystemGamma[256*3]; + + +// OS info +static CTString sys_strOS = ""; +static INDEX sys_iOSMajor = 0; +static INDEX sys_iOSMinor = 0; +static INDEX sys_iOSBuild = 0; +static CTString sys_strOSMisc = ""; + +// CPU info +static CTString sys_strCPUVendor = ""; +static INDEX sys_iCPUType = 0; +static INDEX sys_iCPUFamily = 0; +static INDEX sys_iCPUModel = 0; +static INDEX sys_iCPUStepping = 0; +static BOOL sys_bCPUHasMMX = 0; +static BOOL sys_bCPUHasCMOV = 0; +static INDEX sys_iCPUMHz = 0; + INDEX sys_iCPUMisc = 0; + +// RAM info +static INDEX sys_iRAMPhys = 0; +static INDEX sys_iRAMSwap = 0; + +// HDD info +static INDEX sys_iHDDSize = 0; +static INDEX sys_iHDDFree = 0; +static INDEX sys_iHDDMisc = 0; + +// MOD info +static CTString sys_strModName = ""; +static CTString sys_strModExt = ""; + +// enables paranoia checks for allocation array +extern BOOL _bAllocationArrayParanoiaCheck = FALSE; + +BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + break; + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + default: + ASSERT(FALSE); + } + return TRUE; +} + +static void DetectCPU(void) +{ + char strVendor[12+1]; + strVendor[12] = 0; + ULONG ulTFMS; + ULONG ulFeatures; + + // test MMX presence and update flag + __asm { + mov eax,0 ;// request for basic id + cpuid + mov dword ptr [strVendor+0], ebx + mov dword ptr [strVendor+4], edx + mov dword ptr [strVendor+8], ecx + mov eax,1 ;// request for TFMS feature flags + cpuid + mov dword ptr [ulTFMS], eax ;// remember type, family, model and stepping + mov dword ptr [ulFeatures], edx + } + + INDEX iType = (ulTFMS>>12)&0x3; + INDEX iFamily = (ulTFMS>> 8)&0xF; + INDEX iModel = (ulTFMS>> 4)&0xF; + INDEX iStepping = (ulTFMS>> 0)&0xF; + + + CPrintF(TRANS(" Vendor: %s\n"), strVendor); + CPrintF(TRANS(" Type: %d, Family: %d, Model: %d, Stepping: %d\n"), + iType, iFamily, iModel, iStepping); + + BOOL bMMX = ulFeatures & (1<<23); + BOOL bCMOV = ulFeatures & (1<<15); + + CTString strYes = TRANS("Yes"); + CTString strNo = TRANS("No"); + + CPrintF(TRANS(" MMX : %s\n"), bMMX ?strYes:strNo); + CPrintF(TRANS(" CMOV: %s\n"), bCMOV?strYes:strNo); + CPrintF(TRANS(" Clock: %.0fMHz\n"), _pTimer->tm_llCPUSpeedHZ/1E6); + + sys_strCPUVendor = strVendor; + sys_iCPUType = iType; + sys_iCPUFamily = iFamily; + sys_iCPUModel = iModel; + sys_iCPUStepping = iStepping; + sys_bCPUHasMMX = bMMX!=0; + sys_bCPUHasCMOV = bCMOV!=0; + sys_iCPUMHz = INDEX(_pTimer->tm_llCPUSpeedHZ/1E6); + + if( !bMMX) FatalError( TRANS("MMX support required but not present!")); +} + +static void DetectCPUWrapper(void) +{ + __try { + DetectCPU(); + } __except(EXCEPTION_EXECUTE_HANDLER) { + CPrintF( TRANS("Cannot detect CPU: exception raised.\n")); + } +} + +// reverses string +void StrRev( char *str) { + char ctmp; + char *pch0 = str; + char *pch1 = str+strlen(str)-1; + while( pch1>pch0) { + ctmp = *pch0; + *pch0 = *pch1; + *pch1 = ctmp; + pch0++; + pch1--; + } +} + +static char strExePath[MAX_PATH] = ""; +static char strDirPath[MAX_PATH] = ""; + +static void AnalyzeApplicationPath(void) +{ + strcpy(strDirPath, "D:\\"); + strcpy(strExePath, "D:\\TestExe.xbe"); + char strTmpPath[MAX_PATH] = ""; + // get full path to the exe + GetModuleFileNameA( NULL, strExePath, sizeof(strExePath)-1); + // copy that to the path + strncpy(strTmpPath, strExePath, sizeof(strTmpPath)-1); + strDirPath[sizeof(strTmpPath)-1] = 0; + // remove name from application path + StrRev(strTmpPath); + // find last backslash + char *pstr = strchr( strTmpPath, '\\'); + if( pstr==NULL) { + // not found - path is just "\" + strcpy( strTmpPath, "\\"); + pstr = strTmpPath; + } + // remove 'debug' from app path if needed + if( strnicmp( pstr, "\\gubed", 6)==0) pstr += 6; + if( pstr[0] = '\\') pstr++; + char *pstrFin = strchr( pstr, '\\'); + if( pstrFin==NULL) { + strcpy( pstr, "\\"); + pstrFin = pstr; + } + // copy that to the path + StrRev(pstrFin); + strncpy( strDirPath, pstrFin, sizeof(strDirPath)-1); + strDirPath[sizeof(strDirPath)-1] = 0; +} + + +// startup engine +ENGINE_API void SE_InitEngine(CTString strGameID) +{ + #pragma message(">> Remove this from SE_InitEngine : _bWorldEditorApp") + if(strGameID=="SeriousEditor") { + _bWorldEditorApp = TRUE; + } + + AnalyzeApplicationPath(); + _fnmApplicationPath = CTString(strDirPath); + _fnmApplicationExe = CTString(strExePath); + try { + _fnmApplicationExe.RemoveApplicationPath_t(); + } catch (char *strError) { + (void) strError; + ASSERT(FALSE); + } + + _pConsole = new CConsole; + if (_strLogFile=="") { + _strLogFile = CTFileName(CTString(strExePath)).FileName(); + } + _pConsole->Initialize(_fnmApplicationPath+_strLogFile+".log", 90, 512); + + _pAnimStock = new CStock_CAnimData; + _pTextureStock = new CStock_CTextureData; + _pSoundStock = new CStock_CSoundData; + _pModelStock = new CStock_CModelData; + _pEntityClassStock = new CStock_CEntityClass; + _pMeshStock = new CStock_CMesh; + _pSkeletonStock = new CStock_CSkeleton; + _pAnimSetStock = new CStock_CAnimSet; + _pShaderStock = new CStock_CShader; + + _pTimer = new CTimer; + _pGfx = new CGfxLibrary; + _pSound = new CSoundLibrary; + _pInput = new CInput; + _pNetwork = new CNetworkLibrary; + + CRCT_Init(); + + _strEngineBuild.PrintF( TRANS("SeriousEngine Build: %d.%d"), _SE_BUILD_MAJOR, _SE_BUILD_MINOR); + + // print basic engine info + CPrintF(TRANS("--- Serious Engine Startup ---\n")); + CPrintF(" %s\n\n", _strEngineBuild); + + // print info on the started application + CPrintF(TRANS("Executable: %s\n"), strExePath); + CPrintF(TRANS("Assumed engine directory: %s\n"), _fnmApplicationPath); + + CPrintF("\n"); + + // report os info + CPrintF(TRANS("Examining underlying OS...\n")); + OSVERSIONINFOA osv; + memset(&osv, 0, sizeof(osv)); + osv.dwOSVersionInfoSize = sizeof(osv); + if (GetVersionExA(&osv)) { + switch (osv.dwPlatformId) { + case VER_PLATFORM_WIN32s: sys_strOS = "Win32s"; break; + case VER_PLATFORM_WIN32_WINDOWS: sys_strOS = "Win9x"; break; + case VER_PLATFORM_WIN32_NT: sys_strOS = "WinNT"; break; + default: sys_strOS = "Unknown\n"; break; + } + + sys_iOSMajor = osv.dwMajorVersion; + sys_iOSMinor = osv.dwMinorVersion; + sys_iOSBuild = osv.dwBuildNumber & 0xFFFF; + sys_strOSMisc = osv.szCSDVersion; + + CPrintF(TRANS(" Type: %s\n"), (const char*)sys_strOS); + CPrintF(TRANS(" Version: %d.%d, build %d\n"), + osv.dwMajorVersion, osv.dwMinorVersion, osv.dwBuildNumber & 0xFFFF); + CPrintF(TRANS(" Misc: %s\n"), osv.szCSDVersion); + } else { + CPrintF(TRANS("Error getting OS info: %s\n"), GetWindowsError(GetLastError()) ); + } + CPrintF("\n"); + + // init main shell + _pShell = new CShell; + _pShell->Initialize(); + + // report CPU + CPrintF(TRANS("Detecting CPU...\n")); + DetectCPUWrapper(); + CPrintF("\n"); + + // report memory info + extern void ReportGlobalMemoryStatus(void); + ReportGlobalMemoryStatus(); + + MEMORYSTATUS ms; + GlobalMemoryStatus(&ms); + + #define MB (1024*1024) + sys_iRAMPhys = ms.dwTotalPhys /MB; + sys_iRAMSwap = ms.dwTotalPageFile/MB; + + // initialize zip semaphore + zip_csLock.cs_iIndex = -1; // not checked for locking order + + + // get info on the first disk in system + DWORD dwSerial; + DWORD dwFreeClusters; + DWORD dwClusters; + DWORD dwSectors; + DWORD dwBytes; + + char strDrive[] = "C:\\"; + strDrive[0] = strExePath[0]; + + GetVolumeInformationA(strDrive, NULL, 0, &dwSerial, NULL, NULL, NULL, 0); + GetDiskFreeSpaceA(strDrive, &dwSectors, &dwBytes, &dwFreeClusters, &dwClusters); + sys_iHDDSize = __int64(dwSectors)*dwBytes*dwClusters/MB; + sys_iHDDFree = __int64(dwSectors)*dwBytes*dwFreeClusters/MB; + sys_iHDDMisc = dwSerial; + + // add console variables + extern INDEX con_bNoWarnings; + extern INDEX wld_bFastObjectOptimization; + extern INDEX fil_bPreferZips; + extern FLOAT mth_fCSGEpsilon; + _pShell->DeclareSymbol("user INDEX con_bNoWarnings;", &con_bNoWarnings); + _pShell->DeclareSymbol("user INDEX wld_bFastObjectOptimization;", &wld_bFastObjectOptimization); + _pShell->DeclareSymbol("user FLOAT mth_fCSGEpsilon;", &mth_fCSGEpsilon); + _pShell->DeclareSymbol("persistent user INDEX fil_bPreferZips;", &fil_bPreferZips); + // OS info + _pShell->DeclareSymbol("user const CTString sys_strOS ;", &sys_strOS); + _pShell->DeclareSymbol("user const INDEX sys_iOSMajor ;", &sys_iOSMajor); + _pShell->DeclareSymbol("user const INDEX sys_iOSMinor ;", &sys_iOSMinor); + _pShell->DeclareSymbol("user const INDEX sys_iOSBuild ;", &sys_iOSBuild); + _pShell->DeclareSymbol("user const CTString sys_strOSMisc;", &sys_strOSMisc); + // CPU info + _pShell->DeclareSymbol("user const CTString sys_strCPUVendor;", &sys_strCPUVendor); + _pShell->DeclareSymbol("user const INDEX sys_iCPUType ;", &sys_iCPUType ); + _pShell->DeclareSymbol("user const INDEX sys_iCPUFamily ;", &sys_iCPUFamily ); + _pShell->DeclareSymbol("user const INDEX sys_iCPUModel ;", &sys_iCPUModel ); + _pShell->DeclareSymbol("user const INDEX sys_iCPUStepping ;", &sys_iCPUStepping); + _pShell->DeclareSymbol("user const INDEX sys_bCPUHasMMX ;", &sys_bCPUHasMMX ); + _pShell->DeclareSymbol("user const INDEX sys_bCPUHasCMOV ;", &sys_bCPUHasCMOV ); + _pShell->DeclareSymbol("user const INDEX sys_iCPUMHz ;", &sys_iCPUMHz ); + _pShell->DeclareSymbol(" const INDEX sys_iCPUMisc ;", &sys_iCPUMisc ); + // RAM info + _pShell->DeclareSymbol("user const INDEX sys_iRAMPhys;", &sys_iRAMPhys); + _pShell->DeclareSymbol("user const INDEX sys_iRAMSwap;", &sys_iRAMSwap); + _pShell->DeclareSymbol("user const INDEX sys_iHDDSize;", &sys_iHDDSize); + _pShell->DeclareSymbol("user const INDEX sys_iHDDFree;", &sys_iHDDFree); + _pShell->DeclareSymbol(" const INDEX sys_iHDDMisc;", &sys_iHDDMisc); + // MOD info + _pShell->DeclareSymbol("user const CTString sys_strModName;", &sys_strModName); + _pShell->DeclareSymbol("user const CTString sys_strModExt;", &sys_strModExt); + + // Stock clearing + extern void FreeUnusedStock(void); + _pShell->DeclareSymbol("user void FreeUnusedStock(void);", &FreeUnusedStock); + + // Timer tick quantum + _pShell->DeclareSymbol("user const FLOAT fTickQuantum;", (FLOAT*)&_pTimer->TickQuantum); + + // init MODs and stuff ... + extern void InitStreams(void); + InitStreams(); + // keep mod name in sys cvar + sys_strModName = _strModName; + sys_strModExt = _strModExt; + +// checking of crc +#if 0 + ULONG ulCRCActual = -2; + SLONG ulCRCExpected = -1; + try { + // get the checksum of engine + #ifndef NDEBUG + #define SELFFILE "Bin\\Debug\\EngineD.dll" + #define SELFCRCFILE "Bin\\Debug\\EngineD.crc" + #else + #define SELFFILE "Bin\\Engine.dll" + #define SELFCRCFILE "Bin\\Engine.crc" + #endif + ulCRCActual = GetFileCRC32_t(CTString(SELFFILE)); + // load expected checksum from the file on disk + ulCRCExpected = 0; + LoadIntVar(CTString(SELFCRCFILE), ulCRCExpected); + } catch (char *strError) { + CPrintF("%s\n", strError); + } + // if not same + if (ulCRCActual!=ulCRCExpected) { + // don't run + //FatalError(TRANS("Engine CRC is invalid.\nExpected %08x, but found %08x.\n"), ulCRCExpected, ulCRCActual); + } +#endif + + _pInput->Initialize(); + + _pGfx->Init(); + _pSound->Init(); + + if (strGameID!="") { + _pNetwork->Init(strGameID); + // just make classes declare their shell variables + try { + CEntityClass* pec = _pEntityClassStock->Obtain_t(CTString("Classes\\Player.ecl")); + ASSERT(pec != NULL); + _pEntityClassStock->Release(pec); // this must not be a dependency! + // if couldn't find player class + } catch (char *strError) { + FatalError(TRANS("Cannot initialize classes:\n%s"), strError); + } + } else { + _pNetwork = NULL; + } + + // mark that default fonts aren't loaded (yet) + _pfdDisplayFont = NULL; + _pfdConsoleFont = NULL; + + // readout system gamma table + HDC hdc = GetDC(NULL); + BOOL bOK = GetDeviceGammaRamp( hdc, &auwSystemGamma[0]); + _pGfx->gl_ulFlags |= GLF_ADJUSTABLEGAMMA; + if( !bOK) { + _pGfx->gl_ulFlags &= ~GLF_ADJUSTABLEGAMMA; + CPrintF( TRANS("\nWARNING: Gamma, brightness and contrast are not adjustable!\n\n")); + } // done + ReleaseDC( NULL, hdc); + + // init IFeel + HWND hwnd = NULL;//GetDesktopWindow(); + HINSTANCE hInstance = GetModuleHandle(NULL); + if(IFeel_InitDevice(hInstance,hwnd)) + { + CTString strDefaultProject = "Data\\Default.ifr"; + // get project file name for this device + CTString strIFeel = IFeel_GetProjectFileName(); + // if no file name is returned use default file + if(strIFeel.Length()==0) strIFeel = strDefaultProject; + if(!IFeel_LoadFile(strIFeel)) + { + if(strIFeel!=strDefaultProject) + { + IFeel_LoadFile(strDefaultProject); + } + } + CPrintF("\n"); + } +} + + +// shutdown entire engine +ENGINE_API void SE_EndEngine(void) +{ + // restore system gamma table (if needed) + if( _pGfx->gl_ulFlags&GLF_ADJUSTABLEGAMMA) { + HDC hdc = GetDC(NULL); + BOOL bOK = SetDeviceGammaRamp( hdc, &auwSystemGamma[0]); + //ASSERT(bOK); + ReleaseDC( NULL, hdc); + } + + // free stocks + delete _pEntityClassStock; _pEntityClassStock = NULL; + delete _pModelStock; _pModelStock = NULL; + delete _pSoundStock; _pSoundStock = NULL; + delete _pTextureStock; _pTextureStock = NULL; + delete _pAnimStock; _pAnimStock = NULL; + delete _pMeshStock; _pMeshStock = NULL; + delete _pSkeletonStock; _pSkeletonStock = NULL; + delete _pAnimSetStock; _pAnimSetStock = NULL; + delete _pShaderStock; _pShaderStock = NULL; + + // free all memory used by the crc cache + CRCT_Clear(); + + // shutdown + if( _pNetwork != NULL) { delete _pNetwork; _pNetwork=NULL; } + delete _pInput; _pInput = NULL; + delete _pSound; _pSound = NULL; + delete _pGfx; _pGfx = NULL; + delete _pTimer; _pTimer = NULL; + delete _pShell; _pShell = NULL; + delete _pConsole; _pConsole = NULL; + extern void EndStreams(void); + EndStreams(); + + // shutdown profilers + _sfStats.Clear(); + _pfGfxProfile .pf_apcCounters.Clear(); + _pfGfxProfile .pf_aptTimers .Clear(); + _pfModelProfile .pf_apcCounters.Clear(); + _pfModelProfile .pf_aptTimers .Clear(); + _pfSoundProfile .pf_apcCounters.Clear(); + _pfSoundProfile .pf_aptTimers .Clear(); + _pfNetworkProfile .pf_apcCounters.Clear(); + _pfNetworkProfile .pf_aptTimers .Clear(); + _pfRenderProfile .pf_apcCounters.Clear(); + _pfRenderProfile .pf_aptTimers .Clear(); + _pfWorldEditingProfile .pf_apcCounters.Clear(); + _pfWorldEditingProfile .pf_aptTimers .Clear(); + _pfPhysicsProfile .pf_apcCounters.Clear(); + _pfPhysicsProfile .pf_aptTimers .Clear(); + + // remove default fonts if needed + if( _pfdDisplayFont != NULL) { delete _pfdDisplayFont; _pfdDisplayFont=NULL; } + if( _pfdConsoleFont != NULL) { delete _pfdConsoleFont; _pfdConsoleFont=NULL; } + + // deinit IFeel + IFeel_DeleteDevice(); +} + + +// prepare and load some default fonts +ENGINE_API void SE_LoadDefaultFonts(void) +{ + _pfdDisplayFont = new CFontData; + _pfdConsoleFont = new CFontData; + + // try to load default fonts + try { + _pfdDisplayFont->Load_t( CTFILENAME( "Fonts\\Display3-narrow.fnt")); + _pfdConsoleFont->Load_t( CTFILENAME( "Fonts\\Console1.fnt")); + } + catch (char *strError) { + FatalError( TRANS("Error loading font: %s."), strError); + } + // change fonts' default spacing a bit + _pfdDisplayFont->SetCharSpacing( 0); + _pfdDisplayFont->SetLineSpacing(+1); + _pfdConsoleFont->SetCharSpacing(-1); + _pfdConsoleFont->SetLineSpacing(+1); + _pfdConsoleFont->SetFixedWidth(); +} + + +// updates main windows' handles for windowed mode and fullscreen +ENGINE_API void SE_UpdateWindowHandle( HWND hwndMain) +{ + ASSERT( hwndMain!=NULL); + _hwndMain = hwndMain; + _bFullScreen = _pGfx!=NULL && (_pGfx->gl_ulFlags&GLF_FULLSCREEN); +} + + +static BOOL TouchBlock(UBYTE *pubMemoryBlock, INDEX ctBlockSize) +{ + // cannot pretouch block that are smaller than 64KB :( + ctBlockSize -= 16*0x1000; + if( ctBlockSize<4) return FALSE; + + __try { + // 4 times should be just enough + for( INDEX i=0; i<4; i++) { + // must do it in asm - don't know what VC will try to optimize + __asm { + // The 16-page skip is to keep Win 95 from thinking we're trying to page ourselves in + // (we are doing that, of course, but there's no reason we shouldn't) - THANX JOHN! :) + mov esi,dword ptr [pubMemoryBlock] + mov ecx,dword ptr [ctBlockSize] + shr ecx,2 +touchLoop: + mov eax,dword ptr [esi] + mov ebx,dword ptr [esi+16*0x1000] + add eax,ebx // BLA, BLA, TROOCH, TRUCH + add esi,4 + dec ecx + jnz touchLoop + } + } + } + __except(EXCEPTION_EXECUTE_HANDLER) { + return FALSE; + } + return TRUE; +} + + +// pretouch all memory commited by process +extern BOOL _bNeedPretouch = FALSE; +ENGINE_API extern void SE_PretouchIfNeeded(void) +{ + // only if pretouching is needed? + extern INDEX gam_bPretouch; + if( !_bNeedPretouch || !gam_bPretouch) return; + _bNeedPretouch = FALSE; + + // set progress bar + SetProgressDescription( TRANS("pretouching")); + CallProgressHook_t(0.0f); + + // need to do this two times - 1st for numerations, and 2nd for real (progress bar and that shit) + BOOL bPretouched = TRUE; + INDEX ctFails, ctBytes, ctBlocks; + INDEX ctPassBytes, ctTotalBlocks; + for( INDEX iPass=1; iPass<=2; iPass++) + { + // flush variables + ctFails=0; ctBytes=0; ctBlocks=0; ctTotalBlocks=0; + void *pvNextBlock = NULL; + MEMORY_BASIC_INFORMATION mbi; + // lets walk thru memory blocks + while( VirtualQuery( pvNextBlock, &mbi, sizeof(mbi))) + { + // don't mess with kernel's memory and zero-sized blocks + if( ((ULONG)pvNextBlock)>0x7FFF0000UL || mbi.RegionSize<1) break; + + // if this region of memory belongs to our process + BOOL bCanAccess = (mbi.Protect==PAGE_READWRITE); // || (mbi.Protect==PAGE_EXECUTE_READWRITE); + if( mbi.State==MEM_COMMIT && bCanAccess && mbi.Type==MEM_PRIVATE) // && !IsBadReadPtr( mbi.BaseAddress, 1) + { + // increase counters + ctBlocks++; + ctBytes += mbi.RegionSize; + // in first pass we only count + if( iPass==1) goto nextRegion; + // update progress bar + CallProgressHook_t( (FLOAT)ctBytes/ctPassBytes); + // pretouch + ASSERT( mbi.RegionSize>0); + BOOL bOK = TouchBlock((UBYTE *)mbi.BaseAddress, mbi.RegionSize); + if( !bOK) { + // whoops! + ctFails++; + } + // for easier debugging (didn't help much, though) + //Sleep(5); + } +nextRegion: + // advance to next region + pvNextBlock = ((UBYTE*)mbi.BaseAddress) + mbi.RegionSize; + ctTotalBlocks++; + } + // done with one pass + ctPassBytes = ctBytes; + if( (ctPassBytes/1024/1024)>sys_iRAMPhys) { + // not enough RAM, sorry :( + bPretouched = FALSE; + break; + } + } + + // report + if( bPretouched) { + // success + CPrintF( TRANS("Pretouched %d KB of memory in %d blocks.\n"), ctBytes/1024, ctBlocks); //, ctTotalBlocks); + } else { + // fail + CPrintF( TRANS("Cannot pretouch due to lack of physical memory (%d KB of overflow).\n"), ctPassBytes/1024-sys_iRAMPhys*1024); + } + // some blocks failed? + if( ctFails>1) CPrintF( TRANS("(%d blocks were skipped)\n"), ctFails); + //_pShell->Execute("StockDump();"); +} + + + + +#if 0 + + // printout block info + CPrintF("--------\n"); + CTString strTmp1, strTmp2; + CPrintF("Base/Alloc Address: 0x%8X / 0x%8X - Size: %d KB\n", mbi.BaseAddress, mbi.AllocationBase, mbi.RegionSize/1024); + switch( mbi.Protect) { + case PAGE_READONLY: strTmp1 = "PAGE_READONLY"; break; + case PAGE_READWRITE: strTmp1 = "PAGE_READWRITE"; break; + case PAGE_WRITECOPY: strTmp1 = "PAGE_WRITECOPY"; break; + case PAGE_EXECUTE: strTmp1 = "PAGE_EXECUTE"; break; + case PAGE_EXECUTE_READ: strTmp1 = "PAGE_EXECUTE_READ"; break; + case PAGE_EXECUTE_READWRITE: strTmp1 = "PAGE_EXECUTE_READWRITE"; break; + case PAGE_GUARD: strTmp1 = "PAGE_GUARD"; break; + case PAGE_NOACCESS: strTmp1 = "PAGE_NOACCESS"; break; + case PAGE_NOCACHE: strTmp1 = "PAGE_NOCACHE"; break; + } + switch( mbi.AllocationProtect) { + case PAGE_READONLY: strTmp2 = "PAGE_READONLY"; break; + case PAGE_READWRITE: strTmp2 = "PAGE_READWRITE"; break; + case PAGE_WRITECOPY: strTmp2 = "PAGE_WRITECOPY"; break; + case PAGE_EXECUTE: strTmp2 = "PAGE_EXECUTE"; break; + case PAGE_EXECUTE_READ: strTmp2 = "PAGE_EXECUTE_READ"; break; + case PAGE_EXECUTE_READWRITE: strTmp2 = "PAGE_EXECUTE_READWRITE"; break; + case PAGE_GUARD: strTmp2 = "PAGE_GUARD"; break; + case PAGE_NOACCESS: strTmp2 = "PAGE_NOACCESS"; break; + case PAGE_NOCACHE: strTmp2 = "PAGE_NOCACHE"; break; + } + CPrintF("Current/Alloc protect: %s / %s\n", strTmp1, strTmp2); + switch( mbi.State) { + case MEM_COMMIT: strTmp1 = "MEM_COMMIT"; break; + case MEM_FREE: strTmp1 = "MEM_FREE"; break; + case MEM_RESERVE: strTmp1 = "MEM_RESERVE"; break; + } + switch( mbi.Type) { + case MEM_IMAGE: strTmp2 = "MEM_IMAGE"; break; + case MEM_MAPPED: strTmp2 = "MEM_MAPPED"; break; + case MEM_PRIVATE: strTmp2 = "MEM_PRIVATE"; break; + } + CPrintF("State/Type: %s / %s\n", strTmp1, strTmp2); + +#endif \ No newline at end of file diff --git a/Sources/Engine/Engine.h b/Sources/Engine/Engine.h new file mode 100644 index 0000000..a9cac2e --- /dev/null +++ b/Sources/Engine/Engine.h @@ -0,0 +1,175 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// set this to 1 to enable checks whether somethig is deleted while iterating some array/container +#define CHECKARRAYLOCKING 0 + +#ifdef _WIN32 + #ifndef PLATFORM_WIN32 + #define PLATFORM_WIN32 1 + #endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include // for qsort +#include // for FPU control + +/* rcg10042001 !!! FIXME: Move these somewhere. */ +#if (defined PLATFORM_WIN32) +#include +#include +#include +#include +#include // for timers +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#pragma message(">> Uncomment include to terrain.h") +//#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// some global stuff +ENGINE_API void SE_InitEngine( CTString strGameID); +ENGINE_API void SE_EndEngine(void); +ENGINE_API void SE_LoadDefaultFonts(void); +ENGINE_API void SE_UpdateWindowHandle( HWND hwndWindowed); +ENGINE_API void SE_PretouchIfNeeded(void); + +extern ENGINE_API CTString _strEngineBuild; // not valid before InitEngine()! +extern ENGINE_API ULONG _ulEngineBuildMajor; +extern ENGINE_API ULONG _ulEngineBuildMinor; + +extern ENGINE_API BOOL _bDedicatedServer; +extern ENGINE_API BOOL _bWorldEditorApp; // is this world edtior app +extern ENGINE_API CTString _strLogFile; + +// temporary vars for adjustments +ENGINE_API extern FLOAT tmp_af[10]; +ENGINE_API extern INDEX tmp_ai[10]; +ENGINE_API extern INDEX tmp_i; +ENGINE_API extern INDEX tmp_fAdd; diff --git a/Sources/Engine/Engine.vcxproj b/Sources/Engine/Engine.vcxproj new file mode 100644 index 0000000..85f3508 --- /dev/null +++ b/Sources/Engine/Engine.vcxproj @@ -0,0 +1,1037 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + + + MFCProj + {4B6F587C-7C59-4481-FBB9-CA44380D0CBF} + + + + Application + v120 + Unicode + + + Application + + + DynamicLibrary + false + Unicode + v120 + + + Application + + + DynamicLibrary + Dynamic + v120 + Unicode + + + + + + + + + + + + + + + + + + Debug\ + Debug\ + false + $(SolutionDir)..\Tools.Win32;$(SolutionDir)..\Bin\Debug;$(ExecutablePath) + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(SolutionDir)Engine;$(IncludePath) + $(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + $(ProjectName)D + + + Release\ + Release\ + false + $(SolutionDir)..\Tools.Win32;$(SolutionDir)..\Bin;$(ExecutablePath) + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + $(ProjectName) + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + WIN32;_DEBUG;_WINDOWS;ENGINE_EXPORTS;_WINDLL;_USE_32BIT_TIME_T;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Debug\ + .\Debug\Engine.pch + Use + StdH.h + .\Debug\ + .\Debug\ + EnableFastChecks + 4603;4996;4812;4333 + + + true + _DEBUG;%(PreprocessorDefinitions) + .\Debug\Engine.tlb + true + Win32 + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\Engine.bsc + + + true + true + true + Console + Debug/EngineD.dll + .\Debug\EngineD.lib + gdi32.lib;DbgHelp.lib;%(AdditionalDependencies) + true + libci.lib;%(IgnoreSpecificDefaultLibraries) + false + + + copy Debug\$(TargetName).dll $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).lib $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to \Bin\Debug + $(SolutionDir)..\Bin\Debug\$(TargetName).dll;%(Outputs) + + + del $(SolutionDir)..\Bin\Debug\$(TargetName).dll /q >nul + + + + + MultiThreadedDLL + OnlyExplicitInline + false + MaxSpeed + true + Level3 + Speed + true + false + WIN32;NDEBUG;_WINDOWS;_USRDLL;ENGINE_EXPORTS;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\Engine.pch + Use + StdH.h + .\Release\ + .\Release\ + 4603;4996;4812;4333 + + + true + NDEBUG;%(PreprocessorDefinitions) + .\Release\Engine.tlb + true + Win32 + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\Engine.bsc + + + true + true + true + Console + .\Release\Engine.dll + .\Release\Engine.lib + odbc32.lib;odbccp32.lib;DbgHelp.lib;%(AdditionalDependencies) + true + libci.lib;%(IgnoreSpecificDefaultLibraries) + false + + + copy Release\$(TargetName).dll $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).lib $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to \Bin + $(SolutionDir)..\Bin\$(TargetName).dll;%(Outputs) + + + del $(SolutionDir)..\Bin\$(TargetName).dll /q >nul + + + + + false + + + + + Use + StdH.h + Use + StdH.h + + + + Use + StdH.h + Use + StdH.h + + + + + + + Use + StdH.h + Use + StdH.h + + + + + Use + StdH.h + Use + StdH.h + + + Use + StdH.h + Use + StdH.h + + + Use + StdH.h + Use + StdH.h + + + Use + StdH.h + Use + StdH.h + + + + + + + + + + + Use + StdH.h + Use + StdH.h + + + + Use + StdH.h + Use + StdH.h + + + Use + StdH.h + Use + StdH.h + + + + Use + StdH.h + true + Use + StdH.h + + + Use + StdH.h + Use + StdH.h + + + Use + StdH.h + Use + StdH.h + + + + Use + StdH.h + Use + StdH.h + + + + + + + + + Use + StdH.h + + + Use + StdH.h + + + + + + + + Use + StdH.h + + + Use + StdH.h + + + Use + StdH.h + + + Use + StdH.h + + + Use + StdH.h + + + + Use + StdH.h + + + + + + + Use + StdH.h + + + Use + StdH.h + + + Use + StdH.h + + + Use + StdH.h + + + + Use + StdH.h + + + + + + Use + StdH.h + + + Use + StdH.h + + + + true + true + + + true + true + + + + Use + StdH.h + + + Use + StdH.h + + + + + Use + StdH.h + + + + Use + StdH.h + + + + Use + StdH.h + + + Use + StdH.h + + + + Use + StdH.h + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + + + + true + true + + + true + true + + + true + true + + + true + true + + + true + true + + + + + true + true + + + true + true + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + true + true + + + true + true + + + true + true + + + + true + true + + + true + true + + + true + true + + + + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Use + StdH.h + + + Create + StdH.h + Create + StdH.h + + + Use + Use + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + pushd $(SolutionDir) +bison -o$(ProjectName)/Base/Parser.c $(ProjectName)/Base/Parser.y -d +popd +copy %(RootDir)%(Directory)\Parser.c %(RootDir)%(Directory)\Parser.cpp +del %(RootDir)%(Directory)\Parser.c /q + Generating shell parser source + %(RootDir)%(Directory)\Parser.cpp;%(RootDir)%(Directory)\Parser.h;%(Outputs) + pushd $(SolutionDir) +bison -o$(ProjectName)/Base/Parser.c $(ProjectName)/Base/Parser.y -d +popd +copy %(RootDir)%(Directory)\Parser.c %(RootDir)%(Directory)\Parser.cpp +del %(RootDir)%(Directory)\Parser.c /q + Generating shell parser source + %(RootDir)%(Directory)\Parser.cpp;%(RootDir)%(Directory)\Parser.h;%(Outputs) + + + Document + flex -o%(RootDir)%(Directory)\Scanner.cpp -S%(RootDir)%(Directory)\Flex.skl %(RootDir)%(Directory)\Scanner.l + Generating shell scanner source + %(RootDir)%(Directory)\Scanner.cpp;%(Outputs) + flex -o%(RootDir)%(Directory)\Scanner.cpp -S%(RootDir)%(Directory)\Flex.skl %(RootDir)%(Directory)\Scanner.l + Generating shell scanner source + %(RootDir)%(Directory)\Scanner.cpp;%(Outputs) + + + Document + + + Document + pushd $(SolutionDir) +bison -psyy -o$(ProjectName)/Ska/smcPars.c $(ProjectName)/Ska/smcPars.y -d +popd +copy %(RootDir)%(Directory)\smcPars.c %(RootDir)%(Directory)\smcPars.cpp +del %(RootDir)%(Directory)\smcPars.c /q + %(RootDir)%(Directory)\smcPars.cpp;%(RootDir)%(Directory)\smcPars.h;%(Outputs) + pushd $(SolutionDir) +bison -psyy -o$(ProjectName)/Ska/smcPars.c $(ProjectName)/Ska/smcPars.y -d +popd +copy %(RootDir)%(Directory)\smcPars.c %(RootDir)%(Directory)\smcPars.cpp +del %(RootDir)%(Directory)\smcPars.c /q + %(RootDir)%(Directory)\smcPars.cpp;%(RootDir)%(Directory)\smcPars.h;%(Outputs) + + + Document + flex -o%(RootDir)%(Directory)\smcScan.cpp -S%(RootDir)%(Directory)\smcFlex.skl %(RootDir)%(Directory)\smcScan.l + %(RootDir)%(Directory)\smcScan.cpp;%(Outputs) + flex -o%(RootDir)%(Directory)\smcScan.cpp -S%(RootDir)%(Directory)\smcFlex.skl %(RootDir)%(Directory)\smcScan.l + %(RootDir)%(Directory)\smcScan.cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc Engine/Classes/%(Filename).es + Engine/Classes/%(Filename).es + Classes/%(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc Engine/Classes/%(Filename).es + Engine/Classes/%(Filename).es + Classes/%(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc Engine/Classes/%(Filename).es + Engine/Classes/%(Filename).es + Classes/%(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc Engine/Classes/%(Filename).es + Engine/Classes/%(Filename).es + Classes/%(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc Engine/Classes/%(Filename).es + Engine/Classes/%(Filename).es + Classes/%(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc Engine/Classes/%(Filename).es + Engine/Classes/%(Filename).es + Classes/%(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc Engine/Classes/%(Filename).es + Engine/Classes/%(Filename).es + Classes/%(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc Engine/Classes/%(Filename).es + Engine/Classes/%(Filename).es + Classes/%(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc Engine/Classes/%(Filename).es + Engine/Classes/%(Filename).es + Classes/%(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc Engine/Classes/%(Filename).es + Engine/Classes/%(Filename).es + Classes/%(Filename).cpp;%(Outputs) + + + + + + + + \ No newline at end of file diff --git a/Sources/Engine/Engine.vcxproj.filters b/Sources/Engine/Engine.vcxproj.filters new file mode 100644 index 0000000..a84e7db --- /dev/null +++ b/Sources/Engine/Engine.vcxproj.filters @@ -0,0 +1,1427 @@ + + + + + {d2af37de-1340-4c84-a955-78272a7da707} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {a0bd9f7d-4f48-40f4-9848-b1d60ed1446f} + + + {013eefac-b492-492c-9ecd-8b1dd97fa78a} + + + {6cadab3e-9717-462b-80df-0c2eb8edb1c9} + + + {b0e6bfff-1903-4a4d-b9a3-46f2cdd79f6f} + + + {f894ee20-ee60-4851-ab6a-826d50b2fac3} + + + {f4f00d5f-72c2-46ed-a1ff-5a41d15f1402} + + + {a22fae84-ca42-4995-92e4-7a59134dace4} + + + {873bae33-3c40-4851-bc94-ca941db5ddcd} + + + {795b33b1-2b76-4e77-95ed-2b9bcc7afa89} + + + {e57fb559-f958-49e6-90ef-9a6daa202a01} + + + {06923da8-3781-46a1-ae5c-a9140e34f662} + + + {12376991-b050-4460-b833-319fe3e1dfa9} + + + {e949b98b-06d0-4289-98bd-bb485f6ba16f} + + + {23578051-c3bd-4c95-82c7-03bd7b80b788} + + + {dddbfcbd-a0ad-40dd-844c-c2c5c91ba8ef} + + + {5e8127f8-8cfb-46ce-aed9-9a2bb7540cc9} + h;inl;hxx + + + {d6ec3ddc-21ac-40c6-baf8-dc9fda4d7d16} + + + {489064e6-536a-4b64-8967-b3a8bca50e47} + + + {cd29c299-0f6e-45d4-8be8-b6c7ee902c9d} + + + {4dfab12e-091a-491f-b490-12be3e8ecfb7} + + + {ee32d05d-33d3-4aa5-8acd-ed80d579dcce} + + + {9ad10322-5eba-4f0f-97e8-a94dbe1437d9} + + + {566403f6-f0b5-4144-b4f9-16fd48b28902} + + + {0577ebde-c09c-4032-917b-d3a03ed96e9a} + + + {0fb7a18d-048a-4edd-8d16-249973dcd024} + + + {cf3367d0-9482-4c25-943f-620ab33a2d31} + + + {007f2692-6d91-486f-95a3-3fd602a1b232} + + + {22ff6724-e781-4878-a594-b526f04ffcb3} + + + {9e9b829a-a1b4-4d50-b915-38027bb2ef24} + + + {8106ef61-3f70-4fa9-8c74-684b476fa56e} + + + {bb506cc5-e844-41c1-abf8-58370e1e40a5} + + + {12d770e9-4595-473a-93a4-6adf8e70321d} + y;l;skl + + + {1fee903d-4db4-423d-aa35-10c6eb197ce0} + + + {050e5524-f62c-40c6-83a0-a7eb090337ec} + + + {a16b8831-a69d-41ad-83ab-393fe06504f5} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {3de7b00a-0b6d-478e-a6b7-e12806e1f7f7} + + + {213d6870-6a86-43c8-b4be-01096c1ccddf} + + + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Base + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Math + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Graphics + + + Source Files\Sound + + + Source Files\Sound + + + Source Files\Sound + + + Source Files\Sound + + + Source Files\Sound + + + Source Files\Sound + + + Source Files\Sound + + + Source Files\Models + + + Source Files\Models + + + Source Files\Models + + + Source Files\Models + + + Source Files\Models + + + Source Files\Models + + + Source Files\Models + + + Source Files\Models + + + Source Files\Models + + + Source Files\World + + + Source Files\World + + + Source Files\World + + + Source Files\World + + + Source Files\World + + + Source Files\World + + + Source Files\World + + + Source Files\World + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Templates + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Network + + + Source Files\Rendering + + + Source Files\Rendering + + + Source Files\Rendering + + + Source Files\Rendering + + + Source Files\Rendering + + + Source Files\Rendering + + + Source Files\Rendering + + + Source Files\Rendering + + + Source Files\Rendering + + + Source Files\Rendering + + + Source Files\Entities + + + Source Files\Entities + + + Source Files\Entities + + + Source Files\Entities + + + Source Files\Entities + + + Source Files\Entities + + + Source Files\Entities + + + Source Files\Entities + + + Source Files\Entities + + + Source Files\Brushes + + + Source Files\Brushes + + + Source Files\Brushes + + + Source Files\Brushes + + + Source Files\Brushes + + + Source Files\Brushes + + + Source Files\Brushes + + + Source Files\Brushes + + + Source Files\Brushes + + + Source Files\Brushes + + + Source Files\Light + + + Source Files\Light + + + Source Files\Light + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\zlib + + + Source Files\Ska + + + Source Files\Ska + + + Source Files\Ska + + + Source Files\Ska + + + Source Files\Ska + + + Source Files\Ska + + + Source Files\Ska + + + Source Files\Terrain + + + Source Files\Terrain + + + Source Files\Terrain + + + Source Files\Terrain + + + Source Files\Terrain + + + Source Files\Terrain + + + Source Files\Terrain + + + Source Files\Terrain + + + Source Files\Terrain + + + Source Files + + + Source Files + + + Generated Sources + + + Generated Sources + + + Generated Sources + + + Generated Sources + + + Generated Sources + + + Generated Sources + + + Generated Sources + + + Generated Sources + + + Generated Sources + + + Source Files\GameAgent + + + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Graphics Headers + + + Header Files\Sound Headers + + + Header Files\Sound Headers + + + Header Files\Sound Headers + + + Header Files\Sound Headers + + + Header Files\Sound Headers + + + Header Files\Sound Headers + + + Header Files\Sound Headers + + + Header Files\Sound Headers + + + Header Files\Sound Headers + + + Header Files\Sound Headers + + + Header Files\Models Headers + + + Header Files\Models Headers + + + Header Files\Models Headers + + + Header Files\Models Headers + + + Header Files\Models Headers + + + Header Files\Models Headers + + + Header Files\Models Headers + + + Header Files\Models Headers + + + Header Files\Models Headers + + + Header Files\Models Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Templates Headers + + + Header Files\Rendering Headers + + + Header Files\Rendering Headers + + + Header Files\Rendering Headers + + + Header Files\Entities Headers + + + Header Files\Entities Headers + + + Header Files\Entities Headers + + + Header Files\Entities Headers + + + Header Files\Entities Headers + + + Header Files\Entities Headers + + + Header Files\Entities Headers + + + Header Files\Entities Headers + + + Header Files\Entities Headers + + + Header Files\Entities Headers + + + Header Files\Entities Headers + + + Header Files\Entities Headers + + + Header Files\Brushes Headers + + + Header Files\Brushes Headers + + + Header Files\Brushes Headers + + + Header Files\Brushes Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Network Headers + + + Header Files\Light Headers + + + Header Files\Light Headers + + + Header Files\Light Headers + + + Header Files\zlib Headers + + + Header Files\zlib Headers + + + Header Files\zlib Headers + + + Header Files\zlib Headers + + + Header Files\zlib Headers + + + Header Files\zlib Headers + + + Header Files\zlib Headers + + + Header Files\zlib Headers + + + Header Files\zlib Headers + + + Header Files\zlib Headers + + + Header Files\zlib Headers + + + Header Files\Ska Headers + + + Header Files\Ska Headers + + + Header Files\Ska Headers + + + Header Files\Ska Headers + + + Header Files\Ska Headers + + + Header Files\Ska Headers + + + Header Files\Ska Headers + + + Header Files\World Headers + + + Header Files\World Headers + + + Header Files\World Headers + + + Header Files\World Headers + + + Header Files\World Headers + + + Header Files\World Headers + + + Header Files\Terrain Headers + + + Header Files\Terrain Headers + + + Header Files\Terrain Headers + + + Header Files\Terrain Headers + + + Header Files\Terrain Headers + + + Header Files\Terrain Headers + + + Header Files\Terrain Headers + + + Header Files\Terrain Headers + + + Header Files\Terrain Headers + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files\GameAgent Headers + + + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Base Headers + + + Header Files\Math Headers + + + Header Files\Math Headers + + + Grammar Files + + + Grammar Files + + + Grammar Files + + + Grammar Files + + + Grammar Files + + + Grammar Files + + + Entity Class Files + + + Entity Class Files + + + Entity Class Files + + + Entity Class Files + + + Entity Class Files + + + + + \ No newline at end of file diff --git a/Sources/Engine/Engine.vcxproj.user b/Sources/Engine/Engine.vcxproj.user new file mode 100644 index 0000000..46a93a9 --- /dev/null +++ b/Sources/Engine/Engine.vcxproj.user @@ -0,0 +1,8 @@ + + + + + + WindowsLocalDebugger + + \ No newline at end of file diff --git a/Sources/Engine/Entities/Entity.cpp b/Sources/Engine/Entities/Entity.cpp new file mode 100644 index 0000000..ce8e4f1 --- /dev/null +++ b/Sources/Engine/Entities/Entity.cpp @@ -0,0 +1,3952 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// a reference to a void event for use as default parameter +const EVoid _evVoid; +const CEntityEvent &_eeVoid = _evVoid; + +// allocation step for state stack of a CRationalEntity +#define STATESTACK_ALLOCATIONSTEP 5 +extern INDEX _ctEntities; +extern INDEX _ctPredictorEntities; + +// check if entity is of given class +BOOL IsOfClass(CEntity *pen, const char *pstrClassName) +{ + if (pen==NULL || pstrClassName==NULL) { + return FALSE; + } + if (strcmp(pen->GetClass()->ec_pdecDLLClass->dec_strName, pstrClassName)==0) { + return TRUE; + } else { + return FALSE; + } +} +BOOL IsOfSameClass(CEntity *pen1, CEntity *pen2) +{ + if (pen1==NULL || pen2==NULL) { + return FALSE; + } + if (pen1->GetClass()->ec_pdecDLLClass == pen2->GetClass()->ec_pdecDLLClass) { + return TRUE; + } else { + return FALSE; + } +} + +// check if entity is of given class or derived from +BOOL IsDerivedFromClass(CEntity *pen, const char *pstrClassName) +{ + if (pen==NULL || pstrClassName==NULL) { + return FALSE; + } + // for all classes in hierarchy of the entity + for(CDLLEntityClass *pdecDLLClass = pen->GetClass()->ec_pdecDLLClass; + pdecDLLClass!=NULL; + pdecDLLClass = pdecDLLClass->dec_pdecBase) { + // if it is the wanted class + if (strcmp(pdecDLLClass->dec_strName, pstrClassName)==0) { + // it is derived + return TRUE; + } + } + // otherwise, it is not derived + return FALSE; +} + +///////////////////////////////////////////////////////////////////// +// CEntity + +/* + * Default constructor. + */ +CEntity::CEntity(void) +{ + en_pbrBrush = NULL; + en_psiShadingInfo = NULL; + en_pciCollisionInfo = NULL; + en_pecClass = NULL; + en_ulFlags = 0; + en_ulSpawnFlags = 0xFFFFFFFFL; // active always + en_ulPhysicsFlags = 0; + en_ulCollisionFlags = 0; + en_ctReferences = 0; + en_ulID = 0; + en_RenderType = RT_NONE; + en_fSpatialClassificationRadius = -1.0f; + en_penParent = NULL; + en_plpLastPositions = NULL; + _ctEntities++; +} + +/* + * Destructor. + */ +CEntity::~CEntity(void) +{ + ASSERT(en_ctReferences==0); + ASSERT(en_ulID!=0); + ASSERT(en_RenderType==RT_NONE); + // remove it from container in its world + ASSERT(!en_pwoWorld->wo_cenEntities.IsMember(this)); + en_pwoWorld->wo_cenAllEntities.Remove(this); + + // unset spatial clasification + en_rdSectors.Clear(); + + /* + Models are always destructed on End(), but brushes and terrains are not, so + if the pointer is not NULL, then it must be a brush or terrain. + Both of them are derived from CBrushBase so GetBrushType() will return its real type + */ + + // if it is brush of terrain + if(en_pbrBrush != NULL) { + INDEX btType = en_pbrBrush->GetBrushType(); + // if this is brush3d + if(btType==CBrushBase::BT_BRUSH3D) { + // free the brush + en_pwoWorld->wo_baBrushes.ba_abrBrushes.Delete(en_pbrBrush); + en_pbrBrush = NULL; + // if this is terrain + } else if(btType==CBrushBase::BT_TERRAIN) { + // free the brush + en_pwoWorld->wo_taTerrains.ta_atrTerrains.Delete(en_ptrTerrain); + en_pbrBrush = NULL; + // unknown type + } else { + ASSERTALWAYS("Unsupported brush type"); + } + } + // clear entity type + en_RenderType = RT_NONE; + en_pecClass->RemReference(); + en_pecClass = NULL; + + en_fSpatialClassificationRadius = -1.0f; + _ctEntities--; + + if (IsPredictable()) { + if (en_pwoWorld->wo_cenPredictable.IsMember(this)) { + en_pwoWorld->wo_cenPredictable.Remove(this); + } + } + if (en_ulFlags&ENF_WILLBEPREDICTED) { + if (en_pwoWorld->wo_cenWillBePredicted.IsMember(this)) { + en_pwoWorld->wo_cenWillBePredicted.Remove(this); + } + } + if (IsPredictor()) { + if (en_pwoWorld->wo_cenPredictor.IsMember(this)) { + en_pwoWorld->wo_cenPredictor.Remove(this); + _ctPredictorEntities--; + } + } +} + +///////////////////////////////////////////////////////////////////// +// Access functions + +/* Test if the entity is an empty brush. */ +BOOL CEntity::IsEmptyBrush(void) const +{ + // if it is not brush + if (en_RenderType != CEntity::RT_BRUSH && en_RenderType != RT_FIELDBRUSH) { + // it is not empty brush + return FALSE; + // if it is brush + } else { + + // get its brush + CBrush3D &brBrush = *en_pbrBrush; + // get the first mip of the brush + CBrushMip *pbmMip = brBrush.GetFirstMip(); + + // it is empty if it has zero sectors + return pbmMip->bm_abscSectors.Count()==0; + } +} + +/* Return max Game Players */ +INDEX CEntity::GetMaxPlayers(void) { + return NET_MAXGAMEPLAYERS; +}; + +/* Return Player Entity */ +CEntity *CEntity::GetPlayerEntity(INDEX iPlayer) +{ + ASSERT(iPlayer>=0 && iPlayerga_sesSessionState; + if (ses.ses_apltPlayers[iPlayer].plt_bActive) { + return ses.ses_apltPlayers[iPlayer].plt_penPlayerEntity; + } else { + return NULL; + } +} + +/* Get bounding box of this entity - for AI purposes only. */ +void CEntity::GetBoundingBox(FLOATaabbox3D &box) +{ + if (en_pciCollisionInfo!=NULL) { + box = en_pciCollisionInfo->ci_boxCurrent; + } else { + GetSize(box); + box += GetPlacement().pl_PositionVector; + } +} + +/* Get size of this entity - for UI purposes only. */ +void CEntity::GetSize(FLOATaabbox3D &box) +{ + if (en_RenderType==CEntity::RT_MODEL || en_RenderType==CEntity::RT_EDITORMODEL) { + en_pmoModelObject->GetCurrentFrameBBox( box); + box.StretchByVector(en_pmoModelObject->mo_Stretch); + } else if(en_RenderType==CEntity::RT_SKAMODEL || en_RenderType==CEntity::RT_SKAEDITORMODEL) { + GetModelInstance()->GetCurrentColisionBox( box); + box.StretchByVector(GetModelInstance()->mi_vStretch); + } else if (en_RenderType==CEntity::RT_TERRAIN) { + GetTerrain()->GetAllTerrainBBox(box); + } else if (en_RenderType==CEntity::RT_BRUSH || en_RenderType==CEntity::RT_FIELDBRUSH) { + CBrushMip *pbm = en_pbrBrush->GetFirstMip(); + if (pbm == NULL) { + box = FLOATaabbox3D(FLOAT3D(0,0,0), FLOAT3D(0,0,0)); + } else { + box = pbm->bm_boxBoundingBox; + box += -GetPlacement().pl_PositionVector; + } + } + else { + box = FLOATaabbox3D(FLOAT3D(0,0,0), FLOAT3D(0,0,0)); + } +} + +/* Get name of this entity. */ +const CTString &CEntity::GetName(void) const +{ + static const CTString strDummyName(""); + return strDummyName; +} +const CTString &CEntity::GetDescription(void) const // name + some more verbose data +{ + static const CTString strDummyDescription(""); + return strDummyDescription; +} + +/* Get first target of this entity. */ +CEntity *CEntity::GetTarget(void) const +{ + return NULL; +} + +/* Check if entity can be used as a target. */ +BOOL CEntity::IsTargetable(void) const +{ + // cannot be targeted unless this function is overridden + return FALSE; +} +/* Check if entity is marker */ +BOOL CEntity::IsMarker(void) const{ + // cannot be marker unless this function is overridden + return FALSE; +} +/* Check if entity is important */ +BOOL CEntity::IsImportant(void) const{ + // cannot be important unless this function is overridden + return FALSE; +} +/* Check if entity is moved on a route set up by its targets. */ +BOOL CEntity::MovesByTargetedRoute(CTString &strTargetProperty) const +{ + return FALSE; +} +/* Check if entity can drop marker for making linked route. */ +BOOL CEntity::DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const +{ + return FALSE; +} + +/* Get light source information - return NULL if not a light source. */ +CLightSource *CEntity::GetLightSource(void) +{ + return NULL; +} + +BOOL CEntity::IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) +{ + return TRUE; +} + +/* Get anim data for given animation property - return NULL for none. */ +CAnimData *CEntity::GetAnimData(SLONG slPropertyOffset) +{ + return NULL; +} + +/* Get force type name, return empty string if not used. */ +const CTString &CEntity::GetForceName(INDEX iForce) +{ + static const CTString strDummyName(""); + return strDummyName; +} + +/* Get forces in given point. */ +void CEntity::GetForce(INDEX iForce, const FLOAT3D &vPoint, + CForceStrength &fsGravity, CForceStrength &fsField) +{ + // default gravity + fsGravity.fs_vDirection = FLOAT3D(0,-1,0); + fsGravity.fs_fAcceleration = 9.81f; + fsGravity.fs_fVelocity = 0; + + // no force field + fsField.fs_fAcceleration = 0; +} +/* Get entity that controls the force, used for change notification checking. */ +CEntity *CEntity::GetForceController(INDEX iForce) +{ + return NULL; +} + +/* Adjust model shading parameters if needed - return TRUE if needs model shadows. */ +BOOL CEntity::AdjustShadingParameters(FLOAT3D &vLightDirection, + COLOR &colLight, COLOR &colAmbient) +{ + return TRUE; +} +/* Adjust model mip factor if needed. */ +void CEntity::AdjustMipFactor(FLOAT &fMipFactor) +{ + (void)fMipFactor; + NOTHING; +} + +// get a different model object for rendering - so entity can change its appearance dynamically +// NOTE: base model is always used for other things (physics, etc). +CModelObject *CEntity::GetModelForRendering(void) +{ + return en_pmoModelObject; +} + +// get a different model instance for rendering - so entity can change its appearance dynamically +// NOTE: base model is always used for other things (physics, etc). +CModelInstance *CEntity::GetModelInstanceForRendering(void) +{ + return en_pmiModelInstance; +} + +/* Get fog type name, return empty string if not used. */ +const CTString &CEntity::GetFogName(INDEX iFog) +{ + static const CTString strDummyName(""); + return strDummyName; +} + +/* Get fog, return FALSE for none. */ +BOOL CEntity::GetFog(INDEX iFog, class CFogParameters &fpFog) +{ + return FALSE; +} + +/* Get haze type name, return empty string if not used. */ +const CTString &CEntity::GetHazeName(INDEX iHaze) +{ + static const CTString strDummyName(""); + return strDummyName; +} + +/* Get haze, return FALSE for none. */ +BOOL CEntity::GetHaze(INDEX iHaze, class CHazeParameters &hpHaze, FLOAT3D &vViewDir) +{ + return FALSE; +} + +/* Get mirror type name, return empty string if not used. */ +const CTString &CEntity::GetMirrorName(INDEX iMirror) +{ + static const CTString strDummyName(""); + return strDummyName; +} + +/* Get mirror, return FALSE for none. */ +BOOL CEntity::GetMirror(INDEX iMirror, class CMirrorParameters &mpMirror) +{ + return FALSE; +} + +/* Get gradient type name, return empty string if not used. */ +const CTString &CEntity::GetGradientName(INDEX iGradient) +{ + static const CTString strDummyName(""); + return strDummyName; +} + +/* Get gradient, return FALSE for none. */ +BOOL CEntity::GetGradient(INDEX iGradient, class CGradientParameters &gpGradient) +{ + return FALSE; +} + +FLOAT3D CEntity::GetClassificationBoxStretch(void) +{ + return FLOAT3D( 1.0f, 1.0f, 1.0f); +} + +/* Get field information - return NULL if not a field. */ +CFieldSettings *CEntity::GetFieldSettings(void) +{ + return NULL; +} +/* Render particles made by this entity. */ +void CEntity::RenderParticles(void) +{ + NOTHING; +} +/* Get current collision box index for this entity. */ +INDEX CEntity::GetCollisionBoxIndex(void) +{ + // by default, use only box 0 + return 0; +} +/* Get current collision box - override for custom collision boxes. */ +void CEntity::GetCollisionBoxParameters(INDEX iBox, FLOATaabbox3D &box, INDEX &iEquality) +{ + // if this is ska model + if(en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL) { + box.minvect = GetModelInstance()->GetCollisionBoxMin(iBox); + box.maxvect = GetModelInstance()->GetCollisionBoxMax(iBox); + FLOATaabbox3D boxNS = box; + box.StretchByVector(GetModelInstance()->mi_vStretch); + iEquality = GetModelInstance()->GetCollisionBoxDimensionEquality(iBox); + } else { + box.minvect = en_pmoModelObject->GetCollisionBoxMin(iBox); + box.maxvect = en_pmoModelObject->GetCollisionBoxMax(iBox); + box.StretchByVector(en_pmoModelObject->mo_Stretch); + iEquality = en_pmoModelObject->GetCollisionBoxDimensionEquality(iBox); + } +} + +/* Render game view */ +void CEntity::RenderGameView(CDrawPort *pdp, void *pvUserData) +{ + NOTHING; +} +// apply mirror and stretch to the entity if supported +void CEntity::MirrorAndStretch(FLOAT fStretch, BOOL bMirrorX) +{ + NOTHING; +} +// get offset for depth-sorting of alpha models (in meters, positive is nearer) +FLOAT CEntity::GetDepthSortOffset(void) +{ + return 0.0f; +} +// get visibility tweaking bits +ULONG CEntity::GetVisTweaks(void) +{ + return 0; +} + +// Get max tessellation level +FLOAT CEntity::GetMaxTessellationLevel(void) +{ + return 0.0f; +} + +// get pointer to your predictor/predicted +CEntity *CEntity::GetPredictionPair(void) +{ + // this should never be called, it must be overriden if prediction is used! + ASSERT(FALSE); + return this; // this is safest to return if in release version +} +void CEntity::SetPredictionPair(CEntity *penPair) +{ + // this should never be called, it must be overriden if prediction is used! + ASSERT(FALSE); +} + +// add to prediction any entities that this entity depends on +void CEntity::AddDependentsToPrediction(void) +{ +} + +// called by other entities to set time prediction parameter +void CEntity::SetPredictionTime(TIME tmAdvance) // give time interval in advance to set +{ + NOTHING; // by default, don't use time prediction +} + +// called by engine to get the upper time limit +TIME CEntity::GetPredictionTime(void) // return moment in time up to which to predict this entity +{ + return -1.0f; // by default, don't use time prediction +} + +// get maximum allowed range for predicting this entity +FLOAT CEntity::GetPredictionRange(void) +{ + return UpperLimit(0.0f); // by default, cli_fPredictEntitiesRange is the limit +} + +// copy for prediction +void CEntity::CopyForPrediction(CEntity &enOrg) +{ + // this should never be called, it must be overriden if prediction is used! + ASSERT(FALSE); +} + +CEntity *CEntity::GetPredictor(void) +{ + ASSERT(IsPredicted()); + CEntity *pen = GetPredictionPair(); + ASSERT(pen->IsPredictor()); + return pen; +} +CEntity *CEntity::GetPredicted(void) +{ + ASSERT(IsPredictor()); + CEntity *pen = GetPredictionPair(); + ASSERT(pen!=NULL); + ASSERT(pen->IsPredicted()); + return pen; +} +// become predictable/unpredictable +void CEntity::SetPredictable(BOOL bON) +{ + // if predictor + if (IsPredictor()) { + // do nothing + return; + } + + // if already set + if (IsPredictable()) { + // check that valid + ASSERT(en_pwoWorld->wo_cenPredictable.IsMember(this)); + // if turning on + if (bON) { + // do nothing + return; + } + // mark as not predictable + en_ulFlags&=~ENF_PREDICTABLE; + // remove from container + en_pwoWorld->wo_cenPredictable.Remove(this); + + // if not set + } else { + // check that valid + ASSERT(!en_pwoWorld->wo_cenPredictable.IsMember(this)); + ASSERT(!IsPredictor()); + ASSERT(!IsPredicted()); + // if turning off + if (!bON) { + // do nothing + return; + } + // mark as predictable + en_ulFlags|=ENF_PREDICTABLE; + // add to container + en_pwoWorld->wo_cenPredictable.Add(this); + } +} + +// check if this instance is head of prediction chain +BOOL CEntity::IsPredictionHead(void) +{ + // if predicted, or will be predicted, or is a temporary predictor + if (en_ulFlags&(ENF_PREDICTED|ENF_WILLBEPREDICTED|ENF_TEMPPREDICTOR)) { + // it cannot be head of the chain + return FALSE; + } + + // if predictor, but not currently in the last step of prediction + if ((en_ulFlags&ENF_PREDICTOR) && + _pTimer->CurrentTick()<=_pNetwork->ga_sesSessionState.ses_tmPredictionHeadTick) { + // it cannot be head of the chain + return FALSE; + } + // otherwise it is head of the chain + return TRUE; +} + +// get the prediction original (predicted), or self if not predicting +CEntity *CEntity::GetPredictionTail(void) +{ + // if this is a predictor + if (IsPredictor()) { + // it must be head of the prediction chain + //ASSERT(IsPredictionHead()); + // get its predicted + return GetPredicted(); + } + // in other cases, return self + return this; +} +// check if active for prediction now +BOOL CEntity::IsAllowedForPrediction(void) const +{ + return !_pNetwork->IsPredicting() || IsPredictor(); +} +// check an event for prediction, returns true if already predicted +BOOL CEntity::CheckEventPrediction(ULONG ulTypeID, ULONG ulEventID) +{ + return _pNetwork->ga_sesSessionState.CheckEventPrediction(this, ulTypeID, ulEventID); +} + +/* Called after creating and setting its properties. */ +void CEntity::OnInitialize(const CEntityEvent &eeInput) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // try to find a handler in start state + pEventHandler pehHandler = HandlerForStateAndEvent(1, eeInput.ee_slEvent); + // if there is a handler + if (pehHandler!=NULL) { + // call the function + (this->*pehHandler)(eeInput); + // if there is no handler + } else { + ASSERTALWAYS("All entities must have Main procedure!"); + } +} +/* Called before releasing entity. */ +void CEntity::OnEnd(void) +{ +} + +// print stack to debug output +const char *CEntity::PrintStackDebug(void) +{ + return "not CRationalEntity"; +}; + +/* + * Prepare entity (call after setting properties). + */ +void CEntity::Initialize(const CEntityEvent &eeInput) +{ + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // make sure we are not deleted during intialization + CEntityPointer penThis = this; + + Initialize_internal(eeInput); + // set spatial clasification + FindSectorsAroundEntity(); + // precache all other things + Precache(); +} +void CEntity::Initialize_internal(const CEntityEvent &eeInput) +{ + #ifndef NDEBUG + // clear settings for debugging + en_RenderType = RT_ILLEGAL; + #endif + + // remember brush zoning flag + BOOL bWasZoning = en_ulFlags&ENF_ZONING; + + // let derived class initialize according to the properties + OnInitialize(eeInput); + // derived class must set all properties +// ASSERT(en_RenderType != RT_ILLEGAL); + + // if this is a brush + if (en_RenderType==RT_BRUSH || en_RenderType==RT_FIELDBRUSH) { + // test if zoning + BOOL bZoning = en_ulFlags&ENF_ZONING; + // if switching from zoning to non-zoning + if (bWasZoning && !bZoning) { + // switch from zoning to non-zoning + en_pbrBrush->SwitchToNonZoning(); + en_rdSectors.Clear(); + // if switching from non-zoning to zoning + } else if (!bWasZoning && bZoning) { + // switch from non-zoning to zoning + en_pbrBrush->SwitchToZoning(); + en_rdSectors.Clear(); + } + } + + // if it is a field brush + CFieldSettings *pfs = GetFieldSettings(); + if (pfs!=NULL) { + // remember its field settings + ASSERT(en_RenderType == RT_FIELDBRUSH); + en_pbrBrush->br_pfsFieldSettings = pfs; + } +} + +/* + * Clean-up entity. + */ +void CEntity::End(void) +{ + CSetFPUPrecision FPUPrecision(FPT_24BIT); + /* NOTE: Must not remove from thinker/mover list here, or CServer::ProcessGameTick() + * might crash! + */ + End_internal(); +} +void CEntity::End_internal(void) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // let derived class clean-up after itself + OnEnd(); + + // clear last positions + if (en_plpLastPositions!=NULL) { + delete en_plpLastPositions; + en_plpLastPositions = NULL; + } + + // clear spatial classification + en_fSpatialClassificationRadius = -1.0f; + en_boxSpatialClassification = FLOATaabbox3D(); + + // depending on entity type + switch(en_RenderType) { + // if it is brush + case RT_BRUSH: + DiscardCollisionInfo(); + break; + // if it is field brush + case RT_FIELDBRUSH: + DiscardCollisionInfo(); + break; + + // if it is model + case RT_MODEL: + case RT_EDITORMODEL: + // free its model object + delete en_pmoModelObject; + delete en_psiShadingInfo; + DiscardCollisionInfo(); + en_pmoModelObject = NULL; + en_psiShadingInfo = NULL; + break; + // if it is ska model + case RT_SKAMODEL: + case RT_SKAEDITORMODEL: + en_pmiModelInstance->Clear(); + delete en_pmiModelInstance; + delete en_psiShadingInfo; + DiscardCollisionInfo(); + en_pmiModelInstance = NULL; + en_psiShadingInfo = NULL; + break; + case RT_TERRAIN: + DiscardCollisionInfo(); + break; + + // if it is nothing + case RT_NONE: + case RT_VOID: + // do nothing + NOTHING; + break; + // if it is any other type + default: + ASSERTALWAYS("Unsupported entity type"); + } + // clear entity type + en_RenderType = RT_NONE; +} + +/* + * Reinitialize the entity. + */ +void CEntity::Reinitialize(void) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + End_internal(); + Initialize_internal(_eeVoid); +} + +// teleport this entity to a new location -- takes care of telefrag damage +void CEntity::Teleport(const CPlacement3D &plNew, BOOL bTelefrag /*=TRUE*/) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + ASSERT(en_fSpatialClassificationRadius>0); + + // if telefragging is on and the entity has collision box + if (bTelefrag && en_pciCollisionInfo!=NULL) { + + // create the box of the entity at its new placement + FLOATmatrix3D mRot; + MakeRotationMatrixFast(mRot, plNew.pl_OrientationAngle); + FLOAT3D vPos = plNew.pl_PositionVector; + CMovingSphere &ms0 = en_pciCollisionInfo->ci_absSpheres[0]; + CMovingSphere &ms1 = en_pciCollisionInfo->ci_absSpheres[en_pciCollisionInfo->ci_absSpheres.Count()-1]; + FLOATaabbox3D box; + box = FLOATaabbox3D(vPos+ms0.ms_vCenter*mRot, ms0.ms_fR); + box |= FLOATaabbox3D(vPos+ms1.ms_vCenter*mRot, ms1.ms_fR); + + // first inflict huge damage there in the entities box + InflictBoxDamage(this, DMT_TELEPORT, 100000.0f, box); + } + + // remember original orientation matrix + FLOATmatrix3D mOld = en_mRotation; + + // now put the entity there + SetPlacement(plNew); + // movable entity + if (en_ulPhysicsFlags & EPF_MOVABLE) { + ((CMovableEntity*)this)->ClearTemporaryData(); + ((CMovableEntity*)this)->en_plLastPlacement = en_plPlacement; + // transform speeds + FLOATmatrix3D mRel = en_mRotation*!mOld; + ((CMovableEntity*)this)->en_vCurrentTranslationAbsolute *= mRel; + + if (_pNetwork->ga_ulDemoMinorVersion>=7) { + // clear reference + ((CMovableEntity*)this)->en_penReference = NULL; + ((CMovableEntity*)this)->en_pbpoStandOn = NULL; + } + + // notify that it was teleported + SendEvent(ETeleport()); + ((CMovableEntity*)this)->AddToMovers(); + + extern INDEX ent_bReportSpawnInWall; + if (ent_bReportSpawnInWall) { + // if movable model + if (en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL || + en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL) { + // check if it was teleported inside a wall + CMovableModelEntity *pmme = (CMovableModelEntity*)this; + CEntity *ppenObstacleDummy; + if (pmme->CheckForCollisionNow(pmme->en_iCollisionBox, &ppenObstacleDummy)) { + CPrintF("Entity '%s' was teleported inside a wall at (%g,%g,%g)!\n", + GetName(), + en_plPlacement.pl_PositionVector(1), + en_plPlacement.pl_PositionVector(2), + en_plPlacement.pl_PositionVector(3)); + } + } + } + } +} + +/* + * Set placement of this entity. (use only in WEd!) + */ +void CEntity::SetPlacement(const CPlacement3D &plNew) +{ + CSetFPUPrecision FPUPrecision(FPT_24BIT); + // check if orientation is changed + BOOL bSameOrientation = (plNew.pl_OrientationAngle==en_plPlacement.pl_OrientationAngle); + + // if the orientation has not changed + if (bSameOrientation) { + // set the placement and do all needed recalculation + SetPlacement_internal(plNew, en_mRotation, FALSE /* doesn't have to be near. */); + + // if the orientation has changed + } else { + // calculate new rotation matrix + FLOATmatrix3D mRotation; + MakeRotationMatrixFast(mRotation, plNew.pl_OrientationAngle); + // set the placement and do all needed recalculation + SetPlacement_internal(plNew, mRotation, FALSE /* doesn't have to be near. */); + } + + // if this entity has parent + if (en_penParent!=NULL) { + // adjust relative placement + en_plRelativeToParent = en_plPlacement; + en_plRelativeToParent.AbsoluteToRelativeSmooth(en_penParent->en_plPlacement); + } +} + + +/* + * Fall down to floor. (use only in WEd!) + */ +void CEntity::FallDownToFloor( void) +{ + CEntity::RenderType rt = GetRenderType(); + // is this old model + if(rt==CEntity::RT_MODEL || rt==CEntity::RT_EDITORMODEL) { + ASSERT(en_pmoModelObject != NULL); + // is this ska model + } else if(rt==CEntity::RT_SKAMODEL || rt==CEntity::RT_SKAEDITORMODEL) { + ASSERT(GetModelInstance() != NULL); + } else { + return; + } + // if( rt!=CEntity::RT_MODEL && rt!=CEntity::RT_EDITORMODEL) return; + // ASSERT(en_pmoModelObject != NULL); + + CPlacement3D plPlacement = GetPlacement(); + FLOAT3D vRay[4]; + // if it is movable entity + if( en_ulPhysicsFlags & EPF_MOVABLE) { + INDEX iEq; + FLOATaabbox3D box; + GetCollisionBoxParameters(GetCollisionBoxIndex(), box, iEq); + FLOAT3D vMin = box.Min(); + FLOAT3D vMax = box.Max(); + // all ray casts start from same height + vRay[0](2) = vMax(2); + vRay[1](2) = vMax(2); + vRay[2](2) = vMax(2); + vRay[3](2) = vMax(2); + + vRay[0](1) = vMin(1); + vRay[0](3) = vMin(3); + vRay[1](1) = vMin(1); + vRay[1](3) = vMax(3); + vRay[2](1) = vMax(1); + vRay[2](3) = vMin(3); + vRay[3](1) = vMax(1); + vRay[3](3) = vMax(3); + } + else { + FLOATaabbox3D box; + if(rt==CEntity::RT_SKAMODEL || rt==CEntity::RT_SKAEDITORMODEL) { + GetModelInstance()->GetCurrentColisionBox( box); + } else { + en_pmoModelObject->GetCurrentFrameBBox( box); + } + + FLOAT3D vCenterUp = box.Center(); + vCenterUp(2) = box.Max()(2); + vRay[0] = vCenterUp; + vRay[1] = vCenterUp; + vRay[2] = vCenterUp; + vRay[3] = vCenterUp; + } + + FLOAT fMaxY = -9999999.0f; + BOOL bFloorHitted = FALSE; + for( INDEX iRay=0; iRay<4; iRay++) + { + FLOAT3D vSource = plPlacement.pl_PositionVector+vRay[iRay]; + FLOAT3D vTarget = vSource; + vTarget(2) -= 1000.0f; + CCastRay crRay( this, vSource, vTarget); + crRay.cr_ttHitModels = CCastRay::TT_NONE; // CCastRay::TT_FULLSEETHROUGH; + crRay.cr_bHitTranslucentPortals = TRUE; + crRay.cr_bPhysical = TRUE; + GetWorld()->CastRay(crRay); + if( (crRay.cr_penHit != NULL) && (crRay.cr_vHit(2) > fMaxY)) { + fMaxY = crRay.cr_vHit(2); + bFloorHitted = TRUE; + } + } + if( bFloorHitted) plPlacement.pl_PositionVector(2) += fMaxY-plPlacement.pl_PositionVector(2)+0.01f; + SetPlacement( plPlacement); +} + + +extern CEntity *_penLightUpdating; +extern BOOL _bDontDiscardLinks = FALSE; + +// internal repositioning function +void CEntity::SetPlacement_internal(const CPlacement3D &plNew, const FLOATmatrix3D &mRotation, + BOOL bNear) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_SETPLACEMENT); + _pfPhysicsProfile.IncrementTimerAveragingCounter(CPhysicsProfile::PTI_SETPLACEMENT); + + // invalidate eventual cached info for still models + en_ulFlags &= ~ENF_VALIDSHADINGINFO; + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_SETPLACEMENT_COORDSUPDATE); + // remembel old placement of the entity + CPlacement3D plOld = en_plPlacement; + // set new placement of the entity + en_plPlacement = plNew; + en_mRotation = mRotation; + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_SETPLACEMENT_COORDSUPDATE); + + // if this is a brush entity + if (en_RenderType==RT_BRUSH || en_RenderType==RT_FIELDBRUSH) { + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_SETPLACEMENT_BRUSHUPDATE); + // recalculate all bounding boxes relative to new position + _bDontDiscardLinks = TRUE; + en_pbrBrush->CalculateBoundingBoxes(); + _bDontDiscardLinks = FALSE; + + BOOL bHasShadows=FALSE; + // for all brush mips + FOREACHINLIST(CBrushMip, bm_lnInBrush, en_pbrBrush->br_lhBrushMips, itbm) { + // for all sectors in the mip + {FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // for all polygons in this sector + {FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + // if the polygon has shadows + if (!(itbpo->bpo_ulFlags & BPOF_FULLBRIGHT)) { + // discard shadows + itbpo->DiscardShadows(); + bHasShadows = TRUE; + } + }} + }} + } + // find possible shadow layers near affected area + if (bHasShadows) { + if (en_ulFlags&ENF_DYNAMICSHADOWS) { + _penLightUpdating = NULL; + } else { + _penLightUpdating = this; + } + en_pwoWorld->FindShadowLayers(en_pbrBrush->GetFirstMip()->bm_boxBoundingBox, + FALSE, FALSE /* no directional */); + _penLightUpdating = NULL; + } + + // if it is zoning + if (en_ulFlags&ENF_ZONING) { + // FPU must be in 53-bit mode + CSetFPUPrecision FPUPrecision(FPT_53BIT); + + // for all brush mips + FOREACHINLIST(CBrushMip, bm_lnInBrush, en_pbrBrush->br_lhBrushMips, itbm) { + // for all sectors in the mip + {FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // find entities in sector + itbsc->FindEntitiesInSector(); + }} + } + } + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_SETPLACEMENT_BRUSHUPDATE); + } else if(en_RenderType==RT_TERRAIN) { + // Update terrain shadow map + CTerrain *ptrTerrain = GetTerrain(); + ASSERT(ptrTerrain!=NULL); + ptrTerrain->UpdateShadowMap(); + } + + // set spatial clasification + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_SETPLACEMENT_SPATIALUPDATE); + if (bNear) { + FindSectorsAroundEntityNear(); + } else { + FindSectorsAroundEntity(); + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_SETPLACEMENT_SPATIALUPDATE); + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_SETPLACEMENT_LIGHTUPDATE); + // if it is a light source + {CLightSource *pls = GetLightSource(); + if (pls!=NULL) { + // find all shadow maps that should have layers from this light source + pls->FindShadowLayers(FALSE); + // update shadow map on all terrains in world + pls->UpdateTerrains(plOld,en_plPlacement); + }} + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_SETPLACEMENT_LIGHTUPDATE); + + // move the entity to new position in collision grid + if (en_pciCollisionInfo!=NULL) { + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_SETPLACEMENT_COLLISIONUPDATE); + FLOATaabbox3D boxNew; + en_pciCollisionInfo->MakeBoxAtPlacement( + en_plPlacement.pl_PositionVector, en_mRotation, boxNew); + if (en_RenderType!=RT_BRUSH && en_RenderType!=RT_FIELDBRUSH) { + en_pwoWorld->MoveEntityInCollisionGrid( this, en_pciCollisionInfo->ci_boxCurrent, boxNew); + } + en_pciCollisionInfo->ci_boxCurrent = boxNew; + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_SETPLACEMENT_COLLISIONUPDATE); + } + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_SETPLACEMENT); + + // NOTE: this is outside profile because it uses recursion + + // for each child of this entity + {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { + CPlacement3D plNew = itenChild->en_plRelativeToParent; + plNew.RelativeToAbsoluteSmooth(en_plPlacement); + itenChild->SetPlacement(plNew); + }} +} +// this one is used in rendering - gets lerped placement between ticks +CPlacement3D CEntity::GetLerpedPlacement(void) const +{ + // if it has no parent + if (en_penParent==NULL) { + // no lerping + return en_plPlacement; + // if it has parent + } else { + // get lerped placement relative to parent + CPlacement3D plParentLerped = en_penParent->GetLerpedPlacement(); + CPlacement3D plLerped = en_plRelativeToParent; + plLerped.RelativeToAbsoluteSmooth(plParentLerped); + return plLerped; + } +} + +void CEntity::SetFlags(ULONG ulFlags) +{ + en_ulFlags = ulFlags; +} + +void CEntity::SetPhysicsFlags(ULONG ulFlags) +{ + // remember the new flags + en_ulPhysicsFlags = ulFlags; + + // cache eventual collision info + FindCollisionInfo(); +} + +void CEntity::SetCollisionFlags(ULONG ulFlags) +{ + // remember the new flags + en_ulCollisionFlags = ulFlags; + + // cache eventual collision info + FindCollisionInfo(); +} + +void CEntity::SetParent(CEntity *penNewParent) +{ + // if there is a parent already + if (en_penParent!=NULL) { + // remove from it + en_penParent = NULL; + en_lnInParent.Remove(); + } + + // if should set new parent + if (penNewParent!=NULL) { + // for each predecesor (parent) entity in the chain + for (CEntity *penPred=penNewParent; penPred!=NULL; penPred=penPred->en_penParent) { + // if self + if (penPred==this) { + // refuse to set parent + return; + } + } + + // set new parent + en_penParent = penNewParent; + penNewParent->en_lhChildren.AddTail(en_lnInParent); + // calculate relative placement + en_plRelativeToParent = en_plPlacement; + en_plRelativeToParent.AbsoluteToRelativeSmooth(en_penParent->en_plPlacement); + } +} + + +// find first child of given class +CEntity *CEntity::GetChildOfClass(const char *strClass) +{ + // for each child of this entity + {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { + // if it is of given class + if (IsOfClass(itenChild, strClass)) { + return itenChild; + } + }} + // not found + return NULL; +} + +/* + * Destroy this entity (entity must not be targetable). + */ +void CEntity::Destroy(void) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // if it is already destroyed + if (en_ulFlags&ENF_DELETED) { + // do nothing + return; + } + // if it is a light source + {CLightSource *pls = GetLightSource(); + if (pls!=NULL) { + // destroy all of its shadow layers + pls->DiscardShadowLayers(); + }} + // clean up the entity + End(); + SetDefaultProperties(); // this effectively clears all entity pointers! + + // unlink parent-child links + if (en_penParent != NULL) { + en_penParent = NULL; + en_lnInParent.Remove(); + } + {FORDELETELIST( CEntity, en_lnInParent, en_lhChildren, itenChild) { + itenChild->en_penParent = NULL; + itenChild->en_lnInParent.Remove(); + }} + + // set its flags to mark that it doesn't not exist anymore + en_ulFlags|=ENF_DELETED; + // make sure that no deleted entity can be alive + en_ulFlags&=~ENF_ALIVE; + // remove from all sectors + en_rdSectors.Clear(); + // remove from active entities in the world + en_pwoWorld->wo_cenEntities.Remove(this); + // remove the reference made by the entity itself (this can delete it!) + RemReference(); +} + + +FLOAT3D _vHandle; +CBrushPolygon *_pbpoNear; +CTerrain *_ptrTerrainNear; +FLOAT _fNearDistance; +FLOAT3D _vNearPoint; + +static void CheckPolygonForShadingInfo(CBrushPolygon &bpo) +{ + // if it is not a wall + if (bpo.bpo_ulFlags&(BPOF_INVISIBLE|BPOF_PORTAL) ) { + // skip it + return; + } + // if the polygon or it's entity are invisible + if (bpo.bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->en_ulFlags&ENF_HIDDEN) { + // skip it + return; + } + + const FLOATplane3D &plPolygon = bpo.bpo_pbplPlane->bpl_plAbsolute; + // find distance of the polygon plane from the handle + FLOAT fDistance = plPolygon.PointDistance(_vHandle); + // if it is behind the plane or further than nearest found + if (fDistance<0.0f || fDistance>_fNearDistance) { + // skip it + return; + } + // find projection of handle to the polygon plane + FLOAT3D vOnPlane = plPolygon.ProjectPoint(_vHandle); + // if it is not in the bounding box of polygon + const FLOATaabbox3D &boxPolygon = bpo.bpo_boxBoundingBox; + const FLOAT EPSILON = 0.01f; + if ( + (boxPolygon.Min()(1)-EPSILON>vOnPlane(1)) || + (boxPolygon.Max()(1)+EPSILONvOnPlane(2)) || + (boxPolygon.Max()(2)+EPSILONvOnPlane(3)) || + (boxPolygon.Max()(3)+EPSILONbpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + const FLOAT3D &vVertex1 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + // pass the edge to the intersector + isIntersector.AddEdge( + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2), + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2)); + } + + // if the point is not inside polygon + if (!isIntersector.IsIntersecting()) { + // skip it + return; + } + + // remember the polygon + _pbpoNear = &bpo; + _fNearDistance = fDistance; + _vNearPoint = vOnPlane; +} + +static void CheckTerrainForShadingInfo(CTerrain *ptrTerrain) +{ + ASSERT(ptrTerrain!=NULL); + ASSERT(ptrTerrain->tr_penEntity!=NULL); + CEntity *pen = ptrTerrain->tr_penEntity; + + FLOAT3D vTerrainNormal; + FLOAT3D vHitPoint; + FLOATplane3D plHitPlane; + vTerrainNormal = FLOAT3D(0,-1,0) * pen->en_mRotation; + FLOAT fDistance = TestRayCastHit(ptrTerrain,pen->en_mRotation,pen->en_plPlacement.pl_PositionVector, + _vHandle,_vHandle+vTerrainNormal,_fNearDistance,FALSE,plHitPlane,vHitPoint); + if(fDistance<_fNearDistance) { + _vNearPoint = vHitPoint; + _fNearDistance = fDistance; + _ptrTerrainNear = ptrTerrain; + } +} + +/* Find and remember shading info for this entity if invalid. */ +void CEntity::FindShadingInfo(void) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // if this entity can't even have shading info + if (en_psiShadingInfo==NULL) { + // do nothing + return; + } + + // if info is valid + if (en_ulFlags & ENF_VALIDSHADINGINFO) { + // !!! check if the polygon is still there ! + // do nothing + return; + } + en_ulFlags |= ENF_VALIDSHADINGINFO; + + en_psiShadingInfo->si_penEntity = this; + + // clear shading info + en_psiShadingInfo->si_pbpoPolygon = NULL; + en_psiShadingInfo->si_ptrTerrain = NULL; + if (en_psiShadingInfo->si_lnInPolygon.IsLinked()) { + en_psiShadingInfo->si_lnInPolygon.Remove(); + } + + // take reference point at handle of the model entity + _vHandle = en_plPlacement.pl_PositionVector; + // start infinitely far away + _pbpoNear = NULL; + _ptrTerrainNear = NULL; + _fNearDistance = UpperLimit(1.0f); + // if this is movable entity + if (en_ulPhysicsFlags&EPF_MOVABLE) { + // for each cached near polygon + CStaticStackArray &apbpo = ((CMovableEntity*)this)->en_apbpoNearPolygons; + for(INDEX iPolygon=0; iPolygonbsc_rsEntities, CEntity, en_rdSectors, pen) + if(pen->en_RenderType==CEntity::RT_TERRAIN) { + CheckTerrainForShadingInfo(pen->GetTerrain()); + } else if(pen->en_RenderType!=CEntity::RT_BRUSH && pen->en_RenderType!=CEntity::RT_FIELDBRUSH) { + break; + } + }} + ENDFOR} + + // if this is non-movable entity, or no polygon or terrain found so far + if (_pbpoNear==NULL && _ptrTerrainNear==NULL) { + // for each sector that this entity is in + {FOREACHSRCOFDST(en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // for each polygon in the sector + {FOREACHINSTATICARRAY(pbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + CBrushPolygon &bpo = *itbpo; + CheckPolygonForShadingInfo(bpo); + }} + ENDFOR} + } + + // if there is some polygon found + if( _pbpoNear!=NULL) { + // remember shading info + en_psiShadingInfo->si_pbpoPolygon = _pbpoNear; + _pbpoNear->bpo_lhShadingInfos.AddTail(en_psiShadingInfo->si_lnInPolygon); + en_psiShadingInfo->si_vNearPoint = _vNearPoint; + + CEntity *penWithPolygon = _pbpoNear->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + ASSERT(penWithPolygon!=NULL); + const FLOATmatrix3D &mPolygonRotation = penWithPolygon->en_mRotation; + const FLOAT3D &vPolygonTranslation = penWithPolygon->GetPlacement().pl_PositionVector; + + _vNearPoint = (_vNearPoint-vPolygonTranslation)*!mPolygonRotation; + + MEX2D vmexShadow; + _pbpoNear->bpo_mdShadow.GetTextureCoordinates( + _pbpoNear->bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, + _vNearPoint, vmexShadow); + CBrushShadowMap &bsm = _pbpoNear->bpo_smShadowMap; + INDEX iMipLevel = bsm.sm_iFirstMipLevel; + FLOAT fpixU = FLOAT(vmexShadow(1)+bsm.sm_mexOffsetX)*(1.0f/(1<si_pixShadowU = floor(fpixU); + en_psiShadingInfo->si_pixShadowV = floor(fpixV); + en_psiShadingInfo->si_fUDRatio = fpixU-en_psiShadingInfo->si_pixShadowU; + en_psiShadingInfo->si_fLRRatio = fpixV-en_psiShadingInfo->si_pixShadowV; + + // else if there is some terrain found + } else if(_ptrTerrainNear!=NULL) { + // remember shading info + en_psiShadingInfo->si_ptrTerrain = _ptrTerrainNear; + en_psiShadingInfo->si_vNearPoint = _vNearPoint; + + FLOAT2D vTc = CalculateShadingTexCoords(_ptrTerrainNear,_vNearPoint); + en_psiShadingInfo->si_pixShadowU = floor(vTc(1)); + en_psiShadingInfo->si_pixShadowV = floor(vTc(2)); + en_psiShadingInfo->si_fLRRatio = vTc(1) - en_psiShadingInfo->si_pixShadowU; + en_psiShadingInfo->si_fUDRatio = vTc(2) - en_psiShadingInfo->si_pixShadowV; + + _ptrTerrainNear->tr_lhShadingInfos.AddTail(en_psiShadingInfo->si_lnInPolygon); + } +} + +CBrushSector *CEntity::GetFirstSector(void) +{ + {FOREACHSRCOFDST(en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + return pbsc; + ENDFOR}; + return NULL; +} + +CBrushSector *CEntity::GetFirstSectorWithName(void) +{ + CBrushSector *pbscResult = NULL; + {FOREACHSRCOFDST(en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + if (pbsc->bsc_strName!="") { + pbscResult = pbsc; + break; + } + ENDFOR}; + return pbscResult; +} + +// max. distance between two spheres (as factor of radius of one sphere) +#define MIN_SPHEREDENSITY 1.0f + +CCollisionInfo::CCollisionInfo(const CCollisionInfo &ciOrg) +{ + ci_absSpheres = ciOrg.ci_absSpheres ; + ci_fMinHeight = ciOrg.ci_fMinHeight ; + ci_fMaxHeight = ciOrg.ci_fMaxHeight ; + ci_fHandleY = ciOrg.ci_fHandleY ; + ci_fHandleR = ciOrg.ci_fHandleR ; + ci_boxCurrent = ciOrg.ci_boxCurrent ; + ci_ulFlags = ciOrg.ci_ulFlags ; +} +/* Create collision info for a model. */ +void CCollisionInfo::FromModel(CEntity *penModel, INDEX iBox) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // get collision box information from the model + FLOATaabbox3D boxModel; + INDEX iBoxType; + penModel->GetCollisionBoxParameters(iBox, boxModel, iBoxType); + FLOAT3D vBoxOffset = boxModel.Center(); + FLOAT3D vBoxSize = boxModel.Size(); + +// ASSERT(iBoxType==LENGHT_EQ_WIDTH); + ci_ulFlags = 0; + + INDEX iAxisMain; // in which direction are spheres set + INDEX iAxis1, iAxis2; // other axis + + if (iBoxType==LENGTH_EQ_WIDTH) { + iAxisMain = 2; + iAxis1 = 1; iAxis2 = 3; + } else if (iBoxType==HEIGHT_EQ_WIDTH) { + iAxisMain = 3; + iAxis1 = 2; iAxis2 = 1; + } else if (iBoxType==LENGTH_EQ_HEIGHT) { + iAxisMain = 1; + iAxis1 = 2; iAxis2 = 3; + } else { + ASSERTALWAYS("Invalid collision box"); + iAxisMain = 2; + iAxis1 = 1; iAxis2 = 3; + } + + // calculate radius of one sphere + FLOAT fSphereRadius = vBoxSize(iAxis1)/2.0f; + // calculate length along which to set spheres + FLOAT fSphereCentersSpan = vBoxSize(iAxisMain)-fSphereRadius*2; + // calculate number of spheres to use + INDEX ctSpheres = 0; + if (fSphereRadius>0.0001f) { + ctSpheres = INDEX(ceil(fSphereCentersSpan/(fSphereRadius*MIN_SPHEREDENSITY)))+1; + } + if (ctSpheres==0) { + ctSpheres=1; + } + // calculate how far from each other to set sphere centers + FLOAT fSphereCentersDistance; + if (ctSpheres==1) { + fSphereCentersDistance = 0.0f; + } else { + fSphereCentersDistance = fSphereCentersSpan/(FLOAT)(ctSpheres-1); + } + + // calculate coordinates for spreading sphere centers + FLOAT fSphereCenterX = vBoxOffset(iAxis1); + FLOAT fSphereCenterZ = vBoxOffset(iAxis2); + FLOAT fSphereCenterY0 = vBoxOffset(iAxisMain)-(vBoxSize(iAxisMain)/2.0f)+fSphereRadius; + FLOAT fSphereCenterKY = fSphereCentersDistance; + + ci_fMinHeight = boxModel.Min()(2); + ci_fMaxHeight = boxModel.Max()(2); + ci_fHandleY = UpperLimit(1.0f); + // create needed number of spheres in the array + ci_absSpheres.Clear(); + ci_absSpheres.New(ctSpheres); + // for each sphere + for(INDEX iSphere=0; iSphereGetFirstMip(); + // for each sector in the brush mip + {FOREACHINDYNAMICARRAY(pbm->bm_abscSectors, CBrushSector, itbsc) { + // for each vertex in the sector + {FOREACHINSTATICARRAY(itbsc->bsc_abvxVertices, CBrushVertex, itbvx) { + CBrushVertex &bvx = *itbvx; + // add it to bounding box + box |= DOUBLEtoFLOAT(bvx.bvx_vdPreciseRelative); + }} + }} + + // create a sphere from the relative box + ci_absSpheres[0].ms_vCenter = box.Center(); + ci_absSpheres[0].ms_fR = box.Size().Length()/2; + ci_fMinHeight = UpperLimit(1.0f); + ci_fMaxHeight = LowerLimit(1.0f); + ci_fHandleY = 0.0f; + ci_fHandleR = 1.0f; +} + +/* Calculate current bounding box in absolute space from position. */ +void CCollisionInfo::MakeBoxAtPlacement(const FLOAT3D &vPosition, const FLOATmatrix3D &mRotation, + FLOATaabbox3D &box) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + CMovingSphere &ms0 = ci_absSpheres[0]; + CMovingSphere &ms1 = ci_absSpheres[ci_absSpheres.Count()-1]; + box = FLOATaabbox3D(vPosition+ms0.ms_vCenter*mRotation, ms0.ms_fR); + box |= FLOATaabbox3D(vPosition+ms1.ms_vCenter*mRotation, ms1.ms_fR); +} + +// get maximum radius of entity in xz plane (relative to entity handle) +FLOAT CCollisionInfo::GetMaxFloorRadius(void) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // get first and last sphere + CMovingSphere &ms0 = ci_absSpheres[0]; + CMovingSphere &ms1 = ci_absSpheres[ci_absSpheres.Count()-1]; + // get their positions in xz plane + FLOAT3D vPosXZ0 = ms0.ms_vCenter; + FLOAT3D vPosXZ1 = ms1.ms_vCenter; + vPosXZ0(2) = 0.0f; + vPosXZ1(2) = 0.0f; + // return maximum distance from the handle in xz plane + return Max( + vPosXZ0.Length()+ms0.ms_fR, + vPosXZ1.Length()+ms1.ms_fR); +} + + +/* Find and remember collision info for this entity. */ +void CEntity::FindCollisionInfo(void) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // discard eventual collision info + DiscardCollisionInfo(); + + // if the entity is colliding + if (en_ulCollisionFlags&ECF_TESTMASK) { + // if it is a model + if ((en_RenderType==RT_MODEL||en_RenderType==RT_EDITORMODEL) + &&(en_pmoModelObject->GetData()!=NULL)) { + // cache its new collision info + en_pciCollisionInfo = new CCollisionInfo; + en_pciCollisionInfo->FromModel(this, GetCollisionBoxIndex()); + } else if ((en_RenderType==RT_SKAMODEL||en_RenderType==RT_SKAEDITORMODEL) + &&(GetModelInstance()!=NULL)) { + // cache its new collision info + en_pciCollisionInfo = new CCollisionInfo; + en_pciCollisionInfo->FromModel(this, GetCollisionBoxIndex()); + // if it is a brush + } else if (en_RenderType==RT_BRUSH) { + // if it is zoning brush and non movable + if ((en_ulFlags&ENF_ZONING) && !(en_ulPhysicsFlags&EPF_MOVABLE)) { + // do nothing + return; + } + // cache its new collision info + en_pciCollisionInfo = new CCollisionInfo; + en_pciCollisionInfo->FromBrush(en_pbrBrush); + // if it is a field brush + } else if (en_RenderType==RT_FIELDBRUSH) { + // cache its new collision info + en_pciCollisionInfo = new CCollisionInfo; + en_pciCollisionInfo->FromBrush(en_pbrBrush); + return; + } else if (en_RenderType==RT_TERRAIN) { + return; + } else { + return; + } + // add entity to collision grid + FLOATaabbox3D boxNew; + en_pciCollisionInfo->MakeBoxAtPlacement( + en_plPlacement.pl_PositionVector, en_mRotation, boxNew); + if (en_RenderType!=RT_BRUSH && en_RenderType!=RT_FIELDBRUSH) { + en_pwoWorld->AddEntityToCollisionGrid(this, boxNew); + } + en_pciCollisionInfo->ci_boxCurrent = boxNew; + } +} +// discard collision info for this entity +void CEntity::DiscardCollisionInfo(void) +{ + // if there was any collision info + if (en_pciCollisionInfo!=NULL) { + // remove entity from collision grid + if (en_RenderType!=RT_BRUSH && en_RenderType!=RT_FIELDBRUSH) { + en_pwoWorld->RemoveEntityFromCollisionGrid(this, en_pciCollisionInfo->ci_boxCurrent); + } + // free it + delete en_pciCollisionInfo; + en_pciCollisionInfo = NULL; + } + // movable entity + if (en_ulPhysicsFlags & EPF_MOVABLE) { + ((CMovableEntity*)this)->ClearTemporaryData(); + } +} +// copy collision info from some other entity +void CEntity::CopyCollisionInfo(CEntity &enOrg) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // if there is no collision info + if (enOrg.en_pciCollisionInfo==NULL) { + // do nothing + en_pciCollisionInfo = NULL; + return; + } + // create info and copy it + en_pciCollisionInfo = new CCollisionInfo(*enOrg.en_pciCollisionInfo); + // add entity to collision grid + FLOATaabbox3D boxNew; + en_pciCollisionInfo->MakeBoxAtPlacement( + en_plPlacement.pl_PositionVector, en_mRotation, boxNew); + if (en_RenderType!=RT_BRUSH && en_RenderType!=RT_FIELDBRUSH) { + en_pwoWorld->AddEntityToCollisionGrid(this, boxNew); + } + en_pciCollisionInfo->ci_boxCurrent = boxNew; +} + +/* Get box and sphere for spatial clasification. */ +void CEntity::UpdateSpatialRange(void) +{ + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + en_fSpatialClassificationRadius = -1.0f; + + // if zoning + if (en_ulFlags&ENF_ZONING) { + // do nothing + return; + } + + FLOATaabbox3D box; + FLOATaabbox3D boxStretched; + // get bounding box of the entity + // is this old model + if (en_RenderType==CEntity::RT_MODEL + ||en_RenderType==CEntity::RT_EDITORMODEL) { + en_pmoModelObject->GetAllFramesBBox(box); + box.StretchByVector(en_pmoModelObject->mo_Stretch); + FLOAT3D fClassificationStretch = GetClassificationBoxStretch(); + boxStretched = box; + boxStretched .StretchByVector( fClassificationStretch); + en_boxSpatialClassification = boxStretched; + // is this ska model + } else if (en_RenderType==CEntity::RT_SKAMODEL + || en_RenderType==RT_SKAEDITORMODEL) { + GetModelInstance()->GetAllFramesBBox(box); + box.StretchByVector(GetModelInstance()->mi_vStretch); + FLOAT3D fClassificationStretch = GetClassificationBoxStretch(); + boxStretched = box; + boxStretched.StretchByVector( fClassificationStretch); + en_boxSpatialClassification = boxStretched; + // is this brush + } else if (en_RenderType==CEntity::RT_BRUSH || en_RenderType==RT_FIELDBRUSH) { + box = en_pbrBrush->GetFirstMip()->bm_boxRelative; + boxStretched = box; + en_boxSpatialClassification = box; + // is this terrain + } else if (en_RenderType==CEntity::RT_TERRAIN) { + GetTerrain()->GetAllTerrainBBox(box); + boxStretched = box; + en_boxSpatialClassification = box; + } else { + return; // sound entities are not related to sectors !!!! + } + en_fSpatialClassificationRadius = Max( box.Min().Length(), box.Max().Length() ); + ASSERT(IsValidFloat(en_fSpatialClassificationRadius)); +} + +/* Find and remember all sectors that this entity is in. */ +void CEntity::FindSectorsAroundEntity(void) +{ + CSetFPUPrecision sfp(FPT_53BIT); + + // if not in spatial clasification + if (en_fSpatialClassificationRadius<0) { + // do nothing + return; + } + // get bounding sphere and box of entity + FLOAT fSphereRadius = en_fSpatialClassificationRadius; + const FLOAT3D &vSphereCenter = en_plPlacement.pl_PositionVector; + // make oriented bounding box of the entity + FLOATobbox3D boxEntity = FLOATobbox3D(en_boxSpatialClassification, + en_plPlacement.pl_PositionVector, en_mRotation); + DOUBLEobbox3D boxdEntity = FLOATtoDOUBLE(boxEntity); + + // unset spatial clasification + en_rdSectors.Clear(); + + // for each brush in the world + FOREACHINDYNAMICARRAY(en_pwoWorld->wo_baBrushes.ba_abrBrushes, CBrush3D, itbr) { + CBrush3D &br=*itbr; + // if the brush entity is not zoning + if (itbr->br_penEntity==NULL || !(itbr->br_penEntity->en_ulFlags&ENF_ZONING)) { + // skip it + continue; + } + // for each mip in the brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, itbr->br_lhBrushMips, itbm) { + // for each sector in the brush mip + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // if the sector's bounding box has contact with the sphere + if(itbsc->bsc_boxBoundingBox.TouchesSphere(vSphereCenter, fSphereRadius) + // and with the box + && boxEntity.HasContactWith(FLOATobbox3D(itbsc->bsc_boxBoundingBox))) { + + // if the sphere is inside the sector + if (itbsc->bsc_bspBSPTree.TestSphere( + FLOATtoDOUBLE(vSphereCenter), FLOATtoDOUBLE(fSphereRadius))>=0) { + + // if the box is inside the sector + if (itbsc->bsc_bspBSPTree.TestBox(boxdEntity)>=0) { + // relate the entity to the sector + if (en_RenderType==RT_BRUSH + ||en_RenderType==RT_FIELDBRUSH + ||en_RenderType==RT_TERRAIN) { // brushes first + AddRelationPairHeadHead(itbsc->bsc_rsEntities, en_rdSectors); + } else { + AddRelationPairTailTail(itbsc->bsc_rsEntities, en_rdSectors); + } + } + } + } + } + } + } +} + +void CEntity::FindSectorsAroundEntityNear(void) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // if not in spatial clasification + if (en_fSpatialClassificationRadius<0) { + // do nothing + return; + } + // this may be called only for movable entities + ASSERT(en_ulPhysicsFlags&EPF_MOVABLE); + CMovableEntity *pen = (CMovableEntity *)this; + + // get bounding sphere and box of entity + FLOAT fSphereRadius = en_fSpatialClassificationRadius; + const FLOAT3D &vSphereCenter = en_plPlacement.pl_PositionVector; + FLOATaabbox3D boxEntity(vSphereCenter, fSphereRadius); + // make oriented bounding box of the entity + FLOATobbox3D oboxEntity = FLOATobbox3D(en_boxSpatialClassification, + en_plPlacement.pl_PositionVector, en_mRotation); + DOUBLEobbox3D oboxdEntity = FLOATtoDOUBLE(oboxEntity); + + CListHead lhActive; + // for each sector around this entity + {FOREACHSRCOFDST(en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // remember its link + pbsc->bsc_prlLink = pbsc_iter; + // add it to list of active sectors + lhActive.AddTail(pbsc->bsc_lnInActiveSectors); + ENDFOR} + + CStaticStackArray &apbpo = pen->en_apbpoNearPolygons; + // for each cached polygon + for(INDEX iPolygon=0; iPolygonbpo_pbscSector; + // add its sector if not already added, and has BSP (is zoning) + if (!pbsc->bsc_lnInActiveSectors.IsLinked() && pbsc->bsc_bspBSPTree.bt_pbnRoot!=NULL) { + lhActive.AddTail(pbsc->bsc_lnInActiveSectors); + pbsc->bsc_prlLink = NULL; + } + } + + // for each active sector + FOREACHINLIST(CBrushSector, bsc_lnInActiveSectors, lhActive, itbsc) { + CBrushSector *pbsc = itbsc; + // test if entity is in sector + BOOL bIn = + // the sector's bounding box has contact with given bounding box, + (pbsc->bsc_boxBoundingBox.HasContactWith(boxEntity))&& + // the sphere is inside the sector + (pbsc->bsc_bspBSPTree.TestSphere( + FLOATtoDOUBLE(vSphereCenter), FLOATtoDOUBLE(fSphereRadius))>=0)&& + // (use more detailed testing for moving brushes) + (en_RenderType!=RT_BRUSH|| + // oriented box touches box of sector + (oboxEntity.HasContactWith(FLOATobbox3D(pbsc->bsc_boxBoundingBox)))&& + // oriented box is in bsp + (pbsc->bsc_bspBSPTree.TestBox(oboxdEntity)>=0)); + // if it is not + if (!bIn) { + // if it has link + if (pbsc->bsc_prlLink!=NULL) { + // remove link to that sector + delete pbsc->bsc_prlLink; + pbsc->bsc_prlLink = NULL; + } + // if it is + } else { + // if it doesn't have link + if (pbsc->bsc_prlLink==NULL) { + // add the link + if (en_RenderType==RT_BRUSH + ||en_RenderType==RT_FIELDBRUSH + ||en_RenderType==RT_TERRAIN) { // brushes first + AddRelationPairHeadHead(pbsc->bsc_rsEntities, en_rdSectors); + } else { + AddRelationPairTailTail(pbsc->bsc_rsEntities, en_rdSectors); + } + } + } + } + + // clear list of active sectors + {FORDELETELIST(CBrushSector, bsc_lnInActiveSectors, lhActive, itbsc) { + itbsc->bsc_prlLink = NULL; + itbsc->bsc_lnInActiveSectors.Remove(); + }} + ASSERT(lhActive.IsEmpty()); + + // if there is no link found + if (en_rdSectors.IsEmpty()) { + // test with brute force algorithm + FindSectorsAroundEntity(); + } +} + +/* + * Uncache shadows of each polygon that has given gradient index + */ +void CEntity::UncacheShadowsForGradient(INDEX iGradient) +{ + if(en_RenderType != CEntity::RT_BRUSH) + { + ASSERTALWAYS("Uncache shadows for gradient called on non-brush entity!"); + return; + } + + // for all brush mips + FOREACHINLIST(CBrushMip, bm_lnInBrush, en_pbrBrush->br_lhBrushMips, itbm) + { + // for all sectors in the mip + {FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) + { + // for all polygons in this sector + {FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) + { + // if the polygon has shadows + if (itbpo->bpo_bppProperties.bpp_ubGradientType == iGradient) + { + // uncache shadows + itbpo->bpo_smShadowMap.Uncache(); + } + }} + }} + } +} + +/* + * Get state transition for given state and event code. + */ +CEntity::pEventHandler CEntity::HandlerForStateAndEvent(SLONG slState, SLONG slEvent) +{ + // find translation in the translation table of the DLL class + return en_pecClass->HandlerForStateAndEvent(slState, slEvent); +} + +/* + * Handle an event - return false if event was not handled. + */ +BOOL CEntity::HandleEvent(const CEntityEvent &ee) +{ + /* + By default, base entities ignore all events. + Events are handled by classes derived from CRationalEntity using state stack. + + Anyway, it is possible to override this in some class if some other way + of event handling is desired. + */ + + return FALSE; +} + +///////////////////////////////////////////////////////////////////// +// Event posting system + +class CSentEvent { +public: + CEntityPointer se_penEntity; + CEntityEvent *se_peeEvent; + inline void Clear(void) { se_penEntity = NULL; } +}; + +static CStaticStackArray _aseSentEvents; // delayed events +/* Send an event to this entity. */ +void CEntity::SendEvent(const CEntityEvent &ee) +{ + if (this==NULL) { + ASSERT(FALSE); + return; + } + CSentEvent &se = _aseSentEvents.Push(); + se.se_penEntity = this; + se.se_peeEvent = ((CEntityEvent&)ee).MakeCopy(); // discard const qualifier +} + +// find entities in a box (box must be around this entity) +void CEntity::FindEntitiesInRange( + const FLOATaabbox3D &boxRange, CDynamicContainer &cen, BOOL bCollidingOnly) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // for each entity in the world of this entity + FOREACHINDYNAMICCONTAINER(en_pwoWorld->wo_cenEntities, CEntity, iten) { + // if it is zoning brush entity + if (iten->en_RenderType == CEntity::RT_BRUSH && (iten->en_ulFlags&ENF_ZONING)) { + // get first mip in its brush + CBrushMip *pbm = iten->en_pbrBrush->GetFirstMip(); + // if the mip doesn't touch the box + if (!pbm->bm_boxBoundingBox.HasContactWith(boxRange)) { + // skip it + continue; + } + + // for all sectors in this mip + FOREACHINDYNAMICARRAY(pbm->bm_abscSectors, CBrushSector, itbsc) { + // if the sector doesn't touch the box + if (!itbsc->bsc_boxBoundingBox.HasContactWith(boxRange)) { + // skip it + continue; + } + + // for all entities in the sector + {FOREACHDSTOFSRC(itbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) + // if the model entity touches the box + if ((pen->en_RenderType==RT_MODEL || pen->en_RenderType==RT_EDITORMODEL) + && boxRange.HasContactWith( + FLOATaabbox3D(pen->GetPlacement().pl_PositionVector, pen->en_fSpatialClassificationRadius))) { + + // if it has collision box + if (pen->en_pciCollisionInfo!=NULL) { + // for each sphere + FOREACHINSTATICARRAY(pen->en_pciCollisionInfo->ci_absSpheres, CMovingSphere, itms) { + // project it + itms->ms_vRelativeCenter0 = itms->ms_vCenter*pen->en_mRotation+pen->en_plPlacement.pl_PositionVector; + // if the sphere touches the range + if (boxRange.HasContactWith(FLOATaabbox3D(itms->ms_vRelativeCenter0, itms->ms_fR))) { + // add it to container + if (!cen.IsMember(pen)) { + cen.Add(pen); + } + goto next_entity; + } + } + // if no collision box, but non-colliding are allowed + } else if (!bCollidingOnly) { + // add it to container + if (!cen.IsMember(pen)) { + cen.Add(pen); + } + } + // if the brush entity touches the box + } else if (pen->en_RenderType==RT_BRUSH && + boxRange.HasContactWith( + FLOATaabbox3D(pen->GetPlacement().pl_PositionVector, pen->en_fSpatialClassificationRadius))) { + // if the brush touches the box + if (boxRange.HasContactWith(pen->en_pbrBrush->GetFirstMip()->bm_boxBoundingBox)) { + // add it to container + if (!cen.IsMember(pen)) { + cen.Add(pen); + } + } + } else if ((pen->en_RenderType==RT_SKAMODEL || pen->en_RenderType==RT_SKAEDITORMODEL) + && boxRange.HasContactWith( + FLOATaabbox3D(pen->GetPlacement().pl_PositionVector, pen->en_fSpatialClassificationRadius))) { + // if it has collision box + if (pen->en_pciCollisionInfo!=NULL) { + // for each sphere + FOREACHINSTATICARRAY(pen->en_pciCollisionInfo->ci_absSpheres, CMovingSphere, itms) { + // project it + itms->ms_vRelativeCenter0 = itms->ms_vCenter*pen->en_mRotation+pen->en_plPlacement.pl_PositionVector; + // if the sphere touches the range + if (boxRange.HasContactWith(FLOATaabbox3D(itms->ms_vRelativeCenter0, itms->ms_fR))) { + // add it to container + if (!cen.IsMember(pen)) { + cen.Add(pen); + } + goto next_entity; + } + } + // if no collision box, but non-colliding are allowed + } else if (!bCollidingOnly) { + // add it to container + if (!cen.IsMember(pen)) { + cen.Add(pen); + } + } + } + next_entity:; + ENDFOR} + } + } + } +} + +/* Send an event to all entities in a box (box must be around this entity). */ +void CEntity::SendEventInRange(const CEntityEvent &ee, const FLOATaabbox3D &boxRange) +{ + // find entities in the range + CDynamicContainer cenToReceive; + FindEntitiesInRange(boxRange, cenToReceive, FALSE); + + // for each entity in container + FOREACHINDYNAMICCONTAINER(cenToReceive, CEntity, iten) { + // send the event to it + iten->SendEvent(ee); + } +} + +/* Handle all sent events. */ +void CEntity::HandleSentEvents(void) +{ + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // while there are any unhandled events + INDEX iFirstEvent = 0; + while (iFirstEvent<_aseSentEvents.Count()) { + CSentEvent &se = _aseSentEvents[iFirstEvent]; + // if not allowed to execute now + if (!se.se_penEntity->IsAllowedForPrediction()) { + // skip it + iFirstEvent++; + continue; + } + // if the entity is not destroyed + if (!(se.se_penEntity->en_ulFlags&ENF_DELETED)) { + // handle the current event + se.se_penEntity->HandleEvent(*se.se_peeEvent); + } + // go to next event + iFirstEvent++; + } + + // for each event + for(INDEX iee=0; iee<_aseSentEvents.Count(); iee++) { + CSentEvent &se = _aseSentEvents[iee]; + // release the entity and destroy the event + se.se_penEntity = NULL; + delete se.se_peeEvent; + se.se_peeEvent = NULL; + } + + // flush all events + _aseSentEvents.PopAll(); +} + +///////////////////////////////////////////////////////////////////// +// DLL class interface + +/* Initialize for being virtual entity that is not rendered. */ +void CEntity::InitAsVoid(void) +{ + en_RenderType = RT_VOID; + en_pbrBrush = NULL; +} +/* + * Initialize for beeing a model object. + */ +void CEntity::InitAsModel(void) +{ + // set render type to model + en_RenderType = RT_MODEL; + // create a model object + en_pmoModelObject = new CModelObject; + en_psiShadingInfo = new CShadingInfo; + en_ulFlags &= ~ENF_VALIDSHADINGINFO; +} +/* + * Initialize for beeing a ska model object. + */ +void CEntity::InitAsSkaModel(void) +{ + en_RenderType = RT_SKAMODEL; + en_psiShadingInfo = new CShadingInfo; + en_ulFlags &= ~ENF_VALIDSHADINGINFO; +} + +/* + * Initialize for beeing a terrain object. + */ +void CEntity::InitAsTerrain(void) +{ + en_RenderType = RT_TERRAIN; + // if there is no existing terrain + if(en_ptrTerrain == NULL) { + // create a new empty terrain in the brush archive of current world + en_ptrTerrain = en_pwoWorld->wo_taTerrains.ta_atrTerrains.New(); + en_ptrTerrain->tr_penEntity = this; + + // Create empty terrain + en_ptrTerrain->CreateEmptyTerrain_t(257,257); + en_ptrTerrain->SetTerrainSize(FLOAT3D(256,50,256)); + en_ptrTerrain->SetShadowMapsSize(0,0); + en_ptrTerrain->UpdateShadowMap(); + } + UpdateSpatialRange(); +} + +/* + * Initialize for beeing a model object, for editor only. + */ +void CEntity::InitAsEditorModel(void) +{ + // set render type to model + en_RenderType = RT_EDITORMODEL; + // create a model object + en_pmoModelObject = new CModelObject; + en_psiShadingInfo = new CShadingInfo; + en_ulFlags &= ~ENF_VALIDSHADINGINFO; +} +/* + * Initialize for beeing a ska model object, for editor only. + */ +void CEntity::InitAsSkaEditorModel(void) +{ + // set render type to model + en_RenderType = RT_SKAEDITORMODEL; + // create a model object + en_psiShadingInfo = new CShadingInfo; + en_ulFlags &= ~ENF_VALIDSHADINGINFO; +} +/* + * Initialize for beeing a brush object. + */ +void CEntity::InitAsBrush(void) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // set render type to brush + en_RenderType = RT_BRUSH; + // if there is no existing brush + if (en_pbrBrush == NULL) { + // create a new empty brush in the brush archive of current world + en_pbrBrush = en_pwoWorld->wo_baBrushes.ba_abrBrushes.New(); + en_pbrBrush->br_penEntity = this; + // create a brush mip for it + CBrushMip *pbmMip = new CBrushMip; + // add it to list + en_pbrBrush->br_lhBrushMips.AddTail(pbmMip->bm_lnInBrush); + // set back-pointer to the brush + pbmMip->bm_pbrBrush = en_pbrBrush; + en_pbrBrush->CalculateBoundingBoxes(); + } + UpdateSpatialRange(); +} + +/* + * Initialize for beeing a field brush object. + */ +void CEntity::InitAsFieldBrush(void) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // set render type to brush + en_RenderType = RT_FIELDBRUSH; + // if there is no existing brush + if (en_pbrBrush == NULL) { + // create a new empty brush in the brush archive of current world + en_pbrBrush = en_pwoWorld->wo_baBrushes.ba_abrBrushes.New(); + en_pbrBrush->br_penEntity = this; + // create a brush mip for it + CBrushMip *pbmMip = new CBrushMip; + // add it to list + en_pbrBrush->br_lhBrushMips.AddTail(pbmMip->bm_lnInBrush); + // set back-pointer to the brush + pbmMip->bm_pbrBrush = en_pbrBrush; + en_pbrBrush->CalculateBoundingBoxes(); + } + UpdateSpatialRange(); +} + +/* + * Switch to Model/Editor model + */ +void CEntity::SwitchToModel(void) +{ + // change to editor model + if(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL) { + en_RenderType = RT_MODEL; + } else if( en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL) { + en_RenderType = RT_SKAMODEL; + } else { + // it must be model (not brush) + ASSERT(FALSE); + } +} +void CEntity::SwitchToEditorModel(void) +{ + // change to editor model + if(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL) { + en_RenderType = RT_EDITORMODEL; + } else if( en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL) { + en_RenderType = RT_SKAEDITORMODEL; + } else { + // it must be model (not brush) + ASSERT(FALSE); + } +} + +///////////////////////////////////////////////////////////////////// +// Model manipulation +/* Set the model data for model entity. */ +void CEntity::SetModel(const CTFileName &fnmModel) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + // try to + try { + // load the new model data + en_pmoModelObject->SetData_t(fnmModel); + // if failed + } catch(char *strError) { + (void)strError; + DECLARE_CTFILENAME(fnmDefault, "Models\\Editor\\Axis.mdl"); + // try to + try { + // load the default model data + en_pmoModelObject->SetData_t(fnmDefault); + // if failed + } catch(char *strErrorDefault) { + FatalError(TRANS("Cannot load default model '%s':\n%s"), + (CTString&)fnmDefault, strErrorDefault); + } + } + UpdateSpatialRange(); + FindCollisionInfo(); +} + +void CEntity::SetModel(SLONG idModelComponent) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + CEntityComponent *pecModel = en_pecClass->ComponentForTypeAndID( + ECT_MODEL, idModelComponent); + en_pmoModelObject->SetData(pecModel->ec_pmdModel); + UpdateSpatialRange(); + FindCollisionInfo(); +} + +void CEntity::SetSkaColisionInfo() +{ + ASSERT(en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL); + // if there is no colision boxes for ska model + if(en_pmiModelInstance->mi_cbAABox.Count() == 0) { + // add one default colision box + en_pmiModelInstance->AddColisionBox("Default",FLOAT3D(-0.5,0,-0.5),FLOAT3D(0.5,2,0.5)); + } + UpdateSpatialRange(); + FindCollisionInfo(); +} + +void CEntity::SetSkaModel_t(const CTString &fnmModel) +{ + ASSERT(en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL); + // if model instance allready exists + if(en_pmiModelInstance!=NULL) { + // release it first + en_pmiModelInstance->Clear(); + } + try { + // load the new model data + en_pmiModelInstance = ParseSmcFile_t(fnmModel); + } catch (char *strErrorDefault) { + throw(strErrorDefault); + } + SetSkaColisionInfo(); +} +BOOL CEntity::SetSkaModel(const CTString &fnmModel) +{ + ASSERT(en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL); + // try to + try { + SetSkaModel_t(fnmModel); + // if failed + } catch(char *strError) { + (void)strError; + WarningMessage("%s\n\rLoading default model.\n", strError); + DECLARE_CTFILENAME(fnmDefault, "Models\\Editor\\Ska\\Axis.smc"); + // try to + try { + // load the default model data + en_pmiModelInstance = ParseSmcFile_t(fnmDefault); + // if failed + } catch(char *strErrorDefault) { + FatalError(TRANS("Cannot load default model '%s':\n%s"), + (CTString&)fnmDefault, strErrorDefault); + } + // set colision info for default model + SetSkaColisionInfo(); + return FALSE; + } + return TRUE; +} +// set/get model main blend color + +void CEntity::SetModelColor( const COLOR colBlend) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + en_pmoModelObject->mo_colBlendColor = colBlend; +} + +COLOR CEntity::GetModelColor(void) const +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + return en_pmoModelObject->mo_colBlendColor; +} + + +/* Get the model data for model entity. */ + +const CTFileName &CEntity::GetModel(void) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + return ((CAnimData*)en_pmoModelObject->GetData())->GetName(); +} +/* Start new animation for model entity. */ +void CEntity::StartModelAnim(INDEX iNewModelAnim, ULONG ulFlags) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + en_pmoModelObject->PlayAnim(iNewModelAnim, ulFlags); +} + +/* Set the main texture data for model entity. */ +void CEntity::SetModelMainTexture(const CTFileName &fnmTexture) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + // try to + try { + // load the texture data + en_pmoModelObject->mo_toTexture.SetData_t(fnmTexture); + + // if failed + } catch(char *strError) { + (void)strError; + DECLARE_CTFILENAME(fnmDefault, "Textures\\Editor\\Default.tex"); + // try to + try { + // load the default model data + en_pmoModelObject->mo_toTexture.SetData_t(fnmDefault); + // if failed + } catch(char *strErrorDefault) { + FatalError(TRANS("Cannot load default texture '%s':\n%s"), + (CTString&)fnmDefault, strErrorDefault); + } + } +} +void CEntity::SetModelMainTexture(SLONG idTextureComponent) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + CEntityComponent *pecTexture = en_pecClass->ComponentForTypeAndID( + ECT_TEXTURE, idTextureComponent); + en_pmoModelObject->mo_toTexture.SetData(pecTexture->ec_ptdTexture); +} +/* Get the main texture data for model entity. */ +const CTFileName &CEntity::GetModelMainTexture(void) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + return en_pmoModelObject->mo_toTexture.GetData()->GetName(); +} +/* Start new animation for main texture of model entity. */ +void CEntity::StartModelMainTextureAnim(INDEX iNewTextureAnim) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + en_pmoModelObject->mo_toTexture.StartAnim(iNewTextureAnim); +} + +/* Set the reflection texture data for model entity. */ +void CEntity::SetModelReflectionTexture(SLONG idTextureComponent) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + CEntityComponent *pecTexture = en_pecClass->ComponentForTypeAndID( + ECT_TEXTURE, idTextureComponent); + en_pmoModelObject->mo_toReflection.SetData(pecTexture->ec_ptdTexture); +} +/* Set the specular texture data for model entity. */ +void CEntity::SetModelSpecularTexture(SLONG idTextureComponent) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + CEntityComponent *pecTexture = en_pecClass->ComponentForTypeAndID( + ECT_TEXTURE, idTextureComponent); + en_pmoModelObject->mo_toSpecular.SetData(pecTexture->ec_ptdTexture); +} + +/* Add attachment to model */ +void CEntity::AddAttachment(INDEX iAttachment, ULONG ulIDModel, ULONG ulIDTexture) +{ + // add attachment + CModelObject &mo = en_pmoModelObject->AddAttachmentModel(iAttachment)->amo_moModelObject; + // update model data + CEntityComponent *pecWeaponModel = ComponentForTypeAndID( ECT_MODEL, ulIDModel); + mo.SetData(pecWeaponModel->ec_pmdModel); + // update texture data if different + CEntityComponent *pecWeaponTexture = ComponentForTypeAndID( ECT_TEXTURE, ulIDTexture); + mo.SetTextureData(pecWeaponTexture->ec_ptdTexture); +} +void CEntity::AddAttachment(INDEX iAttachment, CTFileName fnModel, CTFileName fnTexture) +{ + if( fnModel == CTString("")) return; + CModelObject *pmo = GetModelObject(); + ASSERT( pmo != NULL); + if( pmo == NULL) return; + + CAttachmentModelObject *pamo = pmo->AddAttachmentModel( iAttachment); + try + { + pamo->amo_moModelObject.SetData_t( fnModel); + } + catch(char *strError) + { + (void) strError; + pmo->RemoveAttachmentModel( iAttachment); + return; + } + + try + { + pamo->amo_moModelObject.mo_toTexture.SetData_t( fnTexture); + } + catch(char *strError) + { + (void) strError; + } +} +/* Set the reflection texture data for attachment model entity. */ +void CEntity::SetModelAttachmentReflectionTexture(INDEX iAttachment, SLONG idTextureComponent) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + CModelObject &mo = en_pmoModelObject->GetAttachmentModel(iAttachment)->amo_moModelObject; + CEntityComponent *pecTexture = en_pecClass->ComponentForTypeAndID( + ECT_TEXTURE, idTextureComponent); + mo.mo_toReflection.SetData(pecTexture->ec_ptdTexture); +} +/* Set the specular texture data for attachment model entity. */ +void CEntity::SetModelAttachmentSpecularTexture(INDEX iAttachment, SLONG idTextureComponent) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL); + CModelObject &mo = en_pmoModelObject->GetAttachmentModel(iAttachment)->amo_moModelObject; + CEntityComponent *pecTexture = en_pecClass->ComponentForTypeAndID( + ECT_TEXTURE, idTextureComponent); + mo.mo_toSpecular.SetData(pecTexture->ec_ptdTexture); +} + +// Get all vertices of model entity in absolute space +void CEntity::GetModelVerticesAbsolute( CStaticStackArray &avVertices, FLOAT fNormalOffset, FLOAT fMipFactor) +{ + ASSERT(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL || + en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL); + // get placement + CPlacement3D plPlacement = GetLerpedPlacement(); + // calculate rotation matrix + FLOATmatrix3D mRotation; + MakeRotationMatrixFast(mRotation, plPlacement.pl_OrientationAngle); + if(en_RenderType==RT_MODEL || en_RenderType==RT_EDITORMODEL) { + en_pmoModelObject->GetModelVertices( avVertices, mRotation, plPlacement.pl_PositionVector, fNormalOffset, fMipFactor); + } else { + GetModelInstance()->GetModelVertices( avVertices, mRotation, plPlacement.pl_PositionVector, fNormalOffset, fMipFactor); + } +} + +void EntityAdjustBonesCallback(void *pData) +{ + ((CEntity*)pData)->AdjustBones(); +} +void EntityAdjustShaderParamsCallback(void *pData,INDEX iSurfaceID,CShader *pShader,ShaderParams &spParams) +{ + ((CEntity*)pData)->AdjustShaderParams(iSurfaceID,pShader,spParams); +} + +// Returns true if bone exists and sets two given vectors as start and end point of specified bone +BOOL CEntity::GetBoneRelPosition(INDEX iBoneID, FLOAT3D &vStartPoint, FLOAT3D &vEndPoint) +{ + ASSERT(en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL); + RM_SetObjectPlacement(CPlacement3D(FLOAT3D(0.0f,0.0f,0.0f),ANGLE3D(0.0f,0.0f,0.0f))); + RM_SetBoneAdjustCallback(&EntityAdjustBonesCallback,this); + return RM_GetBoneAbsPosition(*GetModelInstance(),iBoneID,vStartPoint,vEndPoint); +} + +// Returns true if bone exists and sets two given vectors as start and end point of specified bone +BOOL CEntity::GetBoneAbsPosition(INDEX iBoneID, FLOAT3D &vStartPoint, FLOAT3D &vEndPoint) +{ + ASSERT(en_RenderType==RT_SKAMODEL || en_RenderType==RT_SKAEDITORMODEL); + RM_SetObjectPlacement(GetLerpedPlacement()); + RM_SetBoneAdjustCallback(&EntityAdjustBonesCallback,this); + return RM_GetBoneAbsPosition(*GetModelInstance(),iBoneID,vStartPoint,vEndPoint); +} + +// Callback function for aditional bone adjustment +void CEntity::AdjustBones() +{ +} + +// Callback function for aditional shader params adjustment +void CEntity::AdjustShaderParams(INDEX iSurfaceID,CShader *pShader,ShaderParams &spParams) +{ +} + +// precache given component +void CEntity::PrecacheModel(SLONG slID) +{ + en_pecClass->ec_pdecDLLClass->PrecacheModel(slID); +} +void CEntity::PrecacheTexture(SLONG slID) +{ + en_pecClass->ec_pdecDLLClass->PrecacheTexture(slID); +} +void CEntity::PrecacheSound(SLONG slID) +{ + en_pecClass->ec_pdecDLLClass->PrecacheSound(slID); +} +void CEntity::PrecacheClass(SLONG slID, INDEX iUser /* = -1*/) +{ + en_pecClass->ec_pdecDLLClass->PrecacheClass(slID, iUser); +} + +CAutoPrecacheSound::CAutoPrecacheSound() +{ + apc_psd = NULL; +} +CAutoPrecacheSound::~CAutoPrecacheSound() +{ + if (apc_psd!=NULL) { + _pSoundStock->Release(apc_psd); + } +} + +void CAutoPrecacheSound::Precache(const CTFileName &fnm) +{ + if (apc_psd!=NULL) { + _pSoundStock->Release(apc_psd); + } + try { + if (fnm!="") { + apc_psd = _pSoundStock->Obtain_t(fnm); + } + } catch (char *strError) { + CPrintF("%s\n", strError); + } +} + +CAutoPrecacheModel::CAutoPrecacheModel() +{ + apc_pmd = NULL; +} +CAutoPrecacheModel::~CAutoPrecacheModel() +{ + if (apc_pmd!=NULL) { + _pModelStock->Release(apc_pmd); + } +} + +void CAutoPrecacheModel::Precache(const CTFileName &fnm) +{ + if (apc_pmd!=NULL) { + _pModelStock->Release(apc_pmd); + } + try { + if (fnm!="") { + apc_pmd = _pModelStock->Obtain_t(fnm); + } + } catch (char *strError) { + CPrintF("%s\n", strError); + } +} + +CAutoPrecacheTexture::CAutoPrecacheTexture() +{ + apc_ptd = NULL; +} +CAutoPrecacheTexture::~CAutoPrecacheTexture() +{ + if (apc_ptd!=NULL) { + _pTextureStock->Release(apc_ptd); + } +} + +void CAutoPrecacheTexture::Precache(const CTFileName &fnm) +{ + if (apc_ptd!=NULL) { + _pTextureStock->Release(apc_ptd); + } + try { + if (fnm!="") { + apc_ptd = _pTextureStock->Obtain_t(fnm); + } + } catch (char *strError) { + CPrintF("%s\n", strError); + } +} + +/* Get a filename for a component of given id. */ +const CTFileName &CEntity::FileNameForComponent(SLONG slType, SLONG slID) +{ + // find the component + CEntityComponent *pec = en_pecClass->ComponentForTypeAndID( + (EntityComponentType)slType, slID); + // the component must exist + ASSERT(pec!=NULL); + // get its name + return pec->ec_fnmComponent; +} + +// Get data for a texture component +CTextureData *CEntity::GetTextureDataForComponent(SLONG slID) +{ + CEntityComponent *pec = ComponentForTypeAndID( ECT_TEXTURE, slID); + if (pec!=NULL) { + return pec->ec_ptdTexture; + } else { + return NULL; + } +} + +// Get data for a model component +CModelData *CEntity::GetModelDataForComponent(SLONG slID) +{ + CEntityComponent *pec = ComponentForTypeAndID( ECT_MODEL, slID); + if (pec!=NULL) { + return pec->ec_pmdModel; + } else { + return NULL; + } +} + +/* Remove attachment from model */ +void CEntity::RemoveAttachment(INDEX iAttachment) +{ + // remove attachment + en_pmoModelObject->RemoveAttachmentModel(iAttachment); +} + +/* Initialize last positions structure for particles. */ +CLastPositions *CEntity::GetLastPositions(INDEX ctPositions) +{ + TIME tmNow = _pTimer->CurrentTick(); + if (en_plpLastPositions==NULL) { + en_plpLastPositions = new CLastPositions; + en_plpLastPositions->lp_avPositions.New(ctPositions); + en_plpLastPositions->lp_ctUsed = 0; + en_plpLastPositions->lp_iLast = 0; + en_plpLastPositions->lp_tmLastAdded = tmNow; + const FLOAT3D &vNow = GetPlacement().pl_PositionVector; + for(INDEX iPos = 0; iPoslp_avPositions[iPos] = vNow; + } + } + + while(en_plpLastPositions->lp_tmLastAddedAddPosition(en_plpLastPositions->GetPosition(0)); + } + + return en_plpLastPositions; +} + + +/* Get absolute position of point on entity given relative to its size. */ +void CEntity::GetEntityPointRatio(const FLOAT3D &vRatio, FLOAT3D &vAbsPoint, BOOL bLerped) +{ + ASSERT(bLerped || GetFPUPrecision()==FPT_24BIT); + + if (en_RenderType!=RT_MODEL && en_RenderType!=RT_EDITORMODEL && + en_RenderType!=RT_SKAMODEL && en_RenderType!=RT_SKAEDITORMODEL && + en_RenderType!=RT_BRUSH) { + ASSERT(FALSE); + vAbsPoint = en_plPlacement.pl_PositionVector; + return; + } + + FLOAT3D vMin, vMax; + + if (en_RenderType==RT_BRUSH) + { + CBrushMip *pbmMip = en_pbrBrush->GetFirstMip(); + vMin = pbmMip->bm_boxBoundingBox.Min(); + vMax = pbmMip->bm_boxBoundingBox.Max(); + FLOAT3D vOff = vMax-vMin; + vOff(1) *= vRatio(1); + vOff(2) *= vRatio(2); + vOff(3) *= vRatio(3); + vAbsPoint = vMin+vOff; + } + else + { + if (_pNetwork->ga_ulDemoMinorVersion<=2) { + vMin = en_pmoModelObject->GetCollisionBoxMin(GetCollisionBoxIndex()); + vMax = en_pmoModelObject->GetCollisionBoxMax(GetCollisionBoxIndex()); + } else { + INDEX iEq; + FLOATaabbox3D box; + GetCollisionBoxParameters(GetCollisionBoxIndex(), box, iEq); + vMin = box.Min(); + vMax = box.Max(); + } + FLOAT3D vOff = vMax-vMin; + vOff(1) *= vRatio(1); + vOff(2) *= vRatio(2); + vOff(3) *= vRatio(3); + FLOAT3D vPos = vMin+vOff; + if( bLerped) + { + CPlacement3D plLerped=GetLerpedPlacement(); + FLOATmatrix3D mRot; + MakeRotationMatrixFast(mRot, plLerped.pl_OrientationAngle); + vAbsPoint=plLerped.pl_PositionVector+vPos*mRot; + } + else + { + vAbsPoint = en_plPlacement.pl_PositionVector+vPos*en_mRotation; + } + } +} + +/* Get absolute position of point on entity given in meters. */ +void CEntity::GetEntityPointFixed(const FLOAT3D &vFixed, FLOAT3D &vAbsPoint) +{ + vAbsPoint = en_plPlacement.pl_PositionVector+vFixed*en_mRotation; +} +/* Get sector that given point is in - point must be inside this entity. */ +CBrushSector *CEntity::GetSectorFromPoint(const FLOAT3D &vPointAbs) +{ + // for each sector around entity + {FOREACHSRCOFDST(en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // if point is in this sector + if( pbsc->bsc_bspBSPTree.TestSphere(FLOATtoDOUBLE(vPointAbs), 0.01)>=0) { + // return that + return pbsc; + } + ENDFOR;} + return NULL; +} + +/* Model change notify */ +void CEntity::ModelChangeNotify(void) +{ + // if this is ska model + if(en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL) { + if(GetModelInstance()==NULL) { + return; + } + + // this is old model + } else { + if (en_pmoModelObject==NULL || en_pmoModelObject->GetData()==NULL) { + return; + } + } + + UpdateSpatialRange(); + FindCollisionInfo(); +} + +void CEntity::TerrainChangeNotify(void) +{ +// GetTerrain()->RemoveLayer(0,FALSE); +// GetTerrain()->AddDefaultLayer_t(); + GetTerrain()->ReBuildTerrain(TRUE); + UpdateSpatialRange(); +} + +// map world polygon to/from indices +CBrushPolygon *CEntity::GetWorldPolygonPointer(INDEX ibpo) +{ + if (ibpo==-1) { + return NULL; + } else { + return en_pwoWorld->wo_baBrushes.ba_apbpo[ibpo]; + } +} +INDEX CEntity::GetWorldPolygonIndex(CBrushPolygon *pbpo) +{ + if (pbpo==NULL) { + return -1; + } else { + return pbpo->bpo_iInWorld; + } +} + +///////////////////////////////////////////////////////////////////// +// Sound functions +void CEntity::PlaySound(CSoundObject &so, SLONG idSoundComponent, SLONG slPlayType) +{ + CEntityComponent *pecSound = en_pecClass->ComponentForTypeAndID(ECT_SOUND, idSoundComponent); + //so.Stop(); + so.Play(pecSound->ec_psdSound, slPlayType); +} + +double CEntity::GetSoundLength(SLONG idSoundComponent) +{ + CEntityComponent *pecSound = en_pecClass->ComponentForTypeAndID(ECT_SOUND, idSoundComponent); + return pecSound->ec_psdSound->GetSecondsLength(); +} + +void CEntity::PlaySound(CSoundObject &so, const CTFileName &fnmSound, SLONG slPlayType) +{ + // try to + try { + // load the sound data + //so.Stop(); + so.Play_t(fnmSound, slPlayType); + // if failed + } catch(char *strError) { + (void)strError; + DECLARE_CTFILENAME(fnmDefault, "Sounds\\Default.wav"); + // try to + try { + // load the default sound data + so.Play_t(fnmDefault, slPlayType); + // if failed + } catch(char *strErrorDefault) { + FatalError(TRANS("Cannot load default sound '%s':\n%s"), + (CTString&)fnmDefault, strErrorDefault); + } + } +} + +///////////////////////////////////////////////////////////////////// +/* + * Apply some damage directly to one entity. + */ +void CEntity::InflictDirectDamage(CEntity *penToDamage, CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // if any of the entities are not allowed to execute now + if (!IsAllowedForPrediction() + ||!penToDamage->IsAllowedForPrediction() + ||!penInflictor->IsAllowedForPrediction()) { + // do nothing + return; + } + + // if significant damage + if (fDamageAmmount>0) { + penToDamage->ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } +} + +// find intensity of current entity at given distance +static inline FLOAT IntensityAtDistance( + FLOAT fDamageAmmount, FLOAT fHotSpotRange, FLOAT fFallOffRange, FLOAT fDistance) +{ + // if further than fall-off range + if (fDistance>fFallOffRange) { + // intensity is zero + return 0; + // if closer than hot-spot range + } else if (fDistanceci_absSpheres.Count(); + if (ctSpheres<1) { + return FALSE; + } + avPoints[1] = pci->ci_absSpheres[ctSpheres-1].ms_vCenter*mR+vO; + avPoints[2] = pci->ci_absSpheres[0].ms_vCenter*mR+vO; + avPoints[0] = (avPoints[1]+avPoints[2])*0.5f; + + // check if any point can be hit + BOOL bCanHit = FALSE; + for(INDEX i=0; i<3; i++) { + CCastRay crRay( &en, avPoints[i], vCenter); + crRay.cr_ttHitModels = CCastRay::TT_NONE; // only brushes block the damage + crRay.cr_bHitTranslucentPortals = FALSE; + crRay.cr_bPhysical = TRUE; + en.en_pwoWorld->CastRay(crRay); + if (crRay.cr_penHit==NULL) { + bCanHit = TRUE; + break; + } + } + + // if none can be hit + if (!bCanHit) { + // skip this entity + return FALSE; + } + + // find minimum distance + fMinD = UpperLimit(0.0f); + vHitPos = vO; + // for each sphere + FOREACHINSTATICARRAY(pci->ci_absSpheres, CMovingSphere, itms) { + // project it + itms->ms_vRelativeCenter0 = itms->ms_vCenter*en.en_mRotation+vO; + FLOAT fD = (itms->ms_vRelativeCenter0-vCenter).Length()-itms->ms_fR; + if (fDms_vRelativeCenter0; + } + } + if (fMinD<0) { + fMinD = 0; + } + return TRUE; +} + +// check if a range damage can hit given brush entity +static BOOL CheckBrushRangeDamage( + CEntity &en, const FLOAT3D &vCenter, FLOAT &fMinD, FLOAT3D &vHitPos) +{ + // don't actually check for brushes, doesn't have to be too exact + const FLOAT3D &vO = en.en_plPlacement.pl_PositionVector; + fMinD = (vO-vCenter).Length(); + vHitPos = vO; + return TRUE; +} + +/* Apply some damage to all entities in some range. */ +void CEntity::InflictRangeDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vCenter, FLOAT fHotSpotRange, FLOAT fFallOffRange) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // if any of the entities are not allowed to execute now + if (!IsAllowedForPrediction() + ||!penInflictor->IsAllowedForPrediction()) { + // do nothing + return; + } + + // find entities in the range + CDynamicContainer cenInRange; + FindEntitiesInRange(FLOATaabbox3D(vCenter, fFallOffRange), cenInRange, TRUE); + + // for each entity in container + FOREACHINDYNAMICCONTAINER(cenInRange, CEntity, iten) { + CEntity &en = *iten; + // if entity is not allowed to execute now + if (!en.IsAllowedForPrediction()) { + // do nothing + continue; + } + + // if can be hit + FLOAT3D vHitPos; + FLOAT fMinD; + if ( + (en.en_RenderType==RT_MODEL || en.en_RenderType==RT_EDITORMODEL || + en.en_RenderType==RT_SKAMODEL || en.en_RenderType==RT_SKAEDITORMODEL )&& + CheckModelRangeDamage(en, vCenter, fMinD, vHitPos) || + (en.en_RenderType==RT_BRUSH)&& + CheckBrushRangeDamage(en, vCenter, fMinD, vHitPos)) { + + // find damage ammount + FLOAT fAmmount = IntensityAtDistance(fDamageAmmount, fHotSpotRange, fFallOffRange, fMinD); + + // if significant + if (fAmmount>0) { + // inflict damage to it + en.ReceiveDamage(penInflictor, dmtType, fAmmount, vHitPos, (vHitPos-vCenter).Normalize()); + } + } + } +} + +/* Apply some damage to all entities in a box (this doesn't test for obstacles). */ +void CEntity::InflictBoxDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOATaabbox3D &box) +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // if any of the entities are not allowed to execute now + if (!IsAllowedForPrediction() + ||!penInflictor->IsAllowedForPrediction()) { + // do nothing + return; + } + + // find entities in the range + CDynamicContainer cenInRange; + FindEntitiesInRange(box, cenInRange, TRUE); + + // for each entity in container + FOREACHINDYNAMICCONTAINER(cenInRange, CEntity, iten) { + CEntity &en = *iten; + //ASSERT(en.en_pciCollisionInfo!=NULL); // assured by FindEntitiesInRange() + if (en.en_pciCollisionInfo==NULL) { + continue; + } + CCollisionInfo *pci = en.en_pciCollisionInfo; + // if entity is not allowed to execute now + if (!en.IsAllowedForPrediction()) { + // do nothing + continue; + } + + // if significant damage + if (fDamageAmmount>0) { + // inflict damage to it + en.ReceiveDamage(penInflictor, dmtType, + fDamageAmmount, box.Center(), + (box.Center()-en.GetPlacement().pl_PositionVector).Normalize()); + } + } +} + +// notify engine that gravity defined by this entity has changed +void CEntity::NotifyGravityChanged(void) +{ + if (_pNetwork->ga_ulDemoMinorVersion<=2) { + // for each entity in the world of this entity + FOREACHINDYNAMICCONTAINER(en_pwoWorld->wo_cenEntities, CEntity, iten) { + CEntity *pen = &*iten; + // if movable + if (pen->en_ulPhysicsFlags&EPF_MOVABLE) { + CMovableEntity *pmen = (CMovableEntity*)pen; + // if the gravity has changed + // add to movers + pmen->AddToMovers(); + } + } + } else { + // for each zoning brush in the world of this entity + FOREACHINDYNAMICCONTAINER(en_pwoWorld->wo_cenEntities, CEntity, iten) { + CEntity *penBrush = &*iten; + if (iten->en_RenderType != CEntity::RT_BRUSH || !(iten->en_ulFlags&ENF_ZONING)) { + continue; + } + CBrush3D *pbr = penBrush->en_pbrBrush; + // get first brush mip + CBrushMip *pbm = pbr->GetFirstMip(); + // for each sector in the brush mip + {FOREACHINDYNAMICARRAY(pbm->bm_abscSectors, CBrushSector, itbsc) { + // if controlled by this entity + if ( penBrush->GetForceController(itbsc->GetForceType()) == this ) { + // for each entity in the sector + {FOREACHDSTOFSRC(itbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) { + // if movable + if (pen->en_ulPhysicsFlags&EPF_MOVABLE) { + CMovableEntity *pmen = (CMovableEntity*)pen; + // add to movers + pmen->AddToMovers(); + } + ENDFOR}} + } + }} + } + } +} + +// notify engine that collision of this entity was changed +void CEntity::NotifyCollisionChanged(void) +{ + if (en_pciCollisionInfo==NULL) { + return; + } + + // find colliding entities near this one + static CStaticStackArray apenNearEntities; + en_pwoWorld->FindEntitiesNearBox(en_pciCollisionInfo->ci_boxCurrent, apenNearEntities); + + // for each of the found entities + {for(INDEX ienFound=0; ienFoundAddToMovers(); + } + }} + apenNearEntities.PopAll(); +} + +// apply some damage to the entity (see event EDamage for more info) +void CEntity::ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) +{ + CEntityPointer penThis = this; // keep this entity alive during this function + // just throw an event that you are damaged (base entities don't really have health) + EDamage eDamage; + eDamage.penInflictor = penInflictor; + eDamage.vDirection = vDirection; + eDamage.vHitPoint = vHitPoint; + eDamage.fAmount = fDamageAmmount; + eDamage.dmtType = dmtType; + SendEvent(eDamage); +} + +/* Receive item through event */ +BOOL CEntity::ReceiveItem(const CEntityEvent &ee) +{ + return FALSE; +} + +/* Get entity info */ +void *CEntity::GetEntityInfo(void) +{ + return NULL; +}; +/* Fill in entity statistics - for AI purposes only */ +BOOL CEntity::FillEntityStatistics(struct EntityStats *pes) +{ + return FALSE; +} + +///////////////////////////////////////////////////////////////////// +// Overrides from CSerial + +/* + * Read from stream. + */ +void CEntity::Read_t( CTStream *istr) // throw char * +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // read base class data from stream + if (istr->PeekID_t()==CChunkID("ENT4")) { // entity v4 + istr->ExpectID_t("ENT4"); + ULONG ulID; + SLONG slSize; + (*istr)>>ulID>>slSize; // skip id and size + (*istr)>>(ULONG &)en_RenderType + >>en_ulPhysicsFlags + >>en_ulCollisionFlags + >>en_ulSpawnFlags + >>en_ulFlags; + (*istr).Read_t(&en_mRotation, sizeof(en_mRotation)); + } else if (istr->PeekID_t()==CChunkID("ENT3")) { // entity v3 + istr->ExpectID_t("ENT3"); + (*istr)>>(ULONG &)en_RenderType + >>en_ulPhysicsFlags + >>en_ulCollisionFlags + >>en_ulSpawnFlags + >>en_ulFlags; + (*istr).Read_t(&en_mRotation, sizeof(en_mRotation)); + } else if (istr->PeekID_t()==CChunkID("ENT2")) { // entity v2 + istr->ExpectID_t("ENT2"); + (*istr)>>(ULONG &)en_RenderType + >>en_ulPhysicsFlags + >>en_ulCollisionFlags + >>en_ulSpawnFlags + >>en_ulFlags; + } else { + (*istr)>>(ULONG &)en_RenderType + >>en_ulPhysicsFlags + >>en_ulCollisionFlags + >>en_ulFlags; + } + + // clear flags for selection and caching info + en_ulFlags &= ~(ENF_SELECTED|ENF_INRENDERING|ENF_VALIDSHADINGINFO); + en_psiShadingInfo = NULL; + en_pciCollisionInfo = NULL; + + // if this is a brush + if ( en_RenderType == RT_BRUSH || en_RenderType == RT_FIELDBRUSH) { + // read brush index in world's brush archive + INDEX iBrush; + (*istr)>>iBrush; + en_pbrBrush = &en_pwoWorld->wo_baBrushes.ba_abrBrushes[iBrush]; + en_pbrBrush->br_penEntity = this; + // if this is a terrain + } else if (en_RenderType == RT_TERRAIN) { + // read terrain index in world's terrain archive + INDEX iTerrain; + (*istr)>>iTerrain; + en_ptrTerrain = &en_pwoWorld->wo_taTerrains.ta_atrTerrains[iTerrain]; + en_ptrTerrain->tr_penEntity = this; + // force terrain regeneration (regenerate tiles on next render) + en_ptrTerrain->ReBuildTerrain(TRUE); + + // if this is a model + } else if ( en_RenderType == RT_MODEL || en_RenderType == RT_EDITORMODEL) { + // create a new model object + en_pmoModelObject = new CModelObject; + en_psiShadingInfo = new CShadingInfo; + en_ulFlags &= ~ENF_VALIDSHADINGINFO; + + // read model + ReadModelObject_t(*istr, *en_pmoModelObject); + // if this is a ska model + } else if( en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL) { + en_pmiModelInstance = CreateModelInstance("Temp"); + en_psiShadingInfo = new CShadingInfo; + en_ulFlags &= ~ENF_VALIDSHADINGINFO; + + ReadModelInstance_t(*istr, *GetModelInstance()); + // if this is a void + } else if (en_RenderType == RT_VOID) { + en_pbrBrush = NULL; + } + + // if the entity has a parent + if (istr->PeekID_t()==CChunkID("PART")) { // parent + // read the parent pointer and relative offset + istr->ExpectID_t("PART"); + INDEX iParent; + *istr>>iParent; + extern BOOL _bReadEntitiesByID; + if (_bReadEntitiesByID) { + en_penParent = en_pwoWorld->EntityFromID(iParent); + } else { + en_penParent = en_pwoWorld->wo_cenAllEntities.Pointer(iParent); + } + *istr>>en_plRelativeToParent; + // link to parent + en_penParent->en_lhChildren.AddTail(en_lnInParent); + } + + // read the derived class properties from stream + ReadProperties_t(*istr); + + // if it is a light source + {CLightSource *pls = GetLightSource(); + if (pls!=NULL) { + // read the light source layer list + pls->ls_penEntity = this; + pls->Read_t(istr); + }} + + // if it is a field brush + CFieldSettings *pfs = GetFieldSettings(); + if (pfs!=NULL) { + // remember its field settings + ASSERT(en_RenderType == RT_FIELDBRUSH); + en_pbrBrush->br_pfsFieldSettings = pfs; + } + + // if entity was predictable + if (en_ulFlags&ENF_PREDICTABLE) { + // restore that condition + en_ulFlags&=~ENF_PREDICTABLE; // have to clear it to be able to set it back + SetPredictable(TRUE); + } +} + +/* + * Write to stream. + */ +void CEntity::Write_t( CTStream *ostr) // throw char * +{ + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // write base class data to stream + ostr->WriteID_t("ENT4"); + SLONG slSize = 0; + (*ostr)<wo_baBrushes.ba_abrBrushes.Index(en_pbrBrush); + // if this is a terrain + } else if ( en_RenderType == RT_TERRAIN) { + // write brush index in world's brush archive + (*ostr)<wo_taTerrains.ta_atrTerrains.Index(en_ptrTerrain); + // if this is a model + } else if ( en_RenderType == RT_MODEL || en_RenderType == RT_EDITORMODEL) { + // write model + WriteModelObject_t(*ostr, *en_pmoModelObject); + // if this is ska model + } else if ( en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL) { + // write ska model + WriteModelInstance_t(*ostr, *GetModelInstance()); + // if this is a void + } else if (en_RenderType == RT_VOID) { + NOTHING; + } + + // if the entity has a parent + if (en_penParent!=NULL) { + // write the parent pointer and relative offset + ostr->WriteID_t("PART"); // parent + INDEX iParent = en_penParent->en_ulID; + *ostr<Write_t(ostr); + }} +} + + +/* Precache components that might be needed. */ +void CEntity::Precache(void) +{ + NOTHING; +} + + +void CEntity::ChecksumForSync(ULONG &ulCRC, INDEX iExtensiveSyncCheck) +{ + if (iExtensiveSyncCheck>0) { + CRC_AddLONG(ulCRC, en_ulFlags&~ + (ENF_SELECTED|ENF_INRENDERING|ENF_VALIDSHADINGINFO|ENF_FOUNDINGRIDSEARCH|ENF_WILLBEPREDICTED|ENF_PREDICTABLE)); + CRC_AddLONG(ulCRC, en_ulPhysicsFlags); + CRC_AddLONG(ulCRC, en_ulCollisionFlags); + CRC_AddLONG(ulCRC, en_ctReferences); + } + CRC_AddLONG(ulCRC, en_RenderType); + if (iExtensiveSyncCheck>0) { + CRC_AddLONG(ulCRC, en_ulID); + CRC_AddFLOAT(ulCRC, en_fSpatialClassificationRadius); + CRC_AddFLOAT(ulCRC, en_plPlacement.pl_PositionVector(1)); + CRC_AddFLOAT(ulCRC, en_plPlacement.pl_PositionVector(2)); + CRC_AddFLOAT(ulCRC, en_plPlacement.pl_PositionVector(3)); + CRC_AddFLOAT(ulCRC, en_plPlacement.pl_OrientationAngle(1)); + CRC_AddFLOAT(ulCRC, en_plPlacement.pl_OrientationAngle(2)); + CRC_AddFLOAT(ulCRC, en_plPlacement.pl_OrientationAngle(3)); + + CRC_AddBlock(ulCRC, (UBYTE*)(void*)&en_mRotation, sizeof(en_mRotation)); + } else { + CRC_AddLONG(ulCRC, (int)en_plPlacement.pl_PositionVector(1)); + CRC_AddLONG(ulCRC, (int)en_plPlacement.pl_PositionVector(2)); + CRC_AddLONG(ulCRC, (int)en_plPlacement.pl_PositionVector(3)); + } +} + +void CEntity::DumpSync_t(CTStream &strm, INDEX iExtensiveSyncCheck) // throw char * +{ + strm.FPrintF_t("\n---- #%05d ($%05d)----------------\n", + en_pwoWorld->wo_cenAllEntities.Index(this), en_pwoWorld->wo_cenEntities.Index(this)); + if (en_ulFlags&ENF_DELETED) { + strm.FPrintF_t("*** DELETED ***\n"); + } + strm.FPrintF_t("class: '%s'\n", GetClass()->ec_pdecDLLClass->dec_strName); + strm.FPrintF_t("name: '%s'\n", GetName()); + if (iExtensiveSyncCheck>0) { + strm.FPrintF_t("en_ulFlags: 0x%08X\n", en_ulFlags&~ + (ENF_SELECTED|ENF_INRENDERING|ENF_VALIDSHADINGINFO|ENF_FOUNDINGRIDSEARCH|ENF_WILLBEPREDICTED|ENF_PREDICTABLE)); + strm.FPrintF_t("en_ulPhysicsFlags: 0x%08X\n", en_ulPhysicsFlags); + strm.FPrintF_t("en_ulCollisionFlags: 0x%08X\n", en_ulCollisionFlags); + strm.FPrintF_t("en_ctReferences: %d\n", en_ctReferences); + } + strm.FPrintF_t("en_RenderType: %d\n", en_RenderType); + strm.FPrintF_t("en_ulID: 0x%08x\n", en_ulID); + if (iExtensiveSyncCheck>0) { + strm.FPrintF_t("en_fSpatialClassificationRadius: %g(%08x)\n", + en_fSpatialClassificationRadius, (ULONG&)en_fSpatialClassificationRadius); + } + strm.FPrintF_t("placement: %g,%g,%g : %g,%g,%g\n", + en_plPlacement.pl_PositionVector(1), + en_plPlacement.pl_PositionVector(2), + en_plPlacement.pl_PositionVector(3), + en_plPlacement.pl_OrientationAngle(1), + en_plPlacement.pl_OrientationAngle(2), + en_plPlacement.pl_OrientationAngle(3)); + if (iExtensiveSyncCheck>0) { + strm.FPrintF_t("placement raw:\n %08X %08X %08X\n %08X %08X %08X\n", + (ULONG&)en_plPlacement.pl_PositionVector(1), + (ULONG&)en_plPlacement.pl_PositionVector(2), + (ULONG&)en_plPlacement.pl_PositionVector(3), + (ULONG&)en_plPlacement.pl_OrientationAngle(1), + (ULONG&)en_plPlacement.pl_OrientationAngle(2), + (ULONG&)en_plPlacement.pl_OrientationAngle(3)); + strm.FPrintF_t("matrix:\n %g %g %g\n %g %g %g\n %g %g %g\n", + en_mRotation(1,1), en_mRotation(1,2), en_mRotation(1,3), + en_mRotation(2,1), en_mRotation(2,2), en_mRotation(2,3), + en_mRotation(3,1), en_mRotation(3,2), en_mRotation(3,3)); + strm.FPrintF_t("matrix raw:\n %08X %08X %08X\n %08X %08X %08X\n %08X %08X %08X\n", + (ULONG&)en_mRotation(1,1), (ULONG&)en_mRotation(1,2), (ULONG&)en_mRotation(1,3), + (ULONG&)en_mRotation(2,1), (ULONG&)en_mRotation(2,2), (ULONG&)en_mRotation(2,3), + (ULONG&)en_mRotation(3,1), (ULONG&)en_mRotation(3,2), (ULONG&)en_mRotation(3,3)); + if( en_pciCollisionInfo == NULL) { + strm.FPrintF_t("Collision info NULL\n"); + } else if (en_RenderType==RT_BRUSH && en_RenderType==RT_FIELDBRUSH) { + strm.FPrintF_t("Collision info: Brush entity\n"); + } else { + strm.FPrintF_t("Collision info:\n"); + strm.FPrintF_t("Min height, Max height: %g, %g\n", + en_pciCollisionInfo->ci_fMinHeight, en_pciCollisionInfo->ci_fMaxHeight); + strm.FPrintF_t("Handle Y, Handle R: %g, %g\n", + en_pciCollisionInfo->ci_fHandleY, en_pciCollisionInfo->ci_fHandleR); + + strm.FPrintF_t("Handle Y, Handle R: %g, %g\n", + en_pciCollisionInfo->ci_fHandleY, en_pciCollisionInfo->ci_fHandleR); + + DUMPVECTOR(en_pciCollisionInfo->ci_boxCurrent.Min()); + DUMPVECTOR(en_pciCollisionInfo->ci_boxCurrent.Max()); + DUMPLONG(en_pciCollisionInfo->ci_ulFlags); + } + } +} + + +// get a pseudo-random number (safe for network gaming) +ULONG CEntity::IRnd(void) +{ + return ((_pNetwork->ga_sesSessionState.Rnd()>>(31-16))&0xFFFF); +} + + +FLOAT CEntity::FRnd(void) +{ + return ((_pNetwork->ga_sesSessionState.Rnd()>>(31-24))&0xFFFFFF)/FLOAT(0xFFFFFF); +} + + + +// returns ammount of memory used by entity +SLONG CEntity::GetUsedMemory(void) +{ + // initial size + SLONG slUsedMemory = sizeof(CEntity); + + // add relations + slUsedMemory += en_rdSectors.Count() * sizeof(CRelationLnk); + + // add allocated memory for model type (if any) + switch( en_RenderType) { + case CEntity::RT_MODEL: + case CEntity::RT_EDITORMODEL: + slUsedMemory += en_pmoModelObject->GetUsedMemory(); + break; + case CEntity::RT_SKAMODEL: + case CEntity::RT_SKAEDITORMODEL: + slUsedMemory += en_pmiModelInstance->GetUsedMemory(); + default: + break; + } + + // add shading info (if any) + if( en_psiShadingInfo !=NULL) { + slUsedMemory += sizeof(CShadingInfo); + } + // add collision info (if any) + if( en_pciCollisionInfo!=NULL) { + slUsedMemory += sizeof(CCollisionInfo) + (en_pciCollisionInfo->ci_absSpheres.sa_Count * sizeof(CMovingSphere)); + } + // add last positions memory (if any) + if( en_plpLastPositions!=NULL) { + slUsedMemory += sizeof(CLastPositions) + (en_plpLastPositions->lp_avPositions.sa_Count * sizeof(FLOAT3D)); + } + + // done + return slUsedMemory; +} + + + +/* Get pointer to entity property from its packed identifier. */ +class CEntityProperty *CEntity::PropertyForTypeAndID(ULONG ulType, ULONG ulID) +{ + return en_pecClass->PropertyForTypeAndID(ulType, ulID); +} + +/* Get pointer to entity component from its packed identifier. */ +class CEntityComponent *CEntity::ComponentForTypeAndID(ULONG ulType, ULONG ulID) +{ + return en_pecClass->ComponentForTypeAndID((enum EntityComponentType)ulType, ulID); +} + +/* Get pointer to entity property from its name. */ +class CEntityProperty *CEntity::PropertyForName(const CTString &strPropertyName) +{ + return en_pecClass->PropertyForName(strPropertyName); +} + +/* Create a new entity of given class in this world. */ +CEntity *CEntity::CreateEntity(const CPlacement3D &plPlacement, SLONG idClass) +{ + CEntityComponent *pecClassComponent = en_pecClass->ComponentForTypeAndID( + ECT_CLASS, idClass); + return en_pwoWorld->CreateEntity(plPlacement, pecClassComponent->ec_pecEntityClass); +} + + + +///////////////////////////////////////////////////////////////////// +// CLiveEntity + +/* + * Constructor. + */ +CLiveEntity::CLiveEntity(void) +{ + en_fHealth = 0; +} + +/* Copy entity from another entity of same class. */ +void CLiveEntity::Copy(CEntity &enOther, ULONG ulFlags) +{ + CEntity::Copy(enOther, ulFlags); + CLiveEntity *plenOther = (CLiveEntity *)(&enOther); + en_fHealth = plenOther->en_fHealth; +} +/* Read from stream. */ +void CLiveEntity::Read_t( CTStream *istr) // throw char * +{ + CEntity::Read_t(istr); + (*istr)>>en_fHealth; +} +/* Write to stream. */ +void CLiveEntity::Write_t( CTStream *ostr) // throw char * +{ + CEntity::Write_t(ostr); + (*ostr)<0) { + CRC_AddFLOAT(ulCRC, en_timeTimer); + CRC_AddLONG(ulCRC, en_stslStateStack.Count()); + } + if (iExtensiveSyncCheck>0) { + } +} + +// dump sync data to text file +void CRationalEntity::DumpSync_t(CTStream &strm, INDEX iExtensiveSyncCheck) // throw char * +{ + CEntity::DumpSync_t(strm, iExtensiveSyncCheck); + if (iExtensiveSyncCheck>0) { + strm.FPrintF_t("en_timeTimer: %g(%08x)\n", en_timeTimer, (ULONG&)en_timeTimer); + strm.FPrintF_t("en_stslStateStack.Count(): %d\n", en_stslStateStack.Count()); + } + strm.FPrintF_t("en_fHealth: %g(%08x)\n", en_fHealth, (ULONG&)en_fHealth); +} + +/* Copy entity from another entity of same class. */ +void CRationalEntity::Copy(CEntity &enOther, ULONG ulFlags) +{ + CLiveEntity::Copy(enOther, ulFlags); + if (!(ulFlags©_REINIT)) { + CRationalEntity *prenOther = (CRationalEntity *)(&enOther); + en_timeTimer = prenOther->en_timeTimer; + en_stslStateStack = prenOther->en_stslStateStack; + if (prenOther->en_lnInTimers.IsLinked()) { + en_pwoWorld->AddTimer(this); + } + } +} +/* Read from stream. */ +void CRationalEntity::Read_t( CTStream *istr) // throw char * +{ + CLiveEntity::Read_t(istr); + (*istr)>>en_timeTimer; + // if waiting for thinking + if (en_timeTimer!=THINKTIME_NEVER) { + // add to list of thinkers + en_pwoWorld->AddTimer(this); + } + // read the state stack + en_stslStateStack.Clear(); + en_stslStateStack.SetAllocationStep(STATESTACK_ALLOCATIONSTEP); + INDEX ctStates; + (*istr)>>ctStates; + for (INDEX iState=0; iState>en_stslStateStack.Push(); + } + +} +/* Write to stream. */ +void CRationalEntity::Write_t( CTStream *ostr) // throw char * +{ + CLiveEntity::Write_t(ostr); + // if not currently waiting for thinking + if (!en_lnInTimers.IsLinked()) { + // set dummy thinking time as a flag for later loading + en_timeTimer = THINKTIME_NEVER; + } + (*ostr)<_pTimer->CurrentTick() || + timeAbsolute==THINKTIME_NEVER, "Do not SetThink() back in time!"); + // set the timer + en_timeTimer = timeAbsolute; + + // add to world's list of timers if neccessary + if (en_timeTimer != THINKTIME_NEVER) { + en_pwoWorld->AddTimer(this); + } else { + if (en_lnInTimers.IsLinked()) { + en_lnInTimers.Remove(); + } + } +} + +/* + * Set next timer event to occur after given time has elapsed. + */ +void CRationalEntity::SetTimerAfter(TIME timeDelta) +{ + // set the execution for the moment that is that much ahead of the current tick + SetTimerAt(_pTimer->CurrentTick()+timeDelta); +} + +/* Cancel eventual pending timer. */ +void CRationalEntity::UnsetTimer(void) +{ + en_timeTimer = THINKTIME_NEVER; + if (en_lnInTimers.IsLinked()) { + en_lnInTimers.Remove(); + } +} + +/* + * Unwind stack to a given state. + */ +void CRationalEntity::UnwindStack(SLONG slThisState) +{ + // for each state on the stack (from top to bottom) + for(INDEX iStateInStack=en_stslStateStack.Count()-1; iStateInStack>=0; iStateInStack--) { + // if it is the state + if (en_stslStateStack[iStateInStack]==slThisState) { + // unwind to it + en_stslStateStack.PopUntil(iStateInStack); + return; + } + } + // the state must be on the stack + ASSERTALWAYS("Unwinding to unexisting state!"); +} + +/* + * Jump to a new state. + */ +void CRationalEntity::Jump(SLONG slThisState, SLONG slTargetState, BOOL bOverride, const CEntityEvent &eeInput) +{ + // unwind the stack to this state + UnwindStack(slThisState); + // set the new topmost state + if (bOverride) { + slTargetState = en_pecClass->ec_pdecDLLClass->GetOverridenState(slTargetState); + } + en_stslStateStack[en_stslStateStack.Count()-1] = slTargetState; + // handle the given event in the new state + HandleEvent(eeInput); +}; +/* + * Call a subautomaton. + */ +void CRationalEntity::Call(SLONG slThisState, SLONG slTargetState, BOOL bOverride, const CEntityEvent &eeInput) +{ + // unwind the stack to this state + UnwindStack(slThisState); + // push the new state to stack + if (bOverride) { + slTargetState = en_pecClass->ec_pdecDLLClass->GetOverridenState(slTargetState); + } + en_stslStateStack.Push() = slTargetState; + // handle the given event in the new state + HandleEvent(eeInput); +}; +/* + * Return from a subautomaton. + */ +void CRationalEntity::Return(SLONG slThisState, const CEntityEvent &eeReturn) +{ + // unwind the stack to this state + UnwindStack(slThisState); + // pop one state from the stack + en_stslStateStack.PopUntil(en_stslStateStack.Count()-2); + // handle the given event in the new topmost state + HandleEvent(eeReturn); +}; + +// print stack to debug output +const char *CRationalEntity::PrintStackDebug(void) +{ + _RPT2(_CRT_WARN, "-- stack of '%s'@%gs\n", GetName(), _pTimer->CurrentTick()); + + INDEX ctStates = en_stslStateStack.Count(); + for(INDEX iState=ctStates-1; iState>=0; iState--) { + SLONG slState = en_stslStateStack[iState]; + _RPT2(_CRT_WARN, "0x%08x %s\n", slState, + en_pecClass->ec_pdecDLLClass->HandlerNameForState(slState)); + } + _RPT0(_CRT_WARN, "----\n"); + return "ok"; +} + +/* + * Handle an event - return false if event was not handled. + */ +BOOL CRationalEntity::HandleEvent(const CEntityEvent &ee) +{ + // for each state on the stack (from top to bottom) + for(INDEX iStateInStack=en_stslStateStack.Count()-1; iStateInStack>=0; iStateInStack--) { + // try to find a handler in that state + pEventHandler pehHandler = + HandlerForStateAndEvent(en_stslStateStack[iStateInStack], ee.ee_slEvent); + // if there is a handler + if (pehHandler!=NULL) { + // call the function + BOOL bHandled = (this->*pehHandler)(ee); + // if the event was successfully handled + if (bHandled) { + // return that it was handled + return TRUE; + } + } + } + + // if no transition was found, the event was not handled + return FALSE; +} + +/* + * Called after creating and setting its properties. + */ +void CRationalEntity::OnInitialize(const CEntityEvent &eeInput) +{ + // make sure entity doesn't destroy itself during intialization + CEntityPointer penThis = this; + + // do not think + en_timeTimer = THINKTIME_NEVER; + if (en_lnInTimers.IsLinked()) { + en_lnInTimers.Remove(); + } + + // initialize state stack + en_stslStateStack.Clear(); + en_stslStateStack.SetAllocationStep(STATESTACK_ALLOCATIONSTEP); + + en_stslStateStack.Push() = 1; // start state is always state with number 1 + + // call the main function of the entity + HandleEvent(eeInput); +} + +/* Called before releasing entity. */ +void CRationalEntity::OnEnd(void) +{ + // cancel eventual pending timer + UnsetTimer(); +} + diff --git a/Sources/Engine/Entities/Entity.h b/Sources/Engine/Entities/Entity.h new file mode 100644 index 0000000..d1d05c8 --- /dev/null +++ b/Sources/Engine/Entities/Entity.h @@ -0,0 +1,813 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ENTITY_H +#define SE_INCL_ENTITY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define DUMPVECTOR(v) \ + strm.FPrintF_t(#v ": %g,%g,%g %08x,%08x,%08x\n", \ + (v)(1), (v)(2), (v)(3), (ULONG&)(v)(1), (ULONG&)(v)(2), (ULONG&)(v)(3)) +#define DUMPVECTOR2(strDes, v) \ + strm.FPrintF_t( "%s: %g,%g,%g\n", strDes, (v)(1), (v)(2), (v)(3)) +#define DUMPLONG(l) \ + strm.FPrintF_t(#l ": %08x\n", l) +#define DUMPPLACEMENT(plname, pl) \ + strm.FPrintF_t("%s:\n", plname); \ + DUMPVECTOR2( "Position", pl.pl_PositionVector); \ + DUMPVECTOR2( "Orientation", pl.pl_OrientationAngle); + +// force infulence at a point in space +class CForceStrength { +public: + FLOAT3D fs_vDirection; // direction of the force (must be normalized) + FLOAT fs_fAcceleration; // acceleration of the force (m/s2) (along the direction) + FLOAT fs_fVelocity; // max. velocity that force can give (m/s) (along the direction) +}; + + +#define DECL_DLL ENGINE_API +#include +#undef DECL_DLL + +/* + * Flags determining whether some entity is active in some game type or difficulty level. + */ +// difficulty levels +#define SPF_EASY (1L<<0) // active at easy difficulty +#define SPF_NORMAL (1L<<1) // active at normal difficulty +#define SPF_HARD (1L<<2) // active at hard difficulty +#define SPF_EXTREME (1L<<3) // active at extreme difficulty +#define SPF_TOURIST (1L<<4) // active at tourist difficulty + +#define SPF_MASK_DIFFICULTY 0x0000FFFFL // mask for difficulty level flags + +// game types +#define SPF_SINGLEPLAYER (1L<<16) // active in single player mode +#define SPF_DEATHMATCH (1L<<17) // active in deathmatch mode +#define SPF_COOPERATIVE (1L<<18) // active in cooperative mode +#define SPF_FLYOVER (1L<<19) // active in flyover (camera) mode + +#define SPF_MASK_GAMEMODE 0xFFFF0000L // mask for game type flags + +/* + * Various other entity flags + */ +#define ENF_SELECTED (1L<< 0) // set if selected +#define ENF_ZONING (1L<< 1) // brush that defines spatial classification +#define ENF_DELETED (1L<< 2) // set if the entity does not exist anymore +#define ENF_ALIVE (1L<< 3) // set if the entity is currently a living being +#define ENF_INRENDERING (1L<< 4) // set if the entity is currently active in rendering +#define ENF_VALIDSHADINGINFO (1L<< 5) // set if shading info is valid +#define ENF_SEETHROUGH (1L<< 6) // set if cast ray can see through +#define ENF_FOUNDINGRIDSEARCH (1L<< 7) // set if the entity is already found in grid search +#define ENF_CLUSTERSHADOWS (1L<< 8) // model that has cluster shadows +#define ENF_BACKGROUND (1L<< 9) // brush or model that is used for background rendering +#define ENF_ANCHORED (1L<<10) // set if cannot be moved in editor without special allowance +#define ENF_HASPARTICLES (1L<<11) // entity renders particles +#define ENF_INVISIBLE (1L<<12) // entity is invisible (for AI purposes) +#define ENF_DYNAMICSHADOWS (1L<<13) // moving brush that causes automatic shadow recalculation +#define ENF_NOTIFYLEVELCHANGE (1L<<14) // entity is notified when level is changed +#define ENF_CROSSESLEVELS (1L<<15) // entity must be carried when level is changed +#define ENF_PREDICTABLE (1L<<16) // this entity can be predicted +#define ENF_PREDICTOR (1L<<17) // this entity is predictor for another entity +#define ENF_PREDICTED (1L<<18) // this entity has its predictor +#define ENF_WILLBEPREDICTED (1L<<19) // this entity will be predicted +#define ENF_TEMPPREDICTOR (1L<<20) // predictor that was spawned during prediction (doesn't have a predictor) +#define ENF_HIDDEN (1L<<21) // set if the entity is hidden (for editing) +#define ENF_NOSHADINGINFO (1L<<22) // the entity doesn't need FindShadingInfo(), it will set its own shading + + +// selections of entities +typedef CSelection CEntitySelection; + +/* + * General structure of an entity instance. + */ +class ENGINE_API CEntity { +public: + // type of function pointer used as AI event handler + typedef BOOL (CEntity::*pEventHandler)(const CEntityEvent &ee); + + enum RenderType { + RT_ILLEGAL = 1, + RT_NONE = 2, // not rendered ever -- used internally + RT_MODEL = 3, // drawn as model + RT_BRUSH = 4, // rendered as brush + RT_EDITORMODEL = 5, // rendered as model, but only in editor + RT_VOID = 7, // not rendered ever + RT_FIELDBRUSH = 8, // brush used for field effects (like triggers, force fields etc.) + RT_SKAMODEL = 9, // render as ska model + RT_SKAEDITORMODEL = 10, // render as ska model, but only in editor + RT_TERRAIN = 11, // render as terrain + }; +/* Entity physics flags. */ +#define EPF_ORIENTEDBYGRAVITY (1UL<<0) // set if gravity influences its orientation +#define EPF_TRANSLATEDBYGRAVITY (1UL<<1) // set if gravity can move it +#define EPF_PUSHABLE (1UL<<2) // set if can be pushed by other objects +#define EPF_STICKYFEET (1UL<<3) // entity always falls to nearest surface +#define EPF_RT_SYNCHRONIZED (1UL<<4) // set if rotation and translation are synchronized +#define EPF_ABSOLUTETRANSLATE (1UL<<5) // set if entity is translated absolute and not relative to its position +#define EPF_NOACCELERATION (1UL<<6) // set if entity can change its speed immediately +#define EPF_HASLUNGS (1UL<<7) // set if entity has lungs +#define EPF_HASGILLS (1UL<<8) // set if entity has gills +#define EPF_MOVABLE (1UL<<9) // set if derived from CMovableEntity +#define EPF_NOIMPACT (1UL<<10)// entities are not damaged when hitting this one +#define EPF_NOIMPACTTHISTICK (1UL<<11)// this one is not damaged by impact this tick +#define EPF_CANFADESPINNING (1UL<<12)// desired rotation can be reduced by contents (like water) +#define EPF_ONSTEEPSLOPE (1UL<<13)// while sliding down a steep slope (valid only if entity has reference) +#define EPF_ORIENTINGTOGRAVITY (1UL<<14)// while beeing re-oriented by gravity +#define EPF_FLOATING (1UL<<15)// while bouyancy causes floating in fluid +#define EPF_FORCEADDED (1UL<<16)// set if force-added to movers + +// what to do when colliding +#define EPF_ONBLOCK_MASK (7UL<<29) +#define EPF_ONBLOCK_STOP (0UL<<29) // stop moving +#define EPF_ONBLOCK_SLIDE (1UL<<29) // slide along +#define EPF_ONBLOCK_CLIMBORSLIDE (2UL<<29) // clim up a stair or slide along +#define EPF_ONBLOCK_BOUNCE (3UL<<29) // bounce off +#define EPF_ONBLOCK_PUSH (4UL<<29) // push the obstacle +#define EPF_ONBLOCK_STOPEXACT (5UL<<29) // stop moving, but exactly at collision position + +// entity collision flags are divided in 3 groups +#define ECB_COUNT 10 // max number of flags per group +#define ECF_MASK ((1< &cen, + BOOL bCollidingOnly); + // find first entity touching a field (this entity must be a field brush) + CEntity *TouchingEntity(BOOL (*ConsiderEntity)(CEntity *), CEntity *penHintMaybeInside); + +public: + // DLL class interface + /* Initialize for being virtual entity that is not rendered. */ + void InitAsVoid(void); + /* Initialize for beeing a model object. */ + void InitAsModel(void); + void InitAsSkaModel(void); + /* Initialize for beeing a terrain object. */ + void InitAsTerrain(void); + + /* Initialize for beeing an editor model object. */ + void InitAsEditorModel(void); + void InitAsSkaEditorModel(void); + /* Initialize for beeing a brush object. */ + void InitAsBrush(void); + /* Initialize for beeing a field brush object. */ + void InitAsFieldBrush(void); + /* Switch to Model/Editor model */ + void SwitchToModel(void); + void SwitchToEditorModel(void); + + /* Set all properties to default values. - overridden by ecc */ + virtual void SetDefaultProperties(void); + + /* Get a filename for a component of given type and id. */ + const CTFileName &FileNameForComponent(SLONG slType, SLONG slID); + // Get data for a texture component + CTextureData *GetTextureDataForComponent(SLONG slID); + // Get data for a model component + CModelData *GetModelDataForComponent(SLONG slID); + + // model manipulation functions -- only for RT_MODEL/RT_EDITORMODEL + /* Set the model data for model entity. */ + void SetModel(const CTFileName &fnmModel); + void SetModel(SLONG idModelComponent); + BOOL SetSkaModel(const CTString &fnmModel); + void SetSkaModel_t(const CTString &fnmModel); + void SetSkaColisionInfo(); + /* Get the model data for model entity. */ + const CTFileName &GetModel(void); + /* Start new animation for model entity. */ + void StartModelAnim(INDEX iNewModelAnim, ULONG ulFlags); + + /* Play a given sound object. */ + void PlaySound(CSoundObject &so, SLONG idSoundComponent, SLONG slPlayType); + void PlaySound(CSoundObject &so, const CTFileName &fnmSound, SLONG slPlayType); + double GetSoundLength(SLONG idSoundComponent); + + // set/get model main blend color + COLOR GetModelColor(void) const; + void SetModelColor( const COLOR colBlend); + + /* Set the main texture data for model entity. */ + void SetModelMainTexture(SLONG idTextureComponent); + void SetModelMainTexture(const CTFileName &fnmTexture); + /* Get the main texture data for model entity. */ + const CTFileName &GetModelMainTexture(void); + /* Start new animation for main texture of model entity. */ + void StartModelMainTextureAnim(INDEX iNewTextureAnim); + + /* Set the reflection texture data for model entity. */ + void SetModelReflectionTexture(SLONG idTextureComponent); + /* Set the specular texture data for model entity. */ + void SetModelSpecularTexture(SLONG idTextureComponent); + + /* Add attachment to model */ + void AddAttachment(INDEX iAttachment, ULONG ulIDModel, ULONG ulIDTexture); + void AddAttachment(INDEX iAttachment, CTFileName fnModel, CTFileName fnTexture); + /* Remove attachment from model */ + void RemoveAttachment(INDEX iAttachment); + /* Set the reflection texture data for model attachment entity. */ + void SetModelAttachmentReflectionTexture(INDEX iAttachment, SLONG idTextureComponent); + /* Set the specular texture data for model attachment entity. */ + void SetModelAttachmentSpecularTexture(INDEX iAttachment, SLONG idTextureComponent); + + // Get all vertices of model entity in absolute space + void GetModelVerticesAbsolute( CStaticStackArray &avVertices, FLOAT fNormalOffset, FLOAT fMipFactor); + // Returns true if bone exists and sets two given vectors as start and end point of specified bone in abs space + BOOL GetBoneAbsPosition(INDEX iBoneID, FLOAT3D &vStartPoint, FLOAT3D &vEndPoint); + // Returns true if bone exists and sets two given vectors as start and end point of specified bone in relative space + BOOL GetBoneRelPosition(INDEX iBoneID, FLOAT3D &vStartPoint, FLOAT3D &vEndPoint); + // Callback function for aditional bone adjustment + virtual void AdjustBones(); + // Callback function for aditional shader params adjustment + virtual void AdjustShaderParams(INDEX iSurfaceID,CShader *pShader,ShaderParams &spParams); + + // precache given component + void PrecacheModel(SLONG slID); + void PrecacheTexture(SLONG slID); + void PrecacheSound(SLONG slID); + void PrecacheClass(SLONG slID, INDEX iUser = -1); + + /* Create a new entity of given class in this world. */ + CEntity *CreateEntity(const CPlacement3D &plPlacement, SLONG idModelComponent); + + /* Apply some damage directly to one entity. */ + void InflictDirectDamage(CEntity *penToDamage, CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection); + /* Apply some damage to all entities in some range (this tests for obstacles). */ + void InflictRangeDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vCenter, FLOAT fHotSpotRange, FLOAT fFallOffRange); + /* Apply some damage to all entities in a box (this doesn't test for obstacles). */ + void InflictBoxDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOATaabbox3D &box); + + // notify engine that gravity defined by this entity has changed + void NotifyGravityChanged(void); + // notify engine that collision of this entity was changed + void NotifyCollisionChanged(void); + + // get a pseudo-random number (safe for network gaming) + ULONG IRnd(void); // [0x0000 , 0xFFFF] + FLOAT FRnd(void); // [0.0f , 1.0f] + + // DLL class overridables + /* Called after creating and setting its properties. */ + virtual void OnInitialize(const CEntityEvent &eeInput); + /* Called before releasing entity. */ + virtual void OnEnd(void); + + // these functions are dummy in CEntity, but are implemented in CRationalEntity + /* Jump to a new state. */ + void Jump(SLONG slThisState, SLONG slTargetState, BOOL bOverride, const CEntityEvent &eeInput) {}; + /* Call a subautomaton. */ + void Call(SLONG slThisState, SLONG slTargetState, BOOL bOverride, const CEntityEvent &eeInput) {}; + /* Return from a subautomaton. */ + void Return(SLONG slThisState, const CEntityEvent &eeReturn) {}; + // print stack to debug output + virtual const char *PrintStackDebug(void); + + void SetTimerAt(TIME timeAbsolute) {}; + void SetTimerAfter(TIME timeDelta) {}; + void UnsetTimer(void) {}; + + // return opacity of the entity (1 is default) + virtual FLOAT GetOpacity(void) { return 1.0f; }; + + // returns ammount of memory used by entity + virtual SLONG GetUsedMemory(void); + +public: + + // construction/destruction + /* Default constructor. */ + CEntity(void); + /* Destructor. */ + virtual ~CEntity(void); + /* Clear the object. */ + void Clear(void) {}; + + // entities can be selected + IMPLEMENT_SELECTING(en_ulFlags); + + // access functions + /* Prepare entity (call after setting properties). */ + void Initialize(const CEntityEvent &eeInput = _eeVoid); + /* Clean-up entity. */ + void End(void); + + /* Destroy this entity (entity must not be targetable). */ + void Destroy(void); + + /* Get state transition for given state and event code. */ + virtual CEntity::pEventHandler HandlerForStateAndEvent(SLONG slState, SLONG slEvent); + /* Handle an event, return false if the event is not handled. */ + virtual BOOL HandleEvent(const CEntityEvent &ee); + + // get/set functions for use in WEd and/or entity class DLLs + void SetPlacement(const CPlacement3D &plNew); // use this only in WEd + void FallDownToFloor( void); + inline const CPlacement3D &GetPlacement(void) const { return en_plPlacement; }; + inline const FLOATmatrix3D &GetRotationMatrix(void) const { return en_mRotation; }; + // this one is used in rendering - gets lerped placement between ticks + virtual CPlacement3D GetLerpedPlacement(void) const; + /* Find first sector that entity is in */ + CBrushSector *GetFirstSector(void); + /* Find first sector that entity is in (for UI purpuses) */ + CBrushSector *GetFirstSectorWithName(void); + + // teleport this entity to a new location -- takes care of telefrag damage + void Teleport(const CPlacement3D &plNew, BOOL bTelefrag=TRUE); + + void SetFlags(ULONG ulFlags); + inline ULONG GetFlags(void) const { return en_ulFlags; }; + inline void SetSpawnFlags(ULONG ulFlags) { en_ulSpawnFlags = ulFlags; } + inline ULONG GetSpawnFlags(void) const { return en_ulSpawnFlags; }; + void SetPhysicsFlags(ULONG ulFlags); + inline ULONG GetPhysicsFlags(void) const { return en_ulPhysicsFlags; }; + void SetCollisionFlags(ULONG ulFlags); + inline ULONG GetCollisionFlags(void) const { return en_ulCollisionFlags; }; + inline BOOL IsPredictor(void) const { return en_ulFlags&ENF_PREDICTOR; }; + inline BOOL IsPredicted(void) const { return en_ulFlags&ENF_PREDICTED; }; + inline BOOL IsPredictable(void) const { return en_ulFlags&ENF_PREDICTABLE; }; + CEntity *GetPredictor(void); + CEntity *GetPredicted(void); + // become predictable/unpredictable + void SetPredictable(BOOL bON); + // check if this instance is head of prediction chain + BOOL IsPredictionHead(void); + // get the prediction original (predicted), or self if not predicting + CEntity *GetPredictionTail(void); + // check if active for prediction now + BOOL IsAllowedForPrediction(void) const; + // check an event for prediction, returns true if already predicted + BOOL CheckEventPrediction(ULONG ulTypeID, ULONG ulEventID); + + inline enum RenderType GetRenderType(void) { return en_RenderType; }; + inline CEntityClass *GetClass(void) { return en_pecClass; }; + inline CWorld *GetWorld(void) { return en_pwoWorld; }; + inline CBrush3D *GetBrush(void) { return en_pbrBrush; }; + inline CModelObject *GetModelObject(void) { return en_pmoModelObject; }; + inline CModelInstance *GetModelInstance(void) { return en_pmiModelInstance; }; + inline CTerrain *GetTerrain(void) { return en_ptrTerrain; }; + inline CEntity *GetParent(void) { return en_penParent; }; + void SetParent(CEntity *penNewParent); + + // find first child of given class + CEntity *GetChildOfClass(const char *strClass); + + /* Test if the entity is an empty brush. */ + BOOL IsEmptyBrush(void) const; + + /* Return max Game Players */ + static INDEX GetMaxPlayers(void); + /* Return Player Entity */ + static CEntity *GetPlayerEntity(INDEX iPlayer); + + /* Get bounding box of this entity - for AI purposes only. */ + void GetBoundingBox(FLOATaabbox3D &box); + /* Get size of this entity - for UI purposes only. */ + void GetSize(FLOATaabbox3D &box); + /* Get last positions structure for particles. */ + CLastPositions *GetLastPositions(INDEX ctPositions); + /* Get nearest position of nearest brush polygon to this entity if available. */ + CBrushPolygon *GetNearestPolygon(FLOAT3D &vPoint, FLOATplane3D &plPlane, FLOAT &fDistanceToEdge); + /* Get absolute position of point on entity given relative to its size. */ + void GetEntityPointRatio(const FLOAT3D &vRatio, FLOAT3D &vAbsPoint, BOOL bLerped=FALSE); + /* Get absolute position of point on entity given in meters. */ + void GetEntityPointFixed(const FLOAT3D &vFixed, FLOAT3D &vAbsPoint); + /* Get sector that given point is in - point must be inside this entity. */ + CBrushSector *GetSectorFromPoint(const FLOAT3D &vPointAbs); + + // map world polygon to/from indices + CBrushPolygon *GetWorldPolygonPointer(INDEX ibpo); + INDEX GetWorldPolygonIndex(CBrushPolygon *pbpo); + + // virtual functions that are overridden to implement class specific behavior + /* Get name of this entity. */ + virtual const CTString &GetName(void) const; + virtual const CTString &GetDescription(void) const; // name + some more verbose data + /* Get first target of this entity. */ + virtual CEntity *GetTarget(void) const; + /* Check if entity can be used as a target. */ + virtual BOOL IsTargetable(void) const; + /* Check if entity is marker */ + virtual BOOL IsMarker(void) const; + /* Check if entity is important */ + virtual BOOL IsImportant(void) const; + /* Check if entity is moved on a route set up by its targets. */ + virtual BOOL MovesByTargetedRoute(CTString &strTargetProperty) const; + /* Check if entity can drop marker for making linked route. */ + virtual BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const; + /* Get light source information - return NULL if not a light source. */ + virtual CLightSource *GetLightSource(void); + /* Is target valid. */ + virtual BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget); + + /* Get force type name, return empty string if not used. */ + virtual const CTString &GetForceName(INDEX iForce); + /* Get forces in given point. */ + virtual void GetForce(INDEX iForce, const FLOAT3D &vPoint, + CForceStrength &fsGravity, CForceStrength &fsField); + /* Get entity that controls the force, used for change notification checking. */ + virtual CEntity *GetForceController(INDEX iForce); + + /* Get fog type name, return empty string if not used. */ + virtual const CTString &GetFogName(INDEX iFog); + /* Get fog, return FALSE for none. */ + virtual BOOL GetFog(INDEX iFog, class CFogParameters &fpFog); + + /* Get haze type name, return empty string if not used. */ + virtual const CTString &GetHazeName(INDEX iHaze); + /* Get haze, return FALSE for none. */ + virtual BOOL GetHaze(INDEX iHaze, class CHazeParameters &hpHaze, FLOAT3D &vViewDir); + + /* Get mirror type name, return empty string if not used. */ + virtual const CTString &GetMirrorName(INDEX iMirror); + /* Get mirror, return FALSE for none. */ + virtual BOOL GetMirror(INDEX iMirror, class CMirrorParameters &mpMirror); + + /* Get gradient type name, return empty string if not used. */ + virtual const CTString &GetGradientName(INDEX iGradient); + /* Get gradient, return FALSE for none. */ + virtual BOOL GetGradient(INDEX iGradient, class CGradientParameters &gpGradient); + + /* Get classification box stretching vector. */ + virtual FLOAT3D GetClassificationBoxStretch(void); + + /* Get anim data for given animation property - return NULL for none. */ + virtual CAnimData *GetAnimData(SLONG slPropertyOffset); + /* Adjust model shading parameters if needed - return TRUE if needs model shadows. */ + virtual BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, + COLOR &colLight, COLOR &colAmbient); + /* Adjust model mip factor if needed. */ + virtual void AdjustMipFactor(FLOAT &fMipFactor); + // get a different model object for rendering - so entity can change its appearance dynamically + // NOTE: base model is always used for other things (physics, etc). + virtual CModelObject *GetModelForRendering(void); + virtual CModelInstance *GetModelInstanceForRendering(void); + /* Get field information - return NULL if not a field. */ + virtual CFieldSettings *GetFieldSettings(void); + /* Render particles made by this entity. */ + virtual void RenderParticles(void); + /* Get current collision box index for this entity. */ + virtual INDEX GetCollisionBoxIndex(void); + /* Get current collision box - override for custom collision boxes. */ + virtual void GetCollisionBoxParameters(INDEX iBox, FLOATaabbox3D &box, INDEX &iEquality); + /* Render game view */ + virtual void RenderGameView(CDrawPort *pdp, void *pvUserData); + // apply mirror and stretch to the entity if supported + virtual void MirrorAndStretch(FLOAT fStretch, BOOL bMirrorX); + // get offset for depth-sorting of alpha models (in meters, positive is nearer) + virtual FLOAT GetDepthSortOffset(void); + // get visibility tweaking bits + virtual ULONG GetVisTweaks(void); + + /* Get max tessellation level. */ + virtual FLOAT GetMaxTessellationLevel(void); + + // get/set pointer to your predictor/predicted (autogenerated by ECC feature) + virtual CEntity *GetPredictionPair(void); + virtual void SetPredictionPair(CEntity *penPair); + + // add this entity to prediction + void AddToPrediction(void); + // called by other entities to set time prediction parameter + virtual void SetPredictionTime(TIME tmAdvance); // give time interval in advance to set + // called by engine to get the upper time limit + virtual TIME GetPredictionTime(void); // return moment in time up to which to predict this entity + // get maximum allowed range for predicting this entity + virtual FLOAT GetPredictionRange(void); + // add to prediction entities that this entity depends on + virtual void AddDependentsToPrediction(void); + // copy for prediction + virtual void CopyForPrediction(CEntity &enOrg); + + /* Send an event to this entity. */ + void SendEvent(const CEntityEvent &ee); + /* Send an event to all entities in a box (box must be around this entity). */ + void SendEventInRange(const CEntityEvent &ee, const FLOATaabbox3D &boxRange); + + /* apply some damage to the entity (see event EDamage for more info) */ + virtual void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection); + + /* Receive item through event - for AI purposes only */ + virtual BOOL ReceiveItem(const CEntityEvent &ee); + /* Get entity info - for AI purposes only */ + virtual void *GetEntityInfo(void); + /* Fill in entity statistics - for AI purposes only */ + virtual BOOL FillEntityStatistics(struct EntityStats *pes); + + /* Model change notify */ + void ModelChangeNotify(void); + /* Terrain change notify */ + void TerrainChangeNotify(void); +}; + +// check if entity is of given class +BOOL ENGINE_API IsOfClass(CEntity *pen, const char *pstrClassName); +BOOL ENGINE_API IsOfSameClass(CEntity *pen1, CEntity *pen2); +// check if entity is of given class or derived from +BOOL ENGINE_API IsDerivedFromClass(CEntity *pen, const char *pstrClassName); + +// all standard smart pointer functions are here as inlines +inline CEntityPointer::CEntityPointer(void) : ep_pen(NULL) {}; +inline CEntityPointer::~CEntityPointer(void) { ep_pen->RemReference(); }; +inline CEntityPointer::CEntityPointer(const CEntityPointer &penOther) : ep_pen(penOther.ep_pen) { + ep_pen->AddReference(); }; +inline CEntityPointer::CEntityPointer(CEntity *pen) : ep_pen(pen) { + ep_pen->AddReference(); }; +inline const CEntityPointer &CEntityPointer::operator=(CEntity *pen) { + pen->AddReference(); // must first add, then remove! + ep_pen->RemReference(); + ep_pen = pen; + return *this; +} +inline const CEntityPointer &CEntityPointer::operator=(const CEntityPointer &penOther) { + penOther.ep_pen->AddReference(); // must first add, then remove! + ep_pen->RemReference(); + ep_pen = penOther.ep_pen; + return *this; +} +inline CEntity* CEntityPointer::operator->(void) const { return ep_pen; } +inline CEntityPointer::operator CEntity*(void) const { return ep_pen; } +inline CEntity& CEntityPointer::operator*(void) const { return *ep_pen; } + +///////////////////////////////////////////////////////////////////// +// Reference counting functions +inline void CEntity::AddReference(void) { + if (this!=NULL) { + ASSERT(en_ctReferences>=0); + en_ctReferences++; + } +}; +inline void CEntity::RemReference(void) { + if (this!=NULL) { + ASSERT(en_ctReferences>0); + en_ctReferences--; + if(en_ctReferences==0) { + delete this; + } + } +}; + +/* + * Entity that is alive (has health). + */ +class ENGINE_API CLiveEntity : public CEntity { +public: + FLOAT en_fHealth; // health of the entity + + /* Copy entity from another entity of same class. */ + virtual void Copy(CEntity &enOther, ULONG ulFlags); + /* Read from stream. */ + virtual void Read_t( CTStream *istr); // throw char * + /* Write to stream. */ + virtual void Write_t( CTStream *ostr); // throw char * +public: + /* Set health of the entity. (Use only for initialization!) */ + void SetHealth(FLOAT fHealth) { en_fHealth = fHealth; }; + +public: + /* Constructor. */ + CLiveEntity(void); + + /* Get health of the entity. */ + FLOAT GetHealth(void) const { return en_fHealth; }; + // apply some damage to the entity (see event EDamage for more info) + virtual void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection); + + // returns bytes of memory used by this object + inline SLONG GetUsedMemory(void) { + return( sizeof(CLiveEntity) - sizeof(CEntity) + CEntity::GetUsedMemory()); + }; +}; + +// flag for entities that are not waiting for thinking +#define THINKTIME_NEVER (-1.f) + +/* + * Entity that can percept things and make decisions (one that has its own AI). + */ +class ENGINE_API CRationalEntity : public CLiveEntity { +public: + CListNode en_lnInTimers; // node in list of waiting timers - sorted by wait time +public: + TIME en_timeTimer; // moment in time this entity waits for timer + + CStaticStackArray en_stslStateStack; // stack of states for entity AI + + /* Calculate physics for moving. */ + virtual void ClearMovingTemp(void); + virtual void PreMoving(void); + virtual void DoMoving(void); + virtual void PostMoving(void); + // create a checksum value for sync-check + virtual void ChecksumForSync(ULONG &ulCRC, INDEX iExtensiveSyncCheck); + // dump sync data to text file + virtual void DumpSync_t(CTStream &strm, INDEX iExtensiveSyncCheck); // throw char * + + /* Copy entity from another entity of same class. */ + virtual void Copy(CEntity &enOther, ULONG ulFlags); + /* Read from stream. */ + virtual void Read_t( CTStream *istr); // throw char * + /* Write to stream. */ + virtual void Write_t( CTStream *ostr); // throw char * + + /* Unwind stack to a given state. */ + void UnwindStack(SLONG slThisState); + +public: + + /* Jump to a new state. */ + void Jump(SLONG slThisState, SLONG slTargetState, BOOL bOverride, const CEntityEvent &eeInput); + /* Call a subautomaton. */ + void Call(SLONG slThisState, SLONG slTargetState, BOOL bOverride, const CEntityEvent &eeInput); + /* Return from a subautomaton. */ + void Return(SLONG slThisState, const CEntityEvent &eeReturn); + // print stack to debug output + const char *PrintStackDebug(void); + + /* Set next timer event to occur at given moment time. */ + void SetTimerAt(TIME timeAbsolute); + /* Set next timer event to occur after given time has elapsed. */ + void SetTimerAfter(TIME timeDelta); + /* Cancel eventual pending timer. */ + void UnsetTimer(void); + + /* Called after creating and setting its properties. */ + virtual void OnInitialize(const CEntityEvent &eeInput); + /* Called before releasing entity. */ + virtual void OnEnd(void); +public: + /* Constructor. */ + CRationalEntity(void); + + /* Handle an event - return false if event was not handled. */ + virtual BOOL HandleEvent(const CEntityEvent &ee); + + // returns bytes of memory used by this object + inline SLONG GetUsedMemory(void) { + SLONG slUsedMemory = sizeof(CRationalEntity) - sizeof(CLiveEntity) + CLiveEntity::GetUsedMemory(); + slUsedMemory += en_stslStateStack.sa_Count * sizeof(SLONG); + return slUsedMemory; + }; +}; + + +ENGINE_API void EntityAdjustBonesCallback(void *pData); +ENGINE_API void EntityAdjustShaderParamsCallback(void *pData,INDEX iSurfaceID,CShader *pShader,ShaderParams &spParams); + +extern "C" ENGINE_API class CDLLEntityClass CEntity_DLLClass; +extern "C" ENGINE_API class CDLLEntityClass CLiveEntity_DLLClass; +extern "C" ENGINE_API class CDLLEntityClass CRationalEntity_DLLClass; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Entities/EntityClass.cpp b/Sources/Engine/Entities/EntityClass.cpp new file mode 100644 index 0000000..121a95c --- /dev/null +++ b/Sources/Engine/Entities/EntityClass.cpp @@ -0,0 +1,606 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +///////////////////////////////////////////////////////////////////// +// CEntityClass + +/* + * Default constructor. + */ +CEntityClass::CEntityClass(void) +{ + ec_fnmClassDLL.Clear(); + ec_hiClassDLL = NULL; + ec_pdecDLLClass = NULL; +} +/* + * Constructor for a fixed class. + */ +CEntityClass::CEntityClass(class CDLLEntityClass *pdecDLLClass) +{ + ec_pdecDLLClass = pdecDLLClass; + ec_hiClassDLL = NULL; + ec_fnmClassDLL.Clear(); +} + +/* + * Destructor. + */ +CEntityClass::~CEntityClass(void) +{ + Clear(); +} + +///////////////////////////////////////////////////////////////////// +// Reference counting functions +void CEntityClass::AddReference(void) { + if (this!=NULL) { + MarkUsed(); + } +}; +void CEntityClass::RemReference(void) { + if (this!=NULL) { + _pEntityClassStock->Release(this); + } +}; + +/* + * Clear the object. + */ +void CEntityClass::Clear(void) +{ + // if the DLL is loaded + if (ec_hiClassDLL != NULL) { + // detach the DLL + ec_pdecDLLClass->dec_OnEndClass(); + + // release all components needed by the DLL + ReleaseComponents(); + + /* The dll is never released from memory, because declared shell symbols + * must stay avaliable, since they cannot be undeclared. + */ + // free it + //BOOL bSuccess = FreeLibrary(ec_hiClassDLL); + //ASSERT(bSuccess); + } + ec_pdecDLLClass = NULL; + ec_hiClassDLL = NULL; + ec_fnmClassDLL.Clear(); +} + +/* Check that all properties have been properly declared. */ +void CEntityClass::CheckClassProperties(void) +{ +// do nothing in release version +#ifndef NDEBUG + // for all classes in hierarchy of this entity + {for(CDLLEntityClass *pdecDLLClass1 = ec_pdecDLLClass; + pdecDLLClass1!=NULL; + pdecDLLClass1 = pdecDLLClass1->dec_pdecBase) { + // for all properties + for(INDEX iProperty1=0; iProperty1dec_ctProperties; iProperty1++) { + CEntityProperty &epProperty1 = pdecDLLClass1->dec_aepProperties[iProperty1]; + + // for all classes in hierarchy of this entity + for(CDLLEntityClass *pdecDLLClass2 = ec_pdecDLLClass; + pdecDLLClass2!=NULL; + pdecDLLClass2 = pdecDLLClass2->dec_pdecBase) { + // for all properties + for(INDEX iProperty2=0; iProperty2dec_ctProperties; iProperty2++) { + CEntityProperty &epProperty2 = pdecDLLClass2->dec_aepProperties[iProperty2]; + // the two properties must not have same id unless they are same property + ASSERTMSG(&epProperty1==&epProperty2 || epProperty1.ep_ulID!=epProperty2.ep_ulID, + "No two properties may have same id!"); + } + } + } + }} + + // for all classes in hierarchy of this entity + {for(CDLLEntityClass *pdecDLLClass1 = ec_pdecDLLClass; + pdecDLLClass1!=NULL; + pdecDLLClass1 = pdecDLLClass1->dec_pdecBase) { + // for all components + for(INDEX iComponent1=0; iComponent1dec_ctComponents; iComponent1++) { + CEntityComponent &ecComponent1 = pdecDLLClass1->dec_aecComponents[iComponent1]; + + // for all classes in hierarchy of this entity + for(CDLLEntityClass *pdecDLLClass2 = ec_pdecDLLClass; + pdecDLLClass2!=NULL; + pdecDLLClass2 = pdecDLLClass2->dec_pdecBase) { + // for all components + for(INDEX iComponent2=0; iComponent2dec_ctComponents; iComponent2++) { + CEntityComponent &ecComponent2 = pdecDLLClass2->dec_aecComponents[iComponent2]; + // the two components must not have same id unless they are same component + ASSERTMSG(&ecComponent1==&ecComponent2 || ecComponent1.ec_slID!=ecComponent2.ec_slID, + "No two components may have same id!"); + } + } + } + }} +#endif +} + +/* + * Construct a new member of the class. + */ +CEntity *CEntityClass::New(void) +{ + // the DLL must be loaded + ASSERT(ec_pdecDLLClass!= NULL); + // ask the DLL class to call the 'operator new' in the scope where the class is declared + CEntity *penNew = ec_pdecDLLClass->dec_New(); + // remember this class as class of the entity + AddReference(); + penNew->en_pecClass = this; + // set all properties to default + penNew->SetDefaultProperties(); + + // return it + return penNew; +} + +/* + * Obtain all components from component table. + */ +void CEntityClass::ObtainComponents_t(void) +{ + // for each component + for (INDEX iComponent=0; iComponentdec_ctComponents; iComponent++) { + // if not precaching all + if( gam_iPrecachePolicydec_aecComponents[iComponent]; + if (ec.ec_ectType!=ECT_CLASS) { + // skip it + continue; + } + } + + // try to + try { + // obtain the component + ec_pdecDLLClass->dec_aecComponents[iComponent].Obtain_t(); + // if failed + } catch (char *) { + // if in paranoia mode + if( gam_iPrecachePolicy==PRECACHE_PARANOIA) { + // fail + throw; + // if not in paranoia mode + } else { + // ignore all errors + NOTHING; + } + } + } +} + +/* + * Release all components from component table. + */ +void CEntityClass::ReleaseComponents(void) +{ + // for each component + for (INDEX iComponent=0; iComponentdec_ctComponents; iComponent++) { + // release the component + ec_pdecDLLClass->dec_aecComponents[iComponent].Release(); + } +} + +// overrides from CSerial ///////////////////////////////////////////////////// + +/* + * Load a Dynamic Link Library. + */ +HINSTANCE LoadDLL_t(const char *strFileName) // throw char * +{ + HINSTANCE hiDLL = ::LoadLibraryA(strFileName); + + // if the DLL can not be loaded + if (hiDLL==NULL) { + // get the error code + DWORD dwMessageId = GetLastError(); + // format the windows error message + LPVOID lpMsgBuf; + DWORD dwSuccess = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + dwMessageId, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // default language + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + CTString strWinError; + // if formatting succeeds + if (dwSuccess!=0) { + // copy the result + strWinError = ((char *)lpMsgBuf); + // free the windows message buffer + LocalFree( lpMsgBuf ); + } else { + // set our message about the failure + CTString strError; + strError.PrintF( + TRANS("Cannot format error message!\n" + "Original error code: %d,\n" + "Formatting error code: %d.\n"), + dwMessageId, GetLastError()); + strWinError = strError; + } + + // report error + ThrowF_t(TRANS("Cannot load DLL file '%s':\n%s"), strFileName, strWinError); + } + return hiDLL; +} + +/* + * Read from stream. + */ +void CEntityClass::Read_t( CTStream *istr) // throw char * +{ + // read the dll filename and class name from the stream + CTFileName fnmDLL; + fnmDLL.ReadFromText_t(*istr, "Package: "); + CTString strClassName; + strClassName.ReadFromText_t(*istr, "Class: "); + + // create name of dll + #ifndef NDEBUG + fnmDLL = _fnmApplicationExe.FileDir()+fnmDLL.FileName()+_strModExt+"D"+fnmDLL.FileExt(); + #else + fnmDLL = _fnmApplicationExe.FileDir()+fnmDLL.FileName()+_strModExt+fnmDLL.FileExt(); + #endif + + // load the DLL + CTFileName fnmExpanded; + ExpandFilePath(EFP_READ, fnmDLL, fnmExpanded); + + ec_hiClassDLL = LoadDLL_t(fnmExpanded); + ec_fnmClassDLL = fnmDLL; + + // get the pointer to the DLL class structure + ec_pdecDLLClass = (CDLLEntityClass *) GetProcAddress(ec_hiClassDLL, strClassName+"_DLLClass"); + // if class structure is not found + if (ec_pdecDLLClass == NULL) { + // free the library + BOOL bSuccess = FreeLibrary(ec_hiClassDLL); + ASSERT(bSuccess); + ec_hiClassDLL = NULL; + ec_fnmClassDLL.Clear(); + // report error + ThrowF_t(TRANS("Class '%s' not found in entity class package file '%s'"), strClassName, fnmDLL); + } + + // obtain all components needed by the DLL + { + CTmpPrecachingNow tpn; + ObtainComponents_t(); + } + + // attach the DLL + ec_pdecDLLClass->dec_OnInitClass(); + + // check that the class properties have been properly declared + CheckClassProperties(); +} + +/* + * Write to stream. + */ +void CEntityClass::Write_t( CTStream *ostr) // throw char * +{ + ASSERTALWAYS("Do not write CEntityClass objects!"); +} +// get amount of memory used by this object +SLONG CEntityClass::GetUsedMemory(void) +{ + // we don't know exact memory used, but we want to enumerate them + return 0; +} +// check if this kind of objects is auto-freed +BOOL CEntityClass::IsAutoFreed(void) +{ + return FALSE; +}; +// gather the CRC of the file +void CEntityClass::AddToCRCTable(void) +{ + const CTFileName &fnm = GetName(); + // if already added + if (CRCT_IsFileAdded(fnm)) { + // do nothing + return; + } + + // add the file itself + CRCT_AddFile_t(fnm); + // add its DLL + CRCT_AddFile_t(ec_fnmClassDLL); +} + +/* Get pointer to entity property from its name. */ +class CEntityProperty *CEntityClass::PropertyForName(const CTString &strPropertyName) { + return ec_pdecDLLClass->PropertyForName(strPropertyName); +}; +/* Get pointer to entity property from its packed identifier. */ +class CEntityProperty *CEntityClass::PropertyForTypeAndID( + ULONG ulType, ULONG ulID) { + return ec_pdecDLLClass->PropertyForTypeAndID((CEntityProperty::PropertyType)ulType, ulID); +}; + +/* Get event handler for given state and event code. */ +CEntity::pEventHandler CEntityClass::HandlerForStateAndEvent(SLONG slState, SLONG slEvent) { + return ec_pdecDLLClass->HandlerForStateAndEvent(slState, slEvent); +} + +/* Get pointer to component from its identifier. */ +class CEntityComponent *CEntityClass::ComponentForTypeAndID( + EntityComponentType ectType, SLONG slID) { + return ec_pdecDLLClass->ComponentForTypeAndID(ectType, slID); +} +/* Get pointer to component from the component. */ +class CEntityComponent *CEntityClass::ComponentForPointer(void *pv) { + return ec_pdecDLLClass->ComponentForPointer(pv); +} + +// convert value of an enum to its name +const char *CEntityPropertyEnumType::NameForValue(INDEX iValue) +{ + for(INDEX i=0; iPropertyForName(strPropertyName); + // otherwise + } else { + // none found + return NULL; + } +} + +/* + * Get pointer to entity property from its packed identifier. + */ +class CEntityProperty *CDLLEntityClass::PropertyForTypeAndID( + CEntityProperty::PropertyType eptType, ULONG ulID) +{ + // for each property + for (INDEX iProperty=0; iPropertyPropertyForTypeAndID(eptType, ulID); + // otherwise + } else { + // none found + return NULL; + } +}; + +/* + * Get pointer to component from its identifier. + */ +class CEntityComponent *CDLLEntityClass::ComponentForTypeAndID( + EntityComponentType ectType, SLONG slID) +{ + // for each component + for (INDEX iComponent=0; iComponentComponentForTypeAndID(ectType, slID); + // otherwise + } else { + // none found + return NULL; + } +} +/* + * Get pointer to component from the component. + */ +class CEntityComponent *CDLLEntityClass::ComponentForPointer(void *pv) +{ + // for each component + for (INDEX iComponent=0; iComponentComponentForPointer(pv); + // otherwise + } else { + // none found + return NULL; + } +} + +// precache given component +void CDLLEntityClass::PrecacheModel(SLONG slID) +{ + CTmpPrecachingNow tpn; + + CEntityComponent *pecModel = ComponentForTypeAndID(ECT_MODEL, slID); + ASSERT(pecModel!=NULL); + pecModel->ObtainWithCheck(); +} + +void CDLLEntityClass::PrecacheTexture(SLONG slID) +{ + CTmpPrecachingNow tpn; + + CEntityComponent *pecTexture = ComponentForTypeAndID(ECT_TEXTURE, slID); + ASSERT(pecTexture!=NULL); + pecTexture->ObtainWithCheck(); +} + +void CDLLEntityClass::PrecacheSound(SLONG slID) +{ + CTmpPrecachingNow tpn; + + CEntityComponent *pecSound = ComponentForTypeAndID(ECT_SOUND, slID); + ASSERT(pecSound!=NULL); + pecSound->ObtainWithCheck(); +} + +void CDLLEntityClass::PrecacheClass(SLONG slID, INDEX iUser /* = -1 */) +{ + CTmpPrecachingNow tpn; + + CEntityComponent *pecClass = ComponentForTypeAndID(ECT_CLASS, slID); + ASSERT(pecClass!=NULL); + pecClass->ObtainWithCheck(); + pecClass->ec_pecEntityClass->ec_pdecDLLClass->dec_OnPrecache( + pecClass->ec_pecEntityClass->ec_pdecDLLClass, iUser); +} + +/* + * Get event handler given state and event code. + */ +CEntity::pEventHandler CDLLEntityClass::HandlerForStateAndEvent(SLONG slState, SLONG slEvent) +{ + // we ignore the event code here + (void) slEvent; + + // for each handler + for (INDEX iHandler=0; iHandlerHandlerForStateAndEvent(slState, slEvent); + // otherwise + } else { + // none found + return NULL; + } +} + +/* Get event handler name for given state. */ +const char *CDLLEntityClass::HandlerNameForState(SLONG slState) +{ + // for each handler + for (INDEX iHandler=0; iHandlerHandlerNameForState(slState); + // otherwise + } else { + // none found + return "no handler!?"; + } +} + +/* Get derived class override for given state. */ +SLONG CDLLEntityClass::GetOverridenState(SLONG slState) +{ + // for each handler + for (INDEX iHandler=0; iHandler=0 && + dec_aeheHandlers[iHandler].ehe_slBaseState==slState) { + // return overriden state with possible recursive overriding + return GetOverridenState(dec_aeheHandlers[iHandler].ehe_slState); + } + } + // if base class exists + if (dec_pdecBase!=NULL) { + // look in the base class + return dec_pdecBase->GetOverridenState(slState); + // otherwise + } else { + // none found + return slState; + } +} diff --git a/Sources/Engine/Entities/EntityClass.h b/Sources/Engine/Entities/EntityClass.h new file mode 100644 index 0000000..5084d3a --- /dev/null +++ b/Sources/Engine/Entities/EntityClass.h @@ -0,0 +1,73 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ENTITYCLASS_H +#define SE_INCL_ENTITYCLASS_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include /* rcg10042001 */ + +/* + * General structure of an entity class. + */ +class ENGINE_API CEntityClass : public CSerial { +public: + /* Obtain all components from component table. */ + void ObtainComponents_t(void); // throw char * + /* Release all components from component table. */ + void ReleaseComponents(void); +public: + CTFileName ec_fnmClassDLL; // filename of the DLL with the class + HINSTANCE ec_hiClassDLL; // handle to the DLL with the class + class CDLLEntityClass *ec_pdecDLLClass; // pointer to DLL class in the DLL + + /* Default constructor. */ + CEntityClass(void); + /* Constructor for a fixed class. */ + CEntityClass(class CDLLEntityClass *pdecDLLClass); + /* Destructor. */ + ~CEntityClass(void); + /* Clear the object. */ + void Clear(void); + + // reference counting functions + void AddReference(void); + void RemReference(void); + + /* Check that all properties have been properly declared. */ + void CheckClassProperties(void); + + /* Construct a new member of the class. */ + class CEntity *New(void); + + /* Get pointer to entity property from its name. */ + class CEntityProperty *PropertyForName(const CTString &strPropertyName); + /* Get pointer to entity property from its packed identifier. */ + class CEntityProperty *PropertyForTypeAndID(ULONG ulType, ULONG ulID); + /* Get event handler for given state and event code. */ + CEntity::pEventHandler HandlerForStateAndEvent(SLONG slState, SLONG slEvent); + /* Get pointer to component from its type and identifier. */ + class CEntityComponent *ComponentForTypeAndID(enum EntityComponentType ectType, SLONG slID); + /* Get pointer to component from the component. */ + class CEntityComponent *ComponentForPointer(void *pv); + + // overrides from CSerial + /* Read from stream. */ + virtual void Read_t( CTStream *istr); // throw char * + /* Write to stream. */ + virtual void Write_t( CTStream *ostr); // throw char * + + // get amount of memory used by this object + SLONG GetUsedMemory(void); + // check if this kind of objects is auto-freed + BOOL IsAutoFreed(void); + // gather the CRC of the file + void AddToCRCTable(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Entities/EntityCollision.cpp b/Sources/Engine/Entities/EntityCollision.cpp new file mode 100644 index 0000000..b9a1e2b --- /dev/null +++ b/Sources/Engine/Entities/EntityCollision.cpp @@ -0,0 +1,310 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class CClipTest { +public: + CEntity *ct_penEntity; // the entity + CEntity *ct_penObstacle; // obstacle entity (if cannot change) + + INDEX ct_iNewCollisionBox; // index of new collision box to set + CCollisionInfo ct_ciNew; // collision info with new box + FLOATaabbox3D ct_boxTotal; // union box for old and new in absolute coordinates + + CListHead ct_lhActiveSectors; // sectors that may be of interest + + BOOL PointTouchesSphere( + const FLOAT3D &vPoint, + const FLOAT3D &vSphereCenter, + const FLOAT fSphereRadius); + BOOL PointTouchesCylinder( + const FLOAT3D &vPoint, + const FLOAT3D &vCylinderBottomCenter, + const FLOAT3D &vCylinderTopCenter, + const FLOAT fCylinderRadius); + // project spheres of a collision info to given placement + void ProjectSpheresToPlacement(CCollisionInfo &ci, + FLOAT3D &vPosition, FLOATmatrix3D &mRotation); + + // test if a sphere touches brush polygon + BOOL SphereTouchesBrushPolygon(const CMovingSphere &msMoving, + CBrushPolygon *pbpoPolygon); + // test if entity touches brush polygon + BOOL EntityTouchesBrushPolygon(CBrushPolygon *pbpoPolygon); + // test if an entity can change to a new collision box without intersecting anything + BOOL CanChange(CEntity *pen, INDEX iNewCollisionBox); + + ~CClipTest(void); + +}; + +// test if an entity can change to a new collision box without intersecting anything +BOOL CanEntityChangeCollisionBox(CEntity *pen, INDEX iNewCollisionBox, CEntity **ppenObstacle) +{ + // if the entity is not linked to any sectors + if (pen->en_rdSectors.IsEmpty()) { + // make sure that the classification is ok + pen->FindSectorsAroundEntity(); + } + + CClipTest ct; + BOOL bCan = ct.CanChange(pen, iNewCollisionBox); + *ppenObstacle = ct.ct_penObstacle; + return bCan; +} + // project spheres of a collision info to given placement +void CClipTest::ProjectSpheresToPlacement(CCollisionInfo &ci, + FLOAT3D &vPosition, FLOATmatrix3D &mRotation) +{ + // for each sphere + FOREACHINSTATICARRAY(ci.ci_absSpheres, CMovingSphere, itms) { + // project it in start point + itms->ms_vRelativeCenter0 = itms->ms_vCenter*mRotation+vPosition; + } +} + +// test point to a sphere +BOOL CClipTest::PointTouchesSphere( + const FLOAT3D &vPoint, + const FLOAT3D &vSphereCenter, + const FLOAT fSphereRadius) +{ + FLOAT fD = (vSphereCenter-vPoint).Length(); + return fDfCylinderBottomToTopLength) { + // doesn't touch + return FALSE; + } + + // find distance from point to cylinder axis + FLOAT fD = (vBottomToPoint-vCylinderDirection*fPointL).Length(); + + return fDbpo_pbplPlane->bpl_plAbsolute; + // calculate point distance from polygon plane + FLOAT fDistance = plPolygon.PointDistance(msMoving.ms_vRelativeCenter0); + + // if is further away than sphere radius + if (fDistance>msMoving.ms_fR || fDistance<-msMoving.ms_fR) { + // no collision + return FALSE; + } + + // calculate coordinate projected to the polygon plane + FLOAT3D vPosMid = msMoving.ms_vRelativeCenter0; + FLOAT3D vHitPoint = plPolygon.ProjectPoint(vPosMid); + // find major axes of the polygon plane + INDEX iMajorAxis1, iMajorAxis2; + GetMajorAxesForPlane(plPolygon, iMajorAxis1, iMajorAxis2); + + // create an intersector + CIntersector isIntersector(vHitPoint(iMajorAxis1), vHitPoint(iMajorAxis2)); + // for all edges in the polygon + FOREACHINSTATICARRAY(pbpoPolygon->bpo_abpePolygonEdges, CBrushPolygonEdge, + itbpePolygonEdge) { + // get edge vertices (edge direction is irrelevant here!) + const FLOAT3D &vVertex0 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + const FLOAT3D &vVertex1 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + // pass the edge to the intersector + isIntersector.AddEdge( + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2), + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2)); + } + // if the polygon is intersected by the ray + if (isIntersector.IsIntersecting()) { + return TRUE; + } + + // for each edge in polygon + FOREACHINSTATICARRAY(pbpoPolygon->bpo_abpePolygonEdges, CBrushPolygonEdge, itbpe) { + // get edge vertices (edge direction is important here!) + FLOAT3D vVertex0, vVertex1; + itbpe->GetVertexCoordinatesAbsolute(vVertex0, vVertex1); + + // test sphere to the edge (point to the edge cylinder) + if (PointTouchesCylinder( + msMoving.ms_vRelativeCenter0, // point, + vVertex0, // cylinder bottom center, + vVertex1, // cylinder top center, + msMoving.ms_fR // cylinder radius + )) { + return TRUE; + } + // test sphere to the first vertex + // NOTE: using point to sphere collision + if (PointTouchesSphere( + msMoving.ms_vRelativeCenter0, // pount + vVertex0, // sphere center + msMoving.ms_fR // sphere radius + )) { + return TRUE; + } + } + + return FALSE; +} + +// test if entity touches brush polygon +BOOL CClipTest::EntityTouchesBrushPolygon(CBrushPolygon *pbpoPolygon) +{ + // for each sphere + FOREACHINSTATICARRAY(ct_ciNew.ci_absSpheres, CMovingSphere, itms) { + // if it touches + if (SphereTouchesBrushPolygon(*itms, pbpoPolygon)) { + return TRUE; + } + } + return FALSE; +} + +// test if an entity can change to a new collision box without intersecting anything +BOOL CClipTest::CanChange(CEntity *pen, INDEX iNewCollisionBox) +{ + // can be used only for models + ASSERT( + pen->en_RenderType==CEntity::RT_MODEL || + pen->en_RenderType==CEntity::RT_EDITORMODEL || + pen->en_RenderType==CEntity::RT_SKAMODEL || + pen->en_RenderType==CEntity::RT_SKAEDITORMODEL); + + // safety check + if (pen->en_pciCollisionInfo==NULL) { + return FALSE; + } + + // remember parameters + ct_penEntity = pen; + ct_iNewCollisionBox = iNewCollisionBox; + ct_penObstacle = NULL; + + // create new temporary collision info + ct_ciNew.FromModel(pen, iNewCollisionBox); + // project it to entity placement + ProjectSpheresToPlacement(ct_ciNew, + pen->en_plPlacement.pl_PositionVector, pen->en_mRotation); + + // get total bounding box encompassing both old and new collision boxes + FLOATaabbox3D boxOld, boxNew; + ASSERT(ct_penEntity->en_pciCollisionInfo!=NULL); + CCollisionInfo &ciOld = *ct_penEntity->en_pciCollisionInfo; + ciOld.MakeBoxAtPlacement(ct_penEntity->en_plPlacement.pl_PositionVector, + ct_penEntity->en_mRotation, boxOld); + ct_ciNew.MakeBoxAtPlacement(ct_penEntity->en_plPlacement.pl_PositionVector, + ct_penEntity->en_mRotation, boxNew); + + ct_boxTotal = boxOld; + ct_boxTotal |= boxNew; + + // for each zoning sector that this entity is in + {FOREACHSRCOFDST(ct_penEntity->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // add it to list of active sectors + ct_lhActiveSectors.AddTail(pbsc->bsc_lnInActiveSectors); + ENDFOR} + + // for each active sector + FOREACHINLIST(CBrushSector, bsc_lnInActiveSectors, ct_lhActiveSectors, itbsc) { + // for non-zoning brush entities in the sector + {FOREACHDSTOFSRC(itbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) + if (pen->en_RenderType!=CEntity::RT_BRUSH&& + (_pNetwork->ga_ulDemoMinorVersion<=4 || pen->en_RenderType!=CEntity::RT_FIELDBRUSH)) { + break; // brushes are sorted first in list + } + + // get first mip + CBrushMip *pbm = pen->en_pbrBrush->GetFirstMip(); + // if brush mip exists for that mip factor + if (pbm!=NULL) { + // for each sector in the mip + {FOREACHINDYNAMICARRAY(pbm->bm_abscSectors, CBrushSector, itbscNonZoning) { + CBrushSector &bscNonZoning = *itbscNonZoning; + // add it to list of active sectors + if(!bscNonZoning.bsc_lnInActiveSectors.IsLinked()) { + ct_lhActiveSectors.AddTail(bscNonZoning.bsc_lnInActiveSectors); + } + }} + } + ENDFOR} + + // if the sector's brush doesn't have collision + CEntity *penSectorBrush = itbsc->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + if (penSectorBrush->en_ulCollisionFlags==0 || + (_pNetwork->ga_ulDemoMinorVersion>2 && penSectorBrush->en_RenderType!=CEntity::RT_BRUSH) ) { + // skip it + continue; + } + + // for each polygon in the sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + CBrushPolygon *pbpo = itbpo; + // if its bbox has no contact with bbox to test + if (!pbpo->bpo_boxBoundingBox.HasContactWith(ct_boxTotal) ) { + // skip it + continue; + } + + // if it is passable + if (pbpo->bpo_ulFlags&BPOF_PASSABLE) { + // for each sector related to the portal + {FOREACHDSTOFSRC(pbpo->bpo_rsOtherSideSectors, CBrushSector, bsc_rdOtherSidePortals, pbscRelated) + // if the sector is not active + if (!pbscRelated->bsc_lnInActiveSectors.IsLinked()) { + // add it to active list + ct_lhActiveSectors.AddTail(pbscRelated->bsc_lnInActiveSectors); + } + ENDFOR} + + // if it is not passable + } else { + // if entity touches it + if (EntityTouchesBrushPolygon(pbpo)) { + // test fails + ct_penObstacle = pbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + return FALSE; + } + } + } + } + return TRUE; +} + +CClipTest::~CClipTest(void) +{ + // clear list of active sectors + {FORDELETELIST(CBrushSector, bsc_lnInActiveSectors, ct_lhActiveSectors, itbsc) { + itbsc->bsc_lnInActiveSectors.Remove(); + }} +} diff --git a/Sources/Engine/Entities/EntityCollision.h b/Sources/Engine/Entities/EntityCollision.h new file mode 100644 index 0000000..a28352d --- /dev/null +++ b/Sources/Engine/Entities/EntityCollision.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ENTITYCOLLISION_H +#define SE_INCL_ENTITYCOLLISION_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include + +/* + * Bounding sphere used for movement clipping. + */ +class ENGINE_API CMovingSphere { +public: +// implementation: + FLOAT3D ms_vCenter; // sphere center in space of moving entity + FLOAT ms_fR; // sphere radius + + FLOAT3D ms_vRelativeCenter0; // start point of sphere center in space of standing entity + FLOAT3D ms_vRelativeCenter1; // end point of sphere center in space of standing entity + FLOATaabbox3D ms_boxMovement; // the movement path in space of standing entity +public: +// interface: +}; + +// Used for caching collision info for models +#define CIF_IGNOREHEADING (1L<<0) // heading rotation can be ignored +#define CIF_IGNOREROTATION (1L<<1) // any rotation can be ignored +#define CIF_CANSTANDONHANDLE (1L<<2) // entity can stand on its handle sphere +#define CIF_BRUSH (1L<<3) // entity is a brush +class ENGINE_API CCollisionInfo { +public: + CStaticArray ci_absSpheres; // collision spheres of the model + FLOAT ci_fMinHeight, ci_fMaxHeight; // height span of the model + FLOAT ci_fHandleY; // y coordinate of handle sphere to stand on + FLOAT ci_fHandleR; // radius of handle sphere to stand on + FLOATaabbox3D ci_boxCurrent; // current bounding box + ULONG ci_ulFlags; + + CCollisionInfo(void) {}; + CCollisionInfo(const CCollisionInfo &ciOrg); + /* Create collision info for a model. */ + void FromModel(CEntity *penModel, INDEX iBox); + /* Create collision info for a ska model */ + void FromSkaModel(CEntity *penModel, INDEX iBox); + /* Create collision info for a brush. */ + void FromBrush(CBrush3D *pbrBrush); + /* Calculate bounding box in absolute space from position. */ + void MakeBoxAtPlacement(const FLOAT3D &vPosition, const FLOATmatrix3D &mRotation, + FLOATaabbox3D &box); + // get maximum radius of entity in xz plane (relative to entity handle) + FLOAT GetMaxFloorRadius(void); + + inline void Clear(void) { ci_absSpheres.Clear(); }; +}; + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Entities/EntityCopying.cpp b/Sources/Engine/Entities/EntityCopying.cpp new file mode 100644 index 0000000..b9e6a22 --- /dev/null +++ b/Sources/Engine/Entities/EntityCopying.cpp @@ -0,0 +1,734 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +class CPointerRemapping { +public: + CEntity *pr_penOriginal; + CEntity *pr_penCopy; + + inline void Clear(void) {}; +}; + +static CStaticArray _aprRemaps; +static BOOL _bRemapPointersToNULLs = TRUE; +extern BOOL _bReinitEntitiesWhileCopying = TRUE; +static BOOL _bMirrorAndStretch = FALSE; +static FLOAT _fStretch = 1.0f; +static enum WorldMirrorType _wmtMirror = WMT_NONE; +extern INDEX _ctPredictorEntities; + +// mirror a placement of one entity +static void MirrorAndStretchPlacement(CPlacement3D &pl) +{ + ASSERT(_wmtMirror==WMT_X||_wmtMirror==WMT_Y||_wmtMirror==WMT_Z||_wmtMirror==WMT_NONE); + + // if there should be mirror + if (_wmtMirror!=WMT_NONE) { + // make rotation matrix for the placement + FLOATmatrix3D m; + MakeRotationMatrix(m, pl.pl_OrientationAngle); + // get row vectors, with object x flipped + FLOAT3D vX(-m(1,1),m(1,2),m(1,3)); + FLOAT3D vY(-m(2,1),m(2,2),m(2,3)); + FLOAT3D vZ(-m(3,1),m(3,2),m(3,3)); + + // flip needed axis + switch(_wmtMirror) { + case WMT_X: + pl.pl_PositionVector(1) = -pl.pl_PositionVector(1); + vX = -vX; + break; + case WMT_Y: + pl.pl_PositionVector(2) = -pl.pl_PositionVector(2); + vY = -vY; + break; + case WMT_Z: + pl.pl_PositionVector(3) = -pl.pl_PositionVector(3); + vZ = -vZ; + break; + default: ASSERT(FALSE); + } + + // compose matrix back from the vectors + m(1,1) = vX(1); m(2,1) = vY(1); m(3,1) = vZ(1); + m(1,2) = vX(2); m(2,2) = vY(2); m(3,2) = vZ(2); + m(1,3) = vX(3); m(2,3) = vY(3); m(3,3) = vZ(3); + // decompose matrix into angles + DecomposeRotationMatrix(pl.pl_OrientationAngle, m); + } + + pl.pl_PositionVector*=_fStretch; +} + +CEntity *CEntity::FindRemappedEntityPointer(CEntity *penOriginal) +{ + // if original is null + if (penOriginal==NULL) { + // copy is null + return NULL; + } + + // try to find valid remap + {FOREACHINSTATICARRAY(_aprRemaps, CPointerRemapping, itpr) { + if (itpr->pr_penOriginal==penOriginal) { + return itpr->pr_penCopy; + } + }} + // if none found, copy is either null or original + return _bRemapPointersToNULLs?NULL:penOriginal; +} + +/* + * Copy entity from another entity of same class. + * NOTES: + * - Doesn't copy placement, it must be done on creation. + * - Entity must be initialized afterwards. + */ +void CEntity::Copy(CEntity &enOther, ULONG ulFlags) +{ + BOOL bRemapPointers = ulFlags & COPY_REMAP; + BOOL bMakePredictor = ulFlags & COPY_PREDICTOR; + + // copy base class data + en_RenderType = enOther.en_RenderType; + en_ulPhysicsFlags = enOther.en_ulPhysicsFlags; + en_ulCollisionFlags = enOther.en_ulCollisionFlags; + en_ulFlags = enOther.en_ulFlags & + ~(ENF_SELECTED|ENF_FOUNDINGRIDSEARCH|ENF_VALIDSHADINGINFO|ENF_INRENDERING); + en_ulSpawnFlags = enOther.en_ulSpawnFlags; + + // if prediction + if (bMakePredictor) { + // set flags + en_ulFlags = (en_ulFlags&~(ENF_PREDICTED|ENF_PREDICTABLE))|ENF_PREDICTOR; + enOther.en_ulFlags = (enOther.en_ulFlags&~ENF_PREDICTOR)|ENF_PREDICTED; + } else { + en_ulFlags = (en_ulFlags&~(ENF_PREDICTED|ENF_PREDICTABLE|ENF_PREDICTOR)); + } + + // if this is a brush + if ( enOther.en_RenderType == RT_BRUSH || en_RenderType == RT_FIELDBRUSH) { + // there must be no existing brush + ASSERT(en_pbrBrush == NULL); + // create a new empty brush in the brush archive of current world + en_pbrBrush = en_pwoWorld->wo_baBrushes.ba_abrBrushes.New(); + en_pbrBrush->br_penEntity = this; + // copy the brush + if (_bMirrorAndStretch) { + en_pbrBrush->Copy(*enOther.en_pbrBrush, _fStretch, _wmtMirror!=WMT_NONE); + } else { + en_pbrBrush->Copy(*enOther.en_pbrBrush, 1.0f, FALSE); + } + // if this is a terrain + } else if( enOther.en_RenderType == RT_TERRAIN) { + #pragma message(">> CEntity::Copy") + ASSERT(FALSE); + // if this is a model + } if ( enOther.en_RenderType == RT_MODEL || en_RenderType == RT_EDITORMODEL) { + // if will not initialize + if (!(ulFlags©_REINIT)) { + // create a new model object + en_pmoModelObject = new CModelObject; + en_psiShadingInfo = new CShadingInfo; + en_ulFlags &= ~ENF_VALIDSHADINGINFO; + // copy it + en_pmoModelObject->Copy(*enOther.en_pmoModelObject); + } + // if this is ska model + } else if ( enOther.en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL) { + en_psiShadingInfo = new CShadingInfo; + en_ulFlags &= ~ENF_VALIDSHADINGINFO; + en_pmiModelInstance = CreateModelInstance("Temp"); + // copy it + GetModelInstance()->Copy(*enOther.GetModelInstance()); + } + + // copy the parent pointer + if (bRemapPointers) { + en_penParent = FindRemappedEntityPointer(enOther.en_penParent); + } else { + en_penParent = enOther.en_penParent; + } + // if the entity has a parent + if (en_penParent!=NULL) { + // create relative offset + en_plRelativeToParent = en_plPlacement; + en_plRelativeToParent.AbsoluteToRelativeSmooth(en_penParent->en_plPlacement); + // link to parent + en_penParent->en_lhChildren.AddTail(en_lnInParent); + } + + // copy the derived class properties + CopyEntityProperties(enOther, ulFlags); + + // if prediction + if (bMakePredictor) { + // create cross-links and add to containers + SetPredictionPair(&enOther); + enOther.SetPredictionPair(this); + enOther.en_pwoWorld->wo_cenPredicted.Add(&enOther); + enOther.en_pwoWorld->wo_cenPredictor.Add(this); + // copy last positions + if (enOther.en_plpLastPositions!=NULL) { + en_plpLastPositions = new CLastPositions(*enOther.en_plpLastPositions); + } + } +} + +/* + * Copy one entity property from property of another entity. + */ +void CEntity::CopyOneProperty( CEntityProperty &epPropertySrc, CEntityProperty &epPropertyDest, + CEntity &enOther, ULONG ulFlags) +{ +// a helper macro +#define COPYPROPERTY(type) \ + (type &)ENTITYPROPERTY(this, epPropertyDest.ep_slOffset, type) \ + = (type &)ENTITYPROPERTY(&enOther, epPropertySrc.ep_slOffset, type) + + // depending on the property type + switch (epPropertySrc.ep_eptType) { + // if it is BOOL + case CEntityProperty::EPT_BOOL: + // copy BOOL + COPYPROPERTY(INDEX); + break; + // if it is INDEX + case CEntityProperty::EPT_INDEX: + case CEntityProperty::EPT_ENUM: + case CEntityProperty::EPT_FLAGS: + case CEntityProperty::EPT_ANIMATION: + case CEntityProperty::EPT_ILLUMINATIONTYPE: + case CEntityProperty::EPT_COLOR: + case CEntityProperty::EPT_ANGLE: + // copy INDEX + COPYPROPERTY(INDEX); + break; + // if it is FLOAT + case CEntityProperty::EPT_FLOAT: + case CEntityProperty::EPT_RANGE: + // copy FLOAT + COPYPROPERTY(FLOAT); + break; + // if it is STRING + case CEntityProperty::EPT_STRING: + case CEntityProperty::EPT_STRINGTRANS: + // copy STRING + COPYPROPERTY(CTString); + break; + // if it is FILENAME + case CEntityProperty::EPT_FILENAME: + // copy FILENAME + COPYPROPERTY(CTFileName); + break; + // if it is FILENAMENODEP + case CEntityProperty::EPT_FILENAMENODEP: + // copy FILENAMENODEP + COPYPROPERTY(CTFileNameNoDep); + break; + // if it is FLOATAABBOX3D + case CEntityProperty::EPT_FLOATAABBOX3D: + // copy FLOATAABBOX3D + COPYPROPERTY(FLOATaabbox3D); + break; + // if it is FLOATMATRIX3D + case CEntityProperty::EPT_FLOATMATRIX3D: + // copy FLOATMATRIX3D + COPYPROPERTY(FLOATmatrix3D); + break; + + // if it is FLOAT3D + case CEntityProperty::EPT_FLOAT3D: + // copy FLOAT3D + COPYPROPERTY(FLOAT3D); + break; + // if it is ANGLE3D + case CEntityProperty::EPT_ANGLE3D: + // copy ANGLE3D + COPYPROPERTY(ANGLE3D); + break; + // if it is QUATERNION3D + case CEntityProperty::EPT_FLOATQUAT3D: + // copy ANGLE3D + COPYPROPERTY(FLOATquat3D); + break; + // if it is FLOATplane3D + case CEntityProperty::EPT_FLOATplane3D: + // copy FLOATplane3D + COPYPROPERTY(FLOATplane3D); + break; + // if it is ENTITYPTR + case CEntityProperty::EPT_ENTITYPTR: + // remap and copy the pointer + if (ulFlags & COPY_REMAP) { + ENTITYPROPERTY(this, epPropertyDest.ep_slOffset, CEntityPointer) = + FindRemappedEntityPointer(ENTITYPROPERTY(&enOther, epPropertySrc.ep_slOffset, CEntityPointer)); + // copy CEntityPointer + } else { + COPYPROPERTY(CEntityPointer); + } + break; + // if it is MODELOBJECT + case CEntityProperty::EPT_MODELOBJECT: + // copy CModelObject + ENTITYPROPERTY(this, epPropertyDest.ep_slOffset, CModelObject). + Copy(ENTITYPROPERTY(&enOther, epPropertySrc.ep_slOffset, CModelObject)); + // model objects are not copied, but should be initialized in Main() + break; + // if it is MODELINSTANCE + case CEntityProperty::EPT_MODELINSTANCE: + // copy CModelInstance + ENTITYPROPERTY(this, epPropertyDest.ep_slOffset, CModelInstance). + Copy(ENTITYPROPERTY(&enOther, epPropertySrc.ep_slOffset, CModelInstance)); + // model objects are not copied, but should be initialized in Main() + break; + // if it is ANIMOBJECT + case CEntityProperty::EPT_ANIMOBJECT: + // copy CAnimObject + ENTITYPROPERTY(this, epPropertyDest.ep_slOffset, CAnimObject). + Copy(ENTITYPROPERTY(&enOther, epPropertySrc.ep_slOffset, CAnimObject)); + break; + // if it is SOUNDOBJECT + case CEntityProperty::EPT_SOUNDOBJECT: + { + if (!(ulFlags & COPY_PREDICTOR)) { + // copy CSoundObject + CSoundObject &so = ENTITYPROPERTY(this, epPropertyDest.ep_slOffset, CSoundObject); + so.Copy(ENTITYPROPERTY(&enOther, epPropertySrc.ep_slOffset, CSoundObject)); + so.so_penEntity = this; + } + } + break; + // if it is CPlacement3D + case CEntityProperty::EPT_PLACEMENT3D: + // copy CPlacement3D + COPYPROPERTY(CPlacement3D); + break; + default: + ASSERTALWAYS("Unknown property type"); + } +} + +/* + * Copy entity properties from another entity of same class. + */ +void CEntity::CopyEntityProperties(CEntity &enOther, ULONG ulFlags) +{ + // other entity must have same class + ASSERT(enOther.en_pecClass == en_pecClass); + + // for all classes in hierarchy of this entity + for(CDLLEntityClass *pdecDLLClass = en_pecClass->ec_pdecDLLClass; + pdecDLLClass!=NULL; + pdecDLLClass = pdecDLLClass->dec_pdecBase) { + + // for all properties + for(INDEX iProperty=0; iPropertydec_ctProperties; iProperty++) { + CEntityProperty &epProperty = pdecDLLClass->dec_aepProperties[iProperty]; + CopyOneProperty( epProperty, epProperty, enOther, ulFlags); + } + } +} + +/* Copy container of entities from another world to this one and select them. */ +void CWorld::CopyEntities(CWorld &woOther, CDynamicContainer &cenToCopy, + CEntitySelection &senCopied, const CPlacement3D &plOtherSystem) +{ + INDEX ctEntities = cenToCopy.Count(); + if (ctEntities<=0) { + return; + } + + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + ULONG ulCopyFlags = COPY_REMAP; + if(_bReinitEntitiesWhileCopying) { + ulCopyFlags|=COPY_REINIT; + }; + + // create array of pointer remaps + _aprRemaps.Clear(); + _aprRemaps.New(ctEntities); + + + // PASS 1: create entities + + // for each entity to copy + INDEX iRemap = 0; + {FOREACHINDYNAMICCONTAINER(cenToCopy, CEntity, itenToCopy) { + CEntity &enToCopy = *itenToCopy; + + CEntity *penNew; + CPlacement3D plEntity; + // thansform the entity placement from the system of other world + plEntity = enToCopy.en_plPlacement; + plEntity.RelativeToAbsolute(plOtherSystem); + + // mirror and stretch placement if needed + if (_bMirrorAndStretch) { + MirrorAndStretchPlacement(plEntity); + } + + /* + * NOTE: We must use CreateEntity_t() overload with class name instead with class pointer + * because the entity class must be obtained by the target world too! + */ + // try to + try { + // create an entity of same class as the one to copy + penNew = CreateEntity_t(plEntity, enToCopy.en_pecClass->GetName()); + // if not successfull + } catch (char *strError) { + (void)strError; + ASSERT(FALSE); // this should not happen + FatalError(TRANS("Cannot CopyEntity():\n%s"), strError); + } + + // remember its remap pointer + _aprRemaps[iRemap].pr_penOriginal = &enToCopy; + _aprRemaps[iRemap].pr_penCopy = penNew; + iRemap++; + }} + + // PASS 2: copy properties + + // for each of the created entities + {FOREACHINSTATICARRAY(_aprRemaps, CPointerRemapping, itpr) { + CEntity *penOriginal = itpr->pr_penOriginal; + CEntity *penCopy = itpr->pr_penCopy; + + // copy the entity from its original + penCopy->Copy(*penOriginal, ulCopyFlags); + // if this is a brush + if ( penOriginal->en_RenderType == CEntity::RT_BRUSH || + penOriginal->en_RenderType == CEntity::RT_FIELDBRUSH) { + // update the bounding boxes of the brush + penCopy->en_pbrBrush->CalculateBoundingBoxes(); + } + if (_bMirrorAndStretch) { + penCopy->MirrorAndStretch(_fStretch, _wmtMirror!=WMT_NONE); + } + }} + + // PASS 3: initialize + + // for each of the created entities + {FOREACHINSTATICARRAY(_aprRemaps, CPointerRemapping, itpr) { + CEntity *penOriginal = itpr->pr_penOriginal; + CEntity *penCopy = itpr->pr_penCopy; + if (_bReinitEntitiesWhileCopying) { + // init the new copy + penCopy->Initialize(); + } else { + penCopy->UpdateSpatialRange(); + penCopy->FindCollisionInfo(); + // set spatial clasification + penCopy->FindSectorsAroundEntity(); + } + }} + + // PASS 4: find shadows + + // for each of the created entities + {FOREACHINSTATICARRAY(_aprRemaps, CPointerRemapping, itpr) { + CEntity *penOriginal = itpr->pr_penOriginal; + CEntity *penCopy = itpr->pr_penCopy; + + // if this is a brush + if ( penCopy->en_RenderType == CEntity::RT_BRUSH || + penCopy->en_RenderType == CEntity::RT_FIELDBRUSH) { + // find possible shadow layers near affected area + FindShadowLayers(penCopy->en_pbrBrush->GetFirstMip()->bm_boxBoundingBox); + } + + // if this is a light source + {CLightSource *pls = penCopy->GetLightSource(); + if (pls!=NULL) { + // find all shadow maps that should have layers from this light source + pls->FindShadowLayers(FALSE); + // update shadow map on terrains + pls->UpdateTerrains(); + }} + + // select it + senCopied.Select(*penCopy); + }} + + // make sure someone doesn't reuse the remap array accidentially + _aprRemaps.Clear(); +} + +/* Copy one entity from another world into this one. */ +CEntity *CWorld::CopyOneEntity(CEntity &enToCopy, const CPlacement3D &plOtherSystem) +{ + // prepare container for copying + CDynamicContainer cenToCopy; + cenToCopy.Add(&enToCopy); + // copy the entities in container + CEntitySelection senCopied; + CopyEntities(*enToCopy.en_pwoWorld, cenToCopy, senCopied, plOtherSystem); + + {FOREACHINDYNAMICCONTAINER(senCopied, CEntity, itenCopied) { + return itenCopied; + }} + ASSERT(FALSE); + return NULL; +} + +/* + * Copy all entities except one from another world to this one. + */ +void CWorld::CopyAllEntitiesExceptOne(CWorld &woOther, CEntity &enExcepted, + const CPlacement3D &plOtherSystem) +{ + // prepare container for copying, without excepted entity + CDynamicContainer cenToCopy; + cenToCopy = woOther.wo_cenEntities; + cenToCopy.Remove(&enExcepted); + // copy the entities in container and ignore the selection (we don't need it) + CEntitySelection senCopied; + CopyEntities(woOther, cenToCopy, senCopied, plOtherSystem); + senCopied.Clear(); +} + + +/* Copy entity in world. */ +CEntity *CWorld::CopyEntityInWorld(CEntity &enOriginal, const CPlacement3D &plOtherEntity, + BOOL bWithDescendants /*= TRUE*/) +{ + // new entity + CEntity *penNew; + + /* + * NOTE: We must use CreateEntity_t() overload with class name instead with class pointer + * because the entity class must be obtained by the target world too! + */ + // try to + try { + // create an entity of same class as the one to copy + penNew = CreateEntity_t(plOtherEntity, enOriginal.en_pecClass->GetName()); + // if not successfull + } catch (char *strError) { + (void)strError; + ASSERT(FALSE); // this should not happen + FatalError(TRANS("Cannot CopyEntity():\n%s"), strError); + } + + // copy the entity from its original + penNew->Copy(enOriginal, COPY_REINIT); + // if this is a brush + if ( enOriginal.en_RenderType == CEntity::RT_BRUSH || + enOriginal.en_RenderType == CEntity::RT_FIELDBRUSH) { + // update the bounding boxes of the brush + penNew->en_pbrBrush->CalculateBoundingBoxes(); + } + // init the new copy + penNew->Initialize(); + + // if this is a brush + if ( penNew->en_RenderType == CEntity::RT_BRUSH || + penNew->en_RenderType == CEntity::RT_FIELDBRUSH) { + // find possible shadow layers near affected area + FindShadowLayers(penNew->en_pbrBrush->GetFirstMip()->bm_boxBoundingBox); + } + + // if this is a light source + {CLightSource *pls = penNew->GetLightSource(); + if (pls!=NULL) { + // find all shadow maps that should have layers from this light source + pls->FindShadowLayers(FALSE); + }} + + // if descendants should be copied too + if (bWithDescendants) { + // for each child of this entity + {FOREACHINLIST(CEntity, en_lnInParent, enOriginal.en_lhChildren, itenChild) { + // copy it relatively to the new entity + CPlacement3D plChild = itenChild->en_plRelativeToParent; + plChild.RelativeToAbsoluteSmooth(penNew->en_plPlacement); + CEntity *penNewChild = CopyEntityInWorld(*itenChild, plChild, TRUE); + // add new child to its new parent + penNewChild->SetParent(penNew); + }} + } + + return penNew; +} + +// mirror and stretch another world into this one +void CWorld::MirrorAndStretch(CWorld &woOriginal, FLOAT fStretch, enum WorldMirrorType wmt) +{ + _bMirrorAndStretch = TRUE; + _fStretch = fStretch; + _wmtMirror = wmt; + + // clear this world + Clear(); + + // make container for copying + CDynamicContainer cenToCopy; + cenToCopy = woOriginal.wo_cenEntities; + // dummy selection for copied entities, we don't need that info + CEntitySelection senCopied; + // make mirroring placement + CPlacement3D plOtherSystem; + plOtherSystem = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + // copy entities with mirror and stretch + CopyEntities(woOriginal, cenToCopy, senCopied, plOtherSystem); + + // update all links + { + CSetFPUPrecision FPUPrecision(FPT_53BIT); + wo_baBrushes.LinkPortalsAndSectors(); + } + + _bMirrorAndStretch = FALSE; +} + +/* Copy entities for prediction. */ +void CWorld::CopyEntitiesToPredictors(CDynamicContainer &cenToCopy) +{ + INDEX ctEntities = cenToCopy.Count(); + if (ctEntities<=0) { + return; + } + + extern INDEX cli_bReportPredicted; + if (cli_bReportPredicted) { + CPrintF( TRANS("Predicting %d entities:\n"), ctEntities); + {FOREACHINDYNAMICCONTAINER(cenToCopy, CEntity, itenToCopy) { + CEntity &enToCopy = *itenToCopy; + CPrintF(" %s:%s\n", enToCopy.GetClass()->ec_pdecDLLClass->dec_strName, (const char*)enToCopy.GetName()); + }} + } + + // clear current tick to prevent timer setting from assertions + TIME tmCurrentTickOld = _pTimer->CurrentTick(); + _pTimer->SetCurrentTick(0.0f); + + ULONG ulCopyFlags = COPY_REMAP|COPY_PREDICTOR; + + // create array of pointer remaps + _aprRemaps.Clear(); + _aprRemaps.New(ctEntities); + + // PASS 1: create entities + + // for each entity to copy + INDEX iRemap = 0; + {FOREACHINDYNAMICCONTAINER(cenToCopy, CEntity, itenToCopy) { + CEntity &enToCopy = *itenToCopy; + + CEntity *penNew; + + // create an entity of same class as the one to copy + penNew = CreateEntity(enToCopy.en_plPlacement, enToCopy.en_pecClass); + + // remember its remap pointer + _aprRemaps[iRemap].pr_penOriginal = &enToCopy; + _aprRemaps[iRemap].pr_penCopy = penNew; + iRemap++; + _ctPredictorEntities++; + }} + // unfound pointers must be kept unremapped + _bRemapPointersToNULLs = FALSE; + + // PASS 2: copy properties + + // for each of the created entities + {FOREACHINSTATICARRAY(_aprRemaps, CPointerRemapping, itpr) { + CEntity *penOriginal = itpr->pr_penOriginal; + CEntity *penCopy = itpr->pr_penCopy; + + // copy the entity from its original + penCopy->Copy(*penOriginal, ulCopyFlags); + // if this is a brush + if ( penOriginal->en_RenderType == CEntity::RT_BRUSH || + penOriginal->en_RenderType == CEntity::RT_FIELDBRUSH) { + ASSERT(FALSE); // should we allow prediction of brushes? + // update the bounding boxes of the brush + //penCopy->en_pbrBrush->CalculateBoundingBoxes(); + } + }} + + // PASS 3: initialize + + // for each of the created entities + {FOREACHINSTATICARRAY(_aprRemaps, CPointerRemapping, itpr) { + CEntity *penOriginal = itpr->pr_penOriginal; + CEntity *penCopy = itpr->pr_penCopy; + + // copy spatial classification + penCopy->en_fSpatialClassificationRadius = penOriginal->en_fSpatialClassificationRadius; + penCopy->en_boxSpatialClassification = penOriginal->en_boxSpatialClassification; + // copy collision info + penCopy->CopyCollisionInfo(*penOriginal); + // for each sector around the original + {FOREACHSRCOFDST(penOriginal->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // copy the link + if (penOriginal->en_RenderType==CEntity::RT_BRUSH + ||penOriginal->en_RenderType==CEntity::RT_FIELDBRUSH + ||penOriginal->en_RenderType==CEntity::RT_TERRAIN) { // brushes first + AddRelationPairHeadHead(pbsc->bsc_rsEntities, penCopy->en_rdSectors); + } else { + AddRelationPairTailTail(pbsc->bsc_rsEntities, penCopy->en_rdSectors); + } + ENDFOR} + }} + + // PASS 4: find shadows + + // for each of the created entities + {FOREACHINSTATICARRAY(_aprRemaps, CPointerRemapping, itpr) { + CEntity *penOriginal = itpr->pr_penOriginal; + CEntity *penCopy = itpr->pr_penCopy; + + // if this is a brush + if ( penCopy->en_RenderType == CEntity::RT_BRUSH || + penCopy->en_RenderType == CEntity::RT_FIELDBRUSH) { + ASSERT(FALSE); // should we allow prediction of brushes? + // find possible shadow layers near affected area + //FindShadowLayers(penCopy->en_pbrBrush->GetFirstMip()->bm_boxBoundingBox); + } + + // if this is a light source + {CLightSource *pls = penCopy->GetLightSource(); + if (pls!=NULL) { + // find all shadow maps that should have layers from this light source + pls->FindShadowLayers(FALSE); + }} + }} + + // make sure someone doesn't reuse the remap array accidentially + _aprRemaps.Clear(); + + _bRemapPointersToNULLs = TRUE; + + // return current tick + _pTimer->SetCurrentTick(tmCurrentTickOld); +} \ No newline at end of file diff --git a/Sources/Engine/Entities/EntityEvent.h b/Sources/Engine/Entities/EntityEvent.h new file mode 100644 index 0000000..901fb88 --- /dev/null +++ b/Sources/Engine/Entities/EntityEvent.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ENTITYEVENT_H +#define SE_INCL_ENTITYEVENT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// a BOOL that is constructed with value of FALSE (used in some entity initializations) +class ENGINE_API CBoolDefaultFalse { +public: + BOOL bdf_bValue; + CBoolDefaultFalse(void) : bdf_bValue(FALSE) {}; +}; + +/* + * An base class for event message passed to AI functions. + */ +class ENGINE_API CEntityEvent { +public: + SLONG ee_slEvent; // event code + // other data members are placed in derived class + + CEntityEvent(SLONG slEventCode) : ee_slEvent(slEventCode) {}; + virtual ~CEntityEvent(void) {}; // destructor must be virtual + // used for copying events for later delivery + virtual CEntityEvent *MakeCopy(void) { + CEntityEvent *peeCopy = new CEntityEvent(*this); + return peeCopy; + }; +}; +// a reference to a void event for use as default parameter +ENGINE_API extern const CEntityEvent &_eeVoid; + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Entities/EntityPointer.h b/Sources/Engine/Entities/EntityPointer.h new file mode 100644 index 0000000..c14e175 --- /dev/null +++ b/Sources/Engine/Entities/EntityPointer.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ENTITYPOINTER_H +#define SE_INCL_ENTITYPOINTER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* + * Smart pointer to entity objects, does the book-keeping for reference counting. + */ +class CEntityPointer { +public: + CEntity *ep_pen; // the pointer itself +public: + // all standard smart pointer functions are defined as inlines in Entity.h + // (due to strange order of inclusion needed for events and enums) + inline CEntityPointer(void); + inline ~CEntityPointer(void); + inline CEntityPointer(const CEntityPointer &penOther); + inline CEntityPointer(CEntity *pen); + inline const CEntityPointer &operator=(CEntity *pen); + inline const CEntityPointer &operator=(const CEntityPointer &penOther); + inline CEntity* operator->(void) const; + inline operator CEntity*(void) const; + inline CEntity& operator*(void) const; +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Entities/EntityProperties.cpp b/Sources/Engine/Entities/EntityProperties.cpp new file mode 100644 index 0000000..21510a8 --- /dev/null +++ b/Sources/Engine/Entities/EntityProperties.cpp @@ -0,0 +1,673 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define FILTER_ALL "All files (*.*)\0*.*\0" +#define FILTER_END "\0" + +#define PROPERTY(offset, type) ENTITYPROPERTY(this, offset, type) + +///////////////////////////////////////////////////////////////////// +// Property management functions + + +/* + * Set all properties to default values. + */ +void CEntity::SetDefaultProperties(void) +{ + // no properties to set in base class +} + +/* + * Helpers for writing/reading entity pointers. + */ +void CEntity::ReadEntityPointer_t(CTStream *istrm, CEntityPointer &pen) +{ + CEntity *penPointed; + // read index + INDEX iPointedEntity; + *istrm>>iPointedEntity; + // if there is no entity pointed to + if (iPointedEntity == -1) { + // set NULL pointer + penPointed = NULL; + // if there is some entity + } else { + // get the entity in this world with that index + extern BOOL _bReadEntitiesByID; + if (_bReadEntitiesByID) { + penPointed = en_pwoWorld->EntityFromID(iPointedEntity); + } else { + penPointed = en_pwoWorld->wo_cenAllEntities.Pointer(iPointedEntity); + } + } + // return the entity pointer + pen = penPointed; +} +void CEntity::WriteEntityPointer_t(CTStream *ostrm, CEntityPointer pen) +{ + // if there is no entity pointed to + if (pen==NULL) { + // write -1 index + *ostrm<<(INDEX)-1; + // if there is some entity + } else { + // the entity must be in the same world as this one + ASSERT(pen->en_pwoWorld == en_pwoWorld); + // write index of the entity in this world + *ostrm<<(pen->en_ulID); + } +} + +/* + * Read all properties from a stream. + */ +void CEntity::ReadProperties_t(CTStream &istrm) // throw char * +{ + istrm.ExpectID_t("PRPS"); // 'properties' + CDLLEntityClass *pdecDLLClass = en_pecClass->ec_pdecDLLClass; + INDEX ctProperties; + // read number of properties (note that this doesn't have to be same as number + // of properties in the class (class might have changed)) + istrm>>ctProperties; + + // for all saved properties + for(INDEX iProperty=0; iPropertydec_ctProperties; + // read packed identifier + ULONG ulIDAndType; + istrm>>ulIDAndType; + // unpack property ID and property type from the identifier + ULONG ulID; + CEntityProperty::PropertyType eptType; + ulID = ulIDAndType>>8; + eptType = (CEntityProperty::PropertyType )(ulIDAndType&0x000000FFUL); + + // get the property with that ID and type + CEntityProperty *pepProperty = PropertyForTypeAndID(eptType, ulID); + // if not found, but it is a string + if (pepProperty == NULL && eptType==CEntityProperty::EPT_STRING) { + // maybe that became translatable string try that + pepProperty = PropertyForTypeAndID(CEntityProperty::EPT_STRINGTRANS, ulID); + // NOTE: it is still loaded as string, without translation chunk, + // we just find it in properties table as a translatable string. + } + + // if it was not found + if (pepProperty == NULL) { + // depending on the property type + switch (eptType) { + // if it is BOOL + case CEntityProperty::EPT_BOOL: { + // skip BOOL + BOOL bDummy; + istrm>>(INDEX &)bDummy; + break; + } + // if it is INDEX + case CEntityProperty::EPT_INDEX: + case CEntityProperty::EPT_ENUM: + case CEntityProperty::EPT_FLAGS: + case CEntityProperty::EPT_ANIMATION: + case CEntityProperty::EPT_ILLUMINATIONTYPE: + case CEntityProperty::EPT_COLOR: + case CEntityProperty::EPT_ANGLE: { + // skip INDEX + INDEX iDummy; + istrm>>iDummy; + + } break; + // if it is FLOAT + case CEntityProperty::EPT_FLOAT: + case CEntityProperty::EPT_RANGE: { + // skip FLOAT + FLOAT fDummy; + istrm>>fDummy; + } + break; + // if it is STRING + case CEntityProperty::EPT_STRING: { + // skip STRING + CTString strDummy; + istrm>>strDummy; + break; + } + // if it is STRINGTRANS + case CEntityProperty::EPT_STRINGTRANS: { + // skip STRINGTRANS + istrm.ExpectID_t("DTRS"); + CTString strDummy; + istrm>>strDummy; + break; + } + // if it is FILENAME + case CEntityProperty::EPT_FILENAME: { + // skip FILENAME + CTFileName fnmDummy; + istrm>>fnmDummy; + break; + } + // if it is FILENAMENODEP + case CEntityProperty::EPT_FILENAMENODEP: { + // skip FILENAMENODEP + CTFileNameNoDep fnmDummy; + istrm>>fnmDummy; + break; + } + // if it is ENTITYPTR + case CEntityProperty::EPT_ENTITYPTR: { + // skip index + INDEX iDummy; + istrm>>iDummy; + } + break; + // if it is FLOATAABBOX3D + case CEntityProperty::EPT_FLOATAABBOX3D: { + // skip FLOATAABBOX3D + FLOATaabbox3D boxDummy; + istrm.Read_t(&boxDummy, sizeof(FLOATaabbox3D)); + } + break; + // if it is FLOATMATRIX3D + case CEntityProperty::EPT_FLOATMATRIX3D: { + // skip FLOATMATRIX3D + FLOATmatrix3D boxDummy; + istrm.Read_t(&boxDummy, sizeof(FLOATmatrix3D)); + } + break; + // if it is EPT_FLOATQUAT3D + case CEntityProperty::EPT_FLOATQUAT3D: { + // skip EPT_FLOATQUAT3D + FLOATquat3D qDummy; + istrm.Read_t(&qDummy, sizeof(FLOATquat3D)); + } + break; + // if it is FLOAT3D + case CEntityProperty::EPT_FLOAT3D: { + // skip FLOAT3D + FLOAT3D vDummy; + istrm>>vDummy; + } + break; + // if it is ANGLE3D + case CEntityProperty::EPT_ANGLE3D: { + // skip ANGLE3D + ANGLE3D vDummy; + istrm>>vDummy; + } + break; + // if it is FLOATplane3D + case CEntityProperty::EPT_FLOATplane3D: { + // skip FLOATplane3D + FLOATplane3D plDummy; + istrm.Read_t(&plDummy, sizeof(plDummy)); + } + break; + // if it is MODELOBJECT + case CEntityProperty::EPT_MODELOBJECT: + // skip CModelObject + SkipModelObject_t(istrm); + break; + // if it is MODELINSTANCE + case CEntityProperty::EPT_MODELINSTANCE: + SkipModelInstance_t(istrm); + break; + // if it is ANIMOBJECT + case CEntityProperty::EPT_ANIMOBJECT: + // skip CAnimObject + SkipAnimObject_t(istrm); + break; + // if it is SOUNDOBJECT + case CEntityProperty::EPT_SOUNDOBJECT: + // skip CSoundObject + SkipSoundObject_t(istrm); + break; + default: + ASSERTALWAYS("Unknown property type"); + } + + // if it was found + } else { + + // fixup for loading old strings as translatable strings + CEntityProperty::PropertyType eptLoad = pepProperty->ep_eptType; + if (eptType==CEntityProperty::EPT_STRING && + eptLoad==CEntityProperty::EPT_STRINGTRANS) { + eptLoad = CEntityProperty::EPT_STRING; + } + + // depending on the property type + switch (eptLoad) { + // if it is BOOL + case CEntityProperty::EPT_BOOL: + // read BOOL + istrm>>(INDEX &)PROPERTY(pepProperty->ep_slOffset, BOOL); + break; + // if it is INDEX + case CEntityProperty::EPT_INDEX: + case CEntityProperty::EPT_ENUM: + case CEntityProperty::EPT_FLAGS: + case CEntityProperty::EPT_ANIMATION: + case CEntityProperty::EPT_ILLUMINATIONTYPE: + case CEntityProperty::EPT_COLOR: + case CEntityProperty::EPT_ANGLE: + // read INDEX + istrm>>PROPERTY(pepProperty->ep_slOffset, INDEX); + break; + // if it is FLOAT + case CEntityProperty::EPT_FLOAT: + case CEntityProperty::EPT_RANGE: + // read FLOAT + istrm>>PROPERTY(pepProperty->ep_slOffset, FLOAT); + break; + // if it is STRING + case CEntityProperty::EPT_STRING: + // read STRING + istrm>>PROPERTY(pepProperty->ep_slOffset, CTString); + break; + // if it is STRINGTRANS + case CEntityProperty::EPT_STRINGTRANS: + // read STRINGTRANS + istrm.ExpectID_t("DTRS"); + istrm>>PROPERTY(pepProperty->ep_slOffset, CTString); + break; + // if it is FILENAME + case CEntityProperty::EPT_FILENAME: + // read FILENAME + istrm>>PROPERTY(pepProperty->ep_slOffset, CTFileName); + if (PROPERTY(pepProperty->ep_slOffset, CTFileName)=="") { + break; + } + // try to replace file name if it doesn't exist + for(;;) + { + if( !FileExists( PROPERTY(pepProperty->ep_slOffset, CTFileName))) + { + // if file was not found, ask for replacing file + CTFileName fnReplacingFile; + if( GetReplacingFile( PROPERTY(pepProperty->ep_slOffset, CTFileName), + fnReplacingFile, FILTER_ALL FILTER_END)) + { + // replacing file was provided + PROPERTY(pepProperty->ep_slOffset, CTFileName) = fnReplacingFile; + } else { + ThrowF_t(TRANS("File '%s' does not exist"), (const char*)PROPERTY(pepProperty->ep_slOffset, CTFileName)); + } + } + else + { + break; + } + } + break; + // if it is FILENAMENODEP + case CEntityProperty::EPT_FILENAMENODEP: + // read FILENAMENODEP + istrm>>PROPERTY(pepProperty->ep_slOffset, CTFileNameNoDep); + break; + // if it is ENTITYPTR + case CEntityProperty::EPT_ENTITYPTR: + // read the entity pointer + ReadEntityPointer_t(&istrm, PROPERTY(pepProperty->ep_slOffset, CEntityPointer)); + break; + // if it is FLOATAABBOX3D + case CEntityProperty::EPT_FLOATAABBOX3D: + // read FLOATAABBOX3D + istrm.Read_t(&PROPERTY(pepProperty->ep_slOffset, FLOATaabbox3D), sizeof(FLOATaabbox3D)); + break; + // if it is FLOATMATRIX3D + case CEntityProperty::EPT_FLOATMATRIX3D: + // read FLOATMATRIX3D + istrm.Read_t(&PROPERTY(pepProperty->ep_slOffset, FLOATmatrix3D), sizeof(FLOATmatrix3D)); + break; + // if it is FLOATQUAT3D + case CEntityProperty::EPT_FLOATQUAT3D: + // read FLOATQUAT3D + istrm.Read_t(&PROPERTY(pepProperty->ep_slOffset, FLOATquat3D), sizeof(FLOATquat3D)); + break; + // if it is FLOAT3D + case CEntityProperty::EPT_FLOAT3D: + // read FLOAT3D + istrm.Read_t(&PROPERTY(pepProperty->ep_slOffset, FLOAT3D), sizeof(FLOAT3D)); + break; + // if it is ANGLE3D + case CEntityProperty::EPT_ANGLE3D: + // read ANGLE3D + istrm.Read_t(&PROPERTY(pepProperty->ep_slOffset, ANGLE3D), sizeof(ANGLE3D)); + break; + // if it is FLOATplane3D + case CEntityProperty::EPT_FLOATplane3D: + // read FLOATplane3D + istrm.Read_t(&PROPERTY(pepProperty->ep_slOffset, FLOATplane3D), sizeof(FLOATplane3D)); + break; + // if it is MODELOBJECT + case CEntityProperty::EPT_MODELOBJECT: + // read CModelObject + ReadModelObject_t(istrm, PROPERTY(pepProperty->ep_slOffset, CModelObject)); + break; + // if it is MODELINSTANCE + case CEntityProperty::EPT_MODELINSTANCE: + // read CModelObject + ReadModelInstance_t(istrm, PROPERTY(pepProperty->ep_slOffset, CModelInstance)); + break; + // if it is ANIMOBJECT + case CEntityProperty::EPT_ANIMOBJECT: + // read CAnimObject + ReadAnimObject_t(istrm, PROPERTY(pepProperty->ep_slOffset, CAnimObject)); + break; + // if it is SOUNDOBJECT + case CEntityProperty::EPT_SOUNDOBJECT: + // read CSoundObject + { + CSoundObject &so = PROPERTY(pepProperty->ep_slOffset, CSoundObject); + ReadSoundObject_t(istrm, so); + so.so_penEntity = this; + } + break; + // if it is CPlacement3D + case CEntityProperty::EPT_PLACEMENT3D: + // read CPlacement3D + istrm.Read_t(&PROPERTY(pepProperty->ep_slOffset, CPlacement3D), sizeof(CPlacement3D)); + break; + default: + ASSERTALWAYS("Unknown property type"); + } + } + } +} + +/* + * Write all properties to a stream. + */ +void CEntity::WriteProperties_t(CTStream &ostrm) // throw char * +{ + INDEX ctProperties = 0; + // for all classes in hierarchy of this entity + {for(CDLLEntityClass *pdecDLLClass = en_pecClass->ec_pdecDLLClass; + pdecDLLClass!=NULL; + pdecDLLClass = pdecDLLClass->dec_pdecBase) { + // count the properties + ctProperties+=pdecDLLClass->dec_ctProperties; + }} + + ostrm.WriteID_t("PRPS"); // 'properties' + // write number of properties + ostrm<ec_pdecDLLClass; + pdecDLLClass!=NULL; + pdecDLLClass = pdecDLLClass->dec_pdecBase) { + // for all properties + for(INDEX iProperty=0; iPropertydec_ctProperties; iProperty++) { + CEntityProperty &epProperty = pdecDLLClass->dec_aepProperties[iProperty]; + + // pack property ID and property type together + ULONG ulID = epProperty.ep_ulID; + ULONG ulType = (ULONG)epProperty.ep_eptType; + ULONG ulIDAndType = (ulID<<8)|ulType; + // write the packed identifier + ostrm<Obtain_t(ec_fnmComponent); + ctUsed = ec_ptdTexture->GetUsedCount(); + break; + // if model + case ECT_MODEL: + // obtain model data + ec_pmdModel = _pModelStock->Obtain_t(ec_fnmComponent); + ctUsed = ec_pmdModel->GetUsedCount(); + break; + // if sound + case ECT_SOUND: + // obtain sound data + ec_psdSound = _pSoundStock->Obtain_t(ec_fnmComponent); + ctUsed = ec_psdSound->GetUsedCount(); + break; + // if class + case ECT_CLASS: + // obtain entity class + ec_pecEntityClass = _pEntityClassStock->Obtain_t(ec_fnmComponent); + ctUsed = ec_pecEntityClass->GetUsedCount(); + break; + // if something else + default: + // error + ThrowF_t(TRANS("Component '%s'(%d) is of unknown type!"), (CTString&)ec_fnmComponent, ec_slID); + } + + // if not already loaded and should not be precaching now + if( ctUsed<=1 && !_precache_bNowPrecaching) { + // report warning + CPrintF(TRANS("Not precached: (0x%08X)'%s'\n"), this->ec_slID, ec_fnmComponent); + } + //CPrintF(TRANS("Precaching NOW: (0x%08X)'%s'\n"), this->ec_slID, ec_fnmComponent); + + // add to CRC + AddToCRCTable(); +} +void CEntityComponent::ObtainWithCheck(void) +{ + try { + Obtain_t(); + } catch(char *strError) { + FatalError("%s", strError); + } +} + +// add component to crc table +void CEntityComponent::AddToCRCTable(void) +{ + // if not obtained + if (ec_pvPointer==NULL) { + // do nothing + return; + } + + // add it + switch(ec_ectType) { + case ECT_TEXTURE: ec_ptdTexture->AddToCRCTable(); break; + case ECT_MODEL: ec_pmdModel->AddToCRCTable(); break; + case ECT_SOUND: ec_psdSound->AddToCRCTable(); break; + case ECT_CLASS: ec_pecEntityClass->AddToCRCTable(); break; + } +} + +/* + * Release the component. + */ +void CEntityComponent::Release(void) +{ + // if the component is not obtained + if (ec_pvPointer==NULL) { + // don't release it + return; + } + // check the component type + switch(ec_ectType) { + // if texture + case ECT_TEXTURE: + // release texture data + _pTextureStock->Release(ec_ptdTexture); + break; + // if model + case ECT_MODEL: + // release model data + _pModelStock->Release(ec_pmdModel); + break; + // if sound + case ECT_SOUND: + // release sound data + _pSoundStock->Release(ec_psdSound); + break; + // if class + case ECT_CLASS: + // release entity class + _pEntityClassStock->Release(ec_pecEntityClass); + break; + // if something else + default: + // error + ThrowF_t(TRANS("Component '%s'(%d) is of unknown type!"), (CTString&)ec_fnmComponent, ec_slID); + } + + // released + ec_pvPointer=NULL; +} + +// these entity classes are bases, here stop all recursive searches +ENTITY_CLASSDEFINITION_BASE(CEntity, 32000); +ENTITY_CLASSDEFINITION_BASE(CLiveEntity, 32001); +ENTITY_CLASSDEFINITION_BASE(CRationalEntity, 32002); diff --git a/Sources/Engine/Entities/EntityProperties.h b/Sources/Engine/Entities/EntityProperties.h new file mode 100644 index 0000000..53b1472 --- /dev/null +++ b/Sources/Engine/Entities/EntityProperties.h @@ -0,0 +1,271 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ENTITYPROPERTIES_H +#define SE_INCL_ENTITYPROPERTIES_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +///////////////////////////////////////////////////////////////////// +// Classes and macros for defining enums for entity properties + +class CEntityPropertyEnumValue { +public: + INDEX epev_iValue; // value + char *epev_strName; // descriptive name of the enum value (for editor) +}; +class CEntityPropertyEnumType { +public: + CEntityPropertyEnumValue *epet_aepevValues; // array of values + INDEX epet_ctValues; // number of values + // convert value of an enum to its name + ENGINE_API const char *NameForValue(INDEX iValue); +}; +#define EP_ENUMBEG(typename) extern _declspec (dllexport) CEntityPropertyEnumValue typename##_values[] = { +#define EP_ENUMVALUE(value, name) {value, name} +#define EP_ENUMEND(typename) }; CEntityPropertyEnumType typename##_enum = { \ + typename##_values, sizeof(typename##_values)/sizeof(CEntityPropertyEnumValue ) } + +// types that are used only for properties. +// range, edited visually as sphere around entity +typedef FLOAT RANGE; +// type of illumination (for lights that illuminate through polygons) +typedef INDEX ILLUMINATIONTYPE; +// type of light animation +typedef INDEX ANIMATION; +// CTString browsed like a file - doesn't cause dependencies +typedef CTString CTFileNameNoDep; +// CTString that gets translated to different languages +typedef CTString CTStringTrans; + +///////////////////////////////////////////////////////////////////// +// Classes and macros for defining entity properties + +#define EPROPF_HIDEINPERSPECTIVE (1UL<<0) // not visualized in perspective view (for ranges) + +class ENGINE_API CEntityProperty { +public: + enum PropertyType { + /* IMPORTANT: Take care not to renumber the property types, since it would ruin loading + * of previously saved data like levels etc.! Always give a new type new number, and + * never change existing number, nor reuse old ones! + * Update 'next free number' comment when adding new type, but not when removing some! + */ + EPT_PARENT = 9998, // used internaly in WED for setting entity's parents + EPT_SPAWNFLAGS = 9999, // used internaly in WED for spawn flags property + EPT_ENUM = 1, // enum xxx, INDEX with descriptions + EPT_BOOL = 2, // BOOL + EPT_FLOAT = 3, // FLOAT + EPT_COLOR = 4, // COLOR + EPT_STRING = 5, // CTString + EPT_RANGE = 6, // RANGE FLOAT edited as a sphere around the entity + EPT_ENTITYPTR = 7, // CEntityPointer + EPT_FILENAME = 8, // CTFileName + EPT_INDEX = 9, // INDEX + EPT_ANIMATION = 10, // ANIMATION, INDEX edited by animation names + EPT_ILLUMINATIONTYPE = 11, // ILLUMINATIONTYPE, INDEX edited by illumination names + EPT_FLOATAABBOX3D = 12, // FLOATaabbox3D + EPT_ANGLE = 13, // ANGLE, INDEX edited in degrees + EPT_FLOAT3D = 14, // FLOAT3D + EPT_ANGLE3D = 15, // ANGLE3D + EPT_FLOATplane3D = 16, // FLOATplane3D + EPT_MODELOBJECT = 17, // CModelObject + EPT_PLACEMENT3D = 18, // PLACEMENT3D + EPT_ANIMOBJECT = 19, // CAnimObject + EPT_FILENAMENODEP = 20, // CTString browsed like a file - doesn't cause dependencies + EPT_SOUNDOBJECT = 21, // CSoundObject + EPT_STRINGTRANS = 22, // CTString that gets translated to different languages + EPT_FLOATQUAT3D = 23, // FLOATquat3D + EPT_FLOATMATRIX3D = 24, // FLOATmatrix3D + EPT_FLAGS = 25, // flags - ULONG bitfield with names for each field + EPT_MODELINSTANCE = 26, + // next free number: 27 + } ep_eptType; // type of property + CEntityPropertyEnumType *ep_pepetEnumType; // if the type is EPT_ENUM or EPT_FLAGS + + ULONG ep_ulID; // property ID for this class + SLONG ep_slOffset; // offset of the property in the class + char *ep_strName; // descriptive name of the property (for editor) + ULONG ep_ulFlags; // additional flags for the property + char ep_chShortcut; // shortcut key for selecting the property in editor (0 for none) + COLOR ep_colColor; // property color, for various wed purposes (like target arrows) + + CEntityProperty(PropertyType eptType, CEntityPropertyEnumType *pepetEnumType, + ULONG ulID, SLONG slOffset, char *strName, char chShortcut, COLOR colColor, ULONG ulFlags) + : ep_eptType (eptType ) + , ep_pepetEnumType (pepetEnumType) + , ep_ulID (ulID ) + , ep_slOffset (slOffset ) + , ep_strName (strName ) + , ep_chShortcut (chShortcut ) + , ep_colColor (colColor ) + , ep_ulFlags (ulFlags ) + {}; + CEntityProperty(void) {}; +}; + +// macro for accessing property inside an entity +#define ENTITYPROPERTY(entityptr, offset, type) (*((type *)(((UBYTE *)entityptr)+offset))) + +///////////////////////////////////////////////////////////////////// +// Classes and macros for defining entity event handler functions + +// one entry in function table +class CEventHandlerEntry { +public: + SLONG ehe_slState; // code of the automaton state + SLONG ehe_slBaseState; // code of the base state if overridden + CEntity::pEventHandler ehe_pEventHandler; // handler function + const char *ehe_strName; // symbolic name of handler for debugging +}; + +///////////////////////////////////////////////////////////////////// +// Classes and macros for defining entity components + +enum EntityComponentType { // DO NOT RENUMBER! + ECT_TEXTURE = 1, // texture data + ECT_MODEL = 2, // model data + ECT_CLASS = 3, // entity class + ECT_SOUND = 4, // sound data +}; + +class ENGINE_API CEntityComponent { +public: + /* Obtain the component. */ + void Obtain_t(void); // throw char * + void ObtainWithCheck(void); + // add component to crc table + void AddToCRCTable(void); + /* Release the component. */ + void Release(void); +public: + EntityComponentType ec_ectType; // type of component + ULONG ec_slID; // component ID in this class + + CTFileName ec_fnmComponent; // component file name + + // this one is auto-filled by SCape on DLL initialization + union { // pointer to component + CTextureData *ec_ptdTexture; // for textures + CModelData *ec_pmdModel; // for models + CSoundData *ec_psdSound; // for sounds + CEntityClass *ec_pecEntityClass; // for entity classes + void *ec_pvPointer; // for comparison needs + }; + + // NOTE: This uses special EFNM initialization for CTFileName class! + CEntityComponent(EntityComponentType ectType, + ULONG ulID, char *strEFNMComponent) + : ec_ectType(ectType) + , ec_slID(ulID) + , ec_fnmComponent(strEFNMComponent, 4) { ec_pvPointer = NULL; }; + CEntityComponent(void) { ec_slID = (ULONG) -1; ec_pvPointer = NULL; }; +}; + +///////////////////////////////////////////////////////////////////// +// The class defining an entity class DLL itself + +class ENGINE_API CDLLEntityClass { +public: + CEntityProperty *dec_aepProperties; // array of properties + INDEX dec_ctProperties; // number of properties + + CEventHandlerEntry *dec_aeheHandlers; // array of event handlers + INDEX dec_ctHandlers; // number of handlers + + CEntityComponent *dec_aecComponents;// array of components + INDEX dec_ctComponents; // number of components + + char *dec_strName; // descriptive name of the class + char *dec_strIconFileName; // filename of texture or thumbnail + INDEX dec_iID; // class ID + + CDLLEntityClass *dec_pdecBase; // pointer to the base class + + CEntity *(*dec_New)(void); // pointer to function that creates a member of class + void (*dec_OnInitClass)(void); // pointer to function for connecting DLL + void (*dec_OnEndClass)(void); // pointer to function for disconnecting DLL + void (*dec_OnPrecache)(CDLLEntityClass *pdec, INDEX iUser); // function for precaching data + void (*dec_OnWorldInit)(CWorld *pwoWorld); // function called on world initialization + void (*dec_OnWorldTick)(CWorld *pwoWorld); // function called for each tick + void (*dec_OnWorldRender)(CWorld *pwoWorld); // function called for each rendering + void (*dec_OnWorldEnd)(CWorld *pwoWorld); // function called on world cleanup + + /* Get pointer to entity property from its name. */ + class CEntityProperty *PropertyForName(const CTString &strPropertyName); + /* Get pointer to entity property from its packed identifier. */ + class CEntityProperty *PropertyForTypeAndID(CEntityProperty::PropertyType eptType, ULONG ulID); + /* Get event handler given state and event code. */ + CEntity::pEventHandler HandlerForStateAndEvent(SLONG slState, SLONG slEvent); + /* Get event handler name for given state. */ + const char *HandlerNameForState(SLONG slState); + /* Get derived class override for given state. */ + SLONG GetOverridenState(SLONG slState); + /* Get pointer to component from its type and identifier. */ + class CEntityComponent *ComponentForTypeAndID(EntityComponentType ectType, + SLONG slID); + /* Get pointer to component from the component. */ + class CEntityComponent *ComponentForPointer(void *pv); + // precache given component + void PrecacheModel(SLONG slID); + void PrecacheTexture(SLONG slID); + void PrecacheSound(SLONG slID); + void PrecacheClass(SLONG slID, INDEX iUser = -1); +}; + +/* rcg10062001 */ +#if (defined _MSC_VER) + #define DECLSPEC_DLLEXPORT _declspec (dllexport) +#else + #define DECLSPEC_DLLEXPORT +#endif + +// macro for defining entity class DLL structures +#define ENTITY_CLASSDEFINITION(classname, basename, descriptivename, iconfilename, id)\ + extern "C" DECLSPEC_DLLEXPORT CDLLEntityClass classname##_DLLClass; \ + CDLLEntityClass classname##_DLLClass = { \ + classname##_properties, \ + classname##_propertiesct, \ + classname##_handlers, \ + classname##_handlersct, \ + classname##_components, \ + classname##_componentsct, \ + descriptivename, \ + iconfilename, \ + id, \ + &basename##_DLLClass, \ + &classname##_New, \ + &classname##_OnInitClass, \ + &classname##_OnEndClass, \ + &classname##_OnPrecache, \ + &classname##_OnWorldInit, \ + &classname##_OnWorldTick, \ + &classname##_OnWorldRender, \ + &classname##_OnWorldEnd \ + };\ + SYMBOLLOCATOR(classname##_DLLClass) + +#define ENTITY_CLASSDEFINITION_BASE(classname, id) \ + extern "C" DECLSPEC_DLLEXPORT CDLLEntityClass classname##_DLLClass; \ + CDLLEntityClass classname##_DLLClass = { \ + NULL,0, NULL,0, NULL,0, "", "", id, \ + NULL, NULL,NULL,NULL,NULL, NULL,NULL,NULL,NULL \ + } + +inline ENGINE_API void ClearToDefault(FLOAT &f) { f = 0.0f; }; +inline ENGINE_API void ClearToDefault(INDEX &i) { i = 0; }; +inline ENGINE_API void ClearToDefault(BOOL &b) { b = FALSE; }; +inline ENGINE_API void ClearToDefault(CEntityPointer &pen) { pen = NULL; }; +inline ENGINE_API void ClearToDefault(CTString &str) { str = ""; }; +inline ENGINE_API void ClearToDefault(FLOATplane3D &pl) { pl = FLOATplane3D(FLOAT3D(0,1,0), 0); }; +inline ENGINE_API void ClearToDefault(FLOAT3D &v) { v = FLOAT3D(0,1,0); }; +inline ENGINE_API void ClearToDefault(COLOR &c) { c = 0xFFFFFFFF; }; +inline ENGINE_API void ClearToDefault(CModelData *&pmd) { pmd = NULL; }; +inline ENGINE_API void ClearToDefault(CTextureData *&pmt) { pmt = NULL; }; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Entities/FieldBSPTesting.cpp b/Sources/Engine/Entities/FieldBSPTesting.cpp new file mode 100644 index 0000000..f1787bd --- /dev/null +++ b/Sources/Engine/Entities/FieldBSPTesting.cpp @@ -0,0 +1,129 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static CEntity *penField; +static CBrushSector *_pbsc; +static CStaticStackArray _apenActive; + +static BOOL EntityIsInside(CEntity *pen) +{ + // get bounding sphere + FLOAT fSphereRadius = pen->en_fSpatialClassificationRadius; + const FLOAT3D &vSphereCenter = pen->en_plPlacement.pl_PositionVector; + + // if the entity touches sector's bounding box + if (_pbsc->bsc_boxBoundingBox.TouchesSphere(vSphereCenter, fSphereRadius)) { + // make oriented bounding box of the entity + const FLOAT3D &v = pen->en_plPlacement.pl_PositionVector; + const FLOATmatrix3D &m = pen->en_mRotation; + FLOATobbox3D boxEntity = FLOATobbox3D(pen->en_boxSpatialClassification, v, m); + DOUBLEobbox3D boxdEntity = FLOATtoDOUBLE(boxEntity); + + // if the box touches the sector's BSP + if (boxEntity.HasContactWith(FLOATobbox3D(_pbsc->bsc_boxBoundingBox)) && + _pbsc->bsc_bspBSPTree.TestBox(boxdEntity)<=0) { + + // for each collision sphere + CStaticArray &absSpheres = pen->en_pciCollisionInfo->ci_absSpheres; + for(INDEX iSphere=0; iSpherebsc_bspBSPTree.TestSphere( + FLOATtoDOUBLE(ms.ms_vRelativeCenter0), ms.ms_fR)<=0) { + return TRUE; + } + } + } + } + + // otherwise it doesn't touch + return FALSE; +} + +// find first entity touching a field (this entity must be a field brush) +CEntity *CEntity::TouchingEntity(BOOL (*ConsiderEntity)(CEntity *), CEntity *penHintMaybeInside) +{ + // if not a field brush + if (en_RenderType!=RT_FIELDBRUSH) { + // error + ASSERT(FALSE); + return NULL; + } + + // remember the entity and its first sector + penField = this; + CBrushMip *pbm = en_pbrBrush->GetBrushMipByDistance(0.0f); + _pbsc = NULL; + {FOREACHINDYNAMICARRAY(pbm->bm_abscSectors, CBrushSector, itbsc) { + _pbsc = itbsc; + break; + }} + // if illegal number of sectors + if (_pbsc==NULL || pbm->bm_abscSectors.Count()>1) { + // error + CPrintF("Field doesn't have exactly one sector - ignoring!\n"); + return NULL; + } + + // if a specific entity to check is given + if (penHintMaybeInside!=NULL) { + // if it is inside + if (EntityIsInside(penHintMaybeInside)) { + // return it + return penHintMaybeInside; + } + } + + CEntity *penTouched = NULL; + // no entities active initially + _apenActive.PopAll(); + // for each zoning sector that this entity is in + {FOREACHSRCOFDST(en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // for all movable model entities that should be considered in the sector + {FOREACHDSTOFSRC(pbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) + if (!(pen->en_ulPhysicsFlags&EPF_MOVABLE) + || (pen->en_RenderType!=RT_MODEL&&pen->en_RenderType!=RT_EDITORMODEL) + || (!ConsiderEntity(pen))) { + continue; + } + // if already active + if (pen->en_ulFlags&ENF_FOUNDINGRIDSEARCH) { + // skip it + continue; + } + // if it is inside + if (EntityIsInside(pen)) { + // stop the search + penTouched = pen; + break; + } + // add it to active + _apenActive.Push() = pen; + pen->en_ulFlags |= ENF_FOUNDINGRIDSEARCH; + }} + ENDFOR} + + // mark all as inactive + {for (INDEX ien=0; ien<_apenActive.Count(); ien++) { + CEntity *pen = _apenActive[ien]; + pen->en_ulFlags &= ~ENF_FOUNDINGRIDSEARCH; + }} + + _apenActive.PopAll(); + + return penTouched; +} diff --git a/Sources/Engine/Entities/FieldSettings.h b/Sources/Engine/Entities/FieldSettings.h new file mode 100644 index 0000000..2b95515 --- /dev/null +++ b/Sources/Engine/Entities/FieldSettings.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_FIELDSETTINGS_H +#define SE_INCL_FIELDSETTINGS_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Structure describing properties of a field entity. + */ + +class ENGINE_API CFieldSettings { +public: + CTextureObject fs_toTexture; // texture for rendering field in WEd + COLOR fs_colColor; // color for rendering field in WEd +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Entities/InternalClasses.h b/Sources/Engine/Entities/InternalClasses.h new file mode 100644 index 0000000..6372703 --- /dev/null +++ b/Sources/Engine/Entities/InternalClasses.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_INTERNALCLASSES_H +#define SE_INCL_INTERNALCLASSES_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DECL_DLL ENGINE_API +#include +#include +#include +#include +#undef DECL_DLL + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Entities/LastPositions.cpp b/Sources/Engine/Entities/LastPositions.cpp new file mode 100644 index 0000000..84788a4 --- /dev/null +++ b/Sources/Engine/Entities/LastPositions.cpp @@ -0,0 +1,38 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" + +#include +#include +#include +#include + +CLastPositions::CLastPositions(const CLastPositions &lpOrg) +{ + lp_avPositions = lpOrg.lp_avPositions ; + lp_iLast = lpOrg.lp_iLast ; + lp_ctUsed = lpOrg.lp_ctUsed ; + lp_tmLastAdded = lpOrg.lp_tmLastAdded ; +} + +// add a new position +void CLastPositions::AddPosition(const FLOAT3D &vPos) +{ + lp_iLast++; + if (lp_iLast>=lp_avPositions.Count()) { + lp_iLast=0; + } + lp_ctUsed = Min(INDEX(lp_ctUsed+1), lp_avPositions.Count()); + lp_avPositions[lp_iLast] = vPos; + lp_tmLastAdded = _pTimer->CurrentTick(); +} + +// get a position +const FLOAT3D &CLastPositions::GetPosition(INDEX iPre) +{ + INDEX iPos = lp_iLast-iPre; + if (iPos<0) { + iPos+=lp_avPositions.Count(); + } + return lp_avPositions[iPos]; +} diff --git a/Sources/Engine/Entities/LastPositions.h b/Sources/Engine/Entities/LastPositions.h new file mode 100644 index 0000000..413dd53 --- /dev/null +++ b/Sources/Engine/Entities/LastPositions.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_LASTPOSITIONS_H +#define SE_INCL_LASTPOSITIONS_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +// last positions for particle systems +class ENGINE_API CLastPositions { +public: + CStaticArray lp_avPositions; + INDEX lp_iLast; // where entity was last placed + INDEX lp_ctUsed; // how many positions are actually used + TIME lp_tmLastAdded; // time when last updated + + CLastPositions() {}; + CLastPositions(const CLastPositions &lpOrg); + + // add a new position + void AddPosition(const FLOAT3D &vPos); + // get a position + const FLOAT3D &GetPosition(INDEX iPre); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Entities/NearestPolygon.cpp b/Sources/Engine/Entities/NearestPolygon.cpp new file mode 100644 index 0000000..c61ea37 --- /dev/null +++ b/Sources/Engine/Entities/NearestPolygon.cpp @@ -0,0 +1,179 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +#include +#include +#include +#include +#include + +static CEntity *_pen; +static FLOAT3D _vHandle; +static CBrushPolygon *_pbpoNear; +static FLOAT _fNearDistance; +static FLOAT3D _vNearPoint; +static FLOATplane3D _plPlane; + +class CActiveSector { +public: + CBrushSector *as_pbsc; + void Clear(void) {}; +}; + +static CStaticStackArray _aas; + +/* Add a sector if needed. */ +static void AddSector(CBrushSector *pbsc) +{ + // if not already active and in first mip of its brush + if ( pbsc->bsc_pbmBrushMip->IsFirstMip() + &&!(pbsc->bsc_ulFlags&BSCF_NEARTESTED)) { + // add it to active sectors + _aas.Push().as_pbsc = pbsc; + pbsc->bsc_ulFlags|=BSCF_NEARTESTED; + } +} +/* Add all sectors of a brush. */ +static void AddAllSectorsOfBrush(CBrush3D *pbr) +{ + // get first mip + CBrushMip *pbmMip = pbr->GetFirstMip(); + // if it has no brush mip for that mip factor + if (pbmMip==NULL) { + // skip it + return; + } + // for each sector in the brush mip + FOREACHINDYNAMICARRAY(pbmMip->bm_abscSectors, CBrushSector, itbsc) { + // add the sector + AddSector(itbsc); + } +} + +void SearchThroughSectors(void) +{ + // for each active sector (sectors are added during iteration!) + for(INDEX ias=0; ias<_aas.Count(); ias++) { + CBrushSector *pbsc = _aas[ias].as_pbsc; + // for each polygon in the sector + {FOREACHINSTATICARRAY(pbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + CBrushPolygon &bpo = *itbpo; + // if it is not a wall + if (bpo.bpo_ulFlags&BPOF_PORTAL) { + // skip it + continue; + } + const FLOATplane3D &plPolygon = bpo.bpo_pbplPlane->bpl_plAbsolute; + // find distance of the polygon plane from the handle + FLOAT fDistance = plPolygon.PointDistance(_vHandle); + // if it is behind the plane or further than nearest found + if (fDistance<0.0f || fDistance>_fNearDistance) { + // skip it + continue; + } + // find projection of handle to the polygon plane + FLOAT3D vOnPlane = plPolygon.ProjectPoint(_vHandle); + // if it is not in the bounding box of polygon + const FLOATaabbox3D &boxPolygon = bpo.bpo_boxBoundingBox; + const FLOAT EPSILON = 0.01f; + if ( + (boxPolygon.Min()(1)-EPSILON>vOnPlane(1)) || + (boxPolygon.Max()(1)+EPSILONvOnPlane(2)) || + (boxPolygon.Max()(2)+EPSILONvOnPlane(3)) || + (boxPolygon.Max()(3)+EPSILONbpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + const FLOAT3D &vVertex1 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + // pass the edge to the intersector + isIntersector.AddEdge( + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2), + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2)); + } + + // if the point is not inside polygon + if (!isIntersector.IsIntersecting()) { + // skip it + continue; + } + + // remember the polygon + _pbpoNear = &bpo; + _fNearDistance = fDistance; + _vNearPoint = vOnPlane; + }} + + // for each entity in the sector + {FOREACHDSTOFSRC(pbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) + // if it is a brush + if (pen->en_RenderType == CEntity::RT_BRUSH) { + // get its brush + CBrush3D &brBrush = *pen->en_pbrBrush; + // add all sectors in the brush + AddAllSectorsOfBrush(&brBrush); + } + ENDFOR} + } +} + +/* Get nearest position of nearest brush polygon to this entity if available. */ +// use: +// ->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity +// to get the entity +CBrushPolygon *CEntity::GetNearestPolygon( + FLOAT3D &vPoint, FLOATplane3D &plPlane, FLOAT &fDistanceToEdge) +{ + _pen = this; + // take reference point at handle of the model entity + _vHandle = en_plPlacement.pl_PositionVector; + + // start infinitely far away + _pbpoNear = NULL; + _fNearDistance = UpperLimit(1.0f); + + // for each zoning sector that this entity is in + {FOREACHSRCOFDST(en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // add the sector + AddSector(pbsc); + ENDFOR} + + // start the search + SearchThroughSectors(); + + // for each active sector + for(INDEX ias=0; ias<_aas.Count(); ias++) { + // mark it as inactive + _aas[ias].as_pbsc->bsc_ulFlags&=~BSCF_NEARTESTED; + } + _aas.PopAll(); + + // if there is some polygon found + if( _pbpoNear!=NULL) { + // return info + plPlane = _pbpoNear->bpo_pbplPlane->bpl_plAbsolute; + vPoint = _vNearPoint; + fDistanceToEdge = _pbpoNear->GetDistanceFromEdges(_vNearPoint); + return _pbpoNear; + // if none is found + } else { + // return failure + return NULL; + } +} diff --git a/Sources/Engine/Entities/PlayerCharacter.cpp b/Sources/Engine/Entities/PlayerCharacter.cpp new file mode 100644 index 0000000..da824e3 --- /dev/null +++ b/Sources/Engine/Entities/PlayerCharacter.cpp @@ -0,0 +1,198 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include + +typedef HRESULT __stdcall CoCreateGuid_t(UBYTE *pguid); + +// get a GUID from system +static void GetGUID(UBYTE aub[16]) +{ + HINSTANCE hOle32Lib = NULL; + CoCreateGuid_t *pCoCreateGuid = NULL; + + try { + // load ole32 + hOle32Lib = ::LoadLibraryA( "ole32.dll"); + if( hOle32Lib == NULL) { + ThrowF_t(TRANS("Cannot load ole32.dll.")); + } + + // find GUID function + pCoCreateGuid = (CoCreateGuid_t*)GetProcAddress(hOle32Lib, "CoCreateGuid"); + if (pCoCreateGuid==NULL) { + ThrowF_t(TRANS("Cannot find CoCreateGuid().")); + } + + // create the guid + HRESULT hres = pCoCreateGuid(&aub[0]); + + // check for success + if (hres!=S_OK) { + ThrowF_t(TRANS("CoCreateGuid(): Error 0x%08x"), hres); + } + + // free the ole32 library + FreeLibrary(hOle32Lib); + + } catch(char *strError) { + FatalError(TRANS("Cannot make GUID for a player:\n%s"), strError); + } +} + +/* + * Default constructor -- no character. + */ +CPlayerCharacter::CPlayerCharacter(void) + : pc_strName(""), pc_strTeam("") +{ + memset(pc_aubGUID, 0, PLAYERGUIDSIZE); + memset(pc_aubAppearance, 0, MAX_PLAYERAPPEARANCE); +} + +/* + * Create a new character with its name. + */ +CPlayerCharacter::CPlayerCharacter(const CTString &strName) + : pc_strName(strName), pc_strTeam("") +{ + // if the name passed to constructor is empty string + if (strName=="") { + // make this an unnamed player + pc_strName = ""; + } + // create the guid + GetGUID(pc_aubGUID); + memset(pc_aubAppearance, 0, MAX_PLAYERAPPEARANCE); +} + +void CPlayerCharacter::Load_t( const CTFileName &fnFile) // throw char * +{ + CTFileStream strm; + strm.Open_t(fnFile); + Read_t(&strm); + strm.Close(); +} + +void CPlayerCharacter::Save_t( const CTFileName &fnFile) // throw char * +{ + CTFileStream strm; + strm.Create_t(fnFile); + Write_t(&strm); + strm.Close(); +} + +/* + * Read character from a stream. + */ +void CPlayerCharacter::Read_t(CTStream *pstr) // throw char * +{ + pstr->ExpectID_t("PLC4"); + (*pstr)>>pc_strName>>pc_strTeam; + pstr->Read_t(pc_aubGUID, sizeof(pc_aubGUID)); + pstr->Read_t(pc_aubAppearance, sizeof(pc_aubAppearance)); +} + +/* + * Write character into a stream. + */ +void CPlayerCharacter::Write_t(CTStream *pstr) // throw char * +{ + pstr->WriteID_t("PLC4"); + (*pstr)<Write_t(pc_aubGUID, sizeof(pc_aubGUID)); + pstr->Write_t(pc_aubAppearance, sizeof(pc_aubAppearance)); +} + +/* Get character name. */ +const CTString &CPlayerCharacter::GetName(void) const +{ + return pc_strName; +}; +const CTString CPlayerCharacter::GetNameForPrinting(void) const +{ + CTString strName(pc_strName); + // get rid of newlines in the name + strName.ReplaceSubstr("\n", ""); + strName.ReplaceSubstr("\r", ""); + return "^o"+pc_strName+"^r"; +} +/* Set character name. */ +void CPlayerCharacter::SetName(CTString strName) +{ + // limit string length to 20 characters not including decorated text control codes + // strName.TrimRightNaked(20); !!!! needs checking + pc_strName = strName; +}; + +/* Get character team. */ +const CTString &CPlayerCharacter::GetTeam(void) const +{ + return pc_strTeam; +} + +const CTString CPlayerCharacter::GetTeamForPrinting(void) const +{ + return "^o"+pc_strTeam+"^r"; +} + +/* Set character team. */ +void CPlayerCharacter::SetTeam(CTString strTeam) +{ + // limit string length to 20 characters not including decorated text control codes + // strTeam.TrimRightNaked(20); !!!! needs checking + pc_strTeam = strTeam; +} + +/* Assignment operator. */ +CPlayerCharacter &CPlayerCharacter::operator=(const CPlayerCharacter &pcOther) +{ + ASSERT(this!=NULL && &pcOther!=NULL); + pc_strName = pcOther.pc_strName; + pc_strTeam = pcOther.pc_strTeam; + memcpy(pc_aubGUID, pcOther.pc_aubGUID, PLAYERGUIDSIZE); + memcpy(pc_aubAppearance, pcOther.pc_aubAppearance, MAX_PLAYERAPPEARANCE); + return *this; +}; + +/* Comparison operator. */ +BOOL CPlayerCharacter::operator==(const CPlayerCharacter &pcOther) const +{ + for(INDEX i=0;i>(CTStream &strm, CPlayerCharacter &pc) +{ + pc.Read_t(&strm); + return strm; +}; +// message operations +CNetworkMessage &operator<<(CNetworkMessage &nm, CPlayerCharacter &pc) +{ + nm<>(CNetworkMessage &nm, CPlayerCharacter &pc) +{ + nm>>pc.pc_strName>>pc.pc_strTeam; + nm.Read(pc.pc_aubGUID, PLAYERGUIDSIZE); + nm.Read(pc.pc_aubAppearance, MAX_PLAYERAPPEARANCE); + return nm; +}; diff --git a/Sources/Engine/Entities/PlayerCharacter.h b/Sources/Engine/Entities/PlayerCharacter.h new file mode 100644 index 0000000..103f0f8 --- /dev/null +++ b/Sources/Engine/Entities/PlayerCharacter.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PLAYERCHARACTER_H +#define SE_INCL_PLAYERCHARACTER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Class describing one player character in game. + */ +class ENGINE_API CPlayerCharacter { +public: + // globally unique identifier of the player + // this is so that player can be identified even after renaming + #define PLAYERGUIDSIZE 16 + UBYTE pc_aubGUID[PLAYERGUIDSIZE]; + +public: + CTString pc_strName; // name of the character + CTString pc_strTeam; // team of the character + // buffer for custom use by CPlayerEntity derived class to describe player + #define MAX_PLAYERAPPEARANCE 32 + UBYTE pc_aubAppearance[MAX_PLAYERAPPEARANCE]; + + /* Default constructor. */ + CPlayerCharacter(void); + /* Create a new character with its name. */ + CPlayerCharacter(const CTString &strName); + /* Get character name. */ + const CTString &GetName(void) const; + const CTString GetNameForPrinting(void) const; + /* Set character name. */ + void SetName(CTString strName); + /* Get character team. */ + const CTString &GetTeam(void) const; + const CTString GetTeamForPrinting(void) const; + /* Set character team. */ + void SetTeam(CTString strTeam); + + void Load_t( const CTFileName &fnFile); // throw char * + void Save_t( const CTFileName &fnFile); // throw char * + /* Read character from a stream. */ + void Read_t(CTStream *pstr); // throw char * + /* Write character into a stream. */ + void Write_t(CTStream *pstr); // throw char * + + /* Assignment operator. */ + CPlayerCharacter &operator=(const CPlayerCharacter &pcOther); + + /* Comparison operator. */ + BOOL operator==(const CPlayerCharacter &pcOther) const; + + // stream operations + ENGINE_API friend CTStream &operator<<(CTStream &strm, CPlayerCharacter &pc); + ENGINE_API friend CTStream &operator>>(CTStream &strm, CPlayerCharacter &pc); + // message operations + friend CNetworkMessage &operator<<(CNetworkMessage &nm, CPlayerCharacter &pc); + friend CNetworkMessage &operator>>(CNetworkMessage &nm, CPlayerCharacter &pc); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Entities/Precaching.h b/Sources/Engine/Entities/Precaching.h new file mode 100644 index 0000000..3f445b9 --- /dev/null +++ b/Sources/Engine/Entities/Precaching.h @@ -0,0 +1,55 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PRECACHING_H +#define SE_INCL_PRECACHING_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#define PRECACHE_NONE 0 +#define PRECACHE_SMART 1 +#define PRECACHE_ALL 2 +#define PRECACHE_PARANOIA 3 + +extern ENGINE_API INDEX gam_iPrecachePolicy; +extern ENGINE_API INDEX _precache_bNowPrecaching; + +class CTmpPrecachingNow { +public: + BOOL m_bOldPrecaching; + + inline CTmpPrecachingNow(void) { + m_bOldPrecaching = _precache_bNowPrecaching; + _precache_bNowPrecaching = TRUE; + } + ~CTmpPrecachingNow(void) + { + _precache_bNowPrecaching = m_bOldPrecaching; + } +}; + +class ENGINE_API CAutoPrecacheSound { +public: + CSoundData *apc_psd; + CAutoPrecacheSound(); + ~CAutoPrecacheSound(); + void Precache(const CTFileName &fnm); +}; +class ENGINE_API CAutoPrecacheModel { +public: + CModelData *apc_pmd; + CAutoPrecacheModel(); + ~CAutoPrecacheModel(); + void Precache(const CTFileName &fnm); +}; +class ENGINE_API CAutoPrecacheTexture { +public: + CTextureData *apc_ptd; + CAutoPrecacheTexture(); + ~CAutoPrecacheTexture(); + void Precache(const CTFileName &fnm); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Entities/ShadingInfo.h b/Sources/Engine/Entities/ShadingInfo.h new file mode 100644 index 0000000..3571bc9 --- /dev/null +++ b/Sources/Engine/Entities/ShadingInfo.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SHADINGINFO_H +#define SE_INCL_SHADINGINFO_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +// Used for caching shading info for models if they don't move +class ENGINE_API CShadingInfo { +public: + CListNode si_lnInPolygon; // for linking in the relevant polygon + CBrushPolygon *si_pbpoPolygon; // the polygon that entity is above + CTerrain *si_ptrTerrain; // terrain that entity is above + FLOAT3D si_vNearPoint; // the relevant point in absolute space + PIX si_pixShadowU, si_pixShadowV; // the relevant point in the polygon shadow map + FLOAT si_fUDRatio, si_fLRRatio; // fraction between pixels + CEntity *si_penEntity; // the entity which uses this shading info +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/GameAgent/GameAgent.cpp b/Sources/Engine/GameAgent/GameAgent.cpp new file mode 100644 index 0000000..8626253 --- /dev/null +++ b/Sources/Engine/GameAgent/GameAgent.cpp @@ -0,0 +1,477 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" + +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include + +#pragma comment(lib, "wsock32.lib") + +WSADATA* _wsaData = NULL; +SOCKET _socket = NULL; + +sockaddr_in* _sin = NULL; +sockaddr_in* _sinLocal = NULL; +sockaddr_in _sinFrom; + +CHAR* _szBuffer = NULL; + +BOOL _bServer = FALSE; +static BOOL _bInitialized = FALSE; + +TIME _tmLastHeartbeat = 0; + +CDynamicStackArray ga_asrRequests; + +extern CTString ga_strServer = "master1.croteam.org"; + +void _uninitWinsock(); +void _initializeWinsock(void) +{ + if(_wsaData != NULL && _socket != NULL) { + return; + } + + _wsaData = new WSADATA; + _socket = NULL; + + // make the buffer that we'll use for packet reading + if(_szBuffer != NULL) { + delete[] _szBuffer; + } + _szBuffer = new char[1400]; + + // start WSA + if(WSAStartup(MAKEWORD(2, 2), _wsaData) != 0) { + CPrintF("Error initializing winsock!\n"); + _uninitWinsock(); + return; + } + + // get the host IP + hostent* phe = gethostbyname(ga_strServer); + + // if we couldn't resolve the hostname + if(phe == NULL) { + // report and stop + CPrintF("Couldn't resolve GameAgent server %s.\n", ga_strServer); + _uninitWinsock(); + return; + } + + // create the socket destination address + _sin = new sockaddr_in; + _sin->sin_family = AF_INET; + _sin->sin_addr.s_addr = *(ULONG*)phe->h_addr_list[0]; + _sin->sin_port = htons(9005); + + // create the socket + _socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + + // if we're a server + if(_bServer) { + // create the local socket source address + _sinLocal = new sockaddr_in; + _sinLocal->sin_family = AF_INET; + _sinLocal->sin_addr.s_addr = inet_addr("0.0.0.0"); + _sinLocal->sin_port = htons(_pShell->GetINDEX("net_iPort") + 1); + + // bind the socket + bind(_socket, (sockaddr*)_sinLocal, sizeof(*_sinLocal)); + } + + // set the socket to be nonblocking + DWORD dwNonBlocking = 1; + if(ioctlsocket(_socket, FIONBIO, &dwNonBlocking) != 0) { + CPrintF("Error setting socket to nonblocking!\n"); + _uninitWinsock(); + return; + } +} + +void _uninitWinsock() +{ + if(_wsaData != NULL) { + closesocket(_socket); + delete _wsaData; + _wsaData = NULL; + } + _socket = NULL; +} + +void _sendPacketTo(const char* pubBuffer, INDEX iLen, sockaddr_in* sin) +{ + sendto(_socket, pubBuffer, iLen, 0, (sockaddr*)sin, sizeof(sockaddr_in)); +} +void _sendPacketTo(const char* szBuffer, sockaddr_in* addsin) +{ + sendto(_socket, szBuffer, strlen(szBuffer), 0, (sockaddr*)addsin, sizeof(sockaddr_in)); +} + +void _sendPacket(const char* pubBuffer, INDEX iLen) +{ + _initializeWinsock(); + _sendPacketTo(pubBuffer, iLen, _sin); +} +void _sendPacket(const char* szBuffer) +{ + _initializeWinsock(); + _sendPacketTo(szBuffer, _sin); +} + +int _recvPacket() +{ + int fromLength = sizeof(_sinFrom); + return recvfrom(_socket, _szBuffer, 1024, 0, (sockaddr*)&_sinFrom, &fromLength); +} + +CTString _getGameModeName(INDEX iGameMode) +{ + // get function that will provide us the info about gametype + CShellSymbol *pss = _pShell->GetSymbol("GetGameTypeNameSS", /*bDeclaredOnly=*/ TRUE); + + if(pss == NULL) { + return ""; + } + + CTString (*pFunc)(INDEX) = (CTString (*)(INDEX))pss->ss_pvValue; + return pFunc(iGameMode); +} + +const CSessionProperties* _getSP() +{ + return ((const CSessionProperties *)_pNetwork->GetSessionProperties()); +} + +void _sendHeartbeat(INDEX iChallenge) +{ + CTString strPacket; + strPacket.PrintF("0;challenge;%d;players;%d;maxplayers;%d;level;%s;gametype;%s;version;%s;product;%s", + iChallenge, + _pNetwork->ga_srvServer.GetPlayersCount(), + _pNetwork->ga_sesSessionState.ses_ctMaxPlayers, + _pNetwork->ga_World.wo_strName, + _getGameModeName(_getSP()->sp_gmGameMode), + _SE_VER_STRING, + _pShell->GetString("sam_strGameName")); + _sendPacket(strPacket); + _tmLastHeartbeat = _pTimer->GetRealTimeTick(); +} + +static void _setStatus(const CTString &strStatus) +{ + _pNetwork->ga_bEnumerationChange = TRUE; + _pNetwork->ga_strEnumerationStatus = strStatus; +} + +CServerRequest::CServerRequest(void) +{ + Clear(); +} +CServerRequest::~CServerRequest(void) { } +void CServerRequest::Clear(void) +{ + sr_ulAddress = 0; + sr_iPort = 0; + sr_tmRequestTime = 0; +} + +/// Initialize GameAgent. +extern void GameAgent_ServerInit(void) +{ + // join + _bServer = TRUE; + _bInitialized = TRUE; + _sendPacket("q"); +} + +/// Let GameAgent know that the server has stopped. +extern void GameAgent_ServerEnd(void) +{ + if (!_bInitialized) { + return; + } + _uninitWinsock(); + _bInitialized = FALSE; +} + +/// GameAgent server update call which responds to enumeration pings and sends pings to masterserver. +extern void GameAgent_ServerUpdate(void) +{ + if((_socket == NULL) || (!_bInitialized)) { + return; + } + + int iLen = _recvPacket(); + if(iLen > 0) { + // check the received packet ID + switch(_szBuffer[0]) { + case 1: // server join response + { + int iChallenge = *(INDEX*)(_szBuffer + 1); + // send the challenge + _sendHeartbeat(iChallenge); + break; + } + + case 2: // server status request + { + // send the status response + CTString strPacket; + strPacket.PrintF("0;players;%d;maxplayers;%d;level;%s;gametype;%s;version;%s;gamename;%s;sessionname;%s", + _pNetwork->ga_srvServer.GetPlayersCount(), + _pNetwork->ga_sesSessionState.ses_ctMaxPlayers, + _pNetwork->ga_World.wo_strName, + _getGameModeName(_getSP()->sp_gmGameMode), + _SE_VER_STRING, + _pShell->GetString("sam_strGameName"), + _pShell->GetString("gam_strSessionName")); + _sendPacketTo(strPacket, &_sinFrom); + break; + } + + case 3: // player status request + { + // send the player status response + CTString strPacket; + strPacket.PrintF("\x01players\x02%d\x03", _pNetwork->ga_srvServer.GetPlayersCount()); + for(INDEX i=0; i<_pNetwork->ga_srvServer.GetPlayersCount(); i++) { + CPlayerBuffer &plb = _pNetwork->ga_srvServer.srv_aplbPlayers[i]; + CPlayerTarget &plt = _pNetwork->ga_sesSessionState.ses_apltPlayers[i]; + if(plt.plt_bActive) { + CTString strPlayer; + plt.plt_penPlayerEntity->GetGameAgentPlayerInfo(plb.plb_Index, strPlayer); + + // if we don't have enough space left for the next player + if(strlen(strPacket) + strlen(strPlayer) > 1024) { + // send the packet + _sendPacketTo(strPacket, &_sinFrom); + strPacket = ""; + } + + strPacket += strPlayer; + } + } + + strPacket += "\x04"; + _sendPacketTo(strPacket, &_sinFrom); + break; + } + + case 4: // ping + { + // just send back 1 byte and the amount of players in the server (this could be useful in some cases for external scripts) + CTString strPacket; + strPacket.PrintF("\x04%d", _pNetwork->ga_srvServer.GetPlayersCount()); + _sendPacketTo(strPacket, &_sinFrom); + break; + } + } + } + + // send a heartbeat every 150 seconds + if(_pTimer->GetRealTimeTick() - _tmLastHeartbeat >= 150.0f) { + _sendHeartbeat(0); + } +} + +/// Notify GameAgent that the server state has changed. +extern void GameAgent_ServerStateChanged(void) +{ + if (_bInitialized) { + _sendPacket("u"); + } +} + +/// Request serverlist enumeration. +extern void GameAgent_EnumTrigger(BOOL bInternet) +{ + if (!_bInitialized) { + return; + } + // make sure that there are no requests still stuck in buffer + ga_asrRequests.Clear(); + + // we're not a server + _bServer = FALSE; + + // send enumeration packet to masterserver + _sendPacket("e"); + _setStatus(""); +} + +/// GameAgent client update for enumerations. +extern void GameAgent_EnumUpdate(void) +{ + if((_socket == NULL) || (!_bInitialized)) { + return; + } + + int iLen = _recvPacket(); + if(iLen != -1) { + // null terminate the buffer + _szBuffer[iLen] = 0; + + switch(_szBuffer[0]) { + case 's': + { + struct sIPPort { + UBYTE bFirst; + UBYTE bSecond; + UBYTE bThird; + UBYTE bFourth; + USHORT iPort; + }; + sIPPort* pServers = (sIPPort*)(_szBuffer + 1); + while(iLen - ((CHAR*)pServers - _szBuffer) >= sizeof(sIPPort)) { + sIPPort ip = *pServers; + + CTString strIP; + strIP.PrintF("%d.%d.%d.%d", ip.bFirst, ip.bSecond, ip.bThird, ip.bFourth); + + sockaddr_in sinServer; + sinServer.sin_family = AF_INET; + sinServer.sin_addr.s_addr = inet_addr(strIP); + sinServer.sin_port = htons(ip.iPort + 1); + + // insert server status request into container + CServerRequest &sreq = ga_asrRequests.Push(); + sreq.sr_ulAddress = sinServer.sin_addr.s_addr; + sreq.sr_iPort = sinServer.sin_port; + sreq.sr_tmRequestTime = _pTimer->GetHighPrecisionTimer().GetMilliseconds(); + + // send packet to server + _sendPacketTo("\x02", &sinServer); + + pServers++; + } + } + break; + + case '0': + { + CTString strPlayers; + CTString strMaxPlayers; + CTString strLevel; + CTString strGameType; + CTString strVersion; + CTString strGameName; + CTString strSessionName; + + CHAR* pszPacket = _szBuffer + 2; // we do +2 because the first character is always ';', which we don't care about. + + BOOL bReadValue = FALSE; + CTString strKey; + CTString strValue; + + while(*pszPacket != 0) { + switch(*pszPacket) { + case ';': + if(strKey != "sessionname") { + if(bReadValue) { + // we're done reading the value, check which key it was + if(strKey == "players") { + strPlayers = strValue; + } else if(strKey == "maxplayers") { + strMaxPlayers = strValue; + } else if(strKey == "level") { + strLevel = strValue; + } else if(strKey == "gametype") { + strGameType = strValue; + } else if(strKey == "version") { + strVersion = strValue; + } else if(strKey == "gamename") { + strGameName = strValue; + } else { + CPrintF("Unknown GameAgent parameter key '%s'!", strKey); + } + + // reset temporary holders + strKey = ""; + strValue = ""; + } + } + bReadValue = !bReadValue; + break; + + default: + // read into the value or into the key, depending where we are + if(bReadValue) { + strValue.InsertChar(strlen(strValue), *pszPacket); + } else { + strKey.InsertChar(strlen(strKey), *pszPacket); + } + break; + } + + // move to next character + pszPacket++; + } + + // check if we still have a sessionname to back up + if(strKey == "sessionname") { + strSessionName = strValue; + } + + // insert the server into the serverlist + CNetworkSession &ns = *new CNetworkSession; + _pNetwork->ga_lhEnumeratedSessions.AddTail(ns.ns_lnNode); + + long long tmPing = -1; + // find the request in the request array + for(INDEX i=0; iGetHighPrecisionTimer().GetMilliseconds() - req.sr_tmRequestTime; + ga_asrRequests.Delete(&req); + break; + } + } + + if(tmPing == -1) { + // server status was never requested + break; + } + + // add the server to the serverlist + ns.ns_strSession = strSessionName; + ns.ns_strAddress = inet_ntoa(_sinFrom.sin_addr) + CTString(":") + CTString(0, "%d", htons(_sinFrom.sin_port) - 1); + ns.ns_tmPing = (tmPing / 1000.0f); + ns.ns_strWorld = strLevel; + ns.ns_ctPlayers = atoi(strPlayers); + ns.ns_ctMaxPlayers = atoi(strMaxPlayers); + ns.ns_strGameType = strGameType; + ns.ns_strMod = strGameName; + ns.ns_strVer = strVersion; + } + break; + + default: + CPrintF("Unknown enum packet ID %x!\n", _szBuffer[0]); + break; + } + } +} + +/// Cancel the GameAgent serverlist enumeration. +extern void GameAgent_EnumCancel(void) +{ + if (_bInitialized) { + ga_asrRequests.Clear(); + _uninitWinsock(); + } +} diff --git a/Sources/Engine/GameAgent/GameAgent.h b/Sources/Engine/GameAgent/GameAgent.h new file mode 100644 index 0000000..1e8ecb7 --- /dev/null +++ b/Sources/Engine/GameAgent/GameAgent.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_GAMEAGENT_H +#define SE_INCL_GAMEAGENT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +extern CTString ga_strServer; + +/// Initialize GameAgent. +extern void GameAgent_ServerInit(void); +/// Let GameAgent know that the server has stopped. +extern void GameAgent_ServerEnd(void); +/// GameAgent server update call which responds to enumeration pings and sends pings to masterserver. +extern void GameAgent_ServerUpdate(void); +/// Notify GameAgent that the server state has changed. +extern void GameAgent_ServerStateChanged(void); + +/// Request serverlist enumeration. +extern void GameAgent_EnumTrigger(BOOL bInternet); +/// GameAgent client update for enumeration. +extern void GameAgent_EnumUpdate(void); +/// Cancel the GameAgent serverlist enumeration. +extern void GameAgent_EnumCancel(void); + +/// Server request structure. Primarily used for getting server pings. +class CServerRequest { +public: + ULONG sr_ulAddress; + USHORT sr_iPort; + long long sr_tmRequestTime; + +public: + CServerRequest(void); + ~CServerRequest(void); + + /* Destroy all objects, and reset the array to initial (empty) state. */ + void Clear(void); +}; + +#endif // include once check diff --git a/Sources/Engine/GameShell.h b/Sources/Engine/GameShell.h new file mode 100644 index 0000000..cbd114a --- /dev/null +++ b/Sources/Engine/GameShell.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_GAMESHELL_H +#define SE_INCL_GAMESHELL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +struct GameGUI_interface { + // initialize game and load settings + void (*Initialize)(const CTFileName &fnGameSettings); + // save settings and cleanup + void (*End)(void); + // run a quicktest game from within editor + void (*QuickTest)(const CTFileName &fnMapName, CDrawPort *pdpDrawport, CViewPort *pvpViewport); + // show console window + void (*OnInvokeConsole)(void); + // adjust players and controls + void (*OnPlayerSettings)(void); + // adjust audio settings + void (*OnAudioQuality)(void); + // adjust video settings + void (*OnVideoQuality)(void); + // select current active player and controls + void (*OnSelectPlayerAndControls)(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/Adapter.cpp b/Sources/Engine/Graphics/Adapter.cpp new file mode 100644 index 0000000..268a37a --- /dev/null +++ b/Sources/Engine/Graphics/Adapter.cpp @@ -0,0 +1,299 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include + + +extern BOOL _bDedicatedServer; +#ifdef SE1_D3D +extern const D3DDEVTYPE d3dDevType; +#endif // SE1_D3D + +// list of all modes avaliable through CDS +static CListHead _lhCDSModes; + +class CResolution { +public: + PIX re_pixSizeI; + PIX re_pixSizeJ; +}; + +static CResolution _areResolutions[] = +{ + { 320, 240 }, + { 400, 300 }, + { 480, 360 }, + { 512, 384 }, + { 640, 480 }, + { 720, 540 }, + { 720, 576 }, + { 800, 600 }, + { 960, 720 }, + { 1024, 768 }, + { 1152, 864 }, + { 1280, 960 }, + { 1280, 1024 }, + { 1600, 1200 }, + { 1792, 1344 }, + { 1856, 1392 }, + { 1920, 1440 }, + { 2048, 1536 }, + + // matrox dualhead modes + { 1280, 480 }, + { 1600, 600 }, + { 2048, 768 }, + + // NTSC HDTV widescreen + { 848, 480 }, + { 856, 480 }, +}; +// THIS NUMBER MUST NOT BE OVER 25! (otherwise change it in adapter.h) +static const INDEX MAX_RESOLUTIONS = sizeof(_areResolutions)/sizeof(_areResolutions[0]); + + + +// initialize CDS support (enumerate modes at startup) +void CGfxLibrary::InitAPIs(void) +{ + // no need for gfx when dedicated server is on + if( _bDedicatedServer) return; + + CDisplayAdapter *pda; + INDEX iResolution; + + // detect current mode and print to console + DEVMODE devmode; + memset( &devmode, 0, sizeof(devmode)); + devmode.dmSize = sizeof(devmode); + LONG lRes = EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devmode); + CPrintF( TRANS("Current display: '%s' version %d - %dx%dx%d\n\n"), + devmode.dmDeviceName, devmode.dmDriverVersion, + devmode.dmPelsWidth, devmode.dmPelsHeight, devmode.dmBitsPerPel); + + // fill OpenGL adapter info + gl_gaAPI[GAT_OGL].ga_ctAdapters = 1; + gl_gaAPI[GAT_OGL].ga_iCurrentAdapter = 0; + pda = &gl_gaAPI[GAT_OGL].ga_adaAdapter[0]; + pda->da_ulFlags = DAF_USEGDIFUNCTIONS; + pda->da_strVendor = TRANS( "unknown"); + pda->da_strRenderer = TRANS( "Default ICD"); + pda->da_strVersion = "1.1+"; + + // detect modes for OpenGL ICD + pda->da_ctDisplayModes = 0; + pda->da_iCurrentDisplayMode = -1; + + // enumerate modes thru resolution list + for( iResolution=0; iResolutionda_admDisplayModes[pda->da_ctDisplayModes]; + dm.dm_pixSizeI = re.re_pixSizeI; + dm.dm_pixSizeJ = re.re_pixSizeJ; + dm.dm_ddDepth = DD_DEFAULT; + pda->da_ctDisplayModes++; + } + + // detect presence of 3Dfx standalone OpenGL driver (for Voodoo1/2) + char *strDummy; + char strBuffer[_MAX_PATH+1]; + int iRes = SearchPathA( NULL, "3DFXVGL.DLL", NULL, _MAX_PATH, strBuffer, &strDummy); + // if present + if(iRes) { + // set adapter and force some enumeration of voodoo1/2 display modes + gl_gaAPI[GAT_OGL].ga_ctAdapters++; + pda = &gl_gaAPI[GAT_OGL].ga_adaAdapter[1]; + pda->da_ctDisplayModes = 4; // voodoos have only 4 display modes + pda->da_ulFlags = DAF_ONEWINDOW | DAF_FULLSCREENONLY | DAF_16BITONLY; + pda->da_strVendor = "3Dfx"; + pda->da_strRenderer = "3Dfx Voodoo2"; + pda->da_strVersion = "1.1+"; + CDisplayMode *adm = &pda->da_admDisplayModes[0]; + adm[0].dm_pixSizeI = 512; adm[0].dm_pixSizeJ = 384; adm[0].dm_ddDepth = DD_16BIT; + adm[1].dm_pixSizeI = 640; adm[1].dm_pixSizeJ = 480; adm[1].dm_ddDepth = DD_16BIT; + adm[2].dm_pixSizeI = 800; adm[2].dm_pixSizeJ = 600; adm[2].dm_ddDepth = DD_16BIT; + adm[3].dm_pixSizeI = 1024; adm[3].dm_pixSizeJ = 768; adm[3].dm_ddDepth = DD_16BIT; + } + + // try to init Direct3D 8 +#ifdef SE1_D3D + BOOL bRes = InitDriver_D3D(); + if( !bRes) return; // didn't made it? + + // determine DX8 adapters and display modes + const INDEX ctMaxAdapters = gl_pD3D->GetAdapterCount(); + INDEX &ctAdapters = gl_gaAPI[GAT_D3D].ga_ctAdapters; + ctAdapters = 0; + + for( INDEX iAdapter=0; iAdapterda_ulFlags = NONE; + pda->da_ctDisplayModes = 0; + INDEX ctModes = gl_pD3D->GetAdapterModeCount(iAdapter); + INDEX iMode; + HRESULT hr; + + // check whether 32-bits rendering modes are supported + hr = gl_pD3D->CheckDeviceType( iAdapter, d3dDevType, D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FALSE); + if( hr!=D3D_OK) { + hr = gl_pD3D->CheckDeviceType( iAdapter, d3dDevType, D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, FALSE); + if( hr!=D3D_OK) pda->da_ulFlags |= DAF_16BITONLY; + } + + // check whether windowed rendering modes are supported + D3DCAPS8 d3dCaps; + gl_pD3D->GetDeviceCaps( iAdapter, d3dDevType, &d3dCaps); + if( !(d3dCaps.Caps2 & D3DCAPS2_CANRENDERWINDOWED)) pda->da_ulFlags |= DAF_FULLSCREENONLY; + + // enumerate modes thru resolution list + for( iResolution=0; iResolutionEnumAdapterModes( iAdapter, iMode, &d3dDisplayMode); + if( d3dDisplayMode.Width==re.re_pixSizeI && d3dDisplayMode.Height==re.re_pixSizeJ + && (d3dDisplayMode.Format==D3DFMT_A8R8G8B8 || d3dDisplayMode.Format==D3DFMT_X8R8G8B8 + || d3dDisplayMode.Format==D3DFMT_A1R5G5B5 || d3dDisplayMode.Format==D3DFMT_X1R5G5B5 + || d3dDisplayMode.Format==D3DFMT_R5G6B5)) { + hr = gl_pD3D->CheckDeviceType( iAdapter, d3dDevType, d3dDisplayMode.Format, d3dDisplayMode.Format, FALSE); + if( hr!=D3D_OK) continue; + + // make a new display mode + CDisplayMode &dm = pda->da_admDisplayModes[pda->da_ctDisplayModes]; + dm.dm_pixSizeI = re.re_pixSizeI; + dm.dm_pixSizeJ = re.re_pixSizeJ; + dm.dm_ddDepth = DD_DEFAULT; + pda->da_ctDisplayModes++; + break; + } + } + } + + // get adapter identifier + ctAdapters++; + D3DADAPTER_IDENTIFIER8 d3dAdapterIdentifier; + gl_pD3D->GetAdapterIdentifier( iAdapter, D3DENUM_NO_WHQL_LEVEL, &d3dAdapterIdentifier); + pda->da_strVendor = "MS DirectX 8"; + pda->da_strRenderer = d3dAdapterIdentifier.Description; + pda->da_strVersion.PrintF("%d.%d.%d.%d", d3dAdapterIdentifier.DriverVersion.HighPart >>16, + d3dAdapterIdentifier.DriverVersion.HighPart & 0xFFFF, + d3dAdapterIdentifier.DriverVersion.LowPart >>16, + d3dAdapterIdentifier.DriverVersion.LowPart & 0xFFFF); + } + // shutdown DX8 (we'll start it again if needed) + D3DRELEASE( gl_pD3D, TRUE); + if( gl_hiDriver!=NONE) FreeLibrary(gl_hiDriver); + gl_hiDriver = NONE; +#endif // SE1_D3D +} + +// get list of all modes avaliable through CDS -- do not modify/free the returned list +CListHead &CDS_GetModes(void) +{ + return _lhCDSModes; +} + + +// set given display mode +BOOL CDS_SetMode( PIX pixSizeI, PIX pixSizeJ, enum DisplayDepth dd) +{ + // no need for gfx when dedicated server is on + if( _bDedicatedServer) return FALSE; + + // prepare general mode parameters + DEVMODE devmode; + memset(&devmode, 0, sizeof(devmode)); + devmode.dmSize = sizeof(devmode); + devmode.dmPelsWidth = pixSizeI; + devmode.dmPelsHeight = pixSizeJ; + devmode.dmDisplayFlags = CDS_FULLSCREEN; + devmode.dmFields = DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFLAGS; + extern INDEX gap_iRefreshRate; + if( gap_iRefreshRate>0) { + devmode.dmFields |= DM_DISPLAYFREQUENCY; + devmode.dmDisplayFrequency = gap_iRefreshRate; + } + // determine bits per pixel to try to set + SLONG slBPP2 = 0; + switch(dd) { + case DD_16BIT: + devmode.dmBitsPerPel = 16; + slBPP2 = 15; + devmode.dmFields |= DM_BITSPERPEL; + break; + case DD_32BIT: + devmode.dmBitsPerPel = 32; + slBPP2 = 24; + devmode.dmFields |= DM_BITSPERPEL; + break; + case DD_DEFAULT: + NOTHING; + break; + default: + ASSERT(FALSE); + NOTHING; + } + + // try to set primary depth + LONG lRes = ChangeDisplaySettings(&devmode, CDS_FULLSCREEN); + + // if failed + if( lRes!=DISP_CHANGE_SUCCESSFUL) { + // try to set secondary depth + devmode.dmBitsPerPel = slBPP2; + LONG lRes2 = ChangeDisplaySettings(&devmode, CDS_FULLSCREEN); + // if failed + if( lRes2!=DISP_CHANGE_SUCCESSFUL) { + CTString strError; + switch(lRes) { + case DISP_CHANGE_SUCCESSFUL: strError = "DISP_CHANGE_SUCCESSFUL"; break; + case DISP_CHANGE_RESTART: strError = "DISP_CHANGE_RESTART"; break; + case DISP_CHANGE_BADFLAGS: strError = "DISP_CHANGE_BADFLAGS"; break; + case DISP_CHANGE_BADPARAM: strError = "DISP_CHANGE_BADPARAM"; break; + case DISP_CHANGE_FAILED: strError = "DISP_CHANGE_FAILED"; break; + case DISP_CHANGE_BADMODE: strError = "DISP_CHANGE_BADMODE"; break; + case DISP_CHANGE_NOTUPDATED: strError = "DISP_CHANGE_NOTUPDATED"; break; + default: strError.PrintF("%d", lRes); break; + } + CPrintF(TRANS("CDS error: %s\n"), strError); + return FALSE; + } + } + // report + CPrintF(TRANS(" CDS: mode set to %dx%dx%d\n"), pixSizeI, pixSizeJ, devmode.dmBitsPerPel); + return TRUE; +} + + +// reset windows to mode chosen by user within windows diplay properties +void CDS_ResetMode(void) +{ + // no need for gfx when dedicated server is on + if( _bDedicatedServer) return; + + LONG lRes = ChangeDisplaySettings( NULL, 0); + ASSERT(lRes==DISP_CHANGE_SUCCESSFUL); + CPrintF(TRANS(" CDS: mode reset to original desktop settings\n")); +} diff --git a/Sources/Engine/Graphics/Adapter.h b/Sources/Engine/Graphics/Adapter.h new file mode 100644 index 0000000..364db82 --- /dev/null +++ b/Sources/Engine/Graphics/Adapter.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ADAPTER_H +#define SE_INCL_ADAPTER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + + +// display adapter flags +#define DAF_ONEWINDOW (1L<<0) // supports only one window +#define DAF_FULLSCREENONLY (1L<<1) // don't add windowed modes +#define DAF_USEGDIFUNCTIONS (1L<<2) // don't use wgl functions instead gdi functions +#define DAF_16BITONLY (1L<<3) // supports only 16-bit color depth + + +class CDisplayAdapter +{ +public: + CDisplayMode da_admDisplayModes[25]; // 25 should be just enough + INDEX da_ctDisplayModes; // number of display modes with hardware acceleration (>=1) + INDEX da_iCurrentDisplayMode; // currently active display mode (-1 if none) + ULONG da_ulFlags; // various flags (DAF_ ...) + CTString da_strVendor; // OpenGL will fill this upon initialization of adapter ... + CTString da_strRenderer; // ... till then, it will be set to unknown/OpenGL ICD/1.1 or ... + CTString da_strVersion; // ... 3Dfx/OpenGL/1.1 +}; + + +class CGfxAPI +{ +public: + CDisplayAdapter ga_adaAdapter[4]; + INDEX ga_ctAdapters; // min=0, max=4 + INDEX ga_iCurrentAdapter; // currently active display adapter +}; + + +// get list of all modes avaliable through CDS -- do not modify/free the returned list +CListHead &CDS_GetModes(void); + +// set given display mode +BOOL CDS_SetMode( PIX pixSizeI, PIX pixSizeJ, enum DisplayDepth dd); +// reset windows to mode chosen by user within windows diplay properties +void CDS_ResetMode(void); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/Benchmark.cpp b/Sources/Engine/Graphics/Benchmark.cpp new file mode 100644 index 0000000..40afa2f --- /dev/null +++ b/Sources/Engine/Graphics/Benchmark.cpp @@ -0,0 +1,425 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include + + +static CViewPort *_pvp = NULL; +static CDrawPort *_pdp = NULL; +static PIX _pixSizeI; +static PIX _pixSizeJ; +static CTimerValue _tv; +static BOOL _bBlend = FALSE; +static BOOL _bVisible = FALSE; +static BOOL _bTexture = FALSE; +static BOOL _bDepth = FALSE; +static BOOL _bMultiTexture = FALSE; +static UBYTE *_pubTexture; +static ULONG _ulTexObject; +static ULONG _ulTexFormat; +static BOOL _bSubImage = FALSE; +static INDEX _ctR = 100; +static INDEX _ctC = 100; +static CTexParams _tpLocal; + +static CStaticStackArray _avtx; +static CStaticStackArray _atex; +static CStaticStackArray _acol; +static CStaticStackArray _aiElements; + + + +BOOL _bStarted = FALSE; +static __forceinline void StartTimer(void) +{ + ASSERT(!_bStarted); + _tv = _pTimer->GetHighPrecisionTimer(); + _bStarted = TRUE; +} + + +static __forceinline DOUBLE StopTimer(void) +{ + ASSERT(_bStarted); + _bStarted = FALSE; + return (_pTimer->GetHighPrecisionTimer()-_tv).GetSeconds(); +} + + +// fill rate benchmark +static DOUBLE FillRatePass(INDEX ct) +{ + if( !_pdp->Lock()) { + ASSERT(FALSE); + return 0; + } + + StartTimer(); + + _pdp->Fill(C_GRAY|255); + _pdp->FillZBuffer(1.0f); + + GFXVertex avtx[4]; + avtx[0].x = 0; avtx[0].y = 0; avtx[0].z = 0.5f; + avtx[1].x = 0; avtx[1].y = _pixSizeJ; avtx[1].z = 0.5f; + avtx[2].x = _pixSizeI; avtx[2].y = _pixSizeJ; avtx[2].z = 0.5f; + avtx[3].x = _pixSizeI; avtx[3].y = 0; avtx[3].z = 0.5f; + GFXTexCoord atex[4] = { {0,0}, {0,1}, {1,1}, {1,0} }; + GFXColor acol[4] = { 0xFF0000FF, 0xFF00FF00, 0xFFFF0000, 0xFFFF00FF }; + INDEX aidx[6] = { 0,1,2, 0,2,3}; + gfxSetVertexArray( &avtx[0], 4); + gfxSetTexCoordArray( &atex[0], FALSE); + gfxSetColorArray( &acol[0]); + + if(_bTexture) { + gfxEnableTexture(); + if(_bMultiTexture) { + gfxSetTextureUnit(1); + gfxEnableTexture(); + gfxSetTexture( _ulTexObject, _tpLocal); + gfxSetTexCoordArray(atex, FALSE); + gfxSetTextureUnit(0); + } + } else { + gfxDisableTexture(); + } + + if(_bBlend) { + gfxEnableBlend(); + if(_bTexture) { + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + } else { + gfxBlendFunc( GFX_ONE, GFX_ONE); + } + } else { + gfxDisableBlend(); + } + + if(_bDepth) { + gfxEnableDepthTest(); + gfxEnableDepthWrite(); + } else { + gfxDisableDepthTest(); + gfxDisableDepthWrite(); + } + gfxDisableAlphaTest(); + + for( INDEX i=0; iUnlock(); + + gfxFinish(); + _pvp->SwapBuffers(); + + return StopTimer(); +} + + +CTString FillRateString(void) +{ + CTString str; + str.PrintF( "%s, %s, %s ", + _bTexture ? (_bMultiTexture ? "multitexture" : "texture") : "no texture", + _bBlend ? "blending" : "no blending", + _bDepth ? "z-buffer:" : "no z-buffer:"); + return str; +} + + +static DOUBLE FillRate(void) +{ + DOUBLE dDelta = 0; + for( INDEX i=0; i<10; i++) { + dDelta += FillRatePass(3) - FillRatePass(2); + } + dDelta /= 10.0; + return (_pixSizeI*_pixSizeJ)/dDelta; +} + + +static void InitTexture(void) +{ + const SLONG slSize = 256*256 *4 *4/3 +16; + _pubTexture = (UBYTE*)AllocMemory(slSize); + for( INDEX i=0; i<256; i++) { + for( INDEX j=0; j<256; j++) { + _pubTexture[(j*256+i)*4+0] = i; + _pubTexture[(j*256+i)*4+1] = j; + _pubTexture[(j*256+i)*4+2] = i+j; + _pubTexture[(j*256+i)*4+3] = i-j; + } + } + MakeMipmaps( 15, (ULONG*)_pubTexture, 256,256); + _tpLocal.tp_bSingleMipmap = FALSE; + gfxGenerateTexture( _ulTexObject); + gfxSetTexture( _ulTexObject, _tpLocal); +} + + +static void EndTexture(void) +{ + gfxDeleteTexture( _ulTexObject); + FreeMemory(_pubTexture); + _pubTexture = NULL; +} + + +static void InitTris(void) +{ + INDEX iR, iC; + INDEX ctVx = _ctR*_ctC; + _avtx.Push(ctVx); + _atex.Push(ctVx); + _acol.Push(ctVx); + for( iR=0; iR<_ctR; iR++) { + for( iC=0; iC<_ctC; iC++) { + INDEX ivx = iR*_ctC+iC; + _avtx[ivx].x = FLOAT(iC) / _ctC*4 -2.0f; + _avtx[ivx].y = -FLOAT(iR) / _ctR*4 +2.0f; + _avtx[ivx].z = -1.0f; + _atex[ivx].s = (iC+iR) % 2; + _atex[ivx].t = (iR) % 2; + _acol[ivx].abgr = 0xFFFFFFFF; + } + } + INDEX ctTri = (_ctR-1)*(_ctC-1)*2; + _aiElements.Push(ctTri*3); + for( iR=0; iR<_ctR-1; iR++) { + for( iC=0; iC<_ctC-1; iC++) { + INDEX iq = iR*(_ctC-1)+iC; + _aiElements[iq*6+0] = (iR+1) * _ctC + (iC+0); + _aiElements[iq*6+1] = (iR+1) * _ctC + (iC+1); + _aiElements[iq*6+2] = (iR+0) * _ctC + (iC+0); + _aiElements[iq*6+3] = (iR+0) * _ctC + (iC+0); + _aiElements[iq*6+4] = (iR+1) * _ctC + (iC+1); + _aiElements[iq*6+5] = (iR+0) * _ctC + (iC+1); + } + } +} + + +static void EndTris(void) +{ + _avtx.Clear(); + _atex.Clear(); + _acol.Clear(); + _aiElements.Clear(); +} + + +static DOUBLE TrisTroughputPass(INDEX ct) +{ + if( !_pdp->Lock()) { + ASSERT(FALSE); + return 0; + } + + StartTimer(); + + gfxSetFrustum( -0.5f, +0.5f, -0.5f, +0.5f, 0.5f, 2.0f); + gfxSetViewMatrix(NULL); + gfxCullFace(GFX_NONE); + + _pdp->Fill(C_GRAY|255); + _pdp->FillZBuffer(1.0f); + + if(_bTexture) { + gfxEnableTexture(); + } else { + gfxDisableTexture(); + } + + if(_bBlend) { + gfxEnableBlend(); + gfxBlendFunc( GFX_ONE, GFX_ONE); + } else { + gfxDisableBlend(); + } + + if(_bDepth) { + gfxEnableDepthTest(); + gfxEnableDepthWrite(); + } else { + gfxDisableDepthTest(); + gfxDisableDepthWrite(); + } + gfxDisableAlphaTest(); + + gfxSetVertexArray( &_avtx[0], _avtx.Count()); + gfxLockArrays(); + gfxSetTexCoordArray( &_atex[0], FALSE); + gfxSetColorArray( &_acol[0]); + + if(_bMultiTexture) { + gfxSetTextureUnit(1); + gfxEnableTexture(); + gfxSetTexture( _ulTexObject, _tpLocal); + gfxSetTexCoordArray( &_atex[0], FALSE); + gfxSetTextureUnit(0); + } + for( INDEX i=0; iUnlock(); + + gfxFinish(); + _pvp->SwapBuffers(); + + return StopTimer(); +} + + +static DOUBLE TrisTroughput(void) +{ + DOUBLE dDelta = 0; + for( INDEX i=0; i<10; i++) { + dDelta += TrisTroughputPass(3) - TrisTroughputPass(2); + } + dDelta /= 10.0; + return ((_ctR-1)*(_ctC-1)*2)/dDelta; +} + + + +static DOUBLE TextureUpload(void) +{ + StartTimer(); + gfxUploadTexture( (ULONG*)_pubTexture, 256, 256, _ulTexFormat, _bSubImage); + const SLONG slTotal = 256*256*4 *4/3; + return slTotal/StopTimer(); +} + + + +static DOUBLE _dX; +static DOUBLE _dD; +static void RunTest(DOUBLE (*pTest)(void), INDEX ct) +{ + CSetPriority sp(REALTIME_PRIORITY_CLASS, THREAD_PRIORITY_TIME_CRITICAL); + + DOUBLE dSum = 0; + DOUBLE dSum2 = 0; + for(INDEX i=0; i<(ct+5); i++) { + DOUBLE d = pTest(); + // must ignore 1st couple of passes due to API queue + if( i>4) dSum += d; + if( i>4) dSum2 += d*d; + } + _dX = dSum/ct; + _dD = Sqrt((dSum2-2*dSum*_dX+ct*_dX*_dX)/(ct-1)); +} + + +/* Benchmark current driver. */ +void CGfxLibrary::Benchmark(CViewPort *pvp, CDrawPort *pdp) +{ + // remember drawport/viewport + _pdp = pdp; + _pvp = pvp; + _pixSizeI = pdp->GetWidth(); + _pixSizeJ = pdp->GetHeight(); + + CTString strAPI = ""; + if( _pGfx->gl_eCurrentAPI==GAT_OGL) strAPI = "OpenGL"; +#ifdef SE1_D3D + else if( _pGfx->gl_eCurrentAPI==GAT_D3D) strAPI = "Direct3D"; +#endif // SE1_D3D + CPrintF("=====================================\n"); + CPrintF("%s performance testing ...\n", strAPI); + + InitTexture(); + InitTris(); + + CPrintF("\n--- Texture upload\n"); + + _ulTexFormat = TS.ts_tfRGBA8; + _bSubImage = FALSE; + RunTest(TextureUpload, 10); + CPrintF("RGBA8 full: %6.02f +- %5.02f Mtex/s;" , _dX/1000/1000, _dD/1000/1000); + _bSubImage = TRUE; + RunTest(TextureUpload, 10); + CPrintF( " sub: %6.02f +- %5.02f Mtex/s\n", _dX/1000/1000, _dD/1000/1000); + + _ulTexFormat = TS.ts_tfRGB8; + _bSubImage = FALSE; + RunTest(TextureUpload, 10); + CPrintF("RGB8 full: %6.02f +- %5.02f Mtex/s;" , _dX/1000/1000, _dD/1000/1000); + _bSubImage = TRUE; + RunTest(TextureUpload, 10); + CPrintF( " sub: %6.02f +- %5.02f Mtex/s\n", _dX/1000/1000, _dD/1000/1000); + + _ulTexFormat = TS.ts_tfRGBA4; + _bSubImage = FALSE; + RunTest(TextureUpload, 10); + CPrintF("RGBA4 full: %6.02f +- %5.02f Mtex/s;" , _dX/1000/1000, _dD/1000/1000); + _bSubImage = TRUE; + RunTest(TextureUpload, 10); + CPrintF( " sub: %6.02f +- %5.02f Mtex/s\n", _dX/1000/1000, _dD/1000/1000); + + _ulTexFormat = TS.ts_tfRGB5; + _bSubImage = FALSE; + RunTest(TextureUpload, 10); + CPrintF("RGB5 full: %6.02f +- %5.02f Mtex/s;" , _dX/1000/1000, _dD/1000/1000); + _bSubImage = TRUE; + RunTest(TextureUpload, 10); + CPrintF( " sub: %6.02f +- %5.02f Mtex/s\n", _dX/1000/1000, _dD/1000/1000); + + CPrintF("\n--- Fill rate\n"); + _bMultiTexture = 0; + _bBlend = 0; _bDepth = 0; _bTexture = 0; + RunTest(FillRate, 10); + CPrintF("%-38s %6.02f +- %5.02f Mpix/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000); + _bBlend = 0; _bDepth = 0; _bTexture = 1; + RunTest(FillRate, 10); + CPrintF("%-38s %6.02f +- %5.02f Mpix/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000); + _bBlend = 0; _bDepth = 1; _bTexture = 1; + RunTest(FillRate, 10); + CPrintF("%-38s %6.02f +- %5.02f Mpix/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000); + _bBlend = 1; _bDepth = 1; _bTexture = 1; + RunTest(FillRate, 10); + CPrintF("%-38s %6.02f +- %5.02f Mpix/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000); + + if( _pGfx->gl_ctTextureUnits>1) { + _bMultiTexture = 1; + RunTest(FillRate, 10); + CPrintF("%-38s %6.02f +- %5.02f Mpix/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000); + } + + CPrintF("\n--- Geometry speed (%dpix tris)\n", (_pixSizeI/_ctR)*(_pixSizeI/_ctC)/2); + _bMultiTexture = 0; + _bBlend = 0; _bDepth = 1; _bTexture = 1; + RunTest(TrisTroughput, 10); + CPrintF("%-34s %6.02f +- %5.02f Mtri/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000); + _bBlend = 1; _bDepth = 1; _bTexture = 1; + RunTest(TrisTroughput, 10); + CPrintF("%-34s %6.02f +- %5.02f Mtri/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000); + + if( _pGfx->gl_ctTextureUnits>1) { + _bMultiTexture = 1; + RunTest(TrisTroughput, 10); + CPrintF("%-34s %6.02f +- %5.02f Mtri/s\n", FillRateString(), _dX/1000/1000, _dD/1000/1000); + } + + EndTris(); + EndTexture(); +} diff --git a/Sources/Engine/Graphics/Color.cpp b/Sources/Engine/Graphics/Color.cpp new file mode 100644 index 0000000..6a7f466 --- /dev/null +++ b/Sources/Engine/Graphics/Color.cpp @@ -0,0 +1,442 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + + +extern const UBYTE *pubClipByte; + + +// convert HSV components to CroTeam COLOR format +COLOR HSVToColor( UBYTE const ubH, UBYTE const ubS, UBYTE const ubV) +{ + if( ubS>1) { + SLONG xH = (SLONG)ubH *1536; // ->FIXINT/(256/6) + INDEX iHlo = xH & 0xFFFF; + SLONG slP = ((SLONG)ubV * (256- (SLONG)ubS)) >>8; + SLONG slQ = ((SLONG)ubV * (256-(((SLONG)ubS*iHlo)>>16))) >>8; + SLONG slT = ((SLONG)ubV * (256-(((SLONG)ubS*(65536-iHlo))>>16))) >>8; + switch( xH>>16) { + case 0: return RGBToColor(ubV,slT,slP); + case 1: return RGBToColor(slQ,ubV,slP); + case 2: return RGBToColor(slP,ubV,slT); + case 3: return RGBToColor(slP,slQ,ubV); + case 4: return RGBToColor(slT,slP,ubV); + case 5: return RGBToColor(ubV,slP,slQ); + default: ASSERTALWAYS("WHAT???"); return C_BLACK; + } + } else return RGBToColor(ubV,ubV,ubV); +} + + +// convert CroTeam COLOR format to HSV components +void ColorToHSV( COLOR const colSrc, UBYTE &ubH, UBYTE &ubS, UBYTE &ubV) +{ + UBYTE ubR, ubG, ubB; + ColorToRGB( colSrc, ubR,ubG,ubB); + ubH = 0; + ubS = 0; + ubV = Max( Max(ubR,ubG),ubB); + if( ubV>1) { + SLONG slD = ubV - Min( Min(ubR,ubG),ubB); + if( slD<1) return; + ubS = (slD*255) /ubV; + if( ubR==ubV) ubH = 0+ (((SLONG)ubG-ubB)*85) / (slD*2); + else if( ubG==ubV) ubH = 85+ (((SLONG)ubB-ubR)*85) / (slD*2); + else ubH = 170+ (((SLONG)ubR-ubG)*85) / (slD*2); + } +} + + + +// color checking routines + +#define GRAY_TRESHOLD 4 +#define WHITE_TRESHOLD (255-GRAY_TRESHOLD) + +BOOL IsGray( COLOR const col) +{ + UBYTE ubR,ubG,ubB; + ColorToRGB( col, ubR,ubG,ubB); + INDEX iMaxDelta = Max( Max(ubR,ubG),ubB) - Min( Min(ubR,ubG),ubB); + if( iMaxDeltaWHITE_TRESHOLD && ubG>WHITE_TRESHOLD && ubB>WHITE_TRESHOLD) return TRUE; + return FALSE; +} + +BOOL IsBigger( COLOR const col1, COLOR const col2) +{ + UBYTE ubR1,ubG1,ubB1; + UBYTE ubR2,ubG2,ubB2; + ColorToRGB( col1, ubR1,ubG1,ubB1); + ColorToRGB( col2, ubR2,ubG2,ubB2); + SLONG slGray1 = (((SLONG)ubR1+ubG1+ubB1)*21846) >>16; + SLONG slGray2 = (((SLONG)ubR2+ubG2+ubB2)*21846) >>16; + return (slGray1>slGray2); +} + + +// has color same hue and saturation (with little tolerance) ? +BOOL CompareChroma( COLOR col1, COLOR col2) +{ + // make color1 bigger + if( IsBigger(col2,col1)) Swap(col1,col2); + + // find biggest component + SLONG slR1=0, slG1=0, slB1=0; + SLONG slR2=0, slG2=0, slB2=0; + ColorToRGB( col1, (UBYTE&)slR1, (UBYTE&)slG1, (UBYTE&)slB1); + ColorToRGB( col2, (UBYTE&)slR2, (UBYTE&)slG2, (UBYTE&)slB2); + SLONG slMax1 = Max(Max(slR1,slG1),slB1); + SLONG slMax2 = Max(Max(slR2,slG2),slB2); + // trivial? + if( slMax1>16; + slB = (slR2*slB1*slDiv)>>16; + } else if( slG1==slMax1) { + slDiv = 65536 / slG1; + slR = (slG2*slR1*slDiv)>>16; + slG = slG2; + slB = (slG2*slB1*slDiv)>>16; + } else { + slDiv = 65536 / slB1; + slR = (slB2*slR1*slDiv)>>16; + slG = (slB2*slG1*slDiv)>>16; + slB = slB2; + } + + // check expected color + if( Abs(slR-slR2) > (GRAY_TRESHOLD/2)) return FALSE; + if( Abs(slG-slG2) > (GRAY_TRESHOLD/2)) return FALSE; + if( Abs(slB-slB2) > (GRAY_TRESHOLD/2)) return FALSE; + return TRUE; +} + + +// find corresponding desaturated color (it's not same as gray!) +COLOR DesaturateColor( COLOR const col) +{ + UBYTE ubR,ubG,ubB,ubA, ubMax; + ColorToRGBA( col, ubR,ubG,ubB,ubA); + ubMax = Max(Max(ubR,ubG),ubB); + return RGBAToColor( ubMax,ubMax,ubMax,ubA); +} + + +// adjust color saturation and/or hue +COLOR AdjustColor( COLOR const col, SLONG const slHueShift, SLONG const slSaturation) +{ + // nothing? + if( slHueShift==0 && slSaturation==256) return col; + // saturation? + COLOR colRes = col; + UBYTE ubA = (col&CT_AMASK)>>CT_ASHIFT; + if( slSaturation!=256) + { // calculate gray factor + UBYTE ubR,ubG,ubB; + ColorToRGB( col, ubR,ubG,ubB); + SLONG slGray = (ubR*72 + ubG*152 + ubB*32)>>8; + // saturate color components + SLONG slR = slGray + (((ubR-slGray)*slSaturation)>>8); + SLONG slG = slGray + (((ubG-slGray)*slSaturation)>>8); + SLONG slB = slGray + (((ubB-slGray)*slSaturation)>>8); + // clamp color components + colRes = RGBToColor( pubClipByte[slR], pubClipByte[slG], pubClipByte[slB]); + } + // hue? + if( slHueShift==0) return colRes|ubA; + UBYTE ubH,ubS,ubV; + ColorToHSV( colRes, ubH,ubS,ubV); + ubH += slHueShift; + return HSVAToColor( ubH,ubS,ubV,ubA); +} + + +// adjust color gamma correction +COLOR AdjustGamma( COLOR const col, FLOAT const fGamma) +{ + if( fGamma==1.0f || fGamma<0.2f) return col; + const FLOAT f1oGamma = 1.0f / fGamma; + const FLOAT f1o255 = 1.0f / 255.0f; + UBYTE ubR,ubG,ubB,ubA; + ColorToRGBA( col, ubR,ubG,ubB,ubA); + ubR = ClampUp( NormFloatToByte(pow(ubR*f1o255,f1oGamma)), 255UL); + ubG = ClampUp( NormFloatToByte(pow(ubG*f1o255,f1oGamma)), 255UL); + ubB = ClampUp( NormFloatToByte(pow(ubB*f1o255,f1oGamma)), 255UL); + return RGBAToColor( ubR,ubG,ubB,ubA); +} + + + +// color lerping functions + +void LerpColor( COLOR col0, COLOR col1, FLOAT fRatio, UBYTE &ubR, UBYTE &ubG, UBYTE &ubB) +{ + UBYTE ubR0, ubG0, ubB0; + UBYTE ubR1, ubG1, ubB1; + ColorToRGB( col0, ubR0, ubG0, ubB0); + ColorToRGB( col1, ubR1, ubG1, ubB1); + ubR = Lerp( ubR0, ubR1, fRatio); + ubG = Lerp( ubG0, ubG1, fRatio); + ubB = Lerp( ubB0, ubB1, fRatio); +} + + +COLOR LerpColor( COLOR col0, COLOR col1, FLOAT fRatio) +{ + UBYTE ubR0, ubG0, ubB0, ubA0; + UBYTE ubR1, ubG1, ubB1, ubA1; + ColorToRGBA( col0, ubR0, ubG0, ubB0, ubA0); + ColorToRGBA( col1, ubR1, ubG1, ubB1, ubA1); + ubR0 = Lerp( ubR0, ubR1, fRatio); + ubG0 = Lerp( ubG0, ubG1, fRatio); + ubB0 = Lerp( ubB0, ubB1, fRatio); + ubA0 = Lerp( ubA0, ubA1, fRatio); + return RGBAToColor( ubR0, ubG0, ubB0, ubA0); +} + + + +// fast color multiply function - RES = 1ST * 2ND /255 +COLOR MulColors( COLOR col1, COLOR col2) +{ + if( col1==0xFFFFFFFF) return col2; + if( col2==0xFFFFFFFF) return col1; + if( col1==0 || col2==0) return 0; + COLOR colRet; + __asm { + xor ebx,ebx + // red + mov eax,D [col1] + and eax,CT_RMASK + shr eax,CT_RSHIFT + mov ecx,eax + shl ecx,8 + or eax,ecx + mov edx,D [col2] + and edx,CT_RMASK + shr edx,CT_RSHIFT + mov ecx,edx + shl ecx,8 + or edx,ecx + imul eax,edx + shr eax,16+8 + shl eax,CT_RSHIFT + or ebx,eax + // green + mov eax,D [col1] + and eax,CT_GMASK + shr eax,CT_GSHIFT + mov ecx,eax + shl ecx,8 + or eax,ecx + mov edx,D [col2] + and edx,CT_GMASK + shr edx,CT_GSHIFT + mov ecx,edx + shl ecx,8 + or edx,ecx + imul eax,edx + shr eax,16+8 + shl eax,CT_GSHIFT + or ebx,eax + // blue + mov eax,D [col1] + and eax,CT_BMASK + shr eax,CT_BSHIFT + mov ecx,eax + shl ecx,8 + or eax,ecx + mov edx,D [col2] + and edx,CT_BMASK + shr edx,CT_BSHIFT + mov ecx,edx + shl ecx,8 + or edx,ecx + imul eax,edx + shr eax,16+8 + shl eax,CT_BSHIFT + or ebx,eax + // alpha + mov eax,D [col1] + and eax,CT_AMASK + shr eax,CT_ASHIFT + mov ecx,eax + shl ecx,8 + or eax,ecx + mov edx,D [col2] + and edx,CT_AMASK + shr edx,CT_ASHIFT + mov ecx,edx + shl ecx,8 + or edx,ecx + imul eax,edx + shr eax,16+8 + shl eax,CT_ASHIFT + or ebx,eax + // done + mov D [colRet],ebx + } + return colRet; +} + + +// fast color additon function - RES = clamp (1ST + 2ND) +COLOR AddColors( COLOR col1, COLOR col2) +{ + if( col1==0) return col2; + if( col2==0) return col1; + if( col1==0xFFFFFFFF || col2==0xFFFFFFFF) return 0xFFFFFFFF; + COLOR colRet; + __asm { + xor ebx,ebx + mov esi,255 + // red + mov eax,D [col1] + and eax,CT_RMASK + shr eax,CT_RSHIFT + mov edx,D [col2] + and edx,CT_RMASK + shr edx,CT_RSHIFT + add eax,edx + cmp esi,eax // clamp + sbb ecx,ecx + or eax,ecx + shl eax,CT_RSHIFT + and eax,CT_RMASK + or ebx,eax + // green + mov eax,D [col1] + and eax,CT_GMASK + shr eax,CT_GSHIFT + mov edx,D [col2] + and edx,CT_GMASK + shr edx,CT_GSHIFT + add eax,edx + cmp esi,eax // clamp + sbb ecx,ecx + or eax,ecx + shl eax,CT_GSHIFT + and eax,CT_GMASK + or ebx,eax + // blue + mov eax,D [col1] + and eax,CT_BMASK + shr eax,CT_BSHIFT + mov edx,D [col2] + and edx,CT_BMASK + shr edx,CT_BSHIFT + add eax,edx + cmp esi,eax // clamp + sbb ecx,ecx + or eax,ecx + shl eax,CT_BSHIFT + and eax,CT_BMASK + or ebx,eax + // alpha + mov eax,D [col1] + and eax,CT_AMASK + shr eax,CT_ASHIFT + mov edx,D [col2] + and edx,CT_AMASK + shr edx,CT_ASHIFT + add eax,edx + cmp esi,eax // clamp + sbb ecx,ecx + or eax,ecx + shl eax,CT_ASHIFT + and eax,CT_AMASK + or ebx,eax + // done + mov D [colRet],ebx + } + return colRet; +} + + + +// multiple conversion from OpenGL color to DirectX color +extern void abgr2argb( ULONG *pulSrc, ULONG *pulDst, INDEX ct) +{ + __asm { + mov esi,dword ptr [pulSrc] + mov edi,dword ptr [pulDst] + mov ecx,dword ptr [ct] + shr ecx,2 + jz colSkip4 +colLoop4: + push ecx + mov eax,dword ptr [esi+ 0] + mov ebx,dword ptr [esi+ 4] + mov ecx,dword ptr [esi+ 8] + mov edx,dword ptr [esi+12] + bswap eax + bswap ebx + bswap ecx + bswap edx + ror eax,8 + ror ebx,8 + ror ecx,8 + ror edx,8 + mov dword ptr [edi+ 0],eax + mov dword ptr [edi+ 4],ebx + mov dword ptr [edi+ 8],ecx + mov dword ptr [edi+12],edx + add esi,4*4 + add edi,4*4 + pop ecx + dec ecx + jnz colLoop4 +colSkip4: + test dword ptr [ct],2 + jz colSkip2 + mov eax,dword ptr [esi+0] + mov ebx,dword ptr [esi+4] + bswap eax + bswap ebx + ror eax,8 + ror ebx,8 + mov dword ptr [edi+0],eax + mov dword ptr [edi+4],ebx + add esi,4*2 + add edi,4*2 +colSkip2: + test dword ptr [ct],1 + jz colSkip1 + mov eax,dword ptr [esi] + bswap eax + ror eax,8 + mov dword ptr [edi],eax +colSkip1: + } +} diff --git a/Sources/Engine/Graphics/Color.h b/Sources/Engine/Graphics/Color.h new file mode 100644 index 0000000..9dc94b4 --- /dev/null +++ b/Sources/Engine/Graphics/Color.h @@ -0,0 +1,302 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_COLOR_H +#define SE_INCL_COLOR_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +// color definition constants (in CroTeam RGBA format) +#define C_BLACK 0x00000000UL +#define C_vdGRAY 0x1F1F1F00UL +#define C_dGRAY 0x3F3F3F00UL +#define C_mdGRAY 0x5F5F5F00UL +#define C_GRAY 0x7F7F7F00UL +#define C_mlGRAY 0x9F9F9F00UL +#define C_lGRAY 0xBFBFBF00UL +#define C_vlGRAY 0xDFDFDF00UL +#define C_WHITE 0xFFFFFF00UL + +#define C_vdRED 0x3F000000UL +#define C_dRED 0x7F000000UL +#define C_mdRED 0xBF000000UL +#define C_RED 0xFF000000UL +#define C_mlRED 0xFF3F3F00UL +#define C_lRED 0xFF7F7F00UL +#define C_vlRED 0xFFBFBF00UL + +#define C_vdGREEN 0x003F0000UL +#define C_dGREEN 0x007F0000UL +#define C_mdGREEN 0x00BF0000UL +#define C_GREEN 0x00FF0000UL +#define C_mlGREEN 0x3FFF3F00UL +#define C_lGREEN 0x7FFF7F00UL +#define C_vlGREEN 0xBFFFBF00UL + +#define C_vdBLUE 0x00003F00UL +#define C_dBLUE 0x00007F00UL +#define C_mdBLUE 0x0000BF00UL +#define C_BLUE 0x0000FF00UL +#define C_mlBLUE 0x3F3FFF00UL +#define C_lBLUE 0x7F7FFF00UL +#define C_vlBLUE 0xBFBFFF00UL + +#define C_vdCYAN 0x003F3F00UL +#define C_dCYAN 0x007F7F00UL +#define C_mdCYAN 0x00BFBF00UL +#define C_CYAN 0x00FFFF00UL +#define C_mlCYAN 0x3FFFFF00UL +#define C_lCYAN 0x7FFFFF00UL +#define C_vlCYAN 0xBFFFFF00UL + +#define C_vdMAGENTA 0x3F003F00UL +#define C_dMAGENTA 0x7F007F00UL +#define C_mdMAGENTA 0xBF00BF00UL +#define C_MAGENTA 0xFF00FF00UL +#define C_mlMAGENTA 0xFF3FFF00UL +#define C_lMAGENTA 0xFF7FFF00UL +#define C_vlMAGENTA 0xFFBFFF00UL + +#define C_vdYELLOW 0x3F3F0000UL +#define C_dYELLOW 0x7F7F0000UL +#define C_mdYELLOW 0xBFBF0000UL +#define C_YELLOW 0xFFFF0000UL +#define C_mlYELLOW 0xFFFF3F00UL +#define C_lYELLOW 0xFFFF7F00UL +#define C_vlYELLOW 0xFFFFBF00UL + +#define C_vdORANGE 0x5F1F0000UL +#define C_dORANGE 0x7F3F0000UL +#define C_mdORANGE 0x9F5F0000UL +#define C_ORANGE 0xFF7F3F00UL +#define C_mlORANGE 0xFF9F5F00UL +#define C_lORANGE 0xFFBF7F00UL +#define C_vlORANGE 0xFFFF9F00UL + +#define C_vdBROWN 0x3F1F0000UL +#define C_dBROWN 0x5F3F0F00UL +#define C_mdBROWN 0x7F5F1F00UL +#define C_BROWN 0x8C271700UL +#define C_mlBROWN 0xBF3F0F00UL +#define C_lBROWN 0xBF7F1F00UL +#define C_vlBROWN 0xBFBF3F00UL + +#define C_vdPINK 0x9A545400UL +#define C_dPINK 0xAA646400UL +#define C_mdPINK 0xBA747400UL +#define C_PINK 0xC8787800UL +#define C_mlPINK 0xD67C7C00UL +#define C_lPINK 0xE68C8C00UL +#define C_vlPINK 0xF68C8C00UL + +// CT RGBA masks and shifts +#define CT_RMASK 0xFF000000UL +#define CT_GMASK 0x00FF0000UL +#define CT_BMASK 0x0000FF00UL +#define CT_AMASK 0x000000FFUL +#define CT_RSHIFT 24 +#define CT_GSHIFT 16 +#define CT_BSHIFT 8 +#define CT_ASHIFT 0 + +// reversed (OpenGL) RGBA masks and shifts +#define CT_rRMASK 0x000000FFUL +#define CT_rGMASK 0x0000FF00UL +#define CT_rBMASK 0x00FF0000UL +#define CT_rAMASK 0xFF000000UL +#define CT_rRSHIFT 0 +#define CT_rGSHIFT 8 +#define CT_rBSHIFT 16 +#define CT_rASHIFT 24 + +// global factors for saturation and stuff +extern SLONG _slTexSaturation; +extern SLONG _slTexHueShift; +extern SLONG _slShdSaturation; +extern SLONG _slShdHueShift; + + +// COLOR FORMAT CONVERSION ROUTINES + +// convert separate R,G and B color components to CroTeam COLOR format (ULONG type) +__forceinline COLOR RGBToColor( UBYTE const ubR, UBYTE const ubG, UBYTE const ubB) { + return ((ULONG)ubR<>CT_RSHIFT; + ubG = (col&CT_GMASK)>>CT_GSHIFT; + ubB = (col&CT_BMASK)>>CT_BSHIFT; +} +// combine CroTeam COLOR format from separate R,G and B color components +__forceinline COLOR RGBAToColor( UBYTE const ubR, UBYTE const ubG, UBYTE const ubB, UBYTE const ubA) { + return ((ULONG)ubR<>CT_RSHIFT; + ubG = (col&CT_GMASK)>>CT_GSHIFT; + ubB = (col&CT_BMASK)>>CT_BSHIFT; + ubA = (col&CT_AMASK)>>CT_ASHIFT; +} + +// convert HSV components to CroTeam COLOR format +ENGINE_API extern COLOR HSVToColor( UBYTE const ubH, UBYTE const ubS, UBYTE const ubV); +// convert CroTeam COLOR format to HSV components +ENGINE_API extern void ColorToHSV( COLOR const colSrc, UBYTE &ubH, UBYTE &ubS, UBYTE &ubV); + +// convert HSVA components to CroTeam COLOR format +__forceinline COLOR HSVAToColor( UBYTE const ubH, UBYTE const ubS, UBYTE const ubV, UBYTE const ubA) { + return HSVToColor( ubH,ubS,ubV) | ((ULONG)ubA<>CT_ASHIFT; +} + +// is color gray, black or white? +ENGINE_API extern BOOL IsGray( COLOR const col); +ENGINE_API extern BOOL IsBlack( COLOR const col); +ENGINE_API extern BOOL IsWhite( COLOR const col); + +// find corresponding desaturated color (it's not same as gray!) +ENGINE_API extern COLOR DesaturateColor( COLOR const col); + +// is color1 bigger than color2 (gray comparison) +ENGINE_API extern BOOL IsBigger( COLOR const col1, COLOR const col2); +// has color same hue and saturation (with little tolerance) ? +ENGINE_API extern BOOL CompareChroma( COLOR col1, COLOR col2); + +// adjust color saturation and/or hue (hue shift in 0-255 range!) +ENGINE_API extern COLOR AdjustColor( COLOR const col, SLONG const slHueShift, SLONG const slSaturation); +ENGINE_API extern COLOR AdjustGamma( COLOR const col, FLOAT const fGamma); +// color lerping functions +ENGINE_API extern COLOR LerpColor( COLOR col0, COLOR col1, FLOAT fRatio); +ENGINE_API extern void LerpColor( COLOR col0, COLOR col1, FLOAT fRatio, UBYTE &ubR, UBYTE &ubG, UBYTE &ubB); + +// some fast color manipulation functions +ENGINE_API extern COLOR MulColors( COLOR col1, COLOR col2); // fast color multiply function - RES = 1ST * 2ND /255 +ENGINE_API extern COLOR AddColors( COLOR col1, COLOR col2); // fast color additon function - RES = clamp (1ST + 2ND) + + + +// converts colors between Croteam, OpenGL and DirectX + +__forceinline ULONG ByteSwap( ULONG ul) +{ +/* rcg10052001 Platform-wrappers. */ +#if (defined USE_PORTABLE_C) + return( ((ul << 24) ) | + ((ul << 8) & 0x00FF0000) | + ((ul >> 8) & 0x0000FF00) | + ((ul >> 24) ) ); + +#elif (defined _MSC_VER) + ULONG ulRet; + __asm { + mov eax,dword ptr [ul] + bswap eax + mov dword ptr [ulRet],eax + } + return ulRet; +#elif (defined __GNUC__) + __asm__ __volatile__ ( + "bswapl %%eax \n\t" + : "=a" (ul) + : "a" (ul) + ); + return(ul); + +#else + #error please define for your platform. +#endif +} + +__forceinline ULONG rgba2argb( COLOR col) +{ +#if (defined USE_PORTABLE_C) + return( (col << 24) | (col >> 8) ); + +#elif (defined _MSC_VER) + ULONG ulRet; + __asm { + mov eax,dword ptr [col] + ror eax,8 + mov dword ptr [ulRet],eax + } + return ulRet; + +#else + #error please define for your platform. +#endif +} + +__forceinline ULONG abgr2argb( ULONG ul) +{ +#if (defined USE_PORTABLE_C) + // this could be simplified, this is just a safe conversion from asm code + ul = ( ((ul << 24) ) | + ((ul << 8) & 0x00FF0000) | + ((ul >> 8) & 0x0000FF00) | + ((ul >> 24) ) ); + return( (ul << 24) | (ul >> 8) ); + +#elif (defined _MSC_VER) + ULONG ulRet; + __asm { + mov eax,dword ptr [ul] + bswap eax + ror eax,8 + mov dword ptr [ulRet],eax + } + return ulRet; + +#else + #error please define for your platform. +#endif +} + + +// multiple conversion from OpenGL color to DirectX color +extern void abgr2argb( ULONG *pulSrc, ULONG *pulDst, INDEX ct); + + +// fast memory copy of ULONGs +inline void CopyLongs( ULONG *pulSrc, ULONG *pulDst, INDEX ctLongs) +{ +#if (defined _MSC_VER) + __asm { + cld + mov esi,dword ptr [pulSrc] + mov edi,dword ptr [pulDst] + mov ecx,dword ptr [ctLongs] + rep movsd + } +#else + memcpy( pulDst, pulSrc, ctLongs*4); +#endif +} + + +// fast memory set of ULONGs +inline void StoreLongs( ULONG ulVal, ULONG *pulDst, INDEX ctLongs) +{ +#if (defined _MSC_VER) + __asm { + cld + mov eax,dword ptr [ulVal] + mov edi,dword ptr [pulDst] + mov ecx,dword ptr [ctLongs] + rep stosd + } +#else + for( INDEX i=0; i +#include +#include +#include + +#include +#include +#include + + +extern INDEX gap_iOptimizeDepthReads; +#ifdef SE1_D3D +extern COLOR UnpackColor_D3D( UBYTE *pd3dColor, D3DFORMAT d3dFormat, SLONG &slColorSize); +#endif // SE1_D3D + +static INDEX _iCheckIteration = 0; +static CTimerValue _tvLast[8]; // 8 is max mirror recursion + +#define KEEP_BEHIND 8 + +// info of one point for delayed depth buffer lookup +struct DepthInfo { + INDEX di_iID; // unique identifier + PIX di_pixI, di_pixJ; // last requested coordinates + FLOAT di_fOoK; // last requested depth + INDEX di_iSwapLastRequest; // index of swap when last requested + INDEX di_iMirrorLevel; // level of mirror recursion in which flare is + BOOL di_bVisible; // whether the point was visible +}; +CStaticStackArray _adiDelayed; // active delayed points +// don't ask, these are for D3D +CStaticStackArray _avtxDelayed; +CStaticStackArray _acolDelayed; + +// read depth buffer and update visibility flag of depth points +static void UpdateDepthPointsVisibility( const CDrawPort *pdp, const INDEX iMirrorLevel, + DepthInfo *pdi, const INDEX ctCount) +{ + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + ASSERT( pdp!=NULL && ctCount>0); + const CRaster *pra = pdp->dp_Raster; + + // OpenGL + if( eAPI==GAT_OGL) + { + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + FLOAT fPointOoK; + // for each stored point + for( INDEX idi=0; idira_Height-1 - di.di_pixJ; // OpenGL has Y-inversed buffer! + pglReadPixels( di.di_pixI, pixJ, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &fPointOoK); + OGL_CHECKERROR; + // it is visible if there is nothing nearer in z-buffer already + di.di_bVisible = (di.di_fOoKgl_ulFlags & GLF_FULLSCREEN; + if( bFullScreen) { + hr = _pGfx->gl_pd3dDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer); + } else { + hr = pra->ra_pvpViewPort->vp_pSwapChain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer); + } + // what, cannot get a back buffer? + if( hr!=D3D_OK) { + // to hell with it all + _sfStats.StopTimer(CStatForm::STI_GFXAPI); + return; + } + // keep format of back-buffer + pBackBuffer->GetDesc(&surfDesc); + const D3DFORMAT d3dfBack = surfDesc.Format; + + // prepare array that'll back-buffer colors from depth point locations + _acolDelayed.Push(ctCount); + // store all colors + for( idi=0; idiLockRect( &rectLocked, &rectToLock, D3DLOCK_READONLY); + if( hr!=D3D_OK) continue; // skip if lock didn't make it + // read, convert and store original color + _acolDelayed[idi] = UnpackColor_D3D( (UBYTE*)rectLocked.pBits, d3dfBack, slColSize) | CT_OPAQUE; + pBackBuffer->UnlockRect(); + } + + // prepare to draw little triangles there with slightly adjusted colors + _sfStats.StopTimer(CStatForm::STI_GFXAPI); + gfxEnableDepthTest(); + gfxDisableDepthWrite(); + gfxDisableBlend(); + gfxDisableAlphaTest(); + gfxDisableTexture(); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + // prepare array and shader + _avtxDelayed.Push(ctCount*3); + d3dSetVertexShader(D3DFVF_CTVERTEX); + + // draw one trianle around each depth point + INDEX ctVertex = 0; + for( idi=0; ididp_MinI; // convert raster loc to drawport loc + const PIX pixJ = di.di_pixJ - pdp->dp_MinJ; + // batch it and advance to next triangle + CTVERTEX &vtx0 = _avtxDelayed[ctVertex++]; + CTVERTEX &vtx1 = _avtxDelayed[ctVertex++]; + CTVERTEX &vtx2 = _avtxDelayed[ctVertex++]; + vtx0.fX=pixI; vtx0.fY=pixJ-2; vtx0.fZ=di.di_fOoK; vtx0.ulColor=d3dCol; vtx0.fU=vtx0.fV=0; + vtx1.fX=pixI-2; vtx1.fY=pixJ+2; vtx1.fZ=di.di_fOoK; vtx1.ulColor=d3dCol; vtx1.fU=vtx0.fV=0; + vtx2.fX=pixI+2; vtx2.fY=pixJ; vtx2.fZ=di.di_fOoK; vtx2.ulColor=d3dCol; vtx2.fU=vtx0.fV=0; + } + // draw a bunch + hr = _pGfx->gl_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, ctVertex/3, &_avtxDelayed[0], sizeof(CTVERTEX)); + D3D_CHECKERROR(hr); + + // readout colors again and compare to old ones + for( idi=0; idiLockRect( &rectLocked, &rectToLock, D3DLOCK_READONLY); + if( hr!=D3D_OK) continue; // skip if lock didn't make it + // read new color + const COLOR colNew = UnpackColor_D3D( (UBYTE*)rectLocked.pBits, d3dfBack, slColSize) | CT_OPAQUE; + pBackBuffer->UnlockRect(); + // if we managed to write adjusted color, point is visible! + di.di_bVisible = (col!=colNew); + } + // phew, done! :) + D3DRELEASE( pBackBuffer, TRUE); + _acolDelayed.PopAll(); + _avtxDelayed.PopAll(); + _sfStats.StopTimer(CStatForm::STI_GFXAPI); + return; + } +#endif // SE1_D3D +} + + + +// check point against depth buffer +extern BOOL CheckDepthPoint( const CDrawPort *pdp, PIX pixI, PIX pixJ, FLOAT fOoK, INDEX iID, INDEX iMirrorLevel/*=0*/) +{ + // no raster? + const CRaster *pra = pdp->dp_Raster; + if( pra==NULL) return FALSE; + // almoust out of raster? + pixI += pdp->dp_MinI; + pixJ += pdp->dp_MinJ; + if( pixI<1 || pixJ<1 || pixI>pra->ra_Width-2 || pixJ>pra->ra_Height-2) return FALSE; + + // if shouldn't delay + if( gap_iOptimizeDepthReads==0) { + // just check immediately + DepthInfo di = { iID, pixI, pixJ, fOoK, _iCheckIteration, iMirrorLevel, FALSE }; + UpdateDepthPointsVisibility( pdp, iMirrorLevel, &di, 1); + return di.di_bVisible; + } + + // for each stored point + for( INDEX idi=0; idi<_adiDelayed.Count(); idi++) { + DepthInfo &di = _adiDelayed[idi]; + // if same id + if( di.di_iID == iID) { + // remember parameters + di.di_pixI = pixI; + di.di_pixJ = pixJ; + di.di_fOoK = fOoK; + di.di_iSwapLastRequest = _iCheckIteration; + // return visibility + return di.di_bVisible; + } + } + // if not found... + + // create new one + DepthInfo &di = _adiDelayed.Push(); + // remember parameters + di.di_iID = iID; + di.di_pixI = pixI; + di.di_pixJ = pixJ; + di.di_fOoK = fOoK; + di.di_iSwapLastRequest = _iCheckIteration; + di.di_iMirrorLevel = iMirrorLevel; + di.di_bVisible = FALSE; + // not visible by default + return FALSE; +} + + +// check all delayed depth points +extern void CheckDelayedDepthPoints( const CDrawPort *pdp, INDEX iMirrorLevel/*=0*/) +{ + // skip if not delayed or mirror level is to high + gap_iOptimizeDepthReads = Clamp( gap_iOptimizeDepthReads, 0L, 2L); + if( gap_iOptimizeDepthReads==0 || iMirrorLevel>7) return; + ASSERT( pdp!=NULL && iMirrorLevel>=0); + + // check only if time lapse allows + const CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + const TIME tmDelta = (tvNow-_tvLast[iMirrorLevel]).GetSeconds(); + ASSERT( tmDelta>=0); + if( gap_iOptimizeDepthReads==2 && tmDelta<0.1f) return; + + // prepare + _tvLast[iMirrorLevel] = tvNow; + INDEX ctPoints = _adiDelayed.Count(); + if( ctPoints==0) return; // done if no points in queue + + // for each point + INDEX iPoint = 0; + while( iPoint1.0f) return; + + // check and upadete visibility of what has left + ASSERT( ctPoints == _adiDelayed.Count()); + if( ctPoints>0) UpdateDepthPointsVisibility( pdp, iMirrorLevel, &_adiDelayed[0], ctPoints); + // mark checking + _iCheckIteration++; +} + diff --git a/Sources/Engine/Graphics/DisplayMode.cpp b/Sources/Engine/Graphics/DisplayMode.cpp new file mode 100644 index 0000000..f453ae2 --- /dev/null +++ b/Sources/Engine/Graphics/DisplayMode.cpp @@ -0,0 +1,51 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +/* + * Default constructor. + */ +CDisplayMode::CDisplayMode(void) +{ + // clear all members + dm_pixSizeI = 0; + dm_pixSizeJ = 0; + dm_ddDepth = DD_DEFAULT; +} + + +// get depth string +CTString CDisplayMode::DepthString(void) const +{ + switch (dm_ddDepth) { + case DD_NODEPTH: return "none"; break; + case DD_16BIT: return "16"; break; + case DD_32BIT: return "32"; break; + case DD_DEFAULT: return TRANS("desktop"); break; + default: ASSERT(FALSE); return TRANS("unknown"); break; + } +} + + +// check if mode is dualhead +BOOL CDisplayMode::IsDualHead(void) +{ + // if size is 8:3 it is dual head + return dm_pixSizeI*3==dm_pixSizeJ*8; +} + + +// check if mode is widescreen +BOOL CDisplayMode::IsWideScreen(void) +{ + // only this one supported as widescreen + return dm_pixSizeI==856 && dm_pixSizeJ==480; +} +// check if mode is fullscreen +BOOL CDisplayMode::IsFullScreen(void) +{ + return dm_pixSizeI!=0 && dm_pixSizeJ!=0; +} diff --git a/Sources/Engine/Graphics/DisplayMode.h b/Sources/Engine/Graphics/DisplayMode.h new file mode 100644 index 0000000..e0c8004 --- /dev/null +++ b/Sources/Engine/Graphics/DisplayMode.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_DISPLAYMODE_H +#define SE_INCL_DISPLAYMODE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +// display mode bit-depth +enum DisplayDepth +{ + DD_NODEPTH = -1, + DD_DEFAULT = 0, + DD_16BIT = 1, + DD_32BIT = 2, + DD_24BIT = 3, // for z-buffer +}; + +/* + * Structure that holds display mode description + */ + +class ENGINE_API CDisplayMode { +public: + PIX dm_pixSizeI; // size of screen in pixels + PIX dm_pixSizeJ; + enum DisplayDepth dm_ddDepth; // bits per pixel for color + + /* Default constructor. */ + CDisplayMode(void); + + // get depth string + CTString DepthString(void) const; + // check if mode is dualhead + BOOL IsDualHead(void); + // check if mode is widescreen + BOOL IsWideScreen(void); + // check if mode is fullscreen + BOOL IsFullScreen(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/DrawPort.cpp b/Sources/Engine/Graphics/DrawPort.cpp new file mode 100644 index 0000000..3ec4e57 --- /dev/null +++ b/Sources/Engine/Graphics/DrawPort.cpp @@ -0,0 +1,1758 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +extern INDEX gfx_bDecoratedText; +extern INDEX ogl_iFinish; +extern INDEX d3d_iFinish; + + +// RECT HANDLING ROUTINES + + +static BOOL ClipToDrawPort( const CDrawPort *pdp, PIX &pixI, PIX &pixJ, PIX &pixW, PIX &pixH) +{ + if( pixI < 0) { pixW += pixI; pixI = 0; } + else if( pixI >= pdp->dp_Width) return FALSE; + + if( pixJ < 0) { pixH += pixJ; pixJ = 0; } + else if( pixJ >= pdp->dp_Height) return FALSE; + + if( pixW<1 || pixH<1) return FALSE; + + if( (pixI+pixW) > pdp->dp_Width) pixW = pdp->dp_Width - pixI; + if( (pixJ+pixH) > pdp->dp_Height) pixH = pdp->dp_Height - pixJ; + + ASSERT( pixI>=0 && pixIdp_Width); + ASSERT( pixJ>=0 && pixJdp_Height); + ASSERT( pixW>0 && pixH>0); + return TRUE; +} + + +// set scissor (clipping) to window inside drawport +static void SetScissor( const CDrawPort *pdp, PIX pixI, PIX pixJ, PIX pixW, PIX pixH) +{ + ASSERT( pixI>=0 && pixIdp_Width); + ASSERT( pixJ>=0 && pixJdp_Height); + ASSERT( pixW>0 && pixH>0); + + const PIX pixInvMinJ = pdp->dp_Raster->ra_Height - (pdp->dp_MinJ+pixJ+pixH); + pglScissor( pdp->dp_MinI+pixI, pixInvMinJ, pixW, pixH); + ASSERT( pglIsEnabled(GL_SCISSOR_TEST)); + OGL_CHECKERROR; +} + + +// reset scissor (clipping) to whole drawport +static void ResetScissor( const CDrawPort *pdp) +{ + const PIX pixMinSI = pdp->dp_ScissorMinI; + const PIX pixMaxSI = pdp->dp_ScissorMaxI; + const PIX pixMinSJ = pdp->dp_Raster->ra_Height-1 - pdp->dp_ScissorMaxJ; + const PIX pixMaxSJ = pdp->dp_Raster->ra_Height-1 - pdp->dp_ScissorMinJ; + + pglScissor( pixMinSI, pixMinSJ, pixMaxSI-pixMinSI+1, pixMaxSJ-pixMinSJ+1); + ASSERT( pglIsEnabled(GL_SCISSOR_TEST)); + OGL_CHECKERROR; +} + + +// DRAWPORT ROUTINES + +// set cloned drawport dimensions +void CDrawPort::InitCloned( CDrawPort *pdpBase, DOUBLE rMinI,DOUBLE rMinJ, DOUBLE rSizeI,DOUBLE rSizeJ) +{ + // remember the raster structures + dp_Raster = pdpBase->dp_Raster; + // set relative dimensions to make it contain the whole raster + dp_MinIOverRasterSizeI = rMinI * pdpBase->dp_SizeIOverRasterSizeI + +pdpBase->dp_MinIOverRasterSizeI; + dp_MinJOverRasterSizeJ = rMinJ * pdpBase->dp_SizeJOverRasterSizeJ + +pdpBase->dp_MinJOverRasterSizeJ; + dp_SizeIOverRasterSizeI = rSizeI * pdpBase->dp_SizeIOverRasterSizeI; + dp_SizeJOverRasterSizeJ = rSizeJ * pdpBase->dp_SizeJOverRasterSizeJ; + // calculate pixel dimensions from relative dimensions + RecalculateDimensions(); + // clip scissor to origin drawport + dp_ScissorMinI = Max( dp_MinI, pdpBase->dp_MinI); + dp_ScissorMinJ = Max( dp_MinJ, pdpBase->dp_MinJ); + dp_ScissorMaxI = Min( dp_MaxI, pdpBase->dp_MaxI); + dp_ScissorMaxJ = Min( dp_MaxJ, pdpBase->dp_MaxJ); + if( dp_ScissorMinI>dp_ScissorMaxI) dp_ScissorMinI = dp_ScissorMaxI = 0; + if( dp_ScissorMinJ>dp_ScissorMaxJ) dp_ScissorMinJ = dp_ScissorMaxJ = 0; + // clone some vars + dp_FontData = pdpBase->dp_FontData; + dp_pixTextCharSpacing = pdpBase->dp_pixTextCharSpacing; + dp_pixTextLineSpacing = pdpBase->dp_pixTextLineSpacing; + dp_fTextScaling = pdpBase->dp_fTextScaling; + dp_fTextAspect = pdpBase->dp_fTextAspect; + dp_iTextMode = pdpBase->dp_iTextMode; + dp_fWideAdjustment = pdpBase->dp_fWideAdjustment; + dp_bRenderingOverlay = pdpBase->dp_bRenderingOverlay; + // reset rest of vars + dp_ulBlendingRA = 0; + dp_ulBlendingGA = 0; + dp_ulBlendingBA = 0; + dp_ulBlendingA = 0; +} + +/* Create a drawport for full raster. */ +CDrawPort::CDrawPort( CRaster *praBase) +{ + // remember the raster structures + dp_Raster = praBase; + dp_fWideAdjustment = 1.0f; + dp_bRenderingOverlay = FALSE; + // set relative dimensions to make it contain the whole raster + dp_MinIOverRasterSizeI = 0.0; + dp_MinJOverRasterSizeJ = 0.0; + dp_SizeIOverRasterSizeI = 1.0; + dp_SizeJOverRasterSizeJ = 1.0; + // clear unknown values + dp_FontData = NULL; + dp_pixTextCharSpacing = 1; + dp_pixTextLineSpacing = 0; + dp_fTextScaling = 1.0f; + dp_fTextAspect = 1.0f; + dp_iTextMode = 1; + dp_ulBlendingRA = 0; + dp_ulBlendingGA = 0; + dp_ulBlendingBA = 0; + dp_ulBlendingA = 0; +} + +/* Clone a drawport */ +CDrawPort::CDrawPort( CDrawPort *pdpBase, + DOUBLE rMinI,DOUBLE rMinJ, DOUBLE rSizeI,DOUBLE rSizeJ) +{ + InitCloned( pdpBase, rMinI,rMinJ, rSizeI,rSizeJ); +} + +CDrawPort::CDrawPort( CDrawPort *pdpBase, const PIXaabbox2D &box) +{ + // force dimensions + dp_MinI = box.Min()(1) +pdpBase->dp_MinI; + dp_MinJ = box.Min()(2) +pdpBase->dp_MinJ; + dp_Width = box.Size()(1); + dp_Height = box.Size()(2); + dp_MaxI = dp_MinI+dp_Width -1; + dp_MaxJ = dp_MinJ+dp_Height -1; + // clip scissor to origin drawport + dp_ScissorMinI = Max( dp_MinI, pdpBase->dp_MinI); + dp_ScissorMinJ = Max( dp_MinJ, pdpBase->dp_MinJ); + dp_ScissorMaxI = Min( dp_MaxI, pdpBase->dp_MaxI); + dp_ScissorMaxJ = Min( dp_MaxJ, pdpBase->dp_MaxJ); + if( dp_ScissorMinI>dp_ScissorMaxI) dp_ScissorMinI = dp_ScissorMaxI = 0; + if( dp_ScissorMinJ>dp_ScissorMaxJ) dp_ScissorMinJ = dp_ScissorMaxJ = 0; + // remember the raster structures + dp_Raster = pdpBase->dp_Raster; + // set relative dimensions to make it contain the whole raster + dp_MinIOverRasterSizeI = (DOUBLE)dp_MinI / dp_Raster->ra_Width; + dp_MinJOverRasterSizeJ = (DOUBLE)dp_MinJ / dp_Raster->ra_Height; + dp_SizeIOverRasterSizeI = (DOUBLE)dp_Width / dp_Raster->ra_Width; + dp_SizeJOverRasterSizeJ = (DOUBLE)dp_Height / dp_Raster->ra_Height; + // clone some vars + dp_FontData = pdpBase->dp_FontData; + dp_pixTextCharSpacing = pdpBase->dp_pixTextCharSpacing; + dp_pixTextLineSpacing = pdpBase->dp_pixTextLineSpacing; + dp_fTextScaling = pdpBase->dp_fTextScaling; + dp_fTextAspect = pdpBase->dp_fTextAspect; + dp_iTextMode = pdpBase->dp_iTextMode; + dp_fWideAdjustment = pdpBase->dp_fWideAdjustment; + dp_bRenderingOverlay = pdpBase->dp_bRenderingOverlay; + // reset rest of vars + dp_ulBlendingRA = 0; + dp_ulBlendingGA = 0; + dp_ulBlendingBA = 0; + dp_ulBlendingA = 0; +} + + + +// check if a drawport is dualhead +BOOL CDrawPort::IsDualHead(void) +{ + return GetWidth()*3 == GetHeight()*8; +} + + +// check if a drawport is already wide screen +BOOL CDrawPort::IsWideScreen(void) +{ + return GetWidth()*9 == GetHeight()*16; +} + + +// returns unique drawports number +ULONG CDrawPort::GetID(void) +{ + ULONG ulCRC; + CRC_Start( ulCRC); + CRC_AddLONG( ulCRC, (ULONG)dp_Raster); + CRC_AddLONG( ulCRC, (ULONG)dp_MinI); + CRC_AddLONG( ulCRC, (ULONG)dp_MinJ); + CRC_AddLONG( ulCRC, (ULONG)dp_MaxI); + CRC_AddLONG( ulCRC, (ULONG)dp_MaxJ); + CRC_Finish( ulCRC); + return ulCRC; +} + + +// dualhead cloning +CDrawPort::CDrawPort( CDrawPort *pdpBase, BOOL bLeft) +{ + // if it is not a dualhead drawport + if (!pdpBase->IsDualHead()) { + // always use entire drawport + InitCloned(pdpBase, 0,0, 1,1); + // if dualhead is on + } else { + // use left or right + if (bLeft) { + InitCloned(pdpBase, 0,0, 0.5,1); + } else { + InitCloned(pdpBase, 0.5,0, 0.5,1); + } + } +} + + +// wide-screen cloning +void CDrawPort::MakeWideScreen(CDrawPort *pdp) +{ + // already wide? + if( IsWideScreen()) { + pdp->InitCloned( this, 0,0, 1,1); + return; + } + // make wide! + else { + // get size + const PIX pixSizeI = GetWidth(); + const PIX pixSizeJ = GetHeight(); + // make horiz width + PIX pixSizeJW = pixSizeI*9/16; + // if already too wide + if (pixSizeJW>pixSizeJ-10) { + // no wide screen + pdp->InitCloned( this, 0,0, 1,1); + return; + } + // clear upper and lower blanks + const PIX pixJ0 = (pixSizeJ-pixSizeJW)/2; + if( Lock()) { + Fill(0, 0, pixSizeI, pixJ0, C_BLACK|CT_OPAQUE); + Fill(0, pixJ0+pixSizeJW, pixSizeI, pixJ0, C_BLACK|CT_OPAQUE); + Unlock(); + } + // init + pdp->InitCloned( this, 0, FLOAT(pixJ0)/pixSizeJ, 1, FLOAT(pixSizeJW)/pixSizeJ); + pdp->dp_fWideAdjustment = 9.0f / 12.0f; + } +} + + +/***** + * Recalculate pixel dimensions from relative dimensions and raster size. + */ + +void CDrawPort::RecalculateDimensions(void) +{ + const PIX pixRasterSizeI = dp_Raster->ra_Width; + const PIX pixRasterSizeJ = dp_Raster->ra_Height; + dp_Width = (PIX)(dp_SizeIOverRasterSizeI*pixRasterSizeI); + dp_Height = (PIX)(dp_SizeJOverRasterSizeJ*pixRasterSizeJ); + dp_ScissorMinI = dp_MinI = (PIX)(dp_MinIOverRasterSizeI*pixRasterSizeI); + dp_ScissorMinJ = dp_MinJ = (PIX)(dp_MinJOverRasterSizeJ*pixRasterSizeJ); + dp_ScissorMaxI = dp_MaxI = dp_MinI+dp_Width -1; + dp_ScissorMaxJ = dp_MaxJ = dp_MinJ+dp_Height -1; +} + + +// set orthogonal projection +void CDrawPort::SetOrtho(void) const +{ + // finish all pending render-operations (if required) + ogl_iFinish = Clamp( ogl_iFinish, 0L, 3L); + d3d_iFinish = Clamp( d3d_iFinish, 0L, 3L); + if( (ogl_iFinish==3 && _pGfx->gl_eCurrentAPI==GAT_OGL) +#ifdef SE1_D3D + || (d3d_iFinish==3 && _pGfx->gl_eCurrentAPI==GAT_D3D) +#endif // SE1_D3D + ) gfxFinish(); + + // prepare ortho dimensions + const PIX pixMinI = dp_MinI; + const PIX pixMinSI = dp_ScissorMinI; + const PIX pixMaxSI = dp_ScissorMaxI; + const PIX pixMaxJ = dp_Raster->ra_Height -1 - dp_MinJ; + const PIX pixMinSJ = dp_Raster->ra_Height -1 - dp_ScissorMaxJ; + const PIX pixMaxSJ = dp_Raster->ra_Height -1 - dp_ScissorMinJ; + + // init matrices (D3D needs sub-pixel adjustment) + gfxSetOrtho( pixMinSI-pixMinI, pixMaxSI-pixMinI+1, pixMaxJ-pixMaxSJ, pixMaxJ-pixMinSJ+1, 0.0f, -1.0f, TRUE); + gfxDepthRange(0,1); + gfxSetViewMatrix(NULL); + // disable face culling, custom clip plane and truform + gfxCullFace(GFX_NONE); + gfxDisableClipPlane(); + gfxDisableTruform(); +} + + +// set given projection +void CDrawPort::SetProjection(CAnyProjection3D &apr) const +{ + // finish all pending render-operations (if required) + ogl_iFinish = Clamp( ogl_iFinish, 0L, 3L); + d3d_iFinish = Clamp( d3d_iFinish, 0L, 3L); + if( (ogl_iFinish==3 && _pGfx->gl_eCurrentAPI==GAT_OGL) +#ifdef SE1_D3D + || (d3d_iFinish==3 && _pGfx->gl_eCurrentAPI==GAT_D3D) +#endif // SE1_D3D + ) gfxFinish(); + + // if isometric projection + if( apr.IsIsometric()) { + CIsometricProjection3D &ipr = (CIsometricProjection3D&)*apr; + const FLOAT2D vMin = ipr.pr_ScreenBBox.Min()-ipr.pr_ScreenCenter; + const FLOAT2D vMax = ipr.pr_ScreenBBox.Max()-ipr.pr_ScreenCenter; + const FLOAT fFactor = 1.0f / (ipr.ipr_ZoomFactor*ipr.pr_fViewStretch); + const FLOAT fNear = ipr.pr_NearClipDistance; + const FLOAT fLeft = +vMin(1) *fFactor; + const FLOAT fRight = +vMax(1) *fFactor; + const FLOAT fTop = -vMin(2) *fFactor; + const FLOAT fBottom = -vMax(2) *fFactor; + // if far clip plane is not specified use maximum expected dimension of the world + FLOAT fFar = ipr.pr_FarClipDistance; + if( fFar<0) fFar = 1E5f; // max size 32768, 3D (sqrt(3)), rounded up + gfxSetOrtho( fLeft, fRight, fTop, fBottom, fNear, fFar, FALSE); + } + // if perspective projection + else { + ASSERT( apr.IsPerspective()); + CPerspectiveProjection3D &ppr = (CPerspectiveProjection3D&)*apr; + const FLOAT fNear = ppr.pr_NearClipDistance; + const FLOAT fLeft = ppr.pr_plClipL(3) / ppr.pr_plClipL(1) *fNear; + const FLOAT fRight = ppr.pr_plClipR(3) / ppr.pr_plClipR(1) *fNear; + const FLOAT fTop = ppr.pr_plClipU(3) / ppr.pr_plClipU(2) *fNear; + const FLOAT fBottom = ppr.pr_plClipD(3) / ppr.pr_plClipD(2) *fNear; + // if far clip plane is not specified use maximum expected dimension of the world + FLOAT fFar = ppr.pr_FarClipDistance; + if( fFar<0) fFar = 1E5f; // max size 32768, 3D (sqrt(3)), rounded up + gfxSetFrustum( fLeft, fRight, fTop, fBottom, fNear, fFar); + } + + // set some rendering params + gfxDepthRange( apr->pr_fDepthBufferNear, apr->pr_fDepthBufferFar); + gfxCullFace(GFX_BACK); + gfxSetViewMatrix(NULL); + gfxDisableTruform(); + + // if projection is mirrored/warped and mirroring is allowed + if( apr->pr_bMirror || apr->pr_bWarp) { + // set custom clip plane 0 to mirror plane + gfxEnableClipPlane(); + DOUBLE adViewPlane[4]; + adViewPlane[0] = +apr->pr_plMirrorView(1); + adViewPlane[1] = +apr->pr_plMirrorView(2); + adViewPlane[2] = +apr->pr_plMirrorView(3); + adViewPlane[3] = -apr->pr_plMirrorView.Distance(); + gfxClipPlane(adViewPlane); // NOTE: view clip plane is multiplied by inverse modelview matrix at time when specified + } + // if projection is not mirrored + else { + // just disable custom clip plane 0 + gfxDisableClipPlane(); + } +} + + + +// implementation for some drawport routines that uses raster class + +void CDrawPort::Unlock(void) +{ + dp_Raster->Unlock(); + _pGfx->UnlockDrawPort(this); +} + + +BOOL CDrawPort::Lock(void) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_LOCKDRAWPORT); + BOOL bRasterLocked = dp_Raster->Lock(); + if( bRasterLocked) { + // try to lock drawport with driver + BOOL bDrawportLocked = _pGfx->LockDrawPort(this); + if( !bDrawportLocked) { + dp_Raster->Unlock(); + bRasterLocked = FALSE; + } + } // done + _pfGfxProfile.StopTimer( CGfxProfile::PTI_LOCKDRAWPORT); + return bRasterLocked; +} + + + +// DRAWING ROUTINES ------------------------------------- + + + +// draw one point +void CDrawPort::DrawPoint( PIX pixI, PIX pixJ, COLOR col, PIX pixRadius/*=1*/) const +{ + // check API and radius + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_D3D || eAPI==GAT_NONE); +#else // SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_NONE); +#endif // SE1_D3D + ASSERT( pixRadius>=0); + if( pixRadius==0) return; // do nothing if radius is 0 + + // setup rendering mode + gfxDisableTexture(); + gfxDisableDepthTest(); + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + + // set point color/alpha and radius + col = AdjustColor( col, _slTexHueShift, _slTexSaturation); + const FLOAT fR = pixRadius; + + // OpenGL + if( eAPI==GAT_OGL) { + const FLOAT fI = pixI+0.5f; + const FLOAT fJ = pixJ+0.5f; + glCOLOR(col); + pglPointSize(fR); + pglBegin(GL_POINTS); + pglVertex2f(fI,fJ); + pglEnd(); + OGL_CHECKERROR; + } // Direct3D +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) { + HRESULT hr; + const FLOAT fI = pixI+0.75f; + const FLOAT fJ = pixJ+0.75f; + const ULONG d3dColor = rgba2argb(col); + CTVERTEX avtx = {fI,fJ,0, d3dColor, 0,0}; + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_POINTSIZE, *((DWORD*)&fR)); + D3D_CHECKERROR(hr); + // set vertex shader and draw + d3dSetVertexShader(D3DFVF_CTVERTEX); + hr = _pGfx->gl_pd3dDevice->DrawPrimitiveUP( D3DPT_POINTLIST, 1, &avtx, sizeof(CTVERTEX)); + D3D_CHECKERROR(hr); + } +#endif // SE1_D3D +} + + +// draw one point in 3D +void CDrawPort::DrawPoint3D( FLOAT3D v, COLOR col, FLOAT fRadius/*=1.0f*/) const +{ + // check API and radius + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + ASSERT( fRadius>=0); + if( fRadius==0) return; // do nothing if radius is 0 + + // setup rendering mode + gfxDisableTexture(); + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + + // set point color/alpha + col = AdjustColor( col, _slTexHueShift, _slTexSaturation); + + // OpenGL + if( eAPI==GAT_OGL) { + glCOLOR(col); + pglPointSize(fRadius); + pglBegin(GL_POINTS); + pglVertex3f( v(1),v(2),v(3)); + pglEnd(); + OGL_CHECKERROR; + } // Direct3D +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) { + HRESULT hr; + const ULONG d3dColor = rgba2argb(col); + CTVERTEX avtx = {v(1),v(2),v(3), d3dColor, 0,0}; + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_POINTSIZE, *((DWORD*)&fRadius)); + D3D_CHECKERROR(hr); + // set vertex shader and draw + d3dSetVertexShader(D3DFVF_CTVERTEX); + hr = _pGfx->gl_pd3dDevice->DrawPrimitiveUP( D3DPT_POINTLIST, 1, &avtx, sizeof(CTVERTEX)); + D3D_CHECKERROR(hr); + } +#endif // SE1_D3D +} + + + +// draw one line +void CDrawPort::DrawLine( PIX pixI0, PIX pixJ0, PIX pixI1, PIX pixJ1, COLOR col, ULONG typ/*=_FULL*/) const +{ + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + // setup rendering mode + gfxDisableDepthTest(); + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + + FLOAT fD; + INDEX iTexFilter, iTexAnisotropy; + if( typ==_FULL_) { + // no pattern - just disable texturing + gfxDisableTexture(); + fD = 0; + } else { + // revert to simple point-sample filtering without mipmaps + INDEX iNewFilter=10, iNewAnisotropy=1; + gfxGetTextureFiltering( iTexFilter, iTexAnisotropy); + gfxSetTextureFiltering( iNewFilter, iNewAnisotropy); + // prepare line pattern and mapping + extern void gfxSetPattern( ULONG ulPattern); + gfxSetPattern(typ); + fD = Max( Abs(pixI0-pixI1), Abs(pixJ0-pixJ1)) /32.0f; + } + + // set line color/alpha and go go go + col = AdjustColor( col, _slTexHueShift, _slTexSaturation); + // OpenGL + if( eAPI==GAT_OGL) { + const FLOAT fI0 = pixI0+0.5f; const FLOAT fJ0 = pixJ0+0.5f; + const FLOAT fI1 = pixI1+0.5f; const FLOAT fJ1 = pixJ1+0.5f; + glCOLOR(col); + pglBegin( GL_LINES); + pglTexCoord2f( 0,0); pglVertex2f(fI0,fJ0); + pglTexCoord2f(fD,0); pglVertex2f(fI1,fJ1); + pglEnd(); + OGL_CHECKERROR; + } // Direct3D +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) { + HRESULT hr; + const FLOAT fI0 = pixI0+0.75f; const FLOAT fJ0 = pixJ0+0.75f; + const FLOAT fI1 = pixI1+0.75f; const FLOAT fJ1 = pixJ1+0.75f; + const ULONG d3dColor = rgba2argb(col); + CTVERTEX avtxLine[2] = { + {fI0,fJ0,0, d3dColor, 0,0}, + {fI1,fJ1,0, d3dColor, fD,0} }; + // set vertex shader and draw + d3dSetVertexShader(D3DFVF_CTVERTEX); + hr = _pGfx->gl_pd3dDevice->DrawPrimitiveUP( D3DPT_LINELIST, 1, avtxLine, sizeof(CTVERTEX)); + D3D_CHECKERROR(hr); + } +#endif // SE1_D3D + // revert to old filtering + if( typ!=_FULL_) gfxSetTextureFiltering( iTexFilter, iTexAnisotropy); +} + + + +// draw one line in 3D +void CDrawPort::DrawLine3D( FLOAT3D v0, FLOAT3D v1, COLOR col) const +{ + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + // setup rendering mode + gfxDisableTexture(); + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + + // set line color/alpha and go go go + col = AdjustColor( col, _slTexHueShift, _slTexSaturation); + // OpenGL + if( eAPI==GAT_OGL) { + glCOLOR(col); + pglBegin( GL_LINES); + pglVertex3f( v0(1),v0(2),v0(3)); + pglVertex3f( v1(1),v1(2),v1(3)); + pglEnd(); + OGL_CHECKERROR; + } // Direct3D +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) { + HRESULT hr; + const ULONG d3dColor = rgba2argb(col); + CTVERTEX avtxLine[2] = { + {v0(1),v0(2),v0(3), d3dColor, 0,0}, + {v1(1),v1(2),v1(3), d3dColor, 0,0} }; + // set vertex shader and draw + d3dSetVertexShader(D3DFVF_CTVERTEX); + hr = _pGfx->gl_pd3dDevice->DrawPrimitiveUP( D3DPT_LINELIST, 1, avtxLine, sizeof(CTVERTEX)); + D3D_CHECKERROR(hr); + } +#endif // SE1_D3D +} + + + +// draw border +void CDrawPort::DrawBorder( PIX pixI, PIX pixJ, PIX pixWidth, PIX pixHeight, COLOR col, ULONG typ/*=_FULL_*/) const +{ + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + // setup rendering mode + gfxDisableDepthTest(); + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + + // for non-full lines, must have + FLOAT fD; + INDEX iTexFilter, iTexAnisotropy; + if( typ==_FULL_) { + // no pattern - just disable texturing + gfxDisableTexture(); + fD = 0; + } else { + // revert to simple point-sample filtering without mipmaps + INDEX iNewFilter=10, iNewAnisotropy=1; + gfxGetTextureFiltering( iTexFilter, iTexAnisotropy); + gfxSetTextureFiltering( iNewFilter, iNewAnisotropy); + // prepare line pattern + extern void gfxSetPattern( ULONG ulPattern); + gfxSetPattern(typ); + fD = Max( pixWidth, pixHeight) /32.0f; + } + + // set line color/alpha and go go go + col = AdjustColor( col, _slTexHueShift, _slTexSaturation); + const FLOAT fI0 = pixI+0.5f; + const FLOAT fJ0 = pixJ+0.5f; + const FLOAT fI1 = pixI-0.5f +pixWidth; + const FLOAT fJ1 = pixJ-0.5f +pixHeight; + + // OpenGL + if( eAPI==GAT_OGL) { + glCOLOR(col); + pglBegin( GL_LINES); + pglTexCoord2f(0,0); pglVertex2f(fI0,fJ0); pglTexCoord2f(fD,0); pglVertex2f(fI1, fJ0); // up + pglTexCoord2f(0,0); pglVertex2f(fI1,fJ0); pglTexCoord2f(fD,0); pglVertex2f(fI1, fJ1); // right + pglTexCoord2f(0,0); pglVertex2f(fI0,fJ1); pglTexCoord2f(fD,0); pglVertex2f(fI1+1,fJ1); // down + pglTexCoord2f(0,0); pglVertex2f(fI0,fJ0+1); pglTexCoord2f(fD,0); pglVertex2f(fI0, fJ1); // left + pglEnd(); + OGL_CHECKERROR; + } + // Direct3D +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) { + HRESULT hr; + const ULONG d3dColor = rgba2argb(col); + CTVERTEX avtxLines[8] = { // setup lines + {fI0,fJ0, 0, d3dColor, 0,0}, {fI1, fJ0,0, d3dColor, fD,0}, // up + {fI1,fJ0, 0, d3dColor, 0,0}, {fI1, fJ1,0, d3dColor, fD,0}, // right + {fI0,fJ1, 0, d3dColor, 0,0}, {fI1+1,fJ1,0, d3dColor, fD,0}, // down + {fI0,fJ0+1,0, d3dColor, 0,0}, {fI0, fJ1,0, d3dColor, fD,0} }; // left + // set vertex shader and draw + d3dSetVertexShader(D3DFVF_CTVERTEX); + hr = _pGfx->gl_pd3dDevice->DrawPrimitiveUP( D3DPT_LINELIST, 4, avtxLines, sizeof(CTVERTEX)); + D3D_CHECKERROR(hr); + } +#endif // SE1_D3D + // revert to old filtering + if( typ!=_FULL_) gfxSetTextureFiltering( iTexFilter, iTexAnisotropy); +} + + + +// fill part of a drawport with a given color +void CDrawPort::Fill( PIX pixI, PIX pixJ, PIX pixWidth, PIX pixHeight, COLOR col) const +{ + // if color is tranlucent + if( ((col&CT_AMASK)>>CT_ASHIFT) != CT_OPAQUE) + { // draw thru polygon + Fill( pixI,pixJ, pixWidth,pixHeight, col,col,col,col); + return; + } + + // clip and eventually reject + const BOOL bInside = ClipToDrawPort( this, pixI, pixJ, pixWidth, pixHeight); + if( !bInside) return; + + // draw thru fast clear for opaque colors + col = AdjustColor( col, _slTexHueShift, _slTexSaturation); + + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + // OpenGL + if( eAPI==GAT_OGL) + { + // do fast filling + SetScissor( this, pixI, pixJ, pixWidth, pixHeight); + UBYTE ubR, ubG, ubB; + ColorToRGB( col, ubR,ubG,ubB); + pglClearColor( ubR/255.0f, ubG/255.0f, ubB/255.0f, 1.0f); + pglClear( GL_COLOR_BUFFER_BIT); + ResetScissor(this); + } + // Direct3D +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) + { + HRESULT hr; + // must convert coordinates to raster (i.e. surface) + pixI += dp_MinI; + pixJ += dp_MinJ; + const PIX pixRasterW = dp_Raster->ra_Width; + const PIX pixRasterH = dp_Raster->ra_Height; + const ULONG d3dColor = rgba2argb(col); + // do fast filling + if( pixI==0 && pixJ==0 && pixWidth==pixRasterW && pixHeight==pixRasterH) { + hr = _pGfx->gl_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, d3dColor,0,0); + } else { + D3DRECT d3dRect = { pixI, pixJ, pixI+pixWidth, pixJ+pixHeight }; + hr = _pGfx->gl_pd3dDevice->Clear( 1, &d3dRect, D3DCLEAR_TARGET, d3dColor,0,0); + } // done + D3D_CHECKERROR(hr); + } +#endif // SE1_D3D +} + + +// fill part of a drawport with a four corner colors +void CDrawPort::Fill( PIX pixI, PIX pixJ, PIX pixWidth, PIX pixHeight, + COLOR colUL, COLOR colUR, COLOR colDL, COLOR colDR) const +{ + // clip and eventually reject + const BOOL bInside = ClipToDrawPort( this, pixI, pixJ, pixWidth, pixHeight); + if( !bInside) return; + + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + // setup rendering mode + gfxDisableDepthTest(); + gfxDisableDepthWrite(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + gfxDisableAlphaTest(); + gfxDisableTexture(); + // prepare colors and coords + colUL = AdjustColor( colUL, _slTexHueShift, _slTexSaturation); + colUR = AdjustColor( colUR, _slTexHueShift, _slTexSaturation); + colDL = AdjustColor( colDL, _slTexHueShift, _slTexSaturation); + colDR = AdjustColor( colDR, _slTexHueShift, _slTexSaturation); + const FLOAT fI0 = pixI; const FLOAT fI1 = pixI +pixWidth; + const FLOAT fJ0 = pixJ; const FLOAT fJ1 = pixJ +pixHeight; + + // render rectangle + if( eAPI==GAT_OGL) { + // thru OpenGL + gfxResetArrays(); + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + const GFXColor glcolUL(colUL); const GFXColor glcolUR(colUR); + const GFXColor glcolDL(colDL); const GFXColor glcolDR(colDR); + // add to element list and flush (the toilet!:) + pvtx[0].x = fI0; pvtx[0].y = fJ0; pvtx[0].z = 0; pcol[0] = glcolUL; + pvtx[1].x = fI0; pvtx[1].y = fJ1; pvtx[1].z = 0; pcol[1] = glcolDL; + pvtx[2].x = fI1; pvtx[2].y = fJ1; pvtx[2].z = 0; pcol[2] = glcolDR; + pvtx[3].x = fI1; pvtx[3].y = fJ0; pvtx[3].z = 0; pcol[3] = glcolUR; + gfxFlushQuads(); + } +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) { + // thru Direct3D + HRESULT hr; + const ULONG d3dColUL = rgba2argb(colUL); const ULONG d3dColUR = rgba2argb(colUR); + const ULONG d3dColDL = rgba2argb(colDL); const ULONG d3dColDR = rgba2argb(colDR); + CTVERTEX avtxTris[6] = { + {fI0,fJ0,0, d3dColUL, 0,0}, {fI0,fJ1,0, d3dColDL, 0,1}, {fI1,fJ1,0, d3dColDR, 1,1}, + {fI0,fJ0,0, d3dColUL, 0,0}, {fI1,fJ1,0, d3dColDR, 1,1}, {fI1,fJ0,0, d3dColUR, 1,0} }; + // set vertex shader and draw + d3dSetVertexShader(D3DFVF_CTVERTEX); + hr = _pGfx->gl_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLELIST, 2, avtxTris, sizeof(CTVERTEX)); + D3D_CHECKERROR(hr); + } +#endif // SE1_D3D +} + + +// fill an entire drawport with a given color +void CDrawPort::Fill( COLOR col) const +{ + // if color is tranlucent + if( ((col&CT_AMASK)>>CT_ASHIFT) != CT_OPAQUE) + { // draw thru polygon + Fill( 0,0, dp_Width,dp_Height, col,col,col,col); + return; + } + + // draw thru fast clear for opaque colors + col = AdjustColor( col, _slTexHueShift, _slTexSaturation); + + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + // OpenGL + if( eAPI==GAT_OGL) + { + // do fast filling + UBYTE ubR, ubG, ubB; + ColorToRGB( col, ubR,ubG,ubB); + pglClearColor( ubR/255.0f, ubG/255.0f, ubB/255.0f, 1.0f); + pglClear( GL_COLOR_BUFFER_BIT); + } + // Direct3D +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) + { + const ULONG d3dColor = rgba2argb(col); + HRESULT hr = _pGfx->gl_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, d3dColor,0,0); + D3D_CHECKERROR(hr); + } +#endif SE1_D3D +} + + +// fill a part of Z-Buffer with a given value +void CDrawPort::FillZBuffer( PIX pixI, PIX pixJ, PIX pixWidth, PIX pixHeight, FLOAT zval) const +{ + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + // clip and eventually reject + const BOOL bInside = ClipToDrawPort( this, pixI, pixJ, pixWidth, pixHeight); + if( !bInside) return; + + gfxEnableDepthWrite(); + + // OpenGL + if( eAPI==GAT_OGL) + { + // fast clearing thru scissor + SetScissor( this, pixI, pixJ, pixWidth, pixHeight); + pglClearDepth(zval); + pglClearStencil(0); + // must clear stencil buffer too in case it exist (we don't need it) for the performance sake + pglClear( GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); + ResetScissor(this); + OGL_CHECKERROR; + } + // Direct3D +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) + { + D3DRECT d3dRect = { pixI, pixJ, pixI+pixWidth, pixJ+pixHeight }; + HRESULT hr = _pGfx->gl_pd3dDevice->Clear( 1, &d3dRect, D3DCLEAR_ZBUFFER, 0,zval,0); + D3D_CHECKERROR(hr); + } +#endif SE1_D3D +} + + +// fill an entire Z-Buffer with a given value +void CDrawPort::FillZBuffer( FLOAT zval) const +{ + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + gfxEnableDepthWrite(); + + // OpenGL + if( eAPI==GAT_OGL) + { + // fill whole z-buffer + pglClearDepth(zval); + pglClearStencil(0); + pglClear( GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); + } + // Direct3D +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) + { + HRESULT hr = _pGfx->gl_pd3dDevice->Clear( 0, NULL, D3DCLEAR_ZBUFFER, 0,zval,0); + D3D_CHECKERROR(hr); + } +#endif SE1_D3D +} + + +// grab screen +void CDrawPort::GrabScreen( class CImageInfo &iiGrabbedImage, INDEX iGrabZBuffer/*=0*/) const +{ + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + extern INDEX ogl_bGrabDepthBuffer; + const BOOL bGrabDepth = eAPI==GAT_OGL && ((iGrabZBuffer==1 && ogl_bGrabDepthBuffer) || iGrabZBuffer==2); + + // prepare image info's dimensions + iiGrabbedImage.Clear(); + iiGrabbedImage.ii_Width = dp_Width; + iiGrabbedImage.ii_Height = dp_Height; + iiGrabbedImage.ii_BitsPerPixel = bGrabDepth ? 32 : 24; + + // allocate memory for 24-bit raw picture and copy buffer context + const PIX pixPicSize = iiGrabbedImage.ii_Width * iiGrabbedImage.ii_Height; + const SLONG slBytes = pixPicSize * iiGrabbedImage.ii_BitsPerPixel/8; + iiGrabbedImage.ii_Picture = (UBYTE*)AllocMemory( slBytes); + memset( iiGrabbedImage.ii_Picture, 128, slBytes); + + // OpenGL + if( eAPI==GAT_OGL) + { + // determine drawport starting location inside raster + const PIX pixStartI = dp_MinI; + const PIX pixStartJ = dp_Raster->ra_Height-(dp_MinJ+dp_Height); + pglReadPixels( pixStartI, pixStartJ, dp_Width, dp_Height, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)iiGrabbedImage.ii_Picture); + OGL_CHECKERROR; + // grab z-buffer to alpha channel, if needed + if( bGrabDepth) { + // grab + FLOAT *pfZBuffer = (FLOAT*)AllocMemory( pixPicSize*sizeof(FLOAT)); + pglReadPixels( pixStartI, pixStartJ, dp_Width, dp_Height, GL_DEPTH_COMPONENT, GL_FLOAT, (GLvoid*)pfZBuffer); + OGL_CHECKERROR; + // convert + UBYTE *pubZBuffer = (UBYTE*)pfZBuffer; + for( INDEX i=0; igl_ulFlags & GLF_FULLSCREEN; + if( bFullScreen) hr = _pGfx->gl_pd3dDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer); + else hr = dp_Raster->ra_pvpViewPort->vp_pSwapChain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer); + D3D_CHECKERROR(hr); + pBackBuffer->GetDesc(&surfDesc); + ASSERT( surfDesc.Width==dp_Raster->ra_Width && surfDesc.Height==dp_Raster->ra_Height); + const RECT rectToLock = { dp_MinI, dp_MinJ, dp_MaxI+1, dp_MaxJ+1 }; + hr = pBackBuffer->LockRect( &rectLocked, &rectToLock, D3DLOCK_READONLY); + D3D_CHECKERROR(hr); + + // prepare to copy'n'convert + SLONG slColSize; + UBYTE *pubSrc = (UBYTE*)rectLocked.pBits; + UBYTE *pubDst = iiGrabbedImage.ii_Picture; + // loop thru rows + for( INDEX j=0; jUnlockRect(); + D3DRELEASE( pBackBuffer, TRUE); + } +#endif // SE1_D3D +} + + +BOOL CDrawPort::IsPointVisible( PIX pixI, PIX pixJ, FLOAT fOoK, INDEX iID, INDEX iMirrorLevel/*=0*/) const +{ + // must have raster! + if( dp_Raster==NULL) { ASSERT(FALSE); return FALSE; } + + // if the point is out or at the edge of drawport, it is not visible by default + if( pixI<1 || pixI>dp_Width-2 || pixJ<1 || pixJ>dp_Height-2) return FALSE; + + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + // use delayed mechanism for checking + extern BOOL CheckDepthPoint( const CDrawPort *pdp, PIX pixI, PIX pixJ, FLOAT fOoK, INDEX iID, INDEX iMirrorLevel=0); + return CheckDepthPoint( this, pixI, pixJ, fOoK, iID, iMirrorLevel); +} + + +void CDrawPort::RenderLensFlare( CTextureObject *pto, FLOAT fI, FLOAT fJ, + FLOAT fSizeI, FLOAT fSizeJ, ANGLE aRotation, COLOR colLight) const +{ + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + // setup rendering mode + gfxEnableDepthTest(); + gfxDisableDepthWrite(); + gfxEnableBlend(); + gfxBlendFunc( GFX_ONE, GFX_ONE); + gfxDisableAlphaTest(); + gfxResetArrays(); + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + + // find lens location and dimension + const FLOAT fRI = fSizeI*0.5f; + const FLOAT fRJ = fSizeJ*0.5f; + const FLOAT fSinA = SinFast(aRotation); + const FLOAT fCosA = CosFast(aRotation); + const FLOAT fRICosA = fRI * +fCosA; + const FLOAT fRJSinA = fRJ * -fSinA; + const FLOAT fRISinA = fRI * +fSinA; + const FLOAT fRJCosA = fRJ * +fCosA; + + // get texture parameters for current frame and needed mip factor and upload texture + CTextureData *ptd = (CTextureData*)pto->GetData(); + ptd->SetAsCurrent(pto->GetFrame()); + // set lens color + colLight = AdjustColor( colLight, _slShdHueShift, _slShdSaturation); + const GFXColor glcol(colLight); + + // prepare coordinates of the rectangle + pvtx[0].x = fI- fRICosA+fRJSinA; pvtx[0].y = fJ- fRISinA+fRJCosA; pvtx[0].z = 0.01f; + pvtx[1].x = fI- fRICosA-fRJSinA; pvtx[1].y = fJ- fRISinA-fRJCosA; pvtx[1].z = 0.01f; + pvtx[2].x = fI+ fRICosA-fRJSinA; pvtx[2].y = fJ+ fRISinA-fRJCosA; pvtx[2].z = 0.01f; + pvtx[3].x = fI+ fRICosA+fRJSinA; pvtx[3].y = fJ+ fRISinA+fRJCosA; pvtx[3].z = 0.01f; + ptex[0].s = 0; ptex[0].t = 0; + ptex[1].s = 0; ptex[1].t = 1; + ptex[2].s = 1; ptex[2].t = 1; + ptex[3].s = 1; ptex[3].t = 0; + pcol[0] = glcol; + pcol[1] = glcol; + pcol[2] = glcol; + pcol[3] = glcol; + // render it + _pGfx->gl_ctWorldTriangles += 2; + gfxFlushQuads(); +} + + + +/******************************************************* + * Routines for manipulating drawport's text capabilites + */ + + +// sets font to be used to printout some text on this drawport +// WARNING: this resets text spacing, scaling and mode variables +void CDrawPort::SetFont( CFontData *pfd) +{ + // check if we're using font that's not even loaded yet + ASSERT( pfd!=NULL); + dp_FontData = pfd; + dp_pixTextCharSpacing = pfd->fd_pixCharSpacing; + dp_pixTextLineSpacing = pfd->fd_pixLineSpacing; + dp_fTextScaling = 1.0f; + dp_fTextAspect = 1.0f; + dp_iTextMode = 1; +}; + + +// returns width of the longest line in text string +ULONG CDrawPort::GetTextWidth( const CTString &strText) const +{ + // prepare scaling factors + PIX pixCellWidth = dp_FontData->fd_pixCharWidth; + SLONG fixTextScalingX = FloatToInt(dp_fTextScaling*dp_fTextAspect*65536.0f); + + // calculate width of entire text line + PIX pixStringWidth=0, pixOldWidth=0; + PIX pixCharStart=0, pixCharEnd=pixCellWidth; + INDEX ctCharsPrinted=0; + for( INDEX i=0; i<(INDEX)strlen(strText); i++) + { // get current letter + unsigned char chrCurrent = strText[i]; + // next line situation? + if( chrCurrent == '\n') { + if( pixOldWidth < pixStringWidth) pixOldWidth = pixStringWidth; + pixStringWidth=0; + continue; + } + // special char encountered and allowed? + else if( chrCurrent=='^' && dp_iTextMode!=-1) { + // get next char + chrCurrent = strText[++i]; + switch( chrCurrent) { + // skip corresponding number of characters + case 'c': i += FindZero((UBYTE*)&strText[i],6); continue; + case 'a': i += FindZero((UBYTE*)&strText[i],2); continue; + case 'f': i += 1; continue; + case 'b': case 'i': case 'r': case 'o': + case 'C': case 'A': case 'F': case 'B': case 'I': i+=0; continue; + default: break; // if we get here this means that ^ or an unrecognized special code was specified + } + } + // ignore tab + else if( chrCurrent == '\t') continue; + + // add current letter's width to result width + if( !dp_FontData->fd_bFixedWidth) { + // proportional font case + pixCharStart = dp_FontData->fd_fcdFontCharData[chrCurrent].fcd_pixStart; + pixCharEnd = dp_FontData->fd_fcdFontCharData[chrCurrent].fcd_pixEnd; + } + pixStringWidth += (((pixCharEnd-pixCharStart)*fixTextScalingX)>>16) +dp_pixTextCharSpacing; + ctCharsPrinted++; + } + // determine largest width + if( pixStringWidth < pixOldWidth) pixStringWidth = pixOldWidth; + return pixStringWidth; +} + + +// writes text string on drawport (left aligned if not forced otherwise) +void CDrawPort::PutText( const CTString &strText, PIX pixX0, PIX pixY0, const COLOR colBlend) const +{ + // check API and adjust position for D3D by half pixel + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + // skip drawing if text falls above or below draw port + if( pixY0>dp_Height || pixX0>dp_Width) return; + _pfGfxProfile.StartTimer( CGfxProfile::PTI_PUTTEXT); + char acTmp[7]; // needed for strtoul() + char *pcDummy; + INDEX iRet; + + // cache char and texture dimensions + FLOAT fTextScalingX = dp_fTextScaling*dp_fTextAspect; + SLONG fixTextScalingX = FloatToInt(fTextScalingX *65536.0f); + SLONG fixTextScalingY = FloatToInt(dp_fTextScaling*65536.0f); + PIX pixCellWidth = dp_FontData->fd_pixCharWidth; + PIX pixCharHeight = dp_FontData->fd_pixCharHeight-1; + PIX pixScaledWidth = (pixCellWidth *fixTextScalingX)>>16; + PIX pixScaledHeight = (pixCharHeight*fixTextScalingY)>>16; + + // prepare font texture + gfxSetTextureWrapping( GFX_REPEAT, GFX_REPEAT); + CTextureData &td = *dp_FontData->fd_ptdTextureData; + td.SetAsCurrent(); + // setup rendering mode + gfxDisableDepthTest(); + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + + // calculate and apply correction factor + FLOAT fCorrectionU = 1.0f / td.GetPixWidth(); + FLOAT fCorrectionV = 1.0f / td.GetPixHeight(); + INDEX ctMaxChars = (INDEX)strlen(strText); + // determine text color + GFXColor glcolDefault( AdjustColor( colBlend, _slTexHueShift, _slTexSaturation)); + GFXColor glcol = glcolDefault; + ULONG ulAlphaDefault = (colBlend&CT_AMASK)>>CT_ASHIFT;; // for flasher + ASSERT( dp_iTextMode==-1 || dp_iTextMode==0 || dp_iTextMode==+1); + + // prepare some text control and output vars + INDEX ctCharsPrinted=0, ctBoldsPrinted=0; + BOOL bBold = FALSE; + BOOL bItalic = FALSE; + INDEX iFlash = 0; + ULONG ulAlpha = ulAlphaDefault; + TIME tmFrame = _pGfx->gl_tvFrameTime.GetSeconds(); + BOOL bParse = dp_iTextMode==1; + + // prepare arrays + gfxResetArrays(); + GFXVertex *pvtx = _avtxCommon.Push( 2*ctMaxChars*4); // 2* because of bold + GFXTexCoord *ptex = _atexCommon.Push( 2*ctMaxChars*4); + GFXColor *pcol = _acolCommon.Push( 2*ctMaxChars*4); + + // loop thru chars + PIX pixAdvancer = ((pixCellWidth*fixTextScalingX)>>16) +dp_pixTextCharSpacing; + PIX pixStartX = pixX0; + for( INDEX iChar=0; iChardp_Height) break; + // skip to next char + continue; + } + // special char encountered and allowed? + else if( chrCurrent=='^' && dp_iTextMode!=-1) { + // get next char + chrCurrent = strText[++iChar]; + COLOR col; + switch( chrCurrent) + { + // color change? + case 'c': + strncpy( acTmp, &strText[iChar+1], 6); + iRet = FindZero( (UBYTE*)&strText[iChar+1], 6); + iChar+=iRet; + if( !bParse || iRet<6) continue; + acTmp[6] = '\0'; // terminate string + col = strtoul( acTmp, &pcDummy, 16) <<8; + col = AdjustColor( col, _slTexHueShift, _slTexSaturation); + glcol.Set( col|glcol.a); // do color change but keep original alpha + continue; + // alpha change? + case 'a': + strncpy( acTmp, &strText[iChar+1], 2); + iRet = FindZero( (UBYTE*)&strText[iChar+1], 2); + iChar+=iRet; + if( !bParse || iRet<2) continue; + acTmp[2] = '\0'; // terminate string + ulAlpha = strtoul( acTmp, &pcDummy, 16); + continue; + // flash? + case 'f': + chrCurrent = strText[++iChar]; + if( bParse) iFlash = 1+ 2* Clamp( (INDEX)(chrCurrent-'0'), 0L, 9L); + continue; + // reset all? + case 'r': + bBold = FALSE; + bItalic = FALSE; + iFlash = 0; + glcol = glcolDefault; + ulAlpha = ulAlphaDefault; + continue; + // simple codes ... + case 'o': bParse = bParse && gfx_bDecoratedText; continue; // allow console override settings? + case 'b': if( bParse) bBold = TRUE; continue; // bold? + case 'i': if( bParse) bItalic = TRUE; continue; // italic? + case 'C': glcol = glcolDefault; continue; // color reset? + case 'A': ulAlpha = ulAlphaDefault; continue; // alpha reset? + case 'B': bBold = FALSE; continue; // no bold? + case 'I': bItalic = FALSE; continue; // italic? + case 'F': iFlash = 0; continue; // no flash? + default: break; + } // unrecognized special code or just plain ^ + if( chrCurrent!='^') { iChar--; break; } + } + // ignore tab + else if( chrCurrent=='\t') continue; + + // get current location and dimensions + CFontCharData &fcdCurrent = dp_FontData->fd_fcdFontCharData[chrCurrent]; + PIX pixCharX = fcdCurrent.fcd_pixXOffset; + PIX pixCharY = fcdCurrent.fcd_pixYOffset; + PIX pixCharStart = fcdCurrent.fcd_pixStart; + PIX pixCharEnd = fcdCurrent.fcd_pixEnd; + PIX pixXA; // adjusted starting X location of printout + + // determine corresponding char width and position adjustments + if( dp_FontData->fd_bFixedWidth) { + // for fixed font + pixXA = pixX0 - ((pixCharStart*fixTextScalingX)>>16) + + (((pixScaledWidth<<16) - ((pixCharEnd-pixCharStart)*fixTextScalingX) +0x10000) >>17); + } else { + // for proportional font + pixXA = pixX0 - ((pixCharStart*fixTextScalingX)>>16); + pixAdvancer = (((pixCharEnd-pixCharStart)*fixTextScalingX)>>16) +dp_pixTextCharSpacing; + } + // out of screen (left) ? + if( pixXA>dp_Width || (pixXA+pixCharEnd)<0) { + // skip to next char + pixX0 += pixAdvancer; + continue; + } + + // adjust alpha for flashing + if( iFlash>0) glcol.a = ulAlpha*(sin(iFlash*tmFrame)*0.5f+0.5f); + else glcol.a = ulAlpha; + + // prepare coordinates for screen and texture + const FLOAT fX0 = pixXA; const FLOAT fX1 = fX0 +pixScaledWidth; + const FLOAT fY0 = pixY0; const FLOAT fY1 = fY0 +pixScaledHeight; + const FLOAT fU0 = pixCharX *fCorrectionU; const FLOAT fU1 = (pixCharX+pixCellWidth) *fCorrectionU; + const FLOAT fV0 = pixCharY *fCorrectionV; const FLOAT fV1 = (pixCharY+pixCharHeight) *fCorrectionV; + pvtx[0].x = fX0; pvtx[0].y = fY0; pvtx[0].z = 0; + pvtx[1].x = fX0; pvtx[1].y = fY1; pvtx[1].z = 0; + pvtx[2].x = fX1; pvtx[2].y = fY1; pvtx[2].z = 0; + pvtx[3].x = fX1; pvtx[3].y = fY0; pvtx[3].z = 0; + ptex[0].s = fU0; ptex[0].t = fV0; + ptex[1].s = fU0; ptex[1].t = fV1; + ptex[2].s = fU1; ptex[2].t = fV1; + ptex[3].s = fU1; ptex[3].t = fV0; + pcol[0] = glcol; + pcol[1] = glcol; + pcol[2] = glcol; + pcol[3] = glcol; + + // adjust for italic + if( bItalic) { + const FLOAT fAdjustX = fTextScalingX * (fY1-fY0)*0.2f; // 20% slanted + pvtx[0].x += fAdjustX; + pvtx[3].x += fAdjustX; + } + // advance to next vetrices group + pvtx += 4; + ptex += 4; + pcol += 4; + // add bold char + if( bBold) { + const FLOAT fAdjustX = fTextScalingX * ((FLOAT)pixCellWidth)*0.1f; // 10% fat (extra light mayonnaise:) + pvtx[0].x = pvtx[0-4].x +fAdjustX; pvtx[0].y = fY0; pvtx[0].z = 0; + pvtx[1].x = pvtx[1-4].x +fAdjustX; pvtx[1].y = fY1; pvtx[1].z = 0; + pvtx[2].x = pvtx[2-4].x +fAdjustX; pvtx[2].y = fY1; pvtx[2].z = 0; + pvtx[3].x = pvtx[3-4].x +fAdjustX; pvtx[3].y = fY0; pvtx[3].z = 0; + ptex[0].s = fU0; ptex[0].t = fV0; + ptex[1].s = fU0; ptex[1].t = fV1; + ptex[2].s = fU1; ptex[2].t = fV1; + ptex[3].s = fU1; ptex[3].t = fV0; + pcol[0] = glcol; + pcol[1] = glcol; + pcol[2] = glcol; + pcol[3] = glcol; + pvtx += 4; + ptex += 4; + pcol += 4; + ctBoldsPrinted++; + } + // advance to next char + pixX0 += pixAdvancer; + ctCharsPrinted++; + } + + // adjust vertex arrays size according to chars that really got printed out + ctCharsPrinted += ctBoldsPrinted; + _avtxCommon.PopUntil( ctCharsPrinted*4-1); + _atexCommon.PopUntil( ctCharsPrinted*4-1); + _acolCommon.PopUntil( ctCharsPrinted*4-1); + gfxFlushQuads(); + + // all done + _pfGfxProfile.StopTimer( CGfxProfile::PTI_PUTTEXT); +} + + + +// writes text string on drawport (centered arround X) +void CDrawPort::PutTextC( const CTString &strText, PIX pixX0, PIX pixY0, + const COLOR colBlend/*=0xFFFFFFFF*/) const +{ + PutText( strText, pixX0-GetTextWidth(strText)/2, pixY0, colBlend); +} + +// writes text string on drawport (centered arround X and Y) +void CDrawPort::PutTextCXY( const CTString &strText, PIX pixX0, PIX pixY0, + const COLOR colBlend/*=0xFFFFFFFF*/) const +{ + PIX pixTextWidth = GetTextWidth(strText); + PIX pixTextHeight = dp_FontData->fd_pixCharHeight * dp_fTextScaling; + PutText( strText, pixX0-pixTextWidth/2, pixY0-pixTextHeight/2, colBlend); +} + +// writes text string on drawport (right-aligned) +void CDrawPort::PutTextR( const CTString &strText, PIX pixX0, PIX pixY0, + const COLOR colBlend/*=0xFFFFFFFF*/) const +{ + PutText( strText, pixX0-GetTextWidth(strText), pixY0, colBlend); +} + + +/********************************************************** + * Routines for putting and getting textures strictly in 2D + */ + +void CDrawPort::PutTexture( class CTextureObject *pTO, const PIXaabbox2D &boxScreen, + const COLOR colBlend/*=0xFFFFFFFF*/) const +{ + PutTexture( pTO, boxScreen, colBlend, colBlend, colBlend, colBlend); +} + +void CDrawPort::PutTexture( class CTextureObject *pTO, const PIXaabbox2D &boxScreen, + const MEXaabbox2D &boxTexture, const COLOR colBlend/*=0xFFFFFFFF*/) const +{ + PutTexture( pTO, boxScreen, boxTexture, colBlend, colBlend, colBlend, colBlend); +} + +void CDrawPort::PutTexture( class CTextureObject *pTO, const PIXaabbox2D &boxScreen, + const COLOR colUL, const COLOR colUR, const COLOR colDL, const COLOR colDR) const +{ + MEXaabbox2D boxTexture( MEX2D(0,0), MEX2D(pTO->GetWidth(), pTO->GetHeight())); + PutTexture( pTO, boxScreen, boxTexture, colUL, colUR, colDL, colDR); +} + +// complete put texture routine +void CDrawPort::PutTexture( class CTextureObject *pTO, + const PIXaabbox2D &boxScreen, const MEXaabbox2D &boxTexture, + const COLOR colUL, const COLOR colUR, const COLOR colDL, const COLOR colDR) const +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_PUTTEXTURE); + + // extract screen and texture coordinates + const PIX pixI0 = boxScreen.Min()(1); const PIX pixI1 = boxScreen.Max()(1); + const PIX pixJ0 = boxScreen.Min()(2); const PIX pixJ1 = boxScreen.Max()(2); + + // if whole texture is out of drawport + if( pixI0>dp_Width || pixJ0>dp_Height || pixI1<0 || pixJ1<0) { + // skip it (just to reduce OpenGL call overhead) + _pfGfxProfile.StopTimer( CGfxProfile::PTI_PUTTEXTURE); + return; + } + + // check API and adjust position for D3D by half pixel + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + FLOAT fI0 = pixI0; FLOAT fI1 = pixI1; + FLOAT fJ0 = pixJ0; FLOAT fJ1 = pixJ1; + + // prepare texture + gfxSetTextureWrapping( GFX_REPEAT, GFX_REPEAT); + CTextureData *ptd = (CTextureData*)pTO->GetData(); + ptd->SetAsCurrent(pTO->GetFrame()); + + // setup rendering mode + gfxDisableDepthTest(); + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + gfxResetArrays(); + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + + // extract texture coordinates and apply correction factor + const PIX pixWidth = ptd->GetPixWidth(); + const PIX pixHeight = ptd->GetPixHeight(); + FLOAT fCorrectionU, fCorrectionV; + (SLONG&)fCorrectionU = (127-FastLog2(pixWidth)) <<23; // fCorrectionU = 1.0f / ptd->GetPixWidth() + (SLONG&)fCorrectionV = (127-FastLog2(pixHeight)) <<23; // fCorrectionV = 1.0f / ptd->GetPixHeight() + FLOAT fU0 = (boxTexture.Min()(1)>>ptd->td_iFirstMipLevel) *fCorrectionU; + FLOAT fU1 = (boxTexture.Max()(1)>>ptd->td_iFirstMipLevel) *fCorrectionU; + FLOAT fV0 = (boxTexture.Min()(2)>>ptd->td_iFirstMipLevel) *fCorrectionV; + FLOAT fV1 = (boxTexture.Max()(2)>>ptd->td_iFirstMipLevel) *fCorrectionV; + + // if not tiled + const BOOL bTiled = Abs(fU0-fU1)>1 || Abs(fV0-fV1)>1; + if( !bTiled) { + // slight adjust for sub-pixel precision + fU0 += +0.25f *fCorrectionU; + fU1 += -0.25f *fCorrectionU; + fV0 += +0.25f *fCorrectionV; + fV1 += -0.25f *fCorrectionV; + } + // prepare colors + const GFXColor glcolUL( AdjustColor( colUL, _slTexHueShift, _slTexSaturation)); + const GFXColor glcolUR( AdjustColor( colUR, _slTexHueShift, _slTexSaturation)); + const GFXColor glcolDL( AdjustColor( colDL, _slTexHueShift, _slTexSaturation)); + const GFXColor glcolDR( AdjustColor( colDR, _slTexHueShift, _slTexSaturation)); + + // prepare coordinates of the rectangle + pvtx[0].x = fI0; pvtx[0].y = fJ0; pvtx[0].z = 0; + pvtx[1].x = fI0; pvtx[1].y = fJ1; pvtx[1].z = 0; + pvtx[2].x = fI1; pvtx[2].y = fJ1; pvtx[2].z = 0; + pvtx[3].x = fI1; pvtx[3].y = fJ0; pvtx[3].z = 0; + ptex[0].s = fU0; ptex[0].t = fV0; + ptex[1].s = fU0; ptex[1].t = fV1; + ptex[2].s = fU1; ptex[2].t = fV1; + ptex[3].s = fU1; ptex[3].t = fV0; + pcol[0] = glcolUL; + pcol[1] = glcolDL; + pcol[2] = glcolDR; + pcol[3] = glcolUR; + gfxFlushQuads(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_PUTTEXTURE); +} + + + +// prepares texture and rendering arrays +void CDrawPort::InitTexture( class CTextureObject *pTO, const BOOL bClamp/*=FALSE*/) const +{ + // prepare + if( pTO!=NULL) { + // has texture + CTextureData *ptd = (CTextureData*)pTO->GetData(); + GfxWrap eWrap = GFX_REPEAT; + if( bClamp) eWrap = GFX_CLAMP; + gfxSetTextureWrapping( eWrap, eWrap); + ptd->SetAsCurrent(pTO->GetFrame()); + } else { + // no texture + gfxDisableTexture(); + } + // setup rendering mode + gfxDisableDepthTest(); + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + // prepare arrays + gfxResetArrays(); +} + + + +// adds one full texture to rendering queue +void CDrawPort::AddTexture( const FLOAT fI0, const FLOAT fJ0, const FLOAT fI1, const FLOAT fJ1, const COLOR col) const +{ + const GFXColor glCol( AdjustColor( col, _slTexHueShift, _slTexSaturation)); + const INDEX iStart = _avtxCommon.Count(); + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + INDEX *pelm = _aiCommonElements.Push(6); + pvtx[0].x = fI0; pvtx[0].y = fJ0; pvtx[0].z = 0; + pvtx[1].x = fI0; pvtx[1].y = fJ1; pvtx[1].z = 0; + pvtx[2].x = fI1; pvtx[2].y = fJ1; pvtx[2].z = 0; + pvtx[3].x = fI1; pvtx[3].y = fJ0; pvtx[3].z = 0; + ptex[0].s = 0; ptex[0].t = 0; + ptex[1].s = 0; ptex[1].t = 1; + ptex[2].s = 1; ptex[2].t = 1; + ptex[3].s = 1; ptex[3].t = 0; + pcol[0] = glCol; pcol[1] = glCol; pcol[2] = glCol; pcol[3] = glCol; + pelm[0] = iStart+0; pelm[1] = iStart+1; pelm[2] = iStart+2; + pelm[3] = iStart+2; pelm[4] = iStart+3; pelm[5] = iStart+0; +} + + +// adds one part of texture to rendering queue +void CDrawPort::AddTexture( const FLOAT fI0, const FLOAT fJ0, const FLOAT fI1, const FLOAT fJ1, + const FLOAT fU0, const FLOAT fV0, const FLOAT fU1, const FLOAT fV1, const COLOR col) const +{ + const GFXColor glCol( AdjustColor( col, _slTexHueShift, _slTexSaturation)); + const INDEX iStart = _avtxCommon.Count(); + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + INDEX *pelm = _aiCommonElements.Push(6); + pvtx[0].x = fI0; pvtx[0].y = fJ0; pvtx[0].z = 0; + pvtx[1].x = fI0; pvtx[1].y = fJ1; pvtx[1].z = 0; + pvtx[2].x = fI1; pvtx[2].y = fJ1; pvtx[2].z = 0; + pvtx[3].x = fI1; pvtx[3].y = fJ0; pvtx[3].z = 0; + ptex[0].s = fU0; ptex[0].t = fV0; + ptex[1].s = fU0; ptex[1].t = fV1; + ptex[2].s = fU1; ptex[2].t = fV1; + ptex[3].s = fU1; ptex[3].t = fV0; + pcol[0] = glCol; + pcol[1] = glCol; + pcol[2] = glCol; + pcol[3] = glCol; + pelm[0] = iStart+0; pelm[1] = iStart+1; pelm[2] = iStart+2; + pelm[3] = iStart+2; pelm[4] = iStart+3; pelm[5] = iStart+0; +} + + +// adds one triangle to rendering queue +void CDrawPort::AddTriangle( const FLOAT fI0, const FLOAT fJ0, + const FLOAT fI1, const FLOAT fJ1, + const FLOAT fI2, const FLOAT fJ2, const COLOR col) const +{ + const GFXColor glCol( AdjustColor( col, _slTexHueShift, _slTexSaturation)); + const INDEX iStart = _avtxCommon.Count(); + GFXVertex *pvtx = _avtxCommon.Push(3); + GFXTexCoord *ptex = _atexCommon.Push(3); + GFXColor *pcol = _acolCommon.Push(3); + INDEX *pelm = _aiCommonElements.Push(3); + pvtx[0].x = fI0; pvtx[0].y = fJ0; pvtx[0].z = 0; + pvtx[1].x = fI1; pvtx[1].y = fJ1; pvtx[1].z = 0; + pvtx[2].x = fI2; pvtx[2].y = fJ2; pvtx[2].z = 0; + pcol[0] = glCol; + pcol[1] = glCol; + pcol[2] = glCol; + pelm[0] = iStart+0; + pelm[1] = iStart+1; + pelm[2] = iStart+2; +} + + +// adds one textured quad (up-left start, counter-clockwise) +void CDrawPort::AddTexture( const FLOAT fI0, const FLOAT fJ0, const FLOAT fU0, const FLOAT fV0, const COLOR col0, + const FLOAT fI1, const FLOAT fJ1, const FLOAT fU1, const FLOAT fV1, const COLOR col1, + const FLOAT fI2, const FLOAT fJ2, const FLOAT fU2, const FLOAT fV2, const COLOR col2, + const FLOAT fI3, const FLOAT fJ3, const FLOAT fU3, const FLOAT fV3, const COLOR col3) const +{ + const GFXColor glCol0( AdjustColor( col0, _slTexHueShift, _slTexSaturation)); + const GFXColor glCol1( AdjustColor( col1, _slTexHueShift, _slTexSaturation)); + const GFXColor glCol2( AdjustColor( col2, _slTexHueShift, _slTexSaturation)); + const GFXColor glCol3( AdjustColor( col3, _slTexHueShift, _slTexSaturation)); + const INDEX iStart = _avtxCommon.Count(); + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + INDEX *pelm = _aiCommonElements.Push(6); + pvtx[0].x = fI0; pvtx[0].y = fJ0; pvtx[0].z = 0; + pvtx[1].x = fI1; pvtx[1].y = fJ1; pvtx[1].z = 0; + pvtx[2].x = fI2; pvtx[2].y = fJ2; pvtx[2].z = 0; + pvtx[3].x = fI3; pvtx[3].y = fJ3; pvtx[3].z = 0; + ptex[0].s = fU0; ptex[0].t = fV0; + ptex[1].s = fU1; ptex[1].t = fV1; + ptex[2].s = fU2; ptex[2].t = fV2; + ptex[3].s = fU3; ptex[3].t = fV3; + pcol[0] = glCol0; + pcol[1] = glCol1; + pcol[2] = glCol2; + pcol[3] = glCol3; + pelm[0] = iStart+0; pelm[1] = iStart+1; pelm[2] = iStart+2; + pelm[3] = iStart+2; pelm[4] = iStart+3; pelm[5] = iStart+0; +} + + +// renders all textures from rendering queue and flushed rendering arrays +void CDrawPort::FlushRenderingQueue(void) const +{ + gfxFlushElements(); + gfxResetArrays(); +} + + + +// blends screen with accumulation color +void CDrawPort::BlendScreen(void) +{ + if( dp_ulBlendingA==0) return; + + ULONG fix1oA = 65536 / dp_ulBlendingA; + ULONG ulRA = (dp_ulBlendingRA*fix1oA)>>16; + ULONG ulGA = (dp_ulBlendingGA*fix1oA)>>16; + ULONG ulBA = (dp_ulBlendingBA*fix1oA)>>16; + ULONG ulA = ClampUp( dp_ulBlendingA, 255UL); + COLOR colBlending = RGBAToColor( ulRA, ulGA, ulBA, ulA); + + // blend drawport (thru z-buffer because of elimination of pixel artefacts) + gfxEnableDepthTest(); + gfxDisableDepthWrite(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + gfxDisableAlphaTest(); + gfxDisableTexture(); + // prepare color + colBlending = AdjustColor( colBlending, _slTexHueShift, _slTexSaturation); + GFXColor glcol(colBlending); + + // set arrays + gfxResetArrays(); + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + const INDEX iW = dp_Width; + const INDEX iH = dp_Height; + pvtx[0].x = 0; pvtx[0].y = 0; pvtx[0].z = 0.01f; + pvtx[1].x = 0; pvtx[1].y = iH; pvtx[1].z = 0.01f; + pvtx[2].x = iW; pvtx[2].y = iH; pvtx[2].z = 0.01f; + pvtx[3].x = iW; pvtx[3].y = 0; pvtx[3].z = 0.01f; + pcol[0] = glcol; + pcol[1] = glcol; + pcol[2] = glcol; + pcol[3] = glcol; + gfxFlushQuads(); + // reset accumulation color + dp_ulBlendingRA = 0; + dp_ulBlendingGA = 0; + dp_ulBlendingBA = 0; + dp_ulBlendingA = 0; +} + diff --git a/Sources/Engine/Graphics/DrawPort.h b/Sources/Engine/Graphics/DrawPort.h new file mode 100644 index 0000000..09dfe39 --- /dev/null +++ b/Sources/Engine/Graphics/DrawPort.h @@ -0,0 +1,194 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_DRAWPORT_H +#define SE_INCL_DRAWPORT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + + +class ENGINE_API CDrawPort { +// implementation: +public: + CListNode dp_NodeInRaster; // for linking in list of clones +public: + class CRaster *dp_Raster; // pointer to the Raster this refers to + class CFontData *dp_FontData; // pointer to the current text font + PIX dp_Width, dp_Height; // width, height in pixels + PIX dp_MinI, dp_MinJ; // I,J coord of the upper left edge in the Raster + PIX dp_MaxI, dp_MaxJ; // I,J coord of the lower right edge in the Raster + PIX dp_ScissorMinI, dp_ScissorMinJ; // I,J coord of the upper left edge in the Raster + PIX dp_ScissorMaxI, dp_ScissorMaxJ; // I,J coord of the lower right edge in the Raster + PIX dp_pixTextCharSpacing; // space between chars in text + PIX dp_pixTextLineSpacing; // space between lines in text + FLOAT dp_fTextScaling; // scaling factor for font size + FLOAT dp_fTextAspect; // aspect ratio for font (x/y) + INDEX dp_iTextMode; // text output mode (-1 = print special codes, 0 = ignore special codes, 1 = parse special codes) + FLOAT dp_fWideAdjustment; // for wide (16:9 or 16:10) screen support (needed in some calculations) = 1.0f or >1 (10/12 perhaps) + BOOL dp_bRenderingOverlay; // set when scene renderer requires overlay mode (don't clear z-buffer) + + // dimensions and position relative to the raster size + double dp_SizeIOverRasterSizeI, dp_SizeJOverRasterSizeJ; + double dp_MinIOverRasterSizeI, dp_MinJOverRasterSizeJ; + + // adjust this during frame to be used for screen blending + ULONG dp_ulBlendingRA, dp_ulBlendingGA, dp_ulBlendingBA; // r*a, g*a, b*a + ULONG dp_ulBlendingA; + + // set cloned drawport dimensions + void InitCloned(CDrawPort *pdpBase, double rMinI,double rMinJ, double rSizeI,double rSizeJ); + + // Recalculate pixel dimensions from relative dimensions and raster size + void RecalculateDimensions(void); + + // set orthogonal projection + void SetOrtho(void) const; + // set given projection + void SetProjection(CAnyProjection3D &apr) const; + +//interface: + // Create a drawport for full raster + CDrawPort( CRaster *praBase=NULL); + // Clone a drawport + CDrawPort( CDrawPort *pdpBase, double rMinI,double rMinJ, double rSizeI,double rSizeJ); + CDrawPort( CDrawPort *pdpBase, const PIXaabbox2D &box); + // dualhead cloning + CDrawPort( CDrawPort *pdpBase, BOOL bLeft); + + // wide-screen cloning + void MakeWideScreen(CDrawPort *pdp); + + // check if a drawport is dualhead + BOOL IsDualHead(void); + // check if a drawport is wide screen + BOOL IsWideScreen(void); + + // set/get rendering in overlay mode + inline void SetOverlappedRendering(BOOL bOverlay) { dp_bRenderingOverlay = bOverlay; }; + inline BOOL IsOverlappedRendering(void) const { return dp_bRenderingOverlay; }; + + // returns unique drawport number + ULONG GetID(void); + + // Get dimensions and location of drawport + inline PIX GetWidth( void) const { return dp_Width; }; + inline PIX GetHeight(void) const { return dp_Height; }; + + // text manipulation + void SetFont( CFontData *pfd); // WARNING: this resets text variables + inline void SetTextCharSpacing( PIX pixSpacing) { dp_pixTextCharSpacing = pixSpacing; }; + inline void SetTextLineSpacing( PIX pixSpacing) { dp_pixTextLineSpacing = pixSpacing; }; + inline void SetTextScaling( FLOAT fScalingFactor) { dp_fTextScaling = fScalingFactor; }; + inline void SetTextAspect( FLOAT fAspectRatio) { dp_fTextAspect = fAspectRatio; }; + inline void SetTextMode( INDEX iMode) { dp_iTextMode = iMode; }; + // returns width of entire text string (with scale included) + ULONG GetTextWidth( const CTString &strText) const; + + // writes text string on drawport (left-aligned) + void PutText( const CTString &strText, PIX pixX0, PIX pixY0, const COLOR colBlend=0xFFFFFFFF) const; + // writes text string on drawport (centered arround X) + void PutTextC( const CTString &strText, PIX pixX0, PIX pixY0, const COLOR colBlend=0xFFFFFFFF) const; + // writes text string on drawport (centered arround X and Y) + void PutTextCXY( const CTString &strText, PIX pixX0, PIX pixY0, const COLOR colBlend=0xFFFFFFFF) const; + // writes text string on drawport (right-aligned) + void PutTextR( const CTString &strText, PIX pixX0, PIX pixY0, const COLOR colBlend=0xFFFFFFFF) const; + + // plain texture display + void PutTexture( class CTextureObject *pTO, const PIXaabbox2D &boxScreen, + const COLOR colBlend=0xFFFFFFFF) const; + void PutTexture( class CTextureObject *pTO, const PIXaabbox2D &boxScreen, + const COLOR colUL, const COLOR colUR, const COLOR colDL, const COLOR colDR) const; + void PutTexture( class CTextureObject *pTO, const PIXaabbox2D &boxScreen, + const MEXaabbox2D &boxTexture, const COLOR colBlend=0xFFFFFFFF) const; + void PutTexture( class CTextureObject *pTO, const PIXaabbox2D &boxScreen, const MEXaabbox2D &boxTexture, + const COLOR colUL, const COLOR colUR, const COLOR colDL, const COLOR colDR) const; + + // advanced texture display + void InitTexture( class CTextureObject *pTO, const BOOL bClamp=FALSE) const; // prepares texture and rendering arrays + // adds one full texture to rendering queue + void AddTexture( const FLOAT fI0, const FLOAT fJ0, const FLOAT fI1, const FLOAT fJ1, const COLOR col) const; + // adds one part of texture to rendering queue + void AddTexture( const FLOAT fI0, const FLOAT fJ0, const FLOAT fI1, const FLOAT fJ1, + const FLOAT fU0, const FLOAT fV0, const FLOAT fU1, const FLOAT fV1, const COLOR col) const; + // adds one textured quad to rendering queue (up-left start, counter-clockwise) + void AddTexture( const FLOAT fI0, const FLOAT fJ0, const FLOAT fU0, const FLOAT fV0, const COLOR col0, + const FLOAT fI1, const FLOAT fJ1, const FLOAT fU1, const FLOAT fV1, const COLOR col1, + const FLOAT fI2, const FLOAT fJ2, const FLOAT fU2, const FLOAT fV2, const COLOR col2, + const FLOAT fI3, const FLOAT fJ3, const FLOAT fU3, const FLOAT fV3, const COLOR col3) const; + // adds one flat triangle rendering queue (up-left start, counter-clockwise) + void AddTriangle( const FLOAT fI0, const FLOAT fJ0, const FLOAT fI1, const FLOAT fJ1, + const FLOAT fI2, const FLOAT fJ2, const COLOR col) const; + + // renders all textures from rendering queue and flushed rendering arrays + void FlushRenderingQueue(void) const; + + // lock and unlock raster thru drawport functions + BOOL Lock(void); + void Unlock(void); + + // draw point (can be several pixels - depends on radius) + void DrawPoint( PIX pixI, PIX pixJ, COLOR col, PIX pixRadius=1) const; + void DrawPoint3D( FLOAT3D v, COLOR col, FLOAT fRadius=1.0f) const; // in 3D + // draw line + void DrawLine( PIX pixI0, PIX pixJ0, PIX pixI1, PIX pixJ1, COLOR col, ULONG typ=_FULL_) const; + void DrawLine3D( FLOAT3D v0, FLOAT3D v1, COLOR col) const; // in 3D + // draw border + void DrawBorder( PIX pixI, PIX pixJ, PIX pixWidth, PIX pixHeight, COLOR col, ULONG typ=_FULL_) const; + + // fill with blending part of a drawport with a given color + void Fill( PIX pixI, PIX pixJ, PIX pixWidth, PIX pixHeight, COLOR col) const; + // fill with blending part of a drawport with a four corner colors + void Fill( PIX pixI, PIX pixJ, PIX pixWidth, PIX pixHeight, + COLOR colUL, COLOR colUR, COLOR colDL, COLOR colDR) const; + // fill a part of Z-Buffer with a given value + void FillZBuffer( PIX pixI, PIX pixJ, PIX pixWidth, PIX pixHeight, FLOAT zval) const; + + // fill without blending an entire drawport with a given color + void Fill( COLOR col) const; + // fill an entire Z-Buffer with a given value + void FillZBuffer( FLOAT zval) const; + + // grab screen (iGrabZBuffer: 0=no, 1=if allowed, 2=yes) + void GrabScreen( class CImageInfo &iiGrabbedImage, INDEX iGrabZBuffer=0) const; + // functions for getting depth of points on drawport + BOOL IsPointVisible( PIX pixI, PIX pixJ, FLOAT fOoK, INDEX iID, INDEX iMirrorLevel=0) const; + // render one lens flare + void RenderLensFlare( CTextureObject *pto, FLOAT fI, FLOAT fJ, + FLOAT fSizeI, FLOAT fSizeJ, ANGLE aRotation, COLOR colLight) const; + + // blend entire drawport with accumulated colors + void BlendScreen(void); +}; + + +enum ParticleBlendType { + PBT_BLEND, + PBT_ADD, + PBT_MULTIPLY, + PBT_ADDALPHA, + PBT_FLEX, // premultiplied alpha (ONE + [1-SRC_ALPHA]) + PBT_TRANSPARENT, +}; + +void ENGINE_API Particle_PrepareSystem( CDrawPort *pdpDrawPort, CAnyProjection3D &prProjection); +void ENGINE_API Particle_PrepareEntity( FLOAT fMipFactor, BOOL bHasFog, BOOL bHasHaze, CEntity *penViewer); +void ENGINE_API Particle_EndSystem( BOOL bRestoreOrtho=TRUE); +FLOAT ENGINE_API Particle_GetMipFactor(void); +INDEX ENGINE_API Particle_GetDrawPortID(void); +ENGINE_API CEntity *Particle_GetViewer(void); +ENGINE_API CProjection3D *Particle_GetProjection(void); +void ENGINE_API Particle_PrepareTexture( CTextureObject *pto, enum ParticleBlendType pbt); +void ENGINE_API Particle_SetTexturePart( MEX mexWidth, MEX mexHeight, INDEX iCol, INDEX iRow); +void ENGINE_API Particle_RenderSquare( const FLOAT3D &vPos, FLOAT fSize, ANGLE aRotation, COLOR col, FLOAT fYRatio=1.0f); +void ENGINE_API Particle_RenderQuad3D( const FLOAT3D &vPos0, const FLOAT3D &vPos1, const FLOAT3D &vPos2, + const FLOAT3D &vPos3, COLOR col); +void ENGINE_API Particle_RenderLine( const FLOAT3D &vPos0, const FLOAT3D &vPos1, FLOAT fWidth, COLOR col); +void ENGINE_API Particle_Sort( BOOL b3D=FALSE); +void ENGINE_API Particle_Flush(void); + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/DrawPort_Particles.cpp b/Sources/Engine/Graphics/DrawPort_Particles.cpp new file mode 100644 index 0000000..5166682 --- /dev/null +++ b/Sources/Engine/Graphics/DrawPort_Particles.cpp @@ -0,0 +1,630 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + + +extern const FLOAT *pfSinTable; +extern const FLOAT *pfCosTable; + +extern CEntity *_Particle_penCurrentViewer = NULL; +extern INDEX _Particle_iCurrentDrawPort = 0; +extern FLOAT _Particle_fCurrentMip = 0.0f; +extern BOOL _Particle_bHasFog = FALSE; +extern BOOL _Particle_bHasHaze = FALSE; + +// variables used for rendering particles +static CProjection3D *_pprProjection; +static FLOAT _fPerspectiveFactor; +static MEX _mexTextureWidth, _mexTextureHeight; +static FLOAT _fTextureCorrectionU, _fTextureCorrectionV; +static FLOAT _fNearClipDistance; +static GFXTexCoord _atex[4]; +static COLOR _colAttMask; +static BOOL _bTransFogHaze = FALSE; +static BOOL _bNeedsClipping = FALSE; +static CDrawPort *_pDP; +static CStaticStackArray _atexFogHaze; +static CTextureData *_ptd = NULL; +static INDEX _iFrame = 0; + + + +// prepare particles for rendering +void Particle_PrepareSystem( CDrawPort *pdpDrawPort, CAnyProjection3D &prProjection) +{ + _pDP = pdpDrawPort; + _pprProjection = (CProjection3D*)&*prProjection; + _fNearClipDistance = -prProjection->pr_NearClipDistance; + _fPerspectiveFactor = 1.0f; + _Particle_iCurrentDrawPort = pdpDrawPort->GetID(); + + // prepare projection and scale factor + pdpDrawPort->SetProjection(prProjection); + if( prProjection.IsPerspective()) _fPerspectiveFactor = ((CPerspectiveProjection3D*)&*prProjection)->ppr_PerspectiveRatios(1); + + // setup rendering mode + gfxEnableDepthTest(); + gfxCullFace(GFX_NONE); + gfxEnableTexture(); + // prepare general texture parameters + gfxSetTextureWrapping( GFX_REPEAT, GFX_REPEAT); + // prepare arrays to draw from begining + gfxResetArrays(); +} + +void Particle_EndSystem( BOOL bRestoreOrtho/*=TRUE*/) +{ + // reset projection and re-enable clipping + if( bRestoreOrtho) _pDP->SetOrtho(); + gfxEnableClipping(); +} + + +FLOAT Particle_GetMipFactor(void) +{ + return _Particle_fCurrentMip; +} + +CEntity *Particle_GetViewer(void) +{ + return _Particle_penCurrentViewer; +} + +CProjection3D *Particle_GetProjection(void) +{ + return _pprProjection; +} + +INDEX Particle_GetDrawPortID(void) +{ + return _Particle_iCurrentDrawPort; +} + + +void Particle_PrepareTexture( CTextureObject *pto, enum ParticleBlendType pbt) +{ + // determine blend type + switch( pbt) { + case PBT_BLEND: + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + _colAttMask = 0xFFFFFF00; // attenuate alpha + break; + case PBT_ADD: + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_ONE, GFX_ONE); + _colAttMask = 0x000000FF; // attenuate color + break; + case PBT_MULTIPLY: + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_ZERO, GFX_INV_SRC_COLOR); + _colAttMask = 0x000000FF; // attenuate color + break; + case PBT_ADDALPHA: + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_ONE); + _colAttMask = 0xFFFFFF00; // attenuate alpha + break; + case PBT_FLEX: + gfxDisableDepthWrite(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_ONE, GFX_INV_SRC_ALPHA); + _colAttMask = 0xFFFFFFFF; // attenuate alpha + break; + case PBT_TRANSPARENT: + gfxEnableDepthWrite(); + gfxEnableAlphaTest(); + gfxDisableBlend(); + _colAttMask = 0; // no attenuation - texture instead + break; + } + // get texture parameters for current frame and needed mip factor + _ptd = (CTextureData*)pto->GetData(); + _iFrame = pto->GetFrame(); + // prepare and upload texture + _ptd->SetAsCurrent(_iFrame); + // obtain curently used texture's width and height in mexes + _mexTextureWidth = _ptd->GetWidth(); + _mexTextureHeight = _ptd->GetHeight(); + // calculate correction factor (relative to greater texture dimension) + _fTextureCorrectionU = 1.0f/_mexTextureWidth; + _fTextureCorrectionV = 1.0f/_mexTextureHeight; + _atexFogHaze.Push(4); // temporary + _bTransFogHaze = _colAttMask==0 && (_Particle_bHasFog || _Particle_bHasHaze); + _bNeedsClipping = FALSE; +} + + +void Particle_SetTexturePart( MEX mexWidth, MEX mexHeight, INDEX iCol, INDEX iRow) +{ + // prepare full texture for displaying + MEXaabbox2D boxTextureClipped( MEX2D( mexWidth*(iCol+0), mexHeight*(iRow+0)), + MEX2D( mexWidth*(iCol+1), mexHeight*(iRow+1))); + + // prepare coordinates of the rectangle + _atex[0].s = boxTextureClipped.Min()(1) *_fTextureCorrectionU; + _atex[0].t = boxTextureClipped.Min()(2) *_fTextureCorrectionV; + _atex[1].s = boxTextureClipped.Min()(1) *_fTextureCorrectionU; + _atex[1].t = boxTextureClipped.Max()(2) *_fTextureCorrectionV; + _atex[2].s = boxTextureClipped.Max()(1) *_fTextureCorrectionU; + _atex[2].t = boxTextureClipped.Max()(2) *_fTextureCorrectionV; + _atex[3].s = boxTextureClipped.Max()(1) *_fTextureCorrectionU; + _atex[3].t = boxTextureClipped.Min()(2) *_fTextureCorrectionV; +} + + + +// add one particle square to rendering queue +void Particle_RenderSquare( const FLOAT3D &vPos, FLOAT fSize, ANGLE aRotation, COLOR col, FLOAT fYRatio/*=1.0f*/) +{ + // trivial rejection + if( fSize<0.0001f || ((col&CT_AMASK)>>CT_ASHIFT)<2) return; + + // project point to screen + FLOAT3D vProjected; + _pprProjection->PreClip( vPos, vProjected); + // skip if not in screen + const INDEX iTest = _pprProjection->TestSphereToFrustum( vProjected, fSize); + if( iTest<0) return; + const FLOAT fPixSize = fSize * _fPerspectiveFactor / vProjected(3); + if( fPixSize<0.5f) return; + + // adjust the need for clipping + if( iTest==0) _bNeedsClipping = TRUE; + + // eventual tex coords for fog or haze + const INDEX ctTexFG = _atexFogHaze.Count(); + GFXTexCoord *ptexFogHaze = &_atexFogHaze[ctTexFG-4]; + + // if haze is active + if( _Particle_bHasHaze) + { // get haze strength at particle position + ptexFogHaze[0].s = (-vProjected(3)+_haze_fAdd)*_haze_fMul; + const ULONG ulH = 255-GetHazeAlpha(ptexFogHaze[0].s); + if( ulH<4) return; + if( _colAttMask) { // apply haze color (if not transparent) + const COLOR colH = _colAttMask | RGBAToColor( ulH,ulH,ulH,ulH); + col = MulColors( col, colH); + } else ptexFogHaze[0].t = 0; + } + // if fog is active + if( _Particle_bHasFog) + { // get fog strength at particle position + ptexFogHaze[0].s = -vProjected(3)*_fog_fMulZ; + ptexFogHaze[0].t = (vProjected%_fog_vHDirView+_fog_fAddH)*_fog_fMulH; + const ULONG ulF = 255-GetFogAlpha(ptexFogHaze[0]); + if( ulF<4) return; + if( _colAttMask) { // apply fog color (if not transparent) + const COLOR colF = _colAttMask | RGBAToColor( ulF,ulF,ulF,ulF); + col = MulColors( col, colF); + } + } + // keep fog/haze tex coords (if needed) + if( _bTransFogHaze) { + ptexFogHaze[1] = ptexFogHaze[2] = ptexFogHaze[3] = ptexFogHaze[0]; + _atexFogHaze.Push(4); + } + + // prepare screen coords + const FLOAT fI0 = vProjected(1); + const FLOAT fJ0 = vProjected(2); + const FLOAT fOoK = vProjected(3); + + // add to vertex arrays + GFXVertex4 *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + + // prepare vertices + const FLOAT fRX = fSize; + const FLOAT fRY = fSize*fYRatio; + if( aRotation==0) { + const FLOAT fIBeg = fI0-fRX; const FLOAT fIEnd = fI0+fRX; + const FLOAT fJBeg = fJ0-fRY; const FLOAT fJEnd = fJ0+fRY; + pvtx[0].x = fIBeg; pvtx[0].y = fJBeg; pvtx[0].z = fOoK; + pvtx[1].x = fIBeg; pvtx[1].y = fJEnd; pvtx[1].z = fOoK; + pvtx[2].x = fIEnd; pvtx[2].y = fJEnd; pvtx[2].z = fOoK; + pvtx[3].x = fIEnd; pvtx[3].y = fJBeg; pvtx[3].z = fOoK; + } else { + const INDEX iRot256 = FloatToInt(aRotation*0.7111f) & 255; // *256/360 + const FLOAT fSinA = pfSinTable[iRot256]; + const FLOAT fCosA = pfCosTable[iRot256]; + const FLOAT fSinPCos = fCosA*fRX+fSinA*fRY; + const FLOAT fSinMCos = fSinA*fRX-fCosA*fRY; + pvtx[0].x = fI0-fSinPCos; pvtx[0].y = fJ0-fSinMCos; pvtx[0].z = fOoK; + pvtx[1].x = fI0+fSinMCos; pvtx[1].y = fJ0-fSinPCos; pvtx[1].z = fOoK; + pvtx[2].x = fI0+fSinPCos; pvtx[2].y = fJ0+fSinMCos; pvtx[2].z = fOoK; + pvtx[3].x = fI0-fSinMCos; pvtx[3].y = fJ0+fSinPCos; pvtx[3].z = fOoK; + } + // prepare texture coords + ptex[0] = _atex[1]; + ptex[1] = _atex[0]; + ptex[2] = _atex[3]; + ptex[3] = _atex[2]; + // prepare colors + const GFXColor glcol( AdjustColor( col, _slTexHueShift, _slTexSaturation)); + pcol[0] = glcol; + pcol[1] = glcol; + pcol[2] = glcol; + pcol[3] = glcol; +} + + + +// add one particle line to rendering queue +void Particle_RenderLine( const FLOAT3D &vPos0, const FLOAT3D &vPos1, FLOAT fWidth, COLOR col) +{ + // trivial rejection + if( fWidth<0 || ((col&CT_AMASK)>>CT_ASHIFT)<2) return; + + // project point to screen + FLOAT3D vProjected0, vProjected1; + _pprProjection->PreClip( vPos0, vProjected0); + _pprProjection->PreClip( vPos1, vProjected1); + // skip if not in screen + if (vProjected0(3)>_fNearClipDistance || vProjected1(3)>_fNearClipDistance) return; + + const FLOAT fK0 = 1.0f / vProjected0(3); + const FLOAT fK1 = 1.0f / vProjected1(3); + const FLOAT fR0 = fWidth * _fPerspectiveFactor *fK0; + const FLOAT fR1 = fWidth * _fPerspectiveFactor *fK1; + if( fR0<0.5f && fR1<0.5f) return; + + // line might need clipping + _bNeedsClipping = TRUE; + + COLOR col0, col1; + col0 = col1 = col; + // eventual tex coords for fog or haze + const INDEX ctTexFG = _atexFogHaze.Count(); + GFXTexCoord *ptexFogHaze = &_atexFogHaze[ctTexFG-4]; + + // if haze is active + if( _Particle_bHasHaze) + { // get haze strength at particle positions + ptexFogHaze[0].s = (-vProjected0(3)+_haze_fAdd)*_haze_fMul; + ptexFogHaze[1].s = (-vProjected1(3)+_haze_fAdd)*_haze_fMul; + const ULONG ulH0 = 255-GetHazeAlpha(ptexFogHaze[0].s); + const ULONG ulH1 = 255-GetHazeAlpha(ptexFogHaze[1].s); + if( (ulH0|ulH1)<4) return; + if( _colAttMask) { // apply haze color (if not transparent) + COLOR colH; + colH = _colAttMask | RGBAToColor( ulH0,ulH0,ulH0,ulH0); col0 = MulColors( col0, colH); + colH = _colAttMask | RGBAToColor( ulH1,ulH1,ulH1,ulH1); col1 = MulColors( col1, colH); + } else ptexFogHaze[0].t = ptexFogHaze[1].t = 0; + } + // if fog is active + if( _Particle_bHasFog) + { // get fog strength at particle position + ptexFogHaze[0].s = -vProjected0(3)*_fog_fMulZ; + ptexFogHaze[0].t = (vProjected0%_fog_vHDirView+_fog_fAddH)*_fog_fMulH; + ptexFogHaze[1].s = -vProjected1(3)*_fog_fMulZ; + ptexFogHaze[1].t = (vProjected1%_fog_vHDirView+_fog_fAddH)*_fog_fMulH; + const ULONG ulF0 = 255-GetFogAlpha(ptexFogHaze[0]); + const ULONG ulF1 = 255-GetFogAlpha(ptexFogHaze[1]); + if( (ulF0|ulF1)<4) return; + if( _colAttMask) { // apply fog color (if not transparent) + COLOR colF; // apply fog color + colF = _colAttMask | RGBAToColor( ulF0,ulF0,ulF0,ulF0); col0 = MulColors( col0, colF); + colF = _colAttMask | RGBAToColor( ulF1,ulF1,ulF1,ulF1); col1 = MulColors( col1, colF); + } + } + // keep fog/haze tex coords (if needed) + if( _bTransFogHaze) { + ptexFogHaze[2] = ptexFogHaze[1]; + ptexFogHaze[3] = ptexFogHaze[0]; + _atexFogHaze.Push(4); + } + + // lets draw + const FLOAT fI0 = vProjected0(1); const FLOAT fI1 = vProjected1(1); + const FLOAT fJ0 = vProjected0(2); const FLOAT fJ1 = vProjected1(2); + const FLOAT fOoK0 = vProjected0(3); const FLOAT fOoK1 = vProjected1(3); + FLOAT fDI = fI1*fK1 - fI0*fK0; + FLOAT fDJ = fJ1*fK1 - fJ0*fK0; + const FLOAT fD = fWidth / Sqrt( fDI*fDI + fDJ*fDJ); + fDI *= fD; // multiplied by width! + fDJ *= fD; + + // add to vertex arrays + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + + // prepare vertices + pvtx[0].x = fI0+fDJ; pvtx[0].y = fJ0-fDI; pvtx[0].z = fOoK0; + pvtx[1].x = fI1+fDJ; pvtx[1].y = fJ1-fDI; pvtx[1].z = fOoK1; + pvtx[2].x = fI1-fDJ; pvtx[2].y = fJ1+fDI; pvtx[2].z = fOoK1; + pvtx[3].x = fI0-fDJ; pvtx[3].y = fJ0+fDI; pvtx[3].z = fOoK0; + // prepare texture coords + ptex[0] = _atex[0]; + ptex[1] = _atex[1]; + ptex[2] = _atex[2]; + ptex[3] = _atex[3]; + // prepare colors + const GFXColor glcol0( AdjustColor( col0, _slTexHueShift, _slTexSaturation)); + const GFXColor glcol1( AdjustColor( col1, _slTexHueShift, _slTexSaturation)); + pcol[0] = glcol0; + pcol[1] = glcol1; + pcol[2] = glcol1; + pcol[3] = glcol0; +} + + + +// add one 3D particle quad to rendering queue +void Particle_RenderQuad3D( const FLOAT3D &vPos0, const FLOAT3D &vPos1, const FLOAT3D &vPos2, + const FLOAT3D &vPos3, COLOR col) +{ + // trivial rejection + if( ((col&CT_AMASK)>>CT_ASHIFT)<2) return; + + // project point to screen + FLOAT3D vProjected0, vProjected1, vProjected2, vProjected3; + _pprProjection->PreClip( vPos0, vProjected0); + _pprProjection->PreClip( vPos1, vProjected1); + _pprProjection->PreClip( vPos2, vProjected2); + _pprProjection->PreClip( vPos3, vProjected3); + + // test for trivial rejection (sphere method) + FLOAT3D vNearest = vProjected0; // find nearest-Z vertex + if( vNearest(3)>vProjected1(3)) vNearest = vProjected1; + if( vNearest(3)>vProjected2(3)) vNearest = vProjected2; + if( vNearest(3)>vProjected3(3)) vNearest = vProjected3; + // find center + const FLOAT fX = (vProjected0(1)+vProjected1(1)+vProjected2(1)+vProjected3(1)) * 0.25f; + const FLOAT fY = (vProjected0(2)+vProjected1(2)+vProjected2(2)+vProjected3(2)) * 0.25f; + // find radius (approx. distance to nearest-Z vertex) + // we won't do sqrt but rather larger distance * 0.7f (1/sqrt(2)) + const FLOAT fDX = Abs(fX-vNearest(1)); + const FLOAT fDY = Abs(fY-vNearest(2)); + const FLOAT fR = 0.7f * Max(fDX,fDY); + // set center vertex location and test it + vNearest(1) = fX; + vNearest(2) = fY; + const INDEX iTest = _pprProjection->TestSphereToFrustum( vNearest, fR); + if( iTest<0) return; + + // adjust the need for clipping + if( iTest==0) _bNeedsClipping = TRUE; + + // separate colors (for the sake of fog/haze) + COLOR col0,col1,col2,col3; + col0 = col1 = col2 = col3 = col; + // eventual tex coords for fog or haze + const INDEX ctTexFG = _atexFogHaze.Count(); + GFXTexCoord *ptexFogHaze = &_atexFogHaze[ctTexFG-4]; + + // if haze is active + if( _Particle_bHasHaze) + { // get haze strength at particle position + ptexFogHaze[0].s = (-vProjected0(3)+_haze_fAdd)*_haze_fMul; + ptexFogHaze[1].s = (-vProjected1(3)+_haze_fAdd)*_haze_fMul; + ptexFogHaze[2].s = (-vProjected2(3)+_haze_fAdd)*_haze_fMul; + ptexFogHaze[3].s = (-vProjected3(3)+_haze_fAdd)*_haze_fMul; + const ULONG ulH0 = 255-GetHazeAlpha(ptexFogHaze[0].s); + const ULONG ulH1 = 255-GetHazeAlpha(ptexFogHaze[1].s); + const ULONG ulH2 = 255-GetHazeAlpha(ptexFogHaze[2].s); + const ULONG ulH3 = 255-GetHazeAlpha(ptexFogHaze[3].s); + if( (ulH0|ulH1|ulH2|ulH3)<4) return; + if( _colAttMask) { // apply haze color (if not transparent) + COLOR colH; + colH = _colAttMask | RGBAToColor( ulH0,ulH0,ulH0,ulH0); col0 = MulColors( col0, colH); + colH = _colAttMask | RGBAToColor( ulH1,ulH1,ulH1,ulH1); col1 = MulColors( col1, colH); + colH = _colAttMask | RGBAToColor( ulH2,ulH2,ulH2,ulH2); col2 = MulColors( col2, colH); + colH = _colAttMask | RGBAToColor( ulH3,ulH3,ulH3,ulH3); col3 = MulColors( col3, colH); + } else ptexFogHaze[0].t = ptexFogHaze[1].t = ptexFogHaze[2].t = ptexFogHaze[3].t = 0; + } + // if fog is active + if( _Particle_bHasFog) + { // get fog strength at particle position + ptexFogHaze[0].s = -vProjected0(3)*_fog_fMulZ; + ptexFogHaze[0].t = (vProjected0%_fog_vHDirView+_fog_fAddH)*_fog_fMulH; + ptexFogHaze[1].s = -vProjected1(3)*_fog_fMulZ; + ptexFogHaze[1].t = (vProjected1%_fog_vHDirView+_fog_fAddH)*_fog_fMulH; + ptexFogHaze[2].s = -vProjected2(3)*_fog_fMulZ; + ptexFogHaze[2].t = (vProjected2%_fog_vHDirView+_fog_fAddH)*_fog_fMulH; + ptexFogHaze[3].s = -vProjected3(3)*_fog_fMulZ; + ptexFogHaze[3].t = (vProjected3%_fog_vHDirView+_fog_fAddH)*_fog_fMulH; + const ULONG ulF0 = 255-GetFogAlpha(ptexFogHaze[0]); + const ULONG ulF1 = 255-GetFogAlpha(ptexFogHaze[1]); + const ULONG ulF2 = 255-GetFogAlpha(ptexFogHaze[2]); + const ULONG ulF3 = 255-GetFogAlpha(ptexFogHaze[3]); + if( (ulF0|ulF1|ulF2|ulF3)<4) return; + if( _colAttMask) { // apply fog color (if not transparent) + COLOR colF; + colF = _colAttMask | RGBAToColor( ulF0,ulF0,ulF0,ulF0); col0 = MulColors( col0, colF); + colF = _colAttMask | RGBAToColor( ulF1,ulF1,ulF1,ulF1); col1 = MulColors( col1, colF); + colF = _colAttMask | RGBAToColor( ulF2,ulF2,ulF2,ulF2); col2 = MulColors( col2, colF); + colF = _colAttMask | RGBAToColor( ulF3,ulF3,ulF3,ulF3); col3 = MulColors( col3, colF); + } + } + // keep fog/haze tex coords (if needed) + if( _bTransFogHaze) _atexFogHaze.Push(4); + + // add to vertex arrays + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + + // prepare vertices + pvtx[0].x = vProjected0(1); pvtx[0].y = vProjected0(2); pvtx[0].z = vProjected0(3); + pvtx[1].x = vProjected1(1); pvtx[1].y = vProjected1(2); pvtx[1].z = vProjected1(3); + pvtx[2].x = vProjected2(1); pvtx[2].y = vProjected2(2); pvtx[2].z = vProjected2(3); + pvtx[3].x = vProjected3(1); pvtx[3].y = vProjected3(2); pvtx[3].z = vProjected3(3); + // prepare texture coords + ptex[0] = _atex[0]; + ptex[1] = _atex[1]; + ptex[2] = _atex[2]; + ptex[3] = _atex[3]; + // prepare colors + const GFXColor glcol0( AdjustColor( col0, _slTexHueShift, _slTexSaturation)); + const GFXColor glcol1( AdjustColor( col1, _slTexHueShift, _slTexSaturation)); + const GFXColor glcol2( AdjustColor( col2, _slTexHueShift, _slTexSaturation)); + const GFXColor glcol3( AdjustColor( col3, _slTexHueShift, _slTexSaturation)); + pcol[0] = glcol0; + pcol[1] = glcol1; + pcol[2] = glcol2; + pcol[3] = glcol3; +} + + +// flushes particle rendering queue (i.e. renders particle on screen) +void Particle_Flush(void) +{ + // update stats + const INDEX ctParticles = _avtxCommon.Count()/4; + _sfStats.IncrementCounter( CStatForm::SCI_PARTICLES, ctParticles); + _pGfx->gl_ctParticleTriangles += ctParticles*2; + + // determine need for clipping + if( _bNeedsClipping) gfxEnableClipping(); + else gfxDisableClipping(); + + // flush 1st layer + gfxFlushQuads(); + // maybe we need to render fog/haze layer + if( _bTransFogHaze) + { // setup haze/fog color and texture + GFXColor glcolFH; + gfxSetTextureWrapping( GFX_CLAMP, GFX_CLAMP); + if( _Particle_bHasHaze) { + gfxSetTexture( _haze_ulTexture, _haze_tpLocal); + glcolFH.abgr = ByteSwap( AdjustColor( _haze_hp.hp_colColor, _slTexHueShift, _slTexSaturation)); + } else { + gfxSetTexture( _fog_ulTexture, _fog_tpLocal); + glcolFH.abgr = ByteSwap( AdjustColor( _fog_fp.fp_colColor, _slTexHueShift, _slTexSaturation)); + } + // prepare haze rendering parameters + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + gfxDisableDepthWrite(); + gfxDepthFunc( GFX_EQUAL); // adjust z-buffer compare + // copy fog/haze texture array to main texture array and set color to fog/haze + const INDEX ctVertices = _atexCommon.Count(); + ASSERT( _atexFogHaze.Count()==ctVertices+4); + memcpy( &_atexCommon[0], &_atexFogHaze[0], ctVertices*sizeof(GFXTexCoord)); + for( INDEX i=0; iSetAsCurrent(_iFrame); + _pGfx->gl_ctParticleTriangles += ctParticles*2; + } + + // all done + gfxResetArrays(); + _atexFogHaze.PopAll(); + _bNeedsClipping = FALSE; +} + + + +// SORTING ROUTINES + +static int qsort_CompareZ( const void *pI0, const void *pI1) { + const INDEX i0 = (*(INDEX*)pI0) *4; + const INDEX i1 = (*(INDEX*)pI1) *4; + const FLOAT fZ0 = _avtxCommon[i0].z; + const FLOAT fZ1 = _avtxCommon[i1].z; + if( fZ0fZ1) return -1; + else return 0; +} + +static int qsort_CompareZ3D( const void *pI0, const void *pI1) { + const INDEX i0 = (*(INDEX*)pI0) *4; + const INDEX i1 = (*(INDEX*)pI1) *4; + const FLOAT fZ0 = (_avtxCommon[i0].z + _avtxCommon[i0+1].z + _avtxCommon[i0+2].z + _avtxCommon[i0+3].z) / 4.0f; + const FLOAT fZ1 = (_avtxCommon[i1].z + _avtxCommon[i1+1].z + _avtxCommon[i1+2].z + _avtxCommon[i1+3].z) / 4.0f; + if( fZ0fZ1) return -1; + else return 0; +} + + +// sorts particles by distance +void Particle_Sort( BOOL b3D/*=FALSE*/) +{ + INDEX i; + const INDEX ctParticles = _avtxCommon.Count()/4; + if( ctParticles<=0) return; // nothing to do! + + // generate sort array + CStaticArray aiIndices; + aiIndices.New(ctParticles); + for( i=0; i aiInverse; + aiInverse.New(ctParticles); + for( i=0; i= pvtx[(i+1)*4].z); + } +#endif +} diff --git a/Sources/Engine/Graphics/DrawPort_RenderScene.cpp b/Sources/Engine/Graphics/DrawPort_RenderScene.cpp new file mode 100644 index 0000000..b4ec5e9 --- /dev/null +++ b/Sources/Engine/Graphics/DrawPort_RenderScene.cpp @@ -0,0 +1,1855 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + +#define ASMOPT 1 + +#define MAXTEXUNITS 4 +#define SHADOWTEXTURE 3 + +extern INDEX wld_bShowTriangles; +extern INDEX wld_bShowDetailTextures; +extern INDEX wld_bRenderShadowMaps; +extern INDEX wld_bRenderTextures; +extern INDEX wld_bRenderDetailPolygons; +extern INDEX wld_iDetailRemovingBias; +extern INDEX wld_bAccurateColors; + +extern INDEX gfx_bRenderWorld; +extern INDEX shd_iForceFlats; +extern INDEX shd_bShowFlats; + +extern BOOL _bMultiPlayer; +extern BOOL CVA_bWorld; +static GfxAPIType eAPI; + + +// vertex coordinates and elements used by one pass of polygons +static CStaticStackArray _avtxPass; +static CStaticStackArray _atexPass[MAXTEXUNITS]; +static CStaticStackArray _acolPass; +static CStaticStackArray _aiElements; +// general coordinate stack referenced by the scene polygons +CStaticStackArray _avtxScene; + +// group flags (single-texturing) +#define GF_TX0 (1L<<0) +#define GF_TX1 (1L<<1) +#define GF_TX2 (1L<<2) +#define GF_SHD (1L<<3) +#define GF_FLAT (1L<<4) // flat fill instead of texture 1 +#define GF_TA1 (1L<<5) // texture 2 after shade +#define GF_TA2 (1L<<6) // texture 3 after shade +#define GF_FOG (1L<<7) +#define GF_HAZE (1L<<8) +#define GF_SEL (1L<<9) +#define GF_KEY (1L<<10) // first layer requires alpha-keying + +// texture combinations for max 4 texture units (fog, haze and selection not included) +#define GF_TX0_TX1 (1L<<11) +#define GF_TX0_TX2 (1L<<12) +#define GF_TX0_SHD (1L<<13) +#define GF_TX2_SHD (1L<<14) // second pass +#define GF_TX0_TX1_TX2 (1L<<15) +#define GF_TX0_TX1_SHD (1L<<16) +#define GF_TX0_TX2_SHD (1L<<17) +#define GF_TX0_TX1_TX2_SHD (1L<<18) + +// total number of groups +#define GROUPS_MAXCOUNT (1L<<11) // max group +1 ! +#define GROUPS_MINCOUNT (1L<<4)-1 // min group ! +static ScenePolygon *_apspoGroups[GROUPS_MAXCOUNT]; +static INDEX _ctGroupsCount=0; + + +// some static vars + +static FLOAT _fHazeMul, _fHazeAdd; +static FLOAT _fFogMul; + +static COLOR _colSelection; +static INDEX _ctUsableTexUnits; +static BOOL _bTranslucentPass; // rendering translucent polygons + +static ULONG _ulLastFlags[MAXTEXUNITS]; +static ULONG _ulLastBlends[MAXTEXUNITS]; +static INDEX _iLastFrameNo[MAXTEXUNITS]; +static CTextureData *_ptdLastTex[MAXTEXUNITS]; + +static CDrawPort *_pDP; +static CPerspectiveProjection3D *_ppr = NULL; + + +// draw batched elements +static void FlushElements(void) +{ + // skip if empty + const INDEX ctElements = _aiElements.Count(); + if( ctElements<3) return; + // draw + const INDEX ctTris = ctElements/3; + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_DRAWELEMENTS); + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_TRIANGLEPASSESOPT, ctTris); + _sfStats.IncrementCounter( CStatForm::SCI_SCENE_TRIANGLEPASSES, ctTris); + _pGfx->gl_ctWorldTriangles += ctTris; + gfxDrawElements( ctElements, &_aiElements[0]); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_DRAWELEMENTS); + // reset + _aiElements.PopAll(); +} + + +// batch elements of one polygon +static __forceinline void AddElements( ScenePolygon *pspo) +{ + const INDEX ctElems = pspo->spo_ctElements; + INDEX *piDst = _aiElements.Push(ctElems); +#if ASMOPT == 1 + __asm { + mov eax,D [pspo] + mov ecx,D [ctElems] + mov edi,D [piDst] + mov esi,D [eax]ScenePolygon.spo_piElements + mov ebx,D [eax]ScenePolygon.spo_iVtx0Pass + movd mm1,ebx + movq mm0,mm1 + psllq mm1,32 + por mm1,mm0 + shr ecx,1 + jz elemRest +elemLoop: + movq mm0,Q [esi] + paddd mm0,mm1 + movq Q [edi],mm0 + add esi,8 + add edi,8 + dec ecx + jnz elemLoop +elemRest: + emms + test [ctElems],1 + jz elemDone + mov eax,D [esi] + add eax,ebx + mov D [edi],eax +elemDone: + } +#else + const INDEX iVtx0Pass = pspo->spo_iVtx0Pass; + const INDEX *piSrc = pspo->spo_piElements; + for( INDEX iElem=0; iElemspo_pspoSucc) { + const INDEX ctTris = pspo->spo_ctElements/3; + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_TRIANGLEPASSESOPT, ctTris); + _sfStats.IncrementCounter( CStatForm::SCI_SCENE_TRIANGLEPASSES, ctTris); + _pGfx->gl_ctWorldTriangles += ctTris; + AddElements(pspo); + } + FlushElements(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_DRAWELEMENTS); +} + + +// calculate mip factor for a texture and adjust its mapping vectors +static BOOL RSMakeMipFactorAndAdjustMapping( ScenePolygon *pspo, INDEX iLayer) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_MAKEMIPFACTOR); + BOOL bRemoved = FALSE; + MEX mexTexSizeU, mexTexSizeV; + CMappingVectors &mv = pspo->spo_amvMapping[iLayer]; + + // texture map ? + if( iLayerspo_aubTextureFlags[iLayer] & STXF_BLEND_MASK; + CTextureData *ptd = (CTextureData*)pspo->spo_aptoTextures[iLayer]->GetData(); + mexTexSizeU = ptd->GetWidth(); + mexTexSizeV = ptd->GetHeight(); + + // check whether detail can be rejected (but don't reject colorized textures) + if( ulBlend==STXF_BLEND_SHADE && (ptd->td_ulFlags&TEX_EQUALIZED) + && (pspo->spo_acolColors[iLayer]&0xFFFFFF00)==0xFFFFFF00) + { // get nearest vertex Z distance from viewer and u and v steps + const FLOAT fZ = pspo->spo_fNearestZ; + const FLOAT f1oPZ1 = fZ / _ppr->ppr_PerspectiveRatios(1); + const FLOAT f1oPZ2 = fZ / _ppr->ppr_PerspectiveRatios(2); + const FLOAT fDUoDI = Abs( mv.mv_vU(1) *f1oPZ1); + const FLOAT fDUoDJ = Abs( mv.mv_vU(2) *f1oPZ2); + const FLOAT fDVoDI = Abs( mv.mv_vV(1) *f1oPZ1); + const FLOAT fDVoDJ = Abs( mv.mv_vV(2) *f1oPZ2); + // find mip factor and adjust removing of texture layer + const FLOAT fMaxDoD = Max( Max(fDUoDI,fDUoDJ), Max(fDVoDI,fDVoDJ)); + const INDEX iMipFactor = wld_iDetailRemovingBias + (((SLONG&)fMaxDoD)>>23) -127 +10; + const INDEX iLastMip = ptd->td_iFirstMipLevel + ptd->GetNoOfMips() -1; // determine last mipmap in texture + bRemoved = (iMipFactor>=iLastMip); + // check for detail texture showing + extern INDEX wld_bShowDetailTextures; + if( wld_bShowDetailTextures) { + if( iLayer==2) pspo->spo_acolColors[iLayer] = C_MAGENTA|255; + else pspo->spo_acolColors[iLayer] = C_CYAN |255; + } + } + // check if texture has been blended with low alpha + else bRemoved = (ulBlend==STXF_BLEND_ALPHA) && ((pspo->spo_acolColors[iLayer]&CT_AMASK)>>CT_ASHIFT)<3; + } + + // shadow map + else + { + mexTexSizeU = pspo->spo_psmShadowMap->sm_mexWidth; + mexTexSizeV = pspo->spo_psmShadowMap->sm_mexHeight; + } + + // adjust texture gradients + if( mexTexSizeU!=1024) { + const FLOAT fMul = 1024.0f /mexTexSizeU; // (no need to do shift-opt, because it won't speed up much!) + mv.mv_vU(1) *=fMul; mv.mv_vU(2) *=fMul; mv.mv_vU(3) *=fMul; + } + if( mexTexSizeV!=1024) { + const FLOAT fMul = 1024.0f /mexTexSizeV; + mv.mv_vV(1) *=fMul; mv.mv_vV(2) *=fMul; mv.mv_vV(3) *=fMul; + } + + // all done + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_MAKEMIPFACTOR); + return bRemoved; +} + + + +// Remove all polygons with no triangles from a list +static void RSRemoveDummyPolygons( ScenePolygon *pspoAll, ScenePolygon **ppspoNonDummy) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_REMOVEDUMMY); + *ppspoNonDummy = NULL; + // for all span polygons in list (remember one ahead to be able to reconnect them) + ScenePolygon *pspoNext; + for( ScenePolygon *pspoThis=pspoAll; pspoThis!=NULL; pspoThis=pspoNext) { + pspoNext = pspoThis->spo_pspoSucc; + // if the polygon has some triangles + if( pspoThis->spo_ctElements >0) { + // move it to the other list + pspoThis->spo_pspoSucc = *ppspoNonDummy; + *ppspoNonDummy = pspoThis; + } + } + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_REMOVEDUMMY); +} + + +// bin polygons into groups +static void RSBinToGroups( ScenePolygon *pspoFirst) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_BINTOGROUPS); + // clamp texture layers + extern INDEX wld_bTextureLayers; + BOOL bTextureLayer1 =(wld_bTextureLayers /100) || _bMultiPlayer; // must be enabled in multiplayer mode! + BOOL bTextureLayer2 = wld_bTextureLayers /10 %10; + BOOL bTextureLayer3 = wld_bTextureLayers %10; + wld_bTextureLayers = 0; + if( bTextureLayer1) wld_bTextureLayers += 100; + if( bTextureLayer2) wld_bTextureLayers += 10; + if( bTextureLayer3) wld_bTextureLayers += 1; + + // cache rendering states + bTextureLayer1 = bTextureLayer1 && wld_bRenderTextures; + bTextureLayer2 = bTextureLayer2 && wld_bRenderTextures; + bTextureLayer3 = bTextureLayer3 && wld_bRenderTextures; + + // clear all groups initially + memset( _apspoGroups, 0, sizeof(_apspoGroups)); + _ctGroupsCount = GROUPS_MINCOUNT; + + // for all span polygons in list (remember one ahead to be able to reconnect them) + for( ScenePolygon *pspoNext, *pspo=pspoFirst; pspo!=NULL; pspo=pspoNext) + { + pspoNext = pspo->spo_pspoSucc; + const INDEX ctTris = pspo->spo_ctElements/3; + ULONG ulBits = NONE; + + // if it has texture 1 active + if( pspo->spo_aptoTextures[0]!=NULL && bTextureLayer1) { + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_TRIANGLEPASSESORG, ctTris); + // prepare mapping for texture 0 and generate its mip factor + const BOOL bRemoved = RSMakeMipFactorAndAdjustMapping( pspo, 0); + if( !bRemoved) ulBits |= GF_TX0; // add if not removed + } else { + // flat fill is mutually exclusive with texture layer0 + _ctGroupsCount |= GF_FLAT; + ulBits |= GF_FLAT; + } + + // if it has texture 2 active + if( pspo->spo_aptoTextures[1]!=NULL && bTextureLayer2) { + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_TRIANGLEPASSESORG, ctTris); + // prepare mapping for texture 1 and generate its mip factor + const BOOL bRemoved = RSMakeMipFactorAndAdjustMapping( pspo, 1); + if( !bRemoved) { // add if not removed + if( pspo->spo_aubTextureFlags[1] & STXF_AFTERSHADOW) { + _ctGroupsCount |= GF_TA1; + ulBits |= GF_TA1; + } else { + ulBits |= GF_TX1; + } + } + } + // if it has texture 3 active + if( pspo->spo_aptoTextures[2]!=NULL && bTextureLayer3) { + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_TRIANGLEPASSESORG, ctTris); + // prepare mapping for texture 2 and generate its mip factor + const BOOL bRemoved = RSMakeMipFactorAndAdjustMapping( pspo, 2); + if( !bRemoved) { // add if not removed + if( pspo->spo_aubTextureFlags[2] & STXF_AFTERSHADOW) { + _ctGroupsCount |= GF_TA2; + ulBits |= GF_TA2; + } else { + ulBits |= GF_TX2; + } + } + } + + // if it has shadowmap active + if( pspo->spo_psmShadowMap!=NULL && wld_bRenderShadowMaps) { + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_TRIANGLEPASSESORG, ctTris); + // prepare shadow map + CShadowMap *psmShadow = pspo->spo_psmShadowMap; + psmShadow->Prepare(); + const BOOL bFlat = psmShadow->IsFlat(); + COLOR colFlat = psmShadow->sm_colFlat & 0xFFFFFF00; + const BOOL bOverbright = (colFlat & 0x80808000); + // only need to update poly color if shadowmap is flat + if( bFlat) { + if( !bOverbright || shd_iForceFlats==1) { + if( shd_bShowFlats) colFlat = C_mdMAGENTA; // show flat shadows? + else { // enhance light color to emulate overbrighting + if( !bOverbright) colFlat<<=1; + else { + UBYTE ubR,ubG,ubB; + ColorToRGB( colFlat, ubR,ubG,ubB); + ULONG ulR = ClampUp( ((ULONG)ubR)<<1, 255UL); + ULONG ulG = ClampUp( ((ULONG)ubG)<<1, 255UL); + ULONG ulB = ClampUp( ((ULONG)ubB)<<1, 255UL); + colFlat = RGBToColor(ulR,ulG,ulB); + } + } // mix color in the first texture layer + COLOR &colTotal = pspo->spo_acolColors[0]; + COLOR colLayer = pspo->spo_acolColors[3]; + if( colTotal==0xFFFFFFFF) colTotal = colLayer; + else if( colLayer!=0xFFFFFFFF) colTotal = MulColors( colTotal, colLayer); + if( colTotal==0xFFFFFFFF) colTotal = colFlat; + else colTotal = MulColors( colTotal, colFlat); + psmShadow->MarkDrawn(); + } + else { + // need to update poly color if shadowmap is flat and overbrightened + COLOR &colTotal = pspo->spo_acolColors[3]; + if( shd_bShowFlats) colFlat = C_mdBLUE; // overbrightened! + if( colTotal==0xFFFFFFFF) colTotal = colFlat; + else colTotal = MulColors( colTotal, colFlat); + ulBits |= GF_SHD; // mark the need for shadow layer + } + } else { + // prepare mapping for shadowmap and generate its mip factor + RSMakeMipFactorAndAdjustMapping( pspo, SHADOWTEXTURE); + ulBits |= GF_SHD; + } + } + + // if it has fog active + if( pspo->spo_ulFlags&SPOF_RENDERFOG) { + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_TRIANGLEPASSESORG, ctTris); + _ctGroupsCount |= GF_FOG; + ulBits |= GF_FOG; + } + // if it has haze active + if( pspo->spo_ulFlags&SPOF_RENDERHAZE) { + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_TRIANGLEPASSESORG, ctTris); + _ctGroupsCount |= GF_HAZE; + ulBits |= GF_HAZE; + } + + // if it is selected + if( pspo->spo_ulFlags&SPOF_SELECTED) { + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_TRIANGLEPASSESORG, ctTris); + _ctGroupsCount |= GF_SEL; + ulBits |= GF_SEL; + } + + // if it is transparent + if( pspo->spo_ulFlags&SPOF_TRANSPARENT) { + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_TRIANGLEPASSESORG, ctTris); + _ctGroupsCount |= GF_KEY; + ulBits |= GF_KEY; + } + + // in case of at least one layer, add it to proper group + if( ulBits) { + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_TRIANGLES, ctTris); + pspo->spo_pspoSucc = _apspoGroups[ulBits]; + _apspoGroups[ulBits] = pspo; + } + } + + // determine maximum used groups + ASSERT( _ctGroupsCount); + __asm { + mov eax,2 + bsr ecx,D [_ctGroupsCount] + shl eax,cl + mov D [_ctGroupsCount],eax + } + + // done with bining + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_BINTOGROUPS); +} + + + +// bin polygons that can use dual-texturing +static void RSBinByDualTexturing( ScenePolygon *pspoGroup, INDEX iLayer1, INDEX iLayer2, + ScenePolygon **ppspoST, ScenePolygon **ppspoMT) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_BINBYMULTITEXTURING); + *ppspoST = NULL; + *ppspoMT = NULL; + // for all span polygons in list (remember one ahead to be able to reconnect them) + for( ScenePolygon *pspoNext, *pspo=pspoGroup; pspo!=NULL; pspo=pspoNext) + { + pspoNext = pspo->spo_pspoSucc; + // if first texture is opaque or shade and second layer is shade + if( ((pspo->spo_aubTextureFlags[iLayer1]&STXF_BLEND_MASK)==STXF_BLEND_OPAQUE + || (pspo->spo_aubTextureFlags[iLayer1]&STXF_BLEND_MASK)==STXF_BLEND_SHADE) + && (pspo->spo_aubTextureFlags[iLayer2]&STXF_BLEND_MASK)==STXF_BLEND_SHADE) { + // can be merged, so put to multi-texture + pspo->spo_pspoSucc = *ppspoMT; + *ppspoMT = pspo; + } else { + // cannot be merged, so put to single-texture + pspo->spo_pspoSucc = *ppspoST; + *ppspoST = pspo; + } + } + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_BINBYMULTITEXTURING); +} + + +// bin polygons that can use triple-texturing +static void RSBinByTripleTexturing( ScenePolygon *pspoGroup, INDEX iLayer2, INDEX iLayer3, + ScenePolygon **ppspoST, ScenePolygon **ppspoMT) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_BINBYMULTITEXTURING); + *ppspoST = NULL; + *ppspoMT = NULL; + // for all span polygons in list (remember one ahead to be able to reconnect them) + for( ScenePolygon *pspoNext, *pspo=pspoGroup; pspo!=NULL; pspo=pspoNext) + { + pspoNext = pspo->spo_pspoSucc; + // if texture is shade and colors allow merging + if( (pspo->spo_aubTextureFlags[iLayer3]&STXF_BLEND_MASK)==STXF_BLEND_SHADE) { + // can be merged, so put to multi-texture + pspo->spo_pspoSucc = *ppspoMT; + *ppspoMT = pspo; + } else { + // cannot be merged, so put to single-texture + pspo->spo_pspoSucc = *ppspoST; + *ppspoST = pspo; + } + } + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_BINBYMULTITEXTURING); +} + + +// bin polygons that can use quad-texturing +static void RSBinByQuadTexturing( ScenePolygon *pspoGroup, ScenePolygon **ppspoST, ScenePolygon **ppspoMT) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_BINBYMULTITEXTURING); + *ppspoST = NULL; + *ppspoMT = pspoGroup; + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_BINBYMULTITEXTURING); +} + + +// check if all layers in all shadow maps are up to date +static void RSCheckLayersUpToDate( ScenePolygon *pspoFirst) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_CHECKLAYERSUPTODATE); + // for all span polygons in list + for( ScenePolygon *pspo=pspoFirst; pspo!=NULL; pspo=pspo->spo_pspoSucc) { + if( pspo->spo_psmShadowMap!=NULL) pspo->spo_psmShadowMap->CheckLayersUpToDate(); + } + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_CHECKLAYERSUPTODATE); +} + + +// prepare parameters individual to a polygon texture +inline void RSSetTextureWrapping( ULONG ulFlags) +{ + gfxSetTextureWrapping( (ulFlags&STXF_CLAMPU) ? GFX_CLAMP : GFX_REPEAT, + (ulFlags&STXF_CLAMPV) ? GFX_CLAMP : GFX_REPEAT); +} + + +// prepare parameters individual to a polygon texture +static void RSSetInitialTextureParameters(void) +{ + _ulLastFlags[0] = STXF_BLEND_OPAQUE; + _ulLastBlends[0] = STXF_BLEND_OPAQUE; + _iLastFrameNo[0] = 0; + _ptdLastTex[0] = NULL; + gfxSetTextureModulation(1); + gfxDisableBlend(); +} + + +static void RSSetTextureParameters( ULONG ulFlags) +{ + // if blend flags have changed + ULONG ulBlendFlags = ulFlags&STXF_BLEND_MASK; + if( _ulLastBlends[0] != ulBlendFlags) + { // determine new texturing mode + switch( ulBlendFlags) { + case STXF_BLEND_OPAQUE: // opaque texturing + gfxDisableBlend(); + break; + case STXF_BLEND_ALPHA: // blend using texture alpha + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + break; + case STXF_BLEND_ADD: // add to screen + gfxEnableBlend(); + gfxBlendFunc( GFX_ONE, GFX_ONE); + break; + default: // screen*texture*2 + ASSERT( ulBlendFlags==STXF_BLEND_SHADE); + gfxEnableBlend(); + gfxBlendFunc( GFX_DST_COLOR, GFX_SRC_COLOR); + break; + } + // remember new flags + _ulLastBlends[0] = ulFlags; + } +} + + +// prepare initial parameters for polygon texture +static void RSSetInitialTextureParametersMT(void) +{ + INDEX i; + // reset bleding modes + for( i=0; ispo_pspoSucc) + { + // create new vertices for that polygon in per-pass array + const INDEX ctVtx = pspo->spo_ctVtx; + pspo->spo_iVtx0Pass = _avtxPass.Count(); + GFXVertex3 *pvtxScene = &_avtxScene[pspo->spo_iVtx0]; + GFXVertex4 *pvtxPass = _avtxPass.Push(ctVtx); + + // copy the vertex coordinates + for( INDEX iVtx=0; iVtxspo_pspoSucc) { + col = ByteSwap( AdjustColor( pspo->spo_cColor|ubAlpha, _slTexHueShift, _slTexSaturation)); + pcol = &_acolPass[pspo->spo_iVtx0Pass]; + for( INDEX i=0; ispo_ctVtx; i++) pcol[i].abgr = col; + } + gfxSetColorArray( &_acolPass[0]); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_SETCOLORS); +} + + +static void RSSetConstantColors( COLOR col) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_SETCOLORS); + col = ByteSwap( AdjustColor( col, _slTexHueShift, _slTexSaturation)); + GFXColor *pcol = &_acolPass[0]; + for( INDEX i=0; i<_acolPass.Count(); i++) pcol[i].abgr = col; + gfxSetColorArray( &_acolPass[0]); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_SETCOLORS); +} + + +static void RSSetTextureColors( ScenePolygon *pspoGroup, ULONG ulLayerMask) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_SETCOLORS); + ASSERT( !(ulLayerMask & (GF_TA1|GF_TA2|GF_FOG|GF_HAZE|GF_SEL))); + // for all scene polygons in list + COLOR colLayer, colTotal; + for( ScenePolygon *pspo = pspoGroup; pspo != NULL; pspo = pspo->spo_pspoSucc) + { // adjust hue/saturation and set colors + colTotal = C_WHITE|CT_OPAQUE; + if( ulLayerMask&GF_TX0) { + colLayer = AdjustColor( pspo->spo_acolColors[0], _slTexHueShift, _slTexSaturation); + if( colLayer!=0xFFFFFFFF) colTotal = MulColors( colTotal, colLayer); + } + if( ulLayerMask&GF_TX1) { + colLayer = AdjustColor( pspo->spo_acolColors[1], _slTexHueShift, _slTexSaturation); + if( colLayer!=0xFFFFFFFF) colTotal = MulColors( colTotal, colLayer); + } + if( ulLayerMask&GF_TX2) { + colLayer = AdjustColor( pspo->spo_acolColors[2], _slTexHueShift, _slTexSaturation); + if( colLayer!=0xFFFFFFFF) colTotal = MulColors( colTotal, colLayer); + } + if( ulLayerMask&GF_SHD) { + colLayer = AdjustColor( pspo->spo_acolColors[3], _slShdHueShift, _slShdSaturation); + if( colLayer!=0xFFFFFFFF) colTotal = MulColors( colTotal, colLayer); + } + // store + colTotal = ByteSwap(colTotal); + GFXColor *pcol= &_acolPass[pspo->spo_iVtx0Pass]; + for( INDEX i=0; ispo_ctVtx; i++) pcol[i].abgr = colTotal; + } + // set color array + gfxSetColorArray( &_acolPass[0]); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_SETCOLORS); +} + + +// make texture coordinates for one texture in all polygons in group +static INDEX _iLastUnit = -1; +static void RSSetTextureCoords( ScenePolygon *pspoGroup, INDEX iLayer, INDEX iUnit) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_SETTEXCOORDS); + // eventualy switch texture unit + if( _iLastUnit != iUnit) { + gfxSetTextureUnit(iUnit); + gfxEnableTexture(); + _iLastUnit = iUnit; + } + + // generate tex coord for all scene polygons in list + const FLOATmatrix3D &mViewer = _ppr->pr_ViewerRotationMatrix; + const INDEX iMappingOffset = iLayer * sizeof(CMappingVectors); + + for( ScenePolygon *pspo=pspoGroup; pspo!=NULL; pspo=pspo->spo_pspoSucc) + { + ASSERT( pspo->spo_ctVtx>0); + const FLOAT3D &vN = ((CBrushPolygon*)pspo->spo_pvPolygon)->bpo_pbplPlane->bpl_pwplWorking->wpl_plView; + const GFXVertex *pvtx = &_avtxPass[pspo->spo_iVtx0Pass]; + GFXTexCoord *ptex = &_atexPass[iUnit][pspo->spo_iVtx0Pass]; + + // reflective mapping? + if( pspo->spo_aubTextureFlags[iLayer] & STXF_REFLECTION) { + for( INDEX i=0; ispo_ctVtx; i++) { + const FLOAT fNorm = 1.0f / sqrt(pvtx[i].x*pvtx[i].x + pvtx[i].y*pvtx[i].y + pvtx[i].z*pvtx[i].z); + const FLOAT fVx = pvtx[i].x *fNorm; + const FLOAT fVy = pvtx[i].y *fNorm; + const FLOAT fVz = pvtx[i].z *fNorm; + const FLOAT fNV = fVx*vN(1) + fVy*vN(2) + fVz*vN(3); + const FLOAT fRVx = fVx - 2*vN(1)*fNV; + const FLOAT fRVy = fVy - 2*vN(2)*fNV; + const FLOAT fRVz = fVz - 2*vN(3)*fNV; + const FLOAT fRVxT = fRVx*mViewer(1,1) + fRVy*mViewer(2,1) + fRVz*mViewer(3,1); + const FLOAT fRVzT = fRVx*mViewer(1,3) + fRVy*mViewer(2,3) + fRVz*mViewer(3,3); + ptex[i].s = fRVxT*0.5f +0.5f; + ptex[i].t = fRVzT*0.5f +0.5f; + } + // advance to next polygon + continue; + } + + // diffuse mapping + const FLOAT3D &vO = pspo->spo_amvMapping[iLayer].mv_vO; + +#if ASMOPT == 1 + __asm { + mov esi,D [pspo] + mov edi,D [iMappingOffset] + lea eax,[esi].spo_amvMapping[edi].mv_vO + lea ebx,[esi].spo_amvMapping[edi].mv_vU + lea ecx,[esi].spo_amvMapping[edi].mv_vV + mov edx,D [esi].spo_ctVtx + mov esi,D [pvtx] + mov edi,D [ptex] +vtxLoop: + fld D [ebx+0] + fld D [esi]GFXVertex.x + fsub D [eax+0] + fmul st(1),st(0) + fmul D [ecx+0] // vV(1)*fDX, vU(1)*fDX + fld D [ebx+4] + fld D [esi]GFXVertex.y + fsub D [eax+4] + fmul st(1),st(0) + fmul D [ecx+4] // vV(2)*fDY, vU(2)*fDY, vV(1)*fDX, vU(1)*fDX + fld D [ebx+8] + fld D [esi]GFXVertex.z + fsub D [eax+8] + fmul st(1),st(0) + fmul D [ecx+8] // vV(3)*fDZ, vU(3)*fDZ, vV(2)*fDY, vU(2)*fDY, vV(1)*fDX, vU(1)*fDX + fxch st(5) + faddp st(3),st(0) // vU(3)*fDZ, vV(2)*fDY, vU(1)*fDX+vU(2)*fDY, vV(1)*fDX, vV(3)*fDZ + fxch st(1) + faddp st(3),st(0) // vU(3)*fDZ, vU(1)*fDX+vU(2)*fDY, vV(1)*fDX+vV(2)*fDY, vV(3)*fDZ + faddp st(1),st(0) // vU(1)*fDX+vU(2)*fDY+vU(3)*fDZ, vV(1)*fDX+vV(2)*fDY, vV(3)*fDZ + fxch st(1) + faddp st(2),st(0) // vU(1)*fDX+vU(2)*fDY+vU(3)*fDZ, vV(1)*fDX+vV(2)*fDY+vV(3)*fDZ + fstp D [edi]GFXTexCoord.s + fstp D [edi]GFXTexCoord.t + add esi,4*4 + add edi,2*4 + dec edx + jnz vtxLoop + } +#else + const FLOAT3D &vO = pspo->spo_amvMapping[iLayer].mv_vO; + const FLOAT3D &vU = pspo->spo_amvMapping[iLayer].mv_vU; + const FLOAT3D &vV = pspo->spo_amvMapping[iLayer].mv_vV; + for( INDEX i=0; ispo_ctVtx; i++) { + const FLOAT fDX = pvtx[i].x -vO(1); + const FLOAT fDY = pvtx[i].y -vO(2); + const FLOAT fDZ = pvtx[i].z -vO(3); + ptex[i].s = vU(1)*fDX + vU(2)*fDY + vU(3)*fDZ; + ptex[i].t = vV(1)*fDX + vV(2)*fDY + vV(3)*fDZ; + } +#endif + } + + // init array + gfxSetTexCoordArray( &_atexPass[iUnit][0], FALSE); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_SETTEXCOORDS); +} + + + +// make fog texture coordinates for all polygons in group +static void RSSetFogCoordinates( ScenePolygon *pspoGroup) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_SETTEXCOORDS); + // for all scene polygons in list + for( ScenePolygon *pspo=pspoGroup; pspo!=NULL; pspo=pspo->spo_pspoSucc) { + const GFXVertex *pvtx = &_avtxPass[pspo->spo_iVtx0Pass]; + GFXTexCoord *ptex = &_atexPass[0][pspo->spo_iVtx0Pass]; + for( INDEX i=0; ispo_ctVtx; i++) { + ptex[i].s = pvtx[i].z *_fFogMul; + ptex[i].t = (_fog_vHDirView(1)*pvtx[i].x + _fog_vHDirView(2)*pvtx[i].y + + _fog_vHDirView(3)*pvtx[i].z + _fog_fAddH) * _fog_fMulH; + } + } + gfxSetTexCoordArray( &_atexPass[0][0], FALSE); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_SETTEXCOORDS); +} + + +// make haze texture coordinates for all polygons in group +static void RSSetHazeCoordinates( ScenePolygon *pspoGroup) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_SETTEXCOORDS); + // for all scene polygons in list + for( ScenePolygon *pspo=pspoGroup; pspo!=NULL; pspo=pspo->spo_pspoSucc) { + const GFXVertex *pvtx = &_avtxPass[pspo->spo_iVtx0Pass]; + GFXTexCoord *ptex = &_atexPass[0][pspo->spo_iVtx0Pass]; + for( INDEX i=0; ispo_ctVtx; i++) { + ptex[i].s = (pvtx[i].z + _fHazeAdd) *_fHazeMul; + ptex[i].t = 0; + } + } + gfxSetTexCoordArray( &_atexPass[0][0], FALSE); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_SETTEXCOORDS); +} + + +// render textures for all triangles in polygon list +static void RSRenderTEX( ScenePolygon *pspoFirst, INDEX iLayer) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_RENDERTEXTURES); + RSSetInitialTextureParameters(); + + // for all span polygons in list + for( ScenePolygon *pspo=pspoFirst; pspo!=NULL; pspo=pspo->spo_pspoSucc) + { + ASSERT(pspo->spo_aptoTextures[iLayer]!=NULL); + CTextureData *ptdTextureData = (CTextureData*)pspo->spo_aptoTextures[iLayer]->GetData(); + const INDEX iFrameNo = pspo->spo_aptoTextures[iLayer]->GetFrame(); + + if( _ptdLastTex[0] != ptdTextureData + || _ulLastFlags[0] != pspo->spo_aubTextureFlags[iLayer] + || _iLastFrameNo[0] != iFrameNo) { + // flush + FlushElements(); + _ptdLastTex[0] = ptdTextureData; + _ulLastFlags[0] = pspo->spo_aubTextureFlags[iLayer]; + _iLastFrameNo[0] = iFrameNo; + // set texture parameters if needed + RSSetTextureWrapping( pspo->spo_aubTextureFlags[iLayer]); + RSSetTextureParameters( pspo->spo_aubTextureFlags[iLayer]); + // prepare texture to be used by accelerator + ptdTextureData->SetAsCurrent(iFrameNo); + } + // render all triangles + AddElements(pspo); + } + // flush leftovers + FlushElements(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_RENDERTEXTURES); +} + + +// render shadows for all triangles in polygon list +static void RSRenderSHD( ScenePolygon *pspoFirst) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_RENDERSHADOWS); + + RSSetInitialTextureParameters(); + // for all span polygons in list + for( ScenePolygon *pspo = pspoFirst; pspo != NULL; pspo = pspo->spo_pspoSucc) + { + // get shadow map for the polygon + CShadowMap *psmShadow = pspo->spo_psmShadowMap; + ASSERT( psmShadow!=NULL); // shadows have been already sorted out + + // set texture parameters if needed + RSSetTextureWrapping( pspo->spo_aubTextureFlags[SHADOWTEXTURE]); + RSSetTextureParameters( pspo->spo_aubTextureFlags[SHADOWTEXTURE]); + + // upload the shadow to accelerator memory + psmShadow->SetAsCurrent(); + + // batch and render triangles + AddElements(pspo); + FlushElements(); + } + // done + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_RENDERSHADOWS); +} + + +// render texture and shadow for all triangles in polygon list +static void RSRenderTEX_SHD( ScenePolygon *pspoFirst, INDEX iLayer) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_RENDERMT); + RSSetInitialTextureParametersMT(); + + // for all span polygons in list + for( ScenePolygon *pspo=pspoFirst; pspo!=NULL; pspo=pspo->spo_pspoSucc) + { + // render batched triangles + FlushElements(); + ASSERT( pspo->spo_aptoTextures[iLayer]!=NULL && pspo->spo_psmShadowMap!=NULL); + + // upload the shadow to accelerator memory + gfxSetTextureUnit(1); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[SHADOWTEXTURE]); + pspo->spo_psmShadowMap->SetAsCurrent(); + + // prepare texture to be used by accelerator + CTextureData *ptd = (CTextureData*)pspo->spo_aptoTextures[iLayer]->GetData(); + const INDEX iFrameNo = pspo->spo_aptoTextures[iLayer]->GetFrame(); + + gfxSetTextureUnit(0); + if( _ptdLastTex[0]!=ptd || _iLastFrameNo[0]!=iFrameNo || _ulLastFlags[0]!=pspo->spo_aubTextureFlags[iLayer]) { + _ptdLastTex[0]=ptd; _iLastFrameNo[0]=iFrameNo; _ulLastFlags[0]=pspo->spo_aubTextureFlags[iLayer]; + RSSetTextureWrapping( pspo->spo_aubTextureFlags[iLayer]); + ptd->SetAsCurrent(iFrameNo); + // set rendering parameters if needed + RSSetTextureParametersMT( pspo->spo_aubTextureFlags[iLayer]); + } + // batch triangles + AddElements(pspo); + } + + // flush leftovers + FlushElements(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_RENDERMT); +} + + +// render two textures for all triangles in polygon list +static void RSRender2TEX( ScenePolygon *pspoFirst, INDEX iLayer2) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_RENDERMT); + RSSetInitialTextureParametersMT(); + + // for all span polygons in list + for( ScenePolygon *pspo=pspoFirst; pspo!=NULL; pspo=pspo->spo_pspoSucc) + { + ASSERT( pspo->spo_aptoTextures[0]!=NULL && pspo->spo_aptoTextures[iLayer2]!=NULL); + CTextureData *ptd0 = (CTextureData*)pspo->spo_aptoTextures[0]->GetData(); + CTextureData *ptd1 = (CTextureData*)pspo->spo_aptoTextures[iLayer2]->GetData(); + const INDEX iFrameNo0 = pspo->spo_aptoTextures[0]->GetFrame(); + const INDEX iFrameNo1 = pspo->spo_aptoTextures[iLayer2]->GetFrame(); + + if( _ptdLastTex[0]!=ptd0 || _iLastFrameNo[0]!=iFrameNo0 || _ulLastFlags[0]!=pspo->spo_aubTextureFlags[0] + || _ptdLastTex[1]!=ptd1 || _iLastFrameNo[1]!=iFrameNo1 || _ulLastFlags[1]!=pspo->spo_aubTextureFlags[iLayer2]) { + FlushElements(); + _ptdLastTex[0]=ptd0; _iLastFrameNo[0]=iFrameNo0; _ulLastFlags[0]=pspo->spo_aubTextureFlags[0]; + _ptdLastTex[1]=ptd1; _iLastFrameNo[1]=iFrameNo1; _ulLastFlags[1]=pspo->spo_aubTextureFlags[iLayer2]; + // upload the second texture to unit 1 + gfxSetTextureUnit(1); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[iLayer2]); + ptd1->SetAsCurrent(iFrameNo1); + // upload the first texture to unit 0 + gfxSetTextureUnit(0); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[0]); + ptd0->SetAsCurrent(iFrameNo0); + // set rendering parameters if needed + RSSetTextureParametersMT( pspo->spo_aubTextureFlags[0]); + } + // render all triangles + AddElements(pspo); + } + + // flush leftovers + FlushElements(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_RENDERMT); +} + + + +// render two textures and shadowmap for all triangles in polygon list +static void RSRender2TEX_SHD( ScenePolygon *pspoFirst, INDEX iLayer2) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_RENDERMT); + RSSetInitialTextureParametersMT(); + + // for all span polygons in list + for( ScenePolygon *pspo=pspoFirst; pspo!=NULL; pspo=pspo->spo_pspoSucc) + { + ASSERT( pspo->spo_aptoTextures[0]!=NULL + && pspo->spo_aptoTextures[iLayer2]!=NULL + && pspo->spo_psmShadowMap!=NULL); + + // render batched triangles + FlushElements(); + + // upload the shadow to accelerator memory + gfxSetTextureUnit(2); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[SHADOWTEXTURE]); + pspo->spo_psmShadowMap->SetAsCurrent(); + + // prepare textures to be used by accelerator + CTextureData *ptd0 = (CTextureData*)pspo->spo_aptoTextures[0]->GetData(); + CTextureData *ptd1 = (CTextureData*)pspo->spo_aptoTextures[iLayer2]->GetData(); + const INDEX iFrameNo0 = pspo->spo_aptoTextures[0]->GetFrame(); + const INDEX iFrameNo1 = pspo->spo_aptoTextures[iLayer2]->GetFrame(); + + gfxSetTextureUnit(0); + if( _ptdLastTex[0]!=ptd0 || _iLastFrameNo[0]!=iFrameNo0 || _ulLastFlags[0]!=pspo->spo_aubTextureFlags[0] + || _ptdLastTex[1]!=ptd1 || _iLastFrameNo[1]!=iFrameNo1 || _ulLastFlags[1]!=pspo->spo_aubTextureFlags[iLayer2]) { + _ptdLastTex[0]=ptd0; _iLastFrameNo[0]=iFrameNo0; _ulLastFlags[0]=pspo->spo_aubTextureFlags[0]; + _ptdLastTex[1]=ptd1; _iLastFrameNo[1]=iFrameNo1; _ulLastFlags[1]=pspo->spo_aubTextureFlags[iLayer2]; + // upload the second texture to unit 1 + gfxSetTextureUnit(1); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[iLayer2]); + ptd1->SetAsCurrent(iFrameNo1); + // upload the first texture to unit 0 + gfxSetTextureUnit(0); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[0]); + ptd0->SetAsCurrent(iFrameNo0); + // set rendering parameters if needed + RSSetTextureParametersMT( pspo->spo_aubTextureFlags[0]); + } + // render all triangles + AddElements(pspo); + } + + // flush leftovers + FlushElements(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_RENDERMT); +} + + + +// render three textures for all triangles in polygon list +static void RSRender3TEX( ScenePolygon *pspoFirst) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_RENDERMT); + RSSetInitialTextureParametersMT(); + + // for all span polygons in list + for( ScenePolygon *pspo=pspoFirst; pspo!=NULL; pspo=pspo->spo_pspoSucc) + { + ASSERT( pspo->spo_aptoTextures[0]!=NULL + && pspo->spo_aptoTextures[1]!=NULL + && pspo->spo_aptoTextures[2]!=NULL); + CTextureData *ptd0 = (CTextureData*)pspo->spo_aptoTextures[0]->GetData(); + CTextureData *ptd1 = (CTextureData*)pspo->spo_aptoTextures[1]->GetData(); + CTextureData *ptd2 = (CTextureData*)pspo->spo_aptoTextures[2]->GetData(); + const INDEX iFrameNo0 = pspo->spo_aptoTextures[0]->GetFrame(); + const INDEX iFrameNo1 = pspo->spo_aptoTextures[1]->GetFrame(); + const INDEX iFrameNo2 = pspo->spo_aptoTextures[2]->GetFrame(); + + if( _ptdLastTex[0]!=ptd0 || _iLastFrameNo[0]!=iFrameNo0 || _ulLastFlags[0]!=pspo->spo_aubTextureFlags[0] + || _ptdLastTex[1]!=ptd1 || _iLastFrameNo[1]!=iFrameNo1 || _ulLastFlags[1]!=pspo->spo_aubTextureFlags[1] + || _ptdLastTex[2]!=ptd2 || _iLastFrameNo[2]!=iFrameNo2 || _ulLastFlags[2]!=pspo->spo_aubTextureFlags[2]) { + FlushElements(); + _ptdLastTex[0]=ptd0; _iLastFrameNo[0]=iFrameNo0; _ulLastFlags[0]=pspo->spo_aubTextureFlags[0]; + _ptdLastTex[1]=ptd1; _iLastFrameNo[1]=iFrameNo1; _ulLastFlags[1]=pspo->spo_aubTextureFlags[1]; + _ptdLastTex[2]=ptd2; _iLastFrameNo[2]=iFrameNo2; _ulLastFlags[2]=pspo->spo_aubTextureFlags[2]; + // upload the third texture to unit 2 + gfxSetTextureUnit(2); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[2]); + ptd2->SetAsCurrent(iFrameNo2); + // upload the second texture to unit 1 + gfxSetTextureUnit(1); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[1]); + ptd1->SetAsCurrent(iFrameNo1); + // upload the first texture to unit 0 + gfxSetTextureUnit(0); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[0]); + ptd0->SetAsCurrent(iFrameNo0); + // set rendering parameters if needed + RSSetTextureParametersMT( pspo->spo_aubTextureFlags[0]); + } + // render all triangles + AddElements(pspo); + } + + // flush leftovers + FlushElements(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_RENDERMT); +} + + +// render three textures and shadowmap for all triangles in polygon list +static void RSRender3TEX_SHD( ScenePolygon *pspoFirst) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_RENDERMT); + RSSetInitialTextureParametersMT(); + + // for all span polygons in list + for( ScenePolygon *pspo=pspoFirst; pspo!=NULL; pspo=pspo->spo_pspoSucc) + { + ASSERT( pspo->spo_aptoTextures[0]!=NULL + && pspo->spo_aptoTextures[1]!=NULL + && pspo->spo_aptoTextures[2]!=NULL + && pspo->spo_psmShadowMap!=NULL); + + // render batched triangles + FlushElements(); + + // upload the shadow to accelerator memory + gfxSetTextureUnit(3); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[SHADOWTEXTURE]); + pspo->spo_psmShadowMap->SetAsCurrent(); + + // prepare textures to be used by accelerator + CTextureData *ptd0 = (CTextureData*)pspo->spo_aptoTextures[0]->GetData(); + CTextureData *ptd1 = (CTextureData*)pspo->spo_aptoTextures[1]->GetData(); + CTextureData *ptd2 = (CTextureData*)pspo->spo_aptoTextures[2]->GetData(); + const INDEX iFrameNo0 = pspo->spo_aptoTextures[0]->GetFrame(); + const INDEX iFrameNo1 = pspo->spo_aptoTextures[1]->GetFrame(); + const INDEX iFrameNo2 = pspo->spo_aptoTextures[2]->GetFrame(); + + gfxSetTextureUnit(0); + if( _ptdLastTex[0]!=ptd0 || _iLastFrameNo[0]!=iFrameNo0 || _ulLastFlags[0]!=pspo->spo_aubTextureFlags[0] + || _ptdLastTex[1]!=ptd1 || _iLastFrameNo[1]!=iFrameNo1 || _ulLastFlags[1]!=pspo->spo_aubTextureFlags[1] + || _ptdLastTex[2]!=ptd2 || _iLastFrameNo[2]!=iFrameNo2 || _ulLastFlags[2]!=pspo->spo_aubTextureFlags[2]) { + _ptdLastTex[0]=ptd0; _iLastFrameNo[0]=iFrameNo0; _ulLastFlags[0]=pspo->spo_aubTextureFlags[0]; + _ptdLastTex[1]=ptd1; _iLastFrameNo[1]=iFrameNo1; _ulLastFlags[1]=pspo->spo_aubTextureFlags[1]; + _ptdLastTex[2]=ptd2; _iLastFrameNo[2]=iFrameNo2; _ulLastFlags[2]=pspo->spo_aubTextureFlags[2]; + // upload the third texture to unit 2 + gfxSetTextureUnit(2); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[2]); + ptd2->SetAsCurrent(iFrameNo2); + // upload the second texture to unit 1 + gfxSetTextureUnit(1); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[1]); + ptd1->SetAsCurrent(iFrameNo1); + // upload the first texture to unit 0 + gfxSetTextureUnit(0); + RSSetTextureWrapping( pspo->spo_aubTextureFlags[0]); + ptd0->SetAsCurrent(iFrameNo0); + // set rendering parameters if needed + RSSetTextureParametersMT( pspo->spo_aubTextureFlags[0]); + } + // render all triangles + AddElements(pspo); + } + + // flush leftovers + FlushElements(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_RENDERMT); +} + + +// render fog for all affected triangles in polygon list +__forceinline void RSRenderFog( ScenePolygon *pspoFirst) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_RENDERFOG); + // for all scene polygons in list + for( ScenePolygon *pspo=pspoFirst; pspo!=NULL; pspo=pspo->spo_pspoSucc) + { // for all vertices in the polygon + const GFXTexCoord *ptex = &_atexPass[0][pspo->spo_iVtx0Pass]; + for( INDEX i=0; ispo_ctVtx; i++) { + // polygon is in fog, stop searching + if( InFog(ptex[i].t)) goto hasFog; + } + // hasn't got any fog, so skip it + continue; +hasFog: + // render all triangles + AddElements(pspo); + } + // all done + FlushElements(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_RENDERFOG); +} + + +// render haze for all affected triangles in polygon list +__forceinline void RSRenderHaze( ScenePolygon *pspoFirst) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_RENDERFOG); + // for all scene polygons in list + for( ScenePolygon *pspo=pspoFirst; pspo!=NULL; pspo=pspo->spo_pspoSucc) + { // for all vertices in the polygon + const GFXTexCoord *ptex = &_atexPass[0][pspo->spo_iVtx0Pass]; + for( INDEX i=0; ispo_ctVtx; i++) { + // polygon is in haze, stop searching + if( InHaze(ptex[i].s)) goto hasHaze; + } + // hasn't got any haze, so skip it + continue; +hasHaze: + // render all triangles + AddElements(pspo); + } + // all done + FlushElements(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_RENDERFOG); +} + + + +static void RSStartupFog(void) +{ + // upload fog texture + gfxSetTextureWrapping( GFX_CLAMP, GFX_CLAMP); + gfxSetTexture( _fog_ulTexture, _fog_tpLocal); + // prepare fog rendering parameters + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + // calculate fog mapping + _fFogMul = -1.0f / _fog_fp.fp_fFar; +} + + +static void RSStartupHaze(void) +{ + // upload haze texture + gfxEnableTexture(); + gfxSetTextureWrapping( GFX_CLAMP, GFX_CLAMP); + gfxSetTexture( _haze_ulTexture, _haze_tpLocal); + // prepare haze rendering parameters + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + // calculate haze mapping + _fHazeMul = -1.0f / (_haze_hp.hp_fFar - _haze_hp.hp_fNear); + _fHazeAdd = _haze_hp.hp_fNear; +} + + +// process one group of polygons +void RSRenderGroupInternal( ScenePolygon *pspoGroup, ULONG ulGroupFlags); +void RSRenderGroup( ScenePolygon *pspoGroup, ULONG ulGroupFlags, ULONG ulTestedFlags) +{ + // skip if the group is empty + if( pspoGroup==NULL) return; + ASSERT( !(ulTestedFlags&(GF_FOG|GF_HAZE))); // paranoia + + // if multitexturing is enabled (start with 2-layer MT) + if( _ctUsableTexUnits>=2) + { + // if texture 1 could be merged with shadow + if( !(ulTestedFlags&GF_TX0_SHD) + && (ulGroupFlags &GF_TX0) + && !(ulGroupFlags &GF_TX1) + && !(ulGroupFlags &GF_TX2) + && (ulGroupFlags &GF_SHD)) + { // bin polygons that can use the merge and those that cannot + ScenePolygon *pspoST, *pspoMT; + RSBinByDualTexturing( pspoGroup, 0, SHADOWTEXTURE, &pspoST, &pspoMT); + // process the two groups separately + ulTestedFlags |= GF_TX0_SHD; + RSRenderGroup( pspoST, ulGroupFlags, ulTestedFlags); + ulGroupFlags &= ~(GF_TX0|GF_SHD); + ulGroupFlags |= GF_TX0_SHD; + RSRenderGroup( pspoMT, ulGroupFlags, ulTestedFlags); + return; + } + + // if texture 1 could be merged with texture 2 + if( !(ulTestedFlags&GF_TX0_TX1) + && (ulGroupFlags &GF_TX0) + && (ulGroupFlags &GF_TX1)) + { // bin polygons that can use the merge and those that cannot + ScenePolygon *pspoST, *pspoMT; + RSBinByDualTexturing( pspoGroup, 0, 1, &pspoST, &pspoMT); + // process the two groups separately + ulTestedFlags |= GF_TX0_TX1; + RSRenderGroup( pspoST, ulGroupFlags, ulTestedFlags); + ulGroupFlags &= ~(GF_TX0|GF_TX1); + ulGroupFlags |= GF_TX0_TX1; + RSRenderGroup( pspoMT, ulGroupFlags, ulTestedFlags); + return; + } + + // if texture 1 could be merged with texture 3 + if( !(ulTestedFlags&GF_TX0_TX2) + && (ulGroupFlags &GF_TX0) + && !(ulGroupFlags &GF_TX1) + && (ulGroupFlags &GF_TX2)) + { // bin polygons that can use the merge and those that cannot + ScenePolygon *pspoST, *pspoMT; + RSBinByDualTexturing( pspoGroup, 0, 2, &pspoST, &pspoMT); + // process the two groups separately + ulTestedFlags |= GF_TX0_TX2; + RSRenderGroup( pspoST, ulGroupFlags, ulTestedFlags); + ulGroupFlags &= ~(GF_TX0|GF_TX2); + ulGroupFlags |= GF_TX0_TX2; + RSRenderGroup( pspoMT, ulGroupFlags, ulTestedFlags); + return; + } + + // if texture 3 could be merged with shadow + if( !(ulTestedFlags&GF_TX2_SHD) + && (ulGroupFlags &GF_TX0_TX1) + && (ulGroupFlags &GF_TX2) + && (ulGroupFlags &GF_SHD)) + { // bin polygons that can use the merge and those that cannot + ScenePolygon *pspoST, *pspoMT; + RSBinByDualTexturing( pspoGroup, 2, SHADOWTEXTURE, &pspoST, &pspoMT); + // process the two groups separately + ulTestedFlags |= GF_TX2_SHD; + RSRenderGroup( pspoST, ulGroupFlags, ulTestedFlags); + ulGroupFlags &= ~(GF_TX2|GF_SHD); + ulGroupFlags |= GF_TX2_SHD; + RSRenderGroup( pspoMT, ulGroupFlags, ulTestedFlags); + return; + } + } + + // 4-layer multitexturing? + if( _ctUsableTexUnits>=4) + { + // if texture 1 and 2 could be merged with 3 and shadow + if( !(ulTestedFlags&GF_TX0_TX1_TX2_SHD) + && (ulGroupFlags &GF_TX0_TX1) + && (ulGroupFlags &GF_TX2_SHD)) + { // bin polygons that can use the merge and those that cannot + ScenePolygon *pspoST, *pspoMT; + RSBinByQuadTexturing( pspoGroup, &pspoST, &pspoMT); + // process the two groups separately + ulTestedFlags |= GF_TX0_TX1_TX2_SHD; + RSRenderGroup( pspoST, ulGroupFlags, ulTestedFlags); + ulGroupFlags &= ~(GF_TX0_TX1|GF_TX2_SHD); + ulGroupFlags |= GF_TX0_TX1_TX2_SHD; + RSRenderGroup( pspoMT, ulGroupFlags, ulTestedFlags); + return; + } + } + + // 3-layer multitexturing? + if( _ctUsableTexUnits>=3) + { + // if texture 1 and 2 could be merged with 3 + if( !(ulTestedFlags&GF_TX0_TX1_TX2) + && (ulGroupFlags &GF_TX0_TX1) + && (ulGroupFlags &GF_TX2)) + { // bin polygons that can use the merge and those that cannot + ScenePolygon *pspoST, *pspoMT; + RSBinByTripleTexturing( pspoGroup, 1, 2, &pspoST, &pspoMT); + // process the two groups separately + ulTestedFlags |= GF_TX0_TX1_TX2; + RSRenderGroup( pspoST, ulGroupFlags, ulTestedFlags); + ulGroupFlags &= ~(GF_TX0_TX1|GF_TX2); + ulGroupFlags |= GF_TX0_TX1_TX2; + RSRenderGroup( pspoMT, ulGroupFlags, ulTestedFlags); + return; + } + + // if texture 1 and 2 could be merged with shadow + if( !(ulTestedFlags&GF_TX0_TX1_SHD) + && (ulGroupFlags &GF_TX0_TX1) + && !(ulGroupFlags &GF_TX2) + && (ulGroupFlags &GF_SHD)) + { // bin polygons that can use the merge and those that cannot + ScenePolygon *pspoST, *pspoMT; + RSBinByTripleTexturing( pspoGroup, 1, SHADOWTEXTURE, &pspoST, &pspoMT); + // process the two groups separately + ulTestedFlags |= GF_TX0_TX1_SHD; + RSRenderGroup( pspoST, ulGroupFlags, ulTestedFlags); + ulGroupFlags &= ~(GF_TX0_TX1|GF_SHD); + ulGroupFlags |= GF_TX0_TX1_SHD; + RSRenderGroup( pspoMT, ulGroupFlags, ulTestedFlags); + return; + } + + // if texture 1 and 3 could be merged with shadow + if( !(ulTestedFlags&GF_TX0_TX2_SHD) + && (ulGroupFlags &GF_TX0_TX2) + && !(ulGroupFlags &GF_TX1) + && (ulGroupFlags &GF_SHD)) + { // bin polygons that can use the merge and those that cannot + ScenePolygon *pspoST, *pspoMT; + RSBinByTripleTexturing( pspoGroup, 2, SHADOWTEXTURE, &pspoST, &pspoMT); + // process the two groups separately + ulTestedFlags |= GF_TX0_TX2_SHD; + RSRenderGroup( pspoST, ulGroupFlags, ulTestedFlags); + ulGroupFlags &= ~(GF_TX0_TX2|GF_SHD); + ulGroupFlags |= GF_TX0_TX2_SHD; + RSRenderGroup( pspoMT, ulGroupFlags, ulTestedFlags); + return; + } + } + + // render one group + extern INDEX ogl_iMaxBurstSize; + extern INDEX d3d_iMaxBurstSize; + ogl_iMaxBurstSize = Clamp( ogl_iMaxBurstSize, 0L, 9999L); + d3d_iMaxBurstSize = Clamp( d3d_iMaxBurstSize, 0L, 9999L); + const INDEX iMaxBurstSize = (eAPI==GAT_OGL) ? ogl_iMaxBurstSize : d3d_iMaxBurstSize; + + // if unlimited lock count + if( iMaxBurstSize==0) + { // render whole group + RSRenderGroupInternal( pspoGroup, ulGroupFlags); + } + // if lock count is specified + else + { // render group in segments + while( pspoGroup!=NULL) + { // find segment size + INDEX ctVtx = 0; + ScenePolygon *pspoThis = pspoGroup; + ScenePolygon *pspoLast = pspoGroup; + while( ctVtxspo_ctVtx; + pspoLast = pspoGroup; + pspoGroup = pspoGroup->spo_pspoSucc; + } // render one group segment + pspoLast->spo_pspoSucc = NULL; + RSRenderGroupInternal( pspoThis, ulGroupFlags); + } + } +} + + + +// internal group rendering routine +void RSRenderGroupInternal( ScenePolygon *pspoGroup, ULONG ulGroupFlags) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_RENDERGROUPINTERNAL); + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_RS_POLYGONGROUPS); + + // make vertex coordinates for all polygons in the group + RSMakeVertexCoordinates(pspoGroup); + // prepare vertex, texture and color arrays + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_LOCKARRAYS); + gfxSetVertexArray( &_avtxPass[0], _avtxPass.Count()); + if(CVA_bWorld) gfxLockArrays(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_LOCKARRAYS); + + // set alpha keying if required + if( ulGroupFlags & GF_KEY) gfxEnableAlphaTest(); + else gfxDisableAlphaTest(); + + _iLastUnit = 0; // reset mulitex unit change + BOOL bUsedMT = FALSE; + BOOL bUsesMT = ulGroupFlags & (GF_TX0_TX1 | GF_TX0_TX2 | GF_TX0_SHD | GF_TX2_SHD + | GF_TX0_TX1_TX2 | GF_TX0_TX1_SHD | GF_TX0_TX2_SHD + | GF_TX0_TX1_TX2_SHD); + // dual texturing + if( ulGroupFlags & GF_TX0_SHD) { + RSSetTextureCoords( pspoGroup, SHADOWTEXTURE, 1); + RSSetTextureCoords( pspoGroup, 0, 0); + RSSetTextureColors( pspoGroup, GF_TX0|GF_SHD); + RSRenderTEX_SHD( pspoGroup, 0); + bUsedMT = TRUE; + } + else if( ulGroupFlags & GF_TX0_TX1) { + RSSetTextureCoords( pspoGroup, 1, 1); + RSSetTextureCoords( pspoGroup, 0, 0); + RSSetTextureColors( pspoGroup, GF_TX0|GF_TX1); + RSRender2TEX( pspoGroup, 1); + bUsedMT = TRUE; + } + else if( ulGroupFlags & GF_TX0_TX2) { + RSSetTextureCoords( pspoGroup, 2, 1); + RSSetTextureCoords( pspoGroup, 0, 0); + RSSetTextureColors( pspoGroup, GF_TX0|GF_TX2); + RSRender2TEX( pspoGroup, 2); + bUsedMT = TRUE; + } + + // triple texturing + else if( ulGroupFlags & GF_TX0_TX1_TX2) { + RSSetTextureCoords( pspoGroup, 2, 2); + RSSetTextureCoords( pspoGroup, 1, 1); + RSSetTextureCoords( pspoGroup, 0, 0); + RSSetTextureColors( pspoGroup, GF_TX0|GF_TX1|GF_TX2); + RSRender3TEX( pspoGroup); + bUsedMT = TRUE; + } + else if( ulGroupFlags & GF_TX0_TX1_SHD) { + RSSetTextureCoords( pspoGroup, SHADOWTEXTURE, 2); + RSSetTextureCoords( pspoGroup, 1, 1); + RSSetTextureCoords( pspoGroup, 0, 0); + RSSetTextureColors( pspoGroup, GF_TX0|GF_TX1|GF_SHD); + RSRender2TEX_SHD( pspoGroup, 1); + bUsedMT = TRUE; + } + else if( ulGroupFlags & GF_TX0_TX2_SHD) { + RSSetTextureCoords( pspoGroup, SHADOWTEXTURE, 2); + RSSetTextureCoords( pspoGroup, 2, 1); + RSSetTextureCoords( pspoGroup, 0, 0); + RSSetTextureColors( pspoGroup, GF_TX0|GF_TX2|GF_SHD); + RSRender2TEX_SHD( pspoGroup, 2); + bUsedMT = TRUE; + } + + // quad texturing + else if( ulGroupFlags & GF_TX0_TX1_TX2_SHD) { + RSSetTextureCoords( pspoGroup, SHADOWTEXTURE, 3); + RSSetTextureCoords( pspoGroup, 2, 2); + RSSetTextureCoords( pspoGroup, 1, 1); + RSSetTextureCoords( pspoGroup, 0, 0); + RSSetTextureColors( pspoGroup, GF_TX0|GF_TX1|GF_TX2|GF_SHD); + RSRender3TEX_SHD( pspoGroup); + bUsedMT = TRUE; + } + + // if something was drawn and alpha keying was used + if( bUsedMT && (ulGroupFlags&GF_KEY)) { + // force z-buffer test to equal and disable subsequent alpha tests + gfxDepthFunc( GFX_EQUAL); + gfxDisableAlphaTest(); + } + + // dual texturing leftover + if( ulGroupFlags & GF_TX2_SHD) { + RSSetTextureCoords( pspoGroup, SHADOWTEXTURE, 1); + RSSetTextureCoords( pspoGroup, 2, 0); + RSSetTextureColors( pspoGroup, GF_TX2|GF_SHD); + RSRenderTEX_SHD( pspoGroup, 2); + bUsedMT = TRUE; + } + + ASSERT( !bUsedMT==!bUsesMT); + + // if some multi-tex units were used + if( bUsesMT) { + // disable them now + for( INDEX i=1; i<_ctUsableTexUnits; i++) { + gfxSetTextureUnit(i); + gfxDisableTexture(); + } + _iLastUnit = 0; + gfxSetTextureUnit(0); + } + + // if group has color for first layer + if( ulGroupFlags&GF_FLAT) + { // render colors + if( _bTranslucentPass) { + // set opacity to 50% + if( !wld_bRenderTextures) RSSetConstantColors( 0x3F3F3F7F); + else RSSetPolygonColors( pspoGroup, 0x7F); + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + } else { + // set opacity to 100% + if( !wld_bRenderTextures) RSSetConstantColors( 0x7F7F7FFF); + else RSSetPolygonColors( pspoGroup, CT_OPAQUE); + gfxDisableBlend(); + } + gfxDisableTexture(); + DrawAllElements( pspoGroup); + } + + // if group has texture for first layer + if( ulGroupFlags&GF_TX0) { + // render texture 0 + RSSetTextureCoords( pspoGroup, 0, 0); + RSSetTextureColors( pspoGroup, GF_TX0); + RSRenderTEX( pspoGroup, 0); + // eventually prepare subsequent layers for transparency + if( ulGroupFlags & GF_KEY) { + gfxDepthFunc( GFX_EQUAL); + gfxDisableAlphaTest(); + } + } + // if group has texture for second layer + if( ulGroupFlags & GF_TX1) { + // render texture 1 + RSSetTextureCoords( pspoGroup, 1, 0); + RSSetTextureColors( pspoGroup, GF_TX1); + RSRenderTEX( pspoGroup, 1); + } + // if group has texture for third layer + if( ulGroupFlags & GF_TX2) { + // render texture 2 + RSSetTextureCoords( pspoGroup, 2, 0); + RSSetTextureColors( pspoGroup, GF_TX2); + RSRenderTEX( pspoGroup, 2); + } + + // if group has shadow + if( ulGroupFlags & GF_SHD) { + // render shadow + RSSetTextureCoords( pspoGroup, SHADOWTEXTURE, 0); + RSSetTextureColors( pspoGroup, GF_SHD); + RSRenderSHD( pspoGroup); + } + + // if group has aftershadow texture for second layer + if( ulGroupFlags & GF_TA1) { + // render texture 1 + RSSetTextureCoords( pspoGroup, 1, 0); + RSSetTextureColors( pspoGroup, GF_TX1); + RSRenderTEX( pspoGroup, 1); + } + // if group has aftershadow texture for third layer + if( ulGroupFlags & GF_TA2) { + // render texture 2 + RSSetTextureCoords( pspoGroup, 2, 0); + RSSetTextureColors( pspoGroup, GF_TX2); + RSRenderTEX( pspoGroup, 2); + } + + // if group has fog + if( ulGroupFlags & GF_FOG) { + // render fog + RSStartupFog(); + RSSetConstantColors( _fog_fp.fp_colColor); + RSSetFogCoordinates( pspoGroup); + RSRenderFog( pspoGroup); + } + // if group has haze + if( ulGroupFlags & GF_HAZE) { + // render haze + RSStartupHaze(); + RSSetConstantColors( _haze_hp.hp_colColor); + RSSetHazeCoordinates( pspoGroup); + RSRenderHaze( pspoGroup); + } + + // reset depth function and alpha keying back + // (maybe it was altered for transparent polygon rendering) + gfxDepthFunc( GFX_LESS_EQUAL); + gfxDisableAlphaTest(); + + // if group has selection + if( ulGroupFlags & GF_SEL) { + // render selection + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + RSSetConstantColors( _colSelection|128); + gfxDisableTexture(); + DrawAllElements( pspoGroup); + } + + // render triangle wireframe if needed + extern INDEX wld_bShowTriangles; + if( wld_bShowTriangles) { + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + RSSetConstantColors( C_mdYELLOW|222); + gfxDisableTexture(); + // must write to front in z-buffer + gfxPolygonMode(GFX_LINE); + gfxEnableDepthTest(); + gfxEnableDepthWrite(); + gfxDepthFunc(GFX_ALWAYS); + gfxDepthRange( 0,0); + DrawAllElements(pspoGroup); + gfxDepthRange( _ppr->pr_fDepthBufferNear, _ppr->pr_fDepthBufferFar); + gfxDepthFunc(GFX_LESS_EQUAL); + if( _bTranslucentPass) gfxDisableDepthWrite(); + gfxPolygonMode(GFX_FILL); + } + + // all done + gfxUnlockArrays(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_RENDERGROUPINTERNAL); +} + + +static void RSPrepare(void) +{ + // set general params + gfxCullFace(GFX_NONE); + gfxEnableDepthTest(); + gfxEnableClipping(); +} + + +static void RSEnd(void) +{ + // reset unusual gfx API parameters + gfxSetTextureUnit(0); + gfxSetTextureModulation(1); +} + + +void RenderScene( CDrawPort *pDP, ScenePolygon *pspoFirst, CAnyProjection3D &prProjection, + COLOR colSelection, BOOL bTranslucent) +{ + // check API + eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_D3D || eAPI==GAT_NONE); +#else // SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_NONE); +#endif // SE1_D3D + if( eAPI!=GAT_OGL +#ifdef SE1_D3D + && eAPI!=GAT_D3D +#endif // SE1_D3D + ) return; + + // some cvars cannot be altered in multiplayer mode! + if( _bMultiPlayer) { + shd_bShowFlats = FALSE; + gfx_bRenderWorld = TRUE; + wld_bRenderShadowMaps = TRUE; + wld_bRenderTextures = TRUE; + wld_bRenderDetailPolygons = TRUE; + wld_bShowDetailTextures = FALSE; + wld_bShowTriangles = FALSE; + } + + // skip if not rendering world + if( !gfx_bRenderWorld) return; + + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RENDERSCENE); + + // remember input parameters + ASSERT( pDP != NULL); + _ppr = (CPerspectiveProjection3D*)&*prProjection; + _pDP = pDP; + _colSelection = colSelection; + _bTranslucentPass = bTranslucent; + + // clamp detail textures LOD biasing + wld_iDetailRemovingBias = Clamp( wld_iDetailRemovingBias, -9L, +9L); + + // set perspective projection + _pDP->SetProjection(prProjection); + + // adjust multi-texturing support (for clip-plane emulation thru texture units) + extern BOOL GFX_bClipPlane; // WATCHOUT: set by 'SetProjection()' ! + extern INDEX gap_iUseTextureUnits; + extern INDEX ogl_bAlternateClipPlane; + INDEX ctMaxUsableTexUnits = _pGfx->gl_ctTextureUnits; + if( eAPI==GAT_OGL && ogl_bAlternateClipPlane && GFX_bClipPlane && ctMaxUsableTexUnits>1) ctMaxUsableTexUnits--; + _ctUsableTexUnits = Clamp( gap_iUseTextureUnits, 1L, ctMaxUsableTexUnits); + + // prepare + RSPrepare(); + + // turn depth buffer writing on or off + if( bTranslucent) gfxDisableDepthWrite(); + else gfxEnableDepthWrite(); + + // remove all polygons with no triangles from the polygon list + ScenePolygon *pspoNonDummy; + RSRemoveDummyPolygons( pspoFirst, &pspoNonDummy); + + // check that layers of all shadows are up to date + RSCheckLayersUpToDate(pspoNonDummy); + + // bin polygons to groups by texture passes + RSBinToGroups(pspoNonDummy); + + // for each group + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RS_RENDERGROUP); + ASSERT( _apspoGroups[0]==NULL); // zero group must always be empty + for( INDEX iGroup=1; iGroup<_ctGroupsCount; iGroup++) { + // get the group polygon list and render it if not empty + ScenePolygon *pspoGroup = _apspoGroups[iGroup]; + if( pspoGroup!=NULL) RSRenderGroup( pspoGroup, iGroup, 0); + } + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RS_RENDERGROUP); + + // all done + RSEnd(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RENDERSCENE); +} + + +// renders only scene z-buffer +void RenderSceneZOnly( CDrawPort *pDP, ScenePolygon *pspoFirst, CAnyProjection3D &prProjection) +{ + if( _bMultiPlayer) gfx_bRenderWorld = 1; + if( !gfx_bRenderWorld) return; + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RENDERSCENE_ZONLY); + + // set perspective projection + ASSERT(pDP!=NULL); + pDP->SetProjection(prProjection); + + // prepare + RSPrepare(); + + // set for depth-only rendering + const ULONG ulCurrentColorMask = gfxGetColorMask(); + gfxSetColorMask(NONE); + gfxEnableDepthTest(); + gfxEnableDepthWrite(); + gfxDisableTexture(); + + // make vertex coordinates for all polygons in the group and render the polygons + RSMakeVertexCoordinates(pspoFirst); + gfxSetVertexArray( &_avtxPass[0], _avtxPass.Count()); + gfxDisableColorArray(); + DrawAllElements(pspoFirst); + + // restore color masking + gfxSetColorMask( ulCurrentColorMask); + RSEnd(); + + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RENDERSCENE_ZONLY); +} + + +// renders flat background of the scene +void RenderSceneBackground(CDrawPort *pDP, COLOR col) +{ + if( _bMultiPlayer) gfx_bRenderWorld = 1; + if( !gfx_bRenderWorld) return; + + // set orthographic projection + ASSERT(pDP!=NULL); + pDP->SetOrtho(); + + _pfGfxProfile.StartTimer( CGfxProfile::PTI_RENDERSCENE_BCG); + // prepare + gfxEnableDepthTest(); + gfxDisableDepthWrite(); + gfxDisableBlend(); + gfxDisableAlphaTest(); + gfxDisableTexture(); + gfxEnableClipping(); + + col = AdjustColor( col, _slTexHueShift, _slTexSaturation); + GFXColor glcol(col|CT_OPAQUE); + const INDEX iW = pDP->GetWidth(); + const INDEX iH = pDP->GetHeight(); + + // set arrays + gfxResetArrays(); + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + pvtx[0].x = 0; pvtx[0].y = 0; pvtx[0].z = 1; + pvtx[1].x = 0; pvtx[1].y = iH; pvtx[1].z = 1; + pvtx[2].x = iW; pvtx[2].y = iH; pvtx[2].z = 1; + pvtx[3].x = iW; pvtx[3].y = 0; pvtx[3].z = 1; + pcol[0] = glcol; + pcol[1] = glcol; + pcol[2] = glcol; + pcol[3] = glcol; + + // render + _pGfx->gl_ctWorldTriangles += 2; + gfxFlushQuads(); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_RENDERSCENE_BCG); +} diff --git a/Sources/Engine/Graphics/Fog.cpp b/Sources/Engine/Graphics/Fog.cpp new file mode 100644 index 0000000..f73ae71 --- /dev/null +++ b/Sources/Engine/Graphics/Fog.cpp @@ -0,0 +1,396 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + +// current fog parameters +BOOL _fog_bActive = FALSE; +CFogParameters _fog_fp; +CTexParams _fog_tpLocal; + +FLOAT _fog_fViewerH = 0.0f; +FLOAT3D _fog_vViewPosAbs; +FLOAT3D _fog_vViewDirAbs; +FLOAT3D _fog_vHDirAbs; +FLOAT3D _fog_vHDirView; +FLOAT _fog_fMulZ=0; +FLOAT _fog_fMulH=0; +FLOAT _fog_fAddH=0; +ULONG _fog_ulAlpha=0; +ULONG _fog_ulTexture=0; +ULONG _fog_ulFormat=0; + +PIX _fog_pixSizeH=0; +PIX _fog_pixSizeL=0; +FLOAT _fog_fStart=0; // where in height fog starts +FLOAT _fog_fEnd=0; // where in height fog ends +UBYTE *_fog_pubTable=NULL; + + +extern INDEX gfx_bRenderFog; +extern BOOL _bMultiPlayer; + + +// prepares fog and haze parameters and eventualy converts texture +ULONG PrepareTexture( UBYTE *pubTexture, PIX pixSizeI, PIX pixSizeJ) +{ + // need to upload from RGBA format + const PIX pixTextureSize = pixSizeI*pixSizeJ; + __asm { + mov esi,D [pubTexture] + mov edi,D [pubTexture] + mov ecx,D [pixTextureSize] + lea edi,[esi+ecx] +pixLoop: + movzx eax,B [esi] + or eax,0xFFFFFF00 + bswap eax + mov D [edi],eax + add esi,1 + add edi,4 + dec ecx + jnz pixLoop + } + // determine internal format + extern INDEX gap_bAllowGrayTextures; + extern INDEX tex_bFineFog; + if( gap_bAllowGrayTextures) return TS.ts_tfLA8; + if( tex_bFineFog) return TS.ts_tfRGBA8; + return TS.ts_tfRGBA4; +} + + + +// start fog with given parameters +void StartFog( CFogParameters &fp, const FLOAT3D &vViewPosAbs, const FLOATmatrix3D &mAbsToView) +{ + ASSERT( !_fog_bActive); + if( _bMultiPlayer) gfx_bRenderFog = 1; + if( !gfx_bRenderFog) return; + _fog_bActive = TRUE; + + _fog_fp = fp; + _fog_vHDirAbs = -_fog_fp.fp_vFogDir; + _fog_vViewPosAbs = vViewPosAbs; + _fog_vViewDirAbs(1) = -mAbsToView(3, 1); + _fog_vViewDirAbs(2) = -mAbsToView(3, 2); + _fog_vViewDirAbs(3) = -mAbsToView(3, 3); + _fog_fViewerH = _fog_vViewPosAbs%-_fog_fp.fp_vFogDir; + _fog_vHDirView = _fog_vHDirAbs*mAbsToView; + // calculate fog mapping factors + _fog_fMulZ = 1/(_fog_fp.fp_fFar); + _fog_fMulH = 1/(_fog_fp.fp_fH3-_fog_fp.fp_fH0); + _fog_fAddH = _fog_fp.fp_fH3+_fog_fViewerH; + + // calculate fog table size wanted + extern INDEX tex_iFogSize; + tex_iFogSize = Clamp( tex_iFogSize, 4L, 8L); + PIX pixSizeH = ClampUp( _fog_fp.fp_iSizeH, 1L<>CT_ASHIFT; + + // get parameters + const FLOAT fH0 = _fog_fp.fp_fH0; // lowest point in LUT ->texture t=1 + const FLOAT fH1 = _fog_fp.fp_fH1; // bottom of fog in LUT + const FLOAT fH2 = _fog_fp.fp_fH2; // top of fog in LUT + const FLOAT fH3 = _fog_fp.fp_fH3; // highest point in LUT ->texture t=0 + const FLOAT fFar = _fog_fp.fp_fFar; // farthest point in LUT ->texture s=1 + const FLOAT fDensity = _fog_fp.fp_fDensity; + const AttenuationType at = _fog_fp.fp_atType; + const FogGraduationType fgt = _fog_fp.fp_fgtType; + const FLOAT fHFogSize = fH2-fH1; + const FLOAT fHV = -_fog_fViewerH; + const FLOAT fEpsilon = 0.001f; + ASSERT( fHFogSize>0); + + // for each row (height in fog) + for( PIX pixH=0; pixHfHV+fEpsilon) { + fHA=fHV; + fHB=fHP; + } else { + fHA=fHV-fEpsilon; + fHB=fHP+fEpsilon; + } + + // get distance between the two points in height axis + FLOAT fDH = fHB-fHA; + FLOAT fOoDH = 1/fDH; + // calculate relative part of height that goes through the fog + FLOAT fA2 = (fH2-fHA)*fOoDH; + fA2 = Clamp(fA2,0.0f,1.0f); + FLOAT fA1 = (fH1-fHA)*fOoDH; + fA1 = Clamp(fA1,0.0f,1.0f); + FLOAT fA = fA2-fA1; + fA = Clamp(fA,0.0f,1.0f); + + // if not constant graduation + if( fgt!=FGT_CONSTANT) { + // calculate fog height for two points, limited to be inside fog + FLOAT fFH0 = (fHFogSize-Clamp(fHA-fH1, 0.0f, fHFogSize)); + FLOAT fFH1 = (fHFogSize-Clamp(fHB-fH1, 0.0f, fHFogSize)); + + // multiply the heights by graduation factor + fFH0 *= _fog_fp.fp_fGraduation; + fFH1 *= _fog_fp.fp_fGraduation; + + FLOAT fDens; + // if linear graduation + if (fgt==FGT_LINEAR) { + // get linear integrated density factor + fDens = (fFH0+fFH1)/2.0f; + // if exponential graduation + } else { + ASSERT(fgt==FGT_EXP); + // sort the two heights and make sure they are not same + FLOAT fFA, fFB; + if (fFH0fFH1+fEpsilon) { + fFA=fFH1; + fFB=fFH0; + } else { + fFA=fFH1-fEpsilon; + fFB=fFH0+fEpsilon; + } + // calculate exponential integrated density factor normally + fDens = 1.0f+(exp(-fFB)-exp(-fFA))/(fFB-fFA); + } + + // limit the intergrated density factor + fDens = Clamp(fDens, 0.0f, 1.0f); + + // relative size multiplied by integrated density factor gives total fog sum + fA *= fDens; + } + + // do per-row loop + switch(at) + { + // linear fog + case AT_LINEAR: { + // calculate linear step for the fog parameter + FLOAT fT = 0.0f; + FLOAT fTStep = 1.0f/pixSizeL *fFar*fDensity*fA *255; + // fog is just clamped fog parameter in each pixel + for( INDEX pixL=0; pixL0; pix--) { + if( (_fog_pubTable[(pix+1)*pixSizeL-1]*_fog_ulAlpha)>>8) break; + } + if( pix<(pixSizeH-1)) _fog_fEnd = (FLOAT)(pix+1) / (FLOAT)(pixSizeH-1); + } else { + // going from top + INDEX pix=0; + for( ; pix>8) break; + } + if( pix>0) _fog_fStart = (FLOAT)(pix-1) / (FLOAT)(pixSizeH-1); + } + + // prepare and upload the fog table + _fog_tpLocal.tp_bSingleMipmap = TRUE; + const ULONG ulFormat = PrepareTexture( _fog_pubTable, _fog_pixSizeL, _fog_pixSizeH); + if( _fog_ulFormat!=ulFormat) { + _fog_ulFormat = ulFormat; + bNoDiscard = FALSE; + } // set'n'upload + gfxSetTextureWrapping( GFX_CLAMP, GFX_CLAMP); + gfxSetTexture( _fog_ulTexture, _fog_tpLocal); + gfxUploadTexture( (ULONG*)(_fog_pubTable + _fog_pixSizeL*_fog_pixSizeH), + _fog_pixSizeL, _fog_pixSizeH, ulFormat, bNoDiscard); +} + + +// stop fog +void StopFog(void) +{ + _fog_bActive = FALSE; +} + + +// current haze parameters +BOOL _haze_bActive = FALSE; +CHazeParameters _haze_hp; +CTexParams _haze_tpLocal; + +PIX _haze_pixSize=0; +FLOAT _haze_fStart=0; // where in depth haze starts +UBYTE *_haze_pubTable=NULL; +FLOAT3D _haze_vViewPosAbs; +FLOAT3D _haze_vViewDirAbs; +FLOAT _haze_fMul=0; +FLOAT _haze_fAdd=0; +ULONG _haze_ulAlpha=0; +ULONG _haze_ulTexture=0; +ULONG _haze_ulFormat=0; + + +// start haze with given parameters +void StartHaze( CHazeParameters &hp, + const FLOAT3D &vViewPosAbs, const FLOATmatrix3D &mAbsToView) +{ + ASSERT( !_haze_bActive); + if( _bMultiPlayer) gfx_bRenderFog = 1; + if( !gfx_bRenderFog) return; + _haze_bActive = TRUE; + + _haze_hp = hp; + _haze_vViewPosAbs = vViewPosAbs; + _haze_vViewDirAbs(1) = -mAbsToView(3, 1); + _haze_vViewDirAbs(2) = -mAbsToView(3, 2); + _haze_vViewDirAbs(3) = -mAbsToView(3, 3); + + // calculate haze mapping factors + _haze_fMul = 1/(_haze_hp.hp_fFar-_haze_hp.hp_fNear); + _haze_fAdd = -_haze_hp.hp_fNear; + + PIX pixSize = _haze_hp.hp_iSize; + BOOL bNoDiscard = TRUE; + + // if haze table is not allocated in right size + if( _haze_pixSize!=pixSize && _haze_pubTable!=NULL) { + FreeMemory( _haze_pubTable); // free it + _haze_pubTable = NULL; + } + // allocate table if needed + if( _haze_pubTable==NULL) { + // allocate byte table (for intensity values) and ULONG table (color values for uploading) right behind! + _haze_pubTable = (UBYTE*)AllocMemory(pixSize *(sizeof(UBYTE)+sizeof(ULONG))); + _haze_pixSize = pixSize; + _haze_tpLocal.Clear(); + bNoDiscard = FALSE; + } + + // update fog alpha value + _haze_ulAlpha = (_haze_hp.hp_colColor&CT_AMASK)>>CT_ASHIFT; + + // get parameters + FLOAT fNear = _haze_hp.hp_fNear; + FLOAT fFar = _haze_hp.hp_fFar; + FLOAT fDensity = _haze_hp.hp_fDensity; + AttenuationType at = _haze_hp.hp_atType; + // generate table + INDEX pix; + for( pix=0; pix>8) break; + _haze_fStart = (FLOAT)(pix-1) / (FLOAT)(pixSize-1); + + // prepare haze table + _haze_tpLocal.tp_bSingleMipmap = TRUE; + const ULONG ulFormat = PrepareTexture( _haze_pubTable, _haze_pixSize, 1); + if( _haze_ulFormat!=ulFormat) { + _haze_ulFormat = ulFormat; + bNoDiscard = FALSE; + } // set'n'upload + gfxSetTextureWrapping( GFX_CLAMP, GFX_CLAMP); + gfxSetTexture( _haze_ulTexture, _haze_tpLocal); + gfxUploadTexture( (ULONG*)(_haze_pubTable + _haze_pixSize*1), _haze_pixSize, 1, ulFormat, bNoDiscard); +} + + +// stop haze +void StopHaze(void) +{ + _haze_bActive = FALSE; +} diff --git a/Sources/Engine/Graphics/Fog.h b/Sources/Engine/Graphics/Fog.h new file mode 100644 index 0000000..c26d41b --- /dev/null +++ b/Sources/Engine/Graphics/Fog.h @@ -0,0 +1,55 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_FOG_H +#define SE_INCL_FOG_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +enum AttenuationType { + AT_LINEAR, // t*density + AT_EXP, // 1-exp(-t*density) + AT_EXP2, // 1-exp(-(t*density)^2) +}; +enum FogGraduationType { + FGT_CONSTANT, // constant density + FGT_LINEAR, // h*graduation + FGT_EXP, // 1-exp(-h*graduation) +}; + +class CFogParameters { +public: + FLOAT3D fp_vFogDir; // fog direction in absolute space + FLOAT fp_fH0; // lowest point in LUT + FLOAT fp_fH1; // bottom of fog in LUT + FLOAT fp_fH2; // top of fog in LUT + FLOAT fp_fH3; // highest point in LUT + FLOAT fp_fFar; // farthest point in LUT + INDEX fp_iSizeL; // LUT size in distance (must be pow2) + INDEX fp_iSizeH; // LUT size in depth (must be pow2) + + COLOR fp_colColor; // fog color and alpha + enum AttenuationType fp_atType; // type of attenuation + FLOAT fp_fDensity; // attenuation parameter + enum FogGraduationType fp_fgtType; // type of graduation + FLOAT fp_fGraduation; // graduation parameter +}; + +#define HPF_VISIBLEFROMOUTSIDE (1UL<<0) // can be viewed from sectors that are not hazed +class CHazeParameters { +public: + ULONG hp_ulFlags; + FLOAT hp_fNear; // nearest point in LUT + FLOAT hp_fFar; // farthest point in LUT + INDEX hp_iSize; // LUT size in distance (must be pow2) + + COLOR hp_colColor; // fog color and alpha + enum AttenuationType hp_atType; // type of attenuation + FLOAT hp_fDensity; // attenuation parameter +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/Fog_internal.h b/Sources/Engine/Graphics/Fog_internal.h new file mode 100644 index 0000000..694d1d6 --- /dev/null +++ b/Sources/Engine/Graphics/Fog_internal.h @@ -0,0 +1,107 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_FOG_INTERNAL_H +#define SE_INCL_FOG_INTERNAL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + + +// current fog parameters +extern BOOL _fog_bActive; +extern CFogParameters _fog_fp; +extern CTexParams _fog_tpLocal; +extern FLOAT _fog_fViewerH; +extern FLOAT3D _fog_vViewPosAbs; +extern FLOAT3D _fog_vViewDirAbs; +extern FLOAT3D _fog_vHDirAbs; +extern FLOAT3D _fog_vHDirView; +extern FLOAT _fog_fMulZ; +extern FLOAT _fog_fMulH; +extern FLOAT _fog_fAddH; +extern PIX _fog_pixSizeH; +extern PIX _fog_pixSizeL; +extern FLOAT _fog_fStart; +extern FLOAT _fog_fEnd; +extern ULONG _fog_ulAlpha; +extern ULONG _fog_ulTexture; +extern UBYTE *_fog_pubTable; + +// start fog with given parameters +extern void StartFog( CFogParameters &fp, const FLOAT3D &vViewPosAbs, + const FLOATmatrix3D &mAbsToView); +// stop fog +extern void StopFog(void); + + +// current haze parameters +extern BOOL _haze_bActive; +extern CHazeParameters _haze_hp; +extern CTexParams _haze_tpLocal; +extern UBYTE *_haze_pubTable; +extern FLOAT3D _haze_vViewPosAbs; +extern FLOAT3D _haze_vViewDirAbs; +extern FLOAT _haze_fMul; +extern FLOAT _haze_fAdd; +extern PIX _haze_pixSize; +extern ULONG _haze_ulAlpha; +extern ULONG _haze_ulTexture; +extern FLOAT _haze_fStart; + +// start haze with given parameters +extern void StartHaze( CHazeParameters &hp, const FLOAT3D &vViewPosAbs, + const FLOATmatrix3D &mAbsToView); +// stop haze +extern void StopHaze(void); + + +// returns lineary-interpolated fog strength in fog texture +__forceinline ULONG GetFogAlpha( const GFXTexCoord &tex) +{ + // point sampling of height + PIX pixT = FloatToInt( tex.t * _fog_pixSizeH); + pixT = Clamp( pixT, 0L, _fog_pixSizeH-1L) * _fog_pixSizeL; + // linear interpolation of depth + const PIX pixSF = FloatToInt( tex.s*(FLOAT)_fog_pixSizeL*255.499f); + const PIX pixS1 = Clamp( (PIX)((pixSF>>8)+0), 0L, _fog_pixSizeL-1L); + const PIX pixS2 = Clamp( (PIX)((pixSF>>8)+1), 0L, _fog_pixSizeL-1L); + const ULONG ulF = pixSF & 255; + const ULONG ulA1 = _fog_pubTable[pixT +pixS1]; + const ULONG ulA2 = _fog_pubTable[pixT +pixS2]; + return ((ulA1*(ulF^255)+ulA2*ulF) * _fog_ulAlpha) >>16; +} + + +// check if texture coord is in fog +__forceinline BOOL InFog( const FLOAT fT) +{ + return (fT>_fog_fStart && fT<_fog_fEnd); +} + + + +// returns lineary-interpolated haze strength in haze texture +__forceinline ULONG GetHazeAlpha( const FLOAT fS) +{ + // linear interpolation of depth + const PIX pixSH = FloatToInt( fS*(FLOAT)_haze_pixSize*255.4999f); + const PIX pixS1 = Clamp( (PIX)((pixSH>>8)+0), 0L, _haze_pixSize-1L); + const PIX pixS2 = Clamp( (PIX)((pixSH>>8)+1), 0L, _haze_pixSize-1L); + const ULONG ulH = pixSH & 255; + const ULONG ulA1 = _haze_pubTable[pixS1]; + const ULONG ulA2 = _haze_pubTable[pixS2]; + return ((ulA1*(ulH^255)+ulA2*ulH) * _haze_ulAlpha) >>16; +} + + +// check if texture coord is in haze +__forceinline BOOL InHaze( const FLOAT fS) +{ + return (fS>_haze_fStart); +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/Font.cpp b/Sources/Engine/Graphics/Font.cpp new file mode 100644 index 0000000..2a8affc --- /dev/null +++ b/Sources/Engine/Graphics/Font.cpp @@ -0,0 +1,198 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include + + +// some default fonts +CFontData *_pfdDisplayFont; +CFontData *_pfdConsoleFont; + + +// constructor deletes letter data +CFontCharData::CFontCharData(void) +{ + fcd_pixXOffset = 0; + fcd_pixYOffset = 0; + fcd_pixStart = 0; + fcd_pixEnd = 0; +} + +// simple stream functions +void CFontCharData::Read_t( CTStream *inFile) +{ + *inFile>>fcd_pixXOffset; + *inFile>>fcd_pixYOffset; + *inFile>>fcd_pixStart; + *inFile>>fcd_pixEnd; +} + +void CFontCharData::Write_t( CTStream *outFile) +{ + *outFile<Release(fd_ptdTextureData); + fd_ptdTextureData = NULL; + } +} + +void CFontData::Read_t( CTStream *inFile) // throw char * +{ + // clear current font data (if needed) + Clear(); + + // read the filename of the corresponding texture file. + inFile->ExpectID_t( CChunkID("FTTF")); + *inFile >> fd_fnTexture; + // read maximum width and height of all letters + *inFile >> fd_pixCharWidth; + *inFile >> fd_pixCharHeight; + // read entire letter data table + for( INDEX iLetterData=0; iLetterData<256; iLetterData ++) { + fd_fcdFontCharData[ iLetterData].Read_t( inFile); + } + // load corresponding texture file + fd_ptdTextureData = _pTextureStock->Obtain_t(fd_fnTexture); + // reload corresponding texture if not loaded in largest mip-map + fd_ptdTextureData->Force( TEX_CONSTANT); + + // initialize default font variables + SetVariableWidth(); + SetCharSpacing(+1); + SetLineSpacing(+1); + SetSpaceWidth(0.5f); + fd_fcdFontCharData[' '].fcd_pixStart = 0; +} + +void CFontData::Write_t( CTStream *outFile) // throw char * +{ + ASSERT( fd_ptdTextureData != NULL); + // write the filename of the corresponding texture file + outFile->WriteID_t( CChunkID("FTTF")); + *outFile << fd_fnTexture; + // write max letter width and height of all letters + *outFile << fd_pixCharWidth; + *outFile << fd_pixCharHeight; + + // write entire letter data table + for( INDEX iLetterData=0; iLetterData<256; iLetterData ++) { + fd_fcdFontCharData[ iLetterData].Write_t( outFile); + } +} + +/* + * Function used for creating font data object + */ +void CFontData::Make_t( const CTFileName &fnTexture, PIX pixCharWidth, PIX pixCharHeight, + CTFileName &fnOrderFile, BOOL bUseAlpha) +{ + // do it only if font has not been created already + ASSERT( fd_ptdTextureData == NULL); + + // remember texture name + fd_fnTexture = fnTexture; + // load texture and cache width + fd_ptdTextureData = _pTextureStock->Obtain_t(fd_fnTexture); + fd_ptdTextureData->Force( TEX_STATIC|TEX_CONSTANT); + PIX pixTexWidth = fd_ptdTextureData->GetPixWidth(); + + // load ascii order file (no application path necessary) + CTString strLettersOrder; + IgnoreApplicationPath(); + strLettersOrder.Load_t( fnOrderFile); + UseApplicationPath(); + + // remember letter width and height + fd_pixCharWidth = pixCharWidth; + fd_pixCharHeight = pixCharHeight; + // determine address in memory where font definition begins in its larger mip-map + ULONG *pulFont = fd_ptdTextureData->td_pulFrames; + ASSERT( pulFont!=NULL); + + // find number of letters in line (assuming that the 1st line represents the width of every line) + INDEX iLettersInLine=0; + while( (strLettersOrder[iLettersInLine]!='\n') && iLettersInLine=strlen(strLettersOrder)) break; + // get char params + unsigned char chrLetter = strLettersOrder[iLetter++]; + // reset current letter's width + PIX pixCurrentStart = fd_pixCharWidth; + PIX pixCurrentEnd = 0; + // for all of the letter's lines + for( INDEX iPixelLine=0; iPixelLine pixCurrentEnd) pixCurrentEnd = iPixelColumn; + } + } + } + // letter's data is stored into table on appropriate place + fd_fcdFontCharData[chrLetter].fcd_pixXOffset = iCurrentLetterColumn * fd_pixCharWidth; + fd_fcdFontCharData[chrLetter].fcd_pixYOffset = iCurrentLetterLine * fd_pixCharHeight; + fd_fcdFontCharData[chrLetter].fcd_pixStart = pixCurrentStart; + fd_fcdFontCharData[chrLetter].fcd_pixEnd = pixCurrentEnd +1; + } + // advance to next line in text file + iCurrentLetterLine++; + iLetter++; // skip carriage return + } + // set default space width + fd_fcdFontCharData[' '].fcd_pixStart = 0; + SetSpaceWidth(0.5f); + + // all done + SetVariableWidth(); + _pTextureStock->Release( fd_ptdTextureData); +} + diff --git a/Sources/Engine/Graphics/Font.h b/Sources/Engine/Graphics/Font.h new file mode 100644 index 0000000..26c3fd5 --- /dev/null +++ b/Sources/Engine/Graphics/Font.h @@ -0,0 +1,72 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_FONT_H +#define SE_INCL_FONT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + + +// some default fonts +ENGINE_API extern CFontData *_pfdDisplayFont; +ENGINE_API extern CFontData *_pfdConsoleFont; + + +/* + * font letter description + */ +class ENGINE_API CFontCharData { +public: + PIX fcd_pixXOffset, fcd_pixYOffset; // offset of letter inside tex file (in pixels) + PIX fcd_pixStart, fcd_pixEnd; // position and size adjustment for current letter + // constructor + CFontCharData(void); + // simple stream functions + void Read_t( CTStream *inFile); + void Write_t( CTStream *outFile); +}; + + +/* + * font description + */ +class ENGINE_API CFontData : public CSerial { +// implementation +public: + PIX fd_pixCharSpacing, fd_pixLineSpacing; // intra character and intra line spacing + PIX fd_pixCharWidth, fd_pixCharHeight; // maximum character width and height + BOOL fd_bFixedWidth; // treated as of fixed width + + CTFileName fd_fnTexture; + class CFontCharData fd_fcdFontCharData[256]; + class CTextureData *fd_ptdTextureData; + +// interface +public: + CFontData(); + ~CFontData(); + inline PIX GetWidth(void) const { return fd_pixCharWidth; }; + inline PIX GetHeight(void) const { return fd_pixCharHeight; }; + inline PIX GetCharSpacing(void) const { return fd_pixCharSpacing; }; + inline PIX GetLineSpacing(void) const { return fd_pixLineSpacing; }; + inline BOOL IsFixedWidth(void) const { return fd_bFixedWidth; }; + inline void SetCharSpacing( PIX pixSpacing) { fd_pixCharSpacing = pixSpacing; }; + inline void SetLineSpacing( PIX pixSpacing) { fd_pixLineSpacing = pixSpacing; }; + inline void SetFixedWidth(void) { fd_bFixedWidth = TRUE; }; + inline void SetVariableWidth(void) { fd_bFixedWidth = FALSE; }; + inline void SetSpaceWidth( FLOAT fWidthRatio) { // relative to char cell width (1/2 is default) + fd_fcdFontCharData[' '].fcd_pixEnd = (PIX)(fd_pixCharWidth*fWidthRatio); } + + void Read_t( CTStream *inFile); // throw char * + void Write_t( CTStream *outFile); // throw char * + void Make_t( const CTFileName &fnTexture, PIX pixCharWidth, PIX pixCharHeight, + CTFileName &fnOrderFile, BOOL bUseAlpha); + void Clear(); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/GfxLibrary.cpp b/Sources/Engine/Graphics/GfxLibrary.cpp new file mode 100644 index 0000000..59e6dff --- /dev/null +++ b/Sources/Engine/Graphics/GfxLibrary.cpp @@ -0,0 +1,2042 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +// control for partial usage of compiled vertex arrays +extern BOOL CVA_b2D = FALSE; +extern BOOL CVA_bWorld = FALSE; +extern BOOL CVA_bModels = FALSE; + +// common element arrays +CStaticStackArray _avtxCommon; +CStaticStackArray _atexCommon; +CStaticStackArray _acolCommon; +CStaticStackArray _aiCommonElements; +CStaticStackArray _aiCommonQuads; // predefined array for rendering quads thru triangles in glDrawElements() + +// global texture parameters +CTexParams _tpGlobal[GFX_MAXTEXUNITS]; + +// pointer to global graphics library object +CGfxLibrary *_pGfx = NULL; + +// forced texture upload quality (0 = default, 16 = force 16-bit, 32 = force 32-bit) +INDEX _iTexForcedQuality = 0; + +extern PIX _fog_pixSizeH; +extern PIX _fog_pixSizeL; +extern PIX _haze_pixSize; + +// control for partial usage of compiled vertex arrays +extern BOOL CVA_b2D; +extern BOOL CVA_bWorld; +extern BOOL CVA_bModels; + +// gamma control +static FLOAT _fLastBrightness, _fLastContrast, _fLastGamma; +static FLOAT _fLastBiasR, _fLastBiasG, _fLastBiasB; +static INDEX _iLastLevels; +static UWORD _auwGammaTable[256*3]; + +// table for clipping [-512..+1024] to [0..255] +static UBYTE aubClipByte[256*2+ 256 +256*3]; +extern const UBYTE *pubClipByte = &aubClipByte[256*2]; + +// fast square root and 1/sqrt tables +UBYTE aubSqrt[SQRTTABLESIZE]; +UWORD auw1oSqrt[SQRTTABLESIZE]; + +// table for conversion from compressed 16-bit gouraud normals to 8-bit +UBYTE aubGouraudConv[16384]; + +// flag for scene rendering in progress (i.e. between 1st lock in frame & swap-buffers) +static BOOL GFX_bRenderingScene = FALSE; +// ID of the last drawport that has been locked +static ULONG GFX_ulLastDrawPortID = 0; + +// last size of vertex buffers +extern INDEX _iLastVertexBufferSize = 0; +// pretouch flag +extern BOOL _bNeedPretouch; + +// flat texture +CTextureData *_ptdFlat = NULL; +static ULONG _ulWhite = 0xFFFFFFFF; + +// fast sin/cos table +static FLOAT afSinTable[256+256+64]; +extern const FLOAT *pfSinTable = afSinTable +256; +extern const FLOAT *pfCosTable = afSinTable +256+64; + +// texture/shadow control +extern INDEX tex_iNormalQuality = 00; // 0=optimal, 1=16bit, 2=32bit, 3=compressed (1st num=opaque tex, 2nd=alpha tex) +extern INDEX tex_iAnimationQuality = 11; // 0=optimal, 1=16bit, 2=32bit, 3=compressed (1st num=opaque tex, 2nd=alpha tex) +extern INDEX tex_iNormalSize = 9; // log2 of texture area /2 for max texture size allowed +extern INDEX tex_iAnimationSize = 7; +extern INDEX tex_iEffectSize = 7; +extern INDEX tex_bDynamicMipmaps = FALSE; // how many mipmaps will be bilineary filtered (0-15) +extern INDEX tex_iDithering = 3; // 0=none, 1-3=low, 4-7=medium, 8-10=high +extern INDEX tex_bFineEffect = FALSE; // 32bit effect? (works only if base texture hasn't been dithered) +extern INDEX tex_bFineFog = TRUE; // should fog be 8/32bit? (or just plain 4/16bit) +extern INDEX tex_iFogSize = 7; // limit fog texture size +extern INDEX tex_iFiltering = 0; // -6 - +6; negative = sharpen, positive = blur, 0 = none +extern INDEX tex_iEffectFiltering = +4; // filtering of fire effect textures +extern INDEX tex_bProgressiveFilter = FALSE; // filter mipmaps in creation time (not afterwards) +extern INDEX tex_bColorizeMipmaps = FALSE; // DEBUG: colorize texture's mipmap levels in various colors +extern INDEX tex_bCompressAlphaChannel = FALSE; // for compressed textures, compress alpha channel too +extern INDEX tex_bAlternateCompression = FALSE; // basically, this is fix for GFs (compress opaque texture as translucent) + +extern INDEX shd_iStaticSize = 8; +extern INDEX shd_iDynamicSize = 8; +extern INDEX shd_bFineQuality = FALSE; +extern INDEX shd_iFiltering = 3; // >0 = blurring, 0 = no filtering +extern INDEX shd_iDithering = 1; // 0=none, 1,2=low, 3,4=medium, 5=high +extern INDEX shd_iAllowDynamic = 1; // 0=disallow, 1=allow on polys w/o 'NoDynamicLights' flag, 2=allow unconditionally +extern INDEX shd_bDynamicMipmaps = TRUE; +extern FLOAT shd_tmFlushDelay = 30.0f; // in seconds +extern FLOAT shd_fCacheSize = 8.0f; // in megabytes +extern INDEX shd_bCacheAll = FALSE; // cache all shadowmap at the level loading time (careful - memory eater!) +extern INDEX shd_bAllowFlats = TRUE; // allow optimization of single-color shadowmaps +extern INDEX shd_iForceFlats = 0; // force all shadowmaps to be flat (internal!) - 0=don't, 1=w/o overbrighting, 2=w/ overbrighting +extern INDEX shd_bShowFlats = FALSE; // colorize flat shadows +extern INDEX shd_bColorize = FALSE; // colorize shadows by size (gradieng from red=big to green=little) + + +// OpenGL control +extern INDEX ogl_iTextureCompressionType = 1; // 0=none, 1=default (ARB), 2=S3TC, 3=FXT1, 4=old S3TC +extern INDEX ogl_bUseCompiledVertexArrays = 101; // =XYZ; X=2D, Y=world, Z=models +extern INDEX ogl_bAllowQuadArrays = FALSE; +extern INDEX ogl_bExclusive = TRUE; +extern INDEX ogl_bGrabDepthBuffer = FALSE; +extern INDEX ogl_iMaxBurstSize = 0; // unlimited +extern INDEX ogl_bTruformLinearNormals = TRUE; +extern INDEX ogl_bAlternateClipPlane = FALSE; // signal when user clip plane requires a texture unit + +extern INDEX ogl_iTBufferEffect = 0; // 0=none, 1=partial FSAA, 2=Motion Blur +extern INDEX ogl_iTBufferSamples = 2; // 2, 4 or 8 (for now) +extern INDEX ogl_iFinish = 1; // 0=never, 1=before rendering of next frame, 2=at the end of this frame, 3=at projection change + +// Direct3D control +extern INDEX d3d_bUseHardwareTnL = TRUE; +extern INDEX d3d_bAlternateDepthReads = FALSE; // should check delayed depth reads at the end of current frame (FALSE) or at begining of the next (TRUE) +extern INDEX d3d_iVertexBuffersSize = 1024; // KBs reserved for vertex buffers +extern INDEX d3d_iVertexRangeTreshold = 99; // minimum vertices in buffer that triggers range optimization +extern INDEX d3d_bFastUpload = TRUE; // use internal format conversion routines +extern INDEX d3d_iMaxBurstSize = 0; // 0=unlimited +extern INDEX d3d_iFinish = 0; + +// API common controls +extern INDEX gap_iUseTextureUnits = 4; +extern INDEX gap_iTextureFiltering = 21; // bilinear by default +extern INDEX gap_iTextureAnisotropy = 1; // 1=isotropic, 2=min anisotropy +extern FLOAT gap_fTextureLODBias = 0.0f; +extern INDEX gap_bOptimizeStateChanges = TRUE; +extern INDEX gap_iOptimizeDepthReads = 1; // 0=imediately, 1=after frame, 2=every 0.1 seconds +extern INDEX gap_iOptimizeClipping = 2; // 0=no, 1=mirror plane only, 2=mirror and frustum +extern INDEX gap_bAllowGrayTextures = TRUE; +extern INDEX gap_bAllowSingleMipmap = TRUE; +extern INDEX gap_iSwapInterval = 0; +extern INDEX gap_iRefreshRate = 0; +extern INDEX gap_iDithering = 2; // 16-bit dithering: 0=none, 1=no alpha, 2=all +extern INDEX gap_bForceTruform = 0; // 0 = only for models that allow truform, 1=for every model +extern INDEX gap_iTruformLevel = 3; // 0 = no tesselation +extern INDEX gap_iDepthBits = 0; // 0 (as color depth), 16, 24 or 32 +extern INDEX gap_iStencilBits = 0; // 0 (no stencil buffer), 4 or 8 + +// models control +extern INDEX mdl_bShowTriangles = FALSE; +extern INDEX mdl_bShowStrips = FALSE; +extern INDEX mdl_bTruformWeapons = FALSE; +extern INDEX mdl_bCreateStrips = TRUE; +extern INDEX mdl_bRenderDetail = TRUE; +extern INDEX mdl_bRenderSpecular = TRUE; +extern INDEX mdl_bRenderReflection = TRUE; +extern INDEX mdl_bAllowOverbright = TRUE; +extern INDEX mdl_bFineQuality = TRUE; +extern INDEX mdl_iShadowQuality = 1; +extern FLOAT mdl_fLODMul = 1.0f; +extern FLOAT mdl_fLODAdd = 0.0f; +extern INDEX mdl_iLODDisappear = 1; // 0=never, 1=ignore bias, 2=with bias +// ska controls +extern INDEX ska_bShowSkeleton = FALSE; +extern INDEX ska_bShowColision = FALSE; +extern FLOAT ska_fLODMul = 1.0f; +extern FLOAT ska_fLODAdd = 0.0f; +// terrain controls +extern INDEX ter_bShowQuadTree = FALSE; +extern INDEX ter_bShowWireframe = FALSE; +extern INDEX ter_bLerpVertices = TRUE; +extern INDEX ter_bShowInfo = FALSE; +extern INDEX ter_bOptimizeRendering = TRUE; +extern INDEX ter_bTempFreezeCast = FALSE; +extern INDEX ter_bNoRegeneration = FALSE; + +// rendering control +extern INDEX wld_bAlwaysAddAll = FALSE; +extern INDEX wld_bRenderMirrors = TRUE; +extern INDEX wld_bRenderEmptyBrushes = TRUE; +extern INDEX wld_bRenderShadowMaps = TRUE; +extern INDEX wld_bRenderTextures = TRUE; +extern INDEX wld_bRenderDetailPolygons = TRUE; +extern INDEX wld_bTextureLayers = 111; +extern INDEX wld_bShowTriangles = FALSE; +extern INDEX wld_bShowDetailTextures = FALSE; +extern INDEX wld_iDetailRemovingBias = 3; +extern FLOAT wld_fEdgeOffsetI = 0.0f; //0.125f; +extern FLOAT wld_fEdgeAdjustK = 1.0f; //1.0001f; + +extern INDEX gfx_bRenderWorld = TRUE; +extern INDEX gfx_bRenderParticles = TRUE; +extern INDEX gfx_bRenderModels = TRUE; +extern INDEX gfx_bRenderPredicted = FALSE; +extern INDEX gfx_bRenderFog = TRUE; +extern INDEX gfx_iLensFlareQuality = 3; // 0=none, 1=corona only, 2=corona and reflections, 3=corona, reflections and glare + +extern INDEX gfx_bDecoratedText = TRUE; +extern INDEX gfx_bClearScreen = FALSE; +extern FLOAT gfx_tmProbeDecay = 30.0f; // seconds +extern INDEX gfx_iProbeSize = 256; // in KBs + +extern INDEX gfx_ctMonitors = 0; +extern INDEX gfx_bMultiMonDisabled = FALSE; +extern INDEX gfx_bDisableMultiMonSupport = TRUE; + +extern INDEX gfx_bDisableWindowsKeys = TRUE; + +extern INDEX wed_bIgnoreTJunctions = FALSE; +extern INDEX wed_bUseBaseForReplacement = FALSE; + +// some nifty features +extern INDEX gfx_iHueShift = 0; // 0-359 +extern FLOAT gfx_fSaturation = 1.0f; // 0.0f = min, 1.0f = default +// the following vars can be influenced by corresponding gfx_ vars +extern INDEX tex_iHueShift = 0; // added to gfx_ +extern FLOAT tex_fSaturation = 1.0f; // multiplied by gfx_ +extern INDEX shd_iHueShift = 0; // added to gfx_ +extern FLOAT shd_fSaturation = 1.0f; // multiplied by gfx_ + +// gamma table control +extern FLOAT gfx_fBrightness = 0.0f; // -0.9 - 0.9 +extern FLOAT gfx_fContrast = 1.0f; // 0.1 - 1.9 +extern FLOAT gfx_fGamma = 1.0f; // 0.1 - 9.0 +extern FLOAT gfx_fBiasR = 1.0f; // 0.0 - 1.0 +extern FLOAT gfx_fBiasG = 1.0f; // 0.0 - 1.0 +extern FLOAT gfx_fBiasB = 1.0f; // 0.0 - 1.0 +extern INDEX gfx_iLevels = 256; // 2 - 256 + +// stereo rendering control +extern INDEX gfx_iStereo = 0; // 0=off, 1=red/cyan +extern INDEX gfx_bStereoInvert = FALSE; // is left eye RED or CYAN +extern INDEX gfx_iStereoOffset = 10; // view offset (or something:) +extern FLOAT gfx_fStereoSeparation = 0.25f; // distance between eyes + +// cached integers for faster calculation +extern SLONG _slTexSaturation = 256; // 0 = min, 256 = default +extern SLONG _slTexHueShift = 0; +extern SLONG _slShdSaturation = 256; +extern SLONG _slShdHueShift = 0; + +// 'supported' console variable flags +static INDEX sys_bHasTextureCompression = 0; +static INDEX sys_bHasTextureAnisotropy = 0; +static INDEX sys_bHasAdjustableGamma = 0; +static INDEX sys_bHasTextureLODBias = 0; +static INDEX sys_bHasMultitexturing = 0; +static INDEX sys_bHas32bitTextures = 0; +static INDEX sys_bHasSwapInterval = 0; +static INDEX sys_bHasHardwareTnL = 1; +static INDEX sys_bHasTruform = 0; +static INDEX sys_bHasCVAs = 0; +static INDEX sys_bUsingOpenGL = 0; +extern INDEX sys_bUsingDirect3D = 0; + +/* + * Low level hook flags + */ +#define WH_KEYBOARD_LL 13 + +#pragma message(">> doublecheck me!!!") +// these are commented because they are already defined in winuser.h +//#define LLKHF_EXTENDED 0x00000001 +//#define LLKHF_INJECTED 0x00000010 +//#define LLKHF_ALTDOWN 0x00000020 +//#define LLKHF_UP 0x00000080 + +//#define LLMHF_INJECTED 0x00000001 + +/* + * Structure used by WH_KEYBOARD_LL + */ +// this is commented because there's a variant for this struct in winuser.h +/*typedef struct tagKBDLLHOOKSTRUCT { + DWORD vkCode; + DWORD scanCode; + DWORD flags; + DWORD time; + DWORD dwExtraInfo; +} KBDLLHOOKSTRUCT, FAR *LPKBDLLHOOKSTRUCT, *PKBDLLHOOKSTRUCT;*/ + +static HHOOK _hLLKeyHook = NULL; + +LRESULT CALLBACK LowLevelKeyboardProc (INT nCode, WPARAM wParam, LPARAM lParam) +{ + // By returning a non-zero value from the hook procedure, the + // message does not get passed to the target window + KBDLLHOOKSTRUCT *pkbhs = (KBDLLHOOKSTRUCT *) lParam; + BOOL bControlKeyDown = 0; + + switch (nCode) + { + case HC_ACTION: + { + // Check to see if the CTRL key is pressed + bControlKeyDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1); + + // Disable CTRL+ESC + if (pkbhs->vkCode == VK_ESCAPE && bControlKeyDown) + return 1; + + // Disable ALT+TAB + if (pkbhs->vkCode == VK_TAB && pkbhs->flags & LLKHF_ALTDOWN) + return 1; + + // Disable ALT+ESC + if (pkbhs->vkCode == VK_ESCAPE && pkbhs->flags & LLKHF_ALTDOWN) + return 1; + + break; + } + + default: + break; + } + return CallNextHookEx (_hLLKeyHook, nCode, wParam, lParam); +} + +void DisableWindowsKeys(void) +{ + //if( _hLLKeyHook!=NULL) UnhookWindowsHookEx(_hLLKeyHook); + //_hLLKeyHook = SetWindowsHookEx(WH_KEYBOARD_LL, &LowLevelKeyboardProc, NULL, GetCurrentThreadId()); + + INDEX iDummy; + SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, &iDummy, 0); +} + +void EnableWindowsKeys(void) +{ + INDEX iDummy; + SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, FALSE, &iDummy, 0); + // if( _hLLKeyHook!=NULL) UnhookWindowsHookEx(_hLLKeyHook); +} + +// texture size reporting + +static CTString ReportQuality( INDEX iQuality) +{ + if( iQuality==0) return "optimal"; + if( iQuality==1) return "16-bit"; + if( iQuality==2) return "32-bit"; + if( iQuality==3) return "compressed"; + ASSERTALWAYS( "Invalid texture quality."); + return "?"; +} + + +static void TexturesInfo(void) +{ + UpdateTextureSettings(); + INDEX ctNo04O=0, ctNo64O=0, ctNoMXO=0; + PIX pixK04O=0, pixK64O=0, pixKMXO=0; + SLONG slKB04O=0, slKB64O=0, slKBMXO=0; + INDEX ctNo04A=0, ctNo64A=0, ctNoMXA=0; + PIX pixK04A=0, pixK64A=0, pixKMXA=0; + SLONG slKB04A=0, slKB64A=0, slKBMXA=0; + + // walk thru all textures on stock + {FOREACHINDYNAMICCONTAINER( _pTextureStock->st_ctObjects, CTextureData, ittd) + { // get texture info + CTextureData &td = *ittd; + BOOL bAlpha = td.td_ulFlags&TEX_ALPHACHANNEL; + INDEX ctFrames = td.td_ctFrames; + SLONG slBytes = td.GetUsedMemory(); + ASSERT( slBytes>=0); + // get texture size + PIX pixTextureSize = td.GetPixWidth() * td.GetPixHeight(); + PIX pixMipmapSize = pixTextureSize; + if( !gap_bAllowSingleMipmap || td.td_ctFineMipLevels>1) pixMipmapSize = pixMipmapSize *4/3; + // increase corresponding counters + if( pixTextureSize<4096) { + if( bAlpha) { pixK04A+=pixMipmapSize; slKB04A+=slBytes; ctNo04A+=ctFrames; } + else { pixK04O+=pixMipmapSize; slKB04O+=slBytes; ctNo04O+=ctFrames; } + } else if( pixTextureSize<=65536) { + if( bAlpha) { pixK64A+=pixMipmapSize; slKB64A+=slBytes; ctNo64A+=ctFrames; } + else { pixK64O+=pixMipmapSize; slKB64O+=slBytes; ctNo64O+=ctFrames; } + } else { + if( bAlpha) { pixKMXA+=pixMipmapSize; slKBMXA+=slBytes; ctNoMXA+=ctFrames; } + else { pixKMXO+=pixMipmapSize; slKBMXO+=slBytes; ctNoMXO+=ctFrames; } + } + }} + + // report + const PIX pixNormDim = sqrt((FLOAT)TS.ts_pixNormSize); + const PIX pixAnimDim = sqrt((FLOAT)TS.ts_pixAnimSize); + const PIX pixEffDim = 1L<256 pix: %3d frames use %6.1f Kpix in %5d KB\n", ctNoMXO, pixKMXO/1024.0f, slKBMXO/1024); + CPrintF( "Translucent textures memory usage:\n"); + CPrintF( " <64 pix: %3d frames use %6.1f Kpix in %5d KB\n", ctNo04A, pixK04A/1024.0f, slKB04A/1024); + CPrintF( " 64-256 pix: %3d frames use %6.1f Kpix in %5d KB\n", ctNo64A, pixK64A/1024.0f, slKB64A/1024); + CPrintF( " >256 pix: %3d frames use %6.1f Kpix in %5d KB\n", ctNoMXA, pixKMXA/1024.0f, slKBMXA/1024); + CPrintF("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n\n"); +} + + + +// reformat an extensions string to cross multiple lines +extern CTString ReformatExtensionsString( CTString strUnformatted) +{ + CTString strTmp, strDst = "\n"; + char *pcSrc = (char*)(const char*)strUnformatted; + FOREVER { + char *pcSpace = strchr( pcSrc, ' '); + if( pcSpace==NULL) break; + *pcSpace = 0; + strTmp.PrintF( " %s\n", pcSrc); + strDst += strTmp; + *pcSpace = ' '; + pcSrc = pcSpace +1; + } + if(strDst=="\n") { + strDst = "none\n"; + } + // done + return strDst; +} + + +// printout extensive OpenGL/Direct3D info to console +static void GAPInfo(void) +{ + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_D3D || eAPI==GAT_NONE); +#else // SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_NONE); +#endif // SE1_D3D + CPrintF( "\n"); + + // in case of driver hasn't been initialized yet + if( (_pGfx->go_hglRC==NULL +#ifdef SE1_D3D + && _pGfx->gl_pd3dDevice==NULL +#endif // SE1_D3D + ) || eAPI==GAT_NONE) { + // be brief, be quick + CPrintF( TRANS("Display driver hasn't been initialized.\n\n")); + return; + } + + // report API + CPrintF( "- Graphics API: "); + if( eAPI==GAT_OGL) CPrintF( "OpenGL\n"); + else CPrintF( "Direct3D\n"); + // and number of adapters + CPrintF( "- Adapters found: %d\n", _pGfx->gl_gaAPI[eAPI].ga_ctAdapters); + CPrintF( "\n"); + + // report renderer + CDisplayAdapter &da = _pGfx->gl_gaAPI[eAPI].ga_adaAdapter[_pGfx->gl_iCurrentAdapter]; + if( eAPI==GAT_OGL) CPrintF( "- Vendor: %s\n", da.da_strVendor); + CPrintF( "- Renderer: %s\n", da.da_strRenderer); + CPrintF( "- Version: %s\n", da.da_strVersion); + CPrintF( "\n"); + + // Z-buffer depth + CPrintF( "- Z-buffer precision: "); + if( _pGfx->gl_iCurrentDepth==0) CPrintF( "default\n"); + else CPrintF( "%d bits\n", _pGfx->gl_iCurrentDepth); + + // 32-bit textures + CPrintF( "- 32-bit textures: "); + if( _pGfx->gl_ulFlags & GLF_32BITTEXTURES) CPrintF( "supported\n"); + else CPrintF( "not supported\n"); + // grayscale textures + CPrintF( "- Grayscale textures: "); + if( gap_bAllowGrayTextures) CPrintF( "allowed\n"); + else CPrintF( "not allowed\n"); + // report maximum texture dimension + CPrintF( "- Max texture dimension: %d pixels\n", _pGfx->gl_pixMaxTextureDimension); + + // report multitexturing capabilities + CPrintF( "- Multi-texturing: "); + if( _pGfx->gl_ctRealTextureUnits<2) CPrintF( "not supported\n"); + else { + if( gap_iUseTextureUnits>1) CPrintF( "enabled (using %d texture units)\n", gap_iUseTextureUnits); + else CPrintF( "disabled\n"); + CPrintF( "- Texture units: %d", _pGfx->gl_ctRealTextureUnits); + if( _pGfx->gl_ctTextureUnits < _pGfx->gl_ctRealTextureUnits) { + CPrintF(" (%d can be used)\n", _pGfx->gl_ctTextureUnits); + } else CPrintF("\n"); + } + + // report texture anisotropy degree + if( _pGfx->gl_iMaxTextureAnisotropy>=2) { + CPrintF( "- Texture anisotropy: %d of %d\n", _tpGlobal[0].tp_iAnisotropy, _pGfx->gl_iMaxTextureAnisotropy); + } else CPrintF( "- Anisotropic texture filtering: not supported\n"); + + // report texture LOD bias range + const FLOAT fMaxLODBias = _pGfx->gl_fMaxTextureLODBias; + if( fMaxLODBias>0) { + CPrintF( "- Texture LOD bias: %.1f of +/-%.1f\n", _pGfx->gl_fTextureLODBias, fMaxLODBias); + } else CPrintF( "- Texture LOD biasing: not supported\n"); + + // OpenGL only stuff ... + if( eAPI==GAT_OGL) + { + // report truform tessellation + CPrintF( "- Truform tessellation: "); + if( _pGfx->gl_iMaxTessellationLevel>0) { + if( _pGfx->gl_iTessellationLevel>0) { + CPrintF( "enabled "); + if( gap_bForceTruform) CPrintF( "(for all models)\n"); + else CPrintF( "(only for Truform-ready models)\n"); + CTString strNormalMode = ogl_bTruformLinearNormals ? "linear" : "quadratic"; + CPrintF( "- Tesselation level: %d of %d (%s normals)\n", _pGfx->gl_iTessellationLevel, _pGfx->gl_iMaxTessellationLevel, strNormalMode); + } else CPrintF( "disabled\n"); + } else CPrintF( "not supported\n"); + + // report current swap interval (only if fullscreen) + if( _pGfx->gl_ulFlags&GLF_FULLSCREEN) { + // report current swap interval + CPrintF( "- Swap interval: "); + if( _pGfx->gl_ulFlags&GLF_VSYNC) { + GLint gliWaits = pwglGetSwapIntervalEXT(); + if( gliWaits>=0) { + ASSERT( gliWaits==_pGfx->gl_iSwapInterval); + CPrintF( "%d frame(s)\n", gliWaits); + } else CPrintF( "not readable\n"); + } else CPrintF( "not adjustable\n"); + } + // report T-Buffer support + if( _pGfx->gl_ulFlags & GLF_EXT_TBUFFER) { + CPrintF( "- T-Buffer effect: "); + if( _pGfx->go_ctSampleBuffers==0) CPrintF( "disabled\n"); + else { + ogl_iTBufferEffect = Clamp( ogl_iTBufferEffect, 0L, 2L); + CTString strEffect = "Partial anti-aliasing"; + if( ogl_iTBufferEffect<1) strEffect = "none"; + if( ogl_iTBufferEffect>1) strEffect = "Motion blur"; + CPrintF( "%s (%d buffers used)\n", strEffect, _pGfx->go_ctSampleBuffers); + } + } + + // compiled vertex arrays support + CPrintF( "- Compiled Vertex Arrays: "); + if( _pGfx->gl_ulFlags & GLF_EXT_COMPILEDVERTEXARRAY) { + extern BOOL CVA_b2D; + extern BOOL CVA_bWorld; + extern BOOL CVA_bModels; + if( ogl_bUseCompiledVertexArrays) { + CTString strSep=""; + CPrintF( "enabled (for "); + if( CVA_bWorld) { CPrintF( "world"); strSep="/"; } + if( CVA_bModels) { CPrintF( "%smodels", strSep); strSep="/"; } + if( CVA_b2D) { CPrintF( "%sparticles", strSep); } + CPrintF( ")\n"); + } else CPrintF( "disabled\n"); + } else CPrintF( "not supported\n"); + + // report texture compression type + CPrintF( "- Supported texture compression system(s): "); + if( !(_pGfx->gl_ulFlags&GLF_TEXTURECOMPRESSION)) CPrintF( "none\n"); + else { + CTString strSep=""; + if( _pGfx->gl_ulFlags & GLF_EXTC_ARB) { CPrintF( "ARB"); strSep=", "; } + if( _pGfx->gl_ulFlags & GLF_EXTC_S3TC) { CPrintF( "%sS3TC", strSep); strSep=", "; } + if( _pGfx->gl_ulFlags & GLF_EXTC_FXT1) { CPrintF( "%sFTX1", strSep); strSep=", "; } + if( _pGfx->gl_ulFlags & GLF_EXTC_LEGACY) { CPrintF( "%sold S3TC", strSep); } + CPrintF( "\n- Current texture compression system: "); + switch( ogl_iTextureCompressionType) { + case 0: CPrintF( "none\n"); break; + case 1: CPrintF( "ARB wrapper\n"); break; + case 2: CPrintF( "S3TC\n"); break; + case 3: CPrintF( "FXT1\n"); break; + default: CPrintF( "old S3TC\n"); break; + } + } + /* if exist, report vertex array range extension usage + if( ulExt & GOEXT_VERTEXARRAYRANGE) { + extern BOOL VB_bSetupFailed; + extern SLONG VB_slVertexBufferSize; + extern INDEX VB_iVertexBufferType; + extern INDEX ogl_iVertexBuffers; + if( VB_bSetupFailed) { // didn't manage to setup vertex buffers + CPrintF( "- Enhanced HW T&L: fail\n"); + } else if( VB_iVertexBufferType==0) { // not used + CPrintF( "- Enhanced HW T&L: disabled\n"); + } else { // works! :) + CTString strBufferType("AGP"); + if( VB_iVertexBufferType==2) strBufferType = "video"; + const SLONG slMemSize = VB_slVertexBufferSize/1024; + CPrintF( "- Enhanced hardware T&L: %d buffers in %d KB of %s memory", + ogl_iVertexBuffers, slMemSize, strBufferType); + } + } */ + // report OpenGL externsions + CPrintF("\n"); + CPrintF("- Published extensions: %s", ReformatExtensionsString(_pGfx->go_strExtensions)); + if( _pGfx->go_strWinExtensions != "") CPrintF("%s", ReformatExtensionsString(_pGfx->go_strWinExtensions)); + CPrintF("\n- Supported extensions: %s\n", ReformatExtensionsString(_pGfx->go_strSupportedExtensions)); + } + + // Direct3D only stuff +#ifdef SE1_D3D + if( eAPI==GAT_D3D) + { + // HW T&L + CPrintF( "- Hardware T&L: "); + if( _pGfx->gl_ulFlags&GLF_D3D_HASHWTNL) { + if( _pGfx->gl_ctMaxStreamsgl_ulFlags&GLF_D3D_USINGHWTNL) CPrintF( "enabled (%d streams)\n", _pGfx->gl_ctMaxStreams); + else CPrintF( "disabled\n"); + } else CPrintF( "not present\n"); + + // report vtx/idx buffers size + extern SLONG SizeFromVertices_D3D( INDEX ctVertices); + const SLONG slMemoryUsed = SizeFromVertices_D3D(_pGfx->gl_ctVertices); + CPrintF( "- Vertex buffer size: %.1f KB (%d vertices)\n", slMemoryUsed/1024.0f, _pGfx->gl_ctVertices); + + // N-Patches tessellation (Truform) + CPrintF( "- N-Patches: "); + if( _pGfx->gl_iMaxTessellationLevel>0) { + if( !(_pGfx->gl_ulFlags&GLF_D3D_USINGHWTNL)) CPrintF( "not possible with SW T&L\n"); + else if( _pGfx->gl_iTessellationLevel>0) { + CPrintF( "enabled "); + if( gap_bForceTruform) CPrintF( "(for all models)\n"); + else CPrintF( "(only for Truform-ready models)\n"); + CPrintF( "- Tesselation level: %d of %d\n", _pGfx->gl_iTessellationLevel, _pGfx->gl_iMaxTessellationLevel); + } else CPrintF( "disabled\n"); + } else CPrintF( "not supported\n"); + + // texture compression + CPrintF( "- Texture compression: "); + if( _pGfx->gl_ulFlags&GLF_TEXTURECOMPRESSION) CPrintF( "supported\n"); + else CPrintF( "not supported\n"); + + // custom clip plane support + CPrintF( "- Custom clip plane: "); + if( _pGfx->gl_ulFlags&GLF_D3D_CLIPPLANE) CPrintF( "supported\n"); + else CPrintF( "not supported\n"); + + // color buffer writes enable/disable support + CPrintF( "- Color masking: "); + if( _pGfx->gl_ulFlags&GLF_D3D_COLORWRITES) CPrintF( "supported\n"); + else CPrintF( "not supported\n"); + + // depth (Z) bias support + CPrintF( "- Depth biasing: "); + if( _pGfx->gl_ulFlags&GLF_D3D_ZBIAS) CPrintF( "supported\n"); + else CPrintF( "not supported\n"); + + // current swap interval (only if fullscreen) + if( _pGfx->gl_ulFlags&GLF_FULLSCREEN) { + CPrintF( "- Swap interval: "); + if( _pGfx->gl_ulFlags&GLF_VSYNC) { + CPrintF( "%d frame(s)\n", _pGfx->gl_iSwapInterval); + } else CPrintF( "not adjustable\n"); + } + } +#endif // SE1_D3D +} + + +// update console system vars +extern void UpdateGfxSysCVars(void) +{ + sys_bHasTextureCompression = 0; + sys_bHasTextureAnisotropy = 0; + sys_bHasAdjustableGamma = 0; + sys_bHasTextureLODBias = 0; + sys_bHasMultitexturing = 0; + sys_bHas32bitTextures = 0; + sys_bHasSwapInterval = 0; + sys_bHasHardwareTnL = 1; + sys_bHasTruform = 0; + sys_bHasCVAs = 1; + sys_bUsingOpenGL = 0; + sys_bUsingDirect3D = 0; + if( _pGfx->gl_iMaxTextureAnisotropy>1) sys_bHasTextureAnisotropy = 1; + if( _pGfx->gl_fMaxTextureLODBias>0) sys_bHasTextureLODBias = 1; + if( _pGfx->gl_ctTextureUnits>1) sys_bHasMultitexturing = 1; + if( _pGfx->gl_iMaxTessellationLevel>0) sys_bHasTruform = 1; + if( _pGfx->gl_ulFlags & GLF_TEXTURECOMPRESSION) sys_bHasTextureCompression = 1; + if( _pGfx->gl_ulFlags & GLF_ADJUSTABLEGAMMA) sys_bHasAdjustableGamma = 1; + if( _pGfx->gl_ulFlags & GLF_32BITTEXTURES) sys_bHas32bitTextures = 1; + if( _pGfx->gl_ulFlags & GLF_VSYNC) sys_bHasSwapInterval = 1; + if( _pGfx->gl_eCurrentAPI==GAT_OGL && !(_pGfx->gl_ulFlags&GLF_EXT_COMPILEDVERTEXARRAY)) sys_bHasCVAs = 0; +#ifdef SE1_D3D + if( _pGfx->gl_eCurrentAPI==GAT_D3D && !(_pGfx->gl_ulFlags&GLF_D3D_HASHWTNL)) sys_bHasHardwareTnL = 0; +#endif // SE1_D3D + if( _pGfx->gl_eCurrentAPI==GAT_OGL) sys_bUsingOpenGL = 1; +#ifdef SE1_D3D + if( _pGfx->gl_eCurrentAPI==GAT_D3D) sys_bUsingDirect3D = 1; +#endif // SE1_D3D +} + + + +// determine whether texture or shadowmap needs probing +extern BOOL ProbeMode( CTimerValue tvLast) +{ + // probing off ? + if( !_pGfx->gl_bAllowProbing) return FALSE; + if( gfx_tmProbeDecay<1) { + gfx_tmProbeDecay = 0; + return FALSE; + } + // clamp and determine probe mode + if( gfx_tmProbeDecay>999) gfx_tmProbeDecay = 999; + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + const TIME tmDelta = (tvNow-tvLast).GetSeconds(); + if( tmDelta>gfx_tmProbeDecay) return TRUE; + return FALSE; +} + + + +// uncache all cached shadow maps +extern void UncacheShadows(void) +{ + // mute all sounds + _pSound->Mute(); + // prepare new saturation factors for shadowmaps + gfx_fSaturation = ClampDn( gfx_fSaturation, 0.0f); + shd_fSaturation = ClampDn( shd_fSaturation, 0.0f); + gfx_iHueShift = Clamp( gfx_iHueShift, 0L, 359L); + shd_iHueShift = Clamp( shd_iHueShift, 0L, 359L); + _slShdSaturation = (SLONG)( gfx_fSaturation*shd_fSaturation*256.0f); + _slShdHueShift = Clamp( (gfx_iHueShift+shd_iHueShift)*255L/359L, 0L, 255L); + + CListHead &lhOriginal = _pGfx->gl_lhCachedShadows; + // while there is some shadow in main list + while( !lhOriginal.IsEmpty()) { + CShadowMap &sm = *LIST_HEAD( lhOriginal, CShadowMap, sm_lnInGfx); + sm.Uncache(); + } + // mark that we need pretouching + _bNeedPretouch = TRUE; +} + + +// refresh (uncache and eventually cache) all cached shadow maps +extern void CacheShadows(void); +static void RecacheShadows(void) +{ + // mute all sounds + _pSound->Mute(); + UncacheShadows(); + if( shd_bCacheAll) CacheShadows(); + else CPrintF( TRANS("All shadows uncached.\n")); +} + + + +// reload all textures that were loaded +extern void ReloadTextures(void) +{ + // mute all sounds + _pSound->Mute(); + + // prepare new saturation factors for textures + gfx_fSaturation = ClampDn( gfx_fSaturation, 0.0f); + tex_fSaturation = ClampDn( tex_fSaturation, 0.0f); + gfx_iHueShift = Clamp( gfx_iHueShift, 0L, 359L); + tex_iHueShift = Clamp( tex_iHueShift, 0L, 359L); + _slTexSaturation = (SLONG)( gfx_fSaturation*tex_fSaturation*256.0f); + _slTexHueShift = Clamp( (gfx_iHueShift+tex_iHueShift)*255L/359L, 0L, 255L); + + // update texture settings + UpdateTextureSettings(); + // loop thru texture stock + {FOREACHINDYNAMICCONTAINER( _pTextureStock->st_ctObjects, CTextureData, ittd) { + CTextureData &td = *ittd; + td.Reload(); + td.td_tpLocal.Clear(); + }} + + // reset fog/haze texture + _fog_pixSizeH = 0; + _fog_pixSizeL = 0; + _haze_pixSize = 0; + + // reinit flat texture + ASSERT( _ptdFlat!=NULL); + _ptdFlat->td_tpLocal.Clear(); + _ptdFlat->Unbind(); + _ptdFlat->td_ulFlags = TEX_ALPHACHANNEL | TEX_32BIT | TEX_STATIC; + _ptdFlat->td_mexWidth = 1; + _ptdFlat->td_mexHeight = 1; + _ptdFlat->td_iFirstMipLevel = 0; + _ptdFlat->td_ctFineMipLevels = 1; + _ptdFlat->td_slFrameSize = 1*1* BYTES_PER_TEXEL; + _ptdFlat->td_ctFrames = 1; + _ptdFlat->td_ulInternalFormat = TS.ts_tfRGBA8; + _ptdFlat->td_pulFrames = &_ulWhite; + _ptdFlat->SetAsCurrent(); + + /* + // reset are renderable textures, too + CListHead &lhOriginal = _pGfx->gl_lhRenderTextures; + while( !lhOriginal.IsEmpty()) { + CRenderTexture &rt = *LIST_HEAD( lhOriginal, CRenderTexture, rt_lnInGfx); + rt.Reset(); + } + */ + + // mark that we need pretouching + _bNeedPretouch = TRUE; + CPrintF( TRANS("All textures reloaded.\n")); +} + + +// refreshes all textures and shadow maps +static void RefreshTextures(void) +{ + // refresh + ReloadTextures(); + RecacheShadows(); +} + + + +// reload all models that were loaded + +static void ReloadModels(void) +{ + // mute all sounds + _pSound->Mute(); + // loop thru model stock + {FOREACHINDYNAMICCONTAINER( _pModelStock->st_ctObjects, CModelData, itmd) { + CModelData &md = *itmd; + md.Reload(); + }} + // mark that we need pretouching + _bNeedPretouch = TRUE; + // all done + CPrintF( TRANS("All models reloaded.\n")); +} + + +// variable change post functions +static BOOL _bLastModelQuality = -1; +static void MdlPostFunc(void *pvVar) +{ + mdl_bFineQuality = Clamp( mdl_bFineQuality, 0L, 1L); + if( _bLastModelQuality!=mdl_bFineQuality) { + _bLastModelQuality = mdl_bFineQuality; + ReloadModels(); + } +} + + +/* + * GfxLibrary functions + */ + +static void PrepareTables(void) +{ + INDEX i; + // prepare array for fast clamping to 0..255 + for( i=-256*2; i<256*4; i++) aubClipByte[i+256*2] = (UBYTE)Clamp( i, 0L, 255L); + // prepare fast sqrt tables + for( i=0; itd_ulFlags = TEX_ALPHACHANNEL | TEX_32BIT | TEX_STATIC; + + // prepare some quad elements + extern void AddQuadElements( const INDEX ctQuads); + AddQuadElements(1024); // should be enough (at least for a start) + + // reset GFX API function pointers + GFX_SetFunctionPointers( (INDEX)GAT_NONE); +} + + +/* + * Destruct (and clean up). + */ +CGfxLibrary::~CGfxLibrary() +{ + extern void EnableWindowsKeys(void); + EnableWindowsKeys(); + // free common arrays + _avtxCommon.Clear(); + _atexCommon.Clear(); + _acolCommon.Clear(); + _aiCommonElements.Clear(); + _aiCommonQuads.Clear(); + // stop current display mode + StopDisplayMode(); + // safe release of flat texture + ASSERT( _ptdFlat!=NULL); + _ptdFlat->td_pulFrames = NULL; + delete _ptdFlat; + _ptdFlat = NULL; +} + + + +#define SM_CXVIRTUALSCREEN 78 +#define SM_CYVIRTUALSCREEN 79 +#define SM_CMONITORS 80 + + + +/* Initialize library for application main window. */ +void CGfxLibrary::Init(void) +{ + ASSERT( this!=NULL); + + // report desktop settings + CPrintF(TRANS("Desktop settings...\n")); + + HDC hdc = GetDC(NULL); + SLONG slBPP = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL); + ReleaseDC(NULL, hdc); + + gfx_ctMonitors = GetSystemMetrics(SM_CMONITORS); + + CPrintF(TRANS(" Color Depth: %dbit\n"), slBPP); + CPrintF(TRANS(" Screen: %dx%d\n"), GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); + CPrintF(TRANS(" Virtual screen: %dx%d\n"), GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN)); + CPrintF(TRANS(" Monitors directly reported: %d\n"), gfx_ctMonitors); + + CPrintF("\n"); + + gfx_bMultiMonDisabled = FALSE; + + _pfGfxProfile.Reset(); + + // we will never allow glide splash screen + putenv( "FX_GLIDE_NO_SPLASH=1"); + + // declare some console vars + _pShell->DeclareSymbol("user void MonitorsOn(void);", &MonitorsOn); + _pShell->DeclareSymbol("user void MonitorsOff(void);", &MonitorsOff); + + _pShell->DeclareSymbol("user void GAPInfo(void);", &GAPInfo); + _pShell->DeclareSymbol("user void TexturesInfo(void);", &TexturesInfo); + _pShell->DeclareSymbol("user void UncacheShadows(void);", &UncacheShadows); + _pShell->DeclareSymbol("user void RecacheShadows(void);", &RecacheShadows); + _pShell->DeclareSymbol("user void RefreshTextures(void);", &RefreshTextures); + _pShell->DeclareSymbol("user void ReloadModels(void);", &ReloadModels); + + _pShell->DeclareSymbol("persistent user INDEX ogl_bUseCompiledVertexArrays;", &ogl_bUseCompiledVertexArrays); + _pShell->DeclareSymbol("persistent user INDEX ogl_bExclusive;", &ogl_bExclusive); + _pShell->DeclareSymbol("persistent user INDEX ogl_bAllowQuadArrays;", &ogl_bAllowQuadArrays); + _pShell->DeclareSymbol("persistent user INDEX ogl_iTextureCompressionType;", &ogl_iTextureCompressionType); + _pShell->DeclareSymbol("persistent user INDEX ogl_iMaxBurstSize;", &ogl_iMaxBurstSize); + _pShell->DeclareSymbol("persistent user INDEX ogl_bGrabDepthBuffer;", &ogl_bGrabDepthBuffer); + _pShell->DeclareSymbol("persistent user INDEX ogl_iFinish;", &ogl_iFinish); + + _pShell->DeclareSymbol("persistent user INDEX ogl_iTBufferEffect;", &ogl_iTBufferEffect); + _pShell->DeclareSymbol("persistent user INDEX ogl_iTBufferSamples;", &ogl_iTBufferSamples); + _pShell->DeclareSymbol("persistent user INDEX ogl_bTruformLinearNormals;", &ogl_bTruformLinearNormals); + _pShell->DeclareSymbol("persistent user INDEX ogl_bAlternateClipPlane;", &ogl_bAlternateClipPlane); + + _pShell->DeclareSymbol("persistent user INDEX d3d_bUseHardwareTnL;", &d3d_bUseHardwareTnL); + _pShell->DeclareSymbol("persistent user INDEX d3d_iMaxBurstSize;", &d3d_iMaxBurstSize); + _pShell->DeclareSymbol("persistent user INDEX d3d_iVertexBuffersSize;", &d3d_iVertexBuffersSize); + _pShell->DeclareSymbol("persistent user INDEX d3d_iVertexRangeTreshold;", &d3d_iVertexRangeTreshold); + _pShell->DeclareSymbol("persistent user INDEX d3d_bAlternateDepthReads;", &d3d_bAlternateDepthReads); + _pShell->DeclareSymbol("persistent INDEX d3d_bFastUpload;", &d3d_bFastUpload); + _pShell->DeclareSymbol("persistent user INDEX d3d_iFinish;", &d3d_iFinish); + + _pShell->DeclareSymbol("persistent user INDEX gap_iUseTextureUnits;", &gap_iUseTextureUnits); + _pShell->DeclareSymbol("persistent user INDEX gap_iTextureFiltering;", &gap_iTextureFiltering); + _pShell->DeclareSymbol("persistent user INDEX gap_iTextureAnisotropy;", &gap_iTextureAnisotropy); + _pShell->DeclareSymbol("persistent user FLOAT gap_fTextureLODBias;", &gap_fTextureLODBias); + _pShell->DeclareSymbol("persistent user INDEX gap_bAllowGrayTextures;", &gap_bAllowGrayTextures); + _pShell->DeclareSymbol("persistent user INDEX gap_bAllowSingleMipmap;", &gap_bAllowSingleMipmap); + _pShell->DeclareSymbol("persistent user INDEX gap_bOptimizeStateChanges;", &gap_bOptimizeStateChanges); + _pShell->DeclareSymbol("persistent user INDEX gap_iOptimizeDepthReads;", &gap_iOptimizeDepthReads); + _pShell->DeclareSymbol("persistent user INDEX gap_iOptimizeClipping;", &gap_iOptimizeClipping); + _pShell->DeclareSymbol("persistent user INDEX gap_iSwapInterval;", &gap_iSwapInterval); + _pShell->DeclareSymbol("persistent user INDEX gap_iRefreshRate;", &gap_iRefreshRate); + _pShell->DeclareSymbol("persistent user INDEX gap_iDithering;", &gap_iDithering); + _pShell->DeclareSymbol("persistent user INDEX gap_bForceTruform;", &gap_bForceTruform); + _pShell->DeclareSymbol("persistent user INDEX gap_iTruformLevel;", &gap_iTruformLevel); + _pShell->DeclareSymbol("persistent user INDEX gap_iDepthBits;", &gap_iDepthBits); + _pShell->DeclareSymbol("persistent user INDEX gap_iStencilBits;", &gap_iStencilBits); + + _pShell->DeclareSymbol("void MdlPostFunc(INDEX);", &MdlPostFunc); + + _pShell->DeclareSymbol(" user INDEX gfx_bRenderPredicted;", &gfx_bRenderPredicted); + _pShell->DeclareSymbol(" user INDEX gfx_bRenderModels;", &gfx_bRenderModels); + _pShell->DeclareSymbol(" user INDEX mdl_bShowTriangles;", &mdl_bShowTriangles); + _pShell->DeclareSymbol(" user INDEX mdl_bCreateStrips;", &mdl_bCreateStrips); + _pShell->DeclareSymbol(" user INDEX mdl_bShowStrips;", &mdl_bShowStrips); + _pShell->DeclareSymbol("persistent user FLOAT mdl_fLODMul;", &mdl_fLODMul); + _pShell->DeclareSymbol("persistent user FLOAT mdl_fLODAdd;", &mdl_fLODAdd); + _pShell->DeclareSymbol("persistent user INDEX mdl_iLODDisappear;", &mdl_iLODDisappear); + _pShell->DeclareSymbol("persistent user INDEX mdl_bRenderDetail;", &mdl_bRenderDetail); + _pShell->DeclareSymbol("persistent user INDEX mdl_bRenderSpecular;", &mdl_bRenderSpecular); + _pShell->DeclareSymbol("persistent user INDEX mdl_bRenderReflection;", &mdl_bRenderReflection); + _pShell->DeclareSymbol("persistent user INDEX mdl_bAllowOverbright;", &mdl_bAllowOverbright); + _pShell->DeclareSymbol("persistent user INDEX mdl_bFineQuality post:MdlPostFunc;", &mdl_bFineQuality); + _pShell->DeclareSymbol("persistent user INDEX mdl_iShadowQuality;", &mdl_iShadowQuality); + _pShell->DeclareSymbol(" INDEX mdl_bTruformWeapons;", &mdl_bTruformWeapons); + + _pShell->DeclareSymbol(" user INDEX ska_bShowSkeleton;", &ska_bShowSkeleton); + _pShell->DeclareSymbol(" user INDEX ska_bShowColision;", &ska_bShowColision); + _pShell->DeclareSymbol("persistent user FLOAT ska_fLODMul;", &ska_fLODMul); + _pShell->DeclareSymbol("persistent user FLOAT ska_fLODAdd;", &ska_fLODAdd); + + _pShell->DeclareSymbol(" user INDEX ter_bShowQuadTree;", &ter_bShowQuadTree); + _pShell->DeclareSymbol(" user INDEX ter_bShowWireframe;", &ter_bShowWireframe); + _pShell->DeclareSymbol(" user INDEX ter_bLerpVertices;", &ter_bLerpVertices); + _pShell->DeclareSymbol(" user INDEX ter_bShowInfo;", &ter_bShowInfo); + _pShell->DeclareSymbol(" user INDEX ter_bOptimizeRendering;", &ter_bOptimizeRendering); + _pShell->DeclareSymbol(" user INDEX ter_bTempFreezeCast; ", &ter_bTempFreezeCast); + _pShell->DeclareSymbol(" user INDEX ter_bNoRegeneration; ", &ter_bNoRegeneration); + + + + + _pShell->DeclareSymbol("persistent user FLOAT gfx_tmProbeDecay;", &gfx_tmProbeDecay); + _pShell->DeclareSymbol("persistent user INDEX gfx_iProbeSize;", &gfx_iProbeSize); + _pShell->DeclareSymbol("persistent user INDEX gfx_bClearScreen;", &gfx_bClearScreen); + _pShell->DeclareSymbol("persistent user INDEX gfx_bDisableMultiMonSupport;", &gfx_bDisableMultiMonSupport); + _pShell->DeclareSymbol("persistent user INDEX gfx_bDisableWindowsKeys;", &gfx_bDisableWindowsKeys); + _pShell->DeclareSymbol("persistent user INDEX gfx_bDecoratedText;", &gfx_bDecoratedText); + _pShell->DeclareSymbol(" const user INDEX gfx_ctMonitors;", &gfx_ctMonitors); + _pShell->DeclareSymbol(" const user INDEX gfx_bMultiMonDisabled;", &gfx_bMultiMonDisabled); + + _pShell->DeclareSymbol("persistent user INDEX tex_iNormalQuality;", &tex_iNormalQuality); + _pShell->DeclareSymbol("persistent user INDEX tex_iAnimationQuality;", &tex_iAnimationQuality); + _pShell->DeclareSymbol("persistent user INDEX tex_bFineEffect;", &tex_bFineEffect); + _pShell->DeclareSymbol("persistent user INDEX tex_bFineFog;", &tex_bFineFog); + _pShell->DeclareSymbol("persistent user INDEX tex_iNormalSize;", &tex_iNormalSize); + _pShell->DeclareSymbol("persistent user INDEX tex_iAnimationSize;", &tex_iAnimationSize); + _pShell->DeclareSymbol("persistent user INDEX tex_iEffectSize;", &tex_iEffectSize); + _pShell->DeclareSymbol("persistent user INDEX tex_iFogSize;", &tex_iFogSize); + _pShell->DeclareSymbol("persistent user INDEX tex_bCompressAlphaChannel;", &tex_bCompressAlphaChannel); + _pShell->DeclareSymbol("persistent user INDEX tex_bAlternateCompression;", &tex_bAlternateCompression); + _pShell->DeclareSymbol("persistent user INDEX tex_bDynamicMipmaps;", &tex_bDynamicMipmaps); + _pShell->DeclareSymbol("persistent user INDEX tex_iDithering;", &tex_iDithering); + _pShell->DeclareSymbol("persistent user INDEX tex_iFiltering;", &tex_iFiltering); + _pShell->DeclareSymbol("persistent user INDEX tex_iEffectFiltering;", &tex_iEffectFiltering); + _pShell->DeclareSymbol("persistent user INDEX tex_bProgressiveFilter;", &tex_bProgressiveFilter); + _pShell->DeclareSymbol(" user INDEX tex_bColorizeMipmaps;", &tex_bColorizeMipmaps); + + _pShell->DeclareSymbol("persistent user INDEX shd_iStaticSize;", &shd_iStaticSize); + _pShell->DeclareSymbol("persistent user INDEX shd_iDynamicSize;", &shd_iDynamicSize); + _pShell->DeclareSymbol("persistent user INDEX shd_bFineQuality;", &shd_bFineQuality); + _pShell->DeclareSymbol("persistent user INDEX shd_iAllowDynamic;", &shd_iAllowDynamic); + _pShell->DeclareSymbol("persistent user INDEX shd_bDynamicMipmaps;", &shd_bDynamicMipmaps); + _pShell->DeclareSymbol("persistent user INDEX shd_iFiltering;", &shd_iFiltering); + _pShell->DeclareSymbol("persistent user INDEX shd_iDithering;", &shd_iDithering); + _pShell->DeclareSymbol("persistent user FLOAT shd_tmFlushDelay;", &shd_tmFlushDelay); + _pShell->DeclareSymbol("persistent user FLOAT shd_fCacheSize;", &shd_fCacheSize); + _pShell->DeclareSymbol("persistent user INDEX shd_bCacheAll;", &shd_bCacheAll); + _pShell->DeclareSymbol("persistent user INDEX shd_bAllowFlats;", &shd_bAllowFlats); + _pShell->DeclareSymbol("persistent INDEX shd_iForceFlats;", &shd_iForceFlats); + _pShell->DeclareSymbol(" user INDEX shd_bShowFlats;", &shd_bShowFlats); + _pShell->DeclareSymbol(" user INDEX shd_bColorize;", &shd_bColorize); + + _pShell->DeclareSymbol(" user INDEX gfx_bRenderParticles;", &gfx_bRenderParticles); + _pShell->DeclareSymbol(" user INDEX gfx_bRenderFog;", &gfx_bRenderFog); + _pShell->DeclareSymbol(" user INDEX gfx_bRenderWorld;", &gfx_bRenderWorld); + _pShell->DeclareSymbol("persistent user INDEX gfx_iLensFlareQuality;", &gfx_iLensFlareQuality); + _pShell->DeclareSymbol("persistent user INDEX wld_bTextureLayers;", &wld_bTextureLayers); + _pShell->DeclareSymbol("persistent user INDEX wld_bRenderMirrors;", &wld_bRenderMirrors); + _pShell->DeclareSymbol("persistent user FLOAT wld_fEdgeOffsetI;", &wld_fEdgeOffsetI); + _pShell->DeclareSymbol("persistent user FLOAT wld_fEdgeAdjustK;", &wld_fEdgeAdjustK); + _pShell->DeclareSymbol("persistent user INDEX wld_iDetailRemovingBias;", &wld_iDetailRemovingBias); + _pShell->DeclareSymbol(" user INDEX wld_bRenderEmptyBrushes;", &wld_bRenderEmptyBrushes); + _pShell->DeclareSymbol(" user INDEX wld_bRenderShadowMaps;", &wld_bRenderShadowMaps); + _pShell->DeclareSymbol(" user INDEX wld_bRenderTextures;", &wld_bRenderTextures); + _pShell->DeclareSymbol(" user INDEX wld_bRenderDetailPolygons;", &wld_bRenderDetailPolygons); + _pShell->DeclareSymbol(" user INDEX wld_bShowTriangles;", &wld_bShowTriangles); + _pShell->DeclareSymbol(" user INDEX wld_bShowDetailTextures;", &wld_bShowDetailTextures); + + _pShell->DeclareSymbol(" user INDEX wed_bIgnoreTJunctions;", &wed_bIgnoreTJunctions); + _pShell->DeclareSymbol("persistent user INDEX wed_bUseBaseForReplacement;", &wed_bUseBaseForReplacement); + + + _pShell->DeclareSymbol("persistent user INDEX tex_iHueShift;", &tex_iHueShift); + _pShell->DeclareSymbol("persistent user FLOAT tex_fSaturation;", &tex_fSaturation); + _pShell->DeclareSymbol("persistent user INDEX shd_iHueShift;", &shd_iHueShift); + _pShell->DeclareSymbol("persistent user FLOAT shd_fSaturation;", &shd_fSaturation); + _pShell->DeclareSymbol("persistent user INDEX gfx_iHueShift;", &gfx_iHueShift); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fSaturation;", &gfx_fSaturation); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fBrightness;", &gfx_fBrightness); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fContrast;", &gfx_fContrast); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fGamma;", &gfx_fGamma); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fBiasR;", &gfx_fBiasR); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fBiasG;", &gfx_fBiasG); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fBiasB;", &gfx_fBiasB); + _pShell->DeclareSymbol("persistent user INDEX gfx_iLevels;", &gfx_iLevels); + + _pShell->DeclareSymbol("persistent user INDEX gfx_iStereo;", &gfx_iStereo); + _pShell->DeclareSymbol("persistent user INDEX gfx_bStereoInvert;", &gfx_bStereoInvert); + _pShell->DeclareSymbol("persistent user INDEX gfx_iStereoOffset;", &gfx_iStereoOffset); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fStereoSeparation;", &gfx_fStereoSeparation); + + _pShell->DeclareSymbol( "INDEX sys_bHasTextureCompression;", &sys_bHasTextureCompression); + _pShell->DeclareSymbol( "INDEX sys_bHasTextureAnisotropy;", &sys_bHasTextureAnisotropy); + _pShell->DeclareSymbol( "INDEX sys_bHasAdjustableGamma;", &sys_bHasAdjustableGamma); + _pShell->DeclareSymbol( "INDEX sys_bHasTextureLODBias;", &sys_bHasTextureLODBias); + _pShell->DeclareSymbol( "INDEX sys_bHasMultitexturing;", &sys_bHasMultitexturing); + _pShell->DeclareSymbol( "INDEX sys_bHas32bitTextures;", &sys_bHas32bitTextures); + _pShell->DeclareSymbol( "INDEX sys_bHasSwapInterval;", &sys_bHasSwapInterval); + _pShell->DeclareSymbol( "INDEX sys_bHasHardwareTnL;", &sys_bHasHardwareTnL); + _pShell->DeclareSymbol( "INDEX sys_bHasTruform;", &sys_bHasTruform); + _pShell->DeclareSymbol( "INDEX sys_bHasCVAs;", &sys_bHasCVAs); + _pShell->DeclareSymbol( "INDEX sys_bUsingOpenGL;", &sys_bUsingOpenGL); + _pShell->DeclareSymbol( "INDEX sys_bUsingDirect3D;", &sys_bUsingDirect3D); + + // initialize gfx APIs support + InitAPIs(); +} + + + +// set new display mode +BOOL CGfxLibrary::SetDisplayMode( enum GfxAPIType eAPI, INDEX iAdapter, PIX pixSizeI, PIX pixSizeJ, + enum DisplayDepth eColorDepth) +{ + // some safeties + ASSERT( pixSizeI>0 && pixSizeJ>0); + + // determine new API + GfxAPIType eNewAPI = eAPI; + if( eNewAPI==GAT_CURRENT) eNewAPI = gl_eCurrentAPI; + + // shutdown old and startup new API, and mode and ... stuff, you know! + StopDisplayMode(); + BOOL bRet = StartDisplayMode( eNewAPI, iAdapter, pixSizeI, pixSizeJ, eColorDepth); + if( !bRet) return FALSE; // didn't make it? + + // update some info + gl_iCurrentAdapter = gl_gaAPI[gl_eCurrentAPI].ga_iCurrentAdapter = iAdapter; + gl_dmCurrentDisplayMode.dm_pixSizeI = pixSizeI; + gl_dmCurrentDisplayMode.dm_pixSizeJ = pixSizeJ; + gl_dmCurrentDisplayMode.dm_ddDepth = eColorDepth; + + // prepare texture formats for this display mode + extern void DetermineSupportedTextureFormats( GfxAPIType eAPI); + DetermineSupportedTextureFormats(gl_eCurrentAPI); + + // made it! (eventually disable windows system keys) + if( gfx_bDisableWindowsKeys) DisableWindowsKeys(); + + return TRUE; +} + + +// set display mode to original desktop display mode and default ICD driver +BOOL CGfxLibrary::ResetDisplayMode( enum GfxAPIType eAPI/*=GAT_CURRENT*/) +{ + // determine new API + GfxAPIType eNewAPI = eAPI; + if( eNewAPI==GAT_CURRENT) eNewAPI = gl_eCurrentAPI; + + // shutdown old and startup new API, and mode and ... stuff, you know! + StopDisplayMode(); + BOOL bRet = StartDisplayMode( eNewAPI, 0, 0, 0, DD_DEFAULT); + if( !bRet) return FALSE; // didn't make it? + + // update some info + gl_iCurrentAdapter = 0; + gl_dmCurrentDisplayMode.dm_pixSizeI = 0; + gl_dmCurrentDisplayMode.dm_pixSizeJ = 0; + gl_dmCurrentDisplayMode.dm_ddDepth = DD_DEFAULT; + + // prepare texture formats for this display mode + extern void DetermineSupportedTextureFormats( GfxAPIType eAPI); + DetermineSupportedTextureFormats(gl_eCurrentAPI); + + // made it! + EnableWindowsKeys(); + + return TRUE; +} + + + +// startup gfx API and set given display mode +BOOL CGfxLibrary::StartDisplayMode( enum GfxAPIType eAPI, INDEX iAdapter, PIX pixSizeI, PIX pixSizeJ, + enum DisplayDepth eColorDepth) +{ + // reinit gamma table + _fLastBrightness = 999; + _fLastContrast = 999; + _fLastGamma = 999; + _iLastLevels = 999; + _fLastBiasR = 999; + _fLastBiasG = 999; + _fLastBiasB = 999; + + // prepare + BOOL bSuccess; + ASSERT( iAdapter>=0); + const BOOL bFullScreen = (pixSizeI>0 && pixSizeJ>0); + gl_ulFlags &= GLF_ADJUSTABLEGAMMA; + gl_ctDriverChanges++; + GFX_bRenderingScene = FALSE; + GFX_ulLastDrawPortID = 0; + gl_iTessellationLevel = 0; + gl_ctRealTextureUnits = 0; + _iLastVertexBufferSize = 0; + + // OpenGL driver ? + if( eAPI==GAT_OGL) + { + // disable multimonitor support if it can interfere with OpenGL + MonitorsOff(); + if( bFullScreen) { + // set windows mode to fit same size + bSuccess = CDS_SetMode( pixSizeI, pixSizeJ, eColorDepth); + if( !bSuccess) return FALSE; + } else { + // reset windows mode + CDS_ResetMode(); + } + // startup OpenGL + bSuccess = InitDriver_OGL(iAdapter!=0); + // try to setup sub-driver + if( !bSuccess) { + // reset windows mode and fail + CDS_ResetMode(); + return FALSE; + } // made it + gl_eCurrentAPI = GAT_OGL; + gl_iSwapInterval = 1234; // need to reset + } + + // DirectX driver ? +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) + { + // startup D3D + bSuccess = InitDriver_D3D(); + if( !bSuccess) return FALSE; // what, didn't make it? + bSuccess = InitDisplay_D3D( iAdapter, pixSizeI, pixSizeJ, eColorDepth); + if( !bSuccess) return FALSE; + // made it + gl_eCurrentAPI = GAT_D3D; + } +#endif // SE1_D3D + + // no driver + else + { + ASSERT( eAPI==GAT_NONE); + gl_eCurrentAPI = GAT_NONE; + } + + // initialize on first child window + gl_iFrameNumber = 0; + gl_pvpActive = NULL; + gl_ulFlags |= GLF_INITONNEXTWINDOW; + bFullScreen ? gl_ulFlags|=GLF_FULLSCREEN : gl_ulFlags&=~GLF_FULLSCREEN; + // mark that some things needs to be reinitialized + gl_fTextureLODBias = 0.0f; + + // set function pointers + GFX_SetFunctionPointers( (INDEX)gl_eCurrentAPI); + + // all done + return TRUE; +} + + +// Stop display mode and shutdown API +void CGfxLibrary::StopDisplayMode(void) +{ + // release all cached shadows and models' arrays + extern void Models_ClearVertexArrays(void); + extern void UncacheShadows(void); + Models_ClearVertexArrays(); + UncacheShadows(); + + // shutdown API + if( gl_eCurrentAPI==GAT_OGL) + { // OpenGL + EndDriver_OGL(); + MonitorsOn(); // re-enable multimonitor support if disabled + CDS_ResetMode(); + } +#ifdef SE1_D3D + else if( gl_eCurrentAPI==GAT_D3D) + { // Direct3D + EndDriver_D3D(); + MonitorsOn(); + } +#endif // SE1_D3D + else + { // none + ASSERT( gl_eCurrentAPI==GAT_NONE); + } + + // free driver DLL + if( gl_hiDriver!=NONE) FreeLibrary(gl_hiDriver); + gl_hiDriver = NONE; + + // reset some vars + gl_ctRealTextureUnits = 0; + gl_eCurrentAPI = GAT_NONE; + gl_pvpActive = NULL; + gl_ulFlags &= GLF_ADJUSTABLEGAMMA; + + // reset function pointers + GFX_SetFunctionPointers( (INDEX)GAT_NONE); +} + + + +// prepare current viewport for rendering +BOOL CGfxLibrary::SetCurrentViewport(CViewPort *pvp) +{ + if( gl_eCurrentAPI==GAT_OGL) return SetCurrentViewport_OGL(pvp); +#ifdef SE1_D3D + if( gl_eCurrentAPI==GAT_D3D) return SetCurrentViewport_D3D(pvp); +#endif // SE1_D3D + if( gl_eCurrentAPI==GAT_NONE) return TRUE; + ASSERTALWAYS( "SetCurrenViewport: Wrong API!"); + return FALSE; +} + + +// Lock a drawport for drawing +BOOL CGfxLibrary::LockDrawPort( CDrawPort *pdpToLock) +{ + // check API +#ifdef SE1_D3D + ASSERT( gl_eCurrentAPI==GAT_OGL || gl_eCurrentAPI==GAT_D3D || gl_eCurrentAPI==GAT_NONE); +#else // SE1_D3D + ASSERT( gl_eCurrentAPI==GAT_OGL || gl_eCurrentAPI==GAT_NONE); +#endif // SE1_D3D + + // don't allow locking if drawport is too small + if( pdpToLock->dp_Width<1 || pdpToLock->dp_Height<1) return FALSE; + + // don't set if same as last + const ULONG ulThisDrawPortID = pdpToLock->GetID(); + if( GFX_ulLastDrawPortID==ulThisDrawPortID && gap_bOptimizeStateChanges) { + // just set projection + pdpToLock->SetOrtho(); + return TRUE; + } + + // OpenGL ... + if( gl_eCurrentAPI==GAT_OGL) + { + // pass drawport dimensions to OpenGL + const PIX pixMinSI = pdpToLock->dp_ScissorMinI; + const PIX pixMaxSI = pdpToLock->dp_ScissorMaxI; + const PIX pixMinSJ = pdpToLock->dp_Raster->ra_Height -1 - pdpToLock->dp_ScissorMaxJ; + const PIX pixMaxSJ = pdpToLock->dp_Raster->ra_Height -1 - pdpToLock->dp_ScissorMinJ; + pglViewport( pixMinSI, pixMinSJ, pixMaxSI-pixMinSI+1, pixMaxSJ-pixMinSJ+1); + pglScissor( pixMinSI, pixMinSJ, pixMaxSI-pixMinSI+1, pixMaxSJ-pixMinSJ+1); + OGL_CHECKERROR; + } + // Direct3D ... +#ifdef SE1_D3D + else if( gl_eCurrentAPI==GAT_D3D) + { + // set viewport + const PIX pixMinSI = pdpToLock->dp_ScissorMinI; + const PIX pixMaxSI = pdpToLock->dp_ScissorMaxI; + const PIX pixMinSJ = pdpToLock->dp_ScissorMinJ; + const PIX pixMaxSJ = pdpToLock->dp_ScissorMaxJ; + D3DVIEWPORT8 d3dViewPort = { pixMinSI, pixMinSJ, pixMaxSI-pixMinSI+1, pixMaxSJ-pixMinSJ+1, 0,1 }; + HRESULT hr = gl_pd3dDevice->SetViewport( &d3dViewPort); + D3D_CHECKERROR(hr); + } +#endif // SE1_D3D + + // mark and set default projection + GFX_ulLastDrawPortID = ulThisDrawPortID; + pdpToLock->SetOrtho(); + return TRUE; +} + + + +// Unlock a drawport after drawing +void CGfxLibrary::UnlockDrawPort( CDrawPort *pdpToUnlock) +{ + // check API +#ifdef SE1_D3D + ASSERT(gl_eCurrentAPI == GAT_OGL || gl_eCurrentAPI == GAT_D3D || gl_eCurrentAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(gl_eCurrentAPI == GAT_OGL || gl_eCurrentAPI == GAT_NONE); +#endif // SE1_D3D + // eventually signalize that scene rendering has ended +} + + +///////////////////////////////////////////////////////////////////// +// Window canvas functions + +/* Create a new window canvas. */ +void CGfxLibrary::CreateWindowCanvas(void *hWnd, CViewPort **ppvpNew, CDrawPort **ppdpNew) +{ + RECT rectWindow; // rectangle for the client area of the window + + // get the dimensions from the window + GetClientRect( (HWND)hWnd, &rectWindow); + PIX pixWidth = rectWindow.right - rectWindow.left; + PIX pixHeight = rectWindow.bottom - rectWindow.top; + + *ppvpNew = NULL; + *ppdpNew = NULL; + // create a new viewport + if (*ppvpNew = new CViewPort( pixWidth, pixHeight, (HWND)hWnd)) { + // and it's drawport + *ppdpNew = &(*ppvpNew)->vp_Raster.ra_MainDrawPort; + } else { + delete *ppvpNew; + *ppvpNew = NULL; + } +} + +/* Destroy a window canvas. */ +void CGfxLibrary::DestroyWindowCanvas(CViewPort *pvpOld) { + // delete the viewport + delete pvpOld; +} + +///////////////////////////////////////////////////////////////////// +// Work canvas functions + +#define WorkCanvasCLASS "WorkCanvas Window" +static BOOL _bClassRegistered = FALSE; + +/* Create a work canvas. */ +void CGfxLibrary::CreateWorkCanvas(PIX pixWidth, PIX pixHeight, CDrawPort **ppdpNew) +{ + // must have dimensions + ASSERT (pixWidth>0 || pixHeight>0); + + if (!_bClassRegistered) { + _bClassRegistered = TRUE; + WNDCLASSA wc; + + // must have owndc for opengl and dblclks to give to parent + wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; + wc.lpfnWndProc = DefWindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = NULL; + wc.hIcon = NULL; + wc.hCursor = LoadCursor( NULL, IDC_ARROW ); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = WorkCanvasCLASS; + RegisterClassA(&wc); + } + + // create a window + HWND hWnd = ::CreateWindowExA( + 0, + WorkCanvasCLASS, + "", // title + WS_CLIPCHILDREN|WS_CLIPSIBLINGS|WS_POPUP, + 0,0, + pixWidth, pixHeight, // window size + NULL, + NULL, + NULL, //hInstance, + NULL); + ASSERT(hWnd != NULL); + + *ppdpNew = NULL; + CViewPort *pvp; + CreateWindowCanvas(hWnd, &pvp, ppdpNew); +} + +/* Destroy a work canvas. */ +void CGfxLibrary::DestroyWorkCanvas(CDrawPort *pdpOld) +{ + CViewPort *pvp = pdpOld->dp_Raster->ra_pvpViewPort; + HWND hwnd = pvp->vp_hWndParent; + DestroyWindowCanvas(pvp); + ::DestroyWindow(hwnd); +} + + + +// optimize memory used by cached shadow maps + +#define SHADOWMAXBYTES (256*256*4*4/3) +static SLONG slCachedShadowMemory=0, slDynamicShadowMemory=0; +static INDEX ctCachedShadows=0, ctFlatShadows=0, ctDynamicShadows=0; +extern BOOL _bShadowsUpdated = TRUE; + +void CGfxLibrary::ReduceShadows(void) +{ + _sfStats.StartTimer( CStatForm::STI_SHADOWUPDATE); + + // clamp shadow caching variables + shd_fCacheSize = Clamp( shd_fCacheSize, 0.1f, 128.0f); + shd_tmFlushDelay = Clamp( shd_tmFlushDelay, 0.1f, 120.0f); + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); // readout current time + const TIME tmAcientDelay = Clamp( shd_tmFlushDelay*3, 60.0f, 300.0f); + + // determine cached shadowmaps stats (if needed) + if( _bShadowsUpdated) + { + _bShadowsUpdated = FALSE; + slCachedShadowMemory=0; slDynamicShadowMemory=0; + ctCachedShadows=0; ctFlatShadows=0; ctDynamicShadows=0; + {FORDELETELIST( CShadowMap, sm_lnInGfx, _pGfx->gl_lhCachedShadows, itsm) { + CShadowMap &sm = *itsm; + ASSERT( sm.sm_pulCachedShadowMap!=NULL); // must be cached + ASSERT( sm.sm_slMemoryUsed>0 && sm.sm_slMemoryUsed<=SHADOWMAXBYTES); // and have valid size + // remove acient shadowmaps from list (if allowed) + const TIME tmDelta = (tvNow-sm.sm_tvLastDrawn).GetSeconds(); + if( tmDelta>tmAcientDelay && !(sm.sm_ulFlags&SMF_PROBED) && !shd_bCacheAll) { + sm.Uncache(); + continue; + } + // determine type and occupied space + const BOOL bDynamic = sm.sm_pulDynamicShadowMap!=NULL; + const BOOL bFlat = sm.sm_pulCachedShadowMap==&sm.sm_colFlat; + if( bDynamic) { slDynamicShadowMemory += sm.sm_slMemoryUsed; ctDynamicShadows++; } + if( !bFlat) { slCachedShadowMemory += sm.sm_slMemoryUsed; ctCachedShadows++; } + else { slCachedShadowMemory += sizeof(sm.sm_colFlat); ctFlatShadows++; } + }} + } + // update statistics counters + _pfGfxProfile.IncrementCounter(CGfxProfile::PCI_CACHEDSHADOWBYTES, slCachedShadowMemory); + _pfGfxProfile.IncrementCounter(CGfxProfile::PCI_CACHEDSHADOWS, ctCachedShadows); + _pfGfxProfile.IncrementCounter(CGfxProfile::PCI_FLATSHADOWS, ctFlatShadows); + _pfGfxProfile.IncrementCounter(CGfxProfile::PCI_DYNAMICSHADOWBYTES, slDynamicShadowMemory); + _pfGfxProfile.IncrementCounter(CGfxProfile::PCI_DYNAMICSHADOWS, ctDynamicShadows); + _sfStats.IncrementCounter( CStatForm::SCI_CACHEDSHADOWBYTES, slCachedShadowMemory); + _sfStats.IncrementCounter( CStatForm::SCI_CACHEDSHADOWS, ctCachedShadows); + _sfStats.IncrementCounter( CStatForm::SCI_FLATSHADOWS, ctFlatShadows); + _sfStats.IncrementCounter( CStatForm::SCI_DYNAMICSHADOWBYTES, slDynamicShadowMemory); + _sfStats.IncrementCounter( CStatForm::SCI_DYNAMICSHADOWS, ctDynamicShadows); + + // done if reducing is not allowed + if( shd_bCacheAll) { + _sfStats.StopTimer( CStatForm::STI_SHADOWUPDATE); + return; + } + + // optimize only if low on memory + ULONG ulShadowCacheSize = (ULONG)(shd_fCacheSize*1024*1024); // in bytes + ULONG ulUsedShadowMemory = slCachedShadowMemory + slDynamicShadowMemory; + if( ulUsedShadowMemory <= ulShadowCacheSize) { + _sfStats.StopTimer( CStatForm::STI_SHADOWUPDATE); + return; + } + + // reduce shadow delay if needed + // (lineary from specified value to 2sec for cachedsize>specsize to cachedsize>2*specsize) + TIME tmFlushDelay = shd_tmFlushDelay; + if( tmFlushDelay>2.0f) { + FLOAT fRatio = (FLOAT)ulUsedShadowMemory / ulShadowCacheSize; + ASSERT( fRatio>=1.0f); + fRatio = ClampUp( fRatio/2.0f, 1.0f); + tmFlushDelay = Lerp( tmFlushDelay, 2.0f, fRatio); + } + + // loop thru cached shadowmaps list + {FORDELETELIST( CShadowMap, sm_lnInGfx, _pGfx->gl_lhCachedShadows, itsm) + { // stop iteration if current shadow map it is not too old (list is sorted by time) + // or we have enough memory for cached shadows that remain + CShadowMap &sm = *itsm; + const TIME tmDelta = (tvNow-sm.sm_tvLastDrawn).GetSeconds(); + if( tmDelta=0); + }} + // done + _sfStats.StopTimer( CStatForm::STI_SHADOWUPDATE); +} + + + +// some vars for probing +extern INDEX _ctProbeTexs = 0; +extern INDEX _ctProbeShdU = 0; +extern INDEX _ctProbeShdB = 0; +extern INDEX _ctFullShdU = 0; +extern SLONG _slFullShdUBytes = 0; +static BOOL GenerateGammaTable(void); + + + +/* + * Swap buffers in a viewport. + */ +void CGfxLibrary::SwapBuffers(CViewPort *pvp) +{ + // check API +#ifdef SE1_D3D + ASSERT(gl_eCurrentAPI == GAT_OGL || gl_eCurrentAPI == GAT_D3D || gl_eCurrentAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(gl_eCurrentAPI == GAT_OGL || gl_eCurrentAPI == GAT_NONE); +#endif // SE1_D3D + + // safety check + ASSERT( gl_pvpActive!=NULL); + if( pvp!=gl_pvpActive) { + ASSERTALWAYS( "Swapping viewport that was not last drawn to!"); + return; + } + + // optimize memory used by cached shadow maps and update shadowmap counters + ReduceShadows(); + + // check and eventually adjust texture filtering and LOD biasing + gfxSetTextureFiltering( gap_iTextureFiltering, gap_iTextureAnisotropy); + gfxSetTextureBiasing( gap_fTextureLODBias); + + // clamp some cvars + gap_iDithering = Clamp( gap_iDithering, 0L, 2L); + gap_iSwapInterval = Clamp( gap_iSwapInterval, 0L, 4L); + gap_iOptimizeClipping = Clamp( gap_iOptimizeClipping, 0L, 2L); + gap_iTruformLevel = Clamp( gap_iTruformLevel, 0L, _pGfx->gl_iMaxTessellationLevel); + ogl_iFinish = Clamp( ogl_iFinish, 0L, 3L); + d3d_iFinish = Clamp( d3d_iFinish, 0L, 3L); + + // OpenGL + if( gl_eCurrentAPI==GAT_OGL) + { + // force finishing of all rendering operations (if required) + if( ogl_iFinish==2) gfxFinish(); + + // check state of swap interval extension usage + if( gl_ulFlags & GLF_VSYNC) { + if( gl_iSwapInterval != gap_iSwapInterval) { + gl_iSwapInterval = gap_iSwapInterval; + pwglSwapIntervalEXT( gl_iSwapInterval); + } + } + // swap buffers + CTempDC tdc(pvp->vp_hWnd); + pwglSwapBuffers(tdc.hdc); + + // force finishing of all rendering operations (if required) + if( ogl_iFinish==3) gfxFinish(); + + // reset CVA usage if ext is not present + if( !(gl_ulFlags&GLF_EXT_COMPILEDVERTEXARRAY)) ogl_bUseCompiledVertexArrays = 0; + } + + // Direct3D +#ifdef SE1_D3D + else if( gl_eCurrentAPI==GAT_D3D) + { + // force finishing of all rendering operations (if required) + if( d3d_iFinish==2) gfxFinish(); + + // end scene rendering + HRESULT hr; + if( GFX_bRenderingScene) { + hr = gl_pd3dDevice->EndScene(); + D3D_CHECKERROR(hr); + } + CDisplayMode dm; + GetCurrentDisplayMode(dm); + ASSERT( (dm.dm_pixSizeI==0 && dm.dm_pixSizeJ==0) || (dm.dm_pixSizeI!=0 && dm.dm_pixSizeJ!=0)); + if( dm.dm_pixSizeI==0 || dm.dm_pixSizeJ==0 ) { + // windowed mode + hr = pvp->vp_pSwapChain->Present( NULL, NULL, NULL, NULL); + } else { + // full screen mode + hr = gl_pd3dDevice->Present( NULL, NULL, NULL, NULL); + } // done swapping + D3D_CHECKERROR(hr); + + // force finishing of all rendering operations (if required) + if( d3d_iFinish==3) gfxFinish(); + + // eventually reset vertex buffer if something got changed + if( _iLastVertexBufferSize!=d3d_iVertexBuffersSize + || (gl_iTessellationLevel<1 && gap_iTruformLevel>0) + || (gl_iTessellationLevel>0 && gap_iTruformLevel<1)) { + extern void SetupVertexArrays_D3D( INDEX ctVertices); + extern void SetupIndexArray_D3D( INDEX ctVertices); + extern DWORD SetupShader_D3D( ULONG ulStreamsMask); + SetupShader_D3D(NONE); + SetupVertexArrays_D3D(0); + SetupIndexArray_D3D(0); + extern INDEX VerticesFromSize_D3D( SLONG &slSize); + const INDEX ctVertices = VerticesFromSize_D3D(d3d_iVertexBuffersSize); + SetupVertexArrays_D3D(ctVertices); + SetupIndexArray_D3D(2*ctVertices); + _iLastVertexBufferSize = d3d_iVertexBuffersSize; + } + } +#endif // SE1_D3D + // update tessellation level + gl_iTessellationLevel = gap_iTruformLevel; + + // must reset drawport and rendering status for subsequent locks + GFX_ulLastDrawPortID = 0; + GFX_bRenderingScene = FALSE; + // reset frustum/ortho matrix, too + extern BOOL GFX_bViewMatrix; + extern FLOAT GFX_fLastL, GFX_fLastR, GFX_fLastT, GFX_fLastB, GFX_fLastN, GFX_fLastF; + GFX_fLastL = GFX_fLastR = GFX_fLastT = GFX_fLastB = GFX_fLastN = GFX_fLastF = 0; + GFX_bViewMatrix = TRUE; + + // set maximum allowed upload ammount + gfx_iProbeSize = Clamp( gfx_iProbeSize, 1L, 16384L); + gl_slAllowedUploadBurst = gfx_iProbeSize *1024; + _ctProbeTexs = 0; + _ctProbeShdU = 0; + _ctProbeShdB = 0; + _ctFullShdU = 0; + _slFullShdUBytes = 0; + + // keep time when swap buffer occured and maintain counter of frames for temporal coherence checking + gl_tvFrameTime = _pTimer->GetHighPrecisionTimer(); + gl_iFrameNumber++; + // reset profiling counters + gl_ctWorldTriangles = 0; + gl_ctModelTriangles = 0; + gl_ctParticleTriangles = 0; + gl_ctTotalTriangles = 0; + + // re-adjust multi-texturing support + gap_iUseTextureUnits = Clamp( gap_iUseTextureUnits, 1L, _pGfx->gl_ctTextureUnits); + ASSERT( gap_iUseTextureUnits>=1 && gap_iUseTextureUnits<=GFX_MAXTEXUNITS); + + // re-get usage of compiled vertex arrays + CVA_b2D = ogl_bUseCompiledVertexArrays /100; + CVA_bWorld = ogl_bUseCompiledVertexArrays /10 %10; + CVA_bModels = ogl_bUseCompiledVertexArrays %10; + ogl_bUseCompiledVertexArrays = 0; + if( CVA_b2D) ogl_bUseCompiledVertexArrays += 100; + if( CVA_bWorld) ogl_bUseCompiledVertexArrays += 10; + if( CVA_bModels) ogl_bUseCompiledVertexArrays += 1; + + // eventually advance to next sample buffer + if( (gl_ulFlags&GLF_EXT_TBUFFER) && go_ctSampleBuffers>1) { + go_iCurrentWriteBuffer--; + if( go_iCurrentWriteBuffer<0) go_iCurrentWriteBuffer = go_ctSampleBuffers-1; + pglDisable( GL_MULTISAMPLE_3DFX); + } + + // clear viewport if needed + if( gfx_bClearScreen) pvp->vp_Raster.ra_MainDrawPort.Fill( C_BLACK|CT_OPAQUE); + //pvp->vp_Raster.ra_MainDrawPort.FillZBuffer(ZBUF_BACK); + + // adjust gamma table if supported ... + if( gl_ulFlags & GLF_ADJUSTABLEGAMMA) { + // ... and required + const BOOL bTableSet = GenerateGammaTable(); + if( bTableSet) { + if( gl_eCurrentAPI==GAT_OGL) { + CTempDC tdc(pvp->vp_hWnd); + SetDeviceGammaRamp( tdc.hdc, &_auwGammaTable[0]); + } +#ifdef SE1_D3D + else if( gl_eCurrentAPI==GAT_D3D) { + gl_pd3dDevice->SetGammaRamp( D3DSGR_NO_CALIBRATION, (D3DGAMMARAMP*)&_auwGammaTable[0]); + } +#endif // SE1_D3D + } + } + // if not supported + else { + // just reset settings to default + gfx_fBrightness = 0; + gfx_fContrast = 1; + gfx_fGamma = 1; + gfx_fBiasR = 1; + gfx_fBiasG = 1; + gfx_fBiasB = 1; + gfx_iLevels = 256; + } +} + + + + +// get array of all supported display modes +CDisplayMode *CGfxLibrary::EnumDisplayModes( INDEX &ctModes, enum GfxAPIType eAPI/*=GAT_CURRENT*/, INDEX iAdapter/*=0*/) +{ + if( eAPI==GAT_CURRENT) eAPI = gl_eCurrentAPI; + if( iAdapter==0) iAdapter = gl_iCurrentAdapter; + CDisplayAdapter *pda = &gl_gaAPI[eAPI].ga_adaAdapter[iAdapter]; + ctModes = pda->da_ctDisplayModes; + return &pda->da_admDisplayModes[0]; +} + + + +// Lock a raster for drawing. +BOOL CGfxLibrary::LockRaster( CRaster *praToLock) +{ + // don't do this! it can break sync consistency in entities! + // SetFPUPrecision(FPT_24BIT); + ASSERT( praToLock->ra_pvpViewPort!=NULL); + BOOL bRes = SetCurrentViewport( praToLock->ra_pvpViewPort); + if( bRes) { + // must signal to picky Direct3D +#ifdef SE1_D3D + if( gl_eCurrentAPI==GAT_D3D && !GFX_bRenderingScene) { + HRESULT hr = gl_pd3dDevice->BeginScene(); + D3D_CHECKERROR(hr); + bRes = (hr==D3D_OK); + } // mark it +#endif // SE1_D3D + GFX_bRenderingScene = TRUE; + } // done + return bRes; +} + + +// Unlock a raster after drawing. +void CGfxLibrary::UnlockRaster( CRaster *praToUnlock) +{ + // don't do this! it can break sync consistency in entities! + // SetFPUPrecision(FPT_53BIT); + ASSERT( GFX_bRenderingScene); +} + + + +// generates gamma table and returns true if gamma table has been changed +static BOOL GenerateGammaTable(void) +{ + // only if needed + if( _fLastBrightness == gfx_fBrightness + && _fLastContrast == gfx_fContrast + && _fLastGamma == gfx_fGamma + && _iLastLevels == gfx_iLevels + && _fLastBiasR == gfx_fBiasR + && _fLastBiasG == gfx_fBiasG + && _fLastBiasB == gfx_fBiasB) return FALSE; + + // guess it's needed + INDEX i; + gfx_fBrightness = Clamp( gfx_fBrightness, -0.8f, 0.8f); + gfx_fContrast = Clamp( gfx_fContrast, 0.2f, 4.0f); + gfx_fGamma = Clamp( gfx_fGamma, 0.2f, 4.0f); + gfx_iLevels = Clamp( gfx_iLevels, 2L, 256L); + gfx_fBiasR = Clamp( gfx_fBiasR, 0.0f, 2.0f); + gfx_fBiasG = Clamp( gfx_fBiasG, 0.0f, 2.0f); + gfx_fBiasB = Clamp( gfx_fBiasB, 0.0f, 2.0f); + _fLastBrightness = gfx_fBrightness; + _fLastContrast = gfx_fContrast; + _fLastGamma = gfx_fGamma; + _iLastLevels = gfx_iLevels; + _fLastBiasR = gfx_fBiasR; + _fLastBiasG = gfx_fBiasG; + _fLastBiasB = gfx_fBiasB; + + // fill and adjust gamma + const FLOAT f1oGamma = 1.0f / gfx_fGamma; + for( i=0; i<256; i++) { + FLOAT fVal = i/255.0f; + fVal = Clamp( (FLOAT)pow(fVal,f1oGamma), 0.0f, 1.0f); + _auwGammaTable[i] = (UWORD)(fVal*65280); + } + + // adjust contrast + for( i=0; i<256; i++) { + FLOAT fVal = _auwGammaTable[i]/65280.0f; + fVal = Clamp( (fVal-0.5f)*gfx_fContrast +0.5f, 0.0f, 1.0f); + _auwGammaTable[i] = (UWORD)(fVal*65280); + } + + // adjust brightness + INDEX iAdd = 256* 256*gfx_fBrightness; + for( i=0; i<256; i++) { + _auwGammaTable[i] = Clamp( _auwGammaTable[i]+iAdd, 0L, 65280L); + } + + // adjust levels (posterize) + if( gfx_iLevels<256) { + const FLOAT fLevels = 256 * 256.0f/gfx_iLevels; + for( i=0; i<256; i++) { + INDEX iVal = _auwGammaTable[i]; + iVal = ((INDEX)(iVal/fLevels)) *fLevels; + _auwGammaTable[i] = ClampUp( iVal, 0xFF00L); + } + } + + // copy R to G and B array + for( i=0; i<256; i++) { + FLOAT fR,fG,fB; + fR=fG=fB = _auwGammaTable[i]/65280.0f; + fR = Clamp( fR*gfx_fBiasR, 0.0f, 1.0f); + fG = Clamp( fG*gfx_fBiasG, 0.0f, 1.0f); + fB = Clamp( fB*gfx_fBiasB, 0.0f, 1.0f); + _auwGammaTable[i+0] = (UWORD)(fR*65280); + _auwGammaTable[i+256] = (UWORD)(fG*65280); + _auwGammaTable[i+512] = (UWORD)(fB*65280); + } + + // done + return TRUE; +} + + + +#if 0 + + +DeclareSymbol( "[persistent] [hidden] [const] [type] name [minval] [maxval] [func()]", &shd_iStaticQuality, func()=NULL); + + +_pShell->DeclareSymbol( "INDEX GfxVarPreFunc(INDEX);", &GfxVarPreFunc); +_pShell->DeclareSymbol( "void GfxVarPostFunc(INDEX);", &GfxVarPostFunc); + +static BOOL GfxVarPreFunc(void *pvVar) +{ + if (pvVar==&gfx_fSaturation) { + CPrintF("cannot change saturation: just for test\n"); + return FALSE; + } else { + CPrintF("gfx var about to be changed\n"); + return TRUE; + } +} + +static void GfxVarPostFunc(void *pvVar) +{ + if (pvVar==&shd_bFineQuality) { + CPrintF("This requires RefreshTextures() to take effect!\n"); + } +} + + +#endif + + + + diff --git a/Sources/Engine/Graphics/GfxLibrary.h b/Sources/Engine/Graphics/GfxLibrary.h new file mode 100644 index 0000000..9cf9c7f --- /dev/null +++ b/Sources/Engine/Graphics/GfxLibrary.h @@ -0,0 +1,346 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_GFXLIBRARY_H +#define SE_INCL_GFXLIBRARY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#ifdef SE1_D3D +#include +#endif // SE1_D3D +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +// common element arrays +extern CStaticStackArray _avtxCommon; +extern CStaticStackArray _atexCommon; +extern CStaticStackArray _acolCommon; +extern CStaticStackArray _aiCommonElements; +extern CStaticStackArray _aiCommonQuads; + + +#include + + +#define SQRTTABLESIZE 8192 +#define SQRTTABLESIZELOG2 13 + +#define GFX_MAXTEXUNITS (4L) // maximum number of supported texture units for multitexturing +#define GFX_MINSTREAMS (3L) // minimum number of D3D streams in order to support HW T&L +#define GFX_MAXLAYERS (5L) // suggested maximum number of multi-passes per one polygon + +// D3D vertex for simple draw functions +struct CTVERTEX { + FLOAT fX,fY,fZ; // position + ULONG ulColor; // color + FLOAT fU,fV; // texture coordinates +}; +#define D3DFVF_CTVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1) + + +// Gfx API type +enum GfxAPIType +{ + GAT_NONE = -1, // no gfx API (gfx functions are disabled) + GAT_OGL = 0, // OpenGL +#ifdef SE1_D3D + GAT_D3D = 1, // Direct3D +#endif // SE1_D3D + GAT_CURRENT = 9, // current API +}; + + +// vertex type (for lock/unlock function) +enum VtxType +{ + VXT_LOC = 1, // x,y,z location + VXT_NOR = 2, // normal + VXT_TEX = 3, // texture coords + VXT_COL = 4, // color +}; + + +// common flags +#define GLF_HASACCELERATION (1UL<<0) // set if current mode supports hardware acceleration +#define GLF_INITONNEXTWINDOW (1UL<<1) // initialize rendering context on next window +#define GLF_ADJUSTABLEGAMMA (1UL<<2) // set if display allows gamma adjustment +#define GLF_TEXTURECOMPRESSION (1UL<<3) // set if texture compression is supported +#define GLF_32BITTEXTURES (1UL<<4) // 32-bit textures +#define GLF_VSYNC (1UL<<5) // supports wait for VSYNC +#define GLF_FULLSCREEN (1UL<<9) // currently in full-screen mode + +// Direct3D specific +#define GLF_D3D_HASHWTNL (1UL<<10) // supports hardware T&L +#define GLF_D3D_USINGHWTNL (1UL<<11) // using hardware T&L +#define GLF_D3D_CLIPPLANE (1UL<<12) // supports at least one custom clip plane +#define GLF_D3D_COLORWRITES (1UL<<13) // supports enable/disable writes to color buffer +#define GLF_D3D_ZBIAS (1UL<<14) // supports z-biasing + +// OpenGL extensions (part of flags!) +#define GLF_EXT_TBUFFER (1UL<<19) // 3DFX's T-Buffer (for partial FSAA & Motion-blur effects) +#define GLF_EXT_EDGECLAMP (1UL<<20) // GL_EXT_texture_edge_clamp +#define GLF_EXT_COMPILEDVERTEXARRAY (1UL<<21) // GL_EXT_compiled_vertex_array +#define GLF_EXT_CLIPHINT (1UL<<22) // GL_EXT_clip_volume_hint +#define GLF_EXT_OCCLUSIONTEST (1UL<<23) // GL_HP_occlusion_test +#define GLF_EXT_OCCLUSIONQUERY (1UL<<24) // GL_NV_occlusion_query + +#define GLF_EXTC_ARB (1UL<<27) // GL_ARB_texture_compression +#define GLF_EXTC_S3TC (1UL<<28) // GL_EXT_texture_compression_s3tc +#define GLF_EXTC_FXT1 (1UL<<29) // GL_3DFX_texture_compression_FXT1 +#define GLF_EXTC_LEGACY (1UL<<30) // GL_S3_s3tc + + +/* + * Graphics library object. + */ +class ENGINE_API CGfxLibrary +{ +public: + CGfxAPI gl_gaAPI[2]; + CViewPort *gl_pvpActive; // active viewport + HINSTANCE gl_hiDriver; // DLL handle + + GfxAPIType gl_eCurrentAPI; // (0=none, 1=OpenGL, 2=DirectX8) + CDisplayMode gl_dmCurrentDisplayMode; + INDEX gl_iCurrentAdapter; + INDEX gl_iCurrentDepth; + INDEX gl_ctDriverChanges; // count of driver changes + ULONG gl_ulFlags; + +#ifdef SE1_D3D + // DirectX info + LPDIRECT3D8 gl_pD3D; // used to create the D3DDevice + LPDIRECT3DDEVICE8 gl_pd3dDevice; // rendering device + D3DFORMAT gl_d3dColorFormat; // current color format + D3DFORMAT gl_d3dDepthFormat; // z-buffer depth format + // DirectX vertex/index buffers + LPDIRECT3DVERTEXBUFFER8 gl_pd3dVtx; + LPDIRECT3DVERTEXBUFFER8 gl_pd3dNor; + LPDIRECT3DVERTEXBUFFER8 gl_pd3dCol[GFX_MAXLAYERS]; + LPDIRECT3DVERTEXBUFFER8 gl_pd3dTex[GFX_MAXLAYERS]; + LPDIRECT3DINDEXBUFFER8 gl_pd3dIdx; +#endif // SE1_D3D + INDEX gl_ctVertices, gl_ctIndices; // size of buffers + INDEX gl_ctColBuffers, gl_ctTexBuffers; // number of color and texture buffers (for multi-pass rendering) + INDEX gl_ctMaxStreams; // maximum number of streams + DWORD gl_dwVertexShader; + + // OpenGL info + HGLRC go_hglRC; // rendering context + CTString go_strExtensions; // reported extensions + CTString go_strWinExtensions; + CTString go_strSupportedExtensions; // supported extensions + INDEX go_ctSampleBuffers; // number of rendering buffers currently on (for T-buffer's motion-blur effect) 0=not supported + INDEX go_iCurrentWriteBuffer; // current buffer enabled for writing + + // common stuff + + PIX gl_pixMaxTextureDimension; // maximum allowed texture dimension by driver + INDEX gl_iSwapInterval; // current swap interval (0=immediate, n=VSyncs to wait) + INDEX gl_ctTextureUnits; // maximum supported texture units (1=no multitexturing) + INDEX gl_ctRealTextureUnits; // maximum reported texture units + FLOAT gl_fTextureLODBias; // current texture lod bias + FLOAT gl_fMaxTextureLODBias; // absolute maximum possible texture lod bias (0 if biasing is not supported) + INDEX gl_iMaxTextureAnisotropy; // maximum possible texture degree of anisotropy (1 if isotropic only) + INDEX gl_iMaxTessellationLevel; // maximum possible truform tesselation level (0=no truform) + INDEX gl_iTessellationLevel; // current tesselation level + + INDEX gl_iFrameNumber; // frame number currently rendering + CTimerValue gl_tvFrameTime; // time when swapbuffer occured + SLONG gl_slAllowedUploadBurst; // remain upload burst size for this frame (max texture or shadowmap size *2) + CListHead gl_lhCachedShadows; // list of all cached shadowmaps + CListHead gl_lhRenderTextures; // list of all render-textures + BOOL gl_bAllowProbing; + + // for profiling + INDEX gl_ctWorldTriangles; // how many world polygons were rendered in last frame + INDEX gl_ctModelTriangles; // how many model polygons were rendered in last frame + INDEX gl_ctParticleTriangles; // how many particle polygons were rendered in last frame + INDEX gl_ctTotalTriangles; // total = (world & lensflares) + (model & shadows) + particle + 2D + +private: + + void InitAPIs(void); + // start full-screen or windowed mode (pixSizeI=pixSizeJ=0 & iAdapter=0 if windowed) + BOOL StartDisplayMode( enum GfxAPIType eAPI, INDEX iAdapter, PIX pixSizeI, PIX pixSizeJ, + enum DisplayDepth eColorDepth); + void StopDisplayMode(void); + + // OpenGL specific + BOOL InitDriver_OGL( BOOL b3Dfx=FALSE); // DLL init and function call adjustments + void EndDriver_OGL(void); + void TestExtension_OGL( ULONG ulFlag, const char *strName); // if exist, add OpenGL extension to flag and list + void AddExtension_OGL( ULONG ulFlag, const char *strName); // unconditionally add OpenGL extension to flag and list +#ifdef PLATFORM_WIN32 + BOOL CreateContext_OGL( HDC hdc); + BOOL SetupPixelFormat_OGL( HDC hdc, BOOL bReport=FALSE); +#endif + void InitContext_OGL(void); + BOOL SetCurrentViewport_OGL( CViewPort *pvp); + void UploadPattern_OGL( ULONG ulPatternEven); + void SwapBuffers_OGL( CViewPort *pvpToSwap); + + // Direct3D specific + BOOL InitDriver_D3D(void); + void EndDriver_D3D(void); + BOOL InitDisplay_D3D( INDEX iAdapter, PIX pixSizeI, PIX pixSizeJ, enum DisplayDepth eColorDepth); + void InitContext_D3D(void); + BOOL SetCurrentViewport_D3D( CViewPort *pvp); + void UploadPattern_D3D( ULONG ulPatternEven); + void SwapBuffers_D3D( CViewPort *pvpToSwap); + +public: + + // common + CGfxLibrary(); // init cvars + ~CGfxLibrary(); // clean up + + // optimize memory used by cached shadow maps + void ReduceShadows(void); + + // pretouch all textures and cached shadowmaps + void PretouchIfNeeded(void); + + // get array of all supported display modes (do not modify array!) + CDisplayMode *EnumDisplayModes( INDEX &ctModes, enum GfxAPIType eAPI=GAT_CURRENT, INDEX iAdapter=0); + + // set viewport for rendering + BOOL SetCurrentViewport( CViewPort *pvp); + // swap buffers in a viewport + void SwapBuffers( CViewPort *pvpToSwap); + // return current frame number + inline INDEX GetFrameNumber(void) { return gl_iFrameNumber; }; + + // lock/unlock raster for drawing + BOOL LockRaster( CRaster *praToLock); + void UnlockRaster( CRaster *praToUnlock); + // lock/unlock drawport for drawing + BOOL LockDrawPort( CDrawPort *pdpToLock); + void UnlockDrawPort( CDrawPort *pdpToUnlock); + + // initialize library + void Init(void); + + // set new display mode + BOOL SetDisplayMode( enum GfxAPIType eAPI, INDEX iAdapter, PIX pixSizeI, PIX pixSizeJ, + enum DisplayDepth eColorDepth); + // set display mode to original desktop display mode (and eventually change API) + BOOL ResetDisplayMode( enum GfxAPIType eAPI=GAT_CURRENT); + + // get current API/adapter/display mode + inline enum GfxAPIType GetCurrentAPI(void) { return gl_eCurrentAPI; }; + inline INDEX GetCurrentAdapter(void) { return gl_iCurrentAdapter; }; + inline void GetCurrentDisplayMode( CDisplayMode &dmCurrent) { dmCurrent = gl_dmCurrentDisplayMode; }; + + // check if 3D acceleration is on + inline BOOL IsCurrentModeAccelerated(void) { return (gl_ulFlags&GLF_HASACCELERATION); }; + // check if DualHead is on + inline BOOL IsCurrentModeDH(void) { return gl_dmCurrentDisplayMode.IsDualHead(); }; + + // is API supported + inline BOOL HasAPI( enum GfxAPIType eAPI) { + if( eAPI==GAT_CURRENT) return TRUE; + if( eAPI==GAT_OGL) return (gl_gaAPI[0].ga_ctAdapters>0); +#ifdef SE1_D3D + if( eAPI==GAT_D3D) return (gl_gaAPI[1].ga_ctAdapters>0); +#endif // SE1_D3D + return FALSE; + }; + + // canvas functions + void CreateWindowCanvas( void *hWnd, CViewPort **ppvpNew, CDrawPort **ppdpNew); // Create a new window canvas + void DestroyWindowCanvas( CViewPort *pvpOld); // Destroy a window canvas + void CreateWorkCanvas( PIX pixWidth, PIX pixHeight, CDrawPort **ppdpNew); // Create a work canvas + void DestroyWorkCanvas( CDrawPort *pdpOld); // Destroy a work canvas + + // simple benchmark routine + void Benchmark( CViewPort *pvp, CDrawPort *pdp); +}; + + +struct MipmapTable { + INDEX mmt_ctMipmaps; // number of mip-maps + SLONG mmt_slTotalSize; // total size of all mip-maps (in pixels) + PIX mmt_pixU; // size of first mip-map + PIX mmt_pixV; + SLONG mmt_aslOffsets[MAX_MEX_LOG2]; // offsets of each mip-map (in pixels) +}; + + +// returns number of mip-maps to skip from original texture depending on maximum allowed texture +// size (in pixels!) and maximum allowed texture dimension (in pixels, too!) +extern INDEX ClampTextureSize( PIX pixClampSize, PIX pixClampDimension, PIX pixSizeU, PIX pixSizeV); + +// create mip-map table for texture or shadow of given dimensions +extern void MakeMipmapTable( PIX pixU, PIX pixV, MipmapTable &mmt); + +// adds 8-bit opaque alpha channel to 24-bit bitmap (in place suported) +extern void AddAlphaChannel( UBYTE *pubSrcBitmap, ULONG *pulDstBitmap, PIX pixSize, UBYTE *pubAlphaBitmap=NULL); +// removes 8-bit alpha channel from 32-bit bitmap (in place suported) +extern void RemoveAlphaChannel( ULONG *pulSrcBitmap, UBYTE *pubDstBitmap, PIX pixSize); + +// flips 24 or 32-bit bitmap (iType: 1-horizontal, 2-vertical, 3-diagonal) - in place supported +extern void FlipBitmap( UBYTE *pubSrc, UBYTE *pubDst, PIX pixWidth, PIX pixHeight, INDEX iFlipType, BOOL bAlphaChannel); + + +// makes ALL lower mipmaps (to size of Nx1 or 1xM) of a specified 32-bit bitmap with eventual filter appliance +// this is done in-place! - all subsequent mip-maps will be posioned just after the original, input bitmap) +// (only first ctFineMips number of mip-maps will be filtered with bilinear subsampling, while +// all others will be downsampled with nearest-neighbour method with border preservance) +extern void MakeMipmaps( INDEX ctFineMips, ULONG *pulMipmaps, PIX pixWidth, PIX pixHeight, INDEX iFilter=NONE); + +// colorize mipmaps +extern void ColorizeMipmaps( INDEX i1stMipmapToColorize, ULONG *pulMipmaps, PIX pixWidth, PIX pixHeight); + + +// performs dithering of a 32-bit bipmap (can be in-place) +extern void DitherBitmap( INDEX iDitherType, ULONG *pulSrc, ULONG *pulDst, PIX pixWidth, PIX pixHeight, + PIX pixCanvasWidth=0, PIX pixCanvasHeight=0); +// performs dithering of a 32-bit mipmaps (can be in-place) +extern void DitherMipmaps( INDEX iDitherType, ULONG *pulSrc, ULONG *pulDst, PIX pixWidth, PIX pixHeight); + +// adjust bitmap's saturation and/or hue (hue 0 and saturation 256 are defaults) +extern void AdjustBitmapColor( ULONG *pulSrc, ULONG *pulDst, PIX pixWidth, PIX pixHeight, + SLONG const slHueShift, SLONG const slSaturation); + +// applies filter to 32-bit bitmap (iFilter from -6 to 6; negative=sharpen, positive=blur, 0=none) +extern void FilterBitmap( INDEX iFilter, ULONG *pulSrc, ULONG *pulDst, PIX pixWidth, PIX pixHeight, + PIX pixCanvasWidth=0, PIX pixCanvasHeight=0); + + + +// retrives number of mip-maps for the given bitmap size +__forceinline INDEX GetNoOfMipmaps( PIX pixWidth, PIX pixHeight) { return( FastLog2( Min(pixWidth, pixHeight))+1); } + +// retrives memory offset of a specified mip-map or a size of all mip-maps (IN PIXELS!) +// (zero offset means first, i.e. largest mip-map) +extern PIX GetMipmapOffset( INDEX iMipLevel, PIX pixWidth, PIX pixHeight); + +// return offset, pointer and dimensions of mipmap of specified size inside texture or shadowmap mipmaps +extern INDEX GetMipmapOfSize( PIX pixSize, ULONG *&pulFrame, PIX &pixProbeWidth, PIX &pixProbeHeight); + + +// flat white texture +ENGINE_API extern CTextureData *_ptdFlat; + +// global texture parameters in engine +ENGINE_API extern CTexParams _tpGlobal[GFX_MAXTEXUNITS]; + +// pointer to global graphics library object +ENGINE_API extern CGfxLibrary *_pGfx; +// forced texture upload quality (0 = default, 16 = force 16-bit, 32 = force 32-bit) +ENGINE_API extern INDEX _iTexForcedQuality; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/GfxProfile.cpp b/Sources/Engine/Graphics/GfxProfile.cpp new file mode 100644 index 0000000..3ba5370 --- /dev/null +++ b/Sources/Engine/Graphics/GfxProfile.cpp @@ -0,0 +1,62 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +// profile form for profiling gfx +CGfxProfile gpGfxProfile; +CProfileForm &_pfGfxProfile = gpGfxProfile; + +CGfxProfile::CGfxProfile(void) + : CProfileForm ("Gfx", "frames", + CGfxProfile::PCI_COUNT, CGfxProfile::PTI_COUNT) +{ + // initialize timers + SETTIMERNAME(PTI_LOCKDRAWPORT, "LockDrawPort()", ""); + SETTIMERNAME(PTI_SWAPBUFFERS, "SwapBuffers()", ""); + SETTIMERNAME(PTI_PUTTEXTURE, "PutTexture()", ""); + SETTIMERNAME(PTI_PUTTEXT, "PutText()", ""); + SETTIMERNAME(PTI_CACHESHADOW, "CacheShadow", ""); + SETTIMERNAME(PTI_SETCURRENTTEXTURE, "SetCurrentTexture", "setting"); + SETTIMERNAME(PTI_TEXTUREPARAMS, " TextureParams", ""); + SETTIMERNAME(PTI_TEXTUREUPLOADING, " TextureUploading", ""); + SETTIMERNAME(PTI_MAKEMIPMAPS, "MakeMipmaps()", ""); + SETTIMERNAME(PTI_DITHERBITMAP, "DitherBitmap()", ""); + SETTIMERNAME(PTI_FILTERBITMAP, "FilterBitmap()", ""); + + SETTIMERNAME(PTI_RENDERSCENE, "RenderScene", ""); + SETTIMERNAME(PTI_RENDERSCENE_BCG, "rs_RenderScene_bcg", ""); + SETTIMERNAME(PTI_RENDERSCENE_ZONLY, "rs_RenderScene_zonly", ""); + SETTIMERNAME(PTI_RS_LOCKARRAYS, "rs_LockArrays", ""); + SETTIMERNAME(PTI_RS_DRAWELEMENTS, "rs_DrawElements", ""); + SETTIMERNAME(PTI_RS_REMOVEDUMMY, "rs_RemoveDummy", ""); + SETTIMERNAME(PTI_RS_CHECKLAYERSUPTODATE, "rs_CheckLayers", ""); + SETTIMERNAME(PTI_RS_BINTOGROUPS, "rs_BinToGroups", ""); + SETTIMERNAME(PTI_RS_MAKEMIPFACTOR, " rs_MakeMipAdjustMap", ""); + SETTIMERNAME(PTI_RS_MAKEVERTEXCOORDS, "rs_MakeVertexCoords", ""); + SETTIMERNAME(PTI_RS_SETCOLORS, "rs_SetColors", ""); + SETTIMERNAME(PTI_RS_SETTEXCOORDS, "rs_SetTexcoords", ""); + SETTIMERNAME(PTI_RS_RENDERGROUP, "rs_RenderGroup", ""); + SETTIMERNAME(PTI_RS_RENDERGROUPINTERNAL, " rs_RenderGroupInternal", ""); + SETTIMERNAME(PTI_RS_BINBYMULTITEXTURING, " rs_BinByMultiTexturing", ""); + SETTIMERNAME(PTI_RS_RENDERSHADOWS, "rs_RenderShadows", ""); + SETTIMERNAME(PTI_RS_RENDERTEXTURES, "rs_RenderTextures", ""); + SETTIMERNAME(PTI_RS_RENDERMT, "rs_RenderMT", ""); + SETTIMERNAME(PTI_RS_RENDERFOG, "rs_RenderFog", ""); + SETTIMERNAME(PTI_RS_RENDERHAZE, "rs_RenderHaze", ""); + + // initialize counters + SETCOUNTERNAME(PCI_TEXTUREPREPARES, "texture prepares"); + SETCOUNTERNAME(PCI_TEXTUREUPLOADS, "texture uploads"); + SETCOUNTERNAME(PCI_TEXTUREUPLOADBYTES, "texture bytes uploaded"); + SETCOUNTERNAME(PCI_CACHEDSHADOWS, "number of shadows cached"); + SETCOUNTERNAME(PCI_FLATSHADOWS, "number of flat shadows"); + SETCOUNTERNAME(PCI_CACHEDSHADOWBYTES, "shadow bytes cached"); + SETCOUNTERNAME(PCI_DYNAMICSHADOWS, "number of dynamic shadows cached"); + SETCOUNTERNAME(PCI_DYNAMICSHADOWBYTES, "dynamic shadow bytes cached"); + SETCOUNTERNAME(PCI_RS_TRIANGLES, "RS: triangles"); + SETCOUNTERNAME(PCI_RS_TRIANGLEPASSESORG, "RS: triangle*passes"); + SETCOUNTERNAME(PCI_RS_TRIANGLEPASSESOPT, "RS: triangle*passesMT"); + SETCOUNTERNAME(PCI_RS_POLYGONGROUPS, "RS: polygon groups"); +} diff --git a/Sources/Engine/Graphics/GfxProfile.h b/Sources/Engine/Graphics/GfxProfile.h new file mode 100644 index 0000000..1a7fa26 --- /dev/null +++ b/Sources/Engine/Graphics/GfxProfile.h @@ -0,0 +1,77 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_GFXPROFILE_H +#define SE_INCL_GFXPROFILE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* Class for holding profiling information for gfx. */ +class CGfxProfile : public CProfileForm { +public: + // indices for profiling counters and timers + enum ProfileTimerIndex + { + PTI_LOCKDRAWPORT, + PTI_SWAPBUFFERS, + PTI_PUTTEXTURE, + PTI_PUTTEXT, + PTI_CACHESHADOW, + PTI_SETCURRENTTEXTURE, + PTI_TEXTUREPARAMS, + PTI_TEXTUREUPLOADING, + PTI_MAKEMIPMAPS, + PTI_DITHERBITMAP, + PTI_FILTERBITMAP, + + PTI_RENDERSCENE, + PTI_RENDERSCENE_BCG, + PTI_RENDERSCENE_ZONLY, + PTI_RS_LOCKARRAYS, + PTI_RS_DRAWELEMENTS, + PTI_RS_REMOVEDUMMY, + PTI_RS_CHECKLAYERSUPTODATE, + PTI_RS_BINTOGROUPS, + PTI_RS_MAKEMIPFACTOR, + PTI_RS_MAKEVERTEXCOORDS, + PTI_RS_SETCOLORS, + PTI_RS_SETTEXCOORDS, + PTI_RS_RENDERGROUP, + PTI_RS_RENDERGROUPINTERNAL, + PTI_RS_BINBYMULTITEXTURING, + PTI_RS_RENDERSHADOWS, + PTI_RS_RENDERTEXTURES, + PTI_RS_RENDERMT, + PTI_RS_RENDERFOG, + PTI_RS_RENDERHAZE, + + PTI_COUNT + }; + + enum ProfileCounterIndex + { + PCI_TEXTUREUPLOADS, // how many times a texture was uploaded + PCI_TEXTUREUPLOADBYTES, // how many texture bytes were uploaded + PCI_TEXTUREPREPARES, // how many times a texture was prepared + PCI_TEXTUREBYTESALLOWED, + PCI_CACHEDSHADOWS, // number of shadowmaps cached + PCI_FLATSHADOWS, // number of flat shadowmaps + PCI_CACHEDSHADOWBYTES, // shadowmap bytes cached + PCI_DYNAMICSHADOWS, + PCI_DYNAMICSHADOWBYTES, + + PCI_RS_TRIANGLES, + PCI_RS_TRIANGLEPASSESORG, + PCI_RS_TRIANGLEPASSESOPT, + PCI_RS_POLYGONGROUPS, + PCI_COUNT, + }; + // constructor + CGfxProfile(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/Gfx_Direct3D.cpp b/Sources/Engine/Graphics/Gfx_Direct3D.cpp new file mode 100644 index 0000000..8ccf6d3 --- /dev/null +++ b/Sources/Engine/Graphics/Gfx_Direct3D.cpp @@ -0,0 +1,1355 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#ifdef SE1_D3D + + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + +#define ASMOPT 1 + + +extern INDEX gap_iTruformLevel; + +extern ULONG _fog_ulTexture; +extern ULONG _haze_ulTexture; + + +// state variables +extern BOOL GFX_bDepthTest; +extern BOOL GFX_bDepthWrite; +extern BOOL GFX_bAlphaTest; +extern BOOL GFX_bBlending; +extern BOOL GFX_bDithering; +extern BOOL GFX_bClipping; +extern BOOL GFX_bClipPlane; +extern BOOL GFX_bColorArray; +extern BOOL GFX_bFrontFace; +extern BOOL GFX_bTruform; +extern INDEX GFX_iActiveTexUnit; +extern FLOAT GFX_fMinDepthRange; +extern FLOAT GFX_fMaxDepthRange; +extern GfxBlend GFX_eBlendSrc; +extern GfxBlend GFX_eBlendDst; +extern GfxComp GFX_eDepthFunc; +extern GfxFace GFX_eCullFace; +extern INDEX GFX_iTexModulation[GFX_MAXTEXUNITS]; + +extern INDEX GFX_ctVertices; +extern BOOL D3D_bUseColorArray = FALSE; + +// internal vars +static INDEX _iVtxOffset = 0; +static INDEX _iIdxOffset = 0; +static INDEX _iVtxPos = 0; +static INDEX _iTexPass = 0; +static INDEX _iColPass = 0; +static DWORD _dwCurrentVS = NONE; +static ULONG _ulStreamsMask = NONE; +static ULONG _ulLastStreamsMask = NONE; +static BOOL _bProjectiveMapping = FALSE; +static BOOL _bLastProjectiveMapping = FALSE; +static DWORD _dwVtxLockFlags; // for vertex and normal +static DWORD _dwColLockFlags[GFX_MAXLAYERS]; // for colors +static DWORD _dwTexLockFlags[GFX_MAXLAYERS]; // for texture coords + +// shaders created so far +struct VertexShader { + ULONG vs_ulMask; + DWORD vs_dwHandle; +}; +static CStaticStackArray _avsShaders; + + +// device type (HAL is default, REF is only for debuging) +extern const D3DDEVTYPE d3dDevType = D3DDEVTYPE_HAL; + +// identity matrix +extern const D3DMATRIX GFX_d3dIdentityMatrix = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 }; + + +// sizes of vertex components +#define POSSIZE (4*sizeof(FLOAT)) +#define NORSIZE (4*sizeof(FLOAT)) +#define TEXSIZE (2*sizeof(FLOAT)) +#define TX4SIZE (4*sizeof(FLOAT)) +#define COLSIZE (4*sizeof(UBYTE)) +#define IDXSIZE (1*sizeof(UWORD)) + +#define POSIDX (0) +#define COLIDX (1) +#define TEXIDX (2) +#define NORIDX (6) + + +// SHADER SETUP PARAMS + +#define DECLTEXOFS (2*TEXIDX) +#define MAXSTREAMS (7L) + +// template shader +DWORD _adwDeclTemplate[] = { + D3DVSD_STREAM(0), + D3DVSD_REG( D3DVSDE_POSITION, D3DVSDT_FLOAT3), + D3DVSD_STREAM(1), + D3DVSD_REG( D3DVSDE_DIFFUSE, D3DVSDT_D3DCOLOR), + D3DVSD_STREAM(2), + D3DVSD_REG( D3DVSDE_TEXCOORD0, D3DVSDT_FLOAT2), + D3DVSD_STREAM(3), + D3DVSD_REG( D3DVSDE_TEXCOORD1, D3DVSDT_FLOAT2), + D3DVSD_STREAM(4), + D3DVSD_REG( D3DVSDE_TEXCOORD2, D3DVSDT_FLOAT2), + D3DVSD_STREAM(5), + D3DVSD_REG( D3DVSDE_TEXCOORD3, D3DVSDT_FLOAT2), + D3DVSD_STREAM(6), + D3DVSD_REG( D3DVSDE_NORMAL, D3DVSDT_FLOAT3), + D3DVSD_END() +}; + +// current shader +DWORD _adwCurrentDecl[2*MAXSTREAMS+1]; + + + +// check whether texture format is supported in D3D +static BOOL HasTextureFormat_D3D( D3DFORMAT d3dTextureFormat) +{ + // quickie? + const D3DFORMAT d3dScreenFormat = _pGfx->gl_d3dColorFormat; + if( d3dTextureFormat==D3DFMT_UNKNOWN || d3dScreenFormat==NONE) return TRUE; + // check + extern const D3DDEVTYPE d3dDevType; + HRESULT hr = _pGfx->gl_pD3D->CheckDeviceFormat( _pGfx->gl_iCurrentAdapter, d3dDevType, d3dScreenFormat, + 0, D3DRTYPE_TEXTURE, d3dTextureFormat); + return( hr==D3D_OK); +} + + +#define VTXSIZE (POSSIZE + (_pGfx->gl_iMaxTessellationLevel>0 ? NORSIZE : 0) + TX4SIZE \ + + COLSIZE * _pGfx->gl_ctColBuffers \ + + TEXSIZE * (_pGfx->gl_ctTexBuffers-1)) + + +// returns number of vertices based on vertex size and required size in memory (KB) +extern INDEX VerticesFromSize_D3D( SLONG &slSize) +{ + slSize = Clamp( slSize, 64L, 4096L); + return (slSize*1024 / VTXSIZE); +} + +// returns size in memory based on number of vertices +extern SLONG SizeFromVertices_D3D( INDEX ctVertices) +{ + return (ctVertices * VTXSIZE); +} + + +// construct vertex shader out of streams' bit-mask +extern DWORD SetupShader_D3D( ULONG ulStreamsMask) +{ + HRESULT hr; + const LPDIRECT3DDEVICE8 pd3dDev = _pGfx->gl_pd3dDevice; + const INDEX ctShaders = _avsShaders.Count(); + INDEX iVS; + + // delete all shaders? + if( ulStreamsMask==NONE) { + for( iVS=0; iVSDeleteVertexShader(_avsShaders[iVS].vs_dwHandle); + D3D_CHECKERROR(hr); + } // free array + _avsShaders.PopAll(); + _dwCurrentVS = NONE; + return NONE; + } + + // see if required shader has already been created + for( iVS=0; iVS>= 1; + } + // mark end + _adwCurrentDecl[iDstDecl*2] = D3DVSD_END(); + ASSERT( iDstDecl < MAXSTREAMS); + ASSERT( _iTexPass>=0 && _iColPass>=0); + ASSERT( _iVtxPos >=0 && _iVtxPos<65536); + + // create new vertex shader + const DWORD dwFlags = (_pGfx->gl_ulFlags&GLF_D3D_USINGHWTNL) ? NONE : D3DUSAGE_SOFTWAREPROCESSING; + hr = pd3dDev->CreateVertexShader( &_adwCurrentDecl[0], NULL, &vs.vs_dwHandle, dwFlags); + D3D_CHECKERROR(hr); + + // store and reset shader + _pGfx->gl_dwVertexShader = 0; + return vs.vs_dwHandle; +} + + + +// prepare vertex arrays for drawing +extern void SetupVertexArrays_D3D( INDEX ctVertices) +{ + INDEX i; + HRESULT hr; + ASSERT( ctVertices>=0); + + // do nothing if buffer is sufficient + ctVertices = ClampUp( ctVertices, 65535L); // need to clamp max vertices first + if( ctVertices!=0 && ctVertices<=_pGfx->gl_ctVertices) return; + + // determine SW or HW VP and NPatches usage (Truform) + DWORD dwFlags = D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY; + const BOOL bNPatches = (_pGfx->gl_iMaxTessellationLevel>0 && gap_iTruformLevel>0); + if( !(_pGfx->gl_ulFlags&GLF_D3D_USINGHWTNL)) dwFlags |= D3DUSAGE_SOFTWAREPROCESSING; + if( bNPatches) dwFlags |= D3DUSAGE_NPATCHES; + const LPDIRECT3DDEVICE8 pd3dDev = _pGfx->gl_pd3dDevice; + + // deallocate if needed + if( _pGfx->gl_pd3dVtx!=NULL) + { + // vertex and eventual normal array + D3DRELEASE( _pGfx->gl_pd3dVtx, TRUE); + if( _pGfx->gl_pd3dNor!=NULL) D3DRELEASE( _pGfx->gl_pd3dNor, TRUE); + // color arrays + for( i=0; i<_pGfx->gl_ctColBuffers; i++) { + ASSERT( _pGfx->gl_pd3dCol[i]!=NULL); + D3DRELEASE( _pGfx->gl_pd3dCol[i], TRUE); + } + // texcoord arrays + for( i=0; i<_pGfx->gl_ctTexBuffers; i++) { + ASSERT( _pGfx->gl_pd3dTex[i]!=NULL); + D3DRELEASE( _pGfx->gl_pd3dTex[i], TRUE); + } + // reset all streams, too + for( i=0; i<_pGfx->gl_ctMaxStreams; i++) { + hr = pd3dDev->SetStreamSource( i, NULL,0); + D3D_CHECKERROR(hr); + } + } + + // allocate if needed + if( ctVertices>0) + { + // update max vertex count + if( _pGfx->gl_ctVertices < ctVertices) _pGfx->gl_ctVertices = ctVertices; + else ctVertices = _pGfx->gl_ctVertices; + // create buffers + hr = pd3dDev->CreateVertexBuffer( ctVertices*POSSIZE, dwFlags, 0, D3DPOOL_DEFAULT, &_pGfx->gl_pd3dVtx); + D3D_CHECKERROR(hr); + // normals buffer only if required + if( bNPatches) { + hr = pd3dDev->CreateVertexBuffer( ctVertices*NORSIZE, dwFlags, 0, D3DPOOL_DEFAULT, &_pGfx->gl_pd3dNor); + D3D_CHECKERROR(hr); + } + // all color buffers + for( i=0; i<_pGfx->gl_ctColBuffers; i++) { + hr = pd3dDev->CreateVertexBuffer( ctVertices*COLSIZE, dwFlags, 0, D3DPOOL_DEFAULT, &_pGfx->gl_pd3dCol[i]); + D3D_CHECKERROR(hr); + } + // 1st texture buffer might have projective mapping + hr = pd3dDev->CreateVertexBuffer( ctVertices*TX4SIZE, dwFlags, 0, D3DPOOL_DEFAULT, &_pGfx->gl_pd3dTex[0]); + D3D_CHECKERROR(hr); + for( i=1; i<_pGfx->gl_ctTexBuffers; i++) { + hr = pd3dDev->CreateVertexBuffer( ctVertices*TEXSIZE, dwFlags, 0, D3DPOOL_DEFAULT, &_pGfx->gl_pd3dTex[i]); + D3D_CHECKERROR(hr); + } + } + // just switch it off if not needed any more (i.e. D3D is shutting down) + else _pGfx->gl_ctVertices = 0; + + // reset and check + _iVtxOffset = 0; + _pGfx->gl_dwVertexShader = NONE; + _ulStreamsMask = NONE; + _ulLastStreamsMask = NONE; + _bProjectiveMapping = FALSE; + _bLastProjectiveMapping = FALSE; + // reset locking flags + _dwVtxLockFlags = D3DLOCK_DISCARD; + for( i=0; igl_ctVertices<65536); +} + + + +// prepare index arrays for drawing +extern void SetupIndexArray_D3D( INDEX ctIndices) +{ + HRESULT hr; + ASSERT( ctIndices>=0); + // clamp max indices + ctIndices = ClampUp( ctIndices, 65535L); + + // do nothing if buffer is sufficient + if( ctIndices!=0 && ctIndices<=_pGfx->gl_ctIndices) return; + + // determine SW or HW VP + DWORD dwFlags = D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY; + if( !(_pGfx->gl_ulFlags&GLF_D3D_USINGHWTNL)) dwFlags |= D3DUSAGE_SOFTWAREPROCESSING; + if( _pGfx->gl_iMaxTessellationLevel>0 && gap_iTruformLevel>0) dwFlags |= D3DUSAGE_NPATCHES; + const LPDIRECT3DDEVICE8 pd3dDev = _pGfx->gl_pd3dDevice; + + // dealocate if needed + if( _pGfx->gl_ctIndices>0) D3DRELEASE( _pGfx->gl_pd3dIdx, TRUE); + + // allocate if needed + if( ctIndices>0) + { + // eventually update max index count + if( _pGfx->gl_ctIndices < ctIndices) _pGfx->gl_ctIndices = ctIndices; + else ctIndices = _pGfx->gl_ctIndices; + // create buffer + hr = pd3dDev->CreateIndexBuffer( ctIndices*IDXSIZE, dwFlags, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &_pGfx->gl_pd3dIdx); + D3D_CHECKERROR(hr); + // set it + hr = _pGfx->gl_pd3dDevice->SetIndices( _pGfx->gl_pd3dIdx, 0); + D3D_CHECKERROR(hr); + } + // just switch it off if not needed any more (i.e. D3D is shutting down) + else _pGfx->gl_ctIndices = 0; + + // reset and check + _iIdxOffset = 0; + ASSERT(_pGfx->gl_ctIndices<65536); +} + + + +// initialize Direct3D driver +BOOL CGfxLibrary::InitDriver_D3D(void) +{ + // check for presence of DirectX 8 + gl_hiDriver = LoadLibraryA( "D3D8.DLL"); + if( gl_hiDriver==NONE) { + // not present - BUAHHAHAHAHAR :) + CPrintF( "DX8 error: API not installed.\n"); + gl_gaAPI[GAT_D3D].ga_ctAdapters = 0; + return FALSE; + } + + // query DX8 interface + IDirect3D8* (WINAPI *pDirect3DCreate8)(UINT SDKVersion); + pDirect3DCreate8 = (IDirect3D8* (WINAPI *)(UINT SDKVersion))GetProcAddress( gl_hiDriver, "Direct3DCreate8"); + if( pDirect3DCreate8==NULL) { + // cannot init + CPrintF( "DX8 error: Cannot get entry procedure address.\n"); + FreeLibrary(gl_hiDriver); + gl_hiDriver = NONE; + return FALSE; + } + + // init DX8 + gl_pD3D = pDirect3DCreate8(D3D_SDK_VERSION); + if( gl_pD3D==NULL) { + // cannot start + CPrintF( "DX8 error: Cannot be initialized.\n"); + FreeLibrary(gl_hiDriver); + gl_hiDriver = NONE; + return FALSE; + } + // made it! + return TRUE; +} + + +// initialize Direct3D driver +void CGfxLibrary::EndDriver_D3D(void) +{ + // unbind textures + if( _pTextureStock!=NULL) { + {FOREACHINDYNAMICCONTAINER( _pTextureStock->st_ctObjects, CTextureData, ittd) { + CTextureData &td = *ittd; + td.td_tpLocal.Clear(); + td.Unbind(); + }} + } + // unbind fog, haze and flat texture + gfxDeleteTexture( _fog_ulTexture); + gfxDeleteTexture( _haze_ulTexture); + ASSERT( _ptdFlat!=NULL); + _ptdFlat->td_tpLocal.Clear(); + _ptdFlat->Unbind(); + + // reset shader and vertices + SetupShader_D3D(NONE); + SetupVertexArrays_D3D(0); + SetupIndexArray_D3D(0); + gl_d3dColorFormat = (D3DFORMAT)NONE; + gl_d3dDepthFormat = (D3DFORMAT)NONE; + + // shutdown device and d3d + INDEX iRef; + iRef = gl_pd3dDevice->Release(); + iRef = gl_pD3D->Release(); +} + + +// prepare current viewport for rendering thru Direct3D +BOOL CGfxLibrary::SetCurrentViewport_D3D(CViewPort *pvp) +{ + // determine full screen mode + CDisplayMode dm; + RECT rectWindow; + _pGfx->GetCurrentDisplayMode(dm); + ASSERT( (dm.dm_pixSizeI==0 && dm.dm_pixSizeJ==0) || (dm.dm_pixSizeI!=0 && dm.dm_pixSizeJ!=0)); + GetClientRect( pvp->vp_hWnd, &rectWindow); + const PIX pixWinSizeI = rectWindow.right - rectWindow.left; + const PIX pixWinSizeJ = rectWindow.bottom - rectWindow.top; + + // full screen allows only one window (main one, which has already been initialized) + if( dm.dm_pixSizeI==pixWinSizeI && dm.dm_pixSizeJ==pixWinSizeJ) { + gl_pvpActive = pvp; // remember as current viewport (must do that BEFORE InitContext) + if( gl_ulFlags & GLF_INITONNEXTWINDOW) InitContext_D3D(); + gl_ulFlags &= ~GLF_INITONNEXTWINDOW; + return TRUE; + } + + // if must init entire D3D + if( gl_ulFlags & GLF_INITONNEXTWINDOW) { + gl_ulFlags &= ~GLF_INITONNEXTWINDOW; + // reopen window + pvp->CloseCanvas(); + pvp->OpenCanvas(); + gl_pvpActive = pvp; + InitContext_D3D(); + pvp->vp_ctDisplayChanges = gl_ctDriverChanges; + return TRUE; + } + + // if window was not set for this driver + if( pvp->vp_ctDisplayChangesCloseCanvas(); + pvp->OpenCanvas(); + pvp->vp_ctDisplayChanges = gl_ctDriverChanges; + gl_pvpActive = pvp; + return TRUE; + } + + // no need to set context if it is the same window as last time + if( gl_pvpActive!=NULL && gl_pvpActive->vp_hWnd==pvp->vp_hWnd) return TRUE; + + // set rendering target + HRESULT hr; + LPDIRECT3DSURFACE8 pColorSurface; + hr = pvp->vp_pSwapChain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pColorSurface); + if( hr!=D3D_OK) return FALSE; + hr = gl_pd3dDevice->SetRenderTarget( pColorSurface, pvp->vp_pSurfDepth); + D3DRELEASE( pColorSurface, TRUE); + if( hr!=D3D_OK) return FALSE; + + // remember as current window + gl_pvpActive = pvp; + return TRUE; +} + + + +// prepares Direct3D drawing context +void CGfxLibrary::InitContext_D3D() +{ + // must have context + ASSERT( gl_pvpActive!=NULL); + + // report header + CPrintF( TRANS("\n* Direct3D context created: *----------------------------------\n")); + CDisplayAdapter &da = gl_gaAPI[GAT_D3D].ga_adaAdapter[gl_iCurrentAdapter]; + CPrintF( " (%s, %s, %s)\n\n", da.da_strVendor, da.da_strRenderer, da.da_strVersion); + HRESULT hr; + + // reset engine's internal Direct3D state variables + GFX_bTruform = FALSE; + GFX_bClipping = TRUE; + GFX_bFrontFace = TRUE; + hr = gl_pd3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE); D3D_CHECKERROR(hr); GFX_bDepthTest = FALSE; + hr = gl_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE); D3D_CHECKERROR(hr); GFX_bDepthWrite = FALSE; + hr = gl_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE); D3D_CHECKERROR(hr); GFX_bAlphaTest = FALSE; + hr = gl_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE); D3D_CHECKERROR(hr); GFX_bBlending = FALSE; + hr = gl_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE); D3D_CHECKERROR(hr); GFX_bDithering = TRUE; + hr = gl_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, FALSE); D3D_CHECKERROR(hr); GFX_bClipPlane = FALSE; + hr = gl_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE); D3D_CHECKERROR(hr); GFX_eCullFace = GFX_NONE; + hr = gl_pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL); D3D_CHECKERROR(hr); GFX_eDepthFunc = GFX_LESS_EQUAL; + hr = gl_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE); D3D_CHECKERROR(hr); GFX_eBlendSrc = GFX_ONE; + hr = gl_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE); D3D_CHECKERROR(hr); GFX_eBlendDst = GFX_ONE; + + // (re)set some D3D defaults + hr = gl_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); D3D_CHECKERROR(hr); + hr = gl_pd3dDevice->SetRenderState( D3DRS_ALPHAREF, 128); D3D_CHECKERROR(hr); + + // constant color default setup + hr = gl_pd3dDevice->SetRenderState( D3DRS_COLORVERTEX, FALSE); D3D_CHECKERROR(hr); + hr = gl_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE); D3D_CHECKERROR(hr); + hr = gl_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0xFFFFFFFF); D3D_CHECKERROR(hr); + D3DMATERIAL8 d3dMaterial; + memset( &d3dMaterial, 0, sizeof(d3dMaterial)); + d3dMaterial.Diffuse.r = d3dMaterial.Ambient.r = 1.0f; + d3dMaterial.Diffuse.g = d3dMaterial.Ambient.g = 1.0f; + d3dMaterial.Diffuse.b = d3dMaterial.Ambient.b = 1.0f; + d3dMaterial.Diffuse.a = d3dMaterial.Ambient.a = 1.0f; + hr = gl_pd3dDevice->SetMaterial(&d3dMaterial); + D3D_CHECKERROR(hr); + GFX_bColorArray = FALSE; + + // disable texturing + extern BOOL GFX_abTexture[GFX_MAXTEXUNITS]; + for( INDEX iUnit=0; iUnitSetTexture( iUnit, NULL); D3D_CHECKERROR(hr); + hr = gl_pd3dDevice->SetTextureStageState( iUnit, D3DTSS_COLOROP, D3DTOP_DISABLE); D3D_CHECKERROR(hr); + hr = gl_pd3dDevice->SetTextureStageState( iUnit, D3DTSS_ALPHAOP, D3DTOP_MODULATE); D3D_CHECKERROR(hr); + } + // set default texture unit and modulation mode + GFX_iActiveTexUnit = 0; + // reset frustum/ortho matrix + extern BOOL GFX_bViewMatrix; + extern FLOAT GFX_fLastL, GFX_fLastR, GFX_fLastT, GFX_fLastB, GFX_fLastN, GFX_fLastF; + GFX_fLastL = GFX_fLastR = GFX_fLastT = GFX_fLastB = GFX_fLastN = GFX_fLastF = 0; + GFX_bViewMatrix = TRUE; + + // reset depth range + D3DVIEWPORT8 d3dViewPort = { 0,0, 8,8, 0,1 }; + hr = gl_pd3dDevice->SetViewport( &d3dViewPort); D3D_CHECKERROR(hr); + hr = gl_pd3dDevice->GetViewport( &d3dViewPort); D3D_CHECKERROR(hr); + ASSERT( d3dViewPort.MinZ==0 && d3dViewPort.MaxZ==1); + GFX_fMinDepthRange = 0.0f; + GFX_fMaxDepthRange = 1.0f; + + // get capabilites + D3DCAPS8 d3dCaps; + hr = gl_pd3dDevice->GetDeviceCaps( &d3dCaps); + D3D_CHECKERROR(hr); + + // determine rasterizer acceleration + gl_ulFlags &= ~GLF_HASACCELERATION; + if( (d3dCaps.DevCaps & D3DDEVCAPS_HWRASTERIZATION) + || d3dDevType==D3DDEVTYPE_REF) gl_ulFlags |= GLF_HASACCELERATION; + + // determine support for 32-bit textures + gl_ulFlags &= ~GLF_32BITTEXTURES; + if( HasTextureFormat_D3D(D3DFMT_X8R8G8B8) + || HasTextureFormat_D3D(D3DFMT_A8R8G8B8)) gl_ulFlags |= GLF_32BITTEXTURES; + + // determine support for compressed textures + gl_ulFlags &= ~GLF_TEXTURECOMPRESSION; + if( HasTextureFormat_D3D(D3DFMT_DXT1)) gl_ulFlags |= GLF_TEXTURECOMPRESSION; + + // determine max supported dimension of texture + gl_pixMaxTextureDimension = d3dCaps.MaxTextureWidth; + ASSERT( gl_pixMaxTextureDimension == d3dCaps.MaxTextureHeight); // perhaps not ? + + // determine support for disabling of color buffer writes + gl_ulFlags &= ~GLF_D3D_COLORWRITES; + if( d3dCaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) gl_ulFlags |= GLF_D3D_COLORWRITES; + + // determine support for custom clip planes + gl_ulFlags &= ~GLF_D3D_CLIPPLANE; + if( d3dCaps.MaxUserClipPlanes>0) gl_ulFlags |= GLF_D3D_CLIPPLANE; + else CPrintF( TRANS("User clip plane not supported - mirrors will not work well.\n")); + + // determine support for texture LOD biasing + gl_fMaxTextureLODBias = 0.0f; + if( d3dCaps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS) { + gl_fMaxTextureLODBias = 4.0f; + } + + // determine support for anisotropic filtering + gl_iMaxTextureAnisotropy = 1; + if( d3dCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) { + gl_iMaxTextureAnisotropy = d3dCaps.MaxAnisotropy; + ASSERT( gl_iMaxTextureAnisotropy>1); + } + + // determine support for z-biasing + gl_ulFlags &= ~GLF_D3D_ZBIAS; + if( d3dCaps.RasterCaps & D3DPRASTERCAPS_ZBIAS) gl_ulFlags |= GLF_D3D_ZBIAS; + + // check support for vsync swapping + gl_ulFlags &= ~GLF_VSYNC; + if( d3dCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) { + if( d3dCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) gl_ulFlags |= GLF_VSYNC; + } else CPrintF( TRANS(" Vertical syncronization cannot be disabled.\n")); + + // determine support for N-Patches + extern INDEX truform_iLevel; + extern BOOL truform_bLinear; + truform_iLevel = -1; + truform_bLinear = FALSE; + gl_iTessellationLevel = 0; + gl_iMaxTessellationLevel = 0; + INDEX ctMinStreams = GFX_MINSTREAMS; // set minimum number of required streams + if( d3dCaps.DevCaps & D3DDEVCAPS_NPATCHES) { + if( gl_ctMaxStreams>GFX_MINSTREAMS) { + gl_iMaxTessellationLevel = 7; + hr = gl_pd3dDevice->SetRenderState( D3DRS_PATCHEDGESTYLE, D3DPATCHEDGE_DISCRETE); + D3D_CHECKERROR(hr); + ctMinStreams++; // need an extra stream for normals now + } else CPrintF( TRANS("Not enough streams - N-Patches cannot be used.\n")); + } + + // determine support for multi-texturing (only if Modulate2X mode is supported!) + gl_ctTextureUnits = 1; + gl_ctRealTextureUnits = d3dCaps.MaxSimultaneousTextures; + if( gl_ctRealTextureUnits>1) { + // check everything that is required for multi-texturing + if( !(d3dCaps.TextureOpCaps&D3DTOP_MODULATE2X)) CPrintF( TRANS("Texture operation MODULATE2X missing - multi-texturing cannot be used.\n")); + else if( gl_ctMaxStreams<=ctMinStreams) CPrintF( TRANS("Not enough streams - multi-texturing cannot be used.\n")); + else gl_ctTextureUnits = Min( GFX_MAXTEXUNITS, Min( gl_ctRealTextureUnits, 1+gl_ctMaxStreams-ctMinStreams)); + } + + // setup fog and haze textures + extern PIX _fog_pixSizeH; + extern PIX _fog_pixSizeL; + extern PIX _haze_pixSize; + _fog_ulTexture = NONE; + _haze_ulTexture = NONE; + _fog_pixSizeH = 0; + _fog_pixSizeL = 0; + _haze_pixSize = 0; + + // prepare pattern texture + extern CTexParams _tpPattern; + extern ULONG _ulPatternTexture; + extern ULONG _ulLastUploadedPattern; + _ulPatternTexture = NONE; + _ulLastUploadedPattern = 0; + _tpPattern.Clear(); + + // determine number of color/texcoord buffers + gl_ctTexBuffers = gl_ctTextureUnits; + gl_ctColBuffers = 1; + INDEX ctStreamsRemain = gl_ctMaxStreams - (ctMinStreams-1+gl_ctTextureUnits); // -1 because of 1 texture unit inside MinStreams + FOREVER { + // done if no more or enough streams + if( ctStreamsRemain==0 || (gl_ctTexBuffers==GFX_MAXLAYERS && gl_ctColBuffers==GFX_MAXLAYERS)) break; + // increase number of tex or color buffers + if( gl_ctColBuffers0 && gl_ctTexBuffers<=GFX_MAXLAYERS); + ASSERT( gl_ctColBuffers>0 && gl_ctColBuffers<=GFX_MAXLAYERS); + gl_ctVertices = 0; + gl_ctIndices = 0; + extern INDEX d3d_iVertexBuffersSize; + extern INDEX _iLastVertexBufferSize; + const INDEX ctVertices = VerticesFromSize_D3D(d3d_iVertexBuffersSize); + _iLastVertexBufferSize = d3d_iVertexBuffersSize; + SetupVertexArrays_D3D(ctVertices); + SetupIndexArray_D3D(2*ctVertices); + + // reset texture filtering and some static vars + _tpGlobal[0].Clear(); + _tpGlobal[1].Clear(); + _tpGlobal[2].Clear(); + _tpGlobal[3].Clear(); + _avsShaders.Clear(); + _iVtxOffset = 0; + _iIdxOffset = 0; + _dwCurrentVS = NONE; + _ulStreamsMask = NONE; + _ulLastStreamsMask = NONE; + _bProjectiveMapping = FALSE; + _bLastProjectiveMapping = FALSE; + gl_dwVertexShader = NONE; + GFX_ctVertices = 0; + // reset locking flags + _dwVtxLockFlags = D3DLOCK_DISCARD; + for( i=0; igl_pD3D->CheckDepthStencilMatch( iAdapter, d3dDevType, d3dfColor, d3dfColor, ad3dFormats[i]); + if( hr==D3D_OK) break; + } + + // not found? + if( i==ctFormats) { + // do additional check for whole format list + for( i=0; igl_pD3D->CheckDepthStencilMatch( iAdapter, d3dDevType, d3dfColor, d3dfColor, ad3dFormats[i]); + if( hr==D3D_OK) break; + } + // what, z-buffer still not supported? + if( i==iStart) { + ASSERT( "FindDepthFormat_D3D: Z-buffer format not found?!" ); + iDepthBits = 0; + return D3DFMT_UNKNOWN; + } + } + // aaaah, found! :) + ASSERT( i>=0 && i3) iDepthBits = 16; + else if( i>0) iDepthBits = 24; + else iDepthBits = 32; + return ad3dFormats[i]; +} + + +// prepare display mode +BOOL CGfxLibrary::InitDisplay_D3D( INDEX iAdapter, PIX pixSizeI, PIX pixSizeJ, + enum DisplayDepth eColorDepth) +{ + // reset + HRESULT hr; + D3DDISPLAYMODE d3dDisplayMode; + D3DPRESENT_PARAMETERS d3dPresentParams; + gl_pD3D->GetAdapterDisplayMode( iAdapter, &d3dDisplayMode); + memset( &d3dPresentParams, 0, sizeof(d3dPresentParams)); + + // readout device capabilites + D3DCAPS8 d3dCaps; + hr = gl_pD3D->GetDeviceCaps( iAdapter, d3dDevType, &d3dCaps); + D3D_CHECKERROR(hr); + + // clamp depth/stencil values + extern INDEX gap_iDepthBits; + extern INDEX gap_iStencilBits; + if( gap_iDepthBits <12) gap_iDepthBits = 0; + else if( gap_iDepthBits <22) gap_iDepthBits = 16; + else if( gap_iDepthBits <28) gap_iDepthBits = 24; + else gap_iDepthBits = 32; + if( gap_iStencilBits<3) gap_iStencilBits = 0; + else if( gap_iStencilBits<7) gap_iStencilBits = 4; + else gap_iStencilBits = 8; + + // prepare + INDEX iZDepth = gap_iDepthBits; + D3DFORMAT d3dDepthFormat = D3DFMT_UNKNOWN; + D3DFORMAT d3dColorFormat = d3dDisplayMode.Format; + d3dPresentParams.BackBufferCount = 1; + d3dPresentParams.MultiSampleType = D3DMULTISAMPLE_NONE; // !!!! TODO + d3dPresentParams.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; + d3dPresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD; + const BOOL bFullScreen = (pixSizeI>0 && pixSizeJ>0); + + // setup for full screen + if( bFullScreen) { + // determine color and depth format + if( eColorDepth==DD_16BIT) d3dColorFormat = D3DFMT_R5G6B5; + if( eColorDepth==DD_32BIT) d3dColorFormat = D3DFMT_X8R8G8B8; + d3dDepthFormat = FindDepthFormat_D3D( iAdapter, d3dColorFormat, iZDepth); + // determine refresh rate and presentation interval + extern INDEX gap_iRefreshRate; + const UINT uiRefresh = gap_iRefreshRate>0 ? gap_iRefreshRate : D3DPRESENT_RATE_DEFAULT; + const SLONG slIntervals = d3dCaps.PresentationIntervals; + UINT uiInterval = (slIntervals&D3DPRESENT_INTERVAL_IMMEDIATE) ? D3DPRESENT_INTERVAL_IMMEDIATE : D3DPRESENT_INTERVAL_ONE; + extern INDEX gap_iSwapInterval; + switch(gap_iSwapInterval) { + case 1: if( slIntervals&D3DPRESENT_INTERVAL_ONE) uiInterval=D3DPRESENT_INTERVAL_ONE; break; + case 2: if( slIntervals&D3DPRESENT_INTERVAL_TWO) uiInterval=D3DPRESENT_INTERVAL_TWO; break; + case 3: if( slIntervals&D3DPRESENT_INTERVAL_THREE) uiInterval=D3DPRESENT_INTERVAL_THREE; break; + case 4: if( slIntervals&D3DPRESENT_INTERVAL_FOUR) uiInterval=D3DPRESENT_INTERVAL_FOUR; break; + default: break; + } // construct back cvar + switch(uiInterval) { + case 1: gap_iSwapInterval=1; break; + case 2: gap_iSwapInterval=2; break; + case 3: gap_iSwapInterval=3; break; + case 4: gap_iSwapInterval=4; break; + default: gap_iSwapInterval=0; break; + } gl_iSwapInterval = gap_iSwapInterval; // copy to gfx lib + // set context directly to main window + d3dPresentParams.Windowed = FALSE; + d3dPresentParams.BackBufferWidth = pixSizeI; + d3dPresentParams.BackBufferHeight = pixSizeJ; + d3dPresentParams.BackBufferFormat = d3dColorFormat; + d3dPresentParams.EnableAutoDepthStencil = TRUE; + d3dPresentParams.AutoDepthStencilFormat = d3dDepthFormat; + d3dPresentParams.FullScreen_RefreshRateInHz = uiRefresh; + d3dPresentParams.FullScreen_PresentationInterval = uiInterval; + } + // setup for windowed mode + else { + // create dummy Direct3D context + d3dPresentParams.Windowed = TRUE; + d3dPresentParams.BackBufferWidth = 8; + d3dPresentParams.BackBufferHeight = 8; + d3dPresentParams.BackBufferFormat = d3dColorFormat; + d3dPresentParams.EnableAutoDepthStencil = FALSE; + d3dDepthFormat = FindDepthFormat_D3D( iAdapter, d3dColorFormat, iZDepth); + gl_iSwapInterval = -1; + } + // determine HW or SW vertex processing + DWORD dwVP = D3DCREATE_SOFTWARE_VERTEXPROCESSING; + gl_ulFlags &= ~(GLF_D3D_HASHWTNL|GLF_D3D_USINGHWTNL); + gl_ctMaxStreams = 16; // software T&L has enough streams + extern INDEX d3d_bUseHardwareTnL; + + // cannot have HW VP if not supported by HW, right? + if( d3dCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { + gl_ulFlags |= GLF_D3D_HASHWTNL; + gl_ctMaxStreams = d3dCaps.MaxStreams; + if( gl_ctMaxStreamsCreateDevice( iAdapter, d3dDevType, _hwndMain, dwVP, &d3dPresentParams, &gl_pd3dDevice); + if( hr!=D3D_OK) return FALSE; + gl_d3dColorFormat = d3dColorFormat; + gl_d3dDepthFormat = d3dDepthFormat; + gl_iCurrentDepth = iZDepth; + return TRUE; +} + + + + +// fallback D3D internal format +// (reverts to next format that closely matches requied one) +static D3DFORMAT FallbackFormat_D3D( D3DFORMAT eFormat, BOOL b2ndTry) +{ + switch( eFormat) { + case D3DFMT_X8R8G8B8: return !b2ndTry ? D3DFMT_A8R8G8B8 : D3DFMT_R5G6B5; + case D3DFMT_X1R5G5B5: return !b2ndTry ? D3DFMT_R5G6B5 : D3DFMT_A1R5G5B5; + case D3DFMT_X4R4G4B4: return !b2ndTry ? D3DFMT_R5G6B5 : D3DFMT_A1R5G5B5; + case D3DFMT_R5G6B5: return !b2ndTry ? D3DFMT_X1R5G5B5 : D3DFMT_A1R5G5B5; + case D3DFMT_L8: return !b2ndTry ? D3DFMT_A8L8 : D3DFMT_X8R8G8B8; + case D3DFMT_A8L8: return D3DFMT_A8R8G8B8; + case D3DFMT_A1R5G5B5: return D3DFMT_A4R4G4B4; + case D3DFMT_A8R8G8B8: return D3DFMT_A4R4G4B4; + case D3DFMT_DXT1: return D3DFMT_A1R5G5B5; + case D3DFMT_DXT3: return D3DFMT_A4R4G4B4; + case D3DFMT_DXT5: return D3DFMT_A4R4G4B4; + case D3DFMT_A4R4G4B4: // must have this one! + default: ASSERTALWAYS( "Can't fallback texture format."); + } // missed! + return D3DFMT_UNKNOWN; +} + + +// find closest +extern D3DFORMAT FindClosestFormat_D3D( D3DFORMAT d3df) +{ + FOREVER { + if( HasTextureFormat_D3D(d3df)) return d3df; + D3DFORMAT d3df2 = FallbackFormat_D3D( d3df, FALSE); + if( HasTextureFormat_D3D(d3df2)) return d3df2; + d3df = FallbackFormat_D3D( d3df, TRUE); + } +} + + + +// VERTEX/INDEX BUFFERS SUPPORT THRU STREAMS + + +// DEBUG helper +static void CheckStreams(void) +{ + UINT uiRet, ui; + INDEX iRef, iPass; + DWORD dwVS; + HRESULT hr; + LPDIRECT3DVERTEXBUFFER8 pVBRet, pVB; + LPDIRECT3DINDEXBUFFER8 pIBRet; + const LPDIRECT3DDEVICE8 pd3dDev = _pGfx->gl_pd3dDevice; + + // check passes and buffer position + ASSERT( _iTexPass>=0 && _iColPass>=0); + ASSERT( _iVtxPos >=0 && _iVtxPos<65536); + + // check vertex positions + ASSERT( _ulStreamsMask & (1<GetStreamSource( POSIDX, &pVBRet, &uiRet); + D3D_CHECKERROR(hr); + ASSERT( pVBRet!=NULL); + iRef = pVBRet->Release(); + ASSERT( iRef==1 && pVBRet==_pGfx->gl_pd3dVtx && uiRet==POSSIZE); + + // check normals + pVB = NULL; + ui = NORSIZE; + hr = pd3dDev->GetStreamSource( NORIDX, &pVBRet, &uiRet); + D3D_CHECKERROR(hr); + if( pVBRet!=NULL) iRef = pVBRet->Release(); + if( _ulStreamsMask & (1<gl_pd3dNor; + ASSERT( iRef==1 && pVBRet==pVB && (uiRet==ui || uiRet==0)); + + // check colors + pVB = NULL; + ui = COLSIZE; + hr = pd3dDev->GetStreamSource( COLIDX, &pVBRet, &uiRet); + D3D_CHECKERROR(hr); + if( pVBRet!=NULL) iRef = pVBRet->Release(); + if( _ulStreamsMask & (1<gl_ctColBuffers; + pVB = _pGfx->gl_pd3dCol[iPass]; + } + ASSERT( iRef==1 && pVBRet==pVB && (uiRet==ui || uiRet==0)); + + // check 1st texture coords + pVB = NULL; + ui = _bProjectiveMapping ? TX4SIZE : TEXSIZE; + hr = pd3dDev->GetStreamSource( TEXIDX, &pVBRet, &uiRet); + D3D_CHECKERROR(hr); + if( pVBRet!=NULL) iRef = pVBRet->Release(); + if( _ulStreamsMask & (1<<(TEXIDX))) { + iPass = (_iTexPass-1) % _pGfx->gl_ctTexBuffers; + pVB = _pGfx->gl_pd3dTex[iPass]; + } + ASSERT( iRef==1 && pVBRet==pVB && (uiRet==ui || uiRet==0)); + + // check indices + hr = pd3dDev->GetIndices( &pIBRet, &uiRet); + D3D_CHECKERROR(hr); + ASSERT( pIBRet!=NULL); + iRef = pIBRet->Release(); + ASSERT( iRef==1 && pIBRet==_pGfx->gl_pd3dIdx && uiRet==0); + + // check shader + hr = pd3dDev->GetVertexShader( &dwVS); + D3D_CHECKERROR(hr); + ASSERT( dwVS!=NONE && dwVS==_pGfx->gl_dwVertexShader); + + /* check shader declaration (SEEMS LIKE THIS SHIT DOESN'T WORK!) + const INDEX ctMaxDecls = 2*MAXSTREAMS+1; + INDEX ctDecls = ctMaxDecls; + DWORD adwDeclRet[ctMaxDecls]; + hr = pd3dDev->GetVertexShaderDeclaration( _pGfx->gl_dwVertexShader, (void*)&adwDeclRet[0], (DWORD*)&ctDecls); + D3D_CHECKERROR(hr); + ASSERT( ctDecls>0 && ctDecls=0 && _iColPass>=0); + ASSERT( _iVtxPos >=0 && _iVtxPos<65536); + const BOOL bHWTnL = _pGfx->gl_ulFlags & GLF_D3D_USINGHWTNL; + + // determine which buffer we work on + switch(iType) + { + + // VERTICES + case 0: + // make sure that we have enough space in vertex buffers + ASSERT(GFX_ctVertices>0); + SetupVertexArrays_D3D( GFX_ctVertices * (bHWTnL?2:1)); + // determine lock type + pd3dVB = _pGfx->gl_pd3dVtx; + if( !bHWTnL || (_iVtxOffset+GFX_ctVertices)>=_pGfx->gl_ctVertices) { + // reset pos and flags + _iVtxOffset = 0; + _dwVtxLockFlags = D3DLOCK_DISCARD; + for( INDEX i=0; igl_iMaxTessellationLevel>0 && gap_iTruformLevel>0); // only if enabled + pd3dVB = _pGfx->gl_pd3dNor; + ASSERT( _iTexPass<2 && _iColPass<2); // normals must be set in 1st pass (completed or not) + // determine lock type, pos and size + dwLockFlag = _dwVtxLockFlags; + ctLockSize = GFX_ctVertices*4; + iLockOffset = _iVtxPos*4; + // set stream params + iStream = NORIDX; + slStride = NORSIZE; + break; + + // COLORS + case 2: + iThisPass = _iColPass; + // restart in case of too many passes + if( iThisPass>=_pGfx->gl_ctColBuffers) { + dwLockFlag = D3DLOCK_DISCARD; + iThisPass %= _pGfx->gl_ctColBuffers; + } else { // continue in case of enough buffers + dwLockFlag = _dwColLockFlags[iThisPass]; + } // mark + _dwColLockFlags[iThisPass] = D3DLOCK_NOOVERWRITE; + ASSERT( iThisPass>=0 && iThisPass<_pGfx->gl_ctColBuffers); + pd3dVB = _pGfx->gl_pd3dCol[iThisPass]; + // determine lock pos and size + ctLockSize = GFX_ctVertices*1; + iLockOffset = _iVtxPos*1; + // set stream params + iStream = COLIDX; + slStride = COLSIZE; + _iColPass++; // advance to next color pass + break; + + // PROJECTIVE TEXTURE COORDINATES + case 4: + _bProjectiveMapping = TRUE; + // fall thru ... + + // TEXTURE COORDINATES + case 3: + iThisPass = _iTexPass; + // restart in case of too many passes + if( iThisPass>=_pGfx->gl_ctTexBuffers) { + dwLockFlag = D3DLOCK_DISCARD; + iThisPass %= _pGfx->gl_ctTexBuffers; + } else { // continue in case of enough buffers + dwLockFlag = _dwTexLockFlags[iThisPass]; + } // mark + _dwTexLockFlags[iThisPass] = D3DLOCK_NOOVERWRITE; + ASSERT( iThisPass>=0 && iThisPass<_pGfx->gl_ctTexBuffers); + pd3dVB = _pGfx->gl_pd3dTex[iThisPass]; + // set stream number (must take into account tex-unit, because of multi-texturing!) + iStream = TEXIDX +GFX_iActiveTexUnit; + // determine stride, lock pos and size + if( _bProjectiveMapping) { + ctLockSize = GFX_ctVertices*4; + iLockOffset = _iVtxPos*4; + slStride = TX4SIZE; + } else { + ctLockSize = GFX_ctVertices*2; + iLockOffset = _iVtxPos*2; + slStride = TEXSIZE; + } // advance to next texture pass + _iTexPass++; + break; + + // BUF! WRONG. + default: ASSERTALWAYS( "SetVertexArray_D3D: wrong stream number!"); + } + + ASSERT( _iTexPass>=0 && _iColPass>=0); + ASSERT( _iVtxPos >=0 && _iVtxPos<65536); + + // fetch D3D buffer + ULONG *pulLockedBuffer; + hr = pd3dVB->Lock( iLockOffset*sizeof(ULONG), ctLockSize*sizeof(ULONG), (UBYTE**)&pulLockedBuffer, dwLockFlag); + D3D_CHECKERROR(hr); + + // copy (or convert) vertices there and unlock + ASSERT(pulVtx!=NULL); + if( iType!=2) CopyLongs( pulVtx, pulLockedBuffer, ctLockSize); // vertex array + else abgr2argb( pulVtx, pulLockedBuffer, ctLockSize); // color array (needs conversion) + + // done + hr = pd3dVB->Unlock(); + D3D_CHECKERROR(hr); + + // update streams mask and assign + _ulStreamsMask |= 1<gl_pd3dDevice->SetStreamSource( iStream, pd3dVB, slStride); + D3D_CHECKERROR(hr); +} + + + +// prepare and draw arrays +extern void DrawElements_D3D( INDEX ctIndices, INDEX *pidx) +{ + // paranoid & sunburnt (by Skunk Anansie:) + ASSERT( _iTexPass>=0 && _iColPass>=0); + ASSERT( _iVtxPos >=0 && _iVtxPos<65536); + const LPDIRECT3DDEVICE8 pd3dDev = _pGfx->gl_pd3dDevice; + + // at least one triangle must be sent + ASSERT( ctIndices>=3 && ((ctIndices/3)*3)==ctIndices); + if( ctIndices<3) return; + extern INDEX d3d_iVertexRangeTreshold; + d3d_iVertexRangeTreshold = Clamp( d3d_iVertexRangeTreshold, 0L, 9999L); + + // eventually adjust size of index buffer + const BOOL bHWTnL = _pGfx->gl_ulFlags & GLF_D3D_USINGHWTNL; + SetupIndexArray_D3D( ctIndices * (bHWTnL?2:1)); + + // determine lock position and type + if( (_iIdxOffset+ctIndices) >= _pGfx->gl_ctIndices) _iIdxOffset = 0; + const DWORD dwLockFlag = (_iIdxOffset>0) ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD; + const SLONG slLockSize = ctIndices *IDXSIZE; + const SLONG slLockOffset = _iIdxOffset*IDXSIZE; + + // copy indices to index buffer + HRESULT hr; + UWORD *puwLockedBuffer; + hr = _pGfx->gl_pd3dIdx->Lock( slLockOffset, slLockSize, (UBYTE**)&puwLockedBuffer, dwLockFlag); + D3D_CHECKERROR(hr); + + INDEX iMinIndex = 65536; + INDEX iMaxIndex = 0; + const BOOL bSetRange = !(_pGfx->gl_ulFlags&GLF_D3D_USINGHWTNL) && (GFX_ctVertices>d3d_iVertexRangeTreshold); + ASSERT( _iVtxPos>=0 && _iVtxPos<65536); + +#if ASMOPT == 1 + const __int64 mmSignD = 0x0000800000008000; + const __int64 mmSignW = 0x8000800080008000; + __asm { + // adjust 32-bit and copy to 16-bit array + mov esi,D [pidx] + mov edi,D [puwLockedBuffer] + mov ecx,D [ctIndices] + shr ecx,2 // 4 by 4 + jz elemL2 + movd mm7,D [_iVtxPos] + punpcklwd mm7,mm7 + punpckldq mm7,mm7 // MM7 = vtxPos | vtxPos || vtxPos | vtxPos + paddw mm7,Q [mmSignW] +elemCLoop: + movq mm1,Q [esi+0] + movq mm2,Q [esi+8] + psubd mm1,Q [mmSignD] + psubd mm2,Q [mmSignD] + packssdw mm1,mm2 + paddw mm1,mm7 + movq Q [edi],mm1 + add esi,4*4 + add edi,2*4 + dec ecx + jnz elemCLoop + emms +elemL2: + test D [ctIndices],2 + jz elemL1 + mov eax,D [esi+0] + mov edx,D [esi+4] + add eax,D [_iVtxPos] + add edx,D [_iVtxPos] + shl edx,16 + or eax,edx + mov D [edi],eax + add esi,4*2 + add edi,2*2 +elemL1: + test D [ctIndices],1 + jz elemRange + mov eax,D [esi] + add eax,D [_iVtxPos] + mov W [edi],ax + +elemRange: + // find min/max index (if needed) + cmp D [bSetRange],0 + jz elemEnd + + mov edi,D [iMinIndex] + mov edx,D [iMaxIndex] + mov esi,D [pidx] + mov ecx,D [ctIndices] +elemTLoop: + mov eax,D [esi] + add eax,D [_iVtxPos] + cmp eax,edi + cmovl edi,eax + cmp eax,edx + cmovg edx,eax + add esi,4 + dec ecx + jnz elemTLoop + mov D [iMinIndex],edi + mov D [iMaxIndex],edx +elemEnd: + } +#else + for( INDEX idx=0; idxiAdj) iMinIndex = iAdj; + else if( iMaxIndexgl_pd3dIdx->Unlock(); + D3D_CHECKERROR(hr); + + // check whether to use color array or not + if( GFX_bColorArray) _ulStreamsMask |= (1<SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, ttf); + D3D_CHECKERROR(hr); + } + + // eventually (re)construct vertex shader out of streams' bit-mask + if( _ulLastStreamsMask != _ulStreamsMask) + { // reset streams that were used before + ULONG ulThisMask = _ulStreamsMask; + ULONG ulLastMask = _ulLastStreamsMask; + for( INDEX iStream=0; iStreamSetStreamSource( iStream,NULL,0); + D3D_CHECKERROR(hr); + } // next stream + ulThisMask >>= 1; + ulLastMask >>= 1; + } + // setup new vertex shader + _dwCurrentVS = SetupShader_D3D(_ulStreamsMask); + _ulLastStreamsMask = _ulStreamsMask; + } + + // (re)set vertex shader + ASSERT(_dwCurrentVS!=NONE); + if( _pGfx->gl_dwVertexShader!=_dwCurrentVS) { + hr = _pGfx->gl_pd3dDevice->SetVertexShader(_dwCurrentVS); + D3D_CHECKERROR(hr); + _pGfx->gl_dwVertexShader = _dwCurrentVS; + } + +#ifndef NDEBUG + // Paranoid Android (by Radiohead:) + CheckStreams(); +#endif + + // determine vertex range + INDEX iVtxStart, ctVtxUsed; + // if not too much vertices in buffer + if( !bSetRange) { + // set whole vertex buffer + iVtxStart = _iVtxPos; + ctVtxUsed = GFX_ctVertices; + // if lotta vertices in buffer + } else { + // set only part of vertex buffer + iVtxStart = iMinIndex; + ctVtxUsed = iMaxIndex-iMinIndex+1; + ASSERT( iMinIndexDrawIndexedPrimitive( D3DPT_TRIANGLELIST, iVtxStart, ctVtxUsed, _iIdxOffset, ctIndices/3); + D3D_CHECKERROR(hr); + // move to next available lock position + _iIdxOffset += ctIndices; +} + +#endif // SE1_D3D \ No newline at end of file diff --git a/Sources/Engine/Graphics/Gfx_Direct3D_Colors.cpp b/Sources/Engine/Graphics/Gfx_Direct3D_Colors.cpp new file mode 100644 index 0000000..a81643b --- /dev/null +++ b/Sources/Engine/Graphics/Gfx_Direct3D_Colors.cpp @@ -0,0 +1,344 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#ifdef SE1_D3D + +#include +#pragma comment(lib, "d3dx8.lib") + +#include + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + + +static ULONG _ulAlphaMask = 0; +static void (*pConvertMipmap)( ULONG *pulSrc, void *pulDst, PIX pixWidth, PIX pixHeight, SLONG slPitch); + + + +// convert to any D3DFormat (thru D3DX functions - slow!) +static void ConvertAny( ULONG *pulSrc, LPDIRECT3DTEXTURE8 ptexDst, PIX pixWidth, PIX pixHeight, INDEX iMip) +{ + // alloc temporary memory and flip colors there + const PIX pixSize = pixWidth*pixHeight; + ULONG *pulFlipped = (ULONG*)AllocMemory( pixSize*4); + abgr2argb( pulSrc, pulFlipped, pixSize); + + // get mipmap surface + HRESULT hr; + LPDIRECT3DSURFACE8 pd3dSurf; + hr = ptexDst->GetSurfaceLevel( iMip, &pd3dSurf); + D3D_CHECKERROR(hr); + + // prepare and upload surface + const RECT rect = { 0,0, pixWidth, pixHeight }; + const SLONG slPitch = pixWidth*4; + hr = D3DXLoadSurfaceFromMemory( pd3dSurf, NULL, NULL, pulFlipped, D3DFMT_A8R8G8B8, slPitch, NULL, &rect, D3DX_FILTER_NONE, 0); + D3D_CHECKERROR(hr); + + // done + pd3dSurf->Release(); // must not use D3DRELEASE, because freeing all istances will free texture also when using DXTC!? (Bravo MS!) + FreeMemory( pulFlipped); +} + + + +// fast conversion from RGBA memory format to one of D3D color formats + + +static void ConvARGB8( ULONG *pulSrc, void *pulDst, PIX pixWidth, PIX pixHeight, SLONG slPitch) +{ + const ULONG slRowModulo = slPitch - (pixWidth<<2); + __asm { + mov esi,D [pulSrc] + mov edi,D [pulDst] + mov ebx,D [pixHeight] +rowLoop: + mov ecx,D [pixWidth] +pixLoop: + mov eax,D [esi] + or eax,D [_ulAlphaMask] + bswap eax + ror eax,8 + mov D [edi],eax + add esi,4 + add edi,4 + dec ecx + jnz pixLoop + add edi,D [slRowModulo] + dec ebx + jnz rowLoop + } +} + + +static void ConvARGB5( ULONG *pulSrc, void *pulDst, PIX pixWidth, PIX pixHeight, SLONG slPitch) +{ + const ULONG slRowModulo = slPitch - (pixWidth<<1); + __asm { + mov esi,D [pulSrc] + mov edi,D [pulDst] + mov ebx,D [pixHeight] +rowLoop: + movd mm0,ebx + mov ecx,D [pixWidth] +pixLoop: + movd mm1,ecx + mov eax,D [esi] + or eax,D [_ulAlphaMask] + mov ebx,eax + mov ecx,eax + mov edx,eax + and eax,0x000000F8 // R + and ebx,0x0000F800 // G + and ecx,0x00F80000 // B + and edx,0x80000000 // A + shl eax,7 + shr ebx,6 + shr ecx,16+3 + shr edx,16 + or eax,ebx + or ecx,edx + or eax,ecx + mov W [edi],ax + add esi,4 + add edi,2 + movd ecx,mm1 + dec ecx + jnz pixLoop + add edi,D [slRowModulo] + movd ebx,mm0 + dec ebx + jnz rowLoop + emms + } +} + + +static void ConvARGB4( ULONG *pulSrc, void *pulDst, PIX pixWidth, PIX pixHeight, SLONG slPitch) +{ + const ULONG slRowModulo = slPitch - (pixWidth<<1); + __asm { + mov esi,D [pulSrc] + mov edi,D [pulDst] + mov ebx,D [pixHeight] +rowLoop: + movd mm0,ebx + mov ecx,D [pixWidth] +pixLoop: + movd mm1,ecx + mov eax,D [esi] + or eax,D [_ulAlphaMask] + mov ebx,eax + mov ecx,eax + mov edx,eax + and eax,0x000000F0 // R + and ebx,0x0000F000 // G + and ecx,0x00F00000 // B + and edx,0xF0000000 // A + shl eax,4 + shr ebx,8 + shr ecx,16+4 + shr edx,16 + or eax,ebx + or ecx,edx + or eax,ecx + mov W [edi],ax + add esi,4 + add edi,2 + movd ecx,mm1 + dec ecx + jnz pixLoop + add edi,D [slRowModulo] + movd ebx,mm0 + dec ebx + jnz rowLoop + emms + } +} + + +static void ConvRGB5( ULONG *pulSrc, void *pulDst, PIX pixWidth, PIX pixHeight, SLONG slPitch) +{ + const ULONG slRowModulo = slPitch - (pixWidth<<1); + __asm { + mov esi,D [pulSrc] + mov edi,D [pulDst] + mov ebx,D [pixHeight] +rowLoop: + movd mm0,ebx + mov ecx,D [pixWidth] +pixLoop: + mov eax,D [esi] + mov ebx,eax + mov edx,eax + and eax,0x000000F8 // R + and ebx,0x0000FC00 // G + and edx,0x00F80000 // B + shl eax,8 + shr ebx,5 + shr edx,8+5+6 + or eax,ebx + or eax,edx + mov W [edi],ax + add esi,4 + add edi,2 + dec ecx + jnz pixLoop + add edi,D [slRowModulo] + movd ebx,mm0 + dec ebx + jnz rowLoop + emms + } +} + + +static void ConvAL8( ULONG *pulSrc, void *pulDst, PIX pixWidth, PIX pixHeight, SLONG slPitch) +{ + const ULONG slRowModulo = slPitch - (pixWidth<<1); + __asm { + mov esi,D [pulSrc] + mov edi,D [pulDst] + mov ebx,D [pixHeight] +rowLoop: + mov ecx,D [pixWidth] +pixLoop: + mov eax,D [esi] + ror eax,8 + bswap eax + mov D [edi],eax + add esi,4 + add edi,2 + dec ecx + jnz pixLoop + add edi,D [slRowModulo] + dec ebx + jnz rowLoop + } +} + + + +static void ConvL8( ULONG *pulSrc, void *pulDst, PIX pixWidth, PIX pixHeight, SLONG slPitch) +{ + const ULONG slRowModulo = slPitch - (pixWidth<<0); + __asm { + mov esi,D [pulSrc] + mov edi,D [pulDst] + mov ebx,D [pixHeight] +rowLoop: + mov ecx,D [pixWidth] +pixLoop: + mov eax,D [esi] + mov B [edi],al + add esi,4 + add edi,1 + dec ecx + jnz pixLoop + add edi,D [slRowModulo] + dec ebx + jnz rowLoop + } +} + + + + +// set color conversion routine +extern void SetInternalFormat_D3D( D3DFORMAT d3dFormat) +{ + // by default, go thru D3DX :( + pConvertMipmap = NULL; + extern INDEX d3d_bFastUpload; + if( !d3d_bFastUpload) return; // done here if fast upload is not allowed + + // try to set corresponding fast-upload routine + switch( d3dFormat) { + case D3DFMT_A8R8G8B8: _ulAlphaMask=0x00000000; pConvertMipmap=ConvARGB8; break; + case D3DFMT_X8R8G8B8: _ulAlphaMask=0xFF000000; pConvertMipmap=ConvARGB8; break; + case D3DFMT_A1R5G5B5: _ulAlphaMask=0x00000000; pConvertMipmap=ConvARGB5; break; + case D3DFMT_X1R5G5B5: _ulAlphaMask=0xFF000000; pConvertMipmap=ConvARGB5; break; + case D3DFMT_A4R4G4B4: _ulAlphaMask=0x00000000; pConvertMipmap=ConvARGB4; break; + case D3DFMT_X4R4G4B4: _ulAlphaMask=0xFF000000; pConvertMipmap=ConvARGB4; break; + case D3DFMT_R5G6B5: pConvertMipmap=ConvRGB5; break; + case D3DFMT_A8L8: pConvertMipmap=ConvAL8; break; + case D3DFMT_L8: pConvertMipmap=ConvL8; break; + default: break; + } +} + + +// convert one mipmap from memory to surface +extern void UploadMipmap_D3D( ULONG *pulSrc, LPDIRECT3DTEXTURE8 ptexDst, PIX pixWidth, PIX pixHeight, INDEX iMip) +{ + // general case thru D3DX approach + if( pConvertMipmap==NULL) { + ConvertAny( pulSrc, ptexDst, pixWidth, pixHeight, iMip); + return; + } + // yeah! - optimized case :) + HRESULT hr; + D3DLOCKED_RECT rectLocked; + hr = ptexDst->LockRect( iMip, &rectLocked, NULL, NONE); + D3D_CHECKERROR(hr); + pConvertMipmap( pulSrc, rectLocked.pBits, pixWidth, pixHeight, rectLocked.Pitch); + hr = ptexDst->UnlockRect(iMip); + D3D_CHECKERROR(hr); +} + + +// unpack from some of D3D color formats to COLOR +extern COLOR UnpackColor_D3D( UBYTE *pd3dColor, D3DFORMAT d3dFormat, SLONG &slColorSize) +{ + UWORD uw; + UBYTE ubR,ubG,ubB; + switch(d3dFormat) { + case D3DFMT_R8G8B8: + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + ubB = pd3dColor[0]; + ubG = pd3dColor[1]; + ubR = pd3dColor[2]; + slColorSize = 4; + if( d3dFormat==D3DFMT_R8G8B8) slColorSize = 3; + break; + case D3DFMT_R5G6B5: + uw = (UWORD&)*pd3dColor; + ubR = (uw&0xF800)>>8; ubR |= ubR>>5; + ubG = (uw&0x07E0)>>3; ubG |= ubG>>6; + ubB = (uw&0x001F)<<3; ubB |= ubB>>5; + slColorSize = 2; + break; + case D3DFMT_X1R5G5B5: + case D3DFMT_A1R5G5B5: + uw = (UWORD&)*pd3dColor; + ubR = (uw&0x7C00)>>7; ubR |= ubR>>5; + ubG = (uw&0x03E0)>>2; ubG |= ubG>>5; + ubB = (uw&0x001F)<<3; ubB |= ubB>>5; + slColorSize = 2; + break; + case D3DFMT_X4R4G4B4: + case D3DFMT_A4R4G4B4: + uw = (UWORD&)*pd3dColor; + ubR = (uw&0x0F00)>>4; ubR |= ubR>>4; + ubG = (uw&0x00F0)>>0; ubG |= ubG>>4; + ubB = (uw&0x000F)<<4; ubB |= ubB>>4; + slColorSize = 2; + break; + default: // unsupported format + ubR = ubG = ubB = 0; + slColorSize = 0; + break; + } + // done + return RGBToColor(ubR,ubG,ubB); +} + +#endif // SE1_D3D \ No newline at end of file diff --git a/Sources/Engine/Graphics/Gfx_Direct3D_Textures.cpp b/Sources/Engine/Graphics/Gfx_Direct3D_Textures.cpp new file mode 100644 index 0000000..0c3dbb4 --- /dev/null +++ b/Sources/Engine/Graphics/Gfx_Direct3D_Textures.cpp @@ -0,0 +1,272 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#ifdef SE1_D3D + +#include +#pragma comment(lib, "d3dx8.lib") + +#include + +#include +#include +#include + +#include + + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + + +// we need array for Direct3D mipmaps that are lower than N*1 or 1*N +static ULONG _aulLastMipmaps[(INDEX)(1024*1.334)]; +static CTexParams *_tpCurrent; +static _D3DTEXTUREFILTERTYPE _eLastMipFilter; + +extern INDEX GFX_iActiveTexUnit; + + +// conversion from OpenGL's RGBA color format to one of D3D color formats +extern void SetInternalFormat_D3D( D3DFORMAT d3dFormat); +extern void UploadMipmap_D3D( ULONG *pulSrc, LPDIRECT3DTEXTURE8 ptexDst, PIX pixWidth, PIX pixHeight, INDEX iMip); + + +// unpacks texture filtering from one INDEX to two GLenums (and eventually re-adjust input INDEX) +extern void UnpackFilter_D3D( INDEX iFilter, _D3DTEXTUREFILTERTYPE &eMagFilter, + _D3DTEXTUREFILTERTYPE &eMinFilter, _D3DTEXTUREFILTERTYPE &eMipFilter) +{ + switch( iFilter) { + case 110: case 10: eMagFilter=D3DTEXF_POINT; eMinFilter=D3DTEXF_POINT; eMipFilter=D3DTEXF_NONE; break; + case 111: case 11: eMagFilter=D3DTEXF_POINT; eMinFilter=D3DTEXF_POINT; eMipFilter=D3DTEXF_POINT; break; + case 112: case 12: eMagFilter=D3DTEXF_POINT; eMinFilter=D3DTEXF_POINT; eMipFilter=D3DTEXF_LINEAR; break; + case 220: case 20: eMagFilter=D3DTEXF_LINEAR; eMinFilter=D3DTEXF_LINEAR; eMipFilter=D3DTEXF_NONE; break; + case 221: case 21: eMagFilter=D3DTEXF_LINEAR; eMinFilter=D3DTEXF_LINEAR; eMipFilter=D3DTEXF_POINT; break; + case 222: case 22: eMagFilter=D3DTEXF_LINEAR; eMinFilter=D3DTEXF_LINEAR; eMipFilter=D3DTEXF_LINEAR; break; + case 120: eMagFilter=D3DTEXF_POINT; eMinFilter=D3DTEXF_LINEAR; eMipFilter=D3DTEXF_NONE; break; + case 121: eMagFilter=D3DTEXF_POINT; eMinFilter=D3DTEXF_LINEAR; eMipFilter=D3DTEXF_POINT; break; + case 122: eMagFilter=D3DTEXF_POINT; eMinFilter=D3DTEXF_LINEAR; eMipFilter=D3DTEXF_LINEAR; break; + case 210: eMagFilter=D3DTEXF_LINEAR; eMinFilter=D3DTEXF_POINT; eMipFilter=D3DTEXF_NONE; break; + case 211: eMagFilter=D3DTEXF_LINEAR; eMinFilter=D3DTEXF_POINT; eMipFilter=D3DTEXF_POINT; break; + case 212: eMagFilter=D3DTEXF_LINEAR; eMinFilter=D3DTEXF_POINT; eMipFilter=D3DTEXF_LINEAR; break; + default: ASSERTALWAYS( "Illegal Direct3D texture filtering mode."); break; + } +} + + +// change texture filtering mode if needed +extern void MimicTexParams_D3D( CTexParams &tpLocal) +{ + ASSERT( &tpLocal!=NULL); + _pfGfxProfile.StartTimer( CGfxProfile::PTI_TEXTUREPARAMS); + + // update texture filtering mode if required + if( tpLocal.tp_iFilter != _tpGlobal[0].tp_iFilter) tpLocal.tp_iFilter = _tpGlobal[0].tp_iFilter; + + // eventually adjust filtering for textures w/o mipmaps + const INDEX iMipFilter = _tpGlobal[0].tp_iFilter % 10; + if( (!tpLocal.tp_bSingleMipmap != !_tpGlobal[GFX_iActiveTexUnit].tp_bSingleMipmap) && iMipFilter!=0) + { + HRESULT hr; + _D3DTEXTUREFILTERTYPE eMipFilter; + extern INDEX GFX_iActiveTexUnit; + + // no mipmaps? + if( tpLocal.tp_bSingleMipmap) { +#ifndef NDEBUG + // paranoid! + hr = _pGfx->gl_pd3dDevice->GetTextureStageState( GFX_iActiveTexUnit, D3DTSS_MIPFILTER, (ULONG*)&eMipFilter); + D3D_CHECKERROR(hr); + ASSERT( eMipFilter==D3DTEXF_POINT || eMipFilter==D3DTEXF_LINEAR); +#endif // set it + hr = _pGfx->gl_pd3dDevice->SetTextureStageState( GFX_iActiveTexUnit, D3DTSS_MIPFILTER, D3DTEXF_NONE); + } + // yes mipmaps? + else { + switch( iMipFilter) { + case 0: eMipFilter = D3DTEXF_NONE; break; + case 1: eMipFilter = D3DTEXF_POINT; break; + case 2: eMipFilter = D3DTEXF_LINEAR; break; + default: ASSERTALWAYS( "Invalid mipmap filtering mode."); + } // set it + hr = _pGfx->gl_pd3dDevice->SetTextureStageState( GFX_iActiveTexUnit, D3DTSS_MIPFILTER, eMipFilter); + } + // check and update mipmap state + D3D_CHECKERROR(hr); + _tpGlobal[GFX_iActiveTexUnit].tp_bSingleMipmap = tpLocal.tp_bSingleMipmap; + } + + // update texture anisotropy degree + if( tpLocal.tp_iAnisotropy != _tpGlobal[0].tp_iAnisotropy) tpLocal.tp_iAnisotropy = _tpGlobal[0].tp_iAnisotropy; + + // update texture clamping modes if changed + if( tpLocal.tp_eWrapU!=_tpGlobal[GFX_iActiveTexUnit].tp_eWrapU || tpLocal.tp_eWrapV!=_tpGlobal[GFX_iActiveTexUnit].tp_eWrapV) { + tpLocal.tp_eWrapU = _tpGlobal[GFX_iActiveTexUnit].tp_eWrapU; + tpLocal.tp_eWrapV = _tpGlobal[GFX_iActiveTexUnit].tp_eWrapV; + } + + // keep last texture params (for tex upload and stuff) + _tpCurrent = &tpLocal; + _pfGfxProfile.StopTimer( CGfxProfile::PTI_TEXTUREPARAMS); +} + + + + +// upload context for current texture to accelerator's memory +// (returns format in which texture was really uploaded) +extern void UploadTexture_D3D( LPDIRECT3DTEXTURE8 *ppd3dTexture, ULONG *pulTexture, + PIX pixSizeU, PIX pixSizeV, D3DFORMAT eInternalFormat, BOOL bDiscard) +{ + // safeties + ASSERT( pulTexture!=NULL); + ASSERT( pixSizeU>0 && pixSizeV>0); + _sfStats.StartTimer( CStatForm::STI_BINDTEXTURE); + _pfGfxProfile.StartTimer( CGfxProfile::PTI_TEXTUREUPLOADING); + + // recreate texture if needed + HRESULT hr; + if( bDiscard) { + if( (*ppd3dTexture)!=NULL) D3DRELEASE( (*ppd3dTexture), TRUE); + hr = _pGfx->gl_pd3dDevice->CreateTexture( pixSizeU, pixSizeV, 0, 0, eInternalFormat, D3DPOOL_MANAGED, ppd3dTexture); + D3D_CHECKERROR(hr); + } + // D3D texture must be valid now + LPDIRECT3DTEXTURE8 pd3dTex = (*ppd3dTexture); + ASSERT( pd3dTex!=NULL); + + // prepare routine for conversion + SetInternalFormat_D3D(eInternalFormat); + + // upload each mipmap + INDEX iMip=0; + PIX pixOffset=0; + while( pixSizeU>0 && pixSizeV>0) + { + // check that memory is readable and upload one mipmap + ASSERT( pulTexture[pixOffset +pixSizeU*pixSizeV -1] != 0xDEADBEEF); + UploadMipmap_D3D( pulTexture+pixOffset, pd3dTex, pixSizeU, pixSizeV, iMip); + // advance to next mip-map + pixOffset += pixSizeU*pixSizeV; + pixSizeU >>=1; + pixSizeV >>=1; + iMip++; + // end here if there is only one mip-map to upload + if( _tpCurrent->tp_bSingleMipmap) break; + } + + // see if we need to generate and upload additional mipmaps (those under 1*N or N*1) + if( !_tpCurrent->tp_bSingleMipmap && pixSizeU!=pixSizeV) + { // prepare variables + PIX pixSize = Max(pixSizeU,pixSizeV); + ASSERT( pixSize<=2048); + ULONG *pulSrc = pulTexture+pixOffset-pixSize*2; + ULONG *pulDst = _aulLastMipmaps; + // loop thru mipmaps + while( pixSizeU>0 || pixSizeV>0) + { // make next mipmap + if( pixSizeU==0) pixSizeU=1; + if( pixSizeV==0) pixSizeV=1; + pixSize = pixSizeU*pixSizeV; + __asm { + pxor mm0,mm0 + mov esi,D [pulSrc] + mov edi,D [pulDst] + mov ecx,D [pixSize] + pixLoop: + movd mm1,D [esi+0] + movd mm2,D [esi+4] + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + paddw mm1,mm2 + psrlw mm1,1 + packuswb mm1,mm0 + movd D [edi],mm1 + add esi,4*2 + add edi,4 + dec ecx + jnz pixLoop + emms + } + // upload mipmap and advance + UploadMipmap_D3D( pulDst, pd3dTex, pixSizeU, pixSizeV, iMip); + pulSrc = pulDst; + pulDst += pixSize; + pixOffset += pixSize; + pixSizeU >>=1; + pixSizeV >>=1; + iMip++; + } + } + + // all done + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_TEXTUREUPLOADS, 1); + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_TEXTUREUPLOADBYTES, pixOffset*4); + _sfStats.IncrementCounter( CStatForm::SCI_TEXTUREUPLOADS, 1); + _sfStats.IncrementCounter( CStatForm::SCI_TEXTUREUPLOADBYTES, pixOffset*4); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_TEXTUREUPLOADING); + _sfStats.StopTimer( CStatForm::STI_BINDTEXTURE); +} + + + +// returns bytes/pixels ratio for texture format +extern INDEX GetFormatPixRatio_D3D( D3DFORMAT d3dFormat) +{ + switch( d3dFormat) { + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + return 4; + case D3DFMT_R8G8B8: + return 3; + case D3DFMT_R5G6B5: + case D3DFMT_X1R5G5B5: + case D3DFMT_A1R5G5B5: + case D3DFMT_A4R4G4B4: + case D3DFMT_X4R4G4B4: + case D3DFMT_A8L8: + return 2; + // compressed formats and single-channel formats + default: + return 1; + } +} + + +// returns bytes/pixels ratio for uploaded texture +extern INDEX GetTexturePixRatio_D3D( LPDIRECT3DTEXTURE8 pd3dTexture) +{ + D3DSURFACE_DESC d3dSurfDesc; + HRESULT hr = pd3dTexture->GetLevelDesc( 0, &d3dSurfDesc); + D3D_CHECKERROR(hr); + return GetFormatPixRatio_D3D( d3dSurfDesc.Format); +} + + +// return allowed dithering method +extern INDEX AdjustDitheringType_D3D( D3DFORMAT eFormat, INDEX iDitheringType) +{ + switch( eFormat) { + // these formats don't need dithering + case D3DFMT_A8R8G8B8: + case D3DFMT_X8R8G8B8: + case D3DFMT_L8: + case D3DFMT_A8L8: + return NONE; + // these formats need reduced dithering + case D3DFMT_R5G6B5: + case D3DFMT_X1R5G5B5: + case D3DFMT_A1R5G5B5: + if( iDitheringType>7) return iDitheringType-3; + // other formats need dithering as it is + default: + return iDitheringType; + } +} + +#endif // SE1_D3D \ No newline at end of file diff --git a/Sources/Engine/Graphics/Gfx_OpenGL.cpp b/Sources/Engine/Graphics/Gfx_OpenGL.cpp new file mode 100644 index 0000000..1af0f1b --- /dev/null +++ b/Sources/Engine/Graphics/Gfx_OpenGL.cpp @@ -0,0 +1,918 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + + +extern INDEX ogl_iTBufferEffect; +extern INDEX ogl_iTBufferSamples; + + +// fog/haze textures +extern ULONG _fog_ulTexture; +extern ULONG _haze_ulTexture; + +// change control +extern INDEX GFX_ctVertices; + + +// attributes for t-buffer +int aiAttribList[] = { + WGL_DRAW_TO_WINDOW_EXT, TRUE, + WGL_SUPPORT_OPENGL_EXT, TRUE, + WGL_DOUBLE_BUFFER_EXT, TRUE, + WGL_PIXEL_TYPE_EXT, WGL_TYPE_RGBA_EXT, + WGL_COLOR_BITS_EXT, 16, + WGL_DEPTH_BITS_EXT, 16, + WGL_SAMPLE_BUFFERS_3DFX, 1, + WGL_SAMPLES_3DFX, 4, + 0, 0 +}; +int *piAttribList = aiAttribList; + + +// engine's internal opengl state variables +extern BOOL GFX_bDepthTest; +extern BOOL GFX_bDepthWrite; +extern BOOL GFX_bAlphaTest; +extern BOOL GFX_bBlending; +extern BOOL GFX_bDithering; +extern BOOL GFX_bClipping; +extern BOOL GFX_bClipPlane; +extern BOOL GFX_bColorArray; +extern BOOL GFX_bFrontFace; +extern BOOL GFX_bTruform; +extern INDEX GFX_iActiveTexUnit; +extern FLOAT GFX_fMinDepthRange; +extern FLOAT GFX_fMaxDepthRange; +extern GfxBlend GFX_eBlendSrc; +extern GfxBlend GFX_eBlendDst; +extern GfxComp GFX_eDepthFunc; +extern GfxFace GFX_eCullFace; +extern INDEX GFX_iTexModulation[GFX_MAXTEXUNITS]; +extern BOOL glbUsingVARs = FALSE; // vertex_array_range + + +// define gl function pointers +#define DLLFUNCTION(dll, output, name, inputs, params, required) \ + output (__stdcall *p##name) inputs = NULL; +#include "gl_functions.h" +#undef DLLFUNCTION + +// extensions +void (__stdcall *pglLockArraysEXT)(GLint first, GLsizei count) = NULL; +void (__stdcall *pglUnlockArraysEXT)(void) = NULL; + +GLboolean (__stdcall *pwglSwapIntervalEXT)(GLint interval) = NULL; +GLint (__stdcall *pwglGetSwapIntervalEXT)(void) = NULL; + +void (__stdcall *pglActiveTextureARB)(GLenum texunit) = NULL; +void (__stdcall *pglClientActiveTextureARB)(GLenum texunit) = NULL; + +// t-buffer support +char *(__stdcall *pwglGetExtensionsStringARB)(HDC hdc); +BOOL (__stdcall *pwglChoosePixelFormatARB)(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +BOOL (__stdcall *pwglGetPixelFormatAttribivARB)(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); +void (__stdcall *pglTBufferMask3DFX)(GLuint mask); + +// NV occlusion query +void (__stdcall *pglGenOcclusionQueriesNV)( GLsizei n, GLuint *ids); +void (__stdcall *pglDeleteOcclusionQueriesNV)( GLsizei n, const GLuint *ids); +void (__stdcall *pglBeginOcclusionQueryNV)( GLuint id); +void (__stdcall *pglEndOcclusionQueryNV)(void); +void (__stdcall *pglGetOcclusionQueryivNV)( GLuint id, GLenum pname, GLint *params); +void (__stdcall *pglGetOcclusionQueryuivNV)( GLuint id, GLenum pname, GLuint *params); +GLboolean (__stdcall *pglIsOcclusionQueryNV)( GLuint id); + +// ATI GL_ATI_pn_triangles +void (__stdcall *pglPNTrianglesiATI)( GLenum pname, GLint param); +void (__stdcall *pglPNTrianglesfATI)( GLenum pname, GLfloat param); + + +void WIN_CheckError(BOOL bRes, const char *strDescription) +{ + if( bRes) return; + DWORD dwWindowsErrorCode = GetLastError(); + if( dwWindowsErrorCode==ERROR_SUCCESS) return; // ignore stupid 'successful' error + WarningMessage("%s: %s", strDescription, GetWindowsError(dwWindowsErrorCode)); +} + + +static void FailFunction_t(const char *strName) { + ThrowF_t(TRANS("Required function %s not found."), strName); +} + + +static void OGL_SetFunctionPointers_t(HINSTANCE hiOGL) +{ + const char *strName; + // get gl function pointers + #define DLLFUNCTION(dll, output, name, inputs, params, required) \ + strName = #name; \ + p##name = (output (__stdcall*) inputs) GetProcAddress( hi##dll, strName); \ + if( required && p##name == NULL) FailFunction_t(strName); + #include "gl_functions.h" + #undef DLLFUNCTION +} + + +static void OGL_ClearFunctionPointers(void) +{ + // clear gl function pointers + #define DLLFUNCTION(dll, output, name, inputs, params, required) p##name = NULL; + #include "gl_functions.h" + #undef DLLFUNCTION +} + + + + +#define BACKOFF pwglMakeCurrent( NULL, NULL); \ + pwglDeleteContext( hglrc); \ + ReleaseDC( dummyhwnd, hdc); \ + DestroyWindow( dummyhwnd); \ + UnregisterClassA( classname, hInstance); + + + +// helper for choosing t-buffer's pixel format +static BOOL _TBCapability = FALSE; +static INDEX ChoosePixelFormatTB( HDC hdc, const PIXELFORMATDESCRIPTOR *ppfd, + PIX pixResWidth, PIX pixResHeight) +{ + _TBCapability = FALSE; + char *extensions = NULL; + char *wglextensions = NULL; + HGLRC hglrc; + HWND dummyhwnd; + WNDCLASSA cls; + HINSTANCE hInstance = GetModuleHandle(NULL); + LPCSTR classname = "dummyOGLwin"; + cls.style = CS_OWNDC; + cls.lpfnWndProc = DefWindowProc; + cls.cbClsExtra = 0; + cls.cbWndExtra = 0; + cls.hInstance = hInstance; + cls.hIcon = LoadIcon(NULL, IDI_APPLICATION); + cls.hCursor = LoadCursor(NULL, IDC_WAIT); + cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + cls.lpszMenuName = NULL; + cls.lpszClassName = classname; + // didn't manage to register class? + if( !RegisterClassA(&cls)) return 0; + + // create window fullscreen + //CPrintF( " Dummy window: %d x %d\n", pixResWidth, pixResHeight); + dummyhwnd = CreateWindowExA( WS_EX_TOPMOST, classname, "Dummy OGL window", + WS_POPUP|WS_VISIBLE, 0, 0, pixResWidth, pixResHeight, + NULL, NULL, hInstance, NULL); + // didn't make it? + if( dummyhwnd == NULL) { + UnregisterClassA( classname, hInstance); + return 0; + } + //CPrintF( " Dummy passed...\n"); + hdc = GetDC(dummyhwnd); + // try to choose pixel format + int iPixelFormat = pwglChoosePixelFormat( hdc, ppfd); + if( !iPixelFormat) { + ReleaseDC( dummyhwnd, hdc); + DestroyWindow(dummyhwnd); + UnregisterClassA( classname, hInstance); + return 0; + } + //CPrintF( " Choose pixel format passed...\n"); + // try to set pixel format + if( !pwglSetPixelFormat( hdc, iPixelFormat, ppfd)) { + ReleaseDC( dummyhwnd, hdc); + DestroyWindow(dummyhwnd); + UnregisterClassA( classname, hInstance); + return 0; + } + //CPrintF( " Set pixel format passed...\n"); + + // create context using the default accelerated pixelformat that was passed + hglrc = pwglCreateContext(hdc); + pwglMakeCurrent( hdc, hglrc); + // update the value list with information passed from the ppfd. + aiAttribList[ 9] = ppfd->cColorBits; + aiAttribList[11] = ppfd->cDepthBits; + aiAttribList[15] = _pGfx->go_ctSampleBuffers; + + // get the extension list. + extensions = (char*)pglGetString(GL_EXTENSIONS); + // get the wgl extension list. + if( strstr((const char*)extensions, "WGL_EXT_extensions_string ") != NULL) + { // windows extension string supported + pwglGetExtensionsStringARB = (char* (__stdcall*)(HDC))pwglGetProcAddress( "wglGetExtensionsStringARB"); + if( pwglGetExtensionsStringARB == NULL) { + BACKOFF + return 0; + } + //CPrintF( " WGL extension string passed...\n"); + // get WGL extension string + wglextensions = (char*)pwglGetExtensionsStringARB(hdc); + } + else { + BACKOFF + return 0; + } + + // check for the pixel format and multisample extension strings + if( (strstr((const char*)wglextensions, "WGL_ARB_pixel_format ") != NULL) && + (strstr((const char*)extensions, "GL_3DFX_multisample ") != NULL)) { + // 3dfx extensions present + _TBCapability = TRUE; + pwglChoosePixelFormatARB = (BOOL (__stdcall*)(HDC,const int*,const FLOAT*,UINT,int*,UINT*))pwglGetProcAddress( "wglChoosePixelFormatARB"); + pwglGetPixelFormatAttribivARB = (BOOL (__stdcall*)(HDC,int,int,UINT,int*,int*) )pwglGetProcAddress( "wglGetPixelFormatAttribivARB"); + pglTBufferMask3DFX = (void (__stdcall*)(GLuint))pwglGetProcAddress("glTBufferMask3DFX"); + if( pwglChoosePixelFormatARB==NULL && pglTBufferMask3DFX==NULL) { + BACKOFF + return 0; + } + //CPrintF( " WGL choose pixel format present...\n"); + int iAttribListNum = {WGL_NUMBER_PIXEL_FORMATS_EXT}; + int iMaxFormats = 1; // default number to return + if( pwglGetPixelFormatAttribivARB!=NULL) { + // get total number of formats supported. + pwglGetPixelFormatAttribivARB( hdc, NULL, NULL, 1, &iAttribListNum, &iMaxFormats); + //CPrintF( "Max formats: %d\n", iMaxFormats); + } + UINT uiNumFormats; + int *piFormats = (int*)AllocMemory( sizeof(UINT) *iMaxFormats); + // try to get all formats that fit the pixel format criteria + if( !pwglChoosePixelFormatARB( hdc, piAttribList, NULL, iMaxFormats, piFormats, &uiNumFormats)) { + FreeMemory(piFormats); + BACKOFF + return 0; + } + //CPrintF( " WGL choose pixel format passed...\n"); + // return the first match for now + iPixelFormat = 0; + if( uiNumFormats>0) { + iPixelFormat = piFormats[0]; + //CPrintF( "Num formats: %d\n", uiNumFormats); + //CPrintF( "First format: %d\n", iPixelFormat); + } + FreeMemory(piFormats); + } + else + { // wglChoosePixelFormatARB extension does not exist :( + iPixelFormat = 0; + } + BACKOFF + return iPixelFormat; +} + + +// prepares pixel format for OpenGL context +BOOL CGfxLibrary::SetupPixelFormat_OGL( HDC hdc, BOOL bReport/*=FALSE*/) +{ + int iPixelFormat = 0; + const PIX pixResWidth = gl_dmCurrentDisplayMode.dm_pixSizeI; + const PIX pixResHeight = gl_dmCurrentDisplayMode.dm_pixSizeJ; + const DisplayDepth dd = gl_dmCurrentDisplayMode.dm_ddDepth; + + PIXELFORMATDESCRIPTOR pfd; + memset( &pfd, 0, sizeof(pfd)); + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + + // clamp depth/stencil values + extern INDEX gap_iDepthBits; + extern INDEX gap_iStencilBits; + if( gap_iDepthBits <12) gap_iDepthBits = 0; + else if( gap_iDepthBits <22) gap_iDepthBits = 16; + else if( gap_iDepthBits <28) gap_iDepthBits = 24; + else gap_iDepthBits = 32; + if( gap_iStencilBits<3) gap_iStencilBits = 0; + else if( gap_iStencilBits<7) gap_iStencilBits = 4; + else gap_iStencilBits = 8; + + // set color/depth buffer values + pfd.cColorBits = (dd!=DD_16BIT) ? 32 : 16; + pfd.cDepthBits = gap_iDepthBits; + pfd.cStencilBits = gap_iStencilBits; + + // must be required and works only in full screen via GDI functions + ogl_iTBufferEffect = Clamp( ogl_iTBufferEffect, 0L, 2L); + if( ogl_iTBufferEffect>0 && pixResWidth>0 && pixResHeight>0) + { // lets T-buffer ... :) + //CPrintF( "TBuffer init...\n"); + ogl_iTBufferSamples = (1L) << FastLog2(ogl_iTBufferSamples); + if( ogl_iTBufferSamples<2) ogl_iTBufferSamples = 4; + go_ctSampleBuffers = ogl_iTBufferSamples; + go_iCurrentWriteBuffer = 0; + iPixelFormat = ChoosePixelFormatTB( hdc, &pfd, pixResWidth, pixResHeight); + // need to reset the desktop resolution because CPFTB() resets it + BOOL bSuccess = CDS_SetMode( pixResWidth, pixResHeight, dd); + if( !bSuccess) iPixelFormat = 0; + // check T-buffer support + if( _TBCapability) pglGetIntegerv( GL_SAMPLES_3DFX, (GLint*)&go_ctSampleBuffers); + if( !iPixelFormat) { ogl_iTBufferEffect=0; CPrintF( TRANS("TBuffer initialization failed.\n")); } + else CPrintF( TRANS("TBuffer initialization passed (%d buffers in use).\n"), go_ctSampleBuffers); + } + + // if T-buffer didn't make it, let's try thru regular path + if( !iPixelFormat) { + go_ctSampleBuffers = 0; + go_iCurrentWriteBuffer = 0; + iPixelFormat = pwglChoosePixelFormat( hdc, &pfd); + } + + if( !iPixelFormat) { + WIN_CHECKERROR( 0, "ChoosePixelFormat"); + return FALSE; + } + if( !pwglSetPixelFormat( hdc, iPixelFormat, &pfd)) { + WIN_CHECKERROR( 0, "SetPixelFormat"); + return FALSE; + } + + // test acceleration + memset( &pfd, 0, sizeof(pfd)); + if( !pwglDescribePixelFormat( hdc, iPixelFormat, sizeof(pfd), &pfd)) return FALSE; + BOOL bGenericFormat = pfd.dwFlags & PFD_GENERIC_FORMAT; + BOOL bGenericAccelerated = pfd.dwFlags & PFD_GENERIC_ACCELERATED; + BOOL bHasAcceleration = (bGenericFormat && bGenericAccelerated) || // MCD + (!bGenericFormat && !bGenericAccelerated); // ICD + if( bHasAcceleration) gl_ulFlags |= GLF_HASACCELERATION; + else gl_ulFlags &= ~GLF_HASACCELERATION; + + // done if report pixel format info isn't required + if( !bReport) return TRUE; + + // prepare pixel type description + CTString strPixelType; + if( pfd.iPixelType==PFD_TYPE_RGBA) strPixelType = "TYPE_RGBA"; + else if( pfd.iPixelType&PFD_TYPE_COLORINDEX) strPixelType = "TYPE_COLORINDEX"; + else strPixelType = "unknown"; + // prepare flags description + CTString strFlags = ""; + if( pfd.dwFlags&PFD_DRAW_TO_WINDOW) strFlags += "DRAW_TO_WINDOW "; + if( pfd.dwFlags&PFD_DRAW_TO_BITMAP) strFlags += "DRAW_TO_BITMAP "; + if( pfd.dwFlags&PFD_SUPPORT_GDI) strFlags += "SUPPORT_GDI "; + if( pfd.dwFlags&PFD_SUPPORT_OPENGL) strFlags += "SUPPORT_OPENGL "; + if( pfd.dwFlags&PFD_GENERIC_ACCELERATED) strFlags += "GENERIC_ACCELERATED "; + if( pfd.dwFlags&PFD_GENERIC_FORMAT) strFlags += "GENERIC_FORMAT "; + if( pfd.dwFlags&PFD_NEED_PALETTE) strFlags += "NEED_PALETTE "; + if( pfd.dwFlags&PFD_NEED_SYSTEM_PALETTE) strFlags += "NEED_SYSTEM_PALETTE "; + if( pfd.dwFlags&PFD_DOUBLEBUFFER) strFlags += "DOUBLEBUFFER "; + if( pfd.dwFlags&PFD_STEREO) strFlags += "STEREO "; + if( pfd.dwFlags&PFD_SWAP_LAYER_BUFFERS) strFlags += "SWAP_LAYER_BUFFERS "; + if( pfd.dwFlags&PFD_DEPTH_DONTCARE) strFlags += "DEPTH_DONTCARE "; + if( pfd.dwFlags&PFD_DOUBLEBUFFER_DONTCARE) strFlags += "DOUBLEBUFFER_DONTCARE "; + if( pfd.dwFlags&PFD_STEREO_DONTCARE) strFlags += "STEREO_DONTCARE "; + if( pfd.dwFlags&PFD_SWAP_COPY) strFlags += "SWAP_COPY "; + if( pfd.dwFlags&PFD_SWAP_EXCHANGE) strFlags += "SWAP_EXCHANGE "; + if( strFlags=="") strFlags = "none"; + + // output pixel format description to console (for debugging purposes) + CPrintF( TRANS("\nPixel Format Description:\n")); + CPrintF( TRANS(" Number: %d (%s)\n"), iPixelFormat, strPixelType); + CPrintF( TRANS(" Flags: %s\n"), strFlags); + CPrintF( TRANS(" Color bits: %d (%d:%d:%d:%d)\n"), pfd.cColorBits, + pfd.cRedBits, pfd.cGreenBits, pfd.cBlueBits, pfd.cAlphaBits); + CPrintF( TRANS(" Depth bits: %d (%d for stencil)\n"), pfd.cDepthBits, pfd.cStencilBits); + gl_iCurrentDepth = pfd.cDepthBits; // keep depth bits + + // all done + CPrintF( "\n"); + return TRUE; +} + + +// test if an extension exists +static BOOL HasExtension( const char *strAllExtensions, const char *strExtension) +{ + // find substring + const char *strFound = strstr( strAllExtensions, strExtension); + // no extension if not found + if( strFound==NULL) return FALSE; + INDEX iExtensionLen = strlen(strExtension); + // if found substring is substring of some other extension + if( strFound[iExtensionLen]!=' ' && strFound[iExtensionLen]!=0) { + // continue searching after that char + return HasExtension( strFound+iExtensionLen, strExtension); + } + // extension found + return TRUE; +} + + +// add OpenGL extensions to engine +void CGfxLibrary::AddExtension_OGL( ULONG ulFlag, const char *strName) +{ + gl_ulFlags = (gl_ulFlags & ~ulFlag) | ulFlag; + go_strSupportedExtensions += strName; + go_strSupportedExtensions += " "; +} + + +// determine OpenGL extensions that engine supports +void CGfxLibrary::TestExtension_OGL( ULONG ulFlag, const char *strName) +{ + if( HasExtension( go_strExtensions, strName)) AddExtension_OGL( ulFlag, strName); +} + + +// creates OpenGL drawing context +BOOL CGfxLibrary::CreateContext_OGL(HDC hdc) +{ + if( !SetupPixelFormat_OGL( hdc, TRUE)) return FALSE; + go_hglRC = pwglCreateContext(hdc); + if( go_hglRC==NULL) { + WIN_CHECKERROR(0, "CreateContext"); + return FALSE; + } + if( !pwglMakeCurrent(hdc, go_hglRC)) { + // NOTE: This error is sometimes reported without a reason on 3dfx hardware + // so we just have to ignore it. + //WIN_CHECKERROR(0, "MakeCurrent after CreateContext"); + return FALSE; + } + return TRUE; +} + + + +// prepares OpenGL drawing context +void CGfxLibrary::InitContext_OGL(void) +{ + // must have context + ASSERT( gl_pvpActive!=NULL); + + // reset engine's internal OpenGL state variables + extern BOOL GFX_abTexture[GFX_MAXTEXUNITS]; + for( INDEX iUnit=0; iUnitvp_hWnd); + go_strWinExtensions = (char*)pwglGetExtensionsStringARB(tdc.hdc); + } + + // multitexture is supported only thru GL_EXT_texture_env_combine extension + gl_ctTextureUnits = 1; + gl_ctRealTextureUnits = 1; + pglActiveTextureARB = NULL; + pglClientActiveTextureARB = NULL; + if( HasExtension( go_strExtensions, "GL_ARB_multitexture")) { + pglGetIntegerv( GL_MAX_TEXTURE_UNITS_ARB, (int*)&gl_ctRealTextureUnits); // get number of texture units + if( gl_ctRealTextureUnits>1 && HasExtension( go_strExtensions, "GL_EXT_texture_env_combine")) { + AddExtension_OGL( NONE, "GL_ARB_multitexture"); + AddExtension_OGL( NONE, "GL_EXT_texture_env_combine"); + pglActiveTextureARB = (void (__stdcall*)(GLenum))pwglGetProcAddress( "glActiveTextureARB"); + pglClientActiveTextureARB = (void (__stdcall*)(GLenum))pwglGetProcAddress( "glClientActiveTextureARB"); + ASSERT( pglActiveTextureARB!=NULL && pglClientActiveTextureARB!=NULL); + gl_ctTextureUnits = Min( GFX_MAXTEXUNITS, gl_ctRealTextureUnits); + } else { + CPrintF( TRANS(" GL_TEXTURE_ENV_COMBINE extension missing - multi-texturing cannot be used.\n")); + } + } + + // find all supported texture compression extensions + TestExtension_OGL( GLF_EXTC_ARB, "GL_ARB_texture_compression"); + TestExtension_OGL( GLF_EXTC_S3TC, "GL_EXT_texture_compression_s3tc"); + TestExtension_OGL( GLF_EXTC_FXT1, "GL_3DFX_texture_compression_FXT1"); + TestExtension_OGL( GLF_EXTC_LEGACY, "GL_S3_s3tc"); + // mark if there is at least one extension present + gl_ulFlags &= ~GLF_TEXTURECOMPRESSION; + if( (gl_ulFlags&GLF_EXTC_ARB) || (gl_ulFlags&GLF_EXTC_FXT1) + || (gl_ulFlags&GLF_EXTC_S3TC) || (gl_ulFlags&GLF_EXTC_LEGACY)) { + gl_ulFlags |= GLF_TEXTURECOMPRESSION; + } + + // determine max supported dimension of texture + pglGetIntegerv( GL_MAX_TEXTURE_SIZE, (GLint*)&gl_pixMaxTextureDimension); + OGL_CHECKERROR; + + // determine support for texture LOD biasing + gl_fMaxTextureLODBias = 0.0f; + if( HasExtension( go_strExtensions, "GL_EXT_texture_lod_bias")) { + AddExtension_OGL( NONE, "GL_EXT_texture_lod_bias"); // register + // check max possible lod bias (absolute) + pglGetFloatv( GL_MAX_TEXTURE_LOD_BIAS_EXT, &glfRet); + GLenum gleError = pglGetError(); // just because of invalid extension implementations (S3) + if( gleError || glfRet<0.1f || glfRet>4.0f) glfRet = 4.0f; + gl_fMaxTextureLODBias = glfRet; + OGL_CHECKERROR; + } + + // determine support for anisotropic filtering + gl_iMaxTextureAnisotropy = 1; + if( HasExtension( go_strExtensions, "GL_EXT_texture_filter_anisotropic")) { + AddExtension_OGL( NONE, "GL_EXT_texture_filter_anisotropic"); // register + // keep max allowed anisotropy degree + pglGetIntegerv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &gliRet); + gl_iMaxTextureAnisotropy = gliRet; + OGL_CHECKERROR; + } + + // check support for compiled vertex arrays + pglLockArraysEXT = NULL; + pglUnlockArraysEXT = NULL; + if( HasExtension( go_strExtensions, "GL_EXT_compiled_vertex_array")) { + AddExtension_OGL( GLF_EXT_COMPILEDVERTEXARRAY, "GL_EXT_compiled_vertex_array"); + pglLockArraysEXT = (void (__stdcall*)(GLint,GLsizei))pwglGetProcAddress( "glLockArraysEXT"); + pglUnlockArraysEXT = (void (__stdcall*)(void) )pwglGetProcAddress( "glUnlockArraysEXT"); + ASSERT( pglLockArraysEXT!=NULL && pglUnlockArraysEXT!=NULL); + } + + // check support for swap interval + pwglSwapIntervalEXT = NULL; + pwglGetSwapIntervalEXT = NULL; + if( HasExtension( go_strExtensions, "WGL_EXT_swap_control")) { + AddExtension_OGL( GLF_VSYNC, "WGL_EXT_swap_control"); + pwglSwapIntervalEXT = (GLboolean (__stdcall*)(GLint))pwglGetProcAddress( "wglSwapIntervalEXT"); + pwglGetSwapIntervalEXT = (GLint (__stdcall*)(void) )pwglGetProcAddress( "wglGetSwapIntervalEXT"); + ASSERT( pwglSwapIntervalEXT!=NULL && pwglGetSwapIntervalEXT!=NULL); + } + + // determine support for ATI Truform technology + extern INDEX truform_iLevel; + extern BOOL truform_bLinear; + truform_iLevel = -1; + truform_bLinear = FALSE; + pglPNTrianglesiATI = NULL; + pglPNTrianglesfATI = NULL; + gl_iTessellationLevel = 0; + gl_iMaxTessellationLevel = 0; + if( HasExtension( go_strExtensions, "GL_ATI_pn_triangles")) { + AddExtension_OGL( NONE, "GL_ATI_pn_triangles"); + pglPNTrianglesiATI = (void (__stdcall*)(GLenum,GLint ))pwglGetProcAddress( "glPNTrianglesiATI"); + pglPNTrianglesfATI = (void (__stdcall*)(GLenum,GLfloat))pwglGetProcAddress( "glPNTrianglesfATI"); + ASSERT( pglPNTrianglesiATI!=NULL && pglPNTrianglesfATI!=NULL); + // check max possible tessellation + pglGetIntegerv( GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI, &gliRet); + gl_iMaxTessellationLevel = gliRet; + OGL_CHECKERROR; + } + + // if T-buffer is supported + if( _TBCapability) { + // add extension and disable t-buffer usage by default + AddExtension_OGL( GLF_EXT_TBUFFER, "GL_3DFX_multisample"); + pglDisable( GL_MULTISAMPLE_3DFX); + OGL_CHECKERROR; + } + + // test for clamp to edge + TestExtension_OGL( GLF_EXT_EDGECLAMP, "GL_EXT_texture_edge_clamp"); + + // test for clip volume hint + TestExtension_OGL( GLF_EXT_CLIPHINT, "GL_EXT_clip_volume_hint"); + /* + // test for occlusion culling + TestExtension_OGL( GLF_EXT_OCCLUSIONTEST, "GL_HP_occlusion_test"); + + pglGenOcclusionQueriesNV = NULL; pglDeleteOcclusionQueriesNV = NULL; + pglBeginOcclusionQueryNV = NULL; pglEndOcclusionQueryNV = NULL; + pglGetOcclusionQueryivNV = NULL; pglGetOcclusionQueryuivNV = NULL; + pglIsOcclusionQueryNV = NULL; + + if( HasExtension( go_strExtensions, "GL_NV_occlusion_query")) + { // prepare extension's functions + AddExtension_OGL( GLF_EXT_OCCLUSIONQUERY, "GL_NV_occlusion_query"); + pglGenOcclusionQueriesNV = (void (__stdcall*)(GLsizei, GLuint*))pwglGetProcAddress( "glGenOcclusionQueriesNV"); + pglDeleteOcclusionQueriesNV = (void (__stdcall*)(GLsizei, const GLuint*))pwglGetProcAddress( "glDeleteOcclusionQueriesNV"); + pglBeginOcclusionQueryNV = (void (__stdcall*)(GLuint))pwglGetProcAddress( "glBeginOcclusionQueryNV"); + pglEndOcclusionQueryNV = (void (__stdcall*)(void))pwglGetProcAddress( "glEndOcclusionQueryNV"); + pglGetOcclusionQueryivNV = (void (__stdcall*)(GLuint, GLenum, GLint*))pwglGetProcAddress( "glGetOcclusionQueryivNV"); + pglGetOcclusionQueryuivNV = (void (__stdcall*)(GLuint, GLenum, GLuint*))pwglGetProcAddress( "glGetOcclusionQueryuivNV"); + pglIsOcclusionQueryNV = (GLboolean (__stdcall*)(GLuint))pwglGetProcAddress( "glIsOcclusionQueryNV"); + ASSERT( pglGenOcclusionQueriesNV!=NULL && pglDeleteOcclusionQueriesNV!=NULL + && pglBeginOcclusionQueryNV!=NULL && pglEndOcclusionQueryNV!=NULL + && pglGetOcclusionQueryivNV!=NULL && pglGetOcclusionQueryuivNV!=NULL + && pglIsOcclusionQueryNV!=NULL); + } + */ + // done with seeking for supported extensions + if( go_strSupportedExtensions=="") go_strSupportedExtensions = "none"; + + // allocate vertex buffers + // eglAdjustVertexBuffers(ogl_iVertexBufferSize*1024); + // OGL_CHECKERROR; + + // check if 32-bit textures are supported + GLuint uiTmpTex; + const ULONG ulTmpTex = 0xFFFFFFFF; + pglGenTextures( 1, &uiTmpTex); + pglBindTexture( GL_TEXTURE_2D, uiTmpTex); + pglTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, 1,1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &ulTmpTex); + OGL_CHECKERROR; + gl_ulFlags &= ~GLF_32BITTEXTURES; + pglGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_GREEN_SIZE, &gliRet); + if( gliRet==8) gl_ulFlags |= GLF_32BITTEXTURES; + pglDeleteTextures( 1, &uiTmpTex); + OGL_CHECKERROR; + + // setup fog and haze textures + extern PIX _fog_pixSizeH; + extern PIX _fog_pixSizeL; + extern PIX _haze_pixSize; + pglGenTextures( 1, (GLuint*)&_fog_ulTexture); + pglGenTextures( 1, (GLuint*)&_haze_ulTexture); + _fog_pixSizeH = 0; + _fog_pixSizeL = 0; + _haze_pixSize = 0; + OGL_CHECKERROR; + + // prepare pattern texture + extern CTexParams _tpPattern; + extern ULONG _ulPatternTexture; + extern ULONG _ulLastUploadedPattern; + pglGenTextures( 1, (GLuint*)&_ulPatternTexture); + _ulLastUploadedPattern = 0; + _tpPattern.Clear(); + + // reset texture filtering and array locking + _tpGlobal[0].Clear(); + _tpGlobal[1].Clear(); + _tpGlobal[2].Clear(); + _tpGlobal[3].Clear(); + GFX_ctVertices = 0; + gl_dwVertexShader = NONE; + + // set default texture filtering/biasing + extern INDEX gap_iTextureFiltering; + extern INDEX gap_iTextureAnisotropy; + extern FLOAT gap_fTextureLODBias; + gfxSetTextureFiltering( gap_iTextureFiltering, gap_iTextureAnisotropy); + gfxSetTextureBiasing( gap_fTextureLODBias); + + // mark pretouching and probing + extern BOOL _bNeedPretouch; + _bNeedPretouch = TRUE; + gl_bAllowProbing = FALSE; + + // update console system vars + extern void UpdateGfxSysCVars(void); + UpdateGfxSysCVars(); + + // reload all loaded textures and eventually shadows + extern INDEX shd_bCacheAll; + extern void ReloadTextures(void); + extern void CacheShadows(void); + ReloadTextures(); + if( shd_bCacheAll) CacheShadows(); +} + + +// initialize OpenGL driver +BOOL CGfxLibrary::InitDriver_OGL( BOOL b3Dfx/*=FALSE*/) +{ + ASSERT( gl_hiDriver==NONE); + UINT iOldErrorMode = SetErrorMode( SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); + CTString strDriverFileName = b3Dfx ? "3DFXVGL.DLL" : "OPENGL32.DLL"; + + try + { // if driver doesn't exists on disk + char strBuffer[_MAX_PATH+1]; + char *strDummy; + int iRes = SearchPathA( NULL, strDriverFileName, NULL, _MAX_PATH, strBuffer, &strDummy); + if( iRes==0) ThrowF_t(TRANS("OpenGL driver '%s' not present"), strDriverFileName); + + // load opengl library + gl_hiDriver = ::LoadLibraryA( strDriverFileName); + // if it cannot be loaded (although it is present on disk) + if( gl_hiDriver==NONE) { + // if it is 3dfx stand-alone driver + if( b3Dfx) { + // do a fatal error and inform user to deinstall it, + // since this loading attempt probably messed up the entire system + FatalError(TRANS( "3Dfx OpenGL driver '%s' is installed, but cannot be loaded!\n" + "If you previously had a 3Dfx card and it was removed,\n" + "please deinstall the driver and restart windows before\n" + "continuing.\n"), strDriverFileName); + } // fail! + ThrowF_t(TRANS("Cannot load OpenGL driver '%s'"), strDriverFileName); + } + // prepare functions + OGL_SetFunctionPointers_t(gl_hiDriver); + } + catch( char *strError) + { // didn't make it :( + if( gl_hiDriver!=NONE) FreeLibrary(gl_hiDriver); + gl_hiDriver = NONE; + CPrintF( TRANS("Error starting OpenGL: %s\n"), strError); + SetErrorMode(iOldErrorMode); + return FALSE; + } + + // revert to old error mode + SetErrorMode(iOldErrorMode); + + // if default driver + if( !b3Dfx) { + // use GDI functions + pwglSwapBuffers = ::SwapBuffers; + pwglSetPixelFormat = ::SetPixelFormat; + pwglChoosePixelFormat = ::ChoosePixelFormat; + // NOTE: + // some ICD implementations are not infact in OPENGL32.DLL, but in some + // other installed DLL, which is loaded when original OPENGL32.DLL from MS is + // loaded. For those, we in fact load OPENGL32.DLL from MS, so we must _not_ + // call these functions directly, because they are in MS dll. We must call + // functions from GDI, which in turn call either OPENGL32.DLL, _or_ the client driver, + // as appropriate. + } + // done + return TRUE; +} + + +// shutdown OpenGL driver +void CGfxLibrary::EndDriver_OGL(void) +{ + // unbind all textures + if( _pTextureStock!=NULL) { + {FOREACHINDYNAMICCONTAINER( _pTextureStock->st_ctObjects, CTextureData, ittd) { + CTextureData &td = *ittd; + td.td_tpLocal.Clear(); + td.Unbind(); + }} + } + // unbind fog, haze and flat texture + gfxDeleteTexture( _fog_ulTexture); + gfxDeleteTexture( _haze_ulTexture); + ASSERT( _ptdFlat!=NULL); + _ptdFlat->td_tpLocal.Clear(); + _ptdFlat->Unbind(); + + // shut the driver down + if( go_hglRC!=NULL) { + if( pwglMakeCurrent!=NULL) { + BOOL bRes = pwglMakeCurrent(NULL, NULL); + WIN_CHECKERROR( bRes, "MakeCurrent(NULL, NULL)"); + } + ASSERT( pwglDeleteContext!=NULL); + BOOL bRes = pwglDeleteContext(go_hglRC); + WIN_CHECKERROR( bRes, "DeleteContext"); + go_hglRC = NULL; + } + OGL_ClearFunctionPointers(); +} + + + +// prepare current viewport for rendering thru OpenGL +BOOL CGfxLibrary::SetCurrentViewport_OGL(CViewPort *pvp) +{ + // if must init entire opengl + if( gl_ulFlags & GLF_INITONNEXTWINDOW) + { + gl_ulFlags &= ~GLF_INITONNEXTWINDOW; + // reopen window + pvp->CloseCanvas(); + pvp->OpenCanvas(); + // init now + CTempDC tdc(pvp->vp_hWnd); + if( !CreateContext_OGL(tdc.hdc)) return FALSE; + gl_pvpActive = pvp; // remember as current viewport (must do that BEFORE InitContext) + InitContext_OGL(); + pvp->vp_ctDisplayChanges = gl_ctDriverChanges; + return TRUE; + } + + // if window was not set for this driver + if( pvp->vp_ctDisplayChangesCloseCanvas(); + pvp->OpenCanvas(); + // set it + CTempDC tdc(pvp->vp_hWnd); + if( !SetupPixelFormat_OGL(tdc.hdc)) return FALSE; + pvp->vp_ctDisplayChanges = gl_ctDriverChanges; + } + + if( gl_pvpActive!=NULL) { + // fail, if only one window is allowed (3dfx driver), already initialized and trying to set non-primary viewport + const BOOL bOneWindow = (gl_gaAPI[GAT_OGL].ga_adaAdapter[gl_iCurrentAdapter].da_ulFlags & DAF_ONEWINDOW); + if( bOneWindow && gl_pvpActive->vp_hWnd!=NULL && gl_pvpActive->vp_hWnd!=pvp->vp_hWnd) return FALSE; + // no need to set context if it is the same window as last time + if( gl_pvpActive->vp_hWnd==pvp->vp_hWnd) return TRUE; + } + + // try to set context to this window + pwglMakeCurrent( NULL, NULL); + CTempDC tdc(pvp->vp_hWnd); + // fail, if cannot set context to this window + if( !pwglMakeCurrent( tdc.hdc, go_hglRC)) return FALSE; + + // remember as current window + gl_pvpActive = pvp; + return TRUE; +} + + + +/* + * 3dfx t-buffer control + */ + + +extern void SetTBufferEffect( BOOL bEnable) +{ + // adjust console vars + ogl_iTBufferEffect = Clamp( ogl_iTBufferEffect, 0L, 2L); + ogl_iTBufferSamples = (1L) << FastLog2(ogl_iTBufferSamples); + if( ogl_iTBufferSamples<2) ogl_iTBufferSamples = 4; + // if supported + if( _pGfx->gl_ulFlags&GLF_EXT_TBUFFER) + { // disable multisampling if not required + ASSERT( pglTBufferMask3DFX!=NULL); + if( ogl_iTBufferEffect==0 || _pGfx->go_ctSampleBuffers<2 || !bEnable) pglDisable( GL_MULTISAMPLE_3DFX); + else { + pglEnable( GL_MULTISAMPLE_3DFX); + UINT uiMask = 0xFFFFFFFF; + // set one buffer in case of motion-blur + if( ogl_iTBufferEffect==2) uiMask = (1UL) << _pGfx->go_iCurrentWriteBuffer; + //pglTBufferMask3DFX(uiMask); + } + } +} diff --git a/Sources/Engine/Graphics/Gfx_OpenGL_Textures.cpp b/Sources/Engine/Graphics/Gfx_OpenGL_Textures.cpp new file mode 100644 index 0000000..b22d2ee --- /dev/null +++ b/Sources/Engine/Graphics/Gfx_OpenGL_Textures.cpp @@ -0,0 +1,256 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include + +#include + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + + +// we need array for OpenGL mipmaps that are lower than N*1 or 1*N +static ULONG _aulLastMipmaps[(INDEX)(1024*1.334)]; +static CTexParams *_tpCurrent; +extern INDEX GFX_iActiveTexUnit; + +// unpacks texture filering from one INDEX to two GLenums (and eventually re-adjust input INDEX) +static void UnpackFilter_OGL( INDEX iFilter, GLenum &eMagFilter, GLenum &eMinFilter) +{ + switch( iFilter) { + case 110: case 10: eMagFilter=GL_NEAREST; eMinFilter=GL_NEAREST; break; + case 111: case 11: eMagFilter=GL_NEAREST; eMinFilter=GL_NEAREST_MIPMAP_NEAREST; break; + case 112: case 12: eMagFilter=GL_NEAREST; eMinFilter=GL_NEAREST_MIPMAP_LINEAR; break; + case 220: case 20: eMagFilter=GL_LINEAR; eMinFilter=GL_LINEAR; break; + case 221: case 21: eMagFilter=GL_LINEAR; eMinFilter=GL_LINEAR_MIPMAP_NEAREST; break; + case 222: case 22: eMagFilter=GL_LINEAR; eMinFilter=GL_LINEAR_MIPMAP_LINEAR; break; + case 120: eMagFilter=GL_NEAREST; eMinFilter=GL_LINEAR; break; + case 121: eMagFilter=GL_NEAREST; eMinFilter=GL_LINEAR_MIPMAP_NEAREST; break; + case 122: eMagFilter=GL_NEAREST; eMinFilter=GL_LINEAR_MIPMAP_LINEAR; break; + case 210: eMagFilter=GL_LINEAR; eMinFilter=GL_NEAREST; break; + case 211: eMagFilter=GL_LINEAR; eMinFilter=GL_NEAREST_MIPMAP_NEAREST; break; + case 212: eMagFilter=GL_LINEAR; eMinFilter=GL_NEAREST_MIPMAP_LINEAR; break; + default: ASSERTALWAYS( "Illegal OpenGL texture filtering mode."); break; + } +} + + +// change texture filtering mode if needed +extern void MimicTexParams_OGL( CTexParams &tpLocal) +{ + ASSERT( &tpLocal!=NULL); + _pfGfxProfile.StartTimer( CGfxProfile::PTI_TEXTUREPARAMS); + + // set texture filtering mode if required + if( tpLocal.tp_iFilter != _tpGlobal[0].tp_iFilter) + { // update OpenGL texture filters + GLenum eMagFilter, eMinFilter; + UnpackFilter_OGL( _tpGlobal[0].tp_iFilter, eMagFilter, eMinFilter); + // adjust minimize filter in case of a single mipmap + if( tpLocal.tp_bSingleMipmap) { + if( eMinFilter==GL_NEAREST_MIPMAP_NEAREST || eMinFilter==GL_NEAREST_MIPMAP_LINEAR) eMinFilter = GL_NEAREST; + else if( eMinFilter==GL_LINEAR_MIPMAP_NEAREST || eMinFilter==GL_LINEAR_MIPMAP_LINEAR) eMinFilter = GL_LINEAR; + } + // update texture filter + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, eMagFilter); + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, eMinFilter); + tpLocal.tp_iFilter = _tpGlobal[0].tp_iFilter; + OGL_CHECKERROR; + } + + // set texture anisotropy degree if required and supported + if( tpLocal.tp_iAnisotropy != _tpGlobal[0].tp_iAnisotropy) { + tpLocal.tp_iAnisotropy = _tpGlobal[0].tp_iAnisotropy; + if( _pGfx->gl_iMaxTextureAnisotropy>=2) { // only if allowed + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, tpLocal.tp_iAnisotropy); + } + } + + // set texture clamping modes if changed + if( tpLocal.tp_eWrapU!=_tpGlobal[GFX_iActiveTexUnit].tp_eWrapU + || tpLocal.tp_eWrapV!=_tpGlobal[GFX_iActiveTexUnit].tp_eWrapV) + { // prepare temp vars + GLuint eWrapU = _tpGlobal[GFX_iActiveTexUnit].tp_eWrapU==GFX_REPEAT ? GL_REPEAT : GL_CLAMP; + GLuint eWrapV = _tpGlobal[GFX_iActiveTexUnit].tp_eWrapV==GFX_REPEAT ? GL_REPEAT : GL_CLAMP; + // eventually re-adjust clamping params in case of clamp_to_edge extension + if( _pGfx->gl_ulFlags&GLF_EXT_EDGECLAMP) { + if( eWrapU == GL_CLAMP) eWrapU = GL_CLAMP_TO_EDGE; + if( eWrapV == GL_CLAMP) eWrapV = GL_CLAMP_TO_EDGE; + } + // set clamping params and update local texture clamping modes + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, eWrapU); + pglTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, eWrapV); + tpLocal.tp_eWrapU = _tpGlobal[GFX_iActiveTexUnit].tp_eWrapU; + tpLocal.tp_eWrapV = _tpGlobal[GFX_iActiveTexUnit].tp_eWrapV; + OGL_CHECKERROR; + } + + // keep last texture params (for tex upload and stuff) + _tpCurrent = &tpLocal; + _pfGfxProfile.StopTimer( CGfxProfile::PTI_TEXTUREPARAMS); +} + + + +// upload context for current texture to accelerator's memory +// (returns format in which texture was really uploaded) +extern void UploadTexture_OGL( ULONG *pulTexture, PIX pixSizeU, PIX pixSizeV, + GLenum eInternalFormat, BOOL bUseSubImage) +{ + // safeties + ASSERT( pulTexture!=NULL); + ASSERT( pixSizeU>0 && pixSizeV>0); + _sfStats.StartTimer( CStatForm::STI_BINDTEXTURE); + _pfGfxProfile.StartTimer( CGfxProfile::PTI_TEXTUREUPLOADING); + + // upload each original mip-map + INDEX iMip=0; + PIX pixOffset=0; + while( pixSizeU>0 && pixSizeV>0) + { + // check that memory is readable + ASSERT( pulTexture[pixOffset +pixSizeU*pixSizeV -1] != 0xDEADBEEF); + // upload mipmap as fast as possible + if( bUseSubImage) { + pglTexSubImage2D( GL_TEXTURE_2D, iMip, 0, 0, pixSizeU, pixSizeV, + GL_RGBA, GL_UNSIGNED_BYTE, pulTexture+pixOffset); + } else { + pglTexImage2D( GL_TEXTURE_2D, iMip, eInternalFormat, pixSizeU, pixSizeV, 0, + GL_RGBA, GL_UNSIGNED_BYTE, pulTexture+pixOffset); + } OGL_CHECKERROR; + // advance to next mip-map + pixOffset += pixSizeU*pixSizeV; + pixSizeU >>=1; + pixSizeV >>=1; + iMip++; + // end here if there is only one mip-map to upload + if( _tpCurrent->tp_bSingleMipmap) break; + } + + // see if we need to generate and upload additional mipmaps (those under 1*N or N*1) + if( !_tpCurrent->tp_bSingleMipmap && pixSizeU!=pixSizeV) + { // prepare variables + PIX pixSize = Max(pixSizeU,pixSizeV); + ASSERT( pixSize<=2048); + ULONG *pulSrc = pulTexture+pixOffset-pixSize*2; + ULONG *pulDst = _aulLastMipmaps; + // loop thru mipmaps + while( pixSizeU>0 || pixSizeV>0) + { // make next mipmap + if( pixSizeU==0) pixSizeU=1; + if( pixSizeV==0) pixSizeV=1; + pixSize = pixSizeU*pixSizeV; + __asm { + pxor mm0,mm0 + mov esi,D [pulSrc] + mov edi,D [pulDst] + mov ecx,D [pixSize] + pixLoop: + movd mm1,D [esi+0] + movd mm2,D [esi+4] + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + paddw mm1,mm2 + psrlw mm1,1 + packuswb mm1,mm0 + movd D [edi],mm1 + add esi,4*2 + add edi,4 + dec ecx + jnz pixLoop + emms + } + // upload mipmap + if( bUseSubImage) { + pglTexSubImage2D( GL_TEXTURE_2D, iMip, 0, 0, pixSizeU, pixSizeV, + GL_RGBA, GL_UNSIGNED_BYTE, pulDst); + } else { + pglTexImage2D( GL_TEXTURE_2D, iMip, eInternalFormat, pixSizeU, pixSizeV, 0, + GL_RGBA, GL_UNSIGNED_BYTE, pulDst); + } OGL_CHECKERROR; + // advance to next mip-map + pulSrc = pulDst; + pulDst += pixSize; + pixOffset += pixSize; + pixSizeU >>=1; + pixSizeV >>=1; + iMip++; + } + } + + // all done + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_TEXTUREUPLOADS, 1); + _pfGfxProfile.IncrementCounter( CGfxProfile::PCI_TEXTUREUPLOADBYTES, pixOffset*4); + _sfStats.IncrementCounter( CStatForm::SCI_TEXTUREUPLOADS, 1); + _sfStats.IncrementCounter( CStatForm::SCI_TEXTUREUPLOADBYTES, pixOffset*4); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_TEXTUREUPLOADING); + _sfStats.StopTimer( CStatForm::STI_BINDTEXTURE); +} + + + +// returns bytes/pixels ratio for uploaded texture +extern INDEX GetFormatPixRatio_OGL( GLenum eFormat) +{ + switch( eFormat) { + case GL_RGBA: + case GL_RGBA8: + return 4; + case GL_RGB: + case GL_RGB8: + return 3; + case GL_RGB5: + case GL_RGB5_A1: + case GL_RGB4: + case GL_RGBA4: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE8_ALPHA8: + return 2; + // compressed formats and single-channel formats + default: + return 1; + } +} + + +// returns bytes/pixels ratio for uploaded texture +extern INDEX GetTexturePixRatio_OGL( GLuint uiBindNo) +{ + GLenum eInternalFormat; + pglBindTexture( GL_TEXTURE_2D, uiBindNo); + pglGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, (GLint*)&eInternalFormat); + OGL_CHECKERROR; + return GetFormatPixRatio_OGL( eInternalFormat); +} + + +// return allowed dithering method +extern INDEX AdjustDitheringType_OGL( GLenum eFormat, INDEX iDitheringType) +{ + switch( eFormat) { + // these formats don't need dithering + case GL_RGB8: + case GL_RGBA8: + case GL_LUMINANCE8: + case GL_LUMINANCE8_ALPHA8: + return NONE; + // these formats need reduced dithering + case GL_RGB5: + case GL_RGB5_A1: + if( iDitheringType>7) return iDitheringType-3; + // other formats need dithering as it is + default: + return iDitheringType; + } +} diff --git a/Sources/Engine/Graphics/Gfx_wrapper.cpp b/Sources/Engine/Graphics/Gfx_wrapper.cpp new file mode 100644 index 0000000..0cd6cfa --- /dev/null +++ b/Sources/Engine/Graphics/Gfx_wrapper.cpp @@ -0,0 +1,872 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +#include +#include + +//#include +//#pragma comment(lib, "d3dx8.lib") + + +//#include +//#pragma comment(lib, "d3dx8.lib") +//extern "C" HRESULT WINAPI D3DXGetErrorStringA( HRESULT hr, LPSTR pBuffer, UINT BufferLen); +//char acErrorString[256]; +//D3DXGetErrorString( hr, acErrorString, 255); +//ASSERTALWAYS( acErrorString); + +extern INDEX gap_bOptimizeStateChanges; +extern INDEX gap_iOptimizeClipping; +extern INDEX gap_iDithering; + + +// cached states +extern BOOL GFX_bDepthTest = FALSE; +extern BOOL GFX_bDepthWrite = FALSE; +extern BOOL GFX_bAlphaTest = FALSE; +extern BOOL GFX_bDithering = TRUE; +extern BOOL GFX_bBlending = TRUE; +extern BOOL GFX_bClipping = TRUE; +extern BOOL GFX_bClipPlane = FALSE; +extern BOOL GFX_bColorArray = FALSE; +extern BOOL GFX_bTruform = FALSE; +extern BOOL GFX_bFrontFace = TRUE; +extern BOOL GFX_bViewMatrix = TRUE; +extern INDEX GFX_iActiveTexUnit = 0; +extern FLOAT GFX_fMinDepthRange = 0.0f; +extern FLOAT GFX_fMaxDepthRange = 0.0f; + +extern GfxBlend GFX_eBlendSrc = GFX_ONE; +extern GfxBlend GFX_eBlendDst = GFX_ZERO; +extern GfxComp GFX_eDepthFunc = GFX_LESS_EQUAL; +extern GfxFace GFX_eCullFace = GFX_NONE; +extern BOOL GFX_abTexture[GFX_MAXTEXUNITS] = { FALSE, FALSE, FALSE, FALSE }; +extern INDEX GFX_iTexModulation[GFX_MAXTEXUNITS] = { 0, 0, 0, 0 }; + +// last ortho/frustum values (frustum has negative sign, because of orgho-frustum switching!) +extern FLOAT GFX_fLastL = 0; +extern FLOAT GFX_fLastR = 0; +extern FLOAT GFX_fLastT = 0; +extern FLOAT GFX_fLastB = 0; +extern FLOAT GFX_fLastN = 0; +extern FLOAT GFX_fLastF = 0; + +// number of vertices currently in buffer +extern INDEX GFX_ctVertices = 0; + +// for D3D: mark need for clipping (when wants to be disable but cannot be because of user clip plane) +static BOOL _bWantsClipping = TRUE; +// current color mask (for Get... function) +static ULONG _ulCurrentColorMask = (CT_RMASK|CT_GMASK|CT_BMASK|CT_AMASK); +// locking state for OGL +static BOOL _bCVAReallyLocked = FALSE; + +// clip plane and last view matrix for D3D +extern FLOAT D3D_afClipPlane[4] = {0,0,0,0}; +extern FLOAT D3D_afViewMatrix[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0}; +static FLOAT _afActiveClipPlane[4] = {0,0,0,0}; + +// Truform/N-Patches +extern INDEX truform_iLevel = -1; +extern BOOL truform_bLinear = FALSE; + + +// functions' pointers +extern void (*gfxEnableDepthWrite)(void) = NULL; +extern void (*gfxEnableDepthBias)(void) = NULL; +extern void (*gfxEnableDepthTest)(void) = NULL; +extern void (*gfxEnableAlphaTest)(void) = NULL; +extern void (*gfxEnableBlend)(void) = NULL; +extern void (*gfxEnableDither)(void) = NULL; +extern void (*gfxEnableTexture)(void) = NULL; +extern void (*gfxEnableClipping)(void) = NULL; +extern void (*gfxEnableClipPlane)(void) = NULL; +extern void (*gfxDisableDepthWrite)(void) = NULL; +extern void (*gfxDisableDepthBias)(void) = NULL; +extern void (*gfxDisableDepthTest)(void) = NULL; +extern void (*gfxDisableAlphaTest)(void) = NULL; +extern void (*gfxDisableBlend)(void) = NULL; +extern void (*gfxDisableDither)(void) = NULL; +extern void (*gfxDisableTexture)(void) = NULL; +extern void (*gfxDisableClipping)(void) = NULL; +extern void (*gfxDisableClipPlane)(void) = NULL; +extern void (*gfxBlendFunc)( GfxBlend eSrc, GfxBlend eDst) = NULL; +extern void (*gfxDepthFunc)( GfxComp eFunc) = NULL; +extern void (*gfxDepthRange)( FLOAT fMin, FLOAT fMax) = NULL; +extern void (*gfxCullFace)( GfxFace eFace) = NULL; +extern void (*gfxFrontFace)( GfxFace eFace) = NULL; +extern void (*gfxClipPlane)( const DOUBLE *pdPlane) = NULL; +extern void (*gfxSetOrtho)( const FLOAT fLeft, const FLOAT fRight, const FLOAT fTop, const FLOAT fBottom, const FLOAT fNear, const FLOAT fFar, const BOOL bSubPixelAdjust) = NULL; +extern void (*gfxSetFrustum)( const FLOAT fLeft, const FLOAT fRight, const FLOAT fTop, const FLOAT fBottom, const FLOAT fNear, const FLOAT fFar) = NULL; +extern void (*gfxSetTextureMatrix)( const FLOAT *pfMatrix) = NULL; +extern void (*gfxSetViewMatrix)( const FLOAT *pfMatrix) = NULL; +extern void (*gfxPolygonMode)( GfxPolyMode ePolyMode) = NULL; +extern void (*gfxSetTextureWrapping)( enum GfxWrap eWrapU, enum GfxWrap eWrapV) = NULL; +extern void (*gfxSetTextureModulation)( INDEX iScale) = NULL; +extern void (*gfxGenerateTexture)( ULONG &ulTexObject) = NULL; +extern void (*gfxDeleteTexture)( ULONG &ulTexObject) = NULL; +extern void (*gfxSetVertexArray)( GFXVertex4 *pvtx, INDEX ctVtx) = NULL; +extern void (*gfxSetNormalArray)( GFXNormal *pnor) = NULL; +extern void (*gfxSetTexCoordArray)( GFXTexCoord *ptex, BOOL b4) = NULL; +extern void (*gfxSetColorArray)( GFXColor *pcol) = NULL; +extern void (*gfxDrawElements)( INDEX ctElem, INDEX *pidx) = NULL; +extern void (*gfxSetConstantColor)(COLOR col) = NULL; +extern void (*gfxEnableColorArray)(void) = NULL; +extern void (*gfxDisableColorArray)(void) = NULL; +extern void (*gfxFinish)(void) = NULL; +extern void (*gfxLockArrays)(void) = NULL; +extern void (*gfxEnableTruform)( void) = NULL; +extern void (*gfxDisableTruform)(void) = NULL; +extern void (*gfxSetColorMask)( ULONG ulColorMask) = NULL; + + + +// dummy function (one size fits all:) +static void none_void(void) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_NONE); +} + + +// error checkers (this is for debug version only) + +extern void OGL_CheckError(void) +{ +#ifndef NDEBUG + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; + if( eAPI==GAT_OGL) ASSERT( pglGetError()==GL_NO_ERROR); + else ASSERT( eAPI==GAT_NONE); +#endif +} + +#ifdef SE1_D3D +extern void D3D_CheckError(HRESULT hr) +{ +#ifndef NDEBUG + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; + if( eAPI==GAT_D3D) ASSERT( hr==D3D_OK); + else ASSERT( eAPI==GAT_NONE); +#endif +} +#endif // SE1_D3D + + +// TEXTURE MANAGEMENT +#ifdef SE1_D3D +static LPDIRECT3DTEXTURE8 *_ppd3dCurrentTexture; +#endif // SE1_D3D + +extern INDEX GetTexturePixRatio_OGL( GLuint uiBindNo); +extern INDEX GetFormatPixRatio_OGL( GLenum eFormat); +extern void MimicTexParams_OGL( CTexParams &tpLocal); +extern void UploadTexture_OGL( ULONG *pulTexture, PIX pixSizeU, PIX pixSizeV, + GLenum eInternalFormat, BOOL bUseSubImage); + +#ifdef SE1_D3D +extern INDEX GetTexturePixRatio_D3D( LPDIRECT3DTEXTURE8 pd3dTexture); +extern INDEX GetFormatPixRatio_D3D( D3DFORMAT d3dFormat); +extern void MimicTexParams_D3D( CTexParams &tpLocal); +extern void UploadTexture_D3D( LPDIRECT3DTEXTURE8 *ppd3dTexture, ULONG *pulTexture, + PIX pixSizeU, PIX pixSizeV, D3DFORMAT eInternalFormat, BOOL bDiscard); +#endif // SE1_D3D + +// update texture LOD bias +extern FLOAT _fCurrentLODBias = 0; // LOD bias adjuster +extern void UpdateLODBias( const FLOAT fLODBias) +{ + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_D3D || eAPI==GAT_NONE); +#else // SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_NONE); +#endif // SE1_D3D + // only if supported and needed + if( _fCurrentLODBias==fLODBias && _pGfx->gl_fMaxTextureLODBias==0) return; + _fCurrentLODBias = fLODBias; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // OpenGL + if( eAPI==GAT_OGL) + { // if no multitexturing + if( _pGfx->gl_ctTextureUnits<2) { + pglTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, fLODBias); + OGL_CHECKERROR; + } + // if multitexturing is active + else { + for( INDEX iUnit=0; iUnit<_pGfx->gl_ctTextureUnits; iUnit++) { // loop thru units + pglActiveTexture(iUnit); // select the unit + pglTexEnvf( GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, fLODBias); + OGL_CHECKERROR; + } // reselect the original unit + pglActiveTexture(GFX_iActiveTexUnit); + OGL_CHECKERROR; + } + } + // Direct3D +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) + { // just set it + HRESULT hr; + for( INDEX iUnit=0; iUnit<_pGfx->gl_ctTextureUnits; iUnit++) { // loop thru tex units + hr = _pGfx->gl_pd3dDevice->SetTextureStageState( iUnit, D3DTSS_MIPMAPLODBIAS, *((DWORD*)&fLODBias)); + D3D_CHECKERROR(hr); + } + } +#endif // SE1_D3D + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// get current texture filtering mode +extern void gfxGetTextureFiltering( INDEX &iFilterType, INDEX &iAnisotropyDegree) +{ + iFilterType = _tpGlobal[0].tp_iFilter; + iAnisotropyDegree = _tpGlobal[0].tp_iAnisotropy; +} + + +// set texture filtering mode +extern void gfxSetTextureFiltering( INDEX &iFilterType, INDEX &iAnisotropyDegree) +{ + // clamp vars + INDEX iMagTex = iFilterType /100; iMagTex = Clamp( iMagTex, 0L, 2L); // 0=same as iMinTex, 1=nearest, 2=linear + INDEX iMinTex = iFilterType /10 %10; iMinTex = Clamp( iMinTex, 1L, 2L); // 1=nearest, 2=linear + INDEX iMinMip = iFilterType %10; iMinMip = Clamp( iMinMip, 0L, 2L); // 0=no mipmapping, 1=nearest, 2=linear + iFilterType = iMagTex*100 + iMinTex*10 + iMinMip; + iAnisotropyDegree = Clamp( iAnisotropyDegree, 1L, _pGfx->gl_iMaxTextureAnisotropy); + + // skip if not changed + if( _tpGlobal[0].tp_iFilter==iFilterType && _tpGlobal[0].tp_iAnisotropy==iAnisotropyDegree) return; + _tpGlobal[0].tp_iFilter = iFilterType; + _tpGlobal[0].tp_iAnisotropy = iAnisotropyDegree; + + // for OpenGL, that's about it +#ifdef SE1_D3D + if( _pGfx->gl_eCurrentAPI!=GAT_D3D) return; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // for D3D, it's a stage state (not texture state), so change it! + HRESULT hr; + _D3DTEXTUREFILTERTYPE eMagFilter, eMinFilter, eMipFilter; + const LPDIRECT3DDEVICE8 pd3dDev = _pGfx->gl_pd3dDevice; + extern void UnpackFilter_D3D( INDEX iFilter, _D3DTEXTUREFILTERTYPE &eMagFilter, + _D3DTEXTUREFILTERTYPE &eMinFilter, _D3DTEXTUREFILTERTYPE &eMipFilter); + UnpackFilter_D3D( iFilterType, eMagFilter, eMinFilter, eMipFilter); + if( iAnisotropyDegree>1) { // adjust filter for anisotropy + eMagFilter = D3DTEXF_ANISOTROPIC; + eMinFilter = D3DTEXF_ANISOTROPIC; + } + // set filtering and anisotropy degree + for( INDEX iUnit=0; iUnit<_pGfx->gl_ctTextureUnits; iUnit++) { // must loop thru all usable texture units + hr = pd3dDev->SetTextureStageState( iUnit, D3DTSS_MAXANISOTROPY, iAnisotropyDegree); D3D_CHECKERROR(hr); + hr = pd3dDev->SetTextureStageState( iUnit, D3DTSS_MAGFILTER, eMagFilter); D3D_CHECKERROR(hr); + hr = pd3dDev->SetTextureStageState( iUnit, D3DTSS_MINFILTER, eMinFilter); D3D_CHECKERROR(hr); + hr = pd3dDev->SetTextureStageState( iUnit, D3DTSS_MIPFILTER, eMipFilter); D3D_CHECKERROR(hr); + } + // done + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +#endif // SE1_D3D +} + + +// set new texture LOD biasing +extern void gfxSetTextureBiasing( FLOAT &fLODBias) +{ + // adjust LOD biasing if needed + fLODBias = Clamp( fLODBias, -_pGfx->gl_fMaxTextureLODBias, +_pGfx->gl_fMaxTextureLODBias); + if( _pGfx->gl_fTextureLODBias != fLODBias) { + _pGfx->gl_fTextureLODBias = fLODBias; + UpdateLODBias( fLODBias); + } +} + + + +// set texture unit as active +extern void gfxSetTextureUnit( INDEX iUnit) +{ + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_D3D || eAPI==GAT_NONE); +#else // SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_NONE); +#endif // SE1_D3D + ASSERT( iUnit>=0 && iUnit<4); // supports 4 layers (for now) + + // check consistency +#ifndef NDEBUG + if( eAPI==GAT_OGL) { + GLint gliRet; + pglGetIntegerv( GL_ACTIVE_TEXTURE_ARB, &gliRet); + ASSERT( GFX_iActiveTexUnit==(gliRet-GL_TEXTURE0_ARB)); + pglGetIntegerv( GL_CLIENT_ACTIVE_TEXTURE_ARB, &gliRet); + ASSERT( GFX_iActiveTexUnit==(gliRet-GL_TEXTURE0_ARB)); + } +#endif + + // cached? + if( GFX_iActiveTexUnit==iUnit) return; + GFX_iActiveTexUnit = iUnit; + + // really set only for OpenGL + if( eAPI!=GAT_OGL) return; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + pglActiveTexture(iUnit); + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// set texture as current +extern void gfxSetTexture( ULONG &ulTexObject, CTexParams &tpLocal) +{ + // clamp texture filtering if needed + static INDEX _iLastTextureFiltering = 0; + if( _iLastTextureFiltering != _tpGlobal[0].tp_iFilter) { + INDEX iMagTex = _tpGlobal[0].tp_iFilter /100; iMagTex = Clamp( iMagTex, 0L, 2L); // 0=same as iMinTex, 1=nearest, 2=linear + INDEX iMinTex = _tpGlobal[0].tp_iFilter /10 %10; iMinTex = Clamp( iMinTex, 1L, 2L); // 1=nearest, 2=linear + INDEX iMinMip = _tpGlobal[0].tp_iFilter %10; iMinMip = Clamp( iMinMip, 0L, 2L); // 0=no mipmapping, 1=nearest, 2=linear + _tpGlobal[0].tp_iFilter = iMagTex*100 + iMinTex*10 + iMinMip; + _iLastTextureFiltering = _tpGlobal[0].tp_iFilter; + } + + // determine API and enable texturing + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + gfxEnableTexture(); + + _sfStats.StartTimer(CStatForm::STI_BINDTEXTURE); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + _pfGfxProfile.StartTimer(CGfxProfile::PTI_SETCURRENTTEXTURE); + _pfGfxProfile.IncrementTimerAveragingCounter(CGfxProfile::PTI_SETCURRENTTEXTURE); + + if( eAPI==GAT_OGL) { // OpenGL + pglBindTexture( GL_TEXTURE_2D, ulTexObject); + MimicTexParams_OGL(tpLocal); + } +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) { // Direct3D + _ppd3dCurrentTexture = (LPDIRECT3DTEXTURE8*)&ulTexObject; + HRESULT hr = _pGfx->gl_pd3dDevice->SetTexture( GFX_iActiveTexUnit, *_ppd3dCurrentTexture); + D3D_CHECKERROR(hr); + MimicTexParams_D3D(tpLocal); + } +#endif // SE1_D3D + // done + _pfGfxProfile.StopTimer(CGfxProfile::PTI_SETCURRENTTEXTURE); + _sfStats.StopTimer(CStatForm::STI_BINDTEXTURE); + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// upload texture +extern void gfxUploadTexture( ULONG *pulTexture, PIX pixWidth, PIX pixHeight, ULONG ulFormat, BOOL bNoDiscard) +{ + // determine API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + if( eAPI==GAT_OGL) { // OpenGL + UploadTexture_OGL( pulTexture, pixWidth, pixHeight, (GLenum)ulFormat, bNoDiscard); + } +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) { // Direct3D + const LPDIRECT3DTEXTURE8 _pd3dLastTexture = *_ppd3dCurrentTexture; + UploadTexture_D3D( _ppd3dCurrentTexture, pulTexture, pixWidth, pixHeight, (D3DFORMAT)ulFormat, !bNoDiscard); + // in case that texture has been changed, must re-set it as current + if( _pd3dLastTexture != *_ppd3dCurrentTexture) { + HRESULT hr = _pGfx->gl_pd3dDevice->SetTexture( GFX_iActiveTexUnit, *_ppd3dCurrentTexture); + D3D_CHECKERROR(hr); + } + } +#endif // SE1_D3D + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +// returns size of uploaded texture +extern SLONG gfxGetTextureSize( ULONG ulTexObject, BOOL bHasMipmaps/*=TRUE*/) +{ + // nothing used if nothing uploaded + if( ulTexObject==NULL) return 0; + + // determine API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + SLONG slMipSize; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // OpenGL + if( eAPI==GAT_OGL) + { + // was texture compressed? + pglBindTexture( GL_TEXTURE_2D, ulTexObject); + BOOL bCompressed = FALSE; + if( _pGfx->gl_ulFlags & GLF_EXTC_ARB) { + pglGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_ARB, (BOOL*)&bCompressed); + OGL_CHECKERROR; + } + // for compressed textures, determine size directly + if( bCompressed) { + pglGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB, (GLint*)&slMipSize); + OGL_CHECKERROR; + } + // non-compressed textures goes thru determination of internal format + else { + PIX pixWidth, pixHeight; + pglGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, (GLint*)&pixWidth); + pglGetTexLevelParameteriv( GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, (GLint*)&pixHeight); + OGL_CHECKERROR; + slMipSize = pixWidth*pixHeight * gfxGetTexturePixRatio(ulTexObject); + } + } + // Direct3D +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) + { + // we can determine exact size from texture surface (i.e. mipmap) + D3DSURFACE_DESC d3dSurfDesc; + HRESULT hr = ((LPDIRECT3DTEXTURE8)ulTexObject)->GetLevelDesc( 0, &d3dSurfDesc); + D3D_CHECKERROR(hr); + slMipSize = d3dSurfDesc.Size; + } +#endif // SE1_D3D + + // eventually count in all the mipmaps (takes extra 33% of texture size) + extern INDEX gap_bAllowSingleMipmap; + const SLONG slUploadSize = (bHasMipmaps || !gap_bAllowSingleMipmap) ? slMipSize*4/3 : slMipSize; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); + return slUploadSize; +} + + + +// returns bytes/pixels ratio for uploaded texture +extern INDEX gfxGetTexturePixRatio( ULONG ulTextureObject) +{ + // determine API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + if( eAPI==GAT_OGL) { + return GetTexturePixRatio_OGL( (GLuint)ulTextureObject); + } +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) return GetTexturePixRatio_D3D( (LPDIRECT3DTEXTURE8)ulTextureObject); +#endif // SE1_D3D + else return 0; +} + + +// returns bytes/pixels ratio for uploaded texture +extern INDEX gfxGetFormatPixRatio( ULONG ulTextureFormat) +{ + // determine API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + if( eAPI==GAT_OGL) { + return GetFormatPixRatio_OGL( (GLenum)ulTextureFormat); + } +#ifdef SE1_D3D + else if( eAPI==GAT_D3D) return GetFormatPixRatio_D3D( (D3DFORMAT)ulTextureFormat); +#endif // SE1_D3D + else return 0; +} + + + +// PATTERN TEXTURE FOR LINES + +CTexParams _tpPattern; +extern ULONG _ulPatternTexture = NONE; +extern ULONG _ulLastUploadedPattern = 0; + +// upload pattern to accelerator memory +extern void gfxSetPattern( ULONG ulPattern) +{ + // set pattern to be current texture + _tpPattern.tp_bSingleMipmap = TRUE; + gfxSetTextureWrapping( GFX_REPEAT, GFX_REPEAT); + gfxSetTexture( _ulPatternTexture, _tpPattern); + + // if this pattern is currently uploaded, do nothing + if( _ulLastUploadedPattern==ulPattern) return; + + // convert bits to ULONGs + ULONG aulPattern[32]; + for( INDEX iBit=0; iBit<32; iBit++) { + if( (0x80000000>>iBit) & ulPattern) aulPattern[iBit] = 0xFFFFFFFF; + else aulPattern[iBit] = 0x00000000; + } + // remember new pattern and upload + _ulLastUploadedPattern = ulPattern; + gfxUploadTexture( &aulPattern[0], 32, 1, TS.ts_tfRGBA8, FALSE); +} + + + +// VERTEX ARRAYS + + +// for D3D - (type 0=vtx, 1=nor, 2=col, 3=tex) +extern void SetVertexArray_D3D( INDEX iType, ULONG *pulVtx); + + +extern void gfxUnlockArrays(void) +{ + // only if locked (OpenGL can lock 'em) + if( !_bCVAReallyLocked) return; + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + INDEX glctRet; + pglGetIntegerv( GL_ARRAY_ELEMENT_LOCK_COUNT_EXT, (GLint*)&glctRet); + ASSERT( glctRet==GFX_ctVertices); +#endif + pglUnlockArraysEXT(); + OGL_CHECKERROR; + _bCVAReallyLocked = FALSE; +} + + + +// OpenGL workarounds + + +// initialization of commond quad elements array +extern void AddQuadElements( const INDEX ctQuads) +{ + const INDEX iStart = _aiCommonQuads.Count() /6*4; + INDEX *piQuads = _aiCommonQuads.Push(ctQuads*6); + for( INDEX i=0; igl_eCurrentAPI==GAT_OGL && ogl_bAllowQuadArrays) FlushArrays( NULL, _avtxCommon.Count()); + else { + // make sure that enough quad elements has been initialized + const INDEX ctQuads = _aiCommonQuads.Count(); + if( ctElements>ctQuads) AddQuadElements( ctElements-ctQuads); // yes, 4 times more! + FlushArrays( &_aiCommonQuads[0], ctElements); + } +} + + +// render elements to screen buffer +extern void gfxFlushElements(void) +{ + const INDEX ctElements = _aiCommonElements.Count(); + if( ctElements>0) FlushArrays( &_aiCommonElements[0], ctElements); +} + + + + +// set truform parameters +extern void gfxSetTruform( INDEX iLevel, BOOL bLinearNormals) +{ + // skip if Truform isn't supported + if( _pGfx->gl_iMaxTessellationLevel<1) { + truform_iLevel = 0; + truform_bLinear = FALSE; + return; + } + // skip if same as last time + iLevel = Clamp( iLevel, 0L, _pGfx->gl_iMaxTessellationLevel); + if( truform_iLevel==iLevel && !truform_bLinear==!bLinearNormals) return; + + // determine API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_D3D || eAPI == GAT_NONE); +#else // SE1_D3D + ASSERT(eAPI == GAT_OGL || eAPI == GAT_NONE); +#endif // SE1_D3D + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // OpenGL needs truform set here + if( eAPI==GAT_OGL) { + GLenum eTriMode = bLinearNormals ? GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI : GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI; + pglPNTrianglesiATI( GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, iLevel); + pglPNTrianglesiATI( GL_PN_TRIANGLES_NORMAL_MODE_ATI, eTriMode); + OGL_CHECKERROR; + } + // if disabled, Direct3D will set tessellation level at "enable" call +#ifdef SE1_D3D + else if( eAPI==GAT_D3D && GFX_bTruform) { + FLOAT fSegments = iLevel+1; + HRESULT hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_PATCHSEGMENTS, *((DWORD*)&fSegments)); + D3D_CHECKERROR(hr); + } +#endif // SE1_D3D + + // keep current truform params + truform_iLevel = iLevel; + truform_bLinear = bLinearNormals; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// readout current colormask +extern ULONG gfxGetColorMask(void) +{ + return _ulCurrentColorMask; +} + + + +#include "GFX_wrapper_OpenGL.cpp" +#include "GFX_wrapper_Direct3D.cpp" + + + +// DUMMY FUNCTIONS FOR NONE API +static void none_BlendFunc( GfxBlend eSrc, GfxBlend eDst) { NOTHING; } +static void none_DepthFunc( GfxComp eFunc) { NOTHING; }; +static void none_DepthRange( FLOAT fMin, FLOAT fMax) { NOTHING; }; +static void none_CullFace( GfxFace eFace) { NOTHING; }; +static void none_ClipPlane( const DOUBLE *pdViewPlane) { NOTHING; }; +static void none_SetOrtho( const FLOAT fLeft, const FLOAT fRight, const FLOAT fTop, const FLOAT fBottom, const FLOAT fNear, const FLOAT fFar, const BOOL bSubPixelAdjust) { NOTHING; }; +static void none_SetFrustum( const FLOAT fLeft, const FLOAT fRight, const FLOAT fTop, const FLOAT fBottom, const FLOAT fNear, const FLOAT fFar) { NOTHING; }; +static void none_SetMatrix( const FLOAT *pfMatrix) { NOTHING; }; +static void none_PolygonMode( GfxPolyMode ePolyMode) { NOTHING; }; +static void none_SetTextureWrapping( enum GfxWrap eWrapU, enum GfxWrap eWrapV) { NOTHING; }; +static void none_SetTextureModulation( INDEX iScale) { NOTHING; }; +static void none_GenDelTexture( ULONG &ulTexObject) { NOTHING; }; +static void none_SetVertexArray( GFXVertex4 *pvtx, INDEX ctVtx) { NOTHING; }; +static void none_SetNormalArray( GFXNormal *pnor) { NOTHING; }; +static void none_SetTexCoordArray( GFXTexCoord *ptex, BOOL b4) { NOTHING; }; +static void none_SetColorArray( GFXColor *pcol) { NOTHING; }; +static void none_DrawElements( INDEX ctElem, INDEX *pidx) { NOTHING; }; +static void none_SetConstantColor( COLOR col) { NOTHING; }; +static void none_SetColorMask( ULONG ulColorMask) { NOTHING; }; + + + +// functions initialization for OGL, D3D or NONE (dummy) +extern void GFX_SetFunctionPointers( INDEX iAPI) +{ + // OpenGL? + if( iAPI==(INDEX)GAT_OGL) + { + gfxEnableDepthWrite = &ogl_EnableDepthWrite; + gfxEnableDepthBias = &ogl_EnableDepthBias; + gfxEnableDepthTest = &ogl_EnableDepthTest; + gfxEnableAlphaTest = &ogl_EnableAlphaTest; + gfxEnableBlend = &ogl_EnableBlend; + gfxEnableDither = &ogl_EnableDither; + gfxEnableTexture = &ogl_EnableTexture; + gfxEnableClipping = &ogl_EnableClipping; + gfxEnableClipPlane = &ogl_EnableClipPlane; + gfxEnableTruform = &ogl_EnableTruform; + gfxDisableDepthWrite = &ogl_DisableDepthWrite; + gfxDisableDepthBias = &ogl_DisableDepthBias; + gfxDisableDepthTest = &ogl_DisableDepthTest; + gfxDisableAlphaTest = &ogl_DisableAlphaTest; + gfxDisableBlend = &ogl_DisableBlend; + gfxDisableDither = &ogl_DisableDither; + gfxDisableTexture = &ogl_DisableTexture; + gfxDisableClipping = &ogl_DisableClipping; + gfxDisableClipPlane = &ogl_DisableClipPlane; + gfxDisableTruform = &ogl_DisableTruform; + gfxBlendFunc = &ogl_BlendFunc; + gfxDepthFunc = &ogl_DepthFunc; + gfxDepthRange = &ogl_DepthRange; + gfxCullFace = &ogl_CullFace; + gfxFrontFace = &ogl_FrontFace; + gfxClipPlane = &ogl_ClipPlane; + gfxSetOrtho = &ogl_SetOrtho; + gfxSetFrustum = &ogl_SetFrustum; + gfxSetTextureMatrix = &ogl_SetTextureMatrix; + gfxSetViewMatrix = &ogl_SetViewMatrix; + gfxPolygonMode = &ogl_PolygonMode; + gfxSetTextureWrapping = &ogl_SetTextureWrapping; + gfxSetTextureModulation = &ogl_SetTextureModulation; + gfxGenerateTexture = &ogl_GenerateTexture; + gfxDeleteTexture = &ogl_DeleteTexture; + gfxSetVertexArray = &ogl_SetVertexArray; + gfxSetNormalArray = &ogl_SetNormalArray; + gfxSetTexCoordArray = &ogl_SetTexCoordArray; + gfxSetColorArray = &ogl_SetColorArray; + gfxDrawElements = &ogl_DrawElements; + gfxSetConstantColor = &ogl_SetConstantColor; + gfxEnableColorArray = &ogl_EnableColorArray; + gfxDisableColorArray = &ogl_DisableColorArray; + gfxFinish = &ogl_Finish; + gfxLockArrays = &ogl_LockArrays; + gfxSetColorMask = &ogl_SetColorMask; + } + // Direct3D? +#ifdef SE1_D3D + else if( iAPI==(INDEX)GAT_D3D) + { + gfxEnableDepthWrite = &d3d_EnableDepthWrite; + gfxEnableDepthBias = &d3d_EnableDepthBias; + gfxEnableDepthTest = &d3d_EnableDepthTest; + gfxEnableAlphaTest = &d3d_EnableAlphaTest; + gfxEnableBlend = &d3d_EnableBlend; + gfxEnableDither = &d3d_EnableDither; + gfxEnableTexture = &d3d_EnableTexture; + gfxEnableClipping = &d3d_EnableClipping; + gfxEnableClipPlane = &d3d_EnableClipPlane; + gfxEnableTruform = &d3d_EnableTruform; + gfxDisableDepthWrite = &d3d_DisableDepthWrite; + gfxDisableDepthBias = &d3d_DisableDepthBias; + gfxDisableDepthTest = &d3d_DisableDepthTest; + gfxDisableAlphaTest = &d3d_DisableAlphaTest; + gfxDisableBlend = &d3d_DisableBlend; + gfxDisableDither = &d3d_DisableDither; + gfxDisableTexture = &d3d_DisableTexture; + gfxDisableClipping = &d3d_DisableClipping; + gfxDisableClipPlane = &d3d_DisableClipPlane; + gfxDisableTruform = &d3d_DisableTruform; + gfxBlendFunc = &d3d_BlendFunc; + gfxDepthFunc = &d3d_DepthFunc; + gfxDepthRange = &d3d_DepthRange; + gfxCullFace = &d3d_CullFace; + gfxFrontFace = &d3d_FrontFace; + gfxClipPlane = &d3d_ClipPlane; + gfxSetOrtho = &d3d_SetOrtho; + gfxSetFrustum = &d3d_SetFrustum; + gfxSetTextureMatrix = &d3d_SetTextureMatrix; + gfxSetViewMatrix = &d3d_SetViewMatrix; + gfxPolygonMode = &d3d_PolygonMode; + gfxSetTextureWrapping = &d3d_SetTextureWrapping; + gfxSetTextureModulation = &d3d_SetTextureModulation; + gfxGenerateTexture = &d3d_GenerateTexture; + gfxDeleteTexture = &d3d_DeleteTexture; + gfxSetVertexArray = &d3d_SetVertexArray; + gfxSetNormalArray = &d3d_SetNormalArray; + gfxSetTexCoordArray = &d3d_SetTexCoordArray; + gfxSetColorArray = &d3d_SetColorArray; + gfxDrawElements = &d3d_DrawElements; + gfxSetConstantColor = &d3d_SetConstantColor; + gfxEnableColorArray = &d3d_EnableColorArray; + gfxDisableColorArray = &d3d_DisableColorArray; + gfxFinish = &d3d_Finish; + gfxLockArrays = &d3d_LockArrays; + gfxSetColorMask = &d3d_SetColorMask; + } +#endif // SE1_D3D + // NONE! + else + { + gfxEnableDepthWrite = &none_void; + gfxEnableDepthBias = &none_void; + gfxEnableDepthTest = &none_void; + gfxEnableAlphaTest = &none_void; + gfxEnableBlend = &none_void; + gfxEnableDither = &none_void; + gfxEnableTexture = &none_void; + gfxEnableClipping = &none_void; + gfxEnableClipPlane = &none_void; + gfxEnableTruform = &none_void; + gfxDisableDepthWrite = &none_void; + gfxDisableDepthBias = &none_void; + gfxDisableDepthTest = &none_void; + gfxDisableAlphaTest = &none_void; + gfxDisableBlend = &none_void; + gfxDisableDither = &none_void; + gfxDisableTexture = &none_void; + gfxDisableClipping = &none_void; + gfxDisableClipPlane = &none_void; + gfxDisableTruform = &none_void; + gfxBlendFunc = &none_BlendFunc; + gfxDepthFunc = &none_DepthFunc; + gfxDepthRange = &none_DepthRange; + gfxCullFace = &none_CullFace; + gfxFrontFace = &none_CullFace; + gfxClipPlane = &none_ClipPlane; + gfxSetOrtho = &none_SetOrtho; + gfxSetFrustum = &none_SetFrustum; + gfxSetTextureMatrix = &none_SetMatrix; + gfxSetViewMatrix = &none_SetMatrix; + gfxPolygonMode = &none_PolygonMode; + gfxSetTextureWrapping = &none_SetTextureWrapping; + gfxSetTextureModulation = &none_SetTextureModulation; + gfxGenerateTexture = &none_GenDelTexture; + gfxDeleteTexture = &none_GenDelTexture; + gfxSetVertexArray = &none_SetVertexArray; + gfxSetNormalArray = &none_SetNormalArray; + gfxSetTexCoordArray = &none_SetTexCoordArray; + gfxSetColorArray = &none_SetColorArray; + gfxDrawElements = &none_DrawElements; + gfxSetConstantColor = &none_SetConstantColor; + gfxEnableColorArray = &none_void; + gfxDisableColorArray = &none_void; + gfxFinish = &none_void; + gfxLockArrays = &none_void; + gfxSetColorMask = &none_SetColorMask; + } +} diff --git a/Sources/Engine/Graphics/Gfx_wrapper.h b/Sources/Engine/Graphics/Gfx_wrapper.h new file mode 100644 index 0000000..4bbce12 --- /dev/null +++ b/Sources/Engine/Graphics/Gfx_wrapper.h @@ -0,0 +1,294 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#pragma once + + +enum GfxBlend +{ + GFX_ONE = 21, + GFX_ZERO = 22, + GFX_SRC_COLOR = 23, + GFX_INV_SRC_COLOR = 24, + GFX_DST_COLOR = 25, + GFX_INV_DST_COLOR = 26, + GFX_SRC_ALPHA = 27, + GFX_INV_SRC_ALPHA = 28, +}; + +enum GfxComp +{ + GFX_NEVER = 41, + GFX_LESS = 42, + GFX_LESS_EQUAL = 43, + GFX_EQUAL = 44, + GFX_NOT_EQUAL = 45, + GFX_GREATER_EQUAL = 46, + GFX_GREATER = 47, + GFX_ALWAYS = 48, +}; + +enum GfxFace +{ + GFX_NONE = 61, + GFX_FRONT = 62, + GFX_BACK = 63, + GFX_CW = 64, + GFX_CCW = 65, +}; + +enum GfxMatrixType +{ + GFX_VIEW = 71, + GFX_PROJECTION = 72, +}; + +enum GfxWrap +{ + GFX_REPEAT = 81, + GFX_CLAMP = 82, +}; + +enum GfxPolyMode +{ + GFX_FILL = 91, + GFX_LINE = 92, + GFX_POINT = 93, +}; + + +// functions initialization for OGL, D3D or NONE (dummy) +extern void GFX_SetFunctionPointers( INDEX iAPI); + + +// enable operations +extern void (*gfxEnableDepthWrite)(void); +extern void (*gfxEnableDepthBias)(void); +extern void (*gfxEnableDepthTest)(void); +extern void (*gfxEnableAlphaTest)(void); +extern void (*gfxEnableBlend)(void); +extern void (*gfxEnableDither)(void); +extern void (*gfxEnableTexture)(void); +extern void (*gfxEnableClipping)(void); +extern void (*gfxEnableClipPlane)(void); + +// disable operations +extern void (*gfxDisableDepthWrite)(void); +extern void (*gfxDisableDepthBias)(void); +extern void (*gfxDisableDepthTest)(void); +extern void (*gfxDisableAlphaTest)(void); +extern void (*gfxDisableBlend)(void); +extern void (*gfxDisableDither)(void); +extern void (*gfxDisableTexture)(void); +extern void (*gfxDisableClipping)(void); +extern void (*gfxDisableClipPlane)(void); + +// set blending operations +extern void (*gfxBlendFunc)( GfxBlend eSrc, GfxBlend eDst); + +// set depth buffer compare mode +extern void (*gfxDepthFunc)( GfxComp eFunc); + +// set depth buffer range +extern void (*gfxDepthRange)( FLOAT fMin, FLOAT fMax); + +// color mask control (use CT_RMASK, CT_GMASK, CT_BMASK, CT_AMASK to enable specific channels) +extern void (*gfxSetColorMask)( ULONG ulColorMask); +extern ULONG gfxGetColorMask(void); + + + +// PROJECTIONS + + +// set face culling +extern void (*gfxCullFace)( GfxFace eFace); +extern void (*gfxFrontFace)( GfxFace eFace); + +// set custom clip plane (if NULL, disable it) +extern void (*gfxClipPlane)( const DOUBLE *pdPlane); + +// set orthographic matrix +extern void (*gfxSetOrtho)( const FLOAT fLeft, const FLOAT fRight, + const FLOAT fTop, const FLOAT fBottom, + const FLOAT fNear, const FLOAT fFar, const BOOL bSubPixelAdjust); +// set frustrum matrix +extern void (*gfxSetFrustum)( const FLOAT fLeft, const FLOAT fRight, + const FLOAT fTop, const FLOAT fBottom, + const FLOAT fNear, const FLOAT fFar); +// set view matrix +extern void (*gfxSetViewMatrix)( const FLOAT *pfMatrix); + +// set texture matrix +extern void (*gfxSetTextureMatrix)( const FLOAT *pfMatrix); + + +// polygon mode (point, line or fill) +extern void (*gfxPolygonMode)( GfxPolyMode ePolyMode); + + + +// TEXTURES + + +// texture settings (holds current states of texture quality, size and such) +struct TextureSettings { +public: + //quailties + INDEX ts_iNormQualityO; + INDEX ts_iNormQualityA; + INDEX ts_iAnimQualityO; + INDEX ts_iAnimQualityA; + // sizes/forcing + PIX ts_pixNormSize; + PIX ts_pixAnimSize; + // texture formats (set by OGL or D3D) + ULONG ts_tfRGB8, ts_tfRGBA8; // true color + ULONG ts_tfRGB5, ts_tfRGBA4, ts_tfRGB5A1; // high color + ULONG ts_tfLA8, ts_tfL8; // grayscale + ULONG ts_tfCRGB, ts_tfCRGBA; // compressed formats + // maximum texel-byte ratio for largest texture size + INDEX ts_iMaxBytesPerTexel; +}; +// singleton object for texture settings +extern struct TextureSettings TS; +// routine for updating texture settings from console variable +extern void UpdateTextureSettings(void); + + +// texture parameters for texture state changes +class CTexParams { +public: + INDEX tp_iFilter; // OpenGL texture mapping mode + INDEX tp_iAnisotropy; // texture degree of anisotropy (>=1.0f; 1.0=isotropic, default) + BOOL tp_bSingleMipmap; // texture has only one mipmap + GfxWrap tp_eWrapU, tp_eWrapV; // wrapping states + inline CTexParams(void) { Clear(); tp_bSingleMipmap = FALSE; }; + inline void Clear(void) { tp_iFilter = 00; tp_iAnisotropy = 0; tp_eWrapU = tp_eWrapV = (GfxWrap)NONE; }; + inline BOOL IsEqual( CTexParams tp) { return tp_iFilter==tp.tp_iFilter && tp_iAnisotropy==tp_iAnisotropy && + tp_eWrapU==tp.tp_eWrapU && tp_eWrapV==tp.tp_eWrapV; }; +}; + +// get current texture filtering mode +extern void gfxGetTextureFiltering( INDEX &iFilterType, INDEX &iAnisotropyDegree); +// set texture filtering +extern void gfxSetTextureFiltering( INDEX &iFilterType, INDEX &iAnisotropyDegree); +// set texture LOD biasing +extern void gfxSetTextureBiasing( FLOAT &fLODBias); + +// set texture wrapping mode +extern void (*gfxSetTextureWrapping)( enum GfxWrap eWrapU, enum GfxWrap eWrapV); + +// set texture modulation mode (1X or 2X) +extern void (*gfxSetTextureModulation)( INDEX iScale); + +// set texture unit as active +extern void gfxSetTextureUnit( INDEX iUnit); + +// generate texture for API +extern void (*gfxGenerateTexture)( ULONG &ulTexObject); +// unbind texture from API +extern void (*gfxDeleteTexture)( ULONG &ulTexObject); + + +// set texture as current +// - ulTexture = bind number for OGL, or *LPDIRECT3DTEXTURE8 for D3D (pointer to pointer!) +extern void gfxSetTexture( ULONG &ulTexObject, CTexParams &tpLocal); + +// upload texture +// - ulTexture = bind number for OGL, or LPDIRECT3DTEXTURE8 for D3D +// - pulTexture = pointer to texture in 32-bit R,G,B,A format (in that byte order) +// - ulFormat = format in which the texture will be stored in accelerator's (or driver's) memory +// - bNoDiscard = no need to discard old texture (for OGL, this is like "use SubImage") +extern void gfxUploadTexture( ULONG *pulTexture, PIX pixWidth, PIX pixHeight, ULONG ulFormat, BOOL bNoDiscard); + +// returns size of uploaded texture +extern SLONG gfxGetTextureSize( ULONG ulTexObject, BOOL bHasMipmaps=TRUE); + +// returns bytes/pixels ratio for uploaded texture or texture format +extern INDEX gfxGetTexturePixRatio( ULONG ulTextureObject); +extern INDEX gfxGetFormatPixRatio( ULONG ulTextureFormat); + + + +// VERTEX ARRAYS + +// prepare arrays for API +extern void (*gfxSetVertexArray)( GFXVertex4 *pvtx, INDEX ctVtx); +extern void (*gfxSetNormalArray)( GFXNormal *pnor); +extern void (*gfxSetTexCoordArray)( GFXTexCoord *ptex, BOOL b4); // b4 = projective mapping (4 FLOATS) +extern void (*gfxSetColorArray)( GFXColor *pcol); + + +// draw prepared arrays +extern void (*gfxDrawElements)( INDEX ctElem, INDEX *pidx); + +// set constant color for subsequent rendering (until 1st gfxSetColorArray() call!) +extern void (*gfxSetConstantColor)(COLOR col); +// color array usage control +extern void (*gfxEnableColorArray)(void); +extern void (*gfxDisableColorArray)(void); + + +// MISC + + +// force finish of rendering queue +extern void (*gfxFinish)(void); + + +// compiled vertex array control +extern void (*gfxLockArrays)(void); +extern void gfxUnlockArrays(void); + + +// helper functions for drawing simple primitives thru drawelements + +inline void gfxResetArrays(void) +{ + _avtxCommon.PopAll(); + _atexCommon.PopAll(); + _acolCommon.PopAll(); + _aiCommonElements.PopAll(); +} + +// render elements to screen buffer +extern void gfxFlushElements(void); +extern void gfxFlushQuads(void); + + +// check GFX errors only in debug builds +#ifndef NDEBUG + extern void OGL_CheckError(void); + extern void D3D_CheckError(HRESULT hr); + #define OGL_CHECKERROR OGL_CheckError(); + #define D3D_CHECKERROR(hr) D3D_CheckError(hr); +#else + #define OGL_CHECKERROR (void)(0); + #define D3D_CHECKERROR(hr) (void)(0); +#endif + + + +// ATI's TRUFORM support + + +// set truform parameters +extern void gfxSetTruform( const INDEX iLevel, BOOL bLinearNormals); +extern void (*gfxEnableTruform)( void); +extern void (*gfxDisableTruform)(void); + + +// set D3D vertex shader only if different than last time +extern void d3dSetVertexShader(DWORD dwHandle); + + +// macro for releasing D3D objects +#define D3DRELEASE(object,check) \ +{ \ + INDEX ref; \ + do { \ + ref = (object)->Release(); \ + if(check) ASSERT(ref==0); \ + } while(ref>0); \ + object = NONE; \ +} diff --git a/Sources/Engine/Graphics/Gfx_wrapper_Direct3D.cpp b/Sources/Engine/Graphics/Gfx_wrapper_Direct3D.cpp new file mode 100644 index 0000000..33b17ad --- /dev/null +++ b/Sources/Engine/Graphics/Gfx_wrapper_Direct3D.cpp @@ -0,0 +1,1303 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifdef SE1_D3D + + +// helper for keep user clip plane of D3D happy (i.e. updated as view matrix changes) +static void UpdateClipPlane_D3D(void) +{ + FLOAT afObjectClipPlane[4]; + + // if view matrix is active + if( GFX_bViewMatrix) { + // need to back-transform user clip plane from view to object space + FLOAT *pcp = &D3D_afClipPlane[0]; // (pl-v) * !m; + FLOAT *pvm = &D3D_afViewMatrix[0]; + afObjectClipPlane[0] = pcp[0]*pvm[0] + pcp[1]*pvm[1] + pcp[2]*pvm[2]; + afObjectClipPlane[1] = pcp[0]*pvm[4] + pcp[1]*pvm[5] + pcp[2]*pvm[6]; + afObjectClipPlane[2] = pcp[0]*pvm[8] + pcp[1]*pvm[9] + pcp[2]*pvm[10]; + afObjectClipPlane[3] = pcp[3] + (pcp[0]*pvm[12] + pcp[1]*pvm[13] + pcp[2]*pvm[14]); + } else { + // just copy clip plane + (ULONG&)afObjectClipPlane[0] = (ULONG&)D3D_afClipPlane[0]; + (ULONG&)afObjectClipPlane[1] = (ULONG&)D3D_afClipPlane[1]; + (ULONG&)afObjectClipPlane[2] = (ULONG&)D3D_afClipPlane[2]; + (ULONG&)afObjectClipPlane[3] = (ULONG&)D3D_afClipPlane[3]; + } + // skip if the same as last time + ULONG *pulThis = (ULONG*) afObjectClipPlane; + ULONG *pulLast = (ULONG*)_afActiveClipPlane; + if( pulLast[0]==pulThis[0] && pulLast[1]==pulThis[1] + && pulLast[2]==pulThis[2] && pulLast[3]==pulThis[3]) return; + // update (if supported!) + if( _pGfx->gl_ulFlags&GLF_D3D_CLIPPLANE) { + HRESULT hr = _pGfx->gl_pd3dDevice->SetClipPlane( 0, &afObjectClipPlane[0]); + D3D_CHECKERROR(hr); + } + // keep it as current + pulLast[0] = pulThis[0]; + pulLast[1] = pulThis[1]; + pulLast[2] = pulThis[2]; + pulLast[3] = pulThis[3]; +} + + + +// ENABLE/DISABLE FUNCTIONS + + +static void d3d_EnableTexture(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetTextureStageState( GFX_iActiveTexUnit, D3DTSS_COLOROP, (DWORD*)&bRes); + if( bRes==D3DTOP_DISABLE) bRes = FALSE; + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_abTexture[GFX_iActiveTexUnit]); +#endif + + // cached? + if( GFX_abTexture[GFX_iActiveTexUnit] && gap_bOptimizeStateChanges) return; + GFX_abTexture[GFX_iActiveTexUnit] = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + D3DTEXTUREOP d3dTexOp = (GFX_iTexModulation[GFX_iActiveTexUnit]==2) ? D3DTOP_MODULATE2X : D3DTOP_MODULATE; + hr = _pGfx->gl_pd3dDevice->SetTextureStageState( GFX_iActiveTexUnit, D3DTSS_COLOROP, d3dTexOp); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_DisableTexture(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetTextureStageState( GFX_iActiveTexUnit, D3DTSS_COLOROP, (DWORD*)&bRes); + if( bRes==D3DTOP_DISABLE) bRes = FALSE; + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_abTexture[GFX_iActiveTexUnit]); +#endif + + // cached? + if( !GFX_abTexture[GFX_iActiveTexUnit] && gap_bOptimizeStateChanges) return; + GFX_abTexture[GFX_iActiveTexUnit] = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetTextureStageState( GFX_iActiveTexUnit, D3DTSS_COLOROP, D3DTOP_DISABLE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_EnableDepthTest(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_ZENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bDepthTest); +#endif + // cached? + if( GFX_bDepthTest && gap_bOptimizeStateChanges) return; + GFX_bDepthTest = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_DisableDepthTest(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_ZENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bDepthTest); +#endif + + // cached? + if( !GFX_bDepthTest && gap_bOptimizeStateChanges) return; + GFX_bDepthTest = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_EnableDepthBias(void) +{ + // only if supported + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + if( !(_pGfx->gl_ulFlags&GLF_D3D_ZBIAS)) return; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + HRESULT hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_ZBIAS, 2); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_DisableDepthBias(void) +{ + // only if supported + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + if( !(_pGfx->gl_ulFlags&GLF_D3D_ZBIAS)) return; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + HRESULT hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_ZBIAS, 0); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_EnableDepthWrite(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_ZWRITEENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bDepthWrite); +#endif + + // cached? + if( GFX_bDepthWrite && gap_bOptimizeStateChanges) return; + GFX_bDepthWrite = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_DisableDepthWrite(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_ZWRITEENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bDepthWrite); +#endif + + // cached? + if( !GFX_bDepthWrite && gap_bOptimizeStateChanges) return; + GFX_bDepthWrite = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_EnableDither(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_DITHERENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bDithering); +#endif + + // cached? + if( GFX_bDithering && gap_bOptimizeStateChanges) return; + GFX_bDithering = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_DisableDither(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_DITHERENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bDithering); +#endif + + // cached? + if( !GFX_bDithering && gap_bOptimizeStateChanges) return; + GFX_bDithering = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, FALSE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_EnableAlphaTest(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_ALPHATESTENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bAlphaTest); +#endif + + // cached? + if( GFX_bAlphaTest && gap_bOptimizeStateChanges) return; + GFX_bAlphaTest = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_DisableAlphaTest(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_ALPHATESTENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bAlphaTest); +#endif + + // cached? + if( !GFX_bAlphaTest && gap_bOptimizeStateChanges) return; + GFX_bAlphaTest = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_EnableBlend(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_ALPHABLENDENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bBlending); +#endif + // cached? + if( GFX_bBlending && gap_bOptimizeStateChanges) return; + GFX_bBlending = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); + + // adjust dithering + if( gap_iDithering==2) d3d_EnableDither(); + else d3d_DisableDither(); +} + + + +static void d3d_DisableBlend(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_ALPHABLENDENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bBlending); +#endif + + // cached? + if( !GFX_bBlending && gap_bOptimizeStateChanges) return; + GFX_bBlending = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); + + // adjust dithering + if( gap_iDithering==0) d3d_DisableDither(); + else d3d_EnableDither(); +} + + + +static void d3d_EnableClipping(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes = GFX_bClipping; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_CLIPPING, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bClipping); +#endif + + // cached? + if( GFX_bClipping && gap_bOptimizeStateChanges) return; + GFX_bClipping = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + _bWantsClipping = TRUE; // need to signal for custom clip plane + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_CLIPPING, TRUE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_DisableClipping(void) +{ + // only if allowed + if( gap_iOptimizeClipping<2) return; + + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_CLIPPING, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bClipping); +#endif + + // cached? + if( !GFX_bClipping && gap_bOptimizeStateChanges) return; + GFX_bClipping = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // cannot disable clipping if clip-plane is enabled! + if( GFX_bClipPlane) { + GFX_bClipping = TRUE; + _bWantsClipping = FALSE; + } else { + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_CLIPPING, FALSE); + D3D_CHECKERROR(hr); + } + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_EnableClipPlane(void) +{ + // only if supported + if( !(_pGfx->gl_ulFlags&GLF_D3D_CLIPPLANE)) return; + + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_CLIPPLANEENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bClipPlane); +#endif + + // cached? + if( GFX_bClipPlane && gap_bOptimizeStateChanges) return; + GFX_bClipPlane = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, D3DCLIPPLANE0); + D3D_CHECKERROR(hr); + // (eventually) update clip plane, too + UpdateClipPlane_D3D(); + // D3D needs to have clipping enabled for that matter + if( !GFX_bClipping) { + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_CLIPPING, TRUE); + D3D_CHECKERROR(hr); + GFX_bClipping = TRUE; + _bWantsClipping = FALSE; + } + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_DisableClipPlane(void) +{ + // only if supported + if( !(_pGfx->gl_ulFlags&GLF_D3D_CLIPPLANE)) return; + + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes = GFX_bClipPlane; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_CLIPPLANEENABLE, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + ASSERT( !bRes == !GFX_bClipPlane); +#endif + // cached? + if( !GFX_bClipPlane && gap_bOptimizeStateChanges) return; + GFX_bClipPlane = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, FALSE); + D3D_CHECKERROR(hr); + // maybe we can disable clipping in general (if was kept enabled just beacuse of clip plane) + if( !_bWantsClipping && GFX_bClipping) { + GFX_bClipping = FALSE; + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_CLIPPING, FALSE); + D3D_CHECKERROR(hr); + } + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_EnableColorArray(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_LIGHTING, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + bRes = !bRes; + ASSERT( !bRes == !GFX_bColorArray); +#endif + + // cached? + if( GFX_bColorArray && gap_bOptimizeStateChanges) return; + GFX_bColorArray = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// enable usage of constant color for subsequent rendering +static void d3d_DisableColorArray(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_LIGHTING, (DWORD*)&bRes); + D3D_CHECKERROR(hr); + bRes = !bRes; + ASSERT( !bRes == !GFX_bColorArray); +#endif + + // cached? + if( !GFX_bColorArray && gap_bOptimizeStateChanges) return; + GFX_bColorArray = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_EnableTruform(void) +{ + // skip if Truform isn't set + if( truform_iLevel<1) return; + + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; + FLOAT fSegments; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_PATCHSEGMENTS, (DWORD*)&fSegments); + D3D_CHECKERROR(hr); + bRes = (fSegments>1) ? TRUE : FALSE; + ASSERT( !bRes == !GFX_bTruform); +#endif + + if( GFX_bTruform && gap_bOptimizeStateChanges) return; + GFX_bTruform = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + fSegments = truform_iLevel+1; + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_PATCHSEGMENTS, *((DWORD*)&fSegments)); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_DisableTruform(void) +{ + // skip if Truform isn't set + if( truform_iLevel<1) return; + + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; + FLOAT fSegments; +#ifndef NDEBUG + BOOL bRes; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_PATCHSEGMENTS, (DWORD*)&fSegments); + D3D_CHECKERROR(hr); + bRes = (fSegments>1) ? TRUE : FALSE; + ASSERT( !bRes == !GFX_bTruform); +#endif + + if( !GFX_bTruform && gap_bOptimizeStateChanges) return; + GFX_bTruform = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + fSegments = 1.0f; + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_PATCHSEGMENTS, *((DWORD*)&fSegments)); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +__forceinline _D3DBLEND BlendToD3D( GfxBlend eFunc) { + switch( eFunc) { + case GFX_ZERO: return D3DBLEND_ZERO; + case GFX_ONE: return D3DBLEND_ONE; + case GFX_SRC_COLOR: return D3DBLEND_SRCCOLOR; + case GFX_INV_SRC_COLOR: return D3DBLEND_INVSRCCOLOR; + case GFX_DST_COLOR: return D3DBLEND_DESTCOLOR; + case GFX_INV_DST_COLOR: return D3DBLEND_INVDESTCOLOR; + case GFX_SRC_ALPHA: return D3DBLEND_SRCALPHA; + case GFX_INV_SRC_ALPHA: return D3DBLEND_INVSRCALPHA; + default: ASSERTALWAYS("Invalid GFX blending function!"); + } return D3DBLEND_ONE; +} + +__forceinline GfxBlend BlendFromD3D( _D3DBLEND d3dbFunc) { + switch( d3dbFunc) { + case D3DBLEND_ZERO: return GFX_ZERO; + case D3DBLEND_ONE: return GFX_ONE; + case D3DBLEND_SRCCOLOR: return GFX_SRC_COLOR; + case D3DBLEND_INVSRCCOLOR: return GFX_INV_SRC_COLOR; + case D3DBLEND_DESTCOLOR: return GFX_DST_COLOR; + case D3DBLEND_INVDESTCOLOR: return GFX_INV_DST_COLOR; + case D3DBLEND_SRCALPHA: return GFX_SRC_ALPHA; + case D3DBLEND_INVSRCALPHA: return GFX_INV_SRC_ALPHA; + default: ASSERTALWAYS("Unsupported D3D blending function!"); + } return GFX_ONE; +} + + + +// set blending operations +static void d3d_BlendFunc( GfxBlend eSrc, GfxBlend eDst) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + GfxBlend gfxSrc, gfxDst; + _D3DBLEND d3dSrc, d3dDst; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_SRCBLEND, (DWORD*)&d3dSrc); D3D_CHECKERROR(hr); + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_DESTBLEND, (DWORD*)&d3dDst); D3D_CHECKERROR(hr); + gfxSrc = BlendFromD3D(d3dSrc); + gfxDst = BlendFromD3D(d3dDst); + ASSERT( gfxSrc==GFX_eBlendSrc && gfxDst==GFX_eBlendDst); +#endif + // cached? + if( eSrc==GFX_eBlendSrc && eDst==GFX_eBlendDst && gap_bOptimizeStateChanges) return; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + if( eSrc!=GFX_eBlendSrc) { + _D3DBLEND d3dSrc = BlendToD3D(eSrc); + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, d3dSrc); + D3D_CHECKERROR(hr); + GFX_eBlendSrc = eSrc; + } + if( eDst!=GFX_eBlendDst) { + _D3DBLEND d3dDst = BlendToD3D(eDst); + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, d3dDst); + D3D_CHECKERROR(hr); + GFX_eBlendDst = eDst; + } + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_SetColorMask( ULONG ulColorMask) +{ + // only if supported + _ulCurrentColorMask = ulColorMask; // keep for Get...() + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + if( !(_pGfx->gl_ulFlags&GLF_D3D_COLORWRITES)) + { // emulate disabling of all channels + if( ulColorMask==0) { + d3d_EnableBlend(); + d3d_BlendFunc( GFX_ZERO, GFX_ONE); + } // done + return; + } + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // no emulation + ULONG ulBitMask = NONE; + if( (ulColorMask&CT_RMASK) == CT_RMASK) ulBitMask |= D3DCOLORWRITEENABLE_RED; + if( (ulColorMask&CT_GMASK) == CT_GMASK) ulBitMask |= D3DCOLORWRITEENABLE_GREEN; + if( (ulColorMask&CT_BMASK) == CT_BMASK) ulBitMask |= D3DCOLORWRITEENABLE_BLUE; + if( (ulColorMask&CT_AMASK) == CT_AMASK) ulBitMask |= D3DCOLORWRITEENABLE_ALPHA; + HRESULT hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_COLORWRITEENABLE, ulBitMask); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +__forceinline _D3DCMPFUNC CompToD3D( GfxComp eFunc) { + switch( eFunc) { + case GFX_NEVER: return D3DCMP_NEVER; + case GFX_LESS: return D3DCMP_LESS; + case GFX_LESS_EQUAL: return D3DCMP_LESSEQUAL; + case GFX_EQUAL: return D3DCMP_EQUAL; + case GFX_NOT_EQUAL: return D3DCMP_NOTEQUAL; + case GFX_GREATER_EQUAL: return D3DCMP_GREATEREQUAL; + case GFX_GREATER: return D3DCMP_GREATER; + case GFX_ALWAYS: return D3DCMP_ALWAYS; + default: ASSERTALWAYS("Invalid GFX compare function!"); + } return D3DCMP_ALWAYS; +} + +__forceinline GfxComp CompFromD3D( _D3DCMPFUNC d3dcFunc) { + switch( d3dcFunc) { + case D3DCMP_NEVER: return GFX_NEVER; + case D3DCMP_LESS: return GFX_LESS; + case D3DCMP_LESSEQUAL: return GFX_LESS_EQUAL; + case D3DCMP_EQUAL: return GFX_EQUAL; + case D3DCMP_NOTEQUAL: return GFX_NOT_EQUAL; + case D3DCMP_GREATEREQUAL: return GFX_GREATER_EQUAL; + case D3DCMP_GREATER: return GFX_GREATER; + case D3DCMP_ALWAYS: return GFX_ALWAYS; + default: ASSERTALWAYS("Invalid D3D compare function!"); + } return GFX_ALWAYS; +} + + + + +// set depth buffer compare mode +static void d3d_DepthFunc( GfxComp eFunc) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; + _D3DCMPFUNC d3dcFunc; +#ifndef NDEBUG + GfxComp gfxFunc; + hr = _pGfx->gl_pd3dDevice->GetRenderState( D3DRS_ZFUNC, (DWORD*)&d3dcFunc); + D3D_CHECKERROR(hr); + gfxFunc = CompFromD3D( d3dcFunc); + ASSERT( gfxFunc==GFX_eDepthFunc); +#endif + // cached? + if( eFunc==GFX_eDepthFunc && gap_bOptimizeStateChanges) return; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + d3dcFunc = CompToD3D(eFunc); + hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_ZFUNC, d3dcFunc); + D3D_CHECKERROR(hr); + GFX_eDepthFunc = eFunc; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +// set depth buffer range +static void d3d_DepthRange( FLOAT fMin, FLOAT fMax) +{ + // D3D doesn't allow 0 for max value (no comment!) + if( fMax<0.001f) fMax = 0.001f; + + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; + D3DVIEWPORT8 d3dViewport; +#ifndef NDEBUG + hr = _pGfx->gl_pd3dDevice->GetViewport( &d3dViewport); + ASSERT( d3dViewport.MinZ==GFX_fMinDepthRange && d3dViewport.MaxZ==GFX_fMaxDepthRange); +#endif + + // cached? + if( GFX_fMinDepthRange==fMin && GFX_fMaxDepthRange==fMax && gap_bOptimizeStateChanges) return; + GFX_fMinDepthRange = fMin; + GFX_fMaxDepthRange = fMax; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // get viewport + hr = _pGfx->gl_pd3dDevice->GetViewport( &d3dViewport); + D3D_CHECKERROR(hr); + // update depth range and set the viewport back + d3dViewport.MinZ = fMin; + d3dViewport.MaxZ = fMax; + hr = _pGfx->gl_pd3dDevice->SetViewport( &d3dViewport); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +static void d3d_CullFace( GfxFace eFace) +{ + // check consistency and face + ASSERT( eFace==GFX_FRONT || eFace==GFX_BACK || eFace==GFX_NONE); + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; + + // must (re)assign faces for front-face emulation purposes + GfxFace eFrontFace, eBackFace; + if( GFX_bFrontFace) { eFrontFace = GFX_FRONT; eBackFace = GFX_BACK; } + else { eFrontFace = GFX_BACK; eBackFace = GFX_FRONT; } + // cached? + if( gap_bOptimizeStateChanges) { + if( GFX_eCullFace==D3DCULL_NONE && eFace==GFX_NONE) return; + if( GFX_eCullFace==D3DCULL_CCW && eFace==eFrontFace) return; + if( GFX_eCullFace==D3DCULL_CW && eFace==eBackFace) return; + } + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + if( eFace==eFrontFace) hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW); + else if( eFace==eBackFace) hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW); + else hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE); + D3D_CHECKERROR(hr); + GFX_eCullFace = eFace; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_FrontFace( GfxFace eFace) +{ + // check consistency and face + ASSERT( eFace==GFX_CW || eFace==GFX_CCW); + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + // cached? + BOOL bFrontFace = (eFace==GFX_CCW); + if( !bFrontFace==!GFX_bFrontFace && gap_bOptimizeStateChanges) return; + + // must emulate this by toggling cull face + GFX_bFrontFace = bFrontFace; + if( GFX_eCullFace!=GFX_NONE) d3d_CullFace(GFX_eCullFace); +} + + + + +static void d3d_ClipPlane( const DOUBLE *pdViewPlane) +{ + // check API and plane + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D && pdViewPlane!=NULL); + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // convert to floats, keep and update + D3D_afClipPlane[0] = pdViewPlane[0]; + D3D_afClipPlane[1] = pdViewPlane[1]; + D3D_afClipPlane[2] = pdViewPlane[2]; + D3D_afClipPlane[3] = pdViewPlane[3]; + UpdateClipPlane_D3D(); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_SetTextureMatrix( const FLOAT *pfMatrix/*=NULL*/) +{ + // check API + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + HRESULT hr; + D3DTRANSFORMSTATETYPE tsMatrixNo = (D3DTRANSFORMSTATETYPE)(D3DTS_TEXTURE0 + GFX_iActiveTexUnit); + + if( pfMatrix!=NULL) { + hr = _pGfx->gl_pd3dDevice->SetTransform( tsMatrixNo, (_D3DMATRIX*)pfMatrix); + } else { + // load identity matrix + extern const D3DMATRIX GFX_d3dIdentityMatrix; + hr = _pGfx->gl_pd3dDevice->SetTransform( tsMatrixNo, &GFX_d3dIdentityMatrix); + } // check + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +static void d3d_SetViewMatrix( const FLOAT *pfMatrix/*=NULL*/) +{ + // check API + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; + + // cached? (only identity matrix) + if( pfMatrix==NULL && GFX_bViewMatrix==NONE && gap_bOptimizeStateChanges) return; + GFX_bViewMatrix = (pfMatrix!=NULL); + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + if( pfMatrix!=NULL) { + // need to keep it for clip plane + CopyLongs( (ULONG*)pfMatrix, (ULONG*)D3D_afViewMatrix, 16); + hr = _pGfx->gl_pd3dDevice->SetTransform( D3DTS_VIEW, (_D3DMATRIX*)D3D_afViewMatrix); + } else { + // load identity matrix + extern const D3DMATRIX GFX_d3dIdentityMatrix; + hr = _pGfx->gl_pd3dDevice->SetTransform( D3DTS_VIEW, &GFX_d3dIdentityMatrix); + } // check + D3D_CHECKERROR(hr); + // update clip plane if enabled + if( GFX_bClipPlane) UpdateClipPlane_D3D(); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_SetOrtho( const FLOAT fLeft, const FLOAT fRight, const FLOAT fTop, + const FLOAT fBottom, const FLOAT fNear, const FLOAT fFar, + const BOOL bSubPixelAdjust/*=FALSE*/) +{ + // check API and matrix type + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + + // cached? + if( GFX_fLastL==fLeft && GFX_fLastT==fTop && GFX_fLastN==fNear + && GFX_fLastR==fRight && GFX_fLastB==fBottom && GFX_fLastF==fFar && gap_bOptimizeStateChanges) return; + GFX_fLastL = fLeft; GFX_fLastT = fTop; GFX_fLastN = fNear; + GFX_fLastR = fRight; GFX_fLastB = fBottom; GFX_fLastF = fFar; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // adjust coords for sub-pixel precision + // generate ortho matrix (+1 is because of sub-pixel adjustment!) + FLOAT fAdj = bSubPixelAdjust ? 1 : 0; + const FLOAT fRpL=fRight+fLeft+fAdj; const FLOAT fRmL=fRight-fLeft; const FLOAT fFpN=fFar+fNear; + const FLOAT fTpB=fTop+fBottom+fAdj; const FLOAT fTmB=fTop-fBottom; const FLOAT fFmN=fFar-fNear; + const FLOAT afMatrix[16] = { 2/fRmL, 0, 0, 0, + 0, 2/fTmB, 0, 0, + 0, 0, -1/fFmN, 0, + -fRpL/fRmL, -fTpB/fTmB, -fNear/fFmN, 1 }; + HRESULT hr = _pGfx->gl_pd3dDevice->SetTransform( D3DTS_PROJECTION, (_D3DMATRIX*)afMatrix); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_SetFrustum( const FLOAT fLeft, const FLOAT fRight, + const FLOAT fTop, const FLOAT fBottom, + const FLOAT fNear, const FLOAT fFar) +{ + // check API + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + + // cached? + if( GFX_fLastL==-fLeft && GFX_fLastT==-fTop && GFX_fLastN==-fNear + && GFX_fLastR==-fRight && GFX_fLastB==-fBottom && GFX_fLastF==-fFar && gap_bOptimizeStateChanges) return; + GFX_fLastL = -fLeft; GFX_fLastT = -fTop; GFX_fLastN = -fNear; + GFX_fLastR = -fRight; GFX_fLastB = -fBottom; GFX_fLastF = -fFar; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // generate frustum matrix + const FLOAT fRpL=fRight+fLeft; const FLOAT fTpB=fTop+fBottom; const FLOAT fFpN=fFar+fNear; + const FLOAT fRmL=fRight-fLeft; const FLOAT fTmB=fTop-fBottom; const FLOAT fFmN=fFar-fNear; + const FLOAT afMatrix[4][4] = { + { 2*fNear/fRmL, 0, 0, 0 }, + { 0, 2*fNear/fTmB, 0, 0 }, + { fRpL/fRmL, fTpB/fTmB, -fFar/fFmN, -1 }, + { 0, 0, -fFar*fNear/fFmN, 0 } + }; // set it + HRESULT hr = _pGfx->gl_pd3dDevice->SetTransform( D3DTS_PROJECTION, (const _D3DMATRIX*)&afMatrix); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +static void d3d_PolygonMode( GfxPolyMode ePolyMode) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + HRESULT hr; + switch(ePolyMode) { + case GFX_POINT: hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_POINT); break; + case GFX_LINE: hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME); break; + case GFX_FILL: hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID); break; + default: ASSERTALWAYS("Wrong polygon mode!"); + } // check + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +// TEXTURE MANAGEMENT + + +static void d3d_SetTextureWrapping( enum GfxWrap eWrapU, enum GfxWrap eWrapV) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + // check wrapping consistency + D3DTEXTUREADDRESS d3dtaU, d3dtaV; + hr = _pGfx->gl_pd3dDevice->GetTextureStageState( GFX_iActiveTexUnit, D3DTSS_ADDRESSU, (ULONG*)&d3dtaU); D3D_CHECKERROR(hr); + hr = _pGfx->gl_pd3dDevice->GetTextureStageState( GFX_iActiveTexUnit, D3DTSS_ADDRESSV, (ULONG*)&d3dtaV); D3D_CHECKERROR(hr); + ASSERT( (d3dtaU==D3DTADDRESS_WRAP && _tpGlobal[GFX_iActiveTexUnit].tp_eWrapU==GFX_REPEAT) + || (d3dtaU==D3DTADDRESS_CLAMP && _tpGlobal[GFX_iActiveTexUnit].tp_eWrapU==GFX_CLAMP) + || (_tpGlobal[GFX_iActiveTexUnit].tp_eWrapU==0)); + ASSERT( (d3dtaV==D3DTADDRESS_WRAP && _tpGlobal[GFX_iActiveTexUnit].tp_eWrapV==GFX_REPEAT) + || (d3dtaV==D3DTADDRESS_CLAMP && _tpGlobal[GFX_iActiveTexUnit].tp_eWrapV==GFX_CLAMP) + || (_tpGlobal[GFX_iActiveTexUnit].tp_eWrapV==0)); +#endif + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // adjust only those that differ + if( _tpGlobal[GFX_iActiveTexUnit].tp_eWrapU!=eWrapU) { + D3DTEXTUREADDRESS d3dta = (eWrapU==GFX_REPEAT) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP; + hr = _pGfx->gl_pd3dDevice->SetTextureStageState( GFX_iActiveTexUnit, D3DTSS_ADDRESSU, d3dta); + D3D_CHECKERROR(hr); + _tpGlobal[GFX_iActiveTexUnit].tp_eWrapU = eWrapU; + } + if( _tpGlobal[GFX_iActiveTexUnit].tp_eWrapV!=eWrapV) { + D3DTEXTUREADDRESS d3dta = (eWrapV==GFX_REPEAT) ? D3DTADDRESS_WRAP : D3DTADDRESS_CLAMP; + hr = _pGfx->gl_pd3dDevice->SetTextureStageState( GFX_iActiveTexUnit, D3DTSS_ADDRESSV, d3dta); + D3D_CHECKERROR(hr); + _tpGlobal[GFX_iActiveTexUnit].tp_eWrapV = eWrapV; + } + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_SetTextureModulation( INDEX iScale) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + HRESULT hr; +#ifndef NDEBUG + INDEX iRet; + hr = _pGfx->gl_pd3dDevice->GetTextureStageState( GFX_iActiveTexUnit, D3DTSS_COLOROP, (DWORD*)&iRet); + D3D_CHECKERROR(hr); + if( iRet==D3DTOP_MODULATE2X) ASSERT( GFX_iTexModulation[GFX_iActiveTexUnit]==2); + else if( iRet==D3DTOP_MODULATE) ASSERT( GFX_iTexModulation[GFX_iActiveTexUnit]==1); + else ASSERT( iRet==D3DTOP_DISABLE); +#endif + + // cached? + ASSERT( iScale==1 || iScale==2); + if( GFX_iTexModulation[GFX_iActiveTexUnit]==iScale) return; + GFX_iTexModulation[GFX_iActiveTexUnit] = iScale; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // set only if texturing is enabled - will be auto-set at gfxEnableTexture + if( GFX_abTexture[GFX_iActiveTexUnit]) { + D3DTEXTUREOP d3dTexOp = (iScale==2) ? D3DTOP_MODULATE2X : D3DTOP_MODULATE; + hr = _pGfx->gl_pd3dDevice->SetTextureStageState( GFX_iActiveTexUnit, D3DTSS_COLOROP, d3dTexOp); + D3D_CHECKERROR(hr); + } + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_GenerateTexture( ULONG &ulTexObject) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + _sfStats.StartTimer(CStatForm::STI_BINDTEXTURE); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // generate one dummy texture that'll be entirely replaced upon 1st upload + HRESULT hr = _pGfx->gl_pd3dDevice->CreateTexture( 1, 1, 0, 0, (D3DFORMAT)TS.ts_tfRGBA8, D3DPOOL_MANAGED, (LPDIRECT3DTEXTURE8*)&ulTexObject); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_BINDTEXTURE); + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + +// unbind texture from API +static void d3d_DeleteTexture( ULONG &ulTexObject) +{ + // skip if already unbound + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + if( ulTexObject==NONE) return; + + _sfStats.StartTimer(CStatForm::STI_BINDTEXTURE); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + D3DRELEASE( (LPDIRECT3DTEXTURE8&)ulTexObject, TRUE); + ulTexObject = NONE; + + _sfStats.StopTimer(CStatForm::STI_BINDTEXTURE); + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +// VERTEX ARRAYS + + +static void d3d_SetVertexArray( GFXVertex4 *pvtx, INDEX ctVtx) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + ASSERT( ctVtx>0 && pvtx!=NULL && GFX_iActiveTexUnit==0); + GFX_ctVertices = ctVtx; + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + SetVertexArray_D3D( 0, (ULONG*)pvtx); // type 0 = vertices + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_SetNormalArray( GFXNormal *pnor) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + ASSERT( pnor!=NULL); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + SetVertexArray_D3D( 1, (ULONG*)pnor); // type 1 = normals + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_SetColorArray( GFXColor *pcol) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + ASSERT( pcol!=NULL); + d3d_EnableColorArray(); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + SetVertexArray_D3D( 2, (ULONG*)pcol); // type 2 = colors + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_SetTexCoordArray( GFXTexCoord *ptex, BOOL b4/*=FALSE*/) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + ASSERT( ptex!=NULL); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // type 3 = regular texture coordinates; type 4 = projective texture coordinates + SetVertexArray_D3D( b4?4:3, (ULONG*)ptex); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_SetConstantColor( COLOR col) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + d3d_DisableColorArray(); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + const ULONG d3dColor = rgba2argb(col); + HRESULT hr = _pGfx->gl_pd3dDevice->SetRenderState( D3DRS_AMBIENT, d3dColor); + D3D_CHECKERROR(hr); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void d3d_DrawElements( INDEX ctElem, INDEX *pidx) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); +#ifndef NDEBUG + // check if all indices are inside lock count (or smaller than 65536) + if( pidx!=NULL) for( INDEX i=0; igl_ctTotalTriangles += ctElem/3; // for profiling + + ASSERT( pidx!=NULL); + extern void DrawElements_D3D( INDEX ctElem, INDEX *pidx); + DrawElements_D3D( ctElem, pidx); + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +// force finish of API rendering queue +static void d3d_Finish(void) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // must "emulate" this by reading from back buffer :( + HRESULT hr; + D3DLOCKED_RECT rectLocked; + LPDIRECT3DSURFACE8 pBackBuffer; + // fetch back buffer (different for full screen and windowed mode) + const BOOL bFullScreen = _pGfx->gl_ulFlags & GLF_FULLSCREEN; + const RECT rectToLock = { 0,0, 1,1 }; + if( bFullScreen) hr = _pGfx->gl_pd3dDevice->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer); + else hr = _pGfx->gl_pvpActive->vp_pSwapChain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer); + if( hr==D3D_OK) { + hr = pBackBuffer->LockRect( &rectLocked, &rectToLock, D3DLOCK_READONLY); + if( hr==D3D_OK) pBackBuffer->UnlockRect(); + D3DRELEASE( pBackBuffer, TRUE); + } + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + + +static void d3d_LockArrays(void) +{ + // only for OpenGL + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + ASSERT( GFX_ctVertices>0 && !_bCVAReallyLocked); +} + + +// SPECIAL FUNCTIONS FOR Direct3D ONLY ! + + +// set D3D vertex shader only if different than last time +extern void d3dSetVertexShader( DWORD dwHandle) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_D3D); + if( _pGfx->gl_dwVertexShader==dwHandle) return; + HRESULT hr = _pGfx->gl_pd3dDevice->SetVertexShader(dwHandle); + D3D_CHECKERROR(hr); + _pGfx->gl_dwVertexShader = dwHandle; +} + +#endif // SE1_D3D \ No newline at end of file diff --git a/Sources/Engine/Graphics/Gfx_wrapper_OpenGL.cpp b/Sources/Engine/Graphics/Gfx_wrapper_OpenGL.cpp new file mode 100644 index 0000000..cb4e2ec --- /dev/null +++ b/Sources/Engine/Graphics/Gfx_wrapper_OpenGL.cpp @@ -0,0 +1,1159 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + + +// ENABLE/DISABLE FUNCTIONS + + +static void ogl_EnableTexture(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_TEXTURE_2D); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_abTexture[GFX_iActiveTexUnit]); +#endif + + // cached? + if( GFX_abTexture[GFX_iActiveTexUnit] && gap_bOptimizeStateChanges) return; + GFX_abTexture[GFX_iActiveTexUnit] = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglEnable(GL_TEXTURE_2D); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void ogl_DisableTexture(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_TEXTURE_2D); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_abTexture[GFX_iActiveTexUnit]); +#endif + + // cached? + if( !GFX_abTexture[GFX_iActiveTexUnit] && gap_bOptimizeStateChanges) return; + GFX_abTexture[GFX_iActiveTexUnit] = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDisable(GL_TEXTURE_2D); + pglDisableClientState(GL_TEXTURE_COORD_ARRAY); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void ogl_EnableDepthTest(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_DEPTH_TEST); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bDepthTest); +#endif + // cached? + if( GFX_bDepthTest && gap_bOptimizeStateChanges) return; + GFX_bDepthTest = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglEnable( GL_DEPTH_TEST); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + +static void ogl_DisableDepthTest(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_DEPTH_TEST); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bDepthTest); +#endif + + // cached? + if( !GFX_bDepthTest && gap_bOptimizeStateChanges) return; + GFX_bDepthTest = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDisable(GL_DEPTH_TEST); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + +static void ogl_EnableDepthBias(void) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglEnable( GL_POLYGON_OFFSET_POINT); + pglEnable( GL_POLYGON_OFFSET_LINE); + pglEnable( GL_POLYGON_OFFSET_FILL); + pglPolygonOffset( -1.0f, -2.0f); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + +static void ogl_DisableDepthBias(void) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDisable( GL_POLYGON_OFFSET_POINT); + pglDisable( GL_POLYGON_OFFSET_LINE); + pglDisable( GL_POLYGON_OFFSET_FILL); + pglPolygonOffset( 0.0f, 0.0f); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void ogl_EnableDepthWrite(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + pglGetIntegerv( GL_DEPTH_WRITEMASK, (GLint*)&bRes); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bDepthWrite); +#endif + + // cached? + if( GFX_bDepthWrite && gap_bOptimizeStateChanges) return; + GFX_bDepthWrite = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDepthMask(GL_TRUE); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void ogl_DisableDepthWrite(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + pglGetIntegerv( GL_DEPTH_WRITEMASK, (GLint*)&bRes); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bDepthWrite); +#endif + + // cached? + if( !GFX_bDepthWrite && gap_bOptimizeStateChanges) return; + GFX_bDepthWrite = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDepthMask(GL_FALSE); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void ogl_EnableDither(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_DITHER); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bDithering); +#endif + + // cached? + if( GFX_bDithering && gap_bOptimizeStateChanges) return; + GFX_bDithering = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglEnable(GL_DITHER); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void ogl_DisableDither(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_DITHER); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bDithering); +#endif + + // cached? + if( !GFX_bDithering && gap_bOptimizeStateChanges) return; + GFX_bDithering = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDisable(GL_DITHER); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void ogl_EnableAlphaTest(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_ALPHA_TEST); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bAlphaTest); +#endif + + // cached? + if( GFX_bAlphaTest && gap_bOptimizeStateChanges) return; + GFX_bAlphaTest = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglEnable(GL_ALPHA_TEST); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void ogl_DisableAlphaTest(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_ALPHA_TEST); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bAlphaTest); +#endif + + // cached? + if( !GFX_bAlphaTest && gap_bOptimizeStateChanges) return; + GFX_bAlphaTest = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDisable(GL_ALPHA_TEST); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void ogl_EnableBlend(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_BLEND); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bBlending); +#endif + // cached? + if( GFX_bBlending && gap_bOptimizeStateChanges) return; + GFX_bBlending = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglEnable( GL_BLEND); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); + + // adjust dithering + if( gap_iDithering==2) ogl_EnableDither(); + else ogl_DisableDither(); +} + + + +static void ogl_DisableBlend(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_BLEND); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bBlending); +#endif + + // cached? + if( !GFX_bBlending && gap_bOptimizeStateChanges) return; + GFX_bBlending = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDisable(GL_BLEND); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); + + // adjust dithering + if( gap_iDithering==0) ogl_DisableDither(); + else ogl_EnableDither(); +} + + + +static void ogl_EnableClipping(void) +{ + // only if supported + if( !(_pGfx->gl_ulFlags&GLF_EXT_CLIPHINT)) return; + + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + pglGetIntegerv( GL_CLIP_VOLUME_CLIPPING_HINT_EXT, (GLint*)&bRes); + bRes = (bRes==GL_FASTEST) ? FALSE : TRUE; + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bClipping); +#endif + + // cached? + if( GFX_bClipping && gap_bOptimizeStateChanges) return; + GFX_bClipping = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglHint( GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_DONT_CARE); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void ogl_DisableClipping(void) +{ + // only if allowed and supported + if( gap_iOptimizeClipping<2 || !(_pGfx->gl_ulFlags&GLF_EXT_CLIPHINT)) return; + + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + pglGetIntegerv( GL_CLIP_VOLUME_CLIPPING_HINT_EXT, (GLint*)&bRes); + bRes = (bRes==GL_FASTEST) ? FALSE : TRUE; + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bClipping); +#endif + + // cached? + if( !GFX_bClipping && gap_bOptimizeStateChanges) return; + GFX_bClipping = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglHint( GL_CLIP_VOLUME_CLIPPING_HINT_EXT, GL_FASTEST); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +static void ogl_EnableClipPlane(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_CLIP_PLANE0); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bClipPlane); +#endif + // cached? + if( GFX_bClipPlane && gap_bOptimizeStateChanges) return; + GFX_bClipPlane = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglEnable( GL_CLIP_PLANE0); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +static void ogl_DisableClipPlane(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_CLIP_PLANE0); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bClipPlane); +#endif + // cached? + if( !GFX_bClipPlane && gap_bOptimizeStateChanges) return; + GFX_bClipPlane = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDisable(GL_CLIP_PLANE0); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// enable usage of color array for subsequent rendering +static void ogl_EnableColorArray(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_COLOR_ARRAY); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bColorArray); +#endif + + // cached? + if( GFX_bColorArray && gap_bOptimizeStateChanges) return; + GFX_bColorArray = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglEnableClientState(GL_COLOR_ARRAY); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// enable usage of constant color for subsequent rendering +static void ogl_DisableColorArray(void) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_COLOR_ARRAY); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bColorArray); +#endif + + // cached? + if( !GFX_bColorArray && gap_bOptimizeStateChanges) return; + GFX_bColorArray = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDisableClientState(GL_COLOR_ARRAY); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// enable truform rendering +static void ogl_EnableTruform(void) +{ + // skip if Truform isn't set + if( truform_iLevel<1) return; + + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_PN_TRIANGLES_ATI); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bTruform); +#endif + + if( GFX_bTruform && gap_bOptimizeStateChanges) return; + GFX_bTruform = TRUE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglEnable( GL_PN_TRIANGLES_ATI); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// disable truform rendering +static void ogl_DisableTruform(void) +{ + // skip if Truform isn't set + if( truform_iLevel<1) return; + + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + BOOL bRes; + bRes = pglIsEnabled(GL_PN_TRIANGLES_ATI); + OGL_CHECKERROR; + ASSERT( !bRes == !GFX_bTruform); +#endif + + if( !GFX_bTruform && gap_bOptimizeStateChanges) return; + GFX_bTruform = FALSE; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDisable( GL_PN_TRIANGLES_ATI); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// helper for blending operation function +__forceinline GLenum BlendToOGL( GfxBlend eFunc) { + switch( eFunc) { + case GFX_ZERO: return GL_ZERO; + case GFX_ONE: return GL_ONE; + case GFX_SRC_COLOR: return GL_SRC_COLOR; + case GFX_INV_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR; + case GFX_DST_COLOR: return GL_DST_COLOR; + case GFX_INV_DST_COLOR: return GL_ONE_MINUS_DST_COLOR; + case GFX_SRC_ALPHA: return GL_SRC_ALPHA; + case GFX_INV_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA; + default: ASSERTALWAYS("Invalid GFX blending function!"); + } return GL_ONE; +} + +__forceinline GfxBlend BlendFromOGL( GLenum gFunc) { + switch( gFunc) { + case GL_ZERO: return GFX_ZERO; + case GL_ONE: return GFX_ONE; + case GL_SRC_COLOR: return GFX_SRC_COLOR; + case GL_ONE_MINUS_SRC_COLOR: return GFX_INV_SRC_COLOR; + case GL_DST_COLOR: return GFX_DST_COLOR; + case GL_ONE_MINUS_DST_COLOR: return GFX_INV_DST_COLOR; + case GL_SRC_ALPHA: return GFX_SRC_ALPHA; + case GL_ONE_MINUS_SRC_ALPHA: return GFX_INV_SRC_ALPHA; + default: ASSERTALWAYS("Unsupported OGL blending function!"); + } return GFX_ONE; +} + + +// set blending operations +static void ogl_BlendFunc( GfxBlend eSrc, GfxBlend eDst) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + GLenum gleSrc, gleDst; +#ifndef NDEBUG + GfxBlend gfxSrc, gfxDst; + pglGetIntegerv( GL_BLEND_SRC, (GLint*)&gleSrc); + pglGetIntegerv( GL_BLEND_DST, (GLint*)&gleDst); + OGL_CHECKERROR; + gfxSrc = BlendFromOGL(gleSrc); + gfxDst = BlendFromOGL(gleDst); + ASSERT( gfxSrc==GFX_eBlendSrc && gfxDst==GFX_eBlendDst); +#endif + // cached? + if( eSrc==GFX_eBlendSrc && eDst==GFX_eBlendDst && gap_bOptimizeStateChanges) return; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + gleSrc = BlendToOGL(eSrc); + gleDst = BlendToOGL(eDst); + pglBlendFunc( gleSrc, gleDst); + OGL_CHECKERROR; + // done + GFX_eBlendSrc = eSrc; + GFX_eBlendDst = eDst; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// color buffer writing enable +static void ogl_SetColorMask( ULONG ulColorMask) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + _ulCurrentColorMask = ulColorMask; // keep for Get...() + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + const BOOL bR = (ulColorMask&CT_RMASK) == CT_RMASK; + const BOOL bG = (ulColorMask&CT_GMASK) == CT_GMASK; + const BOOL bB = (ulColorMask&CT_BMASK) == CT_BMASK; + const BOOL bA = (ulColorMask&CT_AMASK) == CT_AMASK; + pglColorMask( bR,bG,bB,bA); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// helper for depth compare function +__forceinline GLenum CompToOGL( GfxComp eFunc) { + switch( eFunc) { + case GFX_NEVER: return GL_NEVER; + case GFX_LESS: return GL_LESS; + case GFX_LESS_EQUAL: return GL_LEQUAL; + case GFX_EQUAL: return GL_EQUAL; + case GFX_NOT_EQUAL: return GL_NOTEQUAL; + case GFX_GREATER_EQUAL: return GL_GEQUAL; + case GFX_GREATER: return GL_GREATER; + case GFX_ALWAYS: return GL_ALWAYS; + default: ASSERTALWAYS("Invalid GFX compare function!"); + } return GL_ALWAYS; +} + +__forceinline GfxComp CompFromOGL( GLenum gFunc) { + switch( gFunc) { + case GL_NEVER: return GFX_NEVER; + case GL_LESS: return GFX_LESS; + case GL_LEQUAL: return GFX_LESS_EQUAL; + case GL_EQUAL: return GFX_EQUAL; + case GL_NOTEQUAL: return GFX_NOT_EQUAL; + case GL_GEQUAL: return GFX_GREATER_EQUAL; + case GL_GREATER: return GFX_GREATER; + case GL_ALWAYS: return GFX_ALWAYS; + default: ASSERTALWAYS("Invalid OGL compare function!"); + } return GFX_ALWAYS; +} + + + +// set depth buffer compare mode +static void ogl_DepthFunc( GfxComp eFunc) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + GLenum gleFunc; +#ifndef NDEBUG + GfxComp gfxFunc; + pglGetIntegerv( GL_DEPTH_FUNC, (GLint*)&gleFunc); + OGL_CHECKERROR; + gfxFunc = CompFromOGL( gleFunc); + ASSERT( gfxFunc==GFX_eDepthFunc); +#endif + // cached? + if( eFunc==GFX_eDepthFunc && gap_bOptimizeStateChanges) return; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + gleFunc = CompToOGL(eFunc); + pglDepthFunc(gleFunc); + OGL_CHECKERROR; + GFX_eDepthFunc = eFunc; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// set depth buffer range +static void ogl_DepthRange( FLOAT fMin, FLOAT fMax) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + FLOAT fDepths[2]; + pglGetFloatv( GL_DEPTH_RANGE,(GLfloat*)&fDepths); + OGL_CHECKERROR; + ASSERT( fDepths[0]==GFX_fMinDepthRange && fDepths[1]==GFX_fMaxDepthRange); +#endif + + // cached? + if( GFX_fMinDepthRange==fMin && GFX_fMaxDepthRange==fMax && gap_bOptimizeStateChanges) return; + GFX_fMinDepthRange = fMin; + GFX_fMaxDepthRange = fMax; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDepthRange( fMin, fMax); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// set face culling +static void ogl_CullFace( GfxFace eFace) +{ + // check consistency and face + ASSERT( eFace==GFX_FRONT || eFace==GFX_BACK || eFace==GFX_NONE); + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + GLenum gleCull; + BOOL bRes = pglIsEnabled(GL_CULL_FACE); + pglGetIntegerv( GL_CULL_FACE_MODE, (GLint*)&gleCull); + OGL_CHECKERROR; + ASSERT( (bRes==GL_FALSE && GFX_eCullFace==GFX_NONE) + || (bRes==GL_TRUE && gleCull==GL_FRONT && GFX_eCullFace==GFX_FRONT) + || (bRes==GL_TRUE && gleCull==GL_BACK && GFX_eCullFace==GFX_BACK)); +#endif + // cached? + if( GFX_eCullFace==eFace && gap_bOptimizeStateChanges) return; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + if( eFace==GFX_FRONT) { + if( GFX_eCullFace==GFX_NONE) pglEnable(GL_CULL_FACE); + pglCullFace(GL_FRONT); + } else if( eFace==GFX_BACK) { + if( GFX_eCullFace==GFX_NONE) pglEnable(GL_CULL_FACE); + pglCullFace(GL_BACK); + } else { + pglDisable(GL_CULL_FACE); + } + OGL_CHECKERROR; + GFX_eCullFace = eFace; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// set front face +static void ogl_FrontFace( GfxFace eFace) +{ + // check consistency and face + ASSERT( eFace==GFX_CW || eFace==GFX_CCW); + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + GLenum gleFace; + pglGetIntegerv( GL_FRONT_FACE, (GLint*)&gleFace); + OGL_CHECKERROR; + ASSERT( (gleFace==GL_CCW && GFX_bFrontFace) + || (gleFace==GL_CW && !GFX_bFrontFace)); +#endif + // cached? + BOOL bFrontFace = (eFace==GFX_CCW); + if( !bFrontFace==!GFX_bFrontFace && gap_bOptimizeStateChanges) return; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + if( eFace==GFX_CCW) { + pglFrontFace( GL_CCW); + } else { + pglFrontFace( GL_CW); + } + OGL_CHECKERROR; + GFX_bFrontFace = bFrontFace; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// set custom clip plane +static void ogl_ClipPlane( const DOUBLE *pdViewPlane) +{ + // check API and plane + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL && pdViewPlane!=NULL); + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglClipPlane( GL_CLIP_PLANE0, pdViewPlane); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// set texture matrix +static void ogl_SetTextureMatrix( const FLOAT *pfMatrix/*=NULL*/) +{ + // check API + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // set matrix + pglMatrixMode(GL_TEXTURE); + if( pfMatrix!=NULL) pglLoadMatrixf(pfMatrix); + else pglLoadIdentity(); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +// set view matrix +static void ogl_SetViewMatrix( const FLOAT *pfMatrix/*=NULL*/) +{ + // check API + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + + // cached? (only identity matrix) + if( pfMatrix==NULL && GFX_bViewMatrix==NONE && gap_bOptimizeStateChanges) return; + GFX_bViewMatrix = (pfMatrix!=NULL); + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // set matrix + pglMatrixMode( GL_MODELVIEW); + if( pfMatrix!=NULL) pglLoadMatrixf(pfMatrix); + else pglLoadIdentity(); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// set orthographic matrix +static void ogl_SetOrtho( const FLOAT fLeft, const FLOAT fRight, const FLOAT fTop, + const FLOAT fBottom, const FLOAT fNear, const FLOAT fFar, + const BOOL bSubPixelAdjust/*=FALSE*/) +{ + // check API and matrix type + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + + // cached? + if( GFX_fLastL==fLeft && GFX_fLastT==fTop && GFX_fLastN==fNear + && GFX_fLastR==fRight && GFX_fLastB==fBottom && GFX_fLastF==fFar && gap_bOptimizeStateChanges) return; + GFX_fLastL = fLeft; GFX_fLastT = fTop; GFX_fLastN = fNear; + GFX_fLastR = fRight; GFX_fLastB = fBottom; GFX_fLastF = fFar; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // set matrix + pglMatrixMode( GL_PROJECTION); + pglLoadIdentity(); + pglOrtho( fLeft, fRight, fBottom, fTop, fNear, fFar); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// set frustrum matrix +static void ogl_SetFrustum( const FLOAT fLeft, const FLOAT fRight, + const FLOAT fTop, const FLOAT fBottom, + const FLOAT fNear, const FLOAT fFar) +{ + // check API + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + + // cached? + if( GFX_fLastL==-fLeft && GFX_fLastT==-fTop && GFX_fLastN==-fNear + && GFX_fLastR==-fRight && GFX_fLastB==-fBottom && GFX_fLastF==-fFar && gap_bOptimizeStateChanges) return; + GFX_fLastL = -fLeft; GFX_fLastT = -fTop; GFX_fLastN = -fNear; + GFX_fLastR = -fRight; GFX_fLastB = -fBottom; GFX_fLastF = -fFar; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + // set matrix + pglMatrixMode( GL_PROJECTION); + pglLoadIdentity(); + pglFrustum( fLeft, fRight, fBottom, fTop, fNear, fFar); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// set polygon mode (point, line or fill) +static void ogl_PolygonMode( GfxPolyMode ePolyMode) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + switch(ePolyMode) { + case GFX_POINT: pglPolygonMode( GL_FRONT_AND_BACK, GL_POINT); break; + case GFX_LINE: pglPolygonMode( GL_FRONT_AND_BACK, GL_LINE); break; + case GFX_FILL: pglPolygonMode( GL_FRONT_AND_BACK, GL_FILL); break; + default: ASSERTALWAYS("Wrong polygon mode!"); + } // check + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +// TEXTURE MANAGEMENT + + +// set texture wrapping mode +static void ogl_SetTextureWrapping( enum GfxWrap eWrapU, enum GfxWrap eWrapV) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + // check texture unit consistency + GLint gliRet; + pglGetIntegerv( GL_ACTIVE_TEXTURE_ARB, &gliRet); + ASSERT( GFX_iActiveTexUnit==(gliRet-GL_TEXTURE0_ARB)); + pglGetIntegerv( GL_CLIENT_ACTIVE_TEXTURE_ARB, &gliRet); + ASSERT( GFX_iActiveTexUnit==(gliRet-GL_TEXTURE0_ARB)); +#endif + + _tpGlobal[GFX_iActiveTexUnit].tp_eWrapU = eWrapU; + _tpGlobal[GFX_iActiveTexUnit].tp_eWrapV = eWrapV; +} + + + +// set texture modulation mode +static void ogl_SetTextureModulation( INDEX iScale) +{ + // check consistency + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + // check current modulation + GLint iRet; + pglGetTexEnviv( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &iRet); + ASSERT( (GFX_iTexModulation[GFX_iActiveTexUnit]==1 && iRet==GL_MODULATE) + || (GFX_iTexModulation[GFX_iActiveTexUnit]==2 && iRet==GL_COMBINE_EXT)); + OGL_CHECKERROR; +#endif + + // cached? + ASSERT( iScale==1 || iScale==2); + if( GFX_iTexModulation[GFX_iActiveTexUnit]==iScale) return; + GFX_iTexModulation[GFX_iActiveTexUnit] = iScale; + + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + if( iScale==2) { + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); + pglTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); + pglTexEnvf( GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); + } else { + pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + } OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// generate texture for API +static void ogl_GenerateTexture( ULONG &ulTexObject) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + _sfStats.StartTimer(CStatForm::STI_BINDTEXTURE); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglGenTextures( 1, (GLuint*)&ulTexObject); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_BINDTEXTURE); + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// unbind texture from API +static void ogl_DeleteTexture( ULONG &ulTexObject) +{ + // skip if already unbound + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + if( ulTexObject==NONE) return; + + _sfStats.StartTimer(CStatForm::STI_BINDTEXTURE); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDeleteTextures( 1, (GLuint*)&ulTexObject); + ulTexObject = NONE; + + _sfStats.StopTimer(CStatForm::STI_BINDTEXTURE); + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// VERTEX ARRAYS + + +// prepare vertex array for API +static void ogl_SetVertexArray( GFXVertex4 *pvtx, INDEX ctVtx) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + ASSERT( ctVtx>0 && pvtx!=NULL && GFX_iActiveTexUnit==0); + GFX_ctVertices = ctVtx; + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglDisableClientState( GL_TEXTURE_COORD_ARRAY); + pglDisableClientState( GL_COLOR_ARRAY); + pglDisableClientState( GL_NORMAL_ARRAY); + ASSERT( !pglIsEnabled( GL_TEXTURE_COORD_ARRAY)); + ASSERT( !pglIsEnabled( GL_COLOR_ARRAY)); + ASSERT( !pglIsEnabled( GL_NORMAL_ARRAY)); + ASSERT( pglIsEnabled( GL_VERTEX_ARRAY)); + pglVertexPointer( 3, GL_FLOAT, 16, pvtx); + OGL_CHECKERROR; + GFX_bColorArray = FALSE; // mark that color array has been disabled (because of potential LockArrays) + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// prepare normal array for API +static void ogl_SetNormalArray( GFXNormal *pnor) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + ASSERT( pnor!=NULL); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglEnableClientState(GL_NORMAL_ARRAY); + ASSERT( pglIsEnabled(GL_NORMAL_ARRAY)); + pglNormalPointer( GL_FLOAT, 16, pnor); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// prepare color array for API (and force rendering with color array!) +static void ogl_SetColorArray( GFXColor *pcol) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + ASSERT( pcol!=NULL); + ogl_EnableColorArray(); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglColorPointer( 4, GL_UNSIGNED_BYTE, 0, pcol); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// prepare texture coordinates array for API +static void ogl_SetTexCoordArray( GFXTexCoord *ptex, BOOL b4/*=FALSE*/) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + ASSERT( ptex!=NULL); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglEnableClientState(GL_TEXTURE_COORD_ARRAY); + ASSERT( pglIsEnabled(GL_TEXTURE_COORD_ARRAY)); + pglTexCoordPointer( b4?4:2, GL_FLOAT, 0, ptex); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// set constant color (and force rendering w/o color array!) +static void ogl_SetConstantColor( COLOR col) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + ogl_DisableColorArray(); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + glCOLOR(col); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// draw prepared arrays +static void ogl_DrawElements( INDEX ctElem, INDEX *pidx) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); +#ifndef NDEBUG + // check if all indices are inside lock count (or smaller than 65536) + if( pidx!=NULL) for( INDEX i=0; igl_ctTotalTriangles += ctElem/3; // for profiling + + // arrays or elements + if( pidx==NULL) pglDrawArrays( GL_QUADS, 0, ctElem); + else pglDrawElements( GL_TRIANGLES, ctElem, GL_UNSIGNED_INT, pidx); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + +// force finish of API rendering queue +static void ogl_Finish(void) +{ + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + _sfStats.StartTimer(CStatForm::STI_GFXAPI); + + pglFinish(); + OGL_CHECKERROR; + + _sfStats.StopTimer(CStatForm::STI_GFXAPI); +} + + + + +// routines for locking and unlocking compiled vertex arrays +static void ogl_LockArrays(void) +{ + // only if supported + ASSERT( _pGfx->gl_eCurrentAPI==GAT_OGL); + ASSERT( GFX_ctVertices>0 && !_bCVAReallyLocked); + if( !(_pGfx->gl_ulFlags&GLF_EXT_COMPILEDVERTEXARRAY)) return; + pglLockArraysEXT( 0, GFX_ctVertices); + OGL_CHECKERROR; + _bCVAReallyLocked = TRUE; +} diff --git a/Sources/Engine/Graphics/Graphics.cpp b/Sources/Engine/Graphics/Graphics.cpp new file mode 100644 index 0000000..f4c2cf5 --- /dev/null +++ b/Sources/Engine/Graphics/Graphics.cpp @@ -0,0 +1,1629 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + +extern INDEX tex_bProgressiveFilter; // filter mipmaps in creation time (not afterwards) + + +// returns number of mip-maps to skip from original texture +INDEX ClampTextureSize( PIX pixClampSize, PIX pixClampDimension, PIX pixSizeU, PIX pixSizeV) +{ + __int64 pixMaxSize = (__int64)pixSizeU * (__int64)pixSizeV; + PIX pixMaxDimension = Max( pixSizeU, pixSizeV); + INDEX ctSkipMips = 0; + while( (pixMaxSize>pixClampSize || pixMaxDimension>pixClampDimension) && pixMaxDimension>1) { + ctSkipMips++; + pixMaxDimension >>=1; + pixMaxSize >>=2; + } + return ctSkipMips; +} + + +// retrives memory offset of a specified mip-map or a size of all mip-maps (IN PIXELS!) +// (zero offset means first, i.e. largest mip-map) +PIX GetMipmapOffset( INDEX iMipLevel, PIX pixWidth, PIX pixHeight) +{ + PIX pixTexSize = 0; + PIX pixMipSize = pixWidth*pixHeight; + INDEX iMips = GetNoOfMipmaps( pixWidth, pixHeight); + iMips = Min( iMips, iMipLevel); + while( iMips>0) { + pixTexSize +=pixMipSize; + pixMipSize>>=2; + iMips--; + } + return pixTexSize; +} + + +// return offset, pointer and dimensions of mipmap of specified size inside texture or shadowmap mipmaps +INDEX GetMipmapOfSize( PIX pixWantedSize, ULONG *&pulFrame, PIX &pixWidth, PIX &pixHeight) +{ + INDEX iMipOffset = 0; + while( pixWidth>1 && pixHeight>1) { + const PIX pixCurrentSize = pixWidth*pixHeight; + if( pixCurrentSize <= pixWantedSize) break; // found + pulFrame += pixCurrentSize; + pixWidth >>=1; + pixHeight>>=1; + iMipOffset++; + } // done + return iMipOffset; +} + + +// adds 8-bit opaque alpha channel to 24-bit bitmap (in place supported) +void AddAlphaChannel( UBYTE *pubSrcBitmap, ULONG *pulDstBitmap, PIX pixSize, UBYTE *pubAlphaBitmap) +{ + UBYTE ubR,ubG,ubB, ubA=255; + // loop backwards thru all bitmap pixels + for( INDEX iPix=(pixSize-1); iPix>=0; iPix--) { + ubR = pubSrcBitmap[iPix*3 +0]; + ubG = pubSrcBitmap[iPix*3 +1]; + ubB = pubSrcBitmap[iPix*3 +2]; + if( pubAlphaBitmap!=NULL) ubA = pubAlphaBitmap[iPix]; + else ubA = 255; // for the sake of forced RGBA internal formats! + pulDstBitmap[iPix] = ByteSwap( RGBAToColor( ubR,ubG,ubB, ubA)); + } +} + +// removes 8-bit alpha channel from 32-bit bitmap (in place supported) +void RemoveAlphaChannel( ULONG *pulSrcBitmap, UBYTE *pubDstBitmap, PIX pixSize) +{ + UBYTE ubR,ubG,ubB; + // loop thru all bitmap pixels + for( INDEX iPix=0; iPix=0 && iFlipType<4); + // no flipping ? + PIX pixSize = pixWidth*pixHeight; + if( iFlipType==0) { + // copy bitmap only if needed + INDEX ctBPP = (bAlphaChannel ? 4 : 3); + if( pubSrc!=pubDst) memcpy( pubDst, pubSrc, pixSize*ctBPP); + return; + } + + // prepare images without alpha channels + ULONG *pulNew = NULL; + ULONG *pulNewSrc = (ULONG*)pubSrc; + ULONG *pulNewDst = (ULONG*)pubDst; + if( !bAlphaChannel) { + pulNew = (ULONG*)AllocMemory( pixSize *BYTES_PER_TEXEL); + AddAlphaChannel( pubSrc, pulNew, pixSize); + pulNewSrc = pulNew; + pulNewDst = pulNew; + } + + // prepare half-width and half-height rounded + const PIX pixHalfWidth = (pixWidth+1) /2; + const PIX pixHalfHeight = (pixHeight+1)/2; + + // flip horizontal + if( iFlipType==2 || iFlipType==3) + { // for each row + for( INDEX iRow=0; iRow1 && pixHeight>1); + ASSERT( pixWidth == 1L<>=1; + pixHeight>>=1; + + if( bBilinear) // type of filtering? + { // BILINEAR + __asm { + pxor mm0,mm0 + mov ebx,D [pixWidth] + mov esi,D [pulSrcMipmap] + mov edi,D [pulDstMipmap] + mov edx,D [pixHeight] +rowLoop: + mov ecx,D [pixWidth] +pixLoopN: + movd mm1,D [esi+ 0] // up-left + movd mm2,D [esi+ 4] // up-right + movd mm3,D [esi+ ebx*8 +0] // down-left + movd mm4,D [esi+ ebx*8 +4] // down-right + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + punpcklbw mm3,mm0 + punpcklbw mm4,mm0 + paddw mm1,mm2 + paddw mm1,mm3 + paddw mm1,mm4 + paddw mm1,Q [mmRounder] + psrlw mm1,2 + packuswb mm1,mm0 + movd D [edi],mm1 + // advance to next pixel + add esi,4*2 + add edi,4 + dec ecx + jnz pixLoopN + // advance to next row + lea esi,[esi+ ebx*8] // skip one row in source mip-map + dec edx + jnz rowLoop + emms + } + } + else + { // NEAREST-NEIGHBOUR but with border preserving + ULONG ulRowModulo = pixWidth*2 *BYTES_PER_TEXEL; + __asm { + xor ebx,ebx + mov esi,D [pulSrcMipmap] + mov edi,D [pulDstMipmap] + // setup upper half + mov edx,D [pixHeight] + shr edx,1 +halfLoop: + mov ecx,D [pixWidth] + shr ecx,1 +leftLoop: + mov eax,D [esi+ ebx*8+ 0] // upper-left (or lower-left) + mov D [edi],eax + // advance to next pixel + add esi,4*2 + add edi,4 + sub ecx,1 + jg leftLoop + // do right row half + mov ecx,D [pixWidth] + shr ecx,1 + jz halfEnd +rightLoop: + mov eax,D [esi+ ebx*8+ 4] // upper-right (or lower-right) + mov D [edi],eax + // advance to next pixel + add esi,4*2 + add edi,4 + sub ecx,1 + jg rightLoop +halfEnd: + // advance to next row + add esi,D [ulRowModulo] // skip one row in source mip-map + sub edx,1 + jg halfLoop + // do eventual lower half loop (if not yet done) + mov edx,D [pixHeight] + shr edx,1 + jz fullEnd + cmp ebx,D [pixWidth] + mov ebx,D [pixWidth] + jne halfLoop +fullEnd: + } + } +} + + +// makes ALL lower mipmaps (to size of 1x1!) of a specified 32-bit bitmap +// and returns pointer to newely created and mipmaped image +// (only first ctFineMips number of mip-maps will be filtered with bilinear subsampling, while +// all others will be downsampled with nearest-neighbour method) +void MakeMipmaps( INDEX ctFineMips, ULONG *pulMipmaps, PIX pixWidth, PIX pixHeight, INDEX iFilter/*=NONE*/) +{ + ASSERT( pixWidth>0 && pixHeight>0); + _pfGfxProfile.StartTimer( CGfxProfile::PTI_MAKEMIPMAPS); + + // prepare some variables + INDEX ctMipmaps = 1; + PIX pixTexSize = 0; + PIX pixCurrWidth = pixWidth; + PIX pixCurrHeight = pixHeight; + ULONG *pulSrcMipmap, *pulDstMipmap; + + // determine filtering mode (-1=prefiltering, 0=none, 1=postfiltering) + INDEX iFilterMode = 0; + if( iFilter!=0) { + iFilterMode = -1; + if( !tex_bProgressiveFilter) iFilterMode = +1; + } + + // loop thru mip-map levels + while( pixCurrWidth>1 && pixCurrHeight>1) + { // determine mip size + PIX pixMipSize = pixCurrWidth*pixCurrHeight; + pulSrcMipmap = pulMipmaps + pixTexSize; + pulDstMipmap = pulSrcMipmap + pixMipSize; + // do pre filter is required + if( iFilterMode<0) FilterBitmap( iFilter, pulSrcMipmap, pulSrcMipmap, pixCurrWidth, pixCurrHeight); + // create one mipmap + MakeOneMipmap( pulSrcMipmap, pulDstMipmap, pixCurrWidth, pixCurrHeight, ctMipmaps0) FilterBitmap( iFilter, pulSrcMipmap, pulSrcMipmap, pixCurrWidth, pixCurrHeight); + // advance to next mipmap + pixTexSize += pixMipSize; + pixCurrWidth >>=1; + pixCurrHeight >>=1; + ctMipmaps++; + } + // all done + _pfGfxProfile.StopTimer( CGfxProfile::PTI_MAKEMIPMAPS); +} + + +// mipmap colorization table (from 1024 to 1) +static COLOR _acolMips[10] = { C_RED, C_GREEN, C_BLUE, C_CYAN, C_MAGENTA, C_YELLOW, C_RED, C_GREEN, C_BLUE, C_WHITE }; + +// colorize mipmaps +void ColorizeMipmaps( INDEX i1stMipmapToColorize, ULONG *pulMipmaps, PIX pixWidth, PIX pixHeight) +{ + // prepare ... + ULONG *pulSrcMipmap = pulMipmaps + GetMipmapOffset( i1stMipmapToColorize, pixWidth, pixHeight); + ULONG *pulDstMipmap; + PIX pixCurrWidth = pixWidth >>i1stMipmapToColorize; + PIX pixCurrHeight = pixHeight>>i1stMipmapToColorize; + PIX pixMipSize; + // skip too large textures + const PIX pixMaxDim = Max( pixCurrWidth, pixCurrHeight); + if( pixMaxDim>1024) return; + INDEX iTableOfs = 10-FastLog2(pixMaxDim); + + // loop thru mip-map levels + while( pixCurrWidth>1 && pixCurrHeight>1) + { // prepare current mip-level + pixMipSize = pixCurrWidth*pixCurrHeight; + pulDstMipmap = pulSrcMipmap + pixMipSize; + // mask mipmap + const ULONG ulColorMask = ByteSwap( _acolMips[iTableOfs] | 0x3F3F3FFF); + for( INDEX iPix=0; iPix>=1; + pixCurrHeight >>=1; + iTableOfs++; + } +} + + + +// calculates standard deviation of a bitmap +DOUBLE CalcBitmapDeviation( ULONG *pulBitmap, PIX pixSize) +{ + UBYTE ubR,ubG,ubB; + ULONG ulSumR =0, ulSumG =0, ulSumB =0; +__int64 mmSumR2=0, mmSumG2=0, mmSumB2=0; + + // calculate sum and sum^2 + for( INDEX iPix=0; iPix=pixWidth && pixCanvasHeight>=pixHeight); + SLONG slModulo = (pixCanvasWidth-pixWidth) *BYTES_PER_TEXEL; + SLONG slWidthModulo = pixWidth*BYTES_PER_TEXEL +slModulo; + + // if bitmap is smaller than 4x2 pixels + if( pixWidth<4 || pixHeight<2) + { // don't dither it at all, rather copy only (if needed) + if( pulDst!=pulSrc) memcpy( pulDst, pulSrc, pixCanvasWidth*pixCanvasHeight *BYTES_PER_TEXEL); + goto theEnd; + } + + // determine proper dither type + switch( iDitherType) + { // low dithers + case 1: + pulDitherTable = &ulDither2[0][0]; + mmShift = 2; + mmMask = 0x3F3F3F3F3F3F3F3F; + goto ditherOrder; + case 2: + pulDitherTable = &ulDither2[0][0]; + mmShift = 1; + mmMask = 0x7F7F7F7F7F7F7F7F; + goto ditherOrder; + case 3: + mmErrDiffMask = 0x0003000300030003; + goto ditherError; + // medium dithers + case 4: + pulDitherTable = &ulDither2[0][0]; + mmShift = 0; + mmMask = 0xFFFFFFFFFFFFFFFF; + goto ditherOrder; + case 5: + pulDitherTable = &ulDither3[0][0]; + mmShift = 1; + mmMask = 0x7F7F7F7F7F7F7F7F; + goto ditherOrder; + case 6: + pulDitherTable = &ulDither4[0][0]; + mmShift = 1; + mmMask = 0x7F7F7F7F7F7F7F7F; + goto ditherOrder; + case 7: + mmErrDiffMask = 0x0007000700070007; + goto ditherError; + // high dithers + case 8: + pulDitherTable = &ulDither3[0][0]; + mmShift = 0; + mmMask = 0xFFFFFFFFFFFFFFFF; + goto ditherOrder; + case 9: + pulDitherTable = &ulDither4[0][0]; + mmShift = 0; + mmMask = 0xFFFFFFFFFFFFFFFF; + goto ditherOrder; + case 10: + mmErrDiffMask = 0x000F000F000F000F; + goto ditherError; + default: + // improper dither type + ASSERTALWAYS( "Improper dithering type."); + // if bitmap copying is needed + if( pulDst!=pulSrc) memcpy( pulDst, pulSrc, pixCanvasWidth*pixCanvasHeight *BYTES_PER_TEXEL); + goto theEnd; + } + +// ------------------------------- ordered matrix dithering routine + +ditherOrder: + __asm { + mov esi,D [pulSrc] + mov edi,D [pulDst] + mov ebx,D [pulDitherTable] + // reset dither line offset + xor eax,eax + mov edx,D [pixHeight] +rowLoopO: + // get horizontal dither patterns + movq mm4,Q [ebx+ eax*4 +0] + movq mm5,Q [ebx+ eax*4 +8] + psrlw mm4,Q [mmShift] + psrlw mm5,Q [mmShift] + pand mm4,Q [mmMask] + pand mm5,Q [mmMask] + // process row + mov ecx,D [pixWidth] +pixLoopO: + movq mm1,Q [esi +0] + movq mm2,Q [esi +8] + paddusb mm1,mm4 + paddusb mm2,mm5 + movq Q [edi +0],mm1 + movq Q [edi +8],mm2 + // advance to next pixel + add esi,4*4 + add edi,4*4 + sub ecx,4 + jg pixLoopO // !!!! possible memory leak? + je nextRowO + // backup couple of pixels + lea esi,[esi+ ecx*4] + lea edi,[edi+ ecx*4] +nextRowO: + // get next dither line patterns + add esi,D [slModulo] + add edi,D [slModulo] + add eax,1*4 + and eax,4*4-1 + // advance to next row + dec edx + jnz rowLoopO + emms; + } + goto theEnd; + +// ------------------------------- error diffusion dithering routine + +ditherError: + // since error diffusion algorithm requires in-place dithering, original bitmap must be copied if needed + if( pulDst!=pulSrc) memcpy( pulDst, pulSrc, pixCanvasWidth*pixCanvasHeight *BYTES_PER_TEXEL); + // slModulo+=4; + // now, dither destination + __asm { + pxor mm0,mm0 + mov esi,D [pulDst] + mov ebx,D [pixCanvasWidth] + mov edx,D [pixHeight] + dec edx // need not to dither last row +rowLoopE: + // left to right + mov ecx,D [pixWidth] + dec ecx +pixLoopEL: + movd mm1,D [esi] + punpcklbw mm1,mm0 + pand mm1,Q [mmErrDiffMask] + // determine errors + movq mm3,mm1 + movq mm5,mm1 + movq mm7,mm1 + pmullw mm3,Q [mmW3] + pmullw mm5,Q [mmW5] + pmullw mm7,Q [mmW7] + psrlw mm3,4 // *3/16 + psrlw mm5,4 // *5/16 + psrlw mm7,4 // *7/16 + psubw mm1,mm3 + psubw mm1,mm5 + psubw mm1,mm7 // *rest/16 + packuswb mm1,mm0 + packuswb mm3,mm0 + packuswb mm5,mm0 + packuswb mm7,mm0 + // spread errors + paddusb mm7,Q [esi+ +4] + paddusb mm3,Q [esi+ ebx*4 -4] + paddusb mm5,Q [esi+ ebx*4 +0] + paddusb mm1,Q [esi+ ebx*4 +4] // !!!! possible memory leak? + movd D [esi+ +4],mm7 + movd D [esi+ ebx*4 -4],mm3 + movd D [esi+ ebx*4 +0],mm5 + movd D [esi+ ebx*4 +4],mm1 + // advance to next pixel + add esi,4 + dec ecx + jnz pixLoopEL + // advance to next row + add esi,D [slWidthModulo] + dec edx + jz allDoneE + + // right to left + mov ecx,D [pixWidth] + dec ecx +pixLoopER: + movd mm1,D [esi] + punpcklbw mm1,mm0 + pand mm1,Q [mmErrDiffMask] + // determine errors + movq mm3,mm1 + movq mm5,mm1 + movq mm7,mm1 + pmullw mm3,Q [mmW3] + pmullw mm5,Q [mmW5] + pmullw mm7,Q [mmW7] + psrlw mm3,4 // *3/16 + psrlw mm5,4 // *5/16 + psrlw mm7,4 // *7/16 + psubw mm1,mm3 + psubw mm1,mm5 + psubw mm1,mm7 // *rest/16 + packuswb mm1,mm0 + packuswb mm3,mm0 + packuswb mm5,mm0 + packuswb mm7,mm0 + // spread errors + paddusb mm7,Q [esi+ -4] + paddusb mm1,Q [esi+ ebx*4 -4] + paddusb mm5,Q [esi+ ebx*4 +0] + paddusb mm3,Q [esi+ ebx*4 +4] // !!!! possible memory leak? + movd D [esi+ -4],mm7 + movd D [esi+ ebx*4 -4],mm1 + movd D [esi+ ebx*4 +0],mm5 + movd D [esi+ ebx*4 +4],mm3 + // revert to previous pixel + sub esi,4 + dec ecx + jnz pixLoopER + // advance to next row + lea esi,[esi+ ebx*4] + dec edx + jnz rowLoopE +allDoneE: + emms; + } + goto theEnd; + + // all done +theEnd: + _pfGfxProfile.StopTimer( CGfxProfile::PTI_DITHERBITMAP); +} + + + +// performs dithering of a 32-bit mipmaps (can be in-place) +void DitherMipmaps( INDEX iDitherType, ULONG *pulSrc, ULONG *pulDst, PIX pixWidth, PIX pixHeight) +{ + // safety check + ASSERT( pixWidth>0 && pixHeight>0); + // loop thru mipmaps + PIX pixMipSize; + while( pixWidth>0 && pixHeight>0) + { // dither one mipmap + DitherBitmap( iDitherType, pulSrc, pulDst, pixWidth, pixHeight); + // advance to next mipmap + pixMipSize = pixWidth*pixHeight; + pulSrc += pixMipSize; + pulDst += pixMipSize; + pixWidth >>=1; + pixHeight>>=1; + } +} + + + +// blur/sharpen filters +static INDEX aiFilters[6][3] = { + { 0, 1, 16 }, // minimum + { 0, 2, 8 }, // low + { 1, 2, 7 }, // medium + { 1, 2, 3 }, // high + { 3, 4, 5 }, // maximum + { 1, 1, 1 }}; // + +// temp for middle pixels, vertical/horizontal edges, and corners +static __int64 mmMc, mmMe, mmMm; // corner, edge, middle +static __int64 mmEch, mmEm; // corner-high, middle +#define mmEcl mmMc // corner-low +#define mmEe mmMe // edge +static __int64 mmCm; // middle +#define mmCc mmMc // corner +#define mmCe mmEch // edge +static __int64 mmInvDiv; +static __int64 mmAdd = 0x0007000700070007; + +// temp rows for in-place filtering support +static ULONG aulRows[2048]; + + +// FilterBitmap() INTERNAL: generates convolution filter matrix if needed +static INDEX iLastFilter; +static void GenerateConvolutionMatrix( INDEX iFilter) +{ + // same as last? + if( iLastFilter==iFilter) return; + // update filter + iLastFilter = iFilter; + INDEX iFilterAbs = Abs(iFilter) -1; + // convert convolution values to MMX format + INDEX iMc = aiFilters[iFilterAbs][0]; // corner + INDEX iMe = aiFilters[iFilterAbs][1]; // edge + INDEX iMm = aiFilters[iFilterAbs][2]; // middle + // negate values for sharpen filter case + if( iFilter<0) { + iMm += (iMe+iMc) *8; // (4*Edge + 4*Corner) *2 + iMe = -iMe; + iMc = -iMc; + } + // find values for edge and corner cases + INDEX iEch = iMc + iMe; + INDEX iEm = iMm + iMe; + INDEX iCm = iEch + iEm; + // prepare divider + __int64 mm = ((__int64)ceil(65536.0f/(iMc*4+iMe*4+iMm))) & 0xFFFF; + mmInvDiv = (mm<<48) | (mm<<32) | (mm<<16) | mm; + // prepare filter values + mm = iMc & 0xFFFF; mmMc = (mm<<48) | (mm<<32) | (mm<<16) | mm; + mm = iMe & 0xFFFF; mmMe = (mm<<48) | (mm<<32) | (mm<<16) | mm; + mm = iMm & 0xFFFF; mmMm = (mm<<48) | (mm<<32) | (mm<<16) | mm; + mm = iEch & 0xFFFF; mmEch= (mm<<48) | (mm<<32) | (mm<<16) | mm; + mm = iEm & 0xFFFF; mmEm = (mm<<48) | (mm<<32) | (mm<<16) | mm; + mm = iCm & 0xFFFF; mmCm = (mm<<48) | (mm<<32) | (mm<<16) | mm; +} + + +// applies filter to bitmap +void FilterBitmap( INDEX iFilter, ULONG *pulSrc, ULONG *pulDst, PIX pixWidth, PIX pixHeight, + PIX pixCanvasWidth, PIX pixCanvasHeight) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_FILTERBITMAP); + ASSERT( iFilter>=-6 && iFilter<=+6); + + // adjust canvas size + if( pixCanvasWidth ==0) pixCanvasWidth = pixWidth; + if( pixCanvasHeight==0) pixCanvasHeight = pixHeight; + ASSERT( pixCanvasWidth>=pixWidth && pixCanvasHeight>=pixHeight); + + // if bitmap is smaller than 4x4 + if( pixWidth<4 || pixHeight<4) + { // don't blur it at all, but eventually only copy + if( pulDst!=pulSrc) memcpy( pulDst, pulSrc, pixCanvasWidth*pixCanvasHeight *BYTES_PER_TEXEL); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_FILTERBITMAP); + return; + } + + // prepare convolution matrix and row modulo + iFilter = Clamp( iFilter, -6L, +6L); + GenerateConvolutionMatrix( iFilter); + SLONG slModulo1 = (pixCanvasWidth-pixWidth+1) *BYTES_PER_TEXEL; + SLONG slCanvasWidth = pixCanvasWidth *BYTES_PER_TEXEL; + + // lets roll ... + __asm { + cld + mov eax,D [pixCanvasWidth] // EAX = positive row offset + mov edx,eax + neg edx // EDX = negative row offset + pxor mm0,mm0 + mov esi,D [pulSrc] + mov edi,D [pulDst] + xor ebx,ebx + +// ----------------------- process upper left corner + + movd mm1,D [esi+ +0] + movd mm2,D [esi+ +4] + movd mm3,D [esi+ eax*4 +0] + movd mm4,D [esi+ eax*4 +4] + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + punpcklbw mm3,mm0 + punpcklbw mm4,mm0 + paddw mm2,mm3 + pmullw mm1,Q [mmCm] + pmullw mm2,Q [mmCe] + pmullw mm4,Q [mmCc] + paddw mm1,mm2 + paddw mm1,mm4 + paddsw mm1,Q [mmAdd] + pmulhw mm1,Q [mmInvDiv] + packuswb mm1,mm0 + movd D [ebx+ aulRows],mm1 + add esi,4 + add ebx,4 + +// ----------------------- process upper edge pixels + + mov ecx,D [pixWidth] + sub ecx,2 + // for each pixel +upperLoop: + movd mm1,D [esi+ -4] + movd mm2,D [esi+ +0] + movd mm3,D [esi+ +4] + movd mm4,D [esi+ eax*4 -4] + movd mm5,D [esi+ eax*4 +0] + movd mm6,D [esi+ eax*4 +4] + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + punpcklbw mm3,mm0 + punpcklbw mm4,mm0 + punpcklbw mm5,mm0 + punpcklbw mm6,mm0 + paddw mm1,mm3 + paddw mm4,mm6 + pmullw mm1,Q [mmEch] + pmullw mm2,Q [mmEm] + pmullw mm4,Q [mmEcl] + pmullw mm5,Q [mmEe] + paddw mm1,mm2 + paddw mm1,mm4 + paddw mm1,mm5 + paddsw mm1,Q [mmAdd] + pmulhw mm1,Q [mmInvDiv] + packuswb mm1,mm0 + movd D [ebx+ aulRows],mm1 + // advance to next pixel + add esi,4 + add ebx,4 + dec ecx + jnz upperLoop + +// ----------------------- process upper right corner + + movd mm1,D [esi+ -4] + movd mm2,D [esi+ +0] + movd mm3,D [esi+ eax*4 -4] + movd mm4,D [esi+ eax*4 +0] + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + punpcklbw mm3,mm0 + punpcklbw mm4,mm0 + paddw mm1,mm4 + pmullw mm1,Q [mmCe] + pmullw mm2,Q [mmCm] + pmullw mm3,Q [mmCc] + paddw mm1,mm2 + paddw mm1,mm3 + paddsw mm1,Q [mmAdd] + pmulhw mm1,Q [mmInvDiv] + packuswb mm1,mm0 + movd D [ebx+ aulRows],mm1 + +// ----------------------- process bitmap middle pixels + + add esi,D [slModulo1] + add edi,D [slCanvasWidth] + mov ebx,D [pixHeight] + sub ebx,2 + // for each row +rowLoop: + push ebx + xor ebx,ebx + // process left edge pixel + movd mm1,D [esi+ edx*4 +0] + movd mm2,D [esi+ edx*4 +4] + movd mm3,D [esi+ +0] + movd mm4,D [esi+ +4] + movd mm5,D [esi+ eax*4 +0] + movd mm6,D [esi+ eax*4 +4] + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + punpcklbw mm3,mm0 + punpcklbw mm4,mm0 + punpcklbw mm5,mm0 + punpcklbw mm6,mm0 + paddw mm1,mm5 + paddw mm2,mm6 + pmullw mm1,Q [mmEch] + pmullw mm2,Q [mmEcl] + pmullw mm3,Q [mmEm] + pmullw mm4,Q [mmEe] + paddw mm1,mm2 + paddw mm1,mm3 + paddw mm1,mm4 + paddsw mm1,Q [mmAdd] + pmulhw mm1,Q [mmInvDiv] + packuswb mm1,mm0 + movd mm2,D [ebx+ aulRows] + movd D [ebx+ aulRows],mm1 + movd D [edi+ edx*4],mm2 + add esi,4 + add edi,4 + add ebx,4 + + // for each pixel in current row + mov ecx,D [pixWidth] + sub ecx,2 +pixLoop: + // prepare upper convolution row + movd mm1,D [esi+ edx*4 -4] + movd mm2,D [esi+ edx*4 +0] + movd mm3,D [esi+ edx*4 +4] + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + punpcklbw mm3,mm0 + // prepare middle convolution row + movd mm4,D [esi+ -4] + movd mm5,D [esi+ +0] + movd mm6,D [esi+ +4] + punpcklbw mm4,mm0 + punpcklbw mm5,mm0 + punpcklbw mm6,mm0 + // free some registers + paddw mm1,mm3 + paddw mm2,mm4 + pmullw mm5,Q [mmMm] + // prepare lower convolution row + movd mm3,D [esi+ eax*4 -4] + movd mm4,D [esi+ eax*4 +0] + movd mm7,D [esi+ eax*4 +4] + punpcklbw mm3,mm0 + punpcklbw mm4,mm0 + punpcklbw mm7,mm0 + // calc weightened value + paddw mm2,mm6 + paddw mm1,mm3 + paddw mm2,mm4 + paddw mm1,mm7 + pmullw mm2,Q [mmMe] + pmullw mm1,Q [mmMc] + paddw mm2,mm5 + paddw mm1,mm2 + // calc and store wightened value + paddsw mm1,Q [mmAdd] + pmulhw mm1,Q [mmInvDiv] + packuswb mm1,mm0 + movd mm2,D [ebx+ aulRows] + movd D [ebx+ aulRows],mm1 + movd D [edi+ edx*4],mm2 + // advance to next pixel + add esi,4 + add edi,4 + add ebx,4 + dec ecx + jnz pixLoop + + // process right edge pixel + movd mm1,D [esi+ edx*4 -4] + movd mm2,D [esi+ edx*4 +0] + movd mm3,D [esi+ -4] + movd mm4,D [esi+ +0] + movd mm5,D [esi+ eax*4 -4] + movd mm6,D [esi+ eax*4 +0] + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + punpcklbw mm3,mm0 + punpcklbw mm4,mm0 + punpcklbw mm5,mm0 + punpcklbw mm6,mm0 + paddw mm1,mm5 + paddw mm2,mm6 + pmullw mm1,Q [mmEcl] + pmullw mm2,Q [mmEch] + pmullw mm3,Q [mmEe] + pmullw mm4,Q [mmEm] + paddw mm1,mm2 + paddw mm1,mm3 + paddw mm1,mm4 + paddsw mm1,Q [mmAdd] + pmulhw mm1,Q [mmInvDiv] + packuswb mm1,mm0 + movd mm2,D [ebx+ aulRows] + movd D [ebx+ aulRows],mm1 + movd D [edi+ edx*4],mm2 + // advance to next row + add esi,D [slModulo1] + add edi,D [slModulo1] + pop ebx + dec ebx + jnz rowLoop + +// ----------------------- process lower left corner + + xor ebx,ebx + movd mm1,D [esi+ edx*4 +0] + movd mm2,D [esi+ edx*4 +4] + movd mm3,D [esi+ +0] + movd mm4,D [esi+ +4] + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + punpcklbw mm3,mm0 + punpcklbw mm4,mm0 + paddw mm1,mm4 + pmullw mm1,Q [mmCe] + pmullw mm2,Q [mmCc] + pmullw mm3,Q [mmCm] + paddw mm1,mm2 + paddw mm1,mm3 + paddsw mm1,Q [mmAdd] + pmulhw mm1,Q [mmInvDiv] + packuswb mm1,mm0 + movd mm2,D [ebx+ aulRows] + movd D [edi],mm1 + movd D [edi+ edx*4],mm2 + add esi,4 + add edi,4 + add ebx,4 + +// ----------------------- process lower edge pixels + + mov ecx,D [pixWidth] + sub ecx,2 + // for each pixel +lowerLoop: + movd mm1,D [esi+ edx*4 -4] + movd mm2,D [esi+ edx*4 +0] + movd mm3,D [esi+ edx*4 +4] + movd mm4,D [esi+ -4] + movd mm5,D [esi+ +0] + movd mm6,D [esi+ +4] + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + punpcklbw mm3,mm0 + punpcklbw mm4,mm0 + punpcklbw mm5,mm0 + punpcklbw mm6,mm0 + paddw mm1,mm3 + paddw mm4,mm6 + pmullw mm1,Q [mmEcl] + pmullw mm2,Q [mmEe] + pmullw mm4,Q [mmEch] + pmullw mm5,Q [mmEm] + paddw mm1,mm2 + paddw mm1,mm4 + paddw mm1,mm5 + paddsw mm1,Q [mmAdd] + pmulhw mm1,Q [mmInvDiv] + packuswb mm1,mm0 + movd mm2,D [ebx+ aulRows] + movd D [edi],mm1 + movd D [edi+ edx*4],mm2 + // advance to next pixel + add esi,4 + add edi,4 + add ebx,4 + dec ecx + jnz lowerLoop + +// ----------------------- lower right corners + + movd mm1,D [esi+ edx*4 -4] + movd mm2,D [esi+ edx*4 +0] + movd mm3,D [esi+ -4] + movd mm4,D [esi+ +0] + punpcklbw mm1,mm0 + punpcklbw mm2,mm0 + punpcklbw mm3,mm0 + punpcklbw mm4,mm0 + paddw mm2,mm3 + pmullw mm1,Q [mmCc] + pmullw mm2,Q [mmCe] + pmullw mm4,Q [mmCm] + paddw mm1,mm2 + paddw mm1,mm4 + paddsw mm1,Q [mmAdd] + pmulhw mm1,Q [mmInvDiv] + packuswb mm1,mm0 + movd mm2,D [ebx+ aulRows] + movd D [edi],mm1 + movd D [edi+ edx*4],mm2 + emms + } + + // all done (finally) + _pfGfxProfile.StopTimer( CGfxProfile::PTI_FILTERBITMAP); +} + + + +// saturate color of bitmap +void AdjustBitmapColor( ULONG *pulSrc, ULONG *pulDst, PIX pixWidth, PIX pixHeight, + SLONG const slHueShift, SLONG const slSaturation) +{ + for( INDEX i=0; i<(pixWidth*pixHeight); i++) { + pulDst[i] = ByteSwap( AdjustColor( ByteSwap(pulSrc[i]), slHueShift, slSaturation)); + } +} + + +// create mip-map table for texture or shadow of given dimensions +void MakeMipmapTable( PIX pixU, PIX pixV, MipmapTable &mmt) +{ + mmt.mmt_pixU = pixU; + mmt.mmt_pixV = pixV; + // start at first mip map + PIX pixCurrentU = mmt.mmt_pixU; + PIX pixCurrentV = mmt.mmt_pixV; + INDEX iMipmapCurrent = 0; + SLONG slOffsetCurrent = 0; + // while the mip-map is not zero-sized + while (pixCurrentU>0 && pixCurrentV>0) { + // remember its offset + mmt.mmt_aslOffsets[iMipmapCurrent] = slOffsetCurrent; + // go to next mip map + slOffsetCurrent+=pixCurrentU*pixCurrentV; + iMipmapCurrent++; + pixCurrentU>>=1; + pixCurrentV>>=1; + } + // remember number of mip maps and total size + mmt.mmt_ctMipmaps = iMipmapCurrent; + mmt.mmt_slTotalSize = slOffsetCurrent; +} + + + +// TRIANGLE MASK RENDERING (FOR MODEL CLUSTER SHADOWS) ROUTINES + +static ULONG *_pulTexture; +static PIX _pixTexWidth, _pixTexHeight; +extern BOOL _bSomeDarkExists = FALSE; + + +// set texture that will be used for all subsequent triangles +void SetTriangleTexture( ULONG *pulCurrentMipmap, PIX pixMipWidth, PIX pixMipHeight) +{ + _pulTexture = pulCurrentMipmap; + _pixTexWidth = pixMipWidth; + _pixTexHeight = pixMipHeight; +} + +// render one triangle to mask plane for shadow casting purposes +void DrawTriangle_Mask( UBYTE *pubMaskPlane, SLONG slMaskWidth, SLONG slMaskHeight, + struct PolyVertex2D *ppv2Vtx1, struct PolyVertex2D *ppv2Vtx2, + struct PolyVertex2D *ppv2Vtx3, BOOL bTransparency) +{ + struct PolyVertex2D *pUpper = ppv2Vtx1; + struct PolyVertex2D *pMiddle = ppv2Vtx2; + struct PolyVertex2D *pLower = ppv2Vtx3; + struct PolyVertex2D *pTmp; + + // sort vertices by J position + if( pUpper->pv2_fJ > pMiddle->pv2_fJ) { + pTmp = pUpper; pUpper = pMiddle; pMiddle = pTmp; + } + if( pUpper->pv2_fJ > pLower->pv2_fJ) { + pTmp = pUpper; pUpper = pLower; pLower = pTmp; + } + if( pMiddle->pv2_fJ > pLower->pv2_fJ) { + pTmp = pMiddle; pMiddle = pLower; pLower = pTmp; + } + + // determine vertical deltas + FLOAT fDJShort1 = pMiddle->pv2_fJ - pUpper->pv2_fJ; + FLOAT fDJShort2 = pLower->pv2_fJ - pMiddle->pv2_fJ; + FLOAT fDJLong = pLower->pv2_fJ - pUpper->pv2_fJ; + if( fDJLong == 0) return; + + // determine horizontal deltas + FLOAT fDIShort1 = pMiddle->pv2_fI - pUpper->pv2_fI; + FLOAT fDIShort2 = pLower->pv2_fI - pMiddle->pv2_fI; + FLOAT fDILong = pLower->pv2_fI - pUpper->pv2_fI; + + // determine U/K, V/K and 1/K deltas + FLOAT fD1oKShort1 = pMiddle->pv2_f1oK - pUpper->pv2_f1oK; + FLOAT fD1oKShort2 = pLower->pv2_f1oK - pMiddle->pv2_f1oK; + FLOAT fD1oKLong = pLower->pv2_f1oK - pUpper->pv2_f1oK; + FLOAT fDUoKShort1 = pMiddle->pv2_fUoK - pUpper->pv2_fUoK; + FLOAT fDUoKShort2 = pLower->pv2_fUoK - pMiddle->pv2_fUoK; + FLOAT fDUoKLong = pLower->pv2_fUoK - pUpper->pv2_fUoK; + FLOAT fDVoKShort1 = pMiddle->pv2_fVoK - pUpper->pv2_fVoK; + FLOAT fDVoKShort2 = pLower->pv2_fVoK - pMiddle->pv2_fVoK; + FLOAT fDVoKLong = pLower->pv2_fVoK - pUpper->pv2_fVoK; + + // determine stepping factors; + FLOAT f1oDJShort1, f1oDJShort2, f1oDJLong; + if( fDJShort1 != 0) f1oDJShort1 = 1 / fDJShort1; else f1oDJShort1 = 0; + if( fDJShort2 != 0) f1oDJShort2 = 1 / fDJShort2; else f1oDJShort2 = 0; + if( fDJLong != 0) f1oDJLong = 1 / fDJLong; else f1oDJLong = 0; + + FLOAT fDIoDJShort1 = fDIShort1 * f1oDJShort1; + FLOAT fDIoDJShort2 = fDIShort2 * f1oDJShort2; + FLOAT fDIoDJLong = fDILong * f1oDJLong; + FLOAT fMaxWidth = fDIoDJLong*fDJShort1 + pUpper->pv2_fI - pMiddle->pv2_fI; + + // determine drawing direction and factors by direction + SLONG direction = +1; + if( fMaxWidth > 0) direction = -1; + + // find start and end values for J + PIX pixUpJ = FloatToInt(pUpper->pv2_fJ +0.5f); + PIX pixMdJ = FloatToInt(pMiddle->pv2_fJ +0.5f); + PIX pixDnJ = FloatToInt(pLower->pv2_fJ +0.5f); + + // clip vertically + if( pixDnJ<0 || pixUpJ>=slMaskHeight) return; + if( pixUpJ<0) pixUpJ=0; + if( pixDnJ>slMaskHeight) pixDnJ=slMaskHeight; + if( pixMdJ<0) pixMdJ=0; + if( pixMdJ>slMaskHeight) pixMdJ=slMaskHeight; + SLONG fixWidth = slMaskWidth<<11; + + // find prestepped I + FLOAT fPrestepUp = (FLOAT)pixUpJ - pUpper->pv2_fJ; + FLOAT fPrestepMd = (FLOAT)pixMdJ - pMiddle->pv2_fJ; + SLONG fixILong = FloatToInt((pUpper->pv2_fI + fPrestepUp * fDIoDJLong )*2048.0f) +fixWidth*pixUpJ; + SLONG fixIShort1 = FloatToInt((pUpper->pv2_fI + fPrestepUp * fDIoDJShort1)*2048.0f) +fixWidth*pixUpJ; + SLONG fixIShort2 = FloatToInt((pMiddle->pv2_fI + fPrestepMd * fDIoDJShort2)*2048.0f) +fixWidth*pixMdJ; + + // convert steps from floats to fixints (21:11) + SLONG fixDIoDJLong = FloatToInt(fDIoDJLong *2048.0f) +fixWidth; + SLONG fixDIoDJShort1 = FloatToInt(fDIoDJShort1*2048.0f) +fixWidth; + SLONG fixDIoDJShort2 = FloatToInt(fDIoDJShort2*2048.0f) +fixWidth; + + // find row counter and max delta J + SLONG ctJShort1 = pixMdJ - pixUpJ; + SLONG ctJShort2 = pixDnJ - pixMdJ; + SLONG ctJLong = pixDnJ - pixUpJ; + + FLOAT currK, curr1oK, currUoK, currVoK; + PIX pixJ = pixUpJ; + + // if model has texture and texture has alpha channel, do complex mapping thru texture's alpha channel + if( _pulTexture!=NULL && bTransparency) + { + // calculate some texture variables + FLOAT fD1oKoDJShort1 = fD1oKShort1 * f1oDJShort1; + FLOAT fD1oKoDJShort2 = fD1oKShort2 * f1oDJShort2; + FLOAT fD1oKoDJLong = fD1oKLong * f1oDJLong; + FLOAT fDUoKoDJShort1 = fDUoKShort1 * f1oDJShort1; + FLOAT fDUoKoDJShort2 = fDUoKShort2 * f1oDJShort2; + FLOAT fDUoKoDJLong = fDUoKLong * f1oDJLong; + FLOAT fDVoKoDJShort1 = fDVoKShort1 * f1oDJShort1; + FLOAT fDVoKoDJShort2 = fDVoKShort2 * f1oDJShort2; + FLOAT fDVoKoDJLong = fDVoKLong * f1oDJLong; + ;// FactOverDI = (DFoDJ * (J2-J1) + fact1 - fact2) * 1/width + FLOAT f1oMaxWidth = 1 / fMaxWidth; + FLOAT fD1oKoDI = (fD1oKoDJLong * fDJShort1 + pUpper->pv2_f1oK - pMiddle->pv2_f1oK) * f1oMaxWidth; + FLOAT fDUoKoDI = (fDUoKoDJLong * fDJShort1 + pUpper->pv2_fUoK - pMiddle->pv2_fUoK) * f1oMaxWidth; + FLOAT fDVoKoDI = (fDVoKoDJLong * fDJShort1 + pUpper->pv2_fVoK - pMiddle->pv2_fVoK) * f1oMaxWidth; + if( direction == -1) { + fD1oKoDI = -fD1oKoDI; + fDUoKoDI = -fDUoKoDI; + fDVoKoDI = -fDVoKoDI; + } + // find prestepped U/K, V/K, 1/K + FLOAT f1oKLong = pUpper->pv2_f1oK + fPrestepUp * fD1oKoDJLong; + FLOAT f1oKShort1 = pUpper->pv2_f1oK + fPrestepUp * fD1oKoDJShort1; + FLOAT f1oKShort2 = pMiddle->pv2_f1oK + fPrestepMd * fD1oKoDJShort2; + FLOAT fUoKLong = pUpper->pv2_fUoK + fPrestepUp * fDUoKoDJLong; + FLOAT fUoKShort1 = pUpper->pv2_fUoK + fPrestepUp * fDUoKoDJShort1; + FLOAT fUoKShort2 = pMiddle->pv2_fUoK + fPrestepMd * fDUoKoDJShort2; + FLOAT fVoKLong = pUpper->pv2_fVoK + fPrestepUp * fDVoKoDJLong; + FLOAT fVoKShort1 = pUpper->pv2_fVoK + fPrestepUp * fDVoKoDJShort1; + FLOAT fVoKShort2 = pMiddle->pv2_fVoK + fPrestepMd * fDVoKoDJShort2; + + // render upper triangle part + PIX pixTexU, pixTexV; + while( ctJShort1>0) { + SLONG currI = fixILong>>11; + SLONG countI = abs( currI - (fixIShort1>>11)); + if( countI==0) goto nextLine1; + curr1oK = f1oKLong; + currUoK = fUoKLong; + currVoK = fVoKLong; + if( direction == -1) currI--; + if( countI>0) _bSomeDarkExists = TRUE; + while( countI>0) { + currK = 1.0f/curr1oK; + pixTexU = (FloatToInt(currUoK*currK)) & (_pixTexWidth -1); + pixTexV = (FloatToInt(currVoK*currK)) & (_pixTexHeight-1); + if( _pulTexture[pixTexV*_pixTexWidth+pixTexU] & ((CT_rAMASK<<7)&CT_rAMASK)) pubMaskPlane[currI] = 0; + curr1oK += fD1oKoDI; + currUoK += fDUoKoDI; + currVoK += fDVoKoDI; + currI += direction; + countI--; + } + nextLine1: + pixJ++; + f1oKLong += fD1oKoDJLong; + f1oKShort1 += fD1oKoDJShort1; + fUoKLong += fDUoKoDJLong; + fUoKShort1 += fDUoKoDJShort1; + fVoKLong += fDVoKoDJLong; + fVoKShort1 += fDVoKoDJShort1; + fixILong += fixDIoDJLong; + fixIShort1 += fixDIoDJShort1; + ctJShort1--; + } + + // render lower triangle part + while( ctJShort2>0) { + SLONG currI = fixILong>>11; + SLONG countI = abs( currI - (fixIShort2>>11)); + if( countI==0) goto nextLine2; + curr1oK = f1oKLong; + currUoK = fUoKLong; + currVoK = fVoKLong; + if( direction == -1) currI--; + if( countI>0) _bSomeDarkExists = TRUE; + while( countI>0) { + currK = 1.0f/curr1oK; + pixTexU = (FloatToInt(currUoK*currK)) & (_pixTexWidth -1); + pixTexV = (FloatToInt(currVoK*currK)) & (_pixTexHeight-1); + if( _pulTexture[pixTexV*_pixTexWidth+pixTexU] & CT_rAMASK) pubMaskPlane[currI] = 0; + curr1oK += fD1oKoDI; + currUoK += fDUoKoDI; + currVoK += fDVoKoDI; + currI += direction; + countI--; + } + nextLine2: + pixJ++; + f1oKLong += fD1oKoDJLong; + f1oKShort2 += fD1oKoDJShort2; + fUoKLong += fDUoKoDJLong; + fUoKShort2 += fDUoKoDJShort2; + fVoKLong += fDVoKoDJLong; + fVoKShort2 += fDVoKoDJShort2; + fixILong += fixDIoDJLong; + fixIShort2 += fixDIoDJShort2; + ctJShort2--; + } + } + // simple flat mapping (no texture at all) + else + { + // render upper triangle part + while( ctJShort1>0) { + SLONG currI = fixILong>>11; + SLONG countI = abs( currI - (fixIShort1>>11)); + if( direction == -1) currI--; + if( countI>0) _bSomeDarkExists = TRUE; + while( countI>0) { + pubMaskPlane[currI] = 0; + currI += direction; + countI--; + } + pixJ++; + fixILong += fixDIoDJLong; + fixIShort1 += fixDIoDJShort1; + ctJShort1--; + } + // render lower triangle part + while( ctJShort2>0) { + SLONG currI = fixILong>>11; + SLONG countI = abs( currI - (fixIShort2>>11)); + if( countI>0) _bSomeDarkExists = TRUE; + if( direction == -1) currI--; + while( countI>0) { + pubMaskPlane[currI] = 0; + currI += direction; + countI--; + } + pixJ++; + fixILong += fixDIoDJLong; + fixIShort2 += fixDIoDJShort2; + ctJShort2--; + } + } +} + + + + + + + + +// --------------------------------------------------------------------------------------------- + + +#if 0 + + // bilinear filtering of lower mipmap + + // row loop + UBYTE r,g,b,a; + for( PIX v=0; v>=2; gRes >>=2; bRes >>=2; aRes >>=2; + pulDstMipmap[v*pixCurrWidth+u] = RGBAToColor( rRes,gRes,bRes,aRes); + } + } + + + + // nearest-neighbouring of lower mipmap (with border preservance) + + // row loop + PIX u,v; + for( v=0; v4 && pixHeight>4 /*&& tex_bBicubicMipmaps*/) + { + for( INDEX j=0; j>8, slG>>8, slB>>8, slA>>8); + pulDstMipmap[j*pixWidth+i] = ByteSwap(col); + } + } + } + // bilinear! + else + { + + + } + +#endif diff --git a/Sources/Engine/Graphics/ImageInfo.cpp b/Sources/Engine/Graphics/ImageInfo.cpp new file mode 100644 index 0000000..0a91c49 --- /dev/null +++ b/Sources/Engine/Graphics/ImageInfo.cpp @@ -0,0 +1,498 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +#include +#include +#include + +extern void FlipBitmap( UBYTE *pubSrc, UBYTE *pubDst, PIX pixWidth, PIX pixHeight, INDEX iFlipType, BOOL bAlphaChannel); + + +// Order of CroTeam true color pixel components +#define COMPONENT_1 red +#define COMPONENT_2 green +#define COMPONENT_3 blue +#define COMPONENT_4 alpha + +// and vice versa +#define RED_COMPONENT 0 +#define GREEN_COMPONENT 1 +#define BLUE_COMPONENT 2 +#define ALPHA_COMPONENT 3 + + +// PCX header structure +struct PCXHeader +{ + SBYTE MagicID; + SBYTE Version; + SBYTE Encoding; + SBYTE PixelBits; + SWORD Xmin, Ymin, Xmax, Ymax; + SWORD Hres, Vres; + UBYTE Palette[16*3]; + SBYTE Reserved; + SBYTE Planes; + UWORD BytesPerLine; + SWORD PaletteInfo; + SWORD HscreenSize, VscreenSize; + SBYTE Filler[54]; +}; + +// TARGA header structure +struct TGAHeader +{ + UBYTE IdLenght; + UBYTE ColorMapType; + UBYTE ImageType; + UBYTE ColorMapSpec[5]; + UWORD Xorigin; + UWORD Yorigin; + UWORD Width; + UWORD Height; + UBYTE BitsPerPixel; + UBYTE Descriptor; +}; + + + +/****************************************************** + * Routines for manipulating CroTeam picture raw format + */ + +CImageInfo::CImageInfo() { + Detach(); +} +CImageInfo::~CImageInfo() { + Clear(); +} + +// reads image info raw format from file +void CImageInfo::Read_t( CTStream *inFile) // throw char * +{ + Clear(); + + // read image info header + inFile->ExpectID_t( CChunkID("CTII")); + if( inFile->GetSize_t() != 5*4) throw( "Invalid image info file."); + + *inFile >> (PIX)ii_Width; + *inFile >> (PIX)ii_Height; + *inFile >> (SLONG)ii_BitsPerPixel; + + // read image contents (all channels) + ULONG pic_size = ii_Width*ii_Height * ii_BitsPerPixel/8; + ii_Picture = (UBYTE*)AllocMemory( pic_size); + inFile->ReadFullChunk_t( CChunkID("IPIC"), ii_Picture, pic_size); +} + +// writes image info raw format to file +void CImageInfo::Write_t( CTStream *outFile) const // throw char * +{ + // write image info header + outFile->WriteID_t( CChunkID("CTII")); + outFile->WriteSize_t( 5*4); + + *outFile << (PIX)ii_Width; + *outFile << (PIX)ii_Height; + *outFile << (SLONG)ii_BitsPerPixel; + + // write image contents (all channels) + ULONG pic_size = ii_Width*ii_Height * ii_BitsPerPixel/8; + outFile->WriteFullChunk_t( CChunkID("IPIC"), ii_Picture, pic_size); +} + + +// initializes structure members and attaches pointer to image +void CImageInfo::Attach( UBYTE *pPicture, PIX pixWidth, PIX pixHeight, SLONG slBitsPerPixel) +{ + // parameters must be meaningful + ASSERT( (pPicture != NULL) && (pixWidth>0) && (pixHeight>0)); + ASSERT( (slBitsPerPixel == 24) || (slBitsPerPixel == 32)); + // do it ... + ii_Picture = pPicture; + ii_Width = pixWidth; + ii_Height = pixHeight; + ii_BitsPerPixel = slBitsPerPixel; +} + +// clears the content of an image info structure but does not free allocated memory +void CImageInfo::Detach(void) +{ + ii_Picture = NULL; + ii_Width = 0; + ii_Height = 0; + ii_BitsPerPixel = 0; +} + + +// clears the content of an image info structure and frees allocated memory (if any) +void CImageInfo::Clear() +{ + // if allocated, release picture memory + if( ii_Picture != NULL) FreeMemory( ii_Picture); + Detach(); +} + + +// expand image edges +void CImageInfo::ExpandEdges( INDEX ctPasses/*=8192*/) +{ + // do nothing if image is too small or doesn't have an alpha channel + if( ii_Width<3 || ii_Height<3 || ii_BitsPerPixel!=32) return; + + // allocate some memory for spare picture and wipe it clean + SLONG slSize = ii_Width*ii_Height*ii_BitsPerPixel/8; + ULONG *pulSrc = (ULONG*)ii_Picture; + ULONG *pulDst = (ULONG*)AllocMemory(slSize); + memcpy( pulDst, pulSrc, slSize); + + // loop while there are some more pixels to be processed or for specified number of passes + for( INDEX iPass=0; iPass>CT_ASHIFT)>3) continue; + bAllPixelsVisible = FALSE; + // average all surrounding pixels that are visible + ULONG ulRa=0, ulGa=0, ulBa=0; + INDEX ctVisible=0; + for( INDEX j=-1; j<=1; j++) { + for( INDEX i=-1; i<=1; i++) { + const PIX pixSurrOffset = pixOffset + j*ii_Width + i; + col = ByteSwap(pulSrc[pixSurrOffset]); + if( ((col&CT_AMASK)>>CT_ASHIFT)<4) continue; // skip non-visible pixels + UBYTE ubR, ubG, ubB; + ColorToRGB( col, ubR,ubG,ubB); + ulRa+=ubR; ulGa+=ubG; ulBa += ubB; + ctVisible++; + } + } // if there were some visible pixels around + if( ctVisible>0) { + // calc average + ulRa/=ctVisible; ulGa/=ctVisible; ulBa/=ctVisible; + col = RGBAToColor( ulRa,ulGa,ulBa,255); + // put it to center pixel + pulDst[pixOffset] = ByteSwap(col); + } + } + } // copy resulting picture over source + memcpy( pulSrc, pulDst, slSize); + // done if all pixels are visible + if( bAllPixelsVisible) break; + } + // free temp memory + FreeMemory(pulDst); +} + + + +// sets image info structure members with info form file of any supported graphic format +// (CT RAW, PCX8, PCX24, TGA32 uncompressed), but does not load picture content nor palette +INDEX CImageInfo::GetGfxFileInfo_t( const CTFileName &strFileName) // throw char * +{ + CTFileStream GfxFile; + TGAHeader TGAhdr; + PCXHeader PCXhdr; + + // lets assume it's a TGA file + GfxFile.Open_t( strFileName, CTStream::OM_READ); + GfxFile.Read_t( &TGAhdr, sizeof( struct TGAHeader)); + GfxFile.Close(); + + // check for supported targa format + if( (TGAhdr.ImageType==2 || TGAhdr.ImageType==10) && TGAhdr.BitsPerPixel>=24) { + // targa it is, so clear image info and set new values + Clear(); + ii_Width = TGAhdr.Width; + ii_Height = TGAhdr.Height; + ii_BitsPerPixel = TGAhdr.BitsPerPixel; + // we done here, no need to check further + return TGA_FILE; + } + + // we miss Targa, so lets check for supported PCX format + GfxFile.Open_t( strFileName, CTStream::OM_READ); + GfxFile.Read_t( &PCXhdr, sizeof( struct PCXHeader)); + GfxFile.Close(); + + // check for supported PCX format + if( (PCXhdr.MagicID == 10) && (PCXhdr.PixelBits == 8)) { + // PCX it is, so clear image info and set new values + Clear(); + ii_Width = PCXhdr.Xmax - PCXhdr.Xmin + 1; + ii_Height = PCXhdr.Ymax - PCXhdr.Ymin + 1; + ii_BitsPerPixel = PCXhdr.PixelBits * PCXhdr.Planes; + // we done here, no need to check further + return PCX_FILE; + } + + // we didn't found a supported gfx format, sorry ... + return UNSUPPORTED_FILE; +} + + + +/* TGA ********************************************************************************* + * Routines that load and save true color (24 or 32 bit per pixel) uncompressed targa file + */ + + + +void CImageInfo::LoadTGA_t( const CTFileName &strFileName) // throw char * +{ + TGAHeader *pTGAHdr; + UBYTE *pTGABuffer, *pTGAImage; + SLONG slFileSize; + CTFileStream TGAFile; + + Clear(); + + // determine file size + TGAFile.Open_t( strFileName, CTStream::OM_READ); + slFileSize = TGAFile.GetStreamSize(); + + // load entire TGA file to memory, as is, and close it (no further usage) + pTGABuffer = (UBYTE*)AllocMemory( slFileSize); + TGAFile.Read_t( pTGABuffer, slFileSize); + TGAFile.Close(); + + // TGA header starts at the begining of the TGA file + pTGAHdr = (struct TGAHeader*)pTGABuffer; + // TGA image bytes definition follows up + pTGAImage = pTGABuffer + sizeof(struct TGAHeader) + pTGAHdr->IdLenght; + + // detremine picture size dimensions + ii_Width = (SLONG)pTGAHdr->Width; + ii_Height = (SLONG)pTGAHdr->Height; + ii_BitsPerPixel = (SLONG)pTGAHdr->BitsPerPixel; + SLONG slBytesPerPixel = ii_BitsPerPixel/8; + PIX pixBitmapSize = ii_Width*ii_Height; + BOOL bAlphaChannel = (slBytesPerPixel==4); + + // check for supported file types + ASSERT( slBytesPerPixel==3 || slBytesPerPixel==4); + if( slBytesPerPixel!=3 && slBytesPerPixel!=4) throw( TRANS("Unsupported BitsPerPixel in TGA format.")); + + // allocate memory for image content + ii_Picture = (UBYTE*)AllocMemory( ii_Width*ii_Height *slBytesPerPixel); + UBYTE *pubSrc = pTGAImage; // need 'walking' pointers + UBYTE *pubDst = ii_Picture; + + // determine TGA image type + if( pTGAHdr->ImageType==10) { + // RLE encoded + UBYTE ubControl; + INDEX iBlockSize; + BOOL bRepeat; + PIX pixCurrentSize=0; + // loop thru blocks + while( pixCurrentSizeImageType!=2) { + // whoops! + ASSERTALWAYS("Unsupported TGA format."); + throw( TRANS("Unsupported TGA format.")); + } + + // determine image flipping + INDEX iFlipType; + switch( (pTGAHdr->Descriptor&0x30)>>4) { + case 0: iFlipType = 1; break; // vertical flipping + case 1: iFlipType = 3; break; // diagonal flipping + case 3: iFlipType = 2; break; // horizontal flipping + default: iFlipType = 0; break; // no flipping (just copying) + } + // do flipping + FlipBitmap( pTGAImage, ii_Picture, ii_Width, ii_Height, iFlipType, bAlphaChannel); + + // convert TGA pixel format to CroTeam + pubSrc = ii_Picture; // need 'walking' pointer again + for( INDEX iPix=0; iPixWidth = (UWORD)ii_Width; + pTGAHdr->Height = (UWORD)ii_Height; + pTGAHdr->BitsPerPixel = (UBYTE)ii_BitsPerPixel; + pTGAHdr->ImageType = 2; + + // flip image vertically + BOOL bAlphaChannel = (slBytesPerPixel==4); + FlipBitmap( ii_Picture, pTGAImage, ii_Width, ii_Height, 1, bAlphaChannel); + + // convert CroTeam's pixel format to TGA format + UBYTE *pubTmp = pTGAImage; // need 'walking' pointer + for( INDEX iPix=0; iPixXmax - pPCXHdr->Xmin +1); + ii_Height = (SLONG)(pPCXHdr->Ymax - pPCXHdr->Ymin +1); + ii_BitsPerPixel = (SLONG)pPCXHdr->Planes*8; + pic_size = ii_Width * ii_Height * ii_BitsPerPixel/8; + + // allocate memory for image content + ii_Picture = (UBYTE*)AllocMemory( pic_size); + + // allocate memory for decoded PCX file that hasn't been converted to CT RAW Image format + PCX_size = (SLONG)(pPCXHdr->BytesPerLine * ii_Height * ii_BitsPerPixel/8); + pPCXDecodedImage = (UBYTE*)AllocMemory( PCX_size); + pTmp = pPCXDecodedImage; // save pointer for latter usage + + // decode PCX file + for( INDEX i=0; iBytesPerLine * slBytesPerPixel; + // channel looper + for( INDEX p=0; pBytesPerLine; + // byte looper + for( INDEX x=0; x +#include +#include +#include +#include + +// Win9x multimonitor enabling/disabling code, +// idea and original code courtesy of Christian Studer +// added dynamic function loading and exception throwing + +#pragma comment(lib, "advapi32.lib") + +extern INDEX gfx_bDisableMultiMonSupport; +extern INDEX gfx_ctMonitors; +extern INDEX gfx_bMultiMonDisabled; + +typedef BOOL EnumDisplayDevices_t( + PVOID Unused, // not used; must be NULL + DWORD iDevNum, // specifies display device + PDISPLAY_DEVICE lpDisplayDevice, // pointer to structure to + // receive display device information + DWORD dwFlags // flags to condition function behavior +); + +typedef LONG ChangeDisplaySettingsEx_t( + LPCSTR lpszDeviceName, + LPDEVMODE lpDevMode, + HWND hwnd, + DWORD dwflags, + LPVOID lParam +); + +static HINSTANCE _hUser32Lib = NULL; +static EnumDisplayDevices_t *_pEnumDisplayDevices = NULL; +static ChangeDisplaySettingsEx_t *_pChangeDisplaySettingsEx = NULL; + +// disables or enables secondary monitors on Win98/Me +void Mon_DisableEnable9x_t(BOOL bDisable) +{ + // load user32 + if (_hUser32Lib==NULL) { + _hUser32Lib = ::LoadLibraryA( "user32.dll"); + if( _hUser32Lib == NULL) { + ThrowF_t(TRANS("Cannot load user32.dll.")); + } + } + + if (_pEnumDisplayDevices==NULL) { + _pEnumDisplayDevices = (EnumDisplayDevices_t*)GetProcAddress(_hUser32Lib, "EnumDisplayDevicesA"); + if (_pEnumDisplayDevices==NULL) { + ThrowF_t(TRANS("Cannot find EnumDisplayDevices().")); + } + } + + if (_pChangeDisplaySettingsEx==NULL) { + _pChangeDisplaySettingsEx = (ChangeDisplaySettingsEx_t*)GetProcAddress(_hUser32Lib, "ChangeDisplaySettingsExA"); + if (_pChangeDisplaySettingsEx==NULL) { + ThrowF_t(TRANS("Cannot find ChangeDisplaySettingsEx().")); + } + } + + HKEY key; + LONG ret = RegOpenKeyEx(HKEY_CURRENT_CONFIG, _T("Display\\Settings"), 0, KEY_ENUMERATE_SUB_KEYS | + KEY_SET_VALUE, &key); + if (ret != ERROR_SUCCESS) { + ThrowF_t(TRANS("Cannot enumerate display settings from registry\n")); + } + + TCHAR attach[2]; + if (bDisable) + lstrcpy(attach, _T("0")); + else + lstrcpy(attach, _T("1")); + + // enumerate all subkeys. there is at least one subkey for each secondary monitor, maybe more. + DWORD index = 0; + while (ret == ERROR_SUCCESS) + { + TCHAR keyName[500]; + DWORD keyNameSize = 500; + + ret = RegEnumKeyEx(key, index, keyName, &keyNameSize, 0, 0, 0, 0); + if (ret == ERROR_SUCCESS) + { + // open the subkey and set the AttachToDesktop value (0 or 1) + HKEY subKey; + ret = RegOpenKeyEx(key, keyName, 0, KEY_SET_VALUE, &subKey); + if (ret == ERROR_SUCCESS) + { + ret = RegSetValueEx(subKey, _T("AttachToDesktop"), 0, REG_SZ, + reinterpret_cast(attach), sizeof(TCHAR) * 2); + RegCloseKey(subKey); + ++index; + } + } + } + + RegCloseKey(key); + + bool failed = FALSE; + DWORD dev = 0; + DISPLAY_DEVICE dd; + dd.cb = sizeof(dd); + while (_pEnumDisplayDevices(0, dev, &dd, 0)) + { + if (!(dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) && !(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)) + { + // this is a secondary monitor, change display settings to what's currently stored in the registry + ret = _pChangeDisplaySettingsEx((const char*)dd.DeviceName, 0, 0, 0, 0); + // we get DISP_CHANGE_BADPARAM if we try to set settings for a monitor that doesn't exist + if (ret != DISP_CHANGE_SUCCESSFUL && ret != DISP_CHANGE_BADPARAM) + failed = TRUE; + } + + dev++; + } + if (failed) { + ThrowF_t(TRANS("Cannot change settings for at least one secondary monitor\n")); + } +} + +void MonitorsOff(void) +{ + extern BOOL _bDedicatedServer; + if (_bDedicatedServer) { + return; + } + + // check for WinNT or Win2k + BOOL bNT = FALSE; + OSVERSIONINFO osv; + memset(&osv, 0, sizeof(osv)); + osv.dwOSVersionInfoSize = sizeof(osv); + if (GetVersionEx(&osv) && osv.dwPlatformId==VER_PLATFORM_WIN32_NT) { + bNT = TRUE; + } + + // if there is more than one monitor, and OS is not WinNT + if (gfx_ctMonitors>1 && !bNT) { + CPrintF(TRANS("Multimonitor configuration detected...\n")); + // if multimon is not allowed + if (gfx_bDisableMultiMonSupport) { + CPrintF(TRANS(" Multimonitor support disallowed.\n")); + CPrintF(TRANS(" Disabling multimonitor...")); + // disable all but primary + try { + Mon_DisableEnable9x_t(/*bDisable = */ TRUE); + CPrintF(TRANS(" disabled\n")); + } catch(char *strError) { + CPrintF(TRANS(" error: %s\n"), strError); + } + gfx_bMultiMonDisabled = TRUE; + // if multimon is allowed + } else { + CPrintF(TRANS(" Multimonitor support was allowed.\n")); + } + } +} + +void MonitorsOn(void) +{ + // if multimon was disabled + if (gfx_bMultiMonDisabled) { + CPrintF(TRANS("Multimonitor support was disabled.\n")); + CPrintF(TRANS(" re-enabling multimonitor...")); + // enable all secondary + try { + Mon_DisableEnable9x_t(/*bDisable = */ FALSE); + CPrintF(TRANS(" enabled\n")); + } catch(char *strError) { + CPrintF(TRANS(" error: %s\n"), strError); + } + } +} diff --git a/Sources/Engine/Graphics/MultiMonitor.h b/Sources/Engine/Graphics/MultiMonitor.h new file mode 100644 index 0000000..accfb9b --- /dev/null +++ b/Sources/Engine/Graphics/MultiMonitor.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_MULTIMONITOR_H +#define SE_INCL_MULTIMONITOR_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// turn secondary monitors off if neccessary +extern void MonitorsOff(void); +// turn secondary monitors on if they were turned off +extern void MonitorsOn(void); + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/OpenGL.h b/Sources/Engine/Graphics/OpenGL.h new file mode 100644 index 0000000..7b5f88c --- /dev/null +++ b/Sources/Engine/Graphics/OpenGL.h @@ -0,0 +1,124 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_OPENGL_H +#define SE_INCL_OPENGL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include "gl_types.h" + +/* rcg10042001 wraped for platform. */ +#if (defined _MSC_VER) +#define DLLFUNCTION(dll, output, name, inputs, params, required) \ + extern output (__stdcall *p##name) inputs +#elif (defined PLATFORM_UNIX) +#define DLLFUNCTION(dll, output, name, inputs, params, required) \ + extern output (*p##name) inputs + #define __stdcall +#else + #error please define your platform here. +#endif + +#include "gl_functions.h" + +#undef DLLFUNCTION + +// extensions +extern void (__stdcall *pglLockArraysEXT)(GLint first, GLsizei count); +extern void (__stdcall *pglUnlockArraysEXT)(void); + +extern GLboolean (__stdcall *pwglSwapIntervalEXT)(GLint interval); +extern GLint (__stdcall *pwglGetSwapIntervalEXT)(void); + +extern void (__stdcall *pglActiveTextureARB)(GLenum texunit); +extern void (__stdcall *pglClientActiveTextureARB)(GLenum texunit); + +#ifdef PLATFORM_WIN32 /* !!! FIXME: Move to abstraction layer. --rcg. */ +// t-buffer support +extern char *(__stdcall *pwglGetExtensionsStringARB)(HDC hdc); +extern BOOL (__stdcall *pwglChoosePixelFormatARB)(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats); +extern BOOL (__stdcall *pwglGetPixelFormatAttribivARB)(HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, int *piAttributes, int *piValues); +#endif +extern void (__stdcall *pglTBufferMask3DFX)(GLuint mask); + +// GL_NV_vertex_array_range & GL_NV_fence +#ifdef PLATFORM_WIN32 /* !!! FIXME: Move to abstraction layer. --rcg. */ +extern void *(__stdcall *pwglAllocateMemoryNV)(GLint size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); +extern void (__stdcall *pwglFreeMemoryNV)(void *pointer); +#endif +extern void (__stdcall *pglVertexArrayRangeNV)(GLsizei length, void *pointer); +extern void (__stdcall *pglFlushVertexArrayRangeNV)(void); + +extern GLboolean (__stdcall *pglTestFenceNV)(GLuint fence); +extern GLboolean (__stdcall *pglIsFenceNV)(GLuint fence); +extern void (__stdcall *pglGenFencesNV)(GLsizei n, GLuint *fences); +extern void (__stdcall *pglDeleteFencesNV)(GLsizei n, const GLuint *fences); +extern void (__stdcall *pglSetFenceNV)(GLuint fence, GLenum condition); +extern void (__stdcall *pglFinishFenceNV)(GLuint fence); +extern void (__stdcall *pglGetFenceivNV)(GLuint fence, GLenum pname, GLint *params); + +// ATI GL_ATI[X]_pn_triangles +extern void (__stdcall *pglPNTrianglesiATI)( GLenum pname, GLint param); +extern void (__stdcall *pglPNTrianglesfATI)( GLenum pname, GLfloat param); + + +// additional tools ----------------------------------------------------- + + +// set color from croteam format +inline void glCOLOR( COLOR col) +{ +/* rcg10052001 Platform-wrappers. */ +#if (defined USE_PORTABLE_C) + col = ( ((col << 24) ) | + ((col << 8) & 0x00FF0000) | + ((col >> 8) & 0x0000FF00) | + ((col >> 24) ) ); + +#elif (defined _MSC_VER) + __asm { + mov eax,dword ptr [col] + bswap eax + mov dword ptr [col],eax + } + +#elif (defined __GNUC__) + __asm__ __volatile__ ( + "bswapl %%eax \n\t" + : "=a" (col) + : "a" (col) + ); + +#else + #error please define for your platform. +#endif + + pglColor4ubv((GLubyte*)&col); +} + +// check windows errors always +extern void WIN_CheckError(BOOL bRes, const char *strDescription); +#define WIN_CHECKERROR(result, string) WIN_CheckError(result, string); + +extern BOOL glbUsingVARs; // vertex_array_range + +// common textures +extern GLuint _uiFillTextureNo; // binding for flat fill emulator texture +extern GLuint _uiFogTextureNo; // binding for fog texture +extern GLuint _uiHazeTextureNo; // binding for haze texture +extern GLuint _uiPatternTextureNo; // binding for pattern texture + + +// internal! +inline void pglActiveTexture(INDEX texunit) +{ + ASSERT( texunit>=0 && texunit<4); + ASSERT( pglActiveTextureARB!=NULL); + ASSERT( pglClientActiveTextureARB!=NULL); + pglActiveTextureARB( GLenum(GL_TEXTURE0_ARB+texunit)); + pglClientActiveTextureARB(GLenum(GL_TEXTURE0_ARB+texunit)); +} + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/Raster.cpp b/Sources/Engine/Graphics/Raster.cpp new file mode 100644 index 0000000..6b37b2b --- /dev/null +++ b/Sources/Engine/Graphics/Raster.cpp @@ -0,0 +1,130 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include + +/* + * Raster functions + */ + +CRaster::CRaster(PIX ulWidth, PIX ulHeight, ULONG ulFlags) : ra_MainDrawPort() +{ + // remember width and height + ra_Width = ulWidth; + ra_Height = ulHeight; + + // clear uninitialized fields + ra_LockCount = 0; + + // set flags + ra_Flags = ulFlags; + + // add main drawport to list + ASSERT( ra_DrawPortList.IsEmpty()); + ra_DrawPortList.AddTail(ra_MainDrawPort.dp_NodeInRaster); + ra_MainDrawPort.dp_Raster = this; + ra_pvpViewPort = NULL; + + // when all is initialized correct the drawport dimensions + RecalculateDrawPortsDimensions(); +} + + +CRaster::~CRaster(void) +{ + // remove main drawport from list of drawports + ra_MainDrawPort.dp_NodeInRaster.Remove(); + // remove all other drawports in this raster + FORDELETELIST(CDrawPort, dp_NodeInRaster, ra_DrawPortList, litdp) { + // and delete each one + delete &litdp.Current(); + } + + // raster must be unlocked before destroying it + ASSERT(ra_LockCount==0); +} + + +/* Recalculate dimensions for all drawports. */ +void CRaster::RecalculateDrawPortsDimensions(void) +{ + // for all drawports in this raster + FOREACHINLIST(CDrawPort, dp_NodeInRaster, ra_DrawPortList, litdp) { + // recalculate dimensions to fit new size of raster + litdp.Current().RecalculateDimensions(); + } +} + + +/* + * Lock for drawing. + */ +BOOL CRaster::Lock() +{ + ASSERT( this!=NULL); + ASSERT( ra_LockCount>=0); + + // if raster size is too small in some axis + if( ra_Width<1 || ra_Height<1) { + // do not allow locking + ASSERTALWAYS( "Raster size to small to be locked!"); + return FALSE; + } + + // if allready locked + if( ra_LockCount>0) { + // just increment counter + ra_LockCount++; + return TRUE; + } + // if not already locked + else { + // try to lock with driver + BOOL bLocked = _pGfx->LockRaster(this); + // if succeeded in locking + if( bLocked) { + // set the counter to 1 + ra_LockCount = 1; + return TRUE; + } + // lock not ok + return FALSE; + } +} + + +/* + * Unlock after drawing. + */ +void CRaster::Unlock() +{ + ASSERT( this!=NULL); + ASSERT( ra_LockCount>0); + + // decrement counter + ra_LockCount--; + // if reached zero + if( ra_LockCount==0 ) { + // unlock it with driver + _pGfx->UnlockRaster(this); + } +} + + +/***** + * Change Raster size. + */ +void CRaster::Resize( PIX pixWidth, PIX pixHeight) +{ + ASSERT( pixWidth>0 && pixHeight>0); + if( pixWidth <=0) pixWidth = 1; + if( pixHeight<=0) pixHeight = 1; + ra_Width = pixWidth; + ra_Height = pixHeight; + RecalculateDrawPortsDimensions(); +} diff --git a/Sources/Engine/Graphics/Raster.h b/Sources/Engine/Graphics/Raster.h new file mode 100644 index 0000000..86810ec --- /dev/null +++ b/Sources/Engine/Graphics/Raster.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_RASTER_H +#define SE_INCL_RASTER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* + * Raster + */ + +class CRaster { +public: + CViewPort *ra_pvpViewPort; // viewport if existing + CDrawPort ra_MainDrawPort; // initial drawport for entire raster + CListHead ra_DrawPortList; // list of drawports + + PIX ra_Width; // number of pixels in one row + PIX ra_Height; // number of pixels in one column + SLONG ra_LockCount; // counter for memory locking + ULONG ra_Flags; // special flags + + /* Recalculate dimensions for all drawports. */ + void RecalculateDrawPortsDimensions(void); + + /* Constructor for given size. */ + CRaster( PIX pixWidth, PIX pixHeight, ULONG ulFlags); + /* Destructor. */ + virtual ~CRaster(void); + /* Change size of this raster and all it's drawports. */ + void Resize(PIX pixNewWidth, PIX pixNewHeight); + +public: + /* Lock for drawing. */ + virtual BOOL Lock(); + /* Unlock after drawing. */ + virtual void Unlock(); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/RenderPoly.h b/Sources/Engine/Graphics/RenderPoly.h new file mode 100644 index 0000000..b143f30 --- /dev/null +++ b/Sources/Engine/Graphics/RenderPoly.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_RENDERPOLY_H +#define SE_INCL_RENDERPOLY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// general structure +struct PolyVertex2D +{ + FLOAT pv2_fI, pv2_fJ; // DrawPort 2D coords + FLOAT pv2_f1oK; // Viewpoint (camera) distance (z-buffer value) + FLOAT pv2_fUoK, pv2_fVoK; // texture coordinates (for perspective mapping) +}; + +// functions for rendering triangles +extern void SetTriangleTexture( ULONG *pulCurrentMipmap, PIX pixMipWidth, PIX pixMipHeight); + +extern void DrawTriangle_Mask( UBYTE *pubMaskPlane, SLONG slMaskWidth, SLONG slMaskHeight, + struct PolyVertex2D *ppv2Vtx1, struct PolyVertex2D *ppv2Vtx2, + struct PolyVertex2D *ppv2Vtx3, BOOL bTransparency); + +// has model cast some cluster shadow (shadow renderer needs this) +extern BOOL _bSomeDarkExists; + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/RenderScene.h b/Sources/Engine/Graphics/RenderScene.h new file mode 100644 index 0000000..4d60606 --- /dev/null +++ b/Sources/Engine/Graphics/RenderScene.h @@ -0,0 +1,73 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_RENDERSCENE_H +#define SE_INCL_RENDERSCENE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +//#include + + +////////////////////////////////////////////////////////////////////////////////////////////////////// +// WORLD RENDER CONSTANTS + +// scene polygon flags +#define SPOF_SELECTED (1UL<< 0) // is polygon currently selected or not? +#define SPOF_TRANSPARENT (1UL<< 1) // polygon has alpha keying +#define SPOF_RENDERFOG (1UL<< 9) // polygon has fog +#define SPOF_RENDERHAZE (1UL<<10) // polygon has haze +#define SPOF_BACKLIGHT (1UL<<31) // used internaly + +// scene texture flags +#define STXF_CLAMPU (0x01) // clamp u coordinate in texture +#define STXF_CLAMPV (0x02) // clamp v coordinate in texture +#define STXF_REFLECTION (0x04) // clamp v coordinate in texture +#define STXF_AFTERSHADOW (0x08) // texture is to be applied after shadow + +#define STXF_BLEND_OPAQUE (0x00) // opaque texture (just put it on screen) +#define STXF_BLEND_ALPHA (0x10) // alpha blend with screen +#define STXF_BLEND_ADD (0x20) // add to screen +#define STXF_BLEND_SHADE (0x30) // darken or brighten (same as used by shadow maps) + +#define STXF_BLEND_MASK (0x70) + +/* + * RENDER SCENE structures (for world purposes) + */ +// structure that holds information about a polygon that is fully on partially visible +struct ScenePolygon { + ScenePolygon *spo_pspoSucc; // next polygon in list + INDEX spo_iVtx0; // first vertex in arrays + INDEX spo_ctVtx; // number of vertices in arrays + INDEX *spo_piElements; // array of triangle elements + INDEX spo_ctElements; // element count + + // texture and shadow parameters: 0, 1, 2 are texture maps, 3 is shadow + CMappingVectors spo_amvMapping[4]; // texture colors and alpha + COLOR spo_acolColors[4]; // texture flags + UBYTE spo_aubTextureFlags[4]; // current mip factors for each texture + // textures and shadowmap + class CTextureObject *spo_aptoTextures[3]; + class CShadowMap *spo_psmShadowMap; + + // internal for rendering + INDEX spo_iVtx0Pass; // index of first coordinate in per-pass arrays + COLOR spo_cColor; // polygon color (for flat or shadow modes) + ULONG spo_ulFlags; // polygon flags (selected or not? ...) + FLOAT spo_fNearestZ; // Z coord of nearest vertex to viewer + void *spo_pvPolygon; // user data for high level renderer (brush polygon) +}; + +// renders whole scene (all visible polygons) to screen drawport +void RenderScene( CDrawPort *pDP, ScenePolygon *pspoFirst, CAnyProjection3D &prProjection, + COLOR colSelection, BOOL bTranslucent); +// renders only scene z-buffer +void RenderSceneZOnly( CDrawPort *pDP, ScenePolygon *pspoFirst, CAnyProjection3D &prProjection); +// renders flat background of the scene +void RenderSceneBackground(CDrawPort *pDP, COLOR col); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/Shader.cpp b/Sources/Engine/Graphics/Shader.cpp new file mode 100644 index 0000000..e728d98 --- /dev/null +++ b/Sources/Engine/Graphics/Shader.cpp @@ -0,0 +1,836 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include +#include +#include +#include + +static INDEX _ctVertices =-1; +static INDEX _ctIndices =-1; +static INDEX _ctTextures =-1; +static INDEX _ctUVMaps =-1; +static INDEX _ctColors =-1; +static INDEX _ctFloats =-1; +static INDEX _ctLights =-1; + +static CAnyProjection3D *_paprProjection; // current projection +static Matrix12 *_pmObjToView = NULL; +static Matrix12 *_pmObjToAbs = NULL; + +static CShader *_pShader = NULL; // current shader +static GFXTexCoord *_pCurrentUVMap = NULL; // current UVMap + +static GFXVertex4 *_paVertices = NULL; // array of vertices +static GFXNormal *_paNormals = NULL; // array of normals +static GFXTexCoord **_paUVMaps = NULL; // array of uvmaps to chose from + +static GFXTexCoord *_paFogUVMap = NULL; // UVMap for fog pass +static GFXTexCoord *_paHazeUVMap = NULL; // UVMap for haze pass +static GFXColor *_pacolVtxHaze = NULL; // array of vertex colors for haze + +static CTextureObject **_paTextures = NULL;// array of textures to chose from +static INDEX *_paIndices = NULL; // current array of triangle indices + +static GFXColor _colAmbient = 0x000000FF; // Ambient color +static COLOR _colModel = 0x000000FF; // Model color +static GFXColor _colLight = 0x000000FF; // Light color +static FLOAT3D _vLightDir = FLOAT3D(0,0,0); // Light direction + +static COLOR _colConstant = NULL; // current set color +static COLOR *_paColors = NULL; // array of colors to chose from +static FLOAT *_paFloats = NULL; // array of floats to chose from +static ULONG _ulFlags = 0; + +// Vertex colors +static CStaticStackArray _acolVtxColors; // array of color values for each vertex +static CStaticStackArray _acolVtxModifyColors; // array of color modified values for each vertex +GFXColor *_pcolVtxColors = NULL; // pointer to vertex color array (points to current array of vertex colors) + +// vertex array that is returned if shader request vertices for modify +static CStaticStackArray _vModifyVertices; +static CStaticStackArray _uvUVMapForModify; + + +// Begin shader using +void shaBegin(CAnyProjection3D &aprProjection,CShader *pShader) +{ + // Chech that last shading ended with shaEnd + ASSERT(_pShader==NULL); + // Chech if shader exists + ASSERT(pShader!=NULL); + // Set current projection + _paprProjection = &aprProjection; + // Set pointer to shader + _pShader = pShader; +} + +// End shader using +void shaEnd(void) +{ + // Chech if shader exists + ASSERT(_pShader!=NULL); + // Call shader function + _pShader->ShaderFunc(); + // Clean used values + shaClean(); + + _pShader = NULL; +} + +// Render given model +void shaRender(void) +{ + ASSERT(_ctVertices>0); + ASSERT(_ctIndices>0); + ASSERT(_paVertices!=NULL); + ASSERT(_paIndices!=NULL); + + // Set vertices + gfxSetVertexArray(_paVertices,_ctVertices); + gfxLockArrays(); + + // if there is valid UVMap + if(_pCurrentUVMap!=NULL) { + gfxSetTexCoordArray(_pCurrentUVMap, FALSE); + } + + // if there is valid vertex color array + if(_pcolVtxColors!=NULL) { + gfxSetColorArray(_pcolVtxColors); + } + + // draw model with set params + gfxDrawElements( _ctIndices, _paIndices); + gfxUnlockArrays(); +} + +// Render aditional pass for fog and haze +void shaDoFogPass(void) +{ + // if full bright + if(shaGetFlags()&BASE_FULL_BRIGHT) { + // no fog pass + return; + } + + ASSERT(_paFogUVMap==NULL); + ASSERT(_paHazeUVMap==NULL); + + // Calculate fog and haze uvmap for this opaque surface + RM_DoFogAndHaze(TRUE); + // if fog uvmap has been given + if(_paFogUVMap!=NULL) { + // setup texture/color arrays and rendering mode + gfxSetTextureWrapping( GFX_CLAMP, GFX_CLAMP); + gfxSetTexture( _fog_ulTexture, _fog_tpLocal); + gfxSetTexCoordArray(_paFogUVMap, FALSE); + gfxSetConstantColor(_fog_fp.fp_colColor); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + gfxEnableBlend(); + // render fog pass + gfxDrawElements( _ctIndices, _paIndices); + } + // if haze uvmap has been given + if(_paHazeUVMap!=NULL) { + gfxSetTextureWrapping( GFX_CLAMP, GFX_CLAMP); + gfxSetTexture( _haze_ulTexture, _haze_tpLocal); + gfxSetTexCoordArray(_paHazeUVMap, TRUE); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + gfxEnableBlend(); + // set vertex color array for haze + if(_pacolVtxHaze !=NULL ) { + gfxSetColorArray( _pacolVtxHaze); + } + + // render fog pass + gfxDrawElements( _ctIndices, _paIndices); + } +} + +// Modify color for fog +void shaModifyColorForFog(void) +{ + // if full bright + if(shaGetFlags()&BASE_FULL_BRIGHT) { + // no fog colors + return; + } + + // Update this surface color array if fog or haze exists + RM_DoFogAndHaze(FALSE); +} + +// Calculate lightning for given model +void shaCalculateLight(void) +{ + // if full bright + if(shaGetFlags()&BASE_FULL_BRIGHT) { + GFXColor colLight = _colConstant; + GFXColor colAmbient; + GFXColor colConstant; + // is over brightning enabled + if(shaOverBrightningEnabled()) { + colAmbient = 0x7F7F7FFF; + } else { + colAmbient = 0xFFFFFFFF; + } + colConstant.MultiplyRGBA(colLight,colAmbient); + shaSetConstantColor(ByteSwap(colConstant.abgr)); + // no vertex colors + return; + } + + ASSERT(_paNormals!=NULL); + _acolVtxColors.PopAll(); + _acolVtxColors.Push(_ctVertices); + + GFXColor colModel = (GFXColor)_colModel; // Model color + GFXColor &colAmbient = (GFXColor)_colAmbient; // Ambient color + GFXColor &colLight = (GFXColor)_colLight; // Light color + GFXColor &colSurface = (GFXColor)_colConstant; // shader color + + colModel.MultiplyRGBA(colModel,colSurface); + + UBYTE ubColShift = 8; + SLONG slar = colAmbient.r; + SLONG slag = colAmbient.g; + SLONG slab = colAmbient.b; + + if(shaOverBrightningEnabled()) { + slar = ClampUp(slar,127L); + slag = ClampUp(slag,127L); + slab = ClampUp(slab,127L); + ubColShift = 8; + } else { + slar*=2; + slag*=2; + slab*=2; + ubColShift = 7; + } + + // for each vertex color + for(INDEX ivx=0;ivx<_ctVertices;ivx++) { + // calculate vertex light + FLOAT3D &vNorm = FLOAT3D(_paNormals[ivx].nx,_paNormals[ivx].ny,_paNormals[ivx].nz); + FLOAT fDot = vNorm % _vLightDir; + fDot = Clamp(fDot,0.0f,1.0f); + SLONG slDot = NormFloatToByte(fDot); + + _acolVtxColors[ivx].r = ClampUp(colModel.r * (slar + ((colLight.r * slDot)>>ubColShift))>>8,255L); + _acolVtxColors[ivx].g = ClampUp(colModel.g * (slag + ((colLight.g * slDot)>>ubColShift))>>8,255L); + _acolVtxColors[ivx].b = ClampUp(colModel.b * (slab + ((colLight.b * slDot)>>ubColShift))>>8,255L); + _acolVtxColors[ivx].a = colModel.a;//slDot; + } + // Set current vertex color array + _pcolVtxColors = &_acolVtxColors[0]; +} + +// Calculate lightning for given model +void shaCalculateLightForSpecular(void) +{ + ASSERT(_paNormals!=NULL); + _acolVtxColors.PopAll(); + _acolVtxColors.Push(_ctVertices); + + GFXColor colModel = (GFXColor)_colModel; // Model color + GFXColor &colAmbient = (GFXColor)_colAmbient; // Ambient color + GFXColor &colLight = (GFXColor)_colLight; // Light color + GFXColor &colSurface = (GFXColor)_colConstant; // shader color + + // colModel = MulColors(colModel.r,colSurface.abgr); + colModel.MultiplyRGBA(colModel,colSurface); + + UBYTE ubColShift = 8; + SLONG slar = colAmbient.r; + SLONG slag = colAmbient.g; + SLONG slab = colAmbient.b; + + if(shaOverBrightningEnabled()) { + slar = ClampUp(slar,127L); + slag = ClampUp(slag,127L); + slab = ClampUp(slab,127L); + ubColShift = 8; + } else { + slar*=2; + slag*=2; + slab*=2; + ubColShift = 7; + } + + // for each vertex color + for(INDEX ivx=0;ivx<_ctVertices;ivx++) { + // calculate vertex light + FLOAT3D &vNorm = FLOAT3D(_paNormals[ivx].nx,_paNormals[ivx].ny,_paNormals[ivx].nz); + FLOAT fDot = vNorm % _vLightDir; + fDot = Clamp(fDot,0.0f,1.0f); + SLONG slDot = NormFloatToByte(fDot); + + _acolVtxColors[ivx].r = ClampUp(colModel.r * (slar + ((colLight.r * slDot)>>ubColShift))>>8,255L); + _acolVtxColors[ivx].g = ClampUp(colModel.g * (slag + ((colLight.g * slDot)>>ubColShift))>>8,255L); + _acolVtxColors[ivx].b = ClampUp(colModel.b * (slab + ((colLight.b * slDot)>>ubColShift))>>8,255L); + _acolVtxColors[ivx].a = slDot;//colModel.a;//slDot; + } + // Set current wertex array + _pcolVtxColors = &_acolVtxColors[0]; +} + +// Clean all values +void shaClean(void) +{ + _ctVertices = -1; + _ctIndices = -1; + _ctColors = -1; + _ctTextures = -1; + _ctUVMaps = -1; + _ctLights = -1; + + _colConstant = 0; + _ulFlags = 0; + + _pShader = NULL; + _paVertices = NULL; + _paNormals = NULL; + _paIndices = NULL; + _paUVMaps = NULL; + _paTextures = NULL; + _paColors = NULL; + _paFloats = NULL; + _pCurrentUVMap = NULL; + _pcolVtxColors = NULL; + + _paFogUVMap = NULL; + _paHazeUVMap = NULL; + _pacolVtxHaze = NULL; + _pmObjToView = NULL; + _pmObjToAbs = NULL; + _paprProjection = NULL; + + _acolVtxColors.PopAll(); + _acolVtxModifyColors.PopAll(); + _vModifyVertices.PopAll(); + _uvUVMapForModify.PopAll(); + shaCullFace(GFX_BACK); +} + + +/* + * Shader value setting + */ + +// Set array of vertices +void shaSetVertexArray(GFXVertex4 *paVertices,INDEX ctVertices) +{ + ASSERT(paVertices!=NULL); + ASSERT(ctVertices>0); + // set pointer to new vertex array + _paVertices = paVertices; + _ctVertices = ctVertices; +} + +// Set array of normals +void shaSetNormalArray(GFXNormal *paNormals) +{ + ASSERT(paNormals!=NULL); + + _paNormals = paNormals; +} + +// Set array of indices +void shaSetIndices(INDEX *paIndices,INDEX ctIndices) +{ + ASSERT(paIndices!=NULL); + ASSERT(ctIndices>0); + + _paIndices = paIndices; + _ctIndices = ctIndices; +} + +// Set array of texture objects for shader +void shaSetTextureArray(CTextureObject **paTextureObject, INDEX ctTextures) +{ + _paTextures = paTextureObject; + _ctTextures = ctTextures; +} + +// Set array of uv maps +void shaSetUVMapsArray(GFXTexCoord **paUVMaps, INDEX ctUVMaps) +{ + ASSERT(paUVMaps!=NULL); + ASSERT(ctUVMaps>0); + + _paUVMaps = paUVMaps; + _ctUVMaps = ctUVMaps; +} + +// Set array of shader colors +void shaSetColorArray(COLOR *paColors, INDEX ctColors) +{ + ASSERT(paColors!=NULL); + ASSERT(ctColors>0); + + _paColors = paColors; + _ctColors = ctColors; +} + +// Set array of floats for shader +void shaSetFloatArray(FLOAT *paFloats, INDEX ctFloats) +{ + ASSERT(paFloats!=NULL); + _paFloats = paFloats; + _ctFloats = ctFloats; +} + +// Set shading flags +void shaSetFlags(ULONG ulFlags) +{ + _ulFlags = ulFlags; +} + +// Set base color of model +void shaSetModelColor(COLOR &colModel) +{ + _colModel = colModel; +} + +// Set light direction +void shaSetLightDirection(const FLOAT3D &vLightDir) +{ + _vLightDir = vLightDir; +} + +// Set light color +void shaSetLightColor(COLOR colAmbient, COLOR colLight) +{ + _colAmbient = colAmbient; + _colLight = colLight; +} + +// Set object to view matrix +void shaSetObjToViewMatrix(Matrix12 &mat) +{ + _pmObjToView = &mat; +} + +// Set object to abs matrix +void shaSetObjToAbsMatrix(Matrix12 &mat) +{ + _pmObjToAbs = &mat; +} + + + +// Set current texture index +void shaSetTexture(INDEX iTextureIndex) +{ + if(_paTextures==NULL || iTextureIndex<0 || iTextureIndex>=_ctTextures || _paTextures[iTextureIndex] == NULL) { + gfxDisableTexture(); + return; + } + ASSERT(iTextureIndex<_ctTextures); + + CTextureObject *pto = _paTextures[iTextureIndex]; + ASSERT(pto!=NULL); + + CTextureData *pTextureData = (CTextureData*)pto->GetData(); + const INDEX iFrameNo = pto->GetFrame(); + pTextureData->SetAsCurrent(iFrameNo); +} + +// Set current uvmap index +void shaSetUVMap(INDEX iUVMapIndex) +{ + ASSERT(iUVMapIndex>=0); + if(iUVMapIndex<=_ctUVMaps) { + _pCurrentUVMap = _paUVMaps[iUVMapIndex]; + } +} + +// Set current color index +void shaSetColor(INDEX icolIndex) +{ + ASSERT(icolIndex>=0); + + if(icolIndex>=_ctColors) { + _colConstant = C_WHITE|CT_OPAQUE; + } else { + _colConstant = _paColors[icolIndex]; + } + // Set this color as constant color + gfxSetConstantColor(_colConstant); +} + +// Set array of texcoords index +void shaSetTexCoords(GFXTexCoord *uvNewMap) +{ + _pCurrentUVMap = uvNewMap; +} + +// Set array of vertex colors +void shaSetVertexColors(GFXColor *paColors) +{ + _pcolVtxColors = paColors; +} + +// Set constant color +void shaSetConstantColor(const COLOR colConstant) +{ + gfxSetConstantColor(colConstant); +} + + +/* + * Shader value getting + */ + +// Get vertex count +INDEX shaGetVertexCount(void) +{ + return _ctVertices; +} + +// Get index count +INDEX shaGetIndexCount(void) +{ + return _ctIndices; +} + +// Get float from array of floats +FLOAT shaGetFloat(INDEX iFloatIndex) +{ + ASSERT(iFloatIndex>=0); + ASSERT(iFloatIndex<_ctFloats); + return _paFloats[iFloatIndex]; +} + +// Get texture from array of textures +CTextureObject *shaGetTexture( INDEX iTextureIndex) +{ + ASSERT( iTextureIndex>=0); + if( _paTextures==NULL || iTextureIndex>=_ctTextures || _paTextures[iTextureIndex]==NULL) return NULL; + else return _paTextures[iTextureIndex]; +} + +// Get color from color array +COLOR &shaGetColor(INDEX iColorIndex) +{ + ASSERT(iColorIndex<_ctColors); + return _paColors[iColorIndex]; +} + +// Get shading flags +ULONG &shaGetFlags() +{ + return _ulFlags; +} + +// Get base color of model +COLOR &shaGetModelColor(void) +{ + return _colModel; +} + +// Get light direction +FLOAT3D &shaGetLightDirection(void) +{ + return _vLightDir; +} + +// Get current light color +COLOR &shaGetLightColor(void) +{ + return _colLight.abgr; +} + +// Get current ambient volor +COLOR &shaGetAmbientColor(void) +{ + return _colAmbient.abgr; +} + +// Get current set color +COLOR &shaGetCurrentColor(void) +{ + return _colConstant; +} + +// Get vertex array +GFXVertex4 *shaGetVertexArray(void) +{ + return _paVertices; +} + +// Get index array +INDEX *shaGetIndexArray(void) +{ + return _paIndices; +} + +// Get normal array +GFXNormal *shaGetNormalArray(void) +{ + return _paNormals; +} + +// Get uvmap array from array of uvmaps +GFXTexCoord *shaGetUVMap(INDEX iUVMapIndex) +{ + ASSERT( iUVMapIndex>=0); + if( iUVMapIndex>=_ctUVMaps) return NULL; + else return _paUVMaps[iUVMapIndex]; +} + +// Get color array +GFXColor *shaGetColorArray(void) +{ + return &_acolVtxColors[0]; +} + + +// Get empty color array for modifying +GFXColor *shaGetNewColorArray(void) +{ + ASSERT(_ctVertices!=0); + _acolVtxModifyColors.PopAll(); + _acolVtxModifyColors.Push(_ctVertices); + return &_acolVtxModifyColors[0]; +} + +// Get empty texcoords array for modifying +GFXTexCoord *shaGetNewTexCoordArray(void) +{ + ASSERT(_ctVertices!=0); + _uvUVMapForModify.PopAll(); + _uvUVMapForModify.Push(_ctVertices); + return &_uvUVMapForModify[0]; +} + +// Get empty vertex array for modifying +GFXVertex *shaGetNewVertexArray(void) +{ + ASSERT(_ctVertices!=0); + _vModifyVertices.PopAll(); + _vModifyVertices.Push(_ctVertices); + return &_vModifyVertices[0]; +} + +// Get current projection +CAnyProjection3D *shaGetProjection() +{ + return _paprProjection; +} + +// Get object to view matrix +Matrix12 *shaGetObjToViewMatrix(void) +{ + ASSERT(_pmObjToView!=NULL); + return _pmObjToView; +} + +// Get object to abs matrix +Matrix12 *shaGetObjToAbsMatrix(void) +{ + ASSERT(_pmObjToAbs!=NULL); + return _pmObjToAbs; +} + + + +/* + * Shader states + */ + +// Set face culling +void shaCullFace(GfxFace eFace) +{ + if(_paprProjection !=NULL && (*_paprProjection)->pr_bMirror) { + gfxFrontFace( GFX_CW); + } else { + gfxFrontFace( GFX_CCW); + } + gfxCullFace(eFace); +} + +// Set blending operations +void shaBlendFunc(GfxBlend eSrc, GfxBlend eDst) +{ + gfxBlendFunc(eSrc,eDst); +} + +// Set texture modulation mode +void shaSetTextureModulation(INDEX iScale) +{ + gfxSetTextureModulation(iScale); +} + +// Enable/Disable blening +void shaEnableBlend(void) +{ + gfxEnableBlend(); +} +void shaDisableBlend(void) +{ + gfxDisableBlend(); +} + +// Enable/Disable alpha test +void shaEnableAlphaTest(void) +{ + gfxEnableAlphaTest(); +} +void shaDisableAlphaTest(void) +{ + gfxDisableAlphaTest(); +} + +// Enable/Disable depth test +void shaEnableDepthTest(void) +{ + gfxEnableDepthTest(); +} +void shaDisableDepthTest(void) +{ + gfxDisableDepthTest(); +} + +// Enable/Disable depth write +void shaEnableDepthWrite(void) +{ + gfxEnableDepthWrite(); +} +void shaDisableDepthWrite(void) +{ + gfxDisableDepthWrite(); +} + +// Set depth buffer compare mode +void shaDepthFunc(GfxComp eComp) +{ + gfxDepthFunc(eComp); +} + +// Set texture wrapping +void shaSetTextureWrapping( enum GfxWrap eWrapU, enum GfxWrap eWrapV) +{ + gfxSetTextureWrapping(eWrapU,eWrapV); +} + + +// Set uvmap for fog +void shaSetFogUVMap(GFXTexCoord *paFogUVMap) +{ + _paFogUVMap = paFogUVMap; +} + +// Set uvmap for haze +void shaSetHazeUVMap(GFXTexCoord *paHazeUVMap) +{ + _paHazeUVMap = paHazeUVMap; +} + +// Set array of vertex colors used in haze +void shaSetHazeColorArray(GFXColor *paHazeColors) +{ + _pacolVtxHaze = paHazeColors; +} + +BOOL shaOverBrightningEnabled(void) +{ + // determine multitexturing capability for overbrighting purposes + extern INDEX mdl_bAllowOverbright; + return mdl_bAllowOverbright && _pGfx->gl_ctTextureUnits>1; +} + + +/* + * Shader handling + */ + +// Constructor +CShader::CShader() +{ + hLibrary = NULL; + ShaderFunc = NULL; + GetShaderDesc = NULL; +} + +// Destructor +CShader::~CShader() +{ + // Release shader dll + Clear(); +} + +// Clear shader +void CShader::Clear(void) +{ + ShaderFunc = NULL; + GetShaderDesc = NULL; + // release dll + if(hLibrary!=NULL) FreeLibrary(hLibrary); +} + +// Count used memory +SLONG CShader::GetUsedMemory(void) +{ + return sizeof(CShader); +} + +// Write to stream +void CShader::Write_t(CTStream *ostrFile) +{ +} + +// Read from stream +void CShader::Read_t(CTStream *istrFile) +{ + // read the dll filename and class name from the stream + CTFileName fnmDLL; + CTString strShaderFunc; + CTString strShaderInfo; + + fnmDLL.ReadFromText_t(*istrFile, "Package: "); + strShaderFunc.ReadFromText_t(*istrFile, "Name: "); + strShaderInfo.ReadFromText_t(*istrFile, "Info: "); + + // create name of dll + #ifndef NDEBUG + fnmDLL = _fnmApplicationExe.FileDir()+fnmDLL.FileName()+/*_strModExt+*/"D"+fnmDLL.FileExt(); + #else + fnmDLL = _fnmApplicationExe.FileDir()+fnmDLL.FileName()+/*_strModExt+*/fnmDLL.FileExt(); + #endif + + CTFileName fnmExpanded; + ExpandFilePath(EFP_READ | EFP_NOZIPS,fnmDLL,fnmExpanded); + // set new error mode + UINT iOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); + // load dll + hLibrary = LoadLibraryA((const char*)fnmExpanded); + // return last error mode + SetErrorMode(iOldErrorMode); + // check if library has loaded + if(hLibrary==NULL) + { + // report error + istrFile->Throw_t("Error loading '%s' library",(const char*)fnmExpanded); + return; + } + // get pointer to shader render function + ShaderFunc = (void(*)(void))GetProcAddress(hLibrary,(const char*)strShaderFunc); + // if error accured + if(ShaderFunc==NULL) + { + // report error + istrFile->Throw_t("GetProcAddress 'ShaderFunc' Error"); + } + // get pointer to shader info function + GetShaderDesc = (void(*)(ShaderDesc&))GetProcAddress(hLibrary,(const char*)strShaderInfo); + // if error accured + if(GetShaderDesc==NULL) { + // report error + istrFile->Throw_t("GetProcAddress 'ShaderDesc' Error"); + } +} + diff --git a/Sources/Engine/Graphics/Shader.h b/Sources/Engine/Graphics/Shader.h new file mode 100644 index 0000000..c3a4a0a --- /dev/null +++ b/Sources/Engine/Graphics/Shader.h @@ -0,0 +1,222 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SHADER_H +#define SE_INCL_SHADER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include + +// Shader flags +#define BASE_DOUBLE_SIDED (1UL<<0) // Double sided +#define BASE_FULL_BRIGHT (1UL<<1) // Full bright + + +struct ShaderDesc +{ + CStaticArray sd_astrTextureNames; + CStaticArray sd_astrTexCoordNames; + CStaticArray sd_astrColorNames; + CStaticArray sd_astrFloatNames; + CStaticArray sd_astrFlagNames; + CTString sd_strShaderInfo; +}; + +struct ShaderParams +{ + ShaderParams() { + sp_ulFlags = 0; + } + ~ShaderParams() { + sp_aiTextureIDs.Clear(); + sp_aiTexCoordsIndex.Clear(); + sp_acolColors.Clear(); + sp_afFloats.Clear(); + } + CStaticArray sp_aiTextureIDs; + CStaticArray sp_aiTexCoordsIndex; + CStaticArray sp_acolColors; + CStaticArray sp_afFloats; + ULONG sp_ulFlags; +}; + +class ENGINE_API CShader : public CSerial +{ +public: + CShader(); + ~CShader(); + + HINSTANCE hLibrary; + void (*ShaderFunc)(void); + void (*GetShaderDesc)(ShaderDesc &shDesc); + + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * + void Clear(void); + SLONG GetUsedMemory(void); +}; + +// Begin shader using +ENGINE_API void shaBegin(CAnyProjection3D &aprProjection,CShader *pShader); +// End shader using +ENGINE_API void shaEnd(void); +// Render given model +ENGINE_API void shaRender(void); +// Render aditional pass for fog and haze +ENGINE_API void shaDoFogPass(void); +// Modify color for fog +ENGINE_API void shaModifyColorForFog(void); +// Calculate lightning for given model +ENGINE_API void shaCalculateLight(void); +// Calculate lightning for given model (for specular shader) +ENGINE_API void shaCalculateLightForSpecular(void); +// Clear temp vars used by shader +ENGINE_API void shaClean(void); + + +// Set array of vertices +ENGINE_API void shaSetVertexArray(GFXVertex4 *paVertices,INDEX ctVertices); +// Set array of normals +ENGINE_API void shaSetNormalArray(GFXNormal *paNormals); +// Set array of indices +ENGINE_API void shaSetIndices(INDEX *paIndices, INDEX ctIndices); +// Set array of texture objects for shader +ENGINE_API void shaSetTextureArray(CTextureObject **paTextureObject, INDEX ctTextures); +// Set array of uv maps +ENGINE_API void shaSetUVMapsArray(GFXTexCoord **paUVMaps, INDEX ctUVMaps); +// Set array of shader colors +ENGINE_API void shaSetColorArray(COLOR *paColors, INDEX ctColors); +// Set array of floats for shader +ENGINE_API void shaSetFloatArray(FLOAT *paFloats, INDEX ctFloats); +// Set shading flags +ENGINE_API void shaSetFlags(ULONG ulFlags); +// Set base color of model +ENGINE_API void shaSetModelColor(COLOR &colModel); +// Set light direction +ENGINE_API void shaSetLightDirection(const FLOAT3D &vLightDir); +// Set light color +ENGINE_API void shaSetLightColor(COLOR colAmbient, COLOR colLight); +// Set object to view matrix +ENGINE_API void shaSetObjToViewMatrix(Matrix12 &mat); +// Set object to abs matrix +ENGINE_API void shaSetObjToAbsMatrix(Matrix12 &mat); + + +// Set current texture index +ENGINE_API void shaSetTexture(INDEX iTexture); +// Set current uvmap index +ENGINE_API void shaSetUVMap(INDEX iUVMap); +// Set current color index +ENGINE_API void shaSetColor(INDEX icolIndex); +// Set array of texcoords index +ENGINE_API void shaSetTexCoords(GFXTexCoord *uvNewMap); +// Set array of vertex colors +ENGINE_API void shaSetVertexColors(GFXColor *paColors); +// Set constant color +ENGINE_API void shaSetConstantColor(const COLOR colConstant); + + +// Get vertex count +ENGINE_API INDEX shaGetVertexCount(void); +// Get index count +ENGINE_API INDEX shaGetIndexCount(void); +// Get float from array of floats +ENGINE_API FLOAT shaGetFloat(INDEX iFloatIndex); +// Get texture from array of textures +ENGINE_API CTextureObject *shaGetTexture( INDEX iTextureIndex); +// Get base color from array of colors +ENGINE_API COLOR &shaGetColor(INDEX iColorIndex); +// Get shading flags +ENGINE_API ULONG &shaGetFlags(); +// Get base color of model +ENGINE_API COLOR &shaGetModelColor(void); +// Get light direction +ENGINE_API FLOAT3D &shaGetLightDirection(void); +// Get current light color +ENGINE_API COLOR &shaGetLightColor(void); +// Get current ambient volor +ENGINE_API COLOR &shaGetAmbientColor(void); +// Get current set color +ENGINE_API COLOR &shaGetCurrentColor(void); +// Get vertex array +ENGINE_API GFXVertex4 *shaGetVertexArray(void); +// Get index array +ENGINE_API INDEX *shaGetIndexArray(void); +// Get normal array +ENGINE_API GFXNormal *shaGetNormalArray(void); +// Get uvmap array from array of uvmaps +ENGINE_API GFXTexCoord *shaGetUVMap( INDEX iUVMapIndex); +// Get color array +ENGINE_API GFXColor *shaGetColorArray(void); + +// Get empty color array for modifying +ENGINE_API GFXColor *shaGetNewColorArray(void); +// Get empty texcoords array for modifying +ENGINE_API GFXTexCoord *shaGetNewTexCoordArray(void); +// Get empty v array for modifying +ENGINE_API GFXVertex *shaGetNewVertexArray(void); + +// Get current projection +ENGINE_API CAnyProjection3D *shaGetProjection(void); +// Get object to view matrix +ENGINE_API Matrix12 *shaGetObjToViewMatrix(void); +// Get object to abs matrix +ENGINE_API Matrix12 *shaGetObjToAbsMatrix(void); + + +// Set face culling +ENGINE_API void shaCullFace(GfxFace eFace); +// Set blending operations +ENGINE_API void shaBlendFunc(GfxBlend eSrc, GfxBlend eDst); +// Set texture modulation mode +ENGINE_API void shaSetTextureModulation(INDEX iScale); +// Enable/Disable blening +ENGINE_API void shaEnableBlend(void); +ENGINE_API void shaDisableBlend(void); +// Enable/Disable alpha test +ENGINE_API void shaEnableAlphaTest(void); +ENGINE_API void shaDisableAlphaTest(void); +// Enable/Disable depth test +ENGINE_API void shaEnableDepthTest(void); +ENGINE_API void shaDisableDepthTest(void); +// Enable/Disable depth write +ENGINE_API void shaEnableDepthWrite(void); +ENGINE_API void shaDisableDepthWrite(void); +// Set depth buffer compare mode +ENGINE_API void shaDepthFunc(GfxComp eComp); +// Set texture wrapping +ENGINE_API void shaSetTextureWrapping( enum GfxWrap eWrapU, enum GfxWrap eWrapV); + +// Set uvmap for fog +ENGINE_API void shaSetFogUVMap(GFXTexCoord *paFogUVMap); +// Set uvmap for haze +ENGINE_API void shaSetHazeUVMap(GFXTexCoord *paHazeUVMap); +// Set array of vertex colors used in haze +ENGINE_API void shaSetHazeColorArray(GFXColor *paHazeColors); + +// Is overbrightning enabled +ENGINE_API BOOL shaOverBrightningEnabled(void); + +#if (defined _MSC_VER) + #define DECLSPEC_DLLEXPORT _declspec (dllexport) +#else + #define DECLSPEC_DLLEXPORT +#endif + +#define SHADER_MAIN(name) \ + extern "C" void DECLSPEC_DLLEXPORT Shader_##name (void);\ + SYMBOLLOCATOR(Shader_##name);\ + extern "C" void DECLSPEC_DLLEXPORT Shader_##name (void) + +#define SHADER_DESC(name,x) \ + extern "C" void DECLSPEC_DLLEXPORT Shader_Desc_##name (x);\ + SYMBOLLOCATOR(Shader_Desc_##name);\ + extern "C" void DECLSPEC_DLLEXPORT Shader_Desc_##name (x) + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/ShadowMap.cpp b/Sources/Engine/Graphics/ShadowMap.cpp new file mode 100644 index 0000000..0400f27 --- /dev/null +++ b/Sources/Engine/Graphics/ShadowMap.cpp @@ -0,0 +1,670 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#define SHADOWMAXBYTES (256*256*4*4/3) + +extern INDEX shd_iStaticSize; +extern INDEX shd_iDynamicSize; +extern INDEX shd_bFineQuality; +extern INDEX shd_iDithering; +extern INDEX shd_bDynamicMipmaps; + +extern INDEX gap_bAllowSingleMipmap; +extern FLOAT gfx_tmProbeDecay; + +extern BOOL _bShadowsUpdated; +extern BOOL _bMultiPlayer; + + +/* + * Routines that manipulates with shadow cluster map class + */ + +CShadowMap::CShadowMap() +{ + sm_pulCachedShadowMap = NULL; + sm_pulDynamicShadowMap = NULL; + sm_slMemoryUsed = 0; + sm_ulObject = NONE; + sm_ulProbeObject = NONE; + sm_ulInternalFormat = NONE; + sm_iRenderFrame = -1; + sm_ulFlags = NONE; + Clear(); +} + + +CShadowMap::~CShadowMap() +{ + Clear(); +} + + +// report shadowmap memory usage (in bytes) +ULONG CShadowMap::GetShadowSize(void) +{ + CBrushPolygon *pbpo=((CBrushShadowMap *)this)->GetBrushPolygon(); + ULONG ulFlags=pbpo->bpo_ulFlags; + BOOL bIsTransparent = (ulFlags&BPOF_PORTAL) && !(ulFlags&(BPOF_TRANSLUCENT|BPOF_TRANSPARENT)); + BOOL bTakesShadow = !(ulFlags&BPOF_FULLBRIGHT); + BOOL bIsFlat = sm_pulCachedShadowMap==&sm_colFlat; + if( bIsTransparent || !bTakesShadow || bIsFlat) return 0; // not influenced + const PIX pixSizeU = sm_mexWidth >>sm_iFirstMipLevel; + const PIX pixSizeV = sm_mexHeight>>sm_iFirstMipLevel; + return pixSizeU*pixSizeV *BYTES_PER_TEXEL; +} + + +// cache the shadow map +void CShadowMap::Cache( INDEX iWantedMipLevel) +{ + _pfGfxProfile.StartTimer( CGfxProfile::PTI_CACHESHADOW); + _bShadowsUpdated = TRUE; + + // level must be in valid range and caching has to be needed + ASSERT( iWantedMipLevel>=sm_iFirstMipLevel && iWantedMipLevel<=sm_iLastMipLevel); + ASSERT( sm_pulCachedShadowMap==NULL || iWantedMipLevel>iWantedMipLevel; + const PIX pixSizeV = sm_mexHeight>>iWantedMipLevel; + const SLONG slSize = GetMipmapOffset( 15, pixSizeU, pixSizeV) *BYTES_PER_TEXEL; + const BOOL bWasFlat = sm_pulCachedShadowMap==&sm_colFlat; + const BOOL bCached = sm_pulCachedShadowMap!=NULL; + + // determine whether shadowmap is all flat (once flat - always flat!) + if( IsShadowFlat(sm_colFlat)) { + // release memory if allocated + if( bCached) { + ASSERT( sm_slMemoryUsed>0 && sm_slMemoryUsed<=SHADOWMAXBYTES); + if( !bWasFlat) FreeMemory( sm_pulCachedShadowMap); + } + sm_pulCachedShadowMap = &sm_colFlat; + sm_iFirstCachedMipLevel = iWantedMipLevel; + sm_slMemoryUsed = slSize; + // add it to shadow list + if( !sm_lnInGfx.IsLinked()) _pGfx->gl_lhCachedShadows.AddTail(sm_lnInGfx); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_CACHESHADOW); + return; + } + + // if not yet allocated + if( !bCached || bWasFlat) + { + // allocate the memory + sm_pulCachedShadowMap = (ULONG*)AllocMemory(slSize); + sm_slMemoryUsed = slSize; + ASSERT( sm_slMemoryUsed>0 && sm_slMemoryUsed<=SHADOWMAXBYTES); + } + // if already allocated, but too small + else if( iWantedMipLevel0 && sm_slMemoryUsed<=SHADOWMAXBYTES); + if( slSize>sm_slMemoryUsed && !bWasFlat) { + // copy old shadow map at the end of buffer + memcpy( pulNew + (slSize-sm_slMemoryUsed)/BYTES_PER_TEXEL, sm_pulCachedShadowMap, sm_slMemoryUsed); + } // free old block if needed and use the new one + if( !bWasFlat) FreeMemory( sm_pulCachedShadowMap); + sm_pulCachedShadowMap = pulNew; + sm_slMemoryUsed = slSize; + ASSERT( sm_slMemoryUsed>0 && sm_slMemoryUsed<=SHADOWMAXBYTES); + } else { + // WHAT? + ASSERTALWAYS( "Trying to cache shadowmap again in the same mipmap!"); + } + + // let the higher level driver mix its layers + INDEX iLastMipLevelToCache = Min( sm_iLastMipLevel, sm_iFirstCachedMipLevel-1L); + sm_iFirstCachedMipLevel = iWantedMipLevel; + ASSERT( iWantedMipLevel <= iLastMipLevelToCache); + + // colorize shadowmap? + extern INDEX shd_bColorize; + if( _bMultiPlayer) shd_bColorize = FALSE; // don't allow in multiplayer mode! + if( shd_bColorize) { + #define GSIZE 4.0f + #define RSIZE 8.0f + FLOAT fLogSize = Log2((sm_mexWidth>>sm_iFirstCachedMipLevel) * (sm_mexHeight>>sm_iFirstCachedMipLevel)) /2; + fLogSize = Max(fLogSize,GSIZE) -GSIZE; + FLOAT fR = fLogSize / (RSIZE-GSIZE); + COLOR colSize; + if( fR>0.5f) colSize = LerpColor( C_dYELLOW, C_dRED, (fR-0.5f)*2); + else colSize = LerpColor( C_dGREEN, C_dYELLOW, fR*2); + // fill! + for( INDEX iPix=0; iPixgl_lhCachedShadows.AddTail( sm_lnInGfx); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_CACHESHADOW); +} + + +// update dynamic layers of the shadow map +// (returns mip in which shadow needs to be uploaded) +ULONG CShadowMap::UpdateDynamicLayers(void) +{ + // call this only if needed + ASSERT( sm_ulFlags&SMF_DYNAMICINVALID); + sm_ulFlags &= ~SMF_DYNAMICINVALID; + + // if there are no dynamic layers + if( !HasDynamicLayers()) { + // free dynamic shadows if allocated + if( sm_pulDynamicShadowMap!=NULL) { + _bShadowsUpdated = TRUE; + ASSERT( sm_slMemoryUsed>0 && sm_slMemoryUsed<=SHADOWMAXBYTES); + FreeMemory( sm_pulDynamicShadowMap); + sm_pulDynamicShadowMap = NULL; + return sm_iFirstCachedMipLevel; + } else return 31; + } + + _pfGfxProfile.StartTimer( CGfxProfile::PTI_CACHESHADOW); + + // allocate the memory if not yet allocated + if( sm_pulDynamicShadowMap==NULL) { + ASSERT( sm_slMemoryUsed>0 && sm_slMemoryUsed<=SHADOWMAXBYTES); + sm_pulDynamicShadowMap = (ULONG*)AllocMemory(sm_slMemoryUsed); + } + + // determine and clamp to max allowed dynamic shadow dimension + const INDEX iMinSize = Max( shd_iStaticSize-2L, 5L); + shd_iDynamicSize = Clamp( shd_iDynamicSize, iMinSize, shd_iStaticSize); + PIX pixClampAreaSize = 1L<<(shd_iDynamicSize*2); + INDEX iFinestMipLevel = sm_iFirstCachedMipLevel + + ClampTextureSize( pixClampAreaSize, _pGfx->gl_pixMaxTextureDimension, + sm_mexWidth>>sm_iFirstCachedMipLevel, sm_mexHeight>>sm_iFirstCachedMipLevel); + // check if need to generate only one mip-map + INDEX iLastMipLevel = sm_iLastMipLevel; + if( !shd_bDynamicMipmaps && gap_bAllowSingleMipmap) iLastMipLevel = iFinestMipLevel; + // let the higher level driver mix its layers + MixLayers( iFinestMipLevel, iLastMipLevel, TRUE); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_CACHESHADOW); + + // skip if there was nothing to mix-in + if( sm_ulFlags&SMF_DYNAMICBLACK) return 31; + _bShadowsUpdated = TRUE; + return iFinestMipLevel; +} + + +// invalidate the shadow map +void CShadowMap::Invalidate( BOOL bDynamicOnly/*=FALSE*/) +{ + // if only dynamic layers are to be uncached + if( bDynamicOnly) { + // just mark that they are not valid any more + sm_ulFlags |= SMF_DYNAMICINVALID; + // if static layers are to be uncached + } else { + // mark that no mipmaps are cached + sm_iFirstCachedMipLevel = 31; + } +} + + +// mark that shadow has been drawn +void CShadowMap::MarkDrawn(void) +{ + // remove from list + ASSERT( sm_lnInGfx.IsLinked()); + sm_lnInGfx.Remove(); + // set time stamp + sm_tvLastDrawn = _pTimer->GetHighPrecisionTimer(); + // put at the end of the list + _pGfx->gl_lhCachedShadows.AddTail(sm_lnInGfx); +} + + +// uncache the shadow map (returns total ammount of memory that has been freed) +SLONG CShadowMap::Uncache( void) +{ + _bShadowsUpdated = TRUE; + // discard uploaded portion + if( sm_ulObject!=NONE) { + gfxDeleteTexture(sm_ulObject); + gfxDeleteTexture(sm_ulProbeObject); + sm_ulInternalFormat = NONE; + } + SLONG slFreed = 0; + // if dynamic allocated, release memory + if( sm_pulDynamicShadowMap != NULL) { + FreeMemory( sm_pulDynamicShadowMap); + sm_pulDynamicShadowMap = NULL; + ASSERT( sm_slMemoryUsed>0 && sm_slMemoryUsed<=SHADOWMAXBYTES); + slFreed += sm_slMemoryUsed; + } + // if static non-flat has been allocated + if( sm_pulCachedShadowMap!=NULL) { + // release memory + ASSERT( sm_slMemoryUsed>0 && sm_slMemoryUsed<=SHADOWMAXBYTES); + if( sm_pulCachedShadowMap!=&sm_colFlat) { + FreeMemory( sm_pulCachedShadowMap); + slFreed += sm_slMemoryUsed; + } else slFreed += sizeof(sm_colFlat); + } + // reset params + sm_iFirstCachedMipLevel = 31; + sm_pulCachedShadowMap = NULL; + sm_slMemoryUsed = 0; + sm_tvLastDrawn = 0I64; + sm_iRenderFrame = -1; + sm_ulFlags = NONE; + sm_tpLocal.Clear(); + // if added to list of all shadows, remove from there + if( sm_lnInGfx.IsLinked()) sm_lnInGfx.Remove(); + return slFreed; +} + + +// clear the object +void CShadowMap::Clear() +{ + // uncache the shadow map + Uncache(); + // reset structure members + sm_pulCachedShadowMap = NULL; + sm_pulDynamicShadowMap = NULL; + sm_iFirstMipLevel = 0; + sm_slMemoryUsed = 0; + sm_tvLastDrawn = 0I64; + sm_mexOffsetX = 0; + sm_mexOffsetY = 0; + sm_mexWidth = 0; + sm_mexHeight = 0; + sm_ulFlags = NONE; +} + + +// initialize the shadow map +void CShadowMap::Initialize( INDEX iMipLevel, MEX mexOffsetX, MEX mexOffsetY, MEX mexWidth, MEX mexHeight) +{ + // clear old shadow + Clear(); + // just remember new values + sm_iFirstMipLevel = iMipLevel; + sm_mexOffsetX = mexOffsetX; + sm_mexOffsetY = mexOffsetY; + sm_mexWidth = mexWidth; + sm_mexHeight = mexHeight; + sm_iLastMipLevel = FastLog2( Min(mexWidth, mexHeight)); + ASSERT( (mexWidth >>sm_iLastMipLevel)>=1); + ASSERT( (mexHeight>>sm_iLastMipLevel)>=1); +} + + +// skip old shadows saved in stream +void CShadowMap::Read_old_t(CTStream *pstrm) // throw char * +{ + Clear(); + // read shadow map header + // pstrm->ExpectID_t( CChunkID("CTSM")); // read in Read_t() + if( pstrm->GetSize_t() != 5*4) throw( TRANS("Invalid shadow cluster map file.")); + + *pstrm >> (INDEX)sm_iFirstMipLevel; + INDEX iNoOfMipmaps; + *pstrm >> (INDEX)iNoOfMipmaps; + *pstrm >> (MEX)sm_mexOffsetX; + *pstrm >> (MEX)sm_mexOffsetY; + *pstrm >> (MEX)sm_mexWidth; + *pstrm >> (MEX)sm_mexHeight; + BOOL bStaticImagePresent, bAnimatingImagePresent; + *pstrm >> (INDEX&)bStaticImagePresent; + *pstrm >> (INDEX&)bAnimatingImagePresent; + + // skip mip-map offsets + pstrm->Seek_t( MAX_MEX_LOG2*4, CTStream::SD_CUR); + + // skip the shadow map data + if( bStaticImagePresent) { + pstrm->ExpectID_t("SMSI"); + SLONG slSize; + *pstrm>>slSize; + pstrm->Seek_t(slSize, CTStream::SD_CUR); + } + if( bAnimatingImagePresent) { + pstrm->ExpectID_t("SMAI"); + SLONG slSize; + *pstrm>>slSize; + pstrm->Seek_t(slSize, CTStream::SD_CUR); + } +} + + +// reads image info raw format from file +void CShadowMap::Read_t( CTStream *pstrm) // throw char * +{ + Clear(); + + // read the header chunk ID + CChunkID cidHeader = pstrm->GetID_t(); + // if it is the old shadow format + if (cidHeader==CChunkID("CTSM")) { + // read shadows in old format + Read_old_t(pstrm); + return; + // if it is not the new shadow format + } else if (!(cidHeader==CChunkID("LSHM"))) { // layered shadow map + // error + FatalError(TRANS("Error loading shadow map! Wrong header chunk.")); + } + + // load the shadow map data + *pstrm >> sm_ulFlags; + *pstrm >> sm_iFirstMipLevel; + *pstrm >> sm_mexOffsetX; + *pstrm >> sm_mexOffsetY; + *pstrm >> sm_mexWidth; + *pstrm >> sm_mexHeight; + + sm_iLastMipLevel = FastLog2( Min(sm_mexWidth, sm_mexHeight)); + ASSERT((sm_mexWidth >>sm_iLastMipLevel)>=1); + ASSERT((sm_mexHeight>>sm_iLastMipLevel)>=1); + + // read the layers of the shadow + ReadLayers_t(pstrm); +} + + +// writes shadow cluster map format to file +void CShadowMap::Write_t( CTStream *pstrm) // throw char * +{ + pstrm->WriteID_t("LSHM"); // layered shadow map + + // load the shadow map data + *pstrm << sm_ulFlags; + *pstrm << sm_iFirstMipLevel; + *pstrm << sm_mexOffsetX; + *pstrm << sm_mexOffsetY; + *pstrm << sm_mexWidth; + *pstrm << sm_mexHeight; + // write the layers of the shadow + WriteLayers_t(pstrm); +} + + +// mix all layers into cached shadow map +void CShadowMap::MixLayers( INDEX iFirstMip, INDEX iLastMip, BOOL bDynamic/*=FALSE*/) +{ + // base function is used only for testing + (void)iFirstMip; + (void)iLastMip; + // just fill with white + ULONG ulValue = ByteSwap(C_WHITE); + ASSERT( sm_pulCachedShadowMap!=NULL); + if( sm_pulCachedShadowMap==NULL || sm_pulCachedShadowMap==&sm_colFlat) return; + for( INDEX i=0; i<(sm_mexWidth>>sm_iFirstMipLevel)*(sm_mexHeight>>sm_iFirstMipLevel); i++) { + sm_pulCachedShadowMap[i] = ulValue; + } +} + + +// check if all layers are up to date +void CShadowMap::CheckLayersUpToDate(void) +{ + NOTHING; +} + + +// test if there is any dynamic layer +BOOL CShadowMap::HasDynamicLayers(void) +{ + return FALSE; +} + + +void CShadowMap::ReadLayers_t( CTStream *pstrm) // throw char * +{ +} + +void CShadowMap::WriteLayers_t( CTStream *pstrm) // throw char * +{ +} + + + +// prepare shadow map for upload and bind (returns whether the shadowmap is flat or not) +void CShadowMap::Prepare(void) +{ + // determine probing + ASSERT(this!=NULL); + extern BOOL ProbeMode( CTimerValue tvLast); + BOOL bUseProbe = ProbeMode(sm_tvLastDrawn); + + // determine and clamp to max allowed shadow dimension + shd_iStaticSize = Clamp( shd_iStaticSize, 5L, 8L); + PIX pixClampAreaSize = 1L<<(shd_iStaticSize*2); + // determine largest allowed mip level + INDEX iFinestMipLevel = sm_iFirstMipLevel + + ClampTextureSize( pixClampAreaSize, _pGfx->gl_pixMaxTextureDimension, + sm_mexWidth>>sm_iFirstMipLevel, sm_mexHeight>>sm_iFirstMipLevel); + // make sure we didn't run out of range + INDEX iWantedMipLevel = ClampUp( iFinestMipLevel, sm_iLastMipLevel); + sm_iFirstUploadMipLevel = 31; + const PIX pixShadowSize = (sm_mexWidth>>iFinestMipLevel) * (sm_mexHeight>>iFinestMipLevel); + + // see if shadowmap can be pulled out of probe mode + if( pixShadowSize<=16*16*4 || ((sm_ulFlags&SMF_PROBED) && _pGfx->gl_slAllowedUploadBurst>=0)) bUseProbe = FALSE; + if( bUseProbe) { + // adjust mip-level for probing + ULONG *pulDummy = NULL; + PIX pixProbeWidth = sm_mexWidth >>iFinestMipLevel; + PIX pixProbeHeight = sm_mexHeight>>iFinestMipLevel; + INDEX iMipOffset = GetMipmapOfSize( 16*16, pulDummy, pixProbeWidth, pixProbeHeight); + if( iMipOffset<2) bUseProbe = FALSE; + else iWantedMipLevel += iMipOffset; + } + + // cache if it is not cached at all of not in this mip level + if( sm_pulCachedShadowMap==NULL || iWantedMipLevelgl_iFrameNumber) { + sm_iRenderFrame = _pGfx->gl_iFrameNumber; + // determine size and update + SLONG slBytes = pixShadowSize * gfxGetFormatPixRatio(sm_ulInternalFormat); + if( !sm_tpLocal.tp_bSingleMipmap) slBytes = slBytes *4/3; + _sfStats.IncrementCounter( CStatForm::SCI_SHADOWBINDS, 1); + _sfStats.IncrementCounter( CStatForm::SCI_SHADOWBINDBYTES, slBytes); + } + + // reduce allowed burst value if upload is required in non-probe mode + if( !bUseProbe && sm_iFirstUploadMipLevel<31) { + const PIX pixWidth = sm_mexWidth >>sm_iFirstUploadMipLevel; + const PIX pixHeight = sm_mexHeight >>sm_iFirstUploadMipLevel; + const INDEX iPixSize = shd_bFineQuality ? 4 : 2; + SLONG slSize = pixWidth*pixHeight *iPixSize; + _pGfx->gl_slAllowedUploadBurst -= slSize; + } + // update probe requirements + if( bUseProbe) sm_ulFlags |= SMF_WANTSPROBE; + else sm_ulFlags &=~SMF_WANTSPROBE; +} + + + +// provide the data for uploading +void CShadowMap::SetAsCurrent(void) +{ + ASSERT( sm_pulCachedShadowMap!=NULL && sm_iFirstCachedMipLevel<31); + + // eventually re-adjust LOD bias + extern FLOAT _fCurrentLODBias; + extern void UpdateLODBias( const FLOAT fLODBias); + if( _fCurrentLODBias != _pGfx->gl_fTextureLODBias) UpdateLODBias( _pGfx->gl_fTextureLODBias); + + // determine actual need for upload and eventaully colorize shadowmaps + const BOOL bFlat = IsFlat(); + + // done here if flat and non-dynamic + if( bFlat) { + // bind flat texture + _ptdFlat->SetAsCurrent(); + MarkDrawn(); + return; + } + + // init use probe flag + BOOL bUseProbe = (sm_ulFlags & SMF_WANTSPROBE); + + // if needs to be uploaded + if( sm_iFirstUploadMipLevel<31 || ((sm_ulFlags&SMF_DYNAMICUPLOADED) && (sm_ulFlags&SMF_DYNAMICBLACK))) + { + // generate bind number(s) if needed + if( sm_ulObject==NONE) { + gfxGenerateTexture( sm_ulObject); + sm_pixUploadWidth = sm_pixUploadHeight = 0; + sm_ulInternalFormat = NONE; + } + // determine shadow map pointer (static or dynamic shadow) + ULONG *pulShadowMap = sm_pulCachedShadowMap; + BOOL bSingleMipmap = FALSE; + sm_ulFlags &= ~SMF_DYNAMICUPLOADED; + if( sm_pulDynamicShadowMap!=NULL && !(sm_ulFlags&SMF_DYNAMICBLACK)) { + pulShadowMap = sm_pulDynamicShadowMap; + if( !shd_bDynamicMipmaps && gap_bAllowSingleMipmap) bSingleMipmap = TRUE; + sm_ulFlags |= SMF_DYNAMICUPLOADED; + bUseProbe = FALSE; // don't probe dynamic shadowmaps + } + + // reset mapping parameters if needed + if( sm_tpLocal.tp_bSingleMipmap != bSingleMipmap) { + sm_tpLocal.Clear(); + sm_tpLocal.tp_bSingleMipmap = bSingleMipmap; + sm_pixUploadWidth = sm_pixUploadHeight = 0; // will not use subimage + } + + // determine corresponding shadowmap's texture internal format, memory offset and flatness + if( sm_iFirstUploadMipLevel>30) sm_iFirstUploadMipLevel = sm_iFirstCachedMipLevel; + PIX pixWidth=1, pixHeight=1; + pixWidth = sm_mexWidth >>sm_iFirstUploadMipLevel; + pixHeight = sm_mexHeight >>sm_iFirstUploadMipLevel; + pulShadowMap += sm_slMemoryUsed/BYTES_PER_TEXEL - GetMipmapOffset( 15, pixWidth, pixHeight); + + // paranoid + ASSERT( pixWidth>0 && pixHeight>0); + + // determine internal shadow texture format and usage of faster glTexSubImage function instead of slow glTexImage + BOOL bUseSubImage = TRUE; + ULONG ulInternalFormat = TS.ts_tfRGB5; + if( !(_pGfx->gl_ulFlags&GLF_32BITTEXTURES)) shd_bFineQuality = FALSE; + if( shd_bFineQuality) ulInternalFormat = TS.ts_tfRGB8; + if( _slShdSaturation<4) ulInternalFormat = TS.ts_tfL8; // better quality for grayscale shadow mode + // eventually re-adjust uploading parameters + if( sm_pixUploadWidth!=pixWidth || sm_pixUploadHeight!=pixHeight || sm_ulInternalFormat!=ulInternalFormat) { + sm_pixUploadWidth = pixWidth; + sm_pixUploadHeight = pixHeight; + sm_ulInternalFormat = ulInternalFormat; + bUseSubImage = FALSE; + } + + // upload probe (if needed) + if( bUseProbe) { + sm_ulFlags |= SMF_PROBED; + if( sm_ulProbeObject==NONE) gfxGenerateTexture( sm_ulProbeObject); + CTexParams tpTmp = sm_tpLocal; + gfxSetTexture( sm_ulProbeObject, tpTmp); + gfxUploadTexture( pulShadowMap, pixWidth, pixHeight, TS.ts_tfRGB5, FALSE); + } else { + // upload shadow in required format and size + if( sm_ulFlags&SMF_PROBED) { // cannot subimage shadowmap that has been probed + bUseSubImage = FALSE; + sm_ulFlags &= ~SMF_PROBED; + } + // colorize mipmaps if needed + extern INDEX tex_bColorizeMipmaps; + if( tex_bColorizeMipmaps && pixWidth>1 && pixHeight>1) ColorizeMipmaps( 1, pulShadowMap, pixWidth, pixHeight); + MarkDrawn(); // mark that shadowmap has been referenced + gfxSetTexture( sm_ulObject, sm_tpLocal); + gfxUploadTexture( pulShadowMap, pixWidth, pixHeight, ulInternalFormat, bUseSubImage); + } + // paranoid android + ASSERT( sm_iFirstCachedMipLevel<31 && sm_pulCachedShadowMap!=NULL); + return; + } + + // set corresponding probe or texture frame as current + if( bUseProbe && sm_ulProbeObject!=NONE && (_pGfx->gl_slAllowedUploadBurst<0 || (sm_ulFlags&SMF_PROBED))) { + CTexParams tpTmp = sm_tpLocal; + gfxSetTexture( sm_ulProbeObject, tpTmp); + return; + } + + // set non-probe shadowmap and mark that this shadowmap has been drawn + gfxSetTexture( sm_ulObject, sm_tpLocal); + MarkDrawn(); +} + + + + +// returns used memory - static, dynamic and uploaded size separately, slack space ratio (0-1 float) +// and whether the shadowmap is flat or not +BOOL CShadowMap::GetUsedMemory( SLONG &slStaticSize, SLONG &slDynamicSize, SLONG &slUploadSize, FLOAT &fSlackRatio) +{ + const BOOL bFlat = (sm_pulCachedShadowMap==&sm_colFlat); + + // determine static portion size + slStaticSize = 0; + if( sm_pulCachedShadowMap!=NULL) slStaticSize = sm_slMemoryUsed; + + // determine dynamic portion size + slDynamicSize = 0; + if( sm_pulDynamicShadowMap!=NULL) slDynamicSize = sm_slMemoryUsed; + + // determine uploaded portion size + slUploadSize = 0; + const PIX pixMemoryUsed = Max(slStaticSize,slDynamicSize)/BYTES_PER_TEXEL; + if( pixMemoryUsed==0) return bFlat; // done if no memory is used + + if( sm_ulObject!=NONE) { + slUploadSize = gfxGetTexturePixRatio(sm_ulObject); + if( !bFlat || slDynamicSize!=0) slUploadSize *= pixMemoryUsed; + } + + // determine slack space + const FLOAT fPolySize = sm_pixPolygonSizeU*sm_pixPolygonSizeV; + fSlackRatio = 1.0f - ClampUp( fPolySize*4/3/pixMemoryUsed, 1.0f); + return bFlat; +} + + + diff --git a/Sources/Engine/Graphics/ShadowMap.h b/Sources/Engine/Graphics/ShadowMap.h new file mode 100644 index 0000000..27d18e8 --- /dev/null +++ b/Sources/Engine/Graphics/ShadowMap.h @@ -0,0 +1,107 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SHADOWMAP_H +#define SE_INCL_SHADOWMAP_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +#define SMF_DYNAMICINVALID (1UL<<0) // dynamic shadows are not up to date +#define SMF_DYNAMICBLACK (1UL<<1) // there was no need to mix dynamic shadow layer(s) (they were all black) +#define SMF_DYNAMICUPLOADED (1UL<<2) // dynamic shadowmap was uploaded last +#define SMF_ANIMATINGLIGHTS (1UL<<3) // set when shadowmap has at least one animating light +#define SMF_WANTSPROBE (1UL<<20) // set if wants to be probed +#define SMF_PROBED (1UL<<21) // set if last binding was as probe-texture + + +// class that holds information about shadow cluster map of each scene polygon +// format flags (16+) are defined by texture data +class ENGINE_API CShadowMap { +// implementation: +public: + CListNode sm_lnInGfx; // for linking in list of all cached shadow maps + ULONG sm_ulFlags; // various flags + INDEX sm_iFirstMipLevel; // best mip level possible for this shadow map + INDEX sm_iLastMipLevel; // minimum possible mip level + COLOR sm_colFlat; // color of whole shadowmap if shadowmap is flat + MEX sm_mexOffsetX, sm_mexOffsetY; // X and Y offset from the begining of the polygon + MEX sm_mexWidth, sm_mexHeight; // width and height of shadow map + + ULONG *sm_pulCachedShadowMap; // pointer to cached calculated shadow map + ULONG *sm_pulDynamicShadowMap; // pointer to shadow map with dynamic lights + SLONG sm_slMemoryUsed; // memory in use by shadow map (in bytes) + INDEX sm_iFirstCachedMipLevel; // first mip level currently cached + INDEX sm_iFirstUploadMipLevel; // first mip level that is to be uploaded (if >30, upload nothing) + CTimerValue sm_tvLastDrawn; // timer for shadow uncaching and probing + + PIX sm_pixPolygonSizeU, sm_pixPolygonSizeV; // dimensions of used part of shadowmap + PIX sm_pixUploadWidth, sm_pixUploadHeight; // dimensions of last upload size + ULONG sm_ulInternalFormat; // last format in which shadowmap was uploaded + ULONG sm_ulObject; // for API + ULONG sm_ulProbeObject; // for API + CTexParams sm_tpLocal; // local texture parameters + + INDEX sm_iRenderFrame; // frame number currently rendering (for profiling) + + // skip old shadows saved in stream + void Read_old_t(CTStream *inFile); // throw char * + // mix all layers into cached shadow map + virtual void MixLayers( INDEX iFirstMip, INDEX iLastMip, BOOL bDynamic=FALSE); // iFirstMip + +#include +#include +#include +#include + +extern INDEX gfx_iStereo; +extern INDEX gfx_bStereoInvert; +extern INDEX gfx_iStereoOffset; +extern FLOAT gfx_fStereoSeparation; + +// query whether user has turned stereo rendering on +BOOL Stereo_IsEnabled(void) +{ + return gfx_iStereo!=0; +} + + +// set buffer for stereo rendering left/right/nostereo +void Stereo_SetBuffer(INDEX iEye) +{ + if( gfx_bStereoInvert) gfx_bStereoInvert = 1; + const ULONG ulLeftMask = gfx_bStereoInvert ? CT_BMASK|CT_GMASK : CT_RMASK; + const ULONG ulRightMask = gfx_bStereoInvert ? CT_RMASK : CT_BMASK|CT_GMASK; + + if( iEye==STEREO_BOTH || gfx_iStereo==0) { + gfxSetColorMask(CT_RMASK|CT_GMASK|CT_BMASK|CT_AMASK); + } else if (iEye==STEREO_LEFT) { + gfxSetColorMask(ulLeftMask); + } else if (iEye==STEREO_RIGHT) { + gfxSetColorMask(ulRightMask); + } +} + + +// adjust perspective projection stereo rendering left/right/nostereo +void Stereo_AdjustProjection(CProjection3D &pr, INDEX iEye, FLOAT fFactor) +{ + // prepare and clamp + CPerspectiveProjection3D &ppr = (CPerspectiveProjection3D &)pr; + gfx_fStereoSeparation = Clamp( gfx_fStereoSeparation, 0.01f, 1.0f); + gfx_iStereoOffset = Clamp( gfx_iStereoOffset, -100L, +100L); + // apply! + if (iEye==STEREO_BOTH || gfx_iStereo==0) { + NOTHING; + } else if (iEye==STEREO_LEFT) { + pr.ViewerPlacementL().Translate_OwnSystem( FLOAT3D(-gfx_fStereoSeparation*fFactor/2,0,0) ); + ppr.ppr_boxSubScreen = ppr.pr_ScreenBBox; + ppr.ppr_boxSubScreen -= FLOAT2D(-gfx_iStereoOffset/2.0f, 0.0f); + } else if (iEye==STEREO_RIGHT) { + pr.ViewerPlacementL().Translate_OwnSystem( FLOAT3D(+gfx_fStereoSeparation*fFactor/2,0,0) ); + ppr.ppr_boxSubScreen = ppr.pr_ScreenBBox; + ppr.ppr_boxSubScreen -= FLOAT2D(+gfx_iStereoOffset/2.0f, 0.0f); + } +} + diff --git a/Sources/Engine/Graphics/Stereo.h b/Sources/Engine/Graphics/Stereo.h new file mode 100644 index 0000000..b0a3a81 --- /dev/null +++ b/Sources/Engine/Graphics/Stereo.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_GFXSTEREO_H +#define SE_INCL_GFXSTEREO_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// +// stereo rendering support +// + +// note: left and right are in succession, to be able to make 'for' loops +// if stereo is disabled, 'left' has same effect as 'both' to all functions +#define STEREO_LEFT 0 +#define STEREO_RIGHT 1 +#define STEREO_BOTH 2 + +// query whether user has turned stereo rendering on +ENGINE_API BOOL Stereo_IsEnabled(void); +// set buffer for stereo rendering left/right/both +ENGINE_API void Stereo_SetBuffer(INDEX iEye); +// adjust perspective projection for stereo rendering left/right/both +ENGINE_API void Stereo_AdjustProjection(CProjection3D &pr, INDEX iEye, FLOAT fFactor); + +#endif /* include-once check. */ diff --git a/Sources/Engine/Graphics/Texture.cpp b/Sources/Engine/Graphics/Texture.cpp new file mode 100644 index 0000000..ffb8554 --- /dev/null +++ b/Sources/Engine/Graphics/Texture.cpp @@ -0,0 +1,1831 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + + +extern INDEX tex_iNormalQuality; +extern INDEX tex_iAnimationQuality; +extern INDEX tex_iNormalSize; +extern INDEX tex_iAnimationSize; +extern INDEX tex_iEffectSize; + +extern INDEX tex_iDithering; +extern INDEX tex_iFiltering; + +extern INDEX gap_bAllowSingleMipmap; +extern FLOAT gfx_tmProbeDecay; + + +// special mode flag when loading texture for exporting +static BOOL _bExport = FALSE; + +// singleton object for texture settings +struct TextureSettings TS = {0}; + +#define TEXFMT_NONE 0 + +// determine (or assume) support for OpenGL and Direct3D texture internal formats +extern void DetermineSupportedTextureFormats( GfxAPIType eAPI) +{ + if( eAPI==GAT_OGL) { + TS.ts_tfRGB8 = GL_RGB8; + TS.ts_tfRGBA8 = GL_RGBA8; + TS.ts_tfRGB5 = GL_RGB5; + TS.ts_tfRGBA4 = GL_RGBA4; + TS.ts_tfRGB5A1 = GL_RGB5_A1; + TS.ts_tfLA8 = GL_LUMINANCE8_ALPHA8; + TS.ts_tfL8 = GL_LUMINANCE8; + } +#ifdef SE1_D3D + if( eAPI==GAT_D3D) { + extern D3DFORMAT FindClosestFormat_D3D(D3DFORMAT d3df); + TS.ts_tfRGBA8 = FindClosestFormat_D3D(D3DFMT_A8R8G8B8); + TS.ts_tfRGB8 = FindClosestFormat_D3D(D3DFMT_X8R8G8B8); + TS.ts_tfRGB5 = FindClosestFormat_D3D(D3DFMT_R5G6B5); + TS.ts_tfRGB5A1 = FindClosestFormat_D3D(D3DFMT_A1R5G5B5); + TS.ts_tfRGBA4 = FindClosestFormat_D3D(D3DFMT_A4R4G4B4); + TS.ts_tfLA8 = FindClosestFormat_D3D(D3DFMT_A8L8); + TS.ts_tfL8 = FindClosestFormat_D3D(D3DFMT_L8); + } +#endif // SE1_D3D +} + + +// update all relevant texture parameters +extern void UpdateTextureSettings(void) +{ + // determine API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_D3D || eAPI==GAT_NONE); +#else + ASSERT( eAPI==GAT_OGL || eAPI==GAT_NONE); +#endif // SE1_D3D + + // set texture formats and compression + TS.ts_tfRGB8 = TS.ts_tfRGBA8 = NONE; + TS.ts_tfRGB5 = TS.ts_tfRGBA4 = TS.ts_tfRGB5A1 = NONE; + TS.ts_tfLA8 = TS.ts_tfL8 = NONE; + DetermineSupportedTextureFormats(eAPI); + + // clamp and adjust texture compression type + INDEX iTCType = 0; + const ULONG ulGfxFlags = _pGfx->gl_ulFlags; + const BOOL bHasTC = (ulGfxFlags&GLF_TEXTURECOMPRESSION); + if( eAPI==GAT_OGL && bHasTC) + { // OpenGL + extern INDEX ogl_iTextureCompressionType; // 0=none, 1=default (ARB), 2=S3TC, 3=FXT1, 4=legacy S3TC + INDEX &iTC = ogl_iTextureCompressionType; + iTC = Clamp( iTC, 0L, 4L); + if( iTC==3 && !(ulGfxFlags&GLF_EXTC_FXT1)) iTC = 2; + if( iTC==2 && !(ulGfxFlags&GLF_EXTC_S3TC)) iTC = 3; + if((iTC==2 || iTC==3) && !((ulGfxFlags&GLF_EXTC_FXT1) || (ulGfxFlags&GLF_EXTC_S3TC))) iTC = 1; + if( iTC==1 && !(ulGfxFlags&GLF_EXTC_ARB)) iTC = 4; + if( iTC==4 && !(ulGfxFlags&GLF_EXTC_LEGACY)) iTC = 0; // khm ... + iTCType = iTC; // set it + } + // Direct3D (just force DXTC - it's the only one) +#ifdef SE1_D3D + if( eAPI==GAT_D3D && bHasTC) iTCType = 5; +#endif // SE1_D3D + + // clamp and cache cvar + extern INDEX tex_bCompressAlphaChannel; + if( tex_bCompressAlphaChannel) tex_bCompressAlphaChannel = 1; + const BOOL bCAC = tex_bCompressAlphaChannel; + + // set members + switch( iTCType) { + case 1: // ARB + TS.ts_tfCRGBA = GL_COMPRESSED_RGBA_ARB; + TS.ts_tfCRGB = GL_COMPRESSED_RGB_ARB; + break; + case 2: // S3TC + TS.ts_tfCRGBA = bCAC ? GL_COMPRESSED_RGBA_S3TC_DXT5_EXT : GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; + TS.ts_tfCRGB = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; + break; + case 3: // FXT1 + TS.ts_tfCRGBA = GL_COMPRESSED_RGBA_FXT1_3DFX; + TS.ts_tfCRGB = GL_COMPRESSED_RGB_FXT1_3DFX; + break; + case 4: // LEGACY + TS.ts_tfCRGBA = bCAC ? GL_COMPRESSED_RGB4_COMPRESSED_ALPHA4_S3TC : GL_COMPRESSED_RGBA_S3TC; + TS.ts_tfCRGB = GL_COMPRESSED_RGB_S3TC; + break; +#ifdef SE1_D3D + case 5: // DXTC + extern D3DFORMAT FindClosestFormat_D3D(D3DFORMAT d3df); + TS.ts_tfCRGBA = bCAC ? FindClosestFormat_D3D(D3DFMT_DXT5) : FindClosestFormat_D3D(D3DFMT_DXT3); + TS.ts_tfCRGB = D3DFMT_DXT1; + break; +#endif // SE1_D3D + default: // none + TS.ts_tfCRGBA = NONE; + TS.ts_tfCRGB = NONE; + break; + } + // adjust if need to compress opaque textures as transparent + extern INDEX tex_bAlternateCompression; + if( tex_bAlternateCompression) { + tex_bAlternateCompression = 1; + TS.ts_tfCRGB = TS.ts_tfCRGBA; + } + + // clamp texture quality + INDEX iMinQuality = 0; + INDEX iMaxQuality = iTCType>0 ? 3 : 2; + if( !(_pGfx->gl_ulFlags&GLF_32BITTEXTURES)) iMinQuality = iMaxQuality = 1; + TS.ts_iNormQualityO = Clamp( (INDEX)(tex_iNormalQuality /10), iMinQuality, iMaxQuality); + TS.ts_iNormQualityA = Clamp( (INDEX)(tex_iNormalQuality %10), iMinQuality, iMaxQuality); + TS.ts_iAnimQualityO = Clamp( (INDEX)(tex_iAnimationQuality/10), iMinQuality, iMaxQuality); + TS.ts_iAnimQualityA = Clamp( (INDEX)(tex_iAnimationQuality%10), iMinQuality, iMaxQuality); + tex_iNormalQuality = TS.ts_iNormQualityO*10 + TS.ts_iNormQualityA; + tex_iAnimationQuality = TS.ts_iAnimQualityO*10 + TS.ts_iAnimQualityA; + // clamp texture size + tex_iNormalSize = Clamp( tex_iNormalSize, 5L, 11L); + tex_iAnimationSize = Clamp( tex_iAnimationSize, 5L, 9L); + TS.ts_pixNormSize = 1L<<(tex_iNormalSize *2); + TS.ts_pixAnimSize = 1L<<(tex_iAnimationSize*2); + + // determine maximum texel-byte ratio + INDEX iOQ = tex_iNormalQuality /10; if( iOQ==0) iOQ=2; else if( iOQ==3) iOQ=0; + INDEX iAQ = tex_iNormalQuality %10; if( iAQ==0) iAQ=2; else if( iAQ==3) iAQ=0; + INDEX iTexMul = 2 * Max(iOQ,iAQ); if( iTexMul==0) iTexMul=1; + if( tex_iNormalSize<=6 && iTexMul==1) iTexMul = 2; + if( tex_iNormalSize<=5 && iTexMul==2) iTexMul = 4; + TS.ts_iMaxBytesPerTexel = iTexMul; +} + + + +/***************************************** + * Implementation of CTextureData routines + */ +CTextureData::CTextureData() +{ + td_ulFlags = NONE; + td_mexWidth = 0; + td_mexHeight = 0; + td_tvLastDrawn = 0I64; + td_iFirstMipLevel = 0; + td_ctFineMipLevels = 0; + + td_ctFrames = 0; + td_slFrameSize = 0; + td_ulInternalFormat = TEXFMT_NONE; + td_ulProbeObject = NONE; + td_ulObject = NONE; + td_pulFrames = NULL; + + td_pubBuffer1 = NULL; // reset effect buffers + td_pubBuffer2 = NULL; + td_pixBufferWidth = 0; + td_pixBufferHeight = 0; + td_ptdBaseTexture = NULL; // no base texture by default + td_ptegEffect = NULL; // no effect data + + td_iRenderFrame = -1; + CAnimData::DefaultAnimation(); + _bExport = FALSE; +} + + +CTextureData::~CTextureData() +{ + Clear(); +} + + +// converts mip level to the one of allowed by texture +INDEX CTextureData::ClampMipLevel( FLOAT fMipFactor) const +{ + INDEX res = (INDEX)fMipFactor; + INDEX iLastMipLevel = GetNoOfMipmaps( GetPixWidth(), GetPixHeight()) -1 +td_iFirstMipLevel; + res = Clamp( res, td_iFirstMipLevel, iLastMipLevel); + return( res); +} + + +// routine that adds one-frame to texture from one picture +void CTextureData::AddFrame_t( const CImageInfo *pII) +{ + // check for supported image format + ASSERT( pII->ii_BitsPerPixel==24 || pII->ii_BitsPerPixel==32); + if( pII->ii_BitsPerPixel!=24 && pII->ii_BitsPerPixel!=32) { + throw( TRANS("Only 24-bit and 32-bit pictures can be processed.")); + } + PIX pixWidth = pII->ii_Width; + PIX pixHeight = pII->ii_Height; + + // frame that is about to be added must have the same dimensions as the texture + ASSERT( pixWidth == GetPixWidth() ); + ASSERT( pixHeight == GetPixHeight() ); + if( pixWidth != GetPixWidth() ) throw( TRANS("Incompatible frame width.")); + if( pixHeight != GetPixHeight() ) throw( TRANS("Incompatible frame height.")); + + // add memory for new frame + SLONG slFramesSize = td_slFrameSize * td_ctFrames; + GrowMemory( (void**)&td_pulFrames, slFramesSize + td_slFrameSize); + + // add new frame to the end of the previous texture frames + PIX pixMipmapSize = pixWidth*pixHeight; + ULONG *pulCurrentFrame = td_pulFrames + slFramesSize/BYTES_PER_TEXEL; + + if( td_ulFlags&TEX_ALPHACHANNEL) { + // has alpha channel - do simple copying + memcpy( pulCurrentFrame, pII->ii_Picture, pixMipmapSize*4); + } else { + // hasn't got alpha channel - do conversion from 24-bit bitmap to 32-bit format + memcpy( pulCurrentFrame, pII->ii_Picture, pixMipmapSize*3); + AddAlphaChannel( (UBYTE*)pulCurrentFrame, (ULONG*)pulCurrentFrame, pixMipmapSize); + } + // make mipmaps (in place!) + MakeMipmaps( td_ctFineMipLevels, pulCurrentFrame, pixWidth,pixHeight); + + // increase number of frames + td_ctFrames++; +} + + +// routine that creates one-frame-texture from loaded picture thru image info structure +void CTextureData::Create_t( const CImageInfo *pII, MEX mexWanted, INDEX ctFineMips, BOOL bForce32bit) +{ + // check for supported image format + _bExport = FALSE; + ASSERT( pII->ii_BitsPerPixel==24 || pII->ii_BitsPerPixel==32); + if( pII->ii_BitsPerPixel!=24 && pII->ii_BitsPerPixel!=32) { + throw( TRANS("Only 24-bit and 32-bit pictures can be processed.")); + } + + // get picture data + PIX pixSizeU = pII->ii_Width; + PIX pixSizeV = pII->ii_Height; + + // check maximum supported texture dimension + if( pixSizeU>MAX_MEX || pixSizeV>MAX_MEX) throw( TRANS("At least one of texture dimensions is too large.")); + + // determine physical (maximum) number of mip-levels + INDEX iSizeULog2 = FastLog2( pixSizeU); + INDEX iSizeVLog2 = FastLog2( pixSizeV); + ASSERT( (1UL<ii_BitsPerPixel==32) td_ulFlags |= TEX_ALPHACHANNEL; + if( bForce32bit) td_ulFlags |= TEX_32BIT; + + // initialize general TextureData members + td_ctFrames = 0; + td_mexWidth = pixSizeU<td_ptegEffect!=NULL); + PIX pixWidth = pTD->td_pixBufferWidth; + PIX pixHeight = pTD->td_pixBufferHeight; + + ULONG ulSize = pixWidth*pixHeight *sizeof(UBYTE); + // eventual adjustment for water effect type + if( pTD->td_ptegEffect->IsWater()) ulSize = pixWidth*(pixHeight+2) *sizeof(SWORD); + return ulSize; +} + + +// initializes td_pixBufferWidth & td_pixBufferHeight +static void InitEffectBufferDimensions( CTextureData *pTD) +{ + // initialize as default + PIX pixWidth = pTD->GetPixWidth(); + PIX pixHeight = pTD->GetPixHeight(); + + // if water effect type + if( pTD->td_ptegEffect->IsWater()) { + // adjust size for water type effect (width or height must be 64) + if( pixWidth > pixHeight) { + pixHeight = (PIX)((FLOAT)pixHeight/pixWidth *64.0f); + pixWidth = 64; + } else { + pixWidth = (PIX)((FLOAT)pixWidth /pixHeight *64.0f); + pixHeight = 64; + } + } + // set + pTD->td_pixBufferWidth = pixWidth; + pTD->td_pixBufferHeight = pixHeight; +} + + +// free effect buffers' memory +static void FreeEffectBuffers( CTextureData *pTD) +{ + if( pTD->td_pubBuffer1 != NULL) { + FreeMemory( pTD->td_pubBuffer1); + pTD->td_pubBuffer1 = NULL; + } + if( pTD->td_pubBuffer2 != NULL) { + FreeMemory( pTD->td_pubBuffer2); + pTD->td_pubBuffer2 = NULL; + } +} + + +// allocates and resets effect buffers +static ULONG AllocEffectBuffers( CTextureData *pTD) +{ + // free if already allocated + FreeEffectBuffers( pTD); + // determine size of effect buffers + ULONG ulSize = GetEffectBufferSize( pTD); + // allocate and reset buffers (memory walling!) + pTD->td_pubBuffer1 = (UBYTE*)AllocMemory( ulSize+8); + pTD->td_pubBuffer2 = (UBYTE*)AllocMemory( ulSize+8); + memset( pTD->td_pubBuffer1, 0, ulSize); + memset( pTD->td_pubBuffer2, 0, ulSize); + return ulSize; +} + + +// creates new effect texture with one frame +void CTextureData::CreateEffectTexture( PIX pixWidth, PIX pixHeight, MEX mexWidth, + CTextureData *ptdBaseTexture, ULONG ulGlobalEffect) +{ + ptdBaseTexture->MarkUsed(); + Clear(); + CAnimData::DefaultAnimation(); + + // determine mip index from mex size + td_iFirstMipLevel = FastLog2( mexWidth/pixWidth); + // fill some of TextureData members + td_ulFlags = TEX_STATIC; + td_mexWidth = pixWidth <td_ulFlags&TEX_GRAY); + BOOL bAlphaChannel = pTD->td_ulFlags & TEX_ALPHACHANNEL; + PIX pixTexSize = pTD->GetPixWidth() * pTD->GetPixHeight(); + + // choose internal texture format for alpha textures + INDEX iQuality; + ULONG ulInternalFormat; + if( bAlphaChannel) + { + iQuality = pTD->td_ctFrames>1 ? TS.ts_iAnimQualityA : TS.ts_iNormQualityA; + ulInternalFormat = TS.ts_tfRGBA4; + switch( iQuality) { + case 3: case 2: ulInternalFormat = TS.ts_tfRGBA8; break; // uploaded as 32 bit or compressed + case 1: break; // uploaded as 16 bit (default) + case 0: if( pTD->td_ulFlags&TEX_32BIT) ulInternalFormat = TS.ts_tfRGBA8; break; // uploaded optimally + default: ASSERTALWAYS( "Unexpected texture type found."); break; + } + // adjust quality by size + if( pixTexSize<=32*32 && ulInternalFormat==TS.ts_tfRGBA4) ulInternalFormat = TS.ts_tfRGBA8; + // do eventual adjustment of internal format for grayscale textures + if( bGrayTexture) ulInternalFormat = TS.ts_tfLA8; + // handle case of forced internal format (for texture cration process only!) + if( _iTexForcedQuality==16) ulInternalFormat = TS.ts_tfRGBA4; + if( _iTexForcedQuality==32) ulInternalFormat = TS.ts_tfRGBA8; + // do eventual adjustment of transparent textures + if( (pTD->td_ulFlags&TEX_TRANSPARENT) && ulInternalFormat==TS.ts_tfRGBA4) ulInternalFormat = TS.ts_tfRGB5A1; + } + + // choose internal texture format for opaque textures + else + { + iQuality = pTD->td_ctFrames>1 ? TS.ts_iAnimQualityO : TS.ts_iNormQualityO; + ulInternalFormat = TS.ts_tfRGB5; + switch( iQuality) { + case 3: case 2: ulInternalFormat = TS.ts_tfRGB8; break; // uploaded as 32 bit or compressed + case 1: break; // uploaded as 16 bit (default) + case 0: if( pTD->td_ulFlags&TEX_32BIT) ulInternalFormat = TS.ts_tfRGB8; break; // uploaded optimally + default: ASSERTALWAYS( "Unexpected texture type found."); break; + } + // adjust quality by size + if( pixTexSize<=32*32 && ulInternalFormat==TS.ts_tfRGB5) ulInternalFormat = TS.ts_tfRGB8; + // do eventual adjustment of internal format for grayscale textures + if( bGrayTexture) ulInternalFormat = TS.ts_tfL8; + // handle case of forced internal format (for texture cration process only!) + if( _iTexForcedQuality==16) ulInternalFormat = TS.ts_tfRGB5; + if( _iTexForcedQuality==32) ulInternalFormat = TS.ts_tfRGB8; + } + + // adjust format to compressed if needed and allowed + if( iQuality==3 && pixTexSize>=64*64) { + if( ulInternalFormat==TS.ts_tfRGB8 + || ulInternalFormat==TS.ts_tfRGB5 + || ulInternalFormat==TS.ts_tfRGB5A1) ulInternalFormat = TS.ts_tfCRGB; + if( ulInternalFormat==TS.ts_tfRGBA8 + || ulInternalFormat==TS.ts_tfRGBA4) ulInternalFormat = TS.ts_tfCRGBA; + } + // all done + return ulInternalFormat; +} + + + +// routine that performs texture conversion to current texture format (version 4) +static void Convert( CTextureData *pTD) +{ + // skip effect textures + if( pTD->td_ptegEffect != NULL) return; + + // determine dimensions + PIX pixWidth = pTD->GetPixWidth(); + PIX pixHeight = pTD->GetPixHeight(); + PIX pixMipSize = pixWidth * pixHeight; + PIX pixFrameSize = GetMipmapOffset( 15, pixWidth, pixHeight); + // allocate memory for new texture + ULONG *pulFramesNew = (ULONG*)AllocMemory( pixFrameSize*pTD->td_ctFrames *BYTES_PER_TEXEL); + UWORD *puwFramesOld = (UWORD*)pTD->td_pulFrames; + ASSERT( puwFramesOld!=NULL); + + // determine alpha channel presence + BOOL bHasAlphaChannel = pTD->td_ulFlags & TEX_ALPHACHANNEL; + + // unpack texture from 16-bit RGBA4444 or RGBA5551 format to RGBA8888 32-bit format + UBYTE r,g,b,a; + // for each frame + for( INDEX iFr=0; iFrtd_ctFrames; iFr++) + { // get addresses of current frames (new and old) + PIX pixFrameOffset = iFr * pixFrameSize; + // for each pixel + for( INDEX iPix=0; iPix>8; + g = (uwPix & 0x0F00) >>4; + b = (uwPix & 0x00F0) >>0; + a = (uwPix & 0x000F) <<4; + // adjust strength + r |= r>>4; g |= g>>4; b |= b>>4; a |= a>>4; + } else { + // without alpha channel + r = (uwPix & 0xF800) >>8; + g = (uwPix & 0x07C0) >>3; + b = (uwPix & 0x003E) <<2; + a = 0xFF; + // adjust strength + r |= r>>5; g |= g>>5; b |= b>>5; + } + + // pack it back to 32-bit + ULONG ulPix = RGBAToColor(r,g,b,a); + // store 32-bit pixel + pulFramesNew[pixFrameOffset+iPix] = ByteSwap(ulPix); + } + } + + // free old memory + FreeMemory( pTD->td_pulFrames); + // remember new texture parameters + pTD->td_pulFrames = pulFramesNew; + pTD->td_slFrameSize = pixFrameSize *BYTES_PER_TEXEL; +} + + +// remove mipmaps from texture that are not needed (exceeds maximum supported dimension) +static void RemoveOversizedMipmaps( CTextureData *pTD) +{ + // if this is an effect texture, leave as it is + if( pTD->td_ptegEffect != NULL) return; + pTD->td_ulFlags &= ~TEX_DISPOSED; + + // determine and clamp to max allowed texture dimension and size + PIX pixClampAreaSize = (pTD->td_ctFrames>1) ? TS.ts_pixAnimSize : TS.ts_pixNormSize; + // constant textures doesn't need clamping to area, but still must be clamped to max HW dimension! + if( pTD->td_ulFlags & TEX_CONSTANT) pixClampAreaSize = 4096*4096; + + // determine dimensions of finest mip-map + PIX pixSizeU = pTD->GetPixWidth(); + PIX pixSizeV = pTD->GetPixHeight(); + // determine number of mip-maps to skip + INDEX ctSkipMips = ClampTextureSize( pixClampAreaSize, _pGfx->gl_pixMaxTextureDimension, + pixSizeU, pixSizeV); + // return if no need to remove mip-maps + if( ctSkipMips==0) return; + // check for mip overhead + INDEX ctMips = GetNoOfMipmaps( pixSizeU, pixSizeV); + while( ctMips<=ctSkipMips) ctSkipMips--; + + // determine memory size and allocate memory for rest mip-maps + SLONG slRemovedMipsSize = GetMipmapOffset( ctSkipMips, pixSizeU, pixSizeV) *BYTES_PER_TEXEL; + SLONG slNewFrameSize = pTD->td_slFrameSize-slRemovedMipsSize; + ULONG *pulNewFrames = (ULONG*)AllocMemory( slNewFrameSize * pTD->td_ctFrames); + ULONG *pulNewFrame = pulNewFrames; + ULONG *pulOldFrame = pTD->td_pulFrames + (slRemovedMipsSize/BYTES_PER_TEXEL); + + // copy only needed mip-maps from each frame + for( INDEX iFr=0; iFrtd_ctFrames; iFr++) { + memcpy( pulNewFrame, pulOldFrame, slNewFrameSize); + pulNewFrame += slNewFrameSize/BYTES_PER_TEXEL; + pulOldFrame += pTD->td_slFrameSize/BYTES_PER_TEXEL; + } + + // free old frames memory + FreeMemory( pTD->td_pulFrames); + // adjust texture parameters + pTD->td_pulFrames = pulNewFrames; + pTD->td_slFrameSize = slNewFrameSize; + pTD->td_iFirstMipLevel += ctSkipMips; + pTD->td_ctFineMipLevels = ClampDn( (INDEX)(pTD->td_ctFineMipLevels-ctSkipMips), (INDEX)1); + + // mark that this texture had some mip maps disposed + pTD->td_ulFlags |= TEX_DISPOSED; +} + + + +// internal routines for texture::read routine + +// test mipmap if it can be equilized +#define EQUALIZER_TRESHOLD 3 +static BOOL IsEqualized( ULONG *pulMipmap, INDEX pixMipSize) +{ + // determine components and calc averages + COLOR col; + ULONG ulR=0, ulG=0, ulB=0; + for( INDEX iPix=0; iPix>CT_RSHIFT; + ulG += (col&CT_GMASK)>>CT_GSHIFT; + ulB += (col&CT_BMASK)>>CT_BSHIFT; + } + ulR /= pixMipSize; + ulG /= pixMipSize; + ulB /= pixMipSize; + const ULONG ulLoEdge = 127-EQUALIZER_TRESHOLD; + const ULONG ulHiEdge = 128+EQUALIZER_TRESHOLD; + BOOL bEqulized = FALSE; + if( ulR>ulLoEdge && ulRulLoEdge && ulGulLoEdge && ulB>CT_ASHIFT; + if( ulA>TRANS_TRESHOLD && ulA<(255-TRANS_TRESHOLD)) return FALSE; + } + // transparent! + return TRUE; +} + + +// test mipmap whether it is grayscaled +static BOOL IsGray( ULONG *pulMipmap, INDEX pixMipSize) +{ + // loop thru texels + for( INDEX iPix=0; iPixGetDescription() != "Textures\\Test\\BetterQuality\\FloorWS08.tex"); + + // reset texture (blank all except some flags) + Clear(); + + // determine API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_D3D || eAPI==GAT_NONE); +#else // SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_NONE); +#endif // SE1_D3D + + // determine driver context presence (must have at least 1 texture unit!) + const BOOL bHasContext = (_pGfx->gl_ctRealTextureUnits>0); + + // read version + INDEX iVersion; + inFile->ExpectID_t( "TVER"); + *inFile >> iVersion; + + // check currently supported versions + if( iVersion!=4 && iVersion!=3) throw( TRANS("Invalid texture format version.")); + + // mark if this texture was loaded form the old format + if( iVersion==3) td_ulFlags |= TEX_WASOLD; + BOOL bResetEffectBuffers = FALSE; + BOOL bFramesLoaded = FALSE; + BOOL bAlphaChannel = FALSE; + // loop trough file and react according to chunk ID + do + { + // obtain chunk id + CChunkID idChunk = inFile->GetID_t(); + if( idChunk == CChunkID(" ")) { + // we should stop reading when an invalid chunk has been encountered + break; + } + + // if this is chunk containing texture data + if( idChunk == CChunkID("TDAT")) + { + // read data describing texture + ULONG ulFlags=0; + INDEX ctMipLevels; + *inFile >> ulFlags; + *inFile >> td_mexWidth; + *inFile >> td_mexHeight; + *inFile >> td_ctFineMipLevels; + if( iVersion!=4) *inFile >> ctMipLevels; + *inFile >> td_iFirstMipLevel; + if( iVersion!=4) *inFile >> td_slFrameSize; + *inFile >> td_ctFrames; + // combine flags + td_ulFlags |= ulFlags; + bAlphaChannel = td_ulFlags&TEX_ALPHACHANNEL; + // determine frame size + if( iVersion==4) td_slFrameSize = GetMipmapOffset( 15, GetPixWidth(), GetPixHeight()) + * BYTES_PER_TEXEL; + } + // if this is chunk containing raw frames + else if( idChunk == CChunkID("FRMS")) + { + // if no driver is present and texture is not static + if( !(bHasContext || td_ulFlags&TEX_STATIC)) + { // determine frames' size + SLONG slSkipSize = td_slFrameSize; + if( iVersion==4) { + slSkipSize = GetPixWidth()*GetPixHeight(); + if( bAlphaChannel) slSkipSize *=4; + else slSkipSize *=3; + } + // just seek over frames (skip it) + inFile->Seek_t( slSkipSize*td_ctFrames, CTStream::SD_CUR); + continue; + } + // calculate texture size for corresponding texture format and allocate memory + SLONG slTexSize = td_slFrameSize * td_ctFrames; + td_pulFrames = (ULONG*)AllocMemory( slTexSize); + // if older version + if( iVersion==3) { + // alloc memory block and read mip-maps + inFile->Read_t( td_pulFrames, slTexSize); + } + // if current version + else { + PIX pixFrameSizeOnDisk = GetPixWidth()*GetPixHeight(); + for( INDEX iFr=0; iFrRead_t( pulCurrentFrame, pixFrameSizeOnDisk *4); + } else { + // read texture without alpha channel from file + inFile->Read_t( pulCurrentFrame, pixFrameSizeOnDisk *3); + // add opaque alpha channel + AddAlphaChannel( (UBYTE*)pulCurrentFrame, pulCurrentFrame, pixFrameSizeOnDisk); + } + } + } + bFramesLoaded = TRUE; + } + // if this is chunk containing texture animation data + else if( idChunk == CChunkID("ANIM")) + { + // read corresponding animation(s) + CAnimData::Read_t( inFile); + } + // if this is chunk containing base texture name + else if( idChunk == CChunkID("BAST")) + { + CTFileName fnBaseTexture; + // read file name of base texture + *inFile >> fnBaseTexture; + // if there is base texture, obtain it + if( fnBaseTexture != "") { + // must not be the same as base texture + CTFileName fnTex = inFile->GetDescription(); + if( fnTex == fnBaseTexture) { + // generate exception + ThrowF_t( TRANS("Texture \"%s\" has same name as its base texture."), (CTString&)fnTex); + } else { + // obtain base texture + td_ptdBaseTexture = _pTextureStock->Obtain_t( fnBaseTexture); + } + } + // force base to be static by default + td_ptdBaseTexture->Force(TEX_STATIC); + } + // if this is chunk containing saved effect buffers + else if( idChunk == CChunkID("FXBF")) + { // skip chunk in old versions + bResetEffectBuffers = TRUE; + if( iVersion!=4) { + inFile->Seek_t( 2* GetPixWidth()*GetPixHeight() *sizeof(SWORD), CTStream::SD_CUR); + } else { + ASSERT( td_pixBufferWidth>0 && td_pixBufferHeight>0); + ULONG ulSize = AllocEffectBuffers(this); + if( td_ptegEffect->IsWater()) ulSize*=2; + inFile->Seek_t( 2*ulSize, CTStream::SD_CUR); + } + } + else if( idChunk == CChunkID("FXB2")) + { // read effect buffers + ASSERT( td_pixBufferWidth>0 && td_pixBufferHeight>0); + ULONG ulSize = AllocEffectBuffers(this); + inFile->Read_t( td_pubBuffer1, ulSize); + inFile->Read_t( td_pubBuffer2, ulSize); + } + // if this is chunk containing effect data + else if( idChunk == CChunkID("FXDT")) + { // read effect class + ULONG ulGlobalEffect; + *inFile >> ulGlobalEffect; + // read effect buffer dimensions + if( iVersion==4) *inFile >> td_pixBufferWidth; + if( iVersion==4) *inFile >> td_pixBufferHeight; + // allocate memory for texture effect struct + td_ptegEffect = new CTextureEffectGlobal(this, ulGlobalEffect); + // skip global properties for old format effect texture + if( iVersion!=4) inFile->Seek_t( 64*sizeof(char), CTStream::SD_CUR); + // read count of effect sources + INDEX ctEffectSources; + *inFile >> ctEffectSources; + // add requested number of members to effect source array + CTextureEffectSource *pEffectSources = td_ptegEffect->teg_atesEffectSources.New( ctEffectSources); + + // read whole dynamic array of effect sources + FOREACHINDYNAMICARRAY( td_ptegEffect->teg_atesEffectSources, CTextureEffectSource, itEffectSource) + { + // read type of effect source + *inFile >> (ULONG) itEffectSource->tes_ulEffectSourceType; + // read structure holding effect source properties + inFile->Read_t( &itEffectSource->tes_tespEffectSourceProperties, sizeof(struct TextureEffectSourceProperties)); + // remember pointer to global effect + itEffectSource->tes_ptegGlobalEffect = td_ptegEffect; + // read count of effect pixels + INDEX ctEffectSourcePixels; + *inFile >> ctEffectSourcePixels; + // if there are any effect pixels + if (ctEffectSourcePixels>0) { + // alocate needed ammount of members + itEffectSource->tes_atepPixels.New( ctEffectSourcePixels); + // read all effect pixels in one block + inFile->Read_t( &itEffectSource->tes_atepPixels[0], sizeof(struct TextureEffectPixel)*ctEffectSourcePixels); + } + } + // allocate memory for effect frame buffer + SLONG slFrameSize = GetMipmapOffset( 15, GetPixWidth(), GetPixHeight()) *BYTES_PER_TEXEL; + td_pulFrames = (ULONG*)AllocMemory( slFrameSize); + // remember once again new frame size just for the sake of old effect textures + td_slFrameSize = slFrameSize; + // mark that effect texture needs to be static + td_ulFlags |= TEX_STATIC; + } + // if this is chunk containing data about detail texture + else if( idChunk == CChunkID("DTLT")) + { // skip chunk (this is here only for compatibility reasons) + CTFileName fnTmp; + *inFile >> fnTmp; + } + else + { + ThrowF_t( TRANS("Unrecognisable chunk ID (\"%s\") found while reading texture \"%s\"."), + (char*)idChunk, (CTString&)inFile->GetDescription() ); + } + } + // until we didn't reach end of file + while( !inFile->AtEOF()); + + // reset effect buffers if needed + if( bResetEffectBuffers) { + InitEffectBufferDimensions(this); + AllocEffectBuffers(this); + } + + // were done if frames weren't loaded or effect texture has been read + if( !bFramesLoaded || td_ptegEffect!=NULL) return; + + // if texture is in old format, convert it to current format + if( iVersion==3) Convert(this); + PIX pixWidth = GetPixWidth(); + PIX pixHeight = GetPixHeight(); + PIX pixTexSize = pixWidth*pixHeight; + PIX pixFrameSize = td_slFrameSize>>2; // /BYTES_PER_TEXEL; + INDEX iFrame; + + // test first mipmap for transparency (i.e. is one bit of alpha channel enough?) + // (must test it before filtering and/or mipmap reduction gets to this texture) + if( bAlphaChannel) { + td_ulFlags |= TEX_TRANSPARENT; + for( iFrame=0; iFrame>2; // /BYTES_PER_TEXEL; + + // eventually colorize mipmaps + extern INDEX tex_bColorizeMipmaps; + if( !_bExport && tex_bColorizeMipmaps && !(td_ulFlags&TEX_CONSTANT)) { + td_ulFlags |= TEX_COLORIZED; + for( iFrame=0; iFrame1)) + { // get last mipmap pointer + INDEX ctLastPixels = Max(pixWidth,pixHeight) / Min(pixWidth,pixHeight); + ULONG *pulLastMipMap = td_pulFrames + td_slFrameSize/BYTES_PER_TEXEL - ctLastPixels; + if( IsEqualized( pulLastMipMap, ctLastPixels)) td_ulFlags |= TEX_EQUALIZED; + } + + // prepare dithering type + td_ulInternalFormat = DetermineInternalFormat(this); + tex_iDithering = Clamp( tex_iDithering, 0L, 10L); + INDEX iDitherType = 0; + if( !(td_ulFlags&TEX_STATIC) || !(td_ulFlags&TEX_CONSTANT)) { // only non-static-constant textures can be dithered + extern INDEX AdjustDitheringType_OGL( GLenum eFormat, INDEX iDitheringType); + if( eAPI==GAT_OGL) iDitherType = AdjustDitheringType_OGL( (GLenum)td_ulInternalFormat, tex_iDithering); +#ifdef SE1_D3D + extern INDEX AdjustDitheringType_D3D( D3DFORMAT eFormat, INDEX iDitheringType); + if( eAPI==GAT_D3D) iDitherType = AdjustDitheringType_D3D( (D3DFORMAT)td_ulInternalFormat, tex_iDithering); +#endif // SE1_D3D + } + // eventually dither texture + if( !_bExport && iDitherType!=0) { + td_ulFlags |= TEX_DITHERED; + for( iFrame=0; iFrameGetDescription(); + if( fnTex == td_ptdBaseTexture->GetName()) { + ThrowF_t( TRANS("Texture \"%s\" has same name as its base texture."), (CTString&)fnTex); + } + } + + // write version + INDEX iVersion = 4; + outFile->WriteID_t("TVER"); + *outFile << iVersion; + + // isolate required flags + ULONG ulFlags = td_ulFlags & (TEX_ALPHACHANNEL|TEX_32BIT); + BOOL bAlphaChannel = td_ulFlags&TEX_ALPHACHANNEL; + + // write chunk containing texture data + outFile->WriteID_t( CChunkID("TDAT")); + // write data describing texture + *outFile << ulFlags; + *outFile << td_mexWidth; + *outFile << td_mexHeight; + *outFile << td_ctFineMipLevels; + *outFile << td_iFirstMipLevel; + *outFile << td_ctFrames; + + // if global effect struct exists in texture, don't save frames + if( td_ptegEffect==NULL) + { // write chunk containing raw frames + ASSERT( td_ctFrames>0); + ASSERT( td_pulFrames!=NULL); + outFile->WriteID_t( CChunkID("FRMS")); + PIX pixFrSize = GetPixWidth()*GetPixHeight(); + // eventually prepare temp buffer in case of frames without alpha channel + UBYTE *pubTmp = NULL; + if( !bAlphaChannel) pubTmp = (UBYTE*)AllocMemory( pixFrSize*3); + // write frames without mip-maps (just write the largest one) + for( INDEX iFr=0; iFrWrite_t( pulCurrentFrame, pixFrSize *4); + } else { // write frame without alpha channel + RemoveAlphaChannel( pulCurrentFrame, pubTmp, pixFrSize); + outFile->Write_t( pubTmp, pixFrSize *3); + } + } + // no need for temp buffer anymore + if( pubTmp!=NULL) FreeMemory(pubTmp); + } + // if exists global effect struct in texture + else + { // write chunk containing effect data + outFile->WriteID_t( CChunkID("FXDT")); + // write effect class + *outFile << td_ptegEffect->teg_ulEffectType; + // write effect buffer dimensions + *outFile << td_pixBufferWidth; + *outFile << td_pixBufferHeight; + // write count of effect sources + *outFile << td_ptegEffect->teg_atesEffectSources.Count(); + + // write whole dynamic array of effect sources + FOREACHINDYNAMICARRAY(td_ptegEffect->teg_atesEffectSources, CTextureEffectSource, itEffectSource) + { // write type of effect source + *outFile << itEffectSource->tes_ulEffectSourceType; + // write structure holding effect source properties + outFile->Write_t( &itEffectSource->tes_tespEffectSourceProperties, sizeof( struct TextureEffectSourceProperties)); + INDEX ctEffectSourcePixels = itEffectSource->tes_atepPixels.Count(); + // write count of effect pixels + *outFile << ctEffectSourcePixels; + // if there are any effect pixels + if( ctEffectSourcePixels>0) { + // write all effect pixels in one block + outFile->Write_t( &itEffectSource->tes_atepPixels[0], sizeof(struct TextureEffectPixel)*ctEffectSourcePixels); + } + } + // if effect buffers are valid + if( td_pubBuffer1!=NULL && td_pubBuffer2!=NULL) + { // write chunk containing effect buffers + outFile->WriteID_t( CChunkID("FXB2")); + ULONG ulSize = GetEffectBufferSize(this); + // write effect buffers + outFile->Write_t( td_pubBuffer1, ulSize); + outFile->Write_t( td_pubBuffer2, ulSize); + } + } + // write chunk containing texture animation data + outFile->WriteID_t( CChunkID("ANIM")); + // write corresponding animation(s) + CAnimData::Write_t( outFile); + + // if this texture has base texture + if( td_ptdBaseTexture != NULL) + { // write chunk containing base texture file name + outFile->WriteID_t( CChunkID("BAST")); + // write file name of base texture + *outFile << td_ptdBaseTexture->GetName(); + } +} + + +// export finest mipmap of one texture's frame to imageinfo +void CTextureData::Export_t( class CImageInfo &iiExportedImage, INDEX iFrame) +{ + // check for right frame number and non-effect texture type + ASSERT( iFrame=td_ctFrames) throw( TRANS("Texture frame that is to be exported doesn't exist.")); + + // reload without modifications + _bExport = TRUE; + Reload(); + ASSERT( td_pulFrames!=NULL); + + // prepare miplevel and mipmap offset + PIX pixWidth = GetPixWidth(); + PIX pixHeight = GetPixHeight(); + // export header to image info structure + iiExportedImage.Clear(); + iiExportedImage.ii_Width = pixWidth; + iiExportedImage.ii_Height = pixHeight; + iiExportedImage.ii_BitsPerPixel = (td_ulFlags&TEX_ALPHACHANNEL) ? 32 : 24; + + // prepare the texture for exporting (with or without alpha channel) + ULONG *pulFrame = td_pulFrames + td_slFrameSize*iFrame/BYTES_PER_TEXEL; + PIX pixMipSize = pixWidth*pixHeight; + SLONG slMipSize = pixMipSize * iiExportedImage.ii_BitsPerPixel/8; + iiExportedImage.ii_Picture = (UBYTE*)AllocMemory( slMipSize); + // export frame + if( td_ulFlags&TEX_ALPHACHANNEL) { + memcpy( iiExportedImage.ii_Picture, pulFrame, slMipSize); + } else { + RemoveAlphaChannel( pulFrame, iiExportedImage.ii_Picture, pixMipSize); + } + + // reload as it was + _bExport = FALSE; + Reload(); +} + + +// force texture to be re-loaded (if needed) in corresponding manner +void CTextureData::Force( ULONG ulTexFlags) +{ + ASSERT( td_ctFrames>0); + const BOOL bReload = (td_pulFrames==NULL && (ulTexFlags&TEX_STATIC)) + || ((td_ulFlags&TEX_DISPOSED) && (ulTexFlags&TEX_CONSTANT)) + || ((td_ulFlags&TEX_SATURATED) && (ulTexFlags&TEX_KEEPCOLOR)); + td_ulFlags |= ulTexFlags & (TEX_CONSTANT|TEX_STATIC|TEX_KEEPCOLOR); + if( bReload) Reload(); +} + + + +// set texture to be as current for accelerator and eventually upload it to accelerator's memory +void CTextureData::SetAsCurrent( INDEX iFrameNo/*=0*/, BOOL bForceUpload/*=FALSE*/) +{ + // check API + const GfxAPIType eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_D3D || eAPI==GAT_NONE); +#else // SE1_D3D + ASSERT( eAPI==GAT_OGL || eAPI==GAT_NONE); +#endif // SE1_D3D + + ASSERT( iFrameNogl_fTextureLODBias; + extern void UpdateLODBias( const FLOAT fLODBias); + if( td_ulFlags&TEX_CONSTANT) { + // non-adjustable textures don't tolerate positive LOD bias + if( _fCurrentLODBias>0) UpdateLODBias(0); + else if( _fCurrentLODBias>fWantedLODBias) UpdateLODBias(fWantedLODBias); + } + else if( td_ulFlags&TEX_EQUALIZED) { + // equilized textures don't tolerate negative LOD bias + if( _fCurrentLODBias<0) UpdateLODBias(0); + else if( _fCurrentLODBiasgl_pixMaxTextureDimension, pixWidth, pixHeight); + // check whether wanted mip level is beyond last mip-level + iWantedMipLevel = ClampMipLevel( iWantedMipLevel); + + // default adjustment for mapping + pixWidth >>= iWantedMipLevel-td_iFirstMipLevel; + pixHeight >>= iWantedMipLevel-td_iFirstMipLevel; + ASSERT( pixWidth>0 && pixHeight>0); + + // eventually adjust water effect texture size (if larger than base) + if( td_ptegEffect->IsWater()) { + INDEX iMipDiff = Min( FastLog2(td_ptdBaseTexture->GetPixWidth()) - FastLog2(pixWidth), + FastLog2(td_ptdBaseTexture->GetPixHeight()) - FastLog2(pixHeight)); + iWantedMipLevel = iMipDiff; + if( iMipDiff<0) { + pixWidth >>= (-iMipDiff); + pixHeight >>= (-iMipDiff); + iWantedMipLevel = 0; + ASSERT( pixWidth>0 && pixHeight>0); + } + } + // if current frame size differs from the previous one + SLONG slFrameSize = GetMipmapOffset( 15, pixWidth, pixHeight) *BYTES_PER_TEXEL; + if( td_pulFrames==NULL || td_slFrameSize!=slFrameSize) { + // (re)allocate the frame buffer + if( td_pulFrames!=NULL) FreeMemory( td_pulFrames); + td_pulFrames = (ULONG*)AllocMemory( slFrameSize); + td_slFrameSize = slFrameSize; + bNoDiscard = FALSE; + } + + // if not calculated for this tick (must be != to test for time rewinding) + if( td_ptegEffect->teg_updTexture.LastUpdateTime() != _pTimer->CurrentTick()) { + // discard eventual cached frame and calculate new frame + MarkChanged(); + td_ptegEffect->Animate(); + bNeedUpload = TRUE; + // make sure that effect and base textures are static + Force(TEX_STATIC); + td_ptdBaseTexture->Force(TEX_STATIC); + // copy some flags from base texture to effect texture + td_ulFlags |= td_ptdBaseTexture->td_ulFlags & (TEX_ALPHACHANNEL|TEX_TRANSPARENT|TEX_GRAY); + // render effect texture + td_ptegEffect->Render( iWantedMipLevel, pixWidth, pixHeight); + // determine internal format + ULONG ulNewFormat; + if( td_ulFlags&TEX_GRAY) { + if( td_ulFlags&TEX_ALPHACHANNEL) ulNewFormat = TS.ts_tfLA8; + else ulNewFormat = TS.ts_tfL8; + } else { + if( td_ulFlags&TEX_TRANSPARENT) ulNewFormat = TS.ts_tfRGB5A1; + else if( td_ulFlags&TEX_ALPHACHANNEL) ulNewFormat = TS.ts_tfRGBA4; + else ulNewFormat = TS.ts_tfRGB5; + } + // effect texture can be in 32-bit quality only if base texture hasn't been dithered + extern INDEX tex_bFineEffect; + if( tex_bFineEffect && (td_ptdBaseTexture->td_ulFlags&TEX_DITHERED)) { + ulNewFormat = PromoteTo32bitFormat(ulNewFormat); + } + // internal format changed? - must discard! + if( td_ulInternalFormat!=ulNewFormat) { + td_ulInternalFormat = ulNewFormat; + bNoDiscard = FALSE; + } + } // effect texture cannot have probing + bUseProbe = FALSE; + } + + // prepare effect cvars + extern INDEX tex_bDynamicMipmaps; + extern INDEX tex_iEffectFiltering; + if( tex_bDynamicMipmaps) tex_bDynamicMipmaps = 1; + tex_iEffectFiltering = Clamp( tex_iEffectFiltering, -6L, +6L); + + // determine whether texture has single mipmap + if( gap_bAllowSingleMipmap) { + // effect textures are treated differently + if( td_ptegEffect!=NULL) td_tpLocal.tp_bSingleMipmap = !tex_bDynamicMipmaps; + else td_tpLocal.tp_bSingleMipmap = (td_ctFineMipLevels<2); + } else { + // single mipmap is not allowed + td_tpLocal.tp_bSingleMipmap = FALSE; + } + + // effect texture might need dynamic mipmaps creation + if( bNeedUpload && td_ptegEffect!=NULL) { + _sfStats.StartTimer(CStatForm::STI_EFFECTRENDER); + const INDEX iTexFilter = td_ptegEffect->IsWater() ? NONE : tex_iEffectFiltering; // don't filter water textures + if( td_tpLocal.tp_bSingleMipmap) { // no mipmaps? + if( iTexFilter!=NONE) FilterBitmap( iTexFilter, td_pulFrames, td_pulFrames, pixWidth, pixHeight); + } else { // mipmaps! + const INDEX ctFine = tex_bDynamicMipmaps ? 15 : 0; // whether they're fine or coarse still depends on cvar + MakeMipmaps( ctFine, td_pulFrames, pixWidth,pixHeight, iTexFilter); + } // done with effect + _sfStats.StopTimer(CStatForm::STI_EFFECTRENDER); + } + + // if not already generated, generate bind number(s) and force upload + const PIX pixTextureSize = pixWidth*pixHeight; + if( td_ulObject==NONE) + { + // check whether frames are present + ASSERT( td_pulFrames!=NULL && td_pulFrames[0]!=0xDEADBEEF); + + if( td_ctFrames>1) { + // animation textures + td_pulObjects = (ULONG*)AllocMemory( td_ctFrames *sizeof(td_ulProbeObject)); + for( INDEX i=0; i16*16) gfxGenerateTexture( td_ulProbeObject); + // must do initial uploading + bNeedUpload = TRUE; + bNoDiscard = FALSE; + } + + // constant textures cannot be probed either + if( td_ulFlags&TEX_CONSTANT) gfxDeleteTexture(td_ulProbeObject); + if( td_ulProbeObject==NONE) bUseProbe = FALSE; + + // update statistics if not updated already for this frame + if( td_iRenderFrame != _pGfx->gl_iFrameNumber) { + td_iRenderFrame = _pGfx->gl_iFrameNumber; + // determine size and update + SLONG slBytes = pixWidth*pixHeight * gfxGetFormatPixRatio(td_ulInternalFormat); + if( !td_tpLocal.tp_bSingleMipmap) slBytes = slBytes *4/3; + _sfStats.IncrementCounter( CStatForm::SCI_TEXTUREBINDS, 1); + _sfStats.IncrementCounter( CStatForm::SCI_TEXTUREBINDBYTES, slBytes); + } + + // if needs to be uploaded + if( bNeedUpload) + { + // check whether frames are present + ASSERT( td_pulFrames!=NULL && td_pulFrames[0]!=0xDEADBEEF); + + // must discard uploaded texture if single mipmap flag has been changed + const BOOL bLastSingleMipmap = td_ulFlags & TEX_SINGLEMIPMAP; + bNoDiscard = (bNoDiscard && bLastSingleMipmap==td_tpLocal.tp_bSingleMipmap); + // update flag + if( td_tpLocal.tp_bSingleMipmap) td_ulFlags |= TEX_SINGLEMIPMAP; + else td_ulFlags &= ~TEX_SINGLEMIPMAP; + + // upload all texture frames + ASSERT( td_ulInternalFormat!=TEXFMT_NONE); + if( td_ctFrames>1) { + // animation textures + for( INDEX iFr=0; iFr1 && !td_tpLocal.IsEqual(_tpGlobal[0])) { + // must reset local texture parameters for each frame of animated texture + for( INDEX iFr=0; iFr1) ulTexObject = ((ULONG*)td_ulObject)[iFrameNo]; // animation + if( bUseProbe) { + // set probe if burst value doesn't allow real texture + if( _pGfx->gl_slAllowedUploadBurst<0) { + CTexParams tpTmp = td_tpLocal; + ASSERT( td_ulProbeObject!=NONE); + gfxSetTexture( td_ulProbeObject, tpTmp); + //extern INDEX _ctProbeTexs; + //_ctProbeTexs++; + //CPrintF( "Probed!\n"); + return; + } + // reduce allowed burst value + _pGfx->gl_slAllowedUploadBurst -= pixWidth*pixHeight *4; // assume 32-bit textures (don't ask driver!) + } + // set real texture and mark that this texture has been drawn + gfxSetTexture( ulTexObject, td_tpLocal); + MarkDrawn(); + + // debug check + ASSERT( td_ulObject!=NONE); +} + + + +// unbind texture from accelerator's memory +void CTextureData::Unbind(void) +{ + // reset mark + td_tvLastDrawn = 0I64; + + // only if bound + if( td_ulObject==NONE) { + ASSERT( td_ulProbeObject==NONE); + return; + } + // free frame number(s) + if( td_ctFrames>1) { // animation + for( INDEX iFrame=0; iFrameRelease( td_ptdBaseTexture); + td_ptdBaseTexture = NULL; + } + // free global effect data if it exists + if( td_ptegEffect != NULL) { + delete td_ptegEffect; + td_ptegEffect = NULL; + } + + // reset texture parameters + td_tpLocal.Clear(); + // clear animation + CAnimData::Clear(); + + // reset variables (but keep some flags) + td_ctFrames = 0; + td_mexWidth = 0; + td_mexHeight = 0; + td_tvLastDrawn = 0I64; + td_iFirstMipLevel = 0; + td_ctFineMipLevels = 0; + td_pixBufferWidth = 0; + td_pixBufferHeight = 0; + td_ulInternalFormat = TEXFMT_NONE; + td_iRenderFrame = -1; + td_ulFlags &= TEX_CONSTANT|TEX_STATIC|TEX_KEEPCOLOR; +} + + + + +/******************************************* + * Implementation of CTextureObject routines + */ +CTextureObject::CTextureObject(void) +{ +} +// copy from another object of same class +void CTextureObject::Copy(CTextureObject &toOther) +{ + CAnimObject::Copy(toOther); +} + +void CTextureObject::Read_t( CTStream *istrFile) // throw char * +{ + CAnimObject::Read_t( istrFile); +} + +void CTextureObject::Write_t( CTStream *ostrFile) // throw char * +{ + CAnimObject::Write_t( ostrFile); +} +MEX CTextureObject::GetWidth(void) const +{ return ((CTextureData*)ao_AnimData)->GetWidth(); }; +MEX CTextureObject::GetHeight(void) const +{ return ((CTextureData*)ao_AnimData)->GetHeight(); }; +ULONG CTextureObject::GetFlags(void) const +{ return ((CTextureData*)ao_AnimData)->GetFlags(); }; + +/**************************************** + * Implementation of independent routines + */ +#define EQUAL_SUB_STR( str) (strnicmp( ld_line, str, strlen(str))==0) + +void ProcessScript_t( const CTFileName &inFileName) // throw char * +{ + CTFileStream File; + char ld_line[128]; + char err_str[256]; + FLOAT fTextureWidthMeters = 2.0f; + INDEX TexMipmaps = MAX_MEX_LOG2; + CTextureData tex; + CListHead FrameNamesList; + INDEX NoOfDataFound = 0; + BOOL bForce32bit = FALSE; + + File.Open_t( inFileName, CTStream::OM_READ); // open script file for text reading + + FOREVER + { + do { + File.GetLine_t( ld_line, 128); + } while( (strlen( ld_line)==0) || (ld_line[0]==';')); + + _strupr( ld_line); + + // specified width of texture + if( EQUAL_SUB_STR( "TEXTURE_WIDTH")) { + sscanf( ld_line, "TEXTURE_WIDTH %g", &fTextureWidthMeters); + NoOfDataFound ++; + } + // how many mip-map levels will texture have + else if( EQUAL_SUB_STR( "TEXTURE_MIPMAPS")) { + sscanf( ld_line, "TEXTURE_MIPMAPS %d", &TexMipmaps); + } + // should texture be forced to keep 32-bit quality even that 16-bit textures are set + else if( EQUAL_SUB_STR( "TEXTURE_32BIT")) { + bForce32bit = TRUE; + } + + // Key-word "ANIM_START" starts loading of Animation Data object + else if( EQUAL_SUB_STR( "ANIM_START")) { + tex.LoadFromScript_t( &File, &FrameNamesList); + NoOfDataFound ++; + } + // Key-word "END" ends infinite loop and script loading is over + else if( EQUAL_SUB_STR( "END")) break; + + // if none of known key-words isn't recognised, throw error + else { + sprintf( err_str, + TRANS("Unidentified key-word found (line: \"%s\") or unexpected end of file reached."), ld_line); + throw( err_str); + } + } + if( NoOfDataFound != 2) + throw( TRANS("Required key-word(s) has not been specified in script file:\nTEXTURE_WIDTH and/or ANIM_START")); + + // Now we will create texture file form read script data + CImageInfo inPic; + CTFileName outFileName; + CTFileStream outFile; + + // load first picture + CFileNameNode *pFirstFNN = LIST_HEAD( FrameNamesList, CFileNameNode, cfnn_Node); + inPic.LoadAnyGfxFormat_t( CTString(pFirstFNN->cfnn_FileName)); + + // create texture with one frame + tex.Create_t( &inPic, MEX_METERS(fTextureWidthMeters), TexMipmaps, bForce32bit); + inPic.Clear(); + + // process rest of the frames in animation (if any) + INDEX i=0; + FOREACHINLIST( CFileNameNode, cfnn_Node, FrameNamesList, it1) + { + if( i != 0) { // we have to skip first picture since it has already been done + inPic.LoadAnyGfxFormat_t( CTString(it1->cfnn_FileName)); + // add picture as next frame in texture + tex.AddFrame_t( &inPic); + inPic.Clear(); + } + i++; + } + // save texture + outFileName = inFileName.FileDir() + inFileName.FileName() + ".TEX"; + tex.Save_t( outFileName); + + // clear list + FORDELETELIST( CFileNameNode, cfnn_Node, FrameNamesList, itDel) + delete &itDel.Current(); +} + + +void CreateTexture_t( const CTFileName &inFileName, const CTFileName &outFileName, + MEX inMex, INDEX inMipmaps, BOOL bForce32bit) +{ + if( inFileName.FileExt() == ".SCR") + { + // input is a script file + ProcessScript_t( inFileName); + } + else + { + // input is a picture file (PCX or TGA) + CAnimData anim; + CTextureData tex; + CImageInfo inPic; + + // mex must be specified and valid + if( (inMex <= 0)) throw( TRANS("Invalid or unspecified mexel units.")); + + // load picture + inPic.LoadAnyGfxFormat_t( inFileName); + + // create texture + tex.Create_t( &inPic, inMex, inMipmaps, bForce32bit); + + // no more need for picture - get out! + inPic.Clear(); + + // save texture to file + tex.Save_t( outFileName); + } +} + +void CreateTexture_t( const CTFileName &inFileName, + MEX inMex, INDEX inMipmaps, BOOL bForce32bit) +{ + CTFileName outFileName = inFileName.FileDir() + inFileName.FileName() + ".TEX"; + CreateTexture_t( inFileName, outFileName, inMex, inMipmaps, bForce32bit); +} + +// reference counting (override from CAnimData) +void CTextureData::RemReference_internal(void) +{ + _pTextureStock->Release(this); +} + +// obtain texture and set it for this object +void CTextureObject::SetData_t(const CTFileName &fnmTexture) // throw char * +{ + // if the filename is empty + if (fnmTexture=="") { + // release current texture + SetData(NULL); + + // if the filename is not empty + } else { + // obtain it (adds one reference) + CTextureData *ptd = _pTextureStock->Obtain_t(fnmTexture); + // set it as data (adds one more reference, and remove old reference) + SetData(ptd); + // release it (removes one reference) + _pTextureStock->Release(ptd); + // total reference count +1+1-1 = +1 for new data -1 for old data + } +} + + +// get filename of texture or empty string if no texture +const CTFileName &CTextureObject::GetName(void) +{ + static const CTFileName strDummy(CTString("")); + // if there is some texture + if (ao_AnimData!=NULL) { + // get texture filename + return ao_AnimData->GetName(); + // if there is no texture + } else { + // get empty string + return strDummy; + } +} + + + +// check if this kind of objects is auto-freed +BOOL CTextureData::IsAutoFreed(void) +{ + // cannot be + return FALSE; +} + + + +// get amount of memory used by this object +SLONG CTextureData::GetUsedMemory(void) +{ + // readout texture object + ULONG ulTexObject = td_ulObject; + if( td_ctFrames>1) ulTexObject = td_pulObjects[0]; + + // add structure size and anim block size + SLONG slUsed = sizeof(*this) + CAnimData::GetUsedMemory()-sizeof(CAnimData); + // add effect buffers and static memory if exist + if( td_pubBuffer1!=NULL) slUsed += 2* GetEffectBufferSize(this); // two buffers + if( (td_ulFlags&TEX_STATIC) && td_pulFrames!=NULL) { + slUsed += td_ctFrames*td_slFrameSize; + } + + // add eventual uploaded size and finito + const SLONG slUploadSize = gfxGetTextureSize( ulTexObject, !td_tpLocal.tp_bSingleMipmap); + return slUsed + td_ctFrames*slUploadSize; +} + + + +// get texel from texture's largest mip-map +COLOR CTextureData::GetTexel( MEX mexU, MEX mexV) +{ + // if the texture is not static + if (!(td_ulFlags&TEX_STATIC) && !(td_ulFlags&TEX_CONSTANT)) { + // print warning + ASSERTALWAYS("GetTexel: Texture needs to be static and constant."); + CPrintF("GetTexel: '%s' was not static and/or constant!\n", (const char*)GetName()); + } + + // make sure that the texture is static + Force( TEX_STATIC|TEX_CONSTANT); + // convert dimensions to pixels + PIX pixU = mexU >>td_iFirstMipLevel; + PIX pixV = mexV >>td_iFirstMipLevel; + pixU &= GetPixWidth()-1; + pixV &= GetPixHeight()-1; + ASSERT(pixU>=0 && pixU=0 && pixV1 || aiInfo.ai_NumberOfFrames>1) { + strAnims.PrintF(" %d(%d)anim", ad_NumberOfAnims, aiInfo.ai_NumberOfFrames); + } + + // return combined string + return str+strFlags+strAnims; +} diff --git a/Sources/Engine/Graphics/Texture.h b/Sources/Engine/Graphics/Texture.h new file mode 100644 index 0000000..6c5c3f9 --- /dev/null +++ b/Sources/Engine/Graphics/Texture.h @@ -0,0 +1,207 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TEXTURE_H +#define SE_INCL_TEXTURE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include + +#define BYTES_PER_TEXEL 4 // all textures in engine are 4 bytes per pixel + +// td_ulFlags bits +// (on disk and in memory) +#define TEX_ALPHACHANNEL (1UL<<0) // texture has alpha channel (for old version support) +#define TEX_32BIT (1UL<<1) // texture needs to be in 32-bit quality uploaded if can +// (only in memory) +#define TEX_STATIC (1UL<<5) // remain loaded after being bound (i.e. uploaded - for base textures) +#define TEX_CONSTANT (1UL<<6) // cannot be changed (no mip-map disposing, no LOD biasing, no colorizing, nothing!) +#define TEX_TRANSPARENT (1UL<<7) // only one bit of alpha channel is enough (internal format GL_RGB5_A1) +#define TEX_EQUALIZED (1UL<<8) // texture has 128-gray last mipmap (i.e. can be discarded in shade mode) +#define TEX_GRAY (1UL<<9) // grayscale texture +#define TEX_WHITE (1UL<<10) // completely white texture (believe me, there are some cases) +#define TEX_KEEPCOLOR (1UL<<11) // don't (de)saturate (for heightmaps and such!) +#define TEX_SINGLEMIPMAP (1UL<<18) // set if last uploading was in single-mipmap +#define TEX_PROBED (1UL<<19) // set if last binding was as probe-texture +// (flags that shows if texture mipmaps has been changed) +#define TEX_DISPOSED (1UL<<20) // largest mip-map(s) has been left-out +#define TEX_DITHERED (1UL<<21) // dithering has been applied on this texture +#define TEX_FILTERED (1UL<<22) // flitering has been applied on this texture +#define TEX_SATURATED (1UL<<23) // saturation has been adjusted on this texture +#define TEX_COLORIZED (1UL<<24) // mipmaps has been colorized on this texture +#define TEX_WASOLD (1UL<<30) // loaded from old format (version 3) + + +/* + * Bitmap data for a class of texture objects + */ +class ENGINE_API CTextureData : public CAnimData { +public: +// implementation: + ULONG td_ulFlags; // see defines + MEX td_mexWidth, td_mexHeight; // texture dimensions + INDEX td_iFirstMipLevel; // the highest quality mip level + INDEX td_ctFineMipLevels; // number of bilineary created mip levels + SLONG td_slFrameSize; // sum of sizes of all mip-maps for one frame + INDEX td_ctFrames; // number of different frames + + class CTexParams td_tpLocal; // local texture parameters + ULONG td_ulInternalFormat; // format in which texture will be uploaded + CTimerValue td_tvLastDrawn; // timer for probing + ULONG td_ulProbeObject; + union { + ULONG td_ulObject; + ULONG *td_pulObjects; + }; + ULONG *td_pulFrames; // all frames with their mip-maps and private palettes + UBYTE *td_pubBuffer1, *td_pubBuffer2; // buffers for effect textures + PIX td_pixBufferWidth, td_pixBufferHeight; // effect buffer dimensions + class CTextureData *td_ptdBaseTexture; // base texure for effects (if any) + class CTextureEffectGlobal *td_ptegEffect; // all data for effect textures + + INDEX td_iRenderFrame; // frame number currently rendering (for profiling) + + // constructor and destructor + CTextureData(); + ~CTextureData(); + + // reference counting (override from CAnimData) + void RemReference_internal(void); + + // converts global mip level to the corresponding one of texture + INDEX ClampMipLevel( FLOAT fMipFactor) const; + + // gets values from some of texture data members + inline MEX GetWidth(void) const { return td_mexWidth; }; + inline MEX GetHeight(void) const { return td_mexHeight; }; + inline PIX GetPixWidth(void) const { return td_mexWidth >>td_iFirstMipLevel; }; + inline PIX GetPixHeight(void) const { return td_mexHeight>>td_iFirstMipLevel; }; + inline ULONG GetFlags(void) const { return td_ulFlags; }; + inline ULONG GetNoOfMips(void) const { return GetNoOfMipmaps( GetPixWidth(), GetPixHeight()); }; + inline ULONG GetNoOfFineMips(void) const { return td_ctFineMipLevels; }; + + // mark that texture has been used + inline void MarkDrawn(void) { td_tvLastDrawn = _pTimer->GetHighPrecisionTimer(); }; + + // get string description of texture size, mips and parameters + CTString GetDescription(void); + + // sets new texture mex width and changes height remaining texture's aspect ratio + inline void ChangeSize( MEX mexNewWidth) { + td_mexHeight = MEX( ((FLOAT)mexNewWidth)/td_mexWidth * td_mexHeight); + td_mexWidth = mexNewWidth; + }; + + // check if texture frame(s) has been somehow altered (dithering, filtering, saturation, colorizing...) + inline BOOL IsModified(void) { + return td_ulFlags & (TEX_DISPOSED|TEX_DITHERED|TEX_FILTERED|TEX_SATURATED|TEX_COLORIZED); + }; + + // export finest mipmap of one texture's frame to imageinfo + void Export_t( class CImageInfo &iiExportedImage, INDEX iFrame); + + // set texture frame as current for accelerator (this will upload texture that needs or wants uploading) + void SetAsCurrent( INDEX iFrameNo=0, BOOL bForceUpload=FALSE); + + // creates new effect texture with one frame + void CreateEffectTexture( PIX pixWidth, PIX pixHeight, MEX mexWidth, + CTextureData *ptdBaseTexture, ULONG ulGlobalEffect); + // creates new texture with one frame + void Create_t( const CImageInfo *pII, MEX mexWanted, INDEX ctFineMips, BOOL bForce32bit); + // adds one frame to created texture + void AddFrame_t( const CImageInfo *pII); + + // remove texture from gfx API (driver) + void Unbind(void); + // free memory allocated for texture + void Clear(void); + + // read texture from file + void Read_t( CTStream *inFile); + // write texture to file + void Write_t( CTStream *outFile); + // force texture to be re-loaded (if needed) in corresponding manner + void Force( ULONG ulTexFlags); + + // get texel from texture's largest mip-map + COLOR GetTexel( MEX mexU, MEX mexV); + // copy (and eventually convert to floats) one row from texture to an array (iChannel is 1=R,2=G,3=B,4=A) + void FetchRow( PIX pixRow, void *pfDst, INDEX iChannel=4, BOOL bConvertToFloat=TRUE); + // get pointer to one row of texture + ULONG *GetRowPointer( PIX pixRow); + +// overridden from CSerial: + + // check if this kind of objects is auto-freed + virtual BOOL IsAutoFreed(void); + // get amount of memory used by this object + virtual SLONG GetUsedMemory(void); +}; + + +/* + * An instance of a texture object + */ +class ENGINE_API CTextureObject : public CAnimObject { +// implementation: +public: +// interface: +public: + CTextureObject(void); + // copy from another object of same class + void Copy(CTextureObject &toOther); + MEX GetWidth(void) const; + MEX GetHeight(void) const; + ULONG GetFlags(void) const; + void Read_t( CTStream *istrFile); // throw char * // read and + void Write_t( CTStream *ostrFile); // throw char * // write functions + + // obtain texture and set it for this object + void SetData_t(const CTFileName &fnmTexture); // throw char * + // get filename of texture or empty string if no texture + const CTFileName &GetName(void); +}; + +ENGINE_API extern void CreateTexture_t( const CTFileName &inFileName, + MEX inMex, INDEX inMipmaps, BOOL bForce32bit); +ENGINE_API extern void CreateTexture_t( const CTFileName &inFileName, const CTFileName &outFileName, + MEX inMex, INDEX inMipmaps, BOOL bForce32bit); +ENGINE_API extern void ProcessScript_t( const CTFileName &inFileName); + + + +/* + * Render-to-texture class + */ +/* +class ENGINE_API CRenderTexture +{ +// implementation: +public: + CListNode rt_lnInGfx // for linking in list of all renderable textures + ULONG rt_ulFlags; // see defines (only alpha and 32bit, for now) + PIX tt_pixWidth, rt_pixHeight; // texture dimensions + ULONG td_ulInternalFormat; // format in which texture will be uploaded + ULONG *rt_pulImage; // image in memory (no mipmaps for now!) + class CTexParams td_tpLocal; // local texture parameters + +// interface: +public: + CRenderTexture(void); + ~CRenderTexture(void); + // prepare + BOOL Init( PIX pixWidth, PIX pixHeight, BOOL b32bit, BOOL bAlpha=FALSE); + // reset (i.e. prepare again - after display mode switch and stuff like that) + void Reset(void); + // set texture as current for accelerator + void SetAsCurrent(void); + // set texture as target for rendering + void SetAsTarget(void); +}; +*/ + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/TextureEffects.cpp b/Sources/Engine/Graphics/TextureEffects.cpp new file mode 100644 index 0000000..3a60e74 --- /dev/null +++ b/Sources/Engine/Graphics/TextureEffects.cpp @@ -0,0 +1,2678 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + +#define ASMOPT 1 + + +static const __int64 mm1LO = 0x0000000000000001; +static const __int64 mm1HI = 0x0000000100000000; +static const __int64 mm1HILO = 0x0000000100000001; +static const __int64 mm0001 = 0x0000000000000001; +static const __int64 mm0010 = 0x0000000000010000; +static const __int64 mm00M0 = 0x00000000FFFF0000; +static __int64 mmBaseWidthShift=0, mmBaseWidth=0, mmBaseWidthMask=0, mmBaseHeightMask=0, mmBaseMasks=0, mmShift=0; + + +// speed table +static SBYTE asbMod3Sub1Table[256]; +static BOOL bTableSet = FALSE; + +static CTextureData *_ptdEffect, *_ptdBase; +static PIX _pixTexWidth, _pixTexHeight; +static PIX _pixBufferWidth, _pixBufferHeight; +static ULONG _ulBufferMask; +static INDEX _iWantedMipLevel; +static UBYTE *_pubDrawBuffer; +static SWORD *_pswDrawBuffer; + + +// randomizer +static ULONG ulRNDSeed; + +inline void Randomize( ULONG ulSeed) +{ + if( ulSeed==0) ulSeed = 0x87654321; + ulRNDSeed = ulSeed*262147; +}; + +inline ULONG Rnd(void) +{ + ulRNDSeed = ulRNDSeed*262147; + return ulRNDSeed; +}; + +#define RNDW (Rnd()>>16) + + + +// Initialize the texture effect source. +void CTextureEffectSource::Initialize( class CTextureEffectGlobal *ptegGlobalEffect, + ULONG ulEffectSourceType, PIX pixU0, PIX pixV0, + PIX pixU1, PIX pixV1) +{ // remember global effect for cross linking + tes_ptegGlobalEffect = ptegGlobalEffect; + tes_ulEffectSourceType = ulEffectSourceType; + + // obtain effect source table for current effect class + struct TextureEffectSourceType *patestSourceEffectTypes = + _ategtTextureEffectGlobalPresets[ ptegGlobalEffect->teg_ulEffectType].tet_atestEffectSourceTypes; + + // init for animating + patestSourceEffectTypes[ulEffectSourceType].test_Initialize(this, pixU0, pixV0, pixU1, pixV1); +} + +// Animate the texture effect source. +void CTextureEffectSource::Animate(void) +{ + // obtain effect source table for current effect class + struct TextureEffectSourceType *patestSourceEffectTypes = + _ategtTextureEffectGlobalPresets[ tes_ptegGlobalEffect->teg_ulEffectType] + .tet_atestEffectSourceTypes; + + // animating it + patestSourceEffectTypes[tes_ulEffectSourceType].test_Animate(this); +} + + +// ---------------------------------------- +// SLONG WATER +// ---------------------------------------- +inline void PutPixelSLONG_WATER( PIX pixU, PIX pixV, INDEX iHeight) +{ + _pswDrawBuffer[(pixV*_pixBufferWidth+pixU)&_ulBufferMask] += iHeight; +} + +inline void PutPixel9SLONG_WATER( PIX pixU, PIX pixV, INDEX iHeightMid) +{ + INDEX iHeightSide = (iHeightMid*28053) >>16; // iHeight /0.851120 *0.364326; + INDEX iHeightDiag = (iHeightMid*12008) >>16; // iHeight /0.851120 *0.155951; + + PutPixelSLONG_WATER( pixU-1, pixV-1, iHeightDiag); + PutPixelSLONG_WATER( pixU, pixV-1, iHeightSide); + PutPixelSLONG_WATER( pixU+1, pixV-1, iHeightDiag); + + PutPixelSLONG_WATER( pixU-1, pixV, iHeightSide); + PutPixelSLONG_WATER( pixU, pixV, iHeightMid); + PutPixelSLONG_WATER( pixU+1, pixV, iHeightSide); + + PutPixelSLONG_WATER( pixU-1, pixV+1, iHeightDiag); + PutPixelSLONG_WATER( pixU, pixV+1, iHeightSide); + PutPixelSLONG_WATER( pixU+1, pixV+1, iHeightDiag); +} + + +// ---------------------------------------- +// UBYTE FIRE +// ---------------------------------------- +inline void PutPixelUBYTE_FIRE( PIX pixU, PIX pixV, INDEX iHeight) +{ + PIX pixLoc = (pixV*_pixBufferWidth+pixU) & _ulBufferMask; + _pubDrawBuffer[pixLoc] = Clamp( _pubDrawBuffer[pixLoc] +iHeight, 0L, 255L); +} + +inline void PutPixel9UBYTE_FIRE( PIX pixU, PIX pixV, INDEX iHeightMid) +{ + INDEX iHeightSide = (iHeightMid*28053) >>16; // iHeight /0.851120 *0.364326; + INDEX iHeightDiag = (iHeightMid*12008) >>16; // iHeight /0.851120 *0.155951; + + PutPixelUBYTE_FIRE( pixU-1, pixV-1, iHeightDiag); + PutPixelUBYTE_FIRE( pixU, pixV-1, iHeightSide); + PutPixelUBYTE_FIRE( pixU+1, pixV-1, iHeightDiag); + + PutPixelUBYTE_FIRE( pixU-1, pixV, iHeightSide); + PutPixelUBYTE_FIRE( pixU, pixV, iHeightMid); + PutPixelUBYTE_FIRE( pixU+1, pixV, iHeightSide); + + PutPixelUBYTE_FIRE( pixU-1, pixV+1, iHeightDiag); + PutPixelUBYTE_FIRE( pixU, pixV+1, iHeightSide); + PutPixelUBYTE_FIRE( pixU+1, pixV+1, iHeightDiag); +} + +inline void PutPixel25UBYTE_FIRE( PIX pixU, PIX pixV, INDEX iHeightMid) +{ + INDEX iHeightSide = (iHeightMid*28053) >>16; // iHeight /0.851120 *0.364326; + INDEX iHeightDiag = (iHeightMid*12008) >>16; // iHeight /0.851120 *0.155951; + + PutPixelUBYTE_FIRE( pixU-2, pixV-2, iHeightDiag); + PutPixelUBYTE_FIRE( pixU-1, pixV-2, iHeightSide); + PutPixelUBYTE_FIRE( pixU, pixV-2, iHeightSide); + PutPixelUBYTE_FIRE( pixU+1, pixV-2, iHeightSide); + PutPixelUBYTE_FIRE( pixU+2, pixV-2, iHeightDiag); + + PutPixelUBYTE_FIRE( pixU-2, pixV-1, iHeightSide); + PutPixelUBYTE_FIRE( pixU-1, pixV-1, iHeightSide); + PutPixelUBYTE_FIRE( pixU, pixV-1, iHeightMid); + PutPixelUBYTE_FIRE( pixU+1, pixV-1, iHeightSide); + PutPixelUBYTE_FIRE( pixU+2, pixV-1, iHeightSide); + + PutPixelUBYTE_FIRE( pixU-2, pixV, iHeightSide); + PutPixelUBYTE_FIRE( pixU-1, pixV, iHeightMid); + PutPixelUBYTE_FIRE( pixU, pixV, iHeightMid); + PutPixelUBYTE_FIRE( pixU+1, pixV, iHeightMid); + PutPixelUBYTE_FIRE( pixU+2, pixV, iHeightSide); + + PutPixelUBYTE_FIRE( pixU-2, pixV+1, iHeightSide); + PutPixelUBYTE_FIRE( pixU-1, pixV+1, iHeightSide); + PutPixelUBYTE_FIRE( pixU, pixV+1, iHeightMid); + PutPixelUBYTE_FIRE( pixU+1, pixV+1, iHeightSide); + PutPixelUBYTE_FIRE( pixU+2, pixV+1, iHeightSide); + + PutPixelUBYTE_FIRE( pixU+2, pixV+2, iHeightDiag); + PutPixelUBYTE_FIRE( pixU-1, pixV+2, iHeightSide); + PutPixelUBYTE_FIRE( pixU, pixV+2, iHeightSide); + PutPixelUBYTE_FIRE( pixU+1, pixV+2, iHeightSide); + PutPixelUBYTE_FIRE( pixU-2, pixV+2, iHeightDiag); +} + + +///////////////////////////////////////////////////////////////////// +// WATER EFFECTS +///////////////////////////////////////////////////////////////////// + +#define DISTORSION 3 //3 + + +///////////////// random surfer +struct Surfer { + FLOAT fU; + FLOAT fV; + FLOAT fAngle; +}; + +void InitializeRandomSurfer(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + Surfer &sf = + ((Surfer&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + sf.fU = pixU0; + sf.fV = pixV0; + sf.fAngle = RNDW&7; +} + +void AnimateRandomSurfer(CTextureEffectSource *ptes) +{ + Surfer &sf = + ((Surfer&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + + PutPixel9SLONG_WATER(sf.fU, sf.fV, 125); + sf.fU += 2*sin(sf.fAngle); + sf.fV += 2*cos(sf.fAngle); + PutPixel9SLONG_WATER(sf.fU, sf.fV, 250); + + if((RNDW&15)==0) { + sf.fAngle += 3.14f/7.0f; + } + if((RNDW&15)==0) { + sf.fAngle -= 3.14f/5.0f; + } +} + +///////////////// raindrops +struct Raindrop { + UBYTE pixU; + UBYTE pixV; + SWORD iHeight; + SWORD iIndex; +}; + + +void InitializeRaindrops(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1, int iHeight) +{ + for (int iIndex=0; iIndex<5; iIndex++) { + Raindrop &rd = + ((Raindrop&) ptes->tes_tespEffectSourceProperties.tesp_achDummy[iIndex*sizeof(Raindrop)]); + rd.pixU = RNDW&(_pixBufferWidth -1); + rd.pixV = RNDW&(_pixBufferHeight-1); + rd.iHeight = RNDW&iHeight; + rd.iIndex = iIndex*8; + } +} +void InitializeRaindropsStandard(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) { + InitializeRaindrops(ptes, pixU0, pixV0, pixU1, pixV1, 255); +} +void InitializeRaindropsBig(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) { + InitializeRaindrops(ptes, pixU0, pixV0, pixU1, pixV1, 1023); +} +void InitializeRaindropsSmall(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) { + InitializeRaindrops(ptes, pixU0, pixV0, pixU1, pixV1, 31); +} + + +void AnimateRaindrops(CTextureEffectSource *ptes, int iHeight) +{ + for (int iIndex=0; iIndex<5; iIndex++) { + Raindrop &rd = + ((Raindrop&) ptes->tes_tespEffectSourceProperties.tesp_achDummy[iIndex*sizeof(Raindrop)]); + if (rd.iIndex < 48) { + rd.iIndex++; + + if (rd.iIndex < 8) { + PutPixel9SLONG_WATER(rd.pixU, rd.pixV, sin(rd.iIndex/4.0f*(-3.14f))*rd.iHeight); + } + } else { + rd.pixU = RNDW&(_pixBufferWidth -1); + rd.pixV = RNDW&(_pixBufferHeight-1); + rd.iHeight = RNDW&iHeight; + rd.iIndex = 0; + } + } +} +void AnimateRaindropsStandard(CTextureEffectSource *ptes) { + AnimateRaindrops(ptes, 255); +} +void AnimateRaindropsBig(CTextureEffectSource *ptes) { + AnimateRaindrops(ptes, 1023); +} +void AnimateRaindropsSmall(CTextureEffectSource *ptes) { + AnimateRaindrops(ptes, 31); +} + + + +///////////////// oscilator +struct Oscilator { + UBYTE pixU; + UBYTE pixV; + FLOAT fAngle; +}; + +void InitializeOscilator(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + Oscilator &os = + ((Oscilator&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + os.pixU = pixU0; + os.pixV = pixV0; + os.fAngle = -3.14f; +} + +void AnimateOscilator(CTextureEffectSource *ptes) +{ + Oscilator &os = + ((Oscilator&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + PutPixel9SLONG_WATER(os.pixU, os.pixV, sin(os.fAngle)*150); + os.fAngle += (3.14f/6); +} + + +///////////////// Vertical Line +struct VertLine{ + UBYTE pixU; + UBYTE pixV; + UWORD uwSize; + FLOAT fAngle; +}; + +void InitializeVertLine(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + VertLine &vl = + ((VertLine&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + vl.pixU = pixU0; + vl.pixV = pixV0; + vl.fAngle = -3.14f; + if (pixV0==pixV1) { + vl.uwSize = 16; + } else { + vl.uwSize = abs(pixV1-pixV0); + } +} + +void AnimateVertLine(CTextureEffectSource *ptes) +{ + VertLine &vl = + ((VertLine&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + PIX pixV = vl.pixV; + for (int iCnt=0; iCnttes_tespEffectSourceProperties.tesp_achDummy); + hl.pixU = pixU0; + hl.pixV = pixV0; + hl.fAngle = -3.14f; + if (pixU0==pixU1) { + hl.uwSize = 16; + } else { + hl.uwSize = abs(pixU1-pixU0); + } +} + +void AnimateHortLine(CTextureEffectSource *ptes) +{ + HortLine &hl = + ((HortLine&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + PIX pixU = hl.pixU; + for (int iCnt=0; iCnttes_tespEffectSourceProperties.tesp_achDummy); + ft.pixU = pixU0; + ft.pixV = pixV0; +} + +void AnimateFirePoint(CTextureEffectSource *ptes) +{ + FirePoint &ft = + ((FirePoint&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + PutPixel9UBYTE_FIRE(ft.pixU, ft.pixV, 255); +} + +void InitializeRandomFirePoint(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + FirePoint &ft = + ((FirePoint&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + ft.pixU = pixU0; + ft.pixV = pixV0; +} + +void AnimateRandomFirePoint(CTextureEffectSource *ptes) +{ + FirePoint &ft = + ((FirePoint&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + PutPixel9UBYTE_FIRE(ft.pixU, ft.pixV, RNDW&255); +} + +void InitializeFireShakePoint(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + FirePoint &ft = + ((FirePoint&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + ft.pixU = pixU0; + ft.pixV = pixV0; +} + +void AnimateFireShakePoint(CTextureEffectSource *ptes) +{ + FirePoint &ft = + ((FirePoint&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + UBYTE pixU, pixV; + pixU = RNDW%3 - 1; + pixV = RNDW%3 - 1; + PutPixel9UBYTE_FIRE(ft.pixU+pixU, ft.pixV+pixV, 255); +} + + +///////////////// Fire Place +#define FIREPLACE_SIZE 60 + +struct FirePlace{ + UBYTE pixU; + UBYTE pixV; + UBYTE ubWidth; + UBYTE aubFire[FIREPLACE_SIZE]; +}; + +void InitializeFirePlace(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + FirePlace &fp = + ((FirePlace&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + fp.pixU = pixU0; + fp.pixV = pixV0; + fp.ubWidth = abs(pixU1-pixU0); + if (fp.ubWidth>FIREPLACE_SIZE) fp.ubWidth=FIREPLACE_SIZE; + if (fp.ubWidth<10) fp.ubWidth = 10; + // clear fire array + for (int iCnt=0; iCnttes_tespEffectSourceProperties.tesp_achDummy); + ULONG ulRND = RNDW&255; + // match + if (ulRND>200) { + ULONG ulMatchIndex = ulRND%(fp.ubWidth-5); + for (iIndex=0; iIndex<5; iIndex++) { + fp.aubFire[ulMatchIndex+iIndex] = 255; + } + // water + } else if (ulRND<50) { + for (iIndex=0; iIndex<10; iIndex++) { + fp.aubFire[RNDW%fp.ubWidth] = 0; + } + } + // fix fire place + for (iIndex=0; iIndex 10) { + ubFlame += RNDW%30; //30 + // give more fire + } else { + ubFlame += RNDW%30+30; //30,30 + } + } + fp.aubFire[iIndex] = ubFlame; + } + // water on edges + for (iIndex=0; iIndex<4; iIndex++) { + INDEX iWater = RNDW%4; + fp.aubFire[iWater] = 0; + fp.aubFire[fp.ubWidth-1-iWater] = 0; + } + // smooth fire place + for (iIndex=1; iIndex<(fp.ubWidth-1); iIndex++) { + fp.aubFire[iIndex] = (fp.aubFire[iIndex-1]+fp.aubFire[iIndex]+fp.aubFire[iIndex+1])/3; + } + // draw fire place in buffer + for (iIndex=0; iIndextes_tespEffectSourceProperties.tesp_achDummy); + fr.pixU = pixU0; + fr.pixV = pixV0; + if (pixU0==pixU1 && pixV0==pixV1) { + //fr.fRadius = 3; + fr.fRadiusU = 3; + fr.fRadiusV = 3; + fr.fAngleAdd = (3.14f/6); + } else { + //fr.fRadius = sqrt((pixU1-pixU0)*(pixU1-pixU0) + (pixV1-pixV0)*(pixV1-pixV0)); + fr.fRadiusU = pixU1-pixU0; + fr.fRadiusV = pixV1-pixV0; + //fr.fAngleAdd = (3.14f/((fr.fRadius)*2)); + fr.fAngleAdd = (3.14f/(Abs(fr.fRadiusU)+Abs(fr.fRadiusV))); + } + fr.fAngle = 0; +} + +void AnimateFireRoler(CTextureEffectSource *ptes) +{ + FireRoler &fr = + ((FireRoler&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + PutPixel9UBYTE_FIRE(cos(fr.fAngle)*fr.fRadiusU + fr.pixU, + sin(fr.fAngle)*fr.fRadiusV + fr.pixV, 255); + fr.fAngle += fr.fAngleAdd; + PutPixel9UBYTE_FIRE(cos(fr.fAngle)*fr.fRadiusU + fr.pixU, + sin(fr.fAngle)*fr.fRadiusV + fr.pixV, 200); + fr.fAngle += fr.fAngleAdd; + PutPixel9UBYTE_FIRE(cos(fr.fAngle)*fr.fRadiusU + fr.pixU, + sin(fr.fAngle)*fr.fRadiusV + fr.pixV, 150); + fr.fAngle += fr.fAngleAdd; +} + + +///////////////// Fire Fall +#define FIREFALL_POINTS 100 + +struct FireFall{ + UBYTE pixU; + UBYTE pixV; + ULONG ulWidth; + ULONG ulPointToReinitialize; +}; + +struct FireFallPixel{ + UBYTE pixU; + UBYTE pixV; + UBYTE ubSpeed; +}; + +void InitializeFireFall(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + FireFall &ff = + ((FireFall&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + ff.pixU = pixU0; + ff.pixV = pixV0; + if (pixU0==pixU1) { + ff.ulWidth = 15; + } else { + ff.ulWidth = abs(pixU1-pixU0); + } + // initialize fall points + ptes->tes_atepPixels.New(FIREFALL_POINTS); + ff.ulPointToReinitialize = 0; + for (INDEX iIndex=0; iIndextes_atepPixels[iIndex]); + ffp.pixU = ff.pixU+(RNDW%ff.ulWidth); + ffp.pixV = ff.pixV+(RNDW%_pixBufferHeight); + ffp.ubSpeed = (RNDW&1)+2; + } +} + +void AnimateFireFall(CTextureEffectSource *ptes) +{ + FireFall &ff = + ((FireFall&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + // animate fall points + for (INDEX iIndex=0; iIndextes_atepPixels[iIndex]); + // fall from fall + int iHeight = (RNDW&3)*64 + 40; + if (ffp.ubSpeed == 2) { + PutPixelUBYTE_FIRE(ffp.pixU+(RNDW%3)-1, ffp.pixV, iHeight); + PutPixelUBYTE_FIRE(ffp.pixU+(RNDW%3)-1, ffp.pixV+1, iHeight-40); + } else { + PutPixelUBYTE_FIRE(ffp.pixU, ffp.pixV, iHeight); + PutPixelUBYTE_FIRE(ffp.pixU, ffp.pixV+1, iHeight-40); + } + ffp.pixV+=ffp.ubSpeed; + // when falled down reinitialize + if (ffp.pixV >= _pixBufferHeight) { + if (ff.ulPointToReinitialize == iIndex) { + ff.ulPointToReinitialize++; + if (ff.ulPointToReinitialize >= FIREFALL_POINTS) ff.ulPointToReinitialize = 0; + ffp.pixU = ff.pixU+(RNDW%ff.ulWidth); + ffp.pixV -= _pixBufferHeight; + ffp.ubSpeed = (RNDW&1)+2; + } else { + ffp.pixV -= _pixBufferHeight; + } + } + } +} + + +///////////////// Fire Fountain +#define FIREFOUNTAIN_POINTS 100 + +struct FireFountain{ + UBYTE pixU; + UBYTE pixV; + ULONG ulWidth; + ULONG ulBaseHeight; + ULONG ulRandomHeight; + +}; + +struct FireFountainPixel{ + SWORD pixU; + SWORD pixV; + UBYTE pixLastU; + UBYTE pixLastV; + SWORD sbSpeedU; + SWORD sbSpeedV; +}; + +void InitializeFireFountain(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + FireFountain &ff = + ((FireFountain&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + ff.pixU = pixU0; + ff.pixV = pixV0; + // fountain width + if (pixU0==pixU1) { + ff.ulWidth = 31; + } else { + ff.ulWidth = abs(pixU1-pixU0)*2; + } + // fountain height + if (pixV0==pixV1) { + ff.ulBaseHeight = 120; + ff.ulRandomHeight = 40; + } else { + ff.ulBaseHeight = abs(pixV1-pixV0)*3; + ff.ulRandomHeight = abs(pixV1-pixV0); + } + // initialize fountain points + ptes->tes_atepPixels.New(FIREFOUNTAIN_POINTS*2); + for (INDEX iIndex=0; iIndextes_atepPixels[iIndex]); + ffp.pixU = (ff.pixU)<<6; + ffp.pixV = (RNDW%(_pixBufferHeight-(_pixBufferHeight>>3))+(_pixBufferHeight>>3))<<6; + ffp.pixLastU = (ffp.pixU)>>6; + ffp.pixLastV = (ffp.pixV)>>6; + ffp.sbSpeedU = 0; + ffp.sbSpeedV = 0; + } +} + +void AnimateFireFountain(CTextureEffectSource *ptes) +{ + FireFountain &ff = + ((FireFountain&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + // animate fountain points + for (INDEX iIndex=0; iIndextes_atepPixels[iIndex]); + // fall from fountain + PutPixelUBYTE_FIRE((ffp.pixU)>>6, (ffp.pixV)>>6, 200); + PutPixelUBYTE_FIRE(ffp.pixLastU, ffp.pixLastV, 150); + // move pixel + ffp.pixLastU = (ffp.pixU)>>6; + ffp.pixLastV = (ffp.pixV)>>6; + ffp.pixU+=ffp.sbSpeedU; + ffp.pixV-=ffp.sbSpeedV; + ffp.sbSpeedV-=8; + // when falled down reinitialize + if ((ffp.pixV>>6) >= (_pixBufferHeight-5)) { + ffp.pixU = (ff.pixU)<<6; + ffp.pixV = (ff.pixV)<<6; + ffp.pixLastU = (ffp.pixU)>>6; + ffp.pixLastV = (ffp.pixV)>>6; + ffp.sbSpeedU = (RNDW%ff.ulWidth)-(ff.ulWidth/2-1); + ffp.sbSpeedV = (RNDW%ff.ulRandomHeight)+ff.ulBaseHeight; + } + } +} + + +///////////////// Fire Fountain +#define FIRESIDEFOUNTAIN_POINTS 100 + +struct FireSideFountain{ + UBYTE pixU; + UBYTE pixV; + ULONG ulBaseWidth; + ULONG ulRandomWidth; + ULONG ulSide; +}; + +struct FireSideFountainPixel{ + SWORD pixU; + SWORD pixV; + UBYTE pixLastU; + UBYTE pixLastV; + SWORD sbSpeedU; + SWORD sbSpeedV; +}; + +void InitializeFireSideFountain(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + FireSideFountain &fsf = + ((FireSideFountain&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + fsf.pixU = pixU0; + fsf.pixV = pixV0; + // fountain width + if (pixU0==pixU1) { + fsf.ulBaseWidth = 80; + fsf.ulRandomWidth = 40; + fsf.ulSide = (pixU0>(_pixBufferWidth/2)); + } else { + fsf.ulBaseWidth = abs(pixU1-pixU0)*2; + fsf.ulRandomWidth = abs(pixU1-pixU0); + fsf.ulSide = (pixU1tes_atepPixels.New(FIRESIDEFOUNTAIN_POINTS*2); + for (INDEX iIndex=0; iIndextes_atepPixels[iIndex]); + fsfp.pixU = (fsf.pixU)<<6; + fsfp.pixV = (RNDW%(_pixBufferHeight-(_pixBufferHeight>>3))+(_pixBufferHeight>>3))<<6; + fsfp.pixLastU = (fsfp.pixU)>>6; + fsfp.pixLastV = (fsfp.pixV)>>6; + fsfp.sbSpeedU = 0; + fsfp.sbSpeedV = 0; + } +} + +void AnimateFireSideFountain(CTextureEffectSource *ptes) +{ + FireSideFountain &fsf = + ((FireSideFountain&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + // animate fountain points + for (INDEX iIndex=0; iIndextes_atepPixels[iIndex]); + // fall from fountain + PutPixelUBYTE_FIRE((fsfp.pixU)>>6, (fsfp.pixV)>>6, 200); + PutPixelUBYTE_FIRE(fsfp.pixLastU, fsfp.pixLastV, 150); + // move pixel + fsfp.pixLastU = (fsfp.pixU)>>6; + fsfp.pixLastV = (fsfp.pixV)>>6; + fsfp.pixU+=fsfp.sbSpeedU; + fsfp.pixV-=fsfp.sbSpeedV; + fsfp.sbSpeedV-=8; + // when falled down reinitialize + if ((fsfp.pixV>>6) >= (_pixBufferHeight-5)) { + fsfp.pixU = (fsf.pixU)<<6; + fsfp.pixV = (fsf.pixV)<<6; + fsfp.pixLastU = (fsfp.pixU)>>6; + fsfp.pixLastV = (fsfp.pixV)>>6; + fsfp.sbSpeedU = (RNDW%fsf.ulRandomWidth)+fsf.ulBaseWidth; + if (fsf.ulSide) { + fsfp.sbSpeedU = -fsfp.sbSpeedU; + } + fsfp.sbSpeedV = 0; + } + } +} + + +///////////////// Fire Lightning +struct FireLightning{ + FLOAT fpixUFrom; + FLOAT fpixVFrom; + FLOAT fpixUTo; + FLOAT fpixVTo; + FLOAT fvU; + FLOAT fvV; + FLOAT fvNormalU; + FLOAT fvNormalV; + FLOAT fDistance; + SLONG slCnt; +}; + +void InitializeFireLightning(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + FireLightning &fl = + ((FireLightning&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + fl.fpixUFrom = (FLOAT) pixU0; + fl.fpixVFrom = (FLOAT) pixV0; + if (pixU0==pixU1 && pixV0==pixV1) { + fl.fpixUTo = Abs((FLOAT)_pixBufferWidth -fl.fpixUFrom); + fl.fpixVTo = Abs((FLOAT)_pixBufferHeight-fl.fpixVFrom); + } else { + fl.fpixUTo = (FLOAT) pixU1; + fl.fpixVTo = (FLOAT) pixV1; + } + fl.fDistance = sqrt((fl.fpixUTo-fl.fpixUFrom)*(fl.fpixUTo-fl.fpixUFrom)+ + (fl.fpixVTo-fl.fpixVFrom)*(fl.fpixVTo-fl.fpixVFrom)); + // vector + fl.fvU = (fl.fpixUTo-fl.fpixUFrom)/fl.fDistance; + fl.fvV = (fl.fpixVTo-fl.fpixVFrom)/fl.fDistance; + // normal vector + fl.fvNormalU = -fl.fvV; + fl.fvNormalV = fl.fvU; + // frame counter + fl.slCnt = 2; +} + +void AnimateFireLightning(CTextureEffectSource *ptes) +{ + FLOAT fU, fV, fLastU, fLastV; + FLOAT fDU, fDV, fCnt; + SLONG slRND; + ULONG ulDist; + + FireLightning &fl = + ((FireLightning&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + // last point -> starting point + fLastU = fl.fpixUFrom; + fLastV = fl.fpixVFrom; + + fl.slCnt--; + if (fl.slCnt == 0) { + ulDist = 0; + while ((FLOAT)ulDist=fl.fDistance) { + // move point to line end + fU = fl.fpixUTo; + fV = fl.fpixVTo; + } else { + // move point on line + fU = fl.fpixUFrom + fl.fvU*(FLOAT)ulDist; + fV = fl.fpixVFrom + fl.fvV*(FLOAT)ulDist; + // move point offset on normal line + slRND = (SLONG) (RNDW%11)-5; + fU += fl.fvNormalU*(FLOAT)slRND; + fV += fl.fvNormalV*(FLOAT)slRND; + } + // draw line + fDU = fU-fLastU; + fDV = fV-fLastV; + if (Abs(fDU)>Abs(fDV)) fCnt = Abs(fDU); + else fCnt = Abs(fDV); + fDU = fDU/fCnt; + fDV = fDV/fCnt; + while (fCnt>0.0f) { + PutPixelUBYTE_FIRE((PIX) fLastU, (PIX) fLastV, 255); + fLastU += fDU; + fLastV += fDV; + fCnt -= 1; + } + // store last point + fLastU = fU; + fLastV = fV; + } + fl.slCnt = 2; + } +} + + +///////////////// Fire Lightning Ball +#define FIREBALL_LIGHTNINGS 2 + +struct FireLightningBall{ + FLOAT fpixU; + FLOAT fpixV; + FLOAT fRadiusU; + FLOAT fRadiusV; +}; + +void InitializeFireLightningBall(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + FireLightningBall &flb = + ((FireLightningBall&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + flb.fpixU = (FLOAT) pixU0; + flb.fpixV = (FLOAT) pixV0; + if (pixU0==pixU1 && pixV0==pixV1) { + flb.fRadiusU = 20; + flb.fRadiusV = 20; + } else { + flb.fRadiusU = pixU1-pixU0; + flb.fRadiusV = pixV1-pixV0; + } +} + +void AnimateFireLightningBall(CTextureEffectSource *ptes) +{ + FLOAT fU, fV, fLastU, fLastV, fvU, fvV, fvNormalU, fvNormalV; + FLOAT fDU, fDV, fCnt, fDistance; + FLOAT fDestU, fDestV, fAngle; + SLONG slRND; + ULONG ulDist; + + FireLightningBall &flb = + ((FireLightningBall&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + for (int iBalls=0; iBalls starting point + fLastU = flb.fpixU; + fLastV = flb.fpixV; + // destination point + fAngle = (FLOAT) RNDW/10000; + fDestU = flb.fpixU + flb.fRadiusU*cos(fAngle); + fDestV = flb.fpixV + flb.fRadiusV*sin(fAngle); + fDistance = sqrt((fDestU-fLastU)*(fDestU-fLastU)+ + (fDestV-fLastV)*(fDestV-fLastV)); + // vector + fvU = (fDestU-fLastU)/fDistance; + fvV = (fDestV-fLastV)/fDistance; + // normal vector + fvNormalU = -fvV; + fvNormalV = fvU; + ulDist = 0; + while ((FLOAT)ulDist=fDistance) { + // move point on line + fU = fDestU; + fV = fDestV; + } else { + // move point on line + fU = flb.fpixU + fvU*(FLOAT)ulDist; + fV = flb.fpixV + fvV*(FLOAT)ulDist; + // move point offset on normal line + slRND = (SLONG) (RNDW%11)-5; + fU += fvNormalU*(FLOAT)slRND; + fV += fvNormalV*(FLOAT)slRND; + } + // draw line + fDU = fU-fLastU; + fDV = fV-fLastV; + // counter + if (Abs(fDU)>Abs(fDV)) fCnt = Abs(fDU); + else fCnt = Abs(fDV); + fDU = fDU/fCnt; + fDV = fDV/fCnt; + while (fCnt>0.0f) { + PutPixelUBYTE_FIRE((PIX) fLastU, (PIX) fLastV, 255); + fLastU += fDU; + fLastV += fDV; + fCnt -= 1; + } + // store last point + fLastU = fU; + fLastV = fV; + } + } +} + + +///////////////// Fire Smoke +#define SMOKE_POINTS 50 + +struct FireSmoke{ + FLOAT fpixU; + FLOAT fpixV; +}; + +struct FireSmokePoint{ + FLOAT fpixU; + FLOAT fpixV; + FLOAT fSpeedV; +}; + +void InitializeFireSmoke(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1) +{ + FireSmoke &fs = + ((FireSmoke&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + fs.fpixU = (FLOAT) pixU0; + fs.fpixV = (FLOAT) pixV0; + if (pixU0==pixU1 && pixV0==pixV1) { + } else { + } + // initialize smoke points + ptes->tes_atepPixels.New(SMOKE_POINTS*2); + for (INDEX iIndex=0; iIndextes_atepPixels[iIndex]); + fsp.fpixU = FLOAT (pixU0 + (iIndex-(SMOKE_POINTS))/8); + fsp.fpixV = FLOAT (pixV0); + fsp.fSpeedV = 0.0f; + } +} + +void AnimateFireSmoke(CTextureEffectSource *ptes) +{ + int iHeat; + FLOAT fRatio = 32.0f / (FLOAT)_pixBufferHeight; + UBYTE pixU, pixV; + + FireSmoke &fs = + ((FireSmoke&) ptes->tes_tespEffectSourceProperties.tesp_achDummy); + // animate smoke points + for (INDEX iIndex=0; iIndextes_atepPixels[iIndex]); + pixU = RNDW%3 - 1; + pixV = RNDW%3 - 1; + if (fsp.fSpeedV<0.1f) { + PutPixelUBYTE_FIRE((PIX) fsp.fpixU, (PIX) fsp.fpixV, RNDW%128); + } else { + iHeat = int(fsp.fpixV*fRatio+1); + PutPixel25UBYTE_FIRE((PIX) fsp.fpixU+pixU, (PIX) fsp.fpixV+pixV, RNDW%iHeat); + } + // start moving up + if (fsp.fSpeedV<0.1f && (RNDW&255)==0) { + fsp.fSpeedV = 1.0f; + } + // move up + fsp.fpixV -= fsp.fSpeedV; + // at the end of texture go on bottom + if (fsp.fpixV<=(FLOAT)_pixBufferHeight) { + fsp.fpixV = fs.fpixV; + fsp.fSpeedV = 0.0f; + } + } +} + + + +///////////////// Water + + +void InitializeWater(void) +{ + Randomize( (ULONG)(_pTimer->GetHighPrecisionTimer().GetMilliseconds())); +} + + +/******************************* + Water Animation +********************************/ +static void AnimateWater( SLONG slDensity) +{ + _sfStats.StartTimer(CStatForm::STI_EFFECTRENDER); + +/////////////////////////////////// move water + + SWORD *pNew = (SWORD*)_ptdEffect->td_pubBuffer1; + SWORD *pOld = (SWORD*)_ptdEffect->td_pubBuffer2; + + PIX pixV, pixU; + PIX pixOffset, iNew; + SLONG slLineAbove, slLineBelow, slLineLeft, slLineRight; + + // inner rectangle (without 1 pixel top and bottom line) + pixOffset = _pixBufferWidth + 1; + for( pixV=_pixBufferHeight-2; pixV>0; pixV--) { + for( pixU=_pixBufferWidth; pixU>0; pixU--) { + iNew = (( (SLONG)pOld[pixOffset - _pixBufferWidth] + + (SLONG)pOld[pixOffset + _pixBufferWidth] + + (SLONG)pOld[pixOffset - 1] + + (SLONG)pOld[pixOffset + 1] + ) >> 1) + - (SLONG)pNew[pixOffset]; + pNew[pixOffset] = iNew - (iNew >> slDensity); + pixOffset++; + } + } + + // upper horizontal border (without corners) + slLineAbove = ((_pixBufferHeight-1)*_pixBufferWidth) + 1; + slLineBelow = _pixBufferWidth + 1; + slLineLeft = 0; + slLineRight = 2; + pixOffset = 1; + for( pixU=_pixBufferWidth-2; pixU>0; pixU--) { + iNew = (( (SLONG)pOld[slLineAbove] + + (SLONG)pOld[slLineBelow] + + (SLONG)pOld[slLineLeft] + + (SLONG)pOld[slLineRight] + ) >> 1) + - (SLONG)pNew[pixOffset]; + pNew[pixOffset] = iNew - (iNew >> slDensity); + slLineAbove++; + slLineBelow++; + slLineLeft++; + slLineRight++; + pixOffset++; + } + // lower horizontal border (without corners) + slLineAbove = ((_pixBufferHeight-2)*_pixBufferWidth) + 1; + slLineBelow = 1; + slLineLeft = (_pixBufferHeight-1)*_pixBufferWidth; + slLineRight = ((_pixBufferHeight-1)*_pixBufferWidth) + 2; + pixOffset = ((_pixBufferHeight-1)*_pixBufferWidth) + 1; + for( pixU=_pixBufferWidth-2; pixU>0; pixU--) { + iNew = (( (SLONG)pOld[slLineAbove] + + (SLONG)pOld[slLineBelow] + + (SLONG)pOld[slLineLeft] + + (SLONG)pOld[slLineRight] + ) >> 1) + - (SLONG)pNew[pixOffset]; + pNew[pixOffset] = iNew - (iNew >> slDensity); + slLineAbove++; + slLineBelow++; + slLineLeft++; + slLineRight++; + pixOffset++; + } + // corner ( 0, 0) + iNew = (( (SLONG)pOld[_pixBufferWidth] + + (SLONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] + + (SLONG)pOld[1] + + (SLONG)pOld[_pixBufferWidth-1] + ) >> 1) + - (SLONG)pNew[0]; + pNew[0] = iNew - (iNew >> slDensity); + // corner ( 0, _pixBufferWidth) + iNew = (( (SLONG)pOld[(2*_pixBufferWidth) - 1] + + (SLONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] + + (SLONG)pOld[0] + + (SLONG)pOld[_pixBufferWidth-2] + ) >> 1) + - (SLONG)pNew[_pixBufferWidth-1]; + pNew[_pixBufferWidth-1] = iNew - (iNew >> slDensity); + // corner ( _pixBufferHeight, 0) + iNew = (( (SLONG)pOld[0] + + (SLONG)pOld[(_pixBufferHeight-2)*_pixBufferWidth] + + (SLONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) + 1] + + (SLONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] + ) >> 1) + - (SLONG)pNew[(_pixBufferHeight-1)*_pixBufferWidth]; + pNew[(_pixBufferHeight-1)*_pixBufferWidth] = iNew - (iNew >> slDensity); + // corner ( _pixBufferHeight, _pixBufferWidth) + iNew = (( (SLONG)pOld[_pixBufferWidth-1] + + (SLONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) - 1] + + (SLONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] + + (SLONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 2] + ) >> 1) + - (SLONG)pNew[(_pixBufferHeight*_pixBufferWidth) - 1]; + pNew[(_pixBufferHeight*_pixBufferWidth) - 1] = iNew - (iNew >> slDensity); + + // swap buffers + Swap( _ptdEffect->td_pubBuffer1, _ptdEffect->td_pubBuffer2); + + _sfStats.StopTimer(CStatForm::STI_EFFECTRENDER); +} + + + +//////////////////////////// displace texture + + +#define PIXEL(u,v) pulTextureBase[ ((u)&(SLONG&)mmBaseWidthMask) + ((v)&(SLONG&)mmBaseHeightMask) *pixBaseWidth] + + +#pragma warning(disable: 4731) +static void RenderWater(void) +{ + _sfStats.StartTimer(CStatForm::STI_EFFECTRENDER); + + // get textures' parameters + ULONG *pulTexture = _ptdEffect->td_pulFrames; + PIX pixBaseWidth = _ptdBase->GetPixWidth(); + PIX pixBaseHeight = _ptdBase->GetPixHeight(); + ULONG *pulTextureBase = _ptdBase->td_pulFrames + + GetMipmapOffset( _iWantedMipLevel, pixBaseWidth, pixBaseHeight); + pixBaseWidth >>= _iWantedMipLevel; + pixBaseHeight >>= _iWantedMipLevel; + mmBaseWidthMask = pixBaseWidth -1; + mmBaseHeightMask = pixBaseHeight-1; + + ASSERT( _ptdEffect->td_pulFrames!=NULL && _ptdBase->td_pulFrames!=NULL); + SWORD *pswHeightMap = (SWORD*)_ptdEffect->td_pubBuffer1; // height map pointer + + // copy top 2 lines from height map to bottom (so no mask offset will be needed) + memcpy( (void*)(pswHeightMap+(_pixBufferHeight*_pixBufferWidth)), (void*)pswHeightMap, + _pixBufferWidth*sizeof(SWORD)*2); + + // execute corresponding displace routine + if( _pixBufferWidth >= _pixTexWidth) + { // SUB-SAMPLING + SLONG slHeightMapStep, slHeightRowStep; + +#if ASMOPT == 1 + + __asm { + push ebx + bsf ecx,D [_pixTexWidth] + dec ecx + mov eax,D [_pixBufferWidth] + sar eax,cl + mov D [slHeightMapStep],eax + + bsf edx,eax + add edx,DISTORSION+2-1 + mov D [mmShift],edx + + sub eax,2 + imul eax,D [_pixBufferWidth] + mov D [slHeightRowStep],eax + + mov eax,D [pixBaseWidth] + mov edx,D [pixBaseHeight] + shl edx,16 + or eax,edx + sub eax,0x00010001 + mov D [mmBaseMasks],eax + + mov eax,D [pixBaseWidth] + shl eax,16 + or eax,1 + mov D [mmBaseWidth],eax + + mov ebx,D [pswHeightMap] + mov esi,D [pulTextureBase] + mov edi,D [pulTexture] + pxor mm6,mm6 // MM5 = 0 | 0 || pixV | pixU + mov eax,D [_pixBufferWidth] + mov edx,D [_pixTexHeight] +rowLoop: + push edx + mov ecx,D [_pixTexWidth] +pixLoop: + movd mm1,D [ebx] + movd mm3,D [ebx+ eax*2] + movq mm2,mm1 + psubw mm3,mm1 + pslld mm1,16 + psubw mm2,mm1 + pand mm2,Q [mm00M0] + por mm2,mm3 + psraw mm2,Q [mmShift] + + paddw mm2,mm6 + pand mm2,Q [mmBaseMasks] + pmaddwd mm2,Q [mmBaseWidth] + movd edx,mm2 + mov edx,D [esi+ edx*4] + mov D [edi],edx + // advance to next texture pixel + add ebx,D [slHeightMapStep] + add edi,4 + paddd mm6,Q [mm0001] + dec ecx + jnz pixLoop + // advance to next texture row + pop edx + add ebx,D [slHeightRowStep] + paddd mm6,Q [mm0010] + dec edx + jnz rowLoop + emms + pop ebx + } + +#else + + PIX pixPos, pixDU, pixDV; + slHeightMapStep = _pixBufferWidth/pixBaseWidth + slHeightRowStep = (slHeightMapStep-1)*_pixBufferWidth; + mmShift = DISTORSION+ FastLog2(slHeightMapStep) +2; + for( PIX pixV=0; pixV<_pixTexHeight; pixV++) + { // row loop + for( PIX pixU=0; pixU<_pixTexWidth; pixU++) + { // texel loop + pixPos = pswHeightMap[0]; + pixDU = (pswHeightMap[1] - pixPos) >>(SLONG&)mmShift; + pixDV = (pswHeightMap[_pixBufferWidth] - pixPos) >>(SLONG&)mmShift; + pixDU = (pixU +pixDU) & (SLONG&)mmBaseWidthMask; + pixDV = (pixV +pixDV) & (SLONG&)mmBaseHeightMask; + *pulTexture++ = pulTextureBase[pixDV*pixBaseWidth + pixDU]; + // advance to next texel in height map + pswHeightMap += slHeightMapStep; + } + pswHeightMap += slHeightRowStep; + } + +#endif + + } + else if( _pixBufferWidth*2 == _pixTexWidth) + { // BILINEAR SUPER-SAMPLING 2 + +#if ASMOPT == 1 + + __asm { + push ebx + bsf eax,D [pixBaseWidth] + mov edx,32 + sub edx,eax + mov D [mmBaseWidthShift],edx + + movq mm0,Q [mmBaseHeightMask] + psllq mm0,32 + por mm0,Q [mmBaseWidthMask] + movq Q [mmBaseMasks],mm0 + + pxor mm6,mm6 // MM6 = pixV|pixU + mov ebx,D [pswHeightMap] + mov esi,D [pulTextureBase] + mov edi,D [pulTexture] + mov edx,D [_pixBufferHeight] +rowLoop2: + push edx + mov edx,D [_pixTexWidth] + mov ecx,D [_pixBufferWidth] +pixLoop2: + mov eax,D [_pixBufferWidth] + + movd mm1,D [ebx+ 2] + movd mm0,D [ebx+ eax*2] + psllq mm0,32 + por mm1,mm0 + movd mm0,D [ebx] + punpckldq mm0,mm0 + psubd mm1,mm0 + movq mm0,mm6 + pslld mm0,DISTORSION+1+1 + paddd mm1,mm0 // MM1 = slV_00 | slU_00 + + movd mm2,D [ebx+ 4] + movd mm0,D [ebx+ eax*2 +2] + psllq mm0,32 + por mm2,mm0 + movd mm0,D [ebx+ 2] + punpckldq mm0,mm0 + psubd mm2,mm0 + movq mm0,mm6 + paddd mm0,Q [mm1LO] + pslld mm0,DISTORSION+1+1 + paddd mm2,mm0 // MM2 = slV_01 | slU_01 + + movd mm3,D [ebx+ eax*2 +2] + movd mm0,D [ebx+ eax*4] + psllq mm0,32 + por mm3,mm0 + movd mm0,D [ebx+ eax*2] + punpckldq mm0,mm0 + psubd mm3,mm0 + movq mm0,mm6 + paddd mm0,Q [mm1HI] + pslld mm0,DISTORSION+1+1 + paddd mm3,mm0 // MM3 = slV_10 | slU_10 + + movd mm4,D [ebx+ eax*2 +4] + movd mm0,D [ebx+ eax*4 +2] + psllq mm0,32 + por mm4,mm0 + movd mm0,D [ebx+ eax*2 +2] + punpckldq mm0,mm0 + psubd mm4,mm0 + movq mm0,mm6 + paddd mm0,Q [mm1HILO] + pslld mm0,DISTORSION+1+1 + paddd mm4,mm0 // MM4 = slV_11 | slU_11 + + movq mm0,mm1 + psrad mm0,DISTORSION+1+0 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi],eax + + movq mm0,mm1 + paddd mm0,mm2 + psrad mm0,DISTORSION+1+1 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ 4],eax + + movq mm0,mm1 + paddd mm0,mm3 + psrad mm0,DISTORSION+1+1 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*4],eax + + paddd mm1,mm2 + paddd mm1,mm3 + paddd mm1,mm4 + psrad mm1,DISTORSION+1+2 + pand mm1,Q [mmBaseMasks] + movq mm7,mm1 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm1,mm7 + movd eax,mm1 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*4 +4],eax + + // advance to next texture pixels + paddd mm6,Q [mm1LO] + add edi,8 + add ebx,2 + dec ecx + jnz pixLoop2 + // advance to next texture row + lea edi,[edi+ edx*4] + pop edx + paddd mm6,Q [mm1HI] + dec edx + jnz rowLoop2 + emms + pop ebx + } + +#else + + SLONG slU_00, slU_01, slU_10, slU_11; + SLONG slV_00, slV_01, slV_10, slV_11; + for( PIX pixV=0; pixV<_pixBufferHeight; pixV++) + { // row loop + for( PIX pixU=0; pixU<_pixBufferWidth; pixU++) + { // texel loop + slU_00 = pswHeightMap[_pixBufferWidth*0+1] - pswHeightMap[_pixBufferWidth*0+0] + ((pixU+0)<<(DISTORSION+1+1)); + slV_00 = pswHeightMap[_pixBufferWidth*1+0] - pswHeightMap[_pixBufferWidth*0+0] + ((pixV+0)<<(DISTORSION+1+1)); + slU_01 = pswHeightMap[_pixBufferWidth*0+2] - pswHeightMap[_pixBufferWidth*0+1] + ((pixU+1)<<(DISTORSION+1+1)); + slV_01 = pswHeightMap[_pixBufferWidth*1+1] - pswHeightMap[_pixBufferWidth*0+1] + ((pixV+0)<<(DISTORSION+1+1)); + slU_10 = pswHeightMap[_pixBufferWidth*1+1] - pswHeightMap[_pixBufferWidth*1+0] + ((pixU+0)<<(DISTORSION+1+1)); + slV_10 = pswHeightMap[_pixBufferWidth*2+0] - pswHeightMap[_pixBufferWidth*1+0] + ((pixV+1)<<(DISTORSION+1+1)); + slU_11 = pswHeightMap[_pixBufferWidth*1+2] - pswHeightMap[_pixBufferWidth*1+1] + ((pixU+1)<<(DISTORSION+1+1)); + slV_11 = pswHeightMap[_pixBufferWidth*2+1] - pswHeightMap[_pixBufferWidth*1+1] + ((pixV+1)<<(DISTORSION+1+1)); + + pulTexture[_pixTexWidth*0+0] = PIXEL( (slU_00 ) >>(DISTORSION+1 ), (slV_00 ) >>(DISTORSION+1 ) ); + pulTexture[_pixTexWidth*0+1] = PIXEL( (slU_00+slU_01 ) >>(DISTORSION+1+1), (slV_00+slV_01 ) >>(DISTORSION+1+1) ); + pulTexture[_pixTexWidth*1+0] = PIXEL( (slU_00 +slU_10 ) >>(DISTORSION+1+1), (slV_00 +slV_10 ) >>(DISTORSION+1+1) ); + pulTexture[_pixTexWidth*1+1] = PIXEL( (slU_00+slU_01+slU_10+slU_11) >>(DISTORSION+1+2), (slV_00+slV_01+slV_10+slV_11) >>(DISTORSION+1+2) ); + + // advance to next texel + pulTexture+=2; + pswHeightMap++; + } + pulTexture+=_pixTexWidth; + } + +#endif + + } + else if( _pixBufferWidth*4 == _pixTexWidth) + { // BILINEAR SUPER-SAMPLING 4 + +#if ASMOPT == 1 + + __asm { + push ebx + bsf eax,D [pixBaseWidth] + mov edx,32 + sub edx,eax + mov D [mmBaseWidthShift],edx + + movq mm0,Q [mmBaseHeightMask] + psllq mm0,32 + por mm0,Q [mmBaseWidthMask] + movq Q [mmBaseMasks],mm0 + + pxor mm6,mm6 // MM6 = pixV|pixU + mov ebx,D [pswHeightMap] + mov esi,D [pulTextureBase] + mov edi,D [pulTexture] + mov edx,D [_pixBufferHeight] +rowLoop4: + push edx + mov ecx,D [_pixBufferWidth] +pixLoop4: + mov eax,D [_pixBufferWidth] + mov edx,D [_pixTexWidth] + + movd mm1,D [ebx+ 2] + movd mm0,D [ebx+ eax*2] + psllq mm0,32 + por mm1,mm0 + movd mm0,D [ebx] + punpckldq mm0,mm0 + psubd mm1,mm0 + movq mm0,mm6 + pslld mm0,DISTORSION+1+1 + paddd mm1,mm0 // MM1 = slV_00 | slU_00 + + movd mm2,D [ebx+ 4] + movd mm0,D [ebx+ eax*2 +2] + psllq mm0,32 + por mm2,mm0 + movd mm0,D [ebx+ 2] + punpckldq mm0,mm0 + psubd mm2,mm0 + movq mm0,mm6 + paddd mm0,Q [mm1LO] + pslld mm0,DISTORSION+1+1 + paddd mm2,mm0 // MM2 = slV_01 | slU_01 + + movd mm3,D [ebx+ eax*2 +2] + movd mm0,D [ebx+ eax*4] + psllq mm0,32 + por mm3,mm0 + movd mm0,D [ebx+ eax*2] + punpckldq mm0,mm0 + psubd mm3,mm0 + movq mm0,mm6 + paddd mm0,Q [mm1HI] + pslld mm0,DISTORSION+1+1 + paddd mm3,mm0 // MM3 = slV_10 | slU_10 + + movd mm4,D [ebx+ eax*2 +4] + movd mm0,D [ebx+ eax*4 +2] + psllq mm0,32 + por mm4,mm0 + movd mm0,D [ebx+ eax*2 +2] + punpckldq mm0,mm0 + psubd mm4,mm0 + movq mm0,mm6 + paddd mm0,Q [mm1HILO] + pslld mm0,DISTORSION+1+1 + paddd mm4,mm0 // MM4 = slV_11 | slU_11 + + // texel 00 + movq mm0,mm1 + psrad mm0,DISTORSION + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi],eax + // texel 01 + movq mm0,mm1 + paddd mm0,mm1 + paddd mm0,mm1 + paddd mm0,mm2 + psrad mm0,DISTORSION+2 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi +4],eax + // texel 02 + movq mm0,mm1 + paddd mm0,mm2 + psrad mm0,DISTORSION+1 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi +8],eax + // texel 03 + movq mm0,mm1 + paddd mm0,mm2 + paddd mm0,mm2 + paddd mm0,mm2 + psrad mm0,DISTORSION+2 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi +12],eax + + // texel 10 + movq mm0,mm1 + paddd mm0,mm1 + paddd mm0,mm1 + paddd mm0,mm3 + psrad mm0,DISTORSION+2 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*4],eax + // texel 11 + movq mm0,mm1 + pslld mm0,3 + paddd mm0,mm1 + paddd mm0,mm2 + paddd mm0,mm2 + paddd mm0,mm2 + paddd mm0,mm3 + paddd mm0,mm3 + paddd mm0,mm3 + paddd mm0,mm4 + psrad mm0,DISTORSION+4 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*4 +4],eax + // texel 12 + movq mm0,mm1 + paddd mm0,mm0 + paddd mm0,mm1 + paddd mm0,mm2 + paddd mm0,mm2 + paddd mm0,mm2 + paddd mm0,mm3 + paddd mm0,mm4 + psrad mm0,DISTORSION+3 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*4 +8],eax + // texel 13 + movq mm0,mm2 + pslld mm0,3 + paddd mm0,mm2 + paddd mm0,mm1 + paddd mm0,mm1 + paddd mm0,mm1 + paddd mm0,mm3 + paddd mm0,mm4 + paddd mm0,mm4 + paddd mm0,mm4 + psrad mm0,DISTORSION+4 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*4 +12],eax + + // texel 20 + movq mm0,mm1 + paddd mm0,mm3 + psrad mm0,DISTORSION+1 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*8],eax + // texel 21 + movq mm0,mm1 + paddd mm0,mm1 + paddd mm0,mm1 + paddd mm0,mm2 + paddd mm0,mm3 + paddd mm0,mm3 + paddd mm0,mm3 + paddd mm0,mm4 + psrad mm0,DISTORSION+3 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*8 +4],eax + // texel 22 + movq mm0,mm1 + paddd mm0,mm2 + paddd mm0,mm3 + paddd mm0,mm4 + psrad mm0,DISTORSION+2 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*8 +8],eax + // texel 23 + movq mm0,mm1 + paddd mm0,mm2 + paddd mm0,mm2 + paddd mm0,mm2 + paddd mm0,mm3 + paddd mm0,mm4 + paddd mm0,mm4 + paddd mm0,mm4 + psrad mm0,DISTORSION+3 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*8 +12],eax + + imul edx,3 // _pixTexWidth*=3 + // texel 30 + movq mm0,mm1 + paddd mm0,mm3 + paddd mm0,mm3 + paddd mm0,mm3 + psrad mm0,DISTORSION+2 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*4],eax + // texel 31 + movq mm0,mm3 + pslld mm0,3 + paddd mm0,mm3 + paddd mm0,mm1 + paddd mm0,mm1 + paddd mm0,mm1 + paddd mm0,mm2 + paddd mm0,mm4 + paddd mm0,mm4 + paddd mm0,mm4 + psrad mm0,DISTORSION+4 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*4 +4],eax + // texel 32 + movq mm0,mm4 + paddd mm0,mm0 + paddd mm0,mm4 + paddd mm0,mm3 + paddd mm0,mm3 + paddd mm0,mm3 + paddd mm0,mm2 + paddd mm0,mm1 + psrad mm0,DISTORSION+3 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*4 +8],eax + // texel 33 + movq mm0,mm4 + pslld mm0,3 + paddd mm0,mm4 + paddd mm0,mm1 + paddd mm0,mm2 + paddd mm0,mm2 + paddd mm0,mm2 + paddd mm0,mm3 + paddd mm0,mm3 + paddd mm0,mm3 + psrad mm0,DISTORSION+4 + pand mm0,Q [mmBaseMasks] + movq mm7,mm0 + psrlq mm7,Q [mmBaseWidthShift] + paddd mm0,mm7 + movd eax,mm0 + mov eax,D [esi+ eax*4] + mov D [edi+ edx*4 +12],eax + + // advance to next texture pixels + paddd mm6,Q [mm1LO] + add edi,16 + add ebx,2 + dec ecx + jnz pixLoop4 + // advance to next texture row + lea edi,[edi+ edx*4] // +=[_pixTexWidth]*3 + pop edx + paddd mm6,Q [mm1HI] + dec edx + jnz rowLoop4 + emms + pop ebx + } + +#else + + SLONG slU_00, slU_01, slU_10, slU_11; + SLONG slV_00, slV_01, slV_10, slV_11; + mmBaseWidthShift = FastLog2( pixBaseWidth); // faster multiplying with shift + for( PIX pixV=0; pixV<_pixBufferHeight; pixV++) + { // row loop + for( PIX pixU=0; pixU<_pixBufferWidth; pixU++) + { // texel loop + slU_00 = pswHeightMap[_pixBufferWidth*0+1] - pswHeightMap[_pixBufferWidth*0+0] + ((pixU+0)<<(DISTORSION+2)); + slV_00 = pswHeightMap[_pixBufferWidth*1+0] - pswHeightMap[_pixBufferWidth*0+0] + ((pixV+0)<<(DISTORSION+2)); + slU_01 = pswHeightMap[_pixBufferWidth*0+2] - pswHeightMap[_pixBufferWidth*0+1] + ((pixU+1)<<(DISTORSION+2)); + slV_01 = pswHeightMap[_pixBufferWidth*1+1] - pswHeightMap[_pixBufferWidth*0+1] + ((pixV+0)<<(DISTORSION+2)); + slU_10 = pswHeightMap[_pixBufferWidth*1+1] - pswHeightMap[_pixBufferWidth*1+0] + ((pixU+0)<<(DISTORSION+2)); + slV_10 = pswHeightMap[_pixBufferWidth*2+0] - pswHeightMap[_pixBufferWidth*1+0] + ((pixV+1)<<(DISTORSION+2)); + slU_11 = pswHeightMap[_pixBufferWidth*1+2] - pswHeightMap[_pixBufferWidth*1+1] + ((pixU+1)<<(DISTORSION+2)); + slV_11 = pswHeightMap[_pixBufferWidth*2+1] - pswHeightMap[_pixBufferWidth*1+1] + ((pixV+1)<<(DISTORSION+2)); + + pulTexture[_pixTexWidth*0+0] = PIXEL( (slU_00 ) >>(DISTORSION ), (slV_00 ) >>(DISTORSION ) ); + pulTexture[_pixTexWidth*0+1] = PIXEL( (slU_00* 3+slU_01* 1 ) >>(DISTORSION+2), (slV_00* 3+slV_01* 1 ) >>(DISTORSION+2) ); + pulTexture[_pixTexWidth*0+2] = PIXEL( (slU_00 +slU_01 ) >>(DISTORSION+1), (slV_00 +slV_01 ) >>(DISTORSION+1) ); + pulTexture[_pixTexWidth*0+3] = PIXEL( (slU_00* 1+slU_01* 3 ) >>(DISTORSION+2), (slV_00* 1+slV_01* 3 ) >>(DISTORSION+2) ); + + pulTexture[_pixTexWidth*1+0] = PIXEL( (slU_00* 3 +slU_10* 1 ) >>(DISTORSION+2), (slV_00* 3 +slV_10 ) >>(DISTORSION+2) ); + pulTexture[_pixTexWidth*1+1] = PIXEL( (slU_00* 9+slU_01* 3+slU_10* 3+slU_11* 1) >>(DISTORSION+4), (slV_00* 9+slV_01* 3+slV_10* 3+slV_11* 1) >>(DISTORSION+4) ); + pulTexture[_pixTexWidth*1+2] = PIXEL( (slU_00* 3+slU_01* 3+slU_10* 1+slU_11* 1) >>(DISTORSION+3), (slV_00* 3+slV_01* 3+slV_10* 1+slV_11* 1) >>(DISTORSION+3) ); + pulTexture[_pixTexWidth*1+3] = PIXEL( (slU_00* 3+slU_01* 9+slU_10* 1+slU_11* 3) >>(DISTORSION+4), (slV_00* 3+slV_01* 9+slV_10* 1+slV_11* 3) >>(DISTORSION+4) ); + + pulTexture[_pixTexWidth*2+0] = PIXEL( (slU_00 +slU_10 ) >>(DISTORSION+1), (slV_00 +slV_10 ) >>(DISTORSION+1) ); + pulTexture[_pixTexWidth*2+1] = PIXEL( (slU_00* 3+slU_01* 1+slU_10* 3+slU_11* 1) >>(DISTORSION+3), (slV_00* 3+slV_01* 1+slV_10* 3+slV_11* 1) >>(DISTORSION+3) ); + pulTexture[_pixTexWidth*2+2] = PIXEL( (slU_00 +slU_01 +slU_10 +slU_11 ) >>(DISTORSION+2), (slV_00 +slV_01 +slV_10 +slV_11 ) >>(DISTORSION+2) ); + pulTexture[_pixTexWidth*2+3] = PIXEL( (slU_00* 1+slU_01* 3+slU_10* 1+slU_11* 3) >>(DISTORSION+3), (slV_00* 1+slV_01* 3+slV_10* 1+slV_11* 3) >>(DISTORSION+3) ); + + pulTexture[_pixTexWidth*3+0] = PIXEL( (slU_00* 1 +slU_10* 3 ) >>(DISTORSION+2), (slV_00* 1 +slV_10* 3 ) >>(DISTORSION+2) ); + pulTexture[_pixTexWidth*3+1] = PIXEL( (slU_00* 3+slU_01* 1+slU_10* 9+slU_11* 3) >>(DISTORSION+4), (slV_00* 3+slV_01* 1+slV_10* 9+slV_11* 3) >>(DISTORSION+4) ); + pulTexture[_pixTexWidth*3+2] = PIXEL( (slU_00* 1+slU_01* 1+slU_10* 3+slU_11* 3) >>(DISTORSION+3), (slV_00* 1+slV_01* 1+slV_10* 3+slV_11* 3) >>(DISTORSION+3) ); + pulTexture[_pixTexWidth*3+3] = PIXEL( (slU_00* 1+slU_01* 3+slU_10* 3+slU_11* 9) >>(DISTORSION+4), (slV_00* 1+slV_01* 3+slV_10* 3+slV_11* 9) >>(DISTORSION+4) ); + + // advance to next texel + pulTexture+=4; + pHeightMap++; + } + pulTexture+=_pixTexWidth*3; + } + +#endif + + } + else + { // DO NOTHING + ASSERTALWAYS( "Effect textures larger than 256 pixels aren't supported"); + } + + _sfStats.StopTimer(CStatForm::STI_EFFECTRENDER); +} +#pragma warning(default: 4731) + + + +///////////////// Fire + + +void InitializeFire(void) +{ + Randomize( (ULONG)(_pTimer->GetHighPrecisionTimer().GetMilliseconds())); +} + +enum PlasmaType { + ptNormal = 0, + ptUp, + ptUpTile, + ptDown, + ptDownTile +}; + +/******************************* + Plasma Animation +********************************/ +static void AnimatePlasma( SLONG slDensity, PlasmaType eType) +{ + _sfStats.StartTimer(CStatForm::STI_EFFECTRENDER); + +/////////////////////////////////// move plasma + + UBYTE *pNew = (UBYTE*)_ptdEffect->td_pubBuffer1; + UBYTE *pOld = (UBYTE*)_ptdEffect->td_pubBuffer2; + + PIX pixV, pixU; + PIX pixOffset; + SLONG slLineAbove, slLineBelow, slLineLeft, slLineRight; + ULONG ulNew; + + // -------------------------- + // Normal plasma + // -------------------------- + if (eType == ptNormal) { + // inner rectangle (without 1 pixel border) + pixOffset = _pixBufferWidth; + for( pixV=1; pixV<_pixBufferHeight-1; pixV++) { + for( pixU=0; pixU<_pixBufferWidth; pixU++) { + ulNew = ((((ULONG)pOld[pixOffset - _pixBufferWidth] + + (ULONG)pOld[pixOffset + _pixBufferWidth] + + (ULONG)pOld[pixOffset - 1] + + (ULONG)pOld[pixOffset + 1] + )>>2) + + (ULONG)pOld[pixOffset] + )>>1; + pNew[pixOffset] = ulNew - (ulNew >> slDensity); + pixOffset++; + } + } + // upper horizontal border (without corners) + slLineAbove = ((_pixBufferHeight-1)*_pixBufferWidth) + 1; + slLineBelow = _pixBufferWidth + 1; + slLineLeft = 0; + slLineRight = 2; + pixOffset = 1; + for( pixU=_pixBufferWidth-2; pixU>0; pixU--) { + ulNew = ((((ULONG)pOld[slLineAbove] + + (ULONG)pOld[slLineBelow] + + (ULONG)pOld[slLineLeft] + + (ULONG)pOld[slLineRight] + )>>2) + + (ULONG)pOld[pixOffset] + )>>1; + pNew[pixOffset] = ulNew - (ulNew >> slDensity); + slLineAbove++; + slLineBelow++; + slLineLeft++; + slLineRight++; + pixOffset++; + } + // lower horizontal border (without corners) + slLineAbove = ((_pixBufferHeight-2)*_pixBufferWidth) + 1; + slLineBelow = 1; + slLineLeft = (_pixBufferHeight-1)*_pixBufferWidth; + slLineRight = ((_pixBufferHeight-1)*_pixBufferWidth) + 2; + pixOffset = ((_pixBufferHeight-1)*_pixBufferWidth) + 1; + for( pixU=_pixBufferWidth-2; pixU>0; pixU--) { + ulNew = ((((ULONG)pOld[slLineAbove] + + (ULONG)pOld[slLineBelow] + + (ULONG)pOld[slLineLeft] + + (ULONG)pOld[slLineRight] + )>>2) + + (ULONG)pOld[pixOffset] + )>>1; + pNew[pixOffset] = ulNew - (ulNew >> slDensity); + slLineAbove++; + slLineBelow++; + slLineLeft++; + slLineRight++; + pixOffset++; + } + // corner ( 0, 0) + ulNew = ((((ULONG)pOld[_pixBufferWidth] + + (ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] + + (ULONG)pOld[1] + + (ULONG)pOld[_pixBufferWidth-1] + )>>2) + + (ULONG)pOld[0] + )>>1; + pNew[0] = ulNew - (ulNew >> slDensity); + // corner ( 0, _pixBufferWidth) + ulNew = ((((ULONG)pOld[(2*_pixBufferWidth) - 1] + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] + + (ULONG)pOld[0] + + (ULONG)pOld[_pixBufferWidth-2] + )>>2) + + (ULONG)pOld[_pixBufferWidth-1] + )>>1; + pNew[_pixBufferWidth-1] = ulNew - (ulNew >> slDensity); + // corner ( _pixBufferHeight, 0) + ulNew = ((((ULONG)pOld[0] + + (ULONG)pOld[(_pixBufferHeight-2)*_pixBufferWidth] + + (ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) + 1] + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] + )>>2) + + (ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] + )>>1; + pNew[(_pixBufferHeight-1)*_pixBufferWidth] = ulNew - (ulNew >> slDensity); + // corner ( _pixBufferHeight, _pixBufferWidth) + ulNew = ((((ULONG)pOld[_pixBufferWidth-1] + + (ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) - 1] + + (ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 2] + )>>2) + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] + )>>1; + pNew[(_pixBufferHeight*_pixBufferWidth) - 1] = ulNew - (ulNew >> slDensity); + + + // -------------------------- + // Plasma going up + // -------------------------- + } else if (eType==ptUp || eType==ptUpTile) { + // inner rectangle (without 1 pixel border) + pixOffset = _pixBufferWidth; + for( pixV=1; pixV<_pixBufferHeight-1; pixV++) { + for( pixU=0; pixU<_pixBufferWidth; pixU++) { + ulNew = ((((ULONG)pOld[pixOffset - _pixBufferWidth] + + (ULONG)pOld[pixOffset + _pixBufferWidth] + + (ULONG)pOld[pixOffset - 1] + + (ULONG)pOld[pixOffset + 1] + )>>2) + + (ULONG)pOld[pixOffset] + )>>1; + pNew[pixOffset-_pixBufferWidth] = ulNew - (ulNew >> slDensity); + pixOffset++; + } + } + // tile + if (eType==ptUpTile) { + // upper horizontal border (without corners) + slLineAbove = ((_pixBufferHeight-1)*_pixBufferWidth) + 1; + slLineBelow = _pixBufferWidth + 1; + slLineLeft = 0; + slLineRight = 2; + pixOffset = 1; + for( pixU=_pixBufferWidth-2; pixU>0; pixU--) { + ulNew = ((((ULONG)pOld[slLineAbove] + + (ULONG)pOld[slLineBelow] + + (ULONG)pOld[slLineLeft] + + (ULONG)pOld[slLineRight] + )>>2) + + (ULONG)pOld[pixOffset] + )>>1; + pNew[slLineAbove] = ulNew - (ulNew >> slDensity); + slLineAbove++; + slLineBelow++; + slLineLeft++; + slLineRight++; + pixOffset++; + } + // lower horizontal border (without corners) + slLineAbove = ((_pixBufferHeight-2)*_pixBufferWidth) + 1; + slLineBelow = 1; + slLineLeft = (_pixBufferHeight-1)*_pixBufferWidth; + slLineRight = ((_pixBufferHeight-1)*_pixBufferWidth) + 2; + pixOffset = ((_pixBufferHeight-1)*_pixBufferWidth) + 1; + for( pixU=_pixBufferWidth-2; pixU>0; pixU--) { + ulNew = ((((ULONG)pOld[slLineAbove] + + (ULONG)pOld[slLineBelow] + + (ULONG)pOld[slLineLeft] + + (ULONG)pOld[slLineRight] + )>>2) + + (ULONG)pOld[pixOffset] + )>>1; + pNew[slLineAbove] = ulNew - (ulNew >> slDensity); + slLineAbove++; + slLineBelow++; + slLineLeft++; + slLineRight++; + pixOffset++; + } + // corner ( 0, 0) + ulNew = ((((ULONG)pOld[_pixBufferWidth] + + (ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] + + (ULONG)pOld[1] + + (ULONG)pOld[_pixBufferWidth-1] + )>>2) + + (ULONG)pOld[0] + )>>1; + pNew[(_pixBufferHeight-1)*_pixBufferWidth] = ulNew - (ulNew >> slDensity); + // corner ( 0, _pixBufferWidth) + ulNew = ((((ULONG)pOld[(2*_pixBufferWidth) - 1] + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] + + (ULONG)pOld[0] + + (ULONG)pOld[_pixBufferWidth-2] + )>>2) + + (ULONG)pOld[_pixBufferWidth-1] + )>>1; + pNew[(_pixBufferHeight*_pixBufferWidth) - 1] = ulNew - (ulNew >> slDensity); + // corner ( _pixBufferHeight, 0) + ulNew = ((((ULONG)pOld[0] + + (ULONG)pOld[(_pixBufferHeight-2)*_pixBufferWidth] + + (ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) + 1] + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] + )>>2) + + (ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] + )>>1; + pNew[(_pixBufferHeight-2)*_pixBufferWidth] = ulNew - (ulNew >> slDensity); + // corner ( _pixBufferHeight, _pixBufferWidth) + ulNew = ((((ULONG)pOld[_pixBufferWidth-1] + + (ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) - 1] + + (ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 2] + )>>2) + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] + )>>1; + pNew[((_pixBufferHeight-1)*_pixBufferWidth) - 1] = ulNew - (ulNew >> slDensity); + } + + + // -------------------------- + // Plasma going down + // -------------------------- + } else if (eType==ptDown || eType==ptDownTile) { + // inner rectangle (without 1 pixel border) + pixOffset = _pixBufferWidth; + for( pixV=1; pixV<_pixBufferHeight-1; pixV++) { + for( pixU=0; pixU<_pixBufferWidth; pixU++) { + ulNew = ((((ULONG)pOld[pixOffset - _pixBufferWidth] + + (ULONG)pOld[pixOffset + _pixBufferWidth] + + (ULONG)pOld[pixOffset - 1] + + (ULONG)pOld[pixOffset + 1] + )>>2) + + (ULONG)pOld[pixOffset] + )>>1; + pNew[pixOffset+_pixBufferWidth] = ulNew - (ulNew >> slDensity); + pixOffset++; + } + } + // tile + if (eType==ptDownTile) { + // upper horizontal border (without corners) + slLineAbove = ((_pixBufferHeight-1)*_pixBufferWidth) + 1; + slLineBelow = _pixBufferWidth + 1; + slLineLeft = 0; + slLineRight = 2; + pixOffset = 1; + for( pixU=_pixBufferWidth-2; pixU>0; pixU--) { + ulNew = ((((ULONG)pOld[slLineAbove] + + (ULONG)pOld[slLineBelow] + + (ULONG)pOld[slLineLeft] + + (ULONG)pOld[slLineRight] + )>>2) + + (ULONG)pOld[pixOffset] + )>>1; + pNew[slLineBelow] = ulNew - (ulNew >> slDensity); + slLineAbove++; + slLineBelow++; + slLineLeft++; + slLineRight++; + pixOffset++; + } + // lower horizontal border (without corners) + slLineAbove = ((_pixBufferHeight-2)*_pixBufferWidth) + 1; + slLineBelow = 1; + slLineLeft = (_pixBufferHeight-1)*_pixBufferWidth; + slLineRight = ((_pixBufferHeight-1)*_pixBufferWidth) + 2; + pixOffset = ((_pixBufferHeight-1)*_pixBufferWidth) + 1; + for( pixU=_pixBufferWidth-2; pixU>0; pixU--) { + ulNew = ((((ULONG)pOld[slLineAbove] + + (ULONG)pOld[slLineBelow] + + (ULONG)pOld[slLineLeft] + + (ULONG)pOld[slLineRight] + )>>2) + + (ULONG)pOld[pixOffset] + )>>1; + pNew[slLineBelow] = ulNew - (ulNew >> slDensity); + slLineAbove++; + slLineBelow++; + slLineLeft++; + slLineRight++; + pixOffset++; + } + // corner ( 0, 0) + ulNew = ((((ULONG)pOld[_pixBufferWidth] + + (ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] + + (ULONG)pOld[1] + + (ULONG)pOld[_pixBufferWidth-1] + )>>2) + + (ULONG)pOld[0] + )>>1; + pNew[_pixBufferWidth] = ulNew - (ulNew >> slDensity); + // corner ( 0, _pixBufferWidth) + ulNew = ((((ULONG)pOld[(2*_pixBufferWidth) - 1] + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] + + (ULONG)pOld[0] + + (ULONG)pOld[_pixBufferWidth-2] + )>>2) + + (ULONG)pOld[_pixBufferWidth-1] + )>>1; + pNew[(2*_pixBufferWidth) - 1] = ulNew - (ulNew >> slDensity); + // corner ( _pixBufferHeight, 0) + ulNew = ((((ULONG)pOld[0] + + (ULONG)pOld[(_pixBufferHeight-2)*_pixBufferWidth] + + (ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) + 1] + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] + )>>2) + + (ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] + )>>1; + pNew[0] = ulNew - (ulNew >> slDensity); + // corner ( _pixBufferHeight, _pixBufferWidth) + ulNew = ((((ULONG)pOld[_pixBufferWidth-1] + + (ULONG)pOld[((_pixBufferHeight-1)*_pixBufferWidth) - 1] + + (ULONG)pOld[(_pixBufferHeight-1)*_pixBufferWidth] + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 2] + )>>2) + + (ULONG)pOld[(_pixBufferHeight*_pixBufferWidth) - 1] + )>>1; + pNew[_pixBufferWidth-1] = ulNew - (ulNew >> slDensity); + } + } + + // swap buffers + Swap( _ptdEffect->td_pubBuffer1, _ptdEffect->td_pubBuffer2); + + _sfStats.StopTimer(CStatForm::STI_EFFECTRENDER); +} + + +/******************************* + Fire Animation +********************************/ +static void AnimateFire( SLONG slDensity) +{ +// _sfStats.StartTimer(CStatForm::STI_EFFECTRENDER); + +/////////////////////////////////// move fire + + // use only one buffer (otherwise it's not working) + UBYTE *pubNew = (UBYTE*)_ptdEffect->td_pubBuffer2; + SLONG slBufferMask = _pixBufferWidth*_pixBufferHeight -1; + SLONG slColumnModulo = _pixBufferWidth*(_pixBufferHeight-2) -1; + +#if ASMOPT == 1 + + __asm { + push ebx + mov edi,D [ulRNDSeed] ;// EDI = randomizer + mov esi,D [pubNew] + xor ebx,ebx + +colLoopFM: + mov ecx,D [_pixBufferHeight] + sub ecx,2 + +rowLoopFM: + mov edx,D [_pixBufferWidth] + add edx,esi + movzx eax,B [ebx+ edx] + add edx,D [_pixBufferWidth] + movzx edx,B [ebx+ edx] + add eax,edx + shr eax,1 + cmp eax,D [slDensity] + jg doCalc + mov B [esi+ebx],0 + jmp pixDone +doCalc: + mov edx,edi + sar edx,16 + and edx,D [slDensity] + sub eax,edx + movsx edx,B [asbMod3Sub1Table +edx] + add edx,ebx + and edx,D [slBufferMask] + mov B [esi+edx],al + imul edi,262147 + +pixDone: + // advance to next row + add ebx,D [_pixBufferWidth] + dec ecx + jnz rowLoopFM + + // advance to next column + sub ebx,D [slColumnModulo] + cmp ebx,D [_pixBufferWidth] + jl colLoopFM + + // all done + mov D [ulRNDSeed],edi + pop ebx + } + +#else + + // inner rectangle (without 1 pixel border) + for( PIX pixU=0; pixU<_pixBufferWidth; pixU++) + { + SLONG slOffset = pixU; + for( PIX pixV=1; pixV<_pixBufferHeight-1; pixV++) + { + ULONG ulNew = ((ULONG)pubNew[_pixBufferWidth+slOffset] + (ULONG)pubNew[_pixBufferWidth*2+slOffset]) >>1; + if( ulNew>slDensity) { + ULONG ulNewDensity = RNDW&slDensity; + ulNew -= ulNewDensity; + SLONG slDifusion = (SLONG)asbMod3Sub1Table[ulNewDensity]; // (SLONG)(ulNewDensity%3-1); + SLONG slPos = (slDifusion+slOffset) & slBufferMask; + pubNew[slPos] = ulNew; + } else { + pubNew[slOffset] = 0; + } + slOffset += _pixBufferWidth; + } + } + +#endif + +// _sfStats.StopTimer(CStatForm::STI_EFFECTRENDER); +} + +//////////////////////////// displace texture + +static void RenderPlasmaFire(void) +{ +// _sfStats.StartTimer(CStatForm::STI_EFFECTRENDER); + + // get and adjust textures' parameters + PIX pixBaseWidth = _ptdBase->GetPixWidth(); + ULONG *pulTextureBase = _ptdBase->td_pulFrames; + ULONG *pulTexture = _ptdEffect->td_pulFrames; + + ASSERT( _ptdEffect->td_pulFrames!=NULL && _ptdBase->td_pulFrames!=NULL && pixBaseWidth<=256); + UBYTE *pubHeat = (UBYTE*)_ptdEffect->td_pubBuffer2; // heat map pointer + SLONG slHeatMapStep = _pixBufferWidth/_pixTexWidth; + SLONG slHeatRowStep = (slHeatMapStep-1)*_pixBufferWidth; + SLONG slBaseMipShift = 8 - FastLog2(pixBaseWidth); + +#if ASMOPT == 1 + + __asm { + push ebx + mov ebx,D [pubHeat] + mov esi,D [pulTextureBase] + mov edi,D [pulTexture] + mov ecx,D [_pixTexHeight] +rowLoopF: + push ecx + mov edx,D [_pixTexWidth] + mov ecx,D [slBaseMipShift] +pixLoopF: + movzx eax,B [ebx] + shr eax,cl + mov eax,D [esi+ eax*4] + mov D [edi],eax + // advance to next pixel + add ebx,D [slHeatMapStep] + add edi,4 + dec edx + jnz pixLoopF + // advance to next row + pop ecx + add ebx,D [slHeatRowStep] + dec ecx + jnz rowLoopF + pop ebx + } + +#else + + INDEX iPalette; + for( INDEX pixV=0; pixV<_pixTexHeight; pixV++) { + // for every pixel in horizontal line + for( INDEX pixU=0; pixU<_pixTexWidth; pixU++) { + iPalette = (*pubHeat)>>slBaseMipShift; + *pulTexture++ = pulTextureBase[iPalette]; + pubHeat += slHeatMapStep; + } + pubHeat += slHeatRowStep; + } + +#endif + +// _sfStats.StopTimer(CStatForm::STI_EFFECTRENDER); +} + + + +///////////////////////////////////////////////////////////////////// +// EFFECT TABLES +///////////////////////////////////////////////////////////////////// + +struct TextureEffectSourceType atestWater[] = { + { + "Raindrops", + InitializeRaindropsStandard, + AnimateRaindropsStandard + }, + { + "RaindropsBig", + InitializeRaindropsBig, + AnimateRaindropsBig + }, + { + "RaindropsSmall", + InitializeRaindropsSmall, + AnimateRaindropsSmall + }, + { + "Random Surfer", + InitializeRandomSurfer, + AnimateRandomSurfer + }, + { + "Oscilator", + InitializeOscilator, + AnimateOscilator + }, + { + "Vertical Line", + InitializeVertLine, + AnimateVertLine + }, + { + "Horizontal Line", + InitializeHortLine, + AnimateHortLine + }, +}; + +struct TextureEffectSourceType atestFire[] = { + { + "Point", + InitializeFirePoint, + AnimateFirePoint + }, + { + "Random Point", + InitializeRandomFirePoint, + AnimateRandomFirePoint + }, + { + "Shake Point", + InitializeFireShakePoint, + AnimateFireShakePoint + }, + { + "Fire Place", + InitializeFirePlace, + AnimateFirePlace + }, + { + "Roler", + InitializeFireRoler, + AnimateFireRoler + }, + { + "Fall", + InitializeFireFall, + AnimateFireFall + }, + { + "Fountain", + InitializeFireFountain, + AnimateFireFountain + }, + { + "Side Fountain", + InitializeFireSideFountain, + AnimateFireSideFountain + }, + { + "Lightning", + InitializeFireLightning, + AnimateFireLightning + }, + { + "Lightning Ball", + InitializeFireLightningBall, + AnimateFireLightningBall + }, + { + "Smoke", + InitializeFireSmoke, + AnimateFireSmoke + }, +}; + + +void AWaterFast(void) { AnimateWater(2); }; +void AWaterMedium(void) { AnimateWater(3); }; +void AWaterSlow(void) { AnimateWater(5); }; + +void APlasma(void) { AnimatePlasma(4, ptNormal); }; +void APlasmaUp(void) { AnimatePlasma(4, ptUp); }; +void APlasmaUpTile(void) { AnimatePlasma(4, ptUpTile); }; +void APlasmaDown(void) { AnimatePlasma(5, ptDown); }; +void APlasmaDownTile(void) { AnimatePlasma(5, ptDownTile); }; +void APlasmaUpSlow(void) { AnimatePlasma(6, ptUp); }; + +void AFire(void) { AnimateFire(15); }; + + +struct TextureEffectGlobalType _ategtTextureEffectGlobalPresets[] = { + { + "Water Fast", + InitializeWater, + AWaterFast, + sizeof(atestWater)/sizeof(atestWater[0]), + atestWater + }, + { + "Water Medium", + InitializeWater, + AWaterMedium, + sizeof(atestWater)/sizeof(atestWater[0]), + atestWater + }, + { + "Water Slow", + InitializeWater, + AWaterSlow, + sizeof(atestWater)/sizeof(atestWater[0]), + atestWater + }, + { + "", + InitializeWater, + AWaterSlow, + sizeof(atestWater)/sizeof(atestWater[0]), + atestWater + }, + { + "Plasma Tile", + InitializeFire, + APlasma, + sizeof(atestFire)/sizeof(atestFire[0]), + atestFire + }, + { + "Plasma Up", + InitializeFire, + APlasmaUp, + sizeof(atestFire)/sizeof(atestFire[0]), + atestFire + }, + { + "Plasma Up Tile", + InitializeFire, + APlasmaUpTile, + sizeof(atestFire)/sizeof(atestFire[0]), + atestFire + }, + { + "Plasma Down", + InitializeFire, + APlasmaDown, + sizeof(atestFire)/sizeof(atestFire[0]), + atestFire + }, + { + "Plasma Down Tile", + InitializeFire, + APlasmaDownTile, + sizeof(atestFire)/sizeof(atestFire[0]), + atestFire + }, + { + "Plasma Up Slow", + InitializeFire, + APlasmaUpSlow, + sizeof(atestFire)/sizeof(atestFire[0]), + atestFire + }, + { + "Fire", + InitializeFire, + AFire, + sizeof(atestFire)/sizeof(atestFire[0]), + atestFire + }, +}; + +INDEX _ctTextureEffectGlobalPresets = sizeof(_ategtTextureEffectGlobalPresets) + / sizeof(_ategtTextureEffectGlobalPresets[0]); + + +// get effect type (TRUE if water type effect, FALSE if plasma or fire effect) +BOOL CTextureEffectGlobal::IsWater(void) +{ + return( _ategtTextureEffectGlobalPresets[teg_ulEffectType].tegt_Initialize == InitializeWater); +} + +// default constructor +CTextureEffectGlobal::CTextureEffectGlobal(CTextureData *ptdTexture, ULONG ulGlobalEffect) +{ + // remember global effect's texture data for cross linking + teg_ptdTexture = ptdTexture; + teg_ulEffectType = ulGlobalEffect; + // init for animating + _ategtTextureEffectGlobalPresets[teg_ulEffectType].tegt_Initialize(); + // make sure the texture will be updated next time when used + teg_updTexture.Invalidate(); +} + +// add new effect source. +void CTextureEffectGlobal::AddEffectSource( ULONG ulEffectSourceType, PIX pixU0, PIX pixV0, + PIX pixU1, PIX pixV1) +{ + CTextureEffectSource* ptesNew = teg_atesEffectSources.New(1); + ptesNew->Initialize(this, ulEffectSourceType, pixU0, pixV0, pixU1, pixV1); +} + +// animate effect texture +void CTextureEffectGlobal::Animate(void) +{ + // if not set yet (funny word construction:) + if( !bTableSet) { + // set table for fast modulo 3 minus 1 + for( INDEX i=0; i<256; i++) asbMod3Sub1Table[i]=(SBYTE)((i%3)-1); + bTableSet = TRUE; + } + + // setup some internal vars + _ptdEffect = teg_ptdTexture; + _pixBufferWidth = _ptdEffect->td_pixBufferWidth; + _pixBufferHeight = _ptdEffect->td_pixBufferHeight; + _ulBufferMask = _pixBufferHeight*_pixBufferWidth -1; + + // remember buffer pointers + _pubDrawBuffer=(UBYTE*)_ptdEffect->td_pubBuffer2; + _pswDrawBuffer=(SWORD*)_ptdEffect->td_pubBuffer2; + + // for each effect source + FOREACHINDYNAMICARRAY( teg_atesEffectSources, CTextureEffectSource, itEffectSource) { + // let it animate itself + itEffectSource->Animate(); + } + // use animation function for this global effect type + _ategtTextureEffectGlobalPresets[teg_ulEffectType].tegt_Animate(); + // remember that it was calculated + teg_updTexture.MarkUpdated(); +} + +#pragma warning(disable: 4731) +// render effect texture +void CTextureEffectGlobal::Render( INDEX iWantedMipLevel, PIX pixTexWidth, PIX pixTexHeight) +{ + // setup some internal vars + _ptdEffect = teg_ptdTexture; + _ptdBase = teg_ptdTexture->td_ptdBaseTexture; + _pixBufferWidth = _ptdEffect->td_pixBufferWidth; + _pixBufferHeight = _ptdEffect->td_pixBufferHeight; + + if( IsWater()) { + // use water rendering routine + _pixTexWidth = pixTexWidth; + _pixTexHeight = pixTexHeight; + _iWantedMipLevel = iWantedMipLevel; + RenderWater(); + } else { + // use plasma & fire rendering routine + _pixTexWidth = _ptdEffect->GetWidth() >>iWantedMipLevel; + _pixTexHeight = _ptdEffect->GetHeight() >>iWantedMipLevel; + RenderPlasmaFire(); + } +} +#pragma warning(default: 4731) + +// returns number of second it took to render effect texture +DOUBLE CTextureEffectGlobal::GetRenderingTime(void) +{ + return( _sfStats.sf_astTimers[CStatForm::STI_EFFECTRENDER].st_tvElapsed.GetSeconds()); +} + + diff --git a/Sources/Engine/Graphics/TextureEffects.h b/Sources/Engine/Graphics/TextureEffects.h new file mode 100644 index 0000000..5674c7d --- /dev/null +++ b/Sources/Engine/Graphics/TextureEffects.h @@ -0,0 +1,89 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TEXTUREEFFECTS_H +#define SE_INCL_TEXTUREEFFECTS_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include + +struct TextureEffectPixel { + char tepp_achDummy[8]; +}; +struct TextureEffectSourceProperties { + char tesp_achDummy[64]; +}; +class CTextureEffectSource { +public: + class CTextureEffectGlobal *tes_ptegGlobalEffect; // global effect of this effect source + inline void Clear(void) {}; + ULONG tes_ulEffectSourceType; // effect source type + struct TextureEffectSourceProperties tes_tespEffectSourceProperties; + CStaticArray tes_atepPixels; + + // Initialize the texture effect source. + void Initialize( + class CTextureEffectGlobal *ptegGlobalEffect,ULONG ulEffectSourceType, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1); + // Animate the texture effect source. + void Animate(void); +}; + +class CTextureEffectGlobal { +public: + CTextureData *teg_ptdTexture; // texture of this global effect + ULONG teg_ulEffectType; + CUpdateable teg_updTexture; // when the texture was last updated + CDynamicArray teg_atesEffectSources; + + // Constructor. + CTextureEffectGlobal(CTextureData *ptdTexture, ULONG ulGlobalEffect); + + // Add a new effect source. + ENGINE_API void AddEffectSource( ULONG ulEffectSourceType, PIX pixU0, PIX pixV0, + PIX pixU1, PIX pixV1); + // animate effect texture + void Animate(void); + // render effect texture in required mip level + void Render( INDEX iWantedMipLevel, PIX pixTexWidth, PIX pixTexHeight); + + // get effect type (true if water type effect, false if plasma or fire effect) + BOOL IsWater(void); + // returns number of second it took to render effect texture + ENGINE_API DOUBLE GetRenderingTime(void); +}; + +struct TextureEffectSourceType { + char *test_strName; // name used for browsing + void (*test_Initialize)(CTextureEffectSource *ptes, + PIX pixU0, PIX pixV0, PIX pixU1, PIX pixV1); // function for initalization of a new effect source + void (*test_Animate)(CTextureEffectSource *ptes); // function for animation of one effect source +}; + +struct TextureEffectGlobalType { + char *tegt_strName; // name used for browsing + void (*tegt_Initialize)(void); + void (*tegt_Animate)(void); + + // all types of effect sources + INDEX tet_ctEffectSourceTypes; + struct TextureEffectSourceType *tet_atestEffectSourceTypes; +}; + +struct TextureEffectGlobalProperties_Water { + UBYTE tegpw_ubPhong; // 0 for no phong +}; + +struct TextureEffectGlobalProperties_Fire { + UBYTE tegpw_ubRising; // 0 for no rising +}; + +ENGINE_API extern INDEX _ctTextureEffectGlobalPresets; +ENGINE_API extern struct TextureEffectGlobalType _ategtTextureEffectGlobalPresets[]; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/TextureRender.cpp b/Sources/Engine/Graphics/TextureRender.cpp new file mode 100644 index 0000000..852686b --- /dev/null +++ b/Sources/Engine/Graphics/TextureRender.cpp @@ -0,0 +1,21 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + diff --git a/Sources/Engine/Graphics/Vertex.h b/Sources/Engine/Graphics/Vertex.h new file mode 100644 index 0000000..c460195 --- /dev/null +++ b/Sources/Engine/Graphics/Vertex.h @@ -0,0 +1,116 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_VERTEX_H +#define SE_INCL_VERTEX_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + + +struct GFXVertex3 +{ + FLOAT x,y,z; +}; + + +struct GFXNormal3 +{ + FLOAT nx,ny,nz; +}; + + +struct GFXTexCoord +{ + union { + struct { FLOAT u,v; }; + struct { FLOAT s,t; }; + }; +}; + + +struct GFXTexCoord4 +{ + FLOAT s,t,r,q; +}; + + +struct GFXColor +{ + union { + struct { UBYTE r,g,b,a; }; + struct { ULONG abgr; }; // reverse order - use ByteSwap()! + }; + + GFXColor() {}; + + GFXColor( COLOR col) { + _asm mov ecx,dword ptr [this] + _asm mov eax,dword ptr [col] + _asm bswap eax + _asm mov dword ptr [ecx],eax + } + + __forceinline void Set( COLOR col) { + _asm mov ecx,dword ptr [this] + _asm mov eax,dword ptr [col] + _asm bswap eax + _asm mov dword ptr [ecx],eax + } + + void MultiplyRGBA( const GFXColor &col1, const GFXColor &col2) { + r = (ULONG(col1.r)*col2.r)>>8; + g = (ULONG(col1.g)*col2.g)>>8; + b = (ULONG(col1.b)*col2.b)>>8; + a = (ULONG(col1.a)*col2.a)>>8; + } + + void MultiplyRGB( const GFXColor &col1, const GFXColor &col2) { + r = (ULONG(col1.r)*col2.r)>>8; + g = (ULONG(col1.g)*col2.g)>>8; + b = (ULONG(col1.b)*col2.b)>>8; + } + + void MultiplyRGBCopyA1( const GFXColor &col1, const GFXColor &col2) { + r = (ULONG(col1.r)*col2.r)>>8; + g = (ULONG(col1.g)*col2.g)>>8; + b = (ULONG(col1.b)*col2.b)>>8; + a = col1.a; + } + + void AttenuateRGB( ULONG ulA) { + r = (ULONG(r)*ulA)>>8; + g = (ULONG(g)*ulA)>>8; + b = (ULONG(b)*ulA)>>8; + } + + void AttenuateA( ULONG ulA) { + a = (ULONG(a)*ulA)>>8; + } +}; + + +#define GFXVertex GFXVertex4 +struct GFXVertex4 +{ + GFXVertex4() + { + } + FLOAT x,y,z; + union { + struct { struct GFXColor col; }; + struct { SLONG shade; }; + }; +}; + + +#define GFXNormal GFXNormal4 +struct GFXNormal4 +{ + FLOAT nx,ny,nz; + ULONG ul; +}; + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/ViewPort.cpp b/Sources/Engine/Graphics/ViewPort.cpp new file mode 100644 index 0000000..e83a011 --- /dev/null +++ b/Sources/Engine/Graphics/ViewPort.cpp @@ -0,0 +1,260 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include + +extern INDEX ogl_bExclusive; + + +// helper for D3D surface +#ifdef SE1_D3D +static void CreateSwapChain_D3D( CViewPort *pvp, PIX pixSizeI, PIX pixSizeJ) +{ + HRESULT hr; + D3DPRESENT_PARAMETERS d3dPresentParams; + memset( &d3dPresentParams, 0, sizeof(d3dPresentParams)); + d3dPresentParams.Windowed = TRUE; + d3dPresentParams.BackBufferWidth = pixSizeI; + d3dPresentParams.BackBufferHeight = pixSizeJ; + d3dPresentParams.BackBufferFormat = _pGfx->gl_d3dColorFormat; + d3dPresentParams.BackBufferCount = 1; + d3dPresentParams.MultiSampleType = D3DMULTISAMPLE_NONE; // !!!! TODO + d3dPresentParams.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; + d3dPresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD; + d3dPresentParams.hDeviceWindow = pvp->vp_hWnd; + ASSERT( pvp->vp_pSwapChain==NULL && pvp->vp_pSurfDepth==NULL); + hr = _pGfx->gl_pd3dDevice->CreateAdditionalSwapChain( &d3dPresentParams, &pvp->vp_pSwapChain); + D3D_CHECKERROR(hr); + hr = _pGfx->gl_pd3dDevice->CreateDepthStencilSurface( pixSizeI, pixSizeJ, _pGfx->gl_d3dDepthFormat, + D3DMULTISAMPLE_NONE, &pvp->vp_pSurfDepth); + D3D_CHECKERROR(hr); + ASSERT( pvp->vp_pSwapChain!=NULL); + ASSERT( pvp->vp_pSurfDepth!=NULL); +} + +static void SetAsRenderTarget_D3D( CViewPort *pvp) +{ + HRESULT hr; + LPDIRECT3DSURFACE8 pColorSurface; + hr = pvp->vp_pSwapChain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pColorSurface); + D3D_CHECKERROR(hr); + hr = _pGfx->gl_pd3dDevice->SetRenderTarget( pColorSurface, pvp->vp_pSurfDepth); + D3D_CHECKERROR(hr); + D3DRELEASE( pColorSurface, TRUE); +} +#endif // SE1_D3D + +// helper for OGL + +CTempDC::CTempDC(HWND hWnd) +{ + ASSERT(hWnd!=NULL); + hwnd = hWnd; + hdc = GetDC(hwnd); + ASSERT(hdc!=NULL); +} + +CTempDC::~CTempDC(void) +{ + ReleaseDC(hwnd, hdc); +} + + +/* + * ViewPort functions + */ + +CViewPort::CViewPort( PIX pixWidth, PIX pixHeight, HWND hWnd) : + vp_Raster( pixWidth, pixHeight, 0) +{ + vp_hWnd = NULL; + vp_hWndParent = hWnd; +#ifdef SE1_D3D + vp_pSwapChain = NULL; + vp_pSurfDepth = NULL; +#endif // SE1_D3D + vp_ctDisplayChanges = 0; + OpenCanvas(); + vp_Raster.ra_pvpViewPort = this; +} + + +CViewPort::~CViewPort(void) +{ + CloseCanvas(TRUE); + // reset current viewport if needed + if( _pGfx->gl_pvpActive==this) _pGfx->gl_pvpActive = NULL; +} + + +#define CViewPortCLASS "ViewPort Window" +static BOOL _bClassRegistered = FALSE; + +LRESULT CALLBACK CViewPortCLASS_WindowProc( + HWND hWnd, // handle to window + UINT Msg, // message identifier + WPARAM wParam, // first message parameter + LPARAM lParam // second message parameter +) +{ + // forget erase bacground messages + if (Msg==WM_ERASEBKGND) return TRUE; + + // if any mouse message + if ((Msg>=WM_MOUSEFIRST&&Msg<=WM_MOUSELAST)) { + // send it to parent + HWND hWndParent = GetParent(hWnd); + ASSERT(hWndParent!=NULL); + return CallWindowProc( (WNDPROC)GetWindowLong(hWndParent, GWL_WNDPROC), + hWndParent, Msg, wParam, lParam); + } + + return DefWindowProc(hWnd, Msg, wParam, lParam); +} + + +// open overlaid window for rendering context +void CViewPort::OpenCanvas(void) +{ + // do nothing if not feasable + if( vp_hWnd!=NULL || vp_hWndParent==NULL) return; + + // register class + if( !_bClassRegistered) { + WNDCLASSA wc; + wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; + wc.lpfnWndProc = CViewPortCLASS_WindowProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = NULL; + wc.hIcon = NULL; + wc.hCursor = LoadCursor( NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = CViewPortCLASS; + RegisterClassA(&wc); + _bClassRegistered = TRUE; + } + + // determine window and desktopsize + RECT rectWindow; + GetClientRect( vp_hWndParent, &rectWindow); + const PIX pixWinSizeI = rectWindow.right - rectWindow.left; + const PIX pixWinSizeJ = rectWindow.bottom - rectWindow.top; + CDisplayMode dm; + _pGfx->GetCurrentDisplayMode(dm); + ASSERT( (dm.dm_pixSizeI==0 && dm.dm_pixSizeJ==0) || (dm.dm_pixSizeI!=0 && dm.dm_pixSizeJ!=0)); + const BOOL bFullScreen = (dm.dm_pixSizeI==pixWinSizeI && dm.dm_pixSizeJ==pixWinSizeJ); + + // set fullscreen attribs if window size is equal to screen size + DWORD dwExStyle = NONE; + DWORD dwStyle = WS_CHILD|WS_CLIPCHILDREN|WS_CLIPSIBLINGS; + if( bFullScreen && ogl_bExclusive) { + dwExStyle = WS_EX_TOPMOST; + dwStyle = WS_POPUP; + } + + // set child window + vp_hWnd = ::CreateWindowExA( + dwExStyle, + CViewPortCLASS, + "", // title + dwStyle, + 0,0, + 0,0, // window size + vp_hWndParent, + NULL, + (HINSTANCE)GetWindowLong(vp_hWndParent, GWL_HINSTANCE), + NULL); + ASSERT( vp_hWnd!=NULL); +#ifdef SE1_D3D + // prepare new swap chain for D3D + if( _pGfx->gl_eCurrentAPI==GAT_D3D && !bFullScreen) CreateSwapChain_D3D( this, pixWinSizeI, pixWinSizeJ); +#endif // SE1_D3D + + // resize raster + Resize(); + ShowWindow( vp_hWnd, SW_SHOW); +#ifdef SE1_D3D + // set as rendering target + if( _pGfx->gl_eCurrentAPI==GAT_D3D && vp_pSwapChain!=NULL) SetAsRenderTarget_D3D(this); +#endif // SE1_D3D +} + + +// close overlaid window +void CViewPort::CloseCanvas( BOOL bRelease/*=FALSE*/) +{ + // release D3D swap chain if allocated +#ifdef SE1_D3D + if( _pGfx->gl_eCurrentAPI==GAT_D3D && bRelease) { + if( vp_pSwapChain!=NULL) D3DRELEASE( vp_pSwapChain, TRUE); + if( vp_pSurfDepth!=NULL) D3DRELEASE( vp_pSurfDepth, TRUE); + } +#endif // SE1_D3D + // destroy window + if( vp_hWnd!=NULL && IsWindow(vp_hWnd)) { + BOOL bRes = DestroyWindow(vp_hWnd); + ASSERT(bRes); + } + // mark + vp_hWnd = NULL; +#ifdef SE1_D3D + vp_pSwapChain = NULL; + vp_pSurfDepth = NULL; +#endif // SE1_D3D +} + + +// Change size of this viewport, it's raster and all it's drawports +void CViewPort::Resize(void) +{ + PIX pixNewWidth, pixNewHeight; + RECT rectWindow; + + // get the size of the window + GetClientRect( vp_hWndParent, &rectWindow); + pixNewWidth = rectWindow.right - rectWindow.left; + pixNewHeight = rectWindow.bottom - rectWindow.top; + + // resize child window + ASSERT( vp_hWnd!=NULL); + SetWindowPos( vp_hWnd, NULL, 0,0, pixNewWidth, pixNewHeight, SWP_NOZORDER|SWP_NOMOVE); + + // resize the raster + vp_Raster.Resize( pixNewWidth, pixNewHeight); + + // "resize" D3D surface (if any) +#ifdef SE1_D3D + if( _pGfx->gl_eCurrentAPI==GAT_D3D && vp_pSwapChain!=NULL) { + // release old surface + ASSERT( vp_pSurfDepth!=NULL); + D3DRELEASE( vp_pSwapChain, TRUE); + D3DRELEASE( vp_pSurfDepth, TRUE); + // create a new one and set it as current + CreateSwapChain_D3D( this, pixNewWidth, pixNewHeight); + SetAsRenderTarget_D3D(this); + } +#endif // SE1_D3D +} + + +void CViewPort::SwapBuffers(void) +{ + // skip if child window not present + if( vp_hWnd==NULL) return; + + // ask the current driver to swap buffers + _sfStats.StartTimer(CStatForm::STI_SWAPBUFFERS); + _pfGfxProfile.StartTimer( CGfxProfile::PTI_SWAPBUFFERS); + _pfGfxProfile.IncrementAveragingCounter(1); + _pGfx->SwapBuffers(this); + _pfGfxProfile.StopTimer( CGfxProfile::PTI_SWAPBUFFERS); + _sfStats.StopTimer(CStatForm::STI_SWAPBUFFERS); +} + diff --git a/Sources/Engine/Graphics/ViewPort.h b/Sources/Engine/Graphics/ViewPort.h new file mode 100644 index 0000000..51abab0 --- /dev/null +++ b/Sources/Engine/Graphics/ViewPort.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_VIEWPORT_H +#define SE_INCL_VIEWPORT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#ifdef SE1_D3D +#include +#endif // SE1_D3D + +/* + * ViewPort + */ + +/* rcg !!! FIXME: This will need to go away. */ +#ifdef PLATFORM_WIN32 +class CTempDC { +public: + HDC hdc; + HWND hwnd; + CTempDC(HWND hWnd); + ~CTempDC(void); +}; +#endif + +// base abstract class for viewport +class ENGINE_API CViewPort { +public: +// implementation + HWND vp_hWnd; // canvas (child) window + HWND vp_hWndParent; // window of the viewport + CRaster vp_Raster; // the used Raster +#ifdef SE1_D3D + LPDIRECT3DSWAPCHAIN8 vp_pSwapChain; // swap chain for D3D + LPDIRECT3DSURFACE8 vp_pSurfDepth; // z-buffer for D3D +#endif // SE1_D3D + INDEX vp_ctDisplayChanges; // number of display driver + + // open/close canvas window + void OpenCanvas(void); + void CloseCanvas(BOOL bRelease=FALSE); + +// interface + /* Constructor for given window. */ + CViewPort(PIX pixWidth, PIX pixHeight, HWND hWnd); + /* Destructor. */ + ~CViewPort(void); + + /* Display the back buffer on screen. */ + void SwapBuffers(void); + // change size of this viewport, it's raster and all it's drawports to fit it window + void Resize(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Graphics/gl_functions.h b/Sources/Engine/Graphics/gl_functions.h new file mode 100644 index 0000000..cd9b9d5 --- /dev/null +++ b/Sources/Engine/Graphics/gl_functions.h @@ -0,0 +1,996 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + + +// GLFUNCTION(dll, output, name, inputs, params, required) + + + +/* + * Miscellaneous + */ + +DLLFUNCTION( OGL, void , glClearIndex,( GLfloat c ),0,0); + +DLLFUNCTION( OGL, void , glClearColor,( GLclampf red, + GLclampf green, + GLclampf blue, + GLclampf alpha ),0,0); + +DLLFUNCTION( OGL, void , glClear,( GLbitfield mask ),0,0); + +DLLFUNCTION( OGL, void , glIndexMask,( GLuint mask ),0,0); + +DLLFUNCTION( OGL, void , glColorMask,( GLboolean red, GLboolean green, + GLboolean blue, GLboolean alpha ),0,0); + +DLLFUNCTION( OGL, void , glAlphaFunc,( GLenum func, GLclampf ref ),0,0); + +DLLFUNCTION( OGL, void , glBlendFunc,( GLenum sfactor, GLenum dfactor ),0,0); + +DLLFUNCTION( OGL, void , glLogicOp,( GLenum opcode ),0,0); + +DLLFUNCTION( OGL, void , glCullFace,( GLenum mode ),0,0); + +DLLFUNCTION( OGL, void , glFrontFace,( GLenum mode ),0,0); + +DLLFUNCTION( OGL, void , glPointSize,( GLfloat size ),0,0); + +DLLFUNCTION( OGL, void , glLineWidth,( GLfloat width ),0,0); + +DLLFUNCTION( OGL, void , glLineStipple,( GLint factor, GLushort pattern ),0,0); + +DLLFUNCTION( OGL, void , glPolygonMode,( GLenum face, GLenum mode ),0,0); + +DLLFUNCTION( OGL, void , glPolygonOffset,( GLfloat factor, GLfloat units ),0,0); + +DLLFUNCTION( OGL, void , glPolygonStipple,( const GLubyte *mask ),0,0); + +DLLFUNCTION( OGL, void , glGetPolygonStipple,( GLubyte *mask ),0,0); + +DLLFUNCTION( OGL, void , glEdgeFlag,( GLboolean flag ),0,0); + +DLLFUNCTION( OGL, void , glEdgeFlagv,( const GLboolean *flag ),0,0); + +DLLFUNCTION( OGL, void , glScissor,( GLint x, GLint y, + GLsizei width, GLsizei height),0,0); + +DLLFUNCTION( OGL, void , glClipPlane,( GLenum plane, const GLdouble *equation ),0,0); + +DLLFUNCTION( OGL, void , glGetClipPlane,( GLenum plane, GLdouble *equation ),0,0); + +DLLFUNCTION( OGL, void , glDrawBuffer,( GLenum mode ),0,0); + +DLLFUNCTION( OGL, void , glReadBuffer,( GLenum mode ),0,0); + +DLLFUNCTION( OGL, void , glEnable,( GLenum cap ),0,0); + +DLLFUNCTION( OGL, void , glDisable,( GLenum cap ),0,0); + +DLLFUNCTION( OGL, GLboolean , glIsEnabled,( GLenum cap ),0,0); + + +DLLFUNCTION( OGL, void , glEnableClientState,( GLenum cap ),0,0); /* 1.1 */ + +DLLFUNCTION( OGL, void , glDisableClientState,( GLenum cap ),0,0); /* 1.1 */ + + +DLLFUNCTION( OGL, void , glGetBooleanv,( GLenum pname, GLboolean *params ),0,0); + +DLLFUNCTION( OGL, void , glGetDoublev,( GLenum pname, GLdouble *params ),0,0); + +DLLFUNCTION( OGL, void , glGetFloatv,( GLenum pname, GLfloat *params ),0,0); + +DLLFUNCTION( OGL, void , glGetIntegerv,( GLenum pname, GLint *params ),0,0); + + +DLLFUNCTION( OGL, void , glPushAttrib,( GLbitfield mask ),0,0); + +DLLFUNCTION( OGL, void , glPopAttrib,( void ),0,0); + + +DLLFUNCTION( OGL, void , glPushClientAttrib,( GLbitfield mask ),0,0); /* 1.1 */ + +DLLFUNCTION( OGL, void , glPopClientAttrib,( void ),0,0); /* 1.1 */ + + +DLLFUNCTION( OGL, GLint , glRenderMode,( GLenum mode ),0,0); + +DLLFUNCTION( OGL, GLenum , glGetError,( void ),0,1); + +DLLFUNCTION( OGL, const GLubyte* , glGetString,( GLenum name ),0,0); + +DLLFUNCTION( OGL, void , glFinish,( void ),0,0); + +DLLFUNCTION( OGL, void , glFlush,( void ),0,0); + +DLLFUNCTION( OGL, void , glHint,( GLenum target, GLenum mode ),0,0); + + + +/* + * Depth Buffer + */ + +DLLFUNCTION( OGL, void , glClearDepth,( GLclampd depth ),0,0); + +DLLFUNCTION( OGL, void , glDepthFunc,( GLenum func ),0,0); + +DLLFUNCTION( OGL, void , glDepthMask,( GLboolean flag ),0,0); + +DLLFUNCTION( OGL, void , glDepthRange,( GLclampd near_val, GLclampd far_val ),0,0); + + +/* + * Accumulation Buffer + */ + +DLLFUNCTION( OGL, void , glClearAccum,( GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha ),0,0); + +DLLFUNCTION( OGL, void , glAccum,( GLenum op, GLfloat value ),0,0); + + + +/* + * Transformation + */ + +DLLFUNCTION( OGL, void , glMatrixMode,( GLenum mode ),0,0); + +DLLFUNCTION( OGL, void , glOrtho,( GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble near_val, GLdouble far_val ),0,0); + +DLLFUNCTION( OGL, void , glFrustum,( GLdouble left, GLdouble right, + GLdouble bottom, GLdouble top, + GLdouble near_val, GLdouble far_val ),0,0); + +DLLFUNCTION( OGL, void , glViewport,( GLint x, GLint y, + GLsizei width, GLsizei height ),0,0); + +DLLFUNCTION( OGL, void , glPushMatrix,( void ),0,0); + +DLLFUNCTION( OGL, void , glPopMatrix,( void ),0,0); + +DLLFUNCTION( OGL, void , glLoadIdentity,( void ),0,0); + +DLLFUNCTION( OGL, void , glLoadMatrixd,( const GLdouble *m ),0,0); +DLLFUNCTION( OGL, void , glLoadMatrixf,( const GLfloat *m ),0,0); + +DLLFUNCTION( OGL, void , glMultMatrixd,( const GLdouble *m ),0,0); +DLLFUNCTION( OGL, void , glMultMatrixf,( const GLfloat *m ),0,0); + +DLLFUNCTION( OGL, void , glRotated,( GLdouble angle, + GLdouble x, GLdouble y, GLdouble z ),0,0); +DLLFUNCTION( OGL, void , glRotatef,( GLfloat angle, + GLfloat x, GLfloat y, GLfloat z ),0,0); + +DLLFUNCTION( OGL, void , glScaled,( GLdouble x, GLdouble y, GLdouble z ),0,0); +DLLFUNCTION( OGL, void , glScalef,( GLfloat x, GLfloat y, GLfloat z ),0,0); + +DLLFUNCTION( OGL, void , glTranslated,( GLdouble x, GLdouble y, GLdouble z ),0,0); +DLLFUNCTION( OGL, void , glTranslatef,( GLfloat x, GLfloat y, GLfloat z ),0,0); + + + +/* + * Display Lists + */ + +DLLFUNCTION( OGL, GLboolean , glIsList,( GLuint list ),0,0); + +DLLFUNCTION( OGL, void , glDeleteLists,( GLuint list, GLsizei range ),0,0); + +DLLFUNCTION( OGL, GLuint , glGenLists,( GLsizei range ),0,0); + +DLLFUNCTION( OGL, void , glNewList,( GLuint list, GLenum mode ),0,0); + +DLLFUNCTION( OGL, void , glEndList,( void ),0,0); + +DLLFUNCTION( OGL, void , glCallList,( GLuint list ),0,0); + +DLLFUNCTION( OGL, void , glCallLists,( GLsizei n, GLenum type, + const GLvoid *lists ),0,0); + +DLLFUNCTION( OGL, void , glListBase,( GLuint base ),0,0); + + + +/* + * Drawing Functions + */ + +DLLFUNCTION( OGL, void , glBegin,( GLenum mode ),0,0); + +DLLFUNCTION( OGL, void , glEnd,( void ),0,0); + + +DLLFUNCTION( OGL, void , glVertex2d,( GLdouble x, GLdouble y ),0,0); +DLLFUNCTION( OGL, void , glVertex2f,( GLfloat x, GLfloat y ),0,0); +DLLFUNCTION( OGL, void , glVertex2i,( GLint x, GLint y ),0,0); +DLLFUNCTION( OGL, void , glVertex2s,( GLshort x, GLshort y ),0,0); + +DLLFUNCTION( OGL, void , glVertex3d,( GLdouble x, GLdouble y, GLdouble z ),0,0); +DLLFUNCTION( OGL, void , glVertex3f,( GLfloat x, GLfloat y, GLfloat z ),0,0); +DLLFUNCTION( OGL, void , glVertex3i,( GLint x, GLint y, GLint z ),0,0); +DLLFUNCTION( OGL, void , glVertex3s,( GLshort x, GLshort y, GLshort z ),0,0); + +DLLFUNCTION( OGL, void , glVertex4d,( GLdouble x, GLdouble y, GLdouble z, GLdouble w ),0,0); +DLLFUNCTION( OGL, void , glVertex4f,( GLfloat x, GLfloat y, GLfloat z, GLfloat w ),0,0); +DLLFUNCTION( OGL, void , glVertex4i,( GLint x, GLint y, GLint z, GLint w ),0,0); +DLLFUNCTION( OGL, void , glVertex4s,( GLshort x, GLshort y, GLshort z, GLshort w ),0,0); + +DLLFUNCTION( OGL, void , glVertex2dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glVertex2fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glVertex2iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glVertex2sv,( const GLshort *v ),0,0); + +DLLFUNCTION( OGL, void , glVertex3dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glVertex3fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glVertex3iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glVertex3sv,( const GLshort *v ),0,0); + +DLLFUNCTION( OGL, void , glVertex4dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glVertex4fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glVertex4iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glVertex4sv,( const GLshort *v ),0,0); + + +DLLFUNCTION( OGL, void , glNormal3b,( GLbyte nx, GLbyte ny, GLbyte nz ),0,0); +DLLFUNCTION( OGL, void , glNormal3d,( GLdouble nx, GLdouble ny, GLdouble nz ),0,0); +DLLFUNCTION( OGL, void , glNormal3f,( GLfloat nx, GLfloat ny, GLfloat nz ),0,0); +DLLFUNCTION( OGL, void , glNormal3i,( GLint nx, GLint ny, GLint nz ),0,0); +DLLFUNCTION( OGL, void , glNormal3s,( GLshort nx, GLshort ny, GLshort nz ),0,0); + +DLLFUNCTION( OGL, void , glNormal3bv,( const GLbyte *v ),0,0); +DLLFUNCTION( OGL, void , glNormal3dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glNormal3fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glNormal3iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glNormal3sv,( const GLshort *v ),0,0); + + +DLLFUNCTION( OGL, void , glIndexd,( GLdouble c ),0,0); +DLLFUNCTION( OGL, void , glIndexf,( GLfloat c ),0,0); +DLLFUNCTION( OGL, void , glIndexi,( GLint c ),0,0); +DLLFUNCTION( OGL, void , glIndexs,( GLshort c ),0,0); +DLLFUNCTION( OGL, void , glIndexub,( GLubyte c ),0,0); /* 1.1 */ + +DLLFUNCTION( OGL, void , glIndexdv,( const GLdouble *c ),0,0); +DLLFUNCTION( OGL, void , glIndexfv,( const GLfloat *c ),0,0); +DLLFUNCTION( OGL, void , glIndexiv,( const GLint *c ),0,0); +DLLFUNCTION( OGL, void , glIndexsv,( const GLshort *c ),0,0); +DLLFUNCTION( OGL, void , glIndexubv,( const GLubyte *c ),0,0); /* 1.1 */ + +DLLFUNCTION( OGL, void , glColor3b,( GLbyte red, GLbyte green, GLbyte blue ),0,0); +DLLFUNCTION( OGL, void , glColor3d,( GLdouble red, GLdouble green, GLdouble blue ),0,0); +DLLFUNCTION( OGL, void , glColor3f,( GLfloat red, GLfloat green, GLfloat blue ),0,0); +DLLFUNCTION( OGL, void , glColor3i,( GLint red, GLint green, GLint blue ),0,0); +DLLFUNCTION( OGL, void , glColor3s,( GLshort red, GLshort green, GLshort blue ),0,0); +DLLFUNCTION( OGL, void , glColor3ub,( GLubyte red, GLubyte green, GLubyte blue ),0,0); +DLLFUNCTION( OGL, void , glColor3ui,( GLuint red, GLuint green, GLuint blue ),0,0); +DLLFUNCTION( OGL, void , glColor3us,( GLushort red, GLushort green, GLushort blue ),0,0); + +DLLFUNCTION( OGL, void , glColor4b,( GLbyte red, GLbyte green, + GLbyte blue, GLbyte alpha ),0,0); +DLLFUNCTION( OGL, void , glColor4d,( GLdouble red, GLdouble green, + GLdouble blue, GLdouble alpha ),0,0); +DLLFUNCTION( OGL, void , glColor4f,( GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha ),0,0); +DLLFUNCTION( OGL, void , glColor4i,( GLint red, GLint green, + GLint blue, GLint alpha ),0,0); +DLLFUNCTION( OGL, void , glColor4s,( GLshort red, GLshort green, + GLshort blue, GLshort alpha ),0,0); +DLLFUNCTION( OGL, void , glColor4ub,( GLubyte red, GLubyte green, + GLubyte blue, GLubyte alpha ),0,0); +DLLFUNCTION( OGL, void , glColor4ui,( GLuint red, GLuint green, + GLuint blue, GLuint alpha ),0,0); +DLLFUNCTION( OGL, void , glColor4us,( GLushort red, GLushort green, + GLushort blue, GLushort alpha ),0,0); + + +DLLFUNCTION( OGL, void , glColor3bv,( const GLbyte *v ),0,0); +DLLFUNCTION( OGL, void , glColor3dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glColor3fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glColor3iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glColor3sv,( const GLshort *v ),0,0); +DLLFUNCTION( OGL, void , glColor3ubv,( const GLubyte *v ),0,0); +DLLFUNCTION( OGL, void , glColor3uiv,( const GLuint *v ),0,0); +DLLFUNCTION( OGL, void , glColor3usv,( const GLushort *v ),0,0); + +DLLFUNCTION( OGL, void , glColor4bv,( const GLbyte *v ),0,0); +DLLFUNCTION( OGL, void , glColor4dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glColor4fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glColor4iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glColor4sv,( const GLshort *v ),0,0); +DLLFUNCTION( OGL, void , glColor4ubv,( const GLubyte *v ),0,0); +DLLFUNCTION( OGL, void , glColor4uiv,( const GLuint *v ),0,0); +DLLFUNCTION( OGL, void , glColor4usv,( const GLushort *v ),0,0); + + +DLLFUNCTION( OGL, void , glTexCoord1d,( GLdouble s ),0,0); +DLLFUNCTION( OGL, void , glTexCoord1f,( GLfloat s ),0,0); +DLLFUNCTION( OGL, void , glTexCoord1i,( GLint s ),0,0); +DLLFUNCTION( OGL, void , glTexCoord1s,( GLshort s ),0,0); + +DLLFUNCTION( OGL, void , glTexCoord2d,( GLdouble s, GLdouble t ),0,0); +DLLFUNCTION( OGL, void , glTexCoord2f,( GLfloat s, GLfloat t ),0,0); +DLLFUNCTION( OGL, void , glTexCoord2i,( GLint s, GLint t ),0,0); +DLLFUNCTION( OGL, void , glTexCoord2s,( GLshort s, GLshort t ),0,0); + +DLLFUNCTION( OGL, void , glTexCoord3d,( GLdouble s, GLdouble t, GLdouble r ),0,0); +DLLFUNCTION( OGL, void , glTexCoord3f,( GLfloat s, GLfloat t, GLfloat r ),0,0); +DLLFUNCTION( OGL, void , glTexCoord3i,( GLint s, GLint t, GLint r ),0,0); +DLLFUNCTION( OGL, void , glTexCoord3s,( GLshort s, GLshort t, GLshort r ),0,0); + +DLLFUNCTION( OGL, void , glTexCoord4d,( GLdouble s, GLdouble t, GLdouble r, GLdouble q ),0,0); +DLLFUNCTION( OGL, void , glTexCoord4f,( GLfloat s, GLfloat t, GLfloat r, GLfloat q ),0,0); +DLLFUNCTION( OGL, void , glTexCoord4i,( GLint s, GLint t, GLint r, GLint q ),0,0); +DLLFUNCTION( OGL, void , glTexCoord4s,( GLshort s, GLshort t, GLshort r, GLshort q ),0,0); + +DLLFUNCTION( OGL, void , glTexCoord1dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord1fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord1iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord1sv,( const GLshort *v ),0,0); + +DLLFUNCTION( OGL, void , glTexCoord2dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord2fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord2iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord2sv,( const GLshort *v ),0,0); + +DLLFUNCTION( OGL, void , glTexCoord3dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord3fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord3iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord3sv,( const GLshort *v ),0,0); + +DLLFUNCTION( OGL, void , glTexCoord4dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord4fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord4iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glTexCoord4sv,( const GLshort *v ),0,0); + + +DLLFUNCTION( OGL, void , glRasterPos2d,( GLdouble x, GLdouble y ),0,0); +DLLFUNCTION( OGL, void , glRasterPos2f,( GLfloat x, GLfloat y ),0,0); +DLLFUNCTION( OGL, void , glRasterPos2i,( GLint x, GLint y ),0,0); +DLLFUNCTION( OGL, void , glRasterPos2s,( GLshort x, GLshort y ),0,0); + +DLLFUNCTION( OGL, void , glRasterPos3d,( GLdouble x, GLdouble y, GLdouble z ),0,0); +DLLFUNCTION( OGL, void , glRasterPos3f,( GLfloat x, GLfloat y, GLfloat z ),0,0); +DLLFUNCTION( OGL, void , glRasterPos3i,( GLint x, GLint y, GLint z ),0,0); +DLLFUNCTION( OGL, void , glRasterPos3s,( GLshort x, GLshort y, GLshort z ),0,0); + +DLLFUNCTION( OGL, void , glRasterPos4d,( GLdouble x, GLdouble y, GLdouble z, GLdouble w ),0,0); +DLLFUNCTION( OGL, void , glRasterPos4f,( GLfloat x, GLfloat y, GLfloat z, GLfloat w ),0,0); +DLLFUNCTION( OGL, void , glRasterPos4i,( GLint x, GLint y, GLint z, GLint w ),0,0); +DLLFUNCTION( OGL, void , glRasterPos4s,( GLshort x, GLshort y, GLshort z, GLshort w ),0,0); + +DLLFUNCTION( OGL, void , glRasterPos2dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glRasterPos2fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glRasterPos2iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glRasterPos2sv,( const GLshort *v ),0,0); + +DLLFUNCTION( OGL, void , glRasterPos3dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glRasterPos3fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glRasterPos3iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glRasterPos3sv,( const GLshort *v ),0,0); + +DLLFUNCTION( OGL, void , glRasterPos4dv,( const GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glRasterPos4fv,( const GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glRasterPos4iv,( const GLint *v ),0,0); +DLLFUNCTION( OGL, void , glRasterPos4sv,( const GLshort *v ),0,0); + + +DLLFUNCTION( OGL, void , glRectd,( GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2 ),0,0); +DLLFUNCTION( OGL, void , glRectf,( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ),0,0); +DLLFUNCTION( OGL, void , glRecti,( GLint x1, GLint y1, GLint x2, GLint y2 ),0,0); +DLLFUNCTION( OGL, void , glRects,( GLshort x1, GLshort y1, GLshort x2, GLshort y2 ),0,0); + + +DLLFUNCTION( OGL, void , glRectdv,( const GLdouble *v1, const GLdouble *v2 ),0,0); +DLLFUNCTION( OGL, void , glRectfv,( const GLfloat *v1, const GLfloat *v2 ),0,0); +DLLFUNCTION( OGL, void , glRectiv,( const GLint *v1, const GLint *v2 ),0,0); +DLLFUNCTION( OGL, void , glRectsv,( const GLshort *v1, const GLshort *v2 ),0,0); + + + +/* + * Vertex Arrays (1.1) + */ + +DLLFUNCTION( OGL, void , glVertexPointer,( GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr ),0,0); + +DLLFUNCTION( OGL, void , glNormalPointer,( GLenum type, GLsizei stride, + const GLvoid *ptr ),0,0); + +DLLFUNCTION( OGL, void , glColorPointer,( GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr ),0,0); + +DLLFUNCTION( OGL, void , glIndexPointer,( GLenum type, GLsizei stride, + const GLvoid *ptr ),0,0); + +DLLFUNCTION( OGL, void , glTexCoordPointer,( GLint size, GLenum type, + GLsizei stride, const GLvoid *ptr ),0,0); + +DLLFUNCTION( OGL, void , glEdgeFlagPointer,( GLsizei stride, + const GLboolean *ptr ),0,0); + +DLLFUNCTION( OGL, void , glGetPointerv,( GLenum pname, void **params ),0,0); + +DLLFUNCTION( OGL, void , glArrayElement,( GLint i ),0,0); + +DLLFUNCTION( OGL, void , glDrawArrays,( GLenum mode, GLint first, + GLsizei count ),0,0); + +DLLFUNCTION( OGL, void , glDrawElements,( GLenum mode, GLsizei count, + GLenum type, const GLvoid *indices ),0,0); + +DLLFUNCTION( OGL, void , glInterleavedArrays,( GLenum format, GLsizei stride, + const GLvoid *pointer ),0,0); + + +/* + * Lighting + */ + +DLLFUNCTION( OGL, void , glShadeModel,( GLenum mode ),0,0); + +DLLFUNCTION( OGL, void , glLightf,( GLenum light, GLenum pname, GLfloat param ),0,0); +DLLFUNCTION( OGL, void , glLighti,( GLenum light, GLenum pname, GLint param ),0,0); +DLLFUNCTION( OGL, void , glLightfv,( GLenum light, GLenum pname, + const GLfloat *params ),0,0); +DLLFUNCTION( OGL, void , glLightiv,( GLenum light, GLenum pname, + const GLint *params ),0,0); + +DLLFUNCTION( OGL, void , glGetLightfv,( GLenum light, GLenum pname, + GLfloat *params ),0,0); +DLLFUNCTION( OGL, void , glGetLightiv,( GLenum light, GLenum pname, + GLint *params ),0,0); + +DLLFUNCTION( OGL, void , glLightModelf,( GLenum pname, GLfloat param ),0,0); +DLLFUNCTION( OGL, void , glLightModeli,( GLenum pname, GLint param ),0,0); +DLLFUNCTION( OGL, void , glLightModelfv,( GLenum pname, const GLfloat *params ),0,0); +DLLFUNCTION( OGL, void , glLightModeliv,( GLenum pname, const GLint *params ),0,0); + +DLLFUNCTION( OGL, void , glMaterialf,( GLenum face, GLenum pname, GLfloat param ),0,0); +DLLFUNCTION( OGL, void , glMateriali,( GLenum face, GLenum pname, GLint param ),0,0); +DLLFUNCTION( OGL, void , glMaterialfv,( GLenum face, GLenum pname, const GLfloat *params ),0,0); +DLLFUNCTION( OGL, void , glMaterialiv,( GLenum face, GLenum pname, const GLint *params ),0,0); + +DLLFUNCTION( OGL, void , glGetMaterialfv,( GLenum face, GLenum pname, GLfloat *params ),0,0); +DLLFUNCTION( OGL, void , glGetMaterialiv,( GLenum face, GLenum pname, GLint *params ),0,0); + +DLLFUNCTION( OGL, void , glColorMaterial,( GLenum face, GLenum mode ),0,0); + + + + +/* + * Raster functions + */ + +DLLFUNCTION( OGL, void , glPixelZoom,( GLfloat xfactor, GLfloat yfactor ),0,0); + +DLLFUNCTION( OGL, void , glPixelStoref,( GLenum pname, GLfloat param ),0,0); +DLLFUNCTION( OGL, void , glPixelStorei,( GLenum pname, GLint param ),0,0); + +DLLFUNCTION( OGL, void , glPixelTransferf,( GLenum pname, GLfloat param ),0,0); +DLLFUNCTION( OGL, void , glPixelTransferi,( GLenum pname, GLint param ),0,0); + +DLLFUNCTION( OGL, void , glPixelMapfv,( GLenum map, GLint mapsize, + const GLfloat *values ),0,0); +DLLFUNCTION( OGL, void , glPixelMapuiv,( GLenum map, GLint mapsize, + const GLuint *values ),0,0); +DLLFUNCTION( OGL, void , glPixelMapusv,( GLenum map, GLint mapsize, + const GLushort *values ),0,0); + +DLLFUNCTION( OGL, void , glGetPixelMapfv,( GLenum map, GLfloat *values ),0,0); +DLLFUNCTION( OGL, void , glGetPixelMapuiv,( GLenum map, GLuint *values ),0,0); +DLLFUNCTION( OGL, void , glGetPixelMapusv,( GLenum map, GLushort *values ),0,0); + +DLLFUNCTION( OGL, void , glBitmap,( GLsizei width, GLsizei height, + GLfloat xorig, GLfloat yorig, + GLfloat xmove, GLfloat ymove, + const GLubyte *bitmap ),0,0); + +DLLFUNCTION( OGL, void , glReadPixels,( GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + GLvoid *pixels ),0,0); + +DLLFUNCTION( OGL, void , glDrawPixels,( GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ),0,0); + +DLLFUNCTION( OGL, void , glCopyPixels,( GLint x, GLint y, + GLsizei width, GLsizei height, + GLenum type ),0,0); + + + +/* + * Stenciling + */ + +DLLFUNCTION( OGL, void , glStencilFunc,( GLenum func, GLint ref, GLuint mask ),0,0); + +DLLFUNCTION( OGL, void , glStencilMask,( GLuint mask ),0,0); + +DLLFUNCTION( OGL, void , glStencilOp,( GLenum fail, GLenum zfail, GLenum zpass ),0,0); + +DLLFUNCTION( OGL, void , glClearStencil,( GLint s ),0,0); + + + +/* + * Texture mapping + */ + +DLLFUNCTION( OGL, void , glTexGend,( GLenum coord, GLenum pname, GLdouble param ),0,0); +DLLFUNCTION( OGL, void , glTexGenf,( GLenum coord, GLenum pname, GLfloat param ),0,0); +DLLFUNCTION( OGL, void , glTexGeni,( GLenum coord, GLenum pname, GLint param ),0,0); + +DLLFUNCTION( OGL, void , glTexGendv,( GLenum coord, GLenum pname, const GLdouble *params ),0,0); +DLLFUNCTION( OGL, void , glTexGenfv,( GLenum coord, GLenum pname, const GLfloat *params ),0,0); +DLLFUNCTION( OGL, void , glTexGeniv,( GLenum coord, GLenum pname, const GLint *params ),0,0); + +DLLFUNCTION( OGL, void , glGetTexGendv,( GLenum coord, GLenum pname, GLdouble *params ),0,0); +DLLFUNCTION( OGL, void , glGetTexGenfv,( GLenum coord, GLenum pname, GLfloat *params ),0,0); +DLLFUNCTION( OGL, void , glGetTexGeniv,( GLenum coord, GLenum pname, GLint *params ),0,0); + + +DLLFUNCTION( OGL, void , glTexEnvf,( GLenum target, GLenum pname, GLfloat param ),0,0); +DLLFUNCTION( OGL, void , glTexEnvi,( GLenum target, GLenum pname, GLint param ),0,0); + +DLLFUNCTION( OGL, void , glTexEnvfv,( GLenum target, GLenum pname, const GLfloat *params ),0,0); +DLLFUNCTION( OGL, void , glTexEnviv,( GLenum target, GLenum pname, const GLint *params ),0,0); + +DLLFUNCTION( OGL, void , glGetTexEnvfv,( GLenum target, GLenum pname, GLfloat *params ),0,0); +DLLFUNCTION( OGL, void , glGetTexEnviv,( GLenum target, GLenum pname, GLint *params ),0,0); + + +DLLFUNCTION( OGL, void , glTexParameterf,( GLenum target, GLenum pname, GLfloat param ),0,0); +DLLFUNCTION( OGL, void , glTexParameteri,( GLenum target, GLenum pname, GLint param ),0,0); + +DLLFUNCTION( OGL, void , glTexParameterfv,( GLenum target, GLenum pname, + const GLfloat *params ),0,0); +DLLFUNCTION( OGL, void , glTexParameteriv,( GLenum target, GLenum pname, + const GLint *params ),0,0); + +DLLFUNCTION( OGL, void , glGetTexParameterfv,( GLenum target, + GLenum pname, GLfloat *params),0,0); +DLLFUNCTION( OGL, void , glGetTexParameteriv,( GLenum target, + GLenum pname, GLint *params ),0,0); + +DLLFUNCTION( OGL, void , glGetTexLevelParameterfv,( GLenum target, GLint level, + GLenum pname, GLfloat *params ),0,0); +DLLFUNCTION( OGL, void , glGetTexLevelParameteriv,( GLenum target, GLint level, + GLenum pname, GLint *params ),0,0); + + +DLLFUNCTION( OGL, void , glTexImage1D,( GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ),0,0); + +DLLFUNCTION( OGL, void , glTexImage2D,( GLenum target, GLint level, + GLint internalFormat, + GLsizei width, GLsizei height, + GLint border, GLenum format, GLenum type, + const GLvoid *pixels ),0,0); + +DLLFUNCTION( OGL, void , glGetTexImage,( GLenum target, GLint level, + GLenum format, GLenum type, + GLvoid *pixels ),0,0); + + + +/* 1.1 functions */ + +DLLFUNCTION( OGL, void , glGenTextures,( GLsizei n, GLuint *textures ),0,0); + +DLLFUNCTION( OGL, void , glDeleteTextures,( GLsizei n, const GLuint *textures),0,0); + +DLLFUNCTION( OGL, void , glBindTexture,( GLenum target, GLuint texture ),0,0); + +DLLFUNCTION( OGL, void , glPrioritizeTextures,( GLsizei n, + const GLuint *textures, + const GLclampf *priorities ),0,0); + +DLLFUNCTION( OGL, GLboolean , glAreTexturesResident,( GLsizei n, + const GLuint *textures, + GLboolean *residences ),0,0); + +DLLFUNCTION( OGL, GLboolean , glIsTexture,( GLuint texture ),0,0); + + +DLLFUNCTION( OGL, void , glTexSubImage1D,( GLenum target, GLint level, + GLint xoffset, + GLsizei width, GLenum format, + GLenum type, const GLvoid *pixels ),0,0); + + +DLLFUNCTION( OGL, void , glTexSubImage2D,( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid *pixels ),0,0); + + +DLLFUNCTION( OGL, void , glCopyTexImage1D,( GLenum target, GLint level, + GLenum internalformat, + GLint x, GLint y, + GLsizei width, GLint border ),0,0); + + +DLLFUNCTION( OGL, void , glCopyTexImage2D,( GLenum target, GLint level, + GLenum internalformat, + GLint x, GLint y, + GLsizei width, GLsizei height, + GLint border ),0,0); + + +DLLFUNCTION( OGL, void , glCopyTexSubImage1D,( GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, + GLsizei width ),0,0); + + +DLLFUNCTION( OGL, void , glCopyTexSubImage2D,( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, + GLsizei width, GLsizei height ),0,0); + + + + +/* + * Evaluators + */ + +DLLFUNCTION( OGL, void , glMap1d,( GLenum target, GLdouble u1, GLdouble u2, + GLint stride, + GLint order, const GLdouble *points ),0,0); +DLLFUNCTION( OGL, void , glMap1f,( GLenum target, GLfloat u1, GLfloat u2, + GLint stride, + GLint order, const GLfloat *points ),0,0); + +DLLFUNCTION( OGL, void , glMap2d,( GLenum target, + GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, + GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, + const GLdouble *points ),0,0); +DLLFUNCTION( OGL, void , glMap2f,( GLenum target, + GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, + GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, + const GLfloat *points ),0,0); + +DLLFUNCTION( OGL, void , glGetMapdv,( GLenum target, GLenum query, GLdouble *v ),0,0); +DLLFUNCTION( OGL, void , glGetMapfv,( GLenum target, GLenum query, GLfloat *v ),0,0); +DLLFUNCTION( OGL, void , glGetMapiv,( GLenum target, GLenum query, GLint *v ),0,0); + +DLLFUNCTION( OGL, void , glEvalCoord1d,( GLdouble u ),0,0); +DLLFUNCTION( OGL, void , glEvalCoord1f,( GLfloat u ),0,0); + +DLLFUNCTION( OGL, void , glEvalCoord1dv,( const GLdouble *u ),0,0); +DLLFUNCTION( OGL, void , glEvalCoord1fv,( const GLfloat *u ),0,0); + +DLLFUNCTION( OGL, void , glEvalCoord2d,( GLdouble u, GLdouble v ),0,0); +DLLFUNCTION( OGL, void , glEvalCoord2f,( GLfloat u, GLfloat v ),0,0); + +DLLFUNCTION( OGL, void , glEvalCoord2dv,( const GLdouble *u ),0,0); +DLLFUNCTION( OGL, void , glEvalCoord2fv,( const GLfloat *u ),0,0); + +DLLFUNCTION( OGL, void , glMapGrid1d,( GLint un, GLdouble u1, GLdouble u2 ),0,0); +DLLFUNCTION( OGL, void , glMapGrid1f,( GLint un, GLfloat u1, GLfloat u2 ),0,0); + +DLLFUNCTION( OGL, void , glMapGrid2d,( GLint un, GLdouble u1, GLdouble u2, + GLint vn, GLdouble v1, GLdouble v2 ),0,0); +DLLFUNCTION( OGL, void , glMapGrid2f,( GLint un, GLfloat u1, GLfloat u2, + GLint vn, GLfloat v1, GLfloat v2 ),0,0); + +DLLFUNCTION( OGL, void , glEvalPoint1,( GLint i ),0,0); + +DLLFUNCTION( OGL, void , glEvalPoint2,( GLint i, GLint j ),0,0); + +DLLFUNCTION( OGL, void , glEvalMesh1,( GLenum mode, GLint i1, GLint i2 ),0,0); + +DLLFUNCTION( OGL, void , glEvalMesh2,( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 ),0,0); + + + +/* + * Fog + */ + +DLLFUNCTION( OGL, void , glFogf,( GLenum pname, GLfloat param ),0,0); + +DLLFUNCTION( OGL, void , glFogi,( GLenum pname, GLint param ),0,0); + +DLLFUNCTION( OGL, void , glFogfv,( GLenum pname, const GLfloat *params ),0,0); + +DLLFUNCTION( OGL, void , glFogiv,( GLenum pname, const GLint *params ),0,0); + + + +/* + * Selection and Feedback + */ + +DLLFUNCTION( OGL, void , glFeedbackBuffer,( GLsizei size, GLenum type, GLfloat *buffer ),0,0); + +DLLFUNCTION( OGL, void , glPassThrough,( GLfloat token ),0,0); + +DLLFUNCTION( OGL, void , glSelectBuffer,( GLsizei size, GLuint *buffer ),0,0); + +DLLFUNCTION( OGL, void , glInitNames,( void ),0,0); + +DLLFUNCTION( OGL, void , glLoadName,( GLuint name ),0,0); + +DLLFUNCTION( OGL, void , glPushName,( GLuint name ),0,0); + +DLLFUNCTION( OGL, void , glPopName,( void ),0,0); + + + +/* + * 1.0 Extensions + */ + +/* GL_EXT_blend_minmax */ +DLLFUNCTION( OGL, void , glBlendEquationEXT,( GLenum mode ),0,0); + + + +/* GL_EXT_blend_color */ +DLLFUNCTION( OGL, void , glBlendColorEXT,( GLclampf red, GLclampf green, + GLclampf blue, GLclampf alpha ),0,0); + + + +/* GL_EXT_polygon_offset */ +DLLFUNCTION( OGL, void , glPolygonOffsetEXT,( GLfloat factor, GLfloat bias ),0,0); + + + +/* GL_EXT_vertex_array */ + +DLLFUNCTION( OGL, void , glVertexPointerEXT,( GLint size, GLenum type, + GLsizei stride, + GLsizei count, const GLvoid *ptr ),0,0); + +DLLFUNCTION( OGL, void , glNormalPointerEXT,( GLenum type, GLsizei stride, + GLsizei count, const GLvoid *ptr ),0,0); + +DLLFUNCTION( OGL, void , glColorPointerEXT,( GLint size, GLenum type, + GLsizei stride, + GLsizei count, const GLvoid *ptr ),0,0); + +DLLFUNCTION( OGL, void , glIndexPointerEXT,( GLenum type, GLsizei stride, + GLsizei count, const GLvoid *ptr ),0,0); + +DLLFUNCTION( OGL, void , glTexCoordPointerEXT,( GLint size, GLenum type, + GLsizei stride, GLsizei count, + const GLvoid *ptr ),0,0); + +DLLFUNCTION( OGL, void , glEdgeFlagPointerEXT,( GLsizei stride, GLsizei count, + const GLboolean *ptr ),0,0); + +DLLFUNCTION( OGL, void , glGetPointervEXT,( GLenum pname, void **params ),0,0); + +DLLFUNCTION( OGL, void , glArrayElementEXT,( GLint i ),0,0); + +DLLFUNCTION( OGL, void , glDrawArraysEXT,( GLenum mode, GLint first, + GLsizei count ),0,0); + + + +/* GL_EXT_texture_object */ + +DLLFUNCTION( OGL, void , glGenTexturesEXT,( GLsizei n, GLuint *textures ),0,0); + +DLLFUNCTION( OGL, void , glDeleteTexturesEXT,( GLsizei n, + const GLuint *textures),0,0); + +DLLFUNCTION( OGL, void , glBindTextureEXT,( GLenum target, GLuint texture ),0,0); + +DLLFUNCTION( OGL, void , glPrioritizeTexturesEXT,( GLsizei n, + const GLuint *textures, + const GLclampf *priorities ),0,0); + +DLLFUNCTION( OGL, GLboolean , glAreTexturesResidentEXT,( GLsizei n, + const GLuint *textures, + GLboolean *residences ),0,0); + +DLLFUNCTION( OGL, GLboolean , glIsTextureEXT,( GLuint texture ),0,0); + + + +/* GL_EXT_texture3D */ + +DLLFUNCTION( OGL, void , glTexImage3DEXT,( GLenum target, GLint level, + GLenum internalFormat, + GLsizei width, GLsizei height, + GLsizei depth, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ),0,0); + +DLLFUNCTION( OGL, void , glTexSubImage3DEXT,( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLenum format, + GLenum type, const GLvoid *pixels),0,0); + +DLLFUNCTION( OGL, void , glCopyTexSubImage3DEXT,( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLint x, + GLint y, GLsizei width, + GLsizei height ),0,0); + + + +/* GL_EXT_color_table */ + +DLLFUNCTION( OGL, void , glColorTableEXT,( GLenum target, GLenum internalformat, + GLsizei width, GLenum format, + GLenum type, const GLvoid *table ),0,0); + +DLLFUNCTION( OGL, void , glColorSubTableEXT,( GLenum target, + GLsizei start, GLsizei count, + GLenum format, GLenum type, + const GLvoid *data ),0,0); + +DLLFUNCTION( OGL, void , glGetColorTableEXT,( GLenum target, GLenum format, + GLenum type, GLvoid *table ),0,0); + +DLLFUNCTION( OGL, void , glGetColorTableParameterfvEXT,( GLenum target, + GLenum pname, + GLfloat *params ),0,0); + +DLLFUNCTION( OGL, void , glGetColorTableParameterivEXT,( GLenum target, + GLenum pname, + GLint *params ),0,0); + + +/* GL_SGIS_multitexture */ + +DLLFUNCTION( OGL, void , glMultiTexCoord1dSGIS,(GLenum target, GLdouble s),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1dvSGIS,(GLenum target, const GLdouble *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1fSGIS,(GLenum target, GLfloat s),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1fvSGIS,(GLenum target, const GLfloat *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1iSGIS,(GLenum target, GLint s),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1ivSGIS,(GLenum target, const GLint *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1sSGIS,(GLenum target, GLshort s),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1svSGIS,(GLenum target, const GLshort *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2dSGIS,(GLenum target, GLdouble s, GLdouble t),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2dvSGIS,(GLenum target, const GLdouble *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2fSGIS,(GLenum target, GLfloat s, GLfloat t),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2fvSGIS,(GLenum target, const GLfloat *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2iSGIS,(GLenum target, GLint s, GLint t),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2ivSGIS,(GLenum target, const GLint *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2sSGIS,(GLenum target, GLshort s, GLshort t),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2svSGIS,(GLenum target, const GLshort *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3dSGIS,(GLenum target, GLdouble s, GLdouble t, GLdouble r),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3dvSGIS,(GLenum target, const GLdouble *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3fSGIS,(GLenum target, GLfloat s, GLfloat t, GLfloat r),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3fvSGIS,(GLenum target, const GLfloat *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3iSGIS,(GLenum target, GLint s, GLint t, GLint r),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3ivSGIS,(GLenum target, const GLint *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3sSGIS,(GLenum target, GLshort s, GLshort t, GLshort r),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3svSGIS,(GLenum target, const GLshort *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4dSGIS,(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4dvSGIS,(GLenum target, const GLdouble *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4fSGIS,(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4fvSGIS,(GLenum target, const GLfloat *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4iSGIS,(GLenum target, GLint s, GLint t, GLint r, GLint q),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4ivSGIS,(GLenum target, const GLint *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4sSGIS,(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4svSGIS,(GLenum target, const GLshort *v),0,0); + +DLLFUNCTION( OGL, void , glMultiTexCoordPointerSGIS,(GLenum target, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer),0,0); + +DLLFUNCTION( OGL, void , glSelectTextureSGIS,(GLenum target),0,0); + +DLLFUNCTION( OGL, void , glSelectTextureCoordSetSGIS,(GLenum target),0,0); + + +/* GL_EXT_multitexture */ + +DLLFUNCTION( OGL, void , glMultiTexCoord1dEXT,(GLenum target, GLdouble s),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1dvEXT,(GLenum target, const GLdouble *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1fEXT,(GLenum target, GLfloat s),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1fvEXT,(GLenum target, const GLfloat *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1iEXT,(GLenum target, GLint s),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1ivEXT,(GLenum target, const GLint *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1sEXT,(GLenum target, GLshort s),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord1svEXT,(GLenum target, const GLshort *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2dEXT,(GLenum target, GLdouble s, GLdouble t),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2dvEXT,(GLenum target, const GLdouble *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2fEXT,(GLenum target, GLfloat s, GLfloat t),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2fvEXT,(GLenum target, const GLfloat *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2iEXT,(GLenum target, GLint s, GLint t),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2ivEXT,(GLenum target, const GLint *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2sEXT,(GLenum target, GLshort s, GLshort t),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord2svEXT,(GLenum target, const GLshort *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3dEXT,(GLenum target, GLdouble s, GLdouble t, GLdouble r),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3dvEXT,(GLenum target, const GLdouble *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3fEXT,(GLenum target, GLfloat s, GLfloat t, GLfloat r),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3fvEXT,(GLenum target, const GLfloat *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3iEXT,(GLenum target, GLint s, GLint t, GLint r),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3ivEXT,(GLenum target, const GLint *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3sEXT,(GLenum target, GLshort s, GLshort t, GLshort r),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord3svEXT,(GLenum target, const GLshort *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4dEXT,(GLenum target, GLdouble s, GLdouble t, GLdouble r, GLdouble q),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4dvEXT,(GLenum target, const GLdouble *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4fEXT,(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4fvEXT,(GLenum target, const GLfloat *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4iEXT,(GLenum target, GLint s, GLint t, GLint r, GLint q),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4ivEXT,(GLenum target, const GLint *v),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4sEXT,(GLenum target, GLshort s, GLshort t, GLshort r, GLshort q),0,0); +DLLFUNCTION( OGL, void , glMultiTexCoord4svEXT,(GLenum target, const GLshort *v),0,0); + +DLLFUNCTION( OGL, void , glInterleavedTextureCoordSetsEXT,( GLint factor ),0,0); + +DLLFUNCTION( OGL, void , glSelectTextureEXT,( GLenum target ),0,0); + +DLLFUNCTION( OGL, void , glSelectTextureCoordSetEXT,( GLenum target ),0,0); + +DLLFUNCTION( OGL, void , glSelectTextureTransformEXT,( GLenum target ),0,0); + + + + + + +/* GL_EXT_point_parameters */ +DLLFUNCTION( OGL, void , glPointParameterfEXT,( GLenum pname, GLfloat param ),0,0); +DLLFUNCTION( OGL, void , glPointParameterfvEXT,( GLenum pname, + const GLfloat *params ),0,0); + + +/* 1.2 functions */ +DLLFUNCTION( OGL, void , glDrawRangeElements,( GLenum mode, GLuint start, + GLuint end, GLsizei count, GLenum type, const GLvoid *indices ),0,0); + +DLLFUNCTION( OGL, void , glTexImage3D,( GLenum target, GLint level, + GLenum internalFormat, + GLsizei width, GLsizei height, + GLsizei depth, GLint border, + GLenum format, GLenum type, + const GLvoid *pixels ),0,0); + +DLLFUNCTION( OGL, void , glTexSubImage3D,( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLsizei width, + GLsizei height, GLsizei depth, + GLenum format, + GLenum type, const GLvoid *pixels),0,0); + +DLLFUNCTION( OGL, void , glCopyTexSubImage3D,( GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint zoffset, GLint x, + GLint y, GLsizei width, + GLsizei height ),0,0); + + +/* !!! FIXME: This needs to move to a GL context abstraction layer. */ +#ifdef PLATFORM_WIN32 +// gdi functions +DLLFUNCTION( OGL, BOOL , wglCopyContext,(HGLRC, HGLRC, UINT),0,0); +DLLFUNCTION( OGL, HGLRC, wglCreateContext,(HDC),4,1); +DLLFUNCTION( OGL, HGLRC, wglCreateLayerContext,(HDC, int),0,0); +DLLFUNCTION( OGL, BOOL , wglDeleteContext,(HGLRC),4,1); +DLLFUNCTION( OGL, HGLRC, wglGetCurrentContext,(VOID),0,1); +DLLFUNCTION( OGL, HDC , wglGetCurrentDC,(VOID),0,1); +DLLFUNCTION( OGL, PROC , wglGetProcAddress,(LPCSTR),4,1); +DLLFUNCTION( OGL, BOOL , wglMakeCurrent,(HDC, HGLRC),8,1); +DLLFUNCTION( OGL, BOOL , wglShareLists,(HGLRC, HGLRC),0,0); +DLLFUNCTION( OGL, BOOL , wglUseFontBitmapsA,(HDC, DWORD, DWORD, DWORD),0,0); +DLLFUNCTION( OGL, BOOL , wglUseFontBitmapsW,(HDC, DWORD, DWORD, DWORD),0,0); + +DLLFUNCTION( OGL, BOOL, wglSwapBuffers, (HDC), 4,1); +DLLFUNCTION( OGL, BOOL, wglSetPixelFormat, (HDC, int, CONST PIXELFORMATDESCRIPTOR*),12,1); +DLLFUNCTION( OGL, int, wglChoosePixelFormat, (HDC, CONST PIXELFORMATDESCRIPTOR*),8,1); +DLLFUNCTION( OGL, int, wglDescribePixelFormat, (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR),16,1); +#endif + diff --git a/Sources/Engine/Graphics/gl_types.h b/Sources/Engine/Graphics/gl_types.h new file mode 100644 index 0000000..0099ac8 --- /dev/null +++ b/Sources/Engine/Graphics/gl_types.h @@ -0,0 +1,1057 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_GL_TYPES_H +#define SE_INCL_GL_TYPES_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* + * + * Enumerations + * + */ + +/* !!! FIXME: rcg10042001 Christ I hope this are the same on the Linux ABI... */ + +typedef enum { + /* Boolean values */ + GL_FALSE = 0, + GL_TRUE = 1, + + /* Data types */ + GL_BYTE = 0x1400, + GL_UNSIGNED_BYTE = 0x1401, + GL_SHORT = 0x1402, + GL_UNSIGNED_SHORT = 0x1403, + GL_INT = 0x1404, + GL_UNSIGNED_INT = 0x1405, + GL_FLOAT = 0x1406, + GL_DOUBLE = 0x140A, + GL_2_BYTES = 0x1407, + GL_3_BYTES = 0x1408, + GL_4_BYTES = 0x1409, + + /* Primitives */ + GL_LINES = 0x0001, + GL_POINTS = 0x0000, + GL_LINE_STRIP = 0x0003, + GL_LINE_LOOP = 0x0002, + GL_TRIANGLES = 0x0004, + GL_TRIANGLE_STRIP = 0x0005, + GL_TRIANGLE_FAN = 0x0006, + GL_QUADS = 0x0007, + GL_QUAD_STRIP = 0x0008, + GL_POLYGON = 0x0009, + GL_EDGE_FLAG = 0x0B43, + + /* Vertex Arrays */ + GL_VERTEX_ARRAY = 0x8074, + GL_NORMAL_ARRAY = 0x8075, + GL_COLOR_ARRAY = 0x8076, + GL_INDEX_ARRAY = 0x8077, + GL_TEXTURE_COORD_ARRAY = 0x8078, + GL_EDGE_FLAG_ARRAY = 0x8079, + GL_VERTEX_ARRAY_SIZE = 0x807A, + GL_VERTEX_ARRAY_TYPE = 0x807B, + GL_VERTEX_ARRAY_STRIDE = 0x807C, + GL_NORMAL_ARRAY_TYPE = 0x807E, + GL_NORMAL_ARRAY_STRIDE = 0x807F, + GL_COLOR_ARRAY_SIZE = 0x8081, + GL_COLOR_ARRAY_TYPE = 0x8082, + GL_COLOR_ARRAY_STRIDE = 0x8083, + GL_INDEX_ARRAY_TYPE = 0x8085, + GL_INDEX_ARRAY_STRIDE = 0x8086, + GL_TEXTURE_COORD_ARRAY_SIZE = 0x8088, + GL_TEXTURE_COORD_ARRAY_TYPE = 0x8089, + GL_TEXTURE_COORD_ARRAY_STRIDE = 0x808A, + GL_EDGE_FLAG_ARRAY_STRIDE = 0x808C, + GL_VERTEX_ARRAY_POINTER = 0x808E, + GL_NORMAL_ARRAY_POINTER = 0x808F, + GL_COLOR_ARRAY_POINTER = 0x8090, + GL_INDEX_ARRAY_POINTER = 0x8091, + GL_TEXTURE_COORD_ARRAY_POINTER = 0x8092, + GL_EDGE_FLAG_ARRAY_POINTER = 0x8093, + GL_V2F = 0x2A20, + GL_V3F = 0x2A21, + GL_C4UB_V2F = 0x2A22, + GL_C4UB_V3F = 0x2A23, + GL_C3F_V3F = 0x2A24, + GL_N3F_V3F = 0x2A25, + GL_C4F_N3F_V3F = 0x2A26, + GL_T2F_V3F = 0x2A27, + GL_T4F_V4F = 0x2A28, + GL_T2F_C4UB_V3F = 0x2A29, + GL_T2F_C3F_V3F = 0x2A2A, + GL_T2F_N3F_V3F = 0x2A2B, + GL_T2F_C4F_N3F_V3F = 0x2A2C, + GL_T4F_C4F_N3F_V4F = 0x2A2D, + + /* Matrix Mode */ + GL_MATRIX_MODE = 0x0BA0, + GL_MODELVIEW = 0x1700, + GL_PROJECTION = 0x1701, + GL_TEXTURE = 0x1702, + + /* Points */ + GL_POINT_SMOOTH = 0x0B10, + GL_POINT_SIZE = 0x0B11, + GL_POINT_SIZE_GRANULARITY = 0x0B13, + GL_POINT_SIZE_RANGE = 0x0B12, + + /* Lines */ + GL_LINE_SMOOTH = 0x0B20, + GL_LINE_STIPPLE = 0x0B24, + GL_LINE_STIPPLE_PATTERN = 0x0B25, + GL_LINE_STIPPLE_REPEAT = 0x0B26, + GL_LINE_WIDTH = 0x0B21, + GL_LINE_WIDTH_GRANULARITY = 0x0B23, + GL_LINE_WIDTH_RANGE = 0x0B22, + + /* Polygons */ + GL_POINT = 0x1B00, + GL_LINE = 0x1B01, + GL_FILL = 0x1B02, + GL_CCW = 0x0901, + GL_CW = 0x0900, + GL_FRONT = 0x0404, + GL_BACK = 0x0405, + GL_CULL_FACE = 0x0B44, + GL_CULL_FACE_MODE = 0x0B45, + GL_POLYGON_SMOOTH = 0x0B41, + GL_POLYGON_STIPPLE = 0x0B42, + GL_FRONT_FACE = 0x0B46, + GL_POLYGON_MODE = 0x0B40, + GL_POLYGON_OFFSET_FACTOR = 0x8038, + GL_POLYGON_OFFSET_UNITS = 0x2A00, + GL_POLYGON_OFFSET_POINT = 0x2A01, + GL_POLYGON_OFFSET_LINE = 0x2A02, + GL_POLYGON_OFFSET_FILL = 0x8037, + + /* Display Lists */ + GL_COMPILE = 0x1300, + GL_COMPILE_AND_EXECUTE = 0x1301, + GL_LIST_BASE = 0x0B32, + GL_LIST_INDEX = 0x0B33, + GL_LIST_MODE = 0x0B30, + + /* Depth buffer */ + GL_NEVER = 0x0200, + GL_LESS = 0x0201, + GL_GEQUAL = 0x0206, + GL_LEQUAL = 0x0203, + GL_GREATER = 0x0204, + GL_NOTEQUAL = 0x0205, + GL_EQUAL = 0x0202, + GL_ALWAYS = 0x0207, + GL_DEPTH_TEST = 0x0B71, + GL_DEPTH_BITS = 0x0D56, + GL_DEPTH_CLEAR_VALUE = 0x0B73, + GL_DEPTH_FUNC = 0x0B74, + GL_DEPTH_RANGE = 0x0B70, + GL_DEPTH_WRITEMASK = 0x0B72, + GL_DEPTH_COMPONENT = 0x1902, + + /* Lighting */ + GL_LIGHTING = 0x0B50, + GL_LIGHT0 = 0x4000, + GL_LIGHT1 = 0x4001, + GL_LIGHT2 = 0x4002, + GL_LIGHT3 = 0x4003, + GL_LIGHT4 = 0x4004, + GL_LIGHT5 = 0x4005, + GL_LIGHT6 = 0x4006, + GL_LIGHT7 = 0x4007, + GL_SPOT_EXPONENT = 0x1205, + GL_SPOT_CUTOFF = 0x1206, + GL_CONSTANT_ATTENUATION = 0x1207, + GL_LINEAR_ATTENUATION = 0x1208, + GL_QUADRATIC_ATTENUATION = 0x1209, + GL_AMBIENT = 0x1200, + GL_DIFFUSE = 0x1201, + GL_SPECULAR = 0x1202, + GL_SHININESS = 0x1601, + GL_EMISSION = 0x1600, + GL_POSITION = 0x1203, + GL_SPOT_DIRECTION = 0x1204, + GL_AMBIENT_AND_DIFFUSE = 0x1602, + GL_COLOR_INDEXES = 0x1603, + GL_LIGHT_MODEL_TWO_SIDE = 0x0B52, + GL_LIGHT_MODEL_LOCAL_VIEWER = 0x0B51, + GL_LIGHT_MODEL_AMBIENT = 0x0B53, + GL_FRONT_AND_BACK = 0x0408, + GL_SHADE_MODEL = 0x0B54, + GL_FLAT = 0x1D00, + GL_SMOOTH = 0x1D01, + GL_COLOR_MATERIAL = 0x0B57, + GL_COLOR_MATERIAL_FACE = 0x0B55, + GL_COLOR_MATERIAL_PARAMETER = 0x0B56, + GL_NORMALIZE = 0x0BA1, + + /* User clipping planes */ + GL_CLIP_PLANE0 = 0x3000, + GL_CLIP_PLANE1 = 0x3001, + GL_CLIP_PLANE2 = 0x3002, + GL_CLIP_PLANE3 = 0x3003, + GL_CLIP_PLANE4 = 0x3004, + GL_CLIP_PLANE5 = 0x3005, + + /* Accumulation buffer */ + GL_ACCUM_RED_BITS = 0x0D58, + GL_ACCUM_GREEN_BITS = 0x0D59, + GL_ACCUM_BLUE_BITS = 0x0D5A, + GL_ACCUM_ALPHA_BITS = 0x0D5B, + GL_ACCUM_CLEAR_VALUE = 0x0B80, + GL_ACCUM = 0x0100, + GL_ADD = 0x0104, + GL_LOAD = 0x0101, + GL_MULT = 0x0103, + GL_RETURN = 0x0102, + + /* Alpha testing */ + GL_ALPHA_TEST = 0x0BC0, + GL_ALPHA_TEST_REF = 0x0BC2, + GL_ALPHA_TEST_FUNC = 0x0BC1, + + /* Blending */ + GL_BLEND = 0x0BE2, + GL_BLEND_SRC = 0x0BE1, + GL_BLEND_DST = 0x0BE0, + GL_ZERO = 0, + GL_ONE = 1, + GL_SRC_COLOR = 0x0300, + GL_ONE_MINUS_SRC_COLOR = 0x0301, + GL_DST_COLOR = 0x0306, + GL_ONE_MINUS_DST_COLOR = 0x0307, + GL_SRC_ALPHA = 0x0302, + GL_ONE_MINUS_SRC_ALPHA = 0x0303, + GL_DST_ALPHA = 0x0304, + GL_ONE_MINUS_DST_ALPHA = 0x0305, + GL_SRC_ALPHA_SATURATE = 0x0308, + GL_CONSTANT_COLOR = 0x8001, + GL_ONE_MINUS_CONSTANT_COLOR = 0x8002, + GL_CONSTANT_ALPHA = 0x8003, + GL_ONE_MINUS_CONSTANT_ALPHA = 0x8004, + + /* Render Mode */ + GL_FEEDBACK = 0x1C01, + GL_RENDER = 0x1C00, + GL_SELECT = 0x1C02, + + /* Feedback */ + GL_2D = 0x0600, + GL_3D = 0x0601, + GL_3D_COLOR = 0x0602, + GL_3D_COLOR_TEXTURE = 0x0603, + GL_4D_COLOR_TEXTURE = 0x0604, + GL_POINT_TOKEN = 0x0701, + GL_LINE_TOKEN = 0x0702, + GL_LINE_RESET_TOKEN = 0x0707, + GL_POLYGON_TOKEN = 0x0703, + GL_BITMAP_TOKEN = 0x0704, + GL_DRAW_PIXEL_TOKEN = 0x0705, + GL_COPY_PIXEL_TOKEN = 0x0706, + GL_PASS_THROUGH_TOKEN = 0x0700, + GL_FEEDBACK_BUFFER_POINTER = 0x0DF0, + GL_FEEDBACK_BUFFER_SIZE = 0x0DF1, + GL_FEEDBACK_BUFFER_TYPE = 0x0DF2, + + /* Selection */ + GL_SELECTION_BUFFER_POINTER = 0x0DF3, + GL_SELECTION_BUFFER_SIZE = 0x0DF4, + + /* Fog */ + GL_FOG = 0x0B60, + GL_FOG_MODE = 0x0B65, + GL_FOG_DENSITY = 0x0B62, + GL_FOG_COLOR = 0x0B66, + GL_FOG_INDEX = 0x0B61, + GL_FOG_START = 0x0B63, + GL_FOG_END = 0x0B64, + GL_LINEAR = 0x2601, + GL_EXP = 0x0800, + GL_EXP2 = 0x0801, + + /* Logic Ops */ + GL_LOGIC_OP = 0x0BF1, + GL_INDEX_LOGIC_OP = 0x0BF1, + GL_COLOR_LOGIC_OP = 0x0BF2, + GL_LOGIC_OP_MODE = 0x0BF0, + GL_CLEAR = 0x1500, + GL_SET = 0x150F, + GL_COPY = 0x1503, + GL_COPY_INVERTED = 0x150C, + GL_NOOP = 0x1505, + GL_INVERT = 0x150A, + GL_AND = 0x1501, + GL_NAND = 0x150E, + GL_OR = 0x1507, + GL_NOR = 0x1508, + GL_XOR = 0x1506, + GL_EQUIV = 0x1509, + GL_AND_REVERSE = 0x1502, + GL_AND_INVERTED = 0x1504, + GL_OR_REVERSE = 0x150B, + GL_OR_INVERTED = 0x150D, + + /* Stencil */ + GL_STENCIL_TEST = 0x0B90, + GL_STENCIL_WRITEMASK = 0x0B98, + GL_STENCIL_BITS = 0x0D57, + GL_STENCIL_FUNC = 0x0B92, + GL_STENCIL_VALUE_MASK = 0x0B93, + GL_STENCIL_REF = 0x0B97, + GL_STENCIL_FAIL = 0x0B94, + GL_STENCIL_PASS_DEPTH_PASS = 0x0B96, + GL_STENCIL_PASS_DEPTH_FAIL = 0x0B95, + GL_STENCIL_CLEAR_VALUE = 0x0B91, + GL_STENCIL_INDEX = 0x1901, + GL_KEEP = 0x1E00, + GL_REPLACE = 0x1E01, + GL_INCR = 0x1E02, + GL_DECR = 0x1E03, + + /* Buffers, Pixel Drawing/Reading */ + GL_NONE = 0, + GL_LEFT = 0x0406, + GL_RIGHT = 0x0407, + /*GL_FRONT = 0x0404, */ + /*GL_BACK = 0x0405, */ + /*GL_FRONT_AND_BACK = 0x0408, */ + GL_FRONT_LEFT = 0x0400, + GL_FRONT_RIGHT = 0x0401, + GL_BACK_LEFT = 0x0402, + GL_BACK_RIGHT = 0x0403, + GL_AUX0 = 0x0409, + GL_AUX1 = 0x040A, + GL_AUX2 = 0x040B, + GL_AUX3 = 0x040C, + GL_COLOR_INDEX = 0x1900, + GL_RED = 0x1903, + GL_GREEN = 0x1904, + GL_BLUE = 0x1905, + GL_ALPHA = 0x1906, + GL_LUMINANCE = 0x1909, + GL_LUMINANCE_ALPHA = 0x190A, + GL_ALPHA_BITS = 0x0D55, + GL_RED_BITS = 0x0D52, + GL_GREEN_BITS = 0x0D53, + GL_BLUE_BITS = 0x0D54, + GL_INDEX_BITS = 0x0D51, + GL_SUBPIXEL_BITS = 0x0D50, + GL_AUX_BUFFERS = 0x0C00, + GL_READ_BUFFER = 0x0C02, + GL_DRAW_BUFFER = 0x0C01, + GL_DOUBLEBUFFER = 0x0C32, + GL_STEREO = 0x0C33, + GL_BITMAP = 0x1A00, + GL_COLOR = 0x1800, + GL_DEPTH = 0x1801, + GL_STENCIL = 0x1802, + GL_DITHER = 0x0BD0, + GL_RGB = 0x1907, + GL_RGBA = 0x1908, + + /* Implementation limits */ + GL_MAX_LIST_NESTING = 0x0B31, + GL_MAX_ATTRIB_STACK_DEPTH = 0x0D35, + GL_MAX_MODELVIEW_STACK_DEPTH = 0x0D36, + GL_MAX_NAME_STACK_DEPTH = 0x0D37, + GL_MAX_PROJECTION_STACK_DEPTH = 0x0D38, + GL_MAX_TEXTURE_STACK_DEPTH = 0x0D39, + GL_MAX_EVAL_ORDER = 0x0D30, + GL_MAX_LIGHTS = 0x0D31, + GL_MAX_CLIP_PLANES = 0x0D32, + GL_MAX_TEXTURE_SIZE = 0x0D33, + GL_MAX_PIXEL_MAP_TABLE = 0x0D34, + GL_MAX_VIEWPORT_DIMS = 0x0D3A, + GL_MAX_CLIENT_ATTRIB_STACK_DEPTH= 0x0D3B, + + /* Gets */ + GL_ATTRIB_STACK_DEPTH = 0x0BB0, + GL_CLIENT_ATTRIB_STACK_DEPTH = 0x0BB1, + GL_COLOR_CLEAR_VALUE = 0x0C22, + GL_COLOR_WRITEMASK = 0x0C23, + GL_CURRENT_INDEX = 0x0B01, + GL_CURRENT_COLOR = 0x0B00, + GL_CURRENT_NORMAL = 0x0B02, + GL_CURRENT_RASTER_COLOR = 0x0B04, + GL_CURRENT_RASTER_DISTANCE = 0x0B09, + GL_CURRENT_RASTER_INDEX = 0x0B05, + GL_CURRENT_RASTER_POSITION = 0x0B07, + GL_CURRENT_RASTER_TEXTURE_COORDS = 0x0B06, + GL_CURRENT_RASTER_POSITION_VALID = 0x0B08, + GL_CURRENT_TEXTURE_COORDS = 0x0B03, + GL_INDEX_CLEAR_VALUE = 0x0C20, + GL_INDEX_MODE = 0x0C30, + GL_INDEX_WRITEMASK = 0x0C21, + GL_MODELVIEW_MATRIX = 0x0BA6, + GL_MODELVIEW_STACK_DEPTH = 0x0BA3, + GL_NAME_STACK_DEPTH = 0x0D70, + GL_PROJECTION_MATRIX = 0x0BA7, + GL_PROJECTION_STACK_DEPTH = 0x0BA4, + GL_RENDER_MODE = 0x0C40, + GL_RGBA_MODE = 0x0C31, + GL_TEXTURE_MATRIX = 0x0BA8, + GL_TEXTURE_STACK_DEPTH = 0x0BA5, + GL_VIEWPORT = 0x0BA2, + + + /* Evaluators */ + GL_AUTO_NORMAL = 0x0D80, + GL_MAP1_COLOR_4 = 0x0D90, + GL_MAP1_GRID_DOMAIN = 0x0DD0, + GL_MAP1_GRID_SEGMENTS = 0x0DD1, + GL_MAP1_INDEX = 0x0D91, + GL_MAP1_NORMAL = 0x0D92, + GL_MAP1_TEXTURE_COORD_1 = 0x0D93, + GL_MAP1_TEXTURE_COORD_2 = 0x0D94, + GL_MAP1_TEXTURE_COORD_3 = 0x0D95, + GL_MAP1_TEXTURE_COORD_4 = 0x0D96, + GL_MAP1_VERTEX_3 = 0x0D97, + GL_MAP1_VERTEX_4 = 0x0D98, + GL_MAP2_COLOR_4 = 0x0DB0, + GL_MAP2_GRID_DOMAIN = 0x0DD2, + GL_MAP2_GRID_SEGMENTS = 0x0DD3, + GL_MAP2_INDEX = 0x0DB1, + GL_MAP2_NORMAL = 0x0DB2, + GL_MAP2_TEXTURE_COORD_1 = 0x0DB3, + GL_MAP2_TEXTURE_COORD_2 = 0x0DB4, + GL_MAP2_TEXTURE_COORD_3 = 0x0DB5, + GL_MAP2_TEXTURE_COORD_4 = 0x0DB6, + GL_MAP2_VERTEX_3 = 0x0DB7, + GL_MAP2_VERTEX_4 = 0x0DB8, + GL_COEFF = 0x0A00, + GL_DOMAIN = 0x0A02, + GL_ORDER = 0x0A01, + + /* Hints */ + GL_FOG_HINT = 0x0C54, + GL_LINE_SMOOTH_HINT = 0x0C52, + GL_PERSPECTIVE_CORRECTION_HINT = 0x0C50, + GL_POINT_SMOOTH_HINT = 0x0C51, + GL_POLYGON_SMOOTH_HINT = 0x0C53, + GL_DONT_CARE = 0x1100, + GL_FASTEST = 0x1101, + GL_NICEST = 0x1102, + + /* Scissor box */ + GL_SCISSOR_TEST = 0x0C11, + GL_SCISSOR_BOX = 0x0C10, + + /* Pixel Mode / Transfer */ + GL_MAP_COLOR = 0x0D10, + GL_MAP_STENCIL = 0x0D11, + GL_INDEX_SHIFT = 0x0D12, + GL_INDEX_OFFSET = 0x0D13, + GL_RED_SCALE = 0x0D14, + GL_RED_BIAS = 0x0D15, + GL_GREEN_SCALE = 0x0D18, + GL_GREEN_BIAS = 0x0D19, + GL_BLUE_SCALE = 0x0D1A, + GL_BLUE_BIAS = 0x0D1B, + GL_ALPHA_SCALE = 0x0D1C, + GL_ALPHA_BIAS = 0x0D1D, + GL_DEPTH_SCALE = 0x0D1E, + GL_DEPTH_BIAS = 0x0D1F, + GL_PIXEL_MAP_S_TO_S_SIZE = 0x0CB1, + GL_PIXEL_MAP_I_TO_I_SIZE = 0x0CB0, + GL_PIXEL_MAP_I_TO_R_SIZE = 0x0CB2, + GL_PIXEL_MAP_I_TO_G_SIZE = 0x0CB3, + GL_PIXEL_MAP_I_TO_B_SIZE = 0x0CB4, + GL_PIXEL_MAP_I_TO_A_SIZE = 0x0CB5, + GL_PIXEL_MAP_R_TO_R_SIZE = 0x0CB6, + GL_PIXEL_MAP_G_TO_G_SIZE = 0x0CB7, + GL_PIXEL_MAP_B_TO_B_SIZE = 0x0CB8, + GL_PIXEL_MAP_A_TO_A_SIZE = 0x0CB9, + GL_PIXEL_MAP_S_TO_S = 0x0C71, + GL_PIXEL_MAP_I_TO_I = 0x0C70, + GL_PIXEL_MAP_I_TO_R = 0x0C72, + GL_PIXEL_MAP_I_TO_G = 0x0C73, + GL_PIXEL_MAP_I_TO_B = 0x0C74, + GL_PIXEL_MAP_I_TO_A = 0x0C75, + GL_PIXEL_MAP_R_TO_R = 0x0C76, + GL_PIXEL_MAP_G_TO_G = 0x0C77, + GL_PIXEL_MAP_B_TO_B = 0x0C78, + GL_PIXEL_MAP_A_TO_A = 0x0C79, + GL_PACK_ALIGNMENT = 0x0D05, + GL_PACK_LSB_FIRST = 0x0D01, + GL_PACK_ROW_LENGTH = 0x0D02, + GL_PACK_SKIP_PIXELS = 0x0D04, + GL_PACK_SKIP_ROWS = 0x0D03, + GL_PACK_SWAP_BYTES = 0x0D00, + GL_UNPACK_ALIGNMENT = 0x0CF5, + GL_UNPACK_LSB_FIRST = 0x0CF1, + GL_UNPACK_ROW_LENGTH = 0x0CF2, + GL_UNPACK_SKIP_PIXELS = 0x0CF4, + GL_UNPACK_SKIP_ROWS = 0x0CF3, + GL_UNPACK_SWAP_BYTES = 0x0CF0, + GL_ZOOM_X = 0x0D16, + GL_ZOOM_Y = 0x0D17, + + /* Texture mapping */ + GL_TEXTURE_ENV = 0x2300, + GL_TEXTURE_ENV_MODE = 0x2200, + GL_TEXTURE_1D = 0x0DE0, + GL_TEXTURE_2D = 0x0DE1, + GL_TEXTURE_WRAP_S = 0x2802, + GL_TEXTURE_WRAP_T = 0x2803, + GL_TEXTURE_MAG_FILTER = 0x2800, + GL_TEXTURE_MIN_FILTER = 0x2801, + GL_TEXTURE_ENV_COLOR = 0x2201, + GL_TEXTURE_GEN_S = 0x0C60, + GL_TEXTURE_GEN_T = 0x0C61, + GL_TEXTURE_GEN_MODE = 0x2500, + GL_TEXTURE_BORDER_COLOR = 0x1004, + GL_TEXTURE_WIDTH = 0x1000, + GL_TEXTURE_HEIGHT = 0x1001, + GL_TEXTURE_BORDER = 0x1005, + GL_TEXTURE_COMPONENTS = 0x1003, + GL_TEXTURE_RED_SIZE = 0x805C, + GL_TEXTURE_GREEN_SIZE = 0x805D, + GL_TEXTURE_BLUE_SIZE = 0x805E, + GL_TEXTURE_ALPHA_SIZE = 0x805F, + GL_TEXTURE_LUMINANCE_SIZE = 0x8060, + GL_TEXTURE_INTENSITY_SIZE = 0x8061, + GL_NEAREST_MIPMAP_NEAREST = 0x2700, + GL_NEAREST_MIPMAP_LINEAR = 0x2702, + GL_LINEAR_MIPMAP_NEAREST = 0x2701, + GL_LINEAR_MIPMAP_LINEAR = 0x2703, + GL_OBJECT_LINEAR = 0x2401, + GL_OBJECT_PLANE = 0x2501, + GL_EYE_LINEAR = 0x2400, + GL_EYE_PLANE = 0x2502, + GL_SPHERE_MAP = 0x2402, + GL_DECAL = 0x2101, + GL_MODULATE = 0x2100, + GL_NEAREST = 0x2600, + GL_REPEAT = 0x2901, + GL_CLAMP = 0x2900, + GL_S = 0x2000, + GL_T = 0x2001, + GL_R = 0x2002, + GL_Q = 0x2003, + GL_TEXTURE_GEN_R = 0x0C62, + GL_TEXTURE_GEN_Q = 0x0C63, + + /* GL 1.1 texturing */ + GL_PROXY_TEXTURE_1D = 0x8063, + GL_PROXY_TEXTURE_2D = 0x8064, + GL_TEXTURE_PRIORITY = 0x8066, + GL_TEXTURE_RESIDENT = 0x8067, + GL_TEXTURE_BINDING_1D = 0x8068, + GL_TEXTURE_BINDING_2D = 0x8069, + GL_TEXTURE_INTERNAL_FORMAT = 0x1003, + + /* GL 1.2 texturing */ + GL_PACK_SKIP_IMAGES = 0x806B, + GL_PACK_IMAGE_HEIGHT = 0x806C, + GL_UNPACK_SKIP_IMAGES = 0x806D, + GL_UNPACK_IMAGE_HEIGHT = 0x806E, + GL_TEXTURE_3D = 0x806F, + GL_PROXY_TEXTURE_3D = 0x8070, + GL_TEXTURE_DEPTH = 0x8071, + GL_TEXTURE_WRAP_R = 0x8072, + GL_MAX_3D_TEXTURE_SIZE = 0x8073, + GL_TEXTURE_BINDING_3D = 0x806A, + + /* Internal texture formats (GL 1.1) */ + GL_ALPHA4 = 0x803B, + GL_ALPHA8 = 0x803C, + GL_ALPHA12 = 0x803D, + GL_ALPHA16 = 0x803E, + GL_LUMINANCE4 = 0x803F, + GL_LUMINANCE8 = 0x8040, + GL_LUMINANCE12 = 0x8041, + GL_LUMINANCE16 = 0x8042, + GL_LUMINANCE4_ALPHA4 = 0x8043, + GL_LUMINANCE6_ALPHA2 = 0x8044, + GL_LUMINANCE8_ALPHA8 = 0x8045, + GL_LUMINANCE12_ALPHA4 = 0x8046, + GL_LUMINANCE12_ALPHA12 = 0x8047, + GL_LUMINANCE16_ALPHA16 = 0x8048, + GL_INTENSITY = 0x8049, + GL_INTENSITY4 = 0x804A, + GL_INTENSITY8 = 0x804B, + GL_INTENSITY12 = 0x804C, + GL_INTENSITY16 = 0x804D, + GL_R3_G3_B2 = 0x2A10, + GL_RGB4 = 0x804F, + GL_RGB5 = 0x8050, + GL_RGB8 = 0x8051, + GL_RGB10 = 0x8052, + GL_RGB12 = 0x8053, + GL_RGB16 = 0x8054, + GL_RGBA2 = 0x8055, + GL_RGBA4 = 0x8056, + GL_RGB5_A1 = 0x8057, + GL_RGBA8 = 0x8058, + GL_RGB10_A2 = 0x8059, + GL_RGBA12 = 0x805A, + GL_RGBA16 = 0x805B, + + // GL_S3_s3tc + GL_RGB_S3TC = 0x83A0, + GL_RGB4_S3TC = 0x83A1, + GL_RGBA_S3TC = 0x83A2, + GL_COMPRESSED_RGB_S3TC = GL_RGB_S3TC, + GL_COMPRESSED_RGB4_S3TC = GL_RGB4_S3TC, + GL_COMPRESSED_RGBA_S3TC = GL_RGBA_S3TC, + GL_COMPRESSED_LUMINANCE_S3TC = 0x83A3, + GL_COMPRESSED_LUMINANCE_ALPHA_S3TC = 0x83A4, + GL_COMPRESSED_RGB4_COMPRESSED_ALPHA4_S3TC = 0x83A5, + GL_COMPRESSED_RGB4_ALPHA4_S3TC = 0x83A6, + GL_COMPRESSED_LUMINANCE4_S3TC = 0x83A7, + GL_COMPRESSED_LUMINANCE4_ALPHA_S3TC = 0x83A8, + + // GL_EXT_texture_compression_s3tc + GL_COMPRESSED_RGB_S3TC_DXT1_EXT = 0x83F0, + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2, + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3, + + // GL_3DFX_texture_compression_FXT1 + GL_COMPRESSED_RGB_FXT1_3DFX = 0x86B0, + GL_COMPRESSED_RGBA_FXT1_3DFX = 0x86B1, + + // GL_ARB_texture_compression + GL_COMPRESSED_ALPHA_ARB = 0x84E9, + GL_COMPRESSED_LUMINANCE_ARB = 0x84EA, + GL_COMPRESSED_LUMINANCE_ALPHA_ARB = 0x84EB, + GL_COMPRESSED_INTENSITY_ARB = 0x84EC, + GL_COMPRESSED_RGB_ARB = 0x84ED, + GL_COMPRESSED_RGBA_ARB = 0x84EE, + + GL_TEXTURE_COMPRESSION_HINT_ARB = 0x84EF, + + GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB = 0x86A0, + GL_TEXTURE_COMPRESSED_ARB = 0x86A1, + GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB = 0x86A2, + GL_COMPRESSED_TEXTURE_FORMATS_ARB = 0x86A3, + + + /* Utility */ + GL_VENDOR = 0x1F00, + GL_RENDERER = 0x1F01, + GL_VERSION = 0x1F02, + GL_EXTENSIONS = 0x1F03, + + /* Errors */ + GL_INVALID_VALUE = 0x0501, + GL_INVALID_ENUM = 0x0500, + GL_INVALID_OPERATION = 0x0502, + GL_STACK_OVERFLOW = 0x0503, + GL_STACK_UNDERFLOW = 0x0504, + GL_OUT_OF_MEMORY = 0x0505, + + /* + * Extensions + */ + + /* GL_EXT_blend_minmax and GL_EXT_blend_color */ + GL_CONSTANT_COLOR_EXT = 0x8001, + GL_ONE_MINUS_CONSTANT_COLOR_EXT = 0x8002, + GL_CONSTANT_ALPHA_EXT = 0x8003, + GL_ONE_MINUS_CONSTANT_ALPHA_EXT = 0x8004, + GL_BLEND_EQUATION_EXT = 0x8009, + GL_MIN_EXT = 0x8007, + GL_MAX_EXT = 0x8008, + GL_FUNC_ADD_EXT = 0x8006, + GL_FUNC_SUBTRACT_EXT = 0x800A, + GL_FUNC_REVERSE_SUBTRACT_EXT = 0x800B, + GL_BLEND_COLOR_EXT = 0x8005, + + /* GL_EXT_polygon_offset */ + GL_POLYGON_OFFSET_EXT = 0x8037, + GL_POLYGON_OFFSET_FACTOR_EXT = 0x8038, + GL_POLYGON_OFFSET_BIAS_EXT = 0x8039, + + /* GL_EXT_vertex_array */ + GL_VERTEX_ARRAY_EXT = 0x8074, + GL_NORMAL_ARRAY_EXT = 0x8075, + GL_COLOR_ARRAY_EXT = 0x8076, + GL_INDEX_ARRAY_EXT = 0x8077, + GL_TEXTURE_COORD_ARRAY_EXT = 0x8078, + GL_EDGE_FLAG_ARRAY_EXT = 0x8079, + GL_VERTEX_ARRAY_SIZE_EXT = 0x807A, + GL_VERTEX_ARRAY_TYPE_EXT = 0x807B, + GL_VERTEX_ARRAY_STRIDE_EXT = 0x807C, + GL_VERTEX_ARRAY_COUNT_EXT = 0x807D, + GL_NORMAL_ARRAY_TYPE_EXT = 0x807E, + GL_NORMAL_ARRAY_STRIDE_EXT = 0x807F, + GL_NORMAL_ARRAY_COUNT_EXT = 0x8080, + GL_COLOR_ARRAY_SIZE_EXT = 0x8081, + GL_COLOR_ARRAY_TYPE_EXT = 0x8082, + GL_COLOR_ARRAY_STRIDE_EXT = 0x8083, + GL_COLOR_ARRAY_COUNT_EXT = 0x8084, + GL_INDEX_ARRAY_TYPE_EXT = 0x8085, + GL_INDEX_ARRAY_STRIDE_EXT = 0x8086, + GL_INDEX_ARRAY_COUNT_EXT = 0x8087, + GL_TEXTURE_COORD_ARRAY_SIZE_EXT = 0x8088, + GL_TEXTURE_COORD_ARRAY_TYPE_EXT = 0x8089, + GL_TEXTURE_COORD_ARRAY_STRIDE_EXT = 0x808A, + GL_TEXTURE_COORD_ARRAY_COUNT_EXT = 0x808B, + GL_EDGE_FLAG_ARRAY_STRIDE_EXT = 0x808C, + GL_EDGE_FLAG_ARRAY_COUNT_EXT = 0x808D, + GL_VERTEX_ARRAY_POINTER_EXT = 0x808E, + GL_NORMAL_ARRAY_POINTER_EXT = 0x808F, + GL_COLOR_ARRAY_POINTER_EXT = 0x8090, + GL_INDEX_ARRAY_POINTER_EXT = 0x8091, + GL_TEXTURE_COORD_ARRAY_POINTER_EXT = 0x8092, + GL_EDGE_FLAG_ARRAY_POINTER_EXT = 0x8093, + + /* GL_EXT_texture_object */ + GL_TEXTURE_PRIORITY_EXT = 0x8066, + GL_TEXTURE_RESIDENT_EXT = 0x8067, + GL_TEXTURE_1D_BINDING_EXT = 0x8068, + GL_TEXTURE_2D_BINDING_EXT = 0x8069, + + /* GL_EXT_texture3D */ + GL_PACK_SKIP_IMAGES_EXT = 0x806B, + GL_PACK_IMAGE_HEIGHT_EXT = 0x806C, + GL_UNPACK_SKIP_IMAGES_EXT = 0x806D, + GL_UNPACK_IMAGE_HEIGHT_EXT = 0x806E, + GL_TEXTURE_3D_EXT = 0x806F, + GL_PROXY_TEXTURE_3D_EXT = 0x8070, + GL_TEXTURE_DEPTH_EXT = 0x8071, + GL_TEXTURE_WRAP_R_EXT = 0x8072, + GL_MAX_3D_TEXTURE_SIZE_EXT = 0x8073, + GL_TEXTURE_3D_BINDING_EXT = 0x806A, + + /* GL_EXT_paletted_texture */ + GL_TABLE_TOO_LARGE_EXT = 0x8031, + GL_COLOR_TABLE_FORMAT_EXT = 0x80D8, + GL_COLOR_TABLE_WIDTH_EXT = 0x80D9, + GL_COLOR_TABLE_RED_SIZE_EXT = 0x80DA, + GL_COLOR_TABLE_GREEN_SIZE_EXT = 0x80DB, + GL_COLOR_TABLE_BLUE_SIZE_EXT = 0x80DC, + GL_COLOR_TABLE_ALPHA_SIZE_EXT = 0x80DD, + GL_COLOR_TABLE_LUMINANCE_SIZE_EXT = 0x80DE, + GL_COLOR_TABLE_INTENSITY_SIZE_EXT = 0x80DF, + GL_TEXTURE_INDEX_SIZE_EXT = 0x80ED, + GL_COLOR_INDEX1_EXT = 0x80E2, + GL_COLOR_INDEX2_EXT = 0x80E3, + GL_COLOR_INDEX4_EXT = 0x80E4, + GL_COLOR_INDEX8_EXT = 0x80E5, + GL_COLOR_INDEX12_EXT = 0x80E6, + GL_COLOR_INDEX16_EXT = 0x80E7, + + /* GL_EXT_shared_texture_palette */ + GL_SHARED_TEXTURE_PALETTE_EXT = 0x81FB, + + /* GL_EXT_point_parameters */ + GL_POINT_SIZE_MIN_EXT = 0x8126, + GL_POINT_SIZE_MAX_EXT = 0x8127, + GL_POINT_FADE_THRESHOLD_SIZE_EXT = 0x8128, + GL_DISTANCE_ATTENUATION_EXT = 0x8129, + + /* GL_EXT_rescale_normal */ + GL_RESCALE_NORMAL_EXT = 0x803A, + + /* GL_EXT_abgr */ + GL_ABGR_EXT = 0x8000, + + /* GL_SGIS_multitexture */ + GL_SELECTED_TEXTURE_SGIS = 0x835C, + GL_SELECTED_TEXTURE_COORD_SET_SGIS = 0x835D, + GL_MAX_TEXTURES_SGIS = 0x835E, + GL_TEXTURE0_SGIS = 0x835F, + GL_TEXTURE1_SGIS = 0x8360, + GL_TEXTURE2_SGIS = 0x8361, + GL_TEXTURE3_SGIS = 0x8362, + GL_TEXTURE_COORD_SET_SOURCE_SGIS = 0x8363, + + /* GL_EXT_multitexture */ + GL_SELECTED_TEXTURE_EXT = 0x83C0, + GL_SELECTED_TEXTURE_COORD_SET_EXT = 0x83C1, + GL_SELECTED_TEXTURE_TRANSFORM_EXT = 0x83C2, + GL_MAX_TEXTURES_EXT = 0x83C3, + GL_MAX_TEXTURE_COORD_SETS_EXT = 0x83C4, + GL_TEXTURE_ENV_COORD_SET_EXT = 0x83C5, + GL_TEXTURE0_EXT = 0x83C6, + GL_TEXTURE1_EXT = 0x83C7, + GL_TEXTURE2_EXT = 0x83C8, + GL_TEXTURE3_EXT = 0x83C9, + + /* GL_ARB_multitexture */ + GL_ACTIVE_TEXTURE_ARB = 0x84E0, + GL_CLIENT_ACTIVE_TEXTURE_ARB = 0x84E1, + GL_MAX_TEXTURE_UNITS_ARB = 0x84E2, + GL_TEXTURE0_ARB = 0x84C0, + GL_TEXTURE1_ARB = 0x84C1, + GL_TEXTURE2_ARB = 0x84C2, + GL_TEXTURE3_ARB = 0x84C3, + + /* GL_EXT_texture_env_combine */ + GL_COMBINE_EXT = 0x8570, + GL_COMBINE_RGB_EXT = 0x8571, + GL_COMBINE_ALPHA_EXT = 0x8572, + GL_RGB_SCALE_EXT = 0x8573, + GL_ADD_SIGNED_EXT = 0x8574, + GL_INTERPOLATE_EXT = 0x8575, + GL_CONSTANT_EXT = 0x8576, + GL_PRIMARY_COLOR_EXT = 0x8577, + GL_PREVIOUS_EXT = 0x8578, + GL_SOURCE0_RGB_EXT = 0x8580, + GL_SOURCE1_RGB_EXT = 0x8581, + GL_SOURCE2_RGB_EXT = 0x8582, + GL_SOURCE0_ALPHA_EXT = 0x8588, + GL_SOURCE1_ALPHA_EXT = 0x8589, + GL_SOURCE2_ALPHA_EXT = 0x858A, + GL_OPERAND0_RGB_EXT = 0x8590, + GL_OPERAND1_RGB_EXT = 0x8591, + GL_OPERAND2_RGB_EXT = 0x8592, + GL_OPERAND0_ALPHA_EXT = 0x8598, + GL_OPERAND1_ALPHA_EXT = 0x8599, + GL_OPERAND2_ALPHA_EXT = 0x859A, + + /* GL_EXT_clip_volume_hint */ + GL_CLIP_VOLUME_CLIPPING_HINT_EXT = 0x80F0, + + /* GL_EXT_compiled_vertex_array */ + GL_ARRAY_ELEMENT_LOCK_FIRST_EXT = 0x81A8, + GL_ARRAY_ELEMENT_LOCK_COUNT_EXT = 0x81A9, + + /* GL_EXT_texture_filter_anisotropic */ + GL_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE, + GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FF, + + /* GL_EXT_texture_lod_bias */ + GL_MAX_TEXTURE_LOD_BIAS_EXT = 0x84FD, + GL_TEXTURE_FILTER_CONTROL_EXT = 0x8500, + GL_TEXTURE_LOD_BIAS_EXT = 0x8501, + + /* GL_SGIS_texture_edge_clamp */ + GL_CLAMP_TO_EDGE_SGIS = 0x812F, + + /* GL_NV_vertex_array_range & GL_NV_fence */ + GL_ALL_COMPLETED_NV = 0x84F2, + GL_FENCE_STATUS_NV = 0x84F3, + GL_FENCE_CONDITION_NV = 0x84F4, + GL_VERTEX_ARRAY_RANGE_NV = 0x851D, + GL_VERTEX_ARRAY_RANGE_LENGTH_NV = 0x851E, + GL_VERTEX_ARRAY_RANGE_VALID_NV = 0x851F, + GL_MAX_VERTEX_ARRAY_RANGE_ELEMENT_NV = 0x8520, + GL_VERTEX_ARRAY_RANGE_POINTER_NV = 0x8521, + + /* ATI GL_ATI_pn_triangles */ + GL_PN_TRIANGLES_ATI = 0x87F0, + GL_MAX_PN_TRIANGLES_TESSELATION_LEVEL_ATI = 0x87F1, + GL_PN_TRIANGLES_POINT_MODE_ATI = 0x87F2, + GL_PN_TRIANGLES_NORMAL_MODE_ATI = 0x87F3, + GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI = 0x87F4, + GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI = 0x87F5, + GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI = 0x87F6, + GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI = 0x87F7, + GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI = 0x87F8, + + /* 3DFX T-Buffer */ + GL_MULTISAMPLE_BIT_3DFX = 0x20000000, + GL_MULTISAMPLE_3DFX = 0x86B2, + GL_SAMPLE_BUFFERS_3DFX = 0x86B3, + GL_SAMPLES_3DFX = 0x86B4, + + /* occlussion test and query */ + GL_OCCLUSION_TEST_HP = 0x8165, + GL_OCCLUSION_TEST_RESULT_HP = 0x8166, + GL_PIXEL_COUNTER_BITS_NV = 0x8864, + GL_CURRENT_OCCLUSION_QUERY_ID_NV = 0x8865, + GL_PIXEL_COUNT_NV = 0x8866, + GL_PIXEL_COUNT_AVAILABLE_NV = 0x8867, + + /* WGL extensions */ + WGL_NUMBER_PIXEL_FORMATS_EXT = 0x2000, + WGL_DRAW_TO_WINDOW_EXT = 0x2001, + WGL_DRAW_TO_BITMAP_EXT = 0x2002, + WGL_ACCELERATION_EXT = 0x2003, + WGL_NEED_PALETTE_EXT = 0x2004, + WGL_NEED_SYSTEM_PALETTE_EXT = 0x2005, + WGL_SWAP_LAYER_BUFFERS_EXT = 0x2006, + WGL_SWAP_METHOD_EXT = 0x2007, + WGL_NUMBER_OVERLAYS_EXT = 0x2008, + WGL_NUMBER_UNDERLAYS_EXT = 0x2009, + WGL_TRANSPARENT_EXT = 0x200A, + WGL_TRANSPARENT_VALUE_EXT = 0x200B, + WGL_SHARE_DEPTH_EXT = 0x200C, + WGL_SHARE_STENCIL_EXT = 0x200D, + WGL_SHARE_ACCUM_EXT = 0x200E, + WGL_SUPPORT_GDI_EXT = 0x200F, + WGL_SUPPORT_OPENGL_EXT = 0x2010, + WGL_DOUBLE_BUFFER_EXT = 0x2011, + WGL_STEREO_EXT = 0x2012, + WGL_PIXEL_TYPE_EXT = 0x2013, + WGL_COLOR_BITS_EXT = 0x2014, + WGL_RED_BITS_EXT = 0x2015, + WGL_RED_SHIFT_EXT = 0x2016, + WGL_GREEN_BITS_EXT = 0x2017, + WGL_GREEN_SHIFT_EXT = 0x2018, + WGL_BLUE_BITS_EXT = 0x2019, + WGL_BLUE_SHIFT_EXT = 0x201A, + WGL_ALPHA_BITS_EXT = 0x201B, + WGL_ALPHA_SHIFT_EXT = 0x201C, + WGL_ACCUM_BITS_EXT = 0x201D, + WGL_ACCUM_RED_BITS_EXT = 0x201E, + WGL_ACCUM_GREEN_BITS_EXT = 0x201F, + WGL_ACCUM_BLUE_BITS_EXT = 0x2020, + WGL_ACCUM_ALPHA_BITS_EXT = 0x2021, + WGL_DEPTH_BITS_EXT = 0x2022, + WGL_STENCIL_BITS_EXT = 0x2023, + WGL_AUX_BUFFERS_EXT = 0x2024, + + WGL_NO_ACCELERATION_EXT = 0x2025, + WGL_GENERIC_ACCELERATION_EXT = 0x2026, + WGL_FULL_ACCELERATION_EXT = 0x2027, + WGL_SWAP_EXCHANGE_EXT = 0x2028, + WGL_SWAP_COPY_EXT = 0x2029, + WGL_SWAP_UNDEFINED_EXT = 0x202A, + WGL_TYPE_RGBA_EXT = 0x202B, + WGL_TYPE_COLORINDEX_EXT = 0x202C, + + WGL_NUMBER_PIXEL_FORMATS_ARB = 0x2000, + WGL_DRAW_TO_WINDOW_ARB = 0x2001, + WGL_DRAW_TO_BITMAP_ARB = 0x2002, + WGL_ACCELERATION_ARB = 0x2003, + WGL_NEED_PALETTE_ARB = 0x2004, + WGL_NEED_SYSTEM_PALETTE_ARB = 0x2005, + WGL_SWAP_LAYER_BUFFERS_ARB = 0x2006, + WGL_SWAP_METHOD_ARB = 0x2007, + WGL_NUMBER_OVERLAYS_ARB = 0x2008, + WGL_NUMBER_UNDERLAYS_ARB = 0x2009, + WGL_TRANSPARENT_ARB = 0x200A, + WGL_TRANSPARENT_RED_VALUE_ARB = 0x2037, + WGL_TRANSPARENT_GREEN_VALUE_ARB = 0x2038, + WGL_TRANSPARENT_BLUE_VALUE_ARB = 0x2039, + WGL_TRANSPARENT_ALPHA_VALUE_ARB = 0x203A, + WGL_TRANSPARENT_INDEX_VALUE_ARB = 0x203B, + WGL_SHARE_DEPTH_ARB = 0x200C, + WGL_SHARE_STENCIL_ARB = 0x200D, + WGL_SHARE_ACCUM_ARB = 0x200E, + WGL_SUPPORT_GDI_ARB = 0x200F, + WGL_SUPPORT_OPENGL_ARB = 0x2010, + WGL_DOUBLE_BUFFER_ARB = 0x2011, + WGL_STEREO_ARB = 0x2012, + WGL_PIXEL_TYPE_ARB = 0x2013, + WGL_COLOR_BITS_ARB = 0x2014, + WGL_RED_BITS_ARB = 0x2015, + WGL_RED_SHIFT_ARB = 0x2016, + WGL_GREEN_BITS_ARB = 0x2017, + WGL_GREEN_SHIFT_ARB = 0x2018, + WGL_BLUE_BITS_ARB = 0x2019, + WGL_BLUE_SHIFT_ARB = 0x201A, + WGL_ALPHA_BITS_ARB = 0x201B, + WGL_ALPHA_SHIFT_ARB = 0x201C, + WGL_ACCUM_BITS_ARB = 0x201D, + WGL_ACCUM_RED_BITS_ARB = 0x201E, + WGL_ACCUM_GREEN_BITS_ARB = 0x201F, + WGL_ACCUM_BLUE_BITS_ARB = 0x2020, + WGL_ACCUM_ALPHA_BITS_ARB = 0x2021, + WGL_DEPTH_BITS_ARB = 0x2022, + WGL_STENCIL_BITS_ARB = 0x2023, + WGL_AUX_BUFFERS_ARB = 0x2024, + + WGL_NO_ACCELERATION_ARB = 0x2025, + WGL_GENERIC_ACCELERATION_ARB = 0x2026, + WGL_FULL_ACCELERATION_ARB = 0x2027, + WGL_SWAP_EXCHANGE_ARB = 0x2028, + WGL_SWAP_COPY_ARB = 0x2029, + WGL_SWAP_UNDEFINED_ARB = 0x202A, + WGL_TYPE_RGBA_ARB = 0x202B, + WGL_TYPE_COLORINDEX_ARB = 0x202C, + + WGL_SAMPLE_BUFFERS_3DFX = 0x2060, + WGL_SAMPLES_3DFX = 0x2061, + + + /* OpenGL 1.2 */ + GL_RESCALE_NORMAL = 0x803A, + GL_CLAMP_TO_EDGE = 0x812F, + GL_MAX_ELEMENTS_VERTICES = 0xF0E8, + GL_MAX_ELEMENTS_INDICES = 0xF0E9, + GL_BGR = 0x80E0, + GL_BGRA = 0x80E1, + GL_UNSIGNED_BYTE_3_3_2 = 0x8032, + GL_UNSIGNED_BYTE_2_3_3_REV = 0x8362, + GL_UNSIGNED_SHORT_5_6_5 = 0x8363, + GL_UNSIGNED_SHORT_5_6_5_REV = 0x8364, + GL_UNSIGNED_SHORT_4_4_4_4 = 0x8033, + GL_UNSIGNED_SHORT_4_4_4_4_REV = 0x8365, + GL_UNSIGNED_SHORT_5_5_5_1 = 0x8034, + GL_UNSIGNED_SHORT_1_5_5_5_REV = 0x8366, + GL_UNSIGNED_INT_8_8_8_8 = 0x8035, + GL_UNSIGNED_INT_8_8_8_8_REV = 0x8367, + GL_UNSIGNED_INT_10_10_10_2 = 0x8036, + GL_UNSIGNED_INT_2_10_10_10_REV = 0x8368, + GL_LIGHT_MODEL_COLOR_CONTROL = 0x81F8, + GL_SINGLE_COLOR = 0x81F9, + GL_SEPARATE_SPECULAR_COLOR = 0x81FA, + GL_TEXTURE_MIN_LOD = 0x813A, + GL_TEXTURE_MAX_LOD = 0x813B, + GL_TEXTURE_BASE_LEVEL = 0x813C, + GL_TEXTURE_MAX_LEVEL = 0x813D +} GLenum; + + +/* GL_NO_ERROR must be zero */ +#define GL_NO_ERROR 0 + +enum { + GL_CURRENT_BIT = 0x00000001, + GL_POINT_BIT = 0x00000002, + GL_LINE_BIT = 0x00000004, + GL_POLYGON_BIT = 0x00000008, + GL_POLYGON_STIPPLE_BIT = 0x00000010, + GL_PIXEL_MODE_BIT = 0x00000020, + GL_LIGHTING_BIT = 0x00000040, + GL_FOG_BIT = 0x00000080, + GL_DEPTH_BUFFER_BIT = 0x00000100, + GL_ACCUM_BUFFER_BIT = 0x00000200, + GL_STENCIL_BUFFER_BIT = 0x00000400, + GL_VIEWPORT_BIT = 0x00000800, + GL_TRANSFORM_BIT = 0x00001000, + GL_ENABLE_BIT = 0x00002000, + GL_COLOR_BUFFER_BIT = 0x00004000, + GL_HINT_BIT = 0x00008000, + GL_EVAL_BIT = 0x00010000, + GL_LIST_BIT = 0x00020000, + GL_TEXTURE_BIT = 0x00040000, + GL_SCISSOR_BIT = 0x00080000, + GL_ALL_ATTRIB_BITS = 0x000fffff +}; + + +enum { + GL_CLIENT_PIXEL_STORE_BIT = 0x00000001, + GL_CLIENT_VERTEX_ARRAY_BIT = 0x00000002, + GL_CLIENT_ALL_ATTRIB_BITS = 0x0000FFFF +}; + +typedef unsigned int GLbitfield; + + +/* + * + * Data types (may be architecture dependent in some cases) + * + */ + +/* C type GL type storage */ +/*-------------------------------------------------------------------------*/ +typedef void GLvoid; +typedef unsigned char GLboolean; +typedef signed char GLbyte; /* 1-byte signed */ +typedef short GLshort; /* 2-byte signed */ +typedef int GLint; /* 4-byte signed */ +typedef unsigned char GLubyte; /* 1-byte unsigned */ +typedef unsigned short GLushort; /* 2-byte unsigned */ +typedef unsigned int GLuint; /* 4-byte unsigned */ +typedef int GLsizei; /* 4-byte signed */ +typedef float GLfloat; /* single precision float */ +typedef float GLclampf; /* single precision float in [0,1] */ +typedef double GLdouble; /* double precision float */ +typedef double GLclampd; /* double precision float in [0,1] */ + + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Light/Gradient.h b/Sources/Engine/Light/Gradient.h new file mode 100644 index 0000000..1f4e95b --- /dev/null +++ b/Sources/Engine/Light/Gradient.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_GRADIENT_H +#define SE_INCL_GRADIENT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +class CGradientParameters { +public: + FLOAT3D gp_vGradientDir; // gradient direction in absolute space + FLOAT gp_fH0; // position of color 0 + FLOAT gp_fH1; // position of color 1 + BOOL gp_bDark; // if dark light + + COLOR gp_col0; // color 0 + COLOR gp_col1; // color 1 +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Light/LayerMaker.cpp b/Sources/Engine/Light/LayerMaker.cpp new file mode 100644 index 0000000..54ff3bb --- /dev/null +++ b/Sources/Engine/Light/LayerMaker.cpp @@ -0,0 +1,878 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//#include +//#include + +extern INDEX _ctShadowLayers=0; +extern INDEX _ctShadowClusters=0; + + +// class used for making shadow layers (used only locally) +class CLayerMaker { +// implementation: +public: + // information about current polygon + CBrushPolygon *lm_pbpoPolygon; // the polygon + CBrushShadowMap *lm_pbsmShadowMap; // the shadow map on the polygon + FLOAT lm_fMipFactor; // the mip factor of this polygon + CWorld *lm_pwoWorld; // world for casting rays in + CBrushShadowLayer *lm_pbslLayer;// current layer + + // dimensions of currently processed shadow map + MEX lm_mexSizeU; // size in mex + MEX lm_mexSizeV; + MEX lm_mexOffsetU; // offsets in mex + MEX lm_mexOffsetV; + INDEX lm_iMipLevel; // mip level + + PIX lm_pixSizeU; // size in pixels + PIX lm_pixSizeV; + struct MipmapTable lm_mmtPolygonMask; // mip map table of the polygon mask + + PIX lm_pixLayerMinU; // layer rectangle inside shadow map + PIX lm_pixLayerMinV; + PIX lm_pixLayerSizeU; + PIX lm_pixLayerSizeV; + FLOAT lm_fpixHotU; + FLOAT lm_fpixHotV; + FLOAT lm_fLightPlaneDistance; + struct MipmapTable lm_mmtLayer; // mip map table of the layer + + UBYTE *lm_pubPolygonMask; // bit-packed mask of where the current polygon is + UBYTE *lm_pubLayer; // bit-packed mask of where the current light lights the polygon + + FLOAT3D lm_vLight; // position of the light source + + // gradients for shadow map walking + FLOAT3D lm_vO; // upper left corner of shadow map in 3D + FLOAT3D lm_vStepU; // step between pixels in same row + FLOAT3D lm_vStepV; // step between rows + + ANGLE3D lm_aMappingOrientation; // orientation of the texture map in 3D + ANGLE3D lm_aInverseMappingOrientation; + FLOATmatrix3D lm_mToInverseMapping; // matrix for parallel lights + + CLightSource *lm_plsLight; // current light + + // remember general data + void CalculateData(void); + + // make bit-packed mask of where the polygon is in the shadow map + void MakePolygonMask(void); + + // make shadow mask for the light + ULONG MakeShadowMask(CBrushShadowLayer *pbsl); + ULONG MakeOneShadowMaskMip(INDEX iMip); + // flip shadow mask around V axis (for parallel lights) + void FlipShadowMask(INDEX iMip); + + /* Spread the shadow towards pixels outside of polygon. */ + void SpreadShadowMaskOutwards(void); + /* Spread the shadow towards pixels inside of polygon. */ + void SpreadShadowMaskInwards(void); + +public: +// interface: + /* Constructor. */ + CLayerMaker(void); + /* Cast shadows for all layers of a given polygon. */ + BOOL CreateLayers(CBrushPolygon &bpo, CWorld &woWorld, BOOL bDoDirectionalLights); +}; + +/* Make mip-maps of the shadow mask. */ +static void MakeMipmapsForMask(UBYTE *pubMask, PIX pixSizeU, PIX pixSizeV, SLONG slTotalSize) +{ + // remember pointer after first mip map + UBYTE *pubSecond = pubMask+pixSizeU*pixSizeV; + // start at the first mip map + UBYTE *pubThis = pubMask; + PIX pixThisSizeU = pixSizeU; + PIX pixThisSizeV = pixSizeV; + UBYTE *pubNext; + PIX pixNextSizeU; + PIX pixNextSizeV; + // repeat + for(;;) { + // calculate size and position of next mip map + pubNext = pubThis+pixThisSizeU*pixThisSizeV; + pixNextSizeU = pixThisSizeU/2; + pixNextSizeV = pixThisSizeV/2; + + // if the next mip map is too small + if (pixNextSizeU<1 || pixNextSizeV<1) { + // stop + break; + } + // for each pixel in the next mip map + UBYTE *pub = pubNext; + for (PIX pixNextV=0; pixNextVsm_mexWidth; + lm_mexSizeV = lm_pbsmShadowMap->sm_mexHeight; + lm_mexOffsetU = lm_pbsmShadowMap->sm_mexOffsetX; + lm_mexOffsetV = lm_pbsmShadowMap->sm_mexOffsetY; + lm_iMipLevel = lm_pbsmShadowMap->sm_iFirstMipLevel; + lm_pixSizeU = lm_mexSizeU>>lm_iMipLevel; + lm_pixSizeV = lm_mexSizeV>>lm_iMipLevel; + + // find mip-mapping information for the polygon mask + MakeMipmapTable( lm_pixSizeU, lm_pixSizeV, lm_mmtPolygonMask); + + CEntity *penWithPolygon = lm_pbpoPolygon->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + ASSERT(penWithPolygon!=NULL); + const FLOATmatrix3D &mPolygonRotation = penWithPolygon->en_mRotation; + const FLOAT3D &vPolygonTranslation = penWithPolygon->GetPlacement().pl_PositionVector; + + // get first pixel in texture in 3D + Vector vmex0; + vmex0(1) = -lm_mexOffsetU; //+(1<<(lm_iMipLevel-1)); + vmex0(2) = -lm_mexOffsetV; //+(1<<(lm_iMipLevel-1)); + lm_pbpoPolygon->bpo_mdShadow.GetSpaceCoordinates( + lm_pbpoPolygon->bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, + vmex0, lm_vO); + lm_vO = lm_vO*mPolygonRotation+vPolygonTranslation; + // get steps for walking in texture in 3D + Vector vmexU, vmexV; + vmexU(1) = (1<bpo_mdShadow.GetSpaceCoordinates( + lm_pbpoPolygon->bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, + vmexU, lm_vStepU); + lm_vStepU = lm_vStepU*mPolygonRotation+vPolygonTranslation; + lm_pbpoPolygon->bpo_mdShadow.GetSpaceCoordinates( + lm_pbpoPolygon->bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, + vmexV, lm_vStepV); + lm_vStepV = lm_vStepV*mPolygonRotation+vPolygonTranslation; + lm_vStepU-=lm_vO; + lm_vStepV-=lm_vO; + + // make 3 orthogonal vectors that define mapping orientation + FLOAT3D vX = lm_vStepU; + FLOAT3D vY = -lm_vStepV; + FLOAT3D vZ = vX*vY; + // make a rotation matrix from those vectors + vX.Normalize(); + vY.Normalize(); + vZ.Normalize(); + FLOATmatrix3D mOrientation; + mOrientation(1,1) = vX(1); mOrientation(1,2) = vY(1); mOrientation(1,3) = vZ(1); + mOrientation(2,1) = vX(2); mOrientation(2,2) = vY(2); mOrientation(2,3) = vZ(2); + mOrientation(3,1) = vX(3); mOrientation(3,2) = vY(3); mOrientation(3,3) = vZ(3); + FLOATmatrix3D mInvOrientation; + mInvOrientation(1,1) = -vX(1); mInvOrientation(1,2) = vY(1); mInvOrientation(1,3) = -vZ(1); + mInvOrientation(2,1) = -vX(2); mInvOrientation(2,2) = vY(2); mInvOrientation(2,3) = -vZ(2); + mInvOrientation(3,1) = -vX(3); mInvOrientation(3,2) = vY(3); mInvOrientation(3,3) = -vZ(3); + // make orientation angles from the matrix + DecomposeRotationMatrixNoSnap(lm_aMappingOrientation, mOrientation); + DecomposeRotationMatrixNoSnap(lm_aInverseMappingOrientation, mInvOrientation); + + // remember matrix for parallel lights + lm_mToInverseMapping = !mInvOrientation; +} + +// test if a point is inside a brush polygon +inline BOOL TestPointInPolygon(CBrushPolygon &bpo, const FLOAT3D &v) +{ + // find major axes of the polygon plane + INDEX iMajorAxis1 = bpo.bpo_pbplPlane->bpl_iPlaneMajorAxis1; + INDEX iMajorAxis2 = bpo.bpo_pbplPlane->bpl_iPlaneMajorAxis2; + // if the point is not inside the bounding box of polygon (projected to the major plane) + if (v(iMajorAxis1)bpo.bpo_boxBoundingBox.Max()(iMajorAxis1) + ||v(iMajorAxis2)bpo.bpo_boxBoundingBox.Max()(iMajorAxis2) + ) { + // it is not inside the polygon + return FALSE; + } + + // create an intersector + CIntersector isIntersector(v(iMajorAxis1), v(iMajorAxis2)); + // for all edges in the polygon + FOREACHINSTATICARRAY(bpo.bpo_abpePolygonEdges, CBrushPolygonEdge, itbpe) { + // get edge vertices (edge direction is irrelevant here!) + const FLOAT3D &vVertex0 = itbpe->bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + const FLOAT3D &vVertex1 = itbpe->bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + // pass the edge to the intersector + isIntersector.AddEdge( + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2), + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2)); + } + + // ask the intersector if the point is inside the polygon + return isIntersector.IsIntersecting(); +} + +///////////////////////////////////////////////////////////////////// +// CLayerMaker + +/* + * Constructor. + */ +CLayerMaker::CLayerMaker(void) +{ +} + +/* Spread the shadow towards pixels outside of polygon. */ +void CLayerMaker::SpreadShadowMaskOutwards(void) +{ + // for each mip map of the layer + for(INDEX iMipmap=0; iMipmap>iMipmap; + PIX pixLayerMinV = lm_pixLayerMinV>>iMipmap; + PIX pixLayerSizeU = lm_pixLayerSizeU>>iMipmap; + PIX pixLayerSizeV = lm_pixLayerSizeV>>iMipmap; + PIX pixSizeU = lm_pixSizeU>>iMipmap; + PIX pixSizeV = lm_pixSizeV>>iMipmap; + PIX pixSizeULog2 = FastLog2(lm_pixSizeU)-iMipmap; + UBYTE *pubLayer = lm_pubLayer+lm_mmtLayer.mmt_aslOffsets[iMipmap]; + UBYTE *pubPolygonMask = lm_pubPolygonMask+lm_mmtPolygonMask.mmt_aslOffsets[iMipmap]; + + SLONG slOffsetLayer = 0; + // for each pixel in the layer shadow mask + for (PIX pixLayerV=0; pixLayerV=0) \ + &&(pixLayerU+(du)=0) \ + &&(pixLayerV+(dv)0) && (ctLighted>ctInPolygon/2)) { + // make this one lighted + pubLayer[slOffsetLayer] = 255; + // otherwise + } else { + // make this one shadowed + pubLayer[slOffsetLayer] = 0; + } + // if the pixel is inside the polygon + } else { + NOTHING; + } + + slOffsetLayer++; + } + } + } +} + +/* Spread the shadow towards pixels inside of polygon. */ +void CLayerMaker::SpreadShadowMaskInwards(void) +{ + // for each mip map of the layer + for(INDEX iMipmap=0; iMipmap>iMipmap; + PIX pixLayerMinV = lm_pixLayerMinV>>iMipmap; + PIX pixLayerSizeU = lm_pixLayerSizeU>>iMipmap; + PIX pixLayerSizeV = lm_pixLayerSizeV>>iMipmap; + PIX pixSizeU = lm_pixSizeU>>iMipmap; + PIX pixSizeV = lm_pixSizeV>>iMipmap; + PIX pixSizeULog2 = FastLog2(lm_pixSizeU)-iMipmap; + UBYTE *pubLayer = lm_pubLayer+lm_mmtLayer.mmt_aslOffsets[iMipmap]; + UBYTE *pubPolygonMask = lm_pubPolygonMask+lm_mmtPolygonMask.mmt_aslOffsets[iMipmap]; + + SLONG slOffsetLayer = 0; + // for each pixel in the layer shadow mask + for (PIX pixLayerV=0; pixLayerV=0) \ + &&(pixLayerU+(du)=0) \ + &&(pixLayerV+(dv)0) { + // if some are not lighted + if (ctLightedbsm_pubPolygonMask!=NULL) { + // convert it from bit-packed into byte-packed mask + ConvertBitsToBytes( + lm_pbsmShadowMap->bsm_pubPolygonMask, + lm_pubPolygonMask, + lm_mmtPolygonMask.mmt_slTotalSize); + + } else { + UBYTE *pub = lm_pubPolygonMask; + // for each mip-map + for (INDEX iMipmap=0; iMipmap>iMipmap; pixV++) { + FLOAT3D vPoint = vRow; + for (PIX pixU=0; pixU>iMipmap; pixU++) { + // if the point is in the polygon + if (TestPointInPolygon(*lm_pbpoPolygon, vPoint)) { + // set the pixel + *pub = 255; + // if the point is not in the polygon + } else { + // clear the pixel + *pub = 0; + } + // go to the next pixel + pub++; + vPoint+=lm_vStepU*FLOAT(1<bsm_pubPolygonMask = (UBYTE *)AllocMemory((lm_mmtPolygonMask.mmt_slTotalSize+7)/8); + ConvertBytesToBits( + lm_pubPolygonMask, + lm_pbsmShadowMap->bsm_pubPolygonMask, + lm_mmtPolygonMask.mmt_slTotalSize); + } +} + +// flip shadow mask around V axis (for parallel lights) +void CLayerMaker::FlipShadowMask(INDEX iMip) +{ + PIX pixLayerMinU = lm_pixLayerMinU>>iMip; + PIX pixLayerMinV = lm_pixLayerMinV>>iMip; + PIX pixLayerSizeU = lm_pixLayerSizeU>>iMip; + PIX pixLayerSizeV = lm_pixLayerSizeV>>iMip; + UBYTE *pubLayer = lm_pubLayer+lm_mmtLayer.mmt_aslOffsets[iMip]; + + UBYTE *pubRow = pubLayer; + // for each row + for (PIX pixV=0; pixVbsl_plsLightSource->ls_ulFlags&LSF_CASTSHADOWS) || + (lm_pbpoPolygon->bpo_ulFlags&BPOF_DOESNOTRECEIVESHADOW) ) { + // do nothing + return BSLF_ALLLIGHT; + } + + // remember current layer and its light source + lm_plsLight = pbsl->bsl_plsLightSource; + lm_pbslLayer = pbsl; + lm_vLight = lm_plsLight->ls_penEntity->GetPlacement().pl_PositionVector; + + // find the influenced rectangle + CLightRectangle lr; + lm_pbsmShadowMap->FindLightRectangle(*lm_plsLight, lr); + ASSERT(lr.lr_pixSizeU == lm_pbslLayer->bsl_pixSizeU); + ASSERT(lr.lr_pixSizeV == lm_pbslLayer->bsl_pixSizeV); + lm_fpixHotU = lr.lr_fpixHotU; + lm_fpixHotV = lr.lr_fpixHotV; + lm_fLightPlaneDistance = lr.lr_fLightPlaneDistance; + lm_pixLayerMinU = lr.lr_pixMinU; + lm_pixLayerMinV = lr.lr_pixMinV; + lm_pixLayerSizeU= lr.lr_pixSizeU; + lm_pixLayerSizeV= lr.lr_pixSizeV; + // find mip-mapping information for the rectangle + MakeMipmapTable(lm_pixLayerSizeU, lm_pixLayerSizeV, lm_mmtLayer); + + ASSERT(lr.lr_pixSizeU == lm_pbslLayer->bsl_pixSizeU); + ASSERT(lr.lr_pixSizeV == lm_pbslLayer->bsl_pixSizeV); + ASSERT(lr.lr_pixSizeU <= lm_pixSizeU); + ASSERT(lr.lr_pixSizeV <= lm_pixSizeV); + + // if there is no influence, do nothing + if ((lr.lr_pixSizeU==0) || (lr.lr_pixSizeV==0)) return BSLF_ALLDARK; + + lm_pbslLayer->bsl_pixMinU = lr.lr_pixMinU; + lm_pbslLayer->bsl_pixMinV = lr.lr_pixMinV; + lm_pbslLayer->bsl_pixSizeU = lr.lr_pixSizeU; + lm_pbslLayer->bsl_pixSizeV = lr.lr_pixSizeV; + lm_pbslLayer->bsl_slSizeInPixels = lm_mmtLayer.mmt_slTotalSize; + + // allocate shadow mask for the light (+8 is safety wall for fast conversions) + lm_pubLayer = (UBYTE *)AllocMemory(lm_mmtLayer.mmt_slTotalSize+8); + const FLOAT fEpsilon = (1<bpo_ulFlags & BPOF_ACCURATESHADOWS) { + // make each mip-map of mask for itself + for(INDEX iMip=0; iMipbpo_ulFlags&BPOF_DARKCORNERS)) { + SpreadShadowMaskOutwards(); + } else { + SpreadShadowMaskInwards(); + SpreadShadowMaskOutwards(); + } + + // convert the shadow mask from byte-packed into bit-packed mask + ConvertBytesToBits(lm_pubLayer, lm_pubLayer, lm_mmtLayer.mmt_slTotalSize); + ShrinkMemory((void **)&lm_pubLayer, (lm_mmtLayer.mmt_slTotalSize+7)/8); + pbsl->bsl_pubLayer = lm_pubLayer; + + // update statistics + _ctShadowLayers++; + _ctShadowClusters+=lm_mmtLayer.mmt_slTotalSize; + + return ulLighted; +} + +ULONG CLayerMaker::MakeOneShadowMaskMip(INDEX iMip) +{ + ULONG ulLighted=BSLF_ALLLIGHT|BSLF_ALLDARK; + + PIX pixLayerMinU = lm_pixLayerMinU>>iMip; + PIX pixLayerMinV = lm_pixLayerMinV>>iMip; + PIX pixLayerSizeU = lm_pixLayerSizeU>>iMip; + PIX pixLayerSizeV = lm_pixLayerSizeV>>iMip; + INDEX iMipLevel = lm_iMipLevel+iMip; + FLOAT3D vO = lm_vO+(lm_vStepU+lm_vStepV)*(FLOAT(1<ls_ulFlags&LSF_DIRECTIONAL) { + // prepare parallel projection as if viewing from polygon and the shadow map is screen + CParallelProjection3D prProjection; + prProjection.ScreenBBoxL() = FLOATaabbox2D( + FLOAT2D(pixLayerMinU, + pixLayerMinV), + FLOAT2D(pixLayerMinU+pixLayerSizeU, + pixLayerMinV+pixLayerSizeV) + ); + prProjection.AspectRatioL() = 1.0f; + prProjection.NearClipDistanceL() = 0.00f; + prProjection.pr_vZoomFactors(1) = + prProjection.pr_vZoomFactors(2) = 1024.0f/(1<ls_penEntity->GetPlacement().pl_OrientationAngle, + vDirection); + // if polygon is turned away from the light + if ((vDirection%(const FLOAT3D &)lm_pbpoPolygon->bpo_pbplPlane->bpl_plAbsolute)>-0.001) { + // layer is all dark + return BSLF_ALLDARK; + } + + vDirection = vDirection*lm_mToInverseMapping; + + prProjection.pr_vStepFactors(1) = -vDirection(1)/vDirection(3); + prProjection.pr_vStepFactors(2) = -vDirection(2)/vDirection(3); + + prProjection.pr_vStepFactors(1)*=prProjection.pr_vZoomFactors(1); + prProjection.pr_vStepFactors(2)*=prProjection.pr_vZoomFactors(2); + + CPlacement3D plCenter; + plCenter.pl_OrientationAngle = lm_aInverseMappingOrientation; + plCenter.pl_PositionVector = + vO + +vStepU*(FLOAT(pixLayerSizeU)/2-0.5f) // !!!! + +vStepV*(FLOAT(pixLayerSizeV)/2);//+5.0f); + prProjection.ViewerPlacementL() = plCenter; + + // render the view to the shadow layer (but ignore the target polygon) + CAnyProjection3D apr; + apr = prProjection; + ULONG ulFlagsBefore = lm_pbpoPolygon->bpo_ulFlags; + lm_pbpoPolygon->bpo_ulFlags |= BPOF_INVISIBLE; + ulLighted&=RenderShadows(*lm_pwoWorld, *(CEntity*)NULL, apr, + lm_pbpoPolygon->bpo_boxBoundingBox, pubLayer, pixLayerSizeU, pixLayerSizeV, + lm_plsLight->ls_ubPolygonalMask); + lm_pbpoPolygon->bpo_ulFlags = ulFlagsBefore; + + // flip the shadow mask around v axis (left-right) + FlipShadowMask(iMip); + + // if the light is point + } else { + + // prepare perspective projection as if viewing from light and the shadow map is screen + CPerspectiveProjection3D prProjection; + if( !(lm_pbpoPolygon->bpo_ulFlags&BPOF_DARKCORNERS)) { + prProjection.ScreenBBoxL() = FLOATaabbox2D( + FLOAT2D(pixLayerMinU-fpixHotU+1, + pixLayerMinV-fpixHotV+1), + FLOAT2D(pixLayerMinU+pixLayerSizeU-fpixHotU+1, + pixLayerMinV+pixLayerSizeV-fpixHotV+1) + ); + } else { + prProjection.ScreenBBoxL() = FLOATaabbox2D( + FLOAT2D(pixLayerMinU-fpixHotU, + pixLayerMinV-fpixHotV), + FLOAT2D(pixLayerMinU+pixLayerSizeU-fpixHotU, + pixLayerMinV+pixLayerSizeV-fpixHotV) + ); + } + prProjection.AspectRatioL() = 1.0f; + + prProjection.NearClipDistanceL() = lm_plsLight->ls_fNearClipDistance; + prProjection.FarClipDistanceL() + = lm_fLightPlaneDistance-lm_plsLight->ls_fFarClipDistance; //-fEpsilon/2; !!!! use minimal epsilon for polygon + prProjection.ppr_fMetersPerPixel = (1<bpo_ulFlags; + lm_pbpoPolygon->bpo_ulFlags |= BPOF_INVISIBLE; + // if light is not illumination light + if (lm_plsLight->ls_ubPolygonalMask==0) { + // just render starting at the light entity position + ulLighted&=RenderShadows(*lm_pwoWorld, *lm_plsLight->ls_penEntity, + apr, FLOATaabbox3D(), + pubLayer, pixLayerSizeU, pixLayerSizeV, + lm_plsLight->ls_ubPolygonalMask); + // if light is illumination light + } else { + // add entire box around target polygon and light position to rendering + FLOATaabbox3D box = lm_pbpoPolygon->bpo_boxBoundingBox; + box|=lm_plsLight->ls_penEntity->GetPlacement().pl_PositionVector; + ulLighted&=RenderShadows(*lm_pwoWorld, *(CEntity*)NULL, apr, box, + pubLayer, pixLayerSizeU, pixLayerSizeV, + lm_plsLight->ls_ubPolygonalMask); + } + lm_pbpoPolygon->bpo_ulFlags = ulFlagsBefore; + } + + return ulLighted; +} + +/* + * Create a shadow map for a given polygon. + */ +BOOL CLayerMaker::CreateLayers(CBrushPolygon &bpo, CWorld &woWorld, BOOL bDoDirectionalLights) +{ +// __pfWorldEditingProfile.IncrementAveragingCounter(); +// __pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_MAKESHADOWS); + + BOOL bInitialized = FALSE; + BOOL bCalculatedSome = FALSE; + BOOL bSomeAreUncalculated = FALSE; + + // remember the world + lm_pwoWorld = &woWorld; + lm_pbsmShadowMap = &bpo.bpo_smShadowMap; + lm_pbpoPolygon = &bpo; + + // for each layer that should be calculated, but isn't + FORDELETELIST(CBrushShadowLayer, bsl_lnInShadowMap, lm_pbsmShadowMap->bsm_lhLayers, itbsl) { + // if already calculated, or dynamic + if (itbsl->bsl_ulFlags&BSLF_CALCULATED || + itbsl->bsl_plsLightSource->ls_ulFlags&LSF_DYNAMIC) { + // skip it + continue; + } + // if we are not doing directional lights and it is directional + if (!bDoDirectionalLights + && (itbsl->bsl_plsLightSource->ls_ulFlags&LSF_DIRECTIONAL)) { + // skip it + bSomeAreUncalculated = TRUE; + continue; + } + + // if not yet initialized + if( !bInitialized) { + // remember general data + CalculateData(); + // make bit-packed mask of where the polygon is in the shadow map + MakePolygonMask(); + bInitialized = TRUE; + } + + CBrushShadowLayer &bsl = *itbsl; + // mark the layer is calculated + bsl.bsl_ulFlags |= BSLF_CALCULATED; + // make shadow mask for the light + ULONG ulLighted=MakeShadowMask(itbsl); + ASSERT((ulLighted==0) || (ulLighted==BSLF_ALLLIGHT) || (ulLighted==BSLF_ALLDARK)); + bsl.bsl_ulFlags &= ~(BSLF_ALLLIGHT|BSLF_ALLDARK); + bsl.bsl_ulFlags |= ulLighted; + + // if the layer is not needed + if( ulLighted&(BSLF_ALLLIGHT|BSLF_ALLDARK)) { + // free it + if( bsl.bsl_pubLayer!=NULL) FreeMemory( bsl.bsl_pubLayer); + bsl.bsl_pubLayer = NULL; + } + bCalculatedSome = TRUE; + } + + // if was intialized + if( bInitialized) { + // free bit-packed polygon mask + FreeMemory( lm_pubPolygonMask); + } + + // if some new layers have been calculated + if( bCalculatedSome) { + // invalidate mixed layers + bpo.bpo_smShadowMap.Invalidate(); + } + + return bSomeAreUncalculated; +} + +/* + * Create shadow map for the polygon. + */ +void CBrushPolygon::MakeShadowMap(CWorld *pwoWorld, BOOL bDoDirectionalLights) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_MAKESHADOWMAP); + // create new shadow map + CLayerMaker lmMaker; + BOOL bSomeAreUncalculated = lmMaker.CreateLayers(*this, *pwoWorld, bDoDirectionalLights); + // unqueue the shadow map + if (!bSomeAreUncalculated && bpo_smShadowMap.bsm_lnInUncalculatedShadowMaps.IsLinked()) { + bpo_smShadowMap.bsm_lnInUncalculatedShadowMaps.Remove(); + } + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_MAKESHADOWMAP); +} diff --git a/Sources/Engine/Light/LayerMixer.cpp b/Sources/Engine/Light/LayerMixer.cpp new file mode 100644 index 0000000..4898cf2 --- /dev/null +++ b/Sources/Engine/Light/LayerMixer.cpp @@ -0,0 +1,1456 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + +#define ASMOPT 1 + + +extern INDEX shd_bFineQuality; +extern INDEX shd_iFiltering; +extern INDEX shd_iDithering; + +extern const UBYTE *pubClipByte; +extern UBYTE aubSqrt[ SQRTTABLESIZE]; +extern UWORD auw1oSqrt[SQRTTABLESIZE]; +extern UWORD auw1oSqrt[SQRTTABLESIZE]; +// static FLOAT3D _v00; + +// internal class for layer mixing +class CLayerMixer +{ +public: + CBrushShadowMap *lm_pbsmShadowMap; // shadow map whose layers are mixed + CBrushPolygon *lm_pbpoPolygon; // polygon of the shadow map + BOOL lm_bDynamic; // set while doing dynamic light mixing + + // dimensions of currently processed shadow map + MEX lm_mexOffsetU; // offsets in mex + MEX lm_mexOffsetV; + INDEX lm_iFirstLevel; // mip level of first possible mip-map + INDEX lm_iMipLevel; // mip level + INDEX lm_iMipShift; // relative mip level (miplevel-firstlevel) + PIX lm_pixCanvasSizeU; // shadowmap canvas size in pixels + PIX lm_pixCanvasSizeV; + PIX lm_pixPolygonSizeU; // polygon (used part of shadowmap size in pixels + PIX lm_pixPolygonSizeV; + ULONG*lm_pulShadowMap; // buffer for final shadow map + ULONG*lm_pulStaticShadowMap; // precached static shadow map + + // gradients for shadow map walking + FLOAT3D lm_vO; // upper left corner of shadow map in 3D + FLOAT3D lm_vStepU; // step between pixels in same row + FLOAT3D lm_vStepV; // step between rows + FLOAT3D lm_vLightDirection; // light direction for directional light sources + CLightSource *lm_plsLight; // current light source + // color components of current light + COLOR lm_colLight; + COLOR lm_colAmbient; + + // constructor + CLayerMixer( CBrushShadowMap *pbsm, INDEX iFirstMip, INDEX iLastMip, BOOL bDynamic); + + // remember general data + void CalculateData( CBrushShadowMap *pbsm, INDEX iMipmap); + // mix one mip-map + void MixOneMipmap( CBrushShadowMap *pbsm, INDEX iMipmap); + // mix dynamic lights + void MixOneMipmapDynamic(CBrushShadowMap *pbsm, INDEX iMipmap); + + // find start of a mip-map inside a layer + void FindLayerMipmap( CBrushShadowLayer *pbsl, UBYTE *&pub, UBYTE &ubMask); + + // add one point layer to the shadow map + void AddAmbientPoint(void); + void AddAmbientMaskPoint( UBYTE *pubMask, UBYTE ubMask); + void AddDiffusionPoint(void); + void AddDiffusionMaskPoint( UBYTE *pubMask, UBYTE ubMask); + BOOL PrepareOneLayerPoint( CBrushShadowLayer *pbsl, BOOL bNoMask); + void AddOneLayerPoint( CBrushShadowLayer *pbsl, UBYTE *pub, UBYTE ubMask=0); + + // add one directional layer to the shadow map + void AddDirectional(void); + void AddMaskDirectional( UBYTE *pubMask, UBYTE ubMask); + void AddOneLayerDirectional( CBrushShadowLayer *pbsl, UBYTE *pub, UBYTE ubMask=0); + + // add one gradient layer to the shadow map + void AddOneLayerGradient( CGradientParameters &gp); + + // add the intensity to the pixel + inline void AddToCluster( UBYTE *pub); + inline void AddAmbientToCluster( UBYTE *pub); + inline void AddToCluster( UBYTE *pub, FLOAT fIntensity); + + // additional functions + __forceinline void CopyShadowLayer(void); + __forceinline void FillShadowLayer( COLOR col); + // inline FLOAT IntensityAtDistance( FLOAT fDistance, FLOAT fMinDistance); + // FLOAT lm_fLightMax, lm_fLightStep; +}; + + +// increment a byte without overflowing it +static inline void IncrementByteWithClip( UBYTE &ub, SLONG slAdd) +{ + ub = pubClipByte[(SLONG)ub+slAdd]; +} + +// increment a color without overflowing it +static inline void IncrementColorWithClip( UBYTE &ubR, UBYTE &ubG, UBYTE &ubB, + SLONG slR, SLONG slG, SLONG slB) +{ + IncrementByteWithClip( ubR, slR); + IncrementByteWithClip( ubG, slG); + IncrementByteWithClip( ubB, slB); +} + +// add the intensity to the pixel +inline void CLayerMixer::AddToCluster( UBYTE *pub) +{ + IncrementByteWithClip(pub[0], ((UBYTE*)&lm_colLight)[3]); + IncrementByteWithClip(pub[1], ((UBYTE*)&lm_colLight)[2]); + IncrementByteWithClip(pub[2], ((UBYTE*)&lm_colLight)[1]); +} +inline void CLayerMixer::AddAmbientToCluster( UBYTE *pub) +{ + IncrementByteWithClip(pub[0], ((UBYTE*)&lm_colAmbient)[3]); + IncrementByteWithClip(pub[1], ((UBYTE*)&lm_colAmbient)[2]); + IncrementByteWithClip(pub[2], ((UBYTE*)&lm_colAmbient)[1]); +} +inline void CLayerMixer::AddToCluster( UBYTE *pub, FLOAT fIntensity) +{ + IncrementByteWithClip(pub[0], ((UBYTE*)&lm_colLight)[3] *fIntensity); + IncrementByteWithClip(pub[1], ((UBYTE*)&lm_colLight)[2] *fIntensity); + IncrementByteWithClip(pub[2], ((UBYTE*)&lm_colLight)[1] *fIntensity); +} + + +// remember general data +void CLayerMixer::CalculateData( CBrushShadowMap *pbsm, INDEX iMipmap) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_CALCULATEDATA); + + // cache class vars + lm_pbsmShadowMap = pbsm; + lm_pbpoPolygon = pbsm->GetBrushPolygon(); + + lm_mexOffsetU = pbsm->sm_mexOffsetX; + lm_mexOffsetV = pbsm->sm_mexOffsetY; + lm_iFirstLevel = pbsm->sm_iFirstMipLevel; + lm_iMipLevel = iMipmap; + lm_iMipShift = lm_iMipLevel - lm_iFirstLevel; + lm_pixCanvasSizeU = pbsm->sm_mexWidth >>lm_iMipLevel; + lm_pixCanvasSizeV = pbsm->sm_mexHeight>>lm_iMipLevel; + lm_pixPolygonSizeU = Min( lm_pixCanvasSizeU, (PIX)(lm_pbsmShadowMap->sm_pixPolygonSizeU >>lm_iMipShift)+1L); + lm_pixPolygonSizeV = Min( lm_pixCanvasSizeV, (PIX)(lm_pbsmShadowMap->sm_pixPolygonSizeV >>lm_iMipShift)+1L); + + // determine where this mip-map is relative to the allocated shadow map memory + PIX pixOffset = pbsm->sm_slMemoryUsed/BYTES_PER_TEXEL + - GetMipmapOffset( 15, lm_pixCanvasSizeU, lm_pixCanvasSizeV); + + // get right pointers to the shadow mipmap + if( lm_bDynamic) { + lm_pulShadowMap = pbsm->sm_pulDynamicShadowMap + pixOffset; + lm_pulStaticShadowMap = pbsm->sm_pulCachedShadowMap + pixOffset; + } else { + lm_pulShadowMap = pbsm->sm_pulCachedShadowMap + pixOffset; + lm_pulStaticShadowMap = NULL; + } + + // prepare 3D positions + CEntity *penWithPolygon = lm_pbpoPolygon->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + ASSERT(penWithPolygon!=NULL); + const FLOATmatrix3D &mPolygonRotation = penWithPolygon->en_mRotation; + const FLOAT3D &vPolygonTranslation = penWithPolygon->GetPlacement().pl_PositionVector; + + // get first pixel in texture in 3D + Vector vmex0; + vmex0(1) = -lm_mexOffsetU+(1<<(lm_iMipLevel-1)); + vmex0(2) = -lm_mexOffsetV+(1<<(lm_iMipLevel-1)); + lm_pbpoPolygon->bpo_mdShadow.GetSpaceCoordinates( + lm_pbpoPolygon->bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, vmex0, lm_vO); + lm_vO = lm_vO*mPolygonRotation+vPolygonTranslation; + + // get steps for walking in texture in 3D + Vector vmexU, vmexV; + vmexU(1) = (1<bpo_mdShadow.GetSpaceCoordinates( + lm_pbpoPolygon->bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, vmexU, lm_vStepU); + lm_vStepU = lm_vStepU*mPolygonRotation+vPolygonTranslation; + lm_pbpoPolygon->bpo_mdShadow.GetSpaceCoordinates( + lm_pbpoPolygon->bpo_pbplPlane->bpl_pwplWorking->wpl_mvRelative, vmexV, lm_vStepV); + lm_vStepV = lm_vStepV*mPolygonRotation+vPolygonTranslation; + lm_vStepU-= lm_vO; + lm_vStepV-= lm_vO; + + ASSERT( lm_pixPolygonSizeU>0 && lm_pixPolygonSizeV>0); + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CALCULATEDATA); +} + + +// find start of a mip-map inside a layer +void CLayerMixer::FindLayerMipmap( CBrushShadowLayer *pbsl, UBYTE *&pub, UBYTE &ubMask) +{ + struct MipmapTable mmtLayer; + // find mip-mapping information for the layer + MakeMipmapTable(pbsl->bsl_pixSizeU, pbsl->bsl_pixSizeV, mmtLayer); + // get pixel offset of the mipmap + SLONG slPixOffset = mmtLayer.mmt_aslOffsets[lm_iMipLevel-lm_iFirstLevel]; + // convert offset to bits + pub = pbsl->bsl_pubLayer + (slPixOffset>>3); + ubMask = 1<<(slPixOffset&7); +} + + + +#define FTOX 0x10000000 +#define SHIFTX (28-SQRTTABLESIZELOG2) + +// static variables for easier transfers +static const FLOAT3D *_vLight; +static FLOAT _fMinLightDistance, _f1oFallOff; +static INDEX _iPixCt, _iRowCt; +static SLONG _slModulo; +static ULONG _ulLightFlags, _ulPolyFlags; +static SLONG _slL2Row, _slDDL2oDU, _slDDL2oDV, _slDDL2oDUoDV, _slDL2oDURow, _slDL2oDV; +static SLONG _slLightMax, _slHotSpot, _slLightStep; +static ULONG *_pulLayer; + + +// add one layer point light without diffusion and mask +void CLayerMixer::AddAmbientPoint(void) +{ + // prepare some local variables + __int64 mmDDL2oDU = _slDDL2oDU; + __int64 mmDDL2oDV = _slDDL2oDV; + ULONG ulLightRGB = ByteSwap(lm_colLight); + _slLightMax<<=7; + _slLightStep>>=1; + + __asm { + // prepare interpolants + movd mm0,D [_slL2Row] + movd mm1,D [_slDL2oDURow] + psllq mm1,32 + por mm1,mm0 // MM1 = slDL2oDURow | slL2Row + movd mm0,D [_slDL2oDV] + movd mm2,D [_slDDL2oDUoDV] + psllq mm2,32 + por mm2,mm0 // MM2 = slDDL2oDUoDV | slDL2oDV + // prepare color + pxor mm0,mm0 + movd mm7,D [ulLightRGB] + punpcklbw mm7,mm0 + psllw mm7,1 + // loop thru rows + mov edi,D [_pulLayer] + mov ebx,D [_iRowCt] +rowLoop: + push ebx + movd ebx,mm1 // EBX = slL2Point + movq mm3,mm1 + psrlq mm3,32 // MM3 = 0 | slDL2oDU + // loop thru pixels in current row + mov ecx,D [_iPixCt] +pixLoop: + // check if pixel need to be drawn + cmp ebx,FTOX + jge skipPixel + // calculate intensities and do actual drawing of shadow pixel ARGB + movd mm4,ecx + mov eax,ebx + sar eax,SHIFTX + and eax,(SQRTTABLESIZE-1) + movzx eax,B aubSqrt[eax] + mov ecx,D [_slLightMax] + cmp eax,D [_slHotSpot] + jle skipInterpolation + mov ecx,255 + sub ecx,eax + imul ecx,D [_slLightStep] +skipInterpolation: + // calculate rgb pixel to add + movd mm6,ecx + punpcklwd mm6,mm6 + punpckldq mm6,mm6 + pmulhw mm6,mm7 + // add dynamic light pixel to underlying pixel + movd mm5,D [edi] + punpcklbw mm5,mm0 + paddw mm5,mm6 + packuswb mm5,mm0 + movd D [edi],mm5 + movd ecx,mm4 +skipPixel: + // advance to next pixel + add edi,4 + movd eax,mm3 + add ebx,eax + paddd mm3,Q [mmDDL2oDU] + dec ecx + jnz pixLoop + // advance to the next row + pop ebx + add edi,D [_slModulo] + paddd mm1,mm2 + paddd mm2,Q [mmDDL2oDV] + dec ebx + jnz rowLoop + emms + } +} + +// add one layer point light without diffusion and with mask +void CLayerMixer::AddAmbientMaskPoint( UBYTE *pubMask, UBYTE ubMask) +{ + +#if ASMOPT == 1 + + // prepare some local variables + __int64 mmDDL2oDU = _slDDL2oDU; + __int64 mmDDL2oDV = _slDDL2oDV; + ULONG ulLightRGB = ByteSwap(lm_colLight); + _slLightMax<<=7; + _slLightStep>>=1; + + __asm { + // prepare interpolants + movd mm0,D [_slL2Row] + movd mm1,D [_slDL2oDURow] + psllq mm1,32 + por mm1,mm0 // MM1 = slDL2oDURow | slL2Row + movd mm0,D [_slDL2oDV] + movd mm2,D [_slDDL2oDUoDV] + psllq mm2,32 + por mm2,mm0 // MM2 = slDDL2oDUoDV | slDL2oDV + // prepare color + pxor mm0,mm0 // MM0 = 0 | 0 (for unpacking purposes) + movd mm7,D [ulLightRGB] + punpcklbw mm7,mm0 + psllw mm7,1 + // loop thru rows + mov esi,D [pubMask] + mov edi,D [_pulLayer] + movzx edx,B [ubMask] + mov ebx,D [_iRowCt] +rowLoop: + push ebx + movd ebx,mm1 // EBX = slL2Point + movq mm3,mm1 + psrlq mm3,32 // MM3 = 0 | slDL2oDU + // loop thru pixels in current row + mov ecx,D [_iPixCt] +pixLoop: + // check if pixel need to be drawn; i.e. draw if( [esi] & ubMask && (slL2Point>SHIFTX)&(SQRTTABLESIZE-1); // and is just for degenerate cases + SLONG slIntensity = _slLightMax; + slL = aubSqrt[slL]; + if( slL>_slHotSpot) slIntensity = ((255-slL)*_slLightStep)>>8; + // add the intensity to the pixel + AddToCluster( (UBYTE*)_pulLayer, slIntensity/255.0f); + } + // go to the next pixel + _pulLayer++; + slL2Point += _slDL2oDU; + slDL2oDU += _slDDL2oDU; + ubMask<<=1; + if( ubMask==0) { + pubPoint++; + ubMask = 1; + } + } + // go to the next row + _pulLayer += _slModulo/BYTES_PER_TEXEL; + _slL2Row += _slDL2oDV; + _slDL2oDV += _slDDL2oDV; + _slDL2oDURow += _slDDL2oDUoDV; + } + +#endif + +} + +// add one layer point light with diffusion and without mask +void CLayerMixer::AddDiffusionPoint(void) +{ + // adjust params for diffusion lighting + SLONG slMax1oL = MAX_SLONG; + _slLightStep = FloatToInt(_slLightStep * _fMinLightDistance * _f1oFallOff); + if( _slLightStep!=0) slMax1oL = (256<<8) / _slLightStep +256; + + // prepare some local variables + __int64 mmDDL2oDU = _slDDL2oDU; + __int64 mmDDL2oDV = _slDDL2oDV; + ULONG ulLightRGB = ByteSwap(lm_colLight); + _slLightMax<<=7; + _slLightStep>>=1; + + __asm { + // prepare interpolants + movd mm0,D [_slL2Row] + movd mm1,D [_slDL2oDURow] + psllq mm1,32 + por mm1,mm0 // MM1 = slDL2oDURow | slL2Row + movd mm0,D [_slDL2oDV] + movd mm2,D [_slDDL2oDUoDV] + psllq mm2,32 + por mm2,mm0 // MM2 = slDDL2oDUoDV | slDL2oDV + // prepare color + pxor mm0,mm0 + movd mm7,D [ulLightRGB] + punpcklbw mm7,mm0 + psllw mm7,1 + // loop thru rows + mov edi,D [_pulLayer] + mov ebx,D [_iRowCt] +rowLoop: + push ebx + movd ebx,mm1 // EBX = slL2Point + movq mm3,mm1 + psrlq mm3,32 // MM3 = 0 | slDL2oDU + // loop thru pixels in current row + mov ecx,D [_iPixCt] +pixLoop: + // check if pixel need to be drawn + cmp ebx,FTOX + jge skipPixel + // calculate intensities and do actual drawing of shadow pixel ARGB + movd mm4,ecx + mov eax,ebx + sar eax,SHIFTX + and eax,(SQRTTABLESIZE-1) + movzx eax,W auw1oSqrt[eax*2] + mov ecx,D [_slLightMax] + cmp eax,D [slMax1oL] + jge skipInterpolation + lea ecx,[eax-256] + imul ecx,D [_slLightStep] +skipInterpolation: + // calculate rgb pixel to add + movd mm6,ecx + punpcklwd mm6,mm6 + punpckldq mm6,mm6 + pmulhw mm6,mm7 + // add dynamic light pixel to underlying pixel + movd mm5,D [edi] + punpcklbw mm5,mm0 + paddw mm5,mm6 + packuswb mm5,mm0 + movd D [edi],mm5 + movd ecx,mm4 +skipPixel: + // advance to next pixel + add edi,4 + movd eax,mm3 + add ebx,eax + paddd mm3,Q [mmDDL2oDU] + dec ecx + jnz pixLoop + // advance to the next row + pop ebx + add edi,D [_slModulo] + paddd mm1,mm2 + paddd mm2,Q [mmDDL2oDV] + dec ebx + jnz rowLoop + emms + } +} + +// add one layer point light with diffusion and mask +void CLayerMixer::AddDiffusionMaskPoint( UBYTE *pubMask, UBYTE ubMask) +{ + // adjust params for diffusion lighting + SLONG slMax1oL = MAX_SLONG; + _slLightStep = FloatToInt(_slLightStep * _fMinLightDistance * _f1oFallOff); + if( _slLightStep!=0) slMax1oL = (256<<8) / _slLightStep +256; + +#if ASMOPT == 1 + + // prepare some local variables + __int64 mmDDL2oDU = _slDDL2oDU; + __int64 mmDDL2oDV = _slDDL2oDV; + ULONG ulLightRGB = ByteSwap(lm_colLight); + _slLightMax<<=7; + _slLightStep>>=1; + + __asm { + // prepare interpolants + movd mm0,D [_slL2Row] + movd mm1,D [_slDL2oDURow] + psllq mm1,32 + por mm1,mm0 // MM1 = slDL2oDURow | slL2Row + movd mm0,D [_slDL2oDV] + movd mm2,D [_slDDL2oDUoDV] + psllq mm2,32 + por mm2,mm0 // MM2 = slDDL2oDUoDV | slDL2oDV + // prepare color + pxor mm0,mm0 // MM0 = 0 | 0 (for unpacking purposes) + movd mm7,D [ulLightRGB] + punpcklbw mm7,mm0 + psllw mm7,1 + // loop thru rows + mov esi,D [pubMask] + mov edi,D [_pulLayer] + movzx edx,B [ubMask] + mov ebx,D [_iRowCt] +rowLoop: + push ebx + movd ebx,mm1 // EBX = slL2Point + movq mm3,mm1 + psrlq mm3,32 // MM3 = 0 | slDL2oDU + // loop thru pixels in current row + mov ecx,D [_iPixCt] +pixLoop: + // check if pixel need to be drawn; i.e. draw if( [esi] & ubMask && (slL2Point>SHIFTX)&(SQRTTABLESIZE-1); // and is just for degenerate cases + sl1oL = auw1oSqrt[sl1oL]; + SLONG slIntensity = _slLightMax; + if( sl1oL>16; + // add the intensity to the pixel + AddToCluster( (UBYTE*)_pulLayer, slIntensity/255.0f); + } + // advance to next pixel + _pulLayer++; + slL2Point += slDL2oDU; + slDL2oDU += _slDDL2oDU; + ubMask<<=1; + if( ubMask==0) { + pubMask++; + ubMask = 1; + } + } + // advance to next row + _pulLayer += _slModulo/BYTES_PER_TEXEL; + _slL2Row += _slDL2oDV; + _slDL2oDV += _slDDL2oDV; + _slDL2oDURow += _slDDL2oDUoDV; + } + +#endif + +} + +// prepares point light that creates layer (returns TRUE if there is infulence) +BOOL CLayerMixer::PrepareOneLayerPoint( CBrushShadowLayer *pbsl, BOOL bNoMask) +{ + // determine light infulence dimensions + _iPixCt = pbsl->bsl_pixSizeU >>lm_iMipShift; + _iRowCt = pbsl->bsl_pixSizeV >>lm_iMipShift; + PIX pixMinU = pbsl->bsl_pixMinU >>lm_iMipShift; + PIX pixMinV = pbsl->bsl_pixMinV >>lm_iMipShift; + // clamp influence to polygon size + if( (pixMinU+_iPixCt) > lm_pixPolygonSizeU && bNoMask) _iPixCt = lm_pixPolygonSizeU-pixMinU; + if( (pixMinV+_iRowCt) > lm_pixPolygonSizeV) _iRowCt = lm_pixPolygonSizeV-pixMinV; + _slModulo = (lm_pixCanvasSizeU-_iPixCt) *BYTES_PER_TEXEL; + _pulLayer = lm_pulShadowMap + (pixMinV*lm_pixCanvasSizeU)+pixMinU; + ASSERT( pixMinU>=0 && pixMinU=0 && pixMinVbsl_plsLightSource; + _vLight = &lm_plsLight->ls_penEntity->GetPlacement().pl_PositionVector; + _fMinLightDistance = lm_pbpoPolygon->bpo_pbplPlane->bpl_plAbsolute.PointDistance(*_vLight); + _f1oFallOff = 1.0f / lm_plsLight->ls_rFallOff; + _ulLightFlags = lm_plsLight->ls_ulFlags; + _ulPolyFlags = lm_pbpoPolygon->bpo_ulFlags; + lm_colLight = lm_plsLight->GetLightColor(); + pbsl->bsl_colLastAnim = lm_colLight; + + // if there is no influence, do nothing + if( (pbsl->bsl_pixSizeU>>lm_iMipShift)==0 || (pbsl->bsl_pixSizeV>>lm_iMipShift)==0 + || _iPixCt<=0 || _iRowCt<=0) return FALSE; + + // adjust for sector ambient + if( _ulLightFlags&LSF_SUBSTRACTSECTORAMBIENT) { + COLOR colAmbient = lm_pbpoPolygon->bpo_pbscSector->bsc_colAmbient; + IncrementByteWithClip( ((UBYTE*)&lm_colLight)[1], -((UBYTE*)&colAmbient)[1]); + IncrementByteWithClip( ((UBYTE*)&lm_colLight)[2], -((UBYTE*)&colAmbient)[2]); + IncrementByteWithClip( ((UBYTE*)&lm_colLight)[3], -((UBYTE*)&colAmbient)[3]); + if( _ulPolyFlags&BPOF_HASDIRECTIONALAMBIENT) + { // find directional layers for each shadow layer + FOREACHINLIST( CBrushShadowLayer, bsl_lnInShadowMap, lm_pbsmShadowMap->bsm_lhLayers, itbsl) + { // loop thru layers + CBrushShadowLayer &bsl = *itbsl; + if( bsl.bsl_plsLightSource->ls_ulFlags&LSF_DIRECTIONAL) + { // skip if no ambient color + colAmbient = bsl.bsl_plsLightSource->ls_colAmbient & 0xFFFFFF00; + if( IsBlack(colAmbient)) continue; + // substract ambient + IncrementByteWithClip( ((UBYTE*)&lm_colLight)[1], -((UBYTE*)&colAmbient)[1]); + IncrementByteWithClip( ((UBYTE*)&lm_colLight)[2], -((UBYTE*)&colAmbient)[2]); + IncrementByteWithClip( ((UBYTE*)&lm_colLight)[3], -((UBYTE*)&colAmbient)[3]); + } + } + } + } + + // prepare intermediate light interpolants + FLOAT3D v00 = (lm_vO+lm_vStepU*pixMinU + lm_vStepV*pixMinV) - *_vLight; + FLOAT fFactor = FTOX * _f1oFallOff*_f1oFallOff; + FLOAT fL2Row = v00%v00; + FLOAT fDDL2oDU = lm_vStepU%lm_vStepU; + FLOAT fDDL2oDV = lm_vStepV%lm_vStepV; + FLOAT fDDL2oDUoDV = lm_vStepU%lm_vStepV; + FLOAT fDL2oDURow = fDDL2oDU + 2*(lm_vStepU%v00); + FLOAT fDL2oDV = fDDL2oDV + 2*(lm_vStepV%v00); + //_v00 = v00; + +#if ASMOPT == 1 + __asm { + fld D [fDDL2oDU] + fadd D [fDDL2oDU] + fld D [fDDL2oDV] + fadd D [fDDL2oDV] + fld D [fDDL2oDUoDV] + fadd D [fDDL2oDUoDV] + // st0=2*fDDL2oDUoDV, st1=2*fDDL2oDV, st2=2*fDDL2oDU + fld D [fL2Row] + fmul D [fFactor] + fld D [fDL2oDURow] + fmul D [fFactor] + fld D [fDL2oDV] + fmul D [fFactor] + // st0=fDL2oDV*fFactor, st1=fDL2oDURow*fFactor, st2=fL2Row*fFactor, + // st3=2*fDDL2oDUoDV, st4=2*fDDL2oDV, st5=2*fDDL2oDU + fld D [fFactor] + fmul st(4),st(0) + fmul st(5),st(0) + fmulp st(6),st(0) + fistp D [_slDL2oDV] + fistp D [_slDL2oDURow] + fistp D [_slL2Row] + fistp D [_slDDL2oDUoDV] + fistp D [_slDDL2oDV] + fistp D [_slDDL2oDU] + } +#else + fDDL2oDU *= 2; + fDDL2oDV *= 2; + fDDL2oDUoDV *= 2; + _slL2Row = FloatToInt( fL2Row * fFactor); + _slDDL2oDU = FloatToInt( fDDL2oDU * fFactor); + _slDDL2oDV = FloatToInt( fDDL2oDV * fFactor); + _slDDL2oDUoDV = FloatToInt( fDDL2oDUoDV * fFactor); + _slDL2oDURow = FloatToInt( fDL2oDURow * fFactor); + _slDL2oDV = FloatToInt( fDL2oDV * fFactor); +#endif + + // prepare final light interpolants + _slLightMax = 255; + _slHotSpot = FloatToInt( 255.0f * lm_plsLight->ls_rHotSpot * _f1oFallOff); + _slLightStep = FloatToInt( 65535.0f / (255.0f - _slHotSpot)); + // dark light inverts parameters + if( _ulLightFlags & LSF_DARKLIGHT) { + _slLightMax = -_slLightMax; + _slLightStep = -_slLightStep; + } + + // saturate light color + lm_colLight = AdjustColor( lm_colLight, _slShdHueShift, _slShdSaturation); + // all done + return TRUE; +} + + +// add one layer to the shadow map (pubMask=NULL for no mask) +void CLayerMixer::AddOneLayerPoint( CBrushShadowLayer *pbsl, UBYTE *pubMask, UBYTE ubMask) +{ + // try to prepare layer for this point light + _pfWorldEditingProfile.StartTimer( CWorldEditingProfile::PTI_ADDONELAYERPOINT); + if( !PrepareOneLayerPoint( pbsl, pubMask==NULL)) { + _pfWorldEditingProfile.StopTimer( CWorldEditingProfile::PTI_ADDONELAYERPOINT); + return; + } + + // determine diffusion presence and corresponding routine + BOOL bDiffusion = (_ulLightFlags&LSF_DIFFUSION) && !(_ulPolyFlags&BPOF_NOPLANEDIFFUSION); + // masked or non-masked? + if( pubMask==NULL) { + // non-masked + if( !lm_bDynamic && bDiffusion) { + // non-masked diffusion + AddDiffusionPoint(); + } else { + // non-masked ambient + AddAmbientPoint(); + } + } else { + // masked + if( bDiffusion) { + // masked diffusion + AddDiffusionMaskPoint( pubMask, ubMask); + } else { + AddAmbientMaskPoint( pubMask, ubMask); + } + } + + // all done + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_ADDONELAYERPOINT); +} + + + +// apply gradient to layer +void CLayerMixer::AddOneLayerGradient( CGradientParameters &gp) +{ + // convert gradient parameters for plane + ASSERT( Abs(gp.gp_fH1-gp.gp_fH0)>0.0001f); + FLOAT f1oDH = 1.0f / (gp.gp_fH1-gp.gp_fH0); + FLOAT fGr00 = (lm_vO % gp.gp_vGradientDir - gp.gp_fH0) *f1oDH; + FLOAT fDGroDI = (lm_vStepU % gp.gp_vGradientDir) *f1oDH; + FLOAT fDGroDJ = (lm_vStepV % gp.gp_vGradientDir) *f1oDH; + fDGroDI += fDGroDI/lm_pixPolygonSizeU; + fDGroDJ += fDGroDJ/lm_pixPolygonSizeV; + SLONG fixDGroDI = FloatToInt(fDGroDI*32767.0f); // 16:15 + SLONG fixDGroDJ = FloatToInt(fDGroDJ*32767.0f); // 16:15 + COLOR col0 = gp.gp_col0; + COLOR col1 = gp.gp_col1; + _pulLayer = lm_pulShadowMap; + FLOAT fStart = Clamp( fGr00-(fDGroDJ+fDGroDI)*0.5f, 0.0f, 1.0f); + +#if ASMOPT == 1 + + __int64 mmRowAdv; + SLONG fixGRow = (fGr00-(fDGroDJ+fDGroDI)*0.5f)*32767.0f; // 16:15 + SLONG slModulo = (lm_pixCanvasSizeU-lm_pixPolygonSizeU) *BYTES_PER_TEXEL; + COLOR colStart = LerpColor( col0, col1, fStart); + INDEX ctCols = lm_pixPolygonSizeU; + INDEX ctRows = lm_pixPolygonSizeV; + BOOL bDarkLight = gp.gp_bDark; + + __asm { + mov eax,D [colStart] + mov ebx,D [col0] + mov edx,D [col1] + bswap eax + bswap ebx + bswap edx + movd mm1,eax + movd mm2,ebx + movd mm3,edx + punpcklbw mm1,mm1 + punpcklbw mm2,mm2 + punpcklbw mm3,mm3 + psrlw mm1,2 + psrlw mm2,1 + psrlw mm3,1 + // eventually adjust for dark light + cmp D [bDarkLight],0 + je skipDark + pcmpeqd mm0,mm0 + pxor mm1,mm0 + pxor mm2,mm0 + pxor mm3,mm0 + psubw mm1,mm0 + psubw mm2,mm0 + psubw mm3,mm0 +skipDark: + // keep colors + movq mm0,mm2 + movq mm7,mm3 + // find row and column advancers + psubw mm3,mm2 + movq mm2,mm3 + movd mm5,D [fixDGroDI] + movd mm6,D [fixDGroDJ] + punpcklwd mm5,mm5 + punpcklwd mm6,mm6 + punpckldq mm5,mm5 + punpckldq mm6,mm6 + pmulhw mm2,mm5 // column color advancer (8:6) + pmulhw mm3,mm6 // row color advancer (8:6) + movq Q [mmRowAdv],mm3 + + // prepare starting variables + movq mm5,mm0 + movq mm6,mm7 + psraw mm5,1 // starting color + psraw mm6,1 // ending color + pxor mm0,mm0 + mov esi,D [fixGRow] + mov edi,D [_pulLayer] + mov edx,D [ctRows] +rowLoop: + mov ebx,esi + movq mm4,mm1 + mov ecx,D [ctCols] +pixLoop: + // add or substract light pixel to underlying pixel + movq mm7,mm4 + psraw mm7,6 + movd mm3,D [edi] + punpcklbw mm3,mm0 + paddw mm3,mm7 + packuswb mm3,mm0 + movd D [edi],mm3 + + // advance to next pixel + add ebx,D [fixDGroDI] + cmp ebx,0x8000 + ja pixClamp + paddw mm4,mm2 + add edi,4 + dec ecx + jnz pixLoop + jmp pixDone +pixClamp: + movq mm4,mm6 + jg pixNext + movq mm4,mm5 +pixNext: + add edi,4 + dec ecx + jnz pixLoop +pixDone: + + // advance to next row + add esi,D [fixDGroDJ] + cmp esi,0x8000 + ja rowClamp + paddw mm1,Q [mmRowAdv] + add edi,D [slModulo] + dec edx + jnz rowLoop + jmp rowDone +rowClamp: + movq mm1,mm6 + jg rowNext + movq mm1,mm5 +rowNext: + add edi,D [slModulo] + dec edx + jnz rowLoop +rowDone: + emms + } + +#else + + // well, make gradient ... + SLONG slR0=0,slG0=0,slB0=0; + SLONG slR1=0,slG1=0,slB1=0; + ColorToRGB( col0, (UBYTE&)slR0,(UBYTE&)slG0,(UBYTE&)slB0); + ColorToRGB( col1, (UBYTE&)slR1,(UBYTE&)slG1,(UBYTE&)slB1); + if( gp.gp_bDark) { + slR0 = -slR0; slG0 = -slG0; slB0 = -slB0; + slR1 = -slR1; slG1 = -slG1; slB1 = -slB1; + } + fixDGroDI >>= 1; // 16:14 + fixDGroDJ >>= 1; // 16:14 + SWORD fixRrow = Lerp( slR0,slR1,fStart) <<6; // 8:6 + SWORD fixGrow = Lerp( slG0,slG1,fStart) <<6; // 8:6 + SWORD fixBrow = Lerp( slB0,slB1,fStart) <<6; // 8:6 + SWORD fixDRoDI = ((slR1-slR0)*fixDGroDI)>>8; + SWORD fixDGoDI = ((slG1-slG0)*fixDGroDI)>>8; + SWORD fixDBoDI = ((slB1-slB0)*fixDGroDI)>>8; + SWORD fixDRoDJ = ((slR1-slR0)*fixDGroDJ)>>8; + SWORD fixDGoDJ = ((slG1-slG0)*fixDGroDJ)>>8; + SWORD fixDBoDJ = ((slB1-slB0)*fixDGroDJ)>>8; + + // loop it, baby + FLOAT fGrRow = fGr00 - (fDGroDJ+fDGroDI)*0.5f; + PIX pixOffset = 0; + PIX pixModulo = lm_pixCanvasSizeU-lm_pixPolygonSizeU; + for( INDEX j=0; j>6, -255, +255); + SLONG slG = Clamp( fixGcol>>6, -255, +255); + SLONG slB = Clamp( fixBcol>>6, -255, +255); + IncrementByteWithClip( ((UBYTE*)&_pulLayer[pixOffset])[0], slR); + IncrementByteWithClip( ((UBYTE*)&_pulLayer[pixOffset])[1], slG); + IncrementByteWithClip( ((UBYTE*)&_pulLayer[pixOffset])[2], slB); + // advance to next pixel + fGrCol += fDGroDI; + pixOffset++; + if( fGrCol<0) { + fixRcol = slR0<<6; + fixGcol = slG0<<6; + fixBcol = slB0<<6; + } else if( fGrCol>1) { + fixRcol = slR1<<6; + fixGcol = slG1<<6; + fixBcol = slB1<<6; + } else { + fixRcol += fixDRoDI; + fixGcol += fixDGoDI; + fixBcol += fixDBoDI; + } + } + // advance to next row + fGrRow += fDGroDJ; + pixOffset += pixModulo; + if( fGrRow<0) { + fixRrow = slR0<<6; + fixGrow = slG0<<6; + fixBrow = slB0<<6; + } else if( fGrRow>1) { + fixRrow = slR1<<6; + fixGrow = slG1<<6; + fixBrow = slB1<<6; + } else { + fixRrow += fixDRoDJ; + fixGrow += fixDGoDJ; + fixBrow += fixDBoDJ; + } + } + +#endif + +} + + + +// apply directional light or ambient to layer +void CLayerMixer::AddDirectional(void) +{ + +#if ASMOPT == 1 + + ULONG ulLight = ByteSwap( lm_colLight); + __asm { + // prepare pointers and variables + mov edi,D [_pulLayer] + mov ebx,D [_iRowCt] + movd mm6,D [ulLight] + punpckldq mm6,mm6 +rowLoop: + mov ecx,D [_iPixCt] + shr ecx,1 + jz pixRest +pixLoop: + // mix underlaying pixels with the constant color pixel + movq mm5,Q [edi] + paddusb mm5,mm6 + movq Q [edi],mm5 + // advance to next pixel + add edi,8 + dec ecx + jnz pixLoop +pixRest: + test D [_iPixCt],1 + jz rowNext + movd mm5,D [edi] + paddusb mm5,mm6 + movd D [edi],mm5 + add edi,4 +rowNext: + // advance to the next row + add edi,D [_slModulo] + dec ebx + jnz rowLoop + emms + } + +#else + + // for each pixel in the shadow map + for( PIX pixV=0; pixV<_iRowCt; pixV++) { + for( PIX pixU=0; pixU<_iPixCt; pixU++) { + // add the intensity to the pixel + AddToCluster( (UBYTE*)_pulLayer); + _pulLayer++; // go to the next pixel + } // go to the next row + _pulLayer += slModulo; + } + +#endif + +} + +// apply directional light thru mask to layer +void CLayerMixer::AddMaskDirectional( UBYTE *pubMask, UBYTE ubMask) +{ + +#if ASMOPT == 1 + + // prepare some local variables + ULONG ulLight = ByteSwap( lm_colLight); + __asm { + // prepare pointers and variables + movzx edx,B [ubMask] + mov esi,D [pubMask] + mov edi,D [_pulLayer] + mov ebx,D [_iRowCt] + movd mm6,D [ulLight] +rowLoop: + mov ecx,D [_iPixCt] +pixLoop: + // mix underlaying pixels with the constant light color if not shaded + test dl,B [esi] + jz skipLight + movd mm5,D [edi] + paddusb mm5,mm6 + movd D [edi],mm5 +skipLight: + // advance to next pixel + add edi,4 + rol dl,1 + adc esi,0 + dec ecx + jnz pixLoop + // advance to the next row + add edi,D [_slModulo] + dec ebx + jnz rowLoop + emms + } + +#else + + // for each pixel in the shadow map + for( PIX pixV=0; pixV<_iRowCt; pixV++) { + for( PIX pixU=0; pixU<_iPixCt; pixU++) { + // if the point is not masked + if( *pubMask&ubMask) { + // add the intensity to the pixel + AddToCluster( (UBYTE*)_pulLayer); + } // go to the next pixel + _pulLayer++; + ubMask<<=1; + if( ubMask==0) { + pubMask ++; + ubMask = 1; + } + } // go to the next row + _pulLayer += slModulo; + } + +#endif + +} + + +// apply directional light to layer +// (pubMask=NULL for no mask, ubMask = 0xFF for full mask) +void CLayerMixer::AddOneLayerDirectional( CBrushShadowLayer *pbsl, UBYTE *pubMask, UBYTE ubMask) +{ + // only if there is color light (ambient is added at initial fill) + if( !(lm_pbpoPolygon->bpo_ulFlags&BPOF_HASDIRECTIONALLIGHT)) return; + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_ADDONELAYERDIRECTIONAL); + + // determine light influence dimensions + _iPixCt = pbsl->bsl_pixSizeU >>lm_iMipShift; + _iRowCt = pbsl->bsl_pixSizeV >>lm_iMipShift; + PIX pixMinU = pbsl->bsl_pixMinU >>lm_iMipShift; + PIX pixMinV = pbsl->bsl_pixMinV >>lm_iMipShift; + ASSERT( pixMinU==0 && pixMinV==0); + // clamp influence to polygon size + if( _iPixCt > lm_pixPolygonSizeU && pubMask==NULL) _iPixCt = lm_pixPolygonSizeU; + if( _iRowCt > lm_pixPolygonSizeV) _iRowCt = lm_pixPolygonSizeV; + _slModulo = (lm_pixCanvasSizeU-_iPixCt) *BYTES_PER_TEXEL; + _pulLayer = lm_pulShadowMap; + + // if there is no influence, do nothing + if( (pbsl->bsl_pixSizeU>>lm_iMipShift)==0 || (pbsl->bsl_pixSizeV>>lm_iMipShift)==0 + || _iPixCt<=0 || _iRowCt<=0) { + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_ADDONELAYERDIRECTIONAL); + return; + } + + // get the light source of the layer + lm_plsLight = pbsl->bsl_plsLightSource; + const FLOAT3D &vLight = lm_plsLight->ls_penEntity->GetPlacement().pl_PositionVector; + AnglesToDirectionVector( lm_plsLight->ls_penEntity->GetPlacement().pl_OrientationAngle, + lm_vLightDirection); + // calculate intensity + FLOAT fIntensity = 1.0f; + if( !(lm_pbpoPolygon->bpo_ulFlags&BPOF_NOPLANEDIFFUSION)) { + fIntensity = -((lm_pbpoPolygon->bpo_pbplPlane->bpl_plAbsolute)%lm_vLightDirection); + fIntensity = ClampDn( fIntensity, 0.0f); + } + // calculate light color and ambient + lm_colLight = lm_plsLight->GetLightColor(); + pbsl->bsl_colLastAnim = lm_colLight; + ULONG ulIntensity = NormFloatToByte(fIntensity); + ulIntensity = (ulIntensity<2) iDither++; + return iDither; +} + + +// mix one mip-map +void CLayerMixer::MixOneMipmap(CBrushShadowMap *pbsm, INDEX iMipmap) +{ + // remember general data + CalculateData( pbsm, iMipmap); + const BOOL bDynamicOnly = lm_pbpoPolygon->bpo_ulFlags&BPOF_DYNAMICLIGHTSONLY; + + // fill with sector ambient + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_AMBIENTFILL); + + // eventually add ambient component of all directional layers that might contribute + COLOR colAmbient = 0x80808000UL; // overide ambient light color for dynamic lights only + if( !bDynamicOnly) { + colAmbient = AdjustColor( lm_pbpoPolygon->bpo_pbscSector->bsc_colAmbient, _slShdHueShift, _slShdSaturation); + if( lm_pbpoPolygon->bpo_ulFlags&BPOF_HASDIRECTIONALAMBIENT) { + {FOREACHINLIST( CBrushShadowLayer, bsl_lnInShadowMap, lm_pbsmShadowMap->bsm_lhLayers, itbsl) { + CBrushShadowLayer &bsl = *itbsl; + CLightSource &ls = *bsl.bsl_plsLightSource; + ASSERT( &ls!=NULL); if( &ls==NULL) continue; // safety check + if( !(ls.ls_ulFlags&LSF_DIRECTIONAL)) continue; // skip non-directional layers + COLOR col = AdjustColor( ls.GetLightAmbient(), _slShdHueShift, _slShdSaturation); + colAmbient = AddColors( colAmbient, col); + }} + } + } // set initial color + __asm { + cld + mov ebx,D [this] + mov ecx,D [ebx].lm_pixCanvasSizeU + imul ecx,D [ebx].lm_pixCanvasSizeV + mov edi,D [ebx].lm_pulShadowMap + mov eax,D [colAmbient] + bswap eax + rep stosd + } + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_AMBIENTFILL); + + // find gradient layer + CGradientParameters gpGradient; + BOOL bHasGradient = FALSE; + ULONG ulGradientType = lm_pbpoPolygon->bpo_bppProperties.bpp_ubGradientType; + if( ulGradientType>0) { + CEntity *pen = lm_pbpoPolygon->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + if( pen!=NULL) bHasGradient = pen->GetGradient( ulGradientType, gpGradient); + } + // add gradient if gradient is light + if( bHasGradient && !gpGradient.gp_bDark) AddOneLayerGradient( gpGradient); + + // for each shadow layer + lm_pbsmShadowMap->sm_ulFlags &= ~SMF_ANIMATINGLIGHTS; + {FORDELETELIST( CBrushShadowLayer, bsl_lnInShadowMap, lm_pbsmShadowMap->bsm_lhLayers, itbsl) + { + CBrushShadowLayer &bsl = *itbsl; + CLightSource &ls = *bsl.bsl_plsLightSource; + ASSERT( &ls!=NULL); if( &ls==NULL) continue; // safety check + + // skip if should not be applied + if( (bDynamicOnly && !(ls.ls_ulFlags&LSF_NONPERSISTENT)) || ls.ls_ulFlags&LSF_DYNAMIC) continue; + + // set corresponding shadowmap flag if this is an animating light + if( ls.ls_paoLightAnimation!=NULL) lm_pbsmShadowMap->sm_ulFlags |= SMF_ANIMATINGLIGHTS; + + // if the layer is calculated + if( bsl.bsl_pubLayer!=NULL) + { + UBYTE *pub; + UBYTE ubMask; + FindLayerMipmap( itbsl, pub, ubMask); + // add the layer to the shadow map with masking + if( ls.ls_ulFlags&LSF_DIRECTIONAL) { + AddOneLayerDirectional( itbsl, pub, ubMask); + } else { + AddOneLayerPoint( itbsl, pub, ubMask); + } + } + // if the layer is all light + else if( !(bsl.bsl_ulFlags&BSLF_CALCULATED) || (bsl.bsl_ulFlags&BSLF_ALLLIGHT)) + { + // add the layer to the shadow map without masking + if( ls.ls_ulFlags&LSF_DIRECTIONAL) { + AddOneLayerDirectional( itbsl, NULL); + } else { + AddOneLayerPoint( itbsl, NULL); + } + } + }} + + // if gradient is dark, substract gradient + if( bHasGradient && gpGradient.gp_bDark) AddOneLayerGradient( gpGradient); + + // do eventual filtering of shadow layer + shd_iFiltering = Clamp( shd_iFiltering, 0L, +6L); + if( shd_iFiltering>0) { + FilterBitmap( shd_iFiltering, lm_pulShadowMap, lm_pulShadowMap, + lm_pixPolygonSizeU, lm_pixPolygonSizeV, lm_pixCanvasSizeU, lm_pixCanvasSizeV); + } + // do eventual dithering of shadow layer + const INDEX iDither = GetDither(); + if( !(_pGfx->gl_ulFlags&GLF_32BITTEXTURES)) shd_bFineQuality = FALSE; + if( iDither && !(shd_bFineQuality)) { + DitherBitmap( iDither, lm_pulShadowMap, lm_pulShadowMap, + lm_pixPolygonSizeU, lm_pixPolygonSizeV, lm_pixCanvasSizeU, lm_pixCanvasSizeV); + } +} + + + +// copy from static shadow map to dynamic layer +__forceinline void CLayerMixer::CopyShadowLayer(void) +{ + __asm { + cld + mov ebx,D [this] + mov ecx,D [ebx].lm_pixCanvasSizeU + imul ecx,D [ebx].lm_pixCanvasSizeV + mov esi,D [ebx].lm_pulStaticShadowMap + mov edi,D [ebx].lm_pulShadowMap + rep movsd + } +} + + +// copy from static shadow map to dynamic layer +__forceinline void CLayerMixer::FillShadowLayer( COLOR col) +{ + __asm { + cld + mov ebx,D [this] + mov ecx,D [ebx].lm_pixCanvasSizeU + imul ecx,D [ebx].lm_pixCanvasSizeV + mov edi,D [ebx].lm_pulShadowMap + mov eax,D [col] + bswap eax // convert to R,G,B,A memory format! + rep stosd + } +} + + +// mix dynamic lights +void CLayerMixer::MixOneMipmapDynamic( CBrushShadowMap *pbsm, INDEX iMipmap) +{ + // remember general data + CalculateData( pbsm, iMipmap); + // if static shadow map is all flat + if( pbsm->sm_pulCachedShadowMap==&pbsm->sm_colFlat) { + // just fill dynamic shadow map with flat color + FillShadowLayer( pbsm->sm_colFlat); + } // if not flat + else { + // copy static layer + CopyShadowLayer(); + } + + // for each shadow layer + {FORDELETELIST( CBrushShadowLayer, bsl_lnInShadowMap, lm_pbsmShadowMap->bsm_lhLayers, itbsl) + { // the layer's light source must be valid + CBrushShadowLayer &bsl = *itbsl; + CLightSource &ls = *bsl.bsl_plsLightSource; + ASSERT( &ls!=NULL); + if( !(ls.ls_ulFlags&LSF_DYNAMIC)) continue; + COLOR colLight = ls.GetLightColor() & ~CT_AMASK; + if( IsBlack(colLight)) continue; + // apply one layer + colLight = AdjustColor( colLight, _slShdHueShift, _slShdSaturation); + AddOneLayerPoint( itbsl, NULL); + }} +} + + +// constructor +CLayerMixer::CLayerMixer( CBrushShadowMap *pbsm, INDEX iFirstMip, INDEX iLastMip, BOOL bDynamic) +{ + lm_bDynamic = bDynamic; + if( bDynamic) { + // check dynamic layers for complete blackness + BOOL bAllBlack = TRUE; + pbsm->sm_ulFlags &= ~SMF_DYNAMICBLACK; + {FORDELETELIST( CBrushShadowLayer, bsl_lnInShadowMap, pbsm->bsm_lhLayers, itbsl) { + CLightSource &ls = *itbsl->bsl_plsLightSource; + ASSERT( &ls!=NULL); + if( !(ls.ls_ulFlags&LSF_DYNAMIC)) continue; + COLOR colLight = ls.GetLightColor() & ~CT_AMASK; + itbsl->bsl_colLastAnim = colLight; + if( !IsBlack(colLight)) bAllBlack = FALSE; // must continue because of layer info update (light anim and such stuff) + }} + // skip mixing if dynamic layers were all black + if( bAllBlack) { + pbsm->sm_ulFlags |= SMF_DYNAMICBLACK; + return; + } + // need to mix in + for( INDEX iMipmap=iFirstMip; iMipmap<=iLastMip; iMipmap++) MixOneMipmapDynamic( pbsm, iMipmap); + } + // mix static layers + else { + for( INDEX iMipmap=iFirstMip; iMipmap<=iLastMip; iMipmap++) MixOneMipmap( pbsm, iMipmap); + } +} + + +// mix all layers into cached shadow map +void CBrushShadowMap::MixLayers( INDEX iFirstMip, INDEX iLastMip, BOOL bDynamic/*=FALSE*/) +{ + _sfStats.StartTimer( CStatForm::STI_SHADOWUPDATE); + _pfWorldEditingProfile.StartTimer( CWorldEditingProfile::PTI_MIXLAYERS); + // mix the layers with a shadow mixer + CLayerMixer lmMixer( this, iFirstMip, iLastMip, bDynamic); + _pfWorldEditingProfile.StopTimer( CWorldEditingProfile::PTI_MIXLAYERS); + _sfStats.StopTimer( CStatForm::STI_SHADOWUPDATE); +} diff --git a/Sources/Engine/Light/LensFlares.h b/Sources/Engine/Light/LensFlares.h new file mode 100644 index 0000000..0d7c8f6 --- /dev/null +++ b/Sources/Engine/Light/LensFlares.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_LENSFLARES_H +#define SE_INCL_LENSFLARES_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* + * Structure describing one flare in lens flare effect. + */ +#define OLF_FADESIZE (1L<<0) // change size when fading +#define OLF_FADEINTENSITY (1L<<1) // change intensity when fading +#define OLF_FADEOFCENTER (1L<<2) // fade if away from screen center + +class ENGINE_API COneLensFlare { +public: + CTextureObject olf_toTexture; // texture used for this flare + FLOAT olf_fReflectionPosition; // 0=light 1=center of screen + FLOAT olf_fSizeIOverScreenSizeI; // flare dimensions relative to screen size + FLOAT olf_fSizeJOverScreenSizeI; + FLOAT olf_fLightAmplification; // amplification for light color + FLOAT olf_fLightDesaturation; // desaturation factor for light color (1=monochrome) + FLOAT oft_fFallOffFactor; // flare falloff relative to light falloff + ANGLE olf_aRotationFactor; // flare rotation (deg/screen width) + ULONG olf_ulFlags; +}; + +/* + * Structure describing specific kind of lens flare effect. + */ +class ENGINE_API CLensFlareType { +public: + CStaticArray lft_aolfFlares; // all flares for this effect + // glaring when light source is near screen center + FLOAT lft_fGlareCompression; // glaring compression towards center + FLOAT lft_fGlareIntensity; // maximum glare intensity + FLOAT lft_fGlareFallOffFactor; // glare falloff relative to light falloff + FLOAT lft_fGlareDesaturation; // desaturation factor for center glare (1=monochrome) +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Light/LightSource.cpp b/Sources/Engine/Light/LightSource.cpp new file mode 100644 index 0000000..e1af931 --- /dev/null +++ b/Sources/Engine/Light/LightSource.cpp @@ -0,0 +1,679 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +///////////////////////////////////////////////////////////////////// +// CLightSource +// constructor +CLightSource::CLightSource(void) +{ + // set invalid properties, must be initialized by its entity + ls_ulFlags = -1; + ls_rHotSpot = -1; + ls_rFallOff = -1; + ls_colColor = 0; + ls_colAmbient = 0; + ls_ubLightAnimationObject = -1; + ls_ubPolygonalMask = -1; + ls_penEntity = NULL; + ls_plftLensFlare = NULL; + ls_paoLightAnimation = NULL; + ls_paoAmbientLightAnimation = NULL; +} +// destructor +CLightSource::~CLightSource(void) +{ + // discard all linked shadow layers + DiscardShadowLayers(); + // if this isn't dynamic light + if(!(ls_ulFlags&LSF_DYNAMIC) && ls_penEntity!=NULL) { + UpdateTerrains(); + } + + // delete possible lens flare infos in renderer + extern void DeleteLensFlare(CLightSource *pls); + DeleteLensFlare(this); +} + +// read/write from a stream +void CLightSource::Read_t( CTStream *pstrm) // throw char * +{ + // if the light information is really saved here + if (pstrm->PeekID_t()==CChunkID("LIGH")) { // light source + pstrm->ExpectID_t("LIGH"); + + // this light source must not be non-persistent + ASSERT(!(ls_ulFlags&LSF_NONPERSISTENT)); + + // read number of layers + INDEX ctLayers; + *pstrm>>ctLayers; + // for each shadow layer + for(INDEX iLayer=0; iLayer>iBrush; + *pstrm>>iMip; + *pstrm>>iSector; + *pstrm>>iPolygon; + // find the shadow map + CBrush3D *pbrBrush = &ls_penEntity->en_pwoWorld->wo_baBrushes.ba_abrBrushes[iBrush]; + CBrushMip *pbm = pbrBrush->GetBrushMipByIndex(iMip); + ASSERT(pbm!=NULL); + pbm->bm_abscSectors.Lock(); + CBrushSector *pbsc = &pbm->bm_abscSectors[iSector]; + pbm->bm_abscSectors.Unlock(); + CBrushPolygon *pbpo = &pbsc->bsc_abpoPolygons[iPolygon]; + CBrushShadowMap *pbsm = &pbpo->bpo_smShadowMap; + + // read the index of the layer in the shadow map + INDEX iLayerInShadowMap; + *pstrm>>iLayerInShadowMap; + // for each layer in the shadow map + INDEX iLayerInShadowMapCurrent = 0; + BOOL bLayerFound = FALSE; + FOREACHINLIST(CBrushShadowLayer, bsl_lnInShadowMap, pbsm->bsm_lhLayers, itbsl) { + // if it is that layer + if (iLayerInShadowMapCurrent==iLayerInShadowMap) { + // attach the layer to the light source + itbsl->bsl_plsLightSource = this; + ls_lhLayers.AddTail(itbsl->bsl_lnInLightSource); + bLayerFound = TRUE; + break; + } + iLayerInShadowMapCurrent++; + } + // some layer must be found + ASSERT(bLayerFound); + } + } +} + +void CLightSource::Write_t( CTStream *pstrm) // throw char * +{ + // if this light source is non-persistent + if (ls_ulFlags&LSF_NONPERSISTENT) { + // don't save it + return; + } + pstrm->WriteID_t("LIGH"); // light source + // write number of layers + *pstrm<bsl_pbsmShadowMap->GetBrushPolygon(); + CBrushSector *pbsc = pbpo->bpo_pbscSector; + CBrushMip *pbm = pbsc->bsc_pbmBrushMip; + CBrush3D *pbr = pbm->bm_pbrBrush; + // write their indices + *pstrm<en_pwoWorld->wo_baBrushes.ba_abrBrushes.Index(pbr); + + *pstrm<GetMipIndex(); + + pbm->bm_abscSectors.Lock(); + *pstrm<bm_abscSectors.Index(pbsc); + pbm->bm_abscSectors.Unlock(); + + *pstrm<bsc_abpoPolygons.Index(pbpo); + // find the index of the layer in its shadow map + INDEX iLayerInShadowMap = 0; + FOREACHINLIST(CBrushShadowLayer, bsl_lnInShadowMap, + itbsl->bsl_pbsmShadowMap->bsm_lhLayers, itbsl2) { + if (itbsl2->bsl_plsLightSource->ls_ulFlags&LSF_NONPERSISTENT) { + continue; + } + if (&*itbsl == &*itbsl2) { + break; + } + iLayerInShadowMap++; + } + // write that index + *pstrm<bsl_pbsmShadowMap->Invalidate(ls_ulFlags&LSF_DYNAMIC); + } +} + +// discard all linked shadow layers +void CLightSource::DiscardShadowLayers(void) +{ + // for each shadow layer + FORDELETELIST(CBrushShadowLayer, bsl_lnInLightSource, ls_lhLayers, itbsl) { + // invalidate its shadow map + itbsl->bsl_pbsmShadowMap->Invalidate(ls_ulFlags&LSF_DYNAMIC); + // delete the layer + delete &*itbsl; + } +} + +// test if a polygon has a layer from this light source +BOOL CLightSource::PolygonHasLayer(CBrushPolygon &bpo) +{ + // for each shadow layer in the polygon + FOREACHINLIST(CBrushShadowLayer, bsl_lnInShadowMap, bpo.bpo_smShadowMap.bsm_lhLayers, itbsl) { + // if it is from this light source + if (itbsl->bsl_plsLightSource==this) { + // it does have + return TRUE; + } + } + // otherwise, it doesn't have + return FALSE; +} + +// set layer parameters +void CLightSource::SetLayerParameters(CBrushShadowLayer &bsl, CBrushPolygon &bpo, class CLightRectangle &lr) +{ + // remember the rectangle of the layer + bsl.bsl_pixMinU = lr.lr_pixMinU; + bsl.bsl_pixMinV = lr.lr_pixMinV; + bsl.bsl_pixSizeU = lr.lr_pixSizeU; + bsl.bsl_pixSizeV = lr.lr_pixSizeV; + bsl.bsl_ulFlags |= BSLF_RECTANGLE; + + // invalidate the shadow map + bpo.bpo_smShadowMap.Invalidate(ls_ulFlags&LSF_DYNAMIC); + + // if the light casts shadows + if (ls_ulFlags&LSF_CASTSHADOWS) { + // queue the shadow map for calculating + bpo.bpo_smShadowMap.QueueForCalculation(); + } +} + +// add a layer to a polygon +void CLightSource::AddLayer(CBrushPolygon &bpo) +{ + // find the influenced rectangle + CLightRectangle lr; + bpo.bpo_smShadowMap.FindLightRectangle(*this, lr); + // if there is no influence + if ((lr.lr_pixSizeU==0) || (lr.lr_pixSizeV==0)) { + // do nothing + return; + } + // create a new layer + CBrushShadowLayer &bsl = *new CBrushShadowLayer; + bsl.bsl_colLastAnim = 0x12345678; + // attach it to light source and shadow map + bsl.bsl_plsLightSource = this; + ls_lhLayers.AddTail(bsl.bsl_lnInLightSource); + bsl.bsl_pbsmShadowMap = &bpo.bpo_smShadowMap; + // if the light is dark light + if (ls_ulFlags & LSF_DARKLIGHT) { + // add to end of list + bpo.bpo_smShadowMap.bsm_lhLayers.AddTail(bsl.bsl_lnInShadowMap); + // if the light is normal light + } else { + // add to beginning of list + bpo.bpo_smShadowMap.bsm_lhLayers.AddHead(bsl.bsl_lnInShadowMap); + } + + // initially it has no shadow + bsl.bsl_pubLayer = NULL; + bsl.bsl_ulFlags = 0; + + SetLayerParameters(bsl, bpo, lr); +} + +void CLightSource::UpdateLayer(CBrushShadowLayer &bsl) +{ + CBrushPolygon &bpo = *bsl.bsl_pbsmShadowMap->GetBrushPolygon(); + // find the influenced rectangle + CLightRectangle lr; + bsl.bsl_pbsmShadowMap->FindLightRectangle(*this, lr); + + // if there is no influence + if ((lr.lr_pixSizeU==0) || (lr.lr_pixSizeV==0)) { + // invalidate its shadow map + bsl.bsl_pbsmShadowMap->Invalidate(ls_ulFlags&LSF_DYNAMIC); + bpo.bpo_ulFlags &= ~BPOF_MARKEDLAYER; + // delete the layer + delete &bsl; + return; + } + // discard shadows on the layer + bsl.DiscardShadows(); + SetLayerParameters(bsl, bpo, lr); +} + +static inline BOOL IsPolygonInfluencedByDirectionalLight(CBrushPolygon *pbpo) +{ + ULONG ulFlags = pbpo->bpo_ulFlags; + // if polygon has no directional light + if (!(ulFlags&(BPOF_HASDIRECTIONALLIGHT|BPOF_HASDIRECTIONALAMBIENT))) { + // not influenced + return FALSE; + } + + // if has no shadows + BOOL bIsTransparent = (ulFlags&BPOF_PORTAL) && !(ulFlags&(BPOF_TRANSLUCENT|BPOF_TRANSPARENT)); + BOOL bTakesShadow = !(ulFlags&BPOF_FULLBRIGHT); + if (bIsTransparent || !bTakesShadow) { + // not influenced + return FALSE; + } + + // influenced + return TRUE; +} + +// find all shadow maps that should have layers from this light source +void CLightSource::FindShadowLayersDirectional(BOOL bSelectedOnly) +{ + // for each layer of the light source + {FORDELETELIST(CBrushShadowLayer, bsl_lnInLightSource, ls_lhLayers, itbsl) { + CBrushPolygon *pbpo = itbsl->bsl_pbsmShadowMap->GetBrushPolygon(); + // if only selected polygons are checked, and this one is not selected + if (bSelectedOnly && !(pbpo->bpo_ulFlags&BPOF_SELECTED)) { + // skip it + continue; + } + // if the polygon is influenced + if (IsPolygonInfluencedByDirectionalLight(pbpo)) { + // mark it + pbpo->bpo_ulFlags |= BPOF_MARKEDLAYER; + // update its parameters + UpdateLayer(*itbsl); + // if the polygon is not influenced + } else { + // invalidate its shadow map + itbsl->bsl_pbsmShadowMap->Invalidate(ls_ulFlags&LSF_DYNAMIC); + // delete the layer + delete &*itbsl; + } + }} + + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(ls_penEntity->en_pwoWorld->wo_cenEntities, CEntity, iten) { + // if it is brush entity + if (iten->en_RenderType == CEntity::RT_BRUSH) { + // for each mip in its brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) { + // for all sectors in this mip + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // for each polygon in sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + CBrushPolygon *pbpo = itbpo; + // if only selected polygons are checked, and this one is not selected + if (bSelectedOnly && !(pbpo->bpo_ulFlags&BPOF_SELECTED)) { + // skip it + continue; + } + // if the polygon is not marked but it is influenced + if (!(pbpo->bpo_ulFlags&BPOF_MARKEDLAYER) + &&IsPolygonInfluencedByDirectionalLight(pbpo)) { + // add a layer to the polygon + AddLayer(*pbpo); + } + } + } + } + } + }} + + // for each layer of the light source + {FOREACHINLIST(CBrushShadowLayer, bsl_lnInLightSource, ls_lhLayers, itbsl) { + CBrushPolygon *pbpo = itbsl->bsl_pbsmShadowMap->GetBrushPolygon(); + // unmark the polygon + pbpo->bpo_ulFlags &= ~BPOF_MARKEDLAYER; + }} +} + +static const FLOAT3D *_pvOrigin; +static FLOATaabbox3D _boxLight; +static BOOL _bCastShadows; +static FLOAT _rRange; +static FLOAT _fEpsilon; +static INDEX _iDynamic; // 0=disallow, 1=maybe (depend on flag), 2=allow + + +static inline BOOL IsPolygonInfluencedByPointLight(CBrushPolygon *pbpo) +{ + ULONG ulFlags = pbpo->bpo_ulFlags; + + // if has no shadows + BOOL bIsTransparent = (ulFlags&BPOF_PORTAL) && !(ulFlags&(BPOF_TRANSLUCENT|BPOF_TRANSPARENT)); + BOOL bTakesShadow = !(ulFlags&BPOF_FULLBRIGHT); + if( bIsTransparent || !bTakesShadow) { + // not influenced + return FALSE; + } + + // if in range of light + if( _boxLight.HasContactWith(pbpo->bpo_boxBoundingBox)) { + // find distance of light from the plane + const FLOAT fDistance = pbpo->bpo_pbplPlane->bpl_plAbsolute.PointDistance(*_pvOrigin); + // if the polygon is in range, (and not behind for diffuse lights) + if( fDistance<=_rRange && (!_bCastShadows || fDistance>_fEpsilon)) { + // if this light is allowed on this polygon + if( _iDynamic==2 || (!(ulFlags&BPOF_NODYNAMICLIGHTS) && _iDynamic==1)) { + // influenced + return TRUE; + } + } + } + // not influenced + return FALSE; +} + + +extern CEntity *_penLightUpdating = NULL; + +void CLightSource::FindShadowLayersPoint(BOOL bSelectedOnly) +{ + // find bounding sphere and bounding box of the light influence + _rRange = ls_rFallOff; + _pvOrigin = &ls_penEntity->en_plPlacement.pl_PositionVector; + _boxLight = FLOATaabbox3D(*_pvOrigin, _rRange); + _bCastShadows = ls_ulFlags & LSF_CASTSHADOWS; + _fEpsilon = (ls_fFarClipDistance+ls_fNearClipDistance)*1.1f; + + // determine whether this light influences polygon + _iDynamic = 2; + if( ls_ulFlags&LSF_NONPERSISTENT) { + extern INDEX shd_iAllowDynamic; + if( ((ULONG)shd_iAllowDynamic) > 2) shd_iAllowDynamic = 1L; // clamp fast + _iDynamic = shd_iAllowDynamic; + } + + // for each layer of the light source + DOUBLE3D dvOrigin = FLOATtoDOUBLE(*_pvOrigin); + {FORDELETELIST(CBrushShadowLayer, bsl_lnInLightSource, ls_lhLayers, itbsl) { + CBrushPolygon *pbpo = itbsl->bsl_pbsmShadowMap->GetBrushPolygon(); + CEntity *penWithPolygon = pbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + // fixup for fast moving brush shadow recalculation + if (_penLightUpdating!=NULL && _penLightUpdating!=penWithPolygon) { + continue; + } + // if only selected polygons are checked, and this one is not selected + if (bSelectedOnly && !(pbpo->bpo_ulFlags&BPOF_SELECTED)) { + // skip it + continue; + } + + // if the polygon is influenced + if (IsPolygonInfluencedByPointLight(pbpo)) { + // mark it + pbpo->bpo_ulFlags |= BPOF_MARKEDLAYER; + // update its parameters + UpdateLayer(*itbsl); + // if the polygon is not influenced + } else { + // invalidate its shadow map + itbsl->bsl_pbsmShadowMap->Invalidate(ls_ulFlags&LSF_DYNAMIC); + // delete the layer + delete &*itbsl; + } + }} + + // if it is a movable entity + if (ls_penEntity->en_ulPhysicsFlags&EPF_MOVABLE) { + CMovableEntity *pen = (CMovableEntity *)ls_penEntity; + + // for each polygon cached near the entity + CStaticStackArray &apbpo = pen->en_apbpoNearPolygons; + for (INDEX iPolygon=0; iPolygonbpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + // fixup for fast moving brush shadow recalculation + if (_penLightUpdating!=NULL && _penLightUpdating!=penWithPolygon) { + continue; + } + // if the polygon is not marked but it is influenced + if (!(pbpo->bpo_ulFlags&BPOF_MARKEDLAYER) + &&IsPolygonInfluencedByPointLight(pbpo)) { + // add a layer to the polygon + AddLayer(*pbpo); + } + } + + // if it is not a movable entity + } else { + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(ls_penEntity->en_pwoWorld->wo_cenEntities, CEntity, iten) { + // fixup for fast moving brush shadow recalculation + if (_penLightUpdating!=NULL && _penLightUpdating!=&*iten) { + continue; + } + // if it is brush entity + if (iten->en_RenderType == CEntity::RT_BRUSH) { + // for each mip in its brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) { + // if the mip doesn't have contact with the light + if (!itbm->bm_boxBoundingBox.HasContactWith(_boxLight)) { + // skip it + continue; + } + // for all sectors in this mip + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // if the sector doesn't have contact with the light + if (!itbsc->bsc_boxBoundingBox.HasContactWith(_boxLight) + ||(itbsc->bsc_bspBSPTree.bt_pbnRoot!=NULL + &&!(itbsc->bsc_bspBSPTree.TestSphere( + dvOrigin, FLOATtoDOUBLE(_rRange))>=0) )) { + // skip it + continue; + } + // for each polygon in sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + // if only selected polygons are checked, and this one is not selected + if (bSelectedOnly && !(itbpo->bpo_ulFlags&BPOF_SELECTED)) { + // skip it + continue; + } + // if the polygon is not marked but it is influenced + if (!(itbpo->bpo_ulFlags&BPOF_MARKEDLAYER) + &&IsPolygonInfluencedByPointLight(itbpo)) { + // add a layer to the polygon + AddLayer(*itbpo); + } + } + } + } + } + }} + } + + // for each layer of the light source + {FOREACHINLIST(CBrushShadowLayer, bsl_lnInLightSource, ls_lhLayers, itbsl) { + CBrushPolygon *pbpo = itbsl->bsl_pbsmShadowMap->GetBrushPolygon(); + // unmark the polygon + pbpo->bpo_ulFlags &= ~BPOF_MARKEDLAYER; + }} +} + +void CLightSource::FindShadowLayers(BOOL bSelectedOnly) +{ + // if the light is used for lens flares only + if (ls_ulFlags&LSF_LENSFLAREONLY) { + // do nothing + return; + } + + // use spatial classification!!!! + + // find the influenced polygons + if (ls_ulFlags&LSF_DIRECTIONAL) { + FindShadowLayersDirectional(bSelectedOnly); + } else { + FindShadowLayersPoint(bSelectedOnly); + } +} + + +// Update shadow map on all terrains in world without moving +void CLightSource::UpdateTerrains(void) +{ + if(ls_penEntity==NULL) { + return; + } + CPlacement3D &pl = ls_penEntity->en_plPlacement; + UpdateTerrains(pl,pl); + +} +// Update shadow map on all terrains in world +void CLightSource::UpdateTerrains(CPlacement3D plOld, CPlacement3D plNew) +{ + // if this is dynamic light + if(ls_ulFlags&LSF_DYNAMIC) { + // do not terrain update shadow map + return; + } + + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(ls_penEntity->en_pwoWorld->wo_cenEntities, CEntity, iten) { + // if it is terrain entity + if(iten->en_RenderType == CEntity::RT_TERRAIN) { + CTerrain *ptrTerrain = iten->GetTerrain(); + ASSERT(ptrTerrain!=NULL); + // Calculate bboxes of light at old position and new position + FLOATaabbox3D bboxLightOld = FLOATaabbox3D(plOld.pl_PositionVector,ls_rFallOff); + FLOATaabbox3D bboxLightNew = FLOATaabbox3D(plNew.pl_PositionVector,ls_rFallOff); + FLOATaabbox3D bboxLightPos = FLOATaabbox3D(plNew.pl_PositionVector); + + if(ls_ulFlags&LSF_DIRECTIONAL) { + ptrTerrain->UpdateShadowMap(); + } else { + if(bboxLightPos.HasContactWith(bboxLightOld)) { + FLOATaabbox3D bboxLightAll = bboxLightOld; + bboxLightAll |= bboxLightNew; + ptrTerrain->UpdateShadowMap(&bboxLightAll,TRUE); + } else { + // Update part of shadow map where light was before moving + ptrTerrain->UpdateShadowMap(&bboxLightOld,TRUE); + // Update part of shadow map where light is now + ptrTerrain->UpdateShadowMap(&bboxLightNew,TRUE); + } + } + } + }} +} + +// set properties of the light source without discarding shadows +void CLightSource::SetLightSourceWithNoDiscarding( const CLightSource &lsOriginal) +{ + // just copy all properties + ls_ulFlags = lsOriginal.ls_ulFlags; + ls_rHotSpot = lsOriginal.ls_rHotSpot; + ls_rFallOff = lsOriginal.ls_rFallOff; + ls_colColor = lsOriginal.ls_colColor & ~0xFF; + ls_colAmbient = lsOriginal.ls_colAmbient & ~0xFF; + ls_ubLightAnimationObject = lsOriginal.ls_ubLightAnimationObject; + ls_ubPolygonalMask = lsOriginal.ls_ubPolygonalMask; + ls_fNearClipDistance = lsOriginal.ls_fNearClipDistance; + ls_fFarClipDistance = lsOriginal.ls_fFarClipDistance; + ls_plftLensFlare = lsOriginal.ls_plftLensFlare; + ls_paoLightAnimation = lsOriginal.ls_paoLightAnimation; + ls_paoAmbientLightAnimation = lsOriginal.ls_paoAmbientLightAnimation; +} + +// set properties of the light source and discard shadows if neccessary +void CLightSource::SetLightSource(const CLightSource &lsOriginal) +{ + // test if layers should be discarded + BOOL bDiscardLayers = + ls_rFallOff != lsOriginal.ls_rFallOff || + ls_ubPolygonalMask != lsOriginal.ls_ubPolygonalMask || + ls_ulFlags != lsOriginal.ls_ulFlags || + ls_fNearClipDistance != lsOriginal.ls_fNearClipDistance || + ls_fFarClipDistance != lsOriginal.ls_fFarClipDistance ; + // test if shadows should be uncached + BOOL bUncacheShadows = bDiscardLayers || + ls_rHotSpot != lsOriginal.ls_rHotSpot || + ls_colColor != lsOriginal.ls_colColor || + ls_colAmbient != lsOriginal.ls_colAmbient || + ls_ubLightAnimationObject != lsOriginal.ls_ubLightAnimationObject ; + // discard shadows if needed + if( bDiscardLayers) { + DiscardShadowLayers(); + } else if( bUncacheShadows) { + UncacheShadowMaps(); + } + // set the light properties + SetLightSourceWithNoDiscarding(lsOriginal); + // find all shadow maps that should have layers from this light source if needed + if( bDiscardLayers) { + FindShadowLayers(FALSE); + } + + UpdateTerrains(); +} + + +// get color of light accounting for possible animation +COLOR CLightSource::GetLightColor(void) const +{ + // no animation? + if( ls_paoLightAnimation==NULL) return ls_colColor; + // animation! + UBYTE ubR, ubG, ubB; + GetLightColor( ubR, ubG, ubB); + return RGBToColor( ubR, ubG, ubB); +} + +void CLightSource::GetLightColor( UBYTE &ubR, UBYTE &ubG, UBYTE &ubB) const +{ + // no animation? + ColorToRGB( ls_colColor, ubR, ubG, ubB); + if( ls_paoLightAnimation==NULL) return; + // animation! + FLOAT fRatio; + COLOR col0, col1; + UBYTE ubMR, ubMG, ubMB; + ls_paoLightAnimation->GetFrame( (SLONG&)col0, (SLONG&)col1, fRatio); + LerpColor( col0, col1, fRatio, ubMR, ubMG, ubMB); + ubR = ( ((((SLONG)ubR)<<8)|ubR) * ((((SLONG)ubMR)<<8)|ubMR) ) >>24; + ubG = ( ((((SLONG)ubG)<<8)|ubG) * ((((SLONG)ubMG)<<8)|ubMG) ) >>24; + ubB = ( ((((SLONG)ubB)<<8)|ubB) * ((((SLONG)ubMB)<<8)|ubMB) ) >>24; +} + + +// get ambient color of light accounting for possible animation +COLOR CLightSource::GetLightAmbient(void) const +{ + if( ls_paoAmbientLightAnimation==NULL) return ls_colAmbient; + UBYTE ubAR, ubAG, ubAB; + GetLightAmbient( ubAR, ubAG, ubAB); + return RGBToColor( ubAR, ubAG, ubAB); +} + +void CLightSource::GetLightAmbient( UBYTE &ubAR, UBYTE &ubAG, UBYTE &ubAB) const +{ + ColorToRGB( ls_colAmbient, ubAR, ubAG, ubAB); + if( ls_paoAmbientLightAnimation==NULL) return; + FLOAT fRatio; + COLOR col0, col1; + UBYTE ubMR, ubMG, ubMB; + ls_paoAmbientLightAnimation->GetFrame( (SLONG&)col0, (SLONG&)col1, fRatio); + LerpColor( col0, col1, fRatio, ubMR, ubMG, ubMB); + ubAR = ( ((((SLONG)ubAR)<<8)|ubAR) * ((((SLONG)ubMR)<<8)|ubMR) ) >>24; + ubAG = ( ((((SLONG)ubAG)<<8)|ubAG) * ((((SLONG)ubMG)<<8)|ubMG) ) >>24; + ubAB = ( ((((SLONG)ubAB)<<8)|ubAB) * ((((SLONG)ubMB)<<8)|ubMB) ) >>24; +} diff --git a/Sources/Engine/Light/LightSource.h b/Sources/Engine/Light/LightSource.h new file mode 100644 index 0000000..1dc91f4 --- /dev/null +++ b/Sources/Engine/Light/LightSource.h @@ -0,0 +1,100 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_LIGHTSOURCE_H +#define SE_INCL_LIGHTSOURCE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Structure describing properties of a light source entity. + */ +#define LSF_DIRECTIONAL (1L<<0) // rays are not emanating from point, but from direction +#define LSF_CASTSHADOWS (1L<<1) // light can cast shadows +#define LSF_DIFFUSION (1L<<2) // intensity depends on angle with polygon normal +#define LSF_DARKLIGHT (1L<<3) // darkens polygons instead of lighting them +#define LSF_SUBSTRACTSECTORAMBIENT (1L<<4) // sector ambient is substract from intensity +#define LSF_NONPERSISTENT (1L<<5) // not saved (can change during game) +#define LSF_LENSFLAREONLY (1L<<6) // no light, only lens flare +#define LSF_DYNAMIC (1L<<7) // dynamic light (fast frequent caching, no shadows) + +class ENGINE_API CLightSource +{ +public: +// implementation: + // constructor + CLightSource(void); + // destructor + ~CLightSource(void); + CListHead ls_lhLayers; // list of shadow map layers of this light source + class CEntity *ls_penEntity; // the entity of this light source + + ULONG ls_ulFlags; // various flags + + RANGE ls_rHotSpot; // distance before intensity starts to fall off + RANGE ls_rFallOff; // distance before intensity reaches zero + + COLOR ls_colColor; // light color + COLOR ls_colAmbient; // ambient color (for directional lights only) + UBYTE ls_ubLightAnimationObject; // light animation - 0 for non animating lights + UBYTE ls_ubPolygonalMask; // mask for casting rays only through some polygons + + FLOAT ls_fNearClipDistance; // clip plane distance near light + FLOAT ls_fFarClipDistance; // clip plane distance near polygon + + class CLensFlareType *ls_plftLensFlare; // type of lens flare to use or NULL for none + CAnimObject *ls_paoLightAnimation; // animobject for light animating + CAnimObject *ls_paoAmbientLightAnimation; // animobject for light animating + + // test if a polygon has a layer from this light source + BOOL PolygonHasLayer(CBrushPolygon &bpo); + + // set layer parameters + void SetLayerParameters(CBrushShadowLayer &bsl, CBrushPolygon &bpo, class CLightRectangle &lr); + // update layer parameters + void UpdateLayer(CBrushShadowLayer &bsl); + // add a layer to a polygon + void AddLayer(CBrushPolygon &bpo); + // update layer parameters + void UpdateLayer(CBrushPolygon &bpo); + // uncache all influenced shadow maps, but keep shadow layers + void UncacheShadowMaps(void); + // discard all linked shadow layers + void DiscardShadowLayers(void); + // find all shadow maps that should have layers from this light source + void FindShadowLayers(BOOL bSelectedOnly); + void FindShadowLayersDirectional(BOOL bSelectedOnly); + void FindShadowLayersPoint(BOOL bSelectedOnly); + // update shadow map on all terrains in world + void UpdateTerrains(CPlacement3D plOld, CPlacement3D plNew); + void UpdateTerrains(void); + +// interface: + // set properties of the light source without discarding shadows + void SetLightSourceWithNoDiscarding(const CLightSource &lsOriginal); + // set properties of the light source and discard shadows if neccessary + void SetLightSource(const CLightSource &lsOriginal); + // get color of light acounting for possible animation + COLOR GetLightColor(void) const; + void GetLightColor( UBYTE &ubR, UBYTE &ubG, UBYTE &ubB) const; + COLOR GetLightAmbient(void) const; + void GetLightAmbient( UBYTE &ubAR, UBYTE &ubAG, UBYTE &ubAB) const; + inline void GetLightColorAndAmbient( COLOR &colLight, COLOR &colAmbient) const { + colLight = GetLightColor(); + colAmbient = GetLightAmbient(); + } + inline void GetLightColorAndAmbient( UBYTE &ubR, UBYTE &ubG, UBYTE &ubB, + UBYTE &ubAR, UBYTE &ubAG, UBYTE &ubAB) const { + GetLightColor( ubR, ubG, ubB); + GetLightAmbient( ubAR, ubAG, ubAB); + } + // read/write from a stream + void Read_t( CTStream *pstrm); // throw char * + void Write_t( CTStream *pstrm); // throw char * +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Light/Shadows_internal.h b/Sources/Engine/Light/Shadows_internal.h new file mode 100644 index 0000000..90d18cc --- /dev/null +++ b/Sources/Engine/Light/Shadows_internal.h @@ -0,0 +1,14 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +class CLightRectangle { +public: + // the rectangle coordinates + PIX lr_pixMinU; + PIX lr_pixMinV; + PIX lr_pixSizeU; + PIX lr_pixSizeV; + // point on the plane closest to the light + FLOAT lr_fpixHotU; + FLOAT lr_fpixHotV; + FLOAT lr_fLightPlaneDistance; +}; \ No newline at end of file diff --git a/Sources/Engine/Math/AABBox.h b/Sources/Engine/Math/AABBox.h new file mode 100644 index 0000000..6e0c6c4 --- /dev/null +++ b/Sources/Engine/Math/AABBox.h @@ -0,0 +1,380 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_AABBOX_H +#define SE_INCL_AABBOX_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* + * Template for axis-aligned bounding box of arbitrary dimensions + */ +template +class AABBox { +// implementation: +public: + Vector minvect; // vector of min coordinates + Vector maxvect; // vector of max coordinates + + /* Clear to normalized empty bounding box. */ + inline void SetToNormalizedEmpty(void); +// interface: +public: + /* Default constructor. */ + inline AABBox(void); + /* Constructor for one-point bounding box. */ + inline AABBox(const Vector &vPoint); + /* Constructor for one-point and radius bounding box. */ + inline AABBox(const Vector &vPoint, const Type radius); + /* Constructor for two diagonal points. */ + inline AABBox(const Vector &vPoint1, const Vector &vPoint2); + + /* Bounding box for union. */ + inline AABBox &operator|=(const AABBox &b); + /* Bounding box for intersection. */ + inline AABBox &operator&=(const AABBox &b); + /* Bounding box for intersection. */ + inline AABBox operator&(const AABBox &b) const; + /* Function for moving bounding box. */ + inline AABBox &operator+=(const Vector &vct); + inline AABBox &operator-=(const Vector &vct); + /* Function for testing equality of bounding boxes. */ + inline BOOL operator==(const AABBox &box2) const; + /* Function for testing difference between bounding boxes. */ + inline BOOL operator!=(const AABBox &box2) const; + /* Test if the bounding box contains another bounding box. */ + inline BOOL operator>=(const AABBox &b) const; + /* Test if the bounding box is contained in another bounding box. */ + inline BOOL operator<=(const AABBox &b) const; + + /* Get diagonal vector (size of box). */ + inline const Vector Size(void) const; + /* Get center vector (middle of box). */ + inline const Vector Center(void) const; + /* Get minimal vector (lower left of box). */ + inline const Vector &Min(void) const; + /* Get maximal vector (upper right of box). */ + inline const Vector &Max(void) const; + /* Check if empty. */ + inline BOOL IsEmpty(void) const; + + /* Check if intersects or touches another bounding box. */ + inline BOOL HasContactWith(const AABBox &b) const; + inline BOOL HasContactWith(const AABBox &b, Type tEpsilon) const; + /* Check if intersects or touches a sphere. */ + inline BOOL TouchesSphere( + const Vector &vSphereCenter, Type fSphereRadius) const; + + // expand the bounding box by given size + inline void Expand(Type tEpsilon); + // expand the bounding box by given factor of its size along each axis + inline void ExpandByFactor(Type tFactor); + // stretch the bounding box by a given sizing factor + inline void StretchByFactor(Type tSizing); + // stretch the bounding box by a given sizing vector + inline void StretchByVector(Vector vSizing); +}; + +/* + * Clear to normalized empty bounding box. + */ +template +inline void AABBox::SetToNormalizedEmpty(void) { + for ( int i=1; i<=iDimensions; i++ ) { + minvect(i) = UpperLimit(Type(0)); + maxvect(i) = LowerLimit(Type(0)); + } +} + +/* + * Constructor for empty bounding box. + */ +template +inline AABBox::AABBox() { + SetToNormalizedEmpty(); +} + +/* + * Constructor for one-point bounding box. + */ +template +inline AABBox::AABBox(const Vector &vPoint) { + for ( int i=1; i<=iDimensions; i++ ) { + minvect(i) = maxvect(i) = vPoint(i); + } +} + +/* + * Constructor for one-point and radius bounding box. + */ +template +inline AABBox::AABBox(const Vector &vPoint, const Type radius) { + for ( int i=1; i<=iDimensions; i++ ) { + minvect(i) = vPoint(i)-radius; + maxvect(i) = vPoint(i)+radius; + } +} + +/* + * Constructor for two diagonal points. + */ +template +inline AABBox::AABBox(const Vector &vPoint1, const Vector &vPoint2) { + for ( int i=1; i<=iDimensions; i++ ) { + minvect(i) = ::Min(vPoint1(i), vPoint2(i)); + maxvect(i) = ::Max(vPoint1(i), vPoint2(i)); + } +} + +/* + * Function for testing equality of bounding boxes. + */ +template +inline BOOL AABBox::operator==(const AABBox &box2) const { + return ( (minvect==box2.minvect) && (maxvect==box2.maxvect) ); +} + +/* + * Function for testing diferences between bounding boxes. + */ +template +inline BOOL AABBox::operator!=(const AABBox &box2) const { + return !(*this == box2); +} + +/* + * Test if the bounding box contains another bounding box. + */ +template +inline BOOL AABBox::operator>=(const AABBox &b) const +{ + return b<=*this; +} + +/* + * Test if the bounding box is contained in another bounding box. + */ +template +inline BOOL AABBox::operator<=(const AABBox &b) const +{ + // for each dimension + for (INDEX i=1; i<=iDimensions; i++ ) { + // if that dimension's span is not contained + if (minvect(i) < b.minvect(i) || maxvect(i) > b.maxvect(i)) { + // the box is not contained + return FALSE; + } + } + // otherwise, it is contained + return TRUE; +} + +/* + * Check if empty. + */ +template +inline BOOL AABBox::IsEmpty(void) const { + // if any dimension is empty, it is empty + for ( int i=1; i<=iDimensions; i++ ) { + if (minvect(i) > maxvect(i)) { + return TRUE; + } + } + // otherwise, it is not empty + return FALSE; +} + +/* + * Get center vector (middle of box). + */ +template +inline const Vector AABBox::Center(void) const { + // center is in the middle between min and max + return (maxvect + minvect)/(Type)2; +} + +/* + * Get diagonal vector (size of box). + */ +template +inline const Vector AABBox::Size(void) const { + // size is difference between min and max vectors + return maxvect - minvect; +} + +/* + * Get minimal vector (lower left of box). + */ +template +inline const Vector &AABBox::Min(void) const { + return minvect; +} + +/* + * Get maximal vector (upper right of box). + */ +template +inline const Vector &AABBox::Max(void) const { + return maxvect; +} + +/* + * Bounding box for union. + */ +template +inline AABBox &AABBox::operator|=(const AABBox &b) { + for ( int i=1; i<=iDimensions; i++ ) { + minvect(i) = ::Min(minvect(i), b.minvect(i)); + maxvect(i) = ::Max(maxvect(i), b.maxvect(i)); + } + return *this; +} + +/* + * Bounding box for intersection. + */ +template +inline AABBox &AABBox::operator&=(const AABBox &b) { + for ( int i=1; i<=iDimensions; i++ ) { + minvect(i) = ::Max(minvect(i), b.minvect(i)); + maxvect(i) = ::Min(maxvect(i), b.maxvect(i)); + } + // if the result is empty bounding box, normalize it + if ( IsEmpty() ) SetToNormalizedEmpty(); + return *this; +} + +/* + * Function for moving bounding box. + */ +template +inline AABBox &AABBox::operator+=(const Vector &vct) { + minvect += vct; + maxvect += vct; + return *this; +} + +template +inline AABBox &AABBox::operator-=(const Vector &vct) { + minvect -= vct; + maxvect -= vct; + return *this; +} + +/* Bounding box for intersection. */ +template +inline AABBox AABBox::operator&(const AABBox &b) const { + return AABBox(*this)&=b; +} + +/* Check if intersects or touches another bounding box. */ +template +inline BOOL AABBox::HasContactWith(const AABBox &b) const +{ + // for all dimensions + for ( int i=1; i<=iDimensions; i++ ) { + // if spans in that dimension don't have contact + if (maxvect(i)b.maxvect(i) ) { + // whole bounding boxes don't have contact + return FALSE; + } + } + return TRUE; +} + +/* Check if intersects or touches another bounding box. */ +template +inline BOOL AABBox::HasContactWith(const AABBox &b, Type tEpsilon) const +{ + // for all dimensions + for ( int i=1; i<=iDimensions; i++ ) { + // if spans in that dimension don't have contact + if( (maxvect(i)+tEpsilonb.maxvect(i)) ) { + // whole bounding boxes don't have contact + return FALSE; + } + } + return TRUE; +} +/* Check if intersects or touches a sphere. */ +template +inline BOOL AABBox::TouchesSphere( + const Vector &vSphereCenter, Type fSphereRadius) const +{ + // for all dimensions + for ( int i=1; i<=iDimensions; i++ ) { + // if spans in that dimension don't have contact + if( (vSphereCenter(i)+fSphereRadiusmaxvect(i)) ) { + // no contact + return FALSE; + } + } + return TRUE; +} + +// expand the bounding box by given size +template +inline void AABBox::Expand(Type tEpsilon) +{ + // for all dimensions + for ( int i=1; i<=iDimensions; i++ ) { + // expand in that dimension + maxvect(i)+=tEpsilon; + minvect(i)-=tEpsilon; + } +} + +// expand the bounding box by given factor of its size along each axis +template +inline void AABBox::ExpandByFactor(Type tFactor) +{ + // for all dimensions + for ( int i=1; i<=iDimensions; i++ ) { + // expand in that dimension + Type tEpsilon = (maxvect(i)-minvect(i))*tFactor; + maxvect(i)+=tEpsilon; + minvect(i)-=tEpsilon; + } +} + +// stretch the bounding box by a given sizing factor +template +inline void AABBox::StretchByFactor(Type tSizing) +{ + tSizing = Abs(tSizing); + // for each dimension + for ( int i=1; i<=iDimensions; i++ ) { + // stretch in that dimension + maxvect(i)*=tSizing; + minvect(i)*=tSizing; + } +} + +// stretch the bounding box by a given sizing vector +template +inline void AABBox::StretchByVector(Vector vSizing) +{ + // for each dimension + for ( int i=1; i<=iDimensions; i++ ) { + // stretch in that dimension + maxvect(i)*=Abs(vSizing(i)); + minvect(i)*=Abs(vSizing(i)); + } +} + +// helper functions for converting between FLOAT and DOUBLE aabboxes +inline DOUBLEaabbox3D FLOATtoDOUBLE(const FLOATaabbox3D &plf) { + return DOUBLEaabbox3D( FLOATtoDOUBLE(plf.Min()), FLOATtoDOUBLE(plf.Max())); +} +inline FLOATaabbox3D DOUBLEtoFLOAT(const DOUBLEaabbox3D &pld) { + return FLOATaabbox3D( DOUBLEtoFLOAT(pld.Min()), DOUBLEtoFLOAT(pld.Max())); +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/Clipping.inl b/Sources/Engine/Math/Clipping.inl new file mode 100644 index 0000000..886c896 --- /dev/null +++ b/Sources/Engine/Math/Clipping.inl @@ -0,0 +1,406 @@ + +/* + * Line clipping flags + */ +#define LCF_REMOVED (0x00L) // the entire edge is invisible +#define LCF_UNCLIPPED (0x80L) // this point remains unclipped +#define LCF_NEAR (0x01L) // this point is clipped at near plane +#define LCF_FAR (0x02L) // this point is clipped at far plane +#define LCF_LEFT (0x04L) // this point is clipped at left plane +#define LCF_RIGHT (0x08L) // this point is clipped at right plane +#define LCF_TOP (0x10L) // this point is clipped at top plane +#define LCF_BOTTOM (0x20L) // this point is clipped at bottom plane + +#define LCF_EDGEREMOVED (0x0000L) // used for testing if entire edge is removed +// shifts used for clip flags for start/end vertex +#define LCS_VERTEX0 (0) +#define LCS_VERTEX1 (8) +// masks used for clip flags for start/end vertex +#define LCM_VERTEX0 (0x00FFL) +#define LCM_VERTEX1 (0xFF00L) +// creating line clip flags for start/end vertex +#define LCFVERTEX0(lcf) ((lcf)< 0) + { + if( fedgy2 > 0) return; + + if( fedgx1 <= 0) + { + if( fedgx2 <= 0) return; + } + else if( fedgx2 > 0) + { + ci_ct ++; + return; + } + } + else + { + if( fedgy2 <= 0) return; + + if( fedgx1 <= 0) + { + if( fedgx2 <= 0) return; + } + else if( fedgx2 > 0) + { + ci_ct ++; + return; + } + } + // here we calculate x coordinate of edge and +x axis intersection point + FLOAT a, b; + a = (fedgy2 - fedgy1)/(fedgx2 - fedgx1); + b = fedgy1 - a*fedgx1; + if( -b/a < 0) return; // no intersection, intersection coordinate x is left from 0 + ci_ct ++; +} + +/* rcg10042001 !!! FIXME */ +#ifdef _MSC_VER + #define ASMOPT 1 +#endif + +// how much are the clip planes offset inside frustum +#define CLIPPLANE_EPSILON (1E-3f) + +/* + * Clip a line by a single plane -- helper function. + */ +inline BOOL ClipLineByNearPlane(FLOAT3D &v0, FLOAT3D &v1, FLOAT fPlaneDistance, + ULONG &ulCode0, ULONG &ulCode1, ULONG ulCodeClip) +{ +#if ASMOPT + static FLOAT f1=1; + static FLOAT fDistance0, fDistance1; + __asm { + mov esi,D [v0] + mov edi,D [v1] + + fld D [fPlaneDistance] + fchs + + fld D [esi+ 8] + fsubr st(0),st(1) + fld D [edi+ 8] + fsubp st(2),st(0) + fstp D [fDistance0] + fst D [fDistance1] + + fsubr D [fDistance0] + fdivr D [f1] + + cmp D [fDistance0],0 + jg firstFront + + +;firstBack: + cmp D [fDistance1],0 + jle falseRet + +;secondFront: + mov eax,D [fPlaneDistance] + mov ebx,D [ulCode0] + xor eax,80000000h + mov edx,D [ulCodeClip] + mov D [esi+ 8],eax + mov D [ebx],edx + + fmul D [fDistance0] + ;//st0=fFactor + fld D [esi+ 0] + fsub D [edi+ 0] + fld D [esi+ 4] + fsub D [edi+ 4] + ;//st0=v0(2)-v1(2), st1=v0(1)-v1(1), st2=fFactor + fxch st(1) + fmul st(0),st(2) + fxch st(1) + fmulp st(2),st(0) + ;//st0=(v0(1)-v1(1))*fFactor, st1=(v0(2)-v1(2))*fFactor + fsubr D [esi+ 0] + fxch st(1) + fsubr D [esi+ 4] + fxch st(1) + fstp D [esi+ 0] + fst D [esi+ 4] + jmp trueRet + + firstFront: + cmp D [fDistance1],0 + jg trueRet + +;secondBack: + mov eax,D [fPlaneDistance] + mov ebx,D [ulCode1] + mov edx,D [ulCodeClip] + xor eax,80000000h + shl edx,8 + mov D [edi+ 8],eax + mov D [ebx],edx + + fmul D [fDistance1] + ;//st0=fFactor + fld D [esi+ 0] + fsub D [edi+ 0] + fld D [esi+ 4] + fsub D [edi+ 4] + ;//st0=v0(2)-v1(2), st1=v0(1)-v1(1), st2=fFactor + fxch st(1) + fmul st(0),st(2) + fxch st(1) + fmulp st(2),st(0) + ;//st0=(v0(1)-v1(1))*fFactor, st1=(v0(2)-v1(2))*fFactor + fsubr D [edi+ 0] + fxch st(1) + fsubr D [edi+ 4] + fxch st(1) + fstp D [edi+ 0] + fst D [edi+ 4] + } +trueRet: + _asm fstp st(0) + return TRUE; +falseRet: + _asm fstp st(0) + return FALSE; +#else + // calculate point distances from clip plane + FLOAT fDistance0 = -fPlaneDistance-v0(3); + FLOAT fDistance1 = -fPlaneDistance-v1(3); + if (fDistance0<=0) { + // if both are back + if (fDistance1<=0) { + // no line remains + return FALSE; + // if first is back, second front + } else { + // clip first + FLOAT fDivisor = 1.0f/(fDistance0-fDistance1); + FLOAT fFactor = fDistance0*fDivisor; + v0(1) = v0(1)-(v0(1)-v1(1))*fFactor; + v0(2) = v0(2)-(v0(2)-v1(2))*fFactor; + v0(3) = -fPlaneDistance; + // mark that first was clipped + ulCode0 = LCFVERTEX0(ulCodeClip); + // line remains + return TRUE; + } + } else { + // if first is front, second back + if (fDistance1<=0) { + // clip second + FLOAT fDivisor = 1.0f/(fDistance0-fDistance1); + FLOAT fFactor = fDistance1*fDivisor; + v1(1) = v1(1)-(v0(1)-v1(1))*fFactor; + v1(2) = v1(2)-(v0(2)-v1(2))*fFactor; + v1(3) = -fPlaneDistance; + // mark that second was clipped + ulCode1 = LCFVERTEX1(ulCodeClip); + // line remains + return TRUE; + // if both are front + } else { + // line remains unclipped + return TRUE; + } + } +#endif +} + +/* + * Clip a line by a single plane -- helper function. + */ +inline BOOL ClipLineByFarPlane(FLOAT3D &v0, FLOAT3D &v1, FLOAT fPlaneDistance, + ULONG &ulCode0, ULONG &ulCode1, ULONG ulCodeClip) +{ +#if ASMOPT + static FLOAT f1=1; + static FLOAT fDistance0, fDistance1; + __asm { + mov esi,D [v0] + mov edi,D [v1] + + fld D [fPlaneDistance] + fadd D [esi+ 8] + fld D [fPlaneDistance] + fadd D [edi+ 8] + fxch st(1) + fstp D [fDistance0] + fst D [fDistance1] + + fsubr D [fDistance0] + fdivr D [f1] + + cmp D [fDistance0],0 + jg firstFront + + +;firstBack: + cmp D [fDistance1],0 + jle falseRet + +;secondFront: + mov eax,D [fPlaneDistance] + mov ebx,D [ulCode0] + xor eax,80000000h + mov edx,D [ulCodeClip] + mov D [esi+ 8],eax + mov D [ebx],edx + + fmul D [fDistance0] + ;//st0=fFactor + fld D [esi+ 0] + fsub D [edi+ 0] + fld D [esi+ 4] + fsub D [edi+ 4] + ;//st0=v0(2)-v1(2), st1=v0(1)-v1(1), st2=fFactor + fxch st(1) + fmul st(0),st(2) + fxch st(1) + fmulp st(2),st(0) + ;//st0=(v0(1)-v1(1))*fFactor, st1=(v0(2)-v1(2))*fFactor + fsubr D [esi+ 0] + fxch st(1) + fsubr D [esi+ 4] + fxch st(1) + fstp D [esi+ 0] + fst D [esi+ 4] + jmp trueRet + + firstFront: + cmp D [fDistance1],0 + jg trueRet + +;secondBack: + mov eax,D [fPlaneDistance] + mov ebx,D [ulCode1] + mov edx,D [ulCodeClip] + xor eax,80000000h + shl edx,8 + mov D [edi+8],eax + mov D [ebx],edx + + fmul D [fDistance1] + ;//st0=fFactor + fld D [esi+ 0] + fsub D [edi+ 0] + fld D [esi+ 4] + fsub D [edi+ 4] + ;//st0=v0(2)-v1(2), st1=v0(1)-v1(1), st2=fFactor + fxch st(1) + fmul st(0),st(2) + fxch st(1) + fmulp st(2),st(0) + ;//st0=(v0(1)-v1(1))*fFactor, st1=(v0(2)-v1(2))*fFactor + fsubr D [edi+ 0] + fxch st(1) + fsubr D [edi+ 4] + fxch st(1) + fstp D [edi+ 0] + fst D [edi+ 4] + } +trueRet: + _asm fstp st(0) + return TRUE; +falseRet: + _asm fstp st(0) + return FALSE; +#else + // calculate point distances from clip plane + FLOAT fDistance0 = fPlaneDistance+v0(3); + FLOAT fDistance1 = fPlaneDistance+v1(3); + if (fDistance0<=0) { + // if both are back + if (fDistance1<=0) { + // no line remains + return FALSE; + // if first is back, second front + } else { + // clip first + FLOAT fDivisor = 1.0f/(fDistance0-fDistance1); + FLOAT fFactor = fDistance0*fDivisor; + v0(1) = v0(1)-(v0(1)-v1(1))*fFactor; + v0(2) = v0(2)-(v0(2)-v1(2))*fFactor; + v0(3) = -fPlaneDistance; + // mark that first was clipped + ulCode0 = LCFVERTEX0(ulCodeClip); + // line remains + return TRUE; + } + } else { + // if first is front, second back + if (fDistance1<=0) { + // clip second + FLOAT fDivisor = 1.0f/(fDistance0-fDistance1); + FLOAT fFactor = fDistance1*fDivisor; + v1(1) = v1(1)-(v0(1)-v1(1))*fFactor; + v1(2) = v1(2)-(v0(2)-v1(2))*fFactor; + v1(3) = -fPlaneDistance; + // mark that second was clipped + ulCode1 = LCFVERTEX1(ulCodeClip); + // line remains + return TRUE; + // if both are front + } else { + // line remains unclipped + return TRUE; + } + } +#endif +} + +static inline void MakeClipPlane(const FLOAT3D &vN, FLOAT fD, FLOATplane3D &pl) +{ + FLOAT fOoL = 1.0f/vN.Length(); + pl = FLOATplane3D(vN*fOoL, fD*fOoL); +} + +#undef ASMOPT + +#undef O +#undef Q +#undef D +#undef W +#undef B diff --git a/Sources/Engine/Math/FixInt.h b/Sources/Engine/Math/FixInt.h new file mode 100644 index 0000000..0d2209c --- /dev/null +++ b/Sources/Engine/Math/FixInt.h @@ -0,0 +1,85 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_FIXINT_H +#define SE_INCL_FIXINT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* + * iInt - number of bits in integer part + * iFrac - number of bits in fractional part + * NOTE: Since 32 bit integer holds this fix int, iInt+iFrac must be 32. + */ + +/* + * Template class for fixed integer with arbitrary sizes of integer and fractional parts + */ +template +class FixInt { +//implementation: +public: + SLONG slHolder; // the representation is stored here +//interface: +public: + /* Default constructor. */ + inline FixInt(void) {}; + /* Copy constructor. */ + inline FixInt(const FixInt &x) { slHolder = x.slHolder; }; + /* Constructor from integer. */ + inline FixInt(SLONG sl) : slHolder(sl<(ULONG ul) : slHolder((SLONG)(ul<(SWORD sw) : slHolder((SLONG)(sw<(UWORD uw) : slHolder((SLONG)(uw<(SBYTE sb) : slHolder((SLONG)(sb<(UBYTE ub) : slHolder((SLONG)(ub<(signed int si) : slHolder((SLONG)(si<(unsigned int ui) : slHolder((SLONG)(ui<(float f) : slHolder((SLONG)(f*(1L<(double f) : slHolder((SLONG)(f*(1L<(SLONG slNewHolder, int iDummy) : slHolder(slNewHolder) {}; + + /* Conversion to integer (truncatenation). */ + inline operator SLONG(void) const { return slHolder>>iFrac; }; + /* Conversion to float (exact). */ + inline operator float(void) const { return slHolder/(float) (1L< operator-(void) const { return FixInt(-slHolder, 1); }; + /* Addition. */ + inline FixInt &operator+=(FixInt x) { slHolder += x.slHolder; return *this; }; + inline FixInt operator+(FixInt x) const { return FixInt(slHolder+x.slHolder, 1); }; + /* Substraction. */ + inline FixInt &operator-=(FixInt x) { slHolder -= x.slHolder; return *this;}; + inline FixInt operator-(FixInt x) const { return FixInt(slHolder-x.slHolder, 1); }; + /* Multiplication. */ + inline FixInt operator*(FixInt x) const { return FixInt( (SLONG)((__int64(slHolder)*x.slHolder) >>iFrac), 1); }; + inline FixInt operator*(SLONG sl) const { return FixInt(slHolder*sl, 1); }; + friend inline FixInt operator*(SLONG sl, FixInt x){ return FixInt(x.slHolder*sl, 1); }; + inline FixInt &operator*=(FixInt x) { return *this = *this*x; }; + /* Division. */ + inline FixInt operator/(FixInt x) const { return FixInt( (SLONG) ( (__int64(slHolder)< &operator/=(FixInt x) { return *this = *this/x; }; + + /* Relational operators. */ + inline BOOL operator< (FixInt x) const { return slHolder< x.slHolder; }; + inline BOOL operator<=(FixInt x) const { return slHolder<=x.slHolder; }; + inline BOOL operator> (FixInt x) const { return slHolder> x.slHolder; }; + inline BOOL operator>=(FixInt x) const { return slHolder>=x.slHolder; }; + inline BOOL operator==(FixInt x) const { return slHolder==x.slHolder; }; + inline BOOL operator!=(FixInt x) const { return slHolder!=x.slHolder; }; + + /* Rounding and truncatenation functions. */ + friend inline SLONG Floor(FixInt x) { return (x.slHolder)>>iFrac; }; + friend inline SLONG Ceil(FixInt x) { return (x.slHolder+(0xFFFFFFFFL>>iInt))>>iFrac; }; + /* Truncatenate to fixed number of decimal bits. */ + friend inline FixInt Trunc(FixInt x, int iDecimalPart) { + return FixInt(x.slHolder& (0xFFFFFFFF*((1< + +/* Get current precision setting of FPU. */ +enum FPUPrecisionType GetFPUPrecision(void) +{ + // get control flags from FPU + ULONG fpcw = _control87( 0, 0); + + // extract the precision from the flags + switch(fpcw&_MCW_PC) { + case _PC_24: + return FPT_24BIT; + break; + case _PC_53: + return FPT_53BIT; + break; + case _PC_64: + return FPT_64BIT; + break; + default: + ASSERT(FALSE); + return FPT_24BIT; + }; +} + +/* Set current precision setting of FPU. */ +void SetFPUPrecision(enum FPUPrecisionType fptNew) +{ + ULONG fpcw; + // create FPU flags from the precision + switch(fptNew) { + case FPT_24BIT: + fpcw=_PC_24; + break; + case FPT_53BIT: + fpcw=_PC_53; + break; + case FPT_64BIT: + fpcw=_PC_64; + break; + default: + ASSERT(FALSE); + fpcw=_PC_24; + }; + // set the FPU precission + _control87( fpcw, MCW_PC); +} + +///////////////////////////////////////////////////////////////////// +// CSetFPUPrecision +/* + * Constructor with automatic setting of FPU precision. + */ +CSetFPUPrecision::CSetFPUPrecision(enum FPUPrecisionType fptNew) +{ + // remember old precision + sfp_fptOldPrecision = GetFPUPrecision(); + // set new precision if needed + sfp_fptNewPrecision = fptNew; + if (sfp_fptNewPrecision!=sfp_fptOldPrecision) { + SetFPUPrecision(fptNew); + } +} + +/* + * Destructor with automatic restoring of FPU precision. + */ +CSetFPUPrecision::~CSetFPUPrecision(void) +{ + // check consistency + ASSERT(GetFPUPrecision()==sfp_fptNewPrecision); + // restore old precision if needed + if (sfp_fptNewPrecision!=sfp_fptOldPrecision) { + SetFPUPrecision(sfp_fptOldPrecision); + } +} + +BOOL IsValidFloat(float f) +{ + return _finite(f) && (*(ULONG*)&f)!=0xcdcdcdcdUL; +/* int iClass = _fpclass(f); + return + iClass==_FPCLASS_NN || + iClass==_FPCLASS_ND || + iClass==_FPCLASS_NZ || + iClass==_FPCLASS_PZ || + iClass==_FPCLASS_PD || + iClass==_FPCLASS_PN; + */ +} + +BOOL IsValidDouble(double f) +{ + return _finite(f) && (*(unsigned __int64*)&f)!=0xcdcdcdcdcdcdcdcdI64; +/* int iClass = _fpclass(f); + return + iClass==_FPCLASS_NN || + iClass==_FPCLASS_ND || + iClass==_FPCLASS_NZ || + iClass==_FPCLASS_PZ || + iClass==_FPCLASS_PD || + iClass==_FPCLASS_PN; + */ +} + diff --git a/Sources/Engine/Math/Float.h b/Sources/Engine/Math/Float.h new file mode 100644 index 0000000..057a4c4 --- /dev/null +++ b/Sources/Engine/Math/Float.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_FLOAT_H +#define SE_INCL_FLOAT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + + +/* + * FPU control functions and classes. + */ + +// FPU precision setting values +enum FPUPrecisionType { + FPT_24BIT, + FPT_53BIT, + FPT_64BIT, +}; +/* Get current precision setting of FPU. */ +ENGINE_API enum FPUPrecisionType GetFPUPrecision(void); +/* Set current precision setting of FPU. */ +ENGINE_API void SetFPUPrecision(enum FPUPrecisionType fptNew); + +/* + * Class that provides automatic saving/setting/restoring of FPU precision setting. + */ +class ENGINE_API CSetFPUPrecision { +private: + enum FPUPrecisionType sfp_fptOldPrecision; + enum FPUPrecisionType sfp_fptNewPrecision; +public: + /* Constructor with automatic setting of FPU precision. */ + CSetFPUPrecision(enum FPUPrecisionType fptNew); + /* Destructor with automatic restoring of FPU precision. */ + ~CSetFPUPrecision(void); +}; + + +ENGINE_API BOOL IsValidFloat(float f); +ENGINE_API BOOL IsValidDouble(double f); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/Functions.cpp b/Sources/Engine/Math/Functions.cpp new file mode 100644 index 0000000..00848f4 --- /dev/null +++ b/Sources/Engine/Math/Functions.cpp @@ -0,0 +1,81 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +///////////////////////////////////////////////////////////////////// +// Snapping functions + +// does "snap to grid" for given coordinate +void Snap( FLOAT &fDest, FLOAT fStep) +{ + // this must use floor() to get proper snapping of negative values. + FLOAT fDiv = fDest/fStep; + FLOAT fRound = fDiv + 0.5f; + FLOAT fSnap = FLOAT(floor(fRound)); + FLOAT fRes = fSnap * fStep; + fDest = fRes; +} +// does "snap to grid" for given coordinate +void Snap( DOUBLE &fDest, DOUBLE fStep) +{ + // this must use floor() to get proper snapping of negative values. + DOUBLE fDiv = fDest/fStep; + DOUBLE fRound = fDiv + 0.5f; + DOUBLE fSnap = DOUBLE(floor(fRound)); + DOUBLE fRes = fSnap * fStep; + fDest = fRes; +} + +#if 0 +// does "snap to grid" for given angle +void Snap( ANGLE &angDest, ANGLE angStep) +{ + /* Watch out for unsigned-signed mixing! + All sub-expressions and arguments must be unsigned for this to work correctly! + Unfortunately, ANGLE is not an unsigned type by default, so we must cast it. + Also, angStep must be a divisor of ANGLE_180! + */ + ASSERT(ANGLE_180%angStep == 0); // don't test with ANGLE_360 ,since it is 0! + angDest = ANGLE( ((UWORD(angDest)+UWORD(angStep)/2U)/UWORD(angStep))*UWORD(angStep) ); +} +#endif + +double adSinQuadrants[4][2] = +{ + {1.0, 0.0}, + {-1.0, -90.0}, + {-1.0, 0.0}, + {1.0, -90.0}, +}; +double adCosQuadrants[4][2] = +{ + {-1.0, -90.0}, + {-1.0, 0.0}, + {1.0, -90.0}, + {1.0, 0.0}, +}; + +FLOAT Sin(ANGLE a) +{ + double aWrapped = WrapAngle(a); + double aIn90 = fmod(aWrapped, 90.0); + int iQuadrant = int(aWrapped/90.0); + double fSin = adSinQuadrants[iQuadrant][0]* + sin((aIn90+adSinQuadrants[iQuadrant][1])*PI/ANGLE_180); + return FLOAT (fSin); +} +FLOAT Cos(ANGLE a) +{ + double aWrapped = WrapAngle(a); + double aIn90 = fmod(aWrapped, 90.0); + int iQuadrant = int(aWrapped/90.0); + double fCos = adCosQuadrants[iQuadrant][0]* + sin((aIn90+adCosQuadrants[iQuadrant][1])*PI/ANGLE_180); + return FLOAT (fCos); +} +FLOAT Tan(ANGLE a) +{ + return Sin(a)/Cos(a); +} diff --git a/Sources/Engine/Math/Functions.h b/Sources/Engine/Math/Functions.h new file mode 100644 index 0000000..0919bd1 --- /dev/null +++ b/Sources/Engine/Math/Functions.h @@ -0,0 +1,566 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_FUNCTIONS_H +#define SE_INCL_FUNCTIONS_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + +/* + * template implementations + */ + +template +inline Type Abs( const Type x) +{ + return ( x>=Type(0) ? x : -x ); +} + +template +inline Type Max( const Type a, const Type b) +{ + return ( a +inline Type Min( const Type a, const Type b) +{ + return ( a>b ? b : a ); +} + +// linear interpolation +template +inline Type Lerp( const Type x0, const Type x1, const FLOAT fRatio) +{ + if( fRatio==0) return x0; + else if( fRatio==1) return x1; + else return x0+(x1-x0)*fRatio; +} + +template +inline Type Sgn( const Type x) +{ + return (x)>Type(0) ? Type(1):( x<0 ? Type(-1):Type(0) ); +} + +template +inline Type SgnNZ( const Type x) +{ + return (x)>=Type(0) ? Type(1):Type(-1); +} + +template +inline void Swap( Type &a, Type &b) +{ + Type t=a; a=b; b=t; +} + +template +inline Type ClampUp( const Type x, const Type uplimit) +{ + return ( x<=uplimit ? x : uplimit ); +} + +template +inline Type ClampDn( const Type x, const Type dnlimit) +{ + return ( x>=dnlimit ? x : dnlimit ); +} + +template +inline Type Clamp( const Type x, const Type dnlimit, const Type uplimit) +{ + return ( x>=dnlimit ? (x<=uplimit ? x : uplimit): dnlimit ); +} + +/* + * fast implementations + */ + + +inline DOUBLE Abs( const DOUBLE f) { return fabs(f); } +inline FLOAT Abs( const FLOAT f) { return (FLOAT)fabs(f); } +inline SLONG Abs( const SLONG sl) { return labs(sl); } + + +/* +inline FLOAT Min( const FLOAT fA, const FLOAT fB) +{ + FLOAT fRet; + __asm { + fld D [fA] + fld D [fB] + fucomi st(0),st(1) + fcmovnb st(0),st(1) + ffree st(1) + fstp D [fRet] + } + return fRet; +} + +inline FLOAT Max( const FLOAT fA, const FLOAT fB) +{ + FLOAT fRet; + __asm { + fld D [fA] + fld D [fB] + fucomi st(0),st(1) + fcmovb st(0),st(1) + ffree st(1) + fstp D [fRet] + } + return fRet; +} + + +inline SLONG Min( const SLONG slA, const SLONG slB) +{ + SLONG slRet; + __asm { + mov eax,D [slA] + cmp eax,D [slB] + cmovg eax,D [slB] + mov D [slRet],eax + } + return slRet; +} + +inline ULONG Min( const ULONG slA, const ULONG slB) +{ + ULONG ulRet; + __asm { + mov eax,D [slA] + cmp eax,D [slB] + cmova eax,D [slB] + mov D [ulRet],eax + } + return ulRet; +} + +inline SLONG Max( const SLONG slA, const SLONG slB) +{ + SLONG slRet; + __asm { + mov eax,D [slA] + cmp eax,D [slB] + cmovl eax,D [slB] + mov D [slRet],eax + } + return slRet; +} + +inline ULONG Max( const ULONG slA, const ULONG slB) +{ + ULONG ulRet; + __asm { + mov eax,D [slA] + cmp eax,D [slB] + cmovb eax,D [slB] + mov D [ulRet],eax + } + return ulRet; +} + + + +inline FLOAT ClampUp( const FLOAT f, const FLOAT fuplimit) +{ + FLOAT fRet; + __asm { + fld D [fuplimit] + fld D [f] + fucomi st(0),st(1) + fcmovnb st(0),st(1) + fstp D [fRet] + fstp st(0) + } + return fRet; +} + +inline FLOAT ClampDn( const FLOAT f, const FLOAT fdnlimit) +{ + FLOAT fRet; + __asm { + fld D [fdnlimit] + fld D [f] + fucomi st(0),st(1) + fcmovb st(0),st(1) + fstp D [fRet] + fstp st(0) + } + return fRet; +} + +inline FLOAT Clamp( const FLOAT f, const FLOAT fdnlimit, const FLOAT fuplimit) +{ + FLOAT fRet; + __asm { + fld D [fdnlimit] + fld D [fuplimit] + fld D [f] + fucomi st(0),st(2) + fcmovb st(0),st(2) + fucomi st(0),st(1) + fcmovnb st(0),st(1) + fstp D [fRet] + fcompp + } + return fRet; +} + + +inline SLONG ClampDn( const SLONG sl, const SLONG sldnlimit) +{ + SLONG slRet; + __asm { + mov eax,D [sl] + cmp eax,D [sldnlimit] + cmovl eax,D [sldnlimit] + mov D [slRet],eax + } + return slRet; +} + +inline SLONG ClampUp( const SLONG sl, const SLONG sluplimit) +{ + SLONG slRet; + __asm { + mov eax,D [sl] + cmp eax,D [sluplimit] + cmovg eax,D [sluplimit] + mov D [slRet],eax + } + return slRet; +} + +inline SLONG Clamp( const SLONG sl, const SLONG sldnlimit, const SLONG sluplimit) +{ + SLONG slRet; + __asm { + mov eax,D [sl] + cmp eax,D [sldnlimit] + cmovl eax,D [sldnlimit] + cmp eax,D [sluplimit] + cmovg eax,D [sluplimit] + mov D [slRet],eax + } + return slRet; +} + +*/ + +/* + * fast functions + */ + +#define FP_ONE_BITS 0x3F800000 + +// fast reciprocal value +inline FLOAT FastRcp( const FLOAT f) +{ + INDEX i = 2*FP_ONE_BITS - *(INDEX*)&(f); + FLOAT r = *(FLOAT*)&i; + return( r * (2.0f - f*r)); +} + +// convert float from 0.0f to 1.0f -> ulong form 0 to 255 +inline ULONG NormFloatToByte( const FLOAT f) +{ + /* rcg10042001 !!! FIXME: Move this elsewhere. */ +#ifdef _MSC_VER + const FLOAT f255 = 255.0f; + ULONG ulRet; + __asm { + fld D [f] + fmul D [f255] + fistp D [ulRet] + } + return ulRet; +#else + assert((f >= 0.0) && (f <= 1.0)); + return( (ULONG) (f * 255.0) ); +#endif +} + +// convert ulong from 0 to 255 -> float form 0.0f to 255.0f +inline FLOAT NormByteToFloat( const ULONG ul) +{ + return (FLOAT)ul * (1.0f/255.0f); +} + + +// fast float to int conversion +inline SLONG FloatToInt( FLOAT f) +{ +#if (defined USE_PORTABLE_C) + return((SLONG) f); /* best of luck to you. */ + +#elif (defined _MSC_VER) + SLONG slRet; + __asm { + fld D [f] + fistp D [slRet] + } + return slRet; + +#elif (defined __GNUC__) + SLONG slRet; + __asm__ __volatile__ ( + "flds (%%ebx) \n\t" + "fistpl (%%esi) \n\t" + : + : "b" (&f), "S" (&slRet) + : "memory" + ); + return(slRet); +#else + #error Fill this in for your platform. +#endif +} + +// log base 2 of any float numero +inline FLOAT Log2( FLOAT f) { +#if (defined USE_PORTABLE_C) + return (FLOAT)(log10(x)*3.321928094887); // log10(x)/log10(2) + +#elif (defined _MSC_VER) + FLOAT fRet; + _asm { + fld1 + fld D [f] + fyl2x + fstp D [fRet] + } + return fRet; + +#elif (defined __GNUC__) + FLOAT fRet; + __asm__ __volatile__ ( + "fld1 \n\t" + "flds (%%ebx) \n\t" + "fyl2x \n\t" + "fstps (%%esi) \n\t" + : + : "b" (&f), "S" (&fRet) + : "memory" + ); + return(fRet); +#else + #error Fill this in for your platform. +#endif +} + + +// returns accurate values only for integers that are power of 2 +inline SLONG FastLog2( SLONG x) +{ +#if (defined USE_PORTABLE_C) + #error write me. + +#elif (defined _MSC_VER) + SLONG slRet; + __asm { + bsr eax,D [x] + mov D [slRet],eax + } + return slRet; + +#elif (defined __GNUC__) + SLONG slRet; + __asm__ __volatile__ ( + "bsrl (%%ebx), %%eax \n\t" + "movl %%eax, (%%esi) \n\t" + : + : "b" (&x), "S" (&slRet) + : "memory" + ); + return(slRet); +#else + #error Fill this in for your platform. +#endif +} + +// returns log2 of first larger value that is a power of 2 +inline SLONG FastMaxLog2( SLONG x) +{ +#if (defined USE_PORTABLE_C) + #error write me. + +#elif (defined _MSC_VER) + SLONG slRet; + __asm { + bsr eax,D [x] + bsf edx,D [x] + cmp edx,eax + adc eax,0 + mov D [slRet],eax + } + return slRet; + +#elif (defined __GNUC__) + SLONG slRet; + __asm__ __volatile__ ( + "bsrl (%%ebx), %%eax \n\t" + "bsfl (%%ebx), %%edx \n\t" + "cmpl %%eax, %%edx \n\t" + "adcl $0, %%eax \n\t" + "movl %%eax, (%%esi) \n\t" + : + : "b" (&x), "S" (&slRet) + : "memory" + ); + return(slRet); +#else + #error Fill this in for your platform. +#endif +} + + + +// square root (works with negative numbers) +inline FLOAT Sqrt( FLOAT x) { return (FLOAT)sqrt( ClampDn( x, 0.0f)); } + + + +/* + * Trigonometrical functions + */ + +//#define ANGLE_MASK 0x3fff +#define ANGLE_SNAP (0.25f) //0x0010 +// Wrap angle to be between 0 and 360 degrees +inline ANGLE WrapAngle(ANGLE a) { + return (ANGLE) fmod( fmod(a,360.0f) + 360.0f, 360.0f); // 0..360 +} + +// Normalize angle to be between -180 and +180 degrees +inline ANGLE NormalizeAngle(ANGLE a) { + return WrapAngle(a+ANGLE_180)-ANGLE_180; +} + +// math constants +static const FLOAT PI = FLOAT(3.14159265359); + +// convert degrees into angle +inline ANGLE AngleDeg(FLOAT fDegrees) { + //return ANGLE (fDegrees*ANGLE_180/FLOAT(180.0)); + return fDegrees; +} +// convert radians into angle +inline ANGLE AngleRad(FLOAT fRadians) { + return ANGLE (fRadians*ANGLE_180/PI); +} +// convert radians into angle +inline ANGLE AngleRad(DOUBLE dRadians) { + return ANGLE (dRadians*ANGLE_180/PI); +} +// convert angle into degrees +inline FLOAT DegAngle(ANGLE aAngle) { + //return FLOAT (WrapAngle(aAngle)*FLOAT(180.0)/ANGLE_180); + return WrapAngle(aAngle); +} +// convert angle into radians +inline FLOAT RadAngle(ANGLE aAngle) { + return FLOAT (WrapAngle(aAngle)*PI/ANGLE_180); +} + +ENGINE_API FLOAT Sin(ANGLE a); +ENGINE_API FLOAT Cos(ANGLE a); +ENGINE_API FLOAT Tan(ANGLE a); + +inline ENGINE_API FLOAT SinFast(ANGLE a) { return (FLOAT)sin(a*(PI/ANGLE_180)); }; +inline ENGINE_API FLOAT CosFast(ANGLE a) { return (FLOAT)cos(a*(PI/ANGLE_180)); }; +inline ENGINE_API FLOAT TanFast(ANGLE a) { return (FLOAT)tan(a*(PI/ANGLE_180)); }; + +inline ANGLE ASin(FLOAT y) { + return AngleRad (asin(Clamp(y, -1.0f, 1.0f))); +} +inline ANGLE ASin(DOUBLE y) { + return AngleRad (asin(Clamp(y, -1.0, 1.0))); +} +inline ANGLE ACos(FLOAT x) { + return AngleRad (acos(Clamp(x, -1.0f, 1.0f))); +} +inline ANGLE ACos(DOUBLE x) { + return AngleRad (acos(Clamp(x, -1.0, 1.0))); +} +inline ANGLE ATan(FLOAT z) { + return AngleRad (atan(z)); +} +inline ANGLE ATan(DOUBLE z) { + return AngleRad (atan(z)); +} +inline ANGLE ATan2(FLOAT y, FLOAT x) { + return AngleRad (atan2(y, x)); +} +inline ANGLE ATan2(DOUBLE y, DOUBLE x) { + return AngleRad (atan2(y, x)); +} + +// does "snap to grid" for given coordinate +ENGINE_API void Snap( FLOAT &fDest, FLOAT fStep); +ENGINE_API void Snap( DOUBLE &fDest, DOUBLE fStep); +// does "snap to grid" for given angle +//ENGINE_API void Snap( ANGLE &angDest, ANGLE angStep); + + +/* + * linear interpolation, special functions for floats and angles + */ + +inline FLOAT LerpFLOAT(FLOAT f0, FLOAT f1, FLOAT fFactor) +{ + return f0+(f1-f0)*fFactor; +} + +inline ANGLE LerpANGLE(ANGLE a0, ANGLE a1, FLOAT fFactor) +{ + // calculate delta + ANGLE aDelta = WrapAngle(a1)-WrapAngle(a0); + // adjust delta not to wrap around 360 + if (aDelta>ANGLE_180) { + aDelta-=ANGLE(ANGLE_360); + } else if (aDelta<-ANGLE_180) { + aDelta+=ANGLE(ANGLE_360); + } + // interpolate the delta + return a0+ANGLE(fFactor*aDelta); +} + +// Calculates ratio function /~~\ where 0=fMax) + { + return 0.0f; + } + FLOAT fDelta = fMax-fMin; + FLOAT fRatio=(fCurr-fMin)/fDelta; + if(fRatio(1-fFadeOutRatio)) { + fRatio = Clamp( (1.0f-fRatio)/fFadeOutRatio, 0.0f, 1.0f); + } else { + fRatio = 1.0f; + } + return fRatio; +} + + +#undef O +#undef Q +#undef D +#undef W +#undef B + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/Geometry.cpp b/Sources/Engine/Math/Geometry.cpp new file mode 100644 index 0000000..c8ab137 --- /dev/null +++ b/Sources/Engine/Math/Geometry.cpp @@ -0,0 +1,305 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include + +///////////////////////////////////////////////////////////////////// +// +// General functions +// +///////////////////////////////////////////////////////////////////// + +/* + * Calculate rotation matrix from angles in 3D. + */ +/*void operator^=(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles) +{ + MakeRotationMatrix(t3dRotation, a3dAngles); +} +*/ + +void MakeRotationMatrix(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles) +{ + FLOAT fSinH = Sin(a3dAngles(1)); // heading + FLOAT fCosH = Cos(a3dAngles(1)); + FLOAT fSinP = Sin(a3dAngles(2)); // pitch + FLOAT fCosP = Cos(a3dAngles(2)); + FLOAT fSinB = Sin(a3dAngles(3)); // banking + FLOAT fCosB = Cos(a3dAngles(3)); + + t3dRotation(1,1) = fCosH*fCosB+fSinP*fSinH*fSinB; + t3dRotation(1,2) = fSinP*fSinH*fCosB-fCosH*fSinB; + t3dRotation(1,3) = fCosP*fSinH; + t3dRotation(2,1) = fCosP*fSinB; + t3dRotation(2,2) = fCosP*fCosB; + t3dRotation(2,3) = -fSinP; + t3dRotation(3,1) = fSinP*fCosH*fSinB-fSinH*fCosB; + t3dRotation(3,2) = fSinP*fCosH*fCosB+fSinH*fSinB; + t3dRotation(3,3) = fCosP*fCosH; +} +void MakeRotationMatrixFast(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles) +{ + FLOAT fSinH = SinFast(a3dAngles(1)); // heading + FLOAT fCosH = CosFast(a3dAngles(1)); + FLOAT fSinP = SinFast(a3dAngles(2)); // pitch + FLOAT fCosP = CosFast(a3dAngles(2)); + FLOAT fSinB = SinFast(a3dAngles(3)); // banking + FLOAT fCosB = CosFast(a3dAngles(3)); + + t3dRotation(1,1) = fCosH*fCosB+fSinP*fSinH*fSinB; + t3dRotation(1,2) = fSinP*fSinH*fCosB-fCosH*fSinB; + t3dRotation(1,3) = fCosP*fSinH; + t3dRotation(2,1) = fCosP*fSinB; + t3dRotation(2,2) = fCosP*fCosB; + t3dRotation(2,3) = -fSinP; + t3dRotation(3,1) = fSinP*fCosH*fSinB-fSinH*fCosB; + t3dRotation(3,2) = fSinP*fCosH*fCosB+fSinH*fSinB; + t3dRotation(3,3) = fCosP*fCosH; +} + +/* + * Calculate inverse rotation matrix from angles in 3D. + */ +/*void operator!=(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles) +{ + MakeInverseRotationMatrix(t3dRotation, a3dAngles); +} +*/ +void MakeInverseRotationMatrix(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles) +{ + FLOAT fSinH = Sin(a3dAngles(1)); // heading + FLOAT fCosH = Cos(a3dAngles(1)); + FLOAT fSinP = Sin(a3dAngles(2)); // pitch + FLOAT fCosP = Cos(a3dAngles(2)); + FLOAT fSinB = Sin(a3dAngles(3)); // banking + FLOAT fCosB = Cos(a3dAngles(3)); + + // to make inverse of rotation matrix, we only need to transpose it + t3dRotation(1,1) = fCosH*fCosB+fSinP*fSinH*fSinB; + t3dRotation(2,1) = fSinP*fSinH*fCosB-fCosH*fSinB; + t3dRotation(3,1) = fCosP*fSinH; + t3dRotation(1,2) = fCosP*fSinB; + t3dRotation(2,2) = fCosP*fCosB; + t3dRotation(3,2) = -fSinP; + t3dRotation(1,3) = fSinP*fCosH*fSinB-fSinH*fCosB; + t3dRotation(2,3) = fSinP*fCosH*fCosB+fSinH*fSinB; + t3dRotation(3,3) = fCosP*fCosH; +} +void MakeInverseRotationMatrixFast(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles) +{ + FLOAT fSinH = SinFast(a3dAngles(1)); // heading + FLOAT fCosH = CosFast(a3dAngles(1)); + FLOAT fSinP = SinFast(a3dAngles(2)); // pitch + FLOAT fCosP = CosFast(a3dAngles(2)); + FLOAT fSinB = SinFast(a3dAngles(3)); // banking + FLOAT fCosB = CosFast(a3dAngles(3)); + + // to make inverse of rotation matrix, we only need to transpose it + t3dRotation(1,1) = fCosH*fCosB+fSinP*fSinH*fSinB; + t3dRotation(2,1) = fSinP*fSinH*fCosB-fCosH*fSinB; + t3dRotation(3,1) = fCosP*fSinH; + t3dRotation(1,2) = fCosP*fSinB; + t3dRotation(2,2) = fCosP*fCosB; + t3dRotation(3,2) = -fSinP; + t3dRotation(1,3) = fSinP*fCosH*fSinB-fSinH*fCosB; + t3dRotation(2,3) = fSinP*fCosH*fCosB+fSinH*fSinB; + t3dRotation(3,3) = fCosP*fCosH; +} + +/* + * Decompose rotation matrix into angles in 3D. + */ +// NOTE: for derivation of the algorithm, see mathlib.doc +void DecomposeRotationMatrixNoSnap(ANGLE3D &a3dAngles, const FLOATmatrix3D &t3dRotation) +{ + ANGLE &h=a3dAngles(1); // heading + ANGLE &p=a3dAngles(2); // pitch + ANGLE &b=a3dAngles(3); // banking + FLOAT a; // temporary + + // calculate pitch + FLOAT f23 = t3dRotation(2,3); + p = ASin(-f23); + a = Sqrt(1.0f-f23*f23); + + // if pitch makes banking beeing the same as heading + if (a<0.001) { + // we choose to have banking of 0 + b = 0; + // and calculate heading for that + ASSERT(Abs(t3dRotation(2,3))>0.5); // must be around 1, what is far from 0 + h = ATan2(t3dRotation(1,2)/(-t3dRotation(2,3)), t3dRotation(1,1)); // no division by 0 + // otherwise + } else { + // calculate banking and heading normally + b = ATan2(t3dRotation(2,1), t3dRotation(2,2)); + h = ATan2(t3dRotation(1,3), t3dRotation(3,3)); + } +} + +void DecomposeRotationMatrix(ANGLE3D &a3dAngles, const FLOATmatrix3D &t3dRotation) +{ + // decompose the matrix without snapping + DecomposeRotationMatrixNoSnap(a3dAngles, t3dRotation); + // snap angles to compensate for errors when converting to and from matrix notation + Snap(a3dAngles(1), ANGLE_SNAP); + Snap(a3dAngles(2), ANGLE_SNAP); + Snap(a3dAngles(3), ANGLE_SNAP); +} + +/*void operator^=(ANGLE3D &a3dAngles, const FLOATmatrix3D &t3dRotation) { + DecomposeRotationMatrix(a3dAngles, t3dRotation); +} +*/ + +/* + * Create direction vector from angles in 3D (ignoring banking). + */ +void AnglesToDirectionVector(const ANGLE3D &a3dAngles, FLOAT3D &vDirection) +{ + // find the rotation matrix from the angles + FLOATmatrix3D mDirection; + MakeRotationMatrix(mDirection, a3dAngles); + // rotate a front oriented vector by the matrix + vDirection = FLOAT3D(0.0f, 0.0f, -1.0f)*mDirection; +} + +/* + * Create angles in 3D from direction vector(ignoring banking). + */ +void DirectionVectorToAnglesNoSnap(const FLOAT3D &vDirection, ANGLE3D &a3dAngles) +{ + // now calculate the angles + ANGLE &h = a3dAngles(1); + ANGLE &p = a3dAngles(2); + ANGLE &b = a3dAngles(3); + + const FLOAT &x = vDirection(1); + const FLOAT &y = vDirection(2); + const FLOAT &z = vDirection(3); + + // banking is always irrelevant + b = 0; + // calculate pitch + p = ASin(y); + + // if y is near +1 or -1 + if (y>0.99 || y<-0.99) { + // heading is irrelevant + h = 0; + // otherwise + } else { + // calculate heading + h = ATan2(-x, -z); + } +} +void DirectionVectorToAngles(const FLOAT3D &vDirection, ANGLE3D &a3dAngles) +{ + DirectionVectorToAnglesNoSnap(vDirection, a3dAngles); + + // snap angles to compensate for errors when converting to and from vector notation + Snap(a3dAngles(1), ANGLE_SNAP); + Snap(a3dAngles(2), ANGLE_SNAP); + Snap(a3dAngles(3), ANGLE_SNAP); +} + +/* Create angles in 3D from up vector (ignoring objects relative heading). + (up vector must be normalized!)*/ +void UpVectorToAngles(const FLOAT3D &vY, ANGLE3D &a3dAngles) +{ + // create any front vector + FLOAT3D vZ; + if (Abs(vY(2))>0.5f) { + vZ = FLOAT3D(1,0,0)*vY; + } else { + vZ = FLOAT3D(0,1,0)*vY; + } + vZ.Normalize(); + // side vector is cross product + FLOAT3D vX = vY*vZ; + vX.Normalize(); + // create the rotation matrix + FLOATmatrix3D m; + m(1,1) = vX(1); m(1,2) = vY(1); m(1,3) = vZ(1); + m(2,1) = vX(2); m(2,2) = vY(2); m(2,3) = vZ(2); + m(3,1) = vX(3); m(3,2) = vY(3); m(3,3) = vZ(3); + + // decompose the matrix without snapping + DecomposeRotationMatrixNoSnap(a3dAngles, m); +} + +/* + * Calculate rotation matrix from angles in 3D. + */ +void operator^=(DOUBLEmatrix3D &t3dRotation, const ANGLE3D &a3dAngles) { + const ANGLE &h=a3dAngles(1); // heading + const ANGLE &p=a3dAngles(2); // pitch + const ANGLE &b=a3dAngles(3); // banking + + t3dRotation(1,1) = Cos(h)*Cos(b)+Sin(p)*Sin(h)*Sin(b); + t3dRotation(1,2) = Sin(p)*Sin(h)*Cos(b)-Cos(h)*Sin(b); + t3dRotation(1,3) = Cos(p)*Sin(h); + t3dRotation(2,1) = Cos(p)*Sin(b); + t3dRotation(2,2) = Cos(p)*Cos(b); + t3dRotation(2,3) = -Sin(p); + t3dRotation(3,1) = Sin(p)*Cos(h)*Sin(b)-Sin(h)*Cos(b); + t3dRotation(3,2) = Sin(p)*Cos(h)*Cos(b)+Sin(h)*Sin(b); + t3dRotation(3,3) = Cos(p)*Cos(h); +} + +/* + * Calculate inverse rotation matrix from angles in 3D. + */ +void operator!=(DOUBLEmatrix3D &t3dRotation, const ANGLE3D &a3dAngles) { + const ANGLE &h=a3dAngles(1); // heading + const ANGLE &p=a3dAngles(2); // pitch + const ANGLE &b=a3dAngles(3); // banking + + // to make inverse of rotation matrix, we only need to transpose it + t3dRotation(1,1) = Cos(h)*Cos(b)+Sin(p)*Sin(h)*Sin(b); + t3dRotation(2,1) = Sin(p)*Sin(h)*Cos(b)-Cos(h)*Sin(b); + t3dRotation(3,1) = Cos(p)*Sin(h); + t3dRotation(1,2) = Cos(p)*Sin(b); + t3dRotation(2,2) = Cos(p)*Cos(b); + t3dRotation(3,2) = -Sin(p); + t3dRotation(1,3) = Sin(p)*Cos(h)*Sin(b)-Sin(h)*Cos(b); + t3dRotation(2,3) = Sin(p)*Cos(h)*Cos(b)+Sin(h)*Sin(b); + t3dRotation(3,3) = Cos(p)*Cos(h); +} + +/* + * Decompose rotation matrix into angles in 3D. + */ +// NOTE: for derivation of the algorithm, see mathlib.doc +void operator^=(ANGLE3D &a3dAngles, const DOUBLEmatrix3D &t3dRotation) { + ANGLE &h=a3dAngles(1); // heading + ANGLE &p=a3dAngles(2); // pitch + ANGLE &b=a3dAngles(3); // banking + DOUBLE a; // temporary + + // calculate pitch + p = ASin(-t3dRotation(2,3)); + a = sqrt(1-t3dRotation(2,3)*t3dRotation(2,3)); + + // if pitch makes banking beeing the same as heading + if (a<0.0001) { + // we choose to have banking of 0 + b = 0; + // and calculate heading for that + ASSERT(Abs(t3dRotation(2,3))>0.5); // must be around 1, what is far from 0 + h = ATan2(t3dRotation(1,2)/(-t3dRotation(2,3)), t3dRotation(1,1)); // no division by 0 + // otherwise + } else { + // calculate banking and heading normally + b = ATan2(t3dRotation(2,1)/a, t3dRotation(2,2)/a); + h = ATan2(t3dRotation(1,3)/a, t3dRotation(3,3)/a); + } + // snap angles to compensate for errors when converting to and from matrix notation + Snap(h, ANGLE_SNAP); + Snap(p, ANGLE_SNAP); + Snap(b, ANGLE_SNAP); +} + diff --git a/Sources/Engine/Math/Geometry.h b/Sources/Engine/Math/Geometry.h new file mode 100644 index 0000000..bf6788c --- /dev/null +++ b/Sources/Engine/Math/Geometry.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_GEOMETRY_H +#define SE_INCL_GEOMETRY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include + +/* + * General geometry functions + */ + +/* Calculate rotation matrix from angles in 3D. */ +//ENGINE_API extern void operator^=(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles); +ENGINE_API extern void MakeRotationMatrix(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles); +ENGINE_API extern void MakeRotationMatrixFast(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles); +/* Calculate inverse rotation matrix from angles in 3D. */ +//ENGINE_API extern void operator!=(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles); +ENGINE_API extern void MakeInverseRotationMatrix(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles); +ENGINE_API extern void MakeInverseRotationMatrixFast(FLOATmatrix3D &t3dRotation, const ANGLE3D &a3dAngles); +/* Decompose rotation matrix into angles in 3D. */ +//ENGINE_API extern void operator^=(ANGLE3D &a3dAngles, const FLOATmatrix3D &t3dRotation); +ENGINE_API extern void DecomposeRotationMatrix(ANGLE3D &a3dAngles, const FLOATmatrix3D &t3dRotation); +ENGINE_API extern void DecomposeRotationMatrixNoSnap(ANGLE3D &a3dAngles, const FLOATmatrix3D &t3dRotation); + +/* Create direction vector from angles in 3D (ignoring banking). */ +ENGINE_API extern void AnglesToDirectionVector(const ANGLE3D &a3dAngles, + FLOAT3D &vDirection); +/* Create angles in 3D from direction vector(ignoring banking). + (direction must be normalized!)*/ +ENGINE_API extern void DirectionVectorToAngles(const FLOAT3D &vDirection, + ANGLE3D &a3dAngles); +ENGINE_API extern void DirectionVectorToAnglesNoSnap(const FLOAT3D &vDirection, + ANGLE3D &a3dAngles); +/* Create angles in 3D from up vector (ignoring objects relative heading). + (up vector must be normalized!)*/ +ENGINE_API extern void UpVectorToAngles(const FLOAT3D &vUp, + ANGLE3D &a3dAngles); + + +/* Calculate rotation matrix from angles in 3D. */ +ENGINE_API extern void operator^=(DOUBLEmatrix3D &t3dRotation, const ANGLE3D &a3dAngles); +/* Calculate inverse rotation matrix from angles in 3D. */ +ENGINE_API extern void operator!=(DOUBLEmatrix3D &t3dRotation, const ANGLE3D &a3dAngles); +/* Decompose rotation matrix into angles in 3D. */ +ENGINE_API extern void operator^=(ANGLE3D &a3dAngles, const DOUBLEmatrix3D &t3dRotation); + + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/Geometry.inl b/Sources/Engine/Math/Geometry.inl new file mode 100644 index 0000000..a9b2ee2 --- /dev/null +++ b/Sources/Engine/Math/Geometry.inl @@ -0,0 +1,130 @@ + +// mirror a position vector by a given plane +inline void ReflectPositionVectorByPlane(const FLOATplane3D &plPlane, FLOAT3D &vPoint) +{ + vPoint-=((FLOAT3D &)plPlane)*(2*plPlane.PointDistance(vPoint)); +} +// mirror a direction vector by a given plane +inline void ReflectDirectionVectorByPlane(const FLOATplane3D &plPlane, FLOAT3D &vDirection) +{ + vDirection-=((FLOAT3D &)plPlane)*(2*(((FLOAT3D &)plPlane)%vDirection)); +} +// mirror a rotation matrix by a given plane +inline void ReflectRotationMatrixByPlane_cols(const FLOATplane3D &plPlane, FLOATmatrix3D &m) +{ // reflect columns vectors + FLOAT3D vX(m(1,1),m(2,1),m(3,1)); + FLOAT3D vY(m(1,2),m(2,2),m(3,2)); + FLOAT3D vZ(m(1,3),m(2,3),m(3,3)); + + ReflectDirectionVectorByPlane(plPlane, vX); + ReflectDirectionVectorByPlane(plPlane, vY); + ReflectDirectionVectorByPlane(plPlane, vZ); + + m(1,1) = vX(1); m(1,2) = vY(1); m(1,3) = vZ(1); + m(2,1) = vX(2); m(2,2) = vY(2); m(2,3) = vZ(2); + m(3,1) = vX(3); m(3,2) = vY(3); m(3,3) = vZ(3); +} +inline void ReflectRotationMatrixByPlane_rows(const FLOATplane3D &plPlane, FLOATmatrix3D &m) +{ // reflect row vectors + FLOAT3D vX(m(1,1),m(1,2),m(1,3)); + FLOAT3D vY(m(2,1),m(2,2),m(2,3)); + FLOAT3D vZ(m(3,1),m(3,2),m(3,3)); + + ReflectDirectionVectorByPlane(plPlane, vX); + ReflectDirectionVectorByPlane(plPlane, vY); + ReflectDirectionVectorByPlane(plPlane, vZ); + + m(1,1) = vX(1); m(2,1) = vY(1); m(3,1) = vZ(1); + m(1,2) = vX(2); m(2,2) = vY(2); m(3,2) = vZ(2); + m(1,3) = vX(3); m(2,3) = vY(3); m(3,3) = vZ(3); +} + +// get component of a vector parallel to given reference vector +static inline void GetParallelComponent( + const FLOAT3D &vFull, const FLOAT3D &vReference, FLOAT3D &vParallel) +{ + vParallel = vReference*(vFull%vReference); +} + +// get component of a vector normal to given reference vector +static inline void GetNormalComponent( + const FLOAT3D &vFull, const FLOAT3D &vReference, FLOAT3D &vNormal) +{ + vNormal = vFull-vReference*(vFull%vReference); +} + +// get components of a vector parallel and normal to given reference vector +static inline void GetParallelAndNormalComponents( + const FLOAT3D &vFull, const FLOAT3D &vReference, FLOAT3D &vParallel, FLOAT3D &vNormal) +{ + vParallel = vReference*(vFull%vReference); + vNormal = vFull-vParallel; +} + +// get measure of validity of a rotation matrix (should be around zero) +static inline FLOAT RotationMatrixValidity(const FLOATmatrix3D &m) +{ + FLOATmatrix3D mSqr; + mSqr(1,1) = m(1,1)*m(1,1); + mSqr(1,2) = m(1,2)*m(1,2); + mSqr(1,3) = m(1,3)*m(1,3); + mSqr(2,1) = m(2,1)*m(2,1); + mSqr(2,2) = m(2,2)*m(2,2); + mSqr(2,3) = m(2,3)*m(2,3); + mSqr(3,1) = m(3,1)*m(3,1); + mSqr(3,2) = m(3,2)*m(3,2); + mSqr(3,3) = m(3,3)*m(3,3); + + FLOAT3D vH; + vH(1) = Sqrt(mSqr(1,1)+mSqr(1,2)+mSqr(1,3))-1; + vH(2) = Sqrt(mSqr(2,1)+mSqr(2,2)+mSqr(2,3))-1; + vH(3) = Sqrt(mSqr(3,1)+mSqr(3,2)+mSqr(3,3))-1; + FLOAT3D vV; + vV(1) = Sqrt(mSqr(1,1)+mSqr(2,1)+mSqr(3,1))-1; + vV(2) = Sqrt(mSqr(1,2)+mSqr(2,2)+mSqr(3,2))-1; + vV(3) = Sqrt(mSqr(1,3)+mSqr(2,3)+mSqr(3,3))-1; + + return Sqrt( + vH(1)*vH(1)+vH(2)*vH(2)+vH(3)*vH(3)+ + vV(1)*vV(1)+vV(2)*vV(2)+vV(3)*vV(3)); +} + +// normalize rotation matrix to be special orthogonal +static inline void OrthonormalizeRotationMatrix( FLOATmatrix3D &m) +{ + FLOAT3D vX(m(1,1),m(2,1),m(3,1)); + FLOAT3D vY(m(1,2),m(2,2),m(3,2)); + FLOAT3D vZ; + + vX.Normalize(); + vZ = vX*vY; + vZ.Normalize(); + vY = vZ*vX; + vY.Normalize(); + + m(1,1) = vX(1); m(1,2) = vY(1); m(1,3) = vZ(1); + m(2,1) = vX(2); m(2,2) = vY(2); m(2,3) = vZ(2); + m(3,1) = vX(3); m(3,2) = vY(3); m(3,3) = vZ(3); +} + +inline void GetMajorAxesForPlane( + const FLOATplane3D &plPlane, INDEX &iMajorAxis1, INDEX &iMajorAxis2) +{ + // get maximum normal axis + INDEX iMaxNormalAxis = plPlane.GetMaxNormal(); + // the major axes are the other two axes + switch (iMaxNormalAxis) { + case 1: iMajorAxis1 = 2; iMajorAxis2 = 3; + break; + case 2: iMajorAxis1 = 3; iMajorAxis2 = 1; + break; + case 3: iMajorAxis1 = 1; iMajorAxis2 = 2; + break; + default: + ASSERT(FALSE); + iMajorAxis1 = 2; + iMajorAxis2 = 3; + } + ASSERT(Abs(plPlane(iMaxNormalAxis))>=Abs(plPlane(iMajorAxis1)) + &&Abs(plPlane(iMaxNormalAxis))>=Abs(plPlane(iMajorAxis2))); +} diff --git a/Sources/Engine/Math/Geometry_DOUBLE.cpp b/Sources/Engine/Math/Geometry_DOUBLE.cpp new file mode 100644 index 0000000..bd6f011 --- /dev/null +++ b/Sources/Engine/Math/Geometry_DOUBLE.cpp @@ -0,0 +1,15 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include + + +///////////////////////////////////////////////////////////////////// +// CSimpleProjection3D_DOUBLE + diff --git a/Sources/Engine/Math/Matrix.h b/Sources/Engine/Math/Matrix.h new file mode 100644 index 0000000..9d5626b --- /dev/null +++ b/Sources/Engine/Math/Matrix.h @@ -0,0 +1,476 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_MATRIX_H +#define SE_INCL_MATRIX_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* + * Template class for matrix of arbitrary dimensions and arbitrary type of members + */ +template +class Matrix { +public: + Type matrix[iRows][iColumns]; // array that holds the members +public: + /* Default constructor. */ + __forceinline Matrix(void); + /* Constructor that sets the whole matrix to same number. */ + __forceinline Matrix(const Type x); + + /* Reference matrix member by it's row and column indices (1-based indices!). */ + __forceinline Type &operator()(int iRow, int iColumn); + __forceinline const Type &operator()(int iRow, int iColumn) const; + + /* Make a transposed matrix. */ + __forceinline Matrix operator!(void) const; + __forceinline Matrix &operator!=(const Matrix &matrix2); + + /* Mathematical operators. */ + // between matrices + __forceinline Matrix operator+(const Matrix &matrix2) const; + __forceinline Matrix &operator+=(const Matrix &matrix2); + __forceinline Matrix operator-(const Matrix &matrix2) const; + __forceinline Matrix &operator-=(const Matrix &matrix2); + __forceinline Matrix operator*(const Matrix &matrix2) const; + __forceinline Matrix &operator*=(const Matrix &matrix2); + // matrices and scalars + __forceinline Matrix operator*(const Type tMul) const; + __forceinline Matrix &operator*=(const Type tMul); + __forceinline Matrix operator/(const Type tMul) const; + __forceinline Matrix &operator/=(const Type tMul); + + /* Set matrix main diagonal. */ + void Diagonal(Type x); + void Diagonal(const Vector &v); + + // get main vectors of matrix + Vector GetRow(Type iRow) const; + Vector GetColumn(Type iColumn) const; + + /* Stream operations */ + friend __forceinline CTStream &operator>>(CTStream &strm, Matrix &matrix) + { + strm.Read_t(&matrix, sizeof(matrix)); + return strm; + } + friend __forceinline CTStream &operator<<(CTStream &strm, Matrix &matrix) + { + strm.Write_t(&matrix, sizeof(matrix)); + return strm; + } +}; + + +// inline functions implementation + +/* + * Default constructor. + */ +template +__forceinline Matrix::Matrix(void) +{ +#ifndef NDEBUG + // set whole matrix to trash + ULONG ulTrash = 0xCDCDCDCDul; + for(int iRow=1; iRow<=iRows; iRow++) { + for(int iColumn=1; iColumn<=iColumns; iColumn++) { + (*this)(iRow, iColumn) = *reinterpret_cast(&ulTrash); + } + } +#endif +} + + +/* + * Constructor that sets the whole matrix to same number. + */ + +// set FLOAT 3x3 +Matrix::Matrix(const FLOAT x /*= Type(0)*/) +{ + // set whole matrix to constant + (*this)(1,1)=x; (*this)(1,2)=x; (*this)(1,3)=x; + (*this)(2,1)=x; (*this)(2,2)=x; (*this)(2,3)=x; + (*this)(3,1)=x; (*this)(3,2)=x; (*this)(3,3)=x; +} + +// set DOUBLE 3x3 +Matrix::Matrix(const DOUBLE x /*= Type(0)*/) +{ + // set whole matrix to constant + (*this)(1,1)=x; (*this)(1,2)=x; (*this)(1,3)=x; + (*this)(2,1)=x; (*this)(2,2)=x; (*this)(2,3)=x; + (*this)(3,1)=x; (*this)(3,2)=x; (*this)(3,3)=x; +} + +template +Matrix::Matrix(const Type x /*= Type(0)*/) +{ + ASSERT( iRows!=3 && iColumns!=3); // 3 is optimized special case + // set whole matrix to constant + for(int iRow=1; iRow<=iRows; iRow++) { + for(int iColumn=1; iColumn<=iColumns; iColumn++) { + (*this)(iRow, iColumn) = x; + } + } +} + + +/* + * Reference matrix member by it's row and column indices. + */ +template +__forceinline Type &Matrix::operator()(int iRow, int iColumn) +{ + // check boundaries (indices start at 1, not at 0) + ASSERT(iRow>=1 && iRow<=iRows && iColumn>=1 && iColumn<=iColumns); + // return member reference + return matrix[iRow-1][iColumn-1]; +} + +template +__forceinline const Type &Matrix::operator()(int iRow, int iColumn) const +{ + // check boundaries (indices start at 1, not at 0) + ASSERT(iRow>=1 && iRow<=iRows && iColumn>=1 && iColumn<=iColumns); + // return member reference + return matrix[iRow-1][iColumn-1]; +} + + +/* Mathematical operators. */ + + +// transposed FLOAT 3x3 +__forceinline Matrix &Matrix::operator!=(const Matrix &matrix2) +{ + (*this)(1,1)=matrix2(1,1); (*this)(1,2)=matrix2(2,1); (*this)(1,3)=matrix2(3,1); + (*this)(2,1)=matrix2(1,2); (*this)(2,2)=matrix2(2,2); (*this)(2,3)=matrix2(3,2); + (*this)(3,1)=matrix2(1,3); (*this)(3,2)=matrix2(2,3); (*this)(3,3)=matrix2(3,3); + return *this; +} + +// transposed DOUBLE 3x3 +__forceinline Matrix &Matrix::operator!=(const Matrix &matrix2) +{ + (*this)(1,1)=matrix2(1,1); (*this)(1,2)=matrix2(2,1); (*this)(1,3)=matrix2(3,1); + (*this)(2,1)=matrix2(1,2); (*this)(2,2)=matrix2(2,2); (*this)(2,3)=matrix2(3,2); + (*this)(3,1)=matrix2(1,3); (*this)(3,2)=matrix2(2,3); (*this)(3,3)=matrix2(3,3); + return *this; +} + + +// transposed matrix +template +__forceinline Matrix Matrix::operator!(void) const +{ + return Matrix() != *this; +} + +template +__forceinline Matrix &Matrix::operator!=(const Matrix &matrix2) +{ + // transpose member by member + ASSERT( iRows!=3 && iColumns!=3); // 3 is optimized special case + for(int iRow=1; iRow<=iRows; iRow++) { + for(int iColumn=1; iColumn<=iColumns; iColumn++) { + (*this)(iColumn, iRow) = matrix2(iRow, iColumn); + } + } + return *this; +} + + +// sum of two FLOATs 3x3 +__forceinline Matrix &Matrix::operator+=(const Matrix &matrix2) +{ + (*this)(1,1)+=matrix2(1,1); (*this)(1,2)+=matrix2(1,2); (*this)(1,3)+=matrix2(1,3); + (*this)(2,1)+=matrix2(2,1); (*this)(2,2)+=matrix2(2,2); (*this)(2,3)+=matrix2(2,3); + (*this)(3,1)+=matrix2(3,1); (*this)(3,2)+=matrix2(3,2); (*this)(3,3)+=matrix2(3,3); + return *this; +} + +// sum of two DOUBLEs 3x3 +__forceinline Matrix &Matrix::operator+=(const Matrix &matrix2) +{ + (*this)(1,1)+=matrix2(1,1); (*this)(1,2)+=matrix2(1,2); (*this)(1,3)+=matrix2(1,3); + (*this)(2,1)+=matrix2(2,1); (*this)(2,2)+=matrix2(2,2); (*this)(2,3)+=matrix2(2,3); + (*this)(3,1)+=matrix2(3,1); (*this)(3,2)+=matrix2(3,2); (*this)(3,3)+=matrix2(3,3); + return *this; +} + +// sum of two matrices +template +__forceinline Matrix &Matrix::operator+=(const Matrix &matrix2) +{ + // add member by member + ASSERT( iRows!=3 && iColumns!=3); // 3 is optimized special case + for(int iRow=1; iRow<=iRows; iRow++) { + for(int iColumn=1; iColumn<=iColumns; iColumn++) { + (*this)(iRow, iColumn) += matrix2(iRow, iColumn); + } + } + return *this; +} + +template +__forceinline Matrix Matrix::operator+(const Matrix &matrix2) const +{ + return Matrix(*this)+=matrix2; +} + + +// difference of two FLOATs 3x3 +__forceinline Matrix &Matrix::operator-=(const Matrix &matrix2) +{ + (*this)(1,1)-=matrix2(1,1); (*this)(1,2)-=matrix2(1,2); (*this)(1,3)-=matrix2(1,3); + (*this)(2,1)-=matrix2(2,1); (*this)(2,2)-=matrix2(2,2); (*this)(2,3)-=matrix2(2,3); + (*this)(3,1)-=matrix2(3,1); (*this)(3,2)-=matrix2(3,2); (*this)(3,3)-=matrix2(3,3); + return *this; +} + +// difference of two DOUBLEs 3x3 +__forceinline Matrix &Matrix::operator-=(const Matrix &matrix2) +{ + (*this)(1,1)-=matrix2(1,1); (*this)(1,2)-=matrix2(1,2); (*this)(1,3)-=matrix2(1,3); + (*this)(2,1)-=matrix2(2,1); (*this)(2,2)-=matrix2(2,2); (*this)(2,3)-=matrix2(2,3); + (*this)(3,1)-=matrix2(3,1); (*this)(3,2)-=matrix2(3,2); (*this)(3,3)-=matrix2(3,3); + return *this; +} + +// difference of two matrices +template +__forceinline Matrix &Matrix::operator-=(const Matrix &matrix2) +{ + // sub member by member + ASSERT( iRows!=3 && iColumns!=3); // 3 is optimized special case + for(int iRow=1; iRow<=iRows; iRow++) { + for(int iColumn=1; iColumn<=iColumns; iColumn++) { + (*this)(iRow, iColumn) -= matrix2(iRow, iColumn); + } + } + return *this; +} + +template +__forceinline Matrix Matrix::operator-(const Matrix &matrix2) const +{ + return Matrix(*this)-=matrix2; +} + + +// multiplication of two square matrices of same dimensions +/* + * Dimensions: A(n,k), B(k,p), C(n,p) + * + * Formula: C=AxB --> Cij=Sum(s=1..k)(Ais*Bsj) + */ + + + +// FLOAT 3x3 +__forceinline Matrix Matrix::operator*(const Matrix &matrix2) const +{ + Matrix result; + result(1,1) = (*this)(1,1) * matrix2(1,1) + (*this)(1,2) * matrix2(2,1) + (*this)(1,3) * matrix2(3,1); + result(1,2) = (*this)(1,1) * matrix2(1,2) + (*this)(1,2) * matrix2(2,2) + (*this)(1,3) * matrix2(3,2); + result(1,3) = (*this)(1,1) * matrix2(1,3) + (*this)(1,2) * matrix2(2,3) + (*this)(1,3) * matrix2(3,3); + result(2,1) = (*this)(2,1) * matrix2(1,1) + (*this)(2,2) * matrix2(2,1) + (*this)(2,3) * matrix2(3,1); + result(2,2) = (*this)(2,1) * matrix2(1,2) + (*this)(2,2) * matrix2(2,2) + (*this)(2,3) * matrix2(3,2); + result(2,3) = (*this)(2,1) * matrix2(1,3) + (*this)(2,2) * matrix2(2,3) + (*this)(2,3) * matrix2(3,3); + result(3,1) = (*this)(3,1) * matrix2(1,1) + (*this)(3,2) * matrix2(2,1) + (*this)(3,3) * matrix2(3,1); + result(3,2) = (*this)(3,1) * matrix2(1,2) + (*this)(3,2) * matrix2(2,2) + (*this)(3,3) * matrix2(3,2); + result(3,3) = (*this)(3,1) * matrix2(1,3) + (*this)(3,2) * matrix2(2,3) + (*this)(3,3) * matrix2(3,3); + return result; +} + +// DOUBLE 3x3 +__forceinline Matrix Matrix::operator*(const Matrix &matrix2) const +{ + Matrix result; + result(1,1) = (*this)(1,1) * matrix2(1,1) + (*this)(1,2) * matrix2(2,1) + (*this)(1,3) * matrix2(3,1); + result(1,2) = (*this)(1,1) * matrix2(1,2) + (*this)(1,2) * matrix2(2,2) + (*this)(1,3) * matrix2(3,2); + result(1,3) = (*this)(1,1) * matrix2(1,3) + (*this)(1,2) * matrix2(2,3) + (*this)(1,3) * matrix2(3,3); + result(2,1) = (*this)(2,1) * matrix2(1,1) + (*this)(2,2) * matrix2(2,1) + (*this)(2,3) * matrix2(3,1); + result(2,2) = (*this)(2,1) * matrix2(1,2) + (*this)(2,2) * matrix2(2,2) + (*this)(2,3) * matrix2(3,2); + result(2,3) = (*this)(2,1) * matrix2(1,3) + (*this)(2,2) * matrix2(2,3) + (*this)(2,3) * matrix2(3,3); + result(3,1) = (*this)(3,1) * matrix2(1,1) + (*this)(3,2) * matrix2(2,1) + (*this)(3,3) * matrix2(3,1); + result(3,2) = (*this)(3,1) * matrix2(1,2) + (*this)(3,2) * matrix2(2,2) + (*this)(3,3) * matrix2(3,2); + result(3,3) = (*this)(3,1) * matrix2(1,3) + (*this)(3,2) * matrix2(2,3) + (*this)(3,3) * matrix2(3,3); + return result; +} + +// general +template +__forceinline Matrix Matrix::operator*(const Matrix &matrix2) const +{ + Matrix result; + // check that the matrices have square dimensions + ASSERT(iRows==iColumns); + ASSERT( iRows!=3 && iColumns!=3); // 3 is optimized special case + // multiply + for(int iRow=1; iRow<=iRows; iRow++) { + for(int iColumn=1; iColumn<=iColumns; iColumn++) { + result(iRow, iColumn) = (Type)0; + for(int s=1; s<=iRows; s++) { + result(iRow, iColumn) += (*this)(iRow, s) * matrix2(s, iColumn); + } + } + } + return result; +} + +// general +template +__forceinline Matrix &Matrix::operator*=(const Matrix &matrix2) +{ + *this = *this * matrix2; + return *this; +} + + + +// multiply FLOAT 3x3 with scalar +__forceinline Matrix &Matrix::operator*=(const FLOAT tMul) +{ + (*this)(1,1)*=tMul; (*this)(1,2)*=tMul; (*this)(1,3)*=tMul; + (*this)(2,1)*=tMul; (*this)(2,2)*=tMul; (*this)(2,3)*=tMul; + (*this)(3,1)*=tMul; (*this)(3,2)*=tMul; (*this)(3,3)*=tMul; + return *this; +} + +// multiply DOUBLE 3x3 with scalar +__forceinline Matrix &Matrix::operator*=(const DOUBLE tMul) +{ + (*this)(1,1)*=tMul; (*this)(1,2)*=tMul; (*this)(1,3)*=tMul; + (*this)(2,1)*=tMul; (*this)(2,2)*=tMul; (*this)(2,3)*=tMul; + (*this)(3,1)*=tMul; (*this)(3,2)*=tMul; (*this)(3,3)*=tMul; + return *this; +} + + +// multiply matrix with scalar +template +__forceinline Matrix &Matrix::operator*=(const Type tMul) +{ + // multiply member by member + ASSERT( iRows!=3 && iColumns!=3); // 3 is optimized special case + for(int iRow=1; iRow<=iRows; iRow++) { + for(int iColumn=1; iColumn<=iColumns; iColumn++) { + (*this)(iRow, iColumn) *= tMul; + } + } + return *this; +} + +// multiply matrix with scalar +template +__forceinline Matrix Matrix::operator*(const Type tMul) const +{ + return Matrix(*this)*=tMul; +} + + +// divide matrix with scalar +template +__forceinline Matrix &Matrix::operator/=(const Type tDiv) +{ + // multiply with reciprocal + (*this)*=(1/tDiv); + return *this; +} + +// divide matrix with scalar +template +__forceinline Matrix Matrix::operator/(const Type tDiv) const +{ + // multiply with reciprocal + return Matrix(*this)*=(1/tDiv); +} + + + +/* + * Set matrix main diagonal. + */ +template +void Matrix::Diagonal(Type x) +{ + // check that the matrix is symetric + ASSERT(iRows==iColumns); + + // clear whole matrix to zeroes + for(int iRow=1; iRow<=iRows; iRow++) { + for(int iColumn=1; iColumn<=iColumns; iColumn++) { + (*this)(iRow, iColumn) = Type(0); + } + } + // set the main diagonal + {for(int iRow=0; iRow +void Matrix::Diagonal(const Vector &v) +{ + // check that the matrix is symetric + ASSERT(iRows==iColumns); + + // clear whole matrix to zeroes + for(int iRow=1; iRow<=iRows; iRow++) { + for(int iColumn=1; iColumn<=iColumns; iColumn++) { + (*this)(iRow, iColumn) = Type(0); + } + } + // set the main diagonal + {for(int iRow=1; iRow<=iRows; iRow++) { + operator()(iRow, iRow) = v(iRow); + }} +} + + +// get main vectors of matrix +template +Vector Matrix::GetRow(Type iRow) const +{ + Vector v; + for(int iColumn=1; iColumn<=iColumns; iColumn++) { + v(iColumn) = (*this)(iRow, iColumn); + } + return v; +} + +template +Vector Matrix::GetColumn(Type iColumn) const +{ + Vector v; + for(int iRow=1; iRow<=iRows; iRow++) { + v(iRow) = (*this)(iRow, iColumn); + } + return v; +} + + +// helper functions for converting between FLOAT and DOUBLE matrices +__forceinline DOUBLEmatrix3D FLOATtoDOUBLE(const FLOATmatrix3D &mf) +{ + DOUBLEmatrix3D m; + m(1,1) = FLOATtoDOUBLE(mf(1,1)); m(1,2) = FLOATtoDOUBLE(mf(1,2)); m(1,3) = FLOATtoDOUBLE(mf(1,3)); + m(2,1) = FLOATtoDOUBLE(mf(2,1)); m(2,2) = FLOATtoDOUBLE(mf(2,2)); m(2,3) = FLOATtoDOUBLE(mf(2,3)); + m(3,1) = FLOATtoDOUBLE(mf(3,1)); m(3,2) = FLOATtoDOUBLE(mf(3,2)); m(3,3) = FLOATtoDOUBLE(mf(3,3)); + return m; +} +__forceinline FLOATmatrix3D DOUBLEtoFLOAT(const DOUBLEmatrix3D &md) { + FLOATmatrix3D m; + m(1,1) = DOUBLEtoFLOAT(md(1,1)); m(1,2) = DOUBLEtoFLOAT(md(1,2)); m(1,3) = DOUBLEtoFLOAT(md(1,3)); + m(2,1) = DOUBLEtoFLOAT(md(2,1)); m(2,2) = DOUBLEtoFLOAT(md(2,2)); m(2,3) = DOUBLEtoFLOAT(md(2,3)); + m(3,1) = DOUBLEtoFLOAT(md(3,1)); m(3,2) = DOUBLEtoFLOAT(md(3,2)); m(3,3) = DOUBLEtoFLOAT(md(3,3)); + return m; +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/OBBox.h b/Sources/Engine/Math/OBBox.h new file mode 100644 index 0000000..d2037fd --- /dev/null +++ b/Sources/Engine/Math/OBBox.h @@ -0,0 +1,273 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_OBBOX_H +#define SE_INCL_OBBOX_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include + +/* + * Template for oriented bounding box of arbitrary type in 3D + */ +template +class OBBox { +// implementation: +public: + Vector box_vO; // center of the box + Vector box_avAxis[3]; // axis direction vectors + Type box_atSize[3]; // size on each of the axis (in both directions) + + /* Clear to normalized empty bounding box. */ + inline void SetToNormalizedEmpty(void); +// interface: +public: + /* Default constructor. */ + inline OBBox(void); + /* Constructor from components. */ + inline OBBox(const Vector &vO, + const Vector &vAxis0, const Vector &vAxis1, const Vector &vAxis2, + Type tSize0, Type tSize1, Type tSize2); + /* Constructor from axis aligned box and placement. */ + inline OBBox(const AABBox &aabbox, + const Vector &vPos, const Matrix &mRot); + /* Constructor from axis aligned box without placement. */ + inline OBBox(const AABBox &aabbox); + + // classify box with respect to a plane + inline Type TestAgainstPlane(const Plane &pl) const; + // check if two boxes intersect/touch + inline BOOL HasContactWith(const OBBox &boxB) const; + + /* Check if empty. */ + inline BOOL IsEmpty(void) const; +}; + +/* + * Clear to normalized empty bounding box. + */ +template +inline void OBBox::SetToNormalizedEmpty(void) { + for ( int i=0; i<3; i++ ) { + box_atSize[i] = LowerLimit(Type(0)); + } +} + +/* + * Constructor for empty bounding box. + */ +template +inline OBBox::OBBox() { + SetToNormalizedEmpty(); +} + +/* Constructor from axis aligned box and placement. */ +template +inline OBBox::OBBox(const AABBox &aabbox, + const Vector &vPos, const Matrix &mRot) +{ + // translate and rotate the center + box_vO = aabbox.Center()*mRot+vPos; + // extracted orientation from the rotation matrix + box_avAxis[0](1) = mRot(1,1); box_avAxis[0](2) = mRot(2,1); box_avAxis[0](3) = mRot(3,1); + box_avAxis[1](1) = mRot(1,2); box_avAxis[1](2) = mRot(2,2); box_avAxis[1](3) = mRot(3,2); + box_avAxis[2](1) = mRot(1,3); box_avAxis[2](2) = mRot(2,3); box_avAxis[2](3) = mRot(3,3); + + // get sizes from obbox sizes + box_atSize[0] = aabbox.Size()(1)*0.5f; + box_atSize[1] = aabbox.Size()(2)*0.5f; + box_atSize[2] = aabbox.Size()(3)*0.5f; +} +/* Constructor from axis aligned box without placement. */ +template +inline OBBox::OBBox(const AABBox &aabbox) +{ + box_vO = aabbox.Center(); + box_avAxis[0] = Vector(1,0,0); + box_avAxis[1] = Vector(0,1,0); + box_avAxis[2] = Vector(0,0,1); + box_atSize[0] = aabbox.Size()(1)*0.5f; + box_atSize[1] = aabbox.Size()(2)*0.5f; + box_atSize[2] = aabbox.Size()(3)*0.5f; +} + +/* Constructor from components. */ +template +inline OBBox::OBBox(const Vector &vO, + const Vector &vAxis0, const Vector &vAxis1, const Vector &vAxis2, + Type tSize0, Type tSize1, Type tSize2) { + box_vO = vO; + box_avAxis[0] = vAxis0; box_avAxis[1] = vAxis1; box_avAxis[2] = vAxis2; + box_atSize[0] = tSize0; box_atSize[1] = tSize1; box_atSize[2] = tSize2; +}; + +/* + * Check if empty. + */ +template +inline BOOL OBBox::IsEmpty(void) const { + // if any dimension is empty, it is empty + for ( int i=0; i<3; i++ ) { + if (box_atSize[i] < Type(0)) { + return TRUE; + } + } + // otherwise, it is not empty + return FALSE; +} + +// classify a box with respect to a plane +template +inline Type OBBox::TestAgainstPlane(const Plane &pl) const +{ + // project each axis to the plane normal + Type tNX = ((const Vector &)pl)%box_avAxis[0]; + Type tNY = ((const Vector &)pl)%box_avAxis[1]; + Type tNZ = ((const Vector &)pl)%box_avAxis[2]; + // calculate overall size of the box along the plane normal + Type tSize = Abs(tNX*box_atSize[0]) + Abs(tNY*box_atSize[1]) + Abs(tNZ*box_atSize[2]); + // get distance of the center from the plane + Type tCenterD = pl.PointDistance(box_vO); + + // if the center is further front than box's size + if (tCenterD>tSize) { + // completely in front ` + return Type(1); + // if the center is further back than box's size + } else if (tCenterD<-tSize) { + // completely back + return Type(-1); + // otherwise, it touches the plane + } else { + return Type(0); + } +} + +// check if two boxes intersect/touch +// using the separating axes theorem +template +inline BOOL OBBox::HasContactWith(const OBBox &boxB) const +{ + const OBBox &boxA = *this; + + // find offset in abs space + Vector vOffAbs = boxB.box_vO - boxA.box_vO; + // rotate offset to A space + Type vOffA[3] = { + vOffAbs%boxA.box_avAxis[0], + vOffAbs%boxA.box_avAxis[1], + vOffAbs%boxA.box_avAxis[2]}; + + // calculate rotation matrix from B to A + Type mR[3][3]; + {for(INDEX i=0; i<3; i++) { + {for(INDEX j=0; j<3; j++) { + mR[i][j] = boxA.box_avAxis[i]%boxB.box_avAxis[j]; + }} + }} + + Type tRa, tRb, tT; + + // check each axis of A + {for(INDEX i=0; i<3; i++ ) { + tRa = boxA.box_atSize[i]; + tRb = boxB.box_atSize[0]*Abs(mR[i][0]) + boxB.box_atSize[1]*Abs(mR[i][1]) + boxB.box_atSize[2]*Abs(mR[i][2]); + tT = Abs( vOffA[i] ); + if (tT>tRa+tRb) return FALSE; + }} + + // check each axis of B + {for(INDEX i=0; i<3; i++ ) { + tRa = boxA.box_atSize[0]*Abs(mR[0][i]) + boxA.box_atSize[1]*Abs(mR[1][i]) + boxA.box_atSize[2]*Abs(mR[2][i]); + tRb = boxB.box_atSize[i]; + tT = Abs( vOffA[0]*mR[0][i] + vOffA[1]*mR[1][i] + vOffA[2]*mR[2][i] ); + if (tT>tRa+tRb) return FALSE; + }} + + // check A0 x B0 + tRa = boxA.box_atSize[1]*Abs(mR[2][0]) + boxA.box_atSize[2]*Abs(mR[1][0]); + tRb = boxB.box_atSize[1]*Abs(mR[0][2]) + boxB.box_atSize[2]*Abs(mR[0][1]); + tT = Abs( vOffA[2]*mR[1][0] - vOffA[1]*mR[2][0] ); + if(tT>tRa+tRb) return FALSE; + + // check A0 x B1 + tRa = boxA.box_atSize[1]*Abs(mR[2][1]) + boxA.box_atSize[2]*Abs(mR[1][1]); + tRb = boxB.box_atSize[0]*Abs(mR[0][2]) + boxB.box_atSize[2]*Abs(mR[0][0]); + tT = Abs( vOffA[2]*mR[1][1] - vOffA[1]*mR[2][1] ); + if(tT>tRa+tRb) return FALSE; + + // check A0 x B2 + tRa = boxA.box_atSize[1]*Abs(mR[2][2]) + boxA.box_atSize[2]*Abs(mR[1][2]); + tRb = boxB.box_atSize[0]*Abs(mR[0][1]) + boxB.box_atSize[1]*Abs(mR[0][0]); + tT = Abs( vOffA[2]*mR[1][2] - vOffA[1]*mR[2][2] ); + if(tT>tRa+tRb) return FALSE; + + // check A1 x B0 + tRa = boxA.box_atSize[0]*Abs(mR[2][0]) + boxA.box_atSize[2]*Abs(mR[0][0]); + tRb = boxB.box_atSize[1]*Abs(mR[1][2]) + boxB.box_atSize[2]*Abs(mR[1][1]); + tT = Abs( vOffA[0]*mR[2][0] - vOffA[2]*mR[0][0] ); + if(tT>tRa+tRb) return FALSE; + + // check A1 x B1 + tRa = boxA.box_atSize[0]*Abs(mR[2][1]) + boxA.box_atSize[2]*Abs(mR[0][1]); + tRb = boxB.box_atSize[0]*Abs(mR[1][2]) + boxB.box_atSize[2]*Abs(mR[1][0]); + tT = Abs( vOffA[0]*mR[2][1] - vOffA[2]*mR[0][1] ); + if(tT>tRa+tRb) return FALSE; + + // check A1 x B2 + tRa = boxA.box_atSize[0]*Abs(mR[2][2]) + boxA.box_atSize[2]*Abs(mR[0][2]); + tRb = boxB.box_atSize[0]*Abs(mR[1][1]) + boxB.box_atSize[1]*Abs(mR[1][0]); + tT = Abs( vOffA[0]*mR[2][2] - vOffA[2]*mR[0][2] ); + if(tT>tRa+tRb) return FALSE; + + // check A2 x B0 + tRa = boxA.box_atSize[0]*Abs(mR[1][0]) + boxA.box_atSize[1]*Abs(mR[0][0]); + tRb = boxB.box_atSize[1]*Abs(mR[2][2]) + boxB.box_atSize[2]*Abs(mR[2][1]); + tT = Abs( vOffA[1]*mR[0][0] - vOffA[0]*mR[1][0] ); + if(tT>tRa+tRb) return FALSE; + + // check A2 x B1 + tRa = boxA.box_atSize[0]*Abs(mR[1][1]) + boxA.box_atSize[1]*Abs(mR[0][1]); + tRb = boxB.box_atSize[0] *Abs(mR[2][2]) + boxB.box_atSize[2]*Abs(mR[2][0]); + tT = Abs( vOffA[1]*mR[0][1] - vOffA[0]*mR[1][1] ); + if(tT>tRa+tRb) return FALSE; + + // check A2 x B2 + tRa = boxA.box_atSize[0]*Abs(mR[1][2]) + boxA.box_atSize[1]*Abs(mR[0][2]); + tRb = boxB.box_atSize[0]*Abs(mR[2][1]) + boxB.box_atSize[1]*Abs(mR[2][0]); + tT = Abs( vOffA[1]*mR[0][2] - vOffA[0]*mR[1][2] ); + if(tT>tRa+tRb) return FALSE; + + return TRUE; +} + +// helper functions for converting between FLOAT and DOUBLE obboxes +inline DOUBLEobbox3D FLOATtoDOUBLE(const FLOATobbox3D &boxf) { + return DOUBLEobbox3D( + FLOATtoDOUBLE(boxf.box_vO), + FLOATtoDOUBLE(boxf.box_avAxis[0]), + FLOATtoDOUBLE(boxf.box_avAxis[1]), + FLOATtoDOUBLE(boxf.box_avAxis[2]), + FLOATtoDOUBLE(boxf.box_atSize[0]), + FLOATtoDOUBLE(boxf.box_atSize[1]), + FLOATtoDOUBLE(boxf.box_atSize[2])); +} +inline FLOATobbox3D DOUBLEtoFLOAT(const DOUBLEobbox3D &boxd) { + return FLOATobbox3D( + DOUBLEtoFLOAT(boxd.box_vO), + DOUBLEtoFLOAT(boxd.box_avAxis[0]), + DOUBLEtoFLOAT(boxd.box_avAxis[1]), + DOUBLEtoFLOAT(boxd.box_avAxis[2]), + DOUBLEtoFLOAT(boxd.box_atSize[0]), + DOUBLEtoFLOAT(boxd.box_atSize[1]), + DOUBLEtoFLOAT(boxd.box_atSize[2])); +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/Object3D.cpp b/Sources/Engine/Math/Object3D.cpp new file mode 100644 index 0000000..55f41db --- /dev/null +++ b/Sources/Engine/Math/Object3D.cpp @@ -0,0 +1,300 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include + +#include +#include + +inline void Clear(CObjectEdge *poed) {}; + +/* + * Default constructor. + */ +CObject3D::CObject3D() { +}; + +/* + * Destructor. + */ +CObject3D::~CObject3D() { + Clear(); +}; + +void CObject3D::Clear(void) +{ + ob_aoscSectors.Clear(); // clear sectors array +} +/* + * Create indices for all sectors. + */ +void CObject3D::CreateSectorIndices(void) +{ + ob_aoscSectors.Lock(); + + // get the number of sectors in object + INDEX ctSectors = ob_aoscSectors.Count(); + // set sectors indices + for(INDEX iSector=0; iSectorArePolygonsPlanar()) return FALSE; + } + return TRUE; +} + +/* + * Project the whole object into some other space. + */ +void CObject3D::Project(CSimpleProjection3D_DOUBLE &pr) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + // check if projection is mirrored + const FLOAT3D &vObjectStretch = pr.ObjectStretchR(); + BOOL bXInverted = vObjectStretch(1)<0; + BOOL bYInverted = vObjectStretch(2)<0; + BOOL bZInverted = vObjectStretch(3)<0; + BOOL bInverted = bXInverted!=bYInverted!=bZInverted; + + // for all sectors + FOREACHINDYNAMICARRAY(ob_aoscSectors, CObjectSector, itsc) { + + // for all vertices in sector + FOREACHINDYNAMICARRAY(itsc->osc_aovxVertices, CObjectVertex, itvx) { + // project the vertex + pr.ProjectCoordinate(*itvx, *itvx); + } + + /* NOTE: We must project polygons _before_ planes, since projecting + of texture mapping coefficients requires unprojected plane! */ + // for all polygons in sector + FOREACHINDYNAMICARRAY(itsc->osc_aopoPolygons, CObjectPolygon, itpo) { + // project mapping + pr.ProjectMapping(itpo->opo_amdMappings[0], *itpo->opo_Plane, itpo->opo_amdMappings[0]); + pr.ProjectMapping(itpo->opo_amdMappings[1], *itpo->opo_Plane, itpo->opo_amdMappings[1]); + pr.ProjectMapping(itpo->opo_amdMappings[2], *itpo->opo_Plane, itpo->opo_amdMappings[2]); + pr.ProjectMapping(itpo->opo_amdMappings[3], *itpo->opo_Plane, itpo->opo_amdMappings[3]); + // if projection is inverted + if (bInverted) { + // invert all polygon edges + {FOREACHINDYNAMICARRAY(itpo->opo_PolygonEdges, CObjectPolygonEdge, itope) { + CObjectPolygonEdge &ope = *itope; + ope.ope_Backward = !ope.ope_Backward; + }} + } + } + // for all planes in sector + FOREACHINDYNAMICARRAY(itsc->osc_aoplPlanes, CObjectPlane, itpl) { + // project the plane + pr.Project(*itpl, *itpl); + } + } +} + +/* + * Assignment operator. + */ +CObject3D &CObject3D::operator=(CObject3D &obOriginal) +{ + // copy array of sectors from original object, sectors will copy their contents + ob_aoscSectors = obOriginal.ob_aoscSectors; + + return *this; +} + +/* + * Create BSP trees for all sectors. + */ +void CObject3D::CreateSectorBSPs(void) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + // for each sector in object + FOREACHINDYNAMICARRAY(ob_aoscSectors, CObjectSector, itosc) { + // create its BSP tree + itosc->CreateBSP(); + } +} + +/* + * Remove sectors with no polygons. + */ +void CObject3D::RemoveEmptySectors(void) +{ + // create a container for empty sectors + CDynamicContainer coscEmpty; + + // for all sectors in object + {FOREACHINDYNAMICARRAY(ob_aoscSectors, CObjectSector, itosc) { + // if it has no polygons + if (itosc->osc_aopoPolygons.Count() == 0) { + // add the sector to the container of empty sectors + coscEmpty.Add(&itosc.Current()); + } + }} + + // for all empty sectors + {FOREACHINDYNAMICCONTAINER(coscEmpty, CObjectSector, itoscEmpty) { + // delete the sector from object + ob_aoscSectors.Delete(&itoscEmpty.Current()); + }} +} + +/* + * Remove unused and replicated elements. + */ +void CObject3D::Optimize(void) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + + // for all sectors in the object + {FOREACHINDYNAMICARRAY(ob_aoscSectors, CObjectSector, itosc) { + // optimize the sector + itosc->Optimize(); + }} + + // remove sectors that have no polygons + RemoveEmptySectors(); +} + +/* + * Turn all sectors in object inside-out. (not recommended for multi sector objects) + */ +void CObject3D::Inverse(void) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + // for all sectors in object + {FOREACHINDYNAMICARRAY(ob_aoscSectors, CObjectSector, itosc) { + // inverse the sector + itosc->Inverse(); + }} +} + +/* Recalculate all planes from vertices. (used when stretching vertices) */ +void CObject3D::RecalculatePlanes(void) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + // for all sectors in object + {FOREACHINDYNAMICARRAY(ob_aoscSectors, CObjectSector, itosc) { + // recalculate all planes in sector + itosc->RecalculatePlanes(); + }} +} + +/* + * Turn all portals to walls. + */ +void CObject3D::TurnPortalsToWalls(void) +{ + // for all sectors in object + {FOREACHINDYNAMICARRAY(ob_aoscSectors, CObjectSector, itosc) { + // for all polygons + {FOREACHINDYNAMICARRAY(itosc->osc_aopoPolygons, CObjectPolygon, itopo) { + // clear the portal flag + itopo->opo_ulFlags &= ~OPOF_PORTAL; + }} + }} +} + +/* + * Find bounding box of the object. + */ +void CObject3D::GetBoundingBox(DOUBLEaabbox3D &boxObject) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + // clear the bounding box + boxObject = DOUBLEaabbox3D(); + // for each sector in the object + FOREACHINDYNAMICARRAY(ob_aoscSectors, CObjectSector, itosc) { + // get box of the sector + DOUBLEaabbox3D boxSector; + itosc->GetBoundingBox(boxSector); + // add the sector box to the bounding box + boxObject |= boxSector; + } +} + +/* Dump the object 3D to debug window. */ +void CObject3D::DebugDump(void) +{ +#ifndef NDEBUG + + _RPT0(_CRT_WARN, "Object3D dump BEGIN:\n"); + + _RPT1(_CRT_WARN, "Sectors: %d\n", ob_aoscSectors.Count()); + {FOREACHINDYNAMICARRAY(ob_aoscSectors, CObjectSector, itosc) { + + _RPT1(_CRT_WARN, "SC%d:\n", ob_aoscSectors.Index(&itosc.Current())); + + _RPT1(_CRT_WARN, "Vertices: %d\n", itosc->osc_aovxVertices.Count()); + {FOREACHINDYNAMICARRAY(itosc->osc_aovxVertices, CObjectVertex, itovx) { + _RPT4(_CRT_WARN, "VX%d: (%f, %f, %f)\n", itosc->osc_aovxVertices.Index(itovx), + (*itovx)(1), (*itovx)(2), (*itovx)(3)); + }} + + _RPT1(_CRT_WARN, "Planes: %d\n", itosc->osc_aoplPlanes.Count()); + {FOREACHINDYNAMICARRAY(itosc->osc_aoplPlanes, CObjectPlane, itopl) { + _RPT4(_CRT_WARN, "PL%d: (%g, %g, %g)", itosc->osc_aoplPlanes.Index(&itopl.Current()), + itopl.Current()(1), itopl.Current()(2), itopl.Current()(3)); + _RPT1(_CRT_WARN, ":%g\n", itopl->Distance()); + }} + + _RPT1(_CRT_WARN, "Edges: %d\n", itosc->osc_aoedEdges.Count()); + itosc->osc_aovxVertices.Lock(); + {FOREACHINDYNAMICARRAY(itosc->osc_aoedEdges, CObjectEdge, itoed) { + _RPT3(_CRT_WARN, "ED%d: VX%d -> VX%d\n", itosc->osc_aoedEdges.Index(&itoed.Current()), + itosc->osc_aovxVertices.Index(itoed->oed_Vertex0), + itosc->osc_aovxVertices.Index(itoed->oed_Vertex1)); + }} + itosc->osc_aovxVertices.Unlock(); + + + _RPT1(_CRT_WARN, "Polygons: %d\n", itosc->osc_aopoPolygons.Count()); + itosc->osc_aovxVertices.Lock(); + itosc->osc_aoedEdges.Lock(); + itosc->osc_aoplPlanes.Lock(); + {FOREACHINDYNAMICARRAY(itosc->osc_aopoPolygons, CObjectPolygon, itopo) { + _RPT3(_CRT_WARN, "PO%d (PL%d): Edges: %d\n ", + itosc->osc_aopoPolygons.Index(&itopo.Current()), + itosc->osc_aoplPlanes.Index(itopo->opo_Plane), + itopo->opo_PolygonEdges.Count()); + {FOREACHINDYNAMICARRAY(itopo->opo_PolygonEdges, CObjectPolygonEdge, itope) { + _RPT1(_CRT_WARN, "ED%d", itosc->osc_aoedEdges.Index(itope->ope_Edge)); + CObjectVertex *povx0, *povx1; + if (itope->ope_Backward) { + povx0 = itope->ope_Edge->oed_Vertex1; + povx1 = itope->ope_Edge->oed_Vertex0; + } else { + povx0 = itope->ope_Edge->oed_Vertex0; + povx1 = itope->ope_Edge->oed_Vertex1; + } + _RPT4(_CRT_WARN, " (VX%d (%f,%f,%f)", + itosc->osc_aovxVertices.Index(povx0), (*povx0)(1), (*povx0)(2), (*povx0)(3)); + _RPT4(_CRT_WARN, "->VX%d (%f,%f,%f)) ", + itosc->osc_aovxVertices.Index(povx1), (*povx1)(1), (*povx1)(2), (*povx1)(3)); + }} + _RPT0(_CRT_WARN, "\n"); + }} + itosc->osc_aoplPlanes.Unlock(); + itosc->osc_aoedEdges.Unlock(); + itosc->osc_aovxVertices.Unlock(); + }} + + _RPT0(_CRT_WARN, "Object3D dump END:\n"); + +#endif // NDEBUG +} + diff --git a/Sources/Engine/Math/Object3D.h b/Sources/Engine/Math/Object3D.h new file mode 100644 index 0000000..2351ed5 --- /dev/null +++ b/Sources/Engine/Math/Object3D.h @@ -0,0 +1,409 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_OBJECT3D_H +#define SE_INCL_OBJECT3D_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +// a vertex in 3d object +class CObjectVertex : public DOUBLE3D { +public: + CObjectVertex *ovx_Remap; // pointer for index remapping + ULONG ovx_Tag; // tag for format-specific data + INDEX ovx_Index; // index for easier conversions + // flags 0-7 are used by CObjectVertex, flags 8-31 are reserved for custom formats + ULONG ovx_ulFlags; // flags + + /* Default constructor. */ + inline CObjectVertex(void) { ovx_ulFlags = 0;}; + /* Constructor from vector. */ + inline CObjectVertex(const DOUBLE3D &v) : DOUBLE3D(v) { ovx_ulFlags = 0;}; + /* Clear the object. */ + inline void Clear(void) {}; +}; + +// a plane in 3d object +class CObjectPlane : public DOUBLEplane3D { +public: + CObjectPlane *opl_Remap; // pointer for index remapping + ULONG opl_Tag; // tag for format-specific data + INDEX opl_Index; // index for easier conversions + + /* Default constructor. */ + inline CObjectPlane(void) {}; + /* Constructor from plane. */ + inline CObjectPlane(const DOUBLEplane3D &pl) : DOUBLEplane3D(pl) {}; + /* Clear the object. */ + inline void Clear(void) {}; +}; + +/* rcg10042001 named anonymous structs. */ +// an edge in 3d object +class CObjectEdge { +public: + ULONG oed_Tag; // tag for format-specific data + INDEX oed_Index; // index for easier conversions + union { + struct { // used in optimization + CObjectEdge *oed_Remap; // pointer for index remapping + CObjectEdge *oed_InverseEdge; // pointer to inverse edge, if exists + } optimize; + struct { // used in splitting collinear edges + CObjectEdge *oed_FirstChild; // pointer to first part of split edge + CObjectEdge *oed_NextSibling; // pointer to next part of split edge + } colinear1; + struct { // used in splitting collinear edges + class CEdgeEx *oed_pedxLine; // pointer to line information + } colinear2; + }; + + CObjectVertex *oed_Vertex0; // start vertex + CObjectVertex *oed_Vertex1; // end vertex + + /* Default constructor. */ + inline CObjectEdge(void) {}; + /* Constructor from vertex references. */ + inline CObjectEdge(CObjectVertex &ovxVertex0, CObjectVertex &ovxVertex1) + : oed_Vertex0(&ovxVertex0), oed_Vertex1(&ovxVertex1) {}; + /* Clear the object. */ + inline void Clear(void) {}; +}; + +// a material in 3d object +class CObjectMaterial { +public: + ULONG omt_Tag; // tag for format-specific data + INDEX omt_Index; // index for easier conversions + CTString omt_Name; // name of this material + CTString omt_strName2; + CTString omt_strName3; + COLOR omt_Color; // color of this material (surface) + + /* Default constructor. */ + inline CObjectMaterial(void) : omt_Name("") {}; + /* Constructor from string. */ + inline CObjectMaterial(const CTString &strName) : omt_Name(strName) {}; + /* Copy constructor. */ + inline CObjectMaterial(const CObjectMaterial &omt) { + omt_Name = omt.omt_Name; + omt_strName2 = omt.omt_strName2; + omt_strName3 = omt.omt_strName3; + omt_Color = omt.omt_Color; + }; + /* Destructor. */ + inline ~CObjectMaterial(void) {}; + /* Clear the object. */ + inline void Clear(void) { + omt_Name.Clear(); + omt_strName2.Clear(); + omt_strName3.Clear(); + }; + + /* Assignment. */ + inline const CObjectMaterial &operator=(const CObjectMaterial &omt) { + omt_Name = omt.omt_Name; + omt_strName2 = omt.omt_strName2; + omt_strName3 = omt.omt_strName3; + omt_Color = omt.omt_Color; + return *this; + }; + /* Color assignment. */ + inline void SetColor(const COLOR &clrColor) { omt_Color = clrColor; }; +}; + +// a reference to edge in polygon +class ENGINE_API CObjectPolygonEdge { +public: + CObjectEdge *ope_Edge; // pointer to the edge + BOOL ope_Backward; // true if vertex0 and vertex1 must be swapped + + /* Default constructor. */ + inline CObjectPolygonEdge(void) : ope_Backward(FALSE) {}; + /* Constructor from edge pointer. */ + inline CObjectPolygonEdge(CObjectEdge *poed) : ope_Edge(poed), ope_Backward(FALSE) {}; + /* Constructor from edge pointer and reverse marker. */ + inline CObjectPolygonEdge(CObjectEdge *poed, BOOL bReverse) + : ope_Edge(poed), ope_Backward(bReverse) {}; + /* Clear the object. */ + inline void Clear(void) {}; + /* Get start and end vertices. */ + inline void GetVertices(CObjectVertex *&povxStart, CObjectVertex *&povxEnd); +}; + +// a polygon in 3d object +// Flags +// flags 0-2 are used by CObjectPolygon, flags 3-31 are reserved for custom formats +#define OPOF_PORTAL (1L<<0) // set if the polygon is portal +#define OPOF_IGNOREDBYCSG (1L<<1) // set if the polygon is ignored when doing CSG + +class ENGINE_API CObjectPolygon { +public: + ULONG opo_Tag; // tag for format-specific data + INDEX opo_Index; // index for easier conversions + +#define OPO_MAXUSERDATA 64 + UBYTE opo_ubUserData[OPO_MAXUSERDATA]; // reserved space for other data + + CObjectPlane *opo_Plane; // plane of this polygon + CDynamicArray opo_PolygonEdges; // edges in this polygon + CObjectMaterial *opo_Material; // material of this polygon + CMappingDefinition opo_amdMappings[4]; // mapping of textures on this polygon + ULONG opo_ulFlags; // various flags + COLOR opo_colorColor; // color of this polygon + void *opo_pvOriginal; // used for format conversions + + /* Default constructor. */ + inline CObjectPolygon(void) : opo_Material(NULL), opo_ulFlags(0), opo_pvOriginal(NULL) + { memset(&opo_ubUserData, 0, sizeof(opo_ubUserData)); }; + /* Clear the object. */ + inline void Clear(void) { opo_PolygonEdges.Clear(); }; + /* Join polygon edges that are collinear and continuing. */ + void JoinContinuingEdges(CDynamicArray &oedEdges); + /* Remove polygon edges that are used twice from a polygon. */ + void RemoveRedundantEdges(void); + /* Remove polygon edges that are marked as unused (oed_Edge==NULL) from polygon. */ + void RemoveMarkedEdges(INDEX ctNonMarkedEdges); + /* Remove polygon edges that have zero length from a polygon. */ + void RemoveDummyEdgeReferences(void); +}; + +// a sector in 3d object +class CObjectSector { +public: + + /* Create a new edge with two coordinates. */ + inline CObjectEdge &CreateEdge(INDEX ivx0, INDEX ivx1) { + // lock vertex array + osc_aovxVertices.Lock(); + // create edge + CObjectEdge &oeResult = + *osc_aoedEdges.New(1) = CObjectEdge(osc_aovxVertices[ivx0], osc_aovxVertices[ivx1]); + // unlock vertex array + osc_aovxVertices.Unlock(); + return oeResult; + } + + /* Create a new edge with two coordinates. */ + inline CObjectEdge &CreateEdge(const DOUBLE3D &vx0, const DOUBLE3D &vx1) { + // create end vertices for the part + CObjectVertex *aovxs = osc_aovxVertices.New(2); + aovxs[0] = vx0; + aovxs[1] = vx1; + // create edge + return *osc_aoedEdges.New(1) = CObjectEdge(aovxs[0], aovxs[1]); + } + + /* Create an edge and add it to a polygon in this sector. */ + inline void CreateEdgeInPolygon(CObjectPolygon &opoPolygon, + const DOUBLE3D &vVertex0, const DOUBLE3D &vVertex1) { + *opoPolygon.opo_PolygonEdges.New(1) = + CObjectPolygonEdge( &CreateEdge(vVertex0, vVertex1)); + }; + + /* Check the optimization algorithm. */ + void CheckOptimizationAlgorithm(void); + /* See if all polygons in sector are valid (planar). */ + BOOL ArePolygonsPlanar(void); + /* Create indices for all members of all arrays. */ + void CreateIndices(void); + /* Create BSP tree for sector. */ + void CreateBSP(void); + + // optimization functions + /* Remap different vertices with same coordinates to use only one of each. */ + void RemapClonedVertices(void); + /* Remap different edges with same or reverse vertices to use only one of each. */ + void RemapClonedEdges(void); + /* Remap different planes with same coordinates to use only one of each. */ + void RemapClonedPlanes(void); + + /* Remove vertices that are not used by any edge. */ + void RemoveUnusedVertices(void); + /* Remove edges that are not used by any polygon. */ + void RemoveUnusedEdges(void); + /* Remove planes that are not used by any polygon. */ + void RemoveUnusedPlanes(void); + + /* Create array of extended edge infos. */ + void CreateEdgeLines(CStaticArray &aedxEdgeLines, + CStaticArray &apedxSortedEdgeLines, INDEX &ctEdges); + /* Join polygon edges that are collinear and continuing. */ + void JoinContinuingPolygonEdges(void); + /* Find collinear edges and cross-split them with each other. */ + void SplitCollinearEdges(void); + /* Split a run of collinear edges. */ + void SplitCollinearEdgesRun(CStaticArray &apedxSortedEdgeLines, + INDEX iFirstInRun, INDEX iLastInRun); + /* Split an edge with a run of vertices. */ + inline void SplitEdgeWithVertices(CObjectEdge &oedOriginal, + CStaticArray &apvxVertices); + /* Remove polygon edges that are used twice from all polygons. */ + void RemoveRedundantPolygonEdges(void); + + /* Remove polygons with less than 3 edges. */ + void RemoveDummyPolygons(void); + /* Find edges that have zero length and remove them from all polygons. */ + void RemoveDummyEdgeReferences(void); + + /* Remove unused and replicated elements. */ + void Optimize(void); + + /* Turn sector inside-out. */ + void Inverse(void); + /* Recalculate all planes from vertices. (used when stretching vertices) */ + void RecalculatePlanes(void); + +public: + CDynamicArray osc_aovxVertices; // vertices + CDynamicArray osc_aoplPlanes; // planes + CDynamicArray osc_aomtMaterials; // material info + CDynamicArray osc_aoedEdges; // edges + CDynamicArray osc_aopoPolygons; // polygons + + ULONG osc_Tag; // tag for format-specific data + INDEX osc_Index; // index for easier conversions + COLOR osc_colColor; // color of this sector + COLOR osc_colAmbient; // ambient lightning of this sector + ULONG osc_ulFlags[3]; // flags (not used in CTMath) + + CTString osc_strName; // name of the sector + + DOUBLEbsptree3D osc_BSPTree; // BSP tree of this sector + + /* Default constructor. */ + ENGINE_API CObjectSector(void); + /* Destructor. */ + ENGINE_API ~CObjectSector(void); + + /* Clear the object. */ + void Clear(void); + /* Assignment operator. */ + ENGINE_API CObjectSector &operator=(CObjectSector &oscOriginal); + + /* Locks all object sector dynamic arrays */ + void LockAll( void); + /* Unlocks all object sector dynamic arrays */ + void UnlockAll( void); + + /* Create a new polygon in given sector. */ + ENGINE_API CObjectPolygon *CreatePolygon(INDEX ctVertices, INDEX aivVertices[], + CObjectMaterial &omaMaterial, ULONG ulFlags, BOOL bReverse); + /* Create a new polygon in given sector. */ + ENGINE_API CObjectPolygon *CreatePolygon(INDEX ctVertices, DOUBLE3D avVertices[], + CObjectMaterial &omaMaterial, ULONG ulFlags, BOOL bReverse); + /* Find bounding box of the sector. */ + void GetBoundingBox(DOUBLEaabbox3D &boxSector); +}; + +// a local class that holds extended edge information for finding collinear edges. +class CEdgeEx { +public: + CObjectEdge *edx_poedEdge; // the original edge in object + // constants of the line that the edge is on + DOUBLE3D edx_vDirection; // normalized direction vector of the line + DOUBLE3D edx_vReferencePoint; // reference point on the line + BOOL edx_bReverse; // set if the edge direction is opposite to the line direction + + /* Initialize the structure for the given edge. */ + inline void Initialize(CObjectEdge *poedEdge); + inline void Initialize(const DOUBLE3D *pvPoint0, const DOUBLE3D *pvPoint1); + /* Test if a point is on the edge line. */ + inline BOOL PointIsOnLine(const DOUBLE3D &vPoint) const; +}; + +/* + * A mathematical format of 3d object used for importing/exporting, CSG etc. + */ +class ENGINE_API CObject3D { +public: + enum LoadType { + LT_NORMAL = 0, + LT_OPENED, + LT_UNWRAPPED, + }; + + /* Remove sectors with no polygons. */ + void RemoveEmptySectors(void); + + /* Create indices of all sectors (doesn't create vertex indices etc.). */ + void CreateSectorIndices(void); + +public: + CDynamicArray ob_aoscSectors; // sectors + + /* Default constructor. */ + CObject3D(void); + /* Destructor. */ + ~CObject3D(void); + /* Clear all arrays. */ + void Clear(void); + + /* Recognize and load any of supported 3D file formats. */ + void LoadAny3DFormat_t( const CTFileName &FileName, const FLOATmatrix3D &mTransform, enum LoadType ltLoadType=LT_NORMAL); // throw (char *) + // start/end batch loading of 3d objects + static void BatchLoading_t(BOOL bOn); + /* Convert from intermediate structures into O3D */ + void ConvertArraysToO3D( void); + + /* Save in LightWave format. */ + void SaveLWO_t( const CTFileName &FileName); // throw (char *) + /* Save in 3DStudio format. */ + void SaveDXF_t( const CTFileName &FileName); // throw (char *) + + /* Remove unused and replicated elements. */ + void Optimize(void); + /* See if all polygons in object 3D are valid (planar). */ + BOOL ArePolygonsPlanar(void); + /* Create BSP trees for all sectors. */ + void CreateSectorBSPs(void); + + /* Project the whole object into some other space. */ + void Project(CSimpleProjection3D_DOUBLE &pr); + /* Assignment operator. */ + CObject3D &operator=(CObject3D &obOriginal); + /* Turn all sectors in object inside-out. (not recommended for multi sector objects) */ + void Inverse(void); + /* Recalculate all planes from vertices. (used when stretching vertices) */ + void RecalculatePlanes(void); + + /**** CSG operations -- they all destroy both operands! ****/ + /* Add rooms. */ + void CSGAddRooms(CObject3D &obA, CObject3D &obB); + /* Add material from object B to object A. (B should have only one + open sector and no closed sectors) */ + void CSGAddMaterial(CObject3D &obA, CObject3D &obB); + void CSGAddMaterialReverse(CObject3D &obA, CObject3D &obB); + /* Remove material of object B from object A. (B should have only one + open sector and no closed sectors) */ + void CSGRemoveMaterial(CObject3D &obA, CObject3D &obB); + /* Split sectors of object A using object B. (B should have only one + closed sector and no open sectors) */ + void CSGSplitSectors(CObject3D &obA, CObject3D &obB); + /* Join sectors of object A with sectors of object B. (both A and B should + have only one sector) */ + void CSGJoinSectors(CObject3D &obA, CObject3D &obB); + /* Split polygons of object A with sectors of object B. (both A and B should + have only one sector) */ + void CSGSplitPolygons(CObject3D &obA, CObject3D &obB); + /* Turn all portals to walls. */ + void TurnPortalsToWalls(void); + + /* Find bounding box of the object. */ + void GetBoundingBox(DOUBLEaabbox3D &boxObject); + + /* Dump the object 3D to debug window. */ + void DebugDump(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/Object3D_CSG.cpp b/Sources/Engine/Math/Object3D_CSG.cpp new file mode 100644 index 0000000..9464b92 --- /dev/null +++ b/Sources/Engine/Math/Object3D_CSG.cpp @@ -0,0 +1,674 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +#include + +/* + * CSG operation table action. + */ +enum CSGAction { + CSGA_WallA1, // wall of sector A1 + CSGA_WallA1_2, // wall of sector A1 second part + CSGA_PortalA1A2, // portal between A1 and A2 + CSGA_PortalA1A2_2, // portal between A1 and A2 second part + CSGA_PortalA1B1B1A1, // two portals: A1-B1 and B1-A1 + CSGA_WallB1, // wall of sector B1 + CSGA_PortalB1B2, // portal between B1 and B2 + CSGA_Remove, // this polygon is removed + CSGA_Proceed, // this polygon proceeds with testing +}; + +/* + * CSG operation table. + */ +struct CSGOperationTable { + enum CSGAction cot_WallA1InsideB1, cot_WallA1OutsideB, cot_WallA1OnB1BorderInside, cot_WallA1OnB1BorderOutside; + enum CSGAction cot_PortalA1A2InsideB1, cot_PortalA1A2OutsideB, cot_PortalA1A2OnB1BorderInside, cot_PortalA1A2OnB1BorderOutside; +}; + +/* + NOTE: In following tables, the operations for object B have A and B sectors reversed. + That is because tables are always interpreted as being for object A, therefore + when using it for B, sector B means 'sector of other object' that is in fact sector A + and vice versa. + For readable tables see "CSG.doc". +*/ + +/* + * CSG operation tables for 'add rooms'. + */ +static struct CSGOperationTable csgotAddRoomsA = { + CSGA_PortalA1B1B1A1, CSGA_WallA1, CSGA_WallA1, CSGA_PortalA1B1B1A1, + CSGA_PortalA1A2, CSGA_PortalA1A2, CSGA_PortalA1A2, CSGA_PortalA1A2, +}; +static struct CSGOperationTable csgotAddRoomsB = { + CSGA_Remove, CSGA_WallA1, CSGA_Remove, CSGA_Remove, + CSGA_Remove, CSGA_PortalA1A2, CSGA_Remove, CSGA_Remove, +}; + +/* + * CSG operation tables for 'add material'. + */ +static struct CSGOperationTable csgotAddMaterialA = { + CSGA_WallA1, CSGA_Remove, CSGA_Remove, CSGA_Remove, + CSGA_PortalA1A2, CSGA_Remove, CSGA_Remove, CSGA_Remove, +}; +static struct CSGOperationTable csgotAddMaterialB = { + CSGA_WallB1, CSGA_Remove, CSGA_WallB1, CSGA_Proceed, + CSGA_Remove, CSGA_Remove, CSGA_Remove, CSGA_Remove, +}; +static struct CSGOperationTable csgotAddMaterialReverseA = { + CSGA_WallA1, CSGA_Remove, CSGA_WallA1, CSGA_Remove, + CSGA_PortalA1A2, CSGA_Remove, CSGA_Remove, CSGA_Remove, +}; +static struct CSGOperationTable csgotAddMaterialReverseB = { + CSGA_WallB1, CSGA_Remove, CSGA_Remove, CSGA_Proceed, + CSGA_Remove, CSGA_Remove, CSGA_Remove, CSGA_Remove, +}; + +/* + * CSG operation tables for 'split sectors'. + */ +static struct CSGOperationTable csgotSplitSectorsA = { + CSGA_WallB1, CSGA_WallA1, CSGA_WallB1, CSGA_WallA1, + CSGA_PortalB1B2, CSGA_PortalA1A2, CSGA_PortalB1B2, CSGA_PortalA1A2, +}; +static struct CSGOperationTable csgotSplitSectorsB = { + CSGA_PortalA1B1B1A1, CSGA_Remove, CSGA_Remove, CSGA_Remove, + CSGA_Remove, CSGA_Remove, CSGA_Remove, CSGA_Remove, +}; + +/* + * CSG operation tables for 'join sectors'. + */ +static struct CSGOperationTable csgotJoinSectorsA = { + CSGA_Remove, CSGA_WallA1, CSGA_WallA1, CSGA_Remove, + CSGA_Remove, CSGA_PortalA1A2, CSGA_PortalA1A2, CSGA_Remove, +}; +static struct CSGOperationTable csgotJoinSectorsB = { + CSGA_Remove, CSGA_WallB1, CSGA_Remove, CSGA_Remove, + CSGA_Remove, CSGA_PortalB1B2, CSGA_Remove, CSGA_Remove, +}; + +/* + * CSG operation tables for 'split polygons'. + */ +static struct CSGOperationTable csgotSplitPolygonsA = { + CSGA_WallA1_2, CSGA_WallA1, CSGA_WallA1_2, CSGA_WallA1, + CSGA_PortalA1A2_2, CSGA_PortalA1A2, CSGA_PortalA1A2_2, CSGA_PortalA1A2, +}; +static struct CSGOperationTable csgotSplitPolygonsB = { + CSGA_Remove, CSGA_Remove, CSGA_Remove, CSGA_Remove, + CSGA_Remove, CSGA_Remove, CSGA_Remove, CSGA_Remove, +}; + +/* + * Create a new polygon that will be a piece of some split polygon. + */ +static inline CObjectPolygon *CreatePieceOfPolygon( + CObjectSector *poscSector, + const CObjectPolygon &opoOriginal, + BOOL bReversePlane) +{ + // create new polygon + CObjectPolygon *popoPiece = poscSector->osc_aopoPolygons.New(1); + + // if the plane should be reversed + if (bReversePlane) { + // create a new reversed plane + CObjectPlane *poplNew = poscSector->osc_aoplPlanes.New(1); + *poplNew = -*opoOriginal.opo_Plane; + popoPiece->opo_Plane = poplNew; + // otherwise + } else { + // create a new plane (not reversed) + CObjectPlane *poplNew = poscSector->osc_aoplPlanes.New(1); + *poplNew = *opoOriginal.opo_Plane; + popoPiece->opo_Plane = poplNew; + } + + // create a new material + CObjectMaterial *pomtNew = poscSector->osc_aomtMaterials.New(1); + *pomtNew = *opoOriginal.opo_Material; + popoPiece->opo_Material = pomtNew; + + // copy other attributes + popoPiece->opo_colorColor = opoOriginal.opo_colorColor; + memcpy(popoPiece->opo_amdMappings, opoOriginal.opo_amdMappings, + sizeof(opoOriginal.opo_amdMappings)); + popoPiece->opo_ulFlags = opoOriginal.opo_ulFlags; + memcpy(popoPiece->opo_ubUserData, opoOriginal.opo_ubUserData, OPO_MAXUSERDATA); + return popoPiece; +} + +/* + * A machine for doing CSG operations on an CObject3D object. + */ +class CObjectCSG { +public: + // pointers to sectors and polygons that is currently operating on + CObjectSector *oc_poscSectorA; + CObjectSector *oc_poscSectorB; + + CObjectPolygon *oc_popoA; + + CObjectPolygon *oc_popoWallA1; + CObjectPolygon *oc_popoWallA1_2; + CObjectPolygon *oc_popoPortalA1A2; + CObjectPolygon *oc_popoPortalA1A2_2; + CObjectPolygon *oc_popoPortalA1B1; + + CObjectPolygon *oc_popoWallB1; + CObjectPolygon *oc_popoPortalB1A1; + CObjectPolygon *oc_popoPortalB1B2; + + inline CObjectPolygon *GetWallA1(void); + inline CObjectPolygon *GetWallA1_2(void); + inline CObjectPolygon *GetPortalA1A2(void); + inline CObjectPolygon *GetPortalA1A2_2(void); + inline CObjectPolygon *GetPortalA1B1(void); + + inline CObjectPolygon *GetWallB1(void); + inline CObjectPolygon *GetPortalB1A1(void); + inline CObjectPolygon *GetPortalB1B2(void); + + BOOL oc_bCSGIngoringEnabled; + BOOL oc_bSkipObjectB; + + // array for holding edges that proceed with testing + CDynamicArray oc_abedProceeding; + + CObjectCSG(void) { + oc_bCSGIngoringEnabled = FALSE; + oc_bSkipObjectB = FALSE; + } + + /* Add an entire array of BSP edges to some polygon according to action code. */ + inline void AddEdgeArrayAccordingToAction( + CDynamicArray &abed, + enum CSGAction csga); + + /* Fill array of bsp edges from array of polygon edges. */ + void PolygonEdgesToBSPEdges( + CDynamicArray &aope, + CDynamicArray &abed + ); + +public: + /* Perform CSG splitting of sectors in one operand using other operand. */ + void DoCSGSplitting( + CObject3D &obResult, + CObject3D &obA, + INDEX iSectorOffsetA, + struct CSGOperationTable *pcsgotA, + CObject3D &obB, + INDEX iSectorOffsetB); + /* Perform CSG operation -- destroys both operands! */ + void DoCSGOperation( + CObject3D &obResult, + CObject3D &obA, + CObject3D &obB, + struct CSGOperationTable *pcsgotA, + struct CSGOperationTable *pcsgotB); +}; + +CObjectPolygon *CObjectCSG::GetWallA1(void) +{ + if (oc_popoWallA1==NULL) { + oc_popoWallA1 = CreatePieceOfPolygon(oc_poscSectorA, *oc_popoA, FALSE); + oc_popoWallA1->opo_ulFlags &= ~OPOF_PORTAL; + } + return oc_popoWallA1; +} + +CObjectPolygon *CObjectCSG::GetWallA1_2(void) +{ + if (oc_popoWallA1_2==NULL) { + oc_popoWallA1_2 = CreatePieceOfPolygon(oc_poscSectorA, *oc_popoA, FALSE); + oc_popoWallA1_2->opo_ulFlags &= ~OPOF_PORTAL; + } + return oc_popoWallA1_2; +} + +CObjectPolygon *CObjectCSG::GetPortalA1A2(void) +{ + if (oc_popoPortalA1A2==NULL) { + oc_popoPortalA1A2 = CreatePieceOfPolygon(oc_poscSectorA, *oc_popoA, FALSE); + oc_popoPortalA1A2->opo_ulFlags |= OPOF_PORTAL; + } + return oc_popoPortalA1A2; +} + +CObjectPolygon *CObjectCSG::GetPortalA1A2_2(void) +{ + if (oc_popoPortalA1A2_2==NULL) { + oc_popoPortalA1A2_2 = CreatePieceOfPolygon(oc_poscSectorA, *oc_popoA, FALSE); + oc_popoPortalA1A2_2->opo_ulFlags |= OPOF_PORTAL; + } + return oc_popoPortalA1A2_2; +} + +CObjectPolygon *CObjectCSG::GetPortalA1B1(void) +{ + if (oc_popoPortalA1B1==NULL) { + oc_popoPortalA1B1 = CreatePieceOfPolygon(oc_poscSectorA, *oc_popoA, FALSE); + oc_popoPortalA1B1->opo_ulFlags |= OPOF_PORTAL; + } + return oc_popoPortalA1B1; +} + +CObjectPolygon *CObjectCSG::GetWallB1(void) +{ + if (oc_popoWallB1==NULL) { + oc_popoWallB1 = CreatePieceOfPolygon(oc_poscSectorB, *oc_popoA, FALSE); + oc_popoWallB1->opo_ulFlags &= ~OPOF_PORTAL; + } + return oc_popoWallB1; +} + +CObjectPolygon *CObjectCSG::GetPortalB1A1(void) +{ + if (oc_popoPortalB1A1==NULL) { + oc_popoPortalB1A1 = CreatePieceOfPolygon(oc_poscSectorB, *oc_popoA, TRUE); // this one is reversed ! + oc_popoPortalB1A1->opo_ulFlags |= OPOF_PORTAL; + } + return oc_popoPortalB1A1; +} + +CObjectPolygon *CObjectCSG::GetPortalB1B2(void) +{ + if (oc_popoPortalB1B2==NULL) { + oc_popoPortalB1B2 = CreatePieceOfPolygon(oc_poscSectorB, *oc_popoA, FALSE); + oc_popoPortalB1B2->opo_ulFlags |= OPOF_PORTAL; + } + return oc_popoPortalB1B2; +} + +/* + * Fill array of bsp edges from array of polygon edges. + */ +void CObjectCSG::PolygonEdgesToBSPEdges( + CDynamicArray &aope, + CDynamicArray &abed + ) +{ + aope.Lock(); + abed.Lock(); + + // get number of edges in the polygon + INDEX ctEdges = aope.Count(); + // create that much edges in array of bsp edges + abed.New(ctEdges); + + // for each edge in polygon + for(INDEX iEdge=0; iEdgeoed_Vertex1, + *ope.ope_Edge->oed_Vertex0, (ULONG)ope.ope_Edge); + + // if it is not reversed + } else{ + // add bsp edge with normal vertices + abed[iEdge] = DOUBLEbspedge3D(*ope.ope_Edge->oed_Vertex0, + *ope.ope_Edge->oed_Vertex1, (ULONG)ope.ope_Edge); + } + } + + aope.Unlock(); + abed.Unlock(); +} + +/* + * Add an entire array of BSP edges to some polygon according to action code. + */ +inline void CObjectCSG::AddEdgeArrayAccordingToAction( + CDynamicArray &abed, + enum CSGAction csga) +{ + // if there are no edges to process + INDEX ctEdges = abed.Count(); + if (ctEdges==0) { + // do nothing + return; + } + + // if the action is Remove + if (csga==CSGA_Remove) { + // do nothing + return; + } + + // if the action is Proceed + if (csga==CSGA_Proceed) { + // add entire array to array of proceeding edges + oc_abedProceeding.MoveArray(abed); + return; + } + + // check the action code and find sector(s) and polygon(s) to add edges to + CObjectPolygon *popoNormal = NULL; + CObjectSector *poscNormal = NULL; + CObjectPolygon *popoReverse = NULL; + CObjectSector *poscReverse = NULL; + switch (csga) { + case CSGA_WallA1: + poscNormal = oc_poscSectorA; + popoNormal = GetWallA1(); + break; + case CSGA_WallA1_2: + poscNormal = oc_poscSectorA; + popoNormal = GetWallA1_2(); + break; + case CSGA_PortalA1A2_2: + poscNormal = oc_poscSectorA; + popoNormal = GetPortalA1A2_2(); + break; + case CSGA_PortalA1A2: + poscNormal = oc_poscSectorA; + popoNormal = GetPortalA1A2(); + break; + case CSGA_PortalA1B1B1A1: + poscNormal = oc_poscSectorA; + popoNormal = GetPortalA1B1(); + poscReverse = oc_poscSectorB; + popoReverse = GetPortalB1A1(); + break; + case CSGA_WallB1: + poscNormal = oc_poscSectorB; + popoNormal = GetWallB1(); + break; + case CSGA_PortalB1B2: + poscNormal = oc_poscSectorB; + popoNormal = GetPortalB1B2(); + break; + default: + ASSERTALWAYS("Unknown CSG action code"); + } + + // create needed number of vertices, edges and polygon edges + CObjectVertex *aovxNormal = NULL; + CObjectEdge *aoedNormal = NULL; + CObjectPolygonEdge *aopeNormal = NULL; + CObjectVertex *aovxReverse = NULL; + CObjectEdge *aoedReverse = NULL; + CObjectPolygonEdge *aopeReverse = NULL; + + aovxNormal = poscNormal->osc_aovxVertices.New(2*ctEdges); + aoedNormal = poscNormal->osc_aoedEdges.New(ctEdges); + aopeNormal = popoNormal->opo_PolygonEdges.New(ctEdges); + if (poscReverse!=NULL) { + aovxReverse = poscReverse->osc_aovxVertices.New(2*ctEdges); + aoedReverse = poscReverse->osc_aoedEdges.New(ctEdges); + aopeReverse = popoReverse->opo_PolygonEdges.New(ctEdges); + } + + abed.Lock(); + // add all edges to normal polygon + {for(INDEX iEdge=0; iEdgeosc_Index]; + // copy sector properties from operand A to result + oc_poscSectorA->osc_colColor = itoscA->osc_colColor; + oc_poscSectorA->osc_colAmbient = itoscA->osc_colAmbient; + oc_poscSectorA->osc_ulFlags[0] = itoscA->osc_ulFlags[0]; + oc_poscSectorA->osc_ulFlags[1] = itoscA->osc_ulFlags[1]; + oc_poscSectorA->osc_ulFlags[2] = itoscA->osc_ulFlags[2]; + oc_poscSectorA->osc_strName = itoscA->osc_strName; + + // for each of polygons in that sector + {FOREACHINDYNAMICARRAY(itoscA->osc_aopoPolygons, CObjectPolygon, itopoA) { + oc_popoA = itopoA; + // prepare appropriate actions for it + enum CSGAction csgaInside, csgaOutside, csgaBorderInside, csgaBorderOutside, csgaSkip; + if (itopoA->opo_ulFlags & OPOF_PORTAL) { + csgaInside = pcsgotA->cot_PortalA1A2InsideB1; + csgaOutside = pcsgotA->cot_PortalA1A2OutsideB; + csgaBorderInside = pcsgotA->cot_PortalA1A2OnB1BorderInside; + csgaBorderOutside = pcsgotA->cot_PortalA1A2OnB1BorderOutside; + csgaSkip = CSGA_PortalA1A2; + } else { + csgaInside = pcsgotA->cot_WallA1InsideB1; + csgaOutside = pcsgotA->cot_WallA1OutsideB; + csgaBorderInside = pcsgotA->cot_WallA1OnB1BorderInside; + csgaBorderOutside = pcsgotA->cot_WallA1OnB1BorderOutside; + csgaSkip = CSGA_WallA1; + } + + // create temporary array for holding remaining edges + CDynamicArray abedRemaining; + // fill the array with edges from the polygon + PolygonEdgesToBSPEdges(itopoA->opo_PolygonEdges, abedRemaining); + + // create wall A1 polygon + oc_popoWallA1 = NULL; + oc_popoWallA1_2 = NULL; + + // create portal A1-A2 polygon + oc_popoPortalA1A2 = NULL; + oc_popoPortalA1A2_2 = NULL; + + // if the polygon should be skipped + if (oc_bCSGIngoringEnabled && (itopoA->opo_ulFlags&OPOF_IGNOREDBYCSG)) { + // add entire polygon according to _skip_ action + AddEdgeArrayAccordingToAction(abedRemaining, csgaSkip); + // skip splitting + continue; + } + + // for each sector in B + {FOREACHINDYNAMICARRAY(obB.ob_aoscSectors, CObjectSector, itoscB) { + // clear array of proceeding edges + oc_abedProceeding.Clear(); + + // make sector references in result + oc_poscSectorB = &obResult.ob_aoscSectors[iSectorOffsetB+itoscB->osc_Index]; + // copy sector properties from operand B to result + oc_poscSectorB->osc_colColor = itoscB->osc_colColor; + oc_poscSectorB->osc_colAmbient = itoscB->osc_colAmbient; + oc_poscSectorB->osc_ulFlags[0] = itoscB->osc_ulFlags[0]; + oc_poscSectorB->osc_ulFlags[1] = itoscB->osc_ulFlags[1]; + oc_poscSectorB->osc_ulFlags[2] = itoscB->osc_ulFlags[2]; + oc_poscSectorB->osc_strName = itoscB->osc_strName; + + // create portal A1-B1 polygon + oc_popoPortalA1B1 = NULL; + + // create portal B1-A1 polygon + oc_popoPortalB1A1 = NULL; + + // create wall B1 polygon + oc_popoWallB1 = NULL; + + // create portal B1-B2 polygon + oc_popoPortalB1B2 = NULL; + + // create a bsp polygon from first temporary array + DOUBLEbsppolygon3D bpoA(*itopoA->opo_Plane, abedRemaining, (ULONG)itopoA->opo_Plane); + + // create a BSP cutter for B's sector BSP and A's polygon + DOUBLEbspcutter3D bcCutter(bpoA, *itoscB->osc_BSPTree.bt_pbnRoot); + // optimize all parts of the polygon + DOUBLEbspedge3D::OptimizeBSPEdges(bcCutter.bc_abedInside); + DOUBLEbspedge3D::OptimizeBSPEdges(bcCutter.bc_abedBorderInside); + DOUBLEbspedge3D::OptimizeBSPEdges(bcCutter.bc_abedBorderOutside); + DOUBLEbspedge3D::OptimizeBSPEdges(bcCutter.bc_abedOutside); + + // add all parts that are inside according to _inside_ action + AddEdgeArrayAccordingToAction(bcCutter.bc_abedInside, csgaInside); + + // add all parts that are on border inside according to _on_border_inside_ action + AddEdgeArrayAccordingToAction(bcCutter.bc_abedBorderInside, csgaBorderInside); + + // add all parts that are on border outside according to _on_border_outside_ action + AddEdgeArrayAccordingToAction(bcCutter.bc_abedBorderOutside, csgaBorderOutside); + + // clear the temporary array + abedRemaining.Clear(); + + // move all parts that are outside or proceeding to the temporary array + abedRemaining.MoveArray(bcCutter.bc_abedOutside); + abedRemaining.MoveArray(oc_abedProceeding); + }} + + // add all parts that are still remaining according to _outside_ action + AddEdgeArrayAccordingToAction(abedRemaining, csgaOutside); + }} + + }} + + obResult.ob_aoscSectors.Unlock(); +} + +/* + * Perform CSG operation -- destroys both operands! + */ +void CObjectCSG::DoCSGOperation( + CObject3D &obResult, + CObject3D &obA, + CObject3D &obB, + struct CSGOperationTable *pcsgotA, + struct CSGOperationTable *pcsgotB) +{ + // remove current contents + obResult.Clear(); + // create indices in operand sectors + obA.CreateSectorIndices(); + obB.CreateSectorIndices(); + // create sector BSP trees in both operands + obA.CreateSectorBSPs(); + obB.CreateSectorBSPs(); + + // get number of sectors in operands + INDEX ctSectorsA = obA.ob_aoscSectors.Count(); + INDEX ctSectorsB = obB.ob_aoscSectors.Count(); + // create as much sectors in result as there is in both operands + obResult.ob_aoscSectors.New(ctSectorsA+ctSectorsB); + + // do splitting of first operand using the second operand BSPs and first table + DoCSGSplitting(obResult, obA, 0, pcsgotA, obB, ctSectorsA); + // do splitting of second operand using the first operand BSPs and second table + if (!oc_bSkipObjectB) { + DoCSGSplitting(obResult, obB, ctSectorsA, pcsgotB, obA, 0); + } +} + +/* + *** CSG operations -- they all destroy both operands! *** + */ + +/* + * Add rooms. + */ +void CObject3D::CSGAddRooms(CObject3D &obA, CObject3D &obB) +{ + // do CSG with 'add rooms' tables + CObjectCSG oc; + oc.DoCSGOperation(*this, obA, obB, &csgotAddRoomsA, &csgotAddRoomsB); +} + +/* + * Add material from object B to object A. (B should have only one + * open sector and no closed sectors) + */ +void CObject3D::CSGAddMaterial(CObject3D &obA, CObject3D &obB) +{ + // do CSG with 'add material' tables + CObjectCSG oc; + oc.DoCSGOperation(*this, obA, obB, &csgotAddMaterialA, &csgotAddMaterialB); +} +void CObject3D::CSGAddMaterialReverse(CObject3D &obA, CObject3D &obB) +{ + // do CSG with 'add material' tables, but with reverse priorities + CObjectCSG oc; + oc.DoCSGOperation(*this, obA, obB, &csgotAddMaterialReverseA, &csgotAddMaterialReverseB); +} + +/* + * Remove material of object B from object A. (B should have only one + * open sector and no closed sectors) + */ +void CObject3D::CSGRemoveMaterial(CObject3D &obA, CObject3D &obB) +{ + // reverse the object B + obB.Inverse(); + + // do CSG with 'add rooms' tables, but with reversed priorities + CObjectCSG oc; + oc.DoCSGOperation(*this, obA, obB, &csgotAddRoomsB, &csgotAddRoomsA); +} + +/* + * Split sectors of object A using object B. (B should have only one + * closed sector and no open sectors) + */ +void CObject3D::CSGSplitSectors(CObject3D &obA, CObject3D &obB) +{ + // do CSG with 'split sectors' tables + CObjectCSG oc; + oc.DoCSGOperation(*this, obA, obB, &csgotSplitSectorsA, &csgotSplitSectorsB); +} + +/* Join sectors of object A with sectors of object B. (both A and B should + have only one sector) */ +void CObject3D::CSGJoinSectors(CObject3D &obA, CObject3D &obB) +{ + // do CSG with 'join sectors' tables + CObjectCSG oc; + oc.DoCSGOperation(*this, obA, obB, &csgotJoinSectorsA, &csgotJoinSectorsB); +} +/* Split polygons of object A with sectors of object B. (both A and B should + have only one sector) */ +void CObject3D::CSGSplitPolygons(CObject3D &obA, CObject3D &obB) +{ + // do CSG with 'split polygons' tables + CObjectCSG oc; + oc.oc_bCSGIngoringEnabled = TRUE; + oc.oc_bSkipObjectB = TRUE; + oc.DoCSGOperation(*this, obA, obB, &csgotSplitPolygonsA, &csgotSplitPolygonsB); +} diff --git a/Sources/Engine/Math/Object3D_IO.cpp b/Sources/Engine/Math/Object3D_IO.cpp new file mode 100644 index 0000000..2fb0311 --- /dev/null +++ b/Sources/Engine/Math/Object3D_IO.cpp @@ -0,0 +1,593 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// If you happen to have the Exploration 3D library (in Engine/exploration3d/), you can enable its features here. +#define USE_E3D 0 + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include + + +#include +#include +#include + +#if USE_E3D +#include +#include +#endif + +#undef W +#undef NONE + +void FillConversionArrays_t(const FLOATmatrix3D &mTransform); +void ClearConversionArrays( void); +void RemapVertices(BOOL bAsOpened); + + +/* + * Intermediate structures used for converting from Exploration 3D data format into O3D + */ +struct ConversionTriangle { + INDEX ct_iVtx[3]; // indices of vertices + INDEX ct_iTVtx[3]; // indices of texture vertices + INDEX ct_iMaterial; // index of material +}; + +struct ConversionMaterial { + ULONG cm_ulTag; // for recognition of material + CTString cm_strName; // material's name + COLOR cm_colColor; // material's color + CDynamicContainer ms_Polygons; // indices of polygons in this material +}; +// conversion arrays +CDynamicContainer acmMaterials; +CStaticArray actTriangles; +CStaticArray avVertices; +CStaticStackArray avDst; +CStaticArray avTextureVertices; +CStaticArray aiRemap; + +///////////////////////////////////////////////////////////////////////////// +// Helper functions + +//-------------------------------------------------------------------------------------------- +class CObjectSectorLock { +private: + CObjectSector *oscl_posc; // ptr to object sector that will do lock/unlock +public: + CObjectSectorLock( CObjectSector *posc); // lock all object sector arrays + ~CObjectSectorLock(); // unlock all object sector arrays +}; + +//-------------------------------------------------------------------------------------------- +/* + * To lock all object 3D dyna arrays one must create an instance of CObject3DLock. + * Locking job is done inside class constructor + */ +CObjectSectorLock::CObjectSectorLock( CObjectSector *posc) { + ASSERT( posc != NULL); + oscl_posc = posc; + posc->LockAll(); +} + +//-------------------------------------------------------------------------------------------- +/* + * Unlocking of all object 3D dynamic arrays will occur automatically when exiting + * current scope (routine). This is done in class destructor + */ +CObjectSectorLock::~CObjectSectorLock() { + oscl_posc->UnlockAll(); +} + +//-------------------------------------------------------------------------------------------- +// function makes Little-Big indian conversion of 4 bytes and returns valid SLONG +inline SLONG ConvertLong( SBYTE *pfm) +{ + UBYTE i; + UBYTE ret_long[ 4]; + + for( i=0; i<4; i++) + ret_long[ i] = *((UBYTE *) pfm + 3 - i); + return( *((SLONG *) ret_long) ); +}; + +//-------------------------------------------------------------------------------------------- +// function makes Little-Big indian conversion of 2 bytes and returns valid WORD +inline INDEX ConvertWord( SBYTE *pfm) +{ + char aret_word[ 2]; + + aret_word[ 0] = *(pfm+1); + aret_word[ 1] = *(pfm+0); + INDEX ret_word = (INDEX) *((SWORD *) aret_word); + return( ret_word); +}; + +//-------------------------------------------------------------------------------------------- +// function makes Little-Big indian conversion of 4 bytes representing float and returns valid float +inline float ConvertFloat( SBYTE *pfm) +{ + UBYTE i; + char float_no[ 4]; + + for( i=0; i<4; i++) + float_no[ i] = *( pfm + 3 - i); + return( *((float *) float_no) ); +}; + +//-------------------------------------------------------------------------------------------- +// function recognizes and loads many 3D file formats, throws char* errors +#if USE_E3D +HINSTANCE _h3dExploration = NULL; +TInitExploration3D _Init3d; +e3_API*_api; +e3_SCENE*_pe3Scene; +e3_OBJECT *_pe3Object; +HWND _hwnd; +BOOL _bBatchLoading = FALSE; +#endif + +// start/end batch loading of 3d objects +void CObject3D::BatchLoading_t(BOOL bOn) +{ +#if USE_E3D + // check for dummy calls + if (!_bBatchLoading==!bOn) { + return; + } + + // if turning on + if (bOn) { + // if exploration library not yet loaded + if( _h3dExploration == NULL) { + // prepare registry + REG_SetString("HKEY_LOCAL_MACHINE\\SOFTWARE\\X Dimension\\SeriousEngine\\Plugins\\LWO\\BreakObject", "0"); + REG_SetString("HKEY_LOCAL_MACHINE\\SOFTWARE\\X Dimension\\SeriousEngine\\Plugins\\LWO\\textures", "1"); + REG_SetString("HKEY_LOCAL_MACHINE\\SOFTWARE\\X Dimension\\SeriousEngine\\Plugins\\LWO\\chkwrap", "1"); + REG_SetString("HKEY_LOCAL_MACHINE\\SOFTWARE\\X Dimension\\SeriousEngine\\Plugins\\LWO\\readUView", "1"); + // load the dll + _h3dExploration = LoadLibrary(EXPLORATION_LIBRRAY); + // if library not opened + if(_h3dExploration == NULL) { + throw("3D Exploration dll not found !"); + } + _Init3d=(TInitExploration3D)GetProcAddress(_h3dExploration,"InitExploration3D"); + CTString strPlugins = _fnmApplicationPath+"Bin\\3DExplorationPlugins"; + e3_INIT init; + memset(&init,0,sizeof(init)); + init.e_size = sizeof(init); + init.e_registry = "Software\\X Dimension\\SeriousEngine"; + init.e_plugins = (char*)(const char*)strPlugins; + if(_Init3d) { + _api=_Init3d(&init); + } else { + throw("Unable to initialize 3D object library"); + } + } + + // if 3dexp window not open yet + if (_hwnd==NULL) { + // obtain window needed for 3D exploration library to work + _hwnd=CreateWindow(EXPLORATION_WINDOW,"Object Loader",0,100,100,100,50,NULL,0,(HINSTANCE) GetModuleHandle( NULL),0); + //ShowWindow(_hwnd, SW_HIDE); + } + + // if turning off + } else { + // if 3dexp window is open + if (_hwnd!=NULL) { + // close it + DestroyWindow(_hwnd); + _hwnd = NULL; + } + } + _bBatchLoading = bOn; +#else + throw("3D Exploration is disabled in this build."); +#endif +} + +void CObject3D::LoadAny3DFormat_t( + const CTFileName &fnmFileName, + const FLOATmatrix3D &mTransform, + enum LoadType ltLoadType/*= LT_NORMAL*/) +{ +#if USE_E3D + BOOL bWasOn = _bBatchLoading; + try { + if (!_bBatchLoading) { + BatchLoading_t(TRUE); + } + // call file load with file's full path name + CTString strFile = _fnmApplicationPath+fnmFileName; + char acFile[MAX_PATH]; + wsprintf(acFile,"%s",strFile); + e3_LoadFile(_hwnd, acFile); + _pe3Scene=e3_GetScene(_hwnd); + // if scene is successefuly loaded + if(_pe3Scene != NULL) + { + _pe3Object = _pe3Scene->GetObject3d( 0); + // use different methods to convert into Object3D + switch( ltLoadType) + { + case LT_NORMAL: + FillConversionArrays_t(mTransform); + ConvertArraysToO3D(); + break; + case LT_OPENED: + FillConversionArrays_t(mTransform); + RemapVertices(TRUE); + ConvertArraysToO3D(); + break; + case LT_UNWRAPPED: + FLOATmatrix3D mOne; + mOne.Diagonal(1.0f); + FillConversionArrays_t(mOne); + if( avTextureVertices.Count() == 0) + { + ThrowF_t("Unable to import mapping from 3D object because it doesn't contain mapping coordinates."); + } + + RemapVertices(FALSE); + ConvertArraysToO3D(); + break; + } + ClearConversionArrays(); + } + else + { + ThrowF_t("Unable to load 3D object: %s", (const char *)fnmFileName); + } + + if (!bWasOn) { + BatchLoading_t(FALSE); + } + } catch (char *) { + if (!bWasOn) { + BatchLoading_t(FALSE); + } + throw; + } +#endif +} + + +/* + * Converts data from Exploration3D format into arrays used for conversion to O3D + */ +void FillConversionArrays_t(const FLOATmatrix3D &mTransform) +{ +#if USE_E3D + // all polygons must be triangles + if(_pe3Object->_facecount != 0) + { + throw("Error: Not all polygons are triangles!"); + } + + // check if we need flipping (if matrix is flipping, polygons need to be flipped) + const FLOATmatrix3D &m = mTransform; + FLOAT fDet = + m(1,1)*(m(2,2)*m(3,3)-m(2,3)*m(3,2))+ + m(1,2)*(m(2,3)*m(3,1)-m(2,1)*m(3,3))+ + m(1,3)*(m(2,1)*m(3,2)-m(2,2)*m(3,1)); + FLOAT bFlipped = fDet<0; + + // ------------ Convert object vertices (coordinates) + INDEX ctVertices = _pe3Object->pointcount; + avVertices.New(ctVertices); + // copy vertices + for( INDEX iVtx=0; iVtxpoints[iVtx])*mTransform; + avVertices[iVtx](1) = -avVertices[iVtx](1); + avVertices[iVtx](3) = -avVertices[iVtx](3); + } + + // ------------ Convert object's mapping vertices (texture vertices) + INDEX ctTextureVertices = _pe3Object->txtcount; + avTextureVertices.New(ctTextureVertices); + // copy texture vertices + for( INDEX iTVtx=0; iTVtxtxtpoints[iTVtx]; + } + + // ------------ Organize triangles as list of surfaces + // allocate triangles + INDEX ctTriangles = _pe3Object->facecount; + actTriangles.New(ctTriangles); + + acmMaterials.Lock(); + + // sort triangles per surfaces + for( INDEX iTriangle=0; iTriangleGetFace( iTriangle); + // copy vertex indices + if (bFlipped) { + ctTriangle.ct_iVtx[0] = pe3Triangle->v[2]; + ctTriangle.ct_iVtx[1] = pe3Triangle->v[1]; + ctTriangle.ct_iVtx[2] = pe3Triangle->v[0]; + } else { + ctTriangle.ct_iVtx[0] = pe3Triangle->v[0]; + ctTriangle.ct_iVtx[1] = pe3Triangle->v[1]; + ctTriangle.ct_iVtx[2] = pe3Triangle->v[2]; + } + // copy texture vertex indices + if (bFlipped) { + ctTriangle.ct_iTVtx[0] = pe3Triangle->t[2]; + ctTriangle.ct_iTVtx[1] = pe3Triangle->t[1]; + ctTriangle.ct_iTVtx[2] = pe3Triangle->t[0]; + } else { + ctTriangle.ct_iTVtx[0] = pe3Triangle->t[0]; + ctTriangle.ct_iTVtx[1] = pe3Triangle->t[1]; + ctTriangle.ct_iTVtx[2] = pe3Triangle->t[2]; + } + + // obtain material + e3_MATERIAL *pe3Mat = pe3Triangle->material; + BOOL bNewMaterial = TRUE; + // attach triangle into one material + for( INDEX iMat=0; iMatcm_ulTag = (ULONG) pe3Mat; + + // ---------- Set material's name + // if not default material + if( pe3Mat != NULL && pe3Mat->name != NULL) + { + acmMaterials[iNewMaterial].cm_strName = CTString(pe3Mat->name); + // get color + COLOR colColor = CLR_CLRF( pe3Mat->GetDiffuse().rgb()); + acmMaterials[iNewMaterial].cm_colColor = colColor; + } + else + { + acmMaterials[iNewMaterial].cm_strName = "Default"; + acmMaterials[iNewMaterial].cm_colColor = C_GRAY; + } + } + } + acmMaterials.Unlock(); +#endif +} + +void ClearConversionArrays( void) +{ + acmMaterials.Clear(); + actTriangles.Clear(); + avVertices.Clear(); + avTextureVertices.Clear(); + aiRemap.Clear(); +} + +void RemapVertices(BOOL bAsOpened) +{ + {INDEX ctSurf = 0; + // fill remap array with indices of vertices in order how they appear per polygons + {FOREACHINDYNAMICCONTAINER(acmMaterials, ConversionMaterial, itcm) + { + _RPT1(_CRT_WARN, "Indices of polygons in surface %d:", ctSurf); + // for each polygon in surface + {FOREACHINDYNAMICCONTAINER(itcm->ms_Polygons, INDEX, itipol) + { + _RPT1(_CRT_WARN, " %d,", *itipol); + }} + _RPT0(_CRT_WARN, "\n"); + ctSurf++; + }} + + _RPT0(_CRT_WARN, "Polygons and their vertex indices:\n"); + for( INDEX ipol=0; ipolms_Polygons, INDEX, itipol) + { + INDEX idxPol = *itipol; + // for each vertex in polygon + for(INDEX iVtx=0; iVtx<3; iVtx++) + { + // get vertex's index + INDEX idxVtx = actTriangles[idxPol].ct_iVtx[iVtx]; + if( aiRemap[idxVtx] == -1) + { + aiRemap[idxVtx] = ctvx; + ctvx++; + } + } + }} + + INDEX ctOld = avDst.Count(); + // allocate new block of vertices used in this surface + FLOAT3D *pavDst = avDst.Push( ctvx); + + // for each polygon in surface + {FOREACHINDYNAMICCONTAINER(itcm->ms_Polygons, INDEX, itipol) + { + INDEX iPol=*itipol; + // for each vertex in polygon + for(INDEX iVtx=0; iVtx<3; iVtx++) + { + // get vertex's index + INDEX idxVtx = actTriangles[iPol].ct_iVtx[iVtx]; + // get remapped index + INDEX iRemap = aiRemap[idxVtx]; + // if cutting object + if( bAsOpened) + { + // copy vertex coordinate + pavDst[ iRemap] = avVertices[idxVtx]; + } + // if creating unwrapped mapping + else + { + // copy texture coordinate + FLOAT3D vMap; + vMap(1) = avTextureVertices[actTriangles[iPol].ct_iTVtx[iVtx]](1); + vMap(2) = -avTextureVertices[actTriangles[iPol].ct_iTVtx[iVtx]](2); + vMap(3) = 0; + pavDst[ iRemap] = vMap; + } + // remap index of polygon vertex + actTriangles[iPol].ct_iVtx[iVtx] = iRemap+ctOld; + } + }} + } + aiRemap.Clear(); + + // replace remapped array of vertices over original one + avVertices.Clear(); + avVertices.New(avDst.Count()); + for( INDEX iVtxNew=0; iVtxNewms_Polygons, INDEX, itipol) + { + _RPT1(_CRT_WARN, " %d,", *itipol); + }} + _RPT0(_CRT_WARN, "\n"); + ctSurf++; + }} + + _RPT0(_CRT_WARN, "Polygons and their vertex indices:\n"); + for( INDEX ipol=0; ipolomt_Color; + + // create and set plane + popl[iTri] = DOUBLEplane3D( *pVtx0, *pVtx1, *pVtx2); + popo[iTri].opo_Plane = &popl[iTri]; + } + acmMaterials.Unlock(); +} diff --git a/Sources/Engine/Math/ObjectSector.cpp b/Sources/Engine/Math/ObjectSector.cpp new file mode 100644 index 0000000..08cee72 --- /dev/null +++ b/Sources/Engine/Math/ObjectSector.cpp @@ -0,0 +1,1935 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +#include +#include +#include + +// define this for full debugging of all algorithms +#define FULL_DEBUG + +// epsilon value used for vertex comparison +//#define VTX_EPSILON (0.015625f) // 1/2^6 ~= 1.5 cm +#define VTX_EPSILON DOUBLE((1.0/65536.0)/16.0*mth_fCSGEpsilon) // 1/2^16 +//#define VTX_EPSILON DOUBLE(0.00390625) // 1/2^8 +// grid for snapping vertices +#define VTX_SNAP (VTX_EPSILON/2.0) + +// epsilon value used for plane comparison +#define PLX_EPSILON (VTX_EPSILON/16.0*mth_fCSGEpsilon) +// grid for snapping planes +#define PLX_SNAP (PLX_EPSILON/2.0) + +// epsilon value used for edge line comparison +//#define EDX_EPSILON (1E-3f) // 1E-3 == 1 mm +//#define EDX_EPSILON (0.015625f) // 1/2^6 ~= 1.5 cm +//#define EDX_EPSILON DOUBLE(1.0/65536.0) // 1/2^16 +#define EDX_EPSILON DOUBLE(0.00390625*mth_fCSGEpsilon) // 1/2^8 + +// use O(nlogn) instead O(n2) algorithms for object optimization +extern INDEX wld_bFastObjectOptimization = 1.0f; +extern FLOAT mth_fCSGEpsilon = 1.0f; + +/* + * Compare two vertices. + */ +inline int CompareVertices(const CObjectVertex &vx0, const CObjectVertex &vx1) +{ + if (vx0(1)-vx1(1) < -VTX_EPSILON) return -1; + else if (vx0(1)-vx1(1) > +VTX_EPSILON) return 1; + else if (vx0(2)-vx1(2) < -VTX_EPSILON) return -1; + else if (vx0(2)-vx1(2) > +VTX_EPSILON) return 1; + else if (vx0(3)-vx1(3) < -VTX_EPSILON) return -1; + else if (vx0(3)-vx1(3) > +VTX_EPSILON) return 1; + else return 0; +} + +/* + * Compare two vertices for quick-sort. + */ +static int qsort_CompareVertices(const void *pvVertex0, const void *pvVertex1) +{ + CObjectVertex &vx0 = **(CObjectVertex **)pvVertex0; + CObjectVertex &vx1 = **(CObjectVertex **)pvVertex1; + return CompareVertices(vx0, vx1); +} + +/* + * Compare two along line vertices. + */ +static INDEX sortvertices_iMaxAxis; +inline int CompareVerticesAlongLine(const CObjectVertex &vx0, const CObjectVertex &vx1) +{ + if (vx0(sortvertices_iMaxAxis)-vx1(sortvertices_iMaxAxis) < -VTX_EPSILON) return -1; + else if (vx0(sortvertices_iMaxAxis)-vx1(sortvertices_iMaxAxis) > +VTX_EPSILON) return +1; + else return 0; +} +/* + * Compare two vertices along a line for quick-sort. + */ +static int qsort_CompareVerticesAlongLine(const void *pvVertex0, const void *pvVertex1) +{ + CObjectVertex &vx0 = **(CObjectVertex **)pvVertex0; + CObjectVertex &vx1 = **(CObjectVertex **)pvVertex1; + return CompareVerticesAlongLine(vx0, vx1); +} +/* + * Compare two vertices along a line for quick-sort - reversely. + */ +static int qsort_CompareVerticesAlongLineReversely(const void *pvVertex0, const void *pvVertex1) +{ + CObjectVertex &vx0 = **(CObjectVertex **)pvVertex0; + CObjectVertex &vx1 = **(CObjectVertex **)pvVertex1; + return -CompareVerticesAlongLine(vx0, vx1); +} + + +/* + * Compare two planes. + */ +inline int ComparePlanes(const CObjectPlane &pl0, const CObjectPlane &pl1) +{ + if (pl0(1)-pl1(1) < -PLX_EPSILON) return -1; + else if (pl0(1)-pl1(1) > +PLX_EPSILON) return +1; + else if (pl0(2)-pl1(2) < -PLX_EPSILON) return -1; + else if (pl0(2)-pl1(2) > +PLX_EPSILON) return +1; + else if (pl0(3)-pl1(3) < -PLX_EPSILON) return -1; + else if (pl0(3)-pl1(3) > +PLX_EPSILON) return +1; + else if (pl0.Distance()-pl1.Distance() < -PLX_EPSILON) return -1; + else if (pl0.Distance()-pl1.Distance() > +PLX_EPSILON) return +1; + else return 0; +} + +/* + * Compare two planes for quick-sort. + */ +static int qsort_ComparePlanes(const void *pvPlane0, const void *pvPlane1) +{ + CObjectPlane &pl0 = **(CObjectPlane **)pvPlane0; + CObjectPlane &pl1 = **(CObjectPlane **)pvPlane1; + return ComparePlanes(pl0, pl1); +} + +/* + * Compare two edges. + */ +inline int CompareEdges(const CObjectEdge &ed0, const CObjectEdge &ed1) +{ + if (ed0.oed_Vertex0ed1.oed_Vertex0) return +1; + else if (ed0.oed_Vertex1ed1.oed_Vertex1) return +1; + else return 0; +} + +/* + * Compare two edges for quick-sort. + */ +static int qsort_CompareEdges(const void *pvEdge0, const void *pvEdge1) +{ + CObjectEdge &ed0 = **(CObjectEdge **)pvEdge0; + CObjectEdge &ed1 = **(CObjectEdge **)pvEdge1; + return CompareEdges(ed0, ed1); +} + +/* + * Compare two edge lines. + */ +inline int CompareEdgeLines(const CEdgeEx &edx0, const CEdgeEx &edx1) +{ + if (edx0.edx_vDirection(1)-edx1.edx_vDirection(1) < -EDX_EPSILON) return -1; + else if (edx0.edx_vDirection(1)-edx1.edx_vDirection(1) > +EDX_EPSILON) return +1; + else if (edx0.edx_vDirection(2)-edx1.edx_vDirection(2) < -EDX_EPSILON) return -1; + else if (edx0.edx_vDirection(2)-edx1.edx_vDirection(2) > +EDX_EPSILON) return +1; + else if (edx0.edx_vDirection(3)-edx1.edx_vDirection(3) < -EDX_EPSILON) return -1; + else if (edx0.edx_vDirection(3)-edx1.edx_vDirection(3) > +EDX_EPSILON) return +1; + else if (edx0.edx_vReferencePoint(1)-edx1.edx_vReferencePoint(1) < -EDX_EPSILON) return -1; + else if (edx0.edx_vReferencePoint(1)-edx1.edx_vReferencePoint(1) > +EDX_EPSILON) return +1; + else if (edx0.edx_vReferencePoint(2)-edx1.edx_vReferencePoint(2) < -EDX_EPSILON) return -1; + else if (edx0.edx_vReferencePoint(2)-edx1.edx_vReferencePoint(2) > +EDX_EPSILON) return +1; + else if (edx0.edx_vReferencePoint(3)-edx1.edx_vReferencePoint(3) < -EDX_EPSILON) return -1; + else if (edx0.edx_vReferencePoint(3)-edx1.edx_vReferencePoint(3) > +EDX_EPSILON) return +1; + else return 0; +} + +//#define EDX_EPSILON_LOOSE DOUBLE(0.00390625) // 1/2^8 +/* + * Compare two edge lines. + */ +/* +inline int CompareEdgeLines_loosely(const CEdgeEx &edx0, const CEdgeEx &edx1) +{ + if (edx0.edx_vDirection(1)-edx1.edx_vDirection(1) < -EDX_EPSILON_LOOSE) return -1; + else if (edx0.edx_vDirection(1)-edx1.edx_vDirection(1) > +EDX_EPSILON_LOOSE) return +1; + else if (edx0.edx_vDirection(2)-edx1.edx_vDirection(2) < -EDX_EPSILON_LOOSE) return -1; + else if (edx0.edx_vDirection(2)-edx1.edx_vDirection(2) > +EDX_EPSILON_LOOSE) return +1; + else if (edx0.edx_vDirection(3)-edx1.edx_vDirection(3) < -EDX_EPSILON_LOOSE) return -1; + else if (edx0.edx_vDirection(3)-edx1.edx_vDirection(3) > +EDX_EPSILON_LOOSE) return +1; + else if (edx0.edx_vReferencePoint(1)-edx1.edx_vReferencePoint(1) < -EDX_EPSILON_LOOSE) return -1; + else if (edx0.edx_vReferencePoint(1)-edx1.edx_vReferencePoint(1) > +EDX_EPSILON_LOOSE) return +1; + else if (edx0.edx_vReferencePoint(2)-edx1.edx_vReferencePoint(2) < -EDX_EPSILON_LOOSE) return -1; + else if (edx0.edx_vReferencePoint(2)-edx1.edx_vReferencePoint(2) > +EDX_EPSILON_LOOSE) return +1; + else if (edx0.edx_vReferencePoint(3)-edx1.edx_vReferencePoint(3) < -EDX_EPSILON_LOOSE) return -1; + else if (edx0.edx_vReferencePoint(3)-edx1.edx_vReferencePoint(3) > +EDX_EPSILON_LOOSE) return +1; + else return 0; +}*/ + +/* + * Compare two edge lines for quick-sort. + */ +static int qsort_CompareEdgeLines(const void *pvEdgeEx0, const void *pvEdgeEx1) +{ + CEdgeEx &edx0 = **(CEdgeEx **)pvEdgeEx0; + CEdgeEx &edx1 = **(CEdgeEx **)pvEdgeEx1; + return CompareEdgeLines(edx0, edx1); +} + +/* + * Find an edge with given vertices in sorted array of pointers to edges. + */ +BOOL FindEdge( CStaticArray &apedSorted, + CObjectVertex &vx0, CObjectVertex &vx1, + CObjectEdge **ppedResult) +{ + // create a ghost edge with given vertices + CObjectEdge edWanted(vx0, vx1); + CObjectEdge *pedWanted = &edWanted; + + // invoke binary search on the array with ghost edge + CObjectEdge **ppedFound = (CObjectEdge **) bsearch( + &pedWanted, &(apedSorted[0]), apedSorted.Count(), sizeof(CObjectEdge *), + qsort_CompareEdges); + + // if some edge was found + if (ppedFound!=NULL) { + // return it + *ppedResult= *ppedFound; + return TRUE; + // otherwise + } else { + // there is no such edge + return FALSE; + } +} + +/* + * Get start and end vertices. + */ +void CObjectPolygonEdge::GetVertices(CObjectVertex *&povxStart, CObjectVertex *&povxEnd) +{ + ASSERT(ope_Edge!=NULL); + if (ope_Backward) { + povxStart = ope_Edge->oed_Vertex1; + povxEnd = ope_Edge->oed_Vertex0; + } else { + povxStart = ope_Edge->oed_Vertex0; + povxEnd = ope_Edge->oed_Vertex1; + } +} + +/* + * Default constructor. + */ +CObjectSector::CObjectSector(void) : + osc_colAmbient(0), osc_colColor(0), osc_strName("") +{ + osc_ulFlags[0] = 0; + osc_ulFlags[1] = 0; + osc_ulFlags[2] = 0; +} +/* + * Destructor. + */ +CObjectSector::~CObjectSector(void) +{ +} + +/* + * Initialize the structure for the given edge. + */ +inline void CEdgeEx::Initialize(CObjectEdge *poedEdge) +{ + // remember edge + edx_poedEdge = poedEdge; + + // initialize for edge's end vertices + DOUBLE3D vPoint0 = *poedEdge->oed_Vertex0; + DOUBLE3D vPoint1 = *poedEdge->oed_Vertex1; + Initialize(&vPoint0, &vPoint1); +} + +inline void CEdgeEx::Initialize(const DOUBLE3D *pvPoint0, const DOUBLE3D *pvPoint1) +{ + // if the vertices are reversed + if (CompareVertices(*pvPoint0, *pvPoint1)<0) { + // swap them + Swap(pvPoint0, pvPoint1); + // mark edge as reversed + edx_bReverse = TRUE; + + // if the vertices are not reversed + } else { + // mark edge as not reversed + edx_bReverse = FALSE; + } + const DOUBLE3D &vPoint0=*pvPoint0; + const DOUBLE3D &vPoint1=*pvPoint1; + + // normalize the direction + edx_vDirection = (vPoint1-vPoint0).Normalize(); + DOUBLE fDirectionLen = edx_vDirection.Length(); + ASSERT(0.999oed_Vertex0); + } else { + *pplPlane= DOUBLEplane3D( vNormal, *popePolygonEdges[0].ope_Edge->oed_Vertex0); + } + + // set this polygon's plane pointer + opoPolygon.opo_Plane = pplPlane; + // set this polygon's material pointer and color + opoPolygon.opo_Material = &omaMaterial; + opoPolygon.opo_colorColor = omaMaterial.omt_Color; + // set flags + opoPolygon.opo_ulFlags = ulFlags; + + return &opoPolygon; +} + +/* + * Create a new polygon in given sector. + */ +CObjectPolygon *CObjectSector::CreatePolygon(INDEX ctVertices, INDEX aivVertices[], + CObjectMaterial &omaMaterial, ULONG ulFlags, BOOL bReverse) +{ + // create a new polygon in object + CObjectPolygon &opoPolygon = *osc_aopoPolygons.New(); + // create as much polygon edges as there are vertices in the polygon + CObjectPolygonEdge *popePolygonEdges = opoPolygon.opo_PolygonEdges.New(ctVertices); + + // for each vertex + {for (INDEX iVertex=0; iVertexoed_Vertex0); + } else { + *pplPlane= DOUBLEplane3D( vNormal, *popePolygonEdges[0].ope_Edge->oed_Vertex0); + } + + // set this polygon's plane pointer + opoPolygon.opo_Plane = pplPlane; + // set this polygon's material pointer and color + opoPolygon.opo_Material = &omaMaterial; + opoPolygon.opo_colorColor = omaMaterial.omt_Color; + // set flags + opoPolygon.opo_ulFlags = ulFlags; + + return &opoPolygon; +} +/* + * Check the optimization algorithm. + */ +void CObjectSector::CheckOptimizationAlgorithm(void) +{ + // for vertices + FOREACHINDYNAMICARRAY(osc_aovxVertices, CObjectVertex, itvx1) { + FOREACHINDYNAMICARRAY(osc_aovxVertices, CObjectVertex, itvx2) { + CObjectVertex &vx1 = itvx1.Current(); + CObjectVertex &vx2 = itvx2.Current(); + // !!!!why this fails sometimes ?(on spheres) ASSERT( (&vx1 == &vx2) || (CompareVertices(vx1, vx2)!=0) ); + } + } + + // for planes + FOREACHINDYNAMICARRAY(osc_aoplPlanes, CObjectPlane, itpl1) { + FOREACHINDYNAMICARRAY(osc_aoplPlanes, CObjectPlane, itpl2) { + CObjectPlane &pl1 = itpl1.Current(); + CObjectPlane &pl2 = itpl2.Current(); + ASSERT( (&pl1 == &pl2) || (ComparePlanes(pl1, pl2)!=0)); + + } + } + + // for edges + {FOREACHINDYNAMICARRAY(osc_aoedEdges, CObjectEdge, ited1) { + FOREACHINDYNAMICARRAY(osc_aoedEdges, CObjectEdge, ited2) { + CObjectEdge &ed1 = ited1.Current(); + CObjectEdge &ed2 = ited2.Current(); + ASSERT( (&ed1 == &ed2) + || (ed1.oed_Vertex0 != ed2.oed_Vertex0) || (ed1.oed_Vertex1 != ed2.oed_Vertex1) ); + } + }} + + // for inverse edges + INDEX iInversesFound = 0; + {FOREACHINDYNAMICARRAY(osc_aoedEdges, CObjectEdge, ited1) { + FOREACHINDYNAMICARRAY(osc_aoedEdges, CObjectEdge, ited2) { + CObjectEdge &ed1 = ited1.Current(); + CObjectEdge &ed2 = ited2.Current(); + if (&ed1 == &ed2) continue; + BOOL inv1, inv2; + inv1 = (&ed1 == ed2.optimize.oed_InverseEdge); + inv2 = (&ed2 == ed1.optimize.oed_InverseEdge); + // check against cross linked inverses + ASSERT(!(inv1&&inv2)); + if (inv1) { + iInversesFound++; + } + // check against inverses that have not been found + ASSERT( (inv1 || inv2) || (ed1.oed_Vertex0 != ed2.oed_Vertex1) || (ed1.oed_Vertex1 != ed2.oed_Vertex0) ); + } + }} + + // for each polygon + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + // for each edge in polygon + {FOREACHINDYNAMICARRAY(itopo->opo_PolygonEdges, CObjectPolygonEdge, itope) { + CObjectEdge &oedThis = *itope->ope_Edge; + CObjectVertex *povxStartThis, *povxEndThis; + // get start and end vertices + itope->GetVertices(povxStartThis, povxEndThis); + // if start vertex is not on the plane + DOUBLE fDistance = itopo->opo_Plane->PointDistance(*povxStartThis); + if (Abs(fDistance)>(VTX_EPSILON*16.0)) { + // report it + _RPT4(_CRT_WARN, "(%f, %f, %f) is 1/%f from plane ", + (*povxStartThis)(1), + (*povxStartThis)(2), + (*povxStartThis)(3), + 1.0/fDistance); + _RPT4(_CRT_WARN, "(%f, %f, %f):%f\n", + (*itopo->opo_Plane)(1), + (*itopo->opo_Plane)(2), + (*itopo->opo_Plane)(3), + itopo->opo_Plane->Distance()); + } + }} + }} +} + +BOOL CObjectSector::ArePolygonsPlanar(void) +{ + // for each polygon + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + // for each edge in polygon + {FOREACHINDYNAMICARRAY(itopo->opo_PolygonEdges, CObjectPolygonEdge, itope) { + CObjectEdge &oedThis = *itope->ope_Edge; + CObjectVertex *povxStartThis, *povxEndThis; + // get start and end vertices + itope->GetVertices(povxStartThis, povxEndThis); + // if start vertex is not on the plane + DOUBLE fDistance = itopo->opo_Plane->PointDistance(*povxStartThis); + if (Abs(fDistance)>(VTX_EPSILON*16.0)) { + return FALSE; + } + }} + }} + return TRUE; +} + +/* + * Remap different planes with same coordinates to use only one of each. + */ +void CObjectSector::RemapClonedPlanes(void) +{ + // if there are no planes in the sector + if (osc_aoplPlanes.Count()==0) { + // do nothing (optimization algorithms assume at least one plane present) + return; + } + + osc_aoplPlanes.Lock(); + + /* Prepare sorted array for remapping planes. */ + + // create an array of pointers for sorting planes + INDEX ctPlanes = osc_aoplPlanes.Count(); + CStaticArray applSortedPlanes; + applSortedPlanes.New(ctPlanes); + // for all vertices + for(INDEX iPlane=0; iPlaneopl_Remap = applSortedPlanes[iSortedPlane]->opl_Remap; + } + } + + } else { + // for all pairs of planes + {for(INDEX iPlane1=0; iPlane1opo_Plane = itopo->opo_Plane->opl_Remap; + }} + + osc_aoplPlanes.Unlock(); +} + +/* + * Remap different vertices with same coordinates to use only one of each. + */ +static BOOL bBug=FALSE; +void CObjectSector::RemapClonedVertices(void) +{ + // if there are no vertices in the sector + if (osc_aovxVertices.Count()==0) { + // do nothing (optimization algorithms assume at least one vertex present) + return; + } + + osc_aovxVertices.Lock(); + + /* Prepare sorted array for remapping vertices. */ + + // create an array of pointers for sorting vertices + INDEX ctVertices = osc_aovxVertices.Count(); + CStaticArray apvxSortedVertices; + apvxSortedVertices.New(ctVertices); + // for all vertices + for(INDEX iVertex=0; iVertexovx_Remap = apvxSortedVertices[iSortedVertex]->ovx_Remap; + + // otherwise + } else { + #ifndef NDEBUG + // check that it is really ok + CObjectVertex &vx1 = *apvxSortedVertices[iSortedVertex]; + CObjectVertex &vx2 = *apvxSortedVertices[iSortedVertex+1]; + ASSERT( (&vx1 == &vx2) || (CompareVertices(vx1, vx2)!=0)); + #endif + } + } + } else { + // for all pairs of vertices + {for(INDEX iVertex1=0; iVertex1oed_Vertex0 = ited->oed_Vertex0->ovx_Remap; + ited->oed_Vertex1 = ited->oed_Vertex1->ovx_Remap; + }} + + osc_aovxVertices.Unlock(); + +#if 0 +#ifndef NDEBUG + if (bBug) goto skipbug; + // for vertices + {FOREACHINDYNAMICARRAY(osc_aovxVertices, CObjectVertex, itvx1) { + FOREACHINDYNAMICARRAY(osc_aovxVertices, CObjectVertex, itvx2) { + CObjectVertex &vx1 = *(itvx1->ovx_Remap); + CObjectVertex &vx2 = *(itvx2->ovx_Remap); + //ASSERT( (&vx1 == &vx2) || (CompareVertices(vx1, vx2)!=0)); + if (!( (&vx1 == &vx2) || (CompareVertices(vx1, vx2)!=0))) { + goto bug; + } + } + }} + goto skipbug; +bug: + bBug = TRUE; + + // for all vertices in sorted array, except the last one + {for(INDEX iSortedVertex=0; iSortedVertexovx_Tag = FALSE; + }} + + // mark all vertices that are used by some edge + {FOREACHINDYNAMICARRAY(osc_aoedEdges, CObjectEdge, ited) { + ited->oed_Vertex0->ovx_Tag = TRUE; + ited->oed_Vertex1->ovx_Tag = TRUE; + }} + + // find number of used vertices + INDEX ctUsedVertices = 0; + {FOREACHINDYNAMICARRAY(osc_aovxVertices, CObjectVertex, itovx) { + if (itovx->ovx_Tag) { + ctUsedVertices++; + } + }} + + // create a new array with as much vertices as we have counted in last pass + CDynamicArray aovxNew; + CObjectVertex *povxUsed = aovxNew.New(ctUsedVertices); + + // for each vertex + {FOREACHINDYNAMICARRAY(osc_aovxVertices, CObjectVertex, itovx) { + // if it is used + if (itovx->ovx_Tag) { + // copy it to new array + *povxUsed = itovx.Current(); + // set its remap pointer into new array + itovx->ovx_Remap = povxUsed; + povxUsed++; + // if it is not used + } else { + // clear its remap pointer (for debugging) + #ifndef NDEBUG + itovx->ovx_Remap = NULL; + #endif + } + }} + + // for all edges in object + {FOREACHINDYNAMICARRAY(osc_aoedEdges, CObjectEdge, ited) { + // remap vertex pointers + ited->oed_Vertex0 = ited->oed_Vertex0->ovx_Remap; + ited->oed_Vertex1 = ited->oed_Vertex1->ovx_Remap; + }} + + // use new array of vertices instead of the old one + osc_aovxVertices.Clear(); + osc_aovxVertices.MoveArray(aovxNew); +} + +/* + * Remove edges that are not used by any polygon. + */ +void CObjectSector::RemoveUnusedEdges(void) +{ + // if there are no edges in the sector + if (osc_aoedEdges.Count()==0) { + // do nothing (optimization algorithms assume at least one edge present) + return; + } + + // clear all edge tags + {FOREACHINDYNAMICARRAY(osc_aoedEdges, CObjectEdge, itoed) { + itoed->oed_Tag = FALSE; + }} + + // mark all edges that are used by some polygon + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + {FOREACHINDYNAMICARRAY(itopo->opo_PolygonEdges, CObjectPolygonEdge, itope) { + itope->ope_Edge->oed_Tag = TRUE; + }} + }} + + // find number of used edges + INDEX ctUsedEdges = 0; + {FOREACHINDYNAMICARRAY(osc_aoedEdges, CObjectEdge, itoed) { + if (itoed->oed_Tag) { + ctUsedEdges++; + } + }} + + // create a new array with as much edges as we have counted in last pass + CDynamicArray aoedNew; + CObjectEdge *poedUsed = aoedNew.New(ctUsedEdges); + + // for each edge + {FOREACHINDYNAMICARRAY(osc_aoedEdges, CObjectEdge, itoed) { + // if it is used + if (itoed->oed_Tag) { + // copy it to new array + *poedUsed = itoed.Current(); + // set its remap pointer into new array + itoed->optimize.oed_Remap = poedUsed; + poedUsed++; + // if it is not used + } else { + // clear its remap pointer (for debugging) + #ifndef NDEBUG + itoed->optimize.oed_Remap = NULL; + #endif + } + }} + + // remap edge pointers in all polygons + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + {FOREACHINDYNAMICARRAY(itopo->opo_PolygonEdges, CObjectPolygonEdge, itope) { + itope->ope_Edge = itope->ope_Edge->optimize.oed_Remap; + }} + }} + + // use new array of edges instead the old one + osc_aoedEdges.Clear(); + osc_aoedEdges.MoveArray(aoedNew); +} + +/* + * Remove planes that are not used by any polygon. + */ +void CObjectSector::RemoveUnusedPlanes(void) +{ + // if there are no planes in the sector + if (osc_aoplPlanes.Count()==0) { + // do nothing (optimization algorithms assume at least one plane present) + return; + } + + // clear all plane tags + {FOREACHINDYNAMICARRAY(osc_aoplPlanes, CObjectPlane, itopl) { + itopl->opl_Tag = FALSE; + }} + + // mark all planes that are used by some polygon + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + itopo->opo_Plane->opl_Tag = TRUE; + }} + + // find number of used planes + INDEX ctUsedPlanes = 0; + {FOREACHINDYNAMICARRAY(osc_aoplPlanes, CObjectPlane, itopl) { + if (itopl->opl_Tag) { + ctUsedPlanes++; + } + }} + + // create a new array with as much planes as we have counted in last pass + CDynamicArray aoplNew; + CObjectPlane *poplUsed = aoplNew.New(ctUsedPlanes); + + // for each plane + {FOREACHINDYNAMICARRAY(osc_aoplPlanes, CObjectPlane, itopl) { + // if it is used + if (itopl->opl_Tag) { + // copy it to new array + *poplUsed = itopl.Current(); + // set its remap pointer into new array + itopl->opl_Remap = poplUsed; + poplUsed++; + // if it is not used + } else { + // clear its remap pointer (for debugging) + #ifndef NDEBUG + itopl->opl_Remap = NULL; + #endif + } + }} + + // remap plane pointers in all polygons + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + itopo->opo_Plane = itopo->opo_Plane->opl_Remap; + }} + + // use new array of planes instead the old one + osc_aoplPlanes.Clear(); + osc_aoplPlanes.MoveArray(aoplNew); +} + +/* + * Split an edge with a run of vertices. + * NOTE: 'sortvertices_iMaxAxis' must be set correctly! + */ +void CObjectSector::SplitEdgeWithVertices(CObjectEdge &oedOriginal, + CStaticArray &apvxVertices) +{ + CObjectVertex *pvx0 = oedOriginal.oed_Vertex0; + CObjectVertex *pvx1 = oedOriginal.oed_Vertex1; + BOOL bReversed; + + // edge must have length + ASSERT(CompareVertices(*pvx0, *pvx1)!=0); + + // if the edge is going in the direction of the run + if (CompareVerticesAlongLine(*pvx0, *pvx1)<0) { + // mark that it is not reversed + bReversed = FALSE; + + // if the edge is going in opposite direction of the run + } else { + // swap vertices + Swap(pvx0, pvx1); + // mark that it is reversed + bReversed = TRUE; + } + + // init the edge as remap pointer + oedOriginal.colinear1.oed_FirstChild = NULL; + + INDEX iVertex; // current vertex in run + // skip until start vertex is found + for (iVertex=0; apvxVertices[iVertex]!=pvx0; iVertex++) { + NOTHING; + } + + // for all vertices after start vertex and stopping with end vertex + for (iVertex++; apvxVertices[iVertex-1]!=pvx1; iVertex++) { + // if vertex is not same as last one + if (apvxVertices[iVertex]!=apvxVertices[iVertex-1]) { + // create a new edge between the two vertices + CObjectEdge *poedNewChild = osc_aoedEdges.New(); + if (bReversed) { + *poedNewChild = CObjectEdge(*apvxVertices[iVertex], *apvxVertices[iVertex-1]); + } else { + *poedNewChild = CObjectEdge(*apvxVertices[iVertex-1], *apvxVertices[iVertex]); + } + ASSERT(CompareVertices(*poedNewChild->oed_Vertex0, *poedNewChild->oed_Vertex1)!=0); + // link it as a child of this edge + poedNewChild->colinear1.oed_NextSibling = oedOriginal.colinear1.oed_FirstChild; + oedOriginal.colinear1.oed_FirstChild = poedNewChild; + } + } +} + +/* + * Join polygon edges that are collinear are continuing. + */ +void CObjectSector::JoinContinuingPolygonEdges(void) +{ + osc_aoedEdges.Lock(); + + // create array of extended edge infosd + CStaticArray aedxEdgeLines; + CStaticArray apedxSortedEdgeLines; + INDEX ctEdges = osc_aoedEdges.Count(); + CreateEdgeLines(aedxEdgeLines, apedxSortedEdgeLines, ctEdges); + /* NOTE: The array doesn't have to be sorted because only + edges in one polygon are considered. + */ + // for each polygon + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + // join continuing edges in it + itopo->JoinContinuingEdges(osc_aoedEdges); + }} + + osc_aoedEdges.Unlock(); +} +/* + * Join polygon edges that are collinear and continuing. + */ +/* + * NOTE: Edge line infos must be prepared before calling this. + */ +void CObjectPolygon::JoinContinuingEdges(CDynamicArray &oedEdges) +{ + // create an empty array for newly created edges + CDynamicArray aopeNew; + // set the counter of edges to current number of edges + INDEX ctEdges = opo_PolygonEdges.Count(); + + // for each edge + {FOREACHINDYNAMICARRAY(opo_PolygonEdges, CObjectPolygonEdge, itope) { + CObjectEdge &oedThis = *itope->ope_Edge; + + // if not already marked for removal + if (&oedThis != NULL) { + CObjectVertex *povxStartThis, *povxEndThis; + // get start and end vertices + itope->GetVertices(povxStartThis, povxEndThis); + // mark the original edge for removal + itope->ope_Edge = NULL; + + BOOL bChangeDone; // termination condition flag + // repeat + do { + // mark that nothing is changed + bChangeDone = FALSE; + + // for each edge + {FOREACHINDYNAMICARRAY(opo_PolygonEdges, CObjectPolygonEdge, itope2) { + CObjectEdge &oedOther = *itope2->ope_Edge; + + // if not already marked for removal + if (&oedOther != NULL) { + // if the two edges are collinear + if ( CompareEdgeLines(*oedThis.colinear2.oed_pedxLine, *oedOther.colinear2.oed_pedxLine)==0) { + CObjectVertex *povxStartOther, *povxEndOther; + // get start and end vertices + itope2->GetVertices(povxStartOther, povxEndOther); + + // if the other edge is continuing to this one + if ( povxStartOther == povxEndThis ) { + // extend the current edge by it + povxEndThis = povxEndOther; + // mark it for removal + itope2->ope_Edge = NULL; + // mark that a change is done + bChangeDone = TRUE; + + // if the other edge is continued by this one + } else if ( povxStartThis == povxEndOther) { + // extend the current edge by it + povxStartThis = povxStartOther; + // mark it for removal + itope2->ope_Edge = NULL; + // mark that a change is done + bChangeDone = TRUE; + } + } + } + }} + + // until a pass is made without making any change + } while (bChangeDone); + + // create new edge with given start and end vertices + CObjectEdge *poedNew = oedEdges.New(); + *poedNew = CObjectEdge(*povxStartThis, *povxEndThis); + // add it to new array + *aopeNew.New() = CObjectPolygonEdge(poedNew); + } + }} + + // replace old array with the new one + opo_PolygonEdges.Clear(); + opo_PolygonEdges.MoveArray(aopeNew); +} + +/* + * Split a run of collinear edges. + */ +void CObjectSector::SplitCollinearEdgesRun(CStaticArray &apedxSortedEdgeLines, + INDEX iFirstInRun, INDEX iLastInRun) +{ + if (iFirstInRun>iLastInRun) { + return; // this should not happen, but anyway! + } + CEdgeEx &edxLine = *apedxSortedEdgeLines[iFirstInRun]; // representative line of the run + + /* set up array of vertex pointers */ +/* + // for each vertex in sector + INDEX ctVerticesOnLine=0; + {FOREACHINDYNAMICARRAY(osc_aovxVertices, CObjectVertex, itovx) { + // if it is on the line + if (edxLine.PointIsOnLine(*itovx)) { + // mark it as on the line + itovx->ovx_Tag = TRUE; + ctVerticesOnLine++; + + // if it is on the line + } else { + // mark it as on not the line + itovx->ovx_Tag = FALSE; + } + }} + // for all edges in run + {for(INDEX iEdgeInRun=iFirstInRun; iEdgeInRun<=iLastInRun; iEdgeInRun++) { + CObjectEdge &oed = *apedxSortedEdgeLines[iEdgeInRun]->edx_poedEdge; + // if first vertex is not marked + if (!oed.oed_Vertex0->ovx_Tag) { + // mark it + oed.oed_Vertex0->ovx_Tag = TRUE; + ctVerticesOnLine++; + } + // if second vertex is not marked + if (!oed.oed_Vertex1->ovx_Tag) { + // mark it + oed.oed_Vertex1->ovx_Tag = TRUE; + ctVerticesOnLine++; + } + }} + + // if there are no vertices + if (ctVerticesOnLine==0) { + // do nothing + return; + } + + // create array of vertex pointers + CStaticArray apvxSortedVertices; + apvxSortedVertices.New(ctVerticesOnLine); + + // for each vertex in sector + INDEX iVertexOnLine=0; + {FOREACHINDYNAMICARRAY(osc_aovxVertices, CObjectVertex, itovx) { + // if it is marked + if (itovx->ovx_Tag) { + // set its pointer in the array + apvxSortedVertices[iVertexOnLine++] = &*itovx; + } + }} + ASSERT(iVertexOnLine == ctVerticesOnLine); + */ + + // create array of vertex pointers + INDEX ctVerticesOnLine = (iLastInRun-iFirstInRun+1)*2; + // if there are no vertices + if (ctVerticesOnLine==0) { + // do nothing + return; + } + CStaticArray apvxSortedVertices; + apvxSortedVertices.New(ctVerticesOnLine); + // for all edges in run + {for(INDEX iEdgeInRun=iFirstInRun; iEdgeInRun<=iLastInRun; iEdgeInRun++) { + CObjectEdge &oed = *apedxSortedEdgeLines[iEdgeInRun]->edx_poedEdge; + // set vertex pointers + apvxSortedVertices[(iEdgeInRun-iFirstInRun)*2] = oed.oed_Vertex0; + apvxSortedVertices[(iEdgeInRun-iFirstInRun)*2+1] = oed.oed_Vertex1; + }} + + /* sort the array of vertex pointers */ + + // get axis direction from any edge in the run + DOUBLE3D vDirection = apedxSortedEdgeLines[iFirstInRun]->edx_vDirection; + // find largest axis of direction vector + INDEX iMaxAxis = 0; + DOUBLE fMaxAxis = 0.0f; + for (INDEX iAxis=1; iAxis<=3; iAxis++) { + if ( Abs(vDirection(iAxis)) > Abs(fMaxAxis) ) { + fMaxAxis = vDirection(iAxis); + iMaxAxis = iAxis; + } + } + + // set axis for sorting + sortvertices_iMaxAxis = iMaxAxis; + DOUBLE fMaxAxisSign = Sgn(fMaxAxis); + ASSERT(Abs(fMaxAxisSign) > +VTX_EPSILON); + + // if axis is positive + if (fMaxAxisSign > +VTX_EPSILON) { + // sort vertex pointers along the line + if (ctVerticesOnLine>0) { + qsort(&apvxSortedVertices[0], ctVerticesOnLine, sizeof(CObjectVertex *), + qsort_CompareVerticesAlongLine); + } + + // if axis is negative + } else if (fMaxAxisSign < -VTX_EPSILON) { + // sort vertex pointers along the line reversely + if (ctVerticesOnLine>0) { + qsort(&apvxSortedVertices[0], ctVerticesOnLine, sizeof(CObjectVertex *), + qsort_CompareVerticesAlongLine); + //qsort_CompareVerticesAlongLineReversely); ? + } + } + + /* split each edge in turn */ + + // for all edges in run + {for(INDEX iEdgeInRun=iFirstInRun; iEdgeInRun<=iLastInRun; iEdgeInRun++) { + CObjectEdge &oed = *apedxSortedEdgeLines[iEdgeInRun]->edx_poedEdge; + // split the edge with the vertices + SplitEdgeWithVertices(oed, apvxSortedVertices); + }} +} + +/* + * Create array of extended edge infos. + */ +void CObjectSector::CreateEdgeLines(CStaticArray &aedxEdgeLines, + CStaticArray &apedxSortedEdgeLines, INDEX &ctEdges) +{ + // create array of extended edge infos + ctEdges = osc_aoedEdges.Count(); + aedxEdgeLines.New(ctEdges); + // create array of pointers to extended edge infos for sorting edges + apedxSortedEdgeLines.New(ctEdges); + // for all edges + for(INDEX iEdge=0; iEdge aedxEdgeLines; + CStaticArray apedxSortedEdgeLines; + INDEX ctEdges = osc_aoedEdges.Count(); + CreateEdgeLines(aedxEdgeLines, apedxSortedEdgeLines, ctEdges); + // sort the array of pointers, so that collinear edges get next to each other + if (ctEdges>0) { + qsort(&apedxSortedEdgeLines[0], ctEdges, sizeof(CEdgeEx *), qsort_CompareEdgeLines); + } + + /* Create remapping pointers. */ + + // for all edges in normal sorted array, starting at second one + INDEX iFirstInLine = 0; + for(INDEX iSortedEdge=1; iSortedEdgeopo_PolygonEdges, CObjectPolygonEdge, itope) { + // count all children + for (CObjectEdge *poed = itope->ope_Edge->colinear1.oed_FirstChild; + poed!=NULL; + poed = poed->colinear1.oed_NextSibling) { + ctNewEdges++; + } + }} + // create a new array of edge references + CDynamicArray aopoNewPolygonEdges; + if (ctNewEdges>0) { + aopoNewPolygonEdges.New(ctNewEdges); + } + aopoNewPolygonEdges.Lock(); + + /* set the array */ + + // for all of its edge pointers + INDEX iChildEdge = 0; + {FOREACHINDYNAMICARRAY(itpo2->opo_PolygonEdges, CObjectPolygonEdge, itope) { + + // for all of its children + for (CObjectEdge *poed = itope->ope_Edge->colinear1.oed_FirstChild; + poed!=NULL; + poed = poed->colinear1.oed_NextSibling) { + // set the child polygon edge + aopoNewPolygonEdges[iChildEdge] = CObjectPolygonEdge(poed, itope->ope_Backward); + iChildEdge++; + } + }} + + /* replace old array with the new one */ + aopoNewPolygonEdges.Unlock(); + itpo2->opo_PolygonEdges.Clear(); + itpo2->opo_PolygonEdges.MoveArray(aopoNewPolygonEdges); + }} + + osc_aoedEdges.Unlock(); +} + +/* + * Remove polygon edges that are used twice from all polygons. + */ +void CObjectSector::RemoveRedundantPolygonEdges(void) +{ + // for each polygon + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + // remove redundant edges from it + itopo->RemoveRedundantEdges(); + }} +} + +/* + * Remove polygon edges that are used twice from a polygon. + */ +/* + * We will use ope_Edge set to NULL for marking an edge for removal. + */ +void CObjectPolygon::RemoveRedundantEdges(void) +{ + // set the counter of edges to current number of edges + INDEX ctEdges = opo_PolygonEdges.Count(); + + // for each edge + {FOREACHINDYNAMICARRAY(opo_PolygonEdges, CObjectPolygonEdge, itope) { + + // if not already marked for removal + if (itope->ope_Edge != NULL) { + + // for each edge + {FOREACHINDYNAMICARRAY(opo_PolygonEdges, CObjectPolygonEdge, itope2) { + // if it uses same edge in opposite direction + if (itope2->ope_Edge == itope->ope_Edge + && itope2->ope_Backward != itope->ope_Backward ) { + // mark them both for removal + itope2->ope_Edge = NULL; + itope->ope_Edge = NULL; + // mark that there are two edges less + ctEdges -= 2; + // don't test this edge any more + break; + } + }} + } + }} + // remove polygon edges that are mark as unused + RemoveMarkedEdges(ctEdges); +} + +/* + * Remove polygon edges that are marked as unused (oed_Edge==NULL) from polygon. + */ +void CObjectPolygon::RemoveMarkedEdges(INDEX ctEdges) +{ + // create a new array of edge references + CDynamicArray aoedNewPolygonEdges; + if (ctEdges>0) { + aoedNewPolygonEdges.New(ctEdges); + } + aoedNewPolygonEdges.Lock(); + + // for each edge + INDEX iNewEdge = 0; + {FOREACHINDYNAMICARRAY(opo_PolygonEdges, CObjectPolygonEdge, itope) { + + // if it is not marked for removal + if (itope->ope_Edge != NULL) { + // copy it + aoedNewPolygonEdges[iNewEdge++] = itope.Current(); + } + }} + + // replace old array with the new one + aoedNewPolygonEdges.Unlock(); + opo_PolygonEdges.Clear(); + opo_PolygonEdges.MoveArray(aoedNewPolygonEdges); +} + +/* + * Remove polygon edges that have zero length from a polygon. + */ +void CObjectPolygon::RemoveDummyEdgeReferences(void) +{ + INDEX ctUsedEdges = opo_PolygonEdges.Count(); + // for all edges in polygon + {FOREACHINDYNAMICARRAY(opo_PolygonEdges, CObjectPolygonEdge, itope) { + // if it has zero length + if (itope->ope_Edge->oed_Vertex0 == itope->ope_Edge->oed_Vertex1) { + ASSERT(CompareVertices(*itope->ope_Edge->oed_Vertex0, *itope->ope_Edge->oed_Vertex1)==0); + // mark it for removal + itope->ope_Edge = NULL; + ctUsedEdges--; + } else { + // !!!! why this fails sometimes? ASSERT(CompareVertices(*itope->ope_Edge->oed_Vertex0, *itope->ope_Edge->oed_Vertex1)!=0); + } + }} + + // remove all marked edges from the polygon + RemoveMarkedEdges(ctUsedEdges); +} + +/* + * Find edges that have zero length and remove them from all polygons. + */ +void CObjectSector::RemoveDummyEdgeReferences(void) +{ + // for each polygon + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + // remove zero length edges from it + itopo->RemoveDummyEdgeReferences(); + }} +} + +/* + * Remap different edges with same or reverse vertices to use only one of each. + */ +void CObjectSector::RemapClonedEdges(void) +{ + // if there are no edges in the sector + if (osc_aoedEdges.Count()==0) { + // do nothing + return; + } + + osc_aoedEdges.Lock(); + + /* Prepare sorted arrays for remapping edges. */ + + // create array of pointers for sorting edges + INDEX ctEdges = osc_aoedEdges.Count(); + CStaticArray apedSortedEdges; + apedSortedEdges.New(ctEdges); + // for all edges + for(INDEX iEdge=0; iEdgeoptimize.oed_Remap = apedSortedEdges[iSortedEdge]->optimize.oed_Remap; + } + } + + /* Create inverse pointers. */ + + // for all edges in sorted array + for(INDEX iNormalEdge=0; iNormalEdgeoptimize.oed_Remap; + // if the inverse edge pointer is less than this pointer + if (&edInverse < &edNormal) { + // the inverse edge must not be remapped + ASSERT(&edInverse == edInverse.optimize.oed_Remap); + // set the inverse pointer in this edge to the inverse edge + edNormal.optimize.oed_InverseEdge = &edInverse; + } + } + } + } + +#ifndef NDEBUG + // for all edges in object + {FOREACHINDYNAMICARRAY(osc_aoedEdges, CObjectEdge, ited) { + CObjectEdge &edInverse = *ited->optimize.oed_InverseEdge; + // check that no remapped edges have been marked as inverses + ASSERT( &edInverse==NULL || edInverse.optimize.oed_Remap == &edInverse ); + }} +#endif // NDEBUG + + /* Remap all references to edges. */ + + // for all polygons in object + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itpo2) { + // for all of its edge pointers + FOREACHINDYNAMICARRAY(itpo2->opo_PolygonEdges, CObjectPolygonEdge, itope) { + // get the remapped edge pointer + CObjectEdge *pedNew= itope->ope_Edge->optimize.oed_Remap; + + // if has an inverse edge + if (pedNew->optimize.oed_InverseEdge!=NULL) { + // use the inverse edge + pedNew = pedNew->optimize.oed_InverseEdge; + // mark that the direction has changed + itope->ope_Backward = !itope->ope_Backward; + } + + // use the edge + itope->ope_Edge = pedNew; + } + }} + + osc_aoedEdges.Unlock(); +} + +/* + * Remove unused polygons and polygons with less than 3 edges. + */ +void CObjectSector::RemoveDummyPolygons(void) +{ + // for each polygon + INDEX ctUsedPolygons = 0; + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + // if it has more than 2 edges + if(itopo->opo_PolygonEdges.Count()>2) { + // mark it as used + itopo->opo_Tag = TRUE; + // count it + ctUsedPolygons++; + + // if it has less than 3 edges + } else { + // mark it as unused + itopo->opo_Tag = FALSE; + } + }} + + // create a new array of polygons + CDynamicArray aopoNew; + CObjectPolygon *popoNew = aopoNew.New(ctUsedPolygons); + + // for each polygon in sector + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + // if it is used + if (itopo->opo_Tag) { + // add it to the new array + *popoNew++ = itopo.Current(); + } + }} + // replace old array with the new one + osc_aopoPolygons.Clear(); + osc_aopoPolygons.MoveArray(aopoNew); +} + +/* + * Remove unused and replicated elements. + */ +void CObjectSector::Optimize(void) +{ + /* + // for each vertex + {FOREACHINDYNAMICARRAY(osc_aovxVertices, CObjectVertex, itovx) { + // snap the vertex coordinates + Snap((*itovx)(1), VTX_SNAP); + Snap((*itovx)(2), VTX_SNAP); + Snap((*itovx)(3), VTX_SNAP); + }} + // for each plane + {FOREACHINDYNAMICARRAY(osc_aoplPlanes, CObjectPlane, itopl) { + // snap the plane coordinates + Snap((*itopl)(1), PLX_SNAP); + Snap((*itopl)(2), PLX_SNAP); + Snap((*itopl)(3), PLX_SNAP); + Snap((*itopl).Distance(), PLX_SNAP); + }} + */ + + // remove polygons with less than 3 edges + RemoveDummyPolygons(); + + // remap different vertices with same coordinates + RemapClonedVertices(); + // remove unused vertices + RemoveUnusedVertices(); + + // find edges that have zero length and remove them from all polygons + RemoveDummyEdgeReferences(); + // remap different edges with same or reverse vertices + RemapClonedEdges(); + // remove unused edges + RemoveUnusedEdges(); + + // find collinear edges and cross split them with each other + SplitCollinearEdges(); + // find edges that are used twice in same polygon and remove them from the polygon + RemoveRedundantPolygonEdges(); + // find edges that are collinear and continuing in some polygon and join them + JoinContinuingPolygonEdges(); + + // find edges that have zero length and remove them from all polygons + RemoveDummyEdgeReferences(); + // remap different edges with same or reverse vertices + RemapClonedEdges(); + // remove unused edges + RemoveUnusedEdges(); + // remove unused vertices + RemoveUnusedVertices(); + + // find collinear edges and cross split them with each other + SplitCollinearEdges(); + // find edges that have zero length and remove them from all polygons + RemoveDummyEdgeReferences(); + // remap different edges with same or reverse vertices + RemapClonedEdges(); + + // remove unused edges + RemoveUnusedEdges(); + // remove unused vertices + RemoveUnusedVertices(); + + // find edges that are used twice in same polygon and remove them from the polygon + RemoveRedundantPolygonEdges(); + + // remap different planes with same coordinates + RemapClonedPlanes(); + // remove unused planes + RemoveUnusedPlanes(); + // remove polygons with less than 3 edges + RemoveDummyPolygons(); + + #ifndef NDEBUG + // check the optimization algorithm + CheckOptimizationAlgorithm(); + #endif +} + +/* + * Assignment operator. + */ +CObjectSector &CObjectSector::operator=(CObjectSector &oscOriginal) +{ + // remove current contents + Clear(); + + // copy basic properties + osc_colColor = oscOriginal.osc_colColor; + osc_colAmbient = oscOriginal.osc_colAmbient; + osc_ulFlags[0] = oscOriginal.osc_ulFlags[0]; + osc_ulFlags[1] = oscOriginal.osc_ulFlags[1]; + osc_ulFlags[2] = oscOriginal.osc_ulFlags[2]; + osc_strName = oscOriginal.osc_strName; + + // create indices in original sector + oscOriginal.CreateIndices(); + + // copy arrays of elements from original sector + osc_aovxVertices = oscOriginal.osc_aovxVertices; + osc_aoplPlanes = oscOriginal.osc_aoplPlanes; + osc_aomtMaterials = oscOriginal.osc_aomtMaterials; + osc_aoedEdges = oscOriginal.osc_aoedEdges; + osc_aopoPolygons = oscOriginal.osc_aopoPolygons; + + // lock all arrays + LockAll(); + + // for all edges + FOREACHINDYNAMICARRAY(osc_aoedEdges, CObjectEdge, itoed) { + // use vertices in this object with same index + itoed->oed_Vertex0 = &osc_aovxVertices[itoed->oed_Vertex0->ovx_Index]; + itoed->oed_Vertex1 = &osc_aovxVertices[itoed->oed_Vertex1->ovx_Index]; + } + + // for all polygons + FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + // use plane and material in this sector with same indices + itopo->opo_Plane = &osc_aoplPlanes[itopo->opo_Plane->opl_Index]; + if (itopo->opo_Material!=NULL) { + itopo->opo_Material = &osc_aomtMaterials[itopo->opo_Material->omt_Index]; + } + // for all polygon-edges in this polygon + FOREACHINDYNAMICARRAY(itopo->opo_PolygonEdges, CObjectPolygonEdge, itope) { + // use edge in this sector with same index + itope->ope_Edge = &osc_aoedEdges[itope->ope_Edge->oed_Index]; + } + } + + // unlock all arrays + UnlockAll(); + + return *this; +} + +/* + * Find bounding box of the sector. + */ +void CObjectSector::GetBoundingBox(DOUBLEaabbox3D &boxSector) +{ + // clear the bounding box + boxSector = DOUBLEaabbox3D(); + // for each vertex in the sector + FOREACHINDYNAMICARRAY(osc_aovxVertices, CObjectVertex, itovx) { + // add the vertex to the bounding box + boxSector |= *itovx; + } +} + +/* + * Create BSP tree for sector. + */ +void CObjectSector::CreateBSP(void) +{ + /* prepare array of bsp polygons */ + + // get count of polygons in sector + const INDEX ctPolygons = osc_aopoPolygons.Count(); + // create array of BSP polygons + CDynamicArray arbpo; + // create as much BSP polygons as there are polygons in this sector + arbpo.New(ctPolygons); + arbpo.Lock(); + osc_aopoPolygons.Lock(); + + // for each polygon in this sector + for(INDEX iPolygon=0; iPolygonopo_PolygonEdges, CObjectPolygonEdge, itope) { + // reverse the polygon edge direction + itope->ope_Backward = !itope->ope_Backward; + } + } +} + +/* Recalculate all planes from vertices. (used when stretching vertices) */ +void CObjectSector::RecalculatePlanes(void) +{ + // create a container for empty polygons + CDynamicContainer copoEmpty; + + // for all polygons + {FOREACHINDYNAMICARRAY(osc_aopoPolygons, CObjectPolygon, itopo) { + CObjectPolygon &opo = *itopo; + // clear plane normal + DOUBLE3D vNormal = DOUBLE3D(0.0f,0.0f,0.0f); + + // for all edges in polygon + INDEX ctVertices = opo.opo_PolygonEdges.Count(); + opo.opo_PolygonEdges.Lock(); + {for(INDEX iVertex=0; iVertexoed_Vertex1; + povx1 = ope.ope_Edge->oed_Vertex0; + } else { + povx0 = ope.ope_Edge->oed_Vertex0; + povx1 = ope.ope_Edge->oed_Vertex1; + } + DOUBLE3D vSum = *povx0+*povx1; + DOUBLE3D vDif = *povx0-*povx1; + // add the edge contribution to the normal vector + vNormal(1) += vDif(2)*vSum(3); + vNormal(2) += vDif(3)*vSum(1); + vNormal(3) += vDif(1)*vSum(2); + }} + + // if the polygon area is too small + if (vNormal.Length()<1E-8) { + // mark it for removal + copoEmpty.Add(&opo); + // if the polygon area is ok + } else { + // add one plane to planes array + CObjectPlane *pplPlane = osc_aoplPlanes.New(); + // construct this plane from normal vector and one point + *pplPlane= DOUBLEplane3D(vNormal, *opo.opo_PolygonEdges[0].ope_Edge->oed_Vertex0); + opo.opo_Plane = pplPlane; + } + + opo.opo_PolygonEdges.Unlock(); + }} + + // for all empty polygons + {FOREACHINDYNAMICCONTAINER(copoEmpty, CObjectPolygon, itopoEmpty) { + // delete the polygon from sector + osc_aopoPolygons.Delete(itopoEmpty); + }} +} diff --git a/Sources/Engine/Math/Placement.cpp b/Sources/Engine/Math/Placement.cpp new file mode 100644 index 0000000..13b9309 --- /dev/null +++ b/Sources/Engine/Math/Placement.cpp @@ -0,0 +1,213 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include + +// Stream operations + +CTStream &operator>>(CTStream &strm, CPlacement3D &p3d) +{ + strm.Read_t(&p3d, sizeof(p3d)); + return strm; +} +CTStream &operator<<(CTStream &strm, const CPlacement3D &p3d) +{ + strm.Write_t(&p3d, sizeof(p3d)); + return strm; +} + +///////////////////////////////////////////////////////////////////// +// transformations from between coordinate systems + +/* + * Project this placement from absolute system to coordinate system of another placement. + */ +void CPlacement3D::AbsoluteToRelative(const CPlacement3D &plSystem) +{ + // create a simple projection + CSimpleProjection3D prSimple; + // set the relative system as the viewer + prSimple.ViewerPlacementL() = plSystem; + // set the absolute system as object + prSimple.ObjectPlacementL().pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f); + prSimple.ObjectPlacementL().pl_OrientationAngle = ANGLE3D(0, 0, 0); + // prepare the projection + prSimple.Prepare(); + // project this placement using the projection + prSimple.ProjectPlacement(*this, *this); +} +void CPlacement3D::AbsoluteToRelativeSmooth(const CPlacement3D &plSystem) +{ + // create a simple projection + CSimpleProjection3D prSimple; + // set the relative system as the viewer + prSimple.ViewerPlacementL() = plSystem; + // set the absolute system as object + prSimple.ObjectPlacementL().pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f); + prSimple.ObjectPlacementL().pl_OrientationAngle = ANGLE3D(0, 0, 0); + // prepare the projection + prSimple.Prepare(); + // project this placement using the projection + prSimple.ProjectPlacementSmooth(*this, *this); +} + +/* + * Project this placement from coordinate system of another placement to absolute system. + */ +void CPlacement3D::RelativeToAbsolute(const CPlacement3D &plSystem) +{ + // create a simple projection + CSimpleProjection3D prSimple; + // set the absolute system as the viewer + prSimple.ViewerPlacementL().pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f); + prSimple.ViewerPlacementL().pl_OrientationAngle = ANGLE3D(0, 0, 0); + // set the relative system as object + prSimple.ObjectPlacementL() = plSystem; + // prepare the projection + prSimple.Prepare(); + // project this placement using the projection + prSimple.ProjectPlacement(*this, *this); +} +void CPlacement3D::RelativeToAbsoluteSmooth(const CPlacement3D &plSystem) +{ + // create a simple projection + CSimpleProjection3D prSimple; + // set the absolute system as the viewer + prSimple.ViewerPlacementL().pl_PositionVector = FLOAT3D(0.0f, 0.0f, 0.0f); + prSimple.ViewerPlacementL().pl_OrientationAngle = ANGLE3D(0, 0, 0); + // set the relative system as object + prSimple.ObjectPlacementL() = plSystem; + // prepare the projection + prSimple.Prepare(); + // project this placement using the projection + prSimple.ProjectPlacementSmooth(*this, *this); +} + +/* + * Project this placement from system of one placement to system of another placement. + */ +void CPlacement3D::RelativeToRelative(const CPlacement3D &plSource, + const CPlacement3D &plTarget) +{ + // create a simple projection + CSimpleProjection3D prSimple; + // set the target system as the viewer + prSimple.ViewerPlacementL() = plTarget; + // set the source system as object + prSimple.ObjectPlacementL() = plSource; + // prepare the projection + prSimple.Prepare(); + // project this placement using the projection + prSimple.ProjectPlacement(*this, *this); +} +void CPlacement3D::RelativeToRelativeSmooth(const CPlacement3D &plSource, + const CPlacement3D &plTarget) +{ + // create a simple projection + CSimpleProjection3D prSimple; + // set the target system as the viewer + prSimple.ViewerPlacementL() = plTarget; + // set the source system as object + prSimple.ObjectPlacementL() = plSource; + // prepare the projection + prSimple.Prepare(); + // project this placement using the projection + prSimple.ProjectPlacementSmooth(*this, *this); +} + +/* Make this placement be a linear interpolation between given two placements. */ +void CPlacement3D::Lerp(const CPlacement3D &pl0, const CPlacement3D &pl1, FLOAT fFactor) +{ + // lerp the position + pl_PositionVector(1) = + LerpFLOAT(pl0.pl_PositionVector(1), pl1.pl_PositionVector(1), fFactor); + pl_PositionVector(2) = + LerpFLOAT(pl0.pl_PositionVector(2), pl1.pl_PositionVector(2), fFactor); + pl_PositionVector(3) = + LerpFLOAT(pl0.pl_PositionVector(3), pl1.pl_PositionVector(3), fFactor); + + // lerp the orientation + pl_OrientationAngle(1) = + LerpANGLE(pl0.pl_OrientationAngle(1), pl1.pl_OrientationAngle(1), fFactor); + pl_OrientationAngle(2) = + LerpANGLE(pl0.pl_OrientationAngle(2), pl1.pl_OrientationAngle(2), fFactor); + pl_OrientationAngle(3) = + LerpANGLE(pl0.pl_OrientationAngle(3), pl1.pl_OrientationAngle(3), fFactor); +} + +///////////////////////////////////////////////////////////////////// +// translations and rotations + +/* + * Rotate using trackball method. + */ +void CPlacement3D::Rotate_TrackBall(const ANGLE3D &a3dRotation) +{ + FLOATmatrix3D t3dRotation; // matrix for the rotation angles + FLOATmatrix3D t3dOriginal; // matrix for the original angles + + // create matrices from angles + MakeRotationMatrix(t3dRotation, a3dRotation); + MakeRotationMatrix(t3dOriginal, pl_OrientationAngle); + + // make composed matrix + t3dOriginal = t3dRotation*t3dOriginal; // rotate first by original, then by rotation angles + + // recreate angles from composed matrix + DecomposeRotationMatrix(pl_OrientationAngle, t3dOriginal); +} + +/* + * Rotate using airplane method. + */ +void CPlacement3D::Rotate_Airplane(const ANGLE3D &a3dRotation) +{ + FLOATmatrix3D t3dRotation; // matrix for the rotation angles + FLOATmatrix3D t3dOriginal; // matrix for the original angles + + // create matrices from angles + MakeRotationMatrixFast(t3dRotation, a3dRotation); + MakeRotationMatrixFast(t3dOriginal, pl_OrientationAngle); + + // make composed matrix + t3dOriginal = t3dOriginal*t3dRotation; // rotate first by rotation, then by original angles + + // recreate angles from composed matrix + DecomposeRotationMatrixNoSnap(pl_OrientationAngle, t3dOriginal); +} + +/* + * Rotate using HPB method. + */ +void CPlacement3D::Rotate_HPB(const ANGLE3D &a3dRotation) +{ + // just add the rotation angles to original angles + pl_OrientationAngle += a3dRotation; +} + +/* + * Translate in own coordinate system. + */ +void CPlacement3D::Translate_OwnSystem(const FLOAT3D &f3dRelativeTranslation) +{ + FLOATmatrix3D t3dOwnAngles; // matrix for own angles + + // make matrix from own angles + MakeRotationMatrix(t3dOwnAngles, pl_OrientationAngle); + // make absolute translation from relative by rotating for your own angles + pl_PositionVector += f3dRelativeTranslation*t3dOwnAngles; +} + +/* + * Translate in absolute coordinate system. + */ +void CPlacement3D::Translate_AbsoluteSystem(const FLOAT3D &f3dAbsoluteTranslation) +{ + // just add the translation to the position vector + pl_PositionVector += f3dAbsoluteTranslation; +} diff --git a/Sources/Engine/Math/Placement.h b/Sources/Engine/Math/Placement.h new file mode 100644 index 0000000..0472e2b --- /dev/null +++ b/Sources/Engine/Math/Placement.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PLACEMENT_H +#define SE_INCL_PLACEMENT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* + * Placement of an object in 3D space + */ +class ENGINE_API CPlacement3D { +public: + FLOAT3D pl_PositionVector; // position in space + ANGLE3D pl_OrientationAngle; // angles of orientation +public: + /* Default constructor. */ + inline CPlacement3D(void); + /* Constructor from coordinates and angle. */ + inline CPlacement3D(const FLOAT3D &vPosition, const ANGLE3D &aOrientation); + /* Comparison operator. */ + inline BOOL operator==(const CPlacement3D &plOther) const; + + /* Rotate using trackball method. */ + void Rotate_TrackBall(const ANGLE3D &a3dRotation); + /* Rotate using airplane method. */ + void Rotate_Airplane(const ANGLE3D &a3dRotation); + /* Rotate using HPB method. */ + void Rotate_HPB(const ANGLE3D &a3dRotation); + /* Translate in own coordinate system. */ + void Translate_OwnSystem(const FLOAT3D &f3dRelativeTranslation); + /* Translate in absolute coordinate system. */ + void Translate_AbsoluteSystem(const FLOAT3D &f3dAbsoluteTranslation); + + /* Get the direction vector in the direction of this placement. */ + inline void GetDirectionVector(FLOAT3D &vDirection); + + /* Project this placement from absolute system to coordinate system of another placement. */ + void AbsoluteToRelative(const CPlacement3D &plSystem); + void AbsoluteToRelativeSmooth(const CPlacement3D &plSystem); + /* Project this placement from coordinate system of another placement to absolute system. */ + void RelativeToAbsolute(const CPlacement3D &plSystem); + void RelativeToAbsoluteSmooth(const CPlacement3D &plSystem); + /* Project this placement from system of one placement to system of another placement. */ + void RelativeToRelative(const CPlacement3D &plSource, const CPlacement3D &plTarget); + void RelativeToRelativeSmooth(const CPlacement3D &plSource, const CPlacement3D &plTarget); + + /* Make this placement be a linear interpolation between given two placements. */ + void Lerp(const CPlacement3D &pl0, const CPlacement3D &pl1, FLOAT fFactor); +}; +/* Stream operations */ +ENGINE_API CTStream &operator>>(CTStream &strm, CPlacement3D &p3d); +ENGINE_API CTStream &operator<<(CTStream &strm, const CPlacement3D &p3d); +extern ENGINE_API CPlacement3D _plOrigin; + +/* Default constructor. */ +inline CPlacement3D::CPlacement3D(void) { } +/* Constructor from coordinates and angle. */ +inline CPlacement3D::CPlacement3D(const FLOAT3D &vPosition, const ANGLE3D &aOrientation) + : pl_PositionVector(vPosition) + , pl_OrientationAngle(aOrientation) +{} +/* Comparison operator. */ +inline BOOL CPlacement3D::operator==(const CPlacement3D &plOther) const { + return pl_PositionVector==plOther.pl_PositionVector + && pl_OrientationAngle==plOther.pl_OrientationAngle; +} +/* Get the direction vector in the direction of this placement. */ +inline void CPlacement3D::GetDirectionVector(FLOAT3D &vDirection) +{ + AnglesToDirectionVector(pl_OrientationAngle, vDirection); +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/Plane.h b/Sources/Engine/Math/Plane.h new file mode 100644 index 0000000..d9f309a --- /dev/null +++ b/Sources/Engine/Math/Plane.h @@ -0,0 +1,302 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PLANE_H +#define SE_INCL_PLANE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Template class for plane in space of arbitrary dimensions and arbitrary type of coordinates + */ +template +class Plane : public Vector { // normal vector +public: + Type pl_distance; // distance from point 0 along the normal vector +public: + /* Default constructor. */ + inline Plane(void); + /* Constructor from normal vector and distance. */ + inline Plane(const Vector &normal, const Type distance); + /* Constructor from normal vector and a point on plane. */ + inline Plane(const Vector &normal, const Vector &point); + /* Constructor from 3 points on plane, counter clockwise order. */ + inline Plane(const Vector &point0, const Vector &point1, const Vector &point2); + + /* Reference distance. */ + inline Type &Distance(void); + inline const Type &Distance(void) const; + /* Get a reference point on the plane. */ + inline Vector ReferencePoint(void) const; + /* Get a reference point on the plane, if origin is at given vector. */ + inline Vector ReferencePoint(const Vector &vOrigin) const; + + /* Get distance of point from plane. */ + inline const Type PointDistance(const Vector &point) const; + /* Get missing coordinate value */ + inline void GetCoordinate(const int iIndex, Vector &point) const; + /* Get distance of plane from plane. */ + inline const Type PlaneDistance(const Plane &plOther) const; + /* Project a point to the plane. */ + inline Vector ProjectPoint(const Vector &point) const; + /* Project a direction vector to the plane. */ + inline Vector ProjectDirection(const Vector &direction) const; + /* Get index of the greatest coordinate of normal. */ + inline INDEX GetMaxNormal(void) const; + /* Deproject a point to the plane. */ + inline Vector DeprojectPoint(const Plane &plOther, const Vector &point) const; + /* Deproject a direction vector to the plane. */ + inline Vector DeprojectDirection(const Plane &plOther, const Vector &point) const; + + /* Offset the plane forward for a given distance. */ + inline void Offset(const Type offset); + + /* Mathematical operators. */ + // unary minus (fliping of the plane) + inline Plane operator-(void) const; + // addition of vector (translation of the plane by the vector) + inline Plane operator+(const Vector &vector2) const; + inline Plane &operator+=(const Vector &vector2); + inline Plane operator-(const Vector &vector2) const; + inline Plane &operator-=(const Vector &vector2); + // multiplication by a square matrix (sides swapped -- see implementation for notes) + inline Plane &operator*=(const Matrix &matrix2); + Plane operator*(const Matrix &matrix2) const; +}; + +// inline functions implementation +/* + * Default constructor. + */ +template +inline Plane::Plane(void) {} + +/* + * Constructor from normal vector and distance. + */ +template +inline Plane::Plane(const Vector &normal, const Type distance) + : Vector(normal), + pl_distance(distance) +{ + // normalize normal vector + ((Vector)*this).Normalize(); +} + +/* + * Constructor from normal vector and a point on plane. + */ +template +inline Plane::Plane(const Vector &normal, const Vector &point) + : Vector(normal) +{ + // normalize normal vector + Normalize(); + pl_distance = (*this)%point; // distance = normalized_normal * point (dot product) +} + +/* + * Constructor from 3 points on plane, counter clockwise order. + */ +template +inline Plane::Plane(const Vector &point0, const Vector &point1, const Vector &point2) +{ + // create normal vector of plane + Vector normal = (point2-point1)*(point0-point1); // cross product + // construct plane with normal and one point + *this = Plane(normal, point0); +} + +/* + * Reference distance. + */ +template +inline Type &Plane::Distance(void) { + return pl_distance; +} +template +inline const Type &Plane::Distance(void) const { + return pl_distance; +} + +/* + * Get distance of point from plane. + */ +template +inline const Type Plane::PointDistance(const Vector &point) const +{ + /* Distance of the point from (0,0,0) along the normal vector of the plane + * minus distance of the plane from (0,0,0) along the normal vector of the plane. + */ + return (*this)%point-pl_distance; +} + +/* + * Get missing coordinate + */ +template +inline void Plane::GetCoordinate(const int iIndex, Vector &point) const +{ + Type sum = pl_distance; + for( INDEX i=1; i<=iDimensions; i++) + { + if( i != iIndex) + sum -= (*this)(i) * point(i); + } + point( iIndex) = sum/(*this)( iIndex); +} +/* + * Get distance of plane from plane. + */ +template +inline const Type Plane::PlaneDistance(const Plane &plOther) const +{ + /* Distance of the reference point of ther other plane + */ + return PointDistance(plOther.ReferencePoint()); +} + +/* + * Get a reference point on the plane. + */ +template +inline Vector Plane::ReferencePoint(void) const +{ + // let the reference point be from (0,0,0) along the normal vector + return ((Vector)*this)*pl_distance; +} +/* + * Get a reference point on the plane, if origin is at given vector. + */ +template +inline Vector Plane::ReferencePoint(const Vector &vOrigin) const +{ + // let the reference point be from the origin along the normal vector, + // as far as the origin is away from the plane + return vOrigin-((Vector)*this)*(PointDistance(vOrigin)); +} + +/* + * Project a point to the plane. + */ +template +inline Vector Plane::ProjectPoint(const Vector &point) const +{ + return ReferencePoint(point); +} + +/* + * Project a direction vector on the plane. + */ +template +inline Vector Plane::ProjectDirection(const Vector &direction) const +{ + // projected direction is vector between projected endpoint and projected origin + return ProjectPoint(direction) - ReferencePoint(); +} +template +/* Deproject a point to the plane. */ +inline Vector Plane::DeprojectPoint(const Plane &plOther, const Vector &point) const +{ + Vector &vNormal = (Vector &) *this; + Vector &vNormalOther = (Vector &) plOther; + return point - vNormalOther*( PointDistance(point)/(vNormal%vNormalOther) ); +} +template +/* Deproject a direction vector to the plane. */ +inline Vector Plane::DeprojectDirection(const Plane &plOther, const Vector &point) const +{ + Vector &vNormal = (Vector &) *this; + Vector &vNormalOther = (Vector &) plOther; + return point - vNormalOther*( (point%vNormal)/(vNormal%vNormalOther) ); +} +/* + * Get index of the greatest coordinate of normal. + */ +template +inline INDEX Plane::GetMaxNormal(void) const +{ + INDEX iMax = 1; + Type tMax = Abs((*this)(1)); + for(INDEX i=2; i<=iDimensions; i++) { + if (Abs((*this)(i)) > tMax) { + tMax = Abs((*this)(i)); + iMax = i; + } + } + return iMax; +} + +/* Offset the plane forward for a given distance. */ +template +inline void Plane::Offset(const Type offset) +{ + pl_distance+=offset; +} + +// unary minus (fliping of the plane) +template +inline Plane Plane::operator-(void) const { + return Plane(-(Vector)*this, -pl_distance); +} + +// addition of vector (translation along the vector) +template +inline Plane &Plane::operator+=(const Vector &vector2) { + /* Calculate the length of the projection of the translation vector on the + normal vector of the plane and add it to the plane distance. + */ + pl_distance += (*static_cast *>(this))%vector2; + return *this; +} +template +inline Plane Plane::operator+(const Vector &vector2) const { + return Plane(*this)+=vector2; +} +template +inline Plane &Plane::operator-=(const Vector &vector2) { + /* Calculate the length of the projection of the translation vector on the + normal vector of the plane and add it to the plane distance. + */ + pl_distance -= (*static_cast *>(this))%vector2; + return *this; +} +template +inline Plane Plane::operator-(const Vector &vector2) const { + return Plane(*this)-=vector2; +} + +/* + * Multiplication of a plane by a square matrix. + */ +// NOTE: The matrix should have been on the left side of the vector, but the template syntax +// wouldn't allow that. +template +inline Plane &Plane::operator*=(const Matrix &matrix2) { + (*static_cast *>(this))*=matrix2; + return *this; +} +template +inline Plane Plane::operator*(const Matrix &matrix2) const { + return Plane(*this)*=matrix2; +} + +// helper functions for converting between FLOAT and DOUBLE planes +inline DOUBLEplane3D FLOATtoDOUBLE(const FLOATplane3D &plf) { + return DOUBLEplane3D( + FLOATtoDOUBLE((FLOAT3D&)plf), + FLOATtoDOUBLE(plf.Distance()) + ); +} +inline FLOATplane3D DOUBLEtoFLOAT(const DOUBLEplane3D &pld) { + return FLOATplane3D( + DOUBLEtoFLOAT((DOUBLE3D&)pld), + DOUBLEtoFLOAT(pld.Distance()) + ); +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/Projection.cpp b/Sources/Engine/Math/Projection.cpp new file mode 100644 index 0000000..eca0725 --- /dev/null +++ b/Sources/Engine/Math/Projection.cpp @@ -0,0 +1,30 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +///////////////////////////////////////////////////////////////////// +// CProjection3D +///////////////////////////////////////////////////////////////////// +// Construction / destruction + +/* + * Default constructor. + */ +CProjection3D::CProjection3D(void) { + pr_Prepared = FALSE; + pr_ObjectStretch = FLOAT3D(1.0f, 1.0f, 1.0f); + pr_bFaceForward = FALSE; + pr_bHalfFaceForward = FALSE; + pr_vObjectHandle = FLOAT3D(0.0f, 0.0f, 0.0f); + pr_fDepthBufferNear = 0.0f; + pr_fDepthBufferFar = 1.0f; + pr_NearClipDistance = 0.25f; + pr_FarClipDistance = -9999.0f; // never used by default + pr_bMirror = FALSE; + pr_bWarp = FALSE; + pr_fViewStretch = 1.0f; +} + +CPlacement3D _plOrigin(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); diff --git a/Sources/Engine/Math/Projection.h b/Sources/Engine/Math/Projection.h new file mode 100644 index 0000000..5cd8392 --- /dev/null +++ b/Sources/Engine/Math/Projection.h @@ -0,0 +1,793 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PROJECTION_H +#define SE_INCL_PROJECTION_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include + +/* + * Geometric projection of one 3D space onto another 3D space + */ +class ENGINE_API CProjection3D { +public: +// implementation: + // factors set by user + CPlacement3D pr_ObjectPlacement; // placement of the projected object in absolute space + FLOAT3D pr_vObjectHandle; // handle the projected object in its own space + CPlacement3D pr_ViewerPlacement; // placement of the viewer in absolute space + FLOAT3D pr_vViewerPosition; // viewer position (possibly mirrored) + FLOAT pr_NearClipDistance; // distance of near clipping plane from viewer + FLOAT pr_FarClipDistance; // distance of far clipping plane from viewer + FLOATaabbox2D pr_ScreenBBox; // bounding box of viewing screen + FLOAT pr_AspectRatio; // aspect ratio of viewing screen + FLOAT3D pr_ObjectStretch; // stretching coeficients for target object space + BOOL pr_bFaceForward; // set if object is face-forward + BOOL pr_bHalfFaceForward; // set if object is face-forward, but only on heading + BOOL pr_bMirror; // enable mirror projection + BOOL pr_bWarp; // enable warp clip + FLOATplane3D pr_plMirror; // plane to mirror(warp) about + FLOATplane3D pr_plMirrorView; // mirror(warp) clip plane in view space + FLOAT pr_fViewStretch; // stretch of entire view + + // internal variables + BOOL pr_Prepared; // set if all precalculated variables are prepared + BOOL pr_bInverted; // set if projection is inverted + FLOATmatrix3D pr_RotationMatrix; // matrix for rotating when projecting + FLOATmatrix3D pr_mDirectionRotation; // matrix for rotating direction vectors + FLOATmatrix3D pr_ViewerRotationMatrix; // viewer part of rotation matrix + FLOAT3D pr_TranslationVector; // vector for translating when projecting + FLOAT2D pr_ScreenCenter; // center of viewing screen + + FLOAT pr_fDepthBufferFactor; // correction to 0..1 + FLOAT pr_fDepthBufferMul; // correction to needed range + FLOAT pr_fDepthBufferAdd; + FLOAT pr_fDepthBufferNear; // depth buffer range used + FLOAT pr_fDepthBufferFar; + + // clip planes (in view space) + FLOATplane3D pr_plClipL; + FLOATplane3D pr_plClipR; + FLOATplane3D pr_plClipU; + FLOATplane3D pr_plClipD; + +public: +// interface: + // construction/destruction + /* Default constructor. */ + CProjection3D(void); + + // member referencing + /* Reference object placement. */ + inline CPlacement3D &ObjectPlacementL(void); + inline const CPlacement3D &ObjectPlacementR(void) const; + /* Reference object handle. */ + inline FLOAT3D &ObjectHandleL(void); + inline const FLOAT3D &ObjectHandleR(void) const; + /* Reference viewer placement. */ + inline CPlacement3D &ViewerPlacementL(void); + inline const CPlacement3D &ViewerPlacementR(void) const; + /* Reference clipping distances. */ + inline FLOAT &FrontClipDistanceL(void); // obsolete + inline const FLOAT &FrontClipDistanceR(void) const; // obsolete + inline FLOAT &NearClipDistanceL(void); + inline const FLOAT &NearClipDistanceR(void) const; + inline FLOAT &FarClipDistanceL(void); + inline const FLOAT &FarClipDistanceR(void) const; + /* Reference screen bounding box. */ + inline FLOATaabbox2D &ScreenBBoxL(void); + inline const FLOATaabbox2D &ScreenBBoxR(void) const; + /* Reference screen aspect ratio. */ + inline FLOAT &AspectRatioL(void); + inline const FLOAT &AspectRatioR(void) const; + /* Reference target object stretching. */ + inline FLOAT3D &ObjectStretchL(void); + inline const FLOAT3D &ObjectStretchR(void) const; + /* Reference miror plane. */ + inline FLOATplane3D &MirrorPlaneL(void); + inline const FLOATplane3D &MirrorPlaneR(void) const; + inline void TurnOffMirrorPlane(void); + /* Reference warp plane. */ + inline FLOATplane3D &WarpPlaneL(void); + inline const FLOATplane3D &WarpPlaneR(void) const; + inline void TurnOffWarpPlane(void); + /* Reference target object face-forward flag. */ + inline BOOL &ObjectFaceForwardL(void); + inline const BOOL &ObjectFaceForwardR(void) const; + inline BOOL &ObjectHalfFaceForwardL(void); + inline const BOOL &ObjectHalfFaceForwardR(void) const; + /* Reference corrections for depth buffer factor. */ + inline FLOAT &DepthBufferNearL(void); + inline const FLOAT &DepthBufferNearR(void) const; + inline FLOAT &DepthBufferFarL(void); + inline const FLOAT &DepthBufferFarR(void) const; + /* Reference view stretching. */ + inline FLOAT &ViewStretchL(void); + inline const FLOAT &ViewStretchR(void) const; + + /* Prepare for projecting. */ + virtual void Prepare(void) = 0; + virtual BOOL IsPerspective(void) { return FALSE; }; + + /* Project 3D object point into 3D view space. */ + virtual void ProjectCoordinate(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dViewPoint) const = 0; + /* Get a distance of object point from the viewer. */ + virtual FLOAT GetDistance(const FLOAT3D &v3dObjectPoint) const = 0; + /* Project 3D object direction vector into 3D view space. */ + virtual void ProjectDirection(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dViewPoint) const = 0; + /* Project 3D object axis aligned bounding box into 3D view space. */ + virtual void ProjectAABBox(const FLOATaabbox3D &boxObject, FLOATaabbox3D &boxView) const = 0; + /* Project 3D object point into 3D view space, before clipping. */ + virtual void PreClip(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dTransformedPoint) const = 0; + /* Clip a line. */ + virtual ULONG ClipLine(FLOAT3D &v3dPoint0, FLOAT3D &v3dPoint1) const = 0; + /* Project 3D object point into 3D view space, after clipping. */ + virtual void PostClip(const FLOAT3D &v3dTransformedPoint, FLOAT3D &v3dViewPoint) const = 0; + virtual void PostClip(const FLOAT3D &v3dTransformedPoint, FLOAT fTransformedR, + FLOAT3D &v3dViewPoint, FLOAT &fViewR) const = 0; + /* Test if a sphere in view space is inside view frustum. */ + virtual INDEX TestSphereToFrustum(const FLOAT3D &vViewPoint, FLOAT fRadius) const = 0; + /* Test if an oriented box in view space is inside view frustum. */ + virtual INDEX TestBoxToFrustum(const FLOATobbox3D &boxView) const = 0; + + /* Get placement for a ray through a projected point. */ + virtual void RayThroughPoint(const FLOAT3D &v3dViewPoint, CPlacement3D &plRay) const = 0; + + /* Project 3D object plane into 3D view space. */ + virtual void Project(const FLOATplane3D &p3dObjectPlane, FLOATplane3D &v3dTransformedPlane) const = 0; + /* Check if an object-space plane is visible. */ + virtual BOOL IsObjectPlaneVisible(const FLOATplane3D &p3dObjectPlane) const = 0; + /* Check if a viewer-space plane is visible. */ + virtual BOOL IsViewerPlaneVisible(const FLOATplane3D &p3dViewerPlane) const = 0; + + /* Calculate a mip-factor for a given object. */ + // by its distance from viewer + virtual FLOAT MipFactor(FLOAT fDistance) const = 0; + // general mip-factor for target object + virtual FLOAT MipFactor(void) const = 0; + + /* Calculate plane gradient for a plane in 3D view space. */ + virtual void MakeOoKGradient(const FLOATplane3D &plViewerPlane, CPlanarGradients &pgOoK) const = 0; +}; + +/* + * Perspective projection. + */ +class ENGINE_API CPerspectiveProjection3D : public CProjection3D { +public: +// implementation: + // factors set by user + ANGLE ppr_FOVWidth; // width of field-of-view + FLOAT ppr_fMipRatio; // for mip-factor calculation + + // internal variables + FLOAT2D ppr_PerspectiveRatios; // ratios for perspective projection + + // factors for shadow casting projections + FLOAT ppr_fMetersPerPixel; // meters per pixel on destination plane + FLOAT ppr_fViewerDistance; // distance between viewer and destination plane + FLOATaabbox2D ppr_boxSubScreen; // box-in-box for rendering on subdrawports +public: +// interface: + // constructor + CPerspectiveProjection3D(void); + + // member referencing + /* Reference field of view. */ + inline ANGLE &FOVL(void); + inline const ANGLE &FOVR(void) const; + + /* Prepare for projecting. */ + virtual void Prepare(void); + virtual BOOL IsPerspective(void) { return TRUE; }; + + /* Project 3D object point into 3D view space. */ + void ProjectCoordinate(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dViewPoint) const; + /* Get a distance of object point from the viewer. */ + FLOAT GetDistance(const FLOAT3D &v3dObjectPoint) const; + /* Project 3D object direction vector into 3D view space. */ + void ProjectDirection(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dViewPoint) const; + /* Project 3D object axis aligned bounding box into 3D view space. */ + virtual void ProjectAABBox(const FLOATaabbox3D &boxObject, FLOATaabbox3D &boxView) const; + /* Project 3D object point into 3D view space, before clipping. */ + virtual void PreClip(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dTransformedPoint) const; + /* Clip a line. */ + virtual ULONG ClipLine(FLOAT3D &v3dPoint0, FLOAT3D &v3dPoint1) const; + /* Project 3D object point into 3D view space, after clipping. */ + virtual void PostClip(const FLOAT3D &v3dTransformedPoint, FLOAT3D &v3dViewPoint) const; + virtual void PostClip(const FLOAT3D &v3dTransformedPoint, FLOAT fTransformedR, + FLOAT3D &v3dViewPoint, FLOAT &fViewR) const; + /* Test if a sphere in view space is inside view frustum. */ + INDEX TestSphereToFrustum(const FLOAT3D &vViewPoint, FLOAT fRadius) const; + /* Test if an oriented box in view space is inside view frustum. */ + INDEX TestBoxToFrustum(const FLOATobbox3D &boxView) const; + + /* Calculate plane gradient for a plane in 3D view space. */ + virtual void MakeOoKGradient(const FLOATplane3D &plViewerPlane, CPlanarGradients &pgOoK) const; + + /* Get placement for a ray through a projected point. */ + virtual void RayThroughPoint(const FLOAT3D &v3dViewPoint, CPlacement3D &plRay) const; + + /* Project 3D object plane into 3D view space. */ + virtual void Project(const FLOATplane3D &p3dObjectPlane, FLOATplane3D &v3dTransformedPlane) const; + /* Check if an object-space plane is visible. */ + virtual BOOL IsObjectPlaneVisible(const FLOATplane3D &p3dObjectPlane) const; + /* Check if a viewer-space plane is visible. */ + virtual BOOL IsViewerPlaneVisible(const FLOATplane3D &p3dViewerPlane) const; + + /* Calculate a mip-factor for a given object. */ + // by its distance from viewer + virtual FLOAT MipFactor(FLOAT fDistance) const; + // general mip-factor for target object + virtual FLOAT MipFactor(void) const; +}; + +/* + * Isometric projection. + */ +class ENGINE_API CIsometricProjection3D : public CProjection3D { +public: +// implementation: + // factors set by user + FLOAT ipr_ZoomFactor; // zoom factor + + // internal variables +public: +// implementation: + // member referencing + /* Reference zoom factor. */ + inline FLOAT &ZoomFactorL(void); + inline const FLOAT &ZoomFactorR(void) const; + + /* Prepare for projecting. */ + virtual void Prepare(void); + + /* Project 3D object point into 3D view space. */ + void ProjectCoordinate(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dViewPoint) const; + /* Get a distance of object point from the viewer. */ + FLOAT GetDistance(const FLOAT3D &v3dObjectPoint) const; + /* Project 3D object direction vector into 3D view space. */ + void ProjectDirection(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dViewPoint) const; + /* Project 3D object axis aligned bounding box into 3D view space. */ + virtual void ProjectAABBox(const FLOATaabbox3D &boxObject, FLOATaabbox3D &boxView) const; + /* Project 3D object point into 3D view space, before clipping. */ + virtual void PreClip(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dTransformedPoint) const; + /* Clip a line. */ + virtual ULONG ClipLine(FLOAT3D &v3dPoint0, FLOAT3D &v3dPoint1) const; + /* Project 3D object point into 3D view space, after clipping. */ + virtual void PostClip(const FLOAT3D &v3dTransformedPoint, FLOAT3D &v3dViewPoint) const; + virtual void PostClip(const FLOAT3D &v3dTransformedPoint, FLOAT fTransformedR, + FLOAT3D &v3dViewPoint, FLOAT &fViewR) const; + /* Test if a sphere in view space is inside view frustum. */ + INDEX TestSphereToFrustum(const FLOAT3D &vViewPoint, FLOAT fRadius) const; + /* Test if an oriented box in view space is inside view frustum. */ + INDEX TestBoxToFrustum(const FLOATobbox3D &boxView) const; + + /* Get placement for a ray through a projected point. */ + virtual void RayThroughPoint(const FLOAT3D &v3dViewPoint, CPlacement3D &plRay) const; + + /* Calculate plane gradient for a plane in 3D view space. */ + virtual void MakeOoKGradient(const FLOATplane3D &plViewerPlane, CPlanarGradients &pgOoK) const; + + /* Project 3D object plane into 3D view space. */ + virtual void Project(const FLOATplane3D &p3dObjectPlane, FLOATplane3D &v3dTransformedPlane) const; + /* Check if an object-space plane is visible. */ + virtual BOOL IsObjectPlaneVisible(const FLOATplane3D &p3dObjectPlane) const; + /* Check if a viewer-space plane is visible. */ + virtual BOOL IsViewerPlaneVisible(const FLOATplane3D &p3dViewerPlane) const; + + /* Calculate a mip-factor for a given object. */ + // by its distance from viewer + virtual FLOAT MipFactor(FLOAT fDistance) const; + // general mip-factor for target object + virtual FLOAT MipFactor(void) const; +}; + +/* + * Isometric projection. + */ +class ENGINE_API CParallelProjection3D : public CProjection3D { +public: +// implementation: + // factors set by user + FLOAT2D pr_vStepFactors; // gradient of x and y along z (angle of parallel projection) + FLOAT2D pr_vZoomFactors; // zoom of x and y + + // internal variables + FLOAT3D pr_vViewDirection; // heads in the direction of viewing +public: +// implementation: + /* Prepare for projecting. */ + virtual void Prepare(void); + + /* Project 3D object point into 3D view space. */ + virtual void ProjectCoordinate(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dViewPoint) const; + /* Get a distance of object point from the viewer. */ + virtual FLOAT GetDistance(const FLOAT3D &v3dObjectPoint) const; + /* Project 3D object direction vector into 3D view space. */ + virtual void ProjectDirection(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dViewPoint) const; + /* Project 3D object axis aligned bounding box into 3D view space. */ + virtual void ProjectAABBox(const FLOATaabbox3D &boxObject, FLOATaabbox3D &boxView) const; + /* Project 3D object point into 3D view space, before clipping. */ + virtual void PreClip(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dTransformedPoint) const; + /* Clip a line. */ + virtual ULONG ClipLine(FLOAT3D &v3dPoint0, FLOAT3D &v3dPoint1) const; + /* Project 3D object point into 3D view space, after clipping. */ + virtual void PostClip(const FLOAT3D &v3dTransformedPoint, FLOAT3D &v3dViewPoint) const; + virtual void PostClip(const FLOAT3D &v3dTransformedPoint, FLOAT fTransformedR, + FLOAT3D &v3dViewPoint, FLOAT &fViewR) const; + /* Test if a sphere in view space is inside view frustum. */ + INDEX TestSphereToFrustum(const FLOAT3D &vViewPoint, FLOAT fRadius) const; + /* Test if an oriented box in view space is inside view frustum. */ + INDEX TestBoxToFrustum(const FLOATobbox3D &boxView) const; + + /* Get placement for a ray through a projected point. */ + virtual void RayThroughPoint(const FLOAT3D &v3dViewPoint, CPlacement3D &plRay) const; + + /* Calculate plane gradient for a plane in 3D view space. */ + virtual void MakeOoKGradient(const FLOATplane3D &plViewerPlane, CPlanarGradients &pgOoK) const; + + /* Project 3D object plane into 3D view space. */ + virtual void Project(const FLOATplane3D &p3dObjectPlane, FLOATplane3D &v3dTransformedPlane) const; + /* Check if an object-space plane is visible. */ + virtual BOOL IsObjectPlaneVisible(const FLOATplane3D &p3dObjectPlane) const; + /* Check if a viewer-space plane is visible. */ + virtual BOOL IsViewerPlaneVisible(const FLOATplane3D &p3dViewerPlane) const; + + /* Calculate a mip-factor for a given object. */ + // by its distance from viewer + virtual FLOAT MipFactor(FLOAT fDistance) const; + // general mip-factor for target object + virtual FLOAT MipFactor(void) const; +}; + +/* + * Simple projection. + */ +class ENGINE_API CSimpleProjection3D : public CProjection3D { +public: +// implementation: + // factors set by user + // internal variables +public: +// implementation: + // member referencing + + /* Prepare for projecting. */ + virtual void Prepare(void); + + /* Project 3D object point into 3D view space. */ + void ProjectCoordinate(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dViewPoint) const; + /* Get a distance of object point from the viewer. */ + FLOAT GetDistance(const FLOAT3D &v3dObjectPoint) const; + /* Project 3D object direction vector into 3D view space. */ + void ProjectDirection(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dViewPoint) const; + /* Project 3D object placement into 3D view space. */ + void ProjectPlacement(const CPlacement3D &plObject, CPlacement3D &plView) const; + void ProjectPlacementSmooth(const CPlacement3D &plObject, CPlacement3D &plView) const; + /* Project 3D object axis aligned bounding box into 3D view space. */ + virtual void ProjectAABBox(const FLOATaabbox3D &boxObject, FLOATaabbox3D &boxView) const; + /* Project 3D object point into 3D view space, before clipping. */ + virtual void PreClip(const FLOAT3D &v3dObjectPoint, FLOAT3D &v3dTransformedPoint) const; + /* Clip a line. */ + virtual ULONG ClipLine(FLOAT3D &v3dPoint0, FLOAT3D &v3dPoint1) const; + /* Project 3D object point into 3D view space, after clipping. */ + virtual void PostClip(const FLOAT3D &v3dTransformedPoint, FLOAT3D &v3dViewPoint) const; + virtual void PostClip(const FLOAT3D &v3dTransformedPoint, FLOAT fTransformedR, + FLOAT3D &v3dViewPoint, FLOAT &fViewR) const; + /* Test if a sphere in view space is inside view frustum. */ + INDEX TestSphereToFrustum(const FLOAT3D &vViewPoint, FLOAT fRadius) const; + /* Test if an oriented box in view space is inside view frustum. */ + INDEX TestBoxToFrustum(const FLOATobbox3D &boxView) const; + + /* Get placement for a ray through a projected point. */ + virtual void RayThroughPoint(const FLOAT3D &v3dViewPoint, CPlacement3D &plRay) const; + + /* Calculate plane gradient for a plane in 3D view space. */ + virtual void MakeOoKGradient(const FLOATplane3D &plViewerPlane, CPlanarGradients &pgOoK) const; + + /* Project 3D object plane into 3D view space. */ + virtual void Project(const FLOATplane3D &p3dObjectPlane, FLOATplane3D &v3dTransformedPlane) const; + /* Check if an object-space plane is visible. */ + virtual BOOL IsObjectPlaneVisible(const FLOATplane3D &p3dObjectPlane) const; + /* Check if a viewer-space plane is visible. */ + virtual BOOL IsViewerPlaneVisible(const FLOATplane3D &p3dViewerPlane) const; + + /* Calculate a mip-factor for a given object. */ + // by its distance from viewer + virtual FLOAT MipFactor(FLOAT fDistance) const; + // general mip-factor for target object + virtual FLOAT MipFactor(void) const; +}; + +/* + * Holder for any kind of 3D projection. + */ +class ENGINE_API CAnyProjection3D { +private: + CSimpleProjection3D ap_Simple; + CIsometricProjection3D ap_Isometric; + CPerspectiveProjection3D ap_Perspective; + CParallelProjection3D ap_Parallel; + CProjection3D *ap_CurrentProjection; +public: + /* Default constructor. */ + inline CAnyProjection3D(void) : ap_CurrentProjection(NULL) {}; + /* Copy constructor. */ + inline CAnyProjection3D(const CAnyProjection3D &apOriginal) { operator=(apOriginal);} + /* Start beeing CSimpleProjection3D. */ + inline void BeSimple(void); + /* Test if CSimpleProjection3D. */ + inline BOOL IsSimple(void); + /* Start beeing CIsometricProjection3D. */ + inline void BeIsometric(void); + /* Test if CIsometricProjection3D. */ + inline BOOL IsIsometric(void); + /* Start beeing CPerspectiveProjection3D. */ + inline void BePerspective(void); + /* Test if CPerspectiveProjection3D. */ + inline BOOL IsPerspective(void); + /* Start beeing CParallelProjection3D. */ + inline void BeParallel(void); + /* Test if CParallelProjection3D. */ + inline BOOL IsParallel(void); + /* Reference currently active projection. */ + inline CProjection3D *operator->(void); + /* Get the pointer to currently active projection. */ + inline operator CProjection3D *(void); + + /* Initialize from another any-projection. */ + inline void operator=(const CAnyProjection3D &prAny); + /* Initialize from a simple projection. */ + inline void operator=(const CSimpleProjection3D &prSimple); + /* Initialize from an isometric projection. */ + inline void operator=(const CIsometricProjection3D &prIsometric); + /* Initialize from a perspective projection. */ + inline void operator=(const CPerspectiveProjection3D &prPerspective); + /* Initialize from a parallel projection. */ + inline void operator=(const CParallelProjection3D &prParallel); +}; + + +///////////////////////////////////////////////////////////////////// +// CProjection3D +///////////////////////////////////////////////////////////////////// +// Member referencing functions + +/* + * Reference viewer placement. + */ +ENGINE_API inline CPlacement3D &CProjection3D::ViewerPlacementL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_ViewerPlacement; +} +ENGINE_API inline const CPlacement3D &CProjection3D::ViewerPlacementR(void) const { + return pr_ViewerPlacement; +} + +/* + * Reference object placement. + */ +ENGINE_API inline CPlacement3D &CProjection3D::ObjectPlacementL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_ObjectPlacement; +} +ENGINE_API inline const CPlacement3D &CProjection3D::ObjectPlacementR(void) const { + return pr_ObjectPlacement; +} + +/* Reference object handle. */ +ENGINE_API inline FLOAT3D &CProjection3D::ObjectHandleL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_vObjectHandle; +} +ENGINE_API inline const FLOAT3D &CProjection3D::ObjectHandleR(void) const { + return pr_vObjectHandle; +} + +/* + * Reference front clipping distance. + */ +ENGINE_API inline FLOAT &CProjection3D::FrontClipDistanceL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_NearClipDistance; +} +ENGINE_API inline const FLOAT &CProjection3D::FrontClipDistanceR(void) const { + return pr_NearClipDistance; +} +ENGINE_API inline FLOAT &CProjection3D::NearClipDistanceL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_NearClipDistance; +} +ENGINE_API inline const FLOAT &CProjection3D::NearClipDistanceR(void) const { + return pr_NearClipDistance; +} +ENGINE_API inline FLOAT &CProjection3D::FarClipDistanceL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_FarClipDistance; +} +ENGINE_API inline const FLOAT &CProjection3D::FarClipDistanceR(void) const { + return pr_FarClipDistance; +} + +/* + * Reference screen bounding box. + */ +ENGINE_API inline FLOATaabbox2D &CProjection3D::ScreenBBoxL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_ScreenBBox; +} +ENGINE_API inline const FLOATaabbox2D &CProjection3D::ScreenBBoxR(void) const { + return pr_ScreenBBox; +} + +/* + * Reference screen aspect ratio. + */ +ENGINE_API inline FLOAT &CProjection3D::AspectRatioL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_AspectRatio; +} +ENGINE_API inline const FLOAT &CProjection3D::AspectRatioR(void) const { + return pr_AspectRatio; +} + +/* Reference target object stretching. */ +ENGINE_API inline FLOAT3D &CProjection3D::ObjectStretchL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_ObjectStretch; +} +ENGINE_API inline const FLOAT3D &CProjection3D::ObjectStretchR(void) const { + return pr_ObjectStretch; +} + +/* Reference view stretching. */ +ENGINE_API inline FLOAT &CProjection3D::ViewStretchL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_fViewStretch; +} +ENGINE_API inline const FLOAT &CProjection3D::ViewStretchR(void) const { + return pr_fViewStretch; +} + +/* Reference mirror plane. */ +ENGINE_API inline FLOATplane3D &CProjection3D::MirrorPlaneL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + pr_bMirror = TRUE; + return pr_plMirror; +} +ENGINE_API inline const FLOATplane3D &CProjection3D::MirrorPlaneR(void) const { + return pr_plMirror; +} +inline void CProjection3D::TurnOffMirrorPlane(void) +{ + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + pr_bMirror = FALSE; +} +/* Reference warp plane. */ +ENGINE_API inline FLOATplane3D &CProjection3D::WarpPlaneL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + pr_bWarp = TRUE; + return pr_plMirror; +} +ENGINE_API inline const FLOATplane3D &CProjection3D::WarpPlaneR(void) const { + return pr_plMirror; +} +inline void CProjection3D::TurnOffWarpPlane(void) +{ + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + pr_bWarp = FALSE; +} + +/* + * Reference object face-forward flag. + */ +ENGINE_API inline BOOL &CProjection3D::ObjectFaceForwardL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_bFaceForward; +} +ENGINE_API inline const BOOL &CProjection3D::ObjectFaceForwardR(void) const { + return pr_bFaceForward; +} +ENGINE_API inline BOOL &CProjection3D::ObjectHalfFaceForwardL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_bHalfFaceForward; +} +ENGINE_API inline const BOOL &CProjection3D::ObjectHalfFaceForwardR(void) const { + return pr_bHalfFaceForward; +} + +/* Reference corrections for depth buffer factor. */ +ENGINE_API inline FLOAT &CProjection3D::DepthBufferNearL(void) +{ + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_fDepthBufferNear; +} +ENGINE_API inline const FLOAT &CProjection3D::DepthBufferNearR(void) const { + return pr_fDepthBufferNear; +} +ENGINE_API inline FLOAT &CProjection3D::DepthBufferFarL(void) +{ + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_fDepthBufferFar; +} +ENGINE_API inline const FLOAT &CProjection3D::DepthBufferFarR(void) const { + return pr_fDepthBufferFar; +} + +///////////////////////////////////////////////////////////////////// +// CPerspectiveProjection3D +///////////////////////////////////////////////////////////////////// +// Member referencing functions + +/* + * Reference field of view + */ +ENGINE_API inline ANGLE &CPerspectiveProjection3D::FOVL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return ppr_FOVWidth; +} +ENGINE_API inline const ANGLE &CPerspectiveProjection3D::FOVR(void) const { + return ppr_FOVWidth; +} + +///////////////////////////////////////////////////////////////////// +// CIsometricProjection3D +///////////////////////////////////////////////////////////////////// +// Member referencing functions + +/* + * Reference zoom factor. + */ +ENGINE_API inline FLOAT &CIsometricProjection3D::ZoomFactorL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return ipr_ZoomFactor; +} +ENGINE_API inline const FLOAT &CIsometricProjection3D::ZoomFactorR(void) const { + return ipr_ZoomFactor; +} + +///////////////////////////////////////////////////////////////////// +// CAnyProjection3D +///////////////////////////////////////////////////////////////////// +/* + * Start beeing CSimpleProjection3D. + */ +ENGINE_API inline void CAnyProjection3D::BeSimple(void) +{ + ap_CurrentProjection = &ap_Simple; +} + +/* + * Start beeing CIsometricProjection3D. + */ +ENGINE_API inline void CAnyProjection3D::BeIsometric(void) +{ + ap_CurrentProjection = &ap_Isometric; +} + +/* + * Start beeing CPerspectiveProjection3D. + */ +ENGINE_API inline void CAnyProjection3D::BePerspective(void) +{ + ap_CurrentProjection = &ap_Perspective; +} +/* + * Start beeing CParallelProjection3D. + */ +ENGINE_API inline void CAnyProjection3D::BeParallel(void) +{ + ap_CurrentProjection = &ap_Parallel; +} + +/* Test if CSimpleProjection3D. */ +ENGINE_API inline BOOL CAnyProjection3D::IsSimple(void) { + return ap_CurrentProjection == &ap_Simple; +} +/* Test if CIsometricProjection3D. */ +ENGINE_API inline BOOL CAnyProjection3D::IsIsometric(void) { + return ap_CurrentProjection == &ap_Isometric; +} +/* Test if CPerspectiveProjection3D. */ +ENGINE_API inline BOOL CAnyProjection3D::IsPerspective(void) { + return ap_CurrentProjection == &ap_Perspective; +} +/* Test if CParallelProjection3D. */ +ENGINE_API inline BOOL CAnyProjection3D::IsParallel(void) { + return ap_CurrentProjection == &ap_Parallel; +} + +/* + * Reference currently active projection. + */ +ENGINE_API inline CProjection3D *CAnyProjection3D::operator->(void) +{ + return ap_CurrentProjection; +} + +/* + * Get the pointer to currently active projection. + */ +ENGINE_API inline CAnyProjection3D::operator CProjection3D *(void) +{ + return ap_CurrentProjection; +} + +/* + * Initialize from another any-projection. + */ +ENGINE_API inline void CAnyProjection3D::operator=(const CAnyProjection3D &prAny) +{ + // if the other is perspective + if ((const CProjection3D *)prAny.ap_CurrentProjection == &prAny.ap_Perspective) { + // use perspective + ap_Perspective = prAny.ap_Perspective; + ap_CurrentProjection = &ap_Perspective; + // if the other is parallel + } else if ((const CProjection3D *)prAny.ap_CurrentProjection == &prAny.ap_Parallel) { + // use parallel + ap_Parallel = prAny.ap_Parallel; + ap_CurrentProjection = &ap_Parallel; + // if the other is simple + } else if ((const CProjection3D *)prAny.ap_CurrentProjection == &prAny.ap_Simple) { + // use simple + ap_Simple = prAny.ap_Simple; + ap_CurrentProjection = &ap_Simple; + // if the other is isometric + } else if ((const CProjection3D *)prAny.ap_CurrentProjection == &prAny.ap_Isometric) { + // use isometric + ap_Isometric = prAny.ap_Isometric; + ap_CurrentProjection = &ap_Isometric; + // otherwise + } else { + // error + ASSERTALWAYS("CAnyProjection3D::operator=() : Invalid source object"); + } +}; + +/* + * Initialize from a simple projection. + */ +ENGINE_API inline void CAnyProjection3D::operator=(const CSimpleProjection3D &prSimple) +{ + ap_Simple = prSimple; + ap_CurrentProjection = &ap_Simple; +} + +/* + * Initialize from an isometric projection. + */ +ENGINE_API inline void CAnyProjection3D::operator=(const CIsometricProjection3D &prIsometric) +{ + ap_Isometric = prIsometric; + ap_CurrentProjection = &ap_Isometric; +} + +/* + * Initialize from a perspective projection. + */ +ENGINE_API inline void CAnyProjection3D::operator=(const CPerspectiveProjection3D &prPerspective) +{ + ap_Perspective = prPerspective; + ap_CurrentProjection = &ap_Perspective; +} + +/* + * Initialize from a parallel projection. + */ +ENGINE_API inline void CAnyProjection3D::operator=(const CParallelProjection3D &prParallel) +{ + ap_Parallel = prParallel; + ap_CurrentProjection = &ap_Parallel; +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/Projection_DOUBLE.h b/Sources/Engine/Math/Projection_DOUBLE.h new file mode 100644 index 0000000..5ab31cf --- /dev/null +++ b/Sources/Engine/Math/Projection_DOUBLE.h @@ -0,0 +1,81 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PROJECTION_DOUBLE_H +#define SE_INCL_PROJECTION_DOUBLE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include + +/* + * Geometric projection of one 3D space onto another 3D space + */ +class ENGINE_API CSimpleProjection3D_DOUBLE { +public: + // factors set by user + CPlacement3D pr_ObjectPlacement; // placement of the projected object + CPlacement3D pr_ViewerPlacement; // placement of the viewer + FLOAT3D pr_ObjectStretch; // stretching coeficients for target object space + + // internal variables + BOOL pr_Prepared; // set if all precalculated variables are prepared + DOUBLEmatrix3D pr_RotationMatrix; // matrix for rotating when projecting + DOUBLEmatrix3D pr_ViewerRotationMatrix; // viewer part of rotation matrix + DOUBLE3D pr_TranslationVector; // vector for translating when projecting +public: + // construction/destruction + /* Default constructor. */ + CSimpleProjection3D_DOUBLE(void); + + // member referencing + /* Reference viewer placement. */ + inline CPlacement3D &ViewerPlacementL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_ViewerPlacement; + } + inline const CPlacement3D &ViewerPlacementR(void) const { + return pr_ViewerPlacement; + } + + /* Reference object placement. */ + inline CPlacement3D &ObjectPlacementL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_ObjectPlacement; + } + inline const CPlacement3D &ObjectPlacementR(void) const { + return pr_ObjectPlacement; + } + /* Reference target object stretching. */ + inline FLOAT3D &ObjectStretchL(void) { + IFDEBUG(pr_Prepared = FALSE); // invalidate precalculations on any non-const access + return pr_ObjectStretch; + } + inline const FLOAT3D &ObjectStretchR(void) const { + return pr_ObjectStretch; + } + + /* Prepare for projecting. */ + void Prepare(void); + + /* Project 3D object point into 3D view space. */ + void ProjectCoordinate(const DOUBLE3D &v3dObjectPoint, DOUBLE3D &v3dViewPoint) const; + /* Project 3D object direction vector into 3D view space. */ + void ProjectDirection(const DOUBLE3D &v3dObjectPoint, DOUBLE3D &v3dViewPoint) const; + /* Project 3D object placement into 3D view space. */ + void ProjectPlacement(const CPlacement3D &plObject, CPlacement3D &plView) const; + /* Project 3D object mapping into 3D view space. */ + void ProjectMapping(const CMappingDefinition &mdObject, const DOUBLEplane3D &plObject, + CMappingDefinition &mdView) const; + /* Project 3D object axis aligned bounding box into 3D view space. */ + void ProjectAABBox(const DOUBLEaabbox3D &boxObject, DOUBLEaabbox3D &boxView) const; + /* Project 3D object plane into 3D view space. */ + void Project(const DOUBLEplane3D &p3dObjectPlane, DOUBLEplane3D &v3dTransformedPlane) const; +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/Projection_Isometric.cpp b/Sources/Engine/Math/Projection_Isometric.cpp new file mode 100644 index 0000000..a6a7117 --- /dev/null +++ b/Sources/Engine/Math/Projection_Isometric.cpp @@ -0,0 +1,418 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include + +#include +#include + +///////////////////////////////////////////////////////////////////// +// CIsometricProjection3D + +/* + * Prepare for projecting. + */ +void CIsometricProjection3D::Prepare(void) +{ + FLOATmatrix3D t3dObjectStretch; // matrix for object stretch + FLOATmatrix3D t3dObjectRotation; // matrix for object angles + + // calc. matrices for viewer and object angles and stretch + MakeRotationMatrix(t3dObjectRotation, pr_ObjectPlacement.pl_OrientationAngle); // object normally + MakeInverseRotationMatrix(pr_ViewerRotationMatrix, pr_ViewerPlacement.pl_OrientationAngle); // viewer inverse + t3dObjectStretch.Diagonal(pr_ObjectStretch); + pr_vViewerPosition = pr_ViewerPlacement.pl_PositionVector; + BOOL bXInverted = pr_ObjectStretch(1)<0; + BOOL bYInverted = pr_ObjectStretch(2)<0; + BOOL bZInverted = pr_ObjectStretch(3)<0; + + pr_bInverted = bXInverted!=bYInverted!=bZInverted; + + // if the projection is mirrored + if (pr_bMirror) { + // reflect viewer + ReflectPositionVectorByPlane(pr_plMirror, pr_vViewerPosition); + ReflectRotationMatrixByPlane_rows(pr_plMirror, pr_ViewerRotationMatrix); + // invert inversion + pr_bInverted = !pr_bInverted; + } + + // calculate screen center + pr_ScreenCenter = pr_ScreenBBox.Center(); + + // if the object is face-forward + if (pr_bFaceForward) { + // if it turns only heading + if (pr_bHalfFaceForward) { + // get the y-axis vector of object rotation + FLOAT3D vY(t3dObjectRotation(1,2), t3dObjectRotation(2,2), t3dObjectRotation(3,2)); + // find z axis of viewer + FLOAT3D vViewerZ( + pr_ViewerRotationMatrix(3,1), + pr_ViewerRotationMatrix(3,2), + pr_ViewerRotationMatrix(3,3)); + // calculate x and z axis vectors to make object head towards viewer + FLOAT3D vX = (-vViewerZ)*vY; + vX.Normalize(); + FLOAT3D vZ = vY*vX; + // compose the rotation matrix back from those angles + t3dObjectRotation(1,1) = vX(1); t3dObjectRotation(1,2) = vY(1); t3dObjectRotation(1,3) = vZ(1); + t3dObjectRotation(2,1) = vX(2); t3dObjectRotation(2,2) = vY(2); t3dObjectRotation(2,3) = vZ(2); + t3dObjectRotation(3,1) = vX(3); t3dObjectRotation(3,2) = vY(3); t3dObjectRotation(3,3) = vZ(3); + + // first apply object stretch then object rotation and then viewer rotation + pr_mDirectionRotation = pr_ViewerRotationMatrix*t3dObjectRotation; + pr_RotationMatrix = pr_mDirectionRotation*t3dObjectStretch; + // if it is fully face forward + } else { + // apply object stretch only + pr_mDirectionRotation.Diagonal(1); + pr_RotationMatrix = t3dObjectStretch; + } + } else { + // first apply object stretch then object rotation and then viewer rotation + pr_mDirectionRotation = pr_ViewerRotationMatrix*t3dObjectRotation; + pr_RotationMatrix = pr_mDirectionRotation*t3dObjectStretch; + } + + // make clip planes + MakeClipPlane(FLOAT3D(+ipr_ZoomFactor,0,0), pr_ScreenBBox.Min()(1)-pr_ScreenCenter(1), pr_plClipL); + MakeClipPlane(FLOAT3D(-ipr_ZoomFactor,0,0), pr_ScreenCenter(1)-pr_ScreenBBox.Max()(1), pr_plClipR); + MakeClipPlane(FLOAT3D(0,-ipr_ZoomFactor,0), pr_ScreenBBox.Min()(2)-pr_ScreenCenter(2), pr_plClipU); + MakeClipPlane(FLOAT3D(0,+ipr_ZoomFactor,0), pr_ScreenCenter(2)-pr_ScreenBBox.Max()(2), pr_plClipD); + + // calc. offset of object from viewer + pr_TranslationVector = pr_ObjectPlacement.pl_PositionVector - pr_vViewerPosition; + // rotate offset only by viewer angles + pr_TranslationVector = pr_TranslationVector*pr_ViewerRotationMatrix; + // transform handle from object space to viewer space and add it to the offset + pr_TranslationVector -= pr_vObjectHandle*pr_RotationMatrix; + + // mark as prepared + pr_Prepared = TRUE; + // calculate constant value used for calculating z-buffer k-value from vertex's z coordinate + pr_fDepthBufferFactor = -pr_NearClipDistance; + pr_fDepthBufferMul = (pr_fDepthBufferFar-pr_fDepthBufferNear); + pr_fDepthBufferAdd = pr_fDepthBufferNear; +} + +/* + * Project 3D object point into 3D view space, before clipping. + */ +void CIsometricProjection3D::PreClip(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dTransformedPoint) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // rotate and translate the point + v3dTransformedPoint = v3dObjectPoint*pr_RotationMatrix + pr_TranslationVector; +} + +/* + * Project 3D object point into 3D view space, after clipping. + */ +void CIsometricProjection3D::PostClip( const FLOAT3D &v3dTransformedPoint, + FLOAT3D &v3dViewPoint) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + // multiply X and Y coordinates with zoom factor and add the center of screen + v3dViewPoint(1) = pr_ScreenCenter(1) + v3dTransformedPoint(1) * ipr_ZoomFactor*pr_fViewStretch; + v3dViewPoint(2) = pr_ScreenCenter(2) - v3dTransformedPoint(2) * ipr_ZoomFactor*pr_fViewStretch; +} + + +void CIsometricProjection3D::PostClip( const FLOAT3D &v3dTransformedPoint, FLOAT fTransformedR, + FLOAT3D &v3dViewPoint, FLOAT &fViewR) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + // multiply X and Y coordinates with zoom factor and add the center of screen + v3dViewPoint(1) = pr_ScreenCenter(1) + v3dTransformedPoint(1) * ipr_ZoomFactor*pr_fViewStretch; + v3dViewPoint(2) = pr_ScreenCenter(2) - v3dTransformedPoint(2) * ipr_ZoomFactor*pr_fViewStretch; + fViewR = fTransformedR*ipr_ZoomFactor*pr_fViewStretch; +} + + +/* Test if a sphere in view space is inside view frustum. */ +INDEX CIsometricProjection3D::TestSphereToFrustum(const FLOAT3D &vViewPoint, FLOAT fRadius) const +{ + ASSERT( pr_Prepared && fRadius>=0); + const FLOAT fX = vViewPoint(1); + const FLOAT fY = vViewPoint(2); + const FLOAT fZ = vViewPoint(3); + INDEX iPass = 1; + + // check to near + if( fZ-fRadius>-pr_NearClipDistance) { + return -1; + } else if( fZ+fRadius>-pr_NearClipDistance) { + iPass = 0; + } + // check to far + if( pr_FarClipDistance>0) { + if( fZ+fRadius<-pr_FarClipDistance) { + return -1; + } else if( fZ-fRadius<-pr_FarClipDistance) { + iPass = 0; + } + } + // check to left + FLOAT fL = fX*pr_plClipL(1) - pr_plClipL.Distance(); + if( fL<-fRadius) { + return -1; + } else if( fL0) { + iTest = box.TestAgainstPlane(FLOATplane3D(FLOAT3D(0,0,1), -pr_FarClipDistance)); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + } + // check to left + iTest = box.TestAgainstPlane(pr_plClipL); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // check to right + iTest = box.TestAgainstPlane(pr_plClipR); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // check to up + iTest = box.TestAgainstPlane(pr_plClipU); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // check to down + iTest = box.TestAgainstPlane(pr_plClipD); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // all done + return iPass; +} + +/* + * Project 3D object point into 3D view space. + */ +void CIsometricProjection3D::ProjectCoordinate(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dViewPoint) const +{ + // rotate and translate the point + v3dViewPoint = v3dObjectPoint*pr_RotationMatrix + pr_TranslationVector; + // multiply X and Y coordinates with zoom factor and add the center of screen + v3dViewPoint(1) = pr_ScreenCenter(1) + v3dViewPoint(1) * ipr_ZoomFactor*pr_fViewStretch; + v3dViewPoint(2) = pr_ScreenCenter(2) + v3dViewPoint(2) * ipr_ZoomFactor*pr_fViewStretch; +} + +/* + * Get a distance of object point from the viewer. + */ +FLOAT CIsometricProjection3D::GetDistance(const FLOAT3D &v3dObjectPoint) const +{ + // get just the z coordinate of the point in viewer space + return + v3dObjectPoint(1)*pr_RotationMatrix(3,1)+ + v3dObjectPoint(2)*pr_RotationMatrix(3,2)+ + v3dObjectPoint(3)*pr_RotationMatrix(3,3)+ + pr_TranslationVector(3); +} + +/* + * Project 3D object direction vector into 3D view space. + */ +void CIsometricProjection3D::ProjectDirection(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dViewPoint) const +{ + // rotate the direction + v3dViewPoint = v3dObjectPoint*pr_mDirectionRotation; +} + +/* + * Project 3D object axis aligned bounding box into 3D view space. + */ +void CIsometricProjection3D::ProjectAABBox(const FLOATaabbox3D &boxObject, + FLOATaabbox3D &boxView) const +{ + ASSERTALWAYS( "This is not yet implemented"); +} + +/* + * Project 3D object plane into 3D view space. + */ +void CIsometricProjection3D::Project(const FLOATplane3D &p3dObjectPlane, + FLOATplane3D &p3dTransformedPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // rotate and translate the plane + p3dTransformedPlane = p3dObjectPlane*pr_mDirectionRotation + pr_TranslationVector; +} + +/* Calculate plane gradient for a plane in 3D view space. */ +void CIsometricProjection3D::MakeOoKGradient(const FLOATplane3D &plViewerPlane, CPlanarGradients &pgOoK) const +{ + //ASSERTALWAYS("Function not supported"); +} + +/* + * Clip a line. + */ +ULONG CIsometricProjection3D::ClipLine(FLOAT3D &v3dPoint0, FLOAT3D &v3dPoint1) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // front clip plane is exactly the viewplane + //const FLOATplane3D plFrontClip(FLOAT3D(0.0f,0.0f,-1.0f), 0.0f); + + ULONG ulCode0 = LCFVERTEX0(LCF_UNCLIPPED); + ULONG ulCode1 = LCFVERTEX1(LCF_UNCLIPPED); + + // clip the line by each plane at the time, skip if some removes entire line + if (ClipLineByNearPlane(v3dPoint0, v3dPoint1, 0.0f, ulCode0, ulCode1, LCF_NEAR) + // if something remains + ) { + // return the clip code for both vertices + return ulCode0 | ulCode1; + // if some of the planes removed entire line + } else { + // return the code that tells that entire line is removed + return LCF_EDGEREMOVED; + } +} + +/* + * Get placement for a ray through a projected point. + */ +void CIsometricProjection3D::RayThroughPoint(const FLOAT3D &v3dViewPoint, + CPlacement3D &plRay) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + /* The direction in object space is exactly the viewer direction, while + * the position is back-transformed position of the point from the view plane + * to object space. + */ + + // just copy the orientation angle + plRay.pl_OrientationAngle = pr_ViewerPlacement.pl_OrientationAngle; + + // the point on view plane has a view z coordinate of 0 + FLOAT3D vViewPlanePoint; + vViewPlanePoint(1) = (v3dViewPoint(1)-pr_ScreenCenter(1)) / ipr_ZoomFactor; + vViewPlanePoint(2) = (v3dViewPoint(2)-pr_ScreenCenter(2)) / ipr_ZoomFactor; + vViewPlanePoint(3) = 0.0f; + // back transform the point to get the position vector + plRay.pl_PositionVector = (vViewPlanePoint-pr_TranslationVector)*!pr_RotationMatrix; +} + +/* + * Check if an object-space plane is visible. + */ +BOOL CIsometricProjection3D::IsObjectPlaneVisible(const FLOATplane3D &p3dObjectPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // the object plane is visible is it is not heading away from the view plane + return (p3dObjectPlane*pr_mDirectionRotation)(3)>0.0f; +} + +/* + * Check if a viewer-space plane is visible. + */ +BOOL CIsometricProjection3D::IsViewerPlaneVisible(const FLOATplane3D &p3dViewerPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // the object plane is visible is it is not heading away from the view plane + return p3dViewerPlane(3)>0.01f; +} + +/* + * Calculate a mip-factor for a given object. + */ +// by its distance from viewer +FLOAT CIsometricProjection3D::MipFactor(FLOAT fDistance) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + /* calculated using following formula: + k = log2(1024*z/xratio); + */ + return Log2(1024.0f/ipr_ZoomFactor); +} +// general mip-factor for target object +FLOAT CIsometricProjection3D::MipFactor(void) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + /* calculated using following formula: + k = log2(1024*z/xratio); + */ + return Log2(1024.0f/ipr_ZoomFactor); +} diff --git a/Sources/Engine/Math/Projection_Parallel.cpp b/Sources/Engine/Math/Projection_Parallel.cpp new file mode 100644 index 0000000..3d51a3b --- /dev/null +++ b/Sources/Engine/Math/Projection_Parallel.cpp @@ -0,0 +1,422 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include + +#include +#include + +///////////////////////////////////////////////////////////////////// +// CParallelProjection3D + +/* + * Prepare for projecting. + */ +void CParallelProjection3D::Prepare(void) +{ + FLOATmatrix3D t3dObjectStretch; // matrix for object stretch + FLOATmatrix3D t3dObjectRotation; // matrix for object angles + + // calc. matrices for viewer and object angles and stretch + MakeRotationMatrix(t3dObjectRotation, pr_ObjectPlacement.pl_OrientationAngle); // object normally + MakeInverseRotationMatrix(pr_ViewerRotationMatrix, pr_ViewerPlacement.pl_OrientationAngle); // viewer inverse + t3dObjectStretch.Diagonal(pr_ObjectStretch); + pr_vViewerPosition = pr_ViewerPlacement.pl_PositionVector; + BOOL bXInverted = pr_ObjectStretch(1)<0; + BOOL bYInverted = pr_ObjectStretch(2)<0; + BOOL bZInverted = pr_ObjectStretch(3)<0; + + pr_bInverted = bXInverted!=bYInverted!=bZInverted; + + // if the projection is mirrored + if (pr_bMirror) { + // reflect viewer + ReflectPositionVectorByPlane(pr_plMirror, pr_vViewerPosition); + ReflectRotationMatrixByPlane_rows(pr_plMirror, pr_ViewerRotationMatrix); + // invert inversion + pr_bInverted = !pr_bInverted; + } + + // calculate screen center + pr_ScreenCenter = pr_ScreenBBox.Center(); + + // if the object is face-forward + if (pr_bFaceForward) { + // apply object stretch only + pr_RotationMatrix = t3dObjectStretch; + } else { + // first apply object stretch then object rotation and then viewer rotation + pr_mDirectionRotation = pr_ViewerRotationMatrix*t3dObjectRotation; + pr_RotationMatrix = pr_mDirectionRotation*t3dObjectStretch; + } + + // calc. offset of object from viewer + pr_TranslationVector = pr_ObjectPlacement.pl_PositionVector - pr_vViewerPosition; + // rotate offset only by viewer angles + pr_TranslationVector = pr_TranslationVector*pr_ViewerRotationMatrix; + // transform handle from object space to viewer space and add it to the offset + pr_TranslationVector -= pr_vObjectHandle*pr_RotationMatrix; + + // calculate constant value used for calculating z-buffer k-value from vertex's z coordinate + pr_fDepthBufferFactor = -pr_NearClipDistance; + pr_fDepthBufferMul = (pr_fDepthBufferFar-pr_fDepthBufferNear); + pr_fDepthBufferAdd = pr_fDepthBufferNear; + + // make clip planes + MakeClipPlane(FLOAT3D(+pr_vZoomFactors(1),0,+pr_vStepFactors(1)), pr_ScreenBBox.Min()(1)-pr_ScreenCenter(1), pr_plClipL); + MakeClipPlane(FLOAT3D(-pr_vZoomFactors(1),0,-pr_vStepFactors(1)), pr_ScreenCenter(1)-pr_ScreenBBox.Max()(1), pr_plClipR); + MakeClipPlane(FLOAT3D(0,-pr_vZoomFactors(2),-pr_vStepFactors(2)), pr_ScreenBBox.Min()(2)-pr_ScreenCenter(2), pr_plClipU); + MakeClipPlane(FLOAT3D(0,+pr_vZoomFactors(2),+pr_vStepFactors(2)), pr_ScreenCenter(2)-pr_ScreenBBox.Max()(2), pr_plClipD); + + // find vector in direction of viewing + pr_vViewDirection = FLOAT3D( + pr_vStepFactors(1)/pr_vZoomFactors(1), + pr_vStepFactors(2)/pr_vZoomFactors(2), + -1.0f); + + // mark as prepared + pr_Prepared = TRUE; +} + +/* + * Project 3D object point into 3D view space, before clipping. + */ +void CParallelProjection3D::PreClip(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dTransformedPoint) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // rotate and translate the point + v3dTransformedPoint = v3dObjectPoint*pr_RotationMatrix + pr_TranslationVector; +} + + +/* + * Project 3D object point into 3D view space, after clipping. + */ +void CParallelProjection3D::PostClip( const FLOAT3D &v3dTransformedPoint, + FLOAT3D &v3dViewPoint) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + // multiply X and Y coordinates with zoom factor and add the center of screen + v3dViewPoint(1) = pr_ScreenCenter(1) + + v3dTransformedPoint(1) *pr_vZoomFactors(1) + + v3dTransformedPoint(3) *pr_vStepFactors(1); + v3dViewPoint(2) = pr_ScreenCenter(2) + - v3dTransformedPoint(2) *pr_vZoomFactors(2) + - v3dTransformedPoint(3) *pr_vStepFactors(2); +} + + +void CParallelProjection3D::PostClip( const FLOAT3D &v3dTransformedPoint, FLOAT fTransformedR, + FLOAT3D &v3dViewPoint, FLOAT &fViewR) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + // multiply X and Y coordinates with zoom factor and add the center of screen + v3dViewPoint(1) = pr_ScreenCenter(1) + + v3dTransformedPoint(1) *pr_vZoomFactors(1) + + v3dTransformedPoint(3) *pr_vStepFactors(1); + v3dViewPoint(2) = pr_ScreenCenter(2) + - v3dTransformedPoint(2) *pr_vZoomFactors(2) + - v3dTransformedPoint(3) *pr_vStepFactors(2); + fViewR = fTransformedR *pr_vZoomFactors(1); +} + +/* Test if a sphere in view space is inside view frustum. */ +INDEX CParallelProjection3D::TestSphereToFrustum(const FLOAT3D &vViewPoint, FLOAT fRadius) const +{ + ASSERT(pr_Prepared); + const FLOAT fX = vViewPoint(1); + const FLOAT fY = vViewPoint(2); + const FLOAT fZ = vViewPoint(3); + INDEX iPass = 1; + + // check to near + if( fZ-fRadius>-pr_NearClipDistance) { + return -1; + } else if( fZ+fRadius>-pr_NearClipDistance) { + iPass = 0; + } + // check to far + if( pr_FarClipDistance>0) { + if( fZ+fRadius<-pr_FarClipDistance) { + return -1; + } else if( fZ-fRadius<-pr_FarClipDistance) { + iPass = 0; + } + } + // check to left + FLOAT fL = fX*pr_plClipL(1) + fZ*pr_plClipL(3) - pr_plClipL.Distance(); + if( fL<-fRadius) { + return -1; + } else if( fL0) { + iTest = box.TestAgainstPlane(FLOATplane3D(FLOAT3D(0,0,1), -pr_FarClipDistance)); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + } + // check to left + iTest = box.TestAgainstPlane(pr_plClipL); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // check to right + iTest = box.TestAgainstPlane(pr_plClipR); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // check to up + iTest = box.TestAgainstPlane(pr_plClipU); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // check to down + iTest = box.TestAgainstPlane(pr_plClipD); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // all done + return iPass; +} + + +/* + * Project 3D object point into 3D view space. + */ +void CParallelProjection3D::ProjectCoordinate(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dViewPoint) const +{ + // rotate and translate the point + v3dViewPoint = v3dObjectPoint*pr_RotationMatrix + pr_TranslationVector; + // multiply X and Y coordinates with zoom factor and add the center of screen + v3dViewPoint(1) = + pr_ScreenCenter(1) + +v3dViewPoint(1)*pr_vZoomFactors(1) + +v3dViewPoint(3)*pr_vStepFactors(1); + v3dViewPoint(2) = + pr_ScreenCenter(2) + +v3dViewPoint(2)*pr_vZoomFactors(2) + +v3dViewPoint(3)*pr_vStepFactors(2); +} + +/* + * Get a distance of object point from the viewer. + */ +FLOAT CParallelProjection3D::GetDistance(const FLOAT3D &v3dObjectPoint) const +{ + // get just the z coordinate of the point in viewer space + return + v3dObjectPoint(1)*pr_RotationMatrix(3,1)+ + v3dObjectPoint(2)*pr_RotationMatrix(3,2)+ + v3dObjectPoint(3)*pr_RotationMatrix(3,3)+ + pr_TranslationVector(3); +} + +/* + * Project 3D object direction vector into 3D view space. + */ +void CParallelProjection3D::ProjectDirection(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dViewPoint) const +{ + // rotate the direction + v3dViewPoint = v3dObjectPoint*pr_RotationMatrix; +} + +/* + * Project 3D object axis aligned bounding box into 3D view space. + */ +void CParallelProjection3D::ProjectAABBox(const FLOATaabbox3D &boxObject, + FLOATaabbox3D &boxView) const +{ + ASSERTALWAYS( "This is not yet implemented"); +} + +/* + * Project 3D object plane into 3D view space. + */ +void CParallelProjection3D::Project(const FLOATplane3D &p3dObjectPlane, + FLOATplane3D &p3dTransformedPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // rotate and translate the plane + p3dTransformedPlane = p3dObjectPlane*pr_RotationMatrix + pr_TranslationVector; +} + +/* Calculate plane gradient for a plane in 3D view space. */ +void CParallelProjection3D::MakeOoKGradient(const FLOATplane3D &plViewerPlane, CPlanarGradients &pgOoK) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // ####!!!! use viewer plane or object plane? + + // create k gradients from the plane equation + FLOAT xn = plViewerPlane(1); + FLOAT yn = plViewerPlane(2); + FLOAT zn = plViewerPlane(3); + FLOAT d = plViewerPlane.Distance(); + FLOAT ci = pr_ScreenCenter(1); + FLOAT cj = pr_ScreenCenter(2); + FLOAT fx = pr_vZoomFactors(1); + FLOAT fy = pr_vZoomFactors(2); + FLOAT sx = pr_vStepFactors(1); + FLOAT sy = pr_vStepFactors(2); + + FLOAT Div = zn-sx*xn-sy*yn; + + FLOAT dkodi = xn/(fx*Div); + FLOAT dkodj = yn/(fy*Div); + FLOAT k00 = d/Div-ci*dkodi-cj*dkodj; + + // NOTE: here, k is really used instead ook + pgOoK.pg_f00 = k00; + pgOoK.pg_fDOverDI = dkodi; + pgOoK.pg_fDOverDJ = dkodj; +} +/* + * Clip a line. + */ +ULONG CParallelProjection3D::ClipLine(FLOAT3D &v3dPoint0, FLOAT3D &v3dPoint1) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // front clip plane is exactly the viewplane + //const FLOATplane3D plFrontClip(FLOAT3D(0.0f,0.0f,-1.0f), 0.0f); + + ULONG ulCode0 = LCFVERTEX0(LCF_UNCLIPPED); + ULONG ulCode1 = LCFVERTEX1(LCF_UNCLIPPED); + + // clip the line by each plane at the time, skip if some removes entire line + if (ClipLineByNearPlane(v3dPoint0, v3dPoint1, 0.0f, ulCode0, ulCode1, LCF_NEAR) + // if something remains + ) { + // return the clip code for both vertices + return ulCode0 | ulCode1; + // if some of the planes removed entire line + } else { + // return the code that tells that entire line is removed + return LCF_EDGEREMOVED; + } +} + +/* + * Get placement for a ray through a projected point. + */ +void CParallelProjection3D::RayThroughPoint(const FLOAT3D &v3dViewPoint, + CPlacement3D &plRay) const +{ + ASSERTALWAYS("Function not supported"); +} + +/* + * Check if an object-space plane is visible. + */ +BOOL CParallelProjection3D::IsObjectPlaneVisible(const FLOATplane3D &p3dObjectPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // the object plane is visible if it is not heading away from the view direction + return (p3dObjectPlane*pr_mDirectionRotation)%pr_vViewDirection<0.01f; +} + +/* + * Check if a viewer-space plane is visible. + */ +BOOL CParallelProjection3D::IsViewerPlaneVisible(const FLOATplane3D &p3dViewerPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // the object plane is visible if it is not heading away from the view direction + return p3dViewerPlane%pr_vViewDirection<0.01f; +} + +/* + * Calculate a mip-factor for a given object. + */ +// by its distance from viewer +FLOAT CParallelProjection3D::MipFactor(FLOAT fDistance) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + /* calculated using following formula: + k = log2(1024*z/xratio); + */ + return Log2(1024.0f/pr_vZoomFactors(1)); +} +// general mip-factor for target object +FLOAT CParallelProjection3D::MipFactor(void) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + /* calculated using following formula: + k = log2(1024*z/xratio); + */ + return Log2(1024.0f/pr_vZoomFactors(1)); +} diff --git a/Sources/Engine/Math/Projection_Perspective.cpp b/Sources/Engine/Math/Projection_Perspective.cpp new file mode 100644 index 0000000..3d7528c --- /dev/null +++ b/Sources/Engine/Math/Projection_Perspective.cpp @@ -0,0 +1,581 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include + +#include +#include + +///////////////////////////////////////////////////////////////////// +// CPerspectiveProjection3D + +// constructor +CPerspectiveProjection3D::CPerspectiveProjection3D(void) +{ + ppr_fMetersPerPixel = -1.0f; // never used by default + ppr_fViewerDistance = -1.0f; +} + +/* + * Prepare for projecting. + */ +void CPerspectiveProjection3D::Prepare(void) +{ + FLOATmatrix3D t3dObjectStretch; // matrix for object stretch + FLOATmatrix3D t3dObjectRotation; // matrix for object angles + + // calc. matrices for viewer and object angles and stretch + MakeRotationMatrixFast( + t3dObjectRotation, pr_ObjectPlacement.pl_OrientationAngle); + MakeInverseRotationMatrixFast( + pr_ViewerRotationMatrix, pr_ViewerPlacement.pl_OrientationAngle); + t3dObjectStretch.Diagonal(pr_ObjectStretch); + pr_vViewerPosition = pr_ViewerPlacement.pl_PositionVector; + BOOL bXInverted = pr_ObjectStretch(1)<0; + BOOL bYInverted = pr_ObjectStretch(2)<0; + BOOL bZInverted = pr_ObjectStretch(3)<0; + + pr_bInverted = bXInverted!=bYInverted!=bZInverted; + + // if the projection is mirrored + if (pr_bMirror) { + // reflect viewer + ReflectPositionVectorByPlane(pr_plMirror, pr_vViewerPosition); + ReflectRotationMatrixByPlane_rows(pr_plMirror, pr_ViewerRotationMatrix); + // get mirror plane in view space + pr_plMirrorView = pr_plMirror; + pr_plMirrorView -= pr_vViewerPosition; + pr_plMirrorView *= pr_ViewerRotationMatrix; + // invert inversion + pr_bInverted = !pr_bInverted; + } else if (pr_bWarp) { + // get mirror plane in view space + pr_plMirrorView = pr_plMirror; + } + + // if the object is face-forward + if (pr_bFaceForward) { + // if it turns only heading + if (pr_bHalfFaceForward) { + // get the y-axis vector of object rotation + FLOAT3D vY(t3dObjectRotation(1,2), t3dObjectRotation(2,2), t3dObjectRotation(3,2)); + // find z axis of viewer + FLOAT3D vViewerZ( + pr_ViewerRotationMatrix(3,1), + pr_ViewerRotationMatrix(3,2), + pr_ViewerRotationMatrix(3,3)); + // calculate x and z axis vectors to make object head towards viewer + FLOAT3D vX = (-vViewerZ)*vY; + vX.Normalize(); + FLOAT3D vZ = vY*vX; + // compose the rotation matrix back from those angles + t3dObjectRotation(1,1) = vX(1); t3dObjectRotation(1,2) = vY(1); t3dObjectRotation(1,3) = vZ(1); + t3dObjectRotation(2,1) = vX(2); t3dObjectRotation(2,2) = vY(2); t3dObjectRotation(2,3) = vZ(2); + t3dObjectRotation(3,1) = vX(3); t3dObjectRotation(3,2) = vY(3); t3dObjectRotation(3,3) = vZ(3); + + // first apply object stretch then object rotation and then viewer rotation + pr_mDirectionRotation = pr_ViewerRotationMatrix*t3dObjectRotation; + pr_RotationMatrix = pr_mDirectionRotation*t3dObjectStretch; + // if it is fully face forward + } else { + // apply object stretch and banking only + FLOATmatrix3D mBanking; + MakeRotationMatrixFast( + mBanking, ANGLE3D(0,0, pr_ObjectPlacement.pl_OrientationAngle(3))); + pr_mDirectionRotation = mBanking; + pr_RotationMatrix = mBanking*t3dObjectStretch; + } + } else { + // first apply object stretch then object rotation and then viewer rotation + pr_mDirectionRotation = pr_ViewerRotationMatrix*t3dObjectRotation; + pr_RotationMatrix = pr_mDirectionRotation*t3dObjectStretch; + } + + // calc. offset of object from viewer + pr_TranslationVector = pr_ObjectPlacement.pl_PositionVector - pr_vViewerPosition; + // rotate offset only by viewer angles + pr_TranslationVector = pr_TranslationVector*pr_ViewerRotationMatrix; + // transform handle from object space to viewer space and add it to the offset + pr_TranslationVector -= pr_vObjectHandle*pr_RotationMatrix; + + FLOAT2D vMin, vMax; + // if using a shadow projection + if (ppr_fMetersPerPixel>0) { + // caclulate factors + FLOAT fFactor = ppr_fViewerDistance/ppr_fMetersPerPixel; + ppr_PerspectiveRatios(1) = -fFactor; + ppr_PerspectiveRatios(2) = -fFactor; + pr_ScreenCenter = -pr_ScreenBBox.Min(); + + vMin = pr_ScreenBBox.Min(); + vMax = pr_ScreenBBox.Max(); + // if using normal projection + } else if (ppr_boxSubScreen.IsEmpty()) { + // calculate perspective constants + FLOAT2D v2dScreenSize = pr_ScreenBBox.Size(); + pr_ScreenCenter = pr_ScreenBBox.Center(); + /* calculate FOVHeight from FOVWidth by formula: + halfanglej = atan( tan(halfanglei)*jsize*aspect/isize ) */ + ANGLE aHalfI = ppr_FOVWidth/2; + ANGLE aHalfJ = ATan(TanFast(aHalfI)*v2dScreenSize(2)*pr_AspectRatio/v2dScreenSize(1)); + + /* calc. perspective ratios by formulae: + xratio = isize/(2*tan(anglei/2)) + yratio = jsize/(2*tan(anglej/2)) + sign is negative since viewer is looking down the -z axis + */ + ppr_PerspectiveRatios(1) = -v2dScreenSize(1)/(2.0f*TanFast(aHalfI))*pr_fViewStretch; + ppr_PerspectiveRatios(2) = -v2dScreenSize(2)/(2.0f*TanFast(aHalfJ))*pr_fViewStretch; + + vMin = pr_ScreenBBox.Min()-pr_ScreenCenter; + vMax = pr_ScreenBBox.Max()-pr_ScreenCenter; + // if using sub-drawport projection + } else { + // calculate perspective constants + FLOAT2D v2dScreenSize = pr_ScreenBBox.Size(); + pr_ScreenCenter = pr_ScreenBBox.Center(); + /* calculate FOVHeight from FOVWidth by formula: + halfanglej = atan( tan(halfanglei)*jsize*aspect/isize ) */ + ANGLE aHalfI = ppr_FOVWidth/2; + ANGLE aHalfJ = ATan(TanFast(aHalfI)*v2dScreenSize(2)*pr_AspectRatio/v2dScreenSize(1)); + + /* calc. perspective ratios by formulae: + xratio = isize/(2*tan(anglei/2)) + yratio = jsize/(2*tan(anglej/2)) + sign is negative since viewer is looking down the -z axis + */ + ppr_PerspectiveRatios(1) = -v2dScreenSize(1)/(2.0f*TanFast(aHalfI))*pr_fViewStretch; + ppr_PerspectiveRatios(2) = -v2dScreenSize(2)/(2.0f*TanFast(aHalfJ))*pr_fViewStretch; + + vMin = ppr_boxSubScreen.Min()-pr_ScreenCenter; + vMax = ppr_boxSubScreen.Max()-pr_ScreenCenter; + + pr_ScreenCenter -= ppr_boxSubScreen.Min(); + } + // find factors for left, right, up and down clipping + + FLOAT fMinI = vMin(1); FLOAT fMinJ = vMin(2); + FLOAT fMaxI = vMax(1); FLOAT fMaxJ = vMax(2); + FLOAT fRatioX = ppr_PerspectiveRatios(1); + FLOAT fRatioY = ppr_PerspectiveRatios(2); + +#define MySgn(x) ((x)>=0?1:-1) + + FLOAT fDZ = -1.0f; + FLOAT fDXL = fDZ*fMinI/fRatioX; + FLOAT fDXR = fDZ*fMaxI/fRatioX; + FLOAT fDYU = -fDZ*fMinJ/fRatioY; + FLOAT fDYD = -fDZ*fMaxJ/fRatioY; + + FLOAT fNLX = -fDZ; + FLOAT fNLZ = +fDXL; + FLOAT fOoNL = 1.0f/(FLOAT)sqrt(fNLX*fNLX+fNLZ*fNLZ); + fNLX*=fOoNL; fNLZ*=fOoNL; + + FLOAT fNRX = +fDZ; + FLOAT fNRZ = -fDXR; + FLOAT fOoNR = 1.0f/(FLOAT)sqrt(fNRX*fNRX+fNRZ*fNRZ); + fNRX*=fOoNR; fNRZ*=fOoNR; + + FLOAT fNDY = -fDZ; + FLOAT fNDZ = +fDYD; + FLOAT fOoND = 1.0f/(FLOAT)sqrt(fNDY*fNDY+fNDZ*fNDZ); + fNDY*=fOoND; fNDZ*=fOoND; + + FLOAT fNUY = +fDZ; + FLOAT fNUZ = -fDYU; + FLOAT fOoNU = 1.0f/(FLOAT)sqrt(fNUY*fNUY+fNUZ*fNUZ); + fNUY*=fOoNU; fNUZ*=fOoNU; + + // make clip planes + pr_plClipU = FLOATplane3D(FLOAT3D( 0,fNUY,fNUZ), 0.0f); + pr_plClipD = FLOATplane3D(FLOAT3D( 0,fNDY,fNDZ), 0.0f); + pr_plClipL = FLOATplane3D(FLOAT3D(fNLX, 0,fNLZ), 0.0f); + pr_plClipR = FLOATplane3D(FLOAT3D(fNRX, 0,fNRZ), 0.0f); + + // mark as prepared + pr_Prepared = TRUE; + + // calculate constant value used for calculating z-buffer k-value from vertex's z coordinate + pr_fDepthBufferFactor = -pr_NearClipDistance; + pr_fDepthBufferMul = pr_fDepthBufferFar-pr_fDepthBufferNear; + pr_fDepthBufferAdd = pr_fDepthBufferNear; + + // calculate ratio for mip factor calculation + ppr_fMipRatio = pr_ScreenBBox.Size()(1)/(ppr_PerspectiveRatios(1)*640.0f); +} + +/* + * Project 3D object point into 3D view space, before clipping. + */ +void CPerspectiveProjection3D::PreClip(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dTransformedPoint) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // rotate and translate the point + v3dTransformedPoint = v3dObjectPoint*pr_RotationMatrix + pr_TranslationVector; +} + +/* + * Project 3D object point into 3D view space, after clipping. + */ +void CPerspectiveProjection3D::PostClip( const FLOAT3D &v3dTransformedPoint, + FLOAT3D &v3dViewPoint) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + // divide X and Y with Z and add the center of screen + const FLOAT f1oTransZ = 1.0f / v3dTransformedPoint(3); + v3dViewPoint(1) = pr_ScreenCenter(1) + v3dTransformedPoint(1) * ppr_PerspectiveRatios(1) *f1oTransZ; + v3dViewPoint(2) = pr_ScreenCenter(2) - v3dTransformedPoint(2) * ppr_PerspectiveRatios(2) *f1oTransZ; +} + + +void CPerspectiveProjection3D::PostClip( const FLOAT3D &v3dTransformedPoint, FLOAT fTransformedR, + FLOAT3D &v3dViewPoint, FLOAT &fViewR) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + // multiply X and Y coordinates with zoom factor and add the center of screen + v3dViewPoint(3) = 1.0f / v3dTransformedPoint(3); + v3dViewPoint(1) = pr_ScreenCenter(1) + v3dTransformedPoint(1) * ppr_PerspectiveRatios(1) * v3dViewPoint(3); + v3dViewPoint(2) = pr_ScreenCenter(2) - v3dTransformedPoint(2) * ppr_PerspectiveRatios(2) * v3dViewPoint(3); + fViewR = fTransformedR * ppr_PerspectiveRatios(1) * v3dViewPoint(3); +} + + +/* Test if a sphere in view space is inside view frustum. */ +INDEX CPerspectiveProjection3D::TestSphereToFrustum( const FLOAT3D &vViewPoint, FLOAT fRadius) const +{ + ASSERT( pr_Prepared && fRadius>=0); + const FLOAT fX = vViewPoint(1); + const FLOAT fY = vViewPoint(2); + const FLOAT fZ = vViewPoint(3); + INDEX iPass = +1; + + // check to near + if( fZ-fRadius>-pr_NearClipDistance) { + return -1; + } else if( fZ+fRadius>-pr_NearClipDistance) { + iPass = 0; + } + // check to far + if( pr_FarClipDistance>0) { + if( fZ+fRadius<-pr_FarClipDistance) { + return -1; + } else if( fZ-fRadius<-pr_FarClipDistance) { + iPass = 0; + } + } + // check to left + FLOAT fL = fX*pr_plClipL(1) + fZ*pr_plClipL(3) - pr_plClipL.Distance(); + if( fL<-fRadius) { + return -1; + } else if( fL0) { + iTest = box.TestAgainstPlane( FLOATplane3D(FLOAT3D(0,0,1), -pr_FarClipDistance)); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + } + // check to left + iTest = box.TestAgainstPlane(pr_plClipL); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // check to right + iTest = box.TestAgainstPlane(pr_plClipR); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // check to up + iTest = box.TestAgainstPlane(pr_plClipU); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // check to down + iTest = box.TestAgainstPlane(pr_plClipD); + if( iTest<0) { + return -1; + } else if( iTest==0) { + iPass = 0; + } + // all done + return iPass; +} + +/* + * Project 3D object point into 3D view space. + */ +void CPerspectiveProjection3D::ProjectCoordinate(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dViewPoint) const +{ + // rotate and translate the point + v3dViewPoint = v3dObjectPoint*pr_RotationMatrix + pr_TranslationVector; + + // divide X and Y with Z and add the center of screen + v3dViewPoint(1) = pr_ScreenCenter(1) + + v3dViewPoint(1) * ppr_PerspectiveRatios(1) / v3dViewPoint(3); + v3dViewPoint(2) = pr_ScreenCenter(2) + + v3dViewPoint(2) * ppr_PerspectiveRatios(2) / v3dViewPoint(3); +} + +/* + * Get a distance of object point from the viewer. + */ +FLOAT CPerspectiveProjection3D::GetDistance(const FLOAT3D &v3dObjectPoint) const +{ + // get just the z coordinate of the point in viewer space + return + v3dObjectPoint(1)*pr_RotationMatrix(3,1)+ + v3dObjectPoint(2)*pr_RotationMatrix(3,2)+ + v3dObjectPoint(3)*pr_RotationMatrix(3,3)+ + pr_TranslationVector(3); +} + +/* + * Project 3D object direction vector into 3D view space. + */ +void CPerspectiveProjection3D::ProjectDirection(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dViewPoint) const +{ + // rotate the direction + v3dViewPoint = v3dObjectPoint*pr_mDirectionRotation; +} + +/* + * Project 3D object axis aligned bounding box into 3D view space. + */ +void CPerspectiveProjection3D::ProjectAABBox(const FLOATaabbox3D &boxObject, + FLOATaabbox3D &boxView) const +{ + ASSERTALWAYS( "This is not yet implemented"); +} + +/* + * Project 3D object plane into 3D view space. + */ +void CPerspectiveProjection3D::Project(const FLOATplane3D &p3dObjectPlane, + FLOATplane3D &p3dTransformedPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // rotate and translate the normal vector + p3dTransformedPlane = p3dObjectPlane*pr_mDirectionRotation + pr_TranslationVector; +} + +/* Calculate plane gradient for a plane in 3D view space. */ +void CPerspectiveProjection3D::MakeOoKGradient(const FLOATplane3D &plViewerPlane, CPlanarGradients &pgOoK) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // get perspective factors + FLOAT oorx = +1/ppr_PerspectiveRatios(1); + FLOAT oory = -1/ppr_PerspectiveRatios(2); + FLOAT ci = pr_ScreenCenter(1); + FLOAT cj = pr_ScreenCenter(2); + FLOAT f = pr_fDepthBufferFactor; + FLOAT fn = f; + + // normalize control vectors + FLOAT nx = plViewerPlane(1)*fn; + FLOAT ny = plViewerPlane(2)*fn; + FLOAT nz = plViewerPlane(3)*fn; + FLOAT oond = 1/plViewerPlane.Distance(); + // calculate gradients + FLOAT dookodi = nx*oond*oorx; + FLOAT dookodj = ny*oond*oory; + FLOAT ook00 = nz*oond-dookodi*ci-dookodj*cj; + + // remember the gradients + pgOoK.pg_f00 = ook00; + pgOoK.pg_fDOverDI = dookodi; + pgOoK.pg_fDOverDJ = dookodj; +} +/* + * Clip a line. + */ +ULONG CPerspectiveProjection3D::ClipLine(FLOAT3D &v3dPoint0, FLOAT3D &v3dPoint1) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + ULONG ulCode0 = LCFVERTEX0(LCF_UNCLIPPED); + ULONG ulCode1 = LCFVERTEX1(LCF_UNCLIPPED); + + // clip the line by each plane at the time, skip if some removes entire line + if (ClipLineByNearPlane(v3dPoint0, v3dPoint1, pr_NearClipDistance, ulCode0, ulCode1, LCF_NEAR) + && ((pr_FarClipDistance<0) || + ClipLineByFarPlane(v3dPoint0, v3dPoint1, pr_FarClipDistance, ulCode0, ulCode1, LCF_FAR)) + // if something remains + ) { + // return the clip code for both vertices + return ulCode0 | ulCode1; + // if some of the planes removed entire line + } else { + // return the code that tells that entire line is removed + return LCF_EDGEREMOVED; + } +} + +/* + * Get placement for a ray through a projected point. + */ +void CPerspectiveProjection3D::RayThroughPoint(const FLOAT3D &v3dViewPoint, + CPlacement3D &plRay) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + /* Assume z coordinate of -1 and calculate x and y for that. + * These are in fact just the perspective formulae, solved for transformed point. + * The result is a direction in viewer space. + */ + FLOAT3D v3dDirection; + + v3dDirection(1) = -(v3dViewPoint(1) - pr_ScreenCenter(1))/ppr_PerspectiveRatios(1); + v3dDirection(2) = -(v3dViewPoint(2) - pr_ScreenCenter(2))/ppr_PerspectiveRatios(2); + v3dDirection(3) = -1.0f; + + // back-rotate the ray to absolute space + v3dDirection *= !pr_ViewerRotationMatrix; + + // normalize the ray + v3dDirection.Normalize(); + + // now calculate the angles from the direction + DirectionVectorToAngles(v3dDirection, plRay.pl_OrientationAngle); + + // position is same as viewer's + plRay.pl_PositionVector = pr_vViewerPosition; +} + +/* + * Check if an object-space plane is visible. + */ +BOOL CPerspectiveProjection3D::IsObjectPlaneVisible(const FLOATplane3D &p3dObjectPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + /* + In perspective projection, plane is invisible if viewer is not in front of plane. + NOTES: 1) Could add a check for plane beeing inside view frustum. + */ + // if viewer is in front of plane, after plane is transformed into viewer space + // (viewer is at 0,0,0) + if ( (p3dObjectPlane*pr_mDirectionRotation + pr_TranslationVector).Distance() < 0.0f ) { + // plane might be visible (although it still might be out of the view frustum) + return TRUE; + // if viewer is on the plane or behind it + } else { + // plane is surely not visible + return FALSE; + } +} + +/* + * Check if a viewer-space plane is visible. + */ +BOOL CPerspectiveProjection3D::IsViewerPlaneVisible(const FLOATplane3D &p3dViewerPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + /* + In perspective projection, plane is invisible if viewer is not in front of plane. + NOTES: 1) Could add a check for plane beeing inside view frustum. + */ + // if viewer is in front of plane (viewer is at 0,0,0) + if ( p3dViewerPlane.Distance() < -0.01f ) { + // plane might be visible (although it still might be out of the view frustum) + return TRUE; + // if viewer is on the plane or behind it + } else { + // plane is surely not visible + return FALSE; + } +} + + +/* + * Calculate a mip-factor for a given object. + */ +// by its distance from viewer +FLOAT CPerspectiveProjection3D::MipFactor(FLOAT fDistance) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + // calculated using following formula: k = log2(1024*z/xratio); + return Log2( (FLOAT)Abs(1024.0f*fDistance*ppr_fMipRatio)); +} + + +// general mip-factor for target object +FLOAT CPerspectiveProjection3D::MipFactor(void) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + // calculated using following formula: k = log2(1024*z/xratio); + // the distance is, in fact, the z coordinate of the translation vector + return -pr_TranslationVector(3)*TanFast(ppr_FOVWidth/2.0f); // /Tan(90.0f/2.0f)=1; +} diff --git a/Sources/Engine/Math/Projection_Simple.cpp b/Sources/Engine/Math/Projection_Simple.cpp new file mode 100644 index 0000000..442e162 --- /dev/null +++ b/Sources/Engine/Math/Projection_Simple.cpp @@ -0,0 +1,282 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include + +///////////////////////////////////////////////////////////////////// +// CSimpleProjection3D + +/* + * Prepare for projecting. + */ +void CSimpleProjection3D::Prepare(void) +{ + FLOATmatrix3D t3dObjectStretch; // matrix for object stretch + FLOATmatrix3D t3dObjectRotation; // matrix for object angles + + // calc. matrices for viewer and object angles and stretch + MakeRotationMatrix(t3dObjectRotation, pr_ObjectPlacement.pl_OrientationAngle); // object normally + MakeInverseRotationMatrix(pr_ViewerRotationMatrix, pr_ViewerPlacement.pl_OrientationAngle); // viewer inverse + t3dObjectStretch.Diagonal(pr_ObjectStretch); + + // if the object is face-forward + if (pr_bFaceForward) { + // apply object stretch only + pr_RotationMatrix = t3dObjectStretch; + } else { + // first apply object stretch then object rotation and then viewer rotation + pr_RotationMatrix = pr_ViewerRotationMatrix*t3dObjectRotation*t3dObjectStretch; + } + + // calc. offset of object from viewer + pr_TranslationVector = pr_ObjectPlacement.pl_PositionVector - pr_ViewerPlacement.pl_PositionVector; + // rotate offset only by viewer angles + pr_TranslationVector = pr_TranslationVector*pr_ViewerRotationMatrix; + // transform handle from object space to viewer space and add it to the offset + pr_TranslationVector -= pr_vObjectHandle*pr_RotationMatrix; + + // mark as prepared + pr_Prepared = TRUE; +} + +/* + * Project 3D object point into 3D view space, before clipping. + */ +void CSimpleProjection3D::PreClip(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dTransformedPoint) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // rotate and translate the point + v3dTransformedPoint = v3dObjectPoint*pr_RotationMatrix + pr_TranslationVector; +} + +/* + * Project 3D object point into 3D view space, after clipping. + */ +void CSimpleProjection3D::PostClip( const FLOAT3D &v3dTransformedPoint, + FLOAT3D &v3dViewPoint) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + v3dViewPoint = v3dTransformedPoint; +} + + +void CSimpleProjection3D::PostClip( const FLOAT3D &v3dTransformedPoint, FLOAT fTransformedR, + FLOAT3D &v3dViewPoint, FLOAT &fViewR) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + v3dViewPoint = v3dTransformedPoint; + fViewR = fTransformedR; +} + + +/* Test if a sphere in view space is inside view frustum. */ +INDEX CSimpleProjection3D::TestSphereToFrustum(const FLOAT3D &vViewPoint, FLOAT fRadius) const +{ + ASSERT(pr_Prepared); + ASSERTALWAYS("Function not supported"); + return 1; +} + +/* Test if an oriented box in view space is inside view frustum. */ +INDEX CSimpleProjection3D::TestBoxToFrustum(const FLOATobbox3D &boxView) const +{ + ASSERT(pr_Prepared); + ASSERTALWAYS("Function not supported"); + return 1; +} + +/* + * Project 3D object point into 3D view space. + */ +void CSimpleProjection3D::ProjectCoordinate(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dViewPoint) const +{ + // rotate and translate the point + v3dViewPoint = v3dObjectPoint*pr_RotationMatrix + pr_TranslationVector; +} + +/* + * Get a distance of object point from the viewer. + */ +FLOAT CSimpleProjection3D::GetDistance(const FLOAT3D &v3dObjectPoint) const +{ + // get just the z coordinate of the point in viewer space + return + v3dObjectPoint(1)*pr_RotationMatrix(3,1)+ + v3dObjectPoint(2)*pr_RotationMatrix(3,2)+ + v3dObjectPoint(3)*pr_RotationMatrix(3,3)+ + pr_TranslationVector(3); +} + +/* + * Project 3D object direction vector into 3D view space. + */ +void CSimpleProjection3D::ProjectDirection(const FLOAT3D &v3dObjectPoint, + FLOAT3D &v3dViewPoint) const +{ + // rotate the direction + v3dViewPoint = v3dObjectPoint*pr_RotationMatrix; +} + +/* + * Project 3D object placement into 3D view space. + */ +void CSimpleProjection3D::ProjectPlacement(const CPlacement3D &plObject, + CPlacement3D &plView) const +{ + // rotate and translate the position vector + plView.pl_PositionVector = plObject.pl_PositionVector*pr_RotationMatrix + + pr_TranslationVector; + // rotate the orientation + FLOATmatrix3D mOrientation; + MakeRotationMatrix(mOrientation, plObject.pl_OrientationAngle); + DecomposeRotationMatrix(plView.pl_OrientationAngle, pr_RotationMatrix*mOrientation); +} + +/* + * Project 3D object placement into 3D view space. + */ +void CSimpleProjection3D::ProjectPlacementSmooth(const CPlacement3D &plObject, + CPlacement3D &plView) const +{ + // rotate and translate the position vector + plView.pl_PositionVector = plObject.pl_PositionVector*pr_RotationMatrix + + pr_TranslationVector; + // rotate the orientation + FLOATmatrix3D mOrientation; + MakeRotationMatrixFast(mOrientation, plObject.pl_OrientationAngle); + DecomposeRotationMatrixNoSnap(plView.pl_OrientationAngle, pr_RotationMatrix*mOrientation); +} + +/* + * Project 3D object axis aligned bounding box into 3D view space. + */ +void CSimpleProjection3D::ProjectAABBox(const FLOATaabbox3D &boxObject, + FLOATaabbox3D &boxView) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // get center and max axial extent of object box + const FLOAT3D vObjectBoxCenter = boxObject.Center(); + const FLOAT fObjectBoxMaxExtent = boxObject.Size().MaxNorm(); + // project the center to view space + FLOAT3D vViewBoxCenter; + ProjectCoordinate(vObjectBoxCenter, vViewBoxCenter); + + // let the view box have center there and radius of twice max axial extent of object box + boxView = FLOATaabbox3D(vViewBoxCenter, 2*fObjectBoxMaxExtent); + +/* // clear view box + boxView = FLOATaabbox3D(); + // create all vertex points of object box + FLOAT3D avObjectBoxVertices[8]; + avObjectBoxVertices[0](1) = boxObject.Min()(1); + avObjectBoxVertices[0](2) = boxObject.Min()(2); + avObjectBoxVertices[0](3) = boxObject.Min()(3); + + avObjectBoxVertices[0](1) = boxObject.Min()(1); + avObjectBoxVertices[0](2) = boxObject.Min()(2); + avObjectBoxVertices[0](3) = boxObject.Min()(3); + + avObjectBoxVertices[0](1) = boxObject.Max()(1); + // project all vertex points of object box + // add all vertex points of object box to view box +*/ +} + +/* + * Project 3D object plane into 3D view space. + */ +void CSimpleProjection3D::Project(const FLOATplane3D &p3dObjectPlane, + FLOATplane3D &p3dTransformedPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // rotate and translate the plane + p3dTransformedPlane = p3dObjectPlane*pr_RotationMatrix + pr_TranslationVector; +} + +/* Calculate plane gradient for a plane in 3D view space. */ +void CSimpleProjection3D::MakeOoKGradient(const FLOATplane3D &plViewerPlane, CPlanarGradients &pgOoK) const +{ + ASSERTALWAYS("Function not supported"); +} +/* + * Clip a line. + */ +ULONG CSimpleProjection3D::ClipLine(FLOAT3D &v3dPoint0, FLOAT3D &v3dPoint1) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // line remains unclipped + return LCFVERTEX0(LCF_UNCLIPPED) | LCFVERTEX1(LCF_UNCLIPPED); +} + +/* + * Get placement for a ray through a projected point. + */ +void CSimpleProjection3D::RayThroughPoint(const FLOAT3D &v3dViewPoint, + CPlacement3D &plRay) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + ASSERTALWAYS("Not implemented!"); +} + +/* + * Check if an object-space plane is visible. + */ +BOOL CSimpleProjection3D::IsObjectPlaneVisible(const FLOATplane3D &p3dObjectPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + ASSERTALWAYS("Not implemented!"); + return TRUE; +} + +/* + * Check if a viewer-space plane is visible. + */ +BOOL CSimpleProjection3D::IsViewerPlaneVisible(const FLOATplane3D &p3dViewerPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + // the object plane is visible is it is not heading away from the view plane + return p3dViewerPlane(3)>0.0f; +} + +/* + * Calculate a mip-factor for a given object. + */ +// by its distance from viewer +FLOAT CSimpleProjection3D::MipFactor(FLOAT fDistance) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + ASSERTALWAYS("Not implemented!"); + return 0.0f; +} +// general mip-factor for target object +FLOAT CSimpleProjection3D::MipFactor(void) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + ASSERTALWAYS("Not implemented!"); + return 0.0f; +} + diff --git a/Sources/Engine/Math/Projection_Simple_DOUBLE.cpp b/Sources/Engine/Math/Projection_Simple_DOUBLE.cpp new file mode 100644 index 0000000..74be9c3 --- /dev/null +++ b/Sources/Engine/Math/Projection_Simple_DOUBLE.cpp @@ -0,0 +1,173 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include + +#include + +/* + * Default constructor. + */ +CSimpleProjection3D_DOUBLE::CSimpleProjection3D_DOUBLE(void) { + pr_Prepared = FALSE; + pr_ObjectStretch = FLOAT3D(1.0f, 1.0f, 1.0f); +} +/* + * Prepare for projecting. + */ +void CSimpleProjection3D_DOUBLE::Prepare(void) +{ + DOUBLEmatrix3D t3dObjectStretch; // matrix for object stretch + DOUBLEmatrix3D t3dObjectRotation; // matrix for object angles + + // calc. matrices for viewer and object angles and stretch + t3dObjectRotation ^= pr_ObjectPlacement.pl_OrientationAngle; // object normally + pr_ViewerRotationMatrix != pr_ViewerPlacement.pl_OrientationAngle; // viewer inverse + t3dObjectStretch.Diagonal(FLOATtoDOUBLE(pr_ObjectStretch)); + + // first apply object stretch then object rotation and then viewer rotation + pr_RotationMatrix = pr_ViewerRotationMatrix*t3dObjectRotation*t3dObjectStretch; + + // calc. offset of object from viewer + pr_TranslationVector = FLOATtoDOUBLE(pr_ObjectPlacement.pl_PositionVector - pr_ViewerPlacement.pl_PositionVector); + // rotate offset only by viewer angles + pr_TranslationVector = pr_TranslationVector*pr_ViewerRotationMatrix; + + // mark as prepared + pr_Prepared = TRUE; +} + +/* + * Project 3D object point into 3D view space. + */ +void CSimpleProjection3D_DOUBLE::ProjectCoordinate(const DOUBLE3D &v3dObjectPoint, + DOUBLE3D &v3dViewPoint) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // rotate and translate the point + v3dViewPoint = v3dObjectPoint*pr_RotationMatrix + pr_TranslationVector; +} + +/* + * Project 3D object direction vector into 3D view space. + */ +void CSimpleProjection3D_DOUBLE::ProjectDirection(const DOUBLE3D &v3dObjectPoint, + DOUBLE3D &v3dViewPoint) const +{ + // rotate the direction + v3dViewPoint = v3dObjectPoint*pr_RotationMatrix; +} + +/* + * Project 3D object placement into 3D view space. + */ +void CSimpleProjection3D_DOUBLE::ProjectPlacement(const CPlacement3D &plObject, + CPlacement3D &plView) const +{ + // rotate and translate the position vector + plView.pl_PositionVector = DOUBLEtoFLOAT( + FLOATtoDOUBLE(plObject.pl_PositionVector)*pr_RotationMatrix + pr_TranslationVector); + // rotate the orientation + DOUBLEmatrix3D mOrientation; + mOrientation ^= plObject.pl_OrientationAngle; + plView.pl_OrientationAngle ^= pr_RotationMatrix*mOrientation; +} + +/* + * Project 3D object mapping into 3D view space. + */ +void CSimpleProjection3D_DOUBLE::ProjectMapping(const CMappingDefinition &mdObject, + const DOUBLEplane3D &plObject, + CMappingDefinition &mdView) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // make mapping vectors for given plane + CMappingVectors mvObjectDefault; + mvObjectDefault.FromPlane_DOUBLE(plObject); + CMappingVectors mvObject; + mdObject.ToMappingVectors(mvObjectDefault, mvObject); + + // make projected plane and vectors + DOUBLEplane3D plView; + Project(plObject, plView); + CMappingVectors mvViewDefault; + mvViewDefault.FromPlane_DOUBLE(plView); + DOUBLE3D vO, vU, vV; + ProjectCoordinate(FLOATtoDOUBLE(mvObject.mv_vO), vO); + ProjectDirection(FLOATtoDOUBLE(mvObject.mv_vU), vU); + ProjectDirection(FLOATtoDOUBLE(mvObject.mv_vV), vV); + CMappingVectors mvView; + mvView.mv_vO = DOUBLEtoFLOAT(vO); + mvView.mv_vU = DOUBLEtoFLOAT(vU); + mvView.mv_vV = DOUBLEtoFLOAT(vV); + + // create definition back from the vectors + mdView.FromMappingVectors(mvViewDefault, mvView); +} + +/* + * Project 3D object axis aligned bounding box into 3D view space. + */ +void CSimpleProjection3D_DOUBLE::ProjectAABBox(const DOUBLEaabbox3D &boxObject, + DOUBLEaabbox3D &boxView) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // get center and max axial extent of object box + const DOUBLE3D vObjectBoxCenter = boxObject.Center(); + const DOUBLE fObjectBoxMaxExtent = boxObject.Size().MaxNorm(); + // project the center to view space + DOUBLE3D vViewBoxCenter; + ProjectCoordinate(vObjectBoxCenter, vViewBoxCenter); + + // let the view box have center there and radius of twice max axial extent of object box + boxView = DOUBLEaabbox3D(vViewBoxCenter, 2*fObjectBoxMaxExtent); + +/* // clear view box + boxView = DOUBLEaabbox3D(); + // create all vertex points of object box + DOUBLE3D avObjectBoxVertices[8]; + avObjectBoxVertices[0](1) = boxObject.Min()(1); + avObjectBoxVertices[0](2) = boxObject.Min()(2); + avObjectBoxVertices[0](3) = boxObject.Min()(3); + + avObjectBoxVertices[0](1) = boxObject.Min()(1); + avObjectBoxVertices[0](2) = boxObject.Min()(2); + avObjectBoxVertices[0](3) = boxObject.Min()(3); + + avObjectBoxVertices[0](1) = boxObject.Max()(1); + // project all vertex points of object box + // add all vertex points of object box to view box +*/ +} + +/* + * Project 3D object plane into 3D view space. + */ +void CSimpleProjection3D_DOUBLE::Project(const DOUBLEplane3D &p3dObjectPlane, + DOUBLEplane3D &p3dTransformedPlane) const +{ + // check that the projection object is prepared for projecting + ASSERT(pr_Prepared); + + // rotate the plane + p3dTransformedPlane = p3dObjectPlane*pr_RotationMatrix; + // renormalize it in case of stretch + if (pr_ObjectStretch(1)!=1.0f || pr_ObjectStretch(2)!=1.0f || pr_ObjectStretch(3)!=1.0f) { + FLOAT fLen = ((DOUBLE3D&)p3dTransformedPlane).Length(); + p3dTransformedPlane = DOUBLEplane3D( + ((DOUBLE3D&)p3dTransformedPlane)/fLen, + p3dTransformedPlane.Distance()*fLen); + } + // translate the plane + p3dTransformedPlane += pr_TranslationVector; +} diff --git a/Sources/Engine/Math/Quaternion.h b/Sources/Engine/Math/Quaternion.h new file mode 100644 index 0000000..d586bcc --- /dev/null +++ b/Sources/Engine/Math/Quaternion.h @@ -0,0 +1,357 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_QUATERNION_H +#define SE_INCL_QUATERNION_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Template class for quaternion of arbitrary precision. + */ +template +class Quaternion { +public: + Type q_w, q_x, q_y, q_z; +public: + // default constructor + inline Quaternion(void); + // constructor from four scalar values + inline Quaternion(Type w, Type x, Type y, Type z); + + // conversion from euler angles + void FromEuler(const Vector &a); + + // conversion to matrix + void ToMatrix(Matrix &m) const; + // conversion from matrix + void FromMatrix(Matrix &m); + + // conversion to/from axis-angle + void FromAxisAngle(const Vector &n, Type a); + void ToAxisAngle(Vector &n, Type &a); + + // unary minus (fliping of the quaternion) + inline Quaternion operator-(void) const; + // conjugation + inline Quaternion operator~(void) const; + // inversion + inline Quaternion Inv(void) const; + + // multiplication/division by a scalar + inline Quaternion operator*(Type t) const; + inline Quaternion &operator*=(Type t); + friend Quaternion operator*(Type t, Quaternion q); + inline Quaternion operator/(Type t) const; + inline Quaternion &operator/=(Type t); + + // addition/substraction + inline Quaternion operator+(const Quaternion &q2) const; + inline Quaternion &operator+=(const Quaternion &q2); + inline Quaternion operator-(const Quaternion &q2) const; + inline Quaternion &operator-=(const Quaternion &q2); + // multiplication + inline Quaternion operator*(const Quaternion &q2) const; + inline Quaternion &operator*=(const Quaternion &q2); + // dot product + inline Type operator%(const Quaternion &q2) const; + + // quaternion norm (euclidian length of a 4d vector) + inline Type Norm(void) const; + + // transcendental functions + /*friend Quaternion Exp(const Quaternion &q); + friend Quaternion Log(const Quaternion &q);*/ + + // spherical linear interpolation + /*friend Quaternion Slerp(Type tT, + const Quaternion &q1, const Quaternion &q2);*/ + // spherical quadratic interpolation + /*friend Quaternion Squad(Type tT, + const Quaternion &q1, const Quaternion &q2, + const Quaternion &qa, const Quaternion &qb);*/ +}; + +// inline functions implementation +/* + * Default constructor. + */ +template +inline Quaternion::Quaternion(void) {}; + +/* Constructor from three values. */ +template +inline Quaternion::Quaternion(Type w, Type x, Type y, Type z) +: q_w(w), q_x(x), q_y(y), q_z(z) {}; + +// unary minus (additive inversion) +template +inline Quaternion Quaternion::operator-(void) const { + return Quaternion(-q_w, -q_x, -q_y, -q_z); +} +// conjugation +template +inline Quaternion Quaternion::operator~(void) const { + return Quaternion(q_w, -q_x, -q_y, -q_z); +} +// multiplicative inversion +template +inline Quaternion Quaternion::Inv(void) const { + return (~(*this))/Norm(); +} + +// multiplication/division by a scalar +template +inline Quaternion Quaternion::operator*(Type t) const { + return Quaternion(q_w*t, q_x*t, q_y*t, q_z*t); +} +template +inline Quaternion &Quaternion::operator*=(Type t) { + q_w*=t; q_x*=t; q_y*=t; q_z*=t; + return *this; +} +template +inline Quaternion operator*(Type t, Quaternion q) { + return Quaternion(q.q_w*t, q.q_x*t, q.q_y*t, q.q_z*t); +} +template +inline Quaternion Quaternion::operator/(Type t) const { + return Quaternion(q_w/t, q_x/t, q_y/t, q_z/t); +} +template +inline Quaternion &Quaternion::operator/=(Type t) { + q_w/=t; q_x/=t; q_y/=t; q_z/=t; + return *this; +} + +// addition/substraction +template +inline Quaternion Quaternion::operator+(const Quaternion &q2) const { + return Quaternion(q_w+q2.q_w, q_x+q2.q_x, q_y+q2.q_y, q_z+q2.q_z); +} +template +inline Quaternion &Quaternion::operator+=(const Quaternion &q2) { + q_w+=q2.q_w; q_x+=q2.q_x; q_y+=q2.q_y; q_z+=q2.q_z; + return *this; +} +template +inline Quaternion Quaternion::operator-(const Quaternion &q2) const { + return Quaternion(q_w-q2.q_w, q_x-q2.q_x, q_y-q2.q_y, q_z-q2.q_z); +} +template +inline Quaternion &Quaternion::operator-=(const Quaternion &q2) { + q_w-=q2.q_w; q_x-=q2.q_x; q_y-=q2.q_y; q_z-=q2.q_z; + return *this; +} + +// multiplication +template +inline Quaternion Quaternion::operator*(const Quaternion &q2) const { + return Quaternion( + q_w*q2.q_w - q_x*q2.q_x - q_y*q2.q_y - q_z*q2.q_z, + q_w*q2.q_x + q_x*q2.q_w + q_y*q2.q_z - q_z*q2.q_y, + q_w*q2.q_y - q_x*q2.q_z + q_y*q2.q_w + q_z*q2.q_x, + q_w*q2.q_z + q_x*q2.q_y - q_y*q2.q_x + q_z*q2.q_w); +} +template +inline Quaternion &Quaternion::operator*=(const Quaternion &q2) { + *this = (*this)*q2; + return *this; +} +// dot product +template +inline Type Quaternion::operator%(const Quaternion &q2) const { + return q_w*q2.q_w + q_x*q2.q_x + q_y*q2.q_y + q_z*q2.q_z; +} + +// quaternion norm (euclidian length of a 4d vector) +template +inline Type Quaternion::Norm(void) const { + return (Type)sqrt(q_w*q_w + q_x*q_x + q_y*q_y + q_z*q_z); +} + +// transcendental functions +template +inline Quaternion Exp(const Quaternion &q) +{ + Type tAngle = (Type)sqrt(q.q_x*q.q_x + q.q_y*q.q_y + q.q_z*q.q_z); + Type tSin = sin(tAngle); + Type tCos = cos(tAngle); + + if (fabs(tSin)<0.001) { + return Quaternion(tCos, q.q_x, q.q_y, q.q_z); + } else { + Type tRatio = tSin/tAngle; + return Quaternion(tCos, q.q_x*tRatio, q.q_y*tRatio, q.q_z*tRatio); + } +} +// transcendental functions +template +inline Quaternion Log(const Quaternion &q) +{ + if (fabs(q.q_w)<1.0) { + Type tAngle = acos(q.q_w); + Type tSin = sin(tAngle); + if (fabs(tSin)>=0.001) { + Type tRatio = tAngle/tSin; + return Quaternion(Type(0), q.q_x*tRatio, q.q_y*tRatio, q.q_z*tRatio); + } + } + + return Quaternion(Type(0), q.q_x, q.q_y, q.q_z); +} + +// spherical linear interpolation +template +inline Quaternion Slerp(Type tT, + const Quaternion &q1, const Quaternion &q2) +{ + Type tCos = q1%q2; + + Quaternion qTemp; + + if (tCos Type(0.001)) { + // standard case (slerp) + Type tAngle = acos(tCos); + Type tSin = sin(tAngle); + tF1 = sin((Type(1)-tT)*tAngle)/tSin; + tF2 = sin(tT*tAngle)/tSin; + } else { + // linear interpolation + tF1 = Type(1)-tT; + tF2 = tT; + } + return q1*tF1 + qTemp*tF2; +} +// spherical quadratic interpolation +template +inline Quaternion Squad(Type tT, + const Quaternion &q1, const Quaternion &q2, + const Quaternion &qa, const Quaternion &qb) +{ + return Slerp(2*tT*(1-tT),Slerp(tT,q1,q2),Slerp(tT,qa,qb)); +} + +// conversion from euler angles +template +void Quaternion::FromEuler(const Vector &a) +{ + Quaternion qH; + Quaternion qP; + Quaternion qB; + qH.q_w = Cos(a(1)/2); + qH.q_x = 0; + qH.q_y = Sin(a(1)/2); + qH.q_z = 0; + + qP.q_w = Cos(a(2)/2); + qP.q_x = Sin(a(2)/2); + qP.q_y = 0; + qP.q_z = 0; + + qB.q_w = Cos(a(3)/2); + qB.q_x = 0; + qB.q_y = 0; + qB.q_z = Sin(a(3)/2); + + (*this) = qH*qP*qB; +} + +// conversion to matrix +template +void Quaternion::ToMatrix(Matrix &m) const +{ + Type xx = 2*q_x*q_x; Type xy = 2*q_x*q_y; Type xz = 2*q_x*q_z; + Type yy = 2*q_y*q_y; Type yz = 2*q_y*q_z; Type zz = 2*q_z*q_z; + Type wx = 2*q_w*q_x; Type wy = 2*q_w*q_y; Type wz = 2*q_w*q_z; + + m(1,1) = 1.0-(yy+zz); m(1,2) = xy-wz; m(1,3) = xz+wy; + m(2,1) = xy+wz; m(2,2) = 1.0-(xx+zz); m(2,3) = yz-wx; + m(3,1) = xz-wy; m(3,2) = yz+wx; m(3,3) = 1.0-(xx+yy); +} + +// conversion from matrix +template +void Quaternion::FromMatrix(Matrix &m) +{ + Type trace = m(1,1)+m(2,2)+m(3,3); + Type root; + + if ( trace > 0.0 ) + { + // |w| > 1/2, may as well choose w > 1/2 + root = sqrt(trace+1.0); // 2w + q_w = 0.5*root; + root = 0.5/root; // 1/(4w) + q_x = (m(3,2)-m(2,3))*root; + q_y = (m(1,3)-m(3,1))*root; + q_z = (m(2,1)-m(1,2))*root; + } + else + { + // |w| <= 1/2 + static int next[3] = { 1, 2, 0 }; + int i = 0; + if ( m(2,2) > m(1,1) ) + i = 1; + if ( m(3,3) > m(i+1,i+1) ) + i = 2; + int j = next[i]; + int k = next[j]; + + root = sqrt(m(i+1,i+1)-m(j+1,j+1)-m(k+1,k+1)+1.0); + Type* quat[3] = { &q_x, &q_y, &q_z }; + *quat[i] = 0.5*root; + root = 0.5/root; + q_w = (m(k+1,j+1)-m(j+1,k+1))*root; + *quat[j] = (m(j+1,i+1)+m(i+1,j+1))*root; + *quat[k] = (m(k+1,i+1)+m(i+1,k+1))*root; + } +} + +// conversion to/from axis-angle +template +void Quaternion::FromAxisAngle(const Vector &n, Type a) +{ + Type tSin = sin(a/2); + Type tCos = cos(a/2); + + q_x = n(1)*tSin; + q_y = n(2)*tSin; + q_z = n(3)*tSin; + q_w = tCos; +} + +template +void Quaternion::ToAxisAngle(Vector &n, Type &a) +{ + Type tCos = q_w; + Type tSin = sqrt(Type(1)-tCos*tCos); + a = 2*acos(tCos); + + // if angle is not zero + if (Abs(tSin)>=0.001) { + n(1) = q_x / tSin; + n(2) = q_y / tSin; + n(3) = q_z / tSin; + // if angle is zero + } else { + n(1) = Type(1); + n(2) = Type(0); + n(3) = Type(0); + } +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/TextureMapping.cpp b/Sources/Engine/Math/TextureMapping.cpp new file mode 100644 index 0000000..b9c38a9 --- /dev/null +++ b/Sources/Engine/Math/TextureMapping.cpp @@ -0,0 +1,334 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include + +// calculate default texture mapping control points from a plane +void CMappingVectors::FromPlane(const FLOATplane3D &plPlane) +{ + // take origin at plane reference point + mv_vO = plPlane.ReferencePoint(); + + // if the plane is mostly horizontal + if (Abs(plPlane(2))>0.5) { + // use cross product of +x axis and plane normal as +s axis + mv_vU = FLOAT3D(1.0f, 0.0f, 0.0f)*(FLOAT3D&)plPlane; + // if the plane is mostly vertical + } else { + // use cross product of +y axis and plane normal as +s axis + mv_vU = FLOAT3D(0.0f, 1.0f, 0.0f)*(FLOAT3D&)plPlane; + } + // make +s axis normalized + mv_vU.Normalize(); + + // use cross product of plane normal and +s axis as +t axis + mv_vV = mv_vU*(FLOAT3D &)plPlane; +} +void CMappingVectors::FromPlane_DOUBLE(const DOUBLEplane3D &plPlane) +{ + FromPlane(DOUBLEtoFLOAT(plPlane)); +} +// calculate plane from default mapping vectors +void CMappingVectors::ToPlane(FLOATplane3D &plPlane) const +{ + plPlane = FLOATplane3D(mv_vV*mv_vU, mv_vO); +} + +// convert to human-friendly format +void CMappingDefinition::ToUI(CMappingDefinitionUI &mdui) const +{ + // make a copy of parameters + FLOAT fUoS = md_fUoS; + FLOAT fUoT = md_fUoT; + FLOAT fVoS = md_fVoS; + FLOAT fVoT = md_fVoT; + + // find size of mapping vectors + FLOAT fUSize = FLOAT(sqrt(fUoS*fUoS+fUoT*fUoT)); + FLOAT fVSize = FLOAT(sqrt(fVoS*fVoS+fVoT*fVoT)); + + // find rotation of both vectors + ANGLE aURot = -(ATan2(fVoT, fVoS)-90.0f); + ANGLE aVRot = -(ATan2(fUoT, fUoS)); + + // use the found values + Snap(aURot, 0.001f); + Snap(aVRot, 0.001f); + mdui.mdui_aURotation= NormalizeAngle(aURot); + mdui.mdui_aVRotation= NormalizeAngle(aVRot); + mdui.mdui_fUStretch = 1/fUSize; + mdui.mdui_fVStretch = 1/fVSize; + mdui.mdui_fUOffset = md_fUOffset; + mdui.mdui_fVOffset = md_fVOffset; +} + +// convert from human-friendly format +void CMappingDefinition::FromUI(const CMappingDefinitionUI &mdui) +{ + // extract all values from mapping definition + md_fUoS = +Cos(-(mdui.mdui_aVRotation)); + md_fUoT = +Sin(-(mdui.mdui_aVRotation)); + md_fVoS = +Cos(-(mdui.mdui_aURotation)+AngleDeg(90.0f)); + md_fVoT = +Sin(-(mdui.mdui_aURotation)+AngleDeg(90.0f)); + + md_fUoS /= mdui.mdui_fUStretch; + md_fUoT /= mdui.mdui_fUStretch; + md_fVoS /= mdui.mdui_fVStretch; + md_fVoT /= mdui.mdui_fVStretch; + + md_fUOffset = mdui.mdui_fUOffset; + md_fVOffset = mdui.mdui_fVOffset; +} + +// make mapping vectors for this mapping +void CMappingDefinition::MakeMappingVectors( const CMappingVectors &mvSrc, CMappingVectors &mvDst) const +{ + const FLOAT uos = md_fUoS; + const FLOAT uot = md_fUoT; + const FLOAT vos = md_fVoS; + const FLOAT vot = md_fVoT; + const FLOAT ood = 1.0f / (uos*vot-uot*vos); + const FLOAT sou = +vot*ood; const FLOAT sov = -uot*ood; + const FLOAT tov = +uos*ood; const FLOAT tou = -vos*ood; + mvDst.mv_vO = mvSrc.mv_vO + + mvSrc.mv_vU * (md_fUOffset*sou + md_fVOffset*sov) + + mvSrc.mv_vV * (md_fUOffset*tou + md_fVOffset*tov); + mvDst.mv_vU = mvSrc.mv_vU*uos + mvSrc.mv_vV*uot; + mvDst.mv_vV = mvSrc.mv_vU*vos + mvSrc.mv_vV*vot; +} + +// transform default mapping vectors to mapping vectors for this mapping +void CMappingDefinition::TransformMappingVectors( const CMappingVectors &mvSrc, CMappingVectors &mvDst) const +{ + const FLOAT uos = md_fUoS; + const FLOAT uot = md_fUoT; + const FLOAT vos = md_fVoS; + const FLOAT vot = md_fVoT; + mvDst.mv_vU = mvSrc.mv_vU*uos + mvSrc.mv_vV*uot; + mvDst.mv_vV = mvSrc.mv_vU*vos + mvSrc.mv_vV*vot; + + { + FLOAT sou2 = mvDst.mv_vU%mvDst.mv_vU; + FLOAT sov2 = mvDst.mv_vV%mvDst.mv_vU; + FLOAT tou2 = mvDst.mv_vU%mvDst.mv_vV; + FLOAT tov2 = mvDst.mv_vV%mvDst.mv_vV; + + FLOAT ood2 = 1/(sou2*tov2-sov2*tou2); + FLOAT uos2 = +tov2*ood2; FLOAT uot2 = -sov2*ood2; + FLOAT vot2 = +sou2*ood2; FLOAT vos2 = -tou2*ood2; + + mvDst.mv_vO = mvSrc.mv_vO + + mvDst.mv_vU * (md_fUOffset*uos2 + md_fVOffset*vos2) + + mvDst.mv_vV * (md_fUOffset*vos2 + md_fVOffset*vot2); + } +} + +// convert to mapping vectors +void CMappingDefinition::ToMappingVectors( const CMappingVectors &mvDefault, CMappingVectors &mvVectors) const +{ + const FLOAT uos = md_fUoS; + const FLOAT uot = md_fUoT; + const FLOAT vos = md_fVoS; + const FLOAT vot = md_fVoT; + const FLOAT ood = 1.0f /(uos*vot-uot*vos); + const FLOAT sou = +vot*ood; const FLOAT sov = -uot*ood; + const FLOAT tov = +uos*ood; const FLOAT tou = -vos*ood; + mvVectors.mv_vO = mvDefault.mv_vO + + mvDefault.mv_vU * (md_fUOffset*sou + md_fVOffset*sov) + + mvDefault.mv_vV * (md_fUOffset*tou + md_fVOffset*tov); + mvVectors.mv_vU = mvDefault.mv_vU*sou + mvDefault.mv_vV*tou; + mvVectors.mv_vV = mvDefault.mv_vU*sov + mvDefault.mv_vV*tov; +} + +// convert from mapping vectors +void CMappingDefinition::FromMappingVectors( + const CMappingVectors &mvDefault, const CMappingVectors &mvVectors) +{ + FLOAT sou = mvVectors.mv_vU%mvDefault.mv_vU; + FLOAT sov = mvVectors.mv_vV%mvDefault.mv_vU; + FLOAT tou = mvVectors.mv_vU%mvDefault.mv_vV; + FLOAT tov = mvVectors.mv_vV%mvDefault.mv_vV; + + FLOAT ood = 1/(sou*tov-sov*tou); + FLOAT uos = +tov*ood; FLOAT uot = -sov*ood; + FLOAT vot = +sou*ood; FLOAT vos = -tou*ood; + + md_fUoS = uos; + md_fUoT = uot; + md_fVoS = vos; + md_fVoT = vot; + + FLOAT3D vOffset = mvVectors.mv_vO-mvDefault.mv_vO; + FLOAT s = vOffset%mvDefault.mv_vU; + FLOAT t = vOffset%mvDefault.mv_vV; + + md_fUOffset = uos*s+uot*t; + md_fVOffset = vos*s+vot*t; +} + + +// convert from old version of texture mapping defintion +void CMappingDefinition::ReadOld_t(CTStream &strm) // throw char * +{ + // old texture mapping orientation and offsets structure + // - obsolete - used only for loading old worlds + class CTextureMapping_old { + public: + ULONG tm_ulFlags; // flags + ANGLE tm_aRotation; // angle of texture rotation + FLOAT tm_fOffsetU; // texture offsets (in meters) + FLOAT tm_fOffsetV; + } tmo; + strm.Read_t(&tmo, sizeof(tmo)); + + FLOAT fSin = Sin(tmo.tm_aRotation); + FLOAT fCos = Cos(tmo.tm_aRotation); + + md_fUOffset = -tmo.tm_fOffsetU; + md_fVOffset = -tmo.tm_fOffsetV; + md_fUoS = +fCos; + md_fUoT = -fSin; + md_fVoS = +fSin; + md_fVoT = +fCos; +} + +/* Find texture coordinates for an object-space point. */ +void CMappingDefinition::GetTextureCoordinates( + const CMappingVectors &mvDefault, const FLOAT3D &vSpace, MEX2D &vTexture) const +{ + FLOAT3D vOffset = vSpace-mvDefault.mv_vO; + FLOAT s = mvDefault.mv_vU%vOffset; + FLOAT t = mvDefault.mv_vV%vOffset; + FLOAT u = s*md_fUoS+t*md_fUoT; + FLOAT v = s*md_fVoS+t*md_fVoT; + + vTexture(1) = FloatToInt((u+md_fUOffset)*1024.0f); + vTexture(2) = FloatToInt((v+md_fVOffset)*1024.0f); +} +/* Find object-space coordinates for a texture point. */ +void CMappingDefinition::GetSpaceCoordinates( + const CMappingVectors &mvDefault, const MEX2D &vTexture, FLOAT3D &vSpace) const +{ + FLOAT uos = md_fUoS; + FLOAT uot = md_fUoT; + FLOAT vos = md_fVoS; + FLOAT vot = md_fVoT; + + FLOAT ood = 1/(uos*vot-uot*vos); + FLOAT sou = +vot*ood; FLOAT sov = -uot*ood; + FLOAT tov = +uos*ood; FLOAT tou = -vos*ood; + + FLOAT u = (vTexture(1)/1024.0f)+md_fUOffset; + FLOAT v = (vTexture(2)/1024.0f)+md_fVOffset; + FLOAT s = u*sou+v*sov; + FLOAT t = u*tou+v*tov; + + vSpace = mvDefault.mv_vO+mvDefault.mv_vU*s+mvDefault.mv_vV*t; +} +// project another mapping on this one +void CMappingDefinition::ProjectMapping(const FLOATplane3D &plOriginal, const CMappingDefinition &mdOriginal, + const FLOATplane3D &pl) +{ + // make original mapping vectors + CMappingVectors mvDefaultOrg; + mvDefaultOrg.FromPlane(plOriginal); + CMappingVectors mvOriginal; + mdOriginal.ToMappingVectors(mvDefaultOrg, mvOriginal); + + // transform them to this plane + CMappingVectors mv; + mv.mv_vO = pl.DeprojectPoint (plOriginal, mvOriginal.mv_vO); + mv.mv_vU = pl.DeprojectDirection(plOriginal, mvOriginal.mv_vU); + mv.mv_vV = pl.DeprojectDirection(plOriginal, mvOriginal.mv_vV); + FLOAT3D vOTest = plOriginal.ProjectPoint(mv.mv_vO); + FLOAT3D vUTest = plOriginal.ProjectDirection(mv.mv_vU); + FLOAT3D vVTest = plOriginal.ProjectDirection(mv.mv_vV); + + // make mapping on this plane + CMappingVectors mvDefault; + mvDefault.FromPlane(pl); + FromMappingVectors(mvDefault, mv); +} +// translate mapping in 3D +void CMappingDefinition::Translate(const CMappingVectors &mvDefault, const FLOAT3D &vTranslation) +{ + FLOATplane3D plPlane; + mvDefault.ToPlane(plPlane); + // make mapping vectors + CMappingVectors mv; + ToMappingVectors(mvDefault, mv); + // translate mapping origin + mv.mv_vO+=plPlane.ProjectDirection(vTranslation); + // convert back from new mapping vectors + FromMappingVectors(mvDefault, mv); +} +// rotate mapping in 3D +void CMappingDefinition::Rotate(const CMappingVectors &mvDefault, + const FLOAT3D &vRotationOrigin, ANGLE aRotation) +{ + FLOATplane3D plPlane; + mvDefault.ToPlane(plPlane); + // project rotation origin to the plane + FLOAT3D vProjectedRotationOrigin = plPlane.ProjectPoint(vRotationOrigin); + // get texture coordinates of the origin before rotation + MEX2D vmexRotationOrigin0; + GetTextureCoordinates(mvDefault, vProjectedRotationOrigin, vmexRotationOrigin0); + // rotate the mapping + CMappingDefinitionUI mdui; + ToUI(mdui); + mdui.mdui_aURotation+=aRotation; + mdui.mdui_aVRotation+=aRotation; + FromUI(mdui); + // get texture coordinates of the origin after rotation + MEX2D vmexRotationOrigin1; + GetTextureCoordinates(mvDefault, vProjectedRotationOrigin, vmexRotationOrigin1); + // adjust texture offsets so that origin stays on same place in texture + md_fUOffset += (vmexRotationOrigin1(1)-vmexRotationOrigin0(1))/1024.0f; + md_fVOffset += (vmexRotationOrigin1(2)-vmexRotationOrigin0(2))/1024.0f; +} +// center mapping to given point in 3D +void CMappingDefinition::Center(const CMappingVectors &mvDefault, + const FLOAT3D &vNewOrigin) +{ + FLOATplane3D plPlane; + mvDefault.ToPlane(plPlane); + // make mapping vectors + CMappingVectors mv; + ToMappingVectors(mvDefault, mv); + // set new mapping origin + mv.mv_vO=plPlane.ProjectPoint(vNewOrigin); + // convert back from new mapping vectors + FromMappingVectors(mvDefault, mv); +} +// transform mapping from one placement to another +void CMappingDefinition::Transform(const FLOATplane3D &plSourcePlane, + const CPlacement3D &plSource, const CPlacement3D &plTarget) +{ + CSimpleProjection3D_DOUBLE prProjection; + prProjection.ObjectPlacementL() = plSource; + prProjection.ViewerPlacementL() = plTarget; + prProjection.Prepare(); + CMappingDefinition mdTarget; + prProjection.ProjectMapping(*this, FLOATtoDOUBLE(plSourcePlane), mdTarget); + *this = mdTarget; +} + +// stream operations +CTStream &operator>>(CTStream &strm, CMappingDefinition &md) +{ + strm.Read_t(&md, sizeof(md)); + return strm; +} +CTStream &operator<<(CTStream &strm, const CMappingDefinition &md) +{ + strm.Write_t(&md, sizeof(md)); + return strm; +} + diff --git a/Sources/Engine/Math/TextureMapping.h b/Sources/Engine/Math/TextureMapping.h new file mode 100644 index 0000000..51a2127 --- /dev/null +++ b/Sources/Engine/Math/TextureMapping.h @@ -0,0 +1,157 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TEXTUREMAPPING_H +#define SE_INCL_TEXTUREMAPPING_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* General coordinate naming notes: + * s,t are texture coordinates in default mapping on a plane + * +s=right + * +t=down + * u,v are texture coordinates in mapping on a polygon + * +u=right + * +v=down + * i,j are coordinates on screen + * +i=right + * +j=down + * k is distance from screen normalized to be in interval [1,+inf> + * +1= near clip plane + * +inf= far away (infinity) (not normalized to far clip plane!) + * x,y,z are coordinates in 3D + * +x=right + * +y=up + * -z=front + */ + +/* + * Gradients for a variable lineary interpolated along the screen. + */ +class CPlanarGradients { +public: + FLOAT pg_f00; // value at upper left corner + FLOAT pg_fDOverDI; // horizontal gradient + FLOAT pg_fDOverDJ; // vertical gradient +public: + // calculate value at some point on screen (i,j) + inline FLOAT GetValue(FLOAT fI, FLOAT fJ) { + return pg_f00 + pg_fDOverDI*fI + pg_fDOverDJ*fJ; + }; + // set constant gradients + inline void Constant(FLOAT fConst) { + pg_f00 = fConst; + pg_fDOverDI = 0; + pg_fDOverDJ = 0; + } + // multiply gradients by given factor + inline void Multiply(FLOAT fMul) { + pg_f00 *= fMul; + pg_fDOverDI *= fMul; + pg_fDOverDJ *= fMul; + }; + // add given constant to gradients + inline void Add(FLOAT fAdd) { + pg_f00 += fAdd; + }; + // translate gradients in screen space + inline void TranslateOnScreen(FLOAT fI, FLOAT fJ) { + pg_f00 += pg_fDOverDI*fI + pg_fDOverDJ*fJ; + }; +}; + +/* + * Description of texture mapping on a polygon relative to default mapping for its plane, + * version used to communicating information to user. + */ +class ENGINE_API CMappingDefinitionUI { +public: + ANGLE mdui_aURotation;// rotation angle of u axis from s axis + ANGLE mdui_aVRotation;// rotation angle of v axis from t axis + FLOAT mdui_fUStretch; // stretch in u direction + FLOAT mdui_fVStretch; // stretch in v direction + FLOAT mdui_fUOffset; // offset in u direction + FLOAT mdui_fVOffset; // offset in v direction +}; + +/* + * Vectors defining a transformed mapping on a plane. + */ +class ENGINE_API CMappingVectors { +public: + FLOAT3D mv_vO; // origin + FLOAT3D mv_vU; // u axis direction + FLOAT3D mv_vV; // v axis direction + + // calculate default texture mapping control points from a plane + void FromPlane(const FLOATplane3D &plPlane); + void FromPlane_DOUBLE(const DOUBLEplane3D &plPlane); + // calculate plane from default mapping vectors + void ToPlane(FLOATplane3D &plPlane) const; +}; + +/* + * Description of texture mapping on a polygon relative to default mapping for its plane. + */ +class ENGINE_API CMappingDefinition { +public: + FLOAT md_fUoS; // u vector relative to default mapping + FLOAT md_fUoT; + FLOAT md_fVoS; // v vector relative to default mapping + FLOAT md_fVoT; + FLOAT md_fUOffset; // offset in u direction + FLOAT md_fVOffset; // offset in v direction + + // default constructor + inline CMappingDefinition(void) : + md_fUoS(1), md_fUoT(0), + md_fVoS(0), md_fVoT(1), + md_fUOffset(0), md_fVOffset(0) {}; + + // convert to human-friendly format + void ToUI(CMappingDefinitionUI &mdui) const; + // convert from human-friendly format + void FromUI(const CMappingDefinitionUI &mdui); + + // convert to mapping vectors + void ToMappingVectors(const CMappingVectors &mvDefault, CMappingVectors &mvVectors) const; + // convert from mapping vectors + void FromMappingVectors(const CMappingVectors &mvDefault, const CMappingVectors &mvVectors); + // make mapping vectors for this mapping + void MakeMappingVectors(const CMappingVectors &mvSrc, CMappingVectors &mvDst) const; + // transform default mapping vectors to mapping vectors for this mapping + void TransformMappingVectors(const CMappingVectors &mvSrc, CMappingVectors &mvDst) const; + + // project another mapping on this one + void ProjectMapping(const FLOATplane3D &plOriginal, const CMappingDefinition &mdOriginal, + const FLOATplane3D &pl); + + // translate mapping in 3D + void Translate(const CMappingVectors &mvDefault, const FLOAT3D &vTranslation); + // rotate mapping in 3D + void Rotate(const CMappingVectors &mvDefault, const FLOAT3D &vRotationOrigin, ANGLE aRotation); + // center mapping to given point in 3D + void Center(const CMappingVectors &mvDefault, const FLOAT3D &vNewOrigin); + // transform mapping from one placement to another + void Transform(const FLOATplane3D &plPlane, + const class CPlacement3D &plSource, const class CPlacement3D &plTarget); + + // convert from old version of texture mapping defintion + void ReadOld_t(CTStream &strm); // throw char * + // find texture coordinates for an object-space point + void GetTextureCoordinates( + const CMappingVectors &mvDefault, const FLOAT3D &vSpace, MEX2D &vTexture) const; + // find object-space coordinates for a texture point + void GetSpaceCoordinates( + const CMappingVectors &mvDefault, const MEX2D &vTexture, FLOAT3D &vSpace) const; +}; + +// stream operations +ENGINE_API CTStream &operator>>(CTStream &strm, CMappingDefinition &md); // throw char * +ENGINE_API CTStream &operator<<(CTStream &strm, const CMappingDefinition &md); // throw char * + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Math/Vector.h b/Sources/Engine/Math/Vector.h new file mode 100644 index 0000000..6004008 --- /dev/null +++ b/Sources/Engine/Math/Vector.h @@ -0,0 +1,561 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_VECTOR_H +#define SE_INCL_VECTOR_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* + * Template class for vector of arbitrary dimensions and arbitrary type of members + */ +template +class Vector { +public: + Type vector[iDimensions]; // array that holds the members +public: + /* Default constructor. */ + __forceinline Vector(void); + /* Constructor from coordinates. */ + __forceinline Vector(Type x1); + __forceinline Vector(Type x1, Type x2); + __forceinline Vector(Type x1, Type x2, Type x3); + __forceinline Vector(Type x1, Type x2, Type x3, Type x4); + /* Clear function */ + __forceinline void Clear(void) {}; + + + /* Conversion into scalar -- length of vector (Euclidian norm). */ + __forceinline Type Length(void) const; + /* Conversion into scalar -- Manhattan norm of vector. */ + __forceinline Type ManhattanNorm(void) const; + /* Conversion into scalar -- Max norm of vector. */ + __forceinline Type MaxNorm(void) const; + + /* Reference vector member by it's index (1-based indices!). */ + __forceinline Type &operator()(int i); + __forceinline const Type &operator()(int i) const; + + /* Normalize vector, i.e. make it a unit vector. */ + __forceinline Vector &Normalize(void); + __forceinline Vector &SafeNormalize(void); // gives vector with (0,0,0) orientation if input is too small + + /* Mathematical operators. */ + // unary minus + __forceinline Vector &Flip(void); + __forceinline Vector operator-(void) const; + // between two vectors + __forceinline Vector operator+(const Vector &vector2) const; + __forceinline Vector &operator+=(const Vector &vector2); + __forceinline Vector operator-(const Vector &vector2) const; + __forceinline Vector &operator-=(const Vector &vector2); + // multiplication with scalar + __forceinline Vector &operator*=(const Type scalar); + __forceinline Vector operator*(const Type scalar) const; + // division with scalar + __forceinline Vector &operator/=(const Type scalar); + __forceinline Vector operator/(const Type scalar) const; + // multiplication by a square matrix (sides swapped -- see implementation for notes) + __forceinline Vector &operator*=(const Matrix &matrix2); + __forceinline Vector operator*(const Matrix &matrix2) const; + // scalar product - dot product, inner product + __forceinline Type operator%(const Vector &vector2) const; + // vector product - cross product, outer product + __forceinline Vector &operator*=(const Vector &vector2); + __forceinline Vector operator*(const Vector &vector2) const; + // comparing vectors + __forceinline BOOL operator==(const Vector &vector2) const; + __forceinline BOOL operator!=(const Vector &vector2) const; + + /* Stream operations */ + friend __forceinline CTStream &operator>>(CTStream &strm, Vector &vector) { + strm.Read_t(&vector, sizeof(vector)); + return strm; + } + friend __forceinline CTStream &operator<<(CTStream &strm, Vector &vector) { + strm.Write_t(&vector, sizeof(vector)); + return strm; + } +}; + + +// inline functions implementation + +/* + * Default constructor. + */ +template +__forceinline Vector::Vector(void) {} + + +/* + * Constructor from coordinates. + */ +template +__forceinline Vector::Vector(Type x1) +{ + ASSERT(iDimensions==1); + (*this)(1)=x1; +} + +template +__forceinline Vector::Vector(Type x1, Type x2) +{ + ASSERT(iDimensions==2); + (*this)(1)=x1; + (*this)(2)=x2; +} + +template +__forceinline Vector::Vector(Type x1, Type x2, Type x3) +{ + ASSERT(iDimensions==3); + (*this)(1)=x1; + (*this)(2)=x2; + (*this)(3)=x3; +} + +template +__forceinline Vector::Vector(Type x1, Type x2, Type x3, Type x4) +{ + ASSERT(iDimensions==4); + (*this)(1)=x1; + (*this)(2)=x2; + (*this)(3)=x3; + (*this)(4)=x4; +} + + +/* + * Conversion into scalar -- length of vector. + */ +__forceinline FLOAT Vector::Length(void) const +{ + return (FLOAT)sqrt( (DOUBLE)((*this)(1)*(*this)(1) + (*this)(2)*(*this)(2) + (*this)(3)*(*this)(3))); +} + +__forceinline DOUBLE Vector::Length(void) const +{ + return (DOUBLE)sqrt( (DOUBLE)((*this)(1)*(*this)(1) + (*this)(2)*(*this)(2) + (*this)(3)*(*this)(3))); +} + +template +__forceinline Type Vector::Length(void) const +{ + Type result=(Type)0; + for(int i=1; i<=iDimensions; i++) { + result += (*this)(i) * (*this)(i); + } + return (Type)sqrt((DOUBLE)result); +} + +/* + * Conversion into scalar -- Manhattan norm of vector. + */ + +template +__forceinline Type Vector::ManhattanNorm(void) const +{ + Type result=(Type)0; + for(int i=1; i<=iDimensions; i++) { + result += Abs((*this)(i)); + } + return result; +} + +/* + * Conversion into scalar -- Max norm of vector. + */ +template +__forceinline Type Vector::MaxNorm(void) const +{ + Type result=(Type)0; + for(int i=1; i<=iDimensions; i++) { + result = Max(result, Abs((*this)(i))); + } + return result; +} + +/* + * Reference vector member by it's index (1-based indices!). + */ +template +__forceinline Type &Vector::operator()(int i) +{ + // check boundaries (indices start at 1, not at 0) + ASSERT(i>=1 && i<=iDimensions); + // return vector member reference + return vector[i-1]; +} + +template +__forceinline const Type &Vector::operator()(int i) const +{ + // check boundaries (indices start at 1, not at 0) + ASSERT(i>=1 && i<=iDimensions); + // return vector member reference + return vector[i-1]; +} + +/* + * Normalize vector, i.e. make it a unit vector. + */ +template +__forceinline Vector &Vector::Normalize(void) +{ + // Normalizing a vector of a very small length can be very unprecise! + // ASSERT(((Type)*this) > 0.001); + *this/=Length(); + return *this; +} +// gives vector with (0,0,0) orientation if input is too small +template +__forceinline Vector &Vector::SafeNormalize(void) +{ + Type tLen = Length(); + if (tLen<1E-6) { + if (iDimensions==2) { + *this = Vector(1,0); + } else { + *this = Vector(0,0,-1); + } + } else { + *this/=tLen; + } + return *this; +} + + +// unary minus FLOAT3D +__forceinline Vector &Vector::Flip(void) +{ + (*this)(1) = -(*this)(1); + (*this)(2) = -(*this)(2); + (*this)(3) = -(*this)(3); + return *this; +} + +// unary minus DOUBLE3D +__forceinline Vector &Vector::Flip(void) +{ + (*this)(1) = -(*this)(1); + (*this)(2) = -(*this)(2); + (*this)(3) = -(*this)(3); + return *this; +} + +// unary minus +template +__forceinline Vector &Vector::Flip(void) +{ + // flip member by member + ASSERT( iDimensions!=3); // 3 is optimized special case + for(int iDimension=1; iDimension<=iDimensions; iDimension++) { + (*this)(iDimension) = -(*this)(iDimension); + } + return *this; +} + +template +__forceinline Vector Vector::operator-(void) const +{ + return Vector(*this).Flip(); +} + + +// sum of two vectors FLOAT3D +__forceinline Vector &Vector::operator+=(const Vector &vector2) +{ + // add member by member + (*this)(1) += vector2(1); + (*this)(2) += vector2(2); + (*this)(3) += vector2(3); + return *this; +} + +// sum of two vectors DOUBLE3D +__forceinline Vector &Vector::operator+=(const Vector &vector2) +{ + // add member by member + (*this)(1) += vector2(1); + (*this)(2) += vector2(2); + (*this)(3) += vector2(3); + return *this; +} + +// sum of two vectors +template +__forceinline Vector &Vector::operator+=(const Vector &vector2) +{ + // add member by member + ASSERT( iDimensions!=3); // 3 is optimized special case + for(int iDimension=1; iDimension<=iDimensions; iDimension++) { + (*this)(iDimension) += vector2(iDimension); + } + return *this; +} + +template +__forceinline Vector Vector::operator+(const Vector &vector2) const +{ + return Vector(*this)+=vector2; +} + + +// difference of two vectors FLOAT3D +__forceinline Vector &Vector::operator-=(const Vector &vector2) +{ + // add member by member + (*this)(1) -= vector2(1); + (*this)(2) -= vector2(2); + (*this)(3) -= vector2(3); + return *this; +} + +// difference of two vectors DOUBLE3D +__forceinline Vector &Vector::operator-=(const Vector &vector2) +{ + // add member by member + (*this)(1) -= vector2(1); + (*this)(2) -= vector2(2); + (*this)(3) -= vector2(3); + return *this; +} + +// difference of two vectors +template +__forceinline Vector &Vector::operator-=(const Vector &vector2) +{ + // sub member by member + ASSERT( iDimensions!=3); // 3 is optimized special case + for(int iDimension=1; iDimension<=iDimensions; iDimension++) { + (*this)(iDimension) -= vector2(iDimension); + } + return *this; +} + +template +__forceinline Vector Vector::operator-(const Vector &vector2) const +{ + return Vector(*this)-=vector2; +} + + + +// multiplication with scalar FLOAT3D +__forceinline Vector &Vector::operator*=(const FLOAT scalar) +{ + (*this)(1) *= scalar; + (*this)(2) *= scalar; + (*this)(3) *= scalar; + return *this; +} + +// multiplication with scalar DOUBLE3D +__forceinline Vector &Vector::operator*=(const DOUBLE scalar) +{ + (*this)(1) *= scalar; + (*this)(2) *= scalar; + (*this)(3) *= scalar; + return *this; +} + +// multiplication with scalar +template +__forceinline Vector &Vector::operator*=(const Type scalar) +{ + ASSERT( iDimensions!=3); // 3 is optimized special case + for( int i=1; i<=iDimensions; i++) (*this)(i) *= scalar; + return *this; +} + +template +__forceinline Vector Vector::operator*(const Type scalar) const +{ + return Vector(*this) *= scalar; +} + + +// division with scalar FLOAT3D +__forceinline Vector &Vector::operator/=(const FLOAT scalar) +{ + const FLOAT rcp = 1.0f/scalar; + (*this)(1) *= rcp; + (*this)(2) *= rcp; + (*this)(3) *= rcp; + return *this; +} + +// division with scalar DOUBLE3D +__forceinline Vector &Vector::operator/=(const DOUBLE scalar) +{ + const DOUBLE rcp = 1.0/scalar; + (*this)(1) *= rcp; + (*this)(2) *= rcp; + (*this)(3) *= rcp; + return *this; +} + + +// division with scalar +template +__forceinline Vector &Vector::operator/=(const Type scalar) +{ + ASSERT( iDimensions!=3); // 3 is optimized special case + for( int i=1; i<=iDimensions; i++) (*this)(i) /= scalar; + return *this; +} + +template +__forceinline Vector Vector::operator/(const Type scalar) const +{ + return Vector(*this) /= scalar; +} + + +/* + * Multiplication of a vector by a square matrix. + */ +// NOTE: The matrix should have been on the left side of the vector, but the template syntax wouldn't allow that. + +__forceinline Vector Vector::operator*(const Matrix &matrix2) const +{ + Vector result; + result(1) = matrix2(1,1) * (*this)(1) + matrix2(1,2) * (*this)(2) + matrix2(1,3) * (*this)(3); + result(2) = matrix2(2,1) * (*this)(1) + matrix2(2,2) * (*this)(2) + matrix2(2,3) * (*this)(3); + result(3) = matrix2(3,1) * (*this)(1) + matrix2(3,2) * (*this)(2) + matrix2(3,3) * (*this)(3); + return result; +} + +__forceinline Vector Vector::operator*(const Matrix &matrix2) const +{ + Vector result; + result(1) = matrix2(1,1) * (*this)(1) + matrix2(1,2) * (*this)(2) + matrix2(1,3) * (*this)(3); + result(2) = matrix2(2,1) * (*this)(1) + matrix2(2,2) * (*this)(2) + matrix2(2,3) * (*this)(3); + result(3) = matrix2(3,1) * (*this)(1) + matrix2(3,2) * (*this)(2) + matrix2(3,3) * (*this)(3); + return result; +} + +template +__forceinline Vector &Vector::operator*=(const Matrix &matrix2) +{ + (*this) = (*this) * matrix2; + return *this; +} + +template +__forceinline Vector Vector::operator*(const Matrix &matrix2) const +{ + ASSERT( iDimensions!=3); // 3 is optimized special case + Vector result; + for(int iRow=1; iRow<=iDimensions; iRow++) { + result(iRow) = (Type)0; + for(int s=1; s<=iDimensions; s++) { + result(iRow) += matrix2(iRow, s) * (*this)(s); + } + } + return result; +} + + +// scalar product - dot product, inner product for FLOAT3D +__forceinline FLOAT Vector::operator%(const Vector &vector2) const +{ + return (FLOAT)((*this)(1)*vector2(1) + (*this)(2)*vector2(2) + (*this)(3)*vector2(3)); +} + +// scalar product - dot product, inner product for DOUBLE3D +__forceinline DOUBLE Vector::operator%(const Vector &vector2) const +{ + return (DOUBLE)((*this)(1)*vector2(1) + (*this)(2)*vector2(2) + (*this)(3)*vector2(3)); +} + +// scalar product - dot product, inner product +template +__forceinline Type Vector::operator%(const Vector &vector2) const +{ + ASSERT( iDimensions!=3); // 3 is optimized special case + Type result=(Type)0; + for(int i=1; i<=iDimensions; i++) { + result += (*this)(i) * vector2(i); + } + return result; +} + + + +// vector product - cross product, outer product +/* Formula: C=A*B + Cx = Ay*Bz - Az*By + Cy = Az*Bx - Ax*Bz + Cz = Ax*By - Ay*Bx +*/ +template +__forceinline Vector &Vector::operator*=(const Vector &vector2) +{ + (*this) = (*this) * vector2; + return *this; +} + +template +__forceinline Vector Vector::operator*(const Vector &vector2) const +{ + Vector result; + ASSERT(iDimensions==3); // cross product is defined only for 3D vectors + result(1) = (*this)(2)*vector2(3) - (*this)(3)*vector2(2); + result(2) = (*this)(3)*vector2(1) - (*this)(1)*vector2(3); + result(3) = (*this)(1)*vector2(2) - (*this)(2)*vector2(1); + return result; +} + + +// comparation FLOAT3D +__forceinline BOOL Vector::operator==(const Vector &vector2) const +{ + return( (*this)(1)==vector2(1) && (*this)(2)==vector2(2) && (*this)(3)==vector2(3)); +} + +// comparation DOUBLE3D +__forceinline BOOL Vector::operator==(const Vector &vector2) const +{ + return( (*this)(1)==vector2(1) && (*this)(2)==vector2(2) && (*this)(3)==vector2(3)); +} + +// comparation +template +__forceinline BOOL Vector::operator==(const Vector &vector2) const +{ + ASSERT( iDimensions!=3); // 3 is optimized special case + for(int i=1; i<=iDimensions; i++) { + if( (*this)(i) != vector2(i)) + return FALSE; + } + return TRUE; +} + + +template +__forceinline BOOL Vector::operator!=(const Vector &vector2) const +{ + return !(*this == vector2); +} + + +// helper functions for converting between FLOAT and DOUBLE vectors +__forceinline DOUBLE3D FLOATtoDOUBLE(const FLOAT3D &vf) +{ + return DOUBLE3D(FLOATtoDOUBLE(vf(1)), FLOATtoDOUBLE(vf(2)), FLOATtoDOUBLE(vf(3))); +} + +__forceinline FLOAT3D DOUBLEtoFLOAT(const DOUBLE3D &vd) +{ + return FLOAT3D(DOUBLEtoFLOAT(vd(1)), DOUBLEtoFLOAT(vd(2)), DOUBLEtoFLOAT(vd(3))); +} + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Models/EditModel.cpp b/Sources/Engine/Models/EditModel.cpp new file mode 100644 index 0000000..8fb0a06 --- /dev/null +++ b/Sources/Engine/Models/EditModel.cpp @@ -0,0 +1,2889 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// Globally instanciated object containing routines for dealing with progres messages +CProgressRoutines ProgresRoutines; + +// constants important to this module +#define MAX_ALLOWED_DISTANCE 0.0001f + +#define PC_ALLWAYS_ON (1UL << 30) +#define PC_ALLWAYS_OFF (1UL << 31) + + +// origin triangle for transforming object +INDEX aiTransVtx[3] = {-1,-1,-1}; + +class CExtractSurfaceVertex +{ +public: + INDEX esv_Surface; + SLONG esv_TextureVertexRemap; + INDEX esv_MipGlobalIndex; +}; + +CThumbnailSettings::CThumbnailSettings( void) +{ + ts_bSet = FALSE; +} + +void CThumbnailSettings::Read_t( CTStream *strFile) +{ + *strFile>>ts_bSet; + *strFile>>ts_plLightPlacement; + *strFile>>ts_plModelPlacement; + *strFile>>ts_fTargetDistance; + *strFile>>ts_vTarget; + *strFile>>ts_angViewerOrientation; + *strFile>>ts_LightDistance; + *strFile>>ts_LightColor; + *strFile>>ts_colAmbientColor; + *strFile>>ts_PaperColor; + *strFile>>ts_InkColor; + *strFile>>ts_IsWinBcgTexture; + *strFile>>ts_WinBcgTextureName; + ts_RenderPrefs.Read_t( strFile); +} + +void CThumbnailSettings::Write_t( CTStream *strFile) +{ + *strFile<tdi_TextureData != NULL); + _pTextureStock->Release( litDel3->tdi_TextureData); + delete &litDel3.Current(); + } +} + +CProgressRoutines::CProgressRoutines() +{ + SetProgressMessage = NULL; + SetProgressRange = NULL; + SetProgressState = NULL; +} + + +//---------------------------------------------------------------------------------------------- +/* + * This routine loads animation data from opened model script file and converts loaded data + * to model's frame vertices format + */ + +struct VertexNeighbors { CStaticStackArray vp_aiNeighbors; }; + +void CEditModel::LoadModelAnimationData_t( CTStream *pFile, const FLOATmatrix3D &mStretch) // throw char * +{ + try { + CObject3D::BatchLoading_t(TRUE); + + INDEX i; + CObject3D OB3D; + CListHead FrameNamesList; + FLOATaabbox3D OneFrameBB; + FLOATaabbox3D AllFramesBB; + + INDEX ctFramesBefore = edm_md.md_FramesCt; + edm_md.ClearAnimations(); + + OB3D.ob_aoscSectors.Lock(); + // there must be at least one mip model loaded, throw if not + if( edm_md.md_VerticesCt == 0) { + throw( "Trying to update model's animations, but model doesn't exists!"); + } + edm_md.LoadFromScript_t( pFile, &FrameNamesList); // load model's animation data from script + + // if recreating animations, frame count must be the same + if( (ctFramesBefore != 0) && (FrameNamesList.Count() != ctFramesBefore) ) + { + throw( "If you are updating animations, you can't change number of frames. \ + If you want to add or remove some frames or animations, please recreate the model."); + } + edm_md.md_FramesCt = FrameNamesList.Count(); + + /* + * Now we will allocate frames and frames info array and array od 3D objects, + * one for each frame. + */ + + if( ProgresRoutines.SetProgressMessage != NULL) { + ProgresRoutines.SetProgressMessage( "Calculating bounding boxes ..."); + } + if( ProgresRoutines.SetProgressRange != NULL) { + ProgresRoutines.SetProgressRange( FrameNamesList.Count()); + } + + edm_md.md_FrameInfos.New( edm_md.md_FramesCt); + if( edm_md.md_Flags & MF_COMPRESSED_16BIT) { + edm_md.md_FrameVertices16.New( edm_md.md_FramesCt * edm_md.md_VerticesCt); + } else { + edm_md.md_FrameVertices8.New( edm_md.md_FramesCt * edm_md.md_VerticesCt); + } + + INDEX iO3D = 0; // index used for progress dialog + CStaticStackArray avVertices; // for caching all vertices in all frames + + BOOL bOrigin = FALSE; + FLOATmatrix3D mOrientation; + // set bOrigin if aiTransVtx is valid + if((aiTransVtx[0] >=0) && (aiTransVtx[1] >=0) && (aiTransVtx[2] >=0)) + { + bOrigin = TRUE; + } + + {FOREACHINLIST( CFileNameNode, cfnn_Node, FrameNamesList, itFr) + { + CFileNameNode &fnnFileNameNode = itFr.Current(); + if( ProgresRoutines.SetProgressState != NULL) ProgresRoutines.SetProgressState(iO3D); + OB3D.Clear(); + OB3D.LoadAny3DFormat_t( CTString(itFr->cfnn_FileName), mStretch); + if( edm_md.md_VerticesCt != OB3D.ob_aoscSectors[0].osc_aovxVertices.Count()) { + ThrowF_t( "File %s, one of animation frame files has wrong number of points.", + (CTString)fnnFileNameNode.cfnn_FileName); + } + if(bOrigin) + { + // calc matrix for vertex transform + FLOAT3D vY = DOUBLEtoFLOAT(OB3D.ob_aoscSectors[0].osc_aovxVertices[aiTransVtx[2]]-OB3D.ob_aoscSectors[0].osc_aovxVertices[aiTransVtx[0]]); + FLOAT3D vZ = DOUBLEtoFLOAT(OB3D.ob_aoscSectors[0].osc_aovxVertices[aiTransVtx[0]]-OB3D.ob_aoscSectors[0].osc_aovxVertices[aiTransVtx[1]]); + FLOAT3D vX = vY*vZ; + vY = vZ*vX; + // make a rotation matrix from those vectors + vX.Normalize(); + vY.Normalize(); + vZ.Normalize(); + + mOrientation(1,1) = vX(1); mOrientation(1,2) = vY(1); mOrientation(1,3) = vZ(1); + mOrientation(2,1) = vX(2); mOrientation(2,2) = vY(2); mOrientation(2,3) = vZ(2); + mOrientation(3,1) = vX(3); mOrientation(3,2) = vY(3); mOrientation(3,3) = vZ(3); + mOrientation = !mOrientation; + } + + // normalize (clear) our Bounding Box + OB3D.ob_aoscSectors[0].LockAll(); + OneFrameBB = FLOATaabbox3D(); + // Bounding Box makes union with all points in this frame + for( i=0; i avnVertices; + avnVertices.New( edm_md.md_VerticesCt); + + // lost 1st frame (one frame is enough because all frames has same poly->edge->vertex links) + OB3D.Clear(); + const CTString &fnmFirstFrame = LIST_HEAD( FrameNamesList, CFileNameNode, cfnn_Node)->cfnn_FileName; + OB3D.LoadAny3DFormat_t( fnmFirstFrame, mStretch); + OB3D.ob_aoscSectors[0].LockAll(); + + // loop thru polygons + INDEX iPolyNo=0; + {FOREACHINDYNAMICARRAY( OB3D.ob_aoscSectors[0].osc_aopoPolygons, CObjectPolygon, itPoly) + { + CObjectPolygon &opo = *itPoly; + // only triangles are supported! + ASSERT( opo.opo_PolygonEdges.Count() == 3); + if( opo.opo_PolygonEdges.Count() != 3) { + ThrowF_t( "Non-triangle polygon encountered in model file %s !", fnmFirstFrame); + } + // get all 3 vetrices of current polygon and sorted them + opo.opo_PolygonEdges.Lock(); + CObjectPolygonEdge &opeCurr = opo.opo_PolygonEdges[0]; + CObjectPolygonEdge &opeNext = opo.opo_PolygonEdges[1]; + CObjectVertex *povxCurr, *povxPrev, *povxNext; + if( !opeCurr.ope_Backward) { + povxCurr = opeCurr.ope_Edge->oed_Vertex1; + povxPrev = opeCurr.ope_Edge->oed_Vertex0; + ASSERT( opeNext.ope_Edge->oed_Vertex0 == povxCurr); + } else { + povxCurr = opeCurr.ope_Edge->oed_Vertex0; + povxPrev = opeCurr.ope_Edge->oed_Vertex1; + ASSERT( opeNext.ope_Edge->oed_Vertex1 == povxCurr); + } + if( !opeNext.ope_Backward) { + povxNext = opeNext.ope_Edge->oed_Vertex1; + ASSERT( opeNext.ope_Edge->oed_Vertex0 == povxCurr); + } else { + povxNext = opeNext.ope_Edge->oed_Vertex0; + ASSERT( opeNext.ope_Edge->oed_Vertex1 == povxCurr); + } + INDEX iVtx0 = OB3D.ob_aoscSectors[0].osc_aovxVertices.Index(povxPrev); + INDEX iVtx1 = OB3D.ob_aoscSectors[0].osc_aovxVertices.Index(povxCurr); + INDEX iVtx2 = OB3D.ob_aoscSectors[0].osc_aovxVertices.Index(povxNext); + // add neighbor vertices for each of this vertices + avnVertices[iVtx0].vp_aiNeighbors.Push() = iVtx2; + avnVertices[iVtx0].vp_aiNeighbors.Push() = iVtx1; + avnVertices[iVtx1].vp_aiNeighbors.Push() = iVtx0; + avnVertices[iVtx1].vp_aiNeighbors.Push() = iVtx2; + avnVertices[iVtx2].vp_aiNeighbors.Push() = iVtx1; + avnVertices[iVtx2].vp_aiNeighbors.Push() = iVtx0; + // advance to next poly + opo.opo_PolygonEdges.Unlock(); + iPolyNo++; + }} + // vertex->polygons links created + OB3D.ob_aoscSectors[0].UnlockAll(); + + + // cache strecthing reciprocal for faster calc + FLOAT f1oStretchX, f1oStretchY, f1oStretchZ; + if( edm_md.md_Flags & MF_COMPRESSED_16BIT) { + f1oStretchX = 32767.0f / edm_md.md_Stretch(1); + f1oStretchY = 32767.0f / edm_md.md_Stretch(2); + f1oStretchZ = 32767.0f / edm_md.md_Stretch(3); + } else { + f1oStretchX = 127.0f / edm_md.md_Stretch(1); + f1oStretchY = 127.0f / edm_md.md_Stretch(2); + f1oStretchZ = 127.0f / edm_md.md_Stretch(3); + } + + // remember center vector + FLOAT3D vCenter = AllFramesBB.Center(); // obtain bbox center + edm_md.md_vCenter = vCenter; + + // prepare progress bar + if( ProgresRoutines.SetProgressMessage != NULL) { + ProgresRoutines.SetProgressMessage( "Calculating gouraud normals and stretching vertices ..."); + } + if( ProgresRoutines.SetProgressRange != NULL) { + ProgresRoutines.SetProgressRange( edm_md.md_FramesCt); + } + + // loop thru frames + iO3D=0; // index for progress + INDEX iFVtx=0; // count for all vertices in all frames + for( INDEX iFr=0; iFr=0 && a<=180); + aSum += a; + vSum += (v/fLength) * a; + } + + // normalize sum of polygon normals + //ASSERT( aSum>=0); + vSum /= aSum; + vSum.Normalize(); + + // save compressed gouraud normal + if( edm_md.md_Flags & MF_COMPRESSED_16BIT) { + CompressNormal_HQ( vSum, edm_md.md_FrameVertices16[iFVtx].mfv_ubNormH, + edm_md.md_FrameVertices16[iFVtx].mfv_ubNormP); + } else { + edm_md.md_FrameVertices8[iFVtx].mfv_NormIndex = (UBYTE)GouraudNormal(vSum); + } + + // advance to next vertex in model + iFVtx++; + } + + // advance to next frame + iO3D++; + } + + // list of filenames is no longer needed + FORDELETELIST( CFileNameNode, cfnn_Node, FrameNamesList, litDel) delete &litDel.Current(); + + // create compressed vector center that will be used for setting object handle + edm_md.md_vCompressedCenter(1) = -edm_md.md_vCenter(1) * f1oStretchX; + edm_md.md_vCompressedCenter(2) = -edm_md.md_vCenter(2) * f1oStretchY; + edm_md.md_vCompressedCenter(3) = -edm_md.md_vCenter(3) * f1oStretchZ; + + // adjust stretching for compressed format + if( edm_md.md_Flags & MF_COMPRESSED_16BIT) { + edm_md.md_Stretch(1) /= 32767.0f; + edm_md.md_Stretch(2) /= 32767.0f; + edm_md.md_Stretch(3) /= 32767.0f; + } else { + edm_md.md_Stretch(1) /= 127.0f; + edm_md.md_Stretch(2) /= 127.0f; + edm_md.md_Stretch(3) /= 127.0f; + } + + // all done + OB3D.ob_aoscSectors.Unlock(); + + CObject3D::BatchLoading_t(FALSE); + } catch (char*) { + CObject3D::BatchLoading_t(FALSE); + throw; + } +} + + +//-------------------------------------------------------------------------------------------- +/* + * Routine saves model's .h file (#define ......) + */ +void CEditModel::SaveIncludeFile_t( CTFileName fnFileName, CTString strDefinePrefix) // throw char * +{ + CTFileStream strmHFile; + char line[ 1024]; + INDEX i; + + strmHFile.Create_t( fnFileName, CTStream::CM_TEXT); + strcpy( line, strDefinePrefix); + strupr( line); + strDefinePrefix = CTString( line); + + sprintf( line, "// Animation names\n"); + strmHFile.Write_t( line, strlen( line)); + // force animation prefix string to be upper case + char achrUprName[ 256]; + strcpy( achrUprName, strDefinePrefix); + strcat( achrUprName, "_ANIM_"); + CTString strAnimationPrefix = achrUprName; + edm_md.ExportAnimationNames_t( &strmHFile, achrUprName); + + sprintf( line, "\n// Color names\n"); + strmHFile.Write_t( line, strlen( line)); + + for( i=0; iam_strName); + strupr( achrUpper); + sprintf( line, "#define %s_ATTACHMENT_%s %d\n", strDefinePrefix, achrUpper, iAttachingPlcement); + strmHFile.Write_t( line, strlen( line)); + iAttachingPlcement++; + } + sprintf( line, "\n// Sound names\n"); + strmHFile.Write_t( line, strlen( line)); + + for( INDEX iSound=0; iSound0 && !isalpha(strPrefix[0]) && strPrefix[0]!='_') { + strPrefix="_"+strPrefix; + } + SaveIncludeFile_t( fnHFileName, strPrefix); + + CTFileName fnIniFileName = fnFileName.FileDir() + fnFileName.FileName() + ".ini"; + CSerial::Save_t( fnIniFileName); +} + +// overloaded load function +void CEditModel::Load_t( CTFileName fnFileName) +{ + CTFileName fnMdlFileName = fnFileName.FileDir() + fnFileName.FileName() + ".mdl"; + edm_md.Load_t( fnMdlFileName); + + CTFileName fnIniFileName = fnFileName.FileDir() + fnFileName.FileName() + ".ini"; + // try to load ini file + try + { + CSerial::Load_t( fnIniFileName); + } + catch(char *strError) + { + // ignore errors + (void) strError; + CreateEmptyAttachingSounds(); + } +} + +CTextureDataInfo *CEditModel::AddTexture_t(const CTFileName &fnFileName, const MEX mexWidth, + const MEX mexHeight) +{ + CTextureDataInfo *pNewTDI = new CTextureDataInfo; + pNewTDI->tdi_FileName = fnFileName; + + try + { + pNewTDI->tdi_TextureData = _pTextureStock->Obtain_t( pNewTDI->tdi_FileName); + } + catch(char *strError) + { + (void) strError; + delete pNewTDI; + return NULL; + } + + // reload the texture + pNewTDI->tdi_TextureData->Reload(); + + edm_WorkingSkins.AddTail( pNewTDI->tdi_ListNode); + return pNewTDI; +} + +CAttachedModel::CAttachedModel(void) +{ + am_strName = "No name"; + am_iAnimation = 0; + am_bVisible = TRUE; +} + +CAttachedModel::~CAttachedModel(void) +{ + Clear(); +} + +void CAttachedModel::Clear(void) +{ + am_moAttachedModel.mo_toTexture.SetData(NULL); + am_moAttachedModel.mo_toReflection.SetData(NULL); + am_moAttachedModel.mo_toSpecular.SetData(NULL); + am_moAttachedModel.mo_toBump.SetData(NULL); + am_moAttachedModel.SetData(NULL); +} + +void CAttachedModel::Read_t( CTStream *pstrmFile) // throw char * +{ + *pstrmFile >> am_bVisible; + *pstrmFile >> am_strName; + // this data is used no more + CTFileName fnModel, fnDummy; + *pstrmFile >> fnModel; + + // new attached model format has saved index of animation + if( pstrmFile->PeekID_t() == CChunkID("AMAN")) + { + pstrmFile->ExpectID_t( CChunkID( "AMAN")); + *pstrmFile >> am_iAnimation; + } + else + { + *pstrmFile >> fnDummy; // ex model's texture + } + + try + { + SetModel_t( fnModel); + } + catch(char *strError) + { + (void) strError; + try + { + SetModel_t( CTFILENAME("Models\\Editor\\Axis.mdl")); + } + catch(char *strError) + { + FatalError( strError); + } + } +} + +void CAttachedModel::Write_t( CTStream *pstrmFile) // throw char * +{ + *pstrmFile << am_bVisible; + *pstrmFile << am_strName; + *pstrmFile << am_moAttachedModel.GetName(); + + // new attached model format has saved index of animation + pstrmFile->WriteID_t( CChunkID("AMAN")); + *pstrmFile << am_iAnimation; +} + +void CAttachedModel::SetModel_t(CTFileName fnModel) +{ + am_moAttachedModel.SetData_t(fnModel); + am_moAttachedModel.AutoSetTextures(); +} + +CAttachedSound::CAttachedSound( void) +{ + as_fDelay = 0.0f; + as_fnAttachedSound = CTString(""); + as_bLooping = FALSE; + as_bPlaying = TRUE; +} + +void CAttachedSound::Read_t(CTStream *strFile) +{ + *strFile>>as_bLooping; + *strFile>>as_bPlaying; + *strFile>>as_fnAttachedSound; + *strFile>>as_fDelay; +} + +void CAttachedSound::Write_t(CTStream *strFile) +{ + *strFile< 0); + edm_aasAttachedSounds.Clear(); + edm_aasAttachedSounds.New( edm_md.GetAnimsCt()); +} + +void CEditModel::Read_t( CTStream *pFile) // throw char * +{ + CTFileName fnFileName; + INDEX i, iWorkingTexturesCt; + + pFile->ExpectID_t( CChunkID( "WTEX")); + *pFile >> iWorkingTexturesCt; + + for( i=0; i> fnFileName; + try + { + AddTexture_t( fnFileName, edm_md.md_Width, edm_md.md_Height); + } + // This is here because we want to load model even if its texture is not valid + catch( char *err_str){ (char *) err_str;} + } + + // skip patches saved in old format (patches do not exist inside EditModel any more) + if( pFile->PeekID_t() == CChunkID("PATM")) + { + pFile->GetID_t(); + ULONG ulDummySizeOfLong; + ULONG ulOldExistingPatches; + + *pFile >> ulDummySizeOfLong; + *pFile >> ulOldExistingPatches; + for( i=0; i> fnPatchName; + } + } + } + + // try to load attached models + try + { + pFile->ExpectID_t( CChunkID( "ATTM")); + INDEX ctSavedModels; + *pFile >> ctSavedModels; + + // clamp no of saved attachments to no of model's data attached positions + INDEX ctMDAttachments = edm_md.md_aampAttachedPosition.Count(); + INDEX ctToLoad = ClampUp( ctSavedModels, ctMDAttachments); + INDEX ctToSkip = ctSavedModels - ctToLoad; + + // add attached models + edm_aamAttachedModels.Clear(); + if( ctToLoad != 0) + { + edm_aamAttachedModels.New( ctSavedModels); + // read all attached models + FOREACHINDYNAMICARRAY(edm_aamAttachedModels, CAttachedModel, itam) + { + itam->Read_t(pFile); + } + } + + // skip unused attached models + for( INDEX iSkip=0; iSkipExpectID_t( CChunkID( "ATSD")); + INDEX ctAttachedSounds; + *pFile >> ctAttachedSounds; + INDEX ctExisting = edm_aasAttachedSounds.Count(); + INDEX ctToRead = ClampUp( ctAttachedSounds, ctExisting); + + // read all saved attached sounds + for( INDEX iSound=0; iSoundExpectID_t( CChunkID( "TBST")); + edm_tsThumbnailSettings.Read_t( pFile); + } + catch( char *strError) + { + // ignore errors + (void) strError; + } + + // load names of effect textures + // --- specular texture + try { + pFile->ExpectID_t( CChunkID( "FXTS")); + *pFile >> edm_fnSpecularTexture; + } catch( char *strError) { (void) strError; } + + // --- reflection texture + try { + pFile->ExpectID_t( CChunkID( "FXTR")); + *pFile >> edm_fnReflectionTexture; + } catch( char *strError) { (void) strError; } + + // --- bump texture + try { + pFile->ExpectID_t( CChunkID( "FXTB")); + *pFile >> edm_fnBumpTexture; + } catch( char *strError) { (void) strError; } +} + +void CEditModel::Write_t( CTStream *pFile) // throw char * +{ + pFile->WriteID_t( CChunkID( "WTEX")); + + INDEX iWorkingTexturesCt = edm_WorkingSkins.Count(); + *pFile << iWorkingTexturesCt; + + FOREACHINLIST( CTextureDataInfo, tdi_ListNode, edm_WorkingSkins, it) + { + *pFile << it->tdi_FileName; + } + + // CEditModel class has no patches in new patch data format + + pFile->WriteID_t( CChunkID( "ATTM")); + INDEX ctAttachedModels = edm_aamAttachedModels.Count(); + *pFile << ctAttachedModels; + // write all attached models + FOREACHINDYNAMICARRAY(edm_aamAttachedModels, CAttachedModel, itam) + { + itam->Write_t(pFile); + } + + pFile->WriteID_t( CChunkID( "ATSD")); + INDEX ctAttachedSounds = edm_aasAttachedSounds.Count(); + *pFile << ctAttachedSounds; + // write all attached models + FOREACHINSTATICARRAY(edm_aasAttachedSounds, CAttachedSound, itas) + { + itas->Write_t(pFile); + } + + // save last taken thumbnail settings + pFile->WriteID_t( CChunkID( "TBST")); + edm_tsThumbnailSettings.Write_t( pFile); + + // save names of effect textures + // --- specular texture + pFile->WriteID_t( CChunkID( "FXTS")); + *pFile << edm_fnSpecularTexture; + // --- reflection texture + pFile->WriteID_t( CChunkID( "FXTR")); + *pFile << edm_fnReflectionTexture; + // --- bump texture + pFile->WriteID_t( CChunkID( "FXTB")); + *pFile << edm_fnBumpTexture; +} +//---------------------------------------------------------------------------------------------- +/* + * Routine saves defult script file containing only one animation with default data + * Input file name is .LWO file name, not .SCR + */ +void CEditModel::CreateScriptFile_t(CTFileName &fnO3D) // throw char * +{ + CTFileName fnScriptName = fnO3D.FileDir() + fnO3D.FileName() + ".scr"; + CTFileStream File; + char line[ 256]; + + File.Create_t( fnScriptName, CTStream::CM_TEXT); + File.PutLine_t( ";******* Creation settings"); + File.PutLine_t( "TEXTURE_DIM 2.0 2.0"); + File.PutLine_t( "SIZE 1.0"); + File.PutLine_t( "MAX_SHADOW 0"); + File.PutLine_t( "HI_QUALITY YES"); + File.PutLine_t( "FLAT NO"); + File.PutLine_t( "HALF_FLAT NO"); + File.PutLine_t( "STRETCH_DETAIL NO"); + File.PutLine_t( ""); + File.PutLine_t( ";******* Mip models"); + sprintf( line, "DIRECTORY %s", (CTString&)fnO3D.FileDir()); + File.PutLine_t( line); + File.PutLine_t( "MIP_MODELS 1"); + sprintf( line, " %s", (CTString&)(fnO3D.FileName() + fnO3D.FileExt())); + File.PutLine_t( line); + File.PutLine_t( ""); + File.PutLine_t( "ANIM_START"); + File.PutLine_t( ";******* Start of animation block"); + File.PutLine_t( ""); + sprintf( line, "DIRECTORY %s", (CTString&)fnO3D.FileDir()); + File.PutLine_t( line); + File.PutLine_t( "ANIMATION Default"); + File.PutLine_t( "SPEED 0.1"); + sprintf( line, " %s", (CTString&)(fnO3D.FileName() + fnO3D.FileExt())); + File.PutLine_t( line); + File.PutLine_t( ""); + File.PutLine_t( ";******* End of animation block"); + File.PutLine_t( "ANIM_END"); + File.PutLine_t( ""); + File.PutLine_t( "END"); + File.Close(); +} +//---------------------------------------------------------------------------------------------- +/* + * This routine load lines from script file and executes appropriate actions + */ +#define EQUAL_SUB_STR( str) (strnicmp( ld_line, str, strlen(str)) == 0) + +void CEditModel::LoadFromScript_t(CTFileName &fnScriptName) // throw char * +{ + try { + CObject3D::BatchLoading_t(TRUE); + + INDEX i; + CTFileStream File; + CObject3D O3D; + CTFileName fnOpened, fnClosed, fnUnwrapped, fnImportMapping; + char ld_line[ 128]; + char flag_str[ 128]; + char base_path[ PATH_MAX] = ""; + char file_name[ PATH_MAX]; + char mapping_file_name[ PATH_MAX] = ""; + char full_path[ PATH_MAX]; + FLOATmatrix3D mStretch; + mStretch.Diagonal(1.0f); + BOOL bMappingDimFound ; + BOOL bAnimationsFound; + BOOL bLoadInitialMapping; + + O3D.ob_aoscSectors.Lock(); + File.Open_t( fnScriptName); // open script file for reading + + // if these flags will not be TRUE at the end of script, throw error + bMappingDimFound = FALSE; + bAnimationsFound = FALSE; + bLoadInitialMapping = FALSE; + + // to hold number of line's chars + int iLineChars; + FOREVER + { + do + { + File.GetLine_t(ld_line, 128); + iLineChars = strlen( ld_line); + } + while( (iLineChars == 0) || (ld_line[0]==';') ); + + // If key-word is "DIRECTORY", remember base path it and add "\" character at the + // end of new path if it is not yet there + if( EQUAL_SUB_STR( "DIRECTORY")) + { + _strupr( ld_line); + sscanf( ld_line, "DIRECTORY %s", base_path); + if( base_path[ strlen( base_path) - 1] != '\\') + strcat( base_path,"\\"); + } + // Key-word "SIZE" defines stretch factor + else if( EQUAL_SUB_STR( "SIZE")) + { + _strupr( ld_line); + FLOAT fStretch = 1.0f; + sscanf( ld_line, "SIZE %g", &fStretch); + mStretch *= fStretch; + } + else if( EQUAL_SUB_STR( "TRANSFORM")) + { + _strupr( ld_line); + FLOATmatrix3D mTran; + mTran.Diagonal(1.0f); + sscanf( ld_line, "TRANSFORM %g %g %g %g %g %g %g %g %g", + &mTran(1,1), &mTran(1,2), &mTran(1,3), + &mTran(2,1), &mTran(2,2), &mTran(2,3), + &mTran(3,1), &mTran(3,2), &mTran(3,3)); + mStretch *= mTran; + } + // Key-word "FLAT" means that model will be mapped as face - forward, using only + // zooming of texture + else if( EQUAL_SUB_STR( "FLAT")) + { + _strupr( ld_line); + sscanf( ld_line, "FLAT %s", flag_str); + if( strcmp( flag_str, "YES") == 0) + { + edm_md.md_Flags |= MF_FACE_FORWARD; + edm_md.md_Flags &= ~MF_HALF_FACE_FORWARD; + } + } + else if( EQUAL_SUB_STR( "HALF_FLAT")) + { + _strupr( ld_line); + sscanf( ld_line, "HALF_FLAT %s", flag_str); + if( strcmp( flag_str, "YES") == 0) + edm_md.md_Flags |= MF_FACE_FORWARD|MF_HALF_FACE_FORWARD; + } + else if( EQUAL_SUB_STR( "STRETCH_DETAIL")) + { + _strupr( ld_line); + sscanf( ld_line, "STRETCH_DETAIL %s", flag_str); + if( strcmp( flag_str, "YES") == 0) + { + edm_md.md_Flags |= MF_STRETCH_DETAIL; + } + } + else if( EQUAL_SUB_STR( "HI_QUALITY")) + { + _strupr( ld_line); + sscanf( ld_line, "HI_QUALITY %s", flag_str); + if( strcmp( flag_str, "YES") == 0) + { + edm_md.md_Flags |= MF_COMPRESSED_16BIT; + } + } + // Key-word "REFLECTIONS" has been used in old reflections + else if( EQUAL_SUB_STR( "REFLECTIONS")) + { + } + // Key-word "MAX_SHADOW" determines maximum quality of shading that model can obtain + else if( EQUAL_SUB_STR( "MAX_SHADOW")) + { + _strupr( ld_line); + INDEX iShadowQuality; + sscanf( ld_line, "MAX_SHADOW %d", &iShadowQuality); + edm_md.md_ShadowQuality = iShadowQuality; + } + // Key-word "MipModel" must follow name of this mipmodel file + else if( EQUAL_SUB_STR( "MIP_MODELS")) + { + INDEX iMipCt; + sscanf( ld_line, "MIP_MODELS %d", &iMipCt); + if( (iMipCt <= 0) || (iMipCt >= MAX_MODELMIPS)) + { + ThrowF_t("Invalid number of mip models. Number must range from 0 to %d.", MAX_MODELMIPS-1); + } + if( ProgresRoutines.SetProgressMessage != NULL) + ProgresRoutines.SetProgressMessage( "Loading and creating mip-models ..."); + if( ProgresRoutines.SetProgressRange != NULL) + ProgresRoutines.SetProgressRange( iMipCt); + for( i=0; iob_aoscSectors.Lock(); + pO3D->ob_aoscSectors[0].LockAll(); + edm_md.md_VerticesCt = pO3D->ob_aoscSectors[0].osc_aovxVertices.Count(); // see how many vertices we will have + edm_md.md_TransformedVertices.New( edm_md.md_VerticesCt); // create buffer for rotated vertices + edm_md.md_MainMipVertices.New( edm_md.md_VerticesCt); // create buffer for main mip vertices + edm_md.md_VertexMipMask.New( edm_md.md_VerticesCt); // create buffer for vertex masks + + for( INDEX i=0; iob_aoscSectors[0].osc_aovxVertices[ i]); + edm_md.md_VertexMipMask[ i] = 0L; // mark to all vertices that they don't exist in any mip-model + } + + AddMipModel( pO3D); // we add main model, first mip-model + pO3D->ob_aoscSectors[0].UnlockAll(); + pO3D->ob_aoscSectors.Unlock(); +} + +//---------------------------------------------------------------------------------------------- +/* + * Routine takes 3D object as input and adds one mip model + * The main idea is: for every vertice get distances to all vertices in md_MainMipVertices + * array. If minimum distance is found, set that this vertice exists. Loop for all vertices. + * Throw error if minimum distance isn't found. Set also new mip-model polygons info. + */ +void CEditModel::AddMipModel( CObject3D *pO3D) +{ + INDEX i, j; + BOOL same_found; + + // this is mask for vertices in current mip level + ULONG mip_vtx_mask = (1L) << edm_md.md_MipCt; + + struct ModelMipInfo *pmmpi = &edm_md.md_MipInfos[ edm_md.md_MipCt]; // point to mip model that we will create + + // for each vertex + for( INDEX iVertex=0; iVertexob_aoscSectors[0].osc_aovxVertices.Count(); + /* + * For each vertex in 3D object we calculate distances to all vertices in main mip-model. + * If distance (size of vector that is result of substraction of two vertice vectors) is + * less than some minimal float number, we assume that these vertices are the same. + * Processed vertex of 3D object gets its main-mip-model-vertex-friend's index as tag and + * mask value showing that it exists in this mip-model. + */ + for( i=0; iob_aoscSectors[0].osc_aovxVertices[ i]); + FLOAT fAbsoluteDistance = Abs( (vVertex - edm_md.md_MainMipVertices[ j]).Length() ); + if( fAbsoluteDistance < MAX_ALLOWED_DISTANCE) + { + edm_md.md_VertexMipMask[ j] |= mip_vtx_mask;// we mark that this vertice exists in this mip model + pO3D->ob_aoscSectors[0].osc_aovxVertices[ i].ovx_Tag = j;// remapping verice index must be remembered + same_found = TRUE; // mark that this vertex's remap is found + break; + } + } + if( same_found == FALSE) // if no vertice close enough is found, we have error + { + ThrowF_t("Vertex from mip model %d with number %d, coordinates (%f,%f,%f), can't be found in main mip model.\n" + "There can't be new vertices in rougher mip-models," + "but only vertices from main mip model can be removed and polygons reorganized.\n", + edm_md.md_MipCt, i, + pO3D->ob_aoscSectors[0].osc_aovxVertices[ i](1), pO3D->ob_aoscSectors[0].osc_aovxVertices[ i](2), pO3D->ob_aoscSectors[0].osc_aovxVertices[ i](3)); + } + } + + /* + * We will create three arays for this mip polygon info: + * 1) array for polygons + * 2) array for mapping surfaces + * 3) array for polygon vertices + * 4) array for texture vertices + */ + + /* + * First we create array large enough to accept object 3D's polygons. + */ + pmmpi->mmpi_PolygonsCt = pO3D->ob_aoscSectors[0].osc_aopoPolygons.Count(); + pmmpi->mmpi_Polygons.New( pmmpi->mmpi_PolygonsCt); + + /* + * Then we will create array for mapping surfaces and set their names + */ + pmmpi->mmpi_MappingSurfaces.New( pO3D->ob_aoscSectors[0].osc_aomtMaterials.Count()); // create array for mapping surfaces + for( i=0; iob_aoscSectors[0].osc_aomtMaterials.Count(); i++) + { + MappingSurface &ms = pmmpi->mmpi_MappingSurfaces[ i]; + ms.ms_ulOnColor = PC_ALLWAYS_ON; // set default ON and OFF masking colors + ms.ms_ulOffColor = PC_ALLWAYS_OFF; + ms.ms_Name = CTFileName( pO3D->ob_aoscSectors[0].osc_aomtMaterials[ i].omt_Name); + ms.ms_vSurface2DOffset = FLOAT3D( 1.0f, 1.0f, 1.0f); + ms.ms_HPB = FLOAT3D( 0.0f, 0.0f, 0.0f); + ms.ms_Zoom = 1.0f; + + ms.ms_colColor = + pO3D->ob_aoscSectors[0].osc_aomtMaterials[ i].omt_Color | CT_OPAQUE; // copy surface color, set no alpha + ms.ms_sstShadingType = SST_MATTE; + ms.ms_sttTranslucencyType = STT_OPAQUE; + ms.ms_ulRenderingFlags = SRF_DIFFUSE|SRF_NEW_TEXTURE_FORMAT; + } + + /* + * Then we will count how many ModelPolygonVertices we need and create array for them. + * This number is equal to sum of all vertices used by all object 3D's polygons + */ + INDEX pvct = 0; + for( i=0; immpi_PolygonsCt; i++) + { + pvct += pO3D->ob_aoscSectors[0].osc_aopoPolygons[ i].opo_PolygonEdges.Count(); // we have vertices as many as edges + } + /* + * Now we will create an static array of temporary structures used for extracting + * vertice-surface connection. We need this because we have to set for all model vertices: + * 1) their texture vertices + * 2) their transformed vertices. + * First we will set surface and transformed indexes to every polygon vertice + */ + INDEX esvct = 0; // for counting polygon vertices + CStaticArray< CExtractSurfaceVertex> aesv; + aesv.New( pvct); // array with same number of members as polygon vertex array + + {FOREACHINDYNAMICARRAY( pO3D->ob_aoscSectors[0].osc_aopoPolygons, CObjectPolygon, it1) + { + INDEX iPolySurface = pO3D->ob_aoscSectors[0].osc_aomtMaterials.Index( it1->opo_Material); // this polygon's surface index + FOREACHINDYNAMICARRAY( it1->opo_PolygonEdges, CObjectPolygonEdge, it2) + { + aesv[ esvct].esv_Surface = iPolySurface; // all these vertices are members of same polygon so they have same surface index + aesv[ esvct].esv_MipGlobalIndex = pO3D->ob_aoscSectors[0].osc_aovxVertices.Index( it2->ope_Edge->oed_Vertex0); // global index + esvct++; + } + }} + + + /* + * Then we will choose one verice from this array and see if there is any vertice + * processed until now that have same surface and global index. If souch + * vertice exists, copy its remap value, if it doesn't exists, set its remap value + * to value of current texture vertex counter. After counting souch surface-dependent + * vertices (texture vertices, tvct) we will create array for them + */ + BOOL same_vtx_found; + INDEX tvct = 0; + for( i=0; immpi_TextureVertices.New( tvct); // create array for texture vertices + + /* + * Now we will set texture vertex data for all surface unique vertices. We will do it by + * looping this to all polygon vertices: copy coordinates of vertex from global vertex array + * to UVW coordinates of texture vertex. That way we will have little overhead (some + * vertices will be copied many times) but it doesn't really matter. + */ + for( i=0; immpi_TextureVertices[ aesv[ i].esv_TextureVertexRemap].mtv_UVW = + DOUBLEtoFLOAT(pO3D->ob_aoscSectors[0].osc_aovxVertices[ aesv[ i].esv_MipGlobalIndex]); + } + + + /* + * Now we intend to create data for all polygons (that includes setting polygon's + * texture and transformed vertex ptrs) + */ + INDEX mpvct = 0; // start polygon vertex counter + for( i=0; immpi_PolygonsCt; i++) // loop all model polygons + { + struct ModelPolygon *pmp = &pmmpi->mmpi_Polygons[ i]; // ptr to activ model polygon + pmp->mp_Surface = pO3D->ob_aoscSectors[0].osc_aomtMaterials.Index( pO3D->ob_aoscSectors[0].osc_aopoPolygons[ i].opo_Material); // copy surface index + pmp->mp_ColorAndAlpha = + pO3D->ob_aoscSectors[0].osc_aopoPolygons[ i].opo_Material->omt_Color | CT_OPAQUE; // copy surface color, set no alpha + INDEX ctVertices = pO3D->ob_aoscSectors[0].osc_aopoPolygons[ i].opo_PolygonEdges.Count(); // set no of polygon's vertices + pmp->mp_PolygonVertices.New( ctVertices); // create array for them + for( j=0; job_aoscSectors[0].osc_aovxVertices[ aesv[ mpvct].esv_MipGlobalIndex].ovx_Tag; + + pmp->mp_PolygonVertices[ j].mpv_ptvTransformedVertex = + &edm_md.md_TransformedVertices[ (INDEX) trans_vtx_idx ]; // remapped ptr to transformed vertex + pmp->mp_PolygonVertices[ j].mpv_ptvTextureVertex = + &pmmpi->mmpi_TextureVertices[ aesv[ mpvct].esv_TextureVertexRemap]; // ptr to unique vertex in surface + mpvct ++; + } + } + + edm_md.md_MipCt ++; // finally, this mip-model is done. +} + +//---------------------------------------------------------------------------------------------- +/* + * Routine sets unwrapped mapping from given three objects + */ +void CEditModel::CalculateUnwrappedMapping( CObject3D &o3dClosed, CObject3D &o3dOpened, CObject3D &o3dUnwrapped) +{ + o3dOpened.ob_aoscSectors.Lock(); + o3dClosed.ob_aoscSectors.Lock(); + o3dUnwrapped.ob_aoscSectors.Lock(); + // get first mip model + struct ModelMipInfo *pMMI = &edm_md.md_MipInfos[ 0]; + // for each surface in first mip model + for( INDEX iSurface = 0; iSurface < pMMI->mmpi_MappingSurfaces.Count(); iSurface++) + { + MappingSurface *pmsSurface = &pMMI->mmpi_MappingSurfaces[iSurface]; + // for each texture vertex in surface + for(INDEX iSurfaceTextureVertex=0; iSurfaceTextureVertexms_aiTextureVertices.Count(); iSurfaceTextureVertex++) + { + INDEX iGlobalTextureVertex = pmsSurface->ms_aiTextureVertices[iSurfaceTextureVertex]; + ModelTextureVertex *pmtvTextureVertex = &pMMI->mmpi_TextureVertices[iGlobalTextureVertex]; + // obtain index of model vertex + INDEX iModelVertex = pmtvTextureVertex->mtv_iTransformedVertex; + // for each polygon in opened with same surface + for(INDEX iOpenedPolygon=0; iOpenedPolygon< o3dOpened.ob_aoscSectors[0].osc_aopoPolygons.Count(); iOpenedPolygon++) + { + DOUBLE3D vClosedVertex; + DOUBLE3D vOpenedVertex; + + // get coordinate from model vertex in closed + o3dClosed.ob_aoscSectors[0].osc_aovxVertices.Lock(); + vClosedVertex = o3dClosed.ob_aoscSectors[0].osc_aovxVertices[ iModelVertex]; + o3dClosed.ob_aoscSectors[0].osc_aovxVertices.Unlock(); + + // find vertex in opened with same coordinate + o3dOpened.ob_aoscSectors[0].osc_aopoPolygons.Lock(); + CObjectPolygon *popoOpenedPolygon = &o3dOpened.ob_aoscSectors[0].osc_aopoPolygons[ iOpenedPolygon]; + o3dOpened.ob_aoscSectors[0].osc_aopoPolygons.Unlock(); + if( popoOpenedPolygon->opo_Material->omt_Name != pmsSurface->ms_Name) continue; + for( INDEX iOpenedPolyEdge=0; iOpenedPolyEdgeopo_PolygonEdges.Count(); iOpenedPolyEdge++) + { + popoOpenedPolygon->opo_PolygonEdges.Lock(); + CObjectVertex *povOpenedVertex; + if( !popoOpenedPolygon->opo_PolygonEdges[iOpenedPolyEdge].ope_Backward) + { + povOpenedVertex = popoOpenedPolygon->opo_PolygonEdges[iOpenedPolyEdge].ope_Edge->oed_Vertex0; + } + else + { + povOpenedVertex = popoOpenedPolygon->opo_PolygonEdges[iOpenedPolyEdge].ope_Edge->oed_Vertex1; + } + popoOpenedPolygon->opo_PolygonEdges.Unlock(); + + vOpenedVertex = *povOpenedVertex; + + // if these two vertices have same coordinates + FLOAT fAbsoluteDistance = Abs( (vClosedVertex - vOpenedVertex).Length()); + if( fAbsoluteDistance < MAX_ALLOWED_DISTANCE) + { + o3dClosed.ob_aoscSectors[0].osc_aovxVertices.Lock(); + o3dUnwrapped.ob_aoscSectors[0].osc_aovxVertices.Lock(); + // find index in opened + o3dOpened.ob_aoscSectors[0].osc_aovxVertices.Lock(); + INDEX iOpenedModelVertex = o3dOpened.ob_aoscSectors[0].osc_aovxVertices.Index( povOpenedVertex); + o3dOpened.ob_aoscSectors[0].osc_aovxVertices.Unlock(); + // get coordinate from unwrapped using index + DOUBLE3D vMappingCoordinate = o3dUnwrapped.ob_aoscSectors[0].osc_aovxVertices[ iOpenedModelVertex]; + // set new mapping coordinates + pmtvTextureVertex->mtv_UVW = DOUBLEtoFLOAT( vMappingCoordinate); + pmtvTextureVertex->mtv_UVW(2) = -pmtvTextureVertex->mtv_UVW(2); + MEX2D mexUV; + mexUV(1) = MEX_METERS(pmtvTextureVertex->mtv_UVW(1)); + mexUV(2) = MEX_METERS(pmtvTextureVertex->mtv_UVW(2)); + pmtvTextureVertex->mtv_UV = mexUV; + o3dClosed.ob_aoscSectors[0].osc_aovxVertices.Unlock(); + o3dUnwrapped.ob_aoscSectors[0].osc_aovxVertices.Unlock(); + } + } + } + // reset surface position, rotation and zoom + pmsSurface->ms_HPB = FLOAT3D( 0.0f, 0.0f, 0.0f); + pmsSurface->ms_Zoom = 1.0f; + pmsSurface->ms_vSurface2DOffset = FLOAT3D( 0.0f, 0.0f, 0.0f); + } + } + o3dOpened.ob_aoscSectors.Unlock(); + o3dClosed.ob_aoscSectors.Unlock(); + o3dUnwrapped.ob_aoscSectors.Unlock(); +} +//---------------------------------------------------------------------------------------------- +/* + * Routine calculate mapping for mip models (except for main mip) + */ +void CEditModel::CalculateMappingForMips( void) +{ + // for each mip model except first + for( INDEX iCurMip = 1; iCurMip< edm_md.md_MipCt; iCurMip++) + { + // get current mip model + struct ModelMipInfo *pMMICur = &edm_md.md_MipInfos[ iCurMip]; + // get previous mip model + struct ModelMipInfo *pMMIPrev = &edm_md.md_MipInfos[ iCurMip-1]; + // for each surface in current mip model + for( INDEX iSurfaceCur = 0; iSurfaceCur < pMMICur->mmpi_MappingSurfaces.Count(); iSurfaceCur++) + { + MappingSurface *pmsSurfCur = &pMMICur->mmpi_MappingSurfaces[iSurfaceCur]; + // for each texture vertex in surface + for(INDEX iSurfCurTV=0; iSurfCurTVms_aiTextureVertices.Count(); iSurfCurTV++) + { + INDEX iCurGlobalTV = pmsSurfCur->ms_aiTextureVertices[iSurfCurTV]; + ModelTextureVertex *pmtvCur = &pMMICur->mmpi_TextureVertices[iCurGlobalTV]; + // obtain index of model vertex + INDEX iCurMV = pmtvCur->mtv_iTransformedVertex; + + // get 3D coordinate of vertex from main mip + FLOAT3D vMainMipCoordCur = edm_md.md_MainMipVertices[ iCurMV]; + + // -------- Find closest vertex (using 3D coordinate) in previous mip + + // in previous mip model find surface with same name + MappingSurface *pmsSurfPrev = NULL; + for( INDEX iSurfacePrev = 0; iSurfacePrev < pMMIPrev->mmpi_MappingSurfaces.Count(); iSurfacePrev++) + { + pmsSurfPrev = &pMMIPrev->mmpi_MappingSurfaces[iSurfacePrev]; + if( pmsSurfCur->ms_Name == pmsSurfPrev->ms_Name) + { + break; + } + } + + // new surfaces can't appear + ASSERT(pmsSurfPrev != NULL); + if( pmsSurfPrev == NULL) + { + WarningMessage( "Mip model %d has surface that does not exist in previous mip. That is not allowed.", iCurMip); + break; + } + + // set hudge distance as current minimum + FLOAT fMinDistance = 99999999.0f; + ModelTextureVertex *pmtvClosestPrev = NULL; + + // for each texture vertex in previous mip's surface with same name + for(INDEX iSurfPrevTV=0; iSurfPrevTVms_aiTextureVertices.Count(); iSurfPrevTV++) + { + INDEX iPrevGlobalTV = pmsSurfPrev->ms_aiTextureVertices[iSurfPrevTV]; + ModelTextureVertex *pmtvPrev = &pMMIPrev->mmpi_TextureVertices[iPrevGlobalTV]; + // obtain index of model vertex + INDEX iPrevMV = pmtvPrev->mtv_iTransformedVertex; + // get 3D coordinate of vertex from main mip + FLOAT3D vMainMipCoordPrev = edm_md.md_MainMipVertices[ iPrevMV]; + // get distance of these two vertices + FLOAT fAbsoluteDistance = Abs( (vMainMipCoordPrev - vMainMipCoordCur).Length()); + if( fAbsoluteDistance < fMinDistance) + { + // remember current texture vertex as closest one + fMinDistance = fAbsoluteDistance; + pmtvClosestPrev = pmtvPrev; + } + } + ASSERT( pmtvClosestPrev != NULL); + // copy mapping coordinates from closest mapping vertex in previous mip + pmtvCur->mtv_UVW = pmtvClosestPrev->mtv_UVW; + pmtvCur->mtv_UV = pmtvClosestPrev->mtv_UV; + pmtvCur->mtv_vU = pmtvClosestPrev->mtv_vU; + pmtvCur->mtv_vV = pmtvClosestPrev->mtv_vV; + } + } + } +} + +/* + * This routine opens last script file loaded, repeats reading key-words until it finds + * key-word "ANIM_START". Then it calls animation data load from script routine. + */ +void CEditModel::UpdateAnimations_t(CTFileName &fnScriptName) // throw char * +{ + CTFileStream File; + char ld_line[ 128]; + CListHead FrameNamesList; + FLOATmatrix3D mStretch; + mStretch.Diagonal(1.0f); + + File.Open_t( fnScriptName); // open script file for reading + + FOREVER + { + do + { + File.GetLine_t(ld_line, 128); + } + while( (strlen( ld_line)== 0) || (ld_line[0]==';')); + + if( EQUAL_SUB_STR( "SIZE")) + { + _strupr( ld_line); + FLOAT fStretch = 1.0f; + sscanf( ld_line, "SIZE %g", &fStretch); + mStretch *= fStretch; + } + else if( EQUAL_SUB_STR( "TRANSFORM")) + { + _strupr( ld_line); + FLOATmatrix3D mTran; + mTran.Diagonal(1.0f); + sscanf( ld_line, "TRANSFORM %g %g %g %g %g %g %g %g %g", + &mTran(1,1), &mTran(1,2), &mTran(1,3), + &mTran(2,1), &mTran(2,2), &mTran(2,3), + &mTran(3,1), &mTran(3,2), &mTran(3,3)); + mStretch *= mTran; + } + else if( EQUAL_SUB_STR( "ANIM_START")) + { + LoadModelAnimationData_t( &File, mStretch); // load and set model's animation data + break; // we found our animations, we loaded them so we will stop forever loop + } + else if( EQUAL_SUB_STR( "ORIGIN_TRI")) + { + sscanf( ld_line, "ORIGIN_TRI %d %d %d", &aiTransVtx[0], &aiTransVtx[1], &aiTransVtx[2]); // read given vertices + } + } + File.Close(); + + CreateEmptyAttachingSounds(); +} +//---------------------------------------------------------------------------------------------- +void CEditModel::CreateMipModels_t(CObject3D &objRestFrame, CObject3D &objMipSourceFrame, + INDEX iVertexRemoveRate, INDEX iSurfacePreservingFactor) +{ + // free possible mip-models except main mip model + INDEX iMipModel=1; + for( ; iMipModelmp_Surface == iCurrentSurface) + { // readout poly vertices + f3dTr0(1) = (FLOAT)pPoly->mp_PolygonVertices[0].mpv_ptvTextureVertex->mtv_UV(1); + f3dTr0(2) = (FLOAT)pPoly->mp_PolygonVertices[0].mpv_ptvTextureVertex->mtv_UV(2); + f3dTr0(3) = 0.0f; + f3dTr1(1) = (FLOAT)pPoly->mp_PolygonVertices[1].mpv_ptvTextureVertex->mtv_UV(1); + f3dTr1(2) = (FLOAT)pPoly->mp_PolygonVertices[1].mpv_ptvTextureVertex->mtv_UV(2); + f3dTr1(3) = 0.0f; + f3dTr2(1) = (FLOAT)pPoly->mp_PolygonVertices[2].mpv_ptvTextureVertex->mtv_UV(1); + f3dTr2(2) = (FLOAT)pPoly->mp_PolygonVertices[2].mpv_ptvTextureVertex->mtv_UV(2); + f3dTr2(3) = 0.0f; + + // determine line visibility + FLOAT3D f3dNormal = (f3dTr2-f3dTr1)*(f3dTr0-f3dTr1); + COLOR clrWire; + ULONG ulLineType; + if( f3dNormal(3) < 0) { + clrWire = clrVisible; + ulLineType = _FULL_; + } else { + clrWire = clrInvisible; + ulLineType = _POINT_; + } + // draw lines + PIX pixX0, pixY0, pixX1, pixY1; + for( INDEX iVtx=0; iVtxmp_PolygonVertices.Count()-1; iVtx++) { + pVtx0 = pPoly->mp_PolygonVertices[iVtx+0].mpv_ptvTextureVertex; + pVtx1 = pPoly->mp_PolygonVertices[iVtx+1].mpv_ptvTextureVertex; + pixX0 = (PIX)(pVtx0->mtv_UV(1) * fMagnifyFactor) - offx; + pixY0 = (PIX)(pVtx0->mtv_UV(2) * fMagnifyFactor) - offy; + pixX1 = (PIX)(pVtx1->mtv_UV(1) * fMagnifyFactor) - offx; + pixY1 = (PIX)(pVtx1->mtv_UV(2) * fMagnifyFactor) - offy; + pDP->DrawLine( pixX0, pixY0, pixX1, pixY1, clrWire|CT_OPAQUE, ulLineType); + } + // draw last line + pVtx0 = pPoly->mp_PolygonVertices[0].mpv_ptvTextureVertex; + pixX0 = (PIX)(pVtx0->mtv_UV(1) * fMagnifyFactor) - offx; + pixY0 = (PIX)(pVtx0->mtv_UV(2) * fMagnifyFactor) - offy; + pDP->DrawLine( pixX0, pixY0, pixX1, pixY1, clrWire|CT_OPAQUE, ulLineType); + } + } +} + + +/* + * Flat fills given surface + */ +void CEditModel::DrawFilledSurface( CDrawPort *pDP, INDEX iCurrentMip, INDEX iCurrentSurface, + FLOAT fMagnifyFactor, PIX offx, PIX offy, + COLOR clrVisible, COLOR clrInvisible) +{ + FLOAT3D f3dTr0, f3dTr1, f3dTr2; + struct ModelTextureVertex *pVtx0, *pVtx1, *pVtx2; + + // for each polygon + for( INDEX iPoly=0; iPolymp_Surface == iCurrentSurface) + { // readout poly vertices + f3dTr0(1) = (FLOAT)pPoly->mp_PolygonVertices[0].mpv_ptvTextureVertex->mtv_UV(1); + f3dTr0(2) = (FLOAT)pPoly->mp_PolygonVertices[0].mpv_ptvTextureVertex->mtv_UV(2); + f3dTr0(3) = 0.0f; + f3dTr1(1) = (FLOAT)pPoly->mp_PolygonVertices[1].mpv_ptvTextureVertex->mtv_UV(1); + f3dTr1(2) = (FLOAT)pPoly->mp_PolygonVertices[1].mpv_ptvTextureVertex->mtv_UV(2); + f3dTr1(3) = 0.0f; + f3dTr2(1) = (FLOAT)pPoly->mp_PolygonVertices[2].mpv_ptvTextureVertex->mtv_UV(1); + f3dTr2(2) = (FLOAT)pPoly->mp_PolygonVertices[2].mpv_ptvTextureVertex->mtv_UV(2); + f3dTr2(3) = 0.0f; + + // determine poly visibility + COLOR clrFill; + FLOAT3D f3dNormal = (f3dTr2-f3dTr1)*(f3dTr0-f3dTr1); + if( f3dNormal(3) < 0) clrFill = clrVisible|0xFF; + else clrFill = clrInvisible|0xFF; + + // draw traingle(s) fan + pDP->InitTexture( NULL); + pVtx0 = pPoly->mp_PolygonVertices[0].mpv_ptvTextureVertex; + PIX pixX0 = (PIX)(pVtx0->mtv_UV(1) * fMagnifyFactor) - offx; + PIX pixY0 = (PIX)(pVtx0->mtv_UV(2) * fMagnifyFactor) - offy; + for( INDEX iVtx=1; iVtxmp_PolygonVertices.Count()-1; iVtx++) { + pVtx1 = pPoly->mp_PolygonVertices[iVtx+0].mpv_ptvTextureVertex; + pVtx2 = pPoly->mp_PolygonVertices[iVtx+1].mpv_ptvTextureVertex; + PIX pixX1 = (PIX)(pVtx1->mtv_UV(1) * fMagnifyFactor) - offx; + PIX pixY1 = (PIX)(pVtx1->mtv_UV(2) * fMagnifyFactor) - offy; + PIX pixX2 = (PIX)(pVtx2->mtv_UV(1) * fMagnifyFactor) - offx; + PIX pixY2 = (PIX)(pVtx2->mtv_UV(2) * fMagnifyFactor) - offy; + pDP->AddTriangle( pixX0,pixY0, pixX1,pixY1, pixX2,pixY2, clrFill); + } + // to buffer with it + pDP->FlushRenderingQueue(); + } + } +} + + +/* + * Prints surface numbers + */ +void CEditModel::PrintSurfaceNumbers( CDrawPort *pDP, CFontData *pFont, + INDEX iCurrentMip, FLOAT fMagnifyFactor, PIX offx, PIX offy, COLOR clrInk) +{ + char achrLine[ 256]; + + // clear Z-buffer + pDP->FillZBuffer( ZBUF_BACK); + + // get mip model ptr + struct ModelMipInfo *pMMI = &edm_md.md_MipInfos[ iCurrentMip]; + + + // for all surfaces + for( INDEX iSurf=0;iSurfmmpi_MappingSurfaces.Count(); iSurf++) + { + MappingSurface *pms= &pMMI->mmpi_MappingSurfaces[iSurf]; + MEXaabbox2D boxSurface; + // for each texture vertex in surface + for(INDEX iSurfaceTextureVertex=0; iSurfaceTextureVertexms_aiTextureVertices.Count(); iSurfaceTextureVertex++) + { + INDEX iGlobalTextureVertex = pms->ms_aiTextureVertices[iSurfaceTextureVertex]; + ModelTextureVertex *pmtv = &pMMI->mmpi_TextureVertices[iGlobalTextureVertex]; + boxSurface |= pmtv->mtv_UV; + } + + MEX2D mexCenter = boxSurface.Center(); + PIX2D pixCenter = PIX2D(mexCenter(1)*fMagnifyFactor-offx, mexCenter(2)*fMagnifyFactor-offy); + + // print active surface's number into print line + sprintf( achrLine, "%d", iSurf); + + // set font + pDP->SetFont( pFont); + // print line + pDP->PutText( achrLine, pixCenter(1)-strlen(achrLine)*4, pixCenter(2)-6); + } +} + +/* + * Exports surface names and numbers under given file name + */ +void CEditModel::ExportSurfaceNumbersAndNames( CTFileName fnFile) +{ + CTString strExport; + // get mip model ptr + struct ModelMipInfo *pMMI = &edm_md.md_MipInfos[ 0]; + + // for all surfaces + for( INDEX iSurf=0; iSurfmmpi_MappingSurfaces.Count(); iSurf++) + { + MappingSurface *pms= &pMMI->mmpi_MappingSurfaces[iSurf]; + CTString strExportLine; + strExportLine.PrintF( "%d) %s\n", iSurf, pms->ms_Name); + strExport+=strExportLine; + } + + try + { + strExport.Save_t( fnFile); + } + catch(char *strError) + { + // report error + WarningMessage( strError); + } +} + +/* + * Retrieves given surface's name + */ +const char *CEditModel::GetSurfaceName(INDEX iCurrentMip, INDEX iCurrentSurface) +{ + struct MappingSurface *pSurface; + pSurface = &edm_md.md_MipInfos[ iCurrentMip].mmpi_MappingSurfaces[ iCurrentSurface]; + return( pSurface->ms_Name); +} +//-------------------------------------------------------------------------------------------- +/* + * Sets first empty position in existing patches mask + */ +BOOL CEditModel::GetFirstEmptyPatchIndex( INDEX &iMaskBit) +{ + iMaskBit = 0; + for( INDEX iPatch=0; iPatch=0) && (iMaskBitiMaskBit; iPatch--) + { + INDEX iCurrentPatch = iPatch%32; + CTString strPatchName = edm_md.md_mpPatches[ iCurrentPatch].mp_strName; + if( strPatchName != "") + { + iMaskBit = iCurrentPatch; + return; + } + } +} +//-------------------------------------------------------------------------------------------- +/* + * Sets next valid patch position in existing patches mask + */ +void CEditModel::GetNextValidPatchIndex( INDEX &iMaskBit) +{ + ASSERT( (iMaskBit>=0) && (iMaskBitmmpi_aPolygonsPerPatch.Clear(); + // if patches are visible in this mip model + if( (pMMI->mmpi_ulFlags & MM_PATCHES_VISIBLE) && (ctPatches != 0) ) + { + // add description member for each patch + pMMI->mmpi_aPolygonsPerPatch.New( ctPatches); + INDEX iExistingPatch = 0; + // for each patch + for(INDEX iPatch=0; iPatch aiPolygons; + aiPolygons.New( pMMI->mmpi_PolygonsCt); + // clear counter of occupied polygons + INDEX ctOccupiedPolygons = 0; + // get patch occupying box + CTextureData *pTD = (CTextureData *) edm_md.md_mpPatches[ iPatch].mp_toTexture.GetData(); + ASSERT( pTD != NULL); + MEX2D mex2dPosition = edm_md.md_mpPatches[ iPatch].mp_mexPosition; + FLOAT fStretch = edm_md.md_mpPatches[ iPatch].mp_fStretch; + MEXaabbox2D boxPatch = MEXaabbox2D( + mex2dPosition, MEX2D( mex2dPosition(1)+pTD->GetWidth()*fStretch, + mex2dPosition(2)+pTD->GetHeight()*fStretch) ); + // for each polygon + for(INDEX iPolygon=0; iPolygonmmpi_PolygonsCt; iPolygon++) + { + ModelPolygon *pMP = &pMMI->mmpi_Polygons[iPolygon]; + // for all vertices in polygon + MEXaabbox2D boxMapping; + for( INDEX iVertex=0; iVertexmp_PolygonVertices.Count(); iVertex++) + { + ModelTextureVertex *pMTV = pMP->mp_PolygonVertices[iVertex].mpv_ptvTextureVertex; + // calculate bounding box of mapping coordinates + boxMapping |= MEXaabbox2D(pMTV->mtv_UV); + } + // if bounding box of polygon's mapping coordinates touches patch + if( boxPatch.HasContactWith( boxMapping)) + { + // add polygon index to list of occupied polygons + aiPolygons[ ctOccupiedPolygons] = iPolygon; + ctOccupiedPolygons++; + } + } + if( ctOccupiedPolygons != 0) + { + // copy temporary array of polygon indices to mip model's array of polygon indices + pMMI->mmpi_aPolygonsPerPatch[ iExistingPatch].ppp_iPolygons.New( ctOccupiedPolygons); + for( INDEX iOccupied=0; iOccupiedmmpi_aPolygonsPerPatch[ iExistingPatch].ppp_iPolygons[iOccupied] = + aiPolygons[ iOccupied]; + } + } + // count existing patches + iExistingPatch++; + } + } + } + } +} +//-------------------------------------------------------------------------------------------- +/* + * Writes settings of given mip model into file + */ +void CEditModel::WriteMipSettings_t( CTStream *ostrFile, INDEX iMip) +{ + ASSERT( iMip < edm_md.md_MipCt); + + // write indetification of one mip's mapping info + ostrFile->WriteID_t( CChunkID( "MIPS")); + + // get count + INDEX iSurfacesCt = edm_md.md_MipInfos[ iMip].mmpi_MappingSurfaces.Count(); + // write count + (*ostrFile) << iSurfacesCt; + // for all surfaces + FOREACHINSTATICARRAY(edm_md.md_MipInfos[ iMip].mmpi_MappingSurfaces, MappingSurface, itSurface) + { + // write setings for current surface + itSurface->WriteSettings_t( ostrFile); + } +} +//-------------------------------------------------------------------------------------------- +/* + * Reads settigns of given mip model from file + */ +void CEditModel::ReadMipSettings_t(CTStream *istrFile, INDEX iMip) +{ + MappingSurface msTmp; + + ASSERT( iMip < edm_md.md_MipCt); + + // check chunk + istrFile->ExpectID_t( CChunkID( "MIPS")); + // get count + INDEX iSurfacesCt; + *istrFile >> iSurfacesCt; + + // for all saved surfaces + for( INDEX iSurface=0; iSurfaceWrite_t( &strmMappingFile); + } + FOREACHINDYNAMICARRAY(edm_md.md_aampAttachedPosition, CAttachedModelPosition, itamp) + { + itamp->Write_t( &strmMappingFile); + } + + // save collision boxes + INDEX ctCollisionBoxes = edm_md.md_acbCollisionBox.Count(); + ASSERT( ctCollisionBoxes>0); + if(ctCollisionBoxes == 0) + { + WarningMessage( "Trying to save 0 collision boxes into mapping file."); + } + strmMappingFile<Write_t( &strmMappingFile); + } + + // save patches + for( INDEX iPatch=0; iPatch> iSurfacesCt; + for( INDEX iSurface=0; iSurface>ctSounds; + ASSERT(ctSounds > 0); + edm_aasAttachedSounds.Clear(); + edm_aasAttachedSounds.New( ctSounds); + for( INDEX iSound=0; iSound>ctAttachmentPositions; + edm_aamAttachedModels.Clear(); + edm_md.md_aampAttachedPosition.Clear(); + if( ctAttachmentPositions != 0) + { + edm_aamAttachedModels.New(ctAttachmentPositions); + edm_md.md_aampAttachedPosition.New(ctAttachmentPositions); + FOREACHINDYNAMICARRAY(edm_aamAttachedModels, CAttachedModel, itam) + { + try + { + itam->Read_t( &strmMappingFile); + } + catch( char *strError) + { + (void) strError; + edm_aamAttachedModels.Clear(); + edm_md.md_aampAttachedPosition.Clear(); + ThrowF_t( "Error ocured while reading attahment model, maybe model does" + " not exist."); + } + } + FOREACHINDYNAMICARRAY(edm_md.md_aampAttachedPosition, CAttachedModelPosition, itamp) + { + itamp->Read_t( &strmMappingFile); + } + } + } + + if( bReadCollision) + { + // read collision boxes + edm_md.md_acbCollisionBox.Clear(); + INDEX ctCollisionBoxes; + strmMappingFile>>ctCollisionBoxes; + ASSERT(ctCollisionBoxes>0); + if( ctCollisionBoxes>0) + { + edm_md.md_acbCollisionBox.New( ctCollisionBoxes); + FOREACHINDYNAMICARRAY(edm_md.md_acbCollisionBox, CModelCollisionBox, itcb) + { + itcb->Read_t( &strmMappingFile); + itcb->ReadName_t( &strmMappingFile); + } + } + else + { + edm_md.md_acbCollisionBox.New( 1); + throw( "Trying to load 0 collision boxes from mapping file."); + } + } + + if( bReadPatches) + { + EditRemoveAllPatches(); + for( INDEX iPatch=0; iPatch= ctCollisionBoxes) + { + iCollisionBox = ctCollisionBoxes-1; + } + CTString strCollisionBoxName; + edm_md.md_acbCollisionBox.Lock(); + strCollisionBoxName = edm_md.md_acbCollisionBox[ iCollisionBox].mcb_strName; + edm_md.md_acbCollisionBox.Unlock(); + return strCollisionBoxName; +} + +CTString CEditModel::GetCollisionBoxName(void) +{ + CTString strCollisionBoxName; + edm_md.md_acbCollisionBox.Lock(); + strCollisionBoxName = edm_md.md_acbCollisionBox[ edm_iActiveCollisionBox].mcb_strName; + edm_md.md_acbCollisionBox.Unlock(); + return strCollisionBoxName; +} + +void CEditModel::SetCollisionBoxName(CTString strNewName) +{ + edm_md.md_acbCollisionBox.Lock(); + edm_md.md_acbCollisionBox[ edm_iActiveCollisionBox].mcb_strName = strNewName; + edm_md.md_acbCollisionBox.Unlock(); +} + +void CEditModel::CorrectCollisionBoxSize(void) +{ + // no correction needed if colliding as cube + if( edm_md.md_bCollideAsCube) return; + edm_md.md_acbCollisionBox.Lock(); + // get equality radio initial value + INDEX iEqualityType = GetCollisionBoxDimensionEquality(); + // get min and max vectors of currently active collision box + FLOAT3D vMin = edm_md.md_acbCollisionBox[ edm_iActiveCollisionBox].mcb_vCollisionBoxMin; + FLOAT3D vMax = edm_md.md_acbCollisionBox[ edm_iActiveCollisionBox].mcb_vCollisionBoxMax; + FLOAT3D vOldCenter; + + vOldCenter(1) = (vMax(1)+vMin(1))/2.0f; + vOldCenter(3) = (vMax(3)+vMin(3))/2.0f; + + // calculate vector of collision box diagonale + FLOAT3D vCorrectedDiagonale = vMax-vMin; + // apply minimal collision box conditions + if( vCorrectedDiagonale(1) < 0.1f) vCorrectedDiagonale(1) = 0.01f; + if( vCorrectedDiagonale(2) < 0.1f) vCorrectedDiagonale(2) = 0.01f; + if( vCorrectedDiagonale(3) < 0.1f) vCorrectedDiagonale(3) = 0.01f; + // according to equality type flag (which dimensions are same) + switch( iEqualityType) + { + case HEIGHT_EQ_WIDTH: + { + // don't allow that unlocked dimension is smaller than locked ones + if( vCorrectedDiagonale(3) < vCorrectedDiagonale(1) ) + { + vCorrectedDiagonale(3) = vCorrectedDiagonale(1); + } + // height = width + vCorrectedDiagonale(2) = vCorrectedDiagonale(1); + break; + } + case LENGTH_EQ_WIDTH: + { + // don't allow that unlocked dimension is smaller than locked ones + if( vCorrectedDiagonale(2) < vCorrectedDiagonale(1) ) + { + vCorrectedDiagonale(2) = vCorrectedDiagonale(1); + } + // lenght = width + vCorrectedDiagonale(3) = vCorrectedDiagonale(1); + break; + } + case LENGTH_EQ_HEIGHT: + { + // don't allow that unlocked dimension is smaller than locked ones + if( vCorrectedDiagonale(1) < vCorrectedDiagonale(2) ) + { + vCorrectedDiagonale(1) = vCorrectedDiagonale(2); + } + // lenght = height + vCorrectedDiagonale(3) = vCorrectedDiagonale(2); + break; + } + default: + { + ASSERTALWAYS( "Invalid collision box dimension equality value found."); + } + } + // set new, corrected max vector + FLOAT3D vNewMin, vNewMax; + vNewMin(1) = vOldCenter(1)-vCorrectedDiagonale(1)/2.0f; + vNewMin(2) = vMin(2); + vNewMin(3) = vOldCenter(3)-vCorrectedDiagonale(3)/2.0f; + + vNewMax(1) = vOldCenter(1)+vCorrectedDiagonale(1)/2.0f; + vNewMax(2) = vMin(2)+vCorrectedDiagonale(2); + vNewMax(3) = vOldCenter(3)+vCorrectedDiagonale(3)/2.0f; + + edm_md.md_acbCollisionBox[ edm_iActiveCollisionBox].mcb_vCollisionBoxMin = vNewMin; + edm_md.md_acbCollisionBox[ edm_iActiveCollisionBox].mcb_vCollisionBoxMax = vNewMax; + edm_md.md_acbCollisionBox.Unlock(); +} +//--------------------------------------------------------------------------------------------- +// collision box handling functions +FLOAT3D &CEditModel::GetCollisionBoxMin(void) +{ + edm_md.md_acbCollisionBox.Lock(); + FLOAT3D &vMin = edm_md.md_acbCollisionBox[edm_iActiveCollisionBox].mcb_vCollisionBoxMin; + edm_md.md_acbCollisionBox.Unlock(); + return vMin; +}; +FLOAT3D &CEditModel::GetCollisionBoxMax(void) +{ + edm_md.md_acbCollisionBox.Lock(); + FLOAT3D &vMax = edm_md.md_acbCollisionBox[edm_iActiveCollisionBox].mcb_vCollisionBoxMax; + edm_md.md_acbCollisionBox.Unlock(); + return vMax; +}; + +// returns HEIGHT_EQ_WIDTH, LENGHT_EQ_WIDTH or LENGHT_EQ_HEIGHT +INDEX CEditModel::GetCollisionBoxDimensionEquality() +{ + return edm_md.GetCollisionBoxDimensionEquality(edm_iActiveCollisionBox); +}; +// set new collision box equality value +void CEditModel::SetCollisionBoxDimensionEquality( INDEX iNewDimEqType) +{ + edm_md.md_acbCollisionBox.Lock(); + edm_md.md_acbCollisionBox[edm_iActiveCollisionBox].mcb_iCollisionBoxDimensionEquality = + iNewDimEqType; + edm_md.md_acbCollisionBox.Unlock(); + CorrectCollisionBoxSize(); +}; + + + + + +#if 0 + // only triangles are supported! + ASSERT( opo.opo_PolygonEdges.Count() == 3); + if( opo.opo_PolygonEdges.Count() != 3) { + ThrowF_t( "Non-triangle polygon encountered in model file %s !", (CTString)itFr->cfnn_FileName); + } + + CObjectPolygonEdge &ope0 = opo.opo_PolygonEdges[0]; + CObjectPolygonEdge &ope1 = opo.opo_PolygonEdges[1]; + if( ope0.ope_Backward) { + povx0 = ope0.ope_Edge->oed_Vertex1; + povx1 = ope0.ope_Edge->oed_Vertex0; + povx2 = ope1.ope_Edge->oed_Vertex0; + ASSERT( ope1.ope_Edge->oed_Vertex1 == povx1); + } else { + povx0 = ope0.ope_Edge->oed_Vertex0; + povx1 = ope0.ope_Edge->oed_Vertex1; + povx2 = ope1.ope_Edge->oed_Vertex1; + ASSERT( ope1.ope_Edge->oed_Vertex0 == povx1); + } + + if( povx1==&ovxThis || povx0==&ovxThis || povx2==&ovxThis) { + DOUBLE3D v0 = (*povx0)-(*povx1); + DOUBLE3D v1 = (*povx2)-(*povx1); + v0.Normalize(); + v1.Normalize(); + ANGLE a = ASin( (v0*v1).Length()); + ASSERT( a>=0 && a<=180); + aSum += a; + vSum += DOUBLEtoFLOAT( (DOUBLE3D&)*(itPoly->opo_Plane)) * a; + break; + } +#endif diff --git a/Sources/Engine/Models/EditModel.h b/Sources/Engine/Models/EditModel.h new file mode 100644 index 0000000..46eb9e5 --- /dev/null +++ b/Sources/Engine/Models/EditModel.h @@ -0,0 +1,244 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_EDITMODEL_H +#define SE_INCL_EDITMODEL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_MODELERTEXTURES 32 +#define MAPPING_VERSION_WITHOUT_POLYGONS_PER_SURFACE "0001" +#define MAPPING_VERSION_WITHOUT_SOUNDS_AND_ATTACHMENTS "0002" +#define MAPPING_VERSION_WITHOUT_COLLISION "0003" +#define MAPPING_VERSION_WITHOUT_PATCHES "0004" +#define MAPPING_WITHOUT_SURFACE_COLORS "0005" +#define MAPPING_VERSION "0006" + +class ENGINE_API CProgressRoutines +{ +public: + CProgressRoutines(); + void (*SetProgressMessage)( char *strMessage); // sets message for modeler's "new progress dialog" + void (*SetProgressRange)( INDEX iProgresSteps); // sets range of modeler's "new progress dialog" + void (*SetProgressState)( INDEX iCurrentStep); // sets current modeler's "new progress dialog" state +}; + +ENGINE_API extern CProgressRoutines ProgresRoutines; + +class ENGINE_API CTextureDataInfo +{ +public: + CListNode tdi_ListNode; + CTextureData *tdi_TextureData; + CTFileName tdi_FileName; +}; + +#define UNDO_VERTEX 0 +#define UNDO_SURFACE 1 + +class ENGINE_API CMappingUndo +{ +public: + CListNode mu_ListNode; + INDEX mu_Action; + ModelTextureVertex *mu_ClosestVertex; + FLOAT3D mu_UndoCoordinate; + INDEX mu_iCurrentMip; + INDEX mu_iCurrentSurface; + FLOAT mu_Zoom; + FLOAT3D mu_Center; + FLOAT3D mu_HPB; +}; + +class ENGINE_API CAttachedModel { +public: + BOOL am_bVisible; + CModelObject am_moAttachedModel; // used as smart pointer (holds file name of attachment), never rendered + CTString am_strName; + INDEX am_iAnimation; + + CAttachedModel(void); + ~CAttachedModel(void); + void SetModel_t(CTFileName fnModel); + void Read_t( CTStream *strFile); // throw char * + void Write_t( CTStream *strFile); // throw char * + void Clear(void); // clear the object. +}; + +class ENGINE_API CAttachedSound { +public: + BOOL as_bLooping; + BOOL as_bPlaying; + FLOAT as_fDelay; + CTFileName as_fnAttachedSound; + + CAttachedSound(void); + void Read_t( CTStream *strFile); // throw char * + void Write_t( CTStream *strFile); // throw char * + void Clear(void) { as_fnAttachedSound = CTString("");}; +}; + +class ENGINE_API CThumbnailSettings { +public: + BOOL ts_bSet; + CPlacement3D ts_plLightPlacement; + CPlacement3D ts_plModelPlacement; + FLOAT ts_fTargetDistance; + FLOAT3D ts_vTarget; + ANGLE3D ts_angViewerOrientation; + FLOAT ts_LightDistance; + COLOR ts_LightColor; + COLOR ts_colAmbientColor; + COLORREF ts_PaperColor; + COLORREF ts_InkColor; + BOOL ts_IsWinBcgTexture; + CTFileName ts_WinBcgTextureName; + CModelRenderPrefs ts_RenderPrefs; + + CThumbnailSettings( void); + void Read_t( CTStream *strFile); // throw char * + void Write_t( CTStream *strFile); // throw char * +}; + +class ENGINE_API CEditModel : public CSerial +{ +private: + void NewModel(CObject3D *pO3D); // creates new model, surface, vertice and polygon arrays + void AddMipModel(CObject3D *pO3D); // adds one mip model + // loads and converts model's animation data from script file + void LoadModelAnimationData_t( CTStream *pFile, const FLOATmatrix3D &mStretch); // throw char * + INDEX edm_iActiveCollisionBox; // collision box that is currently edited +public: + CEditModel(); // default contructor + ~CEditModel(); // default destructor + CModelData edm_md; // edited model data + CDynamicArray edm_aamAttachedModels;// array of attached models + CStaticArray edm_aasAttachedSounds;// array of attached sounds + CThumbnailSettings edm_tsThumbnailSettings; // remembered parameters for taking thumbnail + CListHead edm_WorkingSkins; // list of file names and texture data objects + CListHead edm_UndoList; // list containing structures used for undo operation + CListHead edm_RedoList; // list containing structures used for redo operation + INDEX edm_Action; // type of last mapping change action (used by undo/redo) + CTFileName edm_fnSpecularTexture; // names of textures saved in ini file + CTFileName edm_fnReflectionTexture; + CTFileName edm_fnBumpTexture; + // create empty attaching sounds + void CreateEmptyAttachingSounds(void); + // creates default script file + void CreateScriptFile_t(CTFileName &fnFile); // throw char * + // creates mip-model and mapping default constructios after it loads data from script + void LoadFromScript_t(CTFileName &fnFileName); // throw char * + // recalculate mapping for surface after some polygon has been added to surface + void RecalculateSurfaceMapping( INDEX iMipModel, INDEX iSurface); + // functions for extracting texture vertex links for given mip model + void CalculateSurfaceCenterOffset( INDEX iCurrentMip, INDEX iSurface); + void RemapTextureVerticesForSurface(INDEX iMip, INDEX iSurface, BOOL bJustCount); + void RemapTextureVertices( INDEX iCurrentMip); + // calculates mapping from three special 3D objects + void CalculateUnwrappedMapping( CObject3D &o3dClosed, CObject3D &o3dOpened, CObject3D &o3dUnwrapped); + // calculates mapping for mip models (except for main mip) + void CalculateMappingForMips(void); + // updates animations + void UpdateAnimations_t(CTFileName &fnScriptName); // throw char * + // updates mip models configuration, looses their mapping ! + void UpdateMipModels_t(CTFileName &fnScriptName); // throw char * + void CreateMipModels_t(CObject3D &objRestFrame, CObject3D &objMipSourceFrame, + INDEX iVertexRemoveRate, INDEX iSurfacePreservingFactor); + void DefaultMapping( INDEX iCurrentMip, INDEX iSurface=-1);// sets default mapping for given mip-model and surface (or all surfaces -1) + void CalculateMapping( INDEX iCurrentMip, INDEX iSurfaceNo); // calculate mapping coordinates + void CalculateMappingAll( INDEX iCurrentMip); + void DrawWireSurface( CDrawPort *pDP, INDEX iCurrentMip, INDEX iCurrentSurface, + FLOAT fMagnifyFactor, PIX offx, PIX offy, COLOR clrVisible, COLOR clrInvisible); // draws given surface in wire frame + void DrawFilledSurface( CDrawPort *pDP, INDEX iCurrentMip, INDEX iCurrentSurface, + FLOAT fMagnifyFactor, PIX offx, PIX offy, COLOR clrVisible, COLOR clrInvisible); // fills given surface with color + void PrintSurfaceNumbers( CDrawPort *pDP, CFontData *pFont, INDEX iCurrentMip, + FLOAT fMagnifyFactor, PIX offx, PIX offy, COLOR clrInk); // prints surface numbers + void ExportSurfaceNumbersAndNames( CTFileName fnFile); + void GetScreenSurfaceCenter( CDrawPort *pDP, INDEX iCurrentMip, + INDEX iCurrentSurface, FLOAT fMagnifyFactor, PIX offx, PIX offy, + PIX &XCenter, PIX &YCenter); // Calculates given surface's center point in view's window (in pixels) + FLOATaabbox3D CalculateSurfaceBBox( INDEX iCurrentMip, // used to calculate mapping coordinate's bbox + INDEX iSurfaceNo, FLOAT3D f3Position, FLOAT3D f3Angle, FLOAT fZoom); + void CalculateMapping(); // used to calculate mapping coordinates + BOOL ChangeSurfacePositionRelative( INDEX iCurrentMip, INDEX iCurrentSurface, FLOAT fDZoom, + FLOAT dX, FLOAT dY, PIX dTH, PIX dTV); // if it can, sets surface position with given offseted values + BOOL ChangeSurfacePositionAbsolute( INDEX iCurrentMip, INDEX iCurrentSurface, + FLOAT newZoom, FLOAT3D newCenter, FLOAT3D newAngle); // if it can, sets surface position to given values + void RememberSurfaceUndo( INDEX iCurrentMip, INDEX iCurrentSurface); // remember undo position + ModelTextureVertex *FindClosestMappingVertex( INDEX iCurrentMip, INDEX iCurrentSurface, + PIX ptx, PIX pty, FLOAT fMagnifyFactor, PIX offx, PIX offy);// finds closest point and returns it + void MoveVertex( ModelTextureVertex *pmtvClosestVertex, PIX dx, PIX dy, INDEX iCurrentMip, INDEX iCurrentSurface); // try new vertex position + void RememberVertexUndo( ModelTextureVertex *pmtvClosestVertex);// remember coordinate change into undo buffer + // add one texture to list of working textures + CTextureDataInfo *AddTexture_t(const CTFileName &fnFileName, const MEX mexWidth, + const MEX mexHeight); // throw char * + FLOAT3D GetSurfacePos(INDEX iCurrentMip, INDEX iCurrentSurface); // Retrieves given surface's position + FLOAT3D GetSurfaceAngles(INDEX iCurrentMip, INDEX iCurrentSurface); // Retrieves given surface's angles + FLOAT GetSurfaceZoom(INDEX iCurrentMip, INDEX iCurrentSurface); // Retrieves given surface's zoom factor + const char *GetSurfaceName(INDEX iCurrentMip, INDEX iCurrentSurface); // Retrieves given surface's name + void Undo(void); // Undoes last operation + void Redo(void); // Redoes last operation + void RemoveTexture(char *pFileName); // removes one of working textures in modeler app + void MovePatchRelative( INDEX iMaskBit, MEX2D mexOffset); + void SetPatchStretch( INDEX iMaskBit, FLOAT fNewStretch); + BOOL EditAddPatch( CTFileName fnPatchName, MEX2D mexPos, INDEX &iMaskBit); // Adds one patch + void EditRemovePatch( INDEX iMaskBit); // Removes given patch + void EditRemoveAllPatches( void); + INDEX CountPatches(void); + ULONG GetExistingPatchesMask(void); + BOOL GetFirstEmptyPatchIndex( INDEX &iMaskBit); // Finds first empty space ready to receive new patch + BOOL GetFirstValidPatchIndex( INDEX &iMaskBit); // Finds first valid patch index + void GetPreviousValidPatchIndex( INDEX &iMaskBit);// Sets previous valid patch index + void GetNextValidPatchIndex( INDEX &iMaskBit); // Sets next valid patch index + void CalculatePatchesPerPolygon(void); + INDEX GetMipCt(){ return edm_md.md_MipCt;}; // Returns number of mip models + MEX GetWidth(){ return edm_md.md_Width;}; // Returns allowed width for model's texture + MEX GetHeight(){ return edm_md.md_Height;}; // Returns allowed height for model's texture + // collision box handling functions + FLOAT3D &GetCollisionBoxMin(void); + FLOAT3D &GetCollisionBoxMax(void); + void AddCollisionBox(void); + void DeleteCurrentCollisionBox(void); + INDEX GetActiveCollisionBoxIndex(void) { return edm_iActiveCollisionBox;}; + void ActivatePreviousCollisionBox(void); + void ActivateNextCollisionBox(void); + void SetCollisionBox(FLOAT3D vMin, FLOAT3D vMax); + CTString GetCollisionBoxName(INDEX iCollisionBox); + CTString GetCollisionBoxName(void); + void SetCollisionBoxName(CTString strNewName); + void CorrectCollisionBoxSize(void); + // returns HEIGHT_EQ_WIDTH, LENGTH_EQ_WIDTH or LENGTH_EQ_HEIGHT + INDEX GetCollisionBoxDimensionEquality(); + // set new collision box equality value + void SetCollisionBoxDimensionEquality( INDEX iNewDimEqType); + // overloaded load function + void Load_t( CTFileName fnFileName); // throw char * + // overloaded save function + void Save_t( CTFileName fnFileName); // throw char * + // exports .h file (#define ......) + void SaveIncludeFile_t( CTFileName fnFileName, CTString strDefinePrefix); // throw char * + + // know how to load + void Read_t( CTStream *istrFile); // throw char * + // and save modeler data (i.e. vindow positions, view prefs, texture file names...) + void Write_t( CTStream *ostrFile); // throw char * + + // load and save mapping data for whole model (iMip = -1) or just for one mip model + void LoadMapping_t( CTFileName fnFileName, INDEX iMip = -1); + void SaveMapping_t( CTFileName fnFileName, INDEX iMip = -1); + // read and write settings for given mip + void ReadMipSettings_t( CTStream *istrFile, INDEX iMip); // throw char * + void WriteMipSettings_t( CTStream *ostrFile, INDEX iMip); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Models/MipMaker.cpp b/Sources/Engine/Models/MipMaker.cpp new file mode 100644 index 0000000..3a9ba1b --- /dev/null +++ b/Sources/Engine/Models/MipMaker.cpp @@ -0,0 +1,473 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include + +#include +#include + +// if vertex removing should occure only inside surfaces +static BOOL _bPreserveSurfaces; + + +CMipModel::~CMipModel() +{ + mm_amsSurfaces.Clear(); + mm_ampPolygons.Clear(); + mm_amvVertices.Clear(); +} + +CMipVertex::CMipVertex() +{ +} +CMipVertex::~CMipVertex() +{ +} +void CMipVertex::Clear() +{ +} + +CMipPolygon::CMipPolygon() +{ + mp_pmpvFirstPolygonVertex = NULL; +} +CMipPolygon::~CMipPolygon() +{ + Clear(); +} +void CMipPolygon::Clear() +{ + if (mp_pmpvFirstPolygonVertex!=NULL) { + // delete all vertices in this polygon + CMipPolygonVertex *pmpvCurrentInPolygon = mp_pmpvFirstPolygonVertex; + do + { + CMipPolygonVertex *pvNextInPolygon = pmpvCurrentInPolygon->mpv_pmpvNextInPolygon; + delete pmpvCurrentInPolygon; + pmpvCurrentInPolygon = pvNextInPolygon; + } + while( pmpvCurrentInPolygon != mp_pmpvFirstPolygonVertex); + } + mp_pmpvFirstPolygonVertex = NULL; +} + +void CMipModel::ToObject3D( CObject3D &objDestination) +{ + // add one sector + CObjectSector *pOS = objDestination.ob_aoscSectors.New(1); + // add vertices to sector + pOS->osc_aovxVertices.New( mm_amvVertices.Count()); + pOS->osc_aovxVertices.Lock(); + INDEX iVertice = 0; + FOREACHINDYNAMICARRAY( mm_amvVertices, CMipVertex, itVertice) + { + FLOAT3D vRestFrame = itVertice->mv_vRestFrameCoordinate; + pOS->osc_aovxVertices[ iVertice] = FLOATtoDOUBLE( vRestFrame); + iVertice++; + } + + // add mip surfaces as materials to object 3d + pOS->osc_aomtMaterials.New( mm_amsSurfaces.Count()); + pOS->osc_aomtMaterials.Lock(); + INDEX iMaterial = 0; + FOREACHINDYNAMICARRAY( mm_amsSurfaces, CMipSurface, itSurface) + { + pOS->osc_aomtMaterials[ iMaterial].omt_Name = itSurface->ms_strName; + pOS->osc_aomtMaterials[ iMaterial].omt_Color = itSurface->ms_colColor; + iMaterial ++; + } + + + // add polygons to object 3d + FOREACHINDYNAMICARRAY( mm_ampPolygons, CMipPolygon, itPolygon) + { + // prepare array of polygon vertex indices + INDEX aivVertices[ 32]; + CMipPolygonVertex *pmpvPolygonVertex = itPolygon->mp_pmpvFirstPolygonVertex; + INDEX ctPolygonVertices = 0; + do + { + ASSERT( ctPolygonVertices<32); + if( ctPolygonVertices >= 32) break; + // add global index of vertex to list of vertex indices of polygon + mm_amvVertices.Lock(); + aivVertices[ ctPolygonVertices] = + mm_amvVertices.Index( pmpvPolygonVertex->mpv_pmvVertex); + mm_amvVertices.Unlock(); + pmpvPolygonVertex = pmpvPolygonVertex->mpv_pmpvNextInPolygon; + ctPolygonVertices ++; + } + while( pmpvPolygonVertex != itPolygon->mp_pmpvFirstPolygonVertex); + // add current polygon + pOS->CreatePolygon( ctPolygonVertices, aivVertices, + pOS->osc_aomtMaterials[ itPolygon->mp_iSurface], 0, FALSE); + } + pOS->osc_aomtMaterials.Unlock(); + pOS->osc_aovxVertices.Unlock(); +} + +void CMipModel::FromObject3D_t( CObject3D &objRestFrame, CObject3D &objMipSourceFrame) +{ + INDEX ctInvalidVertices = 0; + CTString strInvalidVertices; + char achrErrorVertice[ 256]; + objMipSourceFrame.ob_aoscSectors.Lock(); + objRestFrame.ob_aoscSectors.Lock(); + // lock object sectors dynamic array + objMipSourceFrame.ob_aoscSectors[0].LockAll(); + objRestFrame.ob_aoscSectors[0].LockAll(); + + CObjectSector *pOS = &objMipSourceFrame.ob_aoscSectors[0]; + // add mip surface + mm_amsSurfaces.New( pOS->osc_aomtMaterials.Count()); + // copy material data from object 3d to mip surfaces + INDEX iMaterial = 0; + FOREACHINDYNAMICARRAY( mm_amsSurfaces, CMipSurface, itSurface) + { + itSurface->ms_strName = pOS->osc_aomtMaterials[ iMaterial].omt_Name; + itSurface->ms_colColor = pOS->osc_aomtMaterials[ iMaterial].omt_Color; + iMaterial ++; + } + + // add mip vertices + mm_amvVertices.New( pOS->osc_aovxVertices.Count()); + // copy vertice coordinates from object3d to mip vertices + INDEX iVertice = 0; + {FOREACHINDYNAMICARRAY( mm_amvVertices, CMipVertex, itVertice) + { + (FLOAT3D &)(*itVertice) = DOUBLEtoFLOAT( pOS->osc_aovxVertices[ iVertice]); + itVertice->mv_vRestFrameCoordinate = + DOUBLEtoFLOAT( objRestFrame.ob_aoscSectors[0].osc_aovxVertices[ iVertice]); + // calculate bounding box of all vertices + mm_boxBoundingBox |= *itVertice; + iVertice++; + }} + + // add mip polygons + mm_ampPolygons.New( pOS->osc_aopoPolygons.Count()); + // copy polygons object 3d to mip polygons + INDEX iPolygon = 0; + FOREACHINDYNAMICARRAY( mm_ampPolygons, CMipPolygon, itPolygon) + { + CObjectPolygon &opoPolygon = pOS->osc_aopoPolygons[ iPolygon]; + CMipPolygon &mpPolygon = itPolygon.Current(); + INDEX ctPolygonVertices = opoPolygon.opo_PolygonEdges.Count(); + // allocate polygon vertices + CMipPolygonVertex *ppvPolygonVertices[ 32]; + INDEX iPolygonVertice=0; + for( ; iPolygonVerticeosc_aovxVertices.Index( povxStart); + // set references to mip polygon and mip vertex + ppvPolygonVertex->mpv_pmpPolygon = &mpPolygon; + mm_amvVertices.Lock(); + ppvPolygonVertex->mpv_pmvVertex = &mm_amvVertices[iVertexInSector]; + mm_amvVertices.Unlock(); + // link to previous and next vertices in the mip polygon + INDEX iNext=(iPolygonVertice+1)%ctPolygonVertices; + ppvPolygonVertex->mpv_pmpvNextInPolygon = ppvPolygonVertices[ iNext]; + } + opoPolygon.opo_PolygonEdges.Unlock(); + + // set first polygon vertex ptr and surface index to polygon + itPolygon->mp_pmpvFirstPolygonVertex = ppvPolygonVertices[ 0]; + itPolygon->mp_iSurface = + pOS->osc_aomtMaterials.Index( opoPolygon.opo_Material); + iPolygon++; + } + + objRestFrame.ob_aoscSectors[0].UnlockAll(); + // unlock all dynamic arrays in sector + objMipSourceFrame.ob_aoscSectors[0].UnlockAll(); + objRestFrame.ob_aoscSectors.Unlock(); + objMipSourceFrame.ob_aoscSectors.Unlock(); + + if( ctInvalidVertices != 0) + { + sprintf( achrErrorVertice, + "%d invalid vertices found\n-------------------------\n\n", ctInvalidVertices); + strInvalidVertices = CTString( achrErrorVertice) + strInvalidVertices; + strInvalidVertices.Save_t( CTFileName(CTString("Temp\\ErrorVertices.txt"))); + ThrowF_t( "%d invalid vertices found.\nUnable to create mip models.\nList of vertices " + "that must be fixed can be found in file: \"Temp\\ErrorVertices.txt\".", + ctInvalidVertices); + } +} + +void CMipModel::CheckObjectValidity(void) +{ + // for all polygons + FOREACHINDYNAMICARRAY( mm_ampPolygons, CMipPolygon, itPolygon) + { + CMipPolygon &mpMipPolygon = *itPolygon; + CMipPolygonVertex *pvFirstInPolygon = mpMipPolygon.mp_pmpvFirstPolygonVertex; + CMipPolygonVertex *pvCurrent = pvFirstInPolygon; + do + { + ASSERT( pvCurrent->mpv_pmpPolygon == &mpMipPolygon); + pvCurrent = pvCurrent->mpv_pmpvNextInPolygon; + } + while( pvCurrent != pvFirstInPolygon); + } +} + +FLOAT CMipModel::GetGoodness(CMipVertex *pmvSource, CMipVertex *pmvTarget) +{ + if( (_bPreserveSurfaces) && (pmvSource->mv_iSurface == -2) ) return -10000.0f; + FLOAT fDistST = ( *pmvSource - *pmvTarget).Length(); + FLOAT fDistBBoxCenterT = ( mm_boxBoundingBox.Center() - *pmvTarget).Length(); + return fDistBBoxCenterT/100.0f + 1.0f/fDistST; +} + +INDEX CMipModel::FindSurfacesForVertices(void) +{ + {FOREACHINDYNAMICARRAY( mm_amvVertices, CMipVertex, itVertice) + { + itVertice->mv_iSurface = -1; + }} + + // for all polygons + {FOREACHINDYNAMICARRAY( mm_ampPolygons, CMipPolygon, itPolygon) + { + // for all vertices in this polygon + CMipPolygonVertex *pmpvCurrentInPolygon = itPolygon->mp_pmpvFirstPolygonVertex; + do + { + CMipVertex *pmvVertex = pmpvCurrentInPolygon->mpv_pmvVertex; + if( pmvVertex->mv_iSurface == -1) pmvVertex->mv_iSurface = itPolygon->mp_iSurface; + else if( pmvVertex->mv_iSurface == -2); // do nothing + else if( pmvVertex->mv_iSurface == itPolygon->mp_iSurface); // do nothing + else pmvVertex->mv_iSurface = -2; + pmpvCurrentInPolygon = pmpvCurrentInPolygon->mpv_pmpvNextInPolygon; + } + while( pmpvCurrentInPolygon != itPolygon->mp_pmpvFirstPolygonVertex); + }} + + // count vertices that are sourounded with only one surface + INDEX ctVerticesWithOneSurface = 0; + // for all vertices + {FOREACHINDYNAMICARRAY( mm_amvVertices, CMipVertex, itVertice) + { + if( itVertice->mv_iSurface >= 0) ctVerticesWithOneSurface++; + }} + return ctVerticesWithOneSurface; +} + +void CMipModel::JoinVertexPair( CMipVertex *pmvBestSource, CMipVertex *pmvBestTarget) +{ + // for all polygons + {FOREACHINDYNAMICARRAY( mm_ampPolygons, CMipPolygon, itPolygon) + { + // for all vertices in this polygon + CMipPolygonVertex *pmpvCurrentInPolygon = itPolygon->mp_pmpvFirstPolygonVertex; + do + { + if( pmpvCurrentInPolygon->mpv_pmvVertex == pmvBestSource) + { + pmpvCurrentInPolygon->mpv_pmvVertex = pmvBestTarget; + } + pmpvCurrentInPolygon = pmpvCurrentInPolygon->mpv_pmpvNextInPolygon; + } + while( pmpvCurrentInPolygon != itPolygon->mp_pmpvFirstPolygonVertex); + }} + // delete best source vertex + mm_amvVertices.Delete( pmvBestSource); + + // for all polygons + {FOREACHINDYNAMICARRAY( mm_ampPolygons, CMipPolygon, itPolygon) + { + // for all vertices in this polygon + CMipPolygonVertex *pmpvCurrentInPolygon = itPolygon->mp_pmpvFirstPolygonVertex; + do + { + CMipPolygonVertex *pmpvSuccesor = pmpvCurrentInPolygon->mpv_pmpvNextInPolygon; + // if current vertex and its sucessor are same mip vertex + if( pmpvCurrentInPolygon->mpv_pmvVertex == pmpvSuccesor->mpv_pmvVertex) + { + // enable looping even if vertex that is first in polygon is deleted + if( pmpvSuccesor == itPolygon->mp_pmpvFirstPolygonVertex) + { + itPolygon->mp_pmpvFirstPolygonVertex = pmpvSuccesor->mpv_pmpvNextInPolygon; + } + // relink current vertex over sucessor + pmpvCurrentInPolygon->mpv_pmpvNextInPolygon = pmpvSuccesor->mpv_pmpvNextInPolygon; + // delete sucessor vertex + delete pmpvSuccesor; + } + pmpvCurrentInPolygon = pmpvCurrentInPolygon->mpv_pmpvNextInPolygon; + } + while( pmpvCurrentInPolygon != itPolygon->mp_pmpvFirstPolygonVertex); + }} + + CDynamicContainer cPolygonsToDelete; + // for all polygons + {FOREACHINDYNAMICARRAY( mm_ampPolygons, CMipPolygon, itPolygon) + { + CMipPolygonVertex *pmpvFirst = itPolygon->mp_pmpvFirstPolygonVertex; + // if this is polygon with one or two vertices + if( (pmpvFirst->mpv_pmpvNextInPolygon == pmpvFirst) || + (pmpvFirst->mpv_pmpvNextInPolygon->mpv_pmpvNextInPolygon == pmpvFirst) ) + { + // add it to container for deleting + cPolygonsToDelete.Add( &itPolygon.Current()); + } + }} + // delete polygons + {FOREACHINDYNAMICCONTAINER(cPolygonsToDelete, CMipPolygon, itPolygon) + { + mm_ampPolygons.Delete( &itPolygon.Current()); + }} +} + +void CMipModel::FindBestVertexPair( CMipVertex *&pmvBestSource, CMipVertex *&pmvBestTarget) +{ + pmvBestSource = NULL; + pmvBestTarget = NULL; + FLOAT fBestGoodnes = -999999.9f; + // for all polygons + {FOREACHINDYNAMICARRAY( mm_ampPolygons, CMipPolygon, itPolygon) + { + // for all vertices in this polygon + CMipPolygonVertex *pmpvCurrentInPolygon = itPolygon->mp_pmpvFirstPolygonVertex; + do + { + CMipVertex *pmvSource = pmpvCurrentInPolygon->mpv_pmvVertex; + CMipVertex *pmvDestination = pmpvCurrentInPolygon->mpv_pmpvNextInPolygon->mpv_pmvVertex; + FLOAT fCurrentGoodnes = GetGoodness( pmvSource, pmvDestination); + if( fCurrentGoodnes > fBestGoodnes) + { + fBestGoodnes = fCurrentGoodnes; + pmvBestSource = pmvSource; + pmvBestTarget = pmvDestination; + } + // now for inverted order + pmvSource = pmpvCurrentInPolygon->mpv_pmpvNextInPolygon->mpv_pmvVertex; + pmvDestination = pmpvCurrentInPolygon->mpv_pmvVertex; + fCurrentGoodnes = GetGoodness( pmvSource, pmvDestination); + if( fCurrentGoodnes > fBestGoodnes) + { + fBestGoodnes = fCurrentGoodnes; + pmvBestSource = pmvSource; + pmvBestTarget = pmvDestination; + } + pmpvCurrentInPolygon = pmpvCurrentInPolygon->mpv_pmpvNextInPolygon; + } + while( pmpvCurrentInPolygon != itPolygon->mp_pmpvFirstPolygonVertex); + }} + ASSERT( (pmvBestSource != NULL) && (pmvBestTarget != NULL) ); + ASSERT( pmvBestSource != pmvBestTarget); +} + +void CMipModel::RemoveUnusedVertices(void) +{ + // if there are no vertices + if (mm_amvVertices.Count()==0) { + // do nothing + return; + } + + // clear all vertex tags + {FOREACHINDYNAMICARRAY(mm_amvVertices, CMipVertex, itmvtx) { + itmvtx->mv_bUsed = FALSE; + }} + + // mark all vertices that are used by some polygon + {FOREACHINDYNAMICARRAY(mm_ampPolygons, CMipPolygon, itpo) { + CMipPolygonVertex *pmpvCurrentInPolygon = itpo->mp_pmpvFirstPolygonVertex; + do + { + pmpvCurrentInPolygon->mpv_pmvVertex->mv_bUsed = TRUE; + pmpvCurrentInPolygon = pmpvCurrentInPolygon->mpv_pmpvNextInPolygon; + } + while( pmpvCurrentInPolygon != itpo->mp_pmpvFirstPolygonVertex); + }} + + // find number of used vertices + INDEX ctUsedVertices = 0; + {FOREACHINDYNAMICARRAY(mm_amvVertices, CMipVertex, itmvtx) { + if (itmvtx->mv_bUsed) { + ctUsedVertices++; + } + }} + + // create a new array with as much vertices as we have counted in last pass + CDynamicArray amvxNew; + CMipVertex *pmvxUsed = amvxNew.New(ctUsedVertices); + + // for each vertex + {FOREACHINDYNAMICARRAY(mm_amvVertices, CMipVertex, itmvtx) { + // if it is used + if (itmvtx->mv_bUsed) { + // copy it to new array + *pmvxUsed = itmvtx.Current(); + // set its remap pointer into new array + itmvtx->mv_pmvxRemap = pmvxUsed; + pmvxUsed++; + // if it is not used + } else { + // clear its remap pointer (for debugging) + #ifndef NDEBUG + itmvtx->mv_pmvxRemap = NULL; + #endif + } + }} + + // for each polygon + {FOREACHINDYNAMICARRAY(mm_ampPolygons, CMipPolygon, itpo) { + // for each polygon vertex in polygon + CMipPolygonVertex *pmpvCurrentInPolygon = itpo->mp_pmpvFirstPolygonVertex; + do + { + // remap pointer to vertex + pmpvCurrentInPolygon->mpv_pmvVertex = pmpvCurrentInPolygon->mpv_pmvVertex->mv_pmvxRemap; + pmpvCurrentInPolygon = pmpvCurrentInPolygon->mpv_pmpvNextInPolygon; + } + while( pmpvCurrentInPolygon != itpo->mp_pmpvFirstPolygonVertex); + }} + + // use new array of vertices instead of the old one + mm_amvVertices.Clear(); + mm_amvVertices.MoveArray(amvxNew); +} + +BOOL CMipModel::CreateMipModel_t(INDEX ctVerticesToRemove, INDEX iSurfacePreservingFactor) +{ + if( ctVerticesToRemove>mm_amvVertices.Count()) return FALSE; + + for( INDEX ctRemoved = 0; ctRemoved +#include +#include +#include + +class CMipPolygonVertex { +public: + CMipPolygonVertex *mpv_pmpvNextInPolygon; + class CMipPolygon *mpv_pmpPolygon; + class CMipVertex *mpv_pmvVertex; + inline void Clear(void) {}; +}; + +class CMipVertex : public FLOAT3D { +public: + FLOAT3D mv_vRestFrameCoordinate; + INDEX mv_iSurface; + BOOL mv_bUsed; + CMipVertex *mv_pmvxRemap; + CMipVertex(); + ~CMipVertex(); + void Clear(void); +}; + +class CMipPolygon { +public: + class CMipPolygonVertex *mp_pmpvFirstPolygonVertex; + INDEX mp_iSurface; + CMipPolygon(void); + ~CMipPolygon(void); + void Clear(void); +}; + +class CMipSurface { +public: + CTString ms_strName; + COLOR ms_colColor; + inline void Clear(void) {}; +}; + +class CMipModel { +public: + CDynamicArray< CMipSurface> mm_amsSurfaces; + CDynamicArray< CMipPolygon> mm_ampPolygons; + CDynamicArray< CMipVertex> mm_amvVertices; + FLOATaabbox3D mm_boxBoundingBox; + void FromObject3D_t( CObject3D &objRestFrame, CObject3D &objMipSourceFrame); + void ToObject3D( CObject3D &objDestination); + + ~CMipModel(); + BOOL CreateMipModel_t(INDEX iVetexRemoveRate, INDEX iSurfacePreservingFactor); + INDEX FindSurfacesForVertices(void); + void FindBestVertexPair( CMipVertex *&pmvBestSource, CMipVertex *&pmvBestTarget); + void JoinVertexPair( CMipVertex *pmvBestSource, CMipVertex *pmvBestTarget); + void RemoveUnusedVertices(void); + void CheckObjectValidity(void); + FLOAT GetGoodness(CMipVertex *pmvSource, CMipVertex *pmvTarget); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Models/Model.cpp b/Sources/Engine/Models/Model.cpp new file mode 100644 index 0000000..b958d99 --- /dev/null +++ b/Sources/Engine/Models/Model.cpp @@ -0,0 +1,3022 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +template CStaticArray; +template CStaticArray; +template CStaticArray; +template CStaticArray; +template CStaticArray; +template CDynamicArray; + + +extern UBYTE aubGouraudConv[16384]; + +// model LOD biasing control +extern FLOAT mdl_fLODMul; +extern FLOAT mdl_fLODAdd; +extern INDEX mdl_iLODDisappear; // 0=never, 1=ignore bias, 2=with bias +extern INDEX mdl_bFineQuality; // 0=force to 8-bit, 1=optimal + + + +CModelData::CModelData(const CModelData &c) { ASSERT(FALSE); }; +CModelData &CModelData::operator=(const CModelData &c){ ASSERT(FALSE); return *this; }; + +// if any surface in model that we are currently reading has any transparency +BOOL _bHasAlpha; + +// colors used to represent on and off bits +COLOR PaletteColorValues[] = +{ + C_RED, C_GREEN, C_BLUE, C_CYAN, + C_MAGENTA, C_YELLOW, C_ORANGE, C_BROWN, + C_PINK, C_dGRAY, C_GRAY, C_lGRAY, + C_dRED, C_lRED, C_dGREEN, C_lGREEN, + C_dBLUE, C_lBLUE, C_dCYAN, C_lCYAN, + C_dMAGENTA, C_lMAGENTA, C_dYELLOW, C_lYELLOW, + C_dORANGE, C_lORANGE, C_dBROWN, C_lBROWN, + C_dPINK, C_lPINK, C_WHITE, C_BLACK, +}; + +/* + * Instanciated global rendering preferences object containing + * info about rendering of models + */ +CModelRenderPrefs _mrpModelRenderPrefs; + +/* + * Functions dealing with 16-bit normal compression + */ +void CompressNormal_HQ(const FLOAT3D &vNormal, UBYTE &ubH, UBYTE &ubP) +{ + ANGLE h, p; + + const FLOAT &x = vNormal(1); + const FLOAT &y = vNormal(2); + const FLOAT &z = vNormal(3); + + // calculate pitch + p = ASin(y); + + // if y is near +1 or -1 + if (y>0.99 || y<-0.99) { + // heading is irrelevant + h = 0; + // otherwise + } else { + // calculate heading + h = ATan2(-x, -z); + } + + h = (h/360.0f)+0.5f; + p = (p/360.0f)+0.5f; + ASSERT(h>=0 && h<=1); + ASSERT(p>=0 && p<=1); + ubH = UBYTE(h*255); + ubP = UBYTE(p*255); +} + +void DecompressNormal_HQ(FLOAT3D &vNormal, UBYTE ubH, UBYTE ubP) +{ + ANGLE h = (ubH/255.0f)*360.0f-180.0f; + ANGLE p = (ubP/255.0f)*180.0f-90.0f; + + FLOAT &x = vNormal(1); + FLOAT &y = vNormal(2); + FLOAT &z = vNormal(3); + + x = -Sin(h)*Cos(p); + y = Sin(p); + z = -Cos(h)*Cos(p); +} + +//-------------------------------------------------------------------------------------------- +/* + * Function returns number of first setted bit in ULONG + */ +INDEX GetBit( ULONG ulSource) +{ + for( INDEX i=0; i<32; i++) + { + if( (ulSource & (1<= 0); + rp_ShadowQuality = iNewQuality; +} +void CModelRenderPrefs::DesreaseShadowQuality(void) +{ + rp_ShadowQuality += 1; +} +void CModelRenderPrefs::IncreaseShadowQuality(void) +{ + if( rp_ShadowQuality > 0) + rp_ShadowQuality -= 1; +} +INDEX CModelRenderPrefs::GetShadowQuality() +{ + return( rp_ShadowQuality); +} +BOOL CModelRenderPrefs::BBoxFrameVisible() +{ + return( rp_BBoxFrameVisible); +} +void CModelRenderPrefs::BBoxFrameShow( BOOL bShow) +{ + rp_BBoxFrameVisible = bShow; +} +BOOL CModelRenderPrefs::BBoxAllVisible() +{ + return( rp_BBoxAllVisible); +} +void CModelRenderPrefs::BBoxAllShow( BOOL bShow) +{ + rp_BBoxAllVisible = bShow; +} +BOOL CModelRenderPrefs::WireOn() +{ + return( (rp_RenderType & RT_WIRE_ON) != 0); +} +BOOL CModelRenderPrefs::HiddenLines() +{ + return( (rp_RenderType & RT_HIDDEN_LINES) != 0); +} +void CModelRenderPrefs::SetInkColor(COLOR clrNew) +{ + rp_InkColor = clrNew; +} +COLOR CModelRenderPrefs::GetInkColor() +{ + return rp_InkColor; +} +void CModelRenderPrefs::SetPaperColor(COLOR clrNew) +{ + rp_PaperColor = clrNew; +} +COLOR CModelRenderPrefs::GetPaperColor() +{ + return rp_PaperColor; +} +// read and write functions +void CModelRenderPrefs::Read_t( CTStream *istrFile) // throw char * +{ +} +void CModelRenderPrefs::Write_t( CTStream *ostrFile) // throw char * +{ +} + +//-------------------------------------------------------------------------------------------- +CModelPatch::CModelPatch(void) +{ + mp_strName = ""; + mp_mexPosition = MEX2D( 1024, 1024); + mp_fStretch = 1.0f; +} + +void CModelPatch::Read_t(CTStream *strFile) +{ + *strFile >> mp_strName; + CTFileName fnPatchTexture; + *strFile >> fnPatchTexture; + try + { + mp_toTexture.SetData_t( fnPatchTexture); + } + catch( char *strError) + { + (void) strError; + } + *strFile >> mp_mexPosition; + *strFile >> mp_fStretch; +} + +void CModelPatch::Write_t(CTStream *strFile) +{ + *strFile << mp_strName; + *strFile << mp_toTexture.GetName(); + *strFile << mp_mexPosition; + *strFile << mp_fStretch; +} + +//-------------------------------------------------------------------------------------------- +/* + * Default constructor sets invalid data + */ +CModelData::CModelData() +{ + INDEX i; + md_bPreparedForRendering = FALSE; + + md_VerticesCt = 0; // number of vertices in model + md_FramesCt = 0; // number of all frames used by this model + md_MipCt = 0; // number of mip-models + + md_bIsEdited = FALSE; // not edited by default + + // invalidate mip-model info data + for( i=0; i MAX_SWITCH_FACTOR) || ((md_MipCt-iFirst) <= 0) ) + { + // define next switch factor offset + fSteep = 1.2f; + } + + // else divide factor from starting factor to max switch factor with number of mip + // models left + else + { + fSteep = (MAX_SWITCH_FACTOR - fStartingFactor) / (md_MipCt-iFirst); + } + + // spread mip switch factors for rougher mip models + for( INDEX i=iFirst; i> itmp; + mpv_ptvTransformedVertex = (struct TransformedVertexData *) itmp; + (*pFile) >> itmp; + mpv_ptvTextureVertex = (ModelTextureVertex *) itmp; +} +//-------------------------------------------------------------------------------------------- +//------------------------------------------ WRITE +void ModelPolygon::Write_t( CTStream *pFile) // throw char * +{ + pFile->WriteID_t( CChunkID("MDP2")); + INDEX ctVertices = mp_PolygonVertices.Count(); + (*pFile) << ctVertices; + {FOREACHINSTATICARRAY(mp_PolygonVertices, ModelPolygonVertex, it) + { it.Current().Write_t( pFile);}} + (*pFile) << mp_RenderFlags; + (*pFile) << mp_ColorAndAlpha; + (*pFile) << mp_Surface; +}; +//------------------------------------------ READ +void ModelPolygon::Read_t( CTStream *pFile) // throw char * +{ + INDEX ctVertices; + ULONG ulDummy; + if( pFile->PeekID_t() == CChunkID("MDPL")) + { + pFile->ExpectID_t( CChunkID("MDPL")); + pFile->ReadFullChunk_t( CChunkID("IMPV"), &ctVertices, sizeof(INDEX)); + mp_PolygonVertices.New( ctVertices); + + {FOREACHINSTATICARRAY(mp_PolygonVertices, ModelPolygonVertex, it) + { it.Current().Read_t( pFile);}} + (*pFile) >> mp_RenderFlags; + (*pFile) >> mp_ColorAndAlpha; + (*pFile) >> mp_Surface; + (*pFile) >> ulDummy; // ex on color + (*pFile) >> ulDummy; // ex off color + } + else + { + pFile->ExpectID_t( CChunkID("MDP2")); + (*pFile) >> ctVertices; + mp_PolygonVertices.New( ctVertices); + + {FOREACHINSTATICARRAY(mp_PolygonVertices, ModelPolygonVertex, it) + { it.Current().Read_t( pFile);}} + (*pFile) >> mp_RenderFlags; + (*pFile) >> mp_ColorAndAlpha; + (*pFile) >> mp_Surface; + } +}; +//---------------------------------------------------------------------------------- +// TEMPORARY - REMOVE THIS!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// POLYGON RENDER CONSTANTS +// new_render_types = rendertype (0-7)<<0 + phongstrength(0-7)<<3 + alphatype(0-3)<<6 +// poly render types +#define PR_PHONGSHADING (0x00<<0) // textures phong shading +#define PR_LAMBERTSHADING (0x01<<0) // textures lambert shading (no phong/gouraud) +#define PR_ALPHAGOURAUD (0x02<<0) // alpha gouraud shading +#define PR_FRONTPROJECTION (0x03<<0) // front projection shading (no rotation, 2D zoom) +#define PR_SHADOWBLENDING (0x04<<0) // shadow blending (black alpha gouraud) +#define PR_COLORFILLING (0x05<<0) // flat filling (single color poly, no texture) + +#define PR_MASK (0x07<<0) // mask for render types + +// phong strengths (shading types) +#define PS_MATTE (0x00<<3) // same as the gouraud +#define PS_SHINY (0x01<<3) // mild shininig +#define PS_METAL (0x02<<3) // shine as hell + +#define PS_MASK (0x07<<3) // mask for phong strengths + +// texture's alpha channel flag +#define AC_SKIPALPHACHANNEL (0x00<<6) // opaque rendering regardless of alpha channel presence +#define AC_USEALPHACHANNEL (0x01<<6) // texture's alpha ch. will be taken in consideration +#define AC_ZEROTRANSPARENCY (0x02<<6) // texture's zero values are transparent (no alpha ch.) + +#define AC_MASK (0x03<<6) // mask for texture's alpha flag + +// polygon's control flags +#define PCF_DOUBLESIDED (0x01<<9) // double sided polygon +#define PCF_NOSHADING (0x02<<9) // this polygon will not be shaded anyhow (?) +#define PCF_CLIPPOLYGON (0x04<<9) // polygon is clipped, instead rejected +#define PCF_REFLECTIONS (0x08<<9) // use reflection mapping +//---------------------------------------------------------------------------------- + +BOOL MappingSurface::operator==(const MappingSurface &msOther) const { + return msOther.ms_Name == ms_Name; +}; + +// convert old polygon flags from CTGfx into new rendering parameters +void MappingSurface::SetRenderingParameters(ULONG ulOldFlags) +{ + // find rendering type + if (ulOldFlags&PCF_NOSHADING) { + ms_sstShadingType = SST_FULLBRIGHT; + } else { + switch (ulOldFlags&PS_MASK) { + case PS_MATTE: + ms_sstShadingType = SST_MATTE; + break; + case PS_SHINY: + ms_sstShadingType = SST_MATTE; + break; + case PS_METAL: + ms_sstShadingType = SST_MATTE; + break; + default: + ms_sstShadingType = SST_MATTE; + } + } + // find translucency type + if ((ulOldFlags&PR_MASK)==PR_ALPHAGOURAUD) { + ms_sttTranslucencyType = STT_ALPHAGOURAUD; + } else if ((ulOldFlags&AC_MASK)==AC_ZEROTRANSPARENCY) { + ms_sttTranslucencyType = STT_TRANSLUCENT; + } else { + ms_sttTranslucencyType = STT_OPAQUE; + } + // find flags + ms_ulRenderingFlags = 0; + if (ulOldFlags&PCF_DOUBLESIDED) { + ms_ulRenderingFlags|=SRF_DOUBLESIDED; + } + if (ulOldFlags&PCF_REFLECTIONS) { + ms_ulRenderingFlags|=SRF_REFLECTIONS; + } +} +//------------------------------------------ WRITE +void MappingSurface::Write_t( CTStream *pFile) // throw char * +{ + (*pFile) << ms_Name; + pFile->Write_t( &ms_vSurface2DOffset, sizeof(FLOAT3D)); + pFile->Write_t( &ms_HPB, sizeof(FLOAT3D)); + pFile->Write_t( &ms_Zoom, sizeof(float)); + + pFile->Write_t( &ms_sstShadingType, sizeof(SurfaceShadingType)); + pFile->Write_t( &ms_sttTranslucencyType, sizeof(SurfaceTranslucencyType)); + (*pFile) << ms_ulRenderingFlags; + + INDEX ctPolygons = ms_aiPolygons.Count(); + (*pFile) << ctPolygons; + if( ctPolygons != 0) + { + pFile->Write_t( &ms_aiPolygons[0], sizeof( INDEX)*ctPolygons); + } + + INDEX ctTextureVertices = ms_aiTextureVertices.Count(); + (*pFile) << ctTextureVertices; + if( ctTextureVertices != 0) + { + pFile->Write_t( &ms_aiTextureVertices[0], sizeof( INDEX)*ctTextureVertices); + } + + (*pFile) << ms_colColor; + + (*pFile) << ms_colDiffuse; + (*pFile) << ms_colReflections; + (*pFile) << ms_colSpecular; + (*pFile) << ms_colBump; + + (*pFile) << ms_ulOnColor; + (*pFile) << ms_ulOffColor; +} + +void MappingSurface::WriteSettings_t( CTStream *pFile) // throw char * +{ + (*pFile) << ms_Name; + pFile->Write_t( &ms_sstShadingType, sizeof(SurfaceShadingType)); + pFile->Write_t( &ms_sttTranslucencyType, sizeof(SurfaceTranslucencyType)); + (*pFile) << ms_ulRenderingFlags; + (*pFile) << ms_colDiffuse; + (*pFile) << ms_colReflections; + (*pFile) << ms_colSpecular; + (*pFile) << ms_colBump; + (*pFile) << ms_ulOnColor; + (*pFile) << ms_ulOffColor; +} + +void MappingSurface::ReadSettings_t( CTStream *pFile) // throw char * +{ + (*pFile) >> ms_Name; + pFile->Read_t( &ms_sstShadingType, sizeof(SurfaceShadingType)); + pFile->Read_t( &ms_sttTranslucencyType, sizeof(SurfaceTranslucencyType)); + (*pFile) >> ms_ulRenderingFlags; + (*pFile) >> ms_colDiffuse; + (*pFile) >> ms_colReflections; + (*pFile) >> ms_colSpecular; + (*pFile) >> ms_colBump; + (*pFile) >> ms_ulOnColor; + (*pFile) >> ms_ulOffColor; +} + +//------------------------------------------ READ +void MappingSurface::Read_t( CTStream *pFile, BOOL bReadPolygonsPerSurface, + BOOL bReadSurfaceColors) // throw char * +{ + (*pFile) >> ms_Name; + pFile->Read_t( &ms_vSurface2DOffset, sizeof(FLOAT3D)); + pFile->Read_t( &ms_HPB, sizeof(FLOAT3D)); + pFile->Read_t( &ms_Zoom, sizeof(float)); + + if( bReadPolygonsPerSurface) + { + pFile->Read_t( &ms_sstShadingType, sizeof(SurfaceShadingType)); + // WARNING !!! All shading types bigger than matte will be remaped into flat shading + // this was done when SHINY and METAL were removed + if( ms_sstShadingType > SST_MATTE) + { + ms_sstShadingType = SST_FLAT; + } + pFile->Read_t( &ms_sttTranslucencyType, sizeof(SurfaceTranslucencyType)); + (*pFile) >> ms_ulRenderingFlags; + if( (ms_ulRenderingFlags&SRF_NEW_TEXTURE_FORMAT) == 0) + ms_ulRenderingFlags |= SRF_DIFFUSE|SRF_NEW_TEXTURE_FORMAT; + if (ms_sttTranslucencyType==STT_TRANSLUCENT || ms_sttTranslucencyType==STT_ALPHAGOURAUD + ||ms_sttTranslucencyType==STT_ADD||ms_sttTranslucencyType==STT_MULTIPLY) { + _bHasAlpha = TRUE; + } + + ms_aiPolygons.Clear(); + INDEX ctPolygons; + (*pFile) >> ctPolygons; + ms_aiPolygons.New( ctPolygons); + if( ctPolygons != 0) + { + pFile->Read_t( &ms_aiPolygons[0], sizeof( INDEX)*ctPolygons); + } + + ms_aiTextureVertices.Clear(); + INDEX ctTextureVertices; + (*pFile) >> ctTextureVertices; + ms_aiTextureVertices.New( ctTextureVertices); + if( ctTextureVertices != 0) + { + pFile->Read_t( &ms_aiTextureVertices[0], sizeof( INDEX)*ctTextureVertices); + } + + (*pFile) >> ms_colColor; + } + if( bReadSurfaceColors) + { + (*pFile) >> ms_colDiffuse; + (*pFile) >> ms_colReflections; + (*pFile) >> ms_colSpecular; + (*pFile) >> ms_colBump; + (*pFile) >> ms_ulOnColor; + (*pFile) >> ms_ulOffColor; + } +} + + +void CModelData::LinkDataForSurfaces(BOOL bFirstMip) +{ + INDEX iMipStart=1; + if( bFirstMip) + { + iMipStart=0; + } + // for each mip model + for( INDEX iMip=iMipStart; iMipmmpi_Polygons.Count(); iPolygon++) + { + for( INDEX iVertex = 0; iVertexmmpi_Polygons[iPolygon].mp_PolygonVertices.Count(); iVertex++) + { + ModelPolygonVertex *pmpvPolygonVertex = &pMMI->mmpi_Polygons[iPolygon].mp_PolygonVertices[iVertex]; + INDEX iTransformed = md_TransformedVertices.Index( pmpvPolygonVertex->mpv_ptvTransformedVertex); + pmpvPolygonVertex->mpv_ptvTextureVertex->mtv_iTransformedVertex = iTransformed; + } + }} + + // --------------------- Linking polygons for surface + // array telling how many polygons are in each surface + CStaticArray actPolygonsInSurface; + INDEX ctSurfaces = pMMI->mmpi_MappingSurfaces.Count(); + actPolygonsInSurface.New( ctSurfaces); + // for each surface + {for( INDEX iSurface=0; iSurfacemmpi_Polygons.Count(); iPolygon++) + { + // increment count of polygons in its surface + actPolygonsInSurface[ pMMI->mmpi_Polygons[iPolygon].mp_Surface]++; + }} + // for each surface + {for( INDEX iSurface=0; iSurfacemmpi_MappingSurfaces[iSurface].ms_aiPolygons.Clear(); + pMMI->mmpi_MappingSurfaces[iSurface].ms_aiPolygons.New( actPolygonsInSurface[iSurface]); + if( actPolygonsInSurface[iSurface] != 0) + { + // last place in array will contain counter of added polygons + pMMI->mmpi_MappingSurfaces[iSurface].ms_aiPolygons[actPolygonsInSurface[iSurface]-1] = 0; + } + }} + // for each polygon + for( INDEX iPolygon=0; iPolygonmmpi_Polygons.Count(); iPolygon++) + { + // get surface, polygons in surface and last remembered index of polygon in surface + INDEX iSurface = pMMI->mmpi_Polygons[iPolygon].mp_Surface; + INDEX ctPolygonsInSurface = actPolygonsInSurface[iSurface]; + if( ctPolygonsInSurface != 0) + { + INDEX iLastSet = pMMI->mmpi_MappingSurfaces[iSurface].ms_aiPolygons[ ctPolygonsInSurface-1]; + // remember last set polygon index + pMMI->mmpi_MappingSurfaces[iSurface].ms_aiPolygons[ ctPolygonsInSurface-1] = iLastSet+1; + // remember index of polygon + pMMI->mmpi_MappingSurfaces[iSurface].ms_aiPolygons[ iLastSet] = iPolygon; + } + } + + // --------------------- Linking texture vertices for surface + // for each surface + {for( INDEX iSurface=0; iSurface cmtvInSurface; + // for each polygon in surface + FOREACHINSTATICARRAY( pMMI->mmpi_MappingSurfaces[iSurface].ms_aiPolygons, INDEX, itimpo) + { + ModelPolygon &mpPolygon = pMMI->mmpi_Polygons[itimpo.Current()]; + // for each vertex in polygon + for( INDEX iVertex=0; iVertexmmpi_MappingSurfaces[iSurface].ms_aiTextureVertices.Clear(); + pMMI->mmpi_MappingSurfaces[iSurface].ms_aiTextureVertices.New( cmtvInSurface.Count()); + INDEX cttv = 0; + // for each texture vertex in container + FOREACHINDYNAMICCONTAINER(cmtvInSurface, ModelTextureVertex, itmtv) + { + INDEX idxtv = pMMI->mmpi_TextureVertices.Index( itmtv); + pMMI->mmpi_MappingSurfaces[iSurface].ms_aiTextureVertices[cttv] = idxtv; + cttv++; + } + }} + } +} + +// Default constructor +ModelMipInfo::ModelMipInfo(void) +{ + mmpi_ulFlags = MM_PATCHES_VISIBLE | MM_ATTACHED_MODELS_VISIBLE; +} + +//-------------------------------------------------------------------------------------------- +//------------------------------------------ WRITE +/* + * This is write function of one mip-model. It saves all mip's arrays eather by saving + * them really or calling their write functions. + */ +void ModelMipInfo::Write_t( CTStream *pFile) // throw char * +{ + INDEX iMembersCt; + + // Save count, call write for array of model polygons + pFile->WriteFullChunk_t( CChunkID("IPOL"), &mmpi_PolygonsCt, sizeof(INDEX)); + {FOREACHINSTATICARRAY(mmpi_Polygons, ModelPolygon, it) + { it.Current().Write_t( pFile);}} + + // Save count, array of texture vertices + iMembersCt = mmpi_TextureVertices.Count(); + (*pFile) << iMembersCt; + pFile->WriteFullChunk_t( CChunkID("TXV2"), &mmpi_TextureVertices[ 0], iMembersCt * + sizeof(struct ModelTextureVertex)); + + // Save count, call write for array of mapping surfaces + iMembersCt = mmpi_MappingSurfaces.Count(); + (*pFile) << iMembersCt; + {FOREACHINSTATICARRAY(mmpi_MappingSurfaces, MappingSurface, it) + { it.Current().Write_t( pFile);}} + + // write mip model flags + (*pFile) << mmpi_ulFlags; + // write info of polygons occupied by patch + INDEX ctPatches = mmpi_aPolygonsPerPatch.Count(); + (*pFile) << ctPatches; + // for each patch + for( INDEX iPatch=0; iPatchWriteFullChunk_t( CChunkID("OCPL"), + &mmpi_aPolygonsPerPatch[iPatch].ppp_iPolygons[ 0], ctOccupied * sizeof(INDEX)); + } + } +} +//------------------------------------------ READ +/* + * This is read function of one mip-model + */ +void ModelMipInfo::Read_t(CTStream *pFile, + BOOL bReadPolygonalPatches, + BOOL bReadPolygonsPerSurface, + BOOL bReadSurfaceColors) +{ + INDEX iMembersCt; + + // Load count, allocate array and call Read for array of model polygons + pFile->ReadFullChunk_t( CChunkID("IPOL"), &mmpi_PolygonsCt, sizeof(INDEX)); + mmpi_Polygons.New( mmpi_PolygonsCt); + {FOREACHINSTATICARRAY(mmpi_Polygons, ModelPolygon, it) + { + it.Current().Read_t( pFile); + }} + + // Load count, allocate and load array of texture vertices + (*pFile) >> iMembersCt; + mmpi_TextureVertices.New( iMembersCt); + if( bReadPolygonsPerSurface) + { + // chunk ID will tell us if we should read new format that contains bump normals + CChunkID idChunk = pFile->GetID_t(); + // jump over chunk size + ULONG ulDummySize; + (*pFile) >> ulDummySize; + // if bump normals are saved (new format) + if( idChunk == CChunkID("TXV2")) + { + pFile->ReadRawChunk_t( &mmpi_TextureVertices[ 0], iMembersCt * + sizeof(struct ModelTextureVertex)); + } else { + // bump normals are not saved + for( INDEX iVertex = 0; iVertexRead_t( &mmpi_TextureVertices[ iVertex].mtv_UVW, sizeof( FLOAT3D)); + pFile->Read_t( &mmpi_TextureVertices[ iVertex].mtv_UV, sizeof( MEX2D)); + pFile->Read_t( &mmpi_TextureVertices[ iVertex].mtv_Done, sizeof( BOOL)); + pFile->Read_t( &mmpi_TextureVertices[ iVertex].mtv_iTransformedVertex, sizeof( INDEX)); + mmpi_TextureVertices[ iVertex].mtv_vU = FLOAT3D(0,0,0); + mmpi_TextureVertices[ iVertex].mtv_vV = FLOAT3D(0,0,0); + } + } + } + else + { + pFile->ExpectID_t( CChunkID("TXVT")); + // jump over chunk size + ULONG ulDummySize; + (*pFile) >> ulDummySize; + // read models in old format + for( INDEX iVertex = 0; iVertexRead_t( &mmpi_TextureVertices[ iVertex].mtv_UVW, sizeof( FLOAT3D)); + pFile->Read_t( &mmpi_TextureVertices[ iVertex].mtv_UV, sizeof( MEX2D)); + pFile->Read_t( &mmpi_TextureVertices[ iVertex].mtv_Done, sizeof( BOOL)); + mmpi_TextureVertices[ iVertex].mtv_iTransformedVertex = 0; + mmpi_TextureVertices[ iVertex].mtv_vU = FLOAT3D(0,0,0); + mmpi_TextureVertices[ iVertex].mtv_vV = FLOAT3D(0,0,0); + } + } + + // Load count, allcate array and call Read for array of mapping surfaces + (*pFile) >> iMembersCt; + mmpi_MappingSurfaces.New( iMembersCt); + INDEX iIndexOfSurface = 0; + {FOREACHINSTATICARRAY(mmpi_MappingSurfaces, MappingSurface, it) + { + it.Current().Read_t( pFile, bReadPolygonsPerSurface, bReadSurfaceColors); + // obtain color per surface from polygons (old model format) + if( !bReadPolygonsPerSurface) + { + // we will copy color from first polygon found with this surface into color of surface + it->ms_colColor = C_WHITE; + // for all polygons in this mip level + for( INDEX iPolygon=0;iPolygonms_colColor = mmpi_Polygons[ iPolygon].mp_ColorAndAlpha; + break; + } + } + iIndexOfSurface++; + } + }} + + if( bReadPolygonalPatches) + { + // read mip model flags + (*pFile) >> mmpi_ulFlags; + // read no of patches + INDEX ctPatches; + (*pFile) >> ctPatches; + if( ctPatches != 0) + { + mmpi_aPolygonsPerPatch.New( ctPatches); + // read info for polygonal patches + for( INDEX iPatch=0; iPatch> ctOccupied; + if( ctOccupied != 0) + { + mmpi_aPolygonsPerPatch[iPatch].ppp_iPolygons.New( ctOccupied); + pFile->ReadFullChunk_t( CChunkID("OCPL"), + &mmpi_aPolygonsPerPatch[iPatch].ppp_iPolygons[ 0], ctOccupied * sizeof(INDEX)); + } + } + } + } +} + +//-------------------------------------------------------------------------------------------- +/* + * Routine converts mpv_ptvTransformedVertex and mpv_ptvTextureVertex from ptrs to Indices + */ +void CModelData::PtrsToIndices() +{ + INDEX i, j; + + for( i=0; iRead_t( &mcb_vCollisionBoxMin, sizeof(FLOAT3D)); + // Read collision box size + istrFile->Read_t( &mcb_vCollisionBoxMax, sizeof(FLOAT3D)); + // Get "colision box dimensions equality" value + if( (mcb_vCollisionBoxMax(2)-mcb_vCollisionBoxMin(2)) == + (mcb_vCollisionBoxMax(1)-mcb_vCollisionBoxMin(1)) ) + { + mcb_iCollisionBoxDimensionEquality = HEIGHT_EQ_WIDTH; + } + else if( (mcb_vCollisionBoxMax(3)-mcb_vCollisionBoxMin(3)) == + (mcb_vCollisionBoxMax(1)-mcb_vCollisionBoxMin(1)) ) + { + mcb_iCollisionBoxDimensionEquality = LENGTH_EQ_WIDTH; + } + else if( (mcb_vCollisionBoxMax(3)-mcb_vCollisionBoxMin(3)) == + (mcb_vCollisionBoxMax(2)-mcb_vCollisionBoxMin(2)) ) + { + mcb_iCollisionBoxDimensionEquality = LENGTH_EQ_HEIGHT; + } + else + { + /* + // Force them to be legal (Lenght = Width) + mcb_vCollisionBoxMax(3) = mcb_vCollisionBoxMin(3) + + (mcb_vCollisionBoxMax(1)-mcb_vCollisionBoxMin(1)); + */ + mcb_iCollisionBoxDimensionEquality = LENGTH_EQ_WIDTH; + } +} + +void CModelCollisionBox::ReadName_t(CTStream *istrFile) +{ + // read collision box name + (*istrFile)>>mcb_strName; +} + +void CModelCollisionBox::Write_t(CTStream *ostrFile) +{ + // Write collision box min + ostrFile->Write_t( &mcb_vCollisionBoxMin, sizeof(FLOAT3D)); + // Write collision box size + ostrFile->Write_t( &mcb_vCollisionBoxMax, sizeof(FLOAT3D)); + // write collision box name + (*ostrFile)<> amp_iCenterVertex; + *strFile >> amp_iFrontVertex; + *strFile >> amp_iUpVertex; + *strFile >> amp_plRelativePlacement; +} + +void CAttachedModelPosition::Write_t( CTStream *strFile) +{ + *strFile << amp_iCenterVertex; + *strFile << amp_iFrontVertex; + *strFile << amp_iUpVertex; + *strFile << amp_plRelativePlacement; +} + +//-------------------------------------------------------------------------------------------- +//------------------------------------------ WRITE +void CModelData::Write_t( CTStream *pFile) // throw char * +{ + INDEX i; + + PtrsToIndices(); + // Save main ID + pFile->WriteID_t( CChunkID("MDAT")); + + // Save version number + pFile->WriteID_t( CChunkID( MODEL_VERSION)); + + // Save flags + pFile->Write_t( &md_Flags, sizeof(ULONG)); + + // Save vertices and frames ct + pFile->WriteFullChunk_t( CChunkID("IVTX"), &md_VerticesCt, sizeof(INDEX)); + pFile->WriteFullChunk_t( CChunkID("IFRM"), &md_FramesCt, sizeof(INDEX)); + + // write array of 8-bit or 16-bit compressed vertices + if( md_Flags & MF_COMPRESSED_16BIT) + { + pFile->WriteFullChunk_t( CChunkID("AV17"), &md_FrameVertices16[ 0], md_VerticesCt * md_FramesCt * + sizeof(struct ModelFrameVertex16)); + } + else + { + pFile->WriteFullChunk_t( CChunkID("AFVX"), &md_FrameVertices8[ 0], md_VerticesCt * md_FramesCt * + sizeof(struct ModelFrameVertex8)); + } + // Save frame info array + pFile->WriteFullChunk_t( CChunkID("AFIN"), &md_FrameInfos[ 0], md_FramesCt * + sizeof(struct ModelFrameInfo)); + // Save frame main mip vertices array + pFile->WriteFullChunk_t( CChunkID("AMMV"), &md_MainMipVertices[ 0], md_VerticesCt * + sizeof(FLOAT3D)); + // Save vertex mip-mask array + pFile->WriteFullChunk_t( CChunkID("AVMK"), &md_VertexMipMask[ 0], md_VerticesCt * + sizeof(ULONG)); + // Save mip levels counter + pFile->WriteFullChunk_t( CChunkID("IMIP"), &md_MipCt, sizeof(INDEX)); + + // Save mip factors array + pFile->WriteFullChunk_t( CChunkID("FMIP"), &md_MipSwitchFactors[ 0], MAX_MODELMIPS * sizeof(float)); + + // Save all model mip infos + for( i=0; iWriteID_t( CChunkID("PTC2")); + for( INDEX iPatch=0; iPatchWriteFullChunk_t( CChunkID("STXW"), &md_Width, sizeof(MEX)); + pFile->WriteFullChunk_t( CChunkID("STXH"), &md_Height, sizeof(MEX)); + + // Save value for shading type + pFile->Write_t( &md_ShadowQuality, sizeof(SLONG)); + + // Save static stretch value + pFile->Write_t( &md_Stretch, sizeof(FLOAT3D)); + + // Save model offset + pFile->Write_t( &md_vCenter, sizeof(FLOAT3D)); + + // Save count of collision boxes + INDEX ctCollisionBoxes = md_acbCollisionBox.Count(); + pFile->Write_t( &ctCollisionBoxes, sizeof(INDEX)); + md_acbCollisionBox.Lock(); + // save all collision boxes + for( INDEX iCollisionBox=0; iCollisionBoxWriteID_t( CChunkID( "COLI")); + *pFile << md_bCollideAsCube; + + // Save count of attached positions + INDEX ctAttachedPositions = md_aampAttachedPosition.Count(); + *pFile << ctAttachedPositions; + FOREACHINDYNAMICARRAY(md_aampAttachedPosition, CAttachedModelPosition, itamp) + { + itamp->Write_t(pFile); + } + + // Save color names (get count of valid names, write count and then write existing names) + INDEX iValidColorsCt = 0; + for( i=0; iWriteFullChunk_t( CChunkID("ICLN"), &iValidColorsCt, sizeof(INDEX)); + for( i=0; iExpectID_t( CChunkID("MDAT")); + + // Check version number + BOOL bHasSavedCenter = FALSE; + BOOL bHasMultipleCollisionBoxes = FALSE; + BOOL bHasAttachedPositions = FALSE; + BOOL bHasPolygonalPatches = FALSE; + BOOL bHasPolygonsPerSurface = FALSE; + BOOL bHasSavedFlagsOnStart = FALSE; + BOOL bHasColorForReflectionAndSpecularity = FALSE; + BOOL bHasDiffuseColor = FALSE; + // get version ID + CChunkID idVersion = pFile->GetID_t(); + // if this is version without stretch center then it doesn't contain multiple + // collision boxes also + if( CChunkID( MODEL_VERSION_WITHOUT_STRETCH_CENTER) == idVersion) + { + } + // if model has stretch center but does not have multiple collision boxes + else if( CChunkID( MODEL_VERSION_WITHOUT_MULTIPLE_COLLISION_BOXES) == idVersion) + { + bHasSavedCenter = TRUE; + } + else if( CChunkID( MODEL_VERSION_WITHOUT_ATTACHED_POSITIONS) == idVersion) + { + bHasSavedCenter = TRUE; + bHasMultipleCollisionBoxes = TRUE; + } + else if( CChunkID( MODEL_VERSION_WITHOUT_POLYGONAL_PATCHES) == idVersion) + { + bHasSavedCenter = TRUE; + bHasMultipleCollisionBoxes = TRUE; + bHasAttachedPositions = TRUE; + } + else if( CChunkID( MODEL_VERSION_WITHOUT_POLYGONS_PER_SURFACE) == idVersion) + { + bHasSavedCenter = TRUE; + bHasMultipleCollisionBoxes = TRUE; + bHasAttachedPositions = TRUE; + bHasPolygonalPatches = TRUE; + } + else if( CChunkID( MODEL_VERSION_WITHOUT_16_BIT_COMPRESSION) == idVersion) + { + bHasSavedCenter = TRUE; + bHasMultipleCollisionBoxes = TRUE; + bHasAttachedPositions = TRUE; + bHasPolygonalPatches = TRUE; + bHasPolygonsPerSurface = TRUE; + } + // if has saved flags on start - because 16-bit compression + else if( CChunkID( MODEL_VERSION_WITHOUT_REFLECTION_AND_SPECULARITY) == idVersion) + { + bHasSavedCenter = TRUE; + bHasMultipleCollisionBoxes = TRUE; + bHasAttachedPositions = TRUE; + bHasPolygonalPatches = TRUE; + bHasPolygonsPerSurface = TRUE; + bHasSavedFlagsOnStart = TRUE; + } + // has saved color for reflection and specularity + else if( CChunkID( MODEL_VERSION_WITHOUT_DIFFUSE_COLOR) == idVersion) + { + bHasSavedCenter = TRUE; + bHasMultipleCollisionBoxes = TRUE; + bHasAttachedPositions = TRUE; + bHasPolygonalPatches = TRUE; + bHasPolygonsPerSurface = TRUE; + bHasSavedFlagsOnStart = TRUE; + bHasColorForReflectionAndSpecularity = TRUE; + } + // has saved diffuse color + else if( CChunkID( MODEL_VERSION) == idVersion) + { + bHasSavedCenter = TRUE; + bHasMultipleCollisionBoxes = TRUE; + bHasAttachedPositions = TRUE; + bHasPolygonalPatches = TRUE; + bHasPolygonsPerSurface = TRUE; + bHasSavedFlagsOnStart = TRUE; + bHasColorForReflectionAndSpecularity = TRUE; + bHasDiffuseColor = TRUE; + } + else + { + throw(TRANS("Invalid model version.")); + } + + if( bHasSavedFlagsOnStart) + { + pFile->Read_t( &md_Flags, sizeof(ULONG)); + } + + // Read vertices and frames ct + pFile->ReadFullChunk_t( CChunkID("IVTX"), &md_VerticesCt, sizeof(INDEX)); + md_TransformedVertices.New( md_VerticesCt); + pFile->ReadFullChunk_t( CChunkID("IFRM"), &md_FramesCt, sizeof(INDEX)); + + // read array of 8-bit or 16-bit compressed vertices + if( md_Flags & MF_COMPRESSED_16BIT) + { + md_FrameVertices16.New( md_VerticesCt * md_FramesCt); + CChunkID cidVerticesChunk = pFile->PeekID_t(); + // if we are loading model in old 16-bit compressed format (normals use 1 byte) + if( cidVerticesChunk == CChunkID("AV16")) + { + CChunkID cidDummy = pFile->GetID_t(); + ULONG ulDummy; + // skip chunk size + *pFile >> ulDummy; + for( INDEX iVtx=0; iVtxReadRawChunk_t( &md_FrameVertices16[iVtx], sizeof(struct ModelFrameVertex16_old)); + // convert 8-bit normal from index into normal defined using heading and pitch + INDEX i8BitNormalIndex = md_FrameVertices16[iVtx].mfv_ubNormH; + const FLOAT3D &vNormal = avGouraudNormals[i8BitNormalIndex]; + CompressNormal_HQ( vNormal, md_FrameVertices16[iVtx].mfv_ubNormH, md_FrameVertices16[iVtx].mfv_ubNormP); + } + } + // load new 16-bit compressed format (normals use 2 byte) model + else if( cidVerticesChunk == CChunkID("AV17")) + { + pFile->ReadFullChunk_t( CChunkID("AV17"), &md_FrameVertices16[ 0], md_VerticesCt * md_FramesCt * + sizeof(struct ModelFrameVertex16)); + } + else + { + ThrowF_t( TRANS("Expecting chunk ID for model frame vertices but found %s"), cidVerticesChunk); + } + } + else + { + md_FrameVertices8.New( md_VerticesCt * md_FramesCt); + pFile->ReadFullChunk_t( CChunkID("AFVX"), &md_FrameVertices8[ 0], md_VerticesCt * md_FramesCt * + sizeof(struct ModelFrameVertex8)); + } + + // Allocate and Read frame info array + md_FrameInfos.New( md_FramesCt); + pFile->ReadFullChunk_t( CChunkID("AFIN"), &md_FrameInfos[0], md_FramesCt * sizeof(struct ModelFrameInfo)); + // Allocate Read frame main mip vertices array + md_MainMipVertices.New( md_VerticesCt); + pFile->ReadFullChunk_t( CChunkID("AMMV"), &md_MainMipVertices[0], md_VerticesCt * sizeof(FLOAT3D)); + // Allocate and Read vertex mip-mask array + md_VertexMipMask.New( md_VerticesCt); + pFile->ReadFullChunk_t( CChunkID("AVMK"), &md_VertexMipMask[0], md_VerticesCt * sizeof(ULONG)); + + // Read mip levels counter + pFile->ReadFullChunk_t( CChunkID("IMIP"), &md_MipCt, sizeof(INDEX)); + // Read mip factors array + pFile->ReadFullChunk_t( CChunkID("FMIP"), &md_MipSwitchFactors[0], MAX_MODELMIPS * sizeof(float)); + + // Read all model mip infos + INDEX ctMipsRejected=0; + for( i=0; i0) md_MipSwitchFactors[i-ctMipsRejected-1] = md_MipSwitchFactors[i-1]; + } + } + // readjust last mip scaling factor + md_MipSwitchFactors[i-ctMipsRejected-1] = md_MipSwitchFactors[i-1]; + // reduce mip level count + md_MipCt -= ctMipsRejected; + + // if patches are saved in old format + CChunkID cidPatchChunkID = pFile->PeekID_t(); + if( cidPatchChunkID == CChunkID("STMK")) + { + ULONG ulOldExistingPatches; + pFile->ReadFullChunk_t( CChunkID("STMK"), &ulOldExistingPatches, sizeof(ULONG)); + + for( INDEX iPatch=0; iPatch> fnPatchName; + try + { + md_mpPatches[ iPatch].mp_toTexture.SetData_t( fnPatchName); + } + catch(char *strError) + { + (void) strError; + } + } + } + } + // if patches are saved in new format + else if( cidPatchChunkID == CChunkID("PTC2")) + { + pFile->ExpectID_t( CChunkID("PTC2")); + for( INDEX iPatch=0; iPatchReadFullChunk_t( CChunkID("STXW"), &md_Width, sizeof(MEX)); + pFile->ReadFullChunk_t( CChunkID("STXH"), &md_Height, sizeof(MEX)); + + // in old patch format, now patch postiions are loaded + if( cidPatchChunkID == CChunkID("STMK")) + { + pFile->ExpectID_t( CChunkID("POSS")); + ULONG ulChunkSize; + *pFile >> ulChunkSize; + for( INDEX iPatch=0; iPatch> md_mpPatches[ iPatch].mp_mexPosition; + } + } + + + if( !bHasSavedFlagsOnStart) + { + // Read flags + pFile->Read_t( &md_Flags, sizeof(ULONG)); + } + + // Read value for shading type + pFile->Read_t( &md_ShadowQuality, sizeof(SLONG)); + + // Read static stretch value + pFile->Read_t( &md_Stretch, sizeof(FLOAT3D)); + + // if this is model with saved center + if( bHasSavedCenter) { // read it + pFile->Read_t( &md_vCenter, sizeof(FLOAT3D)); + } + // this model has been saved without center point + else { // so just reset it + md_vCenter = FLOAT3D(0,0,0); + } + + // convert model to 8-bit if requested and needed + if( !mdl_bFineQuality && (md_Flags&MF_COMPRESSED_16BIT)) + { + // prepare 8-bit frame vertices array + const INDEX ctVtx = md_VerticesCt * md_FramesCt; + md_FrameVertices8.New(ctVtx); + + // loop thru vertices + for( INDEX iVtx=0; iVtx>8; + mfv8.mfv_SBPoint(2) = mfv16.mfv_SWPoint(2) >>8; + mfv8.mfv_SBPoint(3) = mfv16.mfv_SWPoint(3) >>8; + // convert normal + const INDEX iHofs = mfv16.mfv_ubNormH>>1; + const INDEX iPofs = mfv16.mfv_ubNormP>>1; + mfv8.mfv_NormIndex = aubGouraudConv[iHofs*128+iPofs]; + } + + // done with conversion + md_Stretch *= 256.0f; + md_FrameVertices16.Clear(); + md_Flags &= ~MF_COMPRESSED_16BIT; + } + + // create compressed vector center that will be used for setting object handle + md_vCompressedCenter(1) = -md_vCenter(1)/md_Stretch(1); + md_vCompressedCenter(2) = -md_vCenter(2)/md_Stretch(2); + md_vCompressedCenter(3) = -md_vCenter(3)/md_Stretch(3); + + // if model has been saved with multiple collision boxes + if( bHasMultipleCollisionBoxes) + { + INDEX ctCollisionBoxes; + // get count of collision boxes + pFile->Read_t( &ctCollisionBoxes, sizeof(INDEX)); + // add needed ammount of members + md_acbCollisionBox.New( ctCollisionBoxes); + md_acbCollisionBox.Lock(); + // for all saved collision boxes + for( INDEX iCollisionBox=0; iCollisionBoxPeekID_t()==CChunkID("COLI")) + { + pFile->ExpectID_t("COLI"); + *pFile >> md_bCollideAsCube; + } + else + { + md_bCollideAsCube = FALSE; + } + + // if we should read attached positions + if( bHasAttachedPositions) + { + // read count of attached positions + INDEX ctAttachedPositions; + *pFile >> ctAttachedPositions; + md_aampAttachedPosition.New(ctAttachedPositions); + FOREACHINDYNAMICARRAY(md_aampAttachedPosition, CAttachedModelPosition, itamp) + { + itamp->Read_t(pFile); + // clamp vertices to no of model data vertices + itamp->amp_iCenterVertex = Clamp( itamp->amp_iCenterVertex, (INDEX) 0, md_MainMipVertices.Count()); + itamp->amp_iFrontVertex = Clamp( itamp->amp_iFrontVertex, (INDEX) 0, md_MainMipVertices.Count()); + itamp->amp_iUpVertex = Clamp( itamp->amp_iUpVertex, (INDEX) 0, md_MainMipVertices.Count()); + } + } + + // Read color names (Read count, read existing names) + INDEX iValidColorsCt; + pFile->ReadFullChunk_t( CChunkID("ICLN"), &iValidColorsCt, sizeof(INDEX)); + for( i=0; i> iExistingColorName; + *pFile >> md_ColorNames[ iExistingColorName]; + } + + // Read AnimData + CAnimData::Read_t( pFile); + IndicesToPtrs(); + + // old models don't have saved polygons per surface + if( !bHasPolygonsPerSurface) + { + // so link them manually + LinkDataForSurfaces(TRUE); + + // for each mip model + for( INDEX iMip = 0; iMipmmpi_MappingSurfaces.Count(); iSurface++) + { + // convert rendering flags into new flags format (per surface) + if (pMMI->mmpi_MappingSurfaces[iSurface].ms_aiPolygons.Count()>0) + { + ULONG ulFlags = pMMI->mmpi_Polygons[pMMI->mmpi_MappingSurfaces[iSurface].ms_aiPolygons[0]].mp_RenderFlags; + pMMI->mmpi_MappingSurfaces[iSurface].SetRenderingParameters(ulFlags); + } + } + } + } + + // turn on diffuse map for all models of old format + if( !bHasColorForReflectionAndSpecularity) + { + for( INDEX iMip = 0; iMipmmpi_MappingSurfaces.Count(); iSurface++) + { + pMMI->mmpi_MappingSurfaces[iSurface].ms_ulRenderingFlags |= SRF_DIFFUSE|SRF_NEW_TEXTURE_FORMAT; + } + } + } + + if( bHasDiffuseColor) + { + *pFile >> md_colDiffuse; + } + + // old models don't have saved colors for reflection and specularity + if( bHasColorForReflectionAndSpecularity) + { + // load colors for reflections, specularity and bump + *pFile >> md_colReflections; + *pFile >> md_colSpecular; + *pFile >> md_colBump; + } + + md_bHasAlpha = _bHasAlpha; + + // precalculate rendering data + extern void PrepareModelForRendering(CModelData &md); + PrepareModelForRendering(*this); +} + + +// reference counting (override from CAnimData) +void CModelData::RemReference_internal(void) +{ + // if this model is part of edit model object + if (md_bIsEdited) { + // just unreference it + MarkUnused(); + // if this model is part of model stock + } else { + // release it + _pModelStock->Release(this); + } +} + + +/* Get the description of this object. */ +CTString CModelData::GetDescription(void) +{ + CTString str; + + ModelMipInfo &mmi0 = md_MipInfos[0]; + str.PrintF("%d mips, %d anims, %d frames, %d vtx, %d svx, %d tri", + md_MipCt, ad_NumberOfAnims, md_FramesCt, + mmi0.mmpi_ctMipVx, mmi0.mmpi_ctSrfVx, mmi0.mmpi_ctTriangles); + + return str; +} + +//-------------------------------------------------------------------------------------------- +void ModelMipInfo::Clear() +{ + mmpi_PolygonsCt = 0; // reset number of polygons + mmpi_Polygons.Clear(); // clear static arrays ... + mmpi_TextureVertices.Clear(); + mmpi_MappingSurfaces.Clear(); + mmpi_aPolygonsPerPatch.Clear(); +} +//-------------------------------------------------------------------------------------------- +ModelPolygon::ModelPolygon() +{ + mp_RenderFlags = 0; +} +//-------------------------------------------------------------------------------------------- +ModelPolygon::~ModelPolygon() +{ + mp_PolygonVertices.Clear(); +} +//-------------------------------------------------------------------------------------------- +ModelMipInfo::~ModelMipInfo() +{ + Clear(); +} +//-------------------------------------------------------------------------------------------- +MappingSurface::~MappingSurface() +{ +} +//-------------------------------------------------------------------------------------------- +MappingSurface::MappingSurface() +{ + ms_ulRenderingFlags &= ~SRF_SELECTED; + ms_colDiffuse = C_WHITE|CT_OPAQUE; + ms_colReflections = C_WHITE|CT_OPAQUE; + ms_colSpecular = C_WHITE|CT_OPAQUE; + ms_colBump = C_WHITE|CT_OPAQUE; + ms_ulOnColor = SC_ALLWAYS_ON; + ms_ulOffColor = SC_ALLWAYS_OFF; +} +//-------------------------------------------------------------------------------------------- +/* + * Object constructor + */ +CModelObject::CModelObject() +{ + mo_colBlendColor = 0xFFFFFFFF; + mo_ColorMask = 0x7FFFFFFF; + mo_PatchMask = 0; + mo_iManualMipLevel = 0; + mo_AutoMipModeling = TRUE; + mo_Stretch = FLOAT3D(1,1,1); +} +/* + * Destructor + */ +CModelObject::~CModelObject() +{ + for(INDEX iPatch=0; iPatchamo_iAttachedPosition; + // get one here with same index + CAttachmentModelObject *pamo = GetAttachmentModel(iap); + // if found + if (pamo!=NULL) { + + // sync the model itself + pamo->amo_moModelObject.Synchronize(pamoOther->amo_moModelObject); + + // get original placements of both attachments + pmd->md_aampAttachedPosition.Lock(); + pmdOther->md_aampAttachedPosition.Lock(); + CPlacement3D plOrg = pmd->md_aampAttachedPosition[iap].amp_plRelativePlacement; + CPlacement3D plOtherOrg = pmdOther->md_aampAttachedPosition[iap].amp_plRelativePlacement; + pmd->md_aampAttachedPosition.Unlock(); + pmdOther->md_aampAttachedPosition.Unlock(); + FLOAT3D &v2 = pamo->amo_plRelative.pl_PositionVector; + FLOAT3D &v1 = pamoOther->amo_plRelative.pl_PositionVector; + FLOAT3D &v2O = plOrg.pl_PositionVector; + FLOAT3D &v1O = plOtherOrg.pl_PositionVector; + ANGLE3D &a2 = pamo->amo_plRelative.pl_OrientationAngle; + ANGLE3D &a1 = pamoOther->amo_plRelative.pl_OrientationAngle; + ANGLE3D &a2O = plOrg.pl_OrientationAngle; + ANGLE3D &a1O = plOtherOrg.pl_OrientationAngle; + v2 = v2O+v1-v1O; + a2 = a2O+a1-a1O; + } + } +} + +//-------------------------------------------------------------------------------------------- +//------------------------------------------ WRITE +void CModelObject::Write_t( CTStream *pFile) // throw char * +{ + CAnimObject::Write_t( pFile); + + pFile->WriteID_t( CChunkID( "MODT")); + *pFile << mo_colBlendColor; + pFile->Write_t( &mo_PatchMask, sizeof(ULONG)); + pFile->Write_t( &mo_Stretch, sizeof(FLOAT3D)); + pFile->Write_t( &mo_ColorMask, sizeof(ULONG)); +} +//------------------------------------------ READ +void CModelObject::Read_t( CTStream *pFile) // throw char * +{ + CAnimObject::Read_t( pFile); + + if( pFile->PeekID_t()==CChunkID("MODT")) + { + pFile->ExpectID_t( CChunkID( "MODT")); + *pFile >> mo_colBlendColor; + } + // model object is saved without dynamic blend color + else + { + mo_colBlendColor = 0xFFFFFFFF; + } + + pFile->Read_t( &mo_PatchMask, sizeof(ULONG)); + pFile->Read_t( &mo_Stretch, sizeof(FLOAT3D)); + pFile->Read_t( &mo_ColorMask, sizeof(ULONG)); + for( INDEX i=0; imd_Width; +}; +// retrieves model's texture height +MEX CModelObject::GetHeight() +{ + return GetData()->md_Height; +}; + +//-------------------------------------------------------------------------------------------- +/* + * Routine retrives full model data + */ +void CModelObject::GetModelInfo(CModelInfo &miInfo) +{ + CModelData *pMD = (CModelData *) GetData(); + ASSERT( pMD != NULL); + // copy model data values + miInfo.mi_VerticesCt = pMD->md_VerticesCt; + miInfo.mi_FramesCt = pMD->md_FramesCt; + miInfo.mi_MipCt = pMD->md_MipCt; + for( INDEX i=0; imd_MipCt; i++) + { + miInfo.mi_MipInfos[ i].mi_PolygonsCt = pMD->md_MipInfos[ i].mmpi_PolygonsCt; + + // calculate triangeles + miInfo.mi_MipInfos[ i].mi_TrianglesCt = 0; + for( INDEX iPolygon = 0; iPolygonmd_MipInfos[ i].mmpi_PolygonsCt; iPolygon++) + { + miInfo.mi_MipInfos[ i].mi_TrianglesCt += + pMD->md_MipInfos[ i].mmpi_Polygons[ iPolygon].mp_PolygonVertices.Count()-2; + } + + ULONG ulMipMask = (1L) << i; // working mip model's mask + INDEX iVertexCt = 0; + // count vertices that exists in this mip model + for( INDEX j=0; jmd_VerticesCt; j++) + if( pMD->md_VertexMipMask[ j] & ulMipMask) + iVertexCt ++; + miInfo.mi_MipInfos[ i].mi_VerticesCt = iVertexCt; + } + miInfo.mi_Width = pMD->md_Width; + miInfo.mi_Height = pMD->md_Height; + miInfo.mi_Flags = pMD->md_Flags; + miInfo.mi_ShadowQuality = pMD->md_ShadowQuality; + miInfo.mi_Stretch = pMD->md_Stretch; +} + +//-------------------------------------------------------------------------------------------- +/* + * Is model visible for given mip factor + */ +BOOL CModelObject::IsModelVisible( FLOAT fMipFactor) +{ + CModelData *pMD = (CModelData*)GetData(); + ASSERT( pMD != NULL); + ASSERT( pMD->md_MipCt>0); + // visible if no mip models or disappearence not allowed + if( pMD->md_MipCt==0 || mdl_iLODDisappear==0) return TRUE; + // adjust mip factor in case of dynamic stretch factor + if( mo_Stretch != FLOAT3D(1,1,1)) { + fMipFactor -= Log2( Max(mo_Stretch(1),Max(mo_Stretch(2),mo_Stretch(3)))); + } + // eventually adjusted mip factor with LOD control variables + if( mdl_iLODDisappear==2) fMipFactor = fMipFactor*mdl_fLODMul +mdl_fLODAdd; + // return true if mip factor is smaller than last in model's mip switch factors array + return( fMipFactor < pMD->md_MipSwitchFactors[pMD->md_MipCt-1]); +} + +//-------------------------------------------------------------------------------------------- +/* + * Routine retrieves activ mip model's index + */ +INDEX CModelObject::GetMipModel( FLOAT fMipFactor) +{ + CModelData *pMD = (CModelData*)GetData(); + ASSERT( pMD != NULL); + if( !mo_AutoMipModeling) return mo_iManualMipLevel; + // calculate current mip model + INDEX i=0; + for( ; imd_MipCt; i++) { + if( fMipFactor < pMD->md_MipSwitchFactors[i]) return i; + } + return i-1; +} + +//-------------------------------------------------------------------------------------------- +/* + * retrieves bounding box of given frame + */ +FLOATaabbox3D CModelObject::GetFrameBBox( INDEX iFrameNo) +{ + CModelData *pMD = (CModelData *) GetData(); + ASSERT( pMD != NULL); + return pMD->md_FrameInfos[ iFrameNo].mfi_Box; +} + +//-------------------------------------------------------------------------------------------- +/* + * Routine returns mo_AutoMipModeling flag + */ +BOOL CModelObject::IsAutoMipModeling() +{ + return mo_AutoMipModeling; +} + +//-------------------------------------------------------------------------------------------- +/* + * Sets mo_AutoMipModeling flag to on + */ +void CModelObject::AutoMipModelingOn() +{ + mo_AutoMipModeling = TRUE; + MarkChanged(); +} + +//-------------------------------------------------------------------------------------------- +/* + * Sets mo_AutoMipModeling flag to off + */ +void CModelObject::AutoMipModelingOff() +{ + mo_AutoMipModeling = FALSE; + MarkChanged(); +} + +//-------------------------------------------------------------------------------------------- +/* + * Routine retrieves current mip level + */ +INDEX CModelObject::GetManualMipLevel() +{ + return mo_iManualMipLevel; +} +//-------------------------------------------------------------------------------------------- +/* + * Routine sets current mip level + */ +void CModelObject::SetManualMipLevel(INDEX iNewMipLevel) +{ + mo_iManualMipLevel = iNewMipLevel; + MarkChanged(); +} +//-------------------------------------------------------------------------------------------- +/* + * Routine sets given mip-level's switch factor + */ +void CModelObject::SetMipSwitchFactor(INDEX iMipLevel, float fMipFactor) +{ + CModelData *pMD = (CModelData *) GetData(); + ASSERT( iMipLevel < pMD->md_MipCt); + pMD->md_MipSwitchFactors[ iMipLevel] = fMipFactor; + MarkChanged(); +} +//-------------------------------------------------------------------------------------------- +/* + * Select one rougher mip model level + */ +void CModelObject::NextManualMipLevel() +{ + CModelData *pMD = (CModelData *) GetData(); + if( mo_iManualMipLevel < pMD->md_MipCt-1) + { + mo_iManualMipLevel += 1; + MarkChanged(); + } +} + +//-------------------------------------------------------------------------------------------- +/* + * Select one more precize mip model level + */ +void CModelObject::PrevManualMipLevel() +{ + if( mo_iManualMipLevel > 0) + { + mo_iManualMipLevel -= 1; + MarkChanged(); + } +} + + +// this function returns current value of patches mask +ULONG CModelObject::GetPatchesMask() +{ + return mo_PatchMask; +}; +// use this function to set new patches combination +void CModelObject::SetPatchesMask(ULONG new_patches_mask) +{ + mo_PatchMask = new_patches_mask; +} + +//-------------------------------------------------------------------------------------------- +/* + * Sets new name to a color with given index + */ +void CModelObject::SetColorName( INDEX iColor, CTString &strNewName) +{ + CModelData *pMD = (CModelData *) GetData(); + ASSERT( iColor < MAX_COLOR_NAMES); + pMD->md_ColorNames[ iColor] = strNewName; +} +//-------------------------------------------------------------------------------------------- +/* + * Retrieves name of color with given index + */ +CTString CModelObject::GetColorName( INDEX iColor) +{ + CModelData *pMD = (CModelData *) GetData(); + ASSERT( iColor < MAX_COLOR_NAMES); + return pMD->md_ColorNames[ iColor]; +} +//-------------------------------------------------------------------------------------------- +/* + * Retrieves color of given surface + */ +COLOR CModelObject::GetSurfaceColor( INDEX iCurrentMip, INDEX iCurrentSurface) +{ + struct ModelPolygon *pPoly; + CModelData *pMD = (CModelData *) GetData(); + if( (iCurrentMip>=pMD->md_MipCt) || + (iCurrentSurface>=pMD->md_MipInfos[ iCurrentMip].mmpi_MappingSurfaces.Count()) ) + { + return -1; + } + for( INDEX i=0; imd_MipInfos[ iCurrentMip].mmpi_PolygonsCt; i++) + { + pPoly = &pMD->md_MipInfos[ iCurrentMip].mmpi_Polygons[ i]; + if( pPoly->mp_Surface == iCurrentSurface) + { + return pPoly->mp_ColorAndAlpha; + } + } + return 0; +} +//-------------------------------------------------------------------------------------------- +/* + * Changes color of given surface + */ +void CModelObject::SetSurfaceColor( INDEX iCurrentMip, INDEX iCurrentSurface, + COLOR colNewColorAndAlpha) +{ + struct ModelPolygon *pPoly; + CModelData *pMD = (CModelData *) GetData(); + if( (iCurrentMip>=pMD->md_MipCt) || + (iCurrentSurface>=pMD->md_MipInfos[ iCurrentMip].mmpi_MappingSurfaces.Count()) ) + { + return; + } + pMD->md_MipInfos[ iCurrentMip].mmpi_MappingSurfaces[iCurrentSurface].ms_colColor = colNewColorAndAlpha; + for( INDEX i=0; imd_MipInfos[ iCurrentMip].mmpi_PolygonsCt; i++) + { + pPoly = &pMD->md_MipInfos[ iCurrentMip].mmpi_Polygons[ i]; + if( pPoly->mp_Surface == iCurrentSurface) + { + pPoly->mp_ColorAndAlpha = colNewColorAndAlpha; + } + } +} +//-------------------------------------------------------------------------------------------- +/* + * Retrieves rendering flags of given surface + */ +void CModelObject::GetSurfaceRenderFlags( INDEX iCurrentMip, INDEX iCurrentSurface, + enum SurfaceShadingType &sstShading, enum SurfaceTranslucencyType &sttTranslucency, + ULONG &ulRenderingFlags) +{ + CModelData *pMD = (CModelData *) GetData(); + if( (iCurrentMip>=pMD->md_MipCt) || + (iCurrentSurface>=pMD->md_MipInfos[ iCurrentMip].mmpi_MappingSurfaces.Count()) ) + { + return; + } + MappingSurface *pms = &pMD->md_MipInfos[ iCurrentMip].mmpi_MappingSurfaces[iCurrentSurface]; + sstShading = pms->ms_sstShadingType; + sttTranslucency = pms->ms_sttTranslucencyType; + ulRenderingFlags = pms->ms_ulRenderingFlags; +} +//-------------------------------------------------------------------------------------------- +/* + * Changes rendering of given surface + */ +void CModelObject::SetSurfaceRenderFlags( INDEX iCurrentMip, INDEX iCurrentSurface, + enum SurfaceShadingType sstShading, enum SurfaceTranslucencyType sttTranslucency, + ULONG ulRenderingFlags) +{ + CModelData *pMD = (CModelData *) GetData(); + if( (iCurrentMip>=pMD->md_MipCt) || + (iCurrentSurface>=pMD->md_MipInfos[ iCurrentMip].mmpi_MappingSurfaces.Count()) ) + { + return; + } + // convert surface rendering parameters from old polygon flags -- temporary !!!! + MappingSurface *pms = &pMD->md_MipInfos[ iCurrentMip].mmpi_MappingSurfaces[iCurrentSurface]; + pms->ms_sstShadingType = sstShading; + pms->ms_sttTranslucencyType = sttTranslucency; + pms->ms_ulRenderingFlags = ulRenderingFlags; +} + +//-------------------------------------------------------------------------------------------- +void CModelObject::ProjectFrameVertices( CProjection3D *pProjection, INDEX iMipModel) +{ + FLOAT3D f3dVertex; + + CModelData *pMD = (CModelData *) GetData(); + pProjection->ObjectHandleL() = pMD->md_vCompressedCenter; + pProjection->ObjectStretchL() = pMD->md_Stretch; + // apply dynamic stretch + pProjection->ObjectStretchL()(1) *= mo_Stretch(1); + pProjection->ObjectStretchL()(2) *= mo_Stretch(2); + pProjection->ObjectStretchL()(3) *= mo_Stretch(3); + pProjection->ObjectFaceForwardL() = pMD->md_Flags & (MF_FACE_FORWARD|MF_HALF_FACE_FORWARD); + pProjection->ObjectHalfFaceForwardL() = pMD->md_Flags & MF_HALF_FACE_FORWARD; + pProjection->Prepare(); + + INDEX iCurrentFrame = GetFrame(); + ULONG ulVtxMask = (1L) << iMipModel; + + if( pMD->md_Flags & MF_COMPRESSED_16BIT) + { + ModelFrameVertex16 *pFrame = &pMD->md_FrameVertices16[ iCurrentFrame * pMD->md_VerticesCt]; + for( INDEX i=0; imd_VerticesCt; i++) + { + if( pMD->md_VertexMipMask[ i] & ulVtxMask) + { + f3dVertex(1) = (float) pFrame[ i].mfv_SWPoint(1); + f3dVertex(2) = (float) pFrame[ i].mfv_SWPoint(2); + f3dVertex(3) = (float) pFrame[ i].mfv_SWPoint(3); + pProjection->ProjectCoordinate( f3dVertex, pMD->md_TransformedVertices[ i].tvd_TransformedPoint); + } + } + } + else + { + ModelFrameVertex8 *pFrame = &pMD->md_FrameVertices8[ iCurrentFrame * pMD->md_VerticesCt]; + for( INDEX i=0; imd_VerticesCt; i++) + { + if( pMD->md_VertexMipMask[ i] & ulVtxMask) + { + f3dVertex(1) = (float) pFrame[ i].mfv_SBPoint(1); + f3dVertex(2) = (float) pFrame[ i].mfv_SBPoint(2); + f3dVertex(3) = (float) pFrame[ i].mfv_SBPoint(3); + pProjection->ProjectCoordinate( f3dVertex, pMD->md_TransformedVertices[ i].tvd_TransformedPoint); + } + } + } +} +//-------------------------------------------------------------------------------------------- +/* + * Colorizes surfaces touching given box + */ +void CModelObject::ColorizeRegion( CDrawPort *pDP, CProjection3D *pProjection, PIXaabbox2D box, + INDEX iChoosedColor, BOOL bOnColorMode) +{ + struct ModelPolygon *pPoly; + CModelData *pMD = (CModelData *) GetData(); + struct TransformedVertexData *pTransformedVertice; + PIX pixDPHeight = pDP->GetHeight(); + // project vertices for given mip model + ProjectFrameVertices( pProjection, mo_iLastRenderMipLevel); + for( INDEX j=0; jmd_MipInfos[ mo_iLastRenderMipLevel].mmpi_PolygonsCt; j++) + { + pPoly = &pMD->md_MipInfos[ mo_iLastRenderMipLevel].mmpi_Polygons[ j]; + for( INDEX i=0; imp_PolygonVertices.Count(); i++) + { + pTransformedVertice = pPoly->mp_PolygonVertices[ i].mpv_ptvTransformedVertex; + PIXaabbox2D ptBox = PIXaabbox2D( PIX2D( (SWORD) pTransformedVertice->tvd_TransformedPoint(1), + pixDPHeight - (SWORD) pTransformedVertice->tvd_TransformedPoint(2))); + if( !((box & ptBox).IsEmpty()) ) + { + MappingSurface &ms = pMD->md_MipInfos[ mo_iLastRenderMipLevel].mmpi_MappingSurfaces[ pPoly->mp_Surface]; + if( bOnColorMode) + { + //pPoly->mp_OnColor = 1UL << iChoosedColor; + ms.ms_ulOnColor = 1UL << iChoosedColor; + } + else + { + //pPoly->mp_OffColor = 1UL << iChoosedColor; + ms.ms_ulOffColor = 1UL << iChoosedColor; + } + break; + } + } + } +} +//-------------------------------------------------------------------------------------------- +/* + * Colorizes polygons touching given box + */ +void CModelObject::ApplySurfaceToPolygonsInRegion( CDrawPort *pDP, CProjection3D *pProjection, + PIXaabbox2D box, INDEX iSurface, COLOR colSurfaceColor) +{ + // project vertices for given mip model + ProjectFrameVertices( pProjection, mo_iLastRenderMipLevel); + + struct ModelPolygon *pPoly; + struct TransformedVertexData *pTransformedVertice; + CModelData *pMD = (CModelData *) GetData(); + PIX pixDPHeight = pDP->GetHeight(); + + for( INDEX j=0; jmd_MipInfos[ mo_iLastRenderMipLevel].mmpi_PolygonsCt; j++) + { + pPoly = &pMD->md_MipInfos[ mo_iLastRenderMipLevel].mmpi_Polygons[ j]; + for( INDEX i=0; imp_PolygonVertices.Count(); i++) + { + pTransformedVertice = pPoly->mp_PolygonVertices[ i].mpv_ptvTransformedVertex; + PIXaabbox2D ptBox = PIXaabbox2D( PIX2D( (SWORD) pTransformedVertice->tvd_TransformedPoint(1), + pixDPHeight - (SWORD) pTransformedVertice->tvd_TransformedPoint(2))); + if( !((box & ptBox).IsEmpty()) ) + { + pPoly->mp_Surface = iSurface; + pPoly->mp_ColorAndAlpha = colSurfaceColor; + break; + } + } + } +} + +// unpack a vertex +void CModelObject::UnpackVertex(INDEX iFrame, INDEX iVertex, FLOAT3D &vVertex) +{ + CModelData *pmd = (CModelData *) GetData(); + // get decompression/stretch factors + FLOAT3D &vDataStretch = pmd->md_Stretch; + FLOAT3D &vObjectStretch = mo_Stretch; + FLOAT3D vStretch; + vStretch(1) = vDataStretch(1)*vObjectStretch(1); + vStretch(2) = vDataStretch(2)*vObjectStretch(2); + vStretch(3) = vDataStretch(3)*vObjectStretch(3); + FLOAT3D vOffset = pmd->md_vCompressedCenter; + + if( pmd->md_Flags & MF_COMPRESSED_16BIT) + { + struct ModelFrameVertex16 *pFrame16 = &pmd->md_FrameVertices16[iFrame * pmd->md_VerticesCt]; + vVertex(1) = (pFrame16[iVertex].mfv_SWPoint(1)-vOffset(1))*vStretch(1); + vVertex(2) = (pFrame16[iVertex].mfv_SWPoint(2)-vOffset(2))*vStretch(2); + vVertex(3) = (pFrame16[iVertex].mfv_SWPoint(3)-vOffset(3))*vStretch(3); + } else { + struct ModelFrameVertex8 *pFrame8 = &pmd->md_FrameVertices8[iFrame * pmd->md_VerticesCt]; + vVertex(1) = (pFrame8[iVertex].mfv_SBPoint(1)-vOffset(1))*vStretch(1); + vVertex(2) = (pFrame8[iVertex].mfv_SBPoint(2)-vOffset(2))*vStretch(2); + vVertex(3) = (pFrame8[iVertex].mfv_SBPoint(3)-vOffset(3))*vStretch(3); + } +} + +CPlacement3D CModelObject::GetAttachmentPlacement(CAttachmentModelObject &amo) +{ + // project reference points to view space + FLOAT3D vCenter, vFront, vUp; + CModelData *pmd = (CModelData *) GetData(); + pmd->md_aampAttachedPosition.Lock(); + INDEX iPosition = amo.amo_iAttachedPosition; + INDEX iCenter = pmd->md_aampAttachedPosition[iPosition].amp_iCenterVertex; + INDEX iFront = pmd->md_aampAttachedPosition[iPosition].amp_iFrontVertex; + INDEX iUp = pmd->md_aampAttachedPosition[iPosition].amp_iUpVertex; + INDEX iFrame = GetFrame(); + + UnpackVertex( iFrame, iCenter, vCenter); + UnpackVertex( iFrame, iFront, vFront); + UnpackVertex( iFrame, iUp, vUp); + + // make axis vectors in absolute space + FLOAT3D &vO = vCenter; + FLOAT3D vY = vUp-vCenter; + FLOAT3D vZ = vCenter-vFront; + FLOAT3D vX = vY*vZ; + vY = vZ*vX; + // make a rotation matrix from those vectors + vX.Normalize(); + vY.Normalize(); + vZ.Normalize(); + FLOATmatrix3D mOrientation; + mOrientation(1,1) = vX(1); mOrientation(1,2) = vY(1); mOrientation(1,3) = vZ(1); + mOrientation(2,1) = vX(2); mOrientation(2,2) = vY(2); mOrientation(2,3) = vZ(2); + mOrientation(3,1) = vX(3); mOrientation(3,2) = vY(3); mOrientation(3,3) = vZ(3); + + // make reference placement in absolute space + CPlacement3D plPoints; + plPoints.pl_PositionVector = vO; + DecomposeRotationMatrixNoSnap(plPoints.pl_OrientationAngle, mOrientation); + CPlacement3D pl = amo.amo_plRelative; + pl.RelativeToAbsoluteSmooth(plPoints); + pmd->md_aampAttachedPosition.Unlock(); + return pl; +} + +//-------------------------------------------------------------------------------------------- +/* + * Find hitted polygon + */ +struct ModelPolygon *CModelObject::PolygonHit( + CPlacement3D plRay, CPlacement3D plObject, INDEX iCurrentMip, FLOAT &fHitDistance) +{ + struct ModelPolygon *pResultPoly = NULL; + + fHitDistance = 100000.0f; + + FOREACHINLIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) { + FLOAT fHit; + CPlacement3D plAttachment = GetAttachmentPlacement(*itamo); + plAttachment.RelativeToAbsolute(plObject); + struct ModelPolygon *pmp = itamo->amo_moModelObject.PolygonHit(plRay, plAttachment, iCurrentMip, fHit); + if (fHit < fHitDistance) { + fHitDistance = fHit; + pResultPoly = pmp; + } + } + FLOAT fHit; + struct ModelPolygon *pmp = PolygonHitModelData((CModelData*)GetData(), plRay, plObject, iCurrentMip, fHit); + if (fHit < fHitDistance) { + fHitDistance = fHit; + pResultPoly = pmp; + } + + return pResultPoly; +} + +struct ModelPolygon *CModelObject::PolygonHitModelData(CModelData *pMD, + CPlacement3D plRay, CPlacement3D plObject, INDEX iCurrentMip, FLOAT &fHitDistance) +{ + FLOAT fClosest = -100000.0f; + struct ModelPolygon *pPoly, *pResultPoly = NULL; + CIntersector Intersector; + + CSimpleProjection3D spProjection; + spProjection.ViewerPlacementL() = plRay; + spProjection.ObjectPlacementL() = plObject; + // project vertices for given mip model + ProjectFrameVertices( &spProjection, iCurrentMip); + + for( INDEX j=0; jmd_MipInfos[ iCurrentMip].mmpi_PolygonsCt; j++) + { + Intersector.Clear(); + pPoly = &pMD->md_MipInfos[ iCurrentMip].mmpi_Polygons[ j]; + for( INDEX i=0; imp_PolygonVertices.Count(); i++) + { + // get next vertex index (first is i) + INDEX next = (i+1) % pPoly->mp_PolygonVertices.Count(); + // add edge to intersection object + Intersector.AddEdge( pPoly->mp_PolygonVertices[ i].mpv_ptvTransformedVertex->tvd_TransformedPoint(1), + pPoly->mp_PolygonVertices[ i].mpv_ptvTransformedVertex->tvd_TransformedPoint(2), + pPoly->mp_PolygonVertices[ next].mpv_ptvTransformedVertex->tvd_TransformedPoint(1), + pPoly->mp_PolygonVertices[ next].mpv_ptvTransformedVertex->tvd_TransformedPoint(2)); + } + if( Intersector.IsIntersecting()) + { + FLOAT3D f3dTr0 = pPoly->mp_PolygonVertices[ 0].mpv_ptvTransformedVertex->tvd_TransformedPoint; + FLOAT3D f3dTr1 = pPoly->mp_PolygonVertices[ 1].mpv_ptvTransformedVertex->tvd_TransformedPoint; + FLOAT3D f3dTr2 = pPoly->mp_PolygonVertices[ 2].mpv_ptvTransformedVertex->tvd_TransformedPoint; + FLOATplane3D fplPlane = FLOATplane3D( f3dTr0, f3dTr1, f3dTr2); + + FLOAT3D f3dHitted3DPoint = FLOAT3D(0,0,0); + fplPlane.GetCoordinate( 3, f3dHitted3DPoint); + if( f3dHitted3DPoint(3)<=0.0f && f3dHitted3DPoint(3)> fClosest) + { + fClosest = f3dHitted3DPoint(3); + pResultPoly = pPoly; + } + } + } + // return closest hit polygon and the distance where it was hit + fHitDistance = -fClosest; + return pResultPoly; +} + + +//-------------------------------------------------------------------------------------------- +/* + * Colorizes hitted polygon + */ +void CModelObject::ColorizePolygon( CDrawPort *pDP, CProjection3D *projection, PIX x1, PIX y1, + INDEX iChoosedColor, BOOL bOnColorMode) +{ + CPlacement3D plRay; + CPlacement3D plObjectPlacement; + + projection->Prepare(); + projection->RayThroughPoint( FLOAT3D( (FLOAT)x1, (FLOAT)(pDP->GetHeight()-y1), 0.0f), + plRay); + plObjectPlacement = projection->ObjectPlacementR(); + + FLOAT fHitDistance; + struct ModelPolygon *pPoly = PolygonHit( plRay, plObjectPlacement, mo_iLastRenderMipLevel, fHitDistance); + if( pPoly != NULL) + { + CModelData *pMD = (CModelData *) GetData(); + MappingSurface &ms = pMD->md_MipInfos[ mo_iLastRenderMipLevel].mmpi_MappingSurfaces[ pPoly->mp_Surface]; + if( bOnColorMode) + { + //pPoly->mp_OnColor = 1UL << iChoosedColor; + ms.ms_ulOnColor = 1UL << iChoosedColor; + } + else + { + //pPoly->mp_OffColor = 1UL << iChoosedColor; + ms.ms_ulOffColor = 1UL << iChoosedColor; + } + } +} + +void CModelObject::ApplySurfaceToPolygon( CDrawPort *pDP, CProjection3D *projection, + PIX x1, PIX y1, INDEX iSurface, COLOR colSurfaceColor) +{ + CPlacement3D plRay; + CPlacement3D plObjectPlacement; + + projection->Prepare(); + projection->RayThroughPoint( FLOAT3D( (FLOAT)x1, (FLOAT)(pDP->GetHeight()-y1), 0.0f), + plRay); + plObjectPlacement = projection->ObjectPlacementR(); + + FLOAT fHitDistance; + struct ModelPolygon *pPoly = PolygonHit( plRay, plObjectPlacement, mo_iLastRenderMipLevel, fHitDistance); + if( pPoly != NULL) + { + pPoly->mp_ColorAndAlpha = colSurfaceColor; + pPoly->mp_Surface = iSurface; + } +} +//-------------------------------------------------------------------------------------------- +/* + * Picks color from hitted polygon + */ +void CModelObject::PickPolyColor( CDrawPort *pDP, CProjection3D *projection, PIX x1, PIX y1, + INDEX &iPickedColorNo, BOOL bOnColorMode) +{ + CPlacement3D plRay; + CPlacement3D plObjectPlacement; + + projection->Prepare(); + projection->RayThroughPoint( FLOAT3D( (FLOAT)x1, (FLOAT)(pDP->GetHeight()-y1), 0.0f), + plRay); + plObjectPlacement = projection->ObjectPlacementR(); + + FLOAT fHitDistance; + struct ModelPolygon *pPoly = PolygonHit( plRay, plObjectPlacement, mo_iLastRenderMipLevel, fHitDistance); + if( pPoly != NULL) + { + CModelData *pMD = (CModelData *) GetData(); + MappingSurface &ms = pMD->md_MipInfos[ mo_iLastRenderMipLevel].mmpi_MappingSurfaces[ pPoly->mp_Surface]; + + if( bOnColorMode) + { + iPickedColorNo = GetBit( ms.ms_ulOnColor); + } + else + { + iPickedColorNo = GetBit( ms.ms_ulOffColor); + } + } +} +//-------------------------------------------------------------------------------------------- +INDEX CModelObject::PickPolySurface( CDrawPort *pDP, CProjection3D *projection, PIX x1, PIX y1) +{ + CPlacement3D plRay; + CPlacement3D plObjectPlacement; + + projection->Prepare(); + projection->RayThroughPoint( FLOAT3D( (FLOAT)x1, (FLOAT)(pDP->GetHeight()-y1), 0.0f), + plRay); + plObjectPlacement = projection->ObjectPlacementR(); + + FLOAT fHitDistance; + struct ModelPolygon *pPoly = PolygonHit( plRay, plObjectPlacement, mo_iLastRenderMipLevel, fHitDistance); + if( pPoly != NULL) + { + return pPoly->mp_Surface; + } + return -1; +} + +//-------------------------------------------------------------------------------------------- +/* + * Obtains index of closest vertex + */ +INDEX CModelObject::PickVertexIndex( CDrawPort *pDP, CProjection3D *pProjection, PIX x1, PIX y1, + FLOAT3D &vClosestVertex) +{ + CModelData *pMD = (CModelData *) GetData(); + // project vertices for given mip model + ProjectFrameVertices( pProjection, mo_iLastRenderMipLevel); + + FLOAT fClosest = 64.0f; + FLOAT iClosest = -1; + INDEX iCurrentFrame = GetFrame(); + FLOAT3D vTargetPoint = FLOAT3D( x1, pDP->GetHeight()-y1, 0.0f); + ULONG ulVtxMask = (1L) << mo_iLastRenderMipLevel; + // Find closest vertice + for( INDEX iVertex=0; iVertexmd_VerticesCt; iVertex++) + { + if( pMD->md_VertexMipMask[ iVertex] & ulVtxMask) + { + FLOAT3D vProjected = pMD->md_TransformedVertices[ iVertex].tvd_TransformedPoint; + vProjected(3) = 0.0f; + FLOAT3D vUncompressedVertex; + if( pMD->md_Flags & MF_COMPRESSED_16BIT) + { + ModelFrameVertex16 *pFrame = &pMD->md_FrameVertices16[ iCurrentFrame * pMD->md_VerticesCt]; + vUncompressedVertex(1) = (float) pFrame[ iVertex].mfv_SWPoint(1); + vUncompressedVertex(2) = (float) pFrame[ iVertex].mfv_SWPoint(2); + vUncompressedVertex(3) = (float) pFrame[ iVertex].mfv_SWPoint(3); + } + else + { + ModelFrameVertex8 *pFrame = &pMD->md_FrameVertices8[ iCurrentFrame * pMD->md_VerticesCt]; + vUncompressedVertex(1) = (float) pFrame[ iVertex].mfv_SBPoint(1); + vUncompressedVertex(2) = (float) pFrame[ iVertex].mfv_SBPoint(2); + vUncompressedVertex(3) = (float) pFrame[ iVertex].mfv_SBPoint(3); + } + + FLOAT fDistance = Abs( ( vProjected-vTargetPoint).Length()); + if( fDistance < fClosest) + { + fClosest = fDistance; + iClosest = iVertex; + vClosestVertex(1) = vUncompressedVertex(1)*pMD->md_Stretch(1); + vClosestVertex(2) = vUncompressedVertex(2)*pMD->md_Stretch(2); + vClosestVertex(3) = vUncompressedVertex(3)*pMD->md_Stretch(3); + } + } + } + return iClosest; +} + +/* + * Retrieves current frame's bounding box + */ +void CModelObject::GetCurrentFrameBBox( FLOATaabbox3D &MaxBB) +{ + // obtain model data ptr + CModelData *pMD = (CModelData *)GetData(); + ASSERT( pMD != NULL); + // get current frame + INDEX iCurrentFrame = GetFrame(); + ASSERT( iCurrentFrame < pMD->md_FramesCt); + // set current frame's bounding box + MaxBB = pMD->md_FrameInfos[ iCurrentFrame].mfi_Box; +} + +/* + * Retrieves bounding box of all frames + */ +void CModelObject::GetAllFramesBBox( FLOATaabbox3D &MaxBB) +{ + // obtain model data ptr + CModelData *pMD = (CModelData *)GetData(); + ASSERT( pMD != NULL); + // get all frames bounding box + pMD->GetAllFramesBBox( MaxBB); +} + +FLOAT3D CModelObject::GetCollisionBoxMin(INDEX iCollisionBox) +{ + return GetData()->GetCollisionBoxMin(iCollisionBox); +} + +FLOAT3D CModelObject::GetCollisionBoxMax(INDEX iCollisionBox) +{ + return GetData()->GetCollisionBoxMax(iCollisionBox); +} + +// returns HEIGHT_EQ_WIDTH, LENGHT_EQ_WIDTH or LENGHT_EQ_HEIGHT +INDEX CModelObject::GetCollisionBoxDimensionEquality(INDEX iCollisionBox) +{ + return GetData()->GetCollisionBoxDimensionEquality(iCollisionBox); +} +// test it the model has alpha blending +BOOL CModelObject::HasAlpha(void) +{ + return GetData()->md_bHasAlpha || (mo_colBlendColor&0xFF)!=0xFF; +} + +// retrieves number of surfaces used in given mip model +INDEX CModelObject::SurfacesCt(INDEX iMipModel){ + ASSERT( GetData() != NULL); + return GetData()->md_MipInfos[ iMipModel].mmpi_MappingSurfaces.Count(); +}; +// retrieves number of polygons in given surface in given mip model +INDEX CModelObject::PolygonsInSurfaceCt(INDEX iMipModel, INDEX iSurface) +{ + ASSERT( GetData() != NULL); + return GetData()->md_MipInfos[ iMipModel].mmpi_MappingSurfaces[iSurface].ms_aiPolygons.Count(); +}; + +//-------------------------------------------------------------------------------------------- +/* + * Adds and shows given patch + */ +void CModelObject::ShowPatch( INDEX iMaskBit) +{ + CModelData *pMD = (CModelData *)GetData(); + ASSERT( pMD != NULL); + if( pMD == NULL) return; + if( (mo_PatchMask & ((1UL) << iMaskBit)) != 0) return; + mo_PatchMask |= (1UL) << iMaskBit; +} +//-------------------------------------------------------------------------------------------- +/* + * Hides given patch + */ +void CModelObject::HidePatch( INDEX iMaskBit) +{ + CModelData *pMD = (CModelData *)GetData(); + if( pMD == NULL) return; + if( (mo_PatchMask & ((1UL) << iMaskBit)) == 0) return; + mo_PatchMask &= ~((1UL) << iMaskBit); +} +//-------------------------------------------------------------------------------------------- +/* + * Retrieves index of mip model that casts shadow + */ +BOOL CModelObject::HasShadow(INDEX iModelMip) +{ + CModelData *pMD = (CModelData *) GetData(); + SLONG slShadowQuality = _mrpModelRenderPrefs.GetShadowQuality(); + ASSERT( slShadowQuality >= 0); + SLONG res = iModelMip + slShadowQuality + pMD->md_ShadowQuality; + if( res >= pMD->md_MipCt) + return FALSE; + return TRUE; +} + +/* + * Set texture data for main texture in surface of this model. + */ +void CModelObject::SetTextureData(CTextureData *ptdNewMainTexture) +{ + mo_toTexture.SetData(ptdNewMainTexture); +} + +CTFileName CModelObject::GetName(void) +{ + CModelData *pmd = (CModelData *) GetData(); + if( pmd == NULL) return CTString( ""); + return pmd->GetName(); +} + +// obtain model and set it for this object +void CModelObject::SetData_t(const CTFileName &fnmModel) // throw char * +{ + // if the filename is empty + if (fnmModel=="") { + // release current texture + SetData(NULL); + + // if the filename is not empty + } else { + // obtain it (adds one reference) + CModelData *pmd = _pModelStock->Obtain_t(fnmModel); + // set it as data (adds one more reference, and remove old reference) + SetData(pmd); + // release it (removes one reference) + _pModelStock->Release(pmd); + // total reference count +1+1-1 = +1 for new data -1 for old data + } +} + +void CModelObject::SetData(CModelData *pmd) +{ + RemoveAllAttachmentModels(); + CAnimObject::SetData(pmd); +} + +CModelData *CModelObject::GetData(void) +{ + return (CModelData*)CAnimObject::GetData(); +} + +void CModelObject::AutoSetTextures(void) +{ + CTFileName fnModel = GetName(); + CTFileName fnDiffuse; + INDEX ctDiffuseTextures; + CTFileName fnReflection; + CTFileName fnSpecular; + CTFileName fnBump; + // extract from model's ini file informations about attachment model's textures + try + { + CTFileName fnIni = fnModel.NoExt()+".ini"; + CTFileStream strmIni; + strmIni.Open_t( fnIni); + SLONG slFileSize = strmIni.GetStreamSize(); + // NEVER!NEVER! read after EOF + while(strmIni.GetPos_t()<(slFileSize-4)) + { + CChunkID id = strmIni.PeekID_t(); + if( id == CChunkID("WTEX")) + { + CChunkID idDummy = strmIni.GetID_t(); + strmIni >> ctDiffuseTextures; + strmIni >> fnDiffuse; + } + else if( id == CChunkID("FXTR")) + { + CChunkID idDummy = strmIni.GetID_t(); + strmIni >> fnReflection; + } + else if( id == CChunkID("FXTS")) + { + CChunkID idDummy = strmIni.GetID_t(); + strmIni >> fnSpecular; + } + else if( id == CChunkID("FXTB")) + { + CChunkID idDummy = strmIni.GetID_t(); + strmIni >> fnBump; + } + else + { + strmIni.Seek_t(1,CTStream::SD_CUR); + } + } + } + catch( char *strError){ (void) strError;} + + try + { + if( fnDiffuse != "") mo_toTexture.SetData_t( fnDiffuse); + if( fnReflection != "") mo_toReflection.SetData_t( fnReflection); + if( fnSpecular != "") mo_toSpecular.SetData_t( fnSpecular); + if( fnBump != "") mo_toBump.SetData_t( fnBump); + } + catch( char *strError){ (void) strError;} +} + +void CModelObject::AutoSetAttachments(void) +{ + CTFileName fnModel = GetName(); + RemoveAllAttachmentModels(); + + // extract from model's ini file informations about attachment model's textures + try + { + CTFileName fnIni = fnModel.NoExt()+".ini"; + CTFileStream strmIni; + strmIni.Open_t( fnIni); + SLONG slFileSize = strmIni.GetStreamSize(); + // NEVER!NEVER! read after EOF + while(strmIni.GetPos_t()<(slFileSize-4)) + { + CChunkID id = strmIni.PeekID_t(); + if( id == CChunkID("ATTM")) + { + CChunkID idDummy = strmIni.GetID_t(); + // try to load attached models + INDEX ctAttachedModels; + strmIni >> ctAttachedModels; + // read all attached models + for( INDEX iAtt=0; iAtt> bVisible; + strmIni >> strName; + // this data is used no more + strmIni >> fnModel; + + INDEX iAnimation = 0; + // new attached model format has saved index of animation + if( strmIni.PeekID_t() == CChunkID("AMAN")) + { + strmIni.ExpectID_t( CChunkID( "AMAN")); + strmIni >> iAnimation; + } + else + { + strmIni >> fnDummy; // ex model's texture + } + + if( bVisible) + { + CAttachmentModelObject *pamo = AddAttachmentModel( iAtt); + pamo->amo_moModelObject.SetData_t( fnModel); + pamo->amo_moModelObject.AutoSetTextures(); + pamo->amo_moModelObject.StartAnim( iAnimation); + } + } + } + else + { + strmIni.Seek_t(1,CTStream::SD_CUR); + } + } + } + catch( char *strError) + { + (void) strError; + RemoveAllAttachmentModels(); + } + + FOREACHINLIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) + { + itamo->amo_moModelObject.AutoSetAttachments(); + } +} + +CAttachmentModelObject *CModelObject::AddAttachmentModel( INDEX iAttachedPosition) +{ + CModelData *pMD = (CModelData *) GetData(); + + if (pMD->md_aampAttachedPosition.Count()==0) { + return NULL; + } + ASSERT( iAttachedPosition >= 0); + ASSERT( iAttachedPosition < pMD->md_aampAttachedPosition.Count()); + iAttachedPosition = Clamp(iAttachedPosition, INDEX(0), INDEX(pMD->md_aampAttachedPosition.Count()-1)); + CAttachmentModelObject *pamoNew = new CAttachmentModelObject; + mo_lhAttachments.AddTail( pamoNew->amo_lnInMain); + pamoNew->amo_iAttachedPosition = iAttachedPosition; + pMD->md_aampAttachedPosition.Lock(); + pamoNew->amo_plRelative = pMD->md_aampAttachedPosition[iAttachedPosition].amp_plRelativePlacement; + pMD->md_aampAttachedPosition.Unlock(); + + return pamoNew; +} + +CAttachmentModelObject *CModelObject::GetAttachmentModel( INDEX ipos) +{ + FOREACHINLIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) { + CAttachmentModelObject &amo = *itamo; + if (amo.amo_iAttachedPosition == ipos) { + return &amo; + } + } + return NULL; +} +CAttachmentModelObject *CModelObject::GetAttachmentModelList( INDEX ipos, ...) +{ + va_list marker; + va_start(marker, ipos); + + CAttachmentModelObject *pamo = NULL; + CModelObject *pmo = this; + + // while not end of list + while(ipos>=0) { + // get attachment + pamo = pmo->GetAttachmentModel(ipos); + // if not found + if (pamo==NULL) { + // return failure + va_end(marker); + return NULL; + } + // get next attachment in list + pmo = &pamo->amo_moModelObject; + ipos = va_arg( marker, INDEX); + } + va_end(marker); + + // return current attachment + ASSERT(pamo!=NULL); + return pamo; +} + +void CModelObject::ResetAttachmentModelPosition( INDEX iAttachedPosition) +{ + FOREACHINLIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) + { + if (itamo->amo_iAttachedPosition == iAttachedPosition) + { + CModelData *pMD = (CModelData *) GetData(); + pMD->md_aampAttachedPosition.Lock(); + itamo->amo_plRelative = pMD->md_aampAttachedPosition[iAttachedPosition].amp_plRelativePlacement; + pMD->md_aampAttachedPosition.Unlock(); + return; + } + } +} + +void CModelObject::RemoveAttachmentModel( INDEX iAttachedPosition) +{ + FORDELETELIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) { + if (itamo->amo_iAttachedPosition == iAttachedPosition) { + itamo->amo_lnInMain.Remove(); + delete &*itamo; + return; + } + } +} + +void CModelObject::RemoveAllAttachmentModels(void) +{ + FORDELETELIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) { + itamo->amo_lnInMain.Remove(); + delete &*itamo; + } +} + +void CModelObject::StretchModel(const FLOAT3D &vStretch) +{ + mo_Stretch = vStretch; + FOREACHINLIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) { + itamo->amo_moModelObject.StretchModel(vStretch); + } +} + +void CModelObject::StretchModelRelative(const FLOAT3D &vStretch) +{ + mo_Stretch(1) *= vStretch(1); + mo_Stretch(2) *= vStretch(2); + mo_Stretch(3) *= vStretch(3); + FOREACHINLIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) { + itamo->amo_moModelObject.StretchModelRelative(vStretch); + } +} + +void CModelObject::StretchSingleModel(const FLOAT3D &vStretch) +{ + mo_Stretch = vStretch; +} + + +// get amount of memory used by this object +SLONG CModelObject::GetUsedMemory(void) +{ + // initial size + SLONG slUsedMemory = sizeof(CModelObject); + // add attachment(s) size + FOREACHINLIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itat) { + slUsedMemory += sizeof(CAttachmentModelObject) - sizeof(CModelObject); + itat->amo_moModelObject.GetUsedMemory(); + } + // done + return slUsedMemory; +} diff --git a/Sources/Engine/Models/Model.h b/Sources/Engine/Models/Model.h new file mode 100644 index 0000000..72a4be8 --- /dev/null +++ b/Sources/Engine/Models/Model.h @@ -0,0 +1,19 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// collision box dimension equality names +#define HEIGHT_EQ_WIDTH 0 +#define LENGTH_EQ_WIDTH 1 +#define LENGTH_EQ_HEIGHT 2 + +#define MAX_MODELMIPS 32 +#define MAX_TEXTUREPATCHES 32 +#define MAX_COLOR_NAMES 32 + +struct PolygonsPerPatch; +struct ModelPolygon; +struct ModelTextureVertex; +struct MappingSurface; +class CModelCollisionBox; +class CAttachedModelPosition; +class CRenderModel; +class CModelInfo; diff --git a/Sources/Engine/Models/ModelData.h b/Sources/Engine/Models/ModelData.h new file mode 100644 index 0000000..1be1d0f --- /dev/null +++ b/Sources/Engine/Models/ModelData.h @@ -0,0 +1,133 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_MODELDATA_H +#define SE_INCL_MODELDATA_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define MMI_OPAQUE (1L<<25) // entire mip model writes to z-buffer +#define MMI_TRANSLUCENT (1L<<26) // entire mip model doesn't write to z-buffer +// ! WARNING: to var that holds these flags is copied from surface flags which has reserved bits 20 and below ! + + +class ENGINE_API CModelPatch { +public: + CTString mp_strName; + CTextureObject mp_toTexture; + MEX2D mp_mexPosition; + FLOAT mp_fStretch; + + CModelPatch(void); + void Read_t( CTStream *strFile); // throw char * + void Write_t( CTStream *strFile); // throw char * +}; + +struct ENGINE_API ModelMipInfo +{ + ModelMipInfo(); // constructor + ~ModelMipInfo(); // destructor + INDEX mmpi_PolygonsCt; // how many polygons in this mip-model + ULONG mmpi_ulFlags; // flags for this mip model + CStaticArray mmpi_aPolygonsPerPatch; // for each patch info telling which polygons are occupied by that patch + CStaticArray mmpi_Polygons; // array of polygons + CStaticArray mmpi_TextureVertices; // with U,V and data for calculating U,V (for modeler) [???] + CStaticArray mmpi_MappingSurfaces; // with HPB, zoom, name of all surfaces + + // rendering info + INDEX mmpi_ctMipVx; + INDEX mmpi_ctSrfVx; // total number of surface vertices in this mip + CStaticArray mmpi_auwMipToMdl; // model vertices used in this mip + CStaticArray mmpi_auwSrfToMip; // surface vertices to mip vertices lookup + CStaticArray mmpi_avmexTexCoord; // texture coordinates for each surface vertex + CStaticArray mmpi_avBumpU; // bump directions for each surface vertex + CStaticArray mmpi_avBumpV; // bump directions for each surface vertex + ULONG mmpi_ulLayerFlags; // all texture layers needed in this mip + INDEX mmpi_ctTriangles; // total triangles in this mip + CStaticStackArray mmpi_aiElements; + + void Clear(); // clears this mip model's arays and their sub-arrays, dealocates memory + void Read_t( CTStream *istrFile, BOOL bReadPolygonalPatches, BOOL bReadPolygonsPerSurface, + BOOL bReadSurfaceColors); // throw char * + void Write_t( CTStream *ostrFile); // throw char * +}; + +class ENGINE_API CModelData : public CAnimData { +public: + INDEX md_VerticesCt; // number of vertices in model + INDEX md_FramesCt; // number of all frames used by this model + CStaticArray md_FrameVertices8; // all frames and all their vertices [FramesCt*VerticesCt] (8-bit) + CStaticArray md_FrameVertices16; // same but 16-bit + CStaticArray md_FrameInfos; // bounding box info [FramesCt] + CStaticArray md_MainMipVertices; // global array with coordinates of all vertices of main mip-model, used for creating mip-models [VerticesCt] + CStaticArray md_TransformedVertices; // buffer with i,j,k, rotated and stretched gouraud normal [VerticesCt] + CStaticArray md_VertexMipMask; // array of vertice masks telling in which mip model some vertex exists [VerticesCt] + INDEX md_MipCt; // number of mip-models + float md_MipSwitchFactors[MAX_MODELMIPS]; // array of mip factors determing where mip-models switch + struct ModelMipInfo md_MipInfos[MAX_MODELMIPS]; // contains how many polygons and which contains which vertices (different for each mip-model) + MEX md_Width, md_Height; // size of texture, used for checking validiti of surfaces + CModelPatch md_mpPatches[MAX_TEXTUREPATCHES]; // patches themselfs + CTString md_ColorNames[MAX_COLOR_NAMES]; // strings containing edited color names + ULONG md_Flags; // model flags (face froward, reflesction mapping) + SLONG md_ShadowQuality; // determines maximum shadow quality + FLOAT3D md_Stretch; // stretch vector (static one, dynamic one is in model object) + FLOAT3D md_vCenter; // center of object + FLOAT3D md_vCompressedCenter; // compressed (0-255) center of object (handle) + BOOL md_bHasAlpha; // set if any surface has alpha blending + // array of collision boxes for this model + CDynamicArray md_acbCollisionBox; + BOOL md_bCollideAsCube; // if model colide as stretched cube + CDynamicArray md_aampAttachedPosition; + BOOL md_bIsEdited; // set if model is part of CEditModel object + COLOR md_colDiffuse; + COLOR md_colReflections; + COLOR md_colSpecular; + COLOR md_colBump; + + BOOL md_bPreparedForRendering; // set if model is prepared for rendering +public: + CModelData(); + ~CModelData(); + DECLARE_NOCOPYING(CModelData); + + // reference counting (override from CAnimData) + void RemReference_internal(void); + + void PtrsToIndices(); + void IndicesToPtrs(); + void SpreadMipSwitchFactors( INDEX iFirst, float fStartingFactor); // spreads mip switch factors + void GetTextureDimensions( MEX &mexWidth, MEX &mexHeight); // riches texture dimensions + void GetAllFramesBBox( FLOATaabbox3D &MaxBB); // calculates all frame's bounding box + FLOAT3D GetCollisionBoxMin(INDEX iCollisionBox); + FLOAT3D GetCollisionBoxMax(INDEX iCollisionBox); + // returns HEIGHT_EQ_WIDTH, LENGTH_EQ_WIDTH or LENGTH_EQ_HEIGHT + INDEX GetCollisionBoxDimensionEquality(INDEX iCollisionBox); + ULONG GetFlags(void); + void Clear(void); + // check if this kind of objects is auto-freed + virtual BOOL IsAutoFreed(void); + + // get amount of memory used by this object + SLONG GetUsedMemory(void); + void ClearAnimations(void); + void LinkDataForSurfaces(BOOL bFirstMip);// calculate polygons and vertices for surface + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * + /* Get the description of this object. */ + CTString GetDescription(void); + +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Models/ModelObject.h b/Sources/Engine/Models/ModelObject.h new file mode 100644 index 0000000..f609065 --- /dev/null +++ b/Sources/Engine/Models/ModelObject.h @@ -0,0 +1,180 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_MODELOBJECT_H +#define SE_INCL_MODELOBJECT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include + +class CAttachmentModelObject; +class CRenderModel; +class CModelInfo; + +class ENGINE_API CModelObject : public CAnimObject { +private: + ULONG mo_PatchMask; // used to turn on/off texture patches (i.e. blood patches) + INDEX mo_iManualMipLevel; + BOOL mo_AutoMipModeling; + + // API version + void RenderModel_View( CRenderModel &rm); + void RenderPatches_View( CRenderModel &rm); + void AddSimpleShadow_View( CRenderModel &rm, const FLOAT fIntensity, const FLOATplane3D &plShadowPlane); + void RenderShadow_View( CRenderModel &rm, const CPlacement3D &plLight, + const FLOAT fFallOff, const FLOAT fHotSpot, const FLOAT fIntensity, + const FLOATplane3D &plShadowPlane); + // software version for drawing model mask + void RenderModel_Mask( CRenderModel &rm); + +public: + CTextureObject mo_toTexture; // texture used for model rendering + CTextureObject mo_toReflection; // texture used for reflection + CTextureObject mo_toSpecular; // texture used for specularity + CTextureObject mo_toBump; // texture used for bump + FLOAT3D mo_Stretch; // dynamic stretching vector, (usually 1,1,1) + ULONG mo_ColorMask; // mask telling what parts (colors) are visible + INDEX mo_iLastRenderMipLevel; // last rendered mip model index remembered + COLOR mo_colBlendColor; // dynamic blend color (alpha is applied) + CListHead mo_lhAttachments; // list of currently active attachment models + + CModelObject(void); // default constructor + ~CModelObject(void); // destructor + // copy from another object of same class + void Copy(CModelObject &moOther); + + MEX GetWidth(); // retrieves model's texture width + MEX GetHeight();// retrieves model's texture height + void GetModelInfo(CModelInfo &miInfo); // retrieves full model info + BOOL IsModelVisible(float fMipFactor); // is model visible for given mip factor + INDEX GetMipModel(float fMipFactor); // retrieves current mip model index + BOOL HasShadow(INDEX iModelMip); // test if model has shadow at given mip level + FLOATaabbox3D GetFrameBBox( INDEX iFrameNo); // retrieves bounding box of given frame + BOOL IsAutoMipModeling(); // TRUE if auto mip modeling is on + void AutoMipModelingOn(); // function starts auto mip modeling + void AutoMipModelingOff(); // function stops auto mip modeling + INDEX GetManualMipLevel(void); // retrieves current mip level + void SetManualMipLevel(INDEX iNewMipLevel); // sets given mip-level as current (auto mip modeling off) + void PrevManualMipLevel(); // sets previous mip-level (more precize) + void NextManualMipLevel(); // sets next mip-level (more rough) + void SetMipSwitchFactor(INDEX iMipLevel, float fMipFactor); // sets given mip-level's new switch factor + /* retrieves current frame's bounding box */ + void GetCurrentFrameBBox( FLOATaabbox3D &MaxBB); + /* retrieves bounding box of all frames */ + void GetAllFramesBBox( FLOATaabbox3D &MaxBB); + FLOAT3D GetCollisionBoxMin(INDEX iCollisionBox); + FLOAT3D GetCollisionBoxMax(INDEX iCollisionBox); + // test it the model has alpha blending + BOOL HasAlpha(void); + // returns HEIGHT_EQ_WIDTH, LENGTH_EQ_WIDTH or LENGTH_EQ_HEIGHT + INDEX GetCollisionBoxDimensionEquality(INDEX iCollisionBox); + // retrieves number of surfaces used in given mip model + INDEX SurfacesCt(INDEX iMipModel); + // retrieves number of polygons in given surface in given mip model + INDEX PolygonsInSurfaceCt(INDEX iMipModel, INDEX iSurface); + COLOR GetSurfaceColor( INDEX iCurrentMip, INDEX iCurrentSurface); // retrieves color of given surface + void SetSurfaceColor( INDEX iCurrentMip, INDEX iSurface, COLOR colNewColorAndAlpha); // changes color of given surface + void GetSurfaceRenderFlags( INDEX iCurrentMip, INDEX iCurrentSurface, + enum SurfaceShadingType &sstShading, enum SurfaceTranslucencyType &sttTranslucency, + ULONG &ulRenderingFlags); + void SetSurfaceRenderFlags( INDEX iCurrentMip, INDEX iCurrentSurface, + enum SurfaceShadingType sstShading, enum SurfaceTranslucencyType sttTranslucency, + ULONG ulRenderingFlags); + INDEX GetClosestPatch( MEX2D mexWanted, MEX2D &mexFound); // returns index and position of closest patch + CTString GetColorName( INDEX iColor); // retrieves name of color with given index + void SetColorName( INDEX iColor, CTString &strNewName); // sets new color name + + ULONG GetPatchesMask(); // this function returns current value of patches mask + void SetPatchesMask( ULONG new_patches_mask); // use this function to set new patches combination + + void UnpackVertex( CRenderModel &rm, const INDEX iVertex, FLOAT3D &vVertex); + BOOL CreateAttachment( CRenderModel &rmMain, CAttachmentModelObject &amo); + void ResetAttachmentModelPosition( INDEX iAttachedPosition); + CAttachmentModelObject *GetAttachmentModelList( INDEX iAttachedPosition, ...); + CAttachmentModelObject *GetAttachmentModel( INDEX iAttachedPosition); + CAttachmentModelObject *AddAttachmentModel( INDEX iAttachedPosition); + void RemoveAttachmentModel( INDEX iAttachedPosition); + void RemoveAllAttachmentModels(void); + void StretchModel( const FLOAT3D &vStretch); + // stretches model relative to current size + void StretchModelRelative(const FLOAT3D &vStretch); + // stretches the model without stretching its children + void StretchSingleModel(const FLOAT3D &vStretch); + + // model rendering + void SetupModelRendering( CRenderModel &rm); + void RenderModel( CRenderModel &rm); + void RenderPatches( CRenderModel &rm); + void AddSimpleShadow( CRenderModel &rm, const FLOAT fIntensity, const FLOATplane3D &plShadowPlane); + void RenderShadow( CRenderModel &rm, const CPlacement3D &plLight, + const FLOAT fFallOff, const FLOAT fHotSpot, const FLOAT fIntensity, + const FLOATplane3D &plShadowPlane); + + // Get model vertices in absoulte space + void GetModelVertices( CStaticStackArray &avVertices, FLOATmatrix3D &mRotation, + FLOAT3D &vPosition, FLOAT fNormalOffset, FLOAT fMipFactor); + void GetAttachmentMatrices( CAttachmentModelObject *pamo, FLOATmatrix3D &mRotation, FLOAT3D &vPosition); + void GetAttachmentTransformations( INDEX iAttachment, FLOATmatrix3D &mRotation, FLOAT3D &vPosition, BOOL bDummyAttachment); + + void ProjectFrameVertices( CProjection3D *pProjection, INDEX iMipModel); + void ColorizeRegion( CDrawPort *pDP, CProjection3D *projection, PIXaabbox2D box, + INDEX iChoosedColor, BOOL bOnColorMode); // colorizes polygons touching given box + void ColorizePolygon( CDrawPort *pDP, CProjection3D *projection, PIX x1, PIX y1, + INDEX iChoosedColor, BOOL bOnColorMode); // colorizes hitted polygon + void ApplySurfaceToPolygon( CDrawPort *pDP, CProjection3D *projection, PIX x1, PIX y1, + INDEX iSurface, COLOR colSurfaceColor); + void ApplySurfaceToPolygonsInRegion( CDrawPort *pDP, CProjection3D *projection, + PIXaabbox2D box, INDEX iSurface, COLOR colSurfaceColor); + void UnpackVertex( INDEX iFrame, INDEX iVertex, FLOAT3D &vVertex); + CPlacement3D GetAttachmentPlacement(CAttachmentModelObject &amo); + struct ModelPolygon *PolygonHit(CPlacement3D plRay, CPlacement3D plObject, + INDEX iCurrentMip, FLOAT &fHitDistance); // returns ptr to hitted polygon (NULL if none) + struct ModelPolygon *PolygonHitModelData( CModelData *pMD, CPlacement3D plRay, + CPlacement3D plObject, INDEX iCurrentMip, FLOAT &fHitDistance); + void PickPolyColor( CDrawPort *pDP, CProjection3D *projection, PIX x1, PIX y1, + INDEX &iPickedColorNo, BOOL bOnColorMode); // picks color from hitted polygon + INDEX PickPolySurface( CDrawPort *pDP, CProjection3D *projection, PIX x1, PIX y1); // picks surface from hitted polygon + INDEX PickVertexIndex( CDrawPort *pDP, CProjection3D *projection, PIX x1, PIX y1, FLOAT3D &vClosestVertex); // obtains index of closest vertex + + void ShowPatch( INDEX iMaskBit); + void HidePatch( INDEX iMaskBit); + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile);// throw char * + + // set texture data for main texture in surface of this model + void SetTextureData( CTextureData *ptdNewMainTexture); + CTFileName GetName(void); + void AutoSetTextures(void); + void AutoSetAttachments(void); + // obtain model and set it for this object + void SetData_t(const CTFileName &fnmModel); // throw char * + void SetData(CModelData *pmd); + CModelData *GetData(void); + + // synchronize with another model (copy animations/attachments positions etc from there) + void Synchronize(CModelObject &moOther); + + // get amount of memory used by this object + SLONG GetUsedMemory(void); +}; + + +class ENGINE_API CAttachmentModelObject { +public: + CListNode amo_lnInMain; + INDEX amo_iAttachedPosition; // indentifier of positions saved in model data + CPlacement3D amo_plRelative; // relative placement used for rendering + CModelObject amo_moModelObject; // model and texture + CRenderModel *amo_prm; // render model structure used in rendering +}; + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Models/ModelProfile.cpp b/Sources/Engine/Models/ModelProfile.cpp new file mode 100644 index 0000000..4140f74 --- /dev/null +++ b/Sources/Engine/Models/ModelProfile.cpp @@ -0,0 +1,94 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +// profile form for profiling models +CModelProfile mpModelProfile; +CProfileForm &_pfModelProfile = mpModelProfile; + +// override to provide external averaging from gfx profile +INDEX CModelProfile::GetAveragingCounter(void) +{ + return _pfGfxProfile.GetAveragingCounter(); +} + +CModelProfile::CModelProfile(void) + : CProfileForm ("Model", "frames", CModelProfile::PCI_COUNT, CModelProfile::PTI_COUNT) +{ + // initialize timers + SETTIMERNAME(PTI_INITMODELRENDERING, "InitModelRendering", "model"); + SETTIMERNAME(PTI_INITPROJECTION, " InitProjection", "model"); + SETTIMERNAME(PTI_INITSHADOWPROJECTION, " InitShadowprojection", "model"); + SETTIMERNAME(PTI_INITATTACHMENTS, " InitAttachments", "attachment"); + SETTIMERNAME(PTI_CREATEATTACHMENT, " CreateAttachment", "attachment"); + SETTIMERNAME(PTI_RENDERMODEL, "RenderModel", "model"); + SETTIMERNAME(PTI_RENDERSHADOW, "RenderShadow", "shadow"); + SETTIMERNAME(PTI_RENDERSIMPLESHADOW, "RenderSimpleShadow", "shadow"); + + SETTIMERNAME(PTI_VIEW_PREPAREFORRENDERING, "View_PrepareForRendering", ""); + SETTIMERNAME(PTI_VIEW_SETMODELVIEW, " View_SetModelView", "setting"); + SETTIMERNAME(PTI_VIEW_INIT_UNPACK, "View_Init_Unpack", "vertex"); + SETTIMERNAME(PTI_VIEW_INIT_VERTICES, "View_Init_Vertices", "vertex"); + SETTIMERNAME(PTI_VIEW_INIT_FOG_MIP, "View_Init_Fog_mip ", "vertex"); + SETTIMERNAME(PTI_VIEW_INIT_HAZE_MIP, "View_Init_Haze_mip ", "vertex"); + + SETTIMERNAME(PTI_VIEW_RENDERMODEL, "View_RenderModel", "model"); + SETTIMERNAME(PTI_VIEW_INIT_DIFF_SURF, " View_Init_Diff_surf", "vertex"); + SETTIMERNAME(PTI_VIEW_INIT_BUMP_SURF, " View_Init_Bump_surf", "vertex"); + SETTIMERNAME(PTI_VIEW_INIT_REFL_MIP , " View_Init_Refl_mip ", "vertex"); + SETTIMERNAME(PTI_VIEW_INIT_REFL_SURF, " View_Init_Refl_surf", "vertex"); + SETTIMERNAME(PTI_VIEW_INIT_SPEC_MIP, " View_Init_Spec_mip ", "vertex"); + SETTIMERNAME(PTI_VIEW_INIT_SPEC_SURF, " View_Init_Spec_surf", "vertex"); + SETTIMERNAME(PTI_VIEW_INIT_FOG_SURF, " View_Init_Fog_surf", "vertex"); + SETTIMERNAME(PTI_VIEW_INIT_HAZE_SURF, " View_Init_Haze_surf", "vertex"); + SETTIMERNAME(PTI_VIEW_ATTENUATE_SURF, " View_Attenuate_surf", "vertex"); + + SETTIMERNAME(PTI_VIEW_RENDER_DIFFUSE, " View_Render_Diffuse", "model"); + SETTIMERNAME(PTI_VIEW_RENDER_BUMP, " View_Render_Bump", "model"); + SETTIMERNAME(PTI_VIEW_RENDER_REFLECTIONS, " View_Render_Reflections", "model"); + SETTIMERNAME(PTI_VIEW_RENDER_SPECULAR, " View_Render_Specular", "model"); + SETTIMERNAME(PTI_VIEW_RENDER_FOG, " View_Render_Fog", "model"); + SETTIMERNAME(PTI_VIEW_RENDER_HAZE, " View_Render_Haze", "model"); + + SETTIMERNAME(PTI_VIEW_SETTEXTURE, "View_Settexture", "setting"); + SETTIMERNAME(PTI_VIEW_LOCKARRAYS, "View_Lockarrays", "vertex"); + SETTIMERNAME(PTI_VIEW_DRAWELEMENTS, "View_Drawelements", "triangle"); + SETTIMERNAME(PTI_VIEW_ONESIDE, "View_oneside", "side"); + SETTIMERNAME(PTI_VIEW_ONESIDE_GLSETUP, " View_oneside_glSetup", "setup"); + + SETTIMERNAME(PTI_VIEW_RENDERPATCHES, "View_Renderpatches", "model"); + SETTIMERNAME(PTI_VIEW_RENDERSHADOW, "View_Rendershadow", "shadow"); + SETTIMERNAME(PTI_VIEW_SHAD_INIT_MIP, " View_Shad_Init_mip", "vertex"); + SETTIMERNAME(PTI_VIEW_SHAD_INIT_SURF, " View_Shad_Init_surf", "vertex"); + SETTIMERNAME(PTI_VIEW_SHAD_GLSETUP , " View_Shad_glSetup", "shadow"); + SETTIMERNAME(PTI_VIEW_SHAD_RENDER , " View_Shad_Render", "triangle"); + SETTIMERNAME(PTI_VIEW_RENDERSIMPLESHADOW, "View_RenderSimpleShadow", "shadow"); + SETTIMERNAME(PTI_VIEW_SIMP_CALC, " View_Simp_calc", "shadow"); + SETTIMERNAME(PTI_VIEW_SIMP_PREP, " View_Simp_prep", "shadow"); + SETTIMERNAME(PTI_VIEW_SIMP_COPY , " View_Simp_copy", "shadow"); + SETTIMERNAME(PTI_VIEW_SIMP_BATCHED, " View_Simp_batched", "batch"); + + SETTIMERNAME(PTI_MASK_INITMODELRENDERING, "Mask_InitModelRendering", "model"); + SETTIMERNAME(PTI_MASK_RENDERMODEL, "Mask_RenderModel", "model"); + + // initialize counters + SETCOUNTERNAME(PCI_VERTICES_FIRSTMIP, "Vertices_firstmip"); + SETCOUNTERNAME(PCI_VERTICES_USEDMIP, "Vertices_usedmip"); + SETCOUNTERNAME(PCI_SURFACEVERTICES_FIRSTMIP, "SurfaceVertices_firstmip"); + SETCOUNTERNAME(PCI_SURFACEVERTICES_USEDMIP, "SurfaceVertices_usedmip"); + SETCOUNTERNAME(PCI_TRIANGLES_FIRSTMIP, "Triangles_firstmip"); + SETCOUNTERNAME(PCI_TRIANGLES_USEDMIP, "Triangles_usedmip"); + SETCOUNTERNAME(PCI_SHADOWVERTICES_FIRSTMIP, "ShadowVertices_firstmip"); + SETCOUNTERNAME(PCI_SHADOWVERTICES_USEDMIP, "ShadowvVrtices_usedmip"); + SETCOUNTERNAME(PCI_SHADOWSURFACEVERTICES_FIRSTMIP, "ShadowSurfaceVertices_firstmip"); + SETCOUNTERNAME(PCI_SHADOWSURFACEVERTICES_USEDMIP, "ShadowSurfaceVertices_usedmip"); + SETCOUNTERNAME(PCI_SHADOWTRIANGLES_FIRSTMIP, "ShadowTriangles_firstmip"); + SETCOUNTERNAME(PCI_SHADOWTRIANGLES_USEDMIP, "ShadowTriangles_usedmip"); + + SETCOUNTERNAME(PCI_VIEW_TRIANGLES, "View_Triangles"); + + SETCOUNTERNAME(PCI_MASK_TRIANGLES, "Mask_Triangles"); + SETCOUNTERNAME(PCI_MASK_POLYGONS, "Mask_Polygons"); +}; diff --git a/Sources/Engine/Models/ModelProfile.h b/Sources/Engine/Models/ModelProfile.h new file mode 100644 index 0000000..3ad0ca1 --- /dev/null +++ b/Sources/Engine/Models/ModelProfile.h @@ -0,0 +1,105 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_MODELPROFILE_H +#define SE_INCL_MODELPROFILE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* Class for holding profiling information for models. */ +class CModelProfile : public CProfileForm { +public: + // indices for profiling counters and timers + enum ProfileTimerIndex { + PTI_INITMODELRENDERING, + PTI_INITPROJECTION, + PTI_INITSHADOWPROJECTION, + PTI_INITATTACHMENTS, + PTI_CREATEATTACHMENT, + PTI_RENDERMODEL, + PTI_RENDERSHADOW, + PTI_RENDERSIMPLESHADOW, + + PTI_VIEW_PREPAREFORRENDERING, + PTI_VIEW_SETMODELVIEW, + PTI_VIEW_INIT_UNPACK, + PTI_VIEW_INIT_VERTICES, + PTI_VIEW_INIT_FOG_MIP, + PTI_VIEW_INIT_HAZE_MIP, + PTI_VIEW_RENDERMODEL, + PTI_VIEW_INIT_DIFF_SURF, + PTI_VIEW_INIT_BUMP_SURF, + PTI_VIEW_INIT_REFL_MIP , + PTI_VIEW_INIT_REFL_SURF, + PTI_VIEW_INIT_SPEC_MIP, + PTI_VIEW_INIT_SPEC_SURF, + PTI_VIEW_INIT_FOG_SURF, + PTI_VIEW_INIT_HAZE_SURF, + PTI_VIEW_ATTENUATE_SURF, + + PTI_VIEW_RENDER_DIFFUSE, + PTI_VIEW_RENDER_BUMP, + PTI_VIEW_RENDER_REFLECTIONS, + PTI_VIEW_RENDER_SPECULAR, + PTI_VIEW_RENDER_FOG, + PTI_VIEW_RENDER_HAZE, + + PTI_VIEW_SETTEXTURE, + PTI_VIEW_LOCKARRAYS, + PTI_VIEW_DRAWELEMENTS, + PTI_VIEW_ONESIDE, + PTI_VIEW_ONESIDE_GLSETUP, + + PTI_VIEW_RENDERSHADOW, + PTI_VIEW_SHAD_INIT_MIP, + PTI_VIEW_SHAD_INIT_SURF, + PTI_VIEW_SHAD_GLSETUP, + PTI_VIEW_SHAD_RENDER, + PTI_VIEW_RENDERSIMPLESHADOW, + PTI_VIEW_SIMP_CALC, + PTI_VIEW_SIMP_PREP, + PTI_VIEW_SIMP_COPY, + PTI_VIEW_SIMP_BATCHED, + + PTI_VIEW_RENDERPATCHES, + + PTI_MASK_INITMODELRENDERING, + PTI_MASK_RENDERMODEL, + + PTI_COUNT + }; + + enum ProfileCounterIndex { + + PCI_VERTICES_FIRSTMIP, + PCI_VERTICES_USEDMIP, + PCI_SURFACEVERTICES_FIRSTMIP, + PCI_SURFACEVERTICES_USEDMIP, + PCI_TRIANGLES_FIRSTMIP, + PCI_TRIANGLES_USEDMIP, + + PCI_SHADOWVERTICES_FIRSTMIP, + PCI_SHADOWVERTICES_USEDMIP, + PCI_SHADOWSURFACEVERTICES_FIRSTMIP, + PCI_SHADOWSURFACEVERTICES_USEDMIP, + PCI_SHADOWTRIANGLES_FIRSTMIP, + PCI_SHADOWTRIANGLES_USEDMIP, + + PCI_VIEW_TRIANGLES, + + PCI_MASK_TRIANGLES, + PCI_MASK_POLYGONS, + + PCI_COUNT + }; + // constructor + CModelProfile(void); + // override to provide external averaging from gfx profile + virtual INDEX GetAveragingCounter(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Models/Model_internal.h b/Sources/Engine/Models/Model_internal.h new file mode 100644 index 0000000..0954f07 --- /dev/null +++ b/Sources/Engine/Models/Model_internal.h @@ -0,0 +1,270 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_MODEL_INTERNAL_H +#define SE_INCL_MODEL_INTERNAL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +#define MODEL_VERSION_WITHOUT_STRETCH_CENTER "V002" +#define MODEL_VERSION_WITHOUT_MULTIPLE_COLLISION_BOXES "V003" +#define MODEL_VERSION_WITHOUT_ATTACHED_POSITIONS "V004" +#define MODEL_VERSION_WITHOUT_POLYGONAL_PATCHES "V005" +#define MODEL_VERSION_WITHOUT_POLYGONS_PER_SURFACE "V006" +#define MODEL_VERSION_WITHOUT_16_BIT_COMPRESSION "V007" +#define MODEL_VERSION_WITHOUT_REFLECTION_AND_SPECULARITY "V008" +#define MODEL_VERSION_WITHOUT_DIFFUSE_COLOR "V009" +#define MODEL_VERSION "V010" + + +// surface shading types +enum SurfaceShadingType { + SST_INVALID = -1, + SST_FULLBRIGHT = 0, + SST_MATTE = 1, + SST_FLAT = 2, +}; + +// surface translucency types +enum SurfaceTranslucencyType { + STT_INVALID = -1, + STT_OPAQUE = 0, + STT_TRANSLUCENT = 1, + STT_ALPHAGOURAUD = 2, // obsolete! + STT_ADD = 3, + STT_TRANSPARENT = 4, + STT_MULTIPLY = 5, +}; + +// surface rendering flags +#define SRF_DOUBLESIDED (1L<<0) // double sided polygons +#define SRF_CLIPPOLYGON (1L<<1) // polygons are allways cliped, this is old flag +#define SRF_REFLECTIONS (1L<<2) // use reflection mapping on this surface +#define SRF_INVISIBLE (1L<<3) // if this surface is ignored in rendering process +#define SRF_SPECULAR (1L<<4) // use specularity on this surface +#define SRF_DIFFUSE (1L<<5) // use difuse texture for this surface +#define SRF_BUMP (1L<<6) // use bump on this surface +#define SRF_NEW_TEXTURE_FORMAT (1L<<7) // used for reading of old mapping files (ther don't have diffuse flag set) +#define SRF_CYLINDRICAL_MAPPING (1L<<8) // surface is mapped using spherical mapping +#define SRF_SPHERICAL_MAPPING (1L<<9) // surface is mapped using cylindrical mapping +#define SRF_FOG (1L<<10) // used internally for fog +#define SRF_HAZE (1L<<11) // used internally for haze +#define SRF_DETAIL (1L<<12) // use detail on this surface instead of bump +#define SRF_SELECTED (1L<<13) // for editing purposes +#define SRF_OPAQUE (1L<<14) // writes to z-buffer +// ! WARNING: this flags are copied to mipinfo var flags which has reserved bits 25 and above ! + + +// constant used for spreading mip-switching distances +#define MAX_SWITCH_FACTOR 8.0f + +// render defines for model +#define RT_WIRE_ON ((1L) << 0) +#define RT_HIDDEN_LINES ((1L) << 1) +//------------------------------------- +#define RT_NO_POLYGON_FILL ((1L) << 2) +#define RT_WHITE_TEXTURE ((1L) << 3) +#define RT_SURFACE_COLORS ((1L) << 4) +#define RT_ON_COLORS ((1L) << 5) +#define RT_OFF_COLORS ((1L) << 6) +#define RT_TEXTURE ((1L) << 7) +//------------------------------------- +#define RT_SHADING_NONE ((1L) << 8) +#define RT_SHADING_LAMBERT ((1L) << 9) +#define RT_SHADING_PHONG ((1L) <<10) +//------------------------------------- +#define RT_SHADING_MASK (RT_SHADING_NONE | RT_SHADING_LAMBERT | RT_SHADING_PHONG) +#define RT_TEXTURE_MASK (RT_NO_POLYGON_FILL | RT_WHITE_TEXTURE | RT_SURFACE_COLORS | \ + RT_ON_COLORS | RT_OFF_COLORS | RT_TEXTURE) + +// Model flags +#define MF_FACE_FORWARD ((1L)<<0) +#define MF_REFLECTIONS ((1L)<<1) +#define MF_REFLECTIONS_HALF ((1L)<<2) +#define MF_HALF_FACE_FORWARD ((1L)<<3) +#define MF_COMPRESSED_16BIT ((1L)<<4) +#define MF_STRETCH_DETAIL ((1L)<<5) + +// Mip model flags +#define MM_PATCHES_VISIBLE ((1L)<<0) +#define MM_ATTACHED_MODELS_VISIBLE ((1L)<<1) + + +// colors used to represent on and off bits +ENGINE_API extern COLOR PaletteColorValues[]; + +typedef Vector SWPOINT3D; +typedef Vector SBPOINT3D; +typedef Vector MEX2D; + + +struct ENGINE_API ModelFrameVertex8 { + SBPOINT3D mfv_SBPoint; // 8-bit compressed vertex + UBYTE mfv_NormIndex; +}; + +struct ENGINE_API ModelFrameVertex16_old { + SWPOINT3D mfv_SWPoint; // 16-bit compressed vertex + UBYTE mfv_NormIndex; +}; + +struct ENGINE_API ModelFrameVertex16 { + SWPOINT3D mfv_SWPoint; // 16-bit compressed vertex + UBYTE mfv_ubNormH, mfv_ubNormP; +}; + +struct ENGINE_API ModelFrameInfo { + FLOATaabbox3D mfi_Box; // bounding box info for each frame +}; + +struct ENGINE_API ModelTextureVertex { + ModelTextureVertex(void); + FLOAT3D mtv_UVW; // 3D coordinate of one texture vertex + MEX2D mtv_UV; // U,V mapping coordinates + union { + BOOL mtv_Done; // flag used for mapping + INDEX mtv_iSurfaceVx; + }; + INDEX mtv_iTransformedVertex; + FLOAT3D mtv_vU, mtv_vV; // bump directions +}; + +struct ENGINE_API ModelPolygonVertex +{ + struct TransformedVertexData *mpv_ptvTransformedVertex; // buffer where vertices really rotate + struct ModelTextureVertex *mpv_ptvTextureVertex; // needed by modeler to calculate U,V + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * +}; + +#define SC_ALLWAYS_ON (1UL << 30) +#define SC_ALLWAYS_OFF (1UL << 31) + +struct ENGINE_API ModelPolygon +{ + ModelPolygon(); // constructor + ~ModelPolygon(); // destructor + CStaticArray mp_PolygonVertices; // this polygon's vertices + ULONG mp_RenderFlags; // flags which define rendering of this polygon + ULONG mp_ColorAndAlpha; // color and global alpha for this polygon + INDEX mp_Surface; // in which surface this polygon belongs + SLONG mp_slVisibility; // how this poligon is visible + BOOL mp_bClipped; // is polygon clipped + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * +}; + +struct ENGINE_API MappingSurface +{ + MappingSurface(); // constructor + ~MappingSurface(); // destructor + CTString ms_Name; // name of this surface + COLOR ms_colColor; // color of this surface + FLOAT3D ms_vSurface2DOffset; // center of this surface + FLOAT3D ms_HPB; // orientation of this surface + FLOAT ms_Zoom; // current zoom value + FLOAT3D ms_vSurfaceCenterOffset; // vector of surface center offseting + + COLOR ms_colDiffuse; // difuse color of this surface + COLOR ms_colReflections; // reflections color of this surface + COLOR ms_colSpecular; // specular color of this surface + COLOR ms_colBump; // bump color of this surface + + ULONG ms_ulOnColor; // on and off colors for surface + ULONG ms_ulOffColor; + + ULONG ms_ulRenderingFlags; // surface rendering flags + enum SurfaceShadingType ms_sstShadingType; // surface shading types + enum SurfaceTranslucencyType ms_sttTranslucencyType; // surface translucency types + CStaticArray ms_aiPolygons; // indices of all polygons in surface + CStaticArray ms_aiTextureVertices; // indices of all texture vertices in surface + + // rendering data + INDEX ms_iSrfVx0; // first surface vertex + INDEX ms_ctSrfVx; // number of surface vertices + INDEX ms_ctSrfEl; // number of surface elemtns + + BOOL operator==(const MappingSurface &msOther) const; + + // convert old polygon flags from CTGfx into new rendering parameters + void SetRenderingParameters(ULONG ulOldFlags); + void Read_t( CTStream *istrFile, BOOL bReadPolygonsPerSurface, BOOL bReadSurfaceColors); // throw char * + void Write_t( CTStream *ostrFile); // throw char * + void ReadSettings_t( CTStream *istrFile); // throw char * + void WriteSettings_t( CTStream *ostrFile); // throw char * +}; + + +// struct containing list of polygons that are touched by current patch +struct ENGINE_API PolygonsPerPatch +{ + CStaticArray ppp_iPolygons; // indices of polygons occupied by this patch + // rendering info + CStaticArray ppp_auwElements; // elements for drawing + inline ~PolygonsPerPatch() { Clear();}; + inline void Clear() { ppp_iPolygons.Clear();}; +}; + +/* rcg 10042001 removed anonymous structs, dangerous union. */ +struct ENGINE_API TransformedVertexData { + FLOAT3D tvd_TransformedPoint; // for transformed point vector + PolyVertex2D tvd_pv2; // vertex structure for software + FLOAT tvd_fX, tvd_fY, tvd_fZ; // view space original coords + FLOAT tvd_fU, tvd_fV; // texture mapping temp vars for clipping purposes + BOOL tvd_bClipped; // is clipped to near clip plane or screen boundaries? +}; + +class ENGINE_API CModelCollisionBox { +public: + FLOAT3D mcb_vCollisionBoxMin; // min vector of collision box + FLOAT3D mcb_vCollisionBoxMax; // max vector of collision box + ULONG mcb_iCollisionBoxDimensionEquality; // HEIGHT_EQ_WIDTH or LENGTH_EQ_WIDTH or LENGTH_EQ_HEIGHT + CTString mcb_strName; // name of collision box (exported as define) +// functions + CModelCollisionBox(void); + void Read_t(CTStream *istrFile); + void ReadName_t(CTStream *istrFile); + void Write_t(CTStream *ostrFile); + /* Clear the object. */ + inline void Clear(void) {}; +}; + +class ENGINE_API CAttachedModelPosition { +public: + CAttachedModelPosition(void); + INDEX amp_iCenterVertex; + INDEX amp_iFrontVertex; + INDEX amp_iUpVertex; + CPlacement3D amp_plRelativePlacement; + void Read_t( CTStream *strFile); // throw char * + void Write_t( CTStream *strFile); // throw char * + inline void Clear(void) {}; // clear the object. +}; + + +class ENGINE_API CMipInfo { +public: + INDEX mi_TrianglesCt; // how many triangles in this mip-model + INDEX mi_PolygonsCt; // how many polygons in this mip-model + INDEX mi_VerticesCt; // how many vertices in this mip-model +}; + +class ENGINE_API CModelInfo { +public: + INDEX mi_VerticesCt; // number of vertices in model + INDEX mi_FramesCt; // number of all frames used by this model + INDEX mi_MipCt; // number of mip-models + CMipInfo mi_MipInfos[MAX_MODELMIPS]; // contains count of polygons and vertices + CTFileName mi_PatchFiles[MAX_TEXTUREPATCHES]; // and their names + MEX mi_Width, mi_Height; // size of mapping texture + BOOL mi_Flags; // model flags (MF_...) + SLONG mi_ShadowQuality; // how models will be shaded + FLOAT3D mi_Stretch; // stretch vector (static one, dynamic one is in model object) +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Models/Normals.cpp b/Sources/Engine/Models/Normals.cpp new file mode 100644 index 0000000..71d833a --- /dev/null +++ b/Sources/Engine/Models/Normals.cpp @@ -0,0 +1,287 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +extern FLOAT3D avGouraudNormals[MAX_GOURAUDNORMALS] = { + FLOAT3D( 1.000000f, 0.000000f, 0.000000f), + FLOAT3D( 0.980785f, 0.000000f, 0.195090f), + FLOAT3D( 0.980785f, 0.195090f, 0.000000f), + FLOAT3D( 0.923880f, 0.000000f, 0.382683f), + FLOAT3D( 0.959683f, 0.198757f, 0.198757f), + FLOAT3D( 0.923880f, 0.382683f, 0.000000f), + FLOAT3D( 0.831470f, 0.000000f, 0.555570f), + FLOAT3D( 0.890320f, 0.208847f, 0.404615f), + FLOAT3D( 0.707107f, 0.000000f, 0.707107f), + FLOAT3D( 0.788675f, 0.211325f, 0.577350f), + FLOAT3D( 0.816497f, 0.408248f, 0.408248f), + FLOAT3D( 0.831470f, 0.555570f, 0.000000f), + FLOAT3D( 0.788675f, 0.577350f, 0.211325f), + FLOAT3D( 0.707107f, 0.707107f, 0.000000f), + FLOAT3D( 0.555570f, 0.000000f, 0.831470f), + FLOAT3D( 0.577350f, 0.211325f, 0.788675f), + FLOAT3D( 0.382683f, 0.000000f, 0.923880f), + FLOAT3D( 0.404615f, 0.208847f, 0.890320f), + FLOAT3D( 0.408248f, 0.408248f, 0.816497f), + FLOAT3D( 0.195090f, 0.000000f, 0.980785f), + FLOAT3D( 0.198757f, 0.198757f, 0.959683f), + FLOAT3D( 0.000000f, 0.000000f, 1.000000f), + FLOAT3D( 0.000000f, 0.195090f, 0.980785f), + FLOAT3D( 0.000000f, 0.382683f, 0.923880f), + FLOAT3D( 0.208847f, 0.404615f, 0.890320f), + FLOAT3D( 0.211325f, 0.577350f, 0.788675f), + FLOAT3D( 0.000000f, 0.555570f, 0.831470f), + FLOAT3D( 0.000000f, 0.707107f, 0.707107f), + FLOAT3D( 0.577350f, 0.788675f, 0.211325f), + FLOAT3D( 0.639602f, 0.639602f, 0.426401f), + FLOAT3D( 0.408248f, 0.816497f, 0.408248f), + FLOAT3D( 0.639602f, 0.426401f, 0.639602f), + FLOAT3D( 0.426401f, 0.639602f, 0.639602f), + FLOAT3D( 0.211325f, 0.788675f, 0.577350f), + FLOAT3D( 0.555570f, 0.831470f, 0.000000f), + FLOAT3D( 0.404615f, 0.890320f, 0.208847f), + FLOAT3D( 0.382683f, 0.923880f, 0.000000f), + FLOAT3D( 0.208847f, 0.890320f, 0.404615f), + FLOAT3D( 0.000000f, 0.831470f, 0.555570f), + FLOAT3D( 0.000000f, 0.923880f, 0.382683f), + FLOAT3D( 0.198757f, 0.959683f, 0.198757f), + FLOAT3D( 0.195090f, 0.980785f, 0.000000f), + FLOAT3D( 0.000000f, 0.980785f, 0.195090f), + FLOAT3D( 0.000000f, 1.000000f, 0.000000f), + FLOAT3D( -0.195090f, 0.980785f, 0.000000f), + FLOAT3D( -0.198757f, 0.959683f, 0.198757f), + FLOAT3D( -0.382683f, 0.923880f, 0.000000f), + FLOAT3D( -0.208847f, 0.890320f, 0.404615f), + FLOAT3D( -0.211325f, 0.788675f, 0.577350f), + FLOAT3D( -0.408248f, 0.816497f, 0.408248f), + FLOAT3D( -0.404615f, 0.890320f, 0.208847f), + FLOAT3D( -0.555570f, 0.831470f, 0.000000f), + FLOAT3D( -0.577350f, 0.788675f, 0.211325f), + FLOAT3D( -0.707107f, 0.707107f, 0.000000f), + FLOAT3D( -0.211325f, 0.577350f, 0.788675f), + FLOAT3D( -0.208847f, 0.404615f, 0.890320f), + FLOAT3D( -0.408248f, 0.408248f, 0.816497f), + FLOAT3D( -0.198757f, 0.198757f, 0.959683f), + FLOAT3D( -0.195090f, 0.000000f, 0.980785f), + FLOAT3D( -0.382683f, 0.000000f, 0.923880f), + FLOAT3D( -0.404615f, 0.208847f, 0.890320f), + FLOAT3D( -0.577350f, 0.211325f, 0.788675f), + FLOAT3D( -0.555570f, 0.000000f, 0.831470f), + FLOAT3D( -0.707107f, 0.000000f, 0.707107f), + FLOAT3D( -0.788675f, 0.577350f, 0.211325f), + FLOAT3D( -0.639602f, 0.639602f, 0.426401f), + FLOAT3D( -0.816497f, 0.408248f, 0.408248f), + FLOAT3D( -0.426401f, 0.639602f, 0.639602f), + FLOAT3D( -0.639602f, 0.426401f, 0.639602f), + FLOAT3D( -0.788675f, 0.211325f, 0.577350f), + FLOAT3D( -0.831470f, 0.555570f, 0.000000f), + FLOAT3D( -0.890320f, 0.404615f, 0.208847f), + FLOAT3D( -0.923880f, 0.382683f, 0.000000f), + FLOAT3D( -0.890320f, 0.208847f, 0.404615f), + FLOAT3D( -0.831470f, 0.000000f, 0.555570f), + FLOAT3D( -0.923880f, 0.000000f, 0.382683f), + FLOAT3D( -0.959683f, 0.198757f, 0.198757f), + FLOAT3D( -0.980785f, 0.195090f, 0.000000f), + FLOAT3D( -0.980785f, 0.000000f, 0.195090f), + FLOAT3D( -1.000000f, 0.000000f, 0.000000f), + FLOAT3D( -0.980785f, -0.195090f, 0.000000f), + FLOAT3D( -0.959683f, -0.198757f, 0.198757f), + FLOAT3D( -0.923880f, -0.382683f, 0.000000f), + FLOAT3D( -0.890320f, -0.208847f, 0.404615f), + FLOAT3D( -0.788675f, -0.211325f, 0.577350f), + FLOAT3D( -0.816497f, -0.408248f, 0.408248f), + FLOAT3D( -0.890320f, -0.404615f, 0.208847f), + FLOAT3D( -0.831470f, -0.555570f, 0.000000f), + FLOAT3D( -0.788675f, -0.577350f, 0.211325f), + FLOAT3D( -0.707107f, -0.707107f, 0.000000f), + FLOAT3D( -0.577350f, -0.211325f, 0.788675f), + FLOAT3D( -0.404615f, -0.208847f, 0.890320f), + FLOAT3D( -0.408248f, -0.408248f, 0.816497f), + FLOAT3D( -0.198757f, -0.198757f, 0.959683f), + FLOAT3D( 0.000000f, -0.195090f, 0.980785f), + FLOAT3D( 0.000000f, -0.382683f, 0.923880f), + FLOAT3D( -0.208847f, -0.404615f, 0.890320f), + FLOAT3D( -0.211325f, -0.577350f, 0.788675f), + FLOAT3D( 0.000000f, -0.555570f, 0.831470f), + FLOAT3D( 0.000000f, -0.707107f, 0.707107f), + FLOAT3D( -0.577350f, -0.788675f, 0.211325f), + FLOAT3D( -0.639602f, -0.639602f, 0.426401f), + FLOAT3D( -0.408248f, -0.816497f, 0.408248f), + FLOAT3D( -0.639602f, -0.426401f, 0.639602f), + FLOAT3D( -0.426401f, -0.639602f, 0.639602f), + FLOAT3D( -0.211325f, -0.788675f, 0.577350f), + FLOAT3D( -0.555570f, -0.831470f, 0.000000f), + FLOAT3D( -0.404615f, -0.890320f, 0.208847f), + FLOAT3D( -0.382683f, -0.923880f, 0.000000f), + FLOAT3D( -0.208847f, -0.890320f, 0.404615f), + FLOAT3D( 0.000000f, -0.831470f, 0.555570f), + FLOAT3D( 0.000000f, -0.923880f, 0.382683f), + FLOAT3D( -0.198757f, -0.959683f, 0.198757f), + FLOAT3D( -0.195090f, -0.980785f, 0.000000f), + FLOAT3D( 0.000000f, -0.980785f, 0.195090f), + FLOAT3D( 0.000000f, -1.000000f, 0.000000f), + FLOAT3D( 0.195090f, -0.980785f, 0.000000f), + FLOAT3D( 0.198757f, -0.959683f, 0.198757f), + FLOAT3D( 0.382683f, -0.923880f, 0.000000f), + FLOAT3D( 0.208847f, -0.890320f, 0.404615f), + FLOAT3D( 0.211325f, -0.788675f, 0.577350f), + FLOAT3D( 0.408248f, -0.816497f, 0.408248f), + FLOAT3D( 0.404615f, -0.890320f, 0.208847f), + FLOAT3D( 0.555570f, -0.831470f, 0.000000f), + FLOAT3D( 0.577350f, -0.788675f, 0.211325f), + FLOAT3D( 0.707107f, -0.707107f, 0.000000f), + FLOAT3D( 0.211325f, -0.577350f, 0.788675f), + FLOAT3D( 0.208847f, -0.404615f, 0.890320f), + FLOAT3D( 0.408248f, -0.408248f, 0.816497f), + FLOAT3D( 0.198757f, -0.198757f, 0.959683f), + FLOAT3D( 0.404615f, -0.208847f, 0.890320f), + FLOAT3D( 0.577350f, -0.211325f, 0.788675f), + FLOAT3D( 0.788675f, -0.577350f, 0.211325f), + FLOAT3D( 0.639602f, -0.639602f, 0.426401f), + FLOAT3D( 0.816497f, -0.408248f, 0.408248f), + FLOAT3D( 0.426401f, -0.639602f, 0.639602f), + FLOAT3D( 0.639602f, -0.426401f, 0.639602f), + FLOAT3D( 0.788675f, -0.211325f, 0.577350f), + FLOAT3D( 0.831470f, -0.555570f, 0.000000f), + FLOAT3D( 0.890320f, -0.404615f, 0.208847f), + FLOAT3D( 0.923880f, -0.382683f, 0.000000f), + FLOAT3D( 0.890320f, -0.208847f, 0.404615f), + FLOAT3D( 0.959683f, -0.198757f, 0.198757f), + FLOAT3D( 0.980785f, -0.195090f, 0.000000f), + FLOAT3D( 0.980785f, 0.000000f, -0.195090f), + FLOAT3D( 0.959683f, 0.198757f, -0.198757f), + FLOAT3D( 0.923880f, 0.000000f, -0.382683f), + FLOAT3D( 0.890320f, 0.404615f, -0.208847f), + FLOAT3D( 0.788675f, 0.577350f, -0.211325f), + FLOAT3D( 0.816497f, 0.408248f, -0.408248f), + FLOAT3D( 0.890320f, 0.208847f, -0.404615f), + FLOAT3D( 0.831470f, 0.000000f, -0.555570f), + FLOAT3D( 0.788675f, 0.211325f, -0.577350f), + FLOAT3D( 0.707107f, 0.000000f, -0.707107f), + FLOAT3D( 0.577350f, 0.788675f, -0.211325f), + FLOAT3D( 0.404615f, 0.890320f, -0.208847f), + FLOAT3D( 0.408248f, 0.816497f, -0.408248f), + FLOAT3D( 0.198757f, 0.959683f, -0.198757f), + FLOAT3D( 0.000000f, 0.923880f, -0.382683f), + FLOAT3D( 0.208847f, 0.890320f, -0.404615f), + FLOAT3D( 0.211325f, 0.788675f, -0.577350f), + FLOAT3D( 0.000000f, 0.831470f, -0.555570f), + FLOAT3D( 0.000000f, 0.707107f, -0.707107f), + FLOAT3D( 0.577350f, 0.211325f, -0.788675f), + FLOAT3D( 0.639602f, 0.426401f, -0.639602f), + FLOAT3D( 0.408248f, 0.408248f, -0.816497f), + FLOAT3D( 0.639602f, 0.639602f, -0.426401f), + FLOAT3D( 0.426401f, 0.639602f, -0.639602f), + FLOAT3D( 0.211325f, 0.577350f, -0.788675f), + FLOAT3D( 0.555570f, 0.000000f, -0.831470f), + FLOAT3D( 0.404615f, 0.208847f, -0.890320f), + FLOAT3D( 0.382683f, 0.000000f, -0.923880f), + FLOAT3D( 0.208847f, 0.404615f, -0.890320f), + FLOAT3D( 0.000000f, 0.555570f, -0.831470f), + FLOAT3D( 0.000000f, 0.382683f, -0.923880f), + FLOAT3D( 0.198757f, 0.198757f, -0.959683f), + FLOAT3D( 0.195090f, 0.000000f, -0.980785f), + FLOAT3D( 0.000000f, 0.195090f, -0.980785f), + FLOAT3D( 0.000000f, 0.000000f, -1.000000f), + FLOAT3D( -0.198757f, 0.959683f, -0.198757f), + FLOAT3D( -0.404615f, 0.890320f, -0.208847f), + FLOAT3D( -0.577350f, 0.788675f, -0.211325f), + FLOAT3D( -0.408248f, 0.816497f, -0.408248f), + FLOAT3D( -0.208847f, 0.890320f, -0.404615f), + FLOAT3D( -0.211325f, 0.788675f, -0.577350f), + FLOAT3D( -0.788675f, 0.577350f, -0.211325f), + FLOAT3D( -0.890320f, 0.404615f, -0.208847f), + FLOAT3D( -0.816497f, 0.408248f, -0.408248f), + FLOAT3D( -0.959683f, 0.198757f, -0.198757f), + FLOAT3D( -0.980785f, 0.000000f, -0.195090f), + FLOAT3D( -0.923880f, 0.000000f, -0.382683f), + FLOAT3D( -0.890320f, 0.208847f, -0.404615f), + FLOAT3D( -0.788675f, 0.211325f, -0.577350f), + FLOAT3D( -0.831470f, 0.000000f, -0.555570f), + FLOAT3D( -0.707107f, 0.000000f, -0.707107f), + FLOAT3D( -0.211325f, 0.577350f, -0.788675f), + FLOAT3D( -0.426401f, 0.639602f, -0.639602f), + FLOAT3D( -0.408248f, 0.408248f, -0.816497f), + FLOAT3D( -0.639602f, 0.639602f, -0.426401f), + FLOAT3D( -0.639602f, 0.426401f, -0.639602f), + FLOAT3D( -0.577350f, 0.211325f, -0.788675f), + FLOAT3D( -0.208847f, 0.404615f, -0.890320f), + FLOAT3D( -0.404615f, 0.208847f, -0.890320f), + FLOAT3D( -0.555570f, 0.000000f, -0.831470f), + FLOAT3D( -0.382683f, 0.000000f, -0.923880f), + FLOAT3D( -0.198757f, 0.198757f, -0.959683f), + FLOAT3D( -0.195090f, 0.000000f, -0.980785f), + FLOAT3D( -0.959683f, -0.198757f, -0.198757f), + FLOAT3D( -0.890320f, -0.404615f, -0.208847f), + FLOAT3D( -0.788675f, -0.577350f, -0.211325f), + FLOAT3D( -0.816497f, -0.408248f, -0.408248f), + FLOAT3D( -0.890320f, -0.208847f, -0.404615f), + FLOAT3D( -0.788675f, -0.211325f, -0.577350f), + FLOAT3D( -0.577350f, -0.788675f, -0.211325f), + FLOAT3D( -0.404615f, -0.890320f, -0.208847f), + FLOAT3D( -0.408248f, -0.816497f, -0.408248f), + FLOAT3D( -0.198757f, -0.959683f, -0.198757f), + FLOAT3D( 0.000000f, -0.980785f, -0.195090f), + FLOAT3D( 0.000000f, -0.923880f, -0.382683f), + FLOAT3D( -0.208847f, -0.890320f, -0.404615f), + FLOAT3D( -0.211325f, -0.788675f, -0.577350f), + FLOAT3D( 0.000000f, -0.831470f, -0.555570f), + FLOAT3D( 0.000000f, -0.707107f, -0.707107f), + FLOAT3D( -0.577350f, -0.211325f, -0.788675f), + FLOAT3D( -0.639602f, -0.426401f, -0.639602f), + FLOAT3D( -0.408248f, -0.408248f, -0.816497f), + FLOAT3D( -0.639602f, -0.639602f, -0.426401f), + FLOAT3D( -0.426401f, -0.639602f, -0.639602f), + FLOAT3D( -0.211325f, -0.577350f, -0.788675f), + FLOAT3D( -0.404615f, -0.208847f, -0.890320f), + FLOAT3D( -0.208847f, -0.404615f, -0.890320f), + FLOAT3D( 0.000000f, -0.555570f, -0.831470f), + FLOAT3D( 0.000000f, -0.382683f, -0.923880f), + FLOAT3D( -0.198757f, -0.198757f, -0.959683f), + FLOAT3D( 0.000000f, -0.195090f, -0.980785f), + FLOAT3D( 0.198757f, -0.959683f, -0.198757f), + FLOAT3D( 0.404615f, -0.890320f, -0.208847f), + FLOAT3D( 0.577350f, -0.788675f, -0.211325f), + FLOAT3D( 0.408248f, -0.816497f, -0.408248f), + FLOAT3D( 0.208847f, -0.890320f, -0.404615f), + FLOAT3D( 0.211325f, -0.788675f, -0.577350f), + FLOAT3D( 0.788675f, -0.577350f, -0.211325f), + FLOAT3D( 0.890320f, -0.404615f, -0.208847f), + FLOAT3D( 0.816497f, -0.408248f, -0.408248f), + FLOAT3D( 0.959683f, -0.198757f, -0.198757f), + FLOAT3D( 0.890320f, -0.208847f, -0.404615f), + FLOAT3D( 0.788675f, -0.211325f, -0.577350f), + FLOAT3D( 0.211325f, -0.577350f, -0.788675f), + FLOAT3D( 0.426401f, -0.639602f, -0.639602f), + FLOAT3D( 0.408248f, -0.408248f, -0.816497f), + FLOAT3D( 0.639602f, -0.639602f, -0.426401f), + FLOAT3D( 0.639602f, -0.426401f, -0.639602f), + FLOAT3D( 0.577350f, -0.211325f, -0.788675f), + FLOAT3D( 0.208847f, -0.404615f, -0.890320f), + FLOAT3D( 0.404615f, -0.208847f, -0.890320f), + FLOAT3D( 0.198757f, -0.198757f, -0.959683f), +}; + + +/* Find nearest Gouraud normal for a vector. */ +INDEX GouraudNormal( const FLOAT3D &vNormal) +{ + INDEX i, besti; + FLOAT p, bestp; + // find the Gouraud normal that makes smallest dot product with given vector + besti = 0; + bestp = 0.0f; + for( i=0; ibestp) { + bestp = p; + besti = i; + } + } + return besti; +} + + + diff --git a/Sources/Engine/Models/Normals.h b/Sources/Engine/Models/Normals.h new file mode 100644 index 0000000..58a362b --- /dev/null +++ b/Sources/Engine/Models/Normals.h @@ -0,0 +1,19 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_NORMALS_H +#define SE_INCL_NORMALS_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#define MAX_GOURAUDNORMALS 256 +extern FLOAT3D avGouraudNormals[MAX_GOURAUDNORMALS]; + +/* Find nearest Gouraud normal for a vector. */ +INDEX GouraudNormal( const FLOAT3D &vNormal); +void CompressNormal_HQ( const FLOAT3D &vNormal, UBYTE &ubH, UBYTE &ubP); +void DecompressNormal_HQ( FLOAT3D &vNormal, UBYTE ubH, UBYTE ubP); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Models/RenderModel.cpp b/Sources/Engine/Models/RenderModel.cpp new file mode 100644 index 0000000..f5fc0ea --- /dev/null +++ b/Sources/Engine/Models/RenderModel.cpp @@ -0,0 +1,680 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +CStaticStackArray _armRenderModels; + + +// texture used for simple model shadows +CTextureObject _toSimpleModelShadow; + +static INDEX _iRenderingType = 0; // 0=none, 1=view, 2=mask + +extern FLOAT mdl_fLODMul; +extern FLOAT mdl_fLODAdd; +extern INDEX mdl_iShadowQuality; + +CAnyProjection3D _aprProjection; +CDrawPort *_pdp = NULL; +UBYTE *_pubMask = NULL; +SLONG _slMaskWidth = 0; +SLONG _slMaskHeight = 0; +static enum FPUPrecisionType _fpuOldPrecision; + + +// begin/end model rendering to screen +void BeginModelRenderingView( CAnyProjection3D &prProjection, CDrawPort *pdp) +{ + ASSERT( _iRenderingType==0 && _pdp==NULL); + + // set 3D projection + _iRenderingType = 1; + _pdp = pdp; + prProjection->ObjectPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + prProjection->Prepare(); + // in case of mirror projection, move mirror clip plane a bit father from the mirrored models, + // so we have less clipping (for instance, player feet) + if( prProjection->pr_bMirror) prProjection->pr_plMirrorView.pl_distance -= 0.06f; // -0.06 is because entire projection is offseted by +0.05 + _aprProjection = prProjection; + _pdp->SetProjection( _aprProjection); + // make FPU precision low + _fpuOldPrecision = GetFPUPrecision(); + SetFPUPrecision(FPT_24BIT); + + // prepare common arrays for simple shadows rendering + _avtxCommon.PopAll(); + _atexCommon.PopAll(); + _acolCommon.PopAll(); + + // eventually setup truform + extern INDEX gap_bForceTruform; + extern INDEX ogl_bTruformLinearNormals; + if( ogl_bTruformLinearNormals) ogl_bTruformLinearNormals = 1; + if( gap_bForceTruform) { + gap_bForceTruform = 1; + gfxSetTruform( _pGfx->gl_iTessellationLevel, ogl_bTruformLinearNormals); + } +} + + +void EndModelRenderingView( BOOL bRestoreOrtho/*=TRUE*/) +{ + ASSERT( _iRenderingType==1 && _pdp!=NULL); + // assure that FPU precision was low all the model rendering time, then revert to old FPU precision + ASSERT( GetFPUPrecision()==FPT_24BIT); + SetFPUPrecision(_fpuOldPrecision); + // restore front face direction + gfxFrontFace(GFX_CCW); + // render all batched shadows + extern void RenderBatchedSimpleShadows_View(void); + RenderBatchedSimpleShadows_View(); + // back to 2D projection? + if( bRestoreOrtho) _pdp->SetOrtho(); + _iRenderingType = 0; + _pdp = NULL; + // eventually disable re-enable clipping + gfxEnableClipping(); + if( _aprProjection->pr_bMirror || _aprProjection->pr_bWarp) gfxEnableClipPlane(); +} + + + +// begin/end model rendering to shadow mask +void BeginModelRenderingMask( CAnyProjection3D &prProjection, UBYTE *pubMask, SLONG slMaskWidth, SLONG slMaskHeight) +{ + ASSERT( _iRenderingType==0); + _iRenderingType = 2; + _aprProjection = prProjection; + _pubMask = pubMask; + _slMaskWidth = slMaskWidth; + _slMaskHeight = slMaskHeight; +} + +void EndModelRenderingMask(void) +{ + ASSERT( _iRenderingType==2); + _iRenderingType = 0; +} + + + + +// calculate models bounding box (needed for simple shadows and trivial rejection of in-fog/haze-case) +static void CalculateBoundingBox( CModelObject *pmo, CRenderModel &rm) +{ + if( rm.rm_ulFlags & RMF_BBOXSET) return; + // get model's data and lerp info + rm.rm_pmdModelData = (CModelData*)pmo->GetData(); + pmo->GetFrame( rm.rm_iFrame0, rm.rm_iFrame1, rm.rm_fRatio); + // calculate projection model bounding box in object space + const FLOAT3D &vMin0 = rm.rm_pmdModelData->md_FrameInfos[rm.rm_iFrame0].mfi_Box.Min(); + const FLOAT3D &vMax0 = rm.rm_pmdModelData->md_FrameInfos[rm.rm_iFrame0].mfi_Box.Max(); + const FLOAT3D &vMin1 = rm.rm_pmdModelData->md_FrameInfos[rm.rm_iFrame1].mfi_Box.Min(); + const FLOAT3D &vMax1 = rm.rm_pmdModelData->md_FrameInfos[rm.rm_iFrame1].mfi_Box.Max(); + rm.rm_vObjectMinBB = Lerp( vMin0, vMin1, rm.rm_fRatio); + rm.rm_vObjectMaxBB = Lerp( vMax0, vMax1, rm.rm_fRatio); + rm.rm_vObjectMinBB(1) *= pmo->mo_Stretch(1); rm.rm_vObjectMaxBB(1) *= pmo->mo_Stretch(1); + rm.rm_vObjectMinBB(2) *= pmo->mo_Stretch(2); rm.rm_vObjectMaxBB(2) *= pmo->mo_Stretch(2); + rm.rm_vObjectMinBB(3) *= pmo->mo_Stretch(3); rm.rm_vObjectMaxBB(3) *= pmo->mo_Stretch(3); + rm.rm_ulFlags |= RMF_BBOXSET; +} + + + + +CRenderModel::CRenderModel(void) +{ + rm_ulFlags = 0; + rm_colBlend = C_WHITE|0xFF; + (INDEX&)rm_fDistanceFactor = 12345678; // mip factor readjustment needed + rm_iTesselationLevel = 0; +} + + +CRenderModel::~CRenderModel(void) +{ + if( !(rm_ulFlags&RMF_ATTACHMENT)) _armRenderModels.PopAll(); +} + + +// set placement of the object +void CRenderModel::SetObjectPlacement( const CPlacement3D &pl) +{ + rm_vObjectPosition = pl.pl_PositionVector; + MakeRotationMatrixFast( rm_mObjectRotation, pl.pl_OrientationAngle); +} + +void CRenderModel::SetObjectPlacement( const FLOAT3D &v, const FLOATmatrix3D &m) +{ + rm_vObjectPosition = v; + rm_mObjectRotation = m; +} + + +// set modelview matrix if not already set +void CRenderModel::SetModelView(void) +{ + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_SETMODELVIEW); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_SETMODELVIEW); + + // adjust clipping to frustum + if( rm_ulFlags & RMF_INSIDE) gfxDisableClipping(); + else gfxEnableClipping(); + + // adjust clipping to mirror-plane (if any) + extern INDEX gap_iOptimizeClipping; + if( gap_iOptimizeClipping>0 && (_aprProjection->pr_bMirror || _aprProjection->pr_bWarp)) { + if( rm_ulFlags & RMF_INMIRROR) gfxDisableClipPlane(); + else gfxEnableClipPlane(); + } + + // make transform matrix + const FLOATmatrix3D &m = rm_mObjectToView; + const FLOAT3D &v = rm_vObjectToView; + FLOAT glm[16]; + glm[0] = m(1,1); glm[4] = m(1,2); glm[ 8] = m(1,3); glm[12] = v(1); + glm[1] = m(2,1); glm[5] = m(2,2); glm[ 9] = m(2,3); glm[13] = v(2); + glm[2] = m(3,1); glm[6] = m(3,2); glm[10] = m(3,3); glm[14] = v(3); + glm[3] = 0; glm[7] = 0; glm[11] = 0; glm[15] = 1; + gfxSetViewMatrix(glm); + + // all done + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_SETMODELVIEW); +} + + + +// transform a vertex in model with lerping +void CModelObject::UnpackVertex( CRenderModel &rm, const INDEX iVertex, FLOAT3D &vVertex) +{ + if( ((CModelData*)GetData())->md_Flags & MF_COMPRESSED_16BIT) { + // get 16 bit packed vertices + const SWPOINT3D &vsw0 = rm.rm_pFrame16_0[iVertex].mfv_SWPoint; + const SWPOINT3D &vsw1 = rm.rm_pFrame16_1[iVertex].mfv_SWPoint; + // convert them to float and lerp between them + vVertex(1) = (Lerp( (FLOAT)vsw0(1), (FLOAT)vsw1(1), rm.rm_fRatio) -rm.rm_vOffset(1)) * rm.rm_vStretch(1); + vVertex(2) = (Lerp( (FLOAT)vsw0(2), (FLOAT)vsw1(2), rm.rm_fRatio) -rm.rm_vOffset(2)) * rm.rm_vStretch(2); + vVertex(3) = (Lerp( (FLOAT)vsw0(3), (FLOAT)vsw1(3), rm.rm_fRatio) -rm.rm_vOffset(3)) * rm.rm_vStretch(3); + } else { + // get 8 bit packed vertices + const SBPOINT3D &vsb0 = rm.rm_pFrame8_0[iVertex].mfv_SBPoint; + const SBPOINT3D &vsb1 = rm.rm_pFrame8_1[iVertex].mfv_SBPoint; + // convert them to float and lerp between them + vVertex(1) = (Lerp( (FLOAT)vsb0(1), (FLOAT)vsb1(1), rm.rm_fRatio) -rm.rm_vOffset(1)) * rm.rm_vStretch(1); + vVertex(2) = (Lerp( (FLOAT)vsb0(2), (FLOAT)vsb1(2), rm.rm_fRatio) -rm.rm_vOffset(2)) * rm.rm_vStretch(2); + vVertex(3) = (Lerp( (FLOAT)vsb0(3), (FLOAT)vsb1(3), rm.rm_fRatio) -rm.rm_vOffset(3)) * rm.rm_vStretch(3); + } +} + + +// Create render model structure for rendering an attached model +BOOL CModelObject::CreateAttachment( CRenderModel &rmMain, CAttachmentModelObject &amo) +{ + _pfModelProfile.StartTimer( CModelProfile::PTI_CREATEATTACHMENT); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_CREATEATTACHMENT); + CRenderModel &rmAttached = *amo.amo_prm; + rmAttached.rm_ulFlags = rmMain.rm_ulFlags&(RMF_FOG|RMF_HAZE|RMF_WEAPON) | RMF_ATTACHMENT; + + // get the position + rmMain.rm_pmdModelData->md_aampAttachedPosition.Lock(); + const CAttachedModelPosition & = rmMain.rm_pmdModelData->md_aampAttachedPosition[amo.amo_iAttachedPosition]; + rmMain.rm_pmdModelData->md_aampAttachedPosition.Unlock(); + + // copy common values + rmAttached.rm_vLightDirection = rmMain.rm_vLightDirection; + rmAttached.rm_fDistanceFactor = rmMain.rm_fDistanceFactor; + rmAttached.rm_colLight = rmMain.rm_colLight; + rmAttached.rm_colAmbient = rmMain.rm_colAmbient; + rmAttached.rm_colBlend = rmMain.rm_colBlend; + + // unpack the reference vertices + FLOAT3D vCenter, vFront, vUp; + const INDEX iCenter = amp.amp_iCenterVertex; + const INDEX iFront = amp.amp_iFrontVertex; + const INDEX iUp = amp.amp_iUpVertex; + UnpackVertex( rmMain, iCenter, vCenter); + UnpackVertex( rmMain, iFront, vFront); + UnpackVertex( rmMain, iUp, vUp); + + // create front and up direction vectors + FLOAT3D vY = vUp - vCenter; + FLOAT3D vZ = vCenter - vFront; + // project center and directions from object to absolute space + const FLOATmatrix3D &mO2A = rmMain.rm_mObjectRotation; + const FLOAT3D &vO2A = rmMain.rm_vObjectPosition; + vCenter = vCenter*mO2A +vO2A; + vY = vY *mO2A; + vZ = vZ *mO2A; + + // make a rotation matrix from the direction vectors + FLOAT3D vX = vY*vZ; + vY = vZ*vX; + vX.Normalize(); + vY.Normalize(); + vZ.Normalize(); + FLOATmatrix3D mOrientation; + mOrientation(1,1) = vX(1); mOrientation(1,2) = vY(1); mOrientation(1,3) = vZ(1); + mOrientation(2,1) = vX(2); mOrientation(2,2) = vY(2); mOrientation(2,3) = vZ(2); + mOrientation(3,1) = vX(3); mOrientation(3,2) = vY(3); mOrientation(3,3) = vZ(3); + + // adjust for relative placement of the attachment + FLOAT3D vOffset; + FLOATmatrix3D mRelative; + MakeRotationMatrixFast( mRelative, amo.amo_plRelative.pl_OrientationAngle); + vOffset(1) = amo.amo_plRelative.pl_PositionVector(1) * mo_Stretch(1); + vOffset(2) = amo.amo_plRelative.pl_PositionVector(2) * mo_Stretch(2); + vOffset(3) = amo.amo_plRelative.pl_PositionVector(3) * mo_Stretch(3); + FLOAT3D vO = vCenter + vOffset * mOrientation; + mOrientation *= mRelative; // convert absolute to relative orientation + rmAttached.SetObjectPlacement( vO, mOrientation); + + // done here if clipping optimizations are not allowed + extern INDEX gap_iOptimizeClipping; + if( gap_iOptimizeClipping<1) { + gap_iOptimizeClipping = 0; + _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT); + return TRUE; + } + + // test attachment to frustum and/or mirror + FLOAT3D vHandle; + _aprProjection->PreClip( vO, vHandle); + CalculateBoundingBox( &amo.amo_moModelObject, rmAttached); + + // compose view-space bounding box and sphere of an attacment + const FLOAT fR = Max( rmAttached.rm_vObjectMinBB.Length(), rmAttached.rm_vObjectMaxBB.Length()); + const FLOATobbox3D boxEntity( FLOATaabbox3D(rmAttached.rm_vObjectMinBB, rmAttached.rm_vObjectMaxBB), + vHandle, _aprProjection->pr_ViewerRotationMatrix*mOrientation); + // frustum test? + if( gap_iOptimizeClipping>1) { + // test sphere against frustrum + INDEX iFrustumTest = _aprProjection->TestSphereToFrustum(vHandle,fR); + if( iFrustumTest==0) { + // test box if sphere cut one of frustum planes + iFrustumTest = _aprProjection->TestBoxToFrustum(boxEntity); + } + // mark if attachment is fully inside frustum + if( iFrustumTest>0) rmAttached.rm_ulFlags |= RMF_INSIDE; + else if( iFrustumTest<0) { // if completely outside of frustum + // signal skip rendering only if doesn't have any attachments + _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT); + return !amo.amo_moModelObject.mo_lhAttachments.IsEmpty(); + } + } + // test sphere against mirror/warp plane (if any) + if( _aprProjection->pr_bMirror || _aprProjection->pr_bWarp) { + INDEX iMirrorPlaneTest; + const FLOAT fPlaneDistance = _aprProjection->pr_plMirrorView.PointDistance(vHandle); + if( fPlaneDistance < -fR) iMirrorPlaneTest = -1; + else if( fPlaneDistance > +fR) iMirrorPlaneTest = +1; + else { // test box if sphere cut mirror plane + iMirrorPlaneTest = boxEntity.TestAgainstPlane(_aprProjection->pr_plMirrorView); + } + // mark if attachment is fully inside mirror + if( iMirrorPlaneTest>0) rmAttached.rm_ulFlags |= RMF_INMIRROR; + else if( iMirrorPlaneTest<0) { // if completely outside mirror + // signal skip rendering only if doesn't have any attachments + _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT); + return !amo.amo_moModelObject.mo_lhAttachments.IsEmpty(); + } + } + // all done + _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT); + return TRUE; +} + + +//-------------------------------------------------------------------------------------------- +/* + * Render model using preferences given trough _mrpModelRenderPrefs global variable + */ +//-------------------------------------------------------------------------------------------- + + +// transform model to view space +static void PrepareView( CRenderModel &rm) +{ + // prepare projections + const FLOATmatrix3D &mViewer = _aprProjection->pr_ViewerRotationMatrix; + const FLOAT3D &vViewer = _aprProjection->pr_vViewerPosition; + FLOATmatrix3D &m = rm.rm_mObjectToView; + // if half face forward + if( rm.rm_pmdModelData->md_Flags&MF_HALF_FACE_FORWARD) { + // get the y-axis vector of object rotation + FLOAT3D vY(rm.rm_mObjectRotation(1,2), rm.rm_mObjectRotation(2,2), rm.rm_mObjectRotation(3,2)); + // find z axis of viewer + FLOAT3D vViewerZ( mViewer(3,1), mViewer(3,2), mViewer(3,3)); + // calculate x and z axis vectors to make object head towards viewer + FLOAT3D vX = (-vViewerZ)*vY; + vX.Normalize(); + FLOAT3D vZ = vY*vX; + // compose the rotation matrix back from those angles + m(1,1) = vX(1); m(1,2) = vY(1); m(1,3) = vZ(1); + m(2,1) = vX(2); m(2,2) = vY(2); m(2,3) = vZ(2); + m(3,1) = vX(3); m(3,2) = vY(3); m(3,3) = vZ(3); + // add viewer rotation to that + m = mViewer * m; + } // if full face forward + else if( rm.rm_pmdModelData->md_Flags&MF_FACE_FORWARD) { + // use just object banking for rotation + FLOAT fSinP = -rm.rm_mObjectRotation(2,3); + FLOAT fCosP = Sqrt(1-fSinP*fSinP); + FLOAT fSinB, fCosB; + if( fCosP>0.001f) { + const FLOAT f1oCosP = 1.0f/fCosP; + fSinB = rm.rm_mObjectRotation(2,1)*f1oCosP; + fCosB = rm.rm_mObjectRotation(2,2)*f1oCosP; + } else { + fSinB = 0.0f; + fCosB = 1.0f; + } + m(1,1) = +fCosB; m(1,2) = -fSinB; m(1,3) = 0; + m(2,1) = +fSinB; m(2,2) = +fCosB; m(2,3) = 0; + m(3,1) = 0; m(3,2) = 0; m(3,3) = 1; + } // if normal model + else { + // use viewer and object orientation + m = mViewer * rm.rm_mObjectRotation; + } + // find translation vector + rm.rm_vObjectToView = rm.rm_vObjectPosition - vViewer; + rm.rm_vObjectToView *= mViewer; +} + + +// render bounding box +static void RenderWireframeBox( FLOAT3D vMinVtx, FLOAT3D vMaxVtx, COLOR col) +{ + // only for OpenGL (for now) + if( _pGfx->gl_eCurrentAPI!=GAT_OGL) return; + + // prepare wireframe OpenGL settings + gfxDisableDepthTest(); + gfxDisableDepthWrite(); + gfxDisableBlend(); + gfxDisableAlphaTest(); + gfxDisableTexture(); + // fill vertex array so it represents bounding box + FLOAT3D vBoxVtxs[8]; + vBoxVtxs[0] = FLOAT3D( vMinVtx(1), vMinVtx(2), vMinVtx(3)); + vBoxVtxs[1] = FLOAT3D( vMaxVtx(1), vMinVtx(2), vMinVtx(3)); + vBoxVtxs[2] = FLOAT3D( vMaxVtx(1), vMinVtx(2), vMaxVtx(3)); + vBoxVtxs[3] = FLOAT3D( vMinVtx(1), vMinVtx(2), vMaxVtx(3)); + vBoxVtxs[4] = FLOAT3D( vMinVtx(1), vMaxVtx(2), vMinVtx(3)); + vBoxVtxs[5] = FLOAT3D( vMaxVtx(1), vMaxVtx(2), vMinVtx(3)); + vBoxVtxs[6] = FLOAT3D( vMaxVtx(1), vMaxVtx(2), vMaxVtx(3)); + vBoxVtxs[7] = FLOAT3D( vMinVtx(1), vMaxVtx(2), vMaxVtx(3)); + // connect vertices into lines of bounding box + INDEX iBoxLines[12][2]; + iBoxLines[ 0][0] = 0; iBoxLines[ 0][1] = 1; iBoxLines[ 1][0] = 1; iBoxLines[ 1][1] = 2; + iBoxLines[ 2][0] = 2; iBoxLines[ 2][1] = 3; iBoxLines[ 3][0] = 3; iBoxLines[ 3][1] = 0; + iBoxLines[ 4][0] = 0; iBoxLines[ 4][1] = 4; iBoxLines[ 5][0] = 1; iBoxLines[ 5][1] = 5; + iBoxLines[ 6][0] = 2; iBoxLines[ 6][1] = 6; iBoxLines[ 7][0] = 3; iBoxLines[ 7][1] = 7; + iBoxLines[ 8][0] = 4; iBoxLines[ 8][1] = 5; iBoxLines[ 9][0] = 5; iBoxLines[ 9][1] = 6; + iBoxLines[10][0] = 6; iBoxLines[10][1] = 7; iBoxLines[11][0] = 7; iBoxLines[11][1] = 4; + // for all vertices in bounding box + glCOLOR(col); + pglBegin( GL_LINES); + for( INDEX i=0; i<12; i++) { + // get starting and ending vertices of one line + FLOAT3D &v0 = vBoxVtxs[iBoxLines[i][0]]; + FLOAT3D &v1 = vBoxVtxs[iBoxLines[i][1]]; + pglVertex3f( v0(1), v0(2), v0(3)); + pglVertex3f( v1(1), v1(2), v1(3)); + } + pglEnd(); + OGL_CHECKERROR; +} + + + + +// setup CRenderModel class for rendering one model and eventually it's shadow(s) +void CModelObject::SetupModelRendering( CRenderModel &rm) +{ + _sfStats.IncrementCounter( CStatForm::SCI_MODELS); + _pfModelProfile.StartTimer( CModelProfile::PTI_INITMODELRENDERING); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_INITMODELRENDERING); + + // get model's data and lerp info + rm.rm_pmdModelData = (CModelData*)GetData(); + GetFrame( rm.rm_iFrame0, rm.rm_iFrame1, rm.rm_fRatio); + const INDEX ctVertices = rm.rm_pmdModelData->md_VerticesCt; + if( rm.rm_pmdModelData->md_Flags & MF_COMPRESSED_16BIT) { + // set pFrame to point to last and next frames' vertices + rm.rm_pFrame16_0 = &rm.rm_pmdModelData->md_FrameVertices16[rm.rm_iFrame0 *ctVertices]; + rm.rm_pFrame16_1 = &rm.rm_pmdModelData->md_FrameVertices16[rm.rm_iFrame1 *ctVertices]; + } else { + // set pFrame to point to last and next frames' vertices + rm.rm_pFrame8_0 = &rm.rm_pmdModelData->md_FrameVertices8[rm.rm_iFrame0 *ctVertices]; + rm.rm_pFrame8_1 = &rm.rm_pmdModelData->md_FrameVertices8[rm.rm_iFrame1 *ctVertices]; + } + + // obtain current rendering preferences + rm.rm_rtRenderType = _mrpModelRenderPrefs.GetRenderType(); + // remember blending color + rm.rm_colBlend = MulColors( rm.rm_colBlend, mo_colBlendColor); + + // get decompression/stretch factors + FLOAT3D &vDataStretch = rm.rm_pmdModelData->md_Stretch; + rm.rm_vStretch(1) = vDataStretch(1) * mo_Stretch(1); + rm.rm_vStretch(2) = vDataStretch(2) * mo_Stretch(2); + rm.rm_vStretch(3) = vDataStretch(3) * mo_Stretch(3); + rm.rm_vOffset = rm.rm_pmdModelData->md_vCompressedCenter; + // check if object is inverted (in mirror) + BOOL bXInverted = rm.rm_vStretch(1) < 0; + BOOL bYInverted = rm.rm_vStretch(2) < 0; + BOOL bZInverted = rm.rm_vStretch(3) < 0; + rm.rm_ulFlags &= ~RMF_INVERTED; + if( bXInverted != bYInverted != bZInverted != _aprProjection->pr_bInverted) rm.rm_ulFlags |= RMF_INVERTED; + + // prepare projections + _pfModelProfile.StartTimer( CModelProfile::PTI_INITPROJECTION); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_INITPROJECTION); + PrepareView(rm); + _pfModelProfile.StopTimer( CModelProfile::PTI_INITPROJECTION); + + // get mip factor from projection (if needed) + if( (INDEX&)rm.rm_fDistanceFactor==12345678) { + FLOAT3D vObjectAbs; + _aprProjection->PreClip( rm.rm_vObjectPosition, vObjectAbs); + rm.rm_fDistanceFactor = _aprProjection->MipFactor( Min(vObjectAbs(3), 0.0f)); + } + // adjust mip factor in case of dynamic stretch factor + if( mo_Stretch != FLOAT3D(1,1,1)) { + rm.rm_fMipFactor = rm.rm_fDistanceFactor - Log2( Max(mo_Stretch(1),Max(mo_Stretch(2),mo_Stretch(3)))); + } else { + rm.rm_fMipFactor = rm.rm_fDistanceFactor; + } + // adjust mip factor by custom settings + rm.rm_fMipFactor = rm.rm_fMipFactor*mdl_fLODMul +mdl_fLODAdd; + + // get current mip model using mip factor + rm.rm_iMipLevel = GetMipModel( rm.rm_fMipFactor); + mo_iLastRenderMipLevel = rm.rm_iMipLevel; + // get current vertices mask + rm.rm_pmmiMip = &rm.rm_pmdModelData->md_MipInfos[rm.rm_iMipLevel]; + + // don't allow any shading, if shading is turned off + if( rm.rm_rtRenderType & RT_SHADING_NONE) { + rm.rm_colAmbient = C_WHITE|CT_OPAQUE; + rm.rm_colLight = C_BLACK; + } + + // calculate light vector as seen from model, so that vertex normals + // do not need to be transformed for lighting calculations + FLOAT fLightDirection=(rm.rm_vLightDirection).Length(); + if( fLightDirection>0.001f) { + rm.rm_vLightDirection /= fLightDirection; + } else { + rm.rm_vLightDirection = FLOAT3D(0,0,0); + } + rm.rm_vLightObj = rm.rm_vLightDirection * !rm.rm_mObjectRotation; + + // precalculate rendering data if needed + extern void PrepareModelForRendering( CModelData &md); + PrepareModelForRendering( *rm.rm_pmdModelData); + + // done with setup if viewing from this model + if( rm.rm_ulFlags&RMF_SPECTATOR) { + _pfModelProfile.StopTimer( CModelProfile::PTI_INITMODELRENDERING); + return; + } + + _pfModelProfile.StartTimer( CModelProfile::PTI_INITATTACHMENTS); + // for each attachment on this model object + FOREACHINLIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) { + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_INITATTACHMENTS); + CAttachmentModelObject *pamo = itamo; + // create new render model structure + pamo->amo_prm = &_armRenderModels.Push(); + const BOOL bVisible = CreateAttachment( rm, *pamo); + if( !bVisible) { // skip if not visible + pamo->amo_prm = NULL; + _armRenderModels.Pop(); + continue; + } // prepare if visible + _pfModelProfile.StopTimer( CModelProfile::PTI_INITMODELRENDERING); + _pfModelProfile.StopTimer( CModelProfile::PTI_INITATTACHMENTS); + pamo->amo_moModelObject.SetupModelRendering( *pamo->amo_prm); + _pfModelProfile.StartTimer( CModelProfile::PTI_INITATTACHMENTS); + _pfModelProfile.StartTimer( CModelProfile::PTI_INITMODELRENDERING); + } + // all done + _pfModelProfile.StopTimer( CModelProfile::PTI_INITATTACHMENTS); + _pfModelProfile.StopTimer( CModelProfile::PTI_INITMODELRENDERING); +} + + + +// render model +void CModelObject::RenderModel( CRenderModel &rm) +{ + // skip invisible models + if( mo_Stretch == FLOAT3D(0,0,0)) return; + + _pfModelProfile.StartTimer( CModelProfile::PTI_RENDERMODEL); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_RENDERMODEL); + + // cluster shadows rendering? + if( _iRenderingType==2) { + RenderModel_Mask(rm); + _pfModelProfile.StopTimer( CModelProfile::PTI_RENDERMODEL); + return; + } + ASSERT( _iRenderingType==1); + + // if we should draw polygons and model + if( !(rm.rm_ulFlags&RMF_SPECTATOR) && (!(rm.rm_rtRenderType&RT_NO_POLYGON_FILL) + || (rm.rm_rtRenderType&RT_WIRE_ON) || (rm.rm_rtRenderType&RT_HIDDEN_LINES)) ) { + // eventually calculate projection model bounding box in object space (needed for fog/haze trivial rejection) + if( rm.rm_ulFlags&(RMF_FOG|RMF_HAZE)) CalculateBoundingBox( this, rm); + // render complete model + rm.SetModelView(); + RenderModel_View(rm); + } + + // if we should draw current frame bounding box + if( _mrpModelRenderPrefs.BBoxFrameVisible()) { + // get min and max coordinates of bounding box + FLOAT3D vMin = rm.rm_pmdModelData->md_FrameInfos[rm.rm_iFrame0].mfi_Box.Min(); + FLOAT3D vMax = rm.rm_pmdModelData->md_FrameInfos[rm.rm_iFrame0].mfi_Box.Max(); + rm.SetModelView(); + RenderWireframeBox( vMin, vMax, C_dMAGENTA|CT_OPAQUE); + } + + // if we should draw all frames bounding box + if( _mrpModelRenderPrefs.BBoxAllVisible()) { + // calculate all frames bounding box + FLOATaabbox3D aabbMax; + for( INDEX i=0; imd_FramesCt; i++) { + aabbMax |= rm.rm_pmdModelData->md_FrameInfos[i].mfi_Box; + } // pass min and max coordinates of all frames bounding box + rm.SetModelView(); + RenderWireframeBox( aabbMax.Min(), aabbMax.Max(), C_dGRAY|CT_OPAQUE); + } + + // render each attachment on this model object + FOREACHINLIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) + { + // calculate bounding box of an attachment + CAttachmentModelObject *pamo = itamo; + if( pamo->amo_prm==NULL) continue; // skip view-rejected attachments + _pfModelProfile.StopTimer( CModelProfile::PTI_RENDERMODEL); + pamo->amo_moModelObject.RenderModel( *pamo->amo_prm); + _pfModelProfile.StartTimer( CModelProfile::PTI_RENDERMODEL); + } + // done + _pfModelProfile.StopTimer( CModelProfile::PTI_RENDERMODEL); +} + + +//-------------------------------------------------------------------------------------------- +/* + * Render shadow of model + */ +//-------------------------------------------------------------------------------------------- +void CModelObject::RenderShadow( CRenderModel &rm, const CPlacement3D &plLight, + const FLOAT fFallOff, const FLOAT fHotSpot, const FLOAT fIntensity, + const FLOATplane3D &plShadowPlane) +{ + // if shadows are not rendered for current mip or model is half/full face-forward, do nothing + if( !HasShadow(rm.rm_iMipLevel) + || (rm.rm_pmdModelData->md_Flags&(MF_FACE_FORWARD|MF_HALF_FACE_FORWARD))) return; + ASSERT( _iRenderingType==1); + ASSERT( fIntensity>=0 && fIntensity<=1); + + _pfModelProfile.StartTimer( CModelProfile::PTI_RENDERSHADOW); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_RENDERSHADOW); + _sfStats.IncrementCounter( CStatForm::SCI_MODELSHADOWS); + + // call driver function for drawing shadows + rm.SetModelView(); + RenderShadow_View( rm, plLight, fFallOff, fHotSpot, fIntensity, plShadowPlane); + + // render shadow or each attachment on this model object + FOREACHINLIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) { + CAttachmentModelObject *pamo = itamo; + if( pamo->amo_prm==NULL) continue; // skip view-rejected attachments + _pfModelProfile.StopTimer( CModelProfile::PTI_RENDERSHADOW); + pamo->amo_moModelObject.RenderShadow( *pamo->amo_prm, plLight, fFallOff, fHotSpot, fIntensity, plShadowPlane); + _pfModelProfile.StartTimer( CModelProfile::PTI_RENDERSHADOW); + } + _pfModelProfile.StopTimer( CModelProfile::PTI_RENDERSHADOW); +} + + +// simple shadow rendering +void CModelObject::AddSimpleShadow( CRenderModel &rm, const FLOAT fIntensity, const FLOATplane3D &plShadowPlane) +{ + // if shadows are not rendered for current mip, model is half/full face-forward, + // intensitiy is too low or projection is not perspective - do nothing! + if( !HasShadow(rm.rm_iMipLevel) || fIntensity<0.01f || !_aprProjection.IsPerspective() + || (rm.rm_pmdModelData->md_Flags&(MF_FACE_FORWARD|MF_HALF_FACE_FORWARD))) return; + ASSERT( _iRenderingType==1); + ASSERT( fIntensity>0 && fIntensity<=1); + // do some rendering + _pfModelProfile.StartTimer( CModelProfile::PTI_RENDERSIMPLESHADOW); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_RENDERSIMPLESHADOW); + _sfStats.IncrementCounter( CStatForm::SCI_MODELSHADOWS); + // calculate projection model bounding box in object space (if needed) + CalculateBoundingBox( this, rm); + // add one simple shadow to batch list + AddSimpleShadow_View( rm, fIntensity, plShadowPlane); + // all done + _pfModelProfile.StopTimer( CModelProfile::PTI_RENDERSIMPLESHADOW); +} diff --git a/Sources/Engine/Models/RenderModel.h b/Sources/Engine/Models/RenderModel.h new file mode 100644 index 0000000..778fb83 --- /dev/null +++ b/Sources/Engine/Models/RenderModel.h @@ -0,0 +1,128 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_RENDERMODEL_H +#define SE_INCL_RENDERMODEL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* + * This instance of render prefs object represents global preferences + * used for rendering of all models and their shadows + */ +ENGINE_API extern class CModelRenderPrefs _mrpModelRenderPrefs; + +/* + * This object is used to define how models and their shadows will be rendered + */ +class ENGINE_API CModelRenderPrefs +{ +private: + BOOL rp_BBoxFrameVisible; // determines visibility of frame BBox + BOOL rp_BBoxAllVisible; // determines visibility of all frames BBox + COLOR rp_InkColor; // ink color (wire frame) + COLOR rp_PaperColor; // paper color + ULONG rp_RenderType; // model's rendering type + INDEX rp_ShadowQuality; // model shadow's quality (substraction to mip model index) +public: + CModelRenderPrefs(); // constructor sets defult values + void SetRenderType(ULONG rtNew); // set model rendering type + void SetTextureType(ULONG rtNew); // set model rendering texture type + void SetShadingType(ULONG rtNew); // set model shading texture type + void SetShadowQuality(INDEX iNew); // set shadow quality (best 0, worse -1, ...) + void DesreaseShadowQuality(void); // decrease shadow quality + void IncreaseShadowQuality(void); // increase shadow quality + void SetWire(BOOL bWireOn); // set wire frame on/off + void SetHiddenLines(BOOL bHiddenLinesOn); // set hiden lines on/off + BOOL BBoxFrameVisible(); // bounding box frames visible? + BOOL BBoxAllVisible(); // bounding box all frames visible? + BOOL WireOn(void); // returns TRUE if wire frame is on + BOOL HiddenLines(void); // returns TRUE if hiden lines are visible + void SetInkColor(COLOR clrNew); // set ink color + COLOR GetInkColor(); // get ink color + void SetPaperColor(COLOR clrNew); // set paper color + COLOR GetPaperColor(); // get paper color + void BBoxFrameShow(BOOL bShow); // show bounding box frame + void BBoxAllShow(BOOL bShow); // show bounding box all frames + ULONG GetRenderType(void); // get model rendering type + INDEX GetShadowQuality(void); // retrieves current shadow quality level + void Read_t( CTStream *istrFile); // throw char * // read and + void Write_t( CTStream *ostrFile); // throw char * // write functions +}; + +// texture used for simple model shadows +extern ENGINE_API CTextureObject _toSimpleModelShadow; + +// begin/end model rendering to screen +extern ENGINE_API void BeginModelRenderingView( + CAnyProjection3D &prProjection, CDrawPort *pdp); +extern ENGINE_API void EndModelRenderingView( BOOL bRestoreOrtho=TRUE); + +// begin/end model rendering to shadow mask +extern ENGINE_API void BeginModelRenderingMask( + CAnyProjection3D &prProjection, UBYTE *pubMask, SLONG slMaskWidth, SLONG slMaskHeight); +extern ENGINE_API void EndModelRenderingMask(void); + +#define RMF_ATTACHMENT (1UL<<0) // set for attachment render models +#define RMF_FOG (1UL<<1) // render in fog +#define RMF_HAZE (1UL<<2) // render in haze +#define RMF_SPECTATOR (1UL<<3) // model will not be rendered but shadows might +#define RMF_INVERTED (1UL<<4) // stretch is inverted +#define RMF_BBOXSET (1UL<<5) // bounding box has been calculated +#define RMF_INSIDE (1UL<<6) // doesn't need clipping to frustum +#define RMF_INMIRROR (1UL<<7) // doesn't need clipping to mirror/warp plane +#define RMF_WEAPON (1UL<<8) // TEMP: weapon model is rendering so don't use ATI's Truform! + +class ENGINE_API CRenderModel { +public: +// implementation: + CModelData *rm_pmdModelData; // model's data + struct ModelMipInfo *rm_pmmiMip; // current mip + ULONG rm_rtRenderType; // current rendering preferences + // lerp information + INDEX rm_iFrame0, rm_iFrame1; + FLOAT rm_fRatio; + INDEX rm_iMipLevel; + INDEX rm_iTesselationLevel; + union { struct ModelFrameVertex8 *rm_pFrame8_0; // ptr to last frame + struct ModelFrameVertex16 *rm_pFrame16_0; }; + union { struct ModelFrameVertex8 *rm_pFrame8_1; // ptr to next frame + struct ModelFrameVertex16 *rm_pFrame16_1; }; + FLOAT3D rm_vLightObj; // light vector as seen from object space + // placement of the object + FLOAT3D rm_vObjectPosition; + FLOATmatrix3D rm_mObjectRotation; + // object to view placement + FLOAT3D rm_vObjectToView; + FLOATmatrix3D rm_mObjectToView; + // decompression and stretch factors + FLOAT3D rm_vStretch, rm_vOffset; + // bounding box min/max coords in object space + FLOAT3D rm_vObjectMinBB, rm_vObjectMaxBB; + // flags and blend color global for this rendering + ULONG rm_ulFlags; + COLOR rm_colBlend; + + // set modelview matrix if not already set + void SetModelView(void); +// interface: +public: + CRenderModel(void); + ~CRenderModel(void); + // set placement of the object + void SetObjectPlacement(const CPlacement3D &pl); + void SetObjectPlacement(const FLOAT3D &v, const FLOATmatrix3D &m); + + FLOAT rm_fDistanceFactor; // mip factor not including scaling or biasing + FLOAT rm_fMipFactor; // real mip factor + FLOAT3D rm_vLightDirection; // direction shading light + COLOR rm_colLight; // color of the shading light + COLOR rm_colAmbient; // color of the ambient +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Models/RenderModel_Mask.cpp b/Sources/Engine/Models/RenderModel_Mask.cpp new file mode 100644 index 0000000..20310a1 --- /dev/null +++ b/Sources/Engine/Models/RenderModel_Mask.cpp @@ -0,0 +1,529 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// polygon visibility constants +#define VISIBLE_NOT 0 +#define VISIBLE_FRONT (+1) +#define VISIBLE_BACK (-1) + +// some rendering variables and so ... +static PIX pixWidth; + +// some projection parameters +static FLOAT fCenterI, fCenterJ; +static FLOAT fRatioI, fRatioJ; +static FLOAT fStepI, fStepJ; +static FLOAT fZoomI, fZoomJ; +static FLOAT fFrontClipDistance, f1oFrontClipDistance; +static FLOAT fBackClipDistance, f1oBackClipDistance; +static FLOAT fDepthBufferFactor; +static BOOL bBackFaced, bDoubleSided; +static BOOL bPerspective; +static BOOL b16BitCompression; +static ULONG ulColorMask; +static ULONG ulRenderFlags; +static PIX pixMipWidth, pixMipHeight; +static INDEX iMipLevel; + +// vertex array for clipped polygons +#define MAX_CLIPPEDVERTICES 32 +// double buffer for clipping +static TransformedVertexData atvdClipped1[MAX_CLIPPEDVERTICES]; +static TransformedVertexData atvdClipped2[MAX_CLIPPEDVERTICES]; +static TransformedVertexData *ptvdSrc = atvdClipped1; +static TransformedVertexData *ptvdDst = atvdClipped2; +static INDEX ctvxSrc, ctvxDst; + + + +// prepare list of all visible polygons that are to be rendered to current drawport +static void RenderOneSide( CRenderModel &rm, const INDEX iVisibility) +{ + // for each surface in finest mip model + ModelMipInfo &mmiMip = rm.rm_pmdModelData->md_MipInfos[0]; + FOREACHINSTATICARRAY( mmiMip.mmpi_MappingSurfaces, MappingSurface, itms) + { + MappingSurface &ms = *itms; + ULONG ulFlags = ms.ms_ulRenderingFlags; + // if surface is invisible or empty, skip it + if( (ulFlags&SRF_INVISIBLE) || ms.ms_ctSrfVx==0) continue; + // if rendering back side and surface is not double sided, skip entire surface + if( iVisibility==VISIBLE_BACK && !(ulFlags&SRF_DOUBLESIDED)) continue; + + // for each vertex in the surface + BOOL bTransparency = ms.ms_sttTranslucencyType!=STT_OPAQUE; + for( INDEX ivx=0; ivxmd_TransformedVertices[mtv.mtv_iTransformedVertex]; + // adjust texture coordinates for texture mapping and clipping + tvd.tvd_fU = (mtv.mtv_UV(1)>>iMipLevel); + tvd.tvd_fV = (mtv.mtv_UV(2)>>iMipLevel); + tvd.tvd_pv2.pv2_fUoK = tvd.tvd_fU * tvd.tvd_pv2.pv2_f1oK; + tvd.tvd_pv2.pv2_fVoK = tvd.tvd_fV * tvd.tvd_pv2.pv2_f1oK; + } + + // for each polygon in the surface + for( INDEX iipo=0; iipo=0) { + // add it to clip array + ptvdDst[ctvxDst] = tvd0; + ctvxDst++; + // if second vertex is out + if( fd1<0) { + // add clipped vertex at exit + TransformedVertexData &tvdClipped = ptvdDst[ctvxDst]; + ctvxDst++; + FLOAT fF = fd1/(fd1-fd0); + tvdClipped.tvd_fX = tvd1.tvd_fX - (tvd1.tvd_fX - tvd0.tvd_fX) *fF; + tvdClipped.tvd_fY = tvd1.tvd_fY - (tvd1.tvd_fY - tvd0.tvd_fY) *fF; + tvdClipped.tvd_fZ = fFrontClipDistance; + tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oFrontClipDistance; + FLOAT fU = tvd1.tvd_fU - (tvd1.tvd_fU - tvd0.tvd_fU) *fF; + FLOAT fV = tvd1.tvd_fV - (tvd1.tvd_fV - tvd0.tvd_fV) *fF; + tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK; + tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK; + } + // if first vertex is out (don't add it into clip array) + } else { + // if second vertex is in + if( fd1>=0) { + // add clipped vertex at entry + TransformedVertexData &tvdClipped = ptvdDst[ctvxDst]; + ctvxDst++; + FLOAT fF = fd0/(fd0-fd1); + tvdClipped.tvd_fX = tvd0.tvd_fX - (tvd0.tvd_fX - tvd1.tvd_fX) *fF; + tvdClipped.tvd_fY = tvd0.tvd_fY - (tvd0.tvd_fY - tvd1.tvd_fY) *fF; + tvdClipped.tvd_fZ = fFrontClipDistance; + tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oFrontClipDistance; + FLOAT fU = tvd0.tvd_fU - (tvd0.tvd_fU - tvd1.tvd_fU) *fF; + FLOAT fV = tvd0.tvd_fV - (tvd0.tvd_fV - tvd1.tvd_fV) *fF; + tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK; + tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK; + } + } + // proceed to next vertex in list (i.e. new pair of vertices) + ivx0=ivx1; + ivx1++; + }} + // swap buffers + Swap( ptvdSrc, ptvdDst); + Swap( ctvxSrc, ctvxDst); + + // if clipping to far clip plane is on + if( fBackClipDistance<0) { + ctvxDst=0; + INDEX ivx0=ctvxSrc-1; + INDEX ivx1=0; + {for( INDEX ivx=0; ivx=0) { + // add it to clip array + ptvdDst[ctvxDst] = tvd0; + ctvxDst++; + // if second vertex is out + if( fd1<0) { + // add clipped vertex at exit + TransformedVertexData &tvdClipped = ptvdDst[ctvxDst]; + ctvxDst++; + FLOAT fF = fd1/(fd1-fd0); + tvdClipped.tvd_fX = tvd1.tvd_fX - (tvd1.tvd_fX - tvd0.tvd_fX) *fF; + tvdClipped.tvd_fY = tvd1.tvd_fY - (tvd1.tvd_fY - tvd0.tvd_fY) *fF; + tvdClipped.tvd_fZ = fBackClipDistance; + tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oBackClipDistance; + FLOAT fU = tvd1.tvd_fU - (tvd1.tvd_fU - tvd0.tvd_fU) *fF; + FLOAT fV = tvd1.tvd_fV - (tvd1.tvd_fV - tvd0.tvd_fV) *fF; + tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK; + tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK; + } + // if first vertex is out (don't add it into clip array) + } else { + // if second vertex is in + if( fd1>=0) { + // add clipped vertex at entry + TransformedVertexData &tvdClipped = ptvdDst[ctvxDst]; + ctvxDst++; + FLOAT fF = fd0/(fd0-fd1); + tvdClipped.tvd_fX = tvd0.tvd_fX - (tvd0.tvd_fX - tvd1.tvd_fX) *fF; + tvdClipped.tvd_fY = tvd0.tvd_fY - (tvd0.tvd_fY - tvd1.tvd_fY) *fF; + tvdClipped.tvd_fZ = fBackClipDistance; + tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oBackClipDistance; + FLOAT fU = tvd0.tvd_fU - (tvd0.tvd_fU - tvd1.tvd_fU) *fF; + FLOAT fV = tvd0.tvd_fV - (tvd0.tvd_fV - tvd1.tvd_fV) *fF; + tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK; + tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK; + } + } + // proceed to next vertex in list (i.e. new pair of vertices) + ivx0=ivx1; + ivx1++; + }} + // swap buffers + Swap( ptvdSrc, ptvdDst); + Swap( ctvxSrc, ctvxDst); + } + + // for each vertex + {for( INDEX ivx=0; ivx=0) { + // add it to clip array + ptvdDst[ctvxDst].tvd_pv2 = pv20; + ctvxDst++; + // if second vertex is out + if( fd1<0) { + PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2; + ctvxDst++; + FLOAT fF = fd1/(fd1-fd0); + pv2Clipped.pv2_fI = 0; + pv2Clipped.pv2_fJ = pv21.pv2_fJ - (pv21.pv2_fJ - pv20.pv2_fJ) *fF; + pv2Clipped.pv2_f1oK = pv21.pv2_f1oK - (pv21.pv2_f1oK - pv20.pv2_f1oK) *fF; + pv2Clipped.pv2_fUoK = pv21.pv2_fUoK - (pv21.pv2_fUoK - pv20.pv2_fUoK) *fF; + pv2Clipped.pv2_fVoK = pv21.pv2_fVoK - (pv21.pv2_fVoK - pv20.pv2_fVoK) *fF; + } + // if first vertex is out (don't add it into clip array) + } else { + // if second vertex is in + if( fd1>=0) { + // add clipped vertex at entry + PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2; + ctvxDst++; + FLOAT fF = fd0/(fd0-fd1); + pv2Clipped.pv2_fI = 0; + pv2Clipped.pv2_fJ = pv20.pv2_fJ - (pv20.pv2_fJ - pv21.pv2_fJ)*fF; + pv2Clipped.pv2_f1oK = pv20.pv2_f1oK - (pv20.pv2_f1oK - pv21.pv2_f1oK) *fF; + pv2Clipped.pv2_fUoK = pv20.pv2_fUoK - (pv20.pv2_fUoK - pv21.pv2_fUoK) *fF; + pv2Clipped.pv2_fVoK = pv20.pv2_fVoK - (pv20.pv2_fVoK - pv21.pv2_fVoK) *fF; + } + } + // proceed to next vertex in list (i.e. new pair of vertices) + ivx0=ivx1; + ivx1++; + }} + // swap buffers + Swap( ptvdSrc, ptvdDst); + Swap( ctvxSrc, ctvxDst); + + // clip polygon against right edge + ctvxDst=0; + ivx0=ctvxSrc-1; + ivx1=0; + {for( INDEX ivx=0; ivx=0) { + // add it to clip array + ptvdDst[ctvxDst].tvd_pv2 = pv20; + ctvxDst++; + // if second vertex is out + if( fd1<0) { + PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2; + ctvxDst++; + FLOAT fF = fd1/(fd1-fd0); + pv2Clipped.pv2_fI = pixWidth; + pv2Clipped.pv2_fJ = pv21.pv2_fJ - (pv21.pv2_fJ - pv20.pv2_fJ)*fF; + pv2Clipped.pv2_f1oK = pv21.pv2_f1oK - (pv21.pv2_f1oK - pv20.pv2_f1oK) *fF; + pv2Clipped.pv2_fUoK = pv21.pv2_fUoK - (pv21.pv2_fUoK - pv20.pv2_fUoK) *fF; + pv2Clipped.pv2_fVoK = pv21.pv2_fVoK - (pv21.pv2_fVoK - pv20.pv2_fVoK) *fF; + } + // if first vertex is out (don't add it into clip array) + } else { + // if second vertex is in + if( fd1>=0) { + // add clipped vertex at entry + PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2; + ctvxDst++; + FLOAT fF = fd0/(fd0-fd1); + pv2Clipped.pv2_fI = pixWidth; + pv2Clipped.pv2_fJ = pv20.pv2_fJ - (pv20.pv2_fJ - pv21.pv2_fJ)*fF; + pv2Clipped.pv2_f1oK = pv20.pv2_f1oK - (pv20.pv2_f1oK - pv21.pv2_f1oK) *fF; + pv2Clipped.pv2_fUoK = pv20.pv2_fUoK - (pv20.pv2_fUoK - pv21.pv2_fUoK) *fF; + pv2Clipped.pv2_fVoK = pv20.pv2_fVoK - (pv20.pv2_fVoK - pv21.pv2_fVoK) *fF; + } + } + // proceed to next vertex in list (i.e. new pair of vertices) + ivx0=ivx1; + ivx1++; + }} + // swap buffers + Swap( ptvdSrc, ptvdDst); + Swap( ctvxSrc, ctvxDst); + + // draw all triangles in clipped polygon as a triangle fan, with clipping + PolyVertex2D &pvx0 = ptvdSrc[0].tvd_pv2; + {for( INDEX ivx=1; ivxtvd_pv2; + {for( INDEX ivx=1; ivxtvd_pv2; + PolyVertex2D &pvx2 = mpPolygon.mp_PolygonVertices[ivx+1].mpv_ptvTransformedVertex->tvd_pv2; + DrawTriangle_Mask( _pubMask, _slMaskWidth, _slMaskHeight, &pvx0, &pvx1, &pvx2, bTransparency); + }} + _pfModelProfile.IncrementCounter(CModelProfile::PCI_MASK_TRIANGLES, mpPolygon.mp_PolygonVertices.Count()-2); + _pfModelProfile.IncrementCounter(CModelProfile::PCI_MASK_POLYGONS); + } + } + } +} + + + + +// prepare model for rendering (i.e. project model vertices) +void CModelObject::RenderModel_Mask( CRenderModel &rm) +{ + // skip shadow generation if effect texture has been set + CTextureData *ptd = (CTextureData*)mo_toTexture.GetData(); + if( ptd!=NULL && ptd->td_ptegEffect!=NULL) { + // report to console + CPrintF( TRANS("WARNING: model '%s' cast cluster shadows but has an effect texture.\n"), GetData()->GetName()); + return; + } + + _pfModelProfile.StartTimer( CModelProfile::PTI_MASK_INITMODELRENDERING); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_MASK_INITMODELRENDERING); + + // cache drawport width (for horizontal screen clipping purposes) + pixWidth = _slMaskWidth; + + // test if projection is parallel or perspective + bPerspective = TRUE; + if( !_aprProjection.IsPerspective()) bPerspective = FALSE; + b16BitCompression = rm.rm_pmdModelData->md_Flags & MF_COMPRESSED_16BIT; + ulColorMask = mo_ColorMask; + + // if texture is invalid, backup to white color mode + if( ptd==NULL) rm.rm_rtRenderType = (rm.rm_rtRenderType&~RT_TEXTURE_MASK)|RT_WHITE_TEXTURE; + + // if texture is ok + iMipLevel = 31; + ULONG *pulCurrentMipmap = NULL; + if( rm.rm_rtRenderType & RT_TEXTURE) { + // reload texture + ptd->Force( TEX_STATIC); + // get texture parameters for current frame and needed mip factor + pulCurrentMipmap = ptd->td_pulFrames + (mo_toTexture.GetFrame()*ptd->td_slFrameSize)/BYTES_PER_TEXEL; + iMipLevel = ptd->td_iFirstMipLevel; + pixMipWidth = ptd->GetPixWidth(); + pixMipHeight = ptd->GetPixHeight(); + } + // initialize texture for usage thru render triangle routine + SetTriangleTexture( pulCurrentMipmap, pixMipWidth, pixMipHeight); + + CPerspectiveProjection3D &prPerspective = (CPerspectiveProjection3D &)*_aprProjection; + CParallelProjection3D &prParallel = (CParallelProjection3D &)*_aprProjection; + + const FLOATmatrix3D &m = rm.rm_mObjectToView; + const FLOAT3D &v = rm.rm_vObjectToView; + + if( bPerspective) { + fCenterI = prPerspective.pr_ScreenCenter(1); + fCenterJ = prPerspective.pr_ScreenCenter(2); + fRatioI = prPerspective.ppr_PerspectiveRatios(1); + fRatioJ = prPerspective.ppr_PerspectiveRatios(2); + fFrontClipDistance = -prPerspective.pr_NearClipDistance; + fBackClipDistance = -prPerspective.pr_FarClipDistance; + f1oFrontClipDistance = -1/prPerspective.pr_NearClipDistance; + f1oBackClipDistance = -1/prPerspective.pr_FarClipDistance; + fDepthBufferFactor = prPerspective.pr_fDepthBufferFactor; + } else { + fCenterI = prParallel.pr_ScreenCenter(1); + fCenterJ = prParallel.pr_ScreenCenter(2); + fStepI = prParallel.pr_vStepFactors(1); + fStepJ = prParallel.pr_vStepFactors(2); + fZoomI = prParallel.pr_vZoomFactors(1); + fZoomJ = prParallel.pr_vZoomFactors(2); + fFrontClipDistance = -prPerspective.pr_NearClipDistance; + fBackClipDistance = -prPerspective.pr_FarClipDistance; + f1oFrontClipDistance = 1; + f1oBackClipDistance = 1; + fDepthBufferFactor = 1; + } + + // for each vertex + for( INDEX ivx=0; ivxmd_VerticesCt; ivx++) + { + TransformedVertexData &tvd = rm.rm_pmdModelData->md_TransformedVertices[ ivx]; + tvd.tvd_bClipped = FALSE; // initially, vertex is not clipped + float fxOld, fyOld, fzOld; + if( b16BitCompression) { + ModelFrameVertex16 &mfv = rm.rm_pFrame16_0[ivx]; + fxOld = (mfv.mfv_SWPoint(1)-rm.rm_vOffset(1)) *rm.rm_vStretch(1); + fyOld = (mfv.mfv_SWPoint(2)-rm.rm_vOffset(2)) *rm.rm_vStretch(2); + fzOld = (mfv.mfv_SWPoint(3)-rm.rm_vOffset(3)) *rm.rm_vStretch(3); + } else { + ModelFrameVertex8 &mfv = rm.rm_pFrame8_0[ivx]; + fxOld = (mfv.mfv_SBPoint(1)-rm.rm_vOffset(1)) *rm.rm_vStretch(1); + fyOld = (mfv.mfv_SBPoint(2)-rm.rm_vOffset(2)) *rm.rm_vStretch(2); + fzOld = (mfv.mfv_SBPoint(3)-rm.rm_vOffset(3)) *rm.rm_vStretch(3); + } + // rotate the vertex and remember transformed coordinates, for eventual clipping + tvd.tvd_fX = fxOld*m(1,1) + fyOld*m(1,2) + fzOld*m(1,3) + v(1); + tvd.tvd_fY = fxOld*m(2,1) + fyOld*m(2,2) + fzOld*m(2,3) + v(2); + tvd.tvd_fZ = fxOld*m(3,1) + fyOld*m(3,2) + fzOld*m(3,3) + v(3); + + // prepare screen coordinates for software + if( bPerspective) { + const FLOAT f1oZ = 1.0f/tvd.tvd_fZ; + tvd.tvd_pv2.pv2_fI = fCenterI+tvd.tvd_fX*fRatioI*f1oZ; + tvd.tvd_pv2.pv2_fJ = fCenterJ-tvd.tvd_fY*fRatioJ*f1oZ; + tvd.tvd_pv2.pv2_f1oK = fDepthBufferFactor*f1oZ; + } else { + tvd.tvd_pv2.pv2_fI = fCenterI+tvd.tvd_fX*fZoomI+tvd.tvd_fZ*fStepI; + tvd.tvd_pv2.pv2_fJ = fCenterJ-tvd.tvd_fY*fZoomJ-tvd.tvd_fZ*fStepJ; + tvd.tvd_pv2.pv2_f1oK = 1; + } + + // check clipping against horizontal screen boundaries and near clip plane + if( tvd.tvd_pv2.pv2_fI<0 || tvd.tvd_pv2.pv2_fI>=pixWidth || + tvd.tvd_fZ>fFrontClipDistance || (fBackClipDistance<0 && tvd.tvd_fZmd_MipInfos[0]; + FOREACHINSTATICARRAY( mmiMip.mmpi_Polygons, ModelPolygon, itmp) + { + ModelPolygon &mp = *itmp; + ulRenderFlags = mmiMip.mmpi_MappingSurfaces[mp.mp_Surface].ms_ulRenderingFlags; + // get first three of polygon's transformed vertices + const TransformedVertexData &tvd0 = *mp.mp_PolygonVertices[0].mpv_ptvTransformedVertex; + const TransformedVertexData &tvd1 = *mp.mp_PolygonVertices[1].mpv_ptvTransformedVertex; + const TransformedVertexData &tvd2 = *mp.mp_PolygonVertices[2].mpv_ptvTransformedVertex; + + // calculate polygon normal with front plane clipping + FLOAT fD1X = tvd2.tvd_fX - tvd1.tvd_fX; + FLOAT fD1Y = tvd2.tvd_fY - tvd1.tvd_fY; + FLOAT fD1Z = tvd2.tvd_fZ - tvd1.tvd_fZ; + FLOAT fD2X = tvd0.tvd_fX - tvd1.tvd_fX; + FLOAT fD2Y = tvd0.tvd_fY - tvd1.tvd_fY; + FLOAT fD2Z = tvd0.tvd_fZ - tvd1.tvd_fZ; + FLOAT fNX = fD2Y*fD1Z - fD2Z*fD1Y; + FLOAT fNY = fD2Z*fD1X - fD2X*fD1Z; + FLOAT fNZ = fD2X*fD1Y - fD2Y*fD1X; + // calculate polygon normal visibility + FLOAT fVisible; + if( bPerspective) { + fVisible = fNX*tvd0.tvd_fX + fNY*tvd0.tvd_fY + fNZ*tvd0.tvd_fZ; + } else { + fVisible = fNX*prParallel.pr_vViewDirection(1) + + fNY*prParallel.pr_vViewDirection(2) + + fNZ*prParallel.pr_vViewDirection(3); + } + + // if the polygon is back-facing + if( fVisible<0) { + // if the polygon is double sided + if( ulRenderFlags & SRF_DOUBLESIDED) { + // mark it as back-facing double sided + mp.mp_slVisibility = VISIBLE_BACK; + // if the polygon is not double sided + } else { + // mark it as invisible + mp.mp_slVisibility = VISIBLE_NOT; + } + // if the polygon is front-facing + } else { + // mark it as visible front-facing + mp.mp_slVisibility = VISIBLE_FRONT; + } + + // initally assume that polygon doesn't need clipping + mp.mp_bClipped = FALSE; + // if the polygon plane is not invisible + if( mp.mp_slVisibility != VISIBLE_NOT) { + // for all vertices + {for( INDEX ivx=0; ivx +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + +#define ASMOPT 1 + + +extern BOOL CVA_bModels; +extern BOOL GFX_bTruform; +extern BOOL _bMultiPlayer; + +extern const UBYTE *pubClipByte; +extern const FLOAT *pfSinTable; +extern const FLOAT *pfCosTable; + +static GfxAPIType _eAPI; + +static BOOL _bForceTranslucency; // force translucency of opaque/transparent surfaces (for model fading) +static ULONG _ulMipLayerFlags; +static INDEX _icol=0; + + +// mip arrays +static CStaticStackArray _avtxMipBase; +static CStaticStackArray _atexMipBase; // for reflection and specular +static CStaticStackArray _anorMipBase; +static CStaticStackArray _acolMipBase; + +static CStaticStackArray _atexMipFogy; +static CStaticStackArray _ashdMipFogy; +static CStaticStackArray _atx1MipHaze; +static CStaticStackArray _ashdMipHaze; + +// surface arrays +static CStaticStackArray _avtxSrfBase; +static CStaticStackArray _anorSrfBase; // normals for Truform! +static CStaticStackArray _atexSrfBase; +static CStaticStackArray _acolSrfBase; + +// shadows arrays +static CStaticStackArray _aooqMipShad; +static CStaticStackArray _atx4SrfShad; + + +// pointers to arrays for quicker access +static GFXColor *pcolSrfBase; +static GFXColor *pcolMipBase; +static GFXVertex3 *pvtxMipBase; +static GFXNormal3 *pnorMipBase; +static GFXTexCoord *ptexMipBase; +static GFXTexCoord *ptexMipFogy; +static UBYTE *pshdMipFogy; +static FLOAT *ptx1MipHaze; +static UBYTE *pshdMipHaze; +static FLOAT *pooqMipShad; +static UWORD *puwSrfToMip; + +// misc +static ULONG _ulColorMask = 0; +static INDEX _ctAllMipVx = 0; +static INDEX _ctAllSrfVx = 0; +static BOOL _bFlatFill = FALSE; +static SLONG _slLR=0, _slLG=0, _slLB=0; +static SLONG _slAR=0, _slAG=0, _slAB=0; +static const __int64 mmRounder = 0x007F007F007F007F; +static const __int64 mmF000 = 0x00FF000000000000; + +// viewer absolute and object space projection +static FLOAT3D _vViewer; +static FLOAT3D _vViewerObj; +static FLOAT3D _vLightObj; + +// some constants for asm float ops +static const FLOAT f2 = 2.0f; +static const FLOAT f05 = 0.5f; + + +// convinient routine for timing of texture setting +static __forceinline void SetCurrentTexture( CTextureData *ptd, INDEX iFrame) +{ + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_SETTEXTURE); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_SETTEXTURE); + if( ptd==NULL || _bFlatFill) gfxDisableTexture(); + else ptd->SetAsCurrent(iFrame); + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_SETTEXTURE); +} + + +// reset model vertex buffers +static void ResetVertexArrays(void) +{ + _avtxMipBase.PopAll(); + _atexMipBase.PopAll(); + _acolMipBase.PopAll(); + _anorMipBase.PopAll(); + + _avtxSrfBase.PopAll(); + _anorSrfBase.PopAll(); + _atexSrfBase.PopAll(); + _acolSrfBase.PopAll(); + + _atexMipFogy.PopAll(); + _ashdMipFogy.PopAll(); + _atx1MipHaze.PopAll(); + _ashdMipHaze.PopAll(); +} + + +// reset and free all arrays +extern void Models_ClearVertexArrays(void) +{ + _avtxMipBase.Clear(); + _atexMipBase.Clear(); + _acolMipBase.Clear(); + _anorMipBase.Clear(); + + _atexMipFogy.Clear(); + _ashdMipFogy.Clear(); + _atx1MipHaze.Clear(); + _ashdMipHaze.Clear(); + + _avtxSrfBase.Clear(); + _anorSrfBase.Clear(); + _atexSrfBase.Clear(); + _acolSrfBase.Clear(); + + _aooqMipShad.Clear(); + _atx4SrfShad.Clear(); +} + + +struct Triangle { + INDEX i0; + INDEX i1; + INDEX i2; + BOOL bDone; + Triangle(void) : bDone(FALSE) {}; + void Clear(void) { bDone = FALSE; }; + void Rotate(void) { const INDEX i=i0; + i0=i1; i1=i2; i2=i; } +}; + +static INDEX _ctSurfaces = 0; +static INDEX _ctTriangles = 0; +static INDEX _ctStrips = 0; +static INDEX _ctMaxStripLen = 0; +static INDEX _ctMinStripLen = 10000; +static FLOAT _fTriPerStrip = 0.0f; +static FLOAT _fTriPerSurface = 0.0f; +static FLOAT _fStripPerSurface = 0.0f; +static INDEX _ctStripStartFailed = 0; + + +static CStaticArray _atri; +static CStaticArray _atriDone; +static void GetNeighbourTriangleVertices(Triangle *ptri, INDEX &i1, INDEX &i2) +{ + Triangle &triA = *ptri; + for( INDEX itri=0; itri<_atri.Count(); itri++) { + Triangle &triB = _atri[itri]; + if( triB.bDone) continue; + i1=triA.i1; i2=triA.i2; + if (i2 == triB.i0 && i1 == triB.i1) return; + if (i2 == triB.i1 && i1 == triB.i2) return; + if (i2 == triB.i2 && i1 == triB.i0) return; + triA.Rotate(); + i1=triA.i1; i2=triA.i2; + if (i2 == triB.i0 && i1 == triB.i1) return; + if (i2 == triB.i1 && i1 == triB.i2) return; + if (i2 == triB.i2 && i1 == triB.i0) return; + triA.Rotate(); + i1=triA.i1; i2=triA.i2; + if (i2 == triB.i0 && i1 == triB.i1) return; + if (i2 == triB.i1 && i1 == triB.i2) return; + if (i2 == triB.i2 && i1 == triB.i0) return; + triA.Rotate(); + } + // none found + i1 = -1; + i2 = -1; + _ctStripStartFailed++; +} + + +static Triangle *GetNextStripTriangle(INDEX &i1, INDEX &i2, INDEX iTriInStrip) +{ + for( INDEX itri=0; itri<_atri.Count(); itri++) { + Triangle &tri = _atri[itri]; + if( tri.bDone) continue; + if( iTriInStrip%2 == 0) { + if (i1==tri.i0 && i2==tri.i1) { i1=i2; i2=tri.i2; return &tri;} tri.Rotate(); + if (i1==tri.i0 && i2==tri.i1) { i1=i2; i2=tri.i2; return &tri;} tri.Rotate(); + if (i1==tri.i0 && i2==tri.i1) { i1=i2; i2=tri.i2; return &tri;} tri.Rotate(); + } else { + if (i2==tri.i0 && i1==tri.i1) { i1=i2; i2=tri.i2; return &tri;} tri.Rotate(); + if (i2==tri.i0 && i1==tri.i1) { i1=i2; i2=tri.i2; return &tri;} tri.Rotate(); + if (i2==tri.i0 && i1==tri.i1) { i1=i2; i2=tri.i2; return &tri;} tri.Rotate(); + } + } + i1 = -1; + i2 = -1; + return NULL; +} + +static Triangle *GetFirstTriangle(void) +{ + for( INDEX itri=0; itri<_atri.Count(); itri++) { + Triangle &tri1 = _atri[itri]; + if( tri1.bDone) continue; + return &tri1; + } + ASSERTALWAYS( "WTF?"); + return &_atri[0]; +} + + +static void PrepareSurfaceElements( ModelMipInfo &mmi, MappingSurface &ms) +{ + _ctSurfaces++; + // find total number of triangles + INDEX ctTriangles = 0; + {for( INDEX iipo=0; iipo=ms.ms_aiPolygons.Count()); + + _ctTriangles += ctTriangles; + // allocate that much triangles + _atri.Clear(); + _atri.New(ctTriangles); + _atriDone.Clear(); + _atriDone.New(ctTriangles); + + // put all triangles there (do tri-fans) -> should do tri-strips ? !!!! + INDEX iTriangle = 0; + {for( INDEX iipo=0; iipomtv_iSurfaceVx; + tri.i1 = mp.mp_PolygonVertices[ivx-1].mpv_ptvTextureVertex->mtv_iSurfaceVx; + tri.i2 = mp.mp_PolygonVertices[ivx-0].mpv_ptvTextureVertex->mtv_iSurfaceVx; + }} + }} + + // start with first triangle + INDEX ctTrianglesDone = 0; + Triangle *ptri = &_atri[0]; + INDEX i1, i2; + GetNeighbourTriangleVertices(ptri, i1, i2); + //_RPT2(_CRT_WARN, "Begin: i1=%d i2=%d\n", i1,i2); + + _ctStrips++; + INDEX ctTriPerStrip = 0; + // repeat + FOREVER { + // put current triangles into done triangles + _atriDone[ctTrianglesDone++] = *ptri; + //_RPT3(_CRT_WARN, "Added: %d %d %d\n", ptri->i0, ptri->i1, ptri->i2); + ptri->bDone = TRUE; + ctTriPerStrip++; + + // stop if all triangles are done + if( ctTrianglesDone>=ctTriangles) break; + + // get some neighbour of current triangle + Triangle *ptriNext = NULL; + extern INDEX mdl_bCreateStrips; + if( mdl_bCreateStrips) { + ptriNext = GetNextStripTriangle( i1, i2, ctTriPerStrip); + //_RPT2(_CRT_WARN, "Next: i1=%d i2=%d\n", i1,i2); + } + // if no neighbour + if( ptriNext==NULL) { + // get first one that is not done + ptriNext = GetFirstTriangle(); + GetNeighbourTriangleVertices( ptriNext, i1, i2); + //_RPT2(_CRT_WARN, "Rebegin: i1=%d i2=%d\n", i1,i2); + _ctMaxStripLen = Max( _ctMaxStripLen, ctTriPerStrip); + _ctMinStripLen = Max( _ctMinStripLen, ctTriPerStrip); + _ctStrips++; + ctTriPerStrip = 0; + } + // take that as current triangle + ptri = ptriNext; + } + _ctMaxStripLen = Max( _ctMaxStripLen, ctTriPerStrip); + _ctMinStripLen = Min( _ctMinStripLen, ctTriPerStrip); + ASSERT( ctTrianglesDone==ctTriangles); + + // create elements + ms.ms_ctSrfEl = ctTriangles*3; + INDEX *paiElements = mmi.mmpi_aiElements.Push(ms.ms_ctSrfEl); + // dump all triangles + //_RPT0(_CRT_WARN, "Result:\n"); + INDEX iel = 0; + {for( INDEX itri=0; itrimip remapping tables for vertices + mmi.mmpi_ctMipVx = ctMipVx; + mmi.mmpi_auwMipToMdl.Clear(); + mmi.mmpi_auwMipToMdl.New(ctMipVx); + CStaticArray aiMdlToMip; + aiMdlToMip.New(ctMdlVx); + INDEX iMipVx = 0; + for( iMdlVx=0; iMdlVx &amtv = mmi.mmpi_TextureVertices; + mmi.mmpi_ctSrfVx = amtv.Count(); + + // allocate surface vertex arrays + mmi.mmpi_auwSrfToMip.Clear(); + mmi.mmpi_avmexTexCoord.Clear(); + mmi.mmpi_auwSrfToMip.New(mmi.mmpi_ctSrfVx); + mmi.mmpi_avmexTexCoord.New(mmi.mmpi_ctSrfVx); + + // alloc bump mapping vectors only if needed + mmi.mmpi_avBumpU.Clear(); + mmi.mmpi_avBumpV.Clear(); + + // count surfaces + INDEX ctSurfaces = 0; + {FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) ctSurfaces++; } + // sort surfaces by diffuse type + qsort( &mmi.mmpi_MappingSurfaces[0], ctSurfaces, sizeof(MappingSurface), qsort_CompareSurfaceDiffuseTypes); + + // initialize array for all surfaces' elements + mmi.mmpi_aiElements.Clear(); + + // for each surface + INDEX iSrfVx = 0; + INDEX iSrfEl = 0; + {FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) + { + MappingSurface &ms = *itms; + // if it is empty surface + if( ms.ms_aiPolygons.Count()==0) { + // just clear all its data + ms.ms_ctSrfVx = 0; + ms.ms_ctSrfEl = 0; + ms.ms_iSrfVx0 = MAX_SLONG; // set to invalid to catch eventual bugs + // proceed to next surface + continue; + } + + // determine surface and mip model rendering type (write to z-buffer or not) + if( !(ms.ms_ulRenderingFlags&SRF_DIFFUSE) + || ms.ms_sttTranslucencyType==STT_TRANSLUCENT + || ms.ms_sttTranslucencyType==STT_ADD + || ms.ms_sttTranslucencyType==STT_MULTIPLY) { + ms.ms_ulRenderingFlags &= ~SRF_OPAQUE; + mmi.mmpi_ulLayerFlags &= ~MMI_OPAQUE; + } else { + ms.ms_ulRenderingFlags |= SRF_OPAQUE; + mmi.mmpi_ulLayerFlags &= ~MMI_TRANSLUCENT; + } + // accumulate flags + mmi.mmpi_ulLayerFlags |= ms.ms_ulRenderingFlags; + + // assign surface vertex numbers + ms.ms_iSrfVx0 = iSrfVx; + ms.ms_ctSrfVx = ms.ms_aiTextureVertices.Count(); + // for each vertex + for( INDEX iVxInSurface=0; iVxInSurface should do tri-strips ? !!!! + INDEX iel = 0; + for( iipo=0; iipomtv_iSurfaceVx; + ppp.ppp_auwElements[iel++] = mp.mp_PolygonVertices[ivx-1].mpv_ptvTextureVertex->mtv_iSurfaceVx; + ppp.ppp_auwElements[iel++] = mp.mp_PolygonVertices[ivx-0].mpv_ptvTextureVertex->mtv_iSurfaceVx; + } + } + } +} + + +extern void PrepareModelForRendering( CModelData &md) +{ + // do nothing, if the model has already been initialized for rendering + if( md.md_bPreparedForRendering) return; + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_PREPAREFORRENDERING); + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_TRISTRIPMODELS); + // prepare each mip model + for( INDEX iMip=0; iMip0); + // choose rendering mode + extern INDEX mdl_bShowStrips; + if( _bMultiPlayer) mdl_bShowStrips = 0; // don't allow in multiplayer mode! + if( !mdl_bShowStrips) { + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_DRAWELEMENTS); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_DRAWELEMENTS, ctElem/3); + _pGfx->gl_ctModelTriangles += ctElem/3; + gfxDrawElements( ctElem, pai); + extern INDEX mdl_bShowTriangles; + if( _bMultiPlayer) mdl_bShowTriangles = 0; // don't allow in multiplayer mode! + if( mdl_bShowTriangles) { + gfxSetConstantColor(C_YELLOW|222); // this also disables color array + gfxPolygonMode(GFX_LINE); + gfxDrawElements( ctElem, pai); + gfxPolygonMode(GFX_FILL); + gfxEnableColorArray(); // need to re-enable color array + } // done + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_DRAWELEMENTS); + } + // show strips + else if( _eAPI==GAT_OGL) { + DrawStrips( ctElem, pai); + OGL_CHECKERROR; + } +} + + +// returns if any type of translucent surface was required +static void SetRenderingParameters( SurfaceTranslucencyType stt) +{ + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_ONESIDE_GLSETUP); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_ONESIDE_GLSETUP); + + if( stt==STT_TRANSLUCENT || (_bForceTranslucency && ((stt==STT_OPAQUE) || (stt==STT_TRANSPARENT)))) { + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + gfxDisableAlphaTest(); + gfxDisableDepthWrite(); + } else if( stt==STT_OPAQUE) { + gfxDisableAlphaTest(); + gfxDisableBlend(); + gfxEnableDepthWrite(); + } else if( stt==STT_TRANSPARENT) { + gfxDisableBlend(); + gfxEnableAlphaTest(); + gfxEnableDepthWrite(); + } else if( stt==STT_ADD) { + gfxEnableBlend(); + gfxBlendFunc( GFX_SRC_ALPHA, GFX_ONE); + gfxDisableAlphaTest(); + gfxDisableDepthWrite(); + } else if( stt==STT_MULTIPLY) { + gfxEnableBlend(); + gfxBlendFunc( GFX_ZERO, GFX_INV_SRC_COLOR); + gfxDisableAlphaTest(); + gfxDisableDepthWrite(); + } else { + ASSERTALWAYS( "Unsupported model rendering mode."); + } + // all done + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_ONESIDE_GLSETUP); +} + + +// render one side of a surface (return TRUE if any type of translucent surface has been rendered) +static void RenderOneSide( CRenderModel &rm, BOOL bBackSide, ULONG ulLayerFlags) +{ + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_ONESIDE); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_ONESIDE); + _icol = 0; + + // set face culling + if( bBackSide) { + if( !(_ulMipLayerFlags&SRF_DOUBLESIDED)) { + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_ONESIDE); + return; + } else gfxCullFace(GFX_FRONT); + } else gfxCullFace(GFX_BACK); + + // start with invalid rendering parameters + SurfaceTranslucencyType sttLast = STT_INVALID; + + // for each surface in current mip model + INDEX iStartElem=0; + INDEX ctElements=0; + ModelMipInfo &mmi = *rm.rm_pmmiMip; + {FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) + { + const MappingSurface &ms = *itms; + const ULONG ulFlags = ms.ms_ulRenderingFlags; + // end rendering if surface is invisible or empty - these are the last surfaces in surface list + if( (ulFlags&SRF_INVISIBLE) || ms.ms_ctSrfVx==0) break; + // skip surface if ... + if( !(ulFlags&ulLayerFlags) // not in this layer, + || (bBackSide && !(ulFlags&SRF_DOUBLESIDED)) // rendering back side and surface is not double sided, + || !(_ulColorMask&ms.ms_ulOnColor) // not on or off. + || (_ulColorMask&ms.ms_ulOffColor)) { + if( ctElements>0) FlushElements( ctElements, &mmi.mmpi_aiElements[iStartElem]); + iStartElem+= ctElements+ms.ms_ctSrfEl; + ctElements = 0; + continue; + } + + // if should set parameters + if( ulLayerFlags&SRF_DIFFUSE) { + // get rendering parameters + SurfaceTranslucencyType stt = ms.ms_sttTranslucencyType; + // if surface uses rendering parameters different than last one + if( sttLast!=stt) { + // set up new API states + if( ctElements>0) FlushElements( ctElements, &mmi.mmpi_aiElements[iStartElem]); + SetRenderingParameters(stt); + sttLast=stt; + iStartElem+= ctElements; + ctElements = 0; + } + } // batch the surface polygons for rendering + ctElements += ms.ms_ctSrfEl; + }} + // flush leftovers + if( ctElements>0) FlushElements( ctElements, &mmi.mmpi_aiElements[iStartElem]); + // all done + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_ONESIDE); +} + + + +// render model thru colors +static void RenderColors( CRenderModel &rm) +{ + // only if required + if( rm.rm_rtRenderType&RT_NO_POLYGON_FILL) return; + _icol = 0; + + // parameters + gfxCullFace(GFX_BACK); + gfxDisableBlend(); + gfxDisableAlphaTest(); + gfxDisableTexture(); + gfxEnableDepthWrite(); + + gfxSetVertexArray( &_avtxSrfBase[0], _avtxSrfBase.Count()); + gfxSetColorArray( &_acolSrfBase[0]); + + // for each surface in current mip model + INDEX iStartElem=0; + INDEX ctElements=0; + ModelMipInfo &mmi = *rm.rm_pmmiMip; + FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) + { + const MappingSurface &ms = *itms; + // skip if surface is invisible or empty + if( (ms.ms_ulRenderingFlags&SRF_INVISIBLE) || ms.ms_ctSrfVx==0 + || !(_ulColorMask&ms.ms_ulOnColor) || (_ulColorMask&ms.ms_ulOffColor)) { + if( ctElements>0) FlushElements( ctElements, &mmi.mmpi_aiElements[iStartElem]); + iStartElem+= ctElements+ms.ms_ctSrfEl; + ctElements = 0; + continue; + } + // set surface color + COLOR srfCol; + extern INDEX GetBit( ULONG ulSource); + if( rm.rm_rtRenderType&RT_ON_COLORS) { + srfCol = PaletteColorValues[GetBit(ms.ms_ulOnColor)]|CT_OPAQUE; + } else if( rm.rm_rtRenderType&RT_OFF_COLORS) { + srfCol = PaletteColorValues[GetBit(ms.ms_ulOffColor)]|CT_OPAQUE; + } else { + srfCol = ms.ms_colColor|CT_OPAQUE; + } + // batch the surface polygons for rendering + GFXColor glcol(srfCol); + pcolSrfBase = &_acolSrfBase[ms.ms_iSrfVx0]; + for( INDEX iSrfVx=0; iSrfVx0) FlushElements( ctElements, &mmi.mmpi_aiElements[iStartElem]); +} + + +// render model as wireframe +static void RenderWireframe(CRenderModel &rm) +{ + // only if required + if( !(rm.rm_rtRenderType&RT_WIRE_ON) && !(rm.rm_rtRenderType&RT_HIDDEN_LINES)) return; + _icol = 0; + + // parameters + gfxPolygonMode(GFX_LINE); + gfxDisableBlend(); + gfxDisableAlphaTest(); + gfxDisableTexture(); + gfxDisableDepthTest(); + + gfxSetVertexArray( &_avtxSrfBase[0], _avtxSrfBase.Count()); + gfxSetColorArray( &_acolSrfBase[0]); + + COLOR colWire = _mrpModelRenderPrefs.GetInkColor()|CT_OPAQUE; + ModelMipInfo &mmi = *rm.rm_pmmiMip; + + // first, render hidden lines (if required) + if( rm.rm_rtRenderType&RT_HIDDEN_LINES) + { + gfxCullFace(GFX_FRONT); + INDEX iStartElem=0; + INDEX ctElements=0; + // for each surface in current mip model + FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) { + const MappingSurface &ms = *itms; + // skip if surface is invisible or empty + if( (ms.ms_ulRenderingFlags&SRF_INVISIBLE) || ms.ms_ctSrfVx==0) { + if( ctElements>0) FlushElements( ctElements, &mmi.mmpi_aiElements[iStartElem]); + iStartElem+= ctElements+ms.ms_ctSrfEl; + ctElements = 0; + continue; + } + GFXColor glcol( colWire^0x80808080); + pcolSrfBase = &_acolSrfBase[ms.ms_iSrfVx0]; + for( INDEX iSrfVx=0; iSrfVx0) FlushElements( ctElements, &mmi.mmpi_aiElements[iStartElem]); + gfxCullFace(GFX_BACK); + } + // then, render visible lines (if required) + if( rm.rm_rtRenderType&RT_WIRE_ON) + { + gfxCullFace(GFX_BACK); + INDEX iStartElem=0; + INDEX ctElements=0; + // for each surface in current mip model + FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) { + const MappingSurface &ms = *itms; + // done if surface is invisible or empty + if( (ms.ms_ulRenderingFlags&SRF_INVISIBLE) || ms.ms_ctSrfVx==0) { + if( ctElements>0) FlushElements( ctElements, &mmi.mmpi_aiElements[iStartElem]); + iStartElem+= ctElements+ms.ms_ctSrfEl; + ctElements = 0; + continue; + } + GFXColor glcol(colWire); + pcolSrfBase = &_acolSrfBase[ms.ms_iSrfVx0]; + for( INDEX iSrfVx=0; iSrfVx0) FlushElements( ctElements, &mmi.mmpi_aiElements[iStartElem]); + } + // all done + gfxPolygonMode(GFX_FILL); +} + + + + +// attenuate alphas in base surface array with attenuation array +static void AttenuateAlpha( const UBYTE *pshdMip, const INDEX ctVertices) +{ + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_ATTENUATE_SURF); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_ATTENUATE_SURF, _ctAllSrfVx); + for( INDEX iSrfVx=0; iSrfVxmmpi_auwMipToMdl[0]; + SWORD *pswMipCol = (SWORD*)&pcolMipBase[_ctAllMipVx>>1]; + + // if 16 bit compression + if( rm.rm_pmdModelData->md_Flags & MF_COMPRESSED_16BIT) + { + // if no lerping + const ModelFrameVertex16 *pFrame0 = rm.rm_pFrame16_0; + const ModelFrameVertex16 *pFrame1 = rm.rm_pFrame16_1; + if( pFrame0==pFrame1) + { +#if ASMOPT == 1 + // for each vertex in mip + const SLONG fixLerpRatio = FloatToInt(fLerpRatio*256.0f); // fix 8:8 + SLONG slTmp1, slTmp2, slTmp3; + __asm { + mov edi,D [pvtxMipBase] + mov ebx,D [pswMipCol] + xor ecx,ecx +vtxLoop16: + push ecx + mov esi,D [puwMipToMdl] + movzx eax,W [esi+ecx*2] + mov esi,D [pFrame0] + lea esi,[esi+eax*8] + // store vertex + movsx eax,W [esi]ModelFrameVertex16.mfv_SWPoint[0] + movsx ecx,W [esi]ModelFrameVertex16.mfv_SWPoint[2] + movsx edx,W [esi]ModelFrameVertex16.mfv_SWPoint[4] + mov D [slTmp1],eax + mov D [slTmp2],ecx + mov D [slTmp3],edx + fild D [slTmp1] + fsub D [fOffsetX] + fmul D [fStretchX] + fild D [slTmp2] + fsub D [fOffsetY] + fmul D [fStretchY] + fild D [slTmp3] + fsub D [fOffsetZ] + fmul D [fStretchZ] + fxch st(2) + fstp D [edi]GFXVertex3.x + fstp D [edi]GFXVertex3.y + fstp D [edi]GFXVertex3.z + // determine normal + movzx eax,B [esi]ModelFrameVertex16.mfv_ubNormH + movzx edx,B [esi]ModelFrameVertex16.mfv_ubNormP + mov esi,D [pfSinTable] + fld D [esi+eax*4 +0] + fmul D [esi+edx*4 +64*4] + fld D [esi+eax*4 +64*4] + fmul D [esi+edx*4 +64*4] + fxch st(1) + fstp D [slTmp1] + fstp D [slTmp3] + mov eax,D [slTmp1] + mov ecx,D [slTmp3] + xor eax,0x80000000 + xor ecx,0x80000000 + mov D [slTmp1],eax + mov D [slTmp3],ecx + // determine vertex shade + fld D [slTmp1] + fmul D [fLightObjX] + fld D [esi+edx*4 +0] + fmul D [fLightObjY] + fld D [slTmp3] + fmul D [fLightObjZ] + fxch st(2) + faddp st(1),st(0) + faddp st(1),st(0) + fistp D [ebx] + // store normal (if needed) + cmp D [bKeepNormals],0 + je vtxNext16 + mov ecx,D [esp] + imul ecx,3*4 + add ecx,D [pnorMipBase] + mov eax,D [slTmp1] + mov edx,D [esi+edx*4 +0] + mov esi,D [slTmp3] + mov D [ecx]GFXNormal.nx, eax + mov D [ecx]GFXNormal.ny, edx + mov D [ecx]GFXNormal.nz, esi + // advance to next vertex +vtxNext16: + pop ecx + add edi,3*4 + add ebx,1*2 + inc ecx + cmp ecx,D [_ctAllMipVx] + jl vtxLoop16 + } +#else + // for each vertex in mip + for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) { + // get destination for unpacking + const INDEX iMdlVx = puwMipToMdl[iMipVx]; + const ModelFrameVertex16 &mfv0 = pFrame0[iMdlVx]; + // store vertex + GFXVertex3 &vtx = pvtxMipBase[iMipVx]; + vtx.x = (mfv0.mfv_SWPoint(1) -fOffsetX) *fStretchX; + vtx.y = (mfv0.mfv_SWPoint(2) -fOffsetY) *fStretchY; + vtx.z = (mfv0.mfv_SWPoint(3) -fOffsetZ) *fStretchZ; + // determine normal + const FLOAT fSinH0 = pfSinTable[mfv0.mfv_ubNormH]; + const FLOAT fSinP0 = pfSinTable[mfv0.mfv_ubNormP]; + const FLOAT fCosH0 = pfCosTable[mfv0.mfv_ubNormH]; + const FLOAT fCosP0 = pfCosTable[mfv0.mfv_ubNormP]; + const FLOAT fNX = -fSinH0*fCosP0; + const FLOAT fNY = +fSinP0; + const FLOAT fNZ = -fCosH0*fCosP0; + // store vertex shade + pswMipCol[iMipVx] = FloatToInt(fNX*fLightObjX + fNY*fLightObjY + fNZ*fLightObjZ); + // store normal (if needed) + if( bKeepNormals) { + pnorMipBase[iMipVx].nx = fNX; + pnorMipBase[iMipVx].ny = fNY; + pnorMipBase[iMipVx].nz = fNZ; + } + } +#endif + } + // if lerping + else + { +#if ASMOPT == 1 + // for each vertex in mip + const SLONG fixLerpRatio = FloatToInt(fLerpRatio*256.0f); // fix 8:8 + SLONG slTmp1, slTmp2, slTmp3; + __asm { + mov edi,D [pvtxMipBase] + mov ebx,D [pswMipCol] + xor ecx,ecx +vtxLoop16L: + push ecx + push ebx + mov esi,D [puwMipToMdl] + movzx ebx,W [esi+ecx*2] + mov esi,D [pFrame0] + mov ecx,D [pFrame1] + // lerp vertex + movsx eax,W [esi+ebx*8]ModelFrameVertex16.mfv_SWPoint[0] + movsx edx,W [ecx+ebx*8]ModelFrameVertex16.mfv_SWPoint[0] + sub edx,eax + imul edx,D [fixLerpRatio] + sar edx,8 + add eax,edx + mov D [slTmp1],eax + movsx eax,W [esi+ebx*8]ModelFrameVertex16.mfv_SWPoint[2] + movsx edx,W [ecx+ebx*8]ModelFrameVertex16.mfv_SWPoint[2] + sub edx,eax + imul edx,D [fixLerpRatio] + sar edx,8 + add eax,edx + mov D [slTmp2],eax + movsx eax,W [esi+ebx*8]ModelFrameVertex16.mfv_SWPoint[4] + movsx edx,W [ecx+ebx*8]ModelFrameVertex16.mfv_SWPoint[4] + sub edx,eax + imul edx,D [fixLerpRatio] + sar edx,8 + add eax,edx + mov D [slTmp3],eax + // store vertex + fild D [slTmp1] + fsub D [fOffsetX] + fmul D [fStretchX] + fild D [slTmp2] + fsub D [fOffsetY] + fmul D [fStretchY] + fild D [slTmp3] + fsub D [fOffsetZ] + fmul D [fStretchZ] + fxch st(2) + fstp D [edi]GFXVertex3.x + fstp D [edi]GFXVertex3.y + fstp D [edi]GFXVertex3.z + // load normals + movzx eax,B [esi+ebx*8]ModelFrameVertex16.mfv_ubNormH + movzx edx,B [esi+ebx*8]ModelFrameVertex16.mfv_ubNormP + mov esi,D [pfSinTable] + fld D [esi+eax*4 +0] + fmul D [esi+edx*4 +64*4] + fld D [esi+edx*4 +0] + fld D [esi+eax*4 +64*4] + fmul D [esi+edx*4 +64*4] // fCosH0*fCosP0, fSinP0, fSinH0*fCosP0 + movzx eax,B [ecx+ebx*8]ModelFrameVertex16.mfv_ubNormH + movzx edx,B [ecx+ebx*8]ModelFrameVertex16.mfv_ubNormP + fld D [esi+eax*4 +0] + fmul D [esi+edx*4 +64*4] + fld D [esi+edx*4 +0] + fld D [esi+eax*4 +64*4] + fmul D [esi+edx*4 +64*4] // fCosH1*fCosP1, fSinP1, fSinH1*fCosP1, fCosH0*fCosP0, fSinP0, fSinH0*fCosP0 + // lerp normals + fxch st(5) // SH0CP0, SP1, SH1CP1, CH0CP0, SP0, CH1CP1 + fsub st(2),st(0) + fxch st(4) // SP0, SP1, SH1CP1-SH0CP0, CH0CP0, SH0CP0, CH1CP1 + fsub st(1),st(0) // SP0, SP1-SP0, SH1CP1-SH0CP0, CH0CP0, SH0CP0, CH1CP1 + fxch st(3) // CH0CP0, SP1-SP0, SH1CP1-SH0CP0, SP0, SH0CP0, CH1CP1 + fsub st(5),st(0) // CH0CP0, SP1-SP0, SH1CP1-SH0CP0, SP0, SH0CP0, CH1CP1-CH0CP0 + fxch st(2) // SH1CP1-SH0CP0, SP1-SP0, CH0CP0, SP0, SH0CP0, CH1CP1-CH0CP0 + fmul D [fLerpRatio] + fxch st(1) // SP1-SP0, lSH1CP1, CH0CP0, SP0, SH0CP0, CH1CP1-CH0CP0 + fmul D [fLerpRatio] + fxch st(5) // CH1CP1-CH0CP0, lSH1CP1, CH0CP0, SP0, SH0CP0, lSP1SP0 + fmul D [fLerpRatio] + fxch st(1) // lSH1CP1, lCH1CP1, CH0CP0, SP0, SH0CP0, lSP1SP0 + faddp st(4),st(0) // lCH1CP1, CH0CP0, SP0, fNX, lSP1SP0 + fxch st(2) // SP0, CH0CP0, lCH1CP1, fNX, lSP1SP0 + faddp st(4),st(0) // CH0CP0, lCH1CP1, fNX, fNY + faddp st(1),st(0) // -fNZ, -fNX, fNY + fxch st(2) // fNY, -fNX, -fNZ + fstp D [slTmp2] + fstp D [slTmp1] + fstp D [slTmp3] + pop ebx + mov eax,D [slTmp1] + mov ecx,D [slTmp3] + xor eax,0x80000000 + xor ecx,0x80000000 + mov D [slTmp1],eax + mov D [slTmp3],ecx + // determine vertex shade + fld D [slTmp1] + fmul D [fLightObjX] + fld D [slTmp2] + fmul D [fLightObjY] + fld D [slTmp3] + fmul D [fLightObjZ] + fxch st(2) + faddp st(1),st(0) + faddp st(1),st(0) + fistp D [ebx] + // store lerped normal (if needed) + cmp D [bKeepNormals],0 + je vtxNext16L + mov ecx,D [esp] + imul ecx,3*4 + add ecx,D [pnorMipBase] + mov eax,D [slTmp1] + mov edx,D [slTmp2] + mov esi,D [slTmp3] + mov D [ecx]GFXNormal.nx, eax + mov D [ecx]GFXNormal.ny, edx + mov D [ecx]GFXNormal.nz, esi + // advance to next vertex +vtxNext16L: + pop ecx + add edi,3*4 + add ebx,1*2 + inc ecx + cmp ecx,D [_ctAllMipVx] + jl vtxLoop16L + } +#else + // for each vertex in mip + for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) { + // get destination for unpacking + const INDEX iMdlVx = puwMipToMdl[iMipVx]; + const ModelFrameVertex16 &mfv0 = pFrame0[iMdlVx]; + const ModelFrameVertex16 &mfv1 = pFrame1[iMdlVx]; + // store lerped vertex + GFXVertex3 &vtx = pvtxMipBase[iMipVx]; + vtx.x = (Lerp( (FLOAT)mfv0.mfv_SWPoint(1), (FLOAT)mfv1.mfv_SWPoint(1), fLerpRatio) -fOffsetX) * fStretchX; + vtx.y = (Lerp( (FLOAT)mfv0.mfv_SWPoint(2), (FLOAT)mfv1.mfv_SWPoint(2), fLerpRatio) -fOffsetY) * fStretchY; + vtx.z = (Lerp( (FLOAT)mfv0.mfv_SWPoint(3), (FLOAT)mfv1.mfv_SWPoint(3), fLerpRatio) -fOffsetZ) * fStretchZ; + // determine lerped normal + const FLOAT fSinH0 = pfSinTable[mfv0.mfv_ubNormH]; const FLOAT fSinH1 = pfSinTable[mfv1.mfv_ubNormH]; + const FLOAT fSinP0 = pfSinTable[mfv0.mfv_ubNormP]; const FLOAT fSinP1 = pfSinTable[mfv1.mfv_ubNormP]; + const FLOAT fCosH0 = pfCosTable[mfv0.mfv_ubNormH]; const FLOAT fCosH1 = pfCosTable[mfv1.mfv_ubNormH]; + const FLOAT fCosP0 = pfCosTable[mfv0.mfv_ubNormP]; const FLOAT fCosP1 = pfCosTable[mfv1.mfv_ubNormP]; + const FLOAT fNX = Lerp( -fSinH0*fCosP0, -fSinH1*fCosP1, fLerpRatio); + const FLOAT fNY = Lerp( +fSinP0, +fSinP1, fLerpRatio); + const FLOAT fNZ = Lerp( -fCosH0*fCosP0, -fCosH1*fCosP1, fLerpRatio); + // store vertex shade + pswMipCol[iMipVx] = FloatToInt(fNX*fLightObjX + fNY*fLightObjY + fNZ*fLightObjZ); + // store lerped normal (if needed) + if( bKeepNormals) { + pnorMipBase[iMipVx].nx = fNX; + pnorMipBase[iMipVx].ny = fNY; + pnorMipBase[iMipVx].nz = fNZ; + } + } +#endif + + } + } + // if 8 bit compression + else + { + const ModelFrameVertex8 *pFrame0 = rm.rm_pFrame8_0; + const ModelFrameVertex8 *pFrame1 = rm.rm_pFrame8_1; + // if no lerping + if( pFrame0==pFrame1) + { +#if ASMOPT == 1 + // for each vertex in mip + const SLONG fixLerpRatio = FloatToInt(fLerpRatio*256.0f); // fix 8:8 + SLONG slTmp1, slTmp2, slTmp3; + __asm { + mov edi,D [pvtxMipBase] + mov ebx,D [pswMipCol] + xor ecx,ecx +vtxLoop8: + push ecx + mov esi,D [puwMipToMdl] + movzx eax,W [esi+ecx*2] + mov esi,D [pFrame0] + lea esi,[esi+eax*4] + // store vertex + movsx eax,B [esi]ModelFrameVertex8.mfv_SBPoint[0] + movsx ecx,B [esi]ModelFrameVertex8.mfv_SBPoint[1] + movsx edx,B [esi]ModelFrameVertex8.mfv_SBPoint[2] + mov D [slTmp1],eax + mov D [slTmp2],ecx + mov D [slTmp3],edx + fild D [slTmp1] + fsub D [fOffsetX] + fmul D [fStretchX] + fild D [slTmp2] + fsub D [fOffsetY] + fmul D [fStretchY] + fild D [slTmp3] + fsub D [fOffsetZ] + fmul D [fStretchZ] + fxch st(2) + fstp D [edi]GFXVertex3.x + fstp D [edi]GFXVertex3.y + fstp D [edi]GFXVertex3.z + // determine normal + movzx eax,B [esi]ModelFrameVertex8.mfv_NormIndex + lea esi,[eax*2+eax] + // determine vertex shade + fld D [avGouraudNormals+ esi*4 +0] + fmul D [fLightObjX] + fld D [avGouraudNormals+ esi*4 +4] + fmul D [fLightObjY] + fld D [avGouraudNormals+ esi*4 +8] + fmul D [fLightObjZ] + fxch st(2) + faddp st(1),st(0) + faddp st(1),st(0) + fistp D [ebx] + // store lerped normal (if needed) + cmp D [bKeepNormals],0 + je vtxNext8 + mov ecx,D [esp] + imul ecx,3*4 + add ecx,D [pnorMipBase] + mov eax,D [avGouraudNormals+ esi*4 +0] + mov edx,D [avGouraudNormals+ esi*4 +4] + mov esi,D [avGouraudNormals+ esi*4 +8] + mov D [ecx]GFXNormal.nx, eax + mov D [ecx]GFXNormal.ny, edx + mov D [ecx]GFXNormal.nz, esi + // advance to next vertex +vtxNext8: + pop ecx + add edi,3*4 + add ebx,1*2 + inc ecx + cmp ecx,D [_ctAllMipVx] + jl vtxLoop8 + } +#else + // for each vertex in mip + for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) { + // get destination for unpacking + const INDEX iMdlVx = puwMipToMdl[iMipVx]; + const ModelFrameVertex8 &mfv0 = pFrame0[iMdlVx]; + // store vertex + GFXVertex3 &vtx = pvtxMipBase[iMipVx]; + vtx.x = (mfv0.mfv_SBPoint(1) -fOffsetX) * fStretchX; + vtx.y = (mfv0.mfv_SBPoint(2) -fOffsetY) * fStretchY; + vtx.z = (mfv0.mfv_SBPoint(3) -fOffsetZ) * fStretchZ; + // determine normal + const FLOAT3D &vNormal0 = avGouraudNormals[mfv0.mfv_NormIndex]; + const FLOAT fNX = vNormal0(1); + const FLOAT fNY = vNormal0(2); + const FLOAT fNZ = vNormal0(3); + // store vertex shade + pswMipCol[iMipVx] = FloatToInt(fNX*fLightObjX + fNY*fLightObjY + fNZ*fLightObjZ); + // store lerped normal (if needed) + if( bKeepNormals) { + pnorMipBase[iMipVx].nx = fNX; + pnorMipBase[iMipVx].ny = fNY; + pnorMipBase[iMipVx].nz = fNZ; + } + } +#endif + } + // if lerping + else + { +#if ASMOPT == 1 + const SLONG fixLerpRatio = FloatToInt(fLerpRatio*256.0f); // fix 8:8 + SLONG slTmp1, slTmp2, slTmp3; + // re-adjust stretching factors because of fixint lerping (divide by 256) + fStretchX*=0.00390625f; fOffsetX*=256.0f; + fStretchY*=0.00390625f; fOffsetY*=256.0f; + fStretchZ*=0.00390625f; fOffsetZ*=256.0f; + // for each vertex in mip + __asm { + mov edi,D [pvtxMipBase] + mov ebx,D [pswMipCol] + xor ecx,ecx +vtxLoop8L: + push ecx + push ebx + mov esi,D [puwMipToMdl] + movzx ebx,W [esi+ecx*2] + mov esi,D [pFrame0] + mov ecx,D [pFrame1] + // lerp vertex + movsx eax,B [esi+ebx*4]ModelFrameVertex8.mfv_SBPoint[0] + movsx edx,B [ecx+ebx*4]ModelFrameVertex8.mfv_SBPoint[0] + sub edx,eax + imul edx,D [fixLerpRatio] + shl eax,8 + add eax,edx + mov D [slTmp1],eax + movsx eax,B [esi+ebx*4]ModelFrameVertex8.mfv_SBPoint[1] + movsx edx,B [ecx+ebx*4]ModelFrameVertex8.mfv_SBPoint[1] + sub edx,eax + imul edx,D [fixLerpRatio] + shl eax,8 + add eax,edx + mov D [slTmp2],eax + movsx eax,B [esi+ebx*4]ModelFrameVertex8.mfv_SBPoint[2] + movsx edx,B [ecx+ebx*4]ModelFrameVertex8.mfv_SBPoint[2] + sub edx,eax + imul edx,D [fixLerpRatio] + shl eax,8 + add eax,edx + mov D [slTmp3],eax + // store vertex + fild D [slTmp1] + fsub D [fOffsetX] + fmul D [fStretchX] + fild D [slTmp2] + fsub D [fOffsetY] + fmul D [fStretchY] + fild D [slTmp3] + fsub D [fOffsetZ] + fmul D [fStretchZ] + fxch st(2) + fstp D [edi]GFXVertex3.x + fstp D [edi]GFXVertex3.y + fstp D [edi]GFXVertex3.z + // load normals + movzx eax,B [esi+ebx*4]ModelFrameVertex8.mfv_NormIndex + movzx edx,B [ecx+ebx*4]ModelFrameVertex8.mfv_NormIndex + lea esi,[eax*2+eax] + lea ecx,[edx*2+edx] + // lerp normals + fld D [avGouraudNormals+ ecx*4 +0] + fsub D [avGouraudNormals+ esi*4 +0] + fld D [avGouraudNormals+ ecx*4 +4] + fsub D [avGouraudNormals+ esi*4 +4] + fld D [avGouraudNormals+ ecx*4 +8] + fsub D [avGouraudNormals+ esi*4 +8] + fxch st(2) // nx1-nx0, ny1-ny0, nz1-nz0 + fmul D [fLerpRatio] + fxch st(1) // ny1-ny0, lnx1, nz1-nz0 + fmul D [fLerpRatio] + fxch st(2) // nz1-nz0, lnx1, lny1 + fmul D [fLerpRatio] + fxch st(1) // lnx1, lnz1, lny1 + fadd D [avGouraudNormals+ esi*4 +0] + fxch st(2) // lny1, lnz1, fNX + fadd D [avGouraudNormals+ esi*4 +4] + fxch st(1) // lnz1, fNY, fNX + fadd D [avGouraudNormals+ esi*4 +8] + fxch st(2) // fNX, fNY, fNZ + // determine vertex shade + fld D [fLightObjX] + fmul st(0),st(1) // flnx, fNX, fNY, fNZ + pop ebx + fld D [fLightObjY] + fmul st(0),st(3) // flny, flnx, fNX, fNY, fNZ + fld D [fLightObjZ] + fmul st(0),st(5) // flnz, flny, flnx, fNX, fNY, fNXZ + fxch st(2) + faddp st(1),st(0) + faddp st(1),st(0) // FL, fNX, fNY, fNXZ + fistp D [ebx] + // store lerped normal (if needed) + cmp D [bKeepNormals],0 + je vtxNext8L + mov ecx,D [esp] + imul ecx,3*4 + add ecx,D [pnorMipBase] + fstp D [ecx]GFXNormal.nx + fstp D [ecx]GFXNormal.ny + fst D [ecx]GFXNormal.nz + fld st(0) + fld st(0) + // advance to next vertex +vtxNext8L: + fstp st(0) + fcompp + pop ecx + add edi,3*4 + add ebx,1*2 + inc ecx + cmp ecx,D [_ctAllMipVx] + jl vtxLoop8L + } +#else + // for each vertex in mip + for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) { + // get destination for unpacking + const INDEX iMdlVx = puwMipToMdl[iMipVx]; + const ModelFrameVertex8 &mfv0 = pFrame0[iMdlVx]; + const ModelFrameVertex8 &mfv1 = pFrame1[iMdlVx]; + // store lerped vertex + GFXVertex3 &vtx = pvtxMipBase[iMipVx]; + vtx.x = (Lerp( (FLOAT)mfv0.mfv_SBPoint(1), (FLOAT)mfv1.mfv_SBPoint(1), fLerpRatio) -fOffsetX) * fStretchX; + vtx.y = (Lerp( (FLOAT)mfv0.mfv_SBPoint(2), (FLOAT)mfv1.mfv_SBPoint(2), fLerpRatio) -fOffsetY) * fStretchY; + vtx.z = (Lerp( (FLOAT)mfv0.mfv_SBPoint(3), (FLOAT)mfv1.mfv_SBPoint(3), fLerpRatio) -fOffsetZ) * fStretchZ; + // determine lerped normal + const FLOAT3D &vNormal0 = avGouraudNormals[mfv0.mfv_NormIndex]; + const FLOAT3D &vNormal1 = avGouraudNormals[mfv1.mfv_NormIndex]; + const FLOAT fNX = Lerp( (FLOAT)vNormal0(1), (FLOAT)vNormal1(1), fLerpRatio); + const FLOAT fNY = Lerp( (FLOAT)vNormal0(2), (FLOAT)vNormal1(2), fLerpRatio); + const FLOAT fNZ = Lerp( (FLOAT)vNormal0(3), (FLOAT)vNormal1(3), fLerpRatio); + // store vertex shade + pswMipCol[iMipVx] = FloatToInt(fNX*fLightObjX + fNY*fLightObjY + fNZ*fLightObjZ); + // store lerped normal (if needed) + if( bKeepNormals) { + pnorMipBase[iMipVx].nx = fNX; + pnorMipBase[iMipVx].ny = fNY; + pnorMipBase[iMipVx].nz = fNZ; + } + } +#endif + } + } + + // generate colors from shades +#if ASMOPT == 1 + __asm { + pxor mm0,mm0 + // construct 64-bit RGBA light + mov eax,D [_slLR] + mov ebx,D [_slLG] + mov ecx,D [_slLB] + shl ebx,16 + or eax,ebx + or ecx,0x01FE0000 + movd mm5,eax + movd mm7,ecx + psllq mm7,32 + por mm5,mm7 + psllw mm5,1 // boost for multiply + // construct 64-bit RGBA ambient + mov eax,D [_slAR] + mov ebx,D [_slAG] + mov ecx,D [_slAB] + shl ebx,16 + or eax,ebx + movd mm6,eax + movd mm7,ecx + psllq mm7,32 + por mm6,mm7 + // init + mov esi,D [pswMipCol] + mov edi,D [pcolMipBase] + mov ecx,D [_ctAllMipVx] + shr ecx,2 + jz colRest + // 4-colors loop +colLoop4: + movq mm1,Q [esi] + packuswb mm1,mm0 + punpcklbw mm1,mm1 + psrlw mm1,1 + movq mm3,mm1 + punpcklwd mm1,mm1 + punpckhwd mm3,mm3 + movq mm2,mm1 + movq mm4,mm3 + punpckldq mm1,mm1 + punpckhdq mm2,mm2 + punpckldq mm3,mm3 + punpckhdq mm4,mm4 + pmulhw mm1,mm5 + pmulhw mm2,mm5 + pmulhw mm3,mm5 + pmulhw mm4,mm5 + paddsw mm1,mm6 + paddsw mm2,mm6 + paddsw mm3,mm6 + paddsw mm4,mm6 + packuswb mm1,mm2 + packuswb mm3,mm4 + movq Q [edi+0],mm1 + movq Q [edi+8],mm3 + add esi,2*4 + add edi,4*4 + dec ecx + jnz colLoop4 + // 1-color loop +colRest: + mov ecx,D [_ctAllMipVx] + and ecx,3 + jz colEnd +colLoop1: + movsx eax,W [esi] + movd mm1,eax + packuswb mm1,mm0 + punpcklbw mm1,mm1 + psrlw mm1,1 + punpcklwd mm1,mm1 + punpckldq mm1,mm1 + pmulhw mm1,mm5 + paddsw mm1,mm6 + packuswb mm1,mm0 + movd D [edi],mm1 + add esi,2 + add edi,4 + dec ecx + jnz colLoop1 +colEnd: + emms + } +#else + // generate colors from shades + for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) { + GFXColor &col = pcolMipBase[iMipVx]; + const SLONG slShade = Clamp( (SLONG)pswMipCol[iMipVx], 0L, 255L); + col.r = pubClipByte[_slAR + ((_slLR*slShade)>>8)]; + col.g = pubClipByte[_slAG + ((_slLG*slShade)>>8)]; + col.b = pubClipByte[_slAB + ((_slLB*slShade)>>8)]; + col.a = slShade; + } +#endif + + // all done + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_INIT_UNPACK); +} + + + + +// BEGIN MODEL RENDERING ******************************************************************************* + + +#pragma warning(disable: 4731) +void CModelObject::RenderModel_View( CRenderModel &rm) +{ + // cache API + _eAPI = _pGfx->gl_eCurrentAPI; +#ifdef SE1_D3D + ASSERT( _eAPI==GAT_OGL || _eAPI==GAT_D3D || _eAPI==GAT_NONE); +#else // SE1_D3D + ASSERT( _eAPI==GAT_OGL || _eAPI==GAT_NONE); +#endif // SE1_D3D + if( _eAPI==GAT_NONE) return; // must have API + + // adjust Truform usage + extern INDEX mdl_bTruformWeapons; + extern INDEX gap_bForceTruform; + // if weapon models don't allow tessellation or no tessellation has been set at all + if( ((rm.rm_ulFlags&RMF_WEAPON) && !mdl_bTruformWeapons) || _pGfx->gl_iTessellationLevel<1) { + // just disable truform + gfxDisableTruform(); + } else { + // enable truform for everything? + if( gap_bForceTruform) gfxEnableTruform(); + else { + // enable truform only for truform-ready models! + const INDEX iTesselationLevel = Min( rm.rm_iTesselationLevel, _pGfx->gl_iTessellationLevel); + if( iTesselationLevel>0) { + extern INDEX ogl_bTruformLinearNormals; + gfxSetTruform( iTesselationLevel, ogl_bTruformLinearNormals); + gfxEnableTruform(); + } + else gfxDisableTruform(); + } + } + // setup drawing direction (in case of mirror) + if( rm.rm_ulFlags & RMF_INVERTED) gfxFrontFace(GFX_CW); + else gfxFrontFace(GFX_CCW); + + // declare pointers for general usage + INDEX iSrfVx0, ctSrfVx; + GFXTexCoord *ptexSrfBase; + GFXVertex *pvtxSrfBase; + FLOAT2D *pvTexCoord; + ModelMipInfo &mmi = *rm.rm_pmmiMip; + const ModelMipInfo &mmi0 = rm.rm_pmdModelData->md_MipInfos[0]; + + // calculate projection of viewer in absolute space + FLOATmatrix3D &mViewer = _aprProjection->pr_ViewerRotationMatrix; + _vViewer(1) = -mViewer(3,1); + _vViewer(2) = -mViewer(3,2); + _vViewer(3) = -mViewer(3,3); + // calculate projection of viewer in object space + _vViewerObj = _vViewer * !rm.rm_mObjectRotation; + + _pfModelProfile.IncrementCounter( CModelProfile::PCI_VERTICES_FIRSTMIP, mmi0.mmpi_ctMipVx); + _pfModelProfile.IncrementCounter( CModelProfile::PCI_SURFACEVERTICES_FIRSTMIP, mmi0.mmpi_ctSrfVx); + _pfModelProfile.IncrementCounter( CModelProfile::PCI_TRIANGLES_FIRSTMIP, mmi0.mmpi_ctTriangles); + _pfModelProfile.IncrementCounter( CModelProfile::PCI_VERTICES_USEDMIP, mmi.mmpi_ctMipVx); + _pfModelProfile.IncrementCounter( CModelProfile::PCI_SURFACEVERTICES_USEDMIP, mmi.mmpi_ctSrfVx); + _pfModelProfile.IncrementCounter( CModelProfile::PCI_TRIANGLES_USEDMIP, mmi.mmpi_ctTriangles); + _sfStats.IncrementCounter( CStatForm::SCI_TRIANGLES_FIRSTMIP, mmi0.mmpi_ctTriangles); + _sfStats.IncrementCounter( CStatForm::SCI_TRIANGLES_USEDMIP, mmi.mmpi_ctTriangles); + + // allocate vertex arrays + _ctAllMipVx = mmi.mmpi_ctMipVx; + _ctAllSrfVx = mmi.mmpi_ctSrfVx; + ASSERT( _ctAllMipVx>0 && _ctAllSrfVx>0); + ASSERT( _avtxMipBase.Count()==0); _avtxMipBase.Push(_ctAllMipVx); + ASSERT( _atexMipBase.Count()==0); _atexMipBase.Push(_ctAllMipVx); + ASSERT( _acolMipBase.Count()==0); _acolMipBase.Push(_ctAllMipVx); + ASSERT( _anorMipBase.Count()==0); _anorMipBase.Push(_ctAllMipVx); + + ASSERT( _atexMipFogy.Count()==0); _atexMipFogy.Push(_ctAllMipVx); + ASSERT( _ashdMipFogy.Count()==0); _ashdMipFogy.Push(_ctAllMipVx); + ASSERT( _atx1MipHaze.Count()==0); _atx1MipHaze.Push(_ctAllMipVx); + ASSERT( _ashdMipHaze.Count()==0); _ashdMipHaze.Push(_ctAllMipVx); + + ASSERT( _avtxSrfBase.Count()==0); _avtxSrfBase.Push(_ctAllSrfVx); + ASSERT( _atexSrfBase.Count()==0); _atexSrfBase.Push(_ctAllSrfVx); + ASSERT( _acolSrfBase.Count()==0); _acolSrfBase.Push(_ctAllSrfVx); + + if( GFX_bTruform) { + ASSERT( _anorSrfBase.Count()==0); + _anorSrfBase.Push(_ctAllSrfVx); + } + + // determine multitexturing capability for overbrighting purposes + extern INDEX mdl_bAllowOverbright; + const BOOL bOverbright = mdl_bAllowOverbright && _pGfx->gl_ctTextureUnits>1; + + // saturate light and ambient color + const COLOR colL = AdjustColor( rm.rm_colLight, _slShdHueShift, _slShdSaturation); + const COLOR colA = AdjustColor( rm.rm_colAmbient, _slShdHueShift, _slShdSaturation); + // cache light intensities (-1 in case of overbrighting compensation) + const INDEX iBright = bOverbright ? 0 : 1; + _slLR = (colL & CT_RMASK)>>(CT_RSHIFT-iBright); + _slLG = (colL & CT_GMASK)>>(CT_GSHIFT-iBright); + _slLB = (colL & CT_BMASK)>>(CT_BSHIFT-iBright); + _slAR = (colA & CT_RMASK)>>(CT_RSHIFT-iBright); + _slAG = (colA & CT_GMASK)>>(CT_GSHIFT-iBright); + _slAB = (colA & CT_BMASK)>>(CT_BSHIFT-iBright); + if( bOverbright) { + _slAR = ClampUp( _slAR, 127L); + _slAG = ClampUp( _slAG, 127L); + _slAB = ClampUp( _slAB, 127L); + } + + // set forced translucency and color mask + _bForceTranslucency = ((rm.rm_colBlend&CT_AMASK)>>CT_ASHIFT) != CT_OPAQUE; + _ulColorMask = mo_ColorMask; + // adjust all surfaces' params for eventual forced-translucency case + _ulMipLayerFlags = mmi.mmpi_ulLayerFlags; + if( _bForceTranslucency) { + _ulMipLayerFlags &= ~MMI_OPAQUE; + _ulMipLayerFlags |= MMI_TRANSLUCENT; + } + + // unpack one model frame vertices and eventually normals (lerped or not lerped, as required) + pvtxMipBase = &_avtxMipBase[0]; + pcolMipBase = &_acolMipBase[0]; + pnorMipBase = &_anorMipBase[0]; + const BOOL bNeedNormals = GFX_bTruform || (_ulMipLayerFlags&(SRF_REFLECTIONS|SRF_SPECULAR)); + UnpackFrame( rm, bNeedNormals); + + // cache some more pointers and vars + ptexMipBase = &_atexMipBase[0]; + ptexMipFogy = &_atexMipFogy[0]; + pshdMipFogy = &_ashdMipFogy[0]; + ptx1MipHaze = &_atx1MipHaze[0]; + pshdMipHaze = &_ashdMipHaze[0]; + + + // PREPARE FOG AND HAZE MIP -------------------------------------------------------------------------- + + + // if this model has haze + if( rm.rm_ulFlags & RMF_HAZE) + { + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_INIT_HAZE_MIP); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_INIT_HAZE_MIP, _ctAllMipVx); + // get viewer offset + // _fHazeAdd = (_vViewer%(rm.rm_vObjectPosition-_aprProjection->pr_vViewerPosition)) - _haze_hp.hp_fNear; // might cause a BUG in compiler ???? + _fHazeAdd = -_haze_hp.hp_fNear; + _fHazeAdd += _vViewer(1) * (rm.rm_vObjectPosition(1) - _aprProjection->pr_vViewerPosition(1)); + _fHazeAdd += _vViewer(2) * (rm.rm_vObjectPosition(2) - _aprProjection->pr_vViewerPosition(2)); + _fHazeAdd += _vViewer(3) * (rm.rm_vObjectPosition(3) - _aprProjection->pr_vViewerPosition(3)); + + // if it'll be cost-effective (i.e. model has enough vertices to be potentionaly trivialy rejected) + // check bounding box of model against haze + if( _ctAllMipVx>12 && !IsModelInHaze( rm.rm_vObjectMinBB, rm.rm_vObjectMaxBB)) { + // this model has no haze after all + rm.rm_ulFlags &= ~RMF_HAZE; + } + // model is in haze (at least partially) + else { + // if model is all opaque + if( _ulMipLayerFlags&MMI_OPAQUE) { + // setup haze tex coords only + for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) { + GetHazeMapInVertex( pvtxMipBase[iMipVx], ptx1MipHaze[iMipVx]); + } + // if model is all translucent + } else if( _ulMipLayerFlags&MMI_TRANSLUCENT) { + // setup haze attenuation values only + FLOAT tx1; + for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) { + GetHazeMapInVertex( pvtxMipBase[iMipVx], tx1); + pshdMipHaze[iMipVx] = GetHazeAlpha(tx1) ^255; + } + // if model is partially opaque and partially translucent + } else { + // setup haze both tex coords and attenuation values + for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) { + FLOAT &tx1 = ptx1MipHaze[iMipVx]; + GetHazeMapInVertex( pvtxMipBase[iMipVx], tx1); + pshdMipHaze[iMipVx] = GetHazeAlpha(tx1) ^255; + } + } + } // haze mip setup done + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_INIT_HAZE_MIP); + } + + // if this model has fog + if( rm.rm_ulFlags & RMF_FOG) + { + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_INIT_FOG_MIP); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_INIT_FOG_MIP, _ctAllMipVx); + // get viewer -z in object space + _vFViewerObj = FLOAT3D(0,0,-1) * !rm.rm_mObjectToView; + // get fog direction in object space + _vHDirObj = _fog_vHDirAbs * !(!mViewer*rm.rm_mObjectToView); + // get viewer offset + // _fFogAddZ = _vViewer % (rm.rm_vObjectPosition - _aprProjection->pr_vViewerPosition); // BUG in compiler !!!! + _fFogAddZ = _vViewer(1) * (rm.rm_vObjectPosition(1) - _aprProjection->pr_vViewerPosition(1)); + _fFogAddZ += _vViewer(2) * (rm.rm_vObjectPosition(2) - _aprProjection->pr_vViewerPosition(2)); + _fFogAddZ += _vViewer(3) * (rm.rm_vObjectPosition(3) - _aprProjection->pr_vViewerPosition(3)); + // get fog offset + _fFogAddH = (_fog_vHDirAbs % rm.rm_vObjectPosition) + _fog_fp.fp_fH3; + + // if it'll be cost-effective (i.e. model has enough vertices to be potentionaly trivialy rejected) + // check bounding box of model against fog + if( _ctAllMipVx>16 && !IsModelInFog( rm.rm_vObjectMinBB, rm.rm_vObjectMaxBB)) { + // this model has no fog after all + rm.rm_ulFlags &= ~RMF_FOG; + } + // model is in fog (at least partially) + else { + // if model is all opaque + if( _ulMipLayerFlags&MMI_OPAQUE) { + // setup for tex coords only + for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) { + GetFogMapInVertex( pvtxMipBase[iMipVx], ptexMipFogy[iMipVx]); + } + // if model is all translucent + } else if( _ulMipLayerFlags&MMI_TRANSLUCENT) { + // setup fog attenuation values only + GFXTexCoord tex; + for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) { + GetFogMapInVertex( pvtxMipBase[iMipVx], tex); + pshdMipFogy[iMipVx] = GetFogAlpha(tex) ^255; + } + // if model is partially opaque and partially translucent + } else { + // setup fog both tex coords and attenuation values + for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) { + GFXTexCoord &tex = ptexMipFogy[iMipVx]; + GetFogMapInVertex( pvtxMipBase[iMipVx], tex); + pshdMipFogy[iMipVx] = GetFogAlpha(tex) ^255; + } + } + } // fog mip setup done + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_INIT_FOG_MIP); + } + + // begin model rendering + const BOOL bModelSetupTimer = _sfStats.CheckTimer(CStatForm::STI_MODELSETUP); + if( bModelSetupTimer) _sfStats.StopTimer(CStatForm::STI_MODELSETUP); + _sfStats.StartTimer(CStatForm::STI_MODELRENDERING); + + + // PREPARE SURFACE VERTICES ------------------------------------------------------------------------ + + + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_INIT_VERTICES); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_INIT_VERTICES, _ctAllSrfVx); + + // for each surface in current mip model + BOOL bEmpty = TRUE; + {FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) + { + const MappingSurface &ms = *itms; + iSrfVx0 = ms.ms_iSrfVx0; + ctSrfVx = ms.ms_ctSrfVx; + // skip to next in case of invisible or empty surface + if( (ms.ms_ulRenderingFlags&SRF_INVISIBLE) || ctSrfVx==0) break; + bEmpty = FALSE; + puwSrfToMip = &mmi.mmpi_auwSrfToMip[iSrfVx0]; + pvtxSrfBase = &_avtxSrfBase[iSrfVx0]; + INDEX iSrfVx; + +#if ASMOPT == 1 + __asm { + push ebx + mov ebx,D [puwSrfToMip] + mov esi,D [pvtxMipBase] + mov edi,D [pvtxSrfBase] + mov ecx,D [ctSrfVx] +srfVtxLoop: + movzx eax,W [ebx] + lea eax,[eax*2+eax] // *3 + mov edx,D [esi+eax*4+0] + movq mm1,Q [esi+eax*4+4] + mov D [edi+0],edx + movq Q [edi+4],mm1 + add ebx,2 + add edi,4*4 + dec ecx + jnz srfVtxLoop + emms + pop ebx + } +#else + // setup vetrex array + for( iSrfVx=0; iSrfVx norm float) + FLOAT fTexCorrU, fTexCorrV; + gfxSetTextureWrapping( GFX_REPEAT, GFX_REPEAT); + // color and fill mode setup + _bFlatFill = (rm.rm_rtRenderType&RT_WHITE_TEXTURE) || mo_toTexture.GetData()==NULL; + const BOOL bTexMode = rm.rm_rtRenderType & (RT_TEXTURE|RT_WHITE_TEXTURE); + const BOOL bAllLayers = bTexMode && !_bFlatFill; // disallow rendering of every layer except diffuse + + // model surface vertices prepared + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_INIT_VERTICES); + + + // RENDER DIFFUSE LAYER ------------------------------------------------------------------- + + + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_INIT_DIFF_SURF); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_INIT_DIFF_SURF, _ctAllSrfVx); + + // get diffuse texture corrections + CTextureData *ptdDiff = (CTextureData*)mo_toTexture.GetData(); + if( ptdDiff!=NULL) { + fTexCorrU = 1.0f / ptdDiff->GetWidth(); + fTexCorrV = 1.0f / ptdDiff->GetHeight(); + } else { + fTexCorrU = 1.0f; + fTexCorrV = 1.0f; + } + + // get model diffuse color + GFXColor colMdlDiff; + const COLOR colD = AdjustColor( rm.rm_pmdModelData->md_colDiffuse, _slTexHueShift, _slTexSaturation); + const COLOR colB = AdjustColor( rm.rm_colBlend, _slTexHueShift, _slTexSaturation); + colMdlDiff.MultiplyRGBA( colD, colB); + + // for each surface in current mip model + {FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) + { + const MappingSurface &ms = *itms; + iSrfVx0 = ms.ms_iSrfVx0; + ctSrfVx = ms.ms_ctSrfVx; + if( (ms.ms_ulRenderingFlags&SRF_INVISIBLE) || ctSrfVx==0) break; // done if found invisible or empty surface + // cache surface pointers + puwSrfToMip = &mmi.mmpi_auwSrfToMip[iSrfVx0]; + pvTexCoord = &mmi.mmpi_avmexTexCoord[iSrfVx0]; + ptexSrfBase = &_atexSrfBase[iSrfVx0]; + pcolSrfBase = &_acolSrfBase[iSrfVx0]; + + // get surface diffuse color and combine with model color + GFXColor colSrfDiff; + const COLOR colD = AdjustColor( ms.ms_colDiffuse, _slTexHueShift, _slTexSaturation); + colSrfDiff.MultiplyRGBA( colD, colMdlDiff); + +#if ASMOPT == 1 + // setup texcoord array + __asm { + push ebx + mov esi,D [pvTexCoord] + mov edi,D [ptexSrfBase] + mov ecx,D [ctSrfVx] + shr ecx,1 + jz vtxRest +vtxLoop: + fld D [esi+0] + fmul D [fTexCorrU] + fld D [esi+8] + fmul D [fTexCorrU] + fld D [esi+4] + fmul D [fTexCorrV] + fld D [esi+12] + fmul D [fTexCorrV] + fxch st(3) // u1, v1, u2, v2 + fstp D [edi+0] + fstp D [edi+4] + fstp D [edi+8] + fstp D [edi+12] + add esi,2*2*4 + add edi,2*2*4 + dec ecx + jnz vtxLoop +vtxRest: + test D [ctSrfVx],1 + jz vtxEnd + fld D [esi+0] + fmul D [fTexCorrU] + fld D [esi+4] + fmul D [fTexCorrV] + fxch st(1) + fstp D [edi+0] + fstp D [edi+4] +vtxEnd: + pop ebx + } +#else + // setup texcoord array + for( INDEX iSrfVx=0; iSrfVx>=1; + colSrfDiffAdj.g >>=1; + colSrfDiffAdj.b >>=1; + } // just copy diffuse color + for( INDEX iSrfVx=0; iSrfVx>CT_ASHIFT; + if( (_ulMipLayerFlags&(SRF_DETAIL|SRF_BUMP)) && mdl_bRenderDetail && ptdBump!=NULL && ulTransAlpha>192 && bAllLayers) + { + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_INIT_BUMP_SURF); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_INIT_BUMP_SURF, _ctAllSrfVx); + + // get model detail color + GFXColor colMdlBump; + const COLOR colB = AdjustColor( rm.rm_pmdModelData->md_colBump, _slTexHueShift, _slTexSaturation); + colMdlBump.abgr = ByteSwap(colB); + // get detail texture corrections + fTexCorrU = 1.0f / ptdBump->GetWidth(); + fTexCorrV = 1.0f / ptdBump->GetHeight(); + // adjust detail stretch if needed get model's stretch + if( !(rm.rm_pmdModelData->md_Flags&MF_STRETCH_DETAIL)) { + const FLOAT fStretch = mo_Stretch.Length() * 0.57735f; // /Sqrt(3); + fTexCorrU *= fStretch; + fTexCorrV *= fStretch; + } + + // for each bump surface in current mip model + FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) + { + const MappingSurface &ms = *itms; + iSrfVx0 = ms.ms_iSrfVx0; + ctSrfVx = ms.ms_ctSrfVx; + if( (ms.ms_ulRenderingFlags&SRF_INVISIBLE) || ctSrfVx==0) break; // done if found invisible or empty surface + if( !(ms.ms_ulRenderingFlags&SRF_DETAIL)) continue; // skip non-detail surface + // cache surface pointers + pvTexCoord = &mmi.mmpi_avmexTexCoord[iSrfVx0]; + puwSrfToMip = &mmi.mmpi_auwSrfToMip[iSrfVx0]; + ptexSrfBase = &_atexSrfBase[iSrfVx0]; + pcolSrfBase = &_acolSrfBase[iSrfVx0]; + // get surface detail color and combine with model color + GFXColor colSrfBump; + const COLOR colB = AdjustColor( ms.ms_colBump, _slTexHueShift, _slTexSaturation); + colSrfBump.MultiplyRGB( colB, colMdlBump); + + // for each vertex in the surface + for( INDEX iSrfVx=0; iSrfVxmd_colReflections, _slTexHueShift, _slTexSaturation); + colMdlRefl.abgr = ByteSwap(colR); + colMdlRefl.AttenuateA( (rm.rm_colBlend&CT_AMASK)>>CT_ASHIFT); + + // for each reflective surface in current mip model + FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) + { + const MappingSurface &ms = *itms; + iSrfVx0 = ms.ms_iSrfVx0; + ctSrfVx = ms.ms_ctSrfVx; + if( (ms.ms_ulRenderingFlags&SRF_INVISIBLE) || ctSrfVx==0) break; // done if found invisible or empty surface + if( !(ms.ms_ulRenderingFlags&SRF_REFLECTIONS)) continue; // skip non-reflection surface + // cache surface pointers + puwSrfToMip = &mmi.mmpi_auwSrfToMip[iSrfVx0]; + ptexSrfBase = &_atexSrfBase[iSrfVx0]; + pcolSrfBase = &_acolSrfBase[iSrfVx0]; + // get surface reflection color and combine with model color + GFXColor colSrfRefl; + const COLOR colR = AdjustColor( ms.ms_colReflections, _slTexHueShift, _slTexSaturation); + colSrfRefl.MultiplyRGBA( colR, colMdlRefl); + + // set reflection texture coords + for( INDEX iSrfVx=0; iSrfVxmd_colSpecular, _slTexHueShift, _slTexSaturation); + colMdlSpec.abgr = ByteSwap(colS); + colMdlSpec.AttenuateRGB( (rm.rm_colBlend&CT_AMASK)>>CT_ASHIFT); + colMdlSpec.r = ClampUp( (colMdlSpec.r *_slLR)>>8, 255L); + colMdlSpec.g = ClampUp( (colMdlSpec.g *_slLG)>>8, 255L); + colMdlSpec.b = ClampUp( (colMdlSpec.b *_slLB)>>8, 255L); + + // for each specular surface in current mip model + FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) + { + const MappingSurface &ms = *itms; + iSrfVx0 = ms.ms_iSrfVx0; + ctSrfVx = ms.ms_ctSrfVx; + if( (ms.ms_ulRenderingFlags&SRF_INVISIBLE) || ctSrfVx==0) break; // done if found invisible or empty surface + if( !(ms.ms_ulRenderingFlags&SRF_SPECULAR)) continue; // skip non-specular surface + // cache surface pointers + puwSrfToMip = &mmi.mmpi_auwSrfToMip[iSrfVx0]; + ptexSrfBase = &_atexSrfBase[iSrfVx0]; + pcolSrfBase = &_acolSrfBase[iSrfVx0]; + // get surface specular color and combine with model color + GFXColor colSrfSpec; + const COLOR colS = AdjustColor( ms.ms_colSpecular, _slTexHueShift, _slTexSaturation); + colSrfSpec.MultiplyRGB( colS, colMdlSpec); + + // for each vertex in the surface + for( INDEX iSrfVx=0; iSrfVx>8) + | (((colSrfSpec.g)*slShade)&0x0000FF00) + | ((((colSrfSpec.b)*slShade)<<8)&0x00FF0000); + } + // eventually attenuate color in case of fog or haze + if( (ms.ms_ulRenderingFlags&SRF_OPAQUE) && !_bForceTranslucency) continue; + // eventually do some haze and/or fog attenuation of alpha channel in surface + if( rm.rm_ulFlags & RMF_HAZE) { + if( ms.ms_sttTranslucencyType==STT_MULTIPLY) AttenuateColor( pshdMipHaze, ctSrfVx); + else AttenuateAlpha( pshdMipHaze, ctSrfVx); + } + if( rm.rm_ulFlags & RMF_FOG) { + if( ms.ms_sttTranslucencyType==STT_MULTIPLY) AttenuateColor( pshdMipFogy, ctSrfVx); + else AttenuateAlpha( pshdMipFogy, ctSrfVx); + } + } + // specular prep done + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_INIT_SPEC_SURF); + + // begin rendering + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_RENDER_SPECULAR); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_RENDER_SPECULAR); + + // setup texture/color arrays and rendering mode + SetCurrentTexture( ptdSpecular, mo_toSpecular.GetFrame()); + gfxSetTexCoordArray( &_atexSrfBase[0], FALSE); + gfxSetColorArray( &_acolSrfBase[0]); + gfxBlendFunc( GFX_INV_SRC_ALPHA, GFX_ONE); + // do rendering + RenderOneSide( rm, TRUE , SRF_SPECULAR); + RenderOneSide( rm, FALSE, SRF_SPECULAR); + + // specular rendering done + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_RENDER_SPECULAR); + } + + + + // RENDER HAZE LAYER ------------------------------------------------------------------- + + + // if this model has haze and some opaque surfaces + if( (rm.rm_ulFlags&RMF_HAZE) && !(_ulMipLayerFlags&MMI_TRANSLUCENT)) + { + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_INIT_HAZE_SURF); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_INIT_HAZE_SURF, _ctAllSrfVx); + // unpack haze color + const COLOR colH = AdjustColor( _haze_hp.hp_colColor, _slTexHueShift, _slTexSaturation); + GFXColor colHaze(colH); + + // for each surface in current mip model + FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) + { + MappingSurface &ms = *itms; + iSrfVx0 = ms.ms_iSrfVx0; + ctSrfVx = ms.ms_ctSrfVx; + if( (ms.ms_ulRenderingFlags&SRF_INVISIBLE) || ctSrfVx==0) break; // done if found invisible or empty surface + if( !(ms.ms_ulRenderingFlags&SRF_OPAQUE)) continue; // skip not-solid or empty surfaces + // cache surface pointers + puwSrfToMip = &mmi.mmpi_auwSrfToMip[iSrfVx0]; + ptexSrfBase = &_atexSrfBase[iSrfVx0]; + pcolSrfBase = &_acolSrfBase[iSrfVx0]; + + // prepare haze vertices + for( INDEX iSrfVx=0; iSrfVxmd_MipInfos[rm.rm_iMipLevel]; + + // get main texture size + FLOAT fmexMainSizeU=1, fmexMainSizeV=1; + FLOAT f1oMainSizeV =1, f1oMainSizeU =1; + CTextureData *ptd = (CTextureData*)mo_toTexture.GetData(); + if( ptd!=NULL) { + fmexMainSizeU = GetWidth(); + fmexMainSizeV = GetHeight(); + f1oMainSizeU = 1.0f / fmexMainSizeU; + f1oMainSizeV = 1.0f / fmexMainSizeV; + } + + // for each possible patch + INDEX iExistingPatch=0; + for( INDEX iMaskBit=0; iMaskBitmd_mpPatches[ iMaskBit].mp_toTexture; + CTextureData *ptdPatch = (CTextureData*)toPatch.GetData(); + if( ptdPatch==NULL) continue; + if( mo_PatchMask & ((1UL)<mmpi_aPolygonsPerPatch[iExistingPatch]; + if( ppp.ppp_auwElements.Count()==0) continue; + // calculate correction factor (relative to greater texture dimension) + const MEX2D mexPatchOffset = pmd->md_mpPatches[iMaskBit].mp_mexPosition; + const FLOAT fSizeDivider = 1.0f / pmd->md_mpPatches[iMaskBit].mp_fStretch; + const FLOAT fmexSizeU = ptdPatch->GetWidth(); + const FLOAT fmexSizeV = ptdPatch->GetHeight(); + // set texture for API + SetCurrentTexture( ptdPatch, toPatch.GetFrame()); + pglLoadIdentity(); + pglScalef( fmexMainSizeU/fmexSizeU*fSizeDivider, fmexMainSizeV/fmexSizeV*fSizeDivider, 0); + pglTranslatef( -mexPatchOffset(1)*f1oMainSizeU, -mexPatchOffset(2)*f1oMainSizeV, 0); + gfxSetTexCoordArray( &_atexSrfBase[0], FALSE); + //AddElements( &ppp.ppp_auwElements[0], ppp.ppp_auwElements.Count()); + //FlushElements(); + } + iExistingPatch++; + } + // all done + pglLoadIdentity(); + pglMatrixMode( GL_MODELVIEW); + OGL_CHECKERROR; + + // patches rendered + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_RENDERPATCHES); +} + + + +// ******************************************************************************* + + + +// render comlex model shadow +void CModelObject::RenderShadow_View( CRenderModel &rm, const CPlacement3D &plLight, + const FLOAT fFallOff, const FLOAT fHotSpot, const FLOAT fIntensity, + const FLOATplane3D &plShadowPlane) +{ + // no shadow, if projection is not perspective or no textures + if( !_aprProjection.IsPerspective() || !(rm.rm_rtRenderType & RT_TEXTURE)) return; + + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_RENDERSHADOW); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_RENDERSHADOW); + + // get viewer in absolute space + FLOAT3D vViewerAbs = _aprProjection->ViewerPlacementR().pl_PositionVector; + if( plShadowPlane.PointDistance(vViewerAbs)<0.01f) { + // shadow destination plane is not visible - don't cast shadows + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_RENDERSHADOW); + return; + } + + // get light position in object space + FLOATmatrix3D mAbsToObj = !rm.rm_mObjectRotation; + const FLOAT3D vAbsToObj = -rm.rm_vObjectPosition; + _vLightObj = (plLight.pl_PositionVector+vAbsToObj)*mAbsToObj; + // get shadow plane in object space + FLOATplane3D plShadowPlaneObj = (plShadowPlane+vAbsToObj)*mAbsToObj; + + // project object handle so we can calc how it is far away from viewer + const FLOAT3D vRef = plShadowPlaneObj.ProjectPoint(FLOAT3D(0,0,0)) *rm.rm_mObjectToView +rm.rm_vObjectToView; + plShadowPlaneObj.pl_distance += ClampDn( -vRef(3)*0.001f, 0.01f); // move plane towards the viewer a bit to avoid z-fighting + + // get distance from shadow plane to light + const FLOAT fDl = plShadowPlaneObj.PointDistance(_vLightObj); + if( fDl<0.1f) { + // too small - do nothing + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_RENDERSHADOW); + return; + } + + ModelMipInfo &mmi = *rm.rm_pmmiMip; + ModelMipInfo &mmi0 = rm.rm_pmdModelData->md_MipInfos[0]; + _pfModelProfile.IncrementCounter( CModelProfile::PCI_SHADOWVERTICES_FIRSTMIP, mmi0.mmpi_ctMipVx); + _pfModelProfile.IncrementCounter( CModelProfile::PCI_SHADOWVERTICES_USEDMIP, mmi.mmpi_ctMipVx); + _pfModelProfile.IncrementCounter( CModelProfile::PCI_SHADOWSURFACEVERTICES_FIRSTMIP, mmi0.mmpi_ctSrfVx); + _pfModelProfile.IncrementCounter( CModelProfile::PCI_SHADOWSURFACEVERTICES_USEDMIP, mmi.mmpi_ctSrfVx); + _pfModelProfile.IncrementCounter( CModelProfile::PCI_SHADOWTRIANGLES_FIRSTMIP, mmi0.mmpi_ctTriangles); + _pfModelProfile.IncrementCounter( CModelProfile::PCI_SHADOWTRIANGLES_USEDMIP, mmi.mmpi_ctTriangles); + + _sfStats.IncrementCounter( CStatForm::SCI_SHADOWTRIANGLES_FIRSTMIP, mmi0.mmpi_ctTriangles); + _sfStats.IncrementCounter( CStatForm::SCI_SHADOWTRIANGLES_USEDMIP, mmi.mmpi_ctTriangles); + + // allocate vertex arrays + _ctAllMipVx = mmi.mmpi_ctMipVx; + _ctAllSrfVx = mmi.mmpi_ctSrfVx; + ASSERT( _ctAllMipVx>0 && _ctAllSrfVx>0); + ASSERT( _avtxMipBase.Count()==0); _avtxMipBase.Push(_ctAllMipVx); + ASSERT( _acolMipBase.Count()==0); _acolMipBase.Push(_ctAllMipVx); + ASSERT( _aooqMipShad.Count()==0); _aooqMipShad.Push(_ctAllMipVx); + ASSERT( _avtxSrfBase.Count()==0); _avtxSrfBase.Push(_ctAllSrfVx); + ASSERT( _acolSrfBase.Count()==0); _acolSrfBase.Push(_ctAllSrfVx); + ASSERT( _atx4SrfShad.Count()==0); _atx4SrfShad.Push(_ctAllSrfVx); + + // unpack one model frame vertices and eventually normals (lerped or not lerped, as required) + pvtxMipBase = &_avtxMipBase[0]; + pooqMipShad = &_aooqMipShad[0]; + pcolMipBase = &_acolMipBase[0]; + UnpackFrame( rm, FALSE); + UBYTE *pubsMipBase = (UBYTE*)pcolMipBase; + + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_SHAD_INIT_MIP); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_SHAD_INIT_MIP, _ctAllMipVx); + + // calculate light interpolants attenuated by ambient factor + const INDEX iLightMax = NormFloatToByte(fIntensity); + const FLOAT fLightStep = 255.0f* fIntensity/(fFallOff-fHotSpot); + + // for each mip vertex + {for( INDEX iMipVx=0; iMipVx<_ctAllMipVx; iMipVx++) + { + // get object coordinates + GFXVertex3 &vtx = pvtxMipBase[iMipVx]; + // get distance of the vertex from shadow plane + FLOAT fDt = plShadowPlaneObj(1) *vtx.x + + plShadowPlaneObj(2) *vtx.y + + plShadowPlaneObj(3) *vtx.z + - plShadowPlaneObj.Distance(); + // if vertex below shadow plane + if( fDt<0) { + // THIS MIGHT BE WRONG - it'll make shadow vertex to be the same as model vertex !!!! + // fake as beeing just on plane + fDt=0.0f; + FLOAT fP = fDl/(fDl-fDt); // =1 + FLOAT fL = fDt/(fDl-fDt); // =0 + // calculate shadow vertex + vtx.x = vtx.x*fP - _vLightObj(1)*fL; + vtx.y = vtx.y*fP - _vLightObj(2)*fL; + vtx.z = vtx.z*fP - _vLightObj(3)*fL; + pooqMipShad[iMipVx] = 1.0f; + // make it transparent + pubsMipBase[iMipVx] = 0; + } + // if vertex above light + else if( (fDl-fDt)<0.01f) { + // fake as beeing just a bit below light + fDt = fDl-0.1f; + const FLOAT fDiv = 1.0f / (fDl-fDt); + const FLOAT fP = fDl *fDiv; + const FLOAT fL = fDt *fDiv; + // calculate shadow vertex + vtx.x = vtx.x*fP - _vLightObj(1)*fL; + vtx.y = vtx.y*fP - _vLightObj(2)*fL; + vtx.z = vtx.z*fP - _vLightObj(3)*fL; + pooqMipShad[iMipVx] = 1.0f; + // make it transparent + pubsMipBase[iMipVx] = 0; + } + // if vertex between shadow plane and light + else { + const FLOAT fDiv = 1.0f / (fDl-fDt); + const FLOAT fP = fDl *fDiv; + const FLOAT fL = fDt *fDiv; + // calculate shadow vertex + vtx.x = vtx.x*fP - _vLightObj(1)*fL; + vtx.y = vtx.y*fP - _vLightObj(2)*fL; + vtx.z = vtx.z*fP - _vLightObj(3)*fL; + pooqMipShad[iMipVx] = fP; + // get distance between light and shadow vertex + const FLOAT fDlsx = vtx.x - _vLightObj(1); + const FLOAT fDlsy = vtx.y - _vLightObj(2); + const FLOAT fDlsz = vtx.z - _vLightObj(3); + const FLOAT fDls = sqrt( fDlsx*fDlsx + fDlsy*fDlsy + fDlsz*fDlsz); + // calculate shadow value for this vertex + if( fDlsfFallOff) pubsMipBase[iMipVx] = 0; + else pubsMipBase[iMipVx] = FloatToInt( (fFallOff-fDls)*fLightStep); + } + }} + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_SHAD_INIT_MIP); + + // get diffuse texture corrections + FLOAT fTexCorrU, fTexCorrV; + CTextureData *ptd = (CTextureData*)mo_toTexture.GetData(); + if( ptd!=NULL) { + fTexCorrU = 1.0f / ptd->GetWidth(); + fTexCorrV = 1.0f / ptd->GetHeight(); + } else { + fTexCorrU = 1.0f; + fTexCorrV = 1.0f; + } + + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_SHAD_INIT_SURF); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_SHAD_INIT_SURF, _ctAllSrfVx); + // for each surface in current mip model + FOREACHINSTATICARRAY( mmi.mmpi_MappingSurfaces, MappingSurface, itms) + { + const MappingSurface &ms = *itms; + const INDEX iSrfVx0 = ms.ms_iSrfVx0; + const INDEX ctSrfVx = ms.ms_ctSrfVx; + if( (ms.ms_ulRenderingFlags&SRF_INVISIBLE) || ctSrfVx==0) break; // done if found invisible or empty surface + // cache surface pointers + puwSrfToMip = &mmi.mmpi_auwSrfToMip[iSrfVx0]; + const FLOAT2D *pvTexCoord = (const FLOAT2D*)&mmi.mmpi_avmexTexCoord[iSrfVx0]; + GFXVertex *pvtxSrfBase = &_avtxSrfBase[iSrfVx0]; + GFXTexCoord4 *ptx4SrfShad = &_atx4SrfShad[iSrfVx0]; + GFXColor *pcolSrfBase = &_acolSrfBase[iSrfVx0]; + // for each vertex in the surface + for( INDEX iSrfVx=0; iSrfVx0) FlushElements( ctElements, &mmi.mmpi_aiElements[iStartElem]); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_SHAD_RENDER, ctElements/3); + iStartElem+= ctElements+ms.ms_ctSrfEl; + ctElements = 0; + }} + // flush leftovers + if( ctElements>0) FlushElements( ctElements, &mmi.mmpi_aiElements[iStartElem]); + + // done + gfxUnlockArrays(); + + // reset vertex arrays + _avtxMipBase.PopAll(); + _acolMipBase.PopAll(); + _aooqMipShad.PopAll(); + _avtxSrfBase.PopAll(); + _acolSrfBase.PopAll(); + _atx4SrfShad.PopAll(); + + // shadow rendered + _sfStats.StopTimer(CStatForm::STI_MODELRENDERING); + if( bModelSetupTimer) _sfStats.StartTimer(CStatForm::STI_MODELSETUP); + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_SHAD_RENDER); + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_RENDERSHADOW); +} + + +// ******************************************************************************* + + +// render simple model shadow +void CModelObject::AddSimpleShadow_View( CRenderModel &rm, const FLOAT fIntensity, + const FLOATplane3D &plShadowPlane) +{ + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_RENDERSIMPLESHADOW); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_RENDERSIMPLESHADOW); + + // get viewer in absolute space + FLOAT3D vViewerAbs = _aprProjection->ViewerPlacementR().pl_PositionVector; + // if shadow destination plane is not visible, don't cast shadows + if( plShadowPlane.PointDistance(vViewerAbs)<0.01f) { + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_RENDERSIMPLESHADOW); + return; + } + + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_SIMP_CALC); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_SIMP_CALC); + + // get shadow plane in object space + const FLOATmatrix3D mAbsToObj = !rm.rm_mObjectRotation; + const FLOAT3D vAbsToObj = -rm.rm_vObjectPosition; + FLOATplane3D plShadowPlaneObj = (plShadowPlane+vAbsToObj) * mAbsToObj; + + // project object handle so we can calc how it is far away from viewer + const FLOAT3D vRef = plShadowPlaneObj.ProjectPoint(FLOAT3D(0,0,0)) *rm.rm_mObjectToView +rm.rm_vObjectToView; + plShadowPlaneObj.pl_distance += ClampDn( -vRef(3)*0.001f, 0.01f); // move plane towards the viewer a bit to avoid z-fighting + + // find points on plane nearest to bounding box edges + FLOAT3D vMin = rm.rm_vObjectMinBB * 1.25f; + FLOAT3D vMax = rm.rm_vObjectMaxBB * 1.25f; + if( rm.rm_ulFlags & RMF_SPECTATOR) { vMin*=2; vMax*=2; } // enlarge shadow for 1st person view + const FLOAT3D v00 = plShadowPlaneObj.ProjectPoint(FLOAT3D(vMin(1),vMin(2),vMin(3))) *rm.rm_mObjectToView +rm.rm_vObjectToView; + const FLOAT3D v01 = plShadowPlaneObj.ProjectPoint(FLOAT3D(vMin(1),vMin(2),vMax(3))) *rm.rm_mObjectToView +rm.rm_vObjectToView; + const FLOAT3D v10 = plShadowPlaneObj.ProjectPoint(FLOAT3D(vMax(1),vMin(2),vMin(3))) *rm.rm_mObjectToView +rm.rm_vObjectToView; + const FLOAT3D v11 = plShadowPlaneObj.ProjectPoint(FLOAT3D(vMax(1),vMin(2),vMax(3))) *rm.rm_mObjectToView +rm.rm_vObjectToView; + // calc done + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_SIMP_CALC); + + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_SIMP_COPY); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_SIMP_COPY); + + // prepare color + ASSERT( fIntensity>=0 && fIntensity<=1); + ULONG ulAAAA = NormFloatToByte(fIntensity); + ulAAAA |= (ulAAAA<<8) | (ulAAAA<<16); // alpha isn't needed + + // add to vertex arrays + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + // vertices + pvtx[0].x = v00(1); pvtx[0].y = v00(2); pvtx[0].z = v00(3); + pvtx[2].x = v11(1); pvtx[2].y = v11(2); pvtx[2].z = v11(3); + if( rm.rm_ulFlags & RMF_INVERTED) { // must re-adjust order for mirrored projection + pvtx[1].x = v10(1); pvtx[1].y = v10(2); pvtx[1].z = v10(3); + pvtx[3].x = v01(1); pvtx[3].y = v01(2); pvtx[3].z = v01(3); + } else { + pvtx[1].x = v01(1); pvtx[1].y = v01(2); pvtx[1].z = v01(3); + pvtx[3].x = v10(1); pvtx[3].y = v10(2); pvtx[3].z = v10(3); + } + // texture coords + ptex[0].s = 0; ptex[0].t = 0; + ptex[1].s = 0; ptex[1].t = 1; + ptex[2].s = 1; ptex[2].t = 1; + ptex[3].s = 1; ptex[3].t = 0; + // colors + pcol[0].abgr = ulAAAA; + pcol[1].abgr = ulAAAA; + pcol[2].abgr = ulAAAA; + pcol[3].abgr = ulAAAA; + + // if this model has fog + if( rm.rm_ulFlags & RMF_FOG) + { // for each vertex in shadow quad + GFXTexCoord tex; + for( INDEX i=0; i<4; i++) { + GFXVertex &vtx = pvtx[i]; + // get distance along viewer axis and fog axis and map to texture and attenuate shadow color + const FLOAT fH = vtx.x*_fog_vHDirView(1) + vtx.y*_fog_vHDirView(2) + vtx.z*_fog_vHDirView(3); + tex.s = -vtx.z *_fog_fMulZ; + tex.t = (fH+_fog_fAddH) *_fog_fMulH; + pcol[i].AttenuateRGB(GetFogAlpha(tex)^255); + } + } + // if this model has haze + if( rm.rm_ulFlags & RMF_HAZE) + { // for each vertex in shadow quad + for( INDEX i=0; i<4; i++) { + // get distance along viewer axis map to texture and attenuate shadow color + const FLOAT fS = (_haze_fAdd-pvtx[i].z) *_haze_fMul; + pcol[i].AttenuateRGB(GetHazeAlpha(fS)^255); + } + } + + // one simple shadow added to rendering queue + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_SIMP_COPY); + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_RENDERSIMPLESHADOW); +} + + + +// render several simple model shadows +void RenderBatchedSimpleShadows_View(void) +{ + const INDEX ctVertices = _avtxCommon.Count(); + if( ctVertices<=0) return; + // safety checks + ASSERT( _atexCommon.Count()==ctVertices); + ASSERT( _acolCommon.Count()==ctVertices); + _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_SIMP_BATCHED); + _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_SIMP_BATCHED); + + // begin rendering + const BOOL bModelSetupTimer = _sfStats.CheckTimer(CStatForm::STI_MODELSETUP); + if( bModelSetupTimer) _sfStats.StopTimer(CStatForm::STI_MODELSETUP); + _sfStats.StartTimer(CStatForm::STI_MODELRENDERING); + + // setup texture and projection + _bFlatFill = FALSE; + gfxSetViewMatrix(NULL); + gfxCullFace(GFX_BACK); + gfxSetTextureWrapping( GFX_REPEAT, GFX_REPEAT); + CTextureData *ptd = (CTextureData*)_toSimpleModelShadow.GetData(); + SetCurrentTexture( ptd, _toSimpleModelShadow.GetFrame()); + + // setup rendering mode + gfxEnableDepthTest(); + gfxDepthFunc( GFX_LESS_EQUAL); + gfxDisableDepthWrite(); + gfxEnableBlend(); + gfxBlendFunc( GFX_ZERO, GFX_INV_SRC_COLOR); + gfxDisableAlphaTest(); + gfxEnableClipping(); + gfxDisableTruform(); + + // draw! + _pGfx->gl_ctModelTriangles += ctVertices/2; + gfxFlushQuads(); + + // all simple shadows rendered + gfxResetArrays(); + _sfStats.StopTimer(CStatForm::STI_MODELRENDERING); + if( bModelSetupTimer) _sfStats.StartTimer(CStatForm::STI_MODELSETUP); + _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_SIMP_BATCHED); +} + + + + + diff --git a/Sources/Engine/Models/RenderModel_internal.h b/Sources/Engine/Models/RenderModel_internal.h new file mode 100644 index 0000000..723ec7d --- /dev/null +++ b/Sources/Engine/Models/RenderModel_internal.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_RENDERMODEL_INTERNAL_H +#define SE_INCL_RENDERMODEL_INTERNAL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +extern CDrawPort *_pdp; +extern CAnyProjection3D _aprProjection; +extern UBYTE *_pubMask; +extern SLONG _slMaskWidth; +extern SLONG _slMaskHeight; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Models/VertexGetting.cpp b/Sources/Engine/Models/VertexGetting.cpp new file mode 100644 index 0000000..c12ddca --- /dev/null +++ b/Sources/Engine/Models/VertexGetting.cpp @@ -0,0 +1,341 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +extern FLOAT mdl_fLODMul; +extern FLOAT mdl_fLODAdd; +extern const FLOAT *pfSinTable; +extern const FLOAT *pfCosTable; + + +static BOOL _b16Bit; +static FLOAT _fRatio; +static FLOAT3D _vStretch; +static FLOAT3D _vOffset; +static struct ModelFrameVertex8 *_pFrame8_0; // ptr to last frame +static struct ModelFrameVertex16 *_pFrame16_0; +static struct ModelFrameVertex8 *_pFrame8_1; // ptr to next frame +static struct ModelFrameVertex16 *_pFrame16_1; + +void UnpackVertex( const INDEX iVertex, FLOAT3D &vVertex) +{ + if( _b16Bit ) { + // get 16 bit packed vertices + const SWPOINT3D &vsw0 = _pFrame16_0[iVertex].mfv_SWPoint; + const SWPOINT3D &vsw1 = _pFrame16_1[iVertex].mfv_SWPoint; + // convert them to float and lerp between them + vVertex(1) = (Lerp( (FLOAT)vsw0(1), (FLOAT)vsw1(1), _fRatio) -_vOffset(1)) * _vStretch(1); + vVertex(2) = (Lerp( (FLOAT)vsw0(2), (FLOAT)vsw1(2), _fRatio) -_vOffset(2)) * _vStretch(2); + vVertex(3) = (Lerp( (FLOAT)vsw0(3), (FLOAT)vsw1(3), _fRatio) -_vOffset(3)) * _vStretch(3); + } else { + // get 8 bit packed vertices + const SBPOINT3D &vsb0 = _pFrame8_0[iVertex].mfv_SBPoint; + const SBPOINT3D &vsb1 = _pFrame8_1[iVertex].mfv_SBPoint; + // convert them to float and lerp between them + vVertex(1) = (Lerp( (FLOAT)vsb0(1), (FLOAT)vsb1(1), _fRatio) -_vOffset(1)) * _vStretch(1); + vVertex(2) = (Lerp( (FLOAT)vsb0(2), (FLOAT)vsb1(2), _fRatio) -_vOffset(2)) * _vStretch(2); + vVertex(3) = (Lerp( (FLOAT)vsb0(3), (FLOAT)vsb1(3), _fRatio) -_vOffset(3)) * _vStretch(3); + } +} + +void CModelObject::GetModelVertices( CStaticStackArray &avVertices, FLOATmatrix3D &mRotation, + FLOAT3D &vPosition, FLOAT fNormalOffset, FLOAT fMipFactor) +{ + FLOAT3D f3dVertex; + INDEX iFrame0, iFrame1; + FLOAT fLerpRatio; + CModelData *pmd = GetData(); + + struct ModelFrameVertex16 *pFrame16_0, *pFrame16_1; + struct ModelFrameVertex8 *pFrame8_0, *pFrame8_1; + + // get lerp information + GetFrame( iFrame0, iFrame1, fLerpRatio); + + // set pFrame to point to last and next frames' vertices + if( pmd->md_Flags & MF_COMPRESSED_16BIT) + { + pFrame16_0 = &pmd->md_FrameVertices16[ iFrame0 * pmd->md_VerticesCt]; + pFrame16_1 = &pmd->md_FrameVertices16[ iFrame1 * pmd->md_VerticesCt]; + } else { + pFrame8_0 = &pmd->md_FrameVertices8[ iFrame0 * pmd->md_VerticesCt]; + pFrame8_1 = &pmd->md_FrameVertices8[ iFrame1 * pmd->md_VerticesCt]; + } + + // Apply stretch factors + FLOAT3D &vDataStretch = pmd->md_Stretch; + FLOAT3D &vObjectStretch = mo_Stretch; + FLOAT3D vStretch, vOffset; + vStretch(1) = vDataStretch(1)*vObjectStretch(1); + vStretch(2) = vDataStretch(2)*vObjectStretch(2); + vStretch(3) = vDataStretch(3)*vObjectStretch(3); + _vStretch = vStretch; + _vOffset = vOffset = pmd->md_vCompressedCenter; + + // check if object is inverted (in mirror) + BOOL bXInverted = vStretch(1)<0; + BOOL bYInverted = vStretch(2)<0; + BOOL bZInverted = vStretch(3)<0; + BOOL bInverted = bXInverted!=bYInverted!=bZInverted; + + // if dynamic stretch factor should be applied + if( mo_Stretch != FLOAT3D( 1.0f, 1.0f, 1.0f)) { + fMipFactor -= Log2(Max(mo_Stretch(1),Max(mo_Stretch(2),mo_Stretch(3)))); + } + // adjust mip factor by custom settings + fMipFactor = fMipFactor*mdl_fLODMul+mdl_fLODAdd; + + // get current mip model using mip factor + INDEX iMipLevel = GetMipModel( fMipFactor); + // get current vertices mask + ULONG ulVtxMask = (1L) << iMipLevel; + struct ModelMipInfo *pmmiMip = &pmd->md_MipInfos[iMipLevel]; + + // allocate space for vertices + FLOAT3D *pvFirstVtx = avVertices.Push( pmmiMip->mmpi_ctMipVx); + + // Transform a vertex in model with lerping + if( pmd->md_Flags & MF_COMPRESSED_16BIT) { + // for each vertex in mip + for( INDEX iMipVx=0; iMipVxmmpi_ctMipVx; iMipVx++) { + // get destination for unpacking + INDEX iMdlVx = pmmiMip->mmpi_auwMipToMdl[iMipVx]; + ModelFrameVertex16 &mfv0 = pFrame16_0[iMdlVx]; + ModelFrameVertex16 &mfv1 = pFrame16_1[iMdlVx]; + FLOAT3D &v = *pvFirstVtx; + v(1) = (Lerp((FLOAT)mfv0.mfv_SWPoint(1), (FLOAT)mfv1.mfv_SWPoint(1), fLerpRatio)-vOffset(1))*vStretch(1); + v(2) = (Lerp((FLOAT)mfv0.mfv_SWPoint(2), (FLOAT)mfv1.mfv_SWPoint(2), fLerpRatio)-vOffset(2))*vStretch(2); + v(3) = (Lerp((FLOAT)mfv0.mfv_SWPoint(3), (FLOAT)mfv1.mfv_SWPoint(3), fLerpRatio)-vOffset(3))*vStretch(3); + + + FLOAT fSinH = pfSinTable[mfv0.mfv_ubNormH]; + FLOAT fCosH = pfCosTable[mfv0.mfv_ubNormH]; + FLOAT fSinP = pfSinTable[mfv0.mfv_ubNormP]; + FLOAT fCosP = pfCosTable[mfv0.mfv_ubNormP]; + FLOAT fX0 = -fSinH*fCosP; + FLOAT fY0 = +fSinP; + FLOAT fZ0 = -fCosH*fCosP; + + fSinH = pfSinTable[mfv1.mfv_ubNormH]; + fCosH = pfCosTable[mfv1.mfv_ubNormH]; + fSinP = pfSinTable[mfv1.mfv_ubNormP]; + fCosP = pfCosTable[mfv1.mfv_ubNormP]; + FLOAT fX1 = -fSinH*fCosP; + FLOAT fY1 = +fSinP; + FLOAT fZ1 = -fCosH*fCosP; + + FLOAT3D vNor; + vNor(1) = Lerp(fX0, fX1, fLerpRatio); + vNor(2) = Lerp(fY0, fY1, fLerpRatio); + vNor(3) = Lerp(fZ0, fZ1, fLerpRatio); + + v=(v+vNor*fNormalOffset)*mRotation+vPosition; + pvFirstVtx++; + } + } else { + // for each vertex in mip + for( INDEX iMipVx=0; iMipVxmmpi_ctMipVx; iMipVx++) { + // get destination for unpacking + INDEX iMdlVx = pmmiMip->mmpi_auwMipToMdl[iMipVx]; + // get 16 bit packed vertices + ModelFrameVertex8 &mfv0 = pFrame8_0[iMdlVx]; + ModelFrameVertex8 &mfv1 = pFrame8_1[iMdlVx]; + FLOAT3D &v = *pvFirstVtx; + // convert them to float and lerp between them + v(1) = (Lerp((FLOAT)mfv0.mfv_SBPoint(1), (FLOAT)mfv1.mfv_SBPoint(1), fLerpRatio)-vOffset(1))*vStretch(1); + v(2) = (Lerp((FLOAT)mfv0.mfv_SBPoint(2), (FLOAT)mfv1.mfv_SBPoint(2), fLerpRatio)-vOffset(2))*vStretch(2); + v(3) = (Lerp((FLOAT)mfv0.mfv_SBPoint(3), (FLOAT)mfv1.mfv_SBPoint(3), fLerpRatio)-vOffset(3))*vStretch(3); + + FLOAT3D vNor; + const FLOAT3D &vNormal0 = avGouraudNormals[mfv0.mfv_NormIndex]; + const FLOAT3D &vNormal1 = avGouraudNormals[mfv1.mfv_NormIndex]; + vNor(1) = Lerp((FLOAT)vNormal0(1), (FLOAT)vNormal1(1), fLerpRatio); + vNor(2) = Lerp((FLOAT)vNormal0(2), (FLOAT)vNormal1(2), fLerpRatio); + vNor(3) = Lerp((FLOAT)vNormal0(3), (FLOAT)vNormal1(3), fLerpRatio); + + v=(v+vNor*fNormalOffset)*mRotation+vPosition; + pvFirstVtx++; + } + } + + // for each attachment on this model object + FOREACHINLIST( CAttachmentModelObject, amo_lnInMain, mo_lhAttachments, itamo) { + CAttachmentModelObject *pamo = itamo; + CModelData *pmd=pamo->amo_moModelObject.GetData(); + ASSERT(pmd!=NULL); + if(pmd==NULL || pmd->md_Flags&(MF_FACE_FORWARD|MF_HALF_FACE_FORWARD)) continue; + FLOATmatrix3D mNew = mRotation; + FLOAT3D vNew = vPosition; + // get new rotation and position matrices + GetAttachmentMatrices(pamo, mNew, vNew); + // recursion will concate attached model's vertices in absolute space to array + pamo->amo_moModelObject.GetModelVertices(avVertices, mNew, vNew, fNormalOffset, fMipFactor); + } +} + +void CModelObject::GetAttachmentMatrices( CAttachmentModelObject *pamo, FLOATmatrix3D &mRotation, FLOAT3D &vPosition) +{ + // get the position + CModelData *pmdMain = (CModelData *)GetData(); + pmdMain ->md_aampAttachedPosition.Lock(); + const CAttachedModelPosition & = pmdMain->md_aampAttachedPosition[pamo->amo_iAttachedPosition]; + pmdMain ->md_aampAttachedPosition.Unlock(); + + FLOAT3D &vDataStretch = pmdMain->md_Stretch; + FLOAT3D &vObjectStretch = mo_Stretch; + _vStretch(1) = vDataStretch(1)*vObjectStretch(1); + _vStretch(2) = vDataStretch(2)*vObjectStretch(2); + _vStretch(3) = vDataStretch(3)*vObjectStretch(3); + _vOffset = pmdMain->md_vCompressedCenter; + + INDEX iFrame0, iFrame1; + GetFrame( iFrame0, iFrame1, _fRatio); + const INDEX ctVertices = pmdMain->md_VerticesCt; + if( pmdMain->md_Flags & MF_COMPRESSED_16BIT) { + _b16Bit = TRUE; + // set pFrame to point to last and next frames' vertices + _pFrame16_0 = &pmdMain->md_FrameVertices16[iFrame0 *ctVertices]; + _pFrame16_1 = &pmdMain->md_FrameVertices16[iFrame1 *ctVertices]; + } else { + _b16Bit = FALSE; + // set pFrame to point to last and next frames' vertices + _pFrame8_0 = &pmdMain->md_FrameVertices8[iFrame0 *ctVertices]; + _pFrame8_1 = &pmdMain->md_FrameVertices8[iFrame1 *ctVertices]; + } + + // unpack the reference vertices + FLOAT3D vCenter, vFront, vUp; + const INDEX iCenter = amp.amp_iCenterVertex; + const INDEX iFront = amp.amp_iFrontVertex; + const INDEX iUp = amp.amp_iUpVertex; + ::UnpackVertex( iCenter, vCenter); + ::UnpackVertex( iFront, vFront); + ::UnpackVertex( iUp, vUp); + + // create front and up direction vectors + FLOAT3D vY = vUp - vCenter; + FLOAT3D vZ = vCenter - vFront; + // project center and directions from object to absolute space + const FLOATmatrix3D &mO2A = mRotation; + const FLOAT3D &vO2A = vPosition; + vCenter = vCenter*mO2A +vO2A; + vY = vY *mO2A; + vZ = vZ *mO2A; + + // make a rotation matrix from the direction vectors + FLOAT3D vX = vY*vZ; + vY = vZ*vX; + vX.Normalize(); + vY.Normalize(); + vZ.Normalize(); + FLOATmatrix3D mOrientation; + mOrientation(1,1) = vX(1); mOrientation(1,2) = vY(1); mOrientation(1,3) = vZ(1); + mOrientation(2,1) = vX(2); mOrientation(2,2) = vY(2); mOrientation(2,3) = vZ(2); + mOrientation(3,1) = vX(3); mOrientation(3,2) = vY(3); mOrientation(3,3) = vZ(3); + + // adjust for relative placement of the attachment + FLOAT3D vOffset; + FLOATmatrix3D mRelative; + MakeRotationMatrixFast( mRelative, pamo->amo_plRelative.pl_OrientationAngle); + vOffset(1) = pamo->amo_plRelative.pl_PositionVector(1) * mo_Stretch(1); + vOffset(2) = pamo->amo_plRelative.pl_PositionVector(2) * mo_Stretch(2); + vOffset(3) = pamo->amo_plRelative.pl_PositionVector(3) * mo_Stretch(3); + const FLOAT3D vO = vCenter + vOffset * mOrientation; + mRotation = mOrientation*mRelative; + vPosition = vO; +} + +void CModelObject::GetAttachmentTransformations( INDEX iAttachment, FLOATmatrix3D &mRotation, FLOAT3D &vPosition, BOOL bDummyAttachment) +{ + // get the position + CModelData *pmdMain = (CModelData *)GetData(); + pmdMain ->md_aampAttachedPosition.Lock(); + const CAttachedModelPosition & = pmdMain->md_aampAttachedPosition[iAttachment]; + pmdMain ->md_aampAttachedPosition.Unlock(); + + // Apply stretch factors + FLOAT3D &vDataStretch = pmdMain->md_Stretch; + FLOAT3D &vObjectStretch = mo_Stretch; + FLOAT3D vStretch, vOffset; + vStretch(1) = vDataStretch(1)*vObjectStretch(1); + vStretch(2) = vDataStretch(2)*vObjectStretch(2); + vStretch(3) = vDataStretch(3)*vObjectStretch(3); + _vStretch = vStretch; + _vOffset = vOffset = pmdMain->md_vCompressedCenter; + + INDEX iFrame0, iFrame1; + GetFrame( iFrame0, iFrame1, _fRatio); + const INDEX ctVertices = pmdMain->md_VerticesCt; + if( pmdMain->md_Flags & MF_COMPRESSED_16BIT) { + _b16Bit = TRUE; + // set pFrame to point to last and next frames' vertices + _pFrame16_0 = &pmdMain->md_FrameVertices16[iFrame0 *ctVertices]; + _pFrame16_1 = &pmdMain->md_FrameVertices16[iFrame1 *ctVertices]; + } else { + _b16Bit = FALSE; + // set pFrame to point to last and next frames' vertices + _pFrame8_0 = &pmdMain->md_FrameVertices8[iFrame0 *ctVertices]; + _pFrame8_1 = &pmdMain->md_FrameVertices8[iFrame1 *ctVertices]; + } + + // unpack the reference vertices + FLOAT3D vCenter, vFront, vUp; + const INDEX iCenter = amp.amp_iCenterVertex; + const INDEX iFront = amp.amp_iFrontVertex; + const INDEX iUp = amp.amp_iUpVertex; + ::UnpackVertex( iCenter, vCenter); + ::UnpackVertex( iFront, vFront); + ::UnpackVertex( iUp, vUp); + + // create front and up direction vectors + FLOAT3D vY = vUp - vCenter; + FLOAT3D vZ = vCenter - vFront; + // project center and directions from object to absolute space + const FLOATmatrix3D &mO2A = mRotation; + const FLOAT3D &vO2A = vPosition; + vCenter = vCenter*mO2A +vO2A; + vY = vY *mO2A; + vZ = vZ *mO2A; + + // make a rotation matrix from the direction vectors + FLOAT3D vX = vY*vZ; + vY = vZ*vX; + vX.Normalize(); + vY.Normalize(); + vZ.Normalize(); + FLOATmatrix3D mOrientation; + mOrientation(1,1) = vX(1); mOrientation(1,2) = vY(1); mOrientation(1,3) = vZ(1); + mOrientation(2,1) = vX(2); mOrientation(2,2) = vY(2); mOrientation(2,3) = vZ(2); + mOrientation(3,1) = vX(3); mOrientation(3,2) = vY(3); mOrientation(3,3) = vZ(3); + + // adjust for relative placement of the attachment + if (!bDummyAttachment) { + CAttachmentModelObject *amo = GetAttachmentModel(iAttachment); + ASSERT(amo!=NULL); + FLOATmatrix3D mRelative; + MakeRotationMatrixFast( mRelative, amo->amo_plRelative.pl_OrientationAngle); + vOffset(1) = amo->amo_plRelative.pl_PositionVector(1) * mo_Stretch(1); + vOffset(2) = amo->amo_plRelative.pl_PositionVector(2) * mo_Stretch(2); + vOffset(3) = amo->amo_plRelative.pl_PositionVector(3) * mo_Stretch(3); + const FLOAT3D vO = vCenter + vOffset * mOrientation; + mRotation = mOrientation*mRelative; + vPosition = vO; + } + else + { + mRotation = mOrientation; + vPosition = vCenter; + } +} diff --git a/Sources/Engine/Network/ActionBuffer.cpp b/Sources/Engine/Network/ActionBuffer.cpp new file mode 100644 index 0000000..aef0917 --- /dev/null +++ b/Sources/Engine/Network/ActionBuffer.cpp @@ -0,0 +1,124 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include + +class CActionEntry { +public: + CListNode ae_ln; + CPlayerAction ae_pa; +}; + +CActionBuffer::CActionBuffer(void) +{ +} +CActionBuffer::~CActionBuffer(void) +{ + Clear(); +} +void CActionBuffer::Clear(void) +{ + // for each buffered action + FORDELETELIST(CActionEntry, ae_ln, ab_lhActions, itae) { + // delete it + delete &*itae; + } +} + +int qsort_CompareActions(const void *elem1, const void *elem2 ) +{ + const CActionEntry &ae1 = **(CActionEntry **)elem1; + const CActionEntry &ae2 = **(CActionEntry **)elem2; + return ae1.ae_pa.pa_llCreated-ae2.ae_pa.pa_llCreated; +} + +// add a new action to the buffer +void CActionBuffer::AddAction(const CPlayerAction &pa) +{ + // search all buffered actions + FOREACHINLIST(CActionEntry, ae_ln, ab_lhActions, itae) { + CActionEntry &ae = *itae; + // if this is the one + if (ae.ae_pa.pa_llCreated==pa.pa_llCreated) { + // skip adding it again + return; + } + } + + // add to the tail + CActionEntry *pae = new CActionEntry; + pae->ae_pa = pa; + ab_lhActions.AddTail(pae->ae_ln); + + // sort the list + ab_lhActions.Sort(&qsort_CompareActions, offsetof(CActionEntry, ae_ln)); + + //CPrintF("Buffered: %d (after add)\n", ab_lhActions.Count()); +} + +// flush all actions up to given time tag +void CActionBuffer::FlushUntilTime(__int64 llNewest) +{ + // for each buffered action + FORDELETELIST(CActionEntry, ae_ln, ab_lhActions, itae) { + CActionEntry &ae = *itae; + + // if up to that time + if (ae.ae_pa.pa_llCreated<=llNewest) { + // delete it + delete &*itae; + } + } +} + +// remove oldest buffered action +void CActionBuffer::RemoveOldest(void) +{ + // for each buffered action + FORDELETELIST(CActionEntry, ae_ln, ab_lhActions, itae) { + CActionEntry &ae = *itae; + // delete only first one + delete &*itae; + break; + } + //CPrintF("Buffered: %d (after remove)\n", ab_lhActions.Count()); +} + +// get number of actions buffered +INDEX CActionBuffer::GetCount(void) +{ + return ab_lhActions.Count(); +} + +// get an action by its index (0=oldest) +void CActionBuffer::GetActionByIndex(INDEX i, CPlayerAction &pa) +{ + // for each buffered action + INDEX iInList=0; + FOREACHINLIST(CActionEntry, ae_ln, ab_lhActions, itae) { + if (iInList==i) { + pa = itae->ae_pa; + return; + } + iInList++; + } + // if not found, use empty + pa.Clear(); +} + +// get last action older than given timetag +CPlayerAction *CActionBuffer::GetLastOlderThan(__int64 llTime) +{ + CPlayerAction *ppa = NULL; + FOREACHINLIST(CActionEntry, ae_ln, ab_lhActions, itae) { + CActionEntry &ae = *itae; + if (ae.ae_pa.pa_llCreated>=llTime) { + return ppa; + } + ppa = &ae.ae_pa; + } + return ppa; +} diff --git a/Sources/Engine/Network/ActionBuffer.h b/Sources/Engine/Network/ActionBuffer.h new file mode 100644 index 0000000..64fac99 --- /dev/null +++ b/Sources/Engine/Network/ActionBuffer.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ACTIONBUFFER_H +#define SE_INCL_ACTIONBUFFER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +// buffer of player actions, sorted by time of arrival +class CActionBuffer { +public: + CListHead ab_lhActions; +public: + CActionBuffer(void); + ~CActionBuffer(void); + void Clear(void); + + // add a new action to the buffer + void AddAction(const CPlayerAction &pa); + // remove oldest buffered action + void RemoveOldest(void); + // flush all actions up to given time tag + void FlushUntilTime(__int64 llNewest); + // get number of actions buffered + INDEX GetCount(void); + // get an action by its index (0=oldest) + void GetActionByIndex(INDEX i, CPlayerAction &pa); + // get last action older than given timetag + CPlayerAction *GetLastOlderThan(__int64 llTime); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/Buffer.cpp b/Sources/Engine/Network/Buffer.cpp new file mode 100644 index 0000000..91caba2 --- /dev/null +++ b/Sources/Engine/Network/Buffer.cpp @@ -0,0 +1,642 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include + +// default constructor +CBuffer::CBuffer(void) +{ + bu_slAllocationStep = 1024; + bu_slWriteOffset = 0; + bu_slReadOffset = 0; + + bu_slFree = 0; + bu_slSize = 0; + bu_pubBuffer = NULL; +} + +// destructor +CBuffer::~CBuffer(void) +{ + Clear(); +} + +// free buffer +void CBuffer::Clear(void) +{ + bu_slWriteOffset = 0; + bu_slReadOffset = 0; + + if (bu_slSize>0) { + ASSERT(bu_pubBuffer!=NULL); + FreeMemory(bu_pubBuffer); + } + bu_slFree = 0; + bu_slSize = 0; + bu_pubBuffer = NULL; +} + +// expand buffer to be given number of bytes in size +void CBuffer::Expand(SLONG slNewSize) +{ + ASSERT(slNewSize>0); + ASSERT(bu_slSize>=0); + // if not already allocated + if (bu_slSize==0) { + // allocate a new empty buffer + ASSERT(bu_pubBuffer==NULL); + bu_pubBuffer = (UBYTE*)AllocMemory(slNewSize); + bu_slWriteOffset = 0; + bu_slReadOffset = 0; + bu_slFree = slNewSize; + bu_slSize = slNewSize; + + // if already allocated + } else { + ASSERT(slNewSize>bu_slSize); + SLONG slSizeDiff = slNewSize-bu_slSize; + ASSERT(bu_pubBuffer!=NULL); + // grow buffer + GrowMemory((void**)&bu_pubBuffer, slNewSize); + + // if buffer is currently wrapping + if (bu_slReadOffset>bu_slWriteOffset||bu_slFree==0) { + // move part at the end of buffer to the end + memmove(bu_pubBuffer+bu_slReadOffset+slSizeDiff, bu_pubBuffer+bu_slReadOffset, + bu_slSize-bu_slReadOffset); + bu_slReadOffset+=slSizeDiff; + } + bu_slFree += slNewSize-bu_slSize; + bu_slSize = slNewSize; + + ASSERT(bu_slReadOffset>=0 && bu_slReadOffset=0 && bu_slFree<=bu_slSize); + } +} + +// set how many bytes to add when buffer overflows +void CBuffer::SetAllocationStep(SLONG slStep) +{ + ASSERT(slStep>0); + bu_slAllocationStep = slStep; +} + +// read bytes from buffer +SLONG CBuffer::ReadBytes(void *pv, SLONG slSize) +{ + ASSERT(slSize>0 && pv!=NULL); + UBYTE *pub = (UBYTE*)pv; + + // clamp size to amount of bytes actually in the buffer + SLONG slUsed = bu_slSize-bu_slFree; + if (slUsed=0 && bu_slReadOffset=0 && bu_slFree<=bu_slSize); + + return slSize; +} + +// skip bytes from buffer (read without actually reading) +SLONG CBuffer::SkipBytes(SLONG slSize) +{ + ASSERT(slSize>0); + + // clamp size to amount of bytes actually in the buffer + SLONG slUsed = bu_slSize-bu_slFree; + if (slUsed=0 && bu_slReadOffset=0 && bu_slFree<=bu_slSize); + + return slSize; +} + +// read bytes from buffer to stream +SLONG CBuffer::ReadBytesToStream(CTStream &strm, SLONG slSize) +{ + ASSERT(slSize>0); + + // clamp size to amount of bytes actually in the buffer + SLONG slUsed = bu_slSize-bu_slFree; + if (slUsed=0 && bu_slReadOffset=0 && bu_slFree<=bu_slSize); + + return slSize; +} + +// unread bytes from buffer +void CBuffer::UnreadBytes(SLONG slSize) +{ + ASSERT(bu_slFree>=slSize); + + if (slSize==0) return; + bu_slReadOffset-=slSize; + bu_slReadOffset%=bu_slSize; + if (bu_slReadOffset<0) { + bu_slReadOffset+=bu_slSize; + } + bu_slFree-=slSize; + + ASSERT(bu_slReadOffset>=0 && bu_slReadOffset=0 && bu_slFree<=bu_slSize); +} + +// check how many bytes are there to read +SLONG CBuffer::QueryReadBytes(void) +{ + // return amount of bytes actually in the buffer + return bu_slSize-bu_slFree; +} + +// write bytes to buffer +void CBuffer::WriteBytes(const void *pv, SLONG slSize) +{ + ASSERT(slSize>=0 && pv!=NULL); + // if there is nothing to write + if (slSize==0) { + // do nothing + return; + } + // check for errors + if (slSize<0) { + CPrintF("WARNING: WriteBytes(): slSize<0\n!"); + return; + } + + // if there is not enough free space + if (bu_slFree=slSize); + } + + UBYTE *pub = (UBYTE*)pv; + + // write part of block at the end of buffer + SLONG slSizeEnd = __min(bu_slSize-bu_slWriteOffset, slSize); + memcpy(bu_pubBuffer+bu_slWriteOffset, pub, slSizeEnd); + pub+=slSizeEnd; + memcpy(bu_pubBuffer, pub, slSize-slSizeEnd); + // move write pointer + bu_slWriteOffset+=slSize; + bu_slWriteOffset%=bu_slSize; + bu_slFree-=slSize; + + ASSERT(bu_slWriteOffset>=0 && bu_slWriteOffset=0 && bu_slFree<=bu_slSize); +} + +// move all data from another buffer to this one +void CBuffer::MoveBuffer(CBuffer &buFrom) +{ + // repeat + for(;;){ + // read a block from the other buffer + UBYTE aub[256]; + SLONG slSize = buFrom.ReadBytes(aub, sizeof(aub)); + // if nothing read + if (slSize<=0) { + // stop + return; + } + // write here what was read + WriteBytes(&aub, slSize); + } +} + +void CBlockBufferStats::Clear(void) +{ + bbs_tvTimeUsed.Clear(); +} + +// get time when block of given size will be finished if started now +CTimerValue CBlockBufferStats::GetBlockFinalTime(SLONG slSize) +{ + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + + // calculate how much should block be delayed due to latency and due to bandwidth + CTimerValue tvBandwidth; + if (bbs_fBandwidthLimit<=0.0f) { + tvBandwidth = CTimerValue(0.0); + } else { + tvBandwidth = CTimerValue(DOUBLE((slSize*8)/bbs_fBandwidthLimit)); + } + CTimerValue tvLatency; + if (bbs_fLatencyLimit<=0.0f && bbs_fLatencyVariation<=0.0f) { + tvLatency = CTimerValue(0.0); + } else { + tvLatency = CTimerValue(DOUBLE(bbs_fLatencyLimit+(bbs_fLatencyVariation*rand())/RAND_MAX)); + } + + // start of packet receiving is later of + CTimerValue tvStart( + Max( + // current time plus latency and + (tvNow+tvLatency).tv_llValue, + // next free point in time + bbs_tvTimeUsed.tv_llValue)); + // remember next free time and return it + bbs_tvTimeUsed = tvStart+tvBandwidth; + return bbs_tvTimeUsed; +} + +// default constructor +CBlockBuffer::CBlockBuffer(void) +{ + bb_slBlockSizeRead = 0; + bb_slBlockSizeWrite = 0; + bb_pbbsStats = NULL; +} + +// destructor +CBlockBuffer::~CBlockBuffer(void) +{ + bb_slBlockSizeRead = 0; + bb_slBlockSizeWrite = 0; + bb_pbbsStats = NULL; +} + +// free buffer +void CBlockBuffer::Clear(void) +{ + bb_slBlockSizeRead = 0; + bb_slBlockSizeWrite = 0; + bb_pbbsStats = NULL; + CBuffer::Clear(); +} + + +struct BlockHeader { + SLONG bh_slSize; // block size + CTimerValue bh_tvFinalTime; // block may be read only after this moment in time +}; + +// read one block if possible +BOOL CBlockBuffer::ReadBlock(void *pv, SLONG &slSize) +{ + // must not be inside block reading + ASSERT(bb_slBlockSizeRead==0); + + // read header of next block in incoming buffer + struct BlockHeader bh; + SLONG slbhSize; + slbhSize = ReadBytes(&bh, sizeof(bh)); + + // if the header information is not in buffer + if (slbhSize < sizeof(bh)) { + // unwind + UnreadBytes(slbhSize); + // nothing to receive + return FALSE; + } + + // if the block has not yet been received + if (QueryReadBytes() < bh.bh_slSize) { + // unwind + UnreadBytes(slbhSize); + // nothing to receive + return FALSE; + } + + // if there is too much data for the receiving memory space + if (bh.bh_slSize > slSize) { + // unwind + UnreadBytes(slbhSize); + // mark how much space we would need + slSize = bh.bh_slSize; + // nothing to receive + ASSERT(FALSE); // this shouldn't happen + return FALSE; + } + + // if using stats + if (bb_pbbsStats!=NULL) { + // if block could not have been received yet, due to time limits + if (bh.bh_tvFinalTime>_pTimer->GetHighPrecisionTimer()) { + // unwind + UnreadBytes(slbhSize); + // nothing to receive + return FALSE; + } + } + + // read the block + slSize = ReadBytes(pv, bh.bh_slSize); + ASSERT(slSize == bh.bh_slSize); + + // received + return TRUE; +} + +// read one block from buffer to stream +BOOL CBlockBuffer::ReadBlockToStream(CTStream &strm) +{ + // must not be inside block reading + ASSERT(bb_slBlockSizeRead==0); + + // read header of next block in incoming buffer + struct BlockHeader bh; + SLONG slbhSize; + slbhSize = ReadBytes(&bh, sizeof(bh)); + + // if the header information is not in buffer + if (slbhSize < sizeof(bh)) { + // unwind + UnreadBytes(slbhSize); + // nothing to receive + return FALSE; + } + + // if the block has not yet been received + if (QueryReadBytes() < bh.bh_slSize) { + // unwind + UnreadBytes(slbhSize); + // nothing to receive + return FALSE; + } + + // if using stats + if (bb_pbbsStats!=NULL) { + // if block could not have been received yet, due to time limits + if (bh.bh_tvFinalTime>_pTimer->GetHighPrecisionTimer()) { + // unwind + UnreadBytes(slbhSize); + // nothing to receive + return FALSE; + } + } + + // read from buffer to destination buffer + try { + SLONG slSize = ReadBytesToStream(strm, bh.bh_slSize); + ASSERT(slSize == bh.bh_slSize); + } catch (char *strError) { + ASSERT(FALSE); + CPrintF(TRANS("Buffer error reading to stream: %s\n"), strError); + return FALSE; + } + + return TRUE; +} + +// write one block +void CBlockBuffer::WriteBlock(const void *pv, SLONG slSize) +{ + // must not be inside block writing + ASSERT(bb_slBlockSizeWrite==0); + + // prepare block header + struct BlockHeader bh; + bh.bh_slSize = slSize; + if (bb_pbbsStats!=NULL) { + bh.bh_tvFinalTime = bb_pbbsStats->GetBlockFinalTime(slSize); + } else { + bh.bh_tvFinalTime.Clear(); + } + // write the data to send-buffer + WriteBytes((void*)&bh, sizeof(bh)); + WriteBytes(pv, slSize); +} + +// unread one block +void CBlockBuffer::UnreadBlock(SLONG slSize) +{ + UnreadBytes(slSize+sizeof(struct BlockHeader)); +} + +// read raw block data +SLONG CBlockBuffer::ReadRawBlock(void *pv, SLONG slSize) +{ + // if inside block reading + if(bb_slBlockSizeRead>0) { + // clamp size to prevent reading across real blocks + slSize = Min(slSize, bb_slBlockSizeRead); + + // read the raw block + SLONG slResult = ReadBytes(pv, slSize); + ASSERT(slResult==slSize); + // decrement block size counter + bb_slBlockSizeRead-=slResult; + // must not underflow + ASSERT(bb_slBlockSizeRead>=0); + return slResult; + + // if not inside block reading + } else { + // read header of next block in incoming buffer + struct BlockHeader bh; + SLONG slbhSize; + slbhSize = ReadBytes(&bh, sizeof(bh)); + + // if the header information is not in buffer + if (slbhSize < sizeof(bh)) { + // unwind + UnreadBytes(slbhSize); + // nothing to receive + return FALSE; + } + + // if the block has not yet been received + if (QueryReadBytes() < bh.bh_slSize) { + // unwind + UnreadBytes(slbhSize); + // nothing to receive + return FALSE; + } + + // if using stats + if (bb_pbbsStats!=NULL) { + // if block could not have been received yet, due to time limits + if (bh.bh_tvFinalTime>_pTimer->GetHighPrecisionTimer()) { + // unwind + UnreadBytes(slbhSize); + // nothing to receive + return FALSE; + } + } + + // remember block size counter + bb_slBlockSizeRead = bh.bh_slSize+sizeof(struct BlockHeader); + // unwind header + UnreadBytes(slbhSize); + + // clamp size to prevent reading across real blocks + slSize = Min(slSize, bb_slBlockSizeRead); + + // read the raw block with header + SLONG slResult = ReadBytes(pv, slSize); + ASSERT(slResult==slSize); + // decrement block size counter + bb_slBlockSizeRead-=slResult; + // must not underflow + ASSERT(bb_slBlockSizeRead>=0); + + return slResult; + } +} + +// write raw block data +void CBlockBuffer::WriteRawBlock(const void *pv, SLONG slSize) +{ + // while there is something to write + while (slSize>0) { + + // if inside block writing + if(bb_slBlockSizeWrite>0) { + SLONG slToWrite = Min(bb_slBlockSizeWrite, slSize); + // write the raw block + WriteBytes(pv, slToWrite); + slSize-=slToWrite; + ((UBYTE*&)pv)+=slToWrite; + // decrement block size counter + bb_slBlockSizeWrite-=slToWrite; + // must not underflow + ASSERT(bb_slBlockSizeWrite>=0); + + // if not inside block writing + } else { + // must contain at least the header + ASSERT(slSize>sizeof(struct BlockHeader)); + // find the header in the raw block + struct BlockHeader &bh = *(struct BlockHeader*)pv; + // remember block size counter + bb_slBlockSizeWrite = bh.bh_slSize+sizeof(struct BlockHeader); + // create new block timestamp + if (bb_pbbsStats!=NULL) { + bh.bh_tvFinalTime = bb_pbbsStats->GetBlockFinalTime(bb_slBlockSizeWrite); + } else { + bh.bh_tvFinalTime.Clear(); + } + + SLONG slToWrite = Min(bb_slBlockSizeWrite, slSize); + // write the raw block, with the new header + WriteBytes(pv, slToWrite); + slSize-=slToWrite; + ((UBYTE*&)pv)+=slToWrite; + // decrement block size counter + bb_slBlockSizeWrite-=slToWrite; + // must not underflow + ASSERT(bb_slBlockSizeWrite>=0); + } + } +} + +// peek sizes of next block +void CBlockBuffer::PeekBlockSize(SLONG &slExpectedSize, SLONG &slReceivedSoFar) +{ + // if inside block reading + if(bb_slBlockSizeRead>0) { + // no information available + slExpectedSize = 0; + slReceivedSoFar = 0; + + // if not inside block reading + } else { + // read header of next block in incoming buffer + struct BlockHeader bh; + SLONG slbhSize; + slbhSize = ReadBytes(&bh, sizeof(bh)); + // unwind + UnreadBytes(slbhSize); + + // if the header information is not in buffer + if (slbhSize < sizeof(bh)) { + // no information available + slExpectedSize = 0; + slReceivedSoFar = 0; + // if the header information is present + } else { + // total size is size of block + slExpectedSize = bh.bh_slSize; + // received so far is how much is really present + slReceivedSoFar = QueryReadBytes()-sizeof(struct BlockHeader); + } + } +} + +// unread raw block data +void CBlockBuffer::UnreadRawBlock(SLONG slSize) +{ + bb_slBlockSizeRead+=slSize; + UnreadBytes(slSize); +} + +// move all data from another buffer to this one +void CBlockBuffer::MoveBlockBuffer(CBlockBuffer &buFrom) +{ + // repeat + for(;;){ + // read a block from the other buffer + UBYTE aub[256]; + SLONG slSize = buFrom.ReadRawBlock(aub, sizeof(aub)); + // if nothing read + if (slSize<=0) { + // stop + return; + } + // write here what was read + WriteRawBlock(&aub, slSize); + } +} diff --git a/Sources/Engine/Network/Buffer.h b/Sources/Engine/Network/Buffer.h new file mode 100644 index 0000000..c5e6e9f --- /dev/null +++ b/Sources/Engine/Network/Buffer.h @@ -0,0 +1,102 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_BUFFER_H +#define SE_INCL_BUFFER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Class for buffering data streams at byte level. + */ +class CBuffer { +public: + SLONG bu_slAllocationStep; // how many bytes to add when buffer overflows + SLONG bu_slWriteOffset; // where to write to next + SLONG bu_slReadOffset; // where to read from next + + SLONG bu_slFree; // number of bytes free + SLONG bu_slSize; // current buffer size + UBYTE *bu_pubBuffer; // buffer memory + + // default constructor + CBuffer(void); + // destructor + ~CBuffer(void); + // free buffer + void Clear(void); + // expand buffer to be given number of bytes in size + void Expand(SLONG slNewSize); + // set how many bytes to add when buffer overflows + void SetAllocationStep(SLONG slStep); + // read bytes from buffer + SLONG ReadBytes(void *pv, SLONG slSize); + // skip bytes from buffer (read without actually reading) + SLONG SkipBytes(SLONG slSize); + // read bytes from buffer to stream + SLONG ReadBytesToStream(CTStream &strm, SLONG slSize); + // unread bytes from buffer + void UnreadBytes(SLONG slSize); + // check how many bytes are there to read + SLONG QueryReadBytes(void); + // write bytes to buffer + void WriteBytes(const void *pv, SLONG slSize); + // move all data from another buffer to this one + void MoveBuffer(CBuffer &buFrom); +}; + +// data for limiting bandwidth/lantency and calculating statistics in block-buffers +class CBlockBufferStats { +public: + FLOAT bbs_fLatencyLimit; // minimum latency in seconds + FLOAT bbs_fLatencyVariation;// additional latency variation + FLOAT bbs_fBandwidthLimit; // maximum bandwidth in bps (bits per second) + CTimerValue bbs_tvTimeUsed; // next point in time free for data receiving + + void Clear(void); + // get time when block of given size will be finished if started now + CTimerValue GetBlockFinalTime(SLONG slSize); +}; + +/* + * Class for buffering data streams at block level. + */ +class CBlockBuffer : public CBuffer { +public: + CBlockBufferStats *bb_pbbsStats; // for bandwidth/latency stats and limits + SLONG bb_slBlockSizeRead; // block size left for reading (0 if not inside block) + SLONG bb_slBlockSizeWrite; // block size left for writing (0 if not inside block) + + // default constructor + CBlockBuffer(void); + // destructor + ~CBlockBuffer(void); + // free buffer + void Clear(void); + + // read one block if possible + BOOL ReadBlock(void *pv, SLONG &slSize); + // read one block from buffer to stream + BOOL ReadBlockToStream(CTStream &strm); + // write one block + void WriteBlock(const void *pv, SLONG slSize); + // unread one block + void UnreadBlock(SLONG slSize); + + // read raw block data + SLONG ReadRawBlock(void *pv, SLONG slSize); + // write raw block data + void WriteRawBlock(const void *pv, SLONG slSize); + // unread raw block data + void UnreadRawBlock(SLONG slSize); + // move all data from another buffer to this one + void MoveBlockBuffer(CBlockBuffer &buFrom); + // peek sizes of next block + void PeekBlockSize(SLONG &slExpectedSize, SLONG &slReceivedSoFar); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/CPacket.cpp b/Sources/Engine/Network/CPacket.cpp new file mode 100644 index 0000000..e7acbaf --- /dev/null +++ b/Sources/Engine/Network/CPacket.cpp @@ -0,0 +1,686 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include + +#include + +// should the packet transfers in/out of the buffer be reported to the console +extern INDEX net_bReportPackets; +extern INDEX net_iMaxSendRetries; +extern FLOAT net_fSendRetryWait; + +#define MAX_RETRIES 10 +#define RETRY_INTERVAL 3.0f + +// make the address broadcast +void CAddress::MakeBroadcast(void) +{ + adr_ulAddress = INADDR_BROADCAST; + extern INDEX net_iPort; + adr_uwPort = net_iPort; + adr_uwID = 0; +} + + + +/* +* +* CPacket class implementation +* +*/ + +// copy constructor +CPacket::CPacket(CPacket &paOriginal) +{ + + ASSERT(paOriginal.pa_pubPacketData != NULL && paOriginal.pa_slSize > 0); + + pa_slSize = paOriginal.pa_slSize; + pa_slTransferSize = paOriginal.pa_slTransferSize; + + pa_ulSequence = paOriginal.pa_ulSequence; + pa_ubReliable = paOriginal.pa_ubReliable; + pa_tvSendWhen = paOriginal.pa_tvSendWhen; + pa_ubRetryNumber = paOriginal.pa_ubRetryNumber; + pa_adrAddress.adr_ulAddress = paOriginal.pa_adrAddress.adr_ulAddress; + pa_adrAddress.adr_uwPort = paOriginal.pa_adrAddress.adr_uwPort; + pa_adrAddress.adr_uwID = paOriginal.pa_adrAddress.adr_uwID; + + memcpy(pa_pubPacketData,paOriginal.pa_pubPacketData,pa_slSize); + +}; + +// initialization of the packet - clear all data and remove the packet from any list (buffer) it is in +void CPacket::Clear() +{ + + pa_slSize = 0; + pa_slTransferSize = 0; + pa_ubReliable = UDP_PACKET_UNRELIABLE; + pa_ubRetryNumber = 0; + + pa_tvSendWhen = CTimerValue(0.0f); + if(pa_lnListNode.IsLinked()) pa_lnListNode.Remove(); + +}; + +void CPacket::operator=(const CPacket &paOriginal) +{ + ASSERT(paOriginal.pa_pubPacketData != NULL && paOriginal.pa_slSize > 0); + + pa_slSize = paOriginal.pa_slSize; + pa_slTransferSize = paOriginal.pa_slTransferSize; + + pa_ulSequence = paOriginal.pa_ulSequence; + pa_ubReliable = paOriginal.pa_ubReliable; + pa_tvSendWhen = paOriginal.pa_tvSendWhen; + pa_ubRetryNumber = paOriginal.pa_ubRetryNumber; + pa_adrAddress.adr_ulAddress = paOriginal.pa_adrAddress.adr_ulAddress; + pa_adrAddress.adr_uwPort = paOriginal.pa_adrAddress.adr_uwPort; + pa_adrAddress.adr_uwID = paOriginal.pa_adrAddress.adr_uwID; + + memcpy(pa_pubPacketData,paOriginal.pa_pubPacketData,pa_slSize); + +}; + + +// Takes data from a pointer, adds the packet header and copies the data to the packet +BOOL CPacket::WriteToPacket(void* pv,SLONG slSize,UBYTE ubReliable,ULONG ulSequence,UWORD uwClientID,SLONG slTransferSize) +{ + UBYTE* pubData; + + ASSERT(slSize <= MAX_UDP_BLOCK_SIZE && slSize > 0); + ASSERT(pv != NULL); + ASSERT(slTransferSize >= slSize); + + // set packet properties to values received as parameters + pa_ubReliable = ubReliable; + pa_adrAddress.adr_uwID = uwClientID; + pa_ulSequence = ulSequence; + pa_slSize = slSize + MAX_HEADER_SIZE; + pa_slTransferSize = slTransferSize; + + // insert packet header to the beginning of the packet data + pubData = pa_pubPacketData; + *pubData = pa_ubReliable; + pubData++; + + *(ULONG*)pubData = pa_ulSequence; + pubData+=sizeof(pa_ulSequence); + + *(UWORD*)pubData = pa_adrAddress.adr_uwID; + pubData+=sizeof(pa_adrAddress.adr_uwID); + + *(SLONG*)pubData = pa_slTransferSize; + pubData+=sizeof(pa_slTransferSize); + + // copy the data the packet is to contain + memcpy(pubData,pv,slSize); + + + + return TRUE; + +}; + + +// Takes data from a pointer, reads the packet header and copies the data to the packet +BOOL CPacket::WriteToPacketRaw(void* pv,SLONG slSize) +{ + UBYTE* pubData; + + ASSERT(slSize <= MAX_PACKET_SIZE && slSize > 0); + ASSERT(pv != NULL); + + // get the packet properties from the pointer, and set the values + pubData = (UBYTE*)pv; + pa_ubReliable = *pubData; + pubData++; + pa_ulSequence = *(ULONG*)pubData; + pubData+=sizeof(pa_ulSequence); + pa_adrAddress.adr_uwID = *(UWORD*)pubData; + pubData+=sizeof(pa_adrAddress.adr_uwID); + pa_slTransferSize = *(SLONG*)pubData; + pubData+=sizeof(pa_slTransferSize); + + pa_slSize = slSize; + + // transfer the data to the packet + memcpy(pa_pubPacketData,pv,pa_slSize); + + return TRUE; + +}; + + +// Copies the data from the packet to the location specified by the *pv. +// packet header data is skipped +BOOL CPacket::ReadFromPacket(void* pv,SLONG &slExpectedSize) +{ + UBYTE* pubData; + + ASSERT(slExpectedSize > 0); + ASSERT(pv != NULL); + ASSERT(pa_pubPacketData != NULL); + + if (slExpectedSize < (pa_slSize - MAX_HEADER_SIZE)) { + return FALSE; + } + + // how much data is actually returned + slExpectedSize = pa_slSize - MAX_HEADER_SIZE; + + // skip the header data + pubData = pa_pubPacketData + sizeof(pa_ubReliable) + sizeof(pa_ulSequence) + sizeof(pa_adrAddress.adr_uwID) + sizeof(pa_slTransferSize); + + memcpy(pv,pubData,slExpectedSize); + + return TRUE; + +}; + +// is the packet reliable? +BOOL CPacket::IsReliable() +{ + return pa_ubReliable; +}; + +// is the packet a head of a reliable stream +BOOL CPacket::IsReliableHead() +{ + return pa_ubReliable & UDP_PACKET_RELIABLE_HEAD; +}; + +// is the packet a tail of a reliable stream +BOOL CPacket::IsReliableTail() +{ + return pa_ubReliable & UDP_PACKET_RELIABLE_TAIL; +}; + +// return the sequence of a packet +ULONG CPacket::GetSequence() +{ + ASSERT(pa_ubReliable); + return pa_ulSequence; +}; + +// return the retry status of a packet - can retry now, later or not at all +UBYTE CPacket::CanRetry() +{ + + if (pa_ubRetryNumber >= net_iMaxSendRetries) { + return RS_NOTATALL; + } + + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + + if (tvNow < (pa_tvSendWhen + CTimerValue(net_fSendRetryWait * (pa_ubRetryNumber + 1)))) { + return RS_NOTNOW; + } + + return RS_NOW; + +}; + +//drop the packet from a list (buffer) +void CPacket::Drop() +{ + if (pa_lnListNode.IsLinked()) { + pa_lnListNode.Remove(); + } +}; + +SLONG CPacket::GetTransferSize() +{ + return pa_slTransferSize; +}; + +BOOL CPacket::IsBroadcast() +{ + if (pa_adrAddress.adr_uwID == '//' || pa_adrAddress.adr_uwID == 0) { + return TRUE; + } + + return FALSE; + +}; + + +/* +* +* +* CPacketBufferStats Class implementation +* +* +*/ + +// this class is used for MaxBPS limitation (prevets flooding the client) and for bandwidth limit and latency emulation +void CPacketBufferStats::Clear(void) +{ + + pbs_fBandwidthLimit = 0; + pbs_fLatencyLimit = 0.0f; + pbs_fLatencyVariation = 0.0f; + pbs_tvTimeNextPacketStart = _pTimer->GetHighPrecisionTimer(); + +}; + +// when can a certian ammount of data be sent? +CTimerValue CPacketBufferStats::GetPacketSendTime(SLONG slSize) +{ + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + + // calculate how much should the packet be delayed due to latency and due to bandwidth + CTimerValue tvBandwidth; + if (pbs_fBandwidthLimit<=0.0f) { + tvBandwidth = CTimerValue(0.0); + } else { + tvBandwidth = CTimerValue(DOUBLE((slSize*8)/pbs_fBandwidthLimit)); + } + CTimerValue tvLatency; + if (pbs_fLatencyLimit<=0.0f && pbs_fLatencyVariation<=0.0f) { + tvLatency = CTimerValue(0.0); + } else { + tvLatency = CTimerValue(DOUBLE(pbs_fLatencyLimit+(pbs_fLatencyVariation*rand())/RAND_MAX)); + } + + // time when the packet should be sent is max of + CTimerValue tvStart( + Max( + // current time plus latency and + (tvNow+tvLatency).tv_llValue, + // next free point in time + pbs_tvTimeNextPacketStart.tv_llValue)); + // remember next free time and return it + pbs_tvTimeNextPacketStart = tvStart+tvBandwidth; + return pbs_tvTimeNextPacketStart; + +}; + + + + +/* +* +* CPacketBuffer Class implementation +* +*/ + + +// Empty the packet buffer +void CPacketBuffer::Clear() +{ + + pb_lhPacketStorage.Clear(); + + pb_ulNumOfPackets = 0; + pb_ulNumOfReliablePackets = 0; + pb_ulTotalSize = 0; + pb_ulLastSequenceOut = 0; + + pb_pbsLimits.Clear(); + +}; + + +// Is the packet buffer empty? +BOOL CPacketBuffer::IsEmpty() +{ + + if (pb_ulNumOfPackets>0) { + return FALSE; + } + + return TRUE; +}; + + +// Calculate when the packet can be output from the buffer +CTimerValue CPacketBuffer::GetPacketSendTime(SLONG slSize) { + CTimerValue tvSendTime; + + // if traffic emulation is in use, use the time with the lower bandwidth limit + if (pb_ppbsStats != NULL) { + if (pb_ppbsStats->pbs_fBandwidthLimit > 0.0f && pb_ppbsStats->pbs_fBandwidthLimit < pb_pbsLimits.pbs_fBandwidthLimit) { + tvSendTime = pb_ppbsStats->GetPacketSendTime(slSize); + pb_pbsLimits.pbs_tvTimeNextPacketStart = tvSendTime; + } else { + tvSendTime = pb_pbsLimits.GetPacketSendTime(slSize); + pb_ppbsStats->pbs_tvTimeNextPacketStart = tvSendTime; + } + // else just use the MaxBPS control + } else { + tvSendTime = pb_pbsLimits.GetPacketSendTime(slSize); + } + + return tvSendTime; +}; + +// Adds the packet to the end of the list +BOOL CPacketBuffer::AppendPacket(CPacket &paPacket,BOOL bDelay) +{ + + // bDelay regulates if the packet should be delayed because of the bandwidth limits or not + // internal buffers (reliable, waitack and master buffers) do not pay attention to bandwidth limits + if (bDelay) { + paPacket.pa_tvSendWhen = GetPacketSendTime(paPacket.pa_slSize); + } else { + paPacket.pa_tvSendWhen = _pTimer->GetHighPrecisionTimer(); + } + + // Add the packet to the end of the list + pb_lhPacketStorage.AddTail(paPacket.pa_lnListNode); + pb_ulNumOfPackets++; + + // if the packet is reliable, bump up the number of reliable packets + if (paPacket.pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets++; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize += paPacket.pa_slSize - MAX_HEADER_SIZE; + return TRUE; + +}; + +// Inserts the packet in the buffer, according to it's sequence number +BOOL CPacketBuffer::InsertPacket(CPacket &paPacket,BOOL bDelay) +{ + + // find the right place to insert this packet (this is if this packet is out of sequence) + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + // if there is a packet in the buffer with greater sequence number, insert this one before it + if (paPacket.pa_ulSequence < litPacketIter->pa_ulSequence) { + + // bDelay regulates if the packet should be delayed because of the bandwidth limits or not + // internal buffers (reliable, waitack and master buffers) do not pay attention to bandwidth limits + if (bDelay) { + paPacket.pa_tvSendWhen = GetPacketSendTime(paPacket.pa_slSize); + } else { + paPacket.pa_tvSendWhen = _pTimer->GetHighPrecisionTimer(); + } + + litPacketIter.InsertBeforeCurrent(paPacket.pa_lnListNode); + pb_ulNumOfPackets++; + + // if the packet is reliable, bump up the number of reliable packets + if (paPacket.pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets++; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize += paPacket.pa_slSize - MAX_HEADER_SIZE; + + + return TRUE; + + // if there already is a packet in the buffer with the same sequence, do nothing + } else if (paPacket.pa_ulSequence == litPacketIter->pa_ulSequence) { + return FALSE; + } + } + + // if this packet has the greatest sequence number so far, add it to the end of the list + pb_lhPacketStorage.AddTail(paPacket.pa_lnListNode); + pb_ulNumOfPackets++; + + + // if the packet is reliable, bump up the number of reliable packets + if (paPacket.pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets++; + } + + pb_ulTotalSize += paPacket.pa_slSize - MAX_HEADER_SIZE; + + return TRUE; + +}; + + +// Bumps up the retry count and time, and appends the packet to the buffer +BOOL CPacketBuffer::Retry(CPacket &paPacket) +{ + paPacket.pa_ubRetryNumber++; + + if (net_bReportPackets == TRUE) { + CPrintF("Retrying sequence: %d, reliable flag: %d\n",paPacket.pa_ulSequence,paPacket.pa_ubReliable); + } + + return AppendPacket(paPacket,TRUE); +}; + +// Reads the data from the first packet in the bufffer, but does not remove it +CPacket* CPacketBuffer::PeekFirstPacket() +{ + ASSERT(pb_ulNumOfPackets != 0); + return LIST_HEAD(pb_lhPacketStorage,CPacket,pa_lnListNode); +}; + +// Reads the first packet in the bufffer, and removes it from the buffer +CPacket* CPacketBuffer::GetFirstPacket() +{ + ASSERT(pb_ulNumOfPackets != 0); + + CPacket* ppaHead = LIST_HEAD(pb_lhPacketStorage,CPacket,pa_lnListNode); + + // remove the first packet from the start of the list + pb_lhPacketStorage.RemHead(); + pb_ulNumOfPackets--; + if (ppaHead->pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets--; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (ppaHead->pa_slSize - MAX_HEADER_SIZE); + + // mark the last packet sequence that was output from the buffer - helps to prevent problems wit duplicated packets + if (pb_ulLastSequenceOut < ppaHead->pa_ulSequence) { + pb_ulLastSequenceOut = ppaHead->pa_ulSequence; + } + + return ppaHead; + +}; + +// Reads the data from the packet with the requested sequence, but does not remove it +CPacket* CPacketBuffer::PeekPacket(ULONG ulSequence) +{ + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ulSequence == ulSequence) { + return litPacketIter; + } + } + return NULL; +}; + +// Returns te packet with the matching sequence from the buffer +CPacket* CPacketBuffer::GetPacket(ULONG ulSequence) +{ + + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ulSequence == ulSequence) { + litPacketIter->pa_lnListNode.Remove(); + + pb_ulNumOfPackets--; + if (litPacketIter->pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets--; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (litPacketIter->pa_slSize - MAX_HEADER_SIZE); + + return litPacketIter; + } + } + return NULL; +}; + +// Reads the first connection request packet from the buffer +CPacket* CPacketBuffer::GetConnectRequestPacket() { + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ubReliable & UDP_PACKET_CONNECT_REQUEST) { + litPacketIter->pa_lnListNode.Remove(); + + pb_ulNumOfPackets--; + // connect request packets are allways reliable + pb_ulNumOfReliablePackets--; + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (litPacketIter->pa_slSize - MAX_HEADER_SIZE); + + return litPacketIter; + } + } + return NULL; +}; + +// Removes the first packet from the buffer +BOOL CPacketBuffer::RemoveFirstPacket(BOOL bDelete) { + ASSERT(pb_ulNumOfPackets > 0); + CPacket *lnHead = LIST_HEAD(pb_lhPacketStorage,CPacket,pa_lnListNode); + + pb_ulNumOfPackets--; + if (lnHead->pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets--; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (lnHead->pa_slSize - MAX_HEADER_SIZE); + + if (pb_ulLastSequenceOut < lnHead->pa_ulSequence) { + pb_ulLastSequenceOut = lnHead->pa_ulSequence; + } + + pb_lhPacketStorage.RemHead(); + if (bDelete) { + delete lnHead; + } + return TRUE; +}; + +// Removes the packet with the requested sequence from the buffer +BOOL CPacketBuffer::RemovePacket(ULONG ulSequence,BOOL bDelete) +{ +// ASSERT(pb_ulNumOfPackets > 0); + FORDELETELIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ulSequence == ulSequence) { + litPacketIter->pa_lnListNode.Remove(); + + pb_ulNumOfPackets--; + if (litPacketIter->pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets--; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (litPacketIter->pa_slSize - MAX_HEADER_SIZE); + + if (bDelete) { + delete litPacketIter; + } + } + } + return FALSE; +}; + +// Remove connect response packets from the buffer +BOOL CPacketBuffer::RemoveConnectResponsePackets() { + FORDELETELIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ubReliable & UDP_PACKET_CONNECT_RESPONSE) { + litPacketIter->pa_lnListNode.Remove(); + + pb_ulNumOfPackets--; + + // connect request packets are allways reliable + pb_ulNumOfReliablePackets--; + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (litPacketIter->pa_slSize - MAX_HEADER_SIZE); + + delete litPacketIter; + } + } + return NULL; +}; + + +// Gets the sequence number of the first packet in the buffer +ULONG CPacketBuffer::GetFirstSequence() +{ + ASSERT(pb_ulNumOfPackets > 0); + + return LIST_HEAD(pb_lhPacketStorage,CPacket,pa_lnListNode)->pa_ulSequence; + +}; + +// Gets the sequence number of the last packet in the buffer +ULONG CPacketBuffer::GetLastSequence() +{ + ASSERT(pb_ulNumOfPackets > 0); + + return LIST_TAIL(pb_lhPacketStorage,CPacket,pa_lnListNode)->pa_ulSequence; + +}; + +// Removes the packet with the requested sequence from the buffer +BOOL CPacketBuffer::IsSequenceInBuffer(ULONG ulSequence) +{ + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ulSequence == ulSequence) { + return TRUE; + } + } + return FALSE; +}; + + +// Check if the buffer contains a complete sequence of reliable packets at the start of the buffer +BOOL CPacketBuffer::CheckSequence(SLONG &slSize) +{ + + CPacket* paPacket; + ULONG ulSequence; + + slSize=0; + + if (pb_ulNumOfPackets == 0) { + return FALSE; + } + + paPacket = LIST_HEAD(pb_lhPacketStorage,CPacket,pa_lnListNode); + + // if the first packet is not the head of the reliable packet transfer + if (!(paPacket->pa_ubReliable & UDP_PACKET_RELIABLE_HEAD)) { + return FALSE; + } + + ulSequence = paPacket->pa_ulSequence; + + // for each packet in the buffer + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + // if it's out of order (there is a gap in the reliable sequence), the message is not complete + if (litPacketIter->pa_ulSequence != ulSequence) { + return FALSE; + } + // if it's a tail of the reliable sequence the message is complete (all packets so far + // have been in order) + if (litPacketIter->pa_ubReliable & UDP_PACKET_RELIABLE_TAIL) { + return TRUE; + } + slSize += litPacketIter->pa_slSize - MAX_HEADER_SIZE; + ulSequence++; + } + + // if the function hasn't exited while in the loop, the message is not complete + // (all the packets are in sequence, but there is no tail) + return FALSE; +}; + + + diff --git a/Sources/Engine/Network/CPacket.h b/Sources/Engine/Network/CPacket.h new file mode 100644 index 0000000..ce4ece8 --- /dev/null +++ b/Sources/Engine/Network/CPacket.h @@ -0,0 +1,182 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PACKET_H +#define SE_INCL_PACKET_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + + +// The total size of the UDP packet should be below 1450 bytes, to reduce the +// packet drop rate caused by routers dropping large UDP packets. UDP_BLOCK_SIZE is the +// maximum length of real data, not counting the packet header (ulPacketSequence, bReliable,uwID) +#define MAX_UDP_BLOCK_SIZE 1400 +#define MAX_HEADER_SIZE (sizeof(UBYTE) + sizeof(ULONG) + sizeof(UWORD) + sizeof(ULONG)) // pa_bReliable + pa_ulPacketSequence + pa_uwID + pa_ulTransferSize +#define MAX_PACKET_SIZE (MAX_UDP_BLOCK_SIZE + MAX_HEADER_SIZE) + +// flags for different kinds of packets used by the netcode - note that the acknowledge packets are unreliable +#define UDP_PACKET_UNRELIABLE 0 +#define UDP_PACKET_RELIABLE 1 +#define UDP_PACKET_RELIABLE_HEAD 2 +#define UDP_PACKET_RELIABLE_TAIL 4 +#define UDP_PACKET_ACKNOWLEDGE 8 +#define UDP_PACKET_CONNECT_REQUEST 16 +#define UDP_PACKET_CONNECT_RESPONSE 32 + +// constants for CPacket::CanRetry() function - they describe the retry state of the packet +#define RS_NOW 0 // the packet should be resent immediately +#define RS_NOTNOW 1 // the packet should be resent at a later time +#define RS_NOTATALL 2 // the packet has reached the maximum number of retries - give up + + +class CAddress { +public: + ULONG adr_ulAddress; // host address + UWORD adr_uwPort; // host port + UWORD adr_uwID; // host id + void MakeBroadcast(void); + void Clear(void) { + adr_ulAddress = 0; + adr_uwPort = 0; + adr_uwID = 0; + } +}; + +/* + * A class that contains a single UDP packet. + */ +class CPacket { +public: + ULONG pa_ulSequence; // Sequence number of this packet + UBYTE pa_ubReliable; // Is packet reliable or not + SLONG pa_slSize; // Number of data bytes in packet (without header) + SLONG pa_slTransferSize; // Number of data bytes in a data transfer unit this packet belongs to + + UBYTE pa_ubRetryNumber; // How many retries so far for this packet + CTimerValue pa_tvSendWhen; // When to try sending this packet (includes latency bandwidth limitations + // as well as retry intervals) + + UBYTE pa_pubPacketData[MAX_PACKET_SIZE]; // Packet header + actual data contained in the packet + + CListNode pa_lnListNode; // used to create a linked list of packets - buffer + + CAddress pa_adrAddress; // packet address, port and client ID + + // Constructors/destructors + CPacket() { Clear(); } // Default Constructor + CPacket(CPacket &paOriginal); // Copy constructor + ~CPacket() { Clear(); } + + // Reset all packet data and free allocated memory + void Clear(); + + // Write data to the packet and add header data + BOOL WriteToPacket(void* pv,SLONG slSize,UBYTE ubReliable,ULONG ulSequence,UWORD uwClientID,SLONG slTransferSize); + // Write raw data to the packet and extract header data from the data + BOOL WriteToPacketRaw(void* pv,SLONG slSize); + // Read data from the packet (no header data) + BOOL ReadFromPacket(void* pv,SLONG &slExpectedSize); + + // Is packet reliable + BOOL IsReliable(); + // Is packet a head of a reliable stream? + BOOL IsReliableHead(); + // Is packet a tail of a reliable stream? + BOOL IsReliableTail(); + // Is the packet from a broadcast address (pa_uwID not assigned) + BOOL IsBroadcast(); + + // Get the sequence number of the packet (must be reliable) + ULONG GetSequence(); + // What is the current retry status? + UBYTE CanRetry(); + // Drop the packet from the list + void Drop(); + + // get the size of data transfer unit this packet belongs to + SLONG CPacket::GetTransferSize(); + + // Copy operator + void operator=(const CPacket &paOriginal); + +}; + + +// data used to limit bandwidth/lantency and calculate statistics in packet-buffers +class CPacketBufferStats { +public: + FLOAT pbs_fLatencyLimit; // minimum latency in seconds + FLOAT pbs_fLatencyVariation;// additional latency variation + FLOAT pbs_fBandwidthLimit; // maximum bandwidth in bps (bits per second) + CTimerValue pbs_tvTimeNextPacketStart; // next point in time free for data receiving + + + void Clear(void); + // get time when the packet will be allowed to leave the buffer + CTimerValue GetPacketSendTime(SLONG slSize); +}; + + +class CPacketBuffer { +public: + ULONG pb_ulTotalSize; // Total size of data in packets stored in this buffer (no headers) + ULONG pb_ulLastSequenceOut; // Sequence number of the last packet taken out of the buffer + + CListHead pb_lhPacketStorage; + + ULONG pb_ulNumOfPackets; // Total number of packets currently in storage + ULONG pb_ulNumOfReliablePackets; // Number of reliable packets in storage (0 if no reliable stream in progress) + + CPacketBufferStats *pb_ppbsStats; // for bandwidth/latency emulation stats and limits + CPacketBufferStats pb_pbsLimits; // maximum output BPS for the buffer, to prevent client flooding + + CPacketBuffer() { Clear(); }; + ~CPacketBuffer() { Clear(); }; + + // Empty the packet buffer + void Clear(); + // Is the packet buffer empty? + BOOL IsEmpty(); + + // Calculate when the packet can be output from the buffer + CTimerValue GetPacketSendTime(SLONG slSize); + + // Adds a packet to the end of the packet buffer + BOOL AppendPacket(CPacket &paPacket,BOOL bDelay); + // Inserts the packet in the buffer, according to it's sequence number + BOOL InsertPacket(CPacket &paPacket,BOOL bDelay); + // Bumps up the retry count and time, and appends the packet to the buffer + BOOL Retry(CPacket &paPacket); + // Reads the data from the first packet in the bufffer, but does not remove it + CPacket* PeekFirstPacket(); + // Reads the first packet in the bufffer + CPacket* GetFirstPacket(); + // Reads the data from the packet with the requested sequence, but does not remove it + CPacket* PeekPacket(ULONG ulSequence); + // Reads the packet with the requested sequence + CPacket* GetPacket(ULONG ulSequence); + // Reads the first connection request packet from the buffer + CPacket* GetConnectRequestPacket(); + // Removes the first packet from the buffer + BOOL RemoveFirstPacket(BOOL bDelete); + // Removes the packet with the requested sequence from the buffer + BOOL RemovePacket(ULONG ulSequence,BOOL bDelete); + // Remove connect response packets from the buffer + BOOL RemoveConnectResponsePackets(); + + // Gets the sequence number of the first packet in the buffer + ULONG GetFirstSequence(); + // Gets the sequence number of the last packet in the buffer + ULONG GetLastSequence(); + // Is the packet with the given sequence in the buffer? + BOOL IsSequenceInBuffer(ULONG ulSequence); + // Check if the buffer contains a complete sequence of reliable packets at the start of the buffer + BOOL CheckSequence(SLONG &slSize); + +}; + + +#endif /* include-once check. */ \ No newline at end of file diff --git a/Sources/Engine/Network/ClientInterface.cpp b/Sources/Engine/Network/ClientInterface.cpp new file mode 100644 index 0000000..977485e --- /dev/null +++ b/Sources/Engine/Network/ClientInterface.cpp @@ -0,0 +1,691 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +// how many acknowledges can fit into one UDP packet +#define MAX_ACKS_PER_PACKET (MAX_UDP_BLOCK_SIZE/sizeof(ULONG)) + +extern FLOAT net_fDropPackets; +extern INDEX net_bReportPackets; + +CClientInterface::CClientInterface(void) +{ + Clear(); +}; + +CClientInterface::~CClientInterface(void) +{ + Clear(); +}; + + +void CClientInterface::Clear(void) +{ + ci_bUsed = FALSE; + + ci_bReliableComplete = FALSE; + ci_pbInputBuffer.Clear(); + ci_pbOutputBuffer.Clear(); + ci_pbReliableInputBuffer.Clear(); + ci_pbWaitAckBuffer.Clear(); + + ci_adrAddress.Clear(); + ci_strAddress = ""; + + ci_pciOther = NULL; + ci_ulSequence = 0; +}; + +// mark the client interface as local for this computer +void CClientInterface::SetLocal(CClientInterface *pciOther) +{ + Clear(); + + ci_bUsed = TRUE; + + ci_bClientLocal = TRUE; + ci_pciOther = pciOther; + if (pciOther!=NULL) { + pciOther->ci_pciOther = this; + } + + ci_adrAddress.Clear(); + +}; + +// send a message through this client interface - reliable messages are not limited in size +void CClientInterface::Send(const void *pvSend, SLONG slSize,BOOL bReliable) +{ + ASSERT (ci_bUsed == TRUE); + ASSERT(pvSend != NULL && slSize>0); + // unreliable messages must fit within one UDP packet + ASSERT(bReliable != UDP_PACKET_UNRELIABLE || slSize < MAX_UDP_BLOCK_SIZE); + + UBYTE ubPacketReliable; + UBYTE* pubData; + SLONG slSizeToSend; + SLONG slTransferSize; + ULONG ulSequence; + CPacket* ppaNewPacket; + + //if the message is reliable, make sure the first packet is marked as a head of the message + if (bReliable) { + ubPacketReliable = UDP_PACKET_RELIABLE | UDP_PACKET_RELIABLE_HEAD; + if (slSize <= MAX_UDP_BLOCK_SIZE) { + ubPacketReliable |= UDP_PACKET_RELIABLE_TAIL; + } + } else { + ubPacketReliable = UDP_PACKET_UNRELIABLE; + } + + pubData = (UBYTE*) pvSend; + slSizeToSend = slSize; + slTransferSize = slSizeToSend; + + + // split large reliable messages into packets, and put them in the output buffer + while (slSizeToSend>MAX_UDP_BLOCK_SIZE) { + ppaNewPacket = new CPacket; + + // for each packet, increment the sequence (very important) + ulSequence = (++ci_ulSequence); + ppaNewPacket->WriteToPacket(pubData,MAX_UDP_BLOCK_SIZE,ubPacketReliable,ulSequence,ci_adrAddress.adr_uwID,slTransferSize); + ppaNewPacket->pa_adrAddress.adr_ulAddress = ci_adrAddress.adr_ulAddress; + ppaNewPacket->pa_adrAddress.adr_uwPort = ci_adrAddress.adr_uwPort; + ppaNewPacket->pa_adrAddress.adr_uwID = ci_adrAddress.adr_uwID; + ci_pbOutputBuffer.AppendPacket(*ppaNewPacket,TRUE); + + // turn off udp head flag, if exists (since we just put a packet in the output buffer, the next + // packet cannot be the head + ubPacketReliable &= UDP_PACKET_RELIABLE; + + slSizeToSend -= MAX_UDP_BLOCK_SIZE; + pubData += MAX_UDP_BLOCK_SIZE; + } + + // what remains is a tail of a reliable message, or an unreliable packet + if (ubPacketReliable != UDP_PACKET_UNRELIABLE) { + ubPacketReliable |= UDP_PACKET_RELIABLE_TAIL; + } + + // so send it + ppaNewPacket = new CPacket; + + ulSequence = (++ci_ulSequence); + ppaNewPacket->WriteToPacket(pubData,slSizeToSend,ubPacketReliable,ulSequence,ci_adrAddress.adr_uwID,slTransferSize); + ppaNewPacket->pa_adrAddress.adr_ulAddress = ci_adrAddress.adr_ulAddress; + ppaNewPacket->pa_adrAddress.adr_uwPort = ci_adrAddress.adr_uwPort; + ppaNewPacket->pa_adrAddress.adr_uwID = ci_adrAddress.adr_uwID; + ci_pbOutputBuffer.AppendPacket(*ppaNewPacket,TRUE); + + +}; + +// send a message through this client interface, to the provided address +void CClientInterface::SendTo(const void *pvSend, SLONG slSize,const CAddress adrAdress,BOOL bReliable) +{ + ASSERT (ci_bUsed); + ASSERT(pvSend != NULL && slSize>0); + // unreliable packets must fit within one UDP packet + ASSERT(bReliable != UDP_PACKET_UNRELIABLE || slSize < MAX_UDP_BLOCK_SIZE); + + UBYTE ubPacketReliable; + UBYTE* pubData; + SLONG slSizeToSend; + SLONG slTransferSize; + ULONG ulSequence; + CPacket* ppaNewPacket; + + //if the message is reliable, make sure the first packet is marked as a head of the message + if (bReliable) { + ubPacketReliable = UDP_PACKET_RELIABLE | UDP_PACKET_RELIABLE_HEAD; + if (slSize <= MAX_UDP_BLOCK_SIZE) { + ubPacketReliable |= UDP_PACKET_RELIABLE_TAIL; + } + } else { + ubPacketReliable = UDP_PACKET_UNRELIABLE; + } + + pubData = (UBYTE*) pvSend; + slSizeToSend = slSize; + slTransferSize = slSizeToSend; + + + // split large reliable messages into packets, and put them in the output buffer + while (slSizeToSend>MAX_UDP_BLOCK_SIZE) { + ppaNewPacket = new CPacket; + + // for each packet, increment the sequence (very important) + ulSequence = (++ci_ulSequence); + ppaNewPacket->WriteToPacket(pubData,MAX_UDP_BLOCK_SIZE,ubPacketReliable,ulSequence,adrAdress.adr_uwID,slTransferSize); + ppaNewPacket->pa_adrAddress.adr_ulAddress = adrAdress.adr_ulAddress; + ppaNewPacket->pa_adrAddress.adr_uwPort = adrAdress.adr_uwPort; + ppaNewPacket->pa_adrAddress.adr_uwID = adrAdress.adr_uwID; + ci_pbOutputBuffer.AppendPacket(*ppaNewPacket,TRUE); + + // turn off udp head flag, if exists (since we just put a packet in the output buffer, the next + // packet cannot be the head + ubPacketReliable &= UDP_PACKET_RELIABLE; + + slSizeToSend -= MAX_UDP_BLOCK_SIZE; + pubData += MAX_UDP_BLOCK_SIZE; + } + + // what remains is a tail of a reliable message, or an unreliable packet + if (ubPacketReliable != UDP_PACKET_UNRELIABLE) { + ubPacketReliable |= UDP_PACKET_RELIABLE_TAIL; + } + + ppaNewPacket = new CPacket; + + ulSequence = (++ci_ulSequence); + ppaNewPacket->WriteToPacket(pubData,slSizeToSend,ubPacketReliable,ulSequence,adrAdress.adr_uwID,slTransferSize); + ppaNewPacket->pa_adrAddress.adr_ulAddress = adrAdress.adr_ulAddress; + ppaNewPacket->pa_adrAddress.adr_uwPort = adrAdress.adr_uwPort; + ppaNewPacket->pa_adrAddress.adr_uwID = adrAdress.adr_uwID; + ci_pbOutputBuffer.AppendPacket(*ppaNewPacket,TRUE); +}; + + +// receive a message through the interface, discard originating address +BOOL CClientInterface::Receive(void *pvReceive, SLONG &slSize,BOOL bReliable) +{ + ASSERT (slSize>0); + ASSERT (pvReceive != NULL); + + // we'll use the other receive procedure, and tell it to ignore the address + return ReceiveFrom(pvReceive,slSize,NULL,bReliable); +}; + +// receive a message through the interface, and fill in the originating address +BOOL CClientInterface::ReceiveFrom(void *pvReceive, SLONG &slSize, CAddress *padrAdress,BOOL bReliable) +{ + CPacket* ppaPacket; + UBYTE* pubData = (UBYTE*) pvReceive; + SLONG slDummySize; + UBYTE ubReliable; + + // if a reliable message is requested + if (bReliable) { + // if there is no complete reliable message ready + if (ci_pbReliableInputBuffer.CheckSequence(slDummySize) == FALSE) { + return FALSE; + // if the ready message is longer than the expected size + } else if ( GetCurrentReliableSize() > slSize) { + return FALSE; + // if everything is ok, compose the message and kill the packets + } else { + // fill in the originating address (if necessary) + if (padrAdress != NULL) { + ppaPacket = ci_pbReliableInputBuffer.PeekFirstPacket(); + padrAdress->adr_ulAddress = ppaPacket->pa_adrAddress.adr_ulAddress; + padrAdress->adr_uwPort = ppaPacket->pa_adrAddress.adr_uwPort; + padrAdress->adr_uwID = ppaPacket->pa_adrAddress.adr_uwID; + } + + slSize = 0; + do { + ppaPacket = ci_pbReliableInputBuffer.GetFirstPacket(); + ubReliable = ppaPacket->pa_ubReliable; + slDummySize = ppaPacket->pa_slSize - MAX_HEADER_SIZE; + ppaPacket->ReadFromPacket(pubData,slDummySize); + pubData += slDummySize; + slSize += slDummySize; + delete ppaPacket; + } while (!(ubReliable & UDP_PACKET_RELIABLE_TAIL)); + return TRUE; + } + // if an unreliable message is requested + } else { + // if there are no packets in the input buffer, return + if (ci_pbInputBuffer.pb_ulNumOfPackets == 0) { + return FALSE; + } + ppaPacket = ci_pbInputBuffer.PeekFirstPacket(); + // if the reliable buffer is not empty, nothing can be accepted from the input buffer + // because it would be accepted out-of order (before earlier sequences have been read) + if (ci_pbReliableInputBuffer.pb_ulNumOfPackets != 0) { + return FALSE; + // if the first packet in the input buffer is not unreliable + } else if (ppaPacket->pa_ubReliable != UDP_PACKET_UNRELIABLE) { + return FALSE; + // if the ready message is longer than the expected size + } else if ( ppaPacket->pa_slTransferSize > slSize) { + return FALSE; + // if everything is ok, read the packet data, and kill the packet + } else { + // fill in the originating address (if necessary) + if (padrAdress != NULL) { + padrAdress->adr_ulAddress = ppaPacket->pa_adrAddress.adr_ulAddress; + padrAdress->adr_uwPort = ppaPacket->pa_adrAddress.adr_uwPort; + padrAdress->adr_uwID = ppaPacket->pa_adrAddress.adr_uwID; + } + slSize = ppaPacket->pa_slSize - MAX_HEADER_SIZE; + ppaPacket->ReadFromPacket(pubData,slSize); + // remove the packet from the buffer, and delete it from memory + ci_pbInputBuffer.RemoveFirstPacket(TRUE); + return TRUE; + } + + } + + return FALSE; +}; + + +// receive a message through the interface, discard originating address +BOOL CClientInterface::Receive(CTStream &strmReceive,UBYTE bReliable) +{ + CPacket* ppaPacket; + UBYTE ubReliable; + SLONG slDummySize; + + // if a reliable message is requested + if (bReliable) { + // if there is no complete reliable message ready + if (ci_pbReliableInputBuffer.CheckSequence(slDummySize) == FALSE) { + return FALSE; + // if everything is ok, compose the message and kill the packets + } else { + do { + ppaPacket = ci_pbReliableInputBuffer.GetFirstPacket(); + ubReliable = ppaPacket->pa_ubReliable; + strmReceive.Write_t(ppaPacket->pa_pubPacketData + MAX_HEADER_SIZE,ppaPacket->pa_slSize - MAX_HEADER_SIZE); + if (ci_pbInputBuffer.pb_ulLastSequenceOut < ppaPacket->pa_ulSequence) { + ci_pbInputBuffer.pb_ulLastSequenceOut = ppaPacket->pa_ulSequence; + } + delete ppaPacket; + } while (!(ubReliable & UDP_PACKET_RELIABLE_TAIL)); + return TRUE; + } + // if an unreliable message is requested + } else { + ppaPacket = ci_pbInputBuffer.PeekFirstPacket(); + // if the reliable buffer is not empty, nothing can be accepted from the input buffer + // because it would be accepted out-of order (before earlier sequences have been read) + if (ci_pbReliableInputBuffer.pb_ulNumOfPackets != 0) { + return FALSE; + // if the first packet in the input buffer is not unreliable + } else if (ppaPacket->pa_ubReliable != UDP_PACKET_RELIABLE) { + return FALSE; + // if everything is ok, read the packet data, and kill the packet + } else { + strmReceive.Write_t(ppaPacket->pa_pubPacketData + MAX_HEADER_SIZE,ppaPacket->pa_slSize - MAX_HEADER_SIZE); + // remove the packet from the buffer, and delete it from memory + if (ci_pbInputBuffer.pb_ulLastSequenceOut < ppaPacket->pa_ulSequence) { + ci_pbInputBuffer.pb_ulLastSequenceOut = ppaPacket->pa_ulSequence; + } + ci_pbInputBuffer.RemoveFirstPacket(TRUE); + return TRUE; + } + + } + + return FALSE; +}; + + +// exchanges packets beetween this socket and it's local partner +// from output of this buffet to the input of the other and vice versa +void CClientInterface::ExchangeBuffers(void) +{ + ASSERT (ci_pciOther != NULL); + CPacket* ppaPacket; + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + + // take the output from this interface and give it to it's partner socket + while (ci_pbOutputBuffer.pb_ulNumOfPackets > 0) { + ppaPacket = ci_pbOutputBuffer.PeekFirstPacket(); + if (ppaPacket->pa_tvSendWhen < tvNow) { + ci_pbOutputBuffer.RemoveFirstPacket(FALSE); + if (ci_pciOther->ci_pbInputBuffer.InsertPacket(*ppaPacket,FALSE) == FALSE) { + delete ppaPacket; + } + } else { + break; + } + } + + // and the other way around + while (ci_pciOther->ci_pbOutputBuffer.pb_ulNumOfPackets > 0) { + ppaPacket = ci_pciOther->ci_pbOutputBuffer.PeekFirstPacket(); + if (ppaPacket->pa_tvSendWhen < tvNow) { + ppaPacket = ci_pciOther->ci_pbOutputBuffer.GetFirstPacket(); + if (ci_pbInputBuffer.InsertPacket(*ppaPacket,FALSE) == FALSE) { + delete ppaPacket; + }; + + } else { + break; + } + } + +}; + + +// update interface's input buffer (transfer from input buffer to the reliable buffer...), +// for incoming acknowledge packets, remove acknowledged packets from the output buffers, +// and generate acknowledge messages for incoming reliable packets +BOOL CClientInterface::UpdateInputBuffers(void) +{ + BOOL bSomethingDone; + ULONG pulGenAck[MAX_ACKS_PER_PACKET]; + ULONG ulAckCount=0; + CTimerValue tvNow; + + // if there are packets in the input buffer, process them + FORDELETELIST(CPacket,pa_lnListNode,ci_pbInputBuffer.pb_lhPacketStorage,ppaPacket) { + CPacket &paPacket = *ppaPacket; + + // if it's an acknowledge packet, remove the acknowledged packets from the wait acknowledge buffer + if (ppaPacket->pa_ubReliable & UDP_PACKET_ACKNOWLEDGE) { + ULONG *pulAck; + SLONG slSize; + ULONG ulSequence; + + slSize = ppaPacket->pa_slSize - MAX_HEADER_SIZE; + // if slSize isn't rounded to the size of ulSequence, abort + ASSERT (slSize % sizeof(ULONG) == 0); + + // get the pointer to the start of acknowledged sequences + pulAck = (ULONG*) (ppaPacket->pa_pubPacketData + MAX_HEADER_SIZE); + // for each acknowledged sequence number + while (slSize>0) { + ulSequence = *pulAck; + + // report the packet info to the console + if (net_bReportPackets == TRUE) { + tvNow = _pTimer->GetHighPrecisionTimer(); + CPrintF("%lu: Received acknowledge for packet sequence %d\n",(ULONG) tvNow.GetMilliseconds(),ulSequence); + } + + // remove the matching packet from the wait acknowledge buffer + ci_pbWaitAckBuffer.RemovePacket(ulSequence,TRUE); + // if the packet is waiting to be resent it's in the outgoing buffer, so remove it + ci_pbOutputBuffer.RemovePacket(ulSequence,TRUE); + pulAck++; + slSize -= sizeof(ULONG); + } + + // take this packet out of the input buffer and kill it + ci_pbInputBuffer.RemovePacket(ppaPacket->pa_ulSequence,FALSE); + delete ppaPacket; + + bSomethingDone = TRUE; + // if the packet is reliable + } else if (ppaPacket->pa_ubReliable & UDP_PACKET_RELIABLE) { + + // generate packet acknowledge + // if the packet is from the broadcast address, send the acknowledge for that packet only + if (ppaPacket->pa_adrAddress.adr_uwID == '//' || ppaPacket->pa_adrAddress.adr_uwID == 0) { + CPacket *ppaAckPacket = new CPacket; + ppaAckPacket->pa_adrAddress.adr_ulAddress = ppaPacket->pa_adrAddress.adr_ulAddress; + ppaAckPacket->pa_adrAddress.adr_uwPort = ppaPacket->pa_adrAddress.adr_uwPort; + ppaAckPacket->WriteToPacket(&(ppaPacket->pa_ulSequence),sizeof(ULONG),UDP_PACKET_ACKNOWLEDGE,++ci_ulSequence,'//',sizeof(ULONG)); + ci_pbOutputBuffer.AppendPacket(*ppaAckPacket,TRUE); + if (net_bReportPackets == TRUE) { + CPrintF("Acknowledging broadcast packet sequence %d\n",ppaPacket->pa_ulSequence); + } + ci_pbInputBuffer.RemovePacket(ppaPacket->pa_ulSequence,FALSE); + } else { + // if we have filled the packet to the maximum with acknowledges (an extremely rare event) + // finish this packet and start the next one + if (ulAckCount == MAX_ACKS_PER_PACKET) { + CPacket *ppaAckPacket = new CPacket; + ppaAckPacket->pa_adrAddress.adr_ulAddress = ci_adrAddress.adr_ulAddress; + ppaAckPacket->pa_adrAddress.adr_uwPort = ci_adrAddress.adr_uwPort; + ppaAckPacket->WriteToPacket(pulGenAck,ulAckCount*sizeof(ULONG),UDP_PACKET_ACKNOWLEDGE,++ci_ulSequence,ci_adrAddress.adr_uwID,ulAckCount*sizeof(ULONG)); + ci_pbOutputBuffer.AppendPacket(*ppaAckPacket,TRUE); + ulAckCount = 0; + } + // add the acknowledge for this packet + pulGenAck[ulAckCount] = ppaPacket->pa_ulSequence; + + // report the packet info to the console + if (net_bReportPackets == TRUE) { + tvNow = _pTimer->GetHighPrecisionTimer(); + CPrintF("%lu: Acknowledging packet sequence %d\n",(ULONG) tvNow.GetMilliseconds(),ppaPacket->pa_ulSequence); + } + + ulAckCount++; + } + + // take this packet out of the input buffer + ci_pbInputBuffer.RemovePacket(ppaPacket->pa_ulSequence,FALSE); + + if (ppaPacket->pa_ulSequence == 8) { + ppaPacket->pa_ulSequence = 8; + } + // a packet can be accepted from the broadcast ID only if it is an acknowledge packet or + // if it is a connection confirmation response packet and the client isn't already connected + if (ppaPacket->pa_adrAddress.adr_uwID == '//' || ppaPacket->pa_adrAddress.adr_uwID == 0) { + if (((!ci_bUsed) && (ppaPacket->pa_ubReliable & UDP_PACKET_CONNECT_RESPONSE)) || + (ppaPacket->pa_ubReliable & UDP_PACKET_ACKNOWLEDGE) || ci_bClientLocal) { + + /* if (ci_pbReliableInputBuffer.pb_ulLastSequenceOut >= ppaPacket->pa_ulSequence) { + delete ppaPacket; + } else*/ + ppaPacket->pa_ulSequence = 0; + if (ci_pbReliableInputBuffer.InsertPacket(*ppaPacket,FALSE) == FALSE) { + delete ppaPacket; + } + } else { + delete ppaPacket; + } + // reject duplicates + } else if (ppaPacket->pa_ulSequence > ci_pbReliableInputBuffer.pb_ulLastSequenceOut && + !(ci_pbReliableInputBuffer.IsSequenceInBuffer(ppaPacket->pa_ulSequence))) { + if (ci_pbReliableInputBuffer.InsertPacket(*ppaPacket,FALSE) == FALSE) { + delete ppaPacket; + } + } else { + delete ppaPacket; + } + + // if the packet is unreliable, leave it in the input buffer + // when it is needed, the message will be pulled from there + } else { + + // reject duplicates + ci_pbInputBuffer.RemovePacket(ppaPacket->pa_ulSequence,FALSE); + if (ppaPacket->pa_ulSequence > ci_pbInputBuffer.pb_ulLastSequenceOut && + !(ci_pbReliableInputBuffer.IsSequenceInBuffer(ppaPacket->pa_ulSequence))) { + if (ci_pbInputBuffer.InsertPacket(*ppaPacket,FALSE) == FALSE) { + delete ppaPacket; + } + } else { + delete ppaPacket; + } + + } + } + + // if there are any remaining unsent acknowldges, put them into a packet and send it + if (ulAckCount >0) { + CPacket *ppaAckPacket = new CPacket; + ppaAckPacket->pa_adrAddress.adr_ulAddress = ci_adrAddress.adr_ulAddress; + ppaAckPacket->pa_adrAddress.adr_uwPort = ci_adrAddress.adr_uwPort; + ppaAckPacket->WriteToPacket(pulGenAck,ulAckCount*sizeof(ULONG),UDP_PACKET_ACKNOWLEDGE,++ci_ulSequence,ci_adrAddress.adr_uwID,ulAckCount*sizeof(ULONG)); + ci_pbOutputBuffer.AppendPacket(*ppaAckPacket,TRUE); + } + return TRUE; + +}; + + +// update socket input buffer (transfer from input buffer to the reliable buffer...), +// for incoming acknowledge packets, remove acknowledged packets from the output buffers, +// and generate acknowledge messages for incoming reliable packets +// this method is different than the previous becoause it sends acknowledges for each +// packet separately, instead of grouping them together +BOOL CClientInterface::UpdateInputBuffersBroadcast(void) +{ + BOOL bSomethingDone; + CTimerValue tvNow; + + // if there are packets in the input buffer, process them + FORDELETELIST(CPacket,pa_lnListNode,ci_pbInputBuffer.pb_lhPacketStorage,ppaPacket) { + CPacket &paPacket = *ppaPacket; + + // if it's an acknowledge packet, remove the acknowledged packets from the wait acknowledge buffer + if (ppaPacket->pa_ubReliable & UDP_PACKET_ACKNOWLEDGE) { + ULONG *pulAck; + SLONG slSize; + ULONG ulSequence; + + slSize = ppaPacket->pa_slSize - MAX_HEADER_SIZE; + // if slSize isn't rounded to the size of ulSequence, abort + ASSERT (slSize % sizeof(ULONG) == 0); + + // get the pointer to the start of acknowledged sequences + pulAck = (ULONG*) (ppaPacket->pa_pubPacketData + MAX_HEADER_SIZE); + // for each acknowledged sequence number + while (slSize>0) { + ulSequence = *pulAck; + + // report the packet info to the console + if (net_bReportPackets == TRUE) { + tvNow = _pTimer->GetHighPrecisionTimer(); + CPrintF("%lu: Received acknowledge for broadcast packet sequence %d\n",(ULONG) tvNow.GetMilliseconds(),ulSequence); + } + + // remove the matching packet from the wait acknowledge buffer + ci_pbWaitAckBuffer.RemovePacket(ulSequence,TRUE); + // if the packet is waiting to be resent it's in the outgoing buffer, so remove it + ci_pbOutputBuffer.RemovePacket(ulSequence,TRUE); + pulAck++; + slSize -= sizeof(ULONG); + } + + ci_pbInputBuffer.RemovePacket(ppaPacket->pa_ulSequence,FALSE); + bSomethingDone = TRUE; + delete ppaPacket; + // if the packet is reliable + } else if (ppaPacket->pa_ubReliable & UDP_PACKET_RELIABLE) { + + // generate packet acknowledge (each reliable broadcast packet is acknowledged separately + // because the broadcast interface can receive packets from any number of different addresses + CPacket *ppaAckPacket = new CPacket; + ppaAckPacket->pa_adrAddress.adr_ulAddress = ppaPacket->pa_adrAddress.adr_ulAddress; + ppaAckPacket->pa_adrAddress.adr_uwPort = ppaPacket->pa_adrAddress.adr_uwPort; + ppaAckPacket->WriteToPacket(&(ppaPacket->pa_ulSequence),sizeof(ULONG),UDP_PACKET_ACKNOWLEDGE,ci_ulSequence++,ppaPacket->pa_adrAddress.adr_uwID,sizeof(ULONG)); + ci_pbOutputBuffer.AppendPacket(*ppaAckPacket,TRUE); + + // report the packet info to the console + if (net_bReportPackets == TRUE) { + tvNow = _pTimer->GetHighPrecisionTimer(); + CPrintF("%lu: Acknowledging broadcast packet sequence %d\n",(ULONG) tvNow.GetMilliseconds(),ppaPacket->pa_ulSequence); + } + + ci_pbInputBuffer.RemovePacket(ppaPacket->pa_ulSequence,FALSE); + if (ci_pbReliableInputBuffer.InsertPacket(*ppaPacket,FALSE) == FALSE) { + delete ppaPacket; + } + } else { + + // if the packet is unreliable, leave it in the input buffer + // when it is needed, the message will be pulled from there + // have to check for duplicates + + ci_pbInputBuffer.RemovePacket(ppaPacket->pa_ulSequence,FALSE); + if (ppaPacket->pa_ulSequence > ci_pbInputBuffer.pb_ulLastSequenceOut && + !(ci_pbReliableInputBuffer.IsSequenceInBuffer(ppaPacket->pa_ulSequence))) { + if (ci_pbInputBuffer.InsertPacket(*ppaPacket,FALSE) == FALSE) { + delete ppaPacket; + } + } else { + delete ppaPacket; + } + + } + } + + return TRUE; + +}; + + +// take a look at the wait acknowledge buffer and resend any packets that heve reached the timeout +// if there is a packet that can't be sent sucessfully (RS_NOTATALL), signal it +BOOL CClientInterface::UpdateOutputBuffers(void) +{ + CPacket* ppaPacket; + UBYTE ubRetry; + + // handle resends + while (ci_pbWaitAckBuffer.pb_ulNumOfPackets > 0) { + ppaPacket = ci_pbWaitAckBuffer.PeekFirstPacket(); + + ubRetry = ppaPacket->CanRetry(); + switch (ubRetry) { + // if it's time to retry sending the packet + case RS_NOW: { ci_pbWaitAckBuffer.RemoveFirstPacket(FALSE); + ci_pbOutputBuffer.Retry(*ppaPacket); + break; + } + // if the packet cannot be sent now, no other packets can be sent, so exit + case RS_NOTNOW: { return TRUE; } + // if the packet has reached the retry limit - close the client's connection + case RS_NOTATALL: { Clear(); + return FALSE; + } + + + } + } + return TRUE; +}; + + +// get the next available packet from the output buffer +CPacket* CClientInterface::GetPendingPacket(void) +{ + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + + if (ci_pbOutputBuffer.pb_ulNumOfPackets == 0) { + return NULL; + } + + CPacket* ppaPacket = ci_pbOutputBuffer.PeekFirstPacket(); + + // if it's time to send the packet + if (ppaPacket->pa_tvSendWhen <= tvNow) { + ci_pbOutputBuffer.RemoveFirstPacket(FALSE); + return ppaPacket; + } + + return NULL; + +}; + + +// reads the expected size of current realiable message in the reliable input buffer +SLONG CClientInterface::GetExpectedReliableSize(void) +{ + if (ci_pbReliableInputBuffer.pb_ulNumOfPackets == 0) { + return 0; + } + CPacket* ppaPacket = ci_pbReliableInputBuffer.PeekFirstPacket(); + return ppaPacket->pa_slTransferSize; +}; + +// reads the expected size of current realiable message in the reliable input buffer +SLONG CClientInterface::GetCurrentReliableSize(void) +{ + SLONG slSize; + ci_pbReliableInputBuffer.CheckSequence(slSize); + return slSize; +}; \ No newline at end of file diff --git a/Sources/Engine/Network/ClientInterface.h b/Sources/Engine/Network/ClientInterface.h new file mode 100644 index 0000000..9e3703b --- /dev/null +++ b/Sources/Engine/Network/ClientInterface.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_CLIENTINTERFACE_H +#define SE_INCL_CLIENTINTERFACE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +class CClientInterface { +public: + BOOL ci_bUsed; // client unused + CTString ci_strAddress; // client address in human readable format + CAddress ci_adrAddress; // address this client is connected to (address, port, ID) + BOOL ci_bClientLocal; // set for local clients + ULONG ci_ulSequence; // sequence number for reliable packet confirmation + + CPacketBuffer ci_pbOutputBuffer; // output buffer + CPacketBuffer ci_pbWaitAckBuffer; // buffer for reliable packets that need to be acknowledged + CPacketBuffer ci_pbInputBuffer; // input buffer + CPacketBuffer ci_pbReliableInputBuffer; // a buffer containing received reliable packets + BOOL ci_bReliableComplete; // does the reliable input buffer contain a complete reliable message? + + CClientInterface *ci_pciOther; // other-side client - for local clients + + // interface: + CClientInterface(void); + ~CClientInterface(void); + void Clear(void); + + // sets the client to be local and optionally connects to another local client + void SetLocal(CClientInterface *ci_pciOther); + + // send a message through the interface + void Send(const void *pvSend, SLONG slSize,BOOL bReliable); + void SendTo(const void *pvSend, SLONG slSize,const CAddress adrAdress,BOOL bReliable); + // receive a message from the interface + BOOL Receive(void *pvReceive, SLONG &slSize,BOOL bReliable); + BOOL ReceiveFrom(void *pvReceive, SLONG &slSize, CAddress *adrAdress,BOOL bReliable); + BOOL Receive(CTStream &strmReceive,UBYTE bReliable); + + // exchanges packets beetween this socket and it's local partner + // from output of this buffet to the input of the other and vice versa + void ExchangeBuffers(void); + + // update socket buffers (transfer from input buffer to the reliable buffer...) - grouped acknowledges + BOOL UpdateInputBuffers(void); + + // update socket buffers with per-packet acknowledge + BOOL UpdateInputBuffersBroadcast(void); + + // update socket outgoing buffer (resends, timeouts...) + BOOL UpdateOutputBuffers(void); + + // get a packet whose time has come from the output buffer, NULL if no such packet + CPacket* GetPendingPacket(void); + + // reads the expected size of realiable message in the reliable input buffer + SLONG GetExpectedReliableSize(void); + // reads the current size of realiable message in the reliable input buffer + SLONG GetCurrentReliableSize(void); + +}; + +#endif \ No newline at end of file diff --git a/Sources/Engine/Network/Common.h b/Sources/Engine/Network/Common.h new file mode 100644 index 0000000..1a53b22 --- /dev/null +++ b/Sources/Engine/Network/Common.h @@ -0,0 +1,2 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + diff --git a/Sources/Engine/Network/CommunicationInterface.cpp b/Sources/Engine/Network/CommunicationInterface.cpp new file mode 100644 index 0000000..c5bddf2 --- /dev/null +++ b/Sources/Engine/Network/CommunicationInterface.cpp @@ -0,0 +1,1270 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + + +#pragma comment(lib, "wsock32.lib") + +#define SERVER_LOCAL_CLIENT 0 +extern INDEX net_iPort; +extern CTString net_strLocalHost; +extern INDEX net_bLookupHostNames; +extern INDEX net_bReportICMPErrors; +extern FLOAT net_fDropPackets; +extern FLOAT net_tmConnectionTimeout; +extern INDEX net_bReportPackets; + +static struct ErrorCode ErrorCodes[] = { + ERRORCODE(WSAEINTR , "WSAEINTR"), + ERRORCODE(WSAEBADF , "WSAEBADF"), + ERRORCODE(WSAEACCES , "WSAEACCES"), + ERRORCODE(WSAEFAULT , "WSAEFAULT"), + ERRORCODE(WSAEINVAL , "WSAEINVAL"), + ERRORCODE(WSAEMFILE , "WSAEMFILE"), + ERRORCODE(WSAEWOULDBLOCK , "WSAEWOULDBLOCK"), + ERRORCODE(WSAEINPROGRESS , "WSAEINPROGRESS"), + ERRORCODE(WSAEALREADY , "WSAEALREADY"), + ERRORCODE(WSAENOTSOCK , "WSAENOTSOCK"), + ERRORCODE(WSAEDESTADDRREQ , "WSAEDESTADDRREQ"), + ERRORCODE(WSAEMSGSIZE , "WSAEMSGSIZE"), + ERRORCODE(WSAEPROTOTYPE , "WSAEPROTOTYPE"), + ERRORCODE(WSAENOPROTOOPT , "WSAENOPROTOOPT"), + ERRORCODE(WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT"), + ERRORCODE(WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT"), + ERRORCODE(WSAEOPNOTSUPP , "WSAEOPNOTSUPP"), + ERRORCODE(WSAEPFNOSUPPORT , "WSAEPFNOSUPPORT"), + ERRORCODE(WSAEAFNOSUPPORT , "WSAEAFNOSUPPORT"), + ERRORCODE(WSAEADDRINUSE , "WSAEADDRINUSE"), + ERRORCODE(WSAEADDRNOTAVAIL , "WSAEADDRNOTAVAIL"), + ERRORCODE(WSAENETDOWN , "WSAENETDOWN"), + ERRORCODE(WSAENETUNREACH , "WSAENETUNREACH"), + ERRORCODE(WSAENETRESET , "WSAENETRESET"), + ERRORCODE(WSAECONNABORTED , "WSAECONNABORTED"), + ERRORCODE(WSAECONNRESET , "WSAECONNRESET"), + ERRORCODE(WSAENOBUFS , "WSAENOBUFS"), + ERRORCODE(WSAEISCONN , "WSAEISCONN"), + ERRORCODE(WSAENOTCONN , "WSAENOTCONN"), + ERRORCODE(WSAESHUTDOWN , "WSAESHUTDOWN"), + ERRORCODE(WSAETOOMANYREFS , "WSAETOOMANYREFS"), + ERRORCODE(WSAETIMEDOUT , "WSAETIMEDOUT"), + ERRORCODE(WSAECONNREFUSED , "WSAECONNREFUSED"), + ERRORCODE(WSAELOOP , "WSAELOOP"), + ERRORCODE(WSAENAMETOOLONG , "WSAENAMETOOLONG"), + ERRORCODE(WSAEHOSTDOWN , "WSAEHOSTDOWN"), + ERRORCODE(WSAEHOSTUNREACH , "WSAEHOSTUNREACH"), + ERRORCODE(WSASYSNOTREADY , "WSASYSNOTREADY"), + ERRORCODE(WSAVERNOTSUPPORTED, "WSAVERNOTSUPPORTED"), + ERRORCODE(WSANOTINITIALISED , "WSANOTINITIALISED"), + ERRORCODE(WSAEDISCON , "WSAEDISCON"), + ERRORCODE(WSAHOST_NOT_FOUND , "WSAHOST_NOT_FOUND"), + ERRORCODE(WSATRY_AGAIN , "WSATRY_AGAIN"), + ERRORCODE(WSANO_RECOVERY , "WSANO_RECOVERY"), + ERRORCODE(WSANO_DATA , "WSANO_DATA"), +}; +static struct ErrorTable SocketErrors = ERRORTABLE(ErrorCodes); + + +//structures used to emulate bandwidth and latency parameters - shared by all client interfaces +CPacketBufferStats _pbsSend; +CPacketBufferStats _pbsRecv; + +ULONG cm_ulLocalHost; // configured local host address +CTString cm_strAddress; // local address +CTString cm_strName; // local address + +CTCriticalSection cm_csComm; // critical section for access to communication data + +BOOL cm_bNetworkInitialized; + +// index 0 is the server's local client, this is an array used by server only +CClientInterface cm_aciClients[SERVER_CLIENTS]; + +// Broadcast interface - i.e. interface for 'nonconnected' communication +CClientInterface cm_ciBroadcast; + +// this is used by client only +CClientInterface cm_ciLocalClient; + +// global communication interface object (there is only one for the entire engine) +CCommunicationInterface _cmiComm; + + +/* +* +* Two helper functions - conversion from IP to words +* +*/ + +// convert address to a printable string +CTString AddressToString(ULONG ulHost) +{ + ULONG ulHostNet = htonl(ulHost); + + // initially not converted + struct hostent *hostentry = NULL; + + // if DNS lookup is allowed + if (net_bLookupHostNames) { + // lookup the host + hostentry = gethostbyaddr ((char *)&ulHostNet, sizeof(ulHostNet), AF_INET); + } + + // if DNS lookup succeeded + if (hostentry!=NULL) { + // return its ascii name + return (char *)hostentry->h_name; + // if DNS lookup failed + } else { + // just convert to dotted number format + return inet_ntoa((const in_addr &)ulHostNet); + } +}; + +// convert string address to a number +ULONG StringToAddress(const CTString &strAddress) +{ + // first try to convert numeric address + ULONG ulAddress = ntohl(inet_addr(strAddress)); + // if not a valid numeric address + if (ulAddress==INADDR_NONE) { + // lookup the host + HOSTENT *phe = gethostbyname(strAddress); + // if succeeded + if (phe!=NULL) { + // get that address + ulAddress = ntohl(*(ULONG*)phe->h_addr_list[0]); + } + } + + // return what we got + return ulAddress; +}; + + + +CCommunicationInterface::CCommunicationInterface(void) +{ + cm_csComm.cs_iIndex = -1; + CTSingleLock slComm(&cm_csComm, TRUE); + + cci_bInitialized = FALSE; + cci_bWinSockOpen = FALSE; + + cci_bServerInitialized = FALSE; + cci_bClientInitialized = FALSE; + cm_ciLocalClient.ci_bClientLocal = FALSE; + + cci_hSocket=INVALID_SOCKET; + +}; + + +// initialize +void CCommunicationInterface::Init(void) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + + cci_bWinSockOpen = FALSE; + cci_bInitialized = TRUE; + + // mark as initialized + cm_bNetworkInitialized = FALSE; + + cci_pbMasterInput.Clear(); + cci_pbMasterOutput.Clear(); + +}; + +// close +void CCommunicationInterface::Close(void) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + + ASSERT(cci_bInitialized); + ASSERT(!cci_bServerInitialized); + ASSERT(!cci_bClientInitialized); + + // mark as closed + cm_bNetworkInitialized = FALSE; + cci_bInitialized = FALSE; + cm_ciLocalClient.ci_bClientLocal = FALSE; + + cci_pbMasterInput.Clear(); + cci_pbMasterOutput.Clear(); + +}; + +void CCommunicationInterface::InitWinsock(void) +{ + if (cci_bWinSockOpen) { + return; + } + + // start winsock + WSADATA winsockdata; + WORD wVersionRequested; + wVersionRequested = MAKEWORD(1, 1); + int iResult = WSAStartup(wVersionRequested, &winsockdata); + // if winsock open ok + if (iResult==0) { + // remember that + cci_bWinSockOpen = TRUE; + CPrintF(TRANS(" winsock opened ok\n")); + } +}; + +void CCommunicationInterface::EndWinsock(void) +{ + if (!cci_bWinSockOpen) { + return; + } + + int iResult = WSACleanup(); + ASSERT(iResult==0); + cci_bWinSockOpen = FALSE; +}; + + +// prepares the comm interface for use - MUST be invoked before any data can be sent/received +void CCommunicationInterface::PrepareForUse(BOOL bUseNetwork, BOOL bClient) +{ + + // clear the network conditions emulation data + _pbsSend.Clear(); + _pbsRecv.Clear(); + + // if the network is already initialized, shut it down before proceeding + if (cm_bNetworkInitialized) { + Unprepare(); + } + + // make sure winsock is off (could be on if enumeration was triggered) + GameAgent_EnumCancel(); + EndWinsock(); + + if (bUseNetwork) { + CPrintF(TRANS("Initializing TCP/IP...\n")); + if (bClient) { + CPrintF(TRANS(" opening as client\n")); + } else { + CPrintF(TRANS(" opening as server\n")); + } + + // make sure winsock is on + InitWinsock(); + + // no address by default + cm_ulLocalHost = 0; + // if there is a desired local address + if (net_strLocalHost!="") { + CPrintF(TRANS(" user forced local address: %s\n"), (const char*)net_strLocalHost); + // use that address + cm_strName = net_strLocalHost; + cm_ulLocalHost = StringToAddress(cm_strName); + // if invalid + if (cm_ulLocalHost==0 || cm_ulLocalHost==-1) { + cm_ulLocalHost=0; + // report it + CPrintF(TRANS(" requested local address is invalid\n")); + } + } + + // if no valid desired local address + CPrintF(TRANS(" getting local addresses\n")); + // get default + char hostname[256]; + gethostname(hostname, sizeof(hostname)-1); + cm_strName = hostname; + // lookup the host + HOSTENT *phe = gethostbyname(cm_strName); + // if succeeded + if (phe!=NULL) { + // get the addresses + cm_strAddress = ""; + for(INDEX i=0; phe->h_addr_list[i]!=NULL; i++) { + if (i>0) { + cm_strAddress += ", "; + } + cm_strAddress += inet_ntoa(*(const in_addr *)phe->h_addr_list[i]); + } + } + + CPrintF(TRANS(" local addresses: %s (%s)\n"), cm_strName, cm_strAddress); + CPrintF(TRANS(" port: %d\n"), net_iPort); + + // try to open master UDP socket + try { + OpenSocket_t(cm_ulLocalHost, bClient?0:net_iPort); + cci_pbMasterInput.pb_ppbsStats = NULL; + cci_pbMasterOutput.pb_ppbsStats = NULL; + cm_ciBroadcast.SetLocal(NULL); + CPrintF(TRANS(" opened socket: \n")); + } catch (char *strError) { + CPrintF(TRANS(" cannot open UDP socket: %s\n"), strError); + } + } + + cm_bNetworkInitialized = cci_bWinSockOpen; +}; + + +// shut down the communication interface +void CCommunicationInterface::Unprepare(void) +{ + // close winsock + if (cci_bWinSockOpen) { + // if socket is open + if (cci_hSocket != INVALID_SOCKET) { + // close it + closesocket(cci_hSocket); + cci_hSocket = INVALID_SOCKET; + } + + cm_ciBroadcast.Clear(); + EndWinsock(); + cci_bBound=FALSE; + } + + cci_pbMasterInput.Clear(); + cci_pbMasterOutput.Clear(); + + + cm_bNetworkInitialized = cci_bWinSockOpen; + +}; + + +BOOL CCommunicationInterface::IsNetworkEnabled(void) +{ + return cm_bNetworkInitialized; +}; + +// get address of local machine +void CCommunicationInterface::GetHostName(CTString &strName, CTString &strAddress) +{ + strName = cm_strName; + strAddress = cm_strAddress; +}; + + + +/* +* +* +* Socket functions - creating, binding... +* +* +*/ + + +// create an inet-family socket +void CCommunicationInterface::CreateSocket_t() +{ + ASSERT(cci_hSocket==INVALID_SOCKET); + // open the socket + cci_hSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + cci_bBound = FALSE; + if (cci_hSocket == INVALID_SOCKET) { + ThrowF_t(TRANS("Cannot open socket. %s"), (const char*)GetSocketError(WSAGetLastError())); + } + +}; + +// bind socket to the given address +void CCommunicationInterface::Bind_t(ULONG ulLocalHost, ULONG ulLocalPort) +{ + if (cci_hSocket==INVALID_SOCKET) { + ASSERT(FALSE); + return; + } + + sockaddr_in sin; + sin.sin_family = AF_INET; + sin.sin_port = htons(ulLocalPort); + sin.sin_addr.s_addr = htonl(ulLocalHost); + + // bind socket to server address/port + if (bind(cci_hSocket, (sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR) { + ThrowF_t(TRANS("Cannot bind socket. %s"), (const char*)GetSocketError(WSAGetLastError())); + } + cci_bBound = TRUE; +}; + + +// set socket to non-blocking mode +void CCommunicationInterface::SetNonBlocking_t(void) +{ + if (cci_hSocket==INVALID_SOCKET) { + ASSERT(FALSE); + return; + } + + ULONG ulArgNonBlocking = 1; + if (ioctlsocket(cci_hSocket, FIONBIO, &ulArgNonBlocking) == SOCKET_ERROR) { + ThrowF_t(TRANS("Cannot set socket to non-blocking mode. %s"), + (const char*)GetSocketError(WSAGetLastError())); + } +}; + + +// get generic socket error info string about last error +CTString CCommunicationInterface::GetSocketError(INDEX iError) +{ + CTString strError; + strError.PrintF(TRANS("Socket %d, Error %d (%s)"), + cci_hSocket, iError, ErrorDescription(&SocketErrors, iError)); + return strError; +}; + + +// open an UDP socket at given port +void CCommunicationInterface::OpenSocket_t(ULONG ulLocalHost, ULONG ulLocalPort) +{ + // create the socket as UDP + CreateSocket_t(); + // bind it to that address/port + if (ulLocalPort!=0) { + Bind_t(ulLocalHost, ulLocalPort); + } + // go non-blocking + SetNonBlocking_t(); + + // mark as open + cci_bSocketOpen = TRUE; + + +}; + +// get address of this host +void CCommunicationInterface::GetLocalAddress_t(ULONG &ulHost, ULONG &ulPort) +{ + ulHost = 0; + ulPort = 0; + if (cci_hSocket==INVALID_SOCKET) { + ASSERT(FALSE); + return; + } + + // get socket local port and address + sockaddr_in sin; + int iSize = sizeof(sin); + if (getsockname(cci_hSocket, (sockaddr*)&sin, &iSize) == SOCKET_ERROR) { + ThrowF_t(TRANS("Cannot get local address on socket. %s"), + (const char*)GetSocketError(WSAGetLastError())); + } + ulHost = ntohl(sin.sin_addr.S_un.S_addr); + ulPort = ntohs(sin.sin_port); +} + +// get address of the peer host connected to this socket +void CCommunicationInterface::GetRemoteAddress_t(ULONG &ulHost, ULONG &ulPort) +{ + ulHost = 0; + ulPort = 0; + if (cci_hSocket==INVALID_SOCKET) { + ASSERT(FALSE); + return; + } + + // get socket local port + sockaddr_in sin; + int iSize = sizeof(sin); + if (getpeername(cci_hSocket, (sockaddr*)&sin, &iSize) == SOCKET_ERROR) { + ThrowF_t(TRANS("Cannot get remote address on socket. %s"), + (const char*)GetSocketError(WSAGetLastError())); + } + ulHost = ntohl(sin.sin_addr.S_un.S_addr); + ulPort = ntohs(sin.sin_port); +} + + +/* + * ---->>>> BROADCAST INTERFACE <<<<---- + */ + +// broadcast communication +void CCommunicationInterface::Broadcast_Send(const void *pvSend, SLONG slSendSize,CAddress &adrDestination) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + + cm_ciBroadcast.ci_adrAddress.adr_ulAddress = adrDestination.adr_ulAddress; + cm_ciBroadcast.ci_adrAddress.adr_uwPort = adrDestination.adr_uwPort; + cm_ciBroadcast.ci_adrAddress.adr_uwID = adrDestination.adr_uwID; + + cm_ciBroadcast.Send(pvSend, slSendSize,FALSE); +} + +BOOL CCommunicationInterface::Broadcast_Receive(void *pvReceive, SLONG &slReceiveSize,CAddress &adrAddress) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + return cm_ciBroadcast.ReceiveFrom(pvReceive, slReceiveSize,&adrAddress,FALSE); +} + + +// update the broadcast input buffer - handle any incoming connection requests +void CCommunicationInterface::Broadcast_Update_t() { + CPacket* ppaConnectionRequest; + BOOL bIsAlready; + BOOL bFoundEmpty; + ULONG iClient; + UBYTE ubDummy=65; + + + // while there is a connection request packet in the input buffer + while ((ppaConnectionRequest = cm_ciBroadcast.ci_pbReliableInputBuffer.GetConnectRequestPacket()) != NULL) { + // see if there is a client already connected at that address and port + bIsAlready = FALSE; + for (iClient=1;iClientpa_adrAddress.adr_ulAddress && + cm_aciClients[iClient].ci_adrAddress.adr_uwPort == ppaConnectionRequest->pa_adrAddress.adr_uwPort) { + bIsAlready = TRUE; + break; + } + } + // if the client is already connected then just ignore the packet - else, connect it + if (!bIsAlready) { + // find an empty client structure + bFoundEmpty = FALSE; + for (iClient=1;iClientpa_adrAddress.adr_ulAddress; + cm_aciClients[iClient].ci_adrAddress.adr_uwPort = ppaConnectionRequest->pa_adrAddress.adr_uwPort; + // generate the ID + UWORD uwID = _pTimer->GetHighPrecisionTimer().tv_llValue&0x0FFF; + if (uwID==0 || uwID=='//') { + uwID+=1; + } + cm_aciClients[iClient].ci_adrAddress.adr_uwID = (uwID<<4)+iClient; + // form the connection response packet + ppaConnectionRequest->pa_adrAddress.adr_uwID = '//'; + ppaConnectionRequest->pa_ubReliable = UDP_PACKET_RELIABLE | UDP_PACKET_RELIABLE_HEAD | UDP_PACKET_RELIABLE_TAIL | UDP_PACKET_CONNECT_RESPONSE; + // return it to the client + ppaConnectionRequest->WriteToPacket(&(cm_aciClients[iClient].ci_adrAddress.adr_uwID),sizeof(cm_aciClients[iClient].ci_adrAddress.adr_uwID),ppaConnectionRequest->pa_ubReliable,cm_ciBroadcast.ci_ulSequence++,ppaConnectionRequest->pa_adrAddress.adr_uwID,sizeof(cm_aciClients[iClient].ci_adrAddress.adr_uwID)); + cm_ciBroadcast.ci_pbOutputBuffer.AppendPacket(*ppaConnectionRequest,TRUE); + cm_aciClients[iClient].ci_bUsed = TRUE; + return; + } + } + + // if none found + if (!bFoundEmpty) { + // error + ThrowF_t(TRANS("Server: Cannot accept new clients, all slots used!\n")); + } + + } + } + + +}; + + +/* + * ---->>>> SERVER <<<<---- + */ + +/* + * Initialize server + */ +void CCommunicationInterface::Server_Init_t(void) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + + ASSERT(cci_bInitialized); + ASSERT(!cci_bServerInitialized); + + + + // for each client + for(INDEX iClient=0; iClient=0 && iClient=0 && iClient=0 && iClient=0 && iClient=0 && iClient=0 && iClient=0 && iClient=0 && iClientGetHighPrecisionTimer(); + INDEX iClient; + + // transfer packets for the local client + if (cm_ciLocalClient.ci_bUsed && cm_ciLocalClient.ci_pciOther != NULL) { + cm_ciLocalClient.ExchangeBuffers(); + }; + + cm_aciClients[0].UpdateOutputBuffers(); + + // if not just playing single player + if (cci_bServerInitialized) { + Broadcast_Update_t(); + // for each client transfer packets from the output buffer to the master output buffer + for (iClient=1; iClient 0) { + ppaPacket = ci.ci_pbOutputBuffer.PeekFirstPacket(); + if (ppaPacket->pa_tvSendWhen < tvNow) { + ci.ci_pbOutputBuffer.RemoveFirstPacket(FALSE); + if (ppaPacket->pa_ubReliable & UDP_PACKET_RELIABLE) { + ppaPacketCopy = new CPacket; + *ppaPacketCopy = *ppaPacket; + ci.ci_pbWaitAckBuffer.AppendPacket(*ppaPacketCopy,FALSE); + } + cci_pbMasterOutput.AppendPacket(*ppaPacket,FALSE); + } else { + break; + } + } + } else { + CPrintF(TRANS("Unable to deliver data to client '%s', disconnecting.\n"),AddressToString(cm_aciClients[iClient].ci_adrAddress.adr_ulAddress)); + Server_ClearClient(iClient); + _pNetwork->ga_srvServer.HandleClientDisconected(iClient); + + } + } + + // update broadcast output buffers + // update its buffers + cm_ciBroadcast.UpdateOutputBuffers(); + // transfer packets ready to be sent out to the master output buffer + while (cm_ciBroadcast.ci_pbOutputBuffer.pb_ulNumOfPackets > 0) { + ppaPacket = cm_ciBroadcast.ci_pbOutputBuffer.PeekFirstPacket(); + if (ppaPacket->pa_tvSendWhen < tvNow) { + cm_ciBroadcast.ci_pbOutputBuffer.RemoveFirstPacket(FALSE); + cci_pbMasterOutput.AppendPacket(*ppaPacket,FALSE); + } else { + break; + } + } + + // send/receive packets over the TCP/IP stack + UpdateMasterBuffers(); + + // dispatch all packets from the master input buffer to the clients' input buffers + while (cci_pbMasterInput.pb_ulNumOfPackets > 0) { + BOOL bClientFound; + ppaPacket = cci_pbMasterInput.GetFirstPacket(); + bClientFound = FALSE; + if (ppaPacket->pa_adrAddress.adr_uwID=='//' || ppaPacket->pa_adrAddress.adr_uwID==0) { + cm_ciBroadcast.ci_pbInputBuffer.AppendPacket(*ppaPacket,FALSE); + bClientFound = TRUE; + } else { + for (iClient=0; iClientpa_adrAddress.adr_uwID == cm_aciClients[iClient].ci_adrAddress.adr_uwID) { + cm_aciClients[iClient].ci_pbInputBuffer.AppendPacket(*ppaPacket,FALSE); + bClientFound = TRUE; + break; + } + } + } + if (!bClientFound) { + // warn about possible attack + extern INDEX net_bReportMiscErrors; + if (net_bReportMiscErrors) { + CPrintF(TRANS("WARNING: Invalid message from: %s\n"), AddressToString(ppaPacket->pa_adrAddress.adr_ulAddress)); + } + } + } + + for (iClient=1; iClient>>> CLIENT <<<<---- + */ + +/* + * Initialize client + */ +void CCommunicationInterface::Client_Init_t(char* strServerName) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + + ASSERT(cci_bInitialized); + ASSERT(!cci_bClientInitialized); + + // retrieve server address from server name + ULONG ulServerAddress = StringToAddress(strServerName); + // if lookup failed + if (ulServerAddress==INADDR_NONE) { + ThrowF_t(TRANS("Host '%s' not found!\n"), strServerName); + } + + // call client init with server address + Client_Init_t(ulServerAddress); +}; + +void CCommunicationInterface::Client_Init_t(ULONG ulServerAddress) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + + ASSERT(cci_bInitialized); + ASSERT(!cci_bClientInitialized); + + cm_ciLocalClient.Clear(); + cm_ciLocalClient.ci_pbOutputBuffer.pb_ppbsStats = &_pbsSend; + cm_ciLocalClient.ci_pbInputBuffer.pb_ppbsStats = &_pbsRecv; + + // if this computer is not the server + if (!cci_bServerInitialized) { + // open with connecting to remote server + cm_ciLocalClient.ci_bClientLocal= FALSE; + Client_OpenNet_t(ulServerAddress); + + // if this computer is server + } else { + // open local client + cm_ciLocalClient.ci_bClientLocal = TRUE; + Client_OpenLocal(); + } + + cci_bClientInitialized = TRUE; +}; + +/* + * Close client + */ +void CCommunicationInterface::Client_Close(void) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + + ASSERT(cci_bInitialized); + + // dispatch remaining packets (keep trying for half a second - 10 attempts) + for(TIME tmWait=0; tmWait<500; + Sleep(NET_WAITMESSAGE_DELAY), tmWait+=NET_WAITMESSAGE_DELAY) { + // if all packets are successfully sent, exit loop + if ((cm_ciLocalClient.ci_pbOutputBuffer.pb_ulNumOfPackets == 0) + && (cm_ciLocalClient.ci_pbWaitAckBuffer.pb_ulNumOfPackets == 0)) { + break; + } + if (Client_Update() == FALSE) { + break; + } + } + + cm_ciLocalClient.Clear(); + + cm_ciLocalClient.ci_bClientLocal= FALSE; + cci_bClientInitialized = FALSE; +}; + + +/* + * Open client local + */ +void CCommunicationInterface::Client_OpenLocal(void) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + + CClientInterface &ci0 = cm_ciLocalClient; + CClientInterface &ci1 = cm_aciClients[SERVER_LOCAL_CLIENT]; + + ci0.ci_bUsed = TRUE; + ci0.SetLocal(&ci1); + ci1.ci_bUsed = TRUE; + ci1.SetLocal(&ci0); +}; + + +/* + * Open client remote + */ +void CCommunicationInterface::Client_OpenNet_t(ULONG ulServerAddress) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + CPacket* ppaInfoPacket; + CPacket* ppaReadPacket; + UBYTE ubDummy=65; + UBYTE ubReliable; + + // check for reconnection + static ULONG ulLastServerAddress = -1; + BOOL bReconnecting = ulServerAddress == ulLastServerAddress; + ulLastServerAddress = ulServerAddress; + + const INDEX iRefresh = 100; // (in miliseconds) + // determine connection timeout + INDEX ctRetries = bReconnecting?(180*1000/iRefresh):3; + + // start waiting for server's response + if (ctRetries>1) { + SetProgressDescription(TRANS("waiting for server")); + CallProgressHook_t(0.0f); + } + + + + // form the connection request packet + ppaInfoPacket = new CPacket; + ubReliable = UDP_PACKET_RELIABLE | UDP_PACKET_RELIABLE_HEAD | UDP_PACKET_RELIABLE_TAIL | UDP_PACKET_CONNECT_REQUEST; + ppaInfoPacket->pa_adrAddress.adr_ulAddress = ulServerAddress; + ppaInfoPacket->pa_adrAddress.adr_uwPort = net_iPort; + ppaInfoPacket->pa_ubRetryNumber = 0; + ppaInfoPacket->WriteToPacket(&ubDummy,1,ubReliable,cm_ciLocalClient.ci_ulSequence++,'//',1); + + cm_ciLocalClient.ci_pbOutputBuffer.AppendPacket(*ppaInfoPacket,TRUE); + + // set client destination address to server address + cm_ciLocalClient.ci_adrAddress.adr_ulAddress = ulServerAddress; + cm_ciLocalClient.ci_adrAddress.adr_uwPort = net_iPort; + + // for each retry + for(INDEX iRetry=0; iRetry 0) { + ppaReadPacket = cm_ciLocalClient.ci_pbReliableInputBuffer.GetFirstPacket(); + // and it is a connection confirmation + if (ppaReadPacket->pa_ubReliable && UDP_PACKET_CONNECT_RESPONSE) { + // the client has succedeed to connect, so read the uwID from the packet + cm_ciLocalClient.ci_adrAddress.adr_ulAddress = ulServerAddress; + cm_ciLocalClient.ci_adrAddress.adr_uwPort = net_iPort; + cm_ciLocalClient.ci_adrAddress.adr_uwID = *((UWORD*) (ppaReadPacket->pa_pubPacketData + MAX_HEADER_SIZE)); + cm_ciLocalClient.ci_bUsed = TRUE; + cm_ciLocalClient.ci_bClientLocal = FALSE; + cm_ciLocalClient.ci_pciOther = NULL; + + cm_ciLocalClient.ci_pbReliableInputBuffer.RemoveConnectResponsePackets(); + + delete ppaReadPacket; + + // finish waiting + CallProgressHook_t(1.0f); + return; + } + } + + Sleep(iRefresh); + CallProgressHook_t(FLOAT(iRetry%10)/10); + } + + cci_bBound = FALSE; + ThrowF_t(TRANS("Client: Timeout receiving UDP port")); +}; + + +/* + * Clear local client + */ + +void CCommunicationInterface::Client_Clear(void) +{ + // synchronize access to communication data + CTSingleLock slComm(&cm_csComm, TRUE); + + cm_ciLocalClient.Clear(); +}; + +/* + * Client get status + */ +BOOL CCommunicationInterface::Client_IsConnected(void) +{ + // synchronize access to communication data + CTSingleLock slComm(&cm_csComm, TRUE); + + return cm_ciLocalClient.ci_bUsed; +}; + +/* + * Client Send/Receive Reliable + */ +void CCommunicationInterface::Client_Send_Reliable(const void *pvSend, SLONG slSendSize) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + cm_ciLocalClient.Send(pvSend, slSendSize,TRUE); +}; + +BOOL CCommunicationInterface::Client_Receive_Reliable(void *pvReceive, SLONG &slReceiveSize) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + return cm_ciLocalClient.Receive(pvReceive, slReceiveSize,TRUE); +}; + +BOOL CCommunicationInterface::Client_Receive_Reliable(CTStream &strmReceive) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + return cm_ciLocalClient.Receive(strmReceive,TRUE); +}; + +void CCommunicationInterface::Client_PeekSize_Reliable(SLONG &slExpectedSize,SLONG &slReceivedSize) +{ + slExpectedSize = cm_ciLocalClient.GetExpectedReliableSize(); + slReceivedSize = cm_ciLocalClient.GetCurrentReliableSize(); +} + + +/* + * Client Send/Receive Unreliable + */ +void CCommunicationInterface::Client_Send_Unreliable(const void *pvSend, SLONG slSendSize) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + cm_ciLocalClient.Send(pvSend, slSendSize,FALSE); +}; + +BOOL CCommunicationInterface::Client_Receive_Unreliable(void *pvReceive, SLONG &slReceiveSize) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + return cm_ciLocalClient.Receive(pvReceive, slReceiveSize,FALSE); +}; + + + +BOOL CCommunicationInterface::Client_Update(void) +{ + CTSingleLock slComm(&cm_csComm, TRUE); + CPacket *ppaPacket; + CPacket *ppaPacketCopy; + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + + // update local client's output buffers + if (cm_ciLocalClient.UpdateOutputBuffers() == FALSE) { + return FALSE; + } + + // if not playing on the server (i.e. connectet to a remote server) + if (!cci_bServerInitialized) { + // put all pending packets in the master output buffer + while (cm_ciLocalClient.ci_pbOutputBuffer.pb_ulNumOfPackets > 0) { + ppaPacket = cm_ciLocalClient.ci_pbOutputBuffer.PeekFirstPacket(); + if (ppaPacket->pa_tvSendWhen < tvNow) { + cm_ciLocalClient.ci_pbOutputBuffer.RemoveFirstPacket(FALSE); + if (ppaPacket->pa_ubReliable & UDP_PACKET_RELIABLE) { + ppaPacketCopy = new CPacket; + *ppaPacketCopy = *ppaPacket; + cm_ciLocalClient.ci_pbWaitAckBuffer.AppendPacket(*ppaPacketCopy,FALSE); + } + cci_pbMasterOutput.AppendPacket(*ppaPacket,FALSE); + + } else { + break; + } + } + + // update broadcast output buffers + // update its buffers + cm_ciBroadcast.UpdateOutputBuffers(); + // transfer packets ready to be sent out to the master output buffer + while (cm_ciBroadcast.ci_pbOutputBuffer.pb_ulNumOfPackets > 0) { + ppaPacket = cm_ciBroadcast.ci_pbOutputBuffer.PeekFirstPacket(); + if (ppaPacket->pa_tvSendWhen < tvNow) { + cm_ciBroadcast.ci_pbOutputBuffer.RemoveFirstPacket(FALSE); + cci_pbMasterOutput.AppendPacket(*ppaPacket,FALSE); + } else { + break; + } + } + + // send/receive packets over the TCP/IP stack + UpdateMasterBuffers(); + + // dispatch all packets from the master input buffer to the clients' input buffers + while (cci_pbMasterInput.pb_ulNumOfPackets > 0) { + BOOL bClientFound; + ppaPacket = cci_pbMasterInput.GetFirstPacket(); + bClientFound = FALSE; + + // if the packet address is broadcast and it's an unreliable transfer, put it in the broadcast buffer + if ((ppaPacket->pa_adrAddress.adr_uwID=='//' || ppaPacket->pa_adrAddress.adr_uwID==0) && + ppaPacket->pa_ubReliable == UDP_PACKET_UNRELIABLE) { + cm_ciBroadcast.ci_pbInputBuffer.AppendPacket(*ppaPacket,FALSE); + bClientFound = TRUE; + // if the packet is for this client, accept it + } else if ((ppaPacket->pa_adrAddress.adr_uwID == cm_ciLocalClient.ci_adrAddress.adr_uwID) || + ppaPacket->pa_adrAddress.adr_uwID=='//' || ppaPacket->pa_adrAddress.adr_uwID==0) { + cm_ciLocalClient.ci_pbInputBuffer.AppendPacket(*ppaPacket,FALSE); + bClientFound = TRUE; + } + if (!bClientFound) { + // warn about possible attack + extern INDEX net_bReportMiscErrors; + if (net_bReportMiscErrors) { + CPrintF(TRANS("WARNING: Invalid message from: %s\n"), AddressToString(ppaPacket->pa_adrAddress.adr_ulAddress)); + } + } + } + + } + + cm_ciLocalClient.UpdateInputBuffers(); + cm_ciBroadcast.UpdateInputBuffersBroadcast(); + + return TRUE; +}; + + + +// update master UDP socket and route its messages +void CCommunicationInterface::UpdateMasterBuffers() +{ + + UBYTE aub[MAX_PACKET_SIZE]; + CAddress adrIncomingAddress; + SOCKADDR_IN sa; + int size = sizeof(sa); + SLONG slSizeReceived; + SLONG slSizeSent; + BOOL bSomethingDone; + CPacket* ppaNewPacket; + CTimerValue tvNow; + + if (cci_bBound) { + // read from the socket while there is incoming data + do { + + // initially, nothing is done + bSomethingDone = FALSE; + slSizeReceived = recvfrom(cci_hSocket,(char*)aub,MAX_PACKET_SIZE,0,(SOCKADDR *)&sa,&size); + tvNow = _pTimer->GetHighPrecisionTimer(); + + adrIncomingAddress.adr_ulAddress = ntohl(sa.sin_addr.s_addr); + adrIncomingAddress.adr_uwPort = ntohs(sa.sin_port); + + //On error, report it to the console (if error is not a no data to read message) + if (slSizeReceived == SOCKET_ERROR) { + int iResult = WSAGetLastError(); + if (iResult!=WSAEWOULDBLOCK) { + // report it + if (iResult!=WSAECONNRESET || net_bReportICMPErrors) { + CPrintF(TRANS("Socket error during UDP receive. %s\n"), + (const char*)GetSocketError(iResult)); + return; + } + } + + // if block received + } else { + // if there is not at least one byte more in the packet than the header size + if (slSizeReceived <= MAX_HEADER_SIZE) { + // the packet is in error + extern INDEX net_bReportMiscErrors; + if (net_bReportMiscErrors) { + CPrintF(TRANS("WARNING: Bad UDP packet from '%s'\n"), AddressToString(adrIncomingAddress.adr_ulAddress)); + } + // there might be more to do + bSomethingDone = TRUE; + } else if (net_fDropPackets <= 0 || (FLOAT(rand())/RAND_MAX) > net_fDropPackets) { + // if no packet drop emulation (or the packet is not dropped), form the packet + // and add it to the end of the UDP Master's input buffer + ppaNewPacket = new CPacket; + ppaNewPacket->WriteToPacketRaw(aub,slSizeReceived); + ppaNewPacket->pa_adrAddress.adr_ulAddress = adrIncomingAddress.adr_ulAddress; + ppaNewPacket->pa_adrAddress.adr_uwPort = adrIncomingAddress.adr_uwPort; + + if (net_bReportPackets == TRUE) { + CPrintF("%lu: Received sequence: %d from ID: %d, reliable flag: %d\n",(ULONG) tvNow.GetMilliseconds(),ppaNewPacket->pa_ulSequence,ppaNewPacket->pa_adrAddress.adr_uwID,ppaNewPacket->pa_ubReliable); + } + + cci_pbMasterInput.AppendPacket(*ppaNewPacket,FALSE); + // there might be more to do + bSomethingDone = TRUE; + + } + } + + } while (bSomethingDone); + } + + // write from the output buffer to the socket + while (cci_pbMasterOutput.pb_ulNumOfPackets > 0) { + ppaNewPacket = cci_pbMasterOutput.PeekFirstPacket(); + + sa.sin_family = AF_INET; + sa.sin_addr.s_addr = htonl(ppaNewPacket->pa_adrAddress.adr_ulAddress); + sa.sin_port = htons(ppaNewPacket->pa_adrAddress.adr_uwPort); + + slSizeSent = sendto(cci_hSocket, (char*) ppaNewPacket->pa_pubPacketData, (int) ppaNewPacket->pa_slSize, 0, (SOCKADDR *)&sa, sizeof(sa)); + cci_bBound = TRUE; // UDP socket that did a send is considered bound + tvNow = _pTimer->GetHighPrecisionTimer(); + + // if some error + if (slSizeSent == SOCKET_ERROR) { + int iResult = WSAGetLastError(); + // if output UDP buffer full, stop sending + if (iResult == WSAEWOULDBLOCK) { + return; + // report it + } else if (iResult!=WSAECONNRESET || net_bReportICMPErrors) { + CPrintF(TRANS("Socket error during UDP send. %s\n"), + (const char*)GetSocketError(iResult)); + } + return; + // if all sent ok + } else { + + if (net_bReportPackets == TRUE) { + CPrintF("%lu: Sent sequence: %d to ID: %d, reliable flag: %d\n",(ULONG)tvNow.GetMilliseconds(),ppaNewPacket->pa_ulSequence,ppaNewPacket->pa_adrAddress.adr_uwID,ppaNewPacket->pa_ubReliable); + } + + cci_pbMasterOutput.RemoveFirstPacket(TRUE); + bSomethingDone=TRUE; + } + + } + + + + +}; + + diff --git a/Sources/Engine/Network/CommunicationInterface.h b/Sources/Engine/Network/CommunicationInterface.h new file mode 100644 index 0000000..d95c306 --- /dev/null +++ b/Sources/Engine/Network/CommunicationInterface.h @@ -0,0 +1,113 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_COMMUNICATIONINTERFACE_H +#define SE_INCL_COMMUNICATIONINTERFACE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + + + +#define SERVER_CLIENTS 16 + +#include + +// Communication class +class ENGINE_API CCommunicationInterface { +public: + BOOL cci_bSocketOpen; // set if socket is open and working + BOOL cci_bBound; // set for udp sockets that have been explicitly or implicitly bound + BOOL cci_bInitialized; // is the communication interface initialized or not + BOOL cci_bWinSockOpen; // is the winsock API initialized + BOOL cci_bServerInitialized; + BOOL cci_bClientInitialized; + + CPacketBuffer cci_pbMasterOutput; // master output buffer + CPacketBuffer cci_pbMasterInput; // master input buffer + + SOCKET cci_hSocket; // the socket handle itself + +public: + // client + void Client_OpenLocal(void); + void Client_OpenNet_t(ULONG ulServerAddress); + // update master UDP socket and route its messages + void UpdateMasterBuffers(void); + +public: + CCommunicationInterface(void); + ~CCommunicationInterface(void){}; + + // start/stop protocols + void Init(void); + void Close(void); + + void InitWinsock(void); + void EndWinsock(void); + void PrepareForUse(BOOL bUseNetwork, BOOL bClient); + void Unprepare(void); + BOOL IsNetworkEnabled(void); + // get address of local machine + void GetHostName(CTString &strName, CTString &strAddress); + + // create an inet-family socket + void CreateSocket_t(); + // bind socket to the given address + void Bind_t(ULONG ulLocalHost, ULONG ulLocalPort); + // set socket to non-blocking mode + void SetNonBlocking_t(void); + // get generic socket error info string and last error + CTString GetSocketError(INDEX iError); + // open an UDP socket at given port + void OpenSocket_t(ULONG ulLocalHost, ULONG ulLocalPort); + + // get address of this host + void GetLocalAddress_t(ULONG &ulHost, ULONG &ulPort); + // get address of the peer host connected to this socket + void GetRemoteAddress_t(ULONG &ulHost, ULONG &ulPort); + + // broadcast communication + void Broadcast_Send(const void *pvSend, SLONG slSendSize,CAddress &adrDestination); + BOOL Broadcast_Receive(void *pvReceive, SLONG &slReceiveSize,CAddress &adrAddress); + // here we receive connect requests + void Broadcast_Update_t(void); + + // Server + void Server_Init_t(void); + void Server_Close(void); + + void Server_ClearClient(INDEX iClient); + BOOL Server_IsClientLocal(INDEX iClient); + BOOL Server_IsClientUsed(INDEX iClient); + CTString Server_GetClientName(INDEX iClient); + + void Server_Send_Reliable(INDEX iClient, const void *pvSend, SLONG slSendSize); + BOOL Server_Receive_Reliable(INDEX iClient, void *pvReceive, SLONG &slReceiveSize); + void Server_Send_Unreliable(INDEX iClient, const void *pvSend, SLONG slSendSize); + BOOL Server_Receive_Unreliable(INDEX iClient, void *pvReceive, SLONG &slReceiveSize); + + BOOL Server_Update(void); + + // Client + void Client_Init_t(char* strServerName); + void Client_Init_t(ULONG ulServerAddress); + void Client_Close(void); + + void Client_Clear(void); + BOOL Client_IsConnected(void); + + void Client_Send_Reliable(const void *pvSend, SLONG slSendSize); + BOOL Client_Receive_Reliable(void *pvReceive, SLONG &slReceiveSize); + BOOL Client_Receive_Reliable(CTStream &strmReceive); + void Client_PeekSize_Reliable(SLONG &slExpectedSize,SLONG &slReceivedSize); + void Client_Send_Unreliable(const void *pvSend, SLONG slSendSize); + BOOL Client_Receive_Unreliable(void *pvReceive, SLONG &slReceiveSize); + + BOOL Client_Update(void); +}; + +extern ENGINE_API CCommunicationInterface _cmiComm; +extern CPacketBufferStats _pbsSend; +extern CPacketBufferStats _pbsRecv; + +#endif /* include-once check. */ \ No newline at end of file diff --git a/Sources/Engine/Network/Compression.cpp b/Sources/Engine/Network/Compression.cpp new file mode 100644 index 0000000..10ba359 --- /dev/null +++ b/Sources/Engine/Network/Compression.cpp @@ -0,0 +1,447 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include + +extern CTCriticalSection zip_csLock; // critical section for access to zlib functions + +/* Unpack from stream to stream. */ +void CCompressor::UnpackStream_t(CTMemoryStream &strmSrc, CTStream &strmDst) // throw char * +{ + // read the header + SLONG slSizeDst, slSizeSrc; + strmSrc>>slSizeDst; + strmSrc>>slSizeSrc; + // get the buffer of source stream + UBYTE *pubSrc = strmSrc.mstrm_pubBuffer + strmSrc.mstrm_slLocation; + // allocate buffer for decompression + UBYTE *pubDst = (UBYTE*)AllocMemory(slSizeDst); + // compress there + BOOL bOk = Unpack(pubSrc, slSizeSrc, pubDst, slSizeDst); + // if failed + if (!bOk) { + // report error + FreeMemory(pubDst); + ThrowF_t(TRANS("Error while unpacking a stream.")); + } + + // write the uncompressed data to destination + strmDst.Write_t(pubDst, slSizeDst); + strmDst.SetPos_t(0); + FreeMemory(pubDst); +} + +void CCompressor::PackStream_t(CTMemoryStream &strmSrc, CTStream &strmDst) // throw char * +{ + // get the buffer of source stream + UBYTE *pubSrc = strmSrc.mstrm_pubBuffer + strmSrc.mstrm_slLocation; + SLONG slSizeSrc = strmSrc.GetStreamSize(); + // allocate buffer for compression + SLONG slSizeDst = NeededDestinationSize(slSizeSrc); + UBYTE *pubDst = (UBYTE*)AllocMemory(slSizeDst); + // compress there + BOOL bOk = Pack(pubSrc, slSizeSrc, pubDst, slSizeDst); + // if failed + if (!bOk) { + // report error + FreeMemory(pubDst); + ThrowF_t(TRANS("Error while packing a stream.")); + } + + // write the header to destination + strmDst< REPLICATION + If the code is negative, following data is one byte that is replicated given number of + times: + CODE DATA -> DATA DATA DATA ... DATA ((-CODE)+1 times) + (note that it is not possible to encode just one byte this way, since one byte can be coded + well with copying) + (count = -code+1 => code = -count+1) + + 2) CODE>=0 => COPYING + If the code is positive, following data is given number of bytes that are just copied: + CODE DAT0 DAT1 ... DATn -> DAT0 DAT1 ... DATn (n=CODE) + (note that CODE=0 means copy next one byte) + (count = code+1 => code = count-1) + +Packing algorithm used here relies on the destination buffer being big enough to +hold packed data. Generally, for BYTE-BYTE packing, maximum buffer is 129/128 of +original size (degenerate case with no data replication). +*/ + +/* + * Calculate needed size for destination buffer when packing memory. + */ +SLONG CRLEBBCompressor::NeededDestinationSize(SLONG slSourceSize) +{ + // calculate worst case possible for size of RLEBB packed data + // *129/128+1 would be enough, but we add some more to ensure that we don't + // overwrite the temporary buffer + return slSourceSize*129/128 + 5; +} + +// on entry, slDstSize holds maximum size of output buffer, +// on exit, it is filled with resulting size +/* Pack a chunk of data using given compression. */ +BOOL CRLEBBCompressor::Pack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize) +{ + // cannot pack zero bytes + ASSERT(slSrcSize>=1); + + // calculate limits for source and destination buffers + const SBYTE *pbSourceFirst = (const SBYTE *)pvSrc; // start marker + const SBYTE *pbSourceLimit = (const SBYTE *)pvSrc+slSrcSize; // end marker + +// SLONG slDestinationSize=NeededDestinationSize(slSrcSize); + SBYTE *pbDestinationFirst = (SBYTE *)pvDst; // start marker + SBYTE *pbDestinationLimit = (SBYTE *)pvDst+slDstSize; // end marker + + UBYTE *pbCountFirst = (UBYTE *)pbDestinationLimit-slSrcSize; // start marker + UBYTE *pbCountLimit = (UBYTE *)pbDestinationLimit; // end marker + + { + /* PASS 1: Use destination buffer to cache number of forward-same bytes. */ + + // set the count of the last byte to one + UBYTE *pbCount = pbCountLimit-1; + *pbCount-- = 1; + + // for all bytes from one before last to the first one + for(const SBYTE *pbSource = pbSourceLimit-2; + pbSource>=pbSourceFirst; + pbSource--, pbCount--) { + // if the byte is same as its successor, and the count will fit in code + if (pbSource[0]==pbSource[1] && (SLONG)pbCount[1]+1<=-(SLONG)MIN_SBYTE) { + // set its count to the count of its successor plus one + pbCount[0] = pbCount[1]+1; + // if the byte is different than its successor + } else { + // set its count to one + pbCount[0] = 1; + } + } + } + + + /* PASS 2: Pack bytes from source to the destination buffer. */ + + // start at the beginning of the buffers + const SBYTE *pbSource = pbSourceFirst; + const UBYTE *pbCount = pbCountFirst; + SBYTE *pbDestination = pbDestinationFirst; + + // while there is some data to pack + while(pbSource1) { + // write the replicate-packed data + INDEX ctSameBytes = (INDEX)*pbCount; + SLONG slCode = -ctSameBytes+1; + ASSERT((SLONG)MIN_SBYTE<=slCode && slCode<0); + *pbDestination++ = (SBYTE)slCode; + *pbDestination++ = pbSource[0]; + pbSource+=ctSameBytes; + pbCount +=ctSameBytes; + // if current byte is not replicated + } else { + // count bytes to copy before encountering byte replicated more than 3 times + INDEX ctDiffBytes=1; + while( (ctDiffBytes < (SLONG)MAX_SBYTE + 1) + && (&pbSource[ctDiffBytes]p_dst_post) goto overrun; + if (p_src>p_src_max16) + {unroll=1; + if (p_src>p_src_max1) + {if (p_src==p_src_post) break; goto literal;}} + begin_unrolled_loop: + index=((40543*((((p_src[0]<<4)^p_src[1])<<4)^p_src[2]))>>4) & 0xFFF; + p=hash[index]; + hash[index]=s=p_src; + offset=s-p; + if (offset>4095 || p>=1; control_bits++;} + else + {PS || PS || PS || PS || PS || PS || PS || + PS || PS || PS || PS || PS || PS || s++; len=s-p_src-1; + *p_dst++=(UBYTE)(((offset&0xF00)>>4)+(len-1)); *p_dst++=(UBYTE)(offset&0xFF); + p_src+=len; control=(control>>1)|0x8000; control_bits++;} + /*end_unrolled_loop:*/ if (--unroll) goto begin_unrolled_loop; + if (control_bits==16) + {*p_control=control&0xFF; *(p_control+1)=control>>8; + p_control=p_dst; p_dst+=2; control=control_bits=0;} + } + control>>=16-control_bits; + *p_control++=control&0xFF; *p_control++=control>>8; + if (p_control==p_dst) p_dst-=2; + *p_dst_len=(p_dst-p_dst_first); + return; + overrun: fast_copy(p_src_first,p_dst_first+FLAG_BYTES,src_len); + *p_dst_first=FLAG_COPY; *p_dst_len=src_len+FLAG_BYTES; +} + +/******************************************************************************/ + +void lzrw1_decompress(const UBYTE *p_src_first, ULONG src_len, UBYTE *p_dst_first, ULONG *p_dst_len) +/* Input : Specify input block using p_src_first and src_len. */ +/* Input : Point p_dst_first to the start of the output zone. */ +/* Input : Point p_dst_len to a ULONG to receive the output length. */ +/* Input : Input block and output zone must not overlap. User knows */ +/* Input : upperbound on output block length from earlier compression. */ +/* Input : In any case, maximum expansion possible is eight times. */ +/* Output : Length of output block written to *p_dst_len. */ +/* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */ +/* Output : Writes only in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */ +{UWORD controlbits=0, control; + const UBYTE *p_src=p_src_first+FLAG_BYTES; + UBYTE *p_dst=p_dst_first; + const UBYTE *p_src_post=p_src_first+src_len; + if (*p_src_first==FLAG_COPY) + {fast_copy(p_src_first+FLAG_BYTES,p_dst_first,src_len-FLAG_BYTES); + *p_dst_len=src_len-FLAG_BYTES; return;} + while (p_src!=p_src_post) + {if (controlbits==0) + {control=*p_src++; control|=(*p_src++)<<8; controlbits=16;} + if (control&1) + {UWORD offset,len; UBYTE *p; + offset=(*p_src&0xF0)<<4; len=1+(*p_src++&0xF); + offset+=*p_src++&0xFF; p=p_dst-offset; + while (len--) *p_dst++=*p++;} + else + *p_dst++=*p_src++; + control>>=1; controlbits--; + } + *p_dst_len=p_dst-p_dst_first; +} + + +/* + * Calculate needed size for destination buffer when packing memory. + */ +SLONG CLZCompressor::NeededDestinationSize(SLONG slSourceSize) +{ + // calculate worst case possible for size of LZ packed data + return slSourceSize+256; +} + +// on entry, slDstSize holds maximum size of output buffer, +// on exit, it is filled with resulting size +/* Pack a chunk of data using given compression. */ +BOOL CLZCompressor::Pack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize) +{ + // this is just wrapper for original function by Ross Williams + SLONG slDestinationSizeResult = slDstSize; + lzrw1_compress( + (const UBYTE *)pvSrc, (ULONG)slSrcSize, + (UBYTE *)pvDst, (ULONG *)&slDestinationSizeResult); + slDstSize = slDestinationSizeResult; + return TRUE; +} + +// on entry, slDstSize holds maximum size of output buffer, +// on exit, it is filled with resulting size +/* Unpack a chunk of data using given compression. */ +BOOL CLZCompressor::Unpack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize) +{ + // this is just wrapper for original function by Ross Williams + SLONG slDestinationSizeResult = slDstSize; + lzrw1_decompress( + (const UBYTE *)pvSrc, (ULONG)slSrcSize, + (UBYTE *)pvDst, (ULONG *)&slDestinationSizeResult); + slDstSize = slDestinationSizeResult; + return TRUE; +} + +/* Calculate needed size for destination buffer when packing memory. */ +SLONG CzlibCompressor::NeededDestinationSize(SLONG slSourceSize) +{ + // calculate worst case possible for size of zlib packed data + // NOTE: zlib docs state 0.1% of uncompressed size + 12 bytes, + // we just want to be on the safe side + return SLONG(slSourceSize*1.1f)+32; +} + +// on entry, slDstSize holds maximum size of output buffer, +// on exit, it is filled with resulting size +/* Pack a chunk of data using given compression. */ +BOOL CzlibCompressor::Pack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize) +{ +/* +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + */ + + CTSingleLock slZip(&zip_csLock, TRUE); + int iResult = compress( + (UBYTE *)pvDst, (ULONG *)&slDstSize, + (const UBYTE *)pvSrc, (ULONG)slSrcSize); + if (iResult==Z_OK) { + return TRUE; + } else { + return FALSE; + } +} + +// on entry, slDstSize holds maximum size of output buffer, +// on exit, it is filled with resulting size +/* Unpack a chunk of data using given compression. */ +BOOL CzlibCompressor::Unpack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize) +{ +/* +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + */ + + CTSingleLock slZip(&zip_csLock, TRUE); + int iResult = uncompress( + (UBYTE *)pvDst, (ULONG *)&slDstSize, + (const UBYTE *)pvSrc, (ULONG)slSrcSize); + + if (iResult==Z_OK) { + return TRUE; + } else { + return FALSE; + } +} diff --git a/Sources/Engine/Network/Compression.h b/Sources/Engine/Network/Compression.h new file mode 100644 index 0000000..020e406 --- /dev/null +++ b/Sources/Engine/Network/Compression.h @@ -0,0 +1,82 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_COMPRESSION_H +#define SE_INCL_COMPRESSION_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* + * Abstract base class for objects that can compress memory blocks. + */ +class CCompressor { +public: + /* Calculate needed size for destination buffer when packing memory with given compression. */ + virtual SLONG NeededDestinationSize(SLONG slSourceSize) = 0; + + // on entry, slDstSize holds maximum size of output buffer, + // on exit, it is filled with resulting size + /* Pack a chunk of data using given compression. */ + virtual BOOL Pack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize) = 0; + /* Unpack a chunk of data using given compression. */ + virtual BOOL Unpack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize) = 0; + + /* Pack/unpack from stream to stream. */ + void UnpackStream_t(CTMemoryStream &strmSrc, CTStream &strmDst); // throw char * + void PackStream_t(CTMemoryStream &strmSrc, CTStream &strmDst); // throw char * +}; + +/* + * Compressor for compressing memory blocks using RLE BYTE-BYTE compression + */ +class CRLEBBCompressor : public CCompressor { +public: + /* Calculate needed size for destination buffer when packing memory. */ + SLONG NeededDestinationSize(SLONG slSourceSize); + + // on entry, slDstSize holds maximum size of output buffer, + // on exit, it is filled with resulting size + /* Pack a chunk of data using given compression. */ + BOOL Pack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize); + /* Unpack a chunk of data using given compression. */ + BOOL Unpack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize); +}; + + +/* + * Compressor for compressing memory blocks using LZ compression + * (uses LZRW1 - a modification by Ross Williams) + */ +class CLZCompressor : public CCompressor { +public: + /* Calculate needed size for destination buffer when packing memory. */ + SLONG NeededDestinationSize(SLONG slSourceSize); + + // on entry, slDstSize holds maximum size of output buffer, + // on exit, it is filled with resulting size + /* Pack a chunk of data using given compression. */ + BOOL Pack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize); + /* Unpack a chunk of data using given compression. */ + BOOL Unpack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize); +}; + +/* + * Compressor for compressing memory blocks using zlib compression + * (zlib uses LZ77 - algorithm) + */ +class CzlibCompressor : public CCompressor { +public: + /* Calculate needed size for destination buffer when packing memory. */ + SLONG NeededDestinationSize(SLONG slSourceSize); + + // on entry, slDstSize holds maximum size of output buffer, + // on exit, it is filled with resulting size + /* Pack a chunk of data using given compression. */ + BOOL Pack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize); + /* Unpack a chunk of data using given compression. */ + BOOL Unpack(const void *pvSrc, SLONG slSrcSize, void *pvDst, SLONG &slDstSize); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/Diff.cpp b/Sources/Engine/Network/Diff.cpp new file mode 100644 index 0000000..3f5bb08 --- /dev/null +++ b/Sources/Engine/Network/Diff.cpp @@ -0,0 +1,350 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include + +#include + +#define DIFF_OLD 0 // copy from old file +#define DIFF_NEW 1 // copy from new file +#define DIFF_XOR 2 // xor between an old block and a new block + +UBYTE *_pubOld = NULL; +SLONG _slSizeOld = 0; +UBYTE *_pubNew = NULL; +SLONG _slSizeNew = 0; +ULONG _ulCRC; + +CTStream *_pstrmOut; + +// emit one block copied from old file +void EmitOld_t(SLONG slOffsetOld, SLONG slSizeOld) +{ + (*_pstrmOut)< _aebiOld; +CStaticStackArray _aebiNew; + +// make array of entity offsets in a block +void MakeInfos(CStaticStackArray &aebi, + UBYTE *pubBlock, SLONG slSize, UBYTE *pubFirst, UBYTE *&pubEnd) +{ + // clear all offsets + aebi.PopAll(); + + // until end of block + UBYTE *pub = pubFirst; + while (pub=0) { + EntityBlockInfo &ebiOld = _aebiOld[ieibOld]; + + // if same + if ( ebiOld.ebi_slSize==ebiNew.ebi_slSize) { + if (memcmp(_pubOld+ebiOld.ebi_slOffset, + _pubNew+ebiNew.ebi_slOffset, ebiNew.ebi_slSize)==0) { + //CPrintF("Same blocks\n"); + // emit copy from old + EmitOld_t(ebiOld.ebi_slOffset, ebiOld.ebi_slSize); + bDone = TRUE; + } else { + //CPrintF("Different blocks\n"); + } + } else { + //CPrintF("Different sizes\n"); + } + + if (!bDone) { + // emit xor + EmitXor_t( + ebiOld.ebi_slOffset, ebiOld.ebi_slSize, + ebiNew.ebi_slOffset, ebiNew.ebi_slSize); + bDone = TRUE; + } + } else { + //CPrintF("Not found\n"); + } + if (!bDone) + { + // emit from new + EmitNew_t(ebiNew.ebi_slOffset, ebiNew.ebi_slSize); + bDone = TRUE; + } + } + + // emit chunk after entities by xor + EmitXor_t( + pubEntEndOld-_pubOld, _pubOld+_slSizeOld-pubEntEndOld, + pubEntEndNew-_pubNew, _pubNew+_slSizeNew-pubEntEndNew); +} + +void UnDiff_t(void) +{ + // start at beginning + UBYTE *pubOld = _pubOld; + UBYTE *pubNew = _pubNew; + SLONG slSizeOldStream = 0; + SLONG slSizeOutStream = 0; + // get header with size of files + if (*(SLONG*)pubNew!='FFID') { + ThrowF_t(TRANS("Not a DIFF stream!")); + } + pubNew+=sizeof(SLONG); + slSizeOldStream = *(SLONG*)pubNew; pubNew+=sizeof(SLONG); + slSizeOutStream = *(SLONG*)pubNew; pubNew+=sizeof(SLONG); + ULONG ulCRC = *(ULONG*)pubNew; pubNew+=sizeof(ULONG); + + CRC_Start(_ulCRC); + + if (slSizeOldStream!=_slSizeOld) { + ThrowF_t(TRANS("Invalid DIFF stream!")); + } + // while not end of diff file + while (pubNew<_pubNew+_slSizeNew) { + // read block type + UBYTE ubType = *pubNew++; + switch(ubType) { + // if block type is 'copy from old file' + case DIFF_OLD: { + // get data offset and size + SLONG slOffsetOld = *(SLONG*)pubNew; pubNew+=sizeof(SLONG); + SLONG slSizeOld = *(SLONG*)pubNew; pubNew+=sizeof(SLONG); + // copy it from there + (*_pstrmOut).Write_t(_pubOld+slOffsetOld, slSizeOld); + CRC_AddBlock(_ulCRC, _pubOld+slOffsetOld, slSizeOld); + } break; + // if block type is 'copy from new file' + case DIFF_NEW: { + // get data size + SLONG slSizeNew = *(SLONG*)pubNew; pubNew+=sizeof(SLONG); + // copy it from there + (*_pstrmOut).Write_t(pubNew, slSizeNew); + CRC_AddBlock(_ulCRC, pubNew, slSizeNew); + pubNew+=slSizeNew; + } break; + // if block type is 'xor between an old block and a new block' + case DIFF_XOR: { + // get data offset and sizes + SLONG slOffsetOld = *(SLONG*)pubNew; pubNew+=sizeof(SLONG); + SLONG slSizeOld = *(SLONG*)pubNew; pubNew+=sizeof(SLONG); + SLONG slSizeNew = *(SLONG*)pubNew; pubNew+=sizeof(SLONG); + + // xor it + SLONG slSizeXor = Min(slSizeOld, slSizeNew); + UBYTE *pub0 = _pubOld+slOffsetOld; + UBYTE *pub1 = pubNew; + for (INDEX i=0; iGetHighPrecisionTimer(); + + _slSizeOld = pstrmOld->GetStreamSize()-pstrmOld->GetPos_t(); + _pubOld = (UBYTE*)AllocMemory(_slSizeOld); + pstrmOld->Read_t(_pubOld, _slSizeOld); + + _slSizeNew = pstrmNew->GetStreamSize()-pstrmNew->GetPos_t(); + _pubNew = (UBYTE*)AllocMemory(_slSizeNew); + pstrmNew->Read_t(_pubNew, _slSizeNew); + + CRC_Start(_ulCRC); + CRC_AddBlock(_ulCRC, _pubNew, _slSizeNew); + CRC_Finish(_ulCRC); + + _pstrmOut = pstrmDiff; + + MakeDiff_t(); + + CTimerValue tv1 = _pTimer->GetHighPrecisionTimer(); + //CPrintF("diff encoded in %.2gs\n", (tv1-tv0).GetSeconds()); + + Cleanup(); + + } catch (char *) { + Cleanup(); + throw; + } +} + +// make a new saved game from difference file and old saved game +void DIFF_Undiff_t(CTStream *pstrmOld, CTStream *pstrmDiff, CTStream *pstrmNew) +{ + try { + CTimerValue tv0 = _pTimer->GetHighPrecisionTimer(); + + _slSizeOld = pstrmOld->GetStreamSize()-pstrmOld->GetPos_t(); + _pubOld = (UBYTE*)AllocMemory(_slSizeOld); + pstrmOld->Read_t(_pubOld, _slSizeOld); + + _slSizeNew = pstrmDiff->GetStreamSize()-pstrmDiff->GetPos_t(); + _pubNew = (UBYTE*)AllocMemory(_slSizeNew); + pstrmDiff->Read_t(_pubNew, _slSizeNew); + + _pstrmOut = pstrmNew; + + UnDiff_t(); + + CTimerValue tv1 = _pTimer->GetHighPrecisionTimer(); + //CPrintF("diff decoded in %.2gs\n", (tv1-tv0).GetSeconds()); + + Cleanup(); + + } catch (char *) { + Cleanup(); + throw; + } +} diff --git a/Sources/Engine/Network/Diff.h b/Sources/Engine/Network/Diff.h new file mode 100644 index 0000000..446172c --- /dev/null +++ b/Sources/Engine/Network/Diff.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_DIFF_H +#define SE_INCL_DIFF_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// make a difference file from two saved games +void DIFF_Diff_t(CTStream *pstrmOld, CTStream *pstrmNew, CTStream *pstrmDiff); // throw char * +// make a new saved game from difference file and old saved game +void DIFF_Undiff_t(CTStream *pstrmOld, CTStream *pstrmDiff, CTStream *pstrmNew); // throw char * + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/EMsgBuffer.cpp b/Sources/Engine/Network/EMsgBuffer.cpp new file mode 100644 index 0000000..a57852d --- /dev/null +++ b/Sources/Engine/Network/EMsgBuffer.cpp @@ -0,0 +1,822 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdafx.h" +#include "EMsgBuffer.h" + +#include +#include +#include + + +void AngleToUL(ANGLE3D &Angle,ULONG &ulResult) +{ + Quaternion qQuat; + FLOAT3D Axis; + float fRotAngle; + ANGLE3D AxisAngles; + UBYTE ubDir; + UWORD swAngle; + + qQuat.FromEuler(Angle); + qQuat.ToAxisAngle(Axis,fRotAngle); + Axis.Normalize(); + DirectionVectorToAngles(Axis,AxisAngles); + + + ubDir = (UBYTE) (AxisAngles(1)/360*255); + ulResult = ubDir; + ubDir = (UBYTE) (AxisAngles(2)/90*127); + ulResult = ulResult << 8; + ulResult |= ubDir; + swAngle = (UWORD) (fRotAngle * 180); // after rounding, angle is precise up to 1/180 degrees (65536/360 ~ 180) + ulResult = (ulResult << 16) | swAngle; + +}; + + +void ULToAngle(ULONG &ulResult,ANGLE3D &Angle) +{ + Quaternion qQuat; + FLOAT3D Axis; + float fRotAngle; + ANGLE3D AxisAngles; + UBYTE ubDir; + UWORD swAngle; + Matrix mRotMatrix; + + swAngle = ulResult & 0x0000FFFF; + fRotAngle = swAngle / 180.0f; + ulResult = ulResult >> 16; + ubDir = ulResult & 0x000000FF; + AxisAngles(2) = ((FLOAT) ubDir)*90/127; + ulResult = ulResult >> 8; + ubDir = ulResult & 0x000000FF; + AxisAngles(1) = ((FLOAT) ubDir)*360/255; + AxisAngles(3) = 0; + + AnglesToDirectionVector(AxisAngles,Axis); + qQuat.FromAxisAngle(Axis,fRotAngle); + qQuat.ToMatrix(mRotMatrix); + + DecomposeRotationMatrixNoSnap(Angle,mRotMatrix); + +}; + + + +void CEntityMessage::WritePlacement(ULONG &ulEntityID,CPlacement3D &plPlacement) +{ + UBYTE *pubMarker; + ULONG ulShrunkAngle; + SWORD swH,swP,swB; + + + em_ulType = EMT_SETPLACEMENT; + em_ubSize = sizeof(FLOAT3D) + sizeof(ULONG); + em_ulEntityID = ulEntityID; + + swH = (SWORD) ((plPlacement.pl_OrientationAngle(1)+180)*5); + swP = (SWORD) ((plPlacement.pl_OrientationAngle(2)+90)*5); + swB = (SWORD) ((plPlacement.pl_OrientationAngle(3)+180)*5); + + ulShrunkAngle = ((((ULONG) swH) & 0x000007FF) << 21); + ulShrunkAngle |= ((((ULONG) swP) & 0x000003FF) << 11); + ulShrunkAngle |= (((ULONG) swB) & 0x000007FF); + + pubMarker = em_aubMessage; + memcpy(pubMarker,&(plPlacement.pl_PositionVector(1)),sizeof(FLOAT3D)); + pubMarker += sizeof(FLOAT3D); + memcpy(pubMarker,&ulShrunkAngle,sizeof(ULONG)); +}; + + +void CEntityMessage::ReadPlacement(ULONG &ulEntityID,CPlacement3D &plPlacement) +{ + ASSERT (em_ulType == EMT_SETPLACEMENT); + UBYTE *pubMarker; + ULONG ulShrunkAngle; + SWORD swH,swP,swB; + + + ulEntityID = em_ulEntityID; + + pubMarker = em_aubMessage; + memcpy(&(plPlacement.pl_PositionVector(1)),pubMarker,sizeof(FLOAT3D)); + pubMarker += sizeof(FLOAT3D); + memcpy(&ulShrunkAngle,pubMarker,sizeof(ULONG)); + + swB = (SWORD) ulShrunkAngle & 0x000007FF; + swP = (SWORD) (ulShrunkAngle >> 11) & 0x000003FF; + swH = (SWORD) (ulShrunkAngle >> 21) & 0x000007FF; + + plPlacement.pl_OrientationAngle(1) = ((float)swH) / 5 - 180; + plPlacement.pl_OrientationAngle(2) = ((float)swP) / 5 - 90; + plPlacement.pl_OrientationAngle(3) = ((float)swB) / 5 - 180; + +}; + + +void CEntityMessage::WriteEntityEvent(ULONG &ulEntityID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize) +{ + UBYTE *pubMarker; + + em_ulType = EMT_EVENT; + em_ubSize = sizeof(UWORD) + uwDataSize; + em_ulEntityID = ulEntityID; + + pubMarker = em_aubMessage; + memcpy(pubMarker,&uwEventCode,sizeof(SLONG)); + pubMarker += sizeof(UWORD); + memcpy(pubMarker,pvEventData,uwDataSize); + +}; + + +void CEntityMessage::ReadEntityEvent(ULONG &ulEntityID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize) +{ + ASSERT (em_ulType == EMT_EVENT); + UBYTE *pubMarker; + + pubMarker = em_aubMessage; + memcpy(&uwEventCode,pubMarker,sizeof(SLONG)); + pubMarker += sizeof(UWORD); + uwDataSize = em_ubSize - sizeof(ULONG) - sizeof(UWORD); + memcpy(pvEventData,pubMarker,uwDataSize); + +}; + + +void CEntityMessage::WriteEntityCreate(ULONG &ulEntityID,CPlacement3D &plPlacement,UWORD &uwEntityClassID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize) +{ + UBYTE *pubMarker; + ULONG ulShrunkAngle; + SWORD swH,swP,swB; + + em_ulType = EMT_CREATE; + em_ubSize = sizeof(FLOAT3D) + sizeof(ULONG) + sizeof(UWORD) + sizeof(UWORD) + uwDataSize; + em_ulEntityID = ulEntityID; + + swH = (SWORD) ((plPlacement.pl_OrientationAngle(1)+180)*5); + swP = (SWORD) ((plPlacement.pl_OrientationAngle(2)+90)*5); + swB = (SWORD) ((plPlacement.pl_OrientationAngle(3)+180)*5); + + ulShrunkAngle = ((((ULONG) swH) & 0x000007FF) << 21); + ulShrunkAngle |= ((((ULONG) swP) & 0x000003FF) << 11); + ulShrunkAngle |= (((ULONG) swB) & 0x000007FF); + + + pubMarker = em_aubMessage; + memcpy(pubMarker,&(plPlacement.pl_PositionVector(1)),sizeof(FLOAT3D)); + pubMarker += sizeof(FLOAT3D); + memcpy(pubMarker,&ulShrunkAngle,sizeof(ULONG)); + pubMarker += sizeof(ULONG); + memcpy(pubMarker,&uwEntityClassID,sizeof(UWORD)); + pubMarker += sizeof(UWORD); + memcpy(pubMarker,&uwEventCode,sizeof(UWORD)); + pubMarker += sizeof(UWORD); + memcpy(pubMarker,pvEventData,uwDataSize); + +}; + +void CEntityMessage::ReadEntityCreate(ULONG &ulEntityID,CPlacement3D &plPlacement,UWORD &uwEntityClassID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize) +{ + ASSERT (em_ulType == EMT_CREATE); + UBYTE *pubMarker; + ULONG ulShrunkAngle; + SWORD swH,swP,swB; + + ulEntityID = em_ulEntityID; + + pubMarker = em_aubMessage; + memcpy(&(plPlacement.pl_PositionVector(1)),pubMarker,sizeof(FLOAT3D)); + pubMarker += sizeof(FLOAT3D); + memcpy(&ulShrunkAngle,pubMarker,sizeof(ULONG)); + + swB = (SWORD) ulShrunkAngle & 0x000007FF; + swP = (SWORD) (ulShrunkAngle >> 11) & 0x000003FF; + swH = (SWORD) (ulShrunkAngle >> 21) & 0x000007FF; + + plPlacement.pl_OrientationAngle(1) = ((float)swH) / 5 - 180; + plPlacement.pl_OrientationAngle(2) = ((float)swP) / 5 - 90; + plPlacement.pl_OrientationAngle(3) = ((float)swB) / 5 - 180; + + pubMarker += sizeof(ULONG); + memcpy(&uwEntityClassID,pubMarker,sizeof(UWORD)); + pubMarker += sizeof(UWORD); + memcpy(&uwEventCode,pubMarker,sizeof(UWORD)); + pubMarker += sizeof(UWORD); + uwDataSize = em_ubSize - sizeof(FLOAT3D) - sizeof(ULONG) - sizeof(UWORD) - sizeof(UWORD); + memcpy(pubMarker,pvEventData,uwDataSize); + +}; + + +void CEntityMessage::WriteEntityDestroy(ULONG &ulEntityID) +{ + + em_ulType = EMT_DESTROY; + em_ubSize = 0; + em_ulEntityID = ulEntityID; + +}; + + +void CEntityMessage::ReadEntityDestroy(ULONG &ulEntityID) +{ + ASSERT (em_ulType == EMT_DESTROY); + + ulEntityID = em_ulEntityID; + +}; + + + +void CEntityMessage::WriteEntityCopy(ULONG &ulSourceEntityID,ULONG &ulTargetEntityID,CPlacement3D &plPlacement,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize) +{ + UBYTE *pubMarker; + ULONG ulShrunkAngle; + SWORD swH,swP,swB; + + em_ulType = EMT_COPY; + em_ubSize = sizeof(ULONG) + sizeof(FLOAT3D) + sizeof(ULONG) + sizeof(UWORD) + uwDataSize; + em_ulEntityID = ulSourceEntityID; + + swH = (SWORD) ((plPlacement.pl_OrientationAngle(1)+180)*5); + swP = (SWORD) ((plPlacement.pl_OrientationAngle(2)+90)*5); + swB = (SWORD) ((plPlacement.pl_OrientationAngle(3)+180)*5); + + ulShrunkAngle = ((((ULONG) swH) & 0x000007FF) << 21); + ulShrunkAngle |= ((((ULONG) swP) & 0x000003FF) << 11); + ulShrunkAngle |= (((ULONG) swB) & 0x000007FF); + + + + pubMarker = em_aubMessage; + memcpy(pubMarker,&ulTargetEntityID,sizeof(ULONG)); + pubMarker += sizeof(ULONG); + memcpy(pubMarker,&(plPlacement.pl_PositionVector(1)),sizeof(FLOAT3D)); + pubMarker += sizeof(FLOAT3D); + memcpy(pubMarker,&ulShrunkAngle,sizeof(ULONG)); + pubMarker += sizeof(ULONG); + memcpy(pubMarker,&uwEventCode,sizeof(SLONG)); + pubMarker += sizeof(UWORD); + memcpy(pubMarker,pvEventData,uwDataSize); + +}; + +void CEntityMessage::ReadEntityCopy(ULONG &ulSourceEntityID,ULONG &ulTargetEntityID,CPlacement3D &plPlacement,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize) +{ + ASSERT (em_ulType == EMT_COPY); + UBYTE *pubMarker; + ULONG ulShrunkAngle; + SWORD swH,swP,swB; + + ulSourceEntityID = em_ulEntityID; + + pubMarker = em_aubMessage; + memcpy(&ulTargetEntityID,pubMarker,sizeof(ULONG)); + pubMarker += sizeof(ULONG); + memcpy(&(plPlacement.pl_PositionVector(1)),pubMarker,sizeof(FLOAT3D)); + pubMarker += sizeof(FLOAT3D); + memcpy(&ulShrunkAngle,pubMarker,sizeof(ULONG)); + + swB = (SWORD) ulShrunkAngle & 0x000007FF; + swP = (SWORD) (ulShrunkAngle >> 11) & 0x000003FF; + swH = (SWORD) (ulShrunkAngle >> 21) & 0x000007FF; + + plPlacement.pl_OrientationAngle(1) = ((float)swH) / 5 - 180; + plPlacement.pl_OrientationAngle(2) = ((float)swP) / 5 - 90; + plPlacement.pl_OrientationAngle(3) = ((float)swB) / 5 - 180; + + pubMarker += sizeof(ULONG); + memcpy(&uwEventCode,pubMarker,sizeof(SLONG)); + pubMarker += sizeof(UWORD); + uwDataSize = em_ubSize - sizeof(ULONG) - sizeof(FLOAT3D) - sizeof(ULONG) - sizeof(UWORD); + memcpy(pubMarker,pvEventData,uwDataSize); + +}; + + + +CEMsgBuffer::CEMsgBuffer() +{ + emb_uwNumTickMarkers = 0; + emb_iFirstTickMarker = 0; + emb_iCurrentTickMarker = 0; + emb_fCurrentTickTime = -1; + + for (int i=0;i 0); + ULONG ulTemp; + int iTickMarker; + + ulTemp = emEntityMessage.em_ulEntityID | (emEntityMessage.em_ulType << 24); + WriteBytes(&(ulTemp),sizeof(ULONG)); + WriteBytes(&(emEntityMessage.em_ubSize),sizeof(emEntityMessage.em_ubSize)); + if (emEntityMessage.em_ubSize > 0) { + WriteBytes(emEntityMessage.em_aubMessage,emEntityMessage.em_ubSize); + } + + iTickMarker = emb_iCurrentTickMarker-1; + if (iTickMarker < 0) iTickMarker += MAX_TICKS_KEPT; + emb_atmTickMarkers[iTickMarker].tm_uwNumMessages++; +}; + + +int CEMsgBuffer::ReadMessage(CEntityMessage &emEntityMessage) +{ + ULONG ulTemp; + + if (bu_slReadOffset == bu_slWriteOffset) { + return EMB_ERR_BUFFER_EMPTY; + } + + ReadBytes(&(ulTemp),sizeof(ULONG)); + emEntityMessage.em_ulType = ulTemp >> 24; + emEntityMessage.em_ulEntityID = ulTemp & 0x007FFFFF; + ReadBytes(&(emEntityMessage.em_ubSize),sizeof(emEntityMessage.em_ubSize)); + if (emEntityMessage.em_ubSize > 0) { + ReadBytes(emEntityMessage.em_aubMessage,emEntityMessage.em_ubSize); + } + + return EMB_SUCCESS_OK; +}; + + +int CEMsgBuffer::PeekMessageAtOffset(CEntityMessage &emEntityMessage,SLONG &slTickOffset) +{ + ASSERT(slTickOffset >= 0 && slTickOffset <= bu_slSize); + ULONG ulTemp; + + PeekBytesAtOffset(&(ulTemp),sizeof(ULONG),slTickOffset); + emEntityMessage.em_ulType = ulTemp >> 24; + emEntityMessage.em_ulEntityID = ulTemp & 0x007FFFFF; + PeekBytesAtOffset(&(emEntityMessage.em_ubSize),sizeof(emEntityMessage.em_ubSize),slTickOffset); + if (emEntityMessage.em_ubSize > 0) { + PeekBytesAtOffset(emEntityMessage.em_aubMessage,emEntityMessage.em_ubSize,slTickOffset); + } + + return EMB_SUCCESS_OK; +}; + + +int CEMsgBuffer::StartNewTick(float fTickTime) +{ + + if (emb_uwNumTickMarkers >= MAX_TICKS_KEPT) { + return EMB_ERR_MAX_TICKS; + } + + emb_atmTickMarkers[emb_iCurrentTickMarker].tm_fTickTime = fTickTime; + emb_atmTickMarkers[emb_iCurrentTickMarker].tm_slTickOffset = bu_slWriteOffset; + emb_atmTickMarkers[emb_iCurrentTickMarker].tm_ubAcknowledgesExpected = 0; + emb_atmTickMarkers[emb_iCurrentTickMarker].tm_uwNumMessages = 0; + + emb_uwNumTickMarkers++; + emb_iCurrentTickMarker++; + emb_iCurrentTickMarker %= MAX_TICKS_KEPT; + + return EMB_SUCCESS_OK; +}; + + +int CEMsgBuffer::SetCurrentTick(float fTickTime) +{ + int iErr; + INDEX iTickIndex; + + iErr = GetTickIndex(fTickTime,iTickIndex); + if (iErr != EMB_SUCCESS_OK) { + return iErr; + } + + emb_iCurrentTickMarker = iTickIndex; + + return EMB_SUCCESS_OK; +}; + + +int CEMsgBuffer::GetTickIndex(float fTickTime,INDEX &iTickIndex) +{ + INDEX iTickMarker; + + // 0.025 should be _pTimer->TickQuantum/2 + for (int i=0;iTickQuantum/2 + for (int i=0;i 0) { + fNextTickTime = emb_atmTickMarkers[0].tm_fTickTime; + return EMB_SUCCESS_OK; + } else { + return EMB_ERR_NOT_IN_BUFFER; + } + } + + if (fTickTime < emb_atmTickMarkers[emb_iFirstTickMarker].tm_fTickTime) { + fNextTickTime = emb_atmTickMarkers[emb_iFirstTickMarker].tm_fTickTime; + return SUCCESS_OK; + }; + + iErr = GetTickIndex(fTickTime,iTickIndex); + if (iErr != EMB_SUCCESS_OK) { + return iErr; + } + + iTickIndex = (iTickIndex + 1) % MAX_TICKS_KEPT; + + fNextTickTime = emb_atmTickMarkers[iTickIndex].tm_fTickTime; + + return EMB_SUCCESS_OK; +}; + + +int CEMsgBuffer::RequestTickAcknowledge(float fTickTime,UBYTE ubNumAcknowledges) +{ + ASSERT (fTickTime >= 0); + INDEX iTickIndex; + int iErr; + + iErr = GetTickIndex(fTickTime,iTickIndex); + if (iErr == EMB_SUCCESS_OK) { + emb_atmTickMarkers[iTickIndex].tm_ubAcknowledgesExpected += ubNumAcknowledges; + return EMB_SUCCESS_OK; + } + return iErr; +}; + + + +int CEMsgBuffer::ReceiveTickAcknowledge(float fTickTime) +{ + ASSERT (fTickTime >= 0); + INDEX iTickIndex; + INDEX iFirst; + int iErr; + int iNumMark = emb_uwNumTickMarkers; + + iErr = GetTickIndex(fTickTime,iTickIndex); + if (iErr == EMB_SUCCESS_OK) { + iFirst = emb_iFirstTickMarker; + emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected--; + while (iFirst!=iTickIndex) { + iFirst++; + iFirst%=MAX_TICKS_KEPT; + emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected--; + } + + + iFirst = emb_iFirstTickMarker; + if (emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected == 0 && iNumMark != 0) { + while (emb_atmTickMarkers[iFirst].tm_ubAcknowledgesExpected == 0 && iNumMark != 0) { + if (iNumMark > 0) { + iNumMark--; + iFirst++; + iFirst %= MAX_TICKS_KEPT; + } + } + MoveToStartOfTick(emb_atmTickMarkers[iFirst].tm_fTickTime); + } + + return EMB_SUCCESS_OK; + } + return iErr; +}; + + +// does not advance the read offset - access is random, not sequential +int CEMsgBuffer::ReadTick(float fTickTime,const void *pv, SLONG &slSize) +{ + ASSERT (slSize>0); + ASSERT (pv != NULL); + ASSERT (fTickTime >= 0); + int iErr; + INDEX iTickIndex,iNextTickIndex; + + + iErr = GetTickIndex(fTickTime,iTickIndex); + + if (iErr != EMB_SUCCESS_OK) { + return iErr; + } + + if (iTickIndex >= (emb_iFirstTickMarker + emb_uwNumTickMarkers - 1)) { + return EMB_ERR_TICK_NOT_COMPLETE; + } + + iNextTickIndex = (iTickIndex + 1) % MAX_TICKS_KEPT; + SLONG slTickSize = emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset - emb_atmTickMarkers[iTickIndex].tm_slTickOffset; + // if not wrapping + if ( slTickSize > 0) { + if (slSize < slTickSize) { + return EMB_ERR_BUFFER_TOO_SMALL; + } + slSize = slTickSize; + memcpy((UBYTE*)pv,bu_pubBuffer+emb_atmTickMarkers[iTickIndex].tm_slTickOffset,slTickSize); + } else { + if (slSize < (bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset) + emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset-1) { + return EMB_ERR_BUFFER_TOO_SMALL; + } + slSize = (bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset) + emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset; + // copy data from the start of this ick to the end of the bufer + memcpy((UBYTE*)pv,bu_pubBuffer+emb_atmTickMarkers[iTickIndex].tm_slTickOffset,bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset); + // copy datafrom the start of the buffer to the start of next tick + memcpy(((UBYTE*)pv)+bu_slSize - emb_atmTickMarkers[iTickIndex].tm_slTickOffset,bu_pubBuffer,emb_atmTickMarkers[iNextTickIndex].tm_slTickOffset); + } + + return EMB_SUCCESS_OK; + +}; + + +void CEMsgBuffer::WriteTick(float tm_fTickTime,const void *pv, SLONG slSize) +{ + ASSERT(slSize>=0 && pv!=NULL); + + StartNewTick(tm_fTickTime); + WriteBytes(pv,slSize); +}; + + + +int CEMsgBuffer::MoveToStartOfTick(float fTickTime) +{ + int iErr; + INDEX iTickIndex; + + ASSERT(fTickTime >= emb_atmTickMarkers[emb_iFirstTickMarker].tm_fTickTime); + + iErr = GetTickIndex(fTickTime,iTickIndex); + if (iErr != EMB_SUCCESS_OK) { + return iErr; + } + + + // if not wrapping + if (iTickIndex >= emb_iFirstTickMarker) { + emb_uwNumTickMarkers -= iTickIndex - emb_iFirstTickMarker; + } else { + emb_uwNumTickMarkers -= iTickIndex + (MAX_TICKS_KEPT - emb_iFirstTickMarker); + } + + emb_iFirstTickMarker = iTickIndex; + + if (bu_slReadOffset <= emb_atmTickMarkers[iTickIndex].tm_slTickOffset) { + bu_slFree += emb_atmTickMarkers[iTickIndex].tm_slTickOffset - bu_slReadOffset; + } else { + bu_slFree += (bu_slSize - bu_slReadOffset) + emb_atmTickMarkers[iTickIndex].tm_slTickOffset; + } + + bu_slReadOffset = emb_atmTickMarkers[iTickIndex].tm_slTickOffset; + + + return EMB_SUCCESS_OK; + +}; + + +// expand buffer to be given number of bytes in size +void CEMsgBuffer::Expand(SLONG slNewSize) +{ + ASSERT(slNewSize>0); + ASSERT(bu_slSize>=0); + // if not already allocated + if (bu_slSize==0) { + // allocate a new empty buffer + ASSERT(bu_pubBuffer==NULL); + bu_pubBuffer = (UBYTE*)AllocMemory(slNewSize); + bu_slWriteOffset = 0; + bu_slReadOffset = 0; + bu_slFree = slNewSize; + bu_slSize = slNewSize; + + // if already allocated + } else { + ASSERT(slNewSize>bu_slSize); + SLONG slSizeDiff = slNewSize-bu_slSize; + ASSERT(bu_pubBuffer!=NULL); + // grow buffer + GrowMemory((void**)&bu_pubBuffer, slNewSize); + + cout << "EXPAND!\n"; + // if buffer is currently wrapping + if (bu_slReadOffset>bu_slWriteOffset||bu_slFree==0) { + cout << "WRAP!\n"; + // move part at the end of buffer to the end + memmove(bu_pubBuffer+bu_slReadOffset+slSizeDiff, bu_pubBuffer+bu_slReadOffset,bu_slSize-bu_slReadOffset); + for (int i=0;i= bu_slReadOffset) { + emb_atmTickMarkers[i].tm_slTickOffset += slSizeDiff; + } + } + bu_slReadOffset+=slSizeDiff; + } + bu_slFree += slNewSize-bu_slSize; + bu_slSize = slNewSize; + + ASSERT(bu_slReadOffset>=0 && bu_slReadOffset=0 && bu_slFree<=bu_slSize); + } +} + + + + +// write bytes to buffer +void CEMsgBuffer::WriteBytes(const void *pv, SLONG slSize) +{ + BOOL bWraping = FALSE; + SLONG slOldReadOffset = bu_slReadOffset; + + // if buffer is currently wrapping + + ASSERT(slSize>=0 && pv!=NULL); + // if there is nothing to write + + if (slSize==0) { + // do nothing + return; + } + // check for errors + if (slSize<0) { + cout << "WARNING: WriteBytes(): slSize<0\n!"; + return; + } + + // if there is not enough free space + if (bu_slFreebu_slWriteOffset||bu_slFree==0) { +// bWraping = TRUE; +// } + // expand the buffer + Expand(slNewSize); + + + ASSERT(bu_slFree>=slSize); + } + + UBYTE *pub = (UBYTE*)pv; + + // write part of block at the end of buffer + SLONG slSizeEnd = __min(bu_slSize-bu_slWriteOffset, slSize); + memcpy(bu_pubBuffer+bu_slWriteOffset, pub, slSizeEnd); + pub+=slSizeEnd; + memcpy(bu_pubBuffer, pub, slSize-slSizeEnd); + // move write pointer + bu_slWriteOffset+=slSize; + bu_slWriteOffset%=bu_slSize; + bu_slFree-=slSize; + + ASSERT(bu_slWriteOffset>=0 && bu_slWriteOffset=0 && bu_slFree<=bu_slSize); +}; + + + + +SLONG CEMsgBuffer::PeekBytes(const void *pv, SLONG slSize) +{ + ASSERT(slSize>0 && pv!=NULL); + UBYTE *pub = (UBYTE*)pv; + + // clamp size to amount of bytes actually in the buffer + SLONG slUsed = bu_slSize-bu_slFree; + if (slUsed=0 && bu_slReadOffset=0 && bu_slFree<=bu_slSize); + + return slSize; +} + + +SLONG CEMsgBuffer::PeekBytesAtOffset(const void *pv, SLONG slSize,SLONG &slTickOffset) +{ + ASSERT(slSize>0 && pv!=NULL); + UBYTE *pub = (UBYTE*)pv; + + // clamp size to amount of bytes actually in the buffer + SLONG slUsed = bu_slSize-bu_slFree; + if (slUsed=0 && slTickOffset=0 && bu_slFree<=bu_slSize); + + return slSize; +} diff --git a/Sources/Engine/Network/EMsgBuffer.h b/Sources/Engine/Network/EMsgBuffer.h new file mode 100644 index 0000000..692ec3e --- /dev/null +++ b/Sources/Engine/Network/EMsgBuffer.h @@ -0,0 +1,124 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_EMSGBUFFER_H +#define SE_INCL_EMSGBUFFER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + + +#include +#include "Buffer.h" + +#define EM_SIZE 256 +#define MAX_TICKS_KEPT 20 // data for how many ticks will be accumulated before an error is reported + + +// max 31 type of messages - stored in the lowest 4 bits of the em_uwType word +// upper 12 bits contain event code, for create and copy messages +#define EMT_CREATE 1 +#define EMT_COPY 2 +#define EMT_SETPLACEMENT 3 +#define EMT_DESTROY 4 +#define EMT_EVENT 5 + +#define EMT_NUMBEROFTYPES 5 // how many different types of messages are there + +#define EMB_SUCCESS_OK 0 +#define EMB_ERR_MAX_TICKS 1 +#define EMB_ERR_NOT_IN_BUFFER 2 +#define EMB_ERR_TICK_NOT_COMPLETE 4 +#define EMB_ERR_BUFFER_TOO_SMALL 5 +#define EMB_ERR_BUFFER_EMPTY 6 + + + +class CEntityMessage { +public: + ULONG em_ulType; + UBYTE em_aubMessage[EM_SIZE]; + UBYTE em_ubSize; + ULONG em_ulEntityID; + + CEntityMessage(){}; + ~CEntityMessage(){}; + + void WritePlacement(ULONG &ulEntityID,CPlacement3D &plPlacement); + void ReadPlacement(ULONG &ulEntityID,CPlacement3D &plPlacement); + + void WriteEntityCreate(ULONG &ulEntityID,CPlacement3D &plPlacement,UWORD &uwEntityClassID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize); + void ReadEntityCreate(ULONG &ulEntityID,CPlacement3D &plPlacement,UWORD &uwEntityClassID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize); + + void WriteEntityCopy(ULONG &ulSourceEntityID,ULONG &ulTargetEntityID,CPlacement3D &plPlacement,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize); + void ReadEntityCopy(ULONG &ulSourceEntityID,ULONG &ulTargetEntityID,CPlacement3D &plPlacement,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize); + + void WriteEntityDestroy(ULONG &ulEntityID); + void ReadEntityDestroy(ULONG &ulEntityID); + + void WriteEntityEvent(ULONG &ulEntityID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize); + void ReadEntityEvent(ULONG &ulEntityID,UWORD &uwEventCode,void* pvEventData,UWORD &uwDataSize); + +}; + + + +struct TickMarker { + float tm_fTickTime; + SLONG tm_slTickOffset; + UBYTE tm_ubAcknowledgesExpected; + UWORD tm_uwNumMessages; + + TickMarker() { + tm_fTickTime = -1; + tm_slTickOffset = -1; + tm_ubAcknowledgesExpected = 0; + tm_uwNumMessages = 0; + } +}; + + +// Entity message buffer - stores entity messages - create, copy, destroy, set placement... +class CEMsgBuffer : public CBuffer{ +public: + CBuffer emb_bufMsgBuffer; // a buffer to store entity messages in + TickMarker emb_atmTickMarkers[MAX_TICKS_KEPT]; // pointers into the buffer, they point to the first message for eachtick + UWORD emb_uwNumTickMarkers; + INDEX emb_iFirstTickMarker; + INDEX emb_iCurrentTickMarker; + float emb_fCurrentTickTime; + + CEMsgBuffer(); + ~CEMsgBuffer(); + + virtual void Clear(void); + + // expand buffer to be given number of bytes in size + virtual void Expand(SLONG slNewSize); + + // write one block + virtual void WriteBytes(const void *pv, SLONG slSize); + SLONG PeekBytes(const void *pv, SLONG slSize); + SLONG PeekBytesAtOffset(const void *pv, SLONG slSize,SLONG &slTickOffset); + + int StartNewTick(float fTickTime); + int SetCurrentTick(float fTickTime); + int GetTickIndex(float fTickTime,INDEX &iTickIndex); + int GetTickOffset(float fTickTime,SLONG &slTickOffset); + int GetNextTickTime(float fTickTime,float &fNextTickTime); + int RequestTickAcknowledge(float fTickTime,UBYTE ubNumAcknowledges); + int ReceiveTickAcknowledge(float fTickTime); + int MoveToStartOfTick(float fTickTime); + + + // write the message from _emEntityMessage to the buffer + void WriteMessage(CEntityMessage &emEntityMessage); + int ReadMessage(CEntityMessage &emEntityMessage); + int PeekMessageAtOffset(CEntityMessage &emEntityMessage,SLONG &slTickOffset); + + int ReadTick(float fTickTime,const void *pv, SLONG &slSize); + void WriteTick(float fTickTime,const void *pv, SLONG slSize); + + +}; + +#endif \ No newline at end of file diff --git a/Sources/Engine/Network/EntityHashing.cpp b/Sources/Engine/Network/EntityHashing.cpp new file mode 100644 index 0000000..8cb64f1 --- /dev/null +++ b/Sources/Engine/Network/EntityHashing.cpp @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "EntityHashing.h" +#include + +extern FLOAT ser_fPositionTreshold; +extern FLOAT ser_fOrientationTreshold; + + + +BOOL CEntityHashItem::ClientNeedsUpdate(INDEX iClient,CNetworkMessage &nmMessage) +{ + ASSERT (iClient>=0 && iClienten_plPlacement; + CPlacement3D &plLastPlacement = ceEntry.ce_plLastSentPlacement; + + FLOAT fPositionDelta,fOrientationDelta; + + fPositionDelta = fabs(plLastPlacement.pl_PositionVector(1) - plPlacement.pl_PositionVector(1)) + + fabs(plLastPlacement.pl_PositionVector(2) - plPlacement.pl_PositionVector(2)) + + fabs(plLastPlacement.pl_PositionVector(3) - plPlacement.pl_PositionVector(3)); + fOrientationDelta = fabs(plLastPlacement.pl_OrientationAngle(1) - plPlacement.pl_OrientationAngle(1)) + + fabs(plLastPlacement.pl_OrientationAngle(2) - plPlacement.pl_OrientationAngle(2)) + + fabs(plLastPlacement.pl_OrientationAngle(3) - plPlacement.pl_OrientationAngle(3)); + + BOOL bSendNow = (fPositionDelta >= ser_fPositionTreshold) || (fOrientationDelta > ser_fOrientationTreshold); + + if (bSendNow) { + WritePackedPlacement(ceEntry,nmMessage); + return TRUE; + } + + return FALSE; + +}; + + +void CEntityHashItem::WritePackedPlacement(CClientEntry &ceEntry,CNetworkMessage &nmMessage) +{ + CPlacement3D &plPlacement = ehi_epEntityPointer->en_plPlacement; + CPlacement3D &plLastPlacement = ceEntry.ce_plLastSentPlacement; + + + +}; \ No newline at end of file diff --git a/Sources/Engine/Network/EntityHashing.h b/Sources/Engine/Network/EntityHashing.h new file mode 100644 index 0000000..ef61940 --- /dev/null +++ b/Sources/Engine/Network/EntityHashing.h @@ -0,0 +1,79 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ENTITYHASHING_H +#define SE_INCL_ENTITYHASHING_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include + +struct CClientEntry { +//implementation + TIME ce_tmLastUpdated; + CPlacement3D ce_plLastSentPlacement; + CPlacement3D ce_plLastSentSpeed; + + CClientEntry() { + ce_tmLastUpdated = -1.0f; + ce_plLastSentPlacement.pl_PositionVector = FLOAT3D(0,0,0); + ce_plLastSentPlacement.pl_OrientationAngle = ANGLE3D(0,0,0); + ce_plLastSentSpeed.pl_PositionVector = FLOAT3D(0,0,0); + ce_plLastSentSpeed.pl_OrientationAngle = ANGLE3D(0,0,0); + } + +} + +class CEntityHashItem { +// implementation +public: + ULONG ehi_ulEntityID; + CEntityPointer ehi_epEntityPointer; + CClientEntry ehi_ceClientEntries[SERVER_CLIENTS]; + + CEntityHashItem() {ehi_ulEntityID = -1;} // entity pointer will initialize itself to NULL + + ~CEntityItem() {}; // entity poiner will destroy itself and remove the reference + + void WritePackedPlacement(CClientEntry &ceEntry,CNetworkMessage &nmMessage); + +// interface +public: + BOOL ClientNeedsUpdate(INDEX iClient,CNetworkMessage &nmMessage); +}; + + +#define VALUE_TYPE ULONG +#define TYPE CEntityHashItem +#define CHashTableSlot_TYPE CEntityHashTableSlot +#define CHashTable_TYPE CEntityHashTable +#include + + + +class ENGINE_API CEntityHash { +// implementation +public: + CEntityHashTable eh_ehtHashTable; + + CEntityHash(); + ~CEntityHash(); + + ULONG GetItemKey(ULONG ulEntityID) {return ulEntityID;} + ULONG GetItemValue(CEntityHashItem* ehiItem) {return ehiItem->ehi_ulUntityID;} + + +// interface +public: + BOOL ClientNeedsUpdate(INDEX iClient,ULONG ulEntityID,CNetworkMessage &nmMessage); + + void AddEntity(CEntityPointer* penEntity); + void RemoveEntity(CEntityPointer* penEntity); + +} + + +#endif // include \ No newline at end of file diff --git a/Sources/Engine/Network/LevelChange.h b/Sources/Engine/Network/LevelChange.h new file mode 100644 index 0000000..c38b60f --- /dev/null +++ b/Sources/Engine/Network/LevelChange.h @@ -0,0 +1,33 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_LEVELCHANGE_H +#define SE_INCL_LEVELCHANGE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +enum LevelChangePhase { + // initial state + LCP_NOCHANGE = 0, + // ->initiation-> + LCP_INITIATED, + // ->pre-change signalled-> + LCP_SIGNALLED, + // ->change done-> + LCP_CHANGED, + // ->post-change signalled-> + //LCP_NOCHANGE +}; + +extern LevelChangePhase _lphCurrent; + +class CRememberedLevel { +public: + CListNode rl_lnInSessionState; // for linking in list of all remembered levels + CTString rl_strFileName; // file name of the level + CTMemoryStream rl_strmSessionState; // saved session state +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/MessageDispatcher.cpp b/Sources/Engine/Network/MessageDispatcher.cpp new file mode 100644 index 0000000..7ffdfcd --- /dev/null +++ b/Sources/Engine/Network/MessageDispatcher.cpp @@ -0,0 +1,459 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// define this to randomly drop messages (for debugging of packet-loss recovery) +//#define LOSEPACKETS_THRESHOLD (RAND_MAX/10) + +extern INDEX net_bReportTraffic; +extern BOOL _bTempNetwork; + +///////////////////////////////////////////////////////////////////// +// CMessageBuffer helper class+implementation + +// class for holding received messages (thread locally) +class CMessageBuffer { +public: + // size of message buffer for one message + ULONG mb_ulMessageBufferSize; + // pointer to message buffer for one message + void *mb_pvMessageBuffer; + + void Allocate(void); + void Free(void); +}; + +// the thread's local buffer +static _declspec(thread) CMessageBuffer mbReceivedMessage = { 0,0 }; + +void CMessageBuffer::Allocate(void) +{ + if (mb_ulMessageBufferSize==0) { + ASSERT(mb_pvMessageBuffer == NULL); + // allocate message buffer + mb_ulMessageBufferSize = 16000; + mb_pvMessageBuffer = AllocMemory(mb_ulMessageBufferSize); + } +} + +void CMessageBuffer::Free(void) +{ + // if message buffer is allocated + if (mb_ulMessageBufferSize != 0) { + ASSERT(mb_pvMessageBuffer != NULL); + // free it + FreeMemory(mb_pvMessageBuffer); + mb_ulMessageBufferSize = 0; + mb_pvMessageBuffer = NULL; + } +} + +///////////////////////////////////////////////////////////////////// +// CNetworkProvider implementation + +/* + * Default constructor. + */ +CNetworkProvider::CNetworkProvider(void) +{ +} + +/* + * Create a human description of driver. + */ +const CTString &CNetworkProvider::GetDescription(void) const +{ + return np_Description; +} + + +///////////////////////////////////////////////////////////////////// +// CNetworkSession implementation + +/* + * Default constructor. + */ +CNetworkSession::CNetworkSession(void) +{ +} +/* Construct a session for connecting to certain server. */ +CNetworkSession::CNetworkSession(const CTString &strAddress) +{ + ns_strAddress = strAddress; +} +void CNetworkSession::Copy(const CNetworkSession &nsOriginal) +{ + ns_strAddress = nsOriginal.ns_strAddress ; + ns_strSession = nsOriginal.ns_strSession ; + ns_strWorld = nsOriginal.ns_strWorld ; + ns_tmPing = nsOriginal.ns_tmPing ; + ns_ctPlayers = nsOriginal.ns_ctPlayers ; + ns_ctMaxPlayers = nsOriginal.ns_ctMaxPlayers ; + ns_strGameType = nsOriginal.ns_strGameType ; + ns_strMod = nsOriginal.ns_strMod ; + ns_strVer = nsOriginal.ns_strVer ; +} + +///////////////////////////////////////////////////////////////////// +// CMessageDispatcher -- construction/destruction + +/* + * Default constructor. + */ +CMessageDispatcher::CMessageDispatcher(void) { + if (!_bTempNetwork) { + _cmiComm.Init(); + } + // enumerate network providers + EnumNetworkProviders_startup(md_lhProviders); +} + +/* + * Destructor. + */ +CMessageDispatcher::~CMessageDispatcher(void) +{ + if (!_bTempNetwork) { + _cmiComm.Close(); + } + // destroy the list of network providers + FORDELETELIST(CNetworkProvider, np_Node, md_lhProviders, litProviders) { + delete &*litProviders; + } +} + +/* + * Initialize for a given game. + */ +void CMessageDispatcher::Init(const CTString &strGameID) +{ + md_strGameID = strGameID; +} + +///////////////////////////////////////////////////////////////////// +// CMessageDispatcher -- network provider management + +/* + * Enumerate all providers at startup (later enumeration just copies this list). + */ +void CMessageDispatcher::EnumNetworkProviders_startup(CListHead &lh) +{ + // create local connection provider + CNetworkProvider *pnpLocal = new CNetworkProvider; + pnpLocal->np_Description = "Local"; + lh.AddTail(pnpLocal->np_Node); + // create TCP/IP connection provider + CNetworkProvider *pnpTCP = new CNetworkProvider; + pnpTCP->np_Description = "TCP/IP Server"; + lh.AddTail(pnpTCP->np_Node); + + CNetworkProvider *pnpTCPCl = new CNetworkProvider; + pnpTCPCl->np_Description = "TCP/IP Client"; + lh.AddTail(pnpTCPCl->np_Node); +} + +/* + * Enumerate all providers. + */ +void CMessageDispatcher::EnumNetworkProviders(CListHead &lh) +{ + // for each provider enumerated at startup + FOREACHINLIST(CNetworkProvider, np_Node, md_lhProviders, litProvider) { + // create a copy + CNetworkProvider *pnpNew = new CNetworkProvider(*litProvider); + // add the copy to the list + lh.AddTail(pnpNew->np_Node); + } +} + +/* + * Start using a service provider. + */ +void CMessageDispatcher::StartProvider_t(const CNetworkProvider &npProvider) +{ + if (npProvider.np_Description=="Local") { + _cmiComm.PrepareForUse(FALSE, FALSE); + } else if (npProvider.np_Description=="TCP/IP Server") { + _cmiComm.PrepareForUse(TRUE, FALSE); + } else { + _cmiComm.PrepareForUse(TRUE, TRUE); + } +} + +/* + * Stop using current service provider. + */ +void CMessageDispatcher::StopProvider(void) +{ + _cmiComm.Unprepare(); +} + +///////////////////////////////////////////////////////////////////// +// CMessageDispatcher -- network message management +static void UpdateSentMessageStats(const CNetworkMessage &nmMessage) +{ + // increment profile counters + _pfNetworkProfile.IncrementCounter(CNetworkProfile::PCI_MESSAGESSENT); + _pfNetworkProfile.IncrementCounter(CNetworkProfile::PCI_BYTESSENT, nmMessage.nm_slSize); + switch (nmMessage.GetType()) { + case MSG_GAMESTREAMBLOCKS: + _pfNetworkProfile.IncrementCounter(CNetworkProfile::PCI_GAMESTREAM_BYTES_SENT, nmMessage.nm_slSize); + break; + case MSG_ACTION: + _pfNetworkProfile.IncrementCounter(CNetworkProfile::PCI_ACTION_BYTES_SENT, nmMessage.nm_slSize); + break; + } + if (net_bReportTraffic) { + CPrintF("Sent: %d\n", nmMessage.nm_slSize); + } +} +static void UpdateSentStreamStats(SLONG slSize) +{ + if (net_bReportTraffic) { + CPrintF("STREAM Sent: %d\n", slSize); + } +} +static void UpdateReceivedMessageStats(const CNetworkMessage &nmMessage) +{ + // increment profile counters + _pfNetworkProfile.IncrementCounter(CNetworkProfile::PCI_MESSAGESRECEIVED); + _pfNetworkProfile.IncrementCounter(CNetworkProfile::PCI_BYTESRECEIVED, nmMessage.nm_slSize); + switch (nmMessage.GetType()) { + case MSG_GAMESTREAMBLOCKS: + _pfNetworkProfile.IncrementCounter(CNetworkProfile::PCI_GAMESTREAM_BYTES_RECEIVED, nmMessage.nm_slSize); + break; + case MSG_ACTION: + _pfNetworkProfile.IncrementCounter(CNetworkProfile::PCI_ACTION_BYTES_RECEIVED, nmMessage.nm_slSize); + break; + } + if (net_bReportTraffic) { + CPrintF("Rcvd: %d\n", nmMessage.nm_slSize); + } +} +static void UpdateReceivedStreamStats(SLONG slSize) +{ + if (net_bReportTraffic) { + CPrintF("STREAM Rcvd: %d\n", slSize); + } +} + +/* Send a message from server to client. */ +void CMessageDispatcher::SendToClient(INDEX iClient, const CNetworkMessage &nmMessage) +{ +// if testing for packet-loss recovery +#ifdef LOSEPACKETS_THRESHOLD + // every once a while + if (rand() +#include + +/* + * Network provider description. + */ +class ENGINE_API CNetworkProvider { +public: + CTString np_Description; // description string of the driver +public: + CListNode np_Node; // for linking in list of avaliable providers + + /* Default constructor. */ + CNetworkProvider(void); + + /* Create a human description of driver. */ + const CTString &GetDescription(void) const; +}; + +/* + * Message dispatcher object for sending/receiving messages. + * + * NOTE: message buffer is handled thread-locally + * (only one CMessageDispatcher object pre process is allowed) + */ +class ENGINE_API CMessageDispatcher { +public: + CListHead md_lhProviders; // statical list of providers initialized at startup + CTString md_strGameID; + + /* Enumerate all providers at startup (later enumeration just copies this list). */ + void EnumNetworkProviders_startup(CListHead &lh); +public: + /* Default constructor. */ + CMessageDispatcher(void); + /* Destructor. */ + ~CMessageDispatcher(void); + + /* Initialize for a given game. */ + void Init(const CTString &strGameID); + + /* Enumerate all providers. */ + void EnumNetworkProviders(CListHead &lh); + /* Start using a service provider. */ + void StartProvider_t(const CNetworkProvider &npProvider); + /* Stop using current service provider. */ + void StopProvider(void); + + /* Send a message from server to client. */ + void SendToClient(INDEX iClient, const CNetworkMessage &nmMessage); + void SendToClientReliable(INDEX iClient, const CNetworkMessage &nmMessage); + void SendToClientReliable(INDEX iClient, CTMemoryStream &strmMessage); + /* Send a message from client to server. */ + void SendToServer(const CNetworkMessage &nmMessage); + void SendToServerReliable(const CNetworkMessage &nmMessage); + /* Receive next message from client to server. */ + BOOL ReceiveFromClient(INDEX iClient, CNetworkMessage &nmMessage); + BOOL ReceiveFromClientReliable(INDEX iClient, CNetworkMessage &nmMessage); + /* Receive next message from server to client. */ + BOOL ReceiveFromServer(CNetworkMessage &nmMessage); + BOOL ReceiveFromServerReliable(CNetworkMessage &nmMessage); + BOOL ReceiveFromServerReliable(CTMemoryStream &strmMessage); + /* Send/receive broadcast messages. */ + void SendBroadcast(const CNetworkMessage &nmMessage, ULONG ulAddr, UWORD uwPort); + BOOL ReceiveBroadcast(CNetworkMessage &nmMessage, ULONG &ulAddr, UWORD &uwPort); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/Network.cpp b/Sources/Engine/Network/Network.cpp new file mode 100644 index 0000000..82effb0 --- /dev/null +++ b/Sources/Engine/Network/Network.cpp @@ -0,0 +1,2509 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +// pointer to global instance of the only game object in the application +CNetworkLibrary *_pNetwork= NULL; + +extern BOOL _bNeedPretouch; +extern BOOL _bMultiPlayer = FALSE; +extern INDEX _ctEntities = 0; +extern INDEX _ctPredictorEntities = 0; +extern LevelChangePhase _lphCurrent = LCP_NOCHANGE; +extern BOOL _bTempNetwork = FALSE; // set while using temporary second network object +extern BOOL con_bCapture; +extern CTString con_strCapture; + +static CWorld *_pwoCurrentWorld = NULL; + +static FLOAT _bStartDemoRecordingNextTime = FALSE; +static FLOAT _bStopDemoRecordingNextTime = FALSE; +static INDEX dem_iRecordedNumber = 0; + +// network control +extern INDEX ser_bReportSyncOK = FALSE; +extern INDEX ser_bReportSyncBad = TRUE; +extern INDEX ser_bReportSyncLate = FALSE; +extern INDEX ser_bReportSyncEarly = FALSE; +extern INDEX ser_bPauseOnSyncBad = FALSE; +extern INDEX ser_iKickOnSyncBad = 10; +extern INDEX ser_bKickOnSyncLate = 1; +extern INDEX ser_iRememberBehind = 3000; +extern INDEX ser_iExtensiveSyncCheck = 0; +extern INDEX ser_bClientsMayPause = TRUE; +extern FLOAT ser_tmSyncCheckFrequency = 1.0f; +extern INDEX ser_iSyncCheckBuffer = 60; +extern INDEX ser_bEnumeration = TRUE; +extern INDEX ser_bPingGameAgent = TRUE; +extern FLOAT ser_tmKeepAlive = 0.1f; +extern FLOAT ser_tmPingUpdate = 3.0f; +extern INDEX ser_bWaitFirstPlayer = 0; +extern INDEX ser_iMaxAllowedBPS = 8000; +extern CTString ser_strIPMask = ""; +extern CTString ser_strNameMask = ""; +extern INDEX ser_bInverseBanning = FALSE; +extern CTString ser_strMOTD = ""; + +extern INDEX cli_bEmulateDesync = FALSE; +extern INDEX cli_bDumpSync = FALSE; +extern INDEX cli_bDumpSyncEachTick = FALSE; +extern INDEX cli_bAutoAdjustSettings = FALSE; +extern FLOAT cli_tmAutoAdjustThreshold = 2.0f; +extern INDEX cli_bPrediction = FALSE; +extern INDEX cli_iMaxPredictionSteps = 10; +extern INDEX cli_bPredictIfServer = FALSE; +extern INDEX cli_bPredictLocalPlayers = TRUE; +extern INDEX cli_bPredictRemotePlayers = FALSE; +extern FLOAT cli_fPredictEntitiesRange = 20.0f; +extern INDEX cli_bLerpActions = FALSE; +extern INDEX cli_bReportPredicted = FALSE; +extern INDEX cli_iSendBehind = 3; +extern INDEX cli_iPredictionFlushing = 1; + +extern INDEX cli_iBufferActions = 1; +extern INDEX cli_iMaxBPS = 4000; +extern INDEX cli_iMinBPS = 0; + +extern INDEX net_iCompression = 1; +extern INDEX net_bLookupHostNames = FALSE; +extern INDEX net_bReportPackets = FALSE; +extern INDEX net_iMaxSendRetries = 10; +extern FLOAT net_fSendRetryWait = 0.5f; +extern INDEX net_bReportTraffic = FALSE; +extern INDEX net_bReportICMPErrors = FALSE; +extern INDEX net_bReportMiscErrors = FALSE; +extern INDEX net_bLerping = TRUE; +extern INDEX net_iGraphBuffer = 100; +extern INDEX net_iExactTimer = 2; +extern INDEX net_bDumpStreamBlocks = 0; +extern INDEX net_bDumpConnectionInfo = 0; +extern INDEX net_iPort = 25600; +extern CTString net_strLocalHost = ""; +extern CTString net_strLocationCode = ""; +extern CTString net_strConnectPassword = ""; +extern CTString net_strAdminPassword = ""; +extern CTString net_strVIPPassword = ""; +extern CTString net_strObserverPassword = ""; +extern INDEX net_iVIPReserve = 0; +extern INDEX net_iMaxObservers = 16; +extern INDEX net_iMaxClients = 0; +extern FLOAT net_tmConnectionTimeout = 30.0f; +extern FLOAT net_tmProblemsTimeout = 5.0f; +extern FLOAT net_tmDisconnectTimeout = 300.0f; // must be higher for level changing +extern INDEX net_bReportCRC = FALSE; +extern FLOAT net_fDropPackets = 0.0f; +extern FLOAT net_tmLatency = 0.0f; + +extern INDEX ent_bReportSpawnInWall = FALSE; + +extern FLOAT cmd_tmTick = 0.0f; +extern CTString cmd_cmdOnTick = ""; +extern CTString cmd_strChatSender = ""; +extern CTString cmd_strChatMessage = ""; +extern CTString cmd_cmdOnChat = ""; +extern INDEX net_ctChatMessages = 0; // counter for incoming chat messages + +extern CPacketBufferStats _pbsSend; +extern CPacketBufferStats _pbsRecv; + +extern BOOL _bPredictionActive = FALSE; + +class CGatherCRC { +public: + BOOL bOld; + CGatherCRC(); + ~CGatherCRC(); +}; + +CGatherCRC::CGatherCRC() { + bOld = CRCT_bGatherCRCs; +} +CGatherCRC::~CGatherCRC() { + CRCT_bGatherCRCs = bOld; +} + +// precache control +extern INDEX _precache_NONE = PRECACHE_NONE; +extern INDEX _precache_SMART = PRECACHE_SMART; +extern INDEX _precache_ALL = PRECACHE_ALL; +extern INDEX _precache_PARANOIA = PRECACHE_PARANOIA; +extern INDEX gam_iPrecachePolicy = _precache_SMART; +extern INDEX _precache_bNowPrecaching = FALSE; + +extern INDEX dbg_bBreak = FALSE; +extern INDEX gam_bPretouch = FALSE; + +extern FLOAT phy_fCollisionCacheAhead = 5.0f; +extern FLOAT phy_fCollisionCacheAround = 1.5f; +extern FLOAT cli_fPredictionFilter = 0.5f; + +extern INDEX shd_bCacheAll; + + +// input +extern INDEX inp_iKeyboardReadingMethod = 2; // 0=getasynckey, 1=virtkeytrap, 2=scancodetrap +extern INDEX inp_bAllowMouseAcceleration = TRUE; +extern FLOAT inp_fMouseSensitivity = 1.0f; +extern INDEX inp_bMousePrecision = FALSE; +extern FLOAT inp_fMousePrecisionFactor = 4.0f; +extern FLOAT inp_fMousePrecisionThreshold = 10.0f; +extern FLOAT inp_fMousePrecisionTimeout = 0.25f; +extern FLOAT inp_bInvertMouse = FALSE; +extern INDEX inp_bFilterMouse = FALSE; +extern INDEX inp_bAllowPrescan = TRUE; + +extern INDEX inp_i2ndMousePort = 0; // COM no (0=disable) +extern FLOAT inp_f2ndMouseSensitivity = 1.0f; +extern INDEX inp_b2ndMousePrecision = FALSE; +extern FLOAT inp_f2ndMousePrecisionFactor = 4.0f; +extern FLOAT inp_f2ndMousePrecisionThreshold = 10.0f; +extern FLOAT inp_f2ndMousePrecisionTimeout = 0.25f; +extern INDEX inp_bInvert2ndMouse = FALSE; +extern INDEX inp_bFilter2ndMouse = FALSE; + +extern INDEX inp_iMButton4Up; +extern INDEX inp_iMButton4Dn; +extern INDEX inp_iMButton5Up; +extern INDEX inp_iMButton5Dn; +extern INDEX inp_bMsgDebugger; +extern INDEX inp_ctJoysticksAllowed; +extern INDEX inp_bForceJoystickPolling; +extern INDEX inp_bAutoDisableJoysticks; + +extern INDEX wed_bUseGenericTextureReplacement = FALSE; + +extern void RendererInfo(void); +extern void ClearRenderer(void); + + +// cache all shadowmaps now +extern void CacheShadows(void) +{ + // mute all sounds + _pSound->Mute(); + CWorld *pwo = (CWorld*)_pShell->GetINDEX("pwoCurrentWorld"); + if( pwo!=NULL) { + pwo->wo_baBrushes.CacheAllShadowmaps(); + CPrintF( TRANS("All shadows recached")); + if( shd_bCacheAll) CPrintF(".\n"); + else CPrintF( TRANS(", but not for long.\n(precache all shadows function is disabled)\n")); + } + // mark that we need pretouching + _bNeedPretouch = TRUE; +} + +// check if a name or IP matches a mask +extern BOOL MatchesBanMask(const CTString &strString, const CTString &strMask) +{ + CTString strRest = strMask; + CTString strLine; + + while(strRest!="") { + strLine = strRest; + strLine.OnlyFirstLine(); + strRest.RemovePrefix(strLine); + strRest.DeleteChar(0); + + if (strString.Matches(strLine)) { + return TRUE; + } + } + return FALSE; +} + +extern CTString RemoveSubstring(const CTString &strFull, const CTString &strSub); + +static void AddIPMask(void* pArgs) +{ + CTString strIP = *NEXTARGUMENT(CTString*); + ser_strIPMask+= strIP+"\n"; +} +static void RemIPMask(void* pArgs) +{ + CTString strIP = *NEXTARGUMENT(CTString*); + ser_strIPMask = RemoveSubstring(ser_strIPMask, strIP+"\n"); +} +static void AddNameMask(void* pArgs) +{ + CTString strName = *NEXTARGUMENT(CTString*); + ser_strNameMask += strName+"\n"; +} +static void RemNameMask(void* pArgs) +{ + CTString strName = *NEXTARGUMENT(CTString*); + ser_strNameMask = RemoveSubstring(ser_strNameMask, strName+"\n"); +} + +static void StartDemoRecording(void) +{ + _bStartDemoRecordingNextTime = TRUE; +} + + +static void StopDemoRecording(void) +{ + _bStopDemoRecordingNextTime = TRUE; +} + + +static void NetworkInfo(void) +{ + CPrintF("*Network library information:\n"); + CPrintF("Entities existing: %d\n", _ctEntities); + CPrintF("Predictor entities existing: %d\n", _ctPredictorEntities); + CPrintF("Server:\n"); + if (_pNetwork->ga_srvServer.srv_bActive) { + CPrintF(" last processed tick: %g\n", _pNetwork->ga_srvServer.srv_tmLastProcessedTick); + CPrintF(" last processed sequence: %d\n", _pNetwork->ga_srvServer.srv_iLastProcessedSequence); + CPrintF(" players:\n"); + for(INDEX iplb=0; iplb<_pNetwork->ga_srvServer.srv_aplbPlayers.Count(); iplb++) { + CPlayerBuffer &plb = _pNetwork->ga_srvServer.srv_aplbPlayers[iplb]; + if (plb.plb_Active) { + CPrintF(" %2d(%2d):'%s'@client%2d: (%dact)\n", + iplb, plb.plb_Index, plb.plb_pcCharacter.GetNameForPrinting(), + plb.plb_iClient, plb.plb_abReceived.GetCount()); + } + } + CPrintF(" clients:\n"); + for(INDEX iSession=0; iSession<_pNetwork->ga_srvServer.srv_assoSessions.Count(); iSession++) { + CSessionSocket &sso = _pNetwork->ga_srvServer.srv_assoSessions[iSession]; + if (sso.sso_bActive) { + CPrintF(" %2d:'%s'\n", iSession, _cmiComm.Server_GetClientName(iSession)), + CPrintF(" buffer: %dblk=%dk\n", + sso.sso_nsBuffer.GetUsedBlocks(), + sso.sso_nsBuffer.GetUsedMemory()/1024); + CPrintF(" state:"); + if (sso.sso_iDisconnectedState>0) { + CPrintF(" disconnecting"); + } else if (sso.sso_bSendStream) { + CPrintF(" connected"); + } else { + CPrintF(" connecting"); + } + CPrintF("\n"); + } + } + } else { + CPrintF(" not a server\n"); + } + CPrintF("Session state:\n"); + CPrintF(" buffer: (%dblk)%dk\n", + _pNetwork->ga_sesSessionState.ses_nsGameStream.GetUsedBlocks(), + _pNetwork->ga_sesSessionState.ses_nsGameStream.GetUsedMemory()/1024); + CPrintF(" last processed tick: %g\n", _pNetwork->ga_sesSessionState.ses_tmLastProcessedTick); + CPrintF(" last processed sequence: %d\n", _pNetwork->ga_sesSessionState.ses_iLastProcessedSequence); + CPrintF(" level change: %d\n", _pNetwork->ga_sesSessionState.ses_iLevel); + for(INDEX iplt=0; iplt<_pNetwork->ga_sesSessionState.ses_apltPlayers.Count(); iplt++) { + CPlayerTarget &plt = _pNetwork->ga_sesSessionState.ses_apltPlayers[iplt]; + if (plt.plt_bActive) { + ULONG ulID = -1; + if (plt.plt_penPlayerEntity!=NULL) { + ulID = plt.plt_penPlayerEntity->en_ulID; + } + CPrintF(" player %2d (ID:%d): (%dact)\n", iplt, ulID, plt.plt_abPrediction.GetCount()); + } + } + + + if (TIMER_PROFILING) { + CTString strNetProfile; + _pfNetworkProfile.Report(strNetProfile); + CPrintF(strNetProfile); + } +} + +static void ListPlayers(void) +{ + CPrintF("player list:\n"); + if (!_pNetwork->ga_srvServer.srv_bActive) { + CPrintF(" \n"); + return; + } + + CPrintF(" client# name\n"); + CPrintF(" ----------------------\n"); + for(INDEX iplb=0; iplb<_pNetwork->ga_srvServer.srv_aplbPlayers.Count(); iplb++) { + CPlayerBuffer &plb = _pNetwork->ga_srvServer.srv_aplbPlayers[iplb]; + if (plb.plb_Active) { + CPrintF(" %-2d %s\n", plb.plb_iClient, plb.plb_pcCharacter.GetNameForPrinting()); + } + } + CPrintF(" ----------------------\n"); +} + +static void KickClient(INDEX iClient, const CTString &strReason) +{ + if (!_pNetwork->IsServer()) { + CPrintF( TRANS("Only server can kick people!\n")); + return; + } + iClient = Clamp(iClient, INDEX(0), INDEX(NET_MAXGAMECOMPUTERS)); + if (!_pNetwork->ga_srvServer.srv_assoSessions[iClient].IsActive()) { + CPrintF(TRANS("Client not connected!\n")); + return; + } + if (iClient == 0) { + CPrintF(TRANS("Can't kick local client!\n")); + return; + } + CPrintF( TRANS("Kicking %d with explanation '%s'...\n"), iClient, strReason); + _pNetwork->ga_srvServer.SendDisconnectMessage(iClient, "Admin: "+strReason); +} +static void KickClientCfunc(void* pArgs) +{ + INDEX iClient = NEXTARGUMENT(INDEX); + CTString strReason = *NEXTARGUMENT(CTString*); + KickClient(iClient, strReason); +} +static void KickByName(const CTString &strName, const CTString &strReason) +{ + if (!_pNetwork->IsServer()) { + CPrintF( TRANS("Only server can kick people!\n")); + return; + } + for(INDEX iplb=0; iplb<_pNetwork->ga_srvServer.srv_aplbPlayers.Count(); iplb++) { + CPlayerBuffer &plb = _pNetwork->ga_srvServer.srv_aplbPlayers[iplb]; + if (plb.plb_Active && plb.plb_pcCharacter.GetNameForPrinting().Undecorated().Matches(strName)) { + KickClient(plb.plb_iClient, strReason); + } + } +} +static void KickByNameCfunc(void* pArgs) +{ + CTString strName = *NEXTARGUMENT(CTString*); + CTString strReason = *NEXTARGUMENT(CTString*); + KickByName(strName, strReason); +} + +static void Admin(void* pArgs) +{ + CTString strCommand = *NEXTARGUMENT(CTString*); + + CNetworkMessage nm(MSG_ADMIN_COMMAND); + nm<SendToServerReliable(nm); +} + +static void StockInfo(void) +{ + // find memory used by shadowmap (both cached and uploaded) + INDEX ctCachedShadows=0, ctDynamicShadows=0, ctFlatShadows=0; + SLONG slStaticMemory=0, slDynamicMemory=0, slUploadMemory=0; + SLONG slShdBytes=0, slSlackMemory=0, slFlatMemory=0; + INDEX ct256=0, ct128=0, ct64=0, ct32=0, ct16=0; + SLONG sl256Memory=0, sl128Memory=0, sl64Memory=0, sl32Memory=0, sl16Memory=0; + + if( _pGfx!=NULL) + { + FLOAT fSlackRatio; + FOREACHINLIST( CShadowMap, sm_lnInGfx, _pGfx->gl_lhCachedShadows, itsm) + { // get polygon size in pixels (used portion of shadowmap) + SLONG slStaticSize, slDynamicSize, slUploadSize; + BOOL bIsFlat = itsm->GetUsedMemory( slStaticSize, slDynamicSize, slUploadSize, fSlackRatio); + SLONG slTotalSize = slDynamicSize+slUploadSize; + if( bIsFlat) { + slStaticMemory += 4; + slTotalSize += 4; + slFlatMemory += slStaticSize; + ctFlatShadows++; + } else { + slStaticMemory += slStaticSize; + slTotalSize += slStaticSize; + if( slTotalSize>0) ctCachedShadows++; + } + if( slDynamicSize>0) { + slDynamicMemory += slDynamicSize; + ctDynamicShadows++; + } + slUploadMemory += slUploadSize; + slShdBytes += slTotalSize + sizeof(CShadowMap); + slSlackMemory += slTotalSize*fSlackRatio; + + if( !bIsFlat) { // by size ... + if( slStaticSize>128*1024) { ct256++; sl256Memory+=slTotalSize; } + else if( slStaticSize> 64*1024) { ct128++; sl128Memory+=slTotalSize; } + else if( slStaticSize> 32*1024) { ct64++; sl64Memory +=slTotalSize; } + else if( slStaticSize> 16*1024) { ct32++; sl32Memory +=slTotalSize; } + else if( slStaticSize> 0) { ct16++; sl16Memory +=slTotalSize; } + } + } + // report shadowmap memory usage (if any) + if( slShdBytes>0) { + CPrintF( "\nCached shadowmaps:\n"); + CPrintF( " Total: %d in %d KB with %d%% (%d KB) of slack space\n", ctCachedShadows, slShdBytes/1024, slSlackMemory*100/slShdBytes, slSlackMemory/1024); + CPrintF( " Static: %d KB\n", slStaticMemory/1024); + CPrintF( " Upload: %d KB\n", slUploadMemory/1024); + CPrintF( " Dynamic: %d in %d KB\n", ctDynamicShadows, slDynamicMemory/1024); + if( ctCachedShadows<1) ctCachedShadows=1; // for percentage calc + CPrintF( " Flats: %d (%d%%) with %d KB saved\n", ctFlatShadows, ctFlatShadows*100/ctCachedShadows, slFlatMemory/1024); + CPrintF("of size:\n"); + CPrintF( " >128K: %4d in %d KB\n", ct256, sl256Memory/1024); + CPrintF( " 128-64K: %4d in %d KB\n", ct128, sl128Memory/1024); + CPrintF( " 64-32K: %4d in %d KB\n", ct64, sl64Memory /1024); + CPrintF( " 32-16K: %4d in %d KB\n", ct32, sl32Memory /1024); + CPrintF( " <=16K: %4d in %d KB\n", ct16, sl16Memory /1024); + } + } + + // report world stats + INDEX ctEntities=0, ctShadowLayers=0, ctPolys=0, ctPlanes=0, ctEdges=0, ctVertices=0, ctSectors=0; + SLONG slEntBytes=0, slLyrBytes=0, slPlyBytes=0, slPlnBytes=0, slEdgBytes=0, slVtxBytes=0, slSecBytes=0; + SLONG slCgrBytes=0; + CWorld *pwo = (CWorld*)_pShell->GetINDEX("pwoCurrentWorld"); + + if( pwo!=NULL) + { + // report count of and memory used by entities + FOREACHINDYNAMICCONTAINER( pwo->wo_cenEntities, CEntity, iten) { + ctEntities++; + slEntBytes += iten->GetUsedMemory(); + } + + // report shadow layers and world geometry memory usage + FOREACHINDYNAMICARRAY( pwo->wo_baBrushes.ba_abrBrushes, CBrush3D, itbr) // for all brush entities in the world + { + // skip brush without entity + if( itbr->br_penEntity==NULL) continue; + + // for each mip + FOREACHINLIST( CBrushMip, bm_lnInBrush, itbr->br_lhBrushMips, itbm) + { + // for each sector in the brush mip + FOREACHINDYNAMICARRAY( itbm->bm_abscSectors, CBrushSector, itbsc) + { + // add sector class memory usage to polygons memory + ctSectors++; + slSecBytes += itbsc->GetUsedMemory(); + + // add each vertex and working vertex in sector + ctVertices += itbsc->bsc_abvxVertices.Count(); + FOREACHINSTATICARRAY( itbsc->bsc_abvxVertices, CBrushVertex, itbvx) slVtxBytes += itbvx->GetUsedMemory(); + FOREACHINSTATICARRAY( itbsc->bsc_awvxVertices, CWorkingVertex, itwvx) slVtxBytes += 32; // aligned to 32 bytes! + + // add each plane and working plane in sector + ctPlanes += itbsc->bsc_abplPlanes.Count(); + FOREACHINSTATICARRAY( itbsc->bsc_abplPlanes, CBrushPlane, itbpl) slPlnBytes += itbpl->GetUsedMemory(); + FOREACHINSTATICARRAY( itbsc->bsc_awplPlanes, CWorkingPlane, itwpl) slPlnBytes += sizeof(CWorkingPlane); + + // add each edge and working edge in sector + ctEdges += itbsc->bsc_abedEdges.Count(); + FOREACHINSTATICARRAY( itbsc->bsc_abedEdges, CBrushEdge, itbed) slEdgBytes += itbed->GetUsedMemory(); + FOREACHINSTATICARRAY( itbsc->bsc_awedEdges, CWorkingEdge, itwed) slEdgBytes += sizeof(CWorkingEdge); + + // for each polygon in sector + ctPolys += itbsc->bsc_abpoPolygons.Count(); + FOREACHINSTATICARRAY( itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + CBrushPolygon &bpo = *itbpo; + slPlyBytes += bpo.GetUsedMemory(); + // count in the shadow layers (if any) + if( bpo.bpo_smShadowMap.bsm_lhLayers.IsEmpty()) continue; // skip polygon without shadowmap + ctShadowLayers += bpo.bpo_smShadowMap.GetShadowLayersCount(); + slLyrBytes += bpo.bpo_smShadowMap.GetUsedMemory(); + } + } + } + } // add in memory used by collision grid + extern SLONG GetCollisionGridMemory( CCollisionGrid *pcg); + slCgrBytes += GetCollisionGridMemory( pwo->wo_pcgCollisionGrid); + } + + // stock info + const DOUBLE dToMB = 1.0/1024.0/1024.0; + const FLOAT fTexBytes = dToMB * _pTextureStock->CalculateUsedMemory(); + const FLOAT fMdlBytes = dToMB * _pModelStock->CalculateUsedMemory(); + const FLOAT fSndBytes = dToMB * _pSoundStock->CalculateUsedMemory(); + const FLOAT fMshBytes = dToMB * _pMeshStock->CalculateUsedMemory(); + const FLOAT fAstBytes = dToMB * _pAnimSetStock->CalculateUsedMemory(); + const FLOAT fShaBytes = dToMB * _pShaderStock->CalculateUsedMemory(); + const FLOAT fSkaBytes = dToMB * _pSkeletonStock->CalculateUsedMemory(); + + CPrintF("\nStock information:\n"); + CPrintF(" Textures: %5d (%5.2f MB)\n", _pTextureStock->GetTotalCount(), fTexBytes); + CPrintF(" ShadowMaps: %5d (%5.2f MB)\n", ctCachedShadows, slShdBytes*dToMB); + CPrintF(" Entities: %5d (%5.2f MB)\n", ctEntities, slEntBytes*dToMB); + CPrintF(" Sounds: %5d (%5.2f MB)\n", _pSoundStock->GetTotalCount(), fSndBytes); + CPrintF("\n"); + CPrintF(" Sectors: %5d (%5.2f MB)\n", ctSectors, slSecBytes*dToMB); + CPrintF(" Planes: %5d (%5.2f MB)\n", ctPlanes, slPlnBytes*dToMB); + CPrintF(" Edges: %5d (%5.2f MB)\n", ctEdges, slEdgBytes*dToMB); + CPrintF(" Polygons: %5d (%5.2f MB)\n", ctPolys, slPlyBytes*dToMB); + CPrintF(" Vertices: %5d (%5.2f MB)\n", ctVertices, slVtxBytes*dToMB); + CPrintF(" ShadowLayers: %5d (%5.2f MB)\n", ctShadowLayers, slLyrBytes*dToMB); + CPrintF("\n"); + CPrintF(" Models: %5d (%5.2f MB)\n", _pModelStock->GetTotalCount(), fMdlBytes); + CPrintF(" Meshes: %5d (%5.2f MB)\n", _pMeshStock->GetTotalCount(), fMshBytes); + CPrintF(" Skeletons: %5d (%5.2f MB)\n", _pSkeletonStock->GetTotalCount(), fSkaBytes); + CPrintF(" AnimSets: %5d (%5.2f MB)\n", _pAnimSetStock->GetTotalCount(), fAstBytes); + CPrintF(" Shaders: %5d (%5.2f MB)\n", _pShaderStock->GetTotalCount(), fShaBytes); + CPrintF("\n"); + CPrintF("CollisionGrid: %.2f MB\n", slCgrBytes*dToMB); + CPrintF("--------------\n"); + CPrintF(" Total: %.2f MB\n", fTexBytes+fSndBytes+fMdlBytes+fMshBytes+fSkaBytes+fAstBytes+fShaBytes + + (slShdBytes+slEntBytes+slSecBytes+slPlnBytes+slEdgBytes+slPlyBytes+slVtxBytes+slLyrBytes+slCgrBytes)*dToMB); + CPrintF("\n"); +} + + +static void StockDump(void) +{ + try { + CTFileStream strm; + CTFileName fnm = CTString("Temp\\StockDump.txt"); + strm.Create_t(fnm); + strm.PutLine_t("Animations:"); + _pAnimStock->DumpMemoryUsage_t(strm); + strm.PutLine_t("Textures:"); + _pTextureStock->DumpMemoryUsage_t(strm); + strm.PutLine_t("Models:"); + _pModelStock->DumpMemoryUsage_t(strm); + strm.PutLine_t("Sounds:"); + _pSoundStock->DumpMemoryUsage_t(strm); + strm.PutLine_t("Classes:"); + _pEntityClassStock->DumpMemoryUsage_t(strm); + CPrintF("Dumped to '%s'\n", CTString(fnm)); + } catch (char *strError) { + CPrintF("Error: %s\n", strError); + } +} + + +// free all unused stocks +extern void FreeUnusedStock(void) +{ + // free all unused stocks + _pEntityClassStock->FreeUnused(); + _pModelStock->FreeUnused(); + _pSoundStock->FreeUnused(); + _pTextureStock->FreeUnused(); + _pAnimStock->FreeUnused(); +} + + +/* + * This is called every TickQuantum seconds. + */ +void CNetworkTimerHandler::HandleTimer(void) +{ + if (this==NULL || _bTempNetwork) { + return; // this can happen during NET_MakeDefaultState_t()! + } + // enable stream handling during timer + CTSTREAM_BEGIN { + // do the timer loop + _pNetwork->TimerLoop(); + } CTSTREAM_END; +} + +/* + * Default constructor. + */ +CNetworkLibrary::CNetworkLibrary(void) : + ga_IsServer(FALSE), // is not server + ga_bDemoRec(FALSE), // not recording demo + ga_bDemoPlay(FALSE), // not playing demo + ga_bDemoPlayFinished(FALSE), // demo not finished + ga_srvServer(*new CServer), + ga_sesSessionState(*new CSessionState) +{ + ga_aplsPlayers.New(NET_MAXLOCALPLAYERS); + + // default demo syncronization is real-time, with 1:1 playback speed + ga_fDemoSyncRate = DEMOSYNC_REALTIME; + ga_fDemoRealTimeFactor = 1.0f; + ga_fGameRealTimeFactor = 1.0f; + ga_pubDefaultState = NULL; + ga_slDefaultStateSize = 0; + memset(ga_aubDefaultProperties, 0, sizeof(ga_aubDefaultProperties)); + ga_pubCRCList = NULL; + ga_slCRCList = 0; + ga_ulDemoMinorVersion = _SE_BUILD_MINOR; + + ga_csNetwork.cs_iIndex = 2000; + ga_ctTimersPending = -1; + + ga_fEnumerationProgress = 0; + ga_bEnumerationChange = FALSE; +} + +/* + * Destructor. + */ +CNetworkLibrary::~CNetworkLibrary(void) +{ + // clear the global world + ga_World.DeletePredictors(); + ga_World.Clear(); + + // free renderer info to free pointers to entities etc. + if (!_bTempNetwork) { + extern void ClearRenderer(void); + ClearRenderer(); + } + + delete &ga_sesSessionState; + delete &ga_srvServer; +} + + +/* + * Initialize game management. + */ +void CNetworkLibrary::Init(const CTString &strGameID) +{ + // remember the game ID + CMessageDispatcher::Init(strGameID); + + // add shell symbols + _pShell->DeclareSymbol("user INDEX dbg_bBreak;", &dbg_bBreak); + _pShell->DeclareSymbol("persistent user INDEX gam_bPretouch;", &gam_bPretouch); + + _pShell->DeclareSymbol("user INDEX dem_iRecordedNumber;", &dem_iRecordedNumber); + _pShell->DeclareSymbol("user void StartDemoRecording(void);", &StartDemoRecording); + _pShell->DeclareSymbol("user void StopDemoRecording(void);", &StopDemoRecording); + _pShell->DeclareSymbol("user void NetworkInfo(void);", &NetworkInfo); + _pShell->DeclareSymbol("user void StockInfo(void);", &StockInfo); + _pShell->DeclareSymbol("user void StockDump(void);", &StockDump); + _pShell->DeclareSymbol("user void RendererInfo(void);", &RendererInfo); + _pShell->DeclareSymbol("user void ClearRenderer(void);", &ClearRenderer); + _pShell->DeclareSymbol("user void CacheShadows(void);", &CacheShadows); + _pShell->DeclareSymbol("user void KickClient(INDEX, CTString);", &KickClientCfunc); + _pShell->DeclareSymbol("user void KickByName(CTString, CTString);", &KickByNameCfunc); + _pShell->DeclareSymbol("user void ListPlayers(void);", &ListPlayers); + _pShell->DeclareSymbol("user void Admin(CTString);", &Admin); + + _pShell->DeclareSymbol("user void AddIPMask(CTString);", &AddIPMask); + _pShell->DeclareSymbol("user void RemIPMask(CTString);", &RemIPMask); + _pShell->DeclareSymbol("user void AddNameMask(CTString);", &AddNameMask); + _pShell->DeclareSymbol("user void RemNameMask(CTString);", &RemNameMask); + + + _pShell->DeclareSymbol("user FLOAT dem_tmTimer;", &ga_fDemoTimer); + _pShell->DeclareSymbol("user FLOAT dem_fSyncRate;", &ga_fDemoSyncRate); + _pShell->DeclareSymbol("user FLOAT dem_fRealTimeFactor;", &ga_fDemoRealTimeFactor); + _pShell->DeclareSymbol("user FLOAT gam_fRealTimeFactor;", &ga_fGameRealTimeFactor); + + _pShell->DeclareSymbol("user const FLOAT net_tmLatency;", &net_tmLatency); + _pShell->DeclareSymbol("user const FLOAT cmd_tmTick;", &cmd_tmTick); + _pShell->DeclareSymbol("persistent user CTString cmd_cmdOnTick;", &cmd_cmdOnTick); + _pShell->DeclareSymbol("user CTString cmd_strChatSender ;", &cmd_strChatSender ); + _pShell->DeclareSymbol("user CTString cmd_strChatMessage;", &cmd_strChatMessage); + _pShell->DeclareSymbol("persistent user CTString cmd_cmdOnChat;", &cmd_cmdOnChat); + + _pShell->DeclareSymbol("user INDEX net_ctChatMessages;", &net_ctChatMessages); + + _pShell->DeclareSymbol("persistent user INDEX ent_bReportSpawnInWall;", &ent_bReportSpawnInWall); + + _pShell->DeclareSymbol("user INDEX ser_bReportSyncOK;", &ser_bReportSyncOK); + _pShell->DeclareSymbol("user INDEX ser_bReportSyncBad;", &ser_bReportSyncBad); + _pShell->DeclareSymbol("user INDEX ser_bReportSyncLate;", &ser_bReportSyncLate); + _pShell->DeclareSymbol("user INDEX ser_bReportSyncEarly;", &ser_bReportSyncEarly); + _pShell->DeclareSymbol("user INDEX ser_bPauseOnSyncBad;", &ser_bPauseOnSyncBad); + _pShell->DeclareSymbol("user INDEX ser_iKickOnSyncBad;", &ser_iKickOnSyncBad); + _pShell->DeclareSymbol("user INDEX ser_bKickOnSyncLate;", &ser_bKickOnSyncLate); + _pShell->DeclareSymbol("persistent user FLOAT ser_tmSyncCheckFrequency;", &ser_tmSyncCheckFrequency); + _pShell->DeclareSymbol("persistent user INDEX ser_iSyncCheckBuffer;", &ser_iSyncCheckBuffer); + _pShell->DeclareSymbol("persistent user INDEX cli_bLerpActions;", &cli_bLerpActions); + _pShell->DeclareSymbol("persistent user INDEX cli_bReportPredicted;", &cli_bReportPredicted); + _pShell->DeclareSymbol("persistent user INDEX net_iExactTimer;", &net_iExactTimer); + _pShell->DeclareSymbol("user INDEX net_bDumpStreamBlocks;", &net_bDumpStreamBlocks); + _pShell->DeclareSymbol("user INDEX net_bDumpConnectionInfo;", &net_bDumpConnectionInfo); + _pShell->DeclareSymbol("user INDEX net_iPort;", &net_iPort); + _pShell->DeclareSymbol("persistent user CTString net_strLocalHost;", &net_strLocalHost); + _pShell->DeclareSymbol("persistent user CTString net_strLocationCode;", &net_strLocationCode); + _pShell->DeclareSymbol("user CTString net_strVIPPassword;", &net_strVIPPassword); + _pShell->DeclareSymbol("user CTString net_strObserverPassword;", &net_strObserverPassword); + _pShell->DeclareSymbol("user INDEX net_iVIPReserve;", &net_iVIPReserve); + _pShell->DeclareSymbol("user INDEX net_iMaxObservers;", &net_iMaxObservers); + _pShell->DeclareSymbol("user INDEX net_iMaxClients;", &net_iMaxClients); + _pShell->DeclareSymbol("user CTString net_strConnectPassword;", &net_strConnectPassword); + _pShell->DeclareSymbol("user CTString net_strAdminPassword;", &net_strAdminPassword); + _pShell->DeclareSymbol("user FLOAT net_tmConnectionTimeout;", &net_tmConnectionTimeout); + _pShell->DeclareSymbol("user FLOAT net_tmProblemsTimeout;", &net_tmProblemsTimeout); + _pShell->DeclareSymbol("user FLOAT net_tmDisconnectTimeout;", &net_tmDisconnectTimeout); + _pShell->DeclareSymbol("user INDEX net_bReportCRC;", &net_bReportCRC); + _pShell->DeclareSymbol("user INDEX ser_iRememberBehind;", &ser_iRememberBehind); + _pShell->DeclareSymbol("user INDEX cli_bEmulateDesync;", &cli_bEmulateDesync); + _pShell->DeclareSymbol("user INDEX cli_bDumpSync;", &cli_bDumpSync); + _pShell->DeclareSymbol("user INDEX cli_bDumpSyncEachTick;",&cli_bDumpSyncEachTick); + _pShell->DeclareSymbol("persistent user INDEX ser_iExtensiveSyncCheck;", &ser_iExtensiveSyncCheck); + _pShell->DeclareSymbol("persistent user INDEX net_bLookupHostNames;", &net_bLookupHostNames); + _pShell->DeclareSymbol("persistent user INDEX net_iCompression ;", &net_iCompression); + _pShell->DeclareSymbol("persistent user INDEX net_bReportPackets;", &net_bReportPackets); + _pShell->DeclareSymbol("persistent user INDEX net_iMaxSendRetries;", &net_iMaxSendRetries); + _pShell->DeclareSymbol("persistent user FLOAT net_fSendRetryWait;", &net_fSendRetryWait); + _pShell->DeclareSymbol("persistent user INDEX net_bReportTraffic;", &net_bReportTraffic); + _pShell->DeclareSymbol("persistent user INDEX net_bReportICMPErrors;", &net_bReportICMPErrors); + _pShell->DeclareSymbol("persistent user INDEX net_bReportMiscErrors;", &net_bReportMiscErrors); + _pShell->DeclareSymbol("persistent user INDEX net_bLerping;", &net_bLerping); + _pShell->DeclareSymbol("persistent user INDEX ser_bClientsMayPause;", &ser_bClientsMayPause); + _pShell->DeclareSymbol("persistent user INDEX ser_bEnumeration;", &ser_bEnumeration); + _pShell->DeclareSymbol("persistent user INDEX ser_bPingGameAgent;", &ser_bPingGameAgent); + _pShell->DeclareSymbol("persistent user FLOAT ser_tmKeepAlive;", &ser_tmKeepAlive); + _pShell->DeclareSymbol("persistent user FLOAT ser_tmPingUpdate;", &ser_tmPingUpdate); + _pShell->DeclareSymbol("persistent user INDEX ser_bWaitFirstPlayer;", &ser_bWaitFirstPlayer); + _pShell->DeclareSymbol("persistent user INDEX ser_iMaxAllowedBPS;", &ser_iMaxAllowedBPS); + _pShell->DeclareSymbol("persistent user INDEX ser_iMaxAllowedBPS;", &ser_iMaxAllowedBPS); + _pShell->DeclareSymbol("persistent user CTString ser_strIPMask;", &ser_strIPMask); + _pShell->DeclareSymbol("persistent user CTString ser_strNameMask;", &ser_strNameMask); + _pShell->DeclareSymbol("persistent user INDEX ser_bInverseBanning;", &ser_bInverseBanning); + _pShell->DeclareSymbol("persistent user CTString ser_strMOTD;", &ser_strMOTD); + + _pShell->DeclareSymbol("persistent user INDEX cli_bAutoAdjustSettings;", &cli_bAutoAdjustSettings); + _pShell->DeclareSymbol("persistent user FLOAT cli_tmAutoAdjustThreshold;", &cli_tmAutoAdjustThreshold); + _pShell->DeclareSymbol("persistent user INDEX cli_bPrediction;", &cli_bPrediction); + _pShell->DeclareSymbol("persistent user INDEX cli_iMaxPredictionSteps;", &cli_iMaxPredictionSteps); + _pShell->DeclareSymbol("persistent user INDEX cli_bPredictIfServer;", &cli_bPredictIfServer); + _pShell->DeclareSymbol("persistent user INDEX cli_bPredictLocalPlayers;", &cli_bPredictLocalPlayers); + _pShell->DeclareSymbol("persistent user INDEX cli_bPredictRemotePlayers;", &cli_bPredictRemotePlayers); + _pShell->DeclareSymbol("persistent user FLOAT cli_fPredictEntitiesRange;", &cli_fPredictEntitiesRange); + _pShell->DeclareSymbol("persistent user FLOAT cli_fPredictionFilter;", &cli_fPredictionFilter); + _pShell->DeclareSymbol("persistent user INDEX cli_iSendBehind;", &cli_iSendBehind); + _pShell->DeclareSymbol("persistent user INDEX cli_iPredictionFlushing;", &cli_iPredictionFlushing); + + _pShell->DeclareSymbol("persistent user INDEX cli_iBufferActions;", &cli_iBufferActions); + _pShell->DeclareSymbol("persistent user INDEX cli_iMaxBPS;", &cli_iMaxBPS); + _pShell->DeclareSymbol("persistent user INDEX cli_iMinBPS;", &cli_iMinBPS); + + _pShell->DeclareSymbol("user FLOAT net_fLimitLatencySend;", &_pbsSend.pbs_fLatencyLimit); + _pShell->DeclareSymbol("user FLOAT net_fLimitLatencyRecv;", &_pbsRecv.pbs_fLatencyLimit); + _pShell->DeclareSymbol("user FLOAT net_fLatencyVariationSend;", &_pbsSend.pbs_fLatencyVariation); + _pShell->DeclareSymbol("user FLOAT net_fLatencyVariationRecv;", &_pbsRecv.pbs_fLatencyVariation); + _pShell->DeclareSymbol("user FLOAT net_fLimitBandwidthSend;", &_pbsSend.pbs_fBandwidthLimit); + _pShell->DeclareSymbol("user FLOAT net_fLimitBandwidthRecv;", &_pbsRecv.pbs_fBandwidthLimit); + _pShell->DeclareSymbol("user FLOAT net_fDropPackets;", &net_fDropPackets); + + _pShell->DeclareSymbol("persistent user INDEX net_iGraphBuffer;", &net_iGraphBuffer); + + _pShell->DeclareSymbol("user const INDEX precache_NONE;", &_precache_NONE); + _pShell->DeclareSymbol("user const INDEX precache_SMART;", &_precache_SMART); + _pShell->DeclareSymbol("user const INDEX precache_ALL;", &_precache_ALL); + _pShell->DeclareSymbol("user const INDEX precache_PARANOIA;", &_precache_PARANOIA); + _pShell->DeclareSymbol("persistent user INDEX gam_iPrecachePolicy;", &gam_iPrecachePolicy); + + _pShell->DeclareSymbol("user FLOAT phy_fCollisionCacheAhead;", &phy_fCollisionCacheAhead); + _pShell->DeclareSymbol("user FLOAT phy_fCollisionCacheAround;", &phy_fCollisionCacheAround); + + _pShell->DeclareSymbol("persistent user INDEX inp_iKeyboardReadingMethod;", &inp_iKeyboardReadingMethod); + _pShell->DeclareSymbol("persistent user INDEX inp_bAllowMouseAcceleration;", &inp_bAllowMouseAcceleration); + _pShell->DeclareSymbol("persistent user FLOAT inp_fMouseSensitivity;", &inp_fMouseSensitivity); + _pShell->DeclareSymbol("persistent user INDEX inp_bMousePrecision;", &inp_bMousePrecision); + _pShell->DeclareSymbol("persistent user FLOAT inp_fMousePrecisionFactor;", &inp_fMousePrecisionFactor); + _pShell->DeclareSymbol("persistent user FLOAT inp_fMousePrecisionThreshold;", &inp_fMousePrecisionThreshold); + _pShell->DeclareSymbol("persistent user FLOAT inp_fMousePrecisionTimeout;", &inp_fMousePrecisionTimeout); + _pShell->DeclareSymbol("persistent user INDEX inp_bInvertMouse;", &inp_bInvertMouse); + _pShell->DeclareSymbol("persistent user INDEX inp_bFilterMouse;", &inp_bFilterMouse); + _pShell->DeclareSymbol("persistent user INDEX inp_bAllowPrescan;", &inp_bAllowPrescan); + + _pShell->DeclareSymbol("persistent user INDEX inp_i2ndMousePort;", &inp_i2ndMousePort); + _pShell->DeclareSymbol("persistent user INDEX inp_bInvert2ndMouse;", &inp_bInvert2ndMouse); + _pShell->DeclareSymbol("persistent user INDEX inp_bFilter2ndMouse;", &inp_bFilter2ndMouse); + _pShell->DeclareSymbol("persistent user FLOAT inp_f2ndMouseSensitivity;", &inp_f2ndMouseSensitivity); + _pShell->DeclareSymbol("persistent user INDEX inp_b2ndMousePrecision;", &inp_b2ndMousePrecision); + _pShell->DeclareSymbol("persistent user FLOAT inp_f2ndMousePrecisionFactor;", &inp_f2ndMousePrecisionFactor); + _pShell->DeclareSymbol("persistent user FLOAT inp_f2ndMousePrecisionThreshold;", &inp_f2ndMousePrecisionThreshold); + _pShell->DeclareSymbol("persistent user FLOAT inp_f2ndMousePrecisionTimeout;", &inp_f2ndMousePrecisionTimeout); + + _pShell->DeclareSymbol("persistent user INDEX inp_bMsgDebugger;", &inp_bMsgDebugger); + _pShell->DeclareSymbol("persistent user INDEX inp_iMButton4Up;", &inp_iMButton4Up); + _pShell->DeclareSymbol("persistent user INDEX inp_iMButton4Dn;", &inp_iMButton4Dn); + _pShell->DeclareSymbol("persistent user INDEX inp_iMButton5Up;", &inp_iMButton5Up); + _pShell->DeclareSymbol("persistent user INDEX inp_iMButton5Dn;", &inp_iMButton5Dn); + _pShell->DeclareSymbol("persistent user INDEX inp_ctJoysticksAllowed;", &inp_ctJoysticksAllowed); + _pShell->DeclareSymbol("persistent user INDEX inp_bForceJoystickPolling;", &inp_bForceJoystickPolling); + _pShell->DeclareSymbol("persistent user INDEX inp_bAutoDisableJoysticks;", &inp_bAutoDisableJoysticks); + + _pShell->DeclareSymbol("persistent user INDEX wed_bUseGenericTextureReplacement;", &wed_bUseGenericTextureReplacement); + + _pShell->DeclareSymbol("user CTString ga_strServer;", &ga_strServer); + + _pShell->DeclareSymbol("INDEX pwoCurrentWorld;", &_pwoCurrentWorld); +} + +/* + * Add the timer handler. + */ +void CNetworkLibrary::AddTimerHandler(void) +{ + if (this==NULL || _bTempNetwork) { + return; // this can happen during NET_MakeDefaultState_t()! + } + _pTimer->AddHandler(&ga_thTimerHandler); +} +/* + * Remove the timer handler. + */ +void CNetworkLibrary::RemoveTimerHandler(void) +{ + if (this==NULL || _bTempNetwork) { + return; // this can happen during NET_MakeDefaultState_t()! + } + _pTimer->RemHandler(&ga_thTimerHandler); +} + +/* +// set settings to prediction-off +void AdjustPredictionOff(void) +{ + if (!cli_bAutoAdjustSettings) { + return; + } + if (cli_bPrediction) { + CPrintF("AutoAdjustment: prediction off, buffer 1\n"); + } + cli_bPrediction = 0; + cli_iBufferActions = 1; +} +// set settings to prediction-on +void AdjustPredictionOn(void) +{ + if (!cli_bAutoAdjustSettings) { + return; + } + if (!cli_bPrediction) { + CPrintF("AutoAdjustment: prediction on, buffer 3\n"); + } + cli_bPrediction = 1; + cli_iBufferActions = 3; +} + +// automatically adjust network settings +void CNetworkLibrary::AutoAdjustSettings(void) +{ + // if server and not debugging prediction + if (IsServer() && !cli_bPredictIfServer) { + // just turn it all off + AdjustPredictionOff(); + return; + } + + static TIME _tmLastTimeNoPredictionSteps = -1; + // get network lag in terms of ticks + INDEX ctLagTicks = ga_sesSessionState.GetPredictionStepsCount()-(cli_iBufferActions-1); + + // if no significant lag + if (ctLagTicks<=1) { + // set settings to prediction-off + AdjustPredictionOff(); + _tmLastTimeNoPredictionSteps = _pTimer->CurrentTick(); + // if there is lag now for some time + } else if (_pTimer->CurrentTick()-_tmLastTimeNoPredictionSteps>=cli_tmAutoAdjustThreshold) { + // set settings to prediction-on + AdjustPredictionOn(); + } +} +*/ + +/* + * Start a peer-to-peer game session. + * + * remember to keep this routine up to date with CNetworkLibrary::Read() + */ +void CNetworkLibrary::StartPeerToPeer_t(const CTString &strSessionName, + const CTFileName &fnmWorld, ULONG ulSpawnFlags, + INDEX ctMaxPlayers, BOOL bWaitAllPlayers, + void *pvSessionProperties) // throw char * +{ + // mute all sounds + _pSound->Mute(); + + // go on + CPrintF( TRANS("Starting session: '%s'\n"), strSessionName); + CPrintF( TRANS(" level: '%s'\n"), (const char*) fnmWorld); + CPrintF( TRANS(" spawnflags: %08x\n"), ulSpawnFlags); + CPrintF( TRANS(" max players: %d\n"), ctMaxPlayers); + CPrintF( TRANS(" waiting: %d\n"), bWaitAllPlayers); + + CGatherCRC gc; + + // if starting in network + if (_cmiComm.IsNetworkEnabled()) { + CPrintF( TRANS(" network is on\n")); + // start gathering CRCs + InitCRCGather(); + + // make default state data for creating deltas + MakeDefaultState(fnmWorld, ulSpawnFlags, pvSessionProperties); + } else { + CPrintF( TRANS(" network is off\n")); + } + + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + ga_ctTimersPending = -1; // disable timer pending + + ga_strSessionName = strSessionName; + ga_bLocalPause = FALSE; + ga_sesSessionState.ses_iLevel+=1; + ga_sesSessionState.ses_ulSpawnFlags = ulSpawnFlags; + ga_sesSessionState.ses_tmSyncCheckFrequency = ser_tmSyncCheckFrequency; + ga_sesSessionState.ses_iExtensiveSyncCheck = ser_iExtensiveSyncCheck; + + memcpy(ga_aubProperties, pvSessionProperties, NET_MAXSESSIONPROPERTIES); + + // remember the world filename + ga_fnmWorld = fnmWorld; + ga_fnmNextLevel = CTString(""); + try { + // load the world + _pTimer->SetCurrentTick(0.0f); // must have timer at 0 while loading + ga_World.Load_t(fnmWorld); + // delete all entities that don't fit given spawn flags + ga_World.FilterEntitiesBySpawnFlags(ga_sesSessionState.ses_ulSpawnFlags); + } catch(char *) { + ga_fnmWorld = CTString(""); + _cmiComm.Server_Close(); + _cmiComm.Client_Close(); + throw; + } + // remember the world pointer + _pShell->SetINDEX("pwoCurrentWorld", (INDEX)&ga_World); + + SetProgressDescription(TRANS("starting server")); + CallProgressHook_t(0.0f); + // initialize server + try { + ga_srvServer.Start_t(); + } catch (char *) { + ga_World.DeletePredictors(); + ga_World.Clear(); + throw; + } + ga_IsServer = TRUE; + ga_ulDemoMinorVersion = _SE_BUILD_MINOR; + CallProgressHook_t(1.0f); + + // start the timer loop + AddTimerHandler(); + + SetProgressDescription(TRANS("starting session")); + CallProgressHook_t(0.0f); + // initialize session state + try { + ga_sesSessionState.Start_t(-1); + } catch (char *strError) { + (void)strError; + RemoveTimerHandler(); + ga_srvServer.Stop(); + ga_World.DeletePredictors(); + ga_World.Clear(); + throw; + } + CallProgressHook_t(1.0f); + + // remember maximum number of players + ga_sesSessionState.ses_ctMaxPlayers = ctMaxPlayers; + ga_sesSessionState.ses_bWaitAllPlayers = bWaitAllPlayers; + + // time speed is normal by default + ga_sesSessionState.ses_fRealTimeFactor = 1.0f; + + // eventually cache all shadowmaps in world (memory eater!) + if( shd_bCacheAll) ga_World.wo_baBrushes.CacheAllShadowmaps(); + // flush stale caches + FreeUnusedStock(); + // mark that pretouching is required + _bNeedPretouch = TRUE; + + // start timer sync anew + ga_ctTimersPending = 0; + FinishCRCGather(); + CPrintF( TRANS(" started.\n")); +} + +/* + * Save the game. + */ +void CNetworkLibrary::Save_t(const CTFileName &fnmGame) // throw char * +{ + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + + // must be server + if (!ga_IsServer) { + throw TRANS("Cannot save game - not a server!\n"); + } + + // create the file + CTFileStream strmFile; + strmFile.Create_t(fnmGame); + + // write game to stream + strmFile.WriteID_t("GAME"); + ga_sesSessionState.Write_t(&strmFile); + strmFile.WriteID_t("GEND"); // game end +} + +/* + * Load the game. + * + * remember to keep this routine up to date with CNetworkLibrary::StartPeerToPeer() + */ +void CNetworkLibrary::Load_t(const CTFileName &fnmGame) // throw char * +{ + // mute all sounds + _pSound->Mute(); + + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + ga_ctTimersPending = -1; // disable timer pending + CGatherCRC gc; + + ga_bLocalPause = FALSE; + + // open the file + CTFileStream strmFile; + strmFile.Open_t(fnmGame); + + // if starting in network + if (_cmiComm.IsNetworkEnabled()) { + // start gathering CRCs + InitCRCGather(); + } + + // initialize server + ga_srvServer.Start_t(); + ga_IsServer = TRUE; + ga_ulDemoMinorVersion = _SE_BUILD_MINOR; + ga_fnmNextLevel = CTString(""); + memset(ga_aubProperties, 0, NET_MAXSESSIONPROPERTIES); + + // start the timer loop + AddTimerHandler(); + + strmFile.ExpectID_t("GAME"); + // read session state + try { + ga_sesSessionState.Start_t(-1); + ga_sesSessionState.Read_t(&strmFile); + // if starting in network + if (_cmiComm.IsNetworkEnabled()) { + // make default state data for creating deltas + MakeDefaultState(ga_fnmWorld, ga_sesSessionState.ses_ulSpawnFlags, + ga_aubProperties); + } + // players will be connected later + ga_sesSessionState.ses_apltPlayers.Clear(); + ga_sesSessionState.ses_apltPlayers.New(NET_MAXGAMEPLAYERS); + strmFile.ExpectID_t("GEND"); // game end + } catch(char *) { + RemoveTimerHandler(); + ga_srvServer.Stop(); + ga_IsServer = FALSE; + throw; + } + + // set time and pause for server from the saved game + ga_sesSessionState.ses_iLevel+=1; + ga_srvServer.srv_tmLastProcessedTick = ga_sesSessionState.ses_tmLastProcessedTick; + ga_srvServer.srv_iLastProcessedSequence = ga_sesSessionState.ses_iLastProcessedSequence; + ga_srvServer.srv_bPause = ga_sesSessionState.ses_bPause; + ga_srvServer.srv_bGameFinished = ga_sesSessionState.ses_bGameFinished; + ga_sesSessionState.ses_tmPredictionHeadTick = ga_sesSessionState.ses_tmLastProcessedTick; + // start sending stream to local state + ga_srvServer.srv_assoSessions[0].sso_bSendStream = TRUE; + ga_srvServer.srv_assoSessions[0].sso_iLastSentSequence = ga_srvServer.srv_iLastProcessedSequence; + + // eventually cache all shadowmaps in world (memory eater!) + if( shd_bCacheAll) ga_World.wo_baBrushes.CacheAllShadowmaps(); + // flush stale caches + FreeUnusedStock(); + // mark that pretouching is required + _bNeedPretouch = TRUE; + + // start timer sync anew + ga_ctTimersPending = 0; + FinishCRCGather(); +} + +/* + * Save a debugging game. + */ +void CNetworkLibrary::DebugSave(void) +{ + // try to save game + try { + Save_t(CTString("Save\\Debug.sav")); + // if not successful + } catch (char *strError){ + FatalError("Cannot save debug game:\n%s", strError); + } +} + +/* Enumerate existing sessions. */ +void CNetworkLibrary::EnumSessions(BOOL bInternet) +{ + // clear old list + FORDELETELIST(CNetworkSession, ns_lnNode, ga_lhEnumeratedSessions, itns) { + delete &*itns; + } + + // make sure network is on + if (!_cmiComm.IsNetworkEnabled()) { + _cmiComm.PrepareForUse(/*network*/TRUE, /*client*/FALSE); // have to enumerate as server + } + + // request enumeration + GameAgent_EnumTrigger(bInternet); +} + +/* + * Join a running multi-player game. + */ +void CNetworkLibrary::JoinSession_t(const CNetworkSession &nsSesssion, INDEX ctLocalPlayers) // throw char * +{ + // mute all sounds + _pSound->Mute(); + + // report session addres + CPrintF( TRANS("Joining session at: '%s'\n"), nsSesssion.ns_strAddress); + + ga_bLocalPause = FALSE; + + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + ga_ctTimersPending = -1; // disable timer pending + // start gathering CRCs + CGatherCRC gc; + InitCRCGather(); + + // set session name and server address + ga_strSessionName = nsSesssion.ns_strSession; + ga_strServerAddress = nsSesssion.ns_strAddress; + ga_fnmNextLevel = CTString(""); + ga_fnmWorld = CTString(""); + memset(ga_aubProperties, 0, NET_MAXSESSIONPROPERTIES); + + ga_IsServer = FALSE; + ga_ulDemoMinorVersion = _SE_BUILD_MINOR; + // start the timer loop + AddTimerHandler(); + + SetProgressDescription(TRANS("connecting")); + CallProgressHook_t(0.0f); + // initialize session state + try { + ga_sesSessionState.Start_t(ctLocalPlayers); + } catch(char *) { + RemoveTimerHandler(); + throw; + } + + // remember the world pointer + _pShell->SetINDEX("pwoCurrentWorld", (INDEX)&ga_World); + + // eventually cache all shadowmaps in world (memory eater!) + if( shd_bCacheAll) ga_World.wo_baBrushes.CacheAllShadowmaps(); + // flush stale caches + FreeUnusedStock(); + // mark that pretouching is required + _bNeedPretouch = TRUE; + + // run main loop to let session state process messages from server + MainLoop(); + // start timer sync anew + ga_ctTimersPending = 0; + + // initially auto adjust prediction on +// AdjustPredictionOn(); + CPrintF(" joined\n"); +} + +/* Start playing a demo. */ +void CNetworkLibrary::StartDemoPlay_t(const CTFileName &fnDemo) // throw char * +{ + // mute all sounds + _pSound->Mute(); + + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + ga_ctTimersPending = -1; // disable timer pending + ga_bLocalPause = FALSE; + + // open the file + ga_strmDemoPlay.Open_t(fnDemo); + + // remember that playing demo + ga_bDemoPlay = TRUE; + ga_bDemoPlayFinished = FALSE; + + // create session name from demo name + CTString strSessionName = CTString("Demo: ")+fnDemo; + ga_strSessionName = strSessionName; + + ga_IsServer = FALSE; + // start the timer loop + AddTimerHandler(); + // initialize server + try { + // read initial info to stream + ga_strmDemoPlay.ExpectID_t("DEMO"); + if (ga_strmDemoPlay.PeekID_t()==CChunkID("MVER")) { + ga_strmDemoPlay.ExpectID_t("MVER"); + ga_strmDemoPlay>>ga_ulDemoMinorVersion; + } else { + ga_ulDemoMinorVersion = 2; + } + ga_sesSessionState.Read_t(&ga_strmDemoPlay); + } catch(char *) { + RemoveTimerHandler(); + ga_strmDemoPlay.Close(); + ga_bDemoPlay = FALSE; + throw; + } + + // eventually cache all shadowmaps in world (memory eater!) + if( shd_bCacheAll) ga_World.wo_baBrushes.CacheAllShadowmaps(); + // flush stale caches + FreeUnusedStock(); + // mark that pretouching is required + _bNeedPretouch = TRUE; + + // remember the world pointer + _pShell->SetINDEX("pwoCurrentWorld", (INDEX)&ga_World); + + // demo synchronization starts at the beginning initially + ga_fDemoTimer = 0.0f; + ga_tvDemoTimerLastTime = _pTimer->GetHighPrecisionTimer(); + + // demo sync seuqence must be initialized first time in ProcessGameStream() + ga_sesSessionState.ses_tmLastDemoSequence = -1.0f; + + // run main loop to let server process messages from host + MainLoop(); + // start timer sync anew + ga_ctTimersPending = 0; +} + +/* Test if currently playing demo has finished. */ +BOOL CNetworkLibrary::IsDemoPlayFinished(void) +{ + return ga_bDemoPlay && ga_bDemoPlayFinished; +} + +/* Test if currently playing a demo. */ +BOOL CNetworkLibrary::IsPlayingDemo(void) +{ + return ga_bDemoPlay; +} + +/* Test if currently recording a demo. */ +BOOL CNetworkLibrary::IsRecordingDemo(void) +{ + return ga_bDemoRec; +} +BOOL CNetworkLibrary::IsNetworkEnabled(void) +{ + return _cmiComm.IsNetworkEnabled(); +} +// pause/unpause game +void CNetworkLibrary::TogglePause(void) +{ + ga_sesSessionState.ses_bWantPause = !ga_sesSessionState.ses_bWantPause; +} + +// test if game is paused +BOOL CNetworkLibrary::IsPaused(void) +{ + if (this==NULL || _bTempNetwork) { + return TRUE; // this can happen during NET_MakeDefaultState_t()! + } + return ga_sesSessionState.ses_bPause; +} + +// test if having connnection problems (not getting messages from server regulary) +BOOL CNetworkLibrary::IsConnectionStable(void) +{ + // if network is not enabled + if (!_cmiComm.IsNetworkEnabled()) { + // it is always stable + return TRUE; + } + + // check when last message was received. + return (_pTimer->GetHighPrecisionTimer()-ga_sesSessionState.ses_tvMessageReceived).GetSeconds()Mute(); + + CPrintF( TRANS("stopping game.\n")); + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + ga_ctTimersPending = -1; // disable timer pending + + // stop demo recording if active + StopDemoRec(); + + // if playing demo + if (ga_bDemoPlay) { + // close the demo file + ga_strmDemoPlay.Close(); + // remember that not playing demo + ga_bDemoPlay = FALSE; + ga_bDemoPlayFinished = FALSE; + } + + // stop the timer loop + RemoveTimerHandler(); + + // stop session + ga_sesSessionState.Stop(); + + // stop server + if (ga_IsServer) { + ga_srvServer.Stop(); + ga_IsServer = FALSE; + } + ga_ulDemoMinorVersion = _SE_BUILD_MINOR; + + ga_strSessionName = ""; + + ga_World.DeletePredictors(); + ga_World.Clear(); + + // free default state if existing + if (ga_pubDefaultState!=NULL) { + FreeMemory(ga_pubDefaultState); + ga_pubDefaultState = NULL; + ga_slDefaultStateSize = 0; + memset(ga_aubDefaultProperties, 0, sizeof(ga_aubDefaultProperties)); + } + if (ga_pubCRCList!=NULL) { + FreeMemory(ga_pubCRCList); + ga_pubCRCList = NULL; + ga_slCRCList = 0; + } + + ga_aplsPlayers.Clear(); + ga_aplsPlayers.New(NET_MAXLOCALPLAYERS); + // remember the world pointer + _pShell->SetINDEX("pwoCurrentWorld", (INDEX)NULL); + + // rewind the timer + _pTimer->SetCurrentTick(0.0f); +} + +// initiate level change +void CNetworkLibrary::ChangeLevel( + const CTFileName &fnmNextLevel, BOOL bRemember, INDEX iUserData) +{ + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + + ASSERT(!IsPredicting()); + + // if not currently changing + if (_lphCurrent==LCP_NOCHANGE) { + // initiate change + ga_fnmNextLevel = fnmNextLevel; + ga_bNextRemember = bRemember; + ga_iNextLevelUserData = iUserData; + _lphCurrent = LCP_INITIATED; + } +} + +// really do the level change +void CNetworkLibrary::ChangeLevel_internal(void) +{ + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + extern BOOL _bReinitEntitiesWhileCopying; + _bReinitEntitiesWhileCopying = FALSE; + + // mute all sounds + _pSound->Mute(); + + // cancel all predictions before crossing levels + _pNetwork->ga_World.DeletePredictors(); + + // find all entities that are to cross to next level + CEntitySelection senToCross; + {FOREACHINDYNAMICCONTAINER(ga_World.wo_cenEntities, CEntity, iten) { + if (iten->en_ulFlags&ENF_CROSSESLEVELS) { + senToCross.Select(*iten); + } + }} + + // copy them to a temporary world + CWorld wldTemp; + CEntitySelection senInTemp; + wldTemp.CopyEntities(ga_World, senToCross, + senInTemp, CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0))); + + // remember characters for all player targets and disable them + CPlayerCharacter apc[NET_MAXGAMEPLAYERS]; + BOOL abWasActive[NET_MAXGAMEPLAYERS]; + CPlayerAction apaActions[NET_MAXGAMEPLAYERS][2]; + {for(INDEX i=0; ien_pcCharacter; + apaActions[i][0] = plt.plt_paLastAction; + apaActions[i][1] = plt.plt_paPreLastAction; + plt.plt_penPlayerEntity = NULL; + plt.Deactivate(); + } + }} + + // destroy all entities that will cross level + ga_World.DestroyEntities(senToCross); + + // if should remember old levels + if (ga_bNextRemember) { + // remember current level + ga_sesSessionState.RememberCurrentLevel(ga_fnmWorld); + } + + CGatherCRC gc; + + // if starting in network + if (_cmiComm.IsNetworkEnabled()) { + // start gathering CRCs + InitCRCGather(); + + // make default state data for creating deltas + MakeDefaultState(ga_fnmNextLevel, ga_sesSessionState.ses_ulSpawnFlags, ga_aubProperties); + } + + // if the new level is not remembered + if (ga_sesSessionState.FindRememberedLevel(ga_fnmNextLevel)==NULL) { + // remember original world filename + CTFileName fnmOldWorld = ga_fnmWorld; + + // try to + try { + // load the new world + _pTimer->SetCurrentTick(0.0f); // must have timer at 0 while loading + ga_World.Load_t(ga_fnmNextLevel); + // delete all entities that don't fit given spawn flags + ga_World.FilterEntitiesBySpawnFlags(ga_sesSessionState.ses_ulSpawnFlags); + // if failed + } catch(char *strError) { + // report error + CPrintF(TRANS("Cannot change level:\n%s"), strError); + // try to + try { + // load the old world + ga_fnmNextLevel = fnmOldWorld; + ga_World.Load_t(ga_fnmNextLevel); + // delete all entities that don't fit given spawn flags + ga_World.FilterEntitiesBySpawnFlags(ga_sesSessionState.ses_ulSpawnFlags); + // if that fails + } catch (char *strError2) { + // fatal error + FatalError( + TRANS("Cannot change level because:\n%s\n" + "and cannot go back to original one because:\n%s"), strError, strError2); + return; + } + } + // remember the world filename + ga_fnmWorld = ga_fnmNextLevel; + // remember the world pointer + _pShell->SetINDEX("pwoCurrentWorld", (INDEX)&ga_World); + // if there is remembered level + } else { + // restore it + ga_sesSessionState.RestoreOldLevel(ga_fnmNextLevel); + } + + // set overdue timers in just loaded world to be due in current time + ga_World.AdjustLateTimers(ga_sesSessionState.ses_tmLastProcessedTick); + + // copy entities from temporary world into new one + CEntitySelection senCrossed; + ga_World.CopyEntities(wldTemp, senInTemp, + senCrossed, CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0))); + + // restore pointers to entities for all active player targets + {for(INDEX i=0; iga_srvServer.srv_aplbPlayers[iPlayer]; + if (plb.plb_Active) { + // add one dummy action + CPlayerAction pa; + pa.Clear(); + pa.pa_aRotation = plb.plb_paLastAction.pa_aRotation; + pa.pa_aViewRotation = plb.plb_paLastAction.pa_aViewRotation; + plb.plb_abReceived.AddAction(pa); + } + }} + } + ga_sesSessionState.ses_iLevel+=1; + + // flush stale caches + FreeUnusedStock(); + // mark that pretouching is required + _bNeedPretouch = TRUE; + + // start timer sync anew + ga_ctTimersPending = 0; + FinishCRCGather(); +} + +/* Start recording a demo. */ +void CNetworkLibrary::StartDemoRec_t(const CTFileName &fnDemo) // throw char * +{ + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + + // if already recording + if (ga_bDemoRec) { + // error + throw TRANS("Already recording a demo!"); + } + + // create the file + ga_strmDemoRec.Create_t(fnDemo); + + // write initial info to stream + ga_strmDemoRec.WriteID_t("DEMO"); + ga_strmDemoRec.WriteID_t("MVER"); + ga_strmDemoRec<0) { + CNetworkMessage nm(MSG_EXTRA); + nm<SendBroadcast(nm, ulAdr, uwPort); + } + } +} + +/* + * Main loop. + */ +void CNetworkLibrary::MainLoop(void) +{ + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + + // update network state variable (to control usage of some cvars that cannot be altered in mulit-player mode) + _bMultiPlayer = (_pNetwork->ga_sesSessionState.GetPlayersCount() > 1); + + // if should change world + if (_lphCurrent==LCP_SIGNALLED) { + // really do the level change here + ChangeLevel_internal(); + _lphCurrent=LCP_CHANGED; + } + + if (_bStartDemoRecordingNextTime) { + _bStartDemoRecordingNextTime = 0.0f; + if (!ga_bDemoRec) { + try { + CTString strName; + strName.PrintF("Temp\\Recorded%02d.dem", (INDEX)dem_iRecordedNumber); + StartDemoRec_t(strName); + dem_iRecordedNumber+=1; + } catch(char *strError) { + CPrintF(TRANS("Demo recording error: %s\n"), strError); + } + } + } + if (_bStopDemoRecordingNextTime) { + _bStopDemoRecordingNextTime = 0.0f; + if (ga_bDemoRec) { + StopDemoRec(); + } + } + + _sfStats.StartTimer(CStatForm::STI_MAINLOOP); + _pfNetworkProfile.StartTimer(CNetworkProfile::PTI_MAINLOOP); + + // handle messages for session state + if (!ga_bDemoPlay) { + if (_cmiComm.Client_Update() == FALSE) { + ga_sesSessionState.Stop(); + return; + } + ga_sesSessionState.SessionStateLoop(); + if (_cmiComm.Client_Update() == FALSE) { + ga_sesSessionState.Stop(); + return; + } + } + // if this is server computer + if (ga_IsServer) { + // handle server messages + _cmiComm.Server_Update(); + } + + // let server process game stream + TIME tmBefore = _pTimer->GetRealTimeTick(); + _pTimer->SetLerp(0.0f); + + +/* + // automatically adjust network settings + if (cli_bAutoAdjustSettings) { + AutoAdjustSettings(); + } + */ + + // determine whether to use prediction + BOOL bUsePrediction = cli_bPrediction && (cli_bPredictIfServer || !IsServer()); + _bPredictionActive = bUsePrediction; // memeber this for other misc code + + // mark all predictable entities that will be predicted using user-set criterions + if (bUsePrediction) { + ga_World.MarkForPrediction(); + } + // process the game stream coming from the server + ga_sesSessionState.ProcessGameStream(); + // flush actions that don't need to be predicted any more + ga_sesSessionState.FlushProcessedPredictions(); + // process additional prediction steps + if (bUsePrediction) { + // mark all new predictable entities that might have been spawned + ga_World.UnmarkForPrediction(); + ga_World.MarkForPrediction(); + ga_sesSessionState.ProcessPrediction(); + // unmark all predictable entities marked for prediction + ga_World.UnmarkForPrediction(); + } + + ga_sesSessionState.ses_tmLastUpdated = _pTimer->GetRealTimeTick(); + + TIME tmAfter = _pTimer->GetRealTimeTick(); + ga_sesSessionState.ses_bKeepingUpWithTime = (tmAfter-tmBefore)<=_pTimer->TickQuantum*2.01f; + + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + // set the lerping factor for current frame + if (!ga_bDemoPlay) { + ga_sesSessionState.SetLerpFactor(tvNow); + } else { + ga_sesSessionState.SetLerpFactor(CTimerValue(ga_fDemoTimer)); + } + + // if playing a demo + if (ga_bDemoPlay) { + // if synchronizing by real time + if (ga_fDemoSyncRate==DEMOSYNC_REALTIME) { + // if server is keeping up + if (ga_sesSessionState.ses_bKeepingUpWithTime) { + // add passed time with slow/fast factor + ga_fDemoTimer += FLOAT((tvNow-ga_tvDemoTimerLastTime).GetSeconds()) + *ga_fDemoRealTimeFactor*ga_sesSessionState.ses_fRealTimeFactor; + } + // if synchronizing is stopped + } else if (ga_fDemoSyncRate==DEMOSYNC_STOP) { + // don't step + NOTHING; + // if synchronizing by given steps + } else { + // just add the step + ga_fDemoTimer += 1.0f/ga_fDemoSyncRate; + } + } + // remember the demo timer + ga_tvDemoTimerLastTime = tvNow; + + // if network + if (_cmiComm.IsNetworkEnabled()) { + + // do services for gameagent querying + GameAgent_ServerUpdate(); + +// _cmiComm.Broadcast_Update(); + + // repeat + FOREVER { + CNetworkMessage nmReceived; + +// _cmiComm.Broadcast_Update(); + ULONG ulFrom; + UWORD uwPort; + BOOL bHasMsg = ReceiveBroadcast(nmReceived, ulFrom, uwPort); + // if there are no more messages + if (!bHasMsg) { + // finish + break; + } + + // if this message is not valid rcon message + if (nmReceived.GetType()!=MSG_EXTRA) { + // skip it + continue; + } + // get the string from the message + CTString strMsg; + nmReceived>>strMsg; + + // if this is server + if (IsServer()) { + // accept requests + if (!strMsg.RemovePrefix("rcmd ")) { + continue; + } + ULONG ulCode; + char strPass[80]; + char strCmd[256]; + strMsg.ScanF("%u \"%80[^\"]\"%256[^\n]", &ulCode, strPass, strCmd); + CTString strAdr = AddressToString(ulFrom); + + if (net_strAdminPassword=="" || net_strAdminPassword!=strPass) { + CPrintF(TRANS("Server: Client '%s', Wrong password for remote administration.\n"), (const char*)strAdr); + continue; + } + + CPrintF(TRANS("Server: Client '%s', Admin cmd: %s\n"), (const char*)strAdr, strCmd); + + con_bCapture = TRUE; + con_strCapture = ""; + _pShell->Execute(CTString(strCmd)+";"); + + CTString strResponse = CTString(">")+strCmd+"\n"+con_strCapture; + SendAdminResponse(ulFrom, uwPort, ulCode, strResponse); + con_bCapture = FALSE; + con_strCapture = ""; + } + } + } + + _pfNetworkProfile.StopTimer(CNetworkProfile::PTI_MAINLOOP); + _sfStats.StopTimer(CStatForm::STI_MAINLOOP); +} + +// make actions packet for local players and send to server +void CNetworkLibrary::SendActionsToServer(void) +{ + // make the packet + CNetworkMessage nmAction(MSG_ACTION); + + // for all local players on this machine + for(INDEX ipls=0; ipls=0) { + ga_ctTimersPending++; + } + + // if can synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, FALSE); + // initially, no timer functions needed + INDEX ct = 0; + // if timer exactness level is full + if (net_iExactTimer==2) { + // lock network mutex + slNetwork.Lock(); + // execute exactly one + ct = 1; + // if timer exactness level is partial + } else if (net_iExactTimer==1) { + // if network mutex can be locked + if (slNetwork.TryToLock()) { + // execute all pending + ct = ga_ctTimersPending; + } + // if timer exactness level is low + } else if (net_iExactTimer==0) { + // if network mutex can be locked + if (slNetwork.TryToLock()) { + // execute exactly one + ct = 1; + } + } + // for each pending interrupt + while(ct) { + ct--; + ga_ctTimersPending--; + // if not disconnected +// if (!IsDisconnected()) { + if (_cmiComm.cci_bClientInitialized) { + // make actions packet for all local players and send to server + SendActionsToServer(); + _cmiComm.Client_Update(); + } + + // if this is server computer + if (ga_IsServer) { + // handle server messages + _cmiComm.Server_Update(); + ga_srvServer.ServerLoop(); + _cmiComm.Server_Update(); + } + } + + _pfNetworkProfile.StopTimer(CNetworkProfile::PTI_TIMERLOOP); +} + +/* Get player entity for a given local player. */ +CEntity *CNetworkLibrary::GetLocalPlayerEntity(CPlayerSource *ppls) +{ + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + + // get the index of the player target in game state + INDEX iPlayerTarget = ppls->pls_Index; + // if player is not added + if (iPlayerTarget<0) { + // no entity + return NULL; + // if player is added + } else { + // get the entity from player target + CPlayerTarget &plt = ga_sesSessionState.ses_apltPlayers[iPlayerTarget]; + CPlayerEntity *pen = plt.plt_penPlayerEntity; + return pen; + } +} + +/* Get player entity for a given player by name. */ +CEntity *CNetworkLibrary::GetPlayerEntityByName(const CTString &strName) +{ + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + + // for each player in game + CStaticArray &aplt = ga_sesSessionState.ses_apltPlayers; + for(INDEX iplt = 0; iplten_pcCharacter.GetName()==strName) { + // return it + return aplt[iplt].plt_penPlayerEntity; + } + } + // else not found + return NULL; +} + +/* Get number of entities with given name. */ +INDEX CNetworkLibrary::GetNumberOfEntitiesWithName(const CTString &strName) +{ + INDEX ctEntities = 0; + {FOREACHINDYNAMICCONTAINER(ga_World.wo_cenEntities, CEntity, iten) { + if (iten->GetName()==strName) { + ctEntities++; + } + }} + return ctEntities; +} + +/* Get n-th entity with given name. */ +CEntity *CNetworkLibrary::GetEntityWithName(const CTString &strName, INDEX iEntityWithThatName) +{ + INDEX ctEntities = 0; + CEntity *pen = NULL; + {FOREACHINDYNAMICCONTAINER(ga_World.wo_cenEntities, CEntity, iten) { + if (iten->GetName()==strName) { + pen = iten; + if (ctEntities==iEntityWithThatName) { + break; + } + ctEntities++; + } + }} + return pen; +} +/* Test if a given player is local to this computer. */ +BOOL CNetworkLibrary::IsPlayerLocal(CEntity *pen) +{ + return GetPlayerSource(pen)!=NULL; +} +// get player source for a given player if it is local to this computer +CPlayerSource *CNetworkLibrary::GetPlayerSource(CEntity *pen) +{ + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + + // for all local player on this machine + {FOREACHINSTATICARRAY(ga_aplsPlayers, CPlayerSource, itpls) { + // get the index of the player target in game state + INDEX iPlayerTarget = itpls->pls_Index; + // if player is added + if (iPlayerTarget>=0) { + // get the player target + CPlayerTarget &plt = ga_sesSessionState.ses_apltPlayers[iPlayerTarget]; + // if it is that one + if (plt.plt_penPlayerEntity == pen) { + // return it + return itpls; + } + } + }} + + // if not found, it is not local + return NULL; +} + +// get game time in currently running game +TIME CNetworkLibrary::GetGameTime(void) +{ + return ga_sesSessionState.ses_tmLastProcessedTick; +} + +/* + * Add a new client to game. + */ +CPlayerSource *CNetworkLibrary::AddPlayer_t(CPlayerCharacter &pcCharacter) // throw char * +{ + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + CPrintF( TRANS("Adding player: '%s'\n"), pcCharacter.GetNameForPrinting()); + + // for all local clients on this machine + FOREACHINSTATICARRAY(ga_aplsPlayers, CPlayerSource, itcls) { + // if client is not active + if (!itcls->IsActive()) { + // activate it + itcls->Start_t(pcCharacter); + CPrintF( TRANS(" done.\n")); + return &itcls.Current(); + } + } + // number of local clients is limited with NET_MAXLOCALCLIENTS + ASSERTALWAYS("Adding too much local clients!"); + throw TRANS("Cannot add more local clients"); + return NULL; +} + +/* Get session properties for current game. */ +void *CNetworkLibrary::GetSessionProperties(void) +{ + // synchronize access to network + CTSingleLock slNetwork(&ga_csNetwork, TRUE); + + return ga_aubProperties; +} + +/* Send chat message from some players to some other players. */ +void CNetworkLibrary::SendChat(ULONG ulFrom, ULONG ulTo, const CTString &strMessage) +{ + // if the string is too long and we're not server + if (strlen(strMessage)>256 && !_pNetwork->IsServer()) { + // refuse it + return; + } + + // just make the message and send it to server + CNetworkMessage nm(MSG_CHAT_IN); + nm<>iSaved; + // get current one + INDEX iCurrent = _SE_BUILD_MAJOR; + // if current version is an internal build + if (iCurrent==0) { + // it is never forced to reinit + bNeedsReinit = FALSE; + return; + } + + // if current version is older than the saved one + if (iCurrentiSaved) { + // it should be reinitialized + bNeedsReinit = TRUE; + + // if it may not be reinitialized + if (!bAllowReinit) { + ThrowF_t(TRANS("File '%s' was saved by an older version of engine, it cannot be loaded"), + strm.GetDescription()); + } + return; + } + // this should not happen + ASSERT(FALSE); + bNeedsReinit = FALSE; + return; +} + +// add a value to the netgraph +void CNetworkLibrary::AddNetGraphValue(enum NetGraphEntryType nget, FLOAT fLatency) +{ + net_iGraphBuffer = Clamp(net_iGraphBuffer, INDEX(20), INDEX(1000)); + + // make sure the netgraph has wanted number of values + if (ga_angeNetGraph.Count()!=net_iGraphBuffer) { + ga_angeNetGraph.Clear(); + ga_angeNetGraph.New(net_iGraphBuffer); + memset(&ga_angeNetGraph[0], 0, ga_angeNetGraph.Count()*sizeof(ga_angeNetGraph[0])); + } + + // scroll the values in the netgraph by one value + memmove(&ga_angeNetGraph[1], &ga_angeNetGraph[0], (ga_angeNetGraph.Count()-1)*sizeof(ga_angeNetGraph[0])); + + // add the new value + ga_angeNetGraph[0].nge_ngetType = nget; + ga_angeNetGraph[0].nge_fLatency = fLatency; +} + +// make default state for a network game +extern void NET_MakeDefaultState_t( + const CTFileName &fnmWorld, ULONG ulSpawnFlags, void *pvSessionProperties, + CTStream &strmState) // throw char * +{ + // mute all sounds + _pSound->Mute(); + + // first off - mark that we are in the special state + _bTempNetwork = TRUE; + + // make sure that current network object gets locked + CTSingleLock slNetwork(&_pNetwork->ga_csNetwork, TRUE); + + // remember original network pointer and clear it + CNetworkLibrary *pnlOld = _pNetwork; + _pNetwork = NULL; + + // try to + try { + // create new network object + CNetworkLibrary *pNewNet = new CNetworkLibrary; + // it must have new mutex index since both will be locked + pNewNet->ga_csNetwork.cs_iIndex = 2001; + + // lock the new network access + CTSingleLock slNetwork(&pNewNet->ga_csNetwork, TRUE); + pNewNet->ga_ctTimersPending = -1; // disable timer pending + // only after locking it, we may allow the new pointer to be remembered + // otherwise, the other thread can jump in between + _pNetwork = pNewNet; + + // remember settings + _pNetwork->ga_sesSessionState.ses_ulSpawnFlags = ulSpawnFlags; + _pNetwork->ga_sesSessionState.ses_tmSyncCheckFrequency = 10.0f; + _pNetwork->ga_sesSessionState.ses_iExtensiveSyncCheck = 0; + memcpy(_pNetwork->ga_aubProperties, pvSessionProperties, NET_MAXSESSIONPROPERTIES); + _pNetwork->ga_fnmWorld = fnmWorld; + _pNetwork->ga_fnmNextLevel = CTString(""); + + try { + // load the world + _pTimer->SetCurrentTick(0.0f); // must have timer at 0 while loading + _pNetwork->ga_World.Load_t(fnmWorld); + // delete all entities that don't fit given spawn flags + _pNetwork->ga_World.FilterEntitiesBySpawnFlags(_pNetwork->ga_sesSessionState.ses_ulSpawnFlags); + } catch(char *) { + throw; + } + // remember the world filename + _pNetwork->ga_fnmWorld = fnmWorld; + _pNetwork->ga_fnmNextLevel = CTString(""); + // remember the world pointer + _pShell->SetINDEX("pwoCurrentWorld", (INDEX)&_pNetwork->ga_World); + + // reset random number generator + _pNetwork->ga_sesSessionState.ResetRND(); + // flush stale caches + FreeUnusedStock(); + + // warmup the world + _pNetwork->ga_sesSessionState.WarmUpWorld(); + + // save the session state to the stream + _pNetwork->ga_sesSessionState.Write_t(&strmState); + + // if any error + } catch (char *) { + // restore original network pointer + CNetworkLibrary *pnlTemp = _pNetwork; + _pNetwork = pnlOld; + if (pnlTemp!=NULL) { + delete pnlTemp; + } + _bTempNetwork = FALSE; + // fail + throw; + } + + // restore original network pointer + CNetworkLibrary *pnlTemp = _pNetwork; + _pNetwork = pnlOld; + delete pnlTemp; + _bTempNetwork = FALSE; +} + +// handle broadcast messages (server enumeration) +void CNetworkLibrary::GameInactive(void) +{ + GameAgent_EnumUpdate(); + + // if no network + if (!_cmiComm.IsNetworkEnabled()) { + // do not handle + return; + } + +// _cmiComm.Broadcast_Update(); + + // repeat + FOREVER { + CNetworkMessage nmReceived; + +//_cmiComm.Broadcast_Update(); + ULONG ulFrom; + UWORD uwPort; + BOOL bHasMsg = ReceiveBroadcast(nmReceived, ulFrom, uwPort); + // if there are no more messages + if (!bHasMsg) { + // finish + break; + } + + /* This is handled by GameAgent. + + // if requesting enumeration and this is server and enumeration is allowed + if (nmReceived.GetType()==MSG_REQ_ENUMSERVERS + && IsServer() + && (ser_bEnumeration && ga_sesSessionState.ses_ctMaxPlayers>1)) { + // create response + CNetworkMessage nmEnum(MSG_SERVERINFO); + nmEnum<>ns.ns_strSession; + nmReceived>>ns.ns_strWorld; + nmReceived>>ns.ns_ctPlayers; + nmReceived>>ns.ns_ctMaxPlayers; + ns.ns_strAddress = AddressToString(ulFrom); + }*/ + } +} + +void CNetworkLibrary::InitCRCGather(void) +{ + CRCT_ResetActiveList(); + CRCT_bGatherCRCs = TRUE; + CRCT_AddFile_t(CTString("Classes\\Player.ecl")); +} + +// finish gathering of file CRCs to CRC table (call for server only!) +void CNetworkLibrary::FinishCRCGather(void) +{ + try { + // make the list + CTMemoryStream strmCRC; + CRCT_MakeFileList_t(strmCRC); + + // remember it + strmCRC.SetPos_t(0); + ga_slCRCList = strmCRC.GetStreamSize(); + ga_pubCRCList = (UBYTE*)AllocMemory(ga_slCRCList); + strmCRC.Read_t(ga_pubCRCList, ga_slCRCList); + + // remember its CRC + strmCRC.SetPos_t(0); + ga_ulCRC = CRCT_MakeCRCForFiles_t(strmCRC); + + } catch (char *strError) { + CPrintF(TRANS("Warning, cannot get CRCs: %s\n"), strError); + } +} + +// make default state data for creating deltas +void CNetworkLibrary::MakeDefaultState(const CTFileName &fnmWorld, + ULONG ulSpawnFlags, void *pvSessionProperties) +{ + // prepare file or memory stream for state + CTFileStream strmStateFile; CTMemoryStream strmStateMem; + CTStream *pstrmState; + extern INDEX net_bDumpConnectionInfo; + if (net_bDumpConnectionInfo) { + strmStateFile.Create_t(CTString("Temp\\DefaultState.bin")); + pstrmState = &strmStateFile; + } else { + pstrmState = &strmStateMem; + } + // make default state for a network game + NET_MakeDefaultState_t(fnmWorld, ulSpawnFlags, pvSessionProperties, *pstrmState); + pstrmState->SetPos_t(0); + + ga_slDefaultStateSize = pstrmState->GetStreamSize(); + ga_pubDefaultState = (UBYTE*)AllocMemory(ga_slDefaultStateSize); + pstrmState->Read_t(ga_pubDefaultState, ga_slDefaultStateSize); + memcpy(ga_aubDefaultProperties, pvSessionProperties, sizeof(ga_aubDefaultProperties)); +} diff --git a/Sources/Engine/Network/Network.h b/Sources/Engine/Network/Network.h new file mode 100644 index 0000000..fe781d8 --- /dev/null +++ b/Sources/Engine/Network/Network.h @@ -0,0 +1,300 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_NETWORK_H +#define SE_INCL_NETWORK_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include + +#define NET_MAXGAMECOMPUTERS SERVER_CLIENTS // max overall computers in game +#define NET_MAXGAMEPLAYERS 16 // max overall players in game +#define NET_MAXLOCALPLAYERS 4 // max players on a single machine + +#define NET_WAITMESSAGE_DELAY 50 // wait time between receive message attempts + +#define NET_MAXSESSIONPROPERTIES 2048 // size of buffer for custom use by CGame and entities + + +/* + * Timer handler for network timer loop. + */ +class ENGINE_API CNetworkTimerHandler : public CTimerHandler { +public: + /* This is called every TickQuantum seconds. */ + virtual void HandleTimer(void); +}; + +// demo synchronization constants +#define DEMOSYNC_REALTIME (0.0f) +#define DEMOSYNC_STOP (-1.0f) + +enum NetGraphEntryType { + NGET_ACTION = 0, + NGET_NONACTION, + NGET_MISSING, + NGET_SKIPPEDACTION, + NGET_REPLICATEDACTION, +}; +struct NetGraphEntry { + enum NetGraphEntryType nge_ngetType; // type of packet/event + FLOAT nge_fLatency; // latency in seconds + void Clear(void); +}; + +/* + * Network session description. + */ +class ENGINE_API CNetworkSession { +public: + CListNode ns_lnNode; // for linking in list of available sessions + CTString ns_strAddress; // session address + + CTString ns_strSession; // session name + CTString ns_strWorld; // world name + TIME ns_tmPing; // current players + INDEX ns_ctPlayers; // current players + INDEX ns_ctMaxPlayers; // max number of players + CTString ns_strGameType; // game type + CTString ns_strMod; // active mod + CTString ns_strVer; // version +public: + void Copy(const CNetworkSession &nsOriginal); + + /* Default constructor. */ + CNetworkSession(void); + /* Construct a session for connecting to certain server. */ + CNetworkSession(const CTString &strAddress); +}; + +/* + * Game, used for general game initialization/manipulation + */ +class ENGINE_API CNetworkLibrary : public CMessageDispatcher { +public: + +public: + BOOL ga_IsServer; // set if this is a server computer + CServer &ga_srvServer; // server (active only if this is server computer) + + CTCriticalSection ga_csNetwork; // critical section for access to network data + + CSessionState &ga_sesSessionState; // local session state + CStaticArray ga_aplsPlayers; // local players + CTString ga_strSessionName; // name of current session + CTString ga_strServerAddress; // address of game server (if joined) + INDEX ga_ulDemoMinorVersion; // minor version of build that created this demo + CTFileName ga_fnmWorld; // filename of current world + UBYTE *ga_pubDefaultState; // default state for connecting (server only) + SLONG ga_slDefaultStateSize; + UBYTE ga_aubDefaultProperties[NET_MAXSESSIONPROPERTIES]; + UBYTE *ga_pubCRCList; // list of files for CRC checking (server only) + SLONG ga_slCRCList; + ULONG ga_ulCRC; // CRC of CRCs of all files in the list + + BOOL ga_bLocalPause; // local pause for single player/demo + BOOL ga_bDemoRec; // set if currently recording a demo + CTFileStream ga_strmDemoRec; // currently recorded demo file + BOOL ga_bDemoPlay; // set if currently playing a demo + BOOL ga_bDemoPlayFinished; // set if currently playing demo has finished + CTFileStream ga_strmDemoPlay; // currently played demo file + CTimerValue ga_tvDemoTimerLastTime; // real time timer for demo synchronization + CNetworkTimerHandler ga_thTimerHandler; // handler for driving the timer loop + INDEX ga_ctTimersPending; // number of timer loops pending + + CTFileName ga_fnmNextLevel; // world for next level + BOOL ga_bNextRemember; // remember old levels when changing to new one + INDEX ga_iNextLevelUserData; // user data for next level + + CListHead ga_lhEnumeratedSessions; // list of sessions found after last enumeration was triggered + FLOAT ga_fEnumerationProgress; // enumeration progress percentage (0-1) + CTString ga_strEnumerationStatus; // description of current operation + BOOL ga_bEnumerationChange; // this is raised if something was changed in the list + + CTString ga_strRequiredMod; // set if connection failed due to a different mod running on the server + + // buffer for custom use by CGame and entities + UBYTE ga_aubProperties[NET_MAXSESSIONPROPERTIES]; + + BOOL IsServer(void) { return ga_IsServer; }; + + // make actions packet for local players and send to server + void SendActionsToServer(void); + + /* Loop executed in timer interrupt, every game tick. */ + void TimerLoop(void); + + /* Add the timer handler. */ + void AddTimerHandler(void); + /* Remove the timer handler. */ + void RemoveTimerHandler(void); + + // really do the level change + void ChangeLevel_internal(void); + + // save current version of engine + void WriteVersion_t(CTStream &strm); + // load version of engine saved in file and check against current + void CheckVersion_t(CTStream &strm, BOOL bAllowReinit, BOOL &bNeedsReinit); + + // add a value to the netgraph + void AddNetGraphValue(enum NetGraphEntryType nget, FLOAT fLatency); + + // call this while game is not running - to update server enumeration lists + void GameInactive(void); + + // automatically adjust network settings + void AutoAdjustSettings(void); + + // make default state data for creating deltas + void MakeDefaultState(const CTFileName &fnmWorld, ULONG ulSpawnFlags, void *pvSessionProperties); + + // initialize gathering of file CRCs to CRC table + void InitCRCGather(void); + // finish gathering of file CRCs to CRC table (call for server only!) + void FinishCRCGather(void); + +public: + CWorld ga_World; // local copy of world + FLOAT ga_fDemoTimer; // timer for demo playback (in seconds) + FLOAT ga_fDemoRealTimeFactor; // slow/fast playback factor (for DEMOSYNC_REALTIME only) + FLOAT ga_fGameRealTimeFactor; // game time accelerator + FLOAT ga_fDemoSyncRate; // demo sync speed in FPS (or realtime/stop) + CStaticArray ga_angeNetGraph; // array of netgraph entries + + // interface + /* Default constructor. */ + CNetworkLibrary(void); + ~CNetworkLibrary(void); + DECLARE_NOCOPYING(CNetworkLibrary); + + /* Initialize game management. */ + void Init(const CTString &strGameID); + /* Start a peer-to-peer game session. */ + void StartPeerToPeer_t(const CTString &strSessionName, + const CTFileName &fnmWorld, ULONG ulSpawnFlags, + INDEX ctMaxPlayers, BOOL bWaitAllPlayers, + void *pvSessionProperties); // throw char * + /* Trigger sessions enumeration over LAN and iNet. */ + void EnumSessions(BOOL bInternet); + /* Join a running multi-player game. */ + void JoinSession_t(const CNetworkSession &nsSesssion, INDEX ctLocalPlayers); // throw char * + /* Start playing a demo. */ + void StartDemoPlay_t(const CTFileName &fnDemo); // throw char * + /* Test if currently playing a demo. */ + BOOL IsPlayingDemo(void); + /* Test if currently recording a demo. */ + BOOL IsRecordingDemo(void); + /* Test if currently playing demo has finished. */ + BOOL IsDemoPlayFinished(void); + /* Stop currently running game. */ + void StopGame(void); + + // pause/unpause game + void TogglePause(void); + // test if game is paused + BOOL IsPaused(void); + // test if game is waiting for more players to connect + BOOL IsWaitingForPlayers(void); + // test if game is waiting for server + BOOL IsWaitingForServer(void); + // mark that the game has finished -- called from AI + void SetGameFinished(void); + BOOL IsGameFinished(void); + // manipulation with realtime factor for slower/faster time -- called from AI + void SetRealTimeFactor(FLOAT fSpeed); + FLOAT GetRealTimeFactor(void); + // test if having connnection problems (not getting messages from server regulary) + BOOL IsConnectionStable(void); + // test if completely disconnected and why + BOOL IsDisconnected(void); + const CTString &WhyDisconnected(void); + + // set/get server side pause (for single player or demo only) + void SetLocalPause(BOOL bPause); + BOOL GetLocalPause(void); + + // get server/client name and address + void GetHostName(CTString &strName, CTString &strAddress); + + // test if playing in network or locally + BOOL IsNetworkEnabled(void); + + // test if game session is currently doing prediction + BOOL IsPredicting(void); + + // initiate level change + void ChangeLevel(const CTFileName &fnmNextLevel, BOOL bRemember, INDEX iUserData); + + /* Obtain file name of world that is currently loaded. */ + CTFileName &GetCurrentWorld(void) { return ga_fnmWorld;}; + + /* Start recording a demo. */ + void StartDemoRec_t(const CTFileName &fnDemo); // throw char * + /* Stop recording a demo. */ + void StopDemoRec(void); + + /* Read current game situation from a stream. */ + void Read_t(CTStream *pstr); // throw char * + /* Write current game situation into a stream. */ + void Write_t(CTStream *pstr); // throw char * + + /* Save the game. */ + void Save_t(const CTFileName &fnmGame); // throw char * + /* Load the game. */ + void Load_t(const CTFileName &fnmGame); // throw char * + + /* Save a debugging game. */ + void DebugSave(void); // this doesn't throw anything + + /* Add a new player to game. */ + CPlayerSource *AddPlayer_t(CPlayerCharacter &pcCharacter); // throw char * + + /* Loop executed in main application thread. */ + void MainLoop(void); + + /* Get player entity for a given local player. */ + CEntity *GetLocalPlayerEntity(CPlayerSource *ppls); + /* Get player entity for a given player by name. */ + CEntity *GetPlayerEntityByName(const CTString &strName); + /* Get number of entities with given name. */ + INDEX GetNumberOfEntitiesWithName(const CTString &strName); + /* Get n-th entity with given name. */ + CEntity *GetEntityWithName(const CTString &strName, INDEX iEntityWithThatName); + /* Test if a given player is local to this computer. */ + BOOL IsPlayerLocal(CEntity *pen); + // get player source for a given player if it is local to this computer + CPlayerSource *GetPlayerSource(CEntity *pen); + + // get game time in currently running game + TIME GetGameTime(void); + + /* Get session properties for current game. */ + void *GetSessionProperties(void); + + /* Send chat message from some players to some other players. */ + void SendChat(ULONG ulFrom, ULONG ulTo, const CTString &strMessage); +}; + +// make default state for a network game +extern void NET_MakeDefaultState_t( + const CTFileName &fnmWorld, ULONG ulSpawnFlags, void *pvSessionProperties, + CTStream &strmState); // throw char * + +// pointer to global instance of the only network object in the application +ENGINE_API extern CNetworkLibrary *_pNetwork; + +// convert string address to a number +ENGINE_API extern ULONG StringToAddress(const CTString &strAddress); +// convert address to a printable string +ENGINE_API extern CTString AddressToString(ULONG ulHost); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/NetworkMessage.cpp b/Sources/Engine/Network/NetworkMessage.cpp new file mode 100644 index 0000000..25a5c76 --- /dev/null +++ b/Sources/Engine/Network/NetworkMessage.cpp @@ -0,0 +1,1016 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct ErrorCode ErrorCodes[] = { +// message types + ERRORCODE(MSG_REQ_ENUMSERVERS, "MSG_REQ_ENUMSERVERS"), + ERRORCODE(MSG_SERVERINFO, "MSG_SERVERINFO"), + ERRORCODE(MSG_INF_DISCONNECTED, "MSG_INF_DISCONNECTED"), + ERRORCODE(MSG_REQ_CONNECTLOCALSESSIONSTATE, "MSG_REQ_CONNECTLOCALSESSIONSTATE"), + ERRORCODE(MSG_REP_CONNECTLOCALSESSIONSTATE, "MSG_REP_CONNECTLOCALSESSIONSTATE"), + ERRORCODE(MSG_REQ_CONNECTREMOTESESSIONSTATE, "MSG_REQ_CONNECTREMOTESESSIONSTATE"), + ERRORCODE(MSG_REP_CONNECTREMOTESESSIONSTATE, "MSG_REP_CONNECTREMOTESESSIONSTATE"), + ERRORCODE(MSG_REQ_STATEDELTA, "MSG_REQ_STATEDELTA"), + ERRORCODE(MSG_REQ_STATEDELTA, "MSG_REP_STATEDELTA"), + ERRORCODE(MSG_REQ_CONNECTPLAYER, "MSG_REQ_CONNECTPLAYER"), + ERRORCODE(MSG_REP_CONNECTPLAYER, "MSG_REP_CONNECTPLAYER"), + ERRORCODE(MSG_ACTION, "MSG_ACTION"), + ERRORCODE(MSG_ACTIONPREDICT, "MSG_ACTIONPREDICT"), + ERRORCODE(MSG_SEQ_ALLACTIONS, "MSG_SEQ_ALLACTIONS"), + ERRORCODE(MSG_SEQ_ADDPLAYER, "MSG_SEQ_ADDPLAYER"), + ERRORCODE(MSG_SEQ_REMPLAYER, "MSG_SEQ_REMPLAYER"), + ERRORCODE(MSG_GAMESTREAMBLOCKS, "MSG_GAMESTREAMBLOCKS"), + ERRORCODE(MSG_REQUESTGAMESTREAMRESEND, "MSG_REQUESTGAMESTREAMRESEND"), +}; +extern struct ErrorTable MessageTypes = ERRORTABLE(ErrorCodes); + +///////////////////////////////////////////////////////////////////// +// CNetworkMessage + +/* + * Constructor for empty message (for receiving). + */ +CNetworkMessage::CNetworkMessage(void) +{ + // allocate message buffer + nm_slMaxSize = MAX_NETWORKMESSAGE_SIZE; + nm_pubMessage = (UBYTE*) AllocMemory(nm_slMaxSize); + + // mangle pointer and size so that it could not be accidentally read/written + nm_pubPointer = NULL; + nm_iBit = -1; + nm_slSize = -1; +} + +// reinit a message that is to be sent (to write different contents) +void CNetworkMessage::Reinit(void) +{ + // init read/write pointer and size + nm_slMaxSize = MAX_NETWORKMESSAGE_SIZE; + nm_pubPointer = nm_pubMessage; + nm_iBit = 0; + nm_slSize = 0; + // write the type + UBYTE ubType = nm_mtType; + Write(&ubType, sizeof(ubType)); +} + +/* + * Constructor for initializing message that is to be sent. + */ +CNetworkMessage::CNetworkMessage(MESSAGETYPE mtType) +{ + // allocate message buffer + nm_slMaxSize = MAX_NETWORKMESSAGE_SIZE; + nm_pubMessage = (UBYTE*) AllocMemory(nm_slMaxSize); + + // init read/write pointer and size + nm_pubPointer = nm_pubMessage; + nm_iBit = 0; + nm_slSize = 0; + + // remember the type + nm_mtType = mtType; + // write the type + UBYTE ubType = nm_mtType; + Write(&ubType, sizeof(ubType)); +} +/* Copying. */ +CNetworkMessage::CNetworkMessage(const CNetworkMessage &nmOriginal) +{ + // allocate message buffer + nm_slMaxSize = nmOriginal.nm_slMaxSize; + nm_pubMessage = (UBYTE*) AllocMemory(nm_slMaxSize); + + // init read/write pointer and size + nm_pubPointer = nm_pubMessage + (nmOriginal.nm_pubPointer-nmOriginal.nm_pubMessage); + nm_iBit = nmOriginal.nm_iBit; + nm_slSize = nmOriginal.nm_slSize; + + // copy from original + memcpy(nm_pubMessage, nmOriginal.nm_pubMessage, nm_slSize); + + // remember the type + nm_mtType = nmOriginal.nm_mtType; +} + +void CNetworkMessage::operator=(const CNetworkMessage &nmOriginal) +{ + if (nm_slMaxSize != nmOriginal.nm_slMaxSize) { + if (nm_pubMessage!=NULL) { + FreeMemory(nm_pubMessage); + } + + // allocate message buffer + nm_slMaxSize = nmOriginal.nm_slMaxSize; + nm_pubMessage = (UBYTE*) AllocMemory(nm_slMaxSize); + } + + // init read/write pointer and size + nm_pubPointer = nm_pubMessage+sizeof(UBYTE);// + (nmOriginal.nm_pubPointer-nmOriginal.nm_pubMessage); + nm_iBit = 0; + nm_slSize = nmOriginal.nm_slSize; + + // copy from original + memcpy(nm_pubMessage, nmOriginal.nm_pubMessage, nm_slSize); + + // remember the type + nm_mtType = nmOriginal.nm_mtType; +} + +/* + * Destructor. + */ +CNetworkMessage::~CNetworkMessage(void) +{ + ASSERT(nm_pubMessage!=NULL); + if (nm_pubMessage!=NULL) { + FreeMemory(nm_pubMessage); + } +} + +/* + * Ignore the contents of this message. + */ +void CNetworkMessage::IgnoreContents(void) +{ +} + + +/* Check if end of message. */ +BOOL CNetworkMessage::EndOfMessage(void) +{ + ASSERTMSG((nm_pubPointer-nm_pubMessage) <= nm_slSize, "Message over-reading!"); + return (nm_pubPointer-nm_pubMessage) >= nm_slSize; +} + +// read/write functions +void CNetworkMessage::Read(void *pvBuffer, SLONG slSize) +{ + if (nm_pubPointer+slSize > nm_pubMessage+nm_slSize) { + CPrintF(TRANS("Warning: Message over-reading!\n")); + ASSERT(FALSE); + memset(pvBuffer, 0, slSize); + return; + } + memcpy(pvBuffer, nm_pubPointer, slSize); + nm_pubPointer += slSize; + nm_iBit = 0; +} +void CNetworkMessage::Write(const void *pvBuffer, SLONG slSize) +{ + if (nm_pubPointer+slSize > nm_pubMessage+nm_slMaxSize) { + CPrintF(TRANS("Warning: Message over-writing!\n")); + ASSERT(FALSE); + return; + } + memcpy(nm_pubPointer, pvBuffer, slSize); + nm_pubPointer += slSize; + nm_iBit = 0; + nm_slSize += slSize; +} +CNetworkMessage &CNetworkMessage::operator>>(CTString &str) +{ + // start reading string from message + str = ""; + nm_iBit = 0; + // repeat + for(;;) { + // if reached end of message (this happens when we read string-only messages) + if (nm_pubPointer-nm_pubMessage>=nm_slSize) { + // stop + return *this; + } + // get next char + char strChar[2]; + strChar[0] = *nm_pubPointer++; + strChar[1] = 0; + // if end of string + if (strChar[0]==0) { + // stop + return *this; + // if normal char + } else { + // append to the string + str+=strChar; + } + } +} +CNetworkMessage &CNetworkMessage::operator<<(const CTString &str) +{ + // start writing string to message + nm_iBit = 0; + const char *pstr = (const char *)str; + // repeat + for(;;) { + // if reached one byte before end of message + if (nm_pubPointer-nm_pubMessage>=nm_slMaxSize-1) { + // put the end marker + *nm_pubPointer++ = 0; + nm_slSize++; + // report error and stop + CPrintF(TRANS("Warning: Message over-writing!\n")); + ASSERT(FALSE); + return *this; + } + // get next char + const char chr = *pstr++; + // write it to message + *nm_pubPointer++ = chr; + nm_slSize++; + // if end + if (chr==0) { + // stop + return *this; + } + } +} + +/* + * Insert a sub-message into this message. + */ +void CNetworkMessage::InsertSubMessage(const CNetworkMessage &nmSubMessage) +{ + // write sub-message size + operator<<(nmSubMessage.nm_slSize); + // write the contents of the sub-message + Write(nmSubMessage.nm_pubMessage, nmSubMessage.nm_slSize); +} + +/* + * Extract a sub-message from this message. + */ +void CNetworkMessage::ExtractSubMessage(CNetworkMessage &nmSubMessage) +{ + // read sub-message size + operator>>(nmSubMessage.nm_slSize); + // read the contents of the sub-message + Read(nmSubMessage.nm_pubMessage, nmSubMessage.nm_slSize); + // init the submessage read/write pointer + nmSubMessage.nm_pubPointer = nmSubMessage.nm_pubMessage; + nmSubMessage.nm_iBit = 0; + // get the submessage type + UBYTE ubType = 0; + nmSubMessage>>ubType; + nmSubMessage.nm_mtType = (MESSAGETYPE)ubType; +} + +// rewind message to start, so that written message can be read again +void CNetworkMessage::Rewind(void) +{ + nm_pubPointer = nm_pubMessage+sizeof(UBYTE); + nm_iBit = 0; +} + +/* + * Pack a message to another message (message type is left untouched). + */ +void CNetworkMessage::Pack(CNetworkMessage &nmPacked, CCompressor &comp) +{ + // get size and pointers for packing, leave the message type alone + SLONG slUnpackedSize = nm_slSize-sizeof(UBYTE); + void *pvUnpacked = nm_pubMessage+sizeof(UBYTE); + + SLONG slPackedSize = nmPacked.nm_slMaxSize-sizeof(UBYTE); + void *pvPacked = nmPacked.nm_pubMessage+sizeof(UBYTE); + + // pack it there + ASSERT(comp.NeededDestinationSize(slUnpackedSize)<=slPackedSize); + BOOL bSucceded = comp.Pack(pvUnpacked, slUnpackedSize, pvPacked, slPackedSize); + ASSERT(bSucceded); + + // set up the destination message size + nmPacked.nm_slSize = slPackedSize+sizeof(UBYTE); +} +/* + * Unpack a message to another message (message type is left untouched). + */ +void CNetworkMessage::Unpack(CNetworkMessage &nmUnpacked, CCompressor &comp) +{ + // get size and pointers for unpacking, leave the message type alone + SLONG slPackedSize = nm_slSize-sizeof(UBYTE); + void *pvPacked = nm_pubMessage+sizeof(UBYTE); + + SLONG slUnpackedSize = nmUnpacked.nm_slMaxSize-sizeof(UBYTE); + void *pvUnpacked = nmUnpacked.nm_pubMessage+sizeof(UBYTE); + + // unpack it there + BOOL bSucceeded = comp.Unpack(pvPacked, slPackedSize, pvUnpacked, slUnpackedSize); + ASSERT(bSucceeded); + + // set up the destination message size + nmUnpacked.nm_slSize = slUnpackedSize+sizeof(UBYTE); +} + + +// NOTE: +// compression type bits in the messages are different than compression type cvar values +// this is to keep backward compatibility with old demos saved with full compression +void CNetworkMessage::PackDefault(CNetworkMessage &nmPacked) +{ + extern INDEX net_iCompression; + if (net_iCompression==2) { + // pack with zlib only + CzlibCompressor compzlib; + Pack(nmPacked, compzlib); + (int&)nmPacked.nm_mtType|=0<<6; + } else if (net_iCompression==1) { + // pack with LZ only + CLZCompressor compLZ; + Pack(nmPacked, compLZ); + (int&)nmPacked.nm_mtType|=1<<6; + } else { + // no packing + SLONG slUnpackedSize = nm_slSize-sizeof(UBYTE); + void *pvUnpacked = nm_pubMessage+sizeof(UBYTE); + void *pvPacked = nmPacked.nm_pubMessage+sizeof(UBYTE); + nmPacked.nm_slSize = slUnpackedSize+sizeof(UBYTE); + memcpy(pvPacked, pvUnpacked, slUnpackedSize); + (int&)nmPacked.nm_mtType|=2<<6; + } + nmPacked.nm_pubMessage[0] = (UBYTE)nmPacked.nm_mtType; + + /* + // pack with RLE and LZ + CNetworkMessage nmPackedRLE(GetType()); + CRLEBBCompressor compRLE; + Pack(nmPackedRLE ,compRLE); + CLZCompressor compLZ; + nmPackedRLE.Pack(nmPacked, compLZ); + //*/ +} +void CNetworkMessage::UnpackDefault(CNetworkMessage &nmUnpacked) +{ + switch (nm_mtType>>6) { + case 0: { + // unpack with zlib only + CzlibCompressor compzlib; + Unpack(nmUnpacked,compzlib); + } break; + case 1: { + // unpack with LZ only + CLZCompressor compLZ; + Unpack(nmUnpacked,compLZ); + } break; + default: + case 2: { + // no unpacking + SLONG slPackedSize = nm_slSize-sizeof(UBYTE); + void *pvPacked = nm_pubMessage+sizeof(UBYTE); + void *pvUnpacked = nmUnpacked.nm_pubMessage+sizeof(UBYTE); + nmUnpacked.nm_slSize = slPackedSize+sizeof(UBYTE); + memcpy(pvUnpacked, pvPacked, slPackedSize); + } break; + } + + /* + // unpack with LZ and RLE + CNetworkMessage nmUnpackedLZ(GetType()); + CLZCompressor compLZ; + Unpack(nmUnpackedLZ,compLZ); + CRLEBBCompressor compRLE; + nmUnpackedLZ.Unpack(nmUnpacked, compRLE); + //*/ +} + +// dump message to console +void CNetworkMessage::Dump(void) +{ + CPrintF("Message size: %d\n", nm_slSize); + CPrintF("Message contents:"); + for(INDEX iByte=0; iByte=8) { + nm_iBit = 0; + } + iDstBit++; + if (iDstBit>=8) { + iDstBit = 0; + pubDstByte++; + } + } +} + +void CNetworkMessage::WriteBits(const void *pvBuffer, INDEX ctBits) +{ + const UBYTE *pubSrcByte = (const UBYTE *)pvBuffer; + // for each bit + INDEX iSrcBit = 0; + for (INDEX iBit=0; iBit=8) { + nm_iBit = 0; + } + iSrcBit++; + if (iSrcBit>=8) { + iSrcBit = 0; + pubSrcByte++; + } + } +} + +///////////////////////////////////////////////////////////////////// +// CNetworkStreamBlock + +/* + * Constructor for receiving -- uninitialized block. + */ +CNetworkStreamBlock::CNetworkStreamBlock(void) + : CNetworkMessage() + , nsb_iSequenceNumber(-1) +{ +} + +/* + * Constructor for sending -- empty packet with given type and sequence. + */ +CNetworkStreamBlock::CNetworkStreamBlock(MESSAGETYPE mtType, INDEX iSequenceNumber) + : CNetworkMessage(mtType) + , nsb_iSequenceNumber(iSequenceNumber) +{ +} + +/* + * Read a block from a received message. + */ +void CNetworkStreamBlock::ReadFromMessage(CNetworkMessage &nmToRead) +{ + // read sequence number from message + nmToRead>>nsb_iSequenceNumber; + ASSERT(nsb_iSequenceNumber>=0); + // read the block as a submessage + nmToRead.ExtractSubMessage(*this); +} + +/* + * Add a block to a message to send. + */ +void CNetworkStreamBlock::WriteToMessage(CNetworkMessage &nmToWrite) +{ + // write sequence number to message + ASSERT(nsb_iSequenceNumber>=0); + nmToWrite<>nsb_iSequenceNumber; + // read block size + strm>>nm_slSize; + // read block contents + strm.Read_t(nm_pubMessage, nm_slSize); + // init the message read/write pointer + nm_pubPointer = nm_pubMessage; + nm_iBit = 0; + // get the message type + UBYTE ubType = 0; + (*this)>>ubType; + nm_mtType = (MESSAGETYPE)ubType; +} + +///////////////////////////////////////////////////////////////////// +// CNetworkStream +/* + * Constructor. + */ +CNetworkStream::CNetworkStream(void) +{ +} + +/* + * Destructor. + */ +CNetworkStream::~CNetworkStream(void) +{ + // report number of blocks left in stream + //_RPT1(_CRT_WARN, "Destructing stream, %d blocks contained.\n", ns_lhBlocks.Count()); + // remove all blocks + Clear(); +} + +/* + * Clear the object (remove all blocks). + */ +void CNetworkStream::Clear(void) +{ + // for each block in list + FORDELETELIST(CNetworkStreamBlock, nsb_lnInStream, ns_lhBlocks, itnsbInList) { + // remove it from list + itnsbInList->nsb_lnInStream.Remove(); + // delete it + delete &*itnsbInList; + } +} +/* Copy from another network stream. */ +void CNetworkStream::Copy(CNetworkStream &nsOther) +{ + // for each block in list + FOREACHINLIST(CNetworkStreamBlock, nsb_lnInStream, nsOther.ns_lhBlocks, itnsb) { + // add it here + AddBlock(*itnsb); + } +} + +// get number of blocks used by this object +INDEX CNetworkStream::GetUsedBlocks(void) +{ + return ns_lhBlocks.Count(); +} + +// get amount of memory used by this object +SLONG CNetworkStream::GetUsedMemory(void) +{ + SLONG slMem = 0; + // for each block in list + FOREACHINLIST(CNetworkStreamBlock, nsb_lnInStream, ns_lhBlocks, itnsb) { + // add its usage + slMem+=sizeof(CNetworkStreamBlock)+itnsb->nm_slMaxSize; + } + return slMem; +} + +// get index of newest sequence stored +INDEX CNetworkStream::GetNewestSequence(void) +{ + // if the stream is empty + if (ns_lhBlocks.IsEmpty()) { + // return dummy + return -1; + } + // get head of list + CNetworkStreamBlock *pnsb = LIST_HEAD(ns_lhBlocks, CNetworkStreamBlock, nsb_lnInStream); + // return its index + return pnsb->nsb_iSequenceNumber; +} + +/* + * Add a block that is already allocated to the stream. + */ +void CNetworkStream::AddAllocatedBlock(CNetworkStreamBlock *pnsbBlock) +{ + // search all blocks already in list + FOREACHINLISTKEEP(CNetworkStreamBlock, nsb_lnInStream, ns_lhBlocks, itnsbInList) { + // if the block in list has same sequence as the one to add + if (itnsbInList->nsb_iSequenceNumber == pnsbBlock->nsb_iSequenceNumber) { + // just discard the new block + delete pnsbBlock; + return; + } + // if the block in list has lower sequence than the one to add + if (itnsbInList->nsb_iSequenceNumber < pnsbBlock->nsb_iSequenceNumber) { + // stop searching + break; + } + } + // add the new block before current one + itnsbInList.InsertBeforeCurrent(pnsbBlock->nsb_lnInStream); +} + +/* + * Add a block to the stream. + */ +void CNetworkStream::AddBlock(CNetworkStreamBlock &nsbBlock) +{ + // create a copy of the block + CNetworkStreamBlock *pnsbCopy = new CNetworkStreamBlock(nsbBlock); + // shrink it + pnsbCopy->Shrink(); + // add it to the list + AddAllocatedBlock(pnsbCopy); +} + +/* + * Read a block as a submessage from a message and add it to the stream. + */ +void CNetworkStream::ReadBlock(CNetworkMessage &nmMessage) +{ + // create an empty block + CNetworkStreamBlock *pnsbRead = new CNetworkStreamBlock(); + // read it from message + pnsbRead->ReadFromMessage(nmMessage); + // shrink it + pnsbRead->Shrink(); + // add it to the list + AddAllocatedBlock(pnsbRead); +} + +/* + * Get a block from stream by its sequence number. + */ +CNetworkStream::Result CNetworkStream::GetBlockBySequence( + INDEX iSequenceNumber, CNetworkStreamBlock *&pnsbBlock) +{ + BOOL bNewerFound = FALSE; + // search all blocks in list + FOREACHINLIST(CNetworkStreamBlock, nsb_lnInStream, ns_lhBlocks, itnsbInList) { + CNetworkStreamBlock &nsbInList = *itnsbInList; + // if the block in list has newer sequence + if (nsbInList.nsb_iSequenceNumber >= iSequenceNumber) { + // remember that at least one newer block was found + bNewerFound = TRUE; + } + + // if the block in list has wanted sequence + if (nsbInList.nsb_iSequenceNumber == iSequenceNumber) { + // return it + pnsbBlock = itnsbInList; + return R_OK; + } + // if the block in list has older sequence + if (nsbInList.nsb_iSequenceNumber < iSequenceNumber) { + // stop searching + break; + } + } + + // ...if none found + + // if some block of newer sequence number was found + if (bNewerFound) { + // return that the block is missing (probably should be resent) + pnsbBlock = NULL; + return R_BLOCKMISSING; + // if no newer blocks were found + } else { + // we assume that the wanted block is not yet received + pnsbBlock = NULL; + return R_BLOCKNOTRECEIVEDYET; + } +} + +// find oldest block after given one (for batching missing sequences) +INDEX CNetworkStream::GetOldestSequenceAfter(INDEX iSequenceNumber) +{ + // block are sorted newer first, so we just remember the last block found + // until we find the given one + INDEX iOldest = iSequenceNumber; + FOREACHINLIST(CNetworkStreamBlock, nsb_lnInStream, ns_lhBlocks, itnsb) { + CNetworkStreamBlock &nsb = *itnsb; + if (nsb.nsb_iSequenceNumberWriteToMessage(nmMessage); + iBlock++; + if (iBlock>=ctBlocks) { + return iBlock; + } + } + return iBlock; +} + +/* + * Remove all blocks but the given number of newest ones. + */ +void CNetworkStream::RemoveOlderBlocks(INDEX ctBlocksToKeep) +{ + // for each block in list + INDEX iBlock = 0; + FORDELETELIST(CNetworkStreamBlock, nsb_lnInStream, ns_lhBlocks, itnsbInList) { + iBlock++; + // if it is older that given count + if (iBlock>ctBlocksToKeep) { + // remove it from list + itnsbInList->nsb_lnInStream.Remove(); + // delete it + delete &*itnsbInList; + } + } +} + +/* Remove all blocks with sequence older than given. */ +void CNetworkStream::RemoveOlderBlocksBySequence(INDEX iLastSequenceToKeep) +{ + // while there are any blocks in the list + while(!ns_lhBlocks.IsEmpty()) { + // get the tail of the list + CNetworkStreamBlock *pnsb = LIST_TAIL(ns_lhBlocks, CNetworkStreamBlock, nsb_lnInStream); + // if it is not too old + if (pnsb->nsb_iSequenceNumber >= iLastSequenceToKeep) { + // stop + break; + } + // remove the tail + delete pnsb; + }; +} + +///////////////////////////////////////////////////////////////////// +// CPlayerAction + +CPlayerAction::CPlayerAction(void) +{ + Clear(); +} + +/* + * Clear the object (this sets up no actions). + */ +void CPlayerAction::Clear(void) +{ + pa_vTranslation = FLOAT3D(0.0f,0.0f,0.0f); + pa_aRotation = ANGLE3D(0,0,0); + pa_aViewRotation = ANGLE3D(0,0,0); + pa_ulButtons = 0; + pa_llCreated = 0; +} +// normalize action (remove invalid floats like -0) +void CPlayerAction::Normalize(void) +{ + volatile FLOAT *pf = (FLOAT*)&pa_vTranslation; + for (INDEX i=0; i<9; i++) { + if (*pf==0) { + *pf=0; + } + pf++; + } +} +// create a checksum value for sync-check +void CPlayerAction::ChecksumForSync(ULONG &ulCRC) +{ + CRC_AddBlock(ulCRC, (UBYTE*)this, sizeof(this)); +} + +#define DUMPVECTOR(v) \ + strm.FPrintF_t(#v ": %g,%g,%g %08x,%08x,%08x\n", \ + (v)(1), (v)(2), (v)(3), (ULONG&)(v)(1), (ULONG&)(v)(2), (ULONG&)(v)(3)) +#define DUMPLONG(l) \ + strm.FPrintF_t(#l ": %08x\n", l) + +// dump sync data to text file +void CPlayerAction::DumpSync_t(CTStream &strm) // throw char * +{ + DUMPVECTOR(pa_vTranslation); + DUMPVECTOR(pa_aRotation); + DUMPVECTOR(pa_aViewRotation); + DUMPLONG(pa_ulButtons); +} + +void CPlayerAction::Lerp(const CPlayerAction &pa0, const CPlayerAction &pa1, FLOAT fFactor) +{ + pa_vTranslation = ::Lerp(pa0.pa_vTranslation , pa1.pa_vTranslation , fFactor); + pa_aRotation = ::Lerp(pa0.pa_aRotation , pa1.pa_aRotation , fFactor); + pa_aViewRotation = ::Lerp(pa0.pa_aViewRotation, pa1.pa_aViewRotation, fFactor); + pa_ulButtons = pa1.pa_ulButtons; +} + +// player action compression algorithm: +// - all axes (9 of them) are compressed as one bit telling whether the axis value is used +// if that bit is ==0, then the axis value is 0.0, if it is 1, the value follows in next 32 +// bits +// - the flags are compressed by preceding them with a bit sequence telling how many bits +// are saved after that: +// (0) 1 = no bits follow, value is 0 +// (1) 01 = no bits follow, value is 1 +// (2-3) 001 = 1 bit follows, value is 1x where x is the given bit +// (4-15) 0001 = 4 bit value follows +// (16-255) 00001 = 8 bit value follows +// (256-65535) 000001 = 16 bit value follows +// (65536-) 000000 = 32 bit value follows +// note: above bits are ordered in reverse as they come when scanning bit by bit + +/* Write an object into message. */ +CNetworkMessage &operator<<(CNetworkMessage &nm, const CPlayerAction &pa) +{ + nm.Write(&pa.pa_llCreated, sizeof(pa.pa_llCreated)); + + const ULONG *pul = (const ULONG*)&pa.pa_vTranslation; + for (INDEX i=0; i<9; i++) { + if (*pul==0) { + UBYTE ub=0; + nm.WriteBits(&ub, 1); + } else { + UBYTE ub=1; + nm.WriteBits(&ub, 1); + nm.WriteBits(pul, 32); + } + pul++; + } + ULONG ulFlags = pa.pa_ulButtons; + + // (0) 1 = no bits follow, value is 0 + if (ulFlags==0) { + UBYTE ub=1; + nm.WriteBits(&ub, 1); + // (1) 01 = no bits follow, value is 1 + } else if (ulFlags==1) { + UBYTE ub=2; + nm.WriteBits(&ub, 2); + // (2-3) 001 = 1 bit follows, value is 1x where x is the given bit + } else if (ulFlags <= 3) { + UBYTE ub=4; + nm.WriteBits(&ub, 3); + nm.WriteBits(&ulFlags, 1); + // (4-15) 0001 = 4 bit value follows + } else if (ulFlags <= 15) { + UBYTE ub=8; + nm.WriteBits(&ub, 4); + nm.WriteBits(&ulFlags, 4); + // (16-255) 00001 = 8 bit value follows + } else if (ulFlags <= 255) { + UBYTE ub=16; + nm.WriteBits(&ub, 5); + nm.WriteBits(&ulFlags, 8); + // (256-65535) 000001 = 16 bit value follows + } else if (ulFlags <= 65535) { + UBYTE ub=32; + nm.WriteBits(&ub, 6); + nm.WriteBits(&ulFlags, 16); + // (65536-) 000000 = 32 bit value follows + } else { + UBYTE ub=0; + nm.WriteBits(&ub, 6); + nm.WriteBits(&ulFlags, 32); + } + return nm; +} +/* Read an object from message. */ +CNetworkMessage &operator>>(CNetworkMessage &nm, CPlayerAction &pa) +{ + nm.Read(&pa.pa_llCreated, sizeof(pa.pa_llCreated)); + + ULONG *pul = (ULONG*)&pa.pa_vTranslation; + for (INDEX i=0; i<9; i++) { + UBYTE ub = 0; + nm.ReadBits(&ub, 1); + if (ub==0) { + *pul = 0; + } else { + nm.ReadBits(pul, 32); + } + pul++; + } + + // find number of zero bits for flags + INDEX iZeros=0; + for(; iZeros<6; iZeros++) { + UBYTE ub=0; + nm.ReadBits(&ub, 1); + if (ub!=0) { + break; + } + } + ULONG ulFlags = 0; + // now read flags according to the number of bits + // (0) 1 = no bits follow, value is 0 + if (iZeros==0) { + ulFlags = 0; + // (1) 01 = no bits follow, value is 1 + } else if (iZeros==1) { + ulFlags = 1; + // (2-3) 001 = 1 bit follows, value is 1x where x is the given bit + } else if (iZeros==2) { + ulFlags = 0; + nm.ReadBits(&ulFlags, 1); + ulFlags |= 2; + // (4-15) 0001 = 4 bit value follows + } else if (iZeros==3) { + ulFlags = 0; + nm.ReadBits(&ulFlags, 4); + // (16-255) 00001 = 8 bit value follows + } else if (iZeros==4) { + ulFlags = 0; + nm.ReadBits(&ulFlags, 8); + // (256-65535) 000001 = 16 bit value follows + } else if (iZeros==5) { + ulFlags = 0; + nm.ReadBits(&ulFlags, 16); + // (65536-) 000000 = 32 bit value follows + } else { + ulFlags = 0; + nm.ReadBits(&ulFlags, 32); + } + pa.pa_ulButtons = ulFlags; + return nm; +} +/* Write an object into stream. */ +CTStream &operator<<(CTStream &strm, const CPlayerAction &pa) +{ + strm.Write_t(&pa,sizeof(pa)); + return strm; +} +/* Read an object from stream. */ +CTStream &operator>>(CTStream &strm, CPlayerAction &pa) +{ + strm.Read_t(&pa,sizeof(pa)); + return strm; +} diff --git a/Sources/Engine/Network/NetworkMessage.h b/Sources/Engine/Network/NetworkMessage.h new file mode 100644 index 0000000..71a166d --- /dev/null +++ b/Sources/Engine/Network/NetworkMessage.h @@ -0,0 +1,298 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_NETWORKMESSAGE_H +#define SE_INCL_NETWORKMESSAGE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +// message type +// transmitted as 6-bit value +// up to 64 values allowed +// upper 2 bits are used to indicate compression used + +// ADD NEW MESSAGE TYPES TO THE END!!! +typedef enum NetworkMessageType { + // broadcast requesting server infos + MSG_REQ_ENUMSERVERS, + MSG_SERVERINFO, + + MSG_KEEPALIVE, // sent when there's nothing else to send - just to keep connections valid + + // disconnection explanation from server + MSG_INF_DISCONNECTED, + + // info message with pings of all players + MSG_INF_PINGS, + + // main session state connecting to server + MSG_REQ_CONNECTLOCALSESSIONSTATE, + MSG_REP_CONNECTLOCALSESSIONSTATE, + + // remote session state connecting to server + MSG_REQ_CONNECTREMOTESESSIONSTATE, + MSG_REP_CONNECTREMOTESESSIONSTATE, + + // remote session requesting current state delta from original + MSG_REQ_STATEDELTA, + MSG_REP_STATEDELTA, + + // client initialing CRC check + MSG_REQ_CRCLIST, + MSG_REQ_CRCCHECK, + MSG_REP_CRCCHECK, + + // player connecting to server + MSG_REQ_CONNECTPLAYER, + MSG_REP_CONNECTPLAYER, + + MSG_REQ_PAUSE, // request pause/unpause game + + // request character change for a player + MSG_REQ_CHARACTERCHANGE, + + // action packet from client to server + MSG_ACTION, + // data to check for lost synchronization (client to server) + MSG_SYNCCHECK, + // a copy of action stored for prediction + MSG_ACTIONPREDICT, + + // sequenced packets from server to session states + MSG_SEQ_ALLACTIONS, // packed actions of all players from server to clients + MSG_SEQ_ADDPLAYER, // instructions for adding a new player to session states + MSG_SEQ_REMPLAYER, // instructions for removing a new player from session states + MSG_SEQ_PAUSE, // game was paused/unpaused + MSG_SEQ_CHARACTERCHANGE, // a player has changed character + + MSG_GAMESTREAMBLOCKS, // packet with one or more game stream messages + MSG_REQUESTGAMESTREAMRESEND, // request for resend of a game stream message + + // chat messages + MSG_CHAT_IN, // chat request from client to server + MSG_CHAT_OUT, // chat message routed to certain clients + + // parameter setting messages + MSG_SET_CLIENTSETTINGS, // adjust server side settings of a client + + // remote administration + MSG_ADMIN_COMMAND, // c2s incoming console command request + MSG_ADMIN_RESPONSE, // s2c results of the console command + + MSG_EXTRA = '/', // used for special communications like rcon and similar + + + // added to the end so that it would not mess up old numbering - that would corrupt demo playing + // disconnection confirmation from the client + MSG_REP_DISCONNECTED, + + +} MESSAGETYPE; + +extern struct ErrorTable MessageTypes; + +/* + * Holder for network message, can be read/written like a stream. + */ +class ENGINE_API CNetworkMessage { +public: + MESSAGETYPE nm_mtType; // type of this message + +#define MAX_NETWORKMESSAGE_SIZE 2048 // max. length of message buffer + UBYTE *nm_pubMessage; // the message data itself + SLONG nm_slMaxSize; // size of message buffer + + UBYTE *nm_pubPointer; // pointer for reading/writing message + SLONG nm_slSize; // size of message + INDEX nm_iBit; // next bit index to read/write (0 if not reading/writing bits) +public: + /* Constructor for empty message (for receiving). */ + CNetworkMessage(void); + /* Constructor for initializing message that is to be sent. */ + CNetworkMessage(MESSAGETYPE mtType); + /* Copying. */ + CNetworkMessage(const CNetworkMessage &nmOriginal); + void operator=(const CNetworkMessage &nmOriginal); + /* Destructor. */ + ~CNetworkMessage(void); + // reinit a message that is to be sent (to write different contents) + void Reinit(void); + + /* Ignore the contents of this message. */ + void IgnoreContents(void); + // dump message to console + void Dump(void); + + /* Get the type of this message. */ + inline MESSAGETYPE GetType(void) const { ASSERT(this!=NULL); return MESSAGETYPE(nm_mtType&0x3F); }; + /* Check if end of message. */ + BOOL EndOfMessage(void); + // rewind message to start, so that written message can be read again + void Rewind(void); + + /* Pack a message to another message (message type is left untouched). */ + void Pack(CNetworkMessage &nmPacked, CCompressor &comp); + void PackDefault(CNetworkMessage &nmPacked); + /* Unpack a message to another message (message type is left untouched). */ + void Unpack(CNetworkMessage &nmUnpacked, CCompressor &comp); + void UnpackDefault(CNetworkMessage &nmUnpacked); + + // read/write functions + void Read(void *pvBuffer, SLONG slSize); + void Write(const void *pvBuffer, SLONG slSize); + void ReadBits(void *pvBuffer, INDEX ctBits); + void WriteBits(const void *pvBuffer, INDEX ctBits); + + /* Read an object from message. */ + inline CNetworkMessage &operator>>(float &f) { Read( &f, sizeof( f)); return *this; } + inline CNetworkMessage &operator>>(ULONG &ul) { Read(&ul, sizeof(ul)); return *this; } + inline CNetworkMessage &operator>>(UWORD &uw) { Read(&uw, sizeof(uw)); return *this; } + inline CNetworkMessage &operator>>(UBYTE &ub) { Read(&ub, sizeof(ub)); return *this; } + inline CNetworkMessage &operator>>(SLONG &sl) { Read(&sl, sizeof(sl)); return *this; } + inline CNetworkMessage &operator>>(SWORD &sw) { Read(&sw, sizeof(sw)); return *this; } + inline CNetworkMessage &operator>>(SBYTE &sb) { Read(&sb, sizeof(sb)); return *this; } + inline CNetworkMessage &operator>>(MESSAGETYPE &mt) { Read(&mt, sizeof(mt)); return *this; } + CNetworkMessage &operator>>(CTString &str); + /* Write an object into message. */ + inline CNetworkMessage &operator<<(const float &f) { Write( &f, sizeof( f)); return *this; } + inline CNetworkMessage &operator<<(const double &d) { Write( &d, sizeof( d)); return *this; } + inline CNetworkMessage &operator<<(const ULONG &ul) { Write(&ul, sizeof(ul)); return *this; } + inline CNetworkMessage &operator<<(const UWORD &uw) { Write(&uw, sizeof(uw)); return *this; } + inline CNetworkMessage &operator<<(const UBYTE &ub) { Write(&ub, sizeof(ub)); return *this; } + inline CNetworkMessage &operator<<(const SLONG &sl) { Write(&sl, sizeof(sl)); return *this; } + inline CNetworkMessage &operator<<(const SWORD &sw) { Write(&sw, sizeof(sw)); return *this; } + inline CNetworkMessage &operator<<(const SBYTE &sb) { Write(&sb, sizeof(sb)); return *this; } + inline CNetworkMessage &operator<<(const MESSAGETYPE &mt) { Write(&mt, sizeof(mt)); return *this; } + CNetworkMessage &operator<<(const CTString &str); + + /* Insert a sub-message into this message. */ + void InsertSubMessage(const CNetworkMessage &nmSubMessage); + /* Extract a sub-message from this message. */ + void ExtractSubMessage(CNetworkMessage &nmSubMessage); + + // shrink message buffer to exactly fit contents + void Shrink(void); +}; + +/* + * A message block used for streaming data across network. + * + * These can be received duplicated or misordered. They + * are resequenced at the receive side as needed. Can be sent more than one + * together as submessages in a message and duplicated across messages as a + * compensation for eventual packet loss. + */ +class CNetworkStreamBlock : public CNetworkMessage { +public: + CListNode nsb_lnInStream; // node in list of blocks in stream +public: + INDEX nsb_iSequenceNumber; // index for sorting in list +public: + /* Constructor for receiving -- uninitialized block. */ + CNetworkStreamBlock(void); + /* Constructor for sending -- empty packet with given type and sequence. */ + CNetworkStreamBlock(MESSAGETYPE mtType, INDEX iSequenceNumber); + + /* Read a block from a received message. */ + void ReadFromMessage(CNetworkMessage &nmToRead); + /* Add a block to a message to send. */ + void WriteToMessage(CNetworkMessage &nmToWrite); + + /* Remove the block from stream. */ + void RemoveFromStream(void); + + /* Read/write the block from file stream. */ + void Read_t(CTStream &strm); // throw char * + void Write_t(CTStream &strm); // throw char * +}; + +/* + * Stream of message blocks that can be sent across network. + */ +class CNetworkStream { +public: + enum Result { + R_OK = 1, + R_BLOCKMISSING, // block is missing in the stream + R_BLOCKNOTRECEIVEDYET, // block is not yet received + }; +public: + CListHead ns_lhBlocks; // list of blocks of this stream (higher sequences first) + + /* Add a block that is already allocated to the stream. */ + void AddAllocatedBlock(CNetworkStreamBlock *pnsbBlock); +public: + /* Constructor. */ + CNetworkStream(void); + /* Destructor. */ + ~CNetworkStream(void); + /* Clear the object (remove all blocks). */ + void Clear(void); + /* Copy from another network stream. */ + void Copy(CNetworkStream &nsOther); + // get number of blocks used by this object + INDEX GetUsedBlocks(void); + // get amount of memory used by this object + SLONG GetUsedMemory(void); + // get index of newest sequence stored + INDEX GetNewestSequence(void); + + /* Add a block to the stream (makes a copy of block). */ + void AddBlock(CNetworkStreamBlock &nsbBlock); + /* Read a block as a submessage from a message and add it to the stream. */ + void ReadBlock(CNetworkMessage &nmMessage); + /* Get a block from stream by its sequence number. */ + CNetworkStream::Result GetBlockBySequence( + INDEX iSequenceNumber, CNetworkStreamBlock *&pnsbBlock); + // find oldest block after given one (for batching missing sequences) + INDEX GetOldestSequenceAfter(INDEX iSequenceNumber); + + /* Write given number of newest blocks to a message. */ + INDEX WriteBlocksToMessage(CNetworkMessage &nmMessage, INDEX ctBlocks); + /* Remove all blocks but the given number of newest ones. */ + void RemoveOlderBlocks(INDEX ctBlocksToKeep); + /* Remove all blocks with sequence older than given. */ + void RemoveOlderBlocksBySequence(INDEX iLastSequenceToKeep); +}; + +class ENGINE_API CPlayerAction { +public: + // order is important for compression and normalization - do not reorder! + FLOAT3D pa_vTranslation; + ANGLE3D pa_aRotation; + ANGLE3D pa_aViewRotation; + ULONG pa_ulButtons; // 32 bits for action buttons (application defined) + // keep flags that are likely to be changed/set more often at lower bits, + // so that better compression can be achieved for network transmission + __int64 pa_llCreated; // when was created (for ping calc.) in ms + +public: + CPlayerAction(void); + /* Clear the object (this sets up no actions). */ + void Clear(void); + // normalize action (remove invalid floats like -0) + void Normalize(void); + + // create a checksum value for sync-check + void ChecksumForSync(ULONG &ulCRC); + // dump sync data to text file + void DumpSync_t(CTStream &strm); // throw char * + + void Lerp(const CPlayerAction &pa0, const CPlayerAction &pa1, FLOAT fFactor); + + /* Write an object into message. */ + friend CNetworkMessage &operator<<(CNetworkMessage &nm, const CPlayerAction &pa); + /* Read an object from message. */ + friend CNetworkMessage &operator>>(CNetworkMessage &nm, CPlayerAction &pa); + /* Write an object into stream. */ + friend CTStream &operator<<(CTStream &strm, const CPlayerAction &pa); + /* Read an object from stream. */ + friend CTStream &operator>>(CTStream &strm, CPlayerAction &pa); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/NetworkProfile.cpp b/Sources/Engine/Network/NetworkProfile.cpp new file mode 100644 index 0000000..39bae3d --- /dev/null +++ b/Sources/Engine/Network/NetworkProfile.cpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +// profile form for profiling world editing +CNetworkProfile npNetworkProfile; +CProfileForm &_pfNetworkProfile = npNetworkProfile; + +CNetworkProfile::CNetworkProfile(void) + : CProfileForm("Network", "ticks", + CNetworkProfile::PCI_COUNT, CNetworkProfile::PTI_COUNT) +{ + // initialize network profile form + SETTIMERNAME(CNetworkProfile::PTI_MAINLOOP, "MainLoop()", ""); + SETTIMERNAME(CNetworkProfile::PTI_TIMERLOOP, "TimerLoop()", ""); + SETTIMERNAME(CNetworkProfile::PTI_SERVER_LOOP, "ServerLoop()", ""); + SETTIMERNAME(CNetworkProfile::PTI_SESSIONSTATE_LOOP, "SessionStateLoop()", ""); + SETTIMERNAME(CNetworkProfile::PTI_SESSIONSTATE_PROCESSGAMESTREAM, "CSessionState::ProcessGameStream()", ""); + SETTIMERNAME(CNetworkProfile::PTI_SENDMESSAGE, "Send()", ""); + SETTIMERNAME(CNetworkProfile::PTI_RECEIVEMESSAGE, "Receive()", ""); + + SETCOUNTERNAME(CNetworkProfile::PCI_GAMESTREAMRESENDS, "game stream resends"); + + SETCOUNTERNAME(CNetworkProfile::PCI_GAMESTREAM_BYTES_SENT, "gamestream bytes sent"); + SETCOUNTERNAME(CNetworkProfile::PCI_GAMESTREAM_BYTES_RECEIVED, "gamestream bytes received"); + SETCOUNTERNAME(CNetworkProfile::PCI_ACTION_BYTES_SENT, "action bytes sent"); + SETCOUNTERNAME(CNetworkProfile::PCI_ACTION_BYTES_RECEIVED, "action bytes received"); + + SETCOUNTERNAME(CNetworkProfile::PCI_MESSAGESSENT, "messages sent"); + SETCOUNTERNAME(CNetworkProfile::PCI_MESSAGESRECEIVED, "messages received"); + SETCOUNTERNAME(CNetworkProfile::PCI_BYTESSENT, "bytes sent"); + SETCOUNTERNAME(CNetworkProfile::PCI_BYTESRECEIVED, "bytes received"); +} diff --git a/Sources/Engine/Network/NetworkProfile.h b/Sources/Engine/Network/NetworkProfile.h new file mode 100644 index 0000000..8fab5ad --- /dev/null +++ b/Sources/Engine/Network/NetworkProfile.h @@ -0,0 +1,39 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef __ENGINE_BASE_PROFILING_H__ +#include +#endif + +/* Class for holding profiling information for network. */ +class CNetworkProfile : public CProfileForm { +public: + // indices for profiling counters and timers + enum ProfileTimerIndex { + PTI_MAINLOOP, // time spent in main game loop + PTI_TIMERLOOP, // time spent in timer game loop + + PTI_SERVER_LOOP, // time server spent processing messages + PTI_SESSIONSTATE_LOOP, // time session state spent processing messages + PTI_SESSIONSTATE_PROCESSGAMESTREAM, // time session state spent processing gamestream (includes physics) + + PTI_SENDMESSAGE, // time spend sending message + PTI_RECEIVEMESSAGE, // time spend receiving message + PTI_COUNT + }; + enum ProfileCounterIndex { + PCI_GAMESTREAMRESENDS, // how many times gamestream block was resent from server + + PCI_GAMESTREAM_BYTES_SENT, // bytes sent in gamestream messages + PCI_GAMESTREAM_BYTES_RECEIVED, // bytes received in gamestream messages + PCI_ACTION_BYTES_SENT, // bytes sent in action messages + PCI_ACTION_BYTES_RECEIVED, // bytes received in action messages + + PCI_MESSAGESSENT, // total number of messages sent + PCI_MESSAGESRECEIVED, // total number of messages received + PCI_BYTESSENT, // total number of bytes sent + PCI_BYTESRECEIVED, // total number of bytes received + PCI_COUNT + }; + // constructor + CNetworkProfile(void); +}; diff --git a/Sources/Engine/Network/Packet.cpp b/Sources/Engine/Network/Packet.cpp new file mode 100644 index 0000000..fe22ce8 --- /dev/null +++ b/Sources/Engine/Network/Packet.cpp @@ -0,0 +1,686 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include + +#include + +// should the packet transfers in/out of the buffer be reported to the console +extern INDEX net_bReportPackets; +extern INDEX net_iMaxSendRetries; +extern FLOAT net_fSendRetryWait; + +#define MAX_RETRIES 10 +#define RETRY_INTERVAL 3.0f + +// make the address broadcast +void CAddress::MakeBroadcast(void) +{ + adr_ulAddress = INADDR_BROADCAST; + extern INDEX net_iPort; + adr_uwPort = net_iPort; + adr_uwID = 0; +} + + + +/* +* +* CPacket class implementation +* +*/ + +// copy constructor +CPacket::CPacket(CPacket &paOriginal) +{ + + ASSERT(paOriginal.pa_pubPacketData != NULL && paOriginal.pa_slSize > 0); + + pa_slSize = paOriginal.pa_slSize; + pa_slTransferSize = paOriginal.pa_slTransferSize; + + pa_ulSequence = paOriginal.pa_ulSequence; + pa_ubReliable = paOriginal.pa_ubReliable; + pa_tvSendWhen = paOriginal.pa_tvSendWhen; + pa_ubRetryNumber = paOriginal.pa_ubRetryNumber; + pa_adrAddress.adr_ulAddress = paOriginal.pa_adrAddress.adr_ulAddress; + pa_adrAddress.adr_uwPort = paOriginal.pa_adrAddress.adr_uwPort; + pa_adrAddress.adr_uwID = paOriginal.pa_adrAddress.adr_uwID; + + memcpy(pa_pubPacketData,paOriginal.pa_pubPacketData,pa_slSize); + +}; + +// initialization of the packet - clear all data and remove the packet from any list (buffer) it is in +void CPacket::Clear() +{ + + pa_slSize = 0; + pa_slTransferSize = 0; + pa_ubReliable = UDP_PACKET_UNRELIABLE; + pa_ubRetryNumber = 0; + + pa_tvSendWhen = CTimerValue(0.0f); + if(pa_lnListNode.IsLinked()) pa_lnListNode.Remove(); + +}; + +void CPacket::operator=(const CPacket &paOriginal) +{ + ASSERT(paOriginal.pa_pubPacketData != NULL && paOriginal.pa_slSize > 0); + + pa_slSize = paOriginal.pa_slSize; + pa_slTransferSize = paOriginal.pa_slTransferSize; + + pa_ulSequence = paOriginal.pa_ulSequence; + pa_ubReliable = paOriginal.pa_ubReliable; + pa_tvSendWhen = paOriginal.pa_tvSendWhen; + pa_ubRetryNumber = paOriginal.pa_ubRetryNumber; + pa_adrAddress.adr_ulAddress = paOriginal.pa_adrAddress.adr_ulAddress; + pa_adrAddress.adr_uwPort = paOriginal.pa_adrAddress.adr_uwPort; + pa_adrAddress.adr_uwID = paOriginal.pa_adrAddress.adr_uwID; + + memcpy(pa_pubPacketData,paOriginal.pa_pubPacketData,pa_slSize); + +}; + + +// Takes data from a pointer, adds the packet header and copies the data to the packet +BOOL CPacket::WriteToPacket(void* pv,SLONG slSize,UBYTE ubReliable,ULONG ulSequence,UWORD uwClientID,SLONG slTransferSize) +{ + UBYTE* pubData; + + ASSERT(slSize <= MAX_UDP_BLOCK_SIZE && slSize > 0); + ASSERT(pv != NULL); + ASSERT(slTransferSize >= slSize); + + // set packet properties to values received as parameters + pa_ubReliable = ubReliable; + pa_adrAddress.adr_uwID = uwClientID; + pa_ulSequence = ulSequence; + pa_slSize = slSize + MAX_HEADER_SIZE; + pa_slTransferSize = slTransferSize; + + // insert packet header to the beginning of the packet data + pubData = pa_pubPacketData; + *pubData = pa_ubReliable; + pubData++; + + *(ULONG*)pubData = pa_ulSequence; + pubData+=sizeof(pa_ulSequence); + + *(UWORD*)pubData = pa_adrAddress.adr_uwID; + pubData+=sizeof(pa_adrAddress.adr_uwID); + + *(SLONG*)pubData = pa_slTransferSize; + pubData+=sizeof(pa_slTransferSize); + + // copy the data the packet is to contain + memcpy(pubData,pv,slSize); + + + + return TRUE; + +}; + + +// Takes data from a pointer, reads the packet header and copies the data to the packet +BOOL CPacket::WriteToPacketRaw(void* pv,SLONG slSize) +{ + UBYTE* pubData; + + ASSERT(slSize <= MAX_PACKET_SIZE && slSize > 0); + ASSERT(pv != NULL); + + // get the packet properties from the pointer, and set the values + pubData = (UBYTE*)pv; + pa_ubReliable = *pubData; + pubData++; + pa_ulSequence = *(ULONG*)pubData; + pubData+=sizeof(pa_ulSequence); + pa_adrAddress.adr_uwID = *(UWORD*)pubData; + pubData+=sizeof(pa_adrAddress.adr_uwID); + pa_slTransferSize = *(SLONG*)pubData; + pubData+=sizeof(pa_slTransferSize); + + pa_slSize = slSize; + + // transfer the data to the packet + memcpy(pa_pubPacketData,pv,pa_slSize); + + return TRUE; + +}; + + +// Copies the data from the packet to the location specified by the *pv. +// packet header data is skipped +BOOL CPacket::ReadFromPacket(void* pv,SLONG &slExpectedSize) +{ + UBYTE* pubData; + + ASSERT(slExpectedSize > 0); + ASSERT(pv != NULL); + ASSERT(pa_pubPacketData != NULL); + + if (slExpectedSize < (pa_slSize - MAX_HEADER_SIZE)) { + return FALSE; + } + + // how much data is actually returned + slExpectedSize = pa_slSize - MAX_HEADER_SIZE; + + // skip the header data + pubData = pa_pubPacketData + sizeof(pa_ubReliable) + sizeof(pa_ulSequence) + sizeof(pa_adrAddress.adr_uwID) + sizeof(pa_slTransferSize); + + memcpy(pv,pubData,slExpectedSize); + + return TRUE; + +}; + +// is the packet reliable? +BOOL CPacket::IsReliable() +{ + return pa_ubReliable; +}; + +// is the packet a head of a reliable stream +BOOL CPacket::IsReliableHead() +{ + return pa_ubReliable & UDP_PACKET_RELIABLE_HEAD; +}; + +// is the packet a tail of a reliable stream +BOOL CPacket::IsReliableTail() +{ + return pa_ubReliable & UDP_PACKET_RELIABLE_TAIL; +}; + +// return the sequence of a packet +ULONG CPacket::GetSequence() +{ + ASSERT(pa_ubReliable); + return pa_ulSequence; +}; + +// return the retry status of a packet - can retry now, later or not at all +UBYTE CPacket::CanRetry() +{ + + if (pa_ubRetryNumber >= net_iMaxSendRetries) { + return RS_NOTATALL; + } + + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + + if (tvNow < (pa_tvSendWhen + CTimerValue(net_fSendRetryWait * (pa_ubRetryNumber + 1)))) { + return RS_NOTNOW; + } + + return RS_NOW; + +}; + +//drop the packet from a list (buffer) +void CPacket::Drop() +{ + if (pa_lnListNode.IsLinked()) { + pa_lnListNode.Remove(); + } +}; + +SLONG CPacket::GetTransferSize() +{ + return pa_slTransferSize; +}; + +BOOL CPacket::IsBroadcast() +{ + if (pa_adrAddress.adr_uwID == '//' || pa_adrAddress.adr_uwID == 0) { + return TRUE; + } + + return FALSE; + +}; + + +/* +* +* +* CPacketBufferStats Class implementation +* +* +*/ + +// this class is used for MaxBPS limitation (prevets flooding the client) and for bandwidth limit and latency emulation +void CPacketBufferStats::Clear(void) +{ + + pbs_fBandwidthLimit = 0; + pbs_fLatencyLimit = 0.0f; + pbs_fLatencyVariation = 0.0f; + pbs_tvTimeNextPacketStart = _pTimer->GetHighPrecisionTimer(); + +}; + +// when can a certian ammount of data be sent? +CTimerValue CPacketBufferStats::GetPacketSendTime(SLONG slSize) +{ + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + + // calculate how much should the packet be delayed due to latency and due to bandwidth + CTimerValue tvBandwidth; + if (pbs_fBandwidthLimit<=0.0f) { + tvBandwidth = CTimerValue(0.0); + } else { + tvBandwidth = CTimerValue(DOUBLE((slSize*8)/pbs_fBandwidthLimit)); + } + CTimerValue tvLatency; + if (pbs_fLatencyLimit<=0.0f && pbs_fLatencyVariation<=0.0f) { + tvLatency = CTimerValue(0.0); + } else { + tvLatency = CTimerValue(DOUBLE(pbs_fLatencyLimit+(pbs_fLatencyVariation*rand())/RAND_MAX)); + } + + // time when the packet should be sent is max of + CTimerValue tvStart( + Max( + // current time plus latency and + (tvNow+tvLatency).tv_llValue, + // next free point in time + pbs_tvTimeNextPacketStart.tv_llValue)); + // remember next free time and return it + pbs_tvTimeNextPacketStart = tvStart+tvBandwidth; + return pbs_tvTimeNextPacketStart; + +}; + + + + +/* +* +* CPacketBuffer Class implementation +* +*/ + + +// Empty the packet buffer +void CPacketBuffer::Clear() +{ + + pb_lhPacketStorage.Clear(); + + pb_ulNumOfPackets = 0; + pb_ulNumOfReliablePackets = 0; + pb_ulTotalSize = 0; + pb_ulLastSequenceOut = 0; + + pb_pbsLimits.Clear(); + +}; + + +// Is the packet buffer empty? +BOOL CPacketBuffer::IsEmpty() +{ + + if (pb_ulNumOfPackets>0) { + return FALSE; + } + + return TRUE; +}; + + +// Calculate when the packet can be output from the buffer +CTimerValue CPacketBuffer::GetPacketSendTime(SLONG slSize) { + CTimerValue tvSendTime; + + // if traffic emulation is in use, use the time with the lower bandwidth limit + if (pb_ppbsStats != NULL) { + if (pb_ppbsStats->pbs_fBandwidthLimit > 0.0f && pb_ppbsStats->pbs_fBandwidthLimit < pb_pbsLimits.pbs_fBandwidthLimit) { + tvSendTime = pb_ppbsStats->GetPacketSendTime(slSize); + pb_pbsLimits.pbs_tvTimeNextPacketStart = tvSendTime; + } else { + tvSendTime = pb_pbsLimits.GetPacketSendTime(slSize); + pb_ppbsStats->pbs_tvTimeNextPacketStart = tvSendTime; + } + // else just use the MaxBPS control + } else { + tvSendTime = pb_pbsLimits.GetPacketSendTime(slSize); + } + + return tvSendTime; +}; + +// Adds the packet to the end of the list +BOOL CPacketBuffer::AppendPacket(CPacket &paPacket,BOOL bDelay) +{ + + // bDelay regulates if the packet should be delayed because of the bandwidth limits or not + // internal buffers (reliable, waitack and master buffers) do not pay attention to bandwidth limits + if (bDelay) { + paPacket.pa_tvSendWhen = GetPacketSendTime(paPacket.pa_slSize); + } else { + paPacket.pa_tvSendWhen = _pTimer->GetHighPrecisionTimer(); + } + + // Add the packet to the end of the list + pb_lhPacketStorage.AddTail(paPacket.pa_lnListNode); + pb_ulNumOfPackets++; + + // if the packet is reliable, bump up the number of reliable packets + if (paPacket.pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets++; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize += paPacket.pa_slSize - MAX_HEADER_SIZE; + return TRUE; + +}; + +// Inserts the packet in the buffer, according to it's sequence number +BOOL CPacketBuffer::InsertPacket(CPacket &paPacket,BOOL bDelay) +{ + + // find the right place to insert this packet (this is if this packet is out of sequence) + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + // if there is a packet in the buffer with greater sequence number, insert this one before it + if (paPacket.pa_ulSequence < litPacketIter->pa_ulSequence) { + + // bDelay regulates if the packet should be delayed because of the bandwidth limits or not + // internal buffers (reliable, waitack and master buffers) do not pay attention to bandwidth limits + if (bDelay) { + paPacket.pa_tvSendWhen = GetPacketSendTime(paPacket.pa_slSize); + } else { + paPacket.pa_tvSendWhen = _pTimer->GetHighPrecisionTimer(); + } + + litPacketIter.InsertBeforeCurrent(paPacket.pa_lnListNode); + pb_ulNumOfPackets++; + + // if the packet is reliable, bump up the number of reliable packets + if (paPacket.pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets++; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize += paPacket.pa_slSize - MAX_HEADER_SIZE; + + + return TRUE; + + // if there already is a packet in the buffer with the same sequence, do nothing + } else if (paPacket.pa_ulSequence == litPacketIter->pa_ulSequence) { + return FALSE; + } + } + + // if this packet has the greatest sequence number so far, add it to the end of the list + pb_lhPacketStorage.AddTail(paPacket.pa_lnListNode); + pb_ulNumOfPackets++; + + + // if the packet is reliable, bump up the number of reliable packets + if (paPacket.pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets++; + } + + pb_ulTotalSize += paPacket.pa_slSize - MAX_HEADER_SIZE; + + return TRUE; + +}; + + +// Bumps up the retry count and time, and appends the packet to the buffer +BOOL CPacketBuffer::Retry(CPacket &paPacket) +{ + paPacket.pa_ubRetryNumber++; + + if (net_bReportPackets == TRUE) { + CPrintF("Retrying sequence: %d, reliable flag: %d\n",paPacket.pa_ulSequence,paPacket.pa_ubReliable); + } + + return AppendPacket(paPacket,TRUE); +}; + +// Reads the data from the first packet in the bufffer, but does not remove it +CPacket* CPacketBuffer::PeekFirstPacket() +{ + ASSERT(pb_ulNumOfPackets != 0); + return LIST_HEAD(pb_lhPacketStorage,CPacket,pa_lnListNode); +}; + +// Reads the first packet in the bufffer, and removes it from the buffer +CPacket* CPacketBuffer::GetFirstPacket() +{ + ASSERT(pb_ulNumOfPackets != 0); + + CPacket* ppaHead = LIST_HEAD(pb_lhPacketStorage,CPacket,pa_lnListNode); + + // remove the first packet from the start of the list + pb_lhPacketStorage.RemHead(); + pb_ulNumOfPackets--; + if (ppaHead->pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets--; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (ppaHead->pa_slSize - MAX_HEADER_SIZE); + + // mark the last packet sequence that was output from the buffer - helps to prevent problems wit duplicated packets + if (pb_ulLastSequenceOut < ppaHead->pa_ulSequence) { + pb_ulLastSequenceOut = ppaHead->pa_ulSequence; + } + + return ppaHead; + +}; + +// Reads the data from the packet with the requested sequence, but does not remove it +CPacket* CPacketBuffer::PeekPacket(ULONG ulSequence) +{ + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ulSequence == ulSequence) { + return litPacketIter; + } + } + return NULL; +}; + +// Returns te packet with the matching sequence from the buffer +CPacket* CPacketBuffer::GetPacket(ULONG ulSequence) +{ + + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ulSequence == ulSequence) { + litPacketIter->pa_lnListNode.Remove(); + + pb_ulNumOfPackets--; + if (litPacketIter->pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets--; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (litPacketIter->pa_slSize - MAX_HEADER_SIZE); + + return litPacketIter; + } + } + return NULL; +}; + +// Reads the first connection request packet from the buffer +CPacket* CPacketBuffer::GetConnectRequestPacket() { + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ubReliable & UDP_PACKET_CONNECT_REQUEST) { + litPacketIter->pa_lnListNode.Remove(); + + pb_ulNumOfPackets--; + // connect request packets are allways reliable + pb_ulNumOfReliablePackets--; + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (litPacketIter->pa_slSize - MAX_HEADER_SIZE); + + return litPacketIter; + } + } + return NULL; +}; + +// Removes the first packet from the buffer +BOOL CPacketBuffer::RemoveFirstPacket(BOOL bDelete) { + ASSERT(pb_ulNumOfPackets > 0); + CPacket *lnHead = LIST_HEAD(pb_lhPacketStorage,CPacket,pa_lnListNode); + + pb_ulNumOfPackets--; + if (lnHead->pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets--; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (lnHead->pa_slSize - MAX_HEADER_SIZE); + + if (pb_ulLastSequenceOut < lnHead->pa_ulSequence) { + pb_ulLastSequenceOut = lnHead->pa_ulSequence; + } + + pb_lhPacketStorage.RemHead(); + if (bDelete) { + delete lnHead; + } + return TRUE; +}; + +// Removes the packet with the requested sequence from the buffer +BOOL CPacketBuffer::RemovePacket(ULONG ulSequence,BOOL bDelete) +{ +// ASSERT(pb_ulNumOfPackets > 0); + FORDELETELIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ulSequence == ulSequence) { + litPacketIter->pa_lnListNode.Remove(); + + pb_ulNumOfPackets--; + if (litPacketIter->pa_ubReliable & UDP_PACKET_RELIABLE) { + pb_ulNumOfReliablePackets--; + } + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (litPacketIter->pa_slSize - MAX_HEADER_SIZE); + + if (bDelete) { + delete litPacketIter; + } + } + } + return FALSE; +}; + +// Remove connect response packets from the buffer +BOOL CPacketBuffer::RemoveConnectResponsePackets() { + FORDELETELIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ubReliable & UDP_PACKET_CONNECT_RESPONSE) { + litPacketIter->pa_lnListNode.Remove(); + + pb_ulNumOfPackets--; + + // connect request packets are allways reliable + pb_ulNumOfReliablePackets--; + + // update the total size of data stored in the buffer + pb_ulTotalSize -= (litPacketIter->pa_slSize - MAX_HEADER_SIZE); + + delete litPacketIter; + } + } + return NULL; +}; + + +// Gets the sequence number of the first packet in the buffer +ULONG CPacketBuffer::GetFirstSequence() +{ + ASSERT(pb_ulNumOfPackets > 0); + + return LIST_HEAD(pb_lhPacketStorage,CPacket,pa_lnListNode)->pa_ulSequence; + +}; + +// Gets the sequence number of the last packet in the buffer +ULONG CPacketBuffer::GetLastSequence() +{ + ASSERT(pb_ulNumOfPackets > 0); + + return LIST_TAIL(pb_lhPacketStorage,CPacket,pa_lnListNode)->pa_ulSequence; + +}; + +// Removes the packet with the requested sequence from the buffer +BOOL CPacketBuffer::IsSequenceInBuffer(ULONG ulSequence) +{ + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + if (litPacketIter->pa_ulSequence == ulSequence) { + return TRUE; + } + } + return FALSE; +}; + + +// Check if the buffer contains a complete sequence of reliable packets at the start of the buffer +BOOL CPacketBuffer::CheckSequence(SLONG &slSize) +{ + + CPacket* paPacket; + ULONG ulSequence; + + slSize=0; + + if (pb_ulNumOfPackets == 0) { + return FALSE; + } + + paPacket = LIST_HEAD(pb_lhPacketStorage,CPacket,pa_lnListNode); + + // if the first packet is not the head of the reliable packet transfer + if (!(paPacket->pa_ubReliable & UDP_PACKET_RELIABLE_HEAD)) { + return FALSE; + } + + ulSequence = paPacket->pa_ulSequence; + + // for each packet in the buffer + FOREACHINLIST(CPacket,pa_lnListNode,pb_lhPacketStorage,litPacketIter) { + // if it's out of order (there is a gap in the reliable sequence), the message is not complete + if (litPacketIter->pa_ulSequence != ulSequence) { + return FALSE; + } + // if it's a tail of the reliable sequence the message is complete (all packets so far + // have been in order) + if (litPacketIter->pa_ubReliable & UDP_PACKET_RELIABLE_TAIL) { + return TRUE; + } + slSize += litPacketIter->pa_slSize - MAX_HEADER_SIZE; + ulSequence++; + } + + // if the function hasn't exited while in the loop, the message is not complete + // (all the packets are in sequence, but there is no tail) + return FALSE; +}; + + + diff --git a/Sources/Engine/Network/Packet.h b/Sources/Engine/Network/Packet.h new file mode 100644 index 0000000..ce4ece8 --- /dev/null +++ b/Sources/Engine/Network/Packet.h @@ -0,0 +1,182 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PACKET_H +#define SE_INCL_PACKET_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + + +// The total size of the UDP packet should be below 1450 bytes, to reduce the +// packet drop rate caused by routers dropping large UDP packets. UDP_BLOCK_SIZE is the +// maximum length of real data, not counting the packet header (ulPacketSequence, bReliable,uwID) +#define MAX_UDP_BLOCK_SIZE 1400 +#define MAX_HEADER_SIZE (sizeof(UBYTE) + sizeof(ULONG) + sizeof(UWORD) + sizeof(ULONG)) // pa_bReliable + pa_ulPacketSequence + pa_uwID + pa_ulTransferSize +#define MAX_PACKET_SIZE (MAX_UDP_BLOCK_SIZE + MAX_HEADER_SIZE) + +// flags for different kinds of packets used by the netcode - note that the acknowledge packets are unreliable +#define UDP_PACKET_UNRELIABLE 0 +#define UDP_PACKET_RELIABLE 1 +#define UDP_PACKET_RELIABLE_HEAD 2 +#define UDP_PACKET_RELIABLE_TAIL 4 +#define UDP_PACKET_ACKNOWLEDGE 8 +#define UDP_PACKET_CONNECT_REQUEST 16 +#define UDP_PACKET_CONNECT_RESPONSE 32 + +// constants for CPacket::CanRetry() function - they describe the retry state of the packet +#define RS_NOW 0 // the packet should be resent immediately +#define RS_NOTNOW 1 // the packet should be resent at a later time +#define RS_NOTATALL 2 // the packet has reached the maximum number of retries - give up + + +class CAddress { +public: + ULONG adr_ulAddress; // host address + UWORD adr_uwPort; // host port + UWORD adr_uwID; // host id + void MakeBroadcast(void); + void Clear(void) { + adr_ulAddress = 0; + adr_uwPort = 0; + adr_uwID = 0; + } +}; + +/* + * A class that contains a single UDP packet. + */ +class CPacket { +public: + ULONG pa_ulSequence; // Sequence number of this packet + UBYTE pa_ubReliable; // Is packet reliable or not + SLONG pa_slSize; // Number of data bytes in packet (without header) + SLONG pa_slTransferSize; // Number of data bytes in a data transfer unit this packet belongs to + + UBYTE pa_ubRetryNumber; // How many retries so far for this packet + CTimerValue pa_tvSendWhen; // When to try sending this packet (includes latency bandwidth limitations + // as well as retry intervals) + + UBYTE pa_pubPacketData[MAX_PACKET_SIZE]; // Packet header + actual data contained in the packet + + CListNode pa_lnListNode; // used to create a linked list of packets - buffer + + CAddress pa_adrAddress; // packet address, port and client ID + + // Constructors/destructors + CPacket() { Clear(); } // Default Constructor + CPacket(CPacket &paOriginal); // Copy constructor + ~CPacket() { Clear(); } + + // Reset all packet data and free allocated memory + void Clear(); + + // Write data to the packet and add header data + BOOL WriteToPacket(void* pv,SLONG slSize,UBYTE ubReliable,ULONG ulSequence,UWORD uwClientID,SLONG slTransferSize); + // Write raw data to the packet and extract header data from the data + BOOL WriteToPacketRaw(void* pv,SLONG slSize); + // Read data from the packet (no header data) + BOOL ReadFromPacket(void* pv,SLONG &slExpectedSize); + + // Is packet reliable + BOOL IsReliable(); + // Is packet a head of a reliable stream? + BOOL IsReliableHead(); + // Is packet a tail of a reliable stream? + BOOL IsReliableTail(); + // Is the packet from a broadcast address (pa_uwID not assigned) + BOOL IsBroadcast(); + + // Get the sequence number of the packet (must be reliable) + ULONG GetSequence(); + // What is the current retry status? + UBYTE CanRetry(); + // Drop the packet from the list + void Drop(); + + // get the size of data transfer unit this packet belongs to + SLONG CPacket::GetTransferSize(); + + // Copy operator + void operator=(const CPacket &paOriginal); + +}; + + +// data used to limit bandwidth/lantency and calculate statistics in packet-buffers +class CPacketBufferStats { +public: + FLOAT pbs_fLatencyLimit; // minimum latency in seconds + FLOAT pbs_fLatencyVariation;// additional latency variation + FLOAT pbs_fBandwidthLimit; // maximum bandwidth in bps (bits per second) + CTimerValue pbs_tvTimeNextPacketStart; // next point in time free for data receiving + + + void Clear(void); + // get time when the packet will be allowed to leave the buffer + CTimerValue GetPacketSendTime(SLONG slSize); +}; + + +class CPacketBuffer { +public: + ULONG pb_ulTotalSize; // Total size of data in packets stored in this buffer (no headers) + ULONG pb_ulLastSequenceOut; // Sequence number of the last packet taken out of the buffer + + CListHead pb_lhPacketStorage; + + ULONG pb_ulNumOfPackets; // Total number of packets currently in storage + ULONG pb_ulNumOfReliablePackets; // Number of reliable packets in storage (0 if no reliable stream in progress) + + CPacketBufferStats *pb_ppbsStats; // for bandwidth/latency emulation stats and limits + CPacketBufferStats pb_pbsLimits; // maximum output BPS for the buffer, to prevent client flooding + + CPacketBuffer() { Clear(); }; + ~CPacketBuffer() { Clear(); }; + + // Empty the packet buffer + void Clear(); + // Is the packet buffer empty? + BOOL IsEmpty(); + + // Calculate when the packet can be output from the buffer + CTimerValue GetPacketSendTime(SLONG slSize); + + // Adds a packet to the end of the packet buffer + BOOL AppendPacket(CPacket &paPacket,BOOL bDelay); + // Inserts the packet in the buffer, according to it's sequence number + BOOL InsertPacket(CPacket &paPacket,BOOL bDelay); + // Bumps up the retry count and time, and appends the packet to the buffer + BOOL Retry(CPacket &paPacket); + // Reads the data from the first packet in the bufffer, but does not remove it + CPacket* PeekFirstPacket(); + // Reads the first packet in the bufffer + CPacket* GetFirstPacket(); + // Reads the data from the packet with the requested sequence, but does not remove it + CPacket* PeekPacket(ULONG ulSequence); + // Reads the packet with the requested sequence + CPacket* GetPacket(ULONG ulSequence); + // Reads the first connection request packet from the buffer + CPacket* GetConnectRequestPacket(); + // Removes the first packet from the buffer + BOOL RemoveFirstPacket(BOOL bDelete); + // Removes the packet with the requested sequence from the buffer + BOOL RemovePacket(ULONG ulSequence,BOOL bDelete); + // Remove connect response packets from the buffer + BOOL RemoveConnectResponsePackets(); + + // Gets the sequence number of the first packet in the buffer + ULONG GetFirstSequence(); + // Gets the sequence number of the last packet in the buffer + ULONG GetLastSequence(); + // Is the packet with the given sequence in the buffer? + BOOL IsSequenceInBuffer(ULONG ulSequence); + // Check if the buffer contains a complete sequence of reliable packets at the start of the buffer + BOOL CheckSequence(SLONG &slSize); + +}; + + +#endif /* include-once check. */ \ No newline at end of file diff --git a/Sources/Engine/Network/PlayerBuffer.cpp b/Sources/Engine/Network/PlayerBuffer.cpp new file mode 100644 index 0000000..2ec0290 --- /dev/null +++ b/Sources/Engine/Network/PlayerBuffer.cpp @@ -0,0 +1,138 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +/* + * Constructor. + */ +CPlayerBuffer::CPlayerBuffer(void) { + plb_Active = FALSE; + plb_abReceived.Clear(); + plb_paLastAction.Clear(); + plb_iClient = -1; +} + +/* + * Destructor. + */ +CPlayerBuffer::~CPlayerBuffer(void) { +} + +/* + * Activate player buffer for a new player. + */ +void CPlayerBuffer::Activate(INDEX iClient) +{ + ASSERT(!plb_Active); + plb_Active = TRUE; + plb_iClient = iClient; + // make packets dummy before receiving something + plb_abReceived.Clear(); + plb_paLastAction.Clear(); +} + +/* + * Deactivate player data for removed player. + */ +void CPlayerBuffer::Deactivate(void) +{ + ASSERT(plb_Active); + plb_Active = FALSE; + plb_iClient = -1; +} + +/* + * Receive action packet from player source. + */ +void CPlayerBuffer::ReceiveActionPacket(CNetworkMessage *pnm, INDEX iMaxBuffer) +{ + ASSERT(plb_Active); + // receive new action + CPlayerAction pa; + (*pnm)>>pa; + // buffer it + plb_abReceived.AddAction(pa); + // read sendbehind + INDEX iSendBehind = 0; + pnm->ReadBits(&iSendBehind, 2); + // foreach resent action + for(INDEX i=0; i>paOld; + + // if not already sent out back to the client + if (paOld.pa_llCreated>plb_paLastAction.pa_llCreated) { + // buffer it + plb_abReceived.AddAction(paOld); + } + } + +/* + INDEX ctBuffered = plb_abReceived.GetCount(); + if (ctBuffered>net_iPlayerBufferActions) { + CPrintF("Receive: BUFFER FULL (%d) ++++++++++++++\n", ctBuffered); + } + CPrintF("Receive: buffered %d\n", ctBuffered); + */ + // while there are more too many actions buffered + while(plb_abReceived.GetCount()>iMaxBuffer) { + // purge the oldest one + plb_abReceived.RemoveOldest(); + } +} + +/* Create action packet for player target from oldest buffered action. */ +// (prepares lag info for given client number) +void CPlayerBuffer::CreateActionPacket(CNetworkMessage *pnm, INDEX iClient) +{ + ASSERT(plb_Active); + CPlayerAction paCurrent; + + //CPrintF("Send: buffered %d\n", plb_abReceived.GetCount()); + + // if there are any buffered actions + if (plb_abReceived.GetCount()>0) { + // retrieve the oldest one + plb_abReceived.GetActionByIndex(0, paCurrent); + // if there are no buffered actions + } else { + // reuse the last one + paCurrent = plb_paLastAction; + //CPrintF("Send: BUFFER EMPTY ---------\n"); + } + + // create a new delta action packet between last sent and current action + CPlayerAction paDelta; + for (INDEX i=0; i0) { + // get the oldest one and remove it + CPlayerAction paCurrent; + plb_abReceived.GetActionByIndex(0, paCurrent); + plb_abReceived.RemoveOldest(); + // move current action to last action + plb_paLastAction = paCurrent; + } +} diff --git a/Sources/Engine/Network/PlayerBuffer.h b/Sources/Engine/Network/PlayerBuffer.h new file mode 100644 index 0000000..bbb6a10 --- /dev/null +++ b/Sources/Engine/Network/PlayerBuffer.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PLAYERBUFFER_H +#define SE_INCL_PLAYERBUFFER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include + +/* + * Player buffer, located on server; buffers action messages + */ +class ENGINE_API CPlayerBuffer { +public: + BOOL plb_Active; // set if this player exists + INDEX plb_Index; + INDEX plb_iClient; // client that controls this player + INDEX plb_iPing; // ping in milliseconds + CPlayerAction plb_paLastAction; // last action sent (used for delta-packing) + CActionBuffer plb_abReceived; // buffer of actions that were received, but not sent yet + CPlayerCharacter plb_pcCharacter; // this player's character data +public: + + /* Default constructor. */ + CPlayerBuffer(void); + /* Destructor. */ + ~CPlayerBuffer(void); + + /* Activate player buffer for a new player. */ + void Activate(INDEX iClient); + /* Deactivate player data for removed player. */ + void Deactivate(void); + /* Check if this player is active. */ + BOOL IsActive(void) { return plb_Active; }; + + /* Receive action packet from player source. */ + void ReceiveActionPacket(CNetworkMessage *pnm, INDEX iMaxBuffer); + /* Create action packet for player target from oldest buffered action. */ + // (prepares lag info for given client number) + void CreateActionPacket(CNetworkMessage *pnm, INDEX iClient); + /* Advance action buffer by one tick by removing oldest action. */ + void AdvanceActionBuffer(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/PlayerSource.cpp b/Sources/Engine/Network/PlayerSource.cpp new file mode 100644 index 0000000..6f64295 --- /dev/null +++ b/Sources/Engine/Network/PlayerSource.cpp @@ -0,0 +1,230 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +extern FLOAT net_tmConnectionTimeout; +extern FLOAT net_tmProblemsTimeOut; + +/* + * Constructor. + */ +CPlayerSource::CPlayerSource(void) { + pls_Active = FALSE; + pls_Index = -2; + pls_csAction.cs_iIndex = -1; + // clear action packet + pls_paAction.Clear(); +} + +/* + * Destructor. + */ +CPlayerSource::~CPlayerSource(void) { +} + +/* + * Activate a new player. + */ +void CPlayerSource::Start_t(CPlayerCharacter &pcCharacter) // throw char * +{ + ASSERT(!pls_Active); + + // set index to -1 what means that you are not yet registered properly + pls_Index = -1; + // copy the character data + pls_pcCharacter = pcCharacter; + // clear actions + pls_paAction.Clear();; + for(INDEX ipa=0; ipaSendToServerReliable(nmRegisterPlayer); + + for(TIME tmWait=0; + tmWaitga_IsServer) { + _pNetwork->TimerLoop(); + } + + if (_cmiComm.Client_Update() == FALSE) { + break; + } + // wait for message to come + CNetworkMessage nmReceived; + if (!_pNetwork->ReceiveFromServerReliable(nmReceived)) { + continue; + } + + // if this is the init message + if (nmReceived.GetType() == MSG_REP_CONNECTPLAYER) { + // remember your index + nmReceived>>pls_Index; + // finish waiting + pls_Active = TRUE; + return; + // if this is disconnect message + } else if (nmReceived.GetType() == MSG_INF_DISCONNECTED) { + // confirm disconnect + CNetworkMessage nmConfirmDisconnect(MSG_REP_DISCONNECTED); + _pNetwork->SendToServerReliable(nmConfirmDisconnect); + + // throw exception + CTString strReason; + nmReceived>>strReason; + _pNetwork->ga_sesSessionState.ses_strDisconnected = strReason; + ThrowF_t(TRANS("Cannot add player because: %s\n"), strReason); + + // otherwise + } else { + // it is invalid message + ThrowF_t(TRANS("Invalid message while waiting for player registration")); + } + + // if client is disconnected + if (!_cmiComm.Client_IsConnected()) { + // quit + ThrowF_t(TRANS("Client disconnected")); + } + + } + + CNetworkMessage nmConfirmDisconnect(MSG_REP_DISCONNECTED); + _pNetwork->SendToServerReliable(nmConfirmDisconnect); + + ThrowF_t(TRANS("Timeout while waiting for player registration")); +} + +/* + * Deactivate removed player. + */ +void CPlayerSource::Stop(void) +{ + ASSERT(pls_Active); + pls_Active = FALSE; + pls_Index = -2; +} + +// request character change for a player +// NOTE: the request is asynchronious and possible failure cannot be detected +void CPlayerSource::ChangeCharacter(CPlayerCharacter &pcNew) +{ + // if the requested character has different guid + if (!(pls_pcCharacter==pcNew)) { + // fail + CPrintF(TRANS("Cannot update character - different GUID\n")); + } + + // just request the change + CNetworkMessage nmChangeChar(MSG_REQ_CHARACTERCHANGE); + nmChangeChar<SendToServerReliable(nmChangeChar); + // remember new setting + pls_pcCharacter = pcNew; +} + +/* + * Set player action. + */ +void CPlayerSource::SetAction(const CPlayerAction &paAction) +{ + // synchronize access to action + CTSingleLock slAction(&pls_csAction, TRUE); + // set action + pls_paAction = paAction; + pls_paAction.pa_llCreated = _pTimer->GetHighPrecisionTimer().GetMilliseconds(); + //CPrintF("%.2f - created: %d\n", _pTimer->GetRealTimeTick(), SLONG(pls_paAction.pa_llCreated)); +} + +// get mask of this player for chat messages +ULONG CPlayerSource::GetChatMask(void) +{ + return 1UL<GetLocalPlayerEntity(this); + } + // if not + if (ppe==NULL) { + // just write a dummy bit + BOOL bActive = 0; + nm.WriteBits(&bActive, 1); + return; + } + + // normalize action (remove invalid floats like -0) + pls_paAction.Normalize(); + + ASSERT(pls_Active); + ASSERT(pls_Index>=0); + + // determine ping + FLOAT tmPing = ppe->en_tmPing; + INDEX iPing = (INDEX)ceil(tmPing*1000); + + // write all in the message + BOOL bActive = 1; + nm.WriteBits(&bActive, 1); + nm.WriteBits(&pls_Index, 4); // your index + nm.WriteBits(&iPing, 10); // your ping + nm<GetRealTimeTick(), SLONG(pls_paAction.pa_llCreated)); + + // get sendbehind parameters + extern INDEX cli_iSendBehind; + extern INDEX cli_bPredictIfServer; + cli_iSendBehind = Clamp(cli_iSendBehind, 0L, 3L); + INDEX iSendBehind = cli_iSendBehind; + + // disable if server + if (_pNetwork->IsServer() && !cli_bPredictIfServer) { + iSendBehind = 0; + } + + // save sendbehind if needed + nm.WriteBits(&iSendBehind, 2); + for(INDEX i=0; iIsPaused() && !_pNetwork->GetLocalPause()) { + // get the index of the player target in game state + INDEX iPlayerTarget = pls_Index; + // if player is added + if (iPlayerTarget>=0) { + // get the player target + CPlayerTarget &plt = _pNetwork->ga_sesSessionState.ses_apltPlayers[iPlayerTarget]; + // let it buffer the packet + plt.PrebufferActionPacket(pls_paAction); + } + } +} diff --git a/Sources/Engine/Network/PlayerSource.h b/Sources/Engine/Network/PlayerSource.h new file mode 100644 index 0000000..f395d90 --- /dev/null +++ b/Sources/Engine/Network/PlayerSource.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PLAYERSOURCE_H +#define SE_INCL_PLAYERSOURCE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include + +/* + * Player source, located on client computer; creating actions and receiving updates + */ +class ENGINE_API CPlayerSource { +public: + INDEX pls_Index; + BOOL pls_Active; // set if this player exists + CPlayerCharacter pls_pcCharacter; // this player's character data + + CTCriticalSection pls_csAction; // access to player action + CPlayerAction pls_paAction; // action that this player is currently doing +#define PLS_MAXLASTACTIONS 3 + CPlayerAction pls_apaLastActions[PLS_MAXLASTACTIONS]; // old actions remembered for resending +public: + /* Activate a new player. */ + void Start_t(CPlayerCharacter &pcCharacter); + /* Deactivate removed player. */ + void Stop(void); + /* Check if this player is active. */ + BOOL IsActive(void) { return pls_Active; }; + // request character change for a player + // NOTE: the request is asynchronious and possible failure cannot be detected + void ChangeCharacter(CPlayerCharacter &pcNew); + + /* Create action packet from current player commands and for sending to server. */ + void WriteActionPacket(CNetworkMessage &nm); +public: + + CPlayerSource(); + ~CPlayerSource(); + + /* Set current player action. */ + void SetAction(const CPlayerAction &paAction); + // get mask of this player for chat messages + ULONG GetChatMask(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/PlayerTarget.cpp b/Sources/Engine/Network/PlayerTarget.cpp new file mode 100644 index 0000000..f2514a1 --- /dev/null +++ b/Sources/Engine/Network/PlayerTarget.cpp @@ -0,0 +1,230 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include + +extern INDEX cli_bLerpActions; +/* + * Constructor. + */ +CPlayerTarget::CPlayerTarget(void) { + plt_bActive = FALSE; + plt_penPlayerEntity = NULL; + plt_csAction.cs_iIndex = -1; + plt_paLastAction.Clear(); + plt_paPreLastAction.Clear(); + plt_abPrediction.Clear(); +} + +/* + * Destructor. + */ +CPlayerTarget::~CPlayerTarget(void) { +} + +/* + * Read player information from a stream. + */ +void CPlayerTarget::Read_t(CTStream *pstr) // throw char * +{ + INDEX iEntity; + ULONG bActive; + // synchronize access to actions + CTSingleLock slActions(&plt_csAction, TRUE); + + // read activity flag + (*pstr)>>bActive; + // if client is active + if (bActive) { + // set it up + Activate(); + // read data + (*pstr)>>iEntity>>plt_paLastAction>>plt_paPreLastAction; + CPlayerEntity *penPlayer = (CPlayerEntity *)&_pNetwork->ga_World.wo_cenAllEntities[iEntity]; + ASSERT(penPlayer != NULL); + AttachEntity(penPlayer); + } + plt_abPrediction.Clear(); +} + +/* + * Write client information into a stream. + */ +void CPlayerTarget::Write_t(CTStream *pstr) // throw char * +{ + INDEX iEntity; + ULONG bActive = plt_bActive; + // synchronize access to actions + CTSingleLock slActions(&plt_csAction, TRUE); + + // write activity flag + (*pstr)<ga_World.wo_cenAllEntities.Index(plt_penPlayerEntity); + // write data + (*pstr)<IsPlayerLocal(plt_penPlayerEntity)) { + // calculate latency + __int64 llmsNow = _pTimer->GetHighPrecisionTimer().GetMilliseconds(); + __int64 llmsCreated = plt_paLastAction.pa_llCreated; + fLatency = FLOAT(DOUBLE(llmsNow-llmsCreated)/1000.0f); + if (plt_paLastAction.pa_llCreated==plt_paPreLastAction.pa_llCreated) { + _pNetwork->AddNetGraphValue(NGET_REPLICATEDACTION, fLatency); + } else { + CPlayerAction *ppaOlder = plt_abPrediction.GetLastOlderThan(plt_paLastAction.pa_llCreated); + if (ppaOlder!=NULL && ppaOlder->pa_llCreated!=plt_paPreLastAction.pa_llCreated) { + _pNetwork->AddNetGraphValue(NGET_SKIPPEDACTION, 1.0f); + } + extern FLOAT net_tmLatency; + net_tmLatency = fLatency; + _pNetwork->AddNetGraphValue(NGET_ACTION, fLatency); + } + } + + // if the entity is not deleted + if (!(plt_penPlayerEntity->en_ulFlags&ENF_DELETED)) { + // call the player DLL class to apply the new action to the entity + plt_penPlayerEntity->ApplyAction(plt_paLastAction, fLatency); + } + + extern INDEX cli_iPredictionFlushing; + if (cli_iPredictionFlushing==2 || cli_iPredictionFlushing==3) { + plt_abPrediction.RemoveOldest(); + } +} + +/* Remember prediction action. */ +void CPlayerTarget::PrebufferActionPacket(const CPlayerAction &paPrediction) +{ + ASSERT(plt_bActive); + // synchronize access to actions + CTSingleLock slActions(&plt_csAction, TRUE); + + // buffer the action + plt_abPrediction.AddAction(paPrediction); +} + +// flush prediction actions that were already processed +void CPlayerTarget::FlushProcessedPredictions(void) +{ + CTSingleLock slActions(&plt_csAction, TRUE); + extern INDEX cli_iPredictionFlushing; + if (cli_iPredictionFlushing==1) { + // flush all actions that were already processed + plt_abPrediction.FlushUntilTime(plt_paLastAction.pa_llCreated); + } else if (cli_iPredictionFlushing==3) { + // flush older actions that were already processed + plt_abPrediction.FlushUntilTime(plt_paPreLastAction.pa_llCreated); + } +} + +// get maximum number of actions that can be predicted +INDEX CPlayerTarget::GetNumberOfPredictions(void) +{ + CTSingleLock slActions(&plt_csAction, TRUE); + // return current count + return plt_abPrediction.GetCount(); +} + +/* Apply predicted action with given index. */ +void CPlayerTarget::ApplyPredictedAction(INDEX iAction, FLOAT fFactor) +{ + // synchronize access to actions + CTSingleLock slActions(&plt_csAction, TRUE); + + CPlayerAction pa; + + // if the player is local + if (_pNetwork->IsPlayerLocal(plt_penPlayerEntity)) { + // get the action from buffer + plt_abPrediction.GetActionByIndex(iAction, pa); + + // if the player is not local + } else { + // reuse last action + if (cli_bLerpActions) { + pa.Lerp(plt_paPreLastAction, plt_paLastAction, fFactor); + } else { + pa = plt_paLastAction; + } + } + + // get the player's predictor + if (!plt_penPlayerEntity->IsPredicted()) { + return; + } + + CEntity *penPredictor = plt_penPlayerEntity->GetPredictor(); + if (penPredictor==NULL || penPredictor==plt_penPlayerEntity) { + return; + } + + // apply a prediction action packet to the entity's predictor + ((CPlayerEntity*)penPredictor)->ApplyAction(pa, 0.0f); +} diff --git a/Sources/Engine/Network/PlayerTarget.h b/Sources/Engine/Network/PlayerTarget.h new file mode 100644 index 0000000..1eeb55e --- /dev/null +++ b/Sources/Engine/Network/PlayerTarget.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PLAYERTARGET_H +#define SE_INCL_PLAYERTARGET_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include + +/* + * Player target, located in each session state; receiving actions + */ +class CPlayerTarget { +public: + BOOL plt_bActive; // set if this player exists + CPlayerEntity *plt_penPlayerEntity; // player entity used by this player + CTCriticalSection plt_csAction; // access to player action + CPlayerAction plt_paPreLastAction; + CPlayerAction plt_paLastAction; // last action received (used for delta-unpacking) + CActionBuffer plt_abPrediction; // buffer of sent actions (used for prediction) + FLOAT3D plt_vPredictorPos; // last position of predictor - for range calculations +public: + + /* Default constructor. */ + CPlayerTarget(void); + /* Destructor. */ + ~CPlayerTarget(void); + + /* Activate player target for a new player. */ + void Activate(void); + /* Deactivate player target for removed player. */ + void Deactivate(void); + /* Check if this player is active. */ + BOOL IsActive(void) { return plt_bActive; }; + /* Attach an entity to this player. */ + void AttachEntity(CPlayerEntity *penClientEntity); + + /* Apply action packet to current actions. */ + void ApplyActionPacket(const CPlayerAction &paDelta); + + /* Remember prediction action. */ + void PrebufferActionPacket(const CPlayerAction &paPrediction); + // flush prediction actions that were already processed + void FlushProcessedPredictions(void); + // get maximum number of actions that can be predicted + INDEX GetNumberOfPredictions(void); + /* Apply predicted action with given index. */ + void ApplyPredictedAction(INDEX iAction, FLOAT fFactor); + + /* Read player information from a stream. */ + void Read_t(CTStream *pstr); // throw char * + /* Write player information into a stream. */ + void Write_t(CTStream *pstr); // throw char * +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/Server.cpp b/Sources/Engine/Network/Server.cpp new file mode 100644 index 0000000..b75d700 --- /dev/null +++ b/Sources/Engine/Network/Server.cpp @@ -0,0 +1,1595 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +extern INDEX ser_iSyncCheckBuffer; +extern FLOAT net_tmDisconnectTimeout; +extern BOOL con_bCapture; +extern CTString con_strCapture; +extern CTString ser_strIPMask; +extern CTString ser_strNameMask; +extern INDEX ser_bInverseBanning; +extern BOOL MatchesBanMask(const CTString &strString, const CTString &strMask); +extern CClientInterface cm_aciClients[SERVER_CLIENTS]; + +CSessionSocket::CSessionSocket(void) +{ + sso_bActive = FALSE; + sso_bVIP = FALSE; + sso_bSendStream = FALSE; + sso_iDisconnectedState = 0; + sso_iLastSentSequence = -1; + sso_ctBadSyncs = 0; + sso_tvLastMessageSent.Clear(); + sso_tvLastPingSent.Clear(); +} +CSessionSocket::~CSessionSocket(void) +{ + sso_bActive = FALSE; + sso_bVIP = FALSE; + sso_bSendStream = FALSE; + sso_iLastSentSequence = -1; + sso_ctBadSyncs = 0; + sso_tvLastMessageSent.Clear(); + sso_tvLastPingSent.Clear(); +} +void CSessionSocket::Clear(void) +{ + sso_bActive = FALSE; + sso_bVIP = FALSE; + sso_bSendStream = FALSE; + sso_tvMessageReceived.Clear(); + sso_tmLastSyncReceived = -1.0f; + sso_iLastSentSequence = -1; + sso_tvLastMessageSent.Clear(); + sso_tvLastPingSent.Clear(); + sso_nsBuffer.Clear(); + sso_iDisconnectedState = 0; + sso_ctBadSyncs = 0; + sso_sspParams.Clear(); +} + +void CSessionSocket::Activate(void) +{ +#if DEBUG_SYNCSTREAMDUMPING + ClearDumpStream(); +#endif + + ASSERT(!sso_bActive); + sso_bActive = TRUE; + sso_bVIP = FALSE; + sso_bSendStream = FALSE; + sso_tvMessageReceived.Clear(); + sso_tmLastSyncReceived = -1.0f; + sso_iLastSentSequence = -1; + sso_tvLastMessageSent.Clear(); + sso_tvLastPingSent.Clear(); + sso_iDisconnectedState = 0; + sso_ctBadSyncs = 0; + sso_sspParams.Clear(); +// sso_nsBuffer.Clear(); +} + +void CSessionSocket::Deactivate(void) +{ + sso_iDisconnectedState = 0; + sso_iLastSentSequence = -1; + sso_tvLastMessageSent.Clear(); + sso_tvLastPingSent.Clear(); + sso_ctBadSyncs = 0; + sso_bActive = FALSE; + sso_nsBuffer.Clear(); + sso_sspParams.Clear(); +} +BOOL CSessionSocket::IsActive(void) +{ + return sso_bActive; +} + +extern INDEX cli_iBufferActions; +extern INDEX cli_iMaxBPS; +extern INDEX cli_iMinBPS; + +CSessionSocketParams::CSessionSocketParams(void) +{ + Clear(); +} + +void CSessionSocketParams::Clear(void) +{ + ssp_iBufferActions = 2; + ssp_iMaxBPS = 4000; + ssp_iMinBPS = 1000; +} + +static void ClampParams(void) +{ + cli_iBufferActions = Clamp(cli_iBufferActions, INDEX(1), INDEX(20)); + cli_iMaxBPS = Clamp(cli_iMaxBPS, INDEX(100), INDEX(1000000)); + cli_iMinBPS = Clamp(cli_iMinBPS, INDEX(100), INDEX(1000000)); +} + +// check if up to date with current params +BOOL CSessionSocketParams::IsUpToDate(void) +{ + ClampParams(); + return + ssp_iBufferActions == cli_iBufferActions && + ssp_iMaxBPS == cli_iMaxBPS && + ssp_iMinBPS == cli_iMinBPS; +} + +// update +void CSessionSocketParams::Update(void) +{ + ClampParams(); + ssp_iBufferActions = cli_iBufferActions; + ssp_iMaxBPS = cli_iMaxBPS; + ssp_iMinBPS = cli_iMinBPS; +} + +// message operations +CNetworkMessage &operator<<(CNetworkMessage &nm, CSessionSocketParams &ssp) +{ + nm<>(CNetworkMessage &nm, CSessionSocketParams &ssp) +{ + nm>>ssp.ssp_iBufferActions>>ssp.ssp_iMaxBPS>>ssp.ssp_iMinBPS; + return nm; +} + +/* + * Constructor. + */ +CServer::CServer(void) +{ + srv_bActive = FALSE; + + srv_assoSessions.New(NET_MAXGAMECOMPUTERS); + srv_aplbPlayers.New(NET_MAXGAMEPLAYERS); + // initialize player indices + INDEX iPlayer = 0; + FOREACHINSTATICARRAY(srv_aplbPlayers, CPlayerBuffer, itplb) { + itplb->plb_Index = iPlayer; + iPlayer++; + } +} + +/* + * Destructor. + */ +CServer::~CServer() +{ + srv_bActive = FALSE; +} + +/* + * Clear the object. + */ +void CServer::Stop(void) +{ + // stop gameagent + GameAgent_ServerEnd(); + + // tell all clients to disconnect + INDEX ctClients = srv_assoSessions.sa_Count; + INDEX iClient; + for (iClient=0;iClientplb_Index = iPlayer; + iPlayer++; + }} + + // init buffer for sync checks + srv_ascChecks.Clear(); + + srv_bActive = FALSE; +}; + +/* + * Initialize server and start message handlers. + */ +void CServer::Start_t(void) +{ + // init buffer for sync checks + srv_ascChecks.Clear(); + + // set up structures + srv_tmLastProcessedTick = 0.0f; + srv_iLastProcessedSequence = -1; // -1 so that next one will be 0 + srv_bActive = TRUE; + srv_bPause = FALSE; + srv_bGameFinished = FALSE; + srv_fServerStep = 0.0f; + + // init network driver server + _cmiComm.Server_Init_t(); + + // init gameagent + if (_cmiComm.IsNetworkEnabled()) { + GameAgent_ServerInit(); + } +} + +/* + * Send disconnect message to some node. + */ +void CServer::SendDisconnectMessage(INDEX iClient, const char *strExplanation, BOOL bStream) +{ + CSessionSocket &sso = srv_assoSessions[iClient]; + + if (!bStream) { + CNetworkMessage nmDisconnect(MSG_INF_DISCONNECTED); + // compose message + nmDisconnect<SendToClientReliable(iClient, nmDisconnect); + } else { + CTMemoryStream strmDisconnect; + strmDisconnect<SendToClientReliable(iClient, strmDisconnect); + } + // report that it has gone away + CPrintF(TRANS("Client '%s' ordered to disconnect: %s\n"), + _cmiComm.Server_GetClientName(iClient), strExplanation); + // if not disconnected before + if (sso.sso_iDisconnectedState==0) { + // mark the disconnection + sso.sso_iDisconnectedState = 1; + // if the client was already kicked before, but is still hanging here + } else { + // force the disconnection + CPrintF(TRANS("Forcing client '%s' to disconnect\n"), + _cmiComm.Server_GetClientName(iClient)); + sso.sso_iDisconnectedState = 2; + } +} + +// add a new sync check to buffer +void CServer::AddSyncCheck(const CSyncCheck &sc) +{ + ser_iSyncCheckBuffer = ClampDn(ser_iSyncCheckBuffer, INDEX(1)); + if (srv_ascChecks.Count()!=ser_iSyncCheckBuffer) { + srv_ascChecks.Clear(); + srv_ascChecks.New(ser_iSyncCheckBuffer); + } + // find the oldest one + INDEX iOldest = 0; + for (INDEX i=1; itmTick) { + bHasLater = TRUE; + } + } + + if (!bHasEarlier) { + ASSERT(bHasLater); + return -1; + } else if (!bHasLater) { + ASSERT(bHasEarlier); + return +1; + } else { + ASSERT(FALSE); // cannot have both earlier and later and not be found + return +1; + } +} + +/* Send one regular batch of sequences to a client. */ +void CServer::SendGameStreamBlocks(INDEX iClient) +{ + // get corresponding session socket + CSessionSocket &sso = srv_assoSessions[iClient]; + + // gather needed data to decide what to send + INDEX iLastSent = sso.sso_iLastSentSequence; + INDEX ctMinBytes = sso.sso_sspParams.ssp_iMinBPS/20; + INDEX ctMaxBytes = sso.sso_sspParams.ssp_iMaxBPS/20; + // make sure outgoing message doesn't overflow UDP size + ctMinBytes = Clamp(ctMinBytes, 0L, 1000L); + ctMaxBytes = Clamp(ctMaxBytes, 0L, 1000L); + // limit the clients BPS by server's local settings + extern INDEX ser_iMaxAllowedBPS; + ctMinBytes = ClampUp(ctMinBytes, (INDEX) ( ser_iMaxAllowedBPS/20L - MAX_HEADER_SIZE)); + ctMaxBytes = ClampUp(ctMaxBytes, (INDEX) (ser_iMaxAllowedBPS/20L - MAX_HEADER_SIZE)); + + // prevent server/singleplayer from flooding itself + extern INDEX cli_bPredictIfServer; + if (iClient==0 && !cli_bPredictIfServer) { + ctMinBytes = 0; + ctMaxBytes = 1E6; + } + +// CPrintF("Send%d(%d, %d, %d): ", iClient, iLastSent, ctMinBytes, ctMaxBytes); + + // start after last sequence that was sent and go upwards + INDEX iSequence = iLastSent+1; + INDEX iStep = +1; +// CPrintF("last=%d -- ", iLastSent); + + // initialize the message that is to be sent + CNetworkMessage nmGameStreamBlocks(MSG_GAMESTREAMBLOCKS); + // get one message for last compressed message of valid size + CNetworkMessage nmPackedBlocks(MSG_GAMESTREAMBLOCKS); + CNetworkMessage nmPackedBlocksNew(MSG_GAMESTREAMBLOCKS); + + // repeat for max 100 sequences + INDEX iBlocksOk = 0; + INDEX iMaxSent = -1; + for(INDEX i=0; i<100; i++) { + if (iStep<0 && iBlocksOk>=3) { +// break; + } + // get the stream block with current sequence +// CPrintF("%d: ", iSequence); + CNetworkStreamBlock *pnsbBlock; + CNetworkStream::Result res = sso.sso_nsBuffer.GetBlockBySequence(iSequence, pnsbBlock); + // if it is not found + if (res!=CNetworkStream::R_OK) { + // if going upward + if (iStep>0 ) { +// // if this block is missing +// && res==CNetworkStream::R_BLOCKMISSING + // if none sent so far + if (iBlocksOk<=0) { + // give up +// CPrintF("giving up\n"); + break; + } +// CPrintF("rewind ", iSequence); + // rewind and continue downward + if (iSequence == iLastSent+1) { + iSequence = iLastSent-1; + } else { + iSequence = iLastSent; + } + iStep = -1; + // retry + continue; + // otherwise + } else { + // stop adding more blocks + break; + } + } + // if uncompressed message would overflow + if (nmGameStreamBlocks.nm_slSize+pnsbBlock->nm_slSize+32>MAX_NETWORKMESSAGE_SIZE) { +// CPrintF("overflow "); + break; + } + + // add this block to the message and pack it + pnsbBlock->WriteToMessage(nmGameStreamBlocks); + nmPackedBlocksNew.Reinit(); + nmGameStreamBlocks.PackDefault(nmPackedBlocksNew); + // if some blocks written already and the batch is too large + if (iBlocksOk>0) { + if (iStep>0 && nmPackedBlocksNew.nm_slSize>=ctMaxBytes || + iStep<0 && nmPackedBlocksNew.nm_slSize>=ctMinBytes ) { + // stop +// CPrintF("toomuch "); + break; + } + } + // use new pack +// CPrintF("added "); + nmPackedBlocks = nmPackedBlocksNew; + iMaxSent = Max(iMaxSent, iSequence); + iSequence+= iStep; + iBlocksOk++; + } + + // if no blocks to write + if (iBlocksOk<=0) { + // if not sent anything for some time + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + extern FLOAT ser_tmKeepAlive; + if ((tvNow-sso.sso_tvLastMessageSent).GetSeconds()>ser_tmKeepAlive) { + // send keepalive + CNetworkMessage nmKeepalive(MSG_KEEPALIVE); + _pNetwork->SendToClient(iClient, nmKeepalive); + sso.sso_tvLastMessageSent = tvNow; + } + // CPrintF("nothing\n"); + return; + } + + // send the message to the client +// CPrintF("sent: %d=%dB\n", iBlocksOk, nmPackedBlocks.nm_slSize); + _pNetwork->SendToClient(iClient, nmPackedBlocks); + sso.sso_iLastSentSequence = Max(sso.sso_iLastSentSequence, iMaxSent); + sso.sso_tvLastMessageSent = _pTimer->GetHighPrecisionTimer(); + + // remove the block(s) that fall out of the buffer + extern INDEX ser_iRememberBehind; + sso.sso_nsBuffer.RemoveOlderBlocksBySequence(srv_iLastProcessedSequence-ser_iRememberBehind); + + + // if haven't sent pings for some time + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + extern FLOAT ser_tmPingUpdate; + if ((tvNow-sso.sso_tvLastPingSent).GetSeconds()>ser_tmPingUpdate) { + // send ping info + CNetworkMessage nmPings(MSG_INF_PINGS); + for(INDEX i=0; iSendToClient(iClient, nmPings); + sso.sso_tvLastPingSent = tvNow; + } +} + +/* Resend a batch of game stream blocks to a client. */ +void CServer::ResendGameStreamBlocks(INDEX iClient, INDEX iSequence0, INDEX ctSequences) +{ + extern INDEX net_bReportMiscErrors; + if (net_bReportMiscErrors) { + CPrintF(TRANS("Server: Resending sequences %d-%d(%d) to '%s'..."), + iSequence0, iSequence0+ctSequences-1, ctSequences, _cmiComm.Server_GetClientName(iClient)); + } + + // get corresponding session socket + CSessionSocket &sso = srv_assoSessions[iClient]; + + // create a package message + CNetworkMessage nmGameStreamBlocks(MSG_GAMESTREAMBLOCKS); + CNetworkMessage nmPackedBlocks(MSG_GAMESTREAMBLOCKS); + + // for each sequence + INDEX iSequence = iSequence0; + for(; iSequenceWriteToMessage(nmGameStreamBlocks); + nmGameStreamBlocks.PackDefault(nmPackedBlocksNew); + // if the batch is too large + if (nmPackedBlocksNew.nm_slSize>512) { + // stop + break; + } + // use new pack + nmPackedBlocks = nmPackedBlocksNew; + } + + // send the last batch of valid size + _pfNetworkProfile.IncrementCounter(CNetworkProfile::PCI_GAMESTREAMRESENDS); + _pNetwork->SendToClient(iClient, nmPackedBlocks); + extern INDEX net_bReportMiscErrors; + if (net_bReportMiscErrors) { + CPrintF(TRANS(" sent %d-%d(%d - %db)\n"), + iSequence0, iSequence, iSequence-iSequence0-1, nmPackedBlocks.nm_slSize); + } +} + +/* Get number of active players. */ +INDEX CServer::GetPlayersCount(void) +{ + INDEX ctPlayers = 0; + FOREACHINSTATICARRAY(srv_aplbPlayers, CPlayerBuffer, itplb) { + if (itplb->IsActive()) { + ctPlayers++; + } + } + return ctPlayers; +} +/* Get number of active vip players. */ +INDEX CServer::GetVIPPlayersCount(void) +{ + INDEX ctPlayers = 0; + FOREACHINSTATICARRAY(srv_aplbPlayers, CPlayerBuffer, itplb) { + if (itplb->IsActive() && srv_assoSessions[itplb->plb_iClient].sso_bVIP) { + ctPlayers++; + } + } + return ctPlayers; +} +/* Get total number of active clients. */ +INDEX CServer::GetClientsCount(void) +{ + INDEX ctClients = 0; + // for each active session + for(INDEX iSession=0; iSession0 && !sso.IsActive()) { + continue; + } + ctClients++; + } + + return ctClients; + +} +/* Get number of active vip clients. */ +INDEX CServer::GetVIPClientsCount(void) +{ + INDEX ctClients = 0; + // for each active session + for(INDEX iSession=0; iSession0 && !sso.IsActive()) { + continue; + } + if (sso.sso_bVIP) { + ctClients++; + } + } + + return ctClients; +} +/* Get number of active observers. */ +INDEX CServer::GetObserversCount(void) +{ + INDEX ctClients = 0; + // for each active session + for(INDEX iSession=0; iSession0 && !sso.IsActive()) { + continue; + } + if (sso.sso_ctLocalPlayers == 0) { + ctClients++; + } + } + + return ctClients; +} + +/* Get number of active players on one client. */ +INDEX CServer::GetPlayersCountForClient(INDEX iClient) +{ + INDEX ctPlayers = 0; + FOREACHINSTATICARRAY(srv_aplbPlayers, CPlayerBuffer, itplb) { + if (itplb->IsActive() && itplb->plb_iClient==iClient) { + ctPlayers++; + } + } + return ctPlayers; +} + +/* + * Find first inactive client. + */ +CPlayerBuffer *CServer::FirstInactivePlayer(void) +{ + // for all players in game + FOREACHINSTATICARRAY(srv_aplbPlayers, CPlayerBuffer, itplb) { + // if player is not active + if (!itplb->IsActive()) { + // return it + return &itplb.Current(); + } + } + // if no inactive players found, return error + return NULL; +} + +/* + * Check if some character already exists in this session. + */ +BOOL CServer::CharacterNameIsUsed(CPlayerCharacter &pcCharacter) +{ + // for all players in game + FOREACHINSTATICARRAY(srv_aplbPlayers, CPlayerBuffer, itplb) { + // if it is active and has same character as this one + if (itplb->IsActive() && itplb->plb_pcCharacter == pcCharacter) { + // it exists + return TRUE; + } + } + // otherwise, it doesn't exist + return FALSE; +} + +// find a mask of all players on a certain client +ULONG CServer::MaskOfPlayersOnClient(INDEX iClient) +{ + ULONG ulClientPlayers = 0; + for(INDEX ipl=0; iplga_bLocalPause || _pNetwork->IsWaitingForPlayers() || + srv_bGameFinished || ser_bWaitFirstPlayer; + if (_pNetwork->ga_sesSessionState.ses_bKeepingUpWithTime + &&(_pTimer->GetRealTimeTick()-_pNetwork->ga_sesSessionState.ses_tmLastUpdated<=_pTimer->TickQuantum*2.01f) + && !bPaused ) { + + // advance time + srv_fServerStep += _pNetwork->ga_fGameRealTimeFactor*_pNetwork->ga_sesSessionState.ses_fRealTimeFactor; + // if stepped to next tick + if (srv_fServerStep>=1.0f) { + + // find how many ticks were stepped + INDEX iSpeed = ClampDn(INDEX(srv_fServerStep), 1L); + srv_fServerStep -= iSpeed; + + // for each tick + for( INDEX i=0; i0 && (!sso.IsActive() || !sso.sso_bSendStream)) { + continue; + } + // send one regular batch of sequences to the client + SendGameStreamBlocks(iSession); + } + + _pfNetworkProfile.StopTimer(CNetworkProfile::PTI_SERVER_LOOP); +} + +// make allaction messages for one tick +void CServer::MakeAllActions(void) +{ + // increment tick counter and processed sequence + srv_tmLastProcessedTick += _pTimer->TickQuantum; + srv_iLastProcessedSequence++; + + // for each active session + for(INDEX iSession=0; iSession0 && !sso.IsActive()) { + continue; + } + + // create all-actions message + CNetworkStreamBlock nsbAllActions(MSG_SEQ_ALLACTIONS, srv_iLastProcessedSequence); + // write time there + nsbAllActions<IsActive()) { + // player indices transmission is unneccessary unless if debugging + // // write its index + // nsbAllActions<CreateActionPacket(&nsbAllActions, iSession); + } + iPlayer++; + } + + // add the all-actions block to the buffer + sso.sso_nsBuffer.AddBlock(nsbAllActions); + } + + // for all players in game + {FOREACHINSTATICARRAY(srv_aplbPlayers, CPlayerBuffer, itplb) { + // if player is active + if (itplb->IsActive()) { + // flush oldest action + itplb->AdvanceActionBuffer(); + } + }} +} + +// add a block to streams for all sessions +void CServer::AddBlockToAllSessions(CNetworkStreamBlock &nsb) +{ + // for each active session + for(INDEX iSession=0; iSession0 && !sso.IsActive()) { + continue; + } + + // add the block to the buffer + sso.sso_nsBuffer.AddBlock(nsb); + } +} + +/* Send initialization info to local client. */ +void CServer::ConnectLocalSessionState(INDEX iClient, CNetworkMessage &nm) +{ + // find session of this client + CSessionSocket &sso = srv_assoSessions[iClient]; + // activate it + sso.Activate(); + // prepare his initialization message + CNetworkMessage nmInitMainServer(MSG_REP_CONNECTLOCALSESSIONSTATE); + nmInitMainServer<>sso.sso_sspParams; + + // send him server session state initialization message + _pNetwork->SendToClientReliable(iClient, nmInitMainServer); +} + +/* Send initialization info to remote client. */ +void CServer::ConnectRemoteSessionState(INDEX iClient, CNetworkMessage &nm) +{ + ASSERT(iClient>0); + // find session of this client + CSessionSocket &sso = srv_assoSessions[iClient]; + + // if the IP is banned + if (!MatchesBanMask(_cmiComm.Server_GetClientName(iClient), ser_strIPMask) != !ser_bInverseBanning) { + // disconnect the client + SendDisconnectMessage(iClient, TRANS("You are banned from this server"), /*bStream=*/TRUE); + return; + } + + // read version info + INDEX iTag, iMajor, iMinor; + nm>>iTag; + if (iTag=='VTAG') { + nm>>iMajor>>iMinor; + } else { + iMajor = 109; + iMinor = 1; + } + // if wrong + if (iMajor!=_SE_BUILD_MAJOR || iMinor!=_SE_BUILD_MINOR) { + // disconnect the client + CTString strExplanation; + strExplanation.PrintF(TRANS( + "This server runs version %d.%d, your version is %d.%d.\n" + "Please visit http://www.croteam.com for information on version updating."), + _SE_BUILD_MAJOR, _SE_BUILD_MINOR, iMajor, iMinor); + SendDisconnectMessage(iClient, strExplanation, /*bStream=*/TRUE); + return; + } + extern CTString net_strConnectPassword; + extern CTString net_strVIPPassword; + extern CTString net_strObserverPassword; + extern INDEX net_iVIPReserve; + extern INDEX net_iMaxObservers; + extern INDEX net_iMaxClients; + CTString strGivenMod; + CTString strGivenPassword; + nm>>strGivenMod>>strGivenPassword; + INDEX ctWantedLocalPlayers; + nm>>ctWantedLocalPlayers; + // if wrong mod + if (_strModName!=strGivenMod) { + // disconnect the client + // NOTE: DO NOT TRANSLATE THIS STRING! + CTString strMod(0, "MOD:%s\\%s", _strModName, _strModURL); + SendDisconnectMessage(iClient, strMod, /*bStream=*/TRUE); + return; + } + + // get counts of allowed players, clients, vips and check for connection allowance + INDEX ctMaxAllowedPlayers = _pNetwork->ga_sesSessionState.ses_ctMaxPlayers; + INDEX ctMaxAllowedClients = ctMaxAllowedPlayers; + if (net_iMaxClients>0) { + ctMaxAllowedClients = ClampUp(net_iMaxClients, (INDEX)NET_MAXGAMECOMPUTERS); + } + INDEX ctMaxAllowedVIPPlayers = 0; + INDEX ctMaxAllowedVIPClients = 0; + if (net_iVIPReserve>0 && net_strVIPPassword!="") { + ctMaxAllowedVIPPlayers = ClampDn(net_iVIPReserve-GetVIPPlayersCount(), 0L); + ctMaxAllowedVIPClients = ClampDn(net_iVIPReserve-GetVIPClientsCount(), 0L); + } + INDEX ctMaxAllowedObservers = net_iMaxObservers; + + // get current counts + INDEX ctCurrentPlayers = GetPlayersCount(); + INDEX ctCurrentClients = GetClientsCount(); + INDEX ctCurrentObservers = GetObserversCount(); + + // check which passwords this client can satisfy + BOOL bAutorizedAsVIP = FALSE; + BOOL bAutorizedAsObserver = FALSE; + BOOL bAutorizedAsPlayer = FALSE; + if (net_strVIPPassword!="" && net_strVIPPassword==strGivenPassword) { + bAutorizedAsVIP = TRUE; + bAutorizedAsPlayer = TRUE; + bAutorizedAsObserver = TRUE; + } + if (net_strConnectPassword=="" || net_strConnectPassword==strGivenPassword) { + bAutorizedAsPlayer = TRUE; + } + if ((net_strObserverPassword==""&&bAutorizedAsPlayer) || net_strObserverPassword==strGivenPassword) { + bAutorizedAsObserver = TRUE; + } + + // if the user is not authorised as a VIP + if (!bAutorizedAsVIP) { + // artificially decrease allowed number of players and clients + ctMaxAllowedPlayers = ClampDn(ctMaxAllowedPlayers-ctMaxAllowedVIPPlayers, 0L); + ctMaxAllowedClients = ClampDn(ctMaxAllowedClients-ctMaxAllowedVIPClients, 0L); + } + + // if too many clients or players + if (ctCurrentPlayers+ctWantedLocalPlayers>ctMaxAllowedPlayers + ||ctCurrentClients+1>ctMaxAllowedClients) { + // disconnect the client + SendDisconnectMessage(iClient, TRANS("Server full!"), /*bStream=*/TRUE); + return; + } + + // if the user is trying to connect as observer + if (ctWantedLocalPlayers==0) { + // if too many observers already + if (ctCurrentObservers>=ctMaxAllowedObservers && !bAutorizedAsVIP) { + // disconnect the client + SendDisconnectMessage(iClient, TRANS("Too many observers!"), /*bStream=*/TRUE); + return; + } + // if observer password is wrong + if (!bAutorizedAsObserver) { + // disconnect the client + if (strGivenPassword=="") { + SendDisconnectMessage(iClient, TRANS("This server requires password for observers!"), /*bStream=*/TRUE); + } else { + SendDisconnectMessage(iClient, TRANS("Wrong observer password!"), /*bStream=*/TRUE); + } + } + // if the user is trying to connect as player + } else { + // if player password is wrong + if (!bAutorizedAsPlayer) { + // disconnect the client + if (strGivenPassword=="") { + SendDisconnectMessage(iClient, TRANS("This server requires password to connect!"), /*bStream=*/TRUE); + } else { + SendDisconnectMessage(iClient, TRANS("Wrong password!"), /*bStream=*/TRUE); + } + } + + } + + // activate it + sso.Activate(); + // load parameters for it + sso.sso_ctLocalPlayers = ctWantedLocalPlayers; + sso.sso_bVIP = bAutorizedAsVIP; + nm>>sso.sso_sspParams; + + // try to + try { + // create base info to be sent + extern CTString ser_strMOTD; + CTMemoryStream strmInfo; + strmInfo<ga_World.wo_fnmFileName; + strmInfo<<_pNetwork->ga_sesSessionState.ses_ulSpawnFlags; + strmInfo.Write_t(_pNetwork->ga_aubDefaultProperties, NET_MAXSESSIONPROPERTIES); + SLONG slSize = strmInfo.GetStreamSize(); + + // send the stream to the remote session state + _pNetwork->SendToClientReliable(iClient, strmInfo); + + CPrintF(TRANS("Server: Sent initialization info to '%s' (%dk)\n"), + (const char*)_cmiComm.Server_GetClientName(iClient), slSize/1024); + // if failed + } catch (char *strError) { + // deactivate it + sso.Deactivate(); + + // report error + CPrintF(TRANS("Server: Cannot prepare connection data: %s\n"), strError); + } +} + +/* Send session state data to remote client. */ +void CServer::SendSessionStateData(INDEX iClient) +{ + ASSERT(iClient>0); + // find session of this client + CSessionSocket &sso = srv_assoSessions[iClient]; + // copy its buffer from local session state + sso.sso_nsBuffer.Copy(srv_assoSessions[0].sso_nsBuffer); + + // try to + try { + // prepare files or memory streams for connection info + CTFileStream strmStateFile; CTMemoryStream strmStateMem; + CTFileStream strmDeltaFile; CTMemoryStream strmDeltaMem; + CTStream *pstrmState; CTMemoryStream *pstrmDelta; + extern INDEX net_bDumpConnectionInfo; + + UBYTE* pubSrc = NULL; + /*if (net_bDumpConnectionInfo) { + strmStateFile.Create_t(CTString("Temp\\State.bin")); + strmDeltaFile.Create_t(CTString("Temp\\Delta.bin")); + pstrmState = &strmStateFile; + pstrmDelta = &strmDeltaFile; + } else {*/ + pstrmState = &strmStateMem; + pstrmDelta = &strmDeltaMem; + + pubSrc = strmDeltaMem.mstrm_pubBuffer + strmDeltaMem.mstrm_slLocation; + //} + + ASSERT(pubSrc != NULL); + + // write main session state + _pNetwork->ga_sesSessionState.Write_t(pstrmState); + pstrmState->SetPos_t(0); + SLONG slFullSize = pstrmState->GetStreamSize(); + + CTMemoryStream strmInfo; + strmInfo<ga_pubDefaultState, _pNetwork->ga_slDefaultStateSize); + strmDefaultState.SetPos_t(0); + DIFF_Diff_t(&strmDefaultState, pstrmState, pstrmDelta); + pstrmDelta->SetPos_t(0); + SLONG slDeltaSize = pstrmDelta->GetStreamSize(); + CzlibCompressor comp; + comp.PackStream_t(*pstrmDelta, strmInfo); + + SLONG slSize = strmInfo.GetStreamSize(); + + // send the stream to the remote session state + _pNetwork->SendToClientReliable(iClient, strmInfo); + + CPrintF(TRANS("Server: Sent connection data to '%s' (%dk->%dk->%dk)\n"), + (const char*)_cmiComm.Server_GetClientName(iClient), + slFullSize/1024, slDeltaSize/1024, slSize/1024); + if (net_bDumpConnectionInfo) { + CPrintF(TRANS("Server: Connection data dumped.\n")); + } + + // if failed + } catch (char *strError) { + // deactivate it + sso.Deactivate(); + + // report error + CPrintF(TRANS("Server: Cannot prepare connection data: %s\n"), strError); + } +} + +/* Handle incoming network messages. */ +void CServer::HandleAll() +{ + // clear last accepted client info + INDEX iClient = -1; +/* if (_cmiComm.GetLastAccepted(iClient)) { + CPrintF(TRANS("Server: Accepted session connection by '%s'\n"), + _cmiComm.Server_GetClientName(iClient)); + } + */ + + // for each active client + {for( INDEX iClient=0; iClient0 && + sso.sso_tmLastSyncReceived<_pNetwork->ga_sesSessionState.ses_tmLastSyncCheck - + (2*ser_iSyncCheckBuffer*_pNetwork->ga_sesSessionState.ses_tmSyncCheckFrequency)) { + SendDisconnectMessage(iClient, TRANS("No valid SYNCCHECK received for too long!")); + } + + if (iClient>0 && sso.sso_bActive && sso.sso_bSendStream && sso.sso_tvMessageReceived.tv_llValue>0 && + (_pTimer->GetHighPrecisionTimer()-sso.sso_tvMessageReceived).GetSeconds()>net_tmDisconnectTimeout) { + SendDisconnectMessage(iClient, TRANS("Connection timeout")); + } + + // if the client is disconnected + if (!_cmiComm.Server_IsClientUsed(iClient) || sso.sso_iDisconnectedState>1) { + CPrintF(TRANS("Server: Client '%s' disconnected.\n"), _cmiComm.Server_GetClientName(iClient)); + // clear it + _cmiComm.Server_ClearClient(iClient); + // free all that data that was allocated for the client + HandleClientDisconected(iClient); + } + + CNetworkMessage nmReceived; + // repeat + FOREVER { + // if there is some reliable message + if (_pNetwork->ReceiveFromClientReliable(iClient, nmReceived)) { + // process it + Handle(iClient, nmReceived); + + // if there are no more messages + } else { + // skip to receiving unreliable + break; + } + } + + // if the client has confirmed disconnect in this loop + if (!_cmiComm.Server_IsClientUsed(iClient) || sso.sso_iDisconnectedState>1) { + CPrintF(TRANS("Server: Client '%s' disconnected.\n"), _cmiComm.Server_GetClientName(iClient)); + // clear it + _cmiComm.Server_ClearClient(iClient); + // free all that data that was allocated for the client + HandleClientDisconected(iClient); + } + + // repeat + FOREVER { + // if there is some unreliable message + if (_pNetwork->ReceiveFromClient(iClient, nmReceived)) { + // process it + Handle(iClient, nmReceived); + // if there are no more messages + } else { + // finish with this client + break; + } + } +} + +void CServer::HandleClientDisconected(INDEX iClient) +{ + // find session of this client + CSessionSocket &sso = srv_assoSessions[iClient]; + // deactivate it + sso.Deactivate(); + + INDEX iPlayer = 0; + FOREACHINSTATICARRAY(srv_aplbPlayers, CPlayerBuffer, itplb) { + // if player is on that client + if (itplb->plb_iClient==iClient) { + // create message for removing player from all session + CNetworkStreamBlock nsbRemPlayerData(MSG_SEQ_REMPLAYER, ++srv_iLastProcessedSequence); + nsbRemPlayerData<Deactivate(); + } + iPlayer++; + } +} + +// split the rcon response string into lines and send one by one to the client +static void SendAdminResponse(INDEX iClient, const CTString &strResponse) +{ + CTString str = strResponse; + + while (str!="") { + CTString strLine = str; + strLine.OnlyFirstLine(); + str.RemovePrefix(strLine); + str.DeleteChar(0); + if (strLine.Length()>0) { + CNetworkMessage nm(MSG_ADMIN_RESPONSE); + nm<SendToClientReliable(iClient, nm); + } + } +} + +void CServer::Handle(INDEX iClient, CNetworkMessage &nmMessage) +{ + CSessionSocket &sso = srv_assoSessions[iClient]; + sso.sso_tvMessageReceived = _pTimer->GetHighPrecisionTimer(); + + switch (nmMessage.GetType()) { + + // if if it is just keepalive, ignore it + case MSG_KEEPALIVE: break; + case MSG_REP_DISCONNECTED: { + CSessionSocket &sso = srv_assoSessions[iClient]; + sso.sso_iDisconnectedState=2; + } break; + + // if local session state asks for registration + case MSG_REQ_CONNECTLOCALSESSIONSTATE: { + ConnectLocalSessionState(iClient, nmMessage); + } break; + // if remote server asks for registration + case MSG_REQ_CONNECTREMOTESESSIONSTATE: { + ConnectRemoteSessionState(iClient, nmMessage); + } break; + // if remote server asks for data + case MSG_REQ_STATEDELTA: { + CPrintF(TRANS("Sending statedelta response\n")); + SendSessionStateData(iClient); + } break; + // if player asks for registration + case MSG_REQ_CONNECTPLAYER: { + + // check that someone doesn't add too many players + if (iClient>0 && GetPlayersCountForClient(iClient)>=sso.sso_ctLocalPlayers) { + CTString strMessage; + strMessage.PrintF(TRANS("Protocol violation")); + SendDisconnectMessage(iClient, strMessage); + } + + // read character data from the message + CPlayerCharacter pcCharacter; + nmMessage>>pcCharacter; + + // if the name is banned + if (!MatchesBanMask(pcCharacter.GetName(), ser_strNameMask) != !ser_bInverseBanning) { + // disconnect the client + SendDisconnectMessage(iClient, TRANS("You are banned from this server"), /*bStream=*/TRUE); + return; + } + + CPlayerBuffer *pplbNewClient; + + // find some inactive player + pplbNewClient = FirstInactivePlayer(); + // if there is some active player with same character name + if (CharacterNameIsUsed(pcCharacter)) { + // send refusal message + CTString strMessage; + strMessage.PrintF(TRANS("Player character '%s' already exists in this session."), + pcCharacter.GetName()); + SendDisconnectMessage(iClient, strMessage); + + // if the max. number of clients is not reached + } else if (pplbNewClient!=NULL) { + // activate it + pplbNewClient->Activate(iClient); + INDEX iNewPlayer = pplbNewClient->plb_Index; + + // remember its character + pplbNewClient->plb_pcCharacter = pcCharacter; + + // create message for adding player data to sessions + CNetworkStreamBlock nsbAddClientData(MSG_SEQ_ADDPLAYER, ++srv_iLastProcessedSequence); + nsbAddClientData<SendToClientReliable(iClient, nmPlayerRegistered); + + // notify gameagent + GameAgent_ServerStateChanged(); + // if refused + } else { + // send him refusal message + SendDisconnectMessage(iClient, TRANS("Too many players in session.")); + } + } break; + + // if client source wants to change character + case MSG_REQ_CHARACTERCHANGE: { + // read character data from the message + INDEX iPlayer; + CPlayerCharacter pcCharacter; + nmMessage>>iPlayer>>pcCharacter; + // first check if the request is valid + if (iPlayer<0 || iPlayer>srv_aplbPlayers.Count() ) { + break; + } + CPlayerBuffer &plb = srv_aplbPlayers[iPlayer]; + if (plb.plb_iClient!=iClient || !(plb.plb_pcCharacter==pcCharacter) ) { + break; + } + + // if all was right, add that as change a sequence + CNetworkStreamBlock nsbChangeChar(MSG_SEQ_CHARACTERCHANGE, ++srv_iLastProcessedSequence); + nsbChangeChar<0) { + if (sso.sso_ctBadSyncs>=ser_iKickOnSyncBad) { + SendDisconnectMessage(iClient, TRANS("Too many bad syncs")); + } + } else if( ser_bPauseOnSyncBad) { + _pNetwork->ga_sesSessionState.ses_bWantPause = TRUE; + } + } else { + sso.sso_ctBadSyncs = 0; + if (ser_bReportSyncOK) { + CPrintF( TRANS("SYNCOK: Client '%s', Tick %.2f\n"), + _cmiComm.Server_GetClientName(iClient), scRemote.sc_tmTick); + } + } + + // remember that this client has sent sync for that tick + if (srv_assoSessions[iClient].sso_tmLastSyncReceived0) { + CPrintF( TRANS("SYNCLATE: Client '%s', Tick %.2f\n"), + _cmiComm.Server_GetClientName(iClient), scRemote.sc_tmTick); + } + // if too new + } else { + if( ser_bReportSyncEarly) { + CPrintF( TRANS("SYNCEARLY: Client '%s', Tick %.2f\n"), + _cmiComm.Server_GetClientName(iClient), scRemote.sc_tmTick); + } + // remember that this client has sent sync for that tick + // (even though we cannot really check that it is valid) + if (srv_assoSessions[iClient].sso_tmLastSyncReceived>iSequence0; + nmMessage>>ctSequences; + // resend the game stream blocks to the server + ResendGameStreamBlocks(iClient, iSequence0, ctSequences); + } break; + // if a client wants to toggle pause + case MSG_REQ_PAUSE: { + // read the pause state from the message + BOOL bWantPause; + nmMessage>>(INDEX&)bWantPause; + // if state is new + if (!srv_bPause != !bWantPause) { + + // if the client may pause + extern INDEX ser_bClientsMayPause; + if (_cmiComm.Server_IsClientLocal(iClient) || ser_bClientsMayPause) { + // change it + srv_bPause = bWantPause; + // add the pause state block to the buffer to be sent to all clients + CNetworkStreamBlock nsbPause(MSG_SEQ_PAUSE, ++srv_iLastProcessedSequence); + nsbPause<<(INDEX&)srv_bPause; + nsbPause<<_cmiComm.Server_GetClientName(iClient); + AddBlockToAllSessions(nsbPause); + } + } + } break; + // if a player wants to change its buffer settings + case MSG_SET_CLIENTSETTINGS: { + // read data + CSessionSocket &sso = srv_assoSessions[iClient]; + nmMessage>>sso.sso_sspParams; + } break; + // if a chat message was sent + case MSG_CHAT_IN: { + // get it + ULONG ulFrom, ulTo; + CTString strMessage; + nmMessage>>ulFrom>>ulTo>>strMessage; + + // filter the from address by the client's players + ulFrom &= MaskOfPlayersOnClient(iClient); + // if the source has no players + if (ulFrom==0) { + // make it public message + ulTo = -1; + } + + // make the outgoing message + CNetworkMessage nmOut(MSG_CHAT_OUT); + nmOut<0 && !sso.IsActive()) { + continue; + } + // if message is public or the client has some of destination players + if (ulTo==-1 || ulTo&MaskOfPlayersOnClient(iSession)) { + // send the message to that computer + _pNetwork->SendToClient(iSession, nmOut); + } + } + + } break; + // if a crc response is received + case MSG_REQ_CRCLIST: { + CPrintF(TRANS("Sending CRC response\n")); + // create CRC challenge + CTMemoryStream strmCRC; + strmCRC<ga_pubCRCList, _pNetwork->ga_slCRCList); + SLONG slSize = strmCRC.GetStreamSize(); + + // send the stream to the remote session state + _pNetwork->SendToClientReliable(iClient, strmCRC); + CPrintF(TRANS("Server: Sent CRC challenge to '%s' (%dk)\n"), + (const char*)_cmiComm.Server_GetClientName(iClient), slSize/1024); + + } break; + // if a crc response is received + case MSG_REP_CRCCHECK: { + // get it + ULONG ulCRC; + INDEX iLastSequence; + nmMessage>>ulCRC>>iLastSequence; + // if not same + if (_pNetwork->ga_ulCRC!=ulCRC) { + // disconnect the client + SendDisconnectMessage(iClient, TRANS("Wrong CRC check.")); + // if same + } else { + CPrintF(TRANS("Server: Client '%s', CRC check OK\n"), + (const char*)_cmiComm.Server_GetClientName(iClient)); + // use the piggybacked sequence number to initiate sending stream to it + CSessionSocket &sso = srv_assoSessions[iClient]; + sso.sso_bSendStream = TRUE; + sso.sso_nsBuffer.RemoveOlderBlocksBySequence(iLastSequence); + sso.sso_iLastSentSequence = iLastSequence; + } + + } break; + // if a rcon request is received + case MSG_ADMIN_COMMAND: { + extern CTString net_strAdminPassword; + // get it + CTString strPassword, strCommand; + nmMessage>>strPassword>>strCommand; + if (net_strAdminPassword=="") { + CNetworkMessage nmRes(MSG_ADMIN_RESPONSE); + nmRes<SendToClientReliable(iClient, nmRes); + } else if (net_strAdminPassword!=strPassword) { + CPrintF(TRANS("Server: Client '%s', Wrong password for remote administration.\n"), + (const char*)_cmiComm.Server_GetClientName(iClient)); + SendDisconnectMessage(iClient, TRANS("Wrong admin password. The attempt was logged.")); + break; + } else { + + CPrintF(TRANS("Server: Client '%s', Admin cmd: %s\n"), + (const char*)_cmiComm.Server_GetClientName(iClient), strCommand); + + con_bCapture = TRUE; + con_strCapture = ""; + _pShell->Execute(strCommand+";"); + + CTString strResponse = CTString(">")+strCommand+"\n"+con_strCapture; + SendAdminResponse(iClient, strResponse); + con_bCapture = FALSE; + con_strCapture = ""; + } + } break; + // otherwise + default: + ASSERT(FALSE); + } +} diff --git a/Sources/Engine/Network/Server.h b/Sources/Engine/Network/Server.h new file mode 100644 index 0000000..e6bb039 --- /dev/null +++ b/Sources/Engine/Network/Server.h @@ -0,0 +1,98 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SERVER_H +#define SE_INCL_SERVER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include + +/* + * Server, manages game joining and similar, routes messages from PlayerSource to PlayerTarget + */ +class CServer { +public: + BOOL srv_bActive; // set if started + + CStaticArray srv_assoSessions; // client computers in game + CStaticArray srv_aplbPlayers; // player buffers for all clients in game + CStaticArray srv_ascChecks; // remembered sync checks + + TIME srv_tmLastProcessedTick; // last tick when all actions have been resent + INDEX srv_iLastProcessedSequence; // sequence of last sent game stream block + + BOOL srv_bPause; // set while game is paused + BOOL srv_bGameFinished; // set while game is finished + FLOAT srv_fServerStep; // counter for smooth time slowdown/speedup +public: + /* Send disconnect message to some client. */ + void SendDisconnectMessage(INDEX iClient, const char *strExplanation, BOOL bStream = FALSE); + /* Get total number of active players. */ + INDEX GetPlayersCount(void); + /* Get number of active vip players. */ + INDEX GetVIPPlayersCount(void); + /* Get total number of active clients. */ + INDEX GetClientsCount(void); + /* Get number of active vip clients. */ + INDEX GetVIPClientsCount(void); + /* Get number of active observers. */ + INDEX GetObserversCount(void); + /* Get number of active players on one client. */ + INDEX GetPlayersCountForClient(INDEX iClient); + /* Find first inactive player. */ + CPlayerBuffer *FirstInactivePlayer(void); + /* Check if some character name already exists in this session. */ + BOOL CharacterNameIsUsed(CPlayerCharacter &pcCharacter); + + /* Send initialization info to local client. */ + void ConnectLocalSessionState(INDEX iClient, CNetworkMessage &nm); + /* Send initialization info to remote client. */ + void ConnectRemoteSessionState(INDEX iClient, CNetworkMessage &nm); + /* Send session state data to remote client. */ + void SendSessionStateData(INDEX iClient); + + /* Send one regular batch of sequences to a client. */ + void SendGameStreamBlocks(INDEX iClient); + /* Resend a batch of game stream blocks to a client. */ + void ResendGameStreamBlocks(INDEX iClient, INDEX iSequence0, INDEX ctSequences); + + // add a new sync check to buffer + void AddSyncCheck(const CSyncCheck &sc); + // try to find a sync check for given time in the buffer (-1==too old, 0==found, 1==toonew) + INDEX FindSyncCheck(TIME tmTick, CSyncCheck &sc); + + // make allaction messages for one tick + void MakeAllActions(void); + // add a block to streams for all sessions + void AddBlockToAllSessions(CNetworkStreamBlock &nsb); + // find a mask of all players on a certain client + ULONG MaskOfPlayersOnClient(INDEX iClient); +public: + /* Constructor. */ + CServer(void); + /* Destructor. */ + ~CServer(); + + /* Start server. */ + void Start_t(void); + /* Stop server. */ + void Stop(void); + /* Run server loop. */ + void ServerLoop(void); + /* Make synchronization test message and add it to game stream. */ + void MakeSynchronisationCheck(void); + + /* Handle incoming network messages. */ + void HandleAll(); + void HandleAllForAClient(INDEX iClient); + void HandleClientDisconected(INDEX iClient); + void Handle(INDEX iClient, CNetworkMessage &nm); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/SessionSocket.h b/Sources/Engine/Network/SessionSocket.h new file mode 100644 index 0000000..e8c7f11 --- /dev/null +++ b/Sources/Engine/Network/SessionSocket.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SESSIONSOCKET_H +#define SE_INCL_SESSIONSOCKET_H +#ifdef PRAGMA_ONCE + #pragma once +#endif +#include + +// parameters for a client +class CSessionSocketParams { +public: + INDEX ssp_iBufferActions; + INDEX ssp_iMaxBPS; + INDEX ssp_iMinBPS; + +public: + CSessionSocketParams(void); + void Clear(void); + + // check if up to date with current params + BOOL IsUpToDate(void); + // update + void Update(void); + + // message operations + friend CNetworkMessage &operator<<(CNetworkMessage &nm, CSessionSocketParams &ssp); + friend CNetworkMessage &operator>>(CNetworkMessage &nm, CSessionSocketParams &ssp); +}; + +// connection data for each session connected to a server +class CSessionSocket { +public: + BOOL sso_bActive; + BOOL sso_bSendStream; + CTimerValue sso_tvMessageReceived; + TIME sso_tmLastSyncReceived; + INDEX sso_iDisconnectedState; + INDEX sso_iLastSentSequence; + INDEX sso_ctBadSyncs; // counter of bad sync in row + CTimerValue sso_tvLastMessageSent; // for sending keep-alive messages + CTimerValue sso_tvLastPingSent; // for sending ping + CNetworkStream sso_nsBuffer; // stream of blocks buffered for sending + CSessionSocketParams sso_sspParams; // parameters that the client wants + INDEX sso_ctLocalPlayers; // number of players that this client will connect + BOOL sso_bVIP; // set if the client was successfully authorized as a VIP +public: + CSessionSocket(void); + ~CSessionSocket(void); + void Clear(void); + void Activate(void); + void Deactivate(void); + BOOL IsActive(void); +}; + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Network/SessionState.cpp b/Sources/Engine/Network/SessionState.cpp new file mode 100644 index 0000000..4be6556 --- /dev/null +++ b/Sources/Engine/Network/SessionState.cpp @@ -0,0 +1,2215 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define SESSIONSTATEVERSION_OLD 1 +#define SESSIONSTATEVERSION_WITHBULLETTIME 2 +#define SESSIONSTATEVERSION_CURRENT SESSIONSTATEVERSION_WITHBULLETTIME + +//#define DEBUG_LERPING 1 + +extern INDEX net_bLerping; +extern FLOAT net_tmConnectionTimeout; +extern FLOAT net_tmProblemsTimeOut; +extern FLOAT net_tmDisconnectTimeout; + +// this is from ProgresHook.cpp - so we tell the progresshook to run client/srever updates +extern BOOL _bRunNetUpdates; + +#if DEBUG_LERPING + +FLOAT avfStats[1000][4]; +INDEX ctCounter=0; +INDEX ctMax = sizeof(avfStats)/sizeof(avfStats[0]); + +#endif // DEBUG_LERPING + +// get a pseudo-random number (safe for network gaming) +ULONG CSessionState::Rnd(void) { + ASSERTMSG(ses_bAllowRandom, "Use RND only in entity AI!"); + // NOTE: + // using multiplicative congruent method with Greanberger's lambda = 2^18+3 + ses_ulRandomSeed = ses_ulRandomSeed*262147; + ASSERT(ses_ulRandomSeed!=0); + return ses_ulRandomSeed; +} + +// reset random number generator (always randomizes to same sequence!) +void CSessionState::ResetRND(void) +{ + BOOL bOldAllow = ses_bAllowRandom; + ses_bAllowRandom = TRUE; + // random must start at a number different than zero! + ses_ulRandomSeed = 0x87654321; + // run rnd a few times to make it go random + for(INDEX i=0; i<32; i++) { + Rnd(); + } + ses_bAllowRandom = bOldAllow; +} + +/* + * Constructor. + */ +CSessionState::CSessionState(void) +{ + ses_bKeepingUpWithTime = TRUE; + ses_tmLastUpdated = -100; + ses_bAllowRandom = TRUE; // random allowed when not in game + ses_bPredicting = FALSE; + ses_tmPredictionHeadTick = -2.0f; + ses_tmLastSyncCheck = 0; + ses_tmLastPredictionProcessed = -200; + + ses_bPause = FALSE; + ses_bWantPause = FALSE; + ses_bGameFinished = FALSE; + ses_bWaitingForServer = FALSE; + ses_strDisconnected = ""; + ses_ctMaxPlayers = 1; + ses_bWaitAllPlayers = FALSE; + ses_iLevel = 0; + ses_fRealTimeFactor = 1.0f; + + ses_pstrm = NULL; + // reset random number generator + ResetRND(); + + ses_apltPlayers.New(NET_MAXGAMEPLAYERS); +} + +/* + * Destructor. + */ +CSessionState::~CSessionState() +{ +} + +/* + * Clear the object. + */ +void CSessionState::Stop(void) +{ +#if DEBUG_SYNCSTREAMDUMPING + ClearDumpStream(); +#endif +#if DEBUG_SYNCSTREAMDUMPING +#endif + + ses_bKeepingUpWithTime = TRUE; + ses_tmLastUpdated = -100; + ses_bAllowRandom = TRUE; // random allowed when not in game + ses_bPredicting = FALSE; + ses_tmPredictionHeadTick = -2.0f; + ses_tmLastSyncCheck = 0; + ses_bPause = FALSE; + ses_bWantPause = FALSE; + ses_bGameFinished = FALSE; + ses_bWaitingForServer = FALSE; + ses_strDisconnected = ""; + ses_ctMaxPlayers = 1; + ses_fRealTimeFactor = 1.0f; + ses_bWaitAllPlayers = FALSE; + ses_apeEvents.PopAll(); + + // disable lerping + _pTimer->DisableLerp(); + +#if DEBUG_LERPING + + CTFileStream f; + f.Create_t(CTFILENAME("Temp\\Lerp.stats"), CTStream::CM_TEXT); + for (INDEX i=0; iSendToServerReliable(nmConfirmDisconnect); + } + _cmiComm.Client_Close(); + + // clear all old levels + ForgetOldLevels(); + + ses_apltPlayers.Clear(); + ses_apltPlayers.New(NET_MAXGAMEPLAYERS); +} + +/* + * Initialize session state and wait for game to be started. + */ +void CSessionState::Start_t(INDEX ctLocalPlayers) +{ + ses_bKeepingUpWithTime = TRUE; + ses_tmLastUpdated = -100; + // clear message stream + ses_nsGameStream.Clear(); + ses_bAllowRandom = FALSE; // random not allowed in game + ses_bPredicting = FALSE; + ses_tmPredictionHeadTick = -2.0f; + ses_tmLastSyncCheck = 0; + ses_bPause = FALSE; + ses_bWantPause = FALSE; + ses_bWaitingForServer = FALSE; + ses_bGameFinished = FALSE; + ses_strDisconnected = ""; + ses_ctMaxPlayers = 1; + ses_fRealTimeFactor = 1.0f; + ses_bWaitAllPlayers = FALSE; + ses_iMissingSequence = -1; + ses_apeEvents.PopAll(); + ses_tvMessageReceived.Clear(); + _pNetwork->ga_strRequiredMod = ""; + + // reset random number generator + ResetRND(); + + // clear all old levels + ForgetOldLevels(); + +#if DEBUG_LERPING + // clear lerp stats + ctCounter = 0; +#endif // DEBUG_LERPING + + // ses_LastProcessedTick and ses_LastReceivedTick tick counters are + // irrelevant now, will be initialized when initialization message + // from server is received, no need to set them here + + // if this computer is server + if (_pNetwork->IsServer()) { + // initialize local client + _cmiComm.Client_Init_t(0UL); + // connect as main session state + try { + Start_AtServer_t(); + } catch(char *) { + _cmiComm.Client_Close(); + throw; + } + + // if this computer is client + } else { + // connect client to server computer + _cmiComm.Client_Init_t((char*)(const char*)_pNetwork->ga_strServerAddress); + // connect as remote session state + try { + Start_AtClient_t(ctLocalPlayers); + } catch(char *) { + // if failed due to wrong mod + if (strncmp(ses_strDisconnected, "MOD:", 4)==0) { + // remember the mod + _pNetwork->ga_strRequiredMod = ses_strDisconnected+4; + // make sure that the string is never empty + if (_pNetwork->ga_strRequiredMod=="") { + _pNetwork->ga_strRequiredMod=" "; + } + } + _cmiComm.Client_Close(); + throw; + } + } +} + +void CSessionState::Start_AtServer_t(void) // throw char * +{ + // send registration request + CNetworkMessage nmRegisterMainSessionState(MSG_REQ_CONNECTLOCALSESSIONSTATE); + ses_sspParams.Update(); + nmRegisterMainSessionState<SendToServerReliable(nmRegisterMainSessionState); + + for(TIME tmWait=0; tmWaitTimerLoop(); + if (_cmiComm.Client_Update() == FALSE) { + break; + } + + // wait for message to come + CNetworkMessage nmReceived; + if (!_pNetwork->ReceiveFromServerReliable(nmReceived)) { + continue; + } + // if this is the init message + if (nmReceived.GetType() == MSG_REP_CONNECTLOCALSESSIONSTATE) { + // just adjust your tick counters + nmReceived>>ses_tmLastProcessedTick; + nmReceived>>ses_iLastProcessedSequence; + ses_tmInitializationTick = -1.0f; + ses_tmInitializationTick2 = -1.0f; + // finish waiting + return; + // otherwise + } else { + // it is invalid message + ThrowF_t(TRANS("Invalid message while waiting for server session registration")); + } + + // if client is disconnected + if (!_cmiComm.Client_IsConnected()) { + // quit + ThrowF_t(TRANS("Client disconnected")); + } + } + ThrowF_t(TRANS("Timeout while waiting for server session registration")); +} + +void CSessionState::Start_AtClient_t(INDEX ctLocalPlayers) // throw char * +{ + // send one unreliable packet to server to make the connection up and running + CNetworkMessage nmKeepAlive(MSG_KEEPALIVE); + _pNetwork->SendToServer(nmKeepAlive); + + // send registration request + CNetworkMessage nmRegisterSessionState(MSG_REQ_CONNECTREMOTESESSIONSTATE); + nmRegisterSessionState<SendToServerReliable(nmRegisterSessionState); + + // prepare file or memory stream for state + CTFileStream strmStateFile; CTMemoryStream strmStateMem; + CTStream *pstrmState; + extern INDEX net_bDumpConnectionInfo; + if (net_bDumpConnectionInfo) { + strmStateFile.Create_t(CTString("Temp\\DefaultState.bin")); + pstrmState = &strmStateFile; + } else { + pstrmState = &strmStateMem; + } + + { + // wait for server's response + CTMemoryStream strmMessage; + WaitStream_t(strmMessage, "reply", MSG_REP_CONNECTREMOTESESSIONSTATE); + // get motd + strmMessage>>ses_strMOTD; + // get info for creating default state + CTFileName fnmWorld; + strmMessage>>fnmWorld; + ULONG ulSpawnFlags; + strmMessage>>ulSpawnFlags; + UBYTE aubProperties[NET_MAXSESSIONPROPERTIES]; + strmMessage.Read_t(aubProperties, NET_MAXSESSIONPROPERTIES); + // create default state + NET_MakeDefaultState_t(fnmWorld, ulSpawnFlags, aubProperties, *pstrmState); + pstrmState->SetPos_t(0); + } + + // send one unreliable packet to server to make the connection up and running + {CNetworkMessage nmKeepAlive(MSG_KEEPALIVE); + _pNetwork->SendToServer(nmKeepAlive); } + // send data request + CPrintF(TRANS("Sending statedelta request\n")); + CNetworkMessage nmRequestDelta(MSG_REQ_STATEDELTA); + _pNetwork->SendToServerReliable(nmRequestDelta); + + { + // wait for server's response + CTMemoryStream strmMessage; + WaitStream_t(strmMessage, "data", MSG_REP_STATEDELTA); + // decompress saved session state + CTMemoryStream strmDelta; + CzlibCompressor comp; + comp.UnpackStream_t(strmMessage, strmDelta); + CTMemoryStream strmNew; + DIFF_Undiff_t(pstrmState, &strmDelta, &strmNew); + strmNew.SetPos_t(0); + + // read the initialization information from the stream + Read_t(&strmNew); + ses_tmInitializationTick = -1.0f; + ses_tmInitializationTick2 = -1.0f; + } + + // send one unreliable packet to server to make the connection up and running + {CNetworkMessage nmKeepAlive(MSG_KEEPALIVE); + _pNetwork->SendToServer(nmKeepAlive); } + + CPrintF(TRANS("Sending CRC request\n")); + // send data request + CNetworkMessage nmRequestCRC(MSG_REQ_CRCLIST); + _pNetwork->SendToServerReliable(nmRequestCRC); + + { + // wait for CRC challenge + CTMemoryStream strmMessage; + WaitStream_t(strmMessage, "CRC", MSG_REQ_CRCCHECK); + + // make response + CNetworkMessage nmCRC(MSG_REP_CRCCHECK); + nmCRC<SendToServerReliable(nmCRC); + } + + // send one unreliable packet to server to make the connection up and running + {CNetworkMessage nmKeepAlive(MSG_KEEPALIVE); + _pNetwork->SendToServer(nmKeepAlive); } +} + +// notify entities of level change +void CSessionState::SendLevelChangeNotification(CEntityEvent &ee) +{ + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(_pNetwork->ga_World.wo_cenEntities, CEntity, iten) { + // if it should be notified + if (iten->en_ulFlags&ENF_NOTIFYLEVELCHANGE) { + // send the event + iten->SendEvent(ee); + } + }} +} + +// wait for a stream to come from server +void CSessionState::WaitStream_t(CTMemoryStream &strmMessage, const CTString &strName, + INDEX iMsgCode) +{ + + // start waiting for server's response + SetProgressDescription(TRANS("waiting for ")+strName); + CallProgressHook_t(0.0f); + SLONG slReceivedLast = 0; + + // yes, we need the client/server updates in the progres hook + _bRunNetUpdates = TRUE; + // repeat until timed out + for(TIME tmWait=0; tmWaitReceiveFromServerReliable(strmMessage)) { + // continue waiting + continue; + } + // read message identifier + strmMessage.SetPos_t(0); + INDEX iID; + strmMessage>>iID; + + // if this is the message + if (iID == iMsgCode) { + // all ok + CallProgressHook_t(1.0f); + // no more client/server updates in the progres hook + _bRunNetUpdates = TRUE; + return; + // if disconnected + } else if (iID == MSG_INF_DISCONNECTED) { + // confirm disconnect + CNetworkMessage nmConfirmDisconnect(MSG_REP_DISCONNECTED); + _pNetwork->SendToServerReliable(nmConfirmDisconnect); + // report the reason + CTString strReason; + strmMessage>>strReason; + ses_strDisconnected = strReason; + // no more client/server updates in the progres hook + _bRunNetUpdates = FALSE; + ThrowF_t(TRANS("Disconnected: %s\n"), strReason); + // otherwise + } else { + // no more client/server updates in the progres hook + _bRunNetUpdates = FALSE; + // it is invalid message + ThrowF_t(TRANS("Invalid stream while waiting for %s"), strName); + } + + // if client is disconnected + if (!_cmiComm.Client_IsConnected()) { + // no more client/server updates in the progres hook + _bRunNetUpdates = FALSE; + // quit + ThrowF_t(TRANS("Client disconnected")); + } + } + + // no more client/server updates in the progres hook + _bRunNetUpdates = FALSE; + +// CNetworkMessage nmConfirmDisconnect(MSG_REP_DISCONNECTED); +// _pNetwork->SendToServerReliable(nmConfirmDisconnect); + + + ThrowF_t(TRANS("Timeout while waiting for %s"), strName); +} + +// check if disconnected +BOOL CSessionState::IsDisconnected(void) +{ + return ses_strDisconnected!=""; +} + +// print an incoming chat message to console +void CSessionState::PrintChatMessage(ULONG ulFrom, const CTString &strFrom, const CTString &strMessage) +{ + CTString strSender; + // if no sender players + if (ulFrom==0) { + // take symbolic sender string + strSender = strFrom; + // if there are sender players + } else { + // for each sender player + for(INDEX ipl=0; iplGetPlayerName(); + } + } + } + + // let eventual script addon process the message + extern CTString cmd_strChatSender ; + extern CTString cmd_strChatMessage; + extern CTString cmd_cmdOnChat; + cmd_strChatSender = strSender; + cmd_strChatMessage = strMessage; + if (cmd_cmdOnChat!="") { + _pShell->Execute(cmd_cmdOnChat); + } + + // if proccessing didn't kill it + if (cmd_strChatSender!="" && cmd_strChatMessage!="") { + // print the message + CPrintF("%s: ^o^cFFFFFF%s^r\n", (const char*)cmd_strChatSender, (const char*)cmd_strChatMessage); + } + extern INDEX net_ctChatMessages; + net_ctChatMessages++; +} + +/* NOTES: +1) New thinkers might be added by current ones, but it doesn't matter, +since they must be added forward in time and the list is sorted, so they +cannot be processed in this tick. +2) Thinkers/Movers can be removed during iteration, but the CEntityPointer +guarantee that they are not freed from memory. +*/ + +// do physics for a game tick +void CSessionState::HandleMovers(void) +{ + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_HANDLEMOVERS); + +// CPrintF("---- tick %g\n", _pTimer->CurrentTick()); + + // put all movers in active list, pushing ones first + CListHead lhActiveMovers, lhDoneMovers, lhDummyMovers; + {FORDELETELIST(CMovableEntity, en_lnInMovers, _pNetwork->ga_World.wo_lhMovers, itenMover) { + CMovableEntity *pen = itenMover; + pen->en_lnInMovers.Remove(); + // if predicting, and it is not a predictor + if (ses_bPredicting && !pen->IsPredictor()) { + // skip it + lhDummyMovers.AddTail(pen->en_lnInMovers); + continue; + } + if (!(pen->en_ulFlags&ENF_DELETED)) { + if ((pen->en_ulPhysicsFlags&EPF_ONBLOCK_MASK)==EPF_ONBLOCK_PUSH) { + lhActiveMovers.AddHead(pen->en_lnInMovers); + } else { + lhActiveMovers.AddTail(pen->en_lnInMovers); + } + } + }} + + // for each active mover + {FORDELETELIST(CMovableEntity, en_lnInMovers, lhActiveMovers, itenMover) { + // let it clear its temporary variables to prevent bad syncs + itenMover->ClearMovingTemp(); + }} + + // for each active mover + {FORDELETELIST(CMovableEntity, en_lnInMovers, lhActiveMovers, itenMover) { + // let it calculate its wanted parameters for this tick + itenMover->PreMoving(); + }} + + // while there are some active movers + while(!lhActiveMovers.IsEmpty()) { + // get first one + CMovableEntity *penMoving = LIST_HEAD(lhActiveMovers, CMovableEntity, en_lnInMovers); + CEntityPointer penCurrent = penMoving; // just to keep it alive around the loop + // first move it to done list (if not done, it will move back to world's movers) + penMoving->en_lnInMovers.Remove(); + lhDoneMovers.AddTail(penMoving->en_lnInMovers); + +/* + CPrintF("**%s(%08x)", + penMoving->en_pecClass->ec_pdecDLLClass->dec_strName, + penMoving->en_ulID); + if (penMoving->IsPredictable()) { + CPrintF(" predictable"); + } + if (penMoving->IsPredictor()) { + CPrintF(" predictor"); + } + if (penMoving->IsPredicted()) { + CPrintF(" predicted"); + } + if (penMoving->en_penReference!=NULL) { + CPrintF("reference id%08x", penMoving->en_penReference->en_ulID); + } + CPrintF("\n"); +*/ + + // let it do its own physics + penMoving->DoMoving(); +// CPrintF("\n"); + + // if any mover is re-added, put it to the end of active list + lhActiveMovers.MoveList(_pNetwork->ga_World.wo_lhMovers); + } + + // for each done mover + {FORDELETELIST(CMovableEntity, en_lnInMovers, lhDoneMovers, itenMover) { + // if predicting, and it is not a predictor + if (ses_bPredicting && !itenMover->IsPredictor()) { + // skip it + continue; + } + // let it calculate its parameters after all movement has been resolved + itenMover->PostMoving(); + }} + + // for each done mover + + {FORDELETELIST(CMovableEntity, en_lnInMovers, lhDoneMovers, itenMover) { + CMovableEntity *pen = itenMover; + // if predicting, and it is not a predictor + if (ses_bPredicting && !itenMover->IsPredictor()) { + // skip it + continue; + } + // if marked for removing from list of movers + if (pen->en_ulFlags&ENF_INRENDERING) { + // remove it + pen->en_ulFlags&=~ENF_INRENDERING; + pen->en_lnInMovers.Remove(); + } + // let it clear its temporary variables to prevent bad syncs + pen->ClearMovingTemp(); + }} + + // return all done movers to the world's list + _pNetwork->ga_World.wo_lhMovers.MoveList(lhDummyMovers); + _pNetwork->ga_World.wo_lhMovers.MoveList(lhDoneMovers); + + // handle all the sent events + CEntity::HandleSentEvents(); + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_HANDLEMOVERS); +} + +// do thinking for a game tick +void CSessionState::HandleTimers(TIME tmCurrentTick) +{ +#define TIME_EPSILON 0.0001f + IFDEBUG(TIME tmLast = 0.0f); + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_HANDLETIMERS); + // repeat + CListHead &lhTimers = _pNetwork->ga_World.wo_lhTimers; + FOREVER { + // no entity found initially + CRationalEntity *penTimer = NULL; + // for each entity in list of timers + FOREACHINLIST(CRationalEntity, en_lnInTimers, lhTimers, iten) { + // if due after current time + if(iten->en_timeTimer>tmCurrentTick+TIME_EPSILON) { + // stop searching + break; + } + // if now predicting and it is not a predictor + if (ses_bPredicting && !iten->IsPredictor()) { + // skip it + continue; + } + // remember found entity, and stop searching + penTimer = iten; + break; + } + + // if no entity is found + if (penTimer==NULL) { + // stop + break; + } + + // check that timers are propertly handled + ASSERT(penTimer->en_timeTimer>tmCurrentTick-_pTimer->TickQuantum-TIME_EPSILON); + //ASSERT(penTimer->en_timeTimer>=tmLast); + IFDEBUG(tmLast=penTimer->en_timeTimer); + + // remove the timer from the list + penTimer->en_timeTimer = THINKTIME_NEVER; + penTimer->en_lnInTimers.Remove(); + // send timer event to the entity + penTimer->SendEvent(ETimer()); + } + + // handle all the sent events + CEntity::HandleSentEvents(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_HANDLETIMERS); +} + +// do a warm-up run of the world for a few ticks +void CSessionState::WarmUpWorld(void) +{ +#define WORLD_WORMUP_COUNT 20 // run 20 ticks to get stable + ses_tmLastProcessedTick = _pNetwork->ga_srvServer.srv_tmLastProcessedTick = 0; + ses_iLastProcessedSequence = _pNetwork->ga_srvServer.srv_iLastProcessedSequence = -1; + // add a few empty all-action messages to the game stream + for (INDEX iTick=0; iTickga_srvServer.srv_tmLastProcessedTick += _pTimer->TickQuantum; + _pNetwork->ga_srvServer.srv_iLastProcessedSequence++; + CNetworkStreamBlock nsbAllActions(MSG_SEQ_ALLACTIONS, _pNetwork->ga_srvServer.srv_iLastProcessedSequence); + nsbAllActions<<_pNetwork->ga_srvServer.srv_tmLastProcessedTick; + nsbAllActions.Rewind(); + ses_nsGameStream.AddBlock(nsbAllActions); + } + + // process the blocks + ProcessGameStream(); +} + +// create a checksum value for sync-check +void CSessionState::ChecksumForSync(ULONG &ulCRC, INDEX iExtensiveSyncCheck) +{ + CRC_AddLONG(ulCRC, ses_iLastProcessedSequence); + CRC_AddLONG(ulCRC, ses_iLevel); + CRC_AddLONG(ulCRC, ses_bPause); + if (iExtensiveSyncCheck>0) { + CRC_AddLONG(ulCRC, ses_bGameFinished); + CRC_AddLONG(ulCRC, ses_ulRandomSeed); + } + + // if all entities should be synced + if (iExtensiveSyncCheck>1) { + // for each active entity in the world + {FOREACHINDYNAMICCONTAINER(_pNetwork->ga_World.wo_cenEntities, CEntity, iten) { + if (iten->IsPredictor()) { + continue; + } + iten->ChecksumForSync(ulCRC, iExtensiveSyncCheck); + }} + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(_pNetwork->ga_World.wo_cenAllEntities, CEntity, iten) { + if (iten->IsPredictor()) { + continue; + } + iten->ChecksumForSync(ulCRC, iExtensiveSyncCheck); + }} + } + + if (iExtensiveSyncCheck>0) { + // checksum all movers + {FOREACHINLIST(CMovableEntity, en_lnInMovers, _pNetwork->ga_World.wo_lhMovers, iten) { + if (iten->IsPredictor()) { + continue; + } + iten->ChecksumForSync(ulCRC, iExtensiveSyncCheck); + }} + } + // checksum all active players + {FOREACHINSTATICARRAY(ses_apltPlayers, CPlayerTarget, itclt) { + CPlayerTarget &clt = *itclt; + if (clt.IsActive()) { + clt.plt_paPreLastAction.ChecksumForSync(ulCRC); + clt.plt_paLastAction.ChecksumForSync(ulCRC); + clt.plt_penPlayerEntity->ChecksumForSync(ulCRC, iExtensiveSyncCheck); + } + }} +} + +// dump sync data to text file +void CSessionState::DumpSync_t(CTStream &strm, INDEX iExtensiveSyncCheck) // throw char * +{ + strm.FPrintF_t("Level: %d\n", ses_iLevel); + strm.FPrintF_t("Sequence: %d\n", ses_iLastProcessedSequence); + strm.FPrintF_t("Tick: %g\n", ses_tmLastProcessedTick); + strm.FPrintF_t("Paused: %d\n", ses_bPause); + if (iExtensiveSyncCheck>0) { + strm.FPrintF_t("Finished: %d\n", ses_bGameFinished); + strm.FPrintF_t("Random seed: 0x%08x\n", ses_ulRandomSeed); + } + + _pNetwork->ga_World.LockAll(); + + strm.FPrintF_t("\n\n======================== players:\n"); + // dump all active players + {FOREACHINSTATICARRAY(ses_apltPlayers, CPlayerTarget, itclt) { + CPlayerTarget &clt = *itclt; + if (clt.IsActive()) { + clt.plt_penPlayerEntity->DumpSync_t(strm, iExtensiveSyncCheck); + strm.FPrintF_t("\n -- action:\n"); + clt.plt_paPreLastAction.DumpSync_t(strm); + clt.plt_paLastAction.DumpSync_t(strm); + } + }} + + if (iExtensiveSyncCheck>0) { + strm.FPrintF_t("\n\n======================== movers:\n"); + // dump all movers + {FOREACHINLIST(CMovableEntity, en_lnInMovers, _pNetwork->ga_World.wo_lhMovers, iten) { + if (iten->IsPredictor()) { + continue; + } + iten->DumpSync_t(strm, iExtensiveSyncCheck); + }} + } + + // if all entities should be synced + if (iExtensiveSyncCheck>1) { + strm.FPrintF_t("\n\n======================== active entities (%d):\n", + _pNetwork->ga_World.wo_cenEntities.Count()); + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(_pNetwork->ga_World.wo_cenEntities, CEntity, iten) { + if (iten->IsPredictor()) { + continue; + } + iten->DumpSync_t(strm, iExtensiveSyncCheck); + }} + strm.FPrintF_t("\n\n======================== all entities (%d):\n", + _pNetwork->ga_World.wo_cenEntities.Count()); + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(_pNetwork->ga_World.wo_cenAllEntities, CEntity, iten) { + if (iten->IsPredictor()) { + continue; + } + iten->DumpSync_t(strm, iExtensiveSyncCheck); + }} + } + + _pNetwork->ga_World.UnlockAll(); +} + +#if DEBUG_SYNCSTREAMDUMPING +/* + * Obtain valid session dump memory stream + */ +CTMemoryStream *GetDumpStream(void) +{ + if( _pNetwork->ga_sesSessionState.ses_pstrm == NULL) + { + _pNetwork->ga_sesSessionState.ses_pstrm = new CTMemoryStream; + } + return _pNetwork->ga_sesSessionState.ses_pstrm; +} + +void ClearDumpStream(void) +{ + if( _pNetwork->ga_sesSessionState.ses_pstrm != NULL) + { + delete _pNetwork->ga_sesSessionState.ses_pstrm; + _pNetwork->ga_sesSessionState.ses_pstrm = NULL; + } +} +#endif + +/* + * Process a game tick. + */ + +extern INDEX cli_bEmulateDesync; +void CSessionState::ProcessGameTick(CNetworkMessage &nmMessage, TIME tmCurrentTick) +{ + ses_tmLastPredictionProcessed = -1; + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_PROCESSGAMETICK); + ASSERT(this!=NULL); + +#if DEBUG_SYNCSTREAMDUMPING + try + { + CTMemoryStream *pstrm = GetDumpStream(); + pstrm->FPrintF_t("Time tick: %.2f\n", tmCurrentTick); + } + catch (char *strError) + { + CPrintF("Cannot dump sync data: %s\n", strError); + } +#endif + //CPrintF("normal: %.2f\n", tmCurrentTick); + + // FPU must be in 24-bit mode + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // copy the tick to process into tick used for all tasks + _pTimer->SetCurrentTick(tmCurrentTick); + _pfNetworkProfile.IncrementAveragingCounter(); + _pfPhysicsProfile.IncrementAveragingCounter(); + + // random is allowed only here, during entity ai + ses_bAllowRandom = TRUE; + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_APPLYACTIONS); + // for all clients + INDEX iClient = 0; + FOREACHINSTATICARRAY(ses_apltPlayers, CPlayerTarget, itplt) { + // if client is active + if (itplt->IsActive()) { +// player indices transmission is unneccessary unless if debugging +// // check that it is present in message +// INDEX iClientInMessage; +// nmMessage>>iClientInMessage; // client index +// ASSERT(iClient==iClientInMessage); + // read the action + CPlayerAction paAction; + nmMessage>>paAction; + // apply the action + itplt->ApplyActionPacket(paAction); + + // desync emulation! + if( cli_bEmulateDesync) { + itplt->plt_penPlayerEntity->SetHealth(1.0f); + } + } + iClient++; + } + cli_bEmulateDesync = FALSE; + + // handle all the sent events + CEntity::HandleSentEvents(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_APPLYACTIONS); + + // do thinking + HandleTimers(tmCurrentTick); + // do physics + HandleMovers(); + + // notify all entities of level change as needed + if (_lphCurrent==LCP_INITIATED) { + EPreLevelChange ePreChange; + ePreChange.iUserData = _pNetwork->ga_iNextLevelUserData; + SendLevelChangeNotification(ePreChange); + CEntity::HandleSentEvents(); + _lphCurrent=LCP_SIGNALLED; + } + if (_lphCurrent==LCP_CHANGED) { + EPostLevelChange ePostChange; + ePostChange.iUserData = _pNetwork->ga_iNextLevelUserData; + SendLevelChangeNotification(ePostChange); + CEntity::HandleSentEvents(); + _lphCurrent=LCP_NOCHANGE; + } + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_WORLDBASETICK); + // let the worldbase execute its tick function + if (_pNetwork->ga_World.wo_pecWorldBaseClass!=NULL + &&_pNetwork->ga_World.wo_pecWorldBaseClass->ec_pdecDLLClass!=NULL + &&_pNetwork->ga_World.wo_pecWorldBaseClass->ec_pdecDLLClass->dec_OnWorldTick!=NULL) { + _pNetwork->ga_World.wo_pecWorldBaseClass->ec_pdecDLLClass-> + dec_OnWorldTick(&_pNetwork->ga_World); + } + // handle all the sent events + CEntity::HandleSentEvents(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_WORLDBASETICK); + + // make sync-check and send to server if needed + MakeSynchronisationCheck(); + +#if DEBUG_SYNCSTREAMDUMPING + extern INDEX cli_bDumpSyncEachTick; + if( cli_bDumpSyncEachTick) + { + DumpSyncToMemory(); + } +#endif + ses_bAllowRandom = FALSE; + + ses_tmPredictionHeadTick = Max(ses_tmPredictionHeadTick, tmCurrentTick); + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_PROCESSGAMETICK); + + // assure that FPU precision was low all the rendering time + ASSERT( GetFPUPrecision()==FPT_24BIT); + + // let eventual script do something on each tick + extern FLOAT cmd_tmTick; + extern CTString cmd_cmdOnTick; + if (cmd_cmdOnTick!="") { + cmd_tmTick = tmCurrentTick; + _pShell->Execute(cmd_cmdOnTick); + } +} + +/* Process a predicted game tick. */ +void CSessionState::ProcessPredictedGameTick(INDEX iPredictionStep, FLOAT fFactor, TIME tmCurrentTick) +{ + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_PROCESSGAMETICK); + ASSERT(this!=NULL); + + //CPrintF("predicted: %.2f\n", tmCurrentTick); + + // FPU must be in 24-bit mode + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // now predicting + ses_bPredicting = TRUE; + + // copy the tick to process into tick used for all tasks + _pTimer->SetCurrentTick(tmCurrentTick); + _pfNetworkProfile.IncrementAveragingCounter(); + _pfPhysicsProfile.IncrementAveragingCounter(); + + // random is allowed only here, during entity ai + ses_bAllowRandom = TRUE; + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_APPLYACTIONS); + // for all clients + FOREACHINSTATICARRAY(ses_apltPlayers, CPlayerTarget, itplt) { + // if client is active + if (itplt->IsActive()) { + // apply the predicted action + itplt->ApplyPredictedAction(iPredictionStep, fFactor); + } + } + + // handle all the sent events + CEntity::HandleSentEvents(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_APPLYACTIONS); + + // do thinking + HandleTimers(tmCurrentTick); + // do physics + HandleMovers(); + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_WORLDBASETICK); + + // handle all the sent events + CEntity::HandleSentEvents(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_WORLDBASETICK); + + ses_bAllowRandom = FALSE; + + // not predicting any more + ses_bPredicting = FALSE; + + ses_tmPredictionHeadTick = Max(ses_tmPredictionHeadTick, tmCurrentTick); + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_PROCESSGAMETICK); + + // assure that FPU precision was low all the rendering time + ASSERT( GetFPUPrecision()==FPT_24BIT); +} + +/* + * Process all eventual available gamestream blocks. + */ +void CSessionState::ProcessGameStream(void) +{ + _pfNetworkProfile.StartTimer(CNetworkProfile::PTI_SESSIONSTATE_PROCESSGAMESTREAM); + + // must be in 24bit mode when managing entities + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + TIME tmDemoNow = _pNetwork->ga_fDemoTimer; + // if playing a demo + if (_pNetwork->ga_bDemoPlay) { + // find how much ticks to step by now + if (ses_tmLastDemoSequence<0.0f) { + ses_tmLastDemoSequence=tmDemoNow; + } + // if it is finished + if (_pNetwork->ga_bDemoPlayFinished) { + _pfNetworkProfile.StopTimer(CNetworkProfile::PTI_SESSIONSTATE_PROCESSGAMESTREAM); + // do nothing + return; + } + } + + // repeat + FOREVER { + // if playing a demo + if (_pNetwork->ga_bDemoPlay) { + // if finished for this pass + if (ses_tmLastDemoSequence>=tmDemoNow) { + _pfNetworkProfile.StopTimer(CNetworkProfile::PTI_SESSIONSTATE_PROCESSGAMESTREAM); + // end the loop + return; + } + // try to + try { + // read a stream block from the demo + CChunkID cid = _pNetwork->ga_strmDemoPlay.PeekID_t(); + if (cid == CChunkID("DTCK")) { + _pNetwork->ga_strmDemoPlay.ExpectID_t("DTCK");// demo tick + CNetworkStreamBlock nsbBlock; + nsbBlock.Read_t(_pNetwork->ga_strmDemoPlay); + ses_nsGameStream.AddBlock(nsbBlock); + _pNetwork->ga_bDemoPlayFinished = FALSE; + } else { + _pNetwork->ga_strmDemoPlay.ExpectID_t("DEND"); // demo end + _pNetwork->ga_bDemoPlayFinished = TRUE; + _pfNetworkProfile.StopTimer(CNetworkProfile::PTI_SESSIONSTATE_PROCESSGAMESTREAM); + return; + } + // if not successful + } catch(char *strError) { + // report error + CPrintF(TRANS("Error while playing demo: %s"), strError); + _pfNetworkProfile.StopTimer(CNetworkProfile::PTI_SESSIONSTATE_PROCESSGAMESTREAM); + return; + } + } + + // calculate index of next expected sequence + INDEX iSequence = ses_iLastProcessedSequence+1; + // get the stream block with that sequence + CNetworkStreamBlock *pnsbBlock; + CNetworkStream::Result res = ses_nsGameStream.GetBlockBySequence(iSequence, pnsbBlock); + // if it is found + if (res==CNetworkStream::R_OK) { + // if recording a demo + if (_pNetwork->ga_bDemoRec) { + // try to + try { + // write the stream block to the demo + _pNetwork->ga_strmDemoRec.WriteID_t("DTCK"); + pnsbBlock->Write_t(_pNetwork->ga_strmDemoRec); + // if not successful + } catch(char *strError) { + // report error + CPrintF(TRANS("Error while recording demo: %s"), strError); + // stop recording + _pNetwork->StopDemoRec(); + } + } + + // remember the message type + int iMsgType=pnsbBlock->GetType(); + // remember the processed sequence + ses_iLastProcessedSequence = iSequence; + // process the stream block + ProcessGameStreamBlock(*pnsbBlock); + // remove the block from the stream + pnsbBlock->RemoveFromStream(); + delete pnsbBlock; + // remove eventual resent blocks that have already been processed + ses_nsGameStream.RemoveOlderBlocksBySequence(ses_iLastProcessedSequence-2); + + // if the message is all actions + if (iMsgType==MSG_SEQ_ALLACTIONS) { + // if playing a demo + if (_pNetwork->ga_bDemoPlay) { + // step demo sequence + ses_tmLastDemoSequence+=_pTimer->TickQuantum; + } + } + + // if it is not avaliable yet + } if (res==CNetworkStream::R_BLOCKNOTRECEIVEDYET) { + // finish + _pfNetworkProfile.StopTimer(CNetworkProfile::PTI_SESSIONSTATE_PROCESSGAMESTREAM); + return; + // if it is missing + } else if (res==CNetworkStream::R_BLOCKMISSING) { + + // if it is a new sequence + if (iSequence>ses_iMissingSequence) { + ses_iMissingSequence = iSequence; + // setup timeout + ses_tvResendTime = _pTimer->GetHighPrecisionTimer(); + ses_tmResendTimeout = 0.1f; + } + + // if timeout occured + if (_pTimer->GetHighPrecisionTimer()>ses_tvResendTime+CTimerValue(ses_tmResendTimeout)) { + + _pNetwork->AddNetGraphValue(NGET_MISSING, 1.0f); // missing sequence + + // find how many are missing + INDEX iNextValid = ses_nsGameStream.GetOldestSequenceAfter(iSequence); + INDEX ctSequences = Max(iNextValid-iSequence, INDEX(1)); + + // create a request for resending the missing packet + CNetworkMessage nmResendRequest(MSG_REQUESTGAMESTREAMRESEND); + nmResendRequest<SendToServer(nmResendRequest); + + extern INDEX net_bReportMiscErrors; + if (net_bReportMiscErrors) { + CPrintF(TRANS("Session State: Missing sequences %d-%d(%d) timeout %g\n"), + iSequence, iSequence+ctSequences-1, ctSequences, ses_tmResendTimeout); + } + + // increase the timeout + ses_tvResendTime = _pTimer->GetHighPrecisionTimer(); + ses_tmResendTimeout *= 2.0f; + } + + // finish + _pfNetworkProfile.StopTimer(CNetworkProfile::PTI_SESSIONSTATE_PROCESSGAMESTREAM); + return; + } + } +} + +// flush prediction actions that were already processed +void CSessionState::FlushProcessedPredictions(void) +{ + // for all clients + FOREACHINSTATICARRAY(ses_apltPlayers, CPlayerTarget, itplt) { + // flush + itplt->FlushProcessedPredictions(); + } +} + +/* Find out how many prediction steps are currently pending. */ +INDEX CSessionState::GetPredictionStepsCount(void) +{ + // start with no prediction + INDEX ctPredictionSteps = 0; + // for all clients + FOREACHINSTATICARRAY(ses_apltPlayers, CPlayerTarget, itplt) { + // update maximum number of possible predictions + ctPredictionSteps = Max(ctPredictionSteps, itplt->GetNumberOfPredictions()); + } + + return ctPredictionSteps; +} + +/* Process all eventual available prediction actions. */ +void CSessionState::ProcessPrediction(void) +{ + // FPU must be in 24-bit mode + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // get number of steps that could be predicted + INDEX ctSteps = GetPredictionStepsCount(); + + // limit prediction + extern INDEX cli_iMaxPredictionSteps; + ctSteps = ClampUp(ctSteps, cli_iMaxPredictionSteps); + + // if none + if(ctSteps<=0) { + // do nothing + return; + } + + // if this would not result in any new tick predicted + TIME tmNow = ses_tmLastProcessedTick+ctSteps*_pTimer->TickQuantum; + if (Abs(ses_tmLastPredictionProcessed-tmNow)<_pTimer->TickQuantum/10.0f) { + // do nothing + return; + } + // remeber what was predicted now + ses_tmLastPredictionProcessed = tmNow; + + // remember random seed and entity ID + ULONG ulOldRandom = ses_ulRandomSeed; + ULONG ulEntityID = _pNetwork->ga_World.wo_ulNextEntityID; + + // delete all predictors (if any left from last time) + _pNetwork->ga_World.DeletePredictors(); + // create new predictors + _pNetwork->ga_World.CreatePredictors(); + + // for each step + TIME tmPredictedTick = ses_tmLastProcessedTick; + for(INDEX iPredictionStep=0; iPredictionStepTickQuantum; + //ses_tmPredictionHeadTick = Max(ses_tmPredictionHeadTick, tmPredictedTick); + // predict it + ProcessPredictedGameTick(iPredictionStep, FLOAT(iPredictionStep)/ctSteps, tmPredictedTick); + } + // restore random seed and entity ID + ses_ulRandomSeed = ulOldRandom; + _pNetwork->ga_World.wo_ulNextEntityID = ulEntityID; +} + +/* + * Process a gamestream block. + */ +void CSessionState::ProcessGameStreamBlock(CNetworkMessage &nmMessage) +{ + // copy the tick to process into tick used for all tasks + _pTimer->SetCurrentTick(ses_tmLastProcessedTick); + + // check message type + switch (nmMessage.GetType()) { + // if adding a new player + case MSG_SEQ_ADDPLAYER: { + _pNetwork->AddNetGraphValue(NGET_NONACTION, 1.0f); // non-action sequence + INDEX iNewPlayer; + CPlayerCharacter pcCharacter; + nmMessage>>iNewPlayer; // player index + nmMessage>>pcCharacter; // player character + + // delete all predictors + _pNetwork->ga_World.DeletePredictors(); + + // activate the player + ses_apltPlayers[iNewPlayer].Activate(); + + // if there is no entity with that character in the world + CPlayerEntity *penNewPlayer = _pNetwork->ga_World.FindEntityWithCharacter(pcCharacter); + if (penNewPlayer==NULL) { + // create an entity for it + CPlacement3D pl(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0)); + try { + CTFileName fnmPlayer = CTString("Classes\\Player.ecl"); // this must not be a dependency! + penNewPlayer = (CPlayerEntity*)(_pNetwork->ga_World.CreateEntity_t(pl, fnmPlayer)); + // attach entity to client data + ses_apltPlayers[iNewPlayer].AttachEntity(penNewPlayer); + // attach the character to it + penNewPlayer->en_pcCharacter = pcCharacter; + // prepare the entity + penNewPlayer->Initialize(); + } catch (char *strError) { + (void)strError; + FatalError(TRANS("Cannot load Player class:\n%s"), strError); + } + if (!_pNetwork->IsPlayerLocal(penNewPlayer)) { + CPrintF(TRANS("%s joined\n"), penNewPlayer->GetPlayerName()); + } + } else { + // attach entity to client data + ses_apltPlayers[iNewPlayer].AttachEntity(penNewPlayer); + // make it update its character + penNewPlayer->CharacterChanged(pcCharacter); + + if (!_pNetwork->IsPlayerLocal(penNewPlayer)) { + CPrintF(TRANS("%s rejoined\n"), penNewPlayer->GetPlayerName()); + } + } + + } break; + // if removing a player + case MSG_SEQ_REMPLAYER: { + _pNetwork->AddNetGraphValue(NGET_NONACTION, 1.0f); // non-action sequence + INDEX iPlayer; + nmMessage>>iPlayer; // player index + + // delete all predictors + _pNetwork->ga_World.DeletePredictors(); + + // inform entity of disconnnection + CPrintF(TRANS("%s left\n"), ses_apltPlayers[iPlayer].plt_penPlayerEntity->GetPlayerName()); + ses_apltPlayers[iPlayer].plt_penPlayerEntity->Disconnect(); + // deactivate the player + ses_apltPlayers[iPlayer].Deactivate(); + // handle all the sent events + ses_bAllowRandom = TRUE; + CEntity::HandleSentEvents(); + ses_bAllowRandom = FALSE; + + } break; + + // if changing character + case MSG_SEQ_CHARACTERCHANGE: { + _pNetwork->AddNetGraphValue(NGET_NONACTION, 1.0f); // non-action sequence + INDEX iPlayer; + CPlayerCharacter pcCharacter; + nmMessage>>iPlayer>>pcCharacter; + + // delete all predictors + _pNetwork->ga_World.DeletePredictors(); + + // change the character + ses_apltPlayers[iPlayer].plt_penPlayerEntity->CharacterChanged(pcCharacter); + + // handle all the sent events + ses_bAllowRandom = TRUE; + CEntity::HandleSentEvents(); + ses_bAllowRandom = FALSE; + + } break; + // if receiving client actions + case MSG_SEQ_ALLACTIONS: { + // read time from packet + TIME tmPacket; + nmMessage>>tmPacket; // packet time + + // time must be greater by one than that on the last packet received + TIME tmTickQuantum = _pTimer->TickQuantum; + TIME tmPacketDelta = tmPacket-ses_tmLastProcessedTick; + if(! (Abs(tmPacketDelta-tmTickQuantum) < (tmTickQuantum/10.0f)) ) { + // report debug info + CPrintF( + TRANS("Session state: Mistimed MSG_ALLACTIONS: Last received tick %g, this tick %g\n"), + ses_tmLastProcessedTick, tmPacket); + } + // remember the received tick + ses_tmLastProcessedTick = tmPacket; + + // NOTE: if we got a tick, it means that all players have joined + // don't wait for new players any more + ses_bWaitAllPlayers = FALSE; + + // delete all predictors + _pNetwork->ga_World.DeletePredictors(); + // process the tick + ProcessGameTick(nmMessage, tmPacket); + + } break; + + // if receiving pause message + case MSG_SEQ_PAUSE: { + _pNetwork->AddNetGraphValue(NGET_NONACTION, 1.0f); // non-action sequence + + // delete all predictors + _pNetwork->ga_World.DeletePredictors(); + + BOOL bPauseBefore = ses_bPause; + // read the pause state and pauser from it + nmMessage>>(INDEX&)ses_bPause; + CTString strPauser; + nmMessage>>strPauser; + // if paused by some other machine + if (strPauser!=TRANS("Local machine")) { + // report who paused + if (ses_bPause!=bPauseBefore) { + if (ses_bPause) { + CPrintF(TRANS("Paused by '%s'\n"), strPauser); + } else { + CPrintF(TRANS("Unpaused by '%s'\n"), strPauser); + } + } + } + // must keep wanting current state + ses_bWantPause = ses_bPause; + } break; + // otherwise + default: + // error + ASSERT(FALSE); + } +} + +// Set lerping factor for current frame. +void CSessionState::SetLerpFactor(CTimerValue tvNow) +{ + // if no lerping + if (!net_bLerping) { + // set lerping factor without lerping + _pTimer->SetLerp(1.0f); + _pTimer->SetCurrentTick(ses_tmPredictionHeadTick); + return; + } + + FLOAT fFactor = 0.0f; + FLOAT fFactor2 = 0.0f; + + // ---- primary factor - used for prediction + { + TIME tmLastTick = ses_tmPredictionHeadTick; + + // if lerping was never set before + if (ses_tmInitializationTick<0) { + // initialize it + ses_tvInitialization = tvNow; + ses_tmInitializationTick = tmLastTick; + } + + // get passed time from session state starting in precise time and in ticks + FLOAT tmRealDelta = FLOAT((tvNow-ses_tvInitialization).GetSeconds()) + *_pNetwork->ga_fGameRealTimeFactor*_pNetwork->ga_sesSessionState.ses_fRealTimeFactor; + FLOAT tmTickDelta = tmLastTick-ses_tmInitializationTick; + // calculate factor + fFactor = 1.0f-(tmTickDelta-tmRealDelta)/_pTimer->TickQuantum; + + // if the factor starts getting below zero + if (fFactor<0) { + //CPrintF("Lerp=%.2f <0 @ %.2fs\n", fFactor, tmLastTick); + // clamp it + fFactor = 0.0f; + // readjust timers so that it gets better + ses_tvInitialization = tvNow; + ses_tmInitializationTick = tmLastTick-_pTimer->TickQuantum; + } + if (fFactor>1) { + //CPrintF("Lerp=%.2f >1 @ %.2fs\n", fFactor, tmLastTick); + // clamp it + fFactor = 1.0f; + // readjust timers so that it gets better + ses_tvInitialization = tvNow; + ses_tmInitializationTick = tmLastTick; + } + + #if DEBUG_LERPING + + avfStats[ctCounter][0] = tmRealDelta/_pTimer->TickQuantum; + avfStats[ctCounter][1] = tmTickDelta/_pTimer->TickQuantum; + avfStats[ctCounter][2] = fFactor; + avfStats[ctCounter][3] = (tmLastTick/_pTimer->TickQuantum-1.0f)+fFactor; + ctCounter++; + if (ctCounter>=ctMax) { + ctCounter = 0; + } + #endif // DEBUG_LERPING + } + + // ---- secondary factor - used for non-predicted movement + { + TIME tmLastTick = ses_tmLastProcessedTick; + // if lerping was never set before + if (ses_tmInitializationTick2<0) { + // initialize it + ses_tvInitialization2 = tvNow; + ses_tmInitializationTick2 = tmLastTick; + } + + // get passed time from session state starting in precise time and in ticks + FLOAT tmRealDelta = FLOAT((tvNow-ses_tvInitialization2).GetSeconds()) + *_pNetwork->ga_fGameRealTimeFactor*_pNetwork->ga_sesSessionState.ses_fRealTimeFactor; + FLOAT tmTickDelta = tmLastTick-ses_tmInitializationTick2; + // calculate factor + fFactor2 = 1.0f-(tmTickDelta-tmRealDelta)/_pTimer->TickQuantum; + + // if the factor starts getting below zero + if (fFactor2<0) { + //CPrintF("Lerp2=%.2f <0 @ %.2fs\n", fFactor2, tmLastTick); + // clamp it + fFactor2 = 0.0f; + // readjust timers so that it gets better + ses_tvInitialization2 = tvNow; + ses_tmInitializationTick2 = tmLastTick-_pTimer->TickQuantum; + } + if (fFactor2>1) { + //CPrintF("Lerp2=%.2f >1 @ %.2fs\n", fFactor2, tmLastTick); + // clamp it + fFactor2 = 1.0f; + // readjust timers so that it gets better + ses_tvInitialization2 = tvNow; + ses_tmInitializationTick2 = tmLastTick; + } + } + + // set lerping factor2 + _pTimer->SetLerp(fFactor); + _pTimer->SetLerp2(fFactor2); + _pTimer->SetCurrentTick(ses_tmPredictionHeadTick); +} + +/* + * Read session state state from a stream. + */ +void CSessionState::Read_t(CTStream *pstr) // throw char * +{ +#if DEBUG_SYNCSTREAMDUMPING + CPrintF( "Session state read: Sequence %d, Time %g\n", ses_iLastProcessedSequence, ses_tmLastProcessedTick); +#endif + // read time information and random seed + + INDEX iVersion = SESSIONSTATEVERSION_OLD; + if (pstr->PeekID_t()==CChunkID("SESV")) { + pstr->ExpectID_t("SESV"); + (*pstr)>>iVersion; + } + (*pstr)>>ses_tmLastProcessedTick; + (*pstr)>>ses_iLastProcessedSequence; + (*pstr)>>ses_iLevel; + (*pstr)>>ses_ulRandomSeed; + (*pstr)>>ses_ulSpawnFlags; + (*pstr)>>ses_tmSyncCheckFrequency; + (*pstr)>>ses_iExtensiveSyncCheck; + (*pstr)>>ses_tmLastSyncCheck; + (*pstr)>>ses_ctMaxPlayers; + (*pstr)>>ses_bWaitAllPlayers; + (*pstr)>>ses_bPause; + (*pstr)>>ses_bGameFinished; + if (iVersion>=SESSIONSTATEVERSION_WITHBULLETTIME) { + (*pstr)>>ses_fRealTimeFactor; + } + ses_bWaitingForServer = FALSE; + ses_bWantPause = ses_bPause; + ses_strDisconnected = ""; + _pTimer->SetCurrentTick(ses_tmLastProcessedTick); + + // read session properties from stream + (*pstr)>>_pNetwork->ga_strSessionName; + pstr->Read_t(_pNetwork->ga_aubProperties, NET_MAXSESSIONPROPERTIES); + + // read world and its state + ReadWorldAndState_t(pstr); + +#if DEBUG_SYNCSTREAMDUMPING + ClearDumpStream(); + + // dump sync data if needed + extern INDEX cli_bDumpSyncEachTick; + if( cli_bDumpSyncEachTick) + { + DumpSyncToMemory(); + } +#endif +} + +void CSessionState::ReadWorldAndState_t(CTStream *pstr) // throw char * +{ + // check engine build disallowing reinit + BOOL bNeedsReinit; + _pNetwork->CheckVersion_t(*pstr, FALSE, bNeedsReinit); + ASSERT(!bNeedsReinit); + + // read world filename from stream + (*pstr)>>_pNetwork->ga_fnmWorld; + + if (CTFileName(pstr->GetDescription()).FileExt()==".dem" && + GetFileTimeStamp_t(pstr->GetDescription())<=GetFileTimeStamp_t(_pNetwork->ga_fnmWorld)) { + ThrowF_t( + TRANS("Cannot play demo because file '%s'\n" + "is older than file '%s'!\n"), + CTString(pstr->GetDescription()), + CTString(_pNetwork->ga_fnmWorld)); + } + + // prepare the world for loading + _pNetwork->ga_World.DeletePredictors(); + _pNetwork->ga_World.Clear(); + _pNetwork->ga_World.LockAll(); + // load the world brushes from the world file + _pNetwork->ga_World.LoadBrushes_t(_pNetwork->ga_fnmWorld); + // read world situation + _pNetwork->ga_World.ReadState_t(pstr); + + // create an empty list for relinking timers + CListHead lhNewTimers; + // read number of entities in timer list + pstr->ExpectID_t("TMRS"); // timers + INDEX ctTimers; + *pstr>>ctTimers; +// ASSERT(ctTimers == _pNetwork->ga_World.wo_lhTimers.Count()); + // for each entity in the timer list + {for(INDEX ienTimer=0; ienTimer>ien; + // get the entity + CRationalEntity *pen = (CRationalEntity*)_pNetwork->ga_World.EntityFromID(ien); + // remove it from the timer list and add it at the end of the new timer list + if (pen->en_lnInTimers.IsLinked()) { + pen->en_lnInTimers.Remove(); + lhNewTimers.AddTail(pen->en_lnInTimers); + } + }} + // use the new timer list instead the old one + ASSERT(_pNetwork->ga_World.wo_lhTimers.IsEmpty()); + _pNetwork->ga_World.wo_lhTimers.MoveList(lhNewTimers); + + // create an empty list for relinking movers + CListHead lhNewMovers; + // read number of entities in mover list + pstr->ExpectID_t("MVRS"); // movers + INDEX ctMovers; + *pstr>>ctMovers; + ASSERT(ctMovers == _pNetwork->ga_World.wo_lhMovers.Count()); + // for each entity in the mover list + {for(INDEX ienMover=0; ienMover>ien; + // get the entity + CMovableEntity *pen = (CMovableEntity*)_pNetwork->ga_World.EntityFromID(ien); + // remove it from the mover list and add it at the end of the new mover list + if (pen->en_lnInMovers.IsLinked()) { + pen->en_lnInMovers.Remove(); + } + lhNewMovers.AddTail(pen->en_lnInMovers); + }} + // use the new mover list instead the old one + ASSERT(_pNetwork->ga_World.wo_lhMovers.IsEmpty()); + _pNetwork->ga_World.wo_lhMovers.MoveList(lhNewMovers); + + // read number of players + INDEX ctPlayers; + (*pstr)>>ctPlayers; + ASSERT(ctPlayers==ses_apltPlayers.Count()); + // for all clients + FOREACHINSTATICARRAY(ses_apltPlayers, CPlayerTarget, itclt) { + // read from stream + itclt->Read_t(pstr); + } + + _pNetwork->ga_World.UnlockAll(); +} + +void CSessionState::ReadRememberedLevels_t(CTStream *pstr) +{ + pstr->ExpectID_t("RLEV"); // remembered levels + // read count of remembered levels + INDEX ctLevels; + (*pstr)>>ctLevels; + // for each level + for(INDEX iLevel=0; iLevel>prl->rl_strFileName; + //prl->rl_strmSessionState. + // use readstream() !!!! @@@@ + + } + +}; + +/* + * Write session state state into a stream. + */ +void CSessionState::Write_t(CTStream *pstr) // throw char * +{ +#if DEBUG_SYNCSTREAMDUMPING + CPrintF( "Session state write: Sequence %d, Time %.2f\n", ses_iLastProcessedSequence, ses_tmLastProcessedTick); +#endif + pstr->WriteID_t("SESV"); + (*pstr)<ga_strSessionName; + pstr->Write_t(_pNetwork->ga_aubProperties, NET_MAXSESSIONPROPERTIES); + + // write world and its state + WriteWorldAndState_t(pstr); +} + +void CSessionState::WriteWorldAndState_t(CTStream *pstr) // throw char * +{ + // delete all predictor entities before saving + _pNetwork->ga_World.UnmarkForPrediction(); + _pNetwork->ga_World.DeletePredictors(); + + // save engine build + _pNetwork->WriteVersion_t(*pstr); + + // write world filename to stream + (*pstr)<<_pNetwork->ga_fnmWorld; + + // write world situation + _pNetwork->ga_World.LockAll(); + _pNetwork->ga_World.WriteState_t(pstr, TRUE); + + // write number of entities in timer list + pstr->WriteID_t("TMRS"); // timers + CListHead &lhTimers = _pNetwork->ga_World.wo_lhTimers; + *pstr<en_ulID; + }} + + // write number of entities in mover list + pstr->WriteID_t("MVRS"); // movers + CListHead &lhMovers = _pNetwork->ga_World.wo_lhMovers; + *pstr<en_ulID; + }} + + // write number of clients + (*pstr)<Write_t(pstr); + } + + _pNetwork->ga_World.UnlockAll(); +} + +void CSessionState::WriteRememberedLevels_t(CTStream *pstr) +{ + // use writestream() !!!! @@@@ + +}; + +// remember current level +void CSessionState::RememberCurrentLevel(const CTString &strFileName) +{ + // if level is already remembered + for(;;) { + CRememberedLevel *prlOld = FindRememberedLevel(strFileName); + if (prlOld==NULL) { + break; + } + // remove it + prlOld->rl_lnInSessionState.Remove(); + delete prlOld; + } + + // create new remembered level + CRememberedLevel *prlNew = new CRememberedLevel; + ses_lhRememberedLevels.AddTail(prlNew->rl_lnInSessionState); + // remember it + prlNew->rl_strFileName = strFileName; + WriteWorldAndState_t(&prlNew->rl_strmSessionState); +} + +// find a level if it is remembered +CRememberedLevel *CSessionState::FindRememberedLevel(const CTString &strFileName) +{ + {FOREACHINLIST(CRememberedLevel, rl_lnInSessionState, ses_lhRememberedLevels, itrl) { + CRememberedLevel &rl = *itrl; + if (rl.rl_strFileName==strFileName) { + return &rl; + } + }} + return NULL; +} + +// restore some old level +void CSessionState::RestoreOldLevel(const CTString &strFileName) +{ + // find the level + CRememberedLevel *prlOld = FindRememberedLevel(strFileName); + // it must exist + ASSERT(prlOld!=NULL); + // restore it + try { + prlOld->rl_strmSessionState.SetPos_t(0); + _pTimer->SetCurrentTick(0.0f); + ReadWorldAndState_t(&prlOld->rl_strmSessionState); + _pTimer->SetCurrentTick(ses_tmLastProcessedTick); + } catch (char *strError) { + FatalError(TRANS("Cannot restore old level '%s':\n%s"), prlOld->rl_strFileName, strError); + } + // delete it + delete prlOld; +} + +// make synchronization test message and send it to server (if client), or add to buffer (if server) +void CSessionState::MakeSynchronisationCheck(void) +{ + if (!_cmiComm.cci_bClientInitialized) return; + // not yet time + if(ses_tmLastSyncCheck+ses_tmSyncCheckFrequency > ses_tmLastProcessedTick) { + // don't check yet + return; + } + + // make local checksum + ULONG ulLocalCRC; + CRC_Start(ulLocalCRC); + ChecksumForSync(ulLocalCRC, ses_iExtensiveSyncCheck); + CRC_Finish(ulLocalCRC); + + // create sync-check + CSyncCheck sc; + ses_tmLastSyncCheck = ses_tmLastProcessedTick; + sc.sc_tmTick = ses_tmLastSyncCheck; + sc.sc_iSequence = ses_iLastProcessedSequence; + sc.sc_ulCRC = ulLocalCRC; + sc.sc_iLevel = ses_iLevel; + + // NOTE: If local client, here we buffer the sync and send it to ourselves. + // It's because synccheck is piggybacking session message buffer, so we acknowledge + // the server to flush the buffer up to that sequence. + + // if on server + if (_pNetwork->IsServer()) { + // buffer the sync-check + _pNetwork->ga_srvServer.AddSyncCheck(sc); + } + + // create a message with sync check + CNetworkMessage nmSyncCheck(MSG_SYNCCHECK); + nmSyncCheck.Write(&sc, sizeof(sc)); + // send it to server + _pNetwork->SendToServer(nmSyncCheck); +} + +// forget all remembered levels +void CSessionState::ForgetOldLevels(void) +{ + {FORDELETELIST(CRememberedLevel, rl_lnInSessionState, ses_lhRememberedLevels, itrl) { + delete &*itrl; + }} +} + + +extern INDEX cli_bDumpSync; +extern INDEX cli_bDumpSyncEachTick; +void CSessionState::DumpSyncToFile_t(CTStream &strm, INDEX iExtensiveSyncCheck) // throw char * +{ + ULONG ulLocalCRC; + CRC_Start(ulLocalCRC); + ChecksumForSync(ulLocalCRC, iExtensiveSyncCheck); + CRC_Finish(ulLocalCRC); + strm.FPrintF_t("__________________________________________________________________________________\n", ulLocalCRC); + strm.FPrintF_t("CRC: 0x%08X\n", ulLocalCRC); + DumpSync_t(strm, iExtensiveSyncCheck); +} + +#if DEBUG_SYNCSTREAMDUMPING +void CSessionState::DumpSyncToMemory(void) +{ + try + { + CTMemoryStream *pstrm = GetDumpStream(); + DumpSyncToFile_t(*pstrm); + } + catch (char *strError) + { + CPrintF("Cannot dump sync data: %s\n", strError); + } +} +#endif + +/* Session state loop. */ +void CSessionState::SessionStateLoop(void) +{ + _pfNetworkProfile.StartTimer(CNetworkProfile::PTI_SESSIONSTATE_LOOP); + + // while there is something to do + BOOL bSomethingToDo = TRUE; + while (bSomethingToDo && !IsDisconnected()) { + bSomethingToDo = FALSE; + + // if client was disconnected without a notice + if (!_cmiComm.Client_IsConnected()) { + // quit + ses_strDisconnected = TRANS("Link or server is down"); + } + + CNetworkMessage nmMessage; + // if there is some unreliable message + if (_pNetwork->ReceiveFromServer(nmMessage)) { + bSomethingToDo = TRUE; + + // if it is a gamestream message + if (nmMessage.GetType() == MSG_GAMESTREAMBLOCKS) { + ses_tvMessageReceived = _pTimer->GetHighPrecisionTimer(); + ses_bWaitingForServer = FALSE; + + // unpack the message + CNetworkMessage nmUnpackedBlocks(MSG_GAMESTREAMBLOCKS); + nmMessage.UnpackDefault(nmUnpackedBlocks); + + // while there are some more blocks in the message + while (!nmUnpackedBlocks.EndOfMessage()) { + // read a block to the gamestream + ses_nsGameStream.ReadBlock(nmUnpackedBlocks); + } + + // if it is a keepalive + } else if (nmMessage.GetType() == MSG_KEEPALIVE) { + // just remember time + ses_tvMessageReceived = _pTimer->GetHighPrecisionTimer(); + _pNetwork->AddNetGraphValue(NGET_NONACTION, 0.5f); // non-action sequence + + // if it is pings message + } else if (nmMessage.GetType() == MSG_INF_PINGS) { + for(INDEX i=0; ien_tmPing = iPing/1000.0f; + } + } + } + // if it is chat message + } else if (nmMessage.GetType() == MSG_CHAT_OUT) { + // read the message + ULONG ulFrom; + CTString strFrom; + nmMessage>>ulFrom; + if (ulFrom==0) { + nmMessage>>strFrom; + } + CTString strMessage; + nmMessage>>strMessage; + // print it + PrintChatMessage(ulFrom, strFrom, strMessage); + // otherwise + } else { + CPrintF(TRANS("Session state: Unexpected message during game: %s(%d)\n"), + ErrorDescription(&MessageTypes, nmMessage.GetType()), nmMessage.GetType()); + } + } + + CNetworkMessage nmReliable; + // if there is some reliable message + if (_pNetwork->ReceiveFromServerReliable(nmReliable)) { + bSomethingToDo = TRUE; + // if this is disconnect message + if (nmReliable.GetType() == MSG_INF_DISCONNECTED) { + // confirm disconnect + CNetworkMessage nmConfirmDisconnect(MSG_REP_DISCONNECTED); + _pNetwork->SendToServerReliable(nmConfirmDisconnect); + // report the reason + CTString strReason; + nmReliable>>strReason; + ses_strDisconnected = strReason; + CPrintF(TRANS("Disconnected: %s\n"), strReason); + // disconnect + _cmiComm.Client_Close(); + // if this is recon response + } else if (nmReliable.GetType() == MSG_ADMIN_RESPONSE) { + // just print it + CTString strResponse; + nmReliable>>strResponse; + CPrintF("%s", "|"+strResponse+"\n"); + // otherwise + } else { + CPrintF(TRANS("Session state: Unexpected reliable message during game: %s(%d)\n"), + ErrorDescription(&MessageTypes, nmReliable.GetType()), nmReliable.GetType()); + } + } + } + + // if network client and not waiting for server + if (_pNetwork->IsNetworkEnabled() && !_pNetwork->IsServer() && !ses_bWaitingForServer) { + // check when last message was received. + if (ses_tvMessageReceived.tv_llValue>0 && + (_pTimer->GetHighPrecisionTimer()-ses_tvMessageReceived).GetSeconds()>net_tmDisconnectTimeout && + ses_strDisconnected=="") { + ses_strDisconnected = TRANS("Connection timeout"); + CPrintF(TRANS("Disconnected: %s\n"), (const char*)ses_strDisconnected); + } + } + + // if pause state should be changed + if (ses_bPause!=ses_bWantPause) { + // send appropriate packet to server + CNetworkMessage nmReqPause(MSG_REQ_PAUSE); + nmReqPause<<(INDEX&)ses_bWantPause; + _pNetwork->SendToServer(nmReqPause); + } + + // dump sync data if needed + if( cli_bDumpSync) + { + cli_bDumpSync = FALSE; + try + { + CTFileStream strmFile; + CTString strFileName = CTString("temp\\syncdump.txt"); + strmFile.Create_t(CTString("temp\\syncdump.txt"), CTStream::CM_TEXT); + +#if DEBUG_SYNCSTREAMDUMPING + if( cli_bDumpSyncEachTick) + { + // get size and buffer from the stream + void *pvBuffer; + SLONG slSize; + ses_pstrm->LockBuffer(&pvBuffer, &slSize); + strmFile.Write_t(pvBuffer, slSize); + ses_pstrm->UnlockBuffer(); + } + else +#endif + { + DumpSyncToFile_t(strmFile, ses_iExtensiveSyncCheck); + } + // inform user + CPrintF("Sync data dumped to '%s'\n", strFileName); + } + catch (char *strError) + { + CPrintF("Cannot dump sync data: %s\n", strError); + } + } + + // if some client settings changed + if (!ses_sspParams.IsUpToDate()) { + // remember new settings + ses_sspParams.Update(); + // send message to server + CNetworkMessage nmSet(MSG_SET_CLIENTSETTINGS); + nmSet<SendToServerReliable(nmSet); + } + + _pfNetworkProfile.StopTimer(CNetworkProfile::PTI_SESSIONSTATE_LOOP); +} + +/* Get number of active players. */ +INDEX CSessionState::GetPlayersCount(void) +{ + INDEX ctPlayers = 0; + FOREACHINSTATICARRAY(ses_apltPlayers, CPlayerTarget, itplt) { + if (itplt->IsActive()) { + ctPlayers++; + } + } + return ctPlayers; +} + +/* Remember predictor positions of all players. */ +void CSessionState::RememberPlayerPredictorPositions(void) +{ + // for each active player + FOREACHINSTATICARRAY(ses_apltPlayers, CPlayerTarget, itplt) { + CPlayerTarget &plt = *itplt; + if (plt.IsActive()) { + // remember its current, or predictor position + CEntity *pen = plt.plt_penPlayerEntity; + if (pen->IsPredicted()) { + pen = pen->GetPredictor(); + } + plt.plt_vPredictorPos = pen->GetPlacement().pl_PositionVector; + } + } +} + +/* Get player position. */ +const FLOAT3D &CSessionState::GetPlayerPredictorPosition(INDEX iPlayer) +{ + return ses_apltPlayers[iPlayer].plt_vPredictorPos; +} + +CPredictedEvent::CPredictedEvent(void) +{ +} + +// check an event for prediction, returns true if already predicted +BOOL CSessionState::CheckEventPrediction(CEntity *pen, ULONG ulTypeID, ULONG ulEventID) +{ + // if prediction is not involved + if ( !( pen->GetFlags() & (ENF_PREDICTOR|ENF_PREDICTED|ENF_WILLBEPREDICTED) ) ){ + // not predicted + return FALSE; + } + + // find eventual prediction tail + if (pen->IsPredictor()) { + pen = pen->GetPredictionTail(); + } + + // gather all event relevant data + ULONG ulEntityID = pen->en_ulID; + TIME tmNow = _pTimer->CurrentTick(); + + BOOL bPredicted = FALSE; + // for each active event + INDEX ctpe = ses_apeEvents.Count(); + {for(INDEX ipe=0; ipe +#include +#include +#include +#include +#include + +#define DEBUG_SYNCSTREAMDUMPING 0 + +#if DEBUG_SYNCSTREAMDUMPING + /* + * Obtain valid session dump memory stream + */ + CTMemoryStream *GetDumpStream(void); + /* + * Clear session dump memory stream + */ + void ClearDumpStream(void); +#endif + +// checksum of world snapshot at given point in time - used for sync-checking +class CSyncCheck { +public: + TIME sc_tmTick; // time of snapshot + INDEX sc_iSequence; // sequence number last processed before this checksum + ULONG sc_ulCRC; // checksum + INDEX sc_iLevel; // checksum of level filename + CSyncCheck(void) { sc_tmTick = -1.0f; sc_iSequence = -1; sc_ulCRC = 0; sc_iLevel = 0; } + void Clear(void) { sc_tmTick = -1.0f; sc_iSequence = -1; sc_ulCRC = 0; sc_iLevel = 0; } +}; + +// info about an event that was predicted to happen +class CPredictedEvent { +public: + TIME pe_tmTick; + ULONG pe_ulEntityID; + ULONG pe_ulTypeID; + ULONG pe_ulEventID; + + CPredictedEvent(void); + void Clear(void) {}; +}; + +/* + * Session state, manipulates local copy of the world + */ +class ENGINE_API CSessionState { +public: + CStaticArray ses_apltPlayers; // client targets for all players in game + CStaticStackArray ses_apeEvents; // for event prediction + + CTString ses_strMOTD; // MOTD as sent from the server + INDEX ses_iLevel; // for counting level changes + INDEX ses_iLastProcessedSequence; // sequence of last processed stream block + CNetworkStream ses_nsGameStream; // stream of blocks from server + + // lerp params + CTimerValue ses_tvInitialization; // exact moment when the session state was started + TIME ses_tmInitializationTick; // tick when the session state was started + // secondary lerp params for non-predicted movement + CTimerValue ses_tvInitialization2; // exact moment when the session state was started + TIME ses_tmInitializationTick2; // tick when the session state was started + + TIME ses_tmLastProcessedTick; // last tick when all actions were processed + TIME ses_tmPredictionHeadTick; // newest tick that was ever predicted + TIME ses_tmLastSyncCheck; // last time sync-check was generated + TIME ses_tmLastPredictionProcessed; // for determining when to do a new prediction cycle + + INDEX ses_iMissingSequence; // first missing sequence + CTimerValue ses_tvResendTime; // timer for missing sequence retransmission + TIME ses_tmResendTimeout; // timeout value for increasing the request interval + CTimerValue ses_tvMessageReceived; // exact moment when the session state was started + + TIME ses_tmLastDemoSequence; // synchronization timer for demo playing + ULONG ses_ulRandomSeed; // seed for pseudo-random number generation + ULONG ses_ulSpawnFlags; // spawn flags for current game + TIME ses_tmSyncCheckFrequency; // frequency of sync-checking + BOOL ses_iExtensiveSyncCheck; // set if syncheck should be extensive - for debugging purposes + + BOOL ses_bKeepingUpWithTime; // set if the session state is keeping up with the time + TIME ses_tmLastUpdated; + CListHead ses_lhRememberedLevels; // list of remembered levels + BOOL ses_bAllowRandom; // set while random number generation is valid + BOOL ses_bPredicting; // set if the game is currently doing prediction + + BOOL ses_bPause; // set while game is paused + BOOL ses_bWantPause; // set while wanting to have paused + BOOL ses_bGameFinished; // set when game has finished + BOOL ses_bWaitingForServer; // wait for server after level change + CTString ses_strDisconnected; // explanation of disconnection or empty string if not disconnected + + INDEX ses_ctMaxPlayers; // maximum number of players allowed in game + BOOL ses_bWaitAllPlayers; // if set, wait for all players to join before starting + FLOAT ses_fRealTimeFactor; // enables slower or faster time for special effects + CTMemoryStream *ses_pstrm; // debug stream for sync check examination + + CSessionSocketParams ses_sspParams; // local copy of server-side parameters +public: + // network message waiters + void Start_AtServer_t(void); // throw char * + void Start_AtClient_t(INDEX ctLocalPlayers); // throw char * + // Set lerping factor for current frame. + void SetLerpFactor(CTimerValue tvNow); + // notify entities of level change + void SendLevelChangeNotification(class CEntityEvent &ee); + // wait for a stream to come from server + void WaitStream_t(CTMemoryStream &strmMessage, const CTString &strName, INDEX iMsgCode); + // check if disconnected + BOOL IsDisconnected(void); + + // print an incoming chat message to console + void PrintChatMessage(ULONG ulFrom, const CTString &strFrom, const CTString &strMessage); +public: + /* Constructor. */ + CSessionState(void); + /* Destructor. */ + ~CSessionState(void); + + // get a pseudo-random number (safe for network gaming) + ULONG Rnd(void); + + /* Stop the session state. */ + void Stop(void); + /* Start session state. */ + void Start_t(INDEX ctLocalPlayers); // throw char * + + // do physics for a game tick + void HandleMovers(void); + // do thinking for a game tick + void HandleTimers(TIME tmCurrentTick); + // do a warm-up run of the world for a few ticks + void WarmUpWorld(void); + // reset random number generator (always randomizes to same sequence!) + void ResetRND(void); + /* Process a game tick. */ + void ProcessGameTick(CNetworkMessage &nmMessage, TIME tmCurrentTick); + /* Process a predicted game tick. */ + void ProcessPredictedGameTick(INDEX iPredictionStep, FLOAT fFactor, TIME tmCurrentTick); + /* Process a gamestream block. */ + void ProcessGameStreamBlock(CNetworkMessage &nmMessage); + /* Process all eventual avaliable gamestream blocks. */ + void ProcessGameStream(void); + // flush prediction actions that were already processed + void FlushProcessedPredictions(void); + /* Find out how many prediction steps are currently pending. */ + INDEX GetPredictionStepsCount(void); + /* Process all eventual avaliable prediction actions. */ + void ProcessPrediction(void); + /* Get number of active players. */ + INDEX GetPlayersCount(void); + /* Remember predictor positions of all players. */ + void RememberPlayerPredictorPositions(void); + /* Get player position. */ + const FLOAT3D &GetPlayerPredictorPosition(INDEX iPlayer); + + // check an event for prediction, returns true if already predicted + BOOL CheckEventPrediction(CEntity *pen, ULONG ulTypeID, ULONG ulEventID); + + // make synchronization test message and send it to server (if client), or add to buffer (if server) + void MakeSynchronisationCheck(void); + // create a checksum value for sync-check + void ChecksumForSync(ULONG &ulCRC, INDEX iExtensiveSyncCheck); + // dump sync data to text file + void DumpSync_t(CTStream &strm, INDEX iExtensiveSyncCheck); // throw char * + + /* Read session state information from a stream. */ + void Read_t(CTStream *pstr); // throw char * + void ReadWorldAndState_t(CTStream *pstr); // throw char * + void ReadRememberedLevels_t(CTStream *pstr); // throw char * + /* Write session state information into a stream. */ + void Write_t(CTStream *pstr); // throw char * + void WriteWorldAndState_t(CTStream *pstr); // throw char * + void WriteRememberedLevels_t(CTStream *pstr); // throw char * + + // remember current level + void RememberCurrentLevel(const CTString &strFileName); + // find a level if it is remembered + class CRememberedLevel *FindRememberedLevel(const CTString &strFileName); + // restore some old level + void RestoreOldLevel(const CTString &strFileName); + // forget all remembered levels + void ForgetOldLevels(void); + + /* Session state loop. */ + void SessionStateLoop(void); + /* Session sync dump functions. */ + void DumpSyncToFile_t(CTStream &strm, INDEX iExtensiveSyncCheck); // throw char * +#if DEBUG_SYNCSTREAMDUMPING + void DumpSyncToMemory(void); +#endif +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Rendering/RenCache.cpp b/Sources/Engine/Rendering/RenCache.cpp new file mode 100644 index 0000000..e419d82 --- /dev/null +++ b/Sources/Engine/Rendering/RenCache.cpp @@ -0,0 +1,903 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#define OFFSET_DN (0.0625f) + +#define CStaticArray_sa_Count 0 +#define CStaticArray_sa_Array 4 + +#define CDynamicArray_da_Pointers 12 +#define CDynamicArray_da_Count 16 +#define CDynamicStackArray_da_ctUsed 24 + +#define sizeof_CWorkingVertex 32 +#define sizeof_CWorkingEdge 32 + +static FLOATaabbox2D *pfbbClipBox; +static PIX pixCurrentScanJ; +static PIX pixBottomScanJ; +static const FLOAT f65536=65536.0f; + +///////////////////////////////////////////////////////////////////// +// Functions for support of transformed caches + +static FLOAT fCenterI, fCenterJ, fRatioI, fRatioJ; +static FLOAT fNearClipDistance, fooNearClipDistance; +static FLOAT fFarClipDistance, fooFarClipDistance; +static FLOAT fooNearRatioI, fooNearRatioJ; +static FLOAT fooFarRatioI, fooFarRatioJ; + + +static CRenderer *_preThis; + +// check if a sector is inside view frustum +__forceinline INDEX CRenderer::IsSectorVisible(CBrush3D &br, CBrushSector &bsc) +{ + // project the bounding sphere of sector bbox to view + FLOAT3D vCenter; + CProjection3D *ppr; + if (re_bBackgroundEnabled && (br.br_penEntity->en_ulFlags & ENF_BACKGROUND)) { + ppr = re_prBackgroundProjection; + } else { + ppr = re_prProjection; + } + ppr->PreClip(bsc.bsc_boxBoundingBox.Center(), vCenter); + FLOAT fR = bsc.bsc_boxBoundingBox.Size().Length()/2.0f; + + // if the sector bounding sphere is inside view frustum + INDEX iFrustumTest = ppr->TestSphereToFrustum( vCenter, fR); + if( iFrustumTest==0) { // if test was indeterminate + // create oriented box and test it to frustum + FLOATobbox3D boxEntity( bsc.bsc_boxBoundingBox, ppr->pr_TranslationVector, ppr->pr_ViewerRotationMatrix); + iFrustumTest = ppr->TestBoxToFrustum(boxEntity); + } + // done + return iFrustumTest; +} + + +/* Transform vertices in one sector before clipping. */ +void CRenderer::PreClipVertices(void) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_TRANSFORMVERTICES); + + const FLOATmatrix3D &m = re_pbrCurrent->br_prProjection->pr_RotationMatrix; + const FLOAT3D &v = re_pbrCurrent->br_prProjection->pr_TranslationVector; + re_pbscCurrent->bsc_ivvx0 = re_iViewVx0 = re_avvxViewVertices.Count(); + INDEX ctvx = re_pbscCurrent->bsc_awvxVertices.Count(); + CViewVertex *avvx = re_avvxViewVertices.Push(ctvx); + // for each vertex in sector + for( INDEX ivx=0; ivxbsc_awvxVertices[ivx]; + // transform it to view space + const FLOAT fx = wvx.wvx_vRelative(1); + const FLOAT fy = wvx.wvx_vRelative(2); + const FLOAT fz = wvx.wvx_vRelative(3); + avvx[ivx].vvx_vView(1) = fx*m(1, 1)+fy*m(1, 2)+fz*m(1, 3)+v(1); + avvx[ivx].vvx_vView(2) = fx*m(2, 1)+fy*m(2, 2)+fz*m(2, 3)+v(2); + avvx[ivx].vvx_vView(3) = fx*m(3, 1)+fy*m(3, 2)+fz*m(3, 3)+v(3); + // clear the outcode initially + avvx[ivx].vvx_ulOutcode = 0; + } + _pfRenderProfile.IncrementCounter(CRenderProfile::PCI_TRANSFORMEDVERTICES, ctvx); + _pfRenderProfile.IncrementTimerAveragingCounter(CRenderProfile::PTI_TRANSFORMVERTICES, ctvx); + + _pfRenderProfile.StopTimer(CRenderProfile::PTI_TRANSFORMVERTICES); +} + +/* Transform planes in one sector before clipping. */ +void CRenderer::PreClipPlanes(void) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_TRANSFORMPLANES); + + INDEX ctpl =re_pbscCurrent->bsc_awplPlanes.Count(); + CProjection3D *ppr = &*re_pbrCurrent->br_prProjection; + const FLOATmatrix3D &m = ppr->pr_RotationMatrix; + const FLOAT3D &v = ppr->pr_TranslationVector; + + // if the projection is perspective + if (re_pbrCurrent->br_prProjection.IsPerspective()) { + + // for each plane in sector + for(INDEX ipl=0; iplbsc_awplPlanes[ipl]; + const FLOAT fx = wpl.wpl_plRelative(1); + const FLOAT fy = wpl.wpl_plRelative(2); + const FLOAT fz = wpl.wpl_plRelative(3); + const FLOAT fd = wpl.wpl_plRelative.Distance(); + wpl.wpl_plView(1) = fx*m(1, 1)+fy*m(1, 2)+fz*m(1, 3); + wpl.wpl_plView(2) = fx*m(2, 1)+fy*m(2, 2)+fz*m(2, 3); + wpl.wpl_plView(3) = fx*m(3, 1)+fy*m(3, 2)+fz*m(3, 3); + wpl.wpl_plView.Distance() = + wpl.wpl_plView(1)*v(1)+ + wpl.wpl_plView(2)*v(2)+ + wpl.wpl_plView(3)*v(3)+ + wpl.wpl_plRelative.Distance(); + // test if the plane is visible + wpl.wpl_bVisible = (wpl.wpl_plView.Distance() < -0.01f); + } + // if the projection is not perspective + } else { + // !!!! speed this up for other projections too ? + // for each plane in sector + for(INDEX ipl=0; iplbsc_awplPlanes[ipl]; + ppr->Project(wpl.wpl_plRelative, wpl.wpl_plView); + // test if the plane is visible + wpl.wpl_bVisible = ppr->IsViewerPlaneVisible(wpl.wpl_plView); + } + } + + // for each plane + {for(INDEX ipl=0; iplbsc_awplPlanes[ipl]; + // make gradients without fog + ppr->MakeOoKGradient(wpl.wpl_plView, wpl.wpl_pgOoK); + // transform it to view space + const FLOAT fxO = wpl.wpl_mvRelative.mv_vO(1); + const FLOAT fyO = wpl.wpl_mvRelative.mv_vO(2); + const FLOAT fzO = wpl.wpl_mvRelative.mv_vO(3); + const FLOAT fxU = wpl.wpl_mvRelative.mv_vU(1); + const FLOAT fyU = wpl.wpl_mvRelative.mv_vU(2); + const FLOAT fzU = wpl.wpl_mvRelative.mv_vU(3); + const FLOAT fxV = wpl.wpl_mvRelative.mv_vV(1); + const FLOAT fyV = wpl.wpl_mvRelative.mv_vV(2); + const FLOAT fzV = wpl.wpl_mvRelative.mv_vV(3); + wpl.wpl_mvView.mv_vO(1) = fxO*m(1, 1)+fyO*m(1, 2)+fzO*m(1, 3)+v(1); + wpl.wpl_mvView.mv_vO(2) = fxO*m(2, 1)+fyO*m(2, 2)+fzO*m(2, 3)+v(2); + wpl.wpl_mvView.mv_vO(3) = fxO*m(3, 1)+fyO*m(3, 2)+fzO*m(3, 3)+v(3); + wpl.wpl_mvView.mv_vU(1) = fxU*m(1, 1)+fyU*m(1, 2)+fzU*m(1, 3); + wpl.wpl_mvView.mv_vU(2) = fxU*m(2, 1)+fyU*m(2, 2)+fzU*m(2, 3); + wpl.wpl_mvView.mv_vU(3) = fxU*m(3, 1)+fyU*m(3, 2)+fzU*m(3, 3); + wpl.wpl_mvView.mv_vV(1) = fxV*m(1, 1)+fyV*m(1, 2)+fzV*m(1, 3); + wpl.wpl_mvView.mv_vV(2) = fxV*m(2, 1)+fyV*m(2, 2)+fzV*m(2, 3); + wpl.wpl_mvView.mv_vV(3) = fxV*m(3, 1)+fyV*m(3, 2)+fzV*m(3, 3); + }} + + _pfRenderProfile.IncrementCounter(CRenderProfile::PCI_TRANSFORMEDPLANES, ctpl); + _pfRenderProfile.IncrementTimerAveragingCounter(CRenderProfile::PTI_TRANSFORMPLANES, ctpl); + + _pfRenderProfile.StopTimer(CRenderProfile::PTI_TRANSFORMPLANES); +} + +// project vertices in current sector after clipping +void CRenderer::PostClipVertices(void) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_PROJECTVERTICES); + const FLOATmatrix3D &m = re_pbrCurrent->br_prProjection->pr_RotationMatrix; + const FLOAT3D &v = re_pbrCurrent->br_prProjection->pr_TranslationVector; + + // if the projection is perspective + if (re_pbrCurrent->br_prProjection.IsPerspective()) { + CPerspectiveProjection3D &prPerspective = (CPerspectiveProjection3D &)*re_pbrCurrent->br_prProjection; + + fCenterI = prPerspective.pr_ScreenCenter(1); + fCenterJ = prPerspective.pr_ScreenCenter(2); + fRatioI = prPerspective.ppr_PerspectiveRatios(1); + fRatioJ = prPerspective.ppr_PerspectiveRatios(2); + + // for each active view vertex + INDEX iVxTop = re_avvxViewVertices.Count(); + for(INDEX ivx = re_iViewVx0; ivxbr_prProjection->PostClip(vvx.vvx_vView, v); + vvx.vvx_fI = v(1); + vvx.vvx_fJ = v(2); + } + } + _pfRenderProfile.StopTimer(CRenderProfile::PTI_PROJECTVERTICES); +} + + +// setup fog/haze for a sector +void CRenderer::SetupFogAndHaze(void) +{ + CBrush3D &br = *re_pbrCurrent; + CBrushSector &bsc = *re_pbscCurrent; + if( _bMultiPlayer) gfx_bRenderFog = 1; // must render fog in multiplayer mode! + + // if the sector is not part of a zoning brush + if (!(br.br_penEntity->en_ulFlags&ENF_ZONING)) { + // do nothing + return; + } + + // if fog is enabled + re_bCurrentSectorHasFog = FALSE; + if( _wrpWorldRenderPrefs.wrp_bFogOn && gfx_bRenderFog) + { // if the sector has fog + CFogParameters fp; + if( bsc.bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->GetFog(bsc.GetFogType(), fp)) { + // activate fog if not already active + if( !_fog_bActive) { + StartFog( fp, br.br_prProjection->pr_vViewerPosition, + br.br_prProjection->pr_ViewerRotationMatrix); + } + // mark that current sector has fog + re_bCurrentSectorHasFog = TRUE; + } + } + + // if haze is enabled + re_bCurrentSectorHasHaze = FALSE; + if( _wrpWorldRenderPrefs.wrp_bHazeOn && gfx_bRenderFog) + { // if the sector has haze + CHazeParameters hp; + FLOAT3D vViewDir; + FLOATmatrix3D &mAbsToView = bsc.bsc_pbmBrushMip->bm_pbrBrush->br_prProjection->pr_ViewerRotationMatrix; + vViewDir(1) = -mAbsToView(3, 1); + vViewDir(2) = -mAbsToView(3, 2); + vViewDir(3) = -mAbsToView(3, 3); + if( bsc.bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->GetHaze(bsc.GetHazeType(), hp, vViewDir)) { + // if viewer is not in haze + if( !re_bViewerInHaze) { + // if viewer is in this sector + if( bsc.bsc_bspBSPTree.TestSphere(re_vdViewSphere, 0.01)>=0) { + // mark that viewer is in haze + re_bViewerInHaze = TRUE; + } + // if there is a viewer + else if( re_penViewer!=NULL) { + // check rest of sectors the viewer is in + {FOREACHSRCOFDST( re_penViewer->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + CHazeParameters hpDummy; + if( pbsc->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->GetHaze( pbsc->GetHazeType(), hpDummy, vViewDir)) { + // if viewer is in this sector + if( pbsc->bsc_bspBSPTree.TestSphere(re_vdViewSphere, 0.01)>=0) { + // mark that viewer is in haze + re_bViewerInHaze = TRUE; + break; + } + } + ENDFOR} + } + } + // if viewer is in haze, or haze can be viewed from outside + if( re_bViewerInHaze || (hp.hp_ulFlags&HPF_VISIBLEFROMOUTSIDE)) { + // activate haze if not already active + if( !_haze_bActive) { + StartHaze( hp, br.br_prProjection->pr_vViewerPosition, + br.br_prProjection->pr_ViewerRotationMatrix); + } + // mark that current sector has haze + re_bCurrentSectorHasHaze = TRUE; + } + } + } +} + + +/* + * Add an edge to add list of its top scanline. + */ +void CRenderer::AddEdgeToAddAndRemoveLists(CScreenEdge &sed) +{ + _pfRenderProfile.IncrementTimerAveragingCounter(CRenderProfile::PTI_ADDEDGETOADDLIST, 1); + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDEDGETOADDLIST); + + // add it to the remove list at its bottom scan line + ASSERT(sed.sed_pixBottomJ-1-re_pixTopScanLineJ < re_ctScanLines); + INDEX iBottomLine = sed.sed_pixBottomJ-1-re_pixTopScanLineJ; + sed.sed_psedNextRemove = re_apsedRemoveFirst[iBottomLine]; + re_apsedRemoveFirst[iBottomLine] = &sed; + + // search all edges in the add list of top scan line of this edge + INDEX iTopLine = sed.sed_pixTopJ-re_pixTopScanLineJ; + CListNode *plnInList = re_alhAddLists[iTopLine].lh_Head; + re_actAddCounts[iTopLine]++; + SLONG slIThis = sed.sed_xI.slHolder; + + ASSERT(sed.sed_xI > FIX16_16(re_fbbClipBox.Min()(1)-SENTINELEDGE_EPSILON)); + ASSERT(sed.sed_xI < FIX16_16(re_fbbClipBox.Max()(1)+SENTINELEDGE_EPSILON)); + + SLONG slIInList; + while(plnInList->ln_Succ!=NULL) { + slIInList = + ((CAddEdge*)((UBYTE*)plnInList-offsetof(CAddEdge, ade_lnInAdd))) -> ade_xI.slHolder; + // if the edge in list is right of the one to add + if (slIInList>slIThis) { + // stop searching + break; + } + plnInList = plnInList->ln_Succ; + } + // add it to add list + CAddEdge &ade = re_aadeAddEdges.Push(); + ade = CAddEdge(&sed); + CListNode *plnThis = &ade.ade_lnInAdd; + CListNode *plnAfter = plnInList; + CListNode *plnBefore = plnInList->ln_Pred; + plnThis->ln_Succ = plnAfter; + plnThis->ln_Pred = plnBefore; + plnBefore->ln_Succ = plnThis; + plnAfter->ln_Pred = plnThis; + // mark that it is added + sed.sed_bAdded = TRUE; + ASSERT(re_actAddCounts[iTopLine]==re_alhAddLists[iTopLine].Count()); + + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDEDGETOADDLIST); +} + +/* + * Make a screen edge from two vertices doing 2D clipping. + */ +inline void CRenderer::MakeScreenEdge( + CScreenEdge &sed, FLOAT fI0, FLOAT fJ0, FLOAT fI1, FLOAT fJ1) +{ + // mark both vertices as not clipped + _pfRenderProfile.IncrementTimerAveragingCounter(CRenderProfile::PTI_MAKESCREENEDGE, 1); + _pfRenderProfile.StartTimer(CRenderProfile::PTI_MAKESCREENEDGE); + enum LineDirectionType ldtDirection; + + // bias edges towards each others - fix against generating extra trapezoids + if (fJ0re_fbbClipBox.Max()(1)) { + fI0 = re_fbbClipBox.Max()(1); + } + if (fI1>re_fbbClipBox.Max()(1)) { + fI1 = re_fbbClipBox.Max()(1); + } + + FLOAT fDJ=fJ1-fJ0; + FLOAT fDI=fI1-fI0; + + FLOAT fDIoDJ = fDI/fDJ; + + // mark edge as descending + ldtDirection = LDT_DESCENDING; + + // if vertex 0 is below vertex 1 + if ((SLONG&)fDJ<0 ) { // fJ0>fJ1 + // mark edge as ascending + ldtDirection = LDT_ASCENDING; + Swap(fI0, fI1); + Swap(fJ0, fJ1); + fDI = -fDI; + fDJ = -fDJ; + } + + ASSERT(fI0>=re_fbbClipBox.Min()(1)); + ASSERT(fI1>=re_fbbClipBox.Min()(1)); + ASSERT(fI0>=-0.5f); + ASSERT(fI1>=-0.5f); + ASSERT(fI0<=re_fbbClipBox.Max()(1)); + ASSERT(fI1<=re_fbbClipBox.Max()(1)); + + // set line direction + sed.sed_ldtDirection = ldtDirection; + + // edge has polygon initially + sed.sed_pspo = NULL; + // edge is not linked to add and remove lists initially + sed.sed_bAdded = FALSE; + sed.sed_psedNextRemove = NULL; + + // if bottom vertex is above screen top or top vertex is below screen bottom + FLOAT fDJ1Up = fJ1-re_fbbClipBox.Min()(2); + FLOAT fDJ0Dn = re_fbbClipBox.Max()(2)-fJ0; + if ((SLONG&)(fDJ1Up)<0 || (SLONG&)(fDJ0Dn)<0) { + // generate dummy horizontal screen edge + sed.sed_pixTopJ = (PIX) 0; + sed.sed_pixBottomJ = (PIX) 0; + sed.sed_ldtDirection = LDT_HORIZONTAL; + + // otherwise + } else { + // calculate edge slope and convert it to fixed integer + sed.sed_xIStep = (FIX16_16)fDIoDJ; + // convert J coordinates to integers + sed.sed_pixTopJ = PIXCoord(fJ0); + sed.sed_pixBottomJ = PIXCoord(fJ1); + + // if the edge bottom is below screen bottom + if (sed.sed_pixTopJre_pixBottomScanLineJ) { + // set it to bottom + sed.sed_pixBottomJ = re_pixBottomScanLineJ; + } + + // make fixed integer representation of top I coordinate with correction + sed.sed_xI = (FIX16_16) (fI0 + ((FLOAT)sed.sed_pixTopJ-fJ0) * fDIoDJ ); + } + + ASSERT( sed.sed_xI > FIX16_16(-1.0f) + && sed.sed_xI < FIX16_16(re_fbbClipBox.Max()(1) + SENTINELEDGE_EPSILON) + || (sed.sed_pixTopJ >= sed.sed_pixBottomJ)); + + // return the screen edge + _pfRenderProfile.StopTimer(CRenderProfile::PTI_MAKESCREENEDGE); +} + +// add screen edges for all polygons in current sector +void CRenderer::AddScreenEdges(void) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDSCREENEDGES); + // for each polygon + INDEX ispo0 = re_pbscCurrent->bsc_ispo0; + INDEX ispoTop = re_pbscCurrent->bsc_ispo0+re_pbscCurrent->bsc_ctspo; + for(INDEX ispo = ispo0; ispore_pixCurrentScanJ) { + // set its polygon + sed.sed_pspo = &spo; + // add it + AddEdgeToAddAndRemoveLists(sed); + } + + // go to next edge + ised++; + } + } + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDSCREENEDGES); +} + +// set scene rendering parameters for one polygon texture +void CRenderer::SetOneTextureParameters(CBrushPolygon &bpo, ScenePolygon &spo, INDEX iLayer) +{ + spo.spo_aptoTextures[iLayer] = NULL; + CTextureData *ptd = (CTextureData *)bpo.bpo_abptTextures[iLayer].bpt_toTexture.GetData(); + + // if there is no texture or it should not be shown + if (ptd==NULL || !_wrpWorldRenderPrefs.wrp_abTextureLayers[iLayer]) { + // do nothing + return; + } + + CWorkingPlane &wpl = *bpo.bpo_pbplPlane->bpl_pwplWorking; + // set texture and its parameters + spo.spo_aptoTextures[iLayer] = &bpo.bpo_abptTextures[iLayer].bpt_toTexture; + + // get texture blending type + CTextureBlending &tb = re_pwoWorld->wo_atbTextureBlendings[bpo.bpo_abptTextures[iLayer].s.bpt_ubBlend]; + + // set texture blending flags + ASSERT( BPTF_CLAMPU==STXF_CLAMPU && BPTF_CLAMPV==STXF_CLAMPV && BPTF_AFTERSHADOW==STXF_AFTERSHADOW); + spo.spo_aubTextureFlags[iLayer] = + (bpo.bpo_abptTextures[iLayer].s.bpt_ubFlags & (BPTF_CLAMPU|BPTF_CLAMPV|BPTF_AFTERSHADOW)) + | (tb.tb_ubBlendingType); + if( bpo.bpo_abptTextures[iLayer].s.bpt_ubFlags & BPTF_REFLECTION) spo.spo_aubTextureFlags[iLayer] |= STXF_REFLECTION; + + // set texture blending color + spo.spo_acolColors[iLayer] = MulColors( bpo.bpo_abptTextures[iLayer].s.bpt_colColor, tb.tb_colMultiply); + + // if texture should be not transformed + INDEX iTransformation = bpo.bpo_abptTextures[iLayer].s.bpt_ubScroll; + if( iTransformation==0) + { + // if texture is wrapped on both axes + if( (bpo.bpo_abptTextures[iLayer].s.bpt_ubFlags&(BPTF_CLAMPU|BPTF_CLAMPV))==0) + { // make a mapping adjusted for texture wrapping + const MEX mexMaskU = ptd->GetWidth() -1; + const MEX mexMaskV = ptd->GetHeight() -1; + CMappingDefinition mdTmp = bpo.bpo_abptTextures[iLayer].bpt_mdMapping; + mdTmp.md_fUOffset = (FloatToInt(mdTmp.md_fUOffset*1024.0f) & mexMaskU) /1024.0f; + mdTmp.md_fVOffset = (FloatToInt(mdTmp.md_fVOffset*1024.0f) & mexMaskV) /1024.0f; + const FLOAT3D vOffset = wpl.wpl_plView.ReferencePoint() - wpl.wpl_mvView.mv_vO; + const FLOAT fS = vOffset % wpl.wpl_mvView.mv_vU; + const FLOAT fT = vOffset % wpl.wpl_mvView.mv_vV; + const FLOAT fU = fS*mdTmp.md_fUoS + fT*mdTmp.md_fUoT + mdTmp.md_fUOffset; + const FLOAT fV = fS*mdTmp.md_fVoS + fT*mdTmp.md_fVoT + mdTmp.md_fVOffset; + mdTmp.md_fUOffset += (FloatToInt(fU*1024.0f) & ~mexMaskU) /1024.0f; + mdTmp.md_fVOffset += (FloatToInt(fV*1024.0f) & ~mexMaskV) /1024.0f; + // make texture mapping vectors from default vectors of the plane + mdTmp.MakeMappingVectors( wpl.wpl_mvView, spo.spo_amvMapping[iLayer]); + } + // if texture is clamped + else { + // just make texture mapping vectors from default vectors of the plane + bpo.bpo_abptTextures[iLayer].bpt_mdMapping.MakeMappingVectors( wpl.wpl_mvView, spo.spo_amvMapping[iLayer]); + } + } + // if texture should be transformed + else { + // make mapping vectors as normal and then transform them + CMappingDefinition &mdBase = bpo.bpo_abptTextures[iLayer].bpt_mdMapping; + CMappingDefinition &mdScroll = re_pwoWorld->wo_attTextureTransformations[iTransformation].tt_mdTransformation; + CMappingVectors mvTmp; + mdBase.MakeMappingVectors( wpl.wpl_mvView, mvTmp); + mdScroll.TransformMappingVectors( mvTmp, spo.spo_amvMapping[iLayer]); + } +} + +/* + * Make a screen polygon for a brush polygon + */ +CScreenPolygon *CRenderer::MakeScreenPolygon(CBrushPolygon &bpo) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_MAKESCREENPOLYGON); + _pfRenderProfile.IncrementTimerAveragingCounter(CRenderProfile::PTI_MAKESCREENPOLYGON, 1); + // create a new screen polygon + CScreenPolygon &spo = re_aspoScreenPolygons.Push(); + ScenePolygon &sppo = spo.spo_spoScenePolygon; + bpo.bpo_pspoScreenPolygon = &spo; + CBrush3D &br = *re_pbrCurrent; + CBrushSector &bsc = *re_pbscCurrent; + sppo.spo_pvPolygon = &bpo; + sppo.spo_iVtx0 = 0; + sppo.spo_ctVtx = 0; + sppo.spo_piElements = NULL; + sppo.spo_ctElements = 0; + spo.spo_bActive = TRUE; + spo.spo_ubSpanAdded = 0; + // link with brush polygon + spo.spo_pbpoBrushPolygon = &bpo; + spo.spo_ubIllumination = bpo.bpo_bppProperties.bpp_ubIlluminationType; + + // if this is a field brush + if (br.br_pfsFieldSettings!=NULL) { + // set the polygon up to render as a field brush + bpo.bpo_abptTextures[0].bpt_toTexture.SetData(br.br_pfsFieldSettings->fs_toTexture.GetData()); + bpo.bpo_abptTextures[0].s.bpt_colColor = br.br_pfsFieldSettings->fs_colColor; + bpo.bpo_abptTextures[0].s.bpt_ubScroll = 0; + bpo.bpo_abptTextures[0].s.bpt_ubFlags = 0; + bpo.bpo_abptTextures[0].s.bpt_ubBlend = BPT_BLEND_BLEND; + bpo.bpo_abptTextures[1].bpt_toTexture.SetData(NULL); + bpo.bpo_abptTextures[2].bpt_toTexture.SetData(NULL); + bpo.bpo_ulFlags = BPOF_PORTAL|BPOF_RENDERASPORTAL|BPOF_FULLBRIGHT|BPOF_TRANSLUCENT|BPOF_DETAILPOLYGON; + } + + // just copy depth gradient from plane + CWorkingPlane &wpl = *bpo.bpo_pbplPlane->bpl_pwplWorking; + spo.spo_pgOoK = wpl.wpl_pgOoK; + spo.spo_spoScenePolygon.spo_cColor = ColorForPolygons(bpo.bpo_colColor, bsc.bsc_colColor); + + // set polygon shadow + sppo.spo_psmShadowMap = NULL; + if(_wrpWorldRenderPrefs.wrp_shtShadows != CWorldRenderPrefs::SHT_NONE + &&!(bpo.bpo_ulFlags&BPOF_FULLBRIGHT)) { + sppo.spo_psmShadowMap = &bpo.bpo_smShadowMap; + } + + // make texture mapping vectors from default vectors of the plane + CMappingDefinition mdShadow; + mdShadow.md_fUoS = 1; + mdShadow.md_fUoT = 0; + mdShadow.md_fVoS = 0; + mdShadow.md_fVoT = 1; + mdShadow.md_fUOffset = -bpo.bpo_smShadowMap.sm_mexOffsetX/1024.0f; + mdShadow.md_fVOffset = -bpo.bpo_smShadowMap.sm_mexOffsetY/1024.0f; + mdShadow.MakeMappingVectors(wpl.wpl_mvView, sppo.spo_amvMapping[3]); + // adjust shadow blending type + CTextureBlending &tbShadow = re_pwoWorld->wo_atbTextureBlendings[bpo.bpo_bppProperties.bpp_ubShadowBlend]; + sppo.spo_aubTextureFlags[3] = STXF_CLAMPU|STXF_CLAMPV|tbShadow.tb_ubBlendingType; + // set shadow blending color + sppo.spo_acolColors[3] = MulColors(bpo.bpo_colShadow, tbShadow.tb_colMultiply); + + // set textures for the polygon + SetOneTextureParameters( bpo, sppo, 0); + SetOneTextureParameters( bpo, sppo, 1); + SetOneTextureParameters( bpo, sppo, 2); + + // clear polygon flags + sppo.spo_ulFlags = 0; + if (_wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_TEXTURE) { + sppo.spo_aptoTextures[0] = NULL; + sppo.spo_aptoTextures[1] = NULL; + sppo.spo_aptoTextures[2] = NULL; + } + + // if the sector has fog + if (re_bCurrentSectorHasFog) { + // mark for rendering with fog + sppo.spo_ulFlags |= SPOF_RENDERFOG; + } + // if the sector has haze + if (re_bCurrentSectorHasHaze) { + // mark polygon for haze rendering + sppo.spo_ulFlags |= SPOF_RENDERHAZE; + } + + // if the polygon is selected + BOOL bSelected = PolygonIsSelected( bpo, br, bsc); + if (bSelected) { + // mark this polygon for drawing as selected + sppo.spo_ulFlags |= SPOF_SELECTED; + } + + // if the polygon is transparent + if( bpo.bpo_ulFlags & BPOF_TRANSPARENT) { + // mark that this polygon will need alpha keying + sppo.spo_ulFlags |= SPOF_TRANSPARENT; + } + + BOOL bBackgroundPolygon = re_bBackgroundEnabled && + (bpo.bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->en_ulFlags&ENF_BACKGROUND); + // if this is a backfill polygon or illumination polygon for rendering lights + if (bBackgroundPolygon + ||(re_ubLightIllumination!=0 && re_ubLightIllumination==bpo.bpo_bppProperties.bpp_ubIlluminationType)) { + // mark this polygon as backlight (for shadow rendering) + sppo.spo_ulFlags |= SPOF_BACKLIGHT; + // adjust gradients used for sorting to be just before the far sentinel + spo.spo_pgOoK.Add(-2.0f); + } + + // init as not in stack + ASSERT(!spo.spo_lnInStack.IsLinked()); + spo.spo_iInStack = 0; + spo.spo_psedSpanStart = NULL; + + // eventually adjust polygon opacity depending on brush entity variable + BOOL bForceTraslucency = FALSE; + const FLOAT fOpacity = br.br_penEntity->GetOpacity(); + if( fOpacity<1) + { // better to hold opacity in integer + const SLONG slOpacity = NormFloatToByte(fOpacity); + // for all texture layers (not shadowmap!) + for( INDEX i=0; i<3; i++) { + // if texture is opaque + if( (sppo.spo_aubTextureFlags[i] & STXF_BLEND_MASK) == 0) { + // set it to blend with opaque alpha + sppo.spo_aubTextureFlags[i] |= STXF_BLEND_ALPHA; + sppo.spo_acolColors[i] |= CT_AMASK; + } + // if texture is blended + if( sppo.spo_aubTextureFlags[i] & STXF_BLEND_ALPHA) { + // adjust it's alpha factor + SLONG slAlpha = (sppo.spo_acolColors[i] & CT_AMASK) >>CT_ASHIFT; + slAlpha = (slAlpha*slOpacity)>>8; + sppo.spo_acolColors[i] &= ~CT_AMASK; + sppo.spo_acolColors[i] |= slAlpha; + } + } + // mark that we need translucency + bForceTraslucency = TRUE; + } + + // not translucent by default + bpo.bpo_ulFlags &= ~BPOF_RENDERTRANSLUCENT; + + // if the polygon is a portal that is either translucent or selected + if( bForceTraslucency || ((bpo.bpo_ulFlags & BPOF_RENDERASPORTAL) + && ((bpo.bpo_ulFlags & BPOF_TRANSLUCENT) || bSelected))) { + // if not rendering shadows + if (!re_bRenderingShadows) { + // mark for rendering as translucent + bpo.bpo_ulFlags |= BPOF_RENDERTRANSLUCENT; + // add it to the list of translucent span polygons in this renderer + if (bBackgroundPolygon) { + spo.spo_spoScenePolygon.spo_pspoSucc = re_pspoFirstBackgroundTranslucent; + re_pspoFirstBackgroundTranslucent = &spo.spo_spoScenePolygon; + } else { + spo.spo_spoScenePolygon.spo_pspoSucc = re_pspoFirstTranslucent; + re_pspoFirstTranslucent = &spo.spo_spoScenePolygon; + } + // if it is not translucent (ie. it is just plain portal, but selected) + if( !(bpo.bpo_ulFlags & BPOF_TRANSLUCENT) && !bForceTraslucency) { + // set its texture for selection + CModelObject *pmoSelectedPortal = _wrpWorldRenderPrefs.wrp_pmoSelectedPortal; + if (pmoSelectedPortal!=NULL) { + sppo.spo_aptoTextures[0] = &pmoSelectedPortal->mo_toTexture; + sppo.spo_acolColors[0] = C_WHITE|CT_OPAQUE; + sppo.spo_aubTextureFlags[0] = STXF_BLEND_ALPHA; + } + // get its mapping gradients from shadowmap and stretch + CWorkingPlane &wpl = *bpo.bpo_pbplPlane->bpl_pwplWorking; + sppo.spo_amvMapping[0] = sppo.spo_amvMapping[3]; + FLOAT fStretch = bpo.bpo_boxBoundingBox.Size().Length()/1000; + sppo.spo_amvMapping[0].mv_vU *= fStretch; + sppo.spo_amvMapping[0].mv_vV *= fStretch; + } + } + } + // if the polygon is ordinary wall + else { + // add it to the list of span polygons in this renderer + if (bBackgroundPolygon) { + spo.spo_spoScenePolygon.spo_pspoSucc = re_pspoFirstBackground; + re_pspoFirstBackground = &spo.spo_spoScenePolygon; + } else { + spo.spo_spoScenePolygon.spo_pspoSucc = re_pspoFirst; + re_pspoFirst = &spo.spo_spoScenePolygon; + } + } + + // return the screen polygon + _pfRenderProfile.StopTimer(CRenderProfile::PTI_MAKESCREENPOLYGON); + return &spo; +} + + +/* Add a polygon to scene rendering. */ +void CRenderer::AddPolygonToScene( CScreenPolygon *pspo) +{ + // if the polygon is not falid or occluder and not selected + CBrushPolygon &bpo = *pspo->spo_pbpoBrushPolygon; + if( &bpo==NULL || ((bpo.bpo_ulFlags&BPOF_OCCLUDER) && (!(bpo.bpo_ulFlags&BPOF_SELECTED) || + _wrpWorldRenderPrefs.GetSelectionType()!=CWorldRenderPrefs::ST_POLYGONS))) { + // do not add it to rendering + return; + } + CBrushSector &bsc = *bpo.bpo_pbscSector; + ScenePolygon &sppo = pspo->spo_spoScenePolygon; + const CViewVertex *pvvx0 = &re_avvxViewVertices[bsc.bsc_ivvx0]; + const INDEX ctVtx = bpo.bpo_apbvxTriangleVertices.Count(); + sppo.spo_iVtx0 = _avtxScene.Count(); + GFXVertex3 *pvtx = _avtxScene.Push(ctVtx); + + // find vertex with nearest Z distance while copying vertices + FLOAT fNearestZ = 123456789.0f; + for( INDEX i=0; ispo_pbpoBrushPolygon->bpo_pbplPlane->bpl_pwplWorking->wpl_plView.Distance(); + sppo.spo_fNearestZ = Max( fNearestZ, fNearestD); + + // all done + sppo.spo_ctVtx = ctVtx; + sppo.spo_piElements = &bpo.bpo_aiTriangleElements[0]; + sppo.spo_ctElements = bpo.bpo_aiTriangleElements.Count(); + _sfStats.IncrementCounter(CStatForm::SCI_SCENE_TRIANGLES, sppo.spo_ctElements/3); +} + + +/* + * Generate a span for a polygon on current scan line. + */ +void CRenderer::MakeSpan(CScreenPolygon &spo, CScreenEdge *psed0, CScreenEdge *psed1) +{ + // the polygon must not be portal and not illuminating for rendering lights + ASSERT(!(spo.IsPortal() + && (re_ubLightIllumination==0 || re_ubLightIllumination!=spo.spo_ubIllumination))); + + // if rendering shadows + if( re_bRenderingShadows) { + // create a new span for it + CSpan *pspSpan = &re_aspSpans.Push(); + // set up span values + pspSpan->sp_psedEdge0 = psed0; + pspSpan->sp_psedEdge1 = psed1; + pspSpan->sp_pspoPolygon = &spo; + } + // if rendering view + else { + // if no span added to this polygon yet + if( !spo.spo_ubSpanAdded) { + spo.spo_ubSpanAdded = 1; + // add mirror if needed + AddMirror(spo); + // add polygon to scene polygons + AddPolygonToScene(&spo); + const PIX pixI0 = PIXCoord(psed0->sed_xI); + const PIX pixI1 = PIXCoord(psed1->sed_xI); + spo.spo_pixMinI = pixI0; + spo.spo_pixMaxI = pixI1; + spo.spo_pixMinJ = re_pixCurrentScanJ; + spo.spo_pixMaxJ = re_pixCurrentScanJ; + spo.spo_pixTotalArea = pixI1-pixI0; + } else { + const PIX pixI0 = PIXCoord(psed0->sed_xI); + const PIX pixI1 = PIXCoord(psed1->sed_xI); + spo.spo_pixMinI = Min(spo.spo_pixMinI, pixI0); + spo.spo_pixMaxI = Max(spo.spo_pixMaxI, pixI1); + spo.spo_pixMinJ = Min(spo.spo_pixMinJ, re_pixCurrentScanJ); + spo.spo_pixMaxJ = Max(spo.spo_pixMaxJ, re_pixCurrentScanJ); + spo.spo_pixTotalArea += pixI1-pixI0; + } + } +} + +/* + * Add spans in current line to scene. + */ +void CRenderer::AddSpansToScene(void) +{ + if( !re_bRenderingShadows) { + return; + } + + FLOAT fpixLastScanJOffseted = re_pixCurrentScanJ-1 +OFFSET_DN; + // first, little safety check - quit if zero spans in line! + INDEX ctSpans = re_aspSpans.Count(); + if( ctSpans==0) { + return; + } + + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDSPANSTOSCENE); + UBYTE *pubShadow = re_pubShadow+re_slShadowWidth*re_iCurrentScan; + INDEX ctPixels = 0; + // for all spans in the current line + for( INDEX iSpan=0; iSpansed_xI); + PIX pixI1 = PIXCoord( spSpan.sp_psedEdge1->sed_xI); + // get its length + PIX pixLen = pixI1-pixI0; + // skip this span if zero pixels long + if( pixLen<=0) continue; + + // if the span's polygon is background and of proper illumination + if ((spSpan.sp_pspoPolygon->spo_spoScenePolygon.spo_ulFlags & SPOF_BACKLIGHT) + &&(spSpan.sp_pspoPolygon->spo_ubIllumination==re_ubLightIllumination)) { + // mark those pixels as lighted + memset(pubShadow, 255, pixLen); + pubShadow+=pixLen; + // mark that at least one pixel is lighted + re_bSomeLightExists = TRUE; + // if the spans polygon is some other polygon + } else { + // mark those pixels as shadowed + memset(pubShadow, 0, pixLen); + pubShadow+=pixLen; + // mark that at least one pixel is darkened + re_bSomeDarkExists = TRUE; + } + // add to pixel counter + ctPixels+=pixLen; + } + ASSERT(ctPixels<=re_pixSizeI); + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDSPANSTOSCENE); +} + diff --git a/Sources/Engine/Rendering/RendASER.cpp b/Sources/Engine/Rendering/RendASER.cpp new file mode 100644 index 0000000..7e9aff5 --- /dev/null +++ b/Sources/Engine/Rendering/RendASER.cpp @@ -0,0 +1,851 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +/* + * Add all edges in add list to active list. + */ +void CRenderer::AddAddListToActiveList(INDEX iScanLine) +{ + INDEX ctAddEdges = re_actAddCounts[iScanLine]; + // if the add list is empty + if (ctAddEdges==0) { + // do nothing + return; + } + + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDADDLIST); + CListHead &lhAdd = re_alhAddLists[iScanLine]; + ASSERT(ctAddEdges==lhAdd.Count()); + // mark that scan-line coherence is lost + re_bCoherentScanLine = 0; + + // allocate space in destination for sum of source and add + INDEX ctActiveEdges = re_aaceActiveEdges.Count(); + re_aaceActiveEdgesTmp.Push(ctAddEdges+ctActiveEdges); + + // check that the add list is sorted right + #if ASER_EXTREME_CHECKING + { + LISTITER(CAddEdge, ade_lnInAdd) itadeAdd(lhAdd); + FIX16_16 xLastI; + xLastI.slHolder = MIN_SLONG; + while(!itadeAdd.IsPastEnd()) { + CAddEdge &adeAdd = *itadeAdd; + ASSERT(adeAdd.ade_xI==adeAdd.ade_psedEdge->sed_xI); + ASSERT(xLastI.slHolder <= adeAdd.ade_xI.slHolder); + xLastI = adeAdd.ade_xI; + itadeAdd.MoveToNext(); + } + } + #endif + + // check that the active list is sorted right + #if ASER_EXTREME_CHECKING + { + CActiveEdge *paceEnd = &re_aaceActiveEdges[re_aaceActiveEdges.Count()-1]; + CActiveEdge *paceSrc = &re_aaceActiveEdges[0]; + while (paceSrcace_xI.slHolder < itadeAdd->ade_xI.slHolder) { + // copy the active edge + ASSERT(paceSrc<=&re_aaceActiveEdges[ctActiveEdges-1]); + *paceDst++=*paceSrc++; + IFDEBUG(ctOldActive1++); + } + + // copy the add edge + ASSERT(paceDst > &re_aaceActiveEdgesTmp[0]); + ASSERT(ade.ade_xI.slHolder == ade.ade_psedEdge->sed_xI.slHolder); + ASSERT(paceDst[-1].ace_xI.slHolder <= ade.ade_xI.slHolder); + + *paceDst++=CActiveEdge(itadeAdd->ade_psedEdge); + IFDEBUG(ctNewActive++); + // advance iterator in add list + itadeAdd.MoveToNext(); + } + // clear the add list + lhAdd.Clear(); + re_actAddCounts[iScanLine] = 0; + // copy all edges left in the active list + while (paceSrc<=&re_aaceActiveEdges[ctActiveEdges-1]) { + *paceDst++=*paceSrc++; + IFDEBUG(ctOldActive2++); + } + + // swap the lists + Swap(re_aaceActiveEdges.sa_Count , re_aaceActiveEdgesTmp.sa_Count ); + Swap(re_aaceActiveEdges.sa_Array , re_aaceActiveEdgesTmp.sa_Array ); + Swap(re_aaceActiveEdges.sa_UsedCount, re_aaceActiveEdgesTmp.sa_UsedCount); + re_aaceActiveEdgesTmp.PopAll(); + + if (ctAddEdges>_ctMaxAddEdges) { + _ctMaxAddEdges=ctAddEdges; + } + if (re_aaceActiveEdges.Count()>_ctMaxActiveEdges) { + _ctMaxActiveEdges=re_aaceActiveEdges.Count(); + } + + // check that the active list is sorted right + #if ASER_EXTREME_CHECKING + { + CActiveEdge *paceEnd = &re_aaceActiveEdges[re_aaceActiveEdges.Count()-1]; + CActiveEdge *paceSrc = &re_aaceActiveEdges[0]; + while (paceSrcsed_xI.slHolder = ACE_REMOVED; + psed = psed->sed_psedNextRemove; + } while (psed!=NULL); + + // for each active edge + CActiveEdge *paceEnd = &re_aaceActiveEdges[re_aaceActiveEdges.Count()-1]; + CActiveEdge *paceSrc = &re_aaceActiveEdges[1]; + CActiveEdge *paceDst = paceSrc; + do { + // if it is not removed + if (paceSrc->ace_psedEdge->sed_xI.slHolder!=ACE_REMOVED) { + // copy it + *paceDst = *paceSrc; + paceDst++; + } + paceSrc++; + } while (paceSrc<=paceEnd); + // trim the end of active list + re_aaceActiveEdges.PopUntil(paceDst-&re_aaceActiveEdges[0]-1); + + // check that the active list is sorted right + #if ASER_EXTREME_CHECKING + { + CActiveEdge *paceEnd = &re_aaceActiveEdges[re_aaceActiveEdges.Count()-1]; + CActiveEdge *paceSrc = &re_aaceActiveEdges[0]; + while (paceSrcace_xI.slHolder += pace->ace_xIStep.slHolder; + + // if the previous is right of the current + if (pace[-1].ace_xI.slHolder > pace->ace_xI.slHolder) { + // mark that scan-line coherence is lost + re_bCoherentScanLine = 0; + + // find last one that is not right + CActiveEdge *pacePred = pace; + do { + pacePred--; + } while(pacePred->ace_xI.slHolder > pace->ace_xI.slHolder); + + // remember the current one + CActiveEdge aceCurrent = *pace; + // move all of the edges between one place forward + CActiveEdge *paceMove=pace-1; + do { + paceMove[1]=paceMove[0]; + paceMove--; + } while (paceMove>pacePred); + // insert the current to its new place + paceMove[1] = aceCurrent; + } + + pace++; + } while (pace < paceEnd); + + // check that the active list is sorted right + #if ASER_EXTREME_CHECKING + { + CActiveEdge *paceEnd = &re_aaceActiveEdges[re_aaceActiveEdges.Count()-1]; + CActiveEdge *paceSrc = &re_aaceActiveEdges[0]; + while (paceSrcace_psedEdge->sed_xI.slHolder = pace->ace_xI.slHolder; + pace++; + } while (pace<=paceEnd); +} + +/* + * Remove an active portal from rendering + */ +void CRenderer::RemovePortal(CScreenPolygon &spo) +{ + ASSERT(spo.IsPortal()); + ASSERT(spo.spo_bActive); + spo.spo_bActive = FALSE; + + // if it is a translucent portal + if (spo.spo_pbpoBrushPolygon->bpo_ulFlags & (BPOF_RENDERTRANSLUCENT|BPOF_TRANSPARENT)) { + _pfRenderProfile.StartTimer(CRenderProfile::PTI_PROCESSTRANSPORTAL); + // add polygon to scene polygons for rendering + AddPolygonToScene(&spo); + _pfRenderProfile.StopTimer(CRenderProfile::PTI_PROCESSTRANSPORTAL); + } + + // if it is in the surface stack + if (spo.spo_lnInStack.IsLinked()) { + // remove it from surface stack + RemPolygonFromSurfaceStack(spo); + spo.spo_iInStack = 0; + } +} + +/* + * Add sector(s) adjoined to a portal to rendering and remove the portal. + */ +void CRenderer::PassPortal(CScreenPolygon &spo) +{ + ChangeStatsMode(CStatForm::STI_WORLDTRANSFORM); + _pfRenderProfile.StartTimer(CRenderProfile::PTI_PASSPORTAL); + // remove the portal from rendering + RemovePortal(spo); + + // for all sectors related to the portal + {FOREACHDSTOFSRC(spo.spo_pbpoBrushPolygon->bpo_rsOtherSideSectors, CBrushSector, bsc_rdOtherSidePortals, pbsc) + // if the sector is hidden when not rendering shadows + if ((pbsc->bsc_ulFlags&BSCF_HIDDEN) && !re_bRenderingShadows) { + // skip it + continue; + } + // get brush of the sector + CBrushMip *pbmSectorMip = pbsc->bsc_pbmBrushMip; + CBrush3D &brBrush = *pbmSectorMip->bm_pbrBrush; + // prepare the brush entity for rendering if not yet prepared + PrepareBrush(brBrush.br_penEntity); + // get relevant mip factor for that brush and current rendering prefs + CBrushMip *pbmRelevantMip; + if (brBrush.br_ulFlags&BRF_DRAWFIRSTMIP) { + pbmRelevantMip = brBrush.GetBrushMipByDistance( + _wrpWorldRenderPrefs.GetCurrentMipBrushingFactor(0.0f)); + } else { + pbmRelevantMip = brBrush.GetBrushMipByDistance( + _wrpWorldRenderPrefs.GetCurrentMipBrushingFactor(brBrush.br_prProjection->MipFactor())); + } + // if relevant brush mip is same as the sector's brush mip + if (pbmSectorMip==pbmRelevantMip) { + // add that sector to active sectors + AddActiveSector(*pbsc); + } + ENDFOR} + _pfRenderProfile.StopTimer(CRenderProfile::PTI_PASSPORTAL); + ChangeStatsMode(CStatForm::STI_WORLDVISIBILITY); +} + +/* + * Add a sector of a brush to rendering queues. + */ +void CRenderer::AddActiveSector(CBrushSector &bscSector) +{ + // if already active + if (bscSector.bsc_lnInActiveSectors.IsLinked()) { + // do nothing; + return; + } + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDSECTOR); + + // add it to active sectors list + re_lhActiveSectors.AddTail(bscSector.bsc_lnInActiveSectors); + + ASSERT((_controlfp(0, 0)&_MCW_RC)==_RC_NEAR); + + CBrush3D &br = *bscSector.bsc_pbmBrushMip->bm_pbrBrush; + // if should render field brush sector + if (br.br_penEntity->en_RenderType==CEntity::RT_FIELDBRUSH + && !_wrpWorldRenderPrefs.IsFieldBrushesOn()) { + // skip it + bscSector.bsc_ulFlags|=BSCF_INVISIBLE; + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDSECTOR); + return; + } + + // test sector visibility + const INDEX iFrustrumTest = IsSectorVisible( br, bscSector); + if( iFrustrumTest==-1) { + // outside of frustrum - skip it + bscSector.bsc_ulFlags |= BSCF_INVISIBLE; + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDSECTOR); + return; + } else if( iFrustrumTest==0) { + // partially in frustrum - needs clipping + bscSector.bsc_ulFlags |= BSCF_NEEDSCLIPPING; + } else { + // completely in frustrum - doesn't need clipping + bscSector.bsc_ulFlags &= ~BSCF_NEEDSCLIPPING; + } + // mark that sector is visible + bscSector.bsc_ulFlags &= ~BSCF_INVISIBLE; + + // remember current sector + re_pbscCurrent = &bscSector; + re_pbrCurrent = &br; + _sfStats.IncrementCounter(CStatForm::SCI_SECTORS); + + // if projection is perspective + if( br.br_prProjection.IsPerspective()) { + // prepare fog/haze + SetupFogAndHaze(); + } + + // transform all vertices and planes in this sector + PreClipVertices(); + PreClipPlanes(); + + // if polygons should be drawn + if (_wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE + ||re_bRenderingShadows) { + // find which portals should be rendered as portals or as pretenders + FindPretenders(); + // make screen polygons for nondetail polygons in current sector + MakeNonDetailScreenPolygons(); + // clip all polygons to all clip planes + if( bscSector.bsc_ulFlags&BSCF_NEEDSCLIPPING) ClipToAllPlanes( br.br_prProjection); + // project vertices to 2d + PostClipVertices(); + // make final edges for all polygons in current sector + MakeFinalPolygonEdges(); + // add screen edges for all polygons in current sector + AddScreenEdges(); + // make screen polygons for detail polygons in current sector + MakeDetailScreenPolygons(); + } + + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDSECTOR); + + // get the entity the sector is in + CEntity *penSectorEntity = bscSector.bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + // if it has the entity (it is not the background brush) + if (penSectorEntity != NULL) { + // add all other entities near the sector + AddEntitiesInSector(&bscSector); + } +} + +/* + * Initialize list of active edges. + */ +void CRenderer::InitScanEdges(void) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_INITSCANEDGES); + + // empty active lists + re_aaceActiveEdges.PopAll(); re_aaceActiveEdges.SetAllocationStep(256); + re_aaceActiveEdgesTmp.PopAll(); re_aaceActiveEdgesTmp.SetAllocationStep(256); + + // set up left sentinel as left edge of screen and add it to head of active list + re_sedLeftSentinel.sed_xI = FIX16_16(re_fbbClipBox.Min()(1)-SENTINELEDGE_EPSILON); + re_sedLeftSentinel.sed_xIStep = FIX16_16(0); + re_sedLeftSentinel.sed_pspo = &re_spoFarSentinel; + re_aaceActiveEdges.Push() = CActiveEdge(&re_sedLeftSentinel); + + // set up right sentinel as right edge of screen and add it to tail of active list + re_sedRightSentinel.sed_xI = FIX16_16(re_fbbClipBox.Max()(1)+SENTINELEDGE_EPSILON); + re_sedRightSentinel.sed_xIStep = FIX16_16(0); + re_sedRightSentinel.sed_pspo = &re_spoFarSentinel; + re_aaceActiveEdges.Push() = CActiveEdge(&re_sedRightSentinel); + + // set up far sentinel as infinitely far polygon + re_spoFarSentinel.spo_pgOoK.Constant(-999999.0f); // further than infinity + re_spoFarSentinel.spo_iInStack = 1; + re_spoFarSentinel.spo_psedSpanStart = &re_sedLeftSentinel; + re_spoFarSentinel.spo_pbpoBrushPolygon = NULL; + re_spoFarSentinel.spo_ubIllumination = 0; + + // initialize list of spans for far sentinel + re_spoFarSentinel.spo_spoScenePolygon.spo_cColor = re_pwoWorld->wo_colBackground; + re_spoFarSentinel.spo_spoScenePolygon.spo_aptoTextures[0] = NULL; + re_spoFarSentinel.spo_spoScenePolygon.spo_aptoTextures[1] = NULL; + re_spoFarSentinel.spo_spoScenePolygon.spo_aptoTextures[2] = NULL; + re_spoFarSentinel.spo_spoScenePolygon.spo_psmShadowMap = NULL; + re_spoFarSentinel.spo_spoScenePolygon.spo_ulFlags = SPOF_BACKLIGHT; + + // add it to the list of background span polygons in this renderer + re_spoFarSentinel.spo_spoScenePolygon.spo_pspoSucc = re_pspoFirstBackground; + re_pspoFirstBackground = &re_spoFarSentinel.spo_spoScenePolygon; + + // add far sentinel as bottom of surface stack + ASSERT(re_lhSurfaceStack.IsEmpty()); + re_lhSurfaceStack.AddTail(re_spoFarSentinel.spo_lnInStack); + + _pfRenderProfile.StopTimer(CRenderProfile::PTI_INITSCANEDGES); +} + +/* + * Clean up list of active edges. + */ +void CRenderer::EndScanEdges(void) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ENDSCANEDGES); + + // remove far sentinel from surface stack + ASSERT(re_spoFarSentinel.spo_iInStack == 1); + re_spoFarSentinel.spo_lnInStack.Remove(); + re_spoFarSentinel.spo_iInStack = 0; + + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ENDSCANEDGES); +} + +/* + * Add a polygon to surface stack. + */ +BOOL CRenderer::AddPolygonToSurfaceStack(CScreenPolygon &spo) +{ + // increment in-stack counter + spo.spo_iInStack++; + + // if it doesn't have to be added + if (spo.spo_iInStack!=1) { + // return that this is not new top + return FALSE; + } + +#define BIAS (1) +//#define BIAS (0) + + FLOAT fScanI = FLOAT(re_xCurrentScanI)+BIAS; + FLOAT fScanJ = re_fCurrentScanJ;//+re_fMinJ; + + // calculate 1/k for new polygon + CPlanarGradients &pg = spo.spo_pgOoK; + FLOAT fOoK = pg.pg_f00 + pg.pg_fDOverDI*fScanI + pg.pg_fDOverDJ*fScanJ; + + // bias for right edges - fix against generating extra trapezoids + fOoK*=re_fEdgeAdjustK; + + // must not be infinitely far, except if background polygon + //ASSERT(fOneOverK>0.0f || fOneOverK==-9999.0f); + // cannot assert on this, because of +1 bias + + // start at top surface in stack + LISTITER(CScreenPolygon, spo_lnInStack) itspo(re_lhSurfaceStack); + + // if the projection is not perspective + if (!re_prProjection.IsPerspective()) { + // while new polygon is further than polygon in stack + while( + ((fOoK - + itspo->spo_pgOoK.pg_f00 - + itspo->spo_pgOoK.pg_fDOverDI*fScanI - + itspo->spo_pgOoK.pg_fDOverDJ*fScanJ)<0) + && (&*itspo != &re_spoFarSentinel)) { + // move to next polygon in stack + itspo.MoveToNext(); + } + } else { + // while new polygon is further than polygon in stack + FLOAT fDelta = fOoK - + itspo->spo_pgOoK.pg_f00 - + itspo->spo_pgOoK.pg_fDOverDI*fScanI - + itspo->spo_pgOoK.pg_fDOverDJ*fScanJ; + + if (((SLONG &)fDelta) < 0) { + do { + // the polygon in stack must not be far sentinel + ASSERT(&*itspo != &re_spoFarSentinel); + // move to next polygon in stack + itspo.MoveToNext(); + fDelta = fOoK - + itspo->spo_pgOoK.pg_f00 - + itspo->spo_pgOoK.pg_fDOverDI*fScanI - + itspo->spo_pgOoK.pg_fDOverDJ*fScanJ; + } while (((SLONG &)fDelta) < 0); + } + } + + // add the new polygon before the one in stack + itspo.InsertBeforeCurrent(spo.spo_lnInStack); + + // return if this is new top of stack + return spo.spo_lnInStack.IsHead(); +} + +/* + * Remove a polygon from surface stack. + */ +BOOL CRenderer::RemPolygonFromSurfaceStack(CScreenPolygon &spo) +{ + // decrement in-stack counter + spo.spo_iInStack--; + + // if it doesn't have to be removed + if (spo.spo_iInStack!=0) { + // return that this was not top + return FALSE; + } + + // if the polygon is top of stack + if (spo.spo_lnInStack.IsHead()) { + // remove the polygon from stack + spo.spo_lnInStack.Remove(); + // return that this was top + return TRUE; + + // if the polygon is not top of stack + } else { + // remove the polygon from stack + spo.spo_lnInStack.Remove(); + // return that this was not top + return FALSE; + } +} + +/* + * Swap two polygons in surface stack. + */ +BOOL CRenderer::SwapPolygonsInSurfaceStack(CScreenPolygon &spoOld, CScreenPolygon &spoNew) +{ + // !!!!! fix the problems with surfaces beeing multiple times added + // to the stack before reenabling this feature! + + ASSERT(FALSE); + // decrement/increment in-stack counters + spoOld.spo_iInStack--; + spoNew.spo_iInStack++; + + ASSERT(spoOld.spo_iInStack==0); + ASSERT(spoNew.spo_iInStack==1); + + // if the left polygon is top of stack + if (spoOld.spo_lnInStack.IsHead()) { + // swap them + CListNode &lnBefore = spoOld.spo_lnInStack.IterationPred(); + spoOld.spo_lnInStack.Remove(); + lnBefore.IterationInsertAfter(spoNew.spo_lnInStack); + return TRUE; + + // if the polygon is not top of stack + } else { + // swap them + CListNode &lnBefore = spoOld.spo_lnInStack.IterationPred(); + spoOld.spo_lnInStack.Remove(); + lnBefore.IterationInsertAfter(spoNew.spo_lnInStack); + // return that this was not top + return FALSE; + } +} + +/* + * Remove all polygons from surface stack. + */ +void CRenderer::FlushSurfaceStack(void) +{ + // while there is some polygon above far sentinel in surface stack + CScreenPolygon *pspoTop; + while ((pspoTop = LIST_HEAD(re_lhSurfaceStack, CScreenPolygon, spo_lnInStack)) + != &re_spoFarSentinel) { + + // it must be linked in stack +#if 0 + if (pspoTop->spo_iInStack<=0) { + _pSCape->DebugSave(); + FatalError("Surface stack bug encountered!\nDebug game saved!"); + } + ASSERT(pspoTop->spo_iInStack>0); +#endif + + // remove it from stack + pspoTop->spo_lnInStack.Remove(); + pspoTop->spo_iInStack = 0; + } +} + +/* + * Scan list of active edges into spans. + */ +CScreenPolygon *CRenderer::ScanOneLine(void) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_SCANONELINE); + IFDEBUG(FIX16_16 xCurrentI = FIX16_16(-10)); + + // reinit far sentinel + re_spoFarSentinel.spo_iInStack = 1; + re_spoFarSentinel.spo_psedSpanStart = &re_sedLeftSentinel; + + // clear list of spans for current line + re_aspSpans.PopAll(); + + // if left and right sentinels are sorted wrong + if (re_aaceActiveEdges[0].ace_psedEdge!=&re_sedLeftSentinel + ||re_aaceActiveEdges[re_aaceActiveEdges.Count()-1].ace_psedEdge!=&re_sedRightSentinel) { + // skip entire line (this patches some extremely rare crash situations) + _pfRenderProfile.StopTimer(CRenderProfile::PTI_SCANONELINE); + return NULL; + } + + // for all edges in the line + CActiveEdge *pace = &re_aaceActiveEdges[1]; + CActiveEdge *paceEnd = &re_aaceActiveEdges[re_aaceActiveEdges.Count()-1]; + while (paceace_psedEdge; + ASSERT(&sed!=&re_sedLeftSentinel); + ASSERT(&sed!=&re_sedRightSentinel); + // set up current I coordinate on the scan line + re_xCurrentScanI = sed.sed_xI = pace->ace_xI; + + // check that edges are sorted ok + + ASSERT(xCurrentI <= sed.sed_xI); + + // count edge transitions + _pfRenderProfile.IncrementCounter(CRenderProfile::PCI_EDGETRANSITIONS); + _sfStats.IncrementCounter(CStatForm::SCI_EDGETRANSITIONS); + + // if this edge has active polygon + if (sed.sed_pspo!= NULL && sed.sed_pspo->spo_bActive) { + CScreenPolygon &spo = *sed.sed_pspo; + // if it is right edge of the polygon + if (sed.sed_ldtDirection==LDT_ASCENDING) { + + // remove the left polygon from stack + BOOL bWasTop = RemPolygonFromSurfaceStack(spo); + + // if that was top polygon in surface stack + if (bWasTop) { + // if it is portal + if (spo.IsPortal() && + (re_ubLightIllumination==0||re_ubLightIllumination!=spo.spo_ubIllumination)) { + // fail scanning and add that portal + _pfRenderProfile.StopTimer(CRenderProfile::PTI_SCANONELINE); + return &spo; + } + // generate a span for it + MakeSpan(spo, spo.spo_psedSpanStart, &sed); + + // mark that span of new top starts here + CScreenPolygon *pspoNewTop = + LIST_HEAD(re_lhSurfaceStack, CScreenPolygon, spo_lnInStack); + pspoNewTop->spo_psedSpanStart = &sed; + } + + // if it is left edge of the polygon + } else { + ASSERT(sed.sed_ldtDirection==LDT_DESCENDING); + + // add the right polygon to stack + BOOL bIsTop = AddPolygonToSurfaceStack(spo); + + // if it is the new top of surface stack + if (bIsTop) { + // get the old top + CScreenPolygon &spoOldTop = *LIST_SUCC(spo, CScreenPolygon, spo_lnInStack); + // if it is portal + if (spoOldTop.IsPortal() && + (re_ubLightIllumination==0||re_ubLightIllumination!=spoOldTop.spo_ubIllumination)) { + // if its span has at least one pixel in length + if ( PIXCoord(re_xCurrentScanI)-PIXCoord(spoOldTop.spo_psedSpanStart->sed_xI)>0) { + // fail scanning and add that portal + _pfRenderProfile.StopTimer(CRenderProfile::PTI_SCANONELINE); + return &spoOldTop; + } + // if it is not portal + } else { + // generate span for old top + MakeSpan(spoOldTop, spoOldTop.spo_psedSpanStart, &sed); + } + + // mark that span of new polygon starts here + spo.spo_psedSpanStart = &sed; + } + } + + IFDEBUG(xCurrentI = pace->ace_xI); + // if this edge has no active polygon + } else { + // mark it for removal + sed.sed_xI.slHolder = ACE_REMOVED; + } + + pace++; + } + + // NOTE: In some rare and extreme situations (usually when casting shadows) + // the stack might not be empty after scanning - this code fixes that. + + // if surface stack contains something else except background + CScreenPolygon *pspoTop = LIST_HEAD(re_lhSurfaceStack, CScreenPolygon, spo_lnInStack); + if (&re_spoFarSentinel != pspoTop) { + // ASSERTALWAYS("Bug in ASER: Surface stack not empty!"); + CScreenPolygon &spo = *pspoTop; + // generate span of the top polygon to the right border + if (!(spo.IsPortal() + && (re_ubLightIllumination==0 || re_ubLightIllumination!=spo.spo_ubIllumination))) { + MakeSpan(spo, spo.spo_psedSpanStart, &re_sedRightSentinel); + } + // remove all left-over polygons from stack + do { + BOOL bWasTop = RemPolygonFromSurfaceStack(*pspoTop); + pspoTop = LIST_HEAD(re_lhSurfaceStack, CScreenPolygon, spo_lnInStack); + } while (&re_spoFarSentinel != pspoTop); + // mark start of background span at right border + re_spoFarSentinel.spo_psedSpanStart = &re_sedRightSentinel; + } + + // generate span for far sentinel + MakeSpan(re_spoFarSentinel, re_spoFarSentinel.spo_psedSpanStart, &re_sedRightSentinel); + + // return that no portal was encountered + _pfRenderProfile.StopTimer(CRenderProfile::PTI_SCANONELINE); + return NULL; +} + +/* + * Rasterize edges into spans. + */ +void CRenderer::ScanEdges(void) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_SCANEDGES); + // set up the list of active edges, surface stack and the sentinels + InitScanEdges(); + + // mark that first line is never coherent with previous one + re_bCoherentScanLine = 0; + + // for each scan line, top to bottom + for (re_iCurrentScan = 0; re_iCurrentScan0) { + // increment counter of coherent scan lines + _pfRenderProfile.IncrementCounter(CRenderProfile::PCI_COHERENTSCANLINES); + // just copy I coordinates from active list to edge data + CopyActiveCoordinates(); + + // if scan-line is not coherent with the last one + } else/**/ { + + // scan list of active edges into spans + pspoPortal = ScanOneLine(); + + // while portal is encountered during scanning + while (pspoPortal != NULL) { + // increment counter of portal retries + _pfRenderProfile.IncrementCounter(CRenderProfile::PCI_SCANLINEPORTALRETRIES); + + // remove all polygons from surface stack + FlushSurfaceStack(); + + // add sectors near the encountered portal to rendering + PassPortal(*pspoPortal); + // add all newly added edges that start on this scan line to active list + AddAddListToActiveList(re_iCurrentScan); + + // rescan list of active edges into spans again + pspoPortal = ScanOneLine(); + } + } + + // set scan-line coherence marker + re_bCoherentScanLine++; + + // surface stack must contain only background + ASSERT(&re_spoFarSentinel == LIST_HEAD(re_lhSurfaceStack, CScreenPolygon, spo_lnInStack) + && &re_spoFarSentinel == LIST_TAIL(re_lhSurfaceStack, CScreenPolygon, spo_lnInStack)); + + // add spans in this line to the scene + AddSpansToScene(); + + // uncomment this for extreme checking of surface stack management -- very slow + #if 0 + // all surfaces must have in-stack counter of zero + FOREACHINDYNAMICARRAY(re_aspoScreenPolygons, CScreenPolygon, itspo) { + CScreenPolygon &spo = itspo.Current(); + ASSERT(spo.spo_iInStack == 0); + } + #endif + + // remove all edges that stop on this scan from active list and from other lists. + RemRemoveListFromActiveList(re_apsedRemoveFirst[re_iCurrentScan]); + + // step all remaining edges by one scan line and resort the active list + StepAndResortActiveList(); + + } + + // clean up the list of active edges, surface stack and the sentinels + + EndScanEdges(); + _pfRenderProfile.StopTimer(CRenderProfile::PTI_SCANEDGES); +} diff --git a/Sources/Engine/Rendering/RendClip.cpp b/Sources/Engine/Rendering/RendClip.cpp new file mode 100644 index 0000000..79c8fe6 --- /dev/null +++ b/Sources/Engine/Rendering/RendClip.cpp @@ -0,0 +1,518 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +///////////////////////////////////////////////////////////////////// +// Clipping functions + +// check if a polygon is to be visible +__forceinline ULONG CRenderer::GetPolygonVisibility(const CBrushPolygon &bpo) +{ + // get transformed polygon's plane + CWorkingPlane *pwplPolygonPlane = bpo.bpo_pbplPlane->bpl_pwplWorking; + CWorkingPlane wplReverse; + BOOL bInvertPolygon = FALSE; + + // if the polygon should be inverted or double sided + if((re_bRenderingShadows + &&!re_bDirectionalShadows + &&re_ubLightIllumination!=0 + &&bpo.bpo_bppProperties.bpp_ubIlluminationType==re_ubLightIllumination) + || (re_pbrCurrent->br_pfsFieldSettings!=NULL && !pwplPolygonPlane->wpl_bVisible) + ) { + bInvertPolygon = TRUE; + } + + if (bInvertPolygon) { + // make temporary inverted polygon plane + pwplPolygonPlane = &wplReverse; + pwplPolygonPlane->wpl_plView = -bpo.bpo_pbplPlane->bpl_pwplWorking->wpl_plView; + pwplPolygonPlane->wpl_bVisible = + re_pbrCurrent->br_prProjection->IsViewerPlaneVisible(pwplPolygonPlane->wpl_plView); + } + + // if the poly is double-sided and detail + if( !re_bRenderingShadows && (bpo.bpo_ulFlags&BPOF_DOUBLESIDED) && (bpo.bpo_ulFlags&BPOF_DETAILPOLYGON)) { + // it's definately visible + return PDF_POLYGONVISIBLE; + } + + // if the plane is invisible + if (!pwplPolygonPlane->wpl_bVisible) { + // polygon is invisible + return 0; + } + + // if the polygon is invisible + if ((bpo.bpo_ulFlags&BPOF_INVISIBLE) + ||(re_bRenderingShadows && (bpo.bpo_ulFlags&BPOF_DOESNOTCASTSHADOW))) { + // skip it + return 0; + } + + ULONG ulDirection = PDF_POLYGONVISIBLE; + BOOL bProjectionInverted = re_prProjection->pr_bInverted; + if (bProjectionInverted && !bInvertPolygon) { + ulDirection |= PDF_FLIPEDGESPRE; + } else if (!bProjectionInverted && bInvertPolygon){ + ulDirection |= PDF_FLIPEDGESPOST; + } + + // else, polygon is visible + return ulDirection; +} + + +// check if polygon is outside viewfrustum +__forceinline BOOL CRenderer::IsPolygonCulled(const CBrushPolygon &bpo) +{ + CBrushSector &bsc = *bpo.bpo_pbscSector; + // setup initial mask + ULONG ulMask = 0xFFFFFFFF; + + // for each vertex + INDEX ctVtx = bpo.bpo_apbvxTriangleVertices.Count(); + {for(INDEX i=0; ibsc_ispo0 = re_aspoScreenPolygons.Count(); + // for all polygons in sector + FOREACHINSTATICARRAY(re_pbscCurrent->bsc_abpoPolygons, CBrushPolygon, itpo) { + CBrushPolygon &bpo = *itpo; + // initially not rendered as portal + bpo.bpo_ulFlags&=~BPOF_RENDERASPORTAL; + // if it is portal, + if (bpo.bpo_ulFlags&BPOF_PORTAL) { + // initially rendered as portal + bpo.bpo_ulFlags|=BPOF_RENDERASPORTAL; + + // if could be a pretender + if (bpo.bpo_bppProperties.bpp_uwPretenderDistance!=0) { + // get distance at which it is a pretender + FLOAT fPretenderDistance = bpo.bpo_bppProperties.bpp_uwPretenderDistance; + + // for each vertex in the polygon + INDEX ctVtx = bpo.bpo_apbvxTriangleVertices.Count(); + CBrushSector &bsc = *bpo.bpo_pbscSector; + {for(INDEX i=0; ibsc_ispo0 = re_aspoScreenPolygons.Count(); + // detail polygons are not skipped if rendering shadows + const ULONG ulDetailMask = re_bRenderingShadows ? 0 : BPOF_DETAILPOLYGON; + + // for all polygons in sector + FOREACHINSTATICARRAY(re_pbscCurrent->bsc_abpoPolygons, CBrushPolygon, itpo) { + CBrushPolygon &bpo = *itpo; + + // if polygon does not contribute to the visibility determination + if ( (bpo.bpo_ulFlags&ulDetailMask) + &&!(bpo.bpo_ulFlags&BPOF_RENDERASPORTAL)) { + // skip it + continue; + } + + // no screen polygon by default + bpo.bpo_pspoScreenPolygon = NULL; + + // skip if the polygon is not visible + ASSERT( !IsPolygonCulled(bpo)); // cannot be culled yet! + const ULONG ulVisible = GetPolygonVisibility(bpo); + if( ulVisible==0) continue; + + _sfStats.IncrementCounter(CStatForm::SCI_POLYGONS); + _pfRenderProfile.IncrementCounter(CRenderProfile::PCI_NONDETAILPOLYGONS); + + // make screen polygon for the polygon + CScreenPolygon &spo = *MakeScreenPolygon(bpo); + + // add its edges + MakeInitialPolygonEdges(bpo, spo, ulVisible); + } + + // remember number of polygons in sector + re_pbscCurrent->bsc_ctspo = re_aspoScreenPolygons.Count()-re_pbscCurrent->bsc_ispo0; + + _pfRenderProfile.StopTimer(CRenderProfile::PTI_MAKENONDETAILSCREENPOLYGONS); +} + + +// make screen polygons for detail polygons in current sector +void CRenderer::MakeDetailScreenPolygons(void) +{ + // if rendering shadows or not rendering detail polygons + if (re_bRenderingShadows + ||!wld_bRenderDetailPolygons) { + // do nothing + return; + } + + _pfRenderProfile.StartTimer(CRenderProfile::PTI_MAKEDETAILSCREENPOLYGONS); + // for all polygons in sector + FOREACHINSTATICARRAY(re_pbscCurrent->bsc_abpoPolygons, CBrushPolygon, itpo) { + CBrushPolygon &bpo = *itpo; + + // if polygon is not detail + if (!(bpo.bpo_ulFlags&BPOF_DETAILPOLYGON) + || (bpo.bpo_ulFlags&BPOF_RENDERASPORTAL)) { + // skip it + continue; + } + + // no screen polygon by default + bpo.bpo_pspoScreenPolygon = NULL; + + // skip if the polygon is not visible + if( GetPolygonVisibility(bpo)==0) continue; + // skip if outside the frustum + if( (re_pbscCurrent->bsc_ulFlags&BSCF_NEEDSCLIPPING) && IsPolygonCulled(bpo)) continue; + + _sfStats.IncrementCounter(CStatForm::SCI_DETAILPOLYGONS); + _pfRenderProfile.IncrementCounter(CRenderProfile::PCI_DETAILPOLYGONS); + + // make screen polygon for the polygon + CScreenPolygon &spo = *MakeScreenPolygon(bpo); + + // if it is portal + if (spo.IsPortal()) { + // pass it immediately + PassPortal(spo); + } else { + // add polygon to scene polygons for rendering + AddPolygonToScene(&spo); + } + } + _pfRenderProfile.StopTimer(CRenderProfile::PTI_MAKEDETAILSCREENPOLYGONS); +} + +// make initial edges for a polygon +void CRenderer::MakeInitialPolygonEdges(CBrushPolygon &bpo, CScreenPolygon &spo, BOOL ulDirection) +{ + // get number of edges + INDEX ctEdges = bpo.bpo_abpePolygonEdges.Count(); + spo.spo_ubDirectionFlags = ulDirection&PDF_FLIPEDGESPOST; + BOOL bInvert = (ulDirection&PDF_FLIPEDGESPRE)!=0; + + // remember edge vertex start and count + spo.spo_ctEdgeVx = ctEdges*2; + spo.spo_iEdgeVx0 = re_aiEdgeVxClipSrc.Count(); + + // create edge vertices + INDEX *ai = re_aiEdgeVxClipSrc.Push(ctEdges*2); + + // for each edge + for (INDEX iEdge=0; iEdgebed_pwedWorking; + if (bpe.bpe_bReverse^bInvert) { + ai[iEdge*2+0] = wed.wed_iwvx1+re_iViewVx0; + ai[iEdge*2+1] = wed.wed_iwvx0+re_iViewVx0; + } else { + ai[iEdge*2+0] = wed.wed_iwvx0+re_iViewVx0; + ai[iEdge*2+1] = wed.wed_iwvx1+re_iViewVx0; + } + } +} + +// make final edges for all polygons in current sector +void CRenderer::MakeFinalPolygonEdges(void) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_MAKEFINALPOLYGONEDGES); + // for each polygon + INDEX ispo0 = re_pbscCurrent->bsc_ispo0; + INDEX ispoTop = re_pbscCurrent->bsc_ispo0+re_pbscCurrent->bsc_ctspo; + for(INDEX ispo = ispo0; ispobsc_ulFlags&BSCF_NEEDSCLIPPING); + if( !MakeOutcodes()) return; + + // for each polygon + INDEX ispo0 = re_pbscCurrent->bsc_ispo0; + INDEX ispoTop = re_pbscCurrent->bsc_ispo0+re_pbscCurrent->bsc_ctspo; + for(INDEX ispo = ispo0; ispopr_plClipU; pl.Offset(-0.001f); ClipToOnePlane(pl); + pl = pr->pr_plClipD; pl.Offset(-0.001f); ClipToOnePlane(pl); + pl = pr->pr_plClipL; pl.Offset(-0.001f); ClipToOnePlane(pl); + pl = pr->pr_plClipR; pl.Offset(-0.001f); ClipToOnePlane(pl); + // clip to near clip plane + ClipToOnePlane(FLOATplane3D(FLOAT3D(0,0,-1), pr->pr_NearClipDistance)); + // clip to far clip plane if existing + if (pr->pr_FarClipDistance>0) { + ClipToOnePlane(FLOATplane3D(FLOAT3D(0,0,1), -pr->pr_FarClipDistance)); + } + + // if projection is mirrored or warped + if (pr->pr_bMirror||pr->pr_bWarp) { + // clip to mirror plane + ClipToOnePlane(pr->pr_plMirrorView); + } + _pfRenderProfile.StopTimer(CRenderProfile::PTI_CLIPTOALLPLANES); +} + +// make outcodes for current clip plane for all active vertices +__forceinline BOOL CRenderer::MakeOutcodes(void) +{ + SLONG slMask = 0; + // for each active view vertex + INDEX iVxTop = re_avvxViewVertices.Count(); + for(INDEX ivx = re_iViewVx0; ivx>1)|ulOutCode; + // add to mask + slMask|=ulOutCode; + } + // if any was negative, return true -- needs clipping + return slMask; +} + +// clip one polygon to current clip plane +void CRenderer::ClipOnePolygon(CScreenPolygon &spo) +{ +// +// NOTE: There is one ugly problem with this loop. +// I don't know any better way to fix it, so I have commented it. +// If the vertex references (vvx0 and vvx1) are taken _before_ pushing the vvxNew, +// it can cause access violation, because pushing can move array in memory. +// Therefore, it is important to take the references _after_ the Push() call. + + INDEX iEdgeVx0New = re_aiEdgeVxClipDst.Count(); + + // for each edge + INDEX ivxTop = spo.spo_iEdgeVx0+spo.spo_ctEdgeVx; + for(INDEX ivx=spo.spo_iEdgeVx0; ivx0) { + // generate clip edges + GenerateClipEdges(spo); + } + + // remember new edge vertex positions + spo.spo_ctEdgeVx = re_aiEdgeVxClipDst.Count()-iEdgeVx0New; + spo.spo_iEdgeVx0 = iEdgeVx0New; +} + +/* + * Compare two vertices for quick-sort. + */ +static UBYTE *_aVertices=NULL; +static int qsort_CompareVertices_plus( const void *ppvVertex0, const void *ppvVertex1) +{ + INDEX ivx0 = *(const INDEX*)ppvVertex0; + INDEX ivx1 = *(const INDEX*)ppvVertex1; + FLOAT f0 = *(FLOAT*)(_aVertices+ivx0*sizeof(CViewVertex)); + FLOAT f1 = *(FLOAT*)(_aVertices+ivx1*sizeof(CViewVertex)); + if (f0f1) return +1; + else return 0; +} +static int qsort_CompareVertices_minus( const void *ppvVertex0, const void *ppvVertex1) +{ + INDEX ivx0 = *(const INDEX*)ppvVertex0; + INDEX ivx1 = *(const INDEX*)ppvVertex1; + FLOAT f0 = *(FLOAT*)(_aVertices+ivx0*sizeof(CViewVertex)); + FLOAT f1 = *(FLOAT*)(_aVertices+ivx1*sizeof(CViewVertex)); + if (f0f1) return -1; + else return 0; +} + +// generate clip edges for one polygon +void CRenderer::GenerateClipEdges(CScreenPolygon &spo) +{ + ASSERT(re_aiClipBuffer.Count()>0); + + FLOATplane3D &plPolygonPlane = spo.spo_pbpoBrushPolygon->bpo_pbplPlane->bpl_pwplWorking->wpl_plView; + // calculate the clip buffer direction in 3d as: + // clip_normal_vector x polygon_normal_vector + FLOAT3D vClipDir = ((FLOAT3D &)re_plClip)*((FLOAT3D &)plPolygonPlane); + + // get max axis + INDEX iMaxAxis = 1; + FLOAT fMaxAbs = Abs(vClipDir(1)); + if (Abs(vClipDir(2))>fMaxAbs) { + iMaxAxis = 2; + fMaxAbs = Abs(vClipDir(2)); + } + if (Abs(vClipDir(3))>fMaxAbs) { + iMaxAxis = 3; + fMaxAbs = Abs(vClipDir(3)); + } + + _aVertices = (UBYTE*) &re_avvxViewVertices[0].vvx_vView(iMaxAxis); + + INDEX *aIndices = &re_aiClipBuffer[0]; + INDEX ctIndices = re_aiClipBuffer.Count(); + + // there must be even number of vertices in the buffer + ASSERT(ctIndices%2 == 0); + + // if the sign of axis is negative + if (vClipDir(iMaxAxis)<0) { + // sort them inversely + qsort(aIndices, ctIndices, sizeof(INDEX), qsort_CompareVertices_minus); + // if it is negative + } else { + // sort them normally + qsort(aIndices, ctIndices, sizeof(INDEX), qsort_CompareVertices_plus); + } + + // for each two vertices + for(INDEX iClippedVertex=0; iClippedVertex0.01) { + vArrowLen = vDelta/fDelta*FLOAT(10.0); + vArrowWidth = vDelta/fDelta*FLOAT(2.0); + } else { + vArrowWidth = vArrowLen = FLOAT2D(0.0f, 0.0f); + } +// FLOAT3D vArrowLen = vDelta/5.0f; +// FLOAT3D vArrowWidth = vDelta/30.0f; + Swap(vArrowWidth(1), vArrowWidth(2)); + //vArrowWidth(2) *= -1.0f; + + DrawArrowLine(dp, vPoint0, vPoint1, color, ulLineType); + DrawArrowLine(dp, vPoint1-vArrowLen+vArrowWidth, vPoint1, color, ulLineType); + DrawArrowLine(dp, vPoint1-vArrowLen-vArrowWidth, vPoint1, color, ulLineType); + //DrawArrowLine(dp, vPoint0+vArrowWidth, vPoint0-vArrowWidth, color, ulLineType); +} + + +/* + * Determine color to use for coloring vertices. + */ +inline COLOR CRenderer::ColorForVertices(COLOR colorPolygon, COLOR colorSector) +{ + // check vertices fill type + switch(_wrpWorldRenderPrefs.wrp_ftVertices) { + // if it is fixed ink + case CWorldRenderPrefs::FT_INKCOLOR: + // use the vertex ink + return _wrpWorldRenderPrefs.wrp_colVertices; + break; + // if it is polygon + case CWorldRenderPrefs::FT_POLYGONCOLOR: + // use the polygon color + return colorPolygon; + break; + // if it is sector + case CWorldRenderPrefs::FT_SECTORCOLOR: + // use the sector color + return colorSector; + break; + // if it is none + case CWorldRenderPrefs::FT_NONE: + // return any color, doesn't matter + return C_BLACK; + break; + // in any other way + default: + // error + ASSERTALWAYS("Invalid fill type for vertices"); + return C_BLACK; + }; +} + +/* + * Determine color to use for coloring edges. + */ +inline COLOR CRenderer::ColorForEdges(COLOR colorPolygon, COLOR colorSector) +{ + // check edges fill type + switch(_wrpWorldRenderPrefs.wrp_ftEdges) { + // if it is fixed ink + case CWorldRenderPrefs::FT_INKCOLOR: + // use the edge ink + return _wrpWorldRenderPrefs.wrp_colEdges; + break; + // if it is polygon + case CWorldRenderPrefs::FT_POLYGONCOLOR: + // use the polygon color + return colorPolygon; + break; + // if it is sector + case CWorldRenderPrefs::FT_SECTORCOLOR: + // use the sector color + return colorSector; + break; + // if it is none + case CWorldRenderPrefs::FT_NONE: + // return any color, doesn't matter + return C_BLACK; + break; + // in any other way + default: + // error + ASSERTALWAYS("Invalid fill type for edges"); + return C_BLACK; + }; +} + +/* + * Determine color to use for coloring polygons. + */ +inline COLOR CRenderer::ColorForPolygons(COLOR colorPolygon, COLOR colorSector) +{ + // check polygons fill type + switch(_wrpWorldRenderPrefs.wrp_ftPolygons) { + // if it is fixed ink + case CWorldRenderPrefs::FT_INKCOLOR: + // use the polygon ink + return _wrpWorldRenderPrefs.wrp_colPolygons; + break; + // if it is sector + case CWorldRenderPrefs::FT_SECTORCOLOR: + // use the sector color + return colorSector; + break; + // if it is polygon + case CWorldRenderPrefs::FT_POLYGONCOLOR: + // or in any other way + default: + // use the polygon color + return colorPolygon; + break; + }; +} + +/* + * Check if a polygon is selected. + */ +inline BOOL PolygonIsSelected(CBrushPolygon &bpo, + CBrush3D &br, + CBrushSector &bsc) +{ + // if any selection drawing is active + if (_wrpWorldRenderPrefs.GetSelectionType() != CWorldRenderPrefs::ST_NONE) { + // if polygon selection drawing is active and this polygon is selected, + if ((_wrpWorldRenderPrefs.GetSelectionType() == CWorldRenderPrefs::ST_POLYGONS + && bpo.IsSelected(BPOF_SELECTED)) + // or sector selection drawing is active and this polygon's sector is selected, + ||(_wrpWorldRenderPrefs.GetSelectionType() == CWorldRenderPrefs::ST_SECTORS + && bsc.IsSelected(BSCF_SELECTED)) + // or entity selection drawing is active and this polygon's brush is selected + ||(_wrpWorldRenderPrefs.GetSelectionType() == CWorldRenderPrefs::ST_ENTITIES + && (br.br_ulFlags&BRF_DRAWSELECTED)) + ) { + return TRUE; + } + } + return FALSE; +} + +void CRenderer::ProjectClipAndDrawArrow( + const FLOAT3D &v0, const FLOAT3D &v1, COLOR colColor) +{ + // get transformed end vertices + FLOAT3D tv0, tv1; + re_prProjection->PreClip(v0, tv0); + re_prProjection->PreClip(v1, tv1); + + // clip the edge line + FLOAT3D vClipped0 = tv0; + FLOAT3D vClipped1 = tv1; + ULONG ulClipFlags = re_prProjection->ClipLine(vClipped0, vClipped1); + // if the edge remains after clipping to front plane + if (ulClipFlags != LCF_EDGEREMOVED) { + // project the vertices + FLOAT3D v3d0, v3d1; + re_prProjection->PostClip(vClipped0, v3d0); + re_prProjection->PostClip(vClipped1, v3d1); + // make 2d vertices + FLOAT2D v2d0, v2d1; + v2d0(1) = v3d0(1); v2d0(2) = v3d0(2); + v2d1(1) = v3d1(1); v2d1(2) = v3d1(2); + + // draw arrow-headed line between vertices + DrawArrow(*re_pdpDrawPort, (PIX)v2d0(1), (PIX)v2d0(2), + (PIX)v2d1(1), (PIX)v2d1(2), colColor, _FULL_); + } +} + +/* + * Render target lines for each drawn entity that has some targets. + */ +void CRenderer::RenderEntityTargets(void) +{ + // for each drawn entity + FOREACHINDYNAMICCONTAINER(re_cenDrawn, CEntity, iten) { + CEntity &enSource = *iten; + + // if the entity has parent + if (enSource.en_penParent!=NULL) { + // draw the arrow from entity to its parent + ProjectClipAndDrawArrow( + enSource.GetLerpedPlacement().pl_PositionVector, + enSource.en_penParent->GetLerpedPlacement().pl_PositionVector, + C_dBLUE|CT_OPAQUE); + } + + // for all classes in hierarchy of this entity + for(CDLLEntityClass *pdecDLLClass = enSource.en_pecClass->ec_pdecDLLClass; + pdecDLLClass!=NULL; + pdecDLLClass = pdecDLLClass->dec_pdecBase) { + // for all properties + for(INDEX iProperty=0; iPropertydec_ctProperties; iProperty++) { + CEntityProperty &epProperty = pdecDLLClass->dec_aepProperties[iProperty]; + // if the property is not entity pointer + if( (epProperty.ep_eptType!=CEntityProperty::EPT_ENTITYPTR)|| + (strlen(epProperty.ep_strName)==0) ){ + // skip it + continue; + } + // get the target + CEntity *penTarget = ENTITYPROPERTY(&enSource, epProperty.ep_slOffset, CEntityPointer); + // if there is no target + if (penTarget==NULL) { + // skip it + continue; + } + + // draw the arrow from entity to its target + ProjectClipAndDrawArrow( + enSource.GetLerpedPlacement().pl_PositionVector, + penTarget->GetLerpedPlacement().pl_PositionVector, + epProperty.ep_colColor); + } + } + } +} + +extern CFontData *_pfdConsoleFont; +void CRenderer::RenderEntityNames(void) +{ + // for each of models that were kept for delayed rendering + for( INDEX iModel=0; iModelGetCurrentFrameBBox(boxModel); + if(en.en_pciCollisionInfo!=NULL) { + // get its collision box + INDEX iCollision = en.GetCollisionBoxIndex(); + FLOAT3D vMin = pmoModelObject->GetCollisionBoxMin(iCollision); + FLOAT3D vMax = pmoModelObject->GetCollisionBoxMax(iCollision); + // extend the box by the collision box + boxModel|=FLOATaabbox3D(vMin, vMax); + } + // set position of marker at top of the model and it size to be proportional to the model + boxModel.StretchByVector(pmoModelObject->mo_Stretch); + } else if (en.GetRenderType()==CEntity::RT_SKAMODEL || en.GetRenderType()==CEntity::RT_SKAEDITORMODEL) { + pmiModelInstance = en.GetModelInstance(); + pmiModelInstance->GetAllFramesBBox(boxModel); + if(en.en_pciCollisionInfo!=NULL) { + // get its collision box + FLOATaabbox3D box; + pmiModelInstance->GetCurrentColisionBox(box); + // extend the box by the collision box + boxModel|=box; + } + boxModel.StretchByVector(pmiModelInstance->mi_vStretch); + } else { + continue; + } + + FLOAT fSize = boxModel.Size().Length()*0.3f; + _wrpWorldRenderPrefs.wrp_pmoSelectedEntity->mo_Stretch = FLOAT3D( fSize, fSize, fSize); + CPlacement3D plSelection = en.GetLerpedPlacement(); + plSelection.Translate_OwnSystem( FLOAT3D(0.0f, boxModel.Max()(2), 0.0f)); + FLOAT3D vOrigin=plSelection.pl_PositionVector; + FLOAT3D vProjected=FLOAT3D(0,0,0); + re_prProjection->ProjectCoordinate( vOrigin, vProjected); + if( vProjected(3)>0.0f) continue; + FLOAT fSizeFactor=1.0f+fSize; + FLOAT fRatio=Clamp( -vProjected(3)/fSizeFactor, 0.0f, 25.0f); + FLOAT fPower=CalculateRatio(fRatio, 0, 25.0f, 0, 0.25f); + if( fPower==0) continue; + + PIX pixH=re_pdpDrawPort->GetHeight(); + re_pdpDrawPort->SetFont( _pfdConsoleFont); + UBYTE ubAlpha=UBYTE(fPower*255.0f); + re_pdpDrawPort->PutTextC( strName, vProjected(1), pixH-vProjected(2), C_RED|ubAlpha); + } +} diff --git a/Sources/Engine/Rendering/Render.cpp b/Sources/Engine/Rendering/Render.cpp new file mode 100644 index 0000000..f952cae --- /dev/null +++ b/Sources/Engine/Rendering/Render.cpp @@ -0,0 +1,1022 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +extern BOOL _bSomeDarkExists; +extern INDEX d3d_bAlternateDepthReads; + +// general coordinate stack referenced by the scene polygons +extern CStaticStackArray _avtxScene; + + +//#pragma optimize ("gt", on) +#pragma inline_depth(255) +#pragma inline_recursion(on) + +#ifndef NDEBUG +//#define ASER_EXTREME_CHECKING 1 +#endif + +// the renderer structures used in rendering +#define MAX_RENDERERS 2 +static CRenderer _areRenderers[MAX_RENDERERS]; +static BOOL _bMirrorDrawn = FALSE; + +extern INDEX wld_bAlwaysAddAll; +extern INDEX wld_bRenderEmptyBrushes; +extern INDEX wld_bRenderDetailPolygons; +extern INDEX gfx_bRenderParticles; +extern INDEX gfx_bRenderModels; +extern INDEX gfx_bRenderFog; +extern INDEX gfx_bRenderPredicted; +extern INDEX gfx_iLensFlareQuality; +extern BOOL _bMultiPlayer; + +// variables for selection on rendering +extern CBrushVertexSelection *_pselbvxtSelectOnRender = NULL; +extern CStaticStackArray *_pavpixSelectLasso = NULL; +extern CEntitySelection *_pselenSelectOnRender = NULL; +extern PIX2D _vpixSelectNearPoint = PIX2D(0,0); +extern BOOL _bSelectAlternative = FALSE; +extern PIX _pixDeltaAroundVertex = 10; + +// shading info for viewer of last rendered view +FLOAT3D _vViewerLightDirection; +COLOR _colViewerLight; +COLOR _colViewerAmbient; + + +// handy statistic helper routines + +static enum CStatForm::StatTimerIndex _stiLastStatsMode = (enum CStatForm::StatTimerIndex)-1; + +void StopStatsMode(void) +{ + ASSERT( (INDEX)_stiLastStatsMode != -1); + if( _stiLastStatsMode>=0) _sfStats.StopTimer(_stiLastStatsMode); + _stiLastStatsMode = (enum CStatForm::StatTimerIndex)-1; +} + +void StartStatsMode( enum CStatForm::StatTimerIndex sti) +{ + ASSERT( (INDEX)sti != -1); + ASSERT( (INDEX)_stiLastStatsMode == -1); + if( sti>=0) _sfStats.StartTimer(sti); + _stiLastStatsMode = sti; +} + +void ChangeStatsMode( enum CStatForm::StatTimerIndex sti) +{ + StopStatsMode(); + StartStatsMode(sti); +} + + +// screen edges, polygons and trapezoids used in rasterizing +CDynamicStackArray CRenderer::re_aadeAddEdges; +CDynamicStackArray CRenderer::re_asedScreenEdges; +// spans for current scan line +CDynamicStackArray CRenderer::re_aspSpans; + +// vertices clipped to current clip plane +CStaticStackArray CRenderer::re_aiClipBuffer; +// buffers for edges of polygons +CStaticStackArray CRenderer::re_aiEdgeVxClipSrc; +CStaticStackArray CRenderer::re_aiEdgeVxClipDst; + +// add and remove lists for each scan line +CStaticArray CRenderer::re_alhAddLists; +CStaticArray CRenderer::re_actAddCounts; // count of edges in given add list +CStaticArray CRenderer::re_apsedRemoveFirst; +CStaticStackArray CRenderer::re_aaceActiveEdgesTmp; +CStaticStackArray CRenderer::re_aaceActiveEdges; + +// container for sorting translucent polygons +CDynamicStackArray CRenderer::re_atcTranslucentPolygons; + +// container for all light influencing current model +struct ModelLight { + CLightSource *ml_plsLight; // the light source + FLOAT3D ml_vDirection; // direction from light to the model position (normalized) + FLOAT ml_fShadowIntensity; // intensity at the model position (for shadow) + FLOAT ml_fR, ml_fG, ml_fB; // light components at light source (0..255) + inline void Clear(void) {}; +}; +static CDynamicStackArray _amlLights; + +static INDEX _ctMaxAddEdges=0; +static INDEX _ctMaxActiveEdges=0; + +void RendererInfo(void) +{ + CPrintF("Renderer information:\n"); + + SLONG slMem = 0; + + slMem += CRenderer::re_aadeAddEdges.da_Count*sizeof(CAddEdge); + slMem += CRenderer::re_asedScreenEdges.da_Count*sizeof(CScreenEdge); + + slMem += CRenderer::re_aspSpans.da_Count*sizeof(CSpan); + + slMem += CRenderer::re_aiClipBuffer.sa_Count*sizeof(INDEX); + slMem += CRenderer::re_aiEdgeVxClipSrc.sa_Count*sizeof(INDEX); + slMem += CRenderer::re_aiEdgeVxClipDst.sa_Count*sizeof(INDEX); + + slMem += CRenderer::re_alhAddLists.sa_Count*sizeof(CListHead); + slMem += CRenderer::re_actAddCounts.sa_Count*sizeof(INDEX); + slMem += CRenderer::re_apsedRemoveFirst.sa_Count*sizeof(CScreenEdge *); + + slMem += CRenderer::re_atcTranslucentPolygons.da_Count*sizeof(CTranslucentPolygon); + slMem += CRenderer::re_aaceActiveEdges.sa_Count*sizeof(CActiveEdge); + slMem += CRenderer::re_aaceActiveEdgesTmp.sa_Count*sizeof(CActiveEdge); + + for (INDEX ire = 0; ireObjectPlacementL() = CPlacement3D(FLOAT3D(0.0f,0.0f,0.0f), ANGLE3D(0,0,0)); + re_prProjection->ObjectFaceForwardL() = FALSE; + re_prProjection->ObjectStretchL() = FLOAT3D(1.0f, 1.0f, 1.0f); + re_prProjection->DepthBufferNearL() = 0.0f; + re_prProjection->DepthBufferFarL() = 0.9f; + re_prProjection->Prepare(); + + re_asedScreenEdges.PopAll(); + re_aadeAddEdges.PopAll(); + re_aspSpans.PopAll(); + re_avvxViewVertices.PopAll(); + re_aiEdgeVxMain.PopAll(); + + // if more scan lines are needed than last time + if (re_alhAddLists.Count()Count()>0) { + re_ulVisExclude = VISM_INCLUDEEXCLUDE; + } + FOREACHINDYNAMICCONTAINER(*_pselbscVisTweaks, CBrushSector, itbsc) { + if (itbsc->bsc_ulFlags2&BSCF2_VISIBILITYINCLUDE) { + re_ulVisInclude = itbsc->bsc_ulVisFlags&VISM_INCLUDEEXCLUDE; + } else { + re_ulVisExclude &= itbsc->bsc_ulVisFlags&VISM_INCLUDEEXCLUDE; + } + } + } + + // check if the background is needed + re_bBackgroundEnabled = FALSE; + if (!re_bRenderingShadows && _wrpWorldRenderPrefs.wrp_bBackgroundTextureOn) { + CEntity *penBackgroundViewer = re_pwoWorld->GetBackgroundViewer(); + if (penBackgroundViewer!=NULL) { + re_bBackgroundEnabled = TRUE; + re_penBackgroundViewer = penBackgroundViewer; + re_prBackgroundProjection = re_prProjection; + CPlacement3D plViewer = re_prProjection->ViewerPlacementR(); + plViewer.pl_PositionVector = FLOAT3D(0,0,0); + CPlacement3D plBcgViewer = penBackgroundViewer->GetLerpedPlacement(); + if (re_prProjection->pr_bMirror) { + ReflectPositionVectorByPlane(re_prProjection->pr_plMirror, plBcgViewer.pl_PositionVector); + } + plViewer.RelativeToAbsoluteSmooth(plBcgViewer); + re_prBackgroundProjection->ViewerPlacementL() = plViewer; + re_prBackgroundProjection->ObjectPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + re_prBackgroundProjection->FarClipDistanceL() = -1.0f; + re_prBackgroundProjection->DepthBufferNearL() = 0.9f; + re_prBackgroundProjection->DepthBufferFarL() = 1.0f; + re_prBackgroundProjection->TurnOffWarpPlane(); // background never needs warp-plane clipping + re_prBackgroundProjection->Prepare(); + } + } + + // if a viewer entity is given + if (re_penViewer!=NULL) { + // add all zoning sectors near the entity + AddZoningSectorsAroundEntity(re_penViewer, re_prProjection->ViewerPlacementR().pl_PositionVector); + // make sure the viewer is always added (if model) + if(re_penViewer->en_RenderType==CEntity::RT_MODEL || + re_penViewer->en_RenderType==CEntity::RT_EDITORMODEL) { + AddModelEntity(re_penViewer); + } + // if a viewer polygons are given + } else if (re_pcspoViewPolygons!=NULL) { + // for each polygon + FOREACHINDYNAMICCONTAINER(*re_pcspoViewPolygons, CScreenPolygon, itspo) { + CBrushPolygon *pbpo = itspo->spo_pbpoBrushPolygon; + // get the sector, sector's brush mip, brush and entity + CBrushSector *pbsc = pbpo->bpo_pbscSector; + CBrushMip *pbmBrushMip = pbsc->bsc_pbmBrushMip; + CBrush3D *pbrBrush = pbmBrushMip->bm_pbrBrush; + ASSERT(pbrBrush!=NULL); + CEntity *penBrush = pbrBrush->br_penEntity; + // if the brush is zoning + if (penBrush->en_ulFlags&ENF_ZONING) { + // add the sector that the polygon is in + AddGivenZoningSector(pbsc); + // if the brush is non-zoning + } else { + // add sectors around it + AddZoningSectorsAroundEntity(penBrush, penBrush->GetPlacement().pl_PositionVector); + } + } + // if there is no viewer entity/polygon + } else { + // set up viewer bounding box as box of minimum redraw range around viewer position + if (re_bRenderingShadows) { + // NOTE: when rendering shadows, this is set in ::RenderShadows() + //re_boxViewer = FLOATaabbox3D(re_prProjection->ViewerPlacementR().pl_PositionVector, + // 1.0f); + } else { + re_boxViewer = FLOATaabbox3D(re_prProjection->ViewerPlacementR().pl_PositionVector, + _wrpWorldRenderPrefs.wrp_fMinimumRenderRange); + } + // add all zoning sectors near viewer box + AddZoningSectorsAroundBox(re_boxViewer); + // NOTE: this is so entities outside of world can be edited in WEd + // if editor models should be rendered + if (_wrpWorldRenderPrefs.IsEditorModelsOn()) { + // add all nonzoning entities near viewer box + AddEntitiesInBox(re_boxViewer); + } + } + + if( wld_bAlwaysAddAll) { + AddAllEntities(); // used for profiling + } else { + // NOTE: this is so that world can be viewed from the outside in game + // if no brush sectors have been added so far + if (!re_bRenderingShadows && re_lhActiveSectors.IsEmpty()) { + // add all entities in the world + AddAllEntities(); + } + } + + // add the background if needed + if (re_bBackgroundEnabled) { + AddZoningSectorsAroundEntity(re_penBackgroundViewer, + re_penBackgroundViewer->GetPlacement().pl_PositionVector); + } + + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDINITIAL); +} +// scan through portals for other sectors +void CRenderer::ScanForOtherSectors(void) +{ + ChangeStatsMode(CStatForm::STI_WORLDVISIBILITY); + // if shadows or polygons should be drawn + if (re_bRenderingShadows + ||_wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) { + // rasterize edges into spans + ScanEdges(); + } + // for each of models that were kept for delayed rendering + for(INDEX iModel=0; iModelen_ulFlags &= ~ENF_INRENDERING; + } + ChangeStatsMode(CStatForm::STI_WORLDTRANSFORM); +} +// cleanup after scanning +void CRenderer::CleanupScanning(void) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_CLEANUP); + + // for all active sectors + {FORDELETELIST(CBrushSector, bsc_lnInActiveSectors, re_lhActiveSectors, itbsc) { + // remove it from list + itbsc->bsc_lnInActiveSectors.Remove(); + + // for all polygons in sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itpo) { + CBrushPolygon &bpo = *itpo; + // clear screen polygon pointers + bpo.bpo_pspoScreenPolygon = NULL; + } + }} + ASSERT(re_lhActiveSectors.IsEmpty()); + + // for all active brushes + {FORDELETELIST(CBrush3D, br_lnInActiveBrushes, re_lhActiveBrushes, itbr) { + // remove it from list + itbr->br_lnInActiveBrushes.Remove(); + }} + ASSERT(re_lhActiveBrushes.IsEmpty()); + + // for all active terrains + {FORDELETELIST(CTerrain, tr_lnInActiveTerrains, re_lhActiveTerrains, ittr) { + // remove it from list + ittr->tr_lnInActiveTerrains.Remove(); + }} + ASSERT(re_lhActiveTerrains.IsEmpty()); + + _pfRenderProfile.StopTimer(CRenderProfile::PTI_CLEANUP); +} + +// Render active terrains +void CRenderer::RenderTerrains(void) +{ + CAnyProjection3D *papr; + papr = &re_prProjection; + + // for all active terrains + {FORDELETELIST(CTerrain, tr_lnInActiveTerrains, re_lhActiveTerrains, ittr) { + // render terrain + ittr->Render(*papr, re_pdpDrawPort); + }} +} + +// Render active terrains in wireframe mode +void CRenderer::RenderWireFrameTerrains(void) +{ + CAnyProjection3D *papr; + papr = &re_prProjection; + + BOOL bShowEdges = _wrpWorldRenderPrefs.wrp_ftEdges != CWorldRenderPrefs::FT_NONE; + BOOL bShowVertices = _wrpWorldRenderPrefs.wrp_ftVertices != CWorldRenderPrefs::FT_NONE; + // BOOL bForceRegenerate = _wrpWorldRenderPrefs.wrp_ftPolygons + + COLOR colEdges = _wrpWorldRenderPrefs.wrp_colEdges; + COLOR colVertices = 0xFF0000FF; + // for all active terrains + {FORDELETELIST(CTerrain, tr_lnInActiveTerrains, re_lhActiveTerrains, ittr) { + // render terrain + if(bShowEdges) { + ittr->RenderWireFrame(*papr, re_pdpDrawPort,colEdges); + } + if(bShowVertices) { + //ittr->RenderVertices(*papr, re_pdpDrawPort,colVertices); + } + }} +} +// draw the prepared things to screen +void CRenderer::DrawToScreen(void) +{ + ChangeStatsMode(CStatForm::STI_WORLDRENDERING); + + //------------------------------------------------- first render background + // if polygons should be drawn + if (!re_bRenderingShadows && + _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) { + _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE); + if( re_bBackgroundEnabled) { + // render the polygons to screen + CPerspectiveProjection3D *pprPerspective = + (CPerspectiveProjection3D *)(CProjection3D *)(re_prBackgroundProjection); + pprPerspective->Prepare(); + RenderScene( re_pdpDrawPort, re_pspoFirstBackground, re_prBackgroundProjection, re_colSelection, FALSE); + } else { + // this is just for far sentinel + RenderSceneBackground( re_pdpDrawPort, re_spoFarSentinel.spo_spoScenePolygon.spo_cColor); + } + _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE); + } + + if (re_bBackgroundEnabled) { + // render models that were kept for delayed rendering. + ChangeStatsMode(CStatForm::STI_MODELSETUP); + RenderModels(TRUE); // render background models + ChangeStatsMode(CStatForm::STI_WORLDRENDERING); + } + + // if polygons should be drawn + if (!re_bRenderingShadows && + re_bBackgroundEnabled + &&_wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) { + // render translucent portals + _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE); + CPerspectiveProjection3D *pprPerspective = (CPerspectiveProjection3D*)(CProjection3D*)(re_prBackgroundProjection); + RenderScene( re_pdpDrawPort, SortTranslucentPolygons(re_pspoFirstBackgroundTranslucent), + re_prBackgroundProjection, re_colSelection, TRUE); + _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE); + } + + if( re_bBackgroundEnabled) { + ChangeStatsMode(CStatForm::STI_PARTICLERENDERING); + RenderParticles(TRUE); // render background particless + ChangeStatsMode(CStatForm::STI_WORLDRENDERING); + } + + //------------------------------------------------- second render non-background + // if polygons should be drawn + if( !re_bRenderingShadows + && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) { + // render the spans to screen + re_prProjection->Prepare(); + _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE); + CPerspectiveProjection3D *pprPerspective = (CPerspectiveProjection3D*)(CProjection3D*)re_prProjection; + RenderScene( re_pdpDrawPort, re_pspoFirst, re_prProjection, re_colSelection, FALSE); + _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE); + } + + // Render active terrains + if( !re_bRenderingShadows + && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) { + RenderTerrains(); + } + + // if wireframe should be drawn + if( !re_bRenderingShadows && + ( _wrpWorldRenderPrefs.wrp_ftEdges != CWorldRenderPrefs::FT_NONE + || _wrpWorldRenderPrefs.wrp_ftVertices != CWorldRenderPrefs::FT_NONE + || _wrpWorldRenderPrefs.wrp_stSelection == CWorldRenderPrefs::ST_VERTICES + || _wrpWorldRenderPrefs.IsFieldBrushesOn())) { + // render in wireframe all brushes that were added (in orthographic projection!) + re_pdpDrawPort->SetOrtho(); + RenderWireFrameBrushes(); + RenderWireFrameTerrains(); + } + + // render models that were kept for delayed rendering + ChangeStatsMode(CStatForm::STI_MODELSETUP); + RenderModels(FALSE); // render non-background models + ChangeStatsMode(CStatForm::STI_PARTICLERENDERING); + RenderParticles(FALSE); // render non-background particles + ChangeStatsMode(CStatForm::STI_WORLDRENDERING); + + // if polygons should be drawn + if (!re_bRenderingShadows + &&_wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) { + // render translucent portals + _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERSCENE); + CPerspectiveProjection3D *pprPerspective = (CPerspectiveProjection3D*)(CProjection3D*)re_prProjection; + pprPerspective->Prepare(); + RenderScene( re_pdpDrawPort, SortTranslucentPolygons(re_pspoFirstTranslucent), + re_prProjection, re_colSelection, TRUE); + _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERSCENE); + } + + // render lens flares + if( !re_bRenderingShadows) { + ChangeStatsMode(CStatForm::STI_FLARESRENDERING); + RenderLensFlares(); // (this also sets orthographic projection!) + ChangeStatsMode(CStatForm::STI_WORLDRENDERING); + } + + // if entity targets should be drawn + if( !re_bRenderingShadows && _wrpWorldRenderPrefs.wrp_bShowTargetsOn) { + // render entity targets + RenderEntityTargets(); + } + + // if entity targets should be drawn + if( !re_bRenderingShadows && _wrpWorldRenderPrefs.wrp_bShowEntityNames) { + RenderEntityNames(); + } + + // clean all buffers after rendering + re_aspoScreenPolygons.PopAll(); + re_admDelayedModels.PopAll(); + re_cenDrawn.PopAll(); + re_avvxViewVertices.PopAll(); +} + + +// draw mirror polygons to z-buffer to enable drawing of mirror +void CRenderer::FillMirrorDepth(CMirror &mi) +{ + // create a list of scene polygons for mirror + ScenePolygon *pspoFirst = NULL; + // for each polygon + FOREACHINDYNAMICCONTAINER(mi.mi_cspoPolygons, CScreenPolygon, itspo) { + CScreenPolygon &spo = *itspo; + CBrushPolygon &bpo = *spo.spo_pbpoBrushPolygon; + // create a new screen polygon + CScreenPolygon &spoNew = re_aspoScreenPolygons.Push(); + ScenePolygon &sppoNew = spoNew.spo_spoScenePolygon; + // add it to mirror list + sppoNew.spo_pspoSucc = pspoFirst; + pspoFirst = &sppoNew; + + // use same triangles + sppoNew.spo_iVtx0 = spo.spo_spoScenePolygon.spo_iVtx0; + sppoNew.spo_ctVtx = spo.spo_spoScenePolygon.spo_ctVtx; + sppoNew.spo_piElements = spo.spo_spoScenePolygon.spo_piElements; + sppoNew.spo_ctElements = spo.spo_spoScenePolygon.spo_ctElements; + } + + // render all those polygons just to clear z-buffer + RenderSceneZOnly( re_pdpDrawPort, pspoFirst, re_prProjection); +} + + + +// do the rendering +void CRenderer::Render(void) +{ + // if the world doesn't have all portal-sector links updated + if( !re_pwoWorld->wo_bPortalLinksUpToDate) { + // update the links + CSetFPUPrecision FPUPrecision(FPT_53BIT); + re_pwoWorld->wo_baBrushes.LinkPortalsAndSectors(); + re_pwoWorld->wo_bPortalLinksUpToDate = TRUE; + } + + StartStatsMode(CStatForm::STI_WORLDTRANSFORM); + _pfRenderProfile.IncrementAveragingCounter(); + _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERING); + + // set FPU to single precision while rendering + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // initialize all rendering structures + Initialize(); + // init select-on-render functionality if not rendering shadows + extern void InitSelectOnRender( PIX pixSizeI, PIX pixSizeJ); + if( re_pdpDrawPort!=NULL) InitSelectOnRender( re_pdpDrawPort->GetWidth(), re_pdpDrawPort->GetHeight()); + // add initial sectors to active lists + AddInitialSectors(); + // scan through portals for other sectors + ScanForOtherSectors(); + + // force finishing of all OpenGL pending operations, if required + ChangeStatsMode(CStatForm::STI_SWAPBUFFERS); + extern INDEX ogl_iFinish; ogl_iFinish = Clamp( ogl_iFinish, 0L, 3L); + extern INDEX d3d_iFinish; d3d_iFinish = Clamp( d3d_iFinish, 0L, 3L); + if( (ogl_iFinish==1 && _pGfx->gl_eCurrentAPI==GAT_OGL) +#ifdef SE1_D3D + || (d3d_iFinish==1 && _pGfx->gl_eCurrentAPI==GAT_D3D) +#endif // SE1_D3D + ) + gfxFinish(); + + // check any eventual delayed depth points outside the mirror (if API and time allows) + if( !re_bRenderingShadows && re_iIndex==0) { + // OpenGL allows us to check z-buffer from previous frame - cool deal! + // Direct3D is, of course, totally different story. :( + if( _pGfx->gl_eCurrentAPI==GAT_OGL || d3d_bAlternateDepthReads) { + ChangeStatsMode(CStatForm::STI_FLARESRENDERING); + extern void CheckDelayedDepthPoints( const CDrawPort *pdp, INDEX iMirrorLevel=0); + CheckDelayedDepthPoints(re_pdpDrawPort); + } + // in 1st pass - mirrors are not drawn + _bMirrorDrawn = FALSE; + } + + // if may render one more mirror recursion + ChangeStatsMode(CStatForm::STI_WORLDTRANSFORM); + if( !re_bRenderingShadows + && re_prProjection.IsPerspective() + && re_iIndex0 + && !re_pdpDrawPort->IsOverlappedRendering()) + { + // cleanup after scanning + CleanupScanning(); + + // take next renderer + CRenderer &re = _areRenderers[re_iIndex+1]; + // for each mirror + for( INDEX i=0; iGetWidth(); + PIX pixDPSizeJ = re_pdpDrawPort->GetHeight(); + mi.mi_boxOnScreen.Expand(1); + mi.mi_boxOnScreen &= PIXaabbox2D( PIX2D(0,0), PIX2D(pixDPSizeI,pixDPSizeJ)); + + // get drawport and mirror coordinates + PIX pixMirrorMinI = mi.mi_boxOnScreen.Min()(1); + PIX pixMirrorMinJ = mi.mi_boxOnScreen.Min()(2); + PIX pixMirrorMaxI = mi.mi_boxOnScreen.Max()(1); + PIX pixMirrorMaxJ = mi.mi_boxOnScreen.Max()(2); + + // calculate mirror size + PIX pixMirrorSizeI = pixMirrorMaxI-pixMirrorMinI; + PIX pixMirrorSizeJ = pixMirrorMaxJ-pixMirrorMinJ; + // clone drawport (must specify doubles here, to keep the precision) + re_pdpDrawPort->Unlock(); + CDrawPort dpMirror( re_pdpDrawPort, pixMirrorMinI /(DOUBLE)pixDPSizeI, pixMirrorMinJ /(DOUBLE)pixDPSizeJ, + pixMirrorSizeI/(DOUBLE)pixDPSizeI, pixMirrorSizeJ/(DOUBLE)pixDPSizeJ); + // skip if cannot be locked + if( !dpMirror.Lock()) { + // lock back the original drawport + re_pdpDrawPort->Lock(); + continue; + } + + // recalculate mirror size to compensate for possible lost precision + pixMirrorMinI = dpMirror.dp_MinI - re_pdpDrawPort->dp_MinI; + pixMirrorMinJ = dpMirror.dp_MinJ - re_pdpDrawPort->dp_MinJ; + pixMirrorMaxI = dpMirror.dp_MaxI - re_pdpDrawPort->dp_MinI +1; + pixMirrorMaxJ = dpMirror.dp_MaxJ - re_pdpDrawPort->dp_MinJ +1; + pixMirrorSizeI = pixMirrorMaxI-pixMirrorMinI; + pixMirrorSizeJ = pixMirrorMaxJ-pixMirrorMinJ; + ASSERT( pixMirrorSizeI==dpMirror.dp_Width && pixMirrorSizeJ==dpMirror.dp_Height); + + // set it up for rendering + re.re_pwoWorld = re_pwoWorld; + re.re_prProjection = re_prProjection; + re.re_pdpDrawPort = &dpMirror; + // initialize clipping rectangle around the mirror size + re.InitClippingRectangle( 0, 0, pixMirrorSizeI, pixMirrorSizeJ); + // setup projection to use the mirror drawport and keep same perspective as before + re.re_prProjection->ScreenBBoxL() = FLOATaabbox2D( FLOAT2D(0,0), FLOAT2D(pixDPSizeI, pixDPSizeJ)); + ((CPerspectiveProjection3D&)(*re.re_prProjection)).ppr_boxSubScreen = + FLOATaabbox2D( FLOAT2D(pixMirrorMinI, pixMirrorMinJ), FLOAT2D(pixMirrorMaxI, pixMirrorMaxJ)); + + // warp? + if( mi.mi_mp.mp_ulFlags&MPF_WARP) { + // warp clip plane is parallel to view plane and contains the closest point + re.re_penViewer = mi.mi_mp.mp_penWarpViewer; + re.re_pcspoViewPolygons = NULL; + re.re_prProjection->WarpPlaneL() = FLOATplane3D(FLOAT3D(0,0,-1), mi.mi_vClosest); + // create new viewer placement + CPlacement3D pl = re.re_prProjection->ViewerPlacementR(); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, pl.pl_OrientationAngle); + pl.AbsoluteToRelativeSmooth(mi.mi_mp.mp_plWarpIn); + pl.RelativeToAbsoluteSmooth(mi.mi_mp.mp_plWarpOut); + re.re_prProjection->ViewerPlacementL() = pl; + if (re.re_prProjection.IsPerspective() && mi.mi_mp.mp_fWarpFOV>=1 && mi.mi_mp.mp_fWarpFOV<=170) { + ((CPerspectiveProjection3D&)*re.re_prProjection).FOVL() = mi.mi_mp.mp_fWarpFOV; + } + // mirror! + } else { + re.re_penViewer = NULL; + re.re_pcspoViewPolygons = &mi.mi_cspoPolygons; + re.re_prProjection->MirrorPlaneL() = mi.mi_plPlane; + re.re_prProjection->MirrorPlaneL().Offset(0.05f); // move projection towards mirror a bit, to avoid cracks + } + re.re_bRenderingShadows = FALSE; + re.re_ubLightIllumination = 0; + + // just flat-fill if mirrors are disabled + extern INDEX wld_bRenderMirrors; + if( !wld_bRenderMirrors) dpMirror.Fill(C_GRAY|CT_OPAQUE); + else { + // render the view inside mirror + StopStatsMode(); + _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERING); + re.Render(); + _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERING); + StartStatsMode(CStatForm::STI_WORLDTRANSFORM); + } + // unlock mirror's and lock back the original drawport + dpMirror.Unlock(); + re_pdpDrawPort->Lock(); + // clear entire buffer to back value + re_pdpDrawPort->FillZBuffer(ZBUF_BACK); + // fill depth buffer of the mirror, so that scene cannot be drawn through it + FillMirrorDepth(mi); + _bMirrorDrawn = TRUE; + } + + // flush all mirrors + re_amiMirrors.PopAll(); + + // fill z-buffer only if no mirrors have been drawn, not rendering second layer in world editor and not in wireframe mode + if( !_bMirrorDrawn + && !re_pdpDrawPort->IsOverlappedRendering() + && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) { + re_pdpDrawPort->FillZBuffer(ZBUF_BACK); + } + // draw the prepared things to screen + DrawToScreen(); + } + + // no mirrors + else + { + // if rendering a mirror + // or not rendering second layer in world editor + // and not in wireframe mode + if( re_iIndex>0 + || !re_bRenderingShadows + && !re_pdpDrawPort->IsOverlappedRendering() + && _wrpWorldRenderPrefs.wrp_ftPolygons != CWorldRenderPrefs::FT_NONE) { + re_pdpDrawPort->FillZBuffer(ZBUF_BACK); + } + // draw the prepared things to screen and finish + DrawToScreen(); + CleanupScanning(); + } + + // disable fog/haze + StopFog(); + StopHaze(); + // reset vertex arrays if this is the last renderer + if( re_iIndex==0) _avtxScene.PopAll(); + + // for D3D (or mirror) we have to check depth points now, because we need back (not depth!) buffer for it, + // and D3D can't guarantee that it won't be discarded upon swapbuffers (especially if multisampling is on!) :( +#ifdef SE1_D3D + if( !re_bRenderingShadows && ((_pGfx->gl_eCurrentAPI==GAT_D3D && !d3d_bAlternateDepthReads) || re_iIndex>0)) { + extern void CheckDelayedDepthPoints( const CDrawPort *pdp, INDEX iMirrorLevel=0); + CheckDelayedDepthPoints( re_pdpDrawPort, re_iIndex); + } +#endif // SE1_D3D + + // end select-on-render functionality + extern void EndSelectOnRender(void); + EndSelectOnRender(); + + // assure that FPU precision was low all the rendering time + ASSERT( GetFPUPrecision()==FPT_24BIT); + StopStatsMode(); +} + + +/* + * Constructor. + */ +CRenderer::CRenderer(void) +{ + // setup self index + INDEX i = this-_areRenderers; + ASSERT(i>=0 && iec_pdecDLLClass!=NULL + &&woWorld.wo_pecWorldBaseClass->ec_pdecDLLClass->dec_OnWorldRender!=NULL) { + woWorld.wo_pecWorldBaseClass->ec_pdecDLLClass->dec_OnWorldRender(&woWorld); + } + + if(_wrpWorldRenderPrefs.GetShadowsType() == CWorldRenderPrefs::SHT_FULL) + { + // calculate all non directional shadows that are not up to date + woWorld.CalculateNonDirectionalShadows(); + } + + // take first renderer object + CRenderer &re = _areRenderers[0]; + // set it up for rendering + re.re_penViewer = &enViewer; + re.re_pcspoViewPolygons = NULL; + re.re_pwoWorld = &woWorld; + re.re_prProjection = prProjection; + re.re_pdpDrawPort = &dpDrawport; + // initialize clipping rectangle around the drawport + re.InitClippingRectangle(0, 0, dpDrawport.GetWidth(), dpDrawport.GetHeight()); + prProjection->ScreenBBoxL() = FLOATaabbox2D( + FLOAT2D(0.0f, 0.0f), + FLOAT2D((float)dpDrawport.GetWidth(), (float)dpDrawport.GetHeight()) + ); + re.re_bRenderingShadows = FALSE; + re.re_ubLightIllumination = 0; + + // render the view (with eventuall t-buffer effect) + extern void SetTBufferEffect( BOOL bEnable); + SetTBufferEffect(TRUE); + re.Render(); + SetTBufferEffect(FALSE); +} + + +// Render a world with some viewer, projection and drawport. (viewer may be NULL) +// internal version used for rendering shadows +ULONG RenderShadows(CWorld &woWorld, CEntity &enViewer, + CAnyProjection3D &prProjection, const FLOATaabbox3D &boxViewer, + UBYTE *pubShadowMask, SLONG slShadowWidth, SLONG slShadowHeight, + UBYTE ubIllumination) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_RENDERSHADOWS); + + // take a renderer object + CRenderer &re = _areRenderers[0]; + // set it up for rendering + re.re_penViewer = &enViewer; + re.re_pcspoViewPolygons = NULL; + re.re_pwoWorld = &woWorld; + re.re_prProjection = prProjection; + re.re_pdpDrawPort = NULL; + re.re_boxViewer = boxViewer; + // initialize clipping rectangle around the drawport + const FLOATaabbox2D &box = prProjection->ScreenBBoxR(); + //re.InitClippingRectangle(box.Min()(1), box.Min()(2), box.Size()(1), box.Size()(2)); + re.InitClippingRectangle(0, 0, box.Size()(1), box.Size()(2)); + + re.re_bRenderingShadows = TRUE; + re.re_bDirectionalShadows = prProjection.IsParallel(); + re.re_bSomeLightExists = FALSE; + re.re_bSomeDarkExists = FALSE; + _bSomeDarkExists = FALSE; + re.re_pubShadow = pubShadowMask; + re.re_slShadowWidth = slShadowWidth; + re.re_slShadowHeight = slShadowHeight; + re.re_ubLightIllumination = ubIllumination; + // render the view + re.Render(); + + ULONG ulFlags = 0; + if (!re.re_bSomeLightExists) { + ulFlags|=BSLF_ALLDARK; + } + if (!(re.re_bSomeDarkExists|_bSomeDarkExists)) { + ulFlags|=BSLF_ALLLIGHT; + } + + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_RENDERSHADOWS); + + return ulFlags; +} diff --git a/Sources/Engine/Rendering/Render.h b/Sources/Engine/Rendering/Render.h new file mode 100644 index 0000000..bc26422 --- /dev/null +++ b/Sources/Engine/Rendering/Render.h @@ -0,0 +1,225 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include +#include +/* + * Preferences for rendering world (another class is used for rendering models). + */ +class ENGINE_API CWorldRenderPrefs { +public: + enum FillType { + FT_NONE, // do not draw this element + FT_INKCOLOR, // draw all in same color + FT_POLYGONCOLOR, // draw in colors of corresponding polygons + FT_SECTORCOLOR, // draw in colors of corresponding sectors + FT_TEXTURE, // draw with texture + }; + enum SelectionType { + ST_NONE, // no selection is drawn + ST_ENTITIES, // selected entities are marked + ST_POLYGONS, // selected polygons are marked + ST_SECTORS, // selected sectors are marked + ST_VERTICES, // selected vertices are marked + }; + enum ShadowsType { + SHT_NONE = 0, // do not use any shadows + SHT_NOAUTOCALCULATE, // use shadows, but don't auto recalculate + SHT_FULL = 255, // use full shadows + }; + enum LensFlaresType { + LFT_NONE = 0, // do not render lens flares at all + LFT_SINGLE_FLARE, // render only single flare without reflections + LFT_REFLECTIONS, // render flares and reflections + LFT_REFLECTIONS_AND_GLARE, // render flare, reflections and glare + }; +public: + BOOL wrp_bHiddenLinesOn; // set if hidden lines should be drawn + BOOL wrp_bShowTargetsOn; // set if lines to target entities should be drawn + BOOL wrp_bShowEntityNames;// set if entity names should be typed + BOOL wrp_bEditorModelsOn; // set if editor models should be drawn + BOOL wrp_bFieldBrushesOn; // set if field brushes should be drawn + BOOL wrp_bBackgroundTextureOn; // set if background texture should be drawn + BOOL wrp_bShowVisTweaksOn; // set if visibility tweaks for selected sectors should be shown + BOOL wrp_bDisableVisTweaks; // set if entities utilitizing visibility tweaks should be shown allways + BOOL wrp_bAutoMipBrushingOn; // set if mip brushing should be automatic + FLOAT wrp_fManualMipBrushingFactor; // mip factor for manual mip brushing + FLOAT wrp_fFarClipPlane; // far clip plane + BOOL wrp_bApplyFarClipPlaneInIsometricProjection; // if far clip plane should be applied in isometric projections + + enum FillType wrp_ftVertices; // fill type for vertices + COLOR wrp_colVertices; // color used for drawing vertices in ink-color mode + + enum FillType wrp_ftEdges; // fill type for edges + COLOR wrp_colEdges; // color used for drawing edges in ink-color mode + + enum FillType wrp_ftPolygons; // fill type for polygons + COLOR wrp_colPolygons; // color used for drawing polygons in ink-color mode + + enum ShadowsType wrp_shtShadows; // degree of using shadows + enum LensFlaresType wrp_lftLensFlares; // degree of using lens flares + + BOOL wrp_abTextureLayers[3]; // set for texture layers that are rendered + + BOOL wrp_bFogOn; // set if fog should be rendered + BOOL wrp_bHazeOn; // set if haze should be rendered + BOOL wrp_bMirrorsOn; // set if mirrors should be rendered + + FLOAT wrp_fMinimumRenderRange; // range (in meters) around viewer that is always drawn + + CModelObject *wrp_pmoSelectedEntity; // model used for marking selected entities + CModelObject *wrp_pmoSelectedPortal; // model used for marking selected portals + CModelObject *wrp_pmoEmptyBrush; // model used for marking brushes with no sectors + + enum SelectionType wrp_stSelection; // what kind of selection is shown + +public: + /* Constructor -- sets default values. */ + CWorldRenderPrefs(void); + + /* Test if drawing of hidden edges is turned on. */ + inline BOOL IsHiddenLinesOn(void) { return wrp_bHiddenLinesOn; }; + /* Set drawing of hidden edges on or off. */ + inline void SetHiddenLinesOn(BOOL bOn) { wrp_bHiddenLinesOn = bOn; }; + + /* Test if drawing of lines to target entities is turned on. */ + inline BOOL IsShowTargetsOn(void) { return wrp_bShowTargetsOn; }; + /* Set drawing of lines to target entities on or off. */ + inline void SetShowTargetsOn(BOOL bOn) { wrp_bShowTargetsOn = bOn; }; + + /* Test if typing of entity names is turned on. */ + inline BOOL IsShowEntityNamesOn(void) { return wrp_bShowEntityNames; }; + /* Set typing of entity names on or off. */ + inline void SetShowEntityNamesOn(BOOL bOn) { wrp_bShowEntityNames = bOn; }; + + /* Test if drawing of editor models is turned on. */ + inline BOOL IsEditorModelsOn(void) { return wrp_bEditorModelsOn; }; + /* Set drawing of editor models on or off. */ + inline void SetEditorModelsOn(BOOL bOn) { wrp_bEditorModelsOn = bOn; }; + /* Test if drawing of editor models is turned on. */ + inline BOOL IsFieldBrushesOn(void) { return wrp_bFieldBrushesOn; }; + /* Set drawing of editor models on or off. */ + inline void SetFieldBrushesOn(BOOL bOn) { wrp_bFieldBrushesOn = bOn; }; + + /* Test if drawing background texture is on. */ + inline BOOL IsBackgroundTextureOn(void) { return wrp_bBackgroundTextureOn; }; + /* Set drawing of background texture on or off. */ + inline void SetBackgroundTextureOn(BOOL bOn) { wrp_bBackgroundTextureOn = bOn; }; + + /* Test if drawing visibility tweaks for selected sectors is on. */ + inline BOOL IsVisTweaksOn(void) { return wrp_bShowVisTweaksOn; }; + /* Set drawing of visibility tweaks for selected sectors on or off. */ + inline void SetVisTweaksOn(BOOL bOn) { wrp_bShowVisTweaksOn = bOn; }; + + /* Test if visibility tweaks are off. */ + inline BOOL IsVisTweaksDisabled(void) { return wrp_bDisableVisTweaks; }; + /* Set disabling of visibility tweaks on or off. */ + inline void DisableVisTweaks(BOOL bOn) { wrp_bDisableVisTweaks = bOn; }; + + /* Test if drawing fog is on. */ + inline BOOL IsFogOn(void) { return wrp_bFogOn; }; + /* Set drawing of fog on or off. */ + inline void SetFogOn(BOOL bOn) { wrp_bFogOn = bOn; }; + /* Test if drawing haze is on. */ + inline BOOL IsHazeOn(void) { return wrp_bHazeOn; }; + /* Set drawing of haze on or off. */ + inline void SetHazeOn(BOOL bOn) { wrp_bHazeOn = bOn; }; + /* Test if drawing mirrors is on. */ + inline BOOL IsMirrorsOn(void) { return wrp_bMirrorsOn; }; + /* Set drawing of mirrors on or off. */ + inline void SetMirrorsOn(BOOL bOn) { wrp_bMirrorsOn = bOn; }; + + /* Test if mip brushing should be automatic. */ + inline BOOL IsAutoMipBrushingOn(void) { return wrp_bAutoMipBrushingOn; }; + /* Set mip brushing should to automatic or manual. */ + inline void SetAutoMipBrushingOn(BOOL bOn) { wrp_bAutoMipBrushingOn = bOn; }; + /* Set/get mip factor for manual mip brushing. */ + inline void SetManualMipBrushingFactor(FLOAT fFactor) { wrp_fManualMipBrushingFactor = fFactor; }; + inline FLOAT GetManualMipBrushingFactor(void) { return wrp_fManualMipBrushingFactor; }; + + /* Test if texture layer is shown. */ + inline BOOL IsTextureLayerOn(INDEX iTexture) { + ASSERT(iTexture>=0 && iTexture<3); + return wrp_abTextureLayers[iTexture]; + }; + /* Set texture layer shown/hidden. */ + inline void SetTextureLayerOn(BOOL bOn, INDEX iTexture) { + ASSERT(iTexture>=0 && iTexture<3); + wrp_abTextureLayers[iTexture] = bOn; + }; + + // Get mip brushing factor relevant for given distance mip factor + FLOAT GetCurrentMipBrushingFactor(FLOAT fDistanceMipFactor); + + /* Set/get the fill type for vertices. */ + inline void SetVerticesFillType(enum FillType ft) { wrp_ftVertices = ft; }; + inline enum FillType GetVerticesFillType(void) { return wrp_ftVertices; }; + /* Set/get the ink color for vertices. */ + inline void SetVerticesInkColor(COLOR color) { wrp_colVertices = color; }; + inline COLOR GetVerticesInkColor(void) { return wrp_colVertices; }; + + /* Set/get the fill type for edges. */ + inline void SetEdgesFillType(enum FillType ft) { wrp_ftEdges = ft; }; + inline enum FillType GetEdgesFillType(void) { return wrp_ftEdges; }; + /* Set/get the ink color for edges. */ + inline void SetEdgesInkColor(COLOR color) { wrp_colEdges = color; }; + inline COLOR GetEdgesInkColor(void) { return wrp_colEdges; }; + + /* Set/get the fill type for polygons. */ + inline void SetPolygonsFillType(enum FillType ft) { wrp_ftPolygons= ft; }; + inline enum FillType GetPolygonsFillType(void) { return wrp_ftPolygons; }; + /* Set/get the ink color for polygons. */ + inline void SetPolygonsInkColor(COLOR color) { wrp_colPolygons = color; }; + inline COLOR GetPolygonsInkColor(void) { return wrp_colPolygons; }; + + /* Set/get the brush shadow quality. */ + inline void SetShadowsType( enum ShadowsType sht) { wrp_shtShadows = sht; }; + inline enum ShadowsType GetShadowsType(void) { return wrp_shtShadows; }; + + /* Set/get the lens flare quality. */ + inline void SetLensFlaresType( enum LensFlaresType lft) { wrp_lftLensFlares = lft; }; + inline enum LensFlaresType GetLensFlares(void) { return wrp_lftLensFlares; }; + + /* Set/get range (in meters) around viewer that is always drawn. */ + inline void SetMinimumRenderRange(FLOAT fRange) { wrp_fMinimumRenderRange = fRange; }; + inline FLOAT GetMinimumRenderRange(void) { return wrp_fMinimumRenderRange; }; + + /* Set/get model object used for marking selected models. */ + inline void SetSelectedEntityModel(CModelObject *pmoSelection) { wrp_pmoEmptyBrush = wrp_pmoSelectedEntity = pmoSelection; }; + inline CModelObject *GetSelectedEntityModel(void) { return wrp_pmoSelectedEntity; }; + + /* Set/get model object used for marking selected portals. */ + inline void SetSelectedPortalModel(CModelObject *pmoSelection) { wrp_pmoSelectedPortal = pmoSelection; }; + inline CModelObject *GetSelectedPortalModel(void) { return wrp_pmoSelectedPortal; }; + + /* Set/get model object used for marking empty brushes. */ + inline void SetEmptyBrushModel(CModelObject *pmoBrush) { wrp_pmoEmptyBrush = pmoBrush; }; + inline CModelObject *GetEmptyBrushModel(void) { return wrp_pmoEmptyBrush; }; + + /* Set/get the selection type. */ + inline void SetSelectionType(enum SelectionType st) { wrp_stSelection = st; }; + inline enum SelectionType GetSelectionType(void) { return wrp_stSelection; }; +}; + +// global instance used in rendering +ENGINE_API extern CWorldRenderPrefs _wrpWorldRenderPrefs; + +// variables for selection on rendering +ENGINE_API extern CBrushVertexSelection *_pselbvxtSelectOnRender; +ENGINE_API extern CEntitySelection *_pselenSelectOnRender; +ENGINE_API extern CStaticStackArray *_pavpixSelectLasso; +ENGINE_API extern PIX2D _vpixSelectNearPoint; +ENGINE_API extern BOOL _bSelectAlternative; +ENGINE_API extern PIX _pixDeltaAroundVertex; +ENGINE_API extern CBrushSectorSelection *_pselbscVisTweaks; + +/* + * Rendering interface + */ +// Render a world with some viewer, projection and drawport. (viewer may be NULL) +ENGINE_API extern void RenderView(CWorld &woWorld, CEntity &enViewer, + CAnyProjection3D &prProjection, CDrawPort &dpDrawport); + +// shading info for viewer of last rendered view +ENGINE_API extern FLOAT3D _vViewerLightDirection; +ENGINE_API extern COLOR _colViewerLight; +ENGINE_API extern COLOR _colViewerAmbient; diff --git a/Sources/Engine/Rendering/RenderAdding.cpp b/Sources/Engine/Rendering/RenderAdding.cpp new file mode 100644 index 0000000..8f4a099 --- /dev/null +++ b/Sources/Engine/Rendering/RenderAdding.cpp @@ -0,0 +1,911 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +// for generating unique IDs for lens flares +// (32 bit should be enough for generating 1 lens flare per second during approx. 136 years) +static INDEX _iNextLensFlareID = 1; // 0 is reserved for no-id + +extern void SelectEntityOnRender( CProjection3D &prProjection, CEntity &en); + + +// creates oriented bounding box for a model +inline void CreateModelOBBox( CEntity *penModel, FLOAT3D &vHandle, FLOATmatrix3D &mAbsToView, FLOATobbox3D &obbox) +{ + FLOAT3D vAntiStretch = penModel->GetClassificationBoxStretch(); + vAntiStretch(1) = 1.0f/vAntiStretch(1); + vAntiStretch(2) = 1.0f/vAntiStretch(2); + vAntiStretch(3) = 1.0f/vAntiStretch(3); + FLOATaabbox3D boxModel = penModel->en_boxSpatialClassification; + boxModel.StretchByVector( vAntiStretch); + obbox = FLOATobbox3D( boxModel, vHandle, mAbsToView*penModel->en_mRotation); +} + + +/* + * Add a model entity to rendering. + */ +void CRenderer::AddModelEntity(CEntity *penModel) +{ + // if the entity is currently active or hidden, don't add it again + if( penModel->en_ulFlags&(ENF_INRENDERING|ENF_HIDDEN)) return; + // skip the entity if predicted, and predicted entities should not be rendered + if( penModel->IsPredicted() && !gfx_bRenderPredicted) return; + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDMODELENTITY); + + // get its model object + CModelObject *pmoModelObject; + if( penModel->en_RenderType!=CEntity::RT_BRUSH && + penModel->en_RenderType != CEntity::RT_FIELDBRUSH) { + pmoModelObject = penModel->GetModelForRendering(); + } else { + // empty brushes are also rendered as models + pmoModelObject = _wrpWorldRenderPrefs.wrp_pmoEmptyBrush; + } + + // mark the entity as active in rendering + penModel->en_ulFlags |= ENF_INRENDERING; + + // add it to container of all drawn entities + re_cenDrawn.Add(penModel); + // add it to a container for delayed rendering + CDelayedModel &dm = re_admDelayedModels.Push(); + dm.dm_penModel = penModel; + dm.dm_pmoModel = pmoModelObject; + dm.dm_ulFlags = NONE; // invisible until proved otherwise + + // get proper projection for the entity + CProjection3D *pprProjection; + if (re_bBackgroundEnabled && (penModel->en_ulFlags & ENF_BACKGROUND)) { + pprProjection = re_prBackgroundProjection; + } else { + pprProjection = re_prProjection; + } + + // transform its handle to view space + FLOAT3D vHandle; + pprProjection->PreClip(penModel->en_plPlacement.pl_PositionVector, vHandle); + // setup mip factor + FLOAT fDistance = vHandle(3)+penModel->GetDepthSortOffset(); + + FLOAT fMipFactor = pprProjection->MipFactor(fDistance); + + penModel->AdjustMipFactor(fMipFactor); + dm.dm_fDistance = fDistance; + dm.dm_fMipFactor = fMipFactor; + + FLOAT fR = penModel->en_fSpatialClassificationRadius; + if( penModel->en_RenderType==CEntity::RT_BRUSH + || penModel->en_RenderType==CEntity::RT_FIELDBRUSH) { + fR = 1.0f; + } + ASSERT(fR>0.0f); + + // test object sphere to frustum + FLOATobbox3D boxEntity; + BOOL bModelHasBox = FALSE; + INDEX iFrustumTest = pprProjection->TestSphereToFrustum( vHandle, fR); + // if test is indeterminate + if( iFrustumTest==0) { + // create oriented box and test it to frustum + CreateModelOBBox( penModel, vHandle, pprProjection->pr_ViewerRotationMatrix, boxEntity); + bModelHasBox = TRUE; // mark that box has been created + iFrustumTest = pprProjection->TestBoxToFrustum(boxEntity); + } + // if not inside + if( iFrustumTest<0) { + // don't add it + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); + return; + } + + // do additional check for eventual mirror plane (if allowed) + INDEX iMirrorPlaneTest = -1; + extern INDEX gap_iOptimizeClipping; + if( gap_iOptimizeClipping>0 && (pprProjection->pr_bMirror || pprProjection->pr_bWarp)) { + // test sphere against plane + const FLOAT fPlaneDistance = pprProjection->pr_plMirrorView.PointDistance(vHandle); + if( fPlaneDistance < -fR) iMirrorPlaneTest = -1; + else if( fPlaneDistance > +fR) iMirrorPlaneTest = +1; + else { // if test is indeterminate + // create box entity if needed + if( !bModelHasBox) { + CreateModelOBBox( penModel, vHandle, pprProjection->pr_ViewerRotationMatrix, boxEntity); + bModelHasBox = TRUE; + } // test it to mirror/warp plane + iMirrorPlaneTest = boxEntity.TestAgainstPlane(pprProjection->pr_plMirrorView); + } + // if not in mirror + if( iMirrorPlaneTest<0) { + // don't add it + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); + return; + } + } + + // if it has a light source with a lens flare and we're not rendering shadows + CLightSource *pls = penModel->GetLightSource(); + if( !re_bRenderingShadows && pls!=NULL && pls->ls_plftLensFlare!=NULL) { + // add the lens flare to rendering + AddLensFlare( penModel, pls, pprProjection, re_iIndex); + } + + // adjust model flags + if( pmoModelObject->HasAlpha()) dm.dm_ulFlags |= DMF_HASALPHA; + if( re_bCurrentSectorHasFog) dm.dm_ulFlags |= DMF_FOG; + if( re_bCurrentSectorHasHaze) dm.dm_ulFlags |= DMF_HAZE; + if( iFrustumTest>0) dm.dm_ulFlags |= DMF_INSIDE; // mark the need for clipping + if( iMirrorPlaneTest>0) dm.dm_ulFlags |= DMF_INMIRROR; // mark the need for clipping to mirror/warp plane + + // if this is an editor model and editor models are disabled + if( penModel->en_RenderType==CEntity::RT_EDITORMODEL + && !_wrpWorldRenderPrefs.IsEditorModelsOn()) { + // don't render it + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); + return; + } + + // safety check + if( pmoModelObject==NULL) { + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); + return; + } + + // if the object is not visible at its distance + if( (!re_bRenderingShadows && !pmoModelObject->IsModelVisible(fMipFactor))) { + // don't add it + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); + return; + } + + // if entity selecting by laso requested, test for selecting + if( _pselenSelectOnRender != NULL) SelectEntityOnRender( *pprProjection, *penModel); + + // allow its rendering + dm.dm_ulFlags |= DMF_VISIBLE; + ASSERT(pmoModelObject!=NULL); + // if rendering shadows use only first mip level + if( re_bRenderingShadows) dm.dm_fMipFactor = 0; + + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); +} +/* + * Add a ska model entity to rendering. + */ +void CRenderer::AddSkaModelEntity(CEntity *penModel) +{ + // if the entity is currently active or hidden, don't add it again + if( penModel->en_ulFlags&(ENF_INRENDERING|ENF_HIDDEN)) return; + // skip the entity if predicted, and predicted entities should not be rendered + if( penModel->IsPredicted() && !gfx_bRenderPredicted) return; + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDMODELENTITY); + + // get its model object + CModelInstance *pmiModelInstance = penModel->GetModelInstance(); + + // mark the entity as active in rendering + penModel->en_ulFlags |= ENF_INRENDERING; + + // add it to container of all drawn entities + re_cenDrawn.Add(penModel); + // add it to a container for delayed rendering + CDelayedModel &dm = re_admDelayedModels.Push(); + dm.dm_penModel = penModel; + dm.dm_ulFlags = NONE; // invisible until proved otherwise + // dm.dm_pmoModel = pmoModelObject; + + // get proper projection for the entity + CProjection3D *pprProjection; + if (re_bBackgroundEnabled && (penModel->en_ulFlags & ENF_BACKGROUND)) { + pprProjection = re_prBackgroundProjection; + } else { + pprProjection = re_prProjection; + } + + // transform its handle to view space + FLOAT3D vHandle; + pprProjection->PreClip(penModel->en_plPlacement.pl_PositionVector, vHandle); + // setup mip factor + FLOAT fDistance = vHandle(3)+penModel->GetDepthSortOffset(); + + FLOAT fMipFactor = pprProjection->MipFactor(fDistance); + fMipFactor = -fDistance; + + penModel->AdjustMipFactor(fMipFactor); + dm.dm_fDistance = fDistance; + dm.dm_fMipFactor = fMipFactor; + + FLOAT fR = penModel->en_fSpatialClassificationRadius; + ASSERT(fR>0.0f); + + // test object sphere to frustum + FLOATobbox3D boxEntity; + BOOL bModelHasBox = FALSE; + INDEX iFrustumTest = pprProjection->TestSphereToFrustum( vHandle, fR); + // if test is indeterminate + if( iFrustumTest==0) { + // create oriented box and test it to frustum + CreateModelOBBox( penModel, vHandle, pprProjection->pr_ViewerRotationMatrix, boxEntity); + bModelHasBox = TRUE; // mark that box has been created + iFrustumTest = pprProjection->TestBoxToFrustum(boxEntity); + } + // if not inside + if( iFrustumTest<0) { + // don't add it + // _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); + return; + } + + // do additional check for eventual mirror plane (if allowed) + INDEX iMirrorPlaneTest = -1; + extern INDEX gap_iOptimizeClipping; + if( gap_iOptimizeClipping>0 && (pprProjection->pr_bMirror || pprProjection->pr_bWarp)) { + // test sphere against plane + const FLOAT fPlaneDistance = pprProjection->pr_plMirrorView.PointDistance(vHandle); + if( fPlaneDistance < -fR) iMirrorPlaneTest = -1; + else if( fPlaneDistance > +fR) iMirrorPlaneTest = +1; + else { // if test is indeterminate + // create box entity if needed + if( !bModelHasBox) { + CreateModelOBBox( penModel, vHandle, pprProjection->pr_ViewerRotationMatrix, boxEntity); + bModelHasBox = TRUE; + } // test it to mirror/warp plane + iMirrorPlaneTest = boxEntity.TestAgainstPlane(pprProjection->pr_plMirrorView); + } + // if not in mirror + if( iMirrorPlaneTest<0) { + // don't add it + // _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); + return; + } + } + + // if it has a light source with a lens flare and we're not rendering shadows + CLightSource *pls = penModel->GetLightSource(); + if( !re_bRenderingShadows && pls!=NULL && pls->ls_plftLensFlare!=NULL) { + // add the lens flare to rendering + AddLensFlare( penModel, pls, pprProjection, re_iIndex); + } + + // adjust model flags + if( pmiModelInstance->HasAlpha()) dm.dm_ulFlags |= DMF_HASALPHA; + if( re_bCurrentSectorHasFog) dm.dm_ulFlags |= DMF_FOG; + if( re_bCurrentSectorHasHaze) dm.dm_ulFlags |= DMF_HAZE; + if( iFrustumTest>0) dm.dm_ulFlags |= DMF_INSIDE; // mark the need for clipping + if( iMirrorPlaneTest>0) dm.dm_ulFlags |= DMF_INMIRROR; // mark the need for clipping to mirror/warp plane + + // if this is an editor model and editor models are disabled + if( penModel->en_RenderType==CEntity::RT_SKAEDITORMODEL + && !_wrpWorldRenderPrefs.IsEditorModelsOn()) { + // don't render it + // _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); + return; + } + + // safety check + if( pmiModelInstance==NULL) { + // _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); + return; + } + + // if the object is not visible at its distance + if( (!re_bRenderingShadows && !pmiModelInstance->IsModelVisible(fMipFactor))) { + // don't add it + // _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); + return; + } + + // if entity selecting by laso requested, test for selecting + if( _pselenSelectOnRender != NULL) SelectEntityOnRender( *pprProjection, *penModel); + + // allow its rendering + dm.dm_ulFlags |= DMF_VISIBLE; + // if rendering shadows use only first mip level + if( re_bRenderingShadows) dm.dm_fMipFactor = 0; + + // _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDMODELENTITY); +} + + +/* Add a lens flare to rendering. */ +void CRenderer::AddLensFlare( CEntity *penLight, CLightSource *pls, CProjection3D *pprProjection, INDEX iMirrorLevel/*=0*/) +{ + // if flares are off + if (_wrpWorldRenderPrefs.wrp_lftLensFlares == CWorldRenderPrefs::LFT_NONE) { + // don't add any new flares + return; + } + + // project the light source position to view space + FLOAT3D vRotated; + pprProjection->PreClip(penLight->GetLerpedPlacement().pl_PositionVector, vRotated); + // if it is behind near clip plane + if (-vRotated(3)NearClipDistanceR()) { + // skip it + return; + } + // project it to screen + FLOAT3D vScreen; + pprProjection->PostClip(vRotated, vScreen); + + ASSERT( re_pdpDrawPort!=NULL); + const ULONG ulDrawPortID = re_pdpDrawPort->GetID(); + + // for each existing lens flare + CLensFlareInfo *plfi = NULL; + const INDEX ctFlares = re_alfiLensFlares.Count(); + {for(INDEX iFlare=0; iFlare0)) { + // use it + plfi = &lfiOld; + break; + } + }} + // if it is not found + if (plfi==NULL) { + // create a new one + plfi = &re_alfiLensFlares.Push(); + plfi->lfi_iID = _iNextLensFlareID++; + plfi->lfi_tmLastFrame = _pTimer->GetRealTimeTick()-0.05f; + plfi->lfi_iMirrorLevel = iMirrorLevel; + plfi->lfi_fFadeFactor = 0.0f; + plfi->lfi_ulFlags = NONE; + } + + CLensFlareInfo &lfi = *plfi; + lfi.lfi_ulDrawPortID = ulDrawPortID; + lfi.lfi_plsLightSource = pls; + lfi.lfi_fI = vScreen(1); + lfi.lfi_fJ = vScreen(2); + lfi.lfi_fDistance = -vRotated(3); + lfi.lfi_fOoK = (1-pprProjection->pr_fDepthBufferFactor/vRotated(3)) + * pprProjection->pr_fDepthBufferMul+pprProjection->pr_fDepthBufferAdd; + lfi.lfi_vProjected = vRotated; + lfi.lfi_ulFlags |= LFF_ACTIVE; + lfi.lfi_ulFlags &= ~LFF_FOG; + lfi.lfi_ulFlags &= ~LFF_HAZE; + if( re_bCurrentSectorHasFog) lfi.lfi_ulFlags |= LFF_FOG; + if( re_bCurrentSectorHasHaze) lfi.lfi_ulFlags |= LFF_HAZE; +} + + + +/* Add a moving brush entity to rendering list (add all sectors immediately). */ +void CRenderer::AddNonZoningBrush( CEntity *penBrush, CBrushSector *pbscThatAdds) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDNONZONINGBRUSH); + ASSERT( penBrush!=NULL); + // get its brush + CBrush3D &brBrush = *penBrush->en_pbrBrush; + + // if hidden + if( penBrush->en_ulFlags&ENF_HIDDEN) { + // skip it + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDNONZONINGBRUSH); + return; + } + + // if the brush is already added + if( brBrush.br_lnInActiveBrushes.IsLinked()) { + // skip it + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDNONZONINGBRUSH); + return; + } + + const BOOL bDisableVisTweaks = _wrpWorldRenderPrefs.wrp_bDisableVisTweaks; + // if visibility tweaking is enabled + if( !bDisableVisTweaks) + { + // if vistweaks exclude this brush from rendering in this position + ULONG ulVisTweaks = penBrush->GetVisTweaks(); + if ((pbscThatAdds!=NULL && (VISM_DONTCLASSIFY&pbscThatAdds->bsc_ulVisFlags&ulVisTweaks)) + ||(ulVisTweaks&re_ulVisExclude&VISM_INCLUDEEXCLUDE) + ||(re_ulVisInclude!=0 && !(ulVisTweaks&re_ulVisInclude&VISM_INCLUDEEXCLUDE) ) ) { + // skip it + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDNONZONINGBRUSH); + return; + } + } + + + // skip whole non-zoning brush if invisible for rendering and not in wireframe mode + const BOOL bWireFrame = _wrpWorldRenderPrefs.wrp_ftEdges != CWorldRenderPrefs::FT_NONE + || _wrpWorldRenderPrefs.wrp_ftVertices != CWorldRenderPrefs::FT_NONE; + if( !(penBrush->en_ulFlags&ENF_ZONING) && !bWireFrame) + { // test every brush polygon for it's visibility flag + // for every sector in brush + FOREACHINDYNAMICARRAY( brBrush.GetFirstMip()->bm_abscSectors, CBrushSector, itbsc) { + // for all polygons in sector + FOREACHINSTATICARRAY( itbsc->bsc_abpoPolygons, CBrushPolygon, itpo) { + // advance to next polygon if invisible + CBrushPolygon &bpo = *itpo; + if( !(bpo.bpo_ulFlags&BPOF_INVISIBLE)) goto addBrush; + } + } + // skip this brush + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDNONZONINGBRUSH); + return; + } + +addBrush: + // prepare the brush entity for rendering if not yet prepared + PrepareBrush(brBrush.br_penEntity); + + // get relevant mip factor for that brush and current rendering prefs + CBrushMip *pbm = brBrush.GetBrushMipByDistance( + _wrpWorldRenderPrefs.GetCurrentMipBrushingFactor(brBrush.br_prProjection->MipFactor())); + // if brush mip exists for that mip factor + if (pbm!=NULL) { + // if entity selecting by laso requested + if( _pselenSelectOnRender != NULL) + { + // test for selecting + SelectEntityOnRender( *re_prProjection, *penBrush); + } + // for each sector + FOREACHINDYNAMICARRAY(pbm->bm_abscSectors, CBrushSector, itbsc) { + // if the sector is not hidden + if(!((itbsc->bsc_ulFlags&BSCF_HIDDEN) && !re_bRenderingShadows)) { + // add that sector to active sectors + AddActiveSector(itbsc.Current()); + } + } + } + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDNONZONINGBRUSH); +} + +/* Add a terrain entity to rendering list. */ +void CRenderer::AddTerrainEntity(CEntity *penTerrain) +{ + // _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDNONZONINGBRUSH); + ASSERT( penTerrain!=NULL); + // get its terrain + CTerrain &trTerrain = *penTerrain->GetTerrain(); + + // if hidden + if(penTerrain->en_ulFlags&ENF_HIDDEN) { + // skip it + // _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDNONZONINGBRUSH); + return; + } + + if(re_bCurrentSectorHasFog) { + trTerrain.AddFlag(TR_HAS_FOG); + } + if(re_bCurrentSectorHasHaze) { + trTerrain.AddFlag(TR_HAS_HAZE); + } + // if the brush is already added + if( trTerrain.tr_lnInActiveTerrains.IsLinked()) { + // skip it + // _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDNONZONINGBRUSH); + return; + } + + // add it to list of active terrains + re_lhActiveTerrains.AddTail(trTerrain.tr_lnInActiveTerrains); + // add it to container of all drawn entities + re_cenDrawn.Add(penTerrain); +} + +/* Add to rendering all entities in the world (used in special cases in world editor). */ +void CRenderer::AddAllEntities(void) +{ + // for all entities in world + FOREACHINDYNAMICCONTAINER(re_pwoWorld->wo_cenEntities, CEntity, iten) { + // if it is brush + if (iten->en_RenderType==CEntity::RT_BRUSH + ||(iten->en_RenderType==CEntity::RT_FIELDBRUSH + && _wrpWorldRenderPrefs.IsFieldBrushesOn())) { + // add all of its sectors + AddNonZoningBrush(&iten.Current(), NULL); + + // if it is model, or editor model that should be drawn + } else if (iten->en_RenderType==CEntity::RT_MODEL + ||(iten->en_RenderType==CEntity::RT_EDITORMODEL + && _wrpWorldRenderPrefs.IsEditorModelsOn())) { + // add it as a model + AddModelEntity(&iten.Current()); + } else if (iten->en_RenderType==CEntity::RT_SKAMODEL + ||(iten->en_RenderType==CEntity::RT_SKAEDITORMODEL + && _wrpWorldRenderPrefs.IsEditorModelsOn())) { + AddSkaModelEntity(&iten.Current()); + // if this is terrain + } else if(iten->en_RenderType==CEntity::RT_TERRAIN) { + // add it as a terrain + AddTerrainEntity(&iten.Current()); + } + } +} + +/* Add to rendering all entities that are inside an zoning brush sector. */ +void CRenderer::AddEntitiesInSector(CBrushSector *pbscSectorInside) +{ + // if we don't have a relevant sector to test with + if (pbscSectorInside==NULL || pbscSectorInside->bsc_bspBSPTree.bt_pbnRoot==NULL) { + // do nothing + return; + } + + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDENTITIESINSECTOR); + + // for all entities in the sector + {FOREACHDSTOFSRC(pbscSectorInside->bsc_rsEntities, CEntity, en_rdSectors, pen) + // if it is brush + if (pen->en_RenderType==CEntity::RT_BRUSH + ||(pen->en_RenderType==CEntity::RT_FIELDBRUSH + && _wrpWorldRenderPrefs.IsFieldBrushesOn())) { + // add all of its sectors + AddNonZoningBrush(pen, pbscSectorInside); + + // if it is model, or editor model that should be drawn + } else if (pen->en_RenderType==CEntity::RT_MODEL||pen->en_RenderType==CEntity::RT_EDITORMODEL) { + // add it as a model + AddModelEntity(pen); + // if it is a ska model, or editor model that should be drawn + } else if(pen->en_RenderType==CEntity::RT_SKAMODEL||pen->en_RenderType==CEntity::RT_SKAEDITORMODEL) { + AddSkaModelEntity(pen); + // if it is a terrain + } else if(pen->en_RenderType==CEntity::RT_TERRAIN) { + AddTerrainEntity(pen); + } + ENDFOR} + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDENTITIESINSECTOR); +}; + +/* Add to rendering all entities that are inside a given box. */ +void CRenderer::AddEntitiesInBox(const FLOATaabbox3D &boxNear) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDENTITIESINBOX); + + // for all entities in world + FOREACHINDYNAMICCONTAINER(re_pwoWorld->wo_cenEntities, CEntity, iten) { + // if it is brush + if (iten->en_RenderType==CEntity::RT_BRUSH + ||(iten->en_RenderType==CEntity::RT_FIELDBRUSH + && _wrpWorldRenderPrefs.IsFieldBrushesOn())) { + // if it is zoning + if (iten->en_ulFlags&ENF_ZONING) { + // skip it + continue; + } + + // if the first mip of the brush has contact with the box + CEntity *penBrush = iten; + CBrushMip *pbmFirst = penBrush->en_pbrBrush->GetFirstMip(); + if (pbmFirst->bm_boxBoundingBox.HasContactWith(boxNear)) { + // add all of its sectors + AddNonZoningBrush(&iten.Current(), NULL); + } + + // if it is model, or editor model that should be drawn + } else if (iten->en_RenderType==CEntity::RT_MODEL + ||iten->en_RenderType==CEntity::RT_EDITORMODEL) { + // get model's bounding box for current frame + FLOATaabbox3D boxModel; + iten->en_pmoModelObject->GetCurrentFrameBBox(boxModel); + // get center and radius of the bounding sphere + FLOAT fSphereRadius = Max( boxModel.Min().Length(), boxModel.Max().Length() ); + FLOAT3D vSphereCenter = iten->en_plPlacement.pl_PositionVector; + // create maximum box for the model (in cases of any rotation) from the sphere + FLOATaabbox3D boxMaxModel(vSphereCenter, fSphereRadius); + // if the model box is near the given box + if (boxMaxModel.HasContactWith(boxNear)) { + // add it as a model + AddModelEntity(&iten.Current()); + } + } else if( iten->en_RenderType==CEntity::RT_SKAMODEL + || iten->en_RenderType==CEntity::RT_SKAEDITORMODEL) { + // get model's bounding box for current frame + FLOATaabbox3D boxModel; + iten->GetModelInstance()->GetCurrentColisionBox(boxModel); + // get center and radius of the bounding sphere + FLOAT fSphereRadius = Max( boxModel.Min().Length(), boxModel.Max().Length() ); + FLOAT3D vSphereCenter = iten->en_plPlacement.pl_PositionVector; + // create maximum box for the model (in cases of any rotation) from the sphere + FLOATaabbox3D boxMaxModel(vSphereCenter, fSphereRadius); + // if the model box is near the given box + AddSkaModelEntity(&iten.Current()); + // if this is terrain entity + } else if( iten->en_RenderType==CEntity::RT_TERRAIN) { + // get model's bounding box for current frame + #pragma message(">> Is terrain visible") + FLOATaabbox3D boxTerrain; + iten->GetTerrain()->GetAllTerrainBBox(boxTerrain); + // get center and radius of the bounding sphere + FLOAT fSphereRadius = Max( boxTerrain.Min().Length(), boxTerrain.Max().Length() ); + FLOAT3D vSphereCenter = iten->en_plPlacement.pl_PositionVector; + // create maximum box for the model (in cases of any rotation) from the sphere + FLOATaabbox3D boxMaxTerrain(vSphereCenter, fSphereRadius); + // if the model box is near the given box + AddTerrainEntity(&iten.Current()); + } + } + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDENTITIESINBOX); +}; + +// update VisTweak flags with given zoning sector +inline void CRenderer::UpdateVisTweaks(CBrushSector *pbsc) +{ + // if not showing vis tweaks + if (!(_wrpWorldRenderPrefs.wrp_bShowVisTweaksOn && _pselbscVisTweaks!=NULL)) { + // add tweaks for this sector + if (pbsc->bsc_ulFlags2&BSCF2_VISIBILITYINCLUDE) { + re_ulVisInclude = pbsc->bsc_ulVisFlags&VISM_INCLUDEEXCLUDE; + } else { + re_ulVisExclude |= pbsc->bsc_ulVisFlags&VISM_INCLUDEEXCLUDE; + } + } +} + +/* Add to rendering all zoning brush sectors that an entity is in. */ +void CRenderer::AddZoningSectorsAroundEntity(CEntity *pen, const FLOAT3D &vEyesPos) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDZONINGSECTORS); + + // works only for non-zoning entities + ASSERT(!(pen->en_ulFlags&ENF_ZONING)); + + // make parameters for minimum sphere to add + re_vdViewSphere = FLOATtoDOUBLE(vEyesPos); + re_dViewSphereR = re_prProjection->NearClipDistanceR()*1.5f; + + CListHead lhToAdd; + // for all sectors this entity is in + {FOREACHSRCOFDST(pen->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // if the sector is not active + if (!pbsc->bsc_lnInActiveSectors.IsLinked()) { + // add to list of sectors to add + lhToAdd.AddTail(pbsc->bsc_lnInActiveSectors); + } + ENDFOR} + + // for each active sector + while (!lhToAdd.IsEmpty()) { + CBrushSector *pbsc = LIST_HEAD(lhToAdd, CBrushSector, bsc_lnInActiveSectors); + // remove it from list of sectors to add + pbsc->bsc_lnInActiveSectors.Remove(); + // add it to final list + AddGivenZoningSector(pbsc); + // if isn't really added (wrong mip) + if (!pbsc->bsc_lnInActiveSectors.IsLinked()) { + // skip it + continue; + } + + // for each portal in the sector + FOREACHINSTATICARRAY(pbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + CBrushPolygon *pbpo = itbpo; + if (!(pbpo->bpo_ulFlags&BPOF_PORTAL)) { + continue; + } + // for each sector related to the portal + {FOREACHDSTOFSRC(pbpo->bpo_rsOtherSideSectors, CBrushSector, bsc_rdOtherSidePortals, pbscRelated) + // if the sector is not active + if (!pbscRelated->bsc_lnInActiveSectors.IsLinked()) { + // if the view sphere is in the sector + if (pbscRelated->bsc_bspBSPTree.TestSphere( + re_vdViewSphere, re_dViewSphereR)>=0) { + // add it to list to add + lhToAdd.AddTail(pbscRelated->bsc_lnInActiveSectors); + } + } + ENDFOR} + } + } + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDZONINGSECTORS); +} + +/* Add to rendering one particular zoning brush sector. */ +void CRenderer::AddGivenZoningSector(CBrushSector *pbsc) +{ + // get the sector's brush mip, brush and entity + CBrushMip *pbmBrushMip = pbsc->bsc_pbmBrushMip; + CBrush3D *pbrBrush = pbmBrushMip->bm_pbrBrush; + ASSERT(pbrBrush!=NULL); + CEntity *penBrush = pbrBrush->br_penEntity; + ASSERT(penBrush!=NULL); + + // if the brush is field brush + if (penBrush->en_RenderType==CEntity::RT_FIELDBRUSH) { + // skip it + return; + } + + // prepare the brush entity for rendering if not yet prepared + PrepareBrush(penBrush); + penBrush->en_pbrBrush->br_ulFlags|=BRF_DRAWFIRSTMIP; + + // here, get only the first brush mip + CBrushMip *pbmRelevant = pbrBrush->GetFirstMip(); + // if it is the one of that sector + if (pbmRelevant==pbmBrushMip) { + // add that sector to active sectors + AddActiveSector(*pbsc); + UpdateVisTweaks(pbsc); + } +} + +/* Add to rendering all zoning brush sectors near a given box in absolute space. */ +void CRenderer::AddZoningSectorsAroundBox(const FLOATaabbox3D &boxNear) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_ADDZONINGSECTORS); + + // get center and radius of the bounding sphere + FLOAT fSphereRadius = boxNear.Size().Length()/2.0f; + FLOAT3D vSphereCenter = boxNear.Center(); + + re_dViewSphereR = re_prProjection->NearClipDistanceR()*1.5f; + re_vdViewSphere = FLOATtoDOUBLE(vSphereCenter); + + // for all entities in world + FOREACHINDYNAMICCONTAINER(re_pwoWorld->wo_cenEntities, CEntity, iten) { + // if the brush is field brush, and field brushes are not rendered + if (iten->en_RenderType==CEntity::RT_FIELDBRUSH + && !_wrpWorldRenderPrefs.IsFieldBrushesOn()) { + // skip it + continue; + } + // if it is not zoning brush + if (iten->en_RenderType!=CEntity::RT_BRUSH && iten->en_RenderType!=CEntity::RT_FIELDBRUSH + ||!(iten->en_ulFlags&ENF_ZONING)) { + // skip it + continue; + } + + CEntity *penBrush = &*iten; + // get its brush + CBrush3D &brBrush = *penBrush->en_pbrBrush; + + /* !!!! this always prepares all brushes in world, + should be moved inside loop, but the mip factor must be calculated + in some other ways. + */ + // prepare the brush entity for rendering if not yet prepared + PrepareBrush(penBrush); + + // get relevant mip factor for that brush and current rendering prefs + CBrushMip *pbm = brBrush.GetBrushMipByDistance( + _wrpWorldRenderPrefs.GetCurrentMipBrushingFactor(brBrush.br_prProjection->MipFactor())); + // if brush mip exists for that mip factor + if (pbm!=NULL) { + // for each sector + FOREACHINDYNAMICARRAY(pbm->bm_abscSectors, CBrushSector, itbsc) { + // if the sector's bounding box has contact with given bounding box, + // and the sector is not hidden + if(itbsc->bsc_boxBoundingBox.HasContactWith(boxNear) + &&!((itbsc->bsc_ulFlags&BSCF_HIDDEN) && !re_bRenderingShadows)) { + // if the sphere is inside the sector + if (itbsc->bsc_bspBSPTree.TestSphere( + FLOATtoDOUBLE(vSphereCenter), FLOATtoDOUBLE(fSphereRadius))>=0) { + + // add that sector to active sectors + AddActiveSector(itbsc.Current()); + UpdateVisTweaks(itbsc); + } + } + } + } + } + _pfRenderProfile.StopTimer(CRenderProfile::PTI_ADDZONINGSECTORS); +} + +void CMirror::Clear(void) +{ + mi_cspoPolygons.Clear(); +} + +// add given polygon to this mirror +void CMirror::AddPolygon(CRenderer &re, CScreenPolygon &spo) +{ + CBrushPolygon *pbpo = spo.spo_pbpoBrushPolygon; + // if not already added + if (!mi_cspoPolygons.IsMember(&spo)) { + // add it + mi_cspoPolygons.Add(&spo); + CBrushSector &bsc = *pbpo->bpo_pbscSector; + // for each edge of the polygon + FOREACHINSTATICARRAY(pbpo->bpo_abpePolygonEdges, CBrushPolygonEdge, itpe) { + // get transformed end vertices + CBrushVertex &bvx0 = *itpe->bpe_pbedEdge->bed_pbvxVertex0; + CBrushVertex &bvx1 = *itpe->bpe_pbedEdge->bed_pbvxVertex1; + INDEX ivx0 = bsc.bsc_abvxVertices.Index(&bvx0); + INDEX ivx1 = bsc.bsc_abvxVertices.Index(&bvx1); + FLOAT3D &tv0 = re.re_avvxViewVertices[bsc.bsc_ivvx0+ivx0].vvx_vView; + FLOAT3D &tv1 = re.re_avvxViewVertices[bsc.bsc_ivvx0+ivx1].vvx_vView; + // check both vertices and update closest vertex + if (tv0(3)>mi_vClosest(3)) { + mi_vClosest = tv0; + } + if (tv1(3)>mi_vClosest(3)) { + mi_vClosest = tv1; + } + } + } +} + +// calculate all needed data from screen polygons +void CMirror::FinishAdding(void) +{ + // clear all data + mi_boxOnScreen = PIXaabbox2D(); + mi_fpixArea = 0; + mi_fpixMaxPolygonArea = 0; + + // for each polygon + FOREACHINDYNAMICCONTAINER(mi_cspoPolygons, CScreenPolygon, itspo) { + CScreenPolygon &spo = *itspo; + + mi_boxOnScreen|=PIX2D(spo.spo_pixMinI, spo.spo_pixMinJ); + mi_boxOnScreen|=PIX2D(spo.spo_pixMaxI, spo.spo_pixMaxJ); + mi_fpixArea += spo.spo_pixTotalArea; + mi_fpixMaxPolygonArea = Max(mi_fpixMaxPolygonArea, FLOAT(spo.spo_pixTotalArea)); + } +} + +/* Add a mirror/portal. */ +void CRenderer::AddMirror(CScreenPolygon &spo) +{ + // if far sentinel + if (spo.spo_pbpoBrushPolygon==NULL) { + // do nothing + return; + } + + // get its index + CBrushPolygon &bpo = *spo.spo_pbpoBrushPolygon; + INDEX iMirrorType = bpo.bpo_bppProperties.bpp_ubMirrorType; + + // if no mirror + if (iMirrorType == 0) { + // do nothing + return; + } + + // if this is last renderer (no more recursion) + if (re_iIndex>=MAX_RENDERERS-1) { + // do nothing + return; + } + + // if mirrors are disabled + if (!_wrpWorldRenderPrefs.wrp_bMirrorsOn) { + // do nothing + return; + } + + // for each mirror + for(INDEX i=0; ibsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + CPlacement3D plLerped = en.GetLerpedPlacement(); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, plLerped.pl_OrientationAngle); + mi.mi_vClosest = FLOAT3D(0,0,-100000); + mi.mi_plPlane = + bpo.bpo_pbplPlane->bpl_plRelative*m + plLerped.pl_PositionVector; + BOOL bSuccess = en.GetMirror(iMirrorType, mi.mi_mp); + // if mirror is valid + if (bSuccess) { + // add the polygon to it + mi.AddPolygon(*this, spo); + // if mirror is not valid + } else { + // remove the mirror + mi.mi_iMirrorType = -1; + } + +} diff --git a/Sources/Engine/Rendering/RenderBrushes.cpp b/Sources/Engine/Rendering/RenderBrushes.cpp new file mode 100644 index 0000000..386a8d8 --- /dev/null +++ b/Sources/Engine/Rendering/RenderBrushes.cpp @@ -0,0 +1,376 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +void CRenderer::DrawBrushPolygonVerticesAndEdges(CBrushPolygon &bpo) +{ + // get transformed polygon's plane + CWorkingPlane &wplPolygonPlane = *bpo.bpo_pbplPlane->bpl_pwplWorking; + CBrushSector &bsc = *bpo.bpo_pbscSector; + CBrushMip *pbm = bsc.bsc_pbmBrushMip; + CBrush3D &br = *pbm->bm_pbrBrush; + INDEX iMinVx = bsc.bsc_ivvx0; + INDEX iMaxVx = bsc.bsc_ivvx0+bsc.bsc_awvxVertices.Count(); + + // set line type and color for edges and vertices + ULONG ulEdgesLineType = EdgeLineType(wplPolygonPlane.wpl_bVisible); + COLOR colorEdges = ColorForEdges(bpo.bpo_colColor, bpo.bpo_pbscSector->bsc_colColor); + COLOR colorVertices = ColorForVertices(bpo.bpo_colColor, bpo.bpo_pbscSector->bsc_colColor); + + if (bpo.IsSelected(BPOF_SELECTED)) { + // for all edges in the polygon + INDEX cttri = bpo.bpo_aiTriangleElements.Count()/3; + for(INDEX itri=0; itriClipLine(vClipped0, vClipped1); + // if the edge remains after clipping to front plane + if (ulClipFlags != LCF_EDGEREMOVED) { + // project the vertices + FLOAT3D v3d0, v3d1; + br.br_prProjection->PostClip(vClipped0, v3d0); + br.br_prProjection->PostClip(vClipped1, v3d1); + // make 2d vertices + FLOAT fI0 = v3d0(1); FLOAT fJ0 = v3d0(2); + FLOAT fI1 = v3d1(1); FLOAT fJ1 = v3d1(2); + + // if the edge is too short + if( Abs(fI1-fI0)<2 && fabs(fJ1-fJ0)<2) { + // skip it + continue; + } + + // draw line between vertices + re_pdpDrawPort->DrawLine((PIX)fI0, (PIX)fJ0, (PIX)fI1, (PIX)fJ1, + colorEdges|CT_OPAQUE, ulEdgesLineType); + } + }} + } + + FOREACHINSTATICARRAY(bpo.bpo_abpePolygonEdges, CBrushPolygonEdge, itpe) { + // get transformed end vertices + CBrushVertex &bvx0 = *itpe->bpe_pbedEdge->bed_pbvxVertex0; + CBrushVertex &bvx1 = *itpe->bpe_pbedEdge->bed_pbvxVertex1; + INDEX ivx0 = bsc.bsc_abvxVertices.Index(&bvx0); + INDEX ivx1 = bsc.bsc_abvxVertices.Index(&bvx1); + FLOAT3D &tv0 = re_avvxViewVertices[bsc.bsc_ivvx0+ivx0].vvx_vView; + FLOAT3D &tv1 = re_avvxViewVertices[bsc.bsc_ivvx0+ivx1].vvx_vView; + + // clip the edge line + FLOAT3D vClipped0 = tv0; + FLOAT3D vClipped1 = tv1; + ULONG ulClipFlags = br.br_prProjection->ClipLine(vClipped0, vClipped1); + // if the edge remains after clipping to front plane + if (ulClipFlags != LCF_EDGEREMOVED) { + // project the vertices + FLOAT3D v3d0, v3d1; + br.br_prProjection->PostClip(vClipped0, v3d0); + br.br_prProjection->PostClip(vClipped1, v3d1); + // make 2d vertices + FLOAT fI0 = v3d0(1); FLOAT fJ0 = v3d0(2); + FLOAT fI1 = v3d1(1); FLOAT fJ1 = v3d1(2); + + // if the edge is too short + if( Abs(fI1-fI0)<2 && fabs(fJ1-fJ0)<2) { + // skip it + continue; + } + + BOOL bDrawVertex0 = ulClipFlags&LCFVERTEX0(LCF_UNCLIPPED) && !(bvx0.bvx_ulFlags&BVXF_DRAWNINWIREFRAME); + BOOL bDrawVertex1 = ulClipFlags&LCFVERTEX1(LCF_UNCLIPPED) && !(bvx1.bvx_ulFlags&BVXF_DRAWNINWIREFRAME); + // if edges should be drawn + if (_wrpWorldRenderPrefs.wrp_ftEdges != CWorldRenderPrefs::FT_NONE) { + // draw line between vertices + re_pdpDrawPort->DrawLine((PIX)fI0, (PIX)fJ0, (PIX)fI1, (PIX)fJ1, + colorEdges|CT_OPAQUE, ulEdgesLineType); + + #if 0 // used for debugging edge directions + DrawArrow(*re_pdpDrawPort, (PIX)fI0, (PIX)fJ0, (PIX)fI1, (PIX)fJ1, + colorEdges|CT_OPAQUE, ulEdgesLineType); + #endif + } + + extern void SelectVertexOnRender(CBrushVertex &bvx, const PIX2D &vpix); + + if (_wrpWorldRenderPrefs.wrp_stSelection== CWorldRenderPrefs::ST_VERTICES) { + // draw them + if (bDrawVertex0) { + SelectVertexOnRender(bvx0, PIX2D((PIX)fI0, (PIX)fJ0)); + if (bvx0.bvx_ulFlags&BVXF_SELECTED) { + PutMoreFatPixel(*re_pdpDrawPort, (PIX)fI0, (PIX)fJ0, C_BLACK|CT_OPAQUE); + } + bvx0.bvx_ulFlags|=BVXF_DRAWNINWIREFRAME; + } + if (bDrawVertex1) { + SelectVertexOnRender(bvx1, PIX2D((PIX)fI1, (PIX)fJ1)); + if (bvx1.bvx_ulFlags&BVXF_SELECTED) { + PutMoreFatPixel(*re_pdpDrawPort, (PIX)fI1, (PIX)fJ1, C_BLACK|CT_OPAQUE); + } + bvx1.bvx_ulFlags|=BVXF_DRAWNINWIREFRAME; + } + } + // if vertices should be drawn + if (_wrpWorldRenderPrefs.wrp_ftVertices != CWorldRenderPrefs::FT_NONE) { + // draw them + if (bDrawVertex0) { + PutFatPixel(*re_pdpDrawPort, (PIX)fI0, (PIX)fJ0, colorVertices); + bvx0.bvx_ulFlags|=BVXF_DRAWNINWIREFRAME; + } + if (bDrawVertex1) { + PutFatPixel(*re_pdpDrawPort, (PIX)fI1, (PIX)fJ1, colorVertices); + bvx1.bvx_ulFlags|=BVXF_DRAWNINWIREFRAME; + } + } + } + } +} + +/* + * Draw vertices and/or edges of a brush + */ +void CRenderer::DrawBrushSectorVerticesAndEdges(CBrushSector &bscSector) +{ + CBrushMip *pbm = bscSector.bsc_pbmBrushMip; + CBrush3D &br = *pbm->bm_pbrBrush; + + // clear all vertex drawn flags + FOREACHINSTATICARRAY(bscSector.bsc_abvxVertices, CBrushVertex, itbvx) { + itbvx->bvx_ulFlags&=~BVXF_DRAWNINWIREFRAME; + } + + // first render visible polygons + FOREACHINSTATICARRAY(bscSector.bsc_abpoPolygons, CBrushPolygon, itpo) { + CBrushPolygon &bpo = *itpo; + CWorkingPlane &wplPolygonPlane = *bpo.bpo_pbplPlane->bpl_pwplWorking; + if (wplPolygonPlane.wpl_bVisible) { + DrawBrushPolygonVerticesAndEdges(bpo); + } + } + // if hidden edges should be drawn + if (_wrpWorldRenderPrefs.wrp_bHiddenLinesOn) { + // render invisible polygons + FOREACHINSTATICARRAY(bscSector.bsc_abpoPolygons, CBrushPolygon, itpo) { + CBrushPolygon &bpo = *itpo; + CWorkingPlane &wplPolygonPlane = *bpo.bpo_pbplPlane->bpl_pwplWorking; + if (!wplPolygonPlane.wpl_bVisible) { + DrawBrushPolygonVerticesAndEdges(bpo); + } + } + } +} +/* Draw edges of a field brush sector. */ +void CRenderer::DrawFieldBrushSectorEdges(CBrushSector &bscSector) +{ + CBrushMip *pbm = bscSector.bsc_pbmBrushMip; + CBrush3D &br = *pbm->bm_pbrBrush; + // for all polygons in sector + FOREACHINSTATICARRAY(bscSector.bsc_abpoPolygons, CBrushPolygon, itpo) { + CBrushPolygon &bpo = *itpo; + + // get transformed polygon's plane + CWorkingPlane &wplPolygonPlane = *bpo.bpo_pbplPlane->bpl_pwplWorking; + + // set line type and color for edges and vertices + ULONG ulEdgesLineType = EdgeLineType(wplPolygonPlane.wpl_bVisible); + COLOR colorEdges = _wrpWorldRenderPrefs.wrp_colEdges; + + // for all edges in the polygon + FOREACHINSTATICARRAY(itpo->bpo_abpePolygonEdges, CBrushPolygonEdge, itpe) { + + // get transformed end vertices + INDEX ivx0 = bscSector.bsc_abvxVertices.Index(itpe->bpe_pbedEdge->bed_pbvxVertex0); + INDEX ivx1 = bscSector.bsc_abvxVertices.Index(itpe->bpe_pbedEdge->bed_pbvxVertex1); + FLOAT3D &tv0 = re_avvxViewVertices[bscSector.bsc_ivvx0+ivx0].vvx_vView; + FLOAT3D &tv1 = re_avvxViewVertices[bscSector.bsc_ivvx0+ivx1].vvx_vView; + + // clip the edge line + FLOAT3D vClipped0 = tv0; + FLOAT3D vClipped1 = tv1; + ULONG ulClipFlags = br.br_prProjection->ClipLine(vClipped0, vClipped1); + // if the edge remains after clipping to front plane + if (ulClipFlags != LCF_EDGEREMOVED) { + // project the vertices + FLOAT3D v3d0, v3d1; + br.br_prProjection->PostClip(vClipped0, v3d0); + br.br_prProjection->PostClip(vClipped1, v3d1); + // make 2d vertices + FLOAT2D v2d0, v2d1; + v2d0(1) = v3d0(1); v2d0(2) = v3d0(2); + v2d1(1) = v3d1(1); v2d1(2) = v3d1(2); + + re_pdpDrawPort->DrawLine((PIX)v2d0(1), (PIX)v2d0(2), + (PIX)v2d1(1), (PIX)v2d1(2), colorEdges|CT_OPAQUE, ulEdgesLineType); + } + } + } +} + +/* Prepare a brush entity for rendering if it is not yet prepared. */ +void CRenderer::PrepareBrush(CEntity *penBrush) +{ + _pfRenderProfile.StartTimer(CRenderProfile::PTI_PREPAREBRUSH); + ASSERT(penBrush!=NULL); + // get its brush + CBrush3D &brBrush = *penBrush->en_pbrBrush; + // if the brush is already active in rendering + if (brBrush.br_lnInActiveBrushes.IsLinked()) { + // skip it + _pfRenderProfile.StopTimer(CRenderProfile::PTI_PREPAREBRUSH); + return; + } + + brBrush.br_ulFlags&=~BRF_DRAWFIRSTMIP; + + // if it has zero sectors and rendering of editor models is enabled + if (brBrush.GetFirstMip()->bm_abscSectors.Count()==0 + && _wrpWorldRenderPrefs.IsEditorModelsOn() && wld_bRenderEmptyBrushes) { + // add it for delayed rendering as a model (will use empty brush model) + AddModelEntity(penBrush); + } + + // add it to list of active brushes + re_lhActiveBrushes.AddTail(brBrush.br_lnInActiveBrushes); + // add it to container of all drawn entities + re_cenDrawn.Add(penBrush); + + // set up a projection for the brush + if (re_bBackgroundEnabled && (penBrush->en_ulFlags & ENF_BACKGROUND)) { + brBrush.br_prProjection = re_prBackgroundProjection; + } else { + brBrush.br_prProjection = re_prProjection; + } + + // prepare the brush projection + if (penBrush->en_ulPhysicsFlags&EPF_MOVABLE) { + // for moving brushes + brBrush.br_prProjection->ObjectPlacementL() = penBrush->GetLerpedPlacement(); + brBrush.br_prProjection->ObjectStretchL() = FLOAT3D(1.0f, 1.0f, 1.0f); + brBrush.br_prProjection->ObjectFaceForwardL() = FALSE; + brBrush.br_prProjection->Prepare(); + } else { + // for static brushes + CProjection3D &pr = *brBrush.br_prProjection; + const FLOATmatrix3D &mRot = penBrush->en_mRotation; + const FLOAT3D &vRot = penBrush->en_plPlacement.pl_PositionVector; + // fixup projection to use placement of this brush + pr.pr_mDirectionRotation = pr.pr_ViewerRotationMatrix*mRot; + pr.pr_RotationMatrix = pr.pr_mDirectionRotation; + brBrush.br_prProjection->ObjectPlacementL() = penBrush->en_plPlacement; + pr.pr_TranslationVector = pr.pr_ObjectPlacement.pl_PositionVector - pr.pr_vViewerPosition; + pr.pr_TranslationVector = pr.pr_TranslationVector*pr.pr_ViewerRotationMatrix; + pr.pr_Prepared = TRUE; + } + + // mark brush as selected if the entity is selected + if (penBrush->IsSelected(ENF_SELECTED)) { + brBrush.br_ulFlags |= BRF_DRAWSELECTED; + } else { + brBrush.br_ulFlags &= ~BRF_DRAWSELECTED; + } + _pfRenderProfile.StopTimer(CRenderProfile::PTI_PREPAREBRUSH); +} + + +/* + * Render wireframe brushes. + */ +void CRenderer::RenderWireFrameBrushes(void) +{ + BOOL bRenderNonField = + _wrpWorldRenderPrefs. wrp_ftEdges != CWorldRenderPrefs::FT_NONE + ||_wrpWorldRenderPrefs.wrp_ftVertices != CWorldRenderPrefs::FT_NONE + ||_wrpWorldRenderPrefs.wrp_stSelection== CWorldRenderPrefs::ST_VERTICES; + + // for all active sectors + {FORDELETELIST(CBrushSector, bsc_lnInActiveSectors, re_lhActiveSectors, itbsc) { + CBrushSector &bsc = *itbsc; + // if invisible + if (bsc.bsc_ulFlags&BSCF_INVISIBLE) { + // skip it + continue; + } + + // if it is field brush + if (bsc.bsc_pbmBrushMip->bm_pbrBrush->br_pfsFieldSettings!=NULL) { + // if fields should be drawn + if (_wrpWorldRenderPrefs.IsFieldBrushesOn()) { + // draw it (all brush sectors in the list are already prepared and transformed) + DrawFieldBrushSectorEdges(bsc); + } + } else { + if (bRenderNonField) { + // draw it (all brush sectors in the list are already prepared and transformed) + DrawBrushSectorVerticesAndEdges(bsc); + } + } + }} +} + +/* + * Compare two polygons for sorting. + */ +static inline int CompareTranslucentPolygons( + const CTranslucentPolygon &tp0, const CTranslucentPolygon &tp1) +{ + if (tp0.tp_fViewerDistancetp1.tp_fViewerDistance) return +1; + else return 0; +} +static int qsort_CompareTranslucentPolygons( const void *pptp0, const void *pptp1) +{ + CTranslucentPolygon &tp0 = **(CTranslucentPolygon **)pptp0; + CTranslucentPolygon &tp1 = **(CTranslucentPolygon **)pptp1; + return +CompareTranslucentPolygons(tp0, tp1); +} + +/* + * Sort a list of translucent polygons. + */ +ScenePolygon *CRenderer::SortTranslucentPolygons(ScenePolygon *pspoFirst) +{ + // if there are no polygons in list + if (pspoFirst==NULL) { + // do nothing + return NULL; + } + + // for each polygon in list + for (ScenePolygon *pspo = pspoFirst; pspo!=NULL; pspo = pspo->spo_pspoSucc) { + // add it to container for sorting + CTranslucentPolygon &tp = re_atcTranslucentPolygons.Push(); + tp.tp_pspoPolygon = pspo; + tp.tp_fViewerDistance = ((CBrushPolygon*)pspo->spo_pvPolygon)->bpo_pbplPlane + ->bpl_pwplWorking->wpl_plView.Distance(); + } + + // sort the container + qsort(re_atcTranslucentPolygons.GetArrayOfPointers(), re_atcTranslucentPolygons.Count(), + sizeof(CTranslucentPolygon *), qsort_CompareTranslucentPolygons); + + // make empty new list of polygons + ScenePolygon *pspoNewFirst = NULL; + // for each polygon in container + for(INDEX iPolygon=0; iPolygonspo_pspoSucc = pspoNewFirst; + pspoNewFirst = pspo; + } + + // clear containr for future use + re_atcTranslucentPolygons.Clear(); + + // return new list + return pspoNewFirst; +} diff --git a/Sources/Engine/Rendering/RenderModels.cpp b/Sources/Engine/Rendering/RenderModels.cpp new file mode 100644 index 0000000..ca638c4 --- /dev/null +++ b/Sources/Engine/Rendering/RenderModels.cpp @@ -0,0 +1,957 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +extern INDEX mdl_iShadowQuality; +// model shadow precision +// 0 = no shadows +// 1 = one simple shadow +// 2 = one complex shadow +// 3 = all shadows + + +/* + * Compare two models for sorting. + */ +static inline int CompareDelayedModels( const CDelayedModel &dm0, const CDelayedModel &dm1) +{ + BOOL bHasAlpha0 = dm0.dm_ulFlags&DMF_HASALPHA; + BOOL bHasAlpha1 = dm1.dm_ulFlags&DMF_HASALPHA; + if (! bHasAlpha0 && bHasAlpha1) return -1; + else if ( bHasAlpha0 && !bHasAlpha1) return +1; + + if (dm0.dm_fDistancedm1.dm_fDistance) return +1; + else return 0; +} + +static int qsort_CompareDelayedModels( const void *ppdm0, const void *ppdm1) +{ + CDelayedModel &dm0 = **(CDelayedModel **)ppdm0; + CDelayedModel &dm1 = **(CDelayedModel **)ppdm1; + return +CompareDelayedModels(dm0, dm1); +} + + +static inline FLOAT IntensityAtDistance( FLOAT fFallOff, FLOAT fHotSpot, FLOAT fDistance) +{ + // intensity is zero if further than fall-off range + if( fDistance>fFallOff) return 0.0f; + // intensity is maximum if closer than hot-spot range + if( fDistancesi_pbpoPolygon==NULL*/) + { // no shadow + _pfRenderProfile.StopTimer(CRenderProfile::PTI_FINDLIGHTS); + return FALSE; + } + // if there is valid shading info + else + { + // if model is above terrain + if(en.en_psiShadingInfo->si_ptrTerrain!=NULL) { + CTerrain *ptrTerrain = en.en_psiShadingInfo->si_ptrTerrain; + // if full bright rendering + if (_wrpWorldRenderPrefs.wrp_shtShadows==CWorldRenderPrefs::SHT_NONE) { + // no model shading + colLight = C_BLACK; + colAmbient = C_GRAY; + vTotalLightDirection = FLOAT3D(1.0f, -1.0f, 1.0f); + _pfRenderProfile.StopTimer(CRenderProfile::PTI_FINDLIGHTS); + return FALSE; + } + + // create floor plane for shadow + ASSERT(en.en_psiShadingInfo->si_lnInPolygon.IsLinked()); + + COLOR colShade = ptrTerrain->GetShadeColor(en.en_psiShadingInfo); + colLight = MulColors(colShade,0xD8D8D8FF); + colAmbient = MulColors(colShade,0xB2B2B2FF); + vTotalLightDirection = FLOAT3D(1.0f, -1.0f, 1.0f); + fTotalShadowIntensity = 0.5f; + plFloorPlane = ptrTerrain->GetPlaneFromPoint(en.en_psiShadingInfo->si_vNearPoint); + + // else if model is above polygon + } else if(en.en_psiShadingInfo->si_pbpoPolygon!=NULL) { + // if full bright rendering + if (_wrpWorldRenderPrefs.wrp_shtShadows==CWorldRenderPrefs::SHT_NONE) { + // no model shading + colLight = C_BLACK; + colAmbient = C_GRAY; + vTotalLightDirection = FLOAT3D(1.0f, -1.0f, 1.0f); + _pfRenderProfile.StopTimer(CRenderProfile::PTI_FINDLIGHTS); + return FALSE; + } + + // create floor plane for shadow + ASSERT(en.en_psiShadingInfo->si_lnInPolygon.IsLinked()); + plFloorPlane = en.en_psiShadingInfo->si_pbpoPolygon->bpo_pbplPlane->bpl_plAbsolute; + + // if full bright polygon + if( en.en_psiShadingInfo->si_pbpoPolygon->bpo_ulFlags&BPOF_FULLBRIGHT) { + // take light from polygon shadow + COLOR col = en.en_psiShadingInfo->si_pbpoPolygon->bpo_colShadow; + colLight = LerpColor( C_BLACK, col, 0.25f); + colAmbient = LerpColor( C_BLACK, col, 0.33f); + fTotalShadowIntensity = NormByteToFloat((en.en_psiShadingInfo->si_pbpoPolygon->bpo_colShadow&CT_AMASK)>>CT_ASHIFT); + vTotalLightDirection = FLOAT3D(1.0f, -1.0f, 1.0f); + _pfRenderProfile.StopTimer(CRenderProfile::PTI_FINDLIGHTS); + return TRUE; + } + + // get the shadow map of the underlying polygon + CBrushShadowMap &bsm = en.en_psiShadingInfo->si_pbpoPolygon->bpo_smShadowMap; + // get ambient light + UBYTE ubAR, ubAG, ubAB; + ColorToRGB( bsm.GetBrushPolygon()->bpo_pbscSector->bsc_colAmbient, ubAR, ubAG, ubAB); + SLONG slSAR=ubAR, slSAG=ubAG, slSAB=ubAB; + + fTotalShadowIntensity = 0.0f; + // for each shadow layer + {FOREACHINLIST(CBrushShadowLayer, bsl_lnInShadowMap, bsm.bsm_lhLayers, itbsl) + { + // get the light source + CLightSource *plsLight = itbsl->bsl_plsLightSource; + + // remember the light parameters + UBYTE ubR, ubG, ubB; + UBYTE ubDAR, ubDAG, ubDAB; + plsLight->GetLightColorAndAmbient( ubR, ubG, ubB, ubDAR, ubDAG, ubDAB); + + // add directional ambient if needed + if( en.en_psiShadingInfo->si_pbpoPolygon->bpo_ulFlags&BPOF_HASDIRECTIONALAMBIENT) { + slSAR += ubDAR; + slSAG += ubDAG; + slSAB += ubDAB; + } + + // get the layer intensity at the point + FLOAT fShadowFactor; + if (en.en_ulFlags&ENF_CLUSTERSHADOWS) { + fShadowFactor = 1.0f; + } else { + fShadowFactor = itbsl->GetLightStrength( en.en_psiShadingInfo->si_pixShadowU, en.en_psiShadingInfo->si_pixShadowV, + en.en_psiShadingInfo->si_fUDRatio, en.en_psiShadingInfo->si_fLRRatio); + } + // skip this light if no intensity + if( fShadowFactor<0.01f) continue; + + const CPlacement3D &plLight = plsLight->ls_penEntity->GetPlacement(); + const FLOAT3D &vLight = plLight.pl_PositionVector; + // get its parameters at the model position + FLOAT3D vDirection; + FLOAT fDistance; + FLOAT fFallOffFactor; + + if (plsLight->ls_ulFlags&LSF_DIRECTIONAL) { + fFallOffFactor = 1.0f; + AnglesToDirectionVector(plLight.pl_OrientationAngle, vDirection); + plModel.pl_PositionVector-vLight; + if (!(en.en_psiShadingInfo->si_pbpoPolygon->bpo_ulFlags&BPOF_HASDIRECTIONALLIGHT)) { + ubR = ubG = ubB = 0; + } + fDistance = 1.0f; + } else { + vDirection = plModel.pl_PositionVector-vLight; + fDistance = vDirection.Length(); + + if (fDistance>plsLight->ls_rFallOff) { + continue; + } else if (fDistancels_rHotSpot) { + fFallOffFactor = 1.0f; + } else { + fFallOffFactor = (plsLight->ls_rFallOff-fDistance)/ + (plsLight->ls_rFallOff-plsLight->ls_rHotSpot); + } + } + // add the light to active lights + struct ModelLight &ml = _amlLights.Push(); + ml.ml_plsLight = plsLight; + // normalize direction vector + if (fDistance>0.001f) { + ml.ml_vDirection = vDirection/fDistance; + } else { + ml.ml_vDirection = FLOAT3D(0.0f,0.0f,0.0f); + } + // special case for substract sector ambient light + if (plsLight->ls_ulFlags&LSF_SUBSTRACTSECTORAMBIENT) { + ubR = (UBYTE)Clamp( (SLONG)ubR-slSAR, 0L, 255L); + ubG = (UBYTE)Clamp( (SLONG)ubG-slSAG, 0L, 255L); + ubB = (UBYTE)Clamp( (SLONG)ubB-slSAB, 0L, 255L); + } + // calculate light intensity + FLOAT fShade = (ubR+ubG+ubB)*(2.0f/(3.0f*255.0f)); + ml.ml_fShadowIntensity = fShade*fShadowFactor; + fTotalShadowIntensity += ml.ml_fShadowIntensity; + // special case for dark light + if (plsLight->ls_ulFlags&LSF_DARKLIGHT) { + ml.ml_fR = -ubR*fFallOffFactor; + ml.ml_fG = -ubG*fFallOffFactor; + ml.ml_fB = -ubB*fFallOffFactor; + } else { + ml.ml_fR = +ubR*fFallOffFactor; + ml.ml_fG = +ubG*fFallOffFactor; + ml.ml_fB = +ubB*fFallOffFactor; + } + }} + + FLOAT fTR=0.0f; FLOAT fTG=0.0f; FLOAT fTB=0.0f; + FLOAT3D vDirection(0.0f,0.0f,0.0f); + // for each active light + {for(INDEX iLight=0; iLight<_amlLights.Count(); iLight++) { + struct ModelLight &ml = _amlLights[iLight]; + // add it to total intensity + fTR += ml.ml_fR; + fTG += ml.ml_fG; + fTB += ml.ml_fB; + // add it to direction vector + FLOAT fWeight = Abs(ml.ml_fR+ml.ml_fG+ml.ml_fB) * (1.0f/(3.0f*255.0f)); + vDirection+=ml.ml_vDirection*fWeight; + }} + // normalize average direction vector + FLOAT fDirection = vDirection.Length(); + if (fDirection>0.001f) { + vDirection /= fDirection; + } else { + vDirection = FLOAT3D(0.0f,0.0f,0.0f); + } + + // for each active light + FLOAT fDR=0.0f; FLOAT fDG=0.0f; FLOAT fDB=0.0f; + {for(INDEX iLight=0; iLight<_amlLights.Count(); iLight++) { + struct ModelLight &ml = _amlLights[iLight]; + // find its contribution to direction vector + const FLOAT fFactor = ClampDn( vDirection%ml.ml_vDirection, 0.0f); + // add it to directional intensity + fDR += ml.ml_fR*fFactor; + fDG += ml.ml_fG*fFactor; + fDB += ml.ml_fB*fFactor; + }} + + // adjust ambient light with gradient if needed + ULONG ulGradientType = en.en_psiShadingInfo->si_pbpoPolygon->bpo_bppProperties.bpp_ubGradientType; + if( ulGradientType>0) { + CGradientParameters gp; + COLOR colGradientPoint; + CEntity *pen = en.en_psiShadingInfo->si_pbpoPolygon->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + if( pen!=NULL && pen->GetGradient( ulGradientType, gp)) { + FLOAT fGrPt = (en.en_psiShadingInfo->si_vNearPoint % gp.gp_vGradientDir - gp.gp_fH0) / (gp.gp_fH1-gp.gp_fH0); + fGrPt = Clamp( fGrPt, 0.0f, 1.0f); + colGradientPoint = LerpColor( gp.gp_col0, gp.gp_col1, fGrPt); + UBYTE ubGR,ubGG,ubGB; + ColorToRGB( colGradientPoint, ubGR,ubGG,ubGB); + // add or substract gradient component to total ambient + if( gp.gp_bDark) { slSAR-=ubGR; slSAG-=ubGG; slSAB-=ubGB; } + else { slSAR+=ubGR; slSAG+=ubGG; slSAB+=ubGB; } + } + } + // clamp ambient component + slSAR = Clamp( slSAR, 0L, 255L); + slSAG = Clamp( slSAG, 0L, 255L); + slSAB = Clamp( slSAB, 0L, 255L); + + // calculate average light properties + SLONG slAR = Clamp( (SLONG)FloatToInt(fTR-fDR) +slSAR, 0L, 255L); + SLONG slAG = Clamp( (SLONG)FloatToInt(fTG-fDG) +slSAG, 0L, 255L); + SLONG slAB = Clamp( (SLONG)FloatToInt(fTB-fDB) +slSAB, 0L, 255L); + SLONG slLR = Clamp( (SLONG)FloatToInt(fDR), 0L, 255L); + SLONG slLG = Clamp( (SLONG)FloatToInt(fDG), 0L, 255L); + SLONG slLB = Clamp( (SLONG)FloatToInt(fDB), 0L, 255L); + colLight = RGBToColor( slLR,slLG,slLB); + colAmbient = RGBToColor( slAR,slAG,slAB); + + // adjust for changed polygon shadow color + COLOR colShadowMap = en.en_psiShadingInfo->si_pbpoPolygon->bpo_colShadow; + CTextureBlending &tbShadow = re_pwoWorld->wo_atbTextureBlendings[ + en.en_psiShadingInfo->si_pbpoPolygon->bpo_bppProperties.bpp_ubShadowBlend]; + COLOR colShadowMapAdjusted = MulColors(colShadowMap, tbShadow.tb_colMultiply); + colLight = MulColors( colLight, colShadowMapAdjusted); + colAmbient = MulColors( colAmbient, colShadowMapAdjusted); + vTotalLightDirection = vDirection; + // else no valid shading info + } else { + // no shadow + _pfRenderProfile.StopTimer(CRenderProfile::PTI_FINDLIGHTS); + return FALSE; + } + } + _pfRenderProfile.StopTimer(CRenderProfile::PTI_FINDLIGHTS); + return TRUE; +} + + +/* + * Render one model with shadow (eventually) + */ +void CRenderer::RenderOneModel( CEntity &en, CModelObject &moModel, const CPlacement3D &plModel, + const FLOAT fDistanceFactor, BOOL bRenderShadow, ULONG ulDMFlags) +{ + // skip invisible models + if( moModel.mo_Stretch == FLOAT3D(0,0,0)) return; + + // do nothing, if rendering shadows and this model doesn't cast cluster shadows + if( re_bRenderingShadows && !(en.en_ulFlags&ENF_CLUSTERSHADOWS)) return; + _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERONEMODEL); + + CPlacement3D plLight; + plLight.pl_PositionVector = plModel.pl_PositionVector + FLOAT3D(3.0f,3.0f,3.0f); + plLight.pl_OrientationAngle = ANGLE3D(AngleDeg(30.0f), AngleDeg(-45.0f),0); + + // create a default light + COLOR colLight = C_GRAY; + COLOR colAmbient = C_dGRAY; + FLOAT3D vTotalLightDirection( 1.0f, -1.0f, 1.0f); + FLOATplane3D plFloorPlane(FLOAT3D( 0.0f, 1.0f, 0.0f), 0.0f); + + BOOL bRenderModelShadow = FALSE; + FLOAT fTotalShadowIntensity = 0.0f; + // if not rendering cluster shadows + if( !re_bRenderingShadows) { + // find model lights + bRenderModelShadow = FindModelLights( en, plModel, colLight, colAmbient, + fTotalShadowIntensity, vTotalLightDirection, plFloorPlane); + } + + // let the entity adjust shading parameters if it wants to + mdl_iShadowQuality = Clamp( mdl_iShadowQuality, 0L, 3L); + const BOOL bAllowShadows = en.AdjustShadingParameters( vTotalLightDirection, colLight, colAmbient); + bRenderModelShadow = (bRenderModelShadow && bAllowShadows && bRenderShadow && mdl_iShadowQuality>0); + + // prepare render model structure + CRenderModel rm; + rm.rm_vLightDirection = vTotalLightDirection; + rm.rm_fDistanceFactor = fDistanceFactor; + rm.rm_colLight = colLight; + rm.rm_colAmbient = colAmbient; + rm.SetObjectPlacement(plModel); + if( ulDMFlags & DMF_FOG) rm.rm_ulFlags |= RMF_FOG; + if( ulDMFlags & DMF_HAZE) rm.rm_ulFlags |= RMF_HAZE; + if( ulDMFlags & DMF_INSIDE) rm.rm_ulFlags |= RMF_INSIDE; + if( ulDMFlags & DMF_INMIRROR) rm.rm_ulFlags |= RMF_INMIRROR; + + // mark that we don't actualy need entire model + if( re_penViewer==&en) { + rm.rm_ulFlags |= RMF_SPECTATOR; + bRenderModelShadow = FALSE; + } + + // TEMP: disable Truform usage on weapon models + if( IsOfClass( &en, "Player Weapons")) rm.rm_ulFlags |= RMF_WEAPON; + + // set tesselation level of models + rm.rm_iTesselationLevel = en.GetMaxTessellationLevel(); + + // prepare CRenderModel structure for rendering of one model + moModel.SetupModelRendering(rm); + + // determine shadow intensity + + fTotalShadowIntensity *= NormByteToFloat( (moModel.mo_colBlendColor&CT_AMASK)>>CT_ASHIFT); + fTotalShadowIntensity = Clamp( fTotalShadowIntensity, 0.0f, 1.0f); + + // if should render shadow for this model + if( bRenderModelShadow && !(en.en_ulFlags&ENF_CLUSTERSHADOWS) && moModel.HasShadow(rm.rm_iMipLevel)) { + // if only simple shadow + if( mdl_iShadowQuality==1) { + // render simple shadow + fTotalShadowIntensity = 0.1f + fTotalShadowIntensity*0.9f; + moModel.AddSimpleShadow( rm, fTotalShadowIntensity, plFloorPlane); + } + // if only one shadow + else if( mdl_iShadowQuality==2) { + // render one shadow of model from shading light direction + const FLOAT fHotSpot = 1E10f; + const FLOAT fFallOff = 1E11f; + CPlacement3D plLight; + plLight.pl_PositionVector = plModel.pl_PositionVector - rm.rm_vLightDirection*1000.0f; + moModel.RenderShadow( rm, plLight, fFallOff, fHotSpot, fTotalShadowIntensity, plFloorPlane); + } + // if full shadows + else if( mdl_iShadowQuality==3) { + // for each active light + for( INDEX iLight=0; iLight<_amlLights.Count(); iLight++) { + struct ModelLight &ml = _amlLights[iLight]; + // skip light if doesn't cast shadows + if( !(ml.ml_plsLight->ls_ulFlags&LSF_CASTSHADOWS)) continue; + // get light parameters + CPlacement3D plLight = ml.ml_plsLight->ls_penEntity->en_plPlacement; + FLOAT fHotSpot = ml.ml_plsLight->ls_rHotSpot; + FLOAT fFallOff = ml.ml_plsLight->ls_rFallOff; + if (ml.ml_plsLight->ls_ulFlags & LSF_DIRECTIONAL) { + fHotSpot = 1E10f; + fFallOff = 1E11f; + FLOAT3D vDirection; + AnglesToDirectionVector( plLight.pl_OrientationAngle, vDirection); + plLight.pl_PositionVector = plModel.pl_PositionVector-(vDirection*1000.0f); + } + // render one shadow of model + const FLOAT fShadowIntensity = Clamp( ml.ml_fShadowIntensity, 0.0f, 1.0f); + moModel.RenderShadow( rm, plLight, fFallOff, fHotSpot, fShadowIntensity, plFloorPlane); + } + } + } + + // if the entity is not the viewer, or this is not primary renderer + if( re_penViewer!=&en) { + // render model + moModel.RenderModel(rm); + // if the entity is viewer + } else { + // just remember the shading info (needed for first-person-weapon rendering) + _vViewerLightDirection = rm.rm_vLightDirection; + _colViewerLight = rm.rm_colLight; + _colViewerAmbient = rm.rm_colAmbient; + } + + // all done + _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERONEMODEL); +} + +/* + * Render one ska model with shadow (eventually) + */ +void CRenderer::RenderOneSkaModel( CEntity &en, const CPlacement3D &plModel, + const FLOAT fDistanceFactor, BOOL bRenderShadow, ULONG ulDMFlags) +{ + // skip invisible models + if( en.GetModelInstance()->mi_vStretch == FLOAT3D(0,0,0)) return; + + // do nothing, if rendering shadows and this model doesn't cast cluster shadows + if( re_bRenderingShadows && !(en.en_ulFlags&ENF_CLUSTERSHADOWS)) return; + _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERONEMODEL); + + CPlacement3D plLight; + plLight.pl_PositionVector = plModel.pl_PositionVector + FLOAT3D(3.0f,3.0f,3.0f); + plLight.pl_OrientationAngle = ANGLE3D(AngleDeg(30.0f), AngleDeg(-45.0f),0); + + // create a default light + COLOR colLight = C_GRAY; + COLOR colAmbient = C_dGRAY; + FLOAT3D vTotalLightDirection( 1.0f, -1.0f, 1.0f); + FLOATplane3D plFloorPlane(FLOAT3D( 0.0f, 1.0f, 0.0f), 0.0f); + + BOOL bRenderModelShadow = FALSE; + FLOAT fTotalShadowIntensity = 0.0f; + // if not rendering cluster shadows + if( !re_bRenderingShadows) { + // find model lights + bRenderModelShadow = FindModelLights( en, plModel, colLight, colAmbient, + fTotalShadowIntensity, vTotalLightDirection, plFloorPlane); + } + + // let the entity adjust shading parameters if it wants to + mdl_iShadowQuality = Clamp( mdl_iShadowQuality, 0L, 3L); + const BOOL bAllowShadows = en.AdjustShadingParameters( vTotalLightDirection, colLight, colAmbient); + bRenderModelShadow = (bRenderModelShadow && bAllowShadows && bRenderShadow && mdl_iShadowQuality>0); + + ULONG &ulRenFlags = RM_GetRenderFlags(); + ulRenFlags = 0; + if( ulDMFlags & DMF_FOG) ulRenFlags |= RMF_FOG; + if( ulDMFlags & DMF_HAZE) ulRenFlags |= RMF_HAZE; + if( ulDMFlags & DMF_INSIDE) ulRenFlags |= RMF_INSIDE; + if( ulDMFlags & DMF_INMIRROR) ulRenFlags |= RMF_INMIRROR; + + // mark that we don't actualy need entire model + if( re_penViewer==&en) { + ulRenFlags |= RMF_SPECTATOR; + bRenderModelShadow = FALSE; + } + + RM_SetObjectPlacement(en.GetLerpedPlacement()); + RM_SetLightColor(colAmbient,colLight); + RM_SetLightDirection(vTotalLightDirection); + + // determine shadow intensity + fTotalShadowIntensity *= NormByteToFloat( (en.GetModelInstance()->GetModelColor()&CT_AMASK)>>CT_ASHIFT); + fTotalShadowIntensity = Clamp( fTotalShadowIntensity, 0.0f, 1.0f); + + // if should render shadow for this model + if( bRenderModelShadow && !(en.en_ulFlags&ENF_CLUSTERSHADOWS) && en.GetModelInstance()->HasShadow(1/*rm.rm_iMipLevel*/)) { + // if only simple shadow + if( mdl_iShadowQuality==1) { + // render simple shadow + fTotalShadowIntensity = 0.1f + fTotalShadowIntensity*0.9f; + en.GetModelInstance()->AddSimpleShadow(fTotalShadowIntensity, plFloorPlane); + } + // if only one shadow + else if( mdl_iShadowQuality==2) { + /* + // render one shadow of model from shading light direction + const FLOAT fHotSpot = 1E10f; + const FLOAT fFallOff = 1E11f; + CPlacement3D plLight; + plLight.pl_PositionVector = plModel.pl_PositionVector - vTotalLightDirection*1000.0f; + // moModel.RenderShadow( rm, plLight, fFallOff, fHotSpot, fTotalShadowIntensity, plFloorPlane); + */ + fTotalShadowIntensity = 0.1f + fTotalShadowIntensity*0.9f; + en.GetModelInstance()->AddSimpleShadow(fTotalShadowIntensity, plFloorPlane); + } + // if full shadows + else if( mdl_iShadowQuality==3) { + /* + // for each active light + for( INDEX iLight=0; iLight<_amlLights.Count(); iLight++) { + struct ModelLight &ml = _amlLights[iLight]; + // skip light if doesn't cast shadows + if( !(ml.ml_plsLight->ls_ulFlags&LSF_CASTSHADOWS)) continue; + // get light parameters + CPlacement3D plLight = ml.ml_plsLight->ls_penEntity->en_plPlacement; + FLOAT fHotSpot = ml.ml_plsLight->ls_rHotSpot; + FLOAT fFallOff = ml.ml_plsLight->ls_rFallOff; + if (ml.ml_plsLight->ls_ulFlags & LSF_DIRECTIONAL) { + fHotSpot = 1E10f; + fFallOff = 1E11f; + FLOAT3D vDirection; + AnglesToDirectionVector( plLight.pl_OrientationAngle, vDirection); + plLight.pl_PositionVector = plModel.pl_PositionVector-(vDirection*1000.0f); + } + // render one shadow of model + const FLOAT fShadowIntensity = Clamp( ml.ml_fShadowIntensity, 0.0f, 1.0f); + // moModel.RenderShadow( rm, plLight, fFallOff, fHotSpot, fShadowIntensity, plFloorPlane); + } + */ + fTotalShadowIntensity = 0.1f + fTotalShadowIntensity*0.9f; + en.GetModelInstance()->AddSimpleShadow(fTotalShadowIntensity, plFloorPlane); + } + } + + // if the entity is not the viewer, or this is not primary renderer + if( re_penViewer!=&en) { + // render model + RM_SetBoneAdjustCallback(&EntityAdjustBonesCallback,&en); + RM_SetShaderParamsAdjustCallback(&EntityAdjustShaderParamsCallback,&en); + RM_RenderSKA(*en.GetModelInstanceForRendering()); + // if the entity is viewer + } else { + // just remember the shading info (needed for first-person-weapon rendering) + _vViewerLightDirection = vTotalLightDirection; + _colViewerLight = colLight; + _colViewerAmbient = colAmbient; + } + + // all done + // _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERONEMODEL); + +} + +/* + * Render models that were kept for delayed rendering. + */ +void CRenderer::RenderModels( BOOL bBackground) +{ + if( _bMultiPlayer) gfx_bRenderModels = 1; // must render in multiplayer mode! + if( !gfx_bRenderModels && !re_bRenderingShadows) return; + + _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERMODELS); + + // sort all the delayed models by distance + qsort(re_admDelayedModels.GetArrayOfPointers(), re_admDelayedModels.Count(), + sizeof(CDelayedModel *), qsort_CompareDelayedModels); + + CAnyProjection3D *papr; + if( bBackground) { + papr = &re_prBackgroundProjection; + } else { + papr = &re_prProjection; + } + + // begin model rendering + if( !re_bRenderingShadows) { + BeginModelRenderingView( *papr, re_pdpDrawPort); + RM_BeginRenderingView( *papr, re_pdpDrawPort); + } else { + BeginModelRenderingMask( *papr, re_pubShadow, re_slShadowWidth, re_slShadowHeight); + RM_BeginModelRenderingMask( *papr, re_pubShadow, re_slShadowWidth, re_slShadowHeight); + } + + + // for each of models that were kept for delayed rendering + for( INDEX iModel=0; iModelGetCurrentColisionBox(boxModel); + // if model has collision + if( en.en_pciCollisionInfo!=NULL ) { + // get its collision box + INDEX iCollision = en.GetCollisionBoxIndex(); + FLOAT3D vMin = en.GetModelInstance()->GetCollisionBoxMin(iCollision); + FLOAT3D vMax = en.GetModelInstance()->GetCollisionBoxMax(iCollision); + // extend the box by the collision box + boxModel|=FLOATaabbox3D(vMin, vMax); + } + // set position of marker at top of the model and it size to be proportional to the model + boxModel.StretchByVector(en.GetModelInstance()->mi_vStretch); + FLOAT fSize = boxModel.Size().Length()*0.3f; + _wrpWorldRenderPrefs.wrp_pmoSelectedEntity->mo_Stretch = FLOAT3D( fSize, fSize, fSize); + CPlacement3D plSelection = en.GetLerpedPlacement(); + plSelection.Translate_OwnSystem( FLOAT3D(0.0f, boxModel.Max()(2), 0.0f)); + + // render the selection model without shadow + RenderOneModel( en, *_wrpWorldRenderPrefs.wrp_pmoSelectedEntity, plSelection, dm.dm_fMipFactor, FALSE, 0); + } + } + else + { + // render the model with its shadow + CModelObject &moModelObject = *dm.dm_pmoModel; + RenderOneModel( en, moModelObject, en.GetLerpedPlacement(), dm.dm_fMipFactor, TRUE, dm.dm_ulFlags); + + // if selected entities should be drawn and this one is selected + if( !re_bRenderingShadows && _wrpWorldRenderPrefs.wrp_stSelection==CWorldRenderPrefs::ST_ENTITIES + && _wrpWorldRenderPrefs.wrp_pmoSelectedEntity!=NULL && en.IsSelected(ENF_SELECTED)) + { // get bounding box of current frame + FLOATaabbox3D boxModel; + moModelObject.GetCurrentFrameBBox(boxModel); + // if model has collision + if( en.en_pciCollisionInfo!=NULL && + (en.GetRenderType()==CEntity::RT_MODEL || en.GetRenderType()==CEntity::RT_EDITORMODEL)) { + // get its collision box + INDEX iCollision = en.GetCollisionBoxIndex(); + FLOAT3D vMin = moModelObject.GetCollisionBoxMin(iCollision); + FLOAT3D vMax = moModelObject.GetCollisionBoxMax(iCollision); + // extend the box by the collision box + boxModel|=FLOATaabbox3D(vMin, vMax); + } + // set position of marker at top of the model and it size to be proportional to the model + boxModel.StretchByVector(moModelObject.mo_Stretch); + FLOAT fSize = boxModel.Size().Length()*0.3f; + _wrpWorldRenderPrefs.wrp_pmoSelectedEntity->mo_Stretch = FLOAT3D( fSize, fSize, fSize); + CPlacement3D plSelection = en.GetLerpedPlacement(); + plSelection.Translate_OwnSystem( FLOAT3D(0.0f, boxModel.Max()(2), 0.0f)); + // render the selection model without shadow + RenderOneModel( en, *_wrpWorldRenderPrefs.wrp_pmoSelectedEntity, plSelection, dm.dm_fMipFactor, FALSE, 0); + } + } + + } + // end model rendering + if( !re_bRenderingShadows) { + EndModelRenderingView(FALSE); // don't restore ortho projection for now + RM_EndRenderingView(FALSE); + } else { + EndModelRenderingMask(); + RM_EndModelRenderingMask(); + } + + + + // done + _pfRenderProfile.StopTimer(CRenderProfile::PTI_RENDERMODELS); +} + + +extern CEntity *_Particle_penCurrentViewer; +extern FLOAT _Particle_fCurrentMip; +extern BOOL _Particle_bHasFog; +extern BOOL _Particle_bHasHaze; + +void Particle_PrepareEntity( FLOAT fMipFactor, BOOL bHasFog, BOOL bHasHaze, CEntity *penViewer) +{ + _Particle_fCurrentMip = fMipFactor; + _Particle_bHasFog = bHasFog; + _Particle_bHasHaze = bHasHaze; + _Particle_penCurrentViewer = penViewer; +} + +/* Render particles for models that were kept for delayed rendering. */ +void CRenderer::RenderParticles(BOOL bBackground) +{ + if( _bMultiPlayer) gfx_bRenderParticles = 1; // must render in multiplayer mode! + if( re_bRenderingShadows || !gfx_bRenderParticles) return; + + _pfRenderProfile.StartTimer(CRenderProfile::PTI_RENDERPARTICLES); + + // prepare gfx library for particles + if (bBackground) { + Particle_PrepareSystem(re_pdpDrawPort, re_prBackgroundProjection); + } else { + Particle_PrepareSystem(re_pdpDrawPort, re_prProjection); + } + + // for each of models that were kept for delayed rendering + for(INDEX iModel=0; iModelSetOrtho(); + + // if there are no flares of flares are off, do nothing + gfx_iLensFlareQuality = Clamp( gfx_iLensFlareQuality, 0L, 3L); + if( gfx_iLensFlareQuality==0 || re_alfiLensFlares.Count()==0) return; + + // get drawport ID + ASSERT( re_pdpDrawPort!=NULL); + const ULONG ulDrawPortID = re_pdpDrawPort->GetID(); + + // for each lens flare of this drawport + {for(INDEX iFlare=0; iFlareIsPointVisible( lfi.lfi_fI, lfi.lfi_fJ, lfi.lfi_fOoK, lfi.lfi_iID, lfi.lfi_iMirrorLevel)) { + lfi.lfi_ulFlags |= LFF_VISIBLE; + } + }} + + // get count of currently existing flares and time + INDEX ctFlares = re_alfiLensFlares.Count(); + const TIME tmNow = _pTimer->GetRealTimeTick(); + + // for each lens flare + INDEX iFlare=0; + while(iFlarels_plftLensFlare==NULL)) || + (lfi.lfi_ulDrawPortID!=ulDrawPortID && lfi.lfi_tmLastFramels_plftLensFlare==NULL) { + continue; + } + // clear active flag for next frame + lfi.lfi_ulFlags &= ~LFF_ACTIVE; + + // fade the flare in/out + #define FLAREINSPEED (0.2f) + #define FLAREOUTSPEED (0.1f) + if( lfi.lfi_ulFlags&LFF_VISIBLE) { + lfi.lfi_fFadeFactor += (tmNow-lfi.lfi_tmLastFrame) / FLAREINSPEED; + } else { + lfi.lfi_fFadeFactor -= (tmNow-lfi.lfi_tmLastFrame) / FLAREOUTSPEED; + } + lfi.lfi_fFadeFactor = Max( Min(lfi.lfi_fFadeFactor, 1.0f), 0.0f); + + // reset timer of flare + lfi.lfi_tmLastFrame = tmNow; + // skip if the flare is invisible + if( lfi.lfi_fFadeFactor<0.01f) continue; + + // calculate general flare factors + FLOAT fScreenSizeI = re_pdpDrawPort->GetWidth(); + FLOAT fScreenSizeJ = re_pdpDrawPort->GetHeight(); + FLOAT fScreenCenterI = fScreenSizeI*0.5f; + FLOAT fScreenCenterJ = fScreenSizeJ*0.5f; + FLOAT fLightI = lfi.lfi_fI; + FLOAT fLightJ = lfi.lfi_fJ; + FLOAT fIPositionFactor = (fLightI-fScreenCenterI)/fScreenSizeI; + FLOAT fReflectionDirI = fScreenCenterI-fLightI; + FLOAT fReflectionDirJ = fScreenCenterJ-fLightJ; + UBYTE ubR, ubG, ubB; + lfi.lfi_plsLightSource->GetLightColor(ubR, ubG, ubB); + UBYTE ubI = (ULONG(ubR)+ULONG(ubG)+ULONG(ubB))/3; + FLOAT fReflectionDistance = sqrt(fReflectionDirI*fReflectionDirI+fReflectionDirJ*fReflectionDirJ); + FLOAT fOfCenterFadeFactor = 1.0f-2.0f*fReflectionDistance/fScreenSizeI; + fOfCenterFadeFactor = Max(fOfCenterFadeFactor, 0.0f); + + FLOAT fFogHazeFade = 1.0f; + // if in haze + if( lfi.lfi_ulFlags&LFF_HAZE) { + // get haze strength at light position + FLOAT fS = (-lfi.lfi_vProjected(3)+_haze_fAdd)*_haze_fMul; + FLOAT fHazeStrength = NormByteToFloat(GetHazeAlpha(fS)); + // fade flare with haze + fFogHazeFade *= 1-fHazeStrength; + } + // if in fog + if( lfi.lfi_ulFlags&LFF_FOG) { + // get fog strength at light position + GFXTexCoord tex; + tex.s = -lfi.lfi_vProjected(3)*_fog_fMulZ; + tex.t = (lfi.lfi_vProjected%_fog_vHDirView+_fog_fAddH)*_fog_fMulH; + FLOAT fFogStrength = NormByteToFloat(GetFogAlpha(tex)); + // fade flare with fog + fFogHazeFade *= 1-fFogStrength; + } + + // get number of flares to render for this light + CStaticArray &aolf = lfi.lfi_plsLightSource->ls_plftLensFlare->lft_aolfFlares; + INDEX ctReflections = aolf.Count(); + // clamp number reflections if required + if( gfx_iLensFlareQuality<2 || _wrpWorldRenderPrefs.wrp_lftLensFlares==CWorldRenderPrefs::LFT_SINGLE_FLARE) { + ctReflections = 1; + } + + // for each flare in the lens flare effect + {for(INDEX iReflection=0; iReflectionls_rFallOff*olf.oft_fFallOffFactor, + lfi.lfi_plsLightSource->ls_rHotSpot*olf.oft_fFallOffFactor, + lfi.lfi_fDistance); + fFadeFactor*=fFogHazeFade; + if (olf.olf_ulFlags&OLF_FADEOFCENTER) { + fFadeFactor*=fOfCenterFadeFactor; + } + + FLOAT fSizeIFactor = fScreenSizeI; + if (olf.olf_ulFlags&OLF_FADESIZE) { + fSizeIFactor *= fFadeFactor; + } + FLOAT fIntensityFactor = olf.olf_fLightAmplification; + if (olf.olf_ulFlags&OLF_FADEINTENSITY) { + fIntensityFactor *= fFadeFactor; + } + + // calculate flare size + FLOAT fSizeI = olf.olf_fSizeIOverScreenSizeI*fSizeIFactor; + FLOAT fSizeJ = olf.olf_fSizeJOverScreenSizeI*fSizeIFactor; + + // skip if this flare is invisible + if( fIntensityFactor<0.01f || fSizeI<2.0f || fSizeJ<2.0f) continue; + + // determine color + FLOAT fThisR = (ubR + (FLOAT(ubI)-ubR)*olf.olf_fLightDesaturation)*fIntensityFactor; + FLOAT fThisG = (ubG + (FLOAT(ubI)-ubG)*olf.olf_fLightDesaturation)*fIntensityFactor; + FLOAT fThisB = (ubB + (FLOAT(ubI)-ubB)*olf.olf_fLightDesaturation)*fIntensityFactor; + UBYTE ubThisR = Min( fThisR, 255.0f); + UBYTE ubThisG = Min( fThisG, 255.0f); + UBYTE ubThisB = Min( fThisB, 255.0f); + COLOR colBlending = RGBToColor( ubThisR,ubThisG,ubThisB); + + // render the flare + re_pdpDrawPort->RenderLensFlare( + &olf.olf_toTexture, + fLightI+olf.olf_fReflectionPosition*fReflectionDirI, + fLightJ+olf.olf_fReflectionPosition*fReflectionDirJ, + fSizeI, fSizeJ, + olf.olf_aRotationFactor*fIPositionFactor, + colBlending); + }} // for each flare in the lens flare effect + + // if screen glare is on + CLensFlareType &lft = *lfi.lfi_plsLightSource->ls_plftLensFlare; + FLOAT fGlearCompression = lft.lft_fGlareCompression; + if( gfx_iLensFlareQuality>2 + && _wrpWorldRenderPrefs.wrp_lftLensFlares >= CWorldRenderPrefs::LFT_REFLECTIONS_AND_GLARE + && lft.lft_fGlareIntensity>0.01f) { + // calculate glare factor for current position + FLOAT fIntensity = IntensityAtDistance( lfi.lfi_plsLightSource->ls_rFallOff*lft.lft_fGlareFallOffFactor, + lfi.lfi_plsLightSource->ls_rHotSpot*lft.lft_fGlareFallOffFactor, + lfi.lfi_fDistance); + FLOAT fCenterFactor = (1-fOfCenterFadeFactor); + FLOAT fGlare = lft.lft_fGlareIntensity*fIntensity + * (exp(1.0f/(1.0f+fGlearCompression*fCenterFactor*fCenterFactor)) -1.0f) / (exp(1.0f)-1.0f); + ULONG ulGlareA = ClampUp( NormFloatToByte(fGlare), 255UL); + // if there is any relevant glare + if( ulGlareA>1) { + // calculate glare color + FLOAT fGlareR = (ubR + (FLOAT(ubI)-ubR) *lft.lft_fGlareDesaturation); + FLOAT fGlareG = (ubG + (FLOAT(ubI)-ubG) *lft.lft_fGlareDesaturation); + FLOAT fGlareB = (ubB + (FLOAT(ubI)-ubB) *lft.lft_fGlareDesaturation); + FLOAT fMax = Max( fGlareR, Max(fGlareG, fGlareB)); + FLOAT fBrightFactor = 255.0f/fMax; + fGlareR *= fBrightFactor; + fGlareG *= fBrightFactor; + fGlareB *= fBrightFactor; + ULONG ulGlareR = ClampUp( FloatToInt(fGlareR), 255L); + ULONG ulGlareG = ClampUp( FloatToInt(fGlareG), 255L); + ULONG ulGlareB = ClampUp( FloatToInt(fGlareB), 255L); + // add the glare to screen blending + re_pdpDrawPort->dp_ulBlendingRA += ulGlareR*ulGlareA; + re_pdpDrawPort->dp_ulBlendingGA += ulGlareG*ulGlareA; + re_pdpDrawPort->dp_ulBlendingBA += ulGlareB*ulGlareA; + re_pdpDrawPort->dp_ulBlendingA += ulGlareA; + } + } + }} +} diff --git a/Sources/Engine/Rendering/RenderProfile.cpp b/Sources/Engine/Rendering/RenderProfile.cpp new file mode 100644 index 0000000..d2d9913 --- /dev/null +++ b/Sources/Engine/Rendering/RenderProfile.cpp @@ -0,0 +1,75 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +// profile form for profiling world editing +CRenderProfile rpRenderProfile; +CProfileForm &_pfRenderProfile = rpRenderProfile; + +// profile form for profiling world rendering +CRenderProfile::CRenderProfile(void) : + CProfileForm ("Rendering", "frames", CRenderProfile::PCI_COUNT, CRenderProfile::PTI_COUNT) +{ + // initialize rendering profile form + SETTIMERNAME(CRenderProfile::PTI_RENDERING, "rendering", ""); + SETTIMERNAME(CRenderProfile::PTI_INITIALIZATION, " initialization", ""); + SETTIMERNAME(CRenderProfile::PTI_ADDINITIAL, " adding initial sectors", ""); + SETTIMERNAME(CRenderProfile::PTI_CLEANUP, " clean-up", ""); + SETTIMERNAME(CRenderProfile::PTI_RENDERSCENE, " RenderScene()", ""); + SETTIMERNAME(CRenderProfile::PTI_RENDERMODELS, " RenderModels()", ""); + SETTIMERNAME(CRenderProfile::PTI_RENDERONEMODEL, " RenderOneModel()", ""); + SETTIMERNAME(CRenderProfile::PTI_FINDSHADINGINFO, " FindShadingInfo() during RenderOneModel()", "finding"); + SETTIMERNAME(CRenderProfile::PTI_FINDLIGHTS, " searching for lights in RenderOneModel()", ""); + SETTIMERNAME(CRenderProfile::PTI_RENDERPARTICLES, " RenderParticles()", ""); + + SETTIMERNAME(CRenderProfile::PTI_SCANEDGES, " ScanEdges()", ""); + SETTIMERNAME(CRenderProfile::PTI_INITSCANEDGES, " InitScanEdges()", ""); + SETTIMERNAME(CRenderProfile::PTI_ENDSCANEDGES, " EndScanEdges()", ""); + SETTIMERNAME(CRenderProfile::PTI_SCANONELINE, " ScanOneLine()", ""); + SETTIMERNAME(CRenderProfile::PTI_PASSPORTAL, " PassPortal()", ""); + SETTIMERNAME(CRenderProfile::PTI_ADDSPANSTOSCENE, " AddSpansToScene()", ""); + SETTIMERNAME(CRenderProfile::PTI_PROCESSTRANSPORTAL, " processing translucent portals", ""); + SETTIMERNAME(CRenderProfile::PTI_ADDTRANSSPANSTOSCENE, " AddTranslucentSpansToScene()", ""); + SETTIMERNAME(CRenderProfile::PTI_STEPANDRESORT, " StepAndResortActiveList()", ""); + SETTIMERNAME(CRenderProfile::PTI_REMREMLIST, " RemRemoveListFromActiveList()", ""); + SETTIMERNAME(CRenderProfile::PTI_ADDADDLIST, " AddAddListToActiveList()", ""); + + SETTIMERNAME(CRenderProfile::PTI_ADDNONZONINGBRUSH, " AddNonZoningBrush()", ""); + SETTIMERNAME(CRenderProfile::PTI_ADDMODELENTITY, " AddModelEntity()", ""); + SETTIMERNAME(CRenderProfile::PTI_ADDZONINGSECTORS, " AddZoningSectors()", ""); + SETTIMERNAME(CRenderProfile::PTI_ADDENTITIESINSECTOR, " AddEntitiesInSector()", ""); + SETTIMERNAME(CRenderProfile::PTI_ADDENTITIESINBOX, " AddEntitiesInBox()", ""); + + SETTIMERNAME(CRenderProfile::PTI_PREPAREBRUSH, " PrepareBrush()", ""); + SETTIMERNAME(CRenderProfile::PTI_ADDSECTOR, " AddSector()", ""); + SETTIMERNAME(CRenderProfile::PTI_TRANSFORMVERTICES, " transforming vertices", "vertex"); + SETTIMERNAME(CRenderProfile::PTI_TRANSFORMPLANES, " transforming planes", "plane"); + SETTIMERNAME(CRenderProfile::PTI_MAKENONDETAILSCREENPOLYGONS, " makenondetailscreenpolygons", ""); + SETTIMERNAME(CRenderProfile::PTI_CLIPTOALLPLANES, " cliptoallplanes", ""); + SETTIMERNAME(CRenderProfile::PTI_PROJECTVERTICES, " projectvertices", ""); + SETTIMERNAME(CRenderProfile::PTI_MAKEFINALPOLYGONEDGES, " makefinalpolygonedges", ""); + SETTIMERNAME(CRenderProfile::PTI_ADDSCREENEDGES, " addscreenedges", ""); + SETTIMERNAME(CRenderProfile::PTI_MAKEDETAILSCREENPOLYGONS, " makedetailscreenpolygons", ""); + SETTIMERNAME(CRenderProfile::PTI_MAKESCREENEDGE, " MakeScreenEdge()", "edge"); + SETTIMERNAME(CRenderProfile::PTI_ADDEDGETOADDLIST, " AddEdgeToAddList()", "adding"); + SETTIMERNAME(CRenderProfile::PTI_MAKESCREENPOLYGON, " MakeScreenPolygon()", "polygon"); + SETTIMERNAME(CRenderProfile::PTI_REDRAWVIEW, "CSCapeLibrary::RedrawView()", ""); + SETTIMERNAME(CRenderProfile::PTI_RENDERINTERFACE, " CPlayerEntity::RenderInterface()", ""); + + SETCOUNTERNAME(CRenderProfile::PCI_TRANSFORMEDSECTORS, "transformed sectors"); + SETCOUNTERNAME(CRenderProfile::PCI_TRANSFORMEDVERTICES, "transformed vertices"); + SETCOUNTERNAME(CRenderProfile::PCI_TRANSFORMEDPLANES, "transformed planes"); + SETCOUNTERNAME(CRenderProfile::PCI_TRANSFORMEDEDGES, "transformed edges"); + SETCOUNTERNAME(CRenderProfile::PCI_NONDETAILPOLYGONS, "nondetail polygons"); + SETCOUNTERNAME(CRenderProfile::PCI_DETAILPOLYGONS, "detail polygons"); + + SETCOUNTERNAME(CRenderProfile::PCI_EDGETRANSITIONS, "edge transitions"); + SETCOUNTERNAME(CRenderProfile::PCI_SWAPEDGETRANSITIONS, "edge transitions with swap"); + SETCOUNTERNAME(CRenderProfile::PCI_OVERALLSCANLINES, "total scan lines"); + SETCOUNTERNAME(CRenderProfile::PCI_SCANLINEPORTALRETRIES, "portal scan line retries"); + SETCOUNTERNAME(CRenderProfile::PCI_COHERENTSCANLINES, "coherent scan lines"); + SETCOUNTERNAME(CRenderProfile::PCI_SPANS, "total generated spans"); + SETCOUNTERNAME(CRenderProfile::PCI_TRAPEZOIDS, "total generated trapezoids"); +} diff --git a/Sources/Engine/Rendering/RenderProfile.h b/Sources/Engine/Rendering/RenderProfile.h new file mode 100644 index 0000000..24c52f7 --- /dev/null +++ b/Sources/Engine/Rendering/RenderProfile.h @@ -0,0 +1,76 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef __ENGINE_BASE_PROFILING_H__ +#include +#endif + +class CRenderProfile : public CProfileForm { +public: + // indices for profiling counters and timers + enum ProfileTimerIndex { + PTI_RENDERING, // overall rendering time for CRenderer + PTI_INITIALIZATION, // time spent in initialization + PTI_ADDINITIAL, // time spent adding initial sectors + PTI_CLEANUP, // time spent in destructor + PTI_RENDERSCENE, // time spent in RenderScene() + PTI_RENDERMODELS, // time spent in RenderModels() + PTI_RENDERONEMODEL, // time spent in RenderOneModel() + PTI_FINDSHADINGINFO, // time spent in FindShadingInfo() during RenderOneModel() + PTI_FINDLIGHTS, // time spent in searching for lights in RenderOneModel() + PTI_RENDERPARTICLES, // time spent in RenderParticles() + + PTI_SCANEDGES, // time spent in ScanEdges() + PTI_INITSCANEDGES, // time spent in InitScanEdges() + PTI_ENDSCANEDGES, // time spent in EndScanEdges() + PTI_SCANONELINE, // time spent in ScanOneLine() + PTI_PASSPORTAL, // time spent in PassPortal() + PTI_ADDSPANSTOSCENE, // time spent in AddSpansToScene() + PTI_PROCESSTRANSPORTAL, // time spent processing translucent portals + PTI_ADDTRANSSPANSTOSCENE,// time spent in AddTranslucentSpansToScene() + PTI_STEPANDRESORT, // time spent in StepAndResortActiveList() + PTI_REMREMLIST, // time spent in RemRemoveListFromActiveList() + PTI_ADDADDLIST, // time spent in AddAddListToActiveList() + PTI_ADDNONZONINGBRUSH, // time spent in AddNonZoningBrush() + PTI_ADDMODELENTITY, // time spent in AddModelEntity() + PTI_ADDZONINGSECTORS, // time spent in AddZoningSectors() + PTI_ADDENTITIESINSECTOR, // time spent in AddEntitiesInSector() + PTI_ADDENTITIESINBOX, // time spent in AddEntitiesInBox() + PTI_PREPAREBRUSH, // time spent in PrepareBrush() + PTI_ADDSECTOR, // time spent in AddSector() + PTI_TRANSFORMVERTICES, // time spent transforming sector vertices + PTI_TRANSFORMPLANES, // time spent transforming sector planes + PTI_MAKENONDETAILSCREENPOLYGONS, + PTI_CLIPTOALLPLANES, + PTI_PROJECTVERTICES, + PTI_MAKEFINALPOLYGONEDGES, + PTI_ADDSCREENEDGES, + PTI_MAKEDETAILSCREENPOLYGONS, + PTI_MAKESCREENEDGE, // time spent in MakeScreenEdge() + PTI_ADDEDGETOADDLIST, // time spent in AddEdgeToAddList() + PTI_MAKESCREENPOLYGON, // time spent in MakeScreenPolygon() + PTI_REDRAWVIEW, // time spent in CSCapeLibrary::RedrawView() + PTI_RENDERINTERFACE, // time spent in CPlayerEntity::RenderInterface() + PTI_COUNT + }; + enum ProfileCounterIndex { + PCI_POLYGONSRENDERED, // total number of polygons rendered + + PCI_TRANSFORMEDSECTORS, // total number of transformed sectors + PCI_TRANSFORMEDVERTICES, // total number of transformed vertices + PCI_TRANSFORMEDPLANES, // total number of transformed planes + PCI_TRANSFORMEDEDGES, // total number of transformed edges + PCI_NONDETAILPOLYGONS, + PCI_DETAILPOLYGONS, + + PCI_EDGETRANSITIONS, // total number of edge transitions during scanning + PCI_SWAPEDGETRANSITIONS, // number of edge transitions with swap polygons + PCI_OVERALLSCANLINES, // total number of scan lines processed + PCI_SCANLINEPORTALRETRIES, // scan line retries due to portal encounters + PCI_COHERENTSCANLINES, // scan lines that were coherent with previous one + PCI_SPANS, // total generated spans + PCI_TRAPEZOIDS, // total generated trapezoids + PCI_COUNT + }; + + CRenderProfile(void); +}; diff --git a/Sources/Engine/Rendering/Render_internal.h b/Sources/Engine/Rendering/Render_internal.h new file mode 100644 index 0000000..94d0c0b --- /dev/null +++ b/Sources/Engine/Rendering/Render_internal.h @@ -0,0 +1,564 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_RENDER_INTERNAL_H +#define SE_INCL_RENDER_INTERNAL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef ALIGNED_NEW_AND_DELETE +#ifdef NDEBUG +#define ALIGNED_NEW_AND_DELETE(align) \ + void *operator new[] (size_t size) { return AllocMemoryAligned(size, align); }; \ + void operator delete[] (void* ptr) { FreeMemoryAligned(ptr); }; +#else +#define ALIGNED_NEW_AND_DELETE(align) +#endif + +// type of edge orientation on screen +enum LineDirectionType { + LDT_ASCENDING, // edge is going bottom to top + LDT_DESCENDING, // edge is going top to bottom + LDT_HORIZONTAL, // edge is horizontal +}; + +// polygon direction flags +#define PDF_FLIPEDGESPRE (1UL<<0) // flip edges before clipping +#define PDF_FLIPEDGESPOST (1UL<<1) // flip edges after clipping +#define PDF_POLYGONVISIBLE (1UL<<2) // polygon is visible + +/* + * A polygon projected to screen, clipped and used in rendering. + */ +class CScreenPolygon { +public: + // planar gradients of depth for this polygon used in sorting + CPlanarGradients spo_pgOoK; + ScenePolygon spo_spoScenePolygon; // holder for scene data of this polygon + + CBrushPolygon *spo_pbpoBrushPolygon; + BOOL spo_bActive; // set if active in rendering + + CListNode spo_lnInStack; // node in surface stack + INDEX spo_iInStack; // counter of additions to surface stack + class CScreenEdge *spo_psedSpanStart; // edge where polygon's span started + UBYTE spo_ubIllumination; // illumination of the polygon (when rendering shadows) + UBYTE spo_ubSpanAdded; // set if polygon has created any span yet + UBYTE spo_ubDirectionFlags; // set if should invert polygon edges + UBYTE spo_ubDummy; + INDEX spo_iEdgeVx0; // first vertex of edge vertices + INDEX spo_ctEdgeVx; // number of vertices of edge vertices + INDEX spo_ised0; // first screen edge + INDEX spo_ctsed; // number of screen edges + PIX spo_pixMinI; // bounding box on screen + PIX spo_pixMinJ; + PIX spo_pixMaxI; + PIX spo_pixMaxJ; + PIX spo_pixTotalArea; // sum of all visible spans + + /* Default constructor. */ + CScreenPolygon(void) { + #ifndef NDEBUG + spo_iInStack = 0; + #endif + }; + /* Destructor. */ + inline ~CScreenPolygon(void); + + /* Test if this polygon is a portal. */ + inline BOOL IsPortal(void) { + return spo_pbpoBrushPolygon!=NULL && spo_pbpoBrushPolygon->bpo_ulFlags&BPOF_RENDERASPORTAL; + }; + /* Clear the object. */ + inline void Clear(void) {}; +}; + +// transformed vertex used in rendering +class CViewVertex { +public: + FLOAT3D vvx_vView; // coordinates in view space + FLOAT vvx_fD; // distance from clip plane + ULONG vvx_ulOutcode; // outcode of the vertex -> bits set if polygon is behind the plane + FLOAT vvx_fI; // screen-space coordinates + FLOAT vvx_fJ; +}; + +/* + * An edge projected to screen, clipped and used in rendering. + */ +class CScreenEdge { +public: +// first block is data needed for ASER + FIX16_16 sed_xI; // top I coordinate + FIX16_16 sed_xIStep; // I coordinate step per scan line + + CScreenPolygon *sed_pspo; // polygon + + BOOL sed_bAdded; // set if added to add/active list + CScreenEdge *sed_psedNextRemove; // node in remove list + +// second block is data needed for clipping etc. + enum LineDirectionType sed_ldtDirection; // edge orientation on screen + + PIX sed_pixTopJ; // top and bottom J coordinates of the edge + PIX sed_pixBottomJ; + + ALIGNED_NEW_AND_DELETE(32); + /* Clear the object. */ + inline void Clear(void) {}; +}; + +#define ACE_REMOVED 0x7FFFFFFF // I coordinate for removed edges +/* + * Structure used for sorting edges in active list + */ +class CActiveEdge { +public: + FIX16_16 ace_xI; // top I coordinate + FIX16_16 ace_xIStep; // I coordinate step per scan line + CScreenEdge *ace_psedEdge; // the edge + ULONG ace_ulDummy; // alignment to 16 bytes + + ALIGNED_NEW_AND_DELETE(32); + + inline CActiveEdge(void) {}; + inline CActiveEdge(CScreenEdge *psed) + : ace_xI(psed->sed_xI) + , ace_xIStep(psed->sed_xIStep) + , ace_psedEdge(psed) + {}; + inline void Clear(void) {}; +}; + +/* + * Structure used for sorting edges in add list + */ +class CAddEdge { // size is 16 bytes +public: + FIX16_16 ade_xI; // top I coordinate + CListNode ade_lnInAdd; // node in add list + CScreenEdge *ade_psedEdge; // the edge + + ALIGNED_NEW_AND_DELETE(32); + + inline CAddEdge(void) {}; + inline CAddEdge(CScreenEdge *psed) + : ade_xI(psed->sed_xI) + , ade_psedEdge(psed) + {}; + inline void Clear(void) { + ade_lnInAdd.ln_Succ = NULL; + ade_lnInAdd.ln_Pred = NULL; + }; +}; + +/* + * A span of a polygon on current scan line. + */ +class CSpan { +public: + CScreenEdge *sp_psedEdge0; // edge left of this span + CScreenEdge *sp_psedEdge1; // edge right of this span + CScreenPolygon *sp_pspoPolygon; // polygon of this span + + /* Clear the object. */ + inline void Clear(void) {}; +}; + +/* We must declare dummy clear functions for external classes that + * get stored in dynamic stack arrays. + */ +inline void Clear(Vector &dummy) {}; + +/* + * Model that is to be rendered in this frame. + */ +#define DMF_HASALPHA (1UL<<0) // if the model uses alpha blending (sorted last) +#define DMF_VISIBLE (1UL<<1) // really visible (particles are rendered even for invisibles) +#define DMF_FOG (1UL<<2) // in fog +#define DMF_HAZE (1UL<<3) // in haze +#define DMF_INSIDE (1UL<<4) // completely inside frustum (not clipped) +#define DMF_INMIRROR (1UL<<5) // completely inside mirror (not clipped) + +class CDelayedModel { +public: + FLOAT dm_fDistance; // Z distance from viewer (for sorting) + FLOAT dm_fMipFactor; // mip factor of the model + ULONG dm_ulFlags; // various flags + CEntity *dm_penModel; // the model entity + CModelObject *dm_pmoModel; // model of the entity + __forceinline void Clear(void) {}; +}; + +/* + * Lens flare that could rendered in this frame. + */ +#define LFF_ACTIVE (1UL<<0) // set if was active in this frame +#define LFF_VISIBLE (1UL<<1) // set if the light source is visible in this frame +#define LFF_FOG (1UL<<2) // in fog +#define LFF_HAZE (1UL<<3) // in haze +class CLensFlareInfo { +public: + INDEX lfi_iID; // unique ID of a lens flare info + ULONG lfi_ulDrawPortID; // unique ID of the lens flare's drawport + CLightSource *lfi_plsLightSource; // the light source + FLOAT3D lfi_vProjected; // coordinates in view space (for fog and haze) + FLOAT lfi_fI, lfi_fJ; // position of light source on screen in this frame + FLOAT lfi_fDistance; // distance of light source from viewer in this frame + FLOAT lfi_fOoK; // depth of light source in this frame + TIME lfi_tmLastFrame; // last time it was animated + INDEX lfi_iMirrorLevel; // mirror recursion level in which the flare is + FLOAT lfi_fFadeFactor; // current fade ratio (0..1) + ULONG lfi_ulFlags; // various flags + + __forceinline void Clear(void) { }; +}; + +class CTranslucentPolygon { +public: + FLOAT tp_fViewerDistance; + ScenePolygon *tp_pspoPolygon; + __forceinline void Clear(void) {}; +}; + +class CMirror { +public: + INDEX mi_iMirrorType; // mirror index + FLOATplane3D mi_plPlane; // plane in absolute space + FLOAT3D mi_vClosest; // point closest to viewer, in view space + PIXaabbox2D mi_boxOnScreen; // bounding box of the mirror on screen + FLOAT mi_fpixArea; // total area of mirror + FLOAT mi_fpixMaxPolygonArea; // max area of single polygon of mirror + + // parameters + CMirrorParameters mi_mp; + + // for mirrors + CDynamicContainer mi_cspoPolygons; // polygons of the mirror + + void Clear(void); + + // add given polygon to this mirror + void AddPolygon(CRenderer &re, CScreenPolygon &spo); + // calculate all needed data from screen polygons + void FinishAdding(void); +}; + +/* + * Object that performs rendering of a scene as seen by an entity. + */ +class CRenderer { +public: +// implementation: + INDEX re_iIndex; // index of this renderer in static array + CWorld *re_pwoWorld; // world to render + CDrawPort *re_pdpDrawPort; // drawport that is drawn on + // where the spans are emitted + struct ScenePolygon *re_pspoFirst; + struct ScenePolygon *re_pspoFirstTranslucent; + struct ScenePolygon *re_pspoFirstBackground; + struct ScenePolygon *re_pspoFirstBackgroundTranslucent; + + FLOATaabbox3D re_boxViewer; // bounding box of viewer + CEntity *re_penViewer; // entity that is viewed from + CDynamicContainer *re_pcspoViewPolygons; // polygons that is viewed from (for mirrors) + CAnyProjection3D re_prProjection; // projection to viewer space + DOUBLE3D re_vdViewSphere; + DOUBLE re_dViewSphereR; + + // used for fixing problems with extra trapezoids generated on t-junctions + FLOAT re_fEdgeOffsetI; + FLOAT re_fEdgeAdjustK; + + BOOL re_bBackgroundEnabled; // set if should render background objects in background + CEntity *re_penBackgroundViewer; // background viewer entity + CAnyProjection3D re_prBackgroundProjection; // projection for background + + PIX re_pixSizeI; + FLOAT re_fMinJ; // top row + FLOAT re_fMaxJ; // bottom row+1 + FLOATaabbox2D re_fbbClipBox; // clip rectangle on screen + + BOOL re_bRenderingShadows; // set if rendering shadows instead of normal view + BOOL re_bDirectionalShadows; // set if rendering directional shadows + UBYTE *re_pubShadow; // byte-packed shadow mask + SLONG re_slShadowWidth; + SLONG re_slShadowHeight; + BOOL re_bSomeLightExists; // set if rendering light, and at least one pixel is lighted + BOOL re_bSomeDarkExists; // set if rendering light, and at least one pixel is dark + UBYTE re_ubLightIllumination; // the illumination type used by light rendering shadows + COLOR re_colSelection; // selection color + BOOL re_bCurrentSectorHasFog; // set if currently added sector has fog + BOOL re_bCurrentSectorHasHaze; // set if currently added sector has haze + BOOL re_bViewerInHaze; // set if viewer is viewing from a hazed sector + ULONG re_ulVisExclude; // for visibility tweaking + ULONG re_ulVisInclude; + + INDEX re_iViewVx0; // first view vertex for current sector + FLOATplane3D re_plClip; // current clip plane + CBrush3D *re_pbrCurrent; // current brush + CBrushSector *re_pbscCurrent; // current sector + + // screen edges + static CDynamicStackArray re_aadeAddEdges; + static CDynamicStackArray re_asedScreenEdges; + // spans for current scan line + static CDynamicStackArray re_aspSpans; + + // structures needed to render the scanned scene (separated for each renderer) + CDynamicStackArray re_aspoScreenPolygons; + CDynamicStackArray re_admDelayedModels; // model entities to be renderer later + CDynamicContainer re_cenDrawn; // all drawn entities (for drawing target lines etc.) + CStaticStackArray re_alfiLensFlares; // active lens flares + CDynamicStackArray re_amiMirrors; // mirrors/portals for recursion + CStaticStackArray re_avvxViewVertices; // transformed vertices + CStaticStackArray re_aiEdgeVxMain; + + // vertices clipped to current clip plane + static CStaticStackArray re_aiClipBuffer; + // buffers for edges of polygons + static CStaticStackArray re_aiEdgeVxClipSrc; + static CStaticStackArray re_aiEdgeVxClipDst; + + // add and remove lists for each scan line + static CStaticArray re_alhAddLists; + static CStaticArray re_actAddCounts; // count of edges in given add list + static CStaticArray re_apsedRemoveFirst; + + // container for sorting translucent polygons + static CDynamicStackArray re_atcTranslucentPolygons; + +public: + INDEX re_ctScanLines; // number of scanlines + PIX re_pixTopScanLineJ; // J coordinate of the top scanline + PIX re_pixBottomScanLineJ; // J coordinate of the bottom scanline + + CListHead re_lhActiveBrushes; // list of active brushes + CListHead re_lhActiveSectors; // list of active sectors + CListHead re_lhActiveTerrains; // list of active terrains + + static CStaticStackArray re_aaceActiveEdges; // active edges for current scan line + static CStaticStackArray re_aaceActiveEdgesTmp; + + INDEX re_iCurrentScan; // index of current scan line in tables + PIX re_pixCurrentScanJ; // J coordinate of current scan line + FLOAT re_fCurrentScanJ; + FIX16_16 re_xCurrentScanI; // I coordinate on current scan line + BOOL re_bCoherentScanLine; // set if this line is coherent with previous one + + CScreenEdge re_sedLeftSentinel; // sentinel edges for list of active edges + CScreenEdge re_sedRightSentinel; + CScreenPolygon re_spoFarSentinel; // sentinel polygon for surface stack + CListHead re_lhSurfaceStack; // list of polygons in stack - closest first + + /* Determine color to use for coloring vertices. */ + static inline COLOR ColorForVertices(COLOR colPolygon, COLOR colSector); + /* Determine color to use for coloring edges. */ + static inline COLOR ColorForEdges(COLOR colPolygon, COLOR colSector); + /* Determine color to use for coloring polygons. */ + static inline COLOR ColorForPolygons(COLOR colPolygon, COLOR colSector); + /* Draw vertices and/or edges of a brush sector. */ + void DrawBrushPolygonVerticesAndEdges(CBrushPolygon &bpoPolygon); + void DrawBrushSectorVerticesAndEdges(CBrushSector &bscSector); + /* Draw edges of a field brush sector. */ + void DrawFieldBrushSectorEdges(CBrushSector &bscSector); + + /* Make a screen edge from two vertices. */ + inline void MakeScreenEdge(CScreenEdge &sed, FLOAT fI0, FLOAT fJ0, FLOAT fI1, FLOAT fJ1); + // set scene rendering parameters for one polygon texture + inline void SetOneTextureParameters(CBrushPolygon &bpo, ScenePolygon &spo, INDEX iTexture); + /* Make a screen polygon for a brush polygon */ + CScreenPolygon *MakeScreenPolygon(CBrushPolygon &bpo); + /* Add a polygon to scene rendering. */ + void AddPolygonToScene(CScreenPolygon *pspo); + + // check if a sector is inside view frustum + __forceinline INDEX IsSectorVisible(CBrush3D &br, CBrushSector &bsc); + // check if a polygon is to be visible + __forceinline ULONG GetPolygonVisibility(const CBrushPolygon &bpo); + // check if polygon is outside viewfrustum + __forceinline BOOL IsPolygonCulled(const CBrushPolygon &bpo); + // setup fog/haze for current sector + void SetupFogAndHaze(void); + // transform vertices in current sector before clipping + void PreClipVertices(void); + // transform planes in current sector before clipping + void PreClipPlanes(void); + // make initial edges for a polygon + void MakeInitialPolygonEdges(CBrushPolygon &bpo, CScreenPolygon &spo, BOOL bInverted); + // find which portals should be rendered as portals or as pretenders + void FindPretenders(void); + // make screen polygons for nondetail polygons in current sector + void MakeNonDetailScreenPolygons(void); + // make screen polygons for detail polygons in current sector + void MakeDetailScreenPolygons(void); + // make final edges for all polygons in current sector + void MakeFinalPolygonEdges(void); + // add screen edges for all polygons in current sector + void AddScreenEdges(void); + // clip all polygons to one clip plane + void ClipToOnePlane(const FLOATplane3D &plView); + // clip all polygons to all clip planes of a projection + void ClipToAllPlanes(CAnyProjection3D &pr); + // make outcodes for current clip plane for all active vertices + __forceinline BOOL MakeOutcodes(void); + // clip one polygon to current clip plane + void ClipOnePolygon(CScreenPolygon &spo); + // generate clip edges for one polygon + void GenerateClipEdges(CScreenPolygon &spo); + // project vertices in current sector after clipping + void PostClipVertices(void); + + // switch a screen edge to using containers + inline void SwitchEdgeToContainers(CScreenEdge &sed); + /* Add an edge to add list of its top scanline and remove list at its bottom line. */ + inline void AddEdgeToAddAndRemoveLists(CScreenEdge &sed); + /* Add all edges in add list to active list. */ + inline void AddAddListToActiveList(INDEX iScanLine); + /* Remove all edges in remove list from active list and from other lists. */ + inline void RemRemoveListFromActiveList(CScreenEdge *psedFirst); + /* Step all edges in active list by one scan line and resort them. */ + inline void StepAndResortActiveList(void); + /* Copy I coordinates from active list to edge data. */ + inline void CopyActiveCoordinates(void); + /* Remove an active portal from rendering */ + inline void RemovePortal(CScreenPolygon &spo); + + /* Add a sector of a brush to rendering queues. */ + void AddActiveSector(CBrushSector &bscSector); + /* Add sector(s) adjoined to a portal to rendering and remove the portal. */ + void PassPortal(CScreenPolygon &spo); + + /* Generate a span for a polygon on current scan line. */ + inline void MakeSpan(CScreenPolygon &spo, CScreenEdge *psed0, CScreenEdge *psed1); + + /* Add spans in current line to scene. */ + void AddSpansToScene(void); + + /* Add a mirror/portal. */ + void AddMirror(CScreenPolygon &spo); + + /* Add a polygon to surface stack. */ + inline BOOL AddPolygonToSurfaceStack(CScreenPolygon &spo); + /* Remove a polygon from surface stack. */ + inline BOOL RemPolygonFromSurfaceStack(CScreenPolygon &spo); + /* Swap two polygons in surface stack. */ + inline BOOL SwapPolygonsInSurfaceStack(CScreenPolygon &spoOld, CScreenPolygon &spoNew); + /* Remove all polygons from surface stack. */ + inline void FlushSurfaceStack(void); + + // update VisTweak flags with given zoning sector + inline void UpdateVisTweaks(CBrushSector *pbsc); + + /* Initialize list of active edges and surface stack. */ + void InitScanEdges(void); + /* Clean up list of active edges and surface stack. */ + void EndScanEdges(void); + /* Scan list of active edges into spans. */ + inline CScreenPolygon *ScanOneLine(void); + /* Rasterize edges into spans. */ + void ScanEdges(void); + + /* Render wireframe brushes. */ + void RenderWireFrameBrushes(void); + /* Find lights for one model. */ + BOOL FindModelLights( CEntity &en, const CPlacement3D &plModel, COLOR &colLight, COLOR &colAmbient, + FLOAT &fTotalShadowIntensity, FLOAT3D &vTotalLightDirection, FLOATplane3D &plFloorPlane); + /* Render a model. */ + void RenderOneModel( CEntity &en, CModelObject &moModel, const CPlacement3D &plModel, + const FLOAT fDistanceFactor, BOOL bRenderShadow, ULONG ulDMFlags); + /* Render a ska model. */ + void CRenderer::RenderOneSkaModel( CEntity &en, const CPlacement3D &plModel, + const FLOAT fDistanceFactor, BOOL bRenderShadow, ULONG ulDMFlags); + /* Render models that were kept for delayed rendering. */ + void RenderModels(BOOL bBackground); + /* Render active terrains */ + void RenderTerrains(void); + /* Render active terrains in wireframe mode */ + void RenderWireFrameTerrains(void); + /* Render particles for models that were kept for delayed rendering. */ + void RenderParticles(BOOL bBackground); + // render one arrow given its 3d coordinates in world + void ProjectClipAndDrawArrow( + const FLOAT3D &v0, const FLOAT3D &v1, COLOR colColor); + /* Render target lines for each drawn entity that has some targets. */ + void RenderEntityTargets(void); + /* Render entity names. */ + void RenderEntityNames(void); + /* Render lens flares. */ + void RenderLensFlares(void); + /* Sort a list of translucent polygons. */ + ScenePolygon *SortTranslucentPolygons(ScenePolygon *pspoFirst); + + /* Prepare a brush entity for rendering if it is not yet prepared. */ + void PrepareBrush(CEntity *penBrush); + + /* Add a non-zoning brush entity to rendering list (add all sectors immediately). */ + void AddNonZoningBrush(CEntity *penBrush, CBrushSector *pbscThatAdds); + /* Add a model entity to rendering. */ + void AddModelEntity(CEntity *penModel); + /* Add a ska model entity to rendering. */ + void AddSkaModelEntity(CEntity *penModel); + /* Add a terrain entity to rendering list. */ + void AddTerrainEntity(CEntity *penTerrain); + /* Add a lens flare to rendering. */ + void AddLensFlare(CEntity *penLight, CLightSource *pls, CProjection3D *pprProjection, INDEX iMirrorLevel=0); + + /* Add to rendering all entities in the world (used in special cases in world editor). */ + void AddAllEntities(void); + /* Add to rendering all entities that are inside an zoning brush sector. */ + void AddEntitiesInSector(CBrushSector *pbscSectorInside); + /* Add to rendering all zoning brush sectors that an entity is in. */ + void AddZoningSectorsAroundEntity(CEntity *pen, const FLOAT3D &vEyesPos); + /* Add to rendering one particular zoning brush sector. */ + void AddGivenZoningSector(CBrushSector *pbscSector); + /* Add to rendering all zoning brush sectors near a given box in absolute space. */ + void AddZoningSectorsAroundBox(const FLOATaabbox3D &boxNear); + /* Add to rendering all entities that are inside a given box. */ + void AddEntitiesInBox(const FLOATaabbox3D &boxNear); + + /* Constructor. */ + CRenderer(void); + /* Destructor. */ + ~CRenderer(void); + + // initialize clipping rectangle + void InitClippingRectangle(PIX pixMinI, PIX pixMinJ, PIX pixSizeI, PIX pixSizeJ); + // do the rendering + void Render(void); + + // initialize all rendering structures + void Initialize(void); + // add initial sectors to active lists + void AddInitialSectors(void); + // scan through portals for other sectors + void ScanForOtherSectors(void); + // cleanup after scanning + void CleanupScanning(void); + // draw the prepared things to screen + void DrawToScreen(void); + // draw mirror polygons to z-buffer to enable drawing of mirror + void FillMirrorDepth(CMirror &mi); +}; + +// Render a world with some viewer, projection and drawport. (viewer may be NULL) +// internal version used for rendering shadows +extern ULONG RenderShadows(CWorld &woWorld, CEntity &enViewer, + CAnyProjection3D &prProjection, const FLOATaabbox3D &boxViewer, + UBYTE *pubShadowMask, SLONG slShadowWidth, SLONG slShadowHeight, + UBYTE ubIllumination); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Rendering/SelectOnRender.cpp b/Sources/Engine/Rendering/SelectOnRender.cpp new file mode 100644 index 0000000..1733784 --- /dev/null +++ b/Sources/Engine/Rendering/SelectOnRender.cpp @@ -0,0 +1,283 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include + +static PIX _pixSizeI; +static PIX _pixSizeJ; +UBYTE *_pubLassoBuffer = NULL; + +// init select-on-render functionality +void InitSelectOnRender(PIX pixSizeI, PIX pixSizeJ) +{ + _pixSizeI = pixSizeI; + _pixSizeJ = pixSizeJ; + + // if entity selecting not required + if (_pselenSelectOnRender==NULL) + { + // if vertex selecting not requred + if (_pselbvxtSelectOnRender==NULL) { + // do nothing + return; + } + // if not lasso and not alternative + else if (_pavpixSelectLasso==NULL && !_bSelectAlternative) { + // deselect all vertices + _pselbvxtSelectOnRender->Clear(); + } + } + + // if lasso selection is not on, or is invalid + if (_pavpixSelectLasso==NULL || _pavpixSelectLasso->Count()<3 + || pixSizeI<2 || pixSizeJ<2) { + // do nothing + return; + } + + SLONG slMaxOffset = pixSizeI*pixSizeJ-1; + + // allocate lasso buffer + _pubLassoBuffer = (UBYTE*)AllocMemory(_pixSizeI*_pixSizeJ); + // clear it + memset(_pubLassoBuffer, 0, _pixSizeI*_pixSizeJ); + + // for each line in lasso + INDEX ctpt = _pavpixSelectLasso->Count(); + for (INDEX ipt=0; ipt=_pixSizeI || pixI1<0 || pixI1>=_pixSizeI || + pixJ0<0 || pixJ0>=_pixSizeJ || pixJ1<0 || pixJ1>=_pixSizeJ) { + // skip this line + continue; + } + + // if line is horizontal + if (pixJ0==pixJ1) { + // skip it + continue; + // if line goes upwards + } else if (pixJ0>pixJ1) { + // make it go downwards + Swap(pixI0, pixI1); + Swap(pixJ0, pixJ1); + } + + // calculate step + FIX16_16 xStep = FIX16_16(FLOAT(pixI1-pixI0)/(pixJ1-pixJ0)); + // start in first row + FIX16_16 xI = FIX16_16(pixI0); + + // for each row + for(PIX pixJ = pixJ0; pixJ=0 && slOffset<=slMaxOffset) { + // invert the pixel in that row + _pubLassoBuffer[slOffset] ^= 0xFF; + } + // step the line + xI+=xStep; + } + } + + // for each row in lasso buffer + for(PIX pixJ = 0; pixJ<_pixSizeJ; pixJ++) { + // for each pixel in the row, except the last one + UBYTE *pub = _pubLassoBuffer+pixJ*_pixSizeI; + for(PIX pixI = 0; pixI<_pixSizeI-1; pixI++) { + // xor it to the next one + pub[1]^=pub[0]; + pub++; + } + } +} + +// end select-on-render functionality +void EndSelectOnRender(void) +{ + // free lasso buffer + if (_pubLassoBuffer!=NULL) { + FreeMemory(_pubLassoBuffer); + _pubLassoBuffer = NULL; + } +} + +// check if a vertex is influenced by current select-on-render selection +void SelectVertexOnRender(CBrushVertex &bvx, const PIX2D &vpix) +{ + // if not selecting + if (_pselbvxtSelectOnRender==NULL) { + // do nothing + return; + } + + // if the vertex is out of screen + if (vpix(1)<0 || vpix(1)>=_pixSizeI + || vpix(2)<0 || vpix(2)>=_pixSizeJ) { + // do nothing + return; + } + + // if selecting without lasso + if (_pubLassoBuffer==NULL) { + // if vertex is near point + if ((vpix-_vpixSelectNearPoint).Length()<_pixDeltaAroundVertex) { + + // if selected + if (bvx.IsSelected(BVXF_SELECTED)) { + // deselect it + _pselbvxtSelectOnRender->Deselect(bvx); + // if not selected + } else { + // select it + _pselbvxtSelectOnRender->Select(bvx); + } + } + // if selecting with lasso + } else { + // if the vertex is set in lasso buffer + if (_pubLassoBuffer!=NULL + &&_pubLassoBuffer[vpix(2)*_pixSizeI+vpix(1)]) { + + // if alternative + if (_bSelectAlternative) { + // deselect + if (bvx.IsSelected(BVXF_SELECTED)) { + _pselbvxtSelectOnRender->Deselect(bvx); + } + // if normal + } else { + // select + if (!bvx.IsSelected(BVXF_SELECTED)) { + _pselbvxtSelectOnRender->Select(bvx); + } + } + } + } +} + +// check if given vertice is selected by lasso +BOOL IsVertexInLasso( CProjection3D &prProjection, const FLOAT3D &vtx, FLOATmatrix3D *pmR, FLOAT3D &vOffset) +{ + // convert from relative to absolute space + FLOAT3D vAbsolute = vOffset+vtx*(*pmR); + + FLOAT3D vtxProjected; + prProjection.ProjectCoordinate( vAbsolute, vtxProjected); + + PIX2D vpix; + vpix(1) = vtxProjected(1); + // convert coordinate into screen representation + vpix(2) = _pixSizeJ-vtxProjected(2); + + // if the vertex is out of screen + if (vpix(1)<0 || vpix(1)>=_pixSizeI + || vpix(2)<0 || vpix(2)>=_pixSizeJ) { + // no selecting + return FALSE; + } + + // if the vertex is set in lasso buffer + if (_pubLassoBuffer!=NULL + &&_pubLassoBuffer[vpix(2)*_pixSizeI+vpix(1)]) + { + return TRUE; + } + return FALSE; +} + +// check if given bounding box is selected by lasso +BOOL IsBoundingBoxInLasso( CProjection3D &prProjection, const FLOATaabbox3D &box, FLOATmatrix3D *pmR, FLOAT3D &vOffset) +{ + FLOAT3D vMin = box.Min(); + FLOAT3D vMax = box.Max(); + + // test lasso influence for all of bounding box's vertices + if( + IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMin(2), vMin(3)), pmR, vOffset) && + IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMin(2), vMin(3)), pmR, vOffset) && + IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMax(2), vMin(3)), pmR, vOffset) && + IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMax(2), vMin(3)), pmR, vOffset) && + IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMin(2), vMax(3)), pmR, vOffset) && + IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMin(2), vMax(3)), pmR, vOffset) && + IsVertexInLasso( prProjection, FLOAT3D( vMin(1), vMax(2), vMax(3)), pmR, vOffset) && + IsVertexInLasso( prProjection, FLOAT3D( vMax(1), vMax(2), vMax(3)), pmR, vOffset) ) + { + return TRUE; + } + return FALSE; +} + +// check if all of the corners of entity's bounding box are influenced by current select-on-render selection +void SelectEntityOnRender(CProjection3D &prProjection, CEntity &en) +{ + FLOATaabbox3D bbox; + + FLOATmatrix3D mOne = FLOATmatrix3D(0.0f); + mOne.Diagonal(1.0f); + FLOATmatrix3D *pmR; + FLOAT3D vOffset; + + // if this entity is model + if (en.en_RenderType==CEntity::RT_MODEL || en.en_RenderType==CEntity::RT_EDITORMODEL) + { + // get bbox of current frame + CModelObject *pmo = en.GetModelObject(); + pmo->GetCurrentFrameBBox( bbox); + pmR = &en.en_mRotation; + vOffset = en.GetPlacement().pl_PositionVector; + } + // if it is ska model + else if(en.en_RenderType==CEntity::RT_SKAMODEL || en.en_RenderType==CEntity::RT_SKAEDITORMODEL) + { + en.GetModelInstance()->GetCurrentColisionBox( bbox); + pmR = &en.en_mRotation; + vOffset = en.GetPlacement().pl_PositionVector; + } + // if it is brush + else + { + // get bbox of brush's first mip + CBrush3D *pbr = en.GetBrush(); + CBrushMip *pbrmip = pbr->GetFirstMip(); + bbox = pbrmip->bm_boxBoundingBox; + pmR = &mOne; + vOffset = FLOAT3D( 0.0f, 0.0f, 0.0f); + } + + if( IsBoundingBoxInLasso( prProjection, bbox, pmR, vOffset)) + { + if( _bSelectAlternative) + { + // deselect + if (en.IsSelected(ENF_SELECTED)) + { + _pselenSelectOnRender->Deselect(en); + } + } + else + { + // select + if (!en.IsSelected(ENF_SELECTED)) + { + _pselenSelectOnRender->Select(en); + } + } + } +} diff --git a/Sources/Engine/Ska/AnimSet.cpp b/Sources/Engine/Ska/AnimSet.cpp new file mode 100644 index 0000000..af15cfc --- /dev/null +++ b/Sources/Engine/Ska/AnimSet.cpp @@ -0,0 +1,627 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ANIMSET_VERSION 14 +#define ANIMSET_ID "ANIM" + +// table for removed frames +static CStaticArray aiRemFrameTable; +// precalculated angles for rotations +static CStaticArray aangAngles; + +// if rotations are compresed does loader also fills array of uncompresed rotations +static BOOL bAllRotations = FALSE; +void RememberUnCompresedRotatations(BOOL bRemember) +{ + bAllRotations = bRemember; +} +CAnimSet::CAnimSet() +{ + +} +CAnimSet::~CAnimSet() +{ +} +// conpres normal +static void CompressAxis(const FLOAT3D &vNormal, UWORD &ubH, UWORD &ubP) +{ + ANGLE h, p; + + const FLOAT &x = vNormal(1); + const FLOAT &y = vNormal(2); + const FLOAT &z = vNormal(3); + + // calculate pitch + p = ASin(y); + + // if y is near +1 or -1 + if (y>0.99999 || y<-0.99999) { + // heading is irrelevant + h = 0; + // otherwise + } else { + // calculate heading + h = ATan2(-x, -z); + } + + h = (h/360.0f)+0.5f; + p = (p/360.0f)+0.5f; + ASSERT(h>=0 && h<=1); + ASSERT(p>=0 && p<=1); + ubH = UWORD(h*65535); + ubP = UWORD(p*65535); +} +// try to remove 2. keyframe in rotation +BOOL RemoveRotFrame(AnimRot &ar1,AnimRot &ar2,AnimRot &ar3,FLOAT fTreshold) +{ + ANGLE3D ang1,ang2,ang2i,ang3; + FLOATmatrix3D m2i; + // calculate slerp factor for ar2' + FLOAT fSlerpFactor = (FLOAT)(ar2.ar_iFrameNum - ar1.ar_iFrameNum)/(FLOAT)(ar3.ar_iFrameNum - ar1.ar_iFrameNum); + // calculate ar2' + FLOATquat3D q2i = Slerp(fSlerpFactor,ar1.ar_qRot,ar3.ar_qRot); + // read precalculated values + ang1 = aangAngles[ar1.ar_iFrameNum]; + ang2 = aangAngles[ar2.ar_iFrameNum]; + ang3 = aangAngles[ar3.ar_iFrameNum]; + q2i.ToMatrix(m2i); + DecomposeRotationMatrixNoSnap(ang2i,m2i); + + for(INDEX i=1;i<4;i++) + { + if( ((ang2(i) < ang3(i)) && (ang2(i) < ang1(i))) || ((ang2(i) > ang3(i)) && (ang2(i) > ang1(i))) ) + { + // this is extrem + if(Abs(ang2(i)) > 0.1f) return FALSE; + } + FLOAT fErr = Abs(ang2(i)-ang2i(i)) / Abs(ang3(i) - ang1(i)); + if(Abs(ang2(i)-ang2i(i)) < 0.1f) continue; + if(fErr>fTreshold) return FALSE; + } + return TRUE; +} +// try to remove 2. keyrame in translation +BOOL RemovePosFrame(AnimPos &ap1,AnimPos &ap2,AnimPos &ap3,FLOAT fTreshold) +{ + FLOAT fLerpFactor = (FLOAT)(ap2.ap_iFrameNum - ap1.ap_iFrameNum)/(FLOAT)(ap3.ap_iFrameNum - ap1.ap_iFrameNum); + FLOAT3D v2i = Lerp(ap1.ap_vPos,ap3.ap_vPos,fLerpFactor); + + FLOAT3D v1 = ap1.ap_vPos; + FLOAT3D v2 = ap2.ap_vPos; + FLOAT3D v3 = ap3.ap_vPos; + + for(INDEX i=1;i<4;i++) + { + if( ((v2(i) < v3(i)) && (v2(i) < v1(i))) || ((v2(i) > v3(i)) && (v2(i) > v1(i))) ) + { + // extrem + if(Abs(v2(i)) > 0.001f) return FALSE; + } + FLOAT fErr = Abs(v2(i)-v2i(i)) / Abs(v3(i) - v1(i)); + if(Abs(v2(i)-v2i(i)) < 0.001f) continue; + if(fErr>fTreshold) return FALSE; + } + return TRUE; +} +// find next keyframe that havent been marked as removed +INDEX FindNextFrame(INDEX ifnToFind) +{ + INDEX ctfn = aiRemFrameTable.Count(); + if(ifnToFind >= ctfn) return -1; + if(aiRemFrameTable[ifnToFind] == FALSE) return ifnToFind; + for(INDEX ifn=ifnToFind;ifn arRot; + // for each removed frame + for(INDEX ifnr=0;ifnr apPos; + // count removed frames + for(INDEX ifr=0;ifr aMorphs; + + INDEX ctme = an.an_ameMorphs.Count(); + for(INDEX ime=0;ime=ctwm) break; + FLOAT &fMorphFactor = me.me_aFactors[iwm]; + // check if morph factor is 0 + bMorphIsZero = fMorphFactor == 0; + iwm++; + } + // dont remove this morph envelope + if(!bMorphIsZero) + { + // copy this morphmap to temp array of morph envelopes + MorphEnvelope &meNew = aMorphs.Push(); + meNew = me; + } + } + INDEX ctmeNew = aMorphs.Count(); + // crate new array for morph envelopes + an.an_ameMorphs.Clear(); + an.an_ameMorphs.New(ctmeNew); + // copy morph back to animations array of morph envelopes + for(INDEX imeNew=0;imeNew0); + ASSERT(pan!=NULL); + + // copy all animations to temp array + CStaticArray animsTemp; + animsTemp.New(ctan-1); + INDEX ianNew=0; + for(INDEX ian=0;ianWriteID_t(CChunkID(ANIMSET_ID)); + // write version + (*ostrFile)<<(INDEX)ANIMSET_VERSION; + + INDEX ctan = as_Anims.Count(); + (*ostrFile)<Write_t(&be.be_mDefaultPos[0],sizeof(FLOAT)*12); + // count positions + INDEX ctp = be.be_apPos.Count(); + // write position count + (*ostrFile)<Write_t(&be.be_apPos[ip],sizeof(AnimPos)); + } + // count rotations + INDEX ctRotations = be.be_arRot.Count(); + (*ostrFile)<Write_t(&arRot,sizeof(AnimRot)); + } + INDEX ctOptRotations = be.be_arRotOpt.Count(); + if(ctOptRotations>0) + { + // OPTIMISED ROTATIONS ARE NOT SAVED !!! + // use RememberUnCompresedRotatations(); + ASSERT(ctRotations>=ctOptRotations); + } + // write offsetlen + (*ostrFile)<Write_t(&me.me_aFactors[0],sizeof(FLOAT)*ctmf); + } + } +} +// read from stream +void CAnimSet::Read_t(CTStream *istrFile) +{ + INDEX iFileVersion; + // read chunk id + istrFile->ExpectID_t(CChunkID(ANIMSET_ID)); + // check file version + (*istrFile)>>iFileVersion; + if(iFileVersion != ANIMSET_VERSION) + { + ThrowF_t(TRANS("File '%s'.\nInvalid animset file version. Expected Ver \"%d\" but found \"%d\"\n"), + (const char*)istrFile->GetDescription(),ANIMSET_VERSION,iFileVersion); + } + INDEX ctan; + // read anims count + (*istrFile)>>ctan; + // create anims array + as_Anims.New(ctan); + + for(int ian=0;ian>an.an_fnSourceFile; + // read Anim ID + (*istrFile>>pstrNameID); + an.an_iID = ska_GetIDFromStringTable(pstrNameID); + // read secperframe + (*istrFile)>>an.an_fSecPerFrame; + // read num of frames + (*istrFile)>>an.an_iFrames; + // read treshold + (*istrFile)>>an.an_fTreshold; + // read if compresion is used + (*istrFile)>>an.an_bCompresed; + // read bool if animstion uses custom speed + (*istrFile)>>an.an_bCustomSpeed; + + INDEX ctbe; + INDEX ctme; + // read bone envelopes count + (*istrFile)>>ctbe; + // create bone envelopes array + an.an_abeBones.New(ctbe); + // read bone envelopes + for(int ibe=0;ibe>pstrNameID; + // read bone envelope ID + be.be_iBoneID = ska_GetIDFromStringTable(pstrNameID); + // read default pos(matrix12) + istrFile->Read_t(&be.be_mDefaultPos[0],sizeof(FLOAT)*12); + + INDEX ctp; + // read pos array + (*istrFile)>>ctp; + be.be_apPos.New(ctp); + for(INDEX ip=0;ipRead_t(&be.be_apPos[ip],sizeof(AnimPos)); + } + INDEX ctr; + // read rot array count + (*istrFile)>>ctr; + if(!an.an_bCompresed) + { + // create array for uncompresed rotations + be.be_arRot.New(ctr); + } + else + { + // if flag is set to remember uncompresed rotations + if(bAllRotations) + { + // create array for uncompresed rotations + be.be_arRot.New(ctr); + } + // create array for compresed rotations + be.be_arRotOpt.New(ctr); + } + for(INDEX ir=0;irRead_t(&arRot,sizeof(AnimRot)); + if(!an.an_bCompresed) + { + be.be_arRot[ir] = arRot; + } + else + { + if(bAllRotations) + { + // fill uncompresed rotations + be.be_arRot[ir] = arRot; + } + // optimize quaternions + FLOAT3D vAxis; + ANGLE aAngle; + UWORD ubH,ubP; + FLOATquat3D &qRot = arRot.ar_qRot; + AnimRotOpt &aroRot = be.be_arRotOpt[ir]; + qRot.ToAxisAngle(vAxis,aAngle); + CompressAxis(vAxis,ubH,ubP); + + // compress angle + aroRot.aro_aAngle = aAngle * ANG_COMPRESIONMUL; + aroRot.aro_iFrameNum = arRot.ar_iFrameNum; + aroRot.aro_ubH = ubH; + aroRot.aro_ubP = ubP; + be.be_arRotOpt[ir] = aroRot; + } + } + // read offsetlen + (*istrFile)>>be.be_OffSetLen; + } + + // read morph envelopes + (*istrFile)>>ctme; + // create morph envelopes array + an.an_ameMorphs.New(ctme); + // read morph envelopes + for(int ime=0;ime>pstrNameID; + me.me_iMorphMapID = ska_GetIDFromStringTable(pstrNameID); + INDEX ctmf; + // read morph factors count + (*istrFile)>>ctmf; + // create morph factors array + me.me_aFactors.New(ctmf); + // read morph factors + istrFile->Read_t(&me.me_aFactors[0],sizeof(FLOAT)*ctmf); + } + } +} +// clear animset +void CAnimSet::Clear(void) +{ + INDEX ctAnims = as_Anims.Count(); + for(INDEX iAnims=0;iAnims +#include +#include +#include + +#define ANG_COMPRESIONMUL 182.041666666666666666666666666667f; + +#define AN_LOOPING (1UL<<0) // looping animation +#define AN_NORESTART (1UL<<1) // dont restart anim +#define AN_PAUSED (1UL<<2) +#define AN_CLEAR (1UL<<3) // do new clear state before adding animation +#define AN_CLONE (1UL<<4) // do new cloned state before adding animation +#define AN_NOGROUP_SORT (1UL<<5) // dont sort animations by groups + +#define CLEAR_STATE_LENGTH 0.2f +#define CLONED_STATE_LENGTH 0.2f + +struct AnimPos +{ + UWORD ap_iFrameNum; //frame number + FLOAT3D ap_vPos; //bone pos +}; + +struct AnimRotOpt +{ + UWORD aro_iFrameNum; //frame number + UWORD aro_ubH,aro_ubP; + ANGLE aro_aAngle; +}; + +struct AnimRot +{ + UWORD ar_iFrameNum; //frame number + FLOATquat3D ar_qRot; //bone rot +}; + +struct Animation +{ + int an_iID; + INDEX an_iFrames; + FLOAT an_fSecPerFrame; + FLOAT an_fTreshold; + BOOL an_bCompresed;// are quaternions in animation compresed + CStaticArray an_ameMorphs; + CStaticArray an_abeBones; + CTString an_fnSourceFile;// name of ascii aa file, used in Ska studio + BOOL an_bCustomSpeed; // animation has custom speed set in animset list file, witch override speed from anim file +}; + +struct MorphEnvelope +{ + int me_iMorphMapID; + CStaticArray me_aFactors; +}; + +struct BoneEnvelope +{ + int be_iBoneID; + Matrix12 be_mDefaultPos; // default pos + CStaticArray be_apPos;// array of compresed bone positions + CStaticArray be_arRot;// array if compresed bone rotations + CStaticArray be_arRotOpt;// array if optimized compresed bone rotations + FLOAT be_OffSetLen; +}; + +class ENGINE_API CAnimSet : public CSerial +{ +public: + CAnimSet(); + ~CAnimSet(); + void Optimize(); + void OptimizeAnimation(Animation &an, FLOAT fTreshold); + void AddAnimation(Animation *pan); + void RemoveAnimation(Animation *pan); + + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * + void Clear(void); + SLONG GetUsedMemory(void); + + CStaticArray as_Anims; +}; + +// if rotations are compresed does loader also fills array of uncompresed rotations +ENGINE_API void RememberUnCompresedRotatations(BOOL bRemember); +#endif /* include-once check. */ diff --git a/Sources/Engine/Ska/Mesh.cpp b/Sources/Engine/Ska/Mesh.cpp new file mode 100644 index 0000000..b9d2afd --- /dev/null +++ b/Sources/Engine/Ska/Mesh.cpp @@ -0,0 +1,976 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include "Mesh.h" + +#define MESH_VERSION 12 +#define MESH_ID "MESH" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +INDEX AreVerticesDiferent(INDEX iCurentIndex, INDEX iLastIndex); + +struct VertexLocator +{ + INDEX vl_iIndex; + INDEX vl_iSubIndex; +}; + +struct SortArray +{ + INDEX sa_iNewIndex; + INDEX sa_iSurfaceIndex; + CStaticArray sa_aWeightMapList; + CStaticArray sa_aMorphMapList; +}; + +CStaticArray _aSortArray; +CStaticArray _aiOptimizedIndex; +CStaticArray _aiSortedIndex; + +MeshLOD *pMeshLOD;// curent mesh lod (for quick sort) +MeshLOD mshOptimized; + +CMesh::CMesh() +{ +} + +CMesh::~CMesh() +{ +} + +// release old shader and obtain new shader for mesh surface (expand ShaderParams if needed) +void ChangeSurfaceShader_t(MeshSurface &msrf,CTString fnNewShader) +{ + CShader *pShaderNew = _pShaderStock->Obtain_t(fnNewShader); + ASSERT(pShaderNew!=NULL); + if(msrf.msrf_pShader!=NULL) _pShaderStock->Release(msrf.msrf_pShader); + msrf.msrf_pShader = pShaderNew; + // get new shader description + ShaderDesc shDesc; + msrf.msrf_pShader->GetShaderDesc(shDesc); + // if needed expand size of arrays for new shader + // reset new values!!!! + INDEX ctOldTextureIDs = msrf.msrf_ShadingParams.sp_aiTextureIDs.Count(); + INDEX ctNewTextureIDs = shDesc.sd_astrTextureNames.Count(); + INDEX ctOldUVMaps = msrf.msrf_ShadingParams.sp_aiTexCoordsIndex.Count(); + INDEX ctNewUVMaps = shDesc.sd_astrTexCoordNames.Count(); + INDEX ctOldColors = msrf.msrf_ShadingParams.sp_acolColors.Count(); + INDEX ctNewColors = shDesc.sd_astrColorNames.Count(); + INDEX ctOldFloats = msrf.msrf_ShadingParams.sp_afFloats.Count(); + INDEX ctNewFloats = shDesc.sd_astrFloatNames.Count(); + if(ctOldTextureIDsiMaxIndex) iMaxIndex = mtTriangle.iVertex[iv]; + } + } + // remember first index in vertices array + msrf.msrf_iFirstVertex = iMinIndex; + // remember vertices count + msrf.msrf_ctVertices = iMaxIndex-iMinIndex+1; + + // for each triangle in surface + for(its=0;itsmlod_aVertices[iCurentIndex].y,pMeshLOD->mlod_aVertices[iLastIndex].y); + CHECKF(pMeshLOD->mlod_aVertices[iCurentIndex].x,pMeshLOD->mlod_aVertices[iLastIndex].x); + CHECKF(pMeshLOD->mlod_aVertices[iCurentIndex].z,pMeshLOD->mlod_aVertices[iLastIndex].z); + // check normals + CHECKF(pMeshLOD->mlod_aNormals[iCurentIndex].ny,pMeshLOD->mlod_aNormals[iLastIndex].ny); + CHECKF(pMeshLOD->mlod_aNormals[iCurentIndex].nx,pMeshLOD->mlod_aNormals[iLastIndex].nx); + CHECKF(pMeshLOD->mlod_aNormals[iCurentIndex].nz,pMeshLOD->mlod_aNormals[iLastIndex].nz); + // check uvmaps + INDEX ctUVMaps = pMeshLOD->mlod_aUVMaps.Count(); + for(INDEX iuvm=0;iuvmmlod_aUVMaps[iuvm].muv_aTexCoords[iCurentIndex].u,pMeshLOD->mlod_aUVMaps[iuvm].muv_aTexCoords[iLastIndex].u); + CHECKF(pMeshLOD->mlod_aUVMaps[iuvm].muv_aTexCoords[iCurentIndex].v,pMeshLOD->mlod_aUVMaps[iuvm].muv_aTexCoords[iLastIndex].v); + } + // count weight and morph maps + INDEX ctwmCurent = _aSortArray[iCurentIndex].sa_aWeightMapList.Count(); + INDEX ctwmLast = _aSortArray[iLastIndex].sa_aWeightMapList.Count(); + INDEX ctmmCurent = _aSortArray[iCurentIndex].sa_aMorphMapList.Count(); + INDEX ctmmLast = _aSortArray[iLastIndex].sa_aMorphMapList.Count(); + // check if vertices have same weight and morph maps count + CHECK(ctwmCurent,ctwmLast); + CHECK(ctmmCurent,ctmmLast); + // check if vertices have same weight map factors + for(INDEX iwm=0;iwmmlod_aWeightMaps[iwmCurent].mwm_aVertexWeight[iwwCurent].mww_fWeight,pMeshLOD->mlod_aWeightMaps[iwmLast].mwm_aVertexWeight[iwwLast].mww_fWeight); + } + + // check if vertices have same morph map factors + for(INDEX imm=0;immmlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_x, + pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_x); + CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_y, + pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_y); + CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_z, + pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_z); + CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_nx, + pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_nx); + CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_ny, + pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_ny); + CHECKF(pMeshLOD->mlod_aMorphMaps[immCurent].mmp_aMorphMap[imwmCurent].mwm_nz, + pMeshLOD->mlod_aMorphMaps[immLast].mmp_aMorphMap[imwmLast].mwm_nz); + } + return 0; +} +// normalize weights in mlod +void CMesh::NormalizeWeightsInLod(MeshLOD &mlod) +{ + CStaticArray aWeightFactors; + int ctvtx = mlod.mlod_aVertices.Count(); + int ctwm = mlod.mlod_aWeightMaps.Count(); + // create array for weights + aWeightFactors.New(ctvtx); + memset(&aWeightFactors[0],0,sizeof(aWeightFactors[0])*ctvtx); + int iwm=0; + for(;iwm aTempMLODs; + aTempMLODs.New(ctmlod-1); + INDEX iIndexSrc=0; + + // for each skeleton lod in skeleton + for(INDEX imlod=0;imlodWriteID_t(CChunkID(MESH_ID)); + // write version + (*ostrFile)<<(INDEX)MESH_VERSION; + // write mlod count + (*ostrFile)<Write_t(&mLod.mlod_aVertices[0],sizeof(MeshVertex)*ctVx); + // write normals + ostrFile->Write_t(&mLod.mlod_aNormals[0],sizeof(MeshNormal)*ctVx); + + // write uvmaps count + (*ostrFile)<Write_t(&mLod.mlod_aUVMaps[iuv].muv_aTexCoords[0],sizeof(MeshTexCoord)*ctVx); + } + + // write surfaces count + ostrFile->Write_t(&ctSf,sizeof(INDEX)); + // write surfaces + for(INDEX isf=0;isfWrite_t(&mLod.mlod_aSurfaces[isf].msrf_aTriangles[0],sizeof(MeshTriangle)*ctTris); + + // write bool that this surface has a shader + INDEX bShaderExists = (msrf.msrf_pShader!=NULL); + (*ostrFile)<GetShaderDesc(shDesc); + INDEX cttx=shDesc.sd_astrTextureNames.Count(); + INDEX cttc=shDesc.sd_astrTexCoordNames.Count(); + INDEX ctcol=shDesc.sd_astrColorNames.Count(); + INDEX ctfl=shDesc.sd_astrFloatNames.Count(); + // data count must be at same as size defined in shader or higher + ASSERT(cttx<=msrf.msrf_ShadingParams.sp_aiTextureIDs.Count()); + ASSERT(cttc<=msrf.msrf_ShadingParams.sp_aiTexCoordsIndex.Count()); + ASSERT(ctcol<=msrf.msrf_ShadingParams.sp_acolColors.Count()); + ASSERT(ctfl<=msrf.msrf_ShadingParams.sp_afFloats.Count()); + ASSERT(msrf.msrf_pShader->GetShaderDesc!=NULL); + // write texture count + (*ostrFile)<GetName(); + (*ostrFile)<Write_t(&mLod.mlod_aWeightMaps[iwm].mwm_aVertexWeight[0],sizeof(MeshVertexWeight)*ctWw); + } + + // write morphmaps count + (*ostrFile)<Write_t(&mLod.mlod_aMorphMaps[imm].mmp_bRelative,sizeof(BOOL)); + // write morph sets count + ostrFile->Write_t(&ctms,sizeof(INDEX)); + // write morph sets + ostrFile->Write_t(&mLod.mlod_aMorphMaps[imm].mmp_aMorphMap[0],sizeof(MeshVertexMorph)*ctms); + } + } +} + +//read from stream +void CMesh::Read_t(CTStream *istrFile) +{ + INDEX ctmlods; + INDEX iFileVersion; + // read chunk id + istrFile->ExpectID_t(CChunkID(MESH_ID)); + // check file version + (*istrFile)>>iFileVersion; + + // if file version is not 11 nor 12 + if(iFileVersion != 11 && iFileVersion!=12) { + ThrowF_t(TRANS("File '%s'.\nInvalid Mesh file version.\nExpected Ver \"%d\" but found \"%d\"\n"), + (const char*)istrFile->GetDescription(),MESH_VERSION,iFileVersion); + return; + } + + // read mlod count + (*istrFile)>>ctmlods; + // for each lod in mesh + for(INDEX imlod=0;imlod>mLod.mlod_fnSourceFile; + // read max distance + (*istrFile)>>mLod.mlod_fMaxDistance; + // read flags + (*istrFile)>>mLod.mlod_ulFlags; + + // :) + if(iFileVersion<=11) { + mLod.mlod_ulFlags = 0; + } + if(mLod.mlod_ulFlags==0xCDCDCDCD) { + mLod.mlod_ulFlags = 0; + } + + + // read vertex count + (*istrFile)>>ctVx; + // create vertex and normal arrays + mLod.mlod_aVertices.New(ctVx); + mLod.mlod_aNormals.New(ctVx); + // read wertices + istrFile->Read_t(&mLod.mlod_aVertices[0],sizeof(MeshVertex)*ctVx); + // read normals + istrFile->Read_t(&mLod.mlod_aNormals[0],sizeof(MeshNormal)*ctVx); + + // read uvmaps count + (*istrFile)>>ctUV; + // create array for uvmaps + mLod.mlod_aUVMaps.New(ctUV); + // read uvmaps + for(int iuv=0;iuv>strNameID; + mLod.mlod_aUVMaps[iuv].muv_iID = ska_GetIDFromStringTable(strNameID); + // create array for uvmaps texcordinates + mLod.mlod_aUVMaps[iuv].muv_aTexCoords.New(ctVx); + // read uvmap texcordinates + istrFile->Read_t(&mLod.mlod_aUVMaps[iuv].muv_aTexCoords[0],sizeof(MeshTexCoord)*ctVx); + } + // read surfaces count + (*istrFile)>>ctSf; + // create array for surfaces + mLod.mlod_aSurfaces.New(ctSf); + // read surfaces + for(INDEX isf=0;isf>strSurfaceID; + msrf.msrf_iSurfaceID = ska_GetIDFromStringTable(strSurfaceID); + // read first vertex + (*istrFile)>>msrf.msrf_iFirstVertex; + // read vertices count + (*istrFile)>>msrf.msrf_ctVertices; + // read tris count + (*istrFile)>>ctTris; + // create triangles array + mLod.mlod_aSurfaces[isf].msrf_aTriangles.New(ctTris); + // read triangles + istrFile->Read_t(&mLod.mlod_aSurfaces[isf].msrf_aTriangles[0],sizeof(MeshTriangle)*ctTris); + + // read bool that this surface has a shader + INDEX bShaderExists; + (*istrFile)>>bShaderExists; + // if shader exists read its params + if(bShaderExists) { + INDEX cttx,cttc,ctcol,ctfl; + // read texture count + (*istrFile)>>cttx; + // read texture coords count + (*istrFile)>>cttc; + // read color count + (*istrFile)>>ctcol; + // read float count + (*istrFile)>>ctfl; + + CShader *pshMeshShader = NULL; + ShaderParams *pshpShaderParams = NULL; + CShader shDummyShader; // dummy shader if shader is not found + ShaderParams shpDummyShaderParams;// dummy shader params if shader is not found + // read shader name + CTString strShaderName; + (*istrFile)>>strShaderName; + // try to load shader + try{ + msrf.msrf_pShader = _pShaderStock->Obtain_t(strShaderName); + pshMeshShader = msrf.msrf_pShader; + pshpShaderParams = &msrf.msrf_ShadingParams; + } catch(char *strErr) { + CPrintF("%s\n",strErr); + msrf.msrf_pShader = NULL; + pshMeshShader = &shDummyShader; + pshpShaderParams = &shpDummyShaderParams; + } + + // if mesh shader exisits + if(msrf.msrf_pShader!=NULL) { + // get shader description + ShaderDesc shDesc; + msrf.msrf_pShader->GetShaderDesc(shDesc); + // check if saved params count match shader params count + if(shDesc.sd_astrTextureNames.Count() != cttx) ThrowF_t("File '%s'\nWrong texture count %d",(const char*)GetName(),cttx); + if(shDesc.sd_astrTexCoordNames.Count() != cttc) ThrowF_t("File '%s'\nWrong uvmaps count %d",(const char*)GetName(),cttc); + if(shDesc.sd_astrColorNames.Count() != ctcol) ThrowF_t("File '%s'\nWrong colors count %d",(const char*)GetName(),ctcol); + if(shDesc.sd_astrFloatNames.Count() != ctfl) ThrowF_t("File '%s'\nWrong floats count %d",(const char*)GetName(),ctfl); + } + + // create arrays for shader params + pshpShaderParams->sp_aiTextureIDs.New(cttx); + pshpShaderParams->sp_aiTexCoordsIndex.New(cttc); + pshpShaderParams->sp_acolColors.New(ctcol); + pshpShaderParams->sp_afFloats.New(ctfl); + + // read shader texture IDs + for(INDEX itx=0;itx>strTexID; + INDEX iTexID = ska_GetIDFromStringTable(strTexID); + pshpShaderParams->sp_aiTextureIDs[itx] = iTexID; + } + // read shader texture coords indices + for(INDEX itc=0;itc>iTexCoorsIndex; + pshpShaderParams->sp_aiTexCoordsIndex[itc] = iTexCoorsIndex; + } + // read shader colors + for(INDEX icol=0;icol>colColor; + pshpShaderParams->sp_acolColors[icol] = colColor; + } + // read shader floats + for(INDEX ifl=0;ifl>fFloat; + pshpShaderParams->sp_afFloats[ifl] = fFloat; + } + // there were no flags in shader before ver 12 + if(iFileVersion>11) { + ULONG ulFlags; + (*istrFile)>>ulFlags; + pshpShaderParams->sp_ulFlags = ulFlags; + } else { + pshpShaderParams->sp_ulFlags = 0; + } + } else { + // this surface does not have shader + msrf.msrf_pShader=NULL; + } + } + + // read weightmaps count + (*istrFile)>>ctWM; + // create weightmap array + mLod.mlod_aWeightMaps.New(ctWM); + // read each weightmap + for(INDEX iwm=0;iwm>pstrNameID; + mLod.mlod_aWeightMaps[iwm].mwm_iID = ska_GetIDFromStringTable(pstrNameID); + // read wertex weight count + INDEX ctWw; + (*istrFile)>>ctWw; + // create wertex weight array + mLod.mlod_aWeightMaps[iwm].mwm_aVertexWeight.New(ctWw); + // read wertex weights + istrFile->Read_t(&mLod.mlod_aWeightMaps[iwm].mwm_aVertexWeight[0],sizeof(MeshVertexWeight)*ctWw); + } + + // read morphmap count + (*istrFile)>>ctMM; + // create morphmaps array + mLod.mlod_aMorphMaps.New(ctMM); + // read morphmaps + for(INDEX imm=0;imm>pstrNameID; + mLod.mlod_aMorphMaps[imm].mmp_iID = ska_GetIDFromStringTable(pstrNameID); + // read bRelative + (*istrFile)>>mLod.mlod_aMorphMaps[imm].mmp_bRelative; + // read morph sets count + INDEX ctms; + (*istrFile)>>ctms; + // create morps sets array + mLod.mlod_aMorphMaps[imm].mmp_aMorphMap.New(ctms); + // read morph sets + istrFile->Read_t(&mLod.mlod_aMorphMaps[imm].mmp_aMorphMap[0],sizeof(MeshVertexMorph)*ctms); + } + } +} +// clear mesh +void CMesh::Clear(void) +{ + // for each LOD + INDEX ctmlod = msh_aMeshLODs.Count(); + for (INDEX imlod=0; imlodRelease(msrf.msrf_pShader); + msrf.msrf_pShader = NULL; + } + // clear the surfaces array + mlod.mlod_aSurfaces.Clear(); + // for each uvmap, clear the texcord list + INDEX ctuvm = mlod.mlod_aUVMaps.Count(); + for (INDEX iuvm=0;iuvm +#include +#include +#include +#include +#include +#include +#include + +#define ML_HALF_FACE_FORWARD (1UL<<0) // half face forward +#define ML_FULL_FACE_FORWARD (1UL<<1) // full face forward + +struct ENGINE_API MeshLOD +{ + MeshLOD() { + mlod_fMaxDistance = -1; + mlod_ulFlags = 0; + }; + ~MeshLOD() {} + FLOAT mlod_fMaxDistance; + ULONG mlod_ulFlags; + CStaticArray mlod_aVertices; // vertices + CStaticArray mlod_aNormals; // normals + CStaticArray mlod_aUVMaps; // UV maps + CStaticArray mlod_aSurfaces; // surfaces + CStaticArray mlod_aWeightMaps; // weight maps + CStaticArray mlod_aMorphMaps; // morph maps + CTString mlod_fnSourceFile;// file name of ascii am file, used in Ska studio +}; + +struct ENGINE_API MeshVertex +{ + FLOAT x, y, z; + ULONG dummy; // 16 byte alingment +}; + +struct ENGINE_API MeshNormal +{ + FLOAT nx, ny, nz; + ULONG dummy; // 16 byte alingment +}; + +struct ENGINE_API MeshUVMap +{ + ULONG muv_iID; + CStaticArray muv_aTexCoords; // texture coordinates +}; + +struct ENGINE_API MeshTexCoord +{ + FLOAT u, v; +}; + +struct ENGINE_API MeshSurface +{ + INDEX msrf_iFirstVertex; + INDEX msrf_ctVertices; + INDEX msrf_iSurfaceID; + CShader *msrf_pShader; + ShaderParams msrf_ShadingParams; + CStaticArray msrf_aTriangles; // list of triangles +}; + +struct ENGINE_API MeshTriangle +{ + INDEX iVertex[3]; +}; + +struct ENGINE_API MeshWeightMap +{ + int mwm_iID; + CStaticArray mwm_aVertexWeight; // weight maps +}; + +struct ENGINE_API MeshVertexWeight +{ + INDEX mww_iVertex; // absolute index of the vertex this weight refers to + FLOAT mww_fWeight; // weight for this bone [0.0 - 1.0] +}; + +struct ENGINE_API MeshMorphMap +{ + INDEX mmp_iID; + BOOL mmp_bRelative; + CStaticArray mmp_aMorphMap; // Morph maps +}; + +struct ENGINE_API MeshVertexMorph +{ + INDEX mwm_iVxIndex; // absolute index of the vertex this weight refers to + FLOAT mwm_x; + FLOAT mwm_y; + FLOAT mwm_z; + FLOAT mwm_nx; + FLOAT mwm_ny; + FLOAT mwm_nz; + ULONG dummy; // 32 byte padding +}; + +class ENGINE_API CMesh : public CSerial +{ +public: + CMesh(); + ~CMesh(); + void Optimize(void); + void OptimizeLod(MeshLOD &mLod); + void NormalizeWeights(void); + void NormalizeWeightsInLod(MeshLOD &mlod); + + void AddMeshLod(MeshLOD &mlod); + void RemoveMeshLod(MeshLOD *pmlodRemove); + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * + void Clear(void); + SLONG GetUsedMemory(void); + CStaticArray msh_aMeshLODs; +}; +ENGINE_API void ChangeSurfaceShader_t(MeshSurface &msrf,CTString fnNewShader); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Ska/ModelInstance.cpp b/Sources/Engine/Ska/ModelInstance.cpp new file mode 100644 index 0000000..ce83e49 --- /dev/null +++ b/Sources/Engine/Ska/ModelInstance.cpp @@ -0,0 +1,1092 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// does parser remember smc source files? +BOOL bRememberSourceFN = FALSE; + +// pointer to model instance for parser +CModelInstance *_yy_mi = NULL; + +// calculate fade factor of animation list in animqueue +FLOAT CalculateFadeFactor(AnimList &alList) +{ + if(alList.al_fFadeTime==0) { + return 1.0f; + } + + FLOAT fFadeFactor = (_pTimer->GetLerpedCurrentTick() - alList.al_fStartTime) / alList.al_fFadeTime; + return Clamp(fFadeFactor,0.0f,1.0f); +} +// create model instance +CModelInstance *CreateModelInstance(CTString strName) +{ + CModelInstance *pmi = new CModelInstance; + pmi->SetName(strName); + return pmi; +} +void DeleteModelInstance(CModelInstance *pmi) +{ + ASSERT(pmi!=NULL); + // if model instance is valid + if(pmi!=NULL) { + // Clear model instance + pmi->Clear(); + // Delete model instance + delete pmi; + pmi = NULL; + } +} + +// Parse smc file in existing model instance +void ParseSmcFile_t(CModelInstance &mi, const CTString &fnSmcFile) +{ + // Clear given model instance before parsing + mi.Clear(); + + CTFileName fnFileName = fnSmcFile; + try { + fnFileName.RemoveApplicationPath_t(); + } catch (char *) { + } + + CTString strIncludeFile; + strIncludeFile.Load_t(fnFileName); + + _yy_mi = &mi; + SMCPushBuffer(fnFileName, strIncludeFile, TRUE); + syyparse(); +} + +// Create model instance and parse smc file in it +CModelInstance *ParseSmcFile_t(const CTString &fnSmcFile) +{ + _yy_mi = NULL; + // Create new model instance for parser + _yy_mi = CreateModelInstance("Temp"); + // Parse given smc file + ParseSmcFile_t(*_yy_mi,fnSmcFile); + + return _yy_mi; +} + +CModelInstance::CModelInstance() +{ + mi_psklSkeleton = NULL; + mi_iParentBoneID = -1; + mi_colModelColor = 0; + mi_vStretch = FLOAT3D(1,1,1); + mi_colModelColor = 0xFFFFFFFF; + mi_aqAnims.aq_Lists.SetAllocationStep(1); + mi_cmiChildren.SetAllocationStep(1); + memset(&mi_qvOffset,0,sizeof(QVect)); + mi_qvOffset.qRot.q_w = 1; + mi_iCurentBBox = -1; + // set default all frames bbox +// mi_cbAllFramesBBox.SetName("All Frames Bounding box"); + mi_cbAllFramesBBox.SetMin(FLOAT3D(-0.5,0,-0.5)); + mi_cbAllFramesBBox.SetMax(FLOAT3D(0.5,2,0.5)); + // Set default model instance name +// SetName("Noname"); +} + +CModelInstance::~CModelInstance() +{ +} +// copy constructor +CModelInstance::CModelInstance(CModelInstance &miOther) +{ + // Forbiden + ASSERT(FALSE); +} +void CModelInstance::operator=(CModelInstance &miOther) +{ + // Forbiden + ASSERT(FALSE); +} + +void CModelInstance::GetAllFramesBBox(FLOATaabbox3D &aabbox) +{ + aabbox = FLOATaabbox3D(mi_cbAllFramesBBox.Min(),mi_cbAllFramesBBox.Max()); +} + +// fills curent colision box info +void CModelInstance::GetCurrentColisionBox(FLOATaabbox3D &aabbox) +{ + ColisionBox &cb = GetCurrentColisionBox(); + aabbox = FLOATaabbox3D(cb.Min(),cb.Max()); +} + +ColisionBox &CModelInstance::GetCurrentColisionBox() +{ + ASSERT(mi_iCurentBBox>=0); + ASSERT(mi_iCurentBBox0); + + return mi_cbAABox[mi_iCurentBBox]; +} + + +INDEX CModelInstance::GetColisionBoxIndex(INDEX iBoxID) +{ + INDEX ctcb = mi_cbAABox.Count(); + // for each existing box + for(INT icb=0;icb=0); + ASSERT(icb=mi_cbAABox.Count()) { + // give last colision box + iCollisionBox = mi_cbAABox.Count()-1; + } + // check if error is fixed + ASSERT(mi_cbAABox.Count()>iCollisionBox); + + ColisionBox &cb = this->mi_cbAABox[iCollisionBox]; + FLOAT fWeigth = cb.Max()(1) - cb.Min()(1); + FLOAT fHeight = cb.Max()(2) - cb.Min()(2); + FLOAT fLength = cb.Max()(3) - cb.Min()(3); + if(fLength == fHeight) { + return SKA_LENGTH_EQ_HEIGHT; + } else if(fHeight == fWeigth) { + return SKA_HEIGHT_EQ_WIDTH; + // default fLength == fWeight + } else { + return SKA_LENGTH_EQ_WIDTH; + } +}; + +// add colision box to model instance +void CModelInstance::AddColisionBox(CTString strName,FLOAT3D vMin,FLOAT3D vMax) +{ + INDEX ctcb = mi_cbAABox.Count(); + mi_cbAABox.Expand(ctcb+1); + + ColisionBox &cb = mi_cbAABox[ctcb]; + cb.SetName(strName); + cb.SetMin(vMin); + cb.SetMax(vMax); + mi_iCurentBBox = 0; +} +// remove colision box from model instance +void CModelInstance::RemoveColisionBox(INDEX iIndex) +{ + INDEX ctcb = mi_cbAABox.Count(); + INDEX icbNew = 0; + CStaticArray aColisionBoxesTemp; + aColisionBoxesTemp.New(ctcb-1); + for(INDEX icb=0;icb0) { + pmi->SetParentBone(iParentBoneID); + } +} + +// remove model instance child +void CModelInstance::RemoveChild(CModelInstance *pmi) +{ + ASSERT(pmi!=this); + SKAASSERT(pmi!=NULL); + // aditional check + if(pmi==NULL) return; + if(pmi==this) return; + + mi_cmiChildren.Remove(pmi); +} +// set new parent bone index +void CModelInstance::SetParentBone(INDEX iParentBoneID) +{ + mi_iParentBoneID = iParentBoneID; +} + +// Model instance offsets from parent model +void CModelInstance::SetOffset(FLOAT fOffset[6]) +{ + FLOAT3D fRot(fOffset[3],fOffset[4],fOffset[5]); + mi_qvOffset.qRot.FromEuler(fRot); + mi_qvOffset.vPos = FLOAT3D(fOffset[0],fOffset[1],fOffset[2]); +} + +void CModelInstance::SetOffsetPos(FLOAT3D vPos) +{ + mi_qvOffset.vPos = vPos; +} + +void CModelInstance::SetOffsetRot(ANGLE3D aRot) +{ + mi_qvOffset.qRot.FromEuler(aRot); +} + +FLOAT3D CModelInstance::GetOffsetPos() +{ + return mi_qvOffset.vPos; +} + +ANGLE3D CModelInstance::GetOffsetRot() +{ + ANGLE3D aRot; + FLOATmatrix3D mat; + mi_qvOffset.qRot.ToMatrix(mat); + DecomposeRotationMatrix(aRot,mat); + return aRot; +} + +// Stretch model instance +void CModelInstance::StretchModel(FLOAT3D &vStretch) +{ + mi_vStretch = vStretch; +} + +// Stretch model instance without attachments +void CModelInstance::StretchSingleModel(FLOAT3D &vStretch) +{ + mi_vStretch = vStretch; + // for each child of model instance + INDEX ctch = mi_cmiChildren.Count(); + for(INDEX ich=0;ichObtain_t(fnMesh); +} + +// Add skeleton to ModelInstance +void CModelInstance::AddSkeleton_t(CTFileName fnSkeleton) +{ + mi_psklSkeleton = _pSkeletonStock->Obtain_t(fnSkeleton); +} + +// Add AnimSet to ModelInstance +void CModelInstance::AddAnimSet_t(CTFileName fnAnimSet) +{ + CAnimSet *Anim = _pAnimSetStock->Obtain_t(fnAnimSet); + mi_aAnimSet.Add(Anim); +} + +// Add texture to ModelInstance (if no mesh instance given, add texture to last mesh instance) +void CModelInstance::AddTexture_t(CTFileName fnTexture, CTString strTexID,MeshInstance *pmshi) +{ + if(pmshi == NULL) { + INDEX ctMeshInst = mi_aMeshInst.Count(); + if(ctMeshInst<=0) throw("Error adding texture\nMesh instance does not exists"); + pmshi = &mi_aMeshInst[ctMeshInst-1]; + } + + INDEX ctTextInst = pmshi->mi_tiTextures.Count(); + pmshi->mi_tiTextures.Expand(ctTextInst+1); + pmshi->mi_tiTextures[ctTextInst].ti_toTexture.SetData_t(fnTexture); + pmshi->mi_tiTextures[ctTextInst].SetName(strTexID); +} + +// Remove one texture from model instance +void CModelInstance::RemoveTexture(TextureInstance *ptiRemove,MeshInstance *pmshi) +{ + ASSERT(pmshi!=NULL); + CStaticArray atiTextures; + INDEX ctti=pmshi->mi_tiTextures.Count(); + atiTextures.New(ctti-1); + // for each texture instance in mesh instance + INDEX iIndexSrc=0; + for(INDEX iti=0;itimi_tiTextures[iti]; + // if texture instance is different from selected one + if(pti != ptiRemove) { + // copy it to new array of texture isntances + atiTextures[iIndexSrc] = pmshi->mi_tiTextures[iti]; + iIndexSrc++; + } + } + // copy new texture instances array in mesh instance + pmshi->mi_tiTextures.CopyArray(atiTextures); + // clear temp texture isntances array + atiTextures.Clear(); +} + +// Find texture instance in all mesh instances in model instance +TextureInstance *CModelInstance::FindTexureInstance(INDEX iTexID) +{ + // for each mesh instance + INDEX ctmshi = mi_aMeshInst.Count(); + for(INDEX imshi=0;imshimi_cmiChildren.Remove(this); + pmiNewParent->mi_cmiChildren.Add(this); +} + +// return parent of this model instance +// must suply first model instance in hierarchy cos model instance does not have its parent remembered +CModelInstance *CModelInstance::GetParent(CModelInstance *pmiStartFrom) +{ + ASSERT(pmiStartFrom!=NULL); + // aditional check + if(pmiStartFrom==NULL) return NULL; + // if 'this' is member of pmiStartFrom return it + if(pmiStartFrom->mi_cmiChildren.IsMember(this)) { + return pmiStartFrom; + } + // count childrent of pmiStartFrom + INDEX ctcmi = pmiStartFrom->mi_cmiChildren.Count(); + // for each child of pmiStartFrom + for(INDEX icmi=0;icmimi_cmiChildren[icmi]); + if(pmiReturned != NULL) { + return pmiReturned; + } + } + return NULL; +} + +// returns child with specified id +/*CModelInstance *CModelInstance::GetChild(INDEX iChildID, BOOL bRecursive) +{ + INDEX ctcmi = mi_cmiChildren.Count(); + for(INDEX icmi=0;icmimi_iModelID == iChildID) { + return pmi; + } + } + return NULL; +}*/ +CModelInstance *CModelInstance::GetChild(INDEX iChildID, BOOL bRecursive/*=FALSE*/) +{ + INDEX ctcmi = mi_cmiChildren.Count(); + for(INDEX icmi=0;icmimi_iModelID == iChildID) { + return pmi; + } + // if child has own children, go recursive + if(bRecursive && pmi->mi_cmiChildren.Count()>0) { + pmi = pmi->GetChild(iChildID, TRUE); + if (pmi!=NULL) return pmi; + } + } + return NULL; +} + +// returns parent that is not included in his parents smc file +CModelInstance *CModelInstance::GetFirstNonReferencedParent(CModelInstance *pmiRoot) +{ + ASSERT(this!=NULL); + ASSERT(pmiRoot!=NULL); + CModelInstance *pmiParent = this->GetParent(pmiRoot); + CModelInstance *pmiLast = this; + while(pmiParent != NULL) + { + if(pmiParent->mi_fnSourceFile != mi_fnSourceFile) + { + return pmiLast; + } + pmiLast = pmiParent; + pmiParent = pmiParent->GetParent(pmiRoot); + } + return NULL;//return pmiRoot +} + +// add animation to ModelInstance +void CModelInstance::AddAnimation(INDEX iAnimID, ULONG ulFlags, FLOAT fStrength, INDEX iGroupID, FLOAT fSpeedMul/*=1.0f*/) +{ + +#ifdef SKADEBUG +// see whether this animation even exists in the current skeleton +INDEX iDummy1, iDummy2; +if (!FindAnimationByID(iAnimID, &iDummy1, &iDummy2)) { + /*this ModelInstance does not contain the required animation!!!*/ + SKAASSERT(FALSE); +} +#endif + + fSpeedMul = 1/fSpeedMul; + // if no restart flag was set + if(ulFlags&AN_NORESTART) { + // if given animtion is allready playing + if(IsAnimationPlaying(iAnimID)) { + if(ulFlags&AN_LOOPING) { + AddFlagsToPlayingAnim(iAnimID,AN_LOOPING); + } + // return without adding animtion + return; + } + } + + // if flag for new cleared state is set + if(ulFlags&AN_CLEAR) { + // do new clear state with default length + NewClearState(CLEAR_STATE_LENGTH); + // if flag for new cloned state is set + } else if(ulFlags&AN_CLONE) { + // do new clear state with default length + NewClonedState(CLONED_STATE_LENGTH); + } + + // if anim queue is empty + INDEX ctal = mi_aqAnims.aq_Lists.Count(); + if(ctal == 0) { + // add new clear state + NewClearState(0); + } + + ctal = mi_aqAnims.aq_Lists.Count(); + AnimList &alList = mi_aqAnims.aq_Lists[ctal-1]; + + // if flag is set not to sort anims + if(ulFlags&AN_NOGROUP_SORT) { + // just add new animations to end of list + PlayedAnim &plAnim = alList.al_PlayedAnims.Push(); + plAnim.pa_iAnimID = iAnimID; + plAnim.pa_fSpeedMul = fSpeedMul; + plAnim.pa_fStartTime = _pTimer->CurrentTick(); + plAnim.pa_Strength = fStrength; + plAnim.pa_ulFlags = ulFlags; + plAnim.pa_GroupID = iGroupID; + // no flag set, sort animation by groupID + } else { + // add one animation to anim list + alList.al_PlayedAnims.Push(); + INDEX ctpa = alList.al_PlayedAnims.Count(); + + INDEX ipa=ctpa-1; + if(ipa>0) { + // for each old animation from last to first + for(;ipa>0;ipa--) { + PlayedAnim &pa = alList.al_PlayedAnims[ipa-1]; + PlayedAnim &paNext = alList.al_PlayedAnims[ipa]; + // if anim group id is larger than new group id + if(pa.pa_GroupID>iGroupID) { + // move animation in array to right + paNext = pa; + } else break; + } + } + // set new animation as current index in anim list + PlayedAnim &plAnim = alList.al_PlayedAnims[ipa]; + plAnim.pa_iAnimID = iAnimID; + plAnim.pa_fSpeedMul = fSpeedMul; + plAnim.pa_fStartTime = _pTimer->CurrentTick(); + plAnim.pa_Strength = fStrength; + plAnim.pa_ulFlags = ulFlags; + plAnim.pa_GroupID = iGroupID; + } +} + +// remove played anim from stack +void CModelInstance::RemAnimation(INDEX iAnimID) +{ + INDEX ctal = mi_aqAnims.aq_Lists.Count(); + // if anim queue is empty + if(ctal < 1) { + SKAASSERT(FALSE); + // no anim to remove + return; + } + + // get last anim list in queue + AnimList &alList = mi_aqAnims.aq_Lists[ctal-1]; + // count played anims in anim list + INDEX ctpa = alList.al_PlayedAnims.Count(); + // loop each played anim in anim list + for(int ipa=0;ipa=0;ial--) + { + AnimList &alList = mi_aqAnims.aq_Lists[ial]; + // calculate fade factor for this animlist + FLOAT fFadeFactor = CalculateFadeFactor(alList); + // if factor is 1 remove all animlists before this one + if(fFadeFactor >= 1.0f) { + iFirstAnimList = ial; + break; + } + } + if(iFirstAnimList <= 0) return; + // move later anim lists to first pos + for(ial=iFirstAnimList;ialCurrentTick(); +} + +// create new cleared state and give it a fade time +void CModelInstance::NewClearState(FLOAT fFadeTime) +{ + RemovePassedAnimsFromQueue(); + // add new empty list + AnimList &alNewList = mi_aqAnims.aq_Lists.Push(); + alNewList.al_PlayedAnims.SetAllocationStep(1); + alNewList.al_fFadeTime = fFadeTime; + alNewList.al_fStartTime = _pTimer->CurrentTick(); + alNewList.al_PlayedAnims.PopAll(); +} + +// stop all animations in this model instance and its children +void CModelInstance::StopAllAnimations(FLOAT fFadeTime) +{ + INDEX ctmi = mi_cmiChildren.Count(); + for(INDEX imi=0;imi=0;ias--) { + CAnimSet &asAnimSet = mi_aAnimSet[ias]; + INDEX ctan = asAnimSet.as_Anims.Count(); + // for each animation + for(int ian=0;ian0) { + // check last one + AnimList &al = mi_aqAnims.aq_Lists[ctal-1]; + INDEX ctpa = al.al_PlayedAnims.Count(); + for(INDEX ipa=0;ipa0) { + // check last one + AnimList &al = mi_aqAnims.aq_Lists[ctal-1]; + INDEX ctpa = al.al_PlayedAnims.Count(); + for(INDEX ipa=0;ipa &avVertices, FLOATmatrix3D &mRotation, + FLOAT3D &vPosition, FLOAT fNormalOffset, FLOAT fDistance) +{ + RM_SetObjectPlacement(mRotation,vPosition); + RM_GetModelVertices(*this,avVertices, mRotation, vPosition, fNormalOffset, fDistance); +} + +// Model color +COLOR &CModelInstance::GetModelColor(void) +{ + return mi_colModelColor; +} +void CModelInstance::SetModelColor(COLOR colNewColor) +{ + mi_colModelColor = colNewColor; + INDEX ctch = mi_cmiChildren.Count(); + // for each child + for(INDEX ich=0;ich> IsModelVisible") + return TRUE; +} + +BOOL CModelInstance::HasShadow(FLOAT fMipFactor) +{ + #pragma message(">> HasShadow") + return TRUE; +} + +// simple shadow rendering +void CModelInstance::AddSimpleShadow( const FLOAT fIntensity, const FLOATplane3D &plShadowPlane) +{ + + // if shadows are not rendered for current mip, model is half/full face-forward, + // intensitiy is too low or projection is not perspective - do nothing! + //if( !HasShadow(1) || fIntensity<0.01f || !_aprProjection.IsPerspective() + // || (rm.rm_pmdModelData->md_Flags&(MF_FACE_FORWARD|MF_HALF_FACE_FORWARD))) return; + // ASSERT( _iRenderingType==1); + ASSERT( fIntensity>0 && fIntensity<=1); + // do some rendering + // _pfModelProfile.StartTimer( CModelProfile::PTI_RENDERSIMPLESHADOW); + // _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_RENDERSIMPLESHADOW); + // _sfStats.IncrementCounter( CStatForm::SCI_MODELSHADOWS); + // calculate projection model bounding box in object space (if needed) + // CalculateBoundingBox( this, rm); + // add one simple shadow to batch list + RM_SetObjectMatrices(*this); + RM_AddSimpleShadow_View(*this, fIntensity, plShadowPlane); + // all done + // _pfModelProfile.StopTimer( CModelProfile::PTI_RENDERSIMPLESHADOW); + +} + +// Copy mesh instance for other model instance +void CModelInstance::CopyMeshInstance(CModelInstance &miOther) +{ + INDEX ctmshi = miOther.mi_aMeshInst.Count(); + // for each mesh insntace + for(INDEX imshi=0;imshiGetName()); + MeshInstance *pmshi = &mi_aMeshInst[imshi]; + + INDEX ctti = mshiOther.mi_tiTextures.Count(); + // for each texture in mesh instance + for(INDEX iti=0;itiGetName()); + } + + // copy animsets + INDEX ctas = miOther.mi_aAnimSet.Count(); + // for each animset + for(INDEX ias=0;iasCopy(chmiOther); + AddChild(pchmi); + } +} + +// Synchronize with another model (copy animations/attachments positions etc from there) +void CModelInstance::Synchronize(CModelInstance &miOther) +{ + // Sync animations + mi_aqAnims.aq_Lists = miOther.mi_aqAnims.aq_Lists; + // Sync misc params + mi_qvOffset = miOther.mi_qvOffset; + mi_iParentBoneID = miOther.mi_iParentBoneID; + mi_colModelColor = miOther.mi_colModelColor; + mi_vStretch = miOther.mi_vStretch; + + // for each child in model instance + INDEX ctchmi=mi_cmiChildren.Count(); + for(INDEX ichmi=0;ichmiRelease(pmesh); + } + // release all textures in stock used by mesh + INDEX ctti = mshi.mi_tiTextures.Count(); + for(INDEX iti=0;itiRelease(mi_psklSkeleton); + mi_psklSkeleton = NULL; + } + + // release all animsets in stock used by mi + INDEX ctas = mi_aAnimSet.Count(); + for(INDEX ias=0;iasRelease(&mi_aAnimSet[ias]); + } + mi_aAnimSet.Clear(); + + // clear all colision boxes + mi_cbAABox.Clear(); + // clear anim list + mi_aqAnims.aq_Lists.Clear(); +} + +// Count used memory +SLONG CModelInstance::GetUsedMemory(void) +{ + SLONG slMemoryUsed = sizeof(*this); + // Count mesh instances + INDEX ctmshi = mi_aMeshInst.Count(); + for(INDEX imshi=0;imshi +#include +#include +#include +#include +#include +#include +#include + +// nubers are same as in models.h +#define SKA_HEIGHT_EQ_WIDTH 0 +#define SKA_LENGTH_EQ_WIDTH 1 +#define SKA_LENGTH_EQ_HEIGHT 2 + +// special assert for ska +#ifdef SKADEBUG + #ifdef NDEBUG + #define SKAASSERT(__ignore) ((void)0) + #else + #define SKAASSERT(expr) ASSERT(expr) + #endif +#else + #define SKAASSERT(__ignore) ((void)0) +#endif + +struct ColisionBox +{ + ColisionBox() {}; + ColisionBox(FLOAT3D vMin,FLOAT3D vMax) { + SetMin(vMin); + SetMax(vMax); +// SetName("Default"); + }; + inline FLOAT3D &Min() {return cb_vMin;} + inline FLOAT3D &Max() {return cb_vMax;} + inline void SetMin(FLOAT3D &vMin) {cb_vMin = vMin;} + inline void SetMax(FLOAT3D &vMax) {cb_vMax = vMax;} + inline void SetName(CTString strName) { + cb_strName = strName; + cb_iBoxID = ska_GetIDFromStringTable(cb_strName); + } + inline const CTString &GetName() {return cb_strName;} + inline const INDEX GetID() {return cb_iBoxID;} +private: + FLOAT3D cb_vMin; + FLOAT3D cb_vMax; + CTString cb_strName; + INDEX cb_iBoxID; +}; + +struct MeshInstance +{ + CMesh *mi_pMesh; + CStaticArray mi_tiTextures; +}; + +struct TextureInstance +{ + TextureInstance &operator=(const TextureInstance &tiOther) { + ti_iTextureID = tiOther.ti_iTextureID; + TextureInstance &ti = (TextureInstance&)tiOther; + + CTString strTexName = ti.ti_toTexture.GetName(); + ti_toTexture.SetData_t(strTexName); + ti.ti_toTexture.SetData(NULL); + return *this; + } + + INDEX GetID() {return ti_iTextureID;} + void SetName(CTString &strTexID) { + ti_iTextureID = ska_GetIDFromStringTable(strTexID); + } + +public: + CTextureObject ti_toTexture; +private: + INDEX ti_iTextureID; +}; + +struct AnimQueue +{ + CStaticStackArray aq_Lists; // Array of currently playing anim lists +}; + +struct AnimList +{ + FLOAT al_fStartTime; // Time when this list was created + FLOAT al_fFadeTime; // Time when this list will fade in + CStaticStackArray al_PlayedAnims; // Array of currently playing anims in this list +}; + +struct PlayedAnim +{ + FLOAT pa_fStartTime; // Time when this animation was started + FLOAT pa_fSpeedMul; // Speed multiplier + INDEX pa_iAnimID; // Animation id + ULONG pa_ulFlags; // Animation flags + FLOAT pa_Strength; // Animation strength + INDEX pa_GroupID; // Group ID +}; + +class ENGINE_API CModelInstance +{ +public: + CModelInstance(); + ~CModelInstance(); + CModelInstance(CModelInstance &miOther); + void operator=(CModelInstance &miOther); + + // Add child model instance + void AddChild(CModelInstance *pmi, INDEX iParentBoneID = -1); + // Add new mesh to model instance + void AddMesh_t(CTFileName fnMesh); + // Add new skeleton to model instance + void AddSkeleton_t(CTFileName fnSkeleton); + // Add new animset to model instance + void AddAnimSet_t(CTFileName fnAnimSet); + // Add new texture to model instance + void AddTexture_t(CTFileName fnTexture, CTString strTexID, MeshInstance *pmshi); + + // Remove child model instance + void RemoveChild(CModelInstance *pmi); + // Remove one texture from model instance + void RemoveTexture(TextureInstance *ptiRemove,MeshInstance *pmshi); + + // Find mesh instance in model instance + MeshInstance *FindMeshInstance(INDEX iMeshID); + // Find texture instance in all mesh instances in model instance + TextureInstance *FindTexureInstance(INDEX iTexID); + // Find texture instance in given mesh instance + TextureInstance *FindTexureInstance(INDEX iTexID, MeshInstance &mshi); + + + // Copy mesh instance for other model instance + void CopyMeshInstance(CModelInstance &miOther); + // Get child of model instance + CModelInstance *GetChild(INDEX iChildID, BOOL bRecursive = FALSE); + // Set parent bone of model instance + void SetParentBone(INDEX iParentBoneID); + // Get parent of model instance + CModelInstance *GetParent(CModelInstance *pmiStartFrom); + // Get first parent that does not reference its child model instance + CModelInstance *GetFirstNonReferencedParent(CModelInstance *pmiRoot); + // Change parent of model instance + void ChangeParent(CModelInstance *pmiOldParent, CModelInstance *pmiNewParent); + + // Model instance offsets from parent model + void SetOffset(FLOAT fOffset[6]); + void SetOffsetRot(ANGLE3D aRot); + void SetOffsetPos(FLOAT3D vPos); + FLOAT3D GetOffsetPos(); + ANGLE3D GetOffsetRot(); + + // Stretch model instance + void StretchModel(FLOAT3D &vStretch); + // Stretch model instance without attachments + void StretchSingleModel(FLOAT3D &vStretch); + // Add new cloned anim state + void NewClonedState(FLOAT fFadeTime); + // Add new clear anim state + void NewClearState(FLOAT fFadeTime); + // Sets name of model instance + void SetName(CTString strName); + // Gets name of model instance + const CTString &GetName(); + // Gets id of model instance + const INDEX &GetID(); + + // Add animation to last anim queue + void AddAnimation(INDEX iAnimID, DWORD dwFlags, FLOAT fStrength, INDEX iGroupID, FLOAT fSpeedMul = 1.0f); + // Remove all animations before last animation that has fully faded in + void RemovePassedAnimsFromQueue(void); + // Remove animation from anim queue + void RemAnimation(INDEX iAnimID); + // Remove all animations from anim queue with same ID + void RemAnimsWithID(INDEX iGroupID); + // Stop all animations in anim queue + void StopAllAnimations(FLOAT fFadeTime); + // Offset all animations in anim queue + void OffSetAnimationQueue(TIME fOffsetTime); + // Find animation by ID + BOOL FindAnimationByID(int iAnimID, INDEX *piAnimSetIndex, INDEX *piAnimIndex); + // Find first animation of all animations in ModelInstance (safety function) + INDEX FindFirstAnimationID(); + // Get animation length + FLOAT GetAnimLength(INDEX iAnimID); + // Check if given animation is currently playing + BOOL IsAnimationPlaying(INDEX iAnimID); + // Add flags to animation playing in anim queue + BOOL AddFlagsToPlayingAnim(INDEX iAnimID, ULONG ulFlags); + + // Model color + COLOR &GetModelColor(void); + void SetModelColor(COLOR colNewColor); + + BOOL HasAlpha(void); + BOOL HasShadow(FLOAT fMipFactor); + BOOL IsModelVisible( FLOAT fMipFactor); + void AddSimpleShadow( const FLOAT fIntensity, const FLOATplane3D &plShadowPlane); + void GetModelVertices( CStaticStackArray &avVertices, FLOATmatrix3D &mRotation,FLOAT3D &vPosition, FLOAT fNormalOffset, FLOAT fDistance); + + // Colision boxes + ColisionBox &GetColisionBox(INDEX icb); + ColisionBox &GetCurrentColisionBox(); + void GetCurrentColisionBox(FLOATaabbox3D &paabbox); + void GetAllFramesBBox(FLOATaabbox3D &aabbox); + FLOAT3D GetCollisionBoxMin(INDEX iCollisionBox=0); + FLOAT3D GetCollisionBoxMax(INDEX iCollisionBox=0); + INDEX GetCollisionBoxDimensionEquality(INDEX iCollisionBox=0); + INDEX GetColisionBoxIndex(INDEX iBoxID); + // Add new colision box to model instance + void AddColisionBox(CTString strName,FLOAT3D vMin,FLOAT3D vMax); + // Remove colision box from model instance + void RemoveColisionBox(INDEX iIndex); + + // Copy model instance data from other mi + void Copy(CModelInstance &miOther); + // Synchronize with another model (copy animations/attachments positions etc from there) + void Synchronize(CModelInstance &miOther); + // Clear model instance + void Clear(); + // Flag for parser to remember source file names (used only in ska studio) + static void EnableSrcRememberFN(BOOL bEnable); + // Count used memory + SLONG GetUsedMemory(void); + +public: + CSkeleton *mi_psklSkeleton; // pointer to skeleton object + CStaticArray mi_aMeshInst; // array of mesh instances + CStaticArray mi_cbAABox; // array of colision boxes + CDynamicContainer mi_aAnimSet; // array of animsets + CDynamicContainer mi_cmiChildren; // array of child model instances + + AnimQueue mi_aqAnims; // current animation queue for this model instance + QVect mi_qvOffset; // current offset from parent model instance + INDEX mi_iParentBoneID; // ID of parent bone in parent model instance + INDEX mi_iCurentBBox; // index of current colision box in colision box array + COLOR mi_colModelColor; // color of this model instance + FLOAT3D mi_vStretch; // stretch of this model instance + ColisionBox mi_cbAllFramesBBox; // all frames colision box + CTFileName mi_fnSourceFile; // source file name of this model instance (used only for ska studio) + +private: + INDEX mi_iModelID; // ID of this model instance (this is ID for mi_strName) + CTString mi_strName; // name of this model instance +}; + +// Parse smc file in existing model instance +ENGINE_API void ParseSmcFile_t(CModelInstance &mi, const CTString &fnSmcFile); +// Create model instance and parse smc file in it +ENGINE_API CModelInstance *ParseSmcFile_t(const CTString &fnSmcFile); +// Create empty model instance +ENGINE_API CModelInstance *CreateModelInstance(CTString strName); +// Delete model instance +ENGINE_API void DeleteModelInstance(CModelInstance *pmi); +// Calculate fading factor for animation list +ENGINE_API FLOAT CalculateFadeFactor(AnimList &alList); + + +#endif /* include-once check. */ diff --git a/Sources/Engine/Ska/ParsingSmbs.h b/Sources/Engine/Ska/ParsingSmbs.h new file mode 100644 index 0000000..a8ab588 --- /dev/null +++ b/Sources/Engine/Ska/ParsingSmbs.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// needed for parser and scanner +extern int yylex(void); +extern void yyerror(char *s); +extern int syyparse(void); +extern void syyrestart(FILE *f); + +#define YY_NEVER_INTERACTIVE 1 + +#define SMC_MAX_INCLUDE_LEVEL 32 +// temporary values for parsing +extern INDEX _yy_iIndex; +extern CModelInstance *_yy_mi; + +void SMCPushBuffer(const char *strName, const char *strBuffer, BOOL bParserEnd); +BOOL SMCPopBuffer(void); +const char *SMCGetBufferName(void); +int SMCGetBufferLineNumber(void); +const char *SMCGetBufferContents(void); +int SMCGetBufferStackDepth(void); + +void SMCCountOneLine(void); diff --git a/Sources/Engine/Ska/RMRender.cpp b/Sources/Engine/Ska/RMRender.cpp new file mode 100644 index 0000000..7d40325 --- /dev/null +++ b/Sources/Engine/Ska/RMRender.cpp @@ -0,0 +1,2591 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static CAnyProjection3D _aprProjection; +static CDrawPort *_pdp = NULL; +static enum FPUPrecisionType _fpuOldPrecision; +static INDEX _iRenderingType = 0; // 0=none, 1=view, 2=mask + +static FLOAT3D _vLightDir; // Light direction +static FLOAT3D _vLightDirInView; // Light direction transformed in view space +static COLOR _colAmbient; // Ambient color +static COLOR _colLight; // Light color +static FLOAT _fDistanceFactor; // Distance to object from viewer +static Matrix12 _mObjectToAbs; // object to absolute +static Matrix12 _mAbsToViewer; // absolute to viewer +static Matrix12 _mObjToView; // object to viewer +static Matrix12 _mObjToViewStretch; // object to viewer, stretch by root model instance stretch factor + +ULONG _ulFlags = RMF_SHOWTEXTURE; +static ULONG _ulRenFlags = 0; +static FLOAT _fCustomMlodDistance=-1; // custom distance for mesh lods +static FLOAT _fCustomSlodDistance=-1; // custom distance for skeleton lods +extern FLOAT ska_fLODMul; +extern FLOAT ska_fLODAdd; + +// mask shader (for rendering models' shadows to shadowmaps) +static CShader _shMaskShader; + +// temporary rendering structures +static CStaticStackArray _aRenModels; +static CStaticStackArray _aRenBones; +static CStaticStackArray _aRenMesh; +static CStaticStackArray _aRenMorph; +static CStaticStackArray _aRenWeights; +static CStaticStackArray _aMorphedVtxs; +static CStaticStackArray _aMorphedNormals; +static CStaticStackArray _aFinalVtxs; +static CStaticStackArray _aFinalNormals; +static CStaticStackArray _aMeshColors; +static CStaticStackArray _aTexMipFogy; +static CStaticStackArray _aTexMipHazey; + +static MeshVertex *_pavFinalVertices = NULL; // pointer to final arrays +static MeshNormal *_panFinalNormals = NULL; // pointer to final normals +static INDEX _ctFinalVertices; // final vertices count +BOOL _bTransformBonelessModelToViewSpace = TRUE; // are boneless models transformed to view space + +// Pointers for bone adjustment function +static void (*_pAdjustBonesCallback)(void *pData) = NULL; +static void *_pAdjustBonesData = NULL; +// Pointers for shader params adjustment function +static void (*_pAdjustShaderParams)(void *pData, INDEX iSurfaceID, CShader *pShader,ShaderParams &shParams) = NULL; +static void *_pAdjustShaderData = NULL; + +static BOOL FindRenBone(RenModel &rm,int iBoneID,INDEX *piBoneIndex); +static void PrepareMeshForRendering(RenMesh &rmsh, INDEX iSkeletonlod); +static void CalculateRenderingData(CModelInstance &mi); +static void ClearRenArrays(); + +// load our 3x4 matrix from old-fashioned matrix+vector combination +inline void MatrixVectorToMatrix12(Matrix12 &m12,const FLOATmatrix3D &m, const FLOAT3D &v) +{ + m12[ 0] = m(1,1); m12[ 1] = m(1,2); m12[ 2] = m(1,3); m12[ 3] = v(1); + m12[ 4] = m(2,1); m12[ 5] = m(2,2); m12[ 6] = m(2,3); m12[ 7] = v(2); + m12[ 8] = m(3,1); m12[ 9] = m(3,2); m12[10] = m(3,3); m12[11] = v(3); +} + +// convert matrix12 to old matrix 3x3 and vector +inline void Matrix12ToMatrixVector(FLOATmatrix3D &c, FLOAT3D &v, const Matrix12 &m12) +{ + c(1,1) = m12[ 0]; c(1,2) = m12[ 1]; c(1,3) = m12[ 2]; v(1) = m12[ 3]; + c(2,1) = m12[ 4]; c(2,2) = m12[ 5]; c(2,3) = m12[ 6]; v(2) = m12[ 7]; + c(3,1) = m12[ 8]; c(3,2) = m12[ 9]; c(3,3) = m12[10]; v(3) = m12[11]; +} + +// create matrix from vector without rotations +inline static void MakeStretchMatrix(Matrix12 &c, const FLOAT3D &v) +{ + c[ 0] = v(1); c[ 1] = 0.0f; c[ 2] = 0.0f; c[ 3] = 0.0f; + c[ 4] = 0.0f; c[ 5] = v(2); c[ 6] = 0.0f; c[ 7] = 0.0f; + c[ 8] = 0.0f; c[ 9] = 0.0f; c[10] = v(3); c[11] = 0.0f; +} + +// Remove rotation from matrix (make it front face) +inline static void RemoveRotationFromMatrix(Matrix12 &mat) +{ + mat[ 0] = 1; mat[ 1] = 0; mat[ 2] = 0; + mat[ 4] = 0; mat[ 5] = 1; mat[ 6] = 0; + mat[ 8] = 0; mat[ 9] = 0; mat[10] = 1; +} + +// set given matrix as identity matrix +inline static void MakeIdentityMatrix(Matrix12 &mat) +{ + memset(&mat,0,sizeof(mat)); + mat[0] = 1; + mat[5] = 1; + mat[10] = 1; +} + +// transform vector with given matrix +inline static void TransformVector(FLOAT3 &v, const Matrix12 &m) +{ + float x = v[0]; + float y = v[1]; + float z = v[2]; + v[0] = m[0]*x + m[1]*y + m[ 2]*z + m[ 3]; + v[1] = m[4]*x + m[5]*y + m[ 6]*z + m[ 7]; + v[2] = m[8]*x + m[9]*y + m[10]*z + m[11]; +} +inline void TransformVertex(GFXVertex &v, const Matrix12 &m) +{ + float x = v.x; + float y = v.y; + float z = v.z; + v.x = m[0]*x + m[1]*y + m[ 2]*z + m[ 3]; + v.y = m[4]*x + m[5]*y + m[ 6]*z + m[ 7]; + v.z = m[8]*x + m[9]*y + m[10]*z + m[11]; +} + +// rotate vector with given matrix ( does not translate vector ) +inline void RotateVector(FLOAT3 &v, const Matrix12 &m) +{ + float x = v[0]; + float y = v[1]; + float z = v[2]; + v[0] = m[0]*x + m[1]*y + m[ 2]*z; + v[1] = m[4]*x + m[5]*y + m[ 6]*z; + v[2] = m[8]*x + m[9]*y + m[10]*z; +} + +// copy one matrix12 to another +inline void MatrixCopy(Matrix12 &c, const Matrix12 &m) +{ + memcpy(&c,&m,sizeof(c)); +} + +// convert 3x4 matrix to QVect +inline void Matrix12ToQVect(QVect &qv,const Matrix12 &m12) +{ + FLOATmatrix3D m; + m(1,1) = m12[ 0]; m(1,2) = m12[ 1]; m(1,3) = m12[ 2]; + m(2,1) = m12[ 4]; m(2,2) = m12[ 5]; m(2,3) = m12[ 6]; + m(3,1) = m12[ 8]; m(3,2) = m12[ 9]; m(3,3) = m12[10]; + + qv.qRot.FromMatrix(m); + qv.vPos(1) = m12[3]; + qv.vPos(2) = m12[7]; + qv.vPos(3) = m12[11]; +} + +// covert QVect to matrix 3x4 +inline void QVectToMatrix12(Matrix12 &m12, const QVect &qv) +{ + FLOATmatrix3D m; + qv.qRot.ToMatrix(m); + MatrixVectorToMatrix12(m12,m,qv.vPos); +} + +// concatenate two 3x4 matrices C=(MxN) +inline void MatrixMultiply(Matrix12 &c,const Matrix12 &m, const Matrix12 &n) +{ + c[0] = m[0]*n[0] + m[1]*n[4] + m[2]*n[8]; + c[1] = m[0]*n[1] + m[1]*n[5] + m[2]*n[9]; + c[2] = m[0]*n[2] + m[1]*n[6] + m[2]*n[10]; + c[3] = m[0]*n[3] + m[1]*n[7] + m[2]*n[11] + m[3]; + + c[4] = m[4]*n[0] + m[5]*n[4] + m[6]*n[8]; + c[5] = m[4]*n[1] + m[5]*n[5] + m[6]*n[9]; + c[6] = m[4]*n[2] + m[5]*n[6] + m[6]*n[10]; + c[7] = m[4]*n[3] + m[5]*n[7] + m[6]*n[11] + m[7]; + + c[8] = m[8]*n[0] + m[9]*n[4] + m[10]*n[8]; + c[9] = m[8]*n[1] + m[9]*n[5] + m[10]*n[9]; + c[10] = m[8]*n[2] + m[9]*n[6] + m[10]*n[10]; + c[11] = m[8]*n[3] + m[9]*n[7] + m[10]*n[11] + m[11]; +} + +// multiply two matrices into first one +inline void MatrixMultiplyCP(Matrix12 &c,const Matrix12 &m, const Matrix12 &n) +{ + Matrix12 mTemp; + MatrixMultiply(mTemp,m,n); + MatrixCopy(c,mTemp); +} + +// make transpose matrix +inline void MatrixTranspose(Matrix12 &r, const Matrix12 &m) +{ + r[ 0] = m[ 0]; + r[ 5] = m[ 5]; + r[10] = m[10]; + r[ 3] = m[ 3]; + r[ 7] = m[ 7]; + r[11] = m[11]; + + r[1] = m[4]; + r[2] = m[8]; + r[4] = m[1]; + r[8] = m[2]; + r[6] = m[9]; + r[9] = m[6]; + + r[ 3] = -r[0]*m[3] - r[1]*m[7] - r[ 2]*m[11]; + r[ 7] = -r[4]*m[3] - r[5]*m[7] - r[ 6]*m[11]; + r[11] = -r[8]*m[3] - r[9]*m[7] - r[10]*m[11]; +} + +// viewer absolute and object space projection +static FLOAT3D _vViewer; +static FLOAT3D _vViewerObj; +static FLOAT3D _vLightObj; +// returns haze/fog value in vertex +static FLOAT3D _vZDirView, _vHDirView; +static FLOAT _fFogAddZ, _fFogAddH; +static FLOAT _fHazeAdd; + +// check vertex against fog +static void GetFogMapInVertex( GFXVertex4 &vtx, GFXTexCoord &tex) +{ + const FLOAT fD = vtx.x*_vZDirView(1) + vtx.y*_vZDirView(2) + vtx.z*_vZDirView(3); + const FLOAT fH = vtx.x*_vHDirView(1) + vtx.y*_vHDirView(2) + vtx.z*_vHDirView(3); + tex.s = (fD+_fFogAddZ) * _fog_fMulZ; +// tex.s = (vtx.z) * _fog_fMulZ; + tex.t = (fH+_fFogAddH) * _fog_fMulH; +} + +// check vertex against haze +static void GetHazeMapInVertex( GFXVertex4 &vtx, FLOAT &tx1) +{ + const FLOAT fD = vtx.x*_vViewerObj(1) + vtx.y*_vViewerObj(2) + vtx.z*_vViewerObj(3); + tx1 = (fD+_fHazeAdd) * _haze_fMul; +} + +// check model's bounding box against fog +static BOOL IsModelInFog( FLOAT3D &vMin, FLOAT3D &vMax) +{ + GFXTexCoord tex; + GFXVertex4 vtx; + vtx.x=vMin(1); vtx.y=vMin(2); vtx.z=vMin(3); GetFogMapInVertex(vtx,tex); if(InFog(tex.t)) return TRUE; + vtx.x=vMin(1); vtx.y=vMin(2); vtx.z=vMax(3); GetFogMapInVertex(vtx,tex); if(InFog(tex.t)) return TRUE; + vtx.x=vMin(1); vtx.y=vMax(2); vtx.z=vMin(3); GetFogMapInVertex(vtx,tex); if(InFog(tex.t)) return TRUE; + vtx.x=vMin(1); vtx.y=vMax(2); vtx.z=vMax(3); GetFogMapInVertex(vtx,tex); if(InFog(tex.t)) return TRUE; + vtx.x=vMax(1); vtx.y=vMin(2); vtx.z=vMin(3); GetFogMapInVertex(vtx,tex); if(InFog(tex.t)) return TRUE; + vtx.x=vMax(1); vtx.y=vMin(2); vtx.z=vMax(3); GetFogMapInVertex(vtx,tex); if(InFog(tex.t)) return TRUE; + vtx.x=vMax(1); vtx.y=vMax(2); vtx.z=vMin(3); GetFogMapInVertex(vtx,tex); if(InFog(tex.t)) return TRUE; + vtx.x=vMax(1); vtx.y=vMax(2); vtx.z=vMax(3); GetFogMapInVertex(vtx,tex); if(InFog(tex.t)) return TRUE; + return FALSE; +} + +// check model's bounding box against haze +static BOOL IsModelInHaze( FLOAT3D &vMin, FLOAT3D &vMax) +{ + FLOAT fS; + GFXVertex4 vtx; + vtx.x=vMin(1); vtx.y=vMin(2); vtx.z=vMin(3); GetHazeMapInVertex(vtx,fS); if(InHaze(fS)) return TRUE; + vtx.x=vMin(1); vtx.y=vMin(2); vtx.z=vMax(3); GetHazeMapInVertex(vtx,fS); if(InHaze(fS)) return TRUE; + vtx.x=vMin(1); vtx.y=vMax(2); vtx.z=vMin(3); GetHazeMapInVertex(vtx,fS); if(InHaze(fS)) return TRUE; + vtx.x=vMin(1); vtx.y=vMax(2); vtx.z=vMax(3); GetHazeMapInVertex(vtx,fS); if(InHaze(fS)) return TRUE; + vtx.x=vMax(1); vtx.y=vMin(2); vtx.z=vMin(3); GetHazeMapInVertex(vtx,fS); if(InHaze(fS)) return TRUE; + vtx.x=vMax(1); vtx.y=vMin(2); vtx.z=vMax(3); GetHazeMapInVertex(vtx,fS); if(InHaze(fS)) return TRUE; + vtx.x=vMax(1); vtx.y=vMax(2); vtx.z=vMin(3); GetHazeMapInVertex(vtx,fS); if(InHaze(fS)) return TRUE; + vtx.x=vMax(1); vtx.y=vMax(2); vtx.z=vMax(3); GetHazeMapInVertex(vtx,fS); if(InHaze(fS)) return TRUE; + return FALSE; +} + +BOOL PrepareHaze(void) +{ + ULONG &ulRenFlags = RM_GetRenderFlags(); + if( ulRenFlags & SRMF_HAZE) { + _fHazeAdd = _haze_hp.hp_fNear; + _fHazeAdd += -_mObjToView[11]; +/* + // get viewer -z in viewer space + _vZDirView = FLOAT3D(0,0,-1); + // get fog direction in viewer space + // _vHDirView = _fog_vHDirAbs; + // RotateVector(_vHDirView.vector, _mAbsToViewer); + _vHDirView = _fog_vHDirView; + // get viewer offset + // _fFogAddZ = _vViewer % (rm.rm_vObjectPosition - _aprProjection->pr_vViewerPosition); // BUG in compiler !!!! + _fFogAddZ = -_mObjToView[11]; + // get fog offset + _fFogAddH = _fog_fAddH;/*( + _vHDirView(1)*_mObjToView[3] + + _vHDirView(2)*_mObjToView[7] + + _vHDirView(3)*_mObjToView[11]) + _fog_fp.fp_fH3; + CPrintF("hdir:%g,%g,%g addz:%g addh:%g\n", _vHDirView(1), _vHDirView(2), _vHDirView(3), _fFogAddZ, _fFogAddH); +*/ + return TRUE; + } + return FALSE; +} + +BOOL PrepareFog(void) +{ + ULONG &ulRenFlags = RM_GetRenderFlags(); + + if( ulRenFlags & SRMF_FOG) { + // get viewer -z in viewer space + _vZDirView = FLOAT3D(0,0,-1); + // get fog direction in viewer space + // _vHDirView = _fog_vHDirAbs; + // RotateVector(_vHDirView.vector, _mAbsToViewer); + _vHDirView = _fog_vHDirView; + // get viewer offset + // _fFogAddZ = _vViewer % (rm.rm_vObjectPosition - _aprProjection->pr_vViewerPosition); // BUG in compiler !!!! + _fFogAddZ = -_mObjToView[11]; + // get fog offset + _fFogAddH = _fog_fAddH;/*( + _vHDirView(1)*_mObjToView[3] + + _vHDirView(2)*_mObjToView[7] + + _vHDirView(3)*_mObjToView[11]) + _fog_fp.fp_fH3; + CPrintF("hdir:%g,%g,%g addz:%g addh:%g\n", _vHDirView(1), _vHDirView(2), _vHDirView(3), _fFogAddZ, _fFogAddH);*/ + return TRUE; + } + return FALSE; +} + +// Update model for fog and haze +void RM_DoFogAndHaze(BOOL bOpaqueSurface) +{ + // get current surface vertex array + GFXVertex4 *paVertices; + GFXColor *paColors; + GFXColor *paHazeColors; + INDEX ctVertices = shaGetVertexCount(); + + paVertices = shaGetVertexArray(); + paColors = shaGetColorArray(); + paHazeColors = shaGetNewColorArray(); + + // if this is opaque surface + if(bOpaqueSurface) { + // + if(PrepareFog()) { + _aTexMipFogy.PopAll(); + _aTexMipFogy.Push(ctVertices); + // setup tex coords only + for( INDEX ivtx=0; ivtx &avVertices, FLOATmatrix3D &mRotation, + FLOAT3D &vPosition, FLOAT fNormalOffset, FLOAT fDistance) +{ + // Transform all vertices in view space + BOOL bTemp = _bTransformBonelessModelToViewSpace; + _bTransformBonelessModelToViewSpace = TRUE; + + // only root model instances + ASSERT(mi.mi_iParentBoneID==-1); + // remember parent bone ID + INDEX iOldParentBoneID = mi.mi_iParentBoneID; + // set parent bone ID as -1 + mi.mi_iParentBoneID = -1; + + // Reset abs to viewer matrix + MakeIdentityMatrix(_mAbsToViewer); + RM_SetCurrentDistance(fDistance); + CalculateRenderingData(mi); + + // for each ren model + INDEX ctrmsh = _aRenModels.Count(); + for(int irmsh=1;irmsh> Fix this") + FLOAT3D vVtx = FLOAT3D(_pavFinalVertices[ivtx].x,_pavFinalVertices[ivtx].y,_pavFinalVertices[ivtx].z); + FLOAT3D vNor = FLOAT3D(_panFinalNormals[ivtx].nx,_panFinalNormals[ivtx].ny,_panFinalNormals[ivtx].nz); + // add vertex to given vertex array + avVertices[ivtx+ctvtxGiven] = vVtx+(vNor*fNormalOffset); + } + } + } + // restore old bone parent ID + mi.mi_iParentBoneID = iOldParentBoneID; + ClearRenArrays(); + _bTransformBonelessModelToViewSpace = bTemp; +} + + + + + +FLOAT RM_TestRayCastHit( CModelInstance &mi, FLOATmatrix3D &mRotation, FLOAT3D &vPosition,const FLOAT3D &vOrigin, + const FLOAT3D &vTarget,FLOAT fOldDistance,INDEX *piBoneID) +{ + FLOAT fDistance = 1E6f; + int i=0; + i++; + + BOOL bTemp = _bTransformBonelessModelToViewSpace; + _bTransformBonelessModelToViewSpace = TRUE; + + // ASSERT((CProjection3D *)_aprProjection!=NULL); + RM_SetObjectPlacement(mRotation,vPosition); + // Reset abs to viewer matrix + MakeIdentityMatrix(_mAbsToViewer); + // allways use the first LOD + RM_SetCurrentDistance(0); + CalculateRenderingData(mi); + // for each ren model + INDEX ctrmsh = _aRenModels.Count(); + for(int irmsh=1;irmshmi_pMesh->msh_aMeshLODs[rmsh.rmsh_iMeshLODIndex]; + INDEX ctsurf = mshlod.mlod_aSurfaces.Count(); + for(int isurf=0;isurf vVertex0(_pavFinalVertices[mshsurf.msrf_aTriangles[itri].iVertex[0]].x, + _pavFinalVertices[mshsurf.msrf_aTriangles[itri].iVertex[0]].y, + _pavFinalVertices[mshsurf.msrf_aTriangles[itri].iVertex[0]].z); + + Vector vVertex1(_pavFinalVertices[mshsurf.msrf_aTriangles[itri].iVertex[1]].x, + _pavFinalVertices[mshsurf.msrf_aTriangles[itri].iVertex[1]].y, + _pavFinalVertices[mshsurf.msrf_aTriangles[itri].iVertex[1]].z); + + Vector vVertex2(_pavFinalVertices[mshsurf.msrf_aTriangles[itri].iVertex[2]].x, + _pavFinalVertices[mshsurf.msrf_aTriangles[itri].iVertex[2]].y, + _pavFinalVertices[mshsurf.msrf_aTriangles[itri].iVertex[2]].z); + + Plane plTriPlane(vVertex0,vVertex1,vVertex2); + FLOAT fDistance0 = plTriPlane.PointDistance(vOrigin); + FLOAT fDistance1 = plTriPlane.PointDistance(vTarget); + + // if the ray hits the polygon plane + if (fDistance0>=0 && fDistance0>=fDistance1) { + // calculate fraction of line before intersection + FLOAT fFraction = fDistance0/(fDistance0-fDistance1); + // calculate intersection coordinate + FLOAT3D vHitPoint = vOrigin+(vTarget-vOrigin)*fFraction; + // calculate intersection distance + FLOAT fHitDistance = (vHitPoint-vOrigin).Length(); + // if the hit point can not be new closest candidate + if (fHitDistance>fOldDistance) { + // skip this triangle + continue; + } + + // find major axes of the polygon plane + INDEX iMajorAxis1, iMajorAxis2; + GetMajorAxesForPlane(plTriPlane, iMajorAxis1, iMajorAxis2); + + // create an intersector + CIntersector isIntersector(vHitPoint(iMajorAxis1), vHitPoint(iMajorAxis2)); + + + // check intersections for all three edges of the polygon + isIntersector.AddEdge( + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2), + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2)); + isIntersector.AddEdge( + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2), + vVertex2(iMajorAxis1), vVertex2(iMajorAxis2)); + isIntersector.AddEdge( + vVertex2(iMajorAxis1), vVertex2(iMajorAxis2), + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2)); + + + + + // if the polygon is intersected by the ray, and it is the closest intersection so far + if (isIntersector.IsIntersecting() && (fHitDistance < fDistance)) { + // remember hit coordinates + fDistance = fHitDistance; + + + // do we neet to find the bone hit by the ray? + if (piBoneID != NULL) { + INDEX iClosestVertex; + // find the vertex closest to the intersection + FLOAT fDist0 = (vHitPoint - vVertex0).Length(); + FLOAT fDist1 = (vHitPoint - vVertex1).Length(); + FLOAT fDist2 = (vHitPoint - vVertex2).Length(); + if (fDist0 < fDist1) { + if (fDist0 < fDist2) { + iClosestVertex = mshsurf.msrf_aTriangles[itri].iVertex[0]; + } else { + iClosestVertex = mshsurf.msrf_aTriangles[itri].iVertex[2]; + } + } else { + if (fDist1 < fDist2) { + iClosestVertex = mshsurf.msrf_aTriangles[itri].iVertex[1]; + } else { + iClosestVertex = mshsurf.msrf_aTriangles[itri].iVertex[2]; + } + } + + // now find the weightmap with the largest weight for this vertex + INDEX ctwmaps = mshlod.mlod_aWeightMaps.Count(); + FLOAT fMaxVertexWeight = 0.0f; + INDEX iMaxWeightMap = -1; + for (int iwmap=0;iwmap fMaxVertexWeight)) { + fMaxVertexWeight = wtmap.mwm_aVertexWeight[ivtx].mww_fWeight; + iMaxWeightMap = wtmap.mwm_iID; + break; + } + } + } + + *piBoneID = iMaxWeightMap; + + } + } + } + } + } + } + } + + ClearRenArrays(); + _bTransformBonelessModelToViewSpace = bTemp; + + return fDistance; + +} + + +// add simple model shadow +void RM_AddSimpleShadow_View(CModelInstance &mi, const FLOAT fIntensity, const FLOATplane3D &plShadowPlane) +{ + // _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_RENDERSIMPLESHADOW); + // _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_RENDERSIMPLESHADOW); + + // get viewer in absolute space + FLOAT3D vViewerAbs = _aprProjection->ViewerPlacementR().pl_PositionVector; + // if shadow destination plane is not visible, don't cast shadows + if( plShadowPlane.PointDistance(vViewerAbs)<0.01f) { + // _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_RENDERSIMPLESHADOW); + return; + } + + // _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_SIMP_CALC); + // _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_SIMP_CALC); + + // get shadow plane in object space + FLOATmatrix3D mAbsToObj; + FLOAT3D vAbsToObj; + + // Fix this + Matrix12ToMatrixVector(mAbsToObj,vAbsToObj,_mObjectToAbs); + FLOATplane3D plShadowPlaneObj = (plShadowPlane-vAbsToObj) * !mAbsToObj; + + // project object handle so we can calc how it is far away from viewer + FLOAT3D vRef = plShadowPlaneObj.ProjectPoint(FLOAT3D(0,0,0)); + TransformVector(vRef.vector,_mObjToViewStretch); + plShadowPlaneObj.pl_distance += ClampDn( -vRef(3)*0.001f, 0.01f); // move plane towards the viewer a bit to avoid z-fighting + + FLOATaabbox3D box; + mi.GetCurrentColisionBox( box); + // find points on plane nearest to bounding box edges + FLOAT3D vMin = box.Min() * 1.25f; + FLOAT3D vMax = box.Max() * 1.25f; + if( _ulRenFlags & SRMF_SPECTATOR) { vMin*=2; vMax*=2; } // enlarge shadow for 1st person view + FLOAT3D v00 = plShadowPlaneObj.ProjectPoint(FLOAT3D(vMin(1),vMin(2),vMin(3))); + FLOAT3D v01 = plShadowPlaneObj.ProjectPoint(FLOAT3D(vMin(1),vMin(2),vMax(3))); + FLOAT3D v10 = plShadowPlaneObj.ProjectPoint(FLOAT3D(vMax(1),vMin(2),vMin(3))); + FLOAT3D v11 = plShadowPlaneObj.ProjectPoint(FLOAT3D(vMax(1),vMin(2),vMax(3))); + TransformVector(v00.vector,_mObjToViewStretch); + TransformVector(v01.vector,_mObjToViewStretch); + TransformVector(v10.vector,_mObjToViewStretch); + TransformVector(v11.vector,_mObjToViewStretch); + + // calc done + // _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_SIMP_CALC); + + // _pfModelProfile.StartTimer( CModelProfile::PTI_VIEW_SIMP_COPY); + // _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_VIEW_SIMP_COPY); + + // prepare color + ASSERT( fIntensity>=0 && fIntensity<=1); + ULONG ulAAAA = NormFloatToByte(fIntensity); + ulAAAA |= (ulAAAA<<8) | (ulAAAA<<16); // alpha isn't needed + + // add to vertex arrays + GFXVertex *pvtx = _avtxCommon.Push(4); + GFXTexCoord *ptex = _atexCommon.Push(4); + GFXColor *pcol = _acolCommon.Push(4); + // vertices + pvtx[0].x = v00(1); pvtx[0].y = v00(2); pvtx[0].z = v00(3); + pvtx[2].x = v11(1); pvtx[2].y = v11(2); pvtx[2].z = v11(3); + if( _ulRenFlags & SRMF_INVERTED) { // must re-adjust order for mirrored projection + pvtx[1].x = v10(1); pvtx[1].y = v10(2); pvtx[1].z = v10(3); + pvtx[3].x = v01(1); pvtx[3].y = v01(2); pvtx[3].z = v01(3); + } else { + pvtx[1].x = v01(1); pvtx[1].y = v01(2); pvtx[1].z = v01(3); + pvtx[3].x = v10(1); pvtx[3].y = v10(2); pvtx[3].z = v10(3); + } + // texture coords + ptex[0].s = 0; ptex[0].t = 0; + ptex[1].s = 0; ptex[1].t = 1; + ptex[2].s = 1; ptex[2].t = 1; + ptex[3].s = 1; ptex[3].t = 0; + // colors + pcol[0].abgr = ulAAAA; + pcol[1].abgr = ulAAAA; + pcol[2].abgr = ulAAAA; + pcol[3].abgr = ulAAAA; + + // if this model has fog + if( _ulRenFlags & SRMF_FOG) + { // for each vertex in shadow quad + GFXTexCoord tex; + for( INDEX i=0; i<4; i++) { + GFXVertex &vtx = pvtx[i]; + // get distance along viewer axis and fog axis and map to texture and attenuate shadow color + const FLOAT fH = vtx.x*_fog_vHDirView(1) + vtx.y*_fog_vHDirView(2) + vtx.z*_fog_vHDirView(3); + tex.s = -vtx.z *_fog_fMulZ; + tex.t = (fH+_fog_fAddH) *_fog_fMulH; + pcol[i].AttenuateRGB(GetFogAlpha(tex)^255); + } + } + // if this model has haze + if( _ulRenFlags & SRMF_HAZE) + { // for each vertex in shadow quad + for( INDEX i=0; i<4; i++) { + // get distance along viewer axis map to texture and attenuate shadow color + const FLOAT fS = (_haze_fAdd-pvtx[i].z) *_haze_fMul; + pcol[i].AttenuateRGB(GetHazeAlpha(fS)^255); + } + } + + // one simple shadow added to rendering queue + // _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_SIMP_COPY); + // _pfModelProfile.StopTimer( CModelProfile::PTI_VIEW_RENDERSIMPLESHADOW); +} + +// set callback function for bone adjustment +void RM_SetBoneAdjustCallback(void (*pAdjustBones)(void *pData), void *pData) +{ + _pAdjustBonesCallback = pAdjustBones; + _pAdjustBonesData = pData; +} + +void RM_SetShaderParamsAdjustCallback(void (*pAdjustShaderParams)(void *pData, INDEX iSurfaceID,CShader *pShader,ShaderParams &spParams),void *pData) +{ + _pAdjustShaderParams = pAdjustShaderParams; + _pAdjustShaderData = pData; +} + +// show gound for ska studio +void RM_RenderGround(CTextureObject &to) +{ + gfxSetConstantColor(0xFFFFFFFF); + gfxEnableDepthTest(); + gfxEnableDepthWrite(); + gfxDisableAlphaTest(); + gfxDisableBlend(); + gfxCullFace(GFX_NONE); + CTextureData *ptd = (CTextureData *)to.GetData(); + ptd->SetAsCurrent(); + + FLOAT3D vVtx = FLOAT3D(45,0,45); + + GFXVertex vBoxVtxs[4]; + GFXTexCoord tcBoxTex[4]; + INDEX aiIndices[6]; + + // set ground vertices + vBoxVtxs[0].x = vVtx(1); vBoxVtxs[0].y = vVtx(2); vBoxVtxs[0].z = -vVtx(3); + vBoxVtxs[1].x = -vVtx(1); vBoxVtxs[1].y = vVtx(2); vBoxVtxs[1].z = -vVtx(3); + vBoxVtxs[2].x = -vVtx(1); vBoxVtxs[2].y = vVtx(2); vBoxVtxs[2].z = vVtx(3); + vBoxVtxs[3].x = vVtx(1); vBoxVtxs[3].y = vVtx(2); vBoxVtxs[3].z = vVtx(3); + // set ground texcoords + tcBoxTex[0].u = vVtx(1); tcBoxTex[0].v = 0; + tcBoxTex[1].u = 0; tcBoxTex[1].v = 0; + tcBoxTex[2].u = 0; tcBoxTex[2].v = vVtx(3); + tcBoxTex[3].u = vVtx(1); tcBoxTex[3].v = vVtx(3); + + for(INDEX ivx=0;ivx<4;ivx++) { + TransformVertex(vBoxVtxs[ivx],_mAbsToViewer); + } + aiIndices[0] = 0; aiIndices[1] = 2; aiIndices[2] = 1; + aiIndices[3] = 0; aiIndices[4] = 3; aiIndices[5] = 2; + + gfxSetVertexArray(vBoxVtxs,4); + gfxSetTexCoordArray(tcBoxTex, FALSE); + gfxDrawElements(6,aiIndices); +} + +// render wirerame bounding box +static void RenderWireframeBox(FLOAT3D vMinVtx, FLOAT3D vMaxVtx, COLOR col) +{ + // prepare wireframe settings + gfxDisableTexture(); + // fill vertex array so it represents bounding box + FLOAT3D vBoxVtxs[8]; + vBoxVtxs[0] = FLOAT3D( vMinVtx(1), vMinVtx(2), vMinVtx(3)); + vBoxVtxs[1] = FLOAT3D( vMaxVtx(1), vMinVtx(2), vMinVtx(3)); + vBoxVtxs[2] = FLOAT3D( vMaxVtx(1), vMinVtx(2), vMaxVtx(3)); + vBoxVtxs[3] = FLOAT3D( vMinVtx(1), vMinVtx(2), vMaxVtx(3)); + vBoxVtxs[4] = FLOAT3D( vMinVtx(1), vMaxVtx(2), vMinVtx(3)); + vBoxVtxs[5] = FLOAT3D( vMaxVtx(1), vMaxVtx(2), vMinVtx(3)); + vBoxVtxs[6] = FLOAT3D( vMaxVtx(1), vMaxVtx(2), vMaxVtx(3)); + vBoxVtxs[7] = FLOAT3D( vMinVtx(1), vMaxVtx(2), vMaxVtx(3)); + + for(INDEX iwx=0;iwx<8;iwx++) TransformVector(vBoxVtxs[iwx].vector,_mObjToViewStretch); + + // connect vertices into lines of bounding box + INDEX iBoxLines[12][2]; + iBoxLines[ 0][0] = 0; iBoxLines[ 0][1] = 1; iBoxLines[ 1][0] = 1; iBoxLines[ 1][1] = 2; + iBoxLines[ 2][0] = 2; iBoxLines[ 2][1] = 3; iBoxLines[ 3][0] = 3; iBoxLines[ 3][1] = 0; + iBoxLines[ 4][0] = 0; iBoxLines[ 4][1] = 4; iBoxLines[ 5][0] = 1; iBoxLines[ 5][1] = 5; + iBoxLines[ 6][0] = 2; iBoxLines[ 6][1] = 6; iBoxLines[ 7][0] = 3; iBoxLines[ 7][1] = 7; + iBoxLines[ 8][0] = 4; iBoxLines[ 8][1] = 5; iBoxLines[ 9][0] = 5; iBoxLines[ 9][1] = 6; + iBoxLines[10][0] = 6; iBoxLines[10][1] = 7; iBoxLines[11][0] = 7; iBoxLines[11][1] = 4; + // for all vertices in bounding box + for( INDEX i=0; i<12; i++) { + // get starting and ending vertices of one line + FLOAT3D &v0 = vBoxVtxs[iBoxLines[i][0]]; + FLOAT3D &v1 = vBoxVtxs[iBoxLines[i][1]]; + _pdp->DrawLine3D(v0,v1,col); + } +} + +// render bounding box +static void RenderBox(FLOAT3D vMinVtx, FLOAT3D vMaxVtx, COLOR col) +{ + // prepare settings + gfxDisableTexture(); + gfxEnableBlend(); + gfxBlendFunc(GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + gfxCullFace(GFX_NONE); + gfxDisableDepthWrite(); + + gfxSetConstantColor(col); + // fill vertex array so it represents bounding box + GFXVertex vBoxVtxs[8]; + vBoxVtxs[0].x = vMinVtx(1); vBoxVtxs[0].y = vMaxVtx(2); vBoxVtxs[0].z = vMinVtx(3); + vBoxVtxs[1].x = vMinVtx(1); vBoxVtxs[1].y = vMaxVtx(2); vBoxVtxs[1].z = vMaxVtx(3); + vBoxVtxs[2].x = vMaxVtx(1); vBoxVtxs[2].y = vMaxVtx(2); vBoxVtxs[2].z = vMinVtx(3); + vBoxVtxs[3].x = vMaxVtx(1); vBoxVtxs[3].y = vMaxVtx(2); vBoxVtxs[3].z = vMaxVtx(3); + + vBoxVtxs[4].x = vMinVtx(1); vBoxVtxs[4].y = vMinVtx(2); vBoxVtxs[4].z = vMinVtx(3); + vBoxVtxs[5].x = vMinVtx(1); vBoxVtxs[5].y = vMinVtx(2); vBoxVtxs[5].z = vMaxVtx(3); + vBoxVtxs[6].x = vMaxVtx(1); vBoxVtxs[6].y = vMinVtx(2); vBoxVtxs[6].z = vMinVtx(3); + vBoxVtxs[7].x = vMaxVtx(1); vBoxVtxs[7].y = vMinVtx(2); vBoxVtxs[7].z = vMaxVtx(3); + + for(INDEX iwx=0;iwx<8;iwx++) { + TransformVertex(vBoxVtxs[iwx],_mObjToViewStretch); + } + INDEX aiIndices[36]; + aiIndices[ 0] = 0; aiIndices[ 1] = 3; aiIndices[ 2] = 1; + aiIndices[ 3] = 0; aiIndices[ 4] = 2; aiIndices[ 5] = 3; + aiIndices[ 6] = 5; aiIndices[ 7] = 1; aiIndices[ 8] = 3; + aiIndices[ 9] = 7; aiIndices[10] = 5; aiIndices[11] = 3; + aiIndices[12] = 2; aiIndices[13] = 7; aiIndices[14] = 3; + aiIndices[15] = 6; aiIndices[16] = 7; aiIndices[17] = 2; + aiIndices[18] = 4; aiIndices[19] = 2; aiIndices[20] = 0; + aiIndices[21] = 4; aiIndices[22] = 6; aiIndices[23] = 2; + aiIndices[24] = 5; aiIndices[25] = 0; aiIndices[26] = 1; + aiIndices[27] = 5; aiIndices[28] = 4; aiIndices[29] = 0; + aiIndices[30] = 4; aiIndices[31] = 5; aiIndices[32] = 7; + aiIndices[33] = 6; aiIndices[34] = 4; aiIndices[35] = 7; + + gfxSetVertexArray(vBoxVtxs,8); + gfxDrawElements(36,aiIndices); + + gfxDisableBlend(); + gfxEnableDepthTest(); + + RenderWireframeBox(vMinVtx,vMaxVtx,C_BLACK|CT_OPAQUE); + gfxEnableDepthWrite(); + gfxDisableDepthBias(); +} + +// render bounding box on screen +void RM_RenderColisionBox(CModelInstance &mi,ColisionBox &cb, COLOR col) +{ + //ColisionBox &cb = mi.GetColisionBox(icb); + gfxSetViewMatrix(NULL); + if(RM_GetFlags() & RMF_WIREFRAME) { + RenderWireframeBox(cb.Min(),cb.Max(),col|CT_OPAQUE); + } else { + gfxEnableBlend(); + gfxBlendFunc(GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + RenderBox(cb.Min(),cb.Max(),col|0x7F); + gfxDisableBlend(); + } +} + +// draw wireframe mesh on screen +static void RenderMeshWireframe(RenMesh &rmsh) +{ + MeshLOD &mlod = rmsh.rmsh_pMeshInst->mi_pMesh->msh_aMeshLODs[rmsh.rmsh_iMeshLODIndex]; + // count surfaces in mesh + INDEX ctsrf = mlod.mlod_aSurfaces.Count(); + // for each surface + for(INDEX isrf=0; isrfDrawLine3D(vVtx1,vVtx2,0xFFFFFFFF); + } +} + +// render one renbone +static void RenderBone(RenBone &rb, COLOR col) +{ + FLOAT fSize = rb.rb_psbBone->sb_fBoneLength / 20; + FLOAT3D vBoneStart = FLOAT3D(rb.rb_mBonePlacement[3],rb.rb_mBonePlacement[7],rb.rb_mBonePlacement[11]); + FLOAT3D vBoneEnd = FLOAT3D(0,0,-rb.rb_psbBone->sb_fBoneLength); + FLOAT3D vRingPt[4]; + + vRingPt[0] = FLOAT3D(-fSize,-fSize,-fSize*2); + vRingPt[1] = FLOAT3D( fSize,-fSize,-fSize*2); + vRingPt[2] = FLOAT3D( fSize, fSize,-fSize*2); + vRingPt[3] = FLOAT3D(-fSize, fSize,-fSize*2); + TransformVector(vBoneEnd.vector,rb.rb_mBonePlacement); + TransformVector(vRingPt[0].vector,rb.rb_mBonePlacement); + TransformVector(vRingPt[1].vector,rb.rb_mBonePlacement); + TransformVector(vRingPt[2].vector,rb.rb_mBonePlacement); + TransformVector(vRingPt[3].vector,rb.rb_mBonePlacement); + + // connect start point of bone with end point + INDEX il=0; + for(;il<4;il++) { + _pdp->DrawLine3D(vBoneStart,vRingPt[il],col); + _pdp->DrawLine3D(vBoneEnd,vRingPt[il],col); + } + + // draw ring + for(il=0;il<3;il++) { + _pdp->DrawLine3D(vRingPt[il],vRingPt[il+1],col); + } + _pdp->DrawLine3D(vRingPt[0],vRingPt[3],col); +} + +// render one bone in model instance +void RM_RenderBone(CModelInstance &mi,INDEX iBoneID) +{ + UBYTE ubFillColor = 127; + CStaticStackArray aiRenModelIndices; + CStaticStackArray aiRenMeshIndices; + + CalculateRenderingData(mi); + + gfxEnableBlend(); + gfxEnableDepthTest(); + + INDEX iBoneIndex = -1; // index of selected bone in renbone array + INDEX iWeightIndex = -1; // index of weight that have same id as bone + + // find all renmeshes that uses this bone weightmap + INDEX ctrm = _aRenModels.Count(); + // for each renmodel + for(INDEX irm=1;irmmwm_iID == iBoneID) { + INDEX &irmi = aiRenModelIndices.Push(); + INDEX &irmshi = aiRenMeshIndices.Push(); + // rememeber this weight map + irmi = irm; + irmshi = imsh; + iWeightIndex = iwm; + } + } + } + } + } + + // if weightmap is found + if(iWeightIndex>=0) { + // show wertex weights for each mesh that uses this bones weightmap + INDEX ctmshi=aiRenMeshIndices.Count(); + for(INDEX imshi=0;imshimi_pMesh->msh_aMeshLODs[rmsh.rmsh_iMeshLODIndex]; + + // Create array of color + INDEX ctVertices = mlod.mlod_aVertices.Count(); + _aMeshColors.PopAll(); + _aMeshColors.Push(ctVertices); + memset(&_aMeshColors[0],ubFillColor,sizeof(_aMeshColors[0])*ctVertices); + // prepare this mesh for rendering + PrepareMeshForRendering(rmsh,rm.rm_iSkeletonLODIndex); + + // all vertices by default are not visible ( have alpha set to 0 ) + for(INDEX ivx=0;ivxmwm_aVertexWeight.Count(); + // for each vertex in this veight + for(int ivw=0; ivwmwm_aVertexWeight[ivw]; + INDEX ivx = vw.mww_iVertex; + _aMeshColors[ivx].r = 255; + _aMeshColors[ivx].g = 127; + _aMeshColors[ivx].b = 0; + _aMeshColors[ivx].a += vw.mww_fWeight*255; // _aMeshColors[ivx].a = 255; + } + } + + // count surfaces in mesh + INDEX ctsrf = mlod.mlod_aSurfaces.Count(); + // for each surface + for(INDEX isrf=0; isrf=0) { + gfxSetViewMatrix(NULL); + gfxDisableDepthTest(); + // show bone in yellow color + RenderBone(_aRenBones[iBoneIndex],0xFFFF00FF); + } + + gfxDisableBlend(); + aiRenModelIndices.Clear(); + aiRenMeshIndices.Clear(); + ClearRenArrays(); +} + +// render skeleton hierarchy +static void RenderSkeleton(void) +{ + gfxSetViewMatrix(NULL); + // for each bone, except the dummy one + for(int irb=1; irb<_aRenBones.Count(); irb++) + { + RenBone &rb = _aRenBones[irb]; + RenderBone(rb,0x5A5ADCFF); // render in blue color + } +} + +static void RenderActiveBones(RenModel &rm) +{ + CModelInstance *pmi = rm.rm_pmiModel; + if(pmi==NULL) return; + // count animlists + INDEX ctal = pmi->mi_aqAnims.aq_Lists.Count(); + // find newes animlist that has fully faded in + INDEX iFirstAnimList = 0; + // loop from newer to older + INDEX ial=ctal-1; + for(;ial>=0;ial--) { + AnimList &alList = pmi->mi_aqAnims.aq_Lists[ial]; + // calculate fade factor + FLOAT fFadeFactor = CalculateFadeFactor(alList); + if(fFadeFactor >= 1.0f) { + iFirstAnimList = ial; + break; + } + } + // for each anim list after iFirstAnimList + for(ial=iFirstAnimList;ialmi_aqAnims.aq_Lists[ial]; + INDEX ctpa = alList.al_PlayedAnims.Count(); + // for each played anim + for(INDEX ipa=0;ipaFindAnimationByID(pa.pa_iAnimID,&iAnimSet,&iAnimIndex); + CAnimSet &as = pmi->mi_aAnimSet[iAnimSet]; + Animation &an = as.as_Anims[iAnimIndex]; + INDEX ctbe = an.an_abeBones.Count(); + // for each bone envelope + for(INDEX ibe=0;ibe iFind)) return iMid; + else iLow = iMid; + } +} + +// Find renbone in given renmodel +static BOOL FindRenBone(RenModel &rm,int iBoneID,INDEX *piBoneIndex) +{ + int ctb = rm.rm_iFirstBone + rm.rm_ctBones; + // for each renbone in this ren model + for(int ib=rm.rm_iFirstBone;ibsb_iID) { + // return index of this renbone + *piBoneIndex = ib; + return TRUE; + } + } + return FALSE; +} + +// Find renbone in whole array on renbones +RenBone *RM_FindRenBone(INDEX iBoneID) +{ + INDEX ctrb=_aRenBones.Count(); + // for each renbone + for(INDEX irb=1;irbsb_iID == iBoneID) { + // return this renbone + return &rb; + } + } + return NULL; +} + +// Return array of renbones +RenBone *RM_GetRenBoneArray(INDEX &ctrb) +{ + ctrb = _aRenBones.Count(); + if(ctrb>0) { + return &_aRenBones[0]; + } else { + return NULL; + } +} + +// find renmoph in given renmodel +static BOOL FindRenMorph(RenModel &rm,int iMorphID,INDEX *piMorphIndex) +{ + // for each renmesh in given renmodel + INDEX ctmsh = rm.rm_iFirstMesh + rm.rm_ctMeshes; + for(INDEX irmsh=rm.rm_iFirstMesh;irmshmmp_iID) { + // return this renmorph + *piMorphIndex = imm; + return TRUE; + } + } + } + // renmorph was not found + return FALSE; +} + +// Find bone by ID (bone index must be set!) +static BOOL FindBone(int iBoneID, INDEX *piBoneIndex, CModelInstance *pmi,INDEX iSkeletonLod) +{ + // if model instance does not have skeleton + if(pmi->mi_psklSkeleton == NULL) return FALSE; + // if current skeleton lod is invalid + if(iSkeletonLod < 0) return FALSE; + + INDEX ctslods = pmi->mi_psklSkeleton->skl_aSkeletonLODs.Count(); + // if skeleton lods count is invalid + if(ctslods<1) return FALSE; + // if skeleton lod is larger than lod count + if(iSkeletonLod >= ctslods) { + // use skeleton finest skeleton lod + #pragma message(">> Check if this is ok") + iSkeletonLod = 0; + ASSERT(FALSE); + } + + SkeletonLOD &slod = pmi->mi_psklSkeleton->skl_aSkeletonLODs[iSkeletonLod]; + // for each bone in skeleton lod + for(int i=0;imi_cmiChildren.Count(); + for(INDEX imich =0;imichmi_cmiChildren[imich],iSkeletonLod)) + return TRUE; + } + // bone was not found + return FALSE; +} + +// decompres axis for quaternion if animations are optimized +static void DecompressAxis(FLOAT3D &vNormal, UWORD ubH, UWORD ubP) +{ + ANGLE h = (ubH/65535.0f)*360.0f-180.0f; + ANGLE p = (ubP/65535.0f)*360.0f-180.0f; + + FLOAT &x = vNormal(1); + FLOAT &y = vNormal(2); + FLOAT &z = vNormal(3); + + x = -Sin(h)*Cos(p); + y = Sin(p); + z = -Cos(h)*Cos(p); +} + +// initialize batch model rendering +void RM_BeginRenderingView(CAnyProjection3D &apr, CDrawPort *pdp) +{ + // remember parameters + _iRenderingType = 1; + _pdp = pdp; + // prepare and set the projection + apr->ObjectPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + apr->Prepare(); + // in case of mirror projection, move mirror clip plane a bit father from the mirrored models, + // so we have less clipping (for instance, player feet) + if( apr->pr_bMirror) apr->pr_plMirrorView.pl_distance -= 0.06f; // -0.06 is because entire projection is offseted by +0.05 + _aprProjection = apr; + _pdp->SetProjection( _aprProjection); + + // remember the abs to viewer transformation + MatrixVectorToMatrix12(_mAbsToViewer, + _aprProjection->pr_ViewerRotationMatrix, + -_aprProjection->pr_vViewerPosition*_aprProjection->pr_ViewerRotationMatrix); + + // make FPU precision low + _fpuOldPrecision = GetFPUPrecision(); + SetFPUPrecision(FPT_24BIT); + +} + + +// cleanup after batch model rendering +void RM_EndRenderingView( BOOL bRestoreOrtho/*=TRUE*/) +{ + ASSERT( _iRenderingType==1 && _pdp!=NULL); + + // assure that FPU precision was low all the model rendering time, then revert to old FPU precision + ASSERT( GetFPUPrecision()==FPT_24BIT); + SetFPUPrecision(_fpuOldPrecision); + + // back to 2D projection? + if( bRestoreOrtho) _pdp->SetOrtho(); + _pdp->SetOrtho(); + _iRenderingType = 0; + _pdp = NULL; +} + + + +// for mark renderer +extern CAnyProjection3D _aprProjection; +extern UBYTE *_pubMask; +extern SLONG _slMaskWidth; +extern SLONG _slMaskHeight; + +// begin/end model rendering to shadow mask +void RM_BeginModelRenderingMask( CAnyProjection3D &prProjection, UBYTE *pubMask, SLONG slMaskWidth, SLONG slMaskHeight) +{ + ASSERT( _iRenderingType==0); + _iRenderingType = 2; + _aprProjection = prProjection; + _pubMask = pubMask; + _slMaskWidth = slMaskWidth; + _slMaskHeight = slMaskHeight; + + // prepare and set the projection + _aprProjection->ObjectPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + _aprProjection->Prepare(); + // remember the abs to viewer transformation + MatrixVectorToMatrix12(_mAbsToViewer, + _aprProjection->pr_ViewerRotationMatrix, + -_aprProjection->pr_vViewerPosition*_aprProjection->pr_ViewerRotationMatrix); + + // set mask shader + extern void InternalShader_Mask(void); + extern void InternalShaderDesc_Mask(ShaderDesc &shDesc); + _shMaskShader.ShaderFunc = InternalShader_Mask; + _shMaskShader.GetShaderDesc = InternalShaderDesc_Mask; +} + + +void RM_EndModelRenderingMask(void) +{ + ASSERT( _iRenderingType==2); + _iRenderingType = 0; +} + + + + + + +// setup light parameters +void RM_SetLightColor(COLOR colAmbient, COLOR colLight) +{ + _colAmbient = colAmbient; + _colLight = colLight; +} +void RM_SetLightDirection(FLOAT3D &vLightDir) +{ + _vLightDir = vLightDir * (-1); +} + +// calculate object matrices for givem model instance +void RM_SetObjectMatrices(CModelInstance &mi) +{ + ULONG ulFlags = RM_GetRenderFlags(); + + // adjust clipping to frustum + if( ulFlags & SRMF_INSIDE) gfxDisableClipping(); + else gfxEnableClipping(); + + // adjust clipping to mirror-plane (if any) + extern INDEX gap_iOptimizeClipping; + + if((CProjection3D *)_aprProjection != NULL) { + if( gap_iOptimizeClipping>0 && (_aprProjection->pr_bMirror || _aprProjection->pr_bWarp)) { + if( ulFlags & SRMF_INMIRROR) { + gfxDisableClipPlane(); + gfxFrontFace( GFX_CCW); + } else { + gfxEnableClipPlane(); + gfxFrontFace( GFX_CW); + } + } + } + + MatrixMultiply(_mObjToView,_mAbsToViewer, _mObjectToAbs); + + Matrix12 mStretch; + MakeStretchMatrix(mStretch, mi.mi_vStretch); + MatrixMultiply(_mObjToViewStretch,_mObjToView,mStretch); +} + +// setup object position +void RM_SetObjectPlacement(const CPlacement3D &pl) +{ + FLOATmatrix3D m; + MakeRotationMatrixFast( m, pl.pl_OrientationAngle); + MatrixVectorToMatrix12(_mObjectToAbs,m, pl.pl_PositionVector); +} + +void RM_SetObjectPlacement(const FLOATmatrix3D &m, const FLOAT3D &v) +{ + MatrixVectorToMatrix12(_mObjectToAbs,m, v); +} + + +// sets custom mesh lod +void RM_SetCustomMeshLodDistance(FLOAT fMeshLod) +{ + _fCustomMlodDistance = fMeshLod; +} +// sets custom skeleton lod +void RM_SetCustomSkeletonLodDistance(FLOAT fSkeletonLod) +{ + _fCustomSlodDistance = fSkeletonLod; +} + +// Returns index of skeleton lod at given distance +INDEX GetSkeletonLOD(CSkeleton &sk, FLOAT fDistance) +{ + FLOAT fMinDistance = 1000000.0f; + INDEX iSkeletonLod = -1; + + // if custom lod distance is set + if(_fCustomSlodDistance!=-1) { + // set object distance as custom distance + fDistance = _fCustomSlodDistance; + } + // for each lod in skeleton + INDEX ctslods = sk.skl_aSkeletonLODs.Count(); + for(INDEX islod=0;islodmi_iParentBoneID == (-1)) { + // set is parent bone index as 0 + rm.rm_iParentBoneIndex = rmParent.rm_iFirstBone; + // model instance is attached to another model's bone + } else { + INDEX iParentBoneIndex = -1; + // does parent model insntance has a skeleton + if(rmParent.rm_pmiModel->mi_psklSkeleton != NULL && rmParent.rm_iSkeletonLODIndex>=0) { + // get index of parent bone + iParentBoneIndex = rmParent.rm_pmiModel->mi_psklSkeleton->FindBoneInLOD(pmiModel->mi_iParentBoneID,rmParent.rm_iSkeletonLODIndex); + // model instance does not have skeleton + } else { + // do not draw this model + _aRenModels.Pop(); + return -1; + } + // if parent bone index was not found ( not visible in current lod) + if(iParentBoneIndex == (-1)) { + // do not draw this model + _aRenModels.Pop(); + return -1; + // parent bone exists and its visible + } else { + // set this model parent bone index in array of renbones + rm.rm_iParentBoneIndex = iParentBoneIndex + rmParent.rm_iFirstBone; + } + } + + // if this model instance has skeleton + if(pmiModel->mi_psklSkeleton!=NULL) { + // adjust mip factor in case of dynamic stretch factor + FLOAT fDistFactor = _fDistanceFactor; + FLOAT3D &vStretch = pmiModel->mi_vStretch; + // if model is stretched + if( vStretch != FLOAT3D(1,1,1)) { + // calculate new distance factor + fDistFactor = fDistFactor / Max(vStretch(1),Max(vStretch(2),vStretch(3))); + } + // calulate its current skeleton lod + rm.rm_iSkeletonLODIndex = GetSkeletonLOD(*pmiModel->mi_psklSkeleton,fDistFactor); + // if current skeleton lod is valid and visible + if(rm.rm_iSkeletonLODIndex > -1) { + // count all bones in this skeleton + INDEX ctsb = pmiModel->mi_psklSkeleton->skl_aSkeletonLODs[rm.rm_iSkeletonLODIndex].slod_aBones.Count(); + // for each bone in skeleton + for(INDEX irb=0;irbmi_psklSkeleton->skl_aSkeletonLODs[rm.rm_iSkeletonLODIndex].slod_aBones[irb]; + // add one renbone + RenBone &rb = _aRenBones.Push(); + rb.rb_psbBone = pSkeletonBone; + rb.rb_iRenModelIndex = ctrm; + rm.rm_ctBones++; + // add default bone position (used if no animations) + rb.rb_apPos.ap_vPos = pSkeletonBone->sb_qvRelPlacement.vPos; + rb.rb_arRot.ar_qRot = pSkeletonBone->sb_qvRelPlacement.qRot; + + // if this is root bone for this model instance + if(pSkeletonBone->sb_iParentID == (-1)) { + // set its parent bone index to be parent bone of this model instance + rb.rb_iParentIndex = rm.rm_iParentBoneIndex; + // this is child bone + } else { + // get parent index in array of renbones + INDEX rb_iParentIndex = pmiModel->mi_psklSkeleton->FindBoneInLOD(pSkeletonBone->sb_iParentID,rm.rm_iSkeletonLODIndex); + rb.rb_iParentIndex = rb_iParentIndex + rm.rm_iFirstBone; + } + } + } + } + + rm.rm_iFirstMesh = _aRenMesh.Count(); + rm.rm_ctMeshes = 0; + + INDEX ctm = pmiModel->mi_aMeshInst.Count(); + // for each mesh instance in this model instance + for(INDEX im=0;immi_vStretch; + // if model is stretched + if( vStretch != FLOAT3D(1,1,1)) { + // calculate new distance factor + fDistFactor = fDistFactor / Max(vStretch(1),Max(vStretch(2),vStretch(3)));// Log2( Max(vStretch(1),Max(vStretch(2),vStretch(3)))); + } + + // calculate current mesh lod + INDEX iMeshLodIndex = GetMeshLOD(*pmiModel->mi_aMeshInst[im].mi_pMesh,fDistFactor); + // if mesh lod is visible + if(iMeshLodIndex > -1) { + // add one ren mesh + RenMesh &rmsh = _aRenMesh.Push(); + rm.rm_ctMeshes++; + rmsh.rmsh_iRenModelIndex = ctrm; + rmsh.rmsh_pMeshInst = &pmiModel->mi_aMeshInst[im]; + rmsh.rmsh_iFirstMorph = _aRenMorph.Count(); + rmsh.rmsh_iFirstWeight = _aRenWeights.Count(); + rmsh.rmsh_ctMorphs = 0; + rmsh.rmsh_ctWeights = 0; + rmsh.rmsh_bTransToViewSpace = FALSE; + // set mesh lod index for this ren mesh + rmsh.rmsh_iMeshLODIndex = iMeshLodIndex; + + // for each morph map in this mesh lod + INDEX ctmm = rmsh.rmsh_pMeshInst->mi_pMesh->msh_aMeshLODs[rmsh.rmsh_iMeshLODIndex].mlod_aMorphMaps.Count(); + for(INDEX imm=0;immmi_pMesh->msh_aMeshLODs[rmsh.rmsh_iMeshLODIndex].mlod_aMorphMaps[imm]; + rm.rmp_fFactor = 0; + } + + // for each weight map in this mesh lod + INDEX ctw = rmsh.rmsh_pMeshInst->mi_pMesh->msh_aMeshLODs[rmsh.rmsh_iMeshLODIndex].mlod_aWeightMaps.Count(); + for(INDEX iw=0;iwmi_pMesh->msh_aMeshLODs[rmsh.rmsh_iMeshLODIndex].mlod_aWeightMaps[iw]; + rw.rw_pwmWeightMap = &mwm; + rmsh.rmsh_ctWeights++; + rw.rw_iBoneIndex = rm.rm_iFirstBone; + // find bone of this weight in current skeleton lod and get its index for this renweight + if(!FindBone(mwm.mwm_iID,&rw.rw_iBoneIndex,pmiModel,rm.rm_iSkeletonLODIndex)) + { + // if bone not found, set boneindex in renweight to -1 + rw.rw_iBoneIndex = -1; + } + } + } + } + + rm.rm_iFirstChildModel = -1; + // for each child in this model instance + INDEX ctmich = pmiModel->mi_cmiChildren.Count(); + for(int imich=0;imichmi_cmiChildren[imich],ctrm); + // if child is visible + if(irmChildIndex != (-1)) { + // set model sibling + _aRenModels[irmChildIndex].rm_iNextSiblingModel = rm.rm_iFirstChildModel; + rm.rm_iFirstChildModel = irmChildIndex; + } + } + return ctrm; +} + +// calculate transformations for all bones on already built hierarchy +static void CalculateBoneTransforms() +{ + // put basic transformation in first dummy bone + MatrixCopy(_aRenBones[0].rb_mTransform, _mObjToView); + MatrixCopy(_aRenBones[0].rb_mStrTransform, _aRenBones[0].rb_mTransform); + + // if callback function was specified + if(_pAdjustBonesCallback!=NULL) { + // Call callback function + _pAdjustBonesCallback(_pAdjustBonesData); + } + + Matrix12 mStretch; + // for each renbone after first dummy one + int irb=1; + for(; irb<_aRenBones.Count(); irb++) { + Matrix12 mRelPlacement; + Matrix12 mOffset; + RenBone &rb = _aRenBones[irb]; + RenBone &rbParent = _aRenBones[rb.rb_iParentIndex]; + // Convert QVect of placement to matrix12 + QVect qv; + qv.vPos = rb.rb_apPos.ap_vPos; + qv.qRot = rb.rb_arRot.ar_qRot; + QVectToMatrix12(mRelPlacement,qv); + + // if this is root bone + if(rb.rb_psbBone->sb_iParentID == (-1)) { + // stretch root bone + RenModel &rm= _aRenModels[rb.rb_iRenModelIndex]; + MakeStretchMatrix(mStretch, rm.rm_pmiModel->mi_vStretch); + + + RenModel &rmParent = _aRenModels[rb.rb_iRenModelIndex]; + QVectToMatrix12(mOffset,rmParent.rm_pmiModel->mi_qvOffset); + // add offset to root bone + MatrixMultiplyCP(mRelPlacement,mOffset,mRelPlacement); + + Matrix12 mStrParentBoneTrans; + // Create stretch matrix with parent bone transformations + MatrixMultiplyCP(mStrParentBoneTrans, rbParent.rb_mStrTransform,mStretch); + // transform bone using stretch parent's transform, relative placement + MatrixMultiply(rb.rb_mStrTransform, mStrParentBoneTrans, mRelPlacement); + MatrixMultiply(rb.rb_mTransform,rbParent.rb_mTransform, mRelPlacement); + } else { + // transform bone using parent's transform and relative placement + MatrixMultiply(rb.rb_mStrTransform, rbParent.rb_mStrTransform, mRelPlacement); + MatrixMultiply(rb.rb_mTransform,rbParent.rb_mTransform,mRelPlacement); + } + // remember tranform matrix of bone placement for bone rendering + MatrixCopy(rb.rb_mBonePlacement,rb.rb_mStrTransform); + } + + // for each renmodel after first dummy one + for(int irm=1; irm<_aRenModels.Count(); irm++) { + // remember transforms for bone-less models for every renmodel, except the dummy one + Matrix12 mOffset; + Matrix12 mStretch; + RenModel &rm = _aRenModels[irm]; + + QVectToMatrix12(mOffset,rm.rm_pmiModel->mi_qvOffset); + MakeStretchMatrix(mStretch,rm.rm_pmiModel->mi_vStretch); + + MatrixMultiply(rm.rm_mTransform,_aRenBones[rm.rm_iParentBoneIndex].rb_mTransform,mOffset); + MatrixMultiply(rm.rm_mStrTransform,_aRenBones[rm.rm_iParentBoneIndex].rb_mStrTransform,mOffset); + MatrixMultiplyCP(rm.rm_mStrTransform,rm.rm_mStrTransform,mStretch); + } + + Matrix12 mInvert; + // for each renbone + for(irb=1; irb<_aRenBones.Count(); irb++) { + RenBone &rb = _aRenBones[irb]; + // multiply every transform with invert matrix of bone abs placement + MatrixTranspose(mInvert,rb.rb_psbBone->sb_mAbsPlacement); + // create two versions of transform matrices, stretch and normal for vertices and normals + MatrixMultiplyCP(_aRenBones[irb].rb_mStrTransform,_aRenBones[irb].rb_mStrTransform,mInvert); + MatrixMultiplyCP(_aRenBones[irb].rb_mTransform,_aRenBones[irb].rb_mTransform,mInvert); + } +} + +// Match animations in anim queue for bones +static void MatchAnims(RenModel &rm) +{ + const FLOAT fLerpedTick = _pTimer->GetLerpedCurrentTick(); + + // return if no animsets + INDEX ctas = rm.rm_pmiModel->mi_aAnimSet.Count(); + if(ctas == 0) return; + // count animlists + INDEX ctal = rm.rm_pmiModel->mi_aqAnims.aq_Lists.Count(); + // find newes animlist that has fully faded in + INDEX iFirstAnimList = 0; + // loop from newer to older + INDEX ial=ctal-1; + for(;ial>=0;ial--) { + AnimList &alList = rm.rm_pmiModel->mi_aqAnims.aq_Lists[ial]; + // calculate fade factor + FLOAT fFadeFactor = CalculateFadeFactor(alList); + if(fFadeFactor >= 1.0f) { + iFirstAnimList = ial; + break; + } + } + + // for each anim list after iFirstAnimList + for(ial=iFirstAnimList;ialmi_aqAnims.aq_Lists[ial]; + AnimList *palListNext=NULL; + if(ial+1mi_aqAnims.aq_Lists[ial+1]; + + // calculate fade factor + FLOAT fFadeFactor = CalculateFadeFactor(alList); + + INDEX ctpa = alList.al_PlayedAnims.Count(); + // for each played anim in played anim list + for(int ipa=0;ipaFindAnimationByID(pa.pa_iAnimID,&iAnimSetIndex,&iAnimIndex)) { + // if found, animate bones + Animation &an = rm.rm_pmiModel->mi_aAnimSet[iAnimSetIndex].as_Anims[iAnimIndex]; + + // calculate end time for this animation list + FLOAT fFadeInEndTime = alList.al_fStartTime + alList.al_fFadeTime; + + // if there is a newer anmimation list + if(palListNext!=NULL) { + // freeze time of this one to never overlap with the newer list + fTime = ClampUp(fTime, palListNext->al_fStartTime); + } + + // calculate time passed since the animation started + FLOAT fTimeOffset = fTime - pa.pa_fStartTime; + // if this animation list is fading in + if (fLerpedTick < fFadeInEndTime) { + // offset the time so that it is paused at the end of fadein interval + fTimeOffset += fFadeInEndTime - fLerpedTick; + } + + FLOAT f = fTimeOffset / (an.an_fSecPerFrame*pa.pa_fSpeedMul); + + INDEX iCurentFrame; + INDEX iAnimFrame,iNextAnimFrame; + + if(bAnimLooping) { + f = fmod(f,an.an_iFrames); + iCurentFrame = INDEX(f); + iAnimFrame = iCurentFrame % an.an_iFrames; + iNextAnimFrame = (iCurentFrame+1) % an.an_iFrames; + } else { + if(f>an.an_iFrames) f = an.an_iFrames-1; + iCurentFrame = INDEX(f); + iAnimFrame = ClampUp(iCurentFrame,an.an_iFrames-1L); + iNextAnimFrame = ClampUp(iCurentFrame+1L,an.an_iFrames-1L); + } + + // for each bone envelope + INDEX ctbe = an.an_abeBones.Count(); + for(int ibe=0;ibe(fSlerpFactor,*pqRotCurrent,*pqRotNext); + // and currently playing animation + rb.rb_arRot.ar_qRot = Slerp(fFadeFactor*pa.pa_Strength,rb.rb_arRot.ar_qRot,qRot); + + AnimPos *apFirst = &be.be_apPos[0]; + INDEX ctfn = be.be_apPos.Count(); + INDEX iPosFrameIndex = FindFrame((UBYTE*)apFirst,iAnimFrame,ctfn,sizeof(AnimPos)); + + INDEX iNextPosFrameIndex; + // is animation looping + if(bAnimLooping) { + iNextPosFrameIndex = (iPosFrameIndex+1) % be.be_apPos.Count(); + } else { + iNextPosFrameIndex = ClampUp(iPosFrameIndex+1L,be.be_apPos.Count()-1L); + } + + INDEX iPosFrameNum = be.be_apPos[iPosFrameIndex].ap_iFrameNum; + INDEX iNextPosFrameNum = be.be_apPos[iNextPosFrameIndex].ap_iFrameNum; + + FLOAT fLerpFactor; + if(iNextPosFrameNum<=iPosFrameNum) fLerpFactor = (f-iPosFrameNum) / (an.an_iFrames-iPosFrameNum); + else fLerpFactor = (f-iPosFrameNum) / (iNextPosFrameNum-iPosFrameNum); + + FLOAT3D vPos; + FLOAT3D vBonePosCurrent = be.be_apPos[iPosFrameIndex].ap_vPos; + FLOAT3D vBonePosNext = be.be_apPos[iNextPosFrameIndex].ap_vPos; + + // if bone envelope and bone have some length + if((be.be_OffSetLen > 0) && (rb.rb_psbBone->sb_fOffSetLen > 0)) { + // size bone to fit bone envelope + vBonePosCurrent *= (rb.rb_psbBone->sb_fOffSetLen / be.be_OffSetLen); + vBonePosNext *= (rb.rb_psbBone->sb_fOffSetLen / be.be_OffSetLen); + } + + // calculate position for bone beetwen current and next frame in animation + vPos = Lerp(vBonePosCurrent,vBonePosNext,fLerpFactor); + // and currently playing animation + rb.rb_apPos.ap_vPos = Lerp(rb.rb_apPos.ap_vPos,vPos,fFadeFactor * pa.pa_Strength); + } + } + + // for each morphmap + for(INDEX im=0;im _patoTextures; +static CStaticStackArray _paTexCoords; +// draw mesh on screen +static void RenderMesh(RenMesh &rmsh,RenModel &rm) +{ + ASSERT(_pavFinalVertices!=NULL); + ASSERT(_panFinalNormals!=NULL); + + MeshLOD &mlod = rmsh.rmsh_pMeshInst->mi_pMesh->msh_aMeshLODs[rmsh.rmsh_iMeshLODIndex]; + // Count surfaces in mesh + INDEX ctsrf = mlod.mlod_aSurfaces.Count(); + // for each surface + for(INDEX isrf=0; isrfsp_aiTextureIDs.Count(); + INDEX cttxMax = rmsh.rmsh_pMeshInst->mi_tiTextures.Count(); + // cttx = ClampUp(cttx,cttxMax); + + _patoTextures.PopAll(); + if(cttx>0)_patoTextures.Push(cttx); + // for each texture ID + for(INDEX itx=0;itxsp_aiTextureIDs[itx], *rmsh.rmsh_pMeshInst); + } + + // count uvmaps + INDEX ctuvm = pShaderParams->sp_aiTexCoordsIndex.Count(); + // ctuvm = ClampUp(ctuvm,mlod.mlod_aUVMaps.Count()); + + _paTexCoords.PopAll(); + if(ctuvm>0)_paTexCoords.Push(ctuvm); + // for each uvamp + for( INDEX iuvm=0; iuvmsp_aiTexCoordsIndex[iuvm]; + // if mesh lod has this uv map + if(iuvmIndexsp_acolColors.Count(); + INDEX ctFloats = pShaderParams->sp_afFloats.Count(); + + // begin model rendering + const BOOL bModelSetupTimer = _sfStats.CheckTimer(CStatForm::STI_MODELSETUP); + if( bModelSetupTimer) _sfStats.StopTimer(CStatForm::STI_MODELSETUP); + _sfStats.StartTimer(CStatForm::STI_MODELRENDERING); + + shaBegin( _aprProjection, pShader); + shaSetVertexArray((GFXVertex4*)&_pavFinalVertices[msrf.msrf_iFirstVertex],msrf.msrf_ctVertices); + shaSetNormalArray((GFXNormal*)&_panFinalNormals[msrf.msrf_iFirstVertex]); + shaSetIndices(&msrf.msrf_aTriangles[0].iVertex[0],msrf.msrf_aTriangles.Count()*3); + shaSetFlags(msrf.msrf_ShadingParams.sp_ulFlags); + + + // if mesh is transformed to view space + if(rmsh.rmsh_bTransToViewSpace) { + #pragma message(">> FIX THIS !!!") + // no ObjToView matrix is needed in shader so set empty matrix + Matrix12 mIdentity; + MakeIdentityMatrix(mIdentity); + shaSetObjToViewMatrix(mIdentity); + Matrix12 mInvObjToAbs; + MatrixTranspose(mInvObjToAbs,_mAbsToViewer); + shaSetObjToAbsMatrix(mInvObjToAbs); + } else { + // give shader current ObjToView matrix + shaSetObjToViewMatrix(_mObjToView); + shaSetObjToAbsMatrix(_mObjectToAbs); + } + + // Set light parametars + shaSetLightColor(_colAmbient,_colLight); + shaSetLightDirection(_vLightDirInView); + // Set model color + shaSetModelColor(rm.rm_pmiModel->mi_colModelColor); + + if(ctTextures>0) shaSetTextureArray(&_patoTextures[0],ctTextures); + if(ctTexCoords>0) shaSetUVMapsArray(&_paTexCoords[0],ctTexCoords); + if(ctColors>0) shaSetColorArray(&pShaderParams->sp_acolColors[0],ctColors); + if(ctFloats>0) shaSetFloatArray(&pShaderParams->sp_afFloats[0],ctFloats); + shaEnd(); + + _sfStats.StopTimer(CStatForm::STI_MODELRENDERING); + if( bModelSetupTimer) _sfStats.StartTimer(CStatForm::STI_MODELSETUP); + } + // surface has no shader or textures are turned off + else { + COLOR colErrColor = 0xCDCDCDFF; + // surface has no shader, just show vertices using custom simple shader + shaSetVertexArray((GFXVertex4*)&_pavFinalVertices[msrf.msrf_iFirstVertex],msrf.msrf_ctVertices); + shaSetNormalArray((GFXNormal*)&_panFinalNormals[msrf.msrf_iFirstVertex]); + shaSetIndices(&msrf.msrf_aTriangles[0].iVertex[0],msrf.msrf_aTriangles.Count()*3); + shaSetTexture(-1); + shaSetColorArray(&colErrColor,1); + + shaSetLightColor(_colAmbient,_colLight); + shaSetLightDirection(_vLightDirInView); + shaSetModelColor(rm.rm_pmiModel->mi_colModelColor); + + shaDisableBlend(); + shaEnableDepthTest(); + shaEnableDepthWrite(); + shaSetColor(0); + shaCalculateLight(); + shaRender(); + shaClean(); + } + } +} + +// Prepare ren mesh for rendering +static void PrepareMeshForRendering(RenMesh &rmsh, INDEX iSkeletonlod) +{ + // set curent mesh lod + MeshLOD &mlod = rmsh.rmsh_pMeshInst->mi_pMesh->msh_aMeshLODs[rmsh.rmsh_iMeshLODIndex]; + // clear vertices array + _aMorphedVtxs.PopAll(); + _aMorphedNormals.PopAll(); + _aFinalVtxs.PopAll(); + _aFinalNormals.PopAll(); + _pavFinalVertices = NULL; + _panFinalNormals = NULL; + // Reset light direction + _vLightDirInView = _vLightDir; + + + // Get vertices count + INDEX ctVertices = mlod.mlod_aVertices.Count(); + // Allocate memory for vertices + _aMorphedVtxs.Push(ctVertices); + _aMorphedNormals.Push(ctVertices); + _aFinalVtxs.Push(ctVertices); + _aFinalNormals.Push(ctVertices); + // Remember final vertex count + _ctFinalVertices = ctVertices; + + // Copy original vertices and normals to _aMorphedVtxs + memcpy(&_aMorphedVtxs[0],&mlod.mlod_aVertices[0],sizeof(mlod.mlod_aVertices[0]) * ctVertices); + memcpy(&_aMorphedNormals[0],&mlod.mlod_aNormals[0],sizeof(mlod.mlod_aNormals[0]) * ctVertices); + // Set final vertices and normals to 0 + memset(&_aFinalVtxs[0],0,sizeof(_aFinalVtxs[0])*ctVertices); + memset(&_aFinalNormals[0],0,sizeof(_aFinalNormals[0])*ctVertices); + + + INDEX ctmm = rmsh.rmsh_iFirstMorph + rmsh.rmsh_ctMorphs; + // blend vertices and normals for each RenMorph + for(int irm=rmsh.rmsh_iFirstMorph;irm 0 + if(rm.rmp_fFactor > 0.0f) { + // for each vertex and normal in morphmap + for(int ivx=0;ivxmmp_aMorphMap.Count();ivx++) { + // blend vertices and normals + if(rm.rmp_pmmmMorphMap->mmp_bRelative) { + // blend relative (new = cur + f*(dst-src)) + INDEX vtx = rm.rmp_pmmmMorphMap->mmp_aMorphMap[ivx].mwm_iVxIndex; + MeshVertex &mvSrc = mlod.mlod_aVertices[vtx]; + MeshNormal &mnSrc = mlod.mlod_aNormals[vtx]; + MeshVertexMorph &mvmDst = rm.rmp_pmmmMorphMap->mmp_aMorphMap[ivx]; + // blend vertices + _aMorphedVtxs[vtx].x += rm.rmp_fFactor*(mvmDst.mwm_x - mvSrc.x); + _aMorphedVtxs[vtx].y += rm.rmp_fFactor*(mvmDst.mwm_y - mvSrc.y); + _aMorphedVtxs[vtx].z += rm.rmp_fFactor*(mvmDst.mwm_z - mvSrc.z); + // blend normals + _aMorphedNormals[vtx].nx += rm.rmp_fFactor*(mvmDst.mwm_nx - mnSrc.nx); + _aMorphedNormals[vtx].ny += rm.rmp_fFactor*(mvmDst.mwm_ny - mnSrc.ny); + _aMorphedNormals[vtx].nz += rm.rmp_fFactor*(mvmDst.mwm_nz - mnSrc.nz); + } else { + // blend absolute (1-f)*cur + f*dst + INDEX vtx = rm.rmp_pmmmMorphMap->mmp_aMorphMap[ivx].mwm_iVxIndex; + MeshVertex &mvSrc = mlod.mlod_aVertices[vtx]; + MeshVertexMorph &mvmDst = rm.rmp_pmmmMorphMap->mmp_aMorphMap[ivx]; + // blend vertices + _aMorphedVtxs[vtx].x = (1.0f-rm.rmp_fFactor) * _aMorphedVtxs[vtx].x + rm.rmp_fFactor*mvmDst.mwm_x; + _aMorphedVtxs[vtx].y = (1.0f-rm.rmp_fFactor) * _aMorphedVtxs[vtx].y + rm.rmp_fFactor*mvmDst.mwm_y; + _aMorphedVtxs[vtx].z = (1.0f-rm.rmp_fFactor) * _aMorphedVtxs[vtx].z + rm.rmp_fFactor*mvmDst.mwm_z; + // blend normals + _aMorphedNormals[vtx].nx = (1.0f-rm.rmp_fFactor) * _aMorphedNormals[vtx].nx + rm.rmp_fFactor*mvmDst.mwm_nx; + _aMorphedNormals[vtx].ny = (1.0f-rm.rmp_fFactor) * _aMorphedNormals[vtx].ny + rm.rmp_fFactor*mvmDst.mwm_ny; + _aMorphedNormals[vtx].nz = (1.0f-rm.rmp_fFactor) * _aMorphedNormals[vtx].nz + rm.rmp_fFactor*mvmDst.mwm_nz; + } + } + } + } + + INDEX ctrw = rmsh.rmsh_iFirstWeight + rmsh.rmsh_ctWeights; + INDEX ctbones = 0; + CSkeleton *pskl = _aRenModels[rmsh.rmsh_iRenModelIndex].rm_pmiModel->mi_psklSkeleton; + // if skeleton for this model exists and its currently visible + if((pskl!=NULL) && (iSkeletonlod > -1)) { + // count bones in skeleton + ctbones = pskl->skl_aSkeletonLODs[iSkeletonlod].slod_aBones.Count(); + } + + // if there is skeleton attached to this mesh transfrom all vertices + if(ctbones > 0 && ctrw>0) { + // for each renweight + for(int irw=rmsh.rmsh_iFirstWeight; irwmwm_aVertexWeight.Count(); + for(int ivw=0; ivwmwm_aVertexWeight[ivw]; + INDEX ivx = vw.mww_iVertex; + MeshVertex mv = _aMorphedVtxs[ivx]; + MeshNormal mn = _aMorphedNormals[ivx]; + + // transform vertex and normal with this weight transform matrix + TransformVector((FLOAT3&)mv,mStrTransform); + RotateVector((FLOAT3&)mn,mTransform); // Don't stretch normals + + // Add new values to final vertices + _aFinalVtxs[ivx].x += mv.x * vw.mww_fWeight; + _aFinalVtxs[ivx].y += mv.y * vw.mww_fWeight; + _aFinalVtxs[ivx].z += mv.z * vw.mww_fWeight; + _aFinalNormals[ivx].nx += mn.nx * vw.mww_fWeight; + _aFinalNormals[ivx].ny += mn.ny * vw.mww_fWeight; + _aFinalNormals[ivx].nz += mn.nz * vw.mww_fWeight; + } + } + _pavFinalVertices = &_aFinalVtxs[0]; + _panFinalNormals = &_aFinalNormals[0]; + // mesh is in view space so transform light to view space + RotateVector(_vLightDirInView.vector,_mObjToView); + // set flag that mesh is in view space + rmsh.rmsh_bTransToViewSpace = TRUE; + // reset view matrix bacause model is allready transformed in view space + gfxSetViewMatrix(NULL); + // if no skeleton + } else { + // if flag is set to transform all vertices to view space + if(_bTransformBonelessModelToViewSpace) { + // transform every vertex using default model transform matrix (for boneless models) + Matrix12 mTransform; + Matrix12 mStrTransform; + MatrixCopy(mTransform, _aRenModels[rmsh.rmsh_iRenModelIndex].rm_mTransform); + MatrixCopy(mStrTransform, _aRenModels[rmsh.rmsh_iRenModelIndex].rm_mStrTransform); + + // if this is front face mesh remove rotation from transfrom matrix + if(mlod.mlod_ulFlags & ML_FULL_FACE_FORWARD) { + RemoveRotationFromMatrix(mStrTransform); + } + + // for each vertex + for(int ivx=0;ivx> Fix face forward meshes, when objects are left in object space") + + // set view matrix to gfx + gfxm[ 0] = m12[ 0]; gfxm[ 1] = m12[ 4]; gfxm[ 2] = m12[ 8]; gfxm[ 3] = 0; + gfxm[ 4] = m12[ 1]; gfxm[ 5] = m12[ 5]; gfxm[ 6] = m12[ 9]; gfxm[ 7] = 0; + gfxm[ 8] = m12[ 2]; gfxm[ 9] = m12[ 6]; gfxm[10] = m12[10]; gfxm[11] = 0; + gfxm[12] = m12[ 3]; gfxm[13] = m12[ 7]; gfxm[14] = m12[11]; gfxm[15] = 1; + gfxSetViewMatrix(gfxm); + + RenModel &rm = _aRenModels[rmsh.rmsh_iRenModelIndex]; + RenBone &rb = _aRenBones[rm.rm_iParentBoneIndex]; + RotateVector(_vLightDirInView.vector,rb.rb_mBonePlacement); + _pavFinalVertices = &mlod.mlod_aVertices[0]; + _panFinalNormals = &mlod.mlod_aNormals[0]; + // mark this mesh as in object space + rmsh.rmsh_bTransToViewSpace = FALSE; + } + } +} + +// render one ren model +static void RenderModel_View(RenModel &rm) +{ + ASSERT( _iRenderingType==1); + const BOOL bShowNormals = RM_GetFlags() & RMF_SHOWNORMALS; + + // for each mesh in renmodel + INDEX ctmsh = rm.rm_iFirstMesh + rm.rm_ctMeshes; + for( int imsh=rm.rm_iFirstMesh;imshsb_iID == iBoneID) { + rb = rbone; + ClearRenArrays(); + return TRUE; + } + } + // Clear ren arrays + ClearRenArrays(); + return FALSE; +} + +// Returns true if bone exists and sets two given vectors as start and end point of specified bone +BOOL RM_GetBoneAbsPosition(CModelInstance &mi,INDEX iBoneID, FLOAT3D &vStartPoint, FLOAT3D &vEndPoint) +{ + // do not transform to view space + MakeIdentityMatrix(_mAbsToViewer); + // use higher lod for bone finding + RM_SetCurrentDistance(0); + CalculateRenderingData(mi); + INDEX ctrb = _aRenBones.Count(); + // for each render bone after dummy one + for(INDEX irb=1;irbsb_iID == iBoneID) { + vStartPoint = FLOAT3D(0,0,0); + vEndPoint = FLOAT3D(0,0,rb.rb_psbBone->sb_fBoneLength); + TransformVector(vStartPoint.vector,rb.rb_mBonePlacement); + TransformVector(vEndPoint.vector,rb.rb_mBonePlacement); + ClearRenArrays(); + return TRUE; + } + } + // Clear ren arrays + ClearRenArrays(); + return FALSE; +} + +// Calculate complete rendering data for model instance +static void CalculateRenderingData(CModelInstance &mi) +{ + RM_SetObjectMatrices(mi); + // distance to model is z param in objtoview matrix + _fDistanceFactor = -_mObjToView[11]; + + // create first dummy model that serves as parent for the entire hierarchy + MakeRootModel(); + // build entire hierarchy with children + BuildHierarchy(&mi, 0); + + INDEX ctrm = _aRenModels.Count(); + // for each renmodel + for(int irm=1;irm> Add ska_bShowActiveBones") + if(/*ska_bShowActiveBones || */ RM_GetFlags() & RMF_SHOWACTIVEBONES) { + gfxDisableTexture(); + gfxDisableDepthTest(); + // render only active bones + RenderActiveBones(); + gfxEnableDepthTest(); + } + + // show root model instance colision box + if(ska_bShowColision) { + RM_SetObjectMatrices(mi); + if (mi.mi_cbAABox.Count()>0) + { + ColisionBox &cb = mi.GetCurrentColisionBox(); + RM_RenderColisionBox(mi,cb,C_mlGREEN); + } + } + + // reset arrays + ClearRenArrays(); +} + +// clear all ren arrays +static void ClearRenArrays() +{ + _pAdjustBonesCallback = NULL; + _pAdjustBonesData = NULL; + _pAdjustShaderParams = NULL; + _pAdjustShaderData = NULL; + + // clear all arrays + _aRenModels.PopAll(); + _aRenBones.PopAll(); + _aRenMesh.PopAll(); + _aRenWeights.PopAll(); + _aRenMorph.PopAll(); + _fCustomMlodDistance = -1; + _fCustomSlodDistance = -1; +} + diff --git a/Sources/Engine/Ska/RMRenderMask.cpp b/Sources/Engine/Ska/RMRenderMask.cpp new file mode 100644 index 0000000..35b0479 --- /dev/null +++ b/Sources/Engine/Ska/RMRenderMask.cpp @@ -0,0 +1,388 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" + +#include +#include +#include +#include +#include +#include +#include + +// vertex array for clipped polygons +#define MAX_CLIPPEDVERTICES 32 +// double buffer for clipping +static TransformedVertexData atvdClipped1[MAX_CLIPPEDVERTICES]; +static TransformedVertexData atvdClipped2[MAX_CLIPPEDVERTICES]; +static TransformedVertexData *ptvdSrc = atvdClipped1; +static TransformedVertexData *ptvdDst = atvdClipped2; +static INDEX ctvxSrc, ctvxDst; + + + +extern void InternalShader_Mask(void) +{ + // need arrays and texture + INDEX ctIdx = shaGetIndexCount(); + INDEX ctVtx = shaGetVertexCount(); + if( ctIdx==0 || ctVtx==0) return; + INDEX *pidx = shaGetIndexArray(); + GFXVertex4 *pvtx = shaGetVertexArray(); + GFXTexCoord *ptex = shaGetUVMap(0); + CTextureObject *pto = shaGetTexture(0); + ASSERT( (ctIdx%3) == 0); // must have triangles? + + // prepare texture + ULONG *pulTexFrame = NULL; + PIX pixMipWidth=0, pixMipHeight=0; + + if( pto!=NULL && ptex!=NULL) { + CTextureData *ptd = (CTextureData*)pto->GetData(); + if( ptd!=NULL && ptd->td_ptegEffect==NULL) { + // fetch some texture params + pulTexFrame = ptd->td_pulFrames + (pto->GetFrame()*ptd->td_slFrameSize)/BYTES_PER_TEXEL; + pixMipWidth = ptd->GetPixWidth(); + pixMipHeight = ptd->GetPixHeight(); + // reload texture and keep in memory + ptd->Force(TEX_STATIC); + } + } + // initialize texture for usage thru render triangle routine + SetTriangleTexture( pulTexFrame, pixMipWidth, pixMipHeight); + + // prepare projection + const BOOL bPerspective = _aprProjection.IsPerspective(); + CPerspectiveProjection3D &prPerspective = (CPerspectiveProjection3D &)*_aprProjection; + CParallelProjection3D &prParallel = (CParallelProjection3D &)*_aprProjection; + FLOAT fCenterI, fCenterJ, fRatioI, fRatioJ, fStepI, fStepJ, fZoomI, fZoomJ; + FLOAT fFrontClipDistance, fBackClipDistance, f1oFrontClipDistance, f1oBackClipDistance, fDepthBufferFactor; + + if( bPerspective) { + fCenterI = prPerspective.pr_ScreenCenter(1); + fCenterJ = prPerspective.pr_ScreenCenter(2); + fRatioI = prPerspective.ppr_PerspectiveRatios(1); + fRatioJ = prPerspective.ppr_PerspectiveRatios(2); + fFrontClipDistance = -prPerspective.pr_NearClipDistance; + fBackClipDistance = -prPerspective.pr_FarClipDistance; + f1oFrontClipDistance = -1.0f / prPerspective.pr_NearClipDistance; + f1oBackClipDistance = -1.0f / prPerspective.pr_FarClipDistance; + fDepthBufferFactor = prPerspective.pr_fDepthBufferFactor; + } else { + fCenterI = prParallel.pr_ScreenCenter(1); + fCenterJ = prParallel.pr_ScreenCenter(2); + fStepI = prParallel.pr_vStepFactors(1); + fStepJ = prParallel.pr_vStepFactors(2); + fZoomI = prParallel.pr_vZoomFactors(1); + fZoomJ = prParallel.pr_vZoomFactors(2); + fFrontClipDistance = -prPerspective.pr_NearClipDistance; + fBackClipDistance = -prPerspective.pr_FarClipDistance; + f1oFrontClipDistance = 1.0f; + f1oBackClipDistance = 1.0f; + fDepthBufferFactor = 1.0f; + } + + // copy view space vertices, project 'em to screen space and mark clipping + CStaticStackArray atvd; + INDEX iVtx=0; + for(; iVtx=_slMaskWidth + || tvd.tvd_fZ>fFrontClipDistance || (fBackClipDistance<0 && tvd.tvd_fZ=0) { + // add it to clip array + ptvdDst[ctvxDst] = tvd0; + ctvxDst++; + // if second vertex is out + if( fd1<0) { + // add clipped vertex at exit + TransformedVertexData &tvdClipped = ptvdDst[ctvxDst]; + ctvxDst++; + FLOAT fF = fd1/(fd1-fd0); + tvdClipped.tvd_fX = tvd1.tvd_fX - (tvd1.tvd_fX - tvd0.tvd_fX) *fF; + tvdClipped.tvd_fY = tvd1.tvd_fY - (tvd1.tvd_fY - tvd0.tvd_fY) *fF; + tvdClipped.tvd_fZ = fFrontClipDistance; + tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oFrontClipDistance; + FLOAT fU = tvd1.tvd_fU - (tvd1.tvd_fU - tvd0.tvd_fU) *fF; + FLOAT fV = tvd1.tvd_fV - (tvd1.tvd_fV - tvd0.tvd_fV) *fF; + tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK; + tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK; + } + // if first vertex is out (don't add it into clip array) + } else { + // if second vertex is in + if( fd1>=0) { + // add clipped vertex at entry + TransformedVertexData &tvdClipped = ptvdDst[ctvxDst]; + ctvxDst++; + FLOAT fF = fd0/(fd0-fd1); + tvdClipped.tvd_fX = tvd0.tvd_fX - (tvd0.tvd_fX - tvd1.tvd_fX) *fF; + tvdClipped.tvd_fY = tvd0.tvd_fY - (tvd0.tvd_fY - tvd1.tvd_fY) *fF; + tvdClipped.tvd_fZ = fFrontClipDistance; + tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oFrontClipDistance; + FLOAT fU = tvd0.tvd_fU - (tvd0.tvd_fU - tvd1.tvd_fU) *fF; + FLOAT fV = tvd0.tvd_fV - (tvd0.tvd_fV - tvd1.tvd_fV) *fF; + tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK; + tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK; + } + } + // proceed to next vertex in list (i.e. new pair of vertices) + ivx0=ivx1; + ivx1++; + }} + // swap buffers + Swap( ptvdSrc, ptvdDst); + Swap( ctvxSrc, ctvxDst); + + // if clipping to far clip plane is on + if( fBackClipDistance<0) { + ctvxDst=0; + INDEX ivx0=ctvxSrc-1; + INDEX ivx1=0; + {for( INDEX ivx=0; ivx=0) { + // add it to clip array + ptvdDst[ctvxDst] = tvd0; + ctvxDst++; + // if second vertex is out + if( fd1<0) { + // add clipped vertex at exit + TransformedVertexData &tvdClipped = ptvdDst[ctvxDst]; + ctvxDst++; + FLOAT fF = fd1/(fd1-fd0); + tvdClipped.tvd_fX = tvd1.tvd_fX - (tvd1.tvd_fX - tvd0.tvd_fX) *fF; + tvdClipped.tvd_fY = tvd1.tvd_fY - (tvd1.tvd_fY - tvd0.tvd_fY) *fF; + tvdClipped.tvd_fZ = fBackClipDistance; + tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oBackClipDistance; + FLOAT fU = tvd1.tvd_fU - (tvd1.tvd_fU - tvd0.tvd_fU) *fF; + FLOAT fV = tvd1.tvd_fV - (tvd1.tvd_fV - tvd0.tvd_fV) *fF; + tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK; + tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK; + } + // if first vertex is out (don't add it into clip array) + } else { + // if second vertex is in + if( fd1>=0) { + // add clipped vertex at entry + TransformedVertexData &tvdClipped = ptvdDst[ctvxDst]; + ctvxDst++; + FLOAT fF = fd0/(fd0-fd1); + tvdClipped.tvd_fX = tvd0.tvd_fX - (tvd0.tvd_fX - tvd1.tvd_fX) *fF; + tvdClipped.tvd_fY = tvd0.tvd_fY - (tvd0.tvd_fY - tvd1.tvd_fY) *fF; + tvdClipped.tvd_fZ = fBackClipDistance; + tvdClipped.tvd_pv2.pv2_f1oK = fDepthBufferFactor * f1oBackClipDistance; + FLOAT fU = tvd0.tvd_fU - (tvd0.tvd_fU - tvd1.tvd_fU) *fF; + FLOAT fV = tvd0.tvd_fV - (tvd0.tvd_fV - tvd1.tvd_fV) *fF; + tvdClipped.tvd_pv2.pv2_fUoK = fU * tvdClipped.tvd_pv2.pv2_f1oK; + tvdClipped.tvd_pv2.pv2_fVoK = fV * tvdClipped.tvd_pv2.pv2_f1oK; + } + } + // proceed to next vertex in list (i.e. new pair of vertices) + ivx0=ivx1; + ivx1++; + }} + // swap buffers + Swap( ptvdSrc, ptvdDst); + Swap( ctvxSrc, ctvxDst); + } + + // for each vertex + {for( INDEX ivx=0; ivx=0) { + // add it to clip array + ptvdDst[ctvxDst].tvd_pv2 = pv20; + ctvxDst++; + // if second vertex is out + if( fd1<0) { + PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2; + ctvxDst++; + FLOAT fF = fd1/(fd1-fd0); + pv2Clipped.pv2_fI = 0; + pv2Clipped.pv2_fJ = pv21.pv2_fJ - (pv21.pv2_fJ - pv20.pv2_fJ) *fF; + pv2Clipped.pv2_f1oK = pv21.pv2_f1oK - (pv21.pv2_f1oK - pv20.pv2_f1oK) *fF; + pv2Clipped.pv2_fUoK = pv21.pv2_fUoK - (pv21.pv2_fUoK - pv20.pv2_fUoK) *fF; + pv2Clipped.pv2_fVoK = pv21.pv2_fVoK - (pv21.pv2_fVoK - pv20.pv2_fVoK) *fF; + } + // if first vertex is out (don't add it into clip array) + } else { + // if second vertex is in + if( fd1>=0) { + // add clipped vertex at entry + PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2; + ctvxDst++; + FLOAT fF = fd0/(fd0-fd1); + pv2Clipped.pv2_fI = 0; + pv2Clipped.pv2_fJ = pv20.pv2_fJ - (pv20.pv2_fJ - pv21.pv2_fJ)*fF; + pv2Clipped.pv2_f1oK = pv20.pv2_f1oK - (pv20.pv2_f1oK - pv21.pv2_f1oK) *fF; + pv2Clipped.pv2_fUoK = pv20.pv2_fUoK - (pv20.pv2_fUoK - pv21.pv2_fUoK) *fF; + pv2Clipped.pv2_fVoK = pv20.pv2_fVoK - (pv20.pv2_fVoK - pv21.pv2_fVoK) *fF; + } + } + // proceed to next vertex in list (i.e. new pair of vertices) + ivx0=ivx1; + ivx1++; + }} + // swap buffers + Swap( ptvdSrc, ptvdDst); + Swap( ctvxSrc, ctvxDst); + + // clip polygon against right edge + ctvxDst=0; + ivx0=ctvxSrc-1; + ivx1=0; + {for( INDEX ivx=0; ivx=0) { + // add it to clip array + ptvdDst[ctvxDst].tvd_pv2 = pv20; + ctvxDst++; + // if second vertex is out + if( fd1<0) { + PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2; + ctvxDst++; + FLOAT fF = fd1/(fd1-fd0); + pv2Clipped.pv2_fI = _slMaskWidth; + pv2Clipped.pv2_fJ = pv21.pv2_fJ - (pv21.pv2_fJ - pv20.pv2_fJ)*fF; + pv2Clipped.pv2_f1oK = pv21.pv2_f1oK - (pv21.pv2_f1oK - pv20.pv2_f1oK) *fF; + pv2Clipped.pv2_fUoK = pv21.pv2_fUoK - (pv21.pv2_fUoK - pv20.pv2_fUoK) *fF; + pv2Clipped.pv2_fVoK = pv21.pv2_fVoK - (pv21.pv2_fVoK - pv20.pv2_fVoK) *fF; + } + // if first vertex is out (don't add it into clip array) + } else { + // if second vertex is in + if( fd1>=0) { + // add clipped vertex at entry + PolyVertex2D &pv2Clipped = ptvdDst[ctvxDst].tvd_pv2; + ctvxDst++; + FLOAT fF = fd0/(fd0-fd1); + pv2Clipped.pv2_fI = _slMaskWidth; + pv2Clipped.pv2_fJ = pv20.pv2_fJ - (pv20.pv2_fJ - pv21.pv2_fJ)*fF; + pv2Clipped.pv2_f1oK = pv20.pv2_f1oK - (pv20.pv2_f1oK - pv21.pv2_f1oK) *fF; + pv2Clipped.pv2_fUoK = pv20.pv2_fUoK - (pv20.pv2_fUoK - pv21.pv2_fUoK) *fF; + pv2Clipped.pv2_fVoK = pv20.pv2_fVoK - (pv20.pv2_fVoK - pv21.pv2_fVoK) *fF; + } + } + // proceed to next vertex in list (i.e. new pair of vertices) + ivx0=ivx1; + ivx1++; + }} + // swap buffers + Swap( ptvdSrc, ptvdDst); + Swap( ctvxSrc, ctvxDst); + + // draw all triangles in clipped polygon as a triangle fan, with clipping + PolyVertex2D &pvx0 = ptvdSrc[0].tvd_pv2; + {for( INDEX ivx=1; ivx +#include +#include +#include +#include +#include + + +#define RMF_WIREFRAME (1UL<<0) // set wireframe on +#define RMF_SHOWTEXTURE (1UL<<1) // show texture +#define RMF_SHOWNORMALS (1UL<<2) // show normalas +#define RMF_SHOWSKELETON (1UL<<3) // show skeleton +#define RMF_SHOWACTIVEBONES (1UL<<4) // show active bones + +#define SRMF_ATTACHMENT (1UL<<0) // set for attachment render models +#define SRMF_FOG (1UL<<1) // render in fog +#define SRMF_HAZE (1UL<<2) // render in haze +#define SRMF_SPECTATOR (1UL<<3) // model will not be rendered but shadows might +#define SRMF_INVERTED (1UL<<4) // stretch is inverted +#define SRMF_BBOXSET (1UL<<5) // bounding box has been calculated +#define SRMF_INSIDE (1UL<<6) // doesn't need clipping to frustum +#define SRMF_INMIRROR (1UL<<7) // doesn't need clipping to mirror/warp plane +#define SRMF_WEAPON (1UL<<8) // TEMP: weapon model is rendering so don't use ATI's Truform! + +typedef FLOAT FLOAT3[3]; +// Rendering structures +struct RenModel +{ + CModelInstance *rm_pmiModel;// pointer to model instance + INDEX rm_iParentModelIndex; // index of parent renmodel + INDEX rm_iParentBoneIndex; // index of parent bone this model is attached to + Matrix12 rm_mTransform; // Tranform matrix for models without skeletons + Matrix12 rm_mStrTransform; // Stretch transform matrix for models without skeleton + INDEX rm_iSkeletonLODIndex; // index of current skeleton lod + + INDEX rm_iFirstBone; // index if first renbone + INDEX rm_ctBones; // renbones count for this renmodel + INDEX rm_iFirstMesh; // index of first renmesh + INDEX rm_ctMeshes; // meshes count for this renmodel + INDEX rm_iFirstChildModel; + INDEX rm_iNextSiblingModel; +}; + +struct RenBone +{ + SkeletonBone *rb_psbBone; // pointer to skeleton bone + INDEX rb_iParentIndex; // index of parent renbone + INDEX rb_iRenModelIndex; // index of renmodel + AnimPos rb_apPos; + AnimRot rb_arRot; + Matrix12 rb_mTransform; // Transformation matrix for this ren bone + Matrix12 rb_mStrTransform; // Stretched transformation matrix for this ren bone + Matrix12 rb_mBonePlacement; // Placement of bone in absolute space +}; + +struct RenMorph +{ + MeshMorphMap *rmp_pmmmMorphMap; + FLOAT rmp_fFactor; +}; + +struct RenWeight +{ + MeshWeightMap *rw_pwmWeightMap; + INDEX rw_iBoneIndex; +}; + +struct RenMesh +{ + struct MeshInstance *rmsh_pMeshInst; + INDEX rmsh_iRenModelIndex; + INDEX rmsh_iFirstWeight; + INDEX rmsh_ctWeights; + INDEX rmsh_iFirstMorph; + INDEX rmsh_ctMorphs; + INDEX rmsh_iMeshLODIndex; // curent LOD index of msh_aMeshLODs array in Mesh + BOOL rmsh_bTransToViewSpace; // Is mesh transformed to view space +}; + +// initialize batch model rendering +ENGINE_API void RM_BeginRenderingView(CAnyProjection3D &apr, CDrawPort *pdp); +ENGINE_API void RM_BeginModelRenderingMask( CAnyProjection3D &prProjection, + UBYTE *pubMask, SLONG slMaskWidth, SLONG slMaskHeight); +// cleanup after batch model rendering +ENGINE_API void RM_EndRenderingView( BOOL bRestoreOrtho=TRUE); +ENGINE_API void RM_EndModelRenderingMask(void); + +// setup light parameters +ENGINE_API void RM_SetLightColor(COLOR colAmbient, COLOR colLight); +ENGINE_API void RM_SetLightDirection(FLOAT3D &vLightDir); +// LOD factor management +ENGINE_API void RM_SetCurrentDistance(FLOAT fDistFactor); +ENGINE_API FLOAT RM_GetMipFactor(void); +// setup object position +ENGINE_API void RM_SetObjectPlacement(const CPlacement3D &pl); +ENGINE_API void RM_SetObjectPlacement(const FLOATmatrix3D &m, const FLOAT3D &v); +ENGINE_API void RM_SetObjectMatrices(CModelInstance &mi); + +// render one SKA model with its children +ENGINE_API void RM_RenderSKA(CModelInstance &mi); +// render one bone in model instance +ENGINE_API void RM_RenderBone(CModelInstance &mi,INDEX iBoneID); +ENGINE_API void RM_RenderColisionBox(CModelInstance &mi,ColisionBox &cb, COLOR col); +// lods +ENGINE_API void RM_SetCustomMeshLodDistance(FLOAT fMeshLod); +ENGINE_API void RM_SetCustomSkeletonLodDistance(FLOAT fSkeletonLod); +ENGINE_API void RM_RenderGround(CTextureObject &to); +// Returns specified renbone +ENGINE_API RenBone *RM_FindRenBone(INDEX iBoneID); +// Returns renbone array and sets renbone count +ENGINE_API RenBone *RM_GetRenBoneArray(INDEX &ctrb); +// Returns true if bone exists and sets two given vectors as start and end point of specified bone +ENGINE_API BOOL RM_GetBoneAbsPosition(CModelInstance &mi,INDEX iBoneID, FLOAT3D &vStartPoint, FLOAT3D &vEndPoint); +// Returns Renbone +ENGINE_API BOOL RM_GetRenBoneAbs(CModelInstance &mi,INDEX iBoneID,RenBone &rb); + +ENGINE_API void RM_AddSimpleShadow_View(CModelInstance &mi, const FLOAT fIntensity, const FLOATplane3D &plShadowPlane); + +ENGINE_API void RM_GetModelVertices( CModelInstance &mi, CStaticStackArray &avVertices, FLOATmatrix3D &mRotation, + FLOAT3D &vPosition, FLOAT fNormalOffset, FLOAT fDistance); + +// test if the ray hit any of model instance's triangles and return +ENGINE_API FLOAT RM_TestRayCastHit( CModelInstance &mi, FLOATmatrix3D &mRotation, FLOAT3D &vPosition,const FLOAT3D &vOrigin, const FLOAT3D &vTarget,FLOAT fOldDistance,INDEX *piBoneID); + +ENGINE_API void RM_SetBoneAdjustCallback(void (*pAdjustBones)(void *pData), void *pData); +ENGINE_API void RM_SetShaderParamsAdjustCallback(void (*pAdjustShaderParams)(void *pData, INDEX iSurfaceID, CShader *pShader,ShaderParams &shParams),void *pData); +// Matrix12 operations +ENGINE_API void Matrix12ToQVect(QVect &qv,const Matrix12 &m12); +ENGINE_API void MatrixVectorToMatrix12(Matrix12 &m12,const FLOATmatrix3D &m, const FLOAT3D &v); +ENGINE_API void Matrix12ToMatrixVector(FLOATmatrix3D &c, FLOAT3D &v, const Matrix12 &m12); + +ENGINE_API void QVectToMatrix12(Matrix12 &m12, const QVect &qv); +ENGINE_API void MatrixMultiply(Matrix12 &c,const Matrix12 &m, const Matrix12 &n); +ENGINE_API void MatrixMultiplyCP(Matrix12 &c,const Matrix12 &m, const Matrix12 &n); +ENGINE_API void MatrixTranspose(Matrix12 &r, const Matrix12 &m); +ENGINE_API void TransformVertex(GFXVertex &v, const Matrix12 &m); +ENGINE_API void RotateVector(FLOAT3 &v, const Matrix12 &m); + +// model flags +ENGINE_API void RM_SetFlags(ULONG ulNewFlags); +ENGINE_API ULONG RM_GetFlags(); +ENGINE_API void RM_AddFlag(ULONG ulFlag); +ENGINE_API void RM_RemoveFlag(ULONG ulFlag); +ENGINE_API ULONG &RM_GetRenderFlags(); +ENGINE_API void RM_DoFogAndHaze(BOOL bOpaque); + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Ska/Skeleton.cpp b/Sources/Engine/Ska/Skeleton.cpp new file mode 100644 index 0000000..5a66219 --- /dev/null +++ b/Sources/Engine/Ska/Skeleton.cpp @@ -0,0 +1,272 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include "Skeleton.h" + +#include +#include +#include +#include +#include +#include + +#define SKELETON_VERSION 6 +#define SKELETON_ID "SKEL" + +CStaticArray _aSortArray; +INDEX ctSortBones; + +CSkeleton::CSkeleton() +{ +} + +CSkeleton::~CSkeleton() +{ +} +// Find bone in skeleton lod +INDEX CSkeleton::FindBoneInLOD(INDEX iBoneID,INDEX iSkeletonLod) +{ + ASSERT(iSkeletonLod>=0); + INDEX ctslods = skl_aSkeletonLODs.Count(); + if(ctslods < 1) return -1; + + SkeletonLOD &slod = skl_aSkeletonLODs[iSkeletonLod]; + INDEX ctb = slod.slod_aBones.Count(); + // for each bone in skeleton + for(INDEX isb=0;isb (-1)) { + SkeletonBone &sbParent = slod.slod_aBones[iParentIndex]; + MatrixMultiplyCP(sb.sb_mAbsPlacement,sbParent.sb_mAbsPlacement,sb.sb_mAbsPlacement); + } + } +} + +// Add skeleton lod to skeleton +void CSkeleton::AddSkletonLod(SkeletonLOD &slod) +{ + INDEX ctlods = skl_aSkeletonLODs.Count(); + skl_aSkeletonLODs.Expand(ctlods+1); + skl_aSkeletonLODs[ctlods] = slod; +} + +// Remove skleton lod form skeleton +void CSkeleton::RemoveSkeletonLod(SkeletonLOD *pslodRemove) +{ + INDEX ctslod = skl_aSkeletonLODs.Count(); + // create temp space for skeleton lods + CStaticArray aTempSLODs; + aTempSLODs.New(ctslod-1); + INDEX iIndexSrc=0; + + // for each skeleton lod in skeleton + for(INDEX islod=0;islodWriteID_t(CChunkID(SKELETON_ID)); + // write version + (*ostrFile)<<(INDEX)SKELETON_VERSION; + // write lods count + (*ostrFile)<Write_t(&sb.sb_mAbsPlacement,sizeof(FLOAT)*12); + // write RelPlacement Qvect stuct + ostrFile->Write_t(&sb.sb_qvRelPlacement,sizeof(QVect)); + // write offset len + (*ostrFile)<ExpectID_t(CChunkID(SKELETON_ID)); + // check file version + (*istrFile)>>iFileVersion; + if(iFileVersion != SKELETON_VERSION) { + ThrowF_t(TRANS("File '%s'.\nInvalid skeleton file version.\nExpected Ver \"%d\" but found \"%d\"\n"), + (const char*)istrFile->GetDescription(),SKELETON_VERSION,iFileVersion); + } + // read skeleton lod count + (*istrFile)>>ctslods; + + if(ctslods>0) { + skl_aSkeletonLODs.Expand(ctslods); + } + // for each skeleton lod + for(INDEX islod=0;islod>slod.slod_fnSourceFile; + // read MaxDistance + (*istrFile)>>slod.slod_fMaxDistance; + // read bone count + INDEX ctb; + (*istrFile)>>ctb; + // create bone array + slod.slod_aBones.New(ctb); + // read skeleton bones + for(INDEX ib=0;ib>strNameID; + // read Parent ID + (*istrFile)>>strParentID; + //(*istrFile)>>slod.slod_aBones[ib].sb_iParentIndex ; + sb.sb_iID = ska_GetIDFromStringTable(strNameID); + sb.sb_iParentID = ska_GetIDFromStringTable(strParentID); + // read AbsPlacement matrix + istrFile->Read_t(&sb.sb_mAbsPlacement,sizeof(FLOAT)*12); + // read RelPlacement Qvect stuct + istrFile->Read_t(&sb.sb_qvRelPlacement,sizeof(QVect)); + // read offset len + (*istrFile)>>sb.sb_fOffSetLen; + // read bone length + (*istrFile)>>sb.sb_fBoneLength; + } + } +} + +// Clear skeleton +void CSkeleton::Clear(void) +{ + // for each LOD + for (INDEX islod=0; islod +#include +#include +#include +#include +#include +#include +#include + + +struct QVect +{ + FLOAT3D vPos; + FLOATquat3D qRot; +}; + +struct ENGINE_API SkeletonLOD +{ + FLOAT slod_fMaxDistance; // distance in witch this lod is visible + CStaticArray slod_aBones; // array of bones for this lod + CTString slod_fnSourceFile; // source filename of ascii skleton lod +}; + +struct ENGINE_API SkeletonBone +{ + INDEX sb_iID; // ID of bone + INDEX sb_iParentID; // ID of parent bone + Matrix12 sb_mAbsPlacement; // default bone placement + QVect sb_qvRelPlacement; // default bone placement (same as mAbsPlacement) + FLOAT sb_fOffSetLen; + FLOAT sb_fBoneLength; // length of bone +}; + +class ENGINE_API CSkeleton : public CSerial +{ +public: + CSkeleton(); + ~CSkeleton(); + + // Find bone in skeleton lod + INDEX FindBoneInLOD(INDEX iBoneID,INDEX iSkeletonLod); + // Sorts bones in skeleton so parent bones are allways before child bones in array + void SortSkeleton(); + void SortSkeletonRecursive(INDEX iParentID, INDEX iSkeletonLod); + // Calculate absolute transformations for all bones in this lod + void CalculateAbsoluteTransformations(INDEX iSkeletonLod); + // Add skeleton lod to skeleton + void AddSkletonLod(SkeletonLOD &slod); + // Remove skleton lod form skeleton + void RemoveSkeletonLod(SkeletonLOD *pslodRemove); + + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * + void Clear(void); + SLONG GetUsedMemory(void); + + + CStaticArray skl_aSkeletonLODs; +}; + + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Ska/StringTable.cpp b/Sources/Engine/Ska/StringTable.cpp new file mode 100644 index 0000000..712ef26 --- /dev/null +++ b/Sources/Engine/Ska/StringTable.cpp @@ -0,0 +1,65 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" +#include +#include +#include +#include + +struct stTable +{ + INDEX st_iID; + CTString strName; +}; +CStaticStackArray _arStringTable; + +// add index in table +INDEX AddIndexToTable(CTString strName) +{ + _arStringTable.Push(); + + INDEX ctStrings = _arStringTable.Count(); + _arStringTable[ctStrings-1].strName = strName; + _arStringTable[ctStrings-1].st_iID = ctStrings; + return ctStrings-1; +} +// find string in table and return his index, if not found add new and return his index +INDEX ska_GetIDFromStringTable(CTString strName) +{ + if(strName == "") return -1; + + INDEX ctStrings = _arStringTable.Count(); + for(INDEX i=0;i= 0) && (iIndex <= ctStrings-1)) + { + return _arStringTable[iIndex].strName; + } + return ""; +} diff --git a/Sources/Engine/Ska/StringTable.h b/Sources/Engine/Ska/StringTable.h new file mode 100644 index 0000000..a34c8f1 --- /dev/null +++ b/Sources/Engine/Ska/StringTable.h @@ -0,0 +1,5 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +ENGINE_API INDEX ska_GetIDFromStringTable(CTString strName); +ENGINE_API CTString ska_GetStringFromTable(INDEX iIndex); +ENGINE_API INDEX ska_FindStringInTable(CTString strName); diff --git a/Sources/Engine/Ska/bison.simple b/Sources/Engine/Ska/bison.simple new file mode 100644 index 0000000..bbdaa97 --- /dev/null +++ b/Sources/Engine/Ska/bison.simple @@ -0,0 +1,687 @@ +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#undef YYERROR_VERBOSE +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 192 "bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +int +yyparse(YYPARSE_PARAM) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + +$ /* the action file gets copied in in place of this dollarsign */ +#line 487 "bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} diff --git a/Sources/Engine/Ska/smcFlex.skl b/Sources/Engine/Ska/smcFlex.skl new file mode 100644 index 0000000..23fac9c --- /dev/null +++ b/Sources/Engine/Ska/smcFlex.skl @@ -0,0 +1,1496 @@ +#include + +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.81 95/03/20 14:02:24 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +%- +#include +%* + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +//#ifdef c_plusplus +//#ifndef __cplusplus +//#define __cplusplus +//#endif +//#endif + +#if 1 //def __cplusplus + + #include +%+ + class istream; +%* + + /* Use prototypes in function declarations. */ + #define YY_USE_PROTOS + + /* The "const" storage-class-modifier is valid. */ + #define YY_USE_CONST + +#else /* ! __cplusplus */ + + #if __STDC__ + + #define YY_USE_PROTOS + #define YY_USE_CONST + + #endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +%- +extern FILE *yyin, *yyout; +%* + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) syyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { +%- + FILE *yy_input_file; +%+ + istream* yy_input_file; +%* + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +%- Standard (non-C++) definition +static YY_BUFFER_STATE yy_current_buffer = 0; +%* + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +%- Standard (non-C++) definition +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( const char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( const char *bytes, int len )); +%* + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +%% yytext/yyin/yyout/yy_state_type/yylineno etc. def's & init go here + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +//static + void syyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, const char *, int )); +#endif + +#ifndef YY_NO_INPUT +%- Standard (non-C++) definition +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +%* +#endif + +%- Standard (non-C++) definition +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( const char msg[] )); +%* + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ +%% code to fiddle yytext and yyleng for yymore() goes here + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ +%% code to copy yytext_ptr to yytext[] goes here, if %array + yy_c_buf_p = yy_cp; + +%% data tables for the DFA and the user's section 1 definitions go here + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifdef YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +%- Standard (non-C++) definition +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +%+ C++ definition +#define ECHO LexerOutput( yytext, yyleng ) +%* +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ +%% fread()/read() definition of YY_INPUT goes here unless we're doing C++ +%+ C++ definition + if ( (result = LexerInput( (char *) buf, max_size )) < 0 ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +%* +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +%- +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +%+ +#define YY_FATAL_ERROR(msg) LexerError( msg ) +%* +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +%- Standard (non-C++) definition +#define YY_DECL int yylex YY_PROTO(( void )) +%+ C++ definition +#define YY_DECL int yyFlexLexer::yylex() +%* +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +%% YY_RULE_SETUP definition goes here + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +%% user's declarations go here + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) +%- + yyin = stdin; +%+ + yyin = &cin; +%* + + if ( ! yyout ) +%- + yyout = stdout; +%+ + yyout = &cout; +%* + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { +%% yymore()-related code goes here + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + +%% code to set up and find next match goes here + +yy_find_action: +%% code to find the action number goes here + + YY_DO_BEFORE_ACTION; + +%% code for yylineno update goes here + +do_action: /* This label is used only to access EOF actions. */ + +%% debug code goes here + + switch ( yy_act ) + { /* beginning of action switch */ +%% actions go here + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { +%% code to do back-up for compressed tables and set up yy_cp goes here + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + +%+ +yyFlexLexer::yyFlexLexer( istream* arg_yyin, ostream* arg_yyout ) + { + yyin = arg_yyin; + yyout = arg_yyout; + yy_c_buf_p = 0; + yy_init = 1; + yy_start = 0; + yy_flex_debug = 0; + yylineno = 1; // this will only get updated if %option yylineno + + yy_did_buffer_switch_on_eof = 0; + + yy_looking_for_trail_begin = 0; + yy_more_flag = 0; + yy_more_len = 0; + + yy_start_stack_ptr = yy_start_stack_depth = 0; + yy_start_stack = 0; + + yy_current_buffer = 0; + +#ifdef YY_USES_REJECT + yy_state_buf = new yy_state_type[YY_BUF_SIZE + 2]; +#else + yy_state_buf = 0; +#endif + } + +yyFlexLexer::~yyFlexLexer() + { + delete yy_state_buf; + yy_delete_buffer( yy_current_buffer ); + } + +void yyFlexLexer::switch_streams( istream* new_in, ostream* new_out ) + { + if ( new_in ) + { + yy_delete_buffer( yy_current_buffer ); + yy_switch_to_buffer( yy_create_buffer( new_in, YY_BUF_SIZE ) ); + } + + if ( new_out ) + yyout = new_out; + } + +#ifdef YY_INTERACTIVE +int yyFlexLexer::LexerInput( char* buf, int /* max_size */ ) +#else +int yyFlexLexer::LexerInput( char* buf, int max_size ) +#endif + { + if ( yyin->eof() || yyin->fail() ) + return 0; + +#ifdef YY_INTERACTIVE + yyin->get( buf[0] ); + + if ( yyin->eof() ) + return 0; + + if ( yyin->bad() ) + return -1; + + return 1; + +#else + (void) yyin->read( buf, max_size ); + + if ( yyin->bad() ) + return -1; + else + return yyin->gcount(); +#endif + } + +void yyFlexLexer::LexerOutput( const char* buf, int size ) + { + (void) yyout->write( buf, size ); + } +%* + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +%- +static int yy_get_next_buffer() +%+ +int yyFlexLexer::yy_get_next_buffer() +%* + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +%- +static yy_state_type yy_get_previous_state() +%+ +yy_state_type yyFlexLexer::yy_get_previous_state() +%* + { + register yy_state_type yy_current_state; + register char *yy_cp; + +%% code to get the start state into yy_current_state goes here + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { +%% code to find the next state goes here + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +%- +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif +%+ +yy_state_type yyFlexLexer::yy_try_NUL_trans( yy_state_type yy_current_state ) +%* + { + register int yy_is_jam; +%% code to find the next state, and perhaps do backing up, goes here + + return yy_is_jam ? 0 : yy_current_state; + } + + +%- +#ifdef YY_USE_PROTOS +//static + void syyunput( int c, register char *yy_bp ) +#else +//static + void syyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif +%+ +void yyFlexLexer::yyunput( int c, register char* yy_bp ) +%* + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + +%% update yylineno here + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } + + +%- +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif +%+ +int yyFlexLexer::yyinput() +%* + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + +%% update BOL and yylineno + + return c; + } + + +%- +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif +%+ +void yyFlexLexer::yyrestart( istream* input_file ) +%* + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +%- +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif +%+ +void yyFlexLexer::yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +%* + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +%- +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif +%+ +void yyFlexLexer::yy_load_buffer_state() +%* + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +%- +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif +%+ +YY_BUFFER_STATE yyFlexLexer::yy_create_buffer( istream* file, int size ) +%* + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +%- +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif +%+ +void yyFlexLexer::yy_delete_buffer( YY_BUFFER_STATE b ) +%* + { + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +%- +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + +%+ +extern "C" int isatty YY_PROTO(( int )); +void yyFlexLexer::yy_init_buffer( YY_BUFFER_STATE b, istream* file ) +%* + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +%- +#ifdef YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#ifdef YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif +%+ + b->yy_is_interactive = 0; +%* + } + + +%- +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + +%+ +void yyFlexLexer::yy_flush_buffer( YY_BUFFER_STATE b ) +%* + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } +%* + + +#ifndef YY_NO_SCAN_BUFFER +%- +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +%* +#endif + + +#ifndef YY_NO_SCAN_STRING +%- +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( const char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +const char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +%* +#endif + + +#ifndef YY_NO_SCAN_BYTES +%- +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( const char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +const char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +%* +#endif + + +#ifndef YY_NO_PUSH_STATE +%- +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif +%+ +void yyFlexLexer::yy_push_state( int new_state ) +%* + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +%- +static void yy_pop_state() +%+ +void yyFlexLexer::yy_pop_state() +%* + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +%- +static int yy_top_state() +%+ +int yyFlexLexer::yy_top_state() +%* + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +%- +#ifdef YY_USE_PROTOS +static void yy_fatal_error( const char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + +%+ + +void yyFlexLexer::LexerError( const char msg[] ) + { + cerr << msg << '\n'; + exit( YY_EXIT_FAILURE ); + } +%* + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, const char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +const char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + return (void *) realloc( ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#ifdef YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif diff --git a/Sources/Engine/Ska/smcPars.cpp b/Sources/Engine/Ska/smcPars.cpp new file mode 100644 index 0000000..6efa7c3 --- /dev/null +++ b/Sources/Engine/Ska/smcPars.cpp @@ -0,0 +1,1142 @@ + +/* A Bison parser, made from engine/ska/smcpars.y with Bison version GNU Bison version 1.24 + */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define yyparse syyparse +#define yylex syylex +#define yyerror syyerror +#define yylval syylval +#define yychar syychar +#define yydebug syydebug +#define yynerrs syynerrs +#define c_float 258 +#define c_int 259 +#define c_string 260 +#define c_modelinstance 261 +#define k_PARENTBONE 262 +#define k_SE_SMC 263 +#define k_SE_END 264 +#define k_NAME 265 +#define k_TFNM 266 +#define k_MESH 267 +#define k_SKELETON 268 +#define k_ANIMSET 269 +#define K_ANIMATION 270 +#define k_TEXTURES 271 +#define k_OFFSET 272 +#define k_COLISION 273 +#define k_ALLFRAMESBBOX 274 +#define k_ANIMSPEED 275 +#define k_COLOR 276 + +#line 1 "engine/ska/smcpars.y" + +#include +#include +#include +#include +#include +#include +#include +#include "ParsingSmbs.h" + +extern BOOL bRememberSourceFN; +BOOL bOffsetAllreadySet = FALSE; +#line 15 "engine/ska/smcpars.y" + +#define YYERROR_VERBOSE 0 +// if error occurs in parsing +void syyerror(char *str) +{ + // just report the string + _pShell->ErrorF("%s", str); +}; + +#line 27 "engine/ska/smcpars.y" +typedef union { + int i; + float f; + const char *str; + CModelInstance *pmi; + float f6[6]; +} YYSTYPE; + +#ifndef YYLTYPE +typedef + struct yyltype + { + int timestamp; + int first_line; + int first_column; + int last_line; + int last_column; + char *text; + } + yyltype; + +#define YYLTYPE yyltype +#endif + +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 123 +#define YYFLAG -32768 +#define YYNTBASE 26 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 276 ? yytranslate[x] : 55) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 25, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 23, 2, 24, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 1, 10, 11, 14, 16, 18, 20, 22, 24, + 26, 28, 30, 31, 33, 37, 42, 43, 45, 47, + 50, 66, 67, 69, 83, 84, 87, 101, 102, 114, + 115, 122, 127, 130, 135, 137, 140, 144, 145, 147, + 151, 152, 155, 160, 161, 164, 169, 171, 173 +}; + +static const short yyrhs[] = { -1, + 38, 10, 5, 22, 27, 23, 28, 24, 0, 0, + 29, 28, 0, 42, 0, 44, 0, 45, 0, 48, + 0, 40, 0, 32, 0, 36, 0, 30, 0, 0, + 31, 0, 21, 4, 22, 0, 18, 23, 33, 24, + 0, 0, 34, 0, 35, 0, 34, 35, 0, 5, + 23, 54, 25, 54, 25, 54, 25, 54, 25, 54, + 25, 54, 22, 24, 0, 0, 37, 0, 19, 54, + 25, 54, 25, 54, 25, 54, 25, 54, 25, 54, + 22, 0, 0, 39, 38, 0, 17, 54, 25, 54, + 25, 54, 25, 54, 25, 54, 25, 54, 22, 0, + 0, 7, 5, 22, 38, 10, 5, 22, 41, 23, + 28, 24, 0, 0, 12, 11, 5, 22, 43, 50, + 0, 13, 11, 5, 22, 0, 14, 47, 0, 14, + 23, 46, 24, 0, 47, 0, 46, 47, 0, 11, + 5, 22, 0, 0, 49, 0, 15, 5, 22, 0, + 0, 50, 51, 0, 16, 23, 52, 24, 0, 0, + 52, 53, 0, 5, 11, 5, 22, 0, 3, 0, + 4, 0, 4, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 72, 91, 95, 96, 100, 101, 102, 103, 104, 105, + 106, 107, 111, 112, 116, 124, 130, 131, 135, 136, + 140, 150, 151, 155, 164, 174, 181, 200, 225, 234, + 240, 243, 250, 251, 255, 256, 260, 268, 269, 273, + 285, 286, 290, 294, 295, 299, 306, 310, 317 +}; + +static const char * const yytname[] = { "$","error","$undefined.","c_float", +"c_int","c_string","c_modelinstance","k_PARENTBONE","k_SE_SMC","k_SE_END","k_NAME", +"k_TFNM","k_MESH","k_SKELETON","k_ANIMSET","K_ANIMATION","k_TEXTURES","k_OFFSET", +"k_COLISION","k_ALLFRAMESBBOX","k_ANIMSPEED","k_COLOR","';'","'{'","'}'","','", +"parent_model","@1","components","component","mdl_color_opt","mdl_color","colision_header", +"colision_opt","colision_array","colision","all_frames_bbox_opt","all_frames_bbox", +"offset_opt","offset","child_model","@2","mesh","@3","skeleton","animset_header", +"animset_array","animset","animation_opt","animation","opt_textures","textures", +"textures_array","texture","float_const","\37777777735\37777777735\37777777735\37777777735\37777777735\37777777735\37777777735\37777777735\37777777735\37777777735\37777777735\37777777735\37777777735\37777777735" +}; +#endif + +static const short yyr1[] = { 0, + 27, 26, 28, 28, 29, 29, 29, 29, 29, 29, + 29, 29, 30, 30, 31, 32, 33, 33, 34, 34, + 35, 36, 36, 37, 38, 38, 39, 41, 40, 43, + 42, 44, 45, 45, 46, 46, 47, 48, 48, 49, + 50, 50, 51, 52, 52, 53, 54, 54, -1 +}; + +static const short yyr2[] = { 0, + 0, 8, 0, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 0, 1, 3, 4, 0, 1, 1, 2, + 15, 0, 1, 13, 0, 2, 13, 0, 11, 0, + 6, 4, 2, 4, 1, 2, 3, 0, 1, 3, + 0, 2, 4, 0, 2, 4, 1, 1, 1 +}; + +static const short yydefact[] = { 25, + 0, 0, 25, 47, 48, 0, 0, 26, 0, 0, + 0, 1, 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3, 12, 14, 10, + 11, 23, 9, 5, 6, 7, 8, 39, 0, 0, + 0, 0, 0, 0, 33, 0, 17, 0, 0, 2, + 4, 0, 25, 0, 0, 0, 0, 35, 40, 0, + 0, 18, 19, 0, 15, 0, 0, 30, 32, 37, + 34, 36, 0, 16, 20, 0, 0, 0, 41, 0, + 0, 0, 0, 31, 0, 0, 27, 28, 0, 42, + 0, 0, 0, 44, 0, 0, 3, 0, 0, 0, + 0, 0, 43, 45, 0, 0, 29, 0, 0, 0, + 0, 0, 0, 46, 0, 24, 0, 0, 0, 21, + 0, 0, 0 +}; + +static const short yydefgoto[] = { 121, + 14, 26, 27, 28, 29, 30, 61, 62, 63, 31, + 32, 2, 3, 33, 93, 34, 79, 35, 36, 57, + 45, 37, 38, 84, 90, 98, 104, 6 +}; + +static const short yypact[] = { -12, + 6, -4, -12,-32768,-32768, -18, 16,-32768, 6, -11, + 7,-32768, 6, 8, 9, 5, 6, 23, 19, 22, + 2, 30, 13, 6, 33, 14, 5,-32768,-32768,-32768, +-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 15, 17, + 36, 37, 39, 34,-32768, 24, 42, 25, 26,-32768, +-32768, 6, -12, 27, 29, 31, 3,-32768,-32768, 35, + 32, 42,-32768, 6,-32768, 38, 44,-32768,-32768,-32768, +-32768,-32768, 6,-32768,-32768, 40, 6, 52,-32768, 41, + 6, 45, 47, 43, 6, 48,-32768,-32768, 51,-32768, + 50, 6, 54,-32768, 6, 53, 5, -2, 55, 6, + 46, 49,-32768,-32768, 6, 56,-32768, 57, 59, 6, + 60, 6, 63,-32768, 62,-32768, 6, 66, 65,-32768, + 61, 79,-32768 +}; + +static const short yypgoto[] = {-32768, +-32768, -26,-32768,-32768,-32768,-32768,-32768,-32768, 28,-32768, +-32768, -1,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + -28,-32768,-32768,-32768,-32768,-32768,-32768, -9 +}; + + +#define YYLAST 108 + + +static const short yytable[] = { 11, + 51, 8, 102, 15, 1, 7, 9, 39, 4, 5, + 12, 18, 43, 43, 48, 58, 19, 20, 21, 22, + 10, 103, 23, 24, 44, 25, 71, 40, 72, 41, + 16, 13, 42, 17, 46, 47, 49, 50, 53, 52, + 54, 55, 66, 56, 43, 59, 60, 65, 68, 64, + 69, 67, 70, 78, 76, 74, 83, 73, 89, 108, + 122, 111, 77, 80, 81, 85, 87, 82, 88, 107, + 101, 86, 92, 94, 95, 91, 97, 100, 123, 105, + 110, 114, 96, 112, 116, 99, 117, 119, 120, 75, + 106, 0, 0, 0, 0, 109, 0, 0, 0, 0, + 113, 0, 115, 0, 0, 0, 0, 118 +}; + +static const short yycheck[] = { 9, + 27, 3, 5, 13, 17, 10, 25, 17, 3, 4, + 22, 7, 11, 11, 24, 44, 12, 13, 14, 15, + 5, 24, 18, 19, 23, 21, 24, 5, 57, 11, + 23, 25, 11, 25, 5, 23, 4, 24, 22, 25, + 5, 5, 52, 5, 11, 22, 5, 22, 22, 25, + 22, 53, 22, 10, 64, 24, 5, 23, 16, 11, + 0, 5, 25, 73, 25, 25, 22, 77, 22, 24, + 97, 81, 25, 23, 25, 85, 23, 25, 0, 25, + 25, 22, 92, 25, 22, 95, 25, 22, 24, 62, + 100, -1, -1, -1, -1, 105, -1, -1, -1, -1, + 110, -1, 112, -1, -1, -1, -1, 117 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "bison.simple" + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#undef YYERROR_VERBOSE +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#ifdef __cplusplus +extern "C" { +void *alloca (unsigned int); +}; +#else /* not __cplusplus */ +void *alloca (); +#endif /* not __cplusplus */ +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#endif /* alloca not defined. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT return(0) +#define YYABORT return(1) +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +int yyparse (void); +#endif + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (from, to, count) + char *from; + char *to; + int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *from, char *to, int count) +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 192 "bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#else +#define YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#endif + +int +yyparse(YYPARSE_PARAM) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); + yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 1: +#line 73 "engine/ska/smcpars.y" +{ + if(_yy_mi==0) { + yyerror("_yy_mi = NULL"); + } + // create new model instance + // _yy_mi = CreateModelInstance($3); + _yy_mi->SetName(yyvsp[-1].str); + // set its offset + _yy_mi->SetOffset(yyvsp[-3].f6); + // mark offset as read + bOffsetAllreadySet = FALSE; + // check if flag to remember source file name is set + if(bRememberSourceFN) + { + // remember source file name + _yy_mi->mi_fnSourceFile = CTString(SMCGetBufferName()); + } +; + break;} +case 15: +#line 117 "engine/ska/smcpars.y" +{ + COLOR c = yyvsp[-1].i; + // _yy_mi->SetModelColor($2); +; + break;} +case 16: +#line 125 "engine/ska/smcpars.y" +{ + +; + break;} +case 21: +#line 141 "engine/ska/smcpars.y" +{ + FLOAT3D vMin = FLOAT3D(yyvsp[-12].f, yyvsp[-10].f, yyvsp[-8].f); + FLOAT3D vMax = FLOAT3D(yyvsp[-6].f,yyvsp[-4].f,yyvsp[-2].f); + // add new colision box to current model instance + _yy_mi->AddColisionBox(yyvsp[-14].str,vMin,vMax); +; + break;} +case 24: +#line 156 "engine/ska/smcpars.y" +{ + // add new colision box to current model instance + _yy_mi->mi_cbAllFramesBBox.SetMin(FLOAT3D(yyvsp[-11].f, yyvsp[-9].f, yyvsp[-7].f)); + _yy_mi->mi_cbAllFramesBBox.SetMax(FLOAT3D(yyvsp[-5].f,yyvsp[-3].f,yyvsp[-1].f)); +; + break;} +case 25: +#line 165 "engine/ska/smcpars.y" +{ + // set offset with default offset values + yyval.f6[0] = 0; + yyval.f6[1] = 0; + yyval.f6[2] = 0; + yyval.f6[3] = 0; + yyval.f6[4] = 0; + yyval.f6[5] = 0; +; + break;} +case 26: +#line 175 "engine/ska/smcpars.y" +{ + // return new offset + memcpy(yyval.f6,yyvsp[-1].f6,sizeof(float)*6); +; + break;} +case 27: +#line 182 "engine/ska/smcpars.y" +{ + // if offset is not set + if(!bOffsetAllreadySet) + { + // set offset + yyval.f6[0] = yyvsp[-11].f; + yyval.f6[1] = yyvsp[-9].f; + yyval.f6[2] = yyvsp[-7].f; + yyval.f6[3] = yyvsp[-5].f; + yyval.f6[4] = yyvsp[-3].f; + yyval.f6[5] = yyvsp[-1].f; + // mark it as set now + bOffsetAllreadySet = TRUE; + } +; + break;} +case 28: +#line 201 "engine/ska/smcpars.y" +{ + // get parent ID + int iParentBoneID = ska_FindStringInTable(yyvsp[-5].str); + if(iParentBoneID<0) iParentBoneID=0; + // remember current model instance in parent bone token + yyvsp[-6].pmi = _yy_mi; + // set _yy_mi as new child + _yy_mi = CreateModelInstance(yyvsp[-1].str); + // add child to parent model instance + yyvsp[-6].pmi->AddChild(_yy_mi); + // add offset + _yy_mi->SetOffset(yyvsp[-3].f6); + // set its parent bone + _yy_mi->SetParentBone(iParentBoneID); + // + bOffsetAllreadySet = FALSE; + // if flag to remember source file is set + if(bRememberSourceFN) + { + // remember source name + _yy_mi->mi_fnSourceFile = CTString(SMCGetBufferName()); + } +; + break;} +case 29: +#line 226 "engine/ska/smcpars.y" +{ + // set parent model instance to _yy_mi again + _yy_mi = yyvsp[-10].pmi; +; + break;} +case 30: +#line 235 "engine/ska/smcpars.y" +{ + // add mesh to current model instance + _yy_mi->AddMesh_t((CTString)yyvsp[-1].str); +; + break;} +case 32: +#line 244 "engine/ska/smcpars.y" +{ + // add skeleton to current model instance + _yy_mi->AddSkeleton_t((CTString)yyvsp[-1].str); +; + break;} +case 37: +#line 261 "engine/ska/smcpars.y" +{ + // add animset to curent model instnce + _yy_mi->AddAnimSet_t((CTString)yyvsp[-1].str); +; + break;} +case 40: +#line 274 "engine/ska/smcpars.y" +{ + // set new clear state in model instance + _yy_mi->NewClearState(1); + // get anim ID + INDEX iAnimID = ska_GetIDFromStringTable(yyvsp[-1].str); + // add animation to curent model instance + _yy_mi->AddAnimation(iAnimID,AN_LOOPING,1,0); +; + break;} +case 46: +#line 300 "engine/ska/smcpars.y" +{ + // add texture to current model instance + _yy_mi->AddTexture_t((CTString)yyvsp[-1].str,yyvsp[-3].str,NULL); +; + break;} +case 47: +#line 307 "engine/ska/smcpars.y" +{ + yyval.f = yyvsp[0].f; +; + break;} +case 48: +#line 311 "engine/ska/smcpars.y" +{ + yyval.f = (float)yyvsp[0].i; +; + break;} +case 49: +#line 318 "engine/ska/smcpars.y" +{ + yyval.i = yyvsp[0].i; +; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 487 "bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; +} +#line 323 "engine/ska/smcpars.y" diff --git a/Sources/Engine/Ska/smcPars.y b/Sources/Engine/Ska/smcPars.y new file mode 100644 index 0000000..eb38117 --- /dev/null +++ b/Sources/Engine/Ska/smcPars.y @@ -0,0 +1,323 @@ +%{ +#include +#include +#include +#include +#include +#include +#include +#include "ParsingSmbs.h" + +extern BOOL bRememberSourceFN; +BOOL bOffsetAllreadySet = FALSE; +%} + +%{ +#define YYERROR_VERBOSE 0 +// if error occurs in parsing +void syyerror(char *str) +{ + // just report the string + _pShell->ErrorF("%s", str); +}; +%} + +/* BISON Declarations */ + +%union { + int i; + float f; + const char *str; + CModelInstance *pmi; + float f6[6]; +} + +%token c_float +%token c_int +%token c_string +%token c_modelinstance + +%type float_const +%type int_const +%type k_PARENTBONE +%type offset_opt +%type offset + + +%token k_SE_SMC +%token k_SE_END +%token k_NAME +%token k_TFNM +%token k_MESH +%token k_SKELETON +%token k_ANIMSET +%token K_ANIMATION +%token k_TEXTURES +%token k_PARENTBONE +%token k_OFFSET +%token k_COLISION +%token k_ALLFRAMESBBOX +%token k_ANIMSPEED +%token k_COLOR + +%start parent_model + +%% + +/*///////////////////////////////////////////////////////// + * Global structure of the source file. + */ + +parent_model +: offset_opt k_NAME c_string ';' +{ + if(_yy_mi==0) { + yyerror("_yy_mi = NULL"); + } + // create new model instance + // _yy_mi = CreateModelInstance($3); + _yy_mi->SetName($3); + // set its offset + _yy_mi->SetOffset($1); + // mark offset as read + bOffsetAllreadySet = FALSE; + // check if flag to remember source file name is set + if(bRememberSourceFN) + { + // remember source file name + _yy_mi->mi_fnSourceFile = CTString(SMCGetBufferName()); + } +} +'{' components '}' +; + +components +: /*null*/ +| component components +; + +component +: mesh +| skeleton +| animset_header +| animation_opt +| child_model +| colision_header +| all_frames_bbox_opt +| mdl_color_opt +; + +mdl_color_opt +: /*null*/ +| mdl_color +; + +mdl_color +: k_COLOR c_int ';' +{ + COLOR c = $2; + // _yy_mi->SetModelColor($2); +} +; + +colision_header +: k_COLISION '{' colision_opt '}' +{ + +} +; +colision_opt +:/*null*/ +| colision_array +; + +colision_array +: colision +| colision_array colision +; + +colision +: c_string '{' float_const ',' float_const ',' float_const ',' float_const ',' float_const ',' float_const ';' '}' +{ + FLOAT3D vMin = FLOAT3D($3, $5, $7); + FLOAT3D vMax = FLOAT3D($9,$11,$13); + // add new colision box to current model instance + _yy_mi->AddColisionBox($1,vMin,vMax); +} +; + +all_frames_bbox_opt +:/*null*/ +| all_frames_bbox +; + +all_frames_bbox +: k_ALLFRAMESBBOX float_const ',' float_const ',' float_const ',' float_const ',' float_const ',' float_const ';' +{ + // add new colision box to current model instance + _yy_mi->mi_cbAllFramesBBox.SetMin(FLOAT3D($2, $4, $6)); + _yy_mi->mi_cbAllFramesBBox.SetMax(FLOAT3D($8,$10,$12)); +} +; + +offset_opt +:/*null*/ +{ + // set offset with default offset values + $$[0] = 0; + $$[1] = 0; + $$[2] = 0; + $$[3] = 0; + $$[4] = 0; + $$[5] = 0; +} +| offset offset_opt +{ + // return new offset + memcpy($$,$1,sizeof(float)*6); +} +; +offset +: k_OFFSET float_const ',' float_const ',' float_const ',' float_const ',' float_const ',' float_const ';' +{ + // if offset is not set + if(!bOffsetAllreadySet) + { + // set offset + $$[0] = $2; + $$[1] = $4; + $$[2] = $6; + $$[3] = $8; + $$[4] = $10; + $$[5] = $12; + // mark it as set now + bOffsetAllreadySet = TRUE; + } +} +; + +child_model +: k_PARENTBONE c_string ';' offset_opt k_NAME c_string ';' +{ + // get parent ID + int iParentBoneID = ska_FindStringInTable($2); + if(iParentBoneID<0) iParentBoneID=0; + // remember current model instance in parent bone token + $1 = _yy_mi; + // set _yy_mi as new child + _yy_mi = CreateModelInstance($6); + // add child to parent model instance + $1->AddChild(_yy_mi); + // add offset + _yy_mi->SetOffset($4); + // set its parent bone + _yy_mi->SetParentBone(iParentBoneID); + // + bOffsetAllreadySet = FALSE; + // if flag to remember source file is set + if(bRememberSourceFN) + { + // remember source name + _yy_mi->mi_fnSourceFile = CTString(SMCGetBufferName()); + } +} +// read child components +'{' components '}' +{ + // set parent model instance to _yy_mi again + _yy_mi = $1; +} +; + + +mesh +: k_MESH k_TFNM c_string ';' +{ + // add mesh to current model instance + _yy_mi->AddMesh_t((CTString)$3); +} + opt_textures +; + +skeleton +: k_SKELETON k_TFNM c_string ';' +{ + // add skeleton to current model instance + _yy_mi->AddSkeleton_t((CTString)$3); +} +; +animset_header +: k_ANIMSET animset +| k_ANIMSET '{' animset_array '}' +; + +animset_array +: animset +| animset_array animset +; + +animset +: k_TFNM c_string ';' +{ + // add animset to curent model instnce + _yy_mi->AddAnimSet_t((CTString)$2); +} +; + +animation_opt +:/*null*/ +| animation +; + +animation +: K_ANIMATION c_string ';' +{ + // set new clear state in model instance + _yy_mi->NewClearState(1); + // get anim ID + INDEX iAnimID = ska_GetIDFromStringTable($2); + // add animation to curent model instance + _yy_mi->AddAnimation(iAnimID,AN_LOOPING,1,0); +} +; + +opt_textures +: /*null*/ +| opt_textures textures +; + +textures +: k_TEXTURES '{' textures_array'}' +; + +textures_array +: /*null*/ +| textures_array texture +; + +texture +: c_string k_TFNM c_string ';' +{ + // add texture to current model instance + _yy_mi->AddTexture_t((CTString)$3,$1,NULL); +} +; +float_const +: c_float +{ + $$ = $1; +} +| c_int +{ + $$ = (float)$1; +} +; + +int_const +: c_int +{ + $$ = $1; +} +; + +%% \ No newline at end of file diff --git a/Sources/Engine/Ska/smcScan.cpp b/Sources/Engine/Ska/smcScan.cpp new file mode 100644 index 0000000..9aeacf5 --- /dev/null +++ b/Sources/Engine/Ska/smcScan.cpp @@ -0,0 +1,1869 @@ +#define yy_create_buffer syy_create_buffer +#define yy_delete_buffer syy_delete_buffer +#define yy_scan_buffer syy_scan_buffer +#define yy_scan_string syy_scan_string +#define yy_scan_bytes syy_scan_bytes +#define yy_flex_debug syy_flex_debug +#define yy_init_buffer syy_init_buffer +#define yy_flush_buffer syy_flush_buffer +#define yy_load_buffer_state syy_load_buffer_state +#define yy_switch_to_buffer syy_switch_to_buffer +#define yyin syyin +#define yyleng syyleng +#define yylex syylex +#define yyout syyout +#define yyrestart syyrestart +#define yytext syytext +#define yywrap syywrap + +#line 20 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.cpp" +#include + +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.81 95/03/20 14:02:24 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +//#ifdef c_plusplus +//#ifndef __cplusplus +//#define __cplusplus +//#endif +//#endif + +#if 1 //def __cplusplus + + #include + + /* Use prototypes in function declarations. */ + #define YY_USE_PROTOS + + /* The "const" storage-class-modifier is valid. */ + #define YY_USE_CONST + +#else /* ! __cplusplus */ + + #if __STDC__ + + #define YY_USE_PROTOS + #define YY_USE_CONST + + #endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) syyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( const char *str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( const char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +//static + void syyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, const char *, int )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( const char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 33 +#define YY_END_OF_BUFFER 34 +static yyconst short int yy_accept[146] = + { 0, + 0, 0, 0, 0, 0, 0, 34, 32, 30, 31, + 32, 32, 20, 32, 32, 21, 21, 32, 32, 32, + 32, 32, 32, 32, 32, 28, 28, 19, 19, 31, + 17, 30, 0, 25, 0, 0, 21, 26, 0, 23, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 18, 0, 17, 25, 0, + 0, 29, 23, 23, 0, 24, 22, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 27, 0, + 24, 0, 0, 0, 0, 6, 5, 0, 0, 0, + 0, 0, 0, 4, 0, 0, 0, 0, 0, 15, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 3, 2, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 13, 0, 7, 10, 0, 9, 14, 0, 0, + 11, 0, 0, 16, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 4, 1, 5, 6, 1, 1, 1, 1, 1, + 1, 7, 8, 9, 10, 11, 12, 13, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 1, 15, 1, + 1, 1, 1, 1, 16, 17, 18, 19, 20, 21, + 1, 22, 23, 1, 24, 25, 26, 27, 28, 29, + 1, 30, 31, 32, 33, 1, 1, 34, 1, 1, + 1, 35, 1, 1, 36, 1, 37, 37, 37, 37, + + 38, 39, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 40, + 1, 1, 41, 1, 42, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[43] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 1, 2, 2, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, + 1, 1 + } ; + +static yyconst short int yy_base[152] = + { 0, + 0, 0, 40, 41, 47, 51, 221, 222, 55, 222, + 40, 197, 222, 47, 51, 51, 56, 41, 191, 198, + 201, 195, 199, 53, 58, 222, 210, 208, 78, 207, + 222, 70, 76, 222, 79, 184, 79, 222, 207, 82, + 96, 0, 184, 185, 182, 175, 179, 183, 173, 166, + 181, 166, 172, 186, 192, 222, 83, 222, 81, 178, + 192, 222, 87, 222, 84, 109, 0, 173, 167, 90, + 170, 171, 159, 169, 104, 163, 155, 160, 222, 160, + 222, 154, 96, 152, 152, 222, 222, 161, 153, 152, + 152, 157, 143, 222, 142, 158, 141, 99, 149, 222, + + 139, 138, 150, 150, 135, 136, 146, 138, 140, 130, + 141, 132, 222, 142, 222, 222, 119, 126, 125, 124, + 115, 222, 122, 114, 112, 112, 107, 222, 106, 109, + 115, 222, 106, 222, 222, 115, 222, 222, 111, 112, + 222, 87, 71, 222, 222, 148, 150, 152, 154, 156, + 44 + } ; + +static yyconst short int yy_def[152] = + { 0, + 145, 1, 146, 146, 147, 147, 145, 145, 145, 145, + 148, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 149, 149, 149, + 145, 145, 148, 145, 148, 145, 145, 145, 150, 145, + 145, 151, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 149, 145, 149, 145, 148, 145, + 150, 145, 145, 145, 145, 145, 151, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 0, 145, 145, 145, 145, 145, + 145 + } ; + +static yyconst short int yy_nxt[265] = + { 0, + 8, 9, 10, 9, 11, 12, 8, 8, 13, 14, + 8, 15, 16, 17, 13, 18, 8, 19, 8, 8, + 8, 8, 8, 8, 8, 20, 21, 22, 23, 8, + 24, 25, 8, 8, 8, 8, 8, 8, 8, 8, + 13, 13, 10, 10, 34, 67, 27, 27, 29, 30, + 29, 31, 29, 30, 29, 31, 32, 38, 32, 37, + 37, 40, 39, 37, 37, 43, 40, 44, 37, 37, + 41, 32, 50, 32, 35, 41, 51, 52, 53, 57, + 34, 57, 58, 59, 57, 34, 57, 58, 41, 40, + 42, 37, 37, 41, 63, 63, 66, 66, 41, 63, + + 63, 41, 64, 65, 144, 65, 41, 64, 66, 66, + 35, 97, 84, 35, 143, 35, 41, 85, 110, 41, + 64, 66, 66, 90, 41, 64, 98, 111, 142, 81, + 141, 140, 139, 138, 91, 137, 136, 135, 134, 133, + 132, 131, 130, 129, 128, 127, 126, 81, 26, 26, + 28, 28, 33, 33, 55, 55, 61, 61, 125, 124, + 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, + 113, 112, 109, 108, 107, 106, 105, 104, 103, 102, + 101, 100, 99, 96, 95, 94, 93, 92, 89, 88, + 87, 86, 83, 82, 62, 80, 56, 79, 78, 77, + + 76, 75, 74, 73, 72, 71, 70, 69, 68, 62, + 60, 56, 56, 54, 49, 48, 47, 46, 45, 36, + 145, 7, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145 + } ; + +static yyconst short int yy_chk[265] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 3, 4, 11, 151, 3, 4, 5, 5, + 5, 5, 6, 6, 6, 6, 9, 15, 9, 14, + 14, 16, 15, 16, 16, 18, 17, 18, 17, 17, + 16, 32, 24, 32, 11, 17, 24, 25, 25, 29, + 33, 29, 29, 35, 57, 59, 57, 57, 16, 37, + 16, 37, 37, 17, 40, 40, 65, 65, 37, 63, + + 63, 40, 40, 41, 143, 41, 63, 63, 41, 41, + 33, 83, 70, 35, 142, 59, 37, 70, 98, 40, + 40, 66, 66, 75, 63, 63, 83, 98, 140, 66, + 139, 136, 133, 131, 75, 130, 129, 127, 126, 125, + 124, 123, 121, 120, 119, 118, 117, 66, 146, 146, + 147, 147, 148, 148, 149, 149, 150, 150, 114, 112, + 111, 110, 109, 108, 107, 106, 105, 104, 103, 102, + 101, 99, 97, 96, 95, 93, 92, 91, 90, 89, + 88, 85, 84, 82, 80, 78, 77, 76, 74, 73, + 72, 71, 69, 68, 61, 60, 55, 54, 53, 52, + + 51, 50, 49, 48, 47, 46, 45, 44, 43, 39, + 36, 30, 28, 27, 23, 22, 21, 20, 19, 12, + 7, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, + 145, 145, 145, 145 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +char *yytext; +#line 1 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +#define INITIAL 0 +#line 3 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +#include "ParsingSmbs.h" +#include "smcPars.h" + +#include +#include +#include +#include + +#include +extern CTFileName _fnmApplicationPath; + +int syywrap(void) +{ + // no more buffers + return 1; +}; + +// declarations for recursive SMC script parsing +struct BufferStackEntry { + YY_BUFFER_STATE bse_bs; + const char *bse_strName; + const char *bse_strContents; + int bse_iLineCt; + BOOL bse_bParserEnd; +}; + +static BufferStackEntry _abseBufferStack[SMC_MAX_INCLUDE_LEVEL]; +static int _ibsBufferStackTop = -1; + +void SMCPushBuffer(const char *strName, const char *strBuffer, BOOL bParserEnd) +{ + _ibsBufferStackTop++; + + _abseBufferStack[_ibsBufferStackTop].bse_strContents = strdup(strBuffer); + _abseBufferStack[_ibsBufferStackTop].bse_strName = strdup(strName); + _abseBufferStack[_ibsBufferStackTop].bse_iLineCt = 1; + _abseBufferStack[_ibsBufferStackTop].bse_bParserEnd = bParserEnd; + + _abseBufferStack[_ibsBufferStackTop].bse_bs = syy_scan_string((char*)(const char*)strBuffer); + + syy_switch_to_buffer(_abseBufferStack[_ibsBufferStackTop].bse_bs); +} +BOOL SMCPopBuffer(void) +{ + syy_delete_buffer( _abseBufferStack[_ibsBufferStackTop].bse_bs); + free((void*)_abseBufferStack[_ibsBufferStackTop].bse_strName); + free((void*)_abseBufferStack[_ibsBufferStackTop].bse_strContents); + BOOL bParserEnd = _abseBufferStack[_ibsBufferStackTop].bse_bParserEnd; + + _ibsBufferStackTop--; + + if (_ibsBufferStackTop>=0) { + syy_switch_to_buffer(_abseBufferStack[_ibsBufferStackTop].bse_bs); + } + return bParserEnd; +} +const char *SMCGetBufferName(void) +{ + return _abseBufferStack[_ibsBufferStackTop].bse_strName; +} +int SMCGetBufferLineNumber(void) +{ + return _abseBufferStack[_ibsBufferStackTop].bse_iLineCt; +} +int SMCGetBufferStackDepth(void) +{ + return _ibsBufferStackTop; +} +const char *SMCGetBufferContents(void) +{ + return _abseBufferStack[_ibsBufferStackTop].bse_strContents; +} +void SMCCountOneLine(void) +{ + _abseBufferStack[_ibsBufferStackTop].bse_iLineCt++; +} +#define COMMENT 1 + +#define INCLUDE 2 + +#line 593 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.cpp" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifdef YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 91 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" + + +#line 719 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.cpp" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 146 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 222 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 93 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +BEGIN(INCLUDE); + YY_BREAK +case 2: +YY_RULE_SETUP +#line 94 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_SE_SMC); } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 95 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_SE_END); } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 96 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_TFNM); } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 97 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_NAME); } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 98 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_MESH); } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 99 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_SKELETON);} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 100 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_ANIMSET);} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 101 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(K_ANIMATION);} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 102 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_TEXTURES);} + YY_BREAK +case 11: +YY_RULE_SETUP +#line 103 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_PARENTBONE);} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 104 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_OFFSET);} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 105 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_COLISION);} + YY_BREAK +case 14: +YY_RULE_SETUP +#line 106 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_ANIMSPEED);} + YY_BREAK +case 15: +YY_RULE_SETUP +#line 107 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_COLOR);} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 108 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ return(k_ALLFRAMESBBOX);} + YY_BREAK +case 17: +YY_RULE_SETUP +#line 110 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +/* eat the whitespace */ + YY_BREAK +case 18: +YY_RULE_SETUP +#line 111 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ /* got the include file name */ + + if (SMCGetBufferStackDepth() >= SMC_MAX_INCLUDE_LEVEL) { + ThrowF_t("File '%s' line %d\nIncludes nested too deeply '%s'",SMCGetBufferName(), SMCGetBufferLineNumber(),yytext); + } + char strFileName[256]; + strcpy(strFileName, yytext); + strFileName[strlen(strFileName)-1] = 0; + + CTString strIncludeFile; + try { + strIncludeFile.Load_t(CTString(strFileName)); + SMCPushBuffer(strFileName, strIncludeFile, FALSE); + + } catch(char *strError) { + (void)strError; + ThrowF_t("File '%s'\n Could not open '%s' (line %d)",SMCGetBufferName(), strFileName, SMCGetBufferLineNumber()); + } + BEGIN(INITIAL); +} + YY_BREAK +case 19: +YY_RULE_SETUP +#line 131 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ /* something unrecognized inside include statement */ + BEGIN(INITIAL); + ThrowF_t("File '%s'\n Wrong syntax for include statement",SMCGetBufferName()); +} + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMENT): +case YY_STATE_EOF(INCLUDE): +#line 135 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ + if (SMCPopBuffer()) { + yyterminate(); + } +} + YY_BREAK +/* single character operators and punctuations */ +case 20: +YY_RULE_SETUP +#line 143 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ + return(yytext[0]);} + YY_BREAK +/* constants */ +case 21: +YY_RULE_SETUP +#line 148 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ syylval.i = atoi(yytext); return(c_int); } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 149 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ syylval.i = strtoul(yytext+2, NULL, 16); return(c_int);} + YY_BREAK +case 23: +YY_RULE_SETUP +#line 150 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ syylval.f = (float) atof(yytext); return(c_float); } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 151 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ syylval.f = (float) atof(yytext); return(c_float); } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 152 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ + char *strNew; + // remove double-quotes + yytext[strlen(yytext)-1] = 0; + strNew = yytext+1; + syylval.str = (const char*)strNew; + return(c_string); +} + YY_BREAK +/* eat up comments */ +case 26: +YY_RULE_SETUP +#line 162 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ BEGIN(COMMENT); } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 163 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ BEGIN(INITIAL); } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 164 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{} + YY_BREAK +case 29: +YY_RULE_SETUP +#line 165 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ SMCCountOneLine(); } + YY_BREAK +/* eat up whitespace */ +case 30: +YY_RULE_SETUP +#line 168 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ +} + YY_BREAK +/* eat up linefeeds and count lines in all conditions */ +case 31: +YY_RULE_SETUP +#line 171 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ + SMCCountOneLine();; +} + YY_BREAK +/* for all unrecognized characters */ +case 32: +YY_RULE_SETUP +#line 176 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +{ + // report an error + ThrowF_t("File '%s'\n Unrecognized character '%c' (line %d)", SMCGetBufferName(), yytext[0], SMCGetBufferLineNumber()); + //ThrowF_t("Unrecognized character '%c' in line %d)", yytext[0], _yy_iLine ); +} + YY_BREAK +case 33: +YY_RULE_SETUP +#line 182 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" +ECHO; + YY_BREAK +#line 1020 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.cpp" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a singled characater, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 146 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 146 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 145); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifdef YY_USE_PROTOS +//static + void syyunput( int c, register char *yy_bp ) +#else +//static + void syyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + yytext_ptr = yy_c_buf_p; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + { + yy_c_buf_p = + yytext_ptr + YY_MORE_ADJ; + return EOF; + } + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + break; + + case EOB_ACT_LAST_MATCH: +#ifdef __cplusplus + YY_FATAL_ERROR( + "unexpected last match in yyinput()" ); +#else + YY_FATAL_ERROR( + "unexpected last match in input()" ); +#endif + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + + return c; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#ifdef YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#ifdef YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( const char *str ) +#else +YY_BUFFER_STATE yy_scan_string( str ) +const char *str; +#endif + { + int len; + for ( len = 0; str[len]; ++len ) + ; + + return yy_scan_bytes( str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( const char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +const char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( const char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n - YY_MORE_ADJ; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, const char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +const char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + return (void *) realloc( ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#ifdef YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 182 "D:\\SE1_GPL\\Sources\\Engine\\Ska\\\\smcScan.l" + + diff --git a/Sources/Engine/Ska/smcScan.l b/Sources/Engine/Ska/smcScan.l new file mode 100644 index 0000000..759907c --- /dev/null +++ b/Sources/Engine/Ska/smcScan.l @@ -0,0 +1,183 @@ +%option prefix="syy" +%{ +#include "ParsingSmbs.h" +#include "smcPars.h" + +#include +#include +#include +#include + +#include +extern CTFileName _fnmApplicationPath; + +int syywrap(void) +{ + // no more buffers + return 1; +}; + +// declarations for recursive SMC script parsing +struct BufferStackEntry { + YY_BUFFER_STATE bse_bs; + const char *bse_strName; + const char *bse_strContents; + int bse_iLineCt; + BOOL bse_bParserEnd; +}; + +static BufferStackEntry _abseBufferStack[SMC_MAX_INCLUDE_LEVEL]; +static int _ibsBufferStackTop = -1; + +void SMCPushBuffer(const char *strName, const char *strBuffer, BOOL bParserEnd) +{ + _ibsBufferStackTop++; + + _abseBufferStack[_ibsBufferStackTop].bse_strContents = strdup(strBuffer); + _abseBufferStack[_ibsBufferStackTop].bse_strName = strdup(strName); + _abseBufferStack[_ibsBufferStackTop].bse_iLineCt = 1; + _abseBufferStack[_ibsBufferStackTop].bse_bParserEnd = bParserEnd; + + _abseBufferStack[_ibsBufferStackTop].bse_bs = syy_scan_string((char*)(const char*)strBuffer); + + syy_switch_to_buffer(_abseBufferStack[_ibsBufferStackTop].bse_bs); +} +BOOL SMCPopBuffer(void) +{ + syy_delete_buffer( _abseBufferStack[_ibsBufferStackTop].bse_bs); + free((void*)_abseBufferStack[_ibsBufferStackTop].bse_strName); + free((void*)_abseBufferStack[_ibsBufferStackTop].bse_strContents); + BOOL bParserEnd = _abseBufferStack[_ibsBufferStackTop].bse_bParserEnd; + + _ibsBufferStackTop--; + + if (_ibsBufferStackTop>=0) { + syy_switch_to_buffer(_abseBufferStack[_ibsBufferStackTop].bse_bs); + } + return bParserEnd; +} +const char *SMCGetBufferName(void) +{ + return _abseBufferStack[_ibsBufferStackTop].bse_strName; +} +int SMCGetBufferLineNumber(void) +{ + return _abseBufferStack[_ibsBufferStackTop].bse_iLineCt; +} +int SMCGetBufferStackDepth(void) +{ + return _ibsBufferStackTop; +} +const char *SMCGetBufferContents(void) +{ + return _abseBufferStack[_ibsBufferStackTop].bse_strContents; +} +void SMCCountOneLine(void) +{ + _abseBufferStack[_ibsBufferStackTop].bse_iLineCt++; +} +%} + +%x COMMENT +%x INCLUDE + +DIGIT [0-9] +HEXDIGIT [0-9A-Fa-f] +DOUBLEQUOTE \" +STRINGCONTENT ([^\"]|(\\\")) +NONEXP_FLT ({DIGIT}+"."{DIGIT}*) +EXP_FLT (({DIGIT}+("."({DIGIT}*)?)?)("E"|"e")("+"|"-")?{DIGIT}+) + +%% + +"#INCLUDE" BEGIN(INCLUDE); +"SE_SMC" { return(k_SE_SMC); } +"SE_END" { return(k_SE_END); } +"TFNM" { return(k_TFNM); } +"NAME" { return(k_NAME); } +"MESH" { return(k_MESH); } +"SKELETON" { return(k_SKELETON);} +"ANIMSET" { return(k_ANIMSET);} +"ANIMATION" { return(K_ANIMATION);} +"TEXTURES" { return(k_TEXTURES);} +"PARENTBONE" { return(k_PARENTBONE);} +"OFFSET" { return(k_OFFSET);} +"COLISION" { return(k_COLISION);} +"ANIMSPEED" { return(k_ANIMSPEED);} +"COLOR" { return(k_COLOR);} +"ALLFRAMESBBOX" { return(k_ALLFRAMESBBOX);} + +[ \t]*"\"" /* eat the whitespace */ +[^"\""]*"\"" { /* got the include file name */ + + if (SMCGetBufferStackDepth() >= SMC_MAX_INCLUDE_LEVEL) { + ThrowF_t("File '%s' line %d\nIncludes nested too deeply '%s'",SMCGetBufferName(), SMCGetBufferLineNumber(),yytext); + } + char strFileName[256]; + strcpy(strFileName, yytext); + strFileName[strlen(strFileName)-1] = 0; + + CTString strIncludeFile; + try { + strIncludeFile.Load_t(CTString(strFileName)); + SMCPushBuffer(strFileName, strIncludeFile, FALSE); + + } catch(char *strError) { + (void)strError; + ThrowF_t("File '%s'\n Could not open '%s' (line %d)",SMCGetBufferName(), strFileName, SMCGetBufferLineNumber()); + } + BEGIN(INITIAL); +} +. { /* something unrecognized inside include statement */ + BEGIN(INITIAL); + ThrowF_t("File '%s'\n Wrong syntax for include statement",SMCGetBufferName()); +} +<> { + if (SMCPopBuffer()) { + yyterminate(); + } +} + + + /* single character operators and punctuations */ +";"|","|"{"|"}" { + return(yytext[0]);} + + /* constants */ + +"-"?{DIGIT}+ { syylval.i = atoi(yytext); return(c_int); } +"0x"{HEXDIGIT}+ { syylval.i = strtoul(yytext+2, NULL, 16); return(c_int);} +"-"?{NONEXP_FLT}("f"|"F")? { syylval.f = (float) atof(yytext); return(c_float); } +"-"?{EXP_FLT}("f"|"F")? { syylval.f = (float) atof(yytext); return(c_float); } +"\""{STRINGCONTENT}*"\"" { + char *strNew; + // remove double-quotes + yytext[strlen(yytext)-1] = 0; + strNew = yytext+1; + syylval.str = (const char*)strNew; + return(c_string); +} + + /* eat up comments */ +"/*" { BEGIN(COMMENT); } +"* /" { BEGIN(INITIAL); } +. {} +"//"[^\n]*\n { SMCCountOneLine(); } + + /* eat up whitespace */ +[ \t]+ { +} + /* eat up linefeeds and count lines in all conditions */ +<*>\n { + SMCCountOneLine();; +} + + /* for all unrecognized characters */ +. { + // report an error + ThrowF_t("File '%s'\n Unrecognized character '%c' (line %d)", SMCGetBufferName(), yytext[0], SMCGetBufferLineNumber()); + //ThrowF_t("Unrecognized character '%c' in line %d)", yytext[0], _yy_iLine ); +} + +%% + diff --git a/Sources/Engine/Ska/smcpars.h b/Sources/Engine/Ska/smcpars.h new file mode 100644 index 0000000..57a4e8f --- /dev/null +++ b/Sources/Engine/Ska/smcpars.h @@ -0,0 +1,29 @@ +typedef union { + int i; + float f; + const char *str; + CModelInstance *pmi; + float f6[6]; +} YYSTYPE; +#define c_float 258 +#define c_int 259 +#define c_string 260 +#define c_modelinstance 261 +#define k_PARENTBONE 262 +#define k_SE_SMC 263 +#define k_SE_END 264 +#define k_NAME 265 +#define k_TFNM 266 +#define k_MESH 267 +#define k_SKELETON 268 +#define k_ANIMSET 269 +#define K_ANIMATION 270 +#define k_TEXTURES 271 +#define k_OFFSET 272 +#define k_COLISION 273 +#define k_ALLFRAMESBBOX 274 +#define k_ANIMSPEED 275 +#define k_COLOR 276 + + +extern YYSTYPE syylval; diff --git a/Sources/Engine/Sound/DSOUND.H b/Sources/Engine/Sound/DSOUND.H new file mode 100644 index 0000000..d98a6ea --- /dev/null +++ b/Sources/Engine/Sound/DSOUND.H @@ -0,0 +1,2345 @@ +/*==========================================================================; + * + * Copyright (C) 1995-2000 Microsoft Corporation. All Rights Reserved. + * + * File: dsound.h + * Content: DirectSound include file + * + **************************************************************************/ + +#define COM_NO_WINDOWS_H +#include +#include + +#ifndef DIRECTSOUND_VERSION +#define DIRECTSOUND_VERSION 0x0800 /* Version 8.0 */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#ifndef __DSOUND_INCLUDED__ +#define __DSOUND_INCLUDED__ + +/* Type definitions shared with Direct3D */ + +#ifndef DX_SHARED_DEFINES + +typedef float D3DVALUE, *LPD3DVALUE; + +#ifndef D3DCOLOR_DEFINED +typedef DWORD D3DCOLOR; +#define D3DCOLOR_DEFINED +#endif + +#ifndef LPD3DCOLOR_DEFINED +typedef DWORD *LPD3DCOLOR; +#define LPD3DCOLOR_DEFINED +#endif + +#ifndef D3DVECTOR_DEFINED +typedef struct _D3DVECTOR { + float x; + float y; + float z; +} D3DVECTOR; +#define D3DVECTOR_DEFINED +#endif + +#ifndef LPD3DVECTOR_DEFINED +typedef D3DVECTOR *LPD3DVECTOR; +#define LPD3DVECTOR_DEFINED +#endif + +#define DX_SHARED_DEFINES +#endif // DX_SHARED_DEFINES + +#define _FACDS 0x878 /* DirectSound's facility code */ +#define MAKE_DSHRESULT(code) MAKE_HRESULT(1, _FACDS, code) + +// DirectSound Component GUID {47D4D946-62E8-11CF-93BC-444553540000} +DEFINE_GUID(CLSID_DirectSound, 0x47d4d946, 0x62e8, 0x11cf, 0x93, 0xbc, 0x44, 0x45, 0x53, 0x54, 0x0, 0x0); + +// DirectSound 8.0 Component GUID {3901CC3F-84B5-4FA4-BA35-AA8172B8A09B} +DEFINE_GUID(CLSID_DirectSound8, 0x3901cc3f, 0x84b5, 0x4fa4, 0xba, 0x35, 0xaa, 0x81, 0x72, 0xb8, 0xa0, 0x9b); + +// DirectSound Capture Component GUID {B0210780-89CD-11D0-AF08-00A0C925CD16} +DEFINE_GUID(CLSID_DirectSoundCapture, 0xb0210780, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); + +// DirectSound 8.0 Capture Component GUID {E4BCAC13-7F99-4908-9A8E-74E3BF24B6E1} +DEFINE_GUID(CLSID_DirectSoundCapture8, 0xe4bcac13, 0x7f99, 0x4908, 0x9a, 0x8e, 0x74, 0xe3, 0xbf, 0x24, 0xb6, 0xe1); + +// DirectSound Full Duplex Component GUID {FEA4300C-7959-4147-B26A-2377B9E7A91D} +DEFINE_GUID(CLSID_DirectSoundFullDuplex, 0xfea4300c, 0x7959, 0x4147, 0xb2, 0x6a, 0x23, 0x77, 0xb9, 0xe7, 0xa9, 0x1d); + + +// DirectSound default playback device GUID {DEF00000-9C6D-47ED-AAF1-4DDA8F2B5C03} +DEFINE_GUID(DSDEVID_DefaultPlayback, 0xdef00000, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); + +// DirectSound default capture device GUID {DEF00001-9C6D-47ED-AAF1-4DDA8F2B5C03} +DEFINE_GUID(DSDEVID_DefaultCapture, 0xdef00001, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); + +// DirectSound default device for voice playback {DEF00002-9C6D-47ED-AAF1-4DDA8F2B5C03} +DEFINE_GUID(DSDEVID_DefaultVoicePlayback, 0xdef00002, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); + +// DirectSound default device for voice capture {DEF00003-9C6D-47ED-AAF1-4DDA8F2B5C03} +DEFINE_GUID(DSDEVID_DefaultVoiceCapture, 0xdef00003, 0x9c6d, 0x47ed, 0xaa, 0xf1, 0x4d, 0xda, 0x8f, 0x2b, 0x5c, 0x03); + + +// +// Forward declarations for interfaces. +// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined +// + +#ifdef __cplusplus +struct IDirectSound; +struct IDirectSoundBuffer; +struct IDirectSound3DListener; +struct IDirectSound3DBuffer; +struct IDirectSoundCapture; +struct IDirectSoundCaptureBuffer; +struct IDirectSoundNotify; +#endif // __cplusplus + + +// +// DirectSound 8.0 interfaces. +// + +#if DIRECTSOUND_VERSION >= 0x0800 + +#ifdef __cplusplus +struct IDirectSound8; +struct IDirectSoundBuffer8; +struct IDirectSoundCaptureBuffer8; +struct IDirectSoundFXGargle; +struct IDirectSoundFXChorus; +struct IDirectSoundFXFlanger; +struct IDirectSoundFXEcho; +struct IDirectSoundFXDistortion; +struct IDirectSoundFXCompressor; +struct IDirectSoundFXParamEq; +struct IDirectSoundFXWavesReverb; +struct IDirectSoundFXI3DL2Reverb; +struct IDirectSoundCaptureFXAec; +struct IDirectSoundCaptureFXNoiseSuppress; +struct IDirectSoundFullDuplex; +#endif // __cplusplus + +// IDirectSound8, IDirectSoundBuffer8 and IDirectSoundCaptureBuffer8 are the +// only DirectSound 7.0 interfaces with changed functionality in version 8.0. +// The other level 8 interfaces as equivalent to their level 7 counterparts: + +#define IDirectSoundCapture8 IDirectSoundCapture +#define IDirectSound3DListener8 IDirectSound3DListener +#define IDirectSound3DBuffer8 IDirectSound3DBuffer +#define IDirectSoundNotify8 IDirectSoundNotify +#define IDirectSoundFXGargle8 IDirectSoundFXGargle +#define IDirectSoundFXChorus8 IDirectSoundFXChorus +#define IDirectSoundFXFlanger8 IDirectSoundFXFlanger +#define IDirectSoundFXEcho8 IDirectSoundFXEcho +#define IDirectSoundFXDistortion8 IDirectSoundFXDistortion +#define IDirectSoundFXCompressor8 IDirectSoundFXCompressor +#define IDirectSoundFXParamEq8 IDirectSoundFXParamEq +#define IDirectSoundFXWavesReverb8 IDirectSoundFXWavesReverb +#define IDirectSoundFXI3DL2Reverb8 IDirectSoundFXI3DL2Reverb +#define IDirectSoundCaptureFXAec8 IDirectSoundCaptureFXAec +#define IDirectSoundCaptureFXNoiseSuppress8 IDirectSoundCaptureFXNoiseSuppress +#define IDirectSoundFullDuplex8 IDirectSoundFullDuplex + +#endif // DIRECTSOUND_VERSION >= 0x0800 + + +typedef struct IDirectSound *LPDIRECTSOUND; +typedef struct IDirectSoundBuffer *LPDIRECTSOUNDBUFFER; +typedef struct IDirectSound3DListener *LPDIRECTSOUND3DLISTENER; +typedef struct IDirectSound3DBuffer *LPDIRECTSOUND3DBUFFER; +typedef struct IDirectSoundCapture *LPDIRECTSOUNDCAPTURE; +typedef struct IDirectSoundCaptureBuffer *LPDIRECTSOUNDCAPTUREBUFFER; +typedef struct IDirectSoundNotify *LPDIRECTSOUNDNOTIFY; + + +#if DIRECTSOUND_VERSION >= 0x0800 +typedef struct IDirectSoundFXGargle *LPDIRECTSOUNDFXGARGLE; +typedef struct IDirectSoundFXChorus *LPDIRECTSOUNDFXCHORUS; +typedef struct IDirectSoundFXFlanger *LPDIRECTSOUNDFXFLANGER; +typedef struct IDirectSoundFXEcho *LPDIRECTSOUNDFXECHO; +typedef struct IDirectSoundFXDistortion *LPDIRECTSOUNDFXDISTORTION; +typedef struct IDirectSoundFXCompressor *LPDIRECTSOUNDFXCOMPRESSOR; +typedef struct IDirectSoundFXParamEq *LPDIRECTSOUNDFXPARAMEQ; +typedef struct IDirectSoundFXWavesReverb *LPDIRECTSOUNDFXWAVESREVERB; +typedef struct IDirectSoundFXI3DL2Reverb *LPDIRECTSOUNDFXI3DL2REVERB; +typedef struct IDirectSoundCaptureFXAec *LPDIRECTSOUNDCAPTUREFXAEC; +typedef struct IDirectSoundCaptureFXNoiseSuppress *LPDIRECTSOUNDCAPTUREFXNOISESUPPRESS; +typedef struct IDirectSoundFullDuplex *LPDIRECTSOUNDFULLDUPLEX; + +typedef struct IDirectSound8 *LPDIRECTSOUND8; +typedef struct IDirectSoundBuffer8 *LPDIRECTSOUNDBUFFER8; +typedef struct IDirectSound3DListener8 *LPDIRECTSOUND3DLISTENER8; +typedef struct IDirectSound3DBuffer8 *LPDIRECTSOUND3DBUFFER8; +typedef struct IDirectSoundCapture8 *LPDIRECTSOUNDCAPTURE8; +typedef struct IDirectSoundCaptureBuffer8 *LPDIRECTSOUNDCAPTUREBUFFER8; +typedef struct IDirectSoundNotify8 *LPDIRECTSOUNDNOTIFY8; +typedef struct IDirectSoundFXGargle8 *LPDIRECTSOUNDFXGARGLE8; +typedef struct IDirectSoundFXChorus8 *LPDIRECTSOUNDFXCHORUS8; +typedef struct IDirectSoundFXFlanger8 *LPDIRECTSOUNDFXFLANGER8; +typedef struct IDirectSoundFXEcho8 *LPDIRECTSOUNDFXECHO8; +typedef struct IDirectSoundFXDistortion8 *LPDIRECTSOUNDFXDISTORTION8; +typedef struct IDirectSoundFXCompressor8 *LPDIRECTSOUNDFXCOMPRESSOR8; +typedef struct IDirectSoundFXParamEq8 *LPDIRECTSOUNDFXPARAMEQ8; +typedef struct IDirectSoundFXWavesReverb8 *LPDIRECTSOUNDFXWAVESREVERB8; +typedef struct IDirectSoundFXI3DL2Reverb8 *LPDIRECTSOUNDFXI3DL2REVERB8; +typedef struct IDirectSoundCaptureFXAec8 *LPDIRECTSOUNDCAPTUREFXAEC8; +typedef struct IDirectSoundCaptureFXNoiseSuppress8 *LPDIRECTSOUNDCAPTUREFXNOISESUPPRESS8; +typedef struct IDirectSoundFullDuplex8 *LPDIRECTSOUNDFULLDUPLEX8; + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// IID definitions for the unchanged DirectSound 8.0 interfaces +// + +#if DIRECTSOUND_VERSION >= 0x0800 +#define IID_IDirectSoundCapture8 IID_IDirectSoundCapture +#define IID_IDirectSound3DListener8 IID_IDirectSound3DListener +#define IID_IDirectSound3DBuffer8 IID_IDirectSound3DBuffer +#define IID_IDirectSoundNotify8 IID_IDirectSoundNotify +#define IID_IDirectSoundFXGargle8 IID_IDirectSoundFXGargle +#define IID_IDirectSoundFXChorus8 IID_IDirectSoundFXChorus +#define IID_IDirectSoundFXFlanger8 IID_IDirectSoundFXFlanger +#define IID_IDirectSoundFXEcho8 IID_IDirectSoundFXEcho +#define IID_IDirectSoundFXDistortion8 IID_IDirectSoundFXDistortion +#define IID_IDirectSoundFXCompressor8 IID_IDirectSoundFXCompressor +#define IID_IDirectSoundFXParamEq8 IID_IDirectSoundFXParamEq +#define IID_IDirectSoundFXWavesReverb8 IID_IDirectSoundFXWavesReverb +#define IID_IDirectSoundFXI3DL2Reverb8 IID_IDirectSoundFXI3DL2Reverb +#define IID_IDirectSoundCaptureFXAec8 IID_IDirectSoundCaptureFXAec +#define IID_IDirectSoundCaptureFXNoiseSuppress8 IID_IDirectSoundCaptureFXNoiseSuppress +#define IID_IDirectSoundFullDuplex8 IID_IDirectSoundFullDuplex +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// Compatibility typedefs +// + +#ifndef _LPCWAVEFORMATEX_DEFINED +#define _LPCWAVEFORMATEX_DEFINED +typedef const WAVEFORMATEX *LPCWAVEFORMATEX; +#endif // _LPCWAVEFORMATEX_DEFINED + +#ifndef __LPCGUID_DEFINED__ +#define __LPCGUID_DEFINED__ +typedef const GUID *LPCGUID; +#endif // __LPCGUID_DEFINED__ + +typedef LPDIRECTSOUND *LPLPDIRECTSOUND; +typedef LPDIRECTSOUNDBUFFER *LPLPDIRECTSOUNDBUFFER; +typedef LPDIRECTSOUND3DLISTENER *LPLPDIRECTSOUND3DLISTENER; +typedef LPDIRECTSOUND3DBUFFER *LPLPDIRECTSOUND3DBUFFER; +typedef LPDIRECTSOUNDCAPTURE *LPLPDIRECTSOUNDCAPTURE; +typedef LPDIRECTSOUNDCAPTUREBUFFER *LPLPDIRECTSOUNDCAPTUREBUFFER; +typedef LPDIRECTSOUNDNOTIFY *LPLPDIRECTSOUNDNOTIFY; + +#if DIRECTSOUND_VERSION >= 0x0800 +typedef LPDIRECTSOUND8 *LPLPDIRECTSOUND8; +typedef LPDIRECTSOUNDBUFFER8 *LPLPDIRECTSOUNDBUFFER8; +typedef LPDIRECTSOUNDCAPTURE8 *LPLPDIRECTSOUNDCAPTURE8; +typedef LPDIRECTSOUNDCAPTUREBUFFER8 *LPLPDIRECTSOUNDCAPTUREBUFFER8; +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// Structures +// + +typedef struct _DSCAPS +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwMinSecondarySampleRate; + DWORD dwMaxSecondarySampleRate; + DWORD dwPrimaryBuffers; + DWORD dwMaxHwMixingAllBuffers; + DWORD dwMaxHwMixingStaticBuffers; + DWORD dwMaxHwMixingStreamingBuffers; + DWORD dwFreeHwMixingAllBuffers; + DWORD dwFreeHwMixingStaticBuffers; + DWORD dwFreeHwMixingStreamingBuffers; + DWORD dwMaxHw3DAllBuffers; + DWORD dwMaxHw3DStaticBuffers; + DWORD dwMaxHw3DStreamingBuffers; + DWORD dwFreeHw3DAllBuffers; + DWORD dwFreeHw3DStaticBuffers; + DWORD dwFreeHw3DStreamingBuffers; + DWORD dwTotalHwMemBytes; + DWORD dwFreeHwMemBytes; + DWORD dwMaxContigFreeHwMemBytes; + DWORD dwUnlockTransferRateHwBuffers; + DWORD dwPlayCpuOverheadSwBuffers; + DWORD dwReserved1; + DWORD dwReserved2; +} DSCAPS, *LPDSCAPS; + +typedef const DSCAPS *LPCDSCAPS; + +typedef struct _DSBCAPS +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwUnlockTransferRate; + DWORD dwPlayCpuOverhead; +} DSBCAPS, *LPDSBCAPS; + +typedef const DSBCAPS *LPCDSBCAPS; + +#if DIRECTSOUND_VERSION >= 0x0800 + + typedef struct _DSEFFECTDESC + { + DWORD dwSize; + DWORD dwFlags; + GUID guidDSFXClass; + DWORD dwReserved1; + DWORD dwReserved2; + } DSEFFECTDESC, *LPDSEFFECTDESC; + typedef const DSEFFECTDESC *LPCDSEFFECTDESC; + + #define DSFX_LOCHARDWARE 0x00000001 + #define DSFX_LOCSOFTWARE 0x00000002 + + enum + { + DSFXR_PRESENT, // 0 + DSFXR_LOCHARDWARE, // 1 + DSFXR_LOCSOFTWARE, // 2 + DSFXR_UNALLOCATED, // 3 + DSFXR_FAILED, // 4 + DSFXR_UNKNOWN, // 5 + DSFXR_SENDLOOP // 6 + }; + + typedef struct _DSCEFFECTDESC + { + DWORD dwSize; + DWORD dwFlags; + GUID guidDSCFXClass; + GUID guidDSCFXInstance; + DWORD dwReserved1; + DWORD dwReserved2; + } DSCEFFECTDESC, *LPDSCEFFECTDESC; + typedef const DSCEFFECTDESC *LPCDSCEFFECTDESC; + + #define DSCFX_LOCHARDWARE 0x00000001 + #define DSCFX_LOCSOFTWARE 0x00000002 + + #define DSCFXR_LOCHARDWARE 0x00000010 + #define DSCFXR_LOCSOFTWARE 0x00000020 + #define DSCFXR_UNALLOCATED 0x00000040 + #define DSCFXR_FAILED 0x00000080 + #define DSCFXR_UNKNOWN 0x00000100 + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +typedef struct _DSBUFFERDESC +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; +#if DIRECTSOUND_VERSION >= 0x0700 + GUID guid3DAlgorithm; +#endif +} DSBUFFERDESC, *LPDSBUFFERDESC; + +typedef const DSBUFFERDESC *LPCDSBUFFERDESC; + +// Older version of this structure: + +typedef struct _DSBUFFERDESC1 +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; +} DSBUFFERDESC1, *LPDSBUFFERDESC1; + +typedef const DSBUFFERDESC1 *LPCDSBUFFERDESC1; + +typedef struct _DS3DBUFFER +{ + DWORD dwSize; + D3DVECTOR vPosition; + D3DVECTOR vVelocity; + DWORD dwInsideConeAngle; + DWORD dwOutsideConeAngle; + D3DVECTOR vConeOrientation; + LONG lConeOutsideVolume; + D3DVALUE flMinDistance; + D3DVALUE flMaxDistance; + DWORD dwMode; +} DS3DBUFFER, *LPDS3DBUFFER; + +typedef const DS3DBUFFER *LPCDS3DBUFFER; + +typedef struct _DS3DLISTENER +{ + DWORD dwSize; + D3DVECTOR vPosition; + D3DVECTOR vVelocity; + D3DVECTOR vOrientFront; + D3DVECTOR vOrientTop; + D3DVALUE flDistanceFactor; + D3DVALUE flRolloffFactor; + D3DVALUE flDopplerFactor; +} DS3DLISTENER, *LPDS3DLISTENER; + +typedef const DS3DLISTENER *LPCDS3DLISTENER; + +typedef struct _DSCCAPS +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwFormats; + DWORD dwChannels; +} DSCCAPS, *LPDSCCAPS; + +typedef const DSCCAPS *LPCDSCCAPS; + +typedef struct _DSCBUFFERDESC1 +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; +} DSCBUFFERDESC1, *LPDSCBUFFERDESC1; + +typedef struct _DSCBUFFERDESC +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; + LPWAVEFORMATEX lpwfxFormat; +#if DIRECTSOUND_VERSION >= 0x0800 + DWORD dwFXCount; + LPDSCEFFECTDESC lpDSCFXDesc; +#endif +} DSCBUFFERDESC, *LPDSCBUFFERDESC; + +typedef const DSCBUFFERDESC *LPCDSCBUFFERDESC; + +typedef struct _DSCBCAPS +{ + DWORD dwSize; + DWORD dwFlags; + DWORD dwBufferBytes; + DWORD dwReserved; +} DSCBCAPS, *LPDSCBCAPS; + +typedef const DSCBCAPS *LPCDSCBCAPS; + +typedef struct _DSBPOSITIONNOTIFY +{ + DWORD dwOffset; + HANDLE hEventNotify; +} DSBPOSITIONNOTIFY, *LPDSBPOSITIONNOTIFY; + +typedef const DSBPOSITIONNOTIFY *LPCDSBPOSITIONNOTIFY; + +// +// DirectSound API +// + +typedef BOOL (CALLBACK *LPDSENUMCALLBACKA)(LPGUID, LPCSTR, LPCSTR, LPVOID); +typedef BOOL (CALLBACK *LPDSENUMCALLBACKW)(LPGUID, LPCWSTR, LPCWSTR, LPVOID); + +extern HRESULT WINAPI DirectSoundCreate(LPCGUID pcGuidDevice, LPDIRECTSOUND *ppDS, LPUNKNOWN pUnkOuter); +extern HRESULT WINAPI DirectSoundEnumerateA(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext); +extern HRESULT WINAPI DirectSoundEnumerateW(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext); + +extern HRESULT WINAPI DirectSoundCaptureCreate(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE *ppDSC, LPUNKNOWN pUnkOuter); +extern HRESULT WINAPI DirectSoundCaptureEnumerateA(LPDSENUMCALLBACKA pDSEnumCallback, LPVOID pContext); +extern HRESULT WINAPI DirectSoundCaptureEnumerateW(LPDSENUMCALLBACKW pDSEnumCallback, LPVOID pContext); + +#if DIRECTSOUND_VERSION >= 0x0800 +extern HRESULT WINAPI DirectSoundCreate8(LPCGUID pcGuidDevice, LPDIRECTSOUND8 *ppDS8, LPUNKNOWN pUnkOuter); +extern HRESULT WINAPI DirectSoundCaptureCreate8(LPCGUID pcGuidDevice, LPDIRECTSOUNDCAPTURE8 *ppDSC8, LPUNKNOWN pUnkOuter); +extern HRESULT WINAPI DirectSoundFullDuplexCreate(LPCGUID pcGuidCaptureDevice, LPCGUID pcGuidRenderDevice, + LPCDSCBUFFERDESC pcDSCBufferDesc, LPCDSBUFFERDESC pcDSBufferDesc, HWND hWnd, + DWORD dwLevel, LPDIRECTSOUNDFULLDUPLEX* ppDSFD, LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8, + LPDIRECTSOUNDBUFFER8 *ppDSBuffer8, LPUNKNOWN pUnkOuter); +#define DirectSoundFullDuplexCreate8 DirectSoundFullDuplexCreate + +extern HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest); +#endif // DIRECTSOUND_VERSION >= 0x0800 + +#ifdef UNICODE +#define LPDSENUMCALLBACK LPDSENUMCALLBACKW +#define DirectSoundEnumerate DirectSoundEnumerateW +#define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateW +#else // UNICODE +#define LPDSENUMCALLBACK LPDSENUMCALLBACKA +#define DirectSoundEnumerate DirectSoundEnumerateA +#define DirectSoundCaptureEnumerate DirectSoundCaptureEnumerateA +#endif // UNICODE + +// +// IUnknown +// + +#if !defined(__cplusplus) || defined(CINTERFACE) +#ifndef IUnknown_QueryInterface +#define IUnknown_QueryInterface(p,a,b) (p)->lpVtbl->QueryInterface(p,a,b) +#endif // IUnknown_QueryInterface +#ifndef IUnknown_AddRef +#define IUnknown_AddRef(p) (p)->lpVtbl->AddRef(p) +#endif // IUnknown_AddRef +#ifndef IUnknown_Release +#define IUnknown_Release(p) (p)->lpVtbl->Release(p) +#endif // IUnknown_Release +#else // !defined(__cplusplus) || defined(CINTERFACE) +#ifndef IUnknown_QueryInterface +#define IUnknown_QueryInterface(p,a,b) (p)->QueryInterface(a,b) +#endif // IUnknown_QueryInterface +#ifndef IUnknown_AddRef +#define IUnknown_AddRef(p) (p)->AddRef() +#endif // IUnknown_AddRef +#ifndef IUnknown_Release +#define IUnknown_Release(p) (p)->Release() +#endif // IUnknown_Release +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#ifndef __IReferenceClock_INTERFACE_DEFINED__ +#define __IReferenceClock_INTERFACE_DEFINED__ + +typedef LONGLONG REFERENCE_TIME; +typedef REFERENCE_TIME *LPREFERENCE_TIME; + +DEFINE_GUID(IID_IReferenceClock, 0x56a86897, 0x0ad4, 0x11ce, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70); + +#undef INTERFACE +#define INTERFACE IReferenceClock + +DECLARE_INTERFACE_(IReferenceClock, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IReferenceClock methods + STDMETHOD(GetTime) (THIS_ REFERENCE_TIME *pTime) PURE; + STDMETHOD(AdviseTime) (THIS_ REFERENCE_TIME rtBaseTime, REFERENCE_TIME rtStreamTime, + HANDLE hEvent, LPDWORD pdwAdviseCookie) PURE; + STDMETHOD(AdvisePeriodic) (THIS_ REFERENCE_TIME rtStartTime, REFERENCE_TIME rtPeriodTime, + HANDLE hSemaphore, LPDWORD pdwAdviseCookie) PURE; + STDMETHOD(Unadvise) (THIS_ DWORD dwAdviseCookie) PURE; +}; + +#endif // __IReferenceClock_INTERFACE_DEFINED__ + +#ifndef IReferenceClock_QueryInterface + +#define IReferenceClock_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IReferenceClock_AddRef(p) IUnknown_AddRef(p) +#define IReferenceClock_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IReferenceClock_GetTime(p,a) (p)->lpVtbl->GetTime(p,a) +#define IReferenceClock_AdviseTime(p,a,b,c,d) (p)->lpVtbl->AdviseTime(p,a,b,c,d) +#define IReferenceClock_AdvisePeriodic(p,a,b,c,d) (p)->lpVtbl->AdvisePeriodic(p,a,b,c,d) +#define IReferenceClock_Unadvise(p,a) (p)->lpVtbl->Unadvise(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IReferenceClock_GetTime(p,a) (p)->GetTime(a) +#define IReferenceClock_AdviseTime(p,a,b,c,d) (p)->AdviseTime(a,b,c,d) +#define IReferenceClock_AdvisePeriodic(p,a,b,c,d) (p)->AdvisePeriodic(a,b,c,d) +#define IReferenceClock_Unadvise(p,a) (p)->Unadvise(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // IReferenceClock_QueryInterface + +// +// IDirectSound +// + +DEFINE_GUID(IID_IDirectSound, 0x279AFA83, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); + +#undef INTERFACE +#define INTERFACE IDirectSound + +DECLARE_INTERFACE_(IDirectSound, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSound methods + STDMETHOD(CreateSoundBuffer) (THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(GetCaps) (THIS_ LPDSCAPS pDSCaps) PURE; + STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate) PURE; + STDMETHOD(SetCooperativeLevel) (THIS_ HWND hwnd, DWORD dwLevel) PURE; + STDMETHOD(Compact) (THIS) PURE; + STDMETHOD(GetSpeakerConfig) (THIS_ LPDWORD pdwSpeakerConfig) PURE; + STDMETHOD(SetSpeakerConfig) (THIS_ DWORD dwSpeakerConfig) PURE; + STDMETHOD(Initialize) (THIS_ LPCGUID pcGuidDevice) PURE; +}; + +#define IDirectSound_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSound_AddRef(p) IUnknown_AddRef(p) +#define IDirectSound_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->lpVtbl->CreateSoundBuffer(p,a,b,c) +#define IDirectSound_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->lpVtbl->DuplicateSoundBuffer(p,a,b) +#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->lpVtbl->SetCooperativeLevel(p,a,b) +#define IDirectSound_Compact(p) (p)->lpVtbl->Compact(p) +#define IDirectSound_GetSpeakerConfig(p,a) (p)->lpVtbl->GetSpeakerConfig(p,a) +#define IDirectSound_SetSpeakerConfig(p,b) (p)->lpVtbl->SetSpeakerConfig(p,b) +#define IDirectSound_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound_CreateSoundBuffer(p,a,b,c) (p)->CreateSoundBuffer(a,b,c) +#define IDirectSound_GetCaps(p,a) (p)->GetCaps(a) +#define IDirectSound_DuplicateSoundBuffer(p,a,b) (p)->DuplicateSoundBuffer(a,b) +#define IDirectSound_SetCooperativeLevel(p,a,b) (p)->SetCooperativeLevel(a,b) +#define IDirectSound_Compact(p) (p)->Compact() +#define IDirectSound_GetSpeakerConfig(p,a) (p)->GetSpeakerConfig(a) +#define IDirectSound_SetSpeakerConfig(p,b) (p)->SetSpeakerConfig(b) +#define IDirectSound_Initialize(p,a) (p)->Initialize(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#if DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSound8 +// + +DEFINE_GUID(IID_IDirectSound8, 0xC50A7E93, 0xF395, 0x4834, 0x9E, 0xF6, 0x7F, 0xA9, 0x9D, 0xE5, 0x09, 0x66); + +#undef INTERFACE +#define INTERFACE IDirectSound8 + +DECLARE_INTERFACE_(IDirectSound8, IDirectSound) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSound methods + STDMETHOD(CreateSoundBuffer) (THIS_ LPCDSBUFFERDESC pcDSBufferDesc, LPDIRECTSOUNDBUFFER *ppDSBuffer, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(GetCaps) (THIS_ LPDSCAPS pDSCaps) PURE; + STDMETHOD(DuplicateSoundBuffer) (THIS_ LPDIRECTSOUNDBUFFER pDSBufferOriginal, LPDIRECTSOUNDBUFFER *ppDSBufferDuplicate) PURE; + STDMETHOD(SetCooperativeLevel) (THIS_ HWND hwnd, DWORD dwLevel) PURE; + STDMETHOD(Compact) (THIS) PURE; + STDMETHOD(GetSpeakerConfig) (THIS_ LPDWORD pdwSpeakerConfig) PURE; + STDMETHOD(SetSpeakerConfig) (THIS_ DWORD dwSpeakerConfig) PURE; + STDMETHOD(Initialize) (THIS_ LPCGUID pcGuidDevice) PURE; + + // IDirectSound8 methods + STDMETHOD(VerifyCertification) (THIS_ LPDWORD pdwCertified) PURE; +}; + +#define IDirectSound8_QueryInterface(p,a,b) IDirectSound_QueryInterface(p,a,b) +#define IDirectSound8_AddRef(p) IDirectSound_AddRef(p) +#define IDirectSound8_Release(p) IDirectSound_Release(p) +#define IDirectSound8_CreateSoundBuffer(p,a,b,c) IDirectSound_CreateSoundBuffer(p,a,b,c) +#define IDirectSound8_GetCaps(p,a) IDirectSound_GetCaps(p,a) +#define IDirectSound8_DuplicateSoundBuffer(p,a,b) IDirectSound_DuplicateSoundBuffer(p,a,b) +#define IDirectSound8_SetCooperativeLevel(p,a,b) IDirectSound_SetCooperativeLevel(p,a,b) +#define IDirectSound8_Compact(p) IDirectSound_Compact(p) +#define IDirectSound8_GetSpeakerConfig(p,a) IDirectSound_GetSpeakerConfig(p,a) +#define IDirectSound8_SetSpeakerConfig(p,a) IDirectSound_SetSpeakerConfig(p,a) +#define IDirectSound8_Initialize(p,a) IDirectSound_Initialize(p,a) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound8_VerifyCertification(p,a) (p)->lpVtbl->VerifyCertification(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound8_VerifyCertification(p,a) (p)->VerifyCertification(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSoundBuffer +// + +DEFINE_GUID(IID_IDirectSoundBuffer, 0x279AFA85, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); + +#undef INTERFACE +#define INTERFACE IDirectSoundBuffer + +DECLARE_INTERFACE_(IDirectSoundBuffer, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundBuffer methods + STDMETHOD(GetCaps) (THIS_ LPDSBCAPS pDSBufferCaps) PURE; + STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor) PURE; + STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; + STDMETHOD(GetVolume) (THIS_ LPLONG plVolume) PURE; + STDMETHOD(GetPan) (THIS_ LPLONG plPan) PURE; + STDMETHOD(GetFrequency) (THIS_ LPDWORD pdwFrequency) PURE; + STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; + STDMETHOD(Initialize) (THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc) PURE; + STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, + LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; + STDMETHOD(Play) (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE; + STDMETHOD(SetCurrentPosition) (THIS_ DWORD dwNewPosition) PURE; + STDMETHOD(SetFormat) (THIS_ LPCWAVEFORMATEX pcfxFormat) PURE; + STDMETHOD(SetVolume) (THIS_ LONG lVolume) PURE; + STDMETHOD(SetPan) (THIS_ LONG lPan) PURE; + STDMETHOD(SetFrequency) (THIS_ DWORD dwFrequency) PURE; + STDMETHOD(Stop) (THIS) PURE; + STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; + STDMETHOD(Restore) (THIS) PURE; +}; + +#define IDirectSoundBuffer_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundBuffer_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundBuffer_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundBuffer_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) +#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) +#define IDirectSoundBuffer_GetVolume(p,a) (p)->lpVtbl->GetVolume(p,a) +#define IDirectSoundBuffer_GetPan(p,a) (p)->lpVtbl->GetPan(p,a) +#define IDirectSoundBuffer_GetFrequency(p,a) (p)->lpVtbl->GetFrequency(p,a) +#define IDirectSoundBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) +#define IDirectSoundBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) +#define IDirectSoundBuffer_Play(p,a,b,c) (p)->lpVtbl->Play(p,a,b,c) +#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->lpVtbl->SetCurrentPosition(p,a) +#define IDirectSoundBuffer_SetFormat(p,a) (p)->lpVtbl->SetFormat(p,a) +#define IDirectSoundBuffer_SetVolume(p,a) (p)->lpVtbl->SetVolume(p,a) +#define IDirectSoundBuffer_SetPan(p,a) (p)->lpVtbl->SetPan(p,a) +#define IDirectSoundBuffer_SetFrequency(p,a) (p)->lpVtbl->SetFrequency(p,a) +#define IDirectSoundBuffer_Stop(p) (p)->lpVtbl->Stop(p) +#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) +#define IDirectSoundBuffer_Restore(p) (p)->lpVtbl->Restore(p) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundBuffer_GetCaps(p,a) (p)->GetCaps(a) +#define IDirectSoundBuffer_GetCurrentPosition(p,a,b) (p)->GetCurrentPosition(a,b) +#define IDirectSoundBuffer_GetFormat(p,a,b,c) (p)->GetFormat(a,b,c) +#define IDirectSoundBuffer_GetVolume(p,a) (p)->GetVolume(a) +#define IDirectSoundBuffer_GetPan(p,a) (p)->GetPan(a) +#define IDirectSoundBuffer_GetFrequency(p,a) (p)->GetFrequency(a) +#define IDirectSoundBuffer_GetStatus(p,a) (p)->GetStatus(a) +#define IDirectSoundBuffer_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) +#define IDirectSoundBuffer_Play(p,a,b,c) (p)->Play(a,b,c) +#define IDirectSoundBuffer_SetCurrentPosition(p,a) (p)->SetCurrentPosition(a) +#define IDirectSoundBuffer_SetFormat(p,a) (p)->SetFormat(a) +#define IDirectSoundBuffer_SetVolume(p,a) (p)->SetVolume(a) +#define IDirectSoundBuffer_SetPan(p,a) (p)->SetPan(a) +#define IDirectSoundBuffer_SetFrequency(p,a) (p)->SetFrequency(a) +#define IDirectSoundBuffer_Stop(p) (p)->Stop() +#define IDirectSoundBuffer_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) +#define IDirectSoundBuffer_Restore(p) (p)->Restore() +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#if DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSoundBuffer8 +// + +DEFINE_GUID(IID_IDirectSoundBuffer8, 0x6825a449, 0x7524, 0x4d82, 0x92, 0x0f, 0x50, 0xe3, 0x6a, 0xb3, 0xab, 0x1e); + +#undef INTERFACE +#define INTERFACE IDirectSoundBuffer8 + +DECLARE_INTERFACE_(IDirectSoundBuffer8, IDirectSoundBuffer) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundBuffer methods + STDMETHOD(GetCaps) (THIS_ LPDSBCAPS pDSBufferCaps) PURE; + STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCurrentPlayCursor, LPDWORD pdwCurrentWriteCursor) PURE; + STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; + STDMETHOD(GetVolume) (THIS_ LPLONG plVolume) PURE; + STDMETHOD(GetPan) (THIS_ LPLONG plPan) PURE; + STDMETHOD(GetFrequency) (THIS_ LPDWORD pdwFrequency) PURE; + STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; + STDMETHOD(Initialize) (THIS_ LPDIRECTSOUND pDirectSound, LPCDSBUFFERDESC pcDSBufferDesc) PURE; + STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, + LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; + STDMETHOD(Play) (THIS_ DWORD dwReserved1, DWORD dwPriority, DWORD dwFlags) PURE; + STDMETHOD(SetCurrentPosition) (THIS_ DWORD dwNewPosition) PURE; + STDMETHOD(SetFormat) (THIS_ LPCWAVEFORMATEX pcfxFormat) PURE; + STDMETHOD(SetVolume) (THIS_ LONG lVolume) PURE; + STDMETHOD(SetPan) (THIS_ LONG lPan) PURE; + STDMETHOD(SetFrequency) (THIS_ DWORD dwFrequency) PURE; + STDMETHOD(Stop) (THIS) PURE; + STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; + STDMETHOD(Restore) (THIS) PURE; + + // IDirectSoundBuffer8 methods + STDMETHOD(SetFX) (THIS_ DWORD dwEffectsCount, LPDSEFFECTDESC pDSFXDesc, LPDWORD pdwResultCodes) PURE; + STDMETHOD(AcquireResources) (THIS_ DWORD dwFlags, DWORD dwEffectsCount, LPDWORD pdwResultCodes) PURE; + STDMETHOD(GetObjectInPath) (THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE; +}; + +// Special GUID meaning "select all objects" for use in GetObjectInPath() +DEFINE_GUID(GUID_All_Objects, 0xaa114de5, 0xc262, 0x4169, 0xa1, 0xc8, 0x23, 0xd6, 0x98, 0xcc, 0x73, 0xb5); + +#define IDirectSoundBuffer8_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundBuffer8_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundBuffer8_Release(p) IUnknown_Release(p) + +#define IDirectSoundBuffer8_GetCaps(p,a) IDirectSoundBuffer_GetCaps(p,a) +#define IDirectSoundBuffer8_GetCurrentPosition(p,a,b) IDirectSoundBuffer_GetCurrentPosition(p,a,b) +#define IDirectSoundBuffer8_GetFormat(p,a,b,c) IDirectSoundBuffer_GetFormat(p,a,b,c) +#define IDirectSoundBuffer8_GetVolume(p,a) IDirectSoundBuffer_GetVolume(p,a) +#define IDirectSoundBuffer8_GetPan(p,a) IDirectSoundBuffer_GetPan(p,a) +#define IDirectSoundBuffer8_GetFrequency(p,a) IDirectSoundBuffer_GetFrequency(p,a) +#define IDirectSoundBuffer8_GetStatus(p,a) IDirectSoundBuffer_GetStatus(p,a) +#define IDirectSoundBuffer8_Initialize(p,a,b) IDirectSoundBuffer_Initialize(p,a,b) +#define IDirectSoundBuffer8_Lock(p,a,b,c,d,e,f,g) IDirectSoundBuffer_Lock(p,a,b,c,d,e,f,g) +#define IDirectSoundBuffer8_Play(p,a,b,c) IDirectSoundBuffer_Play(p,a,b,c) +#define IDirectSoundBuffer8_SetCurrentPosition(p,a) IDirectSoundBuffer_SetCurrentPosition(p,a) +#define IDirectSoundBuffer8_SetFormat(p,a) IDirectSoundBuffer_SetFormat(p,a) +#define IDirectSoundBuffer8_SetVolume(p,a) IDirectSoundBuffer_SetVolume(p,a) +#define IDirectSoundBuffer8_SetPan(p,a) IDirectSoundBuffer_SetPan(p,a) +#define IDirectSoundBuffer8_SetFrequency(p,a) IDirectSoundBuffer_SetFrequency(p,a) +#define IDirectSoundBuffer8_Stop(p) IDirectSoundBuffer_Stop(p) +#define IDirectSoundBuffer8_Unlock(p,a,b,c,d) IDirectSoundBuffer_Unlock(p,a,b,c,d) +#define IDirectSoundBuffer8_Restore(p) IDirectSoundBuffer_Restore(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundBuffer8_SetFX(p,a,b,c) (p)->lpVtbl->SetFX(p,a,b,c) +#define IDirectSoundBuffer8_AcquireResources(p,a,b,c) (p)->lpVtbl->AcquireResources(p,a,b,c) +#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d) (p)->lpVtbl->GetObjectInPath(p,a,b,c,d) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundBuffer8_SetFX(p,a,b,c) (p)->SetFX(a,b,c) +#define IDirectSoundBuffer8_AcquireResources(p,a,b,c) (p)->AcquireResources(a,b,c) +#define IDirectSoundBuffer8_GetObjectInPath(p,a,b,c,d) (p)->GetObjectInPath(a,b,c,d) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSound3DListener +// + +DEFINE_GUID(IID_IDirectSound3DListener, 0x279AFA84, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); + +#undef INTERFACE +#define INTERFACE IDirectSound3DListener + +DECLARE_INTERFACE_(IDirectSound3DListener, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSound3DListener methods + STDMETHOD(GetAllParameters) (THIS_ LPDS3DLISTENER pListener) PURE; + STDMETHOD(GetDistanceFactor) (THIS_ D3DVALUE* pflDistanceFactor) PURE; + STDMETHOD(GetDopplerFactor) (THIS_ D3DVALUE* pflDopplerFactor) PURE; + STDMETHOD(GetOrientation) (THIS_ D3DVECTOR* pvOrientFront, D3DVECTOR* pvOrientTop) PURE; + STDMETHOD(GetPosition) (THIS_ D3DVECTOR* pvPosition) PURE; + STDMETHOD(GetRolloffFactor) (THIS_ D3DVALUE* pflRolloffFactor) PURE; + STDMETHOD(GetVelocity) (THIS_ D3DVECTOR* pvVelocity) PURE; + STDMETHOD(SetAllParameters) (THIS_ LPCDS3DLISTENER pcListener, DWORD dwApply) PURE; + STDMETHOD(SetDistanceFactor) (THIS_ D3DVALUE flDistanceFactor, DWORD dwApply) PURE; + STDMETHOD(SetDopplerFactor) (THIS_ D3DVALUE flDopplerFactor, DWORD dwApply) PURE; + STDMETHOD(SetOrientation) (THIS_ D3DVALUE xFront, D3DVALUE yFront, D3DVALUE zFront, + D3DVALUE xTop, D3DVALUE yTop, D3DVALUE zTop, DWORD dwApply) PURE; + STDMETHOD(SetPosition) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; + STDMETHOD(SetRolloffFactor) (THIS_ D3DVALUE flRolloffFactor, DWORD dwApply) PURE; + STDMETHOD(SetVelocity) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; + STDMETHOD(CommitDeferredSettings) (THIS) PURE; +}; + +#define IDirectSound3DListener_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSound3DListener_AddRef(p) IUnknown_AddRef(p) +#define IDirectSound3DListener_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound3DListener_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#define IDirectSound3DListener_GetDistanceFactor(p,a) (p)->lpVtbl->GetDistanceFactor(p,a) +#define IDirectSound3DListener_GetDopplerFactor(p,a) (p)->lpVtbl->GetDopplerFactor(p,a) +#define IDirectSound3DListener_GetOrientation(p,a,b) (p)->lpVtbl->GetOrientation(p,a,b) +#define IDirectSound3DListener_GetPosition(p,a) (p)->lpVtbl->GetPosition(p,a) +#define IDirectSound3DListener_GetRolloffFactor(p,a) (p)->lpVtbl->GetRolloffFactor(p,a) +#define IDirectSound3DListener_GetVelocity(p,a) (p)->lpVtbl->GetVelocity(p,a) +#define IDirectSound3DListener_SetAllParameters(p,a,b) (p)->lpVtbl->SetAllParameters(p,a,b) +#define IDirectSound3DListener_SetDistanceFactor(p,a,b) (p)->lpVtbl->SetDistanceFactor(p,a,b) +#define IDirectSound3DListener_SetDopplerFactor(p,a,b) (p)->lpVtbl->SetDopplerFactor(p,a,b) +#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g) (p)->lpVtbl->SetOrientation(p,a,b,c,d,e,f,g) +#define IDirectSound3DListener_SetPosition(p,a,b,c,d) (p)->lpVtbl->SetPosition(p,a,b,c,d) +#define IDirectSound3DListener_SetRolloffFactor(p,a,b) (p)->lpVtbl->SetRolloffFactor(p,a,b) +#define IDirectSound3DListener_SetVelocity(p,a,b,c,d) (p)->lpVtbl->SetVelocity(p,a,b,c,d) +#define IDirectSound3DListener_CommitDeferredSettings(p) (p)->lpVtbl->CommitDeferredSettings(p) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound3DListener_GetAllParameters(p,a) (p)->GetAllParameters(a) +#define IDirectSound3DListener_GetDistanceFactor(p,a) (p)->GetDistanceFactor(a) +#define IDirectSound3DListener_GetDopplerFactor(p,a) (p)->GetDopplerFactor(a) +#define IDirectSound3DListener_GetOrientation(p,a,b) (p)->GetOrientation(a,b) +#define IDirectSound3DListener_GetPosition(p,a) (p)->GetPosition(a) +#define IDirectSound3DListener_GetRolloffFactor(p,a) (p)->GetRolloffFactor(a) +#define IDirectSound3DListener_GetVelocity(p,a) (p)->GetVelocity(a) +#define IDirectSound3DListener_SetAllParameters(p,a,b) (p)->SetAllParameters(a,b) +#define IDirectSound3DListener_SetDistanceFactor(p,a,b) (p)->SetDistanceFactor(a,b) +#define IDirectSound3DListener_SetDopplerFactor(p,a,b) (p)->SetDopplerFactor(a,b) +#define IDirectSound3DListener_SetOrientation(p,a,b,c,d,e,f,g) (p)->SetOrientation(a,b,c,d,e,f,g) +#define IDirectSound3DListener_SetPosition(p,a,b,c,d) (p)->SetPosition(a,b,c,d) +#define IDirectSound3DListener_SetRolloffFactor(p,a,b) (p)->SetRolloffFactor(a,b) +#define IDirectSound3DListener_SetVelocity(p,a,b,c,d) (p)->SetVelocity(a,b,c,d) +#define IDirectSound3DListener_CommitDeferredSettings(p) (p)->CommitDeferredSettings() +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSound3DBuffer +// + +DEFINE_GUID(IID_IDirectSound3DBuffer, 0x279AFA86, 0x4981, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60); + +#undef INTERFACE +#define INTERFACE IDirectSound3DBuffer + +DECLARE_INTERFACE_(IDirectSound3DBuffer, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSound3DBuffer methods + STDMETHOD(GetAllParameters) (THIS_ LPDS3DBUFFER pDs3dBuffer) PURE; + STDMETHOD(GetConeAngles) (THIS_ LPDWORD pdwInsideConeAngle, LPDWORD pdwOutsideConeAngle) PURE; + STDMETHOD(GetConeOrientation) (THIS_ D3DVECTOR* pvOrientation) PURE; + STDMETHOD(GetConeOutsideVolume) (THIS_ LPLONG plConeOutsideVolume) PURE; + STDMETHOD(GetMaxDistance) (THIS_ D3DVALUE* pflMaxDistance) PURE; + STDMETHOD(GetMinDistance) (THIS_ D3DVALUE* pflMinDistance) PURE; + STDMETHOD(GetMode) (THIS_ LPDWORD pdwMode) PURE; + STDMETHOD(GetPosition) (THIS_ D3DVECTOR* pvPosition) PURE; + STDMETHOD(GetVelocity) (THIS_ D3DVECTOR* pvVelocity) PURE; + STDMETHOD(SetAllParameters) (THIS_ LPCDS3DBUFFER pcDs3dBuffer, DWORD dwApply) PURE; + STDMETHOD(SetConeAngles) (THIS_ DWORD dwInsideConeAngle, DWORD dwOutsideConeAngle, DWORD dwApply) PURE; + STDMETHOD(SetConeOrientation) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; + STDMETHOD(SetConeOutsideVolume) (THIS_ LONG lConeOutsideVolume, DWORD dwApply) PURE; + STDMETHOD(SetMaxDistance) (THIS_ D3DVALUE flMaxDistance, DWORD dwApply) PURE; + STDMETHOD(SetMinDistance) (THIS_ D3DVALUE flMinDistance, DWORD dwApply) PURE; + STDMETHOD(SetMode) (THIS_ DWORD dwMode, DWORD dwApply) PURE; + STDMETHOD(SetPosition) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; + STDMETHOD(SetVelocity) (THIS_ D3DVALUE x, D3DVALUE y, D3DVALUE z, DWORD dwApply) PURE; +}; + +#define IDirectSound3DBuffer_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSound3DBuffer_AddRef(p) IUnknown_AddRef(p) +#define IDirectSound3DBuffer_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound3DBuffer_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#define IDirectSound3DBuffer_GetConeAngles(p,a,b) (p)->lpVtbl->GetConeAngles(p,a,b) +#define IDirectSound3DBuffer_GetConeOrientation(p,a) (p)->lpVtbl->GetConeOrientation(p,a) +#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a) (p)->lpVtbl->GetConeOutsideVolume(p,a) +#define IDirectSound3DBuffer_GetPosition(p,a) (p)->lpVtbl->GetPosition(p,a) +#define IDirectSound3DBuffer_GetMinDistance(p,a) (p)->lpVtbl->GetMinDistance(p,a) +#define IDirectSound3DBuffer_GetMaxDistance(p,a) (p)->lpVtbl->GetMaxDistance(p,a) +#define IDirectSound3DBuffer_GetMode(p,a) (p)->lpVtbl->GetMode(p,a) +#define IDirectSound3DBuffer_GetVelocity(p,a) (p)->lpVtbl->GetVelocity(p,a) +#define IDirectSound3DBuffer_SetAllParameters(p,a,b) (p)->lpVtbl->SetAllParameters(p,a,b) +#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c) (p)->lpVtbl->SetConeAngles(p,a,b,c) +#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d) (p)->lpVtbl->SetConeOrientation(p,a,b,c,d) +#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b) (p)->lpVtbl->SetConeOutsideVolume(p,a,b) +#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d) (p)->lpVtbl->SetPosition(p,a,b,c,d) +#define IDirectSound3DBuffer_SetMinDistance(p,a,b) (p)->lpVtbl->SetMinDistance(p,a,b) +#define IDirectSound3DBuffer_SetMaxDistance(p,a,b) (p)->lpVtbl->SetMaxDistance(p,a,b) +#define IDirectSound3DBuffer_SetMode(p,a,b) (p)->lpVtbl->SetMode(p,a,b) +#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d) (p)->lpVtbl->SetVelocity(p,a,b,c,d) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSound3DBuffer_GetAllParameters(p,a) (p)->GetAllParameters(a) +#define IDirectSound3DBuffer_GetConeAngles(p,a,b) (p)->GetConeAngles(a,b) +#define IDirectSound3DBuffer_GetConeOrientation(p,a) (p)->GetConeOrientation(a) +#define IDirectSound3DBuffer_GetConeOutsideVolume(p,a) (p)->GetConeOutsideVolume(a) +#define IDirectSound3DBuffer_GetPosition(p,a) (p)->GetPosition(a) +#define IDirectSound3DBuffer_GetMinDistance(p,a) (p)->GetMinDistance(a) +#define IDirectSound3DBuffer_GetMaxDistance(p,a) (p)->GetMaxDistance(a) +#define IDirectSound3DBuffer_GetMode(p,a) (p)->GetMode(a) +#define IDirectSound3DBuffer_GetVelocity(p,a) (p)->GetVelocity(a) +#define IDirectSound3DBuffer_SetAllParameters(p,a,b) (p)->SetAllParameters(a,b) +#define IDirectSound3DBuffer_SetConeAngles(p,a,b,c) (p)->SetConeAngles(a,b,c) +#define IDirectSound3DBuffer_SetConeOrientation(p,a,b,c,d) (p)->SetConeOrientation(a,b,c,d) +#define IDirectSound3DBuffer_SetConeOutsideVolume(p,a,b) (p)->SetConeOutsideVolume(a,b) +#define IDirectSound3DBuffer_SetPosition(p,a,b,c,d) (p)->SetPosition(a,b,c,d) +#define IDirectSound3DBuffer_SetMinDistance(p,a,b) (p)->SetMinDistance(a,b) +#define IDirectSound3DBuffer_SetMaxDistance(p,a,b) (p)->SetMaxDistance(a,b) +#define IDirectSound3DBuffer_SetMode(p,a,b) (p)->SetMode(a,b) +#define IDirectSound3DBuffer_SetVelocity(p,a,b,c,d) (p)->SetVelocity(a,b,c,d) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundCapture +// + +DEFINE_GUID(IID_IDirectSoundCapture, 0xb0210781, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); + +#undef INTERFACE +#define INTERFACE IDirectSoundCapture + +DECLARE_INTERFACE_(IDirectSoundCapture, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundCapture methods + STDMETHOD(CreateCaptureBuffer) (THIS_ LPCDSCBUFFERDESC pcDSCBufferDesc, LPDIRECTSOUNDCAPTUREBUFFER *ppDSCBuffer, LPUNKNOWN pUnkOuter) PURE; + STDMETHOD(GetCaps) (THIS_ LPDSCCAPS pDSCCaps) PURE; + STDMETHOD(Initialize) (THIS_ LPCGUID pcGuidDevice) PURE; +}; + +#define IDirectSoundCapture_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundCapture_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundCapture_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c) (p)->lpVtbl->CreateCaptureBuffer(p,a,b,c) +#define IDirectSoundCapture_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSoundCapture_Initialize(p,a) (p)->lpVtbl->Initialize(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCapture_CreateCaptureBuffer(p,a,b,c) (p)->CreateCaptureBuffer(a,b,c) +#define IDirectSoundCapture_GetCaps(p,a) (p)->GetCaps(a) +#define IDirectSoundCapture_Initialize(p,a) (p)->Initialize(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundCaptureBuffer +// + +DEFINE_GUID(IID_IDirectSoundCaptureBuffer, 0xb0210782, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); + +#undef INTERFACE +#define INTERFACE IDirectSoundCaptureBuffer + +DECLARE_INTERFACE_(IDirectSoundCaptureBuffer, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundCaptureBuffer methods + STDMETHOD(GetCaps) (THIS_ LPDSCBCAPS pDSCBCaps) PURE; + STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCapturePosition, LPDWORD pdwReadPosition) PURE; + STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; + STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; + STDMETHOD(Initialize) (THIS_ LPDIRECTSOUNDCAPTURE pDirectSoundCapture, LPCDSCBUFFERDESC pcDSCBufferDesc) PURE; + STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, + LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; + STDMETHOD(Start) (THIS_ DWORD dwFlags) PURE; + STDMETHOD(Stop) (THIS) PURE; + STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; +}; + +#define IDirectSoundCaptureBuffer_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundCaptureBuffer_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundCaptureBuffer_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureBuffer_GetCaps(p,a) (p)->lpVtbl->GetCaps(p,a) +#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b) (p)->lpVtbl->GetCurrentPosition(p,a,b) +#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c) (p)->lpVtbl->GetFormat(p,a,b,c) +#define IDirectSoundCaptureBuffer_GetStatus(p,a) (p)->lpVtbl->GetStatus(p,a) +#define IDirectSoundCaptureBuffer_Initialize(p,a,b) (p)->lpVtbl->Initialize(p,a,b) +#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g) (p)->lpVtbl->Lock(p,a,b,c,d,e,f,g) +#define IDirectSoundCaptureBuffer_Start(p,a) (p)->lpVtbl->Start(p,a) +#define IDirectSoundCaptureBuffer_Stop(p) (p)->lpVtbl->Stop(p) +#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) (p)->lpVtbl->Unlock(p,a,b,c,d) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureBuffer_GetCaps(p,a) (p)->GetCaps(a) +#define IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b) (p)->GetCurrentPosition(a,b) +#define IDirectSoundCaptureBuffer_GetFormat(p,a,b,c) (p)->GetFormat(a,b,c) +#define IDirectSoundCaptureBuffer_GetStatus(p,a) (p)->GetStatus(a) +#define IDirectSoundCaptureBuffer_Initialize(p,a,b) (p)->Initialize(a,b) +#define IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g) (p)->Lock(a,b,c,d,e,f,g) +#define IDirectSoundCaptureBuffer_Start(p,a) (p)->Start(a) +#define IDirectSoundCaptureBuffer_Stop(p) (p)->Stop() +#define IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) (p)->Unlock(a,b,c,d) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + +#if DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSoundCaptureBuffer8 +// + +DEFINE_GUID(IID_IDirectSoundCaptureBuffer8, 0x990df4, 0xdbb, 0x4872, 0x83, 0x3e, 0x6d, 0x30, 0x3e, 0x80, 0xae, 0xb6); + +#undef INTERFACE +#define INTERFACE IDirectSoundCaptureBuffer8 + +DECLARE_INTERFACE_(IDirectSoundCaptureBuffer8, IDirectSoundCaptureBuffer) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundCaptureBuffer methods + STDMETHOD(GetCaps) (THIS_ LPDSCBCAPS pDSCBCaps) PURE; + STDMETHOD(GetCurrentPosition) (THIS_ LPDWORD pdwCapturePosition, LPDWORD pdwReadPosition) PURE; + STDMETHOD(GetFormat) (THIS_ LPWAVEFORMATEX pwfxFormat, DWORD dwSizeAllocated, LPDWORD pdwSizeWritten) PURE; + STDMETHOD(GetStatus) (THIS_ LPDWORD pdwStatus) PURE; + STDMETHOD(Initialize) (THIS_ LPDIRECTSOUNDCAPTURE pDirectSoundCapture, LPCDSCBUFFERDESC pcDSCBufferDesc) PURE; + STDMETHOD(Lock) (THIS_ DWORD dwOffset, DWORD dwBytes, LPVOID *ppvAudioPtr1, LPDWORD pdwAudioBytes1, + LPVOID *ppvAudioPtr2, LPDWORD pdwAudioBytes2, DWORD dwFlags) PURE; + STDMETHOD(Start) (THIS_ DWORD dwFlags) PURE; + STDMETHOD(Stop) (THIS) PURE; + STDMETHOD(Unlock) (THIS_ LPVOID pvAudioPtr1, DWORD dwAudioBytes1, LPVOID pvAudioPtr2, DWORD dwAudioBytes2) PURE; + + // IDirectSoundCaptureBuffer8 methods + STDMETHOD(GetObjectInPath) (THIS_ REFGUID rguidObject, DWORD dwIndex, REFGUID rguidInterface, LPVOID *ppObject) PURE; + STDMETHOD(GetFXStatus) (DWORD dwFXCount, LPDWORD pdwFXStatus) PURE; +}; + +#define IDirectSoundCaptureBuffer8_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundCaptureBuffer8_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundCaptureBuffer8_Release(p) IUnknown_Release(p) + +#define IDirectSoundCaptureBuffer8_GetCaps(p,a) IDirectSoundCaptureBuffer_GetCaps(p,a) +#define IDirectSoundCaptureBuffer8_GetCurrentPosition(p,a,b) IDirectSoundCaptureBuffer_GetCurrentPosition(p,a,b) +#define IDirectSoundCaptureBuffer8_GetFormat(p,a,b,c) IDirectSoundCaptureBuffer_GetFormat(p,a,b,c) +#define IDirectSoundCaptureBuffer8_GetStatus(p,a) IDirectSoundCaptureBuffer_GetStatus(p,a) +#define IDirectSoundCaptureBuffer8_Initialize(p,a,b) IDirectSoundCaptureBuffer_Initialize(p,a,b) +#define IDirectSoundCaptureBuffer8_Lock(p,a,b,c,d,e,f,g) IDirectSoundCaptureBuffer_Lock(p,a,b,c,d,e,f,g) +#define IDirectSoundCaptureBuffer8_Start(p,a) IDirectSoundCaptureBuffer_Start(p,a) +#define IDirectSoundCaptureBuffer8_Stop(p) IDirectSoundCaptureBuffer_Stop(p)) +#define IDirectSoundCaptureBuffer8_Unlock(p,a,b,c,d) IDirectSoundCaptureBuffer_Unlock(p,a,b,c,d) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d) (p)->lpVtbl->GetObjectInPath(p,a,b,c,d) +#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b) (p)->lpVtbl->GetFXStatus(p,a,b) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureBuffer8_GetObjectInPath(p,a,b,c,d) (p)->GetObjectInPath(a,b,c,d) +#define IDirectSoundCaptureBuffer8_GetFXStatus(p,a,b) (p)->GetFXStatus(a,b) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSoundNotify +// + +DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); + +#undef INTERFACE +#define INTERFACE IDirectSoundNotify + +DECLARE_INTERFACE_(IDirectSoundNotify, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundNotify methods + STDMETHOD(SetNotificationPositions) (THIS_ DWORD dwPositionNotifies, LPCDSBPOSITIONNOTIFY pcPositionNotifies) PURE; +}; + +#define IDirectSoundNotify_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundNotify_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundNotify_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundNotify_SetNotificationPositions(p,a,b) (p)->lpVtbl->SetNotificationPositions(p,a,b) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundNotify_SetNotificationPositions(p,a,b) (p)->SetNotificationPositions(a,b) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IKsPropertySet +// + +#ifndef _IKsPropertySet_ +#define _IKsPropertySet_ + +#ifdef __cplusplus +// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined +struct IKsPropertySet; +#endif // __cplusplus + +typedef struct IKsPropertySet *LPKSPROPERTYSET; + +#define KSPROPERTY_SUPPORT_GET 0x00000001 +#define KSPROPERTY_SUPPORT_SET 0x00000002 + +DEFINE_GUID(IID_IKsPropertySet, 0x31efac30, 0x515c, 0x11d0, 0xa9, 0xaa, 0x00, 0xaa, 0x00, 0x61, 0xbe, 0x93); + +#undef INTERFACE +#define INTERFACE IKsPropertySet + +DECLARE_INTERFACE_(IKsPropertySet, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IKsPropertySet methods + STDMETHOD(Get) (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength, + LPVOID pPropertyData, ULONG ulDataLength, PULONG pulBytesReturned) PURE; + STDMETHOD(Set) (THIS_ REFGUID rguidPropSet, ULONG ulId, LPVOID pInstanceData, ULONG ulInstanceLength, + LPVOID pPropertyData, ULONG ulDataLength) PURE; + STDMETHOD(QuerySupport) (THIS_ REFGUID rguidPropSet, ULONG ulId, PULONG pulTypeSupport) PURE; +}; + +#define IKsPropertySet_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IKsPropertySet_AddRef(p) IUnknown_AddRef(p) +#define IKsPropertySet_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IKsPropertySet_Get(p,a,b,c,d,e,f,g) (p)->lpVtbl->Get(p,a,b,c,d,e,f,g) +#define IKsPropertySet_Set(p,a,b,c,d,e,f) (p)->lpVtbl->Set(p,a,b,c,d,e,f) +#define IKsPropertySet_QuerySupport(p,a,b,c) (p)->lpVtbl->QuerySupport(p,a,b,c) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IKsPropertySet_Get(p,a,b,c,d,e,f,g) (p)->Get(a,b,c,d,e,f,g) +#define IKsPropertySet_Set(p,a,b,c,d,e,f) (p)->Set(a,b,c,d,e,f) +#define IKsPropertySet_QuerySupport(p,a,b,c) (p)->QuerySupport(a,b,c) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // _IKsPropertySet_ + +#if DIRECTSOUND_VERSION >= 0x0800 + +// +// IDirectSoundFXGargle +// + +DEFINE_GUID(IID_IDirectSoundFXGargle, 0xd616f352, 0xd622, 0x11ce, 0xaa, 0xc5, 0x00, 0x20, 0xaf, 0x0b, 0x99, 0xa3); + +typedef struct _DSFXGargle +{ + DWORD dwRateHz; // Rate of modulation in hz + DWORD dwWaveShape; // DSFXGARGLE_WAVE_xxx +} DSFXGargle, *LPDSFXGargle; + +#define DSFXGARGLE_WAVE_TRIANGLE 0 +#define DSFXGARGLE_WAVE_SQUARE 1 + +typedef const DSFXGargle *LPCDSFXGargle; + +#define DSFXGARGLE_RATEHZ_MIN 1 +#define DSFXGARGLE_RATEHZ_MAX 1000 + +#undef INTERFACE +#define INTERFACE IDirectSoundFXGargle + +DECLARE_INTERFACE_(IDirectSoundFXGargle, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXGargle methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXGargle pcDsFxGargle) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXGargle pDsFxGargle) PURE; +}; + +#define IDirectSoundFXGargle_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXGargle_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXGargle_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXGargle_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXGargle_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXGargle_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXGargle_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXChorus +// + +DEFINE_GUID(IID_IDirectSoundFXChorus, 0x880842e3, 0x145f, 0x43e6, 0xa9, 0x34, 0xa7, 0x18, 0x06, 0xe5, 0x05, 0x47); + +typedef struct _DSFXChorus +{ + FLOAT fWetDryMix; + FLOAT fDepth; + FLOAT fFeedback; + FLOAT fFrequency; + LONG lWaveform; // LFO shape; DSFXCHORUS_WAVE_xxx + FLOAT fDelay; + LONG lPhase; +} DSFXChorus, *LPDSFXChorus; + +typedef const DSFXChorus *LPCDSFXChorus; + +#define DSFXCHORUS_WAVE_TRIANGLE 0 +#define DSFXCHORUS_WAVE_SIN 1 + +#define DSFXCHORUS_WETDRYMIX_MIN 0.0f +#define DSFXCHORUS_WETDRYMIX_MAX 100.0f +#define DSFXCHORUS_DEPTH_MIN 0.0f +#define DSFXCHORUS_DEPTH_MAX 100.0f +#define DSFXCHORUS_FEEDBACK_MIN -99.0f +#define DSFXCHORUS_FEEDBACK_MAX 99.0f +#define DSFXCHORUS_FREQUENCY_MIN 0.0f +#define DSFXCHORUS_FREQUENCY_MAX 10.0f +#define DSFXCHORUS_DELAY_MIN 0.0f +#define DSFXCHORUS_DELAY_MAX 20.0f +#define DSFXCHORUS_PHASE_MIN 0 +#define DSFXCHORUS_PHASE_MAX 4 + +#define DSFXCHORUS_PHASE_NEG_180 0 +#define DSFXCHORUS_PHASE_NEG_90 1 +#define DSFXCHORUS_PHASE_ZERO 2 +#define DSFXCHORUS_PHASE_90 3 +#define DSFXCHORUS_PHASE_180 4 + +#undef INTERFACE +#define INTERFACE IDirectSoundFXChorus + +DECLARE_INTERFACE_(IDirectSoundFXChorus, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXChorus methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXChorus pcDsFxChorus) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXChorus pDsFxChorus) PURE; +}; + +#define IDirectSoundFXChorus_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXChorus_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXChorus_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXChorus_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXChorus_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXChorus_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXChorus_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXFlanger +// + +DEFINE_GUID(IID_IDirectSoundFXFlanger, 0x903e9878, 0x2c92, 0x4072, 0x9b, 0x2c, 0xea, 0x68, 0xf5, 0x39, 0x67, 0x83); + +typedef struct _DSFXFlanger +{ + FLOAT fWetDryMix; + FLOAT fDepth; + FLOAT fFeedback; + FLOAT fFrequency; + LONG lWaveform; + FLOAT fDelay; + LONG lPhase; +} DSFXFlanger, *LPDSFXFlanger; + +typedef const DSFXFlanger *LPCDSFXFlanger; + +#define DSFXFLANGER_WAVE_TRIANGLE 0 +#define DSFXFLANGER_WAVE_SIN 1 + +#define DSFXFLANGER_WETDRYMIX_MIN 0.0f +#define DSFXFLANGER_WETDRYMIX_MAX 100.0f +#define DSFXFLANGER_FREQUENCY_MIN 0.0f +#define DSFXFLANGER_FREQUENCY_MAX 10.0f +#define DSFXFLANGER_DEPTH_MIN 0.0f +#define DSFXFLANGER_DEPTH_MAX 100.0f +#define DSFXFLANGER_PHASE_MIN 0 +#define DSFXFLANGER_PHASE_MAX 4 +#define DSFXFLANGER_FEEDBACK_MIN -99.0f +#define DSFXFLANGER_FEEDBACK_MAX 99.0f +#define DSFXFLANGER_DELAY_MIN 0.0f +#define DSFXFLANGER_DELAY_MAX 4.0f + +#define DSFXFLANGER_PHASE_NEG_180 0 +#define DSFXFLANGER_PHASE_NEG_90 1 +#define DSFXFLANGER_PHASE_ZERO 2 +#define DSFXFLANGER_PHASE_90 3 +#define DSFXFLANGER_PHASE_180 4 + +#undef INTERFACE +#define INTERFACE IDirectSoundFXFlanger + +DECLARE_INTERFACE_(IDirectSoundFXFlanger, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXFlanger methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXFlanger pcDsFxFlanger) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXFlanger pDsFxFlanger) PURE; +}; + +#define IDirectSoundFXFlanger_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXFlanger_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXFlanger_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXFlanger_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXFlanger_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXFlanger_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXFlanger_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXEcho +// + +DEFINE_GUID(IID_IDirectSoundFXEcho, 0x8bd28edf, 0x50db, 0x4e92, 0xa2, 0xbd, 0x44, 0x54, 0x88, 0xd1, 0xed, 0x42); + +typedef struct _DSFXEcho +{ + FLOAT fWetDryMix; + FLOAT fFeedback; + FLOAT fLeftDelay; + FLOAT fRightDelay; + LONG lPanDelay; +} DSFXEcho, *LPDSFXEcho; + +typedef const DSFXEcho *LPCDSFXEcho; + +#define DSFXECHO_WETDRYMIX_MIN 0.0f +#define DSFXECHO_WETDRYMIX_MAX 100.0f +#define DSFXECHO_FEEDBACK_MIN 0.0f +#define DSFXECHO_FEEDBACK_MAX 100.0f +#define DSFXECHO_LEFTDELAY_MIN 1.0f +#define DSFXECHO_LEFTDELAY_MAX 2000.0f +#define DSFXECHO_RIGHTDELAY_MIN 1.0f +#define DSFXECHO_RIGHTDELAY_MAX 2000.0f +#define DSFXECHO_PANDELAY_MIN 0 +#define DSFXECHO_PANDELAY_MAX 1 + +#undef INTERFACE +#define INTERFACE IDirectSoundFXEcho + +DECLARE_INTERFACE_(IDirectSoundFXEcho, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXEcho methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXEcho pcDsFxEcho) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXEcho pDsFxEcho) PURE; +}; + +#define IDirectSoundFXEcho_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXEcho_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXEcho_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXEcho_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXEcho_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXEcho_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXEcho_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXDistortion +// + +DEFINE_GUID(IID_IDirectSoundFXDistortion, 0x8ecf4326, 0x455f, 0x4d8b, 0xbd, 0xa9, 0x8d, 0x5d, 0x3e, 0x9e, 0x3e, 0x0b); + +typedef struct _DSFXDistortion +{ + FLOAT fGain; + FLOAT fEdge; + FLOAT fPostEQCenterFrequency; + FLOAT fPostEQBandwidth; + FLOAT fPreLowpassCutoff; +} DSFXDistortion, *LPDSFXDistortion; + +typedef const DSFXDistortion *LPCDSFXDistortion; + +#define DSFXDISTORTION_GAIN_MIN -60.0f +#define DSFXDISTORTION_GAIN_MAX 0.0f +#define DSFXDISTORTION_EDGE_MIN 0.0f +#define DSFXDISTORTION_EDGE_MAX 100.0f +#define DSFXDISTORTION_POSTEQCENTERFREQUENCY_MIN 100.0f +#define DSFXDISTORTION_POSTEQCENTERFREQUENCY_MAX 8000.0f +#define DSFXDISTORTION_POSTEQBANDWIDTH_MIN 100.0f +#define DSFXDISTORTION_POSTEQBANDWIDTH_MAX 8000.0f +#define DSFXDISTORTION_PRELOWPASSCUTOFF_MIN 100.0f +#define DSFXDISTORTION_PRELOWPASSCUTOFF_MAX 8000.0f + +#undef INTERFACE +#define INTERFACE IDirectSoundFXDistortion + +DECLARE_INTERFACE_(IDirectSoundFXDistortion, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXDistortion methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXDistortion pcDsFxDistortion) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXDistortion pDsFxDistortion) PURE; +}; + +#define IDirectSoundFXDistortion_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXDistortion_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXDistortion_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXDistortion_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXDistortion_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXDistortion_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXDistortion_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXCompressor +// + +DEFINE_GUID(IID_IDirectSoundFXCompressor, 0x4bbd1154, 0x62f6, 0x4e2c, 0xa1, 0x5c, 0xd3, 0xb6, 0xc4, 0x17, 0xf7, 0xa0); + +typedef struct _DSFXCompressor +{ + FLOAT fGain; + FLOAT fAttack; + FLOAT fRelease; + FLOAT fThreshold; + FLOAT fRatio; + FLOAT fPredelay; +} DSFXCompressor, *LPDSFXCompressor; + +typedef const DSFXCompressor *LPCDSFXCompressor; + +#define DSFXCOMPRESSOR_GAIN_MIN -60.0f +#define DSFXCOMPRESSOR_GAIN_MAX 60.0f +#define DSFXCOMPRESSOR_ATTACK_MIN 0.01f +#define DSFXCOMPRESSOR_ATTACK_MAX 500.0f +#define DSFXCOMPRESSOR_RELEASE_MIN 50.0f +#define DSFXCOMPRESSOR_RELEASE_MAX 3000.0f +#define DSFXCOMPRESSOR_THRESHOLD_MIN -60.0f +#define DSFXCOMPRESSOR_THRESHOLD_MAX 0.0f +#define DSFXCOMPRESSOR_RATIO_MIN 1.0f +#define DSFXCOMPRESSOR_RATIO_MAX 100.0f +#define DSFXCOMPRESSOR_PREDELAY_MIN 0.0f +#define DSFXCOMPRESSOR_PREDELAY_MAX 4.0f + +#undef INTERFACE +#define INTERFACE IDirectSoundFXCompressor + +DECLARE_INTERFACE_(IDirectSoundFXCompressor, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXCompressor methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXCompressor pcDsFxCompressor) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXCompressor pDsFxCompressor) PURE; +}; + +#define IDirectSoundFXCompressor_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXCompressor_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXCompressor_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXCompressor_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXCompressor_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXCompressor_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXCompressor_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundFXParamEq +// + +DEFINE_GUID(IID_IDirectSoundFXParamEq, 0xc03ca9fe, 0xfe90, 0x4204, 0x80, 0x78, 0x82, 0x33, 0x4c, 0xd1, 0x77, 0xda); + +typedef struct _DSFXParamEq +{ + FLOAT fCenter; + FLOAT fBandwidth; + FLOAT fGain; +} DSFXParamEq, *LPDSFXParamEq; + +typedef const DSFXParamEq *LPCDSFXParamEq; + +#define DSFXPARAMEQ_CENTER_MIN 80.0f +#define DSFXPARAMEQ_CENTER_MAX 16000.0f +#define DSFXPARAMEQ_BANDWIDTH_MIN 1.0f +#define DSFXPARAMEQ_BANDWIDTH_MAX 36.0f +#define DSFXPARAMEQ_GAIN_MIN -15.0f +#define DSFXPARAMEQ_GAIN_MAX 15.0f + +#undef INTERFACE +#define INTERFACE IDirectSoundFXParamEq + +DECLARE_INTERFACE_(IDirectSoundFXParamEq, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXParamEq methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXParamEq pcDsFxParamEq) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXParamEq pDsFxParamEq) PURE; +}; + +#define IDirectSoundFXParamEq_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXParamEq_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXParamEq_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXParamEq_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXParamEq_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXParamEq_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXParamEq_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + +// +// IDirectSoundFXI3DL2Reverb +// + +DEFINE_GUID(IID_IDirectSoundFXI3DL2Reverb, 0x4b166a6a, 0x0d66, 0x43f3, 0x80, 0xe3, 0xee, 0x62, 0x80, 0xde, 0xe1, 0xa4); + +typedef struct _DSFXI3DL2Reverb +{ + LONG lRoom; // [-10000, 0] default: -1000 mB + LONG lRoomHF; // [-10000, 0] default: 0 mB + FLOAT flRoomRolloffFactor; // [0.0, 10.0] default: 0.0 + FLOAT flDecayTime; // [0.1, 20.0] default: 1.49s + FLOAT flDecayHFRatio; // [0.1, 2.0] default: 0.83 + LONG lReflections; // [-10000, 1000] default: -2602 mB + FLOAT flReflectionsDelay; // [0.0, 0.3] default: 0.007 s + LONG lReverb; // [-10000, 2000] default: 200 mB + FLOAT flReverbDelay; // [0.0, 0.1] default: 0.011 s + FLOAT flDiffusion; // [0.0, 100.0] default: 100.0 % + FLOAT flDensity; // [0.0, 100.0] default: 100.0 % + FLOAT flHFReference; // [20.0, 20000.0] default: 5000.0 Hz +} DSFXI3DL2Reverb, *LPDSFXI3DL2Reverb; + +typedef const DSFXI3DL2Reverb *LPCDSFXI3DL2Reverb; + +#define DSFX_I3DL2REVERB_ROOM_MIN (-10000) +#define DSFX_I3DL2REVERB_ROOM_MAX 0 +#define DSFX_I3DL2REVERB_ROOM_DEFAULT (-1000) + +#define DSFX_I3DL2REVERB_ROOMHF_MIN (-10000) +#define DSFX_I3DL2REVERB_ROOMHF_MAX 0 +#define DSFX_I3DL2REVERB_ROOMHF_DEFAULT (-100) + +#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MIN 0.0f +#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_MAX 10.0f +#define DSFX_I3DL2REVERB_ROOMROLLOFFFACTOR_DEFAULT 0.0f + +#define DSFX_I3DL2REVERB_DECAYTIME_MIN 0.1f +#define DSFX_I3DL2REVERB_DECAYTIME_MAX 20.0f +#define DSFX_I3DL2REVERB_DECAYTIME_DEFAULT 1.49f + +#define DSFX_I3DL2REVERB_DECAYHFRATIO_MIN 0.1f +#define DSFX_I3DL2REVERB_DECAYHFRATIO_MAX 2.0f +#define DSFX_I3DL2REVERB_DECAYHFRATIO_DEFAULT 0.83f + +#define DSFX_I3DL2REVERB_REFLECTIONS_MIN (-10000) +#define DSFX_I3DL2REVERB_REFLECTIONS_MAX 1000 +#define DSFX_I3DL2REVERB_REFLECTIONS_DEFAULT (-2602) + +#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_MIN 0.0f +#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_MAX 0.3f +#define DSFX_I3DL2REVERB_REFLECTIONSDELAY_DEFAULT 0.007f + +#define DSFX_I3DL2REVERB_REVERB_MIN (-10000) +#define DSFX_I3DL2REVERB_REVERB_MAX 2000 +#define DSFX_I3DL2REVERB_REVERB_DEFAULT (200) + +#define DSFX_I3DL2REVERB_REVERBDELAY_MIN 0.0f +#define DSFX_I3DL2REVERB_REVERBDELAY_MAX 0.1f +#define DSFX_I3DL2REVERB_REVERBDELAY_DEFAULT 0.011f + +#define DSFX_I3DL2REVERB_DIFFUSION_MIN 0.0f +#define DSFX_I3DL2REVERB_DIFFUSION_MAX 100.0f +#define DSFX_I3DL2REVERB_DIFFUSION_DEFAULT 100.0f + +#define DSFX_I3DL2REVERB_DENSITY_MIN 0.0f +#define DSFX_I3DL2REVERB_DENSITY_MAX 100.0f +#define DSFX_I3DL2REVERB_DENSITY_DEFAULT 100.0f + +#define DSFX_I3DL2REVERB_HFREFERENCE_MIN 20.0f +#define DSFX_I3DL2REVERB_HFREFERENCE_MAX 20000.0f +#define DSFX_I3DL2REVERB_HFREFERENCE_DEFAULT 5000.0f + +#define DSFX_I3DL2REVERB_QUALITY_MIN 0 +#define DSFX_I3DL2REVERB_QUALITY_MAX 3 +#define DSFX_I3DL2REVERB_QUALITY_DEFAULT 2 + +#undef INTERFACE +#define INTERFACE IDirectSoundFXI3DL2Reverb + +DECLARE_INTERFACE_(IDirectSoundFXI3DL2Reverb, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXI3DL2Reverb methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXI3DL2Reverb pcDsFxI3DL2Reverb) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXI3DL2Reverb pDsFxI3DL2Reverb) PURE; + STDMETHOD(SetPreset) (THIS_ DWORD dwPreset) PURE; + STDMETHOD(GetPreset) (THIS_ LPDWORD pdwPreset) PURE; + STDMETHOD(SetQuality) (THIS_ LONG lQuality) PURE; + STDMETHOD(GetQuality) (THIS_ LONG *plQuality) PURE; +}; + +#define IDirectSoundFXI3DL2Reverb_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXI3DL2Reverb_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXI3DL2Reverb_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXI3DL2Reverb_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXI3DL2Reverb_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#define IDirectSoundFXI3DL2Reverb_SetPreset(p,a) (p)->lpVtbl->SetPreset(p,a) +#define IDirectSoundFXI3DL2Reverb_GetPreset(p,a) (p)->lpVtbl->GetPreset(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXI3DL2Reverb_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXI3DL2Reverb_GetAllParameters(p,a) (p)->GetAllParameters(a) +#define IDirectSoundFXI3DL2Reverb_SetPreset(p,a) (p)->SetPreset(a) +#define IDirectSoundFXI3DL2Reverb_GetPreset(p,a) (p)->GetPreset(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + +// +// IDirectSoundFXWavesReverb +// + +DEFINE_GUID(IID_IDirectSoundFXWavesReverb,0x46858c3a,0x0dc6,0x45e3,0xb7,0x60,0xd4,0xee,0xf1,0x6c,0xb3,0x25); + +typedef struct _DSFXWavesReverb +{ + FLOAT fInGain; // [-96.0,0.0] default: 0.0 dB + FLOAT fReverbMix; // [-96.0,0.0] default: 0.0 db + FLOAT fReverbTime; // [0.001,3000.0] default: 1000.0 ms + FLOAT fHighFreqRTRatio; // [0.001,0.999] default: 0.001 +} DSFXWavesReverb, *LPDSFXWavesReverb; + +typedef const DSFXWavesReverb *LPCDSFXWavesReverb; + +#define DSFX_WAVESREVERB_INGAIN_MIN -96.0f +#define DSFX_WAVESREVERB_INGAIN_MAX 0.0f +#define DSFX_WAVESREVERB_INGAIN_DEFAULT 0.0f +#define DSFX_WAVESREVERB_REVERBMIX_MIN -96.0f +#define DSFX_WAVESREVERB_REVERBMIX_MAX 0.0f +#define DSFX_WAVESREVERB_REVERBMIX_DEFAULT 0.0f +#define DSFX_WAVESREVERB_REVERBTIME_MIN 0.001f +#define DSFX_WAVESREVERB_REVERBTIME_MAX 3000.0f +#define DSFX_WAVESREVERB_REVERBTIME_DEFAULT 1000.0f +#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_MIN 0.001f +#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_MAX 0.999f +#define DSFX_WAVESREVERB_HIGHFREQRTRATIO_DEFAULT 0.001f + +#undef INTERFACE +#define INTERFACE IDirectSoundFXWavesReverb + +DECLARE_INTERFACE_(IDirectSoundFXWavesReverb, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFXWavesReverb methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSFXWavesReverb pcDsFxWavesReverb) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSFXWavesReverb pDsFxWavesReverb) PURE; +}; + +#define IDirectSoundFXWavesReverb_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFXWavesReverb_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFXWavesReverb_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXWavesReverb_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundFXWavesReverb_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFXWavesReverb_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundFXWavesReverb_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +// +// IDirectSoundCaptureFXAec +// + +DEFINE_GUID(IID_IDirectSoundCaptureFXAec, 0x174d3eb9, 0x6696, 0x4fac, 0xa4, 0x6c, 0xa0, 0xac, 0x7b, 0xc9, 0xe2, 0xf); + +typedef struct _DSCFXAec +{ + BOOL fEnable; + BOOL fReset; +} DSCFXAec, *LPDSCFXAec; + +typedef const DSCFXAec *LPCDSCFXAec; + +#undef INTERFACE +#define INTERFACE IDirectSoundCaptureFXAec + +DECLARE_INTERFACE_(IDirectSoundCaptureFXAec, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundCaptureFXAec methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSCFXAec pDscFxAec) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSCFXAec pDscFxAec) PURE; +}; + +#define IDirectSoundCaptureFXAec_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundCaptureFXAec_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundCaptureFXAec_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureFXAec_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundCaptureFXAec_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureFXAec_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundCaptureFXAec_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + +// +// IDirectSoundCaptureFXNoiseSuppress +// + +DEFINE_GUID(IID_IDirectSoundCaptureFXNoiseSuppress, 0xed311e41, 0xfbae, 0x4175, 0x96, 0x25, 0xcd, 0x8, 0x54, 0xf6, 0x93, 0xca); + +typedef struct _DSCFXNoiseSuppress +{ + BOOL fEnable; + BOOL fReset; +} DSCFXNoiseSuppress, *LPDSCFXNoiseSuppress; + +typedef const DSCFXNoiseSuppress *LPCDSCFXNoiseSuppress; + +#undef INTERFACE +#define INTERFACE IDirectSoundCaptureFXNoiseSuppress + +DECLARE_INTERFACE_(IDirectSoundCaptureFXNoiseSuppress, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundCaptureFXNoiseSuppress methods + STDMETHOD(SetAllParameters) (THIS_ LPCDSCFXNoiseSuppress pcDscFxNoiseSuppress) PURE; + STDMETHOD(GetAllParameters) (THIS_ LPDSCFXNoiseSuppress pDscFxNoiseSuppress) PURE; +}; + +#define IDirectSoundCaptureFXNoiseSuppress_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundCaptureFXNoiseSuppress_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundCaptureFXNoiseSuppress_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureFXNoiseSuppress_SetAllParameters(p,a) (p)->lpVtbl->SetAllParameters(p,a) +#define IDirectSoundCaptureFXNoiseSuppress_GetAllParameters(p,a) (p)->lpVtbl->GetAllParameters(p,a) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundCaptureFXNoiseSuppress_SetAllParameters(p,a) (p)->SetAllParameters(a) +#define IDirectSoundCaptureFXNoiseSuppress_GetAllParameters(p,a) (p)->GetAllParameters(a) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + + +// +// IDirectSoundFullDuplex +// + +#ifndef _IDirectSoundFullDuplex_ +#define _IDirectSoundFullDuplex_ + +#ifdef __cplusplus +// 'struct' not 'class' per the way DECLARE_INTERFACE_ is defined +struct IDirectSoundFullDuplex; +#endif // __cplusplus + +typedef struct IDirectSoundFullDuplex *LPDIRECTSOUNDFULLDUPLEX; + +DEFINE_GUID(IID_IDirectSoundFullDuplex, 0xedcb4c7a, 0xdaab, 0x4216, 0xa4, 0x2e, 0x6c, 0x50, 0x59, 0x6d, 0xdc, 0x1d); + +#undef INTERFACE +#define INTERFACE IDirectSoundFullDuplex + +DECLARE_INTERFACE_(IDirectSoundFullDuplex, IUnknown) +{ + // IUnknown methods + STDMETHOD(QueryInterface) (THIS_ REFIID, LPVOID *) PURE; + STDMETHOD_(ULONG,AddRef) (THIS) PURE; + STDMETHOD_(ULONG,Release) (THIS) PURE; + + // IDirectSoundFullDuplex methods + STDMETHOD(Initialize) (THIS_ LPCGUID pCaptureGuid, LPCGUID pRenderGuid, LPCDSCBUFFERDESC lpDscBufferDesc, LPCDSBUFFERDESC lpDsBufferDesc, HWND hWnd, DWORD dwLevel, LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8, LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8) PURE; +}; + +#define IDirectSoundFullDuplex_QueryInterface(p,a,b) IUnknown_QueryInterface(p,a,b) +#define IDirectSoundFullDuplex_AddRef(p) IUnknown_AddRef(p) +#define IDirectSoundFullDuplex_Release(p) IUnknown_Release(p) + +#if !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h) (p)->lpVtbl->Initialize(p,a,b,c,d,e,f,g,h) +#else // !defined(__cplusplus) || defined(CINTERFACE) +#define IDirectSoundFullDuplex_Initialize(p,a,b,c,d,e,f,g,h) (p)->Initialize(a,b,c,d,e,f,g,h) +#endif // !defined(__cplusplus) || defined(CINTERFACE) + +#endif // _IDirectSoundFullDuplex_ + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +// +// Return Codes +// + +// The function completed successfully +#define DS_OK S_OK + +// The call succeeded, but we had to substitute the 3D algorithm +#define DS_NO_VIRTUALIZATION MAKE_HRESULT(0, _FACDS, 10) + +// The call succeeded, but not all of the optional effects were obtained. +#define DS_INCOMPLETE MAKE_HRESULT(0, _FACDS, 20) + +// The call failed because resources (such as a priority level) +// were already being used by another caller +#define DSERR_ALLOCATED MAKE_DSHRESULT(10) + +// The control (vol, pan, etc.) requested by the caller is not available +#define DSERR_CONTROLUNAVAIL MAKE_DSHRESULT(30) + +// An invalid parameter was passed to the returning function +#define DSERR_INVALIDPARAM E_INVALIDARG + +// This call is not valid for the current state of this object +#define DSERR_INVALIDCALL MAKE_DSHRESULT(50) + +// An undetermined error occurred inside the DirectSound subsystem +#define DSERR_GENERIC E_FAIL + +// The caller does not have the priority level required for the function to +// succeed +#define DSERR_PRIOLEVELNEEDED MAKE_DSHRESULT(70) + +// Not enough free memory is available to complete the operation +#define DSERR_OUTOFMEMORY E_OUTOFMEMORY + +// The specified WAVE format is not supported +#define DSERR_BADFORMAT MAKE_DSHRESULT(100) + +// The function called is not supported at this time +#define DSERR_UNSUPPORTED E_NOTIMPL + +// No sound driver is available for use +#define DSERR_NODRIVER MAKE_DSHRESULT(120) + +// This object is already initialized +#define DSERR_ALREADYINITIALIZED MAKE_DSHRESULT(130) + +// This object does not support aggregation +#define DSERR_NOAGGREGATION CLASS_E_NOAGGREGATION + +// The buffer memory has been lost, and must be restored +#define DSERR_BUFFERLOST MAKE_DSHRESULT(150) + +// Another app has a higher priority level, preventing this call from +// succeeding +#define DSERR_OTHERAPPHASPRIO MAKE_DSHRESULT(160) + +// This object has not been initialized +#define DSERR_UNINITIALIZED MAKE_DSHRESULT(170) + +// The requested COM interface is not available +#define DSERR_NOINTERFACE E_NOINTERFACE + +// Access is denied +#define DSERR_ACCESSDENIED E_ACCESSDENIED + +// Tried to create a DSBCAPS_CTRLFX buffer shorter than DSBSIZE_FX_MIN milliseconds +#define DSERR_BUFFERTOOSMALL MAKE_DSHRESULT(180) + +// Attempt to use DirectSound 8 functionality on an older DirectSound object +#define DSERR_DS8_REQUIRED MAKE_DSHRESULT(190) + +// A circular loop of send effects was detected +#define DSERR_SENDLOOP MAKE_DSHRESULT(200) + +// The GUID specified in an audiopath file does not match a valid MIXIN buffer +#define DSERR_BADSENDBUFFERGUID MAKE_DSHRESULT(210) + +// The object requested was not found (numerically equal to DMUS_E_NOT_FOUND) +#define DSERR_OBJECTNOTFOUND MAKE_DSHRESULT(4449) + +// +// Flags +// + +#define DSCAPS_PRIMARYMONO 0x00000001 +#define DSCAPS_PRIMARYSTEREO 0x00000002 +#define DSCAPS_PRIMARY8BIT 0x00000004 +#define DSCAPS_PRIMARY16BIT 0x00000008 +#define DSCAPS_CONTINUOUSRATE 0x00000010 +#define DSCAPS_EMULDRIVER 0x00000020 +#define DSCAPS_CERTIFIED 0x00000040 +#define DSCAPS_SECONDARYMONO 0x00000100 +#define DSCAPS_SECONDARYSTEREO 0x00000200 +#define DSCAPS_SECONDARY8BIT 0x00000400 +#define DSCAPS_SECONDARY16BIT 0x00000800 + +#define DSSCL_NORMAL 0x00000001 +#define DSSCL_PRIORITY 0x00000002 +#define DSSCL_EXCLUSIVE 0x00000003 +#define DSSCL_WRITEPRIMARY 0x00000004 + +#define DSSPEAKER_HEADPHONE 0x00000001 +#define DSSPEAKER_MONO 0x00000002 +#define DSSPEAKER_QUAD 0x00000003 +#define DSSPEAKER_STEREO 0x00000004 +#define DSSPEAKER_SURROUND 0x00000005 +#define DSSPEAKER_5POINT1 0x00000006 + +#define DSSPEAKER_GEOMETRY_MIN 0x00000005 // 5 degrees +#define DSSPEAKER_GEOMETRY_NARROW 0x0000000A // 10 degrees +#define DSSPEAKER_GEOMETRY_WIDE 0x00000014 // 20 degrees +#define DSSPEAKER_GEOMETRY_MAX 0x000000B4 // 180 degrees + +#define DSSPEAKER_COMBINED(c, g) ((DWORD)(((BYTE)(c)) | ((DWORD)((BYTE)(g))) << 16)) +#define DSSPEAKER_CONFIG(a) ((BYTE)(a)) +#define DSSPEAKER_GEOMETRY(a) ((BYTE)(((DWORD)(a) >> 16) & 0x00FF)) + +#define DSBCAPS_PRIMARYBUFFER 0x00000001 +#define DSBCAPS_STATIC 0x00000002 +#define DSBCAPS_LOCHARDWARE 0x00000004 +#define DSBCAPS_LOCSOFTWARE 0x00000008 +#define DSBCAPS_CTRL3D 0x00000010 +#define DSBCAPS_CTRLFREQUENCY 0x00000020 +#define DSBCAPS_CTRLPAN 0x00000040 +#define DSBCAPS_CTRLVOLUME 0x00000080 +#define DSBCAPS_CTRLPOSITIONNOTIFY 0x00000100 +#define DSBCAPS_CTRLFX 0x00000200 +#define DSBCAPS_STICKYFOCUS 0x00004000 +#define DSBCAPS_GLOBALFOCUS 0x00008000 +#define DSBCAPS_GETCURRENTPOSITION2 0x00010000 +#define DSBCAPS_MUTE3DATMAXDISTANCE 0x00020000 +#define DSBCAPS_LOCDEFER 0x00040000 + +#define DSBPLAY_LOOPING 0x00000001 +#define DSBPLAY_LOCHARDWARE 0x00000002 +#define DSBPLAY_LOCSOFTWARE 0x00000004 +#define DSBPLAY_TERMINATEBY_TIME 0x00000008 +#define DSBPLAY_TERMINATEBY_DISTANCE 0x000000010 +#define DSBPLAY_TERMINATEBY_PRIORITY 0x000000020 + +#define DSBSTATUS_PLAYING 0x00000001 +#define DSBSTATUS_BUFFERLOST 0x00000002 +#define DSBSTATUS_LOOPING 0x00000004 +#define DSBSTATUS_LOCHARDWARE 0x00000008 +#define DSBSTATUS_LOCSOFTWARE 0x00000010 +#define DSBSTATUS_TERMINATED 0x00000020 + +#define DSBLOCK_FROMWRITECURSOR 0x00000001 +#define DSBLOCK_ENTIREBUFFER 0x00000002 + +#define DSBFREQUENCY_MIN 100 +#define DSBFREQUENCY_MAX 100000 +#define DSBFREQUENCY_ORIGINAL 0 + +#define DSBPAN_LEFT -10000 +#define DSBPAN_CENTER 0 +#define DSBPAN_RIGHT 10000 + +#define DSBVOLUME_MIN -10000 +#define DSBVOLUME_MAX 0 + +#define DSBSIZE_MIN 4 +#define DSBSIZE_MAX 0x0FFFFFFF +#define DSBSIZE_FX_MIN 150 // NOTE: Milliseconds, not bytes + +#define DS3DMODE_NORMAL 0x00000000 +#define DS3DMODE_HEADRELATIVE 0x00000001 +#define DS3DMODE_DISABLE 0x00000002 + +#define DS3D_IMMEDIATE 0x00000000 +#define DS3D_DEFERRED 0x00000001 + +#define DS3D_MINDISTANCEFACTOR FLT_MIN +#define DS3D_MAXDISTANCEFACTOR FLT_MAX +#define DS3D_DEFAULTDISTANCEFACTOR 1.0f + +#define DS3D_MINROLLOFFFACTOR 0.0f +#define DS3D_MAXROLLOFFFACTOR 10.0f +#define DS3D_DEFAULTROLLOFFFACTOR 1.0f + +#define DS3D_MINDOPPLERFACTOR 0.0f +#define DS3D_MAXDOPPLERFACTOR 10.0f +#define DS3D_DEFAULTDOPPLERFACTOR 1.0f + +#define DS3D_DEFAULTMINDISTANCE 1.0f +#define DS3D_DEFAULTMAXDISTANCE 1000000000.0f + +#define DS3D_MINCONEANGLE 0 +#define DS3D_MAXCONEANGLE 360 +#define DS3D_DEFAULTCONEANGLE 360 + +#define DS3D_DEFAULTCONEOUTSIDEVOLUME DSBVOLUME_MAX + +// IDirectSoundCapture attributes + +#define DSCCAPS_EMULDRIVER DSCAPS_EMULDRIVER +#define DSCCAPS_CERTIFIED DSCAPS_CERTIFIED + +// IDirectSoundCaptureBuffer attributes + +#define DSCBCAPS_WAVEMAPPED 0x80000000 + +#if DIRECTSOUND_VERSION >= 0x0800 +#define DSCBCAPS_CTRLFX 0x00000200 +#endif + + +#define DSCBLOCK_ENTIREBUFFER 0x00000001 + +#define DSCBSTATUS_CAPTURING 0x00000001 +#define DSCBSTATUS_LOOPING 0x00000002 + +#define DSCBSTART_LOOPING 0x00000001 + +#define DSBPN_OFFSETSTOP 0xFFFFFFFF + +#define DS_CERTIFIED 0x00000000 +#define DS_UNCERTIFIED 0x00000001 + +// Dsound SYSTEM resource constants +// Matches the KSAUDIO_CPU_RESOURCES_xxx_HOST_CPU values defined +// in ksmedia.h. +#define DS_SYSTEM_RESOURCES_NO_HOST_RESOURCES 0x00000000 +#define DS_SYSTEM_RESOURCES_ALL_HOST_RESOURCES 0x7FFFFFFF +#define DS_SYSTEM_RESOURCES_UNDEFINED 0x80000000 + + +// +// I3DL2 Material Presets +// + +enum +{ + DSFX_I3DL2_MATERIAL_PRESET_SINGLEWINDOW, + DSFX_I3DL2_MATERIAL_PRESET_DOUBLEWINDOW, + DSFX_I3DL2_MATERIAL_PRESET_THINDOOR, + DSFX_I3DL2_MATERIAL_PRESET_THICKDOOR, + DSFX_I3DL2_MATERIAL_PRESET_WOODWALL, + DSFX_I3DL2_MATERIAL_PRESET_BRICKWALL, + DSFX_I3DL2_MATERIAL_PRESET_STONEWALL, + DSFX_I3DL2_MATERIAL_PRESET_CURTAIN +}; + +#define I3DL2_MATERIAL_PRESET_SINGLEWINDOW -2800,0.71f +#define I3DL2_MATERIAL_PRESET_DOUBLEWINDOW -5000,0.40f +#define I3DL2_MATERIAL_PRESET_THINDOOR -1800,0.66f +#define I3DL2_MATERIAL_PRESET_THICKDOOR -4400,0.64f +#define I3DL2_MATERIAL_PRESET_WOODWALL -4000,0.50f +#define I3DL2_MATERIAL_PRESET_BRICKWALL -5000,0.60f +#define I3DL2_MATERIAL_PRESET_STONEWALL -6000,0.68f +#define I3DL2_MATERIAL_PRESET_CURTAIN -1200,0.15f + + +enum +{ + DSFX_I3DL2_ENVIRONMENT_PRESET_DEFAULT, + DSFX_I3DL2_ENVIRONMENT_PRESET_GENERIC, + DSFX_I3DL2_ENVIRONMENT_PRESET_PADDEDCELL, + DSFX_I3DL2_ENVIRONMENT_PRESET_ROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_BATHROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_LIVINGROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_STONEROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_AUDITORIUM, + DSFX_I3DL2_ENVIRONMENT_PRESET_CONCERTHALL, + DSFX_I3DL2_ENVIRONMENT_PRESET_CAVE, + DSFX_I3DL2_ENVIRONMENT_PRESET_ARENA, + DSFX_I3DL2_ENVIRONMENT_PRESET_HANGAR, + DSFX_I3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY, + DSFX_I3DL2_ENVIRONMENT_PRESET_HALLWAY, + DSFX_I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR, + DSFX_I3DL2_ENVIRONMENT_PRESET_ALLEY, + DSFX_I3DL2_ENVIRONMENT_PRESET_FOREST, + DSFX_I3DL2_ENVIRONMENT_PRESET_CITY, + DSFX_I3DL2_ENVIRONMENT_PRESET_MOUNTAINS, + DSFX_I3DL2_ENVIRONMENT_PRESET_QUARRY, + DSFX_I3DL2_ENVIRONMENT_PRESET_PLAIN, + DSFX_I3DL2_ENVIRONMENT_PRESET_PARKINGLOT, + DSFX_I3DL2_ENVIRONMENT_PRESET_SEWERPIPE, + DSFX_I3DL2_ENVIRONMENT_PRESET_UNDERWATER, + DSFX_I3DL2_ENVIRONMENT_PRESET_SMALLROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_MEDIUMROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_LARGEROOM, + DSFX_I3DL2_ENVIRONMENT_PRESET_MEDIUMHALL, + DSFX_I3DL2_ENVIRONMENT_PRESET_LARGEHALL, + DSFX_I3DL2_ENVIRONMENT_PRESET_PLATE +}; + +// +// I3DL2 Reverberation Presets Values +// + +#define I3DL2_ENVIRONMENT_PRESET_DEFAULT -1000, -100, 0.0f, 1.49f, 0.83f, -2602, 0.007f, 200, 0.011f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_GENERIC -1000, -100, 0.0f, 1.49f, 0.83f, -2602, 0.007f, 200, 0.011f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_PADDEDCELL -1000,-6000, 0.0f, 0.17f, 0.10f, -1204, 0.001f, 207, 0.002f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_ROOM -1000, -454, 0.0f, 0.40f, 0.83f, -1646, 0.002f, 53, 0.003f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_BATHROOM -1000,-1200, 0.0f, 1.49f, 0.54f, -370, 0.007f, 1030, 0.011f, 100.0f, 60.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_LIVINGROOM -1000,-6000, 0.0f, 0.50f, 0.10f, -1376, 0.003f, -1104, 0.004f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_STONEROOM -1000, -300, 0.0f, 2.31f, 0.64f, -711, 0.012f, 83, 0.017f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_AUDITORIUM -1000, -476, 0.0f, 4.32f, 0.59f, -789, 0.020f, -289, 0.030f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_CONCERTHALL -1000, -500, 0.0f, 3.92f, 0.70f, -1230, 0.020f, -2, 0.029f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_CAVE -1000, 0, 0.0f, 2.91f, 1.30f, -602, 0.015f, -302, 0.022f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_ARENA -1000, -698, 0.0f, 7.24f, 0.33f, -1166, 0.020f, 16, 0.030f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_HANGAR -1000,-1000, 0.0f,10.05f, 0.23f, -602, 0.020f, 198, 0.030f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_CARPETEDHALLWAY -1000,-4000, 0.0f, 0.30f, 0.10f, -1831, 0.002f, -1630, 0.030f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_HALLWAY -1000, -300, 0.0f, 1.49f, 0.59f, -1219, 0.007f, 441, 0.011f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_STONECORRIDOR -1000, -237, 0.0f, 2.70f, 0.79f, -1214, 0.013f, 395, 0.020f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_ALLEY -1000, -270, 0.0f, 1.49f, 0.86f, -1204, 0.007f, -4, 0.011f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_FOREST -1000,-3300, 0.0f, 1.49f, 0.54f, -2560, 0.162f, -613, 0.088f, 79.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_CITY -1000, -800, 0.0f, 1.49f, 0.67f, -2273, 0.007f, -2217, 0.011f, 50.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_MOUNTAINS -1000,-2500, 0.0f, 1.49f, 0.21f, -2780, 0.300f, -2014, 0.100f, 27.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_QUARRY -1000,-1000, 0.0f, 1.49f, 0.83f,-10000, 0.061f, 500, 0.025f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_PLAIN -1000,-2000, 0.0f, 1.49f, 0.50f, -2466, 0.179f, -2514, 0.100f, 21.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_PARKINGLOT -1000, 0, 0.0f, 1.65f, 1.50f, -1363, 0.008f, -1153, 0.012f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_SEWERPIPE -1000,-1000, 0.0f, 2.81f, 0.14f, 429, 0.014f, 648, 0.021f, 80.0f, 60.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_UNDERWATER -1000,-4000, 0.0f, 1.49f, 0.10f, -449, 0.007f, 1700, 0.011f, 100.0f, 100.0f, 5000.0f + +// +// Examples simulating 'musical' reverb presets +// +// Name Decay time Description +// Small Room 1.1s A small size room with a length of 5m or so. +// Medium Room 1.3s A medium size room with a length of 10m or so. +// Large Room 1.5s A large size room suitable for live performances. +// Medium Hall 1.8s A medium size concert hall. +// Large Hall 1.8s A large size concert hall suitable for a full orchestra. +// Plate 1.3s A plate reverb simulation. +// + +#define I3DL2_ENVIRONMENT_PRESET_SMALLROOM -1000, -600, 0.0f, 1.10f, 0.83f, -400, 0.005f, 500, 0.010f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_MEDIUMROOM -1000, -600, 0.0f, 1.30f, 0.83f, -1000, 0.010f, -200, 0.020f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_LARGEROOM -1000, -600, 0.0f, 1.50f, 0.83f, -1600, 0.020f, -1000, 0.040f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_MEDIUMHALL -1000, -600, 0.0f, 1.80f, 0.70f, -1300, 0.015f, -800, 0.030f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_LARGEHALL -1000, -600, 0.0f, 1.80f, 0.70f, -2000, 0.030f, -1400, 0.060f, 100.0f, 100.0f, 5000.0f +#define I3DL2_ENVIRONMENT_PRESET_PLATE -1000, -200, 0.0f, 1.30f, 0.90f, 0, 0.002f, 0, 0.010f, 100.0f, 75.0f, 5000.0f + +// +// DirectSound3D Algorithms +// + +// Default DirectSound3D algorithm {00000000-0000-0000-0000-000000000000} +#define DS3DALG_DEFAULT GUID_NULL + +// No virtualization (Pan3D) {C241333F-1C1B-11d2-94F5-00C04FC28ACA} +DEFINE_GUID(DS3DALG_NO_VIRTUALIZATION, 0xc241333f, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca); + +// High-quality HRTF algorithm {C2413340-1C1B-11d2-94F5-00C04FC28ACA} +DEFINE_GUID(DS3DALG_HRTF_FULL, 0xc2413340, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca); + +// Lower-quality HRTF algorithm {C2413342-1C1B-11d2-94F5-00C04FC28ACA} +DEFINE_GUID(DS3DALG_HRTF_LIGHT, 0xc2413342, 0x1c1b, 0x11d2, 0x94, 0xf5, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca); + + +#if DIRECTSOUND_VERSION >= 0x0800 + +// +// DirectSound Internal Effect Algorithms +// + + +// Gargle {DAFD8210-5711-4B91-9FE3-F75B7AE279BF} +DEFINE_GUID(GUID_DSFX_STANDARD_GARGLE, 0xdafd8210, 0x5711, 0x4b91, 0x9f, 0xe3, 0xf7, 0x5b, 0x7a, 0xe2, 0x79, 0xbf); + +// Chorus {EFE6629C-81F7-4281-BD91-C9D604A95AF6} +DEFINE_GUID(GUID_DSFX_STANDARD_CHORUS, 0xefe6629c, 0x81f7, 0x4281, 0xbd, 0x91, 0xc9, 0xd6, 0x04, 0xa9, 0x5a, 0xf6); + +// Flanger {EFCA3D92-DFD8-4672-A603-7420894BAD98} +DEFINE_GUID(GUID_DSFX_STANDARD_FLANGER, 0xefca3d92, 0xdfd8, 0x4672, 0xa6, 0x03, 0x74, 0x20, 0x89, 0x4b, 0xad, 0x98); + +// Echo/Delay {EF3E932C-D40B-4F51-8CCF-3F98F1B29D5D} +DEFINE_GUID(GUID_DSFX_STANDARD_ECHO, 0xef3e932c, 0xd40b, 0x4f51, 0x8c, 0xcf, 0x3f, 0x98, 0xf1, 0xb2, 0x9d, 0x5d); + +// Distortion {EF114C90-CD1D-484E-96E5-09CFAF912A21} +DEFINE_GUID(GUID_DSFX_STANDARD_DISTORTION, 0xef114c90, 0xcd1d, 0x484e, 0x96, 0xe5, 0x09, 0xcf, 0xaf, 0x91, 0x2a, 0x21); + +// Compressor/Limiter {EF011F79-4000-406D-87AF-BFFB3FC39D57} +DEFINE_GUID(GUID_DSFX_STANDARD_COMPRESSOR, 0xef011f79, 0x4000, 0x406d, 0x87, 0xaf, 0xbf, 0xfb, 0x3f, 0xc3, 0x9d, 0x57); + +// Parametric Equalization {120CED89-3BF4-4173-A132-3CB406CF3231} +DEFINE_GUID(GUID_DSFX_STANDARD_PARAMEQ, 0x120ced89, 0x3bf4, 0x4173, 0xa1, 0x32, 0x3c, 0xb4, 0x06, 0xcf, 0x32, 0x31); + + +// I3DL2 Environmental Reverberation: Reverb (Listener) Effect {EF985E71-D5C7-42D4-BA4D-2D073E2E96F4} +DEFINE_GUID(GUID_DSFX_STANDARD_I3DL2REVERB, 0xef985e71, 0xd5c7, 0x42d4, 0xba, 0x4d, 0x2d, 0x07, 0x3e, 0x2e, 0x96, 0xf4); + +// Waves Reverberation {87FC0268-9A55-4360-95AA-004A1D9DE26C} +DEFINE_GUID(GUID_DSFX_WAVES_REVERB, 0x87fc0268, 0x9a55, 0x4360, 0x95, 0xaa, 0x00, 0x4a, 0x1d, 0x9d, 0xe2, 0x6c); + +// +// DirectSound Capture Effect Algorithms +// + + +// Acoustic Echo Canceller {BF963D80-C559-11D0-8A2B-00A0C9255AC1} +// Matches KSNODETYPE_ACOUSTIC_ECHO_CANCEL in ksmedia.h +DEFINE_GUID(GUID_DSCFX_CLASS_AEC, 0xBF963D80L, 0xC559, 0x11D0, 0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1); + +// Microsoft AEC {CDEBB919-379A-488a-8765-F53CFD36DE40} +DEFINE_GUID(GUID_DSCFX_MS_AEC, 0xcdebb919, 0x379a, 0x488a, 0x87, 0x65, 0xf5, 0x3c, 0xfd, 0x36, 0xde, 0x40); + +// System AEC {1C22C56D-9879-4f5b-A389-27996DDC2810} +DEFINE_GUID(GUID_DSCFX_SYSTEM_AEC, 0x1c22c56d, 0x9879, 0x4f5b, 0xa3, 0x89, 0x27, 0x99, 0x6d, 0xdc, 0x28, 0x10); + +// Noise Supression {E07F903F-62FD-4e60-8CDD-DEA7236665B5} +// Matches KSNODETYPE_NOISE_SUPPRESS in post Windows ME DDK's ksmedia.h +DEFINE_GUID(GUID_DSCFX_CLASS_NS, 0xe07f903f, 0x62fd, 0x4e60, 0x8c, 0xdd, 0xde, 0xa7, 0x23, 0x66, 0x65, 0xb5); + +// Microsoft Noise Suppresion {11C5C73B-66E9-4ba1-A0BA-E814C6EED92D} +DEFINE_GUID(GUID_DSCFX_MS_NS, 0x11c5c73b, 0x66e9, 0x4ba1, 0xa0, 0xba, 0xe8, 0x14, 0xc6, 0xee, 0xd9, 0x2d); + +// System Noise Suppresion {5AB0882E-7274-4516-877D-4EEE99BA4FD0} +DEFINE_GUID(GUID_DSCFX_SYSTEM_NS, 0x5ab0882e, 0x7274, 0x4516, 0x87, 0x7d, 0x4e, 0xee, 0x99, 0xba, 0x4f, 0xd0); + + +#endif // DIRECTSOUND_VERSION >= 0x0800 + +#endif // __DSOUND_INCLUDED__ + + + +#ifdef __cplusplus +}; +#endif // __cplusplus + + diff --git a/Sources/Engine/Sound/SoundData.cpp b/Sources/Engine/Sound/SoundData.cpp new file mode 100644 index 0000000..2140477 --- /dev/null +++ b/Sources/Engine/Sound/SoundData.cpp @@ -0,0 +1,254 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* ==================================================== + * + * Sound data awareness functions + */ + +/* + * Pause all playing + */ +void CSoundData::PausePlayingObjects(void) +{ + // for all objects linked to data pause playing + FOREACHINLIST(CSoundObject, so_Node, sd_ClhLinkList, itCsoPause) { + // pause playing + itCsoPause->Pause(); + } +} + +/* + * For all objects resume play + */ +void CSoundData::ResumePlayingObjects(void) +{ + // for all objects resume play + FOREACHINLIST(CSoundObject, so_Node, sd_ClhLinkList, itCsoResume) { + // call play method again + itCsoResume->Resume(); + } +} + + +/* + * Add object in sound aware list + */ +void CSoundData::AddObjectLink(CSoundObject &CsoAdd) +{ + // add object to list tail + sd_ClhLinkList.AddTail(CsoAdd.so_Node); +} + +/* + * Remove a object from aware list + */ +void CSoundData::RemoveObjectLink(CSoundObject &CsoRemove) +{ + // remove it from list + CsoRemove.so_Node.Remove(); +} + + +/* ==================================================== + * + * Class global methods + */ + +// Constructor +CSoundData::CSoundData() +{ + sd_pswBuffer = NULL; +} + +// Destructor +CSoundData::~CSoundData() +{ + Clear(); +} + + +// Free Buffer (and all linked Objects) +void CSoundData::ClearBuffer(void) +{ + // if buffer exist + if( sd_pswBuffer!=NULL) { + // release it + FreeMemory( sd_pswBuffer); + sd_pswBuffer = NULL; + } +} + + +// Get Sound Length in seconds +double CSoundData::GetSecondsLength(void) +{ + // if not encoded + if (!(sd_ulFlags&SDF_ENCODED) ) { + // len is read from wave + return sd_dSecondsLength; + // if encoded + } else { + // implement this!!!! + ASSERT(FALSE); + return 0; + } +} + + +/* ==================================================== + * + * Input methods (load sound in SoundData class) + */ + +// Read sound in memory +void CSoundData::Read_t(CTStream *inFile) // throw char * +{ + // synchronize access to sounds + CTSingleLock slSounds(&_pSound->sl_csSound, TRUE); + + ASSERT( sd_pswBuffer==NULL); + sd_ulFlags = NONE; + + // get filename + CTFileName fnm = inFile->GetDescription(); + // if this is encoded file + if (fnm.FileExt()==".ogg" || fnm.FileExt()==".mp3") { + CSoundDecoder *pmpd = new CSoundDecoder(fnm); + if (pmpd->IsOpen()) { + pmpd->GetFormat(sd_wfeFormat); + } + delete pmpd; + // mark that this is streaming encoded file + sd_ulFlags = SDF_ENCODED|SDF_STREAMING; + + // if this is wave file + } else { + // load wave info + PCMWaveInput CpwiLoad; + sd_wfeFormat = CpwiLoad.LoadInfo_t(inFile); + // store sample length in seconds and average byte rate + sd_dSecondsLength = CpwiLoad.GetSecondsLength(); + + // if sound library is in lower format convert sound to library format + if ((_pSound->sl_SwfeFormat).nSamplesPerSec < sd_wfeFormat.nSamplesPerSec) { + sd_wfeFormat.nSamplesPerSec = (_pSound->sl_SwfeFormat).nSamplesPerSec; + } + // same goes for bits/sample (must be 16) + sd_wfeFormat.wBitsPerSample = 16; + + // if library is active create buffer and load sound data + if (_pSound->IsActive()) { + // create Buffer + sd_slBufferSampleSize = CpwiLoad.GetDataLength(sd_wfeFormat); + SLONG slBufferSize = CpwiLoad.DetermineBufferSize(sd_wfeFormat); + sd_pswBuffer = (SWORD*)AllocMemory( slBufferSize+8); + // load data into buffer + CpwiLoad.LoadData_t( inFile, sd_pswBuffer, sd_wfeFormat); + // copy first sample to the last one (this is needed for linear interpolation) + (ULONG&)(((UBYTE*)sd_pswBuffer)[slBufferSize]) = *(ULONG*)sd_pswBuffer; + } + } + + // add to sound aware list + _pSound->AddSoundAware(*this); +} + + +// Sound can't be written to file +void CSoundData::Write_t( CTStream *outFile) +{ + ASSERTALWAYS("Cannot write sounds!"); + throw TRANS("Cannot write sounds!"); +} + +/* Get the description of this object. */ +CTString CSoundData::GetDescription(void) +{ + CTString str; + str.PrintF("%dkHz %dbit %s %.2lfs", + sd_wfeFormat.nSamplesPerSec/1000, + sd_wfeFormat.wBitsPerSample, + sd_wfeFormat.nChannels==1 ? "mono" : "stereo", + sd_dSecondsLength); + return str; +} + + +/* ==================================================== + * + * Class CLEAR method + */ + +// Free memory allocated for sound and Release DXBuffer +void CSoundData::Clear(void) +{ + // synchronize access to sounds + CTSingleLock slSounds(&_pSound->sl_csSound, TRUE); + + // clear BASE class + CSerial::Clear(); + + // free DXBuffer + ClearBuffer(); + + // if added as sound aware, remove it from sound aware list + if(IsHooked()) { + _pSound->RemoveSoundAware(*this); + } +} + + +// check if this kind of objects is auto-freed +BOOL CSoundData::IsAutoFreed(void) +{ + return FALSE; +} + + +// get amount of memory used by this object +SLONG CSoundData::GetUsedMemory(void) +{ + SLONG slUsed = sizeof(*this); + if( sd_pswBuffer!=NULL) { + ASSERT( sd_wfeFormat.nChannels==1 || sd_wfeFormat.nChannels==2); + slUsed += sd_slBufferSampleSize * sd_wfeFormat.nChannels *2; // all sounds are 16-bit + } + return slUsed; +} + + +/* ==================================================== + * + * Reference counting functions + */ + +// Add one reference +void CSoundData::AddReference(void) +{ + if (this!=NULL) { + MarkUsed(); + } +} + + +// Remove one reference +void CSoundData::RemReference(void) +{ + if (this!=NULL) { + _pSoundStock->Release(this); + } +} diff --git a/Sources/Engine/Sound/SoundData.h b/Sources/Engine/Sound/SoundData.h new file mode 100644 index 0000000..46f14db --- /dev/null +++ b/Sources/Engine/Sound/SoundData.h @@ -0,0 +1,70 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SOUNDDATA_H +#define SE_INCL_SOUNDDATA_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +#define SDF_ENCODED (1UL<<0) // this is ogg or mpx compressed file +#define SDF_STREAMING (1UL<<1) // streaming from disk + +class ENGINE_API CSoundData : public CSerial { +public: + // Sound Mode Aware class (notify class when sound mode change) + CListNode sd_Node; // for linking in list + ULONG sd_ulFlags; // flags + +//private: +public: + // Call-back called when sound mode changes. + void ModeChanged(void); + + inline BOOL IsHooked(void) const { return sd_Node.IsLinked(); }; + CListHead sd_ClhLinkList; // list of objects linked to data + + void PausePlayingObjects(void); + void ResumePlayingObjects(void); + + // Sound Buffer + WAVEFORMATEX sd_wfeFormat; // primary sound buffer format + SWORD *sd_pswBuffer; // pointer on buffer + SLONG sd_slBufferSampleSize; // buffer sample size + double sd_dSecondsLength; // sound length in seconds + + // free Buffer (and all linked Objects) + void ClearBuffer(void); + // Add object in sound aware list + void AddObjectLink(CSoundObject &CsoAdd); + // Remove an object from aware list + void RemoveObjectLink(CSoundObject &CsoRemove); + // reference counting functions + void AddReference(void); + void RemReference(void); +public: + // Constructor + CSoundData(); + // Destructor + ~CSoundData(); + // get sound length in seconds + double GetSecondsLength(void); + // read sound from file and convert it to the current sound format + void Read_t(CTStream *inFile); // throw char * + // write sound to file (not implemented) + void Write_t(CTStream *outFile); // throw char * + /* Get the description of this object. */ + CTString GetDescription(void); + // free allocated memory for sound and Sound in DXBuffer + void Clear(void); + // check if this kind of objects is auto-freed + virtual BOOL IsAutoFreed(void); + // get amount of memory used by this object + SLONG GetUsedMemory(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Sound/SoundDecoder.cpp b/Sources/Engine/Sound/SoundDecoder.cpp new file mode 100644 index 0000000..6037d8b --- /dev/null +++ b/Sources/Engine/Sound/SoundDecoder.cpp @@ -0,0 +1,614 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +// generic function called if a dll function is not found +static void FailFunction_t(const char *strName) { + ThrowF_t(TRANS("Function %s not found."), strName); +} + + +// ------------------------------------ AMP11 + +// amp11lib vars +extern BOOL _bAMP11Enabled = FALSE; +static HINSTANCE _hAmp11lib = NULL; + +// amp11lib types +typedef signed char ALsint8; +typedef unsigned char ALuint8; +typedef signed short ALsint16; +typedef unsigned short ALuint16; +typedef signed int ALsint32; +typedef unsigned int ALuint32; +typedef signed int ALsize; +typedef int ALbool; +typedef float ALfloat; +#define ALtrue 1 +#define ALfalse 0 +typedef ALsint32 ALhandle; + +// define amp11lib function pointers +#define DLLFUNCTION(dll, output, name, inputs, params, required) \ + output (__stdcall *p##name) inputs = NULL; +#include "al_functions.h" +#undef DLLFUNCTION + +static void AMP11_SetFunctionPointers_t(void) { + const char *strName; + // get amp11lib function pointers + #define DLLFUNCTION(dll, output, name, inputs, params, required) \ + strName = "_" #name "@" #params; \ + p##name = (output (__stdcall*) inputs) GetProcAddress( _hAmp11lib, strName); \ + if(p##name == NULL) FailFunction_t(strName); + #include "al_functions.h" + #undef DLLFUNCTION +} + +static void AMP11_ClearFunctionPointers(void) { + // clear amp11lib function pointers + #define DLLFUNCTION(dll, output, name, inputs, params, required) p##name = NULL; + #include "al_functions.h" + #undef DLLFUNCTION +} + +class CDecodeData_MPEG { +public: + ALhandle mpeg_hMainFile; // mainfile handle if using subfile + ALhandle mpeg_hFile; // file handle + ALhandle mpeg_hDecoder; // the decoder handle + FLOAT mpeg_fSecondsLen; // length of sound in seconds + WAVEFORMATEX mpeg_wfeFormat; // format of sound +}; + + +// ------------------------------------ Ogg Vorbis + +//#include // we define needed stuff ourselves, and ignore the rest + +// vorbis vars +extern BOOL _bOVEnabled = FALSE; +static HINSTANCE _hOV = NULL; + +#define OV_FALSE -1 +#define OV_EOF -2 +#define OV_HOLE -3 + +#define OV_EREAD -128 +#define OV_EFAULT -129 +#define OV_EIMPL -130 +#define OV_EINVAL -131 +#define OV_ENOTVORBIS -132 +#define OV_EBADHEADER -133 +#define OV_EVERSION -134 +#define OV_ENOTAUDIO -135 +#define OV_EBADPACKET -136 +#define OV_EBADLINK -137 +#define OV_ENOSEEK -138 + +// vorbis types +typedef __int64 ogg_int64_t; +typedef struct { + size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource); + int (*seek_func) (void *datasource, ogg_int64_t offset, int whence); + int (*close_func) (void *datasource); + long (*tell_func) (void *datasource); +} ov_callbacks; + +struct OggVorbis_File { + // don't wanna know whats inside + UBYTE dummy[2048]; // last time checked, the actual size was 720 (ogg vorbis version 1.0rc1) +}; +struct vorbis_info { + int version; + int channels; + long rate; + + long bitrate_upper; + long bitrate_nominal; + long bitrate_lower; + + // don't want to know the rest... + //.................. +}; + +// define vorbis function pointers +#define DLLFUNCTION(dll, output, name, inputs, params, required) \ + output (__cdecl *p##name) inputs = NULL; +#include "ov_functions.h" +#undef DLLFUNCTION + +static void OV_SetFunctionPointers_t(void) { + const char *strName; + // get vo function pointers + #define DLLFUNCTION(dll, output, name, inputs, params, required) \ + strName = #name ; \ + p##name = (output (__cdecl *) inputs) GetProcAddress( _hOV, strName); \ + if(p##name == NULL) FailFunction_t(strName); + #include "ov_functions.h" + #undef DLLFUNCTION +} +static void OV_ClearFunctionPointers(void) { + // clear vo function pointers + #define DLLFUNCTION(dll, output, name, inputs, params, required) p##name = NULL; + #include "ov_functions.h" + #undef DLLFUNCTION +} + +class CDecodeData_OGG { +public: + FILE *ogg_fFile; // the stdio file that ogg is in + SLONG ogg_slOffset; // offset where the ogg starts in the file (!=0 for oggs in zip) + SLONG ogg_slSize; // size of ogg in the file (!=filesize for oggs in zip) + OggVorbis_File *ogg_vfVorbisFile; // the decoder file + WAVEFORMATEX ogg_wfeFormat; // format of sound +}; + +// ogg file reading callbacks +// + +static size_t ogg_read_func (void *ptr, size_t size, size_t nmemb, void *datasource) +{ + CDecodeData_OGG *pogg = (CDecodeData_OGG *)datasource; + // calculate how much can be read at most + SLONG slToRead = size*nmemb; + SLONG slCurrentPos = ftell(pogg->ogg_fFile)-pogg->ogg_slOffset; + SLONG slSizeLeft = ClampDn(pogg->ogg_slSize-slCurrentPos, 0L); + slToRead = ClampUp(slToRead, slSizeLeft); + + // rounded down to the block size + slToRead/=size; + slToRead*=size; + // if there is nothing to read + if (slToRead<=0) { + return 0; + } + return fread(ptr, size, slToRead/size, pogg->ogg_fFile); +} + +static int ogg_seek_func (void *datasource, ogg_int64_t offset, int whence) +{ + return -1; +/* !!!! seeking is evil with vorbisfile 1.0RC2 + CDecodeData_OGG *pogg = (CDecodeData_OGG *)datasource; + SLONG slCurrentPos = ftell(pogg->ogg_fFile)-pogg->ogg_slOffset; + if (whence==SEEK_CUR) { + return fseek(pogg->ogg_fFile, offset, SEEK_CUR); + } else if (whence==SEEK_END) { + return fseek(pogg->ogg_fFile, pogg->ogg_slOffset+pogg->ogg_slSize-offset, SEEK_SET); + } else { + ASSERT(whence==SEEK_SET); + return fseek(pogg->ogg_fFile, pogg->ogg_slOffset+offset, SEEK_SET); + } +*/ +} + +static int ogg_close_func (void *datasource) +{ + return 0; +/* !!!! closing is evil with vorbisfile 1.0RC2 + CDecodeData_OGG *pogg = (CDecodeData_OGG *)datasource; + fclose(pogg->ogg_fFile); + */ +} +static long ogg_tell_func (void *datasource) +{ + return -1; +/* !!!! seeking is evil with vorbisfile 1.0RC2 + CDecodeData_OGG *pogg = (CDecodeData_OGG *)datasource; + ftell(pogg->ogg_fFile)-pogg->ogg_slOffset; + */ +} + +static ov_callbacks ovcCallbacks = { + ogg_read_func, + ogg_seek_func, + ogg_close_func, + ogg_tell_func, +}; + + +// initialize/end the decoding support engine(s) +void CSoundDecoder::InitPlugins(void) +{ + try { + // load vorbis + if (_hOV==NULL) { +#ifndef NDEBUG + #define VORBISLIB "vorbisfile_d.dll" +#else + #define VORBISLIB "vorbisfile.dll" +#endif + _hOV = ::LoadLibraryA(VORBISLIB); + } + if( _hOV == NULL) { + ThrowF_t(TRANS("Cannot load vorbisfile.dll.")); + } + // prepare function pointers + OV_SetFunctionPointers_t(); + + // if all successful, enable mpx playing + _bOVEnabled = TRUE; + CPrintF(TRANS(" vorbisfile.dll loaded, ogg playing enabled\n")); + + } catch (char *strError) { + CPrintF(TRANS("OGG playing disabled: %s\n"), strError); + } + + try { + // load amp11lib + if (_hAmp11lib==NULL) { + _hAmp11lib = ::LoadLibraryA( "amp11lib.dll"); + } + if( _hAmp11lib == NULL) { + ThrowF_t(TRANS("Cannot load amp11lib.dll.")); + } + // prepare function pointers + AMP11_SetFunctionPointers_t(); + + // initialize amp11lib before calling any of its functions + palInitLibrary(); + + // if all successful, enable mpx playing + _bAMP11Enabled = TRUE; + CPrintF(TRANS(" amp11lib.dll loaded, mpx playing enabled\n")); + + } catch (char *strError) { + CPrintF(TRANS("MPX playing disabled: %s\n"), strError); + } +} + +void CSoundDecoder::EndPlugins(void) +{ + // cleanup amp11lib when not needed anymore + if (_bAMP11Enabled) { + palEndLibrary(); + AMP11_ClearFunctionPointers(); + FreeLibrary(_hAmp11lib); + _hAmp11lib = NULL; + _bAMP11Enabled = FALSE; + } + + // cleanup vorbis when not needed anymore + if (_bOVEnabled) { + OV_ClearFunctionPointers(); + FreeLibrary(_hOV); + _hOV = NULL; + _bOVEnabled = FALSE; + } +} + +// decoder that streams from file +CSoundDecoder::CSoundDecoder(const CTFileName &fnm) +{ + sdc_pogg = NULL; + sdc_pmpeg = NULL; + + CTFileName fnmExpanded; + INDEX iFileType = ExpandFilePath(EFP_READ, fnm, fnmExpanded); + + // if ogg + if (fnmExpanded.FileExt()==".ogg") { + if (!_bOVEnabled) { + return; + } + sdc_pogg = new CDecodeData_OGG; + sdc_pogg->ogg_fFile = NULL; + sdc_pogg->ogg_vfVorbisFile = NULL; + sdc_pogg->ogg_slOffset = 0; + sdc_pogg->ogg_slSize = 0; + INDEX iZipHandle = 0; + + try { + // if in zip + if (iFileType==EFP_BASEZIP || iFileType==EFP_MODZIP) { + // open it + iZipHandle = UNZIPOpen_t(fnmExpanded); + + CTFileName fnmZip; + SLONG slOffset; + SLONG slSizeCompressed; + SLONG slSizeUncompressed; + BOOL bCompressed; + UNZIPGetFileInfo(iZipHandle, fnmZip, slOffset, slSizeCompressed, slSizeUncompressed, bCompressed); + + // if compressed + if (bCompressed) { + ThrowF_t(TRANS("encoded audio in archives must not be compressed!\n")); + } + // open ogg file + sdc_pogg->ogg_fFile = fopen(fnmZip, "rb"); + // if error + if (sdc_pogg->ogg_fFile==0) { + ThrowF_t(TRANS("cannot open archive '%s'"), (const char*)fnmZip); + } + // remember offset and size + sdc_pogg->ogg_slOffset = slOffset; + sdc_pogg->ogg_slSize = slSizeUncompressed; + fseek(sdc_pogg->ogg_fFile, slOffset, SEEK_SET); + + // if not in zip + } else if (iFileType==EFP_FILE) { + // open ogg file + sdc_pogg->ogg_fFile = fopen(fnmExpanded, "rb"); + // if error + if (sdc_pogg->ogg_fFile==0) { + ThrowF_t(TRANS("cannot open encoded audio file")); + } + // remember offset and size + sdc_pogg->ogg_slOffset = 0; + + fseek(sdc_pogg->ogg_fFile, 0, SEEK_END); + sdc_pogg->ogg_slSize = ftell(sdc_pogg->ogg_fFile); + fseek(sdc_pogg->ogg_fFile, 0, SEEK_SET); + // if not found + } else { + ThrowF_t(TRANS("file not found")); + } + + // initialize decoder + sdc_pogg->ogg_vfVorbisFile = new OggVorbis_File; + int iRes = pov_open_callbacks(sdc_pogg, sdc_pogg->ogg_vfVorbisFile, NULL, 0, ovcCallbacks); + + // if error + if (iRes!=0) { + ThrowF_t(TRANS("cannot open ogg decoder")); + } + + // get info on the file + vorbis_info *pvi = pov_info(sdc_pogg->ogg_vfVorbisFile, -1); + + // remember it's format + WAVEFORMATEX form; + form.wFormatTag=WAVE_FORMAT_PCM; + form.nChannels=pvi->channels; + form.nSamplesPerSec=pvi->rate; + form.wBitsPerSample=16; + form.nBlockAlign=form.nChannels*form.wBitsPerSample/8; + form.nAvgBytesPerSec=form.nSamplesPerSec*form.nBlockAlign; + form.cbSize=0; + + // check for stereo + if (pvi->channels!=2) { + ThrowF_t(TRANS("not stereo")); + } + + sdc_pogg->ogg_wfeFormat = form; + + } catch (char*strError) { + CPrintF(TRANS("Cannot open encoded audio '%s' for streaming: %s\n"), (const char*)fnm, (const char*)strError); + if (sdc_pogg->ogg_vfVorbisFile!=NULL) { + delete sdc_pogg->ogg_vfVorbisFile; + sdc_pogg->ogg_vfVorbisFile = NULL; + } + if (sdc_pogg->ogg_fFile!=NULL) { + fclose(sdc_pogg->ogg_fFile); + sdc_pogg->ogg_fFile = NULL; + } + if (iZipHandle!=0) { + UNZIPClose(iZipHandle); + } + Clear(); + return; + } + if (iZipHandle!=0) { + UNZIPClose(iZipHandle); + } + + // if mp3 + } else if (fnmExpanded.FileExt()==".mp3") { + + if (!_bAMP11Enabled) { + return; + } + + sdc_pmpeg = new CDecodeData_MPEG; + sdc_pmpeg->mpeg_hMainFile = 0; + sdc_pmpeg->mpeg_hFile = 0; + sdc_pmpeg->mpeg_hDecoder = 0; + INDEX iZipHandle = 0; + + try { + // if in zip + if (iFileType==EFP_BASEZIP || iFileType==EFP_MODZIP) { + // open it + iZipHandle = UNZIPOpen_t(fnmExpanded); + + CTFileName fnmZip; + SLONG slOffset; + SLONG slSizeCompressed; + SLONG slSizeUncompressed; + BOOL bCompressed; + UNZIPGetFileInfo(iZipHandle, fnmZip, slOffset, slSizeCompressed, slSizeUncompressed, bCompressed); + + // if compressed + if (bCompressed) { + ThrowF_t(TRANS("encoded audio in archives must not be compressed!\n")); + } + // open the zip file + sdc_pmpeg->mpeg_hMainFile = palOpenInputFile(fnmZip); + // if error + if (sdc_pmpeg->mpeg_hMainFile==0) { + ThrowF_t(TRANS("cannot open archive '%s'"), (const char*)fnmZip); + } + // open the subfile + sdc_pmpeg->mpeg_hFile = palOpenSubFile(sdc_pmpeg->mpeg_hMainFile, slOffset, slSizeUncompressed); + // if error + if (sdc_pmpeg->mpeg_hFile==0) { + ThrowF_t(TRANS("cannot open encoded audio file")); + } + + // if not in zip + } else if (iFileType==EFP_FILE) { + // open mpx file + sdc_pmpeg->mpeg_hFile = palOpenInputFile(fnmExpanded); + // if error + if (sdc_pmpeg->mpeg_hFile==0) { + ThrowF_t(TRANS("cannot open mpx file")); + } + // if not found + } else { + ThrowF_t(TRANS("file not found")); + } + + // get info on the file + int layer, ver, freq, stereo, rate; + if (!palGetMPXHeader(sdc_pmpeg->mpeg_hFile, &layer, &ver, &freq, &stereo, &rate)) { + ThrowF_t(TRANS("not a valid mpeg audio file.")); + } + + // remember it's format + WAVEFORMATEX form; + form.wFormatTag=WAVE_FORMAT_PCM; + form.nChannels=stereo?2:1; + form.nSamplesPerSec=freq; + form.wBitsPerSample=16; + form.nBlockAlign=form.nChannels*form.wBitsPerSample/8; + form.nAvgBytesPerSec=form.nSamplesPerSec*form.nBlockAlign; + form.cbSize=0; + + // check for stereo + if (!stereo) { + ThrowF_t(TRANS("not stereo")); + } + + sdc_pmpeg->mpeg_wfeFormat = form; + + // initialize decoder + sdc_pmpeg->mpeg_hDecoder = palOpenDecoder(sdc_pmpeg->mpeg_hFile); + + // if error + if (sdc_pmpeg->mpeg_hDecoder==0) { + ThrowF_t(TRANS("cannot open mpx decoder")); + } + } catch (char*strError) { + CPrintF(TRANS("Cannot open mpx '%s' for streaming: %s\n"), (const char*)fnm, (const char*)strError); + if (iZipHandle!=0) { + UNZIPClose(iZipHandle); + } + Clear(); + return; + } + + if (iZipHandle!=0) { + UNZIPClose(iZipHandle); + } + sdc_pmpeg->mpeg_fSecondsLen = palDecGetLen(sdc_pmpeg->mpeg_hDecoder); + } +} + +CSoundDecoder::~CSoundDecoder(void) +{ + Clear(); +} + +void CSoundDecoder::Clear(void) +{ + if (sdc_pmpeg!=NULL) { + if (sdc_pmpeg->mpeg_hDecoder!=0) palClose(sdc_pmpeg->mpeg_hDecoder); + if (sdc_pmpeg->mpeg_hFile!=0) palClose(sdc_pmpeg->mpeg_hFile); + if (sdc_pmpeg->mpeg_hMainFile!=0) palClose(sdc_pmpeg->mpeg_hMainFile); + + sdc_pmpeg->mpeg_hMainFile = 0; + sdc_pmpeg->mpeg_hFile = 0; + sdc_pmpeg->mpeg_hDecoder = 0; + delete sdc_pmpeg; + sdc_pmpeg = NULL; + + } else if (sdc_pogg!=NULL) { + + if (sdc_pogg->ogg_vfVorbisFile!=NULL) { + pov_clear(sdc_pogg->ogg_vfVorbisFile); + delete sdc_pogg->ogg_vfVorbisFile; + sdc_pogg->ogg_vfVorbisFile = NULL; + } + if (sdc_pogg->ogg_fFile!=NULL) { + fclose(sdc_pogg->ogg_fFile); + sdc_pogg->ogg_fFile = NULL; + } + delete sdc_pogg; + sdc_pogg = NULL; + } +} + +// reset decoder to start of sample +void CSoundDecoder::Reset(void) +{ + if (sdc_pmpeg!=NULL) { + palDecSeekAbs(sdc_pmpeg->mpeg_hDecoder, 0.0f); + } else if (sdc_pogg!=NULL) { +/* !!!! seeking is evil with vorbisfile 1.0RC2 + pov_time_seek(sdc_pogg->ogg_vfVorbisFile, 0.0f); + */ + // so instead, we reinit + pov_clear(sdc_pogg->ogg_vfVorbisFile); + fseek(sdc_pogg->ogg_fFile, sdc_pogg->ogg_slOffset, SEEK_SET); + pov_open_callbacks(sdc_pogg, sdc_pogg->ogg_vfVorbisFile, NULL, 0, ovcCallbacks); + } +} + +BOOL CSoundDecoder::IsOpen(void) +{ + if (sdc_pmpeg!=NULL && sdc_pmpeg->mpeg_hDecoder!=0) { + return TRUE; + } else if (sdc_pogg!=NULL && sdc_pogg->ogg_vfVorbisFile!=0) { + return TRUE; + } else { + return FALSE; + } +} + +void CSoundDecoder::GetFormat(WAVEFORMATEX &wfe) +{ + if (sdc_pmpeg!=NULL) { + wfe = sdc_pmpeg->mpeg_wfeFormat; + + } else if (sdc_pogg!=NULL) { + wfe = sdc_pogg->ogg_wfeFormat; + + } else { + NOTHING; + } +} + +// decode a block of bytes +INDEX CSoundDecoder::Decode(void *pvDestBuffer, INDEX ctBytesToDecode) +{ + // if ogg + if (sdc_pogg!=NULL && sdc_pogg->ogg_vfVorbisFile!=0) { + // decode ogg + static int iCurrrentSection = -1; // we don't care about this + char *pch = (char *)pvDestBuffer; + INDEX ctDecoded = 0; + while (ctDecodedogg_vfVorbisFile, pch, ctBytesToDecode-ctDecoded, + 0, 2, 1, &iCurrrentSection); + if (iRes<=0) { + return ctDecoded; + } + ctDecoded+=iRes; + pch+=iRes; + } + return ctDecoded; + + // if mpeg + } else if (sdc_pmpeg!=NULL && sdc_pmpeg->mpeg_hDecoder!=0) { + // decode mpeg + return palRead(sdc_pmpeg->mpeg_hDecoder, pvDestBuffer, ctBytesToDecode); + + // if no decoder + } else { + // play all zeroes + memset(pvDestBuffer, 0, ctBytesToDecode); + return ctBytesToDecode; + } +} diff --git a/Sources/Engine/Sound/SoundDecoder.h b/Sources/Engine/Sound/SoundDecoder.h new file mode 100644 index 0000000..4e03790 --- /dev/null +++ b/Sources/Engine/Sound/SoundDecoder.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#pragma once + +class CSoundDecoder { +public: + class CDecodeData_MPEG *sdc_pmpeg; + class CDecodeData_OGG *sdc_pogg ; + + // initialize/end the decoding support engine(s) + static void InitPlugins(void); + static void EndPlugins(void); + + // create a decoder that streams from file + CSoundDecoder(const CTFileName &fnmStream); + ~CSoundDecoder(void); + void Clear(void); + + // check if a decoder is succefully opened + BOOL IsOpen(void); + // get wave format of the decoder (invaid if it is not open) + void GetFormat(WAVEFORMATEX &wfe); + + // decode a block of bytes + INDEX Decode(void *pvDestBuffer, INDEX ctBytesToDecode); + // reset decoder to start of sample + void Reset(void); +}; \ No newline at end of file diff --git a/Sources/Engine/Sound/SoundLibrary.cpp b/Sources/Engine/Sound/SoundLibrary.cpp new file mode 100644 index 0000000..d003247 --- /dev/null +++ b/Sources/Engine/Sound/SoundLibrary.cpp @@ -0,0 +1,1342 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include "initguid.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +template CStaticArray; + +#pragma comment(lib, "winmm.lib") + +// pointer to global sound library object +CSoundLibrary *_pSound = NULL; + + +// console variables +extern FLOAT snd_tmMixAhead = 0.2f; // mix-ahead in seconds +extern FLOAT snd_fSoundVolume = 1.0f; // master volume for sound playing [0..1] +extern FLOAT snd_fMusicVolume = 1.0f; // master volume for music playing [0..1] +// NOTES: +// - these 3d sound parameters have been set carefully, take extreme if changing ! +// - ears distance of 20cm causes phase shift of up to 0.6ms which is very noticable +// and is more than enough, too large values cause too much distorsions in other effects +// - pan strength needs not to be very strong, since lrfilter has panning-like influence also +// - if down filter is too large, it makes too much influence even on small elevation changes +// and messes the situation completely +extern FLOAT snd_fDelaySoundSpeed = 1E10; // sound speed used for delay [m/s] +extern FLOAT snd_fDopplerSoundSpeed = 330.0f; // sound speed used for doppler [m/s] +extern FLOAT snd_fEarsDistance = 0.2f; // distance between listener's ears +extern FLOAT snd_fPanStrength = 0.1f; // panning modifier (0=none, 1= full) +extern FLOAT snd_fLRFilter = 3.0f; // filter for left-right +extern FLOAT snd_fBFilter = 5.0f; // filter for back +extern FLOAT snd_fUFilter = 1.0f; // filter for up +extern FLOAT snd_fDFilter = 3.0f; // filter for down + +ENGINE_API extern INDEX snd_iFormat = 3; +extern INDEX snd_bMono = FALSE; +static INDEX snd_iDevice = -1; +static INDEX snd_iInterface = 2; // 0=WaveOut, 1=DirectSound, 2=EAX +static INDEX snd_iMaxOpenRetries = 3; +static INDEX snd_iMaxExtraChannels = 32; +static FLOAT snd_tmOpenFailDelay = 0.5f; +static FLOAT snd_fEAXPanning = 0.0f; + +static FLOAT snd_fNormalizer = 0.9f; +static FLOAT _fLastNormalizeValue = 1; + +extern HWND _hwndMain; // global handle for application window +static HWND _hwndCurrent = NULL; +static HINSTANCE _hInstDS = NULL; +static INDEX _iWriteOffset = 0; +static INDEX _iWriteOffset2 = 0; +static BOOL _bMuted = FALSE; +static INDEX _iLastEnvType = 1234; +static FLOAT _fLastEnvSize = 1234; +static FLOAT _fLastPanning = 1234; + + +// TEMP! - for writing mixer buffer to file +static FILE *_filMixerBuffer; +static BOOL _bOpened = FALSE; + + +#define WAVEOUTBLOCKSIZE 1024 +#define MINPAN (1.0f) +#define MAXPAN (9.0f) + + + +/** + * ---------------------------- + * Sound Library functions + * ---------------------------- +**/ + +/* + * Construct uninitialized sound library. + */ +CSoundLibrary::CSoundLibrary(void) +{ + sl_csSound.cs_iIndex = 3000; + + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + // synchronize access to sounds + CTSingleLock slSounds(&sl_csSound, TRUE); + + // clear sound format + memset( &sl_SwfeFormat, 0, sizeof(WAVEFORMATEX)); + sl_EsfFormat = SF_NONE; + + // reset buffer ptrs + sl_pslMixerBuffer = NULL; + sl_pswDecodeBuffer = NULL; + sl_pubBuffersMemory = NULL; + // clear wave out data + sl_hwoWaveOut = NULL; + + // clear direct sound data + _hInstDS = NULL; + sl_pDS = NULL; + sl_pKSProperty = NULL; + sl_pDSPrimary = NULL; + sl_pDSSecondary = NULL; + sl_pDSSecondary2 = NULL; + sl_pDSListener = NULL; + sl_pDSSourceLeft = NULL; + sl_pDSSourceRight = NULL; + sl_bUsingDirectSound = FALSE; + sl_bUsingEAX = FALSE; +} + + +/* + * Destruct (and clean up). + */ +CSoundLibrary::~CSoundLibrary(void) +{ + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + // synchronize access to sounds + CTSingleLock slSounds(&sl_csSound, TRUE); + + // clear sound enviroment + Clear(); + + // clear any installed sound decoders + CSoundDecoder::EndPlugins(); +} + + + +// post sound console variables' functions + +static FLOAT _tmLastMixAhead = 1234; +static INDEX _iLastFormat = 1234; +static INDEX _iLastDevice = 1234; +static INDEX _iLastAPI = 1234; + +static void SndPostFunc(void *pArgs) +{ + // clamp variables + snd_tmMixAhead = Clamp( snd_tmMixAhead, 0.1f, 0.9f); + snd_iFormat = Clamp( snd_iFormat, (INDEX)CSoundLibrary::SF_NONE, (INDEX)CSoundLibrary::SF_44100_16); + snd_iDevice = Clamp( snd_iDevice, -1L, 15L); + snd_iInterface = Clamp( snd_iInterface, 0L, 2L); + // if any variable has been changed + if( _tmLastMixAhead!=snd_tmMixAhead || _iLastFormat!=snd_iFormat + || _iLastDevice!=snd_iDevice || _iLastAPI!=snd_iInterface) { + // reinit sound format + _pSound->SetFormat( (enum CSoundLibrary::SoundFormat)snd_iFormat, TRUE); + } +} + + + +/* + * some internal functions + */ + + +// DirectSound shutdown procedure +static void ShutDown_dsound( CSoundLibrary &sl) +{ + // free direct sound buffer(s) + sl.sl_bUsingDirectSound = FALSE; + sl.sl_bUsingEAX = FALSE; + + if( sl.sl_pDSSourceRight!=NULL) { + sl.sl_pDSSourceRight->Release(); + sl.sl_pDSSourceRight = NULL; + } + if( sl.sl_pDSSourceLeft != NULL) { + sl.sl_pDSSourceLeft->Release(); + sl.sl_pDSSourceLeft = NULL; + } + if( sl.sl_pDSListener != NULL) { + sl.sl_pDSListener->Release(); + sl.sl_pDSListener = NULL; + } + + if( sl.sl_pDSSecondary2 != NULL) { + sl.sl_pDSSecondary2->Stop(); + sl.sl_pDSSecondary2->Release(); + sl.sl_pDSSecondary2 = NULL; + } + if( sl.sl_pDSSecondary != NULL) { + sl.sl_pDSSecondary->Stop(); + sl.sl_pDSSecondary->Release(); + sl.sl_pDSSecondary = NULL; + } + if( sl.sl_pDSPrimary!=NULL) { + sl.sl_pDSPrimary->Stop(); + sl.sl_pDSPrimary->Release(); + sl.sl_pDSPrimary = NULL; + } + + if( sl.sl_pKSProperty != NULL) { + sl.sl_pKSProperty->Release(); + sl.sl_pKSProperty = NULL; + } + + // free direct sound object + if( sl.sl_pDS!=NULL) { + // reset cooperative level + if( _hwndCurrent!=NULL) sl.sl_pDS->SetCooperativeLevel( _hwndCurrent, DSSCL_NORMAL); + sl.sl_pDS->Release(); + sl.sl_pDS = NULL; + } + // free direct sound library + if( _hInstDS != NULL) { + FreeLibrary(_hInstDS); + _hInstDS = NULL; + } + // free memory + if( sl.sl_pslMixerBuffer!=NULL) { + FreeMemory( sl.sl_pslMixerBuffer); + sl.sl_pslMixerBuffer = NULL; + } + if( sl.sl_pswDecodeBuffer!=NULL) { + FreeMemory( sl.sl_pswDecodeBuffer); + sl.sl_pswDecodeBuffer = NULL; + } +} + + +/* + * Set wave format from library format + */ +static void SetWaveFormat( CSoundLibrary::SoundFormat EsfFormat, WAVEFORMATEX &wfeFormat) +{ + // change Library Wave Format + memset( &wfeFormat, 0, sizeof(WAVEFORMATEX)); + wfeFormat.wFormatTag = WAVE_FORMAT_PCM; + wfeFormat.nChannels = 2; + wfeFormat.wBitsPerSample = 16; + switch( EsfFormat) { + case CSoundLibrary::SF_11025_16: wfeFormat.nSamplesPerSec = 11025; break; + case CSoundLibrary::SF_22050_16: wfeFormat.nSamplesPerSec = 22050; break; + case CSoundLibrary::SF_44100_16: wfeFormat.nSamplesPerSec = 44100; break; + case CSoundLibrary::SF_NONE: ASSERTALWAYS( "Can't set to NONE format"); break; + default: ASSERTALWAYS( "Unknown Sound format"); break; + } + wfeFormat.nBlockAlign = (wfeFormat.wBitsPerSample / 8) * wfeFormat.nChannels; + wfeFormat.nAvgBytesPerSec = wfeFormat.nSamplesPerSec * wfeFormat.nBlockAlign; +} + + +/* + * Set library format from wave format + */ +static void SetLibraryFormat( CSoundLibrary &sl) +{ + // if library format is none return + if( sl.sl_EsfFormat == CSoundLibrary::SF_NONE) return; + + // else check wave format to determine library format + ULONG ulFormat = sl.sl_SwfeFormat.nSamplesPerSec; + // find format + switch( ulFormat) { + case 11025: sl.sl_EsfFormat = CSoundLibrary::SF_11025_16; break; + case 22050: sl.sl_EsfFormat = CSoundLibrary::SF_22050_16; break; + case 44100: sl.sl_EsfFormat = CSoundLibrary::SF_44100_16; break; + // unknown format + default: + ASSERTALWAYS( "Unknown sound format"); + FatalError( TRANS("Unknown sound format")); + sl.sl_EsfFormat = CSoundLibrary::SF_ILLEGAL; + } +} + + + +static BOOL DSFail( CSoundLibrary &sl, char *strError) +{ + CPrintF(strError); + ShutDown_dsound(sl); + snd_iInterface=1; // if EAX failed -> try DirectSound + return FALSE; +} + + +// some helper functions for DirectSound +static BOOL DSInitSecondary( CSoundLibrary &sl, LPDIRECTSOUNDBUFFER &pBuffer, SLONG slSize) +{ + // eventuallt adjust for EAX + DWORD dwFlag3D = NONE; + if( snd_iInterface==2) { + dwFlag3D = DSBCAPS_CTRL3D; + sl.sl_SwfeFormat.nChannels=1; // mono output + sl.sl_SwfeFormat.nBlockAlign/=2; + sl.sl_SwfeFormat.nAvgBytesPerSec/=2; + slSize/=2; + } + DSBUFFERDESC dsBuffer; + memset( &dsBuffer, 0, sizeof(dsBuffer)); + dsBuffer.dwSize = sizeof(DSBUFFERDESC); + dsBuffer.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | dwFlag3D; + dsBuffer.dwBufferBytes = slSize; + dsBuffer.lpwfxFormat = &sl.sl_SwfeFormat; + HRESULT hResult = sl.sl_pDS->CreateSoundBuffer( &dsBuffer, &pBuffer, NULL); + if( snd_iInterface==2) { + // revert back to original wave format (stereo) + sl.sl_SwfeFormat.nChannels=2; + sl.sl_SwfeFormat.nBlockAlign*=2; + sl.sl_SwfeFormat.nAvgBytesPerSec*=2; + } + if( hResult != DS_OK) return DSFail( sl, TRANS(" ! DirectSound error: Cannot create secondary buffer.\n")); + return TRUE; +} + + +static BOOL DSLockBuffer( CSoundLibrary &sl, LPDIRECTSOUNDBUFFER pBuffer, SLONG slSize, LPVOID &lpData, DWORD &dwSize) +{ + INDEX ctRetries = 1000; // too much? + if( sl.sl_bUsingEAX) slSize/=2; // buffer is mono in case of EAX + FOREVER { + HRESULT hResult = pBuffer->Lock( 0, slSize, &lpData, &dwSize, NULL, NULL, 0); + if( hResult==DS_OK && slSize==dwSize) return TRUE; + if( hResult!=DSERR_BUFFERLOST) return DSFail( sl, TRANS(" ! DirectSound error: Cannot lock sound buffer.\n")); + if( ctRetries-- == 0) return DSFail( sl, TRANS(" ! DirectSound error: Couldn't restore sound buffer.\n")); + pBuffer->Restore(); + } +} + + +static void DSPlayBuffers( CSoundLibrary &sl) +{ + DWORD dw; + BOOL bInitiatePlay = FALSE; + ASSERT( sl.sl_pDSSecondary!=NULL && sl.sl_pDSPrimary!=NULL); + if( sl.sl_bUsingEAX && sl.sl_pDSSecondary2->GetStatus(&dw)==DS_OK && !(dw&DSBSTATUS_PLAYING)) bInitiatePlay = TRUE; + if( sl.sl_pDSSecondary->GetStatus(&dw)==DS_OK && !(dw&DSBSTATUS_PLAYING)) bInitiatePlay = TRUE; + if( sl.sl_pDSPrimary->GetStatus(&dw)==DS_OK && !(dw&DSBSTATUS_PLAYING)) bInitiatePlay = TRUE; + + // done if all buffers are already playing + if( !bInitiatePlay) return; + + // stop buffers (in case some buffers are playing + sl.sl_pDSPrimary->Stop(); + sl.sl_pDSSecondary->Stop(); + if( sl.sl_bUsingEAX) sl.sl_pDSSecondary2->Stop(); + + // check sound buffer lock and clear sound buffer(s) + LPVOID lpData; + DWORD dwSize; + if( !DSLockBuffer( sl, sl.sl_pDSSecondary, sl.sl_slMixerBufferSize, lpData, dwSize)) return; + memset( lpData, 0, dwSize); + sl.sl_pDSSecondary->Unlock( lpData, dwSize, NULL, 0); + if( sl.sl_bUsingEAX) { + if( !DSLockBuffer( sl, sl.sl_pDSSecondary2, sl.sl_slMixerBufferSize, lpData, dwSize)) return; + memset( lpData, 0, dwSize); + sl.sl_pDSSecondary2->Unlock( lpData, dwSize, NULL, 0); + // start playing EAX additional buffer + sl.sl_pDSSecondary2->Play( 0, 0, DSBPLAY_LOOPING); + } + // start playing standard DirectSound buffers + sl.sl_pDSPrimary->Play( 0, 0, DSBPLAY_LOOPING); + sl.sl_pDSSecondary->Play( 0, 0, DSBPLAY_LOOPING); + _iWriteOffset = 0; + _iWriteOffset2 = 0; + + // adjust starting offsets for EAX + if( sl.sl_bUsingEAX) { + DWORD dwCursor1, dwCursor2; + SLONG slMinDelta = MAX_SLONG; + for( INDEX i=0; i<10; i++) { // shoud be enough to screw interrupts + sl.sl_pDSSecondary->GetCurrentPosition( &dwCursor1, NULL); + sl.sl_pDSSecondary2->GetCurrentPosition( &dwCursor2, NULL); + SLONG slDelta1 = dwCursor2-dwCursor1; + sl.sl_pDSSecondary2->GetCurrentPosition( &dwCursor2, NULL); + sl.sl_pDSSecondary->GetCurrentPosition( &dwCursor1, NULL); + SLONG slDelta2 = dwCursor2-dwCursor1; + SLONG slDelta = (slDelta1+slDelta2) /2; + if( slDelta0) _iWriteOffset2 = +slMinDelta*2; + _iWriteOffset += _iWriteOffset & 3; // round to 4 bytes + _iWriteOffset2 += _iWriteOffset2 & 3; + + // assure that first writing offsets are inside buffers + if( _iWriteOffset >=sl.sl_slMixerBufferSize) _iWriteOffset -= sl.sl_slMixerBufferSize; + if( _iWriteOffset2>=sl.sl_slMixerBufferSize) _iWriteOffset2 -= sl.sl_slMixerBufferSize; + ASSERT( _iWriteOffset >=0 && _iWriteOffset =0 && _iWriteOffset2GetCaps( &dsCaps); + if( hResult != DS_OK) return DSFail( sl, TRANS(" ! DirectSound error: Cannot determine capabilites.\n")); + + // fail if in emulation mode + if( dsCaps.dwFlags & DSCAPS_EMULDRIVER) { + CPrintF( TRANS(" ! DirectSound error: No driver installed.\n")); + ShutDown_dsound(sl); + return FALSE; + } + + // set cooperative level to priority + _hwndCurrent = _hwndMain; + hResult = sl.sl_pDS->SetCooperativeLevel( _hwndCurrent, DSSCL_PRIORITY); + if( hResult != DS_OK) return DSFail( sl, TRANS(" ! DirectSound error: Cannot set cooperative level.\n")); + + // prepare 3D flag if EAX + DWORD dwFlag3D = NONE; + if( snd_iInterface==2) dwFlag3D = DSBCAPS_CTRL3D; + + // create primary sound buffer (must have one) + DSBUFFERDESC dsBuffer; + memset( &dsBuffer, 0, sizeof(dsBuffer)); + dsBuffer.dwSize = sizeof(dsBuffer); + dsBuffer.dwFlags = DSBCAPS_PRIMARYBUFFER | dwFlag3D; + dsBuffer.dwBufferBytes = 0; + dsBuffer.lpwfxFormat = NULL; + hResult = sl.sl_pDS->CreateSoundBuffer( &dsBuffer, &sl.sl_pDSPrimary, NULL); + if( hResult != DS_OK) return DSFail( sl, TRANS(" ! DirectSound error: Cannot create primary sound buffer.\n")); + + // set primary buffer format + WAVEFORMATEX wfx = sl.sl_SwfeFormat; + hResult = sl.sl_pDSPrimary->SetFormat(&wfx); + if( hResult != DS_OK) return DSFail( sl, TRANS(" ! DirectSound error: Cannot set primary sound buffer format.\n")); + + // startup secondary sound buffer(s) + SLONG slBufferSize = (SLONG)(ceil(snd_tmMixAhead*sl.sl_SwfeFormat.nSamplesPerSec) * + sl.sl_SwfeFormat.wBitsPerSample/8 * sl.sl_SwfeFormat.nChannels); + if( !DSInitSecondary( sl, sl.sl_pDSSecondary, slBufferSize)) return FALSE; + + // set some additionals for EAX + if( snd_iInterface==2) + { + // 2nd secondary buffer + if( !DSInitSecondary( sl, sl.sl_pDSSecondary2, slBufferSize)) return FALSE; + // set 3D for all buffers + HRESULT hr1,hr2,hr3,hr4; + hr1 = sl.sl_pDSPrimary->QueryInterface( IID_IDirectSound3DListener, (LPVOID*)&sl.sl_pDSListener); + hr2 = sl.sl_pDSSecondary->QueryInterface( IID_IDirectSound3DBuffer, (LPVOID*)&sl.sl_pDSSourceLeft); + hr3 = sl.sl_pDSSecondary2->QueryInterface( IID_IDirectSound3DBuffer, (LPVOID*)&sl.sl_pDSSourceRight); + if( hr1!=DS_OK || hr2!=DS_OK || hr3!=DS_OK) return DSFail( sl, TRANS(" ! DirectSound3D error: Cannot set 3D sound buffer.\n")); + + hr1 = sl.sl_pDSListener->SetPosition( 0,0,0, DS3D_DEFERRED); + hr2 = sl.sl_pDSListener->SetOrientation( 0,0,1, 0,1,0, DS3D_DEFERRED); + hr3 = sl.sl_pDSListener->SetRolloffFactor( 1, DS3D_DEFERRED); + if( hr1!=DS_OK || hr2!=DS_OK || hr3!=DS_OK) return DSFail( sl, TRANS(" ! DirectSound3D error: Cannot set 3D parameters for listener.\n")); + hr1 = sl.sl_pDSSourceLeft->SetMinDistance( MINPAN, DS3D_DEFERRED); + hr2 = sl.sl_pDSSourceLeft->SetMaxDistance( MAXPAN, DS3D_DEFERRED); + hr3 = sl.sl_pDSSourceRight->SetMinDistance( MINPAN, DS3D_DEFERRED); + hr4 = sl.sl_pDSSourceRight->SetMaxDistance( MAXPAN, DS3D_DEFERRED); + if( hr1!=DS_OK || hr2!=DS_OK || hr3!=DS_OK || hr4!=DS_OK) { + return DSFail( sl, TRANS(" ! DirectSound3D error: Cannot set 3D parameters for sound source.\n")); + } + // apply + hResult = sl.sl_pDSListener->CommitDeferredSettings(); + if( hResult!=DS_OK) return DSFail( sl, TRANS(" ! DirectSound3D error: Cannot apply 3D parameters.\n")); + // reset EAX parameters + _fLastPanning = 1234; + _iLastEnvType = 1234; + _fLastEnvSize = 1234; + + // query property interface to EAX + hResult = sl.sl_pDSSourceLeft->QueryInterface( IID_IKsPropertySet, (LPVOID*)&sl.sl_pKSProperty); + if( hResult != DS_OK) return DSFail( sl, TRANS(" ! EAX error: Cannot set property interface.\n")); + // query support + ULONG ulSupport = 0; + hResult = sl.sl_pKSProperty->QuerySupport( DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, &ulSupport); + if( hResult != DS_OK || !(ulSupport&KSPROPERTY_SUPPORT_SET)) return DSFail( sl, TRANS(" ! EAX error: Cannot query property support.\n")); + hResult = sl.sl_pKSProperty->QuerySupport( DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, &ulSupport); + if( hResult != DS_OK || !(ulSupport&KSPROPERTY_SUPPORT_SET)) return DSFail( sl, TRANS(" ! EAX error: Cannot query property support.\n")); + // made it - EAX's on! + sl.sl_bUsingEAX = TRUE; + } + + // mark that dsound is operative and set mixer buffer size (decoder buffer always works at 44khz) + _iWriteOffset = 0; + _iWriteOffset2 = 0; + sl.sl_bUsingDirectSound = TRUE; + sl.sl_slMixerBufferSize = slBufferSize; + sl.sl_slDecodeBufferSize = sl.sl_slMixerBufferSize * + ((44100+sl.sl_SwfeFormat.nSamplesPerSec-1) /sl.sl_SwfeFormat.nSamplesPerSec); + // allocate mixing and decoding buffers + sl.sl_pslMixerBuffer = (SLONG*)AllocMemory( sl.sl_slMixerBufferSize *2); // (*2 because of 32-bit buffer) + sl.sl_pswDecodeBuffer = (SWORD*)AllocMemory( sl.sl_slDecodeBufferSize+4); // (+4 because of linear interpolation of last samples) + + // report success + if( bReport) { + CTString strDevice = TRANS("default device"); + if( snd_iDevice>=0) strDevice.PrintF( TRANS("device %d"), snd_iDevice); + CPrintF( TRANS(" %dHz, %dbit, %s, mix-ahead: %gs\n"), + sl.sl_SwfeFormat.nSamplesPerSec, sl.sl_SwfeFormat.wBitsPerSample, strDevice, snd_tmMixAhead); + CPrintF(TRANS(" mixer buffer size: %d KB\n"), sl.sl_slMixerBufferSize /1024); + CPrintF(TRANS(" decode buffer size: %d KB\n"), sl.sl_slDecodeBufferSize/1024); + // EAX? + CTString strEAX = TRANS("Disabled"); + if( sl.sl_bUsingEAX) strEAX = TRANS("Enabled"); + CPrintF( TRANS(" EAX: %s\n"), strEAX); + } + // done + return TRUE; +} + + +// set WaveOut format (internal) + +static INDEX _ctChannelsOpened = 0; +static BOOL StartUp_waveout( CSoundLibrary &sl, BOOL bReport=TRUE) +{ + // not using DirectSound (obviously) + sl.sl_bUsingDirectSound = FALSE; + sl.sl_bUsingEAX = FALSE; + if( bReport) CPrintF(TRANS("WaveOut initialization ...\n")); + // set maximum total number of retries for device opening + INDEX ctMaxRetries = snd_iMaxOpenRetries; + _ctChannelsOpened = 0; + MMRESULT res; + // repeat + FOREVER { + // try to open wave device + HWAVEOUT hwo; + res = waveOutOpen( &hwo, (snd_iDevice<0)?WAVE_MAPPER:snd_iDevice, &sl.sl_SwfeFormat, NULL, NULL, NONE); + // if opened + if( res == MMSYSERR_NOERROR) { + _ctChannelsOpened++; + // if first one + if (_ctChannelsOpened==1) { + // remember as used waveout + sl.sl_hwoWaveOut = hwo; + // if extra channel + } else { + // remember under extra + sl.sl_ahwoExtra.Push() = hwo; + } + // if no extra channels should be taken + if (_ctChannelsOpened>=snd_iMaxExtraChannels+1) { + // no more tries + break; + } + // if cannot open + } else { + // decrement retry counter + ctMaxRetries--; + // if no more retries + if (ctMaxRetries<0) { + // quit trying + break; + // if more retries left + } else { + // wait a bit (probably sound-scheme is playing) + Sleep(int(snd_tmOpenFailDelay*1000)); + } + } + } + + // if couldn't set format + if( _ctChannelsOpened==0 && res != MMSYSERR_NOERROR) { + // report error + CTString strError; + switch (res) { + case MMSYSERR_ALLOCATED: strError = TRANS("Device already in use."); break; + case MMSYSERR_BADDEVICEID: strError = TRANS("Bad device number."); break; + case MMSYSERR_NODRIVER: strError = TRANS("No driver installed."); break; + case MMSYSERR_NOMEM: strError = TRANS("Memory allocation problem."); break; + case WAVERR_BADFORMAT: strError = TRANS("Unsupported data format."); break; + case WAVERR_SYNC: strError = TRANS("Wrong flag?"); break; + default: strError.PrintF( "%d", res); + }; + CPrintF( TRANS(" ! WaveOut error: %s\n"), strError); + return FALSE; + } + + // get waveout capabilities + WAVEOUTCAPS woc; + memset( &woc, 0, sizeof(woc)); + res = waveOutGetDevCaps((int)sl.sl_hwoWaveOut, &woc, sizeof(woc)); + // report success + if( bReport) { + CTString strDevice = TRANS("default device"); + if( snd_iDevice>=0) strDevice.PrintF( TRANS("device %d"), snd_iDevice); + CPrintF( TRANS(" opened device: %s\n"), woc.szPname); + CPrintF( TRANS(" %dHz, %dbit, %s\n"), + sl.sl_SwfeFormat.nSamplesPerSec, sl.sl_SwfeFormat.wBitsPerSample, strDevice); + } + + // determine whole mixer buffer size from mixahead console variable + sl.sl_slMixerBufferSize = (SLONG)(ceil(snd_tmMixAhead*sl.sl_SwfeFormat.nSamplesPerSec) * + sl.sl_SwfeFormat.wBitsPerSample/8 * sl.sl_SwfeFormat.nChannels); + // align size to be next multiply of WAVEOUTBLOCKSIZE + sl.sl_slMixerBufferSize += WAVEOUTBLOCKSIZE - (sl.sl_slMixerBufferSize % WAVEOUTBLOCKSIZE); + // determine number of WaveOut buffers + const INDEX ctWOBuffers = sl.sl_slMixerBufferSize / WAVEOUTBLOCKSIZE; + // decoder buffer always works at 44khz + sl.sl_slDecodeBufferSize = sl.sl_slMixerBufferSize * + ((44100+sl.sl_SwfeFormat.nSamplesPerSec-1)/sl.sl_SwfeFormat.nSamplesPerSec); + if( bReport) { + CPrintF(TRANS(" parameters: %d Hz, %d bit, stereo, mix-ahead: %gs\n"), + sl.sl_SwfeFormat.nSamplesPerSec, sl.sl_SwfeFormat.wBitsPerSample, snd_tmMixAhead); + CPrintF(TRANS(" output buffers: %d x %d bytes\n"), ctWOBuffers, WAVEOUTBLOCKSIZE), + CPrintF(TRANS(" mpx decode: %d bytes\n"), sl.sl_slDecodeBufferSize), + CPrintF(TRANS(" extra sound channels taken: %d\n"), _ctChannelsOpened-1); + } + + // initialise waveout sound buffers + sl.sl_pubBuffersMemory = (UBYTE*)AllocMemory( sl.sl_slMixerBufferSize); + memset( sl.sl_pubBuffersMemory, 0, sl.sl_slMixerBufferSize); + sl.sl_awhWOBuffers.New(ctWOBuffers); + for( INDEX iBuffer = 0; iBuffertm_csHooks, TRUE); + // synchronize access to sounds + CTSingleLock slSounds(&sl.sl_csSound, TRUE); + + // remember library format + sl.sl_EsfFormat = EsfNew; + // release library + sl.ClearLibrary(); + + // if none skip initialization + _fLastNormalizeValue = 1; + if( bReport) CPrintF(TRANS("Setting sound format ...\n")); + if( sl.sl_EsfFormat == CSoundLibrary::SF_NONE) { + if( bReport) CPrintF(TRANS(" (no sound)\n")); + return; + } + + // set wave format from library format + SetWaveFormat( EsfNew, sl.sl_SwfeFormat); + snd_iDevice = Clamp( snd_iDevice, -1L, (INDEX)(sl.sl_ctWaveDevices-1)); + snd_tmMixAhead = Clamp( snd_tmMixAhead, 0.1f, 0.9f); + snd_iInterface = Clamp( snd_iInterface, 0L, 2L); + + BOOL bSoundOK = FALSE; + if( snd_iInterface==2) { + // if wanted, 1st try to set EAX + bSoundOK = StartUp_dsound( sl, bReport); + } + if( !bSoundOK && snd_iInterface==1) { + // if wanted, 2nd try to set DirectSound + bSoundOK = StartUp_dsound( sl, bReport); + } + // if DirectSound failed or not wanted + if( !bSoundOK) { + // try waveout + bSoundOK = StartUp_waveout( sl, bReport); + snd_iInterface = 0; // mark that DirectSound didn't make it + } + + // if didn't make it by now + if( bReport) CPrintF("\n"); + if( !bSoundOK) { + // revert to none in case sound init was unsuccessful + sl.sl_EsfFormat = CSoundLibrary::SF_NONE; + return; + } + // set library format from wave format + SetLibraryFormat(sl); + + // add timer handler + _pTimer->AddHandler(&sl.sl_thTimerHandler); +} + + +/* + * Initialization + */ +void CSoundLibrary::Init(void) +{ + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + // synchronize access to sounds + CTSingleLock slSounds(&sl_csSound, TRUE); + + _pShell->DeclareSymbol( "void SndPostFunc(INDEX);", &SndPostFunc); + + _pShell->DeclareSymbol( " user INDEX snd_bMono;", &snd_bMono); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fEarsDistance;", &snd_fEarsDistance); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fDelaySoundSpeed;", &snd_fDelaySoundSpeed); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fDopplerSoundSpeed;", &snd_fDopplerSoundSpeed); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fPanStrength;", &snd_fPanStrength); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fLRFilter;", &snd_fLRFilter); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fBFilter;", &snd_fBFilter); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fUFilter;", &snd_fUFilter); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fDFilter;", &snd_fDFilter); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fSoundVolume;", &snd_fSoundVolume); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fMusicVolume;", &snd_fMusicVolume); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fNormalizer;", &snd_fNormalizer); + _pShell->DeclareSymbol( "persistent user FLOAT snd_tmMixAhead post:SndPostFunc;", &snd_tmMixAhead); + _pShell->DeclareSymbol( "persistent user INDEX snd_iInterface post:SndPostFunc;", &snd_iInterface); + _pShell->DeclareSymbol( "persistent user INDEX snd_iDevice post:SndPostFunc;", &snd_iDevice); + _pShell->DeclareSymbol( "persistent user INDEX snd_iFormat post:SndPostFunc;", &snd_iFormat); + _pShell->DeclareSymbol( "persistent user INDEX snd_iMaxExtraChannels;", &snd_iMaxExtraChannels); + _pShell->DeclareSymbol( "persistent user INDEX snd_iMaxOpenRetries;", &snd_iMaxOpenRetries); + _pShell->DeclareSymbol( "persistent user FLOAT snd_tmOpenFailDelay;", &snd_tmOpenFailDelay); + _pShell->DeclareSymbol( "persistent user FLOAT snd_fEAXPanning;", &snd_fEAXPanning); + + // print header + CPrintF(TRANS("Initializing sound...\n")); + + // initialize sound library and set no-sound format + SetFormat(SF_NONE); + + // initialize any installed sound decoders + CSoundDecoder::InitPlugins(); + + // get number of devices + INDEX ctDevices = waveOutGetNumDevs(); + CPrintF(TRANS(" Detected devices: %d\n"), ctDevices); + sl_ctWaveDevices = ctDevices; + + // for each device + for(INDEX iDevice=0; iDevicetm_csHooks, TRUE); + // synchronize access to sounds + CTSingleLock slSounds(&sl_csSound, TRUE); + + // clear all sounds and datas buffers + {FOREACHINLIST(CSoundData, sd_Node, sl_ClhAwareList, itCsdStop) { + FOREACHINLIST(CSoundObject, so_Node, (itCsdStop->sd_ClhLinkList), itCsoStop) { + itCsoStop->Stop(); + } + itCsdStop->ClearBuffer(); + }} + + // clear wave out data + ClearLibrary(); + _fLastNormalizeValue = 1; +} + + +/* Clear Library WaveOut */ +void CSoundLibrary::ClearLibrary(void) +{ + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + + // synchronize access to sounds + CTSingleLock slSounds(&sl_csSound, TRUE); + + // remove timer handler if added + if (sl_thTimerHandler.th_Node.IsLinked()) { + _pTimer->RemHandler(&sl_thTimerHandler); + } + + // shut down direct sound buffers (if needed) + ShutDown_dsound(*this); + + // shut down wave out player buffers (if needed) + if( sl_hwoWaveOut!=NULL) + { // reset wave out play buffers (stop playing) + MMRESULT res; + res = waveOutReset(sl_hwoWaveOut); + ASSERT(res == MMSYSERR_NOERROR); + // clear buffers + for( INDEX iBuffer = 0; iBuffer25) iEnvNo=1; + if( fEnvSize<1 || fEnvSize>99) fEnvSize=8; + HRESULT hResult; + hResult = sl_pKSProperty->Set( DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENT, NULL, 0, &iEnvNo, sizeof(DWORD)); + if( hResult != DS_OK) return DSFail( *this, TRANS(" ! EAX error: Cannot set environment.\n")); + hResult = sl_pKSProperty->Set( DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, NULL, 0, &fEnvSize, sizeof(FLOAT)); + if( hResult != DS_OK) return DSFail( *this, TRANS(" ! EAX error: Cannot set environment size.\n")); + return TRUE; +} + + +// mute all sounds (erase playing buffer(s) and supress mixer) +void CSoundLibrary::Mute(void) +{ + // stop all IFeel effects + IFeel_StopEffect(NULL); + + // erase direct sound buffer (waveout will shut-up by itself), but skip if there's no more sound library + if( this==NULL || !sl_bUsingDirectSound) return; + + // synchronize access to sounds + CTSingleLock slSounds(&sl_csSound, TRUE); + + // supress future mixing and erase sound buffer + _bMuted = TRUE; + static LPVOID lpData; + static DWORD dwSize; + + // flush one secondary buffer + if( !DSLockBuffer( *this, sl_pDSSecondary, sl_slMixerBufferSize, lpData, dwSize)) return; + memset( lpData, 0, dwSize); + sl_pDSSecondary->Unlock( lpData, dwSize, NULL, 0); + // if EAX is in use + if( sl_bUsingEAX) { + // flush right buffer, too + if( !DSLockBuffer( *this, sl_pDSSecondary2, sl_slMixerBufferSize, lpData, dwSize)) return; + memset( lpData, 0, dwSize); + sl_pDSSecondary2->Unlock( lpData, dwSize, NULL, 0); + } +} + + + + + +/* + * set sound format + */ +CSoundLibrary::SoundFormat CSoundLibrary::SetFormat( CSoundLibrary::SoundFormat EsfNew, BOOL bReport/*=FALSE*/) +{ + // access to the list of handlers must be locked + CTSingleLock slHooks(&_pTimer->tm_csHooks, TRUE); + // synchronize access to sounds + CTSingleLock slSounds(&sl_csSound, TRUE); + + // pause playing all sounds + {FOREACHINLIST( CSoundData, sd_Node, sl_ClhAwareList, itCsdStop) { + itCsdStop->PausePlayingObjects(); + }} + + // change format and keep console variable states + SetFormat_internal( *this, EsfNew, bReport); + _tmLastMixAhead = snd_tmMixAhead; + _iLastFormat = snd_iFormat; + _iLastDevice = snd_iDevice; + _iLastAPI = snd_iInterface; + + // continue playing all sounds + CListHead lhToReload; + lhToReload.MoveList(sl_ClhAwareList); + {FORDELETELIST( CSoundData, sd_Node, lhToReload, itCsdContinue) { + CSoundData &sd = *itCsdContinue; + if( !(sd.sd_ulFlags&SDF_ENCODED)) { + sd.Reload(); + } else { + sd.sd_Node.Remove(); + sl_ClhAwareList.AddTail(sd.sd_Node); + } + sd.ResumePlayingObjects(); + }} + + // done + return sl_EsfFormat; +} + + + +/* Update all 3d effects and copy internal data. */ +void CSoundLibrary::UpdateSounds(void) +{ + // see if we have valid handle for direct sound and eventually reinit sound + if( sl_bUsingDirectSound && _hwndCurrent!=_hwndMain) { + _hwndCurrent = _hwndMain; + SetFormat( sl_EsfFormat); + } + _bMuted = FALSE; // enable mixer + _sfStats.StartTimer(CStatForm::STI_SOUNDUPDATE); + _pfSoundProfile.StartTimer(CSoundProfile::PTI_UPDATESOUNDS); + + // synchronize access to sounds + CTSingleLock slSounds( &sl_csSound, TRUE); + + // make sure that the buffers are playing + if( sl_bUsingDirectSound) DSPlayBuffers(*this); + + // determine number of listeners and get listener + INDEX ctListeners=0; + CSoundListener *sli; + {FOREACHINLIST( CSoundListener, sli_lnInActiveListeners, _pSound->sl_lhActiveListeners, itsli) { + sli = itsli; + ctListeners++; + }} + // if there's only one listener environment properties have been changed (in split-screen EAX is not supported) + if( ctListeners==1 && (_iLastEnvType!=sli->sli_iEnvironmentType || _fLastEnvSize!=sli->sli_fEnvironmentSize)) { + // keep new properties and eventually update environment (EAX) + _iLastEnvType = sli->sli_iEnvironmentType; + _fLastEnvSize = sli->sli_fEnvironmentSize; + SetEnvironment( _iLastEnvType, _fLastEnvSize); + } + // if there are no listeners - reset environment properties + if( ctListeners<1 && (_iLastEnvType!=1 || _fLastEnvSize!=1.4f)) { + // keep new properties and update environment + _iLastEnvType = 1; + _fLastEnvSize = 1.4f; + SetEnvironment( _iLastEnvType, _fLastEnvSize); + } + + // adjust panning if needed + snd_fEAXPanning = Clamp( snd_fEAXPanning, -1.0f, +1.0f); + if( sl_bUsingEAX && _fLastPanning!=snd_fEAXPanning) + { // determine new panning + _fLastPanning = snd_fEAXPanning; + FLOAT fPanLeft = -1.0f; + FLOAT fPanRight = +1.0f; + if( snd_fEAXPanning<0) fPanRight = MINPAN + Abs(snd_fEAXPanning)*MAXPAN; // pan left + if( snd_fEAXPanning>0) fPanLeft = MINPAN + Abs(snd_fEAXPanning)*MAXPAN; // pan right + // set and apply + HRESULT hr1,hr2,hr3; + hr1 = sl_pDSSourceLeft->SetPosition( fPanLeft, 0,0, DS3D_DEFERRED); + hr2 = sl_pDSSourceRight->SetPosition( fPanRight,0,0, DS3D_DEFERRED); + hr3 = sl_pDSListener->CommitDeferredSettings(); + if( hr1!=DS_OK || hr2!=DS_OK || hr3!=DS_OK) DSFail( *this, TRANS(" ! DirectSound3D error: Cannot set 3D position.\n")); + } + + // for each sound + {FOREACHINLIST( CSoundData, sd_Node, sl_ClhAwareList, itCsdSoundData) { + FORDELETELIST( CSoundObject, so_Node, itCsdSoundData->sd_ClhLinkList, itCsoSoundObject) { + _sfStats.IncrementCounter(CStatForm::SCI_SOUNDSACTIVE); + itCsoSoundObject->Update3DEffects(); + } + }} + + // for each sound + {FOREACHINLIST( CSoundData, sd_Node, sl_ClhAwareList, itCsdSoundData) { + FORDELETELIST( CSoundObject, so_Node, itCsdSoundData->sd_ClhLinkList, itCsoSoundObject) { + CSoundObject &so = *itCsoSoundObject; + // if sound is playing + if( so.so_slFlags&SOF_PLAY) { + // copy parameters + so.so_sp = so.so_spNew; + // prepare sound if not prepared already + if ( !(so.so_slFlags&SOF_PREPARE)) { + so.PrepareSound(); + so.so_slFlags |= SOF_PREPARE; + } + // if it is not playing + } else { + // remove it from list + so.so_Node.Remove(); + } + } + }} + + // remove all listeners + {FORDELETELIST( CSoundListener, sli_lnInActiveListeners, sl_lhActiveListeners, itsli) { + itsli->sli_lnInActiveListeners.Remove(); + }} + + _pfSoundProfile.StopTimer(CSoundProfile::PTI_UPDATESOUNDS); + _sfStats.StopTimer(CStatForm::STI_SOUNDUPDATE); +} + + +/* + * This is called every TickQuantum seconds. + */ +void CSoundTimerHandler::HandleTimer(void) +{ + /* memory leak checking routines + ASSERT( _CrtCheckMemory()); + ASSERT( _CrtIsMemoryBlock( (void*)_pSound->sl_pswDecodeBuffer, + (ULONG)_pSound->sl_slDecodeBufferSize, NULL, NULL, NULL)); + ASSERT( _CrtIsValidPointer( (void*)_pSound->sl_pswDecodeBuffer, + (ULONG)_pSound->sl_slDecodeBufferSize, TRUE)); */ + // mix all needed sounds + _pSound->MixSounds(); +} + + + +/* + * MIXER helper functions + */ + + +// copying of mixer buffer to sound buffer(s) + +static LPVOID _lpData, _lpData2; +static DWORD _dwSize, _dwSize2; + +static void CopyMixerBuffer_dsound( CSoundLibrary &sl, SLONG slMixedSize) +{ + LPVOID lpData; + DWORD dwSize; + SLONG slPart1Size, slPart2Size; + + // if EAX is in use + if( sl.sl_bUsingEAX) + { + // lock left buffer and copy first part of 1st mono block + if( !DSLockBuffer( sl, sl.sl_pDSSecondary, sl.sl_slMixerBufferSize, lpData, dwSize)) return; + slPart1Size = Min( sl.sl_slMixerBufferSize-_iWriteOffset, slMixedSize); + CopyMixerBuffer_mono( 0, ((UBYTE*)lpData)+_iWriteOffset/2, slPart1Size); + // copy second part of 1st mono block + slPart2Size = slMixedSize - slPart1Size; + CopyMixerBuffer_mono( slPart1Size, lpData, slPart2Size); + _iWriteOffset += slMixedSize; + if( _iWriteOffset>=sl.sl_slMixerBufferSize) _iWriteOffset -= sl.sl_slMixerBufferSize; + ASSERT( _iWriteOffset>=0 && _iWriteOffsetUnlock( lpData, dwSize, NULL, 0); + + // lock right buffer and copy first part of 2nd mono block + if( !DSLockBuffer( sl, sl.sl_pDSSecondary2, sl.sl_slMixerBufferSize, lpData, dwSize)) return; + slPart1Size = Min( sl.sl_slMixerBufferSize-_iWriteOffset2, slMixedSize); + CopyMixerBuffer_mono( 2, ((UBYTE*)lpData)+_iWriteOffset2/2, slPart1Size); + // copy second part of 2nd mono block + slPart2Size = slMixedSize - slPart1Size; + CopyMixerBuffer_mono( slPart1Size+2, lpData, slPart2Size); + _iWriteOffset2 += slMixedSize; + if( _iWriteOffset2>=sl.sl_slMixerBufferSize) _iWriteOffset2 -= sl.sl_slMixerBufferSize; + ASSERT( _iWriteOffset2>=0 && _iWriteOffset2Unlock( lpData, dwSize, NULL, 0); + } + // if only standard DSound (no EAX) + else + { + // lock stereo buffer and copy first part of block + if( !DSLockBuffer( sl, sl.sl_pDSSecondary, sl.sl_slMixerBufferSize, lpData, dwSize)) return; + slPart1Size = Min( sl.sl_slMixerBufferSize-_iWriteOffset, slMixedSize); + CopyMixerBuffer_stereo( 0, ((UBYTE*)lpData)+_iWriteOffset, slPart1Size); + // copy second part of block + slPart2Size = slMixedSize - slPart1Size; + CopyMixerBuffer_stereo( slPart1Size, lpData, slPart2Size); + _iWriteOffset += slMixedSize; + if( _iWriteOffset>=sl.sl_slMixerBufferSize) _iWriteOffset -= sl.sl_slMixerBufferSize; + ASSERT( _iWriteOffset>=0 && _iWriteOffsetUnlock( lpData, dwSize, NULL, 0); + } +} + + +static void CopyMixerBuffer_waveout( CSoundLibrary &sl) +{ + MMRESULT res; + SLONG slOffset = 0; + for( INDEX iBuffer = 0; iBufferGetCurrentPosition( &dwCurrentCursor, NULL); + hr2 = sl.sl_pDSSecondary2->GetCurrentPosition( &dwCurrentCursor2, NULL); + if( hr1!=DS_OK || hr2!=DS_OK) return DSFail( sl, TRANS(" ! DirectSound error: Cannot obtain sound buffer write position.\n")); + dwCurrentCursor *=2; // stereo mixer + dwCurrentCursor2*=2; // stereo mixer + // store pointers and wrapped block sizes + SLONG slDataToMix1 = dwCurrentCursor - _iWriteOffset; + if( slDataToMix1<0) slDataToMix1 += sl.sl_slMixerBufferSize; + ASSERT( slDataToMix1>=0 && slDataToMix1<=sl.sl_slMixerBufferSize); + slDataToMix1 = Min( slDataToMix1, sl.sl_slMixerBufferSize); + SLONG slDataToMix2 = dwCurrentCursor2 - _iWriteOffset2; + if( slDataToMix2<0) slDataToMix2 += sl.sl_slMixerBufferSize; + ASSERT( slDataToMix2>=0 && slDataToMix2<=sl.sl_slMixerBufferSize); + slDataToMix = Min( slDataToMix1, slDataToMix2); + } + // if only standard DSound (no EAX) + else + { + hr1 = sl.sl_pDSSecondary->GetCurrentPosition( &dwCurrentCursor, NULL); + if( hr1!=DS_OK) return DSFail( sl, TRANS(" ! DirectSound error: Cannot obtain sound buffer write position.\n")); + // store pointer and wrapped block size + slDataToMix = dwCurrentCursor - _iWriteOffset; + if( slDataToMix<0) slDataToMix += sl.sl_slMixerBufferSize; + ASSERT( slDataToMix>=0 && slDataToMix<=sl.sl_slMixerBufferSize); + slDataToMix = Min( slDataToMix, sl.sl_slMixerBufferSize); + } + + // done + //CPrintF( "LP/LW: %5d / %5d, RP/RW: %5d / %5d, MIX: %5d\n", dwCurrentCursor, _iWriteOffset, dwCurrentCursor2, _iWriteOffset2, slDataToMix); // grgr + return slDataToMix; +} + + +static SLONG PrepareSoundBuffer_waveout( CSoundLibrary &sl) +{ + // scan waveout buffers to find all that are ready to receive sound data (i.e. not playing) + SLONG slDataToMix=0; + for( INDEX iBuffer=0; iBuffer=0); + if( slDataToMix<=0) { + _pfSoundProfile.StopTimer(CSoundProfile::PTI_MIXSOUNDS); + _sfStats.StopTimer(CStatForm::STI_SOUNDMIXING); + return; + } + + // prepare mixer buffer + _pfSoundProfile.IncrementCounter(CSoundProfile::PCI_MIXINGS, 1); + ResetMixer( sl_pslMixerBuffer, slDataToMix); + + BOOL bGamePaused = _pNetwork->IsPaused() || _pNetwork->IsServer() && _pNetwork->GetLocalPause(); + + // for each sound + FOREACHINLIST( CSoundData, sd_Node, sl_ClhAwareList, itCsdSoundData) { + FORDELETELIST( CSoundObject, so_Node, itCsdSoundData->sd_ClhLinkList, itCsoSoundObject) { + CSoundObject &so = *itCsoSoundObject; + // if the sound is in-game sound, and the game paused + if (!(so.so_slFlags&SOF_NONGAME) && bGamePaused) { + // don't mix it it + continue; + } + // if sound is prepared and playing + if( so.so_slFlags&SOF_PLAY && + so.so_slFlags&SOF_PREPARE && + !(so.so_slFlags&SOF_PAUSED)) { + // mix it + MixSound(&so); + } + } + } + + // eventually normalize mixed sounds + snd_fNormalizer = Clamp( snd_fNormalizer, 0.0f, 1.0f); + NormalizeMixerBuffer( snd_fNormalizer, slDataToMix, _fLastNormalizeValue); + + // write mixer buffer to file + // if( !_bOpened) _filMixerBuffer = fopen( "d:\\MixerBufferDump.raw", "wb"); + // fwrite( (void*)sl_pslMixerBuffer, 1, slDataToMix, _filMixerBuffer); + // _bOpened = TRUE; + + // copy mixer buffer to buffers buffer(s) + if( sl_bUsingDirectSound) { // using direct sound + CopyMixerBuffer_dsound( *this, slDataToMix); + } else { // using wave out + CopyMixerBuffer_waveout(*this); + } + + // all done + _pfSoundProfile.StopTimer(CSoundProfile::PTI_MIXSOUNDS); + _sfStats.StopTimer(CStatForm::STI_SOUNDMIXING); +} + + +// +// Sound mode awareness functions +// + +/* + * Add sound in sound aware list + */ +void CSoundLibrary::AddSoundAware(CSoundData &CsdAdd) { + // add sound to list tail + sl_ClhAwareList.AddTail(CsdAdd.sd_Node); +}; + +/* + * Remove a display mode aware object. + */ +void CSoundLibrary::RemoveSoundAware(CSoundData &CsdRemove) { + // remove it from list + CsdRemove.sd_Node.Remove(); +}; + +// listen from this listener this frame +void CSoundLibrary::Listen(CSoundListener &sl) +{ + // just add it to list + if (sl.sli_lnInActiveListeners.IsLinked()) { + sl.sli_lnInActiveListeners.Remove(); + } + sl_lhActiveListeners.AddTail(sl.sli_lnInActiveListeners); +} diff --git a/Sources/Engine/Sound/SoundLibrary.h b/Sources/Engine/Sound/SoundLibrary.h new file mode 100644 index 0000000..08e4043 --- /dev/null +++ b/Sources/Engine/Sound/SoundLibrary.h @@ -0,0 +1,146 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SOUNDLIBRARY_H +#define SE_INCL_SOUNDLIBRARY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + + +#include +#include +#include +#include +#include +#include + +#ifdef PLATFORM_WIN32 /* rcg10042001 */ +#include +#include +#endif + +/* !!! FIXME: rcg10042001 This is going to need OpenAL or SDL_audio... */ + + +// Mixer +// set master volume and resets mixer buffer (wipes it with zeroes and keeps pointers) +void ResetMixer( const SLONG *pslBuffer, const SLONG slBufferSize); +// copy mixer buffer to the output buffer(s) +void CopyMixerBuffer_stereo( const SLONG slSrcOffset, const void *pDstBuffer, const SLONG slBytes); +void CopyMixerBuffer_mono( const SLONG slSrcOffset, const void *pDstBuffer, const SLONG slBytes); +// normalize mixed sounds +void NormalizeMixerBuffer( const FLOAT snd_fNormalizer, const SLONG slBytes, FLOAT &_fLastNormalizeValue); +// mix in one sound object to mixer buffer +void MixSound( class CSoundObject *pso); + + +/* + * Timer handler for sound mixing. + */ +class ENGINE_API CSoundTimerHandler : public CTimerHandler { +public: + /* This is called every TickQuantum seconds. */ + virtual void HandleTimer(void); +}; + +/* + * Sound Library class + */ +class ENGINE_API CSoundLibrary { +public: + enum SoundFormat { + SF_NONE = 0, + SF_11025_16 = 1, + SF_22050_16 = 2, + SF_44100_16 = 3, + SF_ILLEGAL = 4 + }; + +//private: +public: + CTCriticalSection sl_csSound; // sync. access to sounds + CSoundTimerHandler sl_thTimerHandler; // handler for mixing sounds in timer + +/* rcg !!! FIXME: This needs to be abstracted. */ +#ifdef PLATFORM_WIN32 + INDEX sl_ctWaveDevices; // number of devices detected + BOOL sl_bUsingDirectSound; + BOOL sl_bUsingEAX; + HWAVEOUT sl_hwoWaveOut; // wave out handle + CStaticStackArray sl_ahwoExtra; // preventively taken channels + + LPDIRECTSOUND sl_pDS; // direct sound 'handle' + LPKSPROPERTYSET sl_pKSProperty; // for setting properties of EAX + LPDIRECTSOUNDBUFFER sl_pDSPrimary; // and buffers + LPDIRECTSOUNDBUFFER sl_pDSSecondary; // 2D usage + LPDIRECTSOUNDBUFFER sl_pDSSecondary2; + LPDIRECTSOUND3DLISTENER sl_pDSListener; // 3D EAX + LPDIRECTSOUND3DBUFFER sl_pDSSourceLeft; + LPDIRECTSOUND3DBUFFER sl_pDSSourceRight; + + UBYTE *sl_pubBuffersMemory; // memory allocated for the sound buffer(s) output + CStaticArray sl_awhWOBuffers; // the waveout buffers + + SoundFormat sl_EsfFormat; // sound format (external) + WAVEFORMATEX sl_SwfeFormat; // primary sound buffer format + SLONG *sl_pslMixerBuffer; // buffer for mixing sounds (32-bit!) + SWORD *sl_pswDecodeBuffer; // buffer for decoding encoded sounds (ogg, mpeg...) + SLONG sl_slMixerBufferSize; // mixer buffer size + SLONG sl_slDecodeBufferSize; // decoder buffer size + + CListHead sl_ClhAwareList; // list of sound mode aware objects + CListHead sl_lhActiveListeners; // active listeners for current frame of listening + +#else + + SoundFormat sl_EsfFormat; + +#endif + + /* Return library state (active <==> format <> NONE */ + inline BOOL IsActive(void) {return sl_EsfFormat != SF_NONE;}; + /* Clear Library WaveOut */ + void ClearLibrary(void); +public: + /* Constructor */ + CSoundLibrary(void); + /* Destructor */ + ~CSoundLibrary(void); + DECLARE_NOCOPYING(CSoundLibrary); + + /* Initialization */ + void Init(void); + /* Clear Sound Library */ + void Clear(void); + + /* Set Format */ + SoundFormat SetFormat( SoundFormat EsfNew, BOOL bReport=FALSE); + /* Get Format */ + inline SoundFormat GetFormat(void) { return sl_EsfFormat; }; + + /* Update all 3d effects and copy internal data. */ + void UpdateSounds(void); + /* Update Mixer */ + void MixSounds(void); + /* Mute output until next UpdateSounds() */ + void Mute(void); + + /* Set listener enviroment properties (EAX) */ + BOOL SetEnvironment( INDEX iEnvNo, FLOAT fEnvSize=0); + + /* Add sound in sound aware list */ + void AddSoundAware( CSoundData &CsdAdd); + /* Remove a sound mode aware object */ + void RemoveSoundAware( CSoundData &CsdRemove); + + // listen from this listener this frame + void Listen(CSoundListener &sl); +}; + + +// pointer to global sound library object +ENGINE_API extern CSoundLibrary *_pSound; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Sound/SoundListener.h b/Sources/Engine/Sound/SoundListener.h new file mode 100644 index 0000000..f922390 --- /dev/null +++ b/Sources/Engine/Sound/SoundListener.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SOUNDLISTENER_H +#define SE_INCL_SOUNDLISTENER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include + +class CSoundListener { +public: + CListNode sli_lnInActiveListeners; // for linking for current frame of listening + + FLOAT3D sli_vPosition; // listener position + FLOATmatrix3D sli_mRotation; // listener rotation matrix + FLOAT3D sli_vSpeed; // speed of the listener + FLOAT sli_fVolume; // listener volume (i.e. deaf factor) + FLOAT sli_fFilter; // global filter for all sounds on this listener + CEntity *sli_penEntity; // listener entity (for listener local sounds) + INDEX sli_iEnvironmentType; // EAX environment predefine + FLOAT sli_fEnvironmentSize; // EAX environment size +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Sound/SoundMixer.cpp b/Sources/Engine/Sound/SoundMixer.cpp new file mode 100644 index 0000000..88a161f --- /dev/null +++ b/Sources/Engine/Sound/SoundMixer.cpp @@ -0,0 +1,813 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include + +// asm shortcuts +#define O offset +#define Q qword ptr +#define D dword ptr +#define W word ptr +#define B byte ptr + +#define ASMOPT 1 + + +// console variables for volume +extern FLOAT snd_fSoundVolume; +extern FLOAT snd_fMusicVolume; +extern INDEX snd_bMono; + + +// a bunch of local vars coming up + +static SLONG slMixerBufferSampleRate; // quality of destination buffer +static SLONG slMixerBufferSize; // size in samples per channel of the destination buffers +static void *pvMixerBuffer; // pointer to the start of the destination buffers + +static CSoundData *psd; +static SWORD *pswSrcBuffer; +static SLONG slLeftVolume, slRightVolume, slLeftFilter, slRightFilter; +static SLONG slLastLeftSample, slLastRightSample, slSoundBufferSize; +static FLOAT fSoundSampleRate, fPhase; +static FLOAT fOfsDelta, fStep, fLeftStep, fRightStep, fLeftOfs, fRightOfs; +static __int64 fixLeftOfs, fixRightOfs; // fixed integers 32:32 +static __int64 mmSurroundFactor, mmLeftStep, mmRightStep, mmVolumeGain; +static BOOL bNotLoop, bEndOfSound; + +static const FLOAT f65536 = 65536.0f; +static const FLOAT f4G = 4294967296.0f; +static __int64 mmInvFactor = 0x00007FFF00007FFF; +static __int64 mmMaskLD = 0x00000000FFFFFFFF; +static __int64 mmUnsign2Sign = 0x8000800080008000; + + + +// reset mixer buffer (wipes it with zeroes and remembers pointers in static mixer variables) +void ResetMixer( const SLONG *pslBuffer, const SLONG slBufferSize) +{ + // clamp master volumes + snd_fSoundVolume = Clamp(snd_fSoundVolume, 0.0f, 1.0f); + snd_fMusicVolume = Clamp(snd_fMusicVolume, 0.0f, 1.0f); + + // cache local variables + ASSERT( slBufferSize%4==0); + pvMixerBuffer = (void*)pslBuffer; + slMixerBufferSize = slBufferSize /2/2; // because it's stereo and 16-bit dst format + slMixerBufferSampleRate = _pSound->sl_SwfeFormat.nSamplesPerSec; + + // wipe destination mixer buffer + __asm { + cld + xor eax,eax + mov edi,D [pvMixerBuffer] + mov ecx,D [slMixerBufferSize] + shl ecx,1 // *2 because of 32-bit src format + rep stosd + } +} + + +// copy mixer buffer to the output buffer(s) +void CopyMixerBuffer_stereo( const SLONG slSrcOffset, const void *pDstBuffer, const SLONG slBytes) +{ + ASSERT( pDstBuffer!=NULL); + ASSERT( slBytes%4==0); + if( slBytes<4) return; + __asm { + cld + mov esi,D [slSrcOffset] + add esi,D [pvMixerBuffer] + mov edi,D [pDstBuffer] + mov ecx,D [slBytes] + shr ecx,2 // bytes to samples per channel + rep movsd + } +} + + +// copy one channel from mixer buffer to the output buffer(s) +void CopyMixerBuffer_mono( const SLONG slSrcOffset, const void *pDstBuffer, const SLONG slBytes) +{ + ASSERT( pDstBuffer!=NULL); + ASSERT( slBytes%2==0); + if( slBytes<4) return; + __asm { + mov esi,D [slSrcOffset] + add esi,D [pvMixerBuffer] + mov edi,D [pDstBuffer] + mov ecx,D [slBytes] + shr ecx,2 // bytes to samples +copyLoop: + movzx eax,W [esi] + mov W [edi],ax + add esi,4 + add edi,2 + dec ecx + jnz copyLoop + } +} + + +// plain conversion of mixer buffer from 32-bit to 16-bit clamped +static void ConvertMixerBuffer( const SLONG slBytes) +{ + ASSERT( slBytes%4==0); + if( slBytes<4) return; + __asm { + cld + mov esi,D [pvMixerBuffer] + mov edi,D [pvMixerBuffer] + mov ecx,D [slBytes] + shr ecx,2 // bytes to samples (2 channels) +copyLoop: + movq mm0,Q [esi] + packssdw mm0,mm0 + movd D [edi],mm0 + add esi,8 + add edi,4 + dec ecx + jnz copyLoop + emms + } +} + + +// normalize mixer buffer +void NormalizeMixerBuffer( const FLOAT fNormStrength, const SLONG slBytes, FLOAT &fLastNormValue) +{ + // just convert to 16-bit if normalization isn't required + ASSERT( slBytes%4==0); + if( slBytes<8) return; + if( fNormStrength<0.01f) { + ConvertMixerBuffer(slBytes); + return; + } + + // well, I guess we'll might need to normalize a bit, so first - find maximum + INDEX i; + SLONG slPeak = 0; + SLONG *pslSrc = (SLONG*)pvMixerBuffer; + const INDEX iSamples = slBytes/2; // 16-bit was assumed -> samples (treat as mono) + for( i=0; i0.99f && fLastNormValue>0.99f) { // should be enough to tolerate + fLastNormValue = 1.0f; + ConvertMixerBuffer(slBytes); + return; + } + + // adjust normalize value by strength + ASSERT( fNormStrength>=0 && fNormStrength<=1); + fNormValue = Lerp( 1.0f, fNormValue, fNormStrength); + const FLOAT fNormAdd = (fNormValue-fLastNormValue) / (iSamples/4); + + // normalize (and convert to 16-bit) + SWORD *pswDst = (SWORD*)pvMixerBuffer; + FLOAT fCurrentNormValue = fLastNormValue; + for( i=0; ifNormValue && fNormAdd>0) fCurrentNormValue = fNormValue; + } + // CPrintF( "%.5f -> %.5f (%.5f) @ %.9f / %d\n", fLastNormValue, fCurrentNormValue, fNormValue, fNormAdd, iSamples); + // remember normalization value + fLastNormValue = fCurrentNormValue; +} + + + +// mixes one mono 16-bit signed sound to destination buffer +inline void MixMono( CSoundObject *pso) +{ + _pfSoundProfile.StartTimer(CSoundProfile::PTI_RAWMIXER); + +#if ASMOPT == 1 + + __asm { + // convert from floats to fixints 32:16 + fld D [fLeftOfs] + fmul D [f65536] + fld D [fRightOfs] + fmul D [f65536] + fld D [fLeftStep] + fmul D [f65536] + fld D [fRightStep] + fmul D [f4G] + fistp Q [mmRightStep] // fixint 32:32 + fistp Q [mmLeftStep] // fixint 32:16 + fistp Q [fixRightOfs] // fixint 32:16 + fistp Q [fixLeftOfs] // fixint 32:16 + + // get last played sample (for filtering purposes) + movzx eax,W [slLastRightSample] + movzx edx,W [slLastLeftSample] + shl eax,16 + or eax,edx + movd mm6,eax // MM6 = 0 | 0 || lastRightSample | lastLeftSample + + // get volume + movd mm5,D [slRightVolume] + movd mm0,D [slLeftVolume] + psllq mm5,32 + por mm5,mm0 // MM5 = rightVolume || leftVolume + + // get filter + mov eax,D [slRightFilter] + mov edx,D [slLeftFilter] + shl eax,16 + or eax,edx + movd mm7,eax // MM7 = 0 | 0 || rightFilter | leftFilter + + // get offset of each channel inside sound and loop thru destination buffer + mov W [mmRightStep],0 + movzx eax,W [fixLeftOfs] + movzx edx,W [fixRightOfs] + shl edx,16 + or eax,edx // EAX = right ofs frac | left ofs frac + mov ebx,D [fixLeftOfs+2] // EBX = left ofs int + mov edx,D [fixRightOfs+2] // EDX = right ofs int + mov esi,D [pswSrcBuffer] // ESI = source sound buffer start ptr + mov edi,D [pvMixerBuffer] // EDI = mixer buffer ptr + mov ecx,D [slMixerBufferSize] // ECX = samples counter + +sampleLoop: + // check if source offsets came to the end of source sound buffer + cmp ebx,D [slSoundBufferSize] + jl lNotEnd + sub ebx,D [slSoundBufferSize] + push D [bNotLoop] + pop D [bEndOfSound] +lNotEnd: + // same for right channel + cmp edx,D [slSoundBufferSize] + jl rNotEnd + sub edx,D [slSoundBufferSize] + push D [bNotLoop] + pop D [bEndOfSound] +rNotEnd: + + // check end of sample + cmp ecx,0 + jle loopEnd + cmp D [bEndOfSound],TRUE + je loopEnd + + // get sound samples + movd mm1,D [esi+ ebx*2] // MM1 = 0 | 0 || nextLeftSample | leftSample + movd mm2,D [esi+ edx*2] // MM2 = 0 | 0 || nextRightSample | RightSample + psllq mm2,32 + por mm1,mm2 // MM1 = nextRightSample | rightSample || nextLeftSample | leftSample + + // calc linear interpolation factor (strength) + movd mm3,eax // MM3 = 0 | 0 || right frac | left frac + punpcklwd mm3,mm3 + psrlw mm3,1 // MM3 = rightFrac | rightFrac || leftFrac | leftFrac + pxor mm3,Q [mmInvFactor] // MM3 = rightFrac | 1-rightFrac || leftFrac | 1-leftFrac + // apply linear interpolation + pmaddwd mm1,mm3 + psrad mm1,15 + packssdw mm1,mm1 // MM1 = ? | ? || linearRightSample | linearLeftSample + + // apply filter + psubsw mm1,mm6 + pmulhw mm1,mm7 + psllw mm1,1 + paddsw mm1,mm6 + movq mm6,mm1 + + // apply volume adjustment + movq mm0,mm5 + psrad mm0,16 + packssdw mm0,mm0 + pmulhw mm1,mm0 + psllw mm1,1 + pxor mm1,Q [mmSurroundFactor] + paddd mm5,Q [mmVolumeGain] // modify volume + + // unpack to 32bit and mix it into destination buffer + punpcklwd mm1,mm1 + psrad mm1,16 // MM1 = finalRightSample || finalLeftSample + paddd mm1,Q [edi] + movq Q [edi],mm1 + + // advance to next samples in source sound + add eax,D [mmRightStep+0] + adc edx,D [mmRightStep+4] + add ax,W [mmLeftStep +0] + adc ebx,D [mmLeftStep +2] + add edi,8 + dec ecx + jmp sampleLoop + +loopEnd: + // store modified asm local vars + mov D [fixLeftOfs +0],eax + shr eax,16 + mov D [fixRightOfs+0],eax + mov D [fixLeftOfs +2],ebx + mov D [fixRightOfs+2],edx + movd eax,mm6 + mov edx,eax + and eax,0x0000FFFF + shr edx,16 + mov D [slLastLeftSample],eax + mov D [slLastRightSample],edx + emms + } + +#else + + // initialize some local vars + SLONG slLeftSample, slRightSample, slNextSample; + SLONG *pslDstBuffer = (SLONG*)pvMixerBuffer; + fixLeftOfs = (__int64)(fLeftOfs * 65536.0); + fixRightOfs = (__int64)(fRightOfs * 65536.0); + __int64 fixLeftStep = (__int64)(fLeftStep * 65536.0); + __int64 fixRightStep = (__int64)(fRightStep * 65536.0); + __int64 fixSoundBufferSize = ((__int64)slSoundBufferSize)<<16; + mmSurroundFactor = (__int64)(SWORD)mmSurroundFactor; + + // loop thru source buffer + INDEX iCt = slMixerBufferSize; + FOREVER + { + // if left channel source sample came to end of sample buffer + if( fixLeftOfs >= fixSoundBufferSize) { + fixLeftOfs -= fixSoundBufferSize; + // if has no loop, end it + bEndOfSound = bNotLoop; + } + // if right channel source sample came to end of sample buffer + if( fixRightOfs >= fixSoundBufferSize) { + fixRightOfs -= fixSoundBufferSize; + // if has no loop, end it + bEndOfSound = bNotLoop; + } + // end of buffer? + if( iCt<=0 || bEndOfSound) break; + + // fetch one lineary interpolated sample on left channel + slLeftSample = pswSrcBuffer[(fixLeftOfs>>16)+0]; + slNextSample = pswSrcBuffer[(fixLeftOfs>>16)+1]; + slLeftSample = (slLeftSample*(65535-(fixLeftOfs&65535)) + slNextSample*(fixLeftOfs&65535)) >>16; + // fetch one lineary interpolated sample on right channel + slRightSample = pswSrcBuffer[(fixRightOfs>>16)+0]; + slNextSample = pswSrcBuffer[(fixRightOfs>>16)+1]; + slRightSample = (slRightSample*(65535-(fixRightOfs&65535)) + slNextSample*(fixRightOfs&65535)) >>16; + + // filter samples + slLastLeftSample += ((slLeftSample -slLastLeftSample) *slLeftFilter) >>15; + slLastRightSample += ((slRightSample-slLastRightSample)*slRightFilter)>>15; + + // apply stereo volume to current sample + slLeftSample = (slLastLeftSample * slLeftVolume) >>15; + slRightSample = (slLastRightSample * slRightVolume)>>15; + + slRightSample = slRightSample ^ mmSurroundFactor; + + // mix in current sample + slLeftSample += pslDstBuffer[0]; + slRightSample += pslDstBuffer[1]; + // upper clamp + if( slLeftSample > MAX_SWORD) slLeftSample = MAX_SWORD; + if( slRightSample > MAX_SWORD) slRightSample = MAX_SWORD; + // lower clamp + if( slLeftSample < MIN_SWORD) slLeftSample = MIN_SWORD; + if( slRightSample < MIN_SWORD) slRightSample = MIN_SWORD; + + // store samples (both channels) + pslDstBuffer[0] = slLeftSample; + pslDstBuffer[1] = slRightSample; + + // modify volume ` + slLeftVolume += (SWORD)((mmVolumeGain>> 0)&0xFFFF); + slRightVolume += (SWORD)((mmVolumeGain>>16)&0xFFFF); + + // advance to next sample + fixLeftOfs += fixLeftStep; + fixRightOfs += fixRightStep; + pslDstBuffer += 4; + iCt--; + } + +#endif + + _pfSoundProfile.StopTimer(CSoundProfile::PTI_RAWMIXER); +} + + +// mixes one stereo 16-bit signed sound to destination buffer +inline void MixStereo( CSoundObject *pso) +{ + _pfSoundProfile.StartTimer(CSoundProfile::PTI_RAWMIXER); + +#if ASMOPT == 1 + + __asm { + // convert from floats to fixints 32:16 + fld D [fLeftOfs] + fmul D [f65536] + fld D [fRightOfs] + fmul D [f65536] + fld D [fLeftStep] + fmul D [f65536] + fld D [fRightStep] + fmul D [f4G] + fistp Q [mmRightStep] // fixint 32:32 + fistp Q [mmLeftStep] // fixint 32:16 + fistp Q [fixRightOfs] // fixint 32:16 + fistp Q [fixLeftOfs] // fixint 32:16 + + // get last played sample (for filtering purposes) + movzx eax,W [slLastRightSample] + movzx edx,W [slLastLeftSample] + shl eax,16 + or eax,edx + movd mm6,eax // MM6 = 0 | 0 || lastRightSample | lastLeftSample + + // get volume + movd mm5,D [slRightVolume] + movd mm0,D [slLeftVolume] + psllq mm5,32 + por mm5,mm0 // MM5 = rightVolume || leftVolume + + // get filter + mov eax,D [slRightFilter] + mov edx,D [slLeftFilter] + shl eax,16 + or eax,edx + movd mm7,eax // MM7 = 0 | 0 || rightFilter | leftFilter + + // get offset of each channel inside sound and loop thru destination buffer + mov W [mmRightStep],0 + movzx eax,W [fixLeftOfs] + movzx edx,W [fixRightOfs] + shl edx,16 + or eax,edx // EAX = right ofs frac | left ofs frac + mov ebx,D [fixLeftOfs+2] // EBX = left ofs int + mov edx,D [fixRightOfs+2] // EDX = right ofs int + mov esi,D [pswSrcBuffer] // ESI = source sound buffer start ptr + mov edi,D [pvMixerBuffer] // EDI = mixer buffer ptr + mov ecx,D [slMixerBufferSize] // ECX = samples counter + +sampleLoop: + // check if source offsets came to the end of source sound buffer + cmp ebx,D [slSoundBufferSize] + jl lNotEnd + sub ebx,D [slSoundBufferSize] + push D [bNotLoop] + pop D [bEndOfSound] +lNotEnd: + // same for right channel + cmp edx,D [slSoundBufferSize] + jl rNotEnd + sub edx,D [slSoundBufferSize] + push D [bNotLoop] + pop D [bEndOfSound] +rNotEnd: + + // check end of sample + cmp ecx,0 + jle loopEnd + cmp D [bEndOfSound],TRUE + je loopEnd + + // get sound samples + movq mm1,Q [esi+ ebx*4] + movq mm2,Q [esi+ edx*4] + pslld mm1,16 + psrad mm1,16 // MM1 = 0 | nextLeftSample || 0 | leftSample + psrad mm2,16 // MM2 = 0 | nextRightSample || 0 | rightSample + packssdw mm1,mm2 // MM1 = nextRightSample | rightSample || nextLeftSample | leftSample + + // calc linear interpolation factor (strength) + movd mm3,eax // MM3 = 0 | 0 || right frac | left frac + punpcklwd mm3,mm3 + psrlw mm3,1 // MM3 = rightFrac | rightFrac || leftFrac | leftFrac + pxor mm3,Q [mmInvFactor] // MM3 = rightFrac | 1-rightFrac || leftFrac | 1-leftFrac + // apply linear interpolation + pmaddwd mm1,mm3 + psrad mm1,15 + packssdw mm1,mm1 // MM1 = ? | ? || linearRightSample | linearLeftSample + + // apply filter + psubsw mm1,mm6 + pmulhw mm1,mm7 + psllw mm1,1 + paddsw mm1,mm6 + movq mm6,mm1 + + // apply volume adjustment + movq mm0,mm5 + psrad mm0,16 + packssdw mm0,mm0 + pmulhw mm1,mm0 + psllw mm1,1 + pxor mm1,Q [mmSurroundFactor] + paddd mm5,Q [mmVolumeGain] // modify volume + + // unpack to 32bit and mix it into destination buffer + punpcklwd mm1,mm1 + psrad mm1,16 // MM1 = finalRightSample || finalLeftSample + paddd mm1,Q [edi] + movq Q [edi],mm1 + + // advance to next samples in source sound + add eax,D [mmRightStep+0] + adc edx,D [mmRightStep+4] + add ax,W [mmLeftStep +0] + adc ebx,D [mmLeftStep +2] + add edi,8 + dec ecx + jmp sampleLoop + +loopEnd: + // store modified asm local vars + mov D [fixLeftOfs +0],eax + shr eax,16 + mov D [fixRightOfs+0],eax + mov D [fixLeftOfs +2],ebx + mov D [fixRightOfs+2],edx + movd eax,mm6 + mov edx,eax + and eax,0x0000FFFF + shr edx,16 + mov D [slLastLeftSample],eax + mov D [slLastRightSample],edx + emms + } + +#endif + + _pfSoundProfile.StopTimer(CSoundProfile::PTI_RAWMIXER); +} + + +// mixes one sound to destination buffer +void MixSound( CSoundObject *pso) +{ + psd = pso->so_pCsdLink; + + // if don't mix encoded sounds if they are not opened properly + if((psd->sd_ulFlags&SDF_ENCODED) && + (pso->so_psdcDecoder==NULL || !pso->so_psdcDecoder->IsOpen()) ) { + return; + } + + // check for supported sound formats + const SLONG slChannels = pso->so_pCsdLink->sd_wfeFormat.nChannels; + const SLONG slBytes = pso->so_pCsdLink->sd_wfeFormat.wBitsPerSample/8; + // unsupported sound formats will be ignored + if( (slChannels!=1 && slChannels!=2) || slBytes!=2) return; + + // check for delay + const FLOAT f1oMixerBufferSampleRate = 1.0f / slMixerBufferSampleRate; + const FLOAT fSecondsToMix = (FLOAT)slMixerBufferSize * f1oMixerBufferSampleRate; + pso->so_fDelayed += fSecondsToMix; + if( pso->so_fDelayed < pso->so_sp.sp_fDelay) { + _pfSoundProfile.IncrementCounter(CSoundProfile::PCI_SOUNDSDELAYED, 1); + return; + } + // playing started, so skip further delays + pso->so_fDelayed = 9999.9999f; + + // reach sound data and determine sound step, sound buffer and buffer size + pswSrcBuffer = psd->sd_pswBuffer; + fSoundSampleRate = psd->sd_wfeFormat.nSamplesPerSec * pso->so_sp.sp_fPitchShift; + fStep = fSoundSampleRate * f1oMixerBufferSampleRate; + fLeftStep = fStep; + fRightStep = fStep; + slSoundBufferSize = psd->sd_slBufferSampleSize; + // eliminate potentional "puck" at the of sample that hasn't loop + if( !(pso->so_slFlags&SOF_LOOP) && slSoundBufferSize>1) slSoundBufferSize--; + + // get old and new volumes + FLOAT fLeftVolume = ClampDn( pso->so_fLastLeftVolume, 0.0f); + FLOAT fRightVolume = ClampDn( pso->so_fLastRightVolume, 0.0f); + FLOAT fNewLeftVolume = ClampDn( pso->so_sp.sp_fLeftVolume, 0.0f); + FLOAT fNewRightVolume = ClampDn( pso->so_sp.sp_fRightVolume, 0.0f); + + // adjust for master volume + if(pso->so_slFlags&SOF_MUSIC) { + fNewLeftVolume *= snd_fMusicVolume; + fNewRightVolume *= snd_fMusicVolume; + } else { + fNewLeftVolume *= snd_fSoundVolume; + fNewRightVolume *= snd_fSoundVolume; + } + + // if both channel volumes are too low + if( fLeftVolume<0.001f && fRightVolume<0.001f && fNewLeftVolume<0.001f && fNewRightVolume<0.001f) + { + // if this is not an encoded sound + if( !(psd->sd_ulFlags&SDF_ENCODED) ) { + // skip mixing of this sample segment + fOfsDelta = fStep*slMixerBufferSampleRate*fSecondsToMix; + pso->so_fLeftOffset += fOfsDelta; + pso->so_fRightOffset += fOfsDelta; + const FLOAT fMinOfs = Min( pso->so_fLeftOffset, pso->so_fRightOffset); + ASSERT( fMinOfs>=0); + if( fMinOfs<0) CPrintF( "BUG: negative offset (%.2g) encountered in sound: '%s' !\n", fMinOfs, (CTString&)psd->GetName()); + // if looping + if (pso->so_slFlags & SOF_LOOP) { + // adjust offset ptrs inside sound + while( pso->so_fLeftOffset < 0) pso->so_fLeftOffset += slSoundBufferSize; + while( pso->so_fRightOffset < 0) pso->so_fRightOffset += slSoundBufferSize; + while( pso->so_fLeftOffset >= slSoundBufferSize) pso->so_fLeftOffset -= slSoundBufferSize; + while( pso->so_fRightOffset >= slSoundBufferSize) pso->so_fRightOffset -= slSoundBufferSize; + // if not looping + } else { + // no more playing + pso->so_slFlags &= ~SOF_PLAY; + pso->so_fDelayed = 0.0f; + pso->so_sp.sp_fDelay = 0.0f; + } + } + // reset last samples + pso->so_swLastLeftSample = 0; + pso->so_swLastRightSample = 0; + // update volume + pso->so_fLastLeftVolume = fNewLeftVolume; + pso->so_fLastRightVolume = fNewRightVolume; + + _pfSoundProfile.IncrementCounter(CSoundProfile::PCI_SOUNDSSKIPPED, 1); + return; + } + _sfStats.IncrementCounter(CStatForm::SCI_SOUNDSMIXING); + + // cache sound object vars + fPhase = pso->so_sp.sp_fPhaseShift; + fLeftOfs = pso->so_fLeftOffset; + fRightOfs = pso->so_fRightOffset; + fOfsDelta = pso->so_fOffsetDelta; + slLeftVolume = FloatToInt(fLeftVolume * 65536*32767.0f); + slRightVolume = FloatToInt(fRightVolume * 65536*32767.0f); + const FLOAT fMixBufSize = 65536*32767.0f / slMixerBufferSize; + const SLONG slLeftGain = FloatToInt( (fNewLeftVolume -fLeftVolume) *fMixBufSize); + const SLONG slRightGain = FloatToInt( (fNewRightVolume-fRightVolume) *fMixBufSize); + mmVolumeGain = ((__int64)(slRightGain)<<32) | ((__int64)(slLeftGain)&0xFFFFFFFF); + // extrapolate back new volumes because of not enough precision in interpolation! + // (otherwise we might hear occasional pucks) + if( fNewLeftVolume >0.001f) fNewLeftVolume = (slLeftVolume + slLeftGain *slMixerBufferSize) /(65536*32767.0f); + if( fNewRightVolume>0.001f) fNewRightVolume = (slRightVolume + slRightGain*slMixerBufferSize) /(65536*32767.0f); + //ASSERT( fNewLeftVolume>=0 && fNewRightVolume>=0); + //CPrintF( "NV: %.4f / %.4f, GV: %.4f / %.4f\n", fNewLeftVolume,fNewRightVolume, fLeftGainedVolume,fRightGainedVolume); + + // determine filtering and surround + slLeftFilter = pso->so_sp.sp_slLeftFilter; + slRightFilter = pso->so_sp.sp_slRightFilter; + bNotLoop = !(pso->so_slFlags & SOF_LOOP); + mmSurroundFactor = 0; + if( pso->so_slFlags & SOF_SURROUND) mmSurroundFactor = 0x0000FFFF; + + // if this is an encoded sound + BOOL bDecodingFinished = FALSE; + if( psd->sd_ulFlags&SDF_ENCODED) { + _pfSoundProfile.StartTimer(CSoundProfile::PTI_DECODESOUND); + // decode some samples from it + SLONG slWantedBytes = FloatToInt(slMixerBufferSize*fStep*pso->so_pCsdLink->sd_wfeFormat.nChannels) *2; + void *pvDecodeBuffer = _pSound->sl_pswDecodeBuffer; + ASSERT(slWantedBytes<=_pSound->sl_slDecodeBufferSize); + SLONG slDecodedBytes = pso->so_psdcDecoder->Decode( pvDecodeBuffer, slWantedBytes); + ASSERT(slDecodedBytes<=slWantedBytes); + // if it has a loop + if (!bNotLoop) { + // if sound is shorter than buffer + while(slDecodedBytesso_psdcDecoder->Reset(); + slDecodedBytes += pso->so_psdcDecoder->Decode( ((UBYTE*)pvDecodeBuffer) + + slDecodedBytes, slWantedBytes-slDecodedBytes); + } + // if it doesn't have a loop + } else { + // if sound is shorter than buffer + if(slDecodedBytes>2; // convert to samples + fLeftOfs = 0.0f; + fRightOfs = 0.0f; + fPhase = 0.0f; + + _pfSoundProfile.StopTimer(CSoundProfile::PTI_DECODESOUND); + } + + _pfSoundProfile.IncrementCounter(CSoundProfile::PCI_SOUNDSMIXED, 1); + _pfSoundProfile.IncrementCounter(CSoundProfile::PCI_SAMPLES, slMixerBufferSize); + + _pfSoundProfile.StartTimer(CSoundProfile::PTI_MIXSOUND); + + slLastLeftSample = pso->so_swLastLeftSample; + slLastRightSample = pso->so_swLastRightSample; + + // calculate eventual new offsets from phase shift + FLOAT fLastPhase = fOfsDelta / fSoundSampleRate; + FLOAT fPhaseDelta = fPhase - fLastPhase; + FLOAT fStepDelta = Abs( fPhaseDelta*fSoundSampleRate / slMixerBufferSize); + + FLOAT fStepDeltaL, fStepDeltaR; + if( fPhaseDelta>0) { + fStepDeltaL = fStepDelta/2; + if( fStepDeltaL>fLeftStep/2) fStepDeltaL = fLeftStep/2; + fStepDeltaL = -fStepDeltaL; + fStepDeltaR = fStepDelta + fStepDeltaL; + } else { + fStepDeltaR = fStepDelta/2; + if( fStepDeltaR>fLeftStep/2) fStepDeltaR = fLeftStep/2; + fStepDeltaR = -fStepDeltaR; + fStepDeltaL = fStepDelta + fStepDeltaR; + } + fLeftStep += fStepDeltaL; + fRightStep += fStepDeltaR; + fStepDelta = fStepDeltaR-fStepDeltaL; + + // if there is anything to mix (could be nothing when encoded file just finished) + if( slSoundBufferSize>0) { + // safety check (needed because of bad-bug!) + FLOAT fMinOfs = Min( fLeftOfs, fRightOfs); + ASSERT( fMinOfs>=0); + if( fMinOfs<0) CPrintF( "BUG: negative offset (%.2g) encountered in sound: '%s' !\n", fMinOfs, (CTString&)psd->GetName()); + // adjust offset ptrs inside sound to match those of phase shift + while( fLeftOfs < 0) fLeftOfs += slSoundBufferSize; + while( fRightOfs < 0) fRightOfs += slSoundBufferSize; + while( fLeftOfs >= slSoundBufferSize) fLeftOfs -= slSoundBufferSize; + while( fRightOfs >= slSoundBufferSize) fRightOfs -= slSoundBufferSize; + + // if mono output is required + if( snd_bMono) { + // monomize channels (cool word:) + fLeftOfs = (fLeftOfs+fRightOfs)/2; + fRightOfs = fLeftOfs; + fLeftStep = (fLeftStep+fRightStep)/2; + fRightStep = fLeftStep; + slLeftVolume = (slLeftVolume+slRightVolume)/2; + slRightVolume = slLeftVolume; + slLeftFilter = (slLeftFilter+slRightFilter)/2; + slRightFilter = slLeftFilter; + } + + // call corresponding mixer routine for current sound format + bEndOfSound = FALSE; + if( slChannels==2) { + // mix as 16-bit stereo + MixStereo( pso); + } else { + // mix as 16-bit mono + MixMono( pso); + } + } + + // if encoded sound + if( psd->sd_ulFlags&SDF_ENCODED) { + // ignore mixing finished flag, but use decoding finished flag + bEndOfSound = bDecodingFinished; + } + + // if sound ended, not buffer + if( bEndOfSound) { + // reset some sound vars + slLastLeftSample = 0; + slLastRightSample = 0; + pso->so_slFlags &= ~SOF_PLAY; + pso->so_fDelayed = 0.0f; + pso->so_sp.sp_fDelay = 0.0f; + } + + // rememer last samples for the next mix in + pso->so_swLastLeftSample = (SWORD)slLastLeftSample; + pso->so_swLastRightSample = (SWORD)slLastRightSample; + // determine new phase shift offset + pso->so_fOffsetDelta += fStepDelta*slMixerBufferSize; + // update play offset for the next mix iteration + pso->so_fLeftOffset = fixLeftOfs * (1.0f/65536.0f); + pso->so_fRightOffset = fixRightOfs * (1.0f/65536.0f); + // update volume + pso->so_fLastLeftVolume = fNewLeftVolume; + pso->so_fLastRightVolume = fNewRightVolume; + + //if( pso->so_fLastLeftVolume>0 || pso->so_fLastRightVolume>0 || fNewLeftVolume>0 || fNewRightVolume>0) { + // CPrintF( "SO: 0x%8X; OV: %.4f / %.4f, NV: %.4f / %.4f\n", pso, + // pso->so_fLastLeftVolume,pso->so_fLastRightVolume, fNewLeftVolume,fNewRightVolume); + //} + _pfSoundProfile.StopTimer(CSoundProfile::PTI_MIXSOUND); +} + diff --git a/Sources/Engine/Sound/SoundObject.cpp b/Sources/Engine/Sound/SoundObject.cpp new file mode 100644 index 0000000..82d6e2f --- /dev/null +++ b/Sources/Engine/Sound/SoundObject.cpp @@ -0,0 +1,695 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +// sound event codes for prediction +#define EVENT_SOUNDPLAY 0x0101 +#define EVENT_SOUNDSTOP 0x0102 +#define EVENT_SOUNDSETOFFSET 0x0103 + +extern FLOAT snd_fEarsDistance; +extern FLOAT snd_fDelaySoundSpeed; +extern FLOAT snd_fDopplerSoundSpeed; +extern FLOAT snd_fPanStrength; +extern FLOAT snd_fLRFilter; +extern FLOAT snd_fBFilter; +extern FLOAT snd_fUFilter; +extern FLOAT snd_fDFilter; + +extern BOOL _bPredictionActive; + +// console variables for volume +extern FLOAT snd_fSoundVolume; +extern FLOAT snd_fMusicVolume; + +static CTString GetPred(CEntity*pen) +{ + CTString str1; + if (pen->IsPredictor()) { + str1 = "predictor"; + } else if (pen->IsPredicted()) { + str1 = "predicted"; + } else if (pen->en_ulFlags & ENF_WILLBEPREDICTED) { + str1 = "will be predicted"; + } else { + str1 = "???"; + } + CTString str; + str.PrintF("%08x-%s", pen, str1); + return str; +} +/* ==================================================== + * + * Class global methods + */ + +/* + * Constructor + */ +CSoundObject::CSoundObject() +{ + so_pCsdLink = NULL; + so_psdcDecoder = NULL; + so_penEntity = NULL; + so_slFlags = 0; + + // clear sound settings + so_spNew.sp_fLeftVolume = 1.0f; + so_spNew.sp_fRightVolume = 1.0f; + so_spNew.sp_slLeftFilter = 0x7FFF; + so_spNew.sp_slRightFilter = 0x7FFF; + so_spNew.sp_fPitchShift = 1.0f; + so_spNew.sp_fPhaseShift = 0.0f; + so_spNew.sp_fDelay = 0.0f; + + so_sp = so_spNew; + + so_fLeftOffset = 0.0f; + so_fRightOffset = 0.0f; + so_fOffsetDelta = 0.0f; + so_fDelayed = 0.0f; + so_fLastLeftVolume = 1.0f; + so_fLastRightVolume = 1.0f; + so_swLastLeftSample = 0; + so_swLastRightSample = 0; + + // 3d effects + so_sp3.sp3_fFalloff = 0.0f; + so_sp3.sp3_fHotSpot = 0.0f; + so_sp3.sp3_fMaxVolume = 0.0f; + so_sp3.sp3_fPitch = 1.0f; +}; + +/* + * Destructor + */ +CSoundObject::~CSoundObject() +{ + Stop_internal(); +}; + +// copy from another object of same class +void CSoundObject::Copy(CSoundObject &soOther) +{ + Stop_internal(); + so_sp = so_spNew = soOther.so_sp; + so_sp3 = soOther.so_sp3; + so_penEntity = NULL; + so_slFlags = soOther.so_slFlags; + if (soOther.so_slFlags&SOF_PLAY) { + Play(soOther.so_pCsdLink, soOther.so_slFlags); + } +} + +// Set 3D parameters +void CSoundObject::Set3DParameters( FLOAT fFalloff, FLOAT fHotSpot, + FLOAT fMaxVolume, FLOAT fPitch) +{ + ASSERT( (fFalloff > 0) && (fHotSpot >= 0)); + ASSERT( fMaxVolume >= 0); + ASSERT( fFalloff >= fHotSpot); + ASSERT( fPitch > 0); + + CSoundObject *pso = this; + // if the sound's entity is a predictor + if (_bPredictionActive && so_penEntity!=NULL) { + if (so_penEntity->IsPredictionHead()) { + // get your prediction tail + //CPrintF("SET3D: "); + CEntity *pen = so_penEntity->GetPredictionTail(); + if (pen!=so_penEntity) { + pso = (CSoundObject *)( ((UBYTE*)pen) + (int(this)-int(so_penEntity)) ); + } + } + } + + pso->so_sp3.sp3_fFalloff = fFalloff; + pso->so_sp3.sp3_fHotSpot = fHotSpot; + pso->so_sp3.sp3_fMaxVolume = fMaxVolume; + pso->so_sp3.sp3_fPitch = fPitch; +}; + + +/* ==================================================== + * Sound control methods + */ + +// get proper sound object for predicted events - return NULL the event is already predicted +CSoundObject *CSoundObject::GetPredictionTail(ULONG ulTypeID, ULONG ulEventID) +{ + // if the sound has an entity + if (so_penEntity!=NULL) { + //CPrintF(" {%s}", GetPred(so_penEntity)); + // if the entity is temporary predictor + if (so_penEntity->GetFlags()&ENF_TEMPPREDICTOR) { + //CPrintF(" temppred\n"); + // it must not play the sound + return NULL; + } + SLONG slOffset = int(this)-int(so_penEntity); + + ULONG ulCRC; + CRC_Start(ulCRC); + CRC_AddLONG(ulCRC, slOffset); + CRC_AddLONG(ulCRC, ulTypeID); + CRC_Finish(ulCRC); + + // if the event is predicted + if (so_penEntity->CheckEventPrediction(ulCRC, ulEventID)) { + //CPrintF(" predicted\n"); + // return nothing + return NULL; + } + CEntity *pen = so_penEntity; + // find eventual prediction tail sound object + if (pen->IsPredictor()) { + pen = pen->GetPredictionTail(); + if (pen!=so_penEntity) { + //CPrintF(" ROUTED\n"); + return (CSoundObject *)( ((UBYTE*)pen) + slOffset ); + } + } + } + // if no specific prediction states - use this object + //CPrintF(" ORIGINAL\n"); + return this; +} +/* + * Play + */ +void CSoundObject::Play(CSoundData *pCsdLink, SLONG slFlags) +{ + // synchronize access to sounds + CTSingleLock slSounds( &_pSound->sl_csSound, TRUE); + + //CPrintF("PLAY: '%s'", (const char*)pCsdLink->GetName().FileName()); + // get prediction tail + CSoundObject *psoTail = GetPredictionTail(EVENT_SOUNDPLAY, (ULONG)pCsdLink); + // if the event is predicted + if (psoTail==NULL) { + // do nothing; + return; + } + + // play the sound in the given object + psoTail->Play_internal(pCsdLink, slFlags); +} + +// play sound - internal function - doesn't account for prediction +void CSoundObject::Play_internal( CSoundData *pCsdLink, SLONG slFlags) +{ + ASSERT(so_penEntity==NULL || !so_penEntity->IsPredictor()); + + // check if should continue with new sound + BOOL bContinue = + ((slFlags&SOF_SMOOTHCHANGE) && + (so_slFlags&SOF_PREPARE) && + (so_slFlags&SOF_PLAY)); + + Stop_internal(); + + // mark new data as referenced once more + pCsdLink->AddReference(); + // mark old data as referenced once less + so_pCsdLink->RemReference(); + + // store init SoundData + so_pCsdLink = pCsdLink; + // add to link list + so_pCsdLink->AddObjectLink(*this); + + // store flags + so_slFlags = slFlags; + + // if should continue with new sound + if (bContinue) { + // play buffer immediately + so_slFlags = so_slFlags | SOF_PREPARE | SOF_PLAY; + } else { + // play buffer + so_slFlags = (so_slFlags & ~(SOF_PREPARE|SOF_PAUSED)) | SOF_PLAY; + } + + // if the sound data is encoded + if (so_pCsdLink->sd_ulFlags&SDF_ENCODED) { + // create decoder + if (so_pCsdLink->sd_ulFlags&SDF_STREAMING) { + so_psdcDecoder = new CSoundDecoder(so_pCsdLink->GetName()); + } else { + ASSERT(FALSE); // nonstreaming not supported anymore + } + } + + // remember starting parameters + so_sp = so_spNew; + + // initialize mixer temporary variables + if (!(slFlags&SOF_LOADED)) { + so_fLastLeftVolume = so_sp.sp_fLeftVolume; + so_fLastRightVolume = so_sp.sp_fRightVolume; + so_fLeftOffset = 0.0f; + so_fRightOffset = 0.0f; + so_fOffsetDelta = 0.0f; + so_fDelayed = 0.0f; + if (!bContinue) { + so_swLastLeftSample = 0; + so_swLastRightSample = 0; + } else { + // adjust for master volume + if(so_slFlags&SOF_MUSIC) { + so_fLastLeftVolume *= snd_fMusicVolume; + so_fLastRightVolume *= snd_fMusicVolume; + } else { + so_fLastLeftVolume *= snd_fSoundVolume; + so_fLastRightVolume *= snd_fSoundVolume; + } + } + } +} + + +// hard set sound offset in seconds +void CSoundObject::SetOffset( FLOAT fOffset) +{ + // synchronize access to sounds + CTSingleLock slSounds( &_pSound->sl_csSound, TRUE); + + // get prediction tail + //CPrintF("SETOFF: "); + CSoundObject *psoTail = GetPredictionTail(EVENT_SOUNDSETOFFSET, 0); + // if the event is predicted + if (psoTail==NULL) { + // do nothing; + return; + } + + // if sound not playing + if (psoTail->so_pCsdLink==NULL) { + // do nothing + return; + } + + // safety check + ASSERT( fOffset>=0); + if( fOffset<0) { + CPrintF( "BUG: Trying to set negative offset (%.2g) in sound '%s' !\n", fOffset, (CTString&)psoTail->so_pCsdLink->GetName()); + fOffset = 0.0f; + } + + // on the other hand, don't set offset for real - might be source for some bugs! + return; + + // update sound offsets + CPrintF("Setting offset: %g\n", fOffset); + psoTail->so_fLeftOffset = psoTail->so_fRightOffset = psoTail->so_pCsdLink->sd_wfeFormat.nSamplesPerSec*fOffset; +} + + +/* + * Stop + */ +void CSoundObject::Stop(void) +{ + // synchronize access to sounds + CTSingleLock slSounds( &_pSound->sl_csSound, TRUE); + + //CPrintF("STOP"); + if (so_pCsdLink!=NULL) { + //CPrintF(" '%s'", (const char*)so_pCsdLink->GetName().FileName()); + } + + CSoundObject *psoTail = this; + // get prediction tail + psoTail = GetPredictionTail(EVENT_SOUNDSTOP, (ULONG)so_pCsdLink); + // if the event is predicted + if (psoTail==NULL) { + // do nothing; + return; + } + + psoTail->Stop_internal(); +} +void CSoundObject::Stop_internal(void) +{ + // sound is stoped + so_slFlags &= ~(SOF_PLAY|SOF_PREPARE|SOF_PAUSED); + + // destroy decoder if exists + if( so_psdcDecoder!=NULL) { + delete so_psdcDecoder; + so_psdcDecoder = NULL; + } + + // if added in link list, remove it from list + if( IsHooked()) { + ASSERT(so_pCsdLink != NULL); + so_pCsdLink->RemoveObjectLink(*this); + // remove reference from SoundData + so_pCsdLink->RemReference(); + // clear SoundData link + so_pCsdLink = NULL; + } +}; + + +// Update all 3d effects +void CSoundObject::Update3DEffects(void) +{ + // if not 3d sound + if( !(so_slFlags & SOF_3D)) { + // do nothing; + return; + } + +// if (!(so_slFlags&SOF_PREPARE)) { + // if the sound's entity is a predictor +/* if (so_penEntity!=NULL && so_penEntity->IsPredictor()) { + // kill the sound + so_slFlags&=~SOF_PLAY; + //CPrintF("Update canceled %s (%s)\n", (const char*)so_pCsdLink->GetName(), GetPred(so_penEntity)); + // do nothing; + return; + } + */ + //CPrintF("Update PASSED %s (%s)\n", (const char*)so_pCsdLink->GetName(), GetPred(so_penEntity)); +// } + + // total parameters (accounting for all listeners) + FLOAT fTLVolume = 0, fTRVolume = 0; + FLOAT fTLFilter = UpperLimit(0.0f), fTRFilter = UpperLimit(0.0f); + FLOAT fTLDelay = UpperLimit(0.0f), fTRDelay = UpperLimit(0.0f); + FLOAT fTPitchShift = 0; + + // get your position parameters + FLOAT3D vPosition(0,0,0); + FLOAT3D vSpeed(0,0,0); + if (so_penEntity!=NULL) { + vPosition = so_penEntity->en_plPlacement.pl_PositionVector; + if (so_penEntity->en_ulPhysicsFlags&EPF_MOVABLE) { + CMovableEntity *penMovable = (CMovableEntity *)so_penEntity; + vSpeed = penMovable->en_vCurrentTranslationAbsolute; + } + } + + // for each listener + INDEX ctEffectiveListeners = 0; + {FOREACHINLIST( CSoundListener, sli_lnInActiveListeners, _pSound->sl_lhActiveListeners, itsli) + { + CSoundListener &sli = *itsli; + + // if local, but not of this listener + if ((so_slFlags&SOF_LOCAL) && so_penEntity!=sli.sli_penEntity) { + // don't add this listener + continue; + } + + // calculated parameters for this listener + FLOAT fLVolume, fRVolume; + FLOAT fLFilter, fRFilter; + FLOAT fLDelay , fRDelay ; + FLOAT fPitchShift; + + // calculate distance from listener + FLOAT3D vAbsDelta = vPosition - sli.sli_vPosition; + FLOAT fAbsDelta = vAbsDelta.Length(); + + // if too far away + if (fAbsDelta>so_sp3.sp3_fFalloff) { + // don't add this listener + continue; + } + + // calculate distance falloff factor + FLOAT fDistanceFactor; + if( fAbsDelta <= so_sp3.sp3_fHotSpot) { + fDistanceFactor = 1; + } else { + fDistanceFactor = (so_sp3.sp3_fFalloff - fAbsDelta) / + (so_sp3.sp3_fFalloff - so_sp3.sp3_fHotSpot); + } + ASSERT(fDistanceFactor>=0 && fDistanceFactor<=+1); + + // calculate volumetric influence + // NOTE: decoded sounds must be threated as volumetric + FLOAT fNonVolumetric = 1.0f; + FLOAT fNonVolumetricAdvanced = 1.0f; + if( (so_slFlags & SOF_VOLUMETRIC) || so_psdcDecoder!=NULL) { + fNonVolumetric = 1.0f-fDistanceFactor; + fNonVolumetricAdvanced = 0.0f; + } + ASSERT(fNonVolumetric>=0 && fNonVolumetric<=+1); + + // find doppler effect pitch shift + fPitchShift = 1.0f; + if (fAbsDelta>0.001f) { + FLOAT3D vObjectDirection = vAbsDelta/fAbsDelta; + FLOAT fObjectSpeed = vSpeed%vObjectDirection; // negative towards listener + FLOAT fListenerSpeed = sli.sli_vSpeed%vObjectDirection; // positive towards object + fPitchShift = + (snd_fDopplerSoundSpeed+fListenerSpeed*fNonVolumetricAdvanced)/ + (snd_fDopplerSoundSpeed+fObjectSpeed*fNonVolumetricAdvanced); + } + + // find position of sound relative to viewer orientation + FLOAT3D vRelative = vAbsDelta*!sli.sli_mRotation; + // find distances from left and right ear + FLOAT fLDistance = (FLOAT3D(-snd_fEarsDistance*fNonVolumetricAdvanced/2,0,0)-vRelative).Length(); + FLOAT fRDistance = (FLOAT3D(+snd_fEarsDistance*fNonVolumetricAdvanced/2,0,0)-vRelative).Length(); + // calculate sound delay to each ear + fLDelay = fLDistance/snd_fDelaySoundSpeed; + fRDelay = fRDistance/snd_fDelaySoundSpeed; + + // calculate relative sound directions + FLOAT fLRFactor=0; // positive right + FLOAT fFBFactor=0; // positive front + FLOAT fUDFactor=0; // positive up + + if (fAbsDelta>0.001f) { + FLOAT3D vDir = vRelative/fAbsDelta; + fLRFactor = +vDir(1); + fFBFactor = -vDir(3); + fUDFactor = +vDir(2); + } + ASSERT(fLRFactor>=-1.1 && fLRFactor<=+1.1); + ASSERT(fFBFactor>=-1.1 && fFBFactor<=+1.1); + ASSERT(fUDFactor>=-1.1 && fUDFactor<=+1.1); + + + // calculate panning influence factor + FLOAT fPanningFactor= fNonVolumetric*snd_fPanStrength; + ASSERT(fPanningFactor>=0 && fPanningFactor<=+1); + + // calc volume for left and right channel + FLOAT fVolume = so_sp3.sp3_fMaxVolume * fDistanceFactor; + if( fLRFactor > 0) { + fLVolume = (1-fLRFactor*fPanningFactor) * fVolume; + fRVolume = fVolume; + } else { + fLVolume = fVolume; + fRVolume = (1+fLRFactor*fPanningFactor) * fVolume; + } + + // calculate filters + FLOAT fListenerFilter = sli.sli_fFilter; + if (so_slFlags&SOF_NOFILTER) { + fListenerFilter = 0.0f; + } + fLFilter = fRFilter = 1+fListenerFilter; + if( fLRFactor > 0) { + fLFilter += fLRFactor*snd_fLRFilter*fNonVolumetricAdvanced; + } else { + fRFilter -= fLRFactor*snd_fLRFilter*fNonVolumetricAdvanced; + } + if( fFBFactor<0) { + fLFilter -= snd_fBFilter*fFBFactor*fNonVolumetricAdvanced; + fRFilter -= snd_fBFilter*fFBFactor*fNonVolumetricAdvanced; + } + if( fUDFactor>0) { + fLFilter += snd_fUFilter*fUDFactor*fNonVolumetricAdvanced; + fRFilter += snd_fUFilter*fUDFactor*fNonVolumetricAdvanced; + } else { + fLFilter -= snd_fDFilter*fUDFactor*fNonVolumetricAdvanced; + fRFilter -= snd_fDFilter*fUDFactor*fNonVolumetricAdvanced; + } + + // adjust calculated volume to the one of listener + fLVolume *= sli.sli_fVolume; + fRVolume *= sli.sli_fVolume; + + // update parameters for all listener + fTLVolume = Max( fTLVolume, fLVolume); + fTRVolume = Max( fTRVolume, fRVolume); + fTLDelay = Min( fTLDelay , fLDelay ); + fTRDelay = Min( fTRDelay , fRDelay ); + fTLFilter = Min( fTLFilter, fLFilter); + fTRFilter = Min( fTRFilter, fRFilter); + fTPitchShift += fPitchShift; + ctEffectiveListeners++; + }} + + fTPitchShift /= ctEffectiveListeners; + + // calculate 2d parameters + FLOAT fPitchShift = fTPitchShift * so_sp3.sp3_fPitch; + FLOAT fPhaseShift = fTLDelay-fTRDelay; + FLOAT fDelay = Min( fTRDelay,fTLDelay); + +// CPrintF("V:%f %f F:%f %f P:%f S:%f\n", +// fTLVolume, fTRVolume, +// fTLFilter, fTRFilter, +// fPhaseShift, +// fPitchShift); + + // set sound parameters + fTLVolume = Clamp( fTLVolume, SL_VOLUME_MIN, SL_VOLUME_MAX); + fTRVolume = Clamp( fTRVolume, SL_VOLUME_MIN, SL_VOLUME_MAX); + SetVolume( fTLVolume, fTRVolume); + + if( fTLVolume>0 || fTRVolume>0) { + // do safety clamping + fTLFilter = ClampDn( fTLFilter, 1.0f); + fTRFilter = ClampDn( fTRFilter, 1.0f); + fDelay = ClampDn( fDelay, 0.0f); + fPitchShift = ClampDn( fPitchShift, 0.001f); + fPhaseShift = Clamp( fPhaseShift, -1.0f, +1.0f); + // set sound params + SetFilter( fTLFilter, fTRFilter); + SetDelay( fDelay); + SetPitch( fPitchShift); + SetPhase( fPhaseShift); + } +} + + +// Prepare sound +void CSoundObject::PrepareSound(void) +{ + ASSERT(so_penEntity==NULL || !so_penEntity->IsPredictor()); + + so_fLastLeftVolume = so_spNew.sp_fLeftVolume; + so_fLastRightVolume = so_spNew.sp_fRightVolume; + // adjust for master volume + if(so_slFlags&SOF_MUSIC) { + so_fLastLeftVolume *= snd_fMusicVolume; + so_fLastRightVolume *= snd_fMusicVolume; + } else { + so_fLastLeftVolume *= snd_fSoundVolume; + so_fLastRightVolume *= snd_fSoundVolume; + } +}; + + +// Obtain sound and play it for this object +void CSoundObject::Play_t(const CTFileName &fnmSound, SLONG slFlags) // throw char * +{ + // obtain it (adds one reference) + CSoundData *ptd = _pSoundStock->Obtain_t(fnmSound); + // set it as data (adds one more reference, and remove old reference) + Play(ptd, slFlags); + // release it (removes one reference) + _pSoundStock->Release(ptd); + // total reference count +1+1-1 = +1 for new data -1 for old data +}; + + + +// read/write functions +void CSoundObject::Read_t(CTStream *pistr) // throw char * +{ + int iDroppedOut; + + // load file name + CTFileName fnmSound; + *pistr >> fnmSound; + + // load object preferences + *pistr >> iDroppedOut; + *pistr >> so_slFlags; + + *pistr >> so_spNew.sp_fLeftVolume; + *pistr >> so_spNew.sp_fRightVolume; + *pistr >> so_spNew.sp_slLeftFilter; + *pistr >> so_spNew.sp_slRightFilter; + *pistr >> so_spNew.sp_fPitchShift; + *pistr >> so_spNew.sp_fPhaseShift; + *pistr >> so_spNew.sp_fDelay; + + *pistr >> so_fDelayed; + *pistr >> so_fLastLeftVolume; + *pistr >> so_fLastRightVolume; + *pistr >> so_swLastLeftSample; + *pistr >> so_swLastRightSample; + *pistr >> so_fLeftOffset; + *pistr >> so_fRightOffset; + *pistr >> so_fOffsetDelta; + + // load 3D parameters + so_penEntity = NULL; + *pistr >> so_sp3.sp3_fFalloff; + *pistr >> so_sp3.sp3_fHotSpot; + *pistr >> so_sp3.sp3_fMaxVolume; + *pistr >> so_sp3.sp3_fPitch; + + // update current state + so_sp = so_spNew; + + // Obtain and play object (sound) + if ( fnmSound != "" && (so_slFlags&SOF_PLAY)) { + Play_t( fnmSound, so_slFlags|SOF_LOADED); + } +}; + +void CSoundObject::Write_t(CTStream *pistr) // throw char * +{ + int iDroppedOut=0; + + // save file name + if (so_pCsdLink!=NULL) { + *pistr << (so_pCsdLink->GetName()); + } else { + *pistr << CTFILENAME(""); + } + + // save object preferences + *pistr << iDroppedOut; + *pistr << so_slFlags; + + *pistr << so_spNew.sp_fLeftVolume; + *pistr << so_spNew.sp_fRightVolume; + *pistr << so_spNew.sp_slLeftFilter; + *pistr << so_spNew.sp_slRightFilter; + *pistr << so_spNew.sp_fPitchShift; + *pistr << so_spNew.sp_fPhaseShift; + *pistr << so_spNew.sp_fDelay; + + *pistr << so_fDelayed; + *pistr << so_fLastLeftVolume; + *pistr << so_fLastRightVolume; + *pistr << so_swLastLeftSample; + *pistr << so_swLastRightSample; + *pistr << so_fLeftOffset; + *pistr << so_fRightOffset; + *pistr << so_fOffsetDelta; + + // save 3D parameters + *pistr << so_sp3.sp3_fFalloff; + *pistr << so_sp3.sp3_fHotSpot; + *pistr << so_sp3.sp3_fMaxVolume; + *pistr << so_sp3.sp3_fPitch; +}; diff --git a/Sources/Engine/Sound/SoundObject.h b/Sources/Engine/Sound/SoundObject.h new file mode 100644 index 0000000..9b74dc7 --- /dev/null +++ b/Sources/Engine/Sound/SoundObject.h @@ -0,0 +1,170 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SOUNDOBJECT_H +#define SE_INCL_SOUNDOBJECT_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include + + +// sound control values +#define SOF_NONE (0L) +#define SOF_LOOP (1L<<0) // looping sound +#define SOF_3D (1L<<1) // has 3d effects +#define SOF_VOLUMETRIC (1L<<2) // no 3d effects inside hot-spot +#define SOF_SURROUND (1L<<3) // surround effect +#define SOF_LOCAL (1L<<4) // local to listener with same entity +#define SOF_SMOOTHCHANGE (1L<<5) // for smooth transition from one sound to another on same channel +#define SOF_MUSIC (1L<<6) // use music-volume master control instead of sound-volume +#define SOF_NONGAME (1L<<7) // game sounds are not mixed while the game is paused +#define SOF_NOFILTER (1L<<8) // used to disable listener-specific filters - i.e. underwater + +#define SOF_PAUSED (1L<<28) // playing, but paused (internal) +#define SOF_LOADED (1L<<29) // sound just loaded (internal) +#define SOF_PREPARE (1L<<30) // prepared for playing (internal) +#define SOF_PLAY (1L<<31) // currently playing + +// sound parameters +class CSoundParameters { +public: + FLOAT sp_fLeftVolume; // left channel volume (0.0f-1.0f) + FLOAT sp_fRightVolume; // right channel volume + SLONG sp_slLeftFilter; // left channel bass enhance (32767-0, 0=max) + SLONG sp_slRightFilter; // right channel bass enhance + FLOAT sp_fPhaseShift; // right channel(!) delay in seconds (signed! fixint 16:16) + FLOAT sp_fPitchShift; // playing speed factor (>0, 1.0=normal) + FLOAT sp_fDelay; // seconds to wait before actual sound play start +}; + +// 3d sound parameters +class CSoundParameters3D { +public: + FLOAT sp3_fPitch; // sound pitch 1=normal + FLOAT sp3_fFalloff; // distance when sound can't be heard any more + FLOAT sp3_fHotSpot; // sound at maximum volume + FLOAT sp3_fMaxVolume; // maximum sound volume +}; + +class ENGINE_API CSoundObject { +public: + // Sound Object Aware class (notify class when direct sound pointer is not valid) + CListNode so_Node; // for linking in list + class CSoundDecoder *so_psdcDecoder; // only for sounds that are mpx/ogg + +public: //private: + CSoundData *so_pCsdLink; // linked on SoundData + SLONG so_slFlags; // playing flags + + // internal mixer parameters + FLOAT so_fDelayed; // seconds already passed from start playing sound request + FLOAT so_fLastLeftVolume; // volume from previous mixing (for seamless transition) + FLOAT so_fLastRightVolume; + SWORD so_swLastLeftSample; // samples from previous mixing (for filtering purposes) + SWORD so_swLastRightSample; + FLOAT so_fLeftOffset; // current playing offset of left channel + FLOAT so_fRightOffset; // current playing offset of right channel + FLOAT so_fOffsetDelta; // difference between offsets in samples (for seamless transition between phases) + + // sound parameters + CEntity *so_penEntity; // entity that owns this sound (may be null) + CSoundParameters so_sp; // currently active parameters + CSoundParameters so_spNew; // parameters to set on next update + CSoundParameters3D so_sp3; // 3d sound parameters + + /* Play Buffer */ + void PlayBuffer(void); + /* Stop Buffer */ + void StopBuffer(void); + /* Update all 3d effects. */ + void Update3DEffects(void); + /* Prepare sound */ + void PrepareSound(void); + + // get proper sound object for predicted events - return NULL the event is already predicted + CSoundObject *GetPredictionTail(ULONG ulTypeID, ULONG ulEventID); + + // play sound - internal function - doesn't account for prediction + void Play_internal( CSoundData *pCsdLink, SLONG slFlags); + void Stop_internal(void); + +public: + // Constructor + CSoundObject(); + // Destructor + ~CSoundObject(); + // copy from another object of same class + void Copy(CSoundObject &soOther); + + // play sound + void Play( CSoundData *pCsdLink, SLONG slFlags); + // stop playing sound + void Stop( void); + // Pause -> Stop playing sound but keep it linked to data + inline void Pause(void) { so_slFlags |= SOF_PAUSED; }; + // Resume -> Resume playing stoped sound + inline void Resume(void) { so_slFlags &= ~SOF_PAUSED; }; + // check if sound is playing + inline BOOL IsPlaying(void) { + return (so_slFlags&SOF_PLAY); + }; + // check if sound is paused + inline BOOL IsPaused(void) { + return (so_slFlags&SOF_PAUSED); + }; + + // Check if hooked + inline BOOL IsHooked(void) const { return so_Node.IsLinked(); }; + + // Set volume + inline void SetVolume( FLOAT fLeftVolume, FLOAT fRightVolume) { + ASSERT( fLeftVolume <= SL_VOLUME_MAX && fLeftVolume >= SL_VOLUME_MIN); + ASSERT( fRightVolume <= SL_VOLUME_MAX && fRightVolume >= SL_VOLUME_MIN); + so_spNew.sp_fLeftVolume = fLeftVolume *(1.0f/SL_VOLUME_MAX); + so_spNew.sp_fRightVolume = fRightVolume*(1.0f/SL_VOLUME_MAX); + }; + // Set filter + inline void SetFilter( FLOAT fLeftFilter, FLOAT fRightFilter) { // 1=no filter (>1=more bass) + ASSERT( (fLeftFilter >= 1) && (fRightFilter >= 1)); + so_spNew.sp_slLeftFilter = FloatToInt(32767.0/fLeftFilter); + so_spNew.sp_slRightFilter = FloatToInt(32767.0/fRightFilter); + }; + // Set pitch shifting + inline void SetPitch( FLOAT fPitch) { // 1.0 for normal (<1 = slower, >1 = faster playing) + ASSERT( fPitch > 0); + so_spNew.sp_fPitchShift = fPitch; + }; + // Set phase shifting + inline void SetPhase( FLOAT fPhase) { // right channel delay in seconds (0 = no delay) + ASSERT( (fPhase <= 1) && (fPhase >= -1)); + so_spNew.sp_fPhaseShift = fPhase; + }; + // Set delay + inline void SetDelay( FLOAT fDelay) { // in seconds (0 = no delay) + ASSERT( fDelay >= 0); + so_spNew.sp_fDelay = fDelay; + }; + + // Set Position in 3D + inline void SetOwner(CEntity*pen) { + so_penEntity = pen; + }; + // Set 3D parameters + void Set3DParameters(FLOAT fMaxDistance, FLOAT fMinDistance, FLOAT fMaxVolume, FLOAT fPitch); + + // read/write functions + void Read_t(CTStream *pistr); // throw char * + void Write_t(CTStream *postr); // throw char * + + // Obtain sound and play it for this object + void Play_t(const CTFileName &fnmSound, SLONG slFlags); // throw char * + // hard set sound offset in seconds + void SetOffset(FLOAT fOffset); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Sound/SoundProfile.cpp b/Sources/Engine/Sound/SoundProfile.cpp new file mode 100644 index 0000000..a00a2de --- /dev/null +++ b/Sources/Engine/Sound/SoundProfile.cpp @@ -0,0 +1,29 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +// profile form for profiling sounds +CSoundProfile _spSoundProfile; +CProfileForm &_pfSoundProfile = _spSoundProfile; + +///////////////////////////////////////////////////////////////////// +// CSoundProfile + +CSoundProfile::CSoundProfile(void) + : CProfileForm ("Sound", "updates", + CSoundProfile::PCI_COUNT, CSoundProfile::PTI_COUNT) +{ + SETTIMERNAME( PTI_MIXSOUNDS, "MixSounds()", ""); + SETTIMERNAME( PTI_DECODESOUND, " DecodeSound()", ""); + SETTIMERNAME( PTI_MIXSOUND, " MixSound()", ""); + SETTIMERNAME( PTI_RAWMIXER, " Raw Mixer Loop", ""); + SETTIMERNAME( PTI_UPDATESOUNDS, "UpdateSounds()", ""); + + SETCOUNTERNAME( PCI_MIXINGS, "number of mixings"); + SETCOUNTERNAME( PCI_SOUNDSMIXED, "sounds mixed"); + SETCOUNTERNAME( PCI_SOUNDSSKIPPED, "sounds skipped for low volume"); + SETCOUNTERNAME( PCI_SOUNDSDELAYED, "sounds delayed for sound speed latency"); + SETCOUNTERNAME( PCI_SAMPLES, "samples mixed"); +} diff --git a/Sources/Engine/Sound/SoundProfile.h b/Sources/Engine/Sound/SoundProfile.h new file mode 100644 index 0000000..7450cc3 --- /dev/null +++ b/Sources/Engine/Sound/SoundProfile.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SOUNDPROFILE_H +#define SE_INCL_SOUNDPROFILE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* Class for holding profiling information for sound operations. */ +class CSoundProfile : public CProfileForm { +public: + // indices for profiling counters and timers + enum ProfileTimerIndex { + PTI_MIXSOUNDS, // MixSounds() + PTI_DECODESOUND, // DecodeSound() + PTI_MIXSOUND, // MixSound() + PTI_RAWMIXER, // Raw Mixer Loop + PTI_UPDATESOUNDS, // UpdateSounds() + + PTI_COUNT + }; + enum ProfileCounterIndex { + PCI_MIXINGS, // number of mixings + + PCI_SOUNDSMIXED, // sounds mixed + PCI_SOUNDSSKIPPED, // sounds skipped for low volume + PCI_SOUNDSDELAYED, // sounds delayed for sound speed latency + PCI_SAMPLES, // samples mixed + + PCI_COUNT + }; + // constructor + CSoundProfile(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Sound/Wave.cpp b/Sources/Engine/Sound/Wave.cpp new file mode 100644 index 0000000..82dc9e9 --- /dev/null +++ b/Sources/Engine/Sound/Wave.cpp @@ -0,0 +1,332 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include + +/* ==================================================== + * + * CONVERSION FUNCTIONS + * + */ + +// check wave format +void PCMWaveInput::CheckWaveFormat_t(WAVEFORMATEX wfeCheck, char *pcErrorString) +{ + // check format tag + if (wfeCheck.wFormatTag != 1) { + ThrowF_t(TRANS("%s: Invalid format tag, not a PCM Wave file!"), pcErrorString); + } + // check bits per sample + if (wfeCheck.wBitsPerSample != 8 && + wfeCheck.wBitsPerSample != 16) { + ThrowF_t(TRANS("%s: Unknown Bits Per Sample value!"), pcErrorString); + } + // check number of channels + if (wfeCheck.nChannels != 1 && + wfeCheck.nChannels != 2) { + ThrowF_t(TRANS("%s: Invalid number of channels!"), pcErrorString); + } + //ASSERT( wfeCheck.wBitsPerSample==16); +} + + +// Get next data +inline ULONG PCMWaveInput::GetData_t(CTStream *pCstrInput) +{ + ASSERT(pwi_bInfoLoaded); + // read data according to bits per sample value + if (pwi_wfeWave.wBitsPerSample==8) { + // read UBYTE + UBYTE ubData; + *pCstrInput >> ubData; + return ((ULONG)ubData) <<16; // (shift) prepare data for shrink/expand operation + } else { + // read UWORD + SWORD swData; + *pCstrInput >> swData; + return ((ULONG)(swData+0x8000)) <<8; // (shift) prepare data for shrink/expand operation + } +} + + +// Store data +inline void PCMWaveInput::StoreData(ULONG ulData) +{ + ASSERT( pwi_wfeDesired.wBitsPerSample==16); + *pwi_pswMemory++ = ((SWORD)(ulData>>8) -0x8000); // (shift) restore data format +} + + +/* + * Copy data + */ +void PCMWaveInput::CopyData_t(CTStream *pCstrInput) +{ + // for all input data (mono and stereo) + ULONG ulDataCount = GetDataLength() * pwi_wfeWave.nChannels; + while (ulDataCount > 0) { + StoreData(GetData_t(pCstrInput)); // read and store data from input (hidden BitsPerSample conversion!) + ulDataCount--; // to next data + } +} + + + +/* + * Shrink data + */ +// Shrink data +void PCMWaveInput::ShrinkData_t(CTStream *pCstrInput) +{ + ASSERT(pwi_dRatio>1.0); + + // *** MONO *** + if (pwi_wfeWave.nChannels == 1) { + DOUBLE dInterData, dTempData, dRatio; + ULONG ulDataCount; + + // data intermediate value + dInterData = 0.0; + // for all input data (mono) + ulDataCount = GetDataLength(); + dRatio = pwi_dRatio; + while (ulDataCount > 0) { + // read part of data (<100%) + if (dRatio<1.0) { + dTempData = GetData_t(pCstrInput); + dInterData += dTempData*dRatio; + StoreData(ULONG(dInterData/pwi_dRatio)); + // new intermediate value + dRatio = 1 - dRatio; + dInterData = dTempData*dRatio; + dRatio = pwi_dRatio - dRatio; + + // read complete data (100%) + } else { + dInterData += GetData_t(pCstrInput); + dRatio -= 1.0; + } + ulDataCount--; // to next data + } + StoreData(ULONG(dInterData/(pwi_dRatio-dRatio))); + + + // *** STEREO *** + } else if (pwi_wfeWave.nChannels == 2) { + DOUBLE dLInterData, dRInterData, dLTempData, dRTempData, dRatio; + ULONG ulDataCount; + + // data intermediate value + dLInterData = 0.0; + dRInterData = 0.0; + // for all input data (mono) + ulDataCount = GetDataLength(); + dRatio = pwi_dRatio; + while (ulDataCount > 0) { + // read part of data (<100%) + if (dRatio<1.0) { + dLTempData = GetData_t(pCstrInput); + dRTempData = GetData_t(pCstrInput); + dLInterData += dLTempData*dRatio; + dRInterData += dRTempData*dRatio; + StoreData(ULONG(dLInterData/pwi_dRatio)); + StoreData(ULONG(dRInterData/pwi_dRatio)); + // new intermediate value + dRatio = 1 - dRatio; + dLInterData = dLTempData*dRatio; + dRInterData = dRTempData*dRatio; + dRatio = pwi_dRatio - dRatio; + + // read complete data (100%) + } else { + dLInterData += GetData_t(pCstrInput); + dRInterData += GetData_t(pCstrInput); + dRatio -= 1.0; + } + ulDataCount--; // to next data + } + StoreData(ULONG(dLInterData/(pwi_dRatio-dRatio))); + StoreData(ULONG(dRInterData/(pwi_dRatio-dRatio))); + } +} + + + + +/* ==================================================== + * + * WAVE FUNCTIONS + * + */ + +/* + * Load Wave info + */ + +WAVEFORMATEX PCMWaveInput::LoadInfo_t(CTStream *pCstrInput) +{ + // if already loaded -> exception + if (pwi_bInfoLoaded) { + throw (TRANS("PCM Wave Input: Info already loaded.")); + } + + /* Read Riff */ + pCstrInput->ExpectID_t(CChunkID("RIFF")); // ID "RIFF" + (*pCstrInput) >> pwi_ulRiffLength; // Ucitaj duljinu file-a + + /* Read Wave */ + pCstrInput->ExpectID_t(CChunkID("WAVE")); // ID "WAVE" + pCstrInput->ExpectID_t(CChunkID("fmt ")); // ID "fmt " + // read Format Chunk length + SLONG slFmtLength; + (*pCstrInput) >> slFmtLength; + + // read WAVE format + (*pCstrInput) >> pwi_wfeWave.wFormatTag; + (*pCstrInput) >> pwi_wfeWave.nChannels; + (*pCstrInput) >> pwi_wfeWave.nSamplesPerSec; + (*pCstrInput) >> pwi_wfeWave.nAvgBytesPerSec; + (*pCstrInput) >> pwi_wfeWave.nBlockAlign; + (*pCstrInput) >> pwi_wfeWave.wBitsPerSample; + pwi_wfeWave.cbSize = 0; // Only for PCM Wave !!! + + // WARNING !!! - Only for PCM Wave - Skip extra information if exists + if( slFmtLength > 16) { + //WarningMessage("PCM Wave Input: Wave format Extra information skipped!"); + pCstrInput->Seek_t(slFmtLength - 16, CTStream::SD_CUR); + } + + // WARNING - If exist Fact chunk skip it (purpose unknown) + if( pCstrInput->GetID_t() == CChunkID("fact")) { + //WarningMessage("PCM Wave Input: Fact Chunk skipped!"); + SLONG slSkipLength; + (*pCstrInput) >> slSkipLength; + pCstrInput->Seek_t(slSkipLength, CTStream::SD_CUR); + // seek back on Chunk ID + } else { + pCstrInput->Seek_t(-CID_LENGTH, CTStream::SD_CUR); + } + + /* Read Data */ + pCstrInput->ExpectID_t(CChunkID("data")); // ID "data" + // read Data length (in bytes) + (*pCstrInput) >> pwi_ulDataLength; + + /* Check PCM format */ + CheckWaveFormat_t(pwi_wfeWave, "PCM Wave Input (input)"); + + // mark Info loaded + pwi_bInfoLoaded = TRUE; + + // ASSERT( pwi_wfeWave.wBitsPerSample==16); + // return Wave Format + return pwi_wfeWave; +} + + +/* + * Load and convert Wave data + */ +void PCMWaveInput::LoadData_t(CTStream *pCstrInput, SWORD *pswMemory, WAVEFORMATEX &SwfeDesired) +{ + // if info not loaded -> exception + if (!pwi_bInfoLoaded) { + throw (TRANS("PCM Wave Input: Info not loaded.")); + } + // if already loaded -> exception + if (pwi_bDataLoaded) { + throw (TRANS("PCM Wave Input: Data already loaded")); + } + + // set memory pointer + pwi_pswMemory = pswMemory; + + // store and check desired sound format + CheckWaveFormat_t(SwfeDesired, "PCM Wave Input (desired)"); + pwi_wfeDesired = SwfeDesired; + + // calculate expand/shrink ratio (number of channels remain the same) + pwi_dRatio = (DOUBLE)pwi_wfeDesired.nSamplesPerSec / (DOUBLE)pwi_wfeWave.nSamplesPerSec; + + // determine converion type from input and desired sound frequency, and convert sound + if (pwi_dRatio < 1) { + pwi_dRatio = 1/pwi_dRatio; + ShrinkData_t(pCstrInput); + } else if (pwi_dRatio > 1) { + ASSERTALWAYS("Can't expand wave data"); + memset(pwi_pswMemory, 0, DetermineBufferSize(pwi_wfeDesired)); + // copy data + } else { + ASSERT(pwi_dRatio==1.0f); + CopyData_t(pCstrInput); + } + + // data is loaded (and maybe converted from 16-bits) + if( pwi_wfeWave.wBitsPerSample==8) SwfeDesired.nBlockAlign *= 2; + pwi_bDataLoaded = TRUE; +} + + + +/* + * Length in bytes + */ +ULONG PCMWaveInput::GetByteLength(void) +{ + ASSERT(pwi_bInfoLoaded); + return pwi_ulDataLength; +} + +/* + * Length in blocks + */ +ULONG PCMWaveInput::GetDataLength(void) +{ + ASSERT(pwi_bInfoLoaded); + return GetByteLength() / (pwi_wfeWave.nChannels * pwi_wfeWave.wBitsPerSample/8); +} + + +ULONG PCMWaveInput::GetDataLength(WAVEFORMATEX SwfeDesired) +{ + ASSERT(pwi_bInfoLoaded); + // return buffer size + return DetermineBufferSize(SwfeDesired) / (SwfeDesired.nChannels * SwfeDesired.wBitsPerSample/8); +} + +/* + * Length in seconds + */ +DOUBLE PCMWaveInput::GetSecondsLength(void) +{ + ASSERT(pwi_bInfoLoaded); + return (DOUBLE)GetDataLength() / (DOUBLE)pwi_wfeWave.nSamplesPerSec; +} + + +/* + * Buffer length in bytes + */ +ULONG PCMWaveInput::DetermineBufferSize(void) +{ + return DetermineBufferSize(pwi_wfeWave); +} + + +ULONG PCMWaveInput::DetermineBufferSize( WAVEFORMATEX SwfeDesired) +{ + ASSERT(pwi_bInfoLoaded); + DOUBLE dRatio; + + // calculate ratio between formats + dRatio = (DOUBLE)SwfeDesired.nSamplesPerSec / (DOUBLE)pwi_wfeWave.nSamplesPerSec + * (DOUBLE)SwfeDesired.wBitsPerSample / (DOUBLE)pwi_wfeWave.wBitsPerSample; + // return buffer size (must calculate with data length to avoid miss align data, for example: + // 16 bit sound with 2 channels must be aligned to 4 bytes boundary and a multiply with + // random ratio can as result give any possible number + DOUBLE ret = ceil(dRatio*GetDataLength()) * (pwi_wfeWave.nChannels*(pwi_wfeWave.wBitsPerSample/8)); + return (ULONG)ret; +} diff --git a/Sources/Engine/Sound/Wave.h b/Sources/Engine/Sound/Wave.h new file mode 100644 index 0000000..aedd838 --- /dev/null +++ b/Sources/Engine/Sound/Wave.h @@ -0,0 +1,54 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_WAVE_H +#define SE_INCL_WAVE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* + * PCM Wave Input + */ +class PCMWaveInput { +private: + // Wave data + WAVEFORMATEX pwi_wfeWave; + WAVEFORMATEX pwi_wfeDesired; + ULONG pwi_ulRiffLength, pwi_ulDataLength; + BOOL pwi_bInfoLoaded, pwi_bDataLoaded; // Status + SWORD *pwi_pswMemory; // Memory + + /* Conversion */ + DOUBLE pwi_dRatio; + // get and store data + inline ULONG GetData_t( CTStream *pCstrInput); + inline void StoreData( ULONG ulData); + void CopyData_t( CTStream *pCstrInput); + void ShrinkData_t( CTStream *pCstrInput); + +public: + // Check wave format + static void CheckWaveFormat_t( WAVEFORMATEX SwfeCheck, char *pcErrorString); + + /* Constructor */ + inline PCMWaveInput(void) { pwi_bInfoLoaded = FALSE; pwi_bDataLoaded = FALSE; }; + /* Load Wave info */ + WAVEFORMATEX LoadInfo_t( CTStream *pCstrInput); + /* Load and convert Wave data */ + void LoadData_t( CTStream *pCstrInput, SWORD *pswMemory, WAVEFORMATEX &SwfeDesired); + + /* Length in bytes / blocks / seconds */ + ULONG GetByteLength(void); + ULONG GetDataLength(void); + ULONG GetDataLength( WAVEFORMATEX SwfeDesired); + DOUBLE GetSecondsLength(void); + + /* Buffer length in bytes */ + ULONG DetermineBufferSize(void); + ULONG DetermineBufferSize( WAVEFORMATEX SwfeDesired); +}; + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Sound/al_functions.h b/Sources/Engine/Sound/al_functions.h new file mode 100644 index 0000000..f4fb483 --- /dev/null +++ b/Sources/Engine/Sound/al_functions.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +// DLLFUNCTION(dll, output, name, inputs, params, required) + +DLLFUNCTION( A11L, void, alInitLibrary, (void), 0,0); +DLLFUNCTION( A11L, void, alEndLibrary, (void), 0,0); +DLLFUNCTION( A11L, ALhandle, alOpenInputFile, (const char *strFileName), 4,0); +DLLFUNCTION( A11L, ALhandle, alOpenDecoder, (ALhandle hFile), 4,0); +DLLFUNCTION( A11L, ALhandle, alOpenSubFile, (ALhandle hFile, ALsize sOffset, ALsize sSize), 12,0); +DLLFUNCTION( A11L, ALbool, alGetMPXHeader, (ALhandle hFile, ALsint32 *piLayer, + ALsint32 *piVersion, ALsint32 *piFrequency, ALbool *pbStereo, ALsint32 *piRate), 24, 0); +DLLFUNCTION( A11L, void, alClose, (ALhandle hStream), 4,0); +DLLFUNCTION( A11L, ALsize, alRead, (ALhandle hStream, void *pvBuffer, ALsize size), 12,0); +DLLFUNCTION( A11L, void, alDecSeekAbs, (ALhandle hDecoder, ALfloat fSeconds), 8,0); +DLLFUNCTION( A11L, ALfloat, alDecGetLen, (ALhandle hDecoder), 4,0); diff --git a/Sources/Engine/Sound/eax.h b/Sources/Engine/Sound/eax.h new file mode 100644 index 0000000..578d22c --- /dev/null +++ b/Sources/Engine/Sound/eax.h @@ -0,0 +1,413 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +/****************************************************************** +* +* EAX.H - DirectSound3D Environmental Audio Extensions version 2.0 +* Updated July 8, 1999 +* +******************************************************************* +*/ + +#ifndef EAX_H_INCLUDED +#define EAX_H_INCLUDED + +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#pragma pack(push, 4) + +/* +* EAX Wrapper Interface {4FF53B81-1CE0-11d3-AAB8-00A0C95949D5} +*/ +DEFINE_GUID(CLSID_EAXDirectSound, + 0x4ff53b81, + 0x1ce0, + 0x11d3, + 0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5); + +__declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate(GUID*, LPDIRECTSOUND*, IUnknown FAR *); + +typedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE)(GUID*, LPDIRECTSOUND*, IUnknown FAR*); + + +/* +* EAX 2.0 listener property set {0306A6A8-B224-11d2-99E5-0000E8D8C722} +*/ +DEFINE_GUID(DSPROPSETID_EAX20_ListenerProperties, + 0x306a6a8, + 0xb224, + 0x11d2, + 0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22); + +// For compatibility with future EAX versions: +#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX20_ListenerProperties + +typedef enum +{ + DSPROPERTY_EAXLISTENER_NONE, + DSPROPERTY_EAXLISTENER_ALLPARAMETERS, + DSPROPERTY_EAXLISTENER_ROOM, + DSPROPERTY_EAXLISTENER_ROOMHF, + DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, + DSPROPERTY_EAXLISTENER_DECAYTIME, + DSPROPERTY_EAXLISTENER_DECAYHFRATIO, + DSPROPERTY_EAXLISTENER_REFLECTIONS, + DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY, + DSPROPERTY_EAXLISTENER_REVERB, + DSPROPERTY_EAXLISTENER_REVERBDELAY, + DSPROPERTY_EAXLISTENER_ENVIRONMENT, + DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, + DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION, + DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF, + DSPROPERTY_EAXLISTENER_FLAGS +} DSPROPERTY_EAX_LISTENERPROPERTY; + +// OR these flags with property id +#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately +#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later +#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | \ + DSPROPERTY_EAXLISTENER_IMMEDIATE) + +// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS +// - all levels are hundredths of decibels +// - all times are in seconds +// - the reference for high frequency controls is 5 kHz +// +// NOTE: This structure may change in future EAX versions. +// It is recommended to initialize fields by name: +// myListener.lRoom = -1000; +// myListener.lRoomHF = -100; +// ... +// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ; +// instead of: +// myListener = { -1000, -100, ... , 0x00000009 }; +// If you want to save and load presets in binary form, you +// should define your own structure to insure future compatibility. +// +typedef struct _EAXLISTENERPROPERTIES +{ + LONG lRoom; // room effect level at low frequencies + LONG lRoomHF; // room effect high-frequency level re. low frequency level + FLOAT flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + FLOAT flDecayTime; // reverberation decay time at low frequencies + FLOAT flDecayHFRatio; // high-frequency to low-frequency decay time ratio + LONG lReflections; // early reflections level relative to room effect + FLOAT flReflectionsDelay; // initial reflection delay time + LONG lReverb; // late reverberation level relative to room effect + FLOAT flReverbDelay; // late reverberation delay time relative to initial reflection + DWORD dwEnvironment; // sets all listener properties + FLOAT flEnvironmentSize; // environment size in meters + FLOAT flEnvironmentDiffusion; // environment diffusion + FLOAT flAirAbsorptionHF; // change in level per meter at 5 kHz + DWORD dwFlags; // modifies the behavior of properties +} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES; + +// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT +enum +{ + EAX_ENVIRONMENT_GENERIC, + EAX_ENVIRONMENT_PADDEDCELL, + EAX_ENVIRONMENT_ROOM, + EAX_ENVIRONMENT_BATHROOM, + EAX_ENVIRONMENT_LIVINGROOM, + EAX_ENVIRONMENT_STONEROOM, + EAX_ENVIRONMENT_AUDITORIUM, + EAX_ENVIRONMENT_CONCERTHALL, + EAX_ENVIRONMENT_CAVE, + EAX_ENVIRONMENT_ARENA, + EAX_ENVIRONMENT_HANGAR, + EAX_ENVIRONMENT_CARPETEDHALLWAY, + EAX_ENVIRONMENT_HALLWAY, + EAX_ENVIRONMENT_STONECORRIDOR, + EAX_ENVIRONMENT_ALLEY, + EAX_ENVIRONMENT_FOREST, + EAX_ENVIRONMENT_CITY, + EAX_ENVIRONMENT_MOUNTAINS, + EAX_ENVIRONMENT_QUARRY, + EAX_ENVIRONMENT_PLAIN, + EAX_ENVIRONMENT_PARKINGLOT, + EAX_ENVIRONMENT_SEWERPIPE, + EAX_ENVIRONMENT_UNDERWATER, + EAX_ENVIRONMENT_DRUGGED, + EAX_ENVIRONMENT_DIZZY, + EAX_ENVIRONMENT_PSYCHOTIC, + + EAX_ENVIRONMENT_COUNT +}; + +// Used by DSPROPERTY_EAXLISTENER_FLAGS +// +// Note: The number and order of flags may change in future EAX versions. +// It is recommended to use the flag defines as follows: +// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE; +// instead of: +// myFlags = 0x00000009; +// +// These flags determine what properties are affected by environment size. +#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time +#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level +#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time +#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level +#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time + +// This flag limits high-frequency decay time according to air absorption. +#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020 + +#define EAXLISTENERFLAGS_RESERVED 0xFFFFFFC0 // reserved future use + +// property ranges and defaults: + +#define EAXLISTENER_MINROOM (-10000) +#define EAXLISTENER_MAXROOM 0 +#define EAXLISTENER_DEFAULTROOM (-1000) + +#define EAXLISTENER_MINROOMHF (-10000) +#define EAXLISTENER_MAXROOMHF 0 +#define EAXLISTENER_DEFAULTROOMHF (-100) + +#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f +#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f +#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f + +#define EAXLISTENER_MINDECAYTIME 0.1f +#define EAXLISTENER_MAXDECAYTIME 20.0f +#define EAXLISTENER_DEFAULTDECAYTIME 1.49f + +#define EAXLISTENER_MINDECAYHFRATIO 0.1f +#define EAXLISTENER_MAXDECAYHFRATIO 2.0f +#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f + +#define EAXLISTENER_MINREFLECTIONS (-10000) +#define EAXLISTENER_MAXREFLECTIONS 1000 +#define EAXLISTENER_DEFAULTREFLECTIONS (-2602) + +#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f +#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f +#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f + +#define EAXLISTENER_MINREVERB (-10000) +#define EAXLISTENER_MAXREVERB 2000 +#define EAXLISTENER_DEFAULTREVERB 200 + +#define EAXLISTENER_MINREVERBDELAY 0.0f +#define EAXLISTENER_MAXREVERBDELAY 0.1f +#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f + +#define EAXLISTENER_MINENVIRONMENT 0 +#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT-1) +#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC + +#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f +#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f +#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f + +#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f +#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f +#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f + +#define EAXLISTENER_MINAIRABSORPTIONHF (-100.0f) +#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f +#define EAXLISTENER_DEFAULTAIRABSORPTIONHF (-5.0f) + +#define EAXLISTENER_DEFAULTFLAGS (EAXLISTENERFLAGS_DECAYTIMESCALE | \ + EAXLISTENERFLAGS_REFLECTIONSSCALE | \ + EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \ + EAXLISTENERFLAGS_REVERBSCALE | \ + EAXLISTENERFLAGS_REVERBDELAYSCALE | \ + EAXLISTENERFLAGS_DECAYHFLIMIT) + + + +/* +* EAX 2.0 buffer property set {0306A6A7-B224-11d2-99E5-0000E8D8C722} +*/ +DEFINE_GUID(DSPROPSETID_EAX20_BufferProperties, + 0x306a6a7, + 0xb224, + 0x11d2, + 0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22); + +// For compatibility with future EAX versions: +#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX20_BufferProperties + +typedef enum +{ + DSPROPERTY_EAXBUFFER_NONE, + DSPROPERTY_EAXBUFFER_ALLPARAMETERS, + DSPROPERTY_EAXBUFFER_DIRECT, + DSPROPERTY_EAXBUFFER_DIRECTHF, + DSPROPERTY_EAXBUFFER_ROOM, + DSPROPERTY_EAXBUFFER_ROOMHF, + DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, + DSPROPERTY_EAXBUFFER_OBSTRUCTION, + DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, + DSPROPERTY_EAXBUFFER_OCCLUSION, + DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, + DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, + DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, + DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, + DSPROPERTY_EAXBUFFER_FLAGS +} DSPROPERTY_EAX_BUFFERPROPERTY; + +// OR these flags with property id +#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately +#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later +#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | \ + DSPROPERTY_EAXBUFFER_IMMEDIATE) + +// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS +// - all levels are hundredths of decibels +// +// NOTE: This structure may change in future EAX versions. +// It is recommended to initialize fields by name: +// myBuffer.lDirect = 0; +// myBuffer.lDirectHF = -200; +// ... +// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ; +// instead of: +// myBuffer = { 0, -200, ... , 0x00000003 }; +// +typedef struct _EAXBUFFERPROPERTIES +{ + LONG lDirect; // direct path level + LONG lDirectHF; // direct path level at high frequencies + LONG lRoom; // room effect level + LONG lRoomHF; // room effect level at high frequencies + FLOAT flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect + LONG lObstruction; // main obstruction control (attenuation at high frequencies) + FLOAT flObstructionLFRatio; // obstruction low-frequency level re. main control + LONG lOcclusion; // main occlusion control (attenuation at high frequencies) + FLOAT flOcclusionLFRatio; // occlusion low-frequency level re. main control + FLOAT flOcclusionRoomRatio; // occlusion room effect level re. main control + LONG lOutsideVolumeHF; // outside sound cone level at high frequencies + FLOAT flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF + DWORD dwFlags; // modifies the behavior of properties +} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES; + +// Used by DSPROPERTY_EAXBUFFER_FLAGS +// TRUE: value is computed automatically - property is an offset +// FALSE: value is used directly +// +// Note: The number and order of flags may change in future EAX versions. +// To insure future compatibility, use flag defines as follows: +// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO; +// instead of: +// myFlags = 0x00000003; +// +#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF +#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM +#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF + +#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use + +// property ranges and defaults: + +#define EAXBUFFER_MINDIRECT (-10000) +#define EAXBUFFER_MAXDIRECT 1000 +#define EAXBUFFER_DEFAULTDIRECT 0 + +#define EAXBUFFER_MINDIRECTHF (-10000) +#define EAXBUFFER_MAXDIRECTHF 0 +#define EAXBUFFER_DEFAULTDIRECTHF 0 + +#define EAXBUFFER_MINROOM (-10000) +#define EAXBUFFER_MAXROOM 1000 +#define EAXBUFFER_DEFAULTROOM 0 + +#define EAXBUFFER_MINROOMHF (-10000) +#define EAXBUFFER_MAXROOMHF 0 +#define EAXBUFFER_DEFAULTROOMHF 0 + +#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f +#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f +#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f + +#define EAXBUFFER_MINOBSTRUCTION (-10000) +#define EAXBUFFER_MAXOBSTRUCTION 0 +#define EAXBUFFER_DEFAULTOBSTRUCTION 0 + +#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f +#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f +#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f + +#define EAXBUFFER_MINOCCLUSION (-10000) +#define EAXBUFFER_MAXOCCLUSION 0 +#define EAXBUFFER_DEFAULTOCCLUSION 0 + +#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f +#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f +#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f + +#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f +#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f +#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 0.5f + +#define EAXBUFFER_MINOUTSIDEVOLUMEHF (-10000) +#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0 +#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0 + +#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f +#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f +#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f + +#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | \ + EAXBUFFERFLAGS_ROOMAUTO | \ + EAXBUFFERFLAGS_ROOMHFAUTO) + +// Material transmission presets +// 3 values in this order: +// 1: occlusion (or obstruction) +// 2: occlusion LF Ratio (or obstruction LF Ratio) +// 3: occlusion Room Ratio + +// Single window material preset +#define EAX_MATERIAL_SINGLEWINDOW (-2800) +#define EAX_MATERIAL_SINGLEWINDOWLF 0.71f +#define EAX_MATERIAL_SINGLEWINDOWROOMRATIO 0.43f + +// Double window material preset +#define EAX_MATERIAL_DOUBLEWINDOW (-5000) +#define EAX_MATERIAL_DOUBLEWINDOWHF 0.40f +#define EAX_MATERIAL_DOUBLEWINDOWROOMRATIO 0.24f + +// Thin door material preset +#define EAX_MATERIAL_THINDOOR (-1800) +#define EAX_MATERIAL_THINDOORLF 0.66f +#define EAX_MATERIAL_THINDOORROOMRATIO 0.66f + +// Thick door material preset +#define EAX_MATERIAL_THICKDOOR (-4400) +#define EAX_MATERIAL_THICKDOORLF 0.64f +#define EAX_MATERIAL_THICKDOORROOMRTATION 0.27f + +// Wood wall material preset +#define EAX_MATERIAL_WOODWALL (-4000) +#define EAX_MATERIAL_WOODWALLLF 0.50f +#define EAX_MATERIAL_WOODWALLROOMRATIO 0.30f + +// Brick wall material preset +#define EAX_MATERIAL_BRICKWALL (-5000) +#define EAX_MATERIAL_BRICKWALLLF 0.60f +#define EAX_MATERIAL_BRICKWALLROOMRATIO 0.24f + +// Stone wall material preset +#define EAX_MATERIAL_STONEWALL (-6000) +#define EAX_MATERIAL_STONEWALLLF 0.68f +#define EAX_MATERIAL_STONEWALLROOMRATIO 0.20f + +// Curtain material preset +#define EAX_MATERIAL_CURTAIN (-1200) +#define EAX_MATERIAL_CURTAINLF 0.15f +#define EAX_MATERIAL_CURTAINROOMRATIO 1.00f + + +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif diff --git a/Sources/Engine/Sound/ov_functions.h b/Sources/Engine/Sound/ov_functions.h new file mode 100644 index 0000000..9bc81ca --- /dev/null +++ b/Sources/Engine/Sound/ov_functions.h @@ -0,0 +1,11 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +// DLLFUNCTION(dll, output, name, inputs, params, required) + +DLLFUNCTION( OVF, int, ov_clear, (OggVorbis_File *vf), 4, 0) +DLLFUNCTION( OVF, int, ov_open, (FILE *f, OggVorbis_File *vf, char *initial, long ibytes), 16,0); +DLLFUNCTION( OVF, int, ov_open_callbacks, (void *datasource, OggVorbis_File *vf, char *initial, long ibytes, ov_callbacks callbacks), 32,0); +DLLFUNCTION( OVF, long, ov_read, (OggVorbis_File *vf,char *buffer,int length, int bigendianp,int word,int sgned,int *bitstream), 28,0); +DLLFUNCTION( OVF, vorbis_info *, ov_info, (OggVorbis_File *vf,int link), 8,0); +DLLFUNCTION( OVF, int, ov_time_seek, (OggVorbis_File *vf, double pos), 12,0); diff --git a/Sources/Engine/StdH.cpp b/Sources/Engine/StdH.cpp new file mode 100644 index 0000000..95c0896 --- /dev/null +++ b/Sources/Engine/StdH.cpp @@ -0,0 +1,3 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" diff --git a/Sources/Engine/StdH.h b/Sources/Engine/StdH.h new file mode 100644 index 0000000..7a2d829 --- /dev/null +++ b/Sources/Engine/StdH.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +#define ENGINE_INTERNAL 1 +#define ENGINE_EXPORTS 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for qsort +#include // for FPU control + +#include + +#include +#include +#include // for timers + +#include +#include \ No newline at end of file diff --git a/Sources/Engine/Templates/AllocationArray.cpp b/Sources/Engine/Templates/AllocationArray.cpp new file mode 100644 index 0000000..8a100ce --- /dev/null +++ b/Sources/Engine/Templates/AllocationArray.cpp @@ -0,0 +1,202 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +#ifndef SE_INCL_ALLOCATIONARRAY_CPP +#define SE_INCL_ALLOCATIONARRAY_CPP +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include + +extern BOOL _bAllocationArrayParanoiaCheck; + +/* + * Default constructor. + */ +template +inline CAllocationArray::CAllocationArray(void) : + CStaticArray(), + aa_aiFreeElements() +{ + aa_ctAllocationStep = 256; +} + +/* + * Destructor. + */ +template +inline CAllocationArray::~CAllocationArray(void) { +}; + +/* Destroy all objects, and reset the array to initial (empty) state. */ +template +inline void CAllocationArray::Clear(void) { + // delete the objects themselves + CStaticArray::Clear(); + // clear array of free indices + aa_aiFreeElements.Clear(); +} + + /* + * Set how many elements to allocate when stack overflows. + */ +template +inline void CAllocationArray::SetAllocationStep(INDEX ctStep) +{ + ASSERT(ctStep>0); + aa_ctAllocationStep = ctStep; +}; + +/* + * Create a given number of objects. + */ +template +inline void CAllocationArray::New(INDEX iCount) { + // never call this! + ASSERT(FALSE); +}; + +/* + * Destroy all objects. + */ +template +inline void CAllocationArray::Delete(void) { + // never call this! + ASSERT(FALSE); +} + +/* Alocate a new object. */ +template +inline INDEX CAllocationArray::Allocate(void) +{ + // if there are no more free indices + if (aa_aiFreeElements.Count()==0) { + // remember old size + INDEX ctOldSize = CStaticArray::Count(); + // expand the array by the allocation step + Expand(ctOldSize+aa_ctAllocationStep); + // create new free indices + INDEX *piNewFree = aa_aiFreeElements.Push(aa_ctAllocationStep); + // fill them up + for(INDEX iNew=0; iNew +inline void CAllocationArray::Free(INDEX iToFree) +{ +#ifndef NDEBUG + // must be within pool limits + ASSERT(iToFree>=0 && iToFree::Count()); + // must not be free + if (_bAllocationArrayParanoiaCheck) { + ASSERT(IsAllocated(iToFree)); + } +#endif + // push its index on top of the free stack + aa_aiFreeElements.Push() = iToFree; +} + +/* Free all objects, but keep pool space. */ +template +inline void CAllocationArray::FreeAll(void) +{ + // clear the free array + aa_aiFreeElements.PopAll(); + // push as much free elements as there is pool space + INDEX ctSize = CStaticArray::Count(); + INDEX *piNewFree = aa_aiFreeElements.Push(ctSize); + // fill them up + for(INDEX iNew=0; iNew +inline BOOL CAllocationArray::IsAllocated(INDEX i) +{ + // must be within pool limits + ASSERT(i>=0 && i::Count()); + // for each free index + INDEX ctFree = aa_aiFreeElements.Count(); + for(INDEX iFree=0; iFree +inline Type &CAllocationArray::operator[](INDEX iObject) +{ +#ifndef NDEBUG + ASSERT(this!=NULL); + // must be within pool limits + ASSERT(iObject>=0 && iObject::Count()); + // must not be free + if (_bAllocationArrayParanoiaCheck) { + ASSERT(IsAllocated(iObject)); + } +#endif + return CStaticArray::operator[](iObject); +} +template +inline const Type &CAllocationArray::operator[](INDEX iObject) const +{ +#ifndef NDEBUG + ASSERT(this!=NULL); + // must be within pool limits + ASSERT(iObject>=0 && iObject::Count()); + // must not be free + if (_bAllocationArrayParanoiaCheck) { + ASSERT(IsAllocated(iObject)); + } +#endif + return CStaticArray::operator[](iObject); +} +/* Get number of allocated objects in array. */ +template +INDEX CAllocationArray::Count(void) const +{ + ASSERT(this!=NULL); + // it is pool size without the count of free elements + return CStaticArray::Count()-aa_aiFreeElements.Count(); +} + +/* Get index of a object from it's pointer. */ +template +INDEX CAllocationArray::Index(Type *ptObject) +{ + ASSERT(this!=NULL); + INDEX i = CStaticArray::Index(ptMember); + ASSERT(IsAllocated(i)); + return i; +} + +/* Assignment operator. */ +template +CAllocationArray &CAllocationArray::operator=( + const CAllocationArray &aaOriginal) +{ + ASSERT(this!=NULL); + (CStaticArray&)(*this) = (CStaticArray&)aaOriginal; + aa_aiFreeElements = aaOriginal.aa_aiFreeElements; + aa_ctAllocationStep = aaOriginal.aa_ctAllocationStep; +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/AllocationArray.h b/Sources/Engine/Templates/AllocationArray.h new file mode 100644 index 0000000..9a159bd --- /dev/null +++ b/Sources/Engine/Templates/AllocationArray.h @@ -0,0 +1,58 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ALLOCATIONARRAY_H +#define SE_INCL_ALLOCATIONARRAY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Template class for stack-like array with static allocation of objects. + */ +template +class CAllocationArray : public CStaticArray { +public: + CStaticStackArray aa_aiFreeElements; // array of indices of free elements + INDEX aa_ctAllocationStep; // how many elements to allocate when pool overflows +public: + /* Default constructor. */ + inline CAllocationArray(void); + /* Destructor. */ + inline ~CAllocationArray(void); + + /* Set how many elements to allocate when pool overflows. */ + inline void SetAllocationStep(INDEX ctStep); + /* Create a given number of objects - do not use. */ + inline void New(INDEX iCount); + /* Destroy all objects - do not use. */ + inline void Delete(void); + /* Destroy all objects, and reset the array to initial (empty) state. */ + inline void Clear(void); + + /* Alocate a new object. */ + inline INDEX Allocate(void); + /* Free object with given index. */ + inline void Free(INDEX iToFree); + /* Free all objects, but keep pool space. */ + inline void FreeAll(void); + + // check if an index is allocated (slow!) + inline BOOL IsAllocated(INDEX i); + + /* Random access operator. */ + inline Type &operator[](INDEX iObject); + inline const Type &operator[](INDEX iObject) const; + /* Get number of allocated objects in array. */ + INDEX Count(void) const; + /* Get index of a object from it's pointer. */ + INDEX Index(Type *ptObject); + + /* Assignment operator. */ + CAllocationArray &operator=(const CAllocationArray &aaOriginal); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/BSP.cpp b/Sources/Engine/Templates/BSP.cpp new file mode 100644 index 0000000..00a618f --- /dev/null +++ b/Sources/Engine/Templates/BSP.cpp @@ -0,0 +1,1302 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + + +// epsilon value used for BSP cutting +//#define BSP_EPSILON ((Type) 0.015625) // 1/2^6 ~= 1.5 cm +#define BSP_EPSILON Type((1.0/65536.0)*4*mth_fCSGEpsilon) // 1/2^16 +//#define BSP_EPSILON Type(0.00390625) // 1/2^8 +//#define EPSILON (1.0f/8388608.0f) // 1/2^23 +//#define EPSILON 0.0009765625f // 1/2^10 +//#define EPSILON 0.03125f // 1/2^5 +//#define EPSILON 0.00390625f // 1/2^8 + +template +inline BOOL EpsilonEq(const Type &a, const Type &b) { return Abs(a-b)<=BSP_EPSILON; }; +template +inline BOOL EpsilonNe(const Type &a, const Type &b) { return Abs(a-b)> BSP_EPSILON; }; + +///////////////////////////////////////////////////////////////////// +// BSP vertex + +/* + * Assignment operator with coordinates only. + */ +template +BSPVertex &BSPVertex::operator=(const Vector &vCoordinates) +{ + *(Vector *)this = vCoordinates; + return *this; +} + +///////////////////////////////////////////////////////////////////// +// BSP vertex container + +/* + * Default constructor. + */ +template +BSPVertexContainer::BSPVertexContainer(void) +{ +} + +template +void BSPVertexContainer::AddVertex(const Vector &vPoint) +{ + bvc_aVertices.Push() = vPoint; +} + +/* + * Initialize for a direction. + */ +template +void BSPVertexContainer::Initialize(const Vector &vDirection) +{ + bvc_vDirection = vDirection; + + // init array of vertices + bvc_aVertices.SetAllocationStep(32); + + // find largest axis of direction vector + INDEX iMaxAxis = 0; + Type tMaxAxis = (Type)0;//vDirection(1); + for( INDEX iAxis=1; iAxis<=iDimensions; iAxis++) { + if( Abs(vDirection(iAxis)) > Abs(tMaxAxis) ) { + tMaxAxis = vDirection(iAxis); + iMaxAxis = iAxis; + } + } + +/* This assert would seem natural here, but it is not possible because of parallel planes! + // must be greater or equal than minimal max axis of any normalized vector in that space + ASSERT( Abs(tMaxAxis) > (1.0/sqrt(double(iDimensions))-0.01) ); +*/ + + // remember that axis index and sign for sorting + bvc_iMaxAxis = iMaxAxis; + bvc_tMaxAxisSign = Sgn(tMaxAxis); +} + +/* + * Unnitialize. + */ +template +void BSPVertexContainer::Uninitialize(void) +{ + // delete array of vertices + bvc_aVertices.Delete(); + // destroy axis index and sign + bvc_iMaxAxis = -1; + bvc_tMaxAxisSign = (Type)0; +} + +static INDEX qsort_iCompareAxis; + +template +class CVertexComparator { +public: + /* + * Compare two vertices. + */ + static inline int CompareVertices(const Vector &vx0, const Vector &vx1, INDEX iAxis) + { + if (vx0(iAxis)vx1(iAxis)) return 1; + else return 0; + } + + /* + * Compare two vertices for quick-sort. + */ + static int qsort_CompareVertices_plus( const void *pvVertex0, const void *pvVertex1) + { + BSPVertex &vx0 = *(BSPVertex *)pvVertex0; + BSPVertex &vx1 = *(BSPVertex *)pvVertex1; + return +CompareVertices(vx0, vx1, qsort_iCompareAxis); + } + static int qsort_CompareVertices_minus( const void *pvVertex0, const void *pvVertex1) + { + BSPVertex &vx0 = *(BSPVertex *)pvVertex0; + BSPVertex &vx1 = *(BSPVertex *)pvVertex1; + return -CompareVertices(vx0, vx1, qsort_iCompareAxis); + } +}; +/* + * Sort vertices in this container along the largest axis of container direction. + */ +template +void BSPVertexContainer::Sort(void) +{ + // if there are no vertices, or the container is not line + if (bvc_aVertices.Count()==0 || IsPlannar()) { + // do not attempt to sort + return; + } + + // sort by max. axis + qsort_iCompareAxis = bvc_iMaxAxis; + + // if the sign of axis is positive + if (bvc_tMaxAxisSign>0) { + // sort them normally + if (bvc_aVertices.Count()>0) { + qsort(&bvc_aVertices[0], bvc_aVertices.Count(), sizeof(BSPVertex), + CVertexComparator::qsort_CompareVertices_plus); + } + // if it is negative + } else { + // sort them inversely + if (bvc_aVertices.Count()>0) { + qsort(&bvc_aVertices[0], bvc_aVertices.Count(), sizeof(BSPVertex), + CVertexComparator::qsort_CompareVertices_minus); + } + } +} + +/* + * Elliminate paired vertices. + */ +template +void BSPVertexContainer::ElliminatePairedVertices(void) +{ + // if there are no vertices, or the container is not line + if (bvc_aVertices.Count()==0 || IsPlannar()) { + // do not attempt to sort + return; + } + + // initially, last vertices are far away + Type tLastInside; tLastInside = (Type)32000; + BSPVertex *pbvxLastInside = NULL; + + // for all vertices in container + for (INDEX iVertex=0; iVertex &bvx = bvc_aVertices[iVertex]; // reference to this vertex + Type t = bvx(bvc_iMaxAxis); // coordinate along max. axis + + // if last inside vertex is next to this one + if ( EpsilonEq(t, tLastInside) ) { + // last vertex is far away + tLastInside = (Type)32000; + IFDEBUG(pbvxLastInside = NULL); + + // otherwise + } else { + // make this last inside vertex + tLastInside = t; + pbvxLastInside = &bvx; + } + } +} + +/* + * Create edges from vertices in one container -- must be sorted before. + */ +template +void BSPVertexContainer::CreateEdges(CDynamicArray > &abed, ULONG ulEdgeTag) +{ + // if there are no vertices, or the container is not line + if (bvc_aVertices.Count()==0 || IsPlannar()) { + // do not attempt to sort + return; + } + + // initially, edge is inactive + BOOL bActive = FALSE; + BSPEdge *pbed = NULL; + + // for all vertices in container + for (INDEX iVertex=0; iVertex &bvx = bvc_aVertices[iVertex]; // reference to this vertex + + // if edge is inactive + if (!bActive) { + // create new edge + pbed = abed.New(); + pbed->bed_ulEdgeTag = ulEdgeTag; + // set start vertex + pbed->bed_vVertex0 = bvx; + } else { + // set end vertex + pbed->bed_vVertex1 = bvx; + // trash edge pointer + IFDEBUG(pbed = NULL); + } + // toggle edge + bActive = !bActive; + } +} + +///////////////////////////////////////////////////////////////////// +// BSP edge + +/* + * Constructor with two vectors. + */ +template +BSPEdge::BSPEdge(const Vector &vVertex0, const Vector &vVertex1, ULONG ulTag) + : bed_vVertex0(vVertex0) + , bed_vVertex1(vVertex1) + , bed_ulEdgeTag(ulTag) +{} + +// remove all edges marked for removal +template +void BSPEdge::RemoveMarkedBSPEdges(CDynamicArray > &abed) +{ + typedef BSPEdge edge_t; // local declaration, to fix macro expansion in FOREACHINDYNAMICARRAY + // conut edges left + INDEX ctEdgesLeft = 0; + {FOREACHINDYNAMICARRAY(abed, edge_t, itbed) { + if (itbed->bed_ulEdgeTag != 0) { + ctEdgesLeft++; + } + }} + // make a copy of array without removed edges + CDynamicArray > abed2; + abed2.New(ctEdgesLeft); + abed2.Lock(); + INDEX iedNew = 0; + {FOREACHINDYNAMICARRAY(abed, edge_t, itbed) { + edge_t &bed = *itbed; + if (bed.bed_ulEdgeTag != 0) { + abed2[iedNew] = bed; + iedNew++; + } + }} + abed2.Unlock(); + // use that copy instead the original array + abed.Clear(); + abed.MoveArray(abed2); +} + +// optimize a polygon made out of BSP edges using tag information +template +void BSPEdge::OptimizeBSPEdges(CDynamicArray > &abed) +{ + typedef BSPEdge edge_t; // local declaration, to fix macro expansion in FOREACHINDYNAMICARRAY + + // if there are no edges + if (abed.Count()==0) { + // do nothing + return; + } + BOOL bSomeJoined; + // repeat + do { + bSomeJoined = FALSE; + // for each edge + {FOREACHINDYNAMICARRAY(abed, edge_t, itbed1) { + edge_t &bed1 = *itbed1; + // if it is already marked + if (bed1.bed_ulEdgeTag == 0) { + // skip it + continue; + } + // if it is dummy edge + if (bed1.bed_vVertex0==bed1.bed_vVertex1) { + // mark it for removal + bSomeJoined = TRUE; + bed1.bed_ulEdgeTag = 0; + // skip it + continue; + } + + // for each other edge + {FOREACHINDYNAMICARRAY(abed, edge_t, itbed2) { + edge_t &bed2 = *itbed2; + if (&bed1==&bed2) { + continue; + } + // if it is already marked + if (bed2.bed_ulEdgeTag == 0) { + // skip it + continue; + } + // if they originate from same edge (plane) + if (bed1.bed_ulEdgeTag == bed2.bed_ulEdgeTag) { + // if they are complemented + if (bed1.bed_vVertex0==bed2.bed_vVertex1 && bed1.bed_vVertex1==bed2.bed_vVertex0) { + // marked them both + bSomeJoined = TRUE; + bed1.bed_ulEdgeTag = 0; + bed2.bed_ulEdgeTag = 0; + // skip them both + break; + } + // if second one continues after first one + if (bed1.bed_vVertex1==bed2.bed_vVertex0) { + // extend end of first edge to the end of second one + bed1.bed_vVertex1=bed2.bed_vVertex1; + bSomeJoined = TRUE; + // marked second edge + bed2.bed_ulEdgeTag = 0; + // if second one continues before first one + } else if (bed1.bed_vVertex0==bed2.bed_vVertex1) { + // extend start of first edge to the start of second one + bed1.bed_vVertex0=bed2.bed_vVertex0; + bSomeJoined = TRUE; + // marked second edge + bed2.bed_ulEdgeTag = 0; + } + } + }} + }} + // while some edges can be joined + } while(bSomeJoined); + + // remove all marked edges + RemoveMarkedBSPEdges(abed); +} + +///////////////////////////////////////////////////////////////////// +// BSP polygon + +/* + * Add an edge to the polygon. + */ +template +inline void BSPPolygon::AddEdge(const Vector &vPoint0, const Vector &vPoint1, ULONG ulTag) +{ + *bpo_abedPolygonEdges.New() = BSPEdge(vPoint0, vPoint1, ulTag); +} + +///////////////////////////////////////////////////////////////////// +// BSP node + +/* + * Recursive destructor. + */ +template +void BSPNode::DeleteBSPNodeRecursively(void) +{ + // delete sub-trees first, before deleting this node + if (bn_pbnFront!=NULL) { + bn_pbnFront->DeleteBSPNodeRecursively(); + } + if (bn_pbnBack!=NULL) { + bn_pbnBack->DeleteBSPNodeRecursively(); + } + delete this; +} + +/* + * Constructor for a leaf node. + */ +template +BSPNode::BSPNode(enum BSPNodeLocation bnl) + : bn_bnlLocation(bnl) + , bn_pbnFront(NULL) + , bn_pbnBack(NULL) +{ + ASSERT(bnl == BNL_INSIDE || bnl == BNL_OUTSIDE); +} + +/* + * Constructor for a branch node. + */ +template +BSPNode::BSPNode(const Plane &plSplitPlane, ULONG ulPlaneTag, + BSPNode &bnFront, BSPNode &bnBack) + : Plane(plSplitPlane) + , bn_pbnFront(&bnFront) + , bn_pbnBack(&bnBack) + , bn_bnlLocation(BNL_BRANCH) + , bn_ulPlaneTag(ulPlaneTag) +{ +} + +/* + * Constructor for cloning a bsp (sub)tree. + */ +template +BSPNode::BSPNode(BSPNode &bnRoot) + : Plane(bnRoot) // copy the plane + , bn_bnlLocation(bnRoot.bn_bnlLocation) // copy the location + , bn_ulPlaneTag(bnRoot.bn_ulPlaneTag) // copy the plane tag +{ + // if this has a front child + if (bnRoot.bn_pbnFront != NULL) { + // clone front sub tree + bn_pbnFront = new BSPNode(*bnRoot.bn_pbnFront); + // otherwise + } else { + // no front sub tree + bn_pbnFront = NULL; + } + + // if this has a back child + if (bnRoot.bn_pbnBack != NULL) { + // clone back sub tree + bn_pbnBack = new BSPNode(*bnRoot.bn_pbnBack); + // otherwise + } else { + // no back sub tree + bn_pbnBack = NULL; + } +} + +/* Test if a sphere is inside, outside, or intersecting. (Just a trivial rejection test) */ +template +FLOAT BSPNode::TestSphere(const Vector &vSphereCenter, Type tSphereRadius) const +{ + // if this is an inside node + if (bn_bnlLocation == BNL_INSIDE) { + // it is inside + return 1; + // if this is an outside node + } else if (bn_bnlLocation == BNL_OUTSIDE) { + // it is outside + return -1; + // if this is a branch + } else { + ASSERT(bn_bnlLocation == BNL_BRANCH); + // test the sphere against the split plane + Type tCenterDistance = PointDistance(vSphereCenter); + // if the sphere is in front of the plane + if (tCenterDistance > +tSphereRadius) { + // recurse down the front node + return bn_pbnFront->TestSphere(vSphereCenter, tSphereRadius); + // if the sphere is behind the plane + } else if (tCenterDistance < -tSphereRadius) { + // recurse down the back node + return bn_pbnBack->TestSphere(vSphereCenter, tSphereRadius); + // if the sphere is split by the plane + } else { + // if front node touches + FLOAT fFront = bn_pbnFront->TestSphere(vSphereCenter, tSphereRadius); + if (fFront==0) { + // it touches + return 0; + } + // if back node touches + FLOAT fBack = bn_pbnBack->TestSphere(vSphereCenter, tSphereRadius); + if (fBack==0) { + // it touches + return 0; + } + // if front and back have same classification + if (fFront==fBack) { + // return it + return fFront; + // if front and back have different classification + } else { + // it touches + return 0; + } + } + } +} +/* Test if a box is inside, outside, or intersecting. (Just a trivial rejection test) */ +template +FLOAT BSPNode::TestBox(const OBBox &box) const +{ + // if this is an inside node + if (bn_bnlLocation == BNL_INSIDE) { + // it is inside + return 1; + // if this is an outside node + } else if (bn_bnlLocation == BNL_OUTSIDE) { + // it is outside + return -1; + // if this is a branch + } else { + ASSERT(bn_bnlLocation == BNL_BRANCH); + // test the box against the split plane + Type tTest = box.TestAgainstPlane(*this); + // if the sphere is in front of the plane + if (tTest>0) { + // recurse down the front node + return bn_pbnFront->TestBox(box); + // if the sphere is behind the plane + } else if (tTest<0) { + // recurse down the back node + return bn_pbnBack->TestBox(box); + // if the sphere is split by the plane + } else { + // if front node touches + FLOAT fFront = bn_pbnFront->TestBox(box); + if (fFront==0) { + // it touches + return 0; + } + // if back node touches + FLOAT fBack = bn_pbnBack->TestBox(box); + if (fBack==0) { + // it touches + return 0; + } + // if front and back have same classification + if (fFront==fBack) { + // return it + return fFront; + // if front and back have different classification + } else { + // it touches + return 0; + } + } + } +} + +// find minimum/maximum parameters of points on a line that are inside - recursive +template +void BSPNode::FindLineMinMax( + BSPLine &bl, + const Vector &v0, + const Vector &v1, + Type t0, Type t1) +{ + // if this is an inside node + if (bn_bnlLocation == BNL_INSIDE) { + // just update min/max + bl.bl_tMin = Min(bl.bl_tMin, t0); + bl.bl_tMax = Max(bl.bl_tMax, t1); + return; + // if this is an outside node + } else if (bn_bnlLocation == BNL_OUTSIDE) { + // do nothing + return; + // if this is a branch + } else { + ASSERT(bn_bnlLocation == BNL_BRANCH); + // test the points against the split plane + Type tD0 = PointDistance(v0); + Type tD1 = PointDistance(v1); + // if both are front + if (tD0>=0 && tD1>=0) { + // recurse down the front node + bn_pbnFront->FindLineMinMax(bl, v0, v1, t0, t1); + return; + // if both are back + } else if (tD0<0 && tD1<0) { + // recurse down the back node + bn_pbnBack->FindLineMinMax(bl, v0, v1, t0, t1); + return; + // if on different sides + } else { + // find split point + Type tFraction = tD0/(tD0-tD1); + Vector vS = v0+(v1-v0)*tFraction; + Type tS = t0+(t1-t0)*tFraction; + // if first is front + if (tD0>=0) { + // recurse first part down the front node + bn_pbnFront->FindLineMinMax(bl, v0, vS, t0, tS); + // recurse second part down the back node + bn_pbnBack->FindLineMinMax(bl, vS, v1, tS, t1); + return; + // if first is back + } else { + // recurse first part down the back node + bn_pbnBack->FindLineMinMax(bl, v0, vS, t0, tS); + // recurse second part down the front node + bn_pbnFront->FindLineMinMax(bl, vS, v1, tS, t1); + return; + } + } + } +} + +///////////////////////////////////////////////////////////////////// +// BSP cutter + +/* + * Constructor for splitting a polygon with a BSP tree. + */ +template +BSPCutter::BSPCutter(BSPPolygon &bpoPolygon, BSPNode &bnRoot) +{ + // cut the polygon with entire tree + CutPolygon(bpoPolygon, bnRoot); +} + +/* + * Destructor. + */ +template +BSPCutter::~BSPCutter(void) +{ +} + +/* + * Cut a polygon with a BSP tree. + */ +template +void BSPCutter::CutPolygon(BSPPolygon &bpoPolygon, BSPNode &bn) +{ + // if the polygon has no edges + if (bpoPolygon.bpo_abedPolygonEdges.Count()==0) { + // skip cutting + return; + } + + // if this node is inside node + if (bn.bn_bnlLocation == BNL_INSIDE) { + // add entire polygon to inside part + bc_abedInside.MoveArray(bpoPolygon.bpo_abedPolygonEdges); + + // if this node is outside node + } else if (bn.bn_bnlLocation == BNL_OUTSIDE) { + // add entire polygon to outside part + bc_abedOutside.MoveArray(bpoPolygon.bpo_abedPolygonEdges); + + // if this node is a branch + } else if (bn.bn_bnlLocation == BNL_BRANCH) { + BSPPolygon bpoFront; // part of polygon in front of this splitter + BSPPolygon bpoBack; // part of polygon behind this splitter + + // split the polygon with split plane of this node + BOOL bOnPlane = SplitPolygon(bpoPolygon, (Plane &)bn, bn.bn_ulPlaneTag, bpoFront, bpoBack); + + // if the polygon is not on the split plane + if (!bOnPlane) { + // recursively split front part with front part of bsp + CutPolygon(bpoFront, *bn.bn_pbnFront); + // recursively split back part with back part of bsp + CutPolygon(bpoBack, *bn.bn_pbnBack); + + // if the polygon is on the split plane + } else { + BSPNode *pbnFront; // front node (relative to the polygon orientation) + BSPNode *pbnBack; // back node (relative to the polygon orientation) + + // check the direction of the polygon with the front direction of the split plane + Type tDirection = (Vector &)bpoPolygon%(Vector &)bn; + // if the directions are same + if (tDirection > +BSP_EPSILON) { + // make nodes relative to polygon same as relative to the split plane + pbnFront = bn.bn_pbnFront; + pbnBack = bn.bn_pbnBack; + + // if the directions are opposite + } else if (tDirection < -BSP_EPSILON) { + // make nodes relative to polygon opposite as relative to the split plane + pbnFront = bn.bn_pbnBack; + pbnBack = bn.bn_pbnFront; + // if the directions are indeterminate + } else { + // that must not be + ASSERT(FALSE); + } + + // cut it with front part of bsp + BSPCutter bcFront(bpoPolygon, *pbnFront); + // there must be no on-border parts + ASSERT(bcFront.bc_abedBorderInside.Count()==0 && bcFront.bc_abedBorderOutside.Count()==0); + + // make a polygon from parts that are inside in front part of BSP + BSPPolygon bpoInsideFront((Plane &)bpoPolygon, bcFront.bc_abedInside, bpoPolygon.bpo_ulPlaneTag); + // cut them with back part of bsp + BSPCutter bcBackInsideFront(bpoInsideFront, *pbnBack); + + // make a polygon from parts that are outside in front part of BSP + BSPPolygon bpoOutsideFront((Plane &)bpoPolygon, bcFront.bc_abedOutside, bpoPolygon.bpo_ulPlaneTag); + // cut them with back part of bsp + BSPCutter bcBackOutsideFront(bpoOutsideFront, *pbnBack); + + // add parts that are inside both in front and back to inside part + bc_abedInside.MoveArray(bcBackInsideFront.bc_abedInside); + // add parts that are outside both in front and back to outside part + bc_abedOutside.MoveArray(bcBackOutsideFront.bc_abedOutside); + + // add parts that are inside in front and outside back to on-border-inside-part + bc_abedBorderInside.MoveArray(bcBackInsideFront.bc_abedOutside); + // add parts that are outside in front and inside back to on-border-outside-part + bc_abedBorderOutside.MoveArray(bcBackOutsideFront.bc_abedInside); + } + } else { + ASSERTALWAYS("Bad node type"); + } +} + +/* + * Split a polygon with a plane. + * -- returns FALSE if polygon is laying on the plane + */ +template +BOOL BSPCutter::SplitPolygon(BSPPolygon &bpoPolygon, const Plane &plSplitPlane, ULONG ulPlaneTag, + BSPPolygon &bpoFront, BSPPolygon &bpoBack) +{ + (Plane &)bpoFront = (Plane &)bpoPolygon; + bpoFront.bpo_ulPlaneTag = bpoPolygon.bpo_ulPlaneTag; + (Plane &)bpoBack = (Plane &)bpoPolygon; + bpoBack.bpo_ulPlaneTag = bpoPolygon.bpo_ulPlaneTag; + + // calculate the direction of split line + Vector vSplitDirection = ((Vector &)plSplitPlane) * (Vector &)bpoPolygon; + + // if the polygon is parallel with the split plane + if (vSplitDirection.Length() < +BSP_EPSILON) { + // calculate the distance of the polygon from the split plane + Type fDistance = plSplitPlane.PlaneDistance(bpoPolygon); + + // if the polygon is in front of plane + if (fDistance > +BSP_EPSILON) { + // move all edges to front array + bpoFront.bpo_abedPolygonEdges.MoveArray(bpoPolygon.bpo_abedPolygonEdges); + // the polygon is not on the plane + return FALSE; + + // if the polygon is behind the plane + } else if (fDistance < -BSP_EPSILON) { + // move all edges to back array + bpoBack.bpo_abedPolygonEdges.MoveArray(bpoPolygon.bpo_abedPolygonEdges); + // the polygon is not on the plane + return FALSE; + + // if the polygon is on the plane + } else { + // just return so + return TRUE; + } + + // if the polygon is not parallel with the split plane + } else { + // initialize front and back vertex containers + BSPVertexContainer bvcFront, bvcBack; + bvcFront.Initialize(vSplitDirection); + bvcBack.Initialize(-vSplitDirection); + + typedef BSPEdge edge_t; // local declaration, to fix macro expansion in FOREACHINDYNAMICARRAY + // for each edge in polygon + {FOREACHINDYNAMICARRAY(bpoPolygon.bpo_abedPolygonEdges, edge_t, itbed) { + // split the edge + SplitEdge(itbed->bed_vVertex0, itbed->bed_vVertex1, itbed->bed_ulEdgeTag, plSplitPlane, + bpoFront, bpoBack, bvcFront, bvcBack); + }} + + // sort vertex containers + bvcFront.Sort(); + bvcBack.Sort(); + // elliminate paired vertices + bvcFront.ElliminatePairedVertices(); + bvcBack.ElliminatePairedVertices(); + // create more front polygon edges from front vertex container + bvcFront.CreateEdges(bpoFront.bpo_abedPolygonEdges, ulPlaneTag); + // create more back polygon edges from back vertex container + bvcBack.CreateEdges(bpoBack.bpo_abedPolygonEdges, ulPlaneTag); + + // the polygon is not on the plane + return FALSE; + } +} + +/* + * Split an edge with a plane. + */ +template +void BSPCutter::SplitEdge(const Vector &vPoint0, const Vector &vPoint1, ULONG ulEdgeTag, + const Plane &plSplitPlane, + BSPPolygon &bpoFront, BSPPolygon &bpoBack, + BSPVertexContainer &bvcFront, BSPVertexContainer &bvcBack) +{ + + // calculate point distances from clip plane + Type tDistance0 = plSplitPlane.PointDistance(vPoint0); + Type tDistance1 = plSplitPlane.PointDistance(vPoint1); + + /* ---- first point behind plane ---- */ + if (tDistance0 < -BSP_EPSILON) { + + // if both are back + if (tDistance1 < -BSP_EPSILON) { + // add the whole edge to back node + bpoBack.AddEdge(vPoint0, vPoint1, ulEdgeTag); + // no split points + + // if first is back, second front + } else if (tDistance1 > +BSP_EPSILON) { + // calculate intersection coordinates + Vector vPointMid = vPoint0-(vPoint0-vPoint1)*tDistance0/(tDistance0-tDistance1); + // add front part to front node + bpoFront.AddEdge(vPointMid, vPoint1, ulEdgeTag); + // add back part to back node + bpoBack.AddEdge(vPoint0, vPointMid, ulEdgeTag); + // add split point to front _and_ back part of splitter + bvcFront.AddVertex(vPointMid); + bvcBack.AddVertex(vPointMid); + + // if first is back, second on the plane + } else { + // add the whole edge to back node + bpoBack.AddEdge(vPoint0, vPoint1, ulEdgeTag); + // add second point to back part of splitter + bvcBack.AddVertex(vPoint1); + } + + /* ---- first point in front of plane ---- */ + } else if (tDistance0 > +BSP_EPSILON) { + // if first is front, second back + if (tDistance1 < -BSP_EPSILON) { + // calculate intersection coordinates + Vector vPointMid = vPoint1-(vPoint1-vPoint0)*tDistance1/(tDistance1-tDistance0); + // add front part to front node + bpoFront.AddEdge(vPoint0, vPointMid, ulEdgeTag); + // add back part to back node + bpoBack.AddEdge(vPointMid, vPoint1, ulEdgeTag); + // add split point to front _and_ back part of splitter + bvcFront.AddVertex(vPointMid); + bvcBack.AddVertex(vPointMid); + + + // if both are front + } else if (tDistance1 > +BSP_EPSILON) { + // add the whole edge to front node + bpoFront.AddEdge(vPoint0, vPoint1, ulEdgeTag); + // no split points + + // if first is front, second on the plane + } else { + // add the whole edge to front node + bpoFront.AddEdge(vPoint0, vPoint1, ulEdgeTag); + // add second point to front part of splitter + bvcFront.AddVertex(vPoint1); + } + + /* ---- first point on the plane ---- */ + } else { + // if first is on the plane, second back + if (tDistance1 < -BSP_EPSILON) { + // add the whole edge to back node + bpoBack.AddEdge(vPoint0, vPoint1, ulEdgeTag); + // add first point to back part of splitter + bvcBack.AddVertex(vPoint0); + + // if first is on the plane, second in front of the plane + } else if (tDistance1 > +BSP_EPSILON) { + // add the whole edge to front node + bpoFront.AddEdge(vPoint0, vPoint1, ulEdgeTag); + // add first point to front part of splitter + bvcFront.AddVertex(vPoint0); + + // if both are on the plane + } else { + // check the direction of the edge with the front direction of the splitter + Type tDirection = (vPoint1-vPoint0)%bvcFront.bvc_vDirection; + // if the directions are same + if (tDirection > +BSP_EPSILON) { + // add the whole edge to front node + bpoFront.AddEdge(vPoint0, vPoint1, ulEdgeTag); + // add both points to front part of the splitter + bvcFront.AddVertex(vPoint0); + bvcFront.AddVertex(vPoint1); + + + // if the directions are opposite + } else if (tDirection < -BSP_EPSILON) { + // add the whole edge to back node + bpoBack.AddEdge(vPoint0, vPoint1, ulEdgeTag); + // add both points to back part of the splitter + bvcBack.AddVertex(vPoint0); + bvcBack.AddVertex(vPoint1); + + + // if the directions are indeterminate + } else { + // that must mean that there is no edge in fact + //ASSERT(Type(vPoint1-vPoint0) < 2*BSP_EPSILON); //!!!! + } + } + } +} + +///////////////////////////////////////////////////////////////////// +// BSP tree + +/* + * Default constructor. + */ +template +BSPTree::BSPTree(void) +{ + bt_pbnRoot = NULL; +} + +/* + * Destructor. + */ +template +BSPTree::~BSPTree(void) +{ + Destroy(); +} + +/* + * Constructor with array of polygons oriented inwards. + */ +template +BSPTree::BSPTree(CDynamicArray > &abpoPolygons) +{ + bt_pbnRoot = NULL; + Create(abpoPolygons); +} + +/* + * Create bsp-subtree from array of polygons oriented inwards. + */ +template +BSPNode *BSPTree::CreateSubTree(CDynamicArray > &abpoPolygons) +{ + // local declarations, to fix macro expansion in FOREACHINDYNAMICARRAY + typedef BSPEdge edge_t; + typedef BSPPolygon polygon_t; + ASSERT(abpoPolygons.Count()>=1); + + // use first polygon as splitter + abpoPolygons.Lock(); + BSPPolygon bpoSplitter = abpoPolygons[0]; + abpoPolygons.Unlock(); + // tags must be valid + ASSERT(bpoSplitter.bpo_ulPlaneTag!=-1); + + // create two new polygon arrays - back and front + CDynamicArray > abpoFront, abpoBack; + + // for each polygon in this array + {FOREACHINDYNAMICARRAY(abpoPolygons, polygon_t, itbpo) { + BSPPolygon bpoFront, bpoBack; + + // tags must be valid + ASSERT(itbpo->bpo_ulPlaneTag!=-1); + // if the polygon has plane tag same as the tag of the splitter + if (itbpo->bpo_ulPlaneTag == bpoSplitter.bpo_ulPlaneTag) { + // they are assumed coplanar, so skip it + continue; + } + + // split it by the plane of splitter polygon + BOOL bOnPlane = BSPCutter::SplitPolygon(itbpo.Current(), + bpoSplitter, bpoSplitter.bpo_ulPlaneTag, bpoFront, bpoBack); + + // if the polygon is not coplanar with the splitter + if (!bOnPlane) { + + // if there are some parts that are front + if (bpoFront.bpo_abedPolygonEdges.Count()>0) { + // create a polygon in front array and add all inside parts to it + BSPPolygon *pbpo = abpoFront.New(1); + pbpo->bpo_abedPolygonEdges.MoveArray(bpoFront.bpo_abedPolygonEdges); + *(Plane *)pbpo = itbpo.Current(); + pbpo->bpo_ulPlaneTag = itbpo->bpo_ulPlaneTag; + } + // if there are some parts that are back + if (bpoBack.bpo_abedPolygonEdges.Count()>0) { + // create a polygon in back array and add all outside parts to it + BSPPolygon *pbpo = abpoBack.New(1); + pbpo->bpo_abedPolygonEdges.MoveArray(bpoBack.bpo_abedPolygonEdges); + *(Plane *)pbpo = itbpo.Current(); + pbpo->bpo_ulPlaneTag = itbpo->bpo_ulPlaneTag; + } + } + }} + + // free this array (to not consume too much memory) + abpoPolygons.Clear(); + + BSPNode *pbnFront, *pbnBack; + // if there is some polygon in front array + if (abpoFront.Count()>0) { + // create front subtree using front array + pbnFront = CreateSubTree(abpoFront); + // otherwise + } else { + // make front node an inside leaf node + pbnFront = new BSPNode(BNL_INSIDE); + } + + // if there is some polygon in back array + if (abpoBack.Count()>0) { + // create back subtree using back array + pbnBack = CreateSubTree(abpoBack); + // otherwise + } else { + // make back node an outside leaf node + pbnBack = new BSPNode(BNL_OUTSIDE); + } + + // make a splitter node with the front and back nodes + return new BSPNode(bpoSplitter, bpoSplitter.bpo_ulPlaneTag, *pbnFront, *pbnBack); +} + +/* + * Create bsp-tree from array of polygons oriented inwards. + */ +template +void BSPTree::Create(CDynamicArray > &abpoPolygons) +{ + typedef BSPPolygon polygon_t; // local declaration, to fix macro expansion in FOREACHINDYNAMICARRAY + + // free eventual existing tree + Destroy(); + + // create the tree using the recursive function + bt_pbnRoot = CreateSubTree(abpoPolygons); + // move the tree to array + MoveNodesToArray(); +} + +/* + * Destroy bsp-tree. + */ +template +void BSPTree::Destroy(void) +{ + // if tree is in array + if (bt_abnNodes.Count()>0) { + // clear array + bt_abnNodes.Clear(); + bt_pbnRoot = NULL; + // if there is some free tree + } else if (bt_pbnRoot != NULL) { + // delete it + bt_pbnRoot->DeleteBSPNodeRecursively(); + bt_pbnRoot = NULL; + } +} + +/* Test if a sphere could touch any of inside nodes. (Just a trivial rejection test) */ +template +FLOAT BSPTree::TestSphere(const Vector &vSphereCenter, Type tSphereRadius) const +{ + if (bt_pbnRoot==NULL) return FALSE; + // just start recursive testing at root node + return bt_pbnRoot->TestSphere(vSphereCenter, tSphereRadius); +} +/* Test if a box is inside, outside, or intersecting. (Just a trivial rejection test) */ +template +FLOAT BSPTree::TestBox(const OBBox &box) const +{ + if (bt_pbnRoot==NULL) return FALSE; + // just start recursive testing at root node + return bt_pbnRoot->TestBox(box); +} + +// find minimum/maximum parameters of points on a line that are inside +template +void BSPTree::FindLineMinMax( + const Vector &v0, + const Vector &v1, + Type &tMin, + Type &tMax) const +{ + // init line + BSPLine bl; + bl.bl_tMin = UpperLimit(Type(0)); + bl.bl_tMax = LowerLimit(Type(0)); + + // recursively split it + bt_pbnRoot->FindLineMinMax(bl, v0, v1, Type(0), Type(1)); + + // return the min/max + tMin = bl.bl_tMin; + tMax = bl.bl_tMax; +} + +static INDEX _ctNextIndex; +/* Move one subtree to array. */ +template +void BSPTree::MoveSubTreeToArray(BSPNode *pbnSubtree) +{ + // if this is no node + if (pbnSubtree==NULL) { + // do nothing + return; + } + // first move all subnodes + MoveSubTreeToArray(pbnSubtree->bn_pbnFront); + MoveSubTreeToArray(pbnSubtree->bn_pbnBack); + + // get the node in array + BSPNode &bnInArray = bt_abnNodes[_ctNextIndex]; + _ctNextIndex--; + + // copy properties to the array node + (Plane&)bnInArray = (Plane&)*pbnSubtree; + bnInArray.bn_bnlLocation = pbnSubtree->bn_bnlLocation; + bnInArray.bn_ulPlaneTag = pbnSubtree->bn_ulPlaneTag; + // let plane tag hold pointer to node in array + pbnSubtree->bn_ulPlaneTag = (ULONG)&bnInArray; + + // remap pointers to subnodes + if (pbnSubtree->bn_pbnFront==NULL) { + bnInArray.bn_pbnFront = NULL; + } else { + bnInArray.bn_pbnFront = (BSPNode*)pbnSubtree->bn_pbnFront->bn_ulPlaneTag; + } + if (pbnSubtree->bn_pbnBack==NULL) { + bnInArray.bn_pbnBack = NULL; + } else { + bnInArray.bn_pbnBack = (BSPNode*)pbnSubtree->bn_pbnBack->bn_ulPlaneTag; + } +} + +/* Count nodes in subtree. */ +template +INDEX BSPTree::CountNodes(BSPNode *pbnSubtree) +{ + if (pbnSubtree==NULL) { + return 0; + } else { + return 1+ + CountNodes(pbnSubtree->bn_pbnFront)+ + CountNodes(pbnSubtree->bn_pbnBack); + } +} + +/* Move all nodes to array. */ +template +void BSPTree::MoveNodesToArray(void) +{ + // if there is no tree + if (bt_pbnRoot == NULL) { + // do nothing + return; + } + + // count nodes + INDEX ctNodes = CountNodes(bt_pbnRoot); + // allocate large enough array + bt_abnNodes.New(ctNodes); + // start at the end of array + _ctNextIndex = ctNodes-1; + // recusively remap all nodes + MoveSubTreeToArray(bt_pbnRoot); + + // delete the old nodes + bt_pbnRoot->DeleteBSPNodeRecursively(); + + // first node is always at start of array + bt_pbnRoot = &bt_abnNodes[0]; +} + +/* Read/write entire bsp tree to disk. */ +template +void BSPTree::Read_t(CTStream &strm) // throw char * +{ + // free eventual existing tree + Destroy(); + + // read current version and size + INDEX iVersion; + SLONG slSize; + strm>>iVersion>>slSize; + ASSERT(iVersion==1); + + // read count of nodes and create array + INDEX ctNodes; + strm>>ctNodes; + ASSERT(slSize==(SLONG)(sizeof(INDEX)+ctNodes*sizeof(BSPNode))); + bt_abnNodes.New(ctNodes); + // for each node + for(INDEX iNode=0; iNode &bn = bt_abnNodes[iNode]; + // read it from disk + strm.Read_t(&(Plane&)bn, sizeof(Plane)); + strm>>(INDEX&)bn.bn_bnlLocation; + + INDEX iFront; + strm>>iFront; + if (iFront==-1) { + bn.bn_pbnFront=NULL; + } else { + bn.bn_pbnFront = &bt_abnNodes[iFront]; + } + + INDEX iBack; + strm>>iBack; + if (iBack==-1) { + bn.bn_pbnBack=NULL; + } else { + bn.bn_pbnBack = &bt_abnNodes[iBack]; + } + + strm>>bn.bn_ulPlaneTag; + } + + // check end id + strm.ExpectID_t("BSPE"); // bsp end + + // first node is always at start of array + if (bt_abnNodes.Count()>0) { + bt_pbnRoot = &bt_abnNodes[0]; + } else { + bt_pbnRoot = NULL; + } +} + +template +void BSPTree::Write_t(CTStream &strm) // throw char * +{ + INDEX ctNodes = bt_abnNodes.Count(); + + // calculate size of chunk to write + SLONG slSize = sizeof(INDEX)+ctNodes*sizeof(BSPNode); + // write current version and size + strm< &bn = bt_abnNodes[iNode]; + // write it to disk + strm.Write_t(&(Plane&)bn, sizeof(Plane)); + strm<<(INDEX&)bn.bn_bnlLocation; + + INDEX iFront; + if (bn.bn_pbnFront==NULL) { + iFront=-1; + } else { + iFront = bt_abnNodes.Index(bn.bn_pbnFront); + } + strm< + +/* + * Template class for BSP-tree + */ +template +class BSPTree { +public: + CStaticArray< BSPNode > bt_abnNodes; // all nodes are stored here together here + + /* Create bsp-subtree from array of polygons oriented inwards. */ + BSPNode *CreateSubTree(CDynamicArray > &arbpoPolygons); + /* Move one subtree to array. */ + void MoveSubTreeToArray(BSPNode *pbnSubtree); + /* Count nodes in subtree. */ + INDEX CountNodes(BSPNode *pbnSubtree); + + /* Move all nodes to array. */ + void MoveNodesToArray(void); + +public: + BSPNode *bt_pbnRoot; // root node of BSP-tree + + /* Default constructor. */ + BSPTree(void); + /* Destructor. */ + ~BSPTree(void); + /* Constructor with array of polygons oriented inwards. */ + BSPTree(CDynamicArray > &arbpoPolygons); + + /* Create bsp-tree from array of polygons oriented inwards. */ + void Create(CDynamicArray > &arbpoPolygons); + /* Destroy bsp-tree. */ + void Destroy(void); + // find minimum/maximum parameters of points on a line that are inside + void FindLineMinMax( + const Vector &v0, + const Vector &v1, + Type &tMin, + Type &tMax) const; + /* Test if a sphere is inside, outside, or intersecting. (Just a trivial rejection test) */ + FLOAT TestSphere(const Vector &vSphereCenter, Type tSphereRadius) const; + /* Test if a box is inside, outside, or intersecting. (Just a trivial rejection test) */ + FLOAT TestBox(const OBBox &box) const; + /* Read/write entire bsp tree to disk. */ + void Read_t(CTStream &strm); // throw char * + void Write_t(CTStream &strm); // throw char * +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/BSP_internal.h b/Sources/Engine/Templates/BSP_internal.h new file mode 100644 index 0000000..36a20bd --- /dev/null +++ b/Sources/Engine/Templates/BSP_internal.h @@ -0,0 +1,194 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_BSP_INTERNAL_H +#define SE_INCL_BSP_INTERNAL_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +extern FLOAT mth_fCSGEpsilon; + +/* + * Type used to identify BSP-node locations + */ +enum BSPNodeLocation { + BNL_ILLEGAL=0, // for illegal value + BNL_INSIDE, // inside leaf node + BNL_OUTSIDE, // outside leaf node + BNL_BRANCH, // branch node, unspecified location +}; + +/* + * Template class for BSP vertex + */ +template +class BSPVertex : public Vector { +public: + /* Default constructor. */ + inline BSPVertex(void) {}; + + /* Assignment operator with coordinates only. */ + inline BSPVertex &operator=(const Vector &vCoordinates); +}; + +/* + * Template class for BSP vertex container + */ +template +class BSPVertexContainer { +public: + INDEX bvc_iMaxAxis; // index of largest axis of direction + Type bvc_tMaxAxisSign; // sign of largest axis of direction + + CStaticStackArray > bvc_aVertices; // array of vertices +public: + Vector bvc_vDirection; // direction of the split line + + /* Default constructor. */ + BSPVertexContainer(void); + + /* Initialize for a direction. */ + void Initialize(const Vector &vDirection); + /* Uninitialize. */ + void Uninitialize(void); + + /* Check if this container is in an unusable state (polygon coplanar with the splitter).*/ + inline BOOL IsPlannar(void) { return bvc_iMaxAxis==0; }; + + /* Add a new vertex. */ + inline void AddVertex(const Vector &vPoint); + + /* Sort vertices in this container along the largest axis of container direction. */ + void Sort(void); + /* Elliminate paired vertices. */ + void ElliminatePairedVertices(void); + /* Create edges from vertices in one container -- must be sorted before. */ + void CreateEdges(CDynamicArray > &abedAll, ULONG ulEdgeTag); +}; + +/* + * Template class for BSP edge + */ +template +class BSPEdge { +public: + Vector bed_vVertex0; // edge vertices + Vector bed_vVertex1; + ULONG bed_ulEdgeTag; // tags for BSPs with tagged edges/planes + + /* Default constructor. */ + inline BSPEdge(void) {}; + /* Constructor with two vectors. */ + inline BSPEdge(const Vector &vVertex0, const Vector &vVertex1, ULONG ulTag); + /* Clear the object. */ + inline void Clear(void) {}; + // remove all edges marked for removal + static void RemoveMarkedBSPEdges(CDynamicArray > &abed); + // optimize a polygon made out of BSP edges using tag information + static void OptimizeBSPEdges(CDynamicArray > &abed); +}; + +/* + * Template class for polygons used in creating BSP-trees + */ +template +class BSPPolygon : public Plane { +public: + CDynamicArray > bpo_abedPolygonEdges; // array of edges in the polygon + ULONG bpo_ulPlaneTag; // tags for BSPs with tagged planes (-1 for no tag) + + /* Add an edge to the polygon. */ + inline void AddEdge(const Vector &vPoint0, const Vector &vPoint1, ULONG ulTag); + + /* Default constructor. */ + inline BSPPolygon(void) : bpo_ulPlaneTag(-1) {}; + /* Constructor with array of edges and plane. */ + inline BSPPolygon( + Plane &plPlane, CDynamicArray > abedPolygonEdges, ULONG ulPlaneTag) + : Plane(plPlane) + , bpo_abedPolygonEdges(abedPolygonEdges) + , bpo_ulPlaneTag(ulPlaneTag) + {}; + + /* Clear the object. */ + inline void Clear(void) {bpo_abedPolygonEdges.Clear();}; +}; + +template +class BSPLine { +public: + Type bl_tMin; + Type bl_tMax; +}; + +/* + * Template class for BSP-tree node of arbitrary dimensions and arbitrary type of members + */ +template +class BSPNode : public Plane { // split plane +public: + enum BSPNodeLocation bn_bnlLocation; // location of bsp node + + BSPNode *bn_pbnFront; // pointer to child node in front of split plane + BSPNode *bn_pbnBack; // pointer to child node behind split plane + ULONG bn_ulPlaneTag; // tags for BSPs with tagged planes (-1 for no tag) + +public: + /* Defualt constructor (for arrays only). */ + inline BSPNode(void) {}; + /* Constructor for a leaf node. */ + inline BSPNode(enum BSPNodeLocation bnl); + /* Constructor for a branch node. */ + inline BSPNode(const Plane &plSplitPlane, ULONG ulPlaneTag, + BSPNode &bnFront, BSPNode &bnBack); + /* Constructor for cloning a bsp (sub)tree. */ + BSPNode(BSPNode &bnRoot); + /* Recursive destructor. */ + void DeleteBSPNodeRecursively(void); + + // find minimum/maximum parameters of points on a line that are inside - recursive + void FindLineMinMax(BSPLine &bl, + const Vector &v0, + const Vector &v1, + Type t0, Type t1); + + /* Test if a sphere is inside, outside, or intersecting. (Just a trivial rejection test) */ + FLOAT TestSphere(const Vector &vSphereCenter, Type tSphereRadius) const; + /* Test if a box is inside, outside, or intersecting. (Just a trivial rejection test) */ + FLOAT TestBox(const OBBox &box) const; +}; + +/* + * Template class that performs polygon cuts using BSP-tree + */ +template +class BSPCutter { +public: + /* Split an edge with a plane. */ + static inline void SplitEdge(const Vector &vPoint0, const Vector &vPoint1, ULONG ulEdgeTag, + const Plane &plSplitPlane, + BSPPolygon &abedFront, BSPPolygon &abedBack, + BSPVertexContainer &bvcFront, BSPVertexContainer &bvcBack); + + /* Cut a polygon with a BSP tree. */ + void CutPolygon(BSPPolygon &bpoPolygon, BSPNode &bn); + +public: + CDynamicArray > bc_abedInside; // edges of inside part of polygon + CDynamicArray > bc_abedOutside; // edges of outside part of polygon + CDynamicArray > bc_abedBorderInside; // edges of border part of polygon facing inwards + CDynamicArray > bc_abedBorderOutside;// edges of border part of polygon facing outwards + + /* Split a polygon with a plane. */ + static inline BOOL SplitPolygon(BSPPolygon &bpoPolygon, const Plane &plPlane, ULONG ulPlaneTag, + BSPPolygon &bpoFront, BSPPolygon &bpoBack); + + /* Constructor for splitting a polygon with a BSP tree. */ + BSPCutter(BSPPolygon &bpoPolygon, BSPNode &bnRoot); + /* Destructor. */ + ~BSPCutter(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/DynamicArray.cpp b/Sources/Engine/Templates/DynamicArray.cpp new file mode 100644 index 0000000..2c18527 --- /dev/null +++ b/Sources/Engine/Templates/DynamicArray.cpp @@ -0,0 +1,451 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_DYNAMICARRAY_CPP +#define SE_INCL_DYNAMICARRAY_CPP +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +#include + +// iterate whole dynamic array +/* NOTE: The iterator defined by this macro must be destroyed before adding/removing + * elements in the array. To do so, embed the for loop in additional curly braces. + */ +#define FOREACHINDYNAMICARRAY(array, type, iter) \ + for(CDynamicArrayIterator iter(array); !iter.IsPastEnd(); iter.MoveToNext() ) + +class CDABlockInfo { +public: + CListNode bi_ListNode; + void *bi_Memory; +}; + +/* + * Default constructor. + */ +template +CDynamicArray::CDynamicArray(void) { +#if CHECKARRAYLOCKING + // not locked + da_LockCt = 0; +#endif + // set to empty array of pointers + da_Pointers = NULL; + da_Count = 0; +} + +/* + * Copy constructor. + */ +template +CDynamicArray::CDynamicArray(CDynamicArray &daOriginal) +{ +#if CHECKARRAYLOCKING + // not locked + da_LockCt = 0; +#endif + // set to empty array of pointers + da_Pointers = NULL; + da_Count = 0; + + // call assignment operator + (*this) = daOriginal; +} +/* + * Destructor -- frees all memory. + */ +template +CDynamicArray::~CDynamicArray(void) { + Clear(); +} + +/* + * Destroy all objects, and reset the array to initial (empty) state. + */ +template +void CDynamicArray::Clear(void) { + ASSERT(this!=NULL); + // if any pointers are allocated + if (da_Count!=0) { + /* NOTE: We must explicitly clear objects here, because array deleting + * does not call object destructors! + */ + // for all pointers + for (INDEX iPointer=0; iPointerbi_Memory; + // free memory used by block info + delete &itBlock.Current(); + } +} + +/* Random access operator. */ +template +Type &CDynamicArray::operator[](INDEX iObject) { + return *Pointer(iObject); +}; +template +const Type &CDynamicArray::operator[](INDEX iObject) const { + return *Pointer(iObject); +}; + +/* + * Grow pointer array by a given number of members. + */ +template +void CDynamicArray::GrowPointers(INDEX iCount) { + ASSERT(this!=NULL && iCount>0); + // if not yet allocated + if (da_Count==0) { + // check that the pointers are really not allocated + ASSERT(da_Pointers==NULL); + // allocate + da_Count=iCount; + da_Pointers = (Type **)AllocMemory(da_Count*sizeof(Type*)); + // if allocated + } else { + // grow to new size + da_Count+=iCount; + GrowMemory((void **)&da_Pointers, da_Count*sizeof(Type*)); + } +} + +/* + * Shrink pointer array by a given number of members. + */ +template +void CDynamicArray::ShrinkPointers(INDEX iCount) { + ASSERT(this!=NULL && iCount>0); + // check that the pointers are allocated + ASSERT(da_Pointers!=NULL); + + // decrement count + da_Count-=iCount; + // checked that it has not dropped below zero + ASSERT(da_Count>=0); + // if all pointers are freed by this + if (da_Count==0) { + // free the array + FreeMemory(da_Pointers); + da_Pointers = NULL; + // if some remain + } else { + // shrink to new size + ShrinkMemory((void **)&da_Pointers, da_Count*sizeof(Type*)); + } +} + +/* + * Allocate a new memory block. + */ +template +Type *CDynamicArray::AllocBlock(INDEX iCount) { + ASSERT(this!=NULL && iCount>0); + Type *ptBlock; + CDABlockInfo *pbi; + + // allocate the memory and call constructors for all members (+1 for cache-prefetch opt) + ptBlock = new Type[iCount+1]; // call vector constructor, for better performance + // allocate the block info + pbi = new CDABlockInfo; + // add the block to list + da_BlocksList.AddTail(pbi->bi_ListNode); + // remember block memory + pbi->bi_Memory = ptBlock; + return ptBlock; +} + +/* + * Create a given number of new members. + */ +template +Type *CDynamicArray::New(INDEX iCount /*= 1*/) { + ASSERT(this!=NULL && iCount>=0); + // if no new members are needed in fact + if (iCount==0) { + // do nothing + return NULL; + } + Type *ptBlock; + INDEX iOldCount = da_Count; + + // grow the pointer table + GrowPointers(iCount); + // allocate the memory block + ptBlock = AllocBlock(iCount); + // set pointers + for(INDEX iNewMember=0; iNewMember +void CDynamicArray::Delete(Type *ptMember) { + ASSERT(this!=NULL); +#if CHECKARRAYLOCKING + // check that not locked for indices + ASSERT(da_LockCt == 0); +#endif + + // clear the object + ::Clear(*ptMember); + + INDEX iMember=GetIndex(ptMember); + // move last pointer here + da_Pointers[iMember]=da_Pointers[da_Count-1]; + // shrink pointers by one + ShrinkPointers(1); + // do nothing to free memory + //!!!! +} + +/* + * Get pointer to a member from it's index. + */ +template +Type *CDynamicArray::Pointer(INDEX iMember) { + ASSERT(this!=NULL); + // check that index is currently valid + ASSERT(iMember>=0 && iMember0); +#endif + return da_Pointers[iMember]; +} +template +const Type *CDynamicArray::Pointer(INDEX iMember) const { + ASSERT(this!=NULL); + // check that index is currently valid + ASSERT(iMember>=0 && iMember0); +#endif + return da_Pointers[iMember]; +} + +/* + * Lock for getting indices. + */ +template +void CDynamicArray::Lock(void) { + ASSERT(this!=NULL); +#if CHECKARRAYLOCKING + ASSERT(da_LockCt>=0); + // increment lock counter + da_LockCt++; +#endif +} + +/* + * Unlock after getting indices. + */ +template +void CDynamicArray::Unlock(void) { + ASSERT(this!=NULL); +#if CHECKARRAYLOCKING + da_LockCt--; + ASSERT(da_LockCt>=0); +#endif +} + +/* + * Get index of a member from it's pointer. + */ +template +INDEX CDynamicArray::Index(Type *ptMember) { + ASSERT(this!=NULL); +#if CHECKARRAYLOCKING + // check that locked for indices + ASSERT(da_LockCt>0); +#endif + return GetIndex(ptMember); +} + +/* + * Get index of a member from it's pointer without locking. + */ +template +INDEX CDynamicArray::GetIndex(Type *ptMember) { + ASSERT(this!=NULL); + // slow !!!! + // check all members + for (INDEX iMember=0; iMember::Index(): Not a member of this array!"); + return 0; +} + +/* + * Get number of elements in array. + */ +template +INDEX CDynamicArray::Count(void) const { + ASSERT(this!=NULL); + return da_Count; +} + +/* + * Assignment operator. + */ +template +CDynamicArray &CDynamicArray::operator=(CDynamicArray &arOriginal) +{ + ASSERT(this!=NULL); + ASSERT(&arOriginal!=NULL); + ASSERT(this!=&arOriginal); + // clear previous contents + Clear(); + // get count of elements in original array + INDEX ctOriginal = arOriginal.Count(); + // if the other array has no elements + if (ctOriginal ==0) { + // no assignment + return*this; + } + // create that much elements + Type *atNew = New(ctOriginal); + + // copy them all + arOriginal.Lock(); + for (INDEX iNew=0; iNew +void CDynamicArray::MoveArray(CDynamicArray &arOther) +{ + ASSERT(this!=NULL && &arOther!=NULL); +#if CHECKARRAYLOCKING + // check that not locked for indices + ASSERT(da_LockCt==0 && arOther.da_LockCt==0); +#endif + + // if the other array has no elements + if (arOther.da_Count==0) { + // no moving + return; + } + + // remember number of elements + INDEX iOldCount = da_Count; + // grow pointer array to add the pointers to elements of other array + GrowPointers(arOther.da_Count); + // for each pointer in other array + for (INDEX iOtherPointer=0; iOtherPointer +class CDynamicArrayIterator { +private: + INDEX dai_Index; // index of current element + CDynamicArray &dai_Array; // reference to array +public: + /* Constructor for given array. */ + inline CDynamicArrayIterator(CDynamicArray &da); + /* Destructor. */ + inline ~CDynamicArrayIterator(void); + + /* Move to next object. */ + inline void MoveToNext(void); + /* Check if finished. */ + inline BOOL IsPastEnd(void); + /* Get current element. */ + Type &Current(void) { return *dai_Array.Pointer(dai_Index); } + Type &operator*(void) { return *dai_Array.Pointer(dai_Index); } + operator Type *(void) { return dai_Array.Pointer(dai_Index); } + Type *operator->(void) { return dai_Array.Pointer(dai_Index); } +}; + + +/* + * Constructor for given array. + */ +template +inline CDynamicArrayIterator::CDynamicArrayIterator(CDynamicArray &da) : dai_Array(da) { + // lock indices + dai_Array.Lock(); + dai_Index = 0; +} + +/* + * Destructor. + */ +template +inline CDynamicArrayIterator::~CDynamicArrayIterator(void) { + // unlock indices + dai_Array.Unlock(); + dai_Index = -1; +} + +/* + * Move to next object. + */ +template +inline void CDynamicArrayIterator::MoveToNext(void) { + ASSERT(this!=NULL); + dai_Index++; +} + +/* + * Check if finished. + */ +template +inline BOOL CDynamicArrayIterator::IsPastEnd(void) { + ASSERT(this!=NULL); + return dai_Index>=dai_Array.Count(); +} + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/DynamicArray.h b/Sources/Engine/Templates/DynamicArray.h new file mode 100644 index 0000000..2b0f106 --- /dev/null +++ b/Sources/Engine/Templates/DynamicArray.h @@ -0,0 +1,70 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_DYNAMICARRAY_H +#define SE_INCL_DYNAMICARRAY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Template class for array with dynamic allocation of objects. + */ +template +class CDynamicArray { +public: + CListHead da_BlocksList; // list of allocated memory blocks + Type **da_Pointers; // array of object pointers + INDEX da_Count; // number of objects +#if CHECKARRAYLOCKING + INDEX da_LockCt; // lock counter for getting indices +#endif + + /* Grow pointer array by a given number of indices. */ + void GrowPointers(INDEX iCount); + /* Shrink pointer array by a given number of indices. */ + void ShrinkPointers(INDEX iCount); + /* Allocate a new memory block. */ + Type *AllocBlock(INDEX iCount); + /* Get index of an object from it's pointer without locking. */ + INDEX GetIndex(Type *ptMember); +public: + /* Default constructor. */ + CDynamicArray(void); + /* Copy constructor. */ + CDynamicArray(CDynamicArray &daOriginal); + /* Destructor -- frees all memory. */ + ~CDynamicArray(void); + + /* Create a given number of new objects. */ + Type *New(INDEX iCount = 1); + /* Destroy a given member. */ + void Delete(Type *ptObject); + /* Destroy all objects, and reset the array to initial (empty) state. */ + void Clear(void); + + /* Get pointer to a object from it's index. */ + Type *Pointer(INDEX iObject); + const Type *Pointer(INDEX iObject) const; + /* Random access operator. */ + inline Type &operator[](INDEX iObject); + inline const Type &operator[](INDEX iObject) const; + /* Assignment operator. */ + CDynamicArray &operator=(CDynamicArray &arOriginal); + /* Move all elements of another array into this one. */ + void MoveArray(CDynamicArray &arOther); + + /* Lock for getting indices. */ + void Lock(void); + /* Unlock after getting indices. */ + void Unlock(void); + /* Get index of a object from it's pointer. */ + INDEX Index(Type *ptObject); + /* Get number of objects in array. */ + INDEX Count(void) const; +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/DynamicContainer.cpp b/Sources/Engine/Templates/DynamicContainer.cpp new file mode 100644 index 0000000..3dcd2eb --- /dev/null +++ b/Sources/Engine/Templates/DynamicContainer.cpp @@ -0,0 +1,306 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_DYNAMICCONTAINER_CPP +#define SE_INCL_DYNAMICCONTAINER_CPP +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include + +/* + * Default constructor. + */ +template +CDynamicContainer::CDynamicContainer(void) { +#if CHECKARRAYLOCKING + // not locked + dc_LockCt = 0; +#endif +} + +/* + * Copy constructor. + */ +template +CDynamicContainer::CDynamicContainer(CDynamicContainer &dcOriginal) +{ +#if CHECKARRAYLOCKING + // not locked + dc_LockCt = 0; +#endif + + // call assignment operator + (*this) = dcOriginal; +} +/* + * Destructor -- removes all objects. + */ +template +CDynamicContainer::~CDynamicContainer(void) { + Clear(); +} + +/* + * Remove all objects, and reset the array to initial (empty) state. + */ +template +void CDynamicContainer::Clear(void) { + ASSERT(this!=NULL); + CStaticStackArray::Clear(); +} + +/* + * Add a given object to container. + */ +template +void CDynamicContainer::Add(Type *ptNewObject) +{ + // set the new pointer + Push() = ptNewObject; +} + +/* + * Insert a given object to container at specified index. + */ +template +void CDynamicContainer::Insert(Type *ptNewObject, const INDEX iPos/*=0*/) +{ + // get number of member that need moving and add new one + const INDEX ctMovees = CStaticStackArray::Count() - iPos; + CStaticStackArray::Push(); + // move all members after insert position one place up + Type **pptInsertAt = this->sa_Array+iPos; + Type **pptMoveTo = pptInsertAt +1; + memmove( pptMoveTo, pptInsertAt, sizeof(Type*)*ctMovees); + // store pointer to newly inserted member at specified position + *pptInsertAt = ptNewObject; +} + +/* + * Remove a given object from container. + */ +template +void CDynamicContainer::Remove(Type *ptOldObject) +{ + ASSERT(this!=NULL); +#if CHECKARRAYLOCKING + // check that not locked for indices + ASSERT(dc_LockCt == 0); +#endif + + // find its index + INDEX iMember=GetIndex(ptOldObject); + // move last pointer here + sa_Array[iMember]=sa_Array[Count()-1]; + Pop(); +} + +/* Test if a given object is in the container. */ +template +BOOL CDynamicContainer::IsMember(Type *ptOldObject) +{ + ASSERT(this!=NULL); + // slow !!!! + // check all members + for (INDEX iMember=0; iMember +Type *CDynamicContainer::Pointer(INDEX iMember) { + ASSERT(this!=NULL); + // check that index is currently valid + ASSERT(iMember>=0 && iMember0); +#endif + return sa_Array[iMember]; +} +template +const Type *CDynamicContainer::Pointer(INDEX iMember) const { + ASSERT(this!=NULL); + // check that index is currently valid + ASSERT(iMember>=0 && iMember0); +#endif + return sa_Array[iMember]; +} + +/* + * Lock for getting indices. + */ +template +void CDynamicContainer::Lock(void) { + ASSERT(this!=NULL); +#if CHECKARRAYLOCKING + ASSERT(dc_LockCt>=0); + // increment lock counter + dc_LockCt++; +#endif +} + +/* + * Unlock after getting indices. + */ +template +void CDynamicContainer::Unlock(void) { + ASSERT(this!=NULL); +#if CHECKARRAYLOCKING + dc_LockCt--; + ASSERT(dc_LockCt>=0); +#endif +} + +/* + * Get index of a member from it's pointer. + */ +template +INDEX CDynamicContainer::Index(Type *ptMember) { + ASSERT(this!=NULL); + // check that locked for indices +#if CHECKARRAYLOCKING + ASSERT(dc_LockCt>0); +#endif + return GetIndex(ptMember); +} + +/* + * Get index of a member from it's pointer without locking. + */ +template +INDEX CDynamicContainer::GetIndex(Type *ptMember) { + ASSERT(this!=NULL); + // slow !!!! + // check all members + for (INDEX iMember=0; iMember<>::Index(): Not a member of this container!"); + return 0; +} + +/* Get first object in container (there must be at least one when calling this). */ +template +Type &CDynamicContainer::GetFirst(void) +{ + ASSERT(Count()>=1); + return *sa_Array[0]; +} + +/* + * Assignment operator. + */ +template +CDynamicContainer &CDynamicContainer::operator=(CDynamicContainer &coOriginal) +{ + CStaticStackArray::operator=(coOriginal); + return *this; +} + +/* + * Move all elements of another array into this one. + */ +template +void CDynamicContainer::MoveContainer(CDynamicContainer &coOther) +{ + ASSERT(this!=NULL && &coOther!=NULL); + // check that not locked for indices +#if CHECKARRAYLOCKING + ASSERT(dc_LockCt==0 && coOther.dc_LockCt==0); +#endif + CStaticStackArray::MoveArray(coOther); +} + +///////////////////////////////////////////////////////////////////// +// CDynamicContainerIterator + +/* + * Template class for iterating dynamic array. + */ +template +class CDynamicContainerIterator { +private: + INDEX dci_Index; // index of current element + CDynamicContainer &dci_Array; // reference to array +public: + /* Constructor for given array. */ + inline CDynamicContainerIterator(CDynamicContainer &da); + /* Destructor. */ + inline ~CDynamicContainerIterator(void); + + /* Move to next object. */ + inline void MoveToNext(void); + /* Check if finished. */ + inline BOOL IsPastEnd(void); + + /* Get current element. */ + Type &Current(void) { return *dci_Array.Pointer(dci_Index); } + Type &operator*(void) { return *dci_Array.Pointer(dci_Index); } + operator Type *(void) { return dci_Array.Pointer(dci_Index); } + Type *operator->(void) { return dci_Array.Pointer(dci_Index); } +}; + + +/* + * Constructor for given array. + */ +template +inline CDynamicContainerIterator::CDynamicContainerIterator(CDynamicContainer &da) : dci_Array(da) { + // lock indices + dci_Array.Lock(); + dci_Index = 0; +} + +/* + * Destructor. + */ +template +inline CDynamicContainerIterator::~CDynamicContainerIterator(void) { + // unlock indices + dci_Array.Unlock(); + dci_Index = -1; +} + +/* + * Move to next object. + */ +template +inline void CDynamicContainerIterator::MoveToNext(void) { + ASSERT(this!=NULL); + dci_Index++; +} + +/* + * Check if finished. + */ +template +inline BOOL CDynamicContainerIterator::IsPastEnd(void) { + ASSERT(this!=NULL); + return dci_Index>=dci_Array.Count(); +} + +// iterate whole dynamic container +/* NOTE: The iterator defined by this macro must be destroyed before adding/removing + * elements in the container. To do so, embed the for loop in additional curly braces. + */ +#define FOREACHINDYNAMICCONTAINER(container, type, iter) \ + for(CDynamicContainerIterator iter(container); !iter.IsPastEnd(); iter.MoveToNext() ) + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/DynamicContainer.h b/Sources/Engine/Templates/DynamicContainer.h new file mode 100644 index 0000000..9c1defa --- /dev/null +++ b/Sources/Engine/Templates/DynamicContainer.h @@ -0,0 +1,67 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_DYNAMICCONTAINER_H +#define SE_INCL_DYNAMICCONTAINER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + + +/* + * Template class for a container that holds references to objects of some class. + */ +template +class CDynamicContainer : public CStaticStackArray { +public: +#if CHECKARRAYLOCKING + INDEX da_LockCt; // lock counter for getting indices +#endif + + /* Get index of an object from it's pointer without locking. */ + INDEX GetIndex(Type *ptMember); +public: + /* Default constructor. */ + CDynamicContainer(void); + /* Copy constructor. */ + CDynamicContainer(CDynamicContainer &coOriginal); + /* Destructor -- frees all memory. */ + ~CDynamicContainer(void); + + /* Add a given object to container. */ + void Add(Type *ptNewObject); + /* Insert a given object to container at specified index. */ + void Insert(Type *ptNewObject, const INDEX iPos=0); + /* Remove a given object from container. */ + void Remove(Type *ptOldObject); + /* Remove all objects, and reset the container to initial (empty) state. */ + void Clear(void); + /* Test if a given object is in the container. */ + BOOL IsMember(Type *ptOldObject); + + /* Get pointer to a object from it's index. */ + Type *Pointer(INDEX iObject); + const Type *Pointer(INDEX iObject) const; + /* Random access operator. */ + inline Type &operator[](INDEX iObject) { return *Pointer(iObject); }; + inline const Type &operator[](INDEX iObject) const { return *Pointer(iObject); }; + /* Assignment operator. */ + CDynamicContainer &operator=(CDynamicContainer &coOriginal); + /* Move all elements of another container into this one. */ + void MoveContainer(CDynamicContainer &coOther); + + /* Lock for getting indices. */ + void Lock(void); + /* Unlock after getting indices. */ + void Unlock(void); + /* Get index of a object from it's pointer. */ + INDEX Index(Type *ptObject); + /* Get first object in container (there must be at least one when calling this). */ + Type &GetFirst(void); +}; + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/DynamicStackArray.cpp b/Sources/Engine/Templates/DynamicStackArray.cpp new file mode 100644 index 0000000..65f2367 --- /dev/null +++ b/Sources/Engine/Templates/DynamicStackArray.cpp @@ -0,0 +1,164 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_DYNAMICSTACKARRAY_CPP +#define SE_INCL_DYNAMICSTACKARRAY_CPP +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* + * Default constructor. + */ +template +inline CDynamicStackArray::CDynamicStackArray(void) : CDynamicArray() { + da_ctUsed=0; + da_ctAllocationStep = 256; + // lock the array on construction + CDynamicArray::Lock(); +} + +/* + * Destructor. + */ +template +inline CDynamicStackArray::~CDynamicStackArray(void) { + // lock the array on destruction + CDynamicArray::Unlock(); +}; + +/* Destroy all objects, and reset the array to initial (empty) state. */ +template +inline void CDynamicStackArray::Clear(void) { + CDynamicArray::Clear(); da_ctUsed = 0; +} + +/* + * Set how many elements to allocate when stack overflows. + */ +template +inline void CDynamicStackArray::SetAllocationStep(INDEX ctStep) +{ + ASSERT(ctStep>0); + da_ctAllocationStep = ctStep; +}; + +/* + * Add new object(s) on top of stack. + */ +template +inline Type &CDynamicStackArray::Push(void) { + // if there are no free elements in the array + if (CDynamicArray::Count()-da_ctUsed<1) { + // alocate a new block + CDynamicArray::New(da_ctAllocationStep); + } + // get the new element + da_ctUsed++; + ASSERT(da_ctUsed <= CDynamicArray::Count()); + return CDynamicArray::operator[](da_ctUsed-1); +} +template +inline Type *CDynamicStackArray::Push(INDEX ct) { + // if there are no free elements in the array + while(CDynamicArray::Count()-da_ctUsed::New(da_ctAllocationStep); + } + // get new elements + da_ctUsed+=ct; + ASSERT(da_ctUsed <= CDynamicArray::Count()); + return &CDynamicArray::operator[](da_ctUsed-ct); +} + +/* + * Remove all objects from stack, but keep stack space. + */ +template +inline void CDynamicStackArray::PopAll(void) { + // if there is only one block allocated + if ( da_BlocksList.IsEmpty() + || &da_BlocksList.Head()==&da_BlocksList.Tail()) { + // just clear the counter + da_ctUsed = 0; + + // if there is more than one block allocated + } else { + // remember how much was allocated, rounded up to allocation step + INDEX ctUsedBefore = CDynamicArray::Count(); + // free all memory + CDynamicArray::Clear(); + // allocate one big block + CDynamicArray::New(ctUsedBefore); + da_ctUsed = 0; + } +} + +/* + * Random access operator. + */ +template +inline Type &CDynamicStackArray::operator[](INDEX i) { + ASSERT(this!=NULL); + ASSERT(i::operator[](i); +} +template +inline const Type &CDynamicStackArray::operator[](INDEX i) const { + ASSERT(this!=NULL); + ASSERT(i::operator[](i); +} + +/* + * Get number of elements in array. + */ +template +INDEX CDynamicStackArray::Count(void) const { + ASSERT(this!=NULL); + return da_ctUsed; +} + +/* + * Get index of a member from it's pointer + */ +template +INDEX CDynamicStackArray::Index(Type *ptMember) { + ASSERT(this!=NULL); + INDEX i = CDynamicArray::Index(ptMember); + ASSERTMSG(i::Index(): Not a member of this array!"); + return i; +} + +/* + * Get array of pointers to elements (used for sorting elements by sorting pointers). + */ +template +Type **CDynamicStackArray::GetArrayOfPointers(void) +{ + return da_Pointers; +} + +/* + * Assignment operator. + */ +template +CDynamicStackArray &CDynamicStackArray::operator=(CDynamicStackArray &arOriginal) +{ + ASSERT(this!=NULL); + ASSERT(&arOriginal!=NULL); + ASSERT(this!=&arOriginal); + + // copy stack arrays + CDynamicArray::operator=(arOriginal); + // copy used count + da_ctUsed = arOriginal.da_ctUsed; + + return *this; +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/DynamicStackArray.h b/Sources/Engine/Templates/DynamicStackArray.h new file mode 100644 index 0000000..5f5e620 --- /dev/null +++ b/Sources/Engine/Templates/DynamicStackArray.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_DYNAMICSTACKARRAY_H +#define SE_INCL_DYNAMICSTACKARRAY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Template class for stack-like array with dynamic allocation of objects. + */ +template +class CDynamicStackArray : public CDynamicArray { +public: + INDEX da_ctUsed; // number of used objects in array + INDEX da_ctAllocationStep; // how many elements to allocate when stack overflows +public: + /* Default constructor. */ + inline CDynamicStackArray(void); + /* Destructor. */ + inline ~CDynamicStackArray(void); + + /* Set how many elements to allocate when stack overflows. */ + inline void SetAllocationStep(INDEX ctStep); + /* Destroy all objects, and reset the array to initial (empty) state. */ + inline void Clear(void); + + /* Add new object on top of stack. */ + inline Type &Push(void); + inline Type *Push(INDEX ct); + /* Remove all objects from stack, but keep stack space. */ + inline void PopAll(void); + + /* Random access operator. */ + inline Type &operator[](INDEX iObject); + inline const Type &operator[](INDEX iObject) const; + /* Get number of objects in array. */ + INDEX Count(void) const; + /* Get index of a object from it's pointer. */ + INDEX Index(Type *ptObject); + /* Get array of pointers to elements (used for sorting elements by sorting pointers). */ + Type **GetArrayOfPointers(void); + + /* Assignment operator. */ + CDynamicStackArray &operator=(CDynamicStackArray &arOriginal); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/HashTableTemplate.cpp b/Sources/Engine/Templates/HashTableTemplate.cpp new file mode 100644 index 0000000..ce1f57e --- /dev/null +++ b/Sources/Engine/Templates/HashTableTemplate.cpp @@ -0,0 +1,298 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include +#include +#include + +// default constructor +CHashTable_TYPE::CHashTable_TYPE() +{ + ht_ctCompartments = 0; + ht_ctSlotsPerComp = 0; + ht_ctSlotsPerCompStep = 0; + ht_GetItemKey = NULL; + ht_GetItemValue = NULL; +} + +// destructor -- frees all memory +CHashTable_TYPE::~CHashTable_TYPE(void) +{ +} + +// remove all slots, and reset the nametable to initial (empty) state, keeps the callback functions +void CHashTable_TYPE::Clear(void) +{ + ht_ctCompartments = 0; + ht_ctSlotsPerComp = 0; + ht_ctSlotsPerCompStep = 0; + ht_ahtsSlots.Clear(); +} + + +// internal finding, returns pointer to the the item +CHashTableSlot_TYPE *CHashTable_TYPE::FindSlot(ULONG ulKey, VALUE_TYPE &Value) +{ + ASSERT(ht_ctCompartments>0 && ht_ctSlotsPerComp>0); + + // find compartment number + INDEX iComp = ulKey%ht_ctCompartments; + + // for each slot in the compartment + INDEX iSlot = iComp*ht_ctSlotsPerComp; + for(INDEX iSlotInComp=0; iSlotInComphts_ptElement==NULL) { + // skip it + continue; + } + // if it has same key + if (phts->hts_ulKey==ulKey) { + // if it is same element + if (ht_GetItemValue(phts->hts_ptElement) == Value) { + // return it + return phts; + } + } + } + + // not found + return NULL; +} + + +// internal finding, returns the index of the item in the nametable +INDEX CHashTable_TYPE::FindSlotIndex(ULONG ulKey, VALUE_TYPE &Value) +{ + ASSERT(ht_ctCompartments>0 && ht_ctSlotsPerComp>0); + + // find compartment number + INDEX iComp = ulKey%ht_ctCompartments; + + // for each slot in the compartment + INDEX iSlot = iComp*ht_ctSlotsPerComp; + for(INDEX iSlotInComp=0; iSlotInComphts_ptElement==NULL) { + // skip it + continue; + } + // if it has same key + if (phts->hts_ulKey==ulKey) { + // if it is same element + if (ht_GetItemValue(phts->hts_ptElement) == Value) { + // return it + return iSlot; + } + } + } + + // not found + return -1; +} + +TYPE* CHashTable_TYPE::GetItemFromIndex(INDEX iIndex) +{ + ASSERT(ht_ctCompartments>0 && ht_ctSlotsPerComp>0); + ASSERT(iIndex>=0 && iIndex0 && ht_ctSlotsPerComp>0); + ASSERT(iIndex>=0 && iIndex0 && ctSlotsPerComp>0 && ctSlotsPerCompStep>0 ); + + ht_ctCompartments = ctCompartments; + ht_ctSlotsPerComp = ctSlotsPerComp; + ht_ctSlotsPerCompStep = ctSlotsPerCompStep; + + ht_ahtsSlots.New(ht_ctCompartments*ht_ctSlotsPerComp); +} + + +void CHashTable_TYPE::SetCallbacks(ULONG (*GetItemKey)(VALUE_TYPE &Item), ULONG (*GetItemValue)(TYPE* Item)) +{ + ASSERT(GetItemKey!=NULL); + ASSERT(GetItemValue!=NULL); + + ht_GetItemKey = GetItemKey; + ht_GetItemValue = GetItemValue; +} +// find an object by name +TYPE *CHashTable_TYPE::Find(VALUE_TYPE &Value) +{ + ASSERT(ht_ctCompartments>0 && ht_ctSlotsPerComp>0); + + CHashTableSlot_TYPE *phts = FindSlot(ht_GetItemKey(Value), Value); + if (phts==NULL) return NULL; + return phts->hts_ptElement; +} + + +// find an object by name, return it's index +INDEX CHashTable_TYPE::FindIndex(VALUE_TYPE &Value) +{ + ASSERT(ht_ctCompartments>0 && ht_ctSlotsPerComp>0); + + return FindSlotIndex(ht_GetItemKey(Value), Value); +} + + +// expand the name table to next step +void CHashTable_TYPE::Expand(void) +{ + ASSERT(ht_ctCompartments>0 && ht_ctSlotsPerComp>0); + + // if we are here -> the compartment has overflowed + ASSERT(ht_ctSlotsPerCompStep>0); + + // move the array of slots + CStaticArray ahtsSlotsOld; + ahtsSlotsOld.MoveArray(ht_ahtsSlots); + + // allocate new bigger array + INDEX ctOldSlotsPerComp = ht_ctSlotsPerComp; + ht_ctSlotsPerComp+=ht_ctSlotsPerCompStep; + ht_ahtsSlots.New(ht_ctSlotsPerComp*ht_ctCompartments); + + // for each compartment + for(INDEX iComp =0; iComp0 && ht_ctSlotsPerComp>0); + + VALUE_TYPE Value = ht_GetItemValue(ptNew); + ULONG ulKey = ht_GetItemKey(Value); + + // find compartment number + INDEX iComp = ulKey%ht_ctCompartments; + + // for each slot in the compartment + INDEX iSlot = iComp*ht_ctSlotsPerComp; + for(INDEX iSlotInComp=0; iSlotInComphts_ptElement==NULL) { + // put it here + phts->hts_ulKey = ulKey; + phts->hts_ptElement = ptNew; + return; + } + // must not already exist + //ASSERT(phts->hts_ptElement->GetName()!=ptNew->GetName()); + } + + // if we are here -> the compartment has overflowed + + // expand the name table to next step + ASSERT(!_bExpanding); + _bExpanding = TRUE; + Expand(); + // add the new element + Add(ptNew); + _bExpanding = FALSE; +} + + +// remove an object +void CHashTable_TYPE::Remove(TYPE *ptOld) +{ + ASSERT(ht_ctCompartments>0 && ht_ctSlotsPerComp>0); + // find its slot + VALUE_TYPE Value = ht_GetItemValue(ptOld); + CHashTableSlot_TYPE *phts = FindSlot(ht_GetItemKey(Value), Value); + if( phts!=NULL) { + // mark slot as unused + ASSERT( phts->hts_ptElement==ptOld); + phts->hts_ptElement = NULL; + } +} + + +// remove an object +void CHashTable_TYPE::RemoveAll() +{ + ASSERT(ht_ctCompartments>0 && ht_ctSlotsPerComp>0); + + for (INDEX iComp=0;iComp + +class CHashTableSlot_TYPE { +public: + ULONG hts_ulKey; // hashing key + TYPE *hts_ptElement; // the element inhere + CHashTableSlot_TYPE(void) { hts_ptElement = NULL; }; + void Clear(void) { hts_ptElement = NULL; }; +}; + +/* + * Template class for storing pointers to objects for fast access by name. + */ +class CHashTable_TYPE { +// implementation: +public: + INDEX ht_ctCompartments; // number of compartments in table + INDEX ht_ctSlotsPerComp; // number of slots in one compartment + INDEX ht_ctSlotsPerCompStep; // allocation step for number of slots in one compartment + CStaticArray ht_ahtsSlots; // all slots are here + + ULONG (*ht_GetItemKey)(VALUE_TYPE &Value); + VALUE_TYPE (*ht_GetItemValue)(TYPE* Item); + + // internal finding, returns pointer to the the slot + CHashTableSlot_TYPE *FindSlot(ULONG ulKey, VALUE_TYPE &Value); + // internal finding, returns the index of the item in the nametable + INDEX FindSlotIndex(ULONG ulKey, VALUE_TYPE &Value); + // get the item stored in the hashtable by it's index + TYPE* GetItemFromIndex(INDEX iIndex); + // get the value of the item stored in the hashtable by it's index + VALUE_TYPE GetValueFromIndex(INDEX iIndex); + // expand the hash table to next step + void Expand(void); + +// interface: +public: + // default constructor + CHashTable_TYPE(void); + // destructor -- frees all memory + ~CHashTable_TYPE(void); + // remove all slots, and reset the nametable to initial (empty) state + void Clear(void); + + /* Set allocation parameters. */ + void SetAllocationParameters(INDEX ctCompartments, INDEX ctSlotsPerComp, INDEX ctSlotsPerCompStep); + // set callbacks + void SetCallbacks(ULONG (*GetItemKey)(VALUE_TYPE &Item), VALUE_TYPE (*GetItemValue)(TYPE* Item)); + + // find an object by value, return a pointer to it + TYPE* Find(VALUE_TYPE &Value); + // find an object by value, return it's index + INDEX FindIndex(VALUE_TYPE &Value); + // add a new object + void Add(TYPE *ptNew); + // remove an object + void Remove(TYPE *ptOld); + // remove an object + void RemoveAll(); + + // remove all objects but keep slots + void Reset(void); + + // get estimated efficiency of the hashtable + void ReportEfficiency(void); +}; diff --git a/Sources/Engine/Templates/LinearAllocator.cpp b/Sources/Engine/Templates/LinearAllocator.cpp new file mode 100644 index 0000000..815a61b --- /dev/null +++ b/Sources/Engine/Templates/LinearAllocator.cpp @@ -0,0 +1,165 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_LINEARALLOCATOR_CPP +#define SE_INCL_LINEARALLOCATOR_CPP +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +class CLABlockInfo { +public: + CListNode bi_lnNode; + INDEX bi_ctObjects; // number of objects in this block + void *bi_pvMemory; // start of block memory + void *bi_pvEnd; // end of block memory +}; + +// default constructor +template +CLinearAllocator::CLinearAllocator(void) +{ + la_ctAllocationStep = 256; + la_ctObjects = 0; + la_ctFree = 0; + la_ptNextFree = NULL; +} + +// copy constructor +template +CLinearAllocator::CLinearAllocator(CLinearAllocator &laOriginal) +{ + ASSERT(FALSE); +} + +// destructor -- frees all memory +template +CLinearAllocator::~CLinearAllocator(void) +{ + Clear(); +} + +// destroy all objects, and reset the allocator to initial (empty) state +template +void CLinearAllocator::Clear(void) +{ + FORDELETELIST(CLABlockInfo, bi_lnNode, la_lhBlocks, itBlock) { + // for all memory blocks + // free memory used by block (this doesn't call destructors - see note above!) + delete[] (Type *)itBlock->bi_pvMemory; + // free memory used by block info + delete &itBlock.Current(); + } + la_ctObjects = 0; + la_ctFree = 0; + la_ptNextFree = NULL; +} + + +/* Set how many elements to allocate when stack overflows. */ +template +inline void CLinearAllocator::SetAllocationStep(INDEX ctStep) +{ + la_ctAllocationStep = ctStep; +} + + +// allocate a new memory block +template +void CLinearAllocator::AllocBlock(INDEX iCount) +{ + ASSERT(this!=NULL && iCount>0); + //ASSERT(la_ctFree==0); + Type *ptBlock; + CLABlockInfo *pbi; + + // allocate the memory and call constructors for all members + ptBlock = new Type[iCount]; // call vector constructor, for better performance + // allocate the block info + pbi = new CLABlockInfo; + // add the block to list + la_lhBlocks.AddTail(pbi->bi_lnNode); + // remember block memory and size + pbi->bi_pvMemory = ptBlock; + pbi->bi_pvEnd = ptBlock+iCount; + pbi->bi_ctObjects = iCount; + + // count total number of allocated objects + la_ctObjects+=iCount; + // set up to get new objects from here + la_ctFree = iCount; + la_ptNextFree = ptBlock; +} + +// allocate a new object +template +inline Type &CLinearAllocator::New(void) +{ + if (la_ctFree == 0) { + // allocate a new memory block + AllocBlock(la_ctAllocationStep); + } + Type *ptNew = la_ptNextFree; + la_ctFree--; + la_ptNextFree++; + return *ptNew; +} +template +inline Type *CLinearAllocator::New(INDEX ct) +{ + // if not enough space in current block + if (la_ctFree < ct) { + // allocate an entirely new memory block of exact that size + AllocBlock(ct); + // use it entirely + Type *ptNew = la_ptNextFree; + la_ctFree=0; + la_ptNextFree=NULL; + return ptNew; + // if there is enough space in current block + } else { + // use the space + Type *ptNew = la_ptNextFree; + la_ctFree-=ct; + la_ptNextFree+=ct; + return ptNew; + } +} +// free all objects but keep allocated space and relinearize it +template +inline void CLinearAllocator::Reset(void) +{ + // if there is no block allocated + if (la_lhBlocks.IsEmpty()) { + // do nothing + return; + + // if there is only one block allocated + } else if (&la_lhBlocks.Head()==&la_lhBlocks.Tail()) { + // just restart at the beginning + la_ctFree = la_ctObjects; + la_ptNextFree = (Type*) (LIST_HEAD(la_lhBlocks, CLABlockInfo, bi_lnNode)->bi_pvMemory); + + // if there is more than one block allocated + } else { + // remember how much objects were used and allocation step + INDEX ctObjectsOld = la_ctObjects; + INDEX ctAllocationStepOld = la_ctAllocationStep; + // free all blocks + Clear(); + // restore the allocation step + la_ctAllocationStep = ctAllocationStepOld; + // allocate only one linear block + AllocBlock(ctObjectsOld); + } +} + +// make 'for' construct for walking all objects in a linear allocator +#define FOREACHINLINEARALLOCATOR(allocator, type, pt) \ +FOREACHINLIST(CLABlockInfo, bi_lnNode, allocator.la_lhBlocks, pt##itBlock) { \ + for(type *pt = (type *)pt##itBlock->bi_pvMemory; pt<(type *)pt##itBlock->bi_pvEnd; pt++) + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/LinearAllocator.h b/Sources/Engine/Templates/LinearAllocator.h new file mode 100644 index 0000000..6e5335a --- /dev/null +++ b/Sources/Engine/Templates/LinearAllocator.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_LINEARALLOCATOR_H +#define SE_INCL_LINEARALLOCATOR_H +#ifdef PRAGMA_ONCE + #pragma once +#endif +/* + * Template class for dynamic allocation of objects in a linear fashion. + */ +template +class CLinearAllocator { +// implementation: +public: + CListHead la_lhBlocks; // list of allocated memory blocks + INDEX la_ctAllocationStep; // number of objects allocated + INDEX la_ctObjects; // number of objects allocated + INDEX la_ctFree; // number of free objects in current block + Type *la_ptNextFree; // pointer to next free object + + // allocate a new memory block + void AllocBlock(INDEX iCount); + +// interface: +public: + // default constructor + CLinearAllocator(void); + // copy constructor + CLinearAllocator(CLinearAllocator &laOriginal); + // destructor -- frees all memory + ~CLinearAllocator(void); + // destroy all objects, and reset the allocator to initial (empty) state + void Clear(void); + + /* Set how many elements to allocate when stack overflows. */ + inline void SetAllocationStep(INDEX ctStep); + + // allocate a new object + inline Type &New(void); + inline Type *New(INDEX ct); + // free all objects but keep allocated space and relinearize it + inline void Reset(void); +// these are just for compatibility with CDynamicStackArray<>: + inline Type &Push(void) { return New(); }; + inline Type *Push(INDEX ct) { return New(ct); }; + inline void PopAll(void) { Reset(); }; +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/NameTable.cpp b/Sources/Engine/Templates/NameTable.cpp new file mode 100644 index 0000000..019322b --- /dev/null +++ b/Sources/Engine/Templates/NameTable.cpp @@ -0,0 +1,186 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +#include + +#if NAMETABLE_CASESENSITIVE==1 + #define COMPARENAMES(a, b) (strcmp(a, b)==0) +#elif NAMETABLE_CASESENSITIVE==0 + #define COMPARENAMES(a, b) (a==b) +#else + #error "NAMETABLE_CASESENSITIVE not defined" +#endif + +// default constructor +CNameTable_TYPE::CNameTable_TYPE(void) +{ + nt_ctCompartments = 0; + nt_ctSlotsPerComp = 0; + nt_ctSlotsPerCompStep = 0; +} + +// destructor -- frees all memory +CNameTable_TYPE::~CNameTable_TYPE(void) +{ +} + +// remove all slots, and reset the nametable to initial (empty) state +void CNameTable_TYPE::Clear(void) +{ + nt_ctCompartments = 0; + nt_ctSlotsPerComp = 0; + nt_ctSlotsPerCompStep = 0; + nt_antsSlots.Clear(); +} + +// internal finding +CNameTableSlot_TYPE *CNameTable_TYPE::FindSlot(ULONG ulKey, const CTString &strName) +{ + ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0); + + // find compartment number + INDEX iComp = ulKey%nt_ctCompartments; + + // for each slot in the compartment + INDEX iSlot = iComp*nt_ctSlotsPerComp; + for(INDEX iSlotInComp=0; iSlotInCompnts_ptElement==NULL) { + // skip it + continue; + } + // if it has same key + if (pnts->nts_ulKey==ulKey) { + // if it is same element + if (COMPARENAMES(pnts->nts_ptElement->GetName(), strName)) { + // return it + return pnts; + } + } + } + + // not found + return NULL; +} + +/* Set allocation parameters. */ +void CNameTable_TYPE::SetAllocationParameters( + INDEX ctCompartments, INDEX ctSlotsPerComp, INDEX ctSlotsPerCompStep) +{ + ASSERT(nt_ctCompartments==0 && nt_ctSlotsPerComp==0 && nt_ctSlotsPerCompStep==0); + ASSERT(ctCompartments>0 && ctSlotsPerComp>0 && ctSlotsPerCompStep>0 ); + + nt_ctCompartments = ctCompartments; + nt_ctSlotsPerComp = ctSlotsPerComp; + nt_ctSlotsPerCompStep = ctSlotsPerCompStep; + + nt_antsSlots.New(nt_ctCompartments*nt_ctSlotsPerComp); +} + +// find an object by name +TYPE *CNameTable_TYPE::Find(const CTString &strName) +{ + ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0); + + CNameTableSlot_TYPE *pnts = FindSlot(strName.GetHash(), strName); + if (pnts==NULL) return NULL; + return pnts->nts_ptElement; +} + +// expand the name table to next step +void CNameTable_TYPE::Expand(void) +{ + ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0); + + // if we are here -> the compartment has overflowed + ASSERT(nt_ctSlotsPerCompStep>0); + + // move the array of slots + CStaticArray antsSlotsOld; + antsSlotsOld.MoveArray(nt_antsSlots); + + // allocate new bigger array + INDEX ctOldSlotsPerComp = nt_ctSlotsPerComp; + nt_ctSlotsPerComp+=nt_ctSlotsPerCompStep; + nt_antsSlots.New(nt_ctSlotsPerComp*nt_ctCompartments); + + // for each compartment + for(INDEX iComp =0; iComp0 && nt_ctSlotsPerComp>0); + + ULONG ulKey = ptNew->GetName().GetHash(); + + // find compartment number + INDEX iComp = ulKey%nt_ctCompartments; + + // for each slot in the compartment + INDEX iSlot = iComp*nt_ctSlotsPerComp; + for(INDEX iSlotInComp=0; iSlotInCompnts_ptElement==NULL) { + // put it here + pnts->nts_ulKey = ulKey; + pnts->nts_ptElement = ptNew; + return; + } + // must not already exist + //ASSERT(pnts->nts_ptElement->GetName()!=ptNew->GetName()); + } + + // if we are here -> the compartment has overflowed + + // expand the name table to next step + ASSERT(!_bExpanding); + _bExpanding = TRUE; + Expand(); + // add the new element + Add(ptNew); + _bExpanding = FALSE; +} + + +// remove an object +void CNameTable_TYPE::Remove(TYPE *ptOld) +{ + ASSERT(nt_ctCompartments>0 && nt_ctSlotsPerComp>0); + // find its slot + const CTString &strName = ptOld->GetName(); + CNameTableSlot_TYPE *pnts = FindSlot(strName.GetHash(), strName); + if( pnts!=NULL) { + // mark slot as unused + ASSERT( pnts->nts_ptElement==ptOld); + pnts->nts_ptElement = NULL; + } +} + + +// remove all objects but keep slots +void CNameTable_TYPE::Reset(void) +{ + for(INDEX iSlot=0; iSlot + +class CNameTableSlot_TYPE { +public: + ULONG nts_ulKey; // hashing key + TYPE *nts_ptElement; // the element inhere + CNameTableSlot_TYPE(void) { nts_ptElement = NULL; }; + void Clear(void) { nts_ptElement = NULL; }; +}; + +/* + * Template class for storing pointers to objects for fast access by name. + */ +class CNameTable_TYPE { +// implementation: +public: + INDEX nt_ctCompartments; // number of compartments in table + INDEX nt_ctSlotsPerComp; // number of slots in one compartment + INDEX nt_ctSlotsPerCompStep; // allocation step for number of slots in one compartment + CStaticArray nt_antsSlots; // all slots are here + + // internal finding + CNameTableSlot_TYPE *FindSlot(ULONG ulKey, const CTString &strName); + // expand the name table to next step + void Expand(void); + +// interface: +public: + // default constructor + CNameTable_TYPE(void); + // destructor -- frees all memory + ~CNameTable_TYPE(void); + // remove all slots, and reset the nametable to initial (empty) state + void Clear(void); + + /* Set allocation parameters. */ + void SetAllocationParameters( + INDEX ctCompartments, INDEX ctSlotsPerComp, INDEX ctSlotsPerCompStep); + + // find an object by name + TYPE *Find(const CTString &strName); + // add a new object + void Add(TYPE *ptNew); + // remove an object + void Remove(TYPE *ptOld); + + // remove all objects but keep slots + void Reset(void); + + // get estimated efficiency of the nametable + CTString GetEfficiency(void); +}; diff --git a/Sources/Engine/Templates/NameTable_CTFileName.cpp b/Sources/Engine/Templates/NameTable_CTFileName.cpp new file mode 100644 index 0000000..aa01a1a --- /dev/null +++ b/Sources/Engine/Templates/NameTable_CTFileName.cpp @@ -0,0 +1,18 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#define NAMETABLE_CASESENSITIVE 0 +#define TYPE CTFileName +#define CNameTable_TYPE CNameTable_CTFileName +#define CNameTableSlot_TYPE CNameTableSlot_CTFileName + +#include +#include + +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + diff --git a/Sources/Engine/Templates/NameTable_CTFileName.h b/Sources/Engine/Templates/NameTable_CTFileName.h new file mode 100644 index 0000000..2b8c00d --- /dev/null +++ b/Sources/Engine/Templates/NameTable_CTFileName.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_NAMETABLE_CTFILENAME_H +#define SE_INCL_NAMETABLE_CTFILENAME_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#define TYPE CTFileName +#define CNameTable_TYPE CNameTable_CTFileName +#define CNameTableSlot_TYPE CNameTableSlot_CTFileName +#include +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/NameTable_CTranslationPair.cpp b/Sources/Engine/Templates/NameTable_CTranslationPair.cpp new file mode 100644 index 0000000..baf5562 --- /dev/null +++ b/Sources/Engine/Templates/NameTable_CTranslationPair.cpp @@ -0,0 +1,18 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#define NAMETABLE_CASESENSITIVE 1 +#define TYPE CTranslationPair +#define CNameTable_TYPE CNameTable_CTranslationPair +#define CNameTableSlot_TYPE CNameTableSlot_CTranslationPair + +#include +#include + +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + diff --git a/Sources/Engine/Templates/NameTable_CTranslationPair.h b/Sources/Engine/Templates/NameTable_CTranslationPair.h new file mode 100644 index 0000000..cbf502a --- /dev/null +++ b/Sources/Engine/Templates/NameTable_CTranslationPair.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_NAMETABLE_CTRANSLATIONPAIR_H +#define SE_INCL_NAMETABLE_CTRANSLATIONPAIR_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#define TYPE CTranslationPair +#define CNameTable_TYPE CNameTable_CTranslationPair +#define CNameTableSlot_TYPE CNameTableSlot_CTranslationPair +#include +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/Selection.cpp b/Sources/Engine/Templates/Selection.cpp new file mode 100644 index 0000000..597135c --- /dev/null +++ b/Sources/Engine/Templates/Selection.cpp @@ -0,0 +1,93 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SELECTION_CPP +#define SE_INCL_SELECTION_CPP +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* + * Select one object. + */ +template +void CSelection::Select(cType &tToSelect) +{ + // if the object is not yet selected + if (!tToSelect.IsSelected(ulFlag)) { + // select it + tToSelect.Select(ulFlag); + // add it to this container + Add(&tToSelect); + + // if the object is already selected + } else { + ASSERTALWAYS("Object already selected!"); + } +} + +/* + * Deselect one object. + */ +template +void CSelection::Deselect(cType &tToSelect) +{ + // if the object is selected + if (tToSelect.IsSelected(ulFlag)) { + // deselect it + tToSelect.Deselect(ulFlag); + // remove it from this container + Remove(&tToSelect); + + // if the object is not selected + } else { + ASSERTALWAYS("Object is not selected!"); + } +} + +/* + * Test if one object is selected. + */ +template +BOOL CSelection::IsSelected(cType &tToSelect) +{ + // test if the object is selected + return tToSelect.IsSelected(ulFlag); +} + +/* + * Deselect all objects. + */ +template +void CSelection::Clear(void) +{ + // for all objects in the container + FOREACHINDYNAMICCONTAINER(*this, cType, itObject) { + // object must be allocated and valid + ASSERT(_CrtIsValidPointer(&*itObject, sizeof(cType), TRUE)); +/* ASSERT(_CrtIsValidHeapPointer(&*itObject)); + ASSERT(_CrtIsMemoryBlock(&*itObject, sizeof(cType), NULL, NULL, NULL )); + */ + + // deselect it + itObject->Deselect(ulFlag); + } + // clear the entire container at once + CDynamicContainer::Clear(); +} + +template +cType *CSelection::GetFirstInSelection(void) +{ + if( Count() == 0) + { + return NULL; + } + return (cType *) &CDynamicContainer::GetFirst(); +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/Selection.h b/Sources/Engine/Templates/Selection.h new file mode 100644 index 0000000..f1c64f4 --- /dev/null +++ b/Sources/Engine/Templates/Selection.h @@ -0,0 +1,47 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_SELECTION_H +#define SE_INCL_SELECTION_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * A selection of some objects that support selecting. + */ +template +class CSelection : public CDynamicContainer { +public: + /* Deselect all objects. */ + void Clear(void); + /* Destructor. */ + ~CSelection(void) { Clear(); } + + /* Select one object. */ + void Select(cType &tToSelect); + /* Deselect one object. */ + void Deselect(cType &tToDeselect); + /* Test if one object is selected. */ + BOOL IsSelected(cType &tToSelect); + /* Get first in selection. NULL if empty selection */ + cType *GetFirstInSelection(void); +}; + +// macro for implementing selecting features in a class +#define IMPLEMENT_SELECTING(m_ulFlags) \ + inline void Select(unsigned long ulFlag) { \ + m_ulFlags |= ulFlag; \ + } \ + inline void Deselect(unsigned long ulFlag) { \ + m_ulFlags &= ~ulFlag; \ + } \ + inline BOOL IsSelected(unsigned long ulFlag) const { \ + return m_ulFlags & ulFlag; \ + } + + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/StaticArray.cpp b/Sources/Engine/Templates/StaticArray.cpp new file mode 100644 index 0000000..ff62e8d --- /dev/null +++ b/Sources/Engine/Templates/StaticArray.cpp @@ -0,0 +1,260 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STATICARRAY_CPP +#define SE_INCL_STATICARRAY_CPP +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#define FOREACHINSTATICARRAY(array, type, iter) \ + for(CStaticArrayIterator iter(array); !iter.IsPastEnd(); iter.MoveToNext() ) + +#include +#include + +/* + * Default constructor. + */ +template +inline CStaticArray::CStaticArray(void) { + sa_Count=0; + sa_Array=NULL; +} + +/* + * Destructor. + */ +template +inline CStaticArray::~CStaticArray(void) { + // if some objects were allocated + if (sa_Count!=0) { + // destroy them + Delete(); + } +}; + +/* Random access operator. */ +template +inline void CStaticArray::operator=(const CStaticArray &arOriginal) { + CopyArray(arOriginal); +} + +template +/* Destroy all objects, and reset the array to initial (empty) state. */ +inline void CStaticArray::Clear(void) { + if (sa_Count!=0) Delete(); +} + +/* + * Create a given number of objects. + */ +template +inline void CStaticArray::New(INDEX iCount) { + ASSERT(this!=NULL && iCount>=0); + // if no new members are needed in fact + if (iCount==0) { + // do nothing + return; + } + //ASSERT(sa_Count==0 && sa_Array==NULL); +#ifndef NDEBUG + if(!(sa_Count==0 && sa_Array==NULL)) { + if(sa_Array == NULL) { + CPrintF("CStaticArray array not set!\n"); + } else { + CPrintF("CStaticArray new(%d) called while already holding %d elements!\n", iCount, sa_Count); + } + } +#endif + sa_Count = iCount; + sa_Array = new Type[iCount+1]; //(+1 for cache-prefetch opt) +}; +/* Expand stack size but keep old objects. */ +template +inline void CStaticArray::Expand(INDEX iNewCount) +{ + ASSERT(this!=NULL && iNewCount>sa_Count); + // if not already allocated + if (sa_Count==0) { + // just allocate + New(iNewCount); + return; + // if already allocated + } else { + ASSERT(sa_Count!=0 && sa_Array!=NULL); + // allocate new array with more space + Type *ptNewArray = new Type[iNewCount+1]; //(+1 for cache-prefetch opt) + // copy old objects + for (INDEX iOld=0; iOld +inline void CStaticArray::Delete(void) { + ASSERT(this!=NULL); + ASSERT(sa_Count!=0 && sa_Array!=NULL); + delete[] sa_Array; + sa_Count = 0; + sa_Array = NULL; +} + +/* + * Random access operator. + */ +template +inline Type &CStaticArray::operator[](INDEX i) { + ASSERT(this!=NULL); + ASSERT(i>=0 && i +inline const Type &CStaticArray::operator[](INDEX i) const { + ASSERT(this!=NULL); + ASSERT(i>=0 && i +INDEX CStaticArray::Count(void) const { + ASSERT(this!=NULL); + return sa_Count; +} + +/* + * Get index of a member from it's pointer + */ +template +INDEX CStaticArray::Index(Type *ptMember) { + ASSERT(this!=NULL); + INDEX i = ptMember-sa_Array; + ASSERT(i>=0 && i +/* Copy all elements of another array into this one. */ +void CStaticArray::CopyArray(const CStaticArray &arOriginal) +{ + ASSERT(this!=NULL); + ASSERT(&arOriginal!=NULL); + ASSERT(this!=&arOriginal); + + // clear previous contents + Clear(); + // get count of elements in original array + INDEX ctOriginal = arOriginal.Count(); + // if the other array has no elements + if (ctOriginal ==0) { + return; + } + // create that much elements + New(ctOriginal); + // copy them all + for (INDEX iNew=0; iNew +void CStaticArray::MoveArray(CStaticArray &arOther) +{ + ASSERT(this!=NULL); + ASSERT(&arOther!=NULL); + ASSERT(this!=&arOther); + + // clear previous contents + Clear(); + // if the other array has no elements + if (arOther.Count()==0) { + // no assignment + return; + } + // move data from the other array into this one and clear the other one + sa_Count = arOther.sa_Count; + sa_Array = arOther.sa_Array; + arOther.sa_Count = 0; + arOther.sa_Array = NULL; +} + +///////////////////////////////////////////////////////////////////// +// CStaticArrayIterator + +/* + * Template class for iterating static array. + */ +template +class CStaticArrayIterator { +private: + INDEX sai_Index; // index of current element + CStaticArray &sai_Array; // reference to array +public: + /* Constructor for given array. */ + inline CStaticArrayIterator(CStaticArray &sa); + /* Destructor. */ + inline ~CStaticArrayIterator(void); + + /* Move to next object. */ + inline void MoveToNext(void); + /* Check if finished. */ + inline BOOL IsPastEnd(void); + /* Get current element. */ + Type &Current(void) { return sai_Array[sai_Index]; } + Type &operator*(void) { return sai_Array[sai_Index]; } + operator Type *(void) { return &sai_Array[sai_Index]; } + Type *operator->(void) { return &sai_Array[sai_Index]; } +}; + +/* + * Constructor for given array. + */ +template +inline CStaticArrayIterator::CStaticArrayIterator(CStaticArray &sa) : sai_Array(sa) { + sai_Index = 0; +} + +/* + * Destructor. + */ +template +inline CStaticArrayIterator::~CStaticArrayIterator(void) { + sai_Index = -1; +} + +/* + * Move to next object. + */ +template +inline void CStaticArrayIterator::MoveToNext(void) { + ASSERT(this!=NULL); + sai_Index++; +} + +/* + * Check if finished. + */ +template +inline BOOL CStaticArrayIterator::IsPastEnd(void) { + ASSERT(this!=NULL); + return sai_Index>=sai_Array.sa_Count; +} + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/StaticArray.h b/Sources/Engine/Templates/StaticArray.h new file mode 100644 index 0000000..390069c --- /dev/null +++ b/Sources/Engine/Templates/StaticArray.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STATICARRAY_H +#define SE_INCL_STATICARRAY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +/* + * Template class for array with static allocation of objects. + */ +template +class CStaticArray { +public: + INDEX sa_Count; // number of objects in array + Type *sa_Array; // objects +public: + /* Default constructor. */ + inline CStaticArray(void); + /* Destructor. */ + inline ~CStaticArray(void); + void operator=(const CStaticArray &arOriginal); + + /* Create a given number of objects. */ + inline void New(INDEX iCount); + /* Expand stack size but keep old objects. */ + inline void Expand(INDEX iNewCount); + /* Destroy all objects. */ + inline void Delete(void); + /* Destroy all objects, and reset the array to initial (empty) state. */ + inline void Clear(void); + + /* Random access operator. */ + inline Type &operator[](INDEX iObject); + inline const Type &operator[](INDEX iObject) const; + /* Get number of objects in array. */ + INDEX Count(void) const; + /* Get index of a object from it's pointer. */ + INDEX Index(Type *ptObject); + + /* Copy all elements of another array into this one. */ + void CopyArray(const CStaticArray &arOriginal); + /* Move all elements of another array into this one. */ + void MoveArray(CStaticArray &arOther); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/StaticStackArray.cpp b/Sources/Engine/Templates/StaticStackArray.cpp new file mode 100644 index 0000000..db79054 --- /dev/null +++ b/Sources/Engine/Templates/StaticStackArray.cpp @@ -0,0 +1,188 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +#ifndef SE_INCL_STATICSTACKARRAY_CPP +#define SE_INCL_STATICSTACKARRAY_CPP +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* + * Default constructor. + */ +template +inline CStaticStackArray::CStaticStackArray(void) : CStaticArray() { + sa_UsedCount=0; + sa_ctAllocationStep = 256; +} + +/* + * Destructor. + */ +template +inline CStaticStackArray::~CStaticStackArray(void) { +}; + +/* Destroy all objects, and reset the array to initial (empty) state. */ +template +inline void CStaticStackArray::Clear(void) { + if (CStaticArray::Count()!=0) Delete(); +} + + /* + * Set how many elements to allocate when stack overflows. + */ +template +inline void CStaticStackArray::SetAllocationStep(INDEX ctStep) +{ + ASSERT(ctStep>0); + sa_ctAllocationStep = ctStep; +}; + +/* + * Create a given number of objects. + */ +template +inline void CStaticStackArray::New(INDEX iCount) { + CStaticArray::New(iCount); + sa_UsedCount = 0; +}; + +/* + * Destroy all objects. + */ +template +inline void CStaticStackArray::Delete(void) { + CStaticArray::Delete(); + sa_UsedCount = 0; +} + +/* + * Add new object(s) on top of stack. + */ +template +inline Type &CStaticStackArray::Push(void) { + sa_UsedCount++; + if (sa_UsedCount>CStaticArray::Count()) { + Expand(CStaticArray::Count()+sa_ctAllocationStep); + } + ASSERT(sa_UsedCount <= CStaticArray::Count()); + return CStaticArray::operator[](sa_UsedCount-1); +} +template +inline Type *CStaticStackArray::Push(INDEX ct) { + sa_UsedCount+=ct; + while(sa_UsedCount>CStaticArray::Count()) { + Expand(CStaticArray::Count()+sa_ctAllocationStep); + } + ASSERT(sa_UsedCount <= CStaticArray::Count()); + return &CStaticArray::operator[](sa_UsedCount-ct); +} + +/* Remove one object from top of stack and return it. */ +template +inline Type &CStaticStackArray::Pop(void) +{ + ASSERT(sa_UsedCount>0); + sa_UsedCount--; + return CStaticArray::operator[](sa_UsedCount); +} +/* + * Remove objects higher than the given index from stack, but keep stack space. + */ +template +inline void CStaticStackArray::PopUntil(INDEX iNewTop) +{ + ASSERT(iNewTop < sa_UsedCount); + sa_UsedCount = iNewTop+1; +} +/* + * Remove all objects from stack, but keep stack space. + */ +template +inline void CStaticStackArray::PopAll(void) { + sa_UsedCount = 0; +} + +/* + * Random access operator. + */ +template +inline Type &CStaticStackArray::operator[](INDEX i) { + ASSERT(this!=NULL); + ASSERT(i::operator[](i); +} +template +inline const Type &CStaticStackArray::operator[](INDEX i) const { + ASSERT(this!=NULL); + ASSERT(i::operator[](i); +} + +/* + * Get number of elements in array. + */ +template +INDEX CStaticStackArray::Count(void) const { + ASSERT(this!=NULL); + return sa_UsedCount; +} + +/* + * Get index of a member from it's pointer + */ +template +INDEX CStaticStackArray::Index(Type *ptMember) { + ASSERT(this!=NULL); + INDEX i = CStaticArray::Index(ptMember); + ASSERTMSG(i::Index(): Not a member of this array!"); + return i; +} + +/* + * Assignment operator. + */ +template +CStaticStackArray &CStaticStackArray::operator=(const CStaticStackArray &arOriginal) +{ + ASSERT(this!=NULL); + ASSERT(&arOriginal!=NULL); + ASSERT(this!=&arOriginal); + + // copy stack arrays + CStaticArray::operator=(arOriginal); + // copy used count + sa_UsedCount = arOriginal.sa_UsedCount; + + return *this; +} + + +/* Move all elements of another array into this one. */ +template +void CStaticStackArray::MoveArray(CStaticStackArray &arOther) +{ + ASSERT(this!=NULL); + ASSERT(&arOther!=NULL); + ASSERT(this!=&arOther); + + // clear previous contents + Clear(); + // if the other array has no elements + if (arOther.Count()==0) { + // no assignment + return; + } + // move data from the other array into this one and clear the other one + CStaticArray::MoveArray(arOther); + sa_UsedCount = arOther.sa_UsedCount ; + sa_ctAllocationStep = arOther.sa_ctAllocationStep ; + arOther.sa_UsedCount = 0; +} + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/StaticStackArray.h b/Sources/Engine/Templates/StaticStackArray.h new file mode 100644 index 0000000..e588e94 --- /dev/null +++ b/Sources/Engine/Templates/StaticStackArray.h @@ -0,0 +1,60 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STATICSTACKARRAY_H +#define SE_INCL_STATICSTACKARRAY_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* + * Template class for stack-like array with static allocation of objects. + */ +template +class CStaticStackArray : public CStaticArray { +public: + INDEX sa_UsedCount; // number of used objects in array + INDEX sa_ctAllocationStep; // how many elements to allocate when stack overflows +public: + /* Default constructor. */ + inline CStaticStackArray(void); + /* Destructor. */ + inline ~CStaticStackArray(void); + + /* Set how many elements to allocate when stack overflows. */ + inline void SetAllocationStep(INDEX ctStep); + /* Create a given number of objects. */ + inline void New(INDEX iCount); + /* Destroy all objects. */ + inline void Delete(void); + /* Destroy all objects, and reset the array to initial (empty) state. */ + inline void Clear(void); + + /* Add new object(s) on top of stack. */ + inline Type &Push(void); + inline Type *Push(INDEX ct); + /* Remove one object from top of stack and return it. */ + inline Type &Pop(void); + /* Remove objects with higher than the given index from stack, but keep stack space. */ + inline void PopUntil(INDEX iNewTop); + /* Remove all objects from stack, but keep stack space. */ + inline void PopAll(void); + + /* Random access operator. */ + inline Type &operator[](INDEX iObject); + inline const Type &operator[](INDEX iObject) const; + /* Get number of objects in array. */ + INDEX Count(void) const; + /* Get index of a object from it's pointer. */ + INDEX Index(Type *ptObject); + /* Move all elements of another array into this one. */ + void MoveArray(CStaticStackArray &arOther); + + /* Assignment operator. */ + CStaticStackArray &operator=(const CStaticStackArray &arOriginal); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/Stock.cpp b/Sources/Engine/Templates/Stock.cpp new file mode 100644 index 0000000..2aec30b --- /dev/null +++ b/Sources/Engine/Templates/Stock.cpp @@ -0,0 +1,162 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include + +#include + +/* + * Default constructor. + */ + +CStock_TYPE::CStock_TYPE(void) +{ + st_ntObjects.SetAllocationParameters(50, 2, 2); +} + +/* + * Destructor. + */ + +CStock_TYPE::~CStock_TYPE(void) +{ + // free all unused elements of the stock + FreeUnused(); +} + +/* + * Obtain an object from stock - loads if not loaded. + */ + +TYPE *CStock_TYPE::Obtain_t(const CTFileName &fnmFileName) +{ + // find stocked object with same name + TYPE *pExisting = st_ntObjects.Find(fnmFileName); + + // if found + if (pExisting!=NULL) { + // mark that it is used once again + pExisting->MarkUsed(); + // return its pointer + return pExisting; + } + + /* if not found, */ + + // create new stock object + TYPE *ptNew = new TYPE; + ptNew->ser_FileName = fnmFileName; + st_ctObjects.Add(ptNew); + st_ntObjects.Add(ptNew); + + // load it + try { + ptNew->Load_t(fnmFileName); + } catch(char *) { + st_ctObjects.Remove(ptNew); + st_ntObjects.Remove(ptNew); + delete ptNew; + throw; + } + + // mark that it is used for the first time + //ASSERT(!ptNew->IsUsed()); + ptNew->MarkUsed(); + + // return the pointer to the new one + return ptNew; +} + +/* + * Release an object when not needed any more. + */ + +void CStock_TYPE::Release(TYPE *ptObject) +{ + // mark that it is used one less time + ptObject->MarkUnused(); + // if it is not used at all any more and should be freed automatically + if (!ptObject->IsUsed() && ptObject->IsAutoFreed()) { + // remove it from stock + st_ctObjects.Remove(ptObject); + st_ntObjects.Remove(ptObject); + delete ptObject; + } +} + +// free all unused elements of the stock + +void CStock_TYPE::FreeUnused(void) +{ + BOOL bAnyRemoved; + // repeat + do { + // create container of objects that should be freed + CDynamicContainer ctToFree; + {FOREACHINDYNAMICCONTAINER(st_ctObjects, TYPE, itt) { + if (!itt->IsUsed()) { + ctToFree.Add(itt); + } + }} + bAnyRemoved = ctToFree.Count()>0; + // for each object that should be freed + {FOREACHINDYNAMICCONTAINER(ctToFree, TYPE, itt) { + st_ctObjects.Remove(itt); + st_ntObjects.Remove(itt); + delete (&*itt); + }} + + // as long as there is something to remove + } while (bAnyRemoved); + +} +// calculate amount of memory used by all objects in the stock + +SLONG CStock_TYPE::CalculateUsedMemory(void) +{ + SLONG slUsedTotal = 0; + {FOREACHINDYNAMICCONTAINER(st_ctObjects, TYPE, itt) { + SLONG slUsedByObject = itt->GetUsedMemory(); + if (slUsedByObject<0) { + return -1; + } + slUsedTotal+=slUsedByObject; + }} + + return slUsedTotal; +} + +// dump memory usage report to a file +void CStock_TYPE::DumpMemoryUsage_t(CTStream &strm) // throw char * +{ + CTString strLine; + SLONG slUsedTotal = 0; + {FOREACHINDYNAMICCONTAINER(st_ctObjects, TYPE, itt) { + SLONG slUsedByObject = itt->GetUsedMemory(); + if (slUsedByObject<0) { + strm.PutLine_t("Error!"); + return; + } + strLine.PrintF("%7.1fk %s(%d) %s", + slUsedByObject/1024.0f, (const char*)(itt->GetName()), itt->GetUsedCount(), itt->GetDescription()); + strm.PutLine_t(strLine); + }} +} + +// get number of total elements in stock +INDEX CStock_TYPE::GetTotalCount(void) +{ + return st_ctObjects.Count(); +} + +// get number of used elements in stock + +INDEX CStock_TYPE::GetUsedCount(void) +{ + INDEX ctUsed = 0; + {FOREACHINDYNAMICCONTAINER(st_ctObjects, TYPE, itt) { + if (itt->IsUsed()) { + ctUsed++; + } + }} + return ctUsed; +} diff --git a/Sources/Engine/Templates/Stock.h b/Sources/Engine/Templates/Stock.h new file mode 100644 index 0000000..1014ae2 --- /dev/null +++ b/Sources/Engine/Templates/Stock.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +#if !defined(TYPE) || !defined(CStock_TYPE) || !defined(CNameTable_TYPE) +#error +#endif + +#include + +/* + * Template for stock of some kind of objects that can be saved and loaded. + */ +class CStock_TYPE { +public: + CDynamicContainer st_ctObjects; // objects on stock + CNameTable_TYPE st_ntObjects; // name table for fast lookup + +public: + /* Default constructor. */ + CStock_TYPE(void); + /* Destructor. */ + ~CStock_TYPE(void); + + /* Obtain an object from stock - loads if not loaded. */ + ENGINE_API TYPE *Obtain_t(const CTFileName &fnmFileName); // throw char * + /* Release an object when not needed any more. */ + ENGINE_API void Release(TYPE *ptObject); + // free all unused elements of the stock + ENGINE_API void FreeUnused(void); + // calculate amount of memory used by all objects in the stock + SLONG CalculateUsedMemory(void); + // dump memory usage report to a file + void DumpMemoryUsage_t(CTStream &strm); // throw char * + // get number of total elements in stock + INDEX GetTotalCount(void); + // get number of used elements in stock + INDEX GetUsedCount(void); +}; diff --git a/Sources/Engine/Templates/Stock_CAnimData.cpp b/Sources/Engine/Templates/Stock_CAnimData.cpp new file mode 100644 index 0000000..4a16e16 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CAnimData.cpp @@ -0,0 +1,20 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#define TYPE CAnimData +#define CStock_TYPE CStock_CAnimData +#define CNameTable_TYPE CNameTable_CAnimData +#define CNameTableSlot_TYPE CNameTableSlot_CAnimData + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +CStock_CAnimData *_pAnimStock = NULL; diff --git a/Sources/Engine/Templates/Stock_CAnimData.h b/Sources/Engine/Templates/Stock_CAnimData.h new file mode 100644 index 0000000..6bb9ea5 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CAnimData.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STOCK_CANIMDATA_H +#define SE_INCL_STOCK_CANIMDATA_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +#define TYPE CAnimData +#define CStock_TYPE CStock_CAnimData +#define CNameTable_TYPE CNameTable_CAnimData +#define CNameTableSlot_TYPE CNameTableSlot_CAnimData + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +ENGINE_API extern CStock_CAnimData *_pAnimStock; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/Stock_CAnimSet.cpp b/Sources/Engine/Templates/Stock_CAnimSet.cpp new file mode 100644 index 0000000..b415122 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CAnimSet.cpp @@ -0,0 +1,20 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#define TYPE CAnimSet +#define CStock_TYPE CStock_CAnimSet +#define CNameTable_TYPE CNameTable_CAnimSet +#define CNameTableSlot_TYPE CNameTableSlot_CAnimSet + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +CStock_CAnimSet *_pAnimSetStock = NULL; diff --git a/Sources/Engine/Templates/Stock_CAnimSet.h b/Sources/Engine/Templates/Stock_CAnimSet.h new file mode 100644 index 0000000..2ddf426 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CAnimSet.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STOCK_CANIMSET_H +#define SE_INCL_STOCK_CANIMSET_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +#define TYPE CAnimSet +#define CStock_TYPE CStock_CAnimSet +#define CNameTable_TYPE CNameTable_CAnimSet +#define CNameTableSlot_TYPE CNameTableSlot_CAnimSet + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +ENGINE_API extern CStock_CAnimSet *_pAnimSetStock; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/Stock_CEntityClass.cpp b/Sources/Engine/Templates/Stock_CEntityClass.cpp new file mode 100644 index 0000000..3011b35 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CEntityClass.cpp @@ -0,0 +1,20 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#define TYPE CEntityClass +#define CStock_TYPE CStock_CEntityClass +#define CNameTable_TYPE CNameTable_CEntityClass +#define CNameTableSlot_TYPE CNameTableSlot_CEntityClass + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +CStock_CEntityClass *_pEntityClassStock = NULL; diff --git a/Sources/Engine/Templates/Stock_CEntityClass.h b/Sources/Engine/Templates/Stock_CEntityClass.h new file mode 100644 index 0000000..1404e4d --- /dev/null +++ b/Sources/Engine/Templates/Stock_CEntityClass.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STOCK_CENTITYCLASS_H +#define SE_INCL_STOCK_CENTITYCLASS_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +#define TYPE CEntityClass +#define CStock_TYPE CStock_CEntityClass +#define CNameTable_TYPE CNameTable_CEntityClass +#define CNameTableSlot_TYPE CNameTableSlot_CEntityClass + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +ENGINE_API extern CStock_CEntityClass *_pEntityClassStock; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/Stock_CMesh.cpp b/Sources/Engine/Templates/Stock_CMesh.cpp new file mode 100644 index 0000000..9e9e367 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CMesh.cpp @@ -0,0 +1,20 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#define TYPE CMesh +#define CStock_TYPE CStock_CMesh +#define CNameTable_TYPE CNameTable_CMesh +#define CNameTableSlot_TYPE CNameTableSlot_CMesh + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +CStock_CMesh *_pMeshStock = NULL; diff --git a/Sources/Engine/Templates/Stock_CMesh.h b/Sources/Engine/Templates/Stock_CMesh.h new file mode 100644 index 0000000..92489c2 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CMesh.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STOCK_CMESH_H +#define SE_INCL_STOCK_CMESH_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +#define TYPE CMesh +#define CStock_TYPE CStock_CMesh +#define CNameTable_TYPE CNameTable_CMesh +#define CNameTableSlot_TYPE CNameTableSlot_CMesh + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +ENGINE_API extern CStock_CMesh *_pMeshStock; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/Stock_CModelData.cpp b/Sources/Engine/Templates/Stock_CModelData.cpp new file mode 100644 index 0000000..e26e4ea --- /dev/null +++ b/Sources/Engine/Templates/Stock_CModelData.cpp @@ -0,0 +1,20 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#define TYPE CModelData +#define CStock_TYPE CStock_CModelData +#define CNameTable_TYPE CNameTable_CModelData +#define CNameTableSlot_TYPE CNameTableSlot_CModelData + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +CStock_CModelData *_pModelStock = NULL; diff --git a/Sources/Engine/Templates/Stock_CModelData.h b/Sources/Engine/Templates/Stock_CModelData.h new file mode 100644 index 0000000..848aec8 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CModelData.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STOCK_CMODELDATA_H +#define SE_INCL_STOCK_CMODELDATA_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +#define TYPE CModelData +#define CStock_TYPE CStock_CModelData +#define CNameTable_TYPE CNameTable_CModelData +#define CNameTableSlot_TYPE CNameTableSlot_CModelData + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +ENGINE_API extern CStock_CModelData *_pModelStock; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/Stock_CShader.cpp b/Sources/Engine/Templates/Stock_CShader.cpp new file mode 100644 index 0000000..60eca3a --- /dev/null +++ b/Sources/Engine/Templates/Stock_CShader.cpp @@ -0,0 +1,20 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#define TYPE CShader +#define CStock_TYPE CStock_CShader +#define CNameTable_TYPE CNameTable_CShader +#define CNameTableSlot_TYPE CNameTableSlot_CShader + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +CStock_CShader *_pShaderStock = NULL; diff --git a/Sources/Engine/Templates/Stock_CShader.h b/Sources/Engine/Templates/Stock_CShader.h new file mode 100644 index 0000000..81ca9f5 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CShader.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STOCK_CSHADER_H +#define SE_INCL_STOCK_CSHADER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +#define TYPE CShader +#define CStock_TYPE CStock_CShader +#define CNameTable_TYPE CNameTable_CShader +#define CNameTableSlot_TYPE CNameTableSlot_CShader + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +ENGINE_API extern CStock_CShader *_pShaderStock; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/Stock_CSkeleton.cpp b/Sources/Engine/Templates/Stock_CSkeleton.cpp new file mode 100644 index 0000000..3435386 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CSkeleton.cpp @@ -0,0 +1,20 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#define TYPE CSkeleton +#define CStock_TYPE CStock_CSkeleton +#define CNameTable_TYPE CNameTable_CSkeleton +#define CNameTableSlot_TYPE CNameTableSlot_CSkeleton + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +CStock_CSkeleton *_pSkeletonStock = NULL; diff --git a/Sources/Engine/Templates/Stock_CSkeleton.h b/Sources/Engine/Templates/Stock_CSkeleton.h new file mode 100644 index 0000000..0338277 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CSkeleton.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STOCK_CSKELETON_H +#define SE_INCL_STOCK_CSKELETON_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +#define TYPE CSkeleton +#define CStock_TYPE CStock_CSkeleton +#define CNameTable_TYPE CNameTable_CSkeleton +#define CNameTableSlot_TYPE CNameTableSlot_CSkeleton + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +ENGINE_API extern CStock_CSkeleton *_pSkeletonStock; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/Stock_CSoundData.cpp b/Sources/Engine/Templates/Stock_CSoundData.cpp new file mode 100644 index 0000000..73554b6 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CSoundData.cpp @@ -0,0 +1,20 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#define TYPE CSoundData +#define CStock_TYPE CStock_CSoundData +#define CNameTable_TYPE CNameTable_CSoundData +#define CNameTableSlot_TYPE CNameTableSlot_CSoundData + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +CStock_CSoundData *_pSoundStock = NULL; diff --git a/Sources/Engine/Templates/Stock_CSoundData.h b/Sources/Engine/Templates/Stock_CSoundData.h new file mode 100644 index 0000000..a090842 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CSoundData.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STOCK_CSOUNDDATA_H +#define SE_INCL_STOCK_CSOUNDDATA_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +#define TYPE CSoundData +#define CStock_TYPE CStock_CSoundData +#define CNameTable_TYPE CNameTable_CSoundData +#define CNameTableSlot_TYPE CNameTableSlot_CSoundData + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +ENGINE_API extern CStock_CSoundData *_pSoundStock; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Templates/Stock_CTextureData.cpp b/Sources/Engine/Templates/Stock_CTextureData.cpp new file mode 100644 index 0000000..208a00a --- /dev/null +++ b/Sources/Engine/Templates/Stock_CTextureData.cpp @@ -0,0 +1,20 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +#define TYPE CTextureData +#define CStock_TYPE CStock_CTextureData +#define CNameTable_TYPE CNameTable_CTextureData +#define CNameTableSlot_TYPE CNameTableSlot_CTextureData + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +CStock_CTextureData *_pTextureStock = NULL; diff --git a/Sources/Engine/Templates/Stock_CTextureData.h b/Sources/Engine/Templates/Stock_CTextureData.h new file mode 100644 index 0000000..6a3b756 --- /dev/null +++ b/Sources/Engine/Templates/Stock_CTextureData.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_STOCK_CTEXTUREDATA_H +#define SE_INCL_STOCK_CTEXTUREDATA_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +#define TYPE CTextureData +#define CStock_TYPE CStock_CTextureData +#define CNameTable_TYPE CNameTable_CTextureData +#define CNameTableSlot_TYPE CNameTableSlot_CTextureData + +#include +#include + +#undef CStock_TYPE +#undef CNameTableSlot_TYPE +#undef CNameTable_TYPE +#undef TYPE + +ENGINE_API extern CStock_CTextureData *_pTextureStock; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Terrain/ArrayHolder.cpp b/Sources/Engine/Terrain/ArrayHolder.cpp new file mode 100644 index 0000000..7e1218d --- /dev/null +++ b/Sources/Engine/Terrain/ArrayHolder.cpp @@ -0,0 +1,159 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include + +CArrayHolder::CArrayHolder() +{ +} + +CArrayHolder::~CArrayHolder() +{ + Clear(); +} + +void CArrayHolder::operator=(const CArrayHolder &ahOther) +{ + ASSERT(FALSE); +} + +// Returns pointer for new tile arrays +INDEX CArrayHolder::GetNewArrays() +{ + INDEX ctUnusedArrays = ah_aiFreeArrays.Count(); + // if there are some unused arrays + if(ctUnusedArrays>0) { + // get index of last unused arrays + INDEX iArrays = ah_aiFreeArrays[ctUnusedArrays-1]; + // mark last arrays in stack as used + ah_aiFreeArrays.Pop(); + // return last arrays in stack + return iArrays; + // there arn't any unused arrays + } else { + // allocate new one + TileArrays &ta = ah_ataTileArrays.Push(); + + // if this array holder does not hold tiles in highes nor in lowest lod + if(ah_iLod>0 && ah_iLodtr_iMaxTileLod) { + // create new topmap for tile + CTextureData *ptdTopMap = new CTextureData; + ah_ptrTerrain->tr_atdTopMaps.Add(ptdTopMap); + ta.ta_ptdTopMap = ptdTopMap; + + // Setup tile topmap + INDEX iTopMapWidth = ah_ptrTerrain->tr_pixFirstMipTopMapWidth>>(ah_iLod-1); + INDEX iTopMapHeight = ah_ptrTerrain->tr_pixFirstMipTopMapHeight>>(ah_iLod-1); + CreateTopMap(*ta.ta_ptdTopMap,iTopMapWidth,iTopMapHeight); + ASSERT(ta.ta_ptdTopMap->td_pulFrames==NULL); + } + // return index of new arrays + return ah_ataTileArrays.Count()-1; + } +} + +// Mark tile arrays as unused +void CArrayHolder::FreeArrays(INT iOldArraysIndex) +{ + // if arrays are valid + if(iOldArraysIndex!=-1) { + // remember this arrays as unused + INDEX &iFreeIndex = ah_aiFreeArrays.Push(); + iFreeIndex = iOldArraysIndex; + // Popall all arrays + EmptyArrays(iOldArraysIndex); + } +} + +void CArrayHolder::EmptyArrays(INDEX iArrayIndex) +{ + TileArrays &ta = ah_ataTileArrays[iArrayIndex]; + // for each layer + INDEX cttl = ta.ta_atlLayers.Count(); + for(INDEX itl=0;itl0) { + TileArrays *ptaArrays = &ah_ataTileArrays[0]; + // for each tile array + for(INDEX ita=0;itata_avVertices.sa_Count * sizeof(GFXVertex); + slUsedMemory+=ptaArrays->ta_auvTexCoords.sa_Count * sizeof(GFXTexCoord); + slUsedMemory+=ptaArrays->ta_auvShadowMap.sa_Count * sizeof(GFXTexCoord); + slUsedMemory+=ptaArrays->ta_auvDetailMap.sa_Count * sizeof(GFXTexCoord); + slUsedMemory+=ptaArrays->ta_auiIndices.sa_Count * sizeof(INDEX); + // for each tile layer + INDEX cttl = ptaArrays->ta_atlLayers.sa_Count; + if(cttl>0) { + TileLayer *ptlTileLayer = &ptaArrays->ta_atlLayers.sa_Array[0]; + for(INDEX itl=0;itltl_auiIndices.sa_Count * sizeof(INDEX); + slUsedMemory+=ptlTileLayer->tl_acColors.sa_Count * sizeof(GFXColor); + slUsedMemory+=ptlTileLayer->tl_atcTexCoords.sa_Count * sizeof(GFXTexCoord); + slUsedMemory+=ptlTileLayer->tl_avVertices.sa_Count * sizeof(GFXVertex); + ptlTileLayer++; + } + } + ptaArrays++; + } + } + return slUsedMemory; +} diff --git a/Sources/Engine/Terrain/ArrayHolder.h b/Sources/Engine/Terrain/ArrayHolder.h new file mode 100644 index 0000000..5b03792 --- /dev/null +++ b/Sources/Engine/Terrain/ArrayHolder.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_ARRAY_HOLDER_H +#define SE_INCL_ARRAY_HOLDER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include + +struct TileLayer +{ + CStaticStackArray tl_auiIndices; // Array of indices for one layer + CStaticStackArray tl_acColors; // Array of colors for one layer + CStaticStackArray tl_atcTexCoords; // Array of texcoords for one layer + CStaticStackArray tl_avVertices; // Array of vertices for one layer (used only if tile layer) +}; + +struct TileArrays +{ + void operator=(const TileArrays &taOther) { + this->ta_avVertices = taOther.ta_avVertices; + this->ta_auvTexCoords = taOther.ta_auvTexCoords; + this->ta_auvShadowMap = taOther.ta_auvShadowMap; + this->ta_auvDetailMap = taOther.ta_auvDetailMap; + this->ta_auiIndices = taOther.ta_auiIndices; + this->ta_atlLayers = taOther.ta_atlLayers; + this->ta_ptdTopMap = taOther.ta_ptdTopMap; + } + CStaticStackArray ta_avVertices; // Array of vertices for one tile + CStaticStackArray ta_auvTexCoords; // Array of texcoords for one tile (not used in highest lod) + CStaticStackArray ta_auvShadowMap; // Array of texcoords for shadow map + CStaticStackArray ta_auvDetailMap; // Array of texcoords for detail map + CStaticStackArray ta_auiIndices; // Array of indices for one tile + CStaticStackArray ta_atlLayers; // Array if layers per tile (used only in highest lod) + CTextureData *ta_ptdTopMap; // Pointer to tile top map +}; + +class ENGINE_API CArrayHolder +{ +public: + CArrayHolder(); + ~CArrayHolder(); + void operator=(const CArrayHolder &ahOther); + + // Returns index of new tile arrays + INDEX GetNewArrays(); + // Mark tile arrays as unused + void FreeArrays(INT iOldArraysIndex); + // Just do popall on all arrays + void EmptyArrays(INDEX iArrayIndex); + // Release array holder + void Clear(void); + // Count used memory + SLONG GetUsedMemory(void); + +public: + CTerrain *ah_ptrTerrain; // Terrain that owns this array holder + CStaticStackArray ah_ataTileArrays; // array of tile arrays + CStaticStackArray ah_aiFreeArrays; // array of indices of free arrays + INDEX ah_iLod; // this array holder works in this lod +}; + +#endif \ No newline at end of file diff --git a/Sources/Engine/Terrain/Terrain.cpp b/Sources/Engine/Terrain/Terrain.cpp new file mode 100644 index 0000000..8e20278 --- /dev/null +++ b/Sources/Engine/Terrain/Terrain.cpp @@ -0,0 +1,2144 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern CTerrain *_ptrTerrain; + +extern BOOL _bWorldEditorApp; // is this world edtior app + + +static INDEX _iTerrainVersion = 9; // Current terrain version +static INDEX ctGeneratedTopMaps = 0; // TEMP +static INDEX ctGlobalTopMaps = 0; // TEMP +INDEX _ctShadowMapUpdates = 0; // TEMP +// TEMP + +INDEX _ctNodesVis = 0; +INDEX _ctTris = 0; +INDEX _ctDelayedNodes = 0; +static void ShowTerrainInfo(CAnyProjection3D &apr, CDrawPort *pdp, CTerrain *ptrTerrain); // TEMP + +/* + * Terrain initialization + */ +CTerrain::CTerrain() +{ + tr_vStretch = FLOAT3D(1,0.05f,1); + tr_fDistFactor = 32; + tr_iMaxTileLod = 0; + tr_iSelectedLayer = 0; + tr_ctDriverChanges = -1; + + tr_pixHeightMapWidth = 256; + tr_pixHeightMapHeight = 256; + tr_pixTopMapWidth = 256; + tr_pixTopMapHeight = 256; + tr_pixFirstMipTopMapWidth = 256; + tr_pixFirstMipTopMapHeight = 256; + tr_ptdDetailMap = NULL; + tr_auwHeightMap = NULL; + tr_aubEdgeMap = NULL; + tr_auwShadingMap = NULL; + + // TEMP + try { + tr_ptdDetailMap = _pTextureStock->Obtain_t((CTString)"Textures\\Detail\\Crumples04.tex"); + } catch(char *) { + } + + // Set size of shadow and shading maps + SetShadowMapsSize(0,0); + + // Set terrain size + SetTerrainSize(FLOAT3D(256,80,256)); + // Set num of quads in one tile + SetQuadsPerTileRow(32); + + SetFlags(TR_REGENERATE); +} + +// Render visible terrain tiles +void CTerrain::Render(CAnyProjection3D &apr, CDrawPort *pdp) +{ + // prepare gfx stuff + PrepareScene(apr, pdp, this); + + if(tr_ctDriverChanges!=_pGfx->gl_ctDriverChanges) { + tr_ctDriverChanges = _pGfx->gl_ctDriverChanges; + // RefreshTerrain(); + } + + // if terrain is not frozen + extern INDEX ter_bNoRegeneration; + if(GetFlags()&TR_REGENERATE && !ter_bNoRegeneration) { + // Regenerate tiles + ReGenerate(); + } + // if shadow map must be regenerated + if(GetFlags()&TR_UPDATE_SHADOWMAP) { + UpdateShadowMap(); + } + + + // if top map regen is allowed + if(GetFlags()&TR_ALLOW_TOP_MAP_REGEN) { + // if top map regen is requested + if(GetFlags()&TR_REGENERATE_TOP_MAP) { + // update terrain top map + UpdateTopMap(-1); + // remove request for top map regen + RemoveFlag(TR_REGENERATE_TOP_MAP); + } + // remove flag that allows terrain to regenerate top map + RemoveFlag(TR_ALLOW_TOP_MAP_REGEN); + } + + // show + RenderTerrain(); + + // if flag show brush selection has been set + if(GetFlags()&TR_SHOW_SELECTION) { + ShowSelectionInternal(this); + // remove show selection terrain flag + RemoveFlag(TR_SHOW_SELECTION); + } + + // if flag for quadtree rebuilding is set + if(GetFlags()&TR_REBUILD_QUADTREE) { + // Resize quadtree + UpdateQuadTree(); + // remove flag for quadtree rebuilding + RemoveFlag(TR_REBUILD_QUADTREE); + } + + RemoveFlag(TR_HAS_FOG); + RemoveFlag(TR_HAS_HAZE); + + extern INDEX ter_bShowWireframe; + // if wireframe mode forced + if(ter_bShowWireframe) { + COLOR colWire = 0xFFFFFFFF; + RenderTerrainWire(colWire); + } + + extern INDEX ter_bShowQuadTree; + // if showing of quad tree is required + if(ter_bShowQuadTree) { + DrawQuadTree(); + } + + extern INDEX ter_bShowInfo; + if(ter_bShowInfo) { + ShowTerrainInfo(apr, pdp, this); + } + + _ptrTerrain = NULL; +} + +void CTerrain::RenderWireFrame(CAnyProjection3D &apr, CDrawPort *pdp, COLOR &colEdges) +{ + // prepare gfx stuff + PrepareScene(apr, pdp, this); + // Regenerate tiles + if(tr_ctTiles>=0) { + CTerrainTile &tt = tr_attTiles[0]; + if(tt.tt_iLod == -1) { + ReGenerate(); + } + } + // show + RenderTerrainWire(colEdges); +} + +// Create empty terrain with given size +void CTerrain::CreateEmptyTerrain_t(PIX pixWidth,PIX pixHeight) +{ + _ptrTerrain = this; + // Clear old terrain data if exists + Clear(); + + ASSERT(tr_auwHeightMap==NULL); + ASSERT(tr_aubEdgeMap==NULL); + + AllocateHeightMap(pixWidth,pixHeight); + + AddDefaultLayer_t(); + // Rebuild terrain + ReBuildTerrain(); + _ptrTerrain = NULL; +} + +// Import height map from targa file +void CTerrain::ImportHeightMap_t(CTFileName fnHeightMap, BOOL bUse16b/*=TRUE*/) +{ + _ptrTerrain = this; + BOOL bResizeTerrain = FALSE; + + // Load targa file + CImageInfo iiHeightMap; + iiHeightMap.LoadAnyGfxFormat_t(fnHeightMap); + + // if new width and height are same + if(tr_pixHeightMapWidth==iiHeightMap.ii_Width && tr_pixHeightMapHeight==iiHeightMap.ii_Height) { + // Clear terrain data without removing layers + bResizeTerrain = FALSE; + } else { + // Clear all terrain data + bResizeTerrain = TRUE; + } + bResizeTerrain = TRUE; + + FLOAT fLogWidht = Log2(iiHeightMap.ii_Width-1); + FLOAT fLogHeight = Log2(iiHeightMap.ii_Height-1); + if(fLogWidht!=INDEX(fLogWidht) || fLogHeight!=INDEX(fLogHeight)) { + ThrowF_t("Invalid terrain width or height"); + } + if(iiHeightMap.ii_Width!= iiHeightMap.ii_Height) { + ThrowF_t("Only terrains with same width and height are supported in this version"); + } + + // Reallocate memory for terrain with size + ReAllocateHeightMap(iiHeightMap.ii_Width, iiHeightMap.ii_Height); + + INDEX iHeightMapSize = iiHeightMap.ii_Width * iiHeightMap.ii_Height; + + UBYTE *puwSrc = &iiHeightMap.ii_Picture[0]; + UWORD *puwDst = &tr_auwHeightMap[0]; + INDEX iBpp = iiHeightMap.ii_BitsPerPixel/8; + + // for each word in loaded image + for(INDEX iw=0;iw>8); + } + pacolImage++; + puwHeight++; + } + + iiHeightMap.SaveTGA_t(fnHeightMap); + iiHeightMap.Clear(); +} + +// Rebuild all terrain +void CTerrain::ReBuildTerrain(BOOL bDelayTileRegen/*=FALSE*/) +{ + _ptrTerrain = this; + + ClearTopMaps(); + ClearTiles(); + ClearArrays(); + ClearQuadTree(); + + // Make sure terrain is same size (in metars) + SetTerrainSize(tr_vTerrainSize); + // Build terrain data + BuildTerrainData(); + // Build terrain quadtree + BuildQuadTree(); + // Generate global top map + GenerateTerrainTopMap(); + // Clear current regen list + ClearRegenList(); + // Add all tiles to reqen queue + AddAllTilesToRegenQueue(); + + // if not delaying tile regen + if(!bDelayTileRegen) { + // Regenerate tiles now + ReGenerate(); + // Update shadow map + UpdateShadowMap(); + } +} + +// Refresh terrain +void CTerrain::RefreshTerrain(void) +{ + ReBuildTerrain(); +} + +// Set terrain size +void CTerrain::SetTerrainSize(FLOAT3D vSize) +{ + tr_vStretch(1) = vSize(1) / (tr_pixHeightMapWidth-1); + tr_vStretch(2) = vSize(2) / 65535.0f; + tr_vStretch(3) = vSize(3) / (tr_pixHeightMapHeight-1); + // remember new size + tr_vTerrainSize = vSize; +} + +template +static void CropMap(INDEX iNewWidth, INDEX iNewHeight, INDEX iOldWidth, INDEX iOldHeight, Type *pNewData, Type *pOldData) +{ + INDEX iWidth = Min(iOldWidth,iNewWidth); + INDEX iHeight = Min(iOldHeight,iNewHeight); + INDEX iNewStepX = ClampDn(iNewWidth-iOldWidth,0L); + INDEX iOldStepX = ClampDn(iOldWidth-iNewWidth,0L); + + INDEX iNew = 0; + INDEX iOld = 0; + for(INDEX iy=0;iy +static void StretchMap(INDEX iNewWidth, INDEX iNewHeight, INDEX iOldWidth, INDEX iOldHeight, Type *pNewData, Type *pOldData) +{ + int a=0; + CropMap(iNewWidth,iNewHeight,iOldWidth,iOldHeight,pNewData,pOldData); +} + +template +static void ShrinkMap(INDEX iNewWidth, INDEX iNewHeight, INDEX iOldWidth, INDEX iOldHeight, Type *pNewData, Type *pOldData) +{ + FLOAT fWidth = iNewWidth; + FLOAT fHeight = iNewHeight; + FLOAT fDiffX = (FLOAT)iNewWidth / iOldWidth; + FLOAT fDiffY = (FLOAT)iNewHeight / iOldHeight; + + ULONG *pulNewData = (ULONG*)AllocMemory(iNewWidth * iNewHeight * sizeof(ULONG)); + memset(pulNewData,0,iNewWidth * iNewHeight * sizeof(ULONG)); + + INDEX iOldPix = 0; + for(FLOAT fy=0;fy +static void ResizeMap(INDEX iNewWidth, INDEX iNewHeight, INDEX iOldWidth, INDEX iOldHeight, Type *pNewData, Type *pOldData) +{ + CropMap(iNewWidth,iNewHeight,iOldWidth,iOldHeight,pNewData,pOldData); + /* + if(iNewWidth>=iOldWidth && iNewHeight>=iOldHeight) { + StretchMap(iNewWidth,iNewHeight,iOldWidth,iOldHeight,pNewData,pOldData); + } else if(iNewWidth<=iOldWidth && iNewHeight<=iOldHeight) { + ShrinkMap(iNewWidth,iNewHeight,iOldWidth,iOldHeight,pNewData,pOldData); + } else { + INDEX iTempWidth = Max(iNewWidth ,iOldWidth); + INDEX iTempHeight = Max(iNewHeight,iOldHeight); + INDEX iTempSize = iTempWidth*iTempHeight*sizeof(Type); + Type *pTempData = (Type*)AllocMemory(iTempSize); + memset(pTempData,0,iTempSize); + StretchMap(iTempWidth,iTempHeight,iOldWidth,iOldHeight,pTempData,pOldData); + ShrinkMap(iNewWidth,iNewHeight,iTempWidth,iTempHeight,pNewData, pTempData); + FreeMemory(pTempData); + } + */ +} + +void CTerrain::AllocateHeightMap(PIX pixWidth, PIX pixHeight) +{ + ASSERT(tr_auwHeightMap==NULL); + ASSERT(tr_aubEdgeMap==NULL); + + FLOAT fLogWidht = Log2(pixWidth-1); + FLOAT fLogHeight = Log2(pixHeight-1); + if(fLogWidht!=INDEX(fLogWidht) || fLogHeight!=INDEX(fLogHeight)) { + ASSERTALWAYS("Invalid terrain width or height"); + return; + } + if(pixWidth != pixHeight) { + ASSERTALWAYS("Only terrains with same width and height are supported in this version"); + return; + } + + INDEX iSize = pixWidth * pixHeight * sizeof(UBYTE); + + // Allocate memory for maps + tr_auwHeightMap = (UWORD*)AllocMemory(iSize*2); + tr_aubEdgeMap = (UBYTE*)AllocMemory(iSize); + memset(tr_auwHeightMap,0,iSize*2); + memset(tr_aubEdgeMap,255,iSize); + + tr_pixHeightMapWidth = pixWidth; + tr_pixHeightMapHeight = pixHeight; + + // Update shadow map size cos it depends on size of height map + SetShadowMapsSize(tr_iShadowMapSizeAspect,tr_iShadingMapSizeAspect); +} + +void CTerrain::ReAllocateHeightMap(PIX pixWidth, PIX pixHeight) +{ + ASSERT(tr_auwHeightMap!=NULL); + ASSERT(tr_aubEdgeMap!=NULL); + + FLOAT fLogWidht = Log2(pixWidth-1); + FLOAT fLogHeight = Log2(pixHeight-1); + if(fLogWidht!=INDEX(fLogWidht) || fLogHeight!=INDEX(fLogHeight)) { + ASSERTALWAYS("Invalid terrain width or height"); + return; + } + if(pixWidth != pixHeight) { + ASSERTALWAYS("Only terrains with same width and height are supported in this version"); + return; + } + + INDEX iSize = pixWidth * pixHeight * sizeof(UBYTE); + + // Allocate memory for maps + UWORD *auwHeightMap = (UWORD*)AllocMemory(iSize*2); + UBYTE *aubEdgeMap = (UBYTE*)AllocMemory(iSize); + + // Resize height map + memset(auwHeightMap,0,iSize*2); + ResizeMap(pixWidth,pixHeight,tr_pixHeightMapWidth,tr_pixHeightMapHeight,auwHeightMap,tr_auwHeightMap); + + // Resize edge map + memset(aubEdgeMap,255,iSize); + ResizeMap(pixWidth,pixHeight,tr_pixHeightMapWidth,tr_pixHeightMapHeight,aubEdgeMap,tr_aubEdgeMap); + + // for each layer + INDEX cttl = tr_atlLayers.Count(); + for(INDEX itl=0;itl> Clamp dn SetShadowMapsSize") + + if(iShadingMapAspect<0) { + iShadingMapAspect = 0; + } + ASSERT(iShadingMapAspect>=0); + + + tr_iShadowMapSizeAspect = iShadowMapAspect; + tr_iShadingMapSizeAspect = iShadingMapAspect; + + if(GetShadowMapWidth()<32 || GetShadingMapHeight()<32) { + tr_iShadowMapSizeAspect = -(FastLog2(tr_pixHeightMapWidth-1)-5); + } + + if(GetShadingMapWidth()<32 || GetShadingMapWidth()<32) { + tr_iShadingMapSizeAspect = 0; + } + + PIX pixShadowMapWidth = GetShadowMapWidth(); + PIX pixShadowMapHeight = GetShadowMapHeight(); + + PIX pixShadingMapWidth = GetShadingMapWidth(); + PIX pixShadingMapHeight = GetShadingMapHeight(); + + + // Clear current shadow map + ClearShadowMap(); + + ULONG ulShadowMapFlags = 0; + // if current app is world editor app + if(_bWorldEditorApp) { + // force texture to be static + ulShadowMapFlags = TEX_STATIC; + } + + // Create new shadow map texture + ASSERT(tr_tdShadowMap.td_pulFrames==NULL); + CreateTexture(tr_tdShadowMap,pixShadowMapWidth,pixShadowMapHeight,ulShadowMapFlags); + // Reset shadow map texture + memset(&tr_tdShadowMap.td_pulFrames[0],0,sizeof(COLOR)*pixShadowMapWidth*pixShadowMapHeight); + + // Create new shading map + ASSERT(tr_auwShadingMap==NULL); + tr_auwShadingMap = (UWORD*)AllocMemory(pixShadingMapWidth*pixShadingMapHeight*sizeof(UWORD)); + // Reset shading map + memset(&tr_auwShadingMap[0],0,pixShadingMapWidth*pixShadingMapHeight*sizeof(UWORD)); +} + +// Set size of terrain top map texture +void CTerrain::SetGlobalTopMapSize(PIX pixTopMapSize) +{ + FLOAT fLogSize = Log2(pixTopMapSize); + if(fLogSize!=INDEX(fLogSize)) { + ASSERTALWAYS("Invalid top map size"); + return; + } + + tr_pixTopMapWidth = pixTopMapSize; + tr_pixTopMapHeight = pixTopMapSize; +} + +// Set size of top map texture for tiles in lower lods +void CTerrain::SetTileTopMapSize(PIX pixLodTopMapSize) +{ + FLOAT fLogSize = Log2(pixLodTopMapSize); + if(fLogSize!=INDEX(fLogSize)) { + ASSERTALWAYS("Invalid top map size"); + return; + } + + tr_pixFirstMipTopMapWidth = pixLodTopMapSize; + tr_pixFirstMipTopMapHeight = pixLodTopMapSize; +} + +// Set lod distance factor +void CTerrain::SetLodDistanceFactor(FLOAT fLodDistance) +{ + tr_fDistFactor = ClampDn(fLodDistance,0.1f); +} + +// Get shadow map size +inline PIX CTerrain::GetShadowMapWidth(void) +{ + if(tr_iShadowMapSizeAspect<0) { + return (tr_pixHeightMapWidth-1)>>-tr_iShadowMapSizeAspect; + } else { + return (tr_pixHeightMapWidth-1)<>-tr_iShadowMapSizeAspect; + } else { + return (tr_pixHeightMapHeight-1)<=0); + return GetShadowMapWidth()>>tr_iShadingMapSizeAspect; +} +inline PIX CTerrain::GetShadingMapHeight(void) +{ + ASSERT(tr_iShadingMapSizeAspect>=0); + return GetShadowMapHeight()>>tr_iShadingMapSizeAspect; +} + +// Get reference to layer +CTerrainLayer &CTerrain::GetLayer(INDEX iLayer) +{ + INDEX cttl = tr_atlLayers.Count(); + + ASSERT(iLayer=0); + return tr_atlLayers[iLayer]; +} + +// Add new layer +CTerrainLayer &CTerrain::AddLayer_t(CTFileName fnTexture, LayerType ltType/*=LT_NORMAL*/, BOOL bUpdateTerrain/*=TRUE*/) +{ + CTerrainLayer &tl = tr_atlLayers.Push(); + + // Set layer properties + tl.tl_ltType = ltType; + tl.SetLayerSize(tr_pixHeightMapWidth, tr_pixHeightMapHeight); + tl.SetLayerTexture_t(fnTexture); + + // if update terrain flag has been set + if(bUpdateTerrain) { + // Refresh whole terrain + RefreshTerrain(); + } + return tl; +} + +// Remove one layer +void CTerrain::RemoveLayer(INDEX iLayer, BOOL bUpdateTerrain/*=TRUE*/) +{ + CStaticStackArray atlLayers; + INDEX cttl = tr_atlLayers.Count(); + + if(iLayer<0 || iLayer>=cttl) { + ASSERTALWAYS("Invalid layer index"); + return; + } + + if(iLayer==0 && cttl==1) { + ASSERTALWAYS("Can't remove last layer"); + return; + } + + // for each exisiting layer + for(INDEX itl=0;itl atlLayers; + INDEX cttl = tr_atlLayers.Count(); + + if(iLayer<0 || iLayer>=cttl) { + ASSERTALWAYS("Invalid layer index"); + return iLayer; + } + + if(iLayer==0 && cttl==1) { + ASSERTALWAYS("Can't move only layer"); + return iLayer; + } + + if(iLayer==iNewIndex) { + ASSERTALWAYS("Old layer index is same as new one"); + return iLayer; + } + + + CStaticStackArray &atlFrom = tr_atlLayers; + CStaticStackArray &atlTo = atlLayers; + + atlTo.Push(cttl); + + INDEX iOld = iLayer; + INDEX iNew = iNewIndex; + + for(INDEX iFrom=0; iFromiOld && iFrom>iNew)) { + iTo = iFrom; + } else if (iFrom==iOld) { + iTo = iNew; + } else { + if (iNew>iOld) { + iTo = iFrom-1; + } else { + iTo = iFrom+1; + } + } + atlTo[iTo] = atlFrom[iFrom]; + } + + ASSERT(atlLayers.Count() == cttl); + // Clear old layers + tr_atlLayers.Clear(); + // Copy new layers insted of old one + tr_atlLayers = atlLayers; + + // if update terrain flag has been set + if(bUpdateTerrain) { + // Refresh whole terrain + RefreshTerrain(); + } + return iNewIndex; +} + +// Add tile to reqen queue +void CTerrain::AddTileToRegenQueue(INDEX iTileIndex) +{ + INDEX &iRegenIndex = tr_auiRegenList.Push(); + CTerrainTile &tt = tr_attTiles[iTileIndex]; + + iRegenIndex = iTileIndex; + tt.AddFlag(TT_REGENERATE); +} + +// Add all tiles to regen queue +void CTerrain::AddAllTilesToRegenQueue() +{ + // for each terrain tile + for(INDEX itt=0;ittr = Lerp(pcolSrc->r,pcolDst->r,fMaskStrength); + pcolSrc->g = Lerp(pcolSrc->g,pcolDst->g,fMaskStrength); + pcolSrc->b = Lerp(pcolSrc->b,pcolDst->b,fMaskStrength); + pcolSrc->a = 255; +} + +static INDEX _ctSavedTopMaps=0; +static void SaveAsTga(CTextureData *ptdTex) +{ + INDEX iSize = ptdTex->td_mexWidth * ptdTex->td_mexHeight * 4; + CImageInfo iiHeightMap; + iiHeightMap.ii_Width = ptdTex->td_mexWidth; + iiHeightMap.ii_Height = ptdTex->td_mexHeight; + iiHeightMap.ii_BitsPerPixel = 32; + iiHeightMap.ii_Picture = (UBYTE*)AllocMemory(iSize); + + memcpy(&iiHeightMap.ii_Picture[0],&ptdTex->td_pulFrames[0],iSize); + + + CTString strTopMap = CTString(0,"Temp\\Topmap%d.tga",++_ctSavedTopMaps); + iiHeightMap.SaveTGA_t(strTopMap); + iiHeightMap.Clear(); + + + /* + GFXColor *pacolImage = (GFXColor*)&iiHeightMap.ii_Picture[0]; + UWORD *puwHeight = tr_auwHeightMap; + for(INDEX ipix=0;ipix>8); + } + pacolImage++; + puwHeight++; + } + */ + +} + +static void AddTileLayerToTopMap(CTerrain *ptrTerrain, INDEX iTileIndex, INDEX iLayer) +{ + CTerrainLayer &tl = ptrTerrain->tr_atlLayers[iLayer]; + CTextureData *ptdSrc = tl.tl_ptdTexture; + CTextureData *ptdDst; + + INDEX ctQuadsPerTile = ptrTerrain->tr_ctQuadsInTileRow; + INDEX iOffsetX = 0; + INDEX iOffsetZ = 0; + + if(iTileIndex==(-1)) { + ptdDst = &ptrTerrain->tr_tdTopMap; + ctQuadsPerTile = ptrTerrain->tr_ctTilesX * ptrTerrain->tr_ctQuadsInTileRow; + } else { + CTerrainTile &tt = ptrTerrain->tr_attTiles[iTileIndex]; + ptdDst = tt.GetTopMap(); + iOffsetX = tt.tt_iOffsetX*ctQuadsPerTile; + iOffsetZ = tt.tt_iOffsetZ*ctQuadsPerTile; + } + + ULONG *pulFirstInTopMap = ptdDst->td_pulFrames; + UBYTE *pubFirstInLayerMask = tl.tl_aubColors; + + // Calculate width and height of quad that will be draw in top map + PIX pixDstQuadWidth = ptdDst->GetPixWidth() / ctQuadsPerTile; + PIX pixSrcQuadWidth = tl.tl_pixTileWidth; + + // if dst quad is smaller then one pixel + if(pixDstQuadWidth==0) { + return; + } + + ASSERT(tl.tl_ctTilesInRow==tl.tl_ctTilesInCol); + + INDEX iSrcMipmap = FastLog2((ptdSrc->GetPixWidth() / tl.tl_ctTilesInRow) / pixDstQuadWidth); + INDEX iSrcMipMapOffset = GetMipmapOffset(iSrcMipmap,ptdSrc->GetPixWidth(),ptdSrc->GetPixHeight()); + INDEX iSrcMipWidth = ptdSrc->GetPixWidth() >> iSrcMipmap; + INDEX iSrcMipQuadWidth = pixSrcQuadWidth >> iSrcMipmap; + INDEX iSrcMipQuadHeight = iSrcMipQuadWidth; + + ASSERT(pixDstQuadWidth==iSrcMipQuadWidth); + + ULONG *pulSrcMip = &ptdSrc->td_pulFrames[iSrcMipMapOffset]; + + INDEX iMaskIndex = iOffsetX + iOffsetZ*ptrTerrain->tr_pixHeightMapWidth; + INDEX iMaskStepX = ptrTerrain->tr_pixHeightMapWidth - ctQuadsPerTile; + + // for each quad in tile + for(INDEX iQuadY=0;iQuadY>TL_FLIPX_SHIFT; + BOOL bFlipY = (ubMask&TL_FLIPY)>>TL_FLIPY_SHIFT; + BOOL bSwapXY = (ubMask&TL_SWAPXY)>>TL_SWAPXY_SHIFT; + BOOL bVisible = (ubMask&TL_VISIBLE)>>TL_VISIBLE_SHIFT; + INDEX iTile = ubMask&TL_TILE_INDEX; + INDEX iTileX = iTile%tl.tl_ctTilesInRow; + INDEX iTileY = iTile/tl.tl_ctTilesInRow; + + // if not visible + if(!bVisible) { + iMaskIndex++; + continue; // skip it + } + + ASSERT(iTileXGetPixWidth(); + ULONG *pulDstPixel = &pulFirstInTopMap[iFirstDstQuadPixel]; + PIX pixSrc = iTileX*iSrcMipQuadWidth + iTileY*iSrcMipQuadWidth*iSrcMipWidth; + PIX pixDst = 0; + PIX pixDstModulo = ptdDst->GetPixWidth() - pixDstQuadWidth; + PIX pixSrcStepY = iSrcMipWidth; + PIX pixSrcStepX = 1; + + if(bFlipY) { + pixSrcStepY = -pixSrcStepY; + pixSrc+=iSrcMipQuadHeight*iSrcMipWidth; + } + if(bFlipX) { + pixSrcStepX = -pixSrcStepX; + pixSrc+=iSrcMipQuadWidth; + } + + if(bSwapXY) { + Swap(pixSrcStepX, pixSrcStepY); + } + + pixSrcStepY -= pixDstQuadWidth*pixSrcStepX; + + // for each pixel in this quad + for(PIX pixY=0;pixY 0x80000000) { + pulDstPixel[pixDst] = pulSrcMip[pixSrc]; + } + pixSrc+=pixSrcStepX; + pixDst++; + } + pixDst+=pixDstModulo; + pixSrc+=pixSrcStepY; + } + iMaskIndex++; + } + iMaskIndex+=iMaskStepX; + } +} + +void CTerrain::UpdateTopMap(INDEX iTileIndex, Rect *prcDest/*=NULL*/) +{ + //ReGenerateTopMap(this, iTileIndex); + + if(iTileIndex==(-1)) { + ctGlobalTopMaps++; + } else { + ctGeneratedTopMaps++; + } + + FIX16_16 fiMaskDiv = 1; + INDEX iFirstInMask = 0; + INDEX iMaskWidth = tr_pixHeightMapWidth; + INDEX iTiling = 1; + INDEX iSrcMipWidth = 1; + + + // destionation texture (must have set allocated memory) + CTextureData *ptdDest; + + // if global top map + if(iTileIndex==(-1)) { + ptdDest = &tr_tdTopMap; + // else tile top map + } else { + CTerrainTile &tt = tr_attTiles[iTileIndex]; + ptdDest = tt.GetTopMap(); + fiMaskDiv = tr_ctTilesX; + iFirstInMask = iMaskWidth * tt.tt_iOffsetZ * (tr_ctVerticesInTileRow-1) + (tt.tt_iOffsetX * (tr_ctVerticesInTileRow-1)); + } + + ASSERT(ptdDest->td_pulFrames==NULL); + PrepareSharedTopMapMemory(ptdDest, iTileIndex); + + ASSERT(ptdDest!=NULL); + ASSERT(ptdDest->td_pulFrames!=NULL); + + // ASSERT(ptdDest->GetPixWidth()>0 && ptdDest->GetPixHeight()>0 && ptdDest->GetPixWidth()==ptdDest->GetPixHeight()); + // iTiling = ClampDn(iTiling,(INDEX)1); + // INDEX iSrcMipWidth = ClampDn(ptdDest->GetWidth()/iTiling,(INDEX)1); + + + INDEX ctLayers = tr_atlLayers.Count(); + // for each layer + for(INDEX itl=0;itlGetPixWidth()>0 && ptdDest->GetPixHeight()>0 && ptdDest->GetPixWidth()==ptdDest->GetPixHeight()); + ASSERT(iTiling>=1); + iTiling = ClampDn(iTiling,(INDEX)1); + + // get source texture + CTextureData *ptdSrc = tl.tl_ptdTexture; + INDEX iSrcMipWidth = ClampDn( ptdSrc->GetPixWidth() /iTiling, 1L); + INDEX iSrcMipHeight = ClampDn( ptdSrc->GetPixHeight()/iTiling, 1L); + + // Get mipmap of source texture + INDEX immW = FastLog2( ptdSrc->GetPixWidth() / iSrcMipWidth); + INDEX immH = FastLog2( ptdSrc->GetPixHeight() / iSrcMipHeight); + // get address of first byte in source mipmap + INDEX imm = Max( immW, immH); + INDEX iMipAdr = GetMipmapOffset(imm,ptdSrc->GetPixWidth(),ptdSrc->GetPixHeight()); + + // Mask thing + // get first byte in layer mask + UBYTE *ubFirstInMask = &tl.tl_aubColors[iFirstInMask]; + // get first byte in edge map + UBYTE *ubFirstInEdgeMap = &tr_aubEdgeMap[iFirstInMask]; + FIX16_16 fiHMaskStep = FIX16_16(iMaskWidth-1) / FIX16_16(ptdDest->GetWidth()-1) / fiMaskDiv; + FIX16_16 fiVMaskStep = FIX16_16(iMaskWidth-1) / FIX16_16(ptdDest->GetWidth()-1) / fiMaskDiv; + + SLONG xHMaskStep = fiHMaskStep.slHolder; + SLONG xVMaskStep = fiVMaskStep.slHolder; + SLONG xMaskVPos=0; + + // get first byte in destination texture + ULONG *pulTexDst = (ULONG*)&ptdDest->td_pulFrames[0]; + // get first byte in source texture + ULONG *pulFirstInMipSrc = (ULONG*)&ptdSrc->td_pulFrames[iMipAdr]; + + // for each row + for(UINT ir=0;irGetPixHeight();ir++) + { + // get first byte for src mip texture in this row + ULONG *pulSrcRow = &pulFirstInMipSrc[(ir&(iSrcMipWidth-1))*iSrcMipWidth];//% + INDEX iMaskVPos = (INDEX)(xMaskVPos>>16) * (iMaskWidth); + UBYTE *pubMaskRow = &ubFirstInMask[iMaskVPos]; + UBYTE *pubEdgeMaskRow = &ubFirstInEdgeMap[iMaskVPos]; + SLONG xMaskHPos = 0; + // for each column + for(UINT ic=0;icGetPixWidth();ic++) + { + ULONG *ulSrc = &pulSrcRow[ic&(iSrcMipWidth-1)]; + INDEX iMask = (INDEX)(xMaskHPos>>16); + + SLONG x1 = (SLONG)(pubMaskRow[iMask+0]) <<0; //NormByteToFixInt(pubMaskRow[iMask]); + SLONG x2 = (SLONG)(pubMaskRow[iMask+1]) <<0; //NormByteToFixInt(pubMaskRow[iMask+1]); + SLONG x3 = (SLONG)(pubMaskRow[iMask+iMaskWidth+0]) <<0;//NormByteToFixInt(pubMaskRow[iMask+iMaskWidth+0]); + SLONG x4 = (SLONG)(pubMaskRow[iMask+iMaskWidth+1]) <<0;//NormByteToFixInt(pubMaskRow[iMask+iMaskWidth+1]); + SLONG xFactH = xMaskHPos - (xMaskHPos&0xFFFF0000); + SLONG xFactV = xMaskVPos - (xMaskVPos&0xFFFF0000); + + SLONG xStrengthX1 = (x1<<7) + (SLONG)(((x2-x1)*xFactH)>>9); //Lerp(fi1,fi2,fiFactH); + SLONG xStrengthX2 = (x3<<7) + (SLONG)(((x4-x3)*xFactH)>>9); //Lerp(fi3,fi4,fiFactH); + SLONG xStrength = (xStrengthX1<<1) + (SLONG)((((xStrengthX2>>0)-(xStrengthX1>>0))*xFactV)>>15); //Lerp(fiStrengthX1,fiStrengthX2,fiFactV); + + GFXColor *pcolSrc = (GFXColor*)pulTexDst; + GFXColor *pcolDst = (GFXColor*)ulSrc; + pcolSrc->r = (BYTE)( (ULONG)pcolSrc->r + ((((ULONG)pcolDst->r - (ULONG)pcolSrc->r) * xStrength)>>16)); + pcolSrc->g = (BYTE)( (ULONG)pcolSrc->g + ((((ULONG)pcolDst->g - (ULONG)pcolSrc->g) * xStrength)>>16)); + pcolSrc->b = (BYTE)( (ULONG)pcolSrc->b + ((((ULONG)pcolDst->b - (ULONG)pcolSrc->b) * xStrength)>>16)); + pcolSrc->a = pubEdgeMaskRow[iMask]; + + pulTexDst++; + xMaskHPos += xHMaskStep; + } + xMaskVPos += xVMaskStep; + } + } + // make mipmaps + INDEX ctMipMaps = GetNoOfMipmaps(ptdDest->GetPixWidth(),ptdDest->GetPixHeight()); + MakeMipmaps(ctMipMaps, ptdDest->td_pulFrames, ptdDest->GetPixWidth(), ptdDest->GetPixHeight()); + + #pragma message(">> Fix DitherMipmaps") + INDEX iDithering = 4; + DitherMipmaps(iDithering,ptdDest->td_pulFrames,ptdDest->td_pulFrames,ptdDest->GetPixWidth(),ptdDest->GetPixHeight()); + // force topmap upload + ptdDest->SetAsCurrent(0,TRUE); + + // Free shared memory + FreeSharedTopMapMemory(ptdDest, iTileIndex); +} + +void CTerrain::GetAllTerrainBBox(FLOATaabbox3D &bbox) +{ + // Get last quad tree level + INDEX ctqtl = tr_aqtlQuadTreeLevels.Count(); + QuadTreeLevel &qtl = tr_aqtlQuadTreeLevels[ctqtl-1]; + + ASSERT(qtl.qtl_ctNodes==1); + // Get quad tree node for last level + QuadTreeNode &qtn = tr_aqtnQuadTreeNodes[qtl.qtl_iFirstNode]; + bbox = qtn.qtn_aabbox; +} + +// Get shading color from tex coords in shading map +COLOR CTerrain::GetShadeColor(CShadingInfo *psi) +{ + ASSERT(psi!=NULL); + ASSERT(tr_auwShadingMap!=NULL); + + PIX pixShadowU = Clamp(psi->si_pixShadowU,0L,GetShadingMapWidth()-2L); + PIX pixShadowV = Clamp(psi->si_pixShadowV,0L,GetShadingMapHeight()-2L); + FLOAT fUDRatio = psi->si_fUDRatio; + FLOAT fLRRatio = psi->si_fLRRatio; + + PIX pixWidth = GetShadingMapWidth(); + PIX pixShadow = pixShadowU + pixShadowV*pixWidth; + UWORD auwShade[4]; + SLONG aslr[4], aslg[4], aslb[4]; + + auwShade[0] = tr_auwShadingMap[pixShadow]; + auwShade[1] = tr_auwShadingMap[pixShadow+1]; + auwShade[2] = tr_auwShadingMap[pixShadow+pixWidth+0]; + auwShade[3] = tr_auwShadingMap[pixShadow+pixWidth+1]; + + for(INDEX ish=0;ish<4;ish++) { + aslr[ish] = (auwShade[ish]&0x7C00)>>10; + aslg[ish] = (auwShade[ish]&0x03E0)>> 5; + aslb[ish] = (auwShade[ish]&0x001F)>> 0; + + aslr[ish] = (aslr[ish]<<3) | (aslr[ish]>>2); + aslg[ish] = (aslg[ish]<<3) | (aslg[ish]>>2); + aslb[ish] = (aslb[ish]<<3) | (aslb[ish]>>2); + } + + SLONG slRed = Lerp( Lerp(aslr[0], aslr[1], fLRRatio), Lerp(aslr[2], aslr[3], fLRRatio), fUDRatio); + SLONG slGreen = Lerp( Lerp(aslg[0], aslg[1], fLRRatio), Lerp(aslg[2], aslg[3], fLRRatio), fUDRatio); + SLONG slBlue = Lerp( Lerp(aslb[0], aslb[1], fLRRatio), Lerp(aslb[2], aslb[3], fLRRatio), fUDRatio); + + ULONG ulPixel = ((slRed <<24)&0xFF000000) | + ((slGreen<<16)&0x00FF0000) | + ((slBlue << 8)&0x0000FF00) | 0xFF; + + return ulPixel; +} + +// Get plane from given point +FLOATplane3D CTerrain::GetPlaneFromPoint(FLOAT3D &vAbsPoint) +{ + ASSERT(tr_penEntity!=NULL); + FLOAT3D vRelPoint = (vAbsPoint-tr_penEntity->en_plPlacement.pl_PositionVector) * !tr_penEntity->en_mRotation; + vRelPoint(1) /= tr_vStretch(1); + vRelPoint(3) /= tr_vStretch(3); + PIX pixX = floor(vRelPoint(1)); + PIX pixZ = floor(vRelPoint(3)); + PIX pixWidth = tr_pixHeightMapWidth; + FLOAT fXRatio = vRelPoint(1) - pixX; + FLOAT fZRatio = vRelPoint(3) - pixZ; + + INDEX iPix = pixX + pixZ*pixWidth; + BOOL bFacing = (iPix)&1; + + FLOAT3D vx0 = FLOAT3D((pixX+0)*tr_vStretch(1),tr_auwHeightMap[iPix] * tr_vStretch(2) ,(pixZ+0)*tr_vStretch(3)); + FLOAT3D vx1 = FLOAT3D((pixX+1)*tr_vStretch(1),tr_auwHeightMap[iPix+1] * tr_vStretch(2) ,(pixZ+0)*tr_vStretch(3)); + FLOAT3D vx2 = FLOAT3D((pixX+0)*tr_vStretch(1),tr_auwHeightMap[iPix+pixWidth] * tr_vStretch(2) ,(pixZ+1)*tr_vStretch(3)); + FLOAT3D vx3 = FLOAT3D((pixX+1)*tr_vStretch(1),tr_auwHeightMap[iPix+pixWidth+1]* tr_vStretch(2) ,(pixZ+1)*tr_vStretch(3)); + + vx0 = vx0 * tr_penEntity->en_mRotation + tr_penEntity->en_plPlacement.pl_PositionVector; + vx1 = vx1 * tr_penEntity->en_mRotation + tr_penEntity->en_plPlacement.pl_PositionVector; + vx2 = vx2 * tr_penEntity->en_mRotation + tr_penEntity->en_plPlacement.pl_PositionVector; + vx3 = vx3 * tr_penEntity->en_mRotation + tr_penEntity->en_plPlacement.pl_PositionVector; + + if(bFacing) { + if(fXRatio>=fZRatio) { + return FLOATplane3D(vx0,vx2,vx1); + } else { + return FLOATplane3D(vx1,vx2,vx3); + } + } else { + if(fXRatio>=fZRatio) { + return FLOATplane3D(vx2,vx3,vx0); + } else { + return FLOATplane3D(vx0,vx3,vx1); + } + } +} + +// Sets number of quads in row of one tile +void CTerrain::SetQuadsPerTileRow(INDEX ctQuadsPerTileRow) +{ + tr_ctQuadsInTileRow = Clamp(ctQuadsPerTileRow,(INDEX)4,(INDEX)(tr_pixHeightMapWidth-1)); + if(tr_ctQuadsInTileRow!=ctQuadsPerTileRow) { + CPrintF("Warning: Quads per tile has been changed from requested %d to %d\n",ctQuadsPerTileRow,tr_ctQuadsInTileRow); + } + // TODO: Assert that it is 2^n + tr_ctVerticesInTileRow = tr_ctQuadsInTileRow+1; +} + +// Set Terrain stretch +void CTerrain::SetTerrainStretch(FLOAT3D vStretch) +{ + tr_vStretch = vStretch; +} + +// Build terrain data +void CTerrain::BuildTerrainData() +{ + // Allocate space for terrain tiles + tr_ctTilesX = (tr_pixHeightMapWidth-1) / tr_ctQuadsInTileRow; + tr_ctTilesY = (tr_pixHeightMapHeight-1) / tr_ctQuadsInTileRow; + tr_ctTiles = tr_ctTilesX*tr_ctTilesY; + tr_attTiles.New(tr_ctTiles); + + // Calculate max posible lod + INDEX ctVtxInLod = tr_ctQuadsInTileRow; + tr_iMaxTileLod = 0; + while(ctVtxInLod>2) { + tr_iMaxTileLod++; + ctVtxInLod = ctVtxInLod>>1; + } + + // Allocate memory for terrain tile arrays + tr_aArrayHolders.New(tr_iMaxTileLod+1); + INDEX ctah = tr_aArrayHolders.Count(); + // for each array handler + for(INDEX iah=0;iah0) tt.tt_aiNeighbours[NB_TOP] = iTileIndex-tr_ctTilesX; + if(ix>0) tt.tt_aiNeighbours[NB_LEFT] = iTileIndex-1; + if(iyGetPixWidth()>0 && ptdDest->GetPixHeight()>0 && ptdDest->GetPixWidth()==ptdDest->GetPixHeight()); + INDEX iSrcMipWidth = ClampDn(ptdDest->GetWidth()/iTiling,(INDEX)1); + + + INDEX ctLayers = tr_atlLayers.Count(); + // for each layer + for(INDEX itl=0;itlGetPixWidth()/iSrcMipWidth); + // get address of first byte in source mipmap + INDEX iMipAdr = GetMipmapOffset(imm,ptdSrc->GetPixWidth(),ptdSrc->GetPixHeight()); + + // Mask thing + // get first byte in layer mask + UBYTE *ubFirstInMask = &tl.tl_aubColors[iFirstInMask]; + FIX16_16 fiHMaskStep = FIX16_16(iMaskWidth-1)/FIX16_16(ptdDest->GetWidth()-1)/fiMaskDiv; + FIX16_16 fiVMaskStep = FIX16_16(iMaskWidth-1)/FIX16_16(ptdDest->GetWidth()-1)/fiMaskDiv; + + SLONG xHMaskStep = fiHMaskStep.slHolder; + SLONG xVMaskStep = fiVMaskStep.slHolder; + SLONG xMaskVPos=0; + + // get first byte in destination texture + ULONG *pulTexDst = (ULONG*)&ptdDest->td_pulFrames[0]; + // get first byte in source texture + ULONG *pulFirstInMipSrc = (ULONG*)&ptdSrc->td_pulFrames[iMipAdr]; + + // for each row + for(UINT ir=0;irGetHeight();ir++) { + // get first byte for src mip texture in this row + ULONG *pulSrcRow = &pulFirstInMipSrc[(ir&(iSrcMipWidth-1))*iSrcMipWidth];//% + INDEX iMaskVPos = (INDEX)(xMaskVPos>>16) * (iMaskWidth); + UBYTE *pubMaskRow = &ubFirstInMask[iMaskVPos]; + SLONG xMaskHPos = 0; + // for each column + for(UINT ic=0;icGetWidth();ic++) { + + ULONG *ulSrc = &pulSrcRow[ic&(iSrcMipWidth-1)]; + INDEX iMask = (INDEX)(xMaskHPos>>16); + + SLONG x1 = (SLONG)(pubMaskRow[iMask+0]) <<0; //NormByteToFixInt(pubMaskRow[iMask]); + SLONG x2 = (SLONG)(pubMaskRow[iMask+1]) <<0; //NormByteToFixInt(pubMaskRow[iMask+1]); + SLONG x3 = (SLONG)(pubMaskRow[iMask+iMaskWidth+0]) <<0;//NormByteToFixInt(pubMaskRow[iMask+iMaskWidth+0]); + SLONG x4 = (SLONG)(pubMaskRow[iMask+iMaskWidth+1]) <<0;//NormByteToFixInt(pubMaskRow[iMask+iMaskWidth+1]); + SLONG xFactH = xMaskHPos - (xMaskHPos&0xFFFF0000); + SLONG xFactV = xMaskVPos - (xMaskVPos&0xFFFF0000); + + SLONG xStrengthX1 = (x1<<7) + (SLONG)(((x2-x1)*xFactH)>>9); //Lerp(fi1,fi2,fiFactH); + SLONG xStrengthX2 = (x3<<7) + (SLONG)(((x4-x3)*xFactH)>>9); //Lerp(fi3,fi4,fiFactH); + SLONG xStrength = (xStrengthX1<<1) + (SLONG)((((xStrengthX2>>0)-(xStrengthX1>>0))*xFactV)>>15); //Lerp(fiStrengthX1,fiStrengthX2,fiFactV); + + GFXColor *pcolSrc = (GFXColor*)pulTexDst; + GFXColor *pcolDst = (GFXColor*)ulSrc; + pcolSrc->r = (BYTE)( (ULONG)pcolSrc->r + ((((ULONG)pcolDst->r - (ULONG)pcolSrc->r) * xStrength)>>16)); + pcolSrc->g = (BYTE)( (ULONG)pcolSrc->g + ((((ULONG)pcolDst->g - (ULONG)pcolSrc->g) * xStrength)>>16)); + pcolSrc->b = (BYTE)( (ULONG)pcolSrc->b + ((((ULONG)pcolDst->b - (ULONG)pcolSrc->b) * xStrength)>>16)); + pcolSrc->a = 255; + + pulTexDst++; + xMaskHPos += xHMaskStep; + } + xMaskVPos += xVMaskStep; + } + } + // make mipmaps + MakeMipmaps(32, ptdDest->td_pulFrames, ptdDest->GetWidth(), ptdDest->GetHeight()); + // force topmap upload + ptdDest->SetAsCurrent(0,TRUE); +} +#else +void CTerrain::GenerateTopMap(INDEX iTileIndex) +{ + INDEX iMaskDiv = 1; + INDEX iFirstInMask = 0; + INDEX iMaskWidth = tr_pixHeightMapWidth; + INDEX iTiling = (INDEX)(tr_ctTilesX*tr_ctQuadsInTileRow*tr_fTexStretch); + + // destionation texture (must have set required width and height) + CTextureData *ptdDest; + // if global top map + if(iTileIndex==(-1)) { + ptdDest = &tr_tdTopMap; + // else tile top map + } else { + CTerrainTile &tt = tr_attTiles[iTileIndex]; + ptdDest = &tt.GetTopMap(); + iMaskDiv = tr_ctTilesX; + iFirstInMask = iMaskWidth * tt.tt_iOffsetZ * (tr_ctVerticesInTileRow-1) + (tt.tt_iOffsetX * (tr_ctVerticesInTileRow-1)); + iTiling = (INDEX)(tr_ctQuadsInTileRow*tr_fTexStretch); + } + + ASSERT(ptdDest->GetPixWidth()>0 && ptdDest->GetPixHeight()>0 && ptdDest->GetPixWidth()==ptdDest->GetPixHeight()); + + INDEX iSrcMipWidth = ptdDest->GetWidth()/iTiling; + + INDEX ctLayers = tr_atlLayers.Count(); + // for each layer + for(INDEX ilr=0;ilrGetPixWidth()/iSrcMipWidth); + // get address of first byte in source mipmap + INDEX iMipAdr = GetMipmapOffset(imm,ptdSrc->GetPixWidth(),ptdSrc->GetPixHeight()); + + // Mask thing + // get first byte in layer mask + UBYTE *ubFirstInMask = &tl.tl_aubColors[iFirstInMask]; + FLOAT fHMaskStep = FLOAT(iMaskWidth-1)/(ptdDest->GetWidth()-1)/iMaskDiv; + FLOAT fVMaskStep = FLOAT(iMaskWidth-1)/(ptdDest->GetWidth()-1)/iMaskDiv; + FLOAT fMaskVPos=0; + + // get first byte in destination texture + ULONG *pulTexDst = (ULONG*)&ptdDest->td_pulFrames[0]; + // get first byte in source texture + ULONG *pulFirstInMipSrc = &ptdSrc->td_pulFrames[iMipAdr]; + + // for each row + for(UINT ir=0;irGetWidth();ir++) { + // get first byte for src mip texture in this row + ULONG *pulSrcRow = &pulFirstInMipSrc[(ir&(iSrcMipWidth-1))*iSrcMipWidth];//% + INDEX iMaskVPos = (INDEX)fMaskVPos * (iMaskWidth); + UBYTE *pubMaskRow = &ubFirstInMask[iMaskVPos]; + FLOAT fMaskHPos = 0; + // for each column + for(UINT ic=0;icGetWidth();ic++) { + + ULONG *ulSrc = &pulSrcRow[ic&(iSrcMipWidth-1)]; + INDEX iMask = (INDEX)fMaskHPos; + FLOAT f1 = NormByteToFloat(pubMaskRow[iMask]); + FLOAT f2 = NormByteToFloat(pubMaskRow[iMask+1]); + FLOAT f3 = NormByteToFloat(pubMaskRow[iMask+iMaskWidth+0]); + FLOAT f4 = NormByteToFloat(pubMaskRow[iMask+iMaskWidth+1]); + FLOAT fStrengthX1 = Lerp(f1,f2,fMaskHPos-(INDEX)fMaskHPos); + FLOAT fStrengthX2 = Lerp(f3,f4,fMaskHPos-(INDEX)fMaskHPos); + FLOAT fStrength = Lerp(fStrengthX1,fStrengthX2,fMaskVPos-(INDEX)fMaskVPos); + + CopyPixel(pulTexDst,ulSrc,fStrength); + pulTexDst++; + fMaskHPos+=fHMaskStep; + } + fMaskVPos+=fVMaskStep; + } + } + // make mipmaps + MakeMipmaps( 32, ptdDest->td_pulFrames, ptdDest->GetWidth(), ptdDest->GetHeight()); + // force topmap upload + ptdDest->SetAsCurrent(0,TRUE); +} +#endif +*/ + +void CTerrain::GenerateTerrainTopMap() +{ + CreateTopMap(tr_tdTopMap,tr_pixTopMapWidth,tr_pixTopMapHeight); + UpdateTopMap(-1); +} + +// Add default layer +void CTerrain::AddDefaultLayer_t(void) +{ + // Add one layer using default texture, but do not refresh terrain + CTerrainLayer &tl = AddLayer_t((CTString)"Textures\\Editor\\Default.TEX", LT_NORMAL, FALSE); + // fill this layer + tl.ResetLayerMask(255); +} + +// Build quadtree for terrain +void CTerrain::BuildQuadTree(void) +{ + INDEX ctQuadNodeRows = tr_ctTilesX; + INDEX ctQuadNodeCols = tr_ctTilesY; + INDEX ctQuadNodes = 0; + + // Create quad tree levels + while(TRUE) { + QuadTreeLevel &qtl = tr_aqtlQuadTreeLevels.Push(); + // Remember first node + qtl.qtl_iFirstNode = ctQuadNodes; + // Add nodes in this level to total node count + ctQuadNodes += ClampDn(ctQuadNodeRows,(INDEX)1) * ClampDn(ctQuadNodeCols,(INDEX)1); + + // Count nodes in this level + qtl.qtl_ctNodes = ctQuadNodes - qtl.qtl_iFirstNode; + qtl.qtl_ctNodesCol = ctQuadNodeCols; + qtl.qtl_ctNodesRow = ctQuadNodeRows; + + // if only one node is in this level + if(qtl.qtl_ctNodes == 1) { + // this is last level so exit loop + break; + } + if(ctQuadNodeCols%2 == 1 && ctQuadNodeCols != 1) { + ctQuadNodeCols = (ctQuadNodeCols+1)>>1; + } else { + ctQuadNodeCols = ctQuadNodeCols>>1; + } + + if(ctQuadNodeRows%2 == 1 && ctQuadNodeRows != 1) { + ctQuadNodeRows = (ctQuadNodeRows+1)>>1; + } else { + ctQuadNodeRows = ctQuadNodeRows>>1; + } + } + + QuadTreeLevel &qtlFirst = tr_aqtlQuadTreeLevels[0]; + // Add quadtree nodes for first level + tr_aqtnQuadTreeNodes.Push(qtlFirst.qtl_ctNodes); + // for each quad tree node in first level + for(INDEX iqn=0;iqnqtn_aabbox; + qtn.qtn_iChild[0] = iqt; + qtn.qtn_iChild[1] = -1; + qtn.qtn_iChild[2] = -1; + qtn.qtn_iChild[3] = -1; + qtn.qtn_iTileIndex = -1; + // If second child node exists + if(ic+1 _avLerpedVerices; +static void ShowTerrainInfo(CAnyProjection3D &apr, CDrawPort *pdp, CTerrain *ptrTerrain) +{ + pdp->SetFont( _pfdConsoleFont); + pdp->SetTextAspect( 1.0f); + pdp->SetOrtho(); + CTString strInfo; + INDEX ctTopMaps = ptrTerrain->tr_atdTopMaps.Count() + 1; + strInfo.PrintF("Tris = %d\nNodes = %d\nDelayed nodes = %d\nTop maps = %d\nTexgens = %d, %d\nShadowmap updates = %d\n", + _ctTris,_ctNodesVis,_ctDelayedNodes,ctTopMaps,ctGeneratedTopMaps,ctGlobalTopMaps,_ctShadowMapUpdates); + + CStaticStackArray iaLodInfo; + iaLodInfo.Push(ptrTerrain->tr_iMaxTileLod+1); + memset(&iaLodInfo[0],0,sizeof(INDEX)*iaLodInfo.sa_Count); + // build lod info + for(INDEX it=0;ittr_ctTiles;it++) { + CTerrainTile &tt = ptrTerrain->tr_attTiles[it]; + INDEX &ili = iaLodInfo[tt.tt_iLod]; + ili++; + } + // Show how many tiles are in witch lod + CTString strTemp = "LodInfo:\n"; + for(INDEX itti=0;ittitr_iMaxTileLod+1;itti++) { + CTString str; + CArrayHolder &ah = ptrTerrain->tr_aArrayHolders[itti]; + str.PrintF("L%d = mem = %d KB, nodes = %d\n",itti, ah.GetUsedMemory()/1024, iaLodInfo[itti]); + strTemp += str; + } + strTemp += "\n"; + strInfo +=strTemp; + + // Show memory usage + SLONG slUsedMemory=0; + // Height map usage + SLONG slHeightMap = ptrTerrain->tr_pixHeightMapWidth*ptrTerrain->tr_pixHeightMapHeight*sizeof(UWORD); + // Edge map usage + SLONG slEdgeMap = ptrTerrain->tr_pixHeightMapWidth*ptrTerrain->tr_pixHeightMapHeight*sizeof(UBYTE); + // Shadow map usage + SLONG slShadowMap = ptrTerrain->tr_tdShadowMap.GetUsedMemory(); + // Quad tree usage + SLONG slQTNodes = sizeof(QuadTreeNode)*ptrTerrain->tr_aqtnQuadTreeNodes.Count(); + SLONG slQTLevels = sizeof(QuadTreeLevel)*ptrTerrain->tr_aqtlQuadTreeLevels.Count(); + // Tiles usage + SLONG slTiles = 0; + INDEX cttt = ptrTerrain->tr_ctTiles; + for(INDEX itt=0;itttr_attTiles[itt]; + slTiles+=tt.GetUsedMemory(); + } + // Arrays holders usage + SLONG slArrayHoldes=0; + INDEX ctah=ptrTerrain->tr_aArrayHolders.Count(); + for(INDEX iah=0;iahtr_aArrayHolders[iah]; + slArrayHoldes+=ah.GetUsedMemory(); + } + SLONG slLayers=0; + // Terrain layers usage + INDEX cttl = ptrTerrain->tr_atlLayers.Count(); + for(INDEX itl=0;itltr_atlLayers[itl]; + slLayers+=tl.GetUsedMemory(); + } + SLONG slTopMaps=0; + // Top maps usage + INDEX cttm=ptrTerrain->tr_atdTopMaps.Count(); + for(INDEX itm=0;itmtr_atdTopMaps[itm]; + slTopMaps+=ptdTopMap->GetUsedMemory(); + } + SLONG slGlobalTopMap = ptrTerrain->tr_tdTopMap.GetUsedMemory(); + SLONG slTileBatchingSize = GetUsedMemoryForTileBatching(); + SLONG slVertexSmoothing = _avLerpedVerices.sa_Count * sizeof(GFXVertex4); + extern SLONG _slSharedTopMapSize; // Shared top map size + // Global top map usage + SLONG slTotal = slHeightMap+slEdgeMap+slShadowMap+slQTNodes+slQTLevels+slTiles+slArrayHoldes+slLayers+ + slTopMaps+slGlobalTopMap+slTileBatchingSize+slVertexSmoothing; + CTString strMemoryUsed; + strMemoryUsed.PrintF("Heightmap = %d KB\nEdgemap = %d KB\nShadowMap = %d KB\nQuadTree = %d KB\nTiles = %d KB\nArrays = %d KB\nLayers = %d KB\nTopMaps = %d KB\nGlobal TM = %d KB\nShared TM = %d KB\nVtx lerp = %d KB\nBatching = %d KB\nTotal = %d KB\n", + slHeightMap/1024,slEdgeMap/1024,slShadowMap/1024,(slQTNodes+slQTLevels)/1024,slTiles/1024,slArrayHoldes/1024,slLayers/1024,slTopMaps/1024,slGlobalTopMap/1024,_slSharedTopMapSize/1024,slVertexSmoothing/1024,slTileBatchingSize/1024,slTotal/1024); + + + strInfo += strMemoryUsed; + + extern FLOAT3D _vDirection; + strInfo += CTString(0,"Shadow map size = %d,%d [%d]\nShading map size= %d,%d [%d]\n", + ptrTerrain->GetShadowMapWidth(), ptrTerrain->GetShadowMapHeight(), + ptrTerrain->tr_iShadowMapSizeAspect,ptrTerrain->GetShadingMapWidth(), + ptrTerrain->GetShadingMapHeight(),ptrTerrain->tr_iShadingMapSizeAspect); + pdp->PutText(strInfo,0,40); +} + + + + + + + +static void ReadOldShadowMap(CTerrain *ptrTerrain, CTStream *istrFile) +{ + // Read terrain shadow map + // Read shadow map size + INDEX pixShadowMapWidth; + INDEX pixShadowMapHeight; + (*istrFile)>>pixShadowMapWidth; + (*istrFile)>>pixShadowMapHeight; + BOOL bHaveShadowMap; + (*istrFile)>>bHaveShadowMap; + // is shadow map saved + if(bHaveShadowMap) { + // skip reading of first mip of shadow map + istrFile->Seek_t(pixShadowMapWidth*pixShadowMapHeight*sizeof(GFXColor),CTStream::SD_CUR); + //istrFile->Read_t(&tr_tdShadowMap.td_pulFrames[0],tr_pixShadowMapWidth*tr_pixShadowMapHeight*sizeof(GFXColor)); + } + // Set default shadow map size + ptrTerrain->SetShadowMapsSize(0,0); +} + +void CTerrain::ReadVersion_t( CTStream *istrFile, INDEX iSavedVersion) +{ + // set current terrain + _ptrTerrain = this; + + ASSERT(_CrtCheckMemory()); + PIX pixWidth; + PIX pixHeight; + // read height map width and height + (*istrFile)>>pixWidth; + (*istrFile)>>pixHeight; + + // Reallocate memory for terrain with size + AllocateHeightMap(pixWidth,pixHeight); + + // read terrain stretch + (*istrFile)>>tr_vStretch; + // read texture stretch + if(iSavedVersion<6) { + FLOAT fTemp; // Read temp stretch + (*istrFile)>>fTemp; + } + // read lod distance factor + (*istrFile)>>tr_fDistFactor; + + if(iSavedVersion>6) { + // Read terrain size + (*istrFile)>>tr_vTerrainSize; + + istrFile->ExpectID_t("TRSM"); // 'Terrain shadowmap' + + // if version is smaller than 8 + if(iSavedVersion<8) { + // read old shadow map format + ReadOldShadowMap(this,istrFile); + } else { + INDEX iShadowMapAspect; + INDEX iShadingMapAspect; + (*istrFile)>>iShadowMapAspect; + (*istrFile)>>iShadingMapAspect; + SetShadowMapsSize(iShadowMapAspect,iShadingMapAspect); + INDEX iShadowMapSize = GetShadowMapWidth() * GetShadowMapHeight() * sizeof(ULONG); + INDEX iShadingMapSize = GetShadingMapWidth() * GetShadingMapHeight() * sizeof(UWORD); + // Read shadow map + ASSERT(tr_tdShadowMap.td_pulFrames!=NULL); + istrFile->Read_t(&tr_tdShadowMap.td_pulFrames[0],iShadowMapSize); + // Read shading map + ASSERT(tr_auwShadingMap!=NULL); + istrFile->Read_t(&tr_auwShadingMap[0],iShadingMapSize); + } + + // Create shadow map mipmaps + INDEX ctMipMaps = GetNoOfMipmaps(GetShadowMapWidth(),GetShadowMapHeight()); + MakeMipmaps(ctMipMaps, tr_tdShadowMap.td_pulFrames, GetShadowMapWidth(), GetShadowMapHeight()); + // Upload shadow map + tr_tdShadowMap.SetAsCurrent(0,TRUE); + + istrFile->ExpectID_t("TSEN"); // 'Terrain shadowmap end' + + + // if there is edge map saved + if(istrFile->PeekID_t()==CChunkID("TREM")) { // 'Terrain edge map' + // Read terrain edge map + istrFile->ExpectID_t("TREM"); // 'Terrain edge map' + // read edge map + istrFile->Read_t(&tr_aubEdgeMap[0],tr_pixHeightMapWidth*tr_pixHeightMapHeight); + istrFile->ExpectID_t("TEEN"); // 'Terrain edge map end' + } + } + + (*istrFile).ExpectID_t("TRHM"); // 'Terrain heightmap' + + // read height map + (*istrFile).Read_t(&tr_auwHeightMap[0],sizeof(UWORD)*tr_pixHeightMapWidth*tr_pixHeightMapHeight); + (*istrFile).ExpectID_t("THEN"); // 'Terrain heightmap end' + + // Terrain will be rebuild in entity.cpp + _ptrTerrain = NULL; +} + +// Read from stream. +void CTerrain::Read_t( CTStream *istrFile) +{ + (*istrFile).ExpectID_t("TERR"); // 'Terrain' + // read the version number + INDEX iSavedVersion; + (*istrFile)>>iSavedVersion; + // is this version 6 + if(iSavedVersion>4) { + ReadVersion_t(istrFile,iSavedVersion); + // else unknown version + } else { + // report error + ThrowF_t( TRANS("The terrain version on disk is %d.\n" + "Current supported version is %d."), iSavedVersion, _iTerrainVersion); + } + + // Read Terrain layers + (*istrFile).ExpectID_t("TRLR"); // 'Terrain layers' + // Read terrain layers + INDEX cttl; + (*istrFile)>>cttl; + // Create layers + tr_atlLayers.Push(cttl); + // for each terrain layer + for(INDEX itl=0;itlWriteID_t("TRSM"); // 'Terrain shadowmap' + + (*ostrFile)<Write_t(&tr_tdShadowMap.td_pulFrames[0],iShadowMapSize); + // Write shading map + ASSERT(tr_auwShadingMap!=NULL); + ostrFile->Write_t(&tr_auwShadingMap[0],iShadingMapSize); + + ostrFile->WriteID_t("TSEN"); // 'Terrain shadowmap end' + + // if edge map exists + if(tr_aubEdgeMap!=NULL) { + ostrFile->WriteID_t("TREM"); // 'Terrain edge map' + // Write edge map + ostrFile->Write_t(&tr_aubEdgeMap[0],sizeof(UBYTE)*tr_pixHeightMapWidth*tr_pixHeightMapHeight); + ostrFile->WriteID_t("TEEN"); // 'Terrain edge map end' + } + + (*ostrFile).WriteID_t("TRHM"); // 'Terrain heightmap' + // write height map + (*ostrFile).Write_t(&tr_auwHeightMap[0],sizeof(UWORD)*tr_pixHeightMapWidth*tr_pixHeightMapHeight); + (*ostrFile).WriteID_t("THEN"); // 'Terrain heightmap end' + + (*ostrFile).WriteID_t("TRLR"); // 'Terrain layers' + // write terrain layers + INDEX cttl = tr_atlLayers.Count(); + (*ostrFile)<si_penEntity->en_ulFlags &= ~ENF_VALIDSHADINGINFO; + itsi->si_lnInPolygon.Remove(); + itsi->si_pbpoPolygon = NULL; + } +} + +// Clear height map +void CTerrain::ClearHeightMap(void) +{ + // if height map space was allocated + if(tr_auwHeightMap!=NULL) { + // release it + FreeMemory(tr_auwHeightMap); + tr_auwHeightMap = NULL; + } +} + +// Clear shadow map +void CTerrain::ClearShadowMap(void) +{ + // Clear current terrain shadow map + tr_tdShadowMap.Clear(); + + // Also clear shading map + if(tr_auwShadingMap!=NULL) { + FreeMemory(tr_auwShadingMap); + tr_auwShadingMap = NULL; + } +} + +void CTerrain::ClearEdgeMap(void) +{ + // if space for edge map was allocated + if(tr_aubEdgeMap!=NULL) { + // release it + FreeMemory(tr_aubEdgeMap); + tr_aubEdgeMap = NULL; + } +} + +// Clear all topmaps +void CTerrain::ClearTopMaps(void) +{ + // for each topmap in terrain + INDEX cttm = tr_atdTopMaps.Count(); + for(INDEX itm=0;itmtd_pulFrames = NULL; + // Clear tile topmap + ptdTopMap->Clear(); + // remove topmap from container + tr_atdTopMaps.Remove(ptdTopMap); + delete ptdTopMap; + ptdTopMap = NULL; + } + tr_atdTopMaps.Clear(); + ASSERT(_CrtCheckMemory()); + + // Remove memory pointer from global top map cos it is shared memory + tr_tdTopMap.td_pulFrames = NULL; + // Clear global topmap + tr_tdTopMap.Clear(); +} + +// Clear tiles +void CTerrain::ClearTiles(void) +{ + // for each tile + for(INDEX itt=0;ittRelease(tr_ptdDetailMap); + tr_ptdDetailMap = NULL; + } +} + + diff --git a/Sources/Engine/Terrain/Terrain.h b/Sources/Engine/Terrain/Terrain.h new file mode 100644 index 0000000..8abe55c --- /dev/null +++ b/Sources/Engine/Terrain/Terrain.h @@ -0,0 +1,269 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TERRAIN_H +#define SE_INCL_TERRAIN_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TR_REGENERATE (1UL<<0) // terrain needs to be regenerated +#define TR_REGENERATE_TOP_MAP (1UL<<1) // regenerate terrain top map +#define TR_ALLOW_TOP_MAP_REGEN (1UL<<2) // allow top map regen (top map is not regenerate if this flag is not set) +#define TR_REBUILD_QUADTREE (1UL<<3) // rebuild higher levels of quad tree nodes (last levels are rebuild by tile flags) +#define TR_UPDATE_SHADOWMAP (1UL<<4) // update terrain shadow map (NOT USED!) +#define TR_ALLOW_SHADOW_MAP_UPDATE (1UL<<5) // allow terrain shadow map update (NOT USED!) +#define TR_SHOW_SELECTION (1UL<<6) // show selection +#define TR_HAS_FOG (1UL<<7) // terrain has fog +#define TR_HAS_HAZE (1UL<<8) // terrain has haze + +struct QuadTreeNode +{ + FLOATaabbox3D qtn_aabbox; // Bounding box for this quadtree node + INDEX qtn_iTileIndex;// Index of tile that this node represents + INDEX qtn_iChild[4]; // Indices of children for this quadtree node +}; + +struct QuadTreeLevel +{ + INDEX qtl_iFirstNode; // Index of first quadtree node in this level + INDEX qtl_ctNodes; // Count of nodes in this level + INDEX qtl_ctNodesCol; // Count of nodes in col + INDEX qtl_ctNodesRow; // Count of nodes in row +}; + +struct Point { + Point() {} + ~Point() {} + Point(const Point &ptOther) { + *this = ptOther; + } + INDEX pt_iX; + INDEX pt_iY; +}; + +struct Rect { + Rect() {} + ~Rect() {} + Rect(const Rect &rcOther) { + *this = rcOther; + } + Rect(INDEX iLeft, INDEX iTop, INDEX iRight, INDEX iBottom) { + rc_iLeft = iLeft; + rc_iTop = iTop; + rc_iRight = iRight; + rc_iBottom = iBottom; + } + INDEX Width() {return rc_iRight-rc_iLeft;} + INDEX Height() {return rc_iBottom-rc_iTop;} + INDEX rc_iLeft; + INDEX rc_iRight; + INDEX rc_iTop; + INDEX rc_iBottom; +}; + +class ENGINE_API CTerrain : public CBrushBase +{ +public: + CTerrain(); + ~CTerrain(); + + // Render terrain tiles + void Render(CAnyProjection3D &apr, CDrawPort *pdp); + // Render terrain tiles in wireframe + void RenderWireFrame(CAnyProjection3D &apr, CDrawPort *pdp, COLOR &colEdges); + + // Create empty terrain with given size + void CreateEmptyTerrain_t(PIX pixWidth,PIX pixHeight); + // Import height map from targa file + void ImportHeightMap_t(CTFileName fnHeightMap, BOOL bUse16b = TRUE); + // Export height map to targa file + void ExportHeightMap_t(CTFileName fnHeightMap, BOOL bUse16b = TRUE); + // Rebuild all terrain + void ReBuildTerrain(BOOL bDelayTileRegen=FALSE); + // Refresh terrain + void RefreshTerrain(void); + + // Set height map size + void AllocateHeightMap(PIX pixWidth, PIX pixHeight); + // Change height map size + void ReAllocateHeightMap(PIX pixWidth, PIX pixHeight); + // Set terrain size + void SetTerrainSize(FLOAT3D vSize); + // Set shadow map size aspect (relative to height map size) and shading map aspect (relative to shadow map size) + void SetShadowMapsSize(INDEX iShadowMapAspect, INDEX iShadingMapAspect); + + // Set size of top map texture + void SetGlobalTopMapSize(PIX pixTopMapSize); + // Set size of top map texture for tiles in lower lods + void SetTileTopMapSize(PIX pixLodTopMapSize); + // Set lod distance factor + void SetLodDistanceFactor(FLOAT fLodDistance); + + // Get shadow map size + PIX GetShadowMapWidth(void); + PIX GetShadowMapHeight(void); + // Get shading map size + PIX GetShadingMapWidth(void); + PIX GetShadingMapHeight(void); + + // Get reference to layer + CTerrainLayer &GetLayer(INDEX iLayer); + // Add new layer + CTerrainLayer &AddLayer_t(CTFileName fnTexture, LayerType ltType = LT_NORMAL, BOOL bUpdateTerrain=TRUE); + // Remove one layer + void RemoveLayer(INDEX iLayer, BOOL bUpdateTerrain=TRUE); + // Move layer to new position + INDEX SetLayerIndex(INDEX iLayer,INDEX iNewIndex, BOOL bUpdateTerrain=TRUE); + + // Add tile to reqen queue + void AddTileToRegenQueue(INDEX iTileIndex); + // Add all tiles to regen queue + void AddAllTilesToRegenQueue(void); + // Clear current regen list + void ClearRegenList(void); + + // Update shadow map + void UpdateShadowMap(FLOATaabbox3D *pbboxUpdate=NULL, BOOL bAbsoluteSpace=FALSE); + // Update top map + void UpdateTopMap(INDEX iTileIndex, Rect *prcDest = NULL); + + // Terrain flags handling + inline ULONG &GetFlags(void) { return tr_ulTerrainFlags; } + inline void SetFlags(ULONG ulFlags) { tr_ulTerrainFlags = ulFlags; } + inline void AddFlag(ULONG ulFlag) { tr_ulTerrainFlags |= ulFlag; } + inline void RemoveFlag(ULONG ulFlag) { tr_ulTerrainFlags &= ~ulFlag; } + + // get first quad tree node bounding box (all tiles box) + void GetAllTerrainBBox(FLOATaabbox3D &bbox); + + INDEX GetBrushType(void) { return CBrushBase::BT_TERRAIN; } // this is terrain not brush + + // Get shading color from tex coords in shading map + COLOR GetShadeColor(CShadingInfo *psi); + // Get plane from given point + FLOATplane3D GetPlaneFromPoint(FLOAT3D &vAbsPoint); + + + // Sets number of quads in row of one tile + void SetQuadsPerTileRow(INDEX ctQuadsPerTileRow); + inline INDEX GetQuadsPerTileRow(void) {return tr_ctQuadsInTileRow;} + inline INDEX GetVerticesPerTileRow(void) {return tr_ctVerticesInTileRow;} + + // Read from stream. + void ReadVersion_t( CTStream *istrFile, INDEX iSavedVersion); + // Read from stream. + void Read_t( CTStream *istrFile); // throw char * + // Write to stream. + void Write_t( CTStream *ostrFile); // throw char * + // Copy terrain data from other terrain + void Copy(CTerrain &trOther); + // Clean terrain data (does not remove layers) + void Clean(BOOL bCleanLayers=TRUE); + // Clean terrain data + void Clear(void); + + + // Renders visible terrain tiles in wireframe + void RenderWire(void); + // Render vertices of all terrain tiles + void RenderPoints(void); + // Generate terrain tiles + void ReGenerate(void); + // Build terrain data + void BuildTerrainData(void); + // Build quadtree for terrain + void BuildQuadTree(void); + // Update quadtree for terrain + void UpdateQuadTree(void); + // Generate terrain top map + void GenerateTerrainTopMap(void); + // Draws one quad node and its children + void DrawQuadNode(INDEX iqn); + // Set Terrain stretch + void SetTerrainStretch(FLOAT3D vStretch); + // Add default layer + void AddDefaultLayer_t(void); + + // Discard all cached shading info for models + void DiscardShadingInfos(void); + + // Clear height map + void ClearHeightMap(void); + // Clear shadow map + void ClearShadowMap(void); + // Clear edge map + void ClearEdgeMap(void); + // Clear all topmaps + void ClearTopMaps(void); + // Clear tiles + void ClearTiles(void); + // Clear arrays + void ClearArrays(void); + // Clear quadtree + void ClearQuadTree(void); + // Clear layers + void ClearLayers(void); + +public: + CListNode tr_lnInActiveTerrains; // for linking in list of active terrains in renderer + CListHead tr_lhShadingInfos; // for linking shading infos of entities + CEntity *tr_penEntity; // pointer to entity that holds this terrain + + INDEX tr_ctTiles; // Terrain tiles count + INDEX tr_ctTilesX; // Terrain tiles count in row + INDEX tr_ctTilesY; // Terrain tiles count in col + INDEX tr_iMaxTileLod; // Maximum lod in witch one tile can be + + FLOAT3D tr_vStretch; // Terrain stretch + FLOAT tr_fDistFactor; // Distance for lod switching + + CStaticStackArray tr_aqtnQuadTreeNodes; // Array of quadtree nodes + CStaticStackArray tr_aqtlQuadTreeLevels; // Array of quadtree levels + CStaticArray tr_attTiles; // Array of terrain tiles for terrain + CStaticArray tr_aArrayHolders; // Array of memory holders for each lod + CStaticStackArray tr_atlLayers; // Array of terrain layers + CDynamicContainer tr_atdTopMaps; // Array of top maps for each tile array (used by ArrayHolder) + CStaticStackArray tr_auiRegenList; // List of tiles that need to be regenerated + + /* Do not change any of this params directly */ + UWORD *tr_auwHeightMap; // Terrain height map + UWORD *tr_auwShadingMap; // Terrain shading map + UBYTE *tr_aubEdgeMap; // Terrain edge map + CTextureData tr_tdTopMap; // Terrain top map + CTextureData tr_tdShadowMap; // Terrain shadow map + CTextureData *tr_ptdDetailMap; // Terrain detail map + + PIX tr_pixHeightMapWidth; // Terrain height map widht + PIX tr_pixHeightMapHeight; // Terrain height map height + + PIX tr_pixTopMapWidth; // Width of terrain top map + PIX tr_pixTopMapHeight; // Height of terrain top map + PIX tr_pixFirstMipTopMapWidth; // Width of tile first mip top map + PIX tr_pixFirstMipTopMapHeight;// Height of tile first mip top map + + INDEX tr_iShadowMapSizeAspect; // Size of shadow map (relative to height map size) + INDEX tr_iShadingMapSizeAspect; // Size of shading map (relative to shadow map) + + INDEX tr_ctQuadsInTileRow; // Count of quads in one row in tile + INDEX tr_ctVerticesInTileRow; // Count of vertices in one row in tile + ULONG tr_ulTerrainFlags; // Terrain flags + FLOAT3D tr_vTerrainSize; // Terrain size in metars + + INDEX tr_iSelectedLayer; // Selected layer in we +private: + INDEX tr_ctDriverChanges; +}; + + + +#endif \ No newline at end of file diff --git a/Sources/Engine/Terrain/TerrainArchive.cpp b/Sources/Engine/Terrain/TerrainArchive.cpp new file mode 100644 index 0000000..1c924ad --- /dev/null +++ b/Sources/Engine/Terrain/TerrainArchive.cpp @@ -0,0 +1,62 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +template CDynamicArray; + +/* + * Read from stream. + */ +void CTerrainArchive::Read_t( CTStream *istrFile) // throw char * +{ + istrFile->ExpectID_t("TRAR"); // terrain archive + + INDEX ctTerrains; + // read number of terrains + (*istrFile)>>ctTerrains; + + // if there are some terrains + if (ctTerrains!=0) { + // create that much terrains + CTerrain *atrBrushes = ta_atrTerrains.New(ctTerrains); + // for each of the new terrains + for (INDEX iTerrain=0; iTerrainExpectID_t("EOTA"); // end of terrain archive +} + +/* + * Write to stream. + */ +void CTerrainArchive::Write_t( CTStream *ostrFile) // throw char * +{ + ostrFile->WriteID_t("TRAR"); // terrain archive + + // write the number of terrains + (*ostrFile)<Write_t(ostrFile); + } + + ostrFile->WriteID_t("EOTA"); // end of terrain archive +} diff --git a/Sources/Engine/Terrain/TerrainArchive.h b/Sources/Engine/Terrain/TerrainArchive.h new file mode 100644 index 0000000..80895b0 --- /dev/null +++ b/Sources/Engine/Terrain/TerrainArchive.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TERRAIN_ARCHIVE_H +#define SE_INCL_TERRAIN_ARCHIVE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include + +/* + * Terrain archive class -- a collection of terrains used by a level. + */ +class ENGINE_API CTerrainArchive : public CSerial { +public: + CDynamicArray ta_atrTerrains; // all the terrains in archive + CWorld *ta_pwoWorld; // the world + + // overrides from CSerial + /* Read/write to/from stream. */ + void Read_t( CTStream *istrFile); // throw char * + void Write_t( CTStream *ostrFile); // throw char * +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/Terrain/TerrainEditing.cpp b/Sources/Engine/Terrain/TerrainEditing.cpp new file mode 100644 index 0000000..0103552 --- /dev/null +++ b/Sources/Engine/Terrain/TerrainEditing.cpp @@ -0,0 +1,528 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include +#include +#include + +extern FLOAT3D _vViewerAbs; // Viewer pos +extern CStaticStackArray _aiExtColors; + + +// Selection preview +static CTerrain *_ptrSelectionTerrain; // Terrain that needs to show vertex selection +static CTextureData *_ptdSelectionBrush; // Brush that will be used for vertex selection preview +static GFXColor _colSelection; // Selection color +static Rect _rcSelectionExtract; // Rect of selection vertices that will be shown +static FLOAT _fSelectionStrenght; // Selection preview strenght +static SelectionFill _sfSelectionFill; // Type of fill for selection preview + + +static FLOATaabbox3D CalculateAABBoxFromRect(CTerrain *ptrTerrain, Rect rcExtract) +{ + ASSERT(ptrTerrain!=NULL); + ASSERT(ptrTerrain->tr_penEntity!=NULL); + + // Get entity that holds this terrain + CEntity *penEntity = ptrTerrain->tr_penEntity; + + FLOATaabbox3D bboxExtract; + FLOATaabbox3D bboxAllTerrain; + ptrTerrain->GetAllTerrainBBox(bboxAllTerrain); + + FLOAT fMinY = bboxAllTerrain.minvect(2); + FLOAT fMaxY = bboxAllTerrain.maxvect(2); + + bboxExtract.minvect = FLOAT3D(rcExtract.rc_iLeft * ptrTerrain->tr_vStretch(1),fMinY,rcExtract.rc_iTop * ptrTerrain->tr_vStretch(3)); + bboxExtract.maxvect = FLOAT3D(rcExtract.rc_iRight * ptrTerrain->tr_vStretch(1),fMaxY,rcExtract.rc_iBottom * ptrTerrain->tr_vStretch(3)); + return bboxExtract; +} + +// Find if there are any tiles in given rect that are not in lowest nor in highest lod without using TT_NO_LODING flag +static INDEX GetFirstTileInMidLod(CTerrain *ptrTerrain, Rect &rcExtract) +{ + FLOATaabbox3D bboxExtract = CalculateAABBoxFromRect(ptrTerrain,rcExtract); + // for each terrain tile + for(INDEX itt=0;itttr_ctTiles;itt++) { + QuadTreeNode &qtn = ptrTerrain->tr_aqtnQuadTreeNodes[itt]; + CTerrainTile &tt = ptrTerrain->tr_attTiles[itt]; + // if it is coliding with given box + if(qtn.qtn_aabbox.HasContactWith(bboxExtract)) { + // calculate its real distance factor + FLOAT fDistance = (qtn.qtn_aabbox.Center() - _vViewerAbs).Length(); + INDEX iRealLod = Clamp((INDEX)(fDistance/ptrTerrain->tr_fDistFactor),(INDEX)0,ptrTerrain->tr_iMaxTileLod); + if(iRealLod>0 && iRealLodtr_iMaxTileLod) { + // found one + return itt; + } + } + } + return -1; +} + +// Add given flags to all tiles in rect +static void AddFlagsToTilesInRect(CTerrain *ptrTerrain, Rect &rcExtract, ULONG ulFlags, BOOL bRegenerateTiles=FALSE) +{ + ASSERT(ptrTerrain!=NULL); + FLOATaabbox3D bboxExtract = CalculateAABBoxFromRect(ptrTerrain, rcExtract); + + // for each terrain tile + for(INDEX itt=0;itttr_ctTiles;itt++) { + QuadTreeNode &qtn = ptrTerrain->tr_aqtnQuadTreeNodes[itt]; + CTerrainTile &tt = ptrTerrain->tr_attTiles[itt]; + // if it is coliding with given box + if(qtn.qtn_aabbox.HasContactWith(bboxExtract)) { + // if tile must regenerate + if(bRegenerateTiles) { + // add tile to regen queue + ptrTerrain->AddTileToRegenQueue(itt); + } + // add given flags to tile + tt.AddFlag(ulFlags); + } + } +} + +// Update given rect of topmap +static void UpdateShadowMapRect(CTerrain *ptrTerrain, Rect &rcExtract) +{ + FLOATaabbox3D bboxExtract = CalculateAABBoxFromRect(ptrTerrain,rcExtract); + ptrTerrain->UpdateShadowMap(&bboxExtract); +} + +// Update terrain top map +static void UpdateTerrainGlobalTopMap(CTerrain *ptrTerrain, Rect &rcExtract) +{ + // if there aren't any tiles in + if(GetFirstTileInMidLod(ptrTerrain,rcExtract)==(-1)) { + // update gloabal terrain top map now + ptrTerrain->UpdateTopMap(-1); + // else + } else { + // gloabal terrain top map will be updated when first tile chage its lod + ptrTerrain->AddFlag(TR_REGENERATE_TOP_MAP); + } +} + +// +void ShowSelectionInternal(CTerrain *ptrTerrain, Rect &rcExtract, CTextureData *ptdBrush, GFXColor colSelection, FLOAT fStrenght, SelectionFill sfFill) +{ + ASSERT(ptrTerrain!=NULL); + ASSERT(ptdBrush!=NULL); + + Rect rcSelection; + FLOATaabbox3D bboxSelection; + // Clamp rect used for extraction + rcSelection.rc_iLeft = Clamp(rcExtract.rc_iLeft , 0L, ptrTerrain->tr_pixHeightMapWidth); + rcSelection.rc_iTop = Clamp(rcExtract.rc_iTop , 0L, ptrTerrain->tr_pixHeightMapHeight); + rcSelection.rc_iRight = Clamp(rcExtract.rc_iRight , 0L, ptrTerrain->tr_pixHeightMapWidth); + rcSelection.rc_iBottom = Clamp(rcExtract.rc_iBottom , 0L, ptrTerrain->tr_pixHeightMapHeight); + + // Prepare box for vertex selection + bboxSelection = FLOAT3D(rcSelection.rc_iLeft, 0, rcSelection.rc_iTop); + bboxSelection |= FLOAT3D(rcSelection.rc_iRight, 0, rcSelection.rc_iBottom); + + // Stretch selection box + bboxSelection.minvect(1) *= ptrTerrain->tr_vStretch(1); + bboxSelection.minvect(3) *= ptrTerrain->tr_vStretch(3); + bboxSelection.maxvect(1) *= ptrTerrain->tr_vStretch(1); + bboxSelection.maxvect(3) *= ptrTerrain->tr_vStretch(3); + + // Set selection box height + FLOATaabbox3D bboxAllTerrain; + ptrTerrain->GetAllTerrainBBox(bboxAllTerrain); + bboxSelection.minvect(2) = bboxAllTerrain.minvect(2); + bboxSelection.maxvect(2) = bboxAllTerrain.maxvect(2); + + GFXVertex *pavVertices; + INDEX *paiIndices; + INDEX ctVertices; + INDEX ctIndices; + + // Extract vertices in selection rect + ExtractVerticesInRect(ptrTerrain, rcSelection, &pavVertices, &paiIndices, ctVertices, ctIndices); + + if(ctVertices!=rcSelection.Width()*rcSelection.Height()) { + ASSERT(FALSE); + return; + } + + // if no vertices + if(ctVertices==0) { + return; + } + + // Prepare vertex colors for selection preview + PIX pixWidth = rcSelection.Width(); + PIX pixHeight = rcSelection.Height(); + INDEX iStepX = ptdBrush->GetWidth() - pixWidth; + INDEX iFirst = 0; + if(rcExtract.rc_iTop<0) { + iFirst += -rcExtract.rc_iTop*ptdBrush->GetWidth(); + } + if(rcExtract.rc_iLeft<0) { + iFirst += -rcExtract.rc_iLeft; + } + + _aiExtColors.Push(ctVertices); + GFXColor *pacolColor = (GFXColor*)&_aiExtColors[0]; + GFXColor *pacolBrush = (GFXColor*)&ptdBrush->td_pulFrames[iFirst]; + + // Fill vertex colors for selection preview + SLONG slStrength = Clamp(Abs(fStrenght),0.0f,1.0f) * 256.0f; + // for each row + for(INDEX iy=0;iyabgr = colSelection.abgr; + pacolColor->a = (pacolBrush->r*slStrength)>>8; + pacolColor++; + pacolBrush++; + } + pacolBrush+=iStepX; + } + + // Render selected polygons for selection preview + if(sfFill == SF_WIREFRAME) { + gfxPolygonMode(GFX_LINE); + gfxEnableDepthBias(); + } + + if(sfFill != SF_POINTS) { + // Draw selection + gfxDisableTexture(); + gfxDisableAlphaTest(); + gfxEnableBlend(); + gfxBlendFunc(GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + gfxSetVertexArray(pavVertices,ctVertices); + gfxSetColorArray(&_aiExtColors[0]); + gfxLockArrays(); + gfxDrawElements(ctIndices,paiIndices); + gfxUnlockArrays(); + gfxDisableBlend(); + } + + if(sfFill == SF_WIREFRAME) { + gfxDisableDepthBias(); + gfxPolygonMode(GFX_FILL); + } + + if(sfFill == SF_POINTS) { + DrawSelectedVertices(pavVertices,&_aiExtColors[0],ctVertices); + } +} + +void ShowSelectionInternal(CTerrain *ptrTerrain) +{ + // just in case + if(ptrTerrain!=_ptrSelectionTerrain) { + return; + } + + // Show selection + ShowSelectionInternal(ptrTerrain,_rcSelectionExtract,_ptdSelectionBrush,_colSelection,_fSelectionStrenght,_sfSelectionFill); +} + +void ShowSelection(CTerrain *ptrTerrain, Rect &rcExtract, CTextureData *ptdBrush, COLOR colSelection, FLOAT fStrenght, SelectionFill sfFill/*=SF_POLYGON*/) +{ + _ptrSelectionTerrain = ptrTerrain; + _ptdSelectionBrush = ptdBrush; + _colSelection = colSelection; + _rcSelectionExtract = rcExtract; + _fSelectionStrenght = fStrenght; + _sfSelectionFill = sfFill, + + // all tiles in rect must be in zero lod + AddFlagsToTilesInRect(ptrTerrain,rcExtract,TT_NO_LODING); + // Make sure selection is visible on next render + ptrTerrain->AddFlag(TR_SHOW_SELECTION); +} + +static void UpdateEditedTerrainTiles(CTerrain *ptrTerrain, Rect &rcExtract, BufferType btBufferType) +{ + // Update terrain tiles + if(btBufferType == BT_HEIGHT_MAP) { + AddFlagsToTilesInRect(ptrTerrain, rcExtract, TT_NO_LODING|TT_QUADTREENODE_REGEN, TRUE); + UpdateShadowMapRect(ptrTerrain, rcExtract); + + } else if(btBufferType == BT_LAYER_MASK) { + AddFlagsToTilesInRect(ptrTerrain, rcExtract, TT_NO_LODING|TT_FORCE_TOPMAP_REGEN, TRUE); + UpdateTerrainGlobalTopMap(ptrTerrain,rcExtract); + + } else if(btBufferType == BT_EDGE_MAP) { + AddFlagsToTilesInRect(ptrTerrain, rcExtract, TT_NO_LODING|TT_FORCE_TOPMAP_REGEN, TRUE); + UpdateTerrainGlobalTopMap(ptrTerrain,rcExtract); + + } else { + ASSERTALWAYS("Ilegal buffer type"); + return; + } +} + +UWORD *GetBufferForEditing(CTerrain *ptrTerrain, Rect &rcExtract, BufferType btBufferType, INDEX iBufferData/*=-1*/) +{ + ASSERT(ptrTerrain!=NULL); + ASSERT(rcExtract.Width()>0); + ASSERT(rcExtract.Height()>0); + + PIX pixLeft = rcExtract.rc_iLeft; + PIX pixRight = rcExtract.rc_iRight; + PIX pixTop = rcExtract.rc_iTop; + PIX pixBottom = rcExtract.rc_iBottom; + + PIX pixWidht = pixRight-pixLeft; + PIX pixHeight = pixBottom-pixTop; + PIX pixMaxWidth = ptrTerrain->tr_pixHeightMapWidth; + PIX pixMaxHeight = ptrTerrain->tr_pixHeightMapHeight; + + // allocate memory for editing buffer + UWORD *pauwEditingBuffer = (UWORD*)AllocMemory(pixWidht*pixHeight*sizeof(UWORD)); + + // Get pointer to first member in editing pointer + UWORD *puwBufferData = &pauwEditingBuffer[0]; + + // if buffer type is height map + if(btBufferType==BT_HEIGHT_MAP) { + // Extract data from terrain height map + UWORD *puwFirstInHeightMap = &ptrTerrain->tr_auwHeightMap[0]; + // for each row + for(PIX pixY=pixTop;pixYGetLayer(iBufferData); + UBYTE *pubFirstInLayer = &tl.tl_aubColors[0]; + // for each row + for(PIX pixY=pixTop;pixYtr_aubEdgeMap[0]; + // for each row + for(PIX pixY=pixTop;pixY0); + ASSERT(rcExtract.Height()>0); + + PIX pixLeft = rcExtract.rc_iLeft; + PIX pixRight = rcExtract.rc_iRight; + PIX pixTop = rcExtract.rc_iTop; + PIX pixBottom = rcExtract.rc_iBottom; + + PIX pixWidht = pixRight-pixLeft; + PIX pixHeight = pixBottom-pixTop; + PIX pixMaxWidth = ptrTerrain->tr_pixHeightMapWidth; + PIX pixMaxHeight = ptrTerrain->tr_pixHeightMapHeight; + + // Get pointer to first member in editing buffer + UWORD *puwBufferData = &puwEditedBuffer[0]; + + // if buffer type is height map + if(btBufferType==BT_HEIGHT_MAP) { + // put data from buffer to terrain height map + UWORD *puwFirstInHeightMap = &ptrTerrain->tr_auwHeightMap[0]; + // for each row + for(PIX pixY=pixTop;pixY=0 && pixY=0 && pixXGetLayer(iBufferData); + UBYTE *pubFirstInLayer = &tl.tl_aubColors[0]; + // for each row + for(PIX pixY=pixTop;pixY=0 && pixY=0 && pixX>8; + } + puwBufferData++; + } + // else pixY is not inside terrain rect + } else { + // increment buffer data pointer + puwBufferData+=pixRight-pixLeft; + } + } + } else if(btBufferType==BT_EDGE_MAP) { + // Extract data from edge map + UBYTE *pubFirstInEdgeMap = &ptrTerrain->tr_aubEdgeMap[0]; + // for each row + for(PIX pixY=pixTop;pixY=0 && pixY=0 && pixX=1) { + *pubMask = 255; + } else { + *pubMask = 0; + } + } + puwBufferData++; + } + // else pixY is not inside terrain rect + } else { + // increment buffer data pointer + puwBufferData+=pixRight-pixLeft; + } + } + } else { + ASSERTALWAYS("Ilegal buffer type"); + return; + } + + UpdateEditedTerrainTiles(ptrTerrain,rcExtract,btBufferType); +} + + + + + + + + + + + + + + + + + + + + + + + + + + + +// check whether a polygon is below given point, but not too far away +BOOL IsTerrainBelowPoint(CTerrain *ptrTerrain, const FLOAT3D &vPoint, FLOAT fMaxDist, const FLOAT3D &vGravityDir) +{ + return TRUE; +/* + // get distance from point to the plane + FLOAT fD = plPolygon.PointDistance(vPoint); + // if the point is behind the plane + if (fD<-0.01f) { + // it cannot be below + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + + // find distance of point from the polygon along gravity vector + FLOAT fDistance = -fD/fCos; + // if too far away + if (fDistance > fMaxDist) { + // it cannot be below + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + // project point to the polygon along gravity vector + FLOAT3D vProjected = vPoint + en_vGravityDir*fDistance; + + // find major axes of the polygon plane + INDEX iMajorAxis1, iMajorAxis2; + GetMajorAxesForPlane(plPolygon, iMajorAxis1, iMajorAxis2); + + // create an intersector + CIntersector isIntersector(vProjected(iMajorAxis1), vProjected(iMajorAxis2)); + // for all edges in the polygon + FOREACHINSTATICARRAY(pbpo->bpo_abpePolygonEdges, CBrushPolygonEdge, itbpePolygonEdge) { + // get edge vertices (edge direction is irrelevant here!) + const FLOAT3D &vVertex0 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + const FLOAT3D &vVertex1 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + // pass the edge to the intersector + isIntersector.AddEdge( + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2), + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2)); + } + + // if the point is inside polygon + if (isIntersector.IsIntersecting()) { + // it is below + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return TRUE; + // if the point is outside polygon + } else { + // it is not below + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ISSTANDINGONPOLYGON); + return FALSE; + } + */ +} diff --git a/Sources/Engine/Terrain/TerrainEditing.h b/Sources/Engine/Terrain/TerrainEditing.h new file mode 100644 index 0000000..71acc50 --- /dev/null +++ b/Sources/Engine/Terrain/TerrainEditing.h @@ -0,0 +1,45 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TERRAIN_EDITING_H +#define SE_INCL_TERRAIN_EDITING_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +enum EEditingTool { + ET_NONE = 0, + ET_HEIGHT_TOOL = 1, + ET_SMOTH_TOOL = 2, + ET_EQUALIZE = 3, + ET_ERASE = 4, + ET_FLATERN = 5, + ET_NOISE = 6, +}; + +enum BufferType { + BT_INVALID = 0, + BT_HEIGHT_MAP, + BT_LAYER_MASK, + BT_EDGE_MAP, +}; + +enum SelectionFill { + SF_POLYGON = 0, + SF_WIREFRAME, + SF_POINTS +}; +void ShowBrushSelection(void); + +ENGINE_API void EditTerrain(CTerrain *ptrTerrain, CTextureData *ptdBrush, FLOAT3D &vHitPoint, + COLOR colColor, FLOAT fStrength, EEditingTool etTool, INDEX iLayerIndex = -1); + +void ShowSelectionInternal(CTerrain *ptrTerrain); + +ENGINE_API UWORD *GetBufferForEditing(CTerrain *ptrTerrain, Rect &rcExtract, BufferType btBufferType, INDEX iBufferData=-1); +ENGINE_API void SetBufferForEditing(CTerrain *ptrTerrain, UWORD *puwEditedBuffer, Rect &rcExtract, BufferType btBufferType, INDEX iBufferData=-1); +ENGINE_API void ShowSelection(CTerrain *ptrTerrain, Rect &rcExtract, CTextureData *ptdBrush, COLOR colSelection, FLOAT fStrenght, SelectionFill sfFill=SF_POLYGON); + +#endif diff --git a/Sources/Engine/Terrain/TerrainLayer.cpp b/Sources/Engine/Terrain/TerrainLayer.cpp new file mode 100644 index 0000000..d50a1f1 --- /dev/null +++ b/Sources/Engine/Terrain/TerrainLayer.cpp @@ -0,0 +1,523 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include +#include +#include +#include +#include + +CTerrainLayer::CTerrainLayer() +{ + tl_ptdTexture = NULL; + tl_aubColors = NULL; + tl_iMaskWidth = 0; + tl_iMaskHeight = 0; + ResetLayerParams(); +} + +CTerrainLayer::~CTerrainLayer() +{ + Clear(); +} + +CTextureData *CTerrainLayer::GetThumbnail(INDEX iWidth, INDEX iHeight) +{ + tl_tdThumbNail.Clear(); + tl_tdThumbNail.DefaultAnimation(); + + INDEX iMaskWidth = tl_iMaskWidth-1; + INDEX iMaskHeight = tl_iMaskHeight-1; + + if(iWidth>iMaskWidth) { + // ASSERT(FALSE); + iWidth = iMaskWidth; + } + if(iHeight>iMaskHeight) { + // ASSERT(FALSE); + iHeight = iMaskHeight; + } + + CreateTexture(tl_tdThumbNail,iWidth,iHeight,TEX_STATIC); + + INDEX iStepX = iMaskWidth/iWidth; + INDEX iStepY = iMaskHeight/iHeight - 1; + + UBYTE *paubMask = tl_aubColors; + GFXColor *pcolTexture = (GFXColor*)tl_tdThumbNail.td_pulFrames; + + for(INDEX iy=0;iyr = *paubMask; + pcolTexture->g = *paubMask; + pcolTexture->b = *paubMask; + pcolTexture->a = 0xFF; + pcolTexture++; + paubMask+=iStepX; + } + paubMask+=(tl_iMaskWidth*iStepY)+1; + } + + // make mipmaps + INDEX ctMips = GetNoOfMipmaps(iWidth,iHeight); + MakeMipmaps(ctMips, tl_tdThumbNail.td_pulFrames, iWidth, iHeight); + + tl_tdThumbNail.SetAsCurrent(0,TRUE); + return &tl_tdThumbNail; +} + +// Set layer size +void CTerrainLayer::SetLayerSize(INDEX iTerrainWidth, INDEX iTerrainHeight) +{ + // if array of vertex colors was initialized + if(tl_aubColors!=NULL) { + // free array + FreeMemory(tl_aubColors); + tl_aubColors = NULL; + } + // if size of mask is greater than 0 + INDEX iSize = iTerrainWidth*iTerrainHeight; + if(iSize>0) { + // Allocate new memory for vertex colors + tl_aubColors = (UBYTE*)AllocMemory(iSize); + // Reset color values + memset(&tl_aubColors[0],0,sizeof(UBYTE)*iSize); + } + + tl_iMaskWidth = iTerrainWidth; + tl_iMaskHeight = iTerrainHeight; +} + +// Set base texture this layer will be using +void CTerrainLayer::SetLayerTexture_t(CTFileName fnTexture) +{ + // if layer has valid texture + if(tl_ptdTexture!=NULL) { + // release texture from stock + _pTextureStock->Release(tl_ptdTexture); + tl_ptdTexture = NULL; + } + // get reguested texture + tl_ptdTexture = _pTextureStock->Obtain_t(fnTexture); + tl_ptdTexture->Force(TEX_STATIC); + + // if this is tile layer + if(tl_ltType == LT_TILE) { + // Update tile widht and height + SetTilesPerRow(GetTilesPerRow()); + } +} + +// Set num of tiles in one row +void CTerrainLayer::SetTilesPerRow(INDEX ctTilesInRow) +{ + ASSERT(tl_ltType == LT_TILE); + tl_ctTilesInRow = ctTilesInRow; + // Calc one tile widht + tl_pixTileWidth = tl_ptdTexture->GetPixWidth() / ctTilesInRow; + // Calc num of tiles in texture col + tl_ctTilesInCol = tl_ptdTexture->GetPixHeight() / tl_pixTileWidth; + + tl_fTileU = 1.0f / tl_ctTilesInRow; + tl_fTileV = 1.0f / tl_ctTilesInCol; +} + +INDEX CTerrainLayer::GetTilesPerRow() +{ + ASSERT(tl_ltType == LT_TILE); + return tl_ctTilesInRow; +} + +// Import layer mask from targa file +void CTerrainLayer::ImportLayerMask_t(CTFileName fnLayerMask) +{ + // Load targa file + CImageInfo iiLayerMask; + iiLayerMask.LoadAnyGfxFormat_t(fnLayerMask); + if(iiLayerMask.ii_Width != tl_iMaskWidth) { + ThrowF_t(TRANS("Layer mask width is %d, but it must be same size as terrain width %d"),iiLayerMask.ii_Width,tl_iMaskWidth); + } + if(iiLayerMask.ii_Height != tl_iMaskHeight) { + ThrowF_t(TRANS("Layer mask height is %d, but it must be same size as terrain height %d"),iiLayerMask.ii_Height,tl_iMaskHeight); + } + + UBYTE *pubSrc = &iiLayerMask.ii_Picture[0]; + UBYTE *pubDst = &tl_aubColors[0]; + INDEX iBpp = iiLayerMask.ii_BitsPerPixel/8; + + // for each byte in loaded image + INDEX iMaskSize = tl_iMaskWidth * tl_iMaskHeight; + for(INDEX ib=0;ibabgr = 0x00000000; + pacolImage->r = *pubMask; + pacolImage++; + pubMask++; + } + iiHeightMap.SaveTGA_t(fnLayerMask); + iiHeightMap.Clear(); +} + +// Reset layer mask +void CTerrainLayer::ResetLayerMask(UBYTE ubMaskFill) +{ + memset(&tl_aubColors[0],ubMaskFill,sizeof(UBYTE) * tl_iMaskWidth * tl_iMaskHeight); +} + +// Reset layer params +void CTerrainLayer::ResetLayerParams() +{ + tl_iMaskWidth = 0; + tl_iMaskHeight = 0; + tl_strName = "NoName"; + tl_bVisible = TRUE; + + tl_colMultiply = C_GRAY|CT_OPAQUE; + tl_fSmoothness = 1.0f; + tl_ltType = LT_NORMAL; + + tl_fRotateX=0.0f; + tl_fRotateY=0.0f; + tl_fStretchX=1.0f; + tl_fStretchY=1.0f; + tl_fOffsetX=0; + tl_fOffsetY=0; + + tl_bAutoRegenerated=FALSE; + tl_fCoverage=1.0f; + tl_fCoverageNoise=0.5f; + tl_fCoverageRandom=0.0f; + + tl_bApplyMinAltitude=TRUE; + tl_fMinAltitude=0.0f; + tl_fMinAltitudeFade=0.25f; + tl_fMinAltitudeNoise=0.25f; + tl_fMinAltitudeRandom=0; + + tl_bApplyMaxAltitude=TRUE; + tl_fMaxAltitude=1.0f; + tl_fMaxAltitudeFade=0.25f; + tl_fMaxAltitudeNoise=0.25f; + tl_fMaxAltitudeRandom=0; + + tl_bApplyMinSlope=TRUE; + tl_fMinSlope=0.0f; + tl_fMinSlopeFade=0.25f; + tl_fMinSlopeNoise=0.25f; + tl_fMinSlopeRandom=0; + + tl_bApplyMaxSlope=TRUE; + tl_fMaxSlope=1.0f; + tl_fMaxSlopeFade=0.25f; + tl_fMaxSlopeNoise=0.25f; + tl_fMaxSlopeRandom=0; + + // Tile layer properties + tl_ctTilesInRow = 1; + tl_ctTilesInCol = 1; + tl_iSelectedTile = 0; + tl_pixTileWidth = 128; + tl_pixTileHeight = 128; + tl_fTileU = 1.0f; + tl_fTileV = 1.0f; +} + +void CTerrainLayer::operator=(const CTerrainLayer &tlOther) +{ + Copy(tlOther); +} + +// Copy terrain data from other terrain +void CTerrainLayer::Copy(const CTerrainLayer &tlOther) +{ + // clear current layer data + Clear(); + + // if texture exists + if(tlOther.tl_ptdTexture!=NULL) { + // Copy texture + SetLayerTexture_t(tlOther.tl_ptdTexture->GetName()); + } + + // Allocate memory for vertex colors + SetLayerSize(tlOther.tl_iMaskWidth,tlOther.tl_iMaskHeight); + // Copy vertex colors + memcpy(tl_aubColors,tlOther.tl_aubColors,sizeof(UBYTE) * tl_iMaskWidth * tl_iMaskHeight); + + // Copy reast of params + tl_strName = tlOther.tl_strName; + tl_bVisible = tlOther.tl_bVisible; + tl_colMultiply = tlOther.tl_colMultiply; + tl_fSmoothness = tlOther.tl_fSmoothness; + tl_ltType = tlOther.tl_ltType; + + tl_fRotateX = tlOther.tl_fRotateX; + tl_fRotateY = tlOther.tl_fRotateY; + tl_fStretchX = tlOther.tl_fStretchX; + tl_fStretchY = tlOther.tl_fStretchY; + tl_fOffsetX = tlOther.tl_fOffsetX; + tl_fOffsetY = tlOther.tl_fOffsetY; + + tl_bAutoRegenerated = tlOther.tl_bAutoRegenerated; + tl_fCoverage = tlOther.tl_fCoverage; + tl_fCoverageNoise = tlOther.tl_fCoverageNoise; + tl_fCoverageRandom = tlOther.tl_fCoverageRandom; + + tl_bApplyMinAltitude = tlOther.tl_bApplyMinAltitude; + tl_fMinAltitude = tlOther.tl_fMinAltitude; + tl_fMinAltitudeFade = tlOther.tl_fMinAltitudeFade; + tl_fMinAltitudeNoise = tlOther.tl_fMinAltitudeNoise; + tl_fMinAltitudeRandom = tlOther.tl_fMinAltitudeRandom; + + tl_bApplyMaxAltitude = tlOther.tl_bApplyMaxAltitude; + tl_fMaxAltitude = tlOther.tl_fMaxAltitude; + tl_fMaxAltitudeFade = tlOther.tl_fMaxAltitudeFade; + tl_fMaxAltitudeNoise = tlOther.tl_fMaxAltitudeNoise; + tl_fMaxAltitudeRandom = tlOther.tl_fMaxAltitudeRandom; + + tl_bApplyMinSlope = tlOther.tl_bApplyMinSlope; + tl_fMinSlope = tlOther.tl_fMinSlope; + tl_fMinSlopeFade = tlOther.tl_fMinSlopeFade; + tl_fMinSlopeNoise = tlOther.tl_fMinSlopeNoise; + tl_fMinSlopeRandom = tlOther.tl_fMinSlopeRandom; + + tl_bApplyMaxSlope = tlOther.tl_bApplyMaxSlope; + tl_fMaxSlope = tlOther.tl_fMaxSlope; + tl_fMaxSlopeFade = tlOther.tl_fMaxSlopeFade; + tl_fMaxSlopeNoise = tlOther.tl_fMaxSlopeNoise; + tl_fMaxSlopeRandom = tlOther.tl_fMaxSlopeRandom; + + // Tile layer properties + tl_ctTilesInRow = tlOther.tl_ctTilesInRow; + tl_ctTilesInCol = tlOther.tl_ctTilesInCol; + tl_iSelectedTile = tlOther.tl_iSelectedTile; + tl_pixTileWidth = tlOther.tl_pixTileWidth; + tl_pixTileHeight = tlOther.tl_pixTileHeight; + tl_fTileU = tlOther.tl_fTileU; + tl_fTileV = tlOther.tl_fTileV; +} + +// Read from stream. +void CTerrainLayer::Read_t(CTStream *istrFile,INDEX iSavedVersion) +{ + CTFileName fn; + INDEX iMaskWidth; + INDEX iMaskHeight; + + // Read terrain layer texture + (*istrFile).ExpectID_t("TLTX"); // 'Terrain layer texture' + (*istrFile)>>fn; + // Add texture to layer + SetLayerTexture_t(fn); + // Read terrain layer mask + (*istrFile).ExpectID_t("TLMA"); // 'Terrain layer mask' + (*istrFile)>>iMaskWidth; + (*istrFile)>>iMaskHeight; + // Set layer size + SetLayerSize(iMaskWidth,iMaskHeight); + (*istrFile).Read_t(&tl_aubColors[0],sizeof(UBYTE) * tl_iMaskWidth * tl_iMaskHeight); + + if(istrFile->PeekID_t()==CChunkID("TLPA")) { // 'Terrain edge map' + // Read terrain layer params + (*istrFile).ExpectID_t("TLPA"); // 'Terrain layer params' + + (*istrFile)>>tl_strName; + (*istrFile)>>tl_bVisible; + FLOAT fDummy; + (*istrFile)>>tl_fRotateX; + (*istrFile)>>tl_fRotateY; + (*istrFile)>>tl_fStretchX; + (*istrFile)>>tl_fStretchY; + (*istrFile)>>tl_fOffsetX; + (*istrFile)>>tl_fOffsetY; + (*istrFile)>>tl_bAutoRegenerated; + (*istrFile)>>tl_fCoverage; + (*istrFile)>>tl_fCoverageNoise; + (*istrFile)>>fDummy; + (*istrFile)>>fDummy; + (*istrFile)>>fDummy; + (*istrFile)>>fDummy; + (*istrFile)>>tl_fMinSlope; + (*istrFile)>>tl_fMaxSlope; + (*istrFile)>>fDummy; + (*istrFile)>>fDummy; + } else { + // Read terrain layer params + (*istrFile).ExpectID_t("TLPR"); // 'Terrain layer params' + + (*istrFile)>>tl_strName; + (*istrFile)>>tl_bVisible; + + (*istrFile)>>tl_fRotateX; + (*istrFile)>>tl_fRotateY; + (*istrFile)>>tl_fStretchX; + (*istrFile)>>tl_fStretchY; + (*istrFile)>>tl_fOffsetX; + (*istrFile)>>tl_fOffsetY; + + (*istrFile)>>tl_bAutoRegenerated; + (*istrFile)>>tl_fCoverage; + (*istrFile)>>tl_fCoverageNoise; + (*istrFile)>>tl_fCoverageRandom; + + (*istrFile)>>tl_bApplyMinAltitude; + (*istrFile)>>tl_fMinAltitude; + (*istrFile)>>tl_fMinAltitudeFade; + (*istrFile)>>tl_fMinAltitudeNoise; + (*istrFile)>>tl_fMinAltitudeRandom; + + (*istrFile)>>tl_bApplyMaxAltitude; + (*istrFile)>>tl_fMaxAltitude; + (*istrFile)>>tl_fMaxAltitudeFade; + (*istrFile)>>tl_fMaxAltitudeNoise; + (*istrFile)>>tl_fMaxAltitudeRandom; + + (*istrFile)>>tl_bApplyMinSlope; + (*istrFile)>>tl_fMinSlope; + (*istrFile)>>tl_fMinSlopeFade; + (*istrFile)>>tl_fMinSlopeNoise; + (*istrFile)>>tl_fMinSlopeRandom; + + (*istrFile)>>tl_bApplyMaxSlope; + (*istrFile)>>tl_fMaxSlope; + (*istrFile)>>tl_fMaxSlopeFade; + (*istrFile)>>tl_fMaxSlopeNoise; + (*istrFile)>>tl_fMaxSlopeRandom; + + if(iSavedVersion>=9) { + INDEX iType; + (*istrFile)>>tl_colMultiply; + (*istrFile)>>tl_fSmoothness; + (*istrFile)>>iType; + tl_ltType = (LayerType)iType; + + // Tile layer properties + (*istrFile)>>tl_ctTilesInRow; + (*istrFile)>>tl_ctTilesInCol; + (*istrFile)>>tl_iSelectedTile; + (*istrFile)>>tl_pixTileWidth; + (*istrFile)>>tl_pixTileHeight; + (*istrFile)>>tl_fTileU; + (*istrFile)>>tl_fTileV; + } + } +} + +// Write to stream. +void CTerrainLayer::Write_t( CTStream *ostrFile) +{ + (*ostrFile).WriteID_t("TLTX"); // 'Terrain layer texture' + const CTFileName &fn = tl_ptdTexture->GetName(); + (*ostrFile)<Release(tl_ptdTexture); + tl_ptdTexture = NULL; + } + + // Clear tumbnail texture + tl_tdThumbNail.Clear(); +} + +// Count used memory +SLONG CTerrainLayer::GetUsedMemory(void) +{ + SLONG slUsedMemory=0; + slUsedMemory += sizeof(CTerrainLayer); + slUsedMemory += sizeof(UBYTE)*tl_iMaskWidth*tl_iMaskHeight; + return slUsedMemory; +} diff --git a/Sources/Engine/Terrain/TerrainLayer.h b/Sources/Engine/Terrain/TerrainLayer.h new file mode 100644 index 0000000..eb27788 --- /dev/null +++ b/Sources/Engine/Terrain/TerrainLayer.h @@ -0,0 +1,121 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TERRAIN_LAYER_H +#define SE_INCL_TERRAIN_LAYER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +enum LayerType { + LT_NORMAL = 0, + LT_TILE, +}; + +#define TL_FLIPX_SHIFT 4 +#define TL_FLIPY_SHIFT 5 +#define TL_SWAPXY_SHIFT 6 +#define TL_VISIBLE_SHIFT 7 + +#define TL_TILE_INDEX 0x0F +#define TL_VISIBLE (1< +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Terrain raycasting and colision + */ + +extern CTerrain *_ptrTerrain; // Current terrain +static FLOAT3D _vHitLocation = FLOAT3D(-100,-100,-100); + +CStaticStackArray _avExtVertices; +CStaticStackArray _aiExtIndices; +CStaticStackArray _aiExtColors; +CStaticStackArray _aiHitTiles; + +static ULONG *_pulSharedTopMap = NULL; // Shared memory used for topmap regeneration +extern SLONG _slSharedTopMapSize = 0; // Size of shared memory allocated for topmap regeneration +extern INDEX _ctShadowMapUpdates; +#pragma message(">> Create class with destructor to clear shared topmap memory") + +FLOATaabbox3D _bboxDrawOne; +FLOATaabbox3D _bboxDrawTwo; + +#define NUMDIM 3 +#define RIGHT 0 +#define LEFT 1 +#define MIDDLE 2 + +// Test AABBox agains ray +static BOOL HitBoundingBox(FLOAT3D &vOrigin, FLOAT3D &vDir, FLOAT3D &vHit, FLOATaabbox3D &bbox) +{ + BOOL bInside = TRUE; + BOOL quadrant[NUMDIM]; + register int i; + int whichPlane; + + double maxT[NUMDIM]; + double candidatePlane[NUMDIM]; + double minB[NUMDIM], maxB[NUMDIM]; /*box */ + double origin[NUMDIM], dir[NUMDIM]; /*ray */ + double coord[NUMDIM]; /* hit point */ + + minB[0] = bbox.minvect(1); minB[1] = bbox.minvect(2); minB[2] = bbox.minvect(3); + maxB[0] = bbox.maxvect(1); maxB[1] = bbox.maxvect(2); maxB[2] = bbox.maxvect(3); + origin[0] = vOrigin(1); origin[1] = vOrigin(2); origin[2] = vOrigin(3); + dir[0] = vDir(1); dir[1] = vDir(2); dir[2] = vDir(3); + + /* Find candidate planes; this loop can be avoided if + rays cast all from the eye(assume perpsective view) */ + for (i=0; i maxB[i]) { + quadrant[i] = RIGHT; + candidatePlane[i] = maxB[i]; + bInside = FALSE; + } else { + quadrant[i] = MIDDLE; + } + } + + /* Ray origin inside bounding box */ + if(bInside) { + vHit = FLOAT3D(origin[0],origin[1],origin[2]); + return (TRUE); + } + + + /* Calculate T distances to candidate planes */ + for (i = 0; i < NUMDIM; i++) + if (quadrant[i] != MIDDLE && dir[i] !=0.) + maxT[i] = (candidatePlane[i]-origin[i]) / dir[i]; + else + maxT[i] = -1.; + + /* Get largest of the maxT's for final choice of intersection */ + whichPlane = 0; + for (i = 1; i < NUMDIM; i++) + if (maxT[whichPlane] < maxT[i]) + whichPlane = i; + + /* Check final candidate actually inside box */ + if (maxT[whichPlane] < 0.) return (FALSE); + for (i = 0; i < NUMDIM; i++) { + if (whichPlane != i) { + coord[i] = origin[i] + maxT[whichPlane] *dir[i]; + if (coord[i] < minB[i] || coord[i] > maxB[i]) { + return (FALSE); + } + } else { + coord[i] = candidatePlane[i]; + } + } + return (TRUE); /* ray hits box */ +} + + +// Test AABBox agains ray +static BOOL RayHitsAABBox(FLOAT3D &vOrigin, FLOAT3D &vDir, FLOAT3D &vHit, FLOATaabbox3D &bbox) +{ + FLOAT minB[3]; + FLOAT maxB[3]; + FLOAT origin[3]; + FLOAT dir[3]; + FLOAT coord[3]; + + + minB[0] = bbox.minvect(1); minB[1] = bbox.minvect(2); minB[2] = bbox.minvect(3); + maxB[0] = bbox.maxvect(1); maxB[1] = bbox.maxvect(2); maxB[2] = bbox.maxvect(3); + origin[0] = vOrigin(1); origin[1] = vOrigin(2); origin[2] = vOrigin(3); + dir[0] = vDir(1); dir[1] = vDir(2); dir[2] = vDir(3); + + char inside = TRUE; + char quadrant[3]; + register int i; + int whichPlane; + FLOAT maxT[3]; + FLOAT candidatePlane[3]; + + /* Find candidate planes; this loop can be avoided if + rays cast all from the eye(assume perpsective view) */ + for (i=0; i<3; i++) + if(origin[i] < minB[i]) { + quadrant[i] = LEFT; + candidatePlane[i] = minB[i]; + inside = FALSE; + }else if (origin[i] > maxB[i]) { + quadrant[i] = RIGHT; + candidatePlane[i] = maxB[i]; + inside = FALSE; + }else { + quadrant[i] = MIDDLE; + } + + /* Ray origin inside bounding box */ + if(inside) { + vHit = FLOAT3D(origin[0],origin[1],origin[2]); + return TRUE; + } + + + /* Calculate T distances to candidate planes */ + for (i = 0; i < 3; i++) { + if (quadrant[i] != MIDDLE && dir[i] !=0.) { + maxT[i] = (candidatePlane[i]-origin[i]) / dir[i]; + } else { + maxT[i] = -1.; + } + } + + /* Get largest of the maxT's for final choice of intersection */ + whichPlane = 0; + for (i = 1; i < 3; i++) + if (maxT[whichPlane] < maxT[i]) + whichPlane = i; + + /* Check final candidate actually inside box */ + if (maxT[whichPlane] < 0.) { + return FALSE; + } + for (i = 0; i < 3; i++) + if (whichPlane != i) { + coord[i] = origin[i] + maxT[whichPlane] *dir[i]; + if (coord[i] < minB[i] || coord[i] > maxB[i]) { + return FALSE; + } + } else { + coord[i] = candidatePlane[i]; + } + + // ray hits box + vHit = FLOAT3D(coord[0],coord[1],coord[2]); + return TRUE; +} + +// Get exact hit location in tile +FLOAT GetExactHitLocation(INDEX iTileIndex, FLOAT3D &vOrigin, FLOAT3D &vTarget, FLOAT3D &vHitLocation) +{ + CTerrainTile &tt = _ptrTerrain->tr_attTiles[iTileIndex]; + QuadTreeNode &qtn = _ptrTerrain->tr_aqtnQuadTreeNodes[iTileIndex]; + + GFXVertex *pavVertices; + INDEX *paiIndices; + INDEX ctVertices; + INDEX ctIndices; + + ExtractPolygonsInBox(_ptrTerrain,qtn.qtn_aabbox,&pavVertices,&paiIndices,ctVertices,ctIndices); + + + FLOAT fDummyDist = 100000;//(vTarget - vOrigin).Length() * 2; + FLOAT fDistance = fDummyDist; + + // for each triangle + for(INDEX iTri=0;iTri=0 && fDistance0>=fDistance1) { + // calculate fraction of line before intersection + FLOAT fFraction = fDistance0/(fDistance0-fDistance1); + // calculate intersection coordinate + FLOAT3D vHitPoint = vOrigin+(vTarget-vOrigin)*fFraction; + // calculate intersection distance + FLOAT fHitDistance = (vHitPoint-vOrigin).Length(); + // if the hit point can not be new closest candidate + if (fHitDistance>fDistance) { + // skip this triangle + continue; + } + + // find major axes of the polygon plane + INDEX iMajorAxis1, iMajorAxis2; + GetMajorAxesForPlane(plTriPlane, iMajorAxis1, iMajorAxis2); + + // create an intersector + CIntersector isIntersector(vHitPoint(iMajorAxis1), vHitPoint(iMajorAxis2)); + + // check intersections for all three edges of the polygon + isIntersector.AddEdge( + vx0(iMajorAxis1), vx0(iMajorAxis2), + vx1(iMajorAxis1), vx1(iMajorAxis2)); + isIntersector.AddEdge( + vx1(iMajorAxis1), vx1(iMajorAxis2), + vx2(iMajorAxis1), vx2(iMajorAxis2)); + isIntersector.AddEdge( + vx2(iMajorAxis1), vx2(iMajorAxis2), + vx0(iMajorAxis1), vx0(iMajorAxis2)); + + // if the polygon is intersected by the ray, and it is the closest intersection so far + if (isIntersector.IsIntersecting() && (fHitDistance < fDistance)) { + // remember hit coordinates + fDistance = fHitDistance; + vHitLocation = vHitPoint; + } + } + } + if(fDistance!=fDummyDist) { + _vHitLocation = vHitLocation; + return fDistance; + } else { + return -1; + } +} + +FLOAT3D _vHitBegin;// TEMP +FLOAT3D _vHitEnd; // TEMP +FLOAT3D _vDirection; // TEMP +FLOAT3D _vHitExact; // TEMP + +#pragma message(">> Remove Rect from ExtractPolygonsInBox") +// Extract polygons in given box and returns clipped rectangle +Rect ExtractPolygonsInBox(CTerrain *ptrTerrain, const FLOATaabbox3D &bboxExtract, GFXVertex4 **pavVtx, + INDEX **paiInd, INDEX &ctVtx,INDEX &ctInd,BOOL bFixSize/*=FALSE*/) +{ + ASSERT(ptrTerrain!=NULL); + + FLOATaabbox3D bbox = bboxExtract; + + bbox.minvect(1) /= ptrTerrain->tr_vStretch(1); + bbox.minvect(3) /= ptrTerrain->tr_vStretch(3); + bbox.maxvect(1) /= ptrTerrain->tr_vStretch(1); + bbox.maxvect(3) /= ptrTerrain->tr_vStretch(3); + + _avExtVertices.PopAll(); + _aiExtIndices.PopAll(); + _aiExtColors.PopAll(); + + Rect rc; + if(!bFixSize) { + // max vector of bbox in incremented for one, because first vertex is at 0,0,0 in world and in heightmap is at 1,1 + rc.rc_iLeft = Clamp((INDEX)(bbox.minvect(1)-0),(INDEX)0,ptrTerrain->tr_pixHeightMapWidth); + rc.rc_iTop = Clamp((INDEX)(bbox.minvect(3)-0),(INDEX)0,ptrTerrain->tr_pixHeightMapHeight); + rc.rc_iRight = Clamp((INDEX)ceil(bbox.maxvect(1)+1),(INDEX)0,ptrTerrain->tr_pixHeightMapWidth); + rc.rc_iBottom = Clamp((INDEX)ceil(bbox.maxvect(3)+1),(INDEX)0,ptrTerrain->tr_pixHeightMapHeight); + } else { + // max vector of bbox in incremented for one, because first vertex is at 0,0,0 in world and in heightmap is at 1,1 + rc.rc_iLeft = Clamp((INDEX)(bbox.minvect(1)-0),(INDEX)0,ptrTerrain->tr_pixHeightMapWidth); + rc.rc_iTop = Clamp((INDEX)(bbox.minvect(3)-0),(INDEX)0,ptrTerrain->tr_pixHeightMapHeight); + rc.rc_iRight = Clamp((INDEX)(bbox.maxvect(1)+0),(INDEX)0,ptrTerrain->tr_pixHeightMapWidth); + rc.rc_iBottom = Clamp((INDEX)(bbox.maxvect(3)+0),(INDEX)0,ptrTerrain->tr_pixHeightMapHeight); + } + + INDEX iStartX = rc.rc_iLeft; + INDEX iStartY = rc.rc_iTop; + INDEX iWidth = rc.Width(); + INDEX iHeight = rc.Height(); + + INDEX iFirst = iStartX + iStartY * ptrTerrain->tr_pixHeightMapWidth; + INDEX iPitchX = ptrTerrain->tr_pixHeightMapWidth - iWidth; + INDEX iPitchY = ptrTerrain->tr_pixHeightMapHeight - iHeight; + + // get first pixel in height map + UWORD *puwHeight = &ptrTerrain->tr_auwHeightMap[iFirst]; + UBYTE *pubMask = &ptrTerrain->tr_aubEdgeMap[iFirst]; + + INDEX ctVertices = iWidth*iHeight; + INDEX ctIndices = (iWidth-1)*(iHeight-1)*6; + +// ASSERT(ctVertices>0 && ctIndices>0); + if(ctVertices==0 || ctIndices==0) { + ctVtx = 0; + ctInd = 0; + return Rect(0,0,0,0); + } + + // Allocate space for vertices and indices + _avExtVertices.Push(ctVertices); + _aiExtIndices.Push(ctIndices); + + GFXVertex4 *pavVertices = &_avExtVertices[0]; + INDEX *pauiIndices = &_aiExtIndices[0]; + + // for each row + INDEX iy=0; + for(;iytr_vStretch(1); + vx.z = (FLOAT)(iy+iStartY)*ptrTerrain->tr_vStretch(3); + vx.y = *puwHeight * ptrTerrain->tr_vStretch(2); + vx.shade = *pubMask; + + puwHeight++; + pubMask++; + pavVertices++; + } + puwHeight+=iPitchX; + pubMask+=iPitchX; + } + + INDEX ivx=0; + INDEX ind=0; + INDEX iFacing=iFirst; + + GFXVertex *pavExtVtx = &_avExtVertices[0]; + INDEX ctVisTris = 0; // Visible tris + + // for each row + for(iy=0;iytr_pixHeightMapWidth + rc.rc_iLeft; + INDEX iStepY = ptrTerrain->tr_pixHeightMapWidth - iWidth; + UWORD *puwHeight = &ptrTerrain->tr_auwHeightMap[iFirstHeight]; + + GFXVertex *pavVertices = &_avExtVertices[0]; + INDEX iy=0; + for(;iyx = (FLOAT)(ix+iStartX)*ptrTerrain->tr_vStretch(1); + pavVertices->z = (FLOAT)(iy+iStartY)*ptrTerrain->tr_vStretch(3); + pavVertices->y = *puwHeight * ptrTerrain->tr_vStretch(2); + puwHeight++; + pavVertices++; + } + puwHeight+=iStepY; + } + + INDEX *pauiIndices = &_aiExtIndices[0]; + INDEX ivx=0; + INDEX ind=0; + INDEX iFacing=iFirstHeight; + // for each row + for(iy=0;iytr_ctTiles;itt++) { + QuadTreeNode &qtn = _ptrTerrain->tr_aqtnQuadTreeNodes[itt]; + // if it is coliding with given box + if(qtn.qtn_aabbox.HasContactWith(bbox)) { + // add it to array of coliding tiles + INDEX &iHitTile = _aiHitTiles.Push(); + iHitTile = itt; + } + } +} + +// Add these flags to all tiles that have been extracted +void AddFlagsToExtractedTiles(ULONG ulFlags) +{ + ASSERT(_ptrTerrain!=NULL); + // for each tile that has contact with extraction box + INDEX ctht = _aiHitTiles.Count(); + for(INDEX iht=0;ihttr_attTiles[iTileIndex]; + tt.AddFlag(ulFlags); + _ptrTerrain->AddTileToRegenQueue(iTileIndex); + } +} + +// Get value from layer at given point +UBYTE GetValueFromMask(CTerrain *ptrTerrain, INDEX iLayer, FLOAT3D vHitPoint) +{ + ASSERT(ptrTerrain!=NULL); + ASSERT(ptrTerrain->tr_penEntity!=NULL); + + CEntity *penEntity = ptrTerrain->tr_penEntity; + // convert hit point to terrain space and remove terrain stretch from terrain + FLOAT3D vHit = (vHitPoint - penEntity->en_plPlacement.pl_PositionVector) * !penEntity->en_mRotation; + vHit(1)=ceil(vHit(1)/ptrTerrain->tr_vStretch(1)); + vHit(3)=ceil(vHit(3)/ptrTerrain->tr_vStretch(3)); + + CTerrainLayer &tl = ptrTerrain->GetLayer(iLayer); + INDEX iVtx = vHit(1) + tl.tl_iMaskWidth*vHit(3); + if(iVtx<0 || iVtx>=tl.tl_iMaskWidth*tl.tl_iMaskHeight) { + ASSERTALWAYS("Invalid hit point"); + return 0; + } + UBYTE ubValue = tl.tl_aubColors[iVtx]; + return ubValue; +} + +// Allocate memory of one top map +void CreateTexture(CTextureData &tdTopMap, PIX pixWidth, PIX pixHeight,ULONG ulFlags) +{ + // clear current top map + if(tdTopMap.td_pulFrames!=NULL) { + FreeMemory( tdTopMap.td_pulFrames); + tdTopMap.td_pulFrames = NULL; + } + + // Create new top map + tdTopMap.td_mexWidth = pixWidth; + tdTopMap.td_mexHeight = pixHeight; + tdTopMap.td_ulFlags = ulFlags; + // Allocate memory for top map + INDEX ctMipMaps = GetNoOfMipmaps(pixWidth,pixHeight); + SLONG slSize = GetMipmapOffset(ctMipMaps,pixWidth,pixHeight)*BYTES_PER_TEXEL; + tdTopMap.td_pulFrames = (ULONG*)AllocMemory(slSize); + tdTopMap.td_slFrameSize = slSize; + tdTopMap.td_ctFrames = 1; + tdTopMap.td_iFirstMipLevel = 0; + tdTopMap.td_ctFineMipLevels = GetNoOfMipmaps(pixWidth,pixHeight); + // Prepare dithering type + tdTopMap.td_ulInternalFormat = TS.ts_tfRGBA8; +} + +// Create one topmap +void CreateTopMap(CTextureData &tdTopMap, PIX pixWidth , PIX pixHeight) +{ + ASSERT(tdTopMap.td_pulFrames==NULL); + // Prepare new top map + INDEX ctMipMaps = GetNoOfMipmaps(pixWidth,pixHeight); + SLONG slSize = GetMipmapOffset(ctMipMaps,pixWidth,pixHeight)*BYTES_PER_TEXEL; + + tdTopMap.td_mexWidth = pixWidth; + tdTopMap.td_mexHeight = pixHeight; + tdTopMap.td_ulFlags = TEX_ALPHACHANNEL|TEX_STATIC; // Pretend this texture is static + tdTopMap.td_pulFrames = NULL; // This will be shared memory + tdTopMap.td_slFrameSize = slSize; + tdTopMap.td_ctFrames = 1; + tdTopMap.td_iFirstMipLevel = 0; + tdTopMap.td_ctFineMipLevels = GetNoOfMipmaps(pixWidth,pixHeight); + tdTopMap.td_ulInternalFormat = TS.ts_tfRGB5A1; +} + +// Set topmap frames pointer to shared memory +void PrepareSharedTopMapMemory(CTextureData *ptdTopMap, INDEX iTileIndex) +{ + SLONG slSize = ptdTopMap->td_slFrameSize; + // if this is global top map + if(iTileIndex==(-1)) { + // if shared memory is larger then global top map + if(slSize<=_slSharedTopMapSize && _pulSharedTopMap!=NULL) { + // assign pointer of global top map to shared memory + ptdTopMap->td_pulFrames = _pulSharedTopMap; + return; + // else + } else { + // Allocate new memory for global top map + ptdTopMap->td_pulFrames = (ULONG*)AllocMemory(slSize); + } + // else this is normal top map + } else { + // if required memory is larger than currently allocated one + if(slSize>_slSharedTopMapSize) { + // if shared memory exists + if(_pulSharedTopMap!=NULL) { + // free current shared memory + FreeMemory(_pulSharedTopMap); + _pulSharedTopMap = NULL; + } + // allocate new shared memory for top maps + _pulSharedTopMap = (ULONG*)AllocMemory(slSize); + // remember new memory size + _slSharedTopMapSize = slSize; + } + // assign pointer of top map to shared memory + ptdTopMap->td_pulFrames = _pulSharedTopMap; + } +} + +void FreeSharedTopMapMemory(CTextureData *ptdTopMap, INDEX iTileIndex) +{ + // if this is global top map + if(iTileIndex==(-1)) { + // if global top map isn't using shared memory + if(ptdTopMap->td_pulFrames!=_pulSharedTopMap) { + // free memory global top map is using + FreeMemory(ptdTopMap->td_pulFrames); + } + } + // Just clear pointer to memory + ptdTopMap->td_pulFrames = NULL; +} + +static FLOAT3D CalculateNormalFromPoint(FLOAT fPosX, FLOAT fPosZ, FLOAT3D *pvStrPos=NULL) +{ + FLOAT3D vNormal; + INDEX iPosX = (INDEX)fPosX; + INDEX iPosZ = (INDEX)fPosZ; + FLOAT fLerpX = fPosX - iPosX; + FLOAT fLerpZ = fPosZ - iPosZ; + + FLOAT3D avVtx[4]; + INDEX iHMapWidth = _ptrTerrain->tr_pixHeightMapWidth; + FLOAT3D vStretch = _ptrTerrain->tr_vStretch; + + avVtx[0](1) = (FLOAT)(iPosX ) * vStretch(1); + avVtx[1](1) = (FLOAT)(iPosX+1) * vStretch(1); + avVtx[2](1) = (FLOAT)(iPosX ) * vStretch(1); + avVtx[3](1) = (FLOAT)(iPosX+1) * vStretch(1); + + avVtx[0](3) = (FLOAT)(iPosZ ) * vStretch(3); + avVtx[1](3) = (FLOAT)(iPosZ ) * vStretch(3); + avVtx[2](3) = (FLOAT)(iPosZ+1) * vStretch(3); + avVtx[3](3) = (FLOAT)(iPosZ+1) * vStretch(3); + + avVtx[0](2) = (FLOAT)_ptrTerrain->tr_auwHeightMap[ (iPosX ) + (iPosZ )*iHMapWidth ] * vStretch(2); + avVtx[1](2) = (FLOAT)_ptrTerrain->tr_auwHeightMap[ (iPosX+1) + (iPosZ )*iHMapWidth ] * vStretch(2); + avVtx[2](2) = (FLOAT)_ptrTerrain->tr_auwHeightMap[ (iPosX ) + (iPosZ+1)*iHMapWidth ] * vStretch(2); + avVtx[3](2) = (FLOAT)_ptrTerrain->tr_auwHeightMap[ (iPosX+1) + (iPosZ+1)*iHMapWidth ] * vStretch(2); + + FLOAT fHDeltaX = Lerp(avVtx[1](2)-avVtx[0](2), avVtx[3](2)-avVtx[2](2), fLerpZ); + FLOAT fHDeltaZ = Lerp(avVtx[0](2)-avVtx[2](2), avVtx[1](2)-avVtx[3](2), fLerpX); + FLOAT fDeltaX = avVtx[1](1) - avVtx[0](1); + FLOAT fDeltaZ = avVtx[0](3) - avVtx[2](3); + + vNormal(2) = sqrt(1 / (((fHDeltaX*fHDeltaX)/(fDeltaX*fDeltaX)) + ((fHDeltaZ*fHDeltaZ)/(fDeltaZ*fDeltaZ)) + 1)); + vNormal(1) = sqrt(vNormal(2)*vNormal(2) * ((fHDeltaX*fHDeltaX) / (fDeltaX*fDeltaX))); + vNormal(3) = sqrt(vNormal(2)*vNormal(2) * ((fHDeltaZ*fHDeltaZ) / (fDeltaZ*fDeltaZ))); + if (fHDeltaX>0) { + vNormal(1) = -vNormal(1); + } + if (fHDeltaZ<0) { + vNormal(3) = -vNormal(3); + } + ASSERT(Abs(vNormal.Length()-1)<0.01); + + if(pvStrPos!=NULL) { + FLOAT fResX1 = Lerp(avVtx[0](2),avVtx[1](2),fLerpX); + FLOAT fResX2 = Lerp(avVtx[2](2),avVtx[3](2),fLerpX); + FLOAT fPosY = Lerp(fResX1,fResX2,fLerpZ); + + (*pvStrPos)(1) = fPosX * vStretch(1); + (*pvStrPos)(2) = fPosY; // * vStretch(2); + (*pvStrPos)(3) = fPosZ * vStretch(3); + } + + return vNormal; +} + +static void CalcPointLight(CPlacement3D &plLight, CLightSource *plsLight, Rect &rcUpdate) +{ + FLOAT fSHDiffX = (FLOAT)_ptrTerrain->tr_pixHeightMapWidth / _ptrTerrain->GetShadowMapWidth(); + FLOAT fSHDiffZ = (FLOAT)_ptrTerrain->tr_pixHeightMapHeight / _ptrTerrain->GetShadowMapHeight(); + + PIX pixLeft = rcUpdate.rc_iLeft; + PIX pixRight = rcUpdate.rc_iRight; + PIX pixTop = rcUpdate.rc_iTop; + PIX pixBottom = rcUpdate.rc_iBottom; + PIX pixWidth = pixRight - pixLeft; + PIX pixStepX = _ptrTerrain->GetShadowMapWidth() - pixWidth; + + // Get color pointer in shadow map + PIX pixFirst = pixLeft + pixTop*_ptrTerrain->GetShadowMapWidth(); + GFXColor *pacolData = (GFXColor*)&_ptrTerrain->tr_tdShadowMap.td_pulFrames[pixFirst]; + + // for each row in shadow map + for(PIX pixY=pixTop;pixYGetLightColor(); + + // Calculate light intensity + FLOAT fIntensity = 1.0f; + FLOAT fFallOff = plsLight->ls_rFallOff; + FLOAT fHotSpot = plsLight->ls_rHotSpot; + if(fDistance>fFallOff) { + fIntensity = 0; + } else if(fDistance>fHotSpot) { + fIntensity = CalculateRatio(fDistance, fHotSpot, fFallOff, 0.0f, 1.0f); + } + ULONG ulIntensity = NormFloatToByte(fIntensity); + ulIntensity = (ulIntensity<r = ClampUp(pacolData->r + ((colLight.r*slDot)>>8),255L); + pacolData->g = ClampUp(pacolData->g + ((colLight.g*slDot)>>8),255L); + pacolData->b = ClampUp(pacolData->b + ((colLight.b*slDot)>>8),255L); + pacolData->a = 255; + pacolData++; + } + pacolData+=pixStepX; + } +} + +static void CalcDirectionalLight(CPlacement3D &plLight, CLightSource *plsLight, Rect &rcUpdate) +{ + FLOAT fSHDiffX = (FLOAT)_ptrTerrain->tr_pixHeightMapWidth / _ptrTerrain->GetShadowMapWidth(); + FLOAT fSHDiffZ = (FLOAT)_ptrTerrain->tr_pixHeightMapHeight / _ptrTerrain->GetShadowMapHeight(); + + PIX pixLeft = rcUpdate.rc_iLeft; + PIX pixRight = rcUpdate.rc_iRight; + PIX pixTop = rcUpdate.rc_iTop; + PIX pixBottom = rcUpdate.rc_iBottom; + PIX pixWidth = pixRight - pixLeft; + PIX pixStepX = _ptrTerrain->GetShadowMapWidth() - pixWidth; + + // Get color pointer in shadow map + PIX pixFirst = pixLeft + pixTop*_ptrTerrain->GetShadowMapWidth(); + GFXColor *pacolData = (GFXColor*)&_ptrTerrain->tr_tdShadowMap.td_pulFrames[pixFirst]; + + FLOAT3D vLightNormal; + GFXColor colLight = plsLight->GetLightColor(); + GFXColor colAmbient = plsLight->GetLightAmbient(); + + UBYTE ubColShift = 8; + SLONG slar = colAmbient.r; + SLONG slag = colAmbient.g; + SLONG slab = colAmbient.b; + + extern INDEX mdl_bAllowOverbright; + BOOL bOverBrightning = mdl_bAllowOverbright && _pGfx->gl_ctTextureUnits>1; + + // is overbrightning enabled + if(bOverBrightning) { + slar = ClampUp(slar,127L); + slag = ClampUp(slag,127L); + slab = ClampUp(slab,127L); + ubColShift = 8; + } else { + slar*=2; + slag*=2; + slab*=2; + ubColShift = 7; + } + + // Calculate light normal + AnglesToDirectionVector(plLight.pl_OrientationAngle,vLightNormal); + vLightNormal *= !_ptrTerrain->tr_penEntity->en_mRotation; + vLightNormal = -vLightNormal.Normalize(); + + // for each row in shadow map + for(PIX pixY=pixTop;pixYr = ClampUp(pacolData->r + slar + ((colLight.r*slDot)>>ubColShift),255L); + pacolData->g = ClampUp(pacolData->g + slag + ((colLight.g*slDot)>>ubColShift),255L); + pacolData->b = ClampUp(pacolData->b + slab + ((colLight.b*slDot)>>ubColShift),255L); + pacolData->a = 255; + pacolData++; + } + pacolData+=pixStepX; + } +} + +static void ClearPartOfShadowMap(CTerrain *ptrTerrain, Rect &rcUpdate) +{ + PIX pixLeft = rcUpdate.rc_iLeft; + PIX pixRight = rcUpdate.rc_iRight; + PIX pixTop = rcUpdate.rc_iTop; + PIX pixBottom = rcUpdate.rc_iBottom; + PIX pixWidth = pixRight - pixLeft; + PIX pixStepX = _ptrTerrain->GetShadowMapWidth() - pixWidth; + + // Get color pointer in shadow map + PIX pixFirst = rcUpdate.rc_iLeft + rcUpdate.rc_iTop * ptrTerrain->GetShadowMapWidth(); + GFXColor *pacolData = (GFXColor*)&_ptrTerrain->tr_tdShadowMap.td_pulFrames[pixFirst]; + // for each row in shadow map + for(PIX pixY=pixTop;pixYtr_pixHeightMapWidth / ptrTerrain->GetShadowMapWidth(); + FLOAT fSHDiffZ = (FLOAT)ptrTerrain->tr_pixHeightMapHeight / ptrTerrain->GetShadowMapHeight(); + rcUpdate.rc_iLeft = (INDEX)floor((boxUpdate.minvect(1)/ptrTerrain->tr_vStretch(1)) / fSHDiffX); + rcUpdate.rc_iRight = (INDEX)ceil ((boxUpdate.maxvect(1)/ptrTerrain->tr_vStretch(1)) / fSHDiffX); + rcUpdate.rc_iTop = (INDEX)floor((boxUpdate.minvect(3)/ptrTerrain->tr_vStretch(3)) / fSHDiffZ); + rcUpdate.rc_iBottom = (INDEX)ceil ((boxUpdate.maxvect(3)/ptrTerrain->tr_vStretch(3)) / fSHDiffZ); + return rcUpdate; +} + +static FLOATaabbox3D AbsoluteToRelative(const CTerrain *ptrTerrain, const FLOATaabbox3D &bbox) +{ + ASSERT(ptrTerrain!=NULL); + ASSERT(ptrTerrain->tr_penEntity!=NULL); + FLOATaabbox3D bboxRelative; + CEntity *pen = ptrTerrain->tr_penEntity; + + #define TRANSPT(x) (x-pen->en_plPlacement.pl_PositionVector) * !pen->en_mRotation + bboxRelative = TRANSPT(FLOAT3D(bbox.minvect(1),bbox.minvect(2),bbox.minvect(3))); + bboxRelative |= TRANSPT(FLOAT3D(bbox.minvect(1),bbox.minvect(2),bbox.maxvect(3))); + bboxRelative |= TRANSPT(FLOAT3D(bbox.maxvect(1),bbox.minvect(2),bbox.minvect(3))); + bboxRelative |= TRANSPT(FLOAT3D(bbox.maxvect(1),bbox.minvect(2),bbox.maxvect(3))); + bboxRelative |= TRANSPT(FLOAT3D(bbox.minvect(1),bbox.maxvect(2),bbox.minvect(3))); + bboxRelative |= TRANSPT(FLOAT3D(bbox.minvect(1),bbox.maxvect(2),bbox.maxvect(3))); + bboxRelative |= TRANSPT(FLOAT3D(bbox.maxvect(1),bbox.maxvect(2),bbox.minvect(3))); + bboxRelative |= TRANSPT(FLOAT3D(bbox.maxvect(1),bbox.maxvect(2),bbox.maxvect(3))); + return bboxRelative; +} + +static ULONG ulTemp = 0xFFFFFFFF; + +void UpdateTerrainShadowMap(CTerrain *ptrTerrain, FLOATaabbox3D *pboxUpdate/*=NULL*/, BOOL bAbsoluteSpace/*=FALSE*/) +{ + // if this is not world editor app + extern BOOL _bWorldEditorApp; + if(!_bWorldEditorApp) { + + ASSERTALWAYS("Terrain shadow map can only be updated from world editor!"); + return; + } + + ASSERT(ptrTerrain!=NULL); + ASSERT(ptrTerrain->tr_penEntity!=NULL); + ASSERT(ptrTerrain->tr_penEntity->en_pwoWorld!=NULL); + + FLOATaabbox3D boxUpdate; + FLOATaabbox3D boxAllTerrain; + CEntity *penEntity = ptrTerrain->tr_penEntity; + + ptrTerrain->GetAllTerrainBBox(boxAllTerrain); + // if request to update whole terrain is given + if(pboxUpdate==NULL) { + // take all terrain bbox as update box + boxUpdate = boxAllTerrain; + } else { + // use given bbox as update box + boxUpdate = *pboxUpdate; + if(bAbsoluteSpace) { + boxUpdate = AbsoluteToRelative(ptrTerrain, boxUpdate); + } + + // do not update terrain if update box isn't in terrain box + if(!boxUpdate.HasContactWith(boxAllTerrain)) { + return; + } + + boxUpdate.minvect(1) = Clamp(boxUpdate.minvect(1),boxAllTerrain.minvect(1),boxAllTerrain.maxvect(1)); + boxUpdate.minvect(3) = Clamp(boxUpdate.minvect(3),boxAllTerrain.minvect(3),boxAllTerrain.maxvect(3)); + boxUpdate.maxvect(1) = Clamp(boxUpdate.maxvect(1),boxAllTerrain.minvect(1),boxAllTerrain.maxvect(1)); + boxUpdate.maxvect(3) = Clamp(boxUpdate.maxvect(3),boxAllTerrain.minvect(3),boxAllTerrain.maxvect(3)); + boxUpdate.minvect(2) = boxAllTerrain.minvect(2); + boxUpdate.maxvect(2) = boxAllTerrain.maxvect(2); + } + + _ptrTerrain = ptrTerrain; + // Get pointer to world that holds this terrain + CWorld *pwldWorld = penEntity->en_pwoWorld; + + PIX pixWidth = ptrTerrain->GetShadowMapWidth(); + PIX pixHeight = ptrTerrain->GetShadowMapHeight(); + + CTextureData &tdShadowMap = ptrTerrain->tr_tdShadowMap; + ASSERT(tdShadowMap.td_pulFrames!=NULL); + + Rect rcUpdate = GetUpdateRectFromBox(ptrTerrain, boxUpdate); + // Clear part of shadow map that will be updated + ClearPartOfShadowMap(ptrTerrain,rcUpdate); + + // for each entity in the world + FOREACHINDYNAMICCONTAINER(pwldWorld->wo_cenEntities, CEntity, iten) { + // if it is light entity and it influences the given range + CLightSource *pls = iten->GetLightSource(); + CPlacement3D plLight = iten->en_plPlacement; + + // Translate light placement to terrain space + plLight.pl_PositionVector = + (plLight.pl_PositionVector - penEntity->en_plPlacement.pl_PositionVector) * !penEntity->en_mRotation; + + if (pls!=NULL) { + // Get light bounding box + FLOATaabbox3D boxLight(plLight.pl_PositionVector, pls->ls_rFallOff); + // if light is directional + if(pls->ls_ulFlags &LSF_DIRECTIONAL) { + // Calculate lightning + CalcDirectionalLight(plLight,pls,rcUpdate); + // if it is point light + } else { + _bboxDrawOne = boxLight; + _bboxDrawTwo = boxUpdate; + // if point light box have contact with update box + if(boxLight.HasContactWith(boxUpdate)) { + _ctShadowMapUpdates++; + + // if light box is inside update box + if(boxLight.minvect(1)>=boxUpdate.minvect(1) && boxLight.minvect(3)>boxUpdate.minvect(3) && + boxLight.maxvect(1)<=boxUpdate.maxvect(1) && boxLight.maxvect(3)<=boxUpdate.maxvect(3)) { + // Recalculate only light box + Rect rcLightUpdate = GetUpdateRectFromBox(ptrTerrain,boxLight); + CalcPointLight(plLight,pls,rcLightUpdate); + // else + } else { + // Recalculate update box + CalcPointLight(plLight,pls,rcUpdate); + } + } + } + } + } + + // Create shadow map mipmaps + INDEX ctMipMaps = GetNoOfMipmaps(tdShadowMap.td_mexWidth,tdShadowMap.td_mexHeight); + MakeMipmaps(ctMipMaps, tdShadowMap.td_pulFrames, tdShadowMap.td_mexWidth, tdShadowMap.td_mexHeight); + + + // Update shading map from one mip of shadow map + INDEX iMipOffset = GetMipmapOffset(ptrTerrain->tr_iShadingMapSizeAspect,ptrTerrain->GetShadowMapWidth(),ptrTerrain->GetShadowMapHeight()); + UWORD *puwShade = &ptrTerrain->tr_auwShadingMap[0]; + ULONG *ppixShadowMip = &ptrTerrain->tr_tdShadowMap.td_pulFrames[iMipOffset]; + + INDEX ctpixs = ptrTerrain->GetShadingMapWidth()*ptrTerrain->GetShadingMapHeight(); + for(PIX ipix=0;ipix>27)&0x001F)<<10) | + (((ulPixel>>19)&0x001F)<< 5) | + (((ulPixel>>11)&0x001F)<< 0); + puwShade++; + ppixShadowMip++; + } + + // discard cached model info + ptrTerrain->DiscardShadingInfos(); + + ptrTerrain->tr_tdShadowMap.SetAsCurrent(0,TRUE); +} + + +// Calculate 2d relative point in terrain from absolute 3d point in world +Point Calculate2dHitPoint(CTerrain *ptrTerrain, FLOAT3D &vHitPoint) +{ + ASSERT(ptrTerrain!=NULL); + ASSERT(ptrTerrain->tr_penEntity!=NULL); + + // Get entity that holds this terrain + CEntity *penEntity = ptrTerrain->tr_penEntity; + // Get relative hit point + FLOAT3D vRelHitPoint = (vHitPoint - penEntity->en_plPlacement.pl_PositionVector) * !penEntity->en_mRotation; + + // Unstretch hit point and convert it to 2d + Point pt; + pt.pt_iX = ceil(vRelHitPoint(1) / ptrTerrain->tr_vStretch(1) - 0.5f); + pt.pt_iY = ceil(vRelHitPoint(3) / ptrTerrain->tr_vStretch(3) - 0.5f); + + return pt; +} + +// Calculate tex coords on shading map from absolute 3d point in world +FLOAT2D CalculateShadingTexCoords(CTerrain *ptrTerrain, FLOAT3D &vPoint) +{ + ASSERT(ptrTerrain!=NULL); + ASSERT(ptrTerrain->tr_penEntity!=NULL); + // Get entity that holds this terrain + CEntity *penEntity = ptrTerrain->tr_penEntity; + // Get relative hit point + FLOAT3D vRelPoint = (vPoint - penEntity->en_plPlacement.pl_PositionVector) * !penEntity->en_mRotation; + + // Unstretch hit point and convert it to 2d point in shading map + FLOAT fX = vRelPoint(1) / ptrTerrain->tr_vStretch(1); + FLOAT fY = vRelPoint(3) / ptrTerrain->tr_vStretch(3); + FLOAT fU = fX / ((FLOAT)(ptrTerrain->tr_pixHeightMapWidth) / ptrTerrain->GetShadingMapWidth()); + FLOAT fV = fY / ((FLOAT)(ptrTerrain->tr_pixHeightMapHeight) / ptrTerrain->GetShadingMapHeight()); + + ASSERT(fU>0.0f && fUGetShadingMapWidth()); + ASSERT(fV>0.0f && fVGetShadingMapHeight()); + return FLOAT2D(fU,fV); +} diff --git a/Sources/Engine/Terrain/TerrainMisc.h b/Sources/Engine/Terrain/TerrainMisc.h new file mode 100644 index 0000000..232aa30 --- /dev/null +++ b/Sources/Engine/Terrain/TerrainMisc.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TERRAIN_MISC_H +#define SE_INCL_TERRAIN_MISC_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +// Extract polygons in given box and returns clipped rectangle +Rect ExtractPolygonsInBox(CTerrain *ptrTerrain, const FLOATaabbox3D &bbox, GFXVertex4 **pavVtx, + INDEX **paiInd, INDEX &ctVtx,INDEX &ctInd,BOOL bFixSize=FALSE); + +void ExtractVerticesInRect(CTerrain *ptrTerrain, Rect &rc, GFXVertex4 **pavVtx, + INDEX **paiInd, INDEX &ctVtx,INDEX &ctInd); + + +// check whether a polygon is below given point, but not too far away +BOOL IsTerrainBelowPoint(CTerrain *ptrTerrain, const FLOAT3D &vPoint, FLOAT fMaxDist, const FLOAT3D &vGravityDir); + +// Extract all tiles that intersect with given box +void FindTilesInBox(CTerrain *ptrTerrain, FLOATaabbox3D &bbox); +// Add these flags to all tiles that have been extracted +void AddFlagsToExtractedTiles(ULONG ulFlags); + +// Create new texture +void CreateTexture(CTextureData &td, INDEX iWidth, INDEX iHeight, ULONG ulFlags); + +void CreateTopMap(CTextureData &tdTopMap, PIX pixWidth , PIX pixHeight); +void PrepareSharedTopMapMemory(CTextureData *ptdTopMap, INDEX iTileIndex); +void FreeSharedTopMapMemory(CTextureData *ptdTopMap, INDEX iTileIndex); + +void ReGenerateTopMap(CTerrain *ptrTerrain, INDEX iTileIndex); + +// Update terrain shadow map +void UpdateTerrainShadowMap(CTerrain *ptrTerrain, FLOATaabbox3D *pboxUpdate=NULL, BOOL bAbsoluteSpace=FALSE); + +// Get value from layer at given point +ENGINE_API UBYTE GetValueFromMask(CTerrain *ptrTerrain, INDEX iLayer, FLOAT3D vHitPoint); +// Calculate 2d relative point in terrain from absolute 3d point in world +ENGINE_API Point Calculate2dHitPoint(CTerrain *ptrTerrain, FLOAT3D &vHitPoint); +FLOAT2D CalculateShadingTexCoords(CTerrain *ptrTerrain, FLOAT3D &vPoint); + + + + + +#endif \ No newline at end of file diff --git a/Sources/Engine/Terrain/TerrainRayCasting.cpp b/Sources/Engine/Terrain/TerrainRayCasting.cpp new file mode 100644 index 0000000..c846f74 --- /dev/null +++ b/Sources/Engine/Terrain/TerrainRayCasting.cpp @@ -0,0 +1,535 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include +#include +#include + +static CTerrain *_ptrTerrain = NULL; +static FLOAT3D _vOrigin; // Origin of ray +static FLOAT3D _vTarget; // Ray target +static FLOAT _fMinHeight; // Min height that ray will pass through in tested quad +static FLOAT _fMaxHeight; // Max height that ray will pass through in tested quad +static BOOL _bHitInvisibleTris; // Does ray hits invisible triangles + +static FLOAT3D _vHitExact; // hit point +static FLOATplane3D _plHitPlane; // hit plane + +// TEMP +static CStaticStackArray _avRCVertices; +static CStaticStackArray _aiRCIndices; +static FLOAT3D _vHitBegin; +static FLOAT3D _vHitEnd; +static FLOAT _fDistance; + +// Test ray agains one quad on terrain (if it's visible) +static FLOAT HitCheckQuad(const PIX ix, const PIX iz) +{ + FLOAT fDistance = UpperLimit(0.0f); + + // if quad is outside terrain + if(ix<0 || iz<0 || ix>= (_ptrTerrain->tr_pixHeightMapWidth-1) || iz >= (_ptrTerrain->tr_pixHeightMapHeight-1)) { + return fDistance; + } + + ASSERT(ix>=0 && iz>=0); + ASSERT(ix<(_ptrTerrain->tr_pixHeightMapWidth-1) && iz<(_ptrTerrain->tr_pixHeightMapHeight-1)); + + const PIX pixMapWidth = _ptrTerrain->tr_pixHeightMapWidth; + const INDEX ctVertices = _avRCVertices.Count(); // TEMP + + UWORD *puwHeight = &_ptrTerrain->tr_auwHeightMap[ix + iz*pixMapWidth]; + UBYTE *pubMask = &_ptrTerrain->tr_aubEdgeMap[ix + iz*pixMapWidth]; + GFXVertex *pvx = _avRCVertices.Push(4); + + GFXVertex *pavVertices = &_avRCVertices[0]; + // Add four vertices + pvx[0].x = (ix+0) * _ptrTerrain->tr_vStretch(1); + pvx[0].y = puwHeight[0] * _ptrTerrain->tr_vStretch(2); + pvx[0].z = (iz+0) * _ptrTerrain->tr_vStretch(3); + pvx[0].shade = pubMask[0]; + + pvx[1].x = (ix+1) * _ptrTerrain->tr_vStretch(1); + pvx[1].y = puwHeight[1] * _ptrTerrain->tr_vStretch(2); + pvx[1].z = (iz+0) * _ptrTerrain->tr_vStretch(3); + pvx[1].shade = pubMask[1]; + + pvx[2].x = (ix+0) * _ptrTerrain->tr_vStretch(1); + pvx[2].y = puwHeight[pixMapWidth] * _ptrTerrain->tr_vStretch(2); + pvx[2].z = (iz+1) * _ptrTerrain->tr_vStretch(3); + pvx[2].shade = pubMask[pixMapWidth]; + + pvx[3].x = (ix+1) * _ptrTerrain->tr_vStretch(1); + pvx[3].y = puwHeight[pixMapWidth+1] * _ptrTerrain->tr_vStretch(2); + pvx[3].z = (iz+1) * _ptrTerrain->tr_vStretch(3); + pvx[3].shade = pubMask[pixMapWidth+1]; + + BOOL bFacing = (ix + iz*pixMapWidth)&1; + + INDEX ctIndices=0; + // Add one quad + if(bFacing) { + // if at least one point of triangle is above min height and bellow max height of ray and traingle is visible + if((pvx[0].y>=_fMinHeight || pvx[2].y>=_fMinHeight || pvx[1].y>=_fMinHeight) && + (pvx[0].y<=_fMaxHeight || pvx[2].y<=_fMinHeight || pvx[1].y<=_fMinHeight) && + ((pvx[0].shade + pvx[2].shade + pvx[1].shade == 255*3) | _bHitInvisibleTris)) { + // Add this triangle + INDEX *pind = _aiRCIndices.Push(3); + pind[0] = ctVertices+0; + pind[1] = ctVertices+2; + pind[2] = ctVertices+1; + ctIndices+=3; + } + // if at least one point of triangle is above min height and bellow max height of ray and traingle is visible + if((pvx[1].y>=_fMinHeight || pvx[2].y>=_fMinHeight || pvx[3].y>=_fMinHeight) && + (pvx[1].y<=_fMaxHeight || pvx[2].y<=_fMaxHeight || pvx[3].y<=_fMaxHeight) && + ((pvx[1].shade + pvx[2].shade + pvx[3].shade == 255*3) | _bHitInvisibleTris)) { + // Add this triangle + INDEX *pind = _aiRCIndices.Push(3); + pind[0] = ctVertices+1; + pind[1] = ctVertices+2; + pind[2] = ctVertices+3; + ctIndices+=3; + } + } else { + // if at least one point of triangle is above min height and bellow max height of ray and traingle is visible + if((pvx[2].y>=_fMinHeight || pvx[3].y>=_fMinHeight || pvx[0].y>=_fMinHeight) && + (pvx[2].y<=_fMaxHeight || pvx[3].y<=_fMaxHeight || pvx[0].y<=_fMaxHeight) && + ((pvx[2].shade + pvx[3].shade + pvx[0].shade == 255*3) | _bHitInvisibleTris)) { + // Add this triangle + INDEX *pind = _aiRCIndices.Push(3); + pind[0] = ctVertices+2; + pind[1] = ctVertices+3; + pind[2] = ctVertices+0; + ctIndices+=3; + } + // if at least one point of triangle is above min height and bellow max height of ray and traingle is visible + if((pvx[0].y>=_fMinHeight || pvx[3].y>=_fMinHeight || pvx[1].y>=_fMinHeight) && + (pvx[0].y<=_fMaxHeight || pvx[3].y<=_fMaxHeight || pvx[1].y<=_fMaxHeight) && + ((pvx[0].shade + pvx[3].shade + pvx[1].shade == 255*3) | _bHitInvisibleTris)) { + // Add this triangle + INDEX *pind = _aiRCIndices.Push(3); + pind[0] = ctVertices+0; + pind[1] = ctVertices+3; + pind[2] = ctVertices+1; + ctIndices+=3; + } + } + + if(ctIndices==0) { + return fDistance; + } + + INDEX *paiIndices = &_aiRCIndices[_aiRCIndices.Count() - ctIndices]; + // for each triangle + for(INDEX iTri=0;iTri=0 && fDistance0>=fDistance1) { + // calculate fraction of line before intersection + FLOAT fFraction = fDistance0/(fDistance0-fDistance1); + // calculate intersection coordinate + FLOAT3D vHitPoint = _vOrigin+(_vTarget-_vOrigin)*fFraction; + // calculate intersection distance + FLOAT fHitDistance = (vHitPoint-_vOrigin).Length(); + // if the hit point can not be new closest candidate + if (fHitDistance>fDistance) { + // skip this triangle + continue; + } + + // find major axes of the polygon plane + INDEX iMajorAxis1, iMajorAxis2; + GetMajorAxesForPlane(plTriPlane, iMajorAxis1, iMajorAxis2); + + // create an intersector + CIntersector isIntersector(vHitPoint(iMajorAxis1), vHitPoint(iMajorAxis2)); + + // check intersections for all three edges of the polygon + isIntersector.AddEdge( + vx0(iMajorAxis1), vx0(iMajorAxis2), + vx1(iMajorAxis1), vx1(iMajorAxis2)); + isIntersector.AddEdge( + vx1(iMajorAxis1), vx1(iMajorAxis2), + vx2(iMajorAxis1), vx2(iMajorAxis2)); + isIntersector.AddEdge( + vx2(iMajorAxis1), vx2(iMajorAxis2), + vx0(iMajorAxis1), vx0(iMajorAxis2)); + + // if the polygon is intersected by the ray, and it is the closest intersection so far + if (isIntersector.IsIntersecting() && (fHitDistance < fDistance)) { + // remember hit coordinates + if(fHitDistance> Remove defined NUMDIM, RIGHT, LEFT ...") +#define NUMDIM 3 +#define RIGHT 0 +#define LEFT 1 +#define MIDDLE 2 + +// Check if ray hits aabbox and return coords where ray enter and exit the box +static BOOL HitAABBox(const FLOAT3D &vOrigin, const FLOAT3D &vTarget, FLOAT3D &vHitBegin, + FLOAT3D &vHitEnd, const FLOATaabbox3D &bbox) +{ + const FLOAT3D vDir = (vTarget - vOrigin).Normalize(); + const FLOAT3D vMin = bbox.minvect; + const FLOAT3D vMax = bbox.maxvect; + FLOAT3D vBeginCandidatePlane; + FLOAT3D vEndCandidatePlane; + FLOAT3D vBeginTDistance; + FLOAT3D vEndTDistance; + INDEX iOriginSide[3]; + BOOL bOriginInside = TRUE; + + INDEX i; + + // Find candidate planes + for(i=1;i<4;i++) { + // Check begining of ray + if(vOrigin(i) < vMin(i)) { + vBeginCandidatePlane(i) = vMin(i); + vEndCandidatePlane(i) = vMax(i); + bOriginInside = FALSE; + iOriginSide[i-1] = LEFT; + } else if(vOrigin(i) > vMax(i)) { + vBeginCandidatePlane(i) = vMax(i); + vEndCandidatePlane(i) = vMin(i); + bOriginInside = FALSE; + iOriginSide[i-1] = RIGHT; + } else { + iOriginSide[i-1] = MIDDLE; + if(vDir(i)>0.0f) { + vEndCandidatePlane(i) = vMax(i); + } else { + vEndCandidatePlane(i) = vMin(i); + } + } + } + + // Calculate T distances to candidate planes + for(i=1;i<4;i++) { + if(iOriginSide[i-1]!=MIDDLE && vDir(i)!=0.0f) { + vBeginTDistance(i) = (vBeginCandidatePlane(i)-vOrigin(i)) / vDir(i); + } else { + vBeginTDistance(i) = -1.0f; + } + if(vDir(i)!=0.0f) { + vEndTDistance(i) = (vEndCandidatePlane(i)-vOrigin(i)) / vDir(i); + } else { + vEndTDistance(i) = -1.0f; + } + } + + // Get largest of the T distances for final choice of intersection + INDEX iBeginMaxT = 1; + INDEX iEndMinT = 1; + for(i=2;i<4;i++) { + if(vBeginTDistance(i) > vBeginTDistance(iBeginMaxT)) { + iBeginMaxT = i; + } + if(vEndTDistance(i)>=0.0f && (vEndTDistance(iEndMinT)<0.0f || vEndTDistance(i) < vEndTDistance(iEndMinT)) ) { + iEndMinT = i; + } + } + + // if origin inside box + if(bOriginInside) { + // Begining of ray is origin point + vHitBegin = vOrigin; + // else + } else { + // Check final candidate actually inside box + if(vBeginTDistance(iBeginMaxT)<0.0f) { + return FALSE; + } + if(vEndTDistance(iEndMinT)<0.0f) { + return FALSE; + } + + // Calculate point where ray enter box + for(i=1;i<4;i++) { + if(iBeginMaxT != i) { + vHitBegin(i) = vOrigin(i) + vBeginTDistance(iBeginMaxT) * vDir(i); + if(vHitBegin(i) < vMin(i) || vHitBegin(i) > vMax(i)) { + return FALSE; + } + } else { + vHitBegin(i) = vBeginCandidatePlane(i); + } + } + } + + // Caclulate point where ray exit box + for(i=1;i<4;i++) { + if(iEndMinT != i) { + vHitEnd(i) = vOrigin(i) + vEndTDistance(iEndMinT) * vDir(i); + if(vHitEnd(i) < vMin(i) || vHitEnd(i) > vMax(i)) { + // no ray exit point !? + ASSERT(FALSE); + } + } else { + vHitEnd(i) = vEndCandidatePlane(i); + } + } + + return TRUE; +} + +// Test all quads in ray direction and return exact hit location +static FLOAT GetExactHitLocation(CTerrain *ptrTerrain, const FLOAT3D &vHitBegin, const FLOAT3D &vHitEnd, + const FLOAT fOldDistance) +{ + // set global vars + _ptrTerrain = ptrTerrain; + _vOrigin = vHitBegin; + _vTarget = vHitEnd; + + // TEMP + _avRCVertices.PopAll(); + _aiRCIndices.PopAll(); + + const FLOAT fX0 = vHitBegin(1) / ptrTerrain->tr_vStretch(1); + const FLOAT fY0 = vHitBegin(3) / ptrTerrain->tr_vStretch(3); + const FLOAT fH0 = vHitBegin(2);// / ptrTerrain->tr_vStretch(2); + const FLOAT fX1 = vHitEnd(1) / ptrTerrain->tr_vStretch(1); + const FLOAT fY1 = vHitEnd(3) / ptrTerrain->tr_vStretch(3); + const FLOAT fH1 = vHitEnd(2);// / ptrTerrain->tr_vStretch(2); + + FLOAT fDeltaX = Abs(fX1-fX0); + FLOAT fDeltaY = Abs(fY1-fY0); + FLOAT fIterator; + + if(fDeltaX>fDeltaY) { + fIterator = fDeltaX; + } else { + fIterator = fDeltaY; + } + if(fIterator==0) { + fIterator = 0.01f; + } + + const FLOAT fStepX = (fX1-fX0) / fIterator; + const FLOAT fStepY = (fY1-fY0) / fIterator; + const FLOAT fStepH = (fH1-fH0) / fIterator; + const FLOAT fEpsilonH = Abs(fStepH); + + FLOAT fX; + FLOAT fY; + FLOAT fH; + // calculate prestep + if(fDeltaX>fDeltaY) { + if(fX0fDeltaY) { + // check left quad + fDistance1 = HitCheckQuad(pixX-1,pixY); + // else + } else { + // check upper quad + fDistance1 = HitCheckQuad(pixX,pixY-1); + } + + // find closer of two quads + if(fDistance1GetAllTerrainBBox(bboxAll); + + extern INDEX ter_bTempFreezeCast; + static FLOAT3D _vFrozenStart; + static FLOAT3D _vFrozenEnd; + + if(ter_bTempFreezeCast) { + vStart = _vFrozenStart; + vEnd = _vFrozenEnd; + } else { + _vFrozenStart = vStart; + _vFrozenEnd = vEnd; + } + + // if ray hits terrain box + if(HitAABBox(vStart,vEnd,vHitBegin,vHitEnd,bboxAll)) { + // if begin and end are at same pos + if(vHitBegin==vHitEnd) { + // move end hit + vHitBegin(2)+=0.1f; + vHitEnd(2)-=0.1f; + } + _vHitBegin = vHitBegin; + _vHitEnd = vHitEnd; + // find exact hit location on terrain + fDistance = GetExactHitLocation(ptrTerrain,vHitBegin,vHitEnd,fOldDistance); + fDistance += (vStart-vHitBegin).Length(); + } + _fDistance = fDistance; + return fDistance; +} + +FLOAT TestRayCastHit(CTerrain *ptrTerrain, const FLOATmatrix3D &mRotation, const FLOAT3D &vPosition, + const FLOAT3D &vOrigin, const FLOAT3D &vTarget,const FLOAT fOldDistance, + const BOOL bHitInvisibleTris, FLOATplane3D &plHitPlane, FLOAT3D &vHitPoint) +{ + ASSERT(ptrTerrain!=NULL); + ASSERT(ptrTerrain->tr_penEntity!=NULL); + + CEntity *pen = ptrTerrain->tr_penEntity; + + // casting ray + FLOAT fDistance = TestRayCastHit(ptrTerrain, mRotation, vPosition, vOrigin, vTarget, fOldDistance, bHitInvisibleTris); + // convert hit point to absulute point + vHitPoint = (_vHitExact * pen->en_mRotation) + pen->en_plPlacement.pl_PositionVector; + + plHitPlane = _plHitPlane; + return fDistance; + +} + +#include +#include +void ShowRayPath(CDrawPort *pdp) +{ + return; + INDEX ctVertices = _avRCVertices.Count(); + INDEX ctIndices = _aiRCIndices.Count(); + if(ctVertices>0 && ctIndices>0) { + gfxDisableTexture(); + gfxDisableBlend(); + gfxEnableDepthBias(); + gfxPolygonMode(GFX_LINE); + gfxSetVertexArray(&_avRCVertices[0],_avRCVertices.Count()); + gfxSetConstantColor(0xFFFFFFFF); + gfxDrawElements(_aiRCIndices.Count(),&_aiRCIndices[0]); + gfxDisableDepthBias(); + gfxPolygonMode(GFX_FILL); + } + + gfxEnableDepthBias(); + gfxDisableDepthTest(); + pdp->DrawPoint3D(_vHitBegin,0x00FF00FF,8); + pdp->DrawPoint3D(_vHitEnd,0xFF0000FF,8); + pdp->DrawPoint3D(_vHitExact,0x00FFFF,8); + pdp->DrawLine3D(_vHitBegin,_vHitEnd,0xFFFF00FF); + pdp->DrawLine3D(FLOAT3D(_vHitBegin(1),_vHitEnd(2),_vHitBegin(3)),_vHitEnd,0xFF0000FF); + gfxEnableDepthTest(); + gfxDisableDepthBias(); + + /* + extern void gfxDrawWireBox(FLOATaabbox3D &bbox, COLOR col); + if(_ptrTerrain!=NULL) { + FLOATaabbox3D bboxAll; + _ptrTerrain->GetAllTerrainBBox(bboxAll); + gfxDrawWireBox(bboxAll,0xFFFF00FF); + } + pdp->SetFont( _pfdConsoleFont); + pdp->SetTextAspect( 1.0f); + pdp->SetOrtho(); + pdp->PutText(CTString(0,"%g",_fDistance),0,0,0xFFFFFFFF); + */ +} \ No newline at end of file diff --git a/Sources/Engine/Terrain/TerrainRayCasting.h b/Sources/Engine/Terrain/TerrainRayCasting.h new file mode 100644 index 0000000..9f8dca1 --- /dev/null +++ b/Sources/Engine/Terrain/TerrainRayCasting.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TERRAIN_RAY_CASTING_H +#define SE_INCL_TERRAIN_RAY_CASTING_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +FLOAT TestRayCastHit(CTerrain *ptrTerrain, const FLOATmatrix3D &mRotation, const FLOAT3D &vPosition, + const FLOAT3D &vOrigin, const FLOAT3D &vTarget,const FLOAT fOldDistance, + const BOOL bHitInvisibleTris); + +FLOAT TestRayCastHit(CTerrain *ptrTerrain, const FLOATmatrix3D &mRotation, const FLOAT3D &vPosition, + const FLOAT3D &vOrigin, const FLOAT3D &vTarget,const FLOAT fOldDistance, + const BOOL bHitInvisibleTris, FLOATplane3D &plHitPlane, FLOAT3D &vHitPoint); +#endif \ No newline at end of file diff --git a/Sources/Engine/Terrain/TerrainRender.cpp b/Sources/Engine/Terrain/TerrainRender.cpp new file mode 100644 index 0000000..a9cd5f8 --- /dev/null +++ b/Sources/Engine/Terrain/TerrainRender.cpp @@ -0,0 +1,1398 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static CAnyProjection3D _aprProjection; // Current projection +static CDrawPort *_pdp = NULL; // Current drawport +CTerrain *_ptrTerrain; // Current terrain +FLOAT3D _vViewerAbs; // Position of viewer +static COLOR _colTerrainEdges; // Color of terrain edges + +static FLOATmatrix3D _mObjectToView; +static FLOAT3D _vObjectToView; +static FLOAT3D _vViewer; +static FLOAT3D _vViewerObj; + +extern INDEX _ctNodesVis; // visible quad nodes +extern INDEX _ctTris; // tris rendered +extern INDEX _ctDelayedNodes; // DelayedNodes +extern INDEX ter_bLerpVertices; // prepare smoth vertices before rendering + +// Vertex array for calculating smoth vertices +CStaticStackArray _avLerpedVerices; +CStaticStackArray _avLerpedTileLayerVertices; + +// Arrays for batch rendering of tiles is lowest mip +static CStaticStackArray _avDelayedVertices; +static CStaticStackArray _aiDelayedIndices; +static CStaticStackArray _auvDelayedTexCoords; +static CStaticStackArray _auvDelayedShadowMapTC; + +typedef FLOAT Matrix16[16]; +typedef FLOAT Matrix12[12]; + +static void RenderFogLayer(INDEX itt); +static void RenderHazeLayer(INDEX itt); + +FLOATaabbox3D _bboxDrawNextFrame; // TEMP + +SLONG GetUsedMemoryForTileBatching(void) +{ + SLONG slUsedMemory = 0; + slUsedMemory += _avDelayedVertices.sa_Count * sizeof(GFXVertex4); + slUsedMemory += _aiDelayedIndices.sa_Count * sizeof(INDEX); + slUsedMemory += _auvDelayedTexCoords.sa_Count * sizeof(GFXTexCoord); + slUsedMemory += _auvDelayedShadowMapTC.sa_Count * sizeof(GFXTexCoord); + return slUsedMemory; +} + +CStaticStackArray _acolVtxConstColors; +static void FillConstColorArray(INDEX ctVertices) +{ + INDEX ctColors=_acolVtxConstColors.Count(); + _acolVtxConstColors.PopAll(); + _acolVtxConstColors.Push(ctVertices); + // if requested array is larger then existing one + if(ctVertices>ctColors) { + memset(&_acolVtxConstColors[ctColors],255,(ctVertices-ctColors)*sizeof(GFXColor)); + } +} + +// Regenerate one tile +void ReGenerateTile(INDEX itt) +{ + ASSERT(_ptrTerrain!=NULL); + CTerrainTile &tt = _ptrTerrain->tr_attTiles[itt]; + tt.ReGenerate(); +} + +// Convert matrix12 to +void CreateOpenGLMatrix(Matrix12 &m12,Matrix16 &mgl16) +{ + mgl16[ 0] = m12[ 0]; mgl16[ 1] = m12[ 4]; mgl16[ 2] = m12[ 8]; mgl16[ 3] = 0; + mgl16[ 4] = m12[ 1]; mgl16[ 5] = m12[ 5]; mgl16[ 6] = m12[ 9]; mgl16[ 7] = 0; + mgl16[ 8] = m12[ 2]; mgl16[ 9] = m12[ 6]; mgl16[10] = m12[10]; mgl16[11] = 0; + mgl16[12] = m12[ 3]; mgl16[13] = m12[ 7]; mgl16[14] = m12[11]; mgl16[15] = 1; +} + +// set given matrix as identity matrix +inline static void SetMatrixDiagonal(Matrix12 &mat,FLOAT fValue) +{ + memset(&mat,0,sizeof(mat)); + mat[0] = fValue; + mat[5] = fValue; + mat[10] = fValue; +} + +// Set texture matrix +static inline void gfxSetTextureMatrix2(Matrix12 *pMatrix) +{ + pglMatrixMode( GL_TEXTURE); + if(pMatrix==NULL) { + pglLoadIdentity(); + } else { + Matrix16 mrot16; + Matrix16 mtra16; + CreateOpenGLMatrix(*pMatrix,mrot16); + + Matrix12 mtr12; + SetMatrixDiagonal(mtr12,1); + CreateOpenGLMatrix(mtr12,mtra16); + pglLoadMatrixf(mtra16); + pglMultMatrixf(mrot16); + } + pglMatrixMode(GL_MODELVIEW); +} + + +/* + * Render + */ +// Prepare scene for terrain rendering +void PrepareScene(CAnyProjection3D &apr, CDrawPort *pdp, CTerrain *ptrTerrain) +{ + ASSERT(ptrTerrain!=NULL); + ASSERT(ptrTerrain->tr_penEntity!=NULL); + + // Set current terrain + _ptrTerrain = ptrTerrain; + + // Set drawport + _pdp = pdp; + + // Prepare and set the projection + apr->ObjectPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + apr->Prepare(); + _aprProjection = apr; + _pdp->SetProjection( _aprProjection); + + CEntity *pen = ptrTerrain->tr_penEntity; + + // calculate projection of viewer in absolute space + const FLOATmatrix3D &mViewer = _aprProjection->pr_ViewerRotationMatrix; + _vViewer(1) = -mViewer(3,1); + _vViewer(2) = -mViewer(3,2); + _vViewer(3) = -mViewer(3,3); + // calculate projection of viewer in object space + _vViewerObj = _vViewer * !pen->en_mRotation; + + + CPlacement3D &plTerrain = pen->GetLerpedPlacement(); + + _mObjectToView = mViewer * pen->en_mRotation; + _vObjectToView = (plTerrain.pl_PositionVector - _aprProjection->pr_vViewerPosition) * mViewer; + + // make transform matrix + const FLOATmatrix3D &m = _mObjectToView; + const FLOAT3D &v = _vObjectToView; + FLOAT glm[16]; + glm[0] = m(1,1); glm[4] = m(1,2); glm[ 8] = m(1,3); glm[12] = v(1); + glm[1] = m(2,1); glm[5] = m(2,2); glm[ 9] = m(2,3); glm[13] = v(2); + glm[2] = m(3,1); glm[6] = m(3,2); glm[10] = m(3,3); glm[14] = v(3); + glm[3] = 0; glm[7] = 0; glm[11] = 0; glm[15] = 1; + gfxSetViewMatrix(glm); + + // Get viewer in absolute space + _vViewerAbs = (_aprProjection->ViewerPlacementR().pl_PositionVector - + pen->en_plPlacement.pl_PositionVector) * !pen->en_mRotation; + + gfxDisableBlend(); + gfxDisableTexture(); + gfxDisableAlphaTest(); + gfxEnableDepthTest(); + gfxEnableDepthWrite(); + gfxCullFace(GFX_BACK); +} + + +__forceinline void Lerp(GFXVertex &vResult, const GFXVertex &vOriginal, const GFXVertex &v1, const GFXVertex &v2, const FLOAT &fFactor) +{ + FLOAT fHalfPosY = Lerp(v1.y,v2.y,0.5f); + vResult.x = vOriginal.x; + vResult.y = Lerp(vOriginal.y, fHalfPosY, fFactor); + vResult.z = vOriginal.z; +} + +void PrepareSmothVertices(INDEX itt) +{ + CTerrainTile &tt = _ptrTerrain->tr_attTiles[itt]; + const INDEX ctVertices = tt.GetVertices().Count(); + const FLOAT &fLerpFactor = tt.tt_fLodLerpFactor; + + // Allocate memory for all vertices + _avLerpedVerices.PopAll(); + _avLerpedVerices.Push(ctVertices); + + // Get pointers to src and dst vertex arrays + GFXVertex *pavSrcFirst = &tt.GetVertices()[0]; + GFXVertex *pavDstFirst = &_avLerpedVerices[0]; + GFXVertex *pavSrc = &pavSrcFirst[0]; + GFXVertex *pavDst = &pavDstFirst[0]; + + INDEX iFacing=0; + // for each vertex column + for(INDEX iy=0;iy> Fix this") + if(((ix+iy)/2)%2) { + // if(iFacing&1) + // Second vertex (diagonal one) is lerped between topright and bottom left vertices + Lerp(pavDst[1],pavSrc[1],pavSrc[-tt.tt_ctLodVtxX+2],pavSrc[tt.tt_ctLodVtxX],fLerpFactor); + } else { + // Second vertex (diagonal one) is lerped between topleft and bottom right vertices + Lerp(pavDst[1],pavSrc[1],pavSrc[-tt.tt_ctLodVtxX],pavSrc[tt.tt_ctLodVtxX+2],fLerpFactor); + } + iFacing++; + // Increment vertex pointers + pavDst+=2; + pavSrc+=2; + } + // Last vertex in row is lerped between top and bottom vertices (same as first in row) + Lerp(pavDst[0],pavSrc[0],pavSrc[-tt.tt_ctLodVtxX],pavSrc[tt.tt_ctLodVtxX],fLerpFactor); + } + // Increment vertex pointers + pavDst++; + pavSrc++; + } + + pavDst--; + pavSrc--; +/* + // Copy border vertices + GFXVertex *pvBorderDst = pavDst; + GFXVertex *pvBorderSrc = pavSrc; + + for(INDEX ivx=tt.tt_ctNonBorderVertices;ivx=0) { + CTerrainTile &ttTop = _ptrTerrain->tr_attTiles[iTopNeigbour]; + const FLOAT &fLerpFactor = ttTop.tt_fLodLerpFactor; + // Get source vertex pointer in top neighbour (vertex in bottom left corner of top neighbour) + const INDEX iSrcVtx = ttTop.tt_ctLodVtxX * (ttTop.tt_ctLodVtxY-1); + GFXVertex *pavSrc = &ttTop.GetVertices()[iSrcVtx]; + // Calculate num of vertices that needs to be lerped + const INDEX ctLerps = (ttTop.tt_ctLodVtxX-1)/2; + + // is top tile in same lod as this tile and has smaller or equal lerp factor + if(tt.tt_iLod==ttTop.tt_iLod && fLerpFactor<=tt.tt_fLodLerpFactor) { + // Get destination vertex pointer in this tile (first vertex in top left corner of this tile - first vertex in array) + const INDEX iDstVtx = 0; + GFXVertex *pavDst = &pavDstFirst[iDstVtx]; + + // for each vertex in bottom row of top tile that needs to be lerped + for(INDEX ivx=0;ivxttTop.tt_iLod) { + const INDEX iVtxDiff = (ttTop.tt_ctLodVtxX-1) / (tt.tt_ctLodVtxX-1); + // Get destination vertex pointer to copy vertices from top neighbour (first vertex in top left corner of this tile - first vertex in array) + // Get destination vertex pointer to lerp vertices from top neighbour (first vertex added as additional top border vertex) + const INDEX iDstCopyVtx = 0; + const INDEX iDstLerpVtx = tt.tt_iFirstBorderVertex[NB_TOP]; + GFXVertex *pavDstCopy = &pavDstFirst[iDstCopyVtx]; + GFXVertex *pavDstLerp = &pavDstFirst[iDstLerpVtx]; + + // if diference is in one lod + if(iVtxDiff==2) { + // for each vertex in bottom row of top tile that needs to be lerped + for(INDEX ivx=0;ivx=0) { + CTerrainTile &ttBottom = _ptrTerrain->tr_attTiles[iBottomNeigbour]; + const FLOAT &fLerpFactor = ttBottom.tt_fLodLerpFactor; + // Get source vertex pointer in bottom neighbour (vertex in top left corner of bottom neighbour - first vertex in array) + const INDEX iSrcVtx = 0; + GFXVertex *pavSrc = &ttBottom.GetVertices()[iSrcVtx]; + // Calculate num of vertices that needs to be lerped + const INDEX ctLerps = (ttBottom.tt_ctLodVtxX-1)/2; + + // is bottom tile in same lod as this tile and has smaller lerp factor + if(tt.tt_iLod==ttBottom.tt_iLod && fLerpFactorttBottom.tt_iLod) { + const INDEX iVtxDiff = (ttBottom.tt_ctLodVtxX-1) / (tt.tt_ctLodVtxX-1); + // Get destination vertex pointer to copy vertices from bottom neighbour (first vertex in bottom left corner of this tile) + // Get destination vertex pointer to lerp vertices from bottom neighbour (first vertex added as additional bottom border vertex) + const INDEX iDstCopyVtx = tt.tt_ctLodVtxX * (tt.tt_ctLodVtxY-1); + const INDEX iDstLerpVtx = tt.tt_iFirstBorderVertex[NB_BOTTOM]; + GFXVertex *pavDstCopy = &pavDstFirst[iDstCopyVtx]; + GFXVertex *pavDstLerp = &pavDstFirst[iDstLerpVtx]; + + // if diference is in one lod + if(iVtxDiff==2) { + // for each vertex in top row of bottom tile that needs to be lerped + for(INDEX ivx=0;ivx=0) { + CTerrainTile &ttLeft = _ptrTerrain->tr_attTiles[iLeftNeigbour]; + const FLOAT &fLerpFactor = ttLeft.tt_fLodLerpFactor; + // Get source vertex pointer in left neighbour (vertex in top right corner of left neighbour) + const INDEX iSrcVtx = ttLeft.tt_ctLodVtxX-1; + const INDEX iSrcStep = ttLeft.tt_ctLodVtxX; + GFXVertex *pavSrc = &ttLeft.GetVertices()[iSrcVtx]; + // Calculate num of vertices that needs to be lerped + const INDEX ctLerps = (ttLeft.tt_ctLodVtxX-1)/2; + + // is left tile in same lod as this tile and has smaller or equal lerp factor + if(tt.tt_iLod==ttLeft.tt_iLod && fLerpFactor<=tt.tt_fLodLerpFactor) { + // Get destination vertex pointer in this tile (first vertex in top left corner of this tile - first vertex in array) + const INDEX iDstVtx = 0; + const INDEX iDstStep = tt.tt_ctLodVtxX; + GFXVertex *pavDst = &pavDstFirst[iDstVtx]; + + // for each vertex in last column of left tile that needs to be lerped + for(INDEX ivx=0;ivxttLeft.tt_iLod) { + const INDEX iVtxDiff = (ttLeft.tt_ctLodVtxX-1) / (tt.tt_ctLodVtxX-1); + // Get destination vertex pointer to copy vertices from left neighbour (first vertex in top left corner of this tile - first vertex in array) + // Get destination vertex pointer to lerp vertices from left neighbour (first vertex added as additional left border vertex) + const INDEX iDstCopyVtx = 0; + const INDEX iDstLerpVtx = tt.tt_iFirstBorderVertex[NB_LEFT]; + const INDEX iDstStep = tt.tt_ctLodVtxX; + GFXVertex *pavDstCopy = &pavDstFirst[iDstCopyVtx]; + GFXVertex *pavDstLerp = &pavDstFirst[iDstLerpVtx]; + + // if diference is in one lod + if(iVtxDiff==2) { + // for each vertex in last column of left tile that needs to be lerped + for(INDEX ivx=0;ivx=0) { + CTerrainTile &ttRight = _ptrTerrain->tr_attTiles[iRightNeigbour]; + const FLOAT &fLerpFactor = ttRight.tt_fLodLerpFactor; + // Get source vertex pointer in right neighbour (vertex in top left corner of left neighbour - first vertex in array) + const INDEX iSrcVtx = 0; + const INDEX iSrcStep = ttRight.tt_ctLodVtxX; + GFXVertex *pavSrc = &ttRight.GetVertices()[iSrcVtx]; + // Calculate num of vertices that needs to be lerped + const INDEX ctLerps = (ttRight.tt_ctLodVtxX-1)/2; + + // is right tile in same lod as this tile and has smaller lerp factor + if(tt.tt_iLod==ttRight.tt_iLod && fLerpFactorttRight.tt_iLod) { + const INDEX iVtxDiff = (ttRight.tt_ctLodVtxX-1) / (tt.tt_ctLodVtxX-1); + // Get destination vertex pointer to copy vertices from right neighbour (first vertex in top right corner of this tile) + // Get destination vertex pointer to lerp vertices from right neighbour (first vertex added as additional right border vertex) + const INDEX iDstCopyVtx = tt.tt_ctLodVtxX-1; + const INDEX iDstLerpVtx = tt.tt_iFirstBorderVertex[NB_RIGHT]; + const INDEX iDstStep = tt.tt_ctLodVtxX; + GFXVertex *pavDstCopy = &pavDstFirst[iDstCopyVtx]; + GFXVertex *pavDstLerp = &pavDstFirst[iDstLerpVtx]; + + // if diference is in one lod + if(iVtxDiff==2) { + // for each vertex in first column of right tile that needs to be lerped + for(INDEX ivx=0;ivxtr_attTiles[iTerrainTile]; + CTerrainLayer &tl = _ptrTerrain->tr_atlLayers[iTileLayer]; + TileLayer &ttl = tt.GetTileLayers()[iTileLayer]; + + ASSERT(tt.tt_iLod==0); + + const INDEX ctVertices = ttl.tl_avVertices.Count(); + const FLOAT &fLerpFactor = tt.tt_fLodLerpFactor; + + // Allocate memory for all vertices + _avLerpedTileLayerVertices.PopAll(); + _avLerpedTileLayerVertices.Push(ctVertices); + + // Get pointers to src and dst vertex arrays + GFXVertex *pavSrcFirst = &ttl.tl_avVertices[0]; + GFXVertex *pavDstFirst = &_avLerpedTileLayerVertices[0]; + GFXVertex *pavSrc = &pavSrcFirst[0]; + GFXVertex *pavDst = &pavDstFirst[0]; + + INDEX ctQuadsPerRow = _ptrTerrain->tr_ctQuadsInTileRow; + INDEX ctVerticesInRow = _ptrTerrain->tr_ctQuadsInTileRow*2; + INDEX iFacing = 1; + + // Minimize popping on vertices using 4 quads, 2 from current row and 2 from next row in same tile + for(INDEX iz=0;iz=0) { + CTerrainTile &ttTop = _ptrTerrain->tr_attTiles[iTopNeighbour]; + const FLOAT fTopLerpFactor = ttTop.tt_fLodLerpFactor; + // is top tile in highest lod and has smaller or equal lerp factor + if(ttTop.tt_iLod==0 && fTopLerpFactor<=fLerpFactor) { + TileLayer &ttl = ttTop.GetTileLayers()[iTileLayer]; + INDEX iFirstVertex = ctVerticesInRow*(ctVerticesInRow-2); + GFXVertex *pavSrc = &ttl.tl_avVertices[iFirstVertex]; + GFXVertex *pavDst = &_avLerpedTileLayerVertices[0]; + // for each quad + for(INDEX ix=0;ix=0) { + CTerrainTile &ttBottom = _ptrTerrain->tr_attTiles[iBottomNeighbour]; + const FLOAT fBottomLerpFactor = ttBottom.tt_fLodLerpFactor; + // is bottom tile in highest lod and has smaller lerp factor + if(ttBottom.tt_iLod==0 && fBottomLerpFactor=0) { + CTerrainTile &ttLeft = _ptrTerrain->tr_attTiles[iLeftNeighbour]; + const FLOAT fLeftLerpFactor = ttLeft.tt_fLodLerpFactor; + // is left tile in highest lod and has smaller or equal left factor + if(ttLeft.tt_iLod==0 && fLeftLerpFactor<=fLerpFactor) { + TileLayer &ttl = ttLeft.GetTileLayers()[iTileLayer]; + INDEX iFirstVertex = ctVerticesInRow*2-8; + GFXVertex *pavSrc = &ttl.tl_avVertices[iFirstVertex]; + GFXVertex *pavDst = &_avLerpedTileLayerVertices[0]; + // for each quad + for(INDEX ix=0;ix=0) { + CTerrainTile &ttRight = _ptrTerrain->tr_attTiles[iRightNeighbour]; + const FLOAT fRightLerpFactor = ttRight.tt_fLodLerpFactor; + // is right tile in highest lod and has smaller left factor + if(ttRight.tt_iLod==0 && fRightLerpFactortr_tdTopMap.SetAsCurrent(); + + GFXVertex4 *pavVertices = &_avDelayedVertices[0]; + GFXTexCoord *pauvTexCoords = &_auvDelayedTexCoords[0]; + GFXTexCoord *pauvShadowMapTC = &_auvDelayedShadowMapTC[0]; + INDEX *paiIndices = &_aiDelayedIndices[0]; + INDEX ctVertices = _avDelayedVertices.Count(); + INDEX ctIndices = _aiDelayedIndices.Count(); + + // Prepare white color array + FillConstColorArray(ctVertices); + GFXColor *pacolColors = &_acolVtxConstColors[0]; + + gfxEnableAlphaTest(); + gfxDisableBlend(); + gfxSetVertexArray(pavVertices,ctVertices); + gfxSetTexCoordArray(pauvTexCoords, FALSE); + gfxSetColorArray(pacolColors); + gfxLockArrays(); + gfxDrawElements(ctIndices,paiIndices); + gfxDisableAlphaTest(); + _ctTris +=ctIndices/2; + + // if shadows are visible + if(_wrpWorldRenderPrefs.wrp_shtShadows!=CWorldRenderPrefs::SHT_NONE) { + gfxDepthFunc(GFX_EQUAL); + + gfxBlendFunc(GFX_DST_COLOR,GFX_SRC_COLOR); + gfxEnableBlend(); + gfxSetTexCoordArray(pauvShadowMapTC, FALSE); + _ptrTerrain->tr_tdShadowMap.SetAsCurrent(); + gfxDrawElements(ctIndices,paiIndices); + gfxDepthFunc(GFX_LESS_EQUAL); + } + + if(_ptrTerrain->GetFlags()&TR_HAS_FOG) { + RenderFogLayer(-1); + } + if(_ptrTerrain->GetFlags()&TR_HAS_HAZE) { + RenderHazeLayer(-1); + } + gfxUnlockArrays(); + + // Popall delayed arrays + _avDelayedVertices.PopAll(); + _auvDelayedTexCoords.PopAll(); + _auvDelayedShadowMapTC.PopAll(); + _aiDelayedIndices.PopAll(); +} + +static void BatchTile(INDEX itt) +{ + CTerrainTile &tt = _ptrTerrain->tr_attTiles[itt]; + ASSERT(tt.GetVertices().Count()==9); + ASSERT(tt.GetIndices().Count()==24); + + INDEX ctDelayedVertices = _avDelayedVertices.Count(); + + GFXVertex4 *pavVertices = &tt.GetVertices()[0]; + GFXTexCoord *pauvTexCoords = &tt.GetTexCoords()[0]; + GFXTexCoord *pauvShadowMapTC = &tt.GetShadowMapTC()[0]; + INDEX *paiIndices = &tt.GetIndices()[0]; + + GFXVertex4 *pavDelVertices = _avDelayedVertices.Push(9); + GFXTexCoord *pauvDelTexCoords = _auvDelayedTexCoords.Push(9); + GFXTexCoord *pauvDelShadowMapTC = _auvDelayedShadowMapTC.Push(9); + INDEX *paiDelIndices = _aiDelayedIndices.Push(24); + + // for each vertex in tile + for(INDEX ivx=0;ivx<9;ivx++) { + // copy vertex, texcoord & shadow map texcoord to delayed array + pavDelVertices[ivx] = pavVertices[ivx]; + pauvDelTexCoords[ivx] = pauvTexCoords[ivx]; + pauvDelShadowMapTC[ivx] = pauvShadowMapTC[ivx]; + } + // for each index in tile + for(INDEX iind=0;iind<24;iind++) { + // reindex indice for new arrays + paiDelIndices[iind] = paiIndices[iind] + ctDelayedVertices; + } + + _ctDelayedNodes++; +} + +// returns haze/fog value in vertex +static FLOAT3D _vFViewerObj, _vHDirObj; +static FLOAT _fFogAddZ, _fFogAddH; +static FLOAT _fHazeAdd; + +// check vertex against haze +#pragma message(">> no asm in GetHazeMapInVertex and GetFogMapInVertex") +static void GetHazeMapInVertex( GFXVertex4 &vtx, GFXTexCoord &txHaze) +{ + const FLOAT fD = vtx.x*_vViewerObj(1) + vtx.y*_vViewerObj(2) + vtx.z*_vViewerObj(3); + txHaze.u = (fD+_fHazeAdd) * _haze_fMul; + txHaze.v = 0.0f; +} + +static void GetFogMapInVertex( GFXVertex4 &vtx, GFXTexCoord &tex) +{ + const FLOAT fD = vtx.x*_vFViewerObj(1) + vtx.y*_vFViewerObj(2) + vtx.z*_vFViewerObj(3); + const FLOAT fH = vtx.x*_vHDirObj(1) + vtx.y*_vHDirObj(2) + vtx.z*_vHDirObj(3); + tex.u = (fD+_fFogAddZ) * _fog_fMulZ; + tex.v = (fH+_fFogAddH) * _fog_fMulH; +} + +static CStaticStackArray _atcHaze; +static CStaticStackArray _acolHaze; + +static void RenderFogLayer(INDEX itt) +{ + FLOATmatrix3D &mViewer = _aprProjection->pr_ViewerRotationMatrix; + FLOAT3D vObjPosition = _ptrTerrain->tr_penEntity->en_plPlacement.pl_PositionVector; + + // get viewer -z in object space + _vFViewerObj = FLOAT3D(0,0,-1) * !_mObjectToView; + // get fog direction in object space + _vHDirObj = _fog_vHDirAbs * !(!mViewer*_mObjectToView); + // get viewer offset + _fFogAddZ = _vViewer(1) * (vObjPosition(1) - _aprProjection->pr_vViewerPosition(1)); + _fFogAddZ += _vViewer(2) * (vObjPosition(2) - _aprProjection->pr_vViewerPosition(2)); + _fFogAddZ += _vViewer(3) * (vObjPosition(3) - _aprProjection->pr_vViewerPosition(3)); + // get fog offset + _fFogAddH = (_fog_vHDirAbs % vObjPosition) + _fog_fp.fp_fH3; + + GFXVertex *pvVtx; + INDEX *piIndices; + INDEX ctVertices; + INDEX ctIndices; + // if this is tile + if(itt>=0) { + CTerrainTile &tt = _ptrTerrain->tr_attTiles[itt]; + pvVtx = &tt.GetVertices()[0]; + piIndices = &tt.GetIndices()[0]; + ctVertices = tt.GetVertices().Count(); + ctIndices = tt.GetIndices().Count(); + // else this are batched tiles + } else { + pvVtx = &_avDelayedVertices[0]; + piIndices = &_aiDelayedIndices[0]; + ctVertices = _avDelayedVertices.Count(); + ctIndices = _aiDelayedIndices.Count(); + } + + GFXTexCoord *pfFogTC = _atcHaze.Push(ctVertices); + GFXColor *pcolFog = _acolHaze.Push(ctVertices); + + const COLOR colF = AdjustColor( _fog_fp.fp_colColor, _slTexHueShift, _slTexSaturation); + GFXColor colFog(colF); + + // for each vertex in tile + for(INDEX ivx=0;ivxtr_penEntity->en_plPlacement.pl_PositionVector; + + _fHazeAdd = -_haze_hp.hp_fNear; + _fHazeAdd += _vViewer(1) * (vObjPosition(1) - _aprProjection->pr_vViewerPosition(1)); + _fHazeAdd += _vViewer(2) * (vObjPosition(2) - _aprProjection->pr_vViewerPosition(2)); + _fHazeAdd += _vViewer(3) * (vObjPosition(3) - _aprProjection->pr_vViewerPosition(3)); + + GFXVertex *pvVtx; + INDEX *piIndices; + INDEX ctVertices; + INDEX ctIndices; + // if this is tile + if(itt>=0) { + CTerrainTile &tt = _ptrTerrain->tr_attTiles[itt]; + pvVtx = &tt.GetVertices()[0]; + piIndices = &tt.GetIndices()[0]; + ctVertices = tt.GetVertices().Count(); + ctIndices = tt.GetIndices().Count(); + // else this are batched tiles + } else { + pvVtx = &_avDelayedVertices[0]; + piIndices = &_aiDelayedIndices[0]; + ctVertices = _avDelayedVertices.Count(); + ctIndices = _aiDelayedIndices.Count(); + } + + GFXTexCoord *pfHazeTC = _atcHaze.Push(ctVertices); + GFXColor *pcolHaze = _acolHaze.Push(ctVertices); + + const COLOR colH = AdjustColor( _haze_hp.hp_colColor, _slTexHueShift, _slTexSaturation); + GFXColor colHaze(colH); + // for each vertex in tile + for(INDEX ivx=0;ivxtr_attTiles[itt]; + INDEX ctVertices = tt.GetVertices().Count(); + + extern INDEX ter_bOptimizeRendering; + // if tile is in posible lowest lod and doesn't have any border vertices + if(ter_bOptimizeRendering && tt.GetFlags()&TT_IN_LOWEST_LOD) { + // delay tile rendering + BatchTile(itt); + return; + } + + GFXVertex4 *pavVertices; + // if vertex lerping is requested + if(ter_bLerpVertices==1) { + // Prepare smoth vertices + PrepareSmothVertices(itt); + pavVertices = &_avLerpedVerices[0]; + } else { + // use non smoth vertices + pavVertices = &tt.GetVertices()[0]; + } + + // if tile is in highest lod + if(tt.tt_iLod==0) { + gfxBlendFunc(GFX_SRC_ALPHA, GFX_INV_SRC_ALPHA); + gfxSetVertexArray(pavVertices,ctVertices); + + gfxLockArrays(); + // for each tile layer + INDEX cttl= tt.GetTileLayers().Count(); + for(INDEX itl=0;itltr_atlLayers[itl]; + // if layer isn't visible + if(!tl.tl_bVisible) { + continue; // skip it + } + + TileLayer &ttl = tt.GetTileLayers()[itl]; + + // Set tile stretch + Matrix12 m12; + SetMatrixDiagonal(m12,tl.tl_fStretchX); + gfxSetTextureMatrix2(&m12); + + // Set tile blend mode + if(tl.tl_fSmoothness==0) { + gfxDisableBlend(); + gfxEnableAlphaTest(); + } else { + gfxEnableBlend(); + gfxDisableAlphaTest(); + } + + // if this tile has any polygons in this layer + INDEX ctIndices = ttl.tl_auiIndices.Count(); + if(ctIndices>0) { + gfxSetTextureWrapping(GFX_REPEAT,GFX_REPEAT); + tl.tl_ptdTexture->SetAsCurrent(); + + // if this is tile layer + if(tl.tl_ltType==LT_TILE) { + gfxUnlockArrays(); + GFXVertex4 *pavLayerVertices; + if(ter_bLerpVertices==1) { + PrepareSmothVerticesOnTileLayer(itt,itl); + pavLayerVertices = &_avLerpedTileLayerVertices[0]; + } else { + pavLayerVertices = &ttl.tl_avVertices[0]; + } + gfxSetVertexArray(pavLayerVertices,ttl.tl_avVertices.Count()); + gfxLockArrays(); + // gfxSetColorArray(&ttl.tl_acColors[0]); + gfxSetTexCoordArray(&ttl.tl_atcTexCoords[0], FALSE); + + + // set wireframe mode + /* + gfxEnableDepthBias(); + gfxPolygonMode(GFX_LINE); + gfxDisableTexture();*/ + gfxSetConstantColor(0xFFFFFFFF); + + // Draw tiled layer + gfxDrawElements(ttl.tl_auiIndices.Count(),&ttl.tl_auiIndices[0]); + _ctTris +=ttl.tl_auiIndices.Count()/2; + + /* + // set fill mode + gfxDisableDepthBias(); + gfxPolygonMode(GFX_FILL);*/ + + // Set old vertex array + gfxUnlockArrays(); + gfxSetVertexArray(pavVertices,ctVertices); + gfxLockArrays(); + // if this is normal layer + } else { + // render layer + gfxSetColorArray(&ttl.tl_acColors[0]); + gfxSetTexCoordArray(&ttl.tl_atcTexCoords[0], FALSE); + gfxDrawElements(ctIndices,&ttl.tl_auiIndices[0]); + _ctTris +=ctIndices/2; + } + } + } + gfxSetTextureMatrix2(NULL); + INDEX ctIndices = tt.GetIndices().Count(); + if(ctIndices>0) { + INDEX *paiIndices = &tt.GetIndices()[0]; + + // if detail map exists + if(_ptrTerrain->tr_ptdDetailMap!=NULL) { + gfxSetTextureWrapping(GFX_REPEAT,GFX_REPEAT); + gfxDisableAlphaTest(); + shaBlendFunc( GFX_DST_COLOR, GFX_SRC_COLOR); + gfxEnableBlend(); + gfxSetTexCoordArray(&tt.GetDetailTC()[0], FALSE); + _ptrTerrain->tr_ptdDetailMap->SetAsCurrent(); + gfxDrawElements(ctIndices,paiIndices); + } + + // if shadows are visible + if(_wrpWorldRenderPrefs.wrp_shtShadows!=CWorldRenderPrefs::SHT_NONE) { + gfxDisableAlphaTest(); + shaBlendFunc( GFX_DST_COLOR, GFX_SRC_COLOR); + gfxEnableBlend(); + gfxSetTextureWrapping(GFX_CLAMP,GFX_CLAMP); + gfxSetTexCoordArray(&tt.GetShadowMapTC()[0], FALSE); + _ptrTerrain->tr_tdShadowMap.SetAsCurrent(); + gfxDrawElements(ctIndices,paiIndices); + } + } + // if tile is not in highest lod + } else { + gfxSetTextureWrapping(GFX_CLAMP,GFX_CLAMP); + // if tile is in lowest lod + if(tt.tt_iLod == _ptrTerrain->tr_iMaxTileLod) { + // use terrains global top map + _ptrTerrain->tr_tdTopMap.SetAsCurrent(); + // else tile is in some midle lod + } else { + // use its own topmap + tt.GetTopMap()->SetAsCurrent(); + } + + // Render tile + INDEX ctIndices = tt.GetIndices().Count(); + gfxEnableAlphaTest(); + gfxDisableBlend(); + gfxSetVertexArray(pavVertices,ctVertices); + gfxSetTexCoordArray(&tt.GetTexCoords()[0], FALSE); + FillConstColorArray(ctVertices); + gfxSetColorArray(&_acolVtxConstColors[0]); + gfxLockArrays(); + gfxDrawElements(ctIndices,&tt.GetIndices()[0]); + _ctTris +=ctIndices/2; + gfxDisableAlphaTest(); + + // if shadows are visible + if(_wrpWorldRenderPrefs.wrp_shtShadows!=CWorldRenderPrefs::SHT_NONE) { + gfxDepthFunc(GFX_EQUAL); + INDEX ctIndices = tt.GetIndices().Count(); + INDEX *paiIndices = &tt.GetIndices()[0]; + + gfxSetTextureWrapping(GFX_CLAMP,GFX_CLAMP); + gfxBlendFunc(GFX_DST_COLOR,GFX_SRC_COLOR); + gfxEnableBlend(); + gfxSetTexCoordArray(&tt.GetShadowMapTC()[0], FALSE); + _ptrTerrain->tr_tdShadowMap.SetAsCurrent(); + gfxDrawElements(ctIndices,paiIndices); + gfxDepthFunc(GFX_LESS_EQUAL); + } + } + + if(_ptrTerrain->GetFlags()&TR_HAS_FOG) { + RenderFogLayer(itt); + } + if(_ptrTerrain->GetFlags()&TR_HAS_HAZE) { + RenderHazeLayer(itt); + } + + gfxUnlockArrays(); +} + +// Draw one quad tree node ( draws terrain tile if leaf node ) +static void DrawQuadTreeNode(INDEX iqtn) +{ + ASSERT(_ptrTerrain!=NULL); + CEntity *pen = _ptrTerrain->tr_penEntity; + QuadTreeNode &qtn = _ptrTerrain->tr_aqtnQuadTreeNodes[iqtn]; + + FLOATmatrix3D &mAbsToView = _aprProjection->pr_ViewerRotationMatrix; + FLOATobbox3D obbox = FLOATobbox3D( qtn.qtn_aabbox, + (pen->en_plPlacement.pl_PositionVector-_aprProjection->pr_vViewerPosition)*mAbsToView, mAbsToView*pen->en_mRotation); + + INDEX iFrustumTest = _aprProjection->TestBoxToFrustum(obbox); + if(iFrustumTest!=(-1)) { + // is this leaf node + if(qtn.qtn_iTileIndex != -1) { + _ctNodesVis++; + // draw terrain tile for this node + RenderTile(qtn.qtn_iTileIndex); + // this node has some children + } else { + for(INDEX iqc=0;iqc<4;iqc++) { + INDEX iChildNode = qtn.qtn_iChild[iqc]; + // if child node exists + if(iChildNode != -1) { + // draw child node + DrawQuadTreeNode(qtn.qtn_iChild[iqc]); + } + } + } + } +} + +// Render one terrain +void RenderTerrain(void) +{ + ASSERT(_ptrTerrain!=NULL); + ASSERT(_ptrTerrain->tr_penEntity!=NULL); + + _ctNodesVis = 0; + _ctTris = 0; + _ctDelayedNodes = 0; + // draw node from last level + INDEX ctqtl = _ptrTerrain->tr_aqtlQuadTreeLevels.Count(); + QuadTreeLevel &qtl = _ptrTerrain->tr_aqtlQuadTreeLevels[ctqtl-1]; + DrawQuadTreeNode(qtl.qtl_iFirstNode); + + // if any delayed tiles + if(_ctDelayedNodes>0) { + // Draw delayed tiles + RenderBatchedTiles(); + } + + CEntity *pen = _ptrTerrain->tr_penEntity; + + extern void ShowRayPath(CDrawPort *pdp); + ShowRayPath(_pdp); +/* + + extern CStaticStackArray _avExtVertices; + extern CStaticStackArray _aiExtIndices; + + extern FLOATaabbox3D _bboxDrawOne; + extern FLOATaabbox3D _bboxDrawTwo; + #pragma message(">> Remove gfxDrawWireBox") + + FLOATaabbox3D bboxAllTerrain; + extern FLOAT3D _vHitBegin; + extern FLOAT3D _vHitEnd; + extern FLOAT3D _vHitExact; + _ptrTerrain->GetAllTerrainBBox(bboxAllTerrain); + gfxDrawWireBox(bboxAllTerrain,0xFFFF00FF); + + gfxEnableDepthBias(); + gfxDisableDepthTest(); + _pdp->DrawPoint3D(_vHitBegin,0x00FF00FF,8); + _pdp->DrawPoint3D(_vHitEnd,0xFF0000FF,8); + _pdp->DrawPoint3D(_vHitExact,0x00FFFF,8); + + _pdp->DrawLine3D(_vHitBegin,FLOAT3D(_vHitEnd(1),_vHitBegin(2),_vHitEnd(3)),0x00FF00FF); + _pdp->DrawLine3D(FLOAT3D(_vHitBegin(1),_vHitEnd(2),_vHitBegin(3)),_vHitEnd,0xFF0000FF); + _pdp->DrawLine3D(_vHitBegin,_vHitEnd,0xFFFF00FF); + gfxEnableDepthTest(); + gfxDisableDepthBias(); +*/ + + //gfxDrawWireBox(_bboxDrawOne,0xFF0000FF); + //gfxDrawWireBox(_bboxDrawTwo,0x0000FFFF); + //gfxDrawWireBox(_bboxDrawNextFrame,0xFFFFFFFF); +} + +// Render one tile in wireframe mode +static void RenderWireTile(INDEX itt) +{ + ASSERT(_ptrTerrain!=NULL); + CTerrainTile &tt = _ptrTerrain->tr_attTiles[itt]; + INDEX ctVertices = tt.GetVertices().Count(); + + GFXVertex4 *pavVertices; + if(ter_bLerpVertices) { + PrepareSmothVertices(itt); + pavVertices = &_avLerpedVerices[0]; + } else { + pavVertices = &tt.GetVertices()[0]; + } + + INDEX ctIndices = tt.GetIndices().Count(); + if(ctIndices>0) { + gfxDisableBlend(); + gfxDisableTexture(); + gfxSetConstantColor(_colTerrainEdges); + gfxSetVertexArray(pavVertices,ctVertices); + gfxLockArrays(); + gfxDrawElements(ctIndices,&tt.GetIndices()[0]); + gfxUnlockArrays(); + } +} + +// Draw one quad tree node ( draws terrain tile in wireframe mode if leaf node ) +static void DrawWireQuadTreeNode(INDEX iqtn) +{ + ASSERT(_ptrTerrain!=NULL); + CEntity *pen = _ptrTerrain->tr_penEntity; + QuadTreeNode &qtn = _ptrTerrain->tr_aqtnQuadTreeNodes[iqtn]; + + FLOATmatrix3D &mAbsToView = _aprProjection->pr_ViewerRotationMatrix; + FLOATobbox3D obbox = FLOATobbox3D( qtn.qtn_aabbox, + (pen->en_plPlacement.pl_PositionVector-_aprProjection->pr_vViewerPosition)*mAbsToView, mAbsToView*pen->en_mRotation); + + INDEX iFrustumTest = _aprProjection->TestBoxToFrustum(obbox); + if(iFrustumTest!=(-1)) { + // is this leaf node + if(qtn.qtn_iTileIndex != -1) { + _ctNodesVis++; + // draw terrain tile for this node + RenderWireTile(qtn.qtn_iTileIndex); + // this node has some children + } else { + for(INDEX iqc=0;iqc<4;iqc++) { + INDEX iChildNode = qtn.qtn_iChild[iqc]; + // if child node exists + if(iChildNode != -1) { + // draw child node + DrawWireQuadTreeNode(qtn.qtn_iChild[iqc]); + } + } + } + } +} + +// Render one terrain in wireframe mode +void RenderTerrainWire(COLOR &colEdges) +{ + // set wireframe mode + gfxEnableDepthBias(); + gfxPolygonMode(GFX_LINE); + + // remember edges color + _colTerrainEdges = colEdges; + + ASSERT(_ptrTerrain!=NULL); + // draw last node + INDEX ctqtl = _ptrTerrain->tr_aqtlQuadTreeLevels.Count(); + QuadTreeLevel &qtl = _ptrTerrain->tr_aqtlQuadTreeLevels[ctqtl-1]; + DrawWireQuadTreeNode(qtl.qtl_iFirstNode); + + // set fill mode + gfxDisableDepthBias(); + gfxPolygonMode(GFX_FILL); +} + +// Draw terrain quad tree +void DrawQuadTree(void) +{ + ASSERT(_ptrTerrain!=NULL); + QuadTreeLevel &qtl = _ptrTerrain->tr_aqtlQuadTreeLevels[0]; + gfxDisableTexture(); + // for each quad tree node + for(INDEX iqtn=qtl.qtl_iFirstNode;iqtntr_aqtnQuadTreeNodes[iqtn]; + gfxDrawWireBox(qtn.qtn_aabbox,0x00FF00FF); + } +} + +void DrawSelectedVertices(GFXVertex *pavVertices, GFXColor *pacolColors, INDEX ctVertices) +{ + gfxEnableDepthBias(); + // for each vertex + for(INDEX ivx=0;ivxDrawPoint3D(FLOAT3D(vtx.x,vtx.y,vtx.z),ByteSwap(col.abgr),3); + } + gfxDisableDepthBias(); +} + +// TEMP - Draw one AABBox +void gfxDrawWireBox(FLOATaabbox3D &bbox, COLOR col) +{ + FLOAT3D vMinVtx = bbox.Min(); + FLOAT3D vMaxVtx = bbox.Max(); + // fill vertex array so it represents bounding box + FLOAT3D vBoxVtxs[8]; + vBoxVtxs[0] = FLOAT3D( vMinVtx(1), vMinVtx(2), vMinVtx(3)); + vBoxVtxs[1] = FLOAT3D( vMaxVtx(1), vMinVtx(2), vMinVtx(3)); + vBoxVtxs[2] = FLOAT3D( vMaxVtx(1), vMinVtx(2), vMaxVtx(3)); + vBoxVtxs[3] = FLOAT3D( vMinVtx(1), vMinVtx(2), vMaxVtx(3)); + vBoxVtxs[4] = FLOAT3D( vMinVtx(1), vMaxVtx(2), vMinVtx(3)); + vBoxVtxs[5] = FLOAT3D( vMaxVtx(1), vMaxVtx(2), vMinVtx(3)); + vBoxVtxs[6] = FLOAT3D( vMaxVtx(1), vMaxVtx(2), vMaxVtx(3)); + vBoxVtxs[7] = FLOAT3D( vMinVtx(1), vMaxVtx(2), vMaxVtx(3)); + + // connect vertices into lines of bounding box + INDEX iBoxLines[12][2]; + iBoxLines[ 0][0] = 0; iBoxLines[ 0][1] = 1; iBoxLines[ 1][0] = 1; iBoxLines[ 1][1] = 2; + iBoxLines[ 2][0] = 2; iBoxLines[ 2][1] = 3; iBoxLines[ 3][0] = 3; iBoxLines[ 3][1] = 0; + iBoxLines[ 4][0] = 0; iBoxLines[ 4][1] = 4; iBoxLines[ 5][0] = 1; iBoxLines[ 5][1] = 5; + iBoxLines[ 6][0] = 2; iBoxLines[ 6][1] = 6; iBoxLines[ 7][0] = 3; iBoxLines[ 7][1] = 7; + iBoxLines[ 8][0] = 4; iBoxLines[ 8][1] = 5; iBoxLines[ 9][0] = 5; iBoxLines[ 9][1] = 6; + iBoxLines[10][0] = 6; iBoxLines[10][1] = 7; iBoxLines[11][0] = 7; iBoxLines[11][1] = 4; + // for all vertices in bounding box + for( INDEX i=0; i<12; i++) { + // get starting and ending vertices of one line + FLOAT3D &v0 = vBoxVtxs[iBoxLines[i][0]]; + FLOAT3D &v1 = vBoxVtxs[iBoxLines[i][1]]; + _pdp->DrawLine3D(v0,v1,col); + } +} + diff --git a/Sources/Engine/Terrain/TerrainRender.h b/Sources/Engine/Terrain/TerrainRender.h new file mode 100644 index 0000000..94b313d --- /dev/null +++ b/Sources/Engine/Terrain/TerrainRender.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TERRAIN_RENDER_H +#define SE_INCL_TERRAIN_RENDER_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// Prepare scene for terrain render +void PrepareScene(CAnyProjection3D &apr, CDrawPort *pdp, CTerrain *ptrTerrain); +// Render one terrain +void RenderTerrain(void); +// Render one terrain in wireframe mode +void RenderTerrainWire(COLOR &colEdges); +// Regenerate terrain tile +void ReGenerateTile(INDEX itt); +// Draw terrain quad tree +void DrawQuadTree(void); +// Draw box in wireframe +void gfxDrawWireBox(FLOATaabbox3D &bbox, COLOR col); +// Draw selected vertices +void DrawSelectedVertices(GFXVertex *pavVertices, GFXColor *pacolColors, INDEX ctVertices); + +SLONG GetUsedMemoryForTileBatching(void); + +#endif \ No newline at end of file diff --git a/Sources/Engine/Terrain/TerrainTile.cpp b/Sources/Engine/Terrain/TerrainTile.cpp new file mode 100644 index 0000000..d0bb2b1 --- /dev/null +++ b/Sources/Engine/Terrain/TerrainTile.cpp @@ -0,0 +1,986 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include +#include +#include +#include + +extern CTerrain *_ptrTerrain; +extern FLOAT3D _vViewerAbs; + +#define BORDERTEST 0 + +extern CStaticStackArray _avLerpedVerices; + +CTerrainTile::CTerrainTile() +{ + tt_iIndex = -1; + tt_iArrayIndex = -1; + tt_iLod = -1; + tt_iRequestedLod = 0; + tt_ulTileFlags = 0; +} + +// Render tile +void CTerrainTile::Render(void) +{ + ASSERT(FALSE); +} + +CTerrainTile::~CTerrainTile() +{ + Clear(); +} + +// Release tile +void CTerrainTile::Clear() +{ +} + +// TEMP!!!!! +__forceinline void CTerrainTile::LerpVertexPos(GFXVertex4 &vtx, INDEX iVxTarget, INDEX iVxFirst,INDEX iVxLast) +{ + GFXVertex4 &vxFirst = GetVertices()[iVxFirst]; + GFXVertex4 &vxLast = GetVertices()[iVxLast]; + GFXVertex4 &vxTarget = GetVertices()[iVxTarget]; + + FLOAT fLerpMaxPosY = Lerp(vxFirst.y,vxLast.y,0.5f); + FLOAT fLerpResultY = Lerp(vxTarget.y,fLerpMaxPosY,tt_fLodLerpFactor); + vtx.x = vxTarget.x; + vtx.y = fLerpResultY; + vtx.z = vxTarget.z; +} + +/* + * Tile memory alloc + */ + +INDEX CTerrainTile::ChangeTileArrays(INDEX iRequestedArrayLod) +{ + // if requested lod is same as current lod + if(iRequestedArrayLod==tt_iLod) { + // Just pop all arrays + GetVertices().PopAll(); + GetTexCoords().PopAll(); + GetShadowMapTC().PopAll(); + GetIndices().PopAll(); + // if tile is in highest lod + if(tt_iLod==0) { + // pop detail uvmap + GetDetailTC().PopAll(); + // for each tile layer + INDEX cttl=GetTileLayers().Count(); + for(INDEX itl=0;itltr_aArrayHolders[iRequestedArrayLod]; + + ASSERT(tt_iArrayIndex==-1); + tt_iArrayIndex = ah.GetNewArrays(); + + // if this is first lod + if(iRequestedArrayLod==0) { + // Add tile layers + INDEX ctLayers = _ptrTerrain->tr_atlLayers.Count(); + if(ctLayers>0) { + GetTileLayers().Push(ctLayers); + } + } + return iRequestedArrayLod; +} + +void CTerrainTile::ReleaseTileArrays() +{ + // if tile had some arrays + if(tt_iArrayIndex != -1) { + // Free them + CArrayHolder &ahOld = _ptrTerrain->tr_aArrayHolders[tt_iLod]; + ahOld.FreeArrays(tt_iArrayIndex); + tt_iArrayIndex = -1; + } +} + +void CTerrainTile::EmptyTileArrays() +{ + ASSERT(tt_iArrayIndex != -1); + + CArrayHolder &ahCurrent = _ptrTerrain->tr_aArrayHolders[tt_iLod]; + ahCurrent.EmptyArrays(tt_iArrayIndex); +} + +/* + * Tile generation (TEMP) + */ + +inline void CTerrainTile::AddTriangle(INDEX iind1,INDEX iind2,INDEX iind3) +{ + // is this tile in highest lod + if(tt_iLod==0) { + + // Is this triangle visible + GFXVertex *pvx[3]; + pvx[0] = &GetVertices()[iind1]; + pvx[1] = &GetVertices()[iind2]; + pvx[2] = &GetVertices()[iind3]; + + // check if all vertices all visible + SLONG slTriangleMask = pvx[0]->shade + pvx[1]->shade + pvx[2]->shade; + if(slTriangleMask!=255*3) { + return; + } + + // Add one triangle + INDEX *pIndices = GetIndices().Push(3); + pIndices[0] = iind1; + pIndices[1] = iind2; + pIndices[2] = iind3; + + // for each layer + INDEX cttl = GetTileLayers().Count(); + for(INDEX itl=0;itltr_atlLayers[itl]; + // if this is tile layer + if(tl.tl_ltType==LT_TILE) { + continue; // skip it + } + + COLOR ul = ttl.tl_acColors[iind1].a + ttl.tl_acColors[iind2].a + ttl.tl_acColors[iind3].a; + if(ul>0) { + INDEX *pIndices = ttl.tl_auiIndices.Push(3); + pIndices[0] = iind1; + pIndices[1] = iind2; + pIndices[2] = iind3; + } + } + } else { + INDEX *pIndices = GetIndices().Push(3); + pIndices[0] = iind1; + pIndices[1] = iind2; + pIndices[2] = iind3; + } +} + +// Returns a height in heightmap +inline FLOAT GetHeight(INDEX ic,INDEX ir,INDEX iTileIndex) +{ + CTerrainTile &tt = _ptrTerrain->tr_attTiles[iTileIndex]; + // Get Y position of vertex from heightmap + INDEX icHMap = ic + tt.tt_iOffsetX*_ptrTerrain->GetQuadsPerTileRow(); + INDEX irHMap = ir + tt.tt_iOffsetZ*_ptrTerrain->GetQuadsPerTileRow(); + INDEX ivx = icHMap+irHMap*_ptrTerrain->tr_pixHeightMapWidth; + return (FLOAT)_ptrTerrain->tr_auwHeightMap[ivx]; +} + +BYTE GetVertexAlpha(INDEX ic,INDEX ir,INDEX iTileIndex,INDEX iLayer) +{ + CTerrainTile &tt = _ptrTerrain->tr_attTiles[iTileIndex]; + INDEX icHMap = ic + tt.tt_iOffsetX*_ptrTerrain->GetQuadsPerTileRow(); + INDEX irHMap = ir + tt.tt_iOffsetZ*_ptrTerrain->GetQuadsPerTileRow(); + INDEX ivx = icHMap+irHMap*_ptrTerrain->tr_pixHeightMapWidth; + CTerrainLayer &tl = _ptrTerrain->tr_atlLayers[iLayer]; + return tl.tl_aubColors[ivx]; +} + +// Returns vertex at specified position inside one tile +GFXVertex4 GetVertex(INDEX ic,INDEX ir,INDEX iTileIndex) +{ + CTerrainTile &tt = _ptrTerrain->tr_attTiles[iTileIndex]; + FLOAT fPosY = GetHeight(ic,ir,iTileIndex); + + GFXVertex4 vx; + INDEX ix = ic + tt.tt_iOffsetX*_ptrTerrain->GetQuadsPerTileRow(); + INDEX iz = ir + tt.tt_iOffsetZ*_ptrTerrain->GetQuadsPerTileRow(); + vx.x = (FLOAT)(ix); + vx.z = (FLOAT)(iz); + vx.y = fPosY; + // Fill 'shade' with edge map value + INDEX iMask = ix + iz*_ptrTerrain->tr_pixHeightMapWidth; + vx.shade = _ptrTerrain->tr_aubEdgeMap[iMask]; + + return vx; +} + +// Add vertex to array of vertices +void CTerrainTile::AddVertex(INDEX ic, INDEX ir) +{ + GFXVertex4 &vxFinal = GetVertices().Push(); + GFXTexCoord &tcShadow = GetShadowMapTC().Push(); + + GFXVertex4 &vx = GetVertex(ic,ir,tt_iIndex); + vxFinal.x = vx.x * _ptrTerrain->tr_vStretch(1); + vxFinal.y = vx.y * _ptrTerrain->tr_vStretch(2); + vxFinal.z = vx.z * _ptrTerrain->tr_vStretch(3); + vxFinal.shade = vx.shade; + + // if this tile is in highest lod + if(tt_iLod==0) { + // for each layer + INDEX cttl = GetTileLayers().Count(); + for(INDEX itl=0;itltr_atlLayers[itl]; + // Set vertex color + GFXColor &col = ttl.tl_acColors.Push(); + BYTE bAlpha = GetVertexAlpha(ic,ir,tt_iIndex,itl); + col.abgr = 0x00FFFFFF; + col.a = bAlpha; + // if this is normal layer + if(tl.tl_ltType == LT_NORMAL) { + // Set its texcoords + GFXTexCoord &tc = ttl.tl_atcTexCoords.Push(); + tc.u = (FLOAT)ic; + tc.v = (FLOAT)ir; + } + } + + GFXTexCoord &tcDetail = GetDetailTC().Push(); + tcDetail.u = ic * 2; + tcDetail.v = ir * 2; + // if tile is in lowest lod + } else if(tt_iLod==_ptrTerrain->tr_iMaxTileLod) { + GFXTexCoord &tc = GetTexCoords().Push(); + FLOAT fWidth = (_ptrTerrain->tr_pixHeightMapWidth-1); + FLOAT fHeight = (_ptrTerrain->tr_pixHeightMapHeight-1); + tc.u = vx.x / fWidth; + tc.v = vx.z / fHeight; + // tile is not in highest lod nor in lowest lod + } else { + GFXTexCoord &tc = GetTexCoords().Push(); + tc.u = ((vx.x - tt_iOffsetX * _ptrTerrain->GetQuadsPerTileRow()) / (_ptrTerrain->GetQuadsPerTileRow())); + tc.v = ((vx.z - tt_iOffsetZ * _ptrTerrain->GetQuadsPerTileRow()) / (_ptrTerrain->GetQuadsPerTileRow())); + } + + tcShadow.u = vx.x / (_ptrTerrain->tr_pixHeightMapWidth-1); + tcShadow.v = vx.z / (_ptrTerrain->tr_pixHeightMapHeight-1); +} + +void CTerrainTile::ReGenerateTileLayer(INDEX iTileLayer) +{ + FLOAT fStrX = _ptrTerrain->tr_vStretch(1); + FLOAT fStrY = _ptrTerrain->tr_vStretch(2); + FLOAT fStrZ = _ptrTerrain->tr_vStretch(3); + PIX pixHMWidth = _ptrTerrain->tr_pixHeightMapWidth; + + PIX iOffsetX = tt_iOffsetX * _ptrTerrain->tr_ctQuadsInTileRow; + PIX iOffsetZ = tt_iOffsetZ * _ptrTerrain->tr_ctQuadsInTileRow; + + INDEX ctQuadsPerRow = _ptrTerrain->tr_ctQuadsInTileRow; + + CTerrainLayer &tl = _ptrTerrain->tr_atlLayers[iTileLayer]; + TileLayer &ttl = GetTileLayers()[iTileLayer]; + INDEX ctVertices = ctQuadsPerRow*ctQuadsPerRow*4; // four vertices per one quad + INDEX ctIndices = ctQuadsPerRow*ctQuadsPerRow*6; // six indices per one quad + + ASSERT(ttl.tl_avVertices.Count()==0 && ttl.tl_atcTexCoords.Count()==0 && ttl.tl_auiIndices.Count()==0); + GFXVertex *pvtx = ttl.tl_avVertices.Push(ctVertices); + GFXTexCoord *ptc = ttl.tl_atcTexCoords.Push(ctVertices); + INDEX *pind = ttl.tl_auiIndices.Push(ctIndices); + UBYTE *pubMask = tl.tl_aubColors; + + INDEX ivx = 0; + INDEX iind = 0; + BOOL bFacing = FALSE; + INDEX iTilesInRowLog2 = FastLog2(tl.tl_ctTilesInRow); + // for each quad in tile + for(INDEX iz=0;iztr_auwHeightMap[pix] * fStrY; + pvtx[ivx ].z = (FLOAT)(iOffsetZ+iz+0)*fStrZ; + pvtx[ivx+1].x = (FLOAT)(iOffsetX+ix+1)*fStrX; + pvtx[ivx+1].y = (FLOAT)_ptrTerrain->tr_auwHeightMap[pix+1] * fStrY; + pvtx[ivx+1].z = (FLOAT)(iOffsetZ+iz+0)*fStrZ; + pvtx[ivx+2].x = (FLOAT)(iOffsetX+ix+0)*fStrX; + pvtx[ivx+2].y = (FLOAT)_ptrTerrain->tr_auwHeightMap[pix+pixHMWidth] * fStrY; + pvtx[ivx+2].z = (FLOAT)(iOffsetZ+iz+1)*fStrZ; + pvtx[ivx+3].x = (FLOAT)(iOffsetX+ix+1)*fStrX; + pvtx[ivx+3].y = (FLOAT)_ptrTerrain->tr_auwHeightMap[pix+pixHMWidth+1] * fStrY; + pvtx[ivx+3].z = (FLOAT)(iOffsetZ+iz+1)*fStrZ; + + UBYTE ubMask = pubMask[pix]; + INDEX iTile = ubMask&TL_TILE_INDEX; // First 4 bits + BOOL bFlipX = (ubMask&TL_FLIPX)>>TL_FLIPX_SHIFT; + BOOL bFlipY = (ubMask&TL_FLIPY)>>TL_FLIPY_SHIFT; + BOOL bSwapXY = (ubMask&TL_SWAPXY)>>TL_SWAPXY_SHIFT; + BOOL bVisible = (ubMask&TL_VISIBLE)>>TL_VISIBLE_SHIFT; + INDEX iTileX = iTile&(tl.tl_ctTilesInRow-1); + INDEX iTileY = iTile>>iTilesInRowLog2; + + ASSERT(iTileXGetQuadsPerTileRow()>>tt_iLod; + + // Fill middle of tile with triangles + for(ir=1;irtr_atlLayers.Count(); + for(INDEX itl=0;itltr_atlLayers[itl]; + // if this is tile layer + if(tl.tl_ltType == LT_TILE) { + // Regenerate it + ReGenerateTileLayer(itl); + } + } + } + + BOOL bAllowTopMapRegen = !(GetFlags()&TT_NO_TOPMAP_REGEN); + // if top map is allowed to be regenerated + if(bAllowTopMapRegen) { + // if tile is not in highest nor in lowest lod + if(tt_iLod>0 && tt_iLod<_ptrTerrain->tr_iMaxTileLod) { + // if top map regen is forced or tile has changed lod + BOOL bForceTopMapRegen = (GetFlags()&TT_FORCE_TOPMAP_REGEN); + if(bForceTopMapRegen || iOldLod!=tt_iLod) { + // Update tile top map + _ptrTerrain->UpdateTopMap(tt_iIndex); + // remove flag that forced top map regen + RemoveFlag(TT_FORCE_TOPMAP_REGEN); + // allow terrain to regenerete top map + _ptrTerrain->AddFlag(TR_ALLOW_TOP_MAP_REGEN); + } + } + // if not + } else { + // regenerate it next time + RemoveFlag(TT_NO_TOPMAP_REGEN); + } + + // if flag to resize quad tree node has been set + if(GetFlags()&TT_QUADTREENODE_REGEN) { + // update quad tree node + UpdateQuadTreeNode(); + // node has been updated + RemoveFlag(TT_QUADTREENODE_REGEN); + } + + INDEX ctBorderVertices = tt_ctBorderVertices[0] + tt_ctBorderVertices[1] + + tt_ctBorderVertices[2] + tt_ctBorderVertices[3]; + // if tile is in lowest lod, has not lerp factor and no border vertices + if(tt_iLod==_ptrTerrain->tr_iMaxTileLod && tt_fLodLerpFactor==0.0f && ctBorderVertices == 0) { + // mark it as available for batch rendering + AddFlag(TT_IN_LOWEST_LOD); + } else { + RemoveFlag(TT_IN_LOWEST_LOD); + } + +} + +INDEX CTerrainTile::CalculateLOD(void) +{ + QuadTreeNode &qtn = _ptrTerrain->tr_aqtnQuadTreeNodes[tt_iIndex]; + FLOAT fDistance = (qtn.qtn_aabbox.Center() - _vViewerAbs).Length() - qtn.qtn_aabbox.Size().Length() / 2; + + // if flag has been set for tile to regenerate without lod + if(GetFlags()&TT_NO_LODING) { + // set new lod at 0 + fDistance = 0; + // if tile is in highest lod, no need to regenerate texture + // AddFlag(TT_NO_TOPMAP_REGEN); + + // remove flag for no loding + RemoveFlag(TT_NO_LODING); + } + + // Calculate new lod + INDEX iNewLod = Clamp((INDEX)(fDistance/_ptrTerrain->tr_fDistFactor),(INDEX)0,_ptrTerrain->tr_iMaxTileLod); + + // if lod has changed + if(iNewLod!=tt_iLod) { + // add to regeneration queue + _ptrTerrain->AddTileToRegenQueue(tt_iIndex); + // for each neighbour + for(INDEX in=0;in<4;in++) { + INDEX ini = tt_aiNeighbours[in]; + // if neighbour is valid + if(ini>=0) { + CTerrainTile &ttNeigbour = _ptrTerrain->tr_attTiles[ini]; + // if neighbour is in higher lod + if(TRUE) { /*ttNeigbour.tt_iLod > tt.tt_iNewLod*/ + // add neighbour to regen queue + _ptrTerrain->AddTileToRegenQueue(ini); + } + } + } + // Calculate num of vertices for row and col in current lod + tt_ctLodVtxX = (_ptrTerrain->GetQuadsPerTileRow() >> iNewLod) + 1; + tt_ctLodVtxY = (_ptrTerrain->GetQuadsPerTileRow() >> iNewLod) + 1; + } + + // Calculate lerp factor + tt_fLodLerpFactor = Clamp(fDistance/_ptrTerrain->tr_fDistFactor - iNewLod,0.0f,1.0f); + // if tile is in lowest lod + if(iNewLod == _ptrTerrain->tr_iMaxTileLod) { + // no lerping for this tile + tt_fLodLerpFactor = 0.0f; + } + // return new lod + return iNewLod; +} + +// Update quad tree node +void CTerrainTile::UpdateQuadTreeNode() +{ + // resize aabox for this node + FLOATaabbox3D bboxNewBox; + GFXVertex4 *pavVertices; + INDEX *paiIndices; + INDEX ctVertices; + INDEX ctIndices; + QuadTreeNode &qtn = _ptrTerrain->tr_aqtnQuadTreeNodes[tt_iIndex]; + + // prepare box that will extract vertices (x and z of old box are allready valid) + bboxNewBox = qtn.qtn_aabbox; + bboxNewBox.minvect(2) = 0; + bboxNewBox.maxvect(2) = 65536 * _ptrTerrain->tr_vStretch(2); + + // extract vertices in box + ExtractPolygonsInBox(_ptrTerrain,bboxNewBox,&pavVertices,&paiIndices,ctVertices,ctIndices); + + // if some vertices exists + if(ctVertices>0) { + qtn.qtn_aabbox = FLOAT3D(pavVertices->x,pavVertices->y,pavVertices->z); + pavVertices++; + } else { + ASSERTALWAYS("Some vertices must exisits for tile bbox"); + } + + // for each vertex in box after first + for(INDEX ivx=1;ivxx,pavVertices->y,pavVertices->z); + pavVertices++; + } + + // notify terrain that it needs to update higher levels of quad tree + _ptrTerrain->AddFlag(TR_REBUILD_QUADTREE); +} + +// Regenerate top border +void CTerrainTile::ReGenerateTopBorder() +{ + INDEX iTopTileIndex = tt_aiNeighbours[NB_TOP]; + INDEX iTopBorderLod = tt_iLod; + // If top neighbour exists + if(iTopTileIndex!=(-1)) { + CTerrainTile &ttTop = _ptrTerrain->tr_attTiles[iTopTileIndex]; + iTopBorderLod = ttTop.tt_iRequestedLod; // !!!! iLod 2 iRequested + } +#if BORDERTEST + iTopBorderLod = 0; +#endif + + + INDEX iStep = 1<tr_attTiles[iLeftTileIndex]; + iLeftBorderLod = ttLeft.tt_iRequestedLod; + } +#if BORDERTEST + iLeftBorderLod = 0; +#endif + + + INDEX iStep = 1<tr_attTiles[iRightTileIndex]; + iRightBorderLod = ttRight.tt_iRequestedLod; + } +#if BORDERTEST + iRightBorderLod = 0; +#endif + + + INDEX iStep = 1<tr_attTiles[iBottomTileIndex]; + iBottomBorderLod = ttBottom.tt_iRequestedLod; + } +#if BORDERTEST + iBottomBorderLod = 0; +#endif + + + INDEX iStep = 1< &CTerrainTile::GetVertices() { + ASSERT(tt_iArrayIndex!=-1); + ASSERT(tt_iLod!=-1); + CArrayHolder &ah = _ptrTerrain->tr_aArrayHolders[tt_iLod]; + TileArrays &ta = ah.ah_ataTileArrays[tt_iArrayIndex]; + return ta.ta_avVertices; +} +CStaticStackArray &CTerrainTile::GetTexCoords() { + ASSERT(tt_iArrayIndex!=-1); + ASSERT(tt_iLod!=-1); + CArrayHolder &ah = _ptrTerrain->tr_aArrayHolders[tt_iLod]; + TileArrays &ta = ah.ah_ataTileArrays[tt_iArrayIndex]; + return ta.ta_auvTexCoords; +} +CStaticStackArray &CTerrainTile::GetShadowMapTC() { + ASSERT(tt_iArrayIndex!=-1); + ASSERT(tt_iLod!=-1); + CArrayHolder &ah = _ptrTerrain->tr_aArrayHolders[tt_iLod]; + TileArrays &ta = ah.ah_ataTileArrays[tt_iArrayIndex]; + return ta.ta_auvShadowMap; +} +CStaticStackArray &CTerrainTile::GetDetailTC() { + ASSERT(tt_iArrayIndex!=-1); + ASSERT(tt_iRequestedLod==0 || tt_iLod==0); + CArrayHolder &ah = _ptrTerrain->tr_aArrayHolders[tt_iRequestedLod]; + TileArrays &ta = ah.ah_ataTileArrays[tt_iArrayIndex]; + return ta.ta_auvDetailMap; +} +CStaticStackArray &CTerrainTile::GetIndices() { + ASSERT(tt_iArrayIndex!=-1); + ASSERT(tt_iLod!=-1); + CArrayHolder &ah = _ptrTerrain->tr_aArrayHolders[tt_iLod]; + TileArrays &ta = ah.ah_ataTileArrays[tt_iArrayIndex]; + return ta.ta_auiIndices; +} +CStaticStackArray &CTerrainTile::GetTileLayers() { + ASSERT(tt_iArrayIndex!=-1); + ASSERT(tt_iRequestedLod==0 || tt_iLod==0); + CArrayHolder &ah = _ptrTerrain->tr_aArrayHolders[tt_iRequestedLod]; + TileArrays &ta = ah.ah_ataTileArrays[tt_iArrayIndex]; + return ta.ta_atlLayers; +} +CTextureData *CTerrainTile::GetTopMap() +{ + ASSERT(tt_iArrayIndex!=-1); + ASSERT(tt_iLod!=-1); + ASSERT(tt_iLod!=0); + ASSERT(tt_iLod!=_ptrTerrain->tr_iMaxTileLod); + CArrayHolder &ah = _ptrTerrain->tr_aArrayHolders[tt_iRequestedLod]; + TileArrays &ta = ah.ah_ataTileArrays[tt_iArrayIndex]; + return ta.ta_ptdTopMap; +} + +// Count used memory +SLONG CTerrainTile::GetUsedMemory(void) +{ + SLONG slUsedMemory=0; + slUsedMemory += sizeof(CTerrainTile); + return slUsedMemory; +} diff --git a/Sources/Engine/Terrain/TerrainTile.h b/Sources/Engine/Terrain/TerrainTile.h new file mode 100644 index 0000000..2c2fc74 --- /dev/null +++ b/Sources/Engine/Terrain/TerrainTile.h @@ -0,0 +1,106 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_TERRAIN_TILE_H +#define SE_INCL_TERRAIN_TILE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +#define NB_TOP 0 +#define NB_LEFT 1 +#define NB_BOTTOM 2 +#define NB_RIGHT 3 + +#define TT_REGENERATE (1UL<<0) // tile needs to be regenerated +#define TT_NO_TOPMAP_REGEN (1UL<<1) // when regenerating tile do not regenerate top map +#define TT_NO_GEOMETRY_REGEN (1UL<<2) // when regenerating tile do not regenerate geometry +#define TT_QUADTREENODE_REGEN (1UL<<3) // when regenerating tile also regenerate it quad tree node box +#define TT_NO_LODING (1UL<<4) // when regenerating tile do not use lod +#define TT_FORCE_TOPMAP_REGEN (1UL<<5) // force top map regen +#define TT_IN_LOWEST_LOD (1UL<<6) // tile in lowest lod and has no additional vertices inserted + +class ENGINE_API CTerrainTile +{ +public: + CTerrainTile(); + ~CTerrainTile(); + // Render tile + void Render(void); + // Regenerate tile + void ReGenerate(void); + // Regenerate tile layer + void ReGenerateTileLayer(INDEX iTileLayer); + // Release tile + void Clear(void); + // Terrain tile flags handling + inline ULONG &GetFlags() { return tt_ulTileFlags; } + inline void SetFlags(ULONG ulFlags) { tt_ulTileFlags = ulFlags; } + inline void AddFlag(ULONG ulFlag) { tt_ulTileFlags |= ulFlag; } + inline void RemoveFlag(ULONG ulFlag) { tt_ulTileFlags &= ~ulFlag; } + + CStaticStackArray &GetVertices(); + CStaticStackArray &GetTexCoords(); + CStaticStackArray &GetShadowMapTC(); + CStaticStackArray &GetDetailTC(); + CStaticStackArray &GetIndices(); + CStaticStackArray &GetTileLayers(); + CTextureData *GetTopMap(); + + INDEX ChangeTileArrays(INDEX iRequestedArrayLod); + void ReleaseTileArrays(); + void EmptyTileArrays(); + + // Calculate lod of tile + INDEX CalculateLOD(void); + // Update quad tree node + void UpdateQuadTreeNode(); + // Count used memory + SLONG GetUsedMemory(void); + +//temp: +void AddTriangle(INDEX iind1,INDEX iind2,INDEX iind3); +void AddVertex(INDEX ic, INDEX ir); +void LerpVertexPos(GFXVertex4 &vtx, INDEX iVxTarget, INDEX iVxFirst,INDEX iVxLast); +void PrepareSmothVertices(); + + +private: + // Regenerate left border + void ReGenerateLeftBorder(); + // Regenerate top border + void ReGenerateTopBorder(); + // Regenerate right border + void ReGenerateRightBorder(); + // Regenerate bottom border + void ReGenerateBottomBorder(); + + +public: + INDEX tt_ctVtxX; // Number of vertices in row + INDEX tt_ctVtxY; // Number of vertices in col + INDEX tt_ctLodVtxX; // Number of vertices in row for current lod + INDEX tt_ctLodVtxY; // Number of vertices in col for current lod + + INDEX tt_iIndex; // Index of this tile + INDEX tt_iLod; // Current lod of tile + INDEX tt_iRequestedLod; // Requested lod for tile + INDEX tt_iArrayIndex; // Index of array holder this tile uses + INDEX tt_aiNeighbours[4]; // Array of tile neighbours + + INDEX tt_iFirstBorderVertex[4];// Index of first border vertex inserted + INDEX tt_ctBorderVertices[4]; // Number of vertices inserted for each border + + FLOAT tt_fLodLerpFactor; // Lod lerp factor + ULONG tt_ulTileFlags; + BOOL tt_bUseOnlyGlobalTopMap; // Allways use global top map + + INDEX tt_iOffsetX; // Offset of this tile in world + INDEX tt_iOffsetZ; // Offset of this tile in world +private: + +}; + +#endif \ No newline at end of file diff --git a/Sources/Engine/World/PhysicsProfile.cpp b/Sources/Engine/World/PhysicsProfile.cpp new file mode 100644 index 0000000..adb34cd --- /dev/null +++ b/Sources/Engine/World/PhysicsProfile.cpp @@ -0,0 +1,100 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +// profile form for profiling world physics +CPhysicsProfile ppPhysicsProfile; +CProfileForm &_pfPhysicsProfile = ppPhysicsProfile; + +CPhysicsProfile::CPhysicsProfile(void) + : CProfileForm ("Physics", "frames", + CPhysicsProfile::PCI_COUNT, CPhysicsProfile::PTI_COUNT) +{ + SETTIMERNAME(PTI_PROCESSGAMETICK, "ProcessGameTick()", ""); + SETTIMERNAME(PTI_APPLYACTIONS, " applying client actions", ""); + SETTIMERNAME(PTI_HANDLETIMERS, " handling timers", ""); + SETTIMERNAME(PTI_HANDLEMOVERS, " handling movers", ""); + SETTIMERNAME(PTI_WORLDBASETICK, " WorldBase tick", ""); + + SETTIMERNAME(PTI_PREMOVING, "PreMoving()", "move"); + SETTIMERNAME(PTI_POSTMOVING, "PostMoving()", "move"); + SETTIMERNAME(PTI_DOMOVING, "DoMoving()", "move"); + SETTIMERNAME(PTI_ISSTANDINGONPOLYGON, " IsStandingOnPolygon()", ""); + SETTIMERNAME(PTI_TRYTOTRANSLATE, " TryToTranslate()", "try"); + SETTIMERNAME(PTI_TRYTOROTATE, " TryToRotate()", "try"); + SETTIMERNAME(PTI_TRYTOGOUPSTAIRS, " TryToGoUpstairs()", "try"); + SETTIMERNAME(PTI_SETPLACEMENTFROMNEXTPOSITION, "SetPlacementFromNextPosition()", "setting"); + SETTIMERNAME(PTI_SETPLACEMENT, " SetPlacement()", "setting"); + + SETTIMERNAME(PTI_SETPLACEMENT_COORDSUPDATE, " coords updating", ""); + SETTIMERNAME(PTI_SETPLACEMENT_LIGHTUPDATE, " light updating", ""); + SETTIMERNAME(PTI_SETPLACEMENT_BRUSHUPDATE, " brush updating", ""); + SETTIMERNAME(PTI_SETPLACEMENT_SPATIALUPDATE, " spatial updating", ""); + SETTIMERNAME(PTI_SETPLACEMENT_COLLISIONUPDATE, " collision updating", ""); + + + SETTIMERNAME(PTI_PREPARECLIPMOVE, "CClipMove::CClipMove()", ""); + SETTIMERNAME(PTI_CLIPMOVETOWORLD, "ClipMoveToWorld()", "clip"); + SETTIMERNAME(PTI_CLIPMOVETOBRUSHES, "ClipMoveToBrushes()", "clip"); + SETTIMERNAME(PTI_CLIPMOVETOBRUSHES_ADDINITIAL, " addinitial", "sector"); + SETTIMERNAME(PTI_CLIPMOVETOBRUSHES_MAINLOOP, " mainloop", "sector"); + SETTIMERNAME(PTI_CLIPMOVETOBRUSHES_FINDNONZONING, " findnonzoning", ""); + SETTIMERNAME(PTI_CLIPMOVETOBRUSHES_ADDNONZONING, " addnonzoning", ""); + SETTIMERNAME(PTI_CLIPMOVETOBRUSHES_CLEANUP, " cleanup", ""); + SETTIMERNAME(PTI_CLIPMOVETOMODELS, "ClipMoveToModels()", ""); + + SETTIMERNAME(PTI_CACHENEARPOLYGONS, "CacheNearPolygons()", "caching"); + SETTIMERNAME(PTI_CACHENEARPOLYGONS_ADDINITIAL, " addinitial", ""); + SETTIMERNAME(PTI_CACHENEARPOLYGONS_MAINLOOP, " mainloop", "sector"); + SETTIMERNAME(PTI_CACHENEARPOLYGONS_MAINLOOPFOUND, " found", "polygon"); + SETTIMERNAME(PTI_CACHENEARPOLYGONS_CLEANUP, " cleanup", ""); + + SETTIMERNAME(PTI_CLIPTONONZONINGSECTOR, "ClipToNonZoningSector()", "polygon"); + SETTIMERNAME(PTI_CLIPTOZONINGSECTOR, "ClipToZoningSector()", "polygon"); + + SETTIMERNAME(PTI_CLIPMOVETOMODEL, " ClipMoveToModel()", ""); + SETTIMERNAME(PTI_CLIPMOVETOMODELNONTRIVIAL, " ClipMoveToModel()-nontrivial", ""); + SETTIMERNAME(PTI_CLIPMOVETOBRUSHPOLYGON, " ClipMoveToBrushPolygon()", ""); + SETTIMERNAME(PTI_CLIPMODELMOVETOMODEL, " ClipModelMoveToModel()", ""); + SETTIMERNAME(PTI_PREPAREPROJECTIONSANDSPHERES, " PrepareProjectionsAndSpheres()", ""); + SETTIMERNAME(PTI_PROJECTASPHERESTOB, " ProjectASpheresToB()", ""); + SETTIMERNAME(PTI_GETPOSITIONSOFENTITY, " GetPositionsOfEntity()", ""); + + SETTIMERNAME(PTI_FINDENTITIESNEARBOX, " FindEntitiesNearBox()", ""); + SETTIMERNAME(PTI_ADDENTITYTOGRID, " AddEntityToCollisionGrid()", ""); + SETTIMERNAME(PTI_REMENTITYFROMGRID, " RemoveEntityFromCollisionGrid()", ""); + SETTIMERNAME(PTI_MOVEENTITYINGRID, " MoveEntityInCollisionGrid()", ""); + + SETCOUNTERNAME(PCI_GRAVITY_NONTRIVIAL, "non-trivial gravity moves"); + SETCOUNTERNAME(PCI_GRAVITY_TRIVIAL, "trivial gravity moves"); + + SETCOUNTERNAME(PCI_CLIPMOVES, "tested movements"); + SETCOUNTERNAME(PCI_XXTESTS, "x-x tests"); + SETCOUNTERNAME(PCI_MODELXTESTS, "model-x tests"); + SETCOUNTERNAME(PCI_BRUSHXTESTS, "brush-x tests"); + SETCOUNTERNAME(PCI_MODELMODELTESTS, "model-model tests"); + SETCOUNTERNAME(PCI_MODELBRUSHTESTS, "model-brush tests"); + SETCOUNTERNAME(PCI_SPHERETOPOLYGONTESTS, "sphere-polygon tests"); + SETCOUNTERNAME(PCI_SPHERETOSPHERETESTS, "sphere-sphere tests"); + SETCOUNTERNAME(PCI_SPHERETOSPHEREHITS, "sphere-sphere hits"); + + SETCOUNTERNAME(PCI_DOMOVING, "do moving"); + SETCOUNTERNAME(PCI_DOMOVING_SYNC, " sync"); + SETCOUNTERNAME(PCI_DOMOVING_ASYNC, " async"); + SETCOUNTERNAME(PCI_DOMOVING_ASYNC_SYNCTRY, " sync try"); + SETCOUNTERNAME(PCI_DOMOVING_ASYNC_SYNCPASS, " sync pass"); + SETCOUNTERNAME(PCI_DOMOVING_ASYNC_TRANSLATE," translate"); + SETCOUNTERNAME(PCI_DOMOVING_ASYNC_ROTATE, " rotate"); + SETCOUNTERNAME(PCI_TRYTOMOVE, "try to move"); + SETCOUNTERNAME(PCI_TRYTOMOVE_FAST," fast"); + SETCOUNTERNAME(PCI_TRYTOMOVE_PASS," pass"); + SETCOUNTERNAME(PCI_TRYTOMOVE_CLIP," clip"); + + SETCOUNTERNAME(PCI_FINDINGNEARENTITIES, "how many times FindEntitiesNearBox() was called"); + SETCOUNTERNAME(PCI_NEARCELLSFOUND, "cells found in FindEntitiesNearBox()"); + SETCOUNTERNAME(PCI_NEAROCCUPIEDCELLSFOUND, "occupied cells found in FindEntitiesNearBox()"); + SETCOUNTERNAME(PCI_NEARENTITIESFOUND, "entities found in FindEntitiesNearBox()"); +} + diff --git a/Sources/Engine/World/PhysicsProfile.h b/Sources/Engine/World/PhysicsProfile.h new file mode 100644 index 0000000..10698fe --- /dev/null +++ b/Sources/Engine/World/PhysicsProfile.h @@ -0,0 +1,112 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +/* + * S-Cape3D 3D game engine library + * Copyright (c) 1997-1998, CroTeam. All rights reserved. + */ + +#ifndef __ENGINE_BASE_PROFILING_H__ +#include +#endif + +/* Class for holding profiling information for physics. */ +class CPhysicsProfile : public CProfileForm { +public: + // indices for profiling counters and timers + enum ProfileTimerIndex { + PTI_PROCESSGAMETICK, + PTI_APPLYACTIONS, + PTI_HANDLETIMERS, + PTI_HANDLEMOVERS, + PTI_WORLDBASETICK, + + PTI_DUMMY1, + + PTI_PREMOVING, + PTI_POSTMOVING, + PTI_DOMOVING, + PTI_ISSTANDINGONPOLYGON, + PTI_TRYTOTRANSLATE, + PTI_TRYTOROTATE, + PTI_TRYTOGOUPSTAIRS, + PTI_SETPLACEMENTFROMNEXTPOSITION, + PTI_SETPLACEMENT, + PTI_SETPLACEMENT_COORDSUPDATE, + PTI_SETPLACEMENT_LIGHTUPDATE, + PTI_SETPLACEMENT_BRUSHUPDATE, + PTI_SETPLACEMENT_SPATIALUPDATE, + PTI_SETPLACEMENT_COLLISIONUPDATE, + + PTI_DUMMY2, + + PTI_PREPARECLIPMOVE, + PTI_CLIPMOVETOWORLD, + PTI_CLIPMOVETOBRUSHES, + PTI_CLIPMOVETOBRUSHES_ADDINITIAL, + PTI_CLIPMOVETOBRUSHES_MAINLOOP, + PTI_CLIPMOVETOBRUSHES_FINDNONZONING, + PTI_CLIPMOVETOBRUSHES_ADDNONZONING, + PTI_CLIPMOVETOBRUSHES_CLEANUP, + + PTI_CACHENEARPOLYGONS, + PTI_CACHENEARPOLYGONS_ADDINITIAL, + PTI_CACHENEARPOLYGONS_MAINLOOP, + PTI_CACHENEARPOLYGONS_MAINLOOPFOUND, + PTI_CACHENEARPOLYGONS_CLEANUP, + + PTI_CLIPTONONZONINGSECTOR, + PTI_CLIPTOZONINGSECTOR, + + PTI_CLIPMOVETOMODELS, + PTI_CLIPMOVETOMODEL, + PTI_CLIPMOVETOMODELNONTRIVIAL, + PTI_CLIPBRUSHMOVETOMODEL, + PTI_CLIPMOVETOBRUSHPOLYGON, + PTI_CLIPMODELMOVETOMODEL, + PTI_PREPAREPROJECTIONSANDSPHERES, + PTI_PROJECTASPHERESTOB, + PTI_GETPOSITIONSOFENTITY, + + PTI_DUMMY3, + + PTI_FINDENTITIESNEARBOX, + PTI_ADDENTITYTOGRID, + PTI_REMENTITYFROMGRID, + PTI_MOVEENTITYINGRID, + PTI_COUNT + }; + enum ProfileCounterIndex { + PCI_GRAVITY_NONTRIVIAL, // non-trivial gravity moves + PCI_GRAVITY_TRIVIAL, // trivial gravity moves + + PCI_CLIPMOVES, // number of tested movements + PCI_XXTESTS, // number of x-x tests + PCI_MODELXTESTS, // number of model-x tests + PCI_BRUSHXTESTS, // number of brush-x tests + PCI_MODELMODELTESTS, // number of model-model tests + PCI_MODELBRUSHTESTS, // number of model-brush tests + PCI_SPHERETOPOLYGONTESTS, // number of sphere-polygon tests + PCI_SPHERETOSPHERETESTS, // number of sphere-sphere tests + PCI_SPHERETOSPHEREHITS, // number of sphere-sphere hits + + PCI_DOMOVING, + PCI_DOMOVING_SYNC, + PCI_DOMOVING_ASYNC, + PCI_DOMOVING_ASYNC_SYNCTRY, + PCI_DOMOVING_ASYNC_SYNCPASS, + PCI_DOMOVING_ASYNC_TRANSLATE, + PCI_DOMOVING_ASYNC_ROTATE, + PCI_TRYTOMOVE, + PCI_TRYTOMOVE_FAST, + PCI_TRYTOMOVE_PASS, + PCI_TRYTOMOVE_CLIP, + + PCI_FINDINGNEARENTITIES, // how many times FindEntitiesNearBox() was called + PCI_NEARCELLSFOUND, // cells found in FindEntitiesNearBox() + PCI_NEAROCCUPIEDCELLSFOUND, // occupied cells found in FindEntitiesNearBox() + PCI_NEARENTITIESFOUND, // near entities found in FindEntitiesNearBox() + PCI_COUNT + }; + // constructor + CPhysicsProfile(void); +}; diff --git a/Sources/Engine/World/World.cpp b/Sources/Engine/World/World.cpp new file mode 100644 index 0000000..00fb6f1 --- /dev/null +++ b/Sources/Engine/World/World.cpp @@ -0,0 +1,1146 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +template CDynamicContainer; +template CBrushPolygonSelection; +template CBrushSectorSelection; +template CEntitySelection; + +extern BOOL _bPortalSectorLinksPreLoaded; +extern BOOL _bEntitySectorLinksPreLoaded; +extern INDEX _ctPredictorEntities; + +// calculate ray placement from origin and target positions (obsolete?) +static inline CPlacement3D CalculateRayPlacement( + const FLOAT3D &vOrigin, const FLOAT3D &vTarget) +{ + CPlacement3D plRay; + // ray position is at origin + plRay.pl_PositionVector = vOrigin; + // calculate ray direction vector + FLOAT3D vDirection = vTarget-vOrigin; + // calculate ray orientation from the direction vector + vDirection.Normalize(); + DirectionVectorToAngles(vDirection, plRay.pl_OrientationAngle); + return plRay; +} + +/* Constructor. */ +CTextureTransformation::CTextureTransformation(void) +{ + tt_strName = ""; +} + +/* Constructor. */ +CTextureBlending::CTextureBlending(void) +{ + tb_strName = ""; + tb_ubBlendingType = STXF_BLEND_OPAQUE; + tb_colMultiply = C_WHITE|0xFF; +} + +/* + * Constructor. + */ +CWorld::CWorld(void) + : wo_colBackground(C_lGRAY) // clear background color + , wo_pecWorldBaseClass(NULL) // worldbase class must be obtained before using the world + , wo_bPortalLinksUpToDate(FALSE) // portal-sector links must be updated + , wo_baBrushes(*new CBrushArchive) + , wo_taTerrains(*new CTerrainArchive) + , wo_ulSpawnFlags(0) +{ + wo_baBrushes.ba_pwoWorld = this; + wo_taTerrains.ta_pwoWorld = this; + + // create empty texture movements + wo_attTextureTransformations.New(256); + wo_atbTextureBlendings.New(256); + wo_astSurfaceTypes.New(256); + wo_actContentTypes.New(256); + wo_aetEnvironmentTypes.New(256); + wo_aitIlluminationTypes.New(256); + + // initialize collision grid + InitCollisionGrid(); + + wo_slStateDictionaryOffset = 0; + wo_strBackdropUp = ""; + wo_strBackdropFt = ""; + wo_strBackdropRt = ""; + wo_strBackdropObject = ""; + wo_fUpW = wo_fUpL = 1.0f; wo_fUpCX = wo_fUpCZ = 0.0f; + wo_fFtW = wo_fFtH = 1.0f; wo_fFtCX = wo_fFtCY = 0.0f; + wo_fRtL = wo_fRtH = 1.0f; wo_fRtCZ = wo_fRtCY = 0.0f; + + wo_ulNextEntityID = 1; + + // set default placement + wo_plFocus = CPlacement3D( FLOAT3D(3.0f, 4.0f, 10.0f), + ANGLE3D(AngleDeg( 20.0f), AngleDeg( -20.0f), 0)); + wo_fTargetDistance = 10.0f; + + // set default thumbnail placement + wo_plThumbnailFocus = CPlacement3D( FLOAT3D(3.0f, 4.0f, 10.0f), + ANGLE3D(AngleDeg( 20.0f), AngleDeg( -20.0f), 0)); + wo_fThumbnailTargetDistance = 10.0f; +} + +/* + * Destructor. + */ +CWorld::~CWorld() +{ + // clear all arrays + Clear(); + // destroy collision grid + DestroyCollisionGrid(); + + delete &wo_baBrushes; + delete &wo_taTerrains; +} + +/* + * Clear all arrays. + */ +void CWorld::Clear(void) +{ + // detach worldbase class + if (wo_pecWorldBaseClass!=NULL) { + if ( wo_pecWorldBaseClass->ec_pdecDLLClass!=NULL + &&wo_pecWorldBaseClass->ec_pdecDLLClass->dec_OnWorldEnd!=NULL) { + wo_pecWorldBaseClass->ec_pdecDLLClass->dec_OnWorldEnd(this); + } + wo_pecWorldBaseClass=NULL; + } + + { + // must be in 24bit mode when managing entities + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // clear background viewer + SetBackgroundViewer(NULL); + // make a new container of entities + CDynamicContainer cenToDestroy = wo_cenEntities; + // for each of the entities + {FOREACHINDYNAMICCONTAINER(cenToDestroy, CEntity, iten) { + // destroy it + iten->Destroy(); + }} + // the original container must be empty + ASSERT(wo_cenEntities.Count()==0); + ASSERT(wo_cenAllEntities.Count()==0); + wo_cenEntities.Clear(); + wo_cenAllEntities.Clear(); + cenToDestroy.Clear(); + wo_ulNextEntityID = 1; + } + + // clear brushes + wo_baBrushes.ba_abrBrushes.Clear(); + // clear terrains + wo_taTerrains.ta_atrTerrains.Clear(); + + extern void ClearMovableEntityCaches(void); + ClearMovableEntityCaches(); + + // clear collision grid + ClearCollisionGrid(); +} + +/* + * Create a new entity of given class. + */ +CEntity *CWorld::CreateEntity(const CPlacement3D &plPlacement, CEntityClass *pecClass) +{ + // must be in 24bit mode when managing entities + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // if the world base class is not yet remembered and this class is world base + if (wo_pecWorldBaseClass==NULL + && stricmp(pecClass->ec_pdecDLLClass->dec_strName, "WorldBase")==0) { + // remember it + wo_pecWorldBaseClass = pecClass; + // execute the class attach function + if (pecClass->ec_pdecDLLClass->dec_OnWorldInit!=NULL) { + pecClass->ec_pdecDLLClass->dec_OnWorldInit(this); + } + } + // gather CRCs of that class + pecClass->AddToCRCTable(); + + // ask the class to instance a new member + CEntity *penEntity = pecClass->New(); + // add the reference made by the entity itself + penEntity->AddReference(); + + // set the entity's world pointer to this world + penEntity->en_pwoWorld = this; + // add the new member to this world's entity container + wo_cenEntities.Add(penEntity); + wo_cenAllEntities.Add(penEntity); + // set a new identifier + penEntity->en_ulID = wo_ulNextEntityID++; + // set up the placement + penEntity->en_plPlacement = plPlacement; + // calculate rotation matrix + MakeRotationMatrixFast(penEntity->en_mRotation, penEntity->en_plPlacement.pl_OrientationAngle); + + // if now predicting + if (_pNetwork->IsPredicting()) { + // mark entity as a temporary predictor + penEntity->en_ulFlags |= ENF_PREDICTOR|ENF_TEMPPREDICTOR; + wo_cenPredictor.Add(penEntity); + _ctPredictorEntities++; + } + + // return it + return penEntity; +} + +/* + * Create a new entity of given class. + */ +CEntity *CWorld::CreateEntity_t(const CPlacement3D &plPlacement, + const CTFileName &fnmClass) // throw char * +{ + // obtain a new entity class from global stock + CEntityClass *pecClass = _pEntityClassStock->Obtain_t(fnmClass); + // create entity with that class (obtains it once more) + CEntity *penNew = CreateEntity(plPlacement, pecClass); + // release the class + _pEntityClassStock->Release(pecClass); + // return the entity + return penNew; +} + +/* + * Destroy one entities. + */ +void CWorld::DestroyOneEntity( CEntity *penToDestroy) +{ + // if the entity is targetable + if (penToDestroy->IsTargetable()) { + // remove all eventual pointers to it + UntargetEntity( penToDestroy); + } + // destroy it + penToDestroy->Destroy(); +} + +/* + * Destroy a selection of entities. + */ +void CWorld::DestroyEntities(CEntitySelection &senToDestroy) +{ + // must be in 24bit mode when managing entities + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // for each entity in selection + FOREACHINDYNAMICCONTAINER(senToDestroy, CEntity, iten) { + // if the entity is targetable + if (iten->IsTargetable()) { + // remove all eventual pointers to it + UntargetEntity(iten); + } + // destroy it + iten->Destroy(); + } + // clear the selection on the container level + /* NOTE: we must not clear the selection directly, since the entity objects + contained there are already freed and deselecting them would make an access + violation. + */ + senToDestroy.CDynamicContainer::Clear(); +} + +/* + * Clear all entity pointers that point to this entity. + */ +void CWorld::UntargetEntity(CEntity *penToUntarget) +{ + // for all entities in this world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, itenInWorld){ + // get the DLL class of this entity + CDLLEntityClass *pdecDLLClass = itenInWorld->en_pecClass->ec_pdecDLLClass; + + // for all classes in hierarchy of this entity + for(; + pdecDLLClass!=NULL; + pdecDLLClass = pdecDLLClass->dec_pdecBase) { + // for all properties + for(INDEX iProperty=0; iPropertydec_ctProperties; iProperty++) { + CEntityProperty &epProperty = pdecDLLClass->dec_aepProperties[iProperty]; + + // if the property type is entity pointer + if (epProperty.ep_eptType == CEntityProperty::EPT_ENTITYPTR) { + // get the pointer + CEntityPointer &penPointed = ENTITYPROPERTY(&*itenInWorld, epProperty.ep_slOffset, CEntityPointer); + // if it points to the entity to be untargeted + if (penPointed == penToUntarget) { + itenInWorld->End(); + // clear the pointer + penPointed = NULL; + itenInWorld->Initialize(); + } + } + } + } + } + // if the entity is background viewer + if (wo_penBackgroundViewer==penToUntarget) { + // reset background viewer + SetBackgroundViewer(NULL); + } +} + +/* + * Find an entity with given character. + */ +CPlayerEntity *CWorld::FindEntityWithCharacter(CPlayerCharacter &pcCharacter) +{ + ASSERT(pcCharacter.pc_strName != ""); + + // for each entity + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + CEntity *pen = &*iten; + // if it is player entity + if (IsDerivedFromClass(pen, "PlayerEntity")) { + CPlayerEntity *penPlayer = (CPlayerEntity *)pen; + // if it has got that character + if (penPlayer->en_pcCharacter == pcCharacter) { + // return its pointer + return penPlayer; + } + } + } + // otherwise, none exists + return NULL; +} + +/* + * Add an entity to list of thinkers. + */ +void CWorld::AddTimer(CRationalEntity *penThinker) +{ + ASSERT(penThinker->en_timeTimer>_pTimer->CurrentTick()); + ASSERT(GetFPUPrecision()==FPT_24BIT); + + // if the entity is already in the list + if (penThinker->en_lnInTimers.IsLinked()) { + // remove it + penThinker->en_lnInTimers.Remove(); + } + // for each entity in the thinker list + FOREACHINLISTKEEP(CRationalEntity, en_lnInTimers, wo_lhTimers, iten) { + // if the entity in list has greater or same think time than the one to add + if (iten->en_timeTimer>=penThinker->en_timeTimer) { + // stop searching + break; + } + } + // add the new entity before current one + iten.InsertBeforeCurrent(penThinker->en_lnInTimers); +} + +// set overdue timers to be due in current time +void CWorld::AdjustLateTimers(TIME tmCurrentTime) +{ + // must be in 24bit mode when managing entities + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // for each entity in the thinker list + FOREACHINLIST(CRationalEntity, en_lnInTimers, wo_lhTimers, iten) { + CRationalEntity &en = *iten; + // if the entity in list is overdue + if (en.en_timeTimeren_ulFlags&ENF_DELETED) { + // clear the pointer + wo_penBackgroundViewer = NULL; + } + return wo_penBackgroundViewer; +} + +/* Set description for this world. */ +void CWorld::SetDescription(const CTString &strDescription) +{ + wo_strDescription = strDescription; +} +/* Get description for this world. */ +const CTString &CWorld::GetDescription(void) +{ + return wo_strDescription; +} + +// get/set name of the world +void CWorld::SetName(const CTString &strName) +{ + wo_strName = strName; +} +const CTString &CWorld::GetName(void) +{ + return wo_strName; +} + +// get/set spawn flags for the world +void CWorld::SetSpawnFlags(ULONG ulFlags) +{ + wo_ulSpawnFlags = ulFlags; +} +ULONG CWorld::GetSpawnFlags(void) +{ + return wo_ulSpawnFlags; +} + +///////////////////////////////////////////////////////////////////// +// Shadow manipulation functions + +/* + * Recalculate all shadow maps that are not valid or of smaller precision. + */ +void CWorld::CalculateDirectionalShadows(void) +{ + extern INDEX _ctShadowLayers; + extern INDEX _ctShadowClusters; + CTimerValue tvStart; + + // clear shadow rendering stats + tvStart = _pTimer->GetHighPrecisionTimer(); + _ctShadowLayers=0; + _ctShadowClusters=0; + + // for each shadow map that is queued for calculation + FORDELETELIST(CBrushShadowMap, bsm_lnInUncalculatedShadowMaps, + wo_baBrushes.ba_lhUncalculatedShadowMaps, itbsm) { + // calculate shadows on it + itbsm->GetBrushPolygon()->MakeShadowMap(this, TRUE); + } + + // report shadow rendering stats + CTimerValue tvStop = _pTimer->GetHighPrecisionTimer(); + CPrintF("Shadow calculation: total %d clusters in %d layers, %fs\n", + _ctShadowClusters, + _ctShadowLayers, + (tvStop-tvStart).GetSeconds()); +} + +void CWorld::CalculateNonDirectionalShadows(void) +{ + // for each shadow map that is queued for calculation + FORDELETELIST(CBrushShadowMap, bsm_lnInUncalculatedShadowMaps, + wo_baBrushes.ba_lhUncalculatedShadowMaps, itbsm) { + // calculate shadows on it + itbsm->GetBrushPolygon()->MakeShadowMap(this, FALSE); + } +} + + +/* Find all shadow layers near a certain position. */ +void CWorld::FindShadowLayers( + const FLOATaabbox3D &boxNear, + BOOL bSelectedOnly /*=FALSE*/, + BOOL bDirectional /*= TRUE*/) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_FINDSHADOWLAYERS); + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + // if it is light entity and it influences the given range + CLightSource *pls = iten->GetLightSource(); + if (pls!=NULL) { + FLOATaabbox3D boxLight(iten->en_plPlacement.pl_PositionVector, pls->ls_rFallOff); + if ( bDirectional && (pls->ls_ulFlags &LSF_DIRECTIONAL) + ||boxLight.HasContactWith(boxNear)) { + // find layers for that light source + pls->FindShadowLayers(bSelectedOnly); + } + } + } + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_FINDSHADOWLAYERS); +} +/* Discard shadows on all brush polygons in the world. */ +void CWorld::DiscardAllShadows(void) +{ + FLOATaabbox3D box; + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + // if it is brush entity + if (iten->en_RenderType == CEntity::RT_BRUSH) { + // for each mip in its brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) { + box|=itbm->bm_boxBoundingBox; + // for all sectors in this mip + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // for each polygon in the sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + // discard its shadow map + itbpo->DiscardShadows(); + } + } + } + } + } + // find all shadow layers in the world + FindShadowLayers(box); +} +///////////////////////////////////////////////////////////////////// +// Hide/Show functions + +/* + * Hide entities contained in given selection. + */ +void CWorld::HideSelectedEntities(CEntitySelection &selenEntitiesToHide) +{ + // for all entities in the selection + FOREACHINDYNAMICCONTAINER(selenEntitiesToHide, CEntity, iten) { + if( iten->IsSelected(ENF_SELECTED) && + !((iten->en_RenderType==CEntity::RT_BRUSH) && (iten->en_ulFlags&ENF_ZONING)) ) + { + // hide the entity + iten->en_ulFlags |= ENF_HIDDEN; + } + } +} + +/* + * Hide all unselected entities. + */ +void CWorld::HideUnselectedEntities(void) +{ + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) + { + if( !iten->IsSelected(ENF_SELECTED) && + !((iten->en_RenderType==CEntity::RT_BRUSH)&&(iten->en_ulFlags&ENF_ZONING)) ) + { + // hide it + iten->en_ulFlags |= ENF_HIDDEN; + } + } +} + +/* + * Show all entities. + */ +void CWorld::ShowAllEntities(void) +{ + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) + { + iten->en_ulFlags &= ~ENF_HIDDEN; + } +} + +/* + * Hide sectors contained in given selection. + */ +void CWorld::HideSelectedSectors(CBrushSectorSelection &selbscSectorsToHide) +{ + // for all sectors in the selection + FOREACHINDYNAMICCONTAINER(selbscSectorsToHide, CBrushSector, itbsc) { + // hide the sector + itbsc->bsc_ulFlags |= BSCF_HIDDEN; + } +} + +/* + * Hide all unselected sectors. + */ +void CWorld::HideUnselectedSectors(void) +{ + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + // if it is brush entity + if (iten->en_RenderType == CEntity::RT_BRUSH) { + // for each mip in its brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) { + // for all sectors in this mip + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // if the sector is not selected + if (!itbsc->IsSelected(BSCF_SELECTED)) { + // hide it + itbsc->bsc_ulFlags |= BSCF_HIDDEN; + } + } + } + } + } +} + +/* + * Show all sectors. + */ +void CWorld::ShowAllSectors(void) +{ + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + // if it is brush entity + if (iten->en_RenderType == CEntity::RT_BRUSH) { + // for each mip in its brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) { + // for all sectors in this mip + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // show the sector + itbsc->bsc_ulFlags &= ~BSCF_HIDDEN; + } + } + } + } +} + +/* + * Select all polygons in selected sectors with same texture. + */ +void CWorld::SelectByTextureInSelectedSectors( + CTFileName fnTexture, CBrushPolygonSelection &selbpoSimilar, INDEX iTexture) +{ + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + // if it is brush entity + if (iten->en_RenderType == CEntity::RT_BRUSH) { + // for each mip in its brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) { + // for all sectors in this mip + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // if sector is selected + if (itbsc->IsSelected(BSCF_SELECTED)) { + // for all polygons in sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) + { + // if it is not portal and is not selected and has same texture + if ( (!(itbpo->bpo_ulFlags&BPOF_PORTAL) || (itbpo->bpo_ulFlags&(BPOF_TRANSLUCENT|BPOF_TRANSPARENT))) && + !itbpo->IsSelected(BPOF_SELECTED) && + (itbpo->bpo_abptTextures[iTexture].bpt_toTexture.GetData() != NULL) && + (itbpo->bpo_abptTextures[iTexture].bpt_toTexture.GetData()->GetName() + == fnTexture) ) + // select this polygon + selbpoSimilar.Select(*itbpo); + } + } + } + } + } + } +} + +/* + * Select all polygons in world with same texture. + */ +void CWorld::SelectByTextureInWorld( + CTFileName fnTexture, CBrushPolygonSelection &selbpoSimilar, INDEX iTexture) +{ + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + // if it is brush entity + if (iten->en_RenderType == CEntity::RT_BRUSH) { + // for each mip in its brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) { + // for all sectors in this mip + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // for all polygons in sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) + { + // if it is not non translucent portal and is not selected and has same texture + if ( (!(itbpo->bpo_ulFlags&BPOF_PORTAL) || (itbpo->bpo_ulFlags&(BPOF_TRANSLUCENT|BPOF_TRANSPARENT))) && + !itbpo->IsSelected(BPOF_SELECTED) && + (itbpo->bpo_abptTextures[iTexture].bpt_toTexture.GetData() != NULL) && + (itbpo->bpo_abptTextures[iTexture].bpt_toTexture.GetData()->GetName() + == fnTexture) ) + // select this polygon + selbpoSimilar.Select(*itbpo); + } + } + } + } + } +} + +/* + * Reinitialize entities from their properties. (use only in WEd!) + */ +void CWorld::ReinitializeEntities(void) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_REINITIALIZEENTITIES); + + // must be in 24bit mode when managing entities + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + CTmpPrecachingNow tpn; + + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + // reinitialize it + iten->Reinitialize(); + } + + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_REINITIALIZEENTITIES); +} +/* Precache data needed by entities. */ +void CWorld::PrecacheEntities_t(void) +{ + // for each entity in the world + INDEX ctEntities = wo_cenEntities.Count(); + INDEX iEntity = 0; + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + // precache + CallProgressHook_t(FLOAT(iEntity)/ctEntities); + iten->Precache(); + iEntity++; + } +} +// delete all entities that don't fit given spawn flags +void CWorld::FilterEntitiesBySpawnFlags(ULONG ulFlags) +{ + // must be in 24bit mode when managing entities + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + BOOL bOldAllowRandom = _pNetwork->ga_sesSessionState.ses_bAllowRandom; + _pNetwork->ga_sesSessionState.ses_bAllowRandom = TRUE; + + // create an empty selection of entities + CEntitySelection senToDestroy; + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + // if brush + if (iten->en_RenderType==CEntity::RT_BRUSH + ||iten->en_RenderType==CEntity::RT_FIELDBRUSH) { + // skip it (brushes must not be deleted on the fly) + continue; + } + + // if it shouldn't exist + ULONG ulEntityFlags = iten->GetSpawnFlags(); + if (!(ulEntityFlags&ulFlags&SPF_MASK_DIFFICULTY) + ||!(ulEntityFlags&ulFlags&SPF_MASK_GAMEMODE)) { + // add it to the selection + senToDestroy.Select(*iten); + } + }} + // destroy all selected entities + DestroyEntities(senToDestroy); + _pNetwork->ga_sesSessionState.ses_bAllowRandom = bOldAllowRandom; +} + +// create links between zoning-brush sectors and non-zoning entities in sectors +void CWorld::LinkEntitiesToSectors(void) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_LINKENTITIESTOSECTORS); + // must be in 24bit mode when managing entities + CSetFPUPrecision FPUPrecision(FPT_24BIT); + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + CEntity &en = *iten; + // cache eventual collision info + en.FindCollisionInfo(); + en.UpdateSpatialRange(); + // link it + if (!_bEntitySectorLinksPreLoaded) { + en.FindSectorsAroundEntity(); + } + } + // NOTE: this is here to force relinking for all moving zoning brushes after loading! + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + CEntity &en = *iten; + if (en.en_RenderType==CEntity::RT_BRUSH && + (en.en_ulFlags&ENF_ZONING) && (en.en_ulPhysicsFlags&EPF_MOVABLE)){ + // recalculate all bounding boxes relative to new position + extern BOOL _bDontDiscardLinks; + _bDontDiscardLinks = TRUE; + en.en_pbrBrush->CalculateBoundingBoxes(); + _bDontDiscardLinks = FALSE; + // FPU must be in 53-bit mode + CSetFPUPrecision FPUPrecision(FPT_53BIT); + + // for all brush mips + FOREACHINLIST(CBrushMip, bm_lnInBrush, en.en_pbrBrush->br_lhBrushMips, itbm) { + // for all sectors in the mip + {FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // find entities in sector + itbsc->FindEntitiesInSector(); + }} + } + } + }} + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_LINKENTITIESTOSECTORS); +} + +// rebuild all links in world +void CWorld::RebuildLinks(void) +{ + wo_baBrushes.LinkPortalsAndSectors(); + _bEntitySectorLinksPreLoaded = FALSE; + LinkEntitiesToSectors(); +} + +/* Update sectors during brush vertex moving */ +void CWorld::UpdateSectorsDuringVertexChange( CBrushVertexSelection &selVertex) +{ + // create container of sectors that will need to be updated + CDynamicContainer cbscToUpdate; + + {FOREACHINDYNAMICCONTAINER( selVertex, CBrushVertex, itbvx) + { + // add the sector of that vertex to list for updating + if (!cbscToUpdate.IsMember(itbvx->bvx_pbscSector)) { + cbscToUpdate.Add(itbvx->bvx_pbscSector); + } + }} + + // for each sector to be updated + {FOREACHINDYNAMICCONTAINER( cbscToUpdate, CBrushSector, itbsc){ + // recalculate planes for polygons from their vertices + itbsc->MakePlanesFromVertices(); + }} +} + +/* Update sectors after brush vertex moving */ +void CWorld::UpdateSectorsAfterVertexChange( CBrushVertexSelection &selVertex) +{ + // create container of sectors that will need to be updated + CDynamicContainer cbscToUpdate; + + {FOREACHINDYNAMICCONTAINER( selVertex, CBrushVertex, itbvx) + { + // add the sector of that vertex to list for updating + if (!cbscToUpdate.IsMember(itbvx->bvx_pbscSector)) { + cbscToUpdate.Add(itbvx->bvx_pbscSector); + } + }} + + // for each sector to be updated + {FOREACHINDYNAMICCONTAINER( cbscToUpdate, CBrushSector, itbsc){ + // update it + itbsc->UpdateVertexChanges(); + }} +} + +/* Triangularize polygons that contain vertices from given selection */ +void CWorld::TriangularizeForVertices( CBrushVertexSelection &selVertex) +{ + // create container of sectors that contain polygons that need to be triangularized + CDynamicContainer cbscToTriangularize; + + {FOREACHINDYNAMICCONTAINER( selVertex, CBrushVertex, itbvx) + { + // add the sector of that vertex to list for triangularizing + if (!cbscToTriangularize.IsMember(itbvx->bvx_pbscSector)) { + cbscToTriangularize.Add(itbvx->bvx_pbscSector); + } + }} + + // for each sector to be updated + {FOREACHINDYNAMICCONTAINER( cbscToTriangularize, CBrushSector, itbsc){ + // update it + itbsc->TriangularizeForVertices(selVertex); + }} +} + +// add this entity to prediction +void CEntity::AddToPrediction(void) +{ + // this function may be called even for NULLs - so ignore it + if (this==NULL) { + return; + } + // if already added + if (en_ulFlags&ENF_WILLBEPREDICTED) { + // do nothing + return; + } + // mark as added + en_ulFlags|=ENF_WILLBEPREDICTED; + en_pwoWorld->wo_cenWillBePredicted.Add(this); + // add your dependents + AddDependentsToPrediction(); +} + +// mark all predictable entities that will be predicted using user-set criterions +void CWorld::MarkForPrediction(void) +{ + extern INDEX cli_bPredictIfServer; + extern INDEX cli_bPredictLocalPlayers; + extern INDEX cli_bPredictRemotePlayers; + extern FLOAT cli_fPredictEntitiesRange; + static CStaticStackArray avLocalPlayers; + avLocalPlayers.PopAll(); + + // for each player + for (INDEX iPlayer=0; iPlayerIsPlayerLocal(pen); + // if allowed for prediction + if ( bLocal && cli_bPredictLocalPlayers + || !bLocal && cli_bPredictRemotePlayers) { + // add it + pen->AddToPrediction(); + } + // if local + if (bLocal) { + // remember coordinates of the original entity, and eventual predictor coords + avLocalPlayers.Push() = pen->GetPlacement().pl_PositionVector; + avLocalPlayers.Push() = _pNetwork->ga_sesSessionState.GetPlayerPredictorPosition(iPlayer); + } + } + } + + TIME tmNow = _pNetwork->ga_sesSessionState.ses_tmPredictionHeadTick; + + // for each predictable entity + {FOREACHINDYNAMICCONTAINER(wo_cenPredictable, CEntity, iten){ + CEntity &en = *iten; + // it must not be void (so that its coordinates are relevant) + ASSERT(en.GetRenderType()!=CEntity::RT_VOID); + + // get its upper time limit for prediction + TIME tmLimit = en.GetPredictionTime(); + // if now inside time prediction interval + if (tmNowAddToPrediction(); + continue; + } + + // if predicting entities by range + if (cli_fPredictEntitiesRange>0) { + FLOAT fRange = en.GetPredictionRange(); + if (fRange<=0) { + continue; + } + fRange = Min(fRange, cli_fPredictEntitiesRange); + + // get its coordinates and maximal prediction range + const FLOAT3D &v = en.GetPlacement().pl_PositionVector; + // check if it is within range of any local player + BOOL bInRange = FALSE; + for(INDEX i=0; iAddToPrediction(); + } + } + + }} +} + +// unmark all predictable entities marked for prediction +void CWorld::UnmarkForPrediction(void) +{ + // for each entity marked + {FOREACHINDYNAMICCONTAINER(wo_cenWillBePredicted, CEntity, iten){ + // unmark for prediction + iten->en_ulFlags&=~ENF_WILLBEPREDICTED; + }} + wo_cenWillBePredicted.Clear(); +} + +// create predictors for predictable entities that are marked for prediction +void CWorld::CreatePredictors(void) +{ + CDynamicContainer cenForPrediction; + // for each entity marked + {FOREACHINDYNAMICCONTAINER(wo_cenWillBePredicted, CEntity, iten){ + // if not deleted + if (!(iten->en_ulFlags&ENF_DELETED)) { + // add to container + cenForPrediction.Add(iten); + } + // unmark + iten->en_ulFlags&=~ENF_WILLBEPREDICTED; + }} + wo_cenWillBePredicted.Clear(); +// CPrintF("for prediction: %d\n", cenForPrediction.Count()); + + // create copies of those entities as predictors + CopyEntitiesToPredictors(cenForPrediction); +} + +// delete all predictor entities +void CWorld::DeletePredictors(void) +{ + // must be in 24bit mode when managing entities + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // first remember eventual predicted player positions + _pNetwork->ga_sesSessionState.RememberPlayerPredictorPositions(); + + // make a copy of predictor container (for safe iteration) + CDynamicContainer cenPredictor = wo_cenPredictor; + // for each predictor + {FOREACHINDYNAMICCONTAINER( cenPredictor, CEntity, iten){ + CEntity &en = *iten; + ASSERT(en.IsPredictor()); + // destroy it + en.Destroy(); + }} + + // for each predicted + {FOREACHINDYNAMICCONTAINER( wo_cenPredicted, CEntity, iten){ + CEntity &en = *iten; + ASSERT(en.IsPredicted()); + // kill its pointer to predictor + en.SetPredictionPair(NULL); + // mark as not predicted + en.en_ulFlags&=~ENF_PREDICTED; + }} + + ASSERT(_ctPredictorEntities==0); + + wo_cenPredictor.Clear(); + wo_cenPredicted.Clear(); + + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + CEntity &en = *iten; + ASSERT(!en.IsPredictor()); + } +} + +// get entity by its ID +CEntity *CWorld::EntityFromID(ULONG ulID) +{ + FOREACHINDYNAMICCONTAINER(wo_cenAllEntities, CEntity, iten) { + if (iten->en_ulID==ulID) { + return iten; + } + } + ASSERT(FALSE); + return NULL; +} + +/* Triangularize selected polygons. */ +void CWorld::TriangularizePolygons(CDynamicContainer &dcPolygons) +{ + ClearMarkedForUseFlag(); + CDynamicContainer cbscToProcess; + // for each polyon in selection + FOREACHINDYNAMICCONTAINER(dcPolygons, CBrushPolygon, itbpo) + { + CBrushPolygon &bp=*itbpo; + bp.bpo_ulFlags |= BPOF_MARKED_FOR_USE; + CBrushSector *pbsc=bp.bpo_pbscSector; + if( !cbscToProcess.IsMember( pbsc)) + { + cbscToProcess.Add( pbsc); + } + } + + FOREACHINDYNAMICCONTAINER(cbscToProcess, CBrushSector, itbsc) + { + itbsc->TriangularizeMarkedPolygons(); + itbsc->UpdateVertexChanges(); + } +} + +// Clear marked for use flag on all polygons in world +void CWorld::ClearMarkedForUseFlag(void) +{ + // for each entity in the world + FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + // if it is brush entity + if (iten->en_RenderType == CEntity::RT_BRUSH) { + // for each mip in its brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, iten->en_pbrBrush->br_lhBrushMips, itbm) { + // for all sectors in this mip + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) { + // for each polygon in the sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + // discard marked for use flag + itbpo->bpo_ulFlags &= ~BPOF_MARKED_FOR_USE; + } + } + } + } + } +} \ No newline at end of file diff --git a/Sources/Engine/World/World.h b/Sources/Engine/World/World.h new file mode 100644 index 0000000..f41c7c0 --- /dev/null +++ b/Sources/Engine/World/World.h @@ -0,0 +1,363 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_WORLD_H +#define SE_INCL_WORLD_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +class CTextureTransformation; +class CTextureBlending; +class CSurfaceType; +class CContentType; +class CEnvironmentType; +class CIlluminationType; + +// mirroring types for mirror and stretch +enum WorldMirrorType { + WMT_NONE, + WMT_X, + WMT_Y, + WMT_Z, +}; + +class ENGINE_API CWorld { +public: +// implementation: + // current transformations for animating texture mapping + CStaticArray wo_attTextureTransformations; + // current blendings for animating texture blending + CStaticArray wo_atbTextureBlendings; + // polygon surface types + CStaticArray wo_astSurfaceTypes; + // sector content types + CStaticArray wo_actContentTypes; + // sector environment types + CStaticArray wo_aetEnvironmentTypes; + // illumination types (0 is not used) + CStaticArray wo_aitIlluminationTypes; + + CEntityClass *wo_pecWorldBaseClass; // world base class (used for some special features) + + CBrushArchive &wo_baBrushes; // brush archive with all brushes in the world + CTerrainArchive &wo_taTerrains; // terrain archive with all terrains in the world + CDynamicContainer wo_cenAllEntities; // all entities including deleted but referenced ones + CDynamicContainer wo_cenPredictable; // predictable entities + CDynamicContainer wo_cenWillBePredicted; // entities that will be predicted + CDynamicContainer wo_cenPredicted; // predicted entities + CDynamicContainer wo_cenPredictor; // predictor entities + + class CCollisionGrid *wo_pcgCollisionGrid; + + COLOR wo_colBackground; // background color of this world + CEntityPointer wo_penBackgroundViewer; // viewer entity for background rendering + + CTString wo_strBackdropUp; // upper backdrop image + CTString wo_strBackdropFt; // front backdrop image + CTString wo_strBackdropRt; // right backdrop image + CTString wo_strBackdropObject; // 3d object that is rendered as backdrop + FLOAT wo_fUpW, wo_fUpL, wo_fUpCX, wo_fUpCZ; // size and position of upper backdrop image + FLOAT wo_fFtW, wo_fFtH, wo_fFtCX, wo_fFtCY; // size and position of front backdrop image + FLOAT wo_fRtL, wo_fRtH, wo_fRtCZ, wo_fRtCY; // size and position of right backdrop image + + CPlacement3D wo_plFocus; // focus placement in WED at the moment of world saving + FLOAT wo_fTargetDistance;// target distance in WED at the moment of world saving + CPlacement3D wo_plThumbnailFocus; // focus placement for thumbnail in WED + FLOAT wo_fThumbnailTargetDistance;// target distance for thumbnail in WED + + CTFileName wo_fnmFileName; // the file that the world was loaded from + SLONG wo_slStateDictionaryOffset; // offset of the world state filename dictionary + CTString wo_strName; // name of the level to be shown to player + ULONG wo_ulSpawnFlags; // spawn flags telling in which game modes can the level be played + CTString wo_strDescription; // description of the level (intro, mission, etc.) + + ULONG wo_ulNextEntityID; // next free ID for entities + CListHead wo_lhTimers; // timer scheduled entities + CListHead wo_lhMovers; // entities that want to/have to move + BOOL wo_bPortalLinksUpToDate; // set if portal-sector links are up to date + + /* Initialize collision grid. */ + void InitCollisionGrid(void); + /* Destroy collision grid. */ + void DestroyCollisionGrid(void); + /* Clear collision grid. */ + void ClearCollisionGrid(void); + + /* Add an entity to cell(s) in collision grid. */ + void AddEntityToCollisionGrid(CEntity *pen, const FLOATaabbox3D &boxEntity); + /* Remove an entity from cell(s) in collision grid. */ + void RemoveEntityFromCollisionGrid(CEntity *pen, const FLOATaabbox3D &boxEntity); + /* Move an entity inside cell(s) in collision grid. */ + void MoveEntityInCollisionGrid(CEntity *pen, + const FLOATaabbox3D &boxOld, const FLOATaabbox3D &boxNew); + /* Find all entities in collision grid near given box. */ + void FindEntitiesNearBox(const FLOATaabbox3D &boxNear, + CStaticStackArray &apenNearEntities); + + /* Create a new entity of given class. */ + CEntity *CreateEntity(const CPlacement3D &plPlacement, CEntityClass *pecClass); + /* Clear all entity pointers that point to this entity. */ + void UntargetEntity(CEntity *penToUntarget); + + /* Add an entity to list of timers. */ + void AddTimer(CRationalEntity *penTimer); + // set overdue timers to be due in current time + void AdjustLateTimers(TIME tmCurrentTime); + + // CSG operations for editing a world + /* Get a valid brush mip of brush for use in CSG operations. */ + CBrushMip *GetBrushMip(CEntity &enBrush); + /* Copy selected sectors of a source brush to a 3D object. */ + void CopySourceBrushSectorsToObject( + CEntity &enBrush, + CBrushSectorSelectionForCSG &bscselSectors, + const CPlacement3D &plSourcePlacement, + CObject3D &obObject, + const CPlacement3D &plTargetPlacement, + DOUBLEaabbox3D &boxSourceAbsolute + ); + /* Move sectors of a target brush that are affected, to a 3D object. */ + void MoveTargetBrushPartToObject( + CEntity &enBrush, + DOUBLEaabbox3D &boxAffected, + CObject3D &obObject + ); + /* Add 3D object sectors to a brush. */ + void AddObjectToBrush(CObject3D &obObject, CEntity &enBrush); + /* Do some CSG operation with one brush in this world and one brush in other world. */ + void DoCSGOperation( + CEntity &enThis, + CWorld &woOther, + CEntity &enOther, + const CPlacement3D &plOther, + void (CObject3D::*DoCSGOpenSector)(CObject3D &obA, CObject3D &obB), + void (CObject3D::*DoCSGClosedSectors)(CObject3D &obA, CObject3D &obB) + ); + + /* Copy all entities except one from another world to this one. */ + void CopyAllEntitiesExceptOne(CWorld &woOther, CEntity &enExcepted, + const CPlacement3D &plOtherSystem); + /* Join two sectors from one brush-mip together. */ + CBrushSector *JoinTwoSectors(CBrushSector &bscA, CBrushSector &bscB); + /* Split one sector by a 3D object. */ + void SplitOneSector(CBrushSector &bscToSplit, CObject3D &obToSplitBy); + + // read/write world information (description, name, flags...) + void ReadInfo_t(CTStream *strm, BOOL bMaybeDescription); // throw char * + void WriteInfo_t(CTStream *strm); // throw char * + + // mark all predictable entities that will be predicted using user-set criterions + void MarkForPrediction(void); + // unmark all predictable entities marked for prediction + void UnmarkForPrediction(void); + // create predictors for predictable entities that are marked for prediction + void CreatePredictors(void); + // delete all predictor entities + void DeletePredictors(void); + + // get entity by its ID + CEntity *EntityFromID(ULONG ulID); + // triangularize selected polygons + void TriangularizePolygons(CDynamicContainer &dcPolygons); +public: +// interface: + CDynamicContainer wo_cenEntities; // all entities in the world + + TIME wo_WorldGameTick; // game tick that world is currently in + + /* Constructor. */ + CWorld(void); + /* Destructor. */ + ~CWorld(void); + DECLARE_NOCOPYING(CWorld); + /* Clear all arrays. */ + void Clear(void); + + /* Lock all arrays. */ + void LockAll(void); + /* Unlock all arrays. */ + void UnlockAll(void); + + /* Create a new entity of given class. */ + CEntity *CreateEntity_t(const CPlacement3D &plPlacement, + const CTFileName &fnmClass); // throw char * + /* Copy one entity from another world into this one. */ + CEntity *CopyOneEntity(CEntity &enToCopy, const CPlacement3D &plOtherSystem); + /* Copy container of entities from another world to this one and select them. */ + void CopyEntities(CWorld &woOther, CDynamicContainer &cenToCopy, + CEntitySelection &senCopied, const CPlacement3D &plOtherSystem); + /* Copy entity in world. */ + CEntity *CopyEntityInWorld(CEntity &enOriginal, const CPlacement3D &plOtherEntity, + BOOL bWithDescendants = TRUE); + /* Destroy a selection of entities - reserved for use in WEd only! */ + void DestroyEntities(CEntitySelection &senToDestroy); + /* Destroy given entity - reserved for use in WEd only! */ + void DestroyOneEntity( CEntity *penToDestroy); + /* Find an entity with given character. */ + CPlayerEntity *FindEntityWithCharacter(CPlayerCharacter &pcCharacter); + + /* Copy entities for prediction. */ + void CopyEntitiesToPredictors(CDynamicContainer &cenToCopy); + + /* Cast a ray and see what it hits. */ + void CastRay(CCastRay &crRay); + /* Continue to cast already cast ray */ + void ContinueCast(CCastRay &crRay); + /* Test if a movement is clipped by something and where. */ + void ClipMove(CClipMove &cmMove); + + /* Set background color for this world. */ + void SetBackgroundColor(COLOR colBackground); + /* Get background color for this world. */ + COLOR GetBackgroundColor(void); + /* Set background viewer entity for this world. */ + void SetBackgroundViewer(CEntity *penEntity); + /* Get background viewer entity for this world. */ + CEntity *GetBackgroundViewer(void); + + /* Set description for this world. */ + void SetDescription(const CTString &strDescription); + /* Get description for this world. */ + const CTString &GetDescription(void); + + // get/set name of the world + void SetName(const CTString &strName); + const CTString &GetName(void); + // get/set spawn flags for the world + void SetSpawnFlags(ULONG ulFlags); + ULONG GetSpawnFlags(void); + + /* Save entire world (both brushes and current state). */ + void Save_t(const CTFileName &fnmWorld); // throw char * + /* Load entire world (both brushes and current state). */ + void Load_t(const CTFileName &fnmWorld); // throw char * + /* Reinitialize entities from their properties. (use only in WEd!) */ + void ReinitializeEntities(void); + /* Precache data needed by entities. */ + void PrecacheEntities_t(void); // throw char * + // delete all entities that don't fit given spawn flags + void FilterEntitiesBySpawnFlags(ULONG ulFlags); + + /* Read entire world (both brushes and current state). */ + void Read_t(CTStream *pistrm); // throw char * + /* Write entire world (both brushes and current state). */ + void Write_t(CTStream *postrm); // throw char * + + /* Load just world brushes from a file with entire world information. */ + void LoadBrushes_t(const CTFileName &fnmWorld); // throw char * + + /* Update sectors after brush vertex moving */ + void UpdateSectorsAfterVertexChange( CBrushVertexSelection &selVertex); + /* Update sectors during brush vertex moving */ + void UpdateSectorsDuringVertexChange( CBrushVertexSelection &selVertex); + /* Triangularize polygons that contain vertices from given selection */ + void TriangularizeForVertices( CBrushVertexSelection &selVertex); + /* Clears 'marked for use' flag on all polygons in world */ + void ClearMarkedForUseFlag(void); + + // CSG operations for editing worlds + /* Add a brush from another world to a brush in this world, other entities get copied. */ + void CSGAdd(CEntity &enThis, CWorld &woOther, CEntity &enOther, const CPlacement3D &plOther); + void CSGAddReverse(CEntity &enThis, CWorld &woOther, CEntity &enOther, const CPlacement3D &plOther); + /* Substract a brush from another world to a brush in this world. */ + void CSGRemove(CEntity &enThis, CWorld &woOther, CEntity &enOther, + const CPlacement3D &plOther); + /* Split selected sectors in a brush in this world with one brush in other world. + * (other brush must have only one sector.) + */ + void SplitSectors(CEntity &enThis, CBrushSectorSelection &selbscSectorsToSplit, + CWorld &woOther, CEntity &enOther, const CPlacement3D &plOther); + /* If two or more sectors can be joined. */ + BOOL CanJoinSectors(CBrushSectorSelection &selbscSectorsToJoin); + /* Join two or more sectors from one brush-mip together. */ + void JoinSectors(CBrushSectorSelection &selbscSectorsToJoin); + + /* Split selected polygons in a brush in this world with one brush in other world. + * (other brush must have only one sector.) + */ + void SplitPolygons(CEntity &enThis, CBrushPolygonSelection &selbpoPolygonsToSplit, + CWorld &woOther, CEntity &enOther, const CPlacement3D &plOther); + /* Join two or more polygons from one brush-sector together. */ + void JoinPolygons(CBrushPolygonSelection &selbpoPolygonsToJoin); + /* Test if a polygon selection can be joined. */ + BOOL CanJoinPolygons(CBrushPolygonSelection &selbpoPolygonsToJoin); + /* Join all selected polygons that can be joined. */ + void JoinAllPossiblePolygons(CBrushPolygonSelection &selbpoPolygonsToJoin, + BOOL bPreserveTextures, INDEX iTexture); + /* Test if a polygon selection can be joined. */ + BOOL CanJoinAllPossiblePolygons(CBrushPolygonSelection &selbpoPolygonsToJoin); + + /* Copy selected sectors from one brush to a new entity in another world. */ + BOOL CanCopySectors(CBrushSectorSelection &selbscSectorsToCopy); + void CopySectors(CBrushSectorSelection &selbscSectorsToCopy, CEntity *penTarget, BOOL bWithEntities); + /* Delete selected sectors. */ + void DeleteSectors(CBrushSectorSelection &selbscSectorsToDelete, BOOL bClearPortalFlags); + void CopyPolygonInWorld(CBrushPolygon &bpoSrc, CBrushSector &bsc, INDEX iPol, INDEX &iEdg, INDEX &iVtx); + void CopyPolygonsToBrush(CBrushPolygonSelection &selPolygons, CEntity *penbr); + void DeletePolygons(CDynamicContainer &dcPolygons); + void CreatePolygon(CBrushVertexSelection &selVtx); + void FlipPolygon(CBrushPolygon &bpo); + + // mirror and stretch another world into this one + void MirrorAndStretch(CWorld &woOriginal, FLOAT fStretch, enum WorldMirrorType wmt); + + // hide/show functions + /* Hide entities contained in given selection. */ + void HideSelectedEntities(CEntitySelection &selenEntitiesToHide); + /* Hide all unselected entities. */ + void HideUnselectedEntities(void); + /* Show all entities. */ + void ShowAllEntities(void); + /* Hide sectors contained in given selection. */ + void HideSelectedSectors(CBrushSectorSelection &selbscSectorsToHide); + /* Hide all unselected sectors. */ + void HideUnselectedSectors(void); + /* Show all sectors. */ + void ShowAllSectors(void); + + /* Selecting by texture in selected sectors */ + void SelectByTextureInSelectedSectors( CTFileName fnTexture, CBrushPolygonSelection &selbpoSimilar, INDEX iTexture); + /* Selecting by texture in world */ + void SelectByTextureInWorld( CTFileName fnTexture, CBrushPolygonSelection &selbpoSimilar, INDEX iTexture); + + // shadow manipulation functions + /* Recalculate all shadow maps that are not valid or of smaller precision. */ + void CalculateDirectionalShadows(void); + void CalculateNonDirectionalShadows(void); + /* Find all shadow layers near a certain position. */ + void FindShadowLayers(const FLOATaabbox3D &boxNear, BOOL bSelectedOnly=FALSE, BOOL bDirectional = TRUE); + /* Discard shadows on all brush polygons in the world. */ + void DiscardAllShadows(void); + + // create links between zoning brush sectors and non-zoning entities in sectors + void LinkEntitiesToSectors(void); + + // rebuild all links in world + void RebuildLinks(void); + + /* Read world brushes from stream. */ + void ReadBrushes_t( CTStream *istr); // throw char * + /* Write world brushes to stream. */ + void WriteBrushes_t( CTStream *ostr); // throw char * + + /* Read current world state from stream. */ + void ReadState_t( CTStream *istr); // throw char * + void ReadState_veryold_t( CTStream *istr); // throw char * + void ReadState_old_t( CTStream *istr); // throw char * + void ReadState_new_t( CTStream *istr); // throw char * + /* Write current world state to stream. */ + void WriteState_t( CTStream *ostr, BOOL bImportDictionary = FALSE); // throw char * +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/World/WorldCSG.cpp b/Sources/Engine/World/WorldCSG.cpp new file mode 100644 index 0000000..46601b1 --- /dev/null +++ b/Sources/Engine/World/WorldCSG.cpp @@ -0,0 +1,1380 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// assure that floating point precision is 53 bits +void AssureFPT_53(void) +{ + if (GetFPUPrecision()!=FPT_53BIT) { + ASSERTALWAYS( "Floating precision must be set to 53 bits during CSG!"); + SetFPUPrecision(FPT_53BIT); + } +} + + +///////////////////////////////////////////////////////////////////// +// CWorld editing operations +/* + * Get a valid brush mip of brush for use in CSG operations. + */ +CBrushMip *CWorld::GetBrushMip(CEntity &enBrush) +{ + // the entity must be brush + ASSERT(enBrush.en_RenderType == CEntity::RT_BRUSH || + enBrush.en_RenderType == CEntity::RT_FIELDBRUSH); + + // get the brush + CBrush3D &brBrush = *enBrush.en_pbrBrush; + + // get relevant mip as if in manual mip brushing mode + CBrushMip *pbm = brBrush.GetBrushMipByDistance(_wrpWorldRenderPrefs.GetManualMipBrushingFactor()); + return pbm; +} + +/* + * Copy selected sectors of a source brush to a 3D object. + */ +void CWorld::CopySourceBrushSectorsToObject( + CEntity &enBrush, + CBrushSectorSelectionForCSG &bscselSectors, + const CPlacement3D &plSourcePlacement, + CObject3D &obObject, + const CPlacement3D &plTargetPlacement, + DOUBLEaabbox3D &boxSourceAbsolute + ) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + // get the brush mip from the entity + CBrushMip &bmBrushMip = *GetBrushMip(enBrush); + + // calculate placement of the brush in absolute space (taking relative + // world placement and entity placement in account) + CPlacement3D plBrush = enBrush.en_plPlacement; + plBrush.RelativeToAbsolute(plSourcePlacement); + + // copy selected sectors of brush to object3d object + bmBrushMip.ToObject3D(obObject, bscselSectors); + + // make a copy of the object and find its box in absolute space + CObject3D obAbsolute; + obAbsolute = obObject; + CSimpleProjection3D_DOUBLE prToAbsolute; + prToAbsolute.ObjectPlacementL() = plBrush; + prToAbsolute.ViewerPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + prToAbsolute.Prepare(); + obAbsolute.Project(prToAbsolute); + obAbsolute.GetBoundingBox(boxSourceAbsolute); + + // project the brush into target space + CSimpleProjection3D_DOUBLE prSimple; + prSimple.ObjectPlacementL() = plBrush; + prSimple.ViewerPlacementL() = plTargetPlacement; + prSimple.Prepare(); + obObject.Project(prSimple); +} + +/* + * Move sectors of a target brush that are affected, to a 3D object. + */ +void CWorld::MoveTargetBrushPartToObject( + CEntity &enBrush, + DOUBLEaabbox3D &boxAffected, + CObject3D &obObject + ) +{ + ASSERT(GetFPUPrecision()==FPT_53BIT); + // get the brush mip from the entity + CBrushMip &bmBrushMip = *GetBrushMip(enBrush); + + // copy those sectors of brush touching given bbox to 3D object + CBrushSectorSelectionForCSG bscselSectors; + bmBrushMip.SelectSectorsInRange(bscselSectors, DOUBLEtoFLOAT(boxAffected)); + bmBrushMip.ToObject3D(obObject, bscselSectors); + bmBrushMip.DeleteSelectedSectors(bscselSectors); + // if no sectors are moved this way + if (obObject.ob_aoscSectors.Count()==0) { + // move the open sector to object + CBrushSectorSelectionForCSG bscselOpen; + bmBrushMip.SelectOpenSector(bscselOpen); + bmBrushMip.ToObject3D(obObject, bscselOpen); + bmBrushMip.DeleteSelectedSectors(bscselOpen); + } +} + +/* + * Add 3D object sectors to a brush. + */ +void CWorld::AddObjectToBrush(CObject3D &obObject, CEntity &enBrush) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_ADDOBJECTTOBRUSH); + + // get the brush mip from the entity + CBrushMip &bmBrushMip = *GetBrushMip(enBrush); + + // return the result to the source brush + try { + bmBrushMip.AddFromObject3D_t(obObject); + } catch (char *strError) { + FatalError("Unexpected error during CSG operation: %s", strError); + } + // update the bounding boxes of the brush + bmBrushMip.UpdateBoundingBox(); + //bmBrushMip.bm_pbrBrush->CalculateBoundingBoxes(); + // find possible shadow layers near affected area + FindShadowLayers(bmBrushMip.bm_boxBoundingBox); + + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_ADDOBJECTTOBRUSH); +} + +/* + * Do some CSG operation with one brush in this world and one brush in other world. + */ +void CWorld::DoCSGOperation( + CEntity &enThis, + CWorld &woOther, + CEntity &enOther, + const CPlacement3D &plOther, + void (CObject3D::*DoCSGOpenSector)(CObject3D &obA, CObject3D &obB), + void (CObject3D::*DoCSGClosedSectors)(CObject3D &obA, CObject3D &obB) + ) +{ + // assure that floating point precision is 53 bits + AssureFPT_53(); + + // get relevant brush mips in each brush + CBrushMip &bmThis = *GetBrushMip(enThis); + CBrushMip &bmOther = *GetBrushMip(enOther); + if (&bmThis==NULL || &bmOther==NULL) { + return; + } + + // get open sector of the other brush to object + CBrushSectorSelectionForCSG selbscOtherOpen; + bmOther.SelectOpenSector(selbscOtherOpen); + CObject3D obOtherOpen; + DOUBLEaabbox3D boxOtherOpen; + woOther.CopySourceBrushSectorsToObject(enOther, selbscOtherOpen, plOther, + obOtherOpen, enThis.en_plPlacement, boxOtherOpen); + + // if there is an open sector in other object + if (obOtherOpen.ob_aoscSectors.Count()>0) { + CObject3D obResult; + // deportalize the open sector + obOtherOpen.TurnPortalsToWalls(); + + // if there are any sectors in this brush + if (bmThis.bm_abscSectors.Count()>0) { + // move affected part of this brush to an object3d object + CObject3D obThis; + MoveTargetBrushPartToObject(enThis, boxOtherOpen, obThis); + // do the open sector CSG operation on the objects + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_OBJECTCSG); + (obResult.*DoCSGOpenSector)(obThis, obOtherOpen); + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_OBJECTCSG); + + // if there are no sectors in this brush + } else { + // just put the open sector directly in the result + obResult = obOtherOpen; + } + // return the result back to this brush + AddObjectToBrush(obResult, enThis); + } + + // get closed sectors of the other brush to object + CBrushSectorSelectionForCSG selbscOtherClosed; + bmOther.SelectClosedSectors(selbscOtherClosed); + CObject3D obOtherClosed; + DOUBLEaabbox3D boxOtherClosed; + woOther.CopySourceBrushSectorsToObject(enOther, selbscOtherClosed, plOther, + obOtherClosed, enThis.en_plPlacement, boxOtherClosed); + + // if there are closed sectors in other object + if (obOtherClosed.ob_aoscSectors.Count()>0) { + CObject3D obResult; + + // if there are any sectors in this brush + if (bmThis.bm_abscSectors.Count()>0) { + // move affected part of this brush to an object3d object + CObject3D obThis; + MoveTargetBrushPartToObject(enThis, boxOtherClosed, obThis); + // do the closed sectors CSG operation on the objects + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_OBJECTCSG); + (obResult.*DoCSGClosedSectors)(obThis, obOtherClosed); + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_OBJECTCSG); + + // if there are no sectors in this brush + } else { + // just put the closed sectors directly in the result + obResult = obOtherClosed; + } + // return the result back to this brush + AddObjectToBrush(obResult, enThis); + } +} + +/* + * Add a brush from another world to a brush in this world, other entities get copied. + */ +void CWorld::CSGAdd(CEntity &enThis, CWorld &woOther, CEntity &enOther, + const CPlacement3D &plOther) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_CSGTOTAL); + _pfWorldEditingProfile.IncrementAveragingCounter(); + // do add material for open sectors and then do add rooms for closed sectors + DoCSGOperation(enThis, woOther, enOther, plOther, + &CObject3D::CSGAddMaterial, &CObject3D::CSGAddRooms); + + // copy all other entities + CopyAllEntitiesExceptOne(woOther, enOther, plOther); + + // if the world doesn't have all portal-sector links updated + if (!wo_bPortalLinksUpToDate) { + // update the links + wo_baBrushes.LinkPortalsAndSectors(); + wo_bPortalLinksUpToDate = TRUE; + } + + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); +} +/* + * Add a brush from another world to a brush in this world, other entities get copied. + */ +void CWorld::CSGAddReverse(CEntity &enThis, CWorld &woOther, CEntity &enOther, + const CPlacement3D &plOther) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_CSGTOTAL); + _pfWorldEditingProfile.IncrementAveragingCounter(); + // do add material reverse for open sectors and then do add rooms for closed sectors + DoCSGOperation(enThis, woOther, enOther, plOther, + &CObject3D::CSGAddMaterialReverse, &CObject3D::CSGAddRooms); + + // copy all other entities + CopyAllEntitiesExceptOne(woOther, enOther, plOther); + + // if the world doesn't have all portal-sector links updated + if (!wo_bPortalLinksUpToDate) { + // update the links + wo_baBrushes.LinkPortalsAndSectors(); + wo_bPortalLinksUpToDate = TRUE; + } + + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); +} + +/* + * Substract a brush from another world to a brush in this world. + */ +void CWorld::CSGRemove(CEntity &enThis, CWorld &woOther, CEntity &enOther, + const CPlacement3D &plOther) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_CSGTOTAL); + _pfWorldEditingProfile.IncrementAveragingCounter(); + // assure that floating point precision is 53 bits + AssureFPT_53(); + + // get relevant brush mip in other brush + CBrushMip &bmOther = *GetBrushMip(enOther); + if (&bmOther==NULL) { + return; + } + + // if other brush has more than one sector + if (bmOther.bm_abscSectors.Count()>1) { + // join all sectors of the other brush together + CBrushSectorSelection selbscOtherAll; + bmOther.SelectAllSectors(selbscOtherAll); + woOther.JoinSectors(selbscOtherAll); + } + + // do 'remove material' with joined brush + DoCSGOperation(enThis, woOther, enOther, plOther, + &CObject3D::CSGRemoveMaterial, &CObject3D::CSGRemoveMaterial); + + // if the world doesn't have all portal-sector links updated + if (!wo_bPortalLinksUpToDate) { + // update the links + wo_baBrushes.LinkPortalsAndSectors(); + wo_bPortalLinksUpToDate = TRUE; + } + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); +} + +/* + * Split one sector by a 3D object. + */ +void CWorld::SplitOneSector(CBrushSector &bscToSplit, CObject3D &obToSplitBy) +{ + // get the brush mip from sector to split + CBrushMip *pbmMip = bscToSplit.bsc_pbmBrushMip; + + // create object to split from sector to split and destroy the sector + CBrushSectorSelectionForCSG selbscToSplit; + selbscToSplit.Select(bscToSplit); + CObject3D obToSplit; + pbmMip->ToObject3D(obToSplit, selbscToSplit); + pbmMip->DeleteSelectedSectors(selbscToSplit); + // copy ambient value from the sector to split to the sector to split with + obToSplitBy.ob_aoscSectors.Lock(); + obToSplitBy.ob_aoscSectors[0].osc_colAmbient = bscToSplit.bsc_colAmbient; + obToSplitBy.ob_aoscSectors[0].osc_colColor = bscToSplit.bsc_colColor; + obToSplitBy.ob_aoscSectors[0].osc_ulFlags[0] = bscToSplit.bsc_ulFlags; + obToSplitBy.ob_aoscSectors[0].osc_ulFlags[1] = bscToSplit.bsc_ulFlags2; + obToSplitBy.ob_aoscSectors[0].osc_ulFlags[2] = bscToSplit.bsc_ulVisFlags; + obToSplitBy.ob_aoscSectors.Unlock(); + + // do 'split sectors' CSG with the objects + CObject3D obResult; + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_OBJECTCSG); + obResult.CSGSplitSectors(obToSplit, obToSplitBy); + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_OBJECTCSG); + + // return the result to the source brush mip + try { + pbmMip->AddFromObject3D_t(obResult); + } catch (char *strError) { + FatalError("Unexpected error during split sectors operation: %s", strError); + } +} + +/* + * Split selected sectors in a brush in this world with one brush in other world. + * (other brush must have only one sector) + */ +void CWorld::SplitSectors(CEntity &enThis, CBrushSectorSelection &selbscSectorsToSplit, + CWorld &woOther, CEntity &enOther, const CPlacement3D &plOther) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_CSGTOTAL); + _pfWorldEditingProfile.IncrementAveragingCounter(); + // assure that floating point precision is 53 bits + AssureFPT_53(); + + // get relevant brush mip in this brush + CBrushMip &bmThis = *GetBrushMip(enThis); + if (&bmThis==NULL) { + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); + return; + } + + // get relevant brush mip in other brush + CBrushMip &bmOther = *GetBrushMip(enOther); + if (&bmOther==NULL) { + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); + return; + } + + /* Assure that the other brush has only one sector. */ + + // if other brush has more than one sector + if (bmOther.bm_abscSectors.Count()>1) { + // join all sectors of the other brush together + CBrushSectorSelection selbscOtherAll; + bmOther.SelectAllSectors(selbscOtherAll); + woOther.JoinSectors(selbscOtherAll); + } + + /* Split selected sectors with the one sector in the other brush. */ + + // get the sector of the other brush to object + CBrushSectorSelectionForCSG selbscOther; + bmOther.SelectAllSectors(selbscOther); + CObject3D obOther; + DOUBLEaabbox3D boxOther; + woOther.CopySourceBrushSectorsToObject(enOther, selbscOther, plOther, + obOther, enThis.en_plPlacement, boxOther); + + // if the selection is empty + if (selbscSectorsToSplit.Count()==0) { + // select all sectors near the splitting tool + bmThis.SelectSectorsInRange(selbscSectorsToSplit, DOUBLEtoFLOAT(boxOther)); + } + // for all sectors in the selection + FOREACHINDYNAMICCONTAINER(selbscSectorsToSplit, CBrushSector, itbsc) { + // split the sector using the copy of other object + SplitOneSector(*itbsc, CObject3D(obOther)); + } + + // update the bounding boxes of this brush + bmThis.bm_pbrBrush->CalculateBoundingBoxes(); + // find possible shadow layers near affected area + FindShadowLayers(DOUBLEtoFLOAT(boxOther)); + + /* NOTE: we must not clear the selection directly, since the sectors + contained there are already freed and deselecting them would make an access + violation. + */ + // clear the selection on the container level + selbscSectorsToSplit.CDynamicContainer::Clear(); + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); +} + +/* + * Join two sectors from one brush-mip together. + */ +CBrushSector *CWorld::JoinTwoSectors(CBrushSector &bscA, CBrushSector &bscB) +{ + // get the brush mip from sector A + CBrushMip *pbmMip = bscA.bsc_pbmBrushMip; + // the brush mip must be same for sector B + ASSERT(pbmMip == bscB.bsc_pbmBrushMip); + + // remember sector properties of sector A + COLOR colColor = bscA.bsc_colColor; + COLOR colAmbient = bscA.bsc_colAmbient; + + INDEX ctAPolygons = bscA.bsc_abpoPolygons.Count(); + + // create object A from sector A and destroy sector A + CBrushSectorSelectionForCSG selbscA; + selbscA.Select(bscA); + CObject3D obA; + pbmMip->ToObject3D(obA, selbscA); + pbmMip->DeleteSelectedSectors(selbscA); + + // create object B from sector B and destroy sector B + CBrushSectorSelectionForCSG selbscB; + selbscB.Select(bscB); + CObject3D obB; + pbmMip->ToObject3D(obB, selbscB); + pbmMip->DeleteSelectedSectors(selbscB); + + CObject3D obResult; + // if sector A has got at least one polygon + if (ctAPolygons>0) { + // do 'join sectors' CSG with objects A and B + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_OBJECTCSG); + obResult.CSGJoinSectors(obA, obB); + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_OBJECTCSG); + + // if sector A has got no polygons + // (this happens due to algorithm used in CWorld::JoinSectors()) + } else { + // just make result be object B + obResult = obB; + } + // return the result to the source brush mip + CBrushSector *pbscResult; + try { + pbscResult = pbmMip->AddFromObject3D_t(obResult); + } catch (char *strError) { + FatalError("Unexpected error during join sectors operation: %s", strError); + } + + if( obResult.ob_aoscSectors.Count() == 0) return NULL; + + // set sector properties of the resulting sector to be same as in former sector A + pbscResult->bsc_colColor = colColor; + pbscResult->bsc_colAmbient = colAmbient; + + // return the resulting sector (there is only one) + return pbscResult; +} + +/* + * If two or more sectors can be joined + */ +BOOL CWorld::CanJoinSectors(CBrushSectorSelection &selbscSectorsToJoin) +{ + if (selbscSectorsToJoin.Count()<2) return FALSE; + // get the brush mip from first sector in selection + selbscSectorsToJoin.Lock(); + CBrushSector *pbscFirstSector = &selbscSectorsToJoin[0]; + selbscSectorsToJoin.Unlock(); + CBrushMip *pbmMip = pbscFirstSector->bsc_pbmBrushMip; + + // for all sectors in the selection + FOREACHINDYNAMICCONTAINER(selbscSectorsToJoin, CBrushSector, itbsc) { + // if sectors are in the same mip + if( itbsc->bsc_pbmBrushMip != pbmMip) return FALSE; + } + return TRUE; +} + +/* + * Join two or more sectors from one brush-mip together. + */ +// this doesn't have to be member function of CWorld, but is here for future enhancements +void CWorld::JoinSectors(CBrushSectorSelection &selbscSectorsToJoin) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_CSGTOTAL); + _pfWorldEditingProfile.IncrementAveragingCounter(); + // get the brush mip from first sector in selection + selbscSectorsToJoin.Lock(); + CBrushSector *pbscFirstSector = &selbscSectorsToJoin[0]; + selbscSectorsToJoin.Unlock(); + CBrushMip *pbmMip = pbscFirstSector->bsc_pbmBrushMip; + + // create an empty result sector in the brush mip + CBrushSector *pbscResult = pbmMip->bm_abscSectors.New(1); + pbscResult->bsc_pbmBrushMip = pbmMip; + // give it same properties as the first selected sector + pbscResult->bsc_colColor = pbscFirstSector->bsc_colColor; + pbscResult->bsc_colAmbient = pbscFirstSector->bsc_colAmbient; + + // for all sectors in the selection + FOREACHINDYNAMICCONTAINER(selbscSectorsToJoin, CBrushSector, itbsc) { + // join the sector with the result sector + pbscResult = JoinTwoSectors(*pbscResult, *itbsc); + if( pbscResult == NULL) break; + } + + // update the bounding boxes of the brush + pbmMip->bm_pbrBrush->CalculateBoundingBoxes(); + // find possible shadow layers near affected area + FindShadowLayers(pbmMip->bm_boxBoundingBox); + + /* NOTE: we must not clear the selection directly, since the sectors + contained there are already freed and deselecting them would make an access + violation. + */ + // clear the selection on the container level + selbscSectorsToJoin.CDynamicContainer::Clear(); + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); +} + +/* + * Split selected polygons in a brush in this world with one brush in other world. + * (other brush must have only one sector.) + */ +void CWorld::SplitPolygons(CEntity &enThis, CBrushPolygonSelection &selbpoPolygonsToSplit, + CWorld &woOther, CEntity &enOther, const CPlacement3D &plOther) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_CSGTOTAL); + _pfWorldEditingProfile.IncrementAveragingCounter(); + + // get relevant brush mip in other brush + CBrushMip &bmOther = *GetBrushMip(enOther); + if (&bmOther==NULL) { + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); + return; + } + + selbpoPolygonsToSplit.Lock(); + INDEX ctSelectedPolygons = selbpoPolygonsToSplit.Count(); + + // get the brush sectors from all polygons in selection + CDynamicContainer cbscSectors; + {for(INDEX iselbpo=0; iselbpo::Clear(); + + // get the sector of the other brush to object + CBrushSectorSelectionForCSG selbscOther; + bmOther.SelectAllSectors(selbscOther); + CObject3D obOther; + DOUBLEaabbox3D boxOther; + woOther.CopySourceBrushSectorsToObject(enOther, selbscOther, plOther, + obOther, enThis.en_plPlacement, boxOther); + + // for each sector + cbscSectors.Lock(); + INDEX ctSectors = cbscSectors.Count(); + {for(INDEX ibsc=0; ibscbsc_pbmBrushMip; + // move the sector to 3D object + CBrushSectorSelectionForCSG bscselSector; + bscselSector.Select(*pbscSector); + CObject3D obSector; + pbmMip->ToObject3D(obSector, bscselSector); + pbmMip->DeleteSelectedSectors(bscselSector); + // split selected polygons in the object + CObject3D obResult; + obResult.CSGSplitPolygons(obSector, obOther); + + // return it back to brush mip + try { + pbmMip->AddFromObject3D_t(obResult); + } catch (char *strError) { + FatalError("Unexpected error during split polygons operation: %s", strError); + } + + // update the bounding boxes of the brush + pbmMip->bm_pbrBrush->CalculateBoundingBoxes(); + // find possible shadow layers near affected area + FindShadowLayers(pbmMip->bm_boxBoundingBox); + }} + + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); +} + +/* + * Test if a sector selection can be joined. + */ +BOOL CWorld::CanJoinPolygons(CBrushPolygonSelection &selbpoPolygonsToJoin) +{ + // if selection has less than two polygons + if (selbpoPolygonsToJoin.Count()<2) { + // it cannot be joined + return FALSE; + } + + // get the brush sector and plane from the first polygon in selection + selbpoPolygonsToJoin.Lock(); + CBrushPolygon *pbpoFirstPolygon = &selbpoPolygonsToJoin[0]; + selbpoPolygonsToJoin.Unlock(); + CBrushSector *pbscSector = pbpoFirstPolygon->bpo_pbscSector; + CBrushPlane *pbplPlane = pbpoFirstPolygon->bpo_pbplPlane; + + // for each polyon in selection + {FOREACHINDYNAMICCONTAINER(selbpoPolygonsToJoin, CBrushPolygon, itbpo) { + // if it has different sector or plane + if (itbpo->bpo_pbscSector!=pbscSector || itbpo->bpo_pbplPlane!=pbplPlane) { + // it cannot be joined + return FALSE; + } + }} + + // if all tests are passed, it can be joined + return TRUE; +} + +/* + * Join two or more polygons from one brush-sector together. + */ +void CWorld::JoinPolygons(CBrushPolygonSelection &selbpoPolygonsToJoin) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_CSGTOTAL); + _pfWorldEditingProfile.IncrementAveragingCounter(); + + // do not try do this if it is not possible + if (!CanJoinAllPossiblePolygons(selbpoPolygonsToJoin)) { + ASSERT(FALSE); + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); + return; + } + + selbpoPolygonsToJoin.Lock(); + INDEX ctSelectedPolygons = selbpoPolygonsToJoin.Count(); + + // get the brush sectors from all polygons in selection + CDynamicContainer cbscSectors; + {for(INDEX iselbpo=0; iselbpobsc_pbmBrushMip; + // move the sector to 3D object + CBrushSectorSelectionForCSG bscselSector; + bscselSector.Select(*pbscSector); + CObject3D obSector; + pbmMip->ToObject3D(obSector, bscselSector); + pbmMip->DeleteSelectedSectors(bscselSector); + + // return it back to brush mip + try { + pbmMip->AddFromObject3D_t(obSector); + } catch (char *strError) { + FatalError("Unexpected error during join polygons operation: %s", strError); + } + + // update the bounding boxes of the brush + pbmMip->bm_pbrBrush->CalculateBoundingBoxes(); + // find possible shadow layers near affected area + FindShadowLayers(pbmMip->bm_boxBoundingBox); + }} + + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); +} + +/* Test if a polygon selection can be joined. */ +BOOL CWorld::CanJoinAllPossiblePolygons(CBrushPolygonSelection &selbpoPolygonsToJoin) +{ + // if selection has less than two polygons + if (selbpoPolygonsToJoin.Count()<2) { + // it cannot be joined + return FALSE; + } + // if all tests are passed, it can be joined + return TRUE; +} + +struct JoinedPolygon { + INDEX jp_iTarget; + INDEX jp_ctEdges; +}; + +/* Join all selected polygons that can be joined. */ +void CWorld::JoinAllPossiblePolygons( + CBrushPolygonSelection &selbpoPolygonsToJoin, BOOL bPreserveTextures, INDEX iTexture) +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_CSGTOTAL); + _pfWorldEditingProfile.IncrementAveragingCounter(); + + // do not try do this if it is not possible + if (!CanJoinAllPossiblePolygons(selbpoPolygonsToJoin)) { + ASSERT(FALSE); + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); + return; + } + + selbpoPolygonsToJoin.Lock(); + INDEX ctSelectedPolygons = selbpoPolygonsToJoin.Count(); + + // get the brush sectors from all polygons in selection + CDynamicContainer cbscSectors; + {for(INDEX iselbpo=0; iselbpobsc_pbmBrushMip; + // move the sector to 3D object + CBrushSectorSelectionForCSG bscselSector; + bscselSector.Select(*pbscSector); + CObject3D obSector; + pbmMip->ToObject3D(obSector, bscselSector); + pbmMip->DeleteSelectedSectors(bscselSector); + + // return it back to brush mip + try { + pbmMip->AddFromObject3D_t(obSector); + } catch (char *strError) { + FatalError("Unexpected error during join all polygons operation: %s", strError); + } + + // update the bounding boxes of the brush + pbmMip->bm_pbrBrush->CalculateBoundingBoxes(); + // find possible shadow layers near affected area + FindShadowLayers(pbmMip->bm_boxBoundingBox); + }} + + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); +} + +/* Copy selected sectors from one brush to a new entity in another world. */ +BOOL CWorld::CanCopySectors(CBrushSectorSelection &selbscSectorsToCopy) +{ + if (selbscSectorsToCopy.Count()<1) return FALSE; + // get the brush mip from first sector in selection + selbscSectorsToCopy.Lock(); + CBrushSector *pbscFirstSector = &selbscSectorsToCopy[0]; + selbscSectorsToCopy.Unlock(); + CBrushMip *pbmMip = pbscFirstSector->bsc_pbmBrushMip; + + // for all sectors in the selection + FOREACHINDYNAMICCONTAINER(selbscSectorsToCopy, CBrushSector, itbsc) { + // if sectors are not in the same mip + if( itbsc->bsc_pbmBrushMip != pbmMip) return FALSE; + } + return TRUE; +} + +void CWorld::CopySectors(CBrushSectorSelection &selbscSectorsToCopy, CEntity *penTarget, + BOOL bWithEntities) +{ + // destination must be empty brush + ASSERT(penTarget->IsEmptyBrush()); + + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_CSGTOTAL); + _pfWorldEditingProfile.IncrementAveragingCounter(); + // do not try do this if it is not possible + if (!CanCopySectors(selbscSectorsToCopy)) { + ASSERT(FALSE); + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_CSGTOTAL); + return; + } + // assure that floating point precision is 53 bits + AssureFPT_53(); + + // get the brush mip from first sector in selection + selbscSectorsToCopy.Lock(); + CBrushSector *pbscFirstSector = &selbscSectorsToCopy[0]; + selbscSectorsToCopy.Unlock(); + CBrushMip *pbmMip = pbscFirstSector->bsc_pbmBrushMip; + CEntity *penSource = pbmMip->bm_pbrBrush->br_penEntity; + + // get destination mip + CBrushMip *pbmDestination = penTarget->en_pbrBrush->GetFirstMip(); + if (pbmDestination==NULL) { + ASSERT(FALSE); + return; + } + + // copy selected sectors of brush to object3d object + CObject3D obObject; + pbmMip->ToObject3D(obObject, selbscSectorsToCopy); + // get bounding box of the selection + DOUBLEaabbox3D boxSelection; + obObject.GetBoundingBox(boxSelection); + // find the bottom center of the selection + FLOAT3D vCenter = DOUBLEtoFLOAT(boxSelection.Center()); + vCenter(2) = DOUBLEtoFLOAT(boxSelection.Min()(2)); + // snap the center to 1m grid + Snap(vCenter(1), 1.0); + Snap(vCenter(2), 1.0); + Snap(vCenter(3), 1.0); + CPlacement3D plCenter(vCenter, ANGLE3D(0,0,0)); + CPlacement3D plCenterInverse(-vCenter, ANGLE3D(0,0,0)); + // make projection from source entity to center of selection + CSimpleProjection3D_DOUBLE prToCenter; + prToCenter.ObjectPlacementL() = penSource->en_plPlacement; + prToCenter.ViewerPlacementL() = plCenter; + prToCenter.Prepare(); + obObject.Project(prToCenter); + // convert the result to brush in target + AddObjectToBrush(obObject, *penTarget); + + if( bWithEntities) + { + // make a container of entities to copy + CDynamicContainer cenToCopy; + // for each of the selected sectors + {FOREACHINDYNAMICCONTAINER(selbscSectorsToCopy, CBrushSector, itbsc) { + // for each entity in the sector + {FOREACHDSTOFSRC(itbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) + // if it is not in container + if (!cenToCopy.IsMember(pen)) { + // add it to container + cenToCopy.Add(pen); + } + ENDFOR} + }} + + // copy all entities in the container to destination world + CEntitySelection senCopied; + penTarget->en_pwoWorld->CopyEntities(*this, cenToCopy, senCopied, plCenterInverse); + senCopied.Clear(); + } + + // if the world doesn't have all portal-sector links updated + if (!penTarget->en_pwoWorld->wo_bPortalLinksUpToDate) { + // update the links + penTarget->en_pwoWorld->wo_baBrushes.LinkPortalsAndSectors(); + penTarget->en_pwoWorld->wo_bPortalLinksUpToDate = TRUE; + } + + // if any portals are hanging (what is probable), fix them + GetBrushMip(*penTarget)->RemoveDummyPortals(TRUE); + + // if the world doesn't have all portal-sector links updated + if (!penTarget->en_pwoWorld->wo_bPortalLinksUpToDate) { + // update the links + penTarget->en_pwoWorld->wo_baBrushes.LinkPortalsAndSectors(); + penTarget->en_pwoWorld->wo_bPortalLinksUpToDate = TRUE; + } +} + +/* Delete selected sectors. */ +void CWorld::DeleteSectors(CBrushSectorSelection &selbscSectorsToDelete, BOOL bClearPortalFlags) +{ + CBrushMip *pbm = NULL; + // for each sector in the selection + {FOREACHINDYNAMICCONTAINER(selbscSectorsToDelete, CBrushSector, itbsc) { + // delete it from the brush mip + pbm = itbsc->bsc_pbmBrushMip; + pbm->bm_abscSectors.Delete(itbsc); + }} + // clear the selection on the container level + selbscSectorsToDelete.CDynamicContainer::Clear(); + + if (pbm==NULL) { + return; + } + + // if any portals are left hanging (what is probable), fix them + pbm->RemoveDummyPortals(bClearPortalFlags); + + // if the world doesn't have all portal-sector links updated + CWorld *pwo = pbm->bm_pbrBrush->br_penEntity->en_pwoWorld; + if (!pwo->wo_bPortalLinksUpToDate) { + // update the links + pwo->wo_baBrushes.LinkPortalsAndSectors(); + pwo->wo_bPortalLinksUpToDate = TRUE; + } +} + +void CheckOnePolygon(CBrushSector &bsc, CBrushPolygon &bpo) +{ + CBrushPlane *pbplPlane=bpo.bpo_pbplPlane; + INDEX ctEdges=bpo.bpo_abpePolygonEdges.Count(); + INDEX ctVertices=bpo.bpo_apbvxTriangleVertices.Count(); + for(INDEX iEdge=0;iEdgebsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + CEntity &enDst=*bscDst.bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + DOUBLEmatrix3D mdSrc=FLOATtoDOUBLE(enSrc.en_mRotation); + DOUBLEmatrix3D mdDst=FLOATtoDOUBLE(enDst.en_mRotation); + DOUBLE3D vdSrcOrigin=FLOATtoDOUBLE(enSrc.en_plPlacement.pl_PositionVector); + DOUBLE3D vdDstOrigin=FLOATtoDOUBLE(enDst.en_plPlacement.pl_PositionVector); + // calculate source absolute precise plane + DOUBLEplane3D plSrcAbsPrecise=plSrc.bpl_pldPreciseRelative*mdSrc+vdSrcOrigin; + plDst.bpl_plAbsolute=DOUBLEtoFLOAT(plSrcAbsPrecise); + // calculate destination relative precise plane + DOUBLEplane3D plDstRelPrecise=(plSrcAbsPrecise-vdDstOrigin)*!mdDst; + plDst.bpl_pldPreciseRelative=plDstRelPrecise; + GetMajorAxesForPlane(plDst.bpl_plAbsolute, + plDst.bpl_iPlaneMajorAxis1, + plDst.bpl_iPlaneMajorAxis2); + bpoDst.bpo_pbplPlane=&plDst; + + // copy vertices + INDEX ctEdg=bpoSrc.bpo_abpePolygonEdges.Count(); + bpoDst.bpo_abpePolygonEdges.New(ctEdg); + for( INDEX i=0; ibvx_vAbsolute)); + bscDst.bsc_abvxVertices[iVtx+1].SetAbsolutePosition(FLOATtoDOUBLE(pbvx1->bvx_vAbsolute)); + + CBrushEdge &edgDst=bscDst.bsc_abedEdges[iEdg]; + edgDst.bed_pbvxVertex0=&bscDst.bsc_abvxVertices[iVtx+0]; + edgDst.bed_pbvxVertex1=&bscDst.bsc_abvxVertices[iVtx+1]; + + iEdg+=1; + iVtx+=2; + + CBrushPolygonEdge &bpe=bpoDst.bpo_abpePolygonEdges[i]; + bpe.bpe_pbedEdge=&edgDst; + bpe.bpe_bReverse=FALSE; + } + bpoDst.CopyProperties(bpoSrc, TRUE); +} + +void CWorld::CopyPolygonsToBrush(CBrushPolygonSelection &selPolygons, CEntity *penbr) +{ + CBrushMip *pbrmip=penbr->en_pbrBrush->GetFirstMip(); + CBrushSector *pbscDst=pbrmip->bm_abscSectors.New(1); + pbscDst->bsc_colAmbient=C_BLACK|CT_OPAQUE; + pbscDst->bsc_pbmBrushMip=pbrmip; + + ASSERT(pbscDst!=NULL); + ASSERT(pbscDst->bsc_abvxVertices.Count()==0); + ASSERT(pbscDst->bsc_abedEdges.Count()==0); + ASSERT(pbscDst->bsc_abplPlanes.Count()==0); + ASSERT(pbscDst->bsc_abpoPolygons.Count()==0); + + INDEX ctPol=selPolygons.Count(); + ASSERT(ctPol!=0); + + // create polygons and planes + pbscDst->bsc_abpoPolygons.New(ctPol); + pbscDst->bsc_abplPlanes.New(ctPol); + // count edges + INDEX ctEdges=0; + {FOREACHINDYNAMICCONTAINER(selPolygons, CBrushPolygon, itbpo) + { + ctEdges+=itbpo->bpo_abpePolygonEdges.Count(); + }} + ASSERT(ctEdges!=0); + // create edges and vertices + pbscDst->bsc_abedEdges.New(ctEdges); + pbscDst->bsc_abvxVertices.New(ctEdges*2); + + {FOREACHINSTATICARRAY(pbscDst->bsc_abvxVertices, CBrushVertex, itbvx) + { + itbvx->bvx_pbscSector=pbscDst; + }} + + {FOREACHINSTATICARRAY(pbscDst->bsc_abpoPolygons, CBrushPolygon, itbpo) + { + itbpo->bpo_pbscSector=pbscDst; + }} + + INDEX iPol=0; + INDEX iVtx=0; + INDEX iEdg=0; + {FOREACHINDYNAMICCONTAINER(selPolygons, CBrushPolygon, itbpo) + { + CBrushPolygon &bpoSrc=*itbpo; + CopyPolygonInWorld( bpoSrc, *pbscDst, iPol, iEdg, iVtx); + iPol++; + }} + + // check polygon setup + /* + INDEX ctVertices=pbsc->bsc_abvxVertices.Count(); + INDEX ctEdgesControl=pbsc->bsc_abedEdges.Count(); + INDEX ctPlanes=pbsc->bsc_abplPlanes.Count(); + INDEX ctPolygons=pbsc->bsc_abpoPolygons.Count(); + + FOREACHINLIST(CBrushMip, bm_lnInBrush, penbr->GetBrush()->br_lhBrushMips, itbm) + { + CBrushMip &brmip=*itbm; + FOREACHINDYNAMICARRAY(itbm->bm_abscSectors, CBrushSector, itbsc) + { + CBrushSector &bsc=*itbsc; + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) + { + CBrushPolygon &bpo=*itbpo; + CheckOnePolygon(bsc, bpo); + } + } + } + */ + + // reoptimize it + pbscDst->bsc_pbmBrushMip->Reoptimize(); + + // update the bounding boxes of the brush + CBrushMip *pbrNewMip=penbr->en_pbrBrush->GetFirstMip(); + pbrNewMip->UpdateBoundingBox(); + RebuildLinks(); + // find possible shadow layers near affected area + FindShadowLayers(pbrNewMip->bm_boxBoundingBox); +} + +void CWorld::DeletePolygons(CDynamicContainer &dcPolygons) +{ + CDynamicContainer dcSectors; + + FOREACHINDYNAMICCONTAINER(dcPolygons, CBrushPolygon, itbpo) + { + CBrushPolygon &bpo = *itbpo; + bpo.bpo_ulFlags|=BPOF_MARKED_FOR_USE; + if( !dcSectors.IsMember(bpo.bpo_pbscSector)) + { + dcSectors.Add(bpo.bpo_pbscSector); + } + bpo.bpo_abpePolygonEdges.Clear(); + bpo.bpo_apbvxTriangleVertices.Clear(); + } + + // reoptimize mips + CDynamicContainer dcBrushMips; + {FOREACHINDYNAMICCONTAINER(dcSectors, CBrushSector, itbsc) + { + CBrushSector &bsc = *itbsc; + // reoptimize mips + if( !dcBrushMips.IsMember(bsc.bsc_pbmBrushMip)) + { + dcBrushMips.Add(bsc.bsc_pbmBrushMip); + } + }} + + {FOREACHINDYNAMICCONTAINER(dcBrushMips, CBrushMip, itbm) + { + itbm->Reoptimize(); + itbm->UpdateBoundingBox(); + FindShadowLayers(itbm->bm_boxBoundingBox); + }} + RebuildLinks(); +} + +void CWorld::CreatePolygon(CBrushVertexSelection &selVtx) +{ + if(selVtx.Count()!=3) return; + + CBrushSector *pbsc=NULL; + {FOREACHINDYNAMICCONTAINER(selVtx, CBrushVertex, itvtx) + { + CBrushVertex &bvtx=*itvtx; + if( bvtx.bvx_pbscSector==NULL || (pbsc!=NULL && pbsc!=bvtx.bvx_pbscSector)) return; + pbsc=bvtx.bvx_pbscSector; + }} + + selVtx.Lock(); + CBrushVertex &bv0=selVtx[0]; + CBrushVertex &bv1=selVtx[1]; + CBrushVertex &bv2=selVtx[2]; + selVtx.Unlock(); + + CBrushEdge *abpeOld=&pbsc->bsc_abedEdges[0]; + INDEX ctEdgesOld=pbsc->bsc_abedEdges.Count(); + pbsc->bsc_abedEdges.Expand(ctEdgesOld+3); + CBrushEdge *abpeNew=&pbsc->bsc_abedEdges[0]; + + CBrushPlane *abplOld=&pbsc->bsc_abplPlanes[0]; + INDEX ctPlanesOld=pbsc->bsc_abplPlanes.Count(); + pbsc->bsc_abplPlanes.Expand(ctPlanesOld+1); + CBrushPlane *abplNew=&pbsc->bsc_abplPlanes[0]; + + // remap edge pointers in sector's polygons + {FOREACHINSTATICARRAY(pbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) + { + CBrushPolygon &bpo = *itbpo; + for(INDEX iEdg=0; iEdgbsc_abedEdges[ctEdgesOld+0]; + CBrushEdge &be1=pbsc->bsc_abedEdges[ctEdgesOld+1]; + CBrushEdge &be2=pbsc->bsc_abedEdges[ctEdgesOld+2]; + be0.bed_pbvxVertex0=&bv0; + be0.bed_pbvxVertex1=&bv1; + be1.bed_pbvxVertex0=&bv1; + be1.bed_pbvxVertex1=&bv2; + be2.bed_pbvxVertex0=&bv2; + be2.bed_pbvxVertex1=&bv0; + + // initialize new plane + CBrushPlane &bplNew=pbsc->bsc_abplPlanes[ctPlanesOld]; + bplNew.bpl_pldPreciseRelative=DOUBLEplane3D(bv0.bvx_vdPreciseRelative, + bv1.bvx_vdPreciseRelative, + bv2.bvx_vdPreciseRelative); + bplNew.bpl_plRelative=DOUBLEtoFLOAT(bplNew.bpl_pldPreciseRelative); + + // calculate plane in absolute space + CEntity &en=*pbsc->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + DOUBLE3D vOrigin=FLOATtoDOUBLE(en.en_plPlacement.pl_PositionVector); + DOUBLEmatrix3D m=FLOATtoDOUBLE(en.en_mRotation); + DOUBLEplane3D plAbsPrecise=bplNew.bpl_pldPreciseRelative*m+vOrigin; + bplNew.bpl_plAbsolute=DOUBLEtoFLOAT(plAbsPrecise); + GetMajorAxesForPlane(bplNew.bpl_plAbsolute, + bplNew.bpl_iPlaneMajorAxis1, + bplNew.bpl_iPlaneMajorAxis2); + + // initialize working planes + pbsc->bsc_awplPlanes.Delete(); + pbsc->bsc_awplPlanes.New(ctPlanesOld+1); + for( INDEX iPlane=0; iPlanebsc_abplPlanes[iPlane].bpl_pwplWorking=&pbsc->bsc_awplPlanes[iPlane]; + } + + // initialize new polygon + INDEX ctOldPolygons=pbsc->bsc_abpoPolygons.Count(); + + CStaticArray abpNewPolygons; + abpNewPolygons.New(ctOldPolygons+1); + for(INDEX iPol=0; iPolbsc_abpoPolygons[iPol]); + } + + pbsc->bsc_abpoPolygons.MoveArray(abpNewPolygons); + CBrushPolygon &bpoNew = pbsc->bsc_abpoPolygons[ctOldPolygons]; + bpoNew.bpo_pbplPlane=&bplNew; + bpoNew.bpo_abpePolygonEdges.New(3); + bpoNew.bpo_abpePolygonEdges[0].bpe_pbedEdge=&be0; + bpoNew.bpo_abpePolygonEdges[0].bpe_bReverse=FALSE; + bpoNew.bpo_abpePolygonEdges[1].bpe_pbedEdge=&be1; + bpoNew.bpo_abpePolygonEdges[1].bpe_bReverse=FALSE; + bpoNew.bpo_abpePolygonEdges[2].bpe_pbedEdge=&be2; + bpoNew.bpo_abpePolygonEdges[2].bpe_bReverse=FALSE; + bpoNew.bpo_apbvxTriangleVertices.New(3); + bpoNew.bpo_apbvxTriangleVertices[0]=&bv0; + bpoNew.bpo_apbvxTriangleVertices[1]=&bv1; + bpoNew.bpo_apbvxTriangleVertices[2]=&bv2; + bpoNew.bpo_aiTriangleElements.New(3); + bpoNew.bpo_aiTriangleElements[0]=0; + bpoNew.bpo_aiTriangleElements[1]=1; + bpoNew.bpo_aiTriangleElements[2]=2; + bpoNew.bpo_pbscSector=pbsc; + + bpoNew.bpo_colColor=C_GRAY|CT_OPAQUE; + bpoNew.bpo_colShadow=C_WHITE|CT_OPAQUE; + + pbsc->bsc_pbmBrushMip->bm_pbrBrush->CalculateBoundingBoxes(); + + // create array of working edges + INDEX cted = pbsc->bsc_abedEdges.Count(); + pbsc->bsc_awedEdges.Clear(); + pbsc->bsc_awedEdges.New(cted); + // for each edge + for (INDEX ied=0; iedbsc_awedEdges[ied]; + CBrushEdge &bed = pbsc->bsc_abedEdges[ied]; + // setup its working edge + bed.bed_pwedWorking = &wed; + wed.wed_iwvx0 = pbsc->bsc_abvxVertices.Index(bed.bed_pbvxVertex0); + wed.wed_iwvx1 = pbsc->bsc_abvxVertices.Index(bed.bed_pbvxVertex1); + } + pbsc->UpdateSector(); +} + +void CWorld::FlipPolygon(CBrushPolygon &bpo) +{ + CBrushSector &bsc=*bpo.bpo_pbscSector; + + DOUBLEplane3D plOldPreciseRel=bpo.bpo_pbplPlane->bpl_pldPreciseRelative; + // create new array of planes + CBrushPlane *abplOld=&bsc.bsc_abplPlanes[0]; + INDEX ctPlanesOld=bsc.bsc_abplPlanes.Count(); + bsc.bsc_abplPlanes.Expand(ctPlanesOld+1); + CBrushPlane *abplNew=&bsc.bsc_abplPlanes[0]; + + // remap plane ptrs + {FOREACHINSTATICARRAY(bsc.bsc_abpoPolygons, CBrushPolygon, itbpo) + { + CBrushPolygon &bpo = *itbpo; + bpo.bpo_pbplPlane=(CBrushPlane*)((UBYTE*)bpo.bpo_pbplPlane+((UBYTE*)abplNew-(UBYTE*)abplOld)); + }} + + // invert order of triangle vertices + for( INDEX iVtx=0; iVtxbm_pbrBrush->br_penEntity; + DOUBLE3D vOrigin=FLOATtoDOUBLE(en.en_plPlacement.pl_PositionVector); + DOUBLEmatrix3D m=FLOATtoDOUBLE(en.en_mRotation); + DOUBLEplane3D plAbsPrecise=bplNew.bpl_pldPreciseRelative*m+vOrigin; + bplNew.bpl_plAbsolute=DOUBLEtoFLOAT(plAbsPrecise); + GetMajorAxesForPlane(bplNew.bpl_plAbsolute, + bplNew.bpl_iPlaneMajorAxis1, + bplNew.bpl_iPlaneMajorAxis2); + + // set new plane ptr + bpo.bpo_pbplPlane=&bplNew; + + // initialize working planes + bsc.bsc_awplPlanes.Delete(); + bsc.bsc_awplPlanes.New(ctPlanesOld+1); + for( INDEX iPlane=0; iPlane +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// these are used for making projections for converting from X space to Y space this way: +// MatrixMulT(mY, mX, mXToY); +// VectMulT(mY, vX-vY, vXToY); + +// C=AtxB +static inline void MatrixMulT(const FLOATmatrix3D &mA, const FLOATmatrix3D &mB, FLOATmatrix3D &mC) +{ + mC(1,1) = mA(1,1)*mB(1,1)+mA(2,1)*mB(2,1)+mA(3,1)*mB(3,1); + mC(1,2) = mA(1,1)*mB(1,2)+mA(2,1)*mB(2,2)+mA(3,1)*mB(3,2); + mC(1,3) = mA(1,1)*mB(1,3)+mA(2,1)*mB(2,3)+mA(3,1)*mB(3,3); + + mC(2,1) = mA(1,2)*mB(1,1)+mA(2,2)*mB(2,1)+mA(3,2)*mB(3,1); + mC(2,2) = mA(1,2)*mB(1,2)+mA(2,2)*mB(2,2)+mA(3,2)*mB(3,2); + mC(2,3) = mA(1,2)*mB(1,3)+mA(2,2)*mB(2,3)+mA(3,2)*mB(3,3); + + mC(3,1) = mA(1,3)*mB(1,1)+mA(2,3)*mB(2,1)+mA(3,3)*mB(3,1); + mC(3,2) = mA(1,3)*mB(1,2)+mA(2,3)*mB(2,2)+mA(3,3)*mB(3,2); + mC(3,3) = mA(1,3)*mB(1,3)+mA(2,3)*mB(2,3)+mA(3,3)*mB(3,3); +} +// v2 = Mt*v1 +static inline void VectMulT(const FLOATmatrix3D &mM, const FLOAT3D &vV1, FLOAT3D &vV2) +{ + vV2(1) = vV1(1)*mM(1,1)+vV1(2)*mM(2,1)+vV1(3)*mM(3,1); + vV2(2) = vV1(1)*mM(1,2)+vV1(2)*mM(2,2)+vV1(3)*mM(3,2); + vV2(3) = vV1(1)*mM(1,3)+vV1(2)*mM(2,3)+vV1(3)*mM(3,3); +} + +///////////////////////////////////////////////////////////////////// +// CClipMove + +// get start and end positions of an entity in this tick +inline void CClipMove::GetPositionsOfEntity( + CEntity *pen, FLOAT3D &v0, FLOATmatrix3D &m0, FLOAT3D &v1, FLOATmatrix3D &m1) +{ + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_GETPOSITIONSOFENTITY); + + // start is where entity is now + v0 = pen->en_plPlacement.pl_PositionVector; + m0 = pen->en_mRotation; + // if entity is movable + if (pen->en_ulPhysicsFlags&EPF_MOVABLE) { + // get end position from movable entity + CMovableEntity *penMovable = (CMovableEntity*)pen; + v1 = penMovable->en_vNextPosition; + m1 = penMovable->en_mNextRotation; + + // NOTE: this prevents movable entities from hanging in the air when a brush moves + // beneath their feet + + // if moving entity is reference of this entity + if (penMovable->en_penReference == cm_penMoving) { + // add this entity to list of movers + penMovable->AddToMoversDuringMoving(); + } + + // if entity is not movable + } else { + // end position is same as start + v1 = v0; + m1 = m0; + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_GETPOSITIONSOFENTITY); +} + +/* + * Constructor. + */ +CClipMove::CClipMove(CMovableEntity *penEntity) +{ + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_PREPARECLIPMOVE); + + // clear last-hit statistics + cm_penHit = NULL; + cm_pbpoHit = NULL; + cm_fMovementFraction = 2.0f; + + cm_penMoving = penEntity; + // if the entity is deleted, or couldn't possible collide with anything + if ((cm_penMoving->en_ulFlags&ENF_DELETED) + ||!(cm_penMoving->en_ulCollisionFlags&ECF_TESTMASK) + ||cm_penMoving->en_pciCollisionInfo==NULL) { + // do nothing + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_PREPARECLIPMOVE); + return; + } + + // if entity is model + if (penEntity->en_RenderType==CEntity::RT_MODEL || + penEntity->en_RenderType==CEntity::RT_EDITORMODEL || + penEntity->en_RenderType==CEntity::RT_SKAMODEL || + penEntity->en_RenderType==CEntity::RT_SKAEDITORMODEL ) { + cm_bMovingBrush = FALSE; + + // remember entity and placements + cm_penA = penEntity; + GetPositionsOfEntity(cm_penA, cm_vA0, cm_mA0, cm_vA1, cm_mA1); + + // create spheres for the entity + ASSERT(penEntity->en_pciCollisionInfo!=NULL); + cm_pamsA = &penEntity->en_pciCollisionInfo->ci_absSpheres; + + // create aabbox for entire movement path + FLOATaabbox3D box0, box1; + penEntity->en_pciCollisionInfo->MakeBoxAtPlacement(cm_vA0, cm_mA0, box0); + penEntity->en_pciCollisionInfo->MakeBoxAtPlacement(cm_vA1, cm_mA1, box1); + cm_boxMovementPath = box0; + cm_boxMovementPath |= box1; + + // if entity is brush + } else if (penEntity->en_RenderType==CEntity::RT_BRUSH) { + cm_bMovingBrush = TRUE; + + // remember entity and placements + cm_penB = penEntity; + GetPositionsOfEntity(cm_penB, cm_vB0, cm_mB0, cm_vB1, cm_mB1); + + // create spheres for the entity + ASSERT(penEntity->en_pciCollisionInfo!=NULL); + // create aabbox for entire movement path + FLOATaabbox3D box0, box1; + penEntity->en_pciCollisionInfo->MakeBoxAtPlacement(cm_vB0, cm_mB0, box0); + penEntity->en_pciCollisionInfo->MakeBoxAtPlacement(cm_vB1, cm_mB1, box1); + cm_boxMovementPath = box0; + cm_boxMovementPath |= box1; + + } else { + ASSERT(FALSE); + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_PREPARECLIPMOVE); +} + +// send pass if needed +inline BOOL CClipMove::SendPassEvent(CEntity *penTested) +{ + BOOL bSent = FALSE; + if (cm_ulPassMaskA & penTested->en_ulCollisionFlags) { + + EPass ePassA; + ePassA.penOther = penTested; + ePassA.bThisMoved = TRUE; + cm_penMoving->SendEvent(ePassA); + + bSent = TRUE; + } + if (cm_ulPassMaskB & penTested->en_ulCollisionFlags) { + + EPass ePassB; + ePassB.penOther = cm_penMoving; + ePassB.bThisMoved = FALSE; + penTested->SendEvent(ePassB); + + bSent = TRUE; + } + + return bSent; +} + +/* + * Clip a moving point to a sphere, update collision data. + */ +inline void CClipMove::ClipMovingPointToSphere( + const FLOAT3D &vStart, + const FLOAT3D &vEnd, + const FLOAT3D &vSphereCenter, + const FLOAT fSphereRadius) +{ + const FLOAT3D vSphereCenterToStart = vStart - vSphereCenter; + const FLOAT3D vStartToEnd = vEnd - vStart; + // calculate discriminant for intersection parameters + const FLOAT fP = ((vStartToEnd%vSphereCenterToStart)/(vStartToEnd%vStartToEnd)); + const FLOAT fQ = (((vSphereCenterToStart%vSphereCenterToStart) + - (fSphereRadius*fSphereRadius))/(vStartToEnd%vStartToEnd)); + const FLOAT fD = fP*fP-fQ; + // if it is less than zero + if (fD<0) { + // no collision will occur + return; + } + // calculate intersection parameters + const FLOAT fSqrtD = sqrt(fD); + const FLOAT fLambda1 = -fP+fSqrtD; + const FLOAT fLambda2 = -fP-fSqrtD; + // use lower one + const FLOAT fMinLambda = Min(fLambda1, fLambda2); + // if it is betwen zero and last collision found + if (0.0f<=fMinLambda && fMinLambdabpo_pbplPlane->bpl_plRelative; + // calculate point distances from polygon plane + FLOAT fDistance0 = plPolygon.PointDistance(msMoving.ms_vRelativeCenter0)-msMoving.ms_fR; + FLOAT fDistance1 = plPolygon.PointDistance(msMoving.ms_vRelativeCenter1)-msMoving.ms_fR; + + // if first point is in front and second point is behind + if (fDistance0>=0 && fDistance1<0) { + // calculate fraction of line before intersection + FLOAT fFraction = fDistance0/(fDistance0-fDistance1); + ASSERT(fFraction>=0.0f && fFraction<=1.0f); + + // if fraction is less than minimum found fraction + if (fFractionbpo_abpePolygonEdges, CBrushPolygonEdge, + itbpePolygonEdge) { + // get edge vertices (edge direction is irrelevant here!) + const FLOAT3D &vVertex0 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex0->bvx_vRelative; + const FLOAT3D &vVertex1 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex1->bvx_vRelative; + // pass the edge to the intersector + isIntersector.AddEdge( + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2), + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2)); + } + // if the polygon is intersected by the ray + if (isIntersector.IsIntersecting()) { + // if cannot pass + if (!SendPassEvent(cm_penTested)) { + // mark this as the new closest found collision point + cm_fMovementFraction = fFraction; + cm_vClippedLine = msMoving.ms_vRelativeCenter1 - vPosMid; + ASSERT(cm_vClippedLine.Length()<100.0f); + // project the collision plane from space B to absolute space + // only the normal of the plane is correct, not the distance!!!! + cm_plClippedPlane = plPolygon*cm_mBToAbsolute+cm_vBToAbsolute; + // remember hit entity + cm_penHit = cm_penTested; + cm_pbpoHit = cm_pbpoTested; + } + } + } + } + + // for each edge in polygon + FOREACHINSTATICARRAY(pbpoPolygon->bpo_abpePolygonEdges, CBrushPolygonEdge, itbpe) { + // get edge vertices (edge direction is important here!) + FLOAT3D vVertex0, vVertex1; + itbpe->GetVertexCoordinatesRelative(vVertex0, vVertex1); + + // clip moving sphere to the edge (moving point to the edge cylinder) + ClipMovingPointToCylinder( + msMoving.ms_vRelativeCenter0, // start, + msMoving.ms_vRelativeCenter1, // end, + vVertex0, // cylinder bottom center, + vVertex1, // cylinder top center, + msMoving.ms_fR // cylinder radius + ); + // clip moving sphere to the first vertex + // NOTE: use moving point to sphere collision + ClipMovingPointToSphere( + msMoving.ms_vRelativeCenter0, // start + msMoving.ms_vRelativeCenter1, // end + vVertex0, // sphere center + msMoving.ms_fR // sphere radius + ); + } +} + +/* Clip a moving sphere to a terrain polygon, update collision data. */ +void CClipMove::ClipMovingSphereToTerrainPolygon( + const CMovingSphere &msMoving, const FLOAT3D &v0, const FLOAT3D &v1, const FLOAT3D &v2) +{ + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_SPHERETOPOLYGONTESTS); + cm_pbpoTested = NULL; + + const FLOATplane3D plPolygon = FLOATplane3D(v0,v1,v2); + + // calculate point distances from polygon plane + FLOAT fDistance0 = plPolygon.PointDistance(msMoving.ms_vRelativeCenter0)-msMoving.ms_fR; + FLOAT fDistance1 = plPolygon.PointDistance(msMoving.ms_vRelativeCenter1)-msMoving.ms_fR; + + // if first point is in front and second point is behind + if (fDistance0>=0 && fDistance1<0) { + // calculate fraction of line before intersection + FLOAT fFraction = fDistance0/(fDistance0-fDistance1); + ASSERT(fFraction>=0.0f && fFraction<=1.0f); + + // if fraction is less than minimum found fraction + if (fFractionms_vRelativeCenter0 = itmsA->ms_vCenter*cm_mAToB0+cm_vAToB0; + // project it in end point + itmsA->ms_vRelativeCenter1 = itmsA->ms_vCenter*cm_mAToB1+cm_vAToB1; + // make bounding box + itmsA->ms_boxMovement = FLOATaabbox3D(itmsA->ms_vRelativeCenter0, itmsA->ms_vRelativeCenter1); + itmsA->ms_boxMovement.Expand(itmsA->ms_fR); + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_PROJECTASPHERESTOB); +} + +/* Find movement box in absolute space for A entity. */ +void CClipMove::FindAbsoluteMovementBoxForA(void) +{ +/* + // position at beginning of movement is absolute position + FLOAT3D &vPosition0 = cm_vA0; + FLOATmatrix3D &mRotation0 = cm_mA0; + + FLOATmatrix3D mB0Abs, mB1Abs; + FLOAT3D vB0Abs, vB1Abs; + + // make absolute positions of B0 and B1 + mB0Abs.Diagonal(1.0f); + vB0Abs = FLOAT3D(0,0,0); + + vAToB0 + mAToB0 + + MatrixMulT(cm_mB1, cm_mB0, mB1Abs); + VectMulT(cm_mB1, cm_vB0-cm_vB1, vB1Abs); + +// these are used for making projections for converting from X space to Y space this way: +// MatrixMulT(mY, mX, mXToY); +// VectMulT(mY, vX-vY, vXToY); + + FLOAT3D vPosition1; + FLOATmatrix3D mRotation1; + + MatrixMulT(mB1Abs, cm_mA0, mRotation1); + VectMulT(mB1Abs, cm_vA0-vB1Abs, vPosition1); + + FLOATaabbox3D box0, box1; + cm_penA->en_pciCollisionInfo->MakeBoxAtPlacement(vPosition0, mRotation0, box0); + cm_penA->en_pciCollisionInfo->MakeBoxAtPlacement(vPosition1, mRotation1, box1); + cm_boxMovementPathAbsoluteA = box0; + cm_boxMovementPathAbsoluteA |= box1; +*/ + + cm_boxMovementPathAbsoluteA = FLOATaabbox3D(); + // for each sphere + FOREACHINSTATICARRAY(*cm_pamsA, CMovingSphere, itmsA) { + // project it in start point + FLOAT3D v0 = (itmsA->ms_vCenter*cm_mAToB0+cm_vAToB0)*cm_mB0+cm_vB0; + // project it in end point + FLOAT3D v1 = (itmsA->ms_vCenter*cm_mAToB1+cm_vAToB1)*cm_mB0+cm_vB0; + // make bounding box + FLOATaabbox3D box = FLOATaabbox3D(v0, v1); + box.Expand(itmsA->ms_fR); + cm_boxMovementPathAbsoluteA|=box; + } +} + +/* + * Clip movement if B is a model. + */ +void CClipMove::ClipModelMoveToModel(void) +{ + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPMODELMOVETOMODEL); + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_MODELMODELTESTS); + + // assumes that all spheres in one entity have same radius + FLOAT fRB = (*cm_pamsB)[0].ms_fR; + + // for each sphere in entity A + FOREACHINSTATICARRAY(*cm_pamsA, CMovingSphere, itmsA) { + CMovingSphere &msA = *itmsA; + FLOATaabbox3D &boxMovingSphere = msA.ms_boxMovement; + + // for each sphere in entity B + FOREACHINSTATICARRAY(*cm_pamsB, CMovingSphere, itmsB) { + CMovingSphere &msB = *itmsB; + // if the sphere is too far + if ( + (boxMovingSphere.Min()(1)>msB.ms_vCenter(1)+fRB) || + (boxMovingSphere.Max()(1)msB.ms_vCenter(2)+fRB) || + (boxMovingSphere.Max()(2)msB.ms_vCenter(3)+fRB) || + (boxMovingSphere.Max()(3)en_pbrBrush->GetFirstMip(); + // for each sector in the brush mip + FOREACHINDYNAMICARRAY(pbmMip->bm_abscSectors, CBrushSector, itbsc) { + // if the sector's bbox has no contact with bbox of movement path + if ( !itbsc->bsc_boxBoundingBox.HasContactWith(cm_boxMovementPathAbsoluteA, 0.01f) ) { + // skip it + continue; + } + // for each polygon in the sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + // if it is passable or its bbox has no contact with bbox of movement path + if ((itbpo->bpo_ulFlags&BPOF_PASSABLE) + ||!itbpo->bpo_boxBoundingBox.HasContactWith(cm_boxMovementPathAbsoluteA, 0.01f) ) { + // skip it + continue; + } + // clip movement to the polygon + ClipMoveToBrushPolygon(itbpo); + } + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPBRUSHMOVETOMODEL); +} + +/* + * Prepare projections and spheres for movement clipping. + */ +void CClipMove::PrepareProjectionsAndSpheres(void) +{ + // Formula: C=AxB --> Cij=Sum(s=1..k)(Ais*Bsj) + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_PREPAREPROJECTIONSANDSPHERES); + // make projections for converting from A space to B space + MatrixMulT(cm_mB0, cm_mA0, cm_mAToB0); + VectMulT(cm_mB0, cm_vA0-cm_vB0, cm_vAToB0); + MatrixMulT(cm_mB1, cm_mA1, cm_mAToB1); + VectMulT(cm_mB1, cm_vA1-cm_vB1, cm_vAToB1); + + // projection for converting from B space to absolute space + cm_mBToAbsolute = cm_mB0; + cm_vBToAbsolute = cm_vB0; + + // project spheres of entity A to space B + ProjectASpheresToB(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_PREPAREPROJECTIONSANDSPHERES); +} + +/* + * Clip movement to a model entity. + */ +void CClipMove::ClipMoveToModel(CEntity *penModel) +{ + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPMOVETOMODEL); + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_MODELXTESTS); + + // if not possibly colliding + ASSERT(penModel->en_pciCollisionInfo!=NULL); + const FLOATaabbox3D &boxModel = penModel->en_pciCollisionInfo->ci_boxCurrent; + if ( + (cm_boxMovementPath.Min()(1)>boxModel.Max()(1)) || + (cm_boxMovementPath.Max()(1)boxModel.Max()(2)) || + (cm_boxMovementPath.Max()(2)boxModel.Max()(3)) || + (cm_boxMovementPath.Max()(3)en_pciCollisionInfo!=NULL); + cm_pamsB = &penModel->en_pciCollisionInfo->ci_absSpheres; + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPMOVETOMODELNONTRIVIAL); + // prepare new projections and spheres + PrepareProjectionsAndSpheres(); + // clip model to model + ClipModelMoveToModel(); + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPMOVETOMODELNONTRIVIAL); + + // if clipping a moving brush + } else { + // moving brush is B and still model is A + cm_penA = penModel; + GetPositionsOfEntity(cm_penA, cm_vA0, cm_mA0, cm_vA1, cm_mA1); + // create bounding spheres for the model + ASSERT(penModel->en_pciCollisionInfo!=NULL); + cm_pamsA = &penModel->en_pciCollisionInfo->ci_absSpheres; + + // prepare new projections and spheres + PrepareProjectionsAndSpheres(); + FindAbsoluteMovementBoxForA(); + // clip brush to model + ClipBrushMoveToModel(); + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPMOVETOMODEL); +} + +/* Cache near polygons of movable entity. */ +void CClipMove::CacheNearPolygons(void) +{ + // if movement box is still inside cached box + if (cm_boxMovementPath<=cm_penMoving->en_boxNearCached) { + // do nothing + return; + } + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CACHENEARPOLYGONS); + _pfPhysicsProfile.IncrementTimerAveragingCounter( + CPhysicsProfile::PTI_CACHENEARPOLYGONS, 1); + + + FLOATaabbox3D &box = cm_penMoving->en_boxNearCached; + CStaticStackArray &apbpo = cm_penMoving->en_apbpoNearPolygons; + + // flush old cached polygons + apbpo.PopAll(); + // set new box to union of movement box and future estimate + box = cm_boxMovementPath; + box |= cm_penMoving->en_boxMovingEstimate; + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CACHENEARPOLYGONS_ADDINITIAL); + // for each zoning sector that this entity is in + {FOREACHSRCOFDST(cm_penMoving->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // add it to list of active sectors + cm_lhActiveSectors.AddTail(pbsc->bsc_lnInActiveSectors); + ENDFOR} + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CACHENEARPOLYGONS_ADDINITIAL); + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CACHENEARPOLYGONS_MAINLOOP); + // for each active sector + FOREACHINLIST(CBrushSector, bsc_lnInActiveSectors, cm_lhActiveSectors, itbsc) { + _pfPhysicsProfile.IncrementTimerAveragingCounter( + CPhysicsProfile::PTI_CACHENEARPOLYGONS_MAINLOOP, 1); + // for each polygon in the sector + FOREACHINSTATICARRAY(itbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + CBrushPolygon *pbpo = itbpo; + // if its bbox has no contact with bbox to cache + if (!pbpo->bpo_boxBoundingBox.HasContactWith(box) ) { + // skip it + continue; + } + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CACHENEARPOLYGONS_MAINLOOPFOUND); + _pfPhysicsProfile.IncrementTimerAveragingCounter( + CPhysicsProfile::PTI_CACHENEARPOLYGONS_MAINLOOPFOUND, 1); + // add it to cache + apbpo.Push() = pbpo; + // if it is passable + if (pbpo->bpo_ulFlags&BPOF_PASSABLE) { + // for each sector related to the portal + {FOREACHDSTOFSRC(pbpo->bpo_rsOtherSideSectors, CBrushSector, bsc_rdOtherSidePortals, pbscRelated) + // if the sector is not active + if (!pbscRelated->bsc_lnInActiveSectors.IsLinked()) { + // add it to active list + cm_lhActiveSectors.AddTail(pbscRelated->bsc_lnInActiveSectors); + } + ENDFOR} + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CACHENEARPOLYGONS_MAINLOOPFOUND); + } + + // for non-zoning non-movable brush entities in the sector + {FOREACHDSTOFSRC(itbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) + if (pen->en_RenderType==CEntity::RT_TERRAIN) { + continue; + } + if (pen->en_RenderType!=CEntity::RT_BRUSH&& + pen->en_RenderType!=CEntity::RT_FIELDBRUSH) { + break; // brushes are sorted first in list + } + if(pen->en_ulPhysicsFlags&EPF_MOVABLE) { + continue; + } + if(!MustTest(pen)) { + continue; + } + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_ADDNONZONING); + // get first mip + CBrushMip *pbm = pen->en_pbrBrush->GetFirstMip(); + // if brush mip exists for that mip factor + if (pbm!=NULL) { + // for each sector in the mip + {FOREACHINDYNAMICARRAY(pbm->bm_abscSectors, CBrushSector, itbscNonZoning) { + CBrushSector &bscNonZoning = *itbscNonZoning; + // add it to list of active sectors + if(!bscNonZoning.bsc_lnInActiveSectors.IsLinked()) { + cm_lhActiveSectors.AddTail(bscNonZoning.bsc_lnInActiveSectors); + } + }} + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_ADDNONZONING); + ENDFOR} + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_FINDNONZONING); + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CACHENEARPOLYGONS_MAINLOOP); + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CACHENEARPOLYGONS_CLEANUP); + // clear list of active sectors + {FORDELETELIST(CBrushSector, bsc_lnInActiveSectors, cm_lhActiveSectors, itbsc) { + itbsc->bsc_lnInActiveSectors.Remove(); + }} + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CACHENEARPOLYGONS_CLEANUP); + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CACHENEARPOLYGONS); +} + +void CClipMove::ClipToNonZoningSector(CBrushSector *pbsc) +{ + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPTONONZONINGSECTOR); + _pfPhysicsProfile.IncrementTimerAveragingCounter( + CPhysicsProfile::PTI_CLIPTONONZONINGSECTOR, pbsc->bsc_abpoPolygons.Count()); + + // for each polygon in the sector + FOREACHINSTATICARRAY(pbsc->bsc_abpoPolygons, CBrushPolygon, itbpo) { + // if its bbox has no contact with bbox of movement path, or it is passable + if (!itbpo->bpo_boxBoundingBox.HasContactWith(cm_boxMovementPath) + ||(itbpo->bpo_ulFlags&BPOF_PASSABLE)) { + // skip it + continue; + } + // clip movement to the polygon + ClipMoveToBrushPolygon(itbpo); + } + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPTONONZONINGSECTOR); +} + + +void CClipMove::ClipToTerrain(CEntity *pen) +{ + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPTONONZONINGSECTOR); +// _pfPhysicsProfile.IncrementTimerAveragingCounter( +// CPhysicsProfile::PTI_CLIPTONONZONINGSECTOR, pbsc->bsc_abpoPolygons.Count()); + + + CTerrain &tr = *pen->en_ptrTerrain; + GFXVertex4 *pavVertices; + INDEX *paiIndices; + INDEX ctVertices,ctIndices; + + FLOAT3D vMin = cm_boxMovementPath.Min(); + FLOAT3D vMax = cm_boxMovementPath.Max(); + + FLOATaabbox3D boxMovementPath; + #define TRANSPT(x) (x-pen->en_plPlacement.pl_PositionVector) * !pen->en_mRotation + boxMovementPath = TRANSPT(FLOAT3D(vMin(1),vMin(2),vMin(3))); + boxMovementPath |= TRANSPT(FLOAT3D(vMin(1),vMin(2),vMax(3))); + boxMovementPath |= TRANSPT(FLOAT3D(vMax(1),vMin(2),vMin(3))); + boxMovementPath |= TRANSPT(FLOAT3D(vMax(1),vMin(2),vMax(3))); + boxMovementPath |= TRANSPT(FLOAT3D(vMin(1),vMax(2),vMin(3))); + boxMovementPath |= TRANSPT(FLOAT3D(vMin(1),vMax(2),vMax(3))); + boxMovementPath |= TRANSPT(FLOAT3D(vMax(1),vMax(2),vMin(3))); + boxMovementPath |= TRANSPT(FLOAT3D(vMax(1),vMax(2),vMax(3))); + +/* + boxMovementPath.minvect(1) /= tr.tr_vStretch(1); + boxMovementPath.minvect(3) /= tr.tr_vStretch(3); + boxMovementPath.maxvect(1) /= tr.tr_vStretch(1); + boxMovementPath.maxvect(3) /= tr.tr_vStretch(3); +*/ + ExtractPolygonsInBox(&tr,boxMovementPath,&pavVertices,&paiIndices,ctVertices,ctIndices); + + // for each triangle + for(INDEX iTri=0;iTri &apbpo = cm_penMoving->en_apbpoNearPolygons; + + _pfPhysicsProfile.IncrementTimerAveragingCounter( + CPhysicsProfile::PTI_CLIPTOZONINGSECTOR, apbpo.Count()); + + // for each cached polygon + for(INDEX iPolygon=0; iPolygonbpo_pbscSector != pbsc || + !pbpo->bpo_boxBoundingBox.HasContactWith(cm_boxMovementPath)) { + // skip it + continue; + } + // if it is not passable + if (!(pbpo->bpo_ulFlags&BPOF_PASSABLE)) { + // clip movement to the polygon + ClipMoveToBrushPolygon(pbpo); + // if it is passable + } else { + // for each sector related to the portal + {FOREACHDSTOFSRC(pbpo->bpo_rsOtherSideSectors, CBrushSector, bsc_rdOtherSidePortals, pbscRelated) + // if the sector is not active + if (pbscRelated->bsc_pbmBrushMip->IsFirstMip() && + !pbscRelated->bsc_lnInActiveSectors.IsLinked()) { + // add it to active list + cm_lhActiveSectors.AddTail(pbscRelated->bsc_lnInActiveSectors); + } + ENDFOR} + } + } + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPTOZONINGSECTOR); +} + +/* Clip movement to brush sectors near the entity. */ +void CClipMove::ClipMoveToBrushes(void) +{ + // we never clip moving brush to a brush + if (cm_bMovingBrush) { + return; + } + if (cm_penMoving->en_ulCollisionFlags&ECF_IGNOREBRUSHES) { + return; + } + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES); + _pfPhysicsProfile.IncrementTimerAveragingCounter(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES, 1); + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_ADDINITIAL); + // for each zoning sector that this entity is in + {FOREACHSRCOFDST(cm_penMoving->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + _pfPhysicsProfile.IncrementTimerAveragingCounter( + CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_ADDINITIAL, 1); + // if it collides with this one + if (pbsc->bsc_pbmBrushMip->IsFirstMip() && + pbsc->bsc_pbmBrushMip->bm_pbrBrush->br_pfsFieldSettings==NULL && + MustTest(pbsc->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity)) { + // add it to list of active sectors + cm_lhActiveSectors.AddTail(pbsc->bsc_lnInActiveSectors); + } + ENDFOR} + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_ADDINITIAL); + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_MAINLOOP); + // for each active sector + FOREACHINLIST(CBrushSector, bsc_lnInActiveSectors, cm_lhActiveSectors, itbsc) { + _pfPhysicsProfile.IncrementTimerAveragingCounter( + CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_MAINLOOP, 1); + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_FINDNONZONING); + // for non-zoning brush entities in the sector + {FOREACHDSTOFSRC(itbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) + if (pen->en_RenderType!=CEntity::RT_BRUSH&& + pen->en_RenderType!=CEntity::RT_FIELDBRUSH&& + pen->en_RenderType!=CEntity::RT_TERRAIN) { + break; // brushes are sorted first in list + } + if(!MustTest(pen)) { + continue; + } + + if (pen->en_RenderType==CEntity::RT_TERRAIN) { + // remember currently tested entity + cm_penTested = pen; + // moving model is A and still terrain is B + cm_penB = pen; + GetPositionsOfEntity(cm_penB, cm_vB0, cm_mB0, cm_vB1, cm_mB1); + + // prepare new projections and spheres + PrepareProjectionsAndSpheres(); + + // clip movement to the terrain + ClipToTerrain(pen); + + // don't process as brush + continue; + } + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_ADDNONZONING); + // get first mip + CBrushMip *pbm = pen->en_pbrBrush->GetFirstMip(); + // if brush mip exists for that mip factor + if (pbm!=NULL) { + // for each sector in the mip + {FOREACHINDYNAMICARRAY(pbm->bm_abscSectors, CBrushSector, itbscNonZoning) { + CBrushSector &bscNonZoning = *itbscNonZoning; + // add it to list of active sectors + if(!bscNonZoning.bsc_lnInActiveSectors.IsLinked()) { + cm_lhActiveSectors.AddTail(bscNonZoning.bsc_lnInActiveSectors); + } + }} + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_ADDNONZONING); + ENDFOR} + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_FINDNONZONING); + + // get the sector's brush mip, brush and entity + CBrushMip *pbmBrushMip = itbsc->bsc_pbmBrushMip; + CBrush3D *pbrBrush = pbmBrushMip->bm_pbrBrush; + ASSERT(pbrBrush!=NULL); + CEntity *penBrush = pbrBrush->br_penEntity; + ASSERT(penBrush!=NULL); + + // remember currently tested entity + cm_penTested = penBrush; + // moving model is A and still brush is B + cm_penB = penBrush; + GetPositionsOfEntity(cm_penB, cm_vB0, cm_mB0, cm_vB1, cm_mB1); + + // prepare new projections and spheres + PrepareProjectionsAndSpheres(); + + // clip movement to the sector + if (penBrush->en_ulFlags&ENF_ZONING) { + ClipToZoningSector(itbsc); + } else { + ClipToNonZoningSector(itbsc); + } + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_MAINLOOP); + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_CLEANUP); + // clear list of active sectors + {FORDELETELIST(CBrushSector, bsc_lnInActiveSectors, cm_lhActiveSectors, itbsc) { + itbsc->bsc_lnInActiveSectors.Remove(); + }} + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES_CLEANUP); + + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPMOVETOBRUSHES); +} + +/* Clip movement to models near the entity. */ +void CClipMove::ClipMoveToModels(void) +{ + if (cm_penMoving->en_ulCollisionFlags&ECF_IGNOREMODELS) { + return; + } + + // create mask for skipping deleted entities + ULONG ulSkipMask = ENF_DELETED; + // if the moving entity is predictor + if (cm_penMoving->IsPredictor()) { + // add predicted entities to the mask + ulSkipMask |= ENF_PREDICTED; + } + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_CLIPMOVETOMODELS); + + // find colliding entities near the box of movement path + static CStaticStackArray apenNearEntities; + cm_pwoWorld->FindEntitiesNearBox(cm_boxMovementPath, apenNearEntities); + + // for each of the found entities + {for(INDEX ienFound=0; ienFounden_ulFlags&ENF_DELETED) + ||!(cm_penMoving->en_ulCollisionFlags&ECF_TESTMASK)) { + // skip clipping + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_CLIPMOVETOWORLD); + return; + } + + cm_pwoWorld = pwoWorld; + + // prepare flags masks for testing which entities collide with this + cm_ulTestMask1 = ((cm_penMoving->en_ulCollisionFlags&ECF_TESTMASK)>>ECB_TEST)<en_ulCollisionFlags&ECF_ISMASK )>>ECB_IS )<en_ulCollisionFlags&ECF_PASSMASK)>>ECB_PASS)<en_ulCollisionFlags&ECF_ISMASK )>>ECB_IS )< +#include +#include +#include +#include +#include + +/* + * A class used for clipping a movement. + */ +class CClipMove { +public: + BOOL cm_bMovingBrush; // set if moving a brush (some things are reversed then) + CMovableEntity *cm_penMoving; // entity that is moving + CEntity *cm_penA; // entity A - can be only model + CEntity *cm_penB; // entity B - can be either model or brush + + // masks for collision flags of other entities + ULONG cm_ulTestMask1; + ULONG cm_ulTestMask2; + ULONG cm_ulPassMaskA; // pass - send event to A + ULONG cm_ulPassMaskB; // pass - send event to B + + // test if should test with some entity + inline BOOL MustTest(CEntity *pen) { + return + (pen->en_ulCollisionFlags&cm_ulTestMask1)&& + (pen->en_ulCollisionFlags&cm_ulTestMask2); + }; + // send pass if needed + inline BOOL SendPassEvent(CEntity *pen); + + CListHead cm_lhActiveSectors; // brush sectors that are queued for testing + + // placement of entity A + FLOAT3D cm_vA0; FLOATmatrix3D cm_mA0; // at the start of movement + FLOAT3D cm_vA1; FLOATmatrix3D cm_mA1; // at the end of movement + // placement of entity B + FLOAT3D cm_vB0; FLOATmatrix3D cm_mB0; // at the start of movement + FLOAT3D cm_vB1; FLOATmatrix3D cm_mB1; // at the end of movement + + CStaticArray *cm_pamsA; // bounding spheres used by entity A + CStaticArray *cm_pamsB; // bounding spheres used by entity B (if not brush) + +// helper variables + FLOATaabbox3D cm_boxMovementPath; // aabbox around entire movement path + CEntity *cm_penTested; // entity to be remembered if hit (A or B) + CBrushPolygon *cm_pbpoTested; // brush polygon to be remembered if hit + class CWorld *cm_pwoWorld; // world that movement is taking place in + + // projections for converting from space of entity A to space of entity B + FLOAT3D cm_vAToB0; FLOATmatrix3D cm_mAToB0; // at the start of movement + FLOAT3D cm_vAToB1; FLOATmatrix3D cm_mAToB1; // at the end of movement + // for converting from space of entity B to absolute space + FLOAT3D cm_vBToAbsolute; FLOATmatrix3D cm_mBToAbsolute; + + FLOATaabbox3D cm_boxMovementPathAbsoluteA; // movement box in absolute space for A entity + + // get start and end positions of an entity in this tick + inline void GetPositionsOfEntity( + CEntity *pen, FLOAT3D &v0, FLOATmatrix3D &m0, FLOAT3D &v1, FLOATmatrix3D &m1); + + /* Project spheres of entity A to space of entity B. */ + void ProjectASpheresToB(void); + /* Find movement box in absolute space for A entity. */ + void FindAbsoluteMovementBoxForA(void); + + /* Clip a moving point to a sphere, update collision data. */ + inline void ClipMovingPointToSphere(const FLOAT3D &vStart, const FLOAT3D &vEnd, + const FLOAT3D &vSphereCenter, const FLOAT fSphereRadius); + /* Clip a moving point to a cylinder, update collision data. */ + inline void ClipMovingPointToCylinder(const FLOAT3D &vStart, const FLOAT3D &vEnd, + const FLOAT3D &vCylinderBottomCenter, const FLOAT3D &vCylinderTopCenter, + const FLOAT fCylinderRadius); + + /* Clip a moving sphere to a standing sphere, update collision data. */ + void ClipMovingSphereToSphere(const CMovingSphere &msMoving, + const CMovingSphere &msStanding); + /* Clip a moving sphere to a brush polygon, update collision data. */ + void ClipMovingSphereToBrushPolygon( + const CMovingSphere &msMoving, CBrushPolygon *pbpoPolygon); + /* Clip a moving sphere to a terrain polygon, update collision data. */ + void ClipMovingSphereToTerrainPolygon( + const CMovingSphere &msMoving, const FLOAT3D &v0, const FLOAT3D &v1, const FLOAT3D &v2); + /* Clip movement to a brush polygon. */ + void ClipMoveToBrushPolygon(CBrushPolygon *pbpoPolygon); + /* Clip movement to a terrain polygon. */ + void ClipMoveToTerrainPolygon(const FLOAT3D &v0, const FLOAT3D &v1, const FLOAT3D &v2); + + /* Prepare projections and spheres for movement clipping. */ + void PrepareProjectionsAndSpheres(void); + /* Clip movement if B is a model. */ + void ClipModelMoveToModel(void); + /* Clip movement if B is a brush. */ + void ClipBrushMoveToModel(void); + + /* Clip movement to a model entity. */ + void ClipMoveToModel(CEntity *penModel); + + void ClipToNonZoningSector(CBrushSector *pbsc); + void ClipToZoningSector(CBrushSector *pbsc); + void ClipToTerrain(CEntity *pen); + + /* Cache near polygons of movable entity. */ + void CacheNearPolygons(void); + /* Clip movement to brush sectors near the entity. */ + void ClipMoveToBrushes(void); + /* Clip movement to models near the entity. */ + void ClipMoveToModels(void); + + /* Clip movement to the world. */ + void ClipMoveToWorld(class CWorld *pwoWorld); +public: + +// these are filled by clipping algorithm: + CEntity *cm_penHit; // entity hit when moving. NULL if nothing was hit + CBrushPolygon *cm_pbpoHit; // brush polygon that was hit (NULL if did not hit a brush) + FLOAT cm_fMovementFraction; // fraction of movement done before hitting + FLOATplane3D cm_plClippedPlane; // the plane that was hit (in absolute space) + FLOAT3D cm_vClippedLine; // vector describing part of test line that was clipped + + /* Constructor. */ + CClipMove(CMovableEntity *penEntity); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/World/WorldCollisionGrid.cpp b/Sources/Engine/World/WorldCollisionGrid.cpp new file mode 100644 index 0000000..d12fd8f --- /dev/null +++ b/Sources/Engine/World/WorldCollisionGrid.cpp @@ -0,0 +1,445 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.H" + +#include +#include +#include +#include +#include + +#define DEBUG_COLLIDEWITHALL 0 + +#if DEBUG_COLLIDEWITHALL + #include + #include +#endif + +// allowed grid dimensions (meters) +#define GRID_MIN (-32000) +#define GRID_MAX (+32000) + +#define GRID_CELLSIZE 2.0 // size of one grid cell (meters) +// number of hash table entries for grid cells +#define GRID_HASHTABLESIZE_LOG2 12 // must be even for bit-shuffling +#define GRID_HASHTABLESIZE (1<>(GRID_HASHTABLESIZE_LOG2/2)) | ( + (iZ2&(GRID_HASHTABLESIZE/2-1))<<(GRID_HASHTABLESIZE_LOG2/2)); + iKey = iKey^abs(iX); + iKey = iKey&(GRID_HASHTABLESIZE-1); + return iKey; +} + +static inline INDEX MakeKeyFromCode(ULONG ulCode) +{ + INDEX iX = SLONG(ulCode)>>16; + INDEX iZ = SLONG(SWORD(ulCode&0xffff)); + return MakeKey(iX, iZ); +} + +// collision grid classes +class CGridCell { +public: + ULONG gc_ulCode; // 32 bit uid of the cell (from its coordinates in grid) + INDEX gc_iNextCell; // next cell with this hash code + INDEX gc_iFirstEntry; // first entry in this cell +}; +class CGridEntry { +public: + CEntity *ge_penEntity; // entity pointed to + INDEX ge_iNextEntry; // next entry in same cell +}; + +class CCollisionGrid { +public: + CStaticArray cg_aiFirstCells; // first cell for each hash entry + CAllocationArray cg_agcCells; // all cells + CAllocationArray cg_ageEntries; // all entries + + CCollisionGrid(void); + ~CCollisionGrid(void); + void Clear(void); + // create a new grid cell in given hash table entry + INDEX CreateCell(INDEX iKey, ULONG ulCode); + // remove a cell + void RemoveCell(INDEX igc); + // get grid cell for its coordinates + INDEX FindCell(INDEX iX, INDEX iZ, BOOL bCreate); + // add entry to a given cell + void AddEntry(INDEX igc, CEntity *pen); + // remove entry from a given cell + void RemoveEntry(INDEX igc, CEntity *pen); +}; + + +// collision grid class implementation + +CCollisionGrid::CCollisionGrid(void) +{ + Clear(); +} + +CCollisionGrid::~CCollisionGrid(void) +{ + Clear(); +} + +void CCollisionGrid::Clear(void) +{ + cg_aiFirstCells.Clear(); + cg_agcCells.Clear(); + cg_ageEntries.Clear(); + + cg_aiFirstCells.New(GRID_HASHTABLESIZE); + cg_agcCells.SetAllocationStep(1024); + cg_ageEntries.SetAllocationStep(1024); + + // mark all cells as unused + for(INDEX iKey=0; iKey=0); + while(*pigc>=0) { + CGridCell &gc = cg_agcCells[*pigc]; + if (*pigc==igc) { + *pigc = gc.gc_iNextCell; + gc.gc_iNextCell = -2; + gc.gc_iFirstEntry = -1; + gc.gc_ulCode = 0x12345678; + cg_agcCells.Free(igc); + return; + } + pigc = &gc.gc_iNextCell; + } + ASSERT(FALSE); +} + +// get grid cell for its coordinates +INDEX CCollisionGrid::FindCell(INDEX iX, INDEX iZ, BOOL bCreate) +{ + // make uid of the cell + ASSERT(iX>=GRID_MIN && iX<=GRID_MAX); + ASSERT(iZ>=GRID_MIN && iZ<=GRID_MAX); + ULONG ulCode = MakeCode(iX, iZ); + // get the hash key for the cell + INDEX iKey = MakeKey(iX, iZ); // x+z, use lower bits + ASSERT(iKey==MakeKeyFromCode(ulCode)); + // find the cell in list of cells with that key + INDEX igcFound = -1; + for (INDEX igc=cg_aiFirstCells[iKey]; igc>=0; igc = cg_agcCells[igc].gc_iNextCell) { + if (cg_agcCells[igc].gc_ulCode==ulCode) { + igcFound = igc; + break; + } + } + + // if the cell is found + if (igcFound>=0) { + // use existing one + return igcFound; + // if the cell is not found + } else { + // if new one may be created + if (bCreate) { + // create a new one + return CreateCell(iKey, ulCode); + // if new one may not be created + } else { + // return nothing + return -1; + } + } +} + +// add entry to a given cell +void CCollisionGrid::AddEntry(INDEX igc, CEntity *pen) +{ + // find an empty entry + INDEX ige = cg_ageEntries.Allocate(); + CGridEntry &ge = cg_ageEntries[ige]; + + // init the entry and link it in its cell + ge.ge_penEntity = pen; + CGridCell &gc = cg_agcCells[igc]; + ge.ge_iNextEntry = gc.gc_iFirstEntry; + gc.gc_iFirstEntry = ige; +} + +// remove entry from a given cell +void CCollisionGrid::RemoveEntry(INDEX igc, CEntity *pen) +{ + CGridCell &gc = cg_agcCells[igc]; + + // find the entry's index pointer + INDEX *pige = &gc.gc_iFirstEntry; + ASSERT(*pige>=0); + while(*pige>=0) { + CGridEntry &ge = cg_ageEntries[*pige]; + if (ge.ge_penEntity==pen) { + // remove the entry from the list + cg_ageEntries.Free(*pige); + *pige = ge.ge_iNextEntry; + ge.ge_iNextEntry = -2; + ge.ge_penEntity = NULL; + // if the cell becomes empty + if (gc.gc_iFirstEntry<0) { + // remove the cell + RemoveCell(igc); + } + return; + } + pige = &ge.ge_iNextEntry; + } + ASSERT(FALSE); +} + + + +/* Initialize collision grid. */ +void CWorld::InitCollisionGrid(void) +{ + wo_pcgCollisionGrid = new CCollisionGrid; +} +/* Destroy collision grid. */ +void CWorld::DestroyCollisionGrid(void) +{ + delete wo_pcgCollisionGrid; + wo_pcgCollisionGrid = NULL; +} +// clear collision grid +void CWorld::ClearCollisionGrid(void) +{ + wo_pcgCollisionGrid->Clear(); +} + + +/* Add an entity to cell(s) in collision grid. */ +void CWorld::AddEntityToCollisionGrid(CEntity *pen, const FLOATaabbox3D &boxEntity) +{ + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_ADDENTITYTOGRID); + // find grid coordinates + INDEX iMinX, iMaxX, iMinZ, iMaxZ; + BoxToGrid(boxEntity, iMinX, iMaxX, iMinZ, iMaxZ); + // for each cell spanned by the entity + for(INDEX iX=iMinX; iX<=iMaxX; iX++) { + for(INDEX iZ=iMinZ; iZ<=iMaxZ; iZ++) { + // find that cell + INDEX igc = wo_pcgCollisionGrid->FindCell(iX, iZ, TRUE); + // add the entity to the cell + wo_pcgCollisionGrid->AddEntry(igc, pen); + } + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_ADDENTITYTOGRID); +} + + +/* Remove an entity from cell(s) in collision grid. */ +void CWorld::RemoveEntityFromCollisionGrid(CEntity *pen, const FLOATaabbox3D &boxEntity) +{ + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_REMENTITYFROMGRID); + // find grid coordinates + INDEX iMinX, iMaxX, iMinZ, iMaxZ; + BoxToGrid(boxEntity, iMinX, iMaxX, iMinZ, iMaxZ); + // for each cell spanned by the entity + for(INDEX iX=iMinX; iX<=iMaxX; iX++) { + for(INDEX iZ=iMinZ; iZ<=iMaxZ; iZ++) { + // find that cell + INDEX igc = wo_pcgCollisionGrid->FindCell(iX, iZ, FALSE); + ASSERT(igc>=0); + // remove the entity from the cell + if (igc>=0) { + wo_pcgCollisionGrid->RemoveEntry(igc, pen); + } + } + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_REMENTITYFROMGRID); +} + +/* Move an entity inside cell(s) in collision grid. */ +void CWorld::MoveEntityInCollisionGrid(CEntity *pen, + const FLOATaabbox3D &boxOld, const FLOATaabbox3D &boxNew) +{ + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_MOVEENTITYINGRID); + + // find grid coordinates + INDEX iOldMinX, iOldMaxX, iOldMinZ, iOldMaxZ; + BoxToGrid(boxOld, iOldMinX, iOldMaxX, iOldMinZ, iOldMaxZ); + INDEX iNewMinX, iNewMaxX, iNewMinZ, iNewMaxZ; + BoxToGrid(boxNew, iNewMinX, iNewMaxX, iNewMinZ, iNewMaxZ); + + // for each cell spanned by the entity before moving but not after moving + {for(INDEX iX=iOldMinX; iX<=iOldMaxX; iX++) { + for(INDEX iZ=iOldMinZ; iZ<=iOldMaxZ; iZ++) { + if (iX>=iNewMinX && iX<=iNewMaxX + &&iZ>=iNewMinZ && iZ<=iNewMaxZ) { + continue; + } + // find that cell + INDEX igc = wo_pcgCollisionGrid->FindCell(iX, iZ, FALSE); + ASSERT(igc>=0); + // remove the entity from the cell + if (igc>=0) { + wo_pcgCollisionGrid->RemoveEntry(igc, pen); + } + } + }} + + // for each cell spanned by the entity after moving but not before moving + {for(INDEX iX=iNewMinX; iX<=iNewMaxX; iX++) { + for(INDEX iZ=iNewMinZ; iZ<=iNewMaxZ; iZ++) { + if (iX>=iOldMinX && iX<=iOldMaxX + &&iZ>=iOldMinZ && iZ<=iOldMaxZ) { + continue; + } + // find that cell + INDEX igc = wo_pcgCollisionGrid->FindCell(iX, iZ, TRUE); + wo_pcgCollisionGrid->AddEntry(igc, pen); + } + }} + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_MOVEENTITYINGRID); +} + + +/* Find all entities in collision grid near given box. */ +void CWorld::FindEntitiesNearBox(const FLOATaabbox3D &boxNear, + CStaticStackArray &apenNearEntities) +{ + +#if DEBUG_COLLIDEWITHALL + apenNearEntities.PopAll(); + // for each entity + {FOREACHINDYNAMICCONTAINER(wo_cenEntities, CEntity, iten) { + CEntity &en = *iten; + if (en.GetRenderType()==CEntity::RT_MODEL && en.en_pciCollisionInfo!=NULL) { + apenNearEntities.Push() = &en; + } + }} + + return; +#endif + + _pfPhysicsProfile.StartTimer(CPhysicsProfile::PTI_FINDENTITIESNEARBOX); + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_FINDINGNEARENTITIES); + + // find grid coordinates + INDEX iMinX, iMaxX, iMinZ, iMaxZ; + BoxToGrid(boxNear, iMinX, iMaxX, iMinZ, iMaxZ); + apenNearEntities.PopAll(); + + // for each cell spanned by the box + {for(INDEX iX=iMinX; iX<=iMaxX; iX++) { + for(INDEX iZ=iMinZ; iZ<=iMaxZ; iZ++) { + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_NEARCELLSFOUND); + // find that cell + INDEX igc = wo_pcgCollisionGrid->FindCell(iX, iZ, FALSE); + // if the cell is empty + if (igc<0) { + // skip it + continue; + } + _pfPhysicsProfile.IncrementCounter(CPhysicsProfile::PCI_NEAROCCUPIEDCELLSFOUND); + // for each entity in the cell + for(INDEX iEntry = wo_pcgCollisionGrid->cg_agcCells[igc].gc_iFirstEntry; + iEntry>=0; + iEntry = wo_pcgCollisionGrid->cg_ageEntries[iEntry].ge_iNextEntry) { + CEntity *penEntity = wo_pcgCollisionGrid->cg_ageEntries[iEntry].ge_penEntity; + // if it is not already found + if (!(penEntity->en_ulFlags&ENF_FOUNDINGRIDSEARCH)) { + // add it + apenNearEntities.Push() = penEntity; + // mark it as found + penEntity->en_ulFlags|=ENF_FOUNDINGRIDSEARCH; + } + } + } + }} + + + _pfPhysicsProfile.IncrementCounter( + CPhysicsProfile::PCI_NEARENTITIESFOUND, apenNearEntities.Count()); + // for each of the found entities + for(INDEX ienFound=0; ienFounden_ulFlags&=~ENF_FOUNDINGRIDSEARCH; + } + _pfPhysicsProfile.StopTimer(CPhysicsProfile::PTI_FINDENTITIESNEARBOX); +} + + + +// get amount of memory used by this object +extern SLONG GetCollisionGridMemory( CCollisionGrid *pcg) +{ + // no collision grid? + if( pcg==NULL) return 0; + + // phew, it's here! + SLONG slUsedMemory = pcg->cg_aiFirstCells.Count() * sizeof(INDEX); + slUsedMemory += pcg->cg_agcCells.Count() * sizeof(CGridCell); + slUsedMemory += pcg->cg_ageEntries.Count() * sizeof(CGridEntry); + slUsedMemory += pcg->cg_agcCells.aa_aiFreeElements.sa_Count * sizeof(INDEX); + slUsedMemory += pcg->cg_ageEntries.aa_aiFreeElements.sa_Count * sizeof(INDEX); + return slUsedMemory; +} \ No newline at end of file diff --git a/Sources/Engine/World/WorldEditingProfile.cpp b/Sources/Engine/World/WorldEditingProfile.cpp new file mode 100644 index 0000000..c31f2e3 --- /dev/null +++ b/Sources/Engine/World/WorldEditingProfile.cpp @@ -0,0 +1,51 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include + +// profile form for profiling world editing +CWorldEditingProfile wepWorldEditingProfile; +CProfileForm &_pfWorldEditingProfile = wepWorldEditingProfile; + +///////////////////////////////////////////////////////////////////// +// CWorldEditingProfile + +CWorldEditingProfile::CWorldEditingProfile(void) + : CProfileForm ("World editing", "operations", + CWorldEditingProfile::PCI_COUNT, CWorldEditingProfile::PTI_COUNT) +{ + SETTIMERNAME(PTI_CSGTOTAL, "CSG operations total", ""); + SETTIMERNAME(PTI_OBJECTOPTIMIZE, "CObject3D::Optimize()", ""); + SETTIMERNAME(PTI_OBJECTCSG, "CObject3D::CSGxxxx()", ""); + SETTIMERNAME(PTI_OBJECTCSG, "CObject3D::CSGxxxx()", ""); + + SETTIMERNAME(PTI_ADDOBJECTTOBRUSH, "AddObjectToBrush()", ""); + SETTIMERNAME(PTI_FINDSHADOWLAYERS, "FindShadowLayers()", ""); + SETTIMERNAME(PTI_CALCULATEBOUNDINGBOXES, "CalculateBoundingBoxes()", ""); + SETTIMERNAME(PTI_ADDFROMOBJECT3D, "AddFromObject3D()", ""); + SETTIMERNAME(PTI_TRIANGULATE, "Triangulate()", ""); + SETTIMERNAME(PTI_TRISTRIPMODELS, "tristrip models", ""); + + SETTIMERNAME(PTI_LINKENTITIESTOSECTORS, "LinkEntitiesToSectors()", ""); + SETTIMERNAME(PTI_LINKPORTALSANDSECTORS, "LinkPortalsAndSectors()", ""); + SETTIMERNAME(PTI_READBRUSHES, "ReadBrushes()", ""); + SETTIMERNAME(PTI_READBSP, "ReadBSP()", ""); + SETTIMERNAME(PTI_READPORTALSECTORLINKS, "ReadPortalSectorLinks()", ""); + SETTIMERNAME(PTI_READSTATE, "ReadState()", ""); + SETTIMERNAME(PTI_REINITIALIZEENTITIES, "ReinitializeEntities()", ""); + + SETTIMERNAME(PTI_MAKESHADOWMAP, "MakeShadowMap()", ""); + SETTIMERNAME(PTI_RENDERSHADOWS, "RenderShadows()", ""); + + SETTIMERNAME(PTI_MIXLAYERS, "CLayerMixer::MixLayers()", ""); + SETTIMERNAME(PTI_CALCULATEDATA, "CLayerMixer::CalculateData()", ""); + SETTIMERNAME(PTI_AMBIENTFILL, "CLayerMixer::FillWithAmbientLight()", ""); + SETTIMERNAME(PTI_ADDONELAYERPOINT, "CLayerMixer::AddOneLayerPoint()", ""); + SETTIMERNAME(PTI_ADDONELAYERDIRECTIONAL, "CLayerMixer::AddOneLayerDirectional()", ""); + + SETCOUNTERNAME(PCI_SECTORSOPTIMIZED, "sectors optimized"); + SETCOUNTERNAME(PCI_SHADOWIMAGES, "shadow images generated"); + SETCOUNTERNAME(PCI_SHADOWCLUSTERS, "total shadow clusters generated in all images"); + SETCOUNTERNAME(PCI_POLYGONSHADOWS, "total polygon shadows cast"); +} diff --git a/Sources/Engine/World/WorldEditingProfile.h b/Sources/Engine/World/WorldEditingProfile.h new file mode 100644 index 0000000..c4bca67 --- /dev/null +++ b/Sources/Engine/World/WorldEditingProfile.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_WORLDEDITINGPROFILE_H +#define SE_INCL_WORLDEDITINGPROFILE_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include + +/* Class for holding profiling information for world editing operations. */ +class CWorldEditingProfile : public CProfileForm { +public: + // indices for profiling counters and timers + enum ProfileTimerIndex { + PTI_CSGTOTAL, // total time spent for CSG operations + PTI_OBJECTOPTIMIZE, // time spent in CObject3D::Optimize() + PTI_OBJECTCSG, // time spent in CObject3D::CSGxxxx() + PTI_ADDOBJECTTOBRUSH, // AddObjectToBrush() + PTI_FINDSHADOWLAYERS, // FindShadowLayers() + PTI_CALCULATEBOUNDINGBOXES, // CalculateBoundingBoxes() + PTI_ADDFROMOBJECT3D, // AddFromObject3D() + PTI_TRIANGULATE, + PTI_TRISTRIPMODELS, + + PTI_DUMMY1, + + PTI_LINKENTITIESTOSECTORS, // LinkEntititesToSectors() + PTI_LINKPORTALSANDSECTORS, // LinkPortalsAndSectors() + PTI_READBRUSHES, // ReadBrushes() + PTI_READBSP, // ReadBSP() + PTI_READPORTALSECTORLINKS, // ReadPortalSectorLinks() + PTI_READSTATE, // ReadState() + PTI_REINITIALIZEENTITIES, + + PTI_DUMMY2, + + PTI_MAKESHADOWMAP, // MakeShadowMap() + PTI_RENDERSHADOWS, // RenderShadows() + + PTI_DUMMY3, + + PTI_MIXLAYERS, // CLayerMixer::MixLayers() + PTI_CALCULATEDATA, // CLayerMixer::CalculateData() + PTI_AMBIENTFILL, // CLayerMixer::FillWithAmbientLight() + PTI_ADDONELAYERPOINT, // CLayerMixer::AddOneLayerPoint() + PTI_ADDONELAYERDIRECTIONAL, // CLayerMixer::AddOneLayerDirectional() + + PTI_COUNT + }; + enum ProfileCounterIndex { + PCI_SECTORSOPTIMIZED, // total number of sectors optimized + PCI_SHADOWIMAGES, // number of shadow images generated + PCI_SHADOWCLUSTERS, // total number of shadow clusters generated in all images + PCI_POLYGONSHADOWS, // total number of polygon shadows cast + PCI_COUNT + }; + // constructor + CWorldEditingProfile(void); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/World/WorldIO.cpp b/Sources/Engine/World/WorldIO.cpp new file mode 100644 index 0000000..f97e53a --- /dev/null +++ b/Sources/Engine/World/WorldIO.cpp @@ -0,0 +1,825 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WORLDSTATEVERSION_NOCLASSCONTAINER 9 +#define WORLDSTATEVERSION_MULTITEXTURING 8 +#define WORLDSTATEVERSION_SHADOWSPERMIP 7 +#define WORLDSTATEVERSION_CURRENT WORLDSTATEVERSION_NOCLASSCONTAINER +extern CWorld *_pwoCurrentLoading = NULL; // world that is currently loading +extern BOOL _bPortalSectorLinksPreLoaded; +extern BOOL _bEntitySectorLinksPreLoaded; +extern BOOL _bFileReplacingApplied; +extern BOOL _bReadEntitiesByID = FALSE; + +/* + * Save entire world (both brushes current state). + */ +void CWorld::Save_t(const CTFileName &fnmWorld) // throw char * +{ + // create the file + CTFileStream strmFile; + strmFile.Create_t(fnmWorld); + + // save engine build + _pNetwork->WriteVersion_t(strmFile); + + // write the world to the file + Write_t(&strmFile); +} + +/* + * Load entire world (both brushes and current state). + */ +void CWorld::Load_t(const CTFileName &fnmWorld) // throw char * +{ + // remember the file + wo_fnmFileName = fnmWorld; + // open the file + CTFileStream strmFile; + strmFile.Open_t(fnmWorld); + + // check engine build allowing reinit + BOOL bNeedsReinit; + _pNetwork->CheckVersion_t(strmFile, TRUE, bNeedsReinit); + + // read the world from the file + Read_t(&strmFile); + + // close the file + strmFile.Close(); + + // if reinit is needed + if (bNeedsReinit) { + // reinitialize + SetProgressDescription(TRANS("converting from old version")); + CallProgressHook_t(0.0f); + ReinitializeEntities(); + CallProgressHook_t(1.0f); + // reinitialize + SetProgressDescription(TRANS("saving converted file")); + CallProgressHook_t(0.0f); + Save_t(fnmWorld); + CallProgressHook_t(1.0f); + } +} + +/* + * Write entire world (both brushes and current state). + */ +void CWorld::Write_t(CTStream *postrm) // throw char * +{ + // need high FPU precision + CSetFPUPrecision FPUPrecision(FPT_53BIT); + + // delete all predictor entities before saving + UnmarkForPrediction(); + DeletePredictors(); + + // lock all arrays and containers + LockAll(); + + postrm->WriteID_t("WRLD"); // 'world' + // write the world brushes to the file + WriteBrushes_t(postrm); + // write current world state to the file + WriteState_t(postrm); + postrm->WriteID_t("WEND"); // 'world end' + + // unlock all arrays and containers + UnlockAll(); +} + + +/* + * Read entire world (both brushes and current state). + */ +void CWorld::Read_t(CTStream *pistrm) // throw char * +{ + _pfWorldEditingProfile.IncrementAveragingCounter(); + _bFileReplacingApplied = FALSE; + + // need high FPU precision + CSetFPUPrecision FPUPrecision(FPT_53BIT); + + // clear eventual old data in the world + Clear(); + + // lock all arrays and containers + LockAll(); + + pistrm->ExpectID_t("WRLD"); // 'world' + // read the world brushes from the file + ReadBrushes_t(pistrm); + // read current world state from the file + ReadState_t(pistrm); + pistrm->ExpectID_t("WEND"); // 'world end' + + // unlock all arrays and containers + UnlockAll(); + + if( _bFileReplacingApplied) + WarningMessage("Some of files needed to load world have been replaced while loading"); +} + +/* + * Load just world brushes from a file with entire world information. + */ +void CWorld::LoadBrushes_t(const CTFileName &fnmWorld) // throw char * +{ + // remember the file + wo_fnmFileName = fnmWorld; + // open the file + CTFileStream strmFile; + strmFile.Open_t(fnmWorld); + + // check engine build disallowing reinit + BOOL bNeedsReinit; + _pNetwork->CheckVersion_t(strmFile, FALSE, bNeedsReinit); + ASSERT(!bNeedsReinit); + + strmFile.ExpectID_t("WRLD"); // 'world' + // read the world brushes from the file + ReadBrushes_t(&strmFile); +} + +/* + * Read world brushes from stream. + */ +void CWorld::ReadBrushes_t( CTStream *istrm)// throw char * +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_READBRUSHES); + + // must be in 53bit mode when managing brushes + CSetFPUPrecision FPUPrecision(FPT_53BIT); + + ReadInfo_t(istrm, FALSE); + + SetProgressDescription(TRANS("loading world textures")); + CallProgressHook_t(0.0f); + // read the brushes from the file + _pwoCurrentLoading = this; + istrm->DictionaryReadBegin_t(); + istrm->DictionaryPreload_t(); + CallProgressHook_t(1.0f); + SetProgressDescription(TRANS("loading brushes")); + CallProgressHook_t(0.0f); + wo_baBrushes.Read_t(istrm); + CallProgressHook_t(1.0f); + + // if there are some terrais in world + if(istrm->PeekID_t()==CChunkID("TRAR")) { // 'terrain archive' + SetProgressDescription(TRANS("loading terrains")); + CallProgressHook_t(0.0f); + wo_taTerrains.Read_t(istrm); + CallProgressHook_t(1.0f); + } + + istrm->DictionaryReadEnd_t(); + _pwoCurrentLoading = NULL; + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_READBRUSHES); +} + +/* + * Write world brushes to stream. + */ +void CWorld::WriteBrushes_t( CTStream *ostrm) // throw char * +{ + WriteInfo_t(ostrm); + + // write the brushes to the file + ostrm->DictionaryWriteBegin_t(CTString(""), 0); + wo_baBrushes.Write_t(ostrm); + wo_taTerrains.Write_t(ostrm); + ostrm->DictionaryWriteEnd_t(); +} + +/* + * Read current world state from stream. + */ +void CWorld::ReadState_t( CTStream *istr) // throw char * +{ + _pfWorldEditingProfile.StartTimer(CWorldEditingProfile::PTI_READSTATE); + // must be in 24bit mode when managing entities + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + CTmpPrecachingNow tpn; + _bReadEntitiesByID = FALSE; + + SetProgressDescription(TRANS("loading models")); + CallProgressHook_t(0.0f); + wo_slStateDictionaryOffset = istr->DictionaryReadBegin_t(); + istr->DictionaryPreload_t(); + CallProgressHook_t(1.0f); + istr->ExpectID_t("WSTA"); // world state + + // read the version number + INDEX iSavedVersion; + (*istr)>>iSavedVersion; + // if the version number is the newest + if(iSavedVersion==WORLDSTATEVERSION_CURRENT) { + // read current version + ReadState_new_t(istr); + + // if the version number is not the newest + } else { + + // if the version can be converted + if(iSavedVersion==WORLDSTATEVERSION_CURRENT-1) { + // show warning +// WarningMessage( +// "World state version was %d (old).\n" +// "Auto-converting to version %d.", +// iSavedVersion, WORLDSTATEVERSION_CURRENT); + // read previous version + ReadState_old_t(istr); + // if the version can be converted + } else if(iSavedVersion==WORLDSTATEVERSION_CURRENT-2) { + // show warning + WarningMessage( + TRANS("World state version was %d (very old).\n" + "Auto-converting to version %d."), + iSavedVersion, WORLDSTATEVERSION_CURRENT); + // read previous version + ReadState_veryold_t(istr); + } else { + // report error + ThrowF_t( + TRANS("World state version is %d (unsupported).\n" + "Current supported version is %d."), + iSavedVersion, WORLDSTATEVERSION_CURRENT); + } + } + istr->DictionaryReadEnd_t(); + + SetProgressDescription(TRANS("precaching")); + CallProgressHook_t(0.0f); + // precache data needed by entities + if( gam_iPrecachePolicy==PRECACHE_SMART) { + PrecacheEntities_t(); + } + CallProgressHook_t(1.0f); + + _pfWorldEditingProfile.StopTimer(CWorldEditingProfile::PTI_READSTATE); +} + +/* + * Read current world state from stream -- preprevious version. + */ +void CWorld::ReadState_veryold_t( CTStream *istr) // throw char * +{ + // read the world description + (*istr)>>wo_strDescription; + // read the world background color + (*istr)>>wo_colBackground; + + INDEX ienBackgroundViewer = -1; + // if background viewer entity is saved here + if (istr->PeekID_t() == CChunkID("BGVW")) { + // read background viewer entity index + istr->ExpectID_t("BGVW"); // background viewer + (*istr)>>ienBackgroundViewer; + } else { + BOOL bUseBackgroundTexture; + (*istr)>>(SLONG &)bUseBackgroundTexture; + + // read the world background texture name + CTString strBackgroundTexture; + (*istr)>>strBackgroundTexture; // saved as string to bypass dependency catcher + // skip the 6 dummy texture names used for dependencies + CTFileName fnmDummy; + (*istr)>>fnmDummy>>fnmDummy>>fnmDummy + >>fnmDummy>>fnmDummy>>fnmDummy; + } + + // if backdrop image data is saved here + if (istr->PeekID_t() == CChunkID("BRDP")) { + // read backdrop image data + istr->ExpectID_t("BRDP"); // backdrop + (*istr)>>wo_strBackdropUp; + (*istr)>>wo_strBackdropFt; + (*istr)>>wo_strBackdropRt; + (*istr)>>wo_fUpW>>wo_fUpL>>wo_fUpCX>>wo_fUpCZ; + (*istr)>>wo_fFtW>>wo_fFtH>>wo_fFtCX>>wo_fFtCY; + (*istr)>>wo_fRtL>>wo_fRtH>>wo_fRtCZ>>wo_fRtCY; + } + + // if backdrop object name is saved here + if (istr->PeekID_t() == CChunkID("BDRO")) { + // read backdrop object name + istr->ExpectID_t("BDRO"); // backdrop object + (*istr)>>wo_strBackdropObject; + } + + // if viewer position should be loaded + if (istr->PeekID_t() == CChunkID("VWPS")) { + istr->ExpectID_t("VWPS"); // viewer position + (*istr)>>wo_plFocus; + (*istr)>>wo_fTargetDistance; + } + + istr->ExpectID_t("SHAN"); // shadow animations + // for all anim objects + {for(INDEX iao=0; iao<256; iao++) { + // skip animation object + CAnimObject ao; + ao.Read_t(istr); + }} + + istr->ExpectID_t("ECLs"); // entity classes + // read number of entity classes + INDEX ctEntityClasses; + (*istr)>>ctEntityClasses; + + CStaticArray cecClasses; + cecClasses.New(ctEntityClasses); + // for each entity class + {for(INDEX iEntityClass=0; iEntityClass>cecClasses[iEntityClass]; + }} + + /* NOTE: Entities must be loaded in two passes, since all entities must be created + * before any entity pointer properties can be loaded. + */ + istr->ExpectID_t("ENTs"); // entities + // read number of entities + INDEX ctEntities; + (*istr)>>ctEntities; + + // for each entity + {for(INDEX iEntity=0; iEntity>iEntityClass>>plPlacement; + // create an entity of that class + CEntity *penNew = CreateEntity_t(plPlacement, cecClasses[iEntityClass]); + }} + + // for each entity + {for(INDEX iEntity=0; iEntity1); // must be referenced by someone else too + en.RemReference(); + wo_cenEntities.Remove(&en); + } + }} + + // after all entities have been read and brushes are connected to entities, + // calculate bounding boxes of all brushes + wo_baBrushes.CalculateBoundingBoxes(); + // after all bounding boxes and BSP trees are created, + // create links between portals and sectors on their other side + wo_baBrushes.LinkPortalsAndSectors(); + wo_bPortalLinksUpToDate = TRUE; + // create links between sectors and non-zoning entities in sectors + LinkEntitiesToSectors(); +} + +/* + * Read current world state from stream -- previous version. + */ +void CWorld::ReadState_old_t( CTStream *istr) // throw char * +{ + // read the world description + (*istr)>>wo_strDescription; + // read the world background color + (*istr)>>wo_colBackground; + + INDEX ienBackgroundViewer = -1; + // read background viewer entity index + istr->ExpectID_t("BGVW"); // background viewer + (*istr)>>ienBackgroundViewer; + + // read backdrop image data + istr->ExpectID_t("BRDP"); // backdrop + (*istr)>>wo_strBackdropUp; + (*istr)>>wo_strBackdropFt; + (*istr)>>wo_strBackdropRt; + (*istr)>>wo_fUpW>>wo_fUpL>>wo_fUpCX>>wo_fUpCZ; + (*istr)>>wo_fFtW>>wo_fFtH>>wo_fFtCX>>wo_fFtCY; + (*istr)>>wo_fRtL>>wo_fRtH>>wo_fRtCZ>>wo_fRtCY; + + // read backdrop object name + istr->ExpectID_t("BDRO"); // backdrop object + (*istr)>>wo_strBackdropObject; + + istr->ExpectID_t("VWPS"); // viewer position + (*istr)>>wo_plFocus; + (*istr)>>wo_fTargetDistance; + + // if thumbnail saving position should be loaded + if (istr->PeekID_t() == CChunkID("TBPS")) { + istr->ExpectID_t("TBPS"); // thumbnail position + (*istr)>>wo_plThumbnailFocus; + (*istr)>>wo_fThumbnailTargetDistance; + } + + istr->ExpectID_t("SHAN"); // shadow animations + // for all anim objects + {for(INDEX iao=0; iao<256; iao++) { + // skip animation object + CAnimObject ao; + ao.Read_t(istr); + }} + + istr->ExpectID_t("ECLs"); // entity classes + // read number of entity classes + INDEX ctEntityClasses; + (*istr)>>ctEntityClasses; + + CStaticArray cecClasses; + cecClasses.New(ctEntityClasses); + // for each entity class + {for(INDEX iEntityClass=0; iEntityClass>cecClasses[iEntityClass]; + }} + + /* NOTE: Entities must be loaded in two passes, since all entities must be created + * before any entity pointer properties can be loaded. + */ + istr->ExpectID_t("ENTs"); // entities + // read number of entities + INDEX ctEntities; + (*istr)>>ctEntities; + + // for each entity + {for(INDEX iEntity=0; iEntity>iEntityClass>>plPlacement; + // create an entity of that class + CEntity *penNew = CreateEntity_t(plPlacement, cecClasses[iEntityClass]); + }} + + // for each entity + {for(INDEX iEntity=0; iEntity1); // must be referenced by someone else too + en.RemReference(); + wo_cenEntities.Remove(&en); + } + }} + + // after all entities have been read and brushes are connected to entities, + // calculate bounding boxes of all brushes + wo_baBrushes.CalculateBoundingBoxes(); + // after all bounding boxes and BSP trees are created, + // create links between portals and sectors on their other side if needed + if (!_bPortalSectorLinksPreLoaded) { + wo_baBrushes.LinkPortalsAndSectors(); + } + wo_bPortalLinksUpToDate = TRUE; + _bPortalSectorLinksPreLoaded = FALSE; + // create links between sectors and non-zoning entities in sectors + LinkEntitiesToSectors(); +} + +/* + * Read current world state from stream -- current version. + */ +void CWorld::ReadState_new_t( CTStream *istr) // throw char * +{ + // read the world info + ReadInfo_t(istr, TRUE); + + // read the world background color + (*istr)>>wo_colBackground; + + // read entity ID counter + if (istr->PeekID_t()==CChunkID("NFID")) { + istr->ExpectID_t("NFID"); + (*istr)>>wo_ulNextEntityID; + } else { + wo_ulNextEntityID = 1; + } + + INDEX ienBackgroundViewer = -1; + // read background viewer entity index + istr->ExpectID_t("BGVW"); // background viewer + (*istr)>>ienBackgroundViewer; + + // read backdrop image data + istr->ExpectID_t("BRDP"); // backdrop + (*istr)>>wo_strBackdropUp; + (*istr)>>wo_strBackdropFt; + (*istr)>>wo_strBackdropRt; + (*istr)>>wo_fUpW>>wo_fUpL>>wo_fUpCX>>wo_fUpCZ; + (*istr)>>wo_fFtW>>wo_fFtH>>wo_fFtCX>>wo_fFtCY; + (*istr)>>wo_fRtL>>wo_fRtH>>wo_fRtCZ>>wo_fRtCY; + + // read backdrop object name + istr->ExpectID_t("BDRO"); // backdrop object + (*istr)>>wo_strBackdropObject; + + istr->ExpectID_t("VWPS"); // viewer position + (*istr)>>wo_plFocus; + (*istr)>>wo_fTargetDistance; + + // if thumbnail saving position should be loaded + if (istr->PeekID_t() == CChunkID("TBPS")) { + istr->ExpectID_t("TBPS"); // thumbnail position + (*istr)>>wo_plThumbnailFocus; + (*istr)>>wo_fThumbnailTargetDistance; + } + + /* NOTE: Entities must be loaded in two passes, since all entities must be created + * before any entity pointer properties can be loaded. + */ + if (istr->PeekID_t()== CChunkID("ENTs")) { + istr->ExpectID_t("ENTs"); // entities + } else { + istr->ExpectID_t("ENs2"); // entities v2 + _bReadEntitiesByID = TRUE; + } + // read number of entities + INDEX ctEntities; + (*istr)>>ctEntities; + + SetProgressDescription(TRANS("creating entities")); + CallProgressHook_t(0.0f); + // for each entity + {for(INDEX iEntity=0; iEntity>ulID; + } + // read entity class and entity placement + CTFileName fnmClass; + CPlacement3D plPlacement; + (*istr)>>fnmClass>>plPlacement; + // create an entity of that class + CEntity *penNew = CreateEntity_t(plPlacement, fnmClass); + // adjust id if needed + if (_bReadEntitiesByID) { + wo_ulNextEntityID--; + penNew->en_ulID = ulID; + } + CallProgressHook_t(FLOAT(iEntity)/ctEntities); + }} + CallProgressHook_t(1.0f); + + SetProgressDescription(TRANS("loading entities")); + CallProgressHook_t(0.0f); + // for each entity + {for(INDEX iEntity=0; iEntity1); // must be referenced by someone else too + en.RemReference(); + wo_cenEntities.Remove(&en); + } + }} + wo_cenEntities.Lock(); + + // if version with entity order + if (istr->PeekID_t()==CChunkID("ENOR")) { // entity order + istr->ExpectID_t(CChunkID("ENOR")); // entity order + INDEX ctEntities; + *istr>>ctEntities; + wo_cenEntities.Clear(); + // for each non-deleted entity + for(INDEX i=0; i>ulID; + wo_cenEntities.Add(EntityFromID(ulID)); + } + } + + // some shadow layers might not have light sources, remove such to prevent crashes + wo_baBrushes.RemoveDummyLayers(); + + SetProgressDescription(TRANS("preparing world")); + CallProgressHook_t(0.0f); + // after all entities have been read and brushes are connected to entities, + // calculate bounding boxes of all brushes + wo_baBrushes.CalculateBoundingBoxes(); + CallProgressHook_t(0.3f); + // after all bounding boxes and BSP trees are created, + // create links between portals and sectors on their other side if needed + if (!_bPortalSectorLinksPreLoaded) { + wo_baBrushes.LinkPortalsAndSectors(); + } + wo_bPortalLinksUpToDate = TRUE; + // create links between sectors and non-zoning entities in sectors + wo_baBrushes.ReadEntitySectorLinks_t(*istr); + CallProgressHook_t(0.6f); + LinkEntitiesToSectors(); + CallProgressHook_t(1.0f); + _bPortalSectorLinksPreLoaded = FALSE; + _bEntitySectorLinksPreLoaded = FALSE; +} + +/* + * Write current world state to stream. + */ +void CWorld::WriteState_t( CTStream *ostr, BOOL bImportDictionary /* = FALSE */) // throw char * +{ + // must be in 24bit mode when managing entities + CSetFPUPrecision FPUPrecision(FPT_24BIT); + + // all predictors must be deleted + ASSERT( + wo_cenPredicted.Count()==0 && + wo_cenPredictor.Count()==0 && + wo_cenWillBePredicted.Count()==0); + + if (bImportDictionary) { + ostr->DictionaryWriteBegin_t(wo_fnmFileName, wo_slStateDictionaryOffset); + } else { + ostr->DictionaryWriteBegin_t(CTString(""), 0); + } + (*ostr).WriteID_t("WSTA"); // world state + // write the world version + (*ostr)<WriteID_t("NFID"); + (*ostr)<WriteID_t("BGVW"); // background viewer + CEntity *penBackgroundViewer = GetBackgroundViewer(); + if (penBackgroundViewer==NULL) { + (*ostr)<en_ulID; + } + + // write backdrop image data + ostr->WriteID_t("BRDP"); // backdrop + (*ostr)<WriteID_t("BDRO"); // backdrop object + (*ostr)<WriteID_t("VWPS"); // viewer placement + (*ostr)<WriteID_t("TBPS"); // thumbnail placement + (*ostr)<WriteID_t("ENs2"); // entities + // write number of entities + (*ostr)<GetName()<GetPos_t(); + // serialize entity into stream + iten->Write_t(ostr); + // save the size of data in start chunk, after chunkid and entity id + SLONG slOffsetAfter = ostr->GetPos_t(); + ostr->SetPos_t(slOffset+2*sizeof(SLONG)); + *ostr<SetPos_t(slOffsetAfter); + }} + + ostr->WriteID_t(CChunkID("ENOR")); // entity order + *ostr<en_ulID; + }} + + wo_baBrushes.WriteEntitySectorLinks_t(*ostr); + + ostr->DictionaryWriteEnd_t(); +} + +// read/write world information (description, name, flags...) +void CWorld::ReadInfo_t(CTStream *strm, BOOL bMaybeDescription) // throw char * +{ + // if version with world info + if (strm->PeekID_t()==CChunkID("WLIF")) { // world info + strm->ExpectID_t(CChunkID("WLIF")); // world info + + // skip eventual translation chunk + if (strm->PeekID_t()==CChunkID("DTRS")) { + strm->ExpectID_t("DTRS"); + } + // read the name + (*strm)>>wo_strName; + // read the flags + (*strm)>>wo_ulSpawnFlags; + // read the world description + (*strm)>>wo_strDescription; + + // if version with description only + } else if (bMaybeDescription) { + // read the world description + (*strm)>>wo_strDescription; + } +} + +void CWorld::WriteInfo_t(CTStream *strm) // throw char * +{ + strm->WriteID_t(CChunkID("WLIF")); // world info + // write the name + strm->WriteID_t(CChunkID("DTRS")); + (*strm)< +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define EPSILON (0.1f) + +class CActiveSector { +public: + CBrushSector *as_pbsc; + void Clear(void) {}; +}; + +static CStaticStackArray _aas; +CListHead _lhTestedTerrains; // list of tested terrains + +// calculate origin position from ray placement +static inline FLOAT3D CalculateRayOrigin(const CPlacement3D &plRay) +{ + // origin is the position from the placement + return plRay.pl_PositionVector; +} +// calculate target position from ray placement +static inline FLOAT3D CalculateRayTarget(const CPlacement3D &plRay) +{ + // calculate direction of the ray + FLOAT3D vDirection; + AnglesToDirectionVector(plRay.pl_OrientationAngle, vDirection); + // make target be from the origin in that direction + return plRay.pl_PositionVector+vDirection; +} + +/* + * Internal construction helper. + */ +void CCastRay::Init(CEntity *penOrigin, const FLOAT3D &vOrigin, const FLOAT3D &vTarget) +{ + ClearSectorList(); + cr_penOrigin = penOrigin; + cr_vOrigin = vOrigin; + cr_vTarget = vTarget; + cr_bAllowOverHit = FALSE; + cr_pbpoIgnore = NULL; + cr_penIgnore = NULL; + + cr_bHitPortals = FALSE; + cr_bHitTranslucentPortals = TRUE; + cr_ttHitModels = TT_SIMPLE; + cr_bHitFields = FALSE; + cr_bPhysical = FALSE; + cr_bHitBrushes = TRUE; + cr_bHitTerrainInvisibleTris = FALSE; + cr_fTestR = 0; + + cr_bFindBone = TRUE; + cr_iBoneHit = -1; + + cl_plRay.pl_PositionVector = vOrigin; + DirectionVectorToAngles((vTarget-vOrigin).Normalize(), cl_plRay.pl_OrientationAngle); +} + +/* + * Constructor. + */ +CCastRay::CCastRay(CEntity *penOrigin, const CPlacement3D &plOrigin) +{ + Init(penOrigin, CalculateRayOrigin(plOrigin), CalculateRayTarget(plOrigin)); + // mark last found hit point in infinity + cr_fHitDistance = UpperLimit(0.0f); +} +CCastRay::CCastRay(CEntity *penOrigin, const CPlacement3D &plOrigin, FLOAT fMaxTestDistance) +{ + Init(penOrigin, CalculateRayOrigin(plOrigin), CalculateRayTarget(plOrigin)); + // mark last found hit point just as far away as we wan't to test + cr_fHitDistance = fMaxTestDistance; +} +CCastRay::CCastRay(CEntity *penOrigin, const FLOAT3D &vOrigin, const FLOAT3D &vTarget) +{ + Init(penOrigin, vOrigin, vTarget); + // mark last found hit point just a bit behind the target + cr_fHitDistance = (cr_vTarget-cr_vOrigin).Length() + EPSILON; +} + +CCastRay::~CCastRay(void) +{ + ClearSectorList(); +} + +void CCastRay::ClearSectorList(void) +{ + // for each active sector + for(INDEX ias=0; ias<_aas.Count(); ias++) { + // mark it as inactive + _aas[ias].as_pbsc->bsc_ulFlags&=~BSCF_RAYTESTED; + } + _aas.PopAll(); +} + +/* + * Test if a ray hits sphere. + */ +inline static BOOL RayHitsSphere( + const FLOAT3D &vStart, + const FLOAT3D &vEnd, + const FLOAT3D &vSphereCenter, + const FLOAT fSphereRadius, + FLOAT &fDistance) +{ + const FLOAT3D vSphereCenterToStart = vStart - vSphereCenter; + const FLOAT3D vStartToEnd = vEnd - vStart; + // calculate discriminant for intersection parameters + const FLOAT fP = ((vStartToEnd%vSphereCenterToStart)/(vStartToEnd%vStartToEnd)); + const FLOAT fQ = (((vSphereCenterToStart%vSphereCenterToStart) + - (fSphereRadius*fSphereRadius))/(vStartToEnd%vStartToEnd)); + const FLOAT fD = fP*fP-fQ; + // if it is less than zero + if (fD<0) { + // no collision will occur + return FALSE; + } + // calculate intersection parameters + const FLOAT fSqrtD = sqrt(fD); + const FLOAT fLambda1 = -fP+fSqrtD; + const FLOAT fLambda2 = -fP-fSqrtD; + // use lower one + const FLOAT fMinLambda = Min(fLambda1, fLambda2); + // calculate distance from parameter + fDistance = fMinLambda*vStartToEnd.Length(); + return TRUE; +} + +void CCastRay::TestModelSimple(CEntity *penModel, CModelObject &mo) +{ + // get model's bounding box for current frame + FLOATaabbox3D boxModel; + mo.GetCurrentFrameBBox(boxModel); + boxModel.StretchByVector(mo.mo_Stretch); + // get center and radius of the bounding sphere in absolute space + FLOAT fSphereRadius = boxModel.Size().Length()/2.0f; + FLOAT3D vSphereCenter = boxModel.Center(); + vSphereCenter*=penModel->en_mRotation; + vSphereCenter+=penModel->en_plPlacement.pl_PositionVector; + + // if the ray doesn't hit the sphere + FLOAT fSphereHitDistance; + if (!RayHitsSphere(cr_vOrigin, cr_vTarget, + vSphereCenter, fSphereRadius+cr_fTestR, fSphereHitDistance) ) { + // ignore + return; + } + + // if the ray hits the sphere closer than closest found hit point yet + if (fSphereHitDistance0.0f) { + // set the current entity as new hit target + cr_fHitDistance=fSphereHitDistance; + cr_penHit = penModel; + cr_pbscBrushSector = NULL; + cr_pbpoBrushPolygon = NULL; + } +} + +void CCastRay::TestModelCollisionBox(CEntity *penModel) +{ + // if no collision box + CCollisionInfo *pci = penModel->en_pciCollisionInfo; + if (pci==NULL) { + // don't test + return; + } + + // get model's collision bounding box + FLOATaabbox3D &boxModel = pci->ci_boxCurrent; + FLOAT fSphereRadius = boxModel.Size().Length()/2.0f; + FLOAT3D vSphereCenter = boxModel.Center(); + + // if the ray doesn't hit the sphere + FLOAT fSphereHitDistance; + if (!RayHitsSphere(cr_vOrigin, cr_vTarget, + vSphereCenter, fSphereRadius+cr_fTestR, fSphereHitDistance) ) { + // ignore + return; + } + + // get entity collision spheres + CStaticArray &ams = pci->ci_absSpheres; + // get entity position + const FLOAT3D &vPosition = penModel->en_plPlacement.pl_PositionVector; + const FLOATmatrix3D &mRotation = penModel->en_mRotation; + + // for each sphere + FOREACHINSTATICARRAY(ams, CMovingSphere, itms) { + // project its center to absolute space + FLOAT3D vCenter = itms->ms_vCenter*mRotation + vPosition; + // if the ray hits the sphere closer than closest found hit point yet + FLOAT fOneSphereHitDistance; + if (RayHitsSphere(cr_vOrigin, cr_vTarget, + vCenter, itms->ms_fR+cr_fTestR, fOneSphereHitDistance) && + fOneSphereHitDistance-cr_fTestR) { + // set the current entity as new hit target + cr_fHitDistance=fOneSphereHitDistance; + cr_penHit = penModel; + cr_pbscBrushSector = NULL; + cr_pbpoBrushPolygon = NULL; + } + } +} + +void CCastRay::TestModelFull(CEntity *penModel, CModelObject &mo) +{ + // NOTE: this contains an ugly hack to simulate good trivial rejection + // for models that have attachments that extend far off the base entity. + // it is used only in wed, so it should not be a big problem. + + // get model's bounding box for all frames and expand it a lot + FLOATaabbox3D boxModel; + mo.GetAllFramesBBox(boxModel); + boxModel.StretchByVector(mo.mo_Stretch*5.0f); + // get center and radius of the bounding sphere in absolute space + FLOAT fSphereRadius = boxModel.Size().Length()/2.0f; + FLOAT3D vSphereCenter = boxModel.Center(); + vSphereCenter*=penModel->en_mRotation; + vSphereCenter+=penModel->en_plPlacement.pl_PositionVector; + + // if the ray doesn't hit the sphere + FLOAT fSphereHitDistance; + if (!RayHitsSphere(cr_vOrigin, cr_vTarget, + vSphereCenter, fSphereRadius+cr_fTestR, fSphereHitDistance) ) { + // ignore + return; + } + + FLOAT fHitDistance; + // if the ray hits the model closer than closest found hit point yet + if (mo.PolygonHit(cl_plRay, penModel->en_plPlacement, 0/*iCurrentMip*/, + fHitDistance)!=NULL + && fHitDistanceIsPredictor() && penModel->IsPredicted()) { + // don't test it + return; + } + + // if hidden model + if( penModel->en_ulFlags&ENF_HIDDEN) + { + // don't test + return; + } + + // get its model + CModelObject *pmoModel; + if (penModel->en_RenderType!=CEntity::RT_BRUSH + && penModel->en_RenderType != CEntity::RT_FIELDBRUSH) { + pmoModel=penModel->en_pmoModelObject; + } else { + // empty brushes are also tested as models + pmoModel=_wrpWorldRenderPrefs.GetEmptyBrushModel(); + } + // if there is no valid model + if (pmoModel==NULL) { + // don't test it + return; + } + CModelObject &mo = *pmoModel; + + // if simple testing, or no testing (used when testing empty brushes) + if (cr_ttHitModels==TT_SIMPLE || cr_ttHitModels==TT_NONE) { + TestModelSimple(penModel, mo); + // if collision box testing + } else if (cr_ttHitModels==TT_COLLISIONBOX) { + TestModelCollisionBox(penModel); + // if full testing + } else if (cr_ttHitModels==TT_FULL || cr_ttHitModels==TT_FULLSEETHROUGH) { + TestModelFull(penModel, mo); + // must be no other testing + } else { + ASSERT(FALSE); + } +} + +/* + * Test against a ska model + */ +void CCastRay::TestSkaModel(CEntity *penModel) +{ + // if origin is predictor, and the model is predicted + if (cr_penOrigin!=NULL && cr_penOrigin->IsPredictor() && penModel->IsPredicted()) { + // don't test it + return; + } + + // if hidden model + if( penModel->en_ulFlags&ENF_HIDDEN) + { + // don't test + return; + } + + CModelInstance &mi = *penModel->GetModelInstance(); + // if simple testing, or no testing (used when testing empty brushes) + if (cr_ttHitModels==TT_SIMPLE || cr_ttHitModels==TT_NONE) { + TestSkaModelSimple(penModel, mi); + // if collision box testing + } else if (cr_ttHitModels==TT_COLLISIONBOX) { + TestModelCollisionBox(penModel); + // if full testing + } else if (cr_ttHitModels==TT_FULL || cr_ttHitModels==TT_FULLSEETHROUGH) { + TestSkaModelFull(penModel, mi); + // must be no other testing + } else { + ASSERT(FALSE); + } +} + +void CCastRay::TestSkaModelSimple(CEntity *penModel, CModelInstance &mi) +{ + FLOATaabbox3D boxModel; + mi.GetCurrentColisionBox(boxModel); + boxModel.StretchByVector(mi.mi_vStretch); + // get center and radius of the bounding sphere in absolute space + FLOAT fSphereRadius = boxModel.Size().Length()/2.0f; + FLOAT3D vSphereCenter = boxModel.Center(); + vSphereCenter*=penModel->en_mRotation; + vSphereCenter+=penModel->en_plPlacement.pl_PositionVector; + + // if the ray doesn't hit the sphere + FLOAT fSphereHitDistance; + if (!RayHitsSphere(cr_vOrigin, cr_vTarget, + vSphereCenter, fSphereRadius+cr_fTestR, fSphereHitDistance) ) { + // ignore + return; + } + + // if the ray hits the sphere closer than closest found hit point yet + if (fSphereHitDistance0.0f) { + // set the current entity as new hit target + cr_fHitDistance=fSphereHitDistance; + cr_penHit = penModel; + cr_pbscBrushSector = NULL; + cr_pbpoBrushPolygon = NULL; + } +} + +void CCastRay::TestSkaModelFull(CEntity *penModel, CModelInstance &mi) +{ + FLOATaabbox3D boxModel; + mi.GetAllFramesBBox(boxModel); + boxModel.StretchByVector(mi.mi_vStretch); + // get center and radius of the bounding sphere in absolute space + FLOAT fSphereRadius = boxModel.Size().Length()/2.0f; + FLOAT3D vSphereCenter = boxModel.Center(); + vSphereCenter*=penModel->en_mRotation; + vSphereCenter+=penModel->en_plPlacement.pl_PositionVector; + + // if the ray doesn't hit the sphere + FLOAT fSphereHitDistance; + if (!RayHitsSphere(cr_vOrigin, cr_vTarget, + vSphereCenter, fSphereRadius+cr_fTestR, fSphereHitDistance) ) { + // ignore + return; + } + + // if the ray hits the sphere closer than closest found hit point yet + if (fSphereHitDistance0.0f) { + FLOAT fTriangleHitDistance; + // set the current entity as new hit target +// cr_fHitDistance=fSphereHitDistance; +// cr_penHit = penModel; +// cr_pbscBrushSector = NULL; +// cr_pbpoBrushPolygon = NULL; + + INDEX iBoneID = -1; + if (cr_bFindBone) { + fTriangleHitDistance = RM_TestRayCastHit(mi,penModel->en_mRotation,penModel->en_plPlacement.pl_PositionVector,cr_vOrigin,cr_vTarget,cr_fHitDistance,&iBoneID); + } else { + fTriangleHitDistance = RM_TestRayCastHit(mi,penModel->en_mRotation,penModel->en_plPlacement.pl_PositionVector,cr_vOrigin,cr_vTarget,cr_fHitDistance,NULL); + } + + if (fTriangleHitDistance0.0f) { + // set the current entity as new hit target + cr_fHitDistance=fTriangleHitDistance; + cr_penHit = penModel; + cr_pbscBrushSector = NULL; + cr_pbpoBrushPolygon = NULL; + + if (cr_bFindBone) { + cr_iBoneHit = iBoneID; + } + } + + } + return; +} + +void CCastRay::TestTerrain(CEntity *penTerrain) +{ + // if hidden model + if( penTerrain->en_ulFlags&ENF_HIDDEN) { + // don't test + return; + } + + CTerrain *ptrTerrain = penTerrain->GetTerrain(); + FLOAT fHitDistance = TestRayCastHit(ptrTerrain,penTerrain->en_mRotation, penTerrain->en_plPlacement.pl_PositionVector, + cr_vOrigin,cr_vTarget,cr_fHitDistance,cr_bHitTerrainInvisibleTris); + + if (fHitDistance0.0f) { + // set the current entity as new hit target + cr_fHitDistance=fHitDistance; + cr_penHit = penTerrain; + cr_pbscBrushSector = NULL; + cr_pbpoBrushPolygon = NULL; + } +} + +/* + * Test against a brush sector. + */ +void CCastRay::TestBrushSector(CBrushSector *pbscSector) +{ + // if entity is hidden + if(pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->en_ulFlags&ENF_HIDDEN) + { + // don't cast ray + return; + } + // for each polygon in the sector + FOREACHINSTATICARRAY(pbscSector->bsc_abpoPolygons, CBrushPolygon, itpoPolygon) { + CBrushPolygon &bpoPolygon = itpoPolygon.Current(); + + if (&bpoPolygon==cr_pbpoIgnore) { + continue; + } + + ULONG ulFlags = bpoPolygon.bpo_ulFlags; + // if not testing recursively + if (cr_penOrigin==NULL) { + // if the polygon is portal + if (ulFlags&BPOF_PORTAL) { + // if it is translucent or selected + if (ulFlags&(BPOF_TRANSLUCENT|BPOF_TRANSPARENT|BPOF_SELECTED)) { + // if translucent portals should be passed through + if (!cr_bHitTranslucentPortals) { + // skip this polygon + continue; + } + // if it is not translucent + } else { + // if portals should be passed through + if (!cr_bHitPortals) { + // skip this polygon + continue; + } + } + } + // if polygon is detail, and detail polygons are off + extern INDEX wld_bRenderDetailPolygons; + if ((ulFlags&BPOF_DETAILPOLYGON) && !wld_bRenderDetailPolygons) { + // skip this polygon + continue; + } + } + // get distances of ray points from the polygon plane + FLOAT fDistance0 = bpoPolygon.bpo_pbplPlane->bpl_plAbsolute.PointDistance(cr_vOrigin); + FLOAT fDistance1 = bpoPolygon.bpo_pbplPlane->bpl_plAbsolute.PointDistance(cr_vTarget); + + // if the ray hits the polygon plane + if (fDistance0>=0 && fDistance0>=fDistance1) { + // calculate fraction of line before intersection + FLOAT fFraction = fDistance0/((fDistance0-fDistance1) + 0.0000001f/*correction*/); + // calculate intersection coordinate + FLOAT3D vHitPoint = cr_vOrigin+(cr_vTarget-cr_vOrigin)*fFraction; + // calculate intersection distance + FLOAT fHitDistance = (vHitPoint-cr_vOrigin).Length(); + // if the hit point can not be new closest candidate + if (fHitDistance>cr_fHitDistance) { + // skip this polygon + continue; + } + + // find major axes of the polygon plane + INDEX iMajorAxis1, iMajorAxis2; + GetMajorAxesForPlane(itpoPolygon->bpo_pbplPlane->bpl_plAbsolute, iMajorAxis1, iMajorAxis2); + + // create an intersector + CIntersector isIntersector(vHitPoint(iMajorAxis1), vHitPoint(iMajorAxis2)); + // for all edges in the polygon + FOREACHINSTATICARRAY(bpoPolygon.bpo_abpePolygonEdges, CBrushPolygonEdge, + itbpePolygonEdge) { + // get edge vertices (edge direction is irrelevant here!) + const FLOAT3D &vVertex0 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + const FLOAT3D &vVertex1 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + // pass the edge to the intersector + isIntersector.AddEdge( + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2), + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2)); + } + // if the polygon is intersected by the ray + if (isIntersector.IsIntersecting()) { + // if it is portal and testing recusively + if ((ulFlags&cr_ulPassablePolygons) && (cr_penOrigin!=NULL)) { + // for each sector on the other side + {FOREACHDSTOFSRC(bpoPolygon.bpo_rsOtherSideSectors, CBrushSector, bsc_rdOtherSidePortals, pbsc) + // add the sector + AddSector(pbsc); + ENDFOR} + + if( cr_bHitPortals && ulFlags&(BPOF_TRANSLUCENT|BPOF_TRANSPARENT) && !cr_bPhysical) + { + // remember hit coordinates + cr_fHitDistance=fHitDistance; + cr_penHit = pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + cr_pbscBrushSector = pbscSector; + cr_pbpoBrushPolygon = &bpoPolygon; + } + // if the ray just plainly hit it + } else { + // remember hit coordinates + cr_fHitDistance=fHitDistance; + cr_penHit = pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + cr_pbscBrushSector = pbscSector; + cr_pbpoBrushPolygon = &bpoPolygon; + } + } + } + } +} + +/* Add a sector if needed. */ +inline void CCastRay::AddSector(CBrushSector *pbsc) +{ + // if not already active and in first mip of its brush + if ( pbsc->bsc_pbmBrushMip->IsFirstMip() + &&!(pbsc->bsc_ulFlags&BSCF_RAYTESTED)) { + // add it to active sectors + _aas.Push().as_pbsc = pbsc; + pbsc->bsc_ulFlags|=BSCF_RAYTESTED; + } +} +/* Add all sectors of a brush. */ +void CCastRay::AddAllSectorsOfBrush(CBrush3D *pbr) +{ + // get relevant mip as if in manual mip brushing mode + CBrushMip *pbmMip = pbr->GetBrushMipByDistance( + _wrpWorldRenderPrefs.GetManualMipBrushingFactor()); + + // if it has no brush mip for that mip factor + if (pbmMip==NULL) { + // skip it + return; + } + // for each sector in the brush mip + FOREACHINDYNAMICARRAY(pbmMip->bm_abscSectors, CBrushSector, itbsc) { + // add the sector + AddSector(itbsc); + } +} + +/* Add all sectors around given entity. */ +void CCastRay::AddSectorsAroundEntity(CEntity *pen) +{ + // for each zoning sector that this entity is in + {FOREACHSRCOFDST(pen->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // if part of zoning brush + if (pbsc->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity->GetRenderType()!=CEntity::RT_BRUSH) { + // skip it + continue; + } + // add the sector + AddSector(pbsc); + ENDFOR} +} + +/* Test entire world against ray. */ +void CCastRay::TestWholeWorld(CWorld *pwoWorld) +{ + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(pwoWorld->wo_cenEntities, CEntity, itenInWorld) { + // if it is the origin of the ray + if (itenInWorld==cr_penOrigin || itenInWorld==cr_penIgnore) { + // skip it + continue; + } + + // if it is a brush and testing against brushes is disabled + if( (itenInWorld->en_RenderType == CEntity::RT_BRUSH || + itenInWorld->en_RenderType == CEntity::RT_FIELDBRUSH) && + !cr_bHitBrushes) { + // skip it + continue; + } + + // if it is a model and testing against models is enabled + if(((itenInWorld->en_RenderType == CEntity::RT_MODEL + ||(itenInWorld->en_RenderType == CEntity::RT_EDITORMODEL + && _wrpWorldRenderPrefs.IsEditorModelsOn())) + && cr_ttHitModels != TT_NONE) + // and if cast type is TT_FULL_SEETROUGH then model is not + // ENF_SEETROUGH + && !((cr_ttHitModels == TT_FULLSEETHROUGH || cr_ttHitModels == TT_COLLISIONBOX) && + (itenInWorld->en_ulFlags&ENF_SEETHROUGH))) { + // test it against the model entity + TestModel(itenInWorld); + // if it is a ska model + } else if(((itenInWorld->en_RenderType == CEntity::RT_SKAMODEL + ||(itenInWorld->en_RenderType == CEntity::RT_SKAEDITORMODEL + && _wrpWorldRenderPrefs.IsEditorModelsOn())) + && cr_ttHitModels != TT_NONE) + // and if cast type is TT_FULL_SEETROUGH then model is not + // ENF_SEETROUGH + && !((cr_ttHitModels == TT_FULLSEETHROUGH || cr_ttHitModels == TT_COLLISIONBOX) && + (itenInWorld->en_ulFlags&ENF_SEETHROUGH))) { + TestSkaModel(itenInWorld); + } else if (itenInWorld->en_RenderType == CEntity::RT_TERRAIN) { + TestTerrain(itenInWorld); + // if it is a brush + } else if (itenInWorld->en_RenderType == CEntity::RT_BRUSH || + (itenInWorld->en_RenderType == CEntity::RT_FIELDBRUSH + &&_wrpWorldRenderPrefs.IsFieldBrushesOn() && cr_bHitFields)) { + // get its brush + CBrush3D &brBrush = *itenInWorld->en_pbrBrush; + + // get relevant mip as if in manual mip brushing mode + CBrushMip *pbmMip = brBrush.GetBrushMipByDistance( + _wrpWorldRenderPrefs.GetManualMipBrushingFactor()); + + // if it has no brush mip for that mip factor + if (pbmMip==NULL) { + // skip it + continue; + } + + // if it has zero sectors + if (pbmMip->bm_abscSectors.Count()==0){ + // test it against the model entity + TestModel(itenInWorld); + + // if it has some sectors + } else { + // for each sector in the brush mip + FOREACHINDYNAMICARRAY(pbmMip->bm_abscSectors, CBrushSector, itbsc) { + // if the sector is not hidden + if (!(itbsc->bsc_ulFlags & BSCF_HIDDEN)) { + // test the ray against the sector + TestBrushSector(itbsc); + } + } + } + } + }} +} + +/* Test active sectors recusively. */ +void CCastRay::TestThroughSectors(void) +{ + // for each active sector (sectors are added during iteration!) + for(INDEX ias=0; ias<_aas.Count(); ias++) { + CBrushSector *pbsc = _aas[ias].as_pbsc; + // test the ray against the sector + TestBrushSector(pbsc); + // for each entity in the sector + {FOREACHDSTOFSRC(pbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) + // if it is the origin of the ray + if (pen==cr_penOrigin || pen==cr_penIgnore) { + // skip it + continue; + } + // if it is a model and testing against models is enabled + if(((pen->en_RenderType == CEntity::RT_MODEL + ||(pen->en_RenderType == CEntity::RT_EDITORMODEL + && _wrpWorldRenderPrefs.IsEditorModelsOn())) + && cr_ttHitModels != TT_NONE) + // and if cast type is TT_FULL_SEETROUGH then model is not + // ENF_SEETROUGH + && !((cr_ttHitModels == TT_FULLSEETHROUGH || cr_ttHitModels == TT_COLLISIONBOX) && + (pen->en_ulFlags&ENF_SEETHROUGH))) { + // test it against the model entity + TestModel(pen); + // if is is a ska model + } else if(((pen->en_RenderType == CEntity::RT_SKAMODEL + ||(pen->en_RenderType == CEntity::RT_SKAEDITORMODEL + && _wrpWorldRenderPrefs.IsEditorModelsOn())) + && cr_ttHitModels != TT_NONE) + // and if cast type is TT_FULL_SEETROUGH then model is not + // ENF_SEETROUGH + && !((cr_ttHitModels == TT_FULLSEETHROUGH || cr_ttHitModels == TT_COLLISIONBOX) && + (pen->en_ulFlags&ENF_SEETHROUGH))) { + // test it against the ska model entity + TestSkaModel(pen); + // if it is a terrain + } else if( pen->en_RenderType == CEntity::RT_TERRAIN) { + CTerrain *ptrTerrain = pen->GetTerrain(); + ASSERT(ptrTerrain!=NULL); + // if terrain hasn't allready been tested + if(!ptrTerrain->tr_lnInActiveTerrains.IsLinked()) { + // test it now and add it to list of tested terrains + TestTerrain(pen); + _lhTestedTerrains.AddTail(ptrTerrain->tr_lnInActiveTerrains); + } + // if it is a non-hidden brush + } else if ( (pen->en_RenderType == CEntity::RT_BRUSH) && + !(pen->en_ulFlags&ENF_HIDDEN) ) { + // get its brush + CBrush3D &brBrush = *pen->en_pbrBrush; + // add all sectors in the brush + AddAllSectorsOfBrush(&brBrush); + } + ENDFOR} + } + + // for all tested terrains + {FORDELETELIST(CTerrain, tr_lnInActiveTerrains, _lhTestedTerrains, ittr) { + // remove it from list + ittr->tr_lnInActiveTerrains.Remove(); + }} + ASSERT(_lhTestedTerrains.IsEmpty()); +} + +/* + * Do the ray casting. + */ +void CCastRay::Cast(CWorld *pwoWorld) +{ + // setup stat timers + const BOOL bMainLoopTimer = _sfStats.CheckTimer(CStatForm::STI_MAINLOOP); + if( bMainLoopTimer) _sfStats.StopTimer(CStatForm::STI_MAINLOOP); + _sfStats.StartTimer(CStatForm::STI_RAYCAST); + + // initially no polygon is found + cr_pbpoBrushPolygon= NULL; + cr_pbscBrushSector = NULL; + cr_penHit = NULL; + if (cr_bPhysical) { + cr_ulPassablePolygons = BPOF_PASSABLE|BPOF_SHOOTTHRU; + } else { + cr_ulPassablePolygons = BPOF_PORTAL|BPOF_OCCLUDER; + } + + // if origin entity is given + if (cr_penOrigin!=NULL) { + // if not continuing + if (_aas.Count()==0) { + // add all sectors around it + AddSectorsAroundEntity(cr_penOrigin); + } + // test all sectors recursively + TestThroughSectors(); + // if there is no origin entity + } else { + // test entire world against ray + TestWholeWorld(pwoWorld); + } + + // calculate the hit point from the hit distance + cr_vHit = cr_vOrigin + (cr_vTarget-cr_vOrigin).Normalize()*cr_fHitDistance; + + // done with timing + _sfStats.StopTimer(CStatForm::STI_RAYCAST); + if( bMainLoopTimer) _sfStats.StartTimer(CStatForm::STI_MAINLOOP); +} + + +/* + * Continue cast. + */ +void CCastRay::ContinueCast(CWorld *pwoWorld) +{ + cr_pbpoIgnore = cr_pbpoBrushPolygon; + if (cr_penHit->GetRenderType()==CEntity::RT_MODEL) { + cr_penIgnore = cr_penHit; + } + + cr_vOrigin = cr_vHit; + cl_plRay.pl_PositionVector = cr_vOrigin; + cr_fHitDistance = (cr_vTarget-cr_vOrigin).Length() + EPSILON; + Cast(pwoWorld); +} + +///////////////////////////////////////////////////////////////////// +/* + * Cast a ray and see what it hits. + */ +void CWorld::CastRay(CCastRay &crRay) +{ + crRay.Cast(this); +} +/* + * Continue to cast already cast ray + */ +void CWorld::ContinueCast(CCastRay &crRay) +{ + crRay.ContinueCast(this); +} diff --git a/Sources/Engine/World/WorldRayCasting.h b/Sources/Engine/World/WorldRayCasting.h new file mode 100644 index 0000000..2bffad7 --- /dev/null +++ b/Sources/Engine/World/WorldRayCasting.h @@ -0,0 +1,107 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_WORLDRAYCASTING_H +#define SE_INCL_WORLDRAYCASTING_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +/* + * Class that describes casting of a ray. + */ +class ENGINE_API CCastRay { +public: + // diferent types of testing + enum TestType { + TT_NONE, // do not test at all + TT_SIMPLE, // do approximate testing + TT_COLLISIONBOX, // do testing by collision box + TT_FULL, // do full testing + TT_FULLSEETHROUGH, // do full testing without entities marked as see through + }; +public: + BOOL cr_bAllowOverHit; // set if the ray can hit behind its target + ULONG cr_ulPassablePolygons; // flags mask for pass-through testing + CBrushPolygon *cr_pbpoIgnore; // polygon that is origin of the continuted ray (is never hit by the ray) + CEntity *cr_penIgnore; // entity that is origin of the continuted ray (is never hit by the ray) + + /* Internal construction helper. */ + void Init(CEntity *penOrigin, const FLOAT3D &vOrigin, const FLOAT3D &vTarget); + void ClearSectorList(void); + + /* Add a sector if needed. */ + inline void AddSector(CBrushSector *pbsc); + /* Add all sectors of a brush. */ + void AddAllSectorsOfBrush(CBrush3D *pbr); + /* Add all sectors around given entity. */ + void AddSectorsAroundEntity(CEntity *pen); + + /* Test against a model entity. */ + void TestModelSimple(CEntity *penModel, CModelObject &mo); + void TestModelCollisionBox(CEntity *penModel); + void TestModelFull(CEntity *penModel, CModelObject &mo); + void TestSkaModelSimple(CEntity *penModel, CModelInstance &mi); + void TestSkaModelFull(CEntity *penModel, CModelInstance &mi); + void TestModel(CEntity *penModel); + void TestSkaModel(CEntity *penModel); + + /* Test against a terrain */ + void TestTerrain(CEntity *penTerrain); + + /* Test against a brush sector. */ + void TestBrushSector(CBrushSector *pbscSector); + + /* Test entire world against ray. */ + void TestWholeWorld(CWorld *pwoWorld); + /* Test active sectors recusively. */ + void TestThroughSectors(void); + + +public: +// these are filled by the constructor: + CPlacement3D cl_plRay; // placement of the ray in absolute space + CEntity *cr_penOrigin; // entity that is origin of the ray (is never hit by the ray) + FLOAT3D cr_vOrigin; // coordinates of ray origin + FLOAT3D cr_vTarget; // coordinates of ray target + FLOAT3D cr_vOriginRelative; // coordinates of ray origin relative to current entity + FLOAT3D cr_vTargetRelative; // coordinates of ray target relative to current entity + +// these can be altered afterwards for special options + BOOL cr_bHitPortals; // don't pass through portals (off by default) + BOOL cr_bHitTranslucentPortals; // don't pass through translucent portals (on by default) + enum TestType cr_ttHitModels; // type of testing against models (simple by default) + BOOL cr_bHitFields; // don't pass thrugh field brushes (off by default) + BOOL cr_bHitBrushes; // don't pass thrugh brushes (on by default) + BOOL cr_bHitTerrainInvisibleTris;// don't pass thrugh invisible terrain triangles (off by default) + BOOL cr_bPhysical; // pass only where physical objects can pass + FLOAT cr_fTestR; // additional radius of ray (default 0) + +// these are filled by casting algorithm: + CEntity *cr_penHit; // entity hit by ray, NULL if ray was cast in void + FLOAT3D cr_vHit; // coordinate where the ray hit the entity + FLOAT cr_fHitDistance; // how far the hit was from the origin + + BOOL cr_bFindBone; // should the bone ID be checked while testing with SKA + INDEX cr_iBoneHit; // id of the bone hit by the ray (SKA) + + CBrushPolygon *cr_pbpoBrushPolygon; // polygon that was hit (if brush entity hit) + CBrushSector *cr_pbscBrushSector; // sector that was hit (if brush entity hit) + + /* Constructor. */ + CCastRay(CEntity *penOrigin, const CPlacement3D &plOrigin); // target is very far away + CCastRay(CEntity *penOrigin, const CPlacement3D &plOrigin, FLOAT fMaxTestDistance); + CCastRay(CEntity *penOrigin, const FLOAT3D &vOrigin, const FLOAT3D &vTarget); + ~CCastRay(void); + + /* Do the ray casting. */ + void Cast(CWorld *pwoWorld); + /* Continue cast. */ + void ContinueCast(CWorld *pwoWorld); +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/World/WorldSettings.h b/Sources/Engine/World/WorldSettings.h new file mode 100644 index 0000000..35c5b73 --- /dev/null +++ b/Sources/Engine/World/WorldSettings.h @@ -0,0 +1,145 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_WORLDSETTINGS_H +#define SE_INCL_WORLDSETTINGS_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +#include +#include + +// type of dynamic texture mapping transformation +class ENGINE_API CTextureTransformation { +public: + CTString tt_strName; + CMappingDefinition tt_mdTransformation; + + /* Constructor. */ + CTextureTransformation(void); +}; + +// type of texture blending used for a texture on a polygon +class ENGINE_API CTextureBlending { +public: + CTString tb_strName; + UBYTE tb_ubBlendingType; // uses gfx flags for texture blending (STX_BLEND_xxxx) + COLOR tb_colMultiply; // original polygon color is multiplied by this + + /* Constructor. */ + CTextureBlending(void); +}; + +// type of surface of a polygon (its physical properties) +#define STF_SLIDEDOWNSLOPE (1UL<<0) // can accelerate only across slope, not up/down +#define STF_NOIMPACT (1UL<<1) // cannot damage because of impact with this polygon +class ENGINE_API CSurfaceType { +public: + FLOAT st_fFriction; // friction coefficient on the surface + FLOAT st_fStairsHeight; // stairs step-up height modifier (=0-no step, >0 use max, <0 use min) + FLOAT st_fClimbSlopeCos; // cosine of max. climbable slope + FLOAT st_fJumpSlopeCos; // cosine of max. jump-from slope + INDEX st_iWalkDamageType; // type of damage inflicted when walking on surface + FLOAT st_fWalkDamageAmount; // how much to damage when inside + FLOAT st_tmWalkDamageDelay; // how much to delay before first damage + FLOAT st_tmWalkDamageFrequency; // how much to delay between two damages + ULONG st_ulFlags; + CTString st_strName; // name of surface type + /* Default constructor. */ + CSurfaceType(void) : + st_fFriction(1.0f), + st_fStairsHeight(1.0f), + st_fClimbSlopeCos( 0.7071067811865f/*cos(45.0f)*/), + st_fJumpSlopeCos( 0.7071067811865f/*cos(45.0f)*/), + st_iWalkDamageType(0), + st_fWalkDamageAmount(0), + st_tmWalkDamageDelay(0), + st_tmWalkDamageFrequency(100), + st_ulFlags(0), + st_strName("") {} +}; + +// type of content of a sector +#define CTF_BREATHABLE_LUNGS (1UL<<0) // breathable for creatures with lungs +#define CTF_BREATHABLE_GILLS (1UL<<1) // breathable for creatures with gills +#define CTF_FLYABLE (1UL<<2) // flyable in if can fly +#define CTF_SWIMABLE (1UL<<3) // swimmable in if enough density +#define CTF_FADESPINNING (1UL<<4) // spinning objects may stop spinning + +class ENGINE_API CContentType { +public: + CTString ct_strName; // name of surface type + ULONG ct_ulFlags; // various flags + FLOAT ct_fDensity; // density of the fluid inside content kg/m3 - defines buoyancy + + FLOAT ct_fFluidFriction; // friction inside the fluid (stopping movements) + FLOAT ct_fControlMultiplier; // defines voluntary acceleration/decceleration + FLOAT ct_fSpeedMultiplier; // max. speed modifier inside the fluid + INDEX ct_iSwimDamageType; // type of damage inflicted when swimming + FLOAT ct_fSwimDamageAmount; // how much to damage when inside + FLOAT ct_tmSwimDamageDelay; // how much to delay before first damage + FLOAT ct_tmSwimDamageFrequency; // how much to delay between two damages + FLOAT ct_fDrowningDamageAmount; // how much to damage when drowning + FLOAT ct_tmDrowningDamageDelay; // how much to delay between two damages + FLOAT ct_fKillImmersion; // contents kills anything alive that gets in deeper than this + INDEX ct_iKillDamageType; // type of killing damage + /* Default constructor. */ + CContentType(void) : + ct_strName(""), + ct_ulFlags(CTF_BREATHABLE_LUNGS|CTF_FLYABLE), + ct_fDensity(0), + ct_fFluidFriction (0), + ct_fControlMultiplier(1), + ct_fSpeedMultiplier(1), + ct_iSwimDamageType(0), + ct_fSwimDamageAmount(0), + ct_tmSwimDamageDelay(0), + ct_tmSwimDamageFrequency(100), + ct_fDrowningDamageAmount(10), + ct_tmDrowningDamageDelay(1), + ct_fKillImmersion(0), + ct_iKillDamageType(0) + {} +}; + +class ENGINE_API CEnvironmentType { +public: + CTString et_strName; // name of environment type + INDEX et_iType; + FLOAT et_fSize; + /* Default constructor. */ + CEnvironmentType(void) : + et_strName(""), + et_iType(1), + et_fSize(7.5) + {} +}; + +/* + * One type of illuminating polygon. + */ +class ENGINE_API CIlluminationType { +public: + CTString it_strName; // name of illumination type + + /* Default constructor. */ + CIlluminationType(void) : it_strName("") {}; +}; + +/* + * One type of mirroring (or warping) polygon. + */ +#define MPF_WARP (1UL<<0) // warp portal +class CMirrorParameters { +public: + ULONG mp_ulFlags; + // for warps + CPlacement3D mp_plWarpIn; // warp entry + CPlacement3D mp_plWarpOut; // warp exit + CEntity *mp_penWarpViewer; // which entity to view from + FLOAT mp_fWarpFOV; // FOV, -1 for no change +}; + + +#endif /* include-once check. */ + diff --git a/Sources/Engine/temp.h b/Sources/Engine/temp.h new file mode 100644 index 0000000..1a53b22 --- /dev/null +++ b/Sources/Engine/temp.h @@ -0,0 +1,2 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + diff --git a/Sources/Engine/zlib/adler32.c b/Sources/Engine/zlib/adler32.c new file mode 100644 index 0000000..16cf9a7 --- /dev/null +++ b/Sources/Engine/zlib/adler32.c @@ -0,0 +1,48 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +#define BASE 65521L /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} diff --git a/Sources/Engine/zlib/compress.c b/Sources/Engine/zlib/compress.c new file mode 100644 index 0000000..1cee470 --- /dev/null +++ b/Sources/Engine/zlib/compress.c @@ -0,0 +1,68 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} diff --git a/Sources/Engine/zlib/deflate.c b/Sources/Engine/zlib/deflate.c new file mode 100644 index 0000000..25d5818 --- /dev/null +++ b/Sources/Engine/zlib/deflate.c @@ -0,0 +1,1350 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in ftp://ds.internic.net/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id$ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.1.3 Copyright 1995-1998 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +local block_state deflate_slow OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int noheader = 0; + static const char* my_version = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == Z_NULL) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == Z_NULL) strm->zfree = zcfree; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#ifdef FASTEST + level = 1; +#endif + + if (windowBits < 0) { /* undocumented feature: suppress zlib header */ + noheader = 1; + windowBits = -windowBits; + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->noheader = noheader; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->status != INIT_STATE) return Z_STREAM_ERROR; + + s = strm->state; + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->noheader < 0) { + s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ + } + s->status = s->noheader ? BUSY_STATE : INIT_STATE; + strm->adler = 1; + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + + if (level == Z_DEFAULT_COMPRESSION) { + level = 6; + } + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the zlib header */ + if (s->status == INIT_STATE) { + + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags = (s->level-1) >> 1; + + if (level_flags > 3) level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = 1L; + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUFF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->noheader) return Z_STREAM_END; + + /* Write the zlib trailer (adler32) */ + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + s->noheader = -1; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (!strm->state->noheader) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +#ifndef FASTEST +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} + +#else /* FASTEST */ +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return len <= s->lookahead ? len : s->lookahead; +} +#endif /* FASTEST */ +#endif /* ASMV */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + } else if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in hash table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED || + (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/Sources/Engine/zlib/deflate.h b/Sources/Engine/zlib/deflate.h new file mode 100644 index 0000000..962676d --- /dev/null +++ b/Sources/Engine/zlib/deflate.h @@ -0,0 +1,318 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-1998 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef _DEFLATE_H +#define _DEFLATE_H + +#include "zutil.h" + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int noheader; /* suppress zlib header and adler32 */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif diff --git a/Sources/Engine/zlib/infblock.c b/Sources/Engine/zlib/infblock.c new file mode 100644 index 0000000..f4920fa --- /dev/null +++ b/Sources/Engine/zlib/infblock.c @@ -0,0 +1,398 @@ +/* infblock.c -- interpret and process block types to last block + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* Table for deflate from PKZIP's appnote.txt. */ +local const uInt border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* + Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarily, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. + */ + + +void inflate_blocks_reset(s, z, c) +inflate_blocks_statef *s; +z_streamp z; +uLongf *c; +{ + if (c != Z_NULL) + *c = s->check; + if (s->mode == BTREE || s->mode == DTREE) + ZFREE(z, s->sub.trees.blens); + if (s->mode == CODES) + inflate_codes_free(s->sub.decode.codes, z); + s->mode = TYPE; + s->bitk = 0; + s->bitb = 0; + s->read = s->write = s->window; + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); + Tracev((stderr, "inflate: blocks reset\n")); +} + + +inflate_blocks_statef *inflate_blocks_new(z, c, w) +z_streamp z; +check_func c; +uInt w; +{ + inflate_blocks_statef *s; + + if ((s = (inflate_blocks_statef *)ZALLOC + (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) + return s; + if ((s->hufts = + (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) + { + ZFREE(z, s); + return Z_NULL; + } + if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) + { + ZFREE(z, s->hufts); + ZFREE(z, s); + return Z_NULL; + } + s->end = s->window + w; + s->checkfn = c; + s->mode = TYPE; + Tracev((stderr, "inflate: blocks allocated\n")); + inflate_blocks_reset(s, z, Z_NULL); + return s; +} + + +int inflate_blocks(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt t; /* temporary storage */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input based on current state */ + while (1) switch (s->mode) + { + case TYPE: + NEEDBITS(3) + t = (uInt)b & 7; + s->last = t & 1; + switch (t >> 1) + { + case 0: /* stored */ + Tracev((stderr, "inflate: stored block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + t = k & 7; /* go to byte boundary */ + DUMPBITS(t) + s->mode = LENS; /* get length of stored block */ + break; + case 1: /* fixed */ + Tracev((stderr, "inflate: fixed codes block%s\n", + s->last ? " (last)" : "")); + { + uInt bl, bd; + inflate_huft *tl, *td; + + inflate_trees_fixed(&bl, &bd, &tl, &td, z); + s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); + if (s->sub.decode.codes == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + } + DUMPBITS(3) + s->mode = CODES; + break; + case 2: /* dynamic */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + s->mode = TABLE; + break; + case 3: /* illegal */ + DUMPBITS(3) + s->mode = BAD; + z->msg = (char*)"invalid block type"; + r = Z_DATA_ERROR; + LEAVE + } + break; + case LENS: + NEEDBITS(32) + if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) + { + s->mode = BAD; + z->msg = (char*)"invalid stored block lengths"; + r = Z_DATA_ERROR; + LEAVE + } + s->sub.left = (uInt)b & 0xffff; + b = k = 0; /* dump bits */ + Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); + s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); + break; + case STORED: + if (n == 0) + LEAVE + NEEDOUT + t = s->sub.left; + if (t > n) t = n; + if (t > m) t = m; + zmemcpy(q, p, t); + p += t; n -= t; + q += t; m -= t; + if ((s->sub.left -= t) != 0) + break; + Tracev((stderr, "inflate: stored end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + s->mode = s->last ? DRY : TYPE; + break; + case TABLE: + NEEDBITS(14) + s->sub.trees.table = t = (uInt)b & 0x3fff; +#ifndef PKZIP_BUG_WORKAROUND + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + s->mode = BAD; + z->msg = (char*)"too many length or distance symbols"; + r = Z_DATA_ERROR; + LEAVE + } +#endif + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + DUMPBITS(14) + s->sub.trees.index = 0; + Tracev((stderr, "inflate: table sizes ok\n")); + s->mode = BTREE; + case BTREE: + while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) + { + NEEDBITS(3) + s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; + DUMPBITS(3) + } + while (s->sub.trees.index < 19) + s->sub.trees.blens[border[s->sub.trees.index++]] = 0; + s->sub.trees.bb = 7; + t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, + &s->sub.trees.tb, s->hufts, z); + if (t != Z_OK) + { + ZFREE(z, s->sub.trees.blens); + r = t; + if (r == Z_DATA_ERROR) + s->mode = BAD; + LEAVE + } + s->sub.trees.index = 0; + Tracev((stderr, "inflate: bits tree ok\n")); + s->mode = DTREE; + case DTREE: + while (t = s->sub.trees.table, + s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) + { + inflate_huft *h; + uInt i, j, c; + + t = s->sub.trees.bb; + NEEDBITS(t) + h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); + t = h->bits; + c = h->base; + if (c < 16) + { + DUMPBITS(t) + s->sub.trees.blens[s->sub.trees.index++] = c; + } + else /* c == 16..18 */ + { + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + NEEDBITS(t + i) + DUMPBITS(t) + j += (uInt)b & inflate_mask[i]; + DUMPBITS(i) + i = s->sub.trees.index; + t = s->sub.trees.table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + z->msg = (char*)"invalid bit length repeat"; + r = Z_DATA_ERROR; + LEAVE + } + c = c == 16 ? s->sub.trees.blens[i - 1] : 0; + do { + s->sub.trees.blens[i++] = c; + } while (--j); + s->sub.trees.index = i; + } + } + s->sub.trees.tb = Z_NULL; + { + uInt bl, bd; + inflate_huft *tl, *td; + inflate_codes_statef *c; + + bl = 9; /* must be <= 9 for lookahead assumptions */ + bd = 6; /* must be <= 9 for lookahead assumptions */ + t = s->sub.trees.table; + t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), + s->sub.trees.blens, &bl, &bd, &tl, &td, + s->hufts, z); + ZFREE(z, s->sub.trees.blens); + if (t != Z_OK) + { + if (t == (uInt)Z_DATA_ERROR) + s->mode = BAD; + r = t; + LEAVE + } + Tracev((stderr, "inflate: trees ok\n")); + if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + s->sub.decode.codes = c; + } + s->mode = CODES; + case CODES: + UPDATE + if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) + return inflate_flush(s, z, r); + r = Z_OK; + inflate_codes_free(s->sub.decode.codes, z); + LOAD + Tracev((stderr, "inflate: codes end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + if (!s->last) + { + s->mode = TYPE; + break; + } + s->mode = DRY; + case DRY: + FLUSH + if (s->read != s->write) + LEAVE + s->mode = DONE; + case DONE: + r = Z_STREAM_END; + LEAVE + case BAD: + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +} + + +int inflate_blocks_free(s, z) +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_blocks_reset(s, z, Z_NULL); + ZFREE(z, s->window); + ZFREE(z, s->hufts); + ZFREE(z, s); + Tracev((stderr, "inflate: blocks freed\n")); + return Z_OK; +} + + +void inflate_set_dictionary(s, d, n) +inflate_blocks_statef *s; +const Bytef *d; +uInt n; +{ + zmemcpy(s->window, d, n); + s->read = s->write = s->window + n; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. + * IN assertion: s != Z_NULL + */ +int inflate_blocks_sync_point(s) +inflate_blocks_statef *s; +{ + return s->mode == LENS; +} diff --git a/Sources/Engine/zlib/infblock.h b/Sources/Engine/zlib/infblock.h new file mode 100644 index 0000000..bd25c80 --- /dev/null +++ b/Sources/Engine/zlib/infblock.h @@ -0,0 +1,39 @@ +/* infblock.h -- header to use infblock.c + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_blocks_state; +typedef struct inflate_blocks_state FAR inflate_blocks_statef; + +extern inflate_blocks_statef * inflate_blocks_new OF(( + z_streamp z, + check_func c, /* check function */ + uInt w)); /* window size */ + +extern int inflate_blocks OF(( + inflate_blocks_statef *, + z_streamp , + int)); /* initial return code */ + +extern void inflate_blocks_reset OF(( + inflate_blocks_statef *, + z_streamp , + uLongf *)); /* check value on output */ + +extern int inflate_blocks_free OF(( + inflate_blocks_statef *, + z_streamp)); + +extern void inflate_set_dictionary OF(( + inflate_blocks_statef *s, + const Bytef *d, /* dictionary */ + uInt n)); /* dictionary length */ + +extern int inflate_blocks_sync_point OF(( + inflate_blocks_statef *s)); diff --git a/Sources/Engine/zlib/infcodes.c b/Sources/Engine/zlib/infcodes.c new file mode 100644 index 0000000..d4e5ee9 --- /dev/null +++ b/Sources/Engine/zlib/infcodes.c @@ -0,0 +1,257 @@ +/* infcodes.c -- process literals and length/distance pairs + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + START, /* x: set up for LEN */ + LEN, /* i: get length/literal/eob next */ + LENEXT, /* i: getting length extra (have base) */ + DIST, /* i: get distance next */ + DISTEXT, /* i: getting distance extra */ + COPY, /* o: copying bytes in window, waiting for space */ + LIT, /* o: got literal, waiting for output space */ + WASH, /* o: got eob, possibly still output waiting */ + END, /* x: got eob and all data flushed */ + BADCODE} /* x: got error */ +inflate_codes_mode; + +/* inflate codes private state */ +struct inflate_codes_state { + + /* mode */ + inflate_codes_mode mode; /* current inflate_codes mode */ + + /* mode dependent information */ + uInt len; + union { + struct { + inflate_huft *tree; /* pointer into tree */ + uInt need; /* bits needed */ + } code; /* if LEN or DIST, where in tree */ + uInt lit; /* if LIT, literal */ + struct { + uInt get; /* bits to get for extra */ + uInt dist; /* distance back to copy from */ + } copy; /* if EXT or COPY, where and how much */ + } sub; /* submode */ + + /* mode independent information */ + Byte lbits; /* ltree bits decoded per branch */ + Byte dbits; /* dtree bits decoder per branch */ + inflate_huft *ltree; /* literal/length/eob tree */ + inflate_huft *dtree; /* distance tree */ + +}; + + +inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +z_streamp z; +{ + inflate_codes_statef *c; + + if ((c = (inflate_codes_statef *) + ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) + { + c->mode = START; + c->lbits = (Byte)bl; + c->dbits = (Byte)bd; + c->ltree = tl; + c->dtree = td; + Tracev((stderr, "inflate: codes new\n")); + } + return c; +} + + +int inflate_codes(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt j; /* temporary storage */ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + Bytef *f; /* pointer to copy strings from */ + inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input and output based on current state */ + while (1) switch (c->mode) + { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + case START: /* x: set up for LEN */ +#ifndef SLOW + if (m >= 258 && n >= 10) + { + UPDATE + r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); + LOAD + if (r != Z_OK) + { + c->mode = r == Z_STREAM_END ? WASH : BADCODE; + break; + } + } +#endif /* !SLOW */ + c->sub.code.need = c->lbits; + c->sub.code.tree = c->ltree; + c->mode = LEN; + case LEN: /* i: get length/literal/eob next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e == 0) /* literal */ + { + c->sub.lit = t->base; + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", t->base)); + c->mode = LIT; + break; + } + if (e & 16) /* length */ + { + c->sub.copy.get = e & 15; + c->len = t->base; + c->mode = LENEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + if (e & 32) /* end of block */ + { + Tracevv((stderr, "inflate: end of block\n")); + c->mode = WASH; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid literal/length code"; + r = Z_DATA_ERROR; + LEAVE + case LENEXT: /* i: getting length extra (have base) */ + j = c->sub.copy.get; + NEEDBITS(j) + c->len += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + c->sub.code.need = c->dbits; + c->sub.code.tree = c->dtree; + Tracevv((stderr, "inflate: length %u\n", c->len)); + c->mode = DIST; + case DIST: /* i: get distance next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e & 16) /* distance */ + { + c->sub.copy.get = e & 15; + c->sub.copy.dist = t->base; + c->mode = DISTEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid distance code"; + r = Z_DATA_ERROR; + LEAVE + case DISTEXT: /* i: getting distance extra */ + j = c->sub.copy.get; + NEEDBITS(j) + c->sub.copy.dist += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); + c->mode = COPY; + case COPY: /* o: copying bytes in window, waiting for space */ +#ifndef __TURBOC__ /* Turbo C bug for following expression */ + f = (uInt)(q - s->window) < c->sub.copy.dist ? + s->end - (c->sub.copy.dist - (q - s->window)) : + q - c->sub.copy.dist; +#else + f = q - c->sub.copy.dist; + if ((uInt)(q - s->window) < c->sub.copy.dist) + f = s->end - (c->sub.copy.dist - (uInt)(q - s->window)); +#endif + while (c->len) + { + NEEDOUT + OUTBYTE(*f++) + if (f == s->end) + f = s->window; + c->len--; + } + c->mode = START; + break; + case LIT: /* o: got literal, waiting for output space */ + NEEDOUT + OUTBYTE(c->sub.lit) + c->mode = START; + break; + case WASH: /* o: got eob, possibly more output */ + if (k > 7) /* return unused byte, if any */ + { + Assert(k < 16, "inflate_codes grabbed too many bytes") + k -= 8; + n++; + p--; /* can always return one */ + } + FLUSH + if (s->read != s->write) + LEAVE + c->mode = END; + case END: + r = Z_STREAM_END; + LEAVE + case BADCODE: /* x: got error */ + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +void inflate_codes_free(c, z) +inflate_codes_statef *c; +z_streamp z; +{ + ZFREE(z, c); + Tracev((stderr, "inflate: codes free\n")); +} diff --git a/Sources/Engine/zlib/infcodes.h b/Sources/Engine/zlib/infcodes.h new file mode 100644 index 0000000..6c750d8 --- /dev/null +++ b/Sources/Engine/zlib/infcodes.h @@ -0,0 +1,27 @@ +/* infcodes.h -- header to use infcodes.c + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_codes_state; +typedef struct inflate_codes_state FAR inflate_codes_statef; + +extern inflate_codes_statef *inflate_codes_new OF(( + uInt, uInt, + inflate_huft *, inflate_huft *, + z_streamp )); + +extern int inflate_codes OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +extern void inflate_codes_free OF(( + inflate_codes_statef *, + z_streamp )); + diff --git a/Sources/Engine/zlib/inffast.c b/Sources/Engine/zlib/inffast.c new file mode 100644 index 0000000..61a78ee --- /dev/null +++ b/Sources/Engine/zlib/inffast.c @@ -0,0 +1,170 @@ +/* inffast.c -- process literals and length/distance pairs fast + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* macros for bit input with no checking and for returning unused bytes */ +#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} + +/* Called with number of bytes left to write in window at least 258 + (the maximum string length) and number of input bytes available + at least ten. The ten bytes are six bytes for the longest length/ + distance pair plus four bytes for overloading the bit buffer. */ + +int inflate_fast(bl, bd, tl, td, s, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + uInt ml; /* mask for literal/length tree */ + uInt md; /* mask for distance tree */ + uInt c; /* bytes to copy */ + uInt d; /* distance back to copy from */ + Bytef *r; /* copy source pointer */ + + /* load input, output, bit values */ + LOAD + + /* initialize masks */ + ml = inflate_mask[bl]; + md = inflate_mask[bd]; + + /* do until not enough input or output space for fast loop */ + do { /* assume called with m >= 258 && n >= 10 */ + /* get literal/length code */ + GRABBITS(20) /* max bits for literal/length code */ + if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + continue; + } + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits for length */ + e &= 15; + c = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * length %u\n", c)); + + /* decode distance base of block to copy */ + GRABBITS(15); /* max bits for distance code */ + e = (t = td + ((uInt)b & md))->exop; + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits to add to distance base */ + e &= 15; + GRABBITS(e) /* get extra bits (up to 13) */ + d = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * distance %u\n", d)); + + /* do the copy */ + m -= c; + if ((uInt)(q - s->window) >= d) /* offset before dest */ + { /* just copy */ + r = q - d; + *q++ = *r++; c--; /* minimum count is three, */ + *q++ = *r++; c--; /* so unroll loop a little */ + } + else /* else offset after destination */ + { + e = d - (uInt)(q - s->window); /* bytes from offset to end */ + r = s->end - e; /* pointer to offset */ + if (c > e) /* if source crosses, */ + { + c -= e; /* copy to end of window */ + do { + *q++ = *r++; + } while (--e); + r = s->window; /* copy rest from start of window */ + } + } + do { /* copy all or what's left */ + *q++ = *r++; + } while (--c); + break; + } + else if ((e & 64) == 0) + { + t += t->base; + e = (t += ((uInt)b & inflate_mask[e]))->exop; + } + else + { + z->msg = (char*)"invalid distance code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + break; + } + if ((e & 64) == 0) + { + t += t->base; + if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + break; + } + } + else if (e & 32) + { + Tracevv((stderr, "inflate: * end of block\n")); + UNGRAB + UPDATE + return Z_STREAM_END; + } + else + { + z->msg = (char*)"invalid literal/length code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + } while (m >= 258 && n >= 10); + + /* not enough input or output--restore pointers and return */ + UNGRAB + UPDATE + return Z_OK; +} diff --git a/Sources/Engine/zlib/inffast.h b/Sources/Engine/zlib/inffast.h new file mode 100644 index 0000000..8facec5 --- /dev/null +++ b/Sources/Engine/zlib/inffast.h @@ -0,0 +1,17 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +extern int inflate_fast OF(( + uInt, + uInt, + inflate_huft *, + inflate_huft *, + inflate_blocks_statef *, + z_streamp )); diff --git a/Sources/Engine/zlib/inffixed.h b/Sources/Engine/zlib/inffixed.h new file mode 100644 index 0000000..77f7e76 --- /dev/null +++ b/Sources/Engine/zlib/inffixed.h @@ -0,0 +1,151 @@ +/* inffixed.h -- table for decoding fixed codes + * Generated automatically by the maketree.c program + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +local uInt fixed_bl = 9; +local uInt fixed_bd = 5; +local inflate_huft fixed_tl[] = { + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} + }; +local inflate_huft fixed_td[] = { + {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, + {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, + {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, + {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, + {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, + {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, + {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, + {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} + }; diff --git a/Sources/Engine/zlib/inflate.c b/Sources/Engine/zlib/inflate.c new file mode 100644 index 0000000..32e9b8d --- /dev/null +++ b/Sources/Engine/zlib/inflate.c @@ -0,0 +1,366 @@ +/* inflate.c -- zlib interface to inflate modules + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" + +struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ + +typedef enum { + METHOD, /* waiting for method byte */ + FLAG, /* waiting for flag byte */ + DICT4, /* four dictionary check bytes to go */ + DICT3, /* three dictionary check bytes to go */ + DICT2, /* two dictionary check bytes to go */ + DICT1, /* one dictionary check byte to go */ + DICT0, /* waiting for inflateSetDictionary */ + BLOCKS, /* decompressing blocks */ + CHECK4, /* four check bytes to go */ + CHECK3, /* three check bytes to go */ + CHECK2, /* two check bytes to go */ + CHECK1, /* one check byte to go */ + DONE, /* finished check, done */ + BAD} /* got an error--stay here */ +inflate_mode; + +/* inflate private state */ +struct internal_state { + + /* mode */ + inflate_mode mode; /* current inflate mode */ + + /* mode dependent information */ + union { + uInt method; /* if FLAGS, method byte */ + struct { + uLong was; /* computed check value */ + uLong need; /* stream check value */ + } check; /* if CHECK, check values to compare */ + uInt marker; /* if BAD, inflateSync's marker bytes count */ + } sub; /* submode */ + + /* mode independent information */ + int nowrap; /* flag for no wrapper */ + uInt wbits; /* log2(window size) (8..15, defaults to 15) */ + inflate_blocks_statef + *blocks; /* current inflate_blocks state */ + +}; + + +int ZEXPORT inflateReset(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + z->total_in = z->total_out = 0; + z->msg = Z_NULL; + z->state->mode = z->state->nowrap ? BLOCKS : METHOD; + inflate_blocks_reset(z->state->blocks, z, Z_NULL); + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + + +int ZEXPORT inflateEnd(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->blocks != Z_NULL) + inflate_blocks_free(z->state->blocks, z); + ZFREE(z, z->state); + z->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + + +int ZEXPORT inflateInit2_(z, w, version, stream_size) +z_streamp z; +int w; +const char *version; +int stream_size; +{ + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != sizeof(z_stream)) + return Z_VERSION_ERROR; + + /* initialize state */ + if (z == Z_NULL) + return Z_STREAM_ERROR; + z->msg = Z_NULL; + if (z->zalloc == Z_NULL) + { + z->zalloc = zcalloc; + z->opaque = (voidpf)0; + } + if (z->zfree == Z_NULL) z->zfree = zcfree; + if ((z->state = (struct internal_state FAR *) + ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) + return Z_MEM_ERROR; + z->state->blocks = Z_NULL; + + /* handle undocumented nowrap option (no zlib header or check) */ + z->state->nowrap = 0; + if (w < 0) + { + w = - w; + z->state->nowrap = 1; + } + + /* set window size */ + if (w < 8 || w > 15) + { + inflateEnd(z); + return Z_STREAM_ERROR; + } + z->state->wbits = (uInt)w; + + /* create inflate_blocks state */ + if ((z->state->blocks = + inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) + == Z_NULL) + { + inflateEnd(z); + return Z_MEM_ERROR; + } + Tracev((stderr, "inflate: allocated\n")); + + /* reset state */ + inflateReset(z); + return Z_OK; +} + + +int ZEXPORT inflateInit_(z, version, stream_size) +z_streamp z; +const char *version; +int stream_size; +{ + return inflateInit2_(z, DEF_WBITS, version, stream_size); +} + + +#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} +#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) + +int ZEXPORT inflate(z, f) +z_streamp z; +int f; +{ + int r; + uInt b; + + if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) + return Z_STREAM_ERROR; + f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; + r = Z_BUF_ERROR; + while (1) switch (z->state->mode) + { + case METHOD: + NEEDBYTE + if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) + { + z->state->mode = BAD; + z->msg = (char*)"unknown compression method"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + if ((z->state->sub.method >> 4) + 8 > z->state->wbits) + { + z->state->mode = BAD; + z->msg = (char*)"invalid window size"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + z->state->mode = FLAG; + case FLAG: + NEEDBYTE + b = NEXTBYTE; + if (((z->state->sub.method << 8) + b) % 31) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect header check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + if (!(b & PRESET_DICT)) + { + z->state->mode = BLOCKS; + break; + } + z->state->mode = DICT4; + case DICT4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = DICT3; + case DICT3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = DICT2; + case DICT2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = DICT1; + case DICT1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + z->adler = z->state->sub.check.need; + z->state->mode = DICT0; + return Z_NEED_DICT; + case DICT0: + z->state->mode = BAD; + z->msg = (char*)"need dictionary"; + z->state->sub.marker = 0; /* can try inflateSync */ + return Z_STREAM_ERROR; + case BLOCKS: + r = inflate_blocks(z->state->blocks, z, r); + if (r == Z_DATA_ERROR) + { + z->state->mode = BAD; + z->state->sub.marker = 0; /* can try inflateSync */ + break; + } + if (r == Z_OK) + r = f; + if (r != Z_STREAM_END) + return r; + r = f; + inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); + if (z->state->nowrap) + { + z->state->mode = DONE; + break; + } + z->state->mode = CHECK4; + case CHECK4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = CHECK3; + case CHECK3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = CHECK2; + case CHECK2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = CHECK1; + case CHECK1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + + if (z->state->sub.check.was != z->state->sub.check.need) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect data check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib check ok\n")); + z->state->mode = DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + default: + return Z_STREAM_ERROR; + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) +z_streamp z; +const Bytef *dictionary; +uInt dictLength; +{ + uInt length = dictLength; + + if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) + return Z_STREAM_ERROR; + + if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; + z->adler = 1L; + + if (length >= ((uInt)1<state->wbits)) + { + length = (1<state->wbits)-1; + dictionary += dictLength - length; + } + inflate_set_dictionary(z->state->blocks, dictionary, length); + z->state->mode = BLOCKS; + return Z_OK; +} + + +int ZEXPORT inflateSync(z) +z_streamp z; +{ + uInt n; /* number of bytes to look at */ + Bytef *p; /* pointer to bytes */ + uInt m; /* number of marker bytes found in a row */ + uLong r, w; /* temporaries to save total_in and total_out */ + + /* set up */ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->mode != BAD) + { + z->state->mode = BAD; + z->state->sub.marker = 0; + } + if ((n = z->avail_in) == 0) + return Z_BUF_ERROR; + p = z->next_in; + m = z->state->sub.marker; + + /* search */ + while (n && m < 4) + { + static const Byte mark[4] = {0, 0, 0xff, 0xff}; + if (*p == mark[m]) + m++; + else if (*p) + m = 0; + else + m = 4 - m; + p++, n--; + } + + /* restore */ + z->total_in += p - z->next_in; + z->next_in = p; + z->avail_in = n; + z->state->sub.marker = m; + + /* return no joy or set up to restart on a new block */ + if (m != 4) + return Z_DATA_ERROR; + r = z->total_in; w = z->total_out; + inflateReset(z); + z->total_in = r; z->total_out = w; + z->state->mode = BLOCKS; + return Z_OK; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH + * but removes the length bytes of the resulting empty stored block. When + * decompressing, PPP checks that at the end of input packet, inflate is + * waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) + return Z_STREAM_ERROR; + return inflate_blocks_sync_point(z->state->blocks); +} diff --git a/Sources/Engine/zlib/inftrees.c b/Sources/Engine/zlib/inftrees.c new file mode 100644 index 0000000..ef1e0b6 --- /dev/null +++ b/Sources/Engine/zlib/inftrees.c @@ -0,0 +1,455 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#if !defined(BUILDFIXED) && !defined(STDC) +# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ +#endif + +const char inflate_copyright[] = + " inflate 1.1.3 Copyright 1995-1998 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ +struct internal_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + + +local int huft_build OF(( + uIntf *, /* code lengths in bits */ + uInt, /* number of codes */ + uInt, /* number of "simple" codes */ + const uIntf *, /* list of base values for non-simple codes */ + const uIntf *, /* list of extra bits for non-simple codes */ + inflate_huft * FAR*,/* result: starting table */ + uIntf *, /* maximum lookup bits (returns actual) */ + inflate_huft *, /* space for trees */ + uInt *, /* hufts used in space */ + uIntf * )); /* space for values */ + +/* Tables for deflate from PKZIP's appnote.txt. */ +local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* see note #13 above about 258 */ +local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ +local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +local const uInt cpdext[30] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ +#define BMAX 15 /* maximum bit length of any code */ + +local int huft_build(b, n, s, d, e, t, m, hp, hn, v) +uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ +uInt n; /* number of codes (assumed <= 288) */ +uInt s; /* number of simple-valued codes (0..s-1) */ +const uIntf *d; /* list of base values for non-simple codes */ +const uIntf *e; /* list of extra bits for non-simple codes */ +inflate_huft * FAR *t; /* result: starting table */ +uIntf *m; /* maximum lookup bits, returns actual */ +inflate_huft *hp; /* space for trees */ +uInt *hn; /* hufts used in space */ +uIntf *v; /* working area: values in order of bit length */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + if the given code set is incomplete (the tables are still built in this + case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of + lengths), or Z_MEM_ERROR if not enough memory. */ +{ + + uInt a; /* counter for codes of length k */ + uInt c[BMAX+1]; /* bit length count table */ + uInt f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register uInt i; /* counter, current code */ + register uInt j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ + register uIntf *p; /* pointer into c[], b[], or v[] */ + inflate_huft *q; /* points to current table */ + struct inflate_huft_s r; /* table entry for structure assignment */ + inflate_huft *u[BMAX]; /* table stack */ + register int w; /* bits before this table == (l * h) */ + uInt x[BMAX+1]; /* bit offsets, then code stack */ + uIntf *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + uInt z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + p = c; +#define C0 *p++ = 0; +#define C2 C0 C0 C0 C0 +#define C4 C2 C2 C2 C2 + C4 /* clear c[]--assume BMAX+1 is 16 */ + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (inflate_huft *)Z_NULL; + *m = 0; + return Z_OK; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((uInt)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((uInt)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return Z_DATA_ERROR; + if ((y -= c[i]) < 0) + return Z_DATA_ERROR; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + n = x[g]; /* set n to length of v */ + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ + q = (inflate_huft *)Z_NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = g - w; + z = z > (uInt)l ? l : z; /* table size upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + if (j < z) + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate new table */ + if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ + return Z_MEM_ERROR; /* not enough memory */ + u[h] = q = hp + *hn; + *hn += z; + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.bits = (Byte)l; /* bits to dump before this table */ + r.exop = (Byte)j; /* bits in this table */ + j = i >> (w - l); + r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ + u[h-1][j] = r; /* connect to last table */ + } + else + *t = q; /* first table is returned result */ + } + + /* set up table entry in r */ + r.bits = (Byte)(k - w); + if (p >= v + n) + r.exop = 128 + 64; /* out of values--invalid code */ + else if (*p < s) + { + r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ + r.base = *p++; /* simple code is just the value */ + } + else + { + r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ + r.base = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + mask = (1 << w) - 1; /* needed on HP, cc -O bug */ + while ((i & mask) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + mask = (1 << w) - 1; + } + } + } + + + /* Return Z_BUF_ERROR if we were given an incomplete table */ + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; +} + + +int inflate_trees_bits(c, bb, tb, hp, z) +uIntf *c; /* 19 code lengths */ +uIntf *bb; /* bits tree desired/actual depth */ +inflate_huft * FAR *tb; /* bits tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, + tb, bb, hp, &hn, v); + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed dynamic bit lengths tree"; + else if (r == Z_BUF_ERROR || *bb == 0) + { + z->msg = (char*)"incomplete dynamic bit lengths tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +} + + +int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) +uInt nl; /* number of literal/length codes */ +uInt nd; /* number of distance codes */ +uIntf *c; /* that many (total) code lengths */ +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + /* allocate work area */ + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + + /* build literal/length tree */ + r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); + if (r != Z_OK || *bl == 0) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed literal/length tree"; + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"incomplete literal/length tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; + } + + /* build distance tree */ + r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); + if (r != Z_OK || (*bd == 0 && nl > 257)) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed distance tree"; + else if (r == Z_BUF_ERROR) { +#ifdef PKZIP_BUG_WORKAROUND + r = Z_OK; + } +#else + z->msg = (char*)"incomplete distance tree"; + r = Z_DATA_ERROR; + } + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"empty distance tree with lengths"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +#endif + } + + /* done */ + ZFREE(z, v); + return Z_OK; +} + + +/* build fixed tables only once--keep them here */ +#ifdef BUILDFIXED +local int fixed_built = 0; +#define FIXEDH 544 /* number of hufts used by fixed tables */ +local inflate_huft fixed_mem[FIXEDH]; +local uInt fixed_bl; +local uInt fixed_bd; +local inflate_huft *fixed_tl; +local inflate_huft *fixed_td; +#else +#include "inffixed.h" +#endif + + +int inflate_trees_fixed(bl, bd, tl, td, z) +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +z_streamp z; /* for memory allocation */ +{ +#ifdef BUILDFIXED + /* build fixed tables if not already */ + if (!fixed_built) + { + int k; /* temporary variable */ + uInt f = 0; /* number of hufts used in fixed_mem */ + uIntf *c; /* length list for huft_build */ + uIntf *v; /* work area for huft_build */ + + /* allocate memory */ + if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + { + ZFREE(z, c); + return Z_MEM_ERROR; + } + + /* literal table */ + for (k = 0; k < 144; k++) + c[k] = 8; + for (; k < 256; k++) + c[k] = 9; + for (; k < 280; k++) + c[k] = 7; + for (; k < 288; k++) + c[k] = 8; + fixed_bl = 9; + huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, + fixed_mem, &f, v); + + /* distance table */ + for (k = 0; k < 30; k++) + c[k] = 5; + fixed_bd = 5; + huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, + fixed_mem, &f, v); + + /* done */ + ZFREE(z, v); + ZFREE(z, c); + fixed_built = 1; + } +#endif + *bl = fixed_bl; + *bd = fixed_bd; + *tl = fixed_tl; + *td = fixed_td; + return Z_OK; +} diff --git a/Sources/Engine/zlib/inftrees.h b/Sources/Engine/zlib/inftrees.h new file mode 100644 index 0000000..85853e0 --- /dev/null +++ b/Sources/Engine/zlib/inftrees.h @@ -0,0 +1,58 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). */ + +typedef struct inflate_huft_s FAR inflate_huft; + +struct inflate_huft_s { + union { + struct { + Byte Exop; /* number of extra bits or operation */ + Byte Bits; /* number of bits in this code or subcode */ + } what; + uInt pad; /* pad structure to a power of 2 (4 bytes for */ + } word; /* 16-bit, 8 bytes for 32-bit int's) */ + uInt base; /* literal, length base, distance base, + or table offset */ +}; + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 huft structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The actual maximum is not known, but the + value below is more than safe. */ +#define MANY 1440 + +extern int inflate_trees_bits OF(( + uIntf *, /* 19 code lengths */ + uIntf *, /* bits tree desired/actual depth */ + inflate_huft * FAR *, /* bits tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_dynamic OF(( + uInt, /* number of literal/length codes */ + uInt, /* number of distance codes */ + uIntf *, /* that many (total) code lengths */ + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_fixed OF(( + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + z_streamp)); /* for memory allocation */ diff --git a/Sources/Engine/zlib/infutil.c b/Sources/Engine/zlib/infutil.c new file mode 100644 index 0000000..824dab5 --- /dev/null +++ b/Sources/Engine/zlib/infutil.c @@ -0,0 +1,87 @@ +/* inflate_util.c -- data and routines common to blocks and codes + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* And'ing with mask[n] masks the lower n bits */ +uInt inflate_mask[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + + +/* copy as much as possible from the sliding window to the output area */ +int inflate_flush(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt n; + Bytef *p; + Bytef *q; + + /* local copies of source and destination pointers */ + p = z->next_out; + q = s->read; + + /* compute number of bytes to copy as far as end of window */ + n = (uInt)((q <= s->write ? s->write : s->end) - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy as far as end of window */ + zmemcpy(p, q, n); + p += n; + q += n; + + /* see if more to copy at beginning of window */ + if (q == s->end) + { + /* wrap pointers */ + q = s->window; + if (s->write == s->end) + s->write = s->window; + + /* compute bytes to copy */ + n = (uInt)(s->write - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy */ + zmemcpy(p, q, n); + p += n; + q += n; + } + + /* update pointers */ + z->next_out = p; + s->read = q; + + /* done */ + return r; +} diff --git a/Sources/Engine/zlib/infutil.h b/Sources/Engine/zlib/infutil.h new file mode 100644 index 0000000..99d1135 --- /dev/null +++ b/Sources/Engine/zlib/infutil.h @@ -0,0 +1,98 @@ +/* infutil.h -- types and macros common to blocks and codes + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#ifndef _INFUTIL_H +#define _INFUTIL_H + +typedef enum { + TYPE, /* get type bits (3, including end bit) */ + LENS, /* get lengths for stored */ + STORED, /* processing stored block */ + TABLE, /* get table lengths */ + BTREE, /* get bit lengths tree for a dynamic block */ + DTREE, /* get length, distance trees for a dynamic block */ + CODES, /* processing fixed or dynamic block */ + DRY, /* output remaining window bytes */ + DONE, /* finished last block, done */ + BAD} /* got a data error--stuck here */ +inflate_block_mode; + +/* inflate blocks semi-private state */ +struct inflate_blocks_state { + + /* mode */ + inflate_block_mode mode; /* current inflate_block mode */ + + /* mode dependent information */ + union { + uInt left; /* if STORED, bytes left to copy */ + struct { + uInt table; /* table lengths (14 bits) */ + uInt index; /* index into blens (or border) */ + uIntf *blens; /* bit lengths of codes */ + uInt bb; /* bit length tree depth */ + inflate_huft *tb; /* bit length decoding tree */ + } trees; /* if DTREE, decoding info for trees */ + struct { + inflate_codes_statef + *codes; + } decode; /* if CODES, current state */ + } sub; /* submode */ + uInt last; /* true if this block is the last block */ + + /* mode independent information */ + uInt bitk; /* bits in bit buffer */ + uLong bitb; /* bit buffer */ + inflate_huft *hufts; /* single malloc for tree space */ + Bytef *window; /* sliding window */ + Bytef *end; /* one byte after sliding window */ + Bytef *read; /* window read pointer */ + Bytef *write; /* window write pointer */ + check_func checkfn; /* check function */ + uLong check; /* check on output */ + +}; + + +/* defines for inflate input/output */ +/* update pointers and return */ +#define UPDBITS {s->bitb=b;s->bitk=k;} +#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} +#define UPDOUT {s->write=q;} +#define UPDATE {UPDBITS UPDIN UPDOUT} +#define LEAVE {UPDATE return inflate_flush(s,z,r);} +/* get bytes and bits */ +#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} +#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} +#define NEXTBYTE (n--,*p++) +#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} +/* output bytes */ +#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) +#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} +#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} +#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} +#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} +#define OUTBYTE(a) {*q++=(Byte)(a);m--;} +/* load local pointers */ +#define LOAD {LOADIN LOADOUT} + +/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ +extern uInt inflate_mask[17]; + +/* copy as much as possible from the sliding window to the output area */ +extern int inflate_flush OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#endif diff --git a/Sources/Engine/zlib/trees.c b/Sources/Engine/zlib/trees.c new file mode 100644 index 0000000..f01fb30 --- /dev/null +++ b/Sources/Engine/zlib/trees.c @@ -0,0 +1,1214 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-1998 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id$ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +#define MAX(a,b) (a >= b ? a : b) +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute first the block length in bytes*/ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/Sources/Engine/zlib/trees.h b/Sources/Engine/zlib/trees.h new file mode 100644 index 0000000..72facf9 --- /dev/null +++ b/Sources/Engine/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/Sources/Engine/zlib/uncompr.c b/Sources/Engine/zlib/uncompr.c new file mode 100644 index 0000000..d103321 --- /dev/null +++ b/Sources/Engine/zlib/uncompr.c @@ -0,0 +1,58 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/Sources/Engine/zlib/zconf.h b/Sources/Engine/zlib/zconf.h new file mode 100644 index 0000000..6d450fc --- /dev/null +++ b/Sources/Engine/zlib/zconf.h @@ -0,0 +1,279 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include +# define ZEXPORT __declspec(dllexport) WINAPI +# define ZEXPORTRVA __declspec(dllexport) WINAPIV +# else +# if defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# endif +# endif +# endif +#endif + +#if defined (__BEOS__) +# if defined (ZLIB_DLL) +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(MACOS) && !defined(TARGET_OS_MAC) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#endif /* _ZCONF_H */ diff --git a/Sources/Engine/zlib/zlib.h b/Sources/Engine/zlib/zlib.h new file mode 100644 index 0000000..49f56b4 --- /dev/null +++ b/Sources/Engine/zlib/zlib.h @@ -0,0 +1,893 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.3, July 9th, 1998 + + Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.1.3" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + const voidp buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/Sources/Engine/zlib/zutil.c b/Sources/Engine/zlib/zutil.c new file mode 100644 index 0000000..b3de4e8 --- /dev/null +++ b/Sources/Engine/zlib/zutil.c @@ -0,0 +1,225 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char *z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifdef __TURBOC__ +#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) +/* Small and medium model in Turbo C are for now limited to near allocation + * with reduced MAX_WBITS and MAX_MEM_LEVEL + */ +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} +#endif +#endif /* __TURBOC__ */ + + +#if defined(M_I86) && !defined(__32BIT__) +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* MSC */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/Sources/Engine/zlib/zutil.h b/Sources/Engine/zlib/zutil.h new file mode 100644 index 0000000..6f2cb97 --- /dev/null +++ b/Sources/Engine/zlib/zutil.h @@ -0,0 +1,220 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-1998 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#ifdef MSDOS +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#ifdef WIN32 /* Window 95 & Windows NT */ +# define OS_CODE 0x0b +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0F +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# define fdopen(fd,type) _fdopen(fd,type) +#endif + + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, + uInt len)); +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* _Z_UTIL_H */ diff --git a/Sources/EngineGui/DlgChooseTextureType.cpp b/Sources/EngineGui/DlgChooseTextureType.cpp new file mode 100644 index 0000000..16a322e --- /dev/null +++ b/Sources/EngineGui/DlgChooseTextureType.cpp @@ -0,0 +1,67 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgChooseTextureType.cpp : implementation file +// + +#include "StdH.h" +#include "DlgChooseTextureType.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgChooseTextureType dialog + + +CDlgChooseTextureType::CDlgChooseTextureType(CWnd* pParent /*=NULL*/) + : CDialog(CDlgChooseTextureType::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgChooseTextureType) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CDlgChooseTextureType::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDlgChooseTextureType) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDlgChooseTextureType, CDialog) + //{{AFX_MSG_MAP(CDlgChooseTextureType) + ON_BN_CLICKED(ID_ANIMATED_TEXTURE, OnAnimatedTexture) + ON_BN_CLICKED(ID_EFFECT_TEXTURE, OnEffectTexture) + ON_BN_CLICKED(ID_NORMAL_TEXTURE, OnNormalTexture) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgChooseTextureType message handlers + +void CDlgChooseTextureType::OnNormalTexture() +{ + EndDialog( 0); +} + +void CDlgChooseTextureType::OnAnimatedTexture() +{ + EndDialog( 1); +} + +void CDlgChooseTextureType::OnEffectTexture() +{ + EndDialog( 2); +} + +void CDlgChooseTextureType::OnCancel() +{ + EndDialog( -1); +} diff --git a/Sources/EngineGui/DlgChooseTextureType.h b/Sources/EngineGui/DlgChooseTextureType.h new file mode 100644 index 0000000..0a19b95 --- /dev/null +++ b/Sources/EngineGui/DlgChooseTextureType.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#if !defined(AFX_DLGCHOOSETEXTURETYPE_H__C517CED1_FA6C_11D1_82E9_000000000000__INCLUDED_) +#define AFX_DLGCHOOSETEXTURETYPE_H__C517CED1_FA6C_11D1_82E9_000000000000__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// DlgChooseTextureType.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgChooseTextureType dialog + +class CDlgChooseTextureType : public CDialog +{ +// Construction +public: + CDlgChooseTextureType(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDlgChooseTextureType) + enum { IDD = IDD_CHOOSE_TEXTURE_TYPE }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgChooseTextureType) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgChooseTextureType) + afx_msg void OnAnimatedTexture(); + afx_msg void OnEffectTexture(); + afx_msg void OnNormalTexture(); + virtual void OnCancel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGCHOOSETEXTURETYPE_H__C517CED1_FA6C_11D1_82E9_000000000000__INCLUDED_) diff --git a/Sources/EngineGui/DlgCreateAnimatedTexture.cpp b/Sources/EngineGui/DlgCreateAnimatedTexture.cpp new file mode 100644 index 0000000..6c87607 --- /dev/null +++ b/Sources/EngineGui/DlgCreateAnimatedTexture.cpp @@ -0,0 +1,375 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgCreateAnimatedTexture.cpp : implementation file +// + +#include "StdH.h" +#include "DlgCreateAnimatedTexture.h" +#include + + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgCreateAnimatedTexture dialog + + +#define TEMPORARY_SCRIPT_NAME "Temp\\Temp.scr" +#define TEMPORARY_TEXTURE_NAME "Temp\\Temp.tex" + + +void CDlgCreateAnimatedTexture::ReleaseCreatedTexture(void) +{ + // if there is texture obtained, release it + if( m_ptdCreated!= NULL) + { + // free obtained texture + _pTextureStock->Release( m_ptdCreated); + m_ptdCreated = NULL; + m_wndViewCreatedTexture.m_toTexture.SetData( NULL); + } +} + +void CDlgCreateAnimatedTexture::InitAnimationsCombo(void) +{ + m_ctrlAnimationsCombo.ResetContent(); + if( m_ptdCreated != NULL) + { + CAnimInfo aiInfo; + for( INDEX iAnim=0; iAnimGetAnimsCt(); iAnim++) + { + m_ptdCreated->GetAnimInfo( iAnim, aiInfo); + m_ctrlAnimationsCombo.AddString(CString(aiInfo.ai_AnimName)); + } + } + else + { + m_ctrlAnimationsCombo.AddString( L"None"); + } + m_ctrlAnimationsCombo.SetCurSel( 0); +} + +void CDlgCreateAnimatedTexture::OnSelchangeTextureAnimations() +{ + if( m_ptdCreated != NULL) + { + // set selected animation + INDEX iAnim = m_ctrlAnimationsCombo.GetCurSel(); + m_wndViewCreatedTexture.m_toTexture.SetAnim( iAnim); + } +} + +void CDlgCreateAnimatedTexture::RefreshTexture(void) +{ + // refresh script string from edit control + UpdateData( TRUE); + // prepare names for temporary script and texture + CTFileName fnTempScript = CTString(TEMPORARY_SCRIPT_NAME); + CTFileName fnTemptexture = CTString(TEMPORARY_TEXTURE_NAME); + try + { + // write context of edit ctrl to temporary script file + CTFileStream fileScript; + fileScript.Create_t( fnTempScript); + CTString strEditScript = CStringA(m_strEditScript); + char *pScript = (char *) AllocMemory( strlen(strEditScript)+1); + strcpy( pScript, strEditScript); + fileScript.WriteRawChunk_t( pScript, strlen(strEditScript)+1); + fileScript.Close(); + FreeMemory( pScript); + + // process script + ProcessScript_t( fnTempScript); + + // release old texture if it exists and obtain new texture + ReleaseCreatedTexture(); + // obtain newly created texture + m_ptdCreated = _pTextureStock->Obtain_t( fnTemptexture); + m_ptdCreated->Reload(); + // set texture data to texture preview window so it could display texture + m_wndViewCreatedTexture.m_toTexture.SetData( m_ptdCreated); + + char achrSize[64]; + sprintf( achrSize, "%d x %d", + m_ptdCreated->td_mexWidth>>m_ptdCreated->td_iFirstMipLevel, + m_ptdCreated->td_mexHeight>>m_ptdCreated->td_iFirstMipLevel); + m_strSizeInPixels = achrSize; + UpdateData( FALSE); + + // init animations combo + InitAnimationsCombo(); + } + catch(char *err_str) + { + AfxMessageBox( CString(err_str)); + } +} + +CDlgCreateAnimatedTexture::CDlgCreateAnimatedTexture( + CDynamicArray &afnPictures, CWnd* pParent /*=NULL*/) + : CDialog(CDlgCreateAnimatedTexture::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgCreateAnimatedTexture) + m_strEditScript = _T(""); + m_strSizeInPixels = _T(""); + m_strCreatedTextureName = _T(""); + //}}AFX_DATA_INIT + + // remember array of selected frames + m_pafnPictures = &afnPictures; + // set first frame as input file name + afnPictures.Lock(); + CTFileName fnInputFile = afnPictures[0]; + afnPictures.Unlock(); + + if( (fnInputFile != "") && + ((fnInputFile.FileExt() == ".tex") || (fnInputFile.FileExt() == ".scr")) ) + { + m_strCreatedTextureName = fnInputFile.FileDir() + fnInputFile.FileName() + ".tex"; + } + else + { + m_strCreatedTextureName = "Unnamed"; + } + + m_bPreviewWindowsCreated = FALSE; + m_ptdCreated = NULL; + m_pixSourceWidth = -1; + m_pixSourceHeight = -1; + + // remember source and destination file names + m_fnSourceFileName = fnInputFile; + m_fnCreatedFileName = fnInputFile.FileDir()+fnInputFile.FileName()+".tex"; +} + +CDlgCreateAnimatedTexture::~CDlgCreateAnimatedTexture() +{ + ReleaseCreatedTexture(); +} + +void CDlgCreateAnimatedTexture::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + + // if dialog is recieving data + if(pDX->m_bSaveAndValidate == FALSE) + { + } + + //{{AFX_DATA_MAP(CDlgCreateAnimatedTexture) + DDX_Control(pDX, IDC_CHEQUERED_ALPHA, m_ctrlCheckButton); + DDX_Control(pDX, IDC_TEXTURE_ANIMATIONS, m_ctrlAnimationsCombo); + DDX_Text(pDX, IDC_EDIT_SCRIPT, m_strEditScript); + DDX_Text(pDX, IDC_SIZE_IN_PIXELS, m_strSizeInPixels); + DDX_Text(pDX, IDC_TEXTURE_NAME, m_strCreatedTextureName); + //}}AFX_DATA_MAP + + // if dialog is giving data + if(pDX->m_bSaveAndValidate != FALSE) + { + } +} + + +BEGIN_MESSAGE_MAP(CDlgCreateAnimatedTexture, CDialog) + //{{AFX_MSG_MAP(CDlgCreateAnimatedTexture) + ON_WM_PAINT() + ON_BN_CLICKED(IDC_CHEQUERED_ALPHA, OnChequeredAlpha) + ON_BN_CLICKED(ID_CREATE_TEXTURE, OnCreateTexture) + ON_BN_CLICKED(ID_REFRESH_TEXTURE, OnRefreshTexture) + ON_CBN_SELCHANGE(IDC_TEXTURE_ANIMATIONS, OnSelchangeTextureAnimations) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgCreateAnimatedTexture message handlers + +void CDlgCreateAnimatedTexture::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + // if texture preview windows are not yet created + if( !m_bPreviewWindowsCreated) + { + // ---------------- Create custom window that will show how created texture will look like + CWnd *pWndCreatedTexturePreview = GetDlgItem(IDC_TEXTURE_PREVIEW_WINDOW); + ASSERT(pWndCreatedTexturePreview != NULL); + CRect rectPreviewCreatedTextureWnd; + // get rectangle occupied by preview texture window + pWndCreatedTexturePreview->GetWindowRect( &rectPreviewCreatedTextureWnd); + ScreenToClient( &rectPreviewCreatedTextureWnd); + // create window for for showing created texture + m_wndViewCreatedTexture.Create( NULL, NULL, WS_BORDER|WS_VISIBLE, rectPreviewCreatedTextureWnd, + this, IDW_VIEW_CREATED_TEXTURE); + // mark that custom windows are created + m_bPreviewWindowsCreated = TRUE; + } +} + +void CDlgCreateAnimatedTexture::OnChequeredAlpha() +{ + // toggle chequered alpha on/off + m_wndViewCreatedTexture.m_bChequeredAlpha = !m_wndViewCreatedTexture.m_bChequeredAlpha; +} + + +void CDlgCreateAnimatedTexture::OnRefreshTexture() +{ + RefreshTexture(); +} + +void CDlgCreateAnimatedTexture::OnCreateTexture() +{ + // refresh (recreate) texture in temporary directory + RefreshTexture(); + // prepare names for temporary script and texture + CTFileName fnFullTempTexture = _fnmApplicationPath+CTString(TEMPORARY_TEXTURE_NAME); + CTFileName fnFullTempScript = _fnmApplicationPath+CTString(TEMPORARY_SCRIPT_NAME); + // and for supposed final texture name + CTFileName fnFullFinalTexture = _fnmApplicationPath+m_fnCreatedFileName; + + CTFileName fnSaveName; + if( m_strCreatedTextureName == "Unnamed") + { + // extract last sub directory name + char achrLastSubDir[ 256]; + strcpy( achrLastSubDir, m_fnSourceFileName.FileDir()); + achrLastSubDir[ strlen(achrLastSubDir)-1]=0; // remove last '\' + CTString strLastSubDir = CTFileName(CTString(achrLastSubDir)).FileName(); + + // call save texture requester + fnSaveName = _EngineGUI.BrowseTexture( + strLastSubDir+".tex", // default name + KEY_NAME_CREATE_ANIMATED_TEXTURE_DIR, "Choose texture name", + FALSE/* bOpenFileRequester*/); + if( fnSaveName == "") return; + } + else + { + fnSaveName = CTString( CStringA(m_strCreatedTextureName)); + } + + // set newly picked names for final script and texture + fnFullFinalTexture = _fnmApplicationPath+fnSaveName; + CTFileName fnFullFinalScript = + fnFullFinalTexture.FileDir()+fnFullFinalTexture.FileName()+".scr"; + // copy temporary script and texture files into real their place + CopyFileA( fnFullTempScript, fnFullFinalScript, FALSE); + CopyFileA( fnFullTempTexture, fnFullFinalTexture, FALSE); + m_fnCreatedFileName =fnSaveName; + // end dialog + EndDialog( IDOK); +} + +BOOL CDlgCreateAnimatedTexture::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // if we received script as input + if( m_fnSourceFileName.FileExt() == ".scr") + { + // load script file into edit control + try + { + CTFileStream fileScript; + fileScript.Open_t( m_fnSourceFileName); + // get size of script file + ULONG ulScriptFileSize = fileScript.GetStreamSize(); + char *pchrFile = new char[ ulScriptFileSize+1]; + // set eol character + pchrFile[ ulScriptFileSize] = 0; + fileScript.Read_t( pchrFile, ulScriptFileSize); + // copy script to edit ctrl + m_strEditScript = CTString( pchrFile); + delete pchrFile; + } + // catch errors + catch( char *strError) + { + // and do nothing + (void) strError; + } + } + // we will create temporary script + else + { + try + { + // if can't get picture file information + CImageInfo iiImageInfo; + if (iiImageInfo.GetGfxFileInfo_t(m_fnSourceFileName)==UNSUPPORTED_FILE) + { + // throw error + ThrowF_t("File '%s' has unsupported file format", + (CTString&)(_fnmApplicationPath+m_fnSourceFileName)); + } + // get dimensions + m_pixSourceWidth = iiImageInfo.ii_Width; + m_pixSourceHeight = iiImageInfo.ii_Height; + } + catch(char *err_str) + { + AfxMessageBox( CString(err_str)); + } + + // allocate 16k for script + char achrDefaultScript[ 16384]; + // default script into edit control + sprintf( achrDefaultScript, + ";* Texture description\r\n" + "TEXTURE_WIDTH %.4f\r\n" + "TEXTURE_MIPMAPS 8\r\n" + "ANIM_START\r\n" + "DIRECTORY %s\r\n\r\n" + ";* Animations\r\n" + "ANIMATION Default_Animation\r\n" + "SPEED 0.1\r\n" + "FRAMES %d\r\n", + METERS_MEX(m_pixSourceWidth * (1 << 5) ), + (CTString&)m_fnCreatedFileName.FileDir(), + m_pafnPictures->Count()); + // add name for each frame + FOREACHINDYNAMICARRAY( *m_pafnPictures, CTFileName, itPicture) + { + CTFileName &fn=*itPicture; + CTString strName=fn.FileName(); + CTString strExt=fn.FileExt(); + // add finishing part of script + sprintf( achrDefaultScript, "%s %s%s\r\n", achrDefaultScript, strName, strExt); + } + // add finishing part of script + sprintf( achrDefaultScript, "%sANIM_END\r\nEND\r\n", achrDefaultScript); + // copy default script into edit ctrl + m_strEditScript = achrDefaultScript; + } + + CTFileName fnTexFileName = m_fnSourceFileName.FileDir() + m_fnSourceFileName.FileName() + ".tex"; + // try to + try + { + // obtain texture with the same name (if exists) + CTextureData *pTD = _pTextureStock->Obtain_t( fnTexFileName); + pTD->Reload(); + // release texture + _pTextureStock->Release( pTD); + } + // if texture can't be obtained + catch( char *err_str) + { + // never mind + (void) err_str; + } + + m_ctrlCheckButton.SetCheck( 1); + + // force edit script control to pick up default script string + UpdateData( FALSE); + // and refresh (recreate) texture in temporary directory + RefreshTexture(); + return TRUE; +} diff --git a/Sources/EngineGui/DlgCreateAnimatedTexture.h b/Sources/EngineGui/DlgCreateAnimatedTexture.h new file mode 100644 index 0000000..41cd2f1 --- /dev/null +++ b/Sources/EngineGui/DlgCreateAnimatedTexture.h @@ -0,0 +1,73 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#if !defined(AFX_DLGCREATEANIMATEDTEXTURE_H__C517CED3_FA6C_11D1_82E9_000000000000__INCLUDED_) +#define AFX_DLGCREATEANIMATEDTEXTURE_H__C517CED3_FA6C_11D1_82E9_000000000000__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// DlgCreateAnimatedTexture.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgCreateAnimatedTexture dialog + +class CDlgCreateAnimatedTexture : public CDialog +{ +// Construction +public: + CDlgCreateAnimatedTexture(CDynamicArray &afnPictures, CWnd* pParent = NULL); // standard constructor + ~CDlgCreateAnimatedTexture(); + void ReleaseCreatedTexture(void); + void InitAnimationsCombo(void); + void RefreshTexture(void); + + CDynamicArray *m_pafnPictures; + BOOL m_bPreviewWindowsCreated; + PIX m_pixSourceWidth; + PIX m_pixSourceHeight; + CTFileName m_fnSourceFileName; + CTFileName m_fnCreatedFileName; + CWndDisplayTexture m_wndViewDetailTexture; + CWndDisplayTexture m_wndViewCreatedTexture; + CTextureData *m_ptdCreated; + +// Dialog Data + //{{AFX_DATA(CDlgCreateAnimatedTexture) + enum { IDD = IDD_CREATE_ANIMATED_TEXTURE }; + CButton m_ctrlCheckButton; + CComboBox m_ctrlAnimationsCombo; + CString m_strEditScript; + CString m_strSizeInPixels; + CString m_strCreatedTextureName; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgCreateAnimatedTexture) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgCreateAnimatedTexture) + afx_msg void OnPaint(); + afx_msg void OnChequeredAlpha(); + afx_msg void OnBrowseDetail(); + afx_msg void OnDetailNone(); + afx_msg void OnCreateTexture(); + afx_msg void OnRefreshTexture(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeTextureAnimations(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGCREATEANIMATEDTEXTURE_H__C517CED3_FA6C_11D1_82E9_000000000000__INCLUDED_) diff --git a/Sources/EngineGui/DlgCreateEffectTexture.cpp b/Sources/EngineGui/DlgCreateEffectTexture.cpp new file mode 100644 index 0000000..0b98b3c --- /dev/null +++ b/Sources/EngineGui/DlgCreateEffectTexture.cpp @@ -0,0 +1,523 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgCreateEffectTexture.cpp : implementation file +// + +#include "StdH.h" +#include "DlgCreateEffectTexture.h" +#include +#include + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgCreateEffectTexture dialog + +#define MAX_ALLOWED_MEX_SIZE 1024*1024 +static CDlgCreateEffectTexture *pDialog; +static PIX pixStartU; +static PIX pixStartV; + +// called when user pressed LMB on preview effect window +void _OnLeftMouseDown( PIX pixU, PIX pixV) +{ + // store starting point + pixStartU = pixU; + pixStartV = pixV; +} + +// called when user released LMB on preview effect window +void _OnLeftMouseUp( PIX pixU, PIX pixV) +{ + // obtain currently selected effect source type + ULONG ulEffectSourceType = pDialog->m_ctrlEffectTypeCombo.GetCurSel(); + // add new effect source + pDialog->m_tdCreated.td_ptegEffect->AddEffectSource( ulEffectSourceType, pixStartU, pixStartV, pixU, pixV); +} + +// called when user pressed RMB on preview effect window +void _OnRightMouseDown( PIX pixU, PIX pixV) +{ + // obtain currently selected effect source type + ULONG ulEffectSourceType = pDialog->m_ctrlEffectTypeCombo.GetCurSel(); + // add new effect source + pDialog->m_tdCreated.td_ptegEffect->AddEffectSource( ulEffectSourceType, pixU, pixV, pixU, pixV); +} + +// called when user pressed RMB and move mouse on preview effect window +void _OnRightMouseMove( PIX pixU, PIX pixV) +{ + // obtain currently selected effect source type + ULONG ulEffectSourceType = pDialog->m_ctrlEffectTypeCombo.GetCurSel(); + // add new effect source + pDialog->m_tdCreated.td_ptegEffect->AddEffectSource( ulEffectSourceType, pixU, pixV, pixU, pixV); +} + +CDlgCreateEffectTexture::CDlgCreateEffectTexture(CTFileName fnInputFile/*=""*/, CWnd* pParent /*=NULL*/) + : CDialog(CDlgCreateEffectTexture::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgCreateEffectTexture) + m_strCreatedTextureName = _T(""); + m_strBaseTextureName = _T(""); + m_strRendSpeed = _T(""); + //}}AFX_DATA_INIT + + // set dialog ptr + pDialog = this; + // register left mouse button call back function + m_wndViewCreatedTexture.SetLeftMouseButtonClicked( _OnLeftMouseDown); + // register left mouse release button call back function + m_wndViewCreatedTexture.SetLeftMouseButtonReleased( _OnLeftMouseUp); + // register right mouse button call back function + m_wndViewCreatedTexture.SetRightMouseButtonClicked( _OnRightMouseDown); + // register right mouse button move call back function + m_wndViewCreatedTexture.SetRightMouseButtonMoved( _OnRightMouseMove); + + // set invalid initial mip level and size for created texture + m_mexInitialCreatedWidth = 2048; + m_pixInitialCreatedWidth = 256; + m_pixInitialCreatedHeight = 256; + + BOOL bCreateNew = TRUE; + if( fnInputFile != "") + { + m_fnCreatedTextureName = fnInputFile; + try + { + // load texture with the same name (if allready exists) + m_tdCreated.Load_t( m_fnCreatedTextureName); + // remember existing texture's width in mexels + m_mexInitialCreatedWidth = m_tdCreated.GetWidth(); + m_pixInitialCreatedWidth = m_tdCreated.GetPixWidth(); + m_pixInitialCreatedHeight = m_tdCreated.GetPixHeight(); + bCreateNew = FALSE; + } + // if texture can't be obtained + catch( char *err_str) + { + // never mind + (void) err_str; + } + } + else + { + // set texture name to unnamed + m_fnCreatedTextureName = CTString("Unnamed"); + } + + // if we should create a new texture + if( bCreateNew) + { + CTextureData *pBaseTexture; + try + { + // obtain default texture as base + pBaseTexture = _pTextureStock->Obtain_t( CTFILENAME("Textures\\Editor\\Default.tex")); + } + // if texture can't be obtained + catch( char *err_str) + { + // stop executing program + FatalError( "%s", err_str); + } + + // create empty effect texture + m_tdCreated.CreateEffectTexture(m_pixInitialCreatedWidth, m_pixInitialCreatedHeight, + m_mexInitialCreatedWidth, pBaseTexture, 0); + // release default texture + _pTextureStock->Release(pBaseTexture); + } + + m_wndViewCreatedTexture.m_toTexture.SetData( &m_tdCreated); + + // copy texture name to text control + m_strCreatedTextureName = m_fnCreatedTextureName; + m_bPreviewWindowsCreated = FALSE; +} + +CDlgCreateEffectTexture::~CDlgCreateEffectTexture() +{ + m_tdCreated.MarkUsed(); + m_wndViewCreatedTexture.m_toTexture.SetData( NULL); + m_tdCreated.MarkUnused(); +} + +void CDlgCreateEffectTexture::SetNewBaseTexture( CTFileName fnNewBase) +{ + if( fnNewBase != "") + { + // try to + try + { + // obtain texture with the same name (if allready exists) + CTextureData *pTD = _pTextureStock->Obtain_t( fnNewBase); + pTD->Reload(); + if( pTD->td_ptegEffect != NULL) + { + _pTextureStock->Release( pTD); + ThrowF_t( "Texture '%s' is an effect texture.", (CTString&)fnNewBase); + } + // if there is base texture obtained, release it + if( m_tdCreated.td_ptdBaseTexture!= NULL) + { + _pTextureStock->Release( m_tdCreated.td_ptdBaseTexture); + // reset base texture ptr + m_tdCreated.td_ptdBaseTexture = NULL; + } + // set new base texture ptr + m_tdCreated.td_ptdBaseTexture = pTD; + m_pixInitialCreatedWidth = pTD->GetPixWidth(); + m_pixInitialCreatedHeight = pTD->GetPixHeight(); + UpdateData( FALSE); + SelectPixSizeCombo(); + } + catch(char *err_str) + { + AfxMessageBox( CString(err_str)); + return; + } + } +} + +void CDlgCreateEffectTexture::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + + // if dialog is receiving data + if(pDX->m_bSaveAndValidate == FALSE) + { + m_strBaseTextureName = "None"; + CTFileName fnNewBase; + // if there is base texture obtained, get name + if( m_tdCreated.td_ptdBaseTexture != NULL) + { + PIX pixBaseTextureWidth = m_tdCreated.td_ptdBaseTexture->GetPixWidth(); + PIX pixBaseTextureHeight = m_tdCreated.td_ptdBaseTexture->GetPixHeight(); + char achrBaseTextureName[ 256]; + sprintf( achrBaseTextureName, "%s (%d x %d)", + (CTString&)m_tdCreated.td_ptdBaseTexture->GetName(), + pixBaseTextureWidth, pixBaseTextureHeight); + m_strBaseTextureName = achrBaseTextureName; + } + } + + //{{AFX_DATA_MAP(CDlgCreateEffectTexture) + DDX_Control(pDX, IDC_CHEQUERED_ALPHA, m_ctrlCheckButton); + DDX_Control(pDX, IDC_MEX_SIZE, m_ctrlMexSizeCombo); + DDX_Control(pDX, IDC_PIX_WIDTH, m_ctrlPixWidthCombo); + DDX_Control(pDX, IDC_PIX_HEIGHT, m_ctrlPixHeightCombo); + DDX_Control(pDX, IDC_EFFECT_CLASS, m_ctrlEffectClassCombo); + DDX_Control(pDX, IDC_EFFECT_TYPE, m_ctrlEffectTypeCombo); + DDX_Text(pDX, IDC_CREATED_TEXTURE_NAME, m_strCreatedTextureName); + DDX_Text(pDX, IDC_BASE_TEXTURE_NAME, m_strBaseTextureName); + DDX_Text(pDX, IDC_REND_SPEED, m_strRendSpeed); + //}}AFX_DATA_MAP + + // if dialog is giving data + if(pDX->m_bSaveAndValidate != FALSE) + { + } +} + + +BEGIN_MESSAGE_MAP(CDlgCreateEffectTexture, CDialog) + //{{AFX_MSG_MAP(CDlgCreateEffectTexture) + ON_WM_PAINT() + ON_BN_CLICKED(IDC_CHEQUERED_ALPHA, OnChequeredAlpha) + ON_BN_CLICKED(ID_BROWSE_BASE, OnBrowseBase) + ON_BN_CLICKED(ID_CREATE_AS, OnCreateAs) + ON_BN_CLICKED(ID_REMOVE_ALL_EFFECTS, OnRemoveAllEffects) + ON_CBN_SELCHANGE(IDC_PIX_HEIGHT, OnSelchangePixHeight) + ON_CBN_SELCHANGE(IDC_PIX_WIDTH, OnSelchangePixWidth) + ON_CBN_SELCHANGE(IDC_MEX_SIZE, OnSelchangeMexSize) + ON_BN_CLICKED(ID_CREATE, OnCreate) + ON_CBN_SELCHANGE(IDC_EFFECT_CLASS, OnSelchangeEffectClass) + ON_CBN_SELCHANGE(IDC_EFFECT_TYPE, OnSelchangeEffectType) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgCreateEffectTexture message handlers + +void CDlgCreateEffectTexture::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + // if texture preview windows are not yet created + if( !m_bPreviewWindowsCreated) + { + // ---------------- Create custom window that will show how created texture will look like + CWnd *pWndCreatedTexturePreview = GetDlgItem(IDC_TEXTURE_PREVIEW_WINDOW); + ASSERT(pWndCreatedTexturePreview != NULL); + CRect rectPreviewCreatedTextureWnd; + // get rectangle occupied by preview texture window + pWndCreatedTexturePreview->GetWindowRect( &rectPreviewCreatedTextureWnd); + ScreenToClient( &rectPreviewCreatedTextureWnd); + // create window for for showing created texture + m_wndViewCreatedTexture.Create( NULL, NULL, WS_BORDER|WS_VISIBLE, rectPreviewCreatedTextureWnd, + this, IDW_VIEW_CREATED_TEXTURE); + // mark that custom windows are created + m_bPreviewWindowsCreated = TRUE; + } +} + +void CDlgCreateEffectTexture::OnChequeredAlpha() +{ + // toggle chequered alpha on/off + m_wndViewCreatedTexture.m_bChequeredAlpha = !m_wndViewCreatedTexture.m_bChequeredAlpha; +} + +void CDlgCreateEffectTexture::InitializeSizeCombo(void) +{ + // clear combo box + m_ctrlMexSizeCombo.ResetContent(); + + INDEX iSelectedWidth = m_ctrlPixWidthCombo.GetCurSel(); + INDEX iSelectedHeight = m_ctrlPixHeightCombo.GetCurSel(); + // obtain selected size in pixels + m_pixInitialCreatedWidth = 1< MAX_ALLOWED_MEX_SIZE) || + (mexPotentionHeight > MAX_ALLOWED_MEX_SIZE)) + break; + sprintf( strSize, "%.2f x %.2f", + METERS_MEX( mexPotentionWidth), METERS_MEX( mexPotentionHeight)); + INDEX iAddedAs = m_ctrlMexSizeCombo.AddString( CString(strSize)); + // connect item and represented mex value + m_ctrlMexSizeCombo.SetItemData( iAddedAs, mexPotentionWidth); + // try to select consistent size + if( mexPotentionWidth == m_mexInitialCreatedWidth) + { + iInitialSelectedSize = iPotention; + } + // next potention + iPotention ++; + } + // select size + m_ctrlMexSizeCombo.SetCurSel( iInitialSelectedSize); +} + +void CDlgCreateEffectTexture::InitializeEffectTypeCombo( void) +{ + // get selected effect class + INDEX iClass = m_ctrlEffectClassCombo.GetCurSel(); + // obtain effect source table for current effect class + struct TextureEffectSourceType *patestSourceEffectTypes = + _ategtTextureEffectGlobalPresets[ iClass].tet_atestEffectSourceTypes; + INDEX ctSourceEffectTypes = _ategtTextureEffectGlobalPresets[ iClass].tet_ctEffectSourceTypes; + // initialize effect groups combo + m_ctrlEffectTypeCombo.ResetContent(); + for( INDEX iEffectType=0; iEffectTypeteg_ulEffectType; + m_ctrlEffectClassCombo.SetCurSel( iSelectedEffectClass); + + // initialize sub effects + InitializeEffectTypeCombo(); + + m_ctrlCheckButton.SetCheck( 1); + + SelectPixSizeCombo(); + return TRUE; +} + +void CDlgCreateEffectTexture::OnBrowseBase() +{ + CTFileName fnNewBase; + // if there is base texture obtained, release it + if( m_tdCreated.td_ptdBaseTexture != NULL) + { + fnNewBase = _EngineGUI.BrowseTexture( m_tdCreated.td_ptdBaseTexture->GetName(), + KEY_NAME_BASE_TEXTURE_DIR, "Browse base texture"); + } + else + { + fnNewBase = _EngineGUI.BrowseTexture( CTString(""), KEY_NAME_BASE_TEXTURE_DIR, + "Browse base texture"); + } + SetNewBaseTexture( fnNewBase); + CreateTexture(); +} + +void CDlgCreateEffectTexture::OnRemoveAllEffects() +{ + CreateTexture(); +} + +void CDlgCreateEffectTexture::OnSelchangeMexSize() +{ + CreateTexture(); +} + +void CDlgCreateEffectTexture::OnSelchangePixHeight() +{ + INDEX iSelectedWidth = m_ctrlPixWidthCombo.GetCurSel(); + INDEX iSelectedHeight = m_ctrlPixHeightCombo.GetCurSel(); + InitializeSizeCombo(); + CreateTexture(); +} + +void CDlgCreateEffectTexture::OnSelchangePixWidth() +{ + INDEX iSelectedWidth = m_ctrlPixWidthCombo.GetCurSel(); + INDEX iSelectedHeight = m_ctrlPixHeightCombo.GetCurSel(); + InitializeSizeCombo(); + CreateTexture(); +} + +void CDlgCreateEffectTexture::CreateTexture( void) +{ + // obtain selected sizes + m_pixInitialCreatedWidth = 1<= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// DlgCreateEffectTexture.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgCreateEffectTexture dialog + +class CDlgCreateEffectTexture : public CDialog +{ +// Construction +public: + CDlgCreateEffectTexture(CTFileName fnInputFile=CTString(""),CWnd* pParent = NULL); // standard constructor + ~CDlgCreateEffectTexture(); // standard destructor + void SetNewBaseTexture( CTFileName fnNewBase); + void SelectPixSizeCombo(void); + void InitializeSizeCombo(void); + void InitializeEffectTypeCombo(void); + void CreateTexture( void); + + BOOL m_bPreviewWindowsCreated; + MEX m_mexInitialCreatedWidth; + PIX m_pixInitialCreatedWidth; + PIX m_pixInitialCreatedHeight; + CTFileName m_fnCreatedTextureName; + CWndDisplayTexture m_wndViewCreatedTexture; + CTextureData m_tdCreated; + +// Dialog Data + //{{AFX_DATA(CDlgCreateEffectTexture) + enum { IDD = IDD_CREATE_EFFECT_TEXTURE }; + CButton m_ctrlCheckButton; + CComboBox m_ctrlMexSizeCombo; + CComboBox m_ctrlPixWidthCombo; + CComboBox m_ctrlPixHeightCombo; + CComboBox m_ctrlEffectClassCombo; + CComboBox m_ctrlEffectTypeCombo; + CString m_strCreatedTextureName; + CString m_strBaseTextureName; + CString m_strRendSpeed; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgCreateEffectTexture) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgCreateEffectTexture) + afx_msg void OnPaint(); + afx_msg void OnChequeredAlpha(); + virtual BOOL OnInitDialog(); + afx_msg void OnBrowseBase(); + afx_msg void OnCreateAs(); + afx_msg void OnRemoveAllEffects(); + afx_msg void OnSelchangePixHeight(); + afx_msg void OnSelchangePixWidth(); + afx_msg void OnSelchangeMexSize(); + afx_msg void OnCreate(); + afx_msg void OnSelchangeEffectClass(); + afx_msg void OnSelchangeEffectType(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGCREATEEFFECTTEXTURE_H__C517CED4_FA6C_11D1_82E9_000000000000__INCLUDED_) diff --git a/Sources/EngineGui/DlgCreateNormalTexture.cpp b/Sources/EngineGui/DlgCreateNormalTexture.cpp new file mode 100644 index 0000000..5efa23f --- /dev/null +++ b/Sources/EngineGui/DlgCreateNormalTexture.cpp @@ -0,0 +1,305 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgCreateNormalTexture.cpp : implementation file +// + +#include "StdH.h" +#include "DlgCreateNormalTexture.h" +#include + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +static BOOL _bWasForced32 = FALSE; + +///////////////////////////////////////////////////////////////////////////// +// CDlgCreateNormalTexture dialog + + +CDlgCreateNormalTexture::CDlgCreateNormalTexture( CTFileName fnInputFile, CWnd* pParent /*=NULL*/) + : CDialog(CDlgCreateNormalTexture::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgCreateNormalTexture) + m_strCreatedTextureName = _T(""); + m_strSizeInPixels = _T(""); + m_bCreateMipmaps = FALSE; + //}}AFX_DATA_INIT + + m_bSourcePictureValid = FALSE; + m_bPreviewWindowsCreated = FALSE; + m_ptdCreated = NULL; + + CTFileName fnTexFileName = fnInputFile.FileDir() + fnInputFile.FileName() + ".tex"; + // remember source and created texture name + m_fnSourceFileName = fnInputFile; + m_fnCreatedFileName = fnTexFileName; + // set initial values for create mip maps flag and size for create texture dialog + m_bCreateMipmaps = AfxGetApp()->GetProfileInt(L"Creating textures", L"Create mipmaps", 1); + m_mexCreatedWidth = AfxGetApp()->GetProfileInt(L"Creating textures", L"Mex width", -1); + _bWasForced32 = FALSE; + + try + { + // if can't get picture file information + CImageInfo iiImageInfo; + if (iiImageInfo.GetGfxFileInfo_t( m_fnSourceFileName)==UNSUPPORTED_FILE) + { + // throw error + ThrowF_t("File '%s' has unsupported file format", + (CTString&)(_fnmApplicationPath+m_fnSourceFileName)); + } + // get dimensions + m_pixSourceWidth = iiImageInfo.ii_Width; + m_pixSourceHeight = iiImageInfo.ii_Height; + // test if dimensions are at power of 2 + if( (((1<<((int)Log2(m_pixSourceWidth))) != m_pixSourceWidth)) || + (((1<<((int)Log2(m_pixSourceHeight))) != m_pixSourceHeight))) { + ThrowF_t( "Picture %s has wrong dimensions (%d,%d).\n" + "Both width and height must be at power of 2.", + (CTString&)m_fnSourceFileName, m_pixSourceWidth, m_pixSourceHeight); + } + } + catch(char *err_str) + { + AfxMessageBox( CString(err_str)); + return; + } + m_bSourcePictureValid = TRUE; + + // try to + try + { // obtain texture with the same name (if already exists) + CTextureData *pTD = _pTextureStock->Obtain_t( fnTexFileName); + pTD->Reload(); + // now pick up initial number of mip levels + m_bCreateMipmaps = pTD->td_ctFineMipLevels>1; + // remember existing texture's width in mexels + m_mexCreatedWidth = pTD->GetWidth(); + // remember existing texture's flags + _bWasForced32 = pTD->td_ulFlags & TEX_32BIT; + // release texture + _pTextureStock->Release( pTD); + } + // if texture can't be obtained + catch( char *err_str) + { // never mind + (void) err_str; + } + + m_wndViewCreatedTexture.m_bForce32 = FALSE; + if( _bWasForced32) m_wndViewCreatedTexture.m_bForce32 = TRUE; + RefreshCreatedTexture(); + // set created texture name + m_strCreatedTextureName = fnTexFileName; + // prepare string telling size of source picture + char strSize[ 64]; + sprintf( strSize, "%d x %d", m_pixSourceWidth, m_pixSourceHeight); + m_strSizeInPixels = strSize; +} + +CDlgCreateNormalTexture::~CDlgCreateNormalTexture() +{ + ReleaseCreatedTexture(); +} + + +void CDlgCreateNormalTexture::RefreshCreatedTexture(void) +{ + ReleaseCreatedTexture(); + + // prepare forced upload quality + _iTexForcedQuality = 16; + if( m_wndViewCreatedTexture.m_bForce32) _iTexForcedQuality = 32; + // create temporary texture to show how texture will look like + try + { + // create temporary texture + CreateTexture_t( m_fnSourceFileName, CTString( "Temp\\Temp.tex"), + m_pixSourceWidth, MAX_MEX_LOG2+1, FALSE); + m_ptdCreated = _pTextureStock->Obtain_t( CTString( "Temp\\Temp.tex")); + m_ptdCreated->Reload(); + } + catch(char *err_str) + { + AfxMessageBox( CString(err_str)); + return; + } + // set texture data to texture preview window so it could show preview picture + m_wndViewCreatedTexture.m_toTexture.SetData( m_ptdCreated); +} + + + +void CDlgCreateNormalTexture::ReleaseCreatedTexture(void) +{ + // if there is texture obtained, release it + if( m_ptdCreated != NULL) + { + // free obtained texture + _pTextureStock->Release( m_ptdCreated); + m_ptdCreated = NULL; + m_wndViewCreatedTexture.m_toTexture.SetData( NULL); + } + // reset forced upload quality + _iTexForcedQuality = 0; +} + + +void CDlgCreateNormalTexture::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + + // if dialog is recieving data + if(pDX->m_bSaveAndValidate == FALSE) + { + } + + //{{AFX_DATA_MAP(CDlgCreateNormalTexture) + DDX_Control(pDX, IDC_FORCE32, m_ctrlForce32); + DDX_Control(pDX, IDC_CHEQUERED_ALPHA, m_ctrlCheckButton); + DDX_Control(pDX, IDC_MEX_SIZE, m_ctrlMexSizeCombo); + DDX_Text(pDX, IDC_CREATED_TEXTURE_NAME, m_strCreatedTextureName); + DDX_Text(pDX, IDC_SIZE_IN_PIXELS, m_strSizeInPixels); + DDX_Check(pDX, IDC_CREATE_MIPMAPS, m_bCreateMipmaps); + //}}AFX_DATA_MAP + + // if dialog is giving data + if(pDX->m_bSaveAndValidate != FALSE) + { + } +} + + +BEGIN_MESSAGE_MAP(CDlgCreateNormalTexture, CDialog) + //{{AFX_MSG_MAP(CDlgCreateNormalTexture) + ON_WM_PAINT() + ON_BN_CLICKED(IDC_CHEQUERED_ALPHA, OnChequeredAlpha) + ON_BN_CLICKED(IDC_FORCE32, OnForce32) + ON_BN_CLICKED(ID_CREATE_TEXTURE, OnCreateTexture) + ON_BN_CLICKED(IDC_CREATE_MIPMAPS, OnCreateMipmaps) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgCreateNormalTexture message handlers + +void CDlgCreateNormalTexture::OnPaint() +{ + CPaintDC dc(this); // device context for painting + + // if texture preview windows are not yet created + if( !m_bPreviewWindowsCreated) + { + // ---------------- Create custom window that will show how created texture will look like + CWnd *pWndCreatedTexturePreview = GetDlgItem(IDC_TEXTURE_PREVIEW_WINDOW); + ASSERT(pWndCreatedTexturePreview != NULL); + CRect rectPreviewCreatedTextureWnd; + // get rectangle occupied by preview texture window + pWndCreatedTexturePreview->GetWindowRect( &rectPreviewCreatedTextureWnd); + ScreenToClient( &rectPreviewCreatedTextureWnd); + // create window for for showing created texture + m_wndViewCreatedTexture.Create( NULL, NULL, WS_BORDER|WS_VISIBLE, rectPreviewCreatedTextureWnd, + this, IDW_VIEW_CREATED_TEXTURE); + // mark that custom windows are created + m_bPreviewWindowsCreated = TRUE; + } +} + +#define MAX_ALLOWED_MEX_SIZE 32*1024*1024 + +BOOL CDlgCreateNormalTexture::OnInitDialog() +{ + CDialog::OnInitDialog(); + char strSize[ 64]; + + // set default created texture's size + INDEX iInitialSelectedSize = 0; + // first combo entry is selected by default (requesting maximum mip maps to be created) + INDEX iInitialSelectedMipMapCombo = 0; + + // obtain all available potentions of source picture's dimensions + INDEX iPotention = 0; + FOREVER + { + MEX mexPotentionWidth = m_pixSourceWidth * (1 << iPotention); + MEX mexPotentionHeight = m_pixSourceHeight * (1 << iPotention); + if( (mexPotentionWidth > MAX_ALLOWED_MEX_SIZE) || + (mexPotentionHeight > MAX_ALLOWED_MEX_SIZE)) + break; + sprintf( strSize, "%.2f x %.2f", + METERS_MEX( mexPotentionWidth), METERS_MEX( mexPotentionHeight)); + INDEX iAddedAs = m_ctrlMexSizeCombo.AddString( CString(strSize)); + // connect item and represented mex value + m_ctrlMexSizeCombo.SetItemData( iAddedAs, mexPotentionWidth); + // try to select consistent size + if( mexPotentionWidth == m_mexCreatedWidth) + { + iInitialSelectedSize = iPotention; + } + // next potention + iPotention ++; + } + // select size + m_ctrlMexSizeCombo.SetCurSel( iInitialSelectedSize); + m_ctrlCheckButton.SetCheck(1); + // determine correct texture quality + if( _bWasForced32) { + m_ctrlForce32.SetCheck(1); + m_wndViewCreatedTexture.m_bForce32 = TRUE; + } else { + m_ctrlForce32.SetCheck(0); + m_wndViewCreatedTexture.m_bForce32 = FALSE; + } + // return TRUE unless you set the focus to a control + return TRUE; +} + + +void CDlgCreateNormalTexture::OnCreateTexture() +{ + MEX mexWidth = m_ctrlMexSizeCombo.GetItemData( m_ctrlMexSizeCombo.GetCurSel()); + INDEX iMipMaps = 16; + if( !m_bCreateMipmaps) + { + iMipMaps = 1; + } + // create texture + try { + CreateTexture_t( m_fnSourceFileName, m_fnCreatedFileName, mexWidth, iMipMaps, + m_wndViewCreatedTexture.m_bForce32); + } + catch( char *err_str) { + AfxMessageBox( CString(err_str)); + return; + } + AfxGetApp()->WriteProfileInt(L"Creating textures", L"Create mipmaps", m_bCreateMipmaps); + AfxGetApp()->WriteProfileInt(L"Creating textures", L"Mex width", mexWidth); + // end dialog + EndDialog( IDOK); +} + + +void CDlgCreateNormalTexture::OnChequeredAlpha() +{ + // toggle chequered alpha on/off + m_wndViewCreatedTexture.m_bChequeredAlpha = !m_wndViewCreatedTexture.m_bChequeredAlpha; + RefreshCreatedTexture(); +} + +void CDlgCreateNormalTexture::OnForce32() +{ + // toggle force32 on/off + m_wndViewCreatedTexture.m_bForce32 = !m_wndViewCreatedTexture.m_bForce32; + RefreshCreatedTexture(); +} + +void CDlgCreateNormalTexture::OnCreateMipmaps() +{ + m_bCreateMipmaps = !m_bCreateMipmaps; + UpdateData(FALSE); +} diff --git a/Sources/EngineGui/DlgCreateNormalTexture.h b/Sources/EngineGui/DlgCreateNormalTexture.h new file mode 100644 index 0000000..50ea5e8 --- /dev/null +++ b/Sources/EngineGui/DlgCreateNormalTexture.h @@ -0,0 +1,75 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#if !defined(AFX_DLGCREATENORMALTEXTURE_H__C517CED2_FA6C_11D1_82E9_000000000000__INCLUDED_) +#define AFX_DLGCREATENORMALTEXTURE_H__C517CED2_FA6C_11D1_82E9_000000000000__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// DlgCreateNormalTexture.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgCreateNormalTexture dialog + +class CDlgCreateNormalTexture : public CDialog +{ +// Construction +public: + CDlgCreateNormalTexture(CTFileName fnInputFile, CWnd* pParent = NULL); // standard constructor + ~CDlgCreateNormalTexture(); + void RefreshCreatedTexture(void); + void ReleaseCreatedTexture(void); + + BOOL m_bSourcePictureValid; + BOOL m_bPreviewWindowsCreated; + PIX m_pixSourceWidth; + PIX m_pixSourceHeight; + MEX m_mexCreatedWidth; + CTFileName m_fnSourceFileName; + CTFileName m_fnCreatedFileName; + CWndDisplayTexture m_wndViewDetailTexture; + CWndDisplayTexture m_wndViewCreatedTexture; + CTextureData *m_ptdCreated; + +// Dialog Data + //{{AFX_DATA(CDlgCreateNormalTexture) + enum { IDD = IDD_CREATE_NORMAL_TEXTURE }; + CButton m_ctrlForce32; + CButton m_ctrlCheckButton; + CComboBox m_ctrlNoOfMipMapsCombo; + CComboBox m_ctrlMexSizeCombo; + CString m_strCreatedTextureName; + CString m_strSizeInPixels; + BOOL m_bCreateMipmaps; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgCreateNormalTexture) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgCreateNormalTexture) + afx_msg void OnPaint(); + afx_msg void OnChequeredAlpha(); + afx_msg void OnForce32(); + virtual BOOL OnInitDialog(); + afx_msg void OnBrowseDetail(); + afx_msg void OnDetailNone(); + afx_msg void OnCreateTexture(); + afx_msg void OnCreateMipmaps(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGCREATENORMALTEXTURE_H__C517CED2_FA6C_11D1_82E9_000000000000__INCLUDED_) diff --git a/Sources/EngineGui/DlgSelectMode.cpp b/Sources/EngineGui/DlgSelectMode.cpp new file mode 100644 index 0000000..2044e7c --- /dev/null +++ b/Sources/EngineGui/DlgSelectMode.cpp @@ -0,0 +1,373 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgSelectMode.cpp : implementation file +// + +#include "StdH.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +// internal routines for displaying test screen + +static void DrawGradient( CDrawPort *pDP, COLOR colStart, COLOR colEnd, + PIX pixI0, PIX pixJ0, PIX pixI1, PIX pixJ1) +{ + colStart |= CT_OPAQUE; + colEnd |= CT_OPAQUE; + pDP->Fill( pixI0, pixJ0, pixI1-pixI0, pixJ1-pixJ0, colStart, colEnd, colStart, colEnd); +} + + +static void ShowTestModeScreen( CDrawPort *pDP, CViewPort *pVP) +{ + // try to lock draw port + if( !pDP->Lock()) return; + + // draw rectangle + PIX dpWidth = pDP->GetWidth(); + PIX dpHeight = pDP->GetHeight(); + pDP->Fill( C_WHITE | CT_OPAQUE); + pDP->Fill( 2,2, dpWidth-4, dpHeight-4, C_BLACK | CT_OPAQUE); + + // draw gradients + DrawGradient( pDP, C_WHITE, C_RED, 1.0f/8*dpWidth, 1.0f/16*dpHeight, 1.0f/2*dpWidth, 2.0f/16*dpHeight); + DrawGradient( pDP, C_RED, C_BLACK, 1.0f/2*dpWidth, 1.0f/16*dpHeight, 7.0f/8*dpWidth, 2.0f/16*dpHeight); + DrawGradient( pDP, C_BLACK, C_GREEN, 1.0f/8*dpWidth, 2.0f/16*dpHeight, 1.0f/2*dpWidth, 3.0f/16*dpHeight); + DrawGradient( pDP, C_GREEN, C_WHITE, 1.0f/2*dpWidth, 2.0f/16*dpHeight, 7.0f/8*dpWidth, 3.0f/16*dpHeight); + DrawGradient( pDP, C_WHITE, C_BLUE, 1.0f/8*dpWidth, 3.0f/16*dpHeight, 1.0f/2*dpWidth, 4.0f/16*dpHeight); + DrawGradient( pDP, C_BLUE, C_BLACK, 1.0f/2*dpWidth, 3.0f/16*dpHeight, 7.0f/8*dpWidth, 4.0f/16*dpHeight); + + DrawGradient( pDP, C_BLACK, C_CYAN, 1.0f/8*dpWidth, 4.5f/16*dpHeight, 1.0f/2*dpWidth, 5.5f/16*dpHeight); + DrawGradient( pDP, C_CYAN, C_WHITE, 1.0f/2*dpWidth, 4.5f/16*dpHeight, 7.0f/8*dpWidth, 5.5f/16*dpHeight); + DrawGradient( pDP, C_WHITE, C_MAGENTA, 1.0f/8*dpWidth, 5.5f/16*dpHeight, 1.0f/2*dpWidth, 6.5f/16*dpHeight); + DrawGradient( pDP, C_MAGENTA, C_BLACK, 1.0f/2*dpWidth, 5.5f/16*dpHeight, 7.0f/8*dpWidth, 6.5f/16*dpHeight); + DrawGradient( pDP, C_BLACK, C_YELLOW, 1.0f/8*dpWidth, 6.5f/16*dpHeight, 1.0f/2*dpWidth, 7.5f/16*dpHeight); + DrawGradient( pDP, C_YELLOW, C_WHITE, 1.0f/2*dpWidth, 6.5f/16*dpHeight, 7.0f/8*dpWidth, 7.5f/16*dpHeight); + + DrawGradient( pDP, C_WHITE, C_BLACK, 1.0f/8*dpWidth, 8.0f/16*dpHeight, 7.0f/8*dpWidth, 10.0f/16*dpHeight); + + // draw rectangles + pDP->Fill( 1.5f/8*dpWidth, 10.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_dRED |CT_OPAQUE); + pDP->Fill( 1.5f/8*dpWidth, 11.0f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_RED |CT_OPAQUE); + pDP->Fill( 1.5f/8*dpWidth, 11.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_lRED |CT_OPAQUE); + + pDP->Fill( 2.0f/8*dpWidth, 10.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_dGREEN |CT_OPAQUE); + pDP->Fill( 2.0f/8*dpWidth, 11.0f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_GREEN |CT_OPAQUE); + pDP->Fill( 2.0f/8*dpWidth, 11.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_lGREEN |CT_OPAQUE); + + pDP->Fill( 2.5f/8*dpWidth, 10.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_dBLUE |CT_OPAQUE); + pDP->Fill( 2.5f/8*dpWidth, 11.0f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_BLUE |CT_OPAQUE); + pDP->Fill( 2.5f/8*dpWidth, 11.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_lBLUE |CT_OPAQUE); + + pDP->Fill( 3.0f/8*dpWidth, 10.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_dCYAN |CT_OPAQUE); + pDP->Fill( 3.0f/8*dpWidth, 11.0f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_CYAN |CT_OPAQUE); + pDP->Fill( 3.0f/8*dpWidth, 11.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_lCYAN |CT_OPAQUE); + + pDP->Fill( 3.5f/8*dpWidth, 10.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_dMAGENTA |CT_OPAQUE); + pDP->Fill( 3.5f/8*dpWidth, 11.0f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_MAGENTA |CT_OPAQUE); + pDP->Fill( 3.5f/8*dpWidth, 11.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_lMAGENTA |CT_OPAQUE); + + pDP->Fill( 4.0f/8*dpWidth, 10.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_dYELLOW |CT_OPAQUE); + pDP->Fill( 4.0f/8*dpWidth, 11.0f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_YELLOW |CT_OPAQUE); + pDP->Fill( 4.0f/8*dpWidth, 11.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_lYELLOW |CT_OPAQUE); + + pDP->Fill( 4.5f/8*dpWidth, 10.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_dGRAY |CT_OPAQUE); + pDP->Fill( 4.5f/8*dpWidth, 11.0f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_GRAY |CT_OPAQUE); + pDP->Fill( 4.5f/8*dpWidth, 11.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_lGRAY |CT_OPAQUE); + + pDP->Fill( 5.0f/8*dpWidth, 10.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_dORANGE |CT_OPAQUE); + pDP->Fill( 5.0f/8*dpWidth, 11.0f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_ORANGE |CT_OPAQUE); + pDP->Fill( 5.0f/8*dpWidth, 11.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_lORANGE |CT_OPAQUE); + + pDP->Fill( 5.5f/8*dpWidth, 10.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_dBROWN |CT_OPAQUE); + pDP->Fill( 5.5f/8*dpWidth, 11.0f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_BROWN |CT_OPAQUE); + pDP->Fill( 5.5f/8*dpWidth, 11.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_lBROWN |CT_OPAQUE); + + pDP->Fill( 6.0f/8*dpWidth, 10.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_dPINK |CT_OPAQUE); + pDP->Fill( 6.0f/8*dpWidth, 11.0f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_PINK |CT_OPAQUE); + pDP->Fill( 6.0f/8*dpWidth, 11.5f/16*dpHeight, 1.0f/16*dpWidth, 0.5f/16*dpHeight, C_lPINK |CT_OPAQUE); + + // set font + pDP->SetFont( _pfdDisplayFont); + // create text to display + CTString strTestMessage = "test screen"; + + // type messages + pDP->PutTextC( strTestMessage, 1.0f/4*dpWidth, 12.5f/16*dpHeight, C_dRED |CT_OPAQUE); + pDP->PutTextC( strTestMessage, 2.0f/4*dpWidth, 12.5f/16*dpHeight, C_RED |CT_OPAQUE); + pDP->PutTextC( strTestMessage, 3.0f/4*dpWidth, 12.5f/16*dpHeight, C_lRED |CT_OPAQUE); + + pDP->PutTextC( strTestMessage, 1.0f/4*dpWidth, 13.0f/16*dpHeight, C_dGREEN|CT_OPAQUE); + pDP->PutTextC( strTestMessage, 2.0f/4*dpWidth, 13.0f/16*dpHeight, C_GREEN |CT_OPAQUE); + pDP->PutTextC( strTestMessage, 3.0f/4*dpWidth, 13.0f/16*dpHeight, C_lGREEN|CT_OPAQUE); + + pDP->PutTextC( strTestMessage, 1.0f/4*dpWidth, 13.5f/16*dpHeight, C_dBLUE |CT_OPAQUE); + pDP->PutTextC( strTestMessage, 2.0f/4*dpWidth, 13.5f/16*dpHeight, C_BLUE |CT_OPAQUE); + pDP->PutTextC( strTestMessage, 3.0f/4*dpWidth, 13.5f/16*dpHeight, C_lBLUE |CT_OPAQUE); + + pDP->PutTextC( strTestMessage, 1.0f/4*dpWidth, 14.0f/16*dpHeight, C_dGRAY |CT_OPAQUE); + pDP->PutTextC( strTestMessage, 2.0f/4*dpWidth, 14.0f/16*dpHeight, C_GRAY |CT_OPAQUE); + pDP->PutTextC( strTestMessage, 3.0f/4*dpWidth, 14.0f/16*dpHeight, C_lGRAY |CT_OPAQUE); + + // type resolution + CDisplayMode dmCurrent; + _pGfx->GetCurrentDisplayMode( dmCurrent); + strTestMessage.PrintF( "%d x %d x %s", dpWidth, dpHeight, dmCurrent.DepthString()); + pDP->PutTextC( strTestMessage, 1.0f/2*dpWidth+2, 1.0f/2*dpHeight+2, C_dGRAY|CT_OPAQUE); + pDP->PutTextC( strTestMessage, 1.0f/2*dpWidth, 1.0f/2*dpHeight, C_WHITE|CT_OPAQUE); + + // unlock draw port + pDP->Unlock(); + + // show screen + pVP->SwapBuffers(); +} + + +///////////////////////////////////////////////////////////////////////////// +// CDlgSelectMode dialog + + +CDlgSelectMode::CDlgSelectMode( CDisplayMode &dm, enum GfxAPIType &gfxAPI, + CWnd* pParent /*=NULL*/) : CDialog( CDlgSelectMode::IDD, pParent) +{ + // obtain all available modes + m_pdmAvailableModes = _pGfx->EnumDisplayModes(m_ctAvailableDisplayModes); + + // remember initial mode reference + m_pdm = &dm; + m_pGfxAPI = &gfxAPI; + + //{{AFX_DATA_INIT(CDlgSelectMode) + m_strCurrentMode = _T(""); + m_strCurrentDriver = _T(""); + m_iColor = -1; + //}}AFX_DATA_INIT + + // set current mode and driver strings + CTString str; + str.PrintF( "%d x %d x %s", dm.dm_pixSizeI, dm.dm_pixSizeJ, dm.DepthString()); + m_strCurrentMode = str; + + switch(gfxAPI) { + case GAT_OGL: + m_strCurrentDriver = "OpenGL"; + break; +#ifdef SE1_D3D + case GAT_D3D: + m_strCurrentDriver = "Direct3D"; + break; +#endif // SE1_D3D + default: + m_strCurrentDriver = "none"; + break; + } +} + +CDlgSelectMode::~CDlgSelectMode() +{ + +} + +void CDlgSelectMode::ApplySettings( CDisplayMode *pdm, enum GfxAPIType *m_pGfxAPI) +{ + // pass driver type var + *m_pGfxAPI = (GfxAPIType)m_ctrlDriverCombo.GetCurSel(); + // determine color mode + DisplayDepth ddDepth; + switch( m_iColor) { + case 0: ddDepth = DD_DEFAULT; break; + case 1: ddDepth = DD_16BIT; break; + case 2: ddDepth = DD_32BIT; break; + default: ASSERT(FALSE); ddDepth = DD_DEFAULT; break; + } + // get resolution + const ULONG ulRes = (ULONG)m_ctrlResCombo.GetItemData( m_ctrlResCombo.GetCurSel()); + const PIX pixSizeI = ulRes>>16; + const PIX pixSizeJ = ulRes&0xFFFF; + + // find potentional corresponding modes + for( INDEX iMode=0; iModedm_pixSizeI = pixSizeI; + pdm->dm_pixSizeJ = pixSizeJ; + pdm->dm_ddDepth = ddDepth; + } + } +} + + +void CDlgSelectMode::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + + // prepare radio buttons + if( !pDX->m_bSaveAndValidate) + { + // set current color radios + switch (m_pdm->dm_ddDepth) { + case DD_DEFAULT: m_iColor = 0; break; + case DD_16BIT : m_iColor = 1; break; + case DD_32BIT : m_iColor = 2; break; + default: ASSERT(FALSE); m_iColor=0; break; + } + } + + //{{AFX_DATA_MAP(CDlgSelectMode) + DDX_Control(pDX, IDC_RESOLUTIONS, m_ctrlResCombo); + DDX_Control(pDX, IDC_API, m_ctrlDriverCombo); + DDX_Text(pDX, IDC_CURRENT_MODE, m_strCurrentMode); + DDX_Text(pDX, IDC_CURRENT_DRIVER, m_strCurrentDriver); + DDX_Radio(pDX, IDC_COLOR_DEFAULT, m_iColor); + //}}AFX_DATA_MAP + + // if dialog is recieving data + if( !pDX->m_bSaveAndValidate) + { + INDEX i, iSelect=0; + + // clear combo boxes + m_ctrlDriverCombo.ResetContent(); + m_ctrlResCombo.ResetContent(); + + // init driver combo + i = m_ctrlDriverCombo.AddString( L"OpenGL"); + m_ctrlDriverCombo.SetItemData( i, (INDEX)GAT_OGL); + if( *m_pGfxAPI==GAT_OGL) iSelect = i; +#ifdef SE1_D3D + i = m_ctrlDriverCombo.AddString( L"Direct3D"); + m_ctrlDriverCombo.SetItemData( i, (INDEX)GAT_D3D); + if( *m_pGfxAPI==GAT_D3D) iSelect = i; +#endif // SE1_D3D + // set old driver to be default + m_ctrlDriverCombo.SetCurSel( iSelect); + + // init resolutions combo + iSelect=0; + for( INDEX iMode=0; iModedm_pixSizeI && pixSizeJ==m_pdm->dm_pixSizeJ) { + // mark it to be selected by default + iSelect = i; + } + } + } // set current res combo default mode + m_ctrlResCombo.SetCurSel( iSelect); + } + +// -------------------------- + + // if dialog is giving data + if( pDX->m_bSaveAndValidate) + { // apply new display mode settings + ApplySettings( m_pdm, m_pGfxAPI); + } +} + + +BEGIN_MESSAGE_MAP(CDlgSelectMode, CDialog) + //{{AFX_MSG_MAP(CDlgSelectMode) + ON_BN_CLICKED(ID_TEST_BUTTON, OnTestButton) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CDlgSelectMode message handlers + +void CDlgSelectMode::OnTestButton() +{ + CWnd wndTestWindowedMode; + + UpdateData( TRUE); + + // apply wanted display mode settings + CDisplayMode dm; + enum GfxAPIType gfxAPI; + ApplySettings( &dm, &gfxAPI); + + // try to set wanted display mode + PIX pixSizeI = dm.dm_pixSizeI; + PIX pixSizeJ = dm.dm_pixSizeJ; + + BOOL bDisplayModeSet = _pGfx->SetDisplayMode( GAT_OGL, 0, pixSizeI, pixSizeJ, dm.dm_ddDepth); + if( !bDisplayModeSet) { + AfxMessageBox( L"Unable to setup full screen display. Test mode failed."); + return; + } + + //--------------------------- Open window for testing windowed display mode + + // draw ports and viewports needed for printing message + CDrawPort *pDrawPort; + CViewPort *pViewPort; + + // get the windows dimensions for this display + int iScreenX = ::GetSystemMetrics(SM_CXSCREEN); // screen size + int iScreenY = ::GetSystemMetrics(SM_CYSCREEN); + + // open window of display mode size + const wchar_t *strWindowClass = AfxRegisterWndClass( CS_OWNDC|CS_NOCLOSE); + wndTestWindowedMode.CreateEx( WS_EX_TOPMOST, strWindowClass, L"Test mode", + WS_POPUP|WS_VISIBLE, 0,0, iScreenX,iScreenY, m_hWnd, 0); + // create window canvas + _pGfx->CreateWindowCanvas( wndTestWindowedMode.m_hWnd, &pViewPort, &pDrawPort); + + // if screen or window opening was not successful + if( pViewPort == NULL) { + AfxMessageBox( L"Unable to setup full screen display. Test mode failed."); + return; + } + + // show test mode screen + ShowTestModeScreen( pDrawPort, pViewPort); + + // get starting time + CTimerValue tvStart = _pTimer->GetHighPrecisionTimer(); + // loop forever + FOREVER { + // get current time + CTimerValue tvCurrent = _pTimer->GetHighPrecisionTimer(); + // get time difference in seconds + CTimerValue tvElapsed = tvCurrent - tvStart; + // three seconds passed? + if( tvElapsed.GetSeconds() > 5.0f) break; + } + + // destroy windowed canvas + _pGfx->DestroyWindowCanvas( pViewPort); + pViewPort = NULL; + // destroy window + wndTestWindowedMode.DestroyWindow(); + + // restore old mode + _pGfx->ResetDisplayMode(); + + if( AfxMessageBox( L"Did You see displayed message correctly?", MB_YESNO) == IDYES) { + GetDlgItem( IDOK)->SetFocus(); // set focus to apply button + } else { + AfxMessageBox( L"Mode is not valid and it is rejected. Choose another one."); + } + + Invalidate( FALSE); +} diff --git a/Sources/EngineGui/DlgSelectMode.h b/Sources/EngineGui/DlgSelectMode.h new file mode 100644 index 0000000..e0bc832 --- /dev/null +++ b/Sources/EngineGui/DlgSelectMode.h @@ -0,0 +1,61 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#if !defined(AFX_DLGSELECTMODE_H__F71966B3_C31A_11D1_8231_000000000000__INCLUDED_) +#define AFX_DLGSELECTMODE_H__F71966B3_C31A_11D1_8231_000000000000__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// DlgSelectMode.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgSelectMode dialog + +class CDlgSelectMode : public CDialog +{ +public: + CDisplayMode *m_pdm; + CDisplayMode *m_pdmAvailableModes; + INDEX m_ctAvailableDisplayModes; + enum GfxAPIType *m_pGfxAPI; +// Construction +public: + CDlgSelectMode( CDisplayMode &dm, enum GfxAPIType &gfxAPI, CWnd* pParent = NULL); + ~CDlgSelectMode(); + void ApplySettings( CDisplayMode *pdm, enum GfxAPIType *pGfxAPI); + +// Dialog Data + //{{AFX_DATA(CDlgSelectMode) + enum { IDD = IDD_SELECT_MODE_DIALOG }; + CComboBox m_ctrlResCombo; + CComboBox m_ctrlDriverCombo; + CString m_strCurrentMode; + CString m_strCurrentDriver; + int m_iColor; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgSelectMode) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgSelectMode) + afx_msg void OnTestButton(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +public: +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGSELECTMODE_H__F71966B3_C31A_11D1_8231_000000000000__INCLUDED_) diff --git a/Sources/EngineGui/EngineGUI.cpp b/Sources/EngineGui/EngineGUI.cpp new file mode 100644 index 0000000..1017308 --- /dev/null +++ b/Sources/EngineGui/EngineGUI.cpp @@ -0,0 +1,276 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" +#include + +// global engine gui handling object +CEngineGUI _EngineGUI; + +/* + We cannot use dllmain if using MFC. + See MSDN article "Regular DLLs Dynamically Linked to MFC" if initialization is needed. + +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} +*/ + + + +void CEngineGUI::SelectMode( CDisplayMode &dm, GfxAPIType &gat) +{ + // stupid way to change resources, but it must be done + HANDLE hOldResource = AfxGetResourceHandle(); + + // call select mode dialog + CDlgSelectMode dlgSelectMode( dm, gat); + + // activate CTGfx resources + AfxSetResourceHandle( GetModuleHandleA(ENGINEGUI_DLL_NAME)); + INDEX iDialogResult = dlgSelectMode.DoModal(); + + // restore resources + AfxSetResourceHandle( (HINSTANCE)hOldResource); + + // if mode dialog ended successfully + if( iDialogResult == IDOK) SetFullScreenModeToRegistry( "Display modes", dm, gat); +} + + +CTFileName CEngineGUI::CreateTexture(CTFileName fnTexFileToRecreate/*=CTString("")*/, + CDynamicArray *pafnCreatedTextures/*=NULL*/) +{ + CTFileName fnResult; + // stupid way to change resources, but it must be done + HANDLE hOldResource = AfxGetResourceHandle(); + // activate CTGfx resources + AfxSetResourceHandle( GetModuleHandleA(ENGINEGUI_DLL_NAME) ); + + // if create texture is called with a wish to recreate texture + if( fnTexFileToRecreate != "") + { + fnResult = fnTexFileToRecreate; + CTextureData *ptdTextureToRecreate; + CTFileName fnToRecreateNoExt = + fnTexFileToRecreate.FileDir()+fnTexFileToRecreate.FileName(); + // try to + try + { + // obtain texture to recreate + ptdTextureToRecreate = _pTextureStock->Obtain_t( fnTexFileToRecreate); + ptdTextureToRecreate->Reload(); + // if texture is of effect type, call create effect texture dialog + if( ptdTextureToRecreate->td_ptegEffect != NULL) + { + // call create effect texture dialog with .tex name + CDlgCreateEffectTexture dlgCreateEffectTexture( fnTexFileToRecreate); + dlgCreateEffectTexture.DoModal(); + } + // else this texture was created from script or from single picture + else + { + // search for script with same name + CTString strFullNameNoExt = _fnmApplicationPath + + fnTexFileToRecreate.FileDir() + fnTexFileToRecreate.FileName(); + // if there is tga picture with same name + if( GetFileAttributesA( strFullNameNoExt+".tga") != -1) + { + // call create normal texture dialog with tga picture name + CDlgCreateNormalTexture dlgCreateNormalTexture( fnToRecreateNoExt+".tga"); + if( dlgCreateNormalTexture.m_bSourcePictureValid) + { + if( dlgCreateNormalTexture.DoModal() == IDOK) + { + fnResult = dlgCreateNormalTexture.m_fnCreatedFileName; + } + } + } + // else if there is pcx picture with same name + else if( GetFileAttributesA( strFullNameNoExt+".pcx") != -1) + { + // call create normal texture dialog with tga picture name + CDlgCreateNormalTexture dlgCreateNormalTexture( fnToRecreateNoExt+".pcx"); + if( dlgCreateNormalTexture.m_bSourcePictureValid) + { + if( dlgCreateNormalTexture.DoModal() == IDOK) + { + fnResult = dlgCreateNormalTexture.m_fnCreatedFileName; + } + } + } + // else if script exists + else if( GetFileAttributesA( strFullNameNoExt+".scr") != -1) + { + CDynamicArray afnScript; + CTFileName *pfnScript = afnScript.New(); + *pfnScript = fnToRecreateNoExt+".scr"; + // call create animated texture dialog with script name + CDlgCreateAnimatedTexture dlgCreateAnimatedTexture( afnScript); + dlgCreateAnimatedTexture.DoModal(); + } + else + { + WarningMessage( "Cannot find source for recreating texture: \"%s\"", (CTString&)fnTexFileToRecreate); + } + } + // reload the texture + ptdTextureToRecreate->Reload(); + // release obtained texture + _pTextureStock->Release( ptdTextureToRecreate); + } + catch( char *err_str) + { + WarningMessage( err_str); + } + } + else + { + // call choose texture type dialog + CDlgChooseTextureType dlgChooseTextureType; + int iDlgResult = dlgChooseTextureType.DoModal(); + // if user choosed a texture type + if( (iDlgResult != -1) && (iDlgResult >= 0) && (iDlgResult <= 2) ) + { + // if result is 2 we want to create effect texture + if( iDlgResult == 2) + { + // no file requester, just call dialog + CDlgCreateEffectTexture dlgCreateEffectTexture; + if( dlgCreateEffectTexture.DoModal() == IDOK) + { + fnResult = dlgCreateEffectTexture.m_fnCreatedTextureName; + if( pafnCreatedTextures != NULL) + { + CTFileName *pfnCreatedTexture = pafnCreatedTextures->New(); + *pfnCreatedTexture = fnResult; + } + } + } + // both normal and animated textures need to call open file requester + else + { + // different filters for different requests + char *pFilters = "All files (*.*)\0*.*\0\0"; + + // if dialog result is 0 we want to create normal texture + if( iDlgResult == 0) + { + pFilters = "Pictures (*.pcx;*.tga)\0*.pcx;*.tga\0" + "PCX files (*.pcx)\0*.pcx\0" + "TGA files (*.tga)\0*.tga\0\0"; + } + // if dialog result is 1 we want to create animated texture + else if( iDlgResult == 1) + { + pFilters = "Picture or script files (*.pcx;*.tga;*.scr)\0*.pcx;*.tga;*.scr\0" + "PCX files (*.pcx)\0*.pcx\0" + "TGA files (*.tga)\0*.tga\0" + "Script files (*.scr)\0;*.scr\0\0"; + } + // call file requester for opening textures + CDynamicArray afnCreateTexture; + FileRequester( "Create texture", pFilters, KEY_NAME_CREATE_TEXTURE_DIR, + "Textures\\", "", &afnCreateTexture); + if( afnCreateTexture.Count() == 0) + { + // restore resources + AfxSetResourceHandle( (HINSTANCE) hOldResource); + return CTString(""); + } + + // if requested texture type is 0 we want to create normal texture + if( iDlgResult == 0) + { + // create textures + FOREACHINDYNAMICARRAY( afnCreateTexture, CTFileName, itPicture) + { + CTFileName fnSource = itPicture.Current(); + if( (fnSource.FileExt() == ".pcx") || (fnSource.FileExt() == ".tga") ) + { + // call create normal texture dialog + CDlgCreateNormalTexture dlgCreateNormalTexture( fnSource); + if( dlgCreateNormalTexture.m_bSourcePictureValid) + { + if( dlgCreateNormalTexture.DoModal() == IDOK) + { + fnResult = dlgCreateNormalTexture.m_fnCreatedFileName; + if( pafnCreatedTextures != NULL) + { + CTFileName *pfnCreatedTexture = pafnCreatedTextures->New(); + *pfnCreatedTexture = fnResult; + } + } + } + } + } + } + // if requested texture type is 1 we want to create animated texture + else if( iDlgResult == 1) + { + // call create animated texture dialog + CDlgCreateAnimatedTexture dlgCreateAnimatedTexture( afnCreateTexture); + INDEX iDlgResult = dlgCreateAnimatedTexture.DoModal(); + if( iDlgResult == IDOK) + { + fnResult = dlgCreateAnimatedTexture.m_fnCreatedFileName; + if( pafnCreatedTextures != NULL) + { + CTFileName *pfnCreatedTexture = pafnCreatedTextures->New(); + *pfnCreatedTexture = fnResult; + } + } + } + } + } + } + // restore resources + AfxSetResourceHandle( (HINSTANCE) hOldResource); + return fnResult; +} + + + +/* Functions used by application for getting and setting registry keys concerning modes */ + +void CEngineGUI::GetFullScreenModeFromRegistry( CTString strSectionName, CDisplayMode &dm, GfxAPIType &gat) +{ + // prepare full screen mode as default + dm.dm_pixSizeI = 640; + dm.dm_pixSizeJ = 480; + dm.dm_ddDepth = DD_DEFAULT; + // read FS parameters from registry + CTString strResult = CStringA(AfxGetApp()->GetProfileString( CString(strSectionName), L"Full screen mode", L"640 x 480 x 0")); + strResult.ScanF( "%d x %d x %d", &dm.dm_pixSizeI, &dm.dm_pixSizeJ, &dm.dm_ddDepth); + if( dm.dm_ddDepthDD_32BIT) dm.dm_ddDepth = DD_DEFAULT; + strResult = CStringA(AfxGetApp()->GetProfileString( CString(strSectionName), L"Full screen API", L"OpenGL")); +#ifdef SE1_D3D + gat = (strResult=="Direct3D") ? GAT_D3D : GAT_OGL; +#else // SE1_D3D + gat = GAT_OGL; +#endif // SE1_D3D +} + + +void CEngineGUI::SetFullScreenModeToRegistry( CTString strSectionName, CDisplayMode dm, GfxAPIType gat) +{ + CTString strDM( 0, "%d x %d x %d", dm.dm_pixSizeI, dm.dm_pixSizeJ, dm.dm_ddDepth); +#ifdef SE1_D3D + CTString strGAT = (gat==GAT_D3D) ? "Direct3D" : "OpenGL"; +#else // SE1_D3D + CTString strGAT = "OpenGL"; +#endif // SE1_D3D + AfxGetApp()->WriteProfileString(CString(strSectionName), L"Full screen mode", CString(strDM)); + AfxGetApp()->WriteProfileString(CString(strSectionName), L"Full screen API", CString(strGAT)); +} diff --git a/Sources/EngineGui/EngineGUI.h b/Sources/EngineGui/EngineGUI.h new file mode 100644 index 0000000..1e3bb52 --- /dev/null +++ b/Sources/EngineGui/EngineGUI.h @@ -0,0 +1,82 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include + +#ifdef ENGINEGUI_EXPORTS + + #define ENGINEGUI_API __declspec(dllexport) + +#else + + #define ENGINEGUI_API __declspec(dllimport) + + #ifdef NDEBUG + #pragma comment(lib, "EngineGUI.lib") + #else + #pragma comment(lib, "EngineGUID.lib") + #endif + +#endif + +class CEngineGUI +{ +public: + /* Functions used by application for getting and setting registry keys concerning modes */ + ENGINEGUI_API void GetFullScreenModeFromRegistry( CTString strSectionName, CDisplayMode &dm, GfxAPIType &gat); + ENGINEGUI_API void SetFullScreenModeToRegistry( CTString strSectionName, CDisplayMode dm, GfxAPIType gat); + /* Call select mode dialog */ + ENGINEGUI_API void SelectMode( CDisplayMode &dm, GfxAPIType &gat); + + /* Call create texture dialog */ + ENGINEGUI_API CTFileName CreateTexture( CTFileName fnTexFileToRecreate = CTString(""), + CDynamicArray *pafnCreatedTextures=NULL); + +/* Predefined registry key names */ +#define KEY_NAME_REQUEST_FILE_DIR "Request file directory" +#define KEY_NAME_DETAIL_TEXTURE_DIR "Detail texture directory" +#define KEY_NAME_BASE_TEXTURE_DIR "Base texture directory" +#define KEY_NAME_CREATE_TEXTURE_DIR "Create texture directory" +#define KEY_NAME_CREATE_ANIMATED_TEXTURE_DIR "Create animated texture directory" +#define KEY_NAME_CREATE_EFFECT_TEXTURE_DIR "Create effect texture directory" +#define KEY_NAME_BACKGROUND_TEXTURE_DIR "Background texture directory" +#define KEY_NAME_REPLACE_TEXTURE_DIR "Replace texture directory" +#define KEY_NAME_SCREEN_SHOT_DIR "Screen shots directory" + +/* Predefined file filters for file requester */ +#define FILTER_ALL "All files (*.*)\0*.*\0" +#define FILTER_PICTURES "Pictures (*.pcx;*.tga)\0*.pcx;*.tga\0" +#define FILTER_3DOBJ "3D object\0*.lwo;*.obj;*.3ds\0" +#define FILTER_LWO "Lightwave object (*.lwo)\0*.lwo\0" +#define FILTER_OBJ "Alias Wavefront Object (*.obj)\0*.obj\0" +#define FILTER_3DS "3DS object (*.3ds)\0*.3ds\0" +#define FILTER_SCR "Scripts (*.scr)\0*.scr\0" +#define FILTER_PCX "PCX files (*.pcx)\0*.pcx\0" +#define FILTER_TGA "TGA files (*.tga)\0*.tga\0" +#define FILTER_TEX "Textures (*.tex)\0*.tex\0" +#define FILTER_TBN "Thumbnails (*.tbn)\0*.tbn\0" +#define FILTER_MDL "Models (*.mdl)\0*.mdl\0" +#define FILTER_WLD "Worlds (*.wld)\0*.wld\0" +#define FILTER_WAV "Sounds (*.wav)\0*.wav\0" +#define FILTER_ANI "Animations (*.ani)\0*.ani\0" +#define FILTER_TXT "Text files (*.txt)\0*.txt\0" +#define FILTER_LST "List files (*.lst)\0*.lst\0" +#define FILTER_TGA "TGA files (*.tga)\0*.tga\0" +#define FILTER_SMC "SMC files (*.smc)\0*.smc\0" +#define FILTER_END "\0" + /* File requester with thumbnail display */ + ENGINEGUI_API CTFileName FileRequester( char *pchrTitle="Choose file", + char *pchrFilters=FILTER_ALL FILTER_END, + char *pchrRegistry=KEY_NAME_REQUEST_FILE_DIR, + CTString strDefaultDir="", CTString strFileSelectedByDefault="", + CDynamicArray *pafnCreatedTextures=NULL, + BOOL bIfOpen=TRUE); + + /* Call browse texture requester */ + ENGINEGUI_API CTFileName BrowseTexture(CTFileName fnDefaultSelected=CTString(""), + char *pchrIniKeyName=KEY_NAME_REQUEST_FILE_DIR, + char *pchrWindowTitle="Choose texture", + BOOL bIfOpen=TRUE); +}; + +// global engine gui handling object +ENGINEGUI_API extern CEngineGUI _EngineGUI; diff --git a/Sources/EngineGui/EngineGUI.vcxproj b/Sources/EngineGui/EngineGUI.vcxproj new file mode 100644 index 0000000..fd016f1 --- /dev/null +++ b/Sources/EngineGui/EngineGUI.vcxproj @@ -0,0 +1,216 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + + + MFCProj + {870758F3-5C2F-D196-2A89-CC336EBE7779} + + + + Application + v120 + Unicode + + + DynamicLibrary + Dynamic + v120 + Unicode + + + DynamicLibrary + Dynamic + Unicode + v120 + + + + + + + + + + + + + + + + + + Release\ + Release\ + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + $(ProjectName) + + + Debug\ + Debug\ + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin\Debug;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + $(ProjectName)D + + + + MultiThreadedDLL + OnlyExplicitInline + false + MaxSpeed + true + Level3 + Speed + true + false + WIN32;NDEBUG;_WINDOWS;_USRDLL;ENGINEGUI_EXPORTS;_WINDLL;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\EngineGUI.pch + Use + StdH.h + .\Release\ + .\Release\ + 4996;4333 + + + true + NDEBUG;%(PreprocessorDefinitions) + .\Release\EngineGUI.tlb + true + Win32 + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\EngineGUI.bsc + + + true + true + true + Console + Release\EngineGUI.dll + .\Release\EngineGUI.lib + + + copy Release\$(TargetName).dll $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).lib $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to \Bin + $(SolutionDir)..\Bin\$(InputName).dll;%(Outputs) + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + WIN32;_DEBUG;ENGINEGUI_EXPORTS;_WINDLL;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Debug\ + .\Debug\EngineGUI.pch + Use + StdH.h + .\Debug\ + .\Debug\ + EnableFastChecks + 4996;4333 + + + true + _DEBUG;%(PreprocessorDefinitions) + .\Debug\EngineGUI.tlb + true + Win32 + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\EngineGUI.bsc + + + true + true + true + Console + Debug/EngineGUID.dll + .\Debug\EngineGUID.lib + true + + + copy Debug\$(TargetName).dll $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).lib $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(SolutionDir)..\Bin\Debug\$(InputName).dll;%(Outputs) + + + + + + + + + + + + Create + StdH.h + Create + StdH.h + + + + + + + + + + + + + + + + + + + + + Document + + + + + + + \ No newline at end of file diff --git a/Sources/EngineGui/EngineGUI.vcxproj.filters b/Sources/EngineGui/EngineGUI.vcxproj.filters new file mode 100644 index 0000000..831f968 --- /dev/null +++ b/Sources/EngineGui/EngineGUI.vcxproj.filters @@ -0,0 +1,92 @@ + + + + + {1fbec02a-e10b-46c8-9395-3a954d18a95f} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {fc8e6ee4-1976-42e9-a41b-78f6b507dadf} + h;hpp;hxx;hm;inl + + + {9c16e268-94d4-440a-ac2b-1979a0514565} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {43491365-8482-4361-90a0-59df05280571} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + Wizard Files + + + + \ No newline at end of file diff --git a/Sources/EngineGui/EngineGUI.vcxproj.user b/Sources/EngineGui/EngineGUI.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/Sources/EngineGui/EngineGUI.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Sources/EngineGui/FileRequester.cpp b/Sources/EngineGui/FileRequester.cpp new file mode 100644 index 0000000..59c551e --- /dev/null +++ b/Sources/EngineGui/FileRequester.cpp @@ -0,0 +1,325 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdh.h" +#include + +// thumbnail window +static CWnd _wndThumbnail; +CDrawPort *_pDrawPort = NULL; +CViewPort *_pViewPort = NULL; +static INDEX gui_bEnableRequesterThumbnails=TRUE; + +UINT APIENTRY FileOpenRequesterHook( HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam) +{ + _pShell->DeclareSymbol("persistent user INDEX gui_bEnableRequesterThumbnails;", &gui_bEnableRequesterThumbnails); + if( !gui_bEnableRequesterThumbnails) + { + return 0; + } + + CTextureData *pTextureData = NULL; + if( uiMsg == WM_NOTIFY) + { + // obtain file open notification structure + OFNOTIFY *pONNotify = (OFNOTIFY *) lParam; + // obtain notification message header structure + NMHDR *pNMHeader = &pONNotify->hdr; + if(pNMHeader->code == CDN_INITDONE) + { + HWND hwnd = GetDlgItem( hdlg, IDC_THUMBNAIL_RECT); + RECT rect; + BOOL bSuccess = GetClientRect( hwnd, &rect); + POINT pointParent; + pointParent.x=0; + pointParent.y=0; + POINT pointThumbnail; + pointThumbnail.x=0; + pointThumbnail.y=0; + ClientToScreen(hdlg, &pointParent); + ClientToScreen(hwnd, &pointThumbnail); + POINT point; + point.x = pointThumbnail.x-pointParent.x; + point.y = pointThumbnail.y-pointParent.y; + OffsetRect(&rect, point.x, point.y); + + if( !bSuccess) + { + ASSERT( FALSE); + return 0; + } + PIX pixLeft = 120; + PIX pixTop = 250; + // try to create thumbnail window + _wndThumbnail.Create( NULL, NULL, WS_BORDER|WS_VISIBLE, rect, + CWnd::FromHandle(hdlg), IDW_FILE_THUMBNAIL); + /*_wndThumbnail.Create( NULL, NULL, WS_BORDER|WS_VISIBLE, + CRect( pixLeft, pixTop, pixLeft+128, pixTop+128), + CWnd::FromHandle(hdlg), IDW_FILE_THUMBNAIL); + */ + // initialize canvas for thumbnail window + _pGfx->CreateWindowCanvas( _wndThumbnail.m_hWnd, &_pViewPort, &_pDrawPort); + } + char strSelectedFullPath[ PATH_MAX]; + CTFileName fnSelectedFileFullPath; + // obtain selected file's path + CommDlg_OpenSave_GetFilePath(GetParent(hdlg), &strSelectedFullPath, PATH_MAX); + // if multi select was turned on + fnSelectedFileFullPath = CTString(strSelectedFullPath); + + // try to + try + { + // remove application path + fnSelectedFileFullPath.RemoveApplicationPath_t(); + CTFileName fnThumbnail = CTString(""); + if( (fnSelectedFileFullPath.FileExt() == ".wld") || + (fnSelectedFileFullPath.FileExt() == ".mdl") ) + { + fnThumbnail = fnSelectedFileFullPath.FileDir()+fnSelectedFileFullPath.FileName()+".tbn"; + } + else if( (fnSelectedFileFullPath.FileExt() == ".tex") || + (fnSelectedFileFullPath.FileExt() == ".tbn") ) + { + fnThumbnail = fnSelectedFileFullPath; + } + else if( (fnSelectedFileFullPath.FileExt() == ".pcx") || + (fnSelectedFileFullPath.FileExt() == ".tga") ) + { + CImageInfo iiImageInfo; + iiImageInfo.LoadAnyGfxFormat_t( fnSelectedFileFullPath); + // both dimension must be potentions of 2 + if( (iiImageInfo.ii_Width == 1<<((int)Log2( iiImageInfo.ii_Width))) && + (iiImageInfo.ii_Height == 1<<((int)Log2( iiImageInfo.ii_Height))) ) + { + fnThumbnail = CTString( "Temp\\Temp.tex"); + // creates new texture with one frame + CTextureData tdForPictureConverting; + tdForPictureConverting.Create_t( &iiImageInfo, iiImageInfo.ii_Width, 1, FALSE); + tdForPictureConverting.Save_t( fnThumbnail); + } + } + if( fnThumbnail != "") + { + // obtain thumbnail + pTextureData = _pTextureStock->Obtain_t( fnThumbnail); + pTextureData->Reload(); + } + } + catch( char* err_str) + { + (void)err_str; + pTextureData = NULL; + } + + if( IsWindow( _wndThumbnail) ) + { + // if there is a valid drawport, and the drawport can be locked + if( (_pDrawPort != NULL) && (_pDrawPort->Lock()) ) + { + PIXaabbox2D rectPict; + rectPict = PIXaabbox2D( PIX2D(0, 0), + PIX2D(_pDrawPort->GetWidth(), _pDrawPort->GetHeight())); + // clear texture area to black + _pDrawPort->Fill( C_BLACK|CT_OPAQUE); + // erase z-buffer + _pDrawPort->FillZBuffer(ZBUF_BACK); + // if there is valid active texture + if( pTextureData != NULL) + { + CTextureObject toPreview; + toPreview.SetData( pTextureData); + _pDrawPort->PutTexture( &toPreview, rectPict); + CWnd::FromHandle( GetDlgItem( hdlg, IDC_THUMBNAIL_DESCRIPTION))->SetWindowText( + CString(pTextureData->GetDescription())); + // release the texture + _pTextureStock->Release( pTextureData); + } + else + { + // no thumbnail, draw crossed lines + PIX pixRad = Max( _pDrawPort->GetWidth(), _pDrawPort->GetWidth()) * 3/4/2; + PIX CX = _pDrawPort->GetWidth()/2; + PIX CY = _pDrawPort->GetWidth()/2; + for( INDEX iPix=-2;iPix<2;iPix++) + { + _pDrawPort->DrawLine( CX-pixRad+iPix, CY-pixRad, CX+pixRad+iPix, CY+pixRad, C_RED|CT_OPAQUE); + _pDrawPort->DrawLine( CX-pixRad+iPix, CY+pixRad, CX+pixRad+iPix, CY-pixRad, C_RED|CT_OPAQUE); + } + CWnd::FromHandle( GetDlgItem( hdlg, IDC_THUMBNAIL_DESCRIPTION))->SetWindowText( L"No thumbnail"); + } + // unlock the drawport + _pDrawPort->Unlock(); + } + + // if there is a valid viewport + if (_pViewPort!=NULL) + { + // swap it + _pViewPort->SwapBuffers(); + } + } + } + return 0; +} + +CTFileName CEngineGUI::FileRequester( + char *pchrTitle/*="Choose file"*/, + char *pchrFilters/*=FILTER_ALL FILTER_END*/, + char *pchrRegistry/*="KEY_NAME_REQUEST_FILE_DIR"*/, + CTString strDefaultDir/*=""*/, + CTString strFileSelectedByDefault/*=""*/, + CDynamicArray *pafnSelectedFiles/*=NULL*/, + BOOL bIfOpen/*=TRUE*/) +{ + _pDrawPort = NULL; + _pViewPort = NULL; + // stupid way to change resources, but it must be done + HANDLE hOldResource = AfxGetResourceHandle(); + // activate CTGfx resources + AfxSetResourceHandle( GetModuleHandleA(ENGINEGUI_DLL_NAME) ); + + // call multiple file requester + char chrFiles[ 2048]; + OPENFILENAMEA ofnRequestFiles; + + memset( &ofnRequestFiles, 0, sizeof( OPENFILENAME)); + ofnRequestFiles.lStructSize = sizeof(OPENFILENAME); + ofnRequestFiles.hwndOwner = AfxGetMainWnd()->m_hWnd; + ofnRequestFiles.lpstrFilter = pchrFilters; + ofnRequestFiles.lpstrFile = chrFiles; + sprintf( chrFiles, "%s", strFileSelectedByDefault); + ofnRequestFiles.nMaxFile = 2048; + + CString strRequestInDirectory = _fnmApplicationPath+strDefaultDir; + if( pchrRegistry != NULL) + { + strRequestInDirectory = AfxGetApp()->GetProfileString(L"Scape", CString(pchrRegistry), + CString(_fnmApplicationPath+strDefaultDir)); + } + + // if directory is not inside engine dir + CTString strTest = CStringA(strRequestInDirectory); + if (!strTest.RemovePrefix(_fnmApplicationPath)) { + // force it there + strRequestInDirectory = _fnmApplicationPath; + } + + + ofnRequestFiles.lpstrInitialDir = CStringA(strRequestInDirectory); + ofnRequestFiles.lpstrTitle = pchrTitle; + ofnRequestFiles.Flags = OFN_EXPLORER | OFN_ENABLEHOOK | OFN_ENABLETEMPLATE | OFN_HIDEREADONLY; + // setup preview dialog + ofnRequestFiles.lpfnHook = &::FileOpenRequesterHook; + ofnRequestFiles.hInstance = GetModuleHandleA(ENGINEGUI_DLL_NAME); + ofnRequestFiles.lpTemplateName = MAKEINTRESOURCEA( IDD_GFX_FILE_REQUESTER); + // allow multi select + if( pafnSelectedFiles != NULL) ofnRequestFiles.Flags |= OFN_ALLOWMULTISELECT; + + ofnRequestFiles.lpstrDefExt = ""; + + BOOL bResult; + if( bIfOpen) + { + bResult = GetOpenFileNameA( &ofnRequestFiles); + } + else + { + bResult = GetSaveFileNameA( &ofnRequestFiles); + } + + if( bResult) + { + // if multiple file requester is called + if( pafnSelectedFiles != NULL) + { + chrFiles[ ofnRequestFiles.nFileOffset-1] = 0; + if( pchrRegistry != NULL) + { + AfxGetApp()->WriteProfileString(L"Scape", CString(pchrRegistry), CString(chrFiles)); + } + CTFileName fnDirectory = CTString( chrFiles) + "\\"; + + INDEX iOffset = ofnRequestFiles.nFileOffset; + FOREVER + { + try + { + if( CTString( chrFiles + iOffset) == "") + { + // restore resources + AfxSetResourceHandle( (HINSTANCE) hOldResource); + return( CTString( "Multiple files selected")); + } + CTFileName fnSource = fnDirectory + CTString( chrFiles + iOffset); + // remove application path + fnSource.RemoveApplicationPath_t(); + CTFileName *pfnSelectedFile = pafnSelectedFiles->New(); + *pfnSelectedFile = fnSource; + } + catch( char *strError) + { + WarningMessage( strError); + // restore resources + AfxSetResourceHandle( (HINSTANCE) hOldResource); + // return error + return( CTString( "")); + } + iOffset += strlen( chrFiles + iOffset) + 1; + } + } + else + { + CString strChooseFilePath = chrFiles; + strChooseFilePath.SetAt( ofnRequestFiles.nFileOffset, 0); + if( pchrRegistry != NULL) + { + AfxGetApp()->WriteProfileString(L"Scape", CString(pchrRegistry), strChooseFilePath); + } + CTFileName fnResult = CTString( chrFiles); + try + { + fnResult.RemoveApplicationPath_t(); + } + catch( char *strError) + { + WarningMessage( strError); + // restore resources + AfxSetResourceHandle( (HINSTANCE) hOldResource); + // return error + return( CTString( "")); + } + // restore resources + AfxSetResourceHandle( (HINSTANCE) hOldResource); + return fnResult; + } + } + if( _pViewPort != NULL) + { + _pGfx->DestroyWindowCanvas( _pViewPort); + _pViewPort = NULL; + } + // restore resources + AfxSetResourceHandle( (HINSTANCE) hOldResource); + // return error + return CTString( ""); +} + +ENGINEGUI_API CTFileName FileRequester( + char *pchrTitle, + char *pchrFilters, + char *pchrRegistry, + char *pchrFileSelectedByDefault) +{ + return _EngineGUI.FileRequester(pchrTitle, pchrFilters, pchrRegistry, "", pchrFileSelectedByDefault); +} + + +CTFileName CEngineGUI::BrowseTexture(CTFileName fnDefaultSelected/*=""*/, + char *pchrIniKeyName/*=KEY_NAME_REQUEST_FILE_DIR*/, + char *pchrWindowTitle/*="Choose texture"*/, + BOOL bIfOpen/*=TRUE*/) +{ + return FileRequester( pchrWindowTitle, FILTER_TEX FILTER_END, pchrIniKeyName, + "Textures\\", fnDefaultSelected, NULL, bIfOpen); +} + diff --git a/Sources/EngineGui/Graphics.clw b/Sources/EngineGui/Graphics.clw new file mode 100644 index 0000000..f584fc7 --- /dev/null +++ b/Sources/EngineGui/Graphics.clw @@ -0,0 +1,301 @@ +; CLW file contains information for the MFC ClassWizard + +[General Info] +Version=1 +LastClass=CDlgCreateNormalTexture +LastTemplate=generic CWnd +NewFileInclude1=#include "stdafx.h" +NewFileInclude2=#include "ctgfx.h" +LastPage=0 + +ClassCount=7 + +ResourceCount=12 +Class1=CDlgSelectMode +Resource1=IDD_CREATE_NORMAL_TEXTURE +Class2=CDlgCreateAnimatedTexture +Resource2=IDD_SELECT_MODE_DIALOG +Resource3=IDD_CHOOSE_TEXTURE_TYPE +Resource4=IDD_CREATE_EFFECT_TEXTURE +Class3=CDlgChooseTextureType +Class4=CDlgCreateNormalTexture +Class5=CDlgCreateEffectTexture +Class6=CWndDetailTexture +Class7=CWndDisplayTexture +Resource5=IDD_CREATE_ANIMATED_TEXTURE +Resource6=IDD_CHOOSE_TEXTURE_TYPE (English (U.S.)) +Resource7=IDD_SELECT_MODE_DIALOG (English (U.S.)) +Resource8=IDD_CREATE_ANIMATED_TEXTURE (English (U.S.)) +Resource9=IDD_CREATE_NORMAL_TEXTURE (English (U.S.)) +Resource10=IDD_CREATE_EFFECT_TEXTURE (English (U.S.)) +Resource11=IDD_DIALOG2 +Resource12=IDD_GFX_FILE_REQUESTER + +[DLG:IDD_SELECT_MODE_DIALOG] +Type=1 +Class=CDlgSelectMode +ControlCount=17 +Control1=IDC_API,combobox,1344339971 +Control2=IDC_RESOLUTIONS,combobox,1344339971 +Control3=IDC_COLOR_DEFAULT,button,1342373897 +Control4=IDC_COLOR_HIGH,button,1342242825 +Control5=IDC_COLOR_TRUE,button,1342242825 +Control6=ID_TEST_BUTTON,button,1342242817 +Control7=IDOK,button,1342242816 +Control8=IDCANCEL,button,1342242816 +Control9=IDC_CURRENT_MODE,static,1342308352 +Control10=IDC_STATIC,static,1342308352 +Control11=IDC_STATIC,static,1342308352 +Control12=IDC_STATIC,static,1342308354 +Control13=IDC_STATIC,static,1342308352 +Control14=IDC_STATIC,static,1342308352 +Control15=IDC_CURRENT_DRIVER,static,1342308352 +Control16=IDC_STATIC,button,1342177287 +Control17=IDC_STATIC,button,1342177287 + +[CLS:CDlgSelectMode] +Type=0 +HeaderFile=DlgSelectMode.h +ImplementationFile=DlgSelectMode.cpp +BaseClass=CDialog +Filter=D +LastObject=IDC_COLOR_HIGH +VirtualFilter=dWC + +[DLG:IDD_CREATE_ANIMATED_TEXTURE] +Type=1 +Class=CDlgCreateAnimatedTexture +ControlCount=13 +Control1=IDC_EDIT_SCRIPT,edit,1352732868 +Control2=ID_REFRESH_TEXTURE,button,1342242816 +Control3=IDC_TEXTURE_PREVIEW_WINDOW,static,1350569991 +Control4=IDC_STATIC,static,1342308352 +Control5=IDC_SIZE_IN_PIXELS,static,1342308352 +Control6=IDC_STATIC,static,1342308352 +Control7=IDC_TEXTURE_ANIMATIONS,combobox,1344339971 +Control8=IDC_CHEQUERED_ALPHA,button,1342242819 +Control9=ID_CREATE_TEXTURE,button,1342242817 +Control10=IDCANCEL,button,1342242816 +Control11=IDC_STATIC,static,1342308353 +Control12=IDC_STATIC,static,1342308352 +Control13=IDC_TEXTURE_NAME,static,1342308352 + +[DLG:IDD_CREATE_NORMAL_TEXTURE] +Type=1 +Class=CDlgCreateNormalTexture +ControlCount=12 +Control1=IDC_CREATED_TEXTURE_NAME,static,1342312448 +Control2=IDC_STATIC,static,1342308352 +Control3=IDC_STATIC,static,1342308352 +Control4=IDC_MEX_SIZE,combobox,1344339971 +Control5=IDC_TEXTURE_PREVIEW_WINDOW,static,1350569991 +Control6=IDC_CHEQUERED_ALPHA,button,1342242819 +Control7=ID_CREATE_TEXTURE,button,1342242817 +Control8=IDCANCEL,button,1342242816 +Control9=IDC_SIZE_IN_PIXELS,static,1342308352 +Control10=IDC_STATIC,static,1342308353 +Control11=IDC_FORCE32,button,1342242819 +Control12=IDC_CREATE_MIPMAPS,button,1342242819 + +[DLG:IDD_CREATE_EFFECT_TEXTURE] +Type=1 +Class=CDlgCreateEffectTexture +ControlCount=22 +Control1=IDC_MEX_SIZE,combobox,1344339971 +Control2=IDC_STATIC,static,1342308352 +Control3=IDC_STATIC,static,1342308353 +Control4=IDC_EFFECT_CLASS,combobox,1344339971 +Control5=IDC_STATIC,static,1342308354 +Control6=IDC_PIX_WIDTH,combobox,1344339971 +Control7=IDC_STATIC,static,1342308354 +Control8=IDC_PIX_HEIGHT,combobox,1344339971 +Control9=IDC_STATIC,static,1342308352 +Control10=IDC_TEXTURE_PREVIEW_WINDOW,static,1350569991 +Control11=IDC_STATIC,static,1342308352 +Control12=ID_BROWSE_BASE,button,1342242816 +Control13=IDC_CHEQUERED_ALPHA,button,1342242819 +Control14=IDC_STATIC,static,1342308353 +Control15=IDC_EFFECT_TYPE,combobox,1344339971 +Control16=ID_REMOVE_ALL_EFFECTS,button,1342242816 +Control17=ID_CREATE,button,1342242817 +Control18=IDCANCEL,button,1342242816 +Control19=IDC_BASE_TEXTURE_NAME,static,1342312448 +Control20=IDC_CREATED_TEXTURE_NAME,static,1342312448 +Control21=ID_CREATE_AS,button,1342242816 +Control22=IDC_REND_SPEED,static,1342308352 + +[DLG:IDD_CHOOSE_TEXTURE_TYPE] +Type=1 +Class=CDlgChooseTextureType +ControlCount=4 +Control1=ID_NORMAL_TEXTURE,button,1342242817 +Control2=ID_ANIMATED_TEXTURE,button,1342242816 +Control3=ID_EFFECT_TEXTURE,button,1342242816 +Control4=IDCANCEL,button,1342242816 + +[CLS:CDlgChooseTextureType] +Type=0 +HeaderFile=DlgChooseTextureType.h +ImplementationFile=DlgChooseTextureType.cpp +BaseClass=CDialog +Filter=D +LastObject=CDlgChooseTextureType +VirtualFilter=dWC + +[CLS:CDlgCreateNormalTexture] +Type=0 +HeaderFile=DlgCreateNormalTexture.h +ImplementationFile=DlgCreateNormalTexture.cpp +BaseClass=CDialog +Filter=D +LastObject=IDC_CREATE_MIPMAPS +VirtualFilter=dWC + +[CLS:CDlgCreateAnimatedTexture] +Type=0 +HeaderFile=DlgCreateAnimatedTexture.h +ImplementationFile=DlgCreateAnimatedTexture.cpp +BaseClass=CDialog +Filter=D +LastObject=CDlgCreateAnimatedTexture +VirtualFilter=dWC + +[CLS:CDlgCreateEffectTexture] +Type=0 +HeaderFile=DlgCreateEffectTexture.h +ImplementationFile=DlgCreateEffectTexture.cpp +BaseClass=CDialog +Filter=D +LastObject=IDC_REND_SPEED +VirtualFilter=dWC + +[CLS:CWndDetailTexture] +Type=0 +HeaderFile=WndDetailTexture.h +ImplementationFile=WndDetailTexture.cpp +BaseClass=CWnd +Filter=W +LastObject=CWndDetailTexture +VirtualFilter=WC + +[CLS:CWndDisplayTexture] +Type=0 +HeaderFile=WndDisplayTexture.h +ImplementationFile=WndDisplayTexture.cpp +BaseClass=CWnd +Filter=W +LastObject=IDC_THUMBNAIL_DESCRIPTION +VirtualFilter=WC + +[DLG:IDD_CREATE_EFFECT_TEXTURE (English (U.S.))] +Type=1 +Class=CDlgCreateEffectTexture +ControlCount=22 +Control1=IDC_MEX_SIZE,combobox,1344339971 +Control2=IDC_STATIC,static,1342308352 +Control3=IDC_STATIC,static,1342308353 +Control4=IDC_EFFECT_CLASS,combobox,1344339971 +Control5=IDC_STATIC,static,1342308352 +Control6=IDC_PIX_WIDTH,combobox,1344339971 +Control7=IDC_STATIC,static,1342308353 +Control8=IDC_PIX_HEIGHT,combobox,1344339971 +Control9=IDC_STATIC,static,1342308352 +Control10=IDC_TEXTURE_PREVIEW_WINDOW,static,1342177287 +Control11=IDC_STATIC,static,1342308352 +Control12=ID_BROWSE_BASE,button,1342242816 +Control13=IDC_CHEQUERED_ALPHA,button,1342242819 +Control14=IDC_STATIC,static,1342308353 +Control15=IDC_EFFECT_TYPE,combobox,1344339971 +Control16=ID_REMOVE_ALL_EFFECTS,button,1342242816 +Control17=ID_CREATE,button,1342242817 +Control18=IDCANCEL,button,1342242816 +Control19=IDC_BASE_TEXTURE_NAME,static,1342308352 +Control20=IDC_CREATED_TEXTURE_NAME,static,1342308352 +Control21=ID_CREATE_AS,button,1342242816 +Control22=IDC_FRAME_RATE,static,1342308352 + +[DLG:IDD_SELECT_MODE_DIALOG (English (U.S.))] +Type=1 +ControlCount=15 +Control1=IDC_CURRENT_VIDEO_MODE_T,button,1342178055 +Control2=IDC_CURRENT_MODE,static,1342308352 +Control3=IDC_NEW_VIDEO_MODE_T,button,1342178055 +Control4=IDC_STATIC,static,1342308352 +Control5=IDC_SELECTED_DRIVER,static,1342308352 +Control6=IDC_STATIC,static,1342308352 +Control7=IDC_SELECTED_RESOLUTION,static,1342308352 +Control8=IDC_STATIC,static,1342308352 +Control9=IDC_SELECTED_NO_OF_COLORS,static,1342308352 +Control10=IDC_STATIC,static,1342308352 +Control11=IDC_SELECTED_NO_OF_TEXTURE_COLORS,static,1342308352 +Control12=IDC_VIDEO_MODES_TREE,SysTreeView32,1350631479 +Control13=ID_TEST_BUTTON,button,1342242817 +Control14=IDOK,button,1342242816 +Control15=IDCANCEL,button,1342242816 +Class=CDlgSelectMode + +[DLG:IDD_CREATE_ANIMATED_TEXTURE (English (U.S.))] +Type=1 +ControlCount=17 +Control1=IDC_EDIT_SCRIPT,edit,1352732868 +Control2=ID_REFRESH_TEXTURE,button,1342242816 +Control3=IDC_TEXTURE_PREVIEW_WINDOW,static,1342177287 +Control4=IDC_STATIC,static,1342308352 +Control5=IDC_SIZE_IN_PIXELS,static,1342308352 +Control6=IDC_STATIC,static,1342308353 +Control7=IDC_TEXTURE_ANIMATIONS,combobox,1344339971 +Control8=IDC_STATIC,static,1342308353 +Control9=IDC_DETAIL_TEXTURE_WINDOW,static,1342177287 +Control10=ID_BROWSE_DETAIL,button,1342242816 +Control11=ID_DETAIL_NONE,button,1342242816 +Control12=IDC_CHEQUERED_ALPHA,button,1342242819 +Control13=ID_CREATE_TEXTURE,button,1342242817 +Control14=IDCANCEL,button,1342242816 +Control15=IDC_STATIC,static,1342308353 +Control16=IDC_STATIC,static,1342308352 +Control17=IDC_TEXTURE_NAME,static,1342308352 +Class=CDlgCreateAnimatedTexture + +[DLG:IDD_CREATE_NORMAL_TEXTURE (English (U.S.))] +Type=1 +ControlCount=16 +Control1=IDC_STATIC,static,1342308352 +Control2=IDC_CREATED_TEXTURE_NAME,static,1342308352 +Control3=IDC_STATIC,static,1342308352 +Control4=IDC_STATIC,static,1342308352 +Control5=IDC_MEX_SIZE,combobox,1344339971 +Control6=IDC_STATIC,static,1342308352 +Control7=IDC_MIP_MAPS,combobox,1344339971 +Control8=IDC_TEXTURE_PREVIEW_WINDOW,static,1342177287 +Control9=IDC_STATIC,static,1342308353 +Control10=IDC_DETAIL_TEXTURE_WINDOW,static,1342177287 +Control11=ID_BROWSE_DETAIL,button,1342242816 +Control12=ID_DETAIL_NONE,button,1342242816 +Control13=IDC_CHEQUERED_ALPHA,button,1342242819 +Control14=ID_CREATE_TEXTURE,button,1342242817 +Control15=IDCANCEL,button,1342242816 +Control16=IDC_SIZE_IN_PIXELS,static,1342308352 +Class=CDlgCreateNormalTexture + +[DLG:IDD_CHOOSE_TEXTURE_TYPE (English (U.S.))] +Type=1 +ControlCount=4 +Control1=ID_NORMAL_TEXTURE,button,1342242817 +Control2=ID_ANIMATED_TEXTURE,button,1342242816 +Control3=ID_EFFECT_TEXTURE,button,1342242816 +Control4=IDCANCEL,button,1342242816 +Class=CDlgChooseTextureType + +[DLG:IDD_DIALOG2] +Type=1 +ControlCount=2 +Control1=IDOK,button,1342242817 +Control2=IDCANCEL,button,1342242816 + +[DLG:IDD_GFX_FILE_REQUESTER] +Type=1 +Class=? +ControlCount=2 +Control1=IDC_THUMBNAIL_DESCRIPTION,static,1342308353 +Control2=IDC_THUMBNAIL_RECT,static,1073741831 + diff --git a/Sources/EngineGui/Graphics.rc b/Sources/EngineGui/Graphics.rc new file mode 100644 index 0000000..fb2a0f3 --- /dev/null +++ b/Sources/EngineGui/Graphics.rc @@ -0,0 +1,319 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SELECT_MODE_DIALOG DIALOG DISCARDABLE 0, 0, 144, 168 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select full screen mode" +FONT 8, "MS Sans Serif" +BEGIN + COMBOBOX IDC_API,64,62,53,100,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + COMBOBOX IDC_RESOLUTIONS,64,81,52,81,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + CONTROL "Default",IDC_COLOR_DEFAULT,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,80,101,48,8 + CONTROL "High Color",IDC_COLOR_HIGH,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,80,112,48,8 + CONTROL "True Color",IDC_COLOR_TRUE,"Button",BS_AUTORADIOBUTTON | + WS_TABSTOP,80,122,48,10 + DEFPUSHBUTTON "&Test",ID_TEST_BUTTON,15,116,40,14 + PUSHBUTTON "&Apply",IDOK,7,148,46,14 + PUSHBUTTON "Cancel",IDCANCEL,89,148,48,14 + LTEXT "W x H x BPP",IDC_CURRENT_MODE,64,30,66,8 + LTEXT "Display API:",IDC_STATIC,18,65,44,8 + LTEXT "Resolution:",IDC_STATIC,21,84,35,8 + RTEXT "Colors:",IDC_STATIC,52,101,22,8 + LTEXT "Display mode:",IDC_STATIC,13,30,45,8 + LTEXT "Display API:",IDC_STATIC,13,19,44,8 + LTEXT "OpenGL or Direct3D",IDC_CURRENT_DRIVER,64,19,66,8 + GROUPBOX "Current settings",IDC_STATIC,7,8,130,34 + GROUPBOX "New settings",IDC_STATIC,7,49,130,89 +END + +IDD_CREATE_EFFECT_TEXTURE DIALOG DISCARDABLE 0, 0, 296, 192 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Create effect texture" +FONT 8, "MS Sans Serif" +BEGIN + COMBOBOX IDC_MEX_SIZE,224,50,69,75,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + LTEXT "Effect texture:",IDC_STATIC,3,7,44,8 + CTEXT "Effect class:",IDC_STATIC,178,66,115,8 + COMBOBOX IDC_EFFECT_CLASS,178,75,115,75,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + RTEXT "Width:",IDC_STATIC,176,34,21,8 + COMBOBOX IDC_PIX_WIDTH,198,32,31,75,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + RTEXT "Height:",IDC_STATIC,236,34,23,8 + COMBOBOX IDC_PIX_HEIGHT,262,32,31,75,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + LTEXT "Size (meters):",IDC_STATIC,178,53,46,8 + CONTROL "",IDC_TEXTURE_PREVIEW_WINDOW,"Static",SS_BLACKFRAME | + SS_SUNKEN | WS_BORDER,3,32,170,157 + LTEXT "Base texture:",IDC_STATIC,3,18,48,8 + PUSHBUTTON "&...",ID_BROWSE_BASE,273,17,19,12 + CONTROL "&Chequered background",IDC_CHEQUERED_ALPHA,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,183,180,87,10 + CTEXT "Effect",IDC_STATIC,178,90,115,8 + COMBOBOX IDC_EFFECT_TYPE,178,99,115,75,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Remove &FX",ID_REMOVE_ALL_EFFECTS,182,160,50,14 + DEFPUSHBUTTON "C&reate",ID_CREATE,182,140,50,14 + PUSHBUTTON "Cancel",IDCANCEL,239,160,50,14 + LTEXT "Textures\\Effect\\Bases\\WaterBase01.tex", + IDC_BASE_TEXTURE_NAME,49,18,218,10,SS_SUNKEN + LTEXT "Textures\\Effects\\Water01.tex", + IDC_CREATED_TEXTURE_NAME,49,6,243,10,SS_SUNKEN + PUSHBUTTON "Create &As",ID_CREATE_AS,239,140,50,14 + LTEXT "Rendering speed: 0000",IDC_REND_SPEED,182,120,86,8 +END + +IDD_CREATE_ANIMATED_TEXTURE DIALOG DISCARDABLE 0, 0, 343, 204 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Create animated texture using script" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_SCRIPT,178,27,162,138,ES_MULTILINE | + ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | + WS_VSCROLL + PUSHBUTTON "Re&fresh",ID_REFRESH_TEXTURE,178,187,50,14 + CONTROL "",IDC_TEXTURE_PREVIEW_WINDOW,"Static",SS_BLACKFRAME | + SS_SUNKEN | WS_BORDER,3,27,170,157 + LTEXT "Texture name:",IDC_STATIC,3,4,46,8 + LTEXT "256 x 128",IDC_SIZE_IN_PIXELS,58,14,120,8 + LTEXT "Animation:",IDC_STATIC,180,172,38,8 + COMBOBOX IDC_TEXTURE_ANIMATIONS,220,171,120,75,CBS_DROPDOWNLIST | + WS_VSCROLL | WS_TABSTOP + CONTROL "&Chequered background",IDC_CHEQUERED_ALPHA,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,4,190,87,8 + DEFPUSHBUTTON "C&reate",ID_CREATE_TEXTURE,235,187,50,14 + PUSHBUTTON "Cancel",IDCANCEL,290,187,50,14 + CTEXT "Script",IDC_STATIC,246,14,25,9 + LTEXT "Size in pixels:",IDC_STATIC,3,14,46,8 + LTEXT "Textures\\Effect\\Fire\\Burning.tex",IDC_TEXTURE_NAME, + 58,4,282,8 +END + +IDD_CREATE_NORMAL_TEXTURE DIALOGEX 0, 0, 281, 180 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Create normal texture" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Textures\\Effects\\Fire.tex",IDC_CREATED_TEXTURE_NAME, + 52,5,226,10,SS_SUNKEN + LTEXT "Size in pixels:",IDC_STATIC,180,21,44,8 + LTEXT "Size in meters:",IDC_STATIC,178,38,45,8 + COMBOBOX IDC_MEX_SIZE,227,36,51,75,CBS_DROPDOWNLIST | WS_VSCROLL | + WS_TABSTOP + CONTROL "",IDC_TEXTURE_PREVIEW_WINDOW,"Static",SS_BLACKFRAME | + SS_SUNKEN | WS_BORDER,3,20,170,157,WS_EX_STATICEDGE + CONTROL "Chequered &background",IDC_CHEQUERED_ALPHA,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,178,167,87,10 + DEFPUSHBUTTON "C&reate",ID_CREATE_TEXTURE,178,147,49,14 + PUSHBUTTON "Cancel",IDCANCEL,232,147,46,14 + LTEXT "1024 x 1024",IDC_SIZE_IN_PIXELS,227,21,35,8 + CTEXT "Texture name:",IDC_STATIC,3,6,48,8 + CONTROL "Preserve 32-bit &quality",IDC_FORCE32,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,178,66,100,10 + CONTROL "&Create mipmaps",IDC_CREATE_MIPMAPS,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,178,55,100,10 +END + +IDD_CHOOSE_TEXTURE_TYPE DIALOG DISCARDABLE 0, 0, 97, 101 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Choose texture type" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "&Normal texture",ID_NORMAL_TEXTURE,7,7,83,14 + PUSHBUTTON "&Animated texture",ID_ANIMATED_TEXTURE,7,27,83,14 + PUSHBUTTON "E&ffect texture",ID_EFFECT_TEXTURE,7,48,83,14 + PUSHBUTTON "Cancel",IDCANCEL,24,77,50,13 +END + +IDD_GFX_FILE_REQUESTER DIALOG DISCARDABLE 0, 0, 250, 86 +STYLE DS_CONTROL | WS_CHILD | WS_CLIPSIBLINGS +FONT 8, "MS Sans Serif" +BEGIN + CTEXT "Thumbnail description",IDC_THUMBNAIL_DESCRIPTION,32,73, + 180,8 + CONTROL "",IDC_THUMBNAIL_RECT,"Static",SS_BLACKFRAME | NOT + WS_VISIBLE,89,10,66,57 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_SELECT_MODE_DIALOG, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 137 + VERTGUIDE, 7 + VERTGUIDE, 64 + VERTGUIDE, 130 + TOPMARGIN, 10 + BOTTOMMARGIN, 162 + HORZGUIDE, 21 + HORZGUIDE, 29 + HORZGUIDE, 42 + HORZGUIDE, 50 + END + + IDD_CREATE_EFFECT_TEXTURE, DIALOG + BEGIN + LEFTMARGIN, 3 + RIGHTMARGIN, 293 + VERTGUIDE, 34 + VERTGUIDE, 51 + VERTGUIDE, 139 + VERTGUIDE, 178 + VERTGUIDE, 210 + VERTGUIDE, 224 + VERTGUIDE, 243 + TOPMARGIN, 3 + BOTTOMMARGIN, 189 + HORZGUIDE, 15 + HORZGUIDE, 32 + HORZGUIDE, 48 + HORZGUIDE, 66 + HORZGUIDE, 92 + END + + IDD_CREATE_ANIMATED_TEXTURE, DIALOG + BEGIN + LEFTMARGIN, 3 + RIGHTMARGIN, 340 + VERTGUIDE, 58 + VERTGUIDE, 121 + VERTGUIDE, 178 + VERTGUIDE, 209 + VERTGUIDE, 286 + TOPMARGIN, 3 + BOTTOMMARGIN, 201 + HORZGUIDE, 12 + HORZGUIDE, 22 + HORZGUIDE, 27 + HORZGUIDE, 39 + HORZGUIDE, 92 + HORZGUIDE, 201 + END + + IDD_CREATE_NORMAL_TEXTURE, DIALOG + BEGIN + LEFTMARGIN, 3 + RIGHTMARGIN, 278 + VERTGUIDE, 178 + VERTGUIDE, 229 + VERTGUIDE, 234 + TOPMARGIN, 3 + BOTTOMMARGIN, 177 + HORZGUIDE, 15 + HORZGUIDE, 35 + HORZGUIDE, 55 + END + + IDD_CHOOSE_TEXTURE_TYPE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 90 + VERTGUIDE, 53 + TOPMARGIN, 7 + BOTTOMMARGIN, 90 + END + + IDD_GFX_FILE_REQUESTER, DIALOG + BEGIN + BOTTOMMARGIN, 80 + END +END +#endif // APSTUDIO_INVOKED + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_MODE_BROWSING_ICONS BITMAP DISCARDABLE "mode_bro.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDW_FILE_THUMBNAIL "Thumbnail" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Sources/EngineGui/ReadMe.txt b/Sources/EngineGui/ReadMe.txt new file mode 100644 index 0000000..e2e240b --- /dev/null +++ b/Sources/EngineGui/ReadMe.txt @@ -0,0 +1,37 @@ +======================================================================== + DYNAMIC LINK LIBRARY : EngineGUI +======================================================================== + + +AppWizard has created this EngineGUI DLL for you. + +This file contains a summary of what you will find in each of the files that +make up your EngineGUI application. + +EngineGUI.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +EngineGUI.cpp + This is the main DLL source file. + +EngineGUI.h + This file contains your DLL exports. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named EngineGUI.pch and a precompiled types file named StdAfx.obj. + + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + + +///////////////////////////////////////////////////////////////////////////// diff --git a/Sources/EngineGui/StdH.cpp b/Sources/EngineGui/StdH.cpp new file mode 100644 index 0000000..95c0896 --- /dev/null +++ b/Sources/EngineGui/StdH.cpp @@ -0,0 +1,3 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" diff --git a/Sources/EngineGui/StdH.h b/Sources/EngineGui/StdH.h new file mode 100644 index 0000000..af830d7 --- /dev/null +++ b/Sources/EngineGui/StdH.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include // MFC support for Windows Common Controls +#include + +#define ENGINE_INTERNAL 1 +#define ENGINEGUI_EXPORTS 1 +#include + +#include "Resource.h" +#include "DlgSelectMode.h" +#include "WndDisplayTexture.h" +#include "DlgChooseTextureType.h" +#include "DlgCreateNormalTexture.h" +#include "DlgCreateAnimatedTexture.h" +#include "DlgCreateEffectTexture.h" + +// this is needed for resource setting +#ifndef NDEBUG + #define ENGINEGUI_DLL_NAME "EngineGUID.dll" +#else + #define ENGINEGUI_DLL_NAME "EngineGUI.dll" +#endif + diff --git a/Sources/EngineGui/WndDisplayTexture.cpp b/Sources/EngineGui/WndDisplayTexture.cpp new file mode 100644 index 0000000..e3f0aac --- /dev/null +++ b/Sources/EngineGui/WndDisplayTexture.cpp @@ -0,0 +1,299 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// WndDisplayTexture.cpp : implementation file +// + +#include "StdH.h" +#include + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CWndDisplayTexture + +TIME timeLastTick; + +CWndDisplayTexture::CWndDisplayTexture() +{ + m_pLeftMouseButtonClicked = NULL; + m_pLeftMouseButtonReleased = NULL; + m_pRightMouseButtonClicked = NULL; + m_pRightMouseButtonMoved = NULL; + m_pDrawPort = NULL; + m_pViewPort = NULL; + m_iTimerID = -1; + m_bChequeredAlpha = TRUE; + m_bForce32 = FALSE; + m_bDrawLine = FALSE; +} + +CWndDisplayTexture::~CWndDisplayTexture() +{ +} + + +BEGIN_MESSAGE_MAP(CWndDisplayTexture, CWnd) + //{{AFX_MSG_MAP(CWndDisplayTexture) + ON_WM_DESTROY() + ON_WM_PAINT() + ON_WM_TIMER() + ON_WM_LBUTTONDOWN() + ON_WM_RBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_MOUSEMOVE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +///////////////////////////////////////////////////////////////////////////// +// CWndDisplayTexture message handlers + +// converts window mouse coordinates to buffer coordinates +static void ConvertCoords( CTextureData *pTD, PIX &pixU, PIX &pixV) +{ + +} + +void CWndDisplayTexture::OnPaint() +{ + { CPaintDC dc(this); } // device context for painting + + if( m_iTimerID==-1) m_iTimerID = (int)SetTimer( 1, 50, NULL); + + if( m_pViewPort==NULL && m_pDrawPort==NULL) + { // initialize canvas for active texture button + _pGfx->CreateWindowCanvas( m_hWnd, &m_pViewPort, &m_pDrawPort); + } + + // get texture data + CTextureData *pTD = (CTextureData*)m_toTexture.GetData(); + BOOL bAlphaChannel = FALSE; + // if there is a valid drawport, and the drawport can be locked + if( m_pDrawPort!=NULL && m_pDrawPort->Lock()) + { // if it has any texture + if( pTD!=NULL) { + PIX pixWidth = pTD->GetPixWidth(); + PIX pixHeight = pTD->GetPixHeight(); + // adjust for effect texture + if( pTD->td_ptegEffect != NULL) { + pixWidth = pTD->td_pixBufferWidth; + pixHeight = pTD->td_pixBufferHeight; + } + // get window / texture factor + if( pixWidth >= pixHeight) { + m_fWndTexRatio = FLOAT(m_pDrawPort->GetWidth()) /pixWidth; + } else { + m_fWndTexRatio = FLOAT(m_pDrawPort->GetHeight()) /pixHeight; + } + // get width and height of texture window + m_pixWinWidth = pixWidth *m_fWndTexRatio; + m_pixWinHeight = pixHeight*m_fWndTexRatio; + m_pixWinOffsetU = (m_pDrawPort->GetWidth() -m_pixWinWidth ) /2; + m_pixWinOffsetV = (m_pDrawPort->GetHeight()-m_pixWinHeight) /2; + // determine texture's alpha channel presence + bAlphaChannel = pTD->td_ulFlags&TEX_ALPHACHANNEL; + } else { + // whole screen + m_fWndTexRatio = 1.0f; + m_pixWinWidth = m_pDrawPort->GetWidth(); + m_pixWinHeight = m_pDrawPort->GetHeight(); + m_pixWinOffsetU = 0; + m_pixWinOffsetV = 0; + } + + // clear window background + m_pDrawPort->Fill( C_GRAY|CT_OPAQUE); + // if chequered alpha flag is turned on +#define CHESS_BOX_WIDTH 16 +#define CHESS_BOX_HEIGHT 16 + if( m_bChequeredAlpha && bAlphaChannel) + { // create chess looking background + for( INDEX iVert=0; iVert<(m_pixWinHeight/CHESS_BOX_HEIGHT)+1; iVert++) { + // create chess looking background + for( INDEX iHoriz=0; iHoriz<(m_pixWinWidth/CHESS_BOX_WIDTH)+1; iHoriz++) { + COLOR colBox = C_WHITE; + if( (iHoriz+iVert)&1) colBox = C_lGRAY; + // fill part of a drawport with a given color + m_pDrawPort->Fill( iHoriz*CHESS_BOX_WIDTH +m_pixWinOffsetU, + iVert *CHESS_BOX_HEIGHT+m_pixWinOffsetV, + CHESS_BOX_WIDTH, CHESS_BOX_HEIGHT, colBox|CT_OPAQUE); + } + } + } + + // if it has any texture + if( pTD!=NULL) { + // create rectangle proportional with texture ratio covering whole draw port + PIXaabbox2D rectPict = PIXaabbox2D( PIX2D( m_pixWinOffsetU, m_pixWinOffsetV), + PIX2D( m_pixWinOffsetU+m_pixWinWidth, m_pixWinOffsetV+m_pixWinHeight)); + // draw texture + m_pDrawPort->PutTexture( &m_toTexture, rectPict); + } + + // draw line on left mouse move + if( m_bDrawLine) { + m_pDrawPort->DrawLine(m_pixLineStartU, m_pixLineStartV, + m_pixLineStopU, m_pixLineStopV, C_WHITE|CT_OPAQUE, 0xCCCCCCCC); + m_pDrawPort->DrawLine(m_pixLineStartU, m_pixLineStartV, + m_pixLineStopU, m_pixLineStopV, C_BLACK|CT_OPAQUE, 0x33333333); + } + + // unlock the drawport + m_pDrawPort->Unlock(); + // swap if there is a valid viewport + if( m_pViewPort!=NULL) m_pViewPort->SwapBuffers(); + } + + // if this is effect texture + if( pTD!=NULL && pTD->td_ptegEffect!=NULL) + { // display rendering speed + DOUBLE dMS = pTD->td_ptegEffect->GetRenderingTime() * 1000.0; + // only if valid + if( dMS>0) { + char achrSpeed[256]; + CDlgCreateEffectTexture *pDialog = (CDlgCreateEffectTexture*)GetParent(); + sprintf( achrSpeed, "Rendering speed: %.2f ms", dMS); + pDialog->m_strRendSpeed = achrSpeed; + pDialog->UpdateData( FALSE); + } + // reset statistics + STAT_Reset(); + } +} + + +void CWndDisplayTexture::OnTimer(UINT nIDEvent) +{ + // on our timer discard test animation window + if( nIDEvent == 1) + { + TIME timeCurrentTick = _pTimer->GetRealTimeTick(); + if( timeCurrentTick > timeLastTick ) + { + _pTimer->SetCurrentTick( timeCurrentTick); + timeLastTick = timeCurrentTick; + } + Invalidate(FALSE); + } + + CWnd::OnTimer(nIDEvent); +} + + +void CWndDisplayTexture::OnDestroy() +{ + if( m_pViewPort != NULL) + { + _pGfx->DestroyWindowCanvas( m_pViewPort); + m_pViewPort = NULL; + } + + KillTimer( m_iTimerID); + _pTimer->SetCurrentTick( 0.0f); + CWnd::OnDestroy(); +} + + +void CWndDisplayTexture::OnLButtonDown(UINT nFlags, CPoint point) +{ + // start drawing line + m_bDrawLine = TRUE; + // store mouse start coordinates + m_pixLineStartU = point.x; + m_pixLineStartV = point.y; + m_pixLineStopU = point.x; + m_pixLineStopV = point.y; + + // get texture data from surface + CTextureData *pTD = (CTextureData*)m_toTexture.GetData(); + PIX pixU = point.x-m_pixWinOffsetU; + PIX pixV = point.y-m_pixWinOffsetV; + if( pixU<0 || pixU>m_pixWinWidth ) return; + if( pixV<0 || pixV>m_pixWinHeight) return; + pixU = PIX(pixU/m_fWndTexRatio); + pixV = PIX(pixV/m_fWndTexRatio); + + // if there is valid mouse down function set + if( m_pLeftMouseButtonClicked != NULL) + { // call it + m_pLeftMouseButtonClicked(pixU, pixV); + } + + CWnd::OnLButtonDown(nFlags, point); +} + +void CWndDisplayTexture::OnLButtonUp(UINT nFlags, CPoint point) +{ + // stop drawing line + m_bDrawLine = FALSE; + + // get texture data from surface + CTextureData *pTD = (CTextureData*)m_toTexture.GetData(); + PIX pixU = point.x-m_pixWinOffsetU; + PIX pixV = point.y-m_pixWinOffsetV; + if( pixU<0 || pixU>m_pixWinWidth ) return; + if( pixV<0 || pixV>m_pixWinHeight) return; + pixU = PIX(pixU/m_fWndTexRatio); + pixV = PIX(pixV/m_fWndTexRatio); + + // if there is valid mouse down function set + if( m_pLeftMouseButtonReleased != NULL) + { // call it + m_pLeftMouseButtonReleased(pixU, pixV); + } + + CWnd::OnLButtonUp(nFlags, point); +} + +void CWndDisplayTexture::OnRButtonDown(UINT nFlags, CPoint point) +{ + // get texture data from surface + CTextureData *pTD = (CTextureData*)m_toTexture.GetData(); + PIX pixU = point.x-m_pixWinOffsetU; + PIX pixV = point.y-m_pixWinOffsetV; + if( pixU<0 || pixU>m_pixWinWidth ) return; + if( pixV<0 || pixV>m_pixWinHeight) return; + pixU = PIX(pixU/m_fWndTexRatio); + pixV = PIX(pixV/m_fWndTexRatio); + + // if there is valid mouse down function set + if( m_pRightMouseButtonClicked != NULL) + { // call it + m_pRightMouseButtonClicked(pixU, pixV); + } + + CWnd::OnRButtonDown(nFlags, point); +} + +void CWndDisplayTexture::OnMouseMove(UINT nFlags, CPoint point) +{ + // if right mouse is down + if (nFlags&MK_RBUTTON) { + // get texture data from surface + CTextureData *pTD = (CTextureData*)m_toTexture.GetData(); + PIX pixU = point.x-m_pixWinOffsetU; + PIX pixV = point.y-m_pixWinOffsetV; + if( pixU<0 || pixU>m_pixWinWidth ) return; + if( pixV<0 || pixV>m_pixWinHeight) return; + pixU = PIX(pixU/m_fWndTexRatio); + pixV = PIX(pixV/m_fWndTexRatio); + + // if there is valid mouse down function set + if( m_pRightMouseButtonMoved != NULL) + { // call it + m_pRightMouseButtonMoved(pixU, pixV); + } + // if left mouse is down + } else if (nFlags&MK_LBUTTON) { + // store mouse coordinates + m_pixLineStopU = point.x; + m_pixLineStopV = point.y; + } + + CWnd::OnMouseMove(nFlags, point); +} \ No newline at end of file diff --git a/Sources/EngineGui/WndDisplayTexture.h b/Sources/EngineGui/WndDisplayTexture.h new file mode 100644 index 0000000..1b78e79 --- /dev/null +++ b/Sources/EngineGui/WndDisplayTexture.h @@ -0,0 +1,87 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#if !defined(AFX_WNDDISPLAYTEXTURE_H__4B489BC1_FAD9_11D1_82EA_000000000000__INCLUDED_) +#define AFX_WNDDISPLAYTEXTURE_H__4B489BC1_FAD9_11D1_82EA_000000000000__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// WndDisplayTexture.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CWndDisplayTexture window + +class CWndDisplayTexture : public CWnd +{ +// Construction +public: + CWndDisplayTexture(); + + // function that is called when lmb is clicked + inline void SetLeftMouseButtonClicked( void(*pLeftMouseButtonClicked)( PIX pixX, PIX pixY)) + {m_pLeftMouseButtonClicked=pLeftMouseButtonClicked;}; + // function that is called when lmb is released + inline void SetLeftMouseButtonReleased( void(*pLeftMouseButtonReleased)( PIX pixX, PIX pixY)) + {m_pLeftMouseButtonReleased=pLeftMouseButtonReleased;}; + // function that is called when rmb is clicked + inline void SetRightMouseButtonClicked( void(*pRightMouseButtonClicked)( PIX pixX, PIX pixY)) + {m_pRightMouseButtonClicked=pRightMouseButtonClicked;}; + // function that is called when rmb is moved + inline void SetRightMouseButtonMoved( void(*pRightMouseButtonMoved)( PIX pixX, PIX pixY)) + {m_pRightMouseButtonMoved=pRightMouseButtonMoved;}; + + void (*m_pLeftMouseButtonClicked)( PIX pixX, PIX pixY); + void (*m_pLeftMouseButtonReleased)( PIX pixX, PIX pixY); + void (*m_pRightMouseButtonClicked)( PIX pixX, PIX pixY); + void (*m_pRightMouseButtonMoved)( PIX pixX, PIX pixY); + CTextureObject m_toTexture; + CDrawPort *m_pDrawPort; + CViewPort *m_pViewPort; + int m_iTimerID; + BOOL m_bChequeredAlpha; + BOOL m_bForce32; + FLOAT m_fWndTexRatio; + PIX m_pixWinWidth; + PIX m_pixWinHeight; + PIX m_pixWinOffsetU; + PIX m_pixWinOffsetV; +public: + BOOL m_bDrawLine; + PIX m_pixLineStartU; + PIX m_pixLineStartV; + PIX m_pixLineStopU; + PIX m_pixLineStopV; + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CWndDisplayTexture) + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CWndDisplayTexture(); + + // Generated message map functions +protected: + //{{AFX_MSG(CWndDisplayTexture) + afx_msg void OnDestroy(); + afx_msg void OnPaint(); + afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_WNDDISPLAYTEXTURE_H__4B489BC1_FAD9_11D1_82EA_000000000000__INCLUDED_) diff --git a/Sources/EngineGui/mode_bro.bmp b/Sources/EngineGui/mode_bro.bmp new file mode 100644 index 0000000..fefc392 Binary files /dev/null and b/Sources/EngineGui/mode_bro.bmp differ diff --git a/Sources/EngineGui/resource.h b/Sources/EngineGui/resource.h new file mode 100644 index 0000000..53f7b44 --- /dev/null +++ b/Sources/EngineGui/resource.h @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Graphics.rc +// +#define ID_TEST_BUTTON 3 +#define ID_CREATE_AS 3 +#define ID_REFRESH_TEXTURE 6 +#define ID_BASE_NONE 8 +#define ID_BROWSE_BASE 9 +#define ID_REMOVE_ALL_EFFECTS 10 +#define IDD_DIALOG1 101 +#define IDD_SELECT_MODE_DIALOG 101 +#define IDB_MODE_BROWSING_ICONS 102 +#define IDD_CREATE_EFFECT_TEXTURE 103 +#define IDD_CREATE_ANIMATED_TEXTURE 104 +#define IDD_CREATE_NORMAL_TEXTURE 105 +#define IDD_CHOOSE_TEXTURE_TYPE 106 +#define IDD_GFX_FILE_REQUESTER 185 +#define IDC_CURRENT_MODE 1005 +#define IDC_CURRENT_DRIVER 1006 +#define IDC_PIX_WIDTH 1009 +#define IDC_PIX_HEIGHT 1010 +#define IDC_TEXTURE_TYPE 1012 +#define IDC_EFFECT_CLASS 1012 +#define IDC_MEX_SIZE 1013 +#define IDC_MIP_MAPS 1014 +#define IDC_EFFECT_TYPE 1017 +#define IDC_CHEQUERED_ALPHA 1018 +#define IDC_FORCE32 1019 +#define IDC_CREATED_TEXTURE_NAME 1020 +#define IDC_CREATE_MIPMAPS 1021 +#define IDC_VIEW_TEXTURE 1022 +#define IDC_SIZE_IN_PIXELS 1023 +#define IDC_EDIT_SCRIPT 1024 +#define ID_NORMAL_TEXTURE 1025 +#define IDC_TEXTURE_NAME 1025 +#define ID_ANIMATED_TEXTURE 1026 +#define IDC_TEXTURE_ANIMATIONS 1026 +#define ID_EFFECT_TEXTURE 1027 +#define IDC_TEXTURE_PREVIEW_WINDOW 1028 +#define ID_CREATE_TEXTURE 1029 +#define IDW_VIEW_CREATED_TEXTURE 1030 +#define IDC_BASE_TEXTURE_NAME 1032 +#define ID_CREATE 1033 +#define IDC_REND_SPEED 1034 +#define IDW_FILE_THUMBNAIL 1035 +#define IDC_THUMBNAIL_DESCRIPTION 1036 +#define IDC_THUMBNAIL_RECT 1037 +#define IDC_COLOR_HIGH 1038 +#define IDC_COLOR_TRUE 1039 +#define IDC_COLOR_DEFAULT 1040 +#define IDC_API 1041 +#define IDC_RESOLUTIONS 1042 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 109 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1042 +#define _APS_NEXT_SYMED_VALUE 103 +#endif +#endif diff --git a/Sources/EntitiesMP/AirElemental.cpp b/Sources/EntitiesMP/AirElemental.cpp new file mode 100644 index 0000000..63bcff2 --- /dev/null +++ b/Sources/EntitiesMP/AirElemental.cpp @@ -0,0 +1,1087 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/AirElemental/AirElemental.h" +#include "ModelsMP/Enemies/AirElemental/Elemental.h" +#include "Models/Enemies/Elementals/Twister.h" + +#include +#include +CEntityEvent *EElementalGrow::MakeCopy(void) { CEntityEvent *peeCopy = new EElementalGrow(*this); return peeCopy;} +EElementalGrow::EElementalGrow() : CEntityEvent(EVENTCODE_EElementalGrow) {; +}; +#line 18 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" + +#define ECF_AIR ( \ + ((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)< GetAttachmentModel (AIRELEMENTAL_ATTACHMENT_BODY ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return & (amo0 . amo_moModelObject ); +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(m_bInitialAnim ){return ;} +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fHealth = GetHealth (); +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fFullDamage = fDamageAmmount * DamageStrength (((EntityInfo *) GetEntityInfo ()) -> Eeibt , dmtType ) * GetGameDamageMultiplier (); +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(m_bAttGrow && m_iSize < 2){ +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(fHealth - fFullDamage < afGrowArray [ m_iSize + 1 ] [ 0 ] * m_fMaxHealth ){ +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetHealth (fHealth ); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return ; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +}else if(m_bAttGrow && m_iSize == 2){ +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(fHealth - fFullDamage < 1.0f){ +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetHealth (fHealth ); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return ; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(IsOfClass (penInflictor , "AirElemental")){ +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return ; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(dmtType == DMT_TELEPORT ) +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return ; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(dmtType == DMT_CLOSERANGE || +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +dmtType == DMT_BULLET || +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +dmtType == DMT_IMPACT || +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +dmtType == DMT_CHAINSAW ) +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return ; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(dmtType == DMT_CANNONBALL ) +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +fDamageAmmount *= 0.6f; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fOldHealth = GetHealth (); +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fNewHealth = GetHealth (); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CEntityPointer * penTrigger = & m_penTrigger01 ; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +INDEX i = 0; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +for(i = 0;i < AIRBOSS_MAX_TA ;i ++){ +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fHealth = afTriggerArray [ i ] * m_fMaxHealth ; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(fHealth <= fOldHealth && fHealth > fNewHealth ) +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(& * penTrigger [ i ]){ +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SendToTarget (& * penTrigger [ i ] , EET_TRIGGER , FixupCausedToPlayer (this , m_penEnemy )); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +for(i = 0;i < AIRBOSS_MAX_GA ;i ++){ +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fHealth = afGrowArray [ i ] [ 0 ] * m_fMaxHealth ; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(fHealth <= fOldHealth && fHealth > fNewHealth ) +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fAttSizeRequested = afGrowArray [ i ] [ 1 ]; +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_iSize = i ; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +EElementalGrow eeg ; +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SendEvent (eeg ); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_colBurning = COLOR (C_WHITE | CT_OPAQUE ); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +INDEX CAirElemental::AnimForDamage(FLOAT fDamage) { +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +INDEX iAnim = ELEMENTAL_ANIM_IDLE ; +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (iAnim , 0); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return iAnim ; +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::StandingAnimFight(void) { +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (ELEMENTAL_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::StandingAnim(void) { +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (ELEMENTAL_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::WalkingAnim(void) +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (ELEMENTAL_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::RunningAnim(void) +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +WalkingAnim (); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::RotatingAnim(void) { +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +WalkingAnim (); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +INDEX CAirElemental::AnimForDeath(void) +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +INDEX iAnim ; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +iAnim = ELEMENTAL_ANIM_IDLE ; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (iAnim , 0); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return iAnim ; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::IdleSound(void) { +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::WoundSound(void) { +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::SizeModel(void) +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return ; +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +BOOL CAirElemental::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) { +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return CMovableModelEntity :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::BlowUp(void) { +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::EnemyPostInit(void) +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_soFire . Set3DParameters (600.0f , 150.0f , 2.0f , 1.0f); +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_soVoice . Set3DParameters (600.0f , 150.0f , 2.0f , 1.0f); +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_soSound . Set3DParameters (600.0f , 150.0f , 2.0f , 1.0f); +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::LaunchTwister(FLOAT3D vEnemyOffset) +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT3D vFirePos = FIREPOS_TWISTER * m_fAttSizeCurrent * GetRotationMatrix (); +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT3D vShooting = GetPlacement () . pl_PositionVector + vFirePos ; +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT3D vTarget = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fLaunchSpeed ; +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fRelativeHdg ; +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vTarget += vEnemyOffset ; +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CPlacement3D pl ; +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CalculateAngularLaunchParams (vShooting , peiTarget -> vTargetCenter [ 1 ] - 6.0f / 3.0f , +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vTarget , FLOAT3D (0.0f , 0.0f , 0.0f) , 0.0f , fLaunchSpeed , fRelativeHdg ); +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +PrepareFreeFlyingProjectile (pl , vTarget , vFirePos , ANGLE3D (fRelativeHdg , 0.0f , 0.0f)); +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ETwister et ; +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CEntityPointer penTwister = CreateEntity (pl , CLASS_TWISTER ); +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +et . penOwner = this ; +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +et . fSize = FRnd () * 10.0f + m_fAttSizeCurrent / 5.0f + 3.0f; +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +et . fDuration = 15.0f + FRnd () + 5.0f; +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +et . sgnSpinDir = (INDEX) (Sgn (FRnd () - 0.5f)); +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +et . bGrow = TRUE ; +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +et . bMovingAllowed = TRUE ; +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +penTwister -> Initialize (et ); +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +((CMovableEntity &) * penTwister ) . LaunchAsFreeProjectile (FLOAT3D (0.0f , 0.0f , - fLaunchSpeed ) , (CMovableEntity *) (CEntity *) this ); +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::PreMoving() { +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CEnemyBase :: PreMoving (); +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::GetAirElementalAttachmentData(INDEX iAttachment,FLOATmatrix3D & mRot,FLOAT3D & vPos) +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +MakeRotationMatrixFast (mRot , ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vPos = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +GetModelObject () -> GetAttachmentTransformations (AIRELEMENTAL_ATTACHMENT_BODY , mRot , vPos , FALSE ); +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CAttachmentModelObject * pamo = GetModelObject () -> GetAttachmentModel (AIRELEMENTAL_ATTACHMENT_BODY ); +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +pamo -> amo_moModelObject . GetAttachmentTransformations (iAttachment , mRot , vPos , TRUE ); +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vPos = GetPlacement () . pl_PositionVector + vPos * GetRotationMatrix (); +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT CAirElemental::GetCurrentStretchRatio(void) +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CAttachmentModelObject & amo = * GetModelObject () -> GetAttachmentModel (AIRELEMENTAL_ATTACHMENT_BODY ); +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fCurrentStretch = amo . amo_moModelObject . mo_Stretch (1); +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fStretch = (fCurrentStretch - m_fAttSizeBegin ) / (m_fAttSizeEnd - m_fAttSizeBegin ); +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return fStretch ; +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} + +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void CAirElemental::RenderParticles(void) +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +static TIME tmLastGrowTime = 0.0f; +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(m_bFloat ){ +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fTime = _pTimer -> GetLerpedCurrentTick (); +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CAttachmentModelObject & amo0 = * GetModelObject () -> GetAttachmentModel (AIRELEMENTAL_ATTACHMENT_BODY ); +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +amo0 . amo_plRelative . pl_PositionVector (2) = m_fAttPosY + pow (sin (fTime * 2.0f) , 2.0f) * m_fAttSizeCurrent * 2.0f / m_fAttSizeBegin ; +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(m_bAttGrow ){ +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fSize = Lerp (m_fLastSize , m_fTargetSize , _pTimer -> GetLerpFactor ()); +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> StretchModel (FLOAT3D (fSize , fSize , fSize )); +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(m_bRenderParticles ) +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fStretchRatio = GetCurrentStretchRatio (); +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fStretch = 1.0f + (fStretchRatio ) * 6.0f; +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Particles_AirElemental (this , fStretch , 1.0f , m_tmDeath , m_colParticles ); +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +BOOL CAirElemental:: +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Die(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAirElemental_Die + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDeath, "CAirElemental::Die expects 'EDeath' as input!"); const EDeath &eDeath = (const EDeath &)__eeInput; +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +PlaySound (m_soFire , SOUND_DEATH , SOF_3D ); +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (ELEMENTAL_ANIM_DEATH , AOF_NORESTART ); +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_tmDeath = _pTimer -> CurrentTick () + ElementalModel () -> GetAnimLength (ELEMENTAL_ANIM_DEATH ); +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_bFloat = FALSE ; +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(ElementalModel () -> GetAnimLength (ELEMENTAL_ANIM_DEATH ) - 0.1f); +Jump(STATE_CURRENT, 0x015b0002, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b0002_Die_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0002 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0003, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b0003_Die_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0003 +; +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +PlaySound (m_soVoice , SOUND_EXPLOSION , SOF_3D ); +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_bDying = TRUE ; +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fDeathDuration = 4.0f; +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(m_fDeathDuration ); +Jump(STATE_CURRENT, 0x015b0004, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b0004_Die_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0005, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b0005_Die_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0005 +; +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +EDeath eDeath ; +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +eDeath . eLastDamage . penInflictor = m_penDeathInflictor ; +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Die, FALSE, eDeath );return TRUE; ASSERT(FALSE); return TRUE;};BOOL CAirElemental:: +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAirElemental_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAirElemental::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(!(m_tmWindNextFire < _pTimer -> CurrentTick ())){ Jump(STATE_CURRENT,0x015b0011, FALSE, EInternal());return TRUE;} +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (ELEMENTAL_ANIM_FIREPROJECTILES , AOF_NORESTART ); +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_iWind = 0; +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +PlaySound (m_soFire , SOUND_FIREWINDBLAST , SOF_3D ); +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(1.8f); +Jump(STATE_CURRENT, 0x015b0007, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b0007_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0008, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b0008_Fire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0008 +; +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Jump(STATE_CURRENT,0x015b000b, FALSE, EInternal());return TRUE;}BOOL CAirElemental::H0x015b000b_Fire_05(const CEntityEvent &__eeInput) +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000b +if(!(m_iWind < 5)){ Jump(STATE_CURRENT,0x015b000c, FALSE, EInternal());return TRUE;} +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT3D vFirePos ; +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vFirePos = Lerp (m_fWindBlastFirePosBegin * m_fAttSizeCurrent , +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fWindBlastFirePosEnd * m_fAttSizeCurrent , +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +(FLOAT) m_iWind * 0.25f); +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ShootProjectile (PRT_AIRELEMENTAL_WIND , vFirePos , +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ANGLE3D (30.0f - m_iWind * 10.0 , 0.0f , 0.0f)); +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_iWind ++; +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x015b0009, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b0009_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b000a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b000a_Fire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000a +;Jump(STATE_CURRENT,0x015b000b, FALSE, EInternal());return TRUE; +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +}BOOL CAirElemental::H0x015b000c_Fire_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000c + +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_tmWindNextFire = _pTimer -> CurrentTick () + Lerp (m_fWindFireTimeMin , m_fWindFireTimeMax , FRnd ()); +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(ElementalModel () -> GetAnimLength (ELEMENTAL_ANIM_FIREPROJECTILES ) - 1.75f); +Jump(STATE_CURRENT, 0x015b000d, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b000d_Fire_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b000e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b000e_Fire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000e +; +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (ELEMENTAL_ANIM_IDLE , AOF_LOOPING | AOF_SMOOTHCHANGE ); +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x015b000f, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b000f_Fire_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0010, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b0010_Fire_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0010 +; +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return TRUE;Jump(STATE_CURRENT,0x015b0011, FALSE, EInternal());return TRUE;}BOOL CAirElemental::H0x015b0011_Fire_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0011 + +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (ELEMENTAL_ANIM_FIRETWISTER , AOF_NORESTART ); +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +PlaySound (m_soFire , SOUND_FIRETWISTER , SOF_3D ); +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(4.0f); +Jump(STATE_CURRENT, 0x015b0012, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b0012_Fire_12(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0012 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0013, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b0013_Fire_13(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0013 +; +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT3D vOffset ; +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(((CMovableEntity &) * m_penEnemy ) . en_vCurrentTranslationAbsolute . Length () == 0.0f){ +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT3D vPlayerToThis = GetPlacement () . pl_PositionVector - m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vPlayerToThis . Normalize (); +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vOffset = FLOAT3D (vPlayerToThis * (FRnd () * 10.0f + 5.0f)); +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +LaunchTwister (vOffset ); +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vOffset = FLOAT3D (- (FRnd () * 5.0f + 15.0f) , 0.0f , (FRnd () - 0.5f) * 20.0f) * ((CMovableEntity &) * m_penEnemy ) . GetRotationMatrix (); +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +LaunchTwister (vOffset ); +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vOffset = FLOAT3D (+ (FRnd () * 5.0f + 15.0f) , 0.0f , 20.0f) * ((CMovableEntity &) * m_penEnemy ) . GetRotationMatrix (); +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +LaunchTwister (vOffset ); +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +}else { +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT3D vPlayerSpeed = ((CMovableEntity &) * m_penEnemy ) . en_vCurrentTranslationAbsolute ; +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(vPlayerSpeed . Length () > 15.0f){ +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vPlayerSpeed . Normalize (); +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vPlayerSpeed = vPlayerSpeed * 15.0f; +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 559 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vOffset = vPlayerSpeed * (2.0f + FRnd ()); +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT3D vToPlayer = ((CMovableEntity &) * m_penEnemy ) . GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vToPlayer . Normalize (); +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vToPlayer *= 15.0f + FRnd () * 5.0f; +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vOffset -= vToPlayer ; +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +LaunchTwister (vOffset ); +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +LaunchTwister (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +LaunchTwister (vOffset + FLOAT3D (+ 5.0f + FRnd () * 5.0f , 0.0f , - 15.0f - FRnd () * 5.0f)); +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(ElementalModel () -> GetAnimLength (ELEMENTAL_ANIM_FIRETWISTER ) - 4.0f); +Jump(STATE_CURRENT, 0x015b0014, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b0014_Fire_14(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0014 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0015, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b0015_Fire_15(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0015 +; +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (ELEMENTAL_ANIM_IDLE , AOF_LOOPING | AOF_SMOOTHCHANGE ); +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x015b0016, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b0016_Fire_16(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0016 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0017, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b0017_Fire_17(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0017 +; +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CAirElemental:: +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAirElemental_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAirElemental::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 581 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Jump(STATE_CURRENT, STATE_CAirElemental_Fire, TRUE, EVoid());return TRUE; +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CAirElemental:: +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Death(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAirElemental_Death + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAirElemental::Death expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 590 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fFadeStartTime = _pTimer -> CurrentTick (); +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_bFadeOut = TRUE ; +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fFadeTime = 2.0f; +#line 593 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(m_fFadeTime ); +Jump(STATE_CURRENT, 0x015b001a, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b001a_Death_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b001a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b001b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b001b_Death_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b001b +; +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +STATE_CEnemyBase_Death, FALSE; +Jump(STATE_CURRENT, 0x015b001c, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b001c_Death_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b001c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_Death, FALSE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x015b001d, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b001d_Death_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b001d +const EEnd&__e= (EEnd&)__eeInput; +; +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Return(STATE_CURRENT,EEnd ()); +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CAirElemental:: +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Grow(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAirElemental_Grow + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAirElemental::Grow expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ASSERT (m_fAttSizeRequested > m_fAttSizeCurrent ); +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fLastSize = m_fTargetSize = m_fAttSizeCurrent ; +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +PlaySound (m_soSound , SOUND_ROAR , SOF_3D ); +#line 609 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (ELEMENTAL_ANIM_IDLE , AOF_NORESTART ); +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_bAttGrow = TRUE ; +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Jump(STATE_CURRENT,0x015b0021, FALSE, EInternal());return TRUE;}BOOL CAirElemental::H0x015b0021_Grow_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0021 +if(!(m_fLastSize < m_fAttSizeRequested )){ Jump(STATE_CURRENT,0x015b0022, FALSE, EInternal());return TRUE;} +#line 616 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(m_penEnemy ){ +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT3D vToTarget ; +#line 618 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ANGLE3D aToTarget ; +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vToTarget = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +vToTarget . Normalize (); +#line 621 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +DirectionVectorToAngles (vToTarget , aToTarget ); +#line 622 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +aToTarget (1) = aToTarget (1) - GetPlacement () . pl_OrientationAngle (1); +#line 623 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +aToTarget (1) = NormalizeAngle (aToTarget (1)); +#line 624 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetDesiredRotation (FLOAT3D (aToTarget (1) / 2.0f , 0.0f , 0.0f)); +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 628 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fLastSize = m_fTargetSize ; +#line 629 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fTargetSize += m_fGrowSpeed * _pTimer -> TickQuantum ; +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fMiddleSize = Lerp (m_fAttSizeCurrent , m_fAttSizeRequested , 0.33f); +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(m_fLastSize <= fMiddleSize && fMiddleSize < m_fTargetSize ){ +#line 638 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(m_iSize < 2){ +#line 639 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ChangeCollisionBoxIndexWhenPossible (m_iSize + 1); +#line 640 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +}else if(TRUE ){ +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ForceCollisionBoxIndexChange (m_iSize + 1); +#line 642 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 643 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 645 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x015b001f, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b001f_Grow_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b001f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0020, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b0020_Grow_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0020 +;Jump(STATE_CURRENT,0x015b0021, FALSE, EInternal());return TRUE; +#line 646 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +}BOOL CAirElemental::H0x015b0022_Grow_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0022 + +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_bAttGrow = FALSE ; +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fAttSizeCurrent = afGrowArray [ m_iSize ] [ 1 ]; +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fGrowSpeed *= 2.0f; +#line 652 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +if(m_iSize == 1){ +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +GetModelObject () -> PlayAnim (AIRELEMENTAL_ANIM_SIZE50 , AOF_LOOPING ); +#line 654 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +} +#line 656 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CAirElemental:: +#line 659 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAirElemental_ElementalLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAirElemental::ElementalLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 660 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x015b0024, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b0024_ElementalLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0024 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin): +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{const EBegin&e= (EBegin&)__eeInput; + +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Call(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; +#line 664 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +}ASSERT(FALSE);break;case(EVENTCODE_EElementalGrow): +#line 666 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +{const EElementalGrow&e= (EElementalGrow&)__eeInput; + +#line 667 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Call(STATE_CURRENT, STATE_CAirElemental_Grow, TRUE, EVoid());return TRUE; +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +}ASSERT(FALSE);break;default:{ +#line 670 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +return TRUE; +#line 671 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +}ASSERT(FALSE);break; +#line 672 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +}return TRUE;}BOOL CAirElemental::H0x015b0025_ElementalLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0025 + ASSERT(FALSE); return TRUE;};BOOL CAirElemental:: +#line 675 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAirElemental_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAirElemental::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 678 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +InitAsEditorModel (); +#line 680 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 681 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 682 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 684 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +en_fDensity = 10000.0f; +#line 685 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fDamageWounded = 1e6f; +#line 687 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_sptType = SPT_AIRSPOUTS ; +#line 688 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_bBoss = TRUE ; +#line 689 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetHealth (15000.0f); +#line 690 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fMaxHealth = 15000.0f; +#line 692 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fWalkSpeed = 0.0f; +#line 693 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 245.0f); +#line 694 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fAttackRunSpeed = m_fWalkSpeed ; +#line 695 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_aAttackRotateSpeed = m_aWalkRotateSpeed ; +#line 696 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fCloseRunSpeed = m_fWalkSpeed ; +#line 697 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_aCloseRotateSpeed = m_aWalkRotateSpeed ; +#line 699 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fAttackDistance = 500.0f; +#line 700 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fCloseDistance = 60.0f; +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fStopDistance = 30.0f; +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fAttackFireTime = 4.0f; +#line 703 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fCloseFireTime = 4.0f; +#line 704 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fIgnoreRange = 1000.0f; +#line 705 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_iScore = 500000; +#line 707 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +eiAirElemental . vSourceCenter [ 1 ] = AIRBOSS_EYES_HEIGHT * m_fAttSizeBegin ; +#line 708 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +eiAirElemental . vTargetCenter [ 1 ] = AIRBOSS_BODY_HEIGHT * m_fAttSizeBegin ; +#line 711 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetModel (MODEL_INVISIBLE ); +#line 712 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +AddAttachmentToModel (this , * GetModelObject () , AIRELEMENTAL_ATTACHMENT_BODY , MODEL_ELEMENTAL , TEXTURE_ELEMENTAL , 0 , 0 , TEXTURE_DETAIL_ELEM ); +#line 713 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CAttachmentModelObject & amo0 = * GetModelObject () -> GetAttachmentModel (AIRELEMENTAL_ATTACHMENT_BODY ); +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fAttPosY = amo0 . amo_plRelative . pl_PositionVector (2); +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +StandingAnim (); +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_fAttSizeCurrent = m_fAttSizeBegin ; +#line 719 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +GetModelObject () -> StretchModel (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ModelChangeNotify (); +#line 721 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> StretchModel (FLOAT3D (m_fAttSizeBegin , m_fAttSizeBegin , m_fAttSizeBegin )); +#line 723 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_bRenderParticles = FALSE ; +#line 724 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x015b0026, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b0026_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0026 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0027, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b0027_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0027 +; +#line 726 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_emEmiter . Initialize (this ); +#line 727 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_emEmiter . em_etType = ET_AIR_ELEMENTAL ; +#line 729 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_tmDeath = 1e6f; +#line 746 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x015b0028, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b0028_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0028 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x015b0029, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 750 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +}return TRUE;}BOOL CAirElemental::H0x015b0029_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0029 + +#line 752 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetCollisionFlags (ECF_AIR ); +#line 753 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 755 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (ELEMENTAL_ANIM_RAISE , AOF_NORESTART ); +#line 756 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_bRenderParticles = TRUE ; +#line 758 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_bInitialAnim = TRUE ; +#line 760 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +SetTimerAfter(ElementalModel () -> GetAnimLength (ELEMENTAL_ANIM_RAISE )); +Jump(STATE_CURRENT, 0x015b002a, FALSE, EBegin());return TRUE;}BOOL CAirElemental::H0x015b002a_Main_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b002a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b002b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirElemental::H0x015b002b_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b002b +; +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ChangeCollisionBoxIndexWhenPossible (AIRELEMENTAL_COLLISION_BOX_COLLISION01 ); +#line 765 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +GetModelObject () -> PlayAnim (AIRELEMENTAL_ANIM_DEFAULT , AOF_LOOPING ); +#line 767 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalModel () -> PlayAnim (ELEMENTAL_ANIM_IDLE , AOF_LOOPING ); +#line 768 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_bInitialAnim = FALSE ; +#line 769 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_bFloat = TRUE ; +#line 771 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +m_tmWindNextFire = _pTimer -> CurrentTick () + 10.0f; +#line 774 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Jump(STATE_CURRENT, STATE_CAirElemental_ElementalLoop, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/AirElemental.es b/Sources/EntitiesMP/AirElemental.es new file mode 100644 index 0000000..8c38102 --- /dev/null +++ b/Sources/EntitiesMP/AirElemental.es @@ -0,0 +1,777 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +347 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/AirElemental/AirElemental.h" +#include "ModelsMP/Enemies/AirElemental/Elemental.h" +#include "Models/Enemies/Elementals/Twister.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/Twister"; +//uses "EntitiesMP/AirShockwave"; + +event EElementalGrow { +}; + +%{ +#define ECF_AIR ( \ + ((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)<GetAttachmentModel(AIRELEMENTAL_ATTACHMENT_BODY); + return &(amo0.amo_moModelObject); + }; + + // Receive damage + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // nothing can harm elemental during initial animation + if (m_bInitialAnim) { return; } + + // make sure we don't trigger another growth while growing + FLOAT fHealth = GetHealth(); + FLOAT fFullDamage = fDamageAmmount * DamageStrength( ((EntityInfo*)GetEntityInfo())->Eeibt, dmtType) * GetGameDamageMultiplier(); + if (m_bAttGrow && m_iSize<2) { + if (fHealth-fFullDamagefNewHealth) + { + if (&*penTrigger[i]) { + SendToTarget(&*penTrigger[i], EET_TRIGGER, FixupCausedToPlayer(this, m_penEnemy)); + } + } + } + // see if we have to grow + for (i=0; ifNewHealth) + { + m_fAttSizeRequested = afGrowArray[i][1]; + m_iSize = i; + EElementalGrow eeg; + SendEvent(eeg); + } + } + + // bosses don't darken when burning + m_colBurning=COLOR(C_WHITE|CT_OPAQUE); + + }; + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim = ELEMENTAL_ANIM_IDLE; + ElementalModel()->PlayAnim(iAnim, 0); + return iAnim; + }; + + void StandingAnimFight(void) { + ElementalModel()->PlayAnim(ELEMENTAL_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + + // virtual anim functions + void StandingAnim(void) { + ElementalModel()->PlayAnim(ELEMENTAL_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + + void WalkingAnim(void) + { + ElementalModel()->PlayAnim(ELEMENTAL_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + + void RunningAnim(void) + { + WalkingAnim(); + }; + + void RotatingAnim(void) { + WalkingAnim(); + }; + + INDEX AnimForDeath(void) + { + INDEX iAnim; + iAnim = ELEMENTAL_ANIM_IDLE; + ElementalModel()->PlayAnim(iAnim, 0); + return iAnim; + }; + + // virtual sound functions + void IdleSound(void) { + //PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void WoundSound(void) { + //PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + + void SizeModel(void) + { + return; + }; + + // per-frame adjustments + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) { + return CMovableModelEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + }; + + +/************************************************************ + * BLOW UP FUNCTIONS * + ************************************************************/ + // spawn body parts + void BlowUp(void) { + // get your size + /*FLOATaabbox3D box; + GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm()/2; + + INDEX iCount = 7; + FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(m_fBlowUpAmount/m_vDamage.Length()); + vNormalizedDamage /= Sqrt(vNormalizedDamage.Length()); + vNormalizedDamage *= 1.75f; + FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute); + + // hide yourself (must do this after spawning debris) + SwitchToEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL);*/ + }; + + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + m_soFire.Set3DParameters(600.0f, 150.0f, 2.0f, 1.0f); + m_soVoice.Set3DParameters(600.0f, 150.0f, 2.0f, 1.0f); + m_soSound.Set3DParameters(600.0f, 150.0f, 2.0f, 1.0f); + }; + + void LaunchTwister(FLOAT3D vEnemyOffset) + { + // calculate parameters for predicted angular launch curve + FLOAT3D vFirePos = FIREPOS_TWISTER*m_fAttSizeCurrent*GetRotationMatrix(); + FLOAT3D vShooting = GetPlacement().pl_PositionVector + vFirePos; + FLOAT3D vTarget = m_penEnemy->GetPlacement().pl_PositionVector; + FLOAT fLaunchSpeed; + FLOAT fRelativeHdg; + + // shoot in front of the enemy + EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); + + // adjust target position + vTarget += vEnemyOffset; + + CPlacement3D pl; + CalculateAngularLaunchParams( vShooting, peiTarget->vTargetCenter[1]-6.0f/3.0f, + vTarget, FLOAT3D(0.0f, 0.0f, 0.0f), 0.0f, fLaunchSpeed, fRelativeHdg); + + PrepareFreeFlyingProjectile(pl, vTarget, vFirePos, ANGLE3D( fRelativeHdg, 0.0f, 0.0f)); + + ETwister et; + CEntityPointer penTwister = CreateEntity(pl, CLASS_TWISTER); + et.penOwner = this; +// et.fSize = FRnd()*15.0f+5.0f; + et.fSize = FRnd()*10.0f+m_fAttSizeCurrent/5.0f+3.0f; + et.fDuration = 15.0f + FRnd()+5.0f; + et.sgnSpinDir = (INDEX)(Sgn(FRnd()-0.5f)); + et.bGrow = TRUE; + et.bMovingAllowed=TRUE; + penTwister->Initialize(et); + + ((CMovableEntity &)*penTwister).LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -fLaunchSpeed), (CMovableEntity*)(CEntity*)this); + } + + void PreMoving() { + + // TODO: decomment this when shockwave is fixed + /*// see if any of the players are really close to us + INDEX ctMaxPlayers = GetMaxPlayers(); + CEntity *penPlayer; + + for(INDEX i=0; iCurrentTick()>(m_tmLastShockwave+m_fShockwavePeriod)) { + EAirShockwave eas; + CEntityPointer penShockwave = CreateEntity(GetPlacement(), CLASS_AIRSHOCKWAVE); + eas.penLauncher = this; + eas.fHeight = 15.0f + m_iSize*10.0f; + eas.fEndWidth = 80.0f + m_iSize*30.0f; + eas.fDuration = 3.0f; + penShockwave->Initialize(eas); + m_tmLastShockwave = _pTimer->CurrentTick(); + } + } + }*/ + CEnemyBase::PreMoving(); + }; + + void GetAirElementalAttachmentData(INDEX iAttachment, FLOATmatrix3D &mRot, FLOAT3D &vPos) + { + MakeRotationMatrixFast(mRot, ANGLE3D(0.0f, 0.0f, 0.0f)); + vPos=FLOAT3D(0.0f, 0.0f, 0.0f); + GetModelObject()->GetAttachmentTransformations(AIRELEMENTAL_ATTACHMENT_BODY, mRot, vPos, FALSE); + // next in hierarchy + CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel(AIRELEMENTAL_ATTACHMENT_BODY); + pamo->amo_moModelObject.GetAttachmentTransformations( iAttachment, mRot, vPos, TRUE); + vPos=GetPlacement().pl_PositionVector+vPos*GetRotationMatrix(); + } + + FLOAT GetCurrentStretchRatio(void) + { + CAttachmentModelObject &amo=*GetModelObject()->GetAttachmentModel(AIRELEMENTAL_ATTACHMENT_BODY); + FLOAT fCurrentStretch=amo.amo_moModelObject.mo_Stretch(1); + FLOAT fStretch=(fCurrentStretch-m_fAttSizeBegin)/(m_fAttSizeEnd-m_fAttSizeBegin); + return fStretch; + } + + void RenderParticles(void) + { + static TIME tmLastGrowTime = 0.0f; + + if (m_bFloat) { + FLOAT fTime = _pTimer->GetLerpedCurrentTick(); + CAttachmentModelObject &amo0 = *GetModelObject()->GetAttachmentModel(AIRELEMENTAL_ATTACHMENT_BODY); + amo0.amo_plRelative.pl_PositionVector(2) = m_fAttPosY + pow(sin(fTime*2.0f),2.0f)*m_fAttSizeCurrent*2.0f/m_fAttSizeBegin; + } + if (m_bAttGrow) { + FLOAT fSize = Lerp(m_fLastSize, m_fTargetSize, _pTimer->GetLerpFactor()); + ElementalModel()->StretchModel(FLOAT3D(fSize, fSize, fSize)); + } + + if(m_bRenderParticles) + { + FLOAT fStretchRatio=GetCurrentStretchRatio(); + FLOAT fStretch=1.0f+(fStretchRatio)*6.0f; + Particles_AirElemental(this, fStretch, 1.0f, m_tmDeath, m_colParticles); + } + } + + +procedures: + + Die(EDeath eDeath) : CEnemyBase::Die { + + SetDesiredRotation(ANGLE3D(0.0f, 0.0f, 0.0f)); + PlaySound(m_soFire, SOUND_DEATH, SOF_3D); + ElementalModel()->PlayAnim(ELEMENTAL_ANIM_DEATH, AOF_NORESTART); + m_tmDeath = _pTimer->CurrentTick()+ElementalModel()->GetAnimLength(ELEMENTAL_ANIM_DEATH); + m_bFloat = FALSE; + autowait(ElementalModel()->GetAnimLength(ELEMENTAL_ANIM_DEATH)-0.1f); + + PlaySound(m_soVoice, SOUND_EXPLOSION, SOF_3D); + m_bDying = TRUE; + m_fDeathDuration = 4.0f; + + autowait(m_fDeathDuration); + + EDeath eDeath; + eDeath.eLastDamage.penInflictor = m_penDeathInflictor; + jump CEnemyBase::Die(eDeath); + } + +/************************************************************ + * FIRE PROCEDURES * + ************************************************************/ + + Fire(EVoid) : CEnemyBase::Fire { + + if (m_tmWindNextFire<_pTimer->CurrentTick()) { + ElementalModel()->PlayAnim(ELEMENTAL_ANIM_FIREPROJECTILES, AOF_NORESTART); + m_iWind = 0; + PlaySound(m_soFire, SOUND_FIREWINDBLAST, SOF_3D); + + autowait(1.8f); + while(m_iWind<5) + { + FLOAT3D vFirePos; + vFirePos = Lerp(m_fWindBlastFirePosBegin*m_fAttSizeCurrent, + m_fWindBlastFirePosEnd*m_fAttSizeCurrent, + (FLOAT)m_iWind*0.25f); + ShootProjectile(PRT_AIRELEMENTAL_WIND, vFirePos, + ANGLE3D(30.0f-m_iWind*10.0, 0.0f, 0.0f)); + m_iWind++; + autowait(0.1f); + } + m_tmWindNextFire = _pTimer->CurrentTick() + Lerp(m_fWindFireTimeMin, m_fWindFireTimeMax, FRnd()); + + autowait(ElementalModel()->GetAnimLength(ELEMENTAL_ANIM_FIREPROJECTILES)-1.75f); + // stand a while + ElementalModel()->PlayAnim(ELEMENTAL_ANIM_IDLE, AOF_LOOPING|AOF_SMOOTHCHANGE); + + autowait(0.05f); + + return EReturn(); + } + + ElementalModel()->PlayAnim(ELEMENTAL_ANIM_FIRETWISTER, AOF_NORESTART); + //wait to get into twister emitting position + PlaySound(m_soFire, SOUND_FIRETWISTER, SOF_3D); + autowait(4.0f); + + FLOAT3D vOffset; + // static enemy + if (((CMovableEntity &)*m_penEnemy).en_vCurrentTranslationAbsolute.Length()==0.0f) { + // almost directly at the enemy + FLOAT3D vPlayerToThis = GetPlacement().pl_PositionVector - m_penEnemy->GetPlacement().pl_PositionVector; + vPlayerToThis.Normalize(); + vOffset = FLOAT3D(vPlayerToThis*(FRnd()*10.0f+5.0f)); + LaunchTwister(vOffset); + // to the left + vOffset = FLOAT3D(-(FRnd()*5.0f+15.0f), 0.0f, (FRnd()-0.5f)*20.0f)*((CMovableEntity &)*m_penEnemy).GetRotationMatrix(); + LaunchTwister(vOffset); + // to the right + vOffset = FLOAT3D(+(FRnd()*5.0f+15.0f), 0.0f, 20.0f)*((CMovableEntity &)*m_penEnemy).GetRotationMatrix(); + LaunchTwister(vOffset); + // moving enemy + } else { + FLOAT3D vPlayerSpeed = ((CMovableEntity &)*m_penEnemy).en_vCurrentTranslationAbsolute; + if (vPlayerSpeed.Length()>15.0f) { + vPlayerSpeed.Normalize(); + vPlayerSpeed = vPlayerSpeed*15.0f; + } + vOffset = vPlayerSpeed*(2.0f+FRnd()); + FLOAT3D vToPlayer = ((CMovableEntity &)*m_penEnemy).GetPlacement().pl_PositionVector - GetPlacement().pl_PositionVector; + vToPlayer.Normalize(); + vToPlayer*=15.0f + FRnd()*5.0f; + vOffset -= vToPlayer; + LaunchTwister(vOffset); + //LaunchTwister(vOffset+FLOAT3D(-5.0f-FRnd()*5.0f, 0.0f, -15.0f-FRnd()*5.0f)); + LaunchTwister(FLOAT3D(0.0f, 0.0f, 0.0f)); + LaunchTwister(vOffset+FLOAT3D(+5.0f+FRnd()*5.0f, 0.0f, -15.0f-FRnd()*5.0f)); + } + + //PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + + autowait(ElementalModel()->GetAnimLength(ELEMENTAL_ANIM_FIRETWISTER)-4.0f); + // stand a while + ElementalModel()->PlayAnim(ELEMENTAL_ANIM_IDLE, AOF_LOOPING|AOF_SMOOTHCHANGE); + autowait(0.05f); + + return EReturn(); + }; + + Hit(EVoid) : CEnemyBase::Hit { + jump Fire(); + return EReturn(); + }; + +/************************************************************ + * D E A T H * + ************************************************************/ + Death(EVoid) : CEnemyBase::Death + { + m_fFadeStartTime = _pTimer->CurrentTick(); + m_bFadeOut = TRUE; + m_fFadeTime = 2.0f; + autowait(m_fFadeTime); + autocall CEnemyBase::Death() EEnd; + //GetModelObject()->mo_toBump.SetData( NULL); + return EEnd(); + }; + +/************************************************************ + * M A I N * + ************************************************************/ + + Grow() { + // we can only grow, never shrink + ASSERT(m_fAttSizeRequested>m_fAttSizeCurrent); + m_fLastSize = m_fTargetSize = m_fAttSizeCurrent; + + PlaySound(m_soSound, SOUND_ROAR, SOF_3D); + ElementalModel()->PlayAnim(ELEMENTAL_ANIM_IDLE, AOF_NORESTART); + + // stop rotations + SetDesiredRotation(ANGLE3D(0.0f, 0.0f, 0.0f)); + m_bAttGrow = TRUE; + while (m_fLastSizeGetPlacement().pl_PositionVector - GetPlacement().pl_PositionVector; + vToTarget.Normalize(); + DirectionVectorToAngles(vToTarget, aToTarget); + aToTarget(1) = aToTarget(1) - GetPlacement().pl_OrientationAngle(1); + aToTarget(1) = NormalizeAngle(aToTarget(1)); + SetDesiredRotation(FLOAT3D(aToTarget(1)/2.0f, 0.0f, 0.0f)); + } + + // grow + m_fLastSize = m_fTargetSize; + m_fTargetSize += m_fGrowSpeed*_pTimer->TickQuantum; + + // change collision box in the middle of growth + // NOTE: collision box definitions and animations in AirElemental.h + // have to be ordered so that the one with value 0 represents + // the initial one, then the boxes from 1-3 represent + // the scaled versions of the original, in order + FLOAT fMiddleSize = Lerp(m_fAttSizeCurrent, m_fAttSizeRequested, 0.33f); + if (m_fLastSize<=fMiddleSize && fMiddleSizeTickQuantum); + } + m_bAttGrow = FALSE; + + m_fAttSizeCurrent = afGrowArray[m_iSize][1]; + + m_fGrowSpeed *= 2.0f; + if (m_iSize==1) { + GetModelObject()->PlayAnim(AIRELEMENTAL_ANIM_SIZE50, AOF_LOOPING); + } + + jump CEnemyBase::MainLoop(); + } + + ElementalLoop() { + wait () { + on (EBegin) : + { + call CEnemyBase::MainLoop(); + } + on (EElementalGrow) : + { + call Grow(); + } + otherwise (): { + resume; + } + } + } + + Main(EVoid) { + + // declare yourself as a model + InitAsEditorModel(); + + SetCollisionFlags(ECF_IMMATERIAL); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetFlags(GetFlags()|ENF_ALIVE); + + en_fDensity = 10000.0f; + m_fDamageWounded = 1e6f; + + m_sptType = SPT_AIRSPOUTS; + m_bBoss = TRUE; + SetHealth(15000.0f); + m_fMaxHealth = 15000.0f; + // setup moving speed + m_fWalkSpeed = 0.0f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 245.0f); + m_fAttackRunSpeed = m_fWalkSpeed; + m_aAttackRotateSpeed = m_aWalkRotateSpeed; + m_fCloseRunSpeed = m_fWalkSpeed; + m_aCloseRotateSpeed = m_aWalkRotateSpeed; + // setup attack distances + m_fAttackDistance = 500.0f; + m_fCloseDistance = 60.0f; + m_fStopDistance = 30.0f; + m_fAttackFireTime = 4.0f; + m_fCloseFireTime = 4.0f; + m_fIgnoreRange = 1000.0f; + m_iScore = 500000; + + eiAirElemental.vSourceCenter[1] = AIRBOSS_EYES_HEIGHT*m_fAttSizeBegin; + eiAirElemental.vTargetCenter[1] = AIRBOSS_BODY_HEIGHT*m_fAttSizeBegin; + + // set your appearance + SetModel(MODEL_INVISIBLE); + AddAttachmentToModel(this, *GetModelObject(), AIRELEMENTAL_ATTACHMENT_BODY, MODEL_ELEMENTAL, TEXTURE_ELEMENTAL, 0, 0, TEXTURE_DETAIL_ELEM); + CAttachmentModelObject &amo0 = *GetModelObject()->GetAttachmentModel(AIRELEMENTAL_ATTACHMENT_BODY); + m_fAttPosY = amo0.amo_plRelative.pl_PositionVector(2); + StandingAnim(); + + m_fAttSizeCurrent = m_fAttSizeBegin; + + GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f)); + ModelChangeNotify(); + ElementalModel()->StretchModel(FLOAT3D(m_fAttSizeBegin, m_fAttSizeBegin, m_fAttSizeBegin)); + + m_bRenderParticles=FALSE; + autowait(_pTimer->TickQuantum); + + m_emEmiter.Initialize(this); + m_emEmiter.em_etType=ET_AIR_ELEMENTAL; + + m_tmDeath = 1e6f; + + /* + CPlacement3D pl=GetPlacement(); + ETwister et; + CEntityPointer penTwister = CreateEntity(pl, CLASS_TWISTER); + et.penOwner = this; + et.fSize = 6.0f; + et.fDuration = 1e6; + et.sgnSpinDir = (INDEX)(Sgn(FRnd()-0.5f)); + et.bMovingAllowed=FALSE; + et.bGrow = FALSE; + penTwister->Initialize(et); + penTwister->SetParent(this); + */ + + // wait to be triggered + wait() { + on (EBegin) : { resume; } + on (ETrigger) : { stop; } + otherwise (): { resume; } + } + + SetCollisionFlags(ECF_AIR); + SetPhysicsFlags(EPF_MODEL_WALKING); + + ElementalModel()->PlayAnim(ELEMENTAL_ANIM_RAISE, AOF_NORESTART); + m_bRenderParticles=TRUE; + //SwitchToModel(); + m_bInitialAnim = TRUE; + // TODO: start particle animation + autowait(ElementalModel()->GetAnimLength(ELEMENTAL_ANIM_RAISE)); + // TODO: stop particle animation + ChangeCollisionBoxIndexWhenPossible(AIRELEMENTAL_COLLISION_BOX_COLLISION01); + + // deafult size + GetModelObject()->PlayAnim(AIRELEMENTAL_ANIM_DEFAULT, AOF_LOOPING); + + ElementalModel()->PlayAnim(ELEMENTAL_ANIM_IDLE, AOF_LOOPING); + m_bInitialAnim = FALSE; + m_bFloat = TRUE; + + m_tmWindNextFire = _pTimer->CurrentTick() + 10.0f; + + // one state under base class to intercept some events + jump ElementalLoop(); + //jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/AirElemental.h b/Sources/EntitiesMP/AirElemental.h new file mode 100644 index 0000000..d52d4cf --- /dev/null +++ b/Sources/EntitiesMP/AirElemental.h @@ -0,0 +1,204 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_AirElemental_INCLUDED +#define _EntitiesMP_AirElemental_INCLUDED 1 +#include +#include +#define EVENTCODE_EElementalGrow 0x015b0000 +class DECL_DLL EElementalGrow : public CEntityEvent { +public: +EElementalGrow(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EElementalGrow &e) { e = EElementalGrow(); } ; +extern "C" DECL_DLL CDLLEntityClass CAirElemental_DLLClass; +class CAirElemental : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bFloat; + FLOAT m_fAttPosY; + BOOL m_bInitialAnim; + CEntityPointer m_penTrigger01; + CEntityPointer m_penTrigger02; + CEntityPointer m_penTrigger03; + CEntityPointer m_penTrigger04; + CEntityPointer m_penTrigger05; + CEntityPointer m_penTrigger06; + CEntityPointer m_penTrigger07; + CEntityPointer m_penTrigger08; + CEntityPointer m_penTrigger09; + CEntityPointer m_penTrigger10; + FLOAT m_fAttSizeCurrent; + FLOAT m_fAttSizeBegin; + FLOAT m_fAttSizeEnd; + FLOAT m_fAttSizeRequested; + BOOL m_bAttGrow; + INDEX m_iSize; + FLOAT m_fLastSize; + FLOAT m_fTargetSize; + FLOAT m_fGrowSpeed; + FLOAT m_tmWindNextFire; + FLOAT m_fWindFireTimeMin; + FLOAT m_fWindFireTimeMax; + INDEX m_iWind; + BOOL m_bDying; + FLOAT m_tmDeath; + FLOAT m_fDeathDuration; + FLOAT3D m_fWindBlastFirePosBegin; + FLOAT3D m_fWindBlastFirePosEnd; + FLOAT m_tmLastAnimation; + CEntityPointer m_penDeathInflictor; + BOOL m_bRenderParticles; + CSoundObject m_soFire; + CSoundObject m_soVoice; + COLOR m_colParticles; +CEmiter m_emEmiter; + +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void Read_t(CTStream * istr); + +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void Write_t(CTStream * istr); + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void Precache(void); + +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void * GetEntityInfo(void); + +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +CModelObject * ElementalModel(void); + +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void StandingAnimFight(void); + +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void StandingAnim(void); + +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void WalkingAnim(void); + +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void RunningAnim(void); + +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void RotatingAnim(void); + +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +INDEX AnimForDeath(void); + +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void IdleSound(void); + +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void WoundSound(void); + +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void SizeModel(void); + +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void BlowUp(void); + +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void EnemyPostInit(void); + +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void LaunchTwister(FLOAT3D vEnemyOffset); + +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void PreMoving(); + +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void GetAirElementalAttachmentData(INDEX iAttachment,FLOATmatrix3D & mRot,FLOAT3D & vPos); + +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +FLOAT GetCurrentStretchRatio(void); + +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +void RenderParticles(void); +#define STATE_CAirElemental_Die 0x015b0001 + BOOL +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Die(const CEntityEvent &__eeInput); + BOOL H0x015b0002_Die_01(const CEntityEvent &__eeInput); + BOOL H0x015b0003_Die_02(const CEntityEvent &__eeInput); + BOOL H0x015b0004_Die_03(const CEntityEvent &__eeInput); + BOOL H0x015b0005_Die_04(const CEntityEvent &__eeInput); +#define STATE_CAirElemental_Fire 0x015b0006 + BOOL +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x015b0007_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x015b0008_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x015b0009_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x015b000a_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x015b000b_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x015b000c_Fire_06(const CEntityEvent &__eeInput); + BOOL H0x015b000d_Fire_07(const CEntityEvent &__eeInput); + BOOL H0x015b000e_Fire_08(const CEntityEvent &__eeInput); + BOOL H0x015b000f_Fire_09(const CEntityEvent &__eeInput); + BOOL H0x015b0010_Fire_10(const CEntityEvent &__eeInput); + BOOL H0x015b0011_Fire_11(const CEntityEvent &__eeInput); + BOOL H0x015b0012_Fire_12(const CEntityEvent &__eeInput); + BOOL H0x015b0013_Fire_13(const CEntityEvent &__eeInput); + BOOL H0x015b0014_Fire_14(const CEntityEvent &__eeInput); + BOOL H0x015b0015_Fire_15(const CEntityEvent &__eeInput); + BOOL H0x015b0016_Fire_16(const CEntityEvent &__eeInput); + BOOL H0x015b0017_Fire_17(const CEntityEvent &__eeInput); +#define STATE_CAirElemental_Hit 0x015b0018 + BOOL +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Hit(const CEntityEvent &__eeInput); +#define STATE_CAirElemental_Death 0x015b0019 + BOOL +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Death(const CEntityEvent &__eeInput); + BOOL H0x015b001a_Death_01(const CEntityEvent &__eeInput); + BOOL H0x015b001b_Death_02(const CEntityEvent &__eeInput); + BOOL H0x015b001c_Death_03(const CEntityEvent &__eeInput); + BOOL H0x015b001d_Death_04(const CEntityEvent &__eeInput); +#define STATE_CAirElemental_Grow 0x015b001e + BOOL +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Grow(const CEntityEvent &__eeInput); + BOOL H0x015b001f_Grow_01(const CEntityEvent &__eeInput); + BOOL H0x015b0020_Grow_02(const CEntityEvent &__eeInput); + BOOL H0x015b0021_Grow_03(const CEntityEvent &__eeInput); + BOOL H0x015b0022_Grow_04(const CEntityEvent &__eeInput); +#define STATE_CAirElemental_ElementalLoop 0x015b0023 + BOOL +#line 659 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalLoop(const CEntityEvent &__eeInput); + BOOL H0x015b0024_ElementalLoop_01(const CEntityEvent &__eeInput); + BOOL H0x015b0025_ElementalLoop_02(const CEntityEvent &__eeInput); +#define STATE_CAirElemental_Main 1 + BOOL +#line 675 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x015b0026_Main_01(const CEntityEvent &__eeInput); + BOOL H0x015b0027_Main_02(const CEntityEvent &__eeInput); + BOOL H0x015b0028_Main_03(const CEntityEvent &__eeInput); + BOOL H0x015b0029_Main_04(const CEntityEvent &__eeInput); + BOOL H0x015b002a_Main_05(const CEntityEvent &__eeInput); + BOOL H0x015b002b_Main_06(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_AirElemental_INCLUDED diff --git a/Sources/EntitiesMP/AirElemental_tables.h b/Sources/EntitiesMP/AirElemental_tables.h new file mode 100644 index 0000000..20b21b4 --- /dev/null +++ b/Sources/EntitiesMP/AirElemental_tables.h @@ -0,0 +1,149 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CAirElemental + +CEntityProperty CAirElemental_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015b<<8)+2, offsetof(CAirElemental, m_bFloat), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+3, offsetof(CAirElemental, m_fAttPosY), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015b<<8)+10, offsetof(CAirElemental, m_bInitialAnim), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+20, offsetof(CAirElemental, m_penTrigger01), "AirBoss 90% Trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+21, offsetof(CAirElemental, m_penTrigger02), "AirBoss 80% Trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+22, offsetof(CAirElemental, m_penTrigger03), "AirBoss 70% Trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+23, offsetof(CAirElemental, m_penTrigger04), "AirBoss 60% Trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+24, offsetof(CAirElemental, m_penTrigger05), "AirBoss 50% Trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+25, offsetof(CAirElemental, m_penTrigger06), "AirBoss 40% Trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+26, offsetof(CAirElemental, m_penTrigger07), "AirBoss 30% Trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+27, offsetof(CAirElemental, m_penTrigger08), "AirBoss 20% Trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+28, offsetof(CAirElemental, m_penTrigger09), "AirBoss 10% Trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+29, offsetof(CAirElemental, m_penTrigger10), "AirBoss 05% Trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+30, offsetof(CAirElemental, m_fAttSizeCurrent), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+31, offsetof(CAirElemental, m_fAttSizeBegin), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+32, offsetof(CAirElemental, m_fAttSizeEnd), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+33, offsetof(CAirElemental, m_fAttSizeRequested), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015b<<8)+34, offsetof(CAirElemental, m_bAttGrow), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+35, offsetof(CAirElemental, m_iSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+36, offsetof(CAirElemental, m_fLastSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+37, offsetof(CAirElemental, m_fTargetSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+47, offsetof(CAirElemental, m_fGrowSpeed), "AirBoss Grow Speed", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+43, offsetof(CAirElemental, m_tmWindNextFire), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+44, offsetof(CAirElemental, m_fWindFireTimeMin), "AirBoss Wind Fire Min. Time", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+45, offsetof(CAirElemental, m_fWindFireTimeMax), "AirBoss Wind Fire Max. Time", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+46, offsetof(CAirElemental, m_iWind), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015b<<8)+50, offsetof(CAirElemental, m_bDying), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+51, offsetof(CAirElemental, m_tmDeath), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+52, offsetof(CAirElemental, m_fDeathDuration), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015b<<8)+60, offsetof(CAirElemental, m_fWindBlastFirePosBegin), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015b<<8)+61, offsetof(CAirElemental, m_fWindBlastFirePosEnd), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+70, offsetof(CAirElemental, m_tmLastAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+90, offsetof(CAirElemental, m_penDeathInflictor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015b<<8)+91, offsetof(CAirElemental, m_bRenderParticles), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015b<<8)+100, offsetof(CAirElemental, m_soFire), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015b<<8)+101, offsetof(CAirElemental, m_soVoice), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000015b<<8)+110, offsetof(CAirElemental, m_colParticles), "Color of particles", 0, 0x7F0000FFUL, 0), +}; +#define CAirElemental_propertiesct ARRAYCOUNT(CAirElemental_properties) + +CEntityComponent CAirElemental_components[] = { +#define CLASS_BASE ((0x0000015b<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_TWISTER ((0x0000015b<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_TWISTER, "EFNM" "Classes\\Twister.ecl"), +#define CLASS_BLOOD_SPRAY ((0x0000015b<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define CLASS_PROJECTILE ((0x0000015b<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define MODEL_INVISIBLE ((0x0000015b<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_INVISIBLE, "EFNM" "ModelsMP\\Enemies\\AirElemental\\AirElemental.mdl"), +#define MODEL_ELEMENTAL ((0x0000015b<<8)+11) + CEntityComponent(ECT_MODEL, MODEL_ELEMENTAL, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Elemental.mdl"), +#define TEXTURE_ELEMENTAL ((0x0000015b<<8)+12) + CEntityComponent(ECT_TEXTURE, TEXTURE_ELEMENTAL, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Elemental.tex"), +#define TEXTURE_DETAIL_ELEM ((0x0000015b<<8)+13) + CEntityComponent(ECT_TEXTURE, TEXTURE_DETAIL_ELEM, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Detail.tex"), +#define SOUND_FIREWINDBLAST ((0x0000015b<<8)+200) + CEntityComponent(ECT_SOUND, SOUND_FIREWINDBLAST, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Sounds\\BlastFire.wav"), +#define SOUND_FIRETWISTER ((0x0000015b<<8)+201) + CEntityComponent(ECT_SOUND, SOUND_FIRETWISTER, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Sounds\\Fire.wav"), +#define SOUND_ROAR ((0x0000015b<<8)+202) + CEntityComponent(ECT_SOUND, SOUND_ROAR, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Sounds\\Anger.wav"), +#define SOUND_DEATH ((0x0000015b<<8)+203) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Sounds\\Death.wav"), +#define SOUND_EXPLOSION ((0x0000015b<<8)+204) + CEntityComponent(ECT_SOUND, SOUND_EXPLOSION, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Sounds\\Explosion.wav"), +}; +#define CAirElemental_componentsct ARRAYCOUNT(CAirElemental_components) + +CEventHandlerEntry CAirElemental_handlers[] = { + {0x015b0001, STATE_CEnemyBase_Die, CEntity::pEventHandler(&CAirElemental:: +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Die),DEBUGSTRING("CAirElemental::Die")}, + {0x015b0002, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0002_Die_01), DEBUGSTRING("CAirElemental::H0x015b0002_Die_01")}, + {0x015b0003, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0003_Die_02), DEBUGSTRING("CAirElemental::H0x015b0003_Die_02")}, + {0x015b0004, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0004_Die_03), DEBUGSTRING("CAirElemental::H0x015b0004_Die_03")}, + {0x015b0005, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0005_Die_04), DEBUGSTRING("CAirElemental::H0x015b0005_Die_04")}, + {0x015b0006, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CAirElemental:: +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Fire),DEBUGSTRING("CAirElemental::Fire")}, + {0x015b0007, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0007_Fire_01), DEBUGSTRING("CAirElemental::H0x015b0007_Fire_01")}, + {0x015b0008, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0008_Fire_02), DEBUGSTRING("CAirElemental::H0x015b0008_Fire_02")}, + {0x015b0009, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0009_Fire_03), DEBUGSTRING("CAirElemental::H0x015b0009_Fire_03")}, + {0x015b000a, -1, CEntity::pEventHandler(&CAirElemental::H0x015b000a_Fire_04), DEBUGSTRING("CAirElemental::H0x015b000a_Fire_04")}, + {0x015b000b, -1, CEntity::pEventHandler(&CAirElemental::H0x015b000b_Fire_05), DEBUGSTRING("CAirElemental::H0x015b000b_Fire_05")}, + {0x015b000c, -1, CEntity::pEventHandler(&CAirElemental::H0x015b000c_Fire_06), DEBUGSTRING("CAirElemental::H0x015b000c_Fire_06")}, + {0x015b000d, -1, CEntity::pEventHandler(&CAirElemental::H0x015b000d_Fire_07), DEBUGSTRING("CAirElemental::H0x015b000d_Fire_07")}, + {0x015b000e, -1, CEntity::pEventHandler(&CAirElemental::H0x015b000e_Fire_08), DEBUGSTRING("CAirElemental::H0x015b000e_Fire_08")}, + {0x015b000f, -1, CEntity::pEventHandler(&CAirElemental::H0x015b000f_Fire_09), DEBUGSTRING("CAirElemental::H0x015b000f_Fire_09")}, + {0x015b0010, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0010_Fire_10), DEBUGSTRING("CAirElemental::H0x015b0010_Fire_10")}, + {0x015b0011, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0011_Fire_11), DEBUGSTRING("CAirElemental::H0x015b0011_Fire_11")}, + {0x015b0012, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0012_Fire_12), DEBUGSTRING("CAirElemental::H0x015b0012_Fire_12")}, + {0x015b0013, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0013_Fire_13), DEBUGSTRING("CAirElemental::H0x015b0013_Fire_13")}, + {0x015b0014, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0014_Fire_14), DEBUGSTRING("CAirElemental::H0x015b0014_Fire_14")}, + {0x015b0015, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0015_Fire_15), DEBUGSTRING("CAirElemental::H0x015b0015_Fire_15")}, + {0x015b0016, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0016_Fire_16), DEBUGSTRING("CAirElemental::H0x015b0016_Fire_16")}, + {0x015b0017, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0017_Fire_17), DEBUGSTRING("CAirElemental::H0x015b0017_Fire_17")}, + {0x015b0018, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CAirElemental:: +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Hit),DEBUGSTRING("CAirElemental::Hit")}, + {0x015b0019, STATE_CEnemyBase_Death, CEntity::pEventHandler(&CAirElemental:: +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Death),DEBUGSTRING("CAirElemental::Death")}, + {0x015b001a, -1, CEntity::pEventHandler(&CAirElemental::H0x015b001a_Death_01), DEBUGSTRING("CAirElemental::H0x015b001a_Death_01")}, + {0x015b001b, -1, CEntity::pEventHandler(&CAirElemental::H0x015b001b_Death_02), DEBUGSTRING("CAirElemental::H0x015b001b_Death_02")}, + {0x015b001c, -1, CEntity::pEventHandler(&CAirElemental::H0x015b001c_Death_03), DEBUGSTRING("CAirElemental::H0x015b001c_Death_03")}, + {0x015b001d, -1, CEntity::pEventHandler(&CAirElemental::H0x015b001d_Death_04), DEBUGSTRING("CAirElemental::H0x015b001d_Death_04")}, + {0x015b001e, -1, CEntity::pEventHandler(&CAirElemental:: +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Grow),DEBUGSTRING("CAirElemental::Grow")}, + {0x015b001f, -1, CEntity::pEventHandler(&CAirElemental::H0x015b001f_Grow_01), DEBUGSTRING("CAirElemental::H0x015b001f_Grow_01")}, + {0x015b0020, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0020_Grow_02), DEBUGSTRING("CAirElemental::H0x015b0020_Grow_02")}, + {0x015b0021, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0021_Grow_03), DEBUGSTRING("CAirElemental::H0x015b0021_Grow_03")}, + {0x015b0022, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0022_Grow_04), DEBUGSTRING("CAirElemental::H0x015b0022_Grow_04")}, + {0x015b0023, -1, CEntity::pEventHandler(&CAirElemental:: +#line 659 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +ElementalLoop),DEBUGSTRING("CAirElemental::ElementalLoop")}, + {0x015b0024, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0024_ElementalLoop_01), DEBUGSTRING("CAirElemental::H0x015b0024_ElementalLoop_01")}, + {0x015b0025, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0025_ElementalLoop_02), DEBUGSTRING("CAirElemental::H0x015b0025_ElementalLoop_02")}, + {1, -1, CEntity::pEventHandler(&CAirElemental:: +#line 675 "D:/SE1_GPL/Sources/EntitiesMP/AirElemental.es" +Main),DEBUGSTRING("CAirElemental::Main")}, + {0x015b0026, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0026_Main_01), DEBUGSTRING("CAirElemental::H0x015b0026_Main_01")}, + {0x015b0027, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0027_Main_02), DEBUGSTRING("CAirElemental::H0x015b0027_Main_02")}, + {0x015b0028, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0028_Main_03), DEBUGSTRING("CAirElemental::H0x015b0028_Main_03")}, + {0x015b0029, -1, CEntity::pEventHandler(&CAirElemental::H0x015b0029_Main_04), DEBUGSTRING("CAirElemental::H0x015b0029_Main_04")}, + {0x015b002a, -1, CEntity::pEventHandler(&CAirElemental::H0x015b002a_Main_05), DEBUGSTRING("CAirElemental::H0x015b002a_Main_05")}, + {0x015b002b, -1, CEntity::pEventHandler(&CAirElemental::H0x015b002b_Main_06), DEBUGSTRING("CAirElemental::H0x015b002b_Main_06")}, +}; +#define CAirElemental_handlersct ARRAYCOUNT(CAirElemental_handlers) + +CEntity *CAirElemental_New(void) { return new CAirElemental; }; +void CAirElemental_OnInitClass(void) {}; +void CAirElemental_OnEndClass(void) {}; +void CAirElemental_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CAirElemental_OnWorldEnd(CWorld *pwo) {}; +void CAirElemental_OnWorldInit(CWorld *pwo) {}; +void CAirElemental_OnWorldTick(CWorld *pwo) {}; +void CAirElemental_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CAirElemental, CEnemyBase, "AirElemental", "Thumbnails\\AirElemental.tbn", 0x0000015b); +DECLARE_CTFILENAME(_fnmCAirElemental_tbn, "Thumbnails\\AirElemental.tbn"); diff --git a/Sources/EntitiesMP/AirShockwave.cpp b/Sources/EntitiesMP/AirShockwave.cpp new file mode 100644 index 0000000..091cd76 --- /dev/null +++ b/Sources/EntitiesMP/AirShockwave.cpp @@ -0,0 +1,281 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 6 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/AirElemental/ShockwaveBase.h" +#include "ModelsMP/Enemies/AirElemental/Shockwave.h" + +#include +#include +CEntityEvent *EAirShockwave::MakeCopy(void) { CEntityEvent *peeCopy = new EAirShockwave(*this); return peeCopy;} +EAirShockwave::EAirShockwave() : CEntityEvent(EVENTCODE_EAirShockwave) {; + ClearToDefault(penLauncher); + ClearToDefault(fHeight); + ClearToDefault(fEndWidth); + ClearToDefault(fDuration); +}; +#line 22 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" + +// shockwave +#define ECF_SHOCKAWAVE ( \ + ((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)< GetAttachmentModel (SHOCKWAVEBASE_ATTACHMENT_SHOCKWAVE ); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +return & (amo0 . amo_moModelObject ); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +} + +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +BOOL CAirShockwave::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) { +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +if(m_bGrowing ){ +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOAT3D vSize ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOAT fLifeTime = _pTimer -> GetLerpedCurrentTick () - m_tmBegin ; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +vSize (1) = (fLifeTime / m_fDuration ) * (m_fEndStretchXZ - m_fBeginStretchXZ ) + m_fBeginStretchXZ ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +vSize (2) = m_fStretchY ; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +vSize (3) = vSize (1); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +ShockwaveModel () -> StretchModel (vSize ); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +if((fLifeTime / m_fDuration ) > m_fFadeStartPercent && ! m_bFadeOut ){ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_bFadeOut = TRUE ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_fFadeStartTime = _pTimer -> GetLerpedCurrentTick (); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +} +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_tmLastGrow = _pTimer -> GetLerpedCurrentTick (); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +} +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +if(m_bFadeOut ){ +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOAT fTimeRemain = m_tmEnd - _pTimer -> GetLerpedCurrentTick (); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOAT fFadeTime = (1 - m_fFadeStartPercent ) * m_fDuration ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +if(fTimeRemain < 0.0f){fTimeRemain = 0.0f;} +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +COLOR colAlpha = ShockwaveModel () -> mo_colBlendColor ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +colAlpha = (colAlpha & 0xffffff00) + (COLOR (fTimeRemain / fFadeTime * 0xff) & 0xff); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +ShockwaveModel () -> mo_colBlendColor = colAlpha ; +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +} +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +return CMovableModelEntity :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +} + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +void CAirShockwave::LaunchEntity(CEntity * pen) { +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +if(IsOfClass (pen , "AirElemental") || IsOfClass (pen , "Twister") +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +|| IsDerivedFromClass (pen , "Item") || IsOfClass (pen , "AirShockwave")){ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +return ; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +} +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +if(pen -> GetPhysicsFlags () & EPF_MOVABLE ){ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOAT3D vSpeed ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +vSpeed = pen -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +if(vSpeed (2) < vSpeed . Length () * 0.5f){vSpeed (2) = vSpeed . Length () * 0.5f;} +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +vSpeed . Normalize (); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +vSpeed = vSpeed * 50.0f; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +((CMovableEntity &) * pen ) . GiveImpulseTranslationAbsolute (vSpeed ); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +} +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +} + +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +void CAirShockwave::TestForCollisionAndLaunchEntity() { +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +static CStaticStackArray < CEntity * > apenNearEntities ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOAT fLifeTime = _pTimer -> CurrentTick () - m_tmBegin ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOAT fCurrentRadius = Lerp (SHOCKWAVE_WIDTH , m_fEndWidth , fLifeTime / m_fDuration ) / 2.0f; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOATaabbox3D m_boxCurrent = m_boxMaxSize ; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_boxCurrent += GetPlacement () . pl_PositionVector ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOAT fBeltWidth = m_fEndWidth * _pTimer -> TickQuantum * 2.0f / m_fDuration ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +GetWorld () -> FindEntitiesNearBox (m_boxCurrent , apenNearEntities ); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +for(INDEX i = 0;i < apenNearEntities . Count ();i ++) +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +{ +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOAT fDistance = DistanceTo (this , apenNearEntities [ i ]); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOATaabbox3D m_boxEntity ; +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +apenNearEntities [ i ] -> GetBoundingBox (m_boxEntity ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +if(fDistance < (fCurrentRadius + fBeltWidth / 2.0f) && fDistance > (fCurrentRadius - fBeltWidth / 2.0f) && +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_boxEntity . HasContactWith (m_boxCurrent )){ +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +LaunchEntity (apenNearEntities [ i ]); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +} +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +CMovableModelEntity :: PreMoving (); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +} +BOOL CAirShockwave:: +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAirShockwave_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EAirShockwave, "CAirShockwave::Main expects 'EAirShockwave' as input!"); const EAirShockwave &eas = (const EAirShockwave &)__eeInput; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +ASSERT (eas . penLauncher != NULL ); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +ASSERT (eas . fHeight > 0.0f); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +ASSERT (eas . fEndWidth > 0.1f); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +ASSERT (eas . fDuration > 0.0f); +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_penLauncher = eas . penLauncher ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_fHeight = eas . fHeight ; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_fEndWidth = eas . fEndWidth ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_fDuration = eas . fDuration ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_fStretchY = m_fHeight / SHOCKWAVE_HEIGHT ; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_fBeginStretchXZ = 1.0f; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_fEndStretchXZ = m_fEndWidth / SHOCKWAVE_WIDTH ; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOAT3D v1 = FLOAT3D (- m_fEndWidth / 2.0f , 0.0f , - m_fEndWidth / 2.0f); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +FLOAT3D v2 = FLOAT3D (+ m_fEndWidth / 2.0f , m_fHeight , + m_fEndWidth / 2.0f); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_boxMaxSize = FLOATaabbox3D (v1 , v2 ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +InitAsModel (); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +SetPhysicsFlags (EPF_SHOCKAWAVE ); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +SetCollisionFlags (ECF_SHOCKAWAVE ); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +SetModel (MODEL_INVISIBLE ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +AddAttachmentToModel (this , * GetModelObject () , SHOCKWAVEBASE_ATTACHMENT_SHOCKWAVE , MODEL_SHOCKWAVE , TEXTURE_SHOCKWAVE , 0 , 0 , 0); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +GetModelObject () -> StretchModel (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +ModelChangeNotify (); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +ShockwaveModel () -> StretchModel (FLOAT3D (m_fBeginStretchXZ , m_fStretchY , m_fBeginStretchXZ )); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x015d0001, FALSE, EBegin());return TRUE;}BOOL CAirShockwave::H0x015d0001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015d0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015d0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirShockwave::H0x015d0002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015d0002 +; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_tmBegin = _pTimer -> CurrentTick (); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_tmEnd = m_tmBegin + m_fDuration ; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_tmLastGrow = _pTimer -> CurrentTick (); +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +m_bGrowing = TRUE ; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +Jump(STATE_CURRENT,0x015d0005, FALSE, EInternal());return TRUE;}BOOL CAirShockwave::H0x015d0005_Main_05(const CEntityEvent &__eeInput) +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015d0005 +if(!(_pTimer -> CurrentTick () < m_tmEnd )){ Jump(STATE_CURRENT,0x015d0006, FALSE, EInternal());return TRUE;} +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x015d0003, FALSE, EBegin());return TRUE;}BOOL CAirShockwave::H0x015d0003_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015d0003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015d0004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAirShockwave::H0x015d0004_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015d0004 +; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +TestForCollisionAndLaunchEntity ();Jump(STATE_CURRENT,0x015d0005, FALSE, EInternal());return TRUE; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +}BOOL CAirShockwave::H0x015d0006_Main_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015d0006 + +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +Destroy (); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +Return(STATE_CURRENT,EVoid()); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/AirShockwave.es b/Sources/EntitiesMP/AirShockwave.es new file mode 100644 index 0000000..fc23fad --- /dev/null +++ b/Sources/EntitiesMP/AirShockwave.es @@ -0,0 +1,207 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// WARNING: probable sync bads, doesn't work right + +349 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/AirElemental/ShockwaveBase.h" +#include "ModelsMP/Enemies/AirElemental/Shockwave.h" +%} + +uses "EntitiesMP/BasicEffects"; + +// input parameter for launching the projectile +event EAirShockwave { + CEntityPointer penLauncher, // who launched it + FLOAT fHeight, // height in the beginning + FLOAT fEndWidth, // width along the X,Z axes in the end + FLOAT fDuration, // how long to live +}; + +%{ +// shockwave +#define ECF_SHOCKAWAVE ( \ + ((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)<GetAttachmentModel(SHOCKWAVEBASE_ATTACHMENT_SHOCKWAVE); + return &(amo0.amo_moModelObject); + }; + + // per-frame adjustments here + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) { + // growing + if (m_bGrowing) { + FLOAT3D vSize; + FLOAT fLifeTime = _pTimer->GetLerpedCurrentTick() - m_tmBegin; + vSize(1) = (fLifeTime/m_fDuration)*(m_fEndStretchXZ-m_fBeginStretchXZ)+m_fBeginStretchXZ; + vSize(2) = m_fStretchY; + vSize(3) = vSize(1); + + ShockwaveModel()->StretchModel(vSize); + + // start fadeout if more than 70% of lifetime passed + if ((fLifeTime/m_fDuration)>m_fFadeStartPercent && !m_bFadeOut) { + m_bFadeOut = TRUE; + m_fFadeStartTime = _pTimer->GetLerpedCurrentTick(); + } + + // remember last grow time + m_tmLastGrow = _pTimer->GetLerpedCurrentTick(); + } + + // fading out + if (m_bFadeOut) { + FLOAT fTimeRemain = m_tmEnd - _pTimer->GetLerpedCurrentTick(); + FLOAT fFadeTime = (1 - m_fFadeStartPercent)*m_fDuration; + if (fTimeRemain < 0.0f) { fTimeRemain = 0.0f; } + COLOR colAlpha = ShockwaveModel()->mo_colBlendColor; + colAlpha = (colAlpha&0xffffff00) + (COLOR(fTimeRemain/fFadeTime*0xff)&0xff); + ShockwaveModel()->mo_colBlendColor = colAlpha; + } + return CMovableModelEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + }; + + + // throw away an entity when touched + void LaunchEntity(CEntity *pen) { + // don't launch air elemental and twisters and shockwaves and any items + if (IsOfClass(pen, "AirElemental") || IsOfClass(pen, "Twister") + || IsDerivedFromClass(pen, "Item") || IsOfClass(pen, "AirShockwave")) { + return; + } + if (pen->GetPhysicsFlags()&EPF_MOVABLE) { + FLOAT3D vSpeed; + vSpeed = pen->GetPlacement().pl_PositionVector - GetPlacement().pl_PositionVector; + if (vSpeed(2) apenNearEntities; + FLOAT fLifeTime = _pTimer->CurrentTick() - m_tmBegin; + FLOAT fCurrentRadius = Lerp(SHOCKWAVE_WIDTH, m_fEndWidth, fLifeTime/m_fDuration)/2.0f; + + FLOATaabbox3D m_boxCurrent = m_boxMaxSize; + m_boxCurrent += GetPlacement().pl_PositionVector; + + // width of 'launch belt' + FLOAT fBeltWidth = m_fEndWidth*_pTimer->TickQuantum*2.0f/m_fDuration; + + GetWorld()->FindEntitiesNearBox(m_boxCurrent, apenNearEntities); + for (INDEX i=0; iGetBoundingBox(m_boxEntity); + if (fDistance<(fCurrentRadius+fBeltWidth/2.0f) && fDistance>(fCurrentRadius-fBeltWidth/2.0f) && + m_boxEntity.HasContactWith(m_boxCurrent)) { + LaunchEntity(apenNearEntities[i]); + } + } + + CMovableModelEntity::PreMoving(); + }; + +procedures: + + // --->>> MAIN + Main(EAirShockwave eas) { + // remember the initial parameters + ASSERT(eas.penLauncher!=NULL); + ASSERT(eas.fHeight>0.0f); + ASSERT(eas.fEndWidth>0.1f); + ASSERT(eas.fDuration>0.0f); + m_penLauncher = eas.penLauncher; + m_fHeight = eas.fHeight; + m_fEndWidth = eas.fEndWidth; + m_fDuration = eas.fDuration; + + // calculate stretches from parameters + m_fStretchY = m_fHeight/SHOCKWAVE_HEIGHT; + m_fBeginStretchXZ = 1.0f; + m_fEndStretchXZ = m_fEndWidth/SHOCKWAVE_WIDTH; + + FLOAT3D v1 = FLOAT3D(-m_fEndWidth/2.0f, 0.0f, -m_fEndWidth/2.0f); + FLOAT3D v2 = FLOAT3D(+m_fEndWidth/2.0f, m_fHeight, +m_fEndWidth/2.0f); + m_boxMaxSize = FLOATaabbox3D(v1, v2); + + // initialization + InitAsModel(); + SetPhysicsFlags(EPF_SHOCKAWAVE); + SetCollisionFlags(ECF_SHOCKAWAVE); + SetFlags(GetFlags() | ENF_SEETHROUGH); + + // set appearance + SetModel(MODEL_INVISIBLE); + AddAttachmentToModel(this, *GetModelObject(), SHOCKWAVEBASE_ATTACHMENT_SHOCKWAVE, MODEL_SHOCKWAVE, TEXTURE_SHOCKWAVE, 0, 0, 0); + GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f)); + ModelChangeNotify(); + ShockwaveModel()->StretchModel(FLOAT3D(m_fBeginStretchXZ, m_fStretchY, m_fBeginStretchXZ)); + + autowait(_pTimer->TickQuantum); + + m_tmBegin = _pTimer->CurrentTick(); + m_tmEnd = m_tmBegin + m_fDuration; + m_tmLastGrow = _pTimer->CurrentTick(); + m_bGrowing = TRUE; + + while(_pTimer->CurrentTick()TickQuantum); + TestForCollisionAndLaunchEntity(); + } + // cease to exist + Destroy(); + return; + } +}; diff --git a/Sources/EntitiesMP/AirShockwave.h b/Sources/EntitiesMP/AirShockwave.h new file mode 100644 index 0000000..84efa89 --- /dev/null +++ b/Sources/EntitiesMP/AirShockwave.h @@ -0,0 +1,61 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_AirShockwave_INCLUDED +#define _EntitiesMP_AirShockwave_INCLUDED 1 +#include +#define EVENTCODE_EAirShockwave 0x015d0000 +class DECL_DLL EAirShockwave : public CEntityEvent { +public: +EAirShockwave(); +CEntityEvent *MakeCopy(void); +CEntityPointer penLauncher; +FLOAT fHeight; +FLOAT fEndWidth; +FLOAT fDuration; +}; +DECL_DLL inline void ClearToDefault(EAirShockwave &e) { e = EAirShockwave(); } ; +extern "C" DECL_DLL CDLLEntityClass CAirShockwave_DLLClass; +class CAirShockwave : public CMovableModelEntity { +public: + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penLauncher; + FLOAT m_fHeight; + FLOAT m_fEndWidth; + FLOAT m_tmBegin; + FLOAT m_tmEnd; + FLOAT m_fDuration; + BOOL m_bGrowing; + FLOAT m_tmLastGrow; + FLOAT m_fFadeStartTime; + FLOAT m_fFadeStartPercent; + FLOAT m_fStretchY; + FLOAT m_fBeginStretchXZ; + FLOAT m_fEndStretchXZ; + FLOATaabbox3D m_boxMaxSize; + BOOL m_bFadeOut; + +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +CModelObject * ShockwaveModel(void); + +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +void LaunchEntity(CEntity * pen); + +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +void TestForCollisionAndLaunchEntity(); +#define STATE_CAirShockwave_Main 1 + BOOL +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x015d0001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x015d0002_Main_02(const CEntityEvent &__eeInput); + BOOL H0x015d0003_Main_03(const CEntityEvent &__eeInput); + BOOL H0x015d0004_Main_04(const CEntityEvent &__eeInput); + BOOL H0x015d0005_Main_05(const CEntityEvent &__eeInput); + BOOL H0x015d0006_Main_06(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_AirShockwave_INCLUDED diff --git a/Sources/EntitiesMP/AirShockwave_tables.h b/Sources/EntitiesMP/AirShockwave_tables.h new file mode 100644 index 0000000..40dfa70 --- /dev/null +++ b/Sources/EntitiesMP/AirShockwave_tables.h @@ -0,0 +1,60 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CAirShockwave + +CEntityProperty CAirShockwave_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015d<<8)+1, offsetof(CAirShockwave, m_penLauncher), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015d<<8)+2, offsetof(CAirShockwave, m_fHeight), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015d<<8)+3, offsetof(CAirShockwave, m_fEndWidth), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015d<<8)+4, offsetof(CAirShockwave, m_tmBegin), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015d<<8)+5, offsetof(CAirShockwave, m_tmEnd), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015d<<8)+6, offsetof(CAirShockwave, m_fDuration), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015d<<8)+7, offsetof(CAirShockwave, m_bGrowing), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015d<<8)+8, offsetof(CAirShockwave, m_tmLastGrow), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015d<<8)+9, offsetof(CAirShockwave, m_fFadeStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015d<<8)+10, offsetof(CAirShockwave, m_fFadeStartPercent), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015d<<8)+20, offsetof(CAirShockwave, m_fStretchY), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015d<<8)+21, offsetof(CAirShockwave, m_fBeginStretchXZ), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015d<<8)+22, offsetof(CAirShockwave, m_fEndStretchXZ), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATAABBOX3D, NULL, (0x0000015d<<8)+25, offsetof(CAirShockwave, m_boxMaxSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015d<<8)+30, offsetof(CAirShockwave, m_bFadeOut), "", 0, 0, 0), +}; +#define CAirShockwave_propertiesct ARRAYCOUNT(CAirShockwave_properties) + +CEntityComponent CAirShockwave_components[] = { +#define CLASS_BASIC_EFFECT ((0x0000015d<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define MODEL_INVISIBLE ((0x0000015d<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_INVISIBLE, "EFNM" "ModelsMP\\Enemies\\AirElemental\\ShockwaveBase.mdl"), +#define MODEL_SHOCKWAVE ((0x0000015d<<8)+11) + CEntityComponent(ECT_MODEL, MODEL_SHOCKWAVE, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Shockwave.mdl"), +#define TEXTURE_SHOCKWAVE ((0x0000015d<<8)+12) + CEntityComponent(ECT_TEXTURE, TEXTURE_SHOCKWAVE, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Twister.tex"), +}; +#define CAirShockwave_componentsct ARRAYCOUNT(CAirShockwave_components) + +CEventHandlerEntry CAirShockwave_handlers[] = { + {1, -1, CEntity::pEventHandler(&CAirShockwave:: +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/AirShockwave.es" +Main),DEBUGSTRING("CAirShockwave::Main")}, + {0x015d0001, -1, CEntity::pEventHandler(&CAirShockwave::H0x015d0001_Main_01), DEBUGSTRING("CAirShockwave::H0x015d0001_Main_01")}, + {0x015d0002, -1, CEntity::pEventHandler(&CAirShockwave::H0x015d0002_Main_02), DEBUGSTRING("CAirShockwave::H0x015d0002_Main_02")}, + {0x015d0003, -1, CEntity::pEventHandler(&CAirShockwave::H0x015d0003_Main_03), DEBUGSTRING("CAirShockwave::H0x015d0003_Main_03")}, + {0x015d0004, -1, CEntity::pEventHandler(&CAirShockwave::H0x015d0004_Main_04), DEBUGSTRING("CAirShockwave::H0x015d0004_Main_04")}, + {0x015d0005, -1, CEntity::pEventHandler(&CAirShockwave::H0x015d0005_Main_05), DEBUGSTRING("CAirShockwave::H0x015d0005_Main_05")}, + {0x015d0006, -1, CEntity::pEventHandler(&CAirShockwave::H0x015d0006_Main_06), DEBUGSTRING("CAirShockwave::H0x015d0006_Main_06")}, +}; +#define CAirShockwave_handlersct ARRAYCOUNT(CAirShockwave_handlers) + +CEntity *CAirShockwave_New(void) { return new CAirShockwave; }; +void CAirShockwave_OnInitClass(void) {}; +void CAirShockwave_OnEndClass(void) {}; +void CAirShockwave_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CAirShockwave_OnWorldEnd(CWorld *pwo) {}; +void CAirShockwave_OnWorldInit(CWorld *pwo) {}; +void CAirShockwave_OnWorldTick(CWorld *pwo) {}; +void CAirShockwave_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CAirShockwave, CMovableModelEntity, "AirShockwave", "", 0x0000015d); +DECLARE_CTFILENAME(_fnmCAirShockwave_tbn, ""); diff --git a/Sources/EntitiesMP/AmmoItem.cpp b/Sources/EntitiesMP/AmmoItem.cpp new file mode 100644 index 0000000..26b8b5a --- /dev/null +++ b/Sources/EntitiesMP/AmmoItem.cpp @@ -0,0 +1,521 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" + +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" +#include "Models/Items/Ammo/Shells/Shells.h" +#include "Models/Items/Ammo/Bullets/Bullets.h" +#include "Models/Items/Ammo/Rockets/Rockets.h" +#include "Models/Weapons/RocketLauncher/Projectile/Rocket.h" +#include "Models/Items/Ammo/Grenades/Grenades.h" +#include "Models/Items/Ammo/Electricity/Electricity.h" +#include "Models/Items/Ammo/Cannonball/Cannonball.h" +#include "Models/Items/Ammo/Cannonball/CannonballQuad.h" +#include "ModelsMP/Items/Ammo/SniperBullets/SniperBullets.h" + +#include +#include +CEntityEvent *EAmmoItem::MakeCopy(void) { CEntityEvent *peeCopy = new EAmmoItem(*this); return peeCopy;} +EAmmoItem::EAmmoItem() : CEntityEvent(EVENTCODE_EAmmoItem) {; + ClearToDefault(EaitType); + ClearToDefault(iQuantity); +}; +void CAmmoItem::SetDefaultProperties(void) { + m_EaitType = AIT_SHELLS ; + CItem::SetDefaultProperties(); +} + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +void CAmmoItem::Precache(void) { +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +PrecacheSound (SOUND_PICK ); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +void CAmmoItem::RenderParticles(void) { +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +if(GetRenderType () != CEntity :: RT_MODEL || GetSP () -> sp_gmGameMode > CSessionProperties :: GM_COOPERATIVE +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +|| ! ShowItemParticles ()) +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +{ +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +return ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +switch(m_EaitType ){ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_SHELLS : +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Particles_Spiral (this , 1.0f * 0.75 , 1.0f * 0.75 , PT_STAR04 , 4); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_BULLETS : +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Particles_Spiral (this , 1.5f * 0.75 , 1.0f * 0.75 , PT_STAR04 , 6); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_ROCKETS : +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Particles_Spiral (this , 1.5f * 0.75 , 1.25f * 0.75 , PT_STAR04 , 6); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_GRENADES : +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Particles_Spiral (this , 2.0f * 0.75 , 1.25f * 0.75 , PT_STAR04 , 6); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_ELECTRICITY : +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Particles_Spiral (this , 1.5f * 0.75 , 1.125f * 0.75 , PT_STAR04 , 6); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_NUKEBALL : +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Particles_Spiral (this , 1.25f * 0.75 , 1.0f * 0.75 , PT_STAR04 , 4); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_IRONBALLS : +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Particles_Spiral (this , 2.0f * 0.75 , 1.25f * 0.75 , PT_STAR04 , 8); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_BACKPACK : +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Particles_Spiral (this , 3.0f * 0.5 , 2.5f * 0.5 , PT_STAR04 , 10); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_SERIOUSPACK : +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Particles_Spiral (this , 3.0f * 0.5 , 2.5f * 0.5 , PT_STAR04 , 10); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_NAPALM : +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Particles_Spiral (this , 3.0f * 0.5 , 2.5f * 0.5 , PT_STAR04 , 10); +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_SNIPERBULLETS : +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Particles_Spiral (this , 1.5f * 0.75 , 1.25f * 0.75 , PT_STAR04 , 6); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} + +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +BOOL CAmmoItem::FillEntityStatistics(EntityStats * pes) +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +{ +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_ctCount = 1; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_ctAmmount = m_fValue ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +switch(m_EaitType ){ +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_SHELLS : +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_strName = "Shells"; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_fValue = m_fValue * AV_SHELLS ; +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_BULLETS : +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_strName = "Bullets"; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_fValue = m_fValue * AV_BULLETS ; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_ROCKETS : +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_strName = "Rockets"; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_fValue = m_fValue * AV_ROCKETS ; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_GRENADES : +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_strName = "Grenades"; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_fValue = m_fValue * AV_GRENADES ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_ELECTRICITY : +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_strName = "Electricity"; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_fValue = m_fValue * AV_ELECTRICITY ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_IRONBALLS : +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_strName = "Ironballs"; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_fValue = m_fValue * AV_IRONBALLS ; +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_SERIOUSPACK : +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_strName = "SeriousPack"; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_fValue = m_fValue * 100000; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_BACKPACK : +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_strName = "BackPack"; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_fValue = m_fValue * 100000; +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_NAPALM : +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_strName = "Napalm"; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_fValue = m_fValue * AV_NAPALM ; +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_SNIPERBULLETS : +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_strName = "Sniper bullets"; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_fValue = m_fValue * AV_SNIPERBULLETS ; +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +pes -> es_iScore = 0; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +return TRUE ; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} + +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +void CAmmoItem::SetProperties(void) +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +{ +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +switch(m_EaitType ){ +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_SHELLS : +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fValue = 10.0f; +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_strDescription . PrintF ("Shells: %d" , (int ) m_fValue ); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItem (MODEL_SHELLS , TEXTURE_SHELLS , 0 , 0 , 0); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.25f , 0) , FLOAT3D (1.5 , 1.5 , 0.75f)); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +StretchItem (FLOAT3D (0.75f , 0.75f , 0.75f)); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_BULLETS : +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fValue = 50.0f; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_strDescription . PrintF ("Bullets: %d" , (int ) m_fValue ); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItem (MODEL_BULLETS , TEXTURE_BULLETS , 0 , 0 , 0); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.6f , 0) , FLOAT3D (3 , 3 , 1.0f)); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +StretchItem (FLOAT3D (0.75f , 0.75f , 0.75f)); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_ROCKETS : +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fValue = 5.0f; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_strDescription . PrintF ("Rockets: %d" , (int ) m_fValue ); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItem (MODEL_ROCKETS , TEXTURE_ROCKET , 0 , 0 , 0); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItemAttachment (ROCKETS_ATTACHMENT_ROCKET1 , MODEL_RC_ROCKET , TEXTURE_ROCKET , 0 , 0 , 0); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItemAttachment (ROCKETS_ATTACHMENT_ROCKET2 , MODEL_RC_ROCKET , TEXTURE_ROCKET , 0 , 0 , 0); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItemAttachment (ROCKETS_ATTACHMENT_ROCKET3 , MODEL_RC_ROCKET , TEXTURE_ROCKET , 0 , 0 , 0); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItemAttachment (ROCKETS_ATTACHMENT_ROCKET4 , MODEL_RC_ROCKET , TEXTURE_ROCKET , 0 , 0 , 0); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItemAttachment (ROCKETS_ATTACHMENT_ROCKET5 , MODEL_RC_ROCKET , TEXTURE_ROCKET , 0 , 0 , 0); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +SetItemAttachmentAnim (ROCKETS_ATTACHMENT_ROCKET1 , ROCKET_ANIM_FORAMMO ); +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +SetItemAttachmentAnim (ROCKETS_ATTACHMENT_ROCKET2 , ROCKET_ANIM_FORAMMO ); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +SetItemAttachmentAnim (ROCKETS_ATTACHMENT_ROCKET3 , ROCKET_ANIM_FORAMMO ); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +SetItemAttachmentAnim (ROCKETS_ATTACHMENT_ROCKET4 , ROCKET_ANIM_FORAMMO ); +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +SetItemAttachmentAnim (ROCKETS_ATTACHMENT_ROCKET5 , ROCKET_ANIM_FORAMMO ); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.6f , 0) , FLOAT3D (2 , 2 , 0.75f)); +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +StretchItem (FLOAT3D (0.75f , 0.75f , 0.75f)); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_GRENADES : +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fValue = 5.0f; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_strDescription . PrintF ("Grenades: %d" , (int ) m_fValue ); +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItem (MODEL_GRENADES , TEXTURE_GRENADES , 0 , 0 , 0); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.6f , 0) , FLOAT3D (4 , 4 , 1.0f)); +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +StretchItem (FLOAT3D (0.75f , 0.75f , 0.75f)); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_ELECTRICITY : +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fValue = 50.0f; +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_strDescription . PrintF ("Electricity: %d" , (int ) m_fValue ); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItem (MODEL_ELECTRICITY , TEXTURE_ELECTRICITY , TEXTURE_EL_EFFECT , TEXTURE_EL_EFFECT , 0); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItemAttachment (ELECTRICITY_ATTACHMENT_EFFECT1 , MODEL_EL_EFFECT , TEXTURE_EL_EFFECT , 0 , 0 , 0); +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItemAttachment (ELECTRICITY_ATTACHMENT_EFFECT2 , MODEL_EL_EFFECT , TEXTURE_EL_EFFECT , 0 , 0 , 0); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItemAttachment (ELECTRICITY_ATTACHMENT_EFFECT3 , MODEL_EL_EFFECT2 , TEXTURE_EL_EFFECT , 0 , 0 , 0); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.6f , 0) , FLOAT3D (3 , 3 , 0.8f)); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +StretchItem (FLOAT3D (0.75f , 0.75f , 0.75f)); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_IRONBALLS : +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fValue = 4.0f; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_strDescription . PrintF ("Iron balls: %d" , (int ) m_fValue ); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItem (MODEL_CANNONBALLS , TEXTURE_IRONBALL , TEX_REFL_DARKMETAL , TEX_SPEC_WEAK , 0); +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.75f , 0) , FLOAT3D (5 , 5 , 1.3f)); +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +StretchItem (FLOAT3D (0.75f , 0.75f , 0.75f)); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_NAPALM : +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fValue = 100.0f; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_strDescription . PrintF ("Napalm: %d" , (int ) m_fValue ); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItem (MODEL_FL_RESERVOIR , TEXTURE_FL_FUELRESERVOIR , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.75f , 0) , FLOAT3D (3 , 3 , 1.0f)); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +StretchItem (FLOAT3D (1.25f , 1.25f , 1.25f)); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_SERIOUSPACK : +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fValue = 1.0f; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_strDescription . PrintF ("SeriousPack: %d" , (int ) m_fValue ); +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItem (MODEL_SERIOUSPACK , TEXTURE_SERIOUSPACK , 0 , 0 , 0); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.75f , 0) , FLOAT3D (2 , 2 , 1.3f)); +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +StretchItem (FLOAT3D (0.5f , 0.5f , 0.5f)); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_BACKPACK : +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fValue = 1.0f; +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_strDescription . PrintF ("BackPack: %d" , (int ) m_fValue ); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItem (MODEL_BACKPACK , TEXTURE_BACKPACK , 0 , 0 , 0); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.75f , 0) , FLOAT3D (2 , 2 , 1.3f)); +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +StretchItem (FLOAT3D (0.5f , 0.5f , 0.5f)); +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +case AIT_SNIPERBULLETS : +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fValue = 5.0f; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_strDescription . PrintF ("Sniper bullets: %d" , (int ) m_fValue ); +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddItem (MODEL_SNIPER_BULLETS , TEXTURE_SNIPER_BULLETS , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.75f , 0) , FLOAT3D (3 , 3 , 1.0f)); +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +StretchItem (FLOAT3D (1.25f , 1.25f , 1.25f)); +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +break ; +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +default : ASSERTALWAYS ("Uknown ammo"); +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} + +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +void CAmmoItem::AdjustDifficulty(void) +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +{ +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fValue = ceil (m_fValue * GetSP () -> sp_fAmmoQuantity ); +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +if(GetSP () -> sp_bInfiniteAmmo && m_penTarget == NULL ){ +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Destroy (); +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +BOOL CAmmoItem:: +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +ItemCollected(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAmmoItem_ItemCollected + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EPass, "CAmmoItem::ItemCollected expects 'EPass' as input!"); const EPass &epass = (const EPass &)__eeInput; +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +ASSERT (epass . penOther != NULL ); +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +if(GetSP () -> sp_bAmmoStays && ! (m_bPickupOnce || m_bRespawn )){ +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +BOOL bWasPicked = MarkPickedBy (epass . penOther ); +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +if(bWasPicked ){ +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Return(STATE_CURRENT,EVoid()); +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +return TRUE; +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +EAmmoItem eAmmo ; +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +eAmmo . EaitType = m_EaitType ; +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +eAmmo . iQuantity = (INDEX) m_fValue ; +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +if(epass . penOther -> ReceiveItem (eAmmo )){ +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_soPick . Set3DParameters (50.0f , 1.0f , 1.0f , 1.0f); +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +if(_pNetwork -> IsPlayerLocal (epass . penOther )){IFeel_PlayEffect ("PU_Ammo");} +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +if((m_EaitType == AIT_SERIOUSPACK ) || (m_EaitType == AIT_BACKPACK )) +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +{ +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +PlaySound (m_soPick , SOUND_DEFAULT , SOF_3D ); +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +CPrintF ("^cFF0000^f5Warning!!! Replace old serious pack with new, BackPack entity!^r\n"); +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +else +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +{ +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +PlaySound (m_soPick , SOUND_PICK , SOF_3D ); +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_fPickSoundLen = GetSoundLength (SOUND_PICK ); +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +if(! GetSP () -> sp_bAmmoStays || (m_bPickupOnce || m_bRespawn )){ +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemReceived, FALSE, EVoid());return TRUE; +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Return(STATE_CURRENT,EVoid()); +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CAmmoItem:: +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAmmoItem_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAmmoItem::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +if(m_EaitType == AIT_NUKEBALL ){ +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +m_EaitType = AIT_SHELLS ; +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +} +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Initialize (); +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +StartModelAnim (ITEMHOLDER_ANIM_MEDIUMOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_MEDIUM ); +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +SetProperties (); +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/AmmoItem.es b/Sources/EntitiesMP/AmmoItem.es new file mode 100644 index 0000000..27e539b --- /dev/null +++ b/Sources/EntitiesMP/AmmoItem.es @@ -0,0 +1,411 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +803 +%{ +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" +#include "Models/Items/Ammo/Shells/Shells.h" +#include "Models/Items/Ammo/Bullets/Bullets.h" +#include "Models/Items/Ammo/Rockets/Rockets.h" +#include "Models/Weapons/RocketLauncher/Projectile/Rocket.h" +#include "Models/Items/Ammo/Grenades/Grenades.h" +#include "Models/Items/Ammo/Electricity/Electricity.h" +#include "Models/Items/Ammo/Cannonball/Cannonball.h" +#include "Models/Items/Ammo/Cannonball/CannonballQuad.h" +#include "ModelsMP/Items/Ammo/SniperBullets/SniperBullets.h" +%} + +uses "EntitiesMP/Item"; + +// ammo type +enum AmmoItemType { + 1 AIT_SHELLS "Shells", + 2 AIT_BULLETS "Bullets", + 3 AIT_ROCKETS "Rockets", + 4 AIT_GRENADES "Grenades", + 5 AIT_ELECTRICITY "Electricity", + 6 AIT_NUKEBALL "obsolete", + 7 AIT_IRONBALLS "IronBalls", + 8 AIT_SERIOUSPACK "SeriousPack - don't use", + 9 AIT_BACKPACK "BackPack - don't use", + 10 AIT_NAPALM "Napalm", + 11 AIT_SNIPERBULLETS "Sniper bullets" +}; + +// event for sending through receive item +event EAmmoItem { + enum AmmoItemType EaitType, // ammo type + INDEX iQuantity, // ammo quantity +}; + +class CAmmoItem : CItem { +name "Ammo Item"; +thumbnail "Thumbnails\\AmmoItem.tbn"; + +properties: + 1 enum AmmoItemType m_EaitType "Type" 'Y' = AIT_SHELLS, // health type + +components: + 0 class CLASS_BASE "Classes\\Item.ecl", + +// ********* SHELLS ********* + 1 model MODEL_SHELLS "Models\\Items\\Ammo\\Shells\\Shells.mdl", + 2 texture TEXTURE_SHELLS "Models\\Items\\Ammo\\Shells\\Shells.tex", + +// ********* BULLETS ********* + 10 model MODEL_BULLETS "Models\\Items\\Ammo\\Bullets\\Bullets.mdl", + 11 texture TEXTURE_BULLETS "Models\\Items\\Ammo\\Bullets\\Bullets.tex", + +// ********* ROCKETS ********* + 20 model MODEL_ROCKETS "Models\\Items\\Ammo\\Rockets\\Rockets.mdl", + 21 model MODEL_RC_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl", + 22 texture TEXTURE_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex", + +// ********* GRENADES ********* + 30 model MODEL_GRENADES "Models\\Items\\Ammo\\Grenades\\Grenades.mdl", + 31 model MODEL_GR_GRENADE "Models\\Items\\Ammo\\Grenades\\Grenade.mdl", + 32 texture TEXTURE_GRENADES "Models\\Items\\Ammo\\Grenades\\Grenades.tex", + 33 texture TEXTURE_GR_GRENADE "Models\\Weapons\\GrenadeLauncher\\Grenade\\Grenade.tex", + +// ********* ELECTRICITY ********* + 40 model MODEL_ELECTRICITY "Models\\Items\\Ammo\\Electricity\\Electricity.mdl", + 41 model MODEL_EL_EFFECT "Models\\Items\\Ammo\\Electricity\\Effect.mdl", + 42 model MODEL_EL_EFFECT2 "Models\\Items\\Ammo\\Electricity\\Effect2.mdl", + 43 texture TEXTURE_ELECTRICITY "Models\\Items\\Ammo\\Electricity\\Electricity.tex", + 44 texture TEXTURE_EL_EFFECT "Models\\Items\\Ammo\\Electricity\\Effect.tex", + +// ********* CANNON BALLS ********* + 50 model MODEL_CANNONBALL "Models\\Items\\Ammo\\Cannonball\\Cannonball.mdl", + 51 model MODEL_CANNONBALLS "Models\\Items\\Ammo\\Cannonball\\CannonballQuad.mdl", + 52 texture TEXTURE_IRONBALL "Models\\Weapons\\Cannon\\Projectile\\IronBall.tex", +// 53 texture TEXTURE_NUKEBALL "Models\\Weapons\\Cannon\\Projectile\\NukeBall.tex", + +// ********* BACK PACK ********* + 60 model MODEL_BACKPACK "Models\\Items\\PowerUps\\BackPack\\BackPack.mdl", + 61 texture TEXTURE_BACKPACK "Models\\Items\\PowerUps\\BackPack\\BackPack.tex", + +// ********* SERIOUS PACK ********* + 70 model MODEL_SERIOUSPACK "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.mdl", + 71 texture TEXTURE_SERIOUSPACK "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.tex", + + +// ********* FUEL RESERVOIR ********* + 80 model MODEL_FL_RESERVOIR "ModelsMP\\Items\\Ammo\\Napalm\\Napalm.mdl", + 81 texture TEXTURE_FL_FUELRESERVOIR "ModelsMP\\Weapons\\Flamer\\FuelReservoir.tex", + + // ******** SNIPER BULLETS ********* + 90 model MODEL_SNIPER_BULLETS "ModelsMP\\Items\\Ammo\\SniperBullets\\SniperBullets.mdl", + 91 texture TEXTURE_SNIPER_BULLETS "ModelsMP\\Items\\Ammo\\SniperBullets\\SniperBullets.tex", + +// ************** FLARE FOR EFFECT ************** +100 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex", +101 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl", + +// ************** REFLECTIONS ************** +200 texture TEX_REFL_BWRIPLES01 "Models\\ReflectionTextures\\BWRiples01.tex", +201 texture TEX_REFL_BWRIPLES02 "Models\\ReflectionTextures\\BWRiples02.tex", +202 texture TEX_REFL_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex", +203 texture TEX_REFL_LIGHTBLUEMETAL01 "Models\\ReflectionTextures\\LightBlueMetal01.tex", +204 texture TEX_REFL_DARKMETAL "Models\\ReflectionTextures\\DarkMetal.tex", +205 texture TEX_REFL_PURPLE01 "Models\\ReflectionTextures\\Purple01.tex", + +// ************** SPECULAR ************** +210 texture TEX_SPEC_WEAK "Models\\SpecularTextures\\Weak.tex", +211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex", +212 texture TEX_SPEC_STRONG "Models\\SpecularTextures\\Strong.tex", + +// ************** SOUNDS ************** +213 sound SOUND_PICK "Sounds\\Items\\Ammo.wav", +214 sound SOUND_DEFAULT "Sounds\\Default.wav", + +functions: + void Precache(void) { + PrecacheSound(SOUND_PICK); + } + + // render particles + void RenderParticles(void) { + // no particles when not existing or in DM modes + if (GetRenderType()!=CEntity::RT_MODEL || GetSP()->sp_gmGameMode>CSessionProperties::GM_COOPERATIVE + || !ShowItemParticles()) + { + return; + } + switch (m_EaitType) { + case AIT_SHELLS: + Particles_Spiral(this, 1.0f*0.75, 1.0f*0.75, PT_STAR04, 4); + break; + case AIT_BULLETS: + Particles_Spiral(this, 1.5f*0.75, 1.0f*0.75, PT_STAR04, 6); + break; + case AIT_ROCKETS: + Particles_Spiral(this, 1.5f*0.75, 1.25f*0.75, PT_STAR04, 6); + break; + case AIT_GRENADES: + Particles_Spiral(this, 2.0f*0.75, 1.25f*0.75, PT_STAR04, 6); + break; + case AIT_ELECTRICITY: + Particles_Spiral(this, 1.5f*0.75, 1.125f*0.75, PT_STAR04, 6); + break; + case AIT_NUKEBALL: + Particles_Spiral(this, 1.25f*0.75, 1.0f*0.75, PT_STAR04, 4); + break; + case AIT_IRONBALLS: + Particles_Spiral(this, 2.0f*0.75, 1.25f*0.75, PT_STAR04, 8); + break; + case AIT_BACKPACK: + Particles_Spiral(this, 3.0f*0.5, 2.5f*0.5, PT_STAR04, 10); + break; + case AIT_SERIOUSPACK: + Particles_Spiral(this, 3.0f*0.5, 2.5f*0.5, PT_STAR04, 10); + break; + case AIT_NAPALM: + Particles_Spiral(this, 3.0f*0.5, 2.5f*0.5, PT_STAR04, 10); + break; + case AIT_SNIPERBULLETS: + Particles_Spiral(this, 1.5f*0.75, 1.25f*0.75, PT_STAR04, 6); + break; + } + } + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + pes->es_ctCount = 1; + pes->es_ctAmmount = m_fValue; + switch (m_EaitType) { + case AIT_SHELLS: + pes->es_strName = "Shells"; + pes->es_fValue = m_fValue*AV_SHELLS; + break; + case AIT_BULLETS: + pes->es_strName = "Bullets"; + pes->es_fValue = m_fValue*AV_BULLETS; + break; + case AIT_ROCKETS: + pes->es_strName = "Rockets"; + pes->es_fValue = m_fValue*AV_ROCKETS; + break; + case AIT_GRENADES: + pes->es_strName = "Grenades"; + pes->es_fValue = m_fValue*AV_GRENADES; + break; + case AIT_ELECTRICITY: + pes->es_strName = "Electricity"; + pes->es_fValue = m_fValue*AV_ELECTRICITY; + break; +/* + case AIT_NUKEBALL: + pes->es_strName = "Nukeballs"; + pes->es_fValue = m_fValue*AV_NUKEBALLS; + break; + */ + case AIT_IRONBALLS: + pes->es_strName = "Ironballs"; + pes->es_fValue = m_fValue*AV_IRONBALLS; + break; + case AIT_SERIOUSPACK: + pes->es_strName = "SeriousPack"; + pes->es_fValue = m_fValue*100000; + break; + case AIT_BACKPACK: + pes->es_strName = "BackPack"; + pes->es_fValue = m_fValue*100000; + break; + case AIT_NAPALM: + pes->es_strName = "Napalm"; + pes->es_fValue = m_fValue*AV_NAPALM; + break; + case AIT_SNIPERBULLETS: + pes->es_strName = "Sniper bullets"; + pes->es_fValue = m_fValue*AV_SNIPERBULLETS; + break; + } + pes->es_iScore = 0;//m_iScore; + return TRUE; + } + + + // set ammo properties depending on ammo type + void SetProperties(void) + { + switch (m_EaitType) { + case AIT_SHELLS: + m_fValue = 10.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("Shells: %d", (int) m_fValue); + // set appearance + AddItem(MODEL_SHELLS, TEXTURE_SHELLS, 0, 0, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.25f,0), FLOAT3D(1.5,1.5,0.75f) ); + StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f)); + break; + case AIT_BULLETS: + m_fValue = 50.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("Bullets: %d", (int) m_fValue); + // set appearance + AddItem(MODEL_BULLETS, TEXTURE_BULLETS, 0, 0, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(3,3,1.0f) ); + StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f)); + break; + case AIT_ROCKETS: + m_fValue = 5.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("Rockets: %d", (int) m_fValue); + // set appearance + AddItem(MODEL_ROCKETS, TEXTURE_ROCKET, 0, 0, 0); + AddItemAttachment(ROCKETS_ATTACHMENT_ROCKET1, MODEL_RC_ROCKET, TEXTURE_ROCKET, 0, 0, 0); + AddItemAttachment(ROCKETS_ATTACHMENT_ROCKET2, MODEL_RC_ROCKET, TEXTURE_ROCKET, 0, 0, 0); + AddItemAttachment(ROCKETS_ATTACHMENT_ROCKET3, MODEL_RC_ROCKET, TEXTURE_ROCKET, 0, 0, 0); + AddItemAttachment(ROCKETS_ATTACHMENT_ROCKET4, MODEL_RC_ROCKET, TEXTURE_ROCKET, 0, 0, 0); + AddItemAttachment(ROCKETS_ATTACHMENT_ROCKET5, MODEL_RC_ROCKET, TEXTURE_ROCKET, 0, 0, 0); + SetItemAttachmentAnim(ROCKETS_ATTACHMENT_ROCKET1, ROCKET_ANIM_FORAMMO); + SetItemAttachmentAnim(ROCKETS_ATTACHMENT_ROCKET2, ROCKET_ANIM_FORAMMO); + SetItemAttachmentAnim(ROCKETS_ATTACHMENT_ROCKET3, ROCKET_ANIM_FORAMMO); + SetItemAttachmentAnim(ROCKETS_ATTACHMENT_ROCKET4, ROCKET_ANIM_FORAMMO); + SetItemAttachmentAnim(ROCKETS_ATTACHMENT_ROCKET5, ROCKET_ANIM_FORAMMO); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(2,2,0.75f) ); + StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f)); + break; + case AIT_GRENADES: + m_fValue = 5.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("Grenades: %d", (int) m_fValue); + // set appearance + AddItem(MODEL_GRENADES, TEXTURE_GRENADES, 0, 0, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(4,4,1.0f) ); + StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f)); + break; + case AIT_ELECTRICITY: + m_fValue = 50.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("Electricity: %d", (int) m_fValue); + // set appearance + AddItem(MODEL_ELECTRICITY, TEXTURE_ELECTRICITY, TEXTURE_EL_EFFECT, TEXTURE_EL_EFFECT, 0); + AddItemAttachment(ELECTRICITY_ATTACHMENT_EFFECT1, MODEL_EL_EFFECT, TEXTURE_EL_EFFECT, 0, 0, 0); + AddItemAttachment(ELECTRICITY_ATTACHMENT_EFFECT2, MODEL_EL_EFFECT, TEXTURE_EL_EFFECT, 0, 0, 0); + AddItemAttachment(ELECTRICITY_ATTACHMENT_EFFECT3, MODEL_EL_EFFECT2,TEXTURE_EL_EFFECT, 0, 0, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(3,3,0.8f) ); + StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f)); + break; +/* + case AIT_NUKEBALL: + m_fValue = 1.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("Nuke ball: %d", (int) m_fValue); + // set appearance + AddItem(MODEL_CANNONBALL, TEXTURE_NUKEBALL, TEX_REFL_BWRIPLES01, TEX_SPEC_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.5f,0), FLOAT3D(2,2,0.5f) ); + StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f)); + break; + */ + case AIT_IRONBALLS: + m_fValue = 4.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("Iron balls: %d", (int) m_fValue); + // set appearance + AddItem(MODEL_CANNONBALLS, TEXTURE_IRONBALL, TEX_REFL_DARKMETAL, TEX_SPEC_WEAK, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(5,5,1.3f) ); + StretchItem(FLOAT3D(0.75f, 0.75f, 0.75f)); + break; + case AIT_NAPALM: + m_fValue = 100.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("Napalm: %d", (int) m_fValue); + // set appearance + AddItem(MODEL_FL_RESERVOIR, TEXTURE_FL_FUELRESERVOIR, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(3,3,1.0f) ); + StretchItem(FLOAT3D(1.25f, 1.25f, 1.25f)); + break; + case AIT_SERIOUSPACK: + m_fValue = 1.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("SeriousPack: %d", (int) m_fValue); + // set appearance + AddItem(MODEL_SERIOUSPACK, TEXTURE_SERIOUSPACK, 0,0,0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(2,2,1.3f) ); + StretchItem(FLOAT3D(0.5f, 0.5f, 0.5f)); + break; + case AIT_BACKPACK: + m_fValue = 1.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("BackPack: %d", (int) m_fValue); + // set appearance + AddItem(MODEL_BACKPACK, TEXTURE_BACKPACK, 0,0,0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(2,2,1.3f) ); + StretchItem(FLOAT3D(0.5f, 0.5f, 0.5f)); + break; + case AIT_SNIPERBULLETS: + m_fValue = 5.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("Sniper bullets: %d", (int) m_fValue); + // set appearance + AddItem(MODEL_SNIPER_BULLETS, TEXTURE_SNIPER_BULLETS, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(3,3,1.0f) ); + StretchItem(FLOAT3D(1.25f, 1.25f, 1.25f)); + break; + default: ASSERTALWAYS("Uknown ammo"); + } + }; + + void AdjustDifficulty(void) + { + m_fValue = ceil(m_fValue*GetSP()->sp_fAmmoQuantity); + + if (GetSP()->sp_bInfiniteAmmo && m_penTarget==NULL) { + Destroy(); + } + } + +procedures: + ItemCollected(EPass epass) : CItem::ItemCollected { + ASSERT(epass.penOther!=NULL); + + // if ammo stays + if (GetSP()->sp_bAmmoStays && !(m_bPickupOnce||m_bRespawn)) { + // if already picked by this player + BOOL bWasPicked = MarkPickedBy(epass.penOther); + if (bWasPicked) { + // don't pick again + return; + } + } + + // send ammo to entity + EAmmoItem eAmmo; + eAmmo.EaitType = m_EaitType; + eAmmo.iQuantity = (INDEX) m_fValue; + // if health is received + if (epass.penOther->ReceiveItem(eAmmo)) { + // play the pickup sound + m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f); + if(_pNetwork->IsPlayerLocal(epass.penOther)) {IFeel_PlayEffect("PU_Ammo");} + if( (m_EaitType == AIT_SERIOUSPACK) || (m_EaitType == AIT_BACKPACK) ) + { + PlaySound(m_soPick, SOUND_DEFAULT, SOF_3D); + CPrintF("^cFF0000^f5Warning!!! Replace old serious pack with new, BackPack entity!^r\n"); + } + else + { + PlaySound(m_soPick, SOUND_PICK, SOF_3D); + } + m_fPickSoundLen = GetSoundLength(SOUND_PICK); + if (!GetSP()->sp_bAmmoStays || (m_bPickupOnce||m_bRespawn)) { + jump CItem::ItemReceived(); + } + } + return; + }; + + Main() { + if (m_EaitType==AIT_NUKEBALL /*|| m_EaitType==AIT_NAPALM*/) { + m_EaitType=AIT_SHELLS; + } + Initialize(); // initialize base class + StartModelAnim(ITEMHOLDER_ANIM_MEDIUMOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM); + SetProperties(); // set properties + + jump CItem::ItemLoop(); + }; +}; diff --git a/Sources/EntitiesMP/AmmoItem.h b/Sources/EntitiesMP/AmmoItem.h new file mode 100644 index 0000000..75f1b71 --- /dev/null +++ b/Sources/EntitiesMP/AmmoItem.h @@ -0,0 +1,61 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_AmmoItem_INCLUDED +#define _EntitiesMP_AmmoItem_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType AmmoItemType_enum; +enum AmmoItemType { + AIT_SHELLS = 1, + AIT_BULLETS = 2, + AIT_ROCKETS = 3, + AIT_GRENADES = 4, + AIT_ELECTRICITY = 5, + AIT_NUKEBALL = 6, + AIT_IRONBALLS = 7, + AIT_SERIOUSPACK = 8, + AIT_BACKPACK = 9, + AIT_NAPALM = 10, + AIT_SNIPERBULLETS = 11, +}; +DECL_DLL inline void ClearToDefault(AmmoItemType &e) { e = (AmmoItemType)0; } ; +#define EVENTCODE_EAmmoItem 0x03230000 +class DECL_DLL EAmmoItem : public CEntityEvent { +public: +EAmmoItem(); +CEntityEvent *MakeCopy(void); +enum AmmoItemType EaitType; +INDEX iQuantity; +}; +DECL_DLL inline void ClearToDefault(EAmmoItem &e) { e = EAmmoItem(); } ; +extern "C" DECL_DLL CDLLEntityClass CAmmoItem_DLLClass; +class CAmmoItem : public CItem { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum AmmoItemType m_EaitType; + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +void Precache(void); + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +void RenderParticles(void); + +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +void SetProperties(void); + +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +void AdjustDifficulty(void); +#define STATE_CAmmoItem_ItemCollected 0x03230001 + BOOL +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +ItemCollected(const CEntityEvent &__eeInput); +#define STATE_CAmmoItem_Main 1 + BOOL +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_AmmoItem_INCLUDED diff --git a/Sources/EntitiesMP/AmmoItem_tables.h b/Sources/EntitiesMP/AmmoItem_tables.h new file mode 100644 index 0000000..bb2bd77 --- /dev/null +++ b/Sources/EntitiesMP/AmmoItem_tables.h @@ -0,0 +1,131 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(AmmoItemType) + EP_ENUMVALUE(AIT_SHELLS, "Shells"), + EP_ENUMVALUE(AIT_BULLETS, "Bullets"), + EP_ENUMVALUE(AIT_ROCKETS, "Rockets"), + EP_ENUMVALUE(AIT_GRENADES, "Grenades"), + EP_ENUMVALUE(AIT_ELECTRICITY, "Electricity"), + EP_ENUMVALUE(AIT_NUKEBALL, "obsolete"), + EP_ENUMVALUE(AIT_IRONBALLS, "IronBalls"), + EP_ENUMVALUE(AIT_SERIOUSPACK, "SeriousPack - don't use"), + EP_ENUMVALUE(AIT_BACKPACK, "BackPack - don't use"), + EP_ENUMVALUE(AIT_NAPALM, "Napalm"), + EP_ENUMVALUE(AIT_SNIPERBULLETS, "Sniper bullets"), +EP_ENUMEND(AmmoItemType); + +#define ENTITYCLASS CAmmoItem + +CEntityProperty CAmmoItem_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &AmmoItemType_enum, (0x00000323<<8)+1, offsetof(CAmmoItem, m_EaitType), "Type", 'Y', 0x7F0000FFUL, 0), +}; +#define CAmmoItem_propertiesct ARRAYCOUNT(CAmmoItem_properties) + +CEntityComponent CAmmoItem_components[] = { +#define CLASS_BASE ((0x00000323<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\Item.ecl"), +#define MODEL_SHELLS ((0x00000323<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_SHELLS, "EFNM" "Models\\Items\\Ammo\\Shells\\Shells.mdl"), +#define TEXTURE_SHELLS ((0x00000323<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_SHELLS, "EFNM" "Models\\Items\\Ammo\\Shells\\Shells.tex"), +#define MODEL_BULLETS ((0x00000323<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_BULLETS, "EFNM" "Models\\Items\\Ammo\\Bullets\\Bullets.mdl"), +#define TEXTURE_BULLETS ((0x00000323<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_BULLETS, "EFNM" "Models\\Items\\Ammo\\Bullets\\Bullets.tex"), +#define MODEL_ROCKETS ((0x00000323<<8)+20) + CEntityComponent(ECT_MODEL, MODEL_ROCKETS, "EFNM" "Models\\Items\\Ammo\\Rockets\\Rockets.mdl"), +#define MODEL_RC_ROCKET ((0x00000323<<8)+21) + CEntityComponent(ECT_MODEL, MODEL_RC_ROCKET, "EFNM" "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl"), +#define TEXTURE_ROCKET ((0x00000323<<8)+22) + CEntityComponent(ECT_TEXTURE, TEXTURE_ROCKET, "EFNM" "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex"), +#define MODEL_GRENADES ((0x00000323<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_GRENADES, "EFNM" "Models\\Items\\Ammo\\Grenades\\Grenades.mdl"), +#define MODEL_GR_GRENADE ((0x00000323<<8)+31) + CEntityComponent(ECT_MODEL, MODEL_GR_GRENADE, "EFNM" "Models\\Items\\Ammo\\Grenades\\Grenade.mdl"), +#define TEXTURE_GRENADES ((0x00000323<<8)+32) + CEntityComponent(ECT_TEXTURE, TEXTURE_GRENADES, "EFNM" "Models\\Items\\Ammo\\Grenades\\Grenades.tex"), +#define TEXTURE_GR_GRENADE ((0x00000323<<8)+33) + CEntityComponent(ECT_TEXTURE, TEXTURE_GR_GRENADE, "EFNM" "Models\\Weapons\\GrenadeLauncher\\Grenade\\Grenade.tex"), +#define MODEL_ELECTRICITY ((0x00000323<<8)+40) + CEntityComponent(ECT_MODEL, MODEL_ELECTRICITY, "EFNM" "Models\\Items\\Ammo\\Electricity\\Electricity.mdl"), +#define MODEL_EL_EFFECT ((0x00000323<<8)+41) + CEntityComponent(ECT_MODEL, MODEL_EL_EFFECT, "EFNM" "Models\\Items\\Ammo\\Electricity\\Effect.mdl"), +#define MODEL_EL_EFFECT2 ((0x00000323<<8)+42) + CEntityComponent(ECT_MODEL, MODEL_EL_EFFECT2, "EFNM" "Models\\Items\\Ammo\\Electricity\\Effect2.mdl"), +#define TEXTURE_ELECTRICITY ((0x00000323<<8)+43) + CEntityComponent(ECT_TEXTURE, TEXTURE_ELECTRICITY, "EFNM" "Models\\Items\\Ammo\\Electricity\\Electricity.tex"), +#define TEXTURE_EL_EFFECT ((0x00000323<<8)+44) + CEntityComponent(ECT_TEXTURE, TEXTURE_EL_EFFECT, "EFNM" "Models\\Items\\Ammo\\Electricity\\Effect.tex"), +#define MODEL_CANNONBALL ((0x00000323<<8)+50) + CEntityComponent(ECT_MODEL, MODEL_CANNONBALL, "EFNM" "Models\\Items\\Ammo\\Cannonball\\Cannonball.mdl"), +#define MODEL_CANNONBALLS ((0x00000323<<8)+51) + CEntityComponent(ECT_MODEL, MODEL_CANNONBALLS, "EFNM" "Models\\Items\\Ammo\\Cannonball\\CannonballQuad.mdl"), +#define TEXTURE_IRONBALL ((0x00000323<<8)+52) + CEntityComponent(ECT_TEXTURE, TEXTURE_IRONBALL, "EFNM" "Models\\Weapons\\Cannon\\Projectile\\IronBall.tex"), +#define MODEL_BACKPACK ((0x00000323<<8)+60) + CEntityComponent(ECT_MODEL, MODEL_BACKPACK, "EFNM" "Models\\Items\\PowerUps\\BackPack\\BackPack.mdl"), +#define TEXTURE_BACKPACK ((0x00000323<<8)+61) + CEntityComponent(ECT_TEXTURE, TEXTURE_BACKPACK, "EFNM" "Models\\Items\\PowerUps\\BackPack\\BackPack.tex"), +#define MODEL_SERIOUSPACK ((0x00000323<<8)+70) + CEntityComponent(ECT_MODEL, MODEL_SERIOUSPACK, "EFNM" "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.mdl"), +#define TEXTURE_SERIOUSPACK ((0x00000323<<8)+71) + CEntityComponent(ECT_TEXTURE, TEXTURE_SERIOUSPACK, "EFNM" "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.tex"), +#define MODEL_FL_RESERVOIR ((0x00000323<<8)+80) + CEntityComponent(ECT_MODEL, MODEL_FL_RESERVOIR, "EFNM" "ModelsMP\\Items\\Ammo\\Napalm\\Napalm.mdl"), +#define TEXTURE_FL_FUELRESERVOIR ((0x00000323<<8)+81) + CEntityComponent(ECT_TEXTURE, TEXTURE_FL_FUELRESERVOIR, "EFNM" "ModelsMP\\Weapons\\Flamer\\FuelReservoir.tex"), +#define MODEL_SNIPER_BULLETS ((0x00000323<<8)+90) + CEntityComponent(ECT_MODEL, MODEL_SNIPER_BULLETS, "EFNM" "ModelsMP\\Items\\Ammo\\SniperBullets\\SniperBullets.mdl"), +#define TEXTURE_SNIPER_BULLETS ((0x00000323<<8)+91) + CEntityComponent(ECT_TEXTURE, TEXTURE_SNIPER_BULLETS, "EFNM" "ModelsMP\\Items\\Ammo\\SniperBullets\\SniperBullets.tex"), +#define TEXTURE_FLARE ((0x00000323<<8)+100) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.tex"), +#define MODEL_FLARE ((0x00000323<<8)+101) + CEntityComponent(ECT_MODEL, MODEL_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.mdl"), +#define TEX_REFL_BWRIPLES01 ((0x00000323<<8)+200) + CEntityComponent(ECT_TEXTURE, TEX_REFL_BWRIPLES01, "EFNM" "Models\\ReflectionTextures\\BWRiples01.tex"), +#define TEX_REFL_BWRIPLES02 ((0x00000323<<8)+201) + CEntityComponent(ECT_TEXTURE, TEX_REFL_BWRIPLES02, "EFNM" "Models\\ReflectionTextures\\BWRiples02.tex"), +#define TEX_REFL_LIGHTMETAL01 ((0x00000323<<8)+202) + CEntityComponent(ECT_TEXTURE, TEX_REFL_LIGHTMETAL01, "EFNM" "Models\\ReflectionTextures\\LightMetal01.tex"), +#define TEX_REFL_LIGHTBLUEMETAL01 ((0x00000323<<8)+203) + CEntityComponent(ECT_TEXTURE, TEX_REFL_LIGHTBLUEMETAL01, "EFNM" "Models\\ReflectionTextures\\LightBlueMetal01.tex"), +#define TEX_REFL_DARKMETAL ((0x00000323<<8)+204) + CEntityComponent(ECT_TEXTURE, TEX_REFL_DARKMETAL, "EFNM" "Models\\ReflectionTextures\\DarkMetal.tex"), +#define TEX_REFL_PURPLE01 ((0x00000323<<8)+205) + CEntityComponent(ECT_TEXTURE, TEX_REFL_PURPLE01, "EFNM" "Models\\ReflectionTextures\\Purple01.tex"), +#define TEX_SPEC_WEAK ((0x00000323<<8)+210) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_WEAK, "EFNM" "Models\\SpecularTextures\\Weak.tex"), +#define TEX_SPEC_MEDIUM ((0x00000323<<8)+211) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_MEDIUM, "EFNM" "Models\\SpecularTextures\\Medium.tex"), +#define TEX_SPEC_STRONG ((0x00000323<<8)+212) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_STRONG, "EFNM" "Models\\SpecularTextures\\Strong.tex"), +#define SOUND_PICK ((0x00000323<<8)+213) + CEntityComponent(ECT_SOUND, SOUND_PICK, "EFNM" "Sounds\\Items\\Ammo.wav"), +#define SOUND_DEFAULT ((0x00000323<<8)+214) + CEntityComponent(ECT_SOUND, SOUND_DEFAULT, "EFNM" "Sounds\\Default.wav"), +}; +#define CAmmoItem_componentsct ARRAYCOUNT(CAmmoItem_components) + +CEventHandlerEntry CAmmoItem_handlers[] = { + {0x03230001, STATE_CItem_ItemCollected, CEntity::pEventHandler(&CAmmoItem:: +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +ItemCollected),DEBUGSTRING("CAmmoItem::ItemCollected")}, + {1, -1, CEntity::pEventHandler(&CAmmoItem:: +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/AmmoItem.es" +Main),DEBUGSTRING("CAmmoItem::Main")}, +}; +#define CAmmoItem_handlersct ARRAYCOUNT(CAmmoItem_handlers) + +CEntity *CAmmoItem_New(void) { return new CAmmoItem; }; +void CAmmoItem_OnInitClass(void) {}; +void CAmmoItem_OnEndClass(void) {}; +void CAmmoItem_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CAmmoItem_OnWorldEnd(CWorld *pwo) {}; +void CAmmoItem_OnWorldInit(CWorld *pwo) {}; +void CAmmoItem_OnWorldTick(CWorld *pwo) {}; +void CAmmoItem_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CAmmoItem, CItem, "Ammo Item", "Thumbnails\\AmmoItem.tbn", 0x00000323); +DECLARE_CTFILENAME(_fnmCAmmoItem_tbn, "Thumbnails\\AmmoItem.tbn"); diff --git a/Sources/EntitiesMP/AmmoPack.cpp b/Sources/EntitiesMP/AmmoPack.cpp new file mode 100644 index 0000000..90dac5c --- /dev/null +++ b/Sources/EntitiesMP/AmmoPack.cpp @@ -0,0 +1,262 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" + +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" + +#include +#include +CEntityEvent *EAmmoPackItem::MakeCopy(void) { CEntityEvent *peeCopy = new EAmmoPackItem(*this); return peeCopy;} +EAmmoPackItem::EAmmoPackItem() : CEntityEvent(EVENTCODE_EAmmoPackItem) {; + ClearToDefault(iShells); + ClearToDefault(iBullets); + ClearToDefault(iRockets); + ClearToDefault(iGrenades); + ClearToDefault(iNapalm); + ClearToDefault(iElectricity); + ClearToDefault(iIronBalls); + ClearToDefault(iSniperBullets); +}; +void CAmmoPack::SetDefaultProperties(void) { + m_aptPackType = APT_CUSTOM ; + m_iShells = MAX_SHELLS ; + m_iBullets = MAX_BULLETS ; + m_iRockets = MAX_ROCKETS ; + m_iGrenades = MAX_GRENADES ; + m_iNapalm = MAX_NAPALM ; + m_iElectricity = MAX_ELECTRICITY ; + m_iIronBalls = MAX_IRONBALLS ; + m_iSniperBullets = MAX_SNIPERBULLETS ; + CItem::SetDefaultProperties(); +} + +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +void CAmmoPack::Precache(void) { +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +PrecacheSound (SOUND_PICK ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} + +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +void CAmmoPack::RenderParticles(void) +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +{ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(GetRenderType () != CEntity :: RT_MODEL || GetSP () -> sp_gmGameMode > CSessionProperties :: GM_COOPERATIVE +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +|| ! ShowItemParticles ()) +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +{ +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +return ; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +Particles_Spiral (this , 3.0f * 0.5 , 2.5f * 0.5 , PT_STAR04 , 10); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +BOOL CAmmoPack::FillEntityStatistics(EntityStats * pes) +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +{ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +pes -> es_ctCount = 1; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +pes -> es_ctAmmount = 1; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +pes -> es_strName . PrintF ("Back pack: %d Shells, %d Bullets, %d Rockets, %d Grenades, %d Napalm, %d Electricity, %d Iron balls, %d Sniper bullets" , +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iShells , m_iBullets , m_iRockets , m_iGrenades , m_iNapalm , m_iElectricity , m_iIronBalls , m_iSniperBullets ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +pes -> es_fValue = +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iShells * AV_SHELLS + +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iBullets * AV_BULLETS + +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iRockets * AV_ROCKETS + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iGrenades * AV_GRENADES + +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iNapalm * AV_NAPALM + +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iElectricity * AV_ELECTRICITY + +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iIronBalls * AV_IRONBALLS + +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iSniperBullets * AV_SNIPERBULLETS +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +pes -> es_iScore = 0; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +return TRUE ; +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +void CAmmoPack::SetProperties(void) +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +{ +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +switch(m_aptPackType ) +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +{ +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +case APT_SERIOUS : +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_strDescription = "Serious:"; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +AddItem (MODEL_SERIOUSPACK , TEXTURE_SERIOUSPACK , 0 , 0 , 0); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.75f , 0) , FLOAT3D (2 , 2 , 1.3f)); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +StretchItem (FLOAT3D (0.5f , 0.5f , 0.5f)); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +break ; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +case APT_CUSTOM : +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_strDescription = "Custom:"; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +AddItem (MODEL_BACKPACK , TEXTURE_BACKPACK , 0 , 0 , 0); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.75f , 0) , FLOAT3D (2 , 2 , 1.3f)); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +StretchItem (FLOAT3D (0.5f , 0.5f , 0.5f)); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +break ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +default : ASSERTALWAYS ("Uknown ammo"); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_fValue = 1.0f; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(m_iShells != 0){m_strDescription . PrintF ("%s: Shells (%d)" , m_strDescription , m_iShells );} +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(m_iBullets != 0){m_strDescription . PrintF ("%s: Bullets (%d)" , m_strDescription , m_iBullets );} +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(m_iRockets != 0){m_strDescription . PrintF ("%s: Rockets (%d)" , m_strDescription , m_iRockets );} +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(m_iGrenades != 0){m_strDescription . PrintF ("%s: Grenades (%d)" , m_strDescription , m_iGrenades );} +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(m_iNapalm != 0){m_strDescription . PrintF ("%s: Napalm (%d)" , m_strDescription , m_iNapalm );} +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(m_iElectricity != 0){m_strDescription . PrintF ("%s: Electricity (%d)" , m_strDescription , m_iElectricity );} +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(m_iIronBalls != 0){m_strDescription . PrintF ("%s: Iron balls (%d)" , m_strDescription , m_iIronBalls );} +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(m_iSniperBullets != 0){m_strDescription . PrintF ("%s: Sniper bullets (%d)" , m_strDescription , m_iSniperBullets );} +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} + +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +void CAmmoPack::AdjustDifficulty(void) +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +{ +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(GetSP () -> sp_bInfiniteAmmo && m_penTarget == NULL ){ +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +Destroy (); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} +BOOL CAmmoPack:: +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +ItemCollected(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAmmoPack_ItemCollected + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EPass, "CAmmoPack::ItemCollected expects 'EPass' as input!"); const EPass &epass = (const EPass &)__eeInput; +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +ASSERT (epass . penOther != NULL ); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(GetSP () -> sp_bAmmoStays && ! (m_bPickupOnce || m_bRespawn )){ +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +BOOL bWasPicked = MarkPickedBy (epass . penOther ); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(bWasPicked ){ +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +Return(STATE_CURRENT,EVoid()); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +return TRUE; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +EAmmoPackItem eAmmo ; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +eAmmo . iShells = m_iShells ; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +eAmmo . iBullets = m_iBullets ; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +eAmmo . iRockets = m_iRockets ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +eAmmo . iGrenades = m_iGrenades ; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +eAmmo . iNapalm = m_iNapalm ; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +eAmmo . iElectricity = m_iElectricity ; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +eAmmo . iIronBalls = m_iIronBalls ; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +eAmmo . iSniperBullets = m_iSniperBullets ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(epass . penOther -> ReceiveItem (eAmmo )){ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_soPick . Set3DParameters (50.0f , 1.0f , 1.0f , 1.0f); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +PlaySound (m_soPick , SOUND_PICK , SOF_3D ); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_fPickSoundLen = GetSoundLength (SOUND_PICK ); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +if(! GetSP () -> sp_bAmmoStays || (m_bPickupOnce || m_bRespawn )){ +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +Jump(STATE_CURRENT, STATE_CItem_ItemReceived, FALSE, EVoid());return TRUE; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +} +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +Return(STATE_CURRENT,EVoid()); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CAmmoPack:: +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAmmoPack_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAmmoPack::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iShells = Clamp (m_iShells , INDEX (0) , MAX_SHELLS ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iBullets = Clamp (m_iBullets , INDEX (0) , MAX_BULLETS ); +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iRockets = Clamp (m_iRockets , INDEX (0) , MAX_ROCKETS ); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iGrenades = Clamp (m_iGrenades , INDEX (0) , MAX_GRENADES ); +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iNapalm = Clamp (m_iNapalm , INDEX (0) , MAX_NAPALM ); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iElectricity = Clamp (m_iElectricity , INDEX (0) , MAX_ELECTRICITY ); +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iIronBalls = Clamp (m_iIronBalls , INDEX (0) , MAX_IRONBALLS ); +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +m_iSniperBullets = Clamp (m_iSniperBullets , INDEX (0) , MAX_SNIPERBULLETS ); +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +Initialize (); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +StartModelAnim (ITEMHOLDER_ANIM_MEDIUMOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_MEDIUM ); +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +SetProperties (); +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +Jump(STATE_CURRENT, STATE_CItem_ItemLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/AmmoPack.es b/Sources/EntitiesMP/AmmoPack.es new file mode 100644 index 0000000..7433a23 --- /dev/null +++ b/Sources/EntitiesMP/AmmoPack.es @@ -0,0 +1,213 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +806 +%{ +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" +%} + +uses "EntitiesMP/Item"; + +// ammo type +enum AmmoPackType { + 1 APT_CUSTOM "Custom pack", + 2 APT_SERIOUS "Serious pack", +}; + +// event for sending through receive item +event EAmmoPackItem { + INDEX iShells, + INDEX iBullets, + INDEX iRockets, + INDEX iGrenades, + INDEX iNapalm, + INDEX iElectricity, + INDEX iIronBalls, +// INDEX iNukeBalls, + INDEX iSniperBullets, +}; + +class CAmmoPack : CItem { +name "Ammo Pack"; +thumbnail "Thumbnails\\AmmoPack.tbn"; + +properties: + 1 enum AmmoPackType m_aptPackType "Type" 'Y' = APT_CUSTOM, // pack type + + 10 INDEX m_iShells "Shells" 'S' = MAX_SHELLS, + 11 INDEX m_iBullets "Bullets" 'B' = MAX_BULLETS, + 12 INDEX m_iRockets "Rockets" 'C' = MAX_ROCKETS, + 13 INDEX m_iGrenades "Grenades" 'G' = MAX_GRENADES, + 14 INDEX m_iNapalm "Napalm" 'P' = MAX_NAPALM, + 15 INDEX m_iElectricity "Electricity" 'E' = MAX_ELECTRICITY, + 16 INDEX m_iIronBalls "Iron balls" 'I' = MAX_IRONBALLS, +// 17 INDEX m_iNukeBalls "Nuke balls" 'U' = MAX_NUKEBALLS, + 17 INDEX m_iSniperBullets "Sniper bullets" 'N' = MAX_SNIPERBULLETS, + +components: + 0 class CLASS_BASE "Classes\\Item.ecl", + +// ********* BACK PACK ********* + 60 model MODEL_BACKPACK "Models\\Items\\PowerUps\\BackPack\\BackPack.mdl", + 61 texture TEXTURE_BACKPACK "Models\\Items\\PowerUps\\BackPack\\BackPack.tex", + +// ********* SERIOUS PACK ********* + 70 model MODEL_SERIOUSPACK "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.mdl", + 71 texture TEXTURE_SERIOUSPACK "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.tex", + +// ************** FLARE FOR EFFECT ************** +100 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex", +101 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl", + +// ************** SOUNDS ************** +213 sound SOUND_PICK "Sounds\\Items\\Ammo.wav", + +functions: + void Precache(void) { + PrecacheSound(SOUND_PICK); + } + + // render particles + void RenderParticles(void) + { + // no particles when not existing or in DM modes + if (GetRenderType()!=CEntity::RT_MODEL || GetSP()->sp_gmGameMode>CSessionProperties::GM_COOPERATIVE + || !ShowItemParticles()) + { + return; + } + + Particles_Spiral(this, 3.0f*0.5, 2.5f*0.5, PT_STAR04, 10); + } + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + pes->es_ctCount = 1; + pes->es_ctAmmount = 1; + // compile description +// pes->es_strName.PrintF("Back pack: %d Shells, %d Bullets, %d Rockets, %d Grenades, %d Napalm, %d Electricity, %d Iron balls, %d Nuke balls", +// m_iShells, m_iBullets, m_iRockets, m_iGrenades, m_iNapalm, m_iElectricity, m_iIronBalls, m_iNukeBalls); +// pes->es_strName.PrintF("Back pack: %d Shells, %d Bullets, %d Rockets, %d Grenades, %d Electricity, %d Iron balls", +// m_iShells, m_iBullets, m_iRockets, m_iGrenades, m_iElectricity, m_iIronBalls); + pes->es_strName.PrintF("Back pack: %d Shells, %d Bullets, %d Rockets, %d Grenades, %d Napalm, %d Electricity, %d Iron balls, %d Sniper bullets", + m_iShells, m_iBullets, m_iRockets, m_iGrenades, m_iNapalm, m_iElectricity, m_iIronBalls, m_iSniperBullets); + + // calculate value + pes->es_fValue = + m_iShells*AV_SHELLS + + m_iBullets*AV_BULLETS + + m_iRockets*AV_ROCKETS + + m_iGrenades*AV_GRENADES + + m_iNapalm*AV_NAPALM + + m_iElectricity*AV_ELECTRICITY + + m_iIronBalls*AV_IRONBALLS + + m_iSniperBullets*AV_SNIPERBULLETS/*+ + m_iNukeBalls*AV_NUKEBALLS*/; + + pes->es_iScore = 0; + return TRUE; + } + + // set ammo properties depending on ammo type + void SetProperties(void) + { + switch (m_aptPackType) + { + case APT_SERIOUS: + m_strDescription = "Serious:"; + // set appearance + AddItem(MODEL_SERIOUSPACK, TEXTURE_SERIOUSPACK, 0,0,0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(2,2,1.3f) ); + StretchItem(FLOAT3D(0.5f, 0.5f, 0.5f)); + break; + case APT_CUSTOM: + m_strDescription = "Custom:"; + // set appearance + AddItem(MODEL_BACKPACK, TEXTURE_BACKPACK, 0,0,0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(2,2,1.3f) ); + StretchItem(FLOAT3D(0.5f, 0.5f, 0.5f)); + break; + default: ASSERTALWAYS("Uknown ammo"); + } + + m_fValue = 1.0f; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + if( m_iShells != 0) {m_strDescription.PrintF("%s: Shells (%d)", m_strDescription, m_iShells);} + if( m_iBullets != 0) {m_strDescription.PrintF("%s: Bullets (%d)", m_strDescription, m_iBullets);} + if( m_iRockets != 0) {m_strDescription.PrintF("%s: Rockets (%d)", m_strDescription, m_iRockets);} + if( m_iGrenades != 0) {m_strDescription.PrintF("%s: Grenades (%d)", m_strDescription, m_iGrenades);} + if( m_iNapalm != 0) {m_strDescription.PrintF("%s: Napalm (%d)", m_strDescription, m_iNapalm);} + if( m_iElectricity != 0) {m_strDescription.PrintF("%s: Electricity (%d)", m_strDescription, m_iElectricity);} + if( m_iIronBalls != 0) {m_strDescription.PrintF("%s: Iron balls (%d)", m_strDescription, m_iIronBalls);} +// if( m_iNukeBalls != 0) {m_strDescription.PrintF("%s: Nuke balls (%d)", m_strDescription, m_iNukeBalls);} + if( m_iSniperBullets != 0) {m_strDescription.PrintF("%s: Sniper bullets (%d)", m_strDescription, m_iSniperBullets);} + } + + void AdjustDifficulty(void) + { + //m_fValue = ceil(m_fValue*GetSP()->sp_fAmmoQuantity); + + if (GetSP()->sp_bInfiniteAmmo && m_penTarget==NULL) { + Destroy(); + } + } + +procedures: + ItemCollected(EPass epass) : CItem::ItemCollected + { + ASSERT(epass.penOther!=NULL); + + // if ammo stays + if (GetSP()->sp_bAmmoStays && !(m_bPickupOnce||m_bRespawn)) { + // if already picked by this player + BOOL bWasPicked = MarkPickedBy(epass.penOther); + if (bWasPicked) { + // don't pick again + return; + } + } + + // send ammo to entity + EAmmoPackItem eAmmo; + eAmmo.iShells = m_iShells; + eAmmo.iBullets = m_iBullets; + eAmmo.iRockets = m_iRockets; + eAmmo.iGrenades = m_iGrenades; + eAmmo.iNapalm = m_iNapalm; + eAmmo.iElectricity = m_iElectricity; + eAmmo.iIronBalls = m_iIronBalls; +// eAmmo.iNukeBalls = m_iNukeBalls; + eAmmo.iSniperBullets = m_iSniperBullets; + // if health is received + if (epass.penOther->ReceiveItem(eAmmo)) { + // play the pickup sound + m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f); + PlaySound(m_soPick, SOUND_PICK, SOF_3D); + m_fPickSoundLen = GetSoundLength(SOUND_PICK); + if (!GetSP()->sp_bAmmoStays || (m_bPickupOnce||m_bRespawn)) { + jump CItem::ItemReceived(); + } + } + return; + }; + + Main() { + m_iShells = Clamp( m_iShells, INDEX(0), MAX_SHELLS); + m_iBullets = Clamp( m_iBullets, INDEX(0), MAX_BULLETS); + m_iRockets = Clamp( m_iRockets, INDEX(0), MAX_ROCKETS); + m_iGrenades = Clamp( m_iGrenades, INDEX(0), MAX_GRENADES); + m_iNapalm = Clamp( m_iNapalm, INDEX(0), MAX_NAPALM); + m_iElectricity = Clamp( m_iElectricity, INDEX(0), MAX_ELECTRICITY); + m_iIronBalls = Clamp( m_iIronBalls, INDEX(0), MAX_IRONBALLS); +// m_iNukeBalls = Clamp( m_iNukeBalls, INDEX(0), MAX_NUKEBALLS); + m_iSniperBullets = Clamp( m_iSniperBullets, INDEX(0), MAX_SNIPERBULLETS); + + Initialize(); // initialize base class + StartModelAnim(ITEMHOLDER_ANIM_MEDIUMOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM); + SetProperties(); // set properties + + jump CItem::ItemLoop(); + }; +}; diff --git a/Sources/EntitiesMP/AmmoPack.h b/Sources/EntitiesMP/AmmoPack.h new file mode 100644 index 0000000..166f482 --- /dev/null +++ b/Sources/EntitiesMP/AmmoPack.h @@ -0,0 +1,66 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_AmmoPack_INCLUDED +#define _EntitiesMP_AmmoPack_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType AmmoPackType_enum; +enum AmmoPackType { + APT_CUSTOM = 1, + APT_SERIOUS = 2, +}; +DECL_DLL inline void ClearToDefault(AmmoPackType &e) { e = (AmmoPackType)0; } ; +#define EVENTCODE_EAmmoPackItem 0x03260000 +class DECL_DLL EAmmoPackItem : public CEntityEvent { +public: +EAmmoPackItem(); +CEntityEvent *MakeCopy(void); +INDEX iShells; +INDEX iBullets; +INDEX iRockets; +INDEX iGrenades; +INDEX iNapalm; +INDEX iElectricity; +INDEX iIronBalls; +INDEX iSniperBullets; +}; +DECL_DLL inline void ClearToDefault(EAmmoPackItem &e) { e = EAmmoPackItem(); } ; +extern "C" DECL_DLL CDLLEntityClass CAmmoPack_DLLClass; +class CAmmoPack : public CItem { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum AmmoPackType m_aptPackType; + INDEX m_iShells; + INDEX m_iBullets; + INDEX m_iRockets; + INDEX m_iGrenades; + INDEX m_iNapalm; + INDEX m_iElectricity; + INDEX m_iIronBalls; + INDEX m_iSniperBullets; + +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +void Precache(void); + +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +void RenderParticles(void); + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +void SetProperties(void); + +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +void AdjustDifficulty(void); +#define STATE_CAmmoPack_ItemCollected 0x03260001 + BOOL +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +ItemCollected(const CEntityEvent &__eeInput); +#define STATE_CAmmoPack_Main 1 + BOOL +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_AmmoPack_INCLUDED diff --git a/Sources/EntitiesMP/AmmoPack_tables.h b/Sources/EntitiesMP/AmmoPack_tables.h new file mode 100644 index 0000000..26d060f --- /dev/null +++ b/Sources/EntitiesMP/AmmoPack_tables.h @@ -0,0 +1,64 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(AmmoPackType) + EP_ENUMVALUE(APT_CUSTOM, "Custom pack"), + EP_ENUMVALUE(APT_SERIOUS, "Serious pack"), +EP_ENUMEND(AmmoPackType); + +#define ENTITYCLASS CAmmoPack + +CEntityProperty CAmmoPack_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &AmmoPackType_enum, (0x00000326<<8)+1, offsetof(CAmmoPack, m_aptPackType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000326<<8)+10, offsetof(CAmmoPack, m_iShells), "Shells", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000326<<8)+11, offsetof(CAmmoPack, m_iBullets), "Bullets", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000326<<8)+12, offsetof(CAmmoPack, m_iRockets), "Rockets", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000326<<8)+13, offsetof(CAmmoPack, m_iGrenades), "Grenades", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000326<<8)+14, offsetof(CAmmoPack, m_iNapalm), "Napalm", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000326<<8)+15, offsetof(CAmmoPack, m_iElectricity), "Electricity", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000326<<8)+16, offsetof(CAmmoPack, m_iIronBalls), "Iron balls", 'I', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000326<<8)+17, offsetof(CAmmoPack, m_iSniperBullets), "Sniper bullets", 'N', 0x7F0000FFUL, 0), +}; +#define CAmmoPack_propertiesct ARRAYCOUNT(CAmmoPack_properties) + +CEntityComponent CAmmoPack_components[] = { +#define CLASS_BASE ((0x00000326<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\Item.ecl"), +#define MODEL_BACKPACK ((0x00000326<<8)+60) + CEntityComponent(ECT_MODEL, MODEL_BACKPACK, "EFNM" "Models\\Items\\PowerUps\\BackPack\\BackPack.mdl"), +#define TEXTURE_BACKPACK ((0x00000326<<8)+61) + CEntityComponent(ECT_TEXTURE, TEXTURE_BACKPACK, "EFNM" "Models\\Items\\PowerUps\\BackPack\\BackPack.tex"), +#define MODEL_SERIOUSPACK ((0x00000326<<8)+70) + CEntityComponent(ECT_MODEL, MODEL_SERIOUSPACK, "EFNM" "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.mdl"), +#define TEXTURE_SERIOUSPACK ((0x00000326<<8)+71) + CEntityComponent(ECT_TEXTURE, TEXTURE_SERIOUSPACK, "EFNM" "Models\\Items\\PowerUps\\SeriousPack\\SeriousPack.tex"), +#define TEXTURE_FLARE ((0x00000326<<8)+100) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.tex"), +#define MODEL_FLARE ((0x00000326<<8)+101) + CEntityComponent(ECT_MODEL, MODEL_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.mdl"), +#define SOUND_PICK ((0x00000326<<8)+213) + CEntityComponent(ECT_SOUND, SOUND_PICK, "EFNM" "Sounds\\Items\\Ammo.wav"), +}; +#define CAmmoPack_componentsct ARRAYCOUNT(CAmmoPack_components) + +CEventHandlerEntry CAmmoPack_handlers[] = { + {0x03260001, STATE_CItem_ItemCollected, CEntity::pEventHandler(&CAmmoPack:: +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +ItemCollected),DEBUGSTRING("CAmmoPack::ItemCollected")}, + {1, -1, CEntity::pEventHandler(&CAmmoPack:: +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/AmmoPack.es" +Main),DEBUGSTRING("CAmmoPack::Main")}, +}; +#define CAmmoPack_handlersct ARRAYCOUNT(CAmmoPack_handlers) + +CEntity *CAmmoPack_New(void) { return new CAmmoPack; }; +void CAmmoPack_OnInitClass(void) {}; +void CAmmoPack_OnEndClass(void) {}; +void CAmmoPack_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CAmmoPack_OnWorldEnd(CWorld *pwo) {}; +void CAmmoPack_OnWorldInit(CWorld *pwo) {}; +void CAmmoPack_OnWorldTick(CWorld *pwo) {}; +void CAmmoPack_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CAmmoPack, CItem, "Ammo Pack", "Thumbnails\\AmmoPack.tbn", 0x00000326); +DECLARE_CTFILENAME(_fnmCAmmoPack_tbn, "Thumbnails\\AmmoPack.tbn"); diff --git a/Sources/EntitiesMP/AnimationChanger.cpp b/Sources/EntitiesMP/AnimationChanger.cpp new file mode 100644 index 0000000..baa729e --- /dev/null +++ b/Sources/EntitiesMP/AnimationChanger.cpp @@ -0,0 +1,206 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" + +#include "StdH.h" +#include + +#include +#include +CEntityEvent *EChangeAnim::MakeCopy(void) { CEntityEvent *peeCopy = new EChangeAnim(*this); return peeCopy;} +EChangeAnim::EChangeAnim() : CEntityEvent(EVENTCODE_EChangeAnim) {; + ClearToDefault(iModelAnim); + ClearToDefault(bModelLoop); + ClearToDefault(iTextureAnim); + ClearToDefault(bTextureLoop); + ClearToDefault(iLightAnim); + ClearToDefault(iAmbientLightAnim); + ClearToDefault(bLightLoop); + ClearToDefault(bAmbientLightLoop); + ClearToDefault(colAmbient); + ClearToDefault(colDiffuse); +}; +void CAnimationChanger::SetDefaultProperties(void) { + m_strName = "Animation changer"; + m_strDescription = ""; + m_penTarget = NULL; + m_iModelAnim = 0; + m_bModelLoop = FALSE ; + m_iTextureAnim = 0; + m_bTextureLoop = FALSE ; + m_iLightAnim = 0; + m_bLightLoop = FALSE ; + m_iAmbientLightAnim = 0; + m_bAmbientLightLoop = FALSE ; + m_colAmbient = C_dBLUE ; + m_colDiffuse = C_GRAY ; + CRationalEntity::SetDefaultProperties(); +} + +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +const CTString & CAnimationChanger::GetDescription(void)const { +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +if(m_penTarget != NULL ){ +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , m_penTarget -> GetName ()); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return m_strDescription ; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} + +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +CAnimData * CAnimationChanger::GetAnimData(SLONG slPropertyOffset) +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +{ +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +CEntity * penTarget = m_penTarget ; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +if(penTarget == NULL ){ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return NULL ; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +if(IsOfClass (penTarget , "AnimationHub")){ +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +penTarget = ((CAnimationHub *) penTarget ) -> m_penTarget0 ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +if(penTarget == NULL ){ +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return NULL ; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +if(IsOfClass (penTarget , "ModelHolder2")){ +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +CModelHolder2 * penModel = (CModelHolder2 *) & * penTarget ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +if(slPropertyOffset == offsetof (CAnimationChanger , m_iModelAnim )){ +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return penModel -> GetModelObject () -> GetData (); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +}else if(slPropertyOffset == offsetof (CAnimationChanger , m_iTextureAnim )){ +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return penModel -> GetModelObject () -> mo_toTexture . GetData (); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +}else if(slPropertyOffset == offsetof (CAnimationChanger , m_iLightAnim )){ +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return penModel -> m_aoLightAnimation . GetData (); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +}else if(IsOfClass (penTarget , "Light")){ +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +CLight * penLight = (CLight *) & * penTarget ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +if(slPropertyOffset == offsetof (CAnimationChanger , m_iLightAnim )) +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +{ +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return penLight -> m_aoLightAnimation . GetData (); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +else if(slPropertyOffset == offsetof (CAnimationChanger , m_iAmbientLightAnim )) +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +{ +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return penLight -> m_aoAmbientLightAnimation . GetData (); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return CEntity :: GetAnimData (slPropertyOffset ); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} +BOOL CAnimationChanger:: +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAnimationChanger_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAnimationChanger::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +InitAsEditorModel (); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +SetModel (MODEL_CHANGER ); +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +SetModelMainTexture (TEXTURE_CHANGER ); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +if(m_penTarget != NULL && +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +! IsOfClass (m_penTarget , "AnimationHub") && +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +! IsOfClass (m_penTarget , "ModelHolder2") && +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +! IsOfClass (m_penTarget , "Light")){ +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +WarningMessage ("Target must be AnimationHub ModelHolder2 or Light!"); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +m_penTarget = NULL ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +if(m_penTarget == NULL ){ +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +Return(STATE_CURRENT,EVoid()); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return TRUE; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +} +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00da0001, FALSE, EBegin());return TRUE;}BOOL CAnimationChanger::H0x00da0001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00da0001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; + +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +EChangeAnim eChange ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +eChange . iModelAnim = m_iModelAnim ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +eChange . iTextureAnim = m_iTextureAnim ; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +eChange . iLightAnim = m_iLightAnim ; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +eChange . iAmbientLightAnim = m_iAmbientLightAnim ; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +eChange . bModelLoop = m_bModelLoop ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +eChange . bTextureLoop = m_bTextureLoop ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +eChange . bLightLoop = m_bLightLoop ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +eChange . colAmbient = m_colAmbient ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +eChange . colDiffuse = m_colDiffuse ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +m_penTarget -> SendEvent (eChange ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return TRUE; +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +}return TRUE;}BOOL CAnimationChanger::H0x00da0002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00da0002 + +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +Return(STATE_CURRENT,EVoid()); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/AnimationChanger.es b/Sources/EntitiesMP/AnimationChanger.es new file mode 100644 index 0000000..c9ce1d1 --- /dev/null +++ b/Sources/EntitiesMP/AnimationChanger.es @@ -0,0 +1,148 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +218 +%{ +#include "StdH.h" +#include +%} + +uses "EntitiesMP/ModelHolder2"; +uses "EntitiesMP/Light"; + +// event sent to the entity that should change animation +event EChangeAnim { + INDEX iModelAnim, + BOOL bModelLoop, + INDEX iTextureAnim, + BOOL bTextureLoop, + INDEX iLightAnim, + INDEX iAmbientLightAnim, + BOOL bLightLoop, + BOOL bAmbientLightLoop, + COLOR colAmbient, + COLOR colDiffuse, +}; + +class CAnimationChanger : CRationalEntity { +name "AnimationChanger"; +thumbnail "Thumbnails\\AnimationChanger.tbn"; +features "HasName", "HasTarget", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "Animation changer", + 2 CTString m_strDescription = "", + 3 CEntityPointer m_penTarget "Target" 'T' COLOR(C_GREEN|0xFF), + 4 ANIMATION m_iModelAnim "Model Animation" 'M' = 0, + 5 BOOL m_bModelLoop "Model Looping" = FALSE, + 6 ANIMATION m_iTextureAnim "Texture Animation" 'X' = 0, + 7 BOOL m_bTextureLoop "Texture Looping" = FALSE, + 8 ANIMATION m_iLightAnim "Diffuse Light Animation" 'L' = 0, + 9 BOOL m_bLightLoop "Diffuse Light Looping" = FALSE, + 10 ANIMATION m_iAmbientLightAnim "Ambient Light Animation" 'B' = 0, + 11 BOOL m_bAmbientLightLoop "Ambient Light Looping" = FALSE, + 12 COLOR m_colAmbient "Ambient Light Color" 'A' = C_dBLUE, + 13 COLOR m_colDiffuse "Diffuse Light Color" 'C' = C_GRAY, + +components: + 1 model MODEL_CHANGER "Models\\Editor\\AnimationChanger.mdl", + 2 texture TEXTURE_CHANGER "Models\\Editor\\AnimationChanger.tex" + +functions: + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("->"); + if (m_penTarget!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", m_penTarget->GetName()); + } + return m_strDescription; + } + + /* Get anim data for given animation property - return NULL for none. */ + CAnimData *GetAnimData(SLONG slPropertyOffset) + { + CEntity *penTarget = m_penTarget; + + if (penTarget==NULL) { + return NULL; + } + + if (IsOfClass(penTarget, "AnimationHub")) { + penTarget = ((CAnimationHub*)penTarget)->m_penTarget0; + } + + if (penTarget==NULL) { + return NULL; + } + + // if modelholder + if (IsOfClass(penTarget, "ModelHolder2")) { + CModelHolder2 *penModel = (CModelHolder2*)&*penTarget; + if (slPropertyOffset==offsetof(CAnimationChanger, m_iModelAnim)) { + return penModel->GetModelObject()->GetData(); + } else if (slPropertyOffset==offsetof(CAnimationChanger, m_iTextureAnim)) { + return penModel->GetModelObject()->mo_toTexture.GetData(); + } else if (slPropertyOffset==offsetof(CAnimationChanger, m_iLightAnim)) { + return penModel->m_aoLightAnimation.GetData(); + } + + // if light + } else if (IsOfClass(penTarget, "Light")) { + CLight *penLight = (CLight*)&*penTarget; + + if (slPropertyOffset==offsetof(CAnimationChanger, m_iLightAnim)) + { + return penLight->m_aoLightAnimation.GetData(); + } + else if (slPropertyOffset==offsetof(CAnimationChanger, m_iAmbientLightAnim)) + { + return penLight->m_aoAmbientLightAnimation.GetData(); + } + } + + return CEntity::GetAnimData(slPropertyOffset); + }; + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_CHANGER); + SetModelMainTexture(TEXTURE_CHANGER); + + // check target type + if (m_penTarget!=NULL && + !IsOfClass(m_penTarget, "AnimationHub") && + !IsOfClass(m_penTarget, "ModelHolder2") && + !IsOfClass(m_penTarget, "Light")) { + WarningMessage("Target must be AnimationHub ModelHolder2 or Light!"); + m_penTarget=NULL; + } + if (m_penTarget==NULL) { + return; + } + + //main loop + wait() { + on (EBegin) : { resume; } + on (EStart) : { + EChangeAnim eChange; + eChange.iModelAnim =m_iModelAnim ; + eChange.iTextureAnim =m_iTextureAnim; + eChange.iLightAnim =m_iLightAnim ; + eChange.iAmbientLightAnim =m_iAmbientLightAnim; + eChange.bModelLoop =m_bModelLoop ; + eChange.bTextureLoop =m_bTextureLoop; + eChange.bLightLoop =m_bLightLoop ; + eChange.colAmbient =m_colAmbient ; + eChange.colDiffuse =m_colDiffuse ; + m_penTarget->SendEvent(eChange); + resume; + } + } + return; + } +}; + diff --git a/Sources/EntitiesMP/AnimationChanger.h b/Sources/EntitiesMP/AnimationChanger.h new file mode 100644 index 0000000..46d3e54 --- /dev/null +++ b/Sources/EntitiesMP/AnimationChanger.h @@ -0,0 +1,59 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_AnimationChanger_INCLUDED +#define _EntitiesMP_AnimationChanger_INCLUDED 1 +#include +#include +#define EVENTCODE_EChangeAnim 0x00da0000 +class DECL_DLL EChangeAnim : public CEntityEvent { +public: +EChangeAnim(); +CEntityEvent *MakeCopy(void); +INDEX iModelAnim; +BOOL bModelLoop; +INDEX iTextureAnim; +BOOL bTextureLoop; +INDEX iLightAnim; +INDEX iAmbientLightAnim; +BOOL bLightLoop; +BOOL bAmbientLightLoop; +COLOR colAmbient; +COLOR colDiffuse; +}; +DECL_DLL inline void ClearToDefault(EChangeAnim &e) { e = EChangeAnim(); } ; +extern "C" DECL_DLL CDLLEntityClass CAnimationChanger_DLLClass; +class CAnimationChanger : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual CEntity *GetTarget(void) const { return m_penTarget; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CEntityPointer m_penTarget; + ANIMATION m_iModelAnim; + BOOL m_bModelLoop; + ANIMATION m_iTextureAnim; + BOOL m_bTextureLoop; + ANIMATION m_iLightAnim; + BOOL m_bLightLoop; + ANIMATION m_iAmbientLightAnim; + BOOL m_bAmbientLightLoop; + COLOR m_colAmbient; + COLOR m_colDiffuse; + +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +const CTString & GetDescription(void)const; + +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +CAnimData * GetAnimData(SLONG slPropertyOffset); +#define STATE_CAnimationChanger_Main 1 + BOOL +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00da0001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00da0002_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_AnimationChanger_INCLUDED diff --git a/Sources/EntitiesMP/AnimationChanger_tables.h b/Sources/EntitiesMP/AnimationChanger_tables.h new file mode 100644 index 0000000..eecca49 --- /dev/null +++ b/Sources/EntitiesMP/AnimationChanger_tables.h @@ -0,0 +1,50 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CAnimationChanger + +CEntityProperty CAnimationChanger_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000da<<8)+1, offsetof(CAnimationChanger, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000da<<8)+2, offsetof(CAnimationChanger, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000da<<8)+3, offsetof(CAnimationChanger, m_penTarget), "Target", 'T', C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000da<<8)+4, offsetof(CAnimationChanger, m_iModelAnim), "Model Animation", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000da<<8)+5, offsetof(CAnimationChanger, m_bModelLoop), "Model Looping", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000da<<8)+6, offsetof(CAnimationChanger, m_iTextureAnim), "Texture Animation", 'X', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000da<<8)+7, offsetof(CAnimationChanger, m_bTextureLoop), "Texture Looping", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000da<<8)+8, offsetof(CAnimationChanger, m_iLightAnim), "Diffuse Light Animation", 'L', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000da<<8)+9, offsetof(CAnimationChanger, m_bLightLoop), "Diffuse Light Looping", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000da<<8)+10, offsetof(CAnimationChanger, m_iAmbientLightAnim), "Ambient Light Animation", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000da<<8)+11, offsetof(CAnimationChanger, m_bAmbientLightLoop), "Ambient Light Looping", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000da<<8)+12, offsetof(CAnimationChanger, m_colAmbient), "Ambient Light Color", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000da<<8)+13, offsetof(CAnimationChanger, m_colDiffuse), "Diffuse Light Color", 'C', 0x7F0000FFUL, 0), +}; +#define CAnimationChanger_propertiesct ARRAYCOUNT(CAnimationChanger_properties) + +CEntityComponent CAnimationChanger_components[] = { +#define MODEL_CHANGER ((0x000000da<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_CHANGER, "EFNM" "Models\\Editor\\AnimationChanger.mdl"), +#define TEXTURE_CHANGER ((0x000000da<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_CHANGER, "EFNM" "Models\\Editor\\AnimationChanger.tex"), +}; +#define CAnimationChanger_componentsct ARRAYCOUNT(CAnimationChanger_components) + +CEventHandlerEntry CAnimationChanger_handlers[] = { + {1, -1, CEntity::pEventHandler(&CAnimationChanger:: +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/AnimationChanger.es" +Main),DEBUGSTRING("CAnimationChanger::Main")}, + {0x00da0001, -1, CEntity::pEventHandler(&CAnimationChanger::H0x00da0001_Main_01), DEBUGSTRING("CAnimationChanger::H0x00da0001_Main_01")}, + {0x00da0002, -1, CEntity::pEventHandler(&CAnimationChanger::H0x00da0002_Main_02), DEBUGSTRING("CAnimationChanger::H0x00da0002_Main_02")}, +}; +#define CAnimationChanger_handlersct ARRAYCOUNT(CAnimationChanger_handlers) + +CEntity *CAnimationChanger_New(void) { return new CAnimationChanger; }; +void CAnimationChanger_OnInitClass(void) {}; +void CAnimationChanger_OnEndClass(void) {}; +void CAnimationChanger_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CAnimationChanger_OnWorldEnd(CWorld *pwo) {}; +void CAnimationChanger_OnWorldInit(CWorld *pwo) {}; +void CAnimationChanger_OnWorldTick(CWorld *pwo) {}; +void CAnimationChanger_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CAnimationChanger, CRationalEntity, "AnimationChanger", "Thumbnails\\AnimationChanger.tbn", 0x000000da); +DECLARE_CTFILENAME(_fnmCAnimationChanger_tbn, "Thumbnails\\AnimationChanger.tbn"); diff --git a/Sources/EntitiesMP/AnimationHub.cpp b/Sources/EntitiesMP/AnimationHub.cpp new file mode 100644 index 0000000..c660934 --- /dev/null +++ b/Sources/EntitiesMP/AnimationHub.cpp @@ -0,0 +1,216 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" + +#include "StdH.h" +#include + +#include +#include +void CAnimationHub::SetDefaultProperties(void) { + m_strName = "Animation hub"; + m_strDescription = ""; + m_tmDelayEach = 0.0f; + m_penTarget0 = NULL; + m_penTarget1 = NULL; + m_penTarget2 = NULL; + m_penTarget3 = NULL; + m_penTarget4 = NULL; + m_penTarget5 = NULL; + m_penTarget6 = NULL; + m_penTarget7 = NULL; + m_penTarget8 = NULL; + m_penTarget9 = NULL; + m_tmDelay0 = 0.0f; + m_tmDelay1 = 0.0f; + m_tmDelay2 = 0.0f; + m_tmDelay3 = 0.0f; + m_tmDelay4 = 0.0f; + m_tmDelay5 = 0.0f; + m_tmDelay6 = 0.0f; + m_tmDelay7 = 0.0f; + m_tmDelay8 = 0.0f; + m_tmDelay9 = 0.0f; + m_iModelAnim = 0; + m_bModelLoop = 0; + m_iTextureAnim = 0; + m_bTextureLoop = 0; + m_iLightAnim = 0; + m_bLightLoop = 0; + m_colAmbient = 0; + m_colDiffuse = 0; + m_iCounter = 0; + CRationalEntity::SetDefaultProperties(); +} + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +const CTString & CAnimationHub::GetDescription(void)const { +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +if(m_penTarget0 != NULL ){ +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +((CTString &) m_strDescription ) . PrintF ("->%s..." , m_penTarget0 -> GetName ()); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +} +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +return m_strDescription ; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +} +BOOL CAnimationHub:: +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +RelayEvents(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAnimationHub_RelayEvents + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAnimationHub::RelayEvents expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +m_iCounter = 0; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +Jump(STATE_CURRENT,0x00e40004, FALSE, EInternal());return TRUE;}BOOL CAnimationHub::H0x00e40004_RelayEvents_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e40004 +if(!(m_iCounter < 10)){ Jump(STATE_CURRENT,0x00e40005, FALSE, EInternal());return TRUE;} +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +FLOAT fDelay = m_tmDelayEach + (& m_tmDelay0 ) [ m_iCounter ]; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +if(!(fDelay > 0)){ Jump(STATE_CURRENT,0x00e40003, FALSE, EInternal());return TRUE;} +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +SetTimerAfter(fDelay ); +Jump(STATE_CURRENT, 0x00e40001, FALSE, EBegin());return TRUE;}BOOL CAnimationHub::H0x00e40001_RelayEvents_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e40001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00e40002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CAnimationHub::H0x00e40002_RelayEvents_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e40002 +;Jump(STATE_CURRENT,0x00e40003, FALSE, EInternal());return TRUE;}BOOL CAnimationHub::H0x00e40003_RelayEvents_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e40003 + +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +CEntity * penTarget = (& m_penTarget0 ) [ m_iCounter ]; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +if(penTarget == NULL ){ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +Jump(STATE_CURRENT, STATE_CAnimationHub_WaitChange, TRUE, EVoid());return TRUE; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +} +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +EChangeAnim eca ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +eca . iModelAnim = m_iModelAnim ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +eca . bModelLoop = m_bModelLoop ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +eca . iTextureAnim = m_iTextureAnim ; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +eca . bTextureLoop = m_bTextureLoop ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +eca . iLightAnim = m_iLightAnim ; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +eca . bLightLoop = m_bLightLoop ; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +eca . colAmbient = m_colAmbient ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +eca . colDiffuse = m_colDiffuse ; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +penTarget -> SendEvent (eca ); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +m_iCounter ++;Jump(STATE_CURRENT,0x00e40004, FALSE, EInternal());return TRUE; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +}BOOL CAnimationHub::H0x00e40005_RelayEvents_05(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e40005 + +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +Jump(STATE_CURRENT, STATE_CAnimationHub_WaitChange, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CAnimationHub:: +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +WaitChange(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAnimationHub_WaitChange + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAnimationHub::WaitChange expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +Jump(STATE_CURRENT,0x00e40009, FALSE, EInternal());return TRUE;}BOOL CAnimationHub::H0x00e40009_WaitChange_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e40009 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00e4000a, FALSE, EInternal());return TRUE;} +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00e40007, FALSE, EBegin());return TRUE;}BOOL CAnimationHub::H0x00e40007_WaitChange_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e40007 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EChangeAnim):{const EChangeAnim&eca= (EChangeAnim&)__eeInput; + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +m_iModelAnim = eca . iModelAnim ; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +m_bModelLoop = eca . bModelLoop ; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +m_iTextureAnim = eca . iTextureAnim ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +m_bTextureLoop = eca . bTextureLoop ; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +m_iLightAnim = eca . iLightAnim ; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +m_bLightLoop = eca . bLightLoop ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +m_colAmbient = eca . colAmbient ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +m_colDiffuse = eca . colDiffuse ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +Jump(STATE_CURRENT, STATE_CAnimationHub_RelayEvents, TRUE, EVoid());return TRUE; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +}return TRUE;}BOOL CAnimationHub::H0x00e40008_WaitChange_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e40008 +Jump(STATE_CURRENT,0x00e40009, FALSE, EInternal());return TRUE; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +}BOOL CAnimationHub::H0x00e4000a_WaitChange_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e4000a + ASSERT(FALSE); return TRUE;};BOOL CAnimationHub:: +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAnimationHub_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAnimationHub::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +InitAsEditorModel (); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +SetModel (MODEL_HUB ); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +SetModelMainTexture (TEXTURE_HUB ); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +for(INDEX i = 0;i < 10;i ++){ +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +CEntityPointer & penTarget = (& m_penTarget0 ) [ i ]; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +if(penTarget != NULL && +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +! IsOfClass (penTarget , "ModelHolder2") && +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +! IsOfClass (penTarget , "Light")){ +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +WarningMessage ("All targets must be ModelHolder2 or Light!"); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +penTarget = NULL ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +} +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +} +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +Jump(STATE_CURRENT, STATE_CAnimationHub_WaitChange, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/AnimationHub.es b/Sources/EntitiesMP/AnimationHub.es new file mode 100644 index 0000000..577976e --- /dev/null +++ b/Sources/EntitiesMP/AnimationHub.es @@ -0,0 +1,149 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +228 +%{ +#include "StdH.h" +#include +%} + + +class CAnimationHub : CRationalEntity { +name "AnimationHub"; +thumbnail "Thumbnails\\AnimationHub.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "Animation hub", + 2 CTString m_strDescription = "", + + 3 FLOAT m_tmDelayEach "Delay each" 'D' = 0.0f, + + 10 CEntityPointer m_penTarget0 "Target0" 'T' COLOR(C_GREEN|0xFF), + 11 CEntityPointer m_penTarget1 "Target1" COLOR(C_GREEN|0xFF), + 12 CEntityPointer m_penTarget2 "Target2" COLOR(C_GREEN|0xFF), + 13 CEntityPointer m_penTarget3 "Target3" COLOR(C_GREEN|0xFF), + 14 CEntityPointer m_penTarget4 "Target4" COLOR(C_GREEN|0xFF), + 15 CEntityPointer m_penTarget5 "Target5" COLOR(C_GREEN|0xFF), + 16 CEntityPointer m_penTarget6 "Target6" COLOR(C_GREEN|0xFF), + 17 CEntityPointer m_penTarget7 "Target7" COLOR(C_GREEN|0xFF), + 18 CEntityPointer m_penTarget8 "Target8" COLOR(C_GREEN|0xFF), + 19 CEntityPointer m_penTarget9 "Target9" COLOR(C_GREEN|0xFF), + + 20 FLOAT m_tmDelay0 "Delay0" = 0.0f, + 21 FLOAT m_tmDelay1 "Delay1" = 0.0f, + 22 FLOAT m_tmDelay2 "Delay2" = 0.0f, + 23 FLOAT m_tmDelay3 "Delay3" = 0.0f, + 24 FLOAT m_tmDelay4 "Delay4" = 0.0f, + 25 FLOAT m_tmDelay5 "Delay5" = 0.0f, + 26 FLOAT m_tmDelay6 "Delay6" = 0.0f, + 27 FLOAT m_tmDelay7 "Delay7" = 0.0f, + 28 FLOAT m_tmDelay8 "Delay8" = 0.0f, + 29 FLOAT m_tmDelay9 "Delay9" = 0.0f, + + 100 INDEX m_iModelAnim = 0, + 101 BOOL m_bModelLoop = 0, + 102 INDEX m_iTextureAnim = 0, + 103 BOOL m_bTextureLoop = 0, + 104 INDEX m_iLightAnim = 0, + 105 BOOL m_bLightLoop = 0, + 106 COLOR m_colAmbient = 0, + 107 COLOR m_colDiffuse = 0, + + 110 INDEX m_iCounter = 0, + +components: + 1 model MODEL_HUB "Models\\Editor\\AnimationHub.mdl", + 2 texture TEXTURE_HUB "Models\\Editor\\AnimationHub.tex" + +functions: + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("->"); + if (m_penTarget0!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s...", m_penTarget0->GetName()); + } + return m_strDescription; + } + +procedures: + RelayEvents() + { + // for each target + m_iCounter=0; + while(m_iCounter<10) { + // get delay + FLOAT fDelay = m_tmDelayEach + (&m_tmDelay0)[m_iCounter]; + // if has delay + if (fDelay>0) { + // wait + autowait(fDelay); + } + + // get the target + CEntity *penTarget = (&m_penTarget0)[m_iCounter]; + // if no more targets + if (penTarget==NULL) { + // stop + jump WaitChange(); + } + // sent event to it + EChangeAnim eca; + eca.iModelAnim = m_iModelAnim ; + eca.bModelLoop = m_bModelLoop ; + eca.iTextureAnim = m_iTextureAnim; + eca.bTextureLoop = m_bTextureLoop; + eca.iLightAnim = m_iLightAnim ; + eca.bLightLoop = m_bLightLoop ; + eca.colAmbient = m_colAmbient ; + eca.colDiffuse = m_colDiffuse ; + penTarget->SendEvent(eca); + + m_iCounter++; + } + + jump WaitChange(); + } + + WaitChange() + { + // wait forever + while(TRUE) { + wait() { + on (EChangeAnim eca) : { + m_iModelAnim = eca.iModelAnim ; + m_bModelLoop = eca.bModelLoop ; + m_iTextureAnim = eca.iTextureAnim; + m_bTextureLoop = eca.bTextureLoop; + m_iLightAnim = eca.iLightAnim ; + m_bLightLoop = eca.bLightLoop ; + m_colAmbient = eca.colAmbient ; + m_colDiffuse = eca.colDiffuse ; + jump RelayEvents(); + } + } + } + } + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_HUB); + SetModelMainTexture(TEXTURE_HUB); + + // check target types + for (INDEX i=0; i<10; i++) { + CEntityPointer &penTarget = (&m_penTarget0)[i]; + if (penTarget!=NULL && + !IsOfClass(penTarget, "ModelHolder2") && + !IsOfClass(penTarget, "Light")) { + WarningMessage("All targets must be ModelHolder2 or Light!"); + penTarget=NULL; + } + } + jump WaitChange(); + } +}; + diff --git a/Sources/EntitiesMP/AnimationHub.h b/Sources/EntitiesMP/AnimationHub.h new file mode 100644 index 0000000..63bfc0d --- /dev/null +++ b/Sources/EntitiesMP/AnimationHub.h @@ -0,0 +1,70 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_AnimationHub_INCLUDED +#define _EntitiesMP_AnimationHub_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CAnimationHub_DLLClass; +class CAnimationHub : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + FLOAT m_tmDelayEach; + CEntityPointer m_penTarget0; + CEntityPointer m_penTarget1; + CEntityPointer m_penTarget2; + CEntityPointer m_penTarget3; + CEntityPointer m_penTarget4; + CEntityPointer m_penTarget5; + CEntityPointer m_penTarget6; + CEntityPointer m_penTarget7; + CEntityPointer m_penTarget8; + CEntityPointer m_penTarget9; + FLOAT m_tmDelay0; + FLOAT m_tmDelay1; + FLOAT m_tmDelay2; + FLOAT m_tmDelay3; + FLOAT m_tmDelay4; + FLOAT m_tmDelay5; + FLOAT m_tmDelay6; + FLOAT m_tmDelay7; + FLOAT m_tmDelay8; + FLOAT m_tmDelay9; + INDEX m_iModelAnim; + BOOL m_bModelLoop; + INDEX m_iTextureAnim; + BOOL m_bTextureLoop; + INDEX m_iLightAnim; + BOOL m_bLightLoop; + COLOR m_colAmbient; + COLOR m_colDiffuse; + INDEX m_iCounter; + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +const CTString & GetDescription(void)const; +#define STATE_CAnimationHub_RelayEvents 0x00e40000 + BOOL +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +RelayEvents(const CEntityEvent &__eeInput); + BOOL H0x00e40001_RelayEvents_01(const CEntityEvent &__eeInput); + BOOL H0x00e40002_RelayEvents_02(const CEntityEvent &__eeInput); + BOOL H0x00e40003_RelayEvents_03(const CEntityEvent &__eeInput); + BOOL H0x00e40004_RelayEvents_04(const CEntityEvent &__eeInput); + BOOL H0x00e40005_RelayEvents_05(const CEntityEvent &__eeInput); +#define STATE_CAnimationHub_WaitChange 0x00e40006 + BOOL +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +WaitChange(const CEntityEvent &__eeInput); + BOOL H0x00e40007_WaitChange_01(const CEntityEvent &__eeInput); + BOOL H0x00e40008_WaitChange_02(const CEntityEvent &__eeInput); + BOOL H0x00e40009_WaitChange_03(const CEntityEvent &__eeInput); + BOOL H0x00e4000a_WaitChange_04(const CEntityEvent &__eeInput); +#define STATE_CAnimationHub_Main 1 + BOOL +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_AnimationHub_INCLUDED diff --git a/Sources/EntitiesMP/AnimationHub_tables.h b/Sources/EntitiesMP/AnimationHub_tables.h new file mode 100644 index 0000000..f69459e --- /dev/null +++ b/Sources/EntitiesMP/AnimationHub_tables.h @@ -0,0 +1,82 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CAnimationHub + +CEntityProperty CAnimationHub_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e4<<8)+1, offsetof(CAnimationHub, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e4<<8)+2, offsetof(CAnimationHub, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e4<<8)+3, offsetof(CAnimationHub, m_tmDelayEach), "Delay each", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e4<<8)+10, offsetof(CAnimationHub, m_penTarget0), "Target0", 'T', C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e4<<8)+11, offsetof(CAnimationHub, m_penTarget1), "Target1", 0, C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e4<<8)+12, offsetof(CAnimationHub, m_penTarget2), "Target2", 0, C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e4<<8)+13, offsetof(CAnimationHub, m_penTarget3), "Target3", 0, C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e4<<8)+14, offsetof(CAnimationHub, m_penTarget4), "Target4", 0, C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e4<<8)+15, offsetof(CAnimationHub, m_penTarget5), "Target5", 0, C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e4<<8)+16, offsetof(CAnimationHub, m_penTarget6), "Target6", 0, C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e4<<8)+17, offsetof(CAnimationHub, m_penTarget7), "Target7", 0, C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e4<<8)+18, offsetof(CAnimationHub, m_penTarget8), "Target8", 0, C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e4<<8)+19, offsetof(CAnimationHub, m_penTarget9), "Target9", 0, C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e4<<8)+20, offsetof(CAnimationHub, m_tmDelay0), "Delay0", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e4<<8)+21, offsetof(CAnimationHub, m_tmDelay1), "Delay1", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e4<<8)+22, offsetof(CAnimationHub, m_tmDelay2), "Delay2", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e4<<8)+23, offsetof(CAnimationHub, m_tmDelay3), "Delay3", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e4<<8)+24, offsetof(CAnimationHub, m_tmDelay4), "Delay4", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e4<<8)+25, offsetof(CAnimationHub, m_tmDelay5), "Delay5", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e4<<8)+26, offsetof(CAnimationHub, m_tmDelay6), "Delay6", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e4<<8)+27, offsetof(CAnimationHub, m_tmDelay7), "Delay7", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e4<<8)+28, offsetof(CAnimationHub, m_tmDelay8), "Delay8", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e4<<8)+29, offsetof(CAnimationHub, m_tmDelay9), "Delay9", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000e4<<8)+100, offsetof(CAnimationHub, m_iModelAnim), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e4<<8)+101, offsetof(CAnimationHub, m_bModelLoop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000e4<<8)+102, offsetof(CAnimationHub, m_iTextureAnim), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e4<<8)+103, offsetof(CAnimationHub, m_bTextureLoop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000e4<<8)+104, offsetof(CAnimationHub, m_iLightAnim), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e4<<8)+105, offsetof(CAnimationHub, m_bLightLoop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000e4<<8)+106, offsetof(CAnimationHub, m_colAmbient), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000e4<<8)+107, offsetof(CAnimationHub, m_colDiffuse), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000e4<<8)+110, offsetof(CAnimationHub, m_iCounter), "", 0, 0, 0), +}; +#define CAnimationHub_propertiesct ARRAYCOUNT(CAnimationHub_properties) + +CEntityComponent CAnimationHub_components[] = { +#define MODEL_HUB ((0x000000e4<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_HUB, "EFNM" "Models\\Editor\\AnimationHub.mdl"), +#define TEXTURE_HUB ((0x000000e4<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_HUB, "EFNM" "Models\\Editor\\AnimationHub.tex"), +}; +#define CAnimationHub_componentsct ARRAYCOUNT(CAnimationHub_components) + +CEventHandlerEntry CAnimationHub_handlers[] = { + {0x00e40000, -1, CEntity::pEventHandler(&CAnimationHub:: +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +RelayEvents),DEBUGSTRING("CAnimationHub::RelayEvents")}, + {0x00e40001, -1, CEntity::pEventHandler(&CAnimationHub::H0x00e40001_RelayEvents_01), DEBUGSTRING("CAnimationHub::H0x00e40001_RelayEvents_01")}, + {0x00e40002, -1, CEntity::pEventHandler(&CAnimationHub::H0x00e40002_RelayEvents_02), DEBUGSTRING("CAnimationHub::H0x00e40002_RelayEvents_02")}, + {0x00e40003, -1, CEntity::pEventHandler(&CAnimationHub::H0x00e40003_RelayEvents_03), DEBUGSTRING("CAnimationHub::H0x00e40003_RelayEvents_03")}, + {0x00e40004, -1, CEntity::pEventHandler(&CAnimationHub::H0x00e40004_RelayEvents_04), DEBUGSTRING("CAnimationHub::H0x00e40004_RelayEvents_04")}, + {0x00e40005, -1, CEntity::pEventHandler(&CAnimationHub::H0x00e40005_RelayEvents_05), DEBUGSTRING("CAnimationHub::H0x00e40005_RelayEvents_05")}, + {0x00e40006, -1, CEntity::pEventHandler(&CAnimationHub:: +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +WaitChange),DEBUGSTRING("CAnimationHub::WaitChange")}, + {0x00e40007, -1, CEntity::pEventHandler(&CAnimationHub::H0x00e40007_WaitChange_01), DEBUGSTRING("CAnimationHub::H0x00e40007_WaitChange_01")}, + {0x00e40008, -1, CEntity::pEventHandler(&CAnimationHub::H0x00e40008_WaitChange_02), DEBUGSTRING("CAnimationHub::H0x00e40008_WaitChange_02")}, + {0x00e40009, -1, CEntity::pEventHandler(&CAnimationHub::H0x00e40009_WaitChange_03), DEBUGSTRING("CAnimationHub::H0x00e40009_WaitChange_03")}, + {0x00e4000a, -1, CEntity::pEventHandler(&CAnimationHub::H0x00e4000a_WaitChange_04), DEBUGSTRING("CAnimationHub::H0x00e4000a_WaitChange_04")}, + {1, -1, CEntity::pEventHandler(&CAnimationHub:: +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/AnimationHub.es" +Main),DEBUGSTRING("CAnimationHub::Main")}, +}; +#define CAnimationHub_handlersct ARRAYCOUNT(CAnimationHub_handlers) + +CEntity *CAnimationHub_New(void) { return new CAnimationHub; }; +void CAnimationHub_OnInitClass(void) {}; +void CAnimationHub_OnEndClass(void) {}; +void CAnimationHub_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CAnimationHub_OnWorldEnd(CWorld *pwo) {}; +void CAnimationHub_OnWorldInit(CWorld *pwo) {}; +void CAnimationHub_OnWorldTick(CWorld *pwo) {}; +void CAnimationHub_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CAnimationHub, CRationalEntity, "AnimationHub", "Thumbnails\\AnimationHub.tbn", 0x000000e4); +DECLARE_CTFILENAME(_fnmCAnimationHub_tbn, "Thumbnails\\AnimationHub.tbn"); diff --git a/Sources/EntitiesMP/AreaMarker.cpp b/Sources/EntitiesMP/AreaMarker.cpp new file mode 100644 index 0000000..1b09453 --- /dev/null +++ b/Sources/EntitiesMP/AreaMarker.cpp @@ -0,0 +1,47 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" + +#include "StdH.h" + +#include +#include +void CAreaMarker::SetDefaultProperties(void) { + m_strName = "AreaMarker"; + m_strDescription = ""; + m_boxArea = FLOATaabbox3D(FLOAT3D (0 , 0 , 0) , FLOAT3D (10 , 10 , 10)); + CEntity::SetDefaultProperties(); +} + +#line 24 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +void CAreaMarker::GetAreaBox(FLOATaabbox3D & box) { +#line 25 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +box = m_boxArea ; +#line 26 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +box += GetPlacement () . pl_PositionVector ; +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +return ; +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +} +BOOL CAreaMarker:: +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CAreaMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CAreaMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +InitAsEditorModel (); +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +SetModel (MODEL_AREAMARKER ); +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +SetModelMainTexture (TEXTURE_AREAMARKER ); +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/AreaMarker.es b/Sources/EntitiesMP/AreaMarker.es new file mode 100644 index 0000000..076898a --- /dev/null +++ b/Sources/EntitiesMP/AreaMarker.es @@ -0,0 +1,44 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +202 +%{ +#include "StdH.h" +%} + +class CAreaMarker: CEntity { +name "AreaMarker"; +thumbnail "Thumbnails\\AreaMarker.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "AreaMarker", + 2 CTString m_strDescription = "", + 3 FLOATaabbox3D m_boxArea "Area box" 'B' = FLOATaabbox3D(FLOAT3D(0,0,0), FLOAT3D(10,10,10)), + +components: + 1 model MODEL_AREAMARKER "Models\\Editor\\Axis.mdl", + 2 texture TEXTURE_AREAMARKER "Models\\Editor\\Vector.tex" + +functions: + + void GetAreaBox(FLOATaabbox3D &box) { + box = m_boxArea; + box +=GetPlacement().pl_PositionVector; + return; + } + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_AREAMARKER); + SetModelMainTexture(TEXTURE_AREAMARKER); + + return; + } +}; + diff --git a/Sources/EntitiesMP/AreaMarker.h b/Sources/EntitiesMP/AreaMarker.h new file mode 100644 index 0000000..05a5e9f --- /dev/null +++ b/Sources/EntitiesMP/AreaMarker.h @@ -0,0 +1,24 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_AreaMarker_INCLUDED +#define _EntitiesMP_AreaMarker_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CAreaMarker_DLLClass; +class CAreaMarker : public CEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + FLOATaabbox3D m_boxArea; + +#line 24 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +void GetAreaBox(FLOATaabbox3D & box); +#define STATE_CAreaMarker_Main 1 + BOOL +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_AreaMarker_INCLUDED diff --git a/Sources/EntitiesMP/AreaMarker_tables.h b/Sources/EntitiesMP/AreaMarker_tables.h new file mode 100644 index 0000000..f893917 --- /dev/null +++ b/Sources/EntitiesMP/AreaMarker_tables.h @@ -0,0 +1,38 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CAreaMarker + +CEntityProperty CAreaMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ca<<8)+1, offsetof(CAreaMarker, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ca<<8)+2, offsetof(CAreaMarker, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATAABBOX3D, NULL, (0x000000ca<<8)+3, offsetof(CAreaMarker, m_boxArea), "Area box", 'B', 0x7F0000FFUL, 0), +}; +#define CAreaMarker_propertiesct ARRAYCOUNT(CAreaMarker_properties) + +CEntityComponent CAreaMarker_components[] = { +#define MODEL_AREAMARKER ((0x000000ca<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_AREAMARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_AREAMARKER ((0x000000ca<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_AREAMARKER, "EFNM" "Models\\Editor\\Vector.tex"), +}; +#define CAreaMarker_componentsct ARRAYCOUNT(CAreaMarker_components) + +CEventHandlerEntry CAreaMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CAreaMarker:: +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/AreaMarker.es" +Main),DEBUGSTRING("CAreaMarker::Main")}, +}; +#define CAreaMarker_handlersct ARRAYCOUNT(CAreaMarker_handlers) + +CEntity *CAreaMarker_New(void) { return new CAreaMarker; }; +void CAreaMarker_OnInitClass(void) {}; +void CAreaMarker_OnEndClass(void) {}; +void CAreaMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CAreaMarker_OnWorldEnd(CWorld *pwo) {}; +void CAreaMarker_OnWorldInit(CWorld *pwo) {}; +void CAreaMarker_OnWorldTick(CWorld *pwo) {}; +void CAreaMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CAreaMarker, CEntity, "AreaMarker", "Thumbnails\\AreaMarker.tbn", 0x000000ca); +DECLARE_CTFILENAME(_fnmCAreaMarker_tbn, "Thumbnails\\AreaMarker.tbn"); diff --git a/Sources/EntitiesMP/ArmorItem.cpp b/Sources/EntitiesMP/ArmorItem.cpp new file mode 100644 index 0000000..1e50676 --- /dev/null +++ b/Sources/EntitiesMP/ArmorItem.cpp @@ -0,0 +1,372 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" + +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" + +#include +#include +CEntityEvent *EArmor::MakeCopy(void) { CEntityEvent *peeCopy = new EArmor(*this); return peeCopy;} +EArmor::EArmor() : CEntityEvent(EVENTCODE_EArmor) {; + ClearToDefault(fArmor); + ClearToDefault(bOverTopArmor); +}; +void CArmorItem::SetDefaultProperties(void) { + m_EaitType = ARIT_SHARD ; + m_bOverTopArmor = FALSE ; + m_iSoundComponent = 0; + CItem::SetDefaultProperties(); +} + +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +void CArmorItem::Precache(void) { +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +switch(m_EaitType ){ +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SHARD : PrecacheSound (SOUND_SHARD );break ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SMALL : PrecacheSound (SOUND_SMALL );break ; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_MEDIUM : PrecacheSound (SOUND_MEDIUM );break ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_STRONG : PrecacheSound (SOUND_STRONG );break ; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SUPER : PrecacheSound (SOUND_SUPER );break ; +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_HELM : PrecacheSound (SOUND_HELM );break ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +BOOL CArmorItem::FillEntityStatistics(EntityStats * pes) +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +{ +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +pes -> es_strName = "Armor"; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +pes -> es_ctCount = 1; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +pes -> es_ctAmmount = m_fValue ; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +pes -> es_fValue = m_fValue * 2; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +pes -> es_iScore = 0; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +switch(m_EaitType ){ +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SHARD : pes -> es_strName += " shard";break ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SMALL : pes -> es_strName += " small";break ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_MEDIUM : pes -> es_strName += " medium";break ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_STRONG : pes -> es_strName += " strong";break ; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SUPER : pes -> es_strName += " super";break ; +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_HELM : pes -> es_strName += " helm";break ; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +return TRUE ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +void CArmorItem::RenderParticles(void) { +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +if(GetRenderType () != CEntity :: RT_MODEL || GetSP () -> sp_gmGameMode > CSessionProperties :: GM_COOPERATIVE +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +|| ! ShowItemParticles ()) +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +{ +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +return ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +switch(m_EaitType ){ +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SHARD : +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Particles_Emanate (this , 0.75f * 0.75 , 0.75f * 0.75 , PT_STAR04 , 8 , 7.0f); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +break ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SMALL : +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Particles_Emanate (this , 1.0f * 0.75 , 1.0f * 0.75 , PT_STAR04 , 32 , 7.0f); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +break ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_MEDIUM : +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Particles_Emanate (this , 1.5f * 0.75 , 1.5f * 0.75 , PT_STAR04 , 64 , 7.0f); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +break ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_STRONG : +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Particles_Emanate (this , 2.0f * 0.75 , 1.25f * 0.75 , PT_STAR04 , 96 , 7.0f); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +break ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SUPER : +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Particles_Emanate (this , 2.5f * 0.75 , 1.5f * 0.75 , PT_STAR04 , 128 , 7.0f); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +break ; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_HELM : +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Particles_Emanate (this , 0.875f * 0.75 , 0.875f * 0.75 , PT_STAR04 , 16 , 7.0f); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +break ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} + +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +void CArmorItem::SetProperties(void) { +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +switch(m_EaitType ){ +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SHARD : +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_SMALL ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fValue = 1.0f; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_bOverTopArmor = TRUE ; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_strDescription . PrintF ("Shard - H:%g T:%g" , m_fValue , m_fRespawnTime ); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddItem (MODEL_1 , TEXTURE_1 , 0 , TEX_SPEC_MEDIUM , 0); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.4f , 0) , FLOAT3D (1.0 , 1.0 , 0.3f)); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +StretchItem (FLOAT3D (0.75f * 0.75 , 0.75f * 0.75 , 0.75f * 0.75)); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_iSoundComponent = SOUND_SHARD ; +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +break ; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SMALL : +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_MEDIUM ); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fValue = 25.0f; +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_bOverTopArmor = FALSE ; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_strDescription . PrintF ("Small - H:%g T:%g" , m_fValue , m_fRespawnTime ); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddItem (MODEL_25 , TEXTURE_25 , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.6f , 0) , FLOAT3D (2 , 2 , 0.5f)); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +StretchItem (FLOAT3D (2.0f , 2.0f , 2.0f)); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_iSoundComponent = SOUND_SMALL ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +break ; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_MEDIUM : { +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_MEDIUM ); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fValue = 50.0f; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_bOverTopArmor = FALSE ; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 25.0f; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_strDescription . PrintF ("Medium - H:%g T:%g" , m_fValue , m_fRespawnTime ); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddItem (MODEL_50 , TEXTURE_50 , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 1.0f , 0) , FLOAT3D (3 , 3 , 0.5f)); +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +StretchItem (FLOAT3D (2.0f , 2.0f , 2.0f)); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_iSoundComponent = SOUND_MEDIUM ; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +}break ; +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_STRONG : +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_MEDIUM ); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fValue = 100.0f; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_bOverTopArmor = FALSE ; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 60.0f; +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_strDescription . PrintF ("Strong - H:%g T:%g" , m_fValue , m_fRespawnTime ); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddItem (MODEL_100 , TEXTURE_100 , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.75f , 0) , FLOAT3D (3.5 , 3.5 , 1.0f)); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +StretchItem (FLOAT3D (2.5f , 2.5f , 2.5f)); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_iSoundComponent = SOUND_STRONG ; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +break ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SUPER : +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_MEDIUM ); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fValue = 200.0f; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_bOverTopArmor = TRUE ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 120.0f; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_strDescription . PrintF ("Super - H:%g T:%g" , m_fValue , m_fRespawnTime ); +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddItem (MODEL_200 , TEXTURE_200 , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.75f , 0) , FLOAT3D (3 , 3 , 1.0f)); +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +StretchItem (FLOAT3D (2.5f , 2.5f , 2.5f)); +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_iSoundComponent = SOUND_SUPER ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +break ; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_HELM : +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_SMALL ); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fValue = 5.0f; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_bOverTopArmor = FALSE ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_strDescription . PrintF ("Helm - H:%g T:%g" , m_fValue , m_fRespawnTime ); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddItem (MODEL_5 , TEXTURE_5 , 0 , TEX_SPEC_MEDIUM , 0); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.5f , 0) , FLOAT3D (1.5 , 1.5 , 0.4f)); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +StretchItem (FLOAT3D (0.875f * 0.75 , 0.875f * 0.75 , 0.875f * 0.75)); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_iSoundComponent = SOUND_HELM ; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +break ; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} + +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +void CArmorItem::AdjustDifficulty(void) +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +{ +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +if(! GetSP () -> sp_bAllowArmor && m_penTarget == NULL ){ +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Destroy (); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +BOOL CArmorItem:: +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +ItemCollected(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CArmorItem_ItemCollected + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EPass, "CArmorItem::ItemCollected expects 'EPass' as input!"); const EPass &epass = (const EPass &)__eeInput; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +ASSERT (epass . penOther != NULL ); +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +if(GetSP () -> sp_bHealthArmorStays && ! (m_bPickupOnce || m_bRespawn )){ +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +BOOL bWasPicked = MarkPickedBy (epass . penOther ); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +if(bWasPicked ){ +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Return(STATE_CURRENT,EVoid()); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +return TRUE; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +EArmor eArmor ; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +eArmor . fArmor = m_fValue ; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +eArmor . bOverTopArmor = m_bOverTopArmor ; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +if(epass . penOther -> ReceiveItem (eArmor )){ +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +if(_pNetwork -> IsPlayerLocal (epass . penOther )) +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +{ +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +switch(m_EaitType ) +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +{ +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SHARD : IFeel_PlayEffect ("PU_ArmourShard");break ; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SMALL : IFeel_PlayEffect ("PU_ArmourSmall");break ; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_MEDIUM : IFeel_PlayEffect ("PU_ArmourMedium");break ; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_STRONG : IFeel_PlayEffect ("PU_ArmourStrong");break ; +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_SUPER : IFeel_PlayEffect ("PU_ArmourSuper");break ; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +case ARIT_HELM : IFeel_PlayEffect ("PU_ArmourHelm");break ; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_soPick . Set3DParameters (50.0f , 1.0f , 1.0f , 1.0f); +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +PlaySound (m_soPick , m_iSoundComponent , SOF_3D ); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +m_fPickSoundLen = GetSoundLength (m_iSoundComponent ); +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +if(! GetSP () -> sp_bHealthArmorStays || (m_bPickupOnce || m_bRespawn )){ +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemReceived, FALSE, EVoid());return TRUE; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +} +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Return(STATE_CURRENT,EVoid()); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CArmorItem:: +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CArmorItem_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CArmorItem::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Initialize (); +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +SetProperties (); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ArmorItem.es b/Sources/EntitiesMP/ArmorItem.es new file mode 100644 index 0000000..b0c1db0 --- /dev/null +++ b/Sources/EntitiesMP/ArmorItem.es @@ -0,0 +1,280 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +804 +%{ +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" +%} + +uses "EntitiesMP/Item"; + +// health type +enum ArmorItemType { + 0 ARIT_SHARD "Shard", // shard + 1 ARIT_SMALL "Small", // small armor + 2 ARIT_MEDIUM "Medium", // medium armor + 3 ARIT_STRONG "Strong", // strong armor + 4 ARIT_SUPER "Super", // super armor + 5 ARIT_HELM "Helm", // helm +}; + +// event for sending through receive item +event EArmor { + FLOAT fArmor, // armor to receive + BOOL bOverTopArmor, // can be received over top armor +}; + +class CArmorItem : CItem { +name "Armor Item"; +thumbnail "Thumbnails\\ArmorItem.tbn"; + +properties: + 1 enum ArmorItemType m_EaitType "Type" 'Y' = ARIT_SHARD, // armor type + 2 BOOL m_bOverTopArmor = FALSE, // can be received over top armor + 3 INDEX m_iSoundComponent = 0, + +components: + 0 class CLASS_BASE "Classes\\Item.ecl", + +// ********* SHARD ********* + 1 model MODEL_1 "Models\\Items\\Armor\\Armor_1.mdl", + 2 texture TEXTURE_1 "Models\\Items\\Armor\\Armor_1.tex", + +// ********* SMALL ARMOR ********* + 10 model MODEL_25 "Models\\Items\\Armor\\Armor_25.mdl", + 11 texture TEXTURE_25 "Models\\Items\\Armor\\Armor_25.tex", + +// ********* MEDIUM ARMOR ********* + 20 model MODEL_50 "Models\\Items\\Armor\\Armor_50.mdl", + 21 texture TEXTURE_50 "Models\\Items\\Armor\\Armor_50.tex", + +// ********* STRONG ARMOR ********* + 22 model MODEL_100 "Models\\Items\\Armor\\Armor_100.mdl", + 23 texture TEXTURE_100 "Models\\Items\\Armor\\Armor_100.tex", + +// ********* SUPER ARMOR ********* + 40 model MODEL_200 "Models\\Items\\Armor\\Armor_200.mdl", + 41 texture TEXTURE_200 "Models\\Items\\Armor\\Armor_200.tex", + +// ********* HELM ********* + 50 model MODEL_5 "ModelsMP\\Items\\Armor\\Armor_5.mdl", + 51 texture TEXTURE_5 "ModelsMP\\Items\\Armor\\Armor_5.tex", + +// ************** FLARE FOR EFFECT ************** +100 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex", +101 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl", + +// ************** REFLECTIONS ************** +200 texture TEX_REFL_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex", + +// ************** SPECULAR ************** +210 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex", + +// ************** SOUNDS ************** +301 sound SOUND_SHARD "Sounds\\Items\\ArmourShard.wav", +302 sound SOUND_SMALL "Sounds\\Items\\ArmourSmall.wav", +303 sound SOUND_MEDIUM "Sounds\\Items\\ArmourMedium.wav", +304 sound SOUND_STRONG "Sounds\\Items\\ArmourStrong.wav", +305 sound SOUND_SUPER "Sounds\\Items\\ArmourSuper.wav", +306 sound SOUND_HELM "SoundsMP\\Items\\ArmourHelm.wav", + +functions: + void Precache(void) { + switch (m_EaitType) { + case ARIT_SHARD: PrecacheSound(SOUND_SHARD ); break; + case ARIT_SMALL: PrecacheSound(SOUND_SMALL ); break; + case ARIT_MEDIUM: PrecacheSound(SOUND_MEDIUM); break; + case ARIT_STRONG: PrecacheSound(SOUND_STRONG); break; + case ARIT_SUPER: PrecacheSound(SOUND_SUPER ); break; + case ARIT_HELM: PrecacheSound(SOUND_HELM ); break; + } + } + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + pes->es_strName = "Armor"; + pes->es_ctCount = 1; + pes->es_ctAmmount = m_fValue; + pes->es_fValue = m_fValue*2; + pes->es_iScore = 0;//m_iScore; + switch (m_EaitType) { + case ARIT_SHARD: pes->es_strName+=" shard"; break; + case ARIT_SMALL: pes->es_strName+=" small"; break; + case ARIT_MEDIUM: pes->es_strName+=" medium"; break; + case ARIT_STRONG: pes->es_strName+=" strong"; break; + case ARIT_SUPER: pes->es_strName+=" super"; break; + case ARIT_HELM: pes->es_strName+=" helm"; break; + } + return TRUE; + } + + // render particles + void RenderParticles(void) { + // no particles when not existing or in DM modes + if (GetRenderType()!=CEntity::RT_MODEL || GetSP()->sp_gmGameMode>CSessionProperties::GM_COOPERATIVE + || !ShowItemParticles()) + { + return; + } + switch (m_EaitType) { + case ARIT_SHARD: + Particles_Emanate(this, 0.75f*0.75, 0.75f*0.75, PT_STAR04, 8, 7.0f); + break; + case ARIT_SMALL: + Particles_Emanate(this, 1.0f*0.75, 1.0f*0.75, PT_STAR04, 32, 7.0f); + break; + case ARIT_MEDIUM: + Particles_Emanate(this, 1.5f*0.75, 1.5f*0.75, PT_STAR04, 64, 7.0f); + break; + case ARIT_STRONG: + Particles_Emanate(this, 2.0f*0.75, 1.25f*0.75, PT_STAR04, 96, 7.0f); + break; + case ARIT_SUPER: + Particles_Emanate(this, 2.5f*0.75, 1.5f*0.75, PT_STAR04, 128, 7.0f); + break; + case ARIT_HELM: + Particles_Emanate(this, 0.875f*0.75, 0.875f*0.75, PT_STAR04, 16, 7.0f); + break; + } + } + + // set health properties depending on health type + void SetProperties(void) { + switch (m_EaitType) { + case ARIT_SHARD: + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_SMALL); + m_fValue = 1.0f; + m_bOverTopArmor = TRUE; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Shard - H:%g T:%g", m_fValue, m_fRespawnTime); + // set appearance + AddItem(MODEL_1, TEXTURE_1, 0, TEX_SPEC_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.4f,0), FLOAT3D(1.0,1.0,0.3f) ); + StretchItem(FLOAT3D(0.75f*0.75, 0.75f*0.75, 0.75f*0.75)); + m_iSoundComponent = SOUND_SHARD; + break; + case ARIT_SMALL: + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM); + m_fValue = 25.0f; + m_bOverTopArmor = FALSE; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Small - H:%g T:%g", m_fValue, m_fRespawnTime); + // set appearance + AddItem(MODEL_25, TEXTURE_25, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(2,2,0.5f) ); + StretchItem(FLOAT3D(2.0f, 2.0f, 2.0f)); + m_iSoundComponent = SOUND_SMALL; + break; + case ARIT_MEDIUM: { + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM); + m_fValue = 50.0f; + m_bOverTopArmor = FALSE; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 25.0f; + m_strDescription.PrintF("Medium - H:%g T:%g", m_fValue, m_fRespawnTime); + // set appearance + AddItem(MODEL_50, TEXTURE_50, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,1.0f,0), FLOAT3D(3,3,0.5f) ); + StretchItem(FLOAT3D(2.0f, 2.0f, 2.0f)); + m_iSoundComponent = SOUND_MEDIUM; + } break; + case ARIT_STRONG: + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM); + m_fValue = 100.0f; + m_bOverTopArmor = FALSE; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 60.0f; + m_strDescription.PrintF("Strong - H:%g T:%g", m_fValue, m_fRespawnTime); + // set appearance + AddItem(MODEL_100, TEXTURE_100, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(3.5,3.5,1.0f) ); + StretchItem(FLOAT3D(2.5f, 2.5f, 2.5f)); + m_iSoundComponent = SOUND_STRONG; + break; + case ARIT_SUPER: + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM); + m_fValue = 200.0f; + m_bOverTopArmor = TRUE; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 120.0f; + m_strDescription.PrintF("Super - H:%g T:%g", m_fValue, m_fRespawnTime); + // set appearance + + AddItem(MODEL_200, TEXTURE_200, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.75f,0), FLOAT3D(3,3,1.0f) ); + StretchItem(FLOAT3D(2.5f, 2.5f, 2.5f)); + m_iSoundComponent = SOUND_SUPER; + break; + case ARIT_HELM: + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_SMALL); + m_fValue = 5.0f; + m_bOverTopArmor = FALSE; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Helm - H:%g T:%g", m_fValue, m_fRespawnTime); + // set appearance + AddItem(MODEL_5, TEXTURE_5, 0, TEX_SPEC_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.5f,0), FLOAT3D(1.5,1.5,0.4f) ); + StretchItem(FLOAT3D(0.875f*0.75, 0.875f*0.75, 0.875f*0.75)); + m_iSoundComponent = SOUND_HELM; + break; + } + }; + + void AdjustDifficulty(void) + { + if (!GetSP()->sp_bAllowArmor && m_penTarget==NULL) { + Destroy(); + } + } + +procedures: + ItemCollected(EPass epass) : CItem::ItemCollected { + ASSERT(epass.penOther!=NULL); + + // if armor stays + if (GetSP()->sp_bHealthArmorStays && !(m_bPickupOnce||m_bRespawn)) { + // if already picked by this player + BOOL bWasPicked = MarkPickedBy(epass.penOther); + if (bWasPicked) { + // don't pick again + return; + } + } + + // send health to entity + EArmor eArmor; + eArmor.fArmor = m_fValue; + eArmor.bOverTopArmor = m_bOverTopArmor; + // if health is received + if (epass.penOther->ReceiveItem(eArmor)) { + + if(_pNetwork->IsPlayerLocal(epass.penOther)) + { + switch (m_EaitType) + { + case ARIT_SHARD: IFeel_PlayEffect("PU_ArmourShard"); break; + case ARIT_SMALL: IFeel_PlayEffect("PU_ArmourSmall"); break; + case ARIT_MEDIUM: IFeel_PlayEffect("PU_ArmourMedium"); break; + case ARIT_STRONG: IFeel_PlayEffect("PU_ArmourStrong"); break; + case ARIT_SUPER: IFeel_PlayEffect("PU_ArmourSuper"); break; + case ARIT_HELM: IFeel_PlayEffect("PU_ArmourHelm"); break; + } + } + + // play the pickup sound + m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f); + PlaySound(m_soPick, m_iSoundComponent, SOF_3D); + m_fPickSoundLen = GetSoundLength(m_iSoundComponent); + + if (!GetSP()->sp_bHealthArmorStays || (m_bPickupOnce||m_bRespawn)) { + jump CItem::ItemReceived(); + } + } + return; + }; + + Main() { + Initialize(); // initialize base class + StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + SetProperties(); // set properties + + jump CItem::ItemLoop(); + }; +}; diff --git a/Sources/EntitiesMP/ArmorItem.h b/Sources/EntitiesMP/ArmorItem.h new file mode 100644 index 0000000..1a74f02 --- /dev/null +++ b/Sources/EntitiesMP/ArmorItem.h @@ -0,0 +1,58 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ArmorItem_INCLUDED +#define _EntitiesMP_ArmorItem_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType ArmorItemType_enum; +enum ArmorItemType { + ARIT_SHARD = 0, + ARIT_SMALL = 1, + ARIT_MEDIUM = 2, + ARIT_STRONG = 3, + ARIT_SUPER = 4, + ARIT_HELM = 5, +}; +DECL_DLL inline void ClearToDefault(ArmorItemType &e) { e = (ArmorItemType)0; } ; +#define EVENTCODE_EArmor 0x03240000 +class DECL_DLL EArmor : public CEntityEvent { +public: +EArmor(); +CEntityEvent *MakeCopy(void); +FLOAT fArmor; +BOOL bOverTopArmor; +}; +DECL_DLL inline void ClearToDefault(EArmor &e) { e = EArmor(); } ; +extern "C" DECL_DLL CDLLEntityClass CArmorItem_DLLClass; +class CArmorItem : public CItem { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum ArmorItemType m_EaitType; + BOOL m_bOverTopArmor; + INDEX m_iSoundComponent; + +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +void Precache(void); + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +void RenderParticles(void); + +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +void SetProperties(void); + +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +void AdjustDifficulty(void); +#define STATE_CArmorItem_ItemCollected 0x03240001 + BOOL +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +ItemCollected(const CEntityEvent &__eeInput); +#define STATE_CArmorItem_Main 1 + BOOL +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ArmorItem_INCLUDED diff --git a/Sources/EntitiesMP/ArmorItem_tables.h b/Sources/EntitiesMP/ArmorItem_tables.h new file mode 100644 index 0000000..2fce97d --- /dev/null +++ b/Sources/EntitiesMP/ArmorItem_tables.h @@ -0,0 +1,92 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(ArmorItemType) + EP_ENUMVALUE(ARIT_SHARD, "Shard"), + EP_ENUMVALUE(ARIT_SMALL, "Small"), + EP_ENUMVALUE(ARIT_MEDIUM, "Medium"), + EP_ENUMVALUE(ARIT_STRONG, "Strong"), + EP_ENUMVALUE(ARIT_SUPER, "Super"), + EP_ENUMVALUE(ARIT_HELM, "Helm"), +EP_ENUMEND(ArmorItemType); + +#define ENTITYCLASS CArmorItem + +CEntityProperty CArmorItem_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &ArmorItemType_enum, (0x00000324<<8)+1, offsetof(CArmorItem, m_EaitType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000324<<8)+2, offsetof(CArmorItem, m_bOverTopArmor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000324<<8)+3, offsetof(CArmorItem, m_iSoundComponent), "", 0, 0, 0), +}; +#define CArmorItem_propertiesct ARRAYCOUNT(CArmorItem_properties) + +CEntityComponent CArmorItem_components[] = { +#define CLASS_BASE ((0x00000324<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\Item.ecl"), +#define MODEL_1 ((0x00000324<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_1, "EFNM" "Models\\Items\\Armor\\Armor_1.mdl"), +#define TEXTURE_1 ((0x00000324<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_1, "EFNM" "Models\\Items\\Armor\\Armor_1.tex"), +#define MODEL_25 ((0x00000324<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_25, "EFNM" "Models\\Items\\Armor\\Armor_25.mdl"), +#define TEXTURE_25 ((0x00000324<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_25, "EFNM" "Models\\Items\\Armor\\Armor_25.tex"), +#define MODEL_50 ((0x00000324<<8)+20) + CEntityComponent(ECT_MODEL, MODEL_50, "EFNM" "Models\\Items\\Armor\\Armor_50.mdl"), +#define TEXTURE_50 ((0x00000324<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_50, "EFNM" "Models\\Items\\Armor\\Armor_50.tex"), +#define MODEL_100 ((0x00000324<<8)+22) + CEntityComponent(ECT_MODEL, MODEL_100, "EFNM" "Models\\Items\\Armor\\Armor_100.mdl"), +#define TEXTURE_100 ((0x00000324<<8)+23) + CEntityComponent(ECT_TEXTURE, TEXTURE_100, "EFNM" "Models\\Items\\Armor\\Armor_100.tex"), +#define MODEL_200 ((0x00000324<<8)+40) + CEntityComponent(ECT_MODEL, MODEL_200, "EFNM" "Models\\Items\\Armor\\Armor_200.mdl"), +#define TEXTURE_200 ((0x00000324<<8)+41) + CEntityComponent(ECT_TEXTURE, TEXTURE_200, "EFNM" "Models\\Items\\Armor\\Armor_200.tex"), +#define MODEL_5 ((0x00000324<<8)+50) + CEntityComponent(ECT_MODEL, MODEL_5, "EFNM" "ModelsMP\\Items\\Armor\\Armor_5.mdl"), +#define TEXTURE_5 ((0x00000324<<8)+51) + CEntityComponent(ECT_TEXTURE, TEXTURE_5, "EFNM" "ModelsMP\\Items\\Armor\\Armor_5.tex"), +#define TEXTURE_FLARE ((0x00000324<<8)+100) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.tex"), +#define MODEL_FLARE ((0x00000324<<8)+101) + CEntityComponent(ECT_MODEL, MODEL_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.mdl"), +#define TEX_REFL_LIGHTMETAL01 ((0x00000324<<8)+200) + CEntityComponent(ECT_TEXTURE, TEX_REFL_LIGHTMETAL01, "EFNM" "Models\\ReflectionTextures\\LightMetal01.tex"), +#define TEX_SPEC_MEDIUM ((0x00000324<<8)+210) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_MEDIUM, "EFNM" "Models\\SpecularTextures\\Medium.tex"), +#define SOUND_SHARD ((0x00000324<<8)+301) + CEntityComponent(ECT_SOUND, SOUND_SHARD, "EFNM" "Sounds\\Items\\ArmourShard.wav"), +#define SOUND_SMALL ((0x00000324<<8)+302) + CEntityComponent(ECT_SOUND, SOUND_SMALL, "EFNM" "Sounds\\Items\\ArmourSmall.wav"), +#define SOUND_MEDIUM ((0x00000324<<8)+303) + CEntityComponent(ECT_SOUND, SOUND_MEDIUM, "EFNM" "Sounds\\Items\\ArmourMedium.wav"), +#define SOUND_STRONG ((0x00000324<<8)+304) + CEntityComponent(ECT_SOUND, SOUND_STRONG, "EFNM" "Sounds\\Items\\ArmourStrong.wav"), +#define SOUND_SUPER ((0x00000324<<8)+305) + CEntityComponent(ECT_SOUND, SOUND_SUPER, "EFNM" "Sounds\\Items\\ArmourSuper.wav"), +#define SOUND_HELM ((0x00000324<<8)+306) + CEntityComponent(ECT_SOUND, SOUND_HELM, "EFNM" "SoundsMP\\Items\\ArmourHelm.wav"), +}; +#define CArmorItem_componentsct ARRAYCOUNT(CArmorItem_components) + +CEventHandlerEntry CArmorItem_handlers[] = { + {0x03240001, STATE_CItem_ItemCollected, CEntity::pEventHandler(&CArmorItem:: +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +ItemCollected),DEBUGSTRING("CArmorItem::ItemCollected")}, + {1, -1, CEntity::pEventHandler(&CArmorItem:: +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/ArmorItem.es" +Main),DEBUGSTRING("CArmorItem::Main")}, +}; +#define CArmorItem_handlersct ARRAYCOUNT(CArmorItem_handlers) + +CEntity *CArmorItem_New(void) { return new CArmorItem; }; +void CArmorItem_OnInitClass(void) {}; +void CArmorItem_OnEndClass(void) {}; +void CArmorItem_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CArmorItem_OnWorldEnd(CWorld *pwo) {}; +void CArmorItem_OnWorldInit(CWorld *pwo) {}; +void CArmorItem_OnWorldTick(CWorld *pwo) {}; +void CArmorItem_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CArmorItem, CItem, "Armor Item", "Thumbnails\\ArmorItem.tbn", 0x00000324); +DECLARE_CTFILENAME(_fnmCArmorItem_tbn, "Thumbnails\\ArmorItem.tbn"); diff --git a/Sources/EntitiesMP/BackgroundViewer.cpp b/Sources/EntitiesMP/BackgroundViewer.cpp new file mode 100644 index 0000000..c7a3903 --- /dev/null +++ b/Sources/EntitiesMP/BackgroundViewer.cpp @@ -0,0 +1,87 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" + +#include "StdH.h" + +#include +#include +void CBackgroundViewer::SetDefaultProperties(void) { + m_bActive = TRUE ; + m_penWorldSettingsController = NULL; + CMarker::SetDefaultProperties(); +} + +#line 25 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +BOOL CBackgroundViewer::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 26 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +{ +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +if(penTarget == NULL ) +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +{ +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +return FALSE ; +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +} +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +if(slPropertyOffset == offsetof (CBackgroundViewer , m_penWorldSettingsController )) +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +{ +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +return IsOfClass (penTarget , "WorldSettingsController"); +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +} +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +return TRUE ; +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +} + +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +BOOL CBackgroundViewer::HandleEvent(const CEntityEvent & ee) { +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +if(ee . ee_slEvent == EVENTCODE_EStart ){ +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +GetWorld () -> SetBackgroundViewer (this ); +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +return TRUE ; +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +} +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +return FALSE ; +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +} +BOOL CBackgroundViewer:: +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBackgroundViewer_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBackgroundViewer::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +InitAsEditorModel (); +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +SetModel (MODEL_MARKER ); +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +if(m_strName == "Marker"){ +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +m_strName = "Background Viewer"; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +} +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +if(m_bActive ){ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +GetWorld () -> SetBackgroundViewer (this ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +} +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +Return(STATE_CURRENT,EVoid()); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/BackgroundViewer.es b/Sources/EntitiesMP/BackgroundViewer.es new file mode 100644 index 0000000..7d3b9f5 --- /dev/null +++ b/Sources/EntitiesMP/BackgroundViewer.es @@ -0,0 +1,70 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +211 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; + +class CBackgroundViewer: CMarker { +name "Background Viewer"; +thumbnail "Thumbnails\\BackgroundViewer.tbn"; +features "IsImportant"; + +properties: + 1 BOOL m_bActive "Active" 'A' =TRUE, // set if active at beginning of game + 2 CEntityPointer m_penWorldSettingsController "World settings controller" 'W', + +components: + 1 model MODEL_MARKER "Models\\Editor\\Axis.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex" + +functions: + // Validate offered target for one property + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if(penTarget==NULL) + { + return FALSE; + } + // if gradient marker + if( slPropertyOffset==offsetof(CBackgroundViewer, m_penWorldSettingsController)) + { + return IsOfClass(penTarget, "WorldSettingsController"); + } + return TRUE; + } + + BOOL HandleEvent(const CEntityEvent &ee) { + if (ee.ee_slEvent == EVENTCODE_EStart) { + GetWorld()->SetBackgroundViewer(this); + return TRUE; + } + + return FALSE; + }; + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + // set name + if (m_strName=="Marker") { + m_strName = "Background Viewer"; + } + + if (m_bActive) { + GetWorld()->SetBackgroundViewer(this); + } + return; + } +}; + diff --git a/Sources/EntitiesMP/BackgroundViewer.h b/Sources/EntitiesMP/BackgroundViewer.h new file mode 100644 index 0000000..28d079b --- /dev/null +++ b/Sources/EntitiesMP/BackgroundViewer.h @@ -0,0 +1,26 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_BackgroundViewer_INCLUDED +#define _EntitiesMP_BackgroundViewer_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CBackgroundViewer_DLLClass; +class CBackgroundViewer : public CMarker { +public: +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bActive; + CEntityPointer m_penWorldSettingsController; + +#line 25 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CBackgroundViewer_Main 1 + BOOL +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_BackgroundViewer_INCLUDED diff --git a/Sources/EntitiesMP/BackgroundViewer_tables.h b/Sources/EntitiesMP/BackgroundViewer_tables.h new file mode 100644 index 0000000..dd0336d --- /dev/null +++ b/Sources/EntitiesMP/BackgroundViewer_tables.h @@ -0,0 +1,37 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CBackgroundViewer + +CEntityProperty CBackgroundViewer_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d3<<8)+1, offsetof(CBackgroundViewer, m_bActive), "Active", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d3<<8)+2, offsetof(CBackgroundViewer, m_penWorldSettingsController), "World settings controller", 'W', 0x7F0000FFUL, 0), +}; +#define CBackgroundViewer_propertiesct ARRAYCOUNT(CBackgroundViewer_properties) + +CEntityComponent CBackgroundViewer_components[] = { +#define MODEL_MARKER ((0x000000d3<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_MARKER ((0x000000d3<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Vector.tex"), +}; +#define CBackgroundViewer_componentsct ARRAYCOUNT(CBackgroundViewer_components) + +CEventHandlerEntry CBackgroundViewer_handlers[] = { + {1, -1, CEntity::pEventHandler(&CBackgroundViewer:: +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/BackgroundViewer.es" +Main),DEBUGSTRING("CBackgroundViewer::Main")}, +}; +#define CBackgroundViewer_handlersct ARRAYCOUNT(CBackgroundViewer_handlers) + +CEntity *CBackgroundViewer_New(void) { return new CBackgroundViewer; }; +void CBackgroundViewer_OnInitClass(void) {}; +void CBackgroundViewer_OnEndClass(void) {}; +void CBackgroundViewer_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CBackgroundViewer_OnWorldEnd(CWorld *pwo) {}; +void CBackgroundViewer_OnWorldInit(CWorld *pwo) {}; +void CBackgroundViewer_OnWorldTick(CWorld *pwo) {}; +void CBackgroundViewer_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CBackgroundViewer, CMarker, "Background Viewer", "Thumbnails\\BackgroundViewer.tbn", 0x000000d3); +DECLARE_CTFILENAME(_fnmCBackgroundViewer_tbn, "Thumbnails\\BackgroundViewer.tbn"); diff --git a/Sources/EntitiesMP/BasicEffects.cpp b/Sources/EntitiesMP/BasicEffects.cpp new file mode 100644 index 0000000..58a3b57 --- /dev/null +++ b/Sources/EntitiesMP/BasicEffects.cpp @@ -0,0 +1,2184 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" + +#include "StdH.h" +#include "Models/Effects/Teleport01/Teleport.h" +#include "Models/Effects/ExplosionGrenade/ExplosionGrenade.h" +#include "Models/Effects/ShockWave01/ShockWave.h" +#include "Models/Effects/BloodOnTheWall01/Blood.h" +#include "EntitiesMP/MovingBrush.h" + +#define EXPLOSION_GRENADE_TEXTURE_ANIM_FAST 0 +#define EXPLOSION_GRENADE_TEXTURE_ANIM_MEDIUM 1 +#define EXPLOSION_GRENADE_TEXTURE_ANIM_SLOW 2 + +#define SHOCKWAVE_TEXTURE_ANIM_FAST 0 +#define SHOCKWAVE_TEXTURE_ANIM_MEDIUM 1 +#define SHOCKWAVE_TEXTURE_ANIM_SLOW 2 + +#include +#include +CEntityEvent *ESpawnEffect::MakeCopy(void) { CEntityEvent *peeCopy = new ESpawnEffect(*this); return peeCopy;} +ESpawnEffect::ESpawnEffect() : CEntityEvent(EVENTCODE_ESpawnEffect) {; + ClearToDefault(betType); + ClearToDefault(vNormal); + ClearToDefault(vDirection); + ClearToDefault(vStretch); + ClearToDefault(colMuliplier); +}; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" + +void CBasicEffect_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + switch ((BasicEffectType)iUser) { + case BET_ROCKET: + case BET_ROCKET_PLANE: + pdec->PrecacheSound(SOUND_EXPLOSION); + pdec->PrecacheModel(MDL_ROCKET_EXPLOSION); + pdec->PrecacheTexture(TXT_ROCKET_EXPLOSION); + pdec->PrecacheModel(MDL_PARTICLES_EXPLOSION); + pdec->PrecacheTexture(TXT_PARTICLES_EXPLOSION); + pdec->PrecacheModel(MDL_ROCKET3D_EXPLOSION); + pdec->PrecacheTexture(TXT_ROCKET_EXPLOSION); + pdec->PrecacheModel(MDL_PARTICLES3D_EXPLOSION); + pdec->PrecacheTexture(TXT_PARTICLES_EXPLOSION); + break; + case BET_BOMB: + case BET_GRENADE: + case BET_GRENADE_PLANE: + pdec->PrecacheSound(SOUND_EXPLOSION); + pdec->PrecacheModel(MDL_GRENADE_EXPLOSION); + pdec->PrecacheTexture(TXT_GRENADE_EXPLOSION); + pdec->PrecacheModel(MDL_PARTICLES_EXPLOSION); + pdec->PrecacheTexture(TXT_PARTICLES_EXPLOSION); + pdec->PrecacheModel(MDL_GRENADE3D_EXPLOSION); + pdec->PrecacheTexture(TXT_GRENADE_EXPLOSION); + pdec->PrecacheModel(MDL_PARTICLES3D_EXPLOSION); + pdec->PrecacheTexture(TXT_PARTICLES_EXPLOSION); + break; + case BET_CANNON: + case BET_CANNON_NOLIGHT: + case BET_LIGHT_CANNON: + case BET_CANNON_PLANE: + case BET_CANNONSHOCKWAVE: + pdec->PrecacheSound(SOUND_EXPLOSION); + pdec->PrecacheModel(MDL_CANNON_EXPLOSION); + pdec->PrecacheTexture(TXT_CANNON_EXPLOSION); + pdec->PrecacheModel(MDL_CANNON3D_EXPLOSION); + pdec->PrecacheTexture(TXT_CANNON_EXPLOSION); + pdec->PrecacheModel(MODEL_CANNONSHOCKWAVE); + pdec->PrecacheTexture(TEXTURE_CANNONSHOCKWAVE); + break; + case BET_EXPLOSIONSTAIN: + pdec->PrecacheModel(MODEL_EXPLOSION_STAIN); + pdec->PrecacheTexture(TEXTURE_EXPLOSION_STAIN); + break; + case BET_CANNONEXPLOSIONSTAIN: + pdec->PrecacheModel(MODEL_CANNON_EXPLOSION_STAIN); + pdec->PrecacheTexture(TEXTURE_CANNON_EXPLOSION_STAIN); + break; + case BET_SHOCKWAVE: + pdec->PrecacheModel(MODEL_SHOCKWAVE); + pdec->PrecacheTexture(TEXTURE_SHOCKWAVE); + break; + case BET_LASERWAVE: + pdec->PrecacheModel(MODEL_LASERWAVE); + pdec->PrecacheTexture(TEXTURE_LASERWAVE); + break; + case BET_BULLETSTAINSTONE: + case BET_BULLETSTAINSAND: + case BET_BULLETSTAINREDSAND: + case BET_BULLETSTAINWATER: + case BET_BULLETSTAINUNDERWATER: + case BET_BULLETSTAINSTONENOSOUND: + case BET_BULLETSTAINSANDNOSOUND: + case BET_BULLETSTAINREDSANDNOSOUND: + case BET_BULLETSTAINWATERNOSOUND: + case BET_BULLETSTAINUNDERWATERNOSOUND: + case BET_BULLETSTAINGRASS: + case BET_BULLETSTAINWOOD: + case BET_BULLETSTAINGRASSNOSOUND: + case BET_BULLETSTAINWOODNOSOUND: + case BET_BULLETSTAINSNOW: + case BET_BULLETSTAINSNOWNOSOUND: + pdec->PrecacheModel(MODEL_BULLET_HIT); + pdec->PrecacheTexture(TEXTURE_BULLET_HIT); + pdec->PrecacheTexture(TEXTURE_BULLET_SAND); + pdec->PrecacheModel(MODEL_SHOCKWAVE); + pdec->PrecacheTexture(TEXTURE_WATER_WAVE); + pdec->PrecacheSound(SOUND_BULLET_STONE); + pdec->PrecacheSound(SOUND_BULLET_SAND); + pdec->PrecacheSound(SOUND_BULLET_WATER); + pdec->PrecacheModel(MODEL_BULLET_STAIN); + pdec->PrecacheTexture(TEXTURE_BULLET_STAIN); + pdec->PrecacheSound(SOUND_BULLET_GRASS); + pdec->PrecacheSound(SOUND_BULLET_WOOD); + pdec->PrecacheSound(SOUND_BULLET_SNOW); + break; + case BET_BULLETTRAIL: + pdec->PrecacheModel(MODEL_BULLET_TRAIL); + pdec->PrecacheTexture(TEXTURE_BULLET_TRAIL); + break; + case BET_GIZMO_SPLASH_FX: + pdec->PrecacheModel(MODEL_BULLET_HIT); + pdec->PrecacheTexture(TEXTURE_BULLET_HIT); + pdec->PrecacheSound(SOUND_GIZMO_SPLASH); + break; + case BET_BLOODEXPLODE: + pdec->PrecacheModel(MODEL_BLOOD_EXPLODE); + pdec->PrecacheTexture(TEXTURE_BLOOD_EXPLODE); + pdec->PrecacheSound(SOUND_BULLET_FLESH); + break; + case BET_BLOODSTAIN: + case BET_BLOODSTAINGROW: + case BET_BLOODSPILL: + case BET_GIZMOSTAIN: + pdec->PrecacheModel(MODEL_BLOOD_STAIN); + pdec->PrecacheTexture(TEXTURE_BLOOD_STAIN1); + pdec->PrecacheTexture(TEXTURE_BLOOD_STAIN2); + pdec->PrecacheTexture(TEXTURE_BLOOD_STAIN3); + pdec->PrecacheTexture(TEXTURE_BLOOD_STAIN4); + pdec->PrecacheTexture(TEXTURE_BLOOD_SPILL1); + pdec->PrecacheTexture(TEXTURE_BLOOD_SPILL2); + pdec->PrecacheTexture(TEXTURE_BLOOD_SPILL3); + pdec->PrecacheTexture(TEXTURE_BLOOD_FLOWER1); + pdec->PrecacheTexture(TEXTURE_BLOOD_FLOWER2); + pdec->PrecacheTexture(TEXTURE_BLOOD_FLOWER3); + break; + case BET_TELEPORT: + pdec->PrecacheModel(MODEL_TELEPORT_EFFECT); + pdec->PrecacheTexture(TEXTURE_TELEPORT_EFFECT); + pdec->PrecacheSound(SOUND_TELEPORT); + break; + default: + ASSERT(FALSE); + } +} + +void CBasicEffect::SetDefaultProperties(void) { + m_betType = BET_NONE ; + m_fWaitTime = 0.0f; + m_fFadeTime = 0.0f; + m_bFade = FALSE ; + m_fFadeStartTime = 0.0f; + m_fFadeStartAlpha = 1.0f; + m_vNormal = FLOAT3D(0 , 0 , 0); + m_vStretch = FLOAT3D(0 , 0 , 0); + m_vDirection = FLOAT3D(0 , 0 , 0); + m_fDepthSortOffset = 0.0f; + m_fFadeInSpeed = 0.0f; + m_tmSpawn = 0.0f; + m_tmWaitAfterDeath = 0.0f; + m_bLightSource = FALSE ; + m_aoLightAnimation.SetData(NULL); + + m_iLightAnimation = -1; + m_colMultiplyColor = 0xFFFFFFFF; + m_soEffect.SetOwner(this); +m_soEffect.Stop_internal(); + m_fSoundTime = 0.0f; + m_eptType = EPT_NONE ; + m_tmWhenShot = 0.0f; + m_vGravity = FLOAT3D(0 , 0 , 0); + m_penPrediction = NULL; + CRationalEntity::SetDefaultProperties(); +} + void CBasicEffect::DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck) +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CRationalEntity :: DumpSync_t (strm , iExtensiveSyncCheck ); +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +strm . FPrintF_t ("Type: %d\n" , m_betType ); +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::Read_t(CTStream * istr) +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CRationalEntity :: Read_t (istr ); +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_bLightSource ){ +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetupLightSource (); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CLightSource * CBasicEffect::GetLightSource(void) +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_bLightSource && ! IsPredictor ()){ +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +return & m_lsLightSource ; +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +}else { +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +return NULL ; +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::SetupLightSource(void) +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_iLightAnimation >= 0) +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +try { +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_aoLightAnimation . SetData_t (CTFILENAME ("Animations\\BasicEffects.ani")); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +}catch (char * strError ){ +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +WarningMessage (TRANS ("Cannot load Animations\\BasicEffects.ani: %s") , strError ); +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_aoLightAnimation . PlayAnim (m_iLightAnimation , 0); +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CLightSource lsNew ; +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_ulFlags = LSF_NONPERSISTENT | LSF_DYNAMIC ; +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_rHotSpot = 0.0f; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +switch(m_betType ){ +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_ROCKET : +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_colColor = RGBToColor (100 , 100 , 100); +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_rHotSpot = 3.0f; +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_rFallOff = 12.5f; +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_plftLensFlare = NULL ; +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +break ; +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_GRENADE : +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_colColor = RGBToColor (200 , 200 , 200); +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_rFallOff = 12.5f; +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_plftLensFlare = NULL ; +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +break ; +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_CANNON : +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_LIGHT_CANNON : +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_colColor = RGBToColor (200 , 200 , 200); +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_rFallOff = 12.5f; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_plftLensFlare = NULL ; +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +break ; +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_LASERWAVE : +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_colColor = RGBToColor (0 , 64 , 0); +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_rFallOff = 1.5f; +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_plftLensFlare = NULL ; +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +break ; +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BOMB : +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_colColor = RGBToColor (100 , 100 , 100); +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_rFallOff = 8.0f; +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_plftLensFlare = NULL ; +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +break ; +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +default : +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ASSERTALWAYS ("Unknown light source"); +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_ubPolygonalMask = 0; +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_paoLightAnimation = NULL ; +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_paoLightAnimation = NULL ; +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +lsNew . ls_paoLightAnimation = & m_aoLightAnimation ; +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_lsLightSource . ls_penEntity = this ; +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::RenderParticles(void) +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_eptType != EPT_NONE ) +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT fStretch = 0.3f; +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Particles_BulletSpray (en_ulID , GetLerpedPlacement () . pl_PositionVector , m_vGravity , +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_eptType , m_tmSpawn , m_vStretch , fStretch ); +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_betType == BET_EXPLOSION_DEBRIS ) +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Particles_ExplosionDebris1 (this , m_tmSpawn , m_vStretch , m_colMultiplyColor ); +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Particles_ExplosionDebris2 (this , m_tmSpawn , m_vStretch , m_colMultiplyColor ); +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Particles_ExplosionDebris3 (this , m_tmSpawn , m_vStretch , m_colMultiplyColor ); +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_betType == BET_COLLECT_ENERGY ) +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Particles_CollectEnergy (this , m_tmSpawn , m_tmSpawn + m_fWaitTime ); +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_betType == BET_EXPLOSION_SMOKE && _pTimer -> GetLerpedCurrentTick () > (m_tmSpawn + m_fWaitTime )) +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Particles_ExplosionSmoke (this , m_tmSpawn + m_fWaitTime , m_vStretch , m_colMultiplyColor ); +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_betType == BET_SUMMONERSTAREXPLOSION ) +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Particles_SummonerExplode (this , GetPlacement () . pl_PositionVector , +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +60.0f , 1.0f , m_tmSpawn , m_fWaitTime ); +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_betType == BET_GROWING_SWIRL ) +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT fStretch = (m_vStretch (1) + m_vStretch (2) + m_vStretch (3)) / 3.0f; +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Particles_GrowingSwirl (this , fStretch , m_tmSpawn ); +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_betType == BET_DISAPPEAR_DUST ) +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT fStretch = (m_vStretch (1) + m_vStretch (2) + m_vStretch (3)) / 3.0f; +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Particles_DisappearDust (this , fStretch , m_tmSpawn ); +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_betType == BET_DUST_FALL ) +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Particles_DustFall (this , m_tmSpawn , m_vStretch ); +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +BOOL CBasicEffect::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_bFade ){ +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT m_fTimeRemain = m_fFadeStartTime + m_fFadeTime - _pTimer -> CurrentTick (); +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_fTimeRemain < 0.0f){m_fTimeRemain = 0.0f;} +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +COLOR col = GetModelColor () & ~ CT_AMASK ; +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +col |= (ULONG ) (m_fFadeStartAlpha * m_fTimeRemain / m_fFadeTime * 255.0f); +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelColor (col ); +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +}else if(m_fFadeInSpeed > 0){ +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +TIME tmAge = _pTimer -> GetLerpedCurrentTick () - m_tmSpawn ; +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +COLOR col = GetModelColor (); +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +col = (col & ~ CT_AMASK ) | +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +(ULONG ) ((255) * Clamp (tmAge * m_fFadeInSpeed / m_fWaitTime , 0.0f , 1.0f)); +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelColor (col ); +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +return FALSE ; +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT CBasicEffect::GetDepthSortOffset(void) +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +return m_fDepthSortOffset ; +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::SetNonLoopingTexAnims(void) +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject * pmo = GetModelObject (); +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +pmo -> mo_toTexture . PlayAnim (0 , 0); +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FOREACHINLIST (CAttachmentModelObject , amo_lnInMain , pmo -> mo_lhAttachments , itamo ){ +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject * pmoAtt = & itamo -> amo_moModelObject ; +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +pmoAtt -> mo_toTexture . PlayAnim (0 , 0); +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::SetNormalForHalfFaceForward(void) +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CPlacement3D pl = GetPlacement (); +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +UpVectorToAngles (m_vNormal , pl . pl_OrientationAngle ); +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPlacement (pl ); +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::SetNormal(void) +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CPlacement3D pl = GetPlacement (); +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +DirectionVectorToAngles (m_vNormal , pl . pl_OrientationAngle ); +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPlacement (pl ); +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::SetNormalWithRandomBanking(void) +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CPlacement3D pl = GetPlacement (); +#line 534 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +DirectionVectorToAngles (m_vNormal , pl . pl_OrientationAngle ); +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +pl . pl_OrientationAngle (3) = FRnd () * 360.0f; +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPlacement (pl ); +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::FindGravityVectorFromSector(void) +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CBrushSector * pbscContent = NULL ; +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{FOREACHSRCOFDST (en_rdSectors , CBrushSector , bsc_rsEntities , pbsc ) +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +pbscContent = & * pbsc ; +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +break ; +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ENDFOR ;} +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(pbscContent == NULL ) +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +return ; +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +INDEX iForceType = pbscContent -> GetForceType (); +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CEntity * penBrush = pbscContent -> bsc_pbmBrushMip -> bm_pbrBrush -> br_penEntity ; +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CForceStrength fsGravity ; +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CForceStrength fsField ; +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +penBrush -> GetForce (iForceType , en_plPlacement . pl_PositionVector , fsGravity , fsField ); +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vGravity = fsGravity . fs_vDirection ; +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::SetNormalAndDirection(void) +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_vDirection . Length () < 0.01f){ +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 565 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +return ; +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT3D vX ; +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT3D vY = - m_vDirection ; +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT3D vZ = - m_vNormal ; +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +vZ . Normalize (); +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +vX = vY * vZ ; +#line 573 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +vX . Normalize (); +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +vY = vZ * vX ; +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +vY . Normalize (); +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOATmatrix3D m ; +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m (1 , 1) = vX (1);m (1 , 2) = vY (1);m (1 , 3) = vZ (1); +#line 579 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m (2 , 1) = vX (2);m (2 , 2) = vY (2);m (2 , 3) = vZ (2); +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m (3 , 1) = vX (3);m (3 , 2) = vY (3);m (3 , 3) = vZ (3); +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CPlacement3D pl = GetPlacement (); +#line 583 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +DecomposeRotationMatrixNoSnap (pl . pl_OrientationAngle , m ); +#line 584 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPlacement (pl ); +#line 585 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::RandomBanking(void) +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 589 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CPlacement3D pl = GetPlacement (); +#line 590 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +pl . pl_OrientationAngle (3) = FRnd () * 360.0f; +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPlacement (pl ); +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::Stretch(void) { +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ASSERT (m_vStretch (1) > 0.01f && m_vStretch (3) > 0.01f && m_vStretch (3) > 0.01f); +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +GetModelObject () -> mo_Stretch = m_vStretch ; +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::ParentToNearestPolygonAndStretch(void) +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT3D vPoint ; +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOATplane3D plPlaneNormal ; +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT fDistanceToEdge ; +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CBrushPolygon * pbpoNearBrush = GetNearestPolygon (vPoint , plPlaneNormal , fDistanceToEdge ); +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if((m_betType >= BET_BULLETSTAINSTONE && m_betType <= BET_BULLETSTAINREDSANDNOSOUND ) || +#line 609 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +(m_betType >= BET_BULLETSTAINGRASS && m_betType <= BET_BULLETSTAINWOODNOSOUND ) || +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +(m_betType >= BET_BULLETSTAINSNOW && m_betType <= BET_BULLETSTAINSNOWNOSOUND )) +#line 611 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(pbpoNearBrush != NULL ) +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CBrushSector * pbscContent = pbpoNearBrush -> bpo_pbscSector ; +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +INDEX iForceType = pbscContent -> GetForceType (); +#line 616 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CEntity * penNearBrush = pbscContent -> bsc_pbmBrushMip -> bm_pbrBrush -> br_penEntity ; +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CForceStrength fsGravity ; +#line 618 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CForceStrength fsField ; +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +penNearBrush -> GetForce (iForceType , en_plPlacement . pl_PositionVector , fsGravity , fsField ); +#line 621 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vGravity = fsGravity . fs_vDirection ; +#line 622 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 623 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 626 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(pbpoNearBrush == NULL || (pbpoNearBrush -> bpo_ulFlags & BPOF_PORTAL ) +#line 627 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +|| (vPoint - GetPlacement () . pl_PositionVector ) . ManhattanNorm () > 0.1f * 3){ +#line 629 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SwitchToEditorModel (); +#line 631 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +}else { +#line 632 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CEntity * penNearBrush = pbpoNearBrush -> bpo_pbscSector -> bsc_pbmBrushMip -> bm_pbrBrush -> br_penEntity ; +#line 633 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOATaabbox3D box ; +#line 634 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +en_pmoModelObject -> GetCurrentFrameBBox (box ); +#line 635 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +box . StretchByVector (en_pmoModelObject -> mo_Stretch ); +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT fOrgSize = box . Size () . MaxNorm (); +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT fMaxSize = fDistanceToEdge * 2.0f; +#line 639 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(fMaxSize < fOrgSize * 0.25f){ +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SwitchToEditorModel (); +#line 643 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +}else { +#line 645 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT fStretch = fMaxSize / fOrgSize ; +#line 646 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +fStretch = ClampUp (fStretch , 1.0f); +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vStretch = en_pmoModelObject -> mo_Stretch * fStretch ; +#line 648 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ModelChangeNotify (); +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetParent (penNearBrush ); +#line 652 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 654 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::ProjectileExplosion(void) +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 664 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 665 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MDL_ROCKET_EXPLOSION ); +#line 666 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TXT_ROCKET_EXPLOSION ); +#line 667 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +AddAttachment (0 , MDL_PARTICLES_EXPLOSION , TXT_PARTICLES_EXPLOSION ); +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +RandomBanking (); +#line 669 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNonLoopingTexAnims (); +#line 670 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (150.0f , 3.0f , 1.0f , 1.0f); +#line 671 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_EXPLOSION , SOF_3D ); +#line 672 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_EXPLOSION ); +#line 673 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.95f; +#line 674 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = TRUE ; +#line 675 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_iLightAnimation = 0; +#line 676 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 678 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::ProjectilePlaneExplosion(void) { +#line 679 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 680 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 681 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MDL_ROCKET3D_EXPLOSION ); +#line 682 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TXT_ROCKET_EXPLOSION ); +#line 683 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +AddAttachment (0 , MDL_PARTICLES3D_EXPLOSION , TXT_PARTICLES_EXPLOSION ); +#line 684 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 685 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNonLoopingTexAnims (); +#line 686 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.95f; +#line 687 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 688 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 690 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BombExplosion(void) { +#line 691 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 692 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 693 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MDL_GRENADE_EXPLOSION ); +#line 694 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TXT_GRENADE_EXPLOSION ); +#line 695 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNonLoopingTexAnims (); +#line 696 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT fSizeFactor = m_vStretch . MaxNorm (); +#line 697 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (50.0f * fSizeFactor , 10.0f * fSizeFactor , 1.0f * fSizeFactor , 1.0f); +#line 698 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_EXPLOSION , SOF_3D ); +#line 699 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_EXPLOSION ); +#line 700 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.95f; +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = TRUE ; +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_iLightAnimation = 1; +#line 703 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 705 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::GizmoSplashFX(void) +#line 706 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 707 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 708 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_HIT ); +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_HIT ); +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (50.0f , 10.0f , 1.0f , 1.0f); +#line 711 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_GIZMO_SPLASH , SOF_3D ); +#line 712 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_GIZMO_SPLASH ); +#line 713 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.95f; +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::ExplosionDebris(void) +#line 718 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 719 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_HIT ); +#line 721 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_HIT ); +#line 722 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.95f; +#line 723 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 724 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 726 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::CollectEnergy(void) +#line 727 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 728 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 729 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_HIT ); +#line 730 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_HIT ); +#line 731 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 2; +#line 732 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 735 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::GrowingSwirl(void) +#line 736 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 737 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 738 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_HIT ); +#line 739 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_HIT ); +#line 740 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 10.0f; +#line 741 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 742 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 744 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::DisappearDust(void) +#line 745 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 746 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 747 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_HIT ); +#line 748 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_HIT ); +#line 749 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 10.0f; +#line 750 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 751 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 753 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::DustFall(void) +#line 754 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 755 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 756 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_HIT ); +#line 757 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_HIT ); +#line 758 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 10.0f; +#line 759 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 760 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::SniperResidue(void) +#line 763 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 766 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 767 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_HIT ); +#line 768 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_HIT ); +#line 769 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.05f; +#line 770 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 771 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 773 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::ExplosionSmoke(void) +#line 774 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 775 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 776 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_HIT ); +#line 777 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_HIT ); +#line 778 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.25f; +#line 779 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_tmWaitAfterDeath = 8.0f; +#line 780 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 781 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 783 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::GrenadeExplosion(void) { +#line 784 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 785 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 786 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MDL_GRENADE_EXPLOSION ); +#line 787 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TXT_GRENADE_EXPLOSION ); +#line 788 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +AddAttachment (0 , MDL_PARTICLES_EXPLOSION , TXT_PARTICLES_EXPLOSION ); +#line 789 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +RandomBanking (); +#line 790 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNonLoopingTexAnims (); +#line 791 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (150.0f , 3.0f , 1.0f , 1.0f); +#line 792 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_EXPLOSION , SOF_3D ); +#line 793 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_EXPLOSION ); +#line 794 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.95f; +#line 795 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = TRUE ; +#line 796 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_iLightAnimation = 1; +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 799 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::GrenadePlaneExplosion(void) { +#line 800 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 801 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 802 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MDL_GRENADE3D_EXPLOSION ); +#line 803 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TXT_GRENADE_EXPLOSION ); +#line 804 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +AddAttachment (0 , MDL_PARTICLES3D_EXPLOSION , TXT_PARTICLES_EXPLOSION ); +#line 805 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNonLoopingTexAnims (); +#line 806 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 807 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.95f; +#line 808 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 809 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 811 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::CannonExplosion(BOOL bLoVolume,BOOL bNoLight) { +#line 812 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 813 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 814 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MDL_CANNON_EXPLOSION ); +#line 815 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & moExplosion = * GetModelObject (); +#line 816 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TXT_CANNON_EXPLOSION ); +#line 817 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moExplosion . mo_colBlendColor = m_colMultiplyColor ; +#line 818 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moExplosion . mo_toTexture . PlayAnim (EXPLOSION_GRENADE_TEXTURE_ANIM_FAST , 0); +#line 819 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +RandomBanking (); +#line 820 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(bLoVolume ) +#line 821 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 822 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (150.0f , 3.0f , 0.5f , 1.0f); +#line 823 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 824 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +else +#line 825 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 826 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (150.0f , 3.0f , 1.0f , 1.0f); +#line 827 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 829 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_EXPLOSION , SOF_3D ); +#line 830 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_EXPLOSION ); +#line 831 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.8f; +#line 832 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(bNoLight ) +#line 833 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 834 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 835 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 836 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +else +#line 837 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 838 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = TRUE ; +#line 839 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_iLightAnimation = 1; +#line 840 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 841 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 843 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::CannonPlaneExplosion(void) { +#line 844 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 845 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 846 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MDL_CANNON3D_EXPLOSION ); +#line 847 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & moExplosion = * GetModelObject (); +#line 848 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TXT_CANNON_EXPLOSION ); +#line 849 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moExplosion . mo_toTexture . PlayAnim (EXPLOSION_GRENADE_TEXTURE_ANIM_FAST , 0); +#line 850 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 851 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 1.2f; +#line 852 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 853 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::Stain(void) { +#line 856 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_EXPLOSION_STAIN ); +#line 857 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_EXPLOSION_STAIN ); +#line 858 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 859 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 5.0f; +#line 860 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 2.5f; +#line 861 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 862 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 863 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 865 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::CannonStain(void) { +#line 866 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 867 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_CANNON_EXPLOSION_STAIN ); +#line 868 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_CANNON_EXPLOSION_STAIN ); +#line 869 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 5.0f; +#line 871 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 2.5f; +#line 872 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 873 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 874 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 881 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::ShockWave(void) { +#line 882 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 883 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_SHOCKWAVE ); +#line 884 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & moShockwave = * GetModelObject (); +#line 885 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moShockwave . PlayAnim (SHOCKWAVE_ANIM_FAST , 0); +#line 886 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_SHOCKWAVE ); +#line 887 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormal (); +#line 888 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNonLoopingTexAnims (); +#line 889 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.4f; +#line 890 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 0.1f; +#line 891 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 892 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 894 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::CannonShockWave(void) { +#line 895 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 896 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 897 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_CANNONSHOCKWAVE ); +#line 898 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & moShockwave = * GetModelObject (); +#line 899 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moShockwave . PlayAnim (SHOCKWAVE_ANIM_SLOW , 0); +#line 900 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_CANNONSHOCKWAVE ); +#line 901 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moShockwave . mo_toTexture . PlayAnim (SHOCKWAVE_TEXTURE_ANIM_SLOW , 0); +#line 902 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormal (); +#line 903 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 1.25f; +#line 904 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 0.25f; +#line 905 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 906 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 908 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::LaserWave(void) { +#line 909 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_LASERWAVE ); +#line 910 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +GetModelObject () -> StretchModel (FLOAT3D (0.75f , 0.75f , 0.75f)); +#line 911 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ModelChangeNotify (); +#line 912 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_LASERWAVE ); +#line 913 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 914 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNonLoopingTexAnims (); +#line 915 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.05f; +#line 916 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 0.25f; +#line 917 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = TRUE ; +#line 918 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 919 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 926 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::TeleportEffect(void) +#line 927 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 929 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 930 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_TELEPORT_EFFECT ); +#line 931 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & mo = * GetModelObject (); +#line 932 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_TELEPORT_EFFECT ); +#line 933 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +mo . PlayAnim (TELEPORT_ANIM_ACTIVATE , 0); +#line 934 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +RandomBanking (); +#line 935 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT fSize = m_vStretch . MaxNorm (); +#line 936 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (40.0f * fSize , 10.0f * fSize , 1.0f , 1.0f); +#line 937 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_TELEPORT , SOF_3D ); +#line 938 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_TELEPORT ); +#line 939 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.8f; +#line 940 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 941 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 946 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::SummonerStarExplosion() +#line 947 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 948 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 949 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_HIT ); +#line 950 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_HIT ); +#line 951 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 16.0f; +#line 952 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_tmWaitAfterDeath = 8.0f; +#line 953 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 954 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vStretch = FLOAT3D (1.0f , 1.0f , 1.0f); +#line 955 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 956 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 961 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BulletStainSand(BOOL bSound) +#line 962 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 963 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(bSound ) +#line 964 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 965 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (20.0f , 10.0f , 1.0f , 1.0f + FRnd () * 0.2f); +#line 966 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_BULLET_SAND , SOF_3D ); +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_BULLET_SAND ); +#line 968 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 970 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_STAIN ); +#line 971 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_SAND ); +#line 972 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & moHole = * GetModelObject (); +#line 973 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moHole . StretchModel (FLOAT3D (1.5f , 1.5f , 1.5f)); +#line 974 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ModelChangeNotify (); +#line 976 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 977 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 2.0f; +#line 978 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 2.0f; +#line 979 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 980 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_eptType = EPT_BULLET_SAND ; +#line 981 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT3D vTemp = m_vStretch ; +#line 982 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 983 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vStretch = vTemp ; +#line 984 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 986 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BulletStainRedSand(BOOL bSound) +#line 987 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 988 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(bSound ) +#line 989 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 990 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (20.0f , 10.0f , 1.0f , 1.0f + FRnd () * 0.2f); +#line 991 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_BULLET_SAND , SOF_3D ); +#line 992 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_BULLET_SAND ); +#line 993 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 995 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_STAIN ); +#line 996 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_SAND ); +#line 997 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & moHole = * GetModelObject (); +#line 998 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moHole . StretchModel (FLOAT3D (1.5f , 1.5f , 1.5f)); +#line 999 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ModelChangeNotify (); +#line 1000 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moHole . mo_colBlendColor = 0x805030FF; +#line 1002 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 1003 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 2.0f; +#line 1004 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 2.0f; +#line 1005 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1006 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_eptType = EPT_BULLET_RED_SAND ; +#line 1007 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT3D vTemp = m_vStretch ; +#line 1008 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 1009 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vStretch = vTemp ; +#line 1010 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 1012 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BulletStainStone(BOOL bSound,BOOL bSmoke) +#line 1013 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1014 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(bSound ) +#line 1015 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1016 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (20.0f , 10.0f , 1.0f , 1.0f + FRnd () * 0.2f); +#line 1017 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_BULLET_STONE , SOF_3D ); +#line 1018 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_BULLET_STONE ); +#line 1019 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1020 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_STAIN ); +#line 1021 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_STAIN ); +#line 1022 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 1023 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 2.0f; +#line 1024 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 2.0f; +#line 1025 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1026 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(bSmoke ) +#line 1027 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1028 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_eptType = EPT_BULLET_STONE ; +#line 1029 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1030 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +else +#line 1031 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1032 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_eptType = EPT_BULLET_UNDER_WATER ; +#line 1033 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1034 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT3D vTemp = m_vStretch ; +#line 1035 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 1036 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vStretch = vTemp ; +#line 1037 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 1039 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BulletStainWater(BOOL bSound) +#line 1040 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1041 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(bSound ) +#line 1042 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1043 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (20.0f , 10.0f , 1.0f , 1.0f + FRnd () * 0.2f); +#line 1044 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_BULLET_WATER , SOF_3D ); +#line 1045 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_BULLET_WATER ); +#line 1046 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1048 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_SHOCKWAVE ); +#line 1049 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_WATER_WAVE ); +#line 1050 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & moShockwave = * GetModelObject (); +#line 1051 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moShockwave . PlayAnim (SHOCKWAVE_ANIM_MEDIUM , 0); +#line 1052 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moShockwave . StretchModel (FLOAT3D (0.25f , 0.25f , 0.25f)); +#line 1053 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ModelChangeNotify (); +#line 1055 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 1056 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FindGravityVectorFromSector (); +#line 1057 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.5f; +#line 1058 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 0.5f; +#line 1059 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1060 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_tmWaitAfterDeath = 1.0f; +#line 1061 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_eptType = EPT_BULLET_WATER ; +#line 1062 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 1064 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BulletTrail(void) { +#line 1065 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 1066 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_TRAIL ); +#line 1067 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_TRAIL ); +#line 1068 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & mo = * GetModelObject (); +#line 1069 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +mo . mo_colBlendColor = m_colMultiplyColor ; +#line 1070 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalForHalfFaceForward (); +#line 1071 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.1f; +#line 1072 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1073 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 1075 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BulletStainGrass(BOOL bSound) { +#line 1076 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(bSound ) +#line 1077 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1078 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (20.0f , 10.0f , 1.0f , 1.0f + FRnd () * 0.2f); +#line 1079 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_BULLET_GRASS , SOF_3D ); +#line 1080 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_BULLET_GRASS ); +#line 1081 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1083 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_STAIN ); +#line 1084 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_STAIN ); +#line 1085 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & moHole = * GetModelObject (); +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moHole . StretchModel (FLOAT3D (1.5f , 1.5f , 1.5f)); +#line 1087 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ModelChangeNotify (); +#line 1088 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moHole . mo_colBlendColor = 0x80f080FF; +#line 1090 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 1091 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 2.0f; +#line 1092 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 2.0f; +#line 1093 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1094 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_eptType = EPT_BULLET_GRASS ; +#line 1095 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT3D vTemp = m_vStretch ; +#line 1096 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 1097 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vStretch = vTemp ; +#line 1098 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 1100 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BulletStainWood(BOOL bSound) { +#line 1101 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(bSound ) +#line 1102 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1103 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (20.0f , 10.0f , 1.0f , 1.0f + FRnd () * 0.2f); +#line 1104 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_BULLET_WOOD , SOF_3D ); +#line 1105 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_BULLET_WOOD ); +#line 1106 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1108 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_STAIN ); +#line 1109 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_STAIN ); +#line 1110 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & moHole = * GetModelObject (); +#line 1111 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moHole . StretchModel (FLOAT3D (1.5f , 1.5f , 1.5f)); +#line 1112 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ModelChangeNotify (); +#line 1113 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moHole . mo_colBlendColor = 0xffc080FF; +#line 1115 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 1116 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 2.0f; +#line 1117 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 2.0f; +#line 1118 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1119 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_eptType = EPT_BULLET_WOOD ; +#line 1120 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT3D vTemp = m_vStretch ; +#line 1121 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 1122 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vStretch = vTemp ; +#line 1123 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 1125 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BulletStainSnow(BOOL bSound) { +#line 1126 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(bSound ) +#line 1127 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1128 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (20.0f , 10.0f , 1.0f , 1.0f + FRnd () * 0.2f); +#line 1129 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_BULLET_SNOW , SOF_3D ); +#line 1130 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_BULLET_SNOW ); +#line 1131 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1133 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BULLET_STAIN ); +#line 1134 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BULLET_STAIN ); +#line 1135 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & moHole = * GetModelObject (); +#line 1136 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moHole . StretchModel (FLOAT3D (1.5f , 1.5f , 1.5f)); +#line 1137 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ModelChangeNotify (); +#line 1138 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +moHole . mo_colBlendColor = 0x7f7f7fFF; +#line 1140 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalWithRandomBanking (); +#line 1141 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 2.0f; +#line 1142 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 2.0f; +#line 1143 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1144 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_eptType = EPT_BULLET_SNOW ; +#line 1145 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT3D vTemp = m_vStretch ; +#line 1146 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 1147 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vStretch = vTemp ; +#line 1148 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 1156 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BloodExplode(void) +#line 1157 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1159 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +const INDEX iBloodType = GetSP () -> sp_iBlood ; +#line 1160 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType < 1){return ;} +#line 1162 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 1163 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 1164 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BLOOD_EXPLODE ); +#line 1165 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType == 3){ +#line 1167 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelColor (RGBAToColor (255 , 255 , 255 , 255)); +#line 1168 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +switch(IRnd () & 3){ +#line 1169 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 1: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER1 );break ;} +#line 1170 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 2: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER2 );break ;} +#line 1171 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 3: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER3 );break ;} +#line 1172 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +default :{SetModelMainTexture (TEXTURE_BLOOD_FLOWER1 );break ;} +#line 1173 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1174 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +}else { +#line 1175 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BLOOD_EXPLODE ); +#line 1176 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType == 2){SetModelColor (RGBAToColor (250 , 20 , 20 , 255));} +#line 1177 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +else {SetModelColor (RGBAToColor (0 , 250 , 0 , 255));} +#line 1178 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1180 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_soEffect . Set3DParameters (7.5f , 5.0f , 1.0f , 1.0f); +#line 1181 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +PlaySound (m_soEffect , SOUND_BULLET_FLESH , SOF_3D ); +#line 1182 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fSoundTime = GetSoundLength (SOUND_BULLET_FLESH ); +#line 1183 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 0.25f; +#line 1184 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 0.75f; +#line 1185 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1186 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 1190 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BloodStain(void) +#line 1191 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1193 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +const INDEX iBloodType = GetSP () -> sp_iBlood ; +#line 1194 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType < 1){return ;} +#line 1196 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 1197 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BLOOD_STAIN ); +#line 1198 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType == 3){ +#line 1200 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelColor (RGBAToColor (255 , 255 , 255 , 255)); +#line 1201 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +switch(IRnd () & 3){ +#line 1202 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 1: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER1 );break ;} +#line 1203 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 2: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER2 );break ;} +#line 1204 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 3: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER3 );break ;} +#line 1205 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +default :{SetModelMainTexture (TEXTURE_BLOOD_FLOWER1 );break ;} +#line 1206 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1207 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +}else { +#line 1208 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +switch(IRnd () & 3){ +#line 1209 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 1: {SetModelMainTexture (TEXTURE_BLOOD_STAIN1 );break ;} +#line 1210 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 2: {SetModelMainTexture (TEXTURE_BLOOD_STAIN2 );break ;} +#line 1211 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 3: {SetModelMainTexture (TEXTURE_BLOOD_STAIN3 );break ;} +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +default :{SetModelMainTexture (TEXTURE_BLOOD_STAIN4 );break ;} +#line 1213 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1214 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType == 2){SetModelColor (RGBAToColor (250 , 20 , 20 , 255));} +#line 1215 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +else {SetModelColor (RGBAToColor (0 , 250 , 0 , 255));} +#line 1216 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1218 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalAndDirection (); +#line 1219 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 12.0f + FRnd () * 3.0f; +#line 1220 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 3.0f; +#line 1221 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1222 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fDepthSortOffset = - 0.1f; +#line 1223 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 1224 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 1228 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BloodStainGrow(void) +#line 1229 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1231 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +const INDEX iBloodType = GetSP () -> sp_iBlood ; +#line 1232 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType < 1){return ;} +#line 1234 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPredictable (TRUE ); +#line 1235 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 1236 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BLOOD_STAIN ); +#line 1237 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType == 3){ +#line 1239 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelColor (RGBAToColor (255 , 255 , 255 , 255)); +#line 1240 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +switch(IRnd () & 3){ +#line 1241 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 1: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER1 );break ;} +#line 1242 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 2: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER2 );break ;} +#line 1243 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 3: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER3 );break ;} +#line 1244 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +default :{SetModelMainTexture (TEXTURE_BLOOD_FLOWER1 );break ;} +#line 1245 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +}else { +#line 1247 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelMainTexture (TEXTURE_BLOOD_STAIN4 ); +#line 1248 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType == 2){SetModelColor (RGBAToColor (250 , 20 , 20 , 255));} +#line 1249 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +else {SetModelColor (RGBAToColor (0 , 250 , 0 , 255));} +#line 1250 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1251 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalAndDirection (); +#line 1252 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1253 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fDepthSortOffset = - 0.1f; +#line 1254 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 1256 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 15.0f + FRnd () * 2.0f; +#line 1257 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 2.0f; +#line 1258 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeInSpeed = 4.0f; +#line 1259 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CModelObject & mo = * GetModelObject (); +#line 1260 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +mo . PlayAnim (BLOOD_ANIM_GROW , 0); +#line 1261 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 1265 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::GizmoStain(void) +#line 1266 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1268 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +const INDEX iBloodType = GetSP () -> sp_iBlood ; +#line 1269 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType < 1){return ;} +#line 1271 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 1272 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BLOOD_STAIN ); +#line 1273 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType == 3){ +#line 1275 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelColor (RGBAToColor (255 , 255 , 255 , 255)); +#line 1276 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +switch(IRnd () & 3){ +#line 1277 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 1: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER1 );break ;} +#line 1278 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 2: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER2 );break ;} +#line 1279 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 3: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER3 );break ;} +#line 1280 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +default :{SetModelMainTexture (TEXTURE_BLOOD_FLOWER1 );break ;} +#line 1281 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1282 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +}else { +#line 1283 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelColor (RGBAToColor (0 , 250 , 0 , 255)); +#line 1284 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +switch(IRnd () & 3){ +#line 1285 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 1: {SetModelMainTexture (TEXTURE_BLOOD_STAIN1 );break ;} +#line 1286 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 2: {SetModelMainTexture (TEXTURE_BLOOD_STAIN2 );break ;} +#line 1287 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 3: {SetModelMainTexture (TEXTURE_BLOOD_STAIN3 );break ;} +#line 1288 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +default :{SetModelMainTexture (TEXTURE_BLOOD_STAIN4 );break ;} +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1290 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1291 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalAndDirection (); +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 15.0f + FRnd () * 2.0f; +#line 1293 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 2.0f; +#line 1294 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1295 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fDepthSortOffset = - 0.1f; +#line 1296 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 1297 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} + +#line 1301 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CBasicEffect::BloodSpill(COLOR colBloodSpillColor) +#line 1302 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1304 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +const INDEX iBloodType = GetSP () -> sp_iBlood ; +#line 1305 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType < 1){return ;} +#line 1307 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Stretch (); +#line 1308 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModel (MODEL_BLOOD_STAIN ); +#line 1309 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType == 3){ +#line 1311 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelColor (RGBAToColor (255 , 255 , 255 , 255)); +#line 1312 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +switch(IRnd () & 3){ +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 1: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER1 );break ;} +#line 1314 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 2: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER2 );break ;} +#line 1315 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 3: {SetModelMainTexture (TEXTURE_BLOOD_FLOWER3 );break ;} +#line 1316 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +default :{SetModelMainTexture (TEXTURE_BLOOD_FLOWER1 );break ;} +#line 1317 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1318 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +}else { +#line 1319 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +switch(IRnd () % 5){ +#line 1320 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 1: {SetModelMainTexture (TEXTURE_BLOOD_SPILL1 );break ;} +#line 1321 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 2: {SetModelMainTexture (TEXTURE_BLOOD_SPILL2 );break ;} +#line 1322 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 3: {SetModelMainTexture (TEXTURE_BLOOD_SPILL1 );break ;} +#line 1323 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case 4: {SetModelMainTexture (TEXTURE_BLOOD_SPILL2 );break ;} +#line 1324 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +default :{SetModelMainTexture (TEXTURE_BLOOD_SPILL3 );break ;} +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1326 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(iBloodType == 2) +#line 1327 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1328 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetModelColor (colBloodSpillColor ); +#line 1329 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1330 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +else {SetModelColor (RGBAToColor (0 , 250 , 0 , 255));} +#line 1331 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1332 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetNormalAndDirection (); +#line 1333 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fWaitTime = 15.0f + FRnd () * 2.0f; +#line 1334 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeTime = 2.0f; +#line 1335 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bLightSource = FALSE ; +#line 1336 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ParentToNearestPolygonAndStretch (); +#line 1337 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +BOOL CBasicEffect:: +#line 1346 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBasicEffect_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_ESpawnEffect, "CBasicEffect::Main expects 'ESpawnEffect' as input!"); const ESpawnEffect &eSpawn = (const ESpawnEffect &)__eeInput; +#line 1348 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(eSpawn . betType == BET_GIZMO_SPLASH_FX || +#line 1349 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +eSpawn . betType == BET_EXPLOSION_DEBRIS || +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +eSpawn . betType == BET_EXPLOSION_SMOKE || +#line 1351 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +eSpawn . betType == BET_SUMMONERSTAREXPLOSION || +#line 1352 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +eSpawn . betType == BET_COLLECT_ENERGY || +#line 1353 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +eSpawn . betType == BET_GROWING_SWIRL || +#line 1354 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +eSpawn . betType == BET_DISAPPEAR_DUST || +#line 1356 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +eSpawn . betType == BET_DUST_FALL ) +#line 1357 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1358 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +InitAsEditorModel (); +#line 1359 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1360 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +else +#line 1361 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1362 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +InitAsModel (); +#line 1363 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1364 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 1365 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 1366 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_tmSpawn = _pTimer -> CurrentTick (); +#line 1370 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vNormal = eSpawn . vNormal ; +#line 1371 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vDirection = eSpawn . vDirection ; +#line 1372 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_vStretch = eSpawn . vStretch ; +#line 1373 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_betType = eSpawn . betType ; +#line 1374 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_colMultiplyColor = eSpawn . colMuliplier ; +#line 1376 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +switch(m_betType ){ +#line 1377 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_ROCKET : ProjectileExplosion ();break ; +#line 1378 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_ROCKET_PLANE : ProjectilePlaneExplosion ();break ; +#line 1379 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_GRENADE : GrenadeExplosion ();break ; +#line 1380 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_GRENADE_PLANE : GrenadePlaneExplosion ();break ; +#line 1381 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_EXPLOSIONSTAIN : Stain ();break ; +#line 1382 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_SHOCKWAVE : ShockWave ();break ; +#line 1383 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_LASERWAVE : LaserWave ();break ; +#line 1384 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETTRAIL : BulletTrail ();break ; +#line 1385 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINSAND : BulletStainSand (TRUE );break ; +#line 1386 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINREDSAND : BulletStainRedSand (TRUE );break ; +#line 1387 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINSTONE : BulletStainStone (TRUE , TRUE );break ; +#line 1388 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINWATER : BulletStainWater (TRUE );break ; +#line 1389 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINUNDERWATER : BulletStainStone (TRUE , FALSE );break ; +#line 1390 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINSANDNOSOUND : BulletStainSand (FALSE );break ; +#line 1391 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINREDSANDNOSOUND : BulletStainRedSand (FALSE );break ; +#line 1392 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINSTONENOSOUND : BulletStainStone (FALSE , TRUE );break ; +#line 1393 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINWATERNOSOUND : BulletStainWater (FALSE );break ; +#line 1394 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINUNDERWATERNOSOUND : BulletStainStone (FALSE , FALSE );break ; +#line 1395 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BLOODSPILL : BloodSpill (m_colMultiplyColor );break ; +#line 1396 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BLOODSTAIN : BloodStain ();break ; +#line 1397 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_GIZMOSTAIN : GizmoStain ();break ; +#line 1398 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BLOODSTAINGROW : BloodStainGrow ();break ; +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BLOODEXPLODE : BloodExplode ();break ; +#line 1400 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_CANNON : CannonExplosion (FALSE , FALSE );break ; +#line 1401 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_CANNON_NOLIGHT : CannonExplosion (TRUE , TRUE );break ; +#line 1402 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_LIGHT_CANNON : CannonExplosion (TRUE , FALSE );break ; +#line 1403 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_CANNON_PLANE : CannonPlaneExplosion ();break ; +#line 1404 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_CANNONEXPLOSIONSTAIN : CannonStain ();break ; +#line 1405 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_CANNONSHOCKWAVE : CannonShockWave ();break ; +#line 1406 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_TELEPORT : TeleportEffect ();break ; +#line 1407 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BOMB : BombExplosion ();break ; +#line 1408 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_GIZMO_SPLASH_FX : GizmoSplashFX ();break ; +#line 1409 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINGRASS : BulletStainGrass (TRUE );break ; +#line 1410 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINGRASSNOSOUND : BulletStainGrass (FALSE );break ; +#line 1411 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINWOOD : BulletStainWood (TRUE );break ; +#line 1412 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINWOODNOSOUND : BulletStainWood (FALSE );break ; +#line 1413 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_EXPLOSION_DEBRIS : ExplosionDebris ();break ; +#line 1414 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_COLLECT_ENERGY : CollectEnergy ();break ; +#line 1416 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_EXPLOSION_SMOKE : ExplosionSmoke ();break ; +#line 1417 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_SUMMONERSTAREXPLOSION : SummonerStarExplosion ();break ; +#line 1418 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_GROWING_SWIRL : GrowingSwirl ();break ; +#line 1419 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_DISAPPEAR_DUST : DisappearDust ();break ; +#line 1420 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_DUST_FALL : DustFall ();break ; +#line 1421 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINSNOW : BulletStainSnow (TRUE );break ; +#line 1422 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +case BET_BULLETSTAINSNOWNOSOUND : BulletStainSnow (FALSE );break ; +#line 1423 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +default : +#line 1424 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +ASSERTALWAYS ("Unknown effect type"); +#line 1425 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1428 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(m_bLightSource ){SetupLightSource ();} +#line 1430 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x02590001, FALSE, EBegin());return TRUE;}BOOL CBasicEffect::H0x02590001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02590001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +Call(STATE_CURRENT, STATE_CBasicEffect_EffectLoop, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EBrushDestroyed):{const EBrushDestroyed&e= (EBrushDestroyed&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x02590002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x02590002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x02590002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 1435 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +}return TRUE;}BOOL CBasicEffect::H0x02590002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02590002 + +#line 1438 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Destroy (); +#line 1439 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Return(STATE_CURRENT,EVoid()); +#line 1439 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CBasicEffect:: +#line 1444 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +EffectLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBasicEffect_EffectLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBasicEffect::EffectLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1447 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(!(m_fWaitTime > 0.0f)){ Jump(STATE_CURRENT,0x02590006, FALSE, EInternal());return TRUE;} +#line 1448 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetTimerAfter(m_fWaitTime ); +Jump(STATE_CURRENT, 0x02590004, FALSE, EBegin());return TRUE;}BOOL CBasicEffect::H0x02590004_EffectLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02590004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02590005, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBasicEffect::H0x02590005_EffectLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02590005 +;Jump(STATE_CURRENT,0x02590006, FALSE, EInternal());return TRUE;}BOOL CBasicEffect::H0x02590006_EffectLoop_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02590006 + +#line 1451 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(!(m_fFadeTime > 0.0f)){ Jump(STATE_CURRENT,0x02590009, FALSE, EInternal());return TRUE;} +#line 1452 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeStartTime = _pTimer -> CurrentTick (); +#line 1453 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_fFadeStartAlpha = ((GetModelColor () & CT_AMASK ) >> CT_ASHIFT ) / 255.0f; +#line 1454 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bFade = TRUE ; +#line 1455 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetTimerAfter(m_fFadeTime ); +Jump(STATE_CURRENT, 0x02590007, FALSE, EBegin());return TRUE;}BOOL CBasicEffect::H0x02590007_EffectLoop_04(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02590007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02590008, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBasicEffect::H0x02590008_EffectLoop_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02590008 +; +#line 1456 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +m_bFade = FALSE ;Jump(STATE_CURRENT,0x02590009, FALSE, EInternal());return TRUE;}BOOL CBasicEffect::H0x02590009_EffectLoop_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02590009 + +#line 1460 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(!(m_fSoundTime > m_fWaitTime + m_fFadeTime )){ Jump(STATE_CURRENT,0x0259000c, FALSE, EInternal());return TRUE;} +#line 1461 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SwitchToEditorModel (); +#line 1462 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetTimerAfter(m_fSoundTime - (m_fWaitTime + m_fFadeTime )); +Jump(STATE_CURRENT, 0x0259000a, FALSE, EBegin());return TRUE;}BOOL CBasicEffect::H0x0259000a_EffectLoop_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0259000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0259000b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBasicEffect::H0x0259000b_EffectLoop_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0259000b +;Jump(STATE_CURRENT,0x0259000c, FALSE, EInternal());return TRUE;}BOOL CBasicEffect::H0x0259000c_EffectLoop_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0259000c + +#line 1465 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(!(m_tmWaitAfterDeath > 0.0f)){ Jump(STATE_CURRENT,0x0259000f, FALSE, EInternal());return TRUE;} +#line 1466 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +if(en_RenderType != RT_EDITORMODEL ) +#line 1467 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +{ +#line 1468 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SwitchToEditorModel (); +#line 1469 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +} +#line 1470 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +SetTimerAfter(m_tmWaitAfterDeath ); +Jump(STATE_CURRENT, 0x0259000d, FALSE, EBegin());return TRUE;}BOOL CBasicEffect::H0x0259000d_EffectLoop_10(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0259000d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0259000e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBasicEffect::H0x0259000e_EffectLoop_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0259000e +;Jump(STATE_CURRENT,0x0259000f, FALSE, EInternal());return TRUE;}BOOL CBasicEffect::H0x0259000f_EffectLoop_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0259000f + +#line 1473 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Return(STATE_CURRENT,EReturn ()); +#line 1473 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/BasicEffects.es b/Sources/EntitiesMP/BasicEffects.es new file mode 100644 index 0000000..27d247c --- /dev/null +++ b/Sources/EntitiesMP/BasicEffects.es @@ -0,0 +1,1476 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +601 +%{ +#include "StdH.h" +#include "Models/Effects/Teleport01/Teleport.h" +#include "Models/Effects/ExplosionGrenade/ExplosionGrenade.h" +#include "Models/Effects/ShockWave01/ShockWave.h" +#include "Models/Effects/BloodOnTheWall01/Blood.h" +#include "EntitiesMP/MovingBrush.h" + +#define EXPLOSION_GRENADE_TEXTURE_ANIM_FAST 0 +#define EXPLOSION_GRENADE_TEXTURE_ANIM_MEDIUM 1 +#define EXPLOSION_GRENADE_TEXTURE_ANIM_SLOW 2 + +#define SHOCKWAVE_TEXTURE_ANIM_FAST 0 +#define SHOCKWAVE_TEXTURE_ANIM_MEDIUM 1 +#define SHOCKWAVE_TEXTURE_ANIM_SLOW 2 +%} + +uses "EntitiesMP/Light"; + +enum BasicEffectType { + 0 BET_NONE "None", // no effect (never spawned) + 1 BET_ROCKET "Rocket", // rocket explosion + 2 BET_ROCKET_PLANE "Rocket plane", // rocket explosion on plane + 3 BET_GRENADE "Grenade", // grenade explosion + 4 BET_GRENADE_PLANE "Grenade plane", // grenade explosion on plane + 5 BET_EXPLOSIONSTAIN "Explosionstain", // explosion stain on brush + 6 BET_SHOCKWAVE "Shockwave", // shock wave + 7 BET_LASERWAVE "Laserwave", // laser wave + 10 BET_BLOODSPILL "Blood spill", // blood spill from bullet exit wound + 11 BET_BLOODSTAIN "Blood stain", // blood stain + 19 BET_BLOODSTAINGROW "Blood staingrow", // blood stain which grows bigger + 12 BET_BLOODEXPLODE "Blood explode", // blood explosion at bullet entry wound + 13 BET_CANNON "Cannon", // cannon explosion + 14 BET_CANNON_PLANE "Cannon plane", // cannon explosion on plane + 15 BET_CANNONEXPLOSIONSTAIN "Cannon explosion stain", // cannon explosion stain on brush + 16 BET_CANNONSHOCKWAVE "Cannon shockwave", // cannon shock wave + 17 BET_TELEPORT "Teleport", // teleportation + 18 BET_BOMB "Bomb", // small bomb explosion + 20 BET_BULLETTRAIL "Bullet trail", // white trail where bullet has passed + 21 BET_GIZMO_SPLASH_FX "Gizmo splash fx", // gizmo splash fx + 22 BET_GIZMOSTAIN "Gizmo stain", // gizmo stain + 30 BET_BULLETSTAINSTONE "Bullet stain stone", // bullet stain with ricochet on stone + 31 BET_BULLETSTAINSAND "Bullet stain sand", // bullet stain with ricochet on sand + 32 BET_BULLETSTAINWATER "Bullet stain water", // bullet stain with ricochet on water surface + 33 BET_BULLETSTAINUNDERWATER "Bullet stain underwater", // bullet stain with ricochet on underwater surface + 34 BET_BULLETSTAINSTONENOSOUND "Bullet stain stonenosound", // bullet stain on stone with no sound + 35 BET_BULLETSTAINSANDNOSOUND "Bullet stain sandnosound", // bullet stain on sand with no sound + 36 BET_BULLETSTAINWATERNOSOUND "Bullet stain waternosound", // bullet stain on water surface with no sound + 37 BET_BULLETSTAINUNDERWATERNOSOUND "Bullet stain underwater no sound", // bullet stain on under water surface with no sound + 38 BET_BULLETSTAINREDSAND "Bullet stain red sand", // bullet stain with ricochet on red sand + 39 BET_BULLETSTAINREDSANDNOSOUND "Bullet stain red sand no sound", // bullet stain with ricochet on red sand without sound + 40 BET_LIGHT_CANNON "Light cannon", // cannon explosion with lo sound volume + 41 BET_CANNON_NOLIGHT "Cannon no light", // cannon explosion without light witn lo sound volume + 42 BET_BULLETSTAINGRASS "Bullet stain grass", // bullet stain with ricochet on grass + 43 BET_BULLETSTAINWOOD "Bullet stain wood", // bullet stain with ricochet on wood + 44 BET_BULLETSTAINGRASSNOSOUND "Bullet stain grass no sound", // bullet stain on grass with no sound + 45 BET_BULLETSTAINWOODNOSOUND "Bullet stain wood no sound", // bullet stain on wood with no sound + 46 BET_EXPLOSION_DEBRIS "Explosion debris", // debrises flying out of explosion + 47 BET_EXPLOSION_SMOKE "Explosion smoke", // smoke left behind explosion + 48 BET_SUMMONERSTAREXPLOSION "Summoner star explosion", // magic explosion of starts for summoner + 49 BET_COLLECT_ENERGY "Collect energy", + 50 BET_GROWING_SWIRL "Growing swirl", +// 51 BET_SNIPER_RESIDUE "Sniper Residue", // smoke left after firing sniper + 52 BET_DISAPPEAR_DUST "Disappear dust", + 53 BET_DUST_FALL "Dust fall", + 54 BET_BULLETSTAINSNOW "Bullet stain snow", + 55 BET_BULLETSTAINSNOWNOSOUND "Bullet stain snow", +}; + + +// input parameter for spwaning a basic effect +event ESpawnEffect { + enum BasicEffectType betType, // type of effect + FLOAT3D vNormal, // normal for orientative effects + FLOAT3D vDirection, // direction oriented effects + FLOAT3D vStretch, // stretch effect model + COLOR colMuliplier, // color multiplier +}; + +%{ +void CBasicEffect_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + switch ((BasicEffectType)iUser) { + case BET_ROCKET: + case BET_ROCKET_PLANE: + pdec->PrecacheSound(SOUND_EXPLOSION); + pdec->PrecacheModel(MDL_ROCKET_EXPLOSION); + pdec->PrecacheTexture(TXT_ROCKET_EXPLOSION); + pdec->PrecacheModel(MDL_PARTICLES_EXPLOSION); + pdec->PrecacheTexture(TXT_PARTICLES_EXPLOSION); + pdec->PrecacheModel(MDL_ROCKET3D_EXPLOSION); + pdec->PrecacheTexture(TXT_ROCKET_EXPLOSION); + pdec->PrecacheModel(MDL_PARTICLES3D_EXPLOSION); + pdec->PrecacheTexture(TXT_PARTICLES_EXPLOSION); + break; + case BET_BOMB: + case BET_GRENADE: + case BET_GRENADE_PLANE: + pdec->PrecacheSound(SOUND_EXPLOSION); + pdec->PrecacheModel(MDL_GRENADE_EXPLOSION); + pdec->PrecacheTexture(TXT_GRENADE_EXPLOSION); + pdec->PrecacheModel(MDL_PARTICLES_EXPLOSION); + pdec->PrecacheTexture(TXT_PARTICLES_EXPLOSION); + pdec->PrecacheModel(MDL_GRENADE3D_EXPLOSION); + pdec->PrecacheTexture(TXT_GRENADE_EXPLOSION); + pdec->PrecacheModel(MDL_PARTICLES3D_EXPLOSION); + pdec->PrecacheTexture(TXT_PARTICLES_EXPLOSION); + break; + case BET_CANNON: + case BET_CANNON_NOLIGHT: + case BET_LIGHT_CANNON: + case BET_CANNON_PLANE: + case BET_CANNONSHOCKWAVE: + pdec->PrecacheSound(SOUND_EXPLOSION); + pdec->PrecacheModel(MDL_CANNON_EXPLOSION); + pdec->PrecacheTexture(TXT_CANNON_EXPLOSION); + pdec->PrecacheModel(MDL_CANNON3D_EXPLOSION); + pdec->PrecacheTexture(TXT_CANNON_EXPLOSION); + pdec->PrecacheModel(MODEL_CANNONSHOCKWAVE); + pdec->PrecacheTexture(TEXTURE_CANNONSHOCKWAVE); + break; + case BET_EXPLOSIONSTAIN: + pdec->PrecacheModel(MODEL_EXPLOSION_STAIN); + pdec->PrecacheTexture(TEXTURE_EXPLOSION_STAIN); + break; + case BET_CANNONEXPLOSIONSTAIN: + pdec->PrecacheModel(MODEL_CANNON_EXPLOSION_STAIN); + pdec->PrecacheTexture(TEXTURE_CANNON_EXPLOSION_STAIN); + break; + case BET_SHOCKWAVE: + pdec->PrecacheModel(MODEL_SHOCKWAVE); + pdec->PrecacheTexture(TEXTURE_SHOCKWAVE); + break; + case BET_LASERWAVE: + pdec->PrecacheModel(MODEL_LASERWAVE); + pdec->PrecacheTexture(TEXTURE_LASERWAVE); + break; + case BET_BULLETSTAINSTONE: + case BET_BULLETSTAINSAND: + case BET_BULLETSTAINREDSAND: + case BET_BULLETSTAINWATER: + case BET_BULLETSTAINUNDERWATER: + case BET_BULLETSTAINSTONENOSOUND: + case BET_BULLETSTAINSANDNOSOUND: + case BET_BULLETSTAINREDSANDNOSOUND: + case BET_BULLETSTAINWATERNOSOUND: + case BET_BULLETSTAINUNDERWATERNOSOUND: + case BET_BULLETSTAINGRASS: + case BET_BULLETSTAINWOOD: + case BET_BULLETSTAINGRASSNOSOUND: + case BET_BULLETSTAINWOODNOSOUND: + case BET_BULLETSTAINSNOW: + case BET_BULLETSTAINSNOWNOSOUND: + pdec->PrecacheModel(MODEL_BULLET_HIT); + pdec->PrecacheTexture(TEXTURE_BULLET_HIT); + pdec->PrecacheTexture(TEXTURE_BULLET_SAND); + pdec->PrecacheModel(MODEL_SHOCKWAVE); + pdec->PrecacheTexture(TEXTURE_WATER_WAVE); + pdec->PrecacheSound(SOUND_BULLET_STONE); + pdec->PrecacheSound(SOUND_BULLET_SAND); + pdec->PrecacheSound(SOUND_BULLET_WATER); + pdec->PrecacheModel(MODEL_BULLET_STAIN); + pdec->PrecacheTexture(TEXTURE_BULLET_STAIN); + pdec->PrecacheSound(SOUND_BULLET_GRASS); + pdec->PrecacheSound(SOUND_BULLET_WOOD); + pdec->PrecacheSound(SOUND_BULLET_SNOW); + break; + case BET_BULLETTRAIL: + pdec->PrecacheModel(MODEL_BULLET_TRAIL); + pdec->PrecacheTexture(TEXTURE_BULLET_TRAIL); + break; + case BET_GIZMO_SPLASH_FX: + pdec->PrecacheModel(MODEL_BULLET_HIT); + pdec->PrecacheTexture(TEXTURE_BULLET_HIT); + pdec->PrecacheSound(SOUND_GIZMO_SPLASH); + break; + case BET_BLOODEXPLODE: + pdec->PrecacheModel(MODEL_BLOOD_EXPLODE); + pdec->PrecacheTexture(TEXTURE_BLOOD_EXPLODE); + pdec->PrecacheSound(SOUND_BULLET_FLESH); + break; + case BET_BLOODSTAIN: + case BET_BLOODSTAINGROW: + case BET_BLOODSPILL: + case BET_GIZMOSTAIN: + pdec->PrecacheModel(MODEL_BLOOD_STAIN); + pdec->PrecacheTexture(TEXTURE_BLOOD_STAIN1); + pdec->PrecacheTexture(TEXTURE_BLOOD_STAIN2); + pdec->PrecacheTexture(TEXTURE_BLOOD_STAIN3); + pdec->PrecacheTexture(TEXTURE_BLOOD_STAIN4); + pdec->PrecacheTexture(TEXTURE_BLOOD_SPILL1); + pdec->PrecacheTexture(TEXTURE_BLOOD_SPILL2); + pdec->PrecacheTexture(TEXTURE_BLOOD_SPILL3); + pdec->PrecacheTexture(TEXTURE_BLOOD_FLOWER1); + pdec->PrecacheTexture(TEXTURE_BLOOD_FLOWER2); + pdec->PrecacheTexture(TEXTURE_BLOOD_FLOWER3); + break; + case BET_TELEPORT: + pdec->PrecacheModel(MODEL_TELEPORT_EFFECT); + pdec->PrecacheTexture(TEXTURE_TELEPORT_EFFECT); + pdec->PrecacheSound(SOUND_TELEPORT); + break; + default: + ASSERT(FALSE); + } +} +%} + +class CBasicEffect : CRationalEntity { +name "BasicEffect"; +thumbnail ""; +features "ImplementsOnPrecache", "CanBePredictable"; + +properties: + 1 enum BasicEffectType m_betType = BET_NONE, // type of effect + 2 FLOAT m_fWaitTime = 0.0f, // wait time + 3 FLOAT m_fFadeTime = 0.0f, // fade away time + 4 BOOL m_bFade = FALSE, // fade is enabled + 5 FLOAT m_fFadeStartTime = 0.0f, // fade away start time + 9 FLOAT m_fFadeStartAlpha = 1.0f, // alpha value + 6 FLOAT3D m_vNormal = FLOAT3D(0,0,0), // normal for orientative effects + 7 FLOAT3D m_vStretch = FLOAT3D(0,0,0), // stretch effect + 8 FLOAT3D m_vDirection = FLOAT3D(0,0,0), // direction oriented effects + 10 FLOAT m_fDepthSortOffset = 0.0f, + 11 FLOAT m_fFadeInSpeed = 0.0f, + 12 FLOAT m_tmSpawn = 0.0f, // when it was spawned + 13 FLOAT m_tmWaitAfterDeath = 0.0f, // after death wait time + + 20 BOOL m_bLightSource = FALSE, // effect is also light source + 21 CAnimObject m_aoLightAnimation, // light animation object + 22 INDEX m_iLightAnimation = -1, // lignt animation index + 23 COLOR m_colMultiplyColor = 0xFFFFFFFF, // color multiplier + + 30 CSoundObject m_soEffect, // sound channel + 31 FLOAT m_fSoundTime = 0.0f, // wait for sound to end + + 40 enum EffectParticlesType m_eptType = EPT_NONE, // type of particle effect + 41 FLOAT m_tmWhenShot = 0.0f, // when entity was shot + 42 FLOAT3D m_vGravity = FLOAT3D(0,0,0), // simulated direction of gravity + +{ + CLightSource m_lsLightSource; +} + +components: + +// ********** PROJECTILE EXPLOSIONS ********** + 1 model MDL_ROCKET_EXPLOSION "Models\\Effects\\ExplosionRocket\\ExplosionRocket.mdl", + 2 model MDL_ROCKET3D_EXPLOSION "Models\\Effects\\ExplosionRocket\\ExplosionRocket3D.mdl", + 3 texture TXT_ROCKET_EXPLOSION "Models\\Effects\\Explosionrocket\\Texture.tex", + 4 model MDL_GRENADE_EXPLOSION "Models\\Effects\\ExplosionGrenade\\ExplosionGrenade.mdl", + 5 model MDL_GRENADE3D_EXPLOSION "Models\\Effects\\ExplosionGrenade\\ExplosionGrenade3D.mdl", + 6 texture TXT_GRENADE_EXPLOSION "Models\\Effects\\ExplosionGrenade\\Texture.tex", + 7 model MDL_PARTICLES_EXPLOSION "Models\\Effects\\ExplosionParticles\\Particles.mdl", + 8 model MDL_PARTICLES3D_EXPLOSION "Models\\Effects\\ExplosionParticles\\Particles3D.mdl", + 9 texture TXT_PARTICLES_EXPLOSION "Models\\Effects\\ExplosionParticles\\Texture.tex", + 10 sound SOUND_EXPLOSION "Sounds\\Weapons\\_Explosion02.wav", + 11 model MDL_CANNON_EXPLOSION "Models\\Effects\\ExplosionGrenade\\ExplosionGrenade.mdl", + 12 model MDL_CANNON3D_EXPLOSION "Models\\Effects\\ExplosionGrenade\\ExplosionGrenade3D.mdl", + 13 texture TXT_CANNON_EXPLOSION "Models\\Effects\\ExplosionGrenade\\Texture.tex", + +// ********** BULLET HIT ********** + 15 model MODEL_BULLET_HIT "Models\\Effects\\BulletParticles\\BulletParticles.mdl", + 16 texture TEXTURE_BULLET_HIT "Models\\Effects\\BulletParticles\\BulletParticles.tex", + 18 model MODEL_BULLET_STAIN "Models\\Effects\\BulletOnTheWall\\Bullet.mdl", + 19 texture TEXTURE_BULLET_STAIN "Models\\Effects\\BulletOnTheWall\\Bullet.tex", + 70 texture TEXTURE_BULLET_TRAIL "Models\\Effects\\BulletTrail\\BulletTrail.tex", + 71 model MODEL_BULLET_TRAIL "Models\\Effects\\BulletTrail\\BulletTrail.mdl", + + 90 sound SOUND_BULLET_STONE "Sounds\\Weapons\\_BulletHitWall.wav", + 91 sound SOUND_BULLET_SAND "Sounds\\Weapons\\BulletHitSand.wav", + 92 sound SOUND_BULLET_WATER "Sounds\\Weapons\\BulletHitWater.wav", + 93 sound SOUND_BULLET_FLESH "Sounds\\Weapons\\_BulletHitFlesh.wav", + 94 texture TEXTURE_BULLET_SAND "Models\\Effects\\BulletOnTheWall\\BulletSand.tex", + 95 sound SOUND_BULLET_GRASS "SoundsMP\\Weapons\\BulletHitGrass.wav", + 96 sound SOUND_BULLET_WOOD "SoundsMP\\Weapons\\BulletHitWood.wav", + 97 sound SOUND_BULLET_SNOW "SoundsMP\\Weapons\\BulletHitSnow.wav", + +// ********** BLOOD ********** + 21 model MODEL_BLOOD_EXPLODE "Models\\Effects\\BloodCloud\\BloodCloud.mdl", + 22 texture TEXTURE_BLOOD_EXPLODE "Models\\Effects\\BloodCloud\\BloodCloud.tex", + 23 model MODEL_BLOOD_STAIN "Models\\Effects\\BloodOnTheWall01\\Blood.mdl", + 24 texture TEXTURE_BLOOD_STAIN1 "Models\\Effects\\BloodOnTheWall01\\BloodStain01.tex", + 25 texture TEXTURE_BLOOD_STAIN2 "Models\\Effects\\BloodOnTheWall01\\BloodStain02.tex", + 26 texture TEXTURE_BLOOD_STAIN3 "Models\\Effects\\BloodOnTheWall01\\BloodStain03.tex", + 27 texture TEXTURE_BLOOD_STAIN4 "Models\\Effects\\BloodOnTheWall01\\BloodStain04.tex", + 28 texture TEXTURE_BLOOD_SPILL1 "Models\\Effects\\BloodOnTheWall01\\BloodSpill02.tex", + 29 texture TEXTURE_BLOOD_SPILL2 "Models\\Effects\\BloodOnTheWall01\\BloodSpill05.tex", + 30 texture TEXTURE_BLOOD_SPILL3 "Models\\Effects\\BloodOnTheWall01\\BloodSpill06.tex", + 31 texture TEXTURE_BLOOD_FLOWER1 "Models\\Effects\\Flowers\\Flowers1s.tex", + 32 texture TEXTURE_BLOOD_FLOWER2 "Models\\Effects\\Flowers\\Flowers2s.tex", + 33 texture TEXTURE_BLOOD_FLOWER3 "Models\\Effects\\Flowers\\Flowers3s.tex", + +// ********** SHOCK WAVE ********** + 40 model MODEL_SHOCKWAVE "Models\\Effects\\ShockWave01\\ShockWave.mdl", + 41 texture TEXTURE_SHOCKWAVE "Models\\Effects\\ShockWave01\\Textures\\ShockWave.tex", + + 42 model MODEL_CANNONSHOCKWAVE "Models\\Effects\\ShockWave01\\ShockWave.mdl", + 43 texture TEXTURE_CANNONSHOCKWAVE "Models\\Effects\\ShockWave01\\Textures\\ShockWave.tex", + +// ********** EXPLOSION STAIN ********** + 45 model MODEL_EXPLOSION_STAIN "Models\\Effects\\BurnedStainOnTheWall\\BurnedStainOnTheWall.mdl", + 46 texture TEXTURE_EXPLOSION_STAIN "Models\\Effects\\BurnedStainOnTheWall\\BurnedStainOnTheWall.tex", + + 47 model MODEL_CANNON_EXPLOSION_STAIN "Models\\Effects\\BurnedStainOnTheWall\\BurnedStainOnTheWall.mdl", + 48 texture TEXTURE_CANNON_EXPLOSION_STAIN "Models\\Effects\\BurnedStainOnTheWall\\BurnedStainOnTheWall.tex", + +// ********** LASER WAVE ********** + 50 model MODEL_LASERWAVE "Models\\Effects\\ShockWaveGreen\\ShockWaveGreen.mdl", + 51 texture TEXTURE_LASERWAVE "Models\\Effects\\ShockWaveGreen\\ShockWaveGreen.tex", + +// ********** TELEPORT ********** + 61 model MODEL_TELEPORT_EFFECT "Models\\Effects\\Teleport01\\Teleport.mdl", + 62 texture TEXTURE_TELEPORT_EFFECT "Textures\\Effects\\Effect01\\Effect.tex", + 63 sound SOUND_TELEPORT "Sounds\\Misc\\Teleport.wav", + +// ********** GIZMO SPLASH FX ********** + 80 sound SOUND_GIZMO_SPLASH "Models\\Enemies\\Gizmo\\Sounds\\Death.wav", + +// ********** Water shockwave texture ********** + 100 texture TEXTURE_WATER_WAVE "Models\\Effects\\ShockWave01\\Textures\\WaterWave.tex", + +functions: + + // dump sync data to text file + export void DumpSync_t(CTStream &strm, INDEX iExtensiveSyncCheck) // throw char * + { + CRationalEntity::DumpSync_t(strm, iExtensiveSyncCheck); + strm.FPrintF_t("Type: %d\n", m_betType); + } + + /* Read from stream. */ + void Read_t( CTStream *istr) // throw char * + { + CRationalEntity::Read_t(istr); + // setup light source + if( m_bLightSource) { + SetupLightSource(); + } + } + + /* Get static light source information. */ + CLightSource *GetLightSource(void) + { + if( m_bLightSource && !IsPredictor()) { + return &m_lsLightSource; + } else { + return NULL; + } + } + + // Setup light source + void SetupLightSource(void) + { + if( m_iLightAnimation>=0) + { // set light animation if available + try { + m_aoLightAnimation.SetData_t(CTFILENAME("Animations\\BasicEffects.ani")); + } catch (char *strError) { + WarningMessage(TRANS("Cannot load Animations\\BasicEffects.ani: %s"), strError); + } + // play light animation + if (m_aoLightAnimation.GetData()!=NULL) { + m_aoLightAnimation.PlayAnim(m_iLightAnimation, 0); + } + } + + // setup light source + CLightSource lsNew; + lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC; + lsNew.ls_rHotSpot = 0.0f; + switch (m_betType) { + case BET_ROCKET: + lsNew.ls_colColor = RGBToColor(100, 100, 100); + lsNew.ls_rHotSpot = 3.0f; + lsNew.ls_rFallOff = 12.5f; + lsNew.ls_plftLensFlare = NULL; + break; + case BET_GRENADE: + lsNew.ls_colColor = RGBToColor(200, 200, 200); + lsNew.ls_rFallOff = 12.5f; + lsNew.ls_plftLensFlare = NULL; + break; + case BET_CANNON: + case BET_LIGHT_CANNON: + lsNew.ls_colColor = RGBToColor(200, 200, 200); + lsNew.ls_rFallOff = 12.5f; + lsNew.ls_plftLensFlare = NULL; + break; + case BET_LASERWAVE: + lsNew.ls_colColor = RGBToColor(0, 64, 0); + lsNew.ls_rFallOff = 1.5f; + lsNew.ls_plftLensFlare = NULL; + break; + case BET_BOMB: + lsNew.ls_colColor = RGBToColor(100, 100, 100); + lsNew.ls_rFallOff = 8.0f; + lsNew.ls_plftLensFlare = NULL; + break; + default: + ASSERTALWAYS("Unknown light source"); + } + lsNew.ls_ubPolygonalMask = 0; + lsNew.ls_paoLightAnimation = NULL; + + // setup light animation + lsNew.ls_paoLightAnimation = NULL; + if (m_aoLightAnimation.GetData()!=NULL) { + lsNew.ls_paoLightAnimation = &m_aoLightAnimation; + } + + m_lsLightSource.ls_penEntity = this; + m_lsLightSource.SetLightSource(lsNew); + } + + +/* RENDER PARTICLES */ + + + void RenderParticles(void) + { + if( m_eptType != EPT_NONE) + { + FLOAT fStretch=0.3f; + Particles_BulletSpray(en_ulID, GetLerpedPlacement().pl_PositionVector, m_vGravity, + m_eptType, m_tmSpawn, m_vStretch, fStretch); + } + if(m_betType==BET_EXPLOSION_DEBRIS) + { + Particles_ExplosionDebris1(this, m_tmSpawn, m_vStretch, m_colMultiplyColor); + Particles_ExplosionDebris2(this, m_tmSpawn, m_vStretch, m_colMultiplyColor); + Particles_ExplosionDebris3(this, m_tmSpawn, m_vStretch, m_colMultiplyColor); + } + if(m_betType==BET_COLLECT_ENERGY) + { + Particles_CollectEnergy(this, m_tmSpawn, m_tmSpawn+m_fWaitTime); + } + /*if(m_betType==BET_SNIPER_RESIDUE) + { + Particles_SniperResidue(this, m_tmSpawn, m_tmSpawn+m_fWaitTime, m_vNormal, m_vDirection); + }*/ + if(m_betType==BET_EXPLOSION_SMOKE && _pTimer->GetLerpedCurrentTick()>(m_tmSpawn+m_fWaitTime) ) + { + Particles_ExplosionSmoke(this, m_tmSpawn+m_fWaitTime, m_vStretch, m_colMultiplyColor); + } + if(m_betType==BET_SUMMONERSTAREXPLOSION) + { + Particles_SummonerExplode(this, GetPlacement().pl_PositionVector, + 60.0f, 1.0f, m_tmSpawn, m_fWaitTime); + } + if(m_betType==BET_GROWING_SWIRL) + { + FLOAT fStretch=(m_vStretch(1)+m_vStretch(2)+m_vStretch(3))/3.0f; + Particles_GrowingSwirl(this, fStretch, m_tmSpawn); + } + if(m_betType==BET_DISAPPEAR_DUST) + { + FLOAT fStretch=(m_vStretch(1)+m_vStretch(2)+m_vStretch(3))/3.0f; + Particles_DisappearDust(this, fStretch, m_tmSpawn); + } + if(m_betType==BET_DUST_FALL) + { + Particles_DustFall(this, m_tmSpawn, m_vStretch); + } + } + + + +/************************************************************ + * FADE OUT * + ************************************************************/ + + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + if( m_bFade) { + FLOAT m_fTimeRemain = m_fFadeStartTime + m_fFadeTime - _pTimer->CurrentTick(); + if (m_fTimeRemain < 0.0f) { m_fTimeRemain = 0.0f; } + COLOR col = GetModelColor() & ~CT_AMASK; + col |= (ULONG)(m_fFadeStartAlpha* m_fTimeRemain/m_fFadeTime *255.0f); + SetModelColor(col); + } else if (m_fFadeInSpeed>0) { + TIME tmAge = _pTimer->GetLerpedCurrentTick()-m_tmSpawn; + COLOR col = GetModelColor() ; + col = (col &~CT_AMASK) | + (ULONG)((255)*Clamp(tmAge*m_fFadeInSpeed/m_fWaitTime, 0.0f, 1.0f)); + SetModelColor(col); + } + + return FALSE; + }; + + // get offset for depth-sorting of alpha models (in meters, positive is nearer) + FLOAT GetDepthSortOffset(void) + { + return m_fDepthSortOffset; + } + + + +/************************************************************ + * GLOBAL SUPPORT FUNCTIONS * + ************************************************************/ + + void SetNonLoopingTexAnims(void) + { + CModelObject *pmo = GetModelObject(); + pmo->mo_toTexture.PlayAnim(0, 0); + FOREACHINLIST(CAttachmentModelObject, amo_lnInMain, pmo->mo_lhAttachments, itamo) { + CModelObject *pmoAtt = &itamo->amo_moModelObject; + pmoAtt->mo_toTexture.PlayAnim(0, 0); + } + } + + void SetNormalForHalfFaceForward(void) + { + CPlacement3D pl = GetPlacement(); + UpVectorToAngles(m_vNormal, pl.pl_OrientationAngle); + SetPlacement(pl); + }; + + void SetNormal(void) + { + CPlacement3D pl = GetPlacement(); + DirectionVectorToAngles(m_vNormal, pl.pl_OrientationAngle); + SetPlacement(pl); + }; + + void SetNormalWithRandomBanking(void) + { + CPlacement3D pl = GetPlacement(); + DirectionVectorToAngles(m_vNormal, pl.pl_OrientationAngle); + pl.pl_OrientationAngle(3) = FRnd()*360.0f; + SetPlacement(pl); + }; + + void FindGravityVectorFromSector(void) + { + CBrushSector *pbscContent = NULL; + {FOREACHSRCOFDST(en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + pbscContent = &*pbsc; + break; + ENDFOR;} + + if( pbscContent == NULL) + { + return; + } + INDEX iForceType = pbscContent->GetForceType(); + CEntity *penBrush = pbscContent->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + CForceStrength fsGravity; + CForceStrength fsField; + penBrush->GetForce( iForceType, en_plPlacement.pl_PositionVector, fsGravity, fsField); + // remember gravity vector + m_vGravity = fsGravity.fs_vDirection; + }; + + void SetNormalAndDirection(void) + { + // special case for stains without sliding + if( m_vDirection.Length() < 0.01f) { + SetNormalWithRandomBanking(); + return; + } + + FLOAT3D vX; + FLOAT3D vY = -m_vDirection; + FLOAT3D vZ = -m_vNormal; + vZ.Normalize(); + vX = vY*vZ; + vX.Normalize(); + vY = vZ*vX; + vY.Normalize(); + + FLOATmatrix3D m; + m(1,1) = vX(1); m(1,2) = vY(1); m(1,3) = vZ(1); + m(2,1) = vX(2); m(2,2) = vY(2); m(2,3) = vZ(2); + m(3,1) = vX(3); m(3,2) = vY(3); m(3,3) = vZ(3); + + CPlacement3D pl = GetPlacement(); + DecomposeRotationMatrixNoSnap(pl.pl_OrientationAngle, m); + SetPlacement(pl); + }; + + void RandomBanking(void) + { + CPlacement3D pl = GetPlacement(); + pl.pl_OrientationAngle(3) = FRnd()*360.0f; + SetPlacement(pl); + }; + + void Stretch(void) { + ASSERT(m_vStretch(1)>0.01f && m_vStretch(3)>0.01f && m_vStretch(3)>0.01f); + GetModelObject()->mo_Stretch = m_vStretch; + }; + + // parent the effect if needed and adjust size not to get out of the polygon + void ParentToNearestPolygonAndStretch(void) + { + // find nearest polygon + FLOAT3D vPoint; + FLOATplane3D plPlaneNormal; + FLOAT fDistanceToEdge; + CBrushPolygon *pbpoNearBrush = GetNearestPolygon( vPoint, plPlaneNormal, fDistanceToEdge); + + if( (m_betType>=BET_BULLETSTAINSTONE && m_betType<=BET_BULLETSTAINREDSANDNOSOUND) || + (m_betType>=BET_BULLETSTAINGRASS && m_betType<=BET_BULLETSTAINWOODNOSOUND) || + (m_betType>=BET_BULLETSTAINSNOW && m_betType<=BET_BULLETSTAINSNOWNOSOUND)) + { + if( pbpoNearBrush != NULL) + { + CBrushSector *pbscContent = pbpoNearBrush->bpo_pbscSector; + INDEX iForceType = pbscContent->GetForceType(); + CEntity *penNearBrush = pbscContent->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + CForceStrength fsGravity; + CForceStrength fsField; + penNearBrush->GetForce( iForceType, en_plPlacement.pl_PositionVector, fsGravity, fsField); + // remember gravity vector + m_vGravity = fsGravity.fs_vDirection; + } + } + + // if there is none, or if it is portal, or it is not near enough + if (pbpoNearBrush==NULL || (pbpoNearBrush->bpo_ulFlags&BPOF_PORTAL) + || (vPoint-GetPlacement().pl_PositionVector).ManhattanNorm()>0.1f*3) { + // dissapear + SwitchToEditorModel(); + // if polygon is found + } else { + CEntity *penNearBrush = pbpoNearBrush->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity; + FLOATaabbox3D box; + en_pmoModelObject->GetCurrentFrameBBox( box); + box.StretchByVector( en_pmoModelObject->mo_Stretch); + FLOAT fOrgSize = box.Size().MaxNorm(); + FLOAT fMaxSize = fDistanceToEdge*2.0f; + // if minimum distance from polygon edges is too small + if( fMaxSizemo_Stretch*fStretch; + Stretch(); + ModelChangeNotify(); + // set parent to that brush + SetParent( penNearBrush); + } + } + } + + +/************************************************************ + * PROJECTILE/GRENADE EXPLOSION, STAIN * + ************************************************************/ + + void ProjectileExplosion(void) + { + SetPredictable(TRUE); + Stretch(); + SetModel(MDL_ROCKET_EXPLOSION); + SetModelMainTexture(TXT_ROCKET_EXPLOSION); + AddAttachment(0, MDL_PARTICLES_EXPLOSION, TXT_PARTICLES_EXPLOSION); + RandomBanking(); + SetNonLoopingTexAnims(); + m_soEffect.Set3DParameters(150.0f, 3.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_EXPLOSION, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_EXPLOSION); + m_fWaitTime = 0.95f; + m_bLightSource = TRUE; + m_iLightAnimation = 0; + }; + + void ProjectilePlaneExplosion(void) { + SetPredictable(TRUE); + Stretch(); + SetModel(MDL_ROCKET3D_EXPLOSION); + SetModelMainTexture(TXT_ROCKET_EXPLOSION); + AddAttachment(0, MDL_PARTICLES3D_EXPLOSION, TXT_PARTICLES_EXPLOSION); + SetNormalWithRandomBanking(); + SetNonLoopingTexAnims(); + m_fWaitTime = 0.95f; + m_bLightSource = FALSE; + }; + + void BombExplosion(void) { + SetPredictable(TRUE); + Stretch(); + SetModel(MDL_GRENADE_EXPLOSION); + SetModelMainTexture(TXT_GRENADE_EXPLOSION); + SetNonLoopingTexAnims(); + FLOAT fSizeFactor = m_vStretch.MaxNorm(); + m_soEffect.Set3DParameters(50.0f*fSizeFactor, 10.0f*fSizeFactor, 1.0f*fSizeFactor, 1.0f); + PlaySound(m_soEffect, SOUND_EXPLOSION, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_EXPLOSION); + m_fWaitTime = 0.95f; + m_bLightSource = TRUE; + m_iLightAnimation = 1; + }; + + void GizmoSplashFX(void) + { + SetPredictable(TRUE); + SetModel(MODEL_BULLET_HIT); + SetModelMainTexture(TEXTURE_BULLET_HIT); + m_soEffect.Set3DParameters(50.0f, 10.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_GIZMO_SPLASH, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_GIZMO_SPLASH); + m_fWaitTime = 0.95f; + m_bLightSource = FALSE; + }; + + void ExplosionDebris(void) + { + SetPredictable(TRUE); + SetModel(MODEL_BULLET_HIT); + SetModelMainTexture(TEXTURE_BULLET_HIT); + m_fWaitTime = 0.95f; + m_bLightSource = FALSE; + }; + + void CollectEnergy(void) + { + SetPredictable(TRUE); + SetModel(MODEL_BULLET_HIT); + SetModelMainTexture(TEXTURE_BULLET_HIT); + m_fWaitTime = 2; + m_bLightSource = FALSE; + } + + void GrowingSwirl(void) + { + SetPredictable(TRUE); + SetModel(MODEL_BULLET_HIT); + SetModelMainTexture(TEXTURE_BULLET_HIT); + m_fWaitTime = 10.0f; + m_bLightSource = FALSE; + } + + void DisappearDust(void) + { + SetPredictable(TRUE); + SetModel(MODEL_BULLET_HIT); + SetModelMainTexture(TEXTURE_BULLET_HIT); + m_fWaitTime = 10.0f; + m_bLightSource = FALSE; + } + + void DustFall(void) + { + SetPredictable(TRUE); + SetModel(MODEL_BULLET_HIT); + SetModelMainTexture(TEXTURE_BULLET_HIT); + m_fWaitTime = 10.0f; + m_bLightSource = FALSE; + } + + void SniperResidue(void) + { + // NOTE: m_vNormal and m_vDirection here represent the starting and the + // ending point of this effect!!! + SetPredictable(TRUE); + SetModel(MODEL_BULLET_HIT); + SetModelMainTexture(TEXTURE_BULLET_HIT); + m_fWaitTime = 0.05f; + m_bLightSource = FALSE; + } + + void ExplosionSmoke(void) + { + SetPredictable(TRUE); + SetModel(MODEL_BULLET_HIT); + SetModelMainTexture(TEXTURE_BULLET_HIT); + m_fWaitTime=0.25f; + m_tmWaitAfterDeath=8.0f; + m_bLightSource = FALSE; + }; + + void GrenadeExplosion(void) { + SetPredictable(TRUE); + Stretch(); + SetModel(MDL_GRENADE_EXPLOSION); + SetModelMainTexture(TXT_GRENADE_EXPLOSION); + AddAttachment(0, MDL_PARTICLES_EXPLOSION, TXT_PARTICLES_EXPLOSION); + RandomBanking(); + SetNonLoopingTexAnims(); + m_soEffect.Set3DParameters(150.0f, 3.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_EXPLOSION, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_EXPLOSION); + m_fWaitTime = 0.95f; + m_bLightSource = TRUE; + m_iLightAnimation = 1; + }; + + void GrenadePlaneExplosion(void) { + SetPredictable(TRUE); + Stretch(); + SetModel(MDL_GRENADE3D_EXPLOSION); + SetModelMainTexture(TXT_GRENADE_EXPLOSION); + AddAttachment(0, MDL_PARTICLES3D_EXPLOSION, TXT_PARTICLES_EXPLOSION); + SetNonLoopingTexAnims(); + SetNormalWithRandomBanking(); + m_fWaitTime = 0.95f; + m_bLightSource = FALSE; + }; + + void CannonExplosion(BOOL bLoVolume, BOOL bNoLight) { + SetPredictable(TRUE); + Stretch(); + SetModel(MDL_CANNON_EXPLOSION); + CModelObject &moExplosion = *GetModelObject(); + SetModelMainTexture(TXT_CANNON_EXPLOSION); + moExplosion.mo_colBlendColor = m_colMultiplyColor; + moExplosion.mo_toTexture.PlayAnim(EXPLOSION_GRENADE_TEXTURE_ANIM_FAST, 0); + RandomBanking(); + if( bLoVolume) + { + m_soEffect.Set3DParameters(150.0f, 3.0f, 0.5f, 1.0f); + } + else + { + m_soEffect.Set3DParameters(150.0f, 3.0f, 1.0f, 1.0f); + } + + PlaySound(m_soEffect, SOUND_EXPLOSION, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_EXPLOSION); + m_fWaitTime = 0.8f; + if( bNoLight) + { + m_bLightSource = FALSE; + } + else + { + m_bLightSource = TRUE; + m_iLightAnimation = 1; + } + }; + + void CannonPlaneExplosion(void) { + SetPredictable(TRUE); + Stretch(); + SetModel(MDL_CANNON3D_EXPLOSION); + CModelObject &moExplosion = *GetModelObject(); + SetModelMainTexture(TXT_CANNON_EXPLOSION); + moExplosion.mo_toTexture.PlayAnim(EXPLOSION_GRENADE_TEXTURE_ANIM_FAST, 0); + SetNormalWithRandomBanking(); + m_fWaitTime = 1.2f; + m_bLightSource = FALSE; + }; + + void Stain(void) { + SetModel(MODEL_EXPLOSION_STAIN); + SetModelMainTexture(TEXTURE_EXPLOSION_STAIN); + SetNormalWithRandomBanking(); + m_fWaitTime = 5.0f; + m_fFadeTime = 2.5f; + m_bLightSource = FALSE; + ParentToNearestPolygonAndStretch(); + }; + + void CannonStain(void) { + Stretch(); + SetModel(MODEL_CANNON_EXPLOSION_STAIN); + SetModelMainTexture(TEXTURE_CANNON_EXPLOSION_STAIN); + SetNormalWithRandomBanking(); + m_fWaitTime = 5.0f; + m_fFadeTime = 2.5f; + m_bLightSource = FALSE; + ParentToNearestPolygonAndStretch(); + }; + + + +/************************************************************ + * SHOCK / LASER WAVE * + ************************************************************/ + void ShockWave(void) { + SetPredictable(TRUE); + SetModel(MODEL_SHOCKWAVE); + CModelObject &moShockwave = *GetModelObject(); + moShockwave.PlayAnim(SHOCKWAVE_ANIM_FAST, 0); + SetModelMainTexture(TEXTURE_SHOCKWAVE); + SetNormal(); + SetNonLoopingTexAnims(); + m_fWaitTime = 0.4f; + m_fFadeTime = 0.1f; + m_bLightSource = FALSE; + }; + + void CannonShockWave(void) { + SetPredictable(TRUE); + Stretch(); + SetModel(MODEL_CANNONSHOCKWAVE); + CModelObject &moShockwave = *GetModelObject(); + moShockwave.PlayAnim(SHOCKWAVE_ANIM_SLOW, 0); + SetModelMainTexture(TEXTURE_CANNONSHOCKWAVE); + moShockwave.mo_toTexture.PlayAnim(SHOCKWAVE_TEXTURE_ANIM_SLOW, 0); + SetNormal(); + m_fWaitTime = 1.25f; + m_fFadeTime = 0.25f; + m_bLightSource = FALSE; + }; + + void LaserWave(void) { + SetModel(MODEL_LASERWAVE); + GetModelObject()->StretchModel(FLOAT3D(0.75f, 0.75f, 0.75f)); + ModelChangeNotify(); + SetModelMainTexture(TEXTURE_LASERWAVE); + SetNormalWithRandomBanking(); + SetNonLoopingTexAnims(); + m_fWaitTime = 0.05f; + m_fFadeTime = 0.25f; + m_bLightSource = TRUE; + ParentToNearestPolygonAndStretch(); + }; + + + + /************************************************************ + * TELEPORT * + ************************************************************/ + void TeleportEffect(void) + { + SetPredictable(TRUE); + Stretch(); + SetModel(MODEL_TELEPORT_EFFECT); + CModelObject &mo = *GetModelObject(); + SetModelMainTexture(TEXTURE_TELEPORT_EFFECT); + mo.PlayAnim(TELEPORT_ANIM_ACTIVATE, 0); + RandomBanking(); + FLOAT fSize = m_vStretch.MaxNorm(); + m_soEffect.Set3DParameters(40.0f*fSize, 10.0f*fSize, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_TELEPORT, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_TELEPORT); + m_fWaitTime = 0.8f; + m_bLightSource = FALSE; + }; + + /************************************************************ + * SUMMONER STAR EXPLOSION * + ************************************************************/ + void SummonerStarExplosion() + { + SetPredictable(TRUE); + SetModel(MODEL_BULLET_HIT); + SetModelMainTexture(TEXTURE_BULLET_HIT); + m_fWaitTime=16.0f; + m_tmWaitAfterDeath=8.0f; + m_bLightSource = FALSE; + m_vStretch = FLOAT3D(1.0f, 1.0f, 1.0f); + Stretch(); + }; + + /************************************************************ + * BULLET HIT / STAIN * + ************************************************************/ + void BulletStainSand(BOOL bSound) + { + if( bSound) + { + m_soEffect.Set3DParameters(20.0f, 10.0f, 1.0f, 1.0f+FRnd()*0.2f); + PlaySound(m_soEffect, SOUND_BULLET_SAND, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_BULLET_SAND); + } + + SetModel(MODEL_BULLET_STAIN); + SetModelMainTexture(TEXTURE_BULLET_SAND); + CModelObject &moHole = *GetModelObject(); + moHole.StretchModel(FLOAT3D(1.5f, 1.5f, 1.5f)); + ModelChangeNotify(); + + SetNormalWithRandomBanking(); + m_fWaitTime = 2.0f; + m_fFadeTime = 2.0f; + m_bLightSource = FALSE; + m_eptType = EPT_BULLET_SAND; + FLOAT3D vTemp = m_vStretch; + ParentToNearestPolygonAndStretch(); + m_vStretch = vTemp; + } + + void BulletStainRedSand(BOOL bSound) + { + if( bSound) + { + m_soEffect.Set3DParameters(20.0f, 10.0f, 1.0f, 1.0f+FRnd()*0.2f); + PlaySound(m_soEffect, SOUND_BULLET_SAND, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_BULLET_SAND); + } + + SetModel(MODEL_BULLET_STAIN); + SetModelMainTexture(TEXTURE_BULLET_SAND); + CModelObject &moHole = *GetModelObject(); + moHole.StretchModel(FLOAT3D(1.5f, 1.5f, 1.5f)); + ModelChangeNotify(); + moHole.mo_colBlendColor = 0x805030FF; + + SetNormalWithRandomBanking(); + m_fWaitTime = 2.0f; + m_fFadeTime = 2.0f; + m_bLightSource = FALSE; + m_eptType = EPT_BULLET_RED_SAND; + FLOAT3D vTemp = m_vStretch; + ParentToNearestPolygonAndStretch(); + m_vStretch = vTemp; + } + + void BulletStainStone(BOOL bSound, BOOL bSmoke) + { + if( bSound) + { + m_soEffect.Set3DParameters(20.0f, 10.0f, 1.0f, 1.0f+FRnd()*0.2f); + PlaySound(m_soEffect, SOUND_BULLET_STONE, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_BULLET_STONE); + } + SetModel(MODEL_BULLET_STAIN); + SetModelMainTexture(TEXTURE_BULLET_STAIN); + SetNormalWithRandomBanking(); + m_fWaitTime = 2.0f; + m_fFadeTime = 2.0f; + m_bLightSource = FALSE; + if( bSmoke) + { + m_eptType = EPT_BULLET_STONE; + } + else + { + m_eptType = EPT_BULLET_UNDER_WATER; + } + FLOAT3D vTemp = m_vStretch; + ParentToNearestPolygonAndStretch(); + m_vStretch = vTemp; + } + + void BulletStainWater(BOOL bSound) + { + if( bSound) + { + m_soEffect.Set3DParameters(20.0f, 10.0f, 1.0f, 1.0f+FRnd()*0.2f); + PlaySound(m_soEffect, SOUND_BULLET_WATER, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_BULLET_WATER); + } + + SetModel(MODEL_SHOCKWAVE); + SetModelMainTexture(TEXTURE_WATER_WAVE); + CModelObject &moShockwave = *GetModelObject(); + moShockwave.PlayAnim(SHOCKWAVE_ANIM_MEDIUM, 0); + moShockwave.StretchModel(FLOAT3D(0.25f, 0.25f, 0.25f)); + ModelChangeNotify(); + + SetNormalWithRandomBanking(); + FindGravityVectorFromSector(); + m_fWaitTime = 0.5f; + m_fFadeTime = 0.5f; + m_bLightSource = FALSE; + m_tmWaitAfterDeath = 1.0f; + m_eptType = EPT_BULLET_WATER; + } + + void BulletTrail(void) { + Stretch(); + SetModel(MODEL_BULLET_TRAIL); + SetModelMainTexture(TEXTURE_BULLET_TRAIL); + CModelObject &mo = *GetModelObject(); + mo.mo_colBlendColor = m_colMultiplyColor; + SetNormalForHalfFaceForward(); + m_fWaitTime = 0.1f; + m_bLightSource = FALSE; + }; + + void BulletStainGrass(BOOL bSound) { + if( bSound) + { + m_soEffect.Set3DParameters(20.0f, 10.0f, 1.0f, 1.0f+FRnd()*0.2f); + PlaySound(m_soEffect, SOUND_BULLET_GRASS, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_BULLET_GRASS); + } + + SetModel(MODEL_BULLET_STAIN); + SetModelMainTexture(TEXTURE_BULLET_STAIN); + CModelObject &moHole = *GetModelObject(); + moHole.StretchModel(FLOAT3D(1.5f, 1.5f, 1.5f)); + ModelChangeNotify(); + moHole.mo_colBlendColor = 0x80f080FF; + + SetNormalWithRandomBanking(); + m_fWaitTime = 2.0f; + m_fFadeTime = 2.0f; + m_bLightSource = FALSE; + m_eptType = EPT_BULLET_GRASS; + FLOAT3D vTemp = m_vStretch; + ParentToNearestPolygonAndStretch(); + m_vStretch = vTemp; + }; + + void BulletStainWood(BOOL bSound) { + if( bSound) + { + m_soEffect.Set3DParameters(20.0f, 10.0f, 1.0f, 1.0f+FRnd()*0.2f); + PlaySound(m_soEffect, SOUND_BULLET_WOOD, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_BULLET_WOOD); + } + + SetModel(MODEL_BULLET_STAIN); + SetModelMainTexture(TEXTURE_BULLET_STAIN); + CModelObject &moHole = *GetModelObject(); + moHole.StretchModel(FLOAT3D(1.5f, 1.5f, 1.5f)); + ModelChangeNotify(); + moHole.mo_colBlendColor = 0xffc080FF; + + SetNormalWithRandomBanking(); + m_fWaitTime = 2.0f; + m_fFadeTime = 2.0f; + m_bLightSource = FALSE; + m_eptType = EPT_BULLET_WOOD; + FLOAT3D vTemp = m_vStretch; + ParentToNearestPolygonAndStretch(); + m_vStretch = vTemp; + }; + + void BulletStainSnow(BOOL bSound) { + if( bSound) + { + m_soEffect.Set3DParameters(20.0f, 10.0f, 1.0f, 1.0f+FRnd()*0.2f); + PlaySound(m_soEffect, SOUND_BULLET_SNOW, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_BULLET_SNOW); + } + + SetModel(MODEL_BULLET_STAIN); + SetModelMainTexture(TEXTURE_BULLET_STAIN); + CModelObject &moHole = *GetModelObject(); + moHole.StretchModel(FLOAT3D(1.5f, 1.5f, 1.5f)); + ModelChangeNotify(); + moHole.mo_colBlendColor = 0x7f7f7fFF; + + SetNormalWithRandomBanking(); + m_fWaitTime = 2.0f; + m_fFadeTime = 2.0f; + m_bLightSource = FALSE; + m_eptType = EPT_BULLET_SNOW; + FLOAT3D vTemp = m_vStretch; + ParentToNearestPolygonAndStretch(); + m_vStretch = vTemp; + }; + +/************************************************************ + * BLOOD SPILL / STAIN * + ************************************************************/ + + + // bullet hitpoint wound + void BloodExplode(void) + { + // readout blood type + const INDEX iBloodType = GetSP()->sp_iBlood; + if( iBloodType<1) { return; } + + SetPredictable(TRUE); + Stretch(); + SetModel(MODEL_BLOOD_EXPLODE); + if( iBloodType==3) { + // flower mode! :) + SetModelColor( RGBAToColor( 255,255,255,255)); + switch( IRnd()&3) { + case 1: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER1); break; } + case 2: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER2); break; } + case 3: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER3); break; } + default: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER1); break; } + } + } else { + SetModelMainTexture(TEXTURE_BLOOD_EXPLODE); + if( iBloodType==2) { SetModelColor( RGBAToColor( 250,20,20,255)); } + else { SetModelColor( RGBAToColor( 0,250,0,255)); } + } + //RandomBanking(); + m_soEffect.Set3DParameters(7.5f, 5.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_BULLET_FLESH, SOF_3D); + m_fSoundTime = GetSoundLength(SOUND_BULLET_FLESH); + m_fWaitTime = 0.25f; + m_fFadeTime = 0.75f; + m_bLightSource = FALSE; + } + + + // blood stain on wall/floor + void BloodStain(void) + { + // readout blood type + const INDEX iBloodType = GetSP()->sp_iBlood; + if( iBloodType<1) { return; } + + Stretch(); + SetModel(MODEL_BLOOD_STAIN); + if( iBloodType==3) { + // flower mode! :) + SetModelColor( RGBAToColor( 255,255,255,255)); + switch( IRnd()&3) { + case 1: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER1); break; } + case 2: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER2); break; } + case 3: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER3); break; } + default: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER1); break; } + } + } else { + switch( IRnd()&3) { + case 1: { SetModelMainTexture(TEXTURE_BLOOD_STAIN1); break; } + case 2: { SetModelMainTexture(TEXTURE_BLOOD_STAIN2); break; } + case 3: { SetModelMainTexture(TEXTURE_BLOOD_STAIN3); break; } + default: { SetModelMainTexture(TEXTURE_BLOOD_STAIN4); break; } + } + if( iBloodType==2) { SetModelColor( RGBAToColor( 250,20,20,255)); } + else { SetModelColor( RGBAToColor( 0,250,0,255)); } + } + + SetNormalAndDirection(); + m_fWaitTime = 12.0f + FRnd()*3.0f; + m_fFadeTime = 3.0f; + m_bLightSource = FALSE; + m_fDepthSortOffset = -0.1f; + ParentToNearestPolygonAndStretch(); + } + + + // blood stain on wall/floor that grows + void BloodStainGrow(void) + { + // readout blood type + const INDEX iBloodType = GetSP()->sp_iBlood; + if( iBloodType<1) { return; } + + SetPredictable(TRUE); + Stretch(); + SetModel(MODEL_BLOOD_STAIN); + if( iBloodType==3) { + // flower mode! :) + SetModelColor( RGBAToColor( 255,255,255,255)); + switch( IRnd()&3) { + case 1: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER1); break; } + case 2: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER2); break; } + case 3: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER3); break; } + default: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER1); break; } + } + } else { + SetModelMainTexture(TEXTURE_BLOOD_STAIN4); + if( iBloodType==2) { SetModelColor( RGBAToColor( 250,20,20,255)); } + else { SetModelColor( RGBAToColor( 0,250,0,255)); } + } + SetNormalAndDirection(); + m_bLightSource = FALSE; + m_fDepthSortOffset = -0.1f; + ParentToNearestPolygonAndStretch(); + + m_fWaitTime = 15.0f + FRnd()*2.0f; + m_fFadeTime = 2.0f; + m_fFadeInSpeed = 4.0f; + CModelObject &mo = *GetModelObject(); + mo.PlayAnim(BLOOD_ANIM_GROW, 0); + } + + + // gizmo stain on wall/floor + void GizmoStain(void) + { + // readout blood type + const INDEX iBloodType = GetSP()->sp_iBlood; + if( iBloodType<1) { return; } + + Stretch(); + SetModel(MODEL_BLOOD_STAIN); + if( iBloodType==3) { + // flower mode! :) + SetModelColor( RGBAToColor( 255,255,255,255)); + switch( IRnd()&3) { + case 1: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER1); break; } + case 2: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER2); break; } + case 3: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER3); break; } + default: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER1); break; } + } + } else { + SetModelColor( RGBAToColor( 0,250,0,255)); + switch( IRnd()&3) { + case 1: { SetModelMainTexture(TEXTURE_BLOOD_STAIN1); break; } + case 2: { SetModelMainTexture(TEXTURE_BLOOD_STAIN2); break; } + case 3: { SetModelMainTexture(TEXTURE_BLOOD_STAIN3); break; } + default: { SetModelMainTexture(TEXTURE_BLOOD_STAIN4); break; } + } + } + SetNormalAndDirection(); + m_fWaitTime = 15.0f + FRnd()*2.0f; + m_fFadeTime = 2.0f; + m_bLightSource = FALSE; + m_fDepthSortOffset = -0.1f; + ParentToNearestPolygonAndStretch(); + } + + + // bullet exit wound blood on wall/floor + void BloodSpill(COLOR colBloodSpillColor) + { + // readout blood type + const INDEX iBloodType = GetSP()->sp_iBlood; + if( iBloodType<1) { return; } + + Stretch(); + SetModel(MODEL_BLOOD_STAIN); + if( iBloodType==3) { + // flower mode! :) + SetModelColor( RGBAToColor( 255,255,255,255)); + switch( IRnd()&3) { + case 1: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER1); break; } + case 2: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER2); break; } + case 3: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER3); break; } + default: { SetModelMainTexture(TEXTURE_BLOOD_FLOWER1); break; } + } + } else { + switch( IRnd()%5) { + case 1: { SetModelMainTexture(TEXTURE_BLOOD_SPILL1); break; } + case 2: { SetModelMainTexture(TEXTURE_BLOOD_SPILL2); break; } + case 3: { SetModelMainTexture(TEXTURE_BLOOD_SPILL1); break; } + case 4: { SetModelMainTexture(TEXTURE_BLOOD_SPILL2); break; } + default: { SetModelMainTexture(TEXTURE_BLOOD_SPILL3); break; } + } + if( iBloodType==2) + { + SetModelColor( colBloodSpillColor); + } + else { SetModelColor( RGBAToColor( 0,250,0,255)); } + } + SetNormalAndDirection(); + m_fWaitTime = 15.0f + FRnd()*2.0f; + m_fFadeTime = 2.0f; + m_bLightSource = FALSE; + ParentToNearestPolygonAndStretch(); + } + +procedures: + + +/************************************************************ + * M A I N * + ************************************************************/ + + Main(ESpawnEffect eSpawn) + { + if(eSpawn.betType==BET_GIZMO_SPLASH_FX || + eSpawn.betType==BET_EXPLOSION_DEBRIS || + eSpawn.betType==BET_EXPLOSION_SMOKE || + eSpawn.betType==BET_SUMMONERSTAREXPLOSION || + eSpawn.betType==BET_COLLECT_ENERGY || + eSpawn.betType==BET_GROWING_SWIRL|| + eSpawn.betType==BET_DISAPPEAR_DUST|| + /*eSpawn.betType==BET_SNIPER_RESIDUE ||*/ + eSpawn.betType==BET_DUST_FALL) + { + InitAsEditorModel(); + } + else + { + InitAsModel(); + } + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + SetFlags(GetFlags() | ENF_SEETHROUGH); + + // set appearance + m_tmSpawn = _pTimer->CurrentTick(); + m_vNormal = eSpawn.vNormal; + m_vDirection = eSpawn.vDirection; + m_vStretch = eSpawn.vStretch; + m_betType = eSpawn.betType; + m_colMultiplyColor = eSpawn.colMuliplier; + + switch (m_betType) { + case BET_ROCKET: ProjectileExplosion(); break; + case BET_ROCKET_PLANE: ProjectilePlaneExplosion(); break; + case BET_GRENADE: GrenadeExplosion(); break; + case BET_GRENADE_PLANE: GrenadePlaneExplosion(); break; + case BET_EXPLOSIONSTAIN: Stain(); break; + case BET_SHOCKWAVE: ShockWave(); break; + case BET_LASERWAVE: LaserWave(); break; + case BET_BULLETTRAIL: BulletTrail(); break; + case BET_BULLETSTAINSAND: BulletStainSand(TRUE); break; + case BET_BULLETSTAINREDSAND: BulletStainRedSand(TRUE); break; + case BET_BULLETSTAINSTONE: BulletStainStone(TRUE, TRUE); break; + case BET_BULLETSTAINWATER: BulletStainWater(TRUE); break; + case BET_BULLETSTAINUNDERWATER: BulletStainStone(TRUE, FALSE); break; + case BET_BULLETSTAINSANDNOSOUND: BulletStainSand(FALSE); break; + case BET_BULLETSTAINREDSANDNOSOUND: BulletStainRedSand(FALSE); break; + case BET_BULLETSTAINSTONENOSOUND: BulletStainStone(FALSE, TRUE); break; + case BET_BULLETSTAINWATERNOSOUND: BulletStainWater(FALSE); break; + case BET_BULLETSTAINUNDERWATERNOSOUND: BulletStainStone(FALSE, FALSE); break; + case BET_BLOODSPILL: BloodSpill(m_colMultiplyColor); break; + case BET_BLOODSTAIN: BloodStain(); break; + case BET_GIZMOSTAIN: GizmoStain(); break; + case BET_BLOODSTAINGROW: BloodStainGrow(); break; + case BET_BLOODEXPLODE: BloodExplode(); break; + case BET_CANNON: CannonExplosion(FALSE, FALSE); break; + case BET_CANNON_NOLIGHT: CannonExplosion(TRUE, TRUE); break; + case BET_LIGHT_CANNON: CannonExplosion(TRUE, FALSE); break; + case BET_CANNON_PLANE: CannonPlaneExplosion(); break; + case BET_CANNONEXPLOSIONSTAIN: CannonStain(); break; + case BET_CANNONSHOCKWAVE: CannonShockWave(); break; + case BET_TELEPORT: TeleportEffect(); break; + case BET_BOMB: BombExplosion(); break; + case BET_GIZMO_SPLASH_FX: GizmoSplashFX(); break; + case BET_BULLETSTAINGRASS: BulletStainGrass(TRUE); break; + case BET_BULLETSTAINGRASSNOSOUND: BulletStainGrass(FALSE); break; + case BET_BULLETSTAINWOOD: BulletStainWood(TRUE); break; + case BET_BULLETSTAINWOODNOSOUND: BulletStainWood(FALSE); break; + case BET_EXPLOSION_DEBRIS: ExplosionDebris(); break; + case BET_COLLECT_ENERGY: CollectEnergy(); break; + /*case BET_SNIPER_RESIDUE: SniperResidue(); break;*/ + case BET_EXPLOSION_SMOKE: ExplosionSmoke(); break; + case BET_SUMMONERSTAREXPLOSION: SummonerStarExplosion(); break; + case BET_GROWING_SWIRL: GrowingSwirl(); break; + case BET_DISAPPEAR_DUST: DisappearDust(); break; + case BET_DUST_FALL: DustFall(); break; + case BET_BULLETSTAINSNOW: BulletStainSnow(TRUE); break; + case BET_BULLETSTAINSNOWNOSOUND: BulletStainSnow(FALSE); break; + default: + ASSERTALWAYS("Unknown effect type"); + } + + // setup light source + if (m_bLightSource) { SetupLightSource(); } + + wait() { + on (EBegin) : { call EffectLoop(); } + on (EBrushDestroyed) : { stop; } + on (EStop) : { stop; } + on (EReturn) : { stop; } + } + + // cease to exist + Destroy(); + return; + } + + + // standard effect loop + EffectLoop() + { + // wait + if (m_fWaitTime>0.0f) { + autowait(m_fWaitTime); + } + // fading + if (m_fFadeTime>0.0f) { + m_fFadeStartTime = _pTimer->CurrentTick(); + m_fFadeStartAlpha = ((GetModelColor()&CT_AMASK)>>CT_ASHIFT) / 255.0f; + m_bFade = TRUE; + autowait(m_fFadeTime); + m_bFade = FALSE; + } + + // wait for sound to end + if (m_fSoundTime > m_fWaitTime+m_fFadeTime) { + SwitchToEditorModel(); + autowait(m_fSoundTime - (m_fWaitTime+m_fFadeTime)); + } + + if (m_tmWaitAfterDeath>0.0f) { + if( en_RenderType != RT_EDITORMODEL) + { + SwitchToEditorModel(); + } + autowait(m_tmWaitAfterDeath); + } + + return EReturn(); + } + +}; diff --git a/Sources/EntitiesMP/BasicEffects.h b/Sources/EntitiesMP/BasicEffects.h new file mode 100644 index 0000000..842b439 --- /dev/null +++ b/Sources/EntitiesMP/BasicEffects.h @@ -0,0 +1,274 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_BasicEffects_INCLUDED +#define _EntitiesMP_BasicEffects_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType BasicEffectType_enum; +enum BasicEffectType { + BET_NONE = 0, + BET_ROCKET = 1, + BET_ROCKET_PLANE = 2, + BET_GRENADE = 3, + BET_GRENADE_PLANE = 4, + BET_EXPLOSIONSTAIN = 5, + BET_SHOCKWAVE = 6, + BET_LASERWAVE = 7, + BET_BLOODSPILL = 10, + BET_BLOODSTAIN = 11, + BET_BLOODSTAINGROW = 19, + BET_BLOODEXPLODE = 12, + BET_CANNON = 13, + BET_CANNON_PLANE = 14, + BET_CANNONEXPLOSIONSTAIN = 15, + BET_CANNONSHOCKWAVE = 16, + BET_TELEPORT = 17, + BET_BOMB = 18, + BET_BULLETTRAIL = 20, + BET_GIZMO_SPLASH_FX = 21, + BET_GIZMOSTAIN = 22, + BET_BULLETSTAINSTONE = 30, + BET_BULLETSTAINSAND = 31, + BET_BULLETSTAINWATER = 32, + BET_BULLETSTAINUNDERWATER = 33, + BET_BULLETSTAINSTONENOSOUND = 34, + BET_BULLETSTAINSANDNOSOUND = 35, + BET_BULLETSTAINWATERNOSOUND = 36, + BET_BULLETSTAINUNDERWATERNOSOUND = 37, + BET_BULLETSTAINREDSAND = 38, + BET_BULLETSTAINREDSANDNOSOUND = 39, + BET_LIGHT_CANNON = 40, + BET_CANNON_NOLIGHT = 41, + BET_BULLETSTAINGRASS = 42, + BET_BULLETSTAINWOOD = 43, + BET_BULLETSTAINGRASSNOSOUND = 44, + BET_BULLETSTAINWOODNOSOUND = 45, + BET_EXPLOSION_DEBRIS = 46, + BET_EXPLOSION_SMOKE = 47, + BET_SUMMONERSTAREXPLOSION = 48, + BET_COLLECT_ENERGY = 49, + BET_GROWING_SWIRL = 50, + BET_DISAPPEAR_DUST = 52, + BET_DUST_FALL = 53, + BET_BULLETSTAINSNOW = 54, + BET_BULLETSTAINSNOWNOSOUND = 55, +}; +DECL_DLL inline void ClearToDefault(BasicEffectType &e) { e = (BasicEffectType)0; } ; +#define EVENTCODE_ESpawnEffect 0x02590000 +class DECL_DLL ESpawnEffect : public CEntityEvent { +public: +ESpawnEffect(); +CEntityEvent *MakeCopy(void); +enum BasicEffectType betType; +FLOAT3D vNormal; +FLOAT3D vDirection; +FLOAT3D vStretch; +COLOR colMuliplier; +}; +DECL_DLL inline void ClearToDefault(ESpawnEffect &e) { e = ESpawnEffect(); } ; +extern "C" DECL_DLL CDLLEntityClass CBasicEffect_DLLClass; +class CBasicEffect : public CRationalEntity { +public: +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + DECL_DLL virtual void SetDefaultProperties(void); + enum BasicEffectType m_betType; + FLOAT m_fWaitTime; + FLOAT m_fFadeTime; + BOOL m_bFade; + FLOAT m_fFadeStartTime; + FLOAT m_fFadeStartAlpha; + FLOAT3D m_vNormal; + FLOAT3D m_vStretch; + FLOAT3D m_vDirection; + FLOAT m_fDepthSortOffset; + FLOAT m_fFadeInSpeed; + FLOAT m_tmSpawn; + FLOAT m_tmWaitAfterDeath; + BOOL m_bLightSource; + CAnimObject m_aoLightAnimation; + INDEX m_iLightAnimation; + COLOR m_colMultiplyColor; + CSoundObject m_soEffect; + FLOAT m_fSoundTime; + enum EffectParticlesType m_eptType; + FLOAT m_tmWhenShot; + FLOAT3D m_vGravity; + CEntityPointer m_penPrediction; +CLightSource m_lsLightSource; + DECL_DLL void DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck); + +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void Read_t(CTStream * istr); + +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +CLightSource * GetLightSource(void); + +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void SetupLightSource(void); + +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void RenderParticles(void); + +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +FLOAT GetDepthSortOffset(void); + +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void SetNonLoopingTexAnims(void); + +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void SetNormalForHalfFaceForward(void); + +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void SetNormal(void); + +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void SetNormalWithRandomBanking(void); + +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void FindGravityVectorFromSector(void); + +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void SetNormalAndDirection(void); + +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void RandomBanking(void); + +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void Stretch(void); + +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void ParentToNearestPolygonAndStretch(void); + +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void ProjectileExplosion(void); + +#line 678 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void ProjectilePlaneExplosion(void); + +#line 690 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BombExplosion(void); + +#line 705 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void GizmoSplashFX(void); + +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void ExplosionDebris(void); + +#line 726 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CollectEnergy(void); + +#line 735 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void GrowingSwirl(void); + +#line 744 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void DisappearDust(void); + +#line 753 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void DustFall(void); + +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void SniperResidue(void); + +#line 773 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void ExplosionSmoke(void); + +#line 783 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void GrenadeExplosion(void); + +#line 799 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void GrenadePlaneExplosion(void); + +#line 811 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CannonExplosion(BOOL bLoVolume,BOOL bNoLight); + +#line 843 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CannonPlaneExplosion(void); + +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void Stain(void); + +#line 865 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CannonStain(void); + +#line 881 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void ShockWave(void); + +#line 894 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void CannonShockWave(void); + +#line 908 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void LaserWave(void); + +#line 926 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void TeleportEffect(void); + +#line 946 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void SummonerStarExplosion(); + +#line 961 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BulletStainSand(BOOL bSound); + +#line 986 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BulletStainRedSand(BOOL bSound); + +#line 1012 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BulletStainStone(BOOL bSound,BOOL bSmoke); + +#line 1039 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BulletStainWater(BOOL bSound); + +#line 1064 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BulletTrail(void); + +#line 1075 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BulletStainGrass(BOOL bSound); + +#line 1100 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BulletStainWood(BOOL bSound); + +#line 1125 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BulletStainSnow(BOOL bSound); + +#line 1156 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BloodExplode(void); + +#line 1190 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BloodStain(void); + +#line 1228 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BloodStainGrow(void); + +#line 1265 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void GizmoStain(void); + +#line 1301 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +void BloodSpill(COLOR colBloodSpillColor); +#define STATE_CBasicEffect_Main 1 + BOOL +#line 1346 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x02590001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x02590002_Main_02(const CEntityEvent &__eeInput); +#define STATE_CBasicEffect_EffectLoop 0x02590003 + BOOL +#line 1444 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +EffectLoop(const CEntityEvent &__eeInput); + BOOL H0x02590004_EffectLoop_01(const CEntityEvent &__eeInput); + BOOL H0x02590005_EffectLoop_02(const CEntityEvent &__eeInput); + BOOL H0x02590006_EffectLoop_03(const CEntityEvent &__eeInput); + BOOL H0x02590007_EffectLoop_04(const CEntityEvent &__eeInput); + BOOL H0x02590008_EffectLoop_05(const CEntityEvent &__eeInput); + BOOL H0x02590009_EffectLoop_06(const CEntityEvent &__eeInput); + BOOL H0x0259000a_EffectLoop_07(const CEntityEvent &__eeInput); + BOOL H0x0259000b_EffectLoop_08(const CEntityEvent &__eeInput); + BOOL H0x0259000c_EffectLoop_09(const CEntityEvent &__eeInput); + BOOL H0x0259000d_EffectLoop_10(const CEntityEvent &__eeInput); + BOOL H0x0259000e_EffectLoop_11(const CEntityEvent &__eeInput); + BOOL H0x0259000f_EffectLoop_12(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_BasicEffects_INCLUDED diff --git a/Sources/EntitiesMP/BasicEffects_tables.h b/Sources/EntitiesMP/BasicEffects_tables.h new file mode 100644 index 0000000..1a35a05 --- /dev/null +++ b/Sources/EntitiesMP/BasicEffects_tables.h @@ -0,0 +1,230 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(BasicEffectType) + EP_ENUMVALUE(BET_NONE, "None"), + EP_ENUMVALUE(BET_ROCKET, "Rocket"), + EP_ENUMVALUE(BET_ROCKET_PLANE, "Rocket plane"), + EP_ENUMVALUE(BET_GRENADE, "Grenade"), + EP_ENUMVALUE(BET_GRENADE_PLANE, "Grenade plane"), + EP_ENUMVALUE(BET_EXPLOSIONSTAIN, "Explosionstain"), + EP_ENUMVALUE(BET_SHOCKWAVE, "Shockwave"), + EP_ENUMVALUE(BET_LASERWAVE, "Laserwave"), + EP_ENUMVALUE(BET_BLOODSPILL, "Blood spill"), + EP_ENUMVALUE(BET_BLOODSTAIN, "Blood stain"), + EP_ENUMVALUE(BET_BLOODSTAINGROW, "Blood staingrow"), + EP_ENUMVALUE(BET_BLOODEXPLODE, "Blood explode"), + EP_ENUMVALUE(BET_CANNON, "Cannon"), + EP_ENUMVALUE(BET_CANNON_PLANE, "Cannon plane"), + EP_ENUMVALUE(BET_CANNONEXPLOSIONSTAIN, "Cannon explosion stain"), + EP_ENUMVALUE(BET_CANNONSHOCKWAVE, "Cannon shockwave"), + EP_ENUMVALUE(BET_TELEPORT, "Teleport"), + EP_ENUMVALUE(BET_BOMB, "Bomb"), + EP_ENUMVALUE(BET_BULLETTRAIL, "Bullet trail"), + EP_ENUMVALUE(BET_GIZMO_SPLASH_FX, "Gizmo splash fx"), + EP_ENUMVALUE(BET_GIZMOSTAIN, "Gizmo stain"), + EP_ENUMVALUE(BET_BULLETSTAINSTONE, "Bullet stain stone"), + EP_ENUMVALUE(BET_BULLETSTAINSAND, "Bullet stain sand"), + EP_ENUMVALUE(BET_BULLETSTAINWATER, "Bullet stain water"), + EP_ENUMVALUE(BET_BULLETSTAINUNDERWATER, "Bullet stain underwater"), + EP_ENUMVALUE(BET_BULLETSTAINSTONENOSOUND, "Bullet stain stonenosound"), + EP_ENUMVALUE(BET_BULLETSTAINSANDNOSOUND, "Bullet stain sandnosound"), + EP_ENUMVALUE(BET_BULLETSTAINWATERNOSOUND, "Bullet stain waternosound"), + EP_ENUMVALUE(BET_BULLETSTAINUNDERWATERNOSOUND, "Bullet stain underwater no sound"), + EP_ENUMVALUE(BET_BULLETSTAINREDSAND, "Bullet stain red sand"), + EP_ENUMVALUE(BET_BULLETSTAINREDSANDNOSOUND, "Bullet stain red sand no sound"), + EP_ENUMVALUE(BET_LIGHT_CANNON, "Light cannon"), + EP_ENUMVALUE(BET_CANNON_NOLIGHT, "Cannon no light"), + EP_ENUMVALUE(BET_BULLETSTAINGRASS, "Bullet stain grass"), + EP_ENUMVALUE(BET_BULLETSTAINWOOD, "Bullet stain wood"), + EP_ENUMVALUE(BET_BULLETSTAINGRASSNOSOUND, "Bullet stain grass no sound"), + EP_ENUMVALUE(BET_BULLETSTAINWOODNOSOUND, "Bullet stain wood no sound"), + EP_ENUMVALUE(BET_EXPLOSION_DEBRIS, "Explosion debris"), + EP_ENUMVALUE(BET_EXPLOSION_SMOKE, "Explosion smoke"), + EP_ENUMVALUE(BET_SUMMONERSTAREXPLOSION, "Summoner star explosion"), + EP_ENUMVALUE(BET_COLLECT_ENERGY, "Collect energy"), + EP_ENUMVALUE(BET_GROWING_SWIRL, "Growing swirl"), + EP_ENUMVALUE(BET_DISAPPEAR_DUST, "Disappear dust"), + EP_ENUMVALUE(BET_DUST_FALL, "Dust fall"), + EP_ENUMVALUE(BET_BULLETSTAINSNOW, "Bullet stain snow"), + EP_ENUMVALUE(BET_BULLETSTAINSNOWNOSOUND, "Bullet stain snow"), +EP_ENUMEND(BasicEffectType); + +#define ENTITYCLASS CBasicEffect + +CEntityProperty CBasicEffect_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &BasicEffectType_enum, (0x00000259<<8)+1, offsetof(CBasicEffect, m_betType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000259<<8)+2, offsetof(CBasicEffect, m_fWaitTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000259<<8)+3, offsetof(CBasicEffect, m_fFadeTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000259<<8)+4, offsetof(CBasicEffect, m_bFade), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000259<<8)+5, offsetof(CBasicEffect, m_fFadeStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000259<<8)+9, offsetof(CBasicEffect, m_fFadeStartAlpha), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000259<<8)+6, offsetof(CBasicEffect, m_vNormal), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000259<<8)+7, offsetof(CBasicEffect, m_vStretch), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000259<<8)+8, offsetof(CBasicEffect, m_vDirection), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000259<<8)+10, offsetof(CBasicEffect, m_fDepthSortOffset), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000259<<8)+11, offsetof(CBasicEffect, m_fFadeInSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000259<<8)+12, offsetof(CBasicEffect, m_tmSpawn), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000259<<8)+13, offsetof(CBasicEffect, m_tmWaitAfterDeath), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000259<<8)+20, offsetof(CBasicEffect, m_bLightSource), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANIMOBJECT, NULL, (0x00000259<<8)+21, offsetof(CBasicEffect, m_aoLightAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000259<<8)+22, offsetof(CBasicEffect, m_iLightAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x00000259<<8)+23, offsetof(CBasicEffect, m_colMultiplyColor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000259<<8)+30, offsetof(CBasicEffect, m_soEffect), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000259<<8)+31, offsetof(CBasicEffect, m_fSoundTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EffectParticlesType_enum, (0x00000259<<8)+40, offsetof(CBasicEffect, m_eptType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000259<<8)+41, offsetof(CBasicEffect, m_tmWhenShot), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000259<<8)+42, offsetof(CBasicEffect, m_vGravity), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000259<<8)+255, offsetof(CBasicEffect, m_penPrediction), "", 0, 0, 0), +}; +#define CBasicEffect_propertiesct ARRAYCOUNT(CBasicEffect_properties) + +CEntityComponent CBasicEffect_components[] = { +#define MDL_ROCKET_EXPLOSION ((0x00000259<<8)+1) + CEntityComponent(ECT_MODEL, MDL_ROCKET_EXPLOSION, "EFNM" "Models\\Effects\\ExplosionRocket\\ExplosionRocket.mdl"), +#define MDL_ROCKET3D_EXPLOSION ((0x00000259<<8)+2) + CEntityComponent(ECT_MODEL, MDL_ROCKET3D_EXPLOSION, "EFNM" "Models\\Effects\\ExplosionRocket\\ExplosionRocket3D.mdl"), +#define TXT_ROCKET_EXPLOSION ((0x00000259<<8)+3) + CEntityComponent(ECT_TEXTURE, TXT_ROCKET_EXPLOSION, "EFNM" "Models\\Effects\\Explosionrocket\\Texture.tex"), +#define MDL_GRENADE_EXPLOSION ((0x00000259<<8)+4) + CEntityComponent(ECT_MODEL, MDL_GRENADE_EXPLOSION, "EFNM" "Models\\Effects\\ExplosionGrenade\\ExplosionGrenade.mdl"), +#define MDL_GRENADE3D_EXPLOSION ((0x00000259<<8)+5) + CEntityComponent(ECT_MODEL, MDL_GRENADE3D_EXPLOSION, "EFNM" "Models\\Effects\\ExplosionGrenade\\ExplosionGrenade3D.mdl"), +#define TXT_GRENADE_EXPLOSION ((0x00000259<<8)+6) + CEntityComponent(ECT_TEXTURE, TXT_GRENADE_EXPLOSION, "EFNM" "Models\\Effects\\ExplosionGrenade\\Texture.tex"), +#define MDL_PARTICLES_EXPLOSION ((0x00000259<<8)+7) + CEntityComponent(ECT_MODEL, MDL_PARTICLES_EXPLOSION, "EFNM" "Models\\Effects\\ExplosionParticles\\Particles.mdl"), +#define MDL_PARTICLES3D_EXPLOSION ((0x00000259<<8)+8) + CEntityComponent(ECT_MODEL, MDL_PARTICLES3D_EXPLOSION, "EFNM" "Models\\Effects\\ExplosionParticles\\Particles3D.mdl"), +#define TXT_PARTICLES_EXPLOSION ((0x00000259<<8)+9) + CEntityComponent(ECT_TEXTURE, TXT_PARTICLES_EXPLOSION, "EFNM" "Models\\Effects\\ExplosionParticles\\Texture.tex"), +#define SOUND_EXPLOSION ((0x00000259<<8)+10) + CEntityComponent(ECT_SOUND, SOUND_EXPLOSION, "EFNM" "Sounds\\Weapons\\_Explosion02.wav"), +#define MDL_CANNON_EXPLOSION ((0x00000259<<8)+11) + CEntityComponent(ECT_MODEL, MDL_CANNON_EXPLOSION, "EFNM" "Models\\Effects\\ExplosionGrenade\\ExplosionGrenade.mdl"), +#define MDL_CANNON3D_EXPLOSION ((0x00000259<<8)+12) + CEntityComponent(ECT_MODEL, MDL_CANNON3D_EXPLOSION, "EFNM" "Models\\Effects\\ExplosionGrenade\\ExplosionGrenade3D.mdl"), +#define TXT_CANNON_EXPLOSION ((0x00000259<<8)+13) + CEntityComponent(ECT_TEXTURE, TXT_CANNON_EXPLOSION, "EFNM" "Models\\Effects\\ExplosionGrenade\\Texture.tex"), +#define MODEL_BULLET_HIT ((0x00000259<<8)+15) + CEntityComponent(ECT_MODEL, MODEL_BULLET_HIT, "EFNM" "Models\\Effects\\BulletParticles\\BulletParticles.mdl"), +#define TEXTURE_BULLET_HIT ((0x00000259<<8)+16) + CEntityComponent(ECT_TEXTURE, TEXTURE_BULLET_HIT, "EFNM" "Models\\Effects\\BulletParticles\\BulletParticles.tex"), +#define MODEL_BULLET_STAIN ((0x00000259<<8)+18) + CEntityComponent(ECT_MODEL, MODEL_BULLET_STAIN, "EFNM" "Models\\Effects\\BulletOnTheWall\\Bullet.mdl"), +#define TEXTURE_BULLET_STAIN ((0x00000259<<8)+19) + CEntityComponent(ECT_TEXTURE, TEXTURE_BULLET_STAIN, "EFNM" "Models\\Effects\\BulletOnTheWall\\Bullet.tex"), +#define TEXTURE_BULLET_TRAIL ((0x00000259<<8)+70) + CEntityComponent(ECT_TEXTURE, TEXTURE_BULLET_TRAIL, "EFNM" "Models\\Effects\\BulletTrail\\BulletTrail.tex"), +#define MODEL_BULLET_TRAIL ((0x00000259<<8)+71) + CEntityComponent(ECT_MODEL, MODEL_BULLET_TRAIL, "EFNM" "Models\\Effects\\BulletTrail\\BulletTrail.mdl"), +#define SOUND_BULLET_STONE ((0x00000259<<8)+90) + CEntityComponent(ECT_SOUND, SOUND_BULLET_STONE, "EFNM" "Sounds\\Weapons\\_BulletHitWall.wav"), +#define SOUND_BULLET_SAND ((0x00000259<<8)+91) + CEntityComponent(ECT_SOUND, SOUND_BULLET_SAND, "EFNM" "Sounds\\Weapons\\BulletHitSand.wav"), +#define SOUND_BULLET_WATER ((0x00000259<<8)+92) + CEntityComponent(ECT_SOUND, SOUND_BULLET_WATER, "EFNM" "Sounds\\Weapons\\BulletHitWater.wav"), +#define SOUND_BULLET_FLESH ((0x00000259<<8)+93) + CEntityComponent(ECT_SOUND, SOUND_BULLET_FLESH, "EFNM" "Sounds\\Weapons\\_BulletHitFlesh.wav"), +#define TEXTURE_BULLET_SAND ((0x00000259<<8)+94) + CEntityComponent(ECT_TEXTURE, TEXTURE_BULLET_SAND, "EFNM" "Models\\Effects\\BulletOnTheWall\\BulletSand.tex"), +#define SOUND_BULLET_GRASS ((0x00000259<<8)+95) + CEntityComponent(ECT_SOUND, SOUND_BULLET_GRASS, "EFNM" "SoundsMP\\Weapons\\BulletHitGrass.wav"), +#define SOUND_BULLET_WOOD ((0x00000259<<8)+96) + CEntityComponent(ECT_SOUND, SOUND_BULLET_WOOD, "EFNM" "SoundsMP\\Weapons\\BulletHitWood.wav"), +#define SOUND_BULLET_SNOW ((0x00000259<<8)+97) + CEntityComponent(ECT_SOUND, SOUND_BULLET_SNOW, "EFNM" "SoundsMP\\Weapons\\BulletHitSnow.wav"), +#define MODEL_BLOOD_EXPLODE ((0x00000259<<8)+21) + CEntityComponent(ECT_MODEL, MODEL_BLOOD_EXPLODE, "EFNM" "Models\\Effects\\BloodCloud\\BloodCloud.mdl"), +#define TEXTURE_BLOOD_EXPLODE ((0x00000259<<8)+22) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLOOD_EXPLODE, "EFNM" "Models\\Effects\\BloodCloud\\BloodCloud.tex"), +#define MODEL_BLOOD_STAIN ((0x00000259<<8)+23) + CEntityComponent(ECT_MODEL, MODEL_BLOOD_STAIN, "EFNM" "Models\\Effects\\BloodOnTheWall01\\Blood.mdl"), +#define TEXTURE_BLOOD_STAIN1 ((0x00000259<<8)+24) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLOOD_STAIN1, "EFNM" "Models\\Effects\\BloodOnTheWall01\\BloodStain01.tex"), +#define TEXTURE_BLOOD_STAIN2 ((0x00000259<<8)+25) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLOOD_STAIN2, "EFNM" "Models\\Effects\\BloodOnTheWall01\\BloodStain02.tex"), +#define TEXTURE_BLOOD_STAIN3 ((0x00000259<<8)+26) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLOOD_STAIN3, "EFNM" "Models\\Effects\\BloodOnTheWall01\\BloodStain03.tex"), +#define TEXTURE_BLOOD_STAIN4 ((0x00000259<<8)+27) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLOOD_STAIN4, "EFNM" "Models\\Effects\\BloodOnTheWall01\\BloodStain04.tex"), +#define TEXTURE_BLOOD_SPILL1 ((0x00000259<<8)+28) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLOOD_SPILL1, "EFNM" "Models\\Effects\\BloodOnTheWall01\\BloodSpill02.tex"), +#define TEXTURE_BLOOD_SPILL2 ((0x00000259<<8)+29) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLOOD_SPILL2, "EFNM" "Models\\Effects\\BloodOnTheWall01\\BloodSpill05.tex"), +#define TEXTURE_BLOOD_SPILL3 ((0x00000259<<8)+30) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLOOD_SPILL3, "EFNM" "Models\\Effects\\BloodOnTheWall01\\BloodSpill06.tex"), +#define TEXTURE_BLOOD_FLOWER1 ((0x00000259<<8)+31) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLOOD_FLOWER1, "EFNM" "Models\\Effects\\Flowers\\Flowers1s.tex"), +#define TEXTURE_BLOOD_FLOWER2 ((0x00000259<<8)+32) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLOOD_FLOWER2, "EFNM" "Models\\Effects\\Flowers\\Flowers2s.tex"), +#define TEXTURE_BLOOD_FLOWER3 ((0x00000259<<8)+33) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLOOD_FLOWER3, "EFNM" "Models\\Effects\\Flowers\\Flowers3s.tex"), +#define MODEL_SHOCKWAVE ((0x00000259<<8)+40) + CEntityComponent(ECT_MODEL, MODEL_SHOCKWAVE, "EFNM" "Models\\Effects\\ShockWave01\\ShockWave.mdl"), +#define TEXTURE_SHOCKWAVE ((0x00000259<<8)+41) + CEntityComponent(ECT_TEXTURE, TEXTURE_SHOCKWAVE, "EFNM" "Models\\Effects\\ShockWave01\\Textures\\ShockWave.tex"), +#define MODEL_CANNONSHOCKWAVE ((0x00000259<<8)+42) + CEntityComponent(ECT_MODEL, MODEL_CANNONSHOCKWAVE, "EFNM" "Models\\Effects\\ShockWave01\\ShockWave.mdl"), +#define TEXTURE_CANNONSHOCKWAVE ((0x00000259<<8)+43) + CEntityComponent(ECT_TEXTURE, TEXTURE_CANNONSHOCKWAVE, "EFNM" "Models\\Effects\\ShockWave01\\Textures\\ShockWave.tex"), +#define MODEL_EXPLOSION_STAIN ((0x00000259<<8)+45) + CEntityComponent(ECT_MODEL, MODEL_EXPLOSION_STAIN, "EFNM" "Models\\Effects\\BurnedStainOnTheWall\\BurnedStainOnTheWall.mdl"), +#define TEXTURE_EXPLOSION_STAIN ((0x00000259<<8)+46) + CEntityComponent(ECT_TEXTURE, TEXTURE_EXPLOSION_STAIN, "EFNM" "Models\\Effects\\BurnedStainOnTheWall\\BurnedStainOnTheWall.tex"), +#define MODEL_CANNON_EXPLOSION_STAIN ((0x00000259<<8)+47) + CEntityComponent(ECT_MODEL, MODEL_CANNON_EXPLOSION_STAIN, "EFNM" "Models\\Effects\\BurnedStainOnTheWall\\BurnedStainOnTheWall.mdl"), +#define TEXTURE_CANNON_EXPLOSION_STAIN ((0x00000259<<8)+48) + CEntityComponent(ECT_TEXTURE, TEXTURE_CANNON_EXPLOSION_STAIN, "EFNM" "Models\\Effects\\BurnedStainOnTheWall\\BurnedStainOnTheWall.tex"), +#define MODEL_LASERWAVE ((0x00000259<<8)+50) + CEntityComponent(ECT_MODEL, MODEL_LASERWAVE, "EFNM" "Models\\Effects\\ShockWaveGreen\\ShockWaveGreen.mdl"), +#define TEXTURE_LASERWAVE ((0x00000259<<8)+51) + CEntityComponent(ECT_TEXTURE, TEXTURE_LASERWAVE, "EFNM" "Models\\Effects\\ShockWaveGreen\\ShockWaveGreen.tex"), +#define MODEL_TELEPORT_EFFECT ((0x00000259<<8)+61) + CEntityComponent(ECT_MODEL, MODEL_TELEPORT_EFFECT, "EFNM" "Models\\Effects\\Teleport01\\Teleport.mdl"), +#define TEXTURE_TELEPORT_EFFECT ((0x00000259<<8)+62) + CEntityComponent(ECT_TEXTURE, TEXTURE_TELEPORT_EFFECT, "EFNM" "Textures\\Effects\\Effect01\\Effect.tex"), +#define SOUND_TELEPORT ((0x00000259<<8)+63) + CEntityComponent(ECT_SOUND, SOUND_TELEPORT, "EFNM" "Sounds\\Misc\\Teleport.wav"), +#define SOUND_GIZMO_SPLASH ((0x00000259<<8)+80) + CEntityComponent(ECT_SOUND, SOUND_GIZMO_SPLASH, "EFNM" "Models\\Enemies\\Gizmo\\Sounds\\Death.wav"), +#define TEXTURE_WATER_WAVE ((0x00000259<<8)+100) + CEntityComponent(ECT_TEXTURE, TEXTURE_WATER_WAVE, "EFNM" "Models\\Effects\\ShockWave01\\Textures\\WaterWave.tex"), +}; +#define CBasicEffect_componentsct ARRAYCOUNT(CBasicEffect_components) + +CEventHandlerEntry CBasicEffect_handlers[] = { + {1, -1, CEntity::pEventHandler(&CBasicEffect:: +#line 1346 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +Main),DEBUGSTRING("CBasicEffect::Main")}, + {0x02590001, -1, CEntity::pEventHandler(&CBasicEffect::H0x02590001_Main_01), DEBUGSTRING("CBasicEffect::H0x02590001_Main_01")}, + {0x02590002, -1, CEntity::pEventHandler(&CBasicEffect::H0x02590002_Main_02), DEBUGSTRING("CBasicEffect::H0x02590002_Main_02")}, + {0x02590003, -1, CEntity::pEventHandler(&CBasicEffect:: +#line 1444 "D:/SE1_GPL/Sources/EntitiesMP/BasicEffects.es" +EffectLoop),DEBUGSTRING("CBasicEffect::EffectLoop")}, + {0x02590004, -1, CEntity::pEventHandler(&CBasicEffect::H0x02590004_EffectLoop_01), DEBUGSTRING("CBasicEffect::H0x02590004_EffectLoop_01")}, + {0x02590005, -1, CEntity::pEventHandler(&CBasicEffect::H0x02590005_EffectLoop_02), DEBUGSTRING("CBasicEffect::H0x02590005_EffectLoop_02")}, + {0x02590006, -1, CEntity::pEventHandler(&CBasicEffect::H0x02590006_EffectLoop_03), DEBUGSTRING("CBasicEffect::H0x02590006_EffectLoop_03")}, + {0x02590007, -1, CEntity::pEventHandler(&CBasicEffect::H0x02590007_EffectLoop_04), DEBUGSTRING("CBasicEffect::H0x02590007_EffectLoop_04")}, + {0x02590008, -1, CEntity::pEventHandler(&CBasicEffect::H0x02590008_EffectLoop_05), DEBUGSTRING("CBasicEffect::H0x02590008_EffectLoop_05")}, + {0x02590009, -1, CEntity::pEventHandler(&CBasicEffect::H0x02590009_EffectLoop_06), DEBUGSTRING("CBasicEffect::H0x02590009_EffectLoop_06")}, + {0x0259000a, -1, CEntity::pEventHandler(&CBasicEffect::H0x0259000a_EffectLoop_07), DEBUGSTRING("CBasicEffect::H0x0259000a_EffectLoop_07")}, + {0x0259000b, -1, CEntity::pEventHandler(&CBasicEffect::H0x0259000b_EffectLoop_08), DEBUGSTRING("CBasicEffect::H0x0259000b_EffectLoop_08")}, + {0x0259000c, -1, CEntity::pEventHandler(&CBasicEffect::H0x0259000c_EffectLoop_09), DEBUGSTRING("CBasicEffect::H0x0259000c_EffectLoop_09")}, + {0x0259000d, -1, CEntity::pEventHandler(&CBasicEffect::H0x0259000d_EffectLoop_10), DEBUGSTRING("CBasicEffect::H0x0259000d_EffectLoop_10")}, + {0x0259000e, -1, CEntity::pEventHandler(&CBasicEffect::H0x0259000e_EffectLoop_11), DEBUGSTRING("CBasicEffect::H0x0259000e_EffectLoop_11")}, + {0x0259000f, -1, CEntity::pEventHandler(&CBasicEffect::H0x0259000f_EffectLoop_12), DEBUGSTRING("CBasicEffect::H0x0259000f_EffectLoop_12")}, +}; +#define CBasicEffect_handlersct ARRAYCOUNT(CBasicEffect_handlers) + +CEntity *CBasicEffect_New(void) { return new CBasicEffect; }; +void CBasicEffect_OnInitClass(void) {}; +void CBasicEffect_OnEndClass(void) {}; +void CBasicEffect_OnPrecache(CDLLEntityClass *pdec, INDEX iUser); +void CBasicEffect_OnWorldEnd(CWorld *pwo) {}; +void CBasicEffect_OnWorldInit(CWorld *pwo) {}; +void CBasicEffect_OnWorldTick(CWorld *pwo) {}; +void CBasicEffect_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CBasicEffect, CRationalEntity, "BasicEffect", "", 0x00000259); +DECLARE_CTFILENAME(_fnmCBasicEffect_tbn, ""); diff --git a/Sources/EntitiesMP/Beast.cpp b/Sources/EntitiesMP/Beast.cpp new file mode 100644 index 0000000..e51e94e --- /dev/null +++ b/Sources/EntitiesMP/Beast.cpp @@ -0,0 +1,1043 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 5 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" + +#include "StdH.h" +#include "Models/Enemies/Beast/Beast.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" + +#include +#include +#line 21 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" + +static FLOAT _tmLastStandingAnim =0.0f; +#define BEAST_STRETCH 2.0f +#define BIG_BEAST_STRETCH 12.0f +#define HUGE_BEAST_STRETCH 30.0f + +// info structure +static EntityInfo eiBeastHuge = { + EIBT_FLESH, 10000.0f, + 0.0f, 2.0f*HUGE_BEAST_STRETCH, 0.0f, // source (eyes) + 0.0f, 1.5f*HUGE_BEAST_STRETCH, 0.0f, // target (body) +}; +static EntityInfo eiBeastNormal = { + EIBT_FLESH, 1500.0f, + 0.0f, 2.0f*BEAST_STRETCH, 0.0f, // source (eyes) + 0.0f, 1.5f*BEAST_STRETCH, 0.0f, // target (body) +}; +static EntityInfo eiBeastBig = { + EIBT_FLESH, 5000.0f, + 0.0f, 2.0f*BIG_BEAST_STRETCH, 0.0f, // source (eyes) + 0.0f, 1.5f*BIG_BEAST_STRETCH, 0.0f, // target (body) +}; + +void CBeast::SetDefaultProperties(void) { + m_bcType = BT_NORMAL ; + m_iCounter = 0; + m_bBeBoss = FALSE ; + CEnemyBase::SetDefaultProperties(); +} + CTString CBeast::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +CTString str ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +str . PrintF (TRANS ("A Reptiloid killed %s") , strPlayerName ); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return str ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + const CTFileName & CBeast::GetComputerMessageName(void)const { +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +static DECLARE_CTFILENAME (fnmNormal , "Data\\Messages\\Enemies\\BeastNormal.txt"); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +static DECLARE_CTFILENAME (fnmBig , "Data\\Messages\\Enemies\\BeastBig.txt"); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +static DECLARE_CTFILENAME (fnmHuge , "DataMP\\Messages\\Enemies\\BeastBiggest.txt"); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +switch(m_bcType ){ +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +default : ASSERT (FALSE ); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +case BT_NORMAL : return fnmNormal ; +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +case BT_BIG : return fnmBig ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +case BT_HUGE : return fnmHuge ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::Precache(void) { +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +CEnemyBase :: Precache (); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheSound (SOUND_IDLE ); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheSound (SOUND_SIGHT ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheSound (SOUND_WOUND ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheSound (SOUND_ANGER ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheSound (SOUND_FIRE ); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheSound (SOUND_KICK ); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheModel (MODEL_BEAST ); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheTexture (TEXTURE_BEAST_NORMAL ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheTexture (TEXTURE_BEAST_BIG ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_NORMAL ){ +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheSound (SOUND_DEATH ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheClass (CLASS_PROJECTILE , PRT_BEAST_PROJECTILE ); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else { +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheSound (SOUND_DEATHBIG ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PrecacheClass (CLASS_PROJECTILE , PRT_BEAST_BIG_PROJECTILE ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void * CBeast::GetEntityInfo(void) { +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_NORMAL ){ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return & eiBeastNormal ; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else if(m_bcType == BT_HUGE ){ +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return & eiBeastHuge ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else { +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return & eiBeastBig ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::ShakeItBaby(FLOAT tmShaketime,FLOAT fPower) +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(pwsc != NULL ){ +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +pwsc -> m_tmShakeStarted = tmShaketime ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +pwsc -> m_vShakePos = GetPlacement () . pl_PositionVector ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +pwsc -> m_fShakeFalloff = 400.0f; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +pwsc -> m_fShakeFade = 3.0f; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +pwsc -> m_fShakeIntensityZ = 0.0f; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +pwsc -> m_tmShakeFrequencyZ = 5.0f; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +pwsc -> m_fShakeIntensityY = 0.1f * fPower ; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +pwsc -> m_tmShakeFrequencyY = 5.0f; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +pwsc -> m_fShakeIntensityB = 2.5f * fPower ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +pwsc -> m_tmShakeFrequencyB = 7.2f; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +pwsc -> m_bShakeFadeIn = FALSE ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +FLOAT CBeast::GetCrushHealth(void) +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_BIG ){ +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return 100.0f; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else if(m_bcType == BT_HUGE ){ +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return 200.0f; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return 0.0f; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +BOOL CBeast::ForcesCannonballToExplode(void) +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return TRUE ; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(dmtType == DMT_BULLET && fDamageAmmount > 100.0f) +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +fDamageAmmount *= 0.5f; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_BIG && dmtType == DMT_CANNONBALL ) +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +fDamageAmmount *= 0.3333f; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(! IsOfClass (penInflictor , "Beast")){ +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +INDEX CBeast::AnimForDamage(FLOAT fDamage) { +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +INDEX iAnim ; +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if((m_bcType == BT_BIG || m_bcType == BT_HUGE ) && GetHealth () <= m_fMaxHealth / 2){ +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +iAnim = BEAST_ANIM_ANGER ; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else { +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +iAnim = BEAST_ANIM_WOUND ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (iAnim , 0); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return iAnim ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +INDEX CBeast::AnimForDeath(void) { +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +INDEX iAnim ; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_BIG || m_bcType == BT_HUGE ){ +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +iAnim = BEAST_ANIM_DEATHBIG ; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else { +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +iAnim = BEAST_ANIM_DEATH ; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (iAnim , 0); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return iAnim ; +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +FLOAT CBeast::WaitForDust(FLOAT3D & vStretch) { +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(GetModelObject () -> GetAnim () == BEAST_ANIM_DEATH ) +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +vStretch = FLOAT3D (1 , 1 , 2) * 2.0f; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return 0.3f; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return - 1.0f; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::DeathNotify(void) { +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ChangeCollisionBoxIndexWhenPossible (BEAST_COLLISION_BOX_DEATH ); +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +en_fDensity = 500.0f; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::StandingAnim(void) { +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +_tmLastStandingAnim = _pTimer -> CurrentTick (); +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (BEAST_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::WalkingAnim(void) { +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(_pTimer -> CurrentTick () >= _tmLastStandingAnim - _pTimer -> TickQuantum && +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +_pTimer -> CurrentTick () <= _tmLastStandingAnim + _pTimer -> TickQuantum ) +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_BIG || m_bcType == BT_HUGE ){ +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (BEAST_ANIM_WALKBIG , AOF_LOOPING | AOF_NORESTART ); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else { +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (BEAST_ANIM_WALK , AOF_LOOPING | AOF_NORESTART ); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::RunningAnim(void) { +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +WalkingAnim (); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::RotatingAnim(void) { +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +WalkingAnim (); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::IdleSound(void) { +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::SightSound(void) { +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::WoundSound(void) { +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if((m_bcType == BT_BIG || m_bcType == BT_HUGE ) && GetHealth () <= m_fMaxHealth / 2){ +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_ANGER , SOF_3D ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else { +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::DeathSound(void) { +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_NORMAL ){ +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else { +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_DEATHBIG , SOF_3D ); +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} + +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void CBeast::EnemyPostInit(void) +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_soSound . Set3DParameters (160.0f , 50.0f , 2.0f , 1.0f); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +BOOL CBeast:: +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Death(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBeast_Death + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBeast::Death expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_NORMAL ){ +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Death, FALSE, EVoid());return TRUE; +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StopMoving (); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +DeathSound (); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +LeaveStain (TRUE ); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetPhysicsFlags (EPF_MODEL_CORPSE ); +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetCollisionFlags (ECF_CORPSE ); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +RemoveFromFuss (); +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +DeathNotify (); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +AnimForDeath (); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(0.9f); +Jump(STATE_CURRENT, 0x01500001, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500001_Death_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01500002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500002_Death_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500002 +; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_BIG ){ +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ShakeItBaby (_pTimer -> CurrentTick () , 2.0f); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else { +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ShakeItBaby (_pTimer -> CurrentTick () , 3.0f); +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(2.3f - 0.9f); +Jump(STATE_CURRENT, 0x01500003, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500003_Death_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01500004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500004_Death_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500004 +; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_BIG ){ +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ShakeItBaby (_pTimer -> CurrentTick () , 5.0f); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else { +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ShakeItBaby (_pTimer -> CurrentTick () , 7.0f); +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +CPlacement3D plFX = GetPlacement (); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ESpawnEffect ese ; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ese . vStretch = FLOAT3D (1 , 1 , 2) * 15.0f; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ese . vNormal = FLOAT3D (0 , 1 , 0); +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ese . betType = BET_DUST_FALL ; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +CPlacement3D plSmoke = plFX ; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +plSmoke . pl_PositionVector += FLOAT3D (0 , 0.35f * ese . vStretch (2) , 0); +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +CEntityPointer penFX = CreateEntity (plSmoke , CLASS_BASIC_EFFECT ); +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +penFX -> Initialize (ese ); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (BEAST_ANIM_DEATHBIG ) - 2.3f); +Jump(STATE_CURRENT, 0x01500005, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500005_Death_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01500006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500006_Death_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500006 +; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Return(STATE_CURRENT,EEnd ()); +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CBeast:: +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBeast_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBeast::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (BEAST_ANIM_WALKTOIDLE , AOF_SMOOTHCHANGE ); +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x01500008, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500008_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01500009, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500009_Fire_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500009 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(!(m_bcType == BT_NORMAL )){ Jump(STATE_CURRENT,0x01500010, FALSE, EInternal());return TRUE;} +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (BEAST_ANIM_ATTACK , AOF_SMOOTHCHANGE ); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x0150000a, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x0150000a_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0150000b, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CBeast::H0x0150000b_Fire_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150000b +const EReturn&__e= (EReturn&)__eeInput; +; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D ); +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(0.51f); +Jump(STATE_CURRENT, 0x0150000c, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x0150000c_Fire_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150000c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0150000d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x0150000d_Fire_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150000d +; +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ShootProjectile (PRT_BEAST_PROJECTILE , FLOAT3D (0.0f , 1.5f * BEAST_STRETCH , 0.0f) , +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ANGLE3D (AngleDeg ((FRnd () - 0.5) * 30.0f) , AngleDeg (FRnd () * 10.0f) , 0)); +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(0.3f); +Jump(STATE_CURRENT, 0x0150000e, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x0150000e_Fire_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0150000f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x0150000f_Fire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150000f +;Jump(STATE_CURRENT,0x01500010, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x01500010_Fire_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500010 + +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(!(m_bcType == BT_BIG )){ Jump(STATE_CURRENT,0x0150001f, FALSE, EInternal());return TRUE;} +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(!(GetHealth () <= m_fMaxHealth / 2)){ Jump(STATE_CURRENT,0x01500017, FALSE, EInternal());return TRUE;} +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_iCounter = 0; +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Jump(STATE_CURRENT,0x01500015, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x01500015_Fire_14(const CEntityEvent &__eeInput) +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500015 +if(!(m_iCounter < 6)){ Jump(STATE_CURRENT,0x01500016, FALSE, EInternal());return TRUE;} +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (BEAST_ANIM_ATTACKFAST , AOF_SMOOTHCHANGE ); +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x01500011, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500011_Fire_10(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500011 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01500012, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500012_Fire_11(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500012 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D ); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(0.34f); +Jump(STATE_CURRENT, 0x01500013, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500013_Fire_12(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500013 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01500014, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500014_Fire_13(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500014 +; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ShootProjectile (PRT_BEAST_BIG_PROJECTILE , FLOAT3D (0.0f , 1.5f * BIG_BEAST_STRETCH , 0.0f) , +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_iCounter ++;Jump(STATE_CURRENT,0x01500015, FALSE, EInternal());return TRUE; +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}BOOL CBeast::H0x01500016_Fire_15(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500016 + +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fAttackFireTime = 7.0f;Jump(STATE_CURRENT,0x01500017, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x01500017_Fire_16(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500017 + +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(!(GetHealth () > m_fMaxHealth / 2)){ Jump(STATE_CURRENT,0x0150001e, FALSE, EInternal());return TRUE;} +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_iCounter = 0; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Jump(STATE_CURRENT,0x0150001c, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x0150001c_Fire_21(const CEntityEvent &__eeInput) +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150001c +if(!(m_iCounter < 3)){ Jump(STATE_CURRENT,0x0150001d, FALSE, EInternal());return TRUE;} +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (BEAST_ANIM_ATTACK , AOF_SMOOTHCHANGE ); +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x01500018, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500018_Fire_17(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500018 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01500019, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500019_Fire_18(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500019 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D ); +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x0150001a, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x0150001a_Fire_19(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150001a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0150001b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x0150001b_Fire_20(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150001b +; +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ShootProjectile (PRT_BEAST_BIG_PROJECTILE , FLOAT3D (0.0f , 1.5f * BIG_BEAST_STRETCH , 0.0f) , +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_iCounter ++;Jump(STATE_CURRENT,0x0150001c, FALSE, EInternal());return TRUE; +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}BOOL CBeast::H0x0150001d_Fire_22(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150001d +Jump(STATE_CURRENT,0x0150001e, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x0150001e_Fire_23(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150001e +Jump(STATE_CURRENT,0x0150001f, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x0150001f_Fire_24(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150001f + +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(!(m_bcType == BT_HUGE )){ Jump(STATE_CURRENT,0x0150002e, FALSE, EInternal());return TRUE;} +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(!(GetHealth () <= m_fMaxHealth / 2)){ Jump(STATE_CURRENT,0x01500026, FALSE, EInternal());return TRUE;} +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_iCounter = 0; +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Jump(STATE_CURRENT,0x01500024, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x01500024_Fire_29(const CEntityEvent &__eeInput) +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500024 +if(!(m_iCounter < 6)){ Jump(STATE_CURRENT,0x01500025, FALSE, EInternal());return TRUE;} +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (BEAST_ANIM_ATTACKFAST , AOF_SMOOTHCHANGE ); +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x01500020, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500020_Fire_25(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500020 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01500021, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500021_Fire_26(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500021 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D ); +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(0.34f); +Jump(STATE_CURRENT, 0x01500022, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500022_Fire_27(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500022 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01500023, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500023_Fire_28(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500023 +; +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ShootProjectile (PRT_BEAST_BIG_PROJECTILE , FLOAT3D (0.0f , 1.5f * HUGE_BEAST_STRETCH , 0.0f) , +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_iCounter ++;Jump(STATE_CURRENT,0x01500024, FALSE, EInternal());return TRUE; +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}BOOL CBeast::H0x01500025_Fire_30(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500025 + +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fAttackFireTime = 7.0f;Jump(STATE_CURRENT,0x01500026, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x01500026_Fire_31(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500026 + +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(!(GetHealth () > m_fMaxHealth / 2)){ Jump(STATE_CURRENT,0x0150002d, FALSE, EInternal());return TRUE;} +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_iCounter = 0; +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Jump(STATE_CURRENT,0x0150002b, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x0150002b_Fire_36(const CEntityEvent &__eeInput) +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150002b +if(!(m_iCounter < 3)){ Jump(STATE_CURRENT,0x0150002c, FALSE, EInternal());return TRUE;} +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (BEAST_ANIM_ATTACK , AOF_SMOOTHCHANGE ); +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x01500027, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500027_Fire_32(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500027 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01500028, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500028_Fire_33(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500028 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D ); +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x01500029, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500029_Fire_34(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500029 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0150002a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x0150002a_Fire_35(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150002a +; +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ShootProjectile (PRT_BEAST_BIG_PROJECTILE , FLOAT3D (0.0f , 1.5f * HUGE_BEAST_STRETCH , 0.0f) , +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_iCounter ++;Jump(STATE_CURRENT,0x0150002b, FALSE, EInternal());return TRUE; +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}BOOL CBeast::H0x0150002c_Fire_37(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150002c +Jump(STATE_CURRENT,0x0150002d, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x0150002d_Fire_38(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150002d +Jump(STATE_CURRENT,0x0150002e, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x0150002e_Fire_39(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150002e + +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +MaybeSwitchToAnotherPlayer (); +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(FRnd () / 2 + _pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x0150002f, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x0150002f_Fire_40(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150002f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01500030, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500030_Fire_41(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500030 +; +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(!(m_penEnemy != NULL )){ Jump(STATE_CURRENT,0x01500036, FALSE, EInternal());return TRUE;} +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +FLOAT fEnemyDistance = CalcDist (m_penEnemy ); +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(!(fEnemyDistance > m_fCloseDistance * 1.25f)){ Jump(STATE_CURRENT,0x01500035, FALSE, EInternal());return TRUE;} +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (BEAST_ANIM_IDLETOWALK , AOF_SMOOTHCHANGE ); +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x01500031, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500031_Fire_42(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500031 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01500032, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500032_Fire_43(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500032 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (BEAST_ANIM_IDLETOWALK ) / 2.0f - _pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01500033, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500033_Fire_44(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500033 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01500034, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500034_Fire_45(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500034 +;Jump(STATE_CURRENT,0x01500035, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x01500035_Fire_46(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500035 +Jump(STATE_CURRENT,0x01500036, FALSE, EInternal());return TRUE;}BOOL CBeast::H0x01500036_Fire_47(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500036 + +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Return(STATE_CURRENT,EReturn ()); +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CBeast:: +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBeast_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBeast::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StartModelAnim (BEAST_ANIM_KICK , 0); +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(0.45f); +Jump(STATE_CURRENT, 0x01500038, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x01500038_Hit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500038 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01500039, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x01500039_Hit_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500039 +; +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +PlaySound (m_soSound , SOUND_KICK , SOF_3D ); +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(CalcDist (m_penEnemy ) < m_fCloseDistance ){ +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +vDirection . Normalize (); +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_BIG ){ +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 80.0f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else if(m_bcType == BT_HUGE ){ +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 120.0f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +}else { +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 40.0f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetTimerAfter(0.45f); +Jump(STATE_CURRENT, 0x0150003a, FALSE, EBegin());return TRUE;}BOOL CBeast::H0x0150003a_Hit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150003a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0150003b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBeast::H0x0150003b_Hit_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150003b +; +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +MaybeSwitchToAnotherPlayer (); +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Return(STATE_CURRENT,EReturn ()); +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CBeast:: +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBeast_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBeast::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +InitAsModel (); +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetCollisionFlags (ECF_MODEL ); +#line 491 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +en_fDensity = 1100.0f; +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetModel (MODEL_BEAST ); +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +StandingAnim (); +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fWalkSpeed = FRnd () * 2 + 5.0f; +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 20.0f + 50.0f); +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fCloseRunSpeed = FRnd () + 10.0f; +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 100 + 900.0f); +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fAttackDistance = 500.0f; +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fCloseDistance = 0.0f; +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fStopDistance = 0.0f; +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fCloseFireTime = 1.0f; +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fIgnoreRange = 750.0f; +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_bBoss = m_bBeBoss ; +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fStopDistance = 5.0f; +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fCloseDistance = 7.0f; +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_tmGiveUp = Max (m_tmGiveUp , 10.0f); +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +if(m_bcType == BT_NORMAL ) +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fAttackRunSpeed = 6.0f; +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_aAttackRotateSpeed = AngleDeg (3600.0f); +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetHealth (400.0f); +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetModelMainTexture (TEXTURE_BEAST_NORMAL ); +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fBlowUpAmount = 10000.0f; +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fBodyParts = 4; +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fDamageWounded = 250.0f; +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_iScore = 5000; +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +GetModelObject () -> StretchModel (FLOAT3D (BEAST_STRETCH , BEAST_STRETCH , BEAST_STRETCH )); +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ModelChangeNotify (); +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_sptType = SPT_SLIME ; +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fAttackFireTime = 3.0f; +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +else if(m_bcType == BT_BIG ) +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fAttackRunSpeed = 25.0f; +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_aAttackRotateSpeed = AngleDeg (600.0f); +#line 534 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetHealth (3000.0f); +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetModelMainTexture (TEXTURE_BEAST_BIG ); +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fBlowUpAmount = 10000.0f; +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fBodyParts = 6; +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fDamageWounded = 650.0f; +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_iScore = 25000; +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fStopDistance = 15; +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fCloseDistance = 20; +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +GetModelObject () -> StretchModel (FLOAT3D (BIG_BEAST_STRETCH , BIG_BEAST_STRETCH , BIG_BEAST_STRETCH )); +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ModelChangeNotify (); +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_sptType = SPT_BLOOD ; +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fAttackFireTime = 5.0f; +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +else +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +{ +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fAttackRunSpeed = 35.0f; +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_aAttackRotateSpeed = AngleDeg (600.0f); +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetHealth (6000.0f); +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +SetModelMainTexture (TEXTURE_BEAST_HUGE ); +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fBlowUpAmount = 100000.0f; +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fBodyParts = 6; +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fDamageWounded = 1650.0f; +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_iScore = 40000; +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fStopDistance = 75; +#line 559 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fCloseDistance = 80; +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fAttackDistance = 1000.0f; +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fIgnoreRange = 1200.0f; +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +GetModelObject () -> StretchModel (FLOAT3D (HUGE_BEAST_STRETCH , HUGE_BEAST_STRETCH , HUGE_BEAST_STRETCH )); +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +ModelChangeNotify (); +#line 565 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_sptType = SPT_BLOOD ; +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fAttackFireTime = 5.0f; +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +} +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +m_fMaxHealth = GetHealth (); +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Beast.es b/Sources/EntitiesMP/Beast.es new file mode 100644 index 0000000..478afd1 --- /dev/null +++ b/Sources/EntitiesMP/Beast.es @@ -0,0 +1,574 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +336 + +%{ +#include "StdH.h" +#include "Models/Enemies/Beast/Beast.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/BasicEffects"; + +enum BeastType { + 0 BT_NORMAL "Small", // normal (fighter) + 1 BT_BIG "Big", // big + 2 BT_HUGE "Huge", // huge +}; + +%{ +static FLOAT _tmLastStandingAnim =0.0f; +#define BEAST_STRETCH 2.0f +#define BIG_BEAST_STRETCH 12.0f +#define HUGE_BEAST_STRETCH 30.0f + +// info structure +static EntityInfo eiBeastHuge = { + EIBT_FLESH, 10000.0f, + 0.0f, 2.0f*HUGE_BEAST_STRETCH, 0.0f, // source (eyes) + 0.0f, 1.5f*HUGE_BEAST_STRETCH, 0.0f, // target (body) +}; +static EntityInfo eiBeastNormal = { + EIBT_FLESH, 1500.0f, + 0.0f, 2.0f*BEAST_STRETCH, 0.0f, // source (eyes) + 0.0f, 1.5f*BEAST_STRETCH, 0.0f, // target (body) +}; +static EntityInfo eiBeastBig = { + EIBT_FLESH, 5000.0f, + 0.0f, 2.0f*BIG_BEAST_STRETCH, 0.0f, // source (eyes) + 0.0f, 1.5f*BIG_BEAST_STRETCH, 0.0f, // target (body) +}; +%} + +class CBeast : CEnemyBase { +name "Beast"; +thumbnail "Thumbnails\\Beast.tbn"; + +properties: + 1 enum BeastType m_bcType "Character" 'C' = BT_NORMAL, + 2 INDEX m_iCounter = 0, + 3 BOOL m_bBeBoss "Boss" 'B' = FALSE, + +components: + 0 class CLASS_BASE "Classes\\EnemyBase.ecl", + 1 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 2 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + + 10 model MODEL_BEAST "Models\\Enemies\\Beast\\Beast.mdl", + 11 texture TEXTURE_BEAST_NORMAL "Models\\Enemies\\Beast\\Beast.tex", + 12 texture TEXTURE_BEAST_BIG "Models\\Enemies\\Beast\\BeastBig.tex", + 13 texture TEXTURE_BEAST_HUGE "ModelsMP\\Enemies\\Beast\\BeastBiggest.tex", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "Models\\Enemies\\Beast\\Sounds\\Idle.wav", + 51 sound SOUND_SIGHT "Models\\Enemies\\Beast\\Sounds\\Sight.wav", + 52 sound SOUND_WOUND "Models\\Enemies\\Beast\\Sounds\\Wound.wav", + 53 sound SOUND_FIRE "Models\\Enemies\\Beast\\Sounds\\Fire.wav", + 54 sound SOUND_KICK "Models\\Enemies\\Beast\\Sounds\\Kick.wav", + 55 sound SOUND_DEATH "Models\\Enemies\\Beast\\Sounds\\Death.wav", + 56 sound SOUND_DEATHBIG "Models\\Enemies\\Beast\\Sounds\\DeathBig.wav", + 57 sound SOUND_ANGER "Models\\Enemies\\Beast\\Sounds\\Anger.wav", + +functions: + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("A Reptiloid killed %s"), strPlayerName); + return str; + } + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnmNormal, "Data\\Messages\\Enemies\\BeastNormal.txt"); + static DECLARE_CTFILENAME(fnmBig, "Data\\Messages\\Enemies\\BeastBig.txt"); + static DECLARE_CTFILENAME(fnmHuge, "DataMP\\Messages\\Enemies\\BeastBiggest.txt"); + switch(m_bcType) { + default: ASSERT(FALSE); + case BT_NORMAL: return fnmNormal; + case BT_BIG: return fnmBig; + case BT_HUGE: return fnmHuge; + } + }; + void Precache(void) { + CEnemyBase::Precache(); + PrecacheSound(SOUND_IDLE ); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_ANGER); + PrecacheSound(SOUND_FIRE); + PrecacheSound(SOUND_KICK); + PrecacheModel(MODEL_BEAST); + PrecacheTexture(TEXTURE_BEAST_NORMAL); + PrecacheTexture(TEXTURE_BEAST_BIG); + if (m_bcType == BT_NORMAL) { + PrecacheSound(SOUND_DEATH); + PrecacheClass(CLASS_PROJECTILE, PRT_BEAST_PROJECTILE); + } else { + PrecacheSound(SOUND_DEATHBIG); + PrecacheClass(CLASS_PROJECTILE, PRT_BEAST_BIG_PROJECTILE); + } + }; + + /* Entity info */ + void *GetEntityInfo(void) { + if (m_bcType == BT_NORMAL) { + return &eiBeastNormal; + } else if (m_bcType == BT_HUGE) { + return &eiBeastHuge; + } else { + return &eiBeastBig; + } + }; + + void ShakeItBaby(FLOAT tmShaketime, FLOAT fPower) + { + CWorldSettingsController *pwsc = GetWSC(this); + if (pwsc!=NULL) { + pwsc->m_tmShakeStarted = tmShaketime; + pwsc->m_vShakePos = GetPlacement().pl_PositionVector; + pwsc->m_fShakeFalloff = 400.0f; + pwsc->m_fShakeFade = 3.0f; + + pwsc->m_fShakeIntensityZ = 0.0f; + pwsc->m_tmShakeFrequencyZ = 5.0f; + pwsc->m_fShakeIntensityY = 0.1f*fPower; + pwsc->m_tmShakeFrequencyY = 5.0f; + pwsc->m_fShakeIntensityB = 2.5f*fPower; + pwsc->m_tmShakeFrequencyB = 7.2f; + + pwsc->m_bShakeFadeIn = FALSE; + } + } + + FLOAT GetCrushHealth(void) + { + if (m_bcType == BT_BIG) { + return 100.0f; + } else if (m_bcType == BT_HUGE) { + return 200.0f; + } + return 0.0f; + } + + BOOL ForcesCannonballToExplode(void) + { + return TRUE; + } + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + + // take less damage from heavy bullets (e.g. sniper) + if(dmtType==DMT_BULLET && fDamageAmmount>100.0f) + { + fDamageAmmount*=0.5f; + } + + // cannonballs inflict less damage then the default + if(m_bcType==BT_BIG && dmtType==DMT_CANNONBALL) + { + fDamageAmmount *= 0.3333f; + } + + // can't harm own class + if (!IsOfClass(penInflictor, "Beast")) { + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + }; + + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim; + if((m_bcType==BT_BIG || m_bcType==BT_HUGE) && GetHealth() <= m_fMaxHealth/2) { + iAnim = BEAST_ANIM_ANGER; + } else { + iAnim = BEAST_ANIM_WOUND; + } + StartModelAnim(iAnim, 0); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + INDEX iAnim; + if(m_bcType==BT_BIG || m_bcType==BT_HUGE) { + iAnim = BEAST_ANIM_DEATHBIG; + } else { + iAnim = BEAST_ANIM_DEATH; + } + + StartModelAnim(iAnim, 0); + return iAnim; + }; + + FLOAT WaitForDust(FLOAT3D &vStretch) { + if(GetModelObject()->GetAnim()==BEAST_ANIM_DEATH) + { + vStretch=FLOAT3D(1,1,2)*2.0f; + return 0.3f; + } + return -1.0f; + }; + + void DeathNotify(void) { + ChangeCollisionBoxIndexWhenPossible(BEAST_COLLISION_BOX_DEATH); + en_fDensity = 500.0f; + }; + + // virtual anim functions + void StandingAnim(void) { + _tmLastStandingAnim = _pTimer->CurrentTick(); + StartModelAnim(BEAST_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + + void WalkingAnim(void) { + if(_pTimer->CurrentTick()>=_tmLastStandingAnim-_pTimer->TickQuantum && + _pTimer->CurrentTick()<=_tmLastStandingAnim+_pTimer->TickQuantum) + { + //BREAKPOINT; + } + + if(m_bcType==BT_BIG || m_bcType==BT_HUGE) { + StartModelAnim(BEAST_ANIM_WALKBIG, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(BEAST_ANIM_WALK, AOF_LOOPING|AOF_NORESTART); + } + }; + + void RunningAnim(void) { + WalkingAnim(); + }; + void RotatingAnim(void) { + WalkingAnim(); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + if((m_bcType==BT_BIG || m_bcType==BT_HUGE) && GetHealth() <= m_fMaxHealth/2) { + PlaySound(m_soSound, SOUND_ANGER, SOF_3D); + } else { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + } + }; + void DeathSound(void) { + if (m_bcType == BT_NORMAL) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + } else { + PlaySound(m_soSound, SOUND_DEATHBIG, SOF_3D); + } + }; + + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + m_soSound.Set3DParameters(160.0f, 50.0f, 2.0f, 1.0f); + }; + +procedures: +/************************************************************ + * D E A T H * + ************************************************************/ + Death(EVoid) : CEnemyBase::Death { + if (m_bcType == BT_NORMAL) { + jump CEnemyBase::Death(); + } + + // stop moving + StopMoving(); + DeathSound(); // death sound + LeaveStain(TRUE); + // set physic flags + SetPhysicsFlags(EPF_MODEL_CORPSE); + SetCollisionFlags(ECF_CORPSE); + SetFlags(GetFlags() | ENF_SEETHROUGH); + // stop making fuss + RemoveFromFuss(); + // death notify (usually change collision box and change body density) + DeathNotify(); + // start death anim + AnimForDeath(); + autowait(0.9f); + if (m_bcType == BT_BIG) { + ShakeItBaby(_pTimer->CurrentTick(), 2.0f); + } else { + ShakeItBaby(_pTimer->CurrentTick(), 3.0f); + } + autowait(2.3f-0.9f); + if (m_bcType == BT_BIG) { + ShakeItBaby(_pTimer->CurrentTick(), 5.0f); + } else { + ShakeItBaby(_pTimer->CurrentTick(), 7.0f); + } + + // spawn dust effect + CPlacement3D plFX=GetPlacement(); + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.vStretch = FLOAT3D(1,1,2)*15.0f; + ese.vNormal = FLOAT3D(0,1,0); + ese.betType = BET_DUST_FALL; + CPlacement3D plSmoke=plFX; + plSmoke.pl_PositionVector+=FLOAT3D(0,0.35f*ese.vStretch(2),0); + CEntityPointer penFX = CreateEntity(plSmoke, CLASS_BASIC_EFFECT); + penFX->Initialize(ese); + + autowait(GetModelObject()->GetAnimLength(BEAST_ANIM_DEATHBIG)-2.3f); + return EEnd(); + }; + +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + Fire(EVoid) : CEnemyBase::Fire + { + // wait to finish walk and smooth change to idle + StartModelAnim(BEAST_ANIM_WALKTOIDLE, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + + if( m_bcType == BT_NORMAL) + { + StartModelAnim(BEAST_ANIM_ATTACK, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(0.51f); + + ShootProjectile(PRT_BEAST_PROJECTILE, FLOAT3D( 0.0f, 1.5f*BEAST_STRETCH, 0.0f), + ANGLE3D(AngleDeg((FRnd()-0.5)*30.0f), AngleDeg(FRnd()*10.0f), 0)); + autowait(0.3f); + } + + if(m_bcType == BT_BIG) + { + if( GetHealth() <= m_fMaxHealth/2) + { + m_iCounter = 0; + while ( m_iCounter<6) + { + StartModelAnim(BEAST_ANIM_ATTACKFAST, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(0.34f); + ShootProjectile(PRT_BEAST_BIG_PROJECTILE, FLOAT3D( 0.0f, 1.5f*BIG_BEAST_STRETCH, 0.0f), + ANGLE3D(0.0f, 0.0f, 0.0f)); + //ANGLE3D( AngleDeg(40.0f*Cos(m_iCounter*360.0/6.0f)), AngleDeg(20.0f*Sin(m_iCounter*180.0/6.0f)), 0)); + //autowait(0.15f); + m_iCounter++; + } + m_fAttackFireTime = 7.0f; + } + + if( GetHealth() > m_fMaxHealth/2) + { + m_iCounter = 0; + while ( m_iCounter<3) + { + StartModelAnim(BEAST_ANIM_ATTACK, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(0.5f); + ShootProjectile(PRT_BEAST_BIG_PROJECTILE, FLOAT3D( 0.0f, 1.5f*BIG_BEAST_STRETCH, 0.0f), + ANGLE3D(0.0f, 0.0f, 0.0f)); + //ANGLE3D( AngleDeg(20.0f*Cos(m_iCounter*360.0/3.0f)), AngleDeg(10.0f*Sin(m_iCounter*180.0/3.0f)), 0)); + //ANGLE3D( FRnd()*20.0f-10.0f, FRnd()*10.0f-5.0f, 0)); + //autowait(0.25f); + m_iCounter++; + } + } + } + + if(m_bcType == BT_HUGE) + { + if( GetHealth() <= m_fMaxHealth/2) + { + m_iCounter = 0; + while ( m_iCounter<6) + { + StartModelAnim(BEAST_ANIM_ATTACKFAST, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(0.34f); + ShootProjectile(PRT_BEAST_BIG_PROJECTILE, FLOAT3D( 0.0f, 1.5f*HUGE_BEAST_STRETCH, 0.0f), + ANGLE3D(0.0f, 0.0f, 0.0f)); + //ANGLE3D( AngleDeg(40.0f*Cos(m_iCounter*360.0/6.0f)), AngleDeg(20.0f*Sin(m_iCounter*180.0/6.0f)), 0)); + //autowait(0.15f); + m_iCounter++; + } + m_fAttackFireTime = 7.0f; + } + + if( GetHealth() > m_fMaxHealth/2) + { + m_iCounter = 0; + while ( m_iCounter<3) + { + StartModelAnim(BEAST_ANIM_ATTACK, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(0.5f); + ShootProjectile(PRT_BEAST_BIG_PROJECTILE, FLOAT3D( 0.0f, 1.5f*HUGE_BEAST_STRETCH, 0.0f), + ANGLE3D(0.0f, 0.0f, 0.0f)); + //ANGLE3D( AngleDeg(20.0f*Cos(m_iCounter*360.0/3.0f)), AngleDeg(10.0f*Sin(m_iCounter*180.0/3.0f)), 0)); + //ANGLE3D( FRnd()*20.0f-10.0f, FRnd()*10.0f-5.0f, 0)); + //autowait(0.25f); + m_iCounter++; + } + } + } + + MaybeSwitchToAnotherPlayer(); + + autowait(FRnd()/2 + _pTimer->TickQuantum); + + if( m_penEnemy != NULL) + { + FLOAT fEnemyDistance = CalcDist(m_penEnemy); + if( fEnemyDistance>m_fCloseDistance*1.25f) + { + StartModelAnim(BEAST_ANIM_IDLETOWALK, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + autowait(GetModelObject()->GetAnimLength(BEAST_ANIM_IDLETOWALK)/2.0f - _pTimer->TickQuantum); + } + } + + + return EReturn(); + }; + + // hit enemy + Hit(EVoid) : CEnemyBase::Hit { + // close attack + StartModelAnim(BEAST_ANIM_KICK, 0); + autowait(0.45f); + /* + StartModelAnim(BEAST_ANIM_KICK, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + */ + PlaySound(m_soSound, SOUND_KICK, SOF_3D); + if (CalcDist(m_penEnemy) < m_fCloseDistance) { + FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.Normalize(); + if (m_bcType == BT_BIG) { + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 80.0f, FLOAT3D(0, 0, 0), vDirection); + } else if (m_bcType == BT_HUGE) { + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 120.0f, FLOAT3D(0, 0, 0), vDirection); + } else { + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 40.0f, FLOAT3D(0, 0, 0), vDirection); + } + } + + /* + StartModelAnim(BEAST_ANIM_IDLE, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + */ + autowait(0.45f); + MaybeSwitchToAnotherPlayer(); + return EReturn(); + }; + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + + en_fDensity = 1100.0f; + // set your appearance + SetModel(MODEL_BEAST); + StandingAnim(); + // setup moving speed + m_fWalkSpeed = FRnd()*2 + 5.0f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*20.0f + 50.0f); + m_fCloseRunSpeed = FRnd() + 10.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 900.0f); + // setup attack distances + m_fAttackDistance = 500.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 0.0f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 750.0f; + m_bBoss = m_bBeBoss; + m_fStopDistance = 5.0f; + m_fCloseDistance = 7.0f; + m_tmGiveUp = Max(m_tmGiveUp, 10.0f); + + // damage/explode properties + if (m_bcType == BT_NORMAL) + { + m_fAttackRunSpeed = 6.0f;//6 + m_aAttackRotateSpeed = AngleDeg(3600.0f); + SetHealth(400.0f); + SetModelMainTexture(TEXTURE_BEAST_NORMAL); + m_fBlowUpAmount = 10000.0f; + m_fBodyParts = 4; + m_fDamageWounded = 250.0f; + m_iScore = 5000;//500 + // set stretch factor + GetModelObject()->StretchModel(FLOAT3D(BEAST_STRETCH, BEAST_STRETCH, BEAST_STRETCH)); + ModelChangeNotify(); + m_sptType = SPT_SLIME; + m_fAttackFireTime = 3.0f; + } + else if (m_bcType == BT_BIG) + { + m_fAttackRunSpeed = 25.0f;//8 + m_aAttackRotateSpeed = AngleDeg(600.0f); + SetHealth(3000.0f);//500 + SetModelMainTexture(TEXTURE_BEAST_BIG); + m_fBlowUpAmount = 10000.0f;//500 + m_fBodyParts = 6; + m_fDamageWounded = 650.0f;//500 + m_iScore = 25000; //1000 + m_fStopDistance = 15; + m_fCloseDistance = 20; + // set stretch factor + GetModelObject()->StretchModel(FLOAT3D(BIG_BEAST_STRETCH, BIG_BEAST_STRETCH, BIG_BEAST_STRETCH)); + ModelChangeNotify(); + m_sptType = SPT_BLOOD; + m_fAttackFireTime = 5.0f; + } + else // HUGE + { + m_fAttackRunSpeed = 35.0f;//8 + m_aAttackRotateSpeed = AngleDeg(600.0f); + SetHealth(6000.0f);//500 + SetModelMainTexture(TEXTURE_BEAST_HUGE); + m_fBlowUpAmount = 100000.0f;//500 + m_fBodyParts = 6; + m_fDamageWounded = 1650.0f;//500 + m_iScore = 40000; //1000 + m_fStopDistance = 75; + m_fCloseDistance = 80; + m_fAttackDistance = 1000.0f; + m_fIgnoreRange = 1200.0f; + // set stretch factor + GetModelObject()->StretchModel(FLOAT3D(HUGE_BEAST_STRETCH, HUGE_BEAST_STRETCH, HUGE_BEAST_STRETCH)); + ModelChangeNotify(); + m_sptType = SPT_BLOOD; + m_fAttackFireTime = 5.0f; + } + + m_fMaxHealth = GetHealth(); + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Beast.h b/Sources/EntitiesMP/Beast.h new file mode 100644 index 0000000..fb2a189 --- /dev/null +++ b/Sources/EntitiesMP/Beast.h @@ -0,0 +1,162 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Beast_INCLUDED +#define _EntitiesMP_Beast_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType BeastType_enum; +enum BeastType { + BT_NORMAL = 0, + BT_BIG = 1, + BT_HUGE = 2, +}; +DECL_DLL inline void ClearToDefault(BeastType &e) { e = (BeastType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CBeast_DLLClass; +class CBeast : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum BeastType m_bcType; + INDEX m_iCounter; + BOOL m_bBeBoss; + +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void Precache(void); + +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void * GetEntityInfo(void); + +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void ShakeItBaby(FLOAT tmShaketime,FLOAT fPower); + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +FLOAT GetCrushHealth(void); + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +BOOL ForcesCannonballToExplode(void); + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +INDEX AnimForDeath(void); + +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void DeathNotify(void); + +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void StandingAnim(void); + +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void WalkingAnim(void); + +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void RunningAnim(void); + +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void RotatingAnim(void); + +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void IdleSound(void); + +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void SightSound(void); + +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void WoundSound(void); + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void DeathSound(void); + +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +void EnemyPostInit(void); +#define STATE_CBeast_Death 0x01500000 + BOOL +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Death(const CEntityEvent &__eeInput); + BOOL H0x01500001_Death_01(const CEntityEvent &__eeInput); + BOOL H0x01500002_Death_02(const CEntityEvent &__eeInput); + BOOL H0x01500003_Death_03(const CEntityEvent &__eeInput); + BOOL H0x01500004_Death_04(const CEntityEvent &__eeInput); + BOOL H0x01500005_Death_05(const CEntityEvent &__eeInput); + BOOL H0x01500006_Death_06(const CEntityEvent &__eeInput); +#define STATE_CBeast_Fire 0x01500007 + BOOL +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x01500008_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x01500009_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x0150000a_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x0150000b_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x0150000c_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x0150000d_Fire_06(const CEntityEvent &__eeInput); + BOOL H0x0150000e_Fire_07(const CEntityEvent &__eeInput); + BOOL H0x0150000f_Fire_08(const CEntityEvent &__eeInput); + BOOL H0x01500010_Fire_09(const CEntityEvent &__eeInput); + BOOL H0x01500011_Fire_10(const CEntityEvent &__eeInput); + BOOL H0x01500012_Fire_11(const CEntityEvent &__eeInput); + BOOL H0x01500013_Fire_12(const CEntityEvent &__eeInput); + BOOL H0x01500014_Fire_13(const CEntityEvent &__eeInput); + BOOL H0x01500015_Fire_14(const CEntityEvent &__eeInput); + BOOL H0x01500016_Fire_15(const CEntityEvent &__eeInput); + BOOL H0x01500017_Fire_16(const CEntityEvent &__eeInput); + BOOL H0x01500018_Fire_17(const CEntityEvent &__eeInput); + BOOL H0x01500019_Fire_18(const CEntityEvent &__eeInput); + BOOL H0x0150001a_Fire_19(const CEntityEvent &__eeInput); + BOOL H0x0150001b_Fire_20(const CEntityEvent &__eeInput); + BOOL H0x0150001c_Fire_21(const CEntityEvent &__eeInput); + BOOL H0x0150001d_Fire_22(const CEntityEvent &__eeInput); + BOOL H0x0150001e_Fire_23(const CEntityEvent &__eeInput); + BOOL H0x0150001f_Fire_24(const CEntityEvent &__eeInput); + BOOL H0x01500020_Fire_25(const CEntityEvent &__eeInput); + BOOL H0x01500021_Fire_26(const CEntityEvent &__eeInput); + BOOL H0x01500022_Fire_27(const CEntityEvent &__eeInput); + BOOL H0x01500023_Fire_28(const CEntityEvent &__eeInput); + BOOL H0x01500024_Fire_29(const CEntityEvent &__eeInput); + BOOL H0x01500025_Fire_30(const CEntityEvent &__eeInput); + BOOL H0x01500026_Fire_31(const CEntityEvent &__eeInput); + BOOL H0x01500027_Fire_32(const CEntityEvent &__eeInput); + BOOL H0x01500028_Fire_33(const CEntityEvent &__eeInput); + BOOL H0x01500029_Fire_34(const CEntityEvent &__eeInput); + BOOL H0x0150002a_Fire_35(const CEntityEvent &__eeInput); + BOOL H0x0150002b_Fire_36(const CEntityEvent &__eeInput); + BOOL H0x0150002c_Fire_37(const CEntityEvent &__eeInput); + BOOL H0x0150002d_Fire_38(const CEntityEvent &__eeInput); + BOOL H0x0150002e_Fire_39(const CEntityEvent &__eeInput); + BOOL H0x0150002f_Fire_40(const CEntityEvent &__eeInput); + BOOL H0x01500030_Fire_41(const CEntityEvent &__eeInput); + BOOL H0x01500031_Fire_42(const CEntityEvent &__eeInput); + BOOL H0x01500032_Fire_43(const CEntityEvent &__eeInput); + BOOL H0x01500033_Fire_44(const CEntityEvent &__eeInput); + BOOL H0x01500034_Fire_45(const CEntityEvent &__eeInput); + BOOL H0x01500035_Fire_46(const CEntityEvent &__eeInput); + BOOL H0x01500036_Fire_47(const CEntityEvent &__eeInput); +#define STATE_CBeast_Hit 0x01500037 + BOOL +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Hit(const CEntityEvent &__eeInput); + BOOL H0x01500038_Hit_01(const CEntityEvent &__eeInput); + BOOL H0x01500039_Hit_02(const CEntityEvent &__eeInput); + BOOL H0x0150003a_Hit_03(const CEntityEvent &__eeInput); + BOOL H0x0150003b_Hit_04(const CEntityEvent &__eeInput); +#define STATE_CBeast_Main 1 + BOOL +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Beast_INCLUDED diff --git a/Sources/EntitiesMP/Beast_tables.h b/Sources/EntitiesMP/Beast_tables.h new file mode 100644 index 0000000..6cda3d9 --- /dev/null +++ b/Sources/EntitiesMP/Beast_tables.h @@ -0,0 +1,136 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(BeastType) + EP_ENUMVALUE(BT_NORMAL, "Small"), + EP_ENUMVALUE(BT_BIG, "Big"), + EP_ENUMVALUE(BT_HUGE, "Huge"), +EP_ENUMEND(BeastType); + +#define ENTITYCLASS CBeast + +CEntityProperty CBeast_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &BeastType_enum, (0x00000150<<8)+1, offsetof(CBeast, m_bcType), "Character", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000150<<8)+2, offsetof(CBeast, m_iCounter), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000150<<8)+3, offsetof(CBeast, m_bBeBoss), "Boss", 'B', 0x7F0000FFUL, 0), +}; +#define CBeast_propertiesct ARRAYCOUNT(CBeast_properties) + +CEntityComponent CBeast_components[] = { +#define CLASS_BASE ((0x00000150<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_PROJECTILE ((0x00000150<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000150<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define MODEL_BEAST ((0x00000150<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_BEAST, "EFNM" "Models\\Enemies\\Beast\\Beast.mdl"), +#define TEXTURE_BEAST_NORMAL ((0x00000150<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_BEAST_NORMAL, "EFNM" "Models\\Enemies\\Beast\\Beast.tex"), +#define TEXTURE_BEAST_BIG ((0x00000150<<8)+12) + CEntityComponent(ECT_TEXTURE, TEXTURE_BEAST_BIG, "EFNM" "Models\\Enemies\\Beast\\BeastBig.tex"), +#define TEXTURE_BEAST_HUGE ((0x00000150<<8)+13) + CEntityComponent(ECT_TEXTURE, TEXTURE_BEAST_HUGE, "EFNM" "ModelsMP\\Enemies\\Beast\\BeastBiggest.tex"), +#define SOUND_IDLE ((0x00000150<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "Models\\Enemies\\Beast\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000150<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "Models\\Enemies\\Beast\\Sounds\\Sight.wav"), +#define SOUND_WOUND ((0x00000150<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "Models\\Enemies\\Beast\\Sounds\\Wound.wav"), +#define SOUND_FIRE ((0x00000150<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_FIRE, "EFNM" "Models\\Enemies\\Beast\\Sounds\\Fire.wav"), +#define SOUND_KICK ((0x00000150<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_KICK, "EFNM" "Models\\Enemies\\Beast\\Sounds\\Kick.wav"), +#define SOUND_DEATH ((0x00000150<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "Models\\Enemies\\Beast\\Sounds\\Death.wav"), +#define SOUND_DEATHBIG ((0x00000150<<8)+56) + CEntityComponent(ECT_SOUND, SOUND_DEATHBIG, "EFNM" "Models\\Enemies\\Beast\\Sounds\\DeathBig.wav"), +#define SOUND_ANGER ((0x00000150<<8)+57) + CEntityComponent(ECT_SOUND, SOUND_ANGER, "EFNM" "Models\\Enemies\\Beast\\Sounds\\Anger.wav"), +}; +#define CBeast_componentsct ARRAYCOUNT(CBeast_components) + +CEventHandlerEntry CBeast_handlers[] = { + {0x01500000, STATE_CEnemyBase_Death, CEntity::pEventHandler(&CBeast:: +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Death),DEBUGSTRING("CBeast::Death")}, + {0x01500001, -1, CEntity::pEventHandler(&CBeast::H0x01500001_Death_01), DEBUGSTRING("CBeast::H0x01500001_Death_01")}, + {0x01500002, -1, CEntity::pEventHandler(&CBeast::H0x01500002_Death_02), DEBUGSTRING("CBeast::H0x01500002_Death_02")}, + {0x01500003, -1, CEntity::pEventHandler(&CBeast::H0x01500003_Death_03), DEBUGSTRING("CBeast::H0x01500003_Death_03")}, + {0x01500004, -1, CEntity::pEventHandler(&CBeast::H0x01500004_Death_04), DEBUGSTRING("CBeast::H0x01500004_Death_04")}, + {0x01500005, -1, CEntity::pEventHandler(&CBeast::H0x01500005_Death_05), DEBUGSTRING("CBeast::H0x01500005_Death_05")}, + {0x01500006, -1, CEntity::pEventHandler(&CBeast::H0x01500006_Death_06), DEBUGSTRING("CBeast::H0x01500006_Death_06")}, + {0x01500007, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CBeast:: +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Fire),DEBUGSTRING("CBeast::Fire")}, + {0x01500008, -1, CEntity::pEventHandler(&CBeast::H0x01500008_Fire_01), DEBUGSTRING("CBeast::H0x01500008_Fire_01")}, + {0x01500009, -1, CEntity::pEventHandler(&CBeast::H0x01500009_Fire_02), DEBUGSTRING("CBeast::H0x01500009_Fire_02")}, + {0x0150000a, -1, CEntity::pEventHandler(&CBeast::H0x0150000a_Fire_03), DEBUGSTRING("CBeast::H0x0150000a_Fire_03")}, + {0x0150000b, -1, CEntity::pEventHandler(&CBeast::H0x0150000b_Fire_04), DEBUGSTRING("CBeast::H0x0150000b_Fire_04")}, + {0x0150000c, -1, CEntity::pEventHandler(&CBeast::H0x0150000c_Fire_05), DEBUGSTRING("CBeast::H0x0150000c_Fire_05")}, + {0x0150000d, -1, CEntity::pEventHandler(&CBeast::H0x0150000d_Fire_06), DEBUGSTRING("CBeast::H0x0150000d_Fire_06")}, + {0x0150000e, -1, CEntity::pEventHandler(&CBeast::H0x0150000e_Fire_07), DEBUGSTRING("CBeast::H0x0150000e_Fire_07")}, + {0x0150000f, -1, CEntity::pEventHandler(&CBeast::H0x0150000f_Fire_08), DEBUGSTRING("CBeast::H0x0150000f_Fire_08")}, + {0x01500010, -1, CEntity::pEventHandler(&CBeast::H0x01500010_Fire_09), DEBUGSTRING("CBeast::H0x01500010_Fire_09")}, + {0x01500011, -1, CEntity::pEventHandler(&CBeast::H0x01500011_Fire_10), DEBUGSTRING("CBeast::H0x01500011_Fire_10")}, + {0x01500012, -1, CEntity::pEventHandler(&CBeast::H0x01500012_Fire_11), DEBUGSTRING("CBeast::H0x01500012_Fire_11")}, + {0x01500013, -1, CEntity::pEventHandler(&CBeast::H0x01500013_Fire_12), DEBUGSTRING("CBeast::H0x01500013_Fire_12")}, + {0x01500014, -1, CEntity::pEventHandler(&CBeast::H0x01500014_Fire_13), DEBUGSTRING("CBeast::H0x01500014_Fire_13")}, + {0x01500015, -1, CEntity::pEventHandler(&CBeast::H0x01500015_Fire_14), DEBUGSTRING("CBeast::H0x01500015_Fire_14")}, + {0x01500016, -1, CEntity::pEventHandler(&CBeast::H0x01500016_Fire_15), DEBUGSTRING("CBeast::H0x01500016_Fire_15")}, + {0x01500017, -1, CEntity::pEventHandler(&CBeast::H0x01500017_Fire_16), DEBUGSTRING("CBeast::H0x01500017_Fire_16")}, + {0x01500018, -1, CEntity::pEventHandler(&CBeast::H0x01500018_Fire_17), DEBUGSTRING("CBeast::H0x01500018_Fire_17")}, + {0x01500019, -1, CEntity::pEventHandler(&CBeast::H0x01500019_Fire_18), DEBUGSTRING("CBeast::H0x01500019_Fire_18")}, + {0x0150001a, -1, CEntity::pEventHandler(&CBeast::H0x0150001a_Fire_19), DEBUGSTRING("CBeast::H0x0150001a_Fire_19")}, + {0x0150001b, -1, CEntity::pEventHandler(&CBeast::H0x0150001b_Fire_20), DEBUGSTRING("CBeast::H0x0150001b_Fire_20")}, + {0x0150001c, -1, CEntity::pEventHandler(&CBeast::H0x0150001c_Fire_21), DEBUGSTRING("CBeast::H0x0150001c_Fire_21")}, + {0x0150001d, -1, CEntity::pEventHandler(&CBeast::H0x0150001d_Fire_22), DEBUGSTRING("CBeast::H0x0150001d_Fire_22")}, + {0x0150001e, -1, CEntity::pEventHandler(&CBeast::H0x0150001e_Fire_23), DEBUGSTRING("CBeast::H0x0150001e_Fire_23")}, + {0x0150001f, -1, CEntity::pEventHandler(&CBeast::H0x0150001f_Fire_24), DEBUGSTRING("CBeast::H0x0150001f_Fire_24")}, + {0x01500020, -1, CEntity::pEventHandler(&CBeast::H0x01500020_Fire_25), DEBUGSTRING("CBeast::H0x01500020_Fire_25")}, + {0x01500021, -1, CEntity::pEventHandler(&CBeast::H0x01500021_Fire_26), DEBUGSTRING("CBeast::H0x01500021_Fire_26")}, + {0x01500022, -1, CEntity::pEventHandler(&CBeast::H0x01500022_Fire_27), DEBUGSTRING("CBeast::H0x01500022_Fire_27")}, + {0x01500023, -1, CEntity::pEventHandler(&CBeast::H0x01500023_Fire_28), DEBUGSTRING("CBeast::H0x01500023_Fire_28")}, + {0x01500024, -1, CEntity::pEventHandler(&CBeast::H0x01500024_Fire_29), DEBUGSTRING("CBeast::H0x01500024_Fire_29")}, + {0x01500025, -1, CEntity::pEventHandler(&CBeast::H0x01500025_Fire_30), DEBUGSTRING("CBeast::H0x01500025_Fire_30")}, + {0x01500026, -1, CEntity::pEventHandler(&CBeast::H0x01500026_Fire_31), DEBUGSTRING("CBeast::H0x01500026_Fire_31")}, + {0x01500027, -1, CEntity::pEventHandler(&CBeast::H0x01500027_Fire_32), DEBUGSTRING("CBeast::H0x01500027_Fire_32")}, + {0x01500028, -1, CEntity::pEventHandler(&CBeast::H0x01500028_Fire_33), DEBUGSTRING("CBeast::H0x01500028_Fire_33")}, + {0x01500029, -1, CEntity::pEventHandler(&CBeast::H0x01500029_Fire_34), DEBUGSTRING("CBeast::H0x01500029_Fire_34")}, + {0x0150002a, -1, CEntity::pEventHandler(&CBeast::H0x0150002a_Fire_35), DEBUGSTRING("CBeast::H0x0150002a_Fire_35")}, + {0x0150002b, -1, CEntity::pEventHandler(&CBeast::H0x0150002b_Fire_36), DEBUGSTRING("CBeast::H0x0150002b_Fire_36")}, + {0x0150002c, -1, CEntity::pEventHandler(&CBeast::H0x0150002c_Fire_37), DEBUGSTRING("CBeast::H0x0150002c_Fire_37")}, + {0x0150002d, -1, CEntity::pEventHandler(&CBeast::H0x0150002d_Fire_38), DEBUGSTRING("CBeast::H0x0150002d_Fire_38")}, + {0x0150002e, -1, CEntity::pEventHandler(&CBeast::H0x0150002e_Fire_39), DEBUGSTRING("CBeast::H0x0150002e_Fire_39")}, + {0x0150002f, -1, CEntity::pEventHandler(&CBeast::H0x0150002f_Fire_40), DEBUGSTRING("CBeast::H0x0150002f_Fire_40")}, + {0x01500030, -1, CEntity::pEventHandler(&CBeast::H0x01500030_Fire_41), DEBUGSTRING("CBeast::H0x01500030_Fire_41")}, + {0x01500031, -1, CEntity::pEventHandler(&CBeast::H0x01500031_Fire_42), DEBUGSTRING("CBeast::H0x01500031_Fire_42")}, + {0x01500032, -1, CEntity::pEventHandler(&CBeast::H0x01500032_Fire_43), DEBUGSTRING("CBeast::H0x01500032_Fire_43")}, + {0x01500033, -1, CEntity::pEventHandler(&CBeast::H0x01500033_Fire_44), DEBUGSTRING("CBeast::H0x01500033_Fire_44")}, + {0x01500034, -1, CEntity::pEventHandler(&CBeast::H0x01500034_Fire_45), DEBUGSTRING("CBeast::H0x01500034_Fire_45")}, + {0x01500035, -1, CEntity::pEventHandler(&CBeast::H0x01500035_Fire_46), DEBUGSTRING("CBeast::H0x01500035_Fire_46")}, + {0x01500036, -1, CEntity::pEventHandler(&CBeast::H0x01500036_Fire_47), DEBUGSTRING("CBeast::H0x01500036_Fire_47")}, + {0x01500037, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CBeast:: +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Hit),DEBUGSTRING("CBeast::Hit")}, + {0x01500038, -1, CEntity::pEventHandler(&CBeast::H0x01500038_Hit_01), DEBUGSTRING("CBeast::H0x01500038_Hit_01")}, + {0x01500039, -1, CEntity::pEventHandler(&CBeast::H0x01500039_Hit_02), DEBUGSTRING("CBeast::H0x01500039_Hit_02")}, + {0x0150003a, -1, CEntity::pEventHandler(&CBeast::H0x0150003a_Hit_03), DEBUGSTRING("CBeast::H0x0150003a_Hit_03")}, + {0x0150003b, -1, CEntity::pEventHandler(&CBeast::H0x0150003b_Hit_04), DEBUGSTRING("CBeast::H0x0150003b_Hit_04")}, + {1, -1, CEntity::pEventHandler(&CBeast:: +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/Beast.es" +Main),DEBUGSTRING("CBeast::Main")}, +}; +#define CBeast_handlersct ARRAYCOUNT(CBeast_handlers) + +CEntity *CBeast_New(void) { return new CBeast; }; +void CBeast_OnInitClass(void) {}; +void CBeast_OnEndClass(void) {}; +void CBeast_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CBeast_OnWorldEnd(CWorld *pwo) {}; +void CBeast_OnWorldInit(CWorld *pwo) {}; +void CBeast_OnWorldTick(CWorld *pwo) {}; +void CBeast_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CBeast, CEnemyBase, "Beast", "Thumbnails\\Beast.tbn", 0x00000150); +DECLARE_CTFILENAME(_fnmCBeast_tbn, "Thumbnails\\Beast.tbn"); diff --git a/Sources/EntitiesMP/BigHead.cpp b/Sources/EntitiesMP/BigHead.cpp new file mode 100644 index 0000000..fa12106 --- /dev/null +++ b/Sources/EntitiesMP/BigHead.cpp @@ -0,0 +1,532 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/Mental/Mental.h" + +#include +#include +#line 18 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" + +// info structure +static EntityInfo eiMental = { + EIBT_FLESH, 200.0f, + 0.0f, 1.5f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +#define GREET_SENSE_RANGE 10.0f +#define GREET_SENSE_DELAY 30.0f + + +void CBigHead::SetDefaultProperties(void) { + m_fnmHeadTex = CTString(""); + m_fnmNameSnd = CTString(""); + m_tmLastGreetTime = -100.0f; + m_bhtType = BHT_NORMAL ; + m_bIgnorePlayer = FALSE ; + m_bPlayingWalkSound = FALSE ; + m_bSleeping = FALSE ; + m_tmLastWalkingSoundTime = -100.0f; + m_tmWalkingSound = 5.0f; + CEnemyBase::SetDefaultProperties(); +} + +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +BOOL CBigHead::HandleEvent(const CEntityEvent & ee) +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +{ +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(m_bIgnorePlayer ){ +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(ee . ee_slEvent == EVENTCODE_ETouch ){ +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +ETouch & et = (ETouch &) ee ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(IsOfClass (et . penOther , "Player")){ +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return TRUE ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return CEnemyBase :: HandleEvent (ee ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void * CBigHead::GetEntityInfo(void) +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +{ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return & eiMental ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void CBigHead::Precache(void) +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +{ +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +CEnemyBase :: Precache (); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PrecacheSound (SOUND_SIGHT ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PrecacheSound (SOUND_IDLE ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PrecacheSound (SOUND_WOUND ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PrecacheSound (SOUND_DEATH ); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PrecacheSound (SOUND_WALKZOMBIE ); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PrecacheSound (SOUND_WALKSAINT ); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_aps . Precache (m_fnmNameSnd ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_apt . Precache (m_fnmHeadTex ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +INDEX CBigHead::GetWalkAnim(void) +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +{ +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(m_bhtType == BHT_ZOMBIE ){ +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return MENTAL_ANIM_WALKZOMBIE ; +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}else if(m_bhtType == BHT_SAINT ){ +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return MENTAL_ANIM_WALKANGEL ; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}else { +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return MENTAL_ANIM_RUN ; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +INDEX CBigHead::AnimForDamage(FLOAT fDamage) { +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +INDEX iAnim ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +iAnim = MENTAL_ANIM_PANIC ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +StartModelAnim (iAnim , 0); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return iAnim ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +INDEX CBigHead::AnimForDeath(void) { +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +INDEX iAnim ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +iAnim = MENTAL_ANIM_DEATH ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +StartModelAnim (iAnim , 0); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return iAnim ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void CBigHead::DeathNotify(void) { +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +en_fDensity = 500.0f; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void CBigHead::StandingAnim(void) { +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +StartModelAnim (MENTAL_ANIM_GROUNDREST , AOF_LOOPING | AOF_NORESTART ); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void CBigHead::WalkingAnim(void) { +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PlayWalkSound (); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +StartModelAnim (GetWalkAnim () , AOF_LOOPING | AOF_NORESTART ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(! m_bIgnorePlayer && _pTimer -> CurrentTick () > m_tmLastGreetTime + GREET_SENSE_DELAY ){ +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fSenseRange = GREET_SENSE_RANGE ; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bDeaf = FALSE ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void CBigHead::RunningAnim(void) +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +{ +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PlayWalkSound (); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +StartModelAnim (GetWalkAnim () , AOF_LOOPING | AOF_NORESTART ); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void CBigHead::RotatingAnim(void) { +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +RunningAnim (); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void CBigHead::PlayWalkSound(void) +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +{ +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +INDEX iSound = SOUND_WALKZOMBIE ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(m_bhtType == BHT_ZOMBIE ){ +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +iSound = SOUND_WALKZOMBIE ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}else if(m_bhtType == BHT_SAINT ){ +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +iSound = SOUND_WALKSAINT ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}else { +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(! m_bPlayingWalkSound || _pTimer -> CurrentTick () - m_tmLastWalkingSoundTime > m_tmWalkingSound ){ +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bPlayingWalkSound = TRUE ; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_tmLastWalkingSoundTime = _pTimer -> CurrentTick (); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PlaySound (m_soSound , iSound , SOF_3D ); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void CBigHead::IdleSound(void) { +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(m_bIgnorePlayer ){ +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return ; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bPlayingWalkSound = FALSE ; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void CBigHead::SightSound(void) { +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bPlayingWalkSound = FALSE ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void CBigHead::WoundSound(void) { +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bPlayingWalkSound = FALSE ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} + +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void CBigHead::DeathSound(void) { +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bPlayingWalkSound = FALSE ; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +BOOL CBigHead:: +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBigHead_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBigHead::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(!(CalcDist (m_penEnemy ) <= m_fStopDistance * 1.1f)){ Jump(STATE_CURRENT,0x01540003, FALSE, EInternal());return TRUE;} +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(m_fnmNameSnd != ""){ +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PlaySound (m_soSound , m_fnmNameSnd , SOF_3D ); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bPlayingWalkSound = FALSE ; +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bBlind = TRUE ; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bDeaf = TRUE ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fSenseRange = 0.0f; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_tmLastGreetTime = _pTimer -> CurrentTick (); +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SetTargetNone (); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +StartModelAnim (MENTAL_ANIM_GREET , 0); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SetTimerAfter(GetModelObject () -> GetCurrentAnimLength ()); +Jump(STATE_CURRENT, 0x01540001, FALSE, EBegin());return TRUE;}BOOL CBigHead::H0x01540001_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01540001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01540002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBigHead::H0x01540002_Fire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01540002 +; +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +StandingAnim (); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Return(STATE_CURRENT,EReconsiderBehavior ()); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return TRUE;Jump(STATE_CURRENT,0x01540003, FALSE, EInternal());return TRUE;}BOOL CBigHead::H0x01540003_Fire_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01540003 + +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Return(STATE_CURRENT,EReturn ()); +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CBigHead:: +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Sleep(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBigHead_Sleep + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBigHead::Sleep expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +StartModelAnim (MENTAL_ANIM_SNORE , AOF_LOOPING ); +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01540005, FALSE, EBegin());return TRUE;}BOOL CBigHead::H0x01540005_Sleep_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01540005 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Jump(STATE_CURRENT, STATE_CBigHead_WakeUp, TRUE, EVoid());return TRUE; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}ASSERT(FALSE);break;default:{ +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return TRUE; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}ASSERT(FALSE);break; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}return TRUE;}BOOL CBigHead::H0x01540006_Sleep_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01540006 + ASSERT(FALSE); return TRUE;};BOOL CBigHead:: +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +WakeUp(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBigHead_WakeUp + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBigHead::WakeUp expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SightSound (); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +StartModelAnim (MENTAL_ANIM_GETUP , 0); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SetTimerAfter(GetModelObject () -> GetCurrentAnimLength ()); +Jump(STATE_CURRENT, 0x01540008, FALSE, EBegin());return TRUE;}BOOL CBigHead::H0x01540008_WakeUp_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01540008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01540009, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBigHead::H0x01540009_WakeUp_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01540009 +; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Return(STATE_CURRENT,EReturn ()); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CBigHead:: +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PreMainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBigHead_PreMainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBigHead::PreMainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(!(m_bSleeping )){ Jump(STATE_CURRENT,0x0154000d, FALSE, EInternal());return TRUE;} +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bSleeping = FALSE ; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x0154000b, FALSE, EBegin());return TRUE;}BOOL CBigHead::H0x0154000b_PreMainLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0154000b +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Call(STATE_CURRENT, STATE_CBigHead_Sleep, TRUE, EVoid());return TRUE; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; + +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +UnsetTimer();Jump(STATE_CURRENT,0x0154000c, FALSE, EInternal());return TRUE; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Die, FALSE, eDeath );return TRUE; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}return TRUE;}BOOL CBigHead::H0x0154000c_PreMainLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0154000c +Jump(STATE_CURRENT,0x0154000d, FALSE, EInternal());return TRUE;}BOOL CBigHead::H0x0154000d_PreMainLoop_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0154000d + +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Return(STATE_CURRENT,EReturn ()); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CBigHead:: +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBigHead_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBigHead::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +InitAsModel (); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SetCollisionFlags (ECF_MODEL ); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SetHealth (20.0f); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fMaxHealth = 20.0f; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +en_tmMaxHoldBreath = 5.0f; +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +en_fDensity = 2000.0f; +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fBlowUpSize = 2.0f; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SetModel (MODEL_MENTAL ); +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +SetModelMainTexture (TEXTURE_MENTAL ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +AddAttachment (0 , MODEL_HEAD , TEXTURE_MENTAL ); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(m_fnmHeadTex != ""){ +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +try { +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +CAttachmentModelObject * pamoHead = GetModelObject () -> GetAttachmentModel (0); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(pamoHead != NULL ){ +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +pamoHead -> amo_moModelObject . mo_toTexture . SetData_t (m_fnmHeadTex ); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}catch (char * strError ){ +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +CPrintF ("%s\n" , strError ); +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +AddAttachment (0 , MODEL_HEAD , TEXTURE_MENTAL ); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(m_bhtType == BHT_ZOMBIE ){ +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +AddAttachment (MENTAL_ATTACHMENT_HORNS , MODEL_HORNS , TEXTURE_HORNS ); +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}else if(m_bhtType == BHT_SAINT ){ +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +AddAttachment (MENTAL_ATTACHMENT_AURA , MODEL_AURA , TEXTURE_AURA ); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fWalkSpeed = FRnd () + 1.5f; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 500.0f); +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fAttackRunSpeed = FRnd () * 2.0f + 6.0f; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fCloseRunSpeed = FRnd () * 2.0f + 6.0f; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fAttackDistance = 50.0f; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fCloseDistance = 0.0f; +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fStopDistance = 5.0f; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fAttackFireTime = 0.1f; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fCloseFireTime = 0.1f; +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fIgnoreRange = 200.0f; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fBlowUpAmount = 65.0f; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fBodyParts = 4; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fDamageWounded = 1.0f; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_iScore = 0; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +if(m_bIgnorePlayer ){ +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bBlind = TRUE ; +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bDeaf = TRUE ; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fSenseRange = 0; +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +}else { +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_bBlind = TRUE ; +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +m_fSenseRange = GREET_SENSE_RANGE ; +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +} +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +const FLOAT fSize = 0.6f; +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +GetModelObject () -> StretchModel (FLOAT3D (fSize , fSize , fSize )); +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +ModelChangeNotify (); +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +StandingAnim (); +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/BigHead.es b/Sources/EntitiesMP/BigHead.es new file mode 100644 index 0000000..2583066 --- /dev/null +++ b/Sources/EntitiesMP/BigHead.es @@ -0,0 +1,358 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +340 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/Mental/Mental.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/BasicEffects"; + +enum BigHeadType { + 0 BHT_NORMAL "Normal", + 1 BHT_ZOMBIE "Zombie", + 2 BHT_SAINT "Saint", +}; + +%{ +// info structure +static EntityInfo eiMental = { + EIBT_FLESH, 200.0f, + 0.0f, 1.5f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +#define GREET_SENSE_RANGE 10.0f +#define GREET_SENSE_DELAY 30.0f + +%} + +class CBigHead: CEnemyBase { +name "BigHead"; +thumbnail "Thumbnails\\Mental.tbn"; + +properties: + // class internal + 1 CTFileName m_fnmHeadTex "Head texture" 'H' = CTString(""), + 2 CTFileName m_fnmNameSnd "Name sound" 'S' = CTString(""), + 3 FLOAT m_tmLastGreetTime = -100.0f, + 4 enum BigHeadType m_bhtType "Type" 'Y'= BHT_NORMAL, + 5 BOOL m_bIgnorePlayer "Ignore player" 'I' = FALSE, + 6 BOOL m_bPlayingWalkSound = FALSE, + 7 BOOL m_bSleeping "Sleeping" 'S' = FALSE, // set to make it sleep initally + 8 FLOAT m_tmLastWalkingSoundTime = -100.0f, + 9 FLOAT m_tmWalkingSound "Walk sound frequency" = 5.0f, + + { + CAutoPrecacheSound m_aps; + CAutoPrecacheTexture m_apt; + } + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + 2 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + 3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + +// ************** DATA ************** + 10 model MODEL_MENTAL "ModelsMP\\Enemies\\Mental\\Mental.mdl", + 11 texture TEXTURE_MENTAL "ModelsMP\\Enemies\\Mental\\Mental.tex", + 12 model MODEL_HEAD "ModelsMP\\Enemies\\Mental\\Head.mdl", + 13 model MODEL_HORNS "ModelsMP\\Enemies\\Mental\\Horns.mdl", + 14 texture TEXTURE_HORNS "ModelsMP\\Enemies\\Mental\\Horns.tex", + 15 model MODEL_AURA "ModelsMP\\Enemies\\Mental\\Aura.mdl", + 16 texture TEXTURE_AURA "ModelsMP\\Enemies\\Mental\\Aura.tex", + + 50 sound SOUND_IDLE "Models\\Enemies\\Mental\\Sounds\\Idle.wav", + 51 sound SOUND_SIGHT "Models\\Enemies\\Mental\\Sounds\\Sight.wav", + 52 sound SOUND_WOUND "Models\\Enemies\\Mental\\Sounds\\Wound.wav", + 53 sound SOUND_DEATH "Models\\Enemies\\Mental\\Sounds\\Death.wav", + 54 sound SOUND_WALKZOMBIE "ModelsMP\\Enemies\\Mental\\Sounds\\ComeToDaddy.wav", + 55 sound SOUND_WALKSAINT "ModelsMP\\Enemies\\Mental\\Sounds\\PeaceWithYou.wav", + +functions: + BOOL HandleEvent(const CEntityEvent &ee) + { + if (m_bIgnorePlayer) { + if (ee.ee_slEvent==EVENTCODE_ETouch) { + ETouch &et = (ETouch &)ee; + if (IsOfClass(et.penOther, "Player")) { + return TRUE; + } + } + } + return CEnemyBase::HandleEvent(ee); + } + + /* Entity info */ + void *GetEntityInfo(void) + { + return &eiMental; + }; + + void Precache(void) + { + CEnemyBase::Precache(); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_IDLE); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_DEATH); + PrecacheSound(SOUND_WALKZOMBIE); + PrecacheSound(SOUND_WALKSAINT); + m_aps.Precache(m_fnmNameSnd); + m_apt.Precache(m_fnmHeadTex); + }; + + INDEX GetWalkAnim(void) + { + if (m_bhtType==BHT_ZOMBIE) { + return MENTAL_ANIM_WALKZOMBIE; + } else if (m_bhtType==BHT_SAINT) { + return MENTAL_ANIM_WALKANGEL; + } else { + return MENTAL_ANIM_RUN; + } + } + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim; + iAnim = MENTAL_ANIM_PANIC; + StartModelAnim(iAnim, 0); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + INDEX iAnim; + iAnim = MENTAL_ANIM_DEATH; + StartModelAnim(iAnim, 0); + return iAnim; + }; + + void DeathNotify(void) { +// ChangeCollisionBoxIndexWhenPossible(HEADMAN_COLLISION_BOX_DEATH); + en_fDensity = 500.0f; + }; + + // virtual anim functions + void StandingAnim(void) { + StartModelAnim(MENTAL_ANIM_GROUNDREST, AOF_LOOPING|AOF_NORESTART); + }; + void WalkingAnim(void) { + PlayWalkSound(); + StartModelAnim(GetWalkAnim(), AOF_LOOPING|AOF_NORESTART); + + if (!m_bIgnorePlayer && _pTimer->CurrentTick()>m_tmLastGreetTime+GREET_SENSE_DELAY) { + m_fSenseRange = GREET_SENSE_RANGE; + m_bDeaf = FALSE; + } + }; + void RunningAnim(void) + { + PlayWalkSound(); + StartModelAnim(GetWalkAnim(), AOF_LOOPING|AOF_NORESTART); + }; + void RotatingAnim(void) { + RunningAnim(); + }; + + void PlayWalkSound(void) + { + INDEX iSound = SOUND_WALKZOMBIE; + if (m_bhtType==BHT_ZOMBIE) { + iSound = SOUND_WALKZOMBIE; + } else if (m_bhtType==BHT_SAINT) { + iSound = SOUND_WALKSAINT; + } else { + return; + } + if (!m_bPlayingWalkSound || _pTimer->CurrentTick()-m_tmLastWalkingSoundTime>m_tmWalkingSound) { + m_bPlayingWalkSound = TRUE; + m_tmLastWalkingSoundTime = _pTimer->CurrentTick(); + PlaySound(m_soSound, iSound, SOF_3D); + } + } + + // virtual sound functions + void IdleSound(void) { + if (m_bIgnorePlayer) { + return; + } + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + m_bPlayingWalkSound = FALSE; + }; + + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + m_bPlayingWalkSound = FALSE; + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + m_bPlayingWalkSound = FALSE; + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + m_bPlayingWalkSound = FALSE; + }; + +procedures: + Fire(EVoid) : CEnemyBase::Fire { + // hit + if (CalcDist(m_penEnemy) <= m_fStopDistance*1.1f) { + if (m_fnmNameSnd!="") { + PlaySound(m_soSound, m_fnmNameSnd, SOF_3D); + m_bPlayingWalkSound = FALSE; + } + m_bBlind = TRUE; + m_bDeaf = TRUE; + m_fSenseRange = 0.0f; + m_tmLastGreetTime = _pTimer->CurrentTick(); + SetTargetNone(); + StartModelAnim(MENTAL_ANIM_GREET, 0); + autowait(GetModelObject()->GetCurrentAnimLength()); + StandingAnim(); + return EReconsiderBehavior(); + } + return EReturn(); + } + + Sleep(EVoid) + { + // start sleeping anim + StartModelAnim(MENTAL_ANIM_SNORE, AOF_LOOPING); + // repeat + wait() { + // if triggered + on(ETrigger eTrigger) : { +// // remember enemy +// SetTargetSoft(eTrigger.penCaused); + // wake up + jump WakeUp(); + } +/* // if damaged + on(EDamage eDamage) : { + // wake up + jump WakeUp(); + } + */ + otherwise() : { + resume; + } + } + } + + WakeUp(EVoid) + { + // wakeup anim + SightSound(); + StartModelAnim(MENTAL_ANIM_GETUP, 0); + autowait(GetModelObject()->GetCurrentAnimLength()); + + // trigger your target +// SendToTarget(m_penDeathTarget, m_eetDeathType); + // proceed with normal functioning + return EReturn(); + } + + // overridable called before main enemy loop actually begins + PreMainLoop(EVoid) : CEnemyBase::PreMainLoop + { + // if sleeping + if (m_bSleeping) { + m_bSleeping = FALSE; + // go to sleep until waken up + wait() { + on (EBegin) : { + call Sleep(); + } + on (EReturn) : { + stop; + }; + // if dead + on(EDeath eDeath) : { + // die + jump CEnemyBase::Die(eDeath); + } + } + } + return EReturn(); + } + + /************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + SetHealth(20.0f); + m_fMaxHealth = 20.0f; + en_tmMaxHoldBreath = 5.0f; + en_fDensity = 2000.0f; + m_fBlowUpSize = 2.0f; + + // set your appearance + SetModel(MODEL_MENTAL); + SetModelMainTexture(TEXTURE_MENTAL); + AddAttachment(0, MODEL_HEAD, TEXTURE_MENTAL); + if (m_fnmHeadTex!="") { + // try to + try { + CAttachmentModelObject *pamoHead = GetModelObject()->GetAttachmentModel(0); + if (pamoHead!=NULL) { + pamoHead->amo_moModelObject.mo_toTexture.SetData_t(m_fnmHeadTex); + } + // if anything failed + } catch (char *strError) { + // report error + CPrintF("%s\n", strError); + AddAttachment(0, MODEL_HEAD, TEXTURE_MENTAL); + } + } + if (m_bhtType==BHT_ZOMBIE) { + AddAttachment(MENTAL_ATTACHMENT_HORNS, MODEL_HORNS, TEXTURE_HORNS); + } else if (m_bhtType==BHT_SAINT) { + AddAttachment(MENTAL_ATTACHMENT_AURA, MODEL_AURA, TEXTURE_AURA); + } + + // setup moving speed + m_fWalkSpeed = FRnd() + 1.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f); + m_fAttackRunSpeed = FRnd()*2.0f + 6.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + m_fCloseRunSpeed = FRnd()*2.0f + 6.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + // setup attack distances + m_fAttackDistance = 50.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 5.0f; // greeting distance + m_fAttackFireTime = 0.1f; + m_fCloseFireTime = 0.1f; + m_fIgnoreRange = 200.0f; + // damage/explode properties + m_fBlowUpAmount = 65.0f; + m_fBodyParts = 4; + m_fDamageWounded = 1.0f; + m_iScore = 0; + if (m_bIgnorePlayer) { + m_bBlind = TRUE; + m_bDeaf = TRUE; + m_fSenseRange = 0; + } else { + m_bBlind = TRUE; + m_fSenseRange = GREET_SENSE_RANGE; + } + + // set stretch factors for height and width + const FLOAT fSize = 0.6f; + GetModelObject()->StretchModel(FLOAT3D(fSize, fSize, fSize)); + ModelChangeNotify(); + StandingAnim(); + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/BigHead.h b/Sources/EntitiesMP/BigHead.h new file mode 100644 index 0000000..f4c697c --- /dev/null +++ b/Sources/EntitiesMP/BigHead.h @@ -0,0 +1,110 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_BigHead_INCLUDED +#define _EntitiesMP_BigHead_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType BigHeadType_enum; +enum BigHeadType { + BHT_NORMAL = 0, + BHT_ZOMBIE = 1, + BHT_SAINT = 2, +}; +DECL_DLL inline void ClearToDefault(BigHeadType &e) { e = (BigHeadType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CBigHead_DLLClass; +class CBigHead : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + CTFileName m_fnmHeadTex; + CTFileName m_fnmNameSnd; + FLOAT m_tmLastGreetTime; + enum BigHeadType m_bhtType; + BOOL m_bIgnorePlayer; + BOOL m_bPlayingWalkSound; + BOOL m_bSleeping; + FLOAT m_tmLastWalkingSoundTime; + FLOAT m_tmWalkingSound; +CAutoPrecacheSound m_aps; +CAutoPrecacheTexture m_apt; + +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +BOOL HandleEvent(const CEntityEvent & ee); + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void * GetEntityInfo(void); + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void Precache(void); + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +INDEX GetWalkAnim(void); + +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +INDEX AnimForDeath(void); + +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void DeathNotify(void); + +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void StandingAnim(void); + +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void WalkingAnim(void); + +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void RunningAnim(void); + +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void RotatingAnim(void); + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void PlayWalkSound(void); + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void IdleSound(void); + +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void SightSound(void); + +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void WoundSound(void); + +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +void DeathSound(void); +#define STATE_CBigHead_Fire 0x01540000 + BOOL +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x01540001_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x01540002_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x01540003_Fire_03(const CEntityEvent &__eeInput); +#define STATE_CBigHead_Sleep 0x01540004 + BOOL +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Sleep(const CEntityEvent &__eeInput); + BOOL H0x01540005_Sleep_01(const CEntityEvent &__eeInput); + BOOL H0x01540006_Sleep_02(const CEntityEvent &__eeInput); +#define STATE_CBigHead_WakeUp 0x01540007 + BOOL +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +WakeUp(const CEntityEvent &__eeInput); + BOOL H0x01540008_WakeUp_01(const CEntityEvent &__eeInput); + BOOL H0x01540009_WakeUp_02(const CEntityEvent &__eeInput); +#define STATE_CBigHead_PreMainLoop 0x0154000a + BOOL +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PreMainLoop(const CEntityEvent &__eeInput); + BOOL H0x0154000b_PreMainLoop_01(const CEntityEvent &__eeInput); + BOOL H0x0154000c_PreMainLoop_02(const CEntityEvent &__eeInput); + BOOL H0x0154000d_PreMainLoop_03(const CEntityEvent &__eeInput); +#define STATE_CBigHead_Main 1 + BOOL +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_BigHead_INCLUDED diff --git a/Sources/EntitiesMP/BigHead_tables.h b/Sources/EntitiesMP/BigHead_tables.h new file mode 100644 index 0000000..c269521 --- /dev/null +++ b/Sources/EntitiesMP/BigHead_tables.h @@ -0,0 +1,100 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(BigHeadType) + EP_ENUMVALUE(BHT_NORMAL, "Normal"), + EP_ENUMVALUE(BHT_ZOMBIE, "Zombie"), + EP_ENUMVALUE(BHT_SAINT, "Saint"), +EP_ENUMEND(BigHeadType); + +#define ENTITYCLASS CBigHead + +CEntityProperty CBigHead_properties[] = { + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000154<<8)+1, offsetof(CBigHead, m_fnmHeadTex), "Head texture", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000154<<8)+2, offsetof(CBigHead, m_fnmNameSnd), "Name sound", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000154<<8)+3, offsetof(CBigHead, m_tmLastGreetTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &BigHeadType_enum, (0x00000154<<8)+4, offsetof(CBigHead, m_bhtType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000154<<8)+5, offsetof(CBigHead, m_bIgnorePlayer), "Ignore player", 'I', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000154<<8)+6, offsetof(CBigHead, m_bPlayingWalkSound), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000154<<8)+7, offsetof(CBigHead, m_bSleeping), "Sleeping", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000154<<8)+8, offsetof(CBigHead, m_tmLastWalkingSoundTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000154<<8)+9, offsetof(CBigHead, m_tmWalkingSound), "Walk sound frequency", 0, 0x7F0000FFUL, 0), +}; +#define CBigHead_propertiesct ARRAYCOUNT(CBigHead_properties) + +CEntityComponent CBigHead_components[] = { +#define CLASS_BASE ((0x00000154<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_BLOOD_SPRAY ((0x00000154<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000154<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define MODEL_MENTAL ((0x00000154<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_MENTAL, "EFNM" "ModelsMP\\Enemies\\Mental\\Mental.mdl"), +#define TEXTURE_MENTAL ((0x00000154<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_MENTAL, "EFNM" "ModelsMP\\Enemies\\Mental\\Mental.tex"), +#define MODEL_HEAD ((0x00000154<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_HEAD, "EFNM" "ModelsMP\\Enemies\\Mental\\Head.mdl"), +#define MODEL_HORNS ((0x00000154<<8)+13) + CEntityComponent(ECT_MODEL, MODEL_HORNS, "EFNM" "ModelsMP\\Enemies\\Mental\\Horns.mdl"), +#define TEXTURE_HORNS ((0x00000154<<8)+14) + CEntityComponent(ECT_TEXTURE, TEXTURE_HORNS, "EFNM" "ModelsMP\\Enemies\\Mental\\Horns.tex"), +#define MODEL_AURA ((0x00000154<<8)+15) + CEntityComponent(ECT_MODEL, MODEL_AURA, "EFNM" "ModelsMP\\Enemies\\Mental\\Aura.mdl"), +#define TEXTURE_AURA ((0x00000154<<8)+16) + CEntityComponent(ECT_TEXTURE, TEXTURE_AURA, "EFNM" "ModelsMP\\Enemies\\Mental\\Aura.tex"), +#define SOUND_IDLE ((0x00000154<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "Models\\Enemies\\Mental\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000154<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "Models\\Enemies\\Mental\\Sounds\\Sight.wav"), +#define SOUND_WOUND ((0x00000154<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "Models\\Enemies\\Mental\\Sounds\\Wound.wav"), +#define SOUND_DEATH ((0x00000154<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "Models\\Enemies\\Mental\\Sounds\\Death.wav"), +#define SOUND_WALKZOMBIE ((0x00000154<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_WALKZOMBIE, "EFNM" "ModelsMP\\Enemies\\Mental\\Sounds\\ComeToDaddy.wav"), +#define SOUND_WALKSAINT ((0x00000154<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_WALKSAINT, "EFNM" "ModelsMP\\Enemies\\Mental\\Sounds\\PeaceWithYou.wav"), +}; +#define CBigHead_componentsct ARRAYCOUNT(CBigHead_components) + +CEventHandlerEntry CBigHead_handlers[] = { + {0x01540000, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CBigHead:: +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Fire),DEBUGSTRING("CBigHead::Fire")}, + {0x01540001, -1, CEntity::pEventHandler(&CBigHead::H0x01540001_Fire_01), DEBUGSTRING("CBigHead::H0x01540001_Fire_01")}, + {0x01540002, -1, CEntity::pEventHandler(&CBigHead::H0x01540002_Fire_02), DEBUGSTRING("CBigHead::H0x01540002_Fire_02")}, + {0x01540003, -1, CEntity::pEventHandler(&CBigHead::H0x01540003_Fire_03), DEBUGSTRING("CBigHead::H0x01540003_Fire_03")}, + {0x01540004, -1, CEntity::pEventHandler(&CBigHead:: +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Sleep),DEBUGSTRING("CBigHead::Sleep")}, + {0x01540005, -1, CEntity::pEventHandler(&CBigHead::H0x01540005_Sleep_01), DEBUGSTRING("CBigHead::H0x01540005_Sleep_01")}, + {0x01540006, -1, CEntity::pEventHandler(&CBigHead::H0x01540006_Sleep_02), DEBUGSTRING("CBigHead::H0x01540006_Sleep_02")}, + {0x01540007, -1, CEntity::pEventHandler(&CBigHead:: +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +WakeUp),DEBUGSTRING("CBigHead::WakeUp")}, + {0x01540008, -1, CEntity::pEventHandler(&CBigHead::H0x01540008_WakeUp_01), DEBUGSTRING("CBigHead::H0x01540008_WakeUp_01")}, + {0x01540009, -1, CEntity::pEventHandler(&CBigHead::H0x01540009_WakeUp_02), DEBUGSTRING("CBigHead::H0x01540009_WakeUp_02")}, + {0x0154000a, STATE_CEnemyBase_PreMainLoop, CEntity::pEventHandler(&CBigHead:: +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +PreMainLoop),DEBUGSTRING("CBigHead::PreMainLoop")}, + {0x0154000b, -1, CEntity::pEventHandler(&CBigHead::H0x0154000b_PreMainLoop_01), DEBUGSTRING("CBigHead::H0x0154000b_PreMainLoop_01")}, + {0x0154000c, -1, CEntity::pEventHandler(&CBigHead::H0x0154000c_PreMainLoop_02), DEBUGSTRING("CBigHead::H0x0154000c_PreMainLoop_02")}, + {0x0154000d, -1, CEntity::pEventHandler(&CBigHead::H0x0154000d_PreMainLoop_03), DEBUGSTRING("CBigHead::H0x0154000d_PreMainLoop_03")}, + {1, -1, CEntity::pEventHandler(&CBigHead:: +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/BigHead.es" +Main),DEBUGSTRING("CBigHead::Main")}, +}; +#define CBigHead_handlersct ARRAYCOUNT(CBigHead_handlers) + +CEntity *CBigHead_New(void) { return new CBigHead; }; +void CBigHead_OnInitClass(void) {}; +void CBigHead_OnEndClass(void) {}; +void CBigHead_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CBigHead_OnWorldEnd(CWorld *pwo) {}; +void CBigHead_OnWorldInit(CWorld *pwo) {}; +void CBigHead_OnWorldTick(CWorld *pwo) {}; +void CBigHead_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CBigHead, CEnemyBase, "BigHead", "Thumbnails\\Mental.tbn", 0x00000154); +DECLARE_CTFILENAME(_fnmCBigHead_tbn, "Thumbnails\\Mental.tbn"); diff --git a/Sources/EntitiesMP/BlendController.cpp b/Sources/EntitiesMP/BlendController.cpp new file mode 100644 index 0000000..aea93d4 --- /dev/null +++ b/Sources/EntitiesMP/BlendController.cpp @@ -0,0 +1,147 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" + +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" + +#include +#include +void CBlendController::SetDefaultProperties(void) { + m_bctType = BCT_NONE ; + CMarker::SetDefaultProperties(); +} + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +BOOL CBlendController::HandleEvent(const CEntityEvent & ee) +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +{ +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +if(pwsc == NULL ){ +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +return FALSE ; +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +} +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +FLOAT tmNow = _pTimer -> CurrentTick (); +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +if(ee . ee_slEvent == EVENTCODE_EActivate ) +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +{ +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +switch(m_bctType ) +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +{ +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +case BCT_PYRAMID_PLATES : +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmPyramidPlatesStart = tmNow ; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +break ; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +case BCT_ACTIVATE_PLATE_1 : +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmActivatedPlate1 = tmNow ; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmDeactivatedPlate1 = 1e6; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +break ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +case BCT_ACTIVATE_PLATE_2 : +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmActivatedPlate2 = tmNow ; +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmDeactivatedPlate2 = 1e6; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +break ; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +case BCT_ACTIVATE_PLATE_3 : +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmActivatedPlate3 = tmNow ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmDeactivatedPlate3 = 1e6; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +break ; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +case BCT_ACTIVATE_PLATE_4 : +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmActivatedPlate4 = tmNow ; +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmDeactivatedPlate4 = 1e6; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +break ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +case BCT_ACTIVATE_PYRAMID_MORPH_ROOM : +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmPyramidMorphRoomActivated = tmNow ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +break ; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +} +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +} +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +else if(ee . ee_slEvent == EVENTCODE_EDeactivate ) +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +{ +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +switch(m_bctType ) +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +{ +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +case BCT_ACTIVATE_PLATE_1 : +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmDeactivatedPlate1 = tmNow ; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +break ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +case BCT_ACTIVATE_PLATE_2 : +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmDeactivatedPlate2 = tmNow ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +break ; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +case BCT_ACTIVATE_PLATE_3 : +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmDeactivatedPlate3 = tmNow ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +break ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +case BCT_ACTIVATE_PLATE_4 : +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +pwsc -> m_tmDeactivatedPlate4 = tmNow ; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +break ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +} +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +} +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +return FALSE ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +} +BOOL CBlendController:: +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBlendController_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBlendController::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +InitAsEditorModel (); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +SetModel (MODEL_CONTROLLER ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +SetModelMainTexture (TEXTURE_CONTROLLER ); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +Return(STATE_CURRENT,EVoid()); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/BlendController.es b/Sources/EntitiesMP/BlendController.es new file mode 100644 index 0000000..1eff42e --- /dev/null +++ b/Sources/EntitiesMP/BlendController.es @@ -0,0 +1,115 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +612 +%{ +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" +%} + +uses "EntitiesMP/Marker"; + +enum BlendControllerType { + 0 BCT_NONE "None", // no FX + 1 BCT_PYRAMID_PLATES "Appear pyramid plates", // effect of appearing of pyramid plates + 2 BCT_ACTIVATE_PLATE_1 "Activate plate 1", // plate 1 activating + 3 BCT_ACTIVATE_PLATE_2 "Activate plate 2", // plate 2 activating + 4 BCT_ACTIVATE_PLATE_3 "Activate plate 3", // plate 3 activating + 5 BCT_ACTIVATE_PLATE_4 "Activate plate 4", // plate 4 activating + 6 BCT_ACTIVATE_PYRAMID_MORPH_ROOM "Pyramid morph room", // pyramid morph room activated +}; + +class CBlendController: CMarker +{ +name "Blend controller"; +thumbnail "Thumbnails\\BlendController.tbn"; +features "IsImportant"; + +properties: + + 1 enum BlendControllerType m_bctType "Blend type" 'Y' = BCT_NONE, // type of effect + +components: + + 1 model MODEL_CONTROLLER "Models\\Editor\\BlendController.mdl", + 2 texture TEXTURE_CONTROLLER "Models\\Editor\\BlendController.tex", + + +functions: + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + // obtain world settings controller + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc == NULL) { + return FALSE; + } + FLOAT tmNow = _pTimer->CurrentTick(); + + if (ee.ee_slEvent==EVENTCODE_EActivate) + { + switch(m_bctType) + { + case BCT_PYRAMID_PLATES: + pwsc->m_tmPyramidPlatesStart = tmNow; + break; + case BCT_ACTIVATE_PLATE_1: + pwsc->m_tmActivatedPlate1 = tmNow; + pwsc->m_tmDeactivatedPlate1 = 1e6; + break; + case BCT_ACTIVATE_PLATE_2: + pwsc->m_tmActivatedPlate2 = tmNow; + pwsc->m_tmDeactivatedPlate2 = 1e6; + break; + case BCT_ACTIVATE_PLATE_3: + pwsc->m_tmActivatedPlate3 = tmNow; + pwsc->m_tmDeactivatedPlate3 = 1e6; + break; + case BCT_ACTIVATE_PLATE_4: + pwsc->m_tmActivatedPlate4 = tmNow; + pwsc->m_tmDeactivatedPlate4 = 1e6; + break; + case BCT_ACTIVATE_PYRAMID_MORPH_ROOM: + pwsc->m_tmPyramidMorphRoomActivated = tmNow; + break; + } + } + else if (ee.ee_slEvent==EVENTCODE_EDeactivate) + { + switch(m_bctType) + { + case BCT_ACTIVATE_PLATE_1: + pwsc->m_tmDeactivatedPlate1 = tmNow; + break; + case BCT_ACTIVATE_PLATE_2: + pwsc->m_tmDeactivatedPlate2 = tmNow; + break; + case BCT_ACTIVATE_PLATE_3: + pwsc->m_tmDeactivatedPlate3 = tmNow; + break; + case BCT_ACTIVATE_PLATE_4: + pwsc->m_tmDeactivatedPlate4 = tmNow; + break; + } + } + return FALSE; + } + +procedures: + + Main() + { + // init model + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_CONTROLLER); + SetModelMainTexture(TEXTURE_CONTROLLER); + + return; + } +}; + diff --git a/Sources/EntitiesMP/BlendController.h b/Sources/EntitiesMP/BlendController.h new file mode 100644 index 0000000..0a764ae --- /dev/null +++ b/Sources/EntitiesMP/BlendController.h @@ -0,0 +1,33 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_BlendController_INCLUDED +#define _EntitiesMP_BlendController_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType BlendControllerType_enum; +enum BlendControllerType { + BCT_NONE = 0, + BCT_PYRAMID_PLATES = 1, + BCT_ACTIVATE_PLATE_1 = 2, + BCT_ACTIVATE_PLATE_2 = 3, + BCT_ACTIVATE_PLATE_3 = 4, + BCT_ACTIVATE_PLATE_4 = 5, + BCT_ACTIVATE_PYRAMID_MORPH_ROOM = 6, +}; +DECL_DLL inline void ClearToDefault(BlendControllerType &e) { e = (BlendControllerType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CBlendController_DLLClass; +class CBlendController : public CMarker { +public: +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + enum BlendControllerType m_bctType; + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CBlendController_Main 1 + BOOL +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_BlendController_INCLUDED diff --git a/Sources/EntitiesMP/BlendController_tables.h b/Sources/EntitiesMP/BlendController_tables.h new file mode 100644 index 0000000..a0c8561 --- /dev/null +++ b/Sources/EntitiesMP/BlendController_tables.h @@ -0,0 +1,46 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(BlendControllerType) + EP_ENUMVALUE(BCT_NONE, "None"), + EP_ENUMVALUE(BCT_PYRAMID_PLATES, "Appear pyramid plates"), + EP_ENUMVALUE(BCT_ACTIVATE_PLATE_1, "Activate plate 1"), + EP_ENUMVALUE(BCT_ACTIVATE_PLATE_2, "Activate plate 2"), + EP_ENUMVALUE(BCT_ACTIVATE_PLATE_3, "Activate plate 3"), + EP_ENUMVALUE(BCT_ACTIVATE_PLATE_4, "Activate plate 4"), + EP_ENUMVALUE(BCT_ACTIVATE_PYRAMID_MORPH_ROOM, "Pyramid morph room"), +EP_ENUMEND(BlendControllerType); + +#define ENTITYCLASS CBlendController + +CEntityProperty CBlendController_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &BlendControllerType_enum, (0x00000264<<8)+1, offsetof(CBlendController, m_bctType), "Blend type", 'Y', 0x7F0000FFUL, 0), +}; +#define CBlendController_propertiesct ARRAYCOUNT(CBlendController_properties) + +CEntityComponent CBlendController_components[] = { +#define MODEL_CONTROLLER ((0x00000264<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_CONTROLLER, "EFNM" "Models\\Editor\\BlendController.mdl"), +#define TEXTURE_CONTROLLER ((0x00000264<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_CONTROLLER, "EFNM" "Models\\Editor\\BlendController.tex"), +}; +#define CBlendController_componentsct ARRAYCOUNT(CBlendController_components) + +CEventHandlerEntry CBlendController_handlers[] = { + {1, -1, CEntity::pEventHandler(&CBlendController:: +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/BlendController.es" +Main),DEBUGSTRING("CBlendController::Main")}, +}; +#define CBlendController_handlersct ARRAYCOUNT(CBlendController_handlers) + +CEntity *CBlendController_New(void) { return new CBlendController; }; +void CBlendController_OnInitClass(void) {}; +void CBlendController_OnEndClass(void) {}; +void CBlendController_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CBlendController_OnWorldEnd(CWorld *pwo) {}; +void CBlendController_OnWorldInit(CWorld *pwo) {}; +void CBlendController_OnWorldTick(CWorld *pwo) {}; +void CBlendController_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CBlendController, CMarker, "Blend controller", "Thumbnails\\BlendController.tbn", 0x00000264); +DECLARE_CTFILENAME(_fnmCBlendController_tbn, "Thumbnails\\BlendController.tbn"); diff --git a/Sources/EntitiesMP/BloodSpray.cpp b/Sources/EntitiesMP/BloodSpray.cpp new file mode 100644 index 0000000..2f51d6e --- /dev/null +++ b/Sources/EntitiesMP/BloodSpray.cpp @@ -0,0 +1,254 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *ESpawnSpray::MakeCopy(void) { CEntityEvent *peeCopy = new ESpawnSpray(*this); return peeCopy;} +ESpawnSpray::ESpawnSpray() : CEntityEvent(EVENTCODE_ESpawnSpray) {; + ClearToDefault(sptType); + ClearToDefault(fDamagePower); + ClearToDefault(fSizeMultiplier); + ClearToDefault(vDirection); + ClearToDefault(penOwner); + ClearToDefault(colCentralColor); + ClearToDefault(fLaunchPower); + ClearToDefault(colBurnColor); +}; +void CBloodSpray::SetDefaultProperties(void) { + m_sptType = SPT_NONE ; + m_tmStarted = 0.0f; + m_vDirection = FLOAT3D(0 , 0 , 0); + m_penOwner = NULL; + m_fDamagePower = 1.0f; + m_boxSizedOwner = FLOATaabbox3D(FLOAT3D (0 , 0 , 0) , 0.01f); + m_vGDir = FLOAT3D(0 , 0 , 0); + m_fGA = 0.0f; + m_fLaunchPower = 1.0f; + m_colCentralColor = COLOR(C_WHITE | CT_OPAQUE ); + m_boxOriginalOwner = FLOATaabbox3D(FLOAT3D (0 , 0 , 0) , 0.01f); + m_colBurnColor = COLOR(C_WHITE | CT_OPAQUE ); + m_penPrediction = NULL; + CRationalEntity::SetDefaultProperties(); +} + +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +void CBloodSpray::RenderParticles(void) +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +{ +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +switch(m_sptType ) +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +{ +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_BLOOD : +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_BONES : +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_FEATHER : +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_STONES : +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_WOOD : +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_SLIME : +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_LAVA_STONES : +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_SMALL_LAVA_STONES : +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_BEAST_PROJECTILE_SPRAY : +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_AIRSPOUTS : +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_GOO : +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +{ +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_BloodSpray (m_sptType , GetLerpedPlacement () . pl_PositionVector , m_vGDir , m_fGA , +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_boxSizedOwner , m_vDirection , m_tmStarted , m_fDamagePower , m_colBurnColor ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +break ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +} +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_COLOREDSTONE : +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +{ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_BloodSpray (m_sptType , GetLerpedPlacement () . pl_PositionVector , m_vGDir , m_fGA , +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_boxSizedOwner , m_vDirection , m_tmStarted , m_fDamagePower , MulColors (m_colCentralColor , m_colBurnColor )); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +break ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +} +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_TREE01 : +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_BloodSpray (SPT_WOOD , GetLerpedPlacement () . pl_PositionVector , m_vGDir , m_fGA / 1.5f , +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_boxSizedOwner , m_vDirection , m_tmStarted , m_fDamagePower / 2.0f , m_colBurnColor ); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_Leaves (m_penOwner , m_boxOriginalOwner , GetLerpedPlacement () . pl_PositionVector , +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_fDamagePower , m_fDamagePower * m_fLaunchPower , m_vGDir , +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_fGA / 2.0f , m_tmStarted , MulColors (m_colCentralColor , m_colBurnColor )); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +break ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_PLASMA : +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_BloodSpray (m_sptType , GetLerpedPlacement () . pl_PositionVector , m_vGDir , m_fGA , +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_boxSizedOwner , m_vDirection , m_tmStarted , m_fDamagePower ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_DamageSmoke (this , m_tmStarted , m_boxSizedOwner , m_fDamagePower ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_ElectricitySparks (this , m_tmStarted , 5.0f , 0.0f , 32); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +break ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_ELECTRICITY_SPARKS : +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +{ +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_MetalParts (this , m_tmStarted , m_boxSizedOwner , m_fDamagePower ); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_DamageSmoke (this , m_tmStarted , m_boxSizedOwner , m_fDamagePower ); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_BloodSpray (SPT_BLOOD , GetLerpedPlacement () . pl_PositionVector , m_vGDir , m_fGA , +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_boxSizedOwner , m_vDirection , m_tmStarted , m_fDamagePower / 2.0f , C_WHITE | CT_OPAQUE ); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_ElectricitySparks (this , m_tmStarted , 5.0f , 0.0f , 32); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +break ; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +} +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +case SPT_ELECTRICITY_SPARKS_NO_BLOOD : +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +{ +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_MetalParts (this , m_tmStarted , m_boxSizedOwner , m_fDamagePower ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_DamageSmoke (this , m_tmStarted , m_boxSizedOwner , m_fDamagePower ); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Particles_ElectricitySparks (this , m_tmStarted , 5.0f , 0.0f , 32); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +} +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +} +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +} +BOOL CBloodSpray:: +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBloodSpray_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_ESpawnSpray, "CBloodSpray::Main expects 'ESpawnSpray' as input!"); const ESpawnSpray &eSpawn = (const ESpawnSpray &)__eeInput; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +InitAsEditorModel (); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +SetPredictable (TRUE ); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +SetModel (MODEL_MARKER ); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_sptType = eSpawn . sptType ; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_vDirection = eSpawn . vDirection ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_penOwner = eSpawn . penOwner ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_fDamagePower = eSpawn . fDamagePower ; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_fLaunchPower = eSpawn . fLaunchPower ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_colBurnColor = eSpawn . colBurnColor ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_tmStarted = _pTimer -> CurrentTick (); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_colCentralColor = eSpawn . colCentralColor ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +if(eSpawn . penOwner == NULL || eSpawn . penOwner -> en_pmoModelObject == NULL ) +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +{ +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Destroy (); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Return(STATE_CURRENT,EVoid()); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +return TRUE; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +} +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +if(eSpawn . penOwner -> en_RenderType == RT_SKAMODEL ){ +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +eSpawn . penOwner -> GetModelInstance () -> GetCurrentColisionBox (m_boxSizedOwner ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +}else { +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +eSpawn . penOwner -> en_pmoModelObject -> GetCurrentFrameBBox (m_boxSizedOwner ); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_boxOriginalOwner = m_boxSizedOwner ; +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_boxSizedOwner . StretchByVector (eSpawn . penOwner -> en_pmoModelObject -> mo_Stretch * eSpawn . fSizeMultiplier ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_boxOriginalOwner . StretchByVector (eSpawn . penOwner -> en_pmoModelObject -> mo_Stretch ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +} +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +if(m_penOwner -> GetPhysicsFlags () & EPF_MOVABLE ){ +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_vGDir = ((CMovableEntity *) & * m_penOwner ) -> en_vGravityDir ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_fGA = ((CMovableEntity *) & * m_penOwner ) -> en_fGravityA ; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +}else { +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +FLOATmatrix3D & m = m_penOwner -> en_mRotation ; +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_vGDir = FLOAT3D (- m (1 , 2) , - m (2 , 2) , - m (3 , 2)); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +m_fGA = 30.0f; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +} +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +FLOAT fWaitTime = 4.0f; +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +if(m_sptType == SPT_ELECTRICITY_SPARKS || m_sptType == SPT_ELECTRICITY_SPARKS_NO_BLOOD ) +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +{ +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +fWaitTime = 4.0f; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +} +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +SetTimerAfter(fWaitTime ); +Jump(STATE_CURRENT, 0x025b0001, FALSE, EBegin());return TRUE;}BOOL CBloodSpray::H0x025b0001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025b0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x025b0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBloodSpray::H0x025b0002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025b0002 +; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Destroy (); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Return(STATE_CURRENT,EVoid()); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/BloodSpray.es b/Sources/EntitiesMP/BloodSpray.es new file mode 100644 index 0000000..8d48e09 --- /dev/null +++ b/Sources/EntitiesMP/BloodSpray.es @@ -0,0 +1,168 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +603 +%{ +#include "StdH.h" +%} + +// input parameter for spawning a blood spray +event ESpawnSpray { + enum SprayParticlesType sptType, // type of particles + FLOAT fDamagePower, // factor saying how powerfull damage has been + FLOAT fSizeMultiplier, // stretch factor + FLOAT3D vDirection, // dammage direction + CEntityPointer penOwner, // who spawned the spray + COLOR colCentralColor, // central color of particles that is randomized a little + FLOAT fLaunchPower, + COLOR colBurnColor, // burn color +}; + +class CBloodSpray: CRationalEntity { +name "Blood Spray"; +thumbnail ""; +features "CanBePredictable"; + +properties: + + 1 enum SprayParticlesType m_sptType = SPT_NONE, // type of particles + 2 FLOAT m_tmStarted = 0.0f, // time when spawned + 3 FLOAT3D m_vDirection = FLOAT3D(0,0,0), // dammage direction + 5 CEntityPointer m_penOwner, // who spawned the spray + 6 FLOAT m_fDamagePower = 1.0f, // power of inflicted damage + 8 FLOATaabbox3D m_boxSizedOwner = FLOATaabbox3D(FLOAT3D(0,0,0), 0.01f), // bounding box of blood spray's owner + 9 FLOAT3D m_vGDir = FLOAT3D(0,0,0), // gravity direction + 10 FLOAT m_fGA = 0.0f, // gravity strength + 11 FLOAT m_fLaunchPower = 1.0f, + 12 COLOR m_colCentralColor = COLOR(C_WHITE|CT_OPAQUE), + 13 FLOATaabbox3D m_boxOriginalOwner = FLOATaabbox3D(FLOAT3D(0,0,0), 0.01f), + 14 COLOR m_colBurnColor = COLOR(C_WHITE|CT_OPAQUE), + + +components: + 1 model MODEL_MARKER "Models\\Editor\\Axis.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex" + +functions: + + // particles + void RenderParticles(void) + { + switch( m_sptType) + { + case SPT_BLOOD: + case SPT_BONES: + case SPT_FEATHER: + case SPT_STONES: + case SPT_WOOD: + case SPT_SLIME: + case SPT_LAVA_STONES: + case SPT_SMALL_LAVA_STONES: + case SPT_BEAST_PROJECTILE_SPRAY: + case SPT_AIRSPOUTS: + case SPT_GOO: + { + Particles_BloodSpray(m_sptType, GetLerpedPlacement().pl_PositionVector, m_vGDir, m_fGA, + m_boxSizedOwner, m_vDirection, m_tmStarted, m_fDamagePower, m_colBurnColor); + break; + } + case SPT_COLOREDSTONE: + { + Particles_BloodSpray(m_sptType, GetLerpedPlacement().pl_PositionVector, m_vGDir, m_fGA, + m_boxSizedOwner, m_vDirection, m_tmStarted, m_fDamagePower, MulColors(m_colCentralColor, m_colBurnColor) ); + break; + } + case SPT_TREE01: + Particles_BloodSpray(SPT_WOOD, GetLerpedPlacement().pl_PositionVector, m_vGDir, m_fGA/1.5f, + m_boxSizedOwner, m_vDirection, m_tmStarted, m_fDamagePower/2.0f, m_colBurnColor); + Particles_Leaves(m_penOwner, m_boxOriginalOwner, GetLerpedPlacement().pl_PositionVector, + m_fDamagePower, m_fDamagePower*m_fLaunchPower, m_vGDir, + m_fGA/2.0f, m_tmStarted, MulColors(m_colCentralColor,m_colBurnColor)); + break; + case SPT_PLASMA: + Particles_BloodSpray(m_sptType, GetLerpedPlacement().pl_PositionVector, m_vGDir, m_fGA, + m_boxSizedOwner, m_vDirection, m_tmStarted, m_fDamagePower); + Particles_DamageSmoke(this, m_tmStarted, m_boxSizedOwner, m_fDamagePower); + Particles_ElectricitySparks( this, m_tmStarted, 5.0f, 0.0f, 32); + break; + case SPT_ELECTRICITY_SPARKS: + { + Particles_MetalParts(this, m_tmStarted, m_boxSizedOwner, m_fDamagePower); + Particles_DamageSmoke(this, m_tmStarted, m_boxSizedOwner, m_fDamagePower); + Particles_BloodSpray(SPT_BLOOD, GetLerpedPlacement().pl_PositionVector, m_vGDir, m_fGA, + m_boxSizedOwner, m_vDirection, m_tmStarted, m_fDamagePower/2.0f, C_WHITE|CT_OPAQUE); + Particles_ElectricitySparks( this, m_tmStarted, 5.0f, 0.0f, 32); + break; + } + case SPT_ELECTRICITY_SPARKS_NO_BLOOD: + { + Particles_MetalParts(this, m_tmStarted, m_boxSizedOwner, m_fDamagePower); + Particles_DamageSmoke(this, m_tmStarted, m_boxSizedOwner, m_fDamagePower); + Particles_ElectricitySparks( this, m_tmStarted, 5.0f, 0.0f, 32); + } + } + }; + +/************************************************************ + * MAIN * + ************************************************************/ + +procedures: + + Main( ESpawnSpray eSpawn) + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + SetPredictable(TRUE); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + // setup variables + m_sptType = eSpawn.sptType; + m_vDirection = eSpawn.vDirection; + m_penOwner = eSpawn.penOwner; + m_fDamagePower = eSpawn.fDamagePower; + m_fLaunchPower = eSpawn.fLaunchPower; + m_colBurnColor = eSpawn.colBurnColor; + m_tmStarted = _pTimer->CurrentTick(); + m_colCentralColor = eSpawn.colCentralColor; + + // if owner doesn't exist (could be destroyed in initialization) + if( eSpawn.penOwner==NULL || eSpawn.penOwner->en_pmoModelObject == NULL) + { + // don't do anything + Destroy(); + return; + } + + if(eSpawn.penOwner->en_RenderType == RT_SKAMODEL) { + eSpawn.penOwner->GetModelInstance()->GetCurrentColisionBox( m_boxSizedOwner); + } else { + eSpawn.penOwner->en_pmoModelObject->GetCurrentFrameBBox( m_boxSizedOwner); + m_boxOriginalOwner=m_boxSizedOwner; + m_boxSizedOwner.StretchByVector(eSpawn.penOwner->en_pmoModelObject->mo_Stretch*eSpawn.fSizeMultiplier); + m_boxOriginalOwner.StretchByVector(eSpawn.penOwner->en_pmoModelObject->mo_Stretch); + } + + if (m_penOwner->GetPhysicsFlags()&EPF_MOVABLE) { + m_vGDir = ((CMovableEntity *)&*m_penOwner)->en_vGravityDir; + m_fGA = ((CMovableEntity *)&*m_penOwner)->en_fGravityA; + } else { + FLOATmatrix3D &m = m_penOwner->en_mRotation; + m_vGDir = FLOAT3D(-m(1,2), -m(2,2), -m(3,2)); + m_fGA = 30.0f; + } + + FLOAT fWaitTime = 4.0f; + if( m_sptType==SPT_ELECTRICITY_SPARKS || m_sptType==SPT_ELECTRICITY_SPARKS_NO_BLOOD) + { + fWaitTime = 4.0f; + } + autowait(fWaitTime); + Destroy(); + + return; + } +}; diff --git a/Sources/EntitiesMP/BloodSpray.h b/Sources/EntitiesMP/BloodSpray.h new file mode 100644 index 0000000..04e8488 --- /dev/null +++ b/Sources/EntitiesMP/BloodSpray.h @@ -0,0 +1,51 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_BloodSpray_INCLUDED +#define _EntitiesMP_BloodSpray_INCLUDED 1 +#define EVENTCODE_ESpawnSpray 0x025b0000 +class DECL_DLL ESpawnSpray : public CEntityEvent { +public: +ESpawnSpray(); +CEntityEvent *MakeCopy(void); +enum SprayParticlesType sptType; +FLOAT fDamagePower; +FLOAT fSizeMultiplier; +FLOAT3D vDirection; +CEntityPointer penOwner; +COLOR colCentralColor; +FLOAT fLaunchPower; +COLOR colBurnColor; +}; +DECL_DLL inline void ClearToDefault(ESpawnSpray &e) { e = ESpawnSpray(); } ; +extern "C" DECL_DLL CDLLEntityClass CBloodSpray_DLLClass; +class CBloodSpray : public CRationalEntity { +public: +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + DECL_DLL virtual void SetDefaultProperties(void); + enum SprayParticlesType m_sptType; + FLOAT m_tmStarted; + FLOAT3D m_vDirection; + CEntityPointer m_penOwner; + FLOAT m_fDamagePower; + FLOATaabbox3D m_boxSizedOwner; + FLOAT3D m_vGDir; + FLOAT m_fGA; + FLOAT m_fLaunchPower; + COLOR m_colCentralColor; + FLOATaabbox3D m_boxOriginalOwner; + COLOR m_colBurnColor; + CEntityPointer m_penPrediction; + +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +void RenderParticles(void); +#define STATE_CBloodSpray_Main 1 + BOOL +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x025b0001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x025b0002_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_BloodSpray_INCLUDED diff --git a/Sources/EntitiesMP/BloodSpray_tables.h b/Sources/EntitiesMP/BloodSpray_tables.h new file mode 100644 index 0000000..64b063f --- /dev/null +++ b/Sources/EntitiesMP/BloodSpray_tables.h @@ -0,0 +1,50 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CBloodSpray + +CEntityProperty CBloodSpray_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &SprayParticlesType_enum, (0x0000025b<<8)+1, offsetof(CBloodSpray, m_sptType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025b<<8)+2, offsetof(CBloodSpray, m_tmStarted), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000025b<<8)+3, offsetof(CBloodSpray, m_vDirection), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025b<<8)+5, offsetof(CBloodSpray, m_penOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025b<<8)+6, offsetof(CBloodSpray, m_fDamagePower), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATAABBOX3D, NULL, (0x0000025b<<8)+8, offsetof(CBloodSpray, m_boxSizedOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000025b<<8)+9, offsetof(CBloodSpray, m_vGDir), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025b<<8)+10, offsetof(CBloodSpray, m_fGA), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025b<<8)+11, offsetof(CBloodSpray, m_fLaunchPower), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025b<<8)+12, offsetof(CBloodSpray, m_colCentralColor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATAABBOX3D, NULL, (0x0000025b<<8)+13, offsetof(CBloodSpray, m_boxOriginalOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025b<<8)+14, offsetof(CBloodSpray, m_colBurnColor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025b<<8)+255, offsetof(CBloodSpray, m_penPrediction), "", 0, 0, 0), +}; +#define CBloodSpray_propertiesct ARRAYCOUNT(CBloodSpray_properties) + +CEntityComponent CBloodSpray_components[] = { +#define MODEL_MARKER ((0x0000025b<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_MARKER ((0x0000025b<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Vector.tex"), +}; +#define CBloodSpray_componentsct ARRAYCOUNT(CBloodSpray_components) + +CEventHandlerEntry CBloodSpray_handlers[] = { + {1, -1, CEntity::pEventHandler(&CBloodSpray:: +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/BloodSpray.es" +Main),DEBUGSTRING("CBloodSpray::Main")}, + {0x025b0001, -1, CEntity::pEventHandler(&CBloodSpray::H0x025b0001_Main_01), DEBUGSTRING("CBloodSpray::H0x025b0001_Main_01")}, + {0x025b0002, -1, CEntity::pEventHandler(&CBloodSpray::H0x025b0002_Main_02), DEBUGSTRING("CBloodSpray::H0x025b0002_Main_02")}, +}; +#define CBloodSpray_handlersct ARRAYCOUNT(CBloodSpray_handlers) + +CEntity *CBloodSpray_New(void) { return new CBloodSpray; }; +void CBloodSpray_OnInitClass(void) {}; +void CBloodSpray_OnEndClass(void) {}; +void CBloodSpray_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CBloodSpray_OnWorldEnd(CWorld *pwo) {}; +void CBloodSpray_OnWorldInit(CWorld *pwo) {}; +void CBloodSpray_OnWorldTick(CWorld *pwo) {}; +void CBloodSpray_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CBloodSpray, CRationalEntity, "Blood Spray", "", 0x0000025b); +DECLARE_CTFILENAME(_fnmCBloodSpray_tbn, ""); diff --git a/Sources/EntitiesMP/Boneman.cpp b/Sources/EntitiesMP/Boneman.cpp new file mode 100644 index 0000000..183fe50 --- /dev/null +++ b/Sources/EntitiesMP/Boneman.cpp @@ -0,0 +1,645 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" + +#include "StdH.h" +#include "Models/Enemies/Boneman/Boneman.h" + +#include +#include +#line 11 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" + +// info structure +static EntityInfo eiBoneman = { + EIBT_BONES, 250.0f, + 0.0f, 1.9f, 0.0f, // source (eyes) + 0.0f, 1.9f, 0.0f, // target (body) +}; + +#define BONES_HIT 2.8f +#define FIRE_RIGHT_HAND FLOAT3D( 0.25f, 1.5f, 0.0f) +#define FIRE_LEFT_HAND FLOAT3D(-0.25f, 1.5f, 0.0f) + +void CBoneman::SetDefaultProperties(void) { + m_bFistHit = FALSE ; + m_bTouchAnother = FALSE ; + m_soFeet.SetOwner(this); +m_soFeet.Stop_internal(); + m_bRunSoundPlaying = FALSE ; + CEnemyBase::SetDefaultProperties(); +} + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::Precache(void) { +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +CEnemyBase :: Precache (); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheSound (SOUND_IDLE ); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheSound (SOUND_SIGHT ); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheSound (SOUND_WOUND ); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheSound (SOUND_FIRE ); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheSound (SOUND_KICK ); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheSound (SOUND_PUNCH ); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheSound (SOUND_DEATH ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheSound (SOUND_RUN ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheModel (MODEL_BONEMAN_BODY ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheModel (MODEL_BONEMAN_HAND ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheModel (MODEL_BONEMAN_LEGS ); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PrecacheClass (CLASS_PROJECTILE , PRT_BONEMAN_FIRE ); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + CTString CBoneman::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +{ +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +CTString str ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(eDeath . eLastDamage . dmtType == DMT_CLOSERANGE ){ +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +str . PrintF (TRANS ("%s was ripped apart by a Kleer") , strPlayerName ); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +}else { +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +str . PrintF (TRANS ("%s was killed by a Kleer") , strPlayerName ); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return str ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + const CTFileName & CBoneman::GetComputerMessageName(void)const { +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +static DECLARE_CTFILENAME (fnm , "Data\\Messages\\Enemies\\Boneman.txt"); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return fnm ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void * CBoneman::GetEntityInfo(void) { +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return & eiBoneman ; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +{ +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(! IsOfClass (penInflictor , "Boneman")){ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::LeaveStain(BOOL bGrow) +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +{ +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +INDEX CBoneman::AnimForDamage(FLOAT fDamage) { +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +INDEX iAnim ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +switch(IRnd () % 5){ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +case 0: iAnim = BONEMAN_ANIM_WOUNDCRITICAL01 ;break ; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +case 1: iAnim = BONEMAN_ANIM_WOUNDCRITICAL02 ;break ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +case 2: iAnim = BONEMAN_ANIM_WOUNDCRITICAL03 ;break ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +case 3: iAnim = BONEMAN_ANIM_FALL01 ;break ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +case 4: iAnim = BONEMAN_ANIM_FALL02 ;break ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +default : ASSERTALWAYS ("Boneman unknown damage"); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +StartModelAnim (iAnim , 0); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +DeactivateRunningSound (); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return iAnim ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +INDEX CBoneman::AnimForDeath(void) { +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +INDEX iAnim ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +switch(IRnd () % 2){ +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +case 0: iAnim = BONEMAN_ANIM_DEATHTOBACK ;break ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +case 1: iAnim = BONEMAN_ANIM_DEATHTOFRONT ;break ; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +default : ASSERTALWAYS ("Boneman unknown death"); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +StartModelAnim (iAnim , 0); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +DeactivateRunningSound (); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return iAnim ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT CBoneman::WaitForDust(FLOAT3D & vStretch) { +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(GetModelObject () -> GetAnim () == BONEMAN_ANIM_DEATHTOBACK ) +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +{ +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +vStretch = FLOAT3D (1 , 1 , 2) * 1.0f; +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return 0.48f; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +else if(GetModelObject () -> GetAnim () == BONEMAN_ANIM_DEATHTOFRONT ) +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +{ +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +vStretch = FLOAT3D (1 , 1 , 2) * 0.75f; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return 0.48f; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return - 1.0f; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::DeathNotify(void) { +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +ChangeCollisionBoxIndexWhenPossible (BONEMAN_COLLISION_BOX_DEATH ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::StandingAnim(void) { +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +StartModelAnim (BONEMAN_ANIM_STANDLOOP , AOF_LOOPING | AOF_NORESTART ); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +DeactivateRunningSound (); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::WalkingAnim(void) { +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +StartModelAnim (BONEMAN_ANIM_WALKLOOP , AOF_LOOPING | AOF_NORESTART ); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +DeactivateRunningSound (); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::RunningAnim(void) { +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +StartModelAnim (BONEMAN_ANIM_RUNLOOP , AOF_LOOPING | AOF_NORESTART ); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +ActivateRunningSound (); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::RotatingAnim(void) { +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +StartModelAnim (BONEMAN_ANIM_WALKLOOP , AOF_LOOPING | AOF_NORESTART ); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +DeactivateRunningSound (); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::IdleSound(void) { +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::SightSound(void) { +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::WoundSound(void) { +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::DeathSound(void) { +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::ActivateRunningSound(void) +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +{ +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(! m_bRunSoundPlaying ){ +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PlaySound (m_soFeet , SOUND_RUN , SOF_3D | SOF_LOOP ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_bRunSoundPlaying = TRUE ; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::DeactivateRunningSound(void) +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +{ +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_soFeet . Stop (); +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_bRunSoundPlaying = FALSE ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} + +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void CBoneman::BlowUp(void) { +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOATaabbox3D box ; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +GetBoundingBox (box ); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT fEntitySize = box . Size () . MaxNorm (); +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT3D vNormalizedDamage = m_vDamage - m_vDamage * (m_fBlowUpAmount / m_vDamage . Length ()); +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +vNormalizedDamage /= Sqrt (vNormalizedDamage . Length ()); +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +vNormalizedDamage *= 0.75f; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute - en_vGravityDir * (en_vGravityDir % en_vCurrentTranslationAbsolute ); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Debris_Begin (EIBT_BONES , DPT_NONE , BET_NONE , fEntitySize , vNormalizedDamage , vBodySpeed , 5.0f , 2.0f); +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Debris_Spawn (this , this , MODEL_BONEMAN_BODY , TEXTURE_BONEMAN , 0 , 0 , 0 , 0 , 0.0f , +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Debris_Spawn (this , this , MODEL_BONEMAN_HAND , TEXTURE_BONEMAN , 0 , 0 , 0 , 0 , 0.0f , +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Debris_Spawn (this , this , MODEL_BONEMAN_HAND , TEXTURE_BONEMAN , 0 , 0 , 0 , 0 , 0.0f , +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Debris_Spawn (this , this , MODEL_BONEMAN_LEGS , TEXTURE_BONEMAN , 0 , 0 , 0 , 0 , 0.0f , +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SwitchToEditorModel (); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +BOOL CBoneman:: +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBoneman_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBoneman::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +StartModelAnim (BONEMAN_ANIM_ATTACKCLOSELOOP , 0); +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +DeactivateRunningSound (); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetTimerAfter(0.35f); +Jump(STATE_CURRENT, 0x01310001, FALSE, EBegin());return TRUE;}BOOL CBoneman::H0x01310001_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01310002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBoneman::H0x01310002_Fire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310002 +; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +ShootProjectile (PRT_BONEMAN_FIRE , FIRE_RIGHT_HAND , ANGLE3D (0 , 0 , 0)); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D ); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetTimerAfter(0.45f); +Jump(STATE_CURRENT, 0x01310003, FALSE, EBegin());return TRUE;}BOOL CBoneman::H0x01310003_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01310004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBoneman::H0x01310004_Fire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310004 +; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +ShootProjectile (PRT_BONEMAN_FIRE , FIRE_LEFT_HAND , ANGLE3D (0 , 0 , 0)); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetTimerAfter(FRnd () / 3 + 0.6f); +Jump(STATE_CURRENT, 0x01310005, FALSE, EBegin());return TRUE;}BOOL CBoneman::H0x01310005_Fire_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01310006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBoneman::H0x01310006_Fire_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310006 +; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Return(STATE_CURRENT,EReturn ()); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CBoneman:: +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBoneman_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBoneman::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(CalcDist (m_penEnemy ) < BONES_HIT ){ +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Jump(STATE_CURRENT, STATE_CBoneman_HitWithBones, TRUE, EVoid());return TRUE; +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +}else if(CalcDist (m_penEnemy ) < 10.0f){ +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Jump(STATE_CURRENT, STATE_CBoneman_JumpOnEnemy, TRUE, EVoid());return TRUE; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fShootTime = _pTimer -> CurrentTick () + 0.5f; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Return(STATE_CURRENT,EReturn ()); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CBoneman:: +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +JumpOnEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBoneman_JumpOnEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBoneman::JumpOnEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +StartModelAnim (BONEMAN_ANIM_ATTACKFAR , 0); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +DeactivateRunningSound (); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT3D vDir = (m_penEnemy -> GetPlacement () . pl_PositionVector - +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +GetPlacement () . pl_PositionVector ) . Normalize (); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +vDir *= ! GetRotationMatrix (); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +vDir *= m_fCloseRunSpeed * 1.5f; +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +vDir (2) = 2.5f; +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetDesiredTranslation (vDir ); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PlaySound (m_soSound , SOUND_KICK , SOF_3D ); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SpawnReminder (this , 0.5f , 0); +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_iChargeHitAnimation = BONEMAN_ANIM_ATTACKFAR ; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fChargeHitDamage = 20.0f; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fChargeHitAngle = 0.0f; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fChargeHitSpeed = 15.0f; +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +STATE_CEnemyBase_ChargeHitEnemy, FALSE; +Jump(STATE_CURRENT, 0x01310009, FALSE, EBegin());return TRUE;}BOOL CBoneman::H0x01310009_JumpOnEnemy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_ChargeHitEnemy, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0131000a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CBoneman::H0x0131000a_JumpOnEnemy_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0131000a +const EReturn&__e= (EReturn&)__eeInput; +; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetTimerAfter(0.3f); +Jump(STATE_CURRENT, 0x0131000b, FALSE, EBegin());return TRUE;}BOOL CBoneman::H0x0131000b_JumpOnEnemy_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0131000b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0131000c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBoneman::H0x0131000c_JumpOnEnemy_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0131000c +; +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Return(STATE_CURRENT,EReturn ()); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CBoneman:: +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +HitWithBones(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBoneman_HitWithBones + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBoneman::HitWithBones expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +StartModelAnim (BONEMAN_ANIM_ATTACKCLOSELOOP , 0); +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +DeactivateRunningSound (); +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_bFistHit = FALSE ; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetTimerAfter(0.35f); +Jump(STATE_CURRENT, 0x0131000e, FALSE, EBegin());return TRUE;}BOOL CBoneman::H0x0131000e_HitWithBones_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0131000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0131000f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBoneman::H0x0131000f_HitWithBones_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0131000f +; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(CalcDist (m_penEnemy ) < BONES_HIT ){m_bFistHit = TRUE ;} +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PlaySound (m_soSound , SOUND_PUNCH , SOF_3D ); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetTimerAfter(0.10f); +Jump(STATE_CURRENT, 0x01310010, FALSE, EBegin());return TRUE;}BOOL CBoneman::H0x01310010_HitWithBones_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310010 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01310011, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBoneman::H0x01310011_HitWithBones_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310011 +; +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(CalcDist (m_penEnemy ) < BONES_HIT ){m_bFistHit = TRUE ;} +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(m_bFistHit ){ +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +vDirection . Normalize (); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 10.0f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT3D vSpeed ; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +GetHeadingDirection (AngleDeg (90.0f) , vSpeed ); +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +vSpeed = vSpeed * 5.0f; +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +KickEntity (m_penEnemy , vSpeed ); +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_bFistHit = FALSE ; +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x01310012, FALSE, EBegin());return TRUE;}BOOL CBoneman::H0x01310012_HitWithBones_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310012 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01310013, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBoneman::H0x01310013_HitWithBones_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310013 +; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(CalcDist (m_penEnemy ) < BONES_HIT ){m_bFistHit = TRUE ;} +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +PlaySound (m_soSound , SOUND_PUNCH , SOF_3D ); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetTimerAfter(0.10f); +Jump(STATE_CURRENT, 0x01310014, FALSE, EBegin());return TRUE;}BOOL CBoneman::H0x01310014_HitWithBones_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310014 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01310015, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CBoneman::H0x01310015_HitWithBones_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01310015 +; +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(CalcDist (m_penEnemy ) < BONES_HIT ){m_bFistHit = TRUE ;} +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(m_bFistHit ){ +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +vDirection . Normalize (); +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 10.0f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT3D vSpeed ; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +GetHeadingDirection (AngleDeg (- 90.0f) , vSpeed ); +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +vSpeed = vSpeed * 5.0f; +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +KickEntity (m_penEnemy , vSpeed ); +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Return(STATE_CURRENT,EReturn ()); +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CBoneman:: +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBoneman_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBoneman::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +InitAsModel (); +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetCollisionFlags (ECF_MODEL ); +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetHealth (125.0f); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fMaxHealth = 125.0f; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +en_fDensity = 2000.0f; +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetModel (MODEL_BONEMAN ); +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +SetModelMainTexture (TEXTURE_BONEMAN ); +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +StandingAnim (); +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_sptType = SPT_BONES ; +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fWalkSpeed = FRnd () + 2.5f; +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_aWalkRotateSpeed = FRnd () * 25.0f + 45.0f; +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fAttackRunSpeed = FRnd () * 3.0f + 10.0f; +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_aAttackRotateSpeed = FRnd () * 200 + 600.0f; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fCloseRunSpeed = FRnd () + 13.0f; +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_aCloseRotateSpeed = FRnd () * 100 + 1000.0f; +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fAttackDistance = 100.0f; +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fCloseDistance = 30.0f; +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fStopDistance = 2.0f; +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fAttackFireTime = 3.0f; +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fCloseFireTime = 2.0f; +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fIgnoreRange = 200.0f; +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fBlowUpAmount = 70.0f; +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fBodyParts = 4; +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fDamageWounded = 80.0f; +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_iScore = 1000; +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +if(m_fStepHeight == - 1){ +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_fStepHeight = 4.0f; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +} +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +CEnemyBase :: SizeModel (); +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_soFeet . Set3DParameters (80.0f , 5.0f , 1.0f , 1.0f); +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +m_bRunSoundPlaying = FALSE ; +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Boneman.es b/Sources/EntitiesMP/Boneman.es new file mode 100644 index 0000000..5379529 --- /dev/null +++ b/Sources/EntitiesMP/Boneman.es @@ -0,0 +1,401 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +305 +%{ +#include "StdH.h" +#include "Models/Enemies/Boneman/Boneman.h" +%} + +uses "EntitiesMP/EnemyBase"; + +%{ +// info structure +static EntityInfo eiBoneman = { + EIBT_BONES, 250.0f, + 0.0f, 1.9f, 0.0f, // source (eyes) + 0.0f, 1.9f, 0.0f, // target (body) +}; + +#define BONES_HIT 2.8f +#define FIRE_RIGHT_HAND FLOAT3D( 0.25f, 1.5f, 0.0f) +#define FIRE_LEFT_HAND FLOAT3D(-0.25f, 1.5f, 0.0f) +%} + + +class CBoneman : CEnemyBase { +name "Boneman"; +thumbnail "Thumbnails\\Boneman.tbn"; + +properties: + 2 BOOL m_bFistHit = FALSE, // used for close attack + 3 BOOL m_bTouchAnother = FALSE, // another entity touched on far attack + 4 CSoundObject m_soFeet, // for running sound + 5 BOOL m_bRunSoundPlaying = FALSE, + +components: + 0 class CLASS_BASE "Classes\\EnemyBase.ecl", + 1 model MODEL_BONEMAN "Models\\Enemies\\Boneman\\Boneman.mdl", + 2 texture TEXTURE_BONEMAN "Models\\Enemies\\Boneman\\Boneman.tex", + 3 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + +// ************** BONEMAN PARTS ************** + 10 model MODEL_BONEMAN_BODY "Models\\Enemies\\Boneman\\Debris\\Body.mdl", + 11 model MODEL_BONEMAN_HAND "Models\\Enemies\\Boneman\\Debris\\Hand.mdl", + 12 model MODEL_BONEMAN_LEGS "Models\\Enemies\\Boneman\\Debris\\Legs.mdl", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "Models\\Enemies\\Boneman\\Sounds\\Idle.wav", + 51 sound SOUND_SIGHT "Models\\Enemies\\Boneman\\Sounds\\Sight.wav", + 52 sound SOUND_WOUND "Models\\Enemies\\Boneman\\Sounds\\Wound.wav", + 53 sound SOUND_FIRE "Models\\Enemies\\Boneman\\Sounds\\Fire.wav", + 54 sound SOUND_KICK "Models\\Enemies\\Boneman\\Sounds\\Kick.wav", + 55 sound SOUND_PUNCH "Models\\Enemies\\Boneman\\Sounds\\Punch.wav", + 56 sound SOUND_DEATH "Models\\Enemies\\Boneman\\Sounds\\Death.wav", + 57 sound SOUND_RUN "Models\\Enemies\\Boneman\\Sounds\\Run.wav", + +functions: + void Precache(void) { + CEnemyBase::Precache(); + PrecacheSound(SOUND_IDLE ); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_FIRE ); + PrecacheSound(SOUND_KICK ); + PrecacheSound(SOUND_PUNCH); + PrecacheSound(SOUND_DEATH); + PrecacheSound(SOUND_RUN ); + + PrecacheModel(MODEL_BONEMAN_BODY); + PrecacheModel(MODEL_BONEMAN_HAND); + PrecacheModel(MODEL_BONEMAN_LEGS); + + PrecacheClass(CLASS_PROJECTILE, PRT_BONEMAN_FIRE); + }; + + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + if (eDeath.eLastDamage.dmtType==DMT_CLOSERANGE) { + str.PrintF(TRANS("%s was ripped apart by a Kleer"), strPlayerName); + } else { + str.PrintF(TRANS("%s was killed by a Kleer"), strPlayerName); + } + return str; + } + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnm, "Data\\Messages\\Enemies\\Boneman.txt"); + return fnm; + }; + + /* Entity info */ + void *GetEntityInfo(void) { + return &eiBoneman; + }; + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // boneman can't harm boneman + if (!IsOfClass(penInflictor, "Boneman")) { + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + }; + + void LeaveStain(BOOL bGrow) + { + // boneman doesn't leave bloody stain + } + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim; + switch (IRnd()%5) { + case 0: iAnim = BONEMAN_ANIM_WOUNDCRITICAL01; break; + case 1: iAnim = BONEMAN_ANIM_WOUNDCRITICAL02; break; + case 2: iAnim = BONEMAN_ANIM_WOUNDCRITICAL03; break; + case 3: iAnim = BONEMAN_ANIM_FALL01; break; + case 4: iAnim = BONEMAN_ANIM_FALL02; break; + default: ASSERTALWAYS("Boneman unknown damage"); + } + StartModelAnim(iAnim, 0); + DeactivateRunningSound(); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + INDEX iAnim; + switch (IRnd()%2) { + case 0: iAnim = BONEMAN_ANIM_DEATHTOBACK; break; + case 1: iAnim = BONEMAN_ANIM_DEATHTOFRONT; break; + default: ASSERTALWAYS("Boneman unknown death"); + } + StartModelAnim(iAnim, 0); + DeactivateRunningSound(); + return iAnim; + }; + + FLOAT WaitForDust(FLOAT3D &vStretch) { + if(GetModelObject()->GetAnim()==BONEMAN_ANIM_DEATHTOBACK) + { + vStretch=FLOAT3D(1,1,2)*1.0f; + return 0.48f; + } + else if(GetModelObject()->GetAnim()==BONEMAN_ANIM_DEATHTOFRONT) + { + vStretch=FLOAT3D(1,1,2)*0.75f; + return 0.48f; + } + return -1.0f; + }; + + void DeathNotify(void) { + ChangeCollisionBoxIndexWhenPossible(BONEMAN_COLLISION_BOX_DEATH); + }; + + // virtual anim functions + void StandingAnim(void) { + StartModelAnim(BONEMAN_ANIM_STANDLOOP, AOF_LOOPING|AOF_NORESTART); + DeactivateRunningSound(); + }; + void WalkingAnim(void) { + StartModelAnim(BONEMAN_ANIM_WALKLOOP, AOF_LOOPING|AOF_NORESTART); + DeactivateRunningSound(); + }; + void RunningAnim(void) { + StartModelAnim(BONEMAN_ANIM_RUNLOOP, AOF_LOOPING|AOF_NORESTART); + ActivateRunningSound(); + }; + void RotatingAnim(void) { + StartModelAnim(BONEMAN_ANIM_WALKLOOP, AOF_LOOPING|AOF_NORESTART); + DeactivateRunningSound(); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + + // running sounds + void ActivateRunningSound(void) + { + if (!m_bRunSoundPlaying) { + PlaySound(m_soFeet, SOUND_RUN, SOF_3D|SOF_LOOP); + m_bRunSoundPlaying = TRUE; + } + } + void DeactivateRunningSound(void) + { + m_soFeet.Stop(); + m_bRunSoundPlaying = FALSE; + } + +/************************************************************ + * BLOW UP FUNCTIONS * + ************************************************************/ + // spawn body parts + void BlowUp(void) { + // get your size + FLOATaabbox3D box; + GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm(); + + FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(m_fBlowUpAmount/m_vDamage.Length()); + vNormalizedDamage /= Sqrt(vNormalizedDamage.Length()); + + vNormalizedDamage *= 0.75f; + + FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute); + + // spawn debris + Debris_Begin(EIBT_BONES, DPT_NONE, BET_NONE, fEntitySize, vNormalizedDamage, vBodySpeed, 5.0f, 2.0f); + + Debris_Spawn(this, this, MODEL_BONEMAN_BODY, TEXTURE_BONEMAN, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_BONEMAN_HAND, TEXTURE_BONEMAN, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_BONEMAN_HAND, TEXTURE_BONEMAN, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_BONEMAN_LEGS, TEXTURE_BONEMAN, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + + // hide yourself (must do this after spawning debris) + SwitchToEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + }; + + + + + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + Fire(EVoid) : CEnemyBase::Fire { + // fire projectile + StartModelAnim(BONEMAN_ANIM_ATTACKCLOSELOOP, 0); + DeactivateRunningSound(); + autowait(0.35f); + ShootProjectile(PRT_BONEMAN_FIRE, FIRE_RIGHT_HAND, ANGLE3D(0, 0, 0)); + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(0.45f); + ShootProjectile(PRT_BONEMAN_FIRE, FIRE_LEFT_HAND, ANGLE3D(0, 0, 0)); + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(FRnd()/3+0.6f); + + return EReturn(); + }; + + Hit(EVoid) : CEnemyBase::Hit { + // hit + if (CalcDist(m_penEnemy) < BONES_HIT) { + jump HitWithBones(); + + // jump + } else if (CalcDist(m_penEnemy) < 10.0f) { + jump JumpOnEnemy(); + } + + // run to enemy + m_fShootTime = _pTimer->CurrentTick() + 0.5f; + return EReturn(); + }; + + // jump on enemy + JumpOnEnemy(EVoid) { + StartModelAnim(BONEMAN_ANIM_ATTACKFAR, 0); + DeactivateRunningSound(); + + // jump + FLOAT3D vDir = (m_penEnemy->GetPlacement().pl_PositionVector - + GetPlacement().pl_PositionVector).Normalize(); + vDir *= !GetRotationMatrix(); + vDir *= m_fCloseRunSpeed*1.5f; + vDir(2) = 2.5f; + SetDesiredTranslation(vDir); + PlaySound(m_soSound, SOUND_KICK, SOF_3D); + + // animation - IGNORE DAMAGE WOUND - + SpawnReminder(this, 0.5f, 0); + m_iChargeHitAnimation = BONEMAN_ANIM_ATTACKFAR; + m_fChargeHitDamage = 20.0f; + m_fChargeHitAngle = 0.0f; + m_fChargeHitSpeed = 15.0f; + autocall CEnemyBase::ChargeHitEnemy() EReturn; + autowait(0.3f); + return EReturn(); + }; + + // hit with bones + HitWithBones(EVoid) { + // attack with bones + StartModelAnim(BONEMAN_ANIM_ATTACKCLOSELOOP, 0); + DeactivateRunningSound(); + + // right hand + m_bFistHit = FALSE; + autowait(0.35f); + if (CalcDist(m_penEnemy)GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.Normalize(); + // damage enemy + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 10.0f, FLOAT3D(0, 0, 0), vDirection); + // push target left + FLOAT3D vSpeed; + GetHeadingDirection(AngleDeg(90.0f), vSpeed); + vSpeed = vSpeed * 5.0f; + KickEntity(m_penEnemy, vSpeed); + } + + // left hand + m_bFistHit = FALSE; + autowait(0.25f); + if (CalcDist(m_penEnemy)GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.Normalize(); + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 10.0f, FLOAT3D(0, 0, 0), vDirection); + // push target left + FLOAT3D vSpeed; + GetHeadingDirection(AngleDeg(-90.0f), vSpeed); + vSpeed = vSpeed * 5.0f; + KickEntity(m_penEnemy, vSpeed); + } + return EReturn(); + }; + + + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + SetHealth(125.0f); + m_fMaxHealth = 125.0f; + en_fDensity = 2000.0f; + + // set your appearance + SetModel(MODEL_BONEMAN); + SetModelMainTexture(TEXTURE_BONEMAN); + StandingAnim(); + m_sptType = SPT_BONES; + // setup moving speed + m_fWalkSpeed = FRnd() + 2.5f; + m_aWalkRotateSpeed = FRnd()*25.0f + 45.0f; + m_fAttackRunSpeed = FRnd()*3.0f + 10.0f; + m_aAttackRotateSpeed = FRnd()*200 + 600.0f; + m_fCloseRunSpeed = FRnd() + 13.0f; + m_aCloseRotateSpeed = FRnd()*100 + 1000.0f; + // setup attack distances + m_fAttackDistance = 100.0f; + m_fCloseDistance = 30.0f; + m_fStopDistance = 2.0f; + m_fAttackFireTime = 3.0f; + m_fCloseFireTime = 2.0f; + m_fIgnoreRange = 200.0f; + // damage/explode properties + m_fBlowUpAmount = 70.0f; + m_fBodyParts = 4; + m_fDamageWounded = 80.0f; + m_iScore = 1000; + if (m_fStepHeight==-1) { + m_fStepHeight = 4.0f; + } + + // set stretch factors for height and width + CEnemyBase::SizeModel(); + m_soFeet.Set3DParameters(80.0f, 5.0f, 1.0f, 1.0f); + m_bRunSoundPlaying = FALSE; + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Boneman.h b/Sources/EntitiesMP/Boneman.h new file mode 100644 index 0000000..935e26c --- /dev/null +++ b/Sources/EntitiesMP/Boneman.h @@ -0,0 +1,120 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Boneman_INCLUDED +#define _EntitiesMP_Boneman_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CBoneman_DLLClass; +class CBoneman : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bFistHit; + BOOL m_bTouchAnother; + CSoundObject m_soFeet; + BOOL m_bRunSoundPlaying; + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void Precache(void); + +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void * GetEntityInfo(void); + +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void LeaveStain(BOOL bGrow); + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +INDEX AnimForDeath(void); + +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void DeathNotify(void); + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void StandingAnim(void); + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void WalkingAnim(void); + +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void RunningAnim(void); + +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void RotatingAnim(void); + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void IdleSound(void); + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void SightSound(void); + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void WoundSound(void); + +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void DeathSound(void); + +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void ActivateRunningSound(void); + +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void DeactivateRunningSound(void); + +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +void BlowUp(void); +#define STATE_CBoneman_Fire 0x01310000 + BOOL +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x01310001_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x01310002_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x01310003_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x01310004_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x01310005_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x01310006_Fire_06(const CEntityEvent &__eeInput); +#define STATE_CBoneman_Hit 0x01310007 + BOOL +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Hit(const CEntityEvent &__eeInput); +#define STATE_CBoneman_JumpOnEnemy 0x01310008 + BOOL +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +JumpOnEnemy(const CEntityEvent &__eeInput); + BOOL H0x01310009_JumpOnEnemy_01(const CEntityEvent &__eeInput); + BOOL H0x0131000a_JumpOnEnemy_02(const CEntityEvent &__eeInput); + BOOL H0x0131000b_JumpOnEnemy_03(const CEntityEvent &__eeInput); + BOOL H0x0131000c_JumpOnEnemy_04(const CEntityEvent &__eeInput); +#define STATE_CBoneman_HitWithBones 0x0131000d + BOOL +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +HitWithBones(const CEntityEvent &__eeInput); + BOOL H0x0131000e_HitWithBones_01(const CEntityEvent &__eeInput); + BOOL H0x0131000f_HitWithBones_02(const CEntityEvent &__eeInput); + BOOL H0x01310010_HitWithBones_03(const CEntityEvent &__eeInput); + BOOL H0x01310011_HitWithBones_04(const CEntityEvent &__eeInput); + BOOL H0x01310012_HitWithBones_05(const CEntityEvent &__eeInput); + BOOL H0x01310013_HitWithBones_06(const CEntityEvent &__eeInput); + BOOL H0x01310014_HitWithBones_07(const CEntityEvent &__eeInput); + BOOL H0x01310015_HitWithBones_08(const CEntityEvent &__eeInput); +#define STATE_CBoneman_Main 1 + BOOL +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Boneman_INCLUDED diff --git a/Sources/EntitiesMP/Boneman_tables.h b/Sources/EntitiesMP/Boneman_tables.h new file mode 100644 index 0000000..dda895e --- /dev/null +++ b/Sources/EntitiesMP/Boneman_tables.h @@ -0,0 +1,95 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CBoneman + +CEntityProperty CBoneman_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000131<<8)+2, offsetof(CBoneman, m_bFistHit), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000131<<8)+3, offsetof(CBoneman, m_bTouchAnother), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000131<<8)+4, offsetof(CBoneman, m_soFeet), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000131<<8)+5, offsetof(CBoneman, m_bRunSoundPlaying), "", 0, 0, 0), +}; +#define CBoneman_propertiesct ARRAYCOUNT(CBoneman_properties) + +CEntityComponent CBoneman_components[] = { +#define CLASS_BASE ((0x00000131<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define MODEL_BONEMAN ((0x00000131<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_BONEMAN, "EFNM" "Models\\Enemies\\Boneman\\Boneman.mdl"), +#define TEXTURE_BONEMAN ((0x00000131<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_BONEMAN, "EFNM" "Models\\Enemies\\Boneman\\Boneman.tex"), +#define CLASS_PROJECTILE ((0x00000131<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define MODEL_BONEMAN_BODY ((0x00000131<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_BONEMAN_BODY, "EFNM" "Models\\Enemies\\Boneman\\Debris\\Body.mdl"), +#define MODEL_BONEMAN_HAND ((0x00000131<<8)+11) + CEntityComponent(ECT_MODEL, MODEL_BONEMAN_HAND, "EFNM" "Models\\Enemies\\Boneman\\Debris\\Hand.mdl"), +#define MODEL_BONEMAN_LEGS ((0x00000131<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_BONEMAN_LEGS, "EFNM" "Models\\Enemies\\Boneman\\Debris\\Legs.mdl"), +#define SOUND_IDLE ((0x00000131<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "Models\\Enemies\\Boneman\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000131<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "Models\\Enemies\\Boneman\\Sounds\\Sight.wav"), +#define SOUND_WOUND ((0x00000131<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "Models\\Enemies\\Boneman\\Sounds\\Wound.wav"), +#define SOUND_FIRE ((0x00000131<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_FIRE, "EFNM" "Models\\Enemies\\Boneman\\Sounds\\Fire.wav"), +#define SOUND_KICK ((0x00000131<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_KICK, "EFNM" "Models\\Enemies\\Boneman\\Sounds\\Kick.wav"), +#define SOUND_PUNCH ((0x00000131<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_PUNCH, "EFNM" "Models\\Enemies\\Boneman\\Sounds\\Punch.wav"), +#define SOUND_DEATH ((0x00000131<<8)+56) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "Models\\Enemies\\Boneman\\Sounds\\Death.wav"), +#define SOUND_RUN ((0x00000131<<8)+57) + CEntityComponent(ECT_SOUND, SOUND_RUN, "EFNM" "Models\\Enemies\\Boneman\\Sounds\\Run.wav"), +}; +#define CBoneman_componentsct ARRAYCOUNT(CBoneman_components) + +CEventHandlerEntry CBoneman_handlers[] = { + {0x01310000, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CBoneman:: +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Fire),DEBUGSTRING("CBoneman::Fire")}, + {0x01310001, -1, CEntity::pEventHandler(&CBoneman::H0x01310001_Fire_01), DEBUGSTRING("CBoneman::H0x01310001_Fire_01")}, + {0x01310002, -1, CEntity::pEventHandler(&CBoneman::H0x01310002_Fire_02), DEBUGSTRING("CBoneman::H0x01310002_Fire_02")}, + {0x01310003, -1, CEntity::pEventHandler(&CBoneman::H0x01310003_Fire_03), DEBUGSTRING("CBoneman::H0x01310003_Fire_03")}, + {0x01310004, -1, CEntity::pEventHandler(&CBoneman::H0x01310004_Fire_04), DEBUGSTRING("CBoneman::H0x01310004_Fire_04")}, + {0x01310005, -1, CEntity::pEventHandler(&CBoneman::H0x01310005_Fire_05), DEBUGSTRING("CBoneman::H0x01310005_Fire_05")}, + {0x01310006, -1, CEntity::pEventHandler(&CBoneman::H0x01310006_Fire_06), DEBUGSTRING("CBoneman::H0x01310006_Fire_06")}, + {0x01310007, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CBoneman:: +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Hit),DEBUGSTRING("CBoneman::Hit")}, + {0x01310008, -1, CEntity::pEventHandler(&CBoneman:: +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +JumpOnEnemy),DEBUGSTRING("CBoneman::JumpOnEnemy")}, + {0x01310009, -1, CEntity::pEventHandler(&CBoneman::H0x01310009_JumpOnEnemy_01), DEBUGSTRING("CBoneman::H0x01310009_JumpOnEnemy_01")}, + {0x0131000a, -1, CEntity::pEventHandler(&CBoneman::H0x0131000a_JumpOnEnemy_02), DEBUGSTRING("CBoneman::H0x0131000a_JumpOnEnemy_02")}, + {0x0131000b, -1, CEntity::pEventHandler(&CBoneman::H0x0131000b_JumpOnEnemy_03), DEBUGSTRING("CBoneman::H0x0131000b_JumpOnEnemy_03")}, + {0x0131000c, -1, CEntity::pEventHandler(&CBoneman::H0x0131000c_JumpOnEnemy_04), DEBUGSTRING("CBoneman::H0x0131000c_JumpOnEnemy_04")}, + {0x0131000d, -1, CEntity::pEventHandler(&CBoneman:: +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +HitWithBones),DEBUGSTRING("CBoneman::HitWithBones")}, + {0x0131000e, -1, CEntity::pEventHandler(&CBoneman::H0x0131000e_HitWithBones_01), DEBUGSTRING("CBoneman::H0x0131000e_HitWithBones_01")}, + {0x0131000f, -1, CEntity::pEventHandler(&CBoneman::H0x0131000f_HitWithBones_02), DEBUGSTRING("CBoneman::H0x0131000f_HitWithBones_02")}, + {0x01310010, -1, CEntity::pEventHandler(&CBoneman::H0x01310010_HitWithBones_03), DEBUGSTRING("CBoneman::H0x01310010_HitWithBones_03")}, + {0x01310011, -1, CEntity::pEventHandler(&CBoneman::H0x01310011_HitWithBones_04), DEBUGSTRING("CBoneman::H0x01310011_HitWithBones_04")}, + {0x01310012, -1, CEntity::pEventHandler(&CBoneman::H0x01310012_HitWithBones_05), DEBUGSTRING("CBoneman::H0x01310012_HitWithBones_05")}, + {0x01310013, -1, CEntity::pEventHandler(&CBoneman::H0x01310013_HitWithBones_06), DEBUGSTRING("CBoneman::H0x01310013_HitWithBones_06")}, + {0x01310014, -1, CEntity::pEventHandler(&CBoneman::H0x01310014_HitWithBones_07), DEBUGSTRING("CBoneman::H0x01310014_HitWithBones_07")}, + {0x01310015, -1, CEntity::pEventHandler(&CBoneman::H0x01310015_HitWithBones_08), DEBUGSTRING("CBoneman::H0x01310015_HitWithBones_08")}, + {1, -1, CEntity::pEventHandler(&CBoneman:: +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Boneman.es" +Main),DEBUGSTRING("CBoneman::Main")}, +}; +#define CBoneman_handlersct ARRAYCOUNT(CBoneman_handlers) + +CEntity *CBoneman_New(void) { return new CBoneman; }; +void CBoneman_OnInitClass(void) {}; +void CBoneman_OnEndClass(void) {}; +void CBoneman_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CBoneman_OnWorldEnd(CWorld *pwo) {}; +void CBoneman_OnWorldInit(CWorld *pwo) {}; +void CBoneman_OnWorldTick(CWorld *pwo) {}; +void CBoneman_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CBoneman, CEnemyBase, "Boneman", "Thumbnails\\Boneman.tbn", 0x00000131); +DECLARE_CTFILENAME(_fnmCBoneman_tbn, "Thumbnails\\Boneman.tbn"); diff --git a/Sources/EntitiesMP/Bouncer.cpp b/Sources/EntitiesMP/Bouncer.cpp new file mode 100644 index 0000000..2cd07d2 --- /dev/null +++ b/Sources/EntitiesMP/Bouncer.cpp @@ -0,0 +1,71 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" + +#include "StdH.h" + +#include +#include +#line 8 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" + + +extern DECL_DLL void JumpFromBouncer(CEntity *penToBounce, CEntity *penBouncer) +{ + CEntity *pen = penToBounce; + CBouncer *pbo = (CBouncer *)penBouncer; + // if it is a movable model and some time has passed from the last jump + if ( (pen->GetRenderType()==CEntity::RT_MODEL) && + (pen->GetPhysicsFlags()&EPF_MOVABLE) ) { + CMovableEntity *pmen = (CMovableEntity *)pen; + if (pmen->en_penReference==NULL) { + return; + } + // give it speed + FLOAT3D vDir; + AnglesToDirectionVector(pbo->m_aDirection, vDir); + pmen->FakeJump(pmen->en_vIntendedTranslation, vDir, pbo->m_fSpeed, + -pbo->m_fParallelComponentMultiplier, pbo->m_fNormalComponentMultiplier, pbo->m_fMaxExitSpeed, pbo->m_tmControl); + } +} + + +void CBouncer::SetDefaultProperties(void) { + m_strName = "Bouncer"; + m_strDescription = ""; + m_fSpeed = 20.0f; + m_aDirection = ANGLE3D(0 , 90 , 0); + m_tmControl = 5.0f; + m_bEntrySpeed = TRUE ; + m_fMaxExitSpeed = 200.0f; + m_fNormalComponentMultiplier = 1.0f; + m_fParallelComponentMultiplier = 0.0f; + CRationalEntity::SetDefaultProperties(); +} +BOOL CBouncer:: +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBouncer_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CBouncer::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +InitAsBrush (); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +SetPhysicsFlags (EPF_BRUSH_FIXED | EPF_NOIMPACT ); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +SetCollisionFlags (ECF_BRUSH ); +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +if(! m_bEntrySpeed ) +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +{ +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +m_fNormalComponentMultiplier = 0.0f; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +m_bEntrySpeed = TRUE ; +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +} +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +Return(STATE_CURRENT,EVoid()); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Bouncer.es b/Sources/EntitiesMP/Bouncer.es new file mode 100644 index 0000000..e448d2b --- /dev/null +++ b/Sources/EntitiesMP/Bouncer.es @@ -0,0 +1,67 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +105 +%{ +#include "StdH.h" +%} + +%{ + +extern DECL_DLL void JumpFromBouncer(CEntity *penToBounce, CEntity *penBouncer) +{ + CEntity *pen = penToBounce; + CBouncer *pbo = (CBouncer *)penBouncer; + // if it is a movable model and some time has passed from the last jump + if ( (pen->GetRenderType()==CEntity::RT_MODEL) && + (pen->GetPhysicsFlags()&EPF_MOVABLE) ) { + CMovableEntity *pmen = (CMovableEntity *)pen; + if (pmen->en_penReference==NULL) { + return; + } + // give it speed + FLOAT3D vDir; + AnglesToDirectionVector(pbo->m_aDirection, vDir); + pmen->FakeJump(pmen->en_vIntendedTranslation, vDir, pbo->m_fSpeed, + -pbo->m_fParallelComponentMultiplier, pbo->m_fNormalComponentMultiplier, pbo->m_fMaxExitSpeed, pbo->m_tmControl); + } +} + +%} + +class CBouncer : CRationalEntity { +name "Bouncer"; +thumbnail "Thumbnails\\Bouncer.tbn"; +features "HasName"; + +properties: + 1 CTString m_strName "Name" 'N' = "Bouncer", + 2 CTString m_strDescription = "", + + 4 FLOAT m_fSpeed "Speed [m/s]" 'S' = 20.0f, + 5 ANGLE3D m_aDirection "Direction" 'D' = ANGLE3D(0,90,0), + 6 FLOAT m_tmControl "Control time" 'T' = 5.0f, + 7 BOOL m_bEntrySpeed = TRUE, + 10 FLOAT m_fMaxExitSpeed "Max exit speed" 'M' = 200.0f, + 12 FLOAT m_fNormalComponentMultiplier "Normal component multiplier" 'O' = 1.0f, + 13 FLOAT m_fParallelComponentMultiplier "Parallel component multiplier" 'P' = 0.0f, + +components: +functions: +procedures: + Main() { + // declare yourself as a brush + InitAsBrush(); + SetPhysicsFlags(EPF_BRUSH_FIXED|EPF_NOIMPACT); + SetCollisionFlags(ECF_BRUSH); + + // if old flag "entry speed" has been reset + if (!m_bEntrySpeed) + { + // kill normal component by default (same behaviour by default) + m_fNormalComponentMultiplier = 0.0f; + m_bEntrySpeed = TRUE; + } + return; + } +}; + \ No newline at end of file diff --git a/Sources/EntitiesMP/Bouncer.h b/Sources/EntitiesMP/Bouncer.h new file mode 100644 index 0000000..29328c2 --- /dev/null +++ b/Sources/EntitiesMP/Bouncer.h @@ -0,0 +1,26 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Bouncer_INCLUDED +#define _EntitiesMP_Bouncer_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CBouncer_DLLClass; +class CBouncer : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + FLOAT m_fSpeed; + ANGLE3D m_aDirection; + FLOAT m_tmControl; + BOOL m_bEntrySpeed; + FLOAT m_fMaxExitSpeed; + FLOAT m_fNormalComponentMultiplier; + FLOAT m_fParallelComponentMultiplier; +#define STATE_CBouncer_Main 1 + BOOL +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Bouncer_INCLUDED diff --git a/Sources/EntitiesMP/Bouncer_tables.h b/Sources/EntitiesMP/Bouncer_tables.h new file mode 100644 index 0000000..376c5d6 --- /dev/null +++ b/Sources/EntitiesMP/Bouncer_tables.h @@ -0,0 +1,42 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CBouncer + +CEntityProperty CBouncer_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000069<<8)+1, offsetof(CBouncer, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000069<<8)+2, offsetof(CBouncer, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000069<<8)+4, offsetof(CBouncer, m_fSpeed), "Speed [m/s]", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x00000069<<8)+5, offsetof(CBouncer, m_aDirection), "Direction", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000069<<8)+6, offsetof(CBouncer, m_tmControl), "Control time", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000069<<8)+7, offsetof(CBouncer, m_bEntrySpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000069<<8)+10, offsetof(CBouncer, m_fMaxExitSpeed), "Max exit speed", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000069<<8)+12, offsetof(CBouncer, m_fNormalComponentMultiplier), "Normal component multiplier", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000069<<8)+13, offsetof(CBouncer, m_fParallelComponentMultiplier), "Parallel component multiplier", 'P', 0x7F0000FFUL, 0), +}; +#define CBouncer_propertiesct ARRAYCOUNT(CBouncer_properties) + +CEntityComponent CBouncer_components[] = { + CEntityComponent() +}; +#define CBouncer_componentsct 0 + + +CEventHandlerEntry CBouncer_handlers[] = { + {1, -1, CEntity::pEventHandler(&CBouncer:: +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Bouncer.es" +Main),DEBUGSTRING("CBouncer::Main")}, +}; +#define CBouncer_handlersct ARRAYCOUNT(CBouncer_handlers) + +CEntity *CBouncer_New(void) { return new CBouncer; }; +void CBouncer_OnInitClass(void) {}; +void CBouncer_OnEndClass(void) {}; +void CBouncer_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CBouncer_OnWorldEnd(CWorld *pwo) {}; +void CBouncer_OnWorldInit(CWorld *pwo) {}; +void CBouncer_OnWorldTick(CWorld *pwo) {}; +void CBouncer_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CBouncer, CRationalEntity, "Bouncer", "Thumbnails\\Bouncer.tbn", 0x00000069); +DECLARE_CTFILENAME(_fnmCBouncer_tbn, "Thumbnails\\Bouncer.tbn"); diff --git a/Sources/EntitiesMP/Bullet.cpp b/Sources/EntitiesMP/Bullet.cpp new file mode 100644 index 0000000..aa858a1 --- /dev/null +++ b/Sources/EntitiesMP/Bullet.cpp @@ -0,0 +1,414 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *EBulletInit::MakeCopy(void) { CEntityEvent *peeCopy = new EBulletInit(*this); return peeCopy;} +EBulletInit::EBulletInit() : CEntityEvent(EVENTCODE_EBulletInit) {; + ClearToDefault(penOwner); + ClearToDefault(fDamage); +}; +#line 18 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" + +void CBullet_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSTONE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSAND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINREDSAND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINWATER); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSTONENOSOUND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSANDNOSOUND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINREDSANDNOSOUND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINWATERNOSOUND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSPILL); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETTRAIL); +} + +void CBullet::SetDefaultProperties(void) { + m_penOwner = NULL; + m_fDamage = 0.0f; + m_vTarget = FLOAT3D(0 , 0 , 0); + m_vTargetCopy = FLOAT3D(0 , 0 , 0); + m_vHitPoint = FLOAT3D(0 , 0 , 0); + m_iBullet = 0; + m_EdtDamage = DMT_BULLET ; + m_fBulletSize = 0.0f; + CEntity::SetDefaultProperties(); +} + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CBullet::SetDamage(FLOAT fDamage) { +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_fDamage = fDamage ; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CBullet::CalcTarget(FLOAT fRange) { +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +AnglesToDirectionVector (GetPlacement () . pl_OrientationAngle , m_vTarget ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_vTarget *= fRange ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_vTarget += GetPlacement () . pl_PositionVector ; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_vTargetCopy = m_vTarget ; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} + +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CBullet::CalcTarget(CEntity * pen,FLOAT fRange) { +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT3D vTarget ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +EntityInfo * peiTarget = (EntityInfo *) (pen -> GetEntityInfo ()); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +GetEntityInfoPosition (pen , peiTarget -> vTargetCenter , vTarget ); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_vTarget = (vTarget - GetPlacement () . pl_PositionVector ) . Normalize (); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_vTarget *= fRange ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_vTarget += GetPlacement () . pl_PositionVector ; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_vTargetCopy = m_vTarget ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CBullet::CalcJitterTarget(FLOAT fR) { +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT3D vJitter ; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT fZ = FRnd () * 2.0f - 1.0f; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT fA = FRnd () * 360.0f; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT fT = Sqrt (1 - (fZ * fZ )); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vJitter (1) = fT * CosFast (fA ); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vJitter (2) = fT * SinFast (fA ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vJitter (3) = fZ ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vJitter = vJitter * fR * FRnd (); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_vTarget = m_vTargetCopy + vJitter ; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} + +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CBullet::CalcJitterTargetFixed(FLOAT fX,FLOAT fY,FLOAT fJitter) { +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT fRndX = FRnd () * 2.0f - 1.0f; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT fRndY = FRnd () * 2.0f - 1.0f; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT3D vX , vY ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +const FLOATmatrix3D & m = GetRotationMatrix (); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vX (1) = m (1 , 1);vX (2) = m (2 , 1);vX (3) = m (3 , 1); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vY (1) = m (1 , 2);vY (2) = m (2 , 2);vY (3) = m (3 , 2); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_vTarget = m_vTargetCopy + (vX * (fX + fRndX * fJitter )) + (vY * (fY + fRndY * fJitter )); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CBullet::LaunchBullet(BOOL bSound,BOOL bTrail,BOOL bHitFX) +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +CCastRay crRay (m_penOwner , GetPlacement () . pl_PositionVector , m_vTarget ); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +crRay . cr_bHitPortals = TRUE ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +crRay . cr_bHitTranslucentPortals = TRUE ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +crRay . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +crRay . cr_bPhysical = FALSE ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +crRay . cr_fTestR = m_fBulletSize ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT3D vHitDirection ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +AnglesToDirectionVector (GetPlacement () . pl_OrientationAngle , vHitDirection ); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +INDEX ctCasts = 0; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +while(ctCasts < 10) +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(ctCasts == 0) +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +GetWorld () -> CastRay (crRay ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +else +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +GetWorld () -> ContinueCast (crRay ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +ctCasts ++; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(crRay . cr_penHit == NULL ) +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +break ; +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +const FLOAT fDamageMul = GetSeriousDamageMultiplier (m_penOwner ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +InflictDirectDamage (crRay . cr_penHit , m_penOwner , m_EdtDamage , m_fDamage * fDamageMul , +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +crRay . cr_vHit , vHitDirection ); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_vHitPoint = crRay . cr_vHit ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(crRay . cr_penHit -> GetRenderType () == RT_BRUSH && crRay . cr_pbpoBrushPolygon != NULL ) +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +CBrushPolygon * pbpo = crRay . cr_pbpoBrushPolygon ; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT3D vHitNormal = FLOAT3D (pbpo -> bpo_pbplPlane -> bpl_plAbsolute ); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +INDEX iSurfaceType = pbpo -> bpo_bppProperties . bpp_ubSurfaceType ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +BulletHitType bhtType = BHT_BRUSH_STONE ; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +INDEX iContent = pbpo -> bpo_pbscSector -> GetContentType (); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +CContentType & ct = GetWorld () -> wo_actContentTypes [ iContent ]; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +bhtType = (BulletHitType ) GetBulletHitTypeForSurface (iSurfaceType ); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(ct . ct_ulFlags & CTF_BREATHABLE_GILLS ) +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(iSurfaceType == SURFACE_WATER ) +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vHitNormal = - vHitNormal ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +bhtType = BHT_BRUSH_WATER ; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +else +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +bhtType = BHT_BRUSH_UNDER_WATER ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +BOOL bPassable = pbpo -> bpo_ulFlags & (BPOF_PASSABLE | BPOF_SHOOTTHRU ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(! bPassable || iSurfaceType == SURFACE_WATER ){ +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +SpawnHitTypeEffect (this , bhtType , bSound , vHitNormal , crRay . cr_vHit , vHitDirection , FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(! bPassable ){ +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +break ; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +}else { +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(crRay . cr_penHit -> GetEntityInfo () != NULL ){ +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(((EntityInfo *) crRay . cr_penHit -> GetEntityInfo ()) -> Eeibt == EIBT_FLESH ) +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +CEntity * penOfFlesh = crRay . cr_penHit ; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT3D vHitNormal = (GetPlacement () . pl_PositionVector - m_vTarget ) . Normalize (); +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT3D vOldHitPos = crRay . cr_vHit ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT3D vDistance ; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +GetWorld () -> ContinueCast (crRay ); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(crRay . cr_penHit != NULL && crRay . cr_pbpoBrushPolygon != NULL && +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +crRay . cr_penHit -> GetRenderType () == RT_BRUSH ) +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vDistance = crRay . cr_vHit - vOldHitPos ; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vHitNormal = FLOAT3D (crRay . cr_pbpoBrushPolygon -> bpo_pbplPlane -> bpl_plAbsolute ); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +else +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vDistance = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vHitNormal = FLOAT3D (0 , 0 , 0); +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(IsOfClass (penOfFlesh , "Gizmo") || +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +IsOfClass (penOfFlesh , "Beast")) +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +SpawnHitTypeEffect (this , BHT_ACID , bSound , vHitNormal , crRay . cr_vHit , vHitDirection , vDistance ); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +else +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +SpawnHitTypeEffect (this , BHT_FLESH , bSound , vHitNormal , crRay . cr_vHit , vHitDirection , vDistance ); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +break ; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +break ; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(bTrail ) +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +SpawnTrail (); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} + +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CBullet::DestroyBullet(void) { +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +Destroy (); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} + +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CBullet::SpawnTrail(void) +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +{ +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +const FLOAT3D & v0 = GetPlacement () . pl_PositionVector ; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +const FLOAT3D & v1 = m_vHitPoint ; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT3D vD = v1 - v0 ; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT fD = vD . Length (); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(fD < 1.0f){ +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +return ; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT fLen = Min (20.0f , fD ); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT3D vPos ; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +if(fLen < fD ){ +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vPos = Lerp (v0 , v1 , FRnd () * (fD - fLen ) / fD ); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +}else { +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vPos = v0 ; +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +ESpawnEffect ese ; +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +UBYTE ubRndH = UBYTE (8 + FRnd () * 32); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +UBYTE ubRndS = UBYTE (8 + FRnd () * 32); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +UBYTE ubRndV = UBYTE (224 + FRnd () * 32); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +UBYTE ubRndA = UBYTE (32 + FRnd () * 128); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +ese . colMuliplier = HSVToColor (ubRndH , ubRndS , ubRndV ) | ubRndA ; +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +ese . betType = BET_BULLETTRAIL ; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +ese . vNormal = vD / fD ; +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +ese . vStretch = FLOAT3D (0.1f , fLen , 1.0f); +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +FLOAT3D vBulletIncommingDirection ; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +vBulletIncommingDirection = (m_vTarget - GetPlacement () . pl_PositionVector ) . Normalize (); +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +CPlacement3D plHit = CPlacement3D (vPos - vBulletIncommingDirection * 0.1f , GetPlacement () . pl_OrientationAngle ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +CEntityPointer penHit = CreateEntity (plHit , CLASS_BASIC_EFFECT ); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +penHit -> Initialize (ese ); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +} +BOOL CBullet:: +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CBullet_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EBulletInit, "CBullet::Main expects 'EBulletInit' as input!"); const EBulletInit &eInit = (const EBulletInit &)__eeInput; +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +ASSERT (eInit . penOwner != NULL ); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_penOwner = eInit . penOwner ; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_fDamage = eInit . fDamage ; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +InitAsVoid (); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +m_iBullet = 0; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +Return(STATE_CURRENT,EVoid()); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Bullet.es b/Sources/EntitiesMP/Bullet.es new file mode 100644 index 0000000..9dd2218 --- /dev/null +++ b/Sources/EntitiesMP/Bullet.es @@ -0,0 +1,321 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +502 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/BasicEffects"; +uses "Engine/Classes/MovableEntity"; + + +// input parameters for bullet +event EBulletInit { + CEntityPointer penOwner, // who launched it + FLOAT fDamage, // damage +}; + +%{ +void CBullet_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSTONE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSAND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINREDSAND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINWATER); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSTONENOSOUND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINSANDNOSOUND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINREDSANDNOSOUND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETSTAINWATERNOSOUND); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSPILL); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BULLETTRAIL); +} +%} + +class export CBullet : CEntity { +name "Bullet"; +thumbnail ""; +features "ImplementsOnPrecache"; + +properties: + 1 CEntityPointer m_penOwner, // entity which owns it + 2 FLOAT m_fDamage = 0.0f, // damage + 3 FLOAT3D m_vTarget = FLOAT3D(0,0,0), // bullet target point in space + 4 FLOAT3D m_vTargetCopy = FLOAT3D(0,0,0), // copy of bullet target point in space for jitter + 6 FLOAT3D m_vHitPoint = FLOAT3D(0,0,0), // hit point + 8 INDEX m_iBullet = 0, // bullet for lerped launch + 9 enum DamageType m_EdtDamage = DMT_BULLET, // damage type + 10 FLOAT m_fBulletSize = 0.0f, // bullet can have radius, for hitting models only + +components: + 1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl" + +functions: + +/************************************************************ + * BULLET LAUNCH * + ************************************************************/ + // set bullet damage + void SetDamage(FLOAT fDamage) { + m_fDamage = fDamage; + }; + + // calc jitter target + void CalcTarget(FLOAT fRange) { + // destination in bullet direction + AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, m_vTarget); + m_vTarget *= fRange; + m_vTarget += GetPlacement().pl_PositionVector; + m_vTargetCopy = m_vTarget; + }; + + void CalcTarget(CEntity *pen, FLOAT fRange) { + FLOAT3D vTarget; + + // target body + EntityInfo *peiTarget = (EntityInfo*) (pen->GetEntityInfo()); + GetEntityInfoPosition(pen, peiTarget->vTargetCenter, vTarget); + + // calculate + m_vTarget = (vTarget - GetPlacement().pl_PositionVector).Normalize(); + m_vTarget *= fRange; + m_vTarget += GetPlacement().pl_PositionVector; + m_vTargetCopy = m_vTarget; + }; + + // calc jitter target - !!! must call CalcTarget first !!! + void CalcJitterTarget(FLOAT fR) { + FLOAT3D vJitter; +/* My Sphere + FLOAT fXZ = FRnd()*360.0f; + FLOAT fXY = FRnd()*360.0f; + + // sphere + fR *= FRnd(); + vJitter(1) = CosFast(fXZ)*CosFast(fXY)*fR; + vJitter(2) = CosFast(fXZ)*SinFast(fXY)*fR; + vJitter(3) = SinFast(fXZ)*fR;*/ +// comp graphics algorithms sphere + FLOAT fZ = FRnd()*2.0f - 1.0f; + FLOAT fA = FRnd()*360.0f; + FLOAT fT = Sqrt(1-(fZ*fZ)); + vJitter(1) = fT * CosFast(fA); + vJitter(2) = fT * SinFast(fA); + vJitter(3) = fZ; + vJitter = vJitter*fR*FRnd(); + + // target + m_vTarget = m_vTargetCopy + vJitter; + }; + + // calc jitter target asymetric - !!! must call CalcTarget first !!! + void CalcJitterTargetFixed(FLOAT fX, FLOAT fY, FLOAT fJitter) { + FLOAT fRndX = FRnd()*2.0f - 1.0f; + FLOAT fRndY = FRnd()*2.0f - 1.0f; + FLOAT3D vX, vY; + const FLOATmatrix3D &m=GetRotationMatrix(); + vX(1) = m(1,1); vX(2) = m(2,1); vX(3) = m(3,1); + vY(1) = m(1,2); vY(2) = m(2,2); vY(3) = m(3,2); + // target + m_vTarget = m_vTargetCopy + (vX*(fX+fRndX*fJitter)) + (vY*(fY+fRndY*fJitter)); + }; + + // launch one bullet + void LaunchBullet(BOOL bSound, BOOL bTrail, BOOL bHitFX) + { + // cast a ray to find bullet target + CCastRay crRay( m_penOwner, GetPlacement().pl_PositionVector, m_vTarget); + crRay.cr_bHitPortals = TRUE; + crRay.cr_bHitTranslucentPortals = TRUE; + crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX; + crRay.cr_bPhysical = FALSE; + crRay.cr_fTestR = m_fBulletSize; + FLOAT3D vHitDirection; + AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, vHitDirection); + + INDEX ctCasts = 0; + while( ctCasts<10) + { + if(ctCasts == 0) + { + // perform first cast + GetWorld()->CastRay(crRay); + } + else + { + // next casts + GetWorld()->ContinueCast(crRay); + } + ctCasts++; + + // stop casting if nothing hit + if (crRay.cr_penHit==NULL) + { + break; + } + // apply damage + const FLOAT fDamageMul = GetSeriousDamageMultiplier(m_penOwner); + InflictDirectDamage(crRay.cr_penHit, m_penOwner, m_EdtDamage, m_fDamage*fDamageMul, + crRay.cr_vHit, vHitDirection); + + m_vHitPoint = crRay.cr_vHit; + + // if brush hitted + if (crRay.cr_penHit->GetRenderType()==RT_BRUSH && crRay.cr_pbpoBrushPolygon!=NULL) + { + CBrushPolygon *pbpo = crRay.cr_pbpoBrushPolygon; + FLOAT3D vHitNormal = FLOAT3D(pbpo->bpo_pbplPlane->bpl_plAbsolute); + // obtain surface type + INDEX iSurfaceType = pbpo->bpo_bppProperties.bpp_ubSurfaceType; + BulletHitType bhtType = BHT_BRUSH_STONE; + // get content type + INDEX iContent = pbpo->bpo_pbscSector->GetContentType(); + CContentType &ct = GetWorld()->wo_actContentTypes[iContent]; + + bhtType=(BulletHitType) GetBulletHitTypeForSurface(iSurfaceType); + // if this is under water polygon + if( ct.ct_ulFlags&CTF_BREATHABLE_GILLS) + { + // if we hit water surface + if( iSurfaceType==SURFACE_WATER) + { + vHitNormal = -vHitNormal; + + bhtType=BHT_BRUSH_WATER; + } + // if we hit stone under water + else + { + bhtType=BHT_BRUSH_UNDER_WATER; + } + } + // spawn hit effect + BOOL bPassable = pbpo->bpo_ulFlags & (BPOF_PASSABLE|BPOF_SHOOTTHRU); + if (!bPassable || iSurfaceType==SURFACE_WATER) { + SpawnHitTypeEffect(this, bhtType, bSound, vHitNormal, crRay.cr_vHit, vHitDirection, FLOAT3D(0.0f, 0.0f, 0.0f)); + } + if(!bPassable) { + break; + } + // if not brush + } else { + + // if flesh entity + if (crRay.cr_penHit->GetEntityInfo()!=NULL) { + if( ((EntityInfo*)crRay.cr_penHit->GetEntityInfo())->Eeibt == EIBT_FLESH) + { + CEntity *penOfFlesh = crRay.cr_penHit; + FLOAT3D vHitNormal = (GetPlacement().pl_PositionVector-m_vTarget).Normalize(); + FLOAT3D vOldHitPos = crRay.cr_vHit; + FLOAT3D vDistance; + + // look behind the entity (for back-stains) + GetWorld()->ContinueCast(crRay); + if( crRay.cr_penHit!=NULL && crRay.cr_pbpoBrushPolygon!=NULL && + crRay.cr_penHit->GetRenderType()==RT_BRUSH) + { + vDistance = crRay.cr_vHit-vOldHitPos; + vHitNormal = FLOAT3D(crRay.cr_pbpoBrushPolygon->bpo_pbplPlane->bpl_plAbsolute); + } + else + { + vDistance = FLOAT3D(0.0f, 0.0f, 0.0f); + vHitNormal = FLOAT3D(0,0,0); + } + + if(IsOfClass(penOfFlesh, "Gizmo") || + IsOfClass(penOfFlesh, "Beast")) + { + // spawn green blood hit spill effect + SpawnHitTypeEffect(this, BHT_ACID, bSound, vHitNormal, crRay.cr_vHit, vHitDirection, vDistance); + } + else + { + // spawn red blood hit spill effect + SpawnHitTypeEffect(this, BHT_FLESH, bSound, vHitNormal, crRay.cr_vHit, vHitDirection, vDistance); + } + break; + } + } + + // stop casting ray if not brush + break; + } + } + + if( bTrail) + { + SpawnTrail(); + } + }; + + // destroy yourself + void DestroyBullet(void) { + Destroy(); + }; + + + +/************************************************************ + * EFFECTS * + ************************************************************/ + // spawn trail of this bullet + void SpawnTrail(void) + { + // get bullet path positions + const FLOAT3D &v0 = GetPlacement().pl_PositionVector; + const FLOAT3D &v1 = m_vHitPoint; + // calculate distance + FLOAT3D vD = v1-v0; + FLOAT fD = vD.Length(); + // if too short + if (fD<1.0f) { + // no trail + return; + } + + // length must be such that it doesn't get out of path + FLOAT fLen = Min(20.0f, fD); + // position is random, but it must not make trail go out of path + FLOAT3D vPos; + if (fLenInitialize(ese); + } + +procedures: + + Main(EBulletInit eInit) + { + // remember the initial parameters + ASSERT(eInit.penOwner!=NULL); + m_penOwner = eInit.penOwner; + m_fDamage = eInit.fDamage; + + InitAsVoid(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // for lerped launch + m_iBullet = 0; + return; + }; +}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Bullet.h b/Sources/EntitiesMP/Bullet.h new file mode 100644 index 0000000..08a5c5d --- /dev/null +++ b/Sources/EntitiesMP/Bullet.h @@ -0,0 +1,59 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Bullet_INCLUDED +#define _EntitiesMP_Bullet_INCLUDED 1 +#include +#include +#define EVENTCODE_EBulletInit 0x01f60000 +class DECL_DLL EBulletInit : public CEntityEvent { +public: +EBulletInit(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOwner; +FLOAT fDamage; +}; +DECL_DLL inline void ClearToDefault(EBulletInit &e) { e = EBulletInit(); } ; +extern "C" DECL_DLL CDLLEntityClass CBullet_DLLClass; +class DECL_DLL CBullet : public CEntity { +public: + virtual void SetDefaultProperties(void); + CEntityPointer m_penOwner; + FLOAT m_fDamage; + FLOAT3D m_vTarget; + FLOAT3D m_vTargetCopy; + FLOAT3D m_vHitPoint; + INDEX m_iBullet; + enum DamageType m_EdtDamage; + FLOAT m_fBulletSize; + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void SetDamage(FLOAT fDamage); + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CalcTarget(FLOAT fRange); + +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CalcTarget(CEntity * pen,FLOAT fRange); + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CalcJitterTarget(FLOAT fR); + +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void CalcJitterTargetFixed(FLOAT fX,FLOAT fY,FLOAT fJitter); + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void LaunchBullet(BOOL bSound,BOOL bTrail,BOOL bHitFX); + +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void DestroyBullet(void); + +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +void SpawnTrail(void); +#define STATE_CBullet_Main 1 + BOOL +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Bullet_INCLUDED diff --git a/Sources/EntitiesMP/Bullet_tables.h b/Sources/EntitiesMP/Bullet_tables.h new file mode 100644 index 0000000..a030a0a --- /dev/null +++ b/Sources/EntitiesMP/Bullet_tables.h @@ -0,0 +1,41 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CBullet + +CEntityProperty CBullet_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001f6<<8)+1, offsetof(CBullet, m_penOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f6<<8)+2, offsetof(CBullet, m_fDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f6<<8)+3, offsetof(CBullet, m_vTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f6<<8)+4, offsetof(CBullet, m_vTargetCopy), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f6<<8)+6, offsetof(CBullet, m_vHitPoint), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000001f6<<8)+8, offsetof(CBullet, m_iBullet), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DamageType_enum, (0x000001f6<<8)+9, offsetof(CBullet, m_EdtDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f6<<8)+10, offsetof(CBullet, m_fBulletSize), "", 0, 0, 0), +}; +#define CBullet_propertiesct ARRAYCOUNT(CBullet_properties) + +CEntityComponent CBullet_components[] = { +#define CLASS_BASIC_EFFECT ((0x000001f6<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +}; +#define CBullet_componentsct ARRAYCOUNT(CBullet_components) + +CEventHandlerEntry CBullet_handlers[] = { + {1, -1, CEntity::pEventHandler(&CBullet:: +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Bullet.es" +Main),DEBUGSTRING("CBullet::Main")}, +}; +#define CBullet_handlersct ARRAYCOUNT(CBullet_handlers) + +CEntity *CBullet_New(void) { return new CBullet; }; +void CBullet_OnInitClass(void) {}; +void CBullet_OnEndClass(void) {}; +void CBullet_OnPrecache(CDLLEntityClass *pdec, INDEX iUser); +void CBullet_OnWorldEnd(CWorld *pwo) {}; +void CBullet_OnWorldInit(CWorld *pwo) {}; +void CBullet_OnWorldTick(CWorld *pwo) {}; +void CBullet_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CBullet, CEntity, "Bullet", "", 0x000001f6); +DECLARE_CTFILENAME(_fnmCBullet_tbn, ""); diff --git a/Sources/EntitiesMP/Camera.cpp b/Sources/EntitiesMP/Camera.cpp new file mode 100644 index 0000000..e546ed1 --- /dev/null +++ b/Sources/EntitiesMP/Camera.cpp @@ -0,0 +1,1031 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" + +#include "StdH.h" + +#include +#include +void CCamera::SetDefaultProperties(void) { + m_tmTime = 5.0f; + m_fFOV = 90.0f; + m_fLastFOV = 90.0f; + m_penTarget = NULL; + m_strName = "Camera"; + m_penOnBreak = NULL; + m_bWideScreen = TRUE ; + m_tmAtMarker = 0.0f; + m_tmDelta = 0.0f; + m_vPNp0 = FLOAT3D(0 , 0 , 0); + m_vPNp1 = FLOAT3D(0 , 0 , 0); + m_vTNp0 = FLOAT3D(0 , 0 , 0); + m_vTNp1 = FLOAT3D(0 , 0 , 0); + m_fFOVp0 = 0.0f; + m_fFOVp1 = 0.0f; + m_fTFOVp0 = 0.0f; + m_fTFOVp1 = 0.0f; + m_qPNp0 = FLOATquat3D(0 , 0 , 0 , 0); + m_qPNp1 = FLOATquat3D(0 , 0 , 0 , 0); + m_qANp0 = FLOATquat3D(0 , 0 , 0 , 0); + m_qANp1 = FLOATquat3D(0 , 0 , 0 , 0); + m_penLast = NULL; + m_penPlayer = NULL; + m_strDescription = ""; + m_bStopMoving = FALSE ; + m_colFade0 = 0; + m_colFade1 = 0; + m_bMoving = FALSE ; + m_penViewTarget0 = NULL; + m_penViewTarget1 = NULL; + m_vPosRatio0 = FLOAT3D(0 , 0 , 0); + m_vPosRatio1 = FLOAT3D(0 , 0 , 0); + m_fMyTimer = 0.0f; + m_fMyTimerLast = 0.0f; + m_bIgnoreTimeStretch = FALSE ; + m_bAutoRotation = FALSE ; + m_fStartHdg = 0.0f; + m_fRotateSpeed = 180.0f; + m_fRotateTime = 8.0f; + m_fRadX = 8.0f; + m_fHeight = 4.0f; + m_fRadZ = 8.0f; + m_penAutoCameraEndTarget = NULL; + m_eetAutoCameraEndEvent = EET_STOP ; + m_vRelTargetOffset = FLOAT3D(0 , 0 , 0); + CMovableModelEntity::SetDefaultProperties(); +} + +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void CCamera::RenderParticles(void) +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(Particle_GetViewer () == this ){ +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Particles_ViewerLocal (this ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +BOOL CCamera::MovesByTargetedRoute(CTString & strTargetProperty)const +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +strTargetProperty = "Target"; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} + +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +BOOL CCamera::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +fnmMarkerClass = CTFILENAME ("Classes\\CameraMarker.ecl"); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +strTargetProperty = "Target"; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE ; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} + +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +const CTString & CCamera::GetDescription(void)const +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_penTarget != NULL ){ +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , m_penTarget -> GetName ()); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +}else { +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return m_strDescription ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void CCamera::GetAutoRotatePlacement(FLOAT tmCurrent,FLOAT3D & vPos,FLOATmatrix3D & mRot, +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CPlacement3D & plNew,FLOAT3D vTarget)const +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fT = m_fStartHdg + m_fRotateSpeed * tmCurrent ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fX = m_fRadX * Sin (fT ); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fZ = m_fRadZ * Cos (fT ); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +vPos = FLOAT3D (fX , - m_fHeight , fZ ); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT3D vDir = vPos ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +vDir . Normalize (); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ANGLE3D ang ; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +DirectionVectorToAngles (vDir , ang ); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +plNew . pl_PositionVector = vTarget - vPos ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +plNew . pl_OrientationAngle = ang ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +MakeRotationMatrix (mRot , ang ); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CPlacement3D CCamera::GetLerpedPlacement(void)const +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fLerpFactor ; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(IsPredictor ()){ +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +fLerpFactor = _pTimer -> GetLerpFactor (); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +}else { +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +fLerpFactor = _pTimer -> GetLerpFactor2 (); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_bAutoRotation && m_bMoving ) +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fTime = Lerp (m_fMyTimerLast , m_fMyTimer , fLerpFactor ); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT3D vPos ; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATmatrix3D mRot ; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CPlacement3D plNew ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT3D vTarget = FLOAT3D (0 , 0 , 0); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_penTarget != NULL ) +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker * pcm = & (CCameraMarker &) * m_penTarget ; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(pcm -> m_penViewTarget != NULL ) +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +vTarget = pcm -> m_penViewTarget -> GetLerpedPlacement () . pl_PositionVector + m_vRelTargetOffset ; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +GetAutoRotatePlacement (fTime , vPos , mRot , plNew , vTarget ); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return plNew ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +else if(m_penViewTarget0 != NULL ) +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CPlacement3D plNew = LerpPlacementsPrecise (en_plLastPlacement , en_plPlacement , fLerpFactor ); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATmatrix3D mRot ; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CalcTargetedRotation (plNew . pl_PositionVector , m_penViewTarget0 , m_vPosRatio0 , mRot , TRUE ); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +DecomposeRotationMatrixNoSnap (plNew . pl_OrientationAngle , mRot ); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return plNew ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +else +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return LerpPlacementsPrecise (en_plLastPlacement , en_plPlacement , fLerpFactor ); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void CCamera::CalcTargetedRotation(const FLOAT3D & vMyPos,CEntity * penViewTarget, +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT3D vPosRatio,FLOATmatrix3D & mRotTarget,BOOL bLerping)const +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT3D vAbsPos ; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +penViewTarget -> GetEntityPointRatio (vPosRatio , vAbsPos , bLerping ); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT3D vDir ; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +vDir = vAbsPos - vMyPos ; +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +vDir . Normalize (); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ANGLE3D aDir ; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +DirectionVectorToAnglesNoSnap (vDir , aDir ); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +MakeRotationMatrixFast (mRotTarget , aDir ); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} + +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void CCamera::PreMoving() +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +en_plLastPlacement = en_plPlacement ; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void CCamera::DoMoving() +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(! m_bMoving ){ +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return ; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT tmCurrent ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(! m_bIgnoreTimeStretch ) +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +tmCurrent = _pTimer -> CurrentTick (); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +else +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_fMyTimerLast = m_fMyTimer ; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_fMyTimer += _pTimer -> TickQuantum / _pNetwork -> GetRealTimeFactor (); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +tmCurrent = m_fMyTimer ; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_bAutoRotation ) +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(tmCurrent > m_fRotateTime ) +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_bStopMoving = TRUE ; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return ; +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT3D vPos ; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATmatrix3D mRot ; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CPlacement3D plNew ; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT3D vTarget = FLOAT3D (0 , 0 , 0); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_penTarget != NULL ) +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker * pcm = & (CCameraMarker &) * m_penTarget ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(pcm -> m_penViewTarget != NULL ) +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +vTarget = pcm -> m_penViewTarget -> GetPlacement () . pl_PositionVector + m_vRelTargetOffset ; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +GetAutoRotatePlacement (tmCurrent , vPos , mRot , plNew , vTarget ); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +en_vNextPosition = vPos ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +en_mNextRotation = mRot ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CacheNearPolygons (); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SetPlacement_internal (plNew , mRot , TRUE ); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return ; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +BOOL bLerping = TRUE ; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(tmCurrent > (m_tmAtMarker + m_tmDelta - _pTimer -> TickQuantum * 3 / 2)) +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker * pcmNm1 = & (CCameraMarker &) * m_penLast ; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker * pcmNp0 = & (CCameraMarker &) * m_penTarget ; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker * pcmNp1 = & (CCameraMarker &) * pcmNp0 -> m_penTarget ; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker * pcmNp2 = & (CCameraMarker &) * pcmNp1 -> m_penTarget ; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FOREVER { +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(pcmNp0 -> m_penTrigger != NULL ){ +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SendToTarget (pcmNp0 -> m_penTrigger , EET_TRIGGER , m_penPlayer ); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(! pcmNp0 -> m_bSkipToNext ){ +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +break ; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +pcmNm1 = pcmNp0 ; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +pcmNp0 = pcmNp1 ; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +pcmNp1 = pcmNp2 ; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +pcmNp2 = (CCameraMarker *) & * pcmNp2 -> m_penTarget ; +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +bLerping = FALSE ; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penTarget = pcmNp1 ; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penLast = pcmNp0 ; +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker & cmNm1 = * pcmNm1 ; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker & cmNp0 = * pcmNp0 ; +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker & cmNp1 = * pcmNp1 ; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker & cmNp2 = * pcmNp2 ; +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +const FLOAT3D & vPNm1 = cmNm1 . GetPlacement () . pl_PositionVector ; +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +const FLOAT3D & vPNp0 = cmNp0 . GetPlacement () . pl_PositionVector ; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +const FLOAT3D & vPNp1 = cmNp1 . GetPlacement () . pl_PositionVector ; +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +const FLOAT3D & vPNp2 = cmNp2 . GetPlacement () . pl_PositionVector ; +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ANGLE3D aPNm1 = cmNm1 . GetPlacement () . pl_OrientationAngle ; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ANGLE3D aPNp0 = cmNp0 . GetPlacement () . pl_OrientationAngle ; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ANGLE3D aPNp1 = cmNp1 . GetPlacement () . pl_OrientationAngle ; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ANGLE3D aPNp2 = cmNp2 . GetPlacement () . pl_OrientationAngle ; +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fFOVm1 = cmNm1 . m_fFOV ; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fFOVp0 = cmNp0 . m_fFOV ; +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fFOVp1 = cmNp1 . m_fFOV ; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fFOVp2 = cmNp2 . m_fFOV ; +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_colFade0 = cmNp0 . m_colFade ; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_colFade1 = cmNp1 . m_colFade ; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penViewTarget0 = cmNp0 . m_penViewTarget ; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penViewTarget1 = cmNp1 . m_penViewTarget ; +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_vPosRatio0 = FLOAT3D (0 , 0 , 0); +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_vPosRatio1 = FLOAT3D (0 , 0 , 0); +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_penViewTarget0 != NULL ) +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_vPosRatio0 = cmNp0 . m_vPosRatio ; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_penViewTarget1 != NULL ) +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_vPosRatio1 = cmNp1 . m_vPosRatio ; +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATquat3D qPNm1 ;qPNm1 . FromEuler (aPNm1 ); +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATquat3D qPNp0 ;qPNp0 . FromEuler (aPNp0 ); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATquat3D qPNp1 ;qPNp1 . FromEuler (aPNp1 ); +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATquat3D qPNp2 ;qPNp2 . FromEuler (aPNp2 ); +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(qPNm1 % qPNp0 < 0){ +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +qPNp0 = - qPNp0 ; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(qPNp0 % qPNp1 < 0){ +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +qPNp1 = - qPNp1 ; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(qPNp1 % qPNp2 < 0){ +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +qPNp2 = - qPNp2 ; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_tmAtMarker = m_tmAtMarker + m_tmDelta ; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_tmDelta = cmNp0 . m_fDeltaTime ; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_vPNp0 = vPNp0 ; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_vPNp1 = vPNp1 ; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_fFOVp0 = fFOVp0 ; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_fFOVp1 = fFOVp1 ; +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_qPNp0 = qPNp0 ; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_qPNp1 = qPNp1 ; +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT tmDNm1 = cmNm1 . m_fDeltaTime ; +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT tmDNp0 = cmNp0 . m_fDeltaTime ; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT tmDNp1 = cmNp1 . m_fDeltaTime ; +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fD0 = 2 * tmDNp0 / (tmDNm1 + tmDNp0 ); +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fD1 = 2 * tmDNp0 / (tmDNp0 + tmDNp1 ); +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fBNp0 = cmNp0 . m_fBias ; +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fTNp0 = cmNp0 . m_fTension ; +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fCNp0 = cmNp0 . m_fContinuity ; +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fBNp1 = cmNp1 . m_fBias ; +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fTNp1 = cmNp1 . m_fTension ; +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fCNp1 = cmNp1 . m_fContinuity ; +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fF00 = (1 - fTNp0 ) * (1 - fCNp0 ) * (1 - fBNp0 ) / 2; +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fF01 = (1 - fTNp0 ) * (1 + fCNp0 ) * (1 + fBNp0 ) / 2; +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fF10 = (1 - fTNp1 ) * (1 + fCNp1 ) * (1 - fBNp1 ) / 2; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fF11 = (1 - fTNp1 ) * (1 - fCNp1 ) * (1 + fBNp1 ) / 2; +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_vTNp0 = ((vPNp1 - vPNp0 ) * fF00 + (vPNp0 - vPNm1 ) * fF01 ) * fD0 ; +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_vTNp1 = ((vPNp2 - vPNp1 ) * fF10 + (vPNp1 - vPNp0 ) * fF11 ) * fD1 ; +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_fTFOVp0 = ((fFOVp1 - fFOVp0 ) * fF00 + (fFOVp0 - fFOVm1 ) * fF01 ) * fD0 ; +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_fTFOVp1 = ((fFOVp2 - fFOVp1 ) * fF10 + (fFOVp1 - fFOVp0 ) * fF11 ) * fD1 ; +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATquat3D qTNp0 , qTNp1 ; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +qTNp0 = (Log (qPNp0 . Inv () * qPNp1 ) * fF00 + Log (qPNm1 . Inv () * qPNp0 ) * fF01 ) * fD0 ; +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +qTNp1 = (Log (qPNp1 . Inv () * qPNp2 ) * fF10 + Log (qPNp0 . Inv () * qPNp1 ) * fF11 ) * fD1 ; +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_qANp0 = qPNp0 * Exp ((qTNp0 - Log (qPNp0 . Inv () * qPNp1 )) / 2); +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_qANp1 = qPNp1 * Exp ((Log (qPNp0 . Inv () * qPNp1 ) - qTNp1 ) / 2); +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(cmNp0 . m_bStopMoving ){ +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_bStopMoving = TRUE ; +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fT = (tmCurrent - m_tmAtMarker ) / m_tmDelta ; +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fH0 = 2 * fT * fT * fT - 3 * fT * fT + 1; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fH1 = - 2 * fT * fT * fT + 3 * fT * fT ; +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fH2 = fT * fT * fT - 2 * fT * fT + fT ; +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fH3 = fT * fT * fT - fT * fT ; +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT3D vPos = m_vPNp0 * fH0 + m_vPNp1 * fH1 + m_vTNp0 * fH2 + m_vTNp1 * fH3 ; +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fFOV = m_fFOVp0 * fH0 + m_fFOVp1 * fH1 + m_fTFOVp0 * fH2 + m_fTFOVp1 * fH3 ; +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATquat3D qRot = Squad (fT , m_qPNp0 , m_qPNp1 , m_qANp0 , m_qANp1 ); +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATmatrix3D mRot ; +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +qRot . ToMatrix (mRot ); +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATmatrix3D mRotTarget0 = mRot ; +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATmatrix3D mRotTarget1 = mRot ; +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +BOOL bDoTargeting = FALSE ; +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_penViewTarget0 != NULL ){ +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CalcTargetedRotation (vPos , m_penViewTarget0 , m_vPosRatio0 , mRotTarget0 , FALSE ); +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +bDoTargeting = TRUE ; +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_penViewTarget1 != NULL ){ +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CalcTargetedRotation (vPos , m_penViewTarget1 , m_vPosRatio1 , mRotTarget1 , FALSE ); +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +bDoTargeting = TRUE ; +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(bDoTargeting ){ +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATquat3D qRot0 ;qRot0 . FromMatrix (mRotTarget0 ); +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATquat3D qRot1 ;qRot1 . FromMatrix (mRotTarget1 ); +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOATquat3D qRot = Slerp (Clamp (fT , 0.0f , 1.0f) , qRot0 , qRot1 ); +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +qRot . ToMatrix (mRot ); +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +en_vNextPosition = vPos ; +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +en_mNextRotation = mRot ; +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CacheNearPolygons (); +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CPlacement3D plNew ; +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +plNew . pl_PositionVector = vPos ; +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +DecomposeRotationMatrixNoSnap (plNew . pl_OrientationAngle , mRot ); +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SetPlacement_internal (plNew , mRot , TRUE ); +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(! bLerping ){ +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +en_plLastPlacement = en_plPlacement ; +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_fLastFOV = m_fFOV ; +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_fFOV = fFOV ; +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} + +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void CCamera::PostMoving() +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(! m_bMoving ){ +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return ; +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_bStopMoving ){ +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_bMoving = FALSE ; +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +en_ulFlags |= ENF_INRENDERING ; +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SendEvent (EStop ()); +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +BOOL CCamera:: +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayStaticCamera(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCamera_PlayStaticCamera + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCamera::PlayStaticCamera expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_bMoving = FALSE ; +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ECameraStart eStart ; +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +eStart . penCamera = this ; +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penPlayer -> SendEvent (eStart ); +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SetTimerAfter(m_tmTime ); +Jump(STATE_CURRENT, 0x00dc0001, FALSE, EBegin());return TRUE;}BOOL CCamera::H0x00dc0001_PlayStaticCamera_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00dc0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCamera::H0x00dc0002_PlayStaticCamera_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc0002 +; +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ECameraStop eStop ; +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +eStop . penCamera = this ; +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penPlayer -> SendEvent (eStop ); +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Return(STATE_CURRENT,EVoid()); +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCamera:: +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayAutoRotatingCamera(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCamera_PlayAutoRotatingCamera + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCamera::PlayAutoRotatingCamera expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +AddToMovers (); +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_bMoving = TRUE ; +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ECameraStart eStart ; +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +eStart . penCamera = this ; +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penPlayer -> SendEvent (eStart ); +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00dc0004, FALSE, EBegin());return TRUE;}BOOL CCamera::H0x00dc0004_PlayAutoRotatingCamera_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc0004 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ECameraStop eStop ; +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +eStop . penCamera = this ; +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penPlayer -> SendEvent (eStop ); +#line 491 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_penAutoCameraEndTarget != NULL ) +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SendToTarget (m_penAutoCameraEndTarget , m_eetAutoCameraEndEvent , m_penPlayer ); +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Return(STATE_CURRENT,EVoid()); +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +}ASSERT(FALSE);break;default:{ +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +}ASSERT(FALSE);break; +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +}return TRUE;}BOOL CCamera::H0x00dc0005_PlayAutoRotatingCamera_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc0005 + +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Return(STATE_CURRENT,EVoid()); +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCamera:: +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayMovingCamera(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCamera_PlayMovingCamera + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCamera::PlayMovingCamera expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ECameraStart eStart ; +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +eStart . penCamera = this ; +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penPlayer -> SendEvent (eStart ); +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +INDEX ctMarkers = 1; +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +INDEX ctNonSkipped = 0; +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker * pcm0 = (CCameraMarker *) & * m_penTarget ; +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker * pcm = (CCameraMarker *) & * pcm0 -> m_penTarget ; +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +while(pcm != NULL && pcm -> m_penTarget != pcm0 ) +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +pcm = (CCameraMarker *) & * pcm -> m_penTarget ; +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(pcm == NULL ){ +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +WarningMessage ("Movable camera - broken link!"); +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Return(STATE_CURRENT,EVoid()); +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(! pcm -> m_bSkipToNext ){ +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ctNonSkipped ++; +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ctMarkers ++; +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(ctMarkers > 500){ +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +WarningMessage ("Movable camera - invalid marker loop!"); +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Return(STATE_CURRENT,EVoid()); +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(ctMarkers < 2){ +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +WarningMessage ("Movable camera requires at least 2 markers in order to work!"); +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Return(STATE_CURRENT,EVoid()); +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(ctNonSkipped < 1){ +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +WarningMessage ("Movable camera requires at least 1 non-skipped marker!"); +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Return(STATE_CURRENT,EVoid()); +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT tmCurrent ; +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(! m_bIgnoreTimeStretch ) +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +tmCurrent = _pTimer -> CurrentTick (); +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +else +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +tmCurrent = m_fMyTimer ; +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_tmAtMarker = tmCurrent ; +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_tmDelta = 0.0f; +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_bStopMoving = FALSE ; +#line 559 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penLast = pcm ; +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ASSERT (pcm -> m_penTarget == m_penTarget ); +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +pcm = (CCameraMarker *) & * m_penTarget ; +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_colFade0 = m_colFade1 = pcm -> m_colFade ; +#line 565 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +AddToMovers (); +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_bMoving = TRUE ; +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00dc0007, FALSE, EBegin());return TRUE;}BOOL CCamera::H0x00dc0007_PlayMovingCamera_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc0007 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +ECameraStop eStop ; +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +eStop . penCamera = this ; +#line 573 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penPlayer -> SendEvent (eStop ); +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Return(STATE_CURRENT,EVoid()); +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +}ASSERT(FALSE);break;default:{ +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +}ASSERT(FALSE);break; +#line 579 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +}return TRUE;}BOOL CCamera::H0x00dc0008_PlayMovingCamera_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc0008 + +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Return(STATE_CURRENT,EVoid()); +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCamera:: +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayCamera(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCamera_PlayCamera + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCamera::PlayCamera expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 590 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker & cm = (CCameraMarker &) * m_penTarget ; +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_bAutoRotation ) +#line 593 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Jump(STATE_CURRENT, STATE_CCamera_PlayAutoRotatingCamera, TRUE, EVoid());return TRUE; +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +else if(& cm != NULL ) +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Jump(STATE_CURRENT, STATE_CCamera_PlayMovingCamera, TRUE, EVoid());return TRUE; +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +else +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Jump(STATE_CURRENT, STATE_CCamera_PlayStaticCamera, TRUE, EVoid());return TRUE; +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} ASSERT(FALSE); return TRUE;};BOOL CCamera:: +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCamera_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCamera::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +InitAsEditorModel (); +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SetPhysicsFlags (EPF_MOVABLE ); +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SetCollisionFlags (ECF_CAMERA ); +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT fSize = 5.0f; +#line 618 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +GetModelObject () -> mo_Stretch = FLOAT3D (fSize , fSize , fSize ); +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SetModel (MODEL_CAMERA ); +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SetModelMainTexture (TEXTURE_CAMERA ); +#line 621 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_fLastFOV = m_fFOV ; +#line 623 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_penTarget != NULL && ! IsOfClass (m_penTarget , "Camera Marker")){ +#line 624 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +WarningMessage ("Entity '%s' is not of Camera Marker class!" , m_penTarget ); +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penTarget = NULL ; +#line 626 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 628 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(!(m_bAutoRotation || m_penTarget != NULL )){ Jump(STATE_CURRENT,0x00dc000c, FALSE, EInternal());return TRUE;} +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00dc000a, FALSE, EBegin());return TRUE;}BOOL CCamera::H0x00dc000a_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00dc000b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCamera::H0x00dc000b_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc000b +;Jump(STATE_CURRENT,0x00dc000c, FALSE, EInternal());return TRUE;}BOOL CCamera::H0x00dc000c_Main_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc000c + +#line 633 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_vRelTargetOffset = FLOAT3D (0 , 0 , 0); +#line 634 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(m_penTarget != NULL ) +#line 635 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CCameraMarker * pcm = & (CCameraMarker &) * m_penTarget ; +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(pcm -> m_penViewTarget != NULL ) +#line 638 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +#line 639 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT3D vAbsTarget = FLOAT3D (0 , 0 , 0); +#line 640 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +pcm -> m_penViewTarget -> GetEntityPointRatio (pcm -> m_vPosRatio , vAbsTarget , FALSE ); +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_vRelTargetOffset = vAbsTarget - pcm -> m_penViewTarget -> GetPlacement () . pl_PositionVector ; +#line 642 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 643 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 645 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Jump(STATE_CURRENT,0x00dc000f, FALSE, EInternal());return TRUE;}BOOL CCamera::H0x00dc000f_Main_06(const CEntityEvent &__eeInput) +#line 646 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc000f +if(!(TRUE )){ Jump(STATE_CURRENT,0x00dc0010, FALSE, EInternal());return TRUE;} +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00dc000d, FALSE, EBegin());return TRUE;}BOOL CCamera::H0x00dc000d_Main_04(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc000d +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CEntity * penCaused ; +#line 650 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +penCaused = FixupCausedToPlayer (this , eTrigger . penCaused , FALSE ); +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +if(IsDerivedFromClass (penCaused , "Player")){ +#line 652 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +m_penPlayer = penCaused ; +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Call(STATE_CURRENT, STATE_CCamera_PlayCamera, TRUE, EVoid());return TRUE; +#line 654 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +} +#line 655 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; +#line 656 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 657 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +}return TRUE;}BOOL CCamera::H0x00dc000e_Main_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc000e +Jump(STATE_CURRENT,0x00dc000f, FALSE, EInternal());return TRUE; +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +}BOOL CCamera::H0x00dc0010_Main_07(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dc0010 +; +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Destroy (); +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Return(STATE_CURRENT,EVoid()); +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Camera.es b/Sources/EntitiesMP/Camera.es new file mode 100644 index 0000000..bf61ea2 --- /dev/null +++ b/Sources/EntitiesMP/Camera.es @@ -0,0 +1,665 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +220 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Player"; +uses "EntitiesMP/CameraMarker"; + +class CCamera : CMovableModelEntity +{ +name "Camera"; +thumbnail "Thumbnails\\Camera.tbn"; +features "HasName", "IsTargetable", "IsImportant"; + +properties: + + 1 FLOAT m_tmTime "Time" 'E' = 5.0f, // how long to show the scene + 2 FLOAT m_fFOV "FOV" 'F' = 90.0f, // camera fov + 5 FLOAT m_fLastFOV = 90.0f, + 3 CEntityPointer m_penTarget "Target" 'T' COLOR(C_lBLUE|0xFF), + 4 CTString m_strName "Name" 'N' = "Camera", + 6 CEntityPointer m_penOnBreak "OnBreak" 'B' COLOR(C_lRED|0xFF), + 7 BOOL m_bWideScreen "WideScreen" 'W' = TRUE, + + 10 FLOAT m_tmAtMarker = 0.0f, // time when current marker was reached + 11 FLOAT m_tmDelta = 0.0f, // time to reach next marker + 13 FLOAT3D m_vPNp0 = FLOAT3D(0,0,0), + 14 FLOAT3D m_vPNp1 = FLOAT3D(0,0,0), + 15 FLOAT3D m_vTNp0 = FLOAT3D(0,0,0), + 16 FLOAT3D m_vTNp1 = FLOAT3D(0,0,0), + 17 FLOAT m_fFOVp0 = 0.0f, + 18 FLOAT m_fFOVp1 = 0.0f, + 19 FLOAT m_fTFOVp0 = 0.0f, + 20 FLOAT m_fTFOVp1 = 0.0f, + 31 FLOATquat3D m_qPNp0 = FLOATquat3D(0,0,0,0), + 32 FLOATquat3D m_qPNp1 = FLOATquat3D(0,0,0,0), + 33 FLOATquat3D m_qANp0 = FLOATquat3D(0,0,0,0), + 34 FLOATquat3D m_qANp1 = FLOATquat3D(0,0,0,0), + + 40 CEntityPointer m_penLast, // previous marker + 41 CEntityPointer m_penPlayer, // player viewing this camera + 42 CTString m_strDescription = "", + 43 BOOL m_bStopMoving = FALSE, // stop moving camera on next target + + 50 COLOR m_colFade0 = 0, // camera fading color + 51 COLOR m_colFade1 = 0, + 52 BOOL m_bMoving = FALSE, // set while moving + 53 CEntityPointer m_penViewTarget0, + 54 CEntityPointer m_penViewTarget1, + + 55 FLOAT3D m_vPosRatio0 = FLOAT3D(0,0,0), + 56 FLOAT3D m_vPosRatio1 = FLOAT3D(0,0,0), + + 60 FLOAT m_fMyTimer = 0.0f, + 61 FLOAT m_fMyTimerLast = 0.0f, + 62 BOOL m_bIgnoreTimeStretch "Ignore time stretch" = FALSE, + 63 BOOL m_bAutoRotation "Auto rotate (AR)" 'A' = FALSE, + 64 FLOAT m_fStartHdg "AR start heading" 'D' = 0.0f, + 65 FLOAT m_fRotateSpeed "AR Rotate speed" 'S' = 180.0f, + 66 FLOAT m_fRotateTime "AR Rotate time" 'I' = 8.0f, + 67 FLOAT m_fRadX "AR Radius X" 'X' = 8.0f, + 68 FLOAT m_fHeight "AR Height (controlls pitch)" 'H' = 4.0f, + 69 FLOAT m_fRadZ "AR Radius Z" 'Z' = 8.0f, + + 70 CEntityPointer m_penAutoCameraEndTarget "Auto camera end target", + 71 enum EventEType m_eetAutoCameraEndEvent "Auto camera end event" = EET_STOP, + 72 FLOAT3D m_vRelTargetOffset = FLOAT3D(0,0,0), + +components: + + 1 model MODEL_CAMERA "Models\\Editor\\Camera.mdl", + 2 texture TEXTURE_CAMERA "Models\\Editor\\Camera.tex" + + +functions: + + // render particles + void RenderParticles(void) + { + if (Particle_GetViewer()==this) { + Particles_ViewerLocal(this); + } + } + + // Check if entity is moved on a route set up by its targets + BOOL MovesByTargetedRoute( CTString &strTargetProperty) const + { + strTargetProperty = "Target"; + return TRUE; + } + + // Check if entity can drop marker for making linked route + BOOL DropsMarker( CTFileName &fnmMarkerClass, CTString &strTargetProperty) const + { + fnmMarkerClass = CTFILENAME( "Classes\\CameraMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + + // returns camera description + const CTString &GetDescription(void) const + { + if (m_penTarget!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", m_penTarget->GetName()); + } else { + ((CTString&)m_strDescription).PrintF("->"); + } + return m_strDescription; + } + + void GetAutoRotatePlacement( FLOAT tmCurrent, FLOAT3D &vPos, FLOATmatrix3D &mRot, + CPlacement3D &plNew, FLOAT3D vTarget) const + { + // create new pos and angle + FLOAT fT=m_fStartHdg+m_fRotateSpeed*tmCurrent; + FLOAT fX=m_fRadX*Sin(fT); + FLOAT fZ=m_fRadZ*Cos(fT); + vPos = FLOAT3D(fX, -m_fHeight, fZ); + FLOAT3D vDir=vPos; + vDir.Normalize(); + ANGLE3D ang; + DirectionVectorToAngles(vDir, ang); + plNew.pl_PositionVector = vTarget-vPos; + plNew.pl_OrientationAngle = ang; + + MakeRotationMatrix( mRot, ang); + return; + } + + CPlacement3D GetLerpedPlacement(void) const + { + FLOAT fLerpFactor; + if (IsPredictor()) { + fLerpFactor = _pTimer->GetLerpFactor(); + } else { + fLerpFactor = _pTimer->GetLerpFactor2(); + } + + if( m_bAutoRotation && m_bMoving) + { + FLOAT fTime=Lerp(m_fMyTimerLast, m_fMyTimer, fLerpFactor); + + FLOAT3D vPos; + FLOATmatrix3D mRot; + CPlacement3D plNew; + // get target placement + FLOAT3D vTarget=FLOAT3D(0,0,0); + if( m_penTarget!=NULL) + { + CCameraMarker *pcm = &(CCameraMarker&)*m_penTarget; + if( pcm->m_penViewTarget!=NULL) + { + vTarget=pcm->m_penViewTarget->GetLerpedPlacement().pl_PositionVector+m_vRelTargetOffset; + } + } + + GetAutoRotatePlacement( fTime, vPos, mRot, plNew, vTarget); + return plNew; + } + else if(m_penViewTarget0!=NULL) + { + CPlacement3D plNew=LerpPlacementsPrecise(en_plLastPlacement, en_plPlacement, fLerpFactor); + FLOATmatrix3D mRot; + CalcTargetedRotation(plNew.pl_PositionVector, m_penViewTarget0, m_vPosRatio0, mRot, TRUE); + DecomposeRotationMatrixNoSnap(plNew.pl_OrientationAngle, mRot); + return plNew; + } + else + { + return LerpPlacementsPrecise(en_plLastPlacement, en_plPlacement, fLerpFactor); + } + //return CMovableEntity::GetLerpedPlacement(); + } + + // calculate rotation matrix that points in direction of a target entity + void CalcTargetedRotation(const FLOAT3D &vMyPos, CEntity *penViewTarget, + FLOAT3D vPosRatio, FLOATmatrix3D &mRotTarget, BOOL bLerping) const + { + FLOAT3D vAbsPos; + penViewTarget->GetEntityPointRatio(vPosRatio, vAbsPos, bLerping); + FLOAT3D vDir; + vDir=vAbsPos-vMyPos; + vDir.Normalize(); + ANGLE3D aDir; + DirectionVectorToAnglesNoSnap(vDir, aDir); + MakeRotationMatrixFast(mRotTarget, aDir); + } + + void PreMoving() + { + // remember old placement for lerping + en_plLastPlacement = en_plPlacement; + } + + + void DoMoving() + { + if (!m_bMoving) { + return; + } + FLOAT tmCurrent; + if( !m_bIgnoreTimeStretch) + { + tmCurrent= _pTimer->CurrentTick(); + } + else + { + m_fMyTimerLast = m_fMyTimer; + m_fMyTimer+=_pTimer->TickQuantum/_pNetwork->GetRealTimeFactor(); + tmCurrent = m_fMyTimer; + } + + if( m_bAutoRotation) + { + // if we're finished with auto rotating camera + if( tmCurrent>m_fRotateTime) + { + m_bStopMoving=TRUE; + return; + } + FLOAT3D vPos; + FLOATmatrix3D mRot; + CPlacement3D plNew; + // get target placement + FLOAT3D vTarget=FLOAT3D(0,0,0); + if( m_penTarget!=NULL) + { + CCameraMarker *pcm = &(CCameraMarker&)*m_penTarget; + if( pcm->m_penViewTarget!=NULL) + { + vTarget=pcm->m_penViewTarget->GetPlacement().pl_PositionVector+m_vRelTargetOffset; + } + } + GetAutoRotatePlacement( tmCurrent, vPos, mRot, plNew, vTarget); + en_vNextPosition = vPos; + en_mNextRotation = mRot; + CacheNearPolygons(); + SetPlacement_internal(plNew, mRot, TRUE); + return; + } + + // lerping is initially enabled + BOOL bLerping = TRUE; + + // if we hit a marker + if( tmCurrent > (m_tmAtMarker+m_tmDelta - _pTimer->TickQuantum*3/2)) + { + // get markers + CCameraMarker *pcmNm1 = &(CCameraMarker&)*m_penLast; + CCameraMarker *pcmNp0 = &(CCameraMarker&)*m_penTarget; + CCameraMarker *pcmNp1 = &(CCameraMarker&)*pcmNp0->m_penTarget; + CCameraMarker *pcmNp2 = &(CCameraMarker&)*pcmNp1->m_penTarget; + + // repeat + FOREVER { + // if there is a trigger at the hit marker + if (pcmNp0->m_penTrigger!=NULL) { + // trigger it + SendToTarget(pcmNp0->m_penTrigger, EET_TRIGGER, m_penPlayer); + } + + // if the marker should not be skipped + if (!pcmNp0->m_bSkipToNext) { + // stop skipping + break; + } + + // go to next marker immediately + pcmNm1 = pcmNp0; + pcmNp0 = pcmNp1; + pcmNp1 = pcmNp2; + pcmNp2 = (CCameraMarker*)&*pcmNp2->m_penTarget; + + // disable lerping + bLerping = FALSE; + } + + // update markers for next interval + m_penTarget = pcmNp1; + m_penLast = pcmNp0; + + // get markers + CCameraMarker &cmNm1 = *pcmNm1; + CCameraMarker &cmNp0 = *pcmNp0; + CCameraMarker &cmNp1 = *pcmNp1; + CCameraMarker &cmNp2 = *pcmNp2; + + // get positions from four markers + const FLOAT3D &vPNm1 = cmNm1.GetPlacement().pl_PositionVector; + const FLOAT3D &vPNp0 = cmNp0.GetPlacement().pl_PositionVector; + const FLOAT3D &vPNp1 = cmNp1.GetPlacement().pl_PositionVector; + const FLOAT3D &vPNp2 = cmNp2.GetPlacement().pl_PositionVector; + ANGLE3D aPNm1 = cmNm1.GetPlacement().pl_OrientationAngle; + ANGLE3D aPNp0 = cmNp0.GetPlacement().pl_OrientationAngle; + ANGLE3D aPNp1 = cmNp1.GetPlacement().pl_OrientationAngle; + ANGLE3D aPNp2 = cmNp2.GetPlacement().pl_OrientationAngle; + FLOAT fFOVm1 = cmNm1.m_fFOV; + FLOAT fFOVp0 = cmNp0.m_fFOV; + FLOAT fFOVp1 = cmNp1.m_fFOV; + FLOAT fFOVp2 = cmNp2.m_fFOV; + m_colFade0 = cmNp0.m_colFade; + m_colFade1 = cmNp1.m_colFade; + m_penViewTarget0 = cmNp0.m_penViewTarget; + m_penViewTarget1 = cmNp1.m_penViewTarget; + m_vPosRatio0=FLOAT3D(0,0,0); + m_vPosRatio1=FLOAT3D(0,0,0); + if( m_penViewTarget0!=NULL) + { + m_vPosRatio0=cmNp0.m_vPosRatio; + } + if( m_penViewTarget1!=NULL) + { + m_vPosRatio1=cmNp1.m_vPosRatio; + } + + // find quaternions for rotations + FLOATquat3D qPNm1; qPNm1.FromEuler(aPNm1); + FLOATquat3D qPNp0; qPNp0.FromEuler(aPNp0); + FLOATquat3D qPNp1; qPNp1.FromEuler(aPNp1); + FLOATquat3D qPNp2; qPNp2.FromEuler(aPNp2); + + // make all angles between quaternion pairs acute + if( qPNm1%qPNp0<0 ) { + qPNp0 = -qPNp0; + } + if( qPNp0%qPNp1<0 ) { + qPNp1 = -qPNp1; + } + if( qPNp1%qPNp2<0 ) { + qPNp2 = -qPNp2; + } + + // update time and position + m_tmAtMarker = m_tmAtMarker+m_tmDelta; + m_tmDelta = cmNp0.m_fDeltaTime; + m_vPNp0 = vPNp0; + m_vPNp1 = vPNp1; + m_fFOVp0 = fFOVp0; + m_fFOVp1 = fFOVp1; + m_qPNp0 = qPNp0; + m_qPNp1 = qPNp1; + + // determine delta time multipliers + FLOAT tmDNm1 = cmNm1.m_fDeltaTime; + FLOAT tmDNp0 = cmNp0.m_fDeltaTime; + FLOAT tmDNp1 = cmNp1.m_fDeltaTime; + FLOAT fD0 = 2*tmDNp0 / (tmDNm1+tmDNp0); + FLOAT fD1 = 2*tmDNp0 / (tmDNp0+tmDNp1); + + // determine biases, tensions and continuities + FLOAT fBNp0 = cmNp0.m_fBias; + FLOAT fTNp0 = cmNp0.m_fTension; + FLOAT fCNp0 = cmNp0.m_fContinuity; + FLOAT fBNp1 = cmNp1.m_fBias; + FLOAT fTNp1 = cmNp1.m_fTension; + FLOAT fCNp1 = cmNp1.m_fContinuity; + + FLOAT fF00 = (1-fTNp0)*(1-fCNp0)*(1-fBNp0) / 2; + FLOAT fF01 = (1-fTNp0)*(1+fCNp0)*(1+fBNp0) / 2; + FLOAT fF10 = (1-fTNp1)*(1+fCNp1)*(1-fBNp1) / 2; + FLOAT fF11 = (1-fTNp1)*(1-fCNp1)*(1+fBNp1) / 2; + + // find tangents for translation + m_vTNp0 = ( (vPNp1-vPNp0) * fF00 + (vPNp0-vPNm1) * fF01) * fD0; + m_vTNp1 = ( (vPNp2-vPNp1) * fF10 + (vPNp1-vPNp0) * fF11) * fD1; + + // find tangents for FOV + m_fTFOVp0 = ( (fFOVp1-fFOVp0) * fF00 + (fFOVp0-fFOVm1) * fF01) * fD0; + m_fTFOVp1 = ( (fFOVp2-fFOVp1) * fF10 + (fFOVp1-fFOVp0) * fF11) * fD1; + + // find tangents for rotation + FLOATquat3D qTNp0, qTNp1; + qTNp0 = ( Log(qPNp0.Inv()*qPNp1) * fF00 + Log(qPNm1.Inv()*qPNp0) * fF01) * fD0; + qTNp1 = ( Log(qPNp1.Inv()*qPNp2) * fF10 + Log(qPNp0.Inv()*qPNp1) * fF11) * fD1; + + // find squad parameters + m_qANp0 = qPNp0*Exp( (qTNp0 - Log(qPNp0.Inv()*qPNp1))/2 ); + m_qANp1 = qPNp1*Exp( (Log(qPNp0.Inv()*qPNp1) - qTNp1)/2 ); + + // check for stop moving + if( cmNp0.m_bStopMoving) { + m_bStopMoving = TRUE; + } + } + + // calculate the parameter value and hermit basis + FLOAT fT = (tmCurrent - m_tmAtMarker) / m_tmDelta; + FLOAT fH0 = 2*fT*fT*fT - 3*fT*fT + 1; + FLOAT fH1 = -2*fT*fT*fT + 3*fT*fT; + FLOAT fH2 = fT*fT*fT - 2*fT*fT + fT; + FLOAT fH3 = fT*fT*fT - fT*fT; + + // interpolate position, rotation and fov + FLOAT3D vPos = m_vPNp0*fH0 + m_vPNp1*fH1 + m_vTNp0*fH2 + m_vTNp1*fH3; + FLOAT fFOV = m_fFOVp0*fH0 + m_fFOVp1*fH1 + m_fTFOVp0*fH2 + m_fTFOVp1*fH3; + FLOATquat3D qRot = Squad(fT, m_qPNp0, m_qPNp1, m_qANp0, m_qANp1); + FLOATmatrix3D mRot; + qRot.ToMatrix(mRot); + + // calculate targeted matrices + FLOATmatrix3D mRotTarget0 = mRot; + FLOATmatrix3D mRotTarget1 = mRot; + BOOL bDoTargeting = FALSE; + if (m_penViewTarget0!=NULL) { + CalcTargetedRotation(vPos, m_penViewTarget0, m_vPosRatio0, mRotTarget0, FALSE); + bDoTargeting = TRUE; + } + if (m_penViewTarget1!=NULL) { + CalcTargetedRotation(vPos, m_penViewTarget1, m_vPosRatio1, mRotTarget1, FALSE); + bDoTargeting = TRUE; + } + + // if any targeting involved + if (bDoTargeting) { + // lerp between two matrices + FLOATquat3D qRot0; qRot0.FromMatrix(mRotTarget0); + FLOATquat3D qRot1; qRot1.FromMatrix(mRotTarget1); + FLOATquat3D qRot = Slerp(Clamp(fT, 0.0f, 1.0f), qRot0, qRot1); + qRot.ToMatrix(mRot); + } + + // just cache near polygons for various engine needs + en_vNextPosition = vPos; + en_mNextRotation = mRot; + CacheNearPolygons(); + + // set new placement + CPlacement3D plNew; + plNew.pl_PositionVector = vPos; + DecomposeRotationMatrixNoSnap(plNew.pl_OrientationAngle, mRot); + SetPlacement_internal(plNew, mRot, TRUE); + // if lerping is disabled + if (!bLerping) { + // make last placement same as this one + en_plLastPlacement = en_plPlacement; + } + // set new fov + m_fLastFOV = m_fFOV; + m_fFOV = fFOV; + } + + + void PostMoving() + { + if (!m_bMoving) { + return; + } + // + if( m_bStopMoving) { + m_bMoving = FALSE; + // mark for removing from list of movers + en_ulFlags |= ENF_INRENDERING; + SendEvent( EStop()); + } + } + + +procedures: + + // routine for playing static camera + PlayStaticCamera() + { + m_bMoving = FALSE; + ECameraStart eStart; + eStart.penCamera = this; + m_penPlayer->SendEvent(eStart); + autowait(m_tmTime); + ECameraStop eStop; + eStop.penCamera=this; + m_penPlayer->SendEvent(eStop); + return; + } + + // routine for playing autorotating camera + PlayAutoRotatingCamera() + { + // register camera as movable entity + AddToMovers(); + m_bMoving = TRUE; + ECameraStart eStart; + eStart.penCamera = this; + m_penPlayer->SendEvent(eStart); + // roll, baby, roll ... + wait() { + on( EStop) : { + ECameraStop eStop; + eStop.penCamera=this; + m_penPlayer->SendEvent(eStop); + if( m_penAutoCameraEndTarget!=NULL) + { + SendToTarget(m_penAutoCameraEndTarget, m_eetAutoCameraEndEvent, m_penPlayer); + } + return; + } + otherwise() : { + resume; + } + } + return; + } + + // routine for playing movable camera + PlayMovingCamera() + { + // init camera + ECameraStart eStart; + eStart.penCamera = this; + m_penPlayer->SendEvent(eStart); + + // check all markers for correct type and numbers + INDEX ctMarkers=1; + INDEX ctNonSkipped=0; + CCameraMarker *pcm0 = (CCameraMarker*)&*m_penTarget; + CCameraMarker *pcm = (CCameraMarker*)&*pcm0->m_penTarget; + // loop thru markers + while( pcm!=NULL && pcm->m_penTarget!=pcm0) + { + pcm = (CCameraMarker*)&*pcm->m_penTarget; + if (pcm==NULL) { + WarningMessage( "Movable camera - broken link!"); + return; + } + if (!pcm->m_bSkipToNext) { + ctNonSkipped++; + } + ctMarkers++; + if (ctMarkers>500) { + WarningMessage( "Movable camera - invalid marker loop!"); + return; + } + } + // check if we have enough markers to do smooth interpolation + if( ctMarkers<2) { + WarningMessage( "Movable camera requires at least 2 markers in order to work!"); + return; + } + // check if we have enough markers to do smooth interpolation + if( ctNonSkipped<1) { + WarningMessage( "Movable camera requires at least 1 non-skipped marker!"); + return; + } + + // prepare internal variables + FLOAT tmCurrent; + if( !m_bIgnoreTimeStretch) + { + tmCurrent= _pTimer->CurrentTick(); + } + else + { + tmCurrent = m_fMyTimer; + } + + m_tmAtMarker = tmCurrent; + m_tmDelta = 0.0f; + m_bStopMoving = FALSE; + m_penLast = pcm; // keep last marker + ASSERT( pcm->m_penTarget == m_penTarget); + pcm = (CCameraMarker*)&*m_penTarget; + m_colFade0 = m_colFade1 = pcm->m_colFade; + + // register camera as movable entity + AddToMovers(); + m_bMoving = TRUE; + + // roll, baby, roll ... + wait() { + on( EStop) : { + ECameraStop eStop; + eStop.penCamera=this; + m_penPlayer->SendEvent(eStop); + return; + } + otherwise() : { + resume; + } + } + + // all done for now + return; + } + + + // determine camera type and jump to corresponding routine + PlayCamera() + { + // eventually add to movers list + CCameraMarker &cm = (CCameraMarker&)*m_penTarget; + // if auto rotating + if( m_bAutoRotation) + { + jump PlayAutoRotatingCamera(); + } + // if there is at least one marker + else if( &cm!=NULL) + { + // treat camera as movable + jump PlayMovingCamera(); + } + else + { + // treat camera as fixed + jump PlayStaticCamera(); + } + } + + + Main() + { + // init as model + InitAsEditorModel(); + SetPhysicsFlags(EPF_MOVABLE); + SetCollisionFlags(ECF_CAMERA); + // set appearance + FLOAT fSize = 5.0f; + GetModelObject()->mo_Stretch = FLOAT3D(fSize, fSize, fSize); + SetModel(MODEL_CAMERA); + SetModelMainTexture(TEXTURE_CAMERA); + m_fLastFOV = m_fFOV; + + if( m_penTarget!=NULL && !IsOfClass( m_penTarget, "Camera Marker")) { + WarningMessage( "Entity '%s' is not of Camera Marker class!", m_penTarget); + m_penTarget = NULL; + } + + if( m_bAutoRotation || m_penTarget!=NULL) + { + autowait(0.1f); + } + + m_vRelTargetOffset=FLOAT3D(0,0,0); + if( m_penTarget!=NULL) + { + CCameraMarker *pcm = &(CCameraMarker&)*m_penTarget; + if( pcm->m_penViewTarget!=NULL) + { + FLOAT3D vAbsTarget=FLOAT3D(0,0,0); + pcm->m_penViewTarget->GetEntityPointRatio(pcm->m_vPosRatio, vAbsTarget, FALSE); + m_vRelTargetOffset=vAbsTarget-pcm->m_penViewTarget->GetPlacement().pl_PositionVector; + } + } + + while(TRUE) + { + wait() { + on (ETrigger eTrigger) : { + CEntity *penCaused; + penCaused = FixupCausedToPlayer(this, eTrigger.penCaused, FALSE); + if( IsDerivedFromClass(penCaused, "Player")) { + m_penPlayer = penCaused; + call PlayCamera(); + } + resume; + } + } + }; + + // cease to exist + Destroy(); + return; + }; +}; + diff --git a/Sources/EntitiesMP/Camera.h b/Sources/EntitiesMP/Camera.h new file mode 100644 index 0000000..ef32f7b --- /dev/null +++ b/Sources/EntitiesMP/Camera.h @@ -0,0 +1,129 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Camera_INCLUDED +#define _EntitiesMP_Camera_INCLUDED 1 +#include +#include +extern "C" DECL_DLL CDLLEntityClass CCamera_DLLClass; +class CCamera : public CMovableModelEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_tmTime; + FLOAT m_fFOV; + FLOAT m_fLastFOV; + CEntityPointer m_penTarget; + CTString m_strName; + CEntityPointer m_penOnBreak; + BOOL m_bWideScreen; + FLOAT m_tmAtMarker; + FLOAT m_tmDelta; + FLOAT3D m_vPNp0; + FLOAT3D m_vPNp1; + FLOAT3D m_vTNp0; + FLOAT3D m_vTNp1; + FLOAT m_fFOVp0; + FLOAT m_fFOVp1; + FLOAT m_fTFOVp0; + FLOAT m_fTFOVp1; + FLOATquat3D m_qPNp0; + FLOATquat3D m_qPNp1; + FLOATquat3D m_qANp0; + FLOATquat3D m_qANp1; + CEntityPointer m_penLast; + CEntityPointer m_penPlayer; + CTString m_strDescription; + BOOL m_bStopMoving; + COLOR m_colFade0; + COLOR m_colFade1; + BOOL m_bMoving; + CEntityPointer m_penViewTarget0; + CEntityPointer m_penViewTarget1; + FLOAT3D m_vPosRatio0; + FLOAT3D m_vPosRatio1; + FLOAT m_fMyTimer; + FLOAT m_fMyTimerLast; + BOOL m_bIgnoreTimeStretch; + BOOL m_bAutoRotation; + FLOAT m_fStartHdg; + FLOAT m_fRotateSpeed; + FLOAT m_fRotateTime; + FLOAT m_fRadX; + FLOAT m_fHeight; + FLOAT m_fRadZ; + CEntityPointer m_penAutoCameraEndTarget; + enum EventEType m_eetAutoCameraEndEvent; + FLOAT3D m_vRelTargetOffset; + +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void RenderParticles(void); + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +const CTString & GetDescription(void)const; + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void GetAutoRotatePlacement(FLOAT tmCurrent,FLOAT3D & vPos,FLOATmatrix3D & mRot, +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CPlacement3D & plNew,FLOAT3D vTarget)const; + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +CPlacement3D GetLerpedPlacement(void)const; + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void CalcTargetedRotation(const FLOAT3D & vMyPos,CEntity * penViewTarget, +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +FLOAT3D vPosRatio,FLOATmatrix3D & mRotTarget,BOOL bLerping)const; + +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void PreMoving(); + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void DoMoving(); + +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +void PostMoving(); +#define STATE_CCamera_PlayStaticCamera 0x00dc0000 + BOOL +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayStaticCamera(const CEntityEvent &__eeInput); + BOOL H0x00dc0001_PlayStaticCamera_01(const CEntityEvent &__eeInput); + BOOL H0x00dc0002_PlayStaticCamera_02(const CEntityEvent &__eeInput); +#define STATE_CCamera_PlayAutoRotatingCamera 0x00dc0003 + BOOL +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayAutoRotatingCamera(const CEntityEvent &__eeInput); + BOOL H0x00dc0004_PlayAutoRotatingCamera_01(const CEntityEvent &__eeInput); + BOOL H0x00dc0005_PlayAutoRotatingCamera_02(const CEntityEvent &__eeInput); +#define STATE_CCamera_PlayMovingCamera 0x00dc0006 + BOOL +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayMovingCamera(const CEntityEvent &__eeInput); + BOOL H0x00dc0007_PlayMovingCamera_01(const CEntityEvent &__eeInput); + BOOL H0x00dc0008_PlayMovingCamera_02(const CEntityEvent &__eeInput); +#define STATE_CCamera_PlayCamera 0x00dc0009 + BOOL +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayCamera(const CEntityEvent &__eeInput); +#define STATE_CCamera_Main 1 + BOOL +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00dc000a_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00dc000b_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00dc000c_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00dc000d_Main_04(const CEntityEvent &__eeInput); + BOOL H0x00dc000e_Main_05(const CEntityEvent &__eeInput); + BOOL H0x00dc000f_Main_06(const CEntityEvent &__eeInput); + BOOL H0x00dc0010_Main_07(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Camera_INCLUDED diff --git a/Sources/EntitiesMP/CameraMarker.cpp b/Sources/EntitiesMP/CameraMarker.cpp new file mode 100644 index 0000000..dc80e32 --- /dev/null +++ b/Sources/EntitiesMP/CameraMarker.cpp @@ -0,0 +1,87 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" + +#include "StdH.h" + +#include +#include +void CCameraMarker::SetDefaultProperties(void) { + m_fDeltaTime = 5.0f; + m_fBias = 0.0f; + m_fTension = 0.0f; + m_fContinuity = 0.0f; + m_bStopMoving = FALSE ; + m_fFOV = 90.0f; + m_bSkipToNext = FALSE ; + m_colFade = 0; + m_penTrigger = NULL; + m_penViewTarget = NULL; + m_vPosRatio = FLOAT3D(0 , 0 , 0); + m_fRatioX = 0.5f; + m_fRatioY = 0.5f; + m_fRatioZ = 0.5f; + CMarker::SetDefaultProperties(); +} + +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +BOOL CCameraMarker::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +{ +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +fnmMarkerClass = CTFILENAME ("Classes\\CameraMarker.ecl"); +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +strTargetProperty = "Target"; +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +return TRUE ; +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +} + +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +SLONG CCameraMarker::GetUsedMemory(void) +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +{ +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +return (sizeof (CCameraMarker ) - sizeof (CMarker ) + CMarker :: GetUsedMemory ()); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +} +BOOL CCameraMarker:: +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCameraMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCameraMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +m_fDeltaTime = ClampDn (m_fDeltaTime , 0.001f); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +m_fBias = Clamp (m_fBias , - 1.0f , + 1.0f); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +m_fTension = Clamp (m_fTension , - 1.0f , + 1.0f); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +m_fContinuity = Clamp (m_fContinuity , - 1.0f , + 1.0f); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +m_vPosRatio = FLOAT3D (m_fRatioX , m_fRatioY , m_fRatioZ ); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +InitAsEditorModel (); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +SetModel (MODEL_MARKER ); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +if(m_penTarget != NULL && ! IsOfClass (m_penTarget , "Camera Marker")){ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +WarningMessage ("Entity '%s' is not of Camera Marker class!" , m_penTarget ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +m_penTarget = NULL ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +} +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/CameraMarker.es b/Sources/EntitiesMP/CameraMarker.es new file mode 100644 index 0000000..b7ed4dc --- /dev/null +++ b/Sources/EntitiesMP/CameraMarker.es @@ -0,0 +1,89 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +224 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; + +class CCameraMarker: CMarker +{ +name "Camera Marker"; +thumbnail "Thumbnails\\CameraMarker.tbn"; + + +properties: + + 1 FLOAT m_fDeltaTime "Delta time" 'D' = 5.0f, + 2 FLOAT m_fBias "Bias" 'B' = 0.0f, + 3 FLOAT m_fTension "Tension" 'E' = 0.0f, + 4 FLOAT m_fContinuity "Continuity" 'C' = 0.0f, + 5 BOOL m_bStopMoving "Stop moving" 'O' = FALSE, + 6 FLOAT m_fFOV "FOV" 'F' = 90.0f, + 7 BOOL m_bSkipToNext "Skip to next" 'S' = FALSE, + 8 COLOR m_colFade "Fade Color" 'C' = 0, // camera fading color + 9 CEntityPointer m_penTrigger "Trigger" 'G', // camera triggers when at this marker + 10 CEntityPointer m_penViewTarget "View Target" 'V', // camera will targeting this entity + 11 FLOAT3D m_vPosRatio = FLOAT3D(0,0,0), + 12 FLOAT m_fRatioX "View pos ratio X" 'X' = 0.5f, + 13 FLOAT m_fRatioY "View pos ratio Y" 'Y' = 0.5f, + 14 FLOAT m_fRatioZ "View pos ratio Z" 'Z' = 0.5f, + + +components: + + 1 model MODEL_MARKER "Models\\Editor\\CameraMarker.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\CameraMarker.tex" + + +functions: + + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker( CTFileName &fnmMarkerClass, CTString &strTargetProperty) const + { + fnmMarkerClass = CTFILENAME("Classes\\CameraMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + return( sizeof(CCameraMarker) - sizeof(CMarker) + CMarker::GetUsedMemory()); + } + + + +procedures: + + Main() + { + // clamp parameters + m_fDeltaTime = ClampDn( m_fDeltaTime, 0.001f); + m_fBias = Clamp( m_fBias, -1.0f, +1.0f); + m_fTension = Clamp( m_fTension, -1.0f, +1.0f); + m_fContinuity = Clamp( m_fContinuity, -1.0f, +1.0f); + + m_vPosRatio=FLOAT3D(m_fRatioX, m_fRatioY, m_fRatioZ); + + // init model + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + if( m_penTarget!=NULL && !IsOfClass( m_penTarget, "Camera Marker")) { + WarningMessage( "Entity '%s' is not of Camera Marker class!", m_penTarget); + m_penTarget = NULL; + } + + return; + } + +}; + diff --git a/Sources/EntitiesMP/CameraMarker.h b/Sources/EntitiesMP/CameraMarker.h new file mode 100644 index 0000000..643362e --- /dev/null +++ b/Sources/EntitiesMP/CameraMarker.h @@ -0,0 +1,37 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_CameraMarker_INCLUDED +#define _EntitiesMP_CameraMarker_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CCameraMarker_DLLClass; +class CCameraMarker : public CMarker { +public: + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fDeltaTime; + FLOAT m_fBias; + FLOAT m_fTension; + FLOAT m_fContinuity; + BOOL m_bStopMoving; + FLOAT m_fFOV; + BOOL m_bSkipToNext; + COLOR m_colFade; + CEntityPointer m_penTrigger; + CEntityPointer m_penViewTarget; + FLOAT3D m_vPosRatio; + FLOAT m_fRatioX; + FLOAT m_fRatioY; + FLOAT m_fRatioZ; + +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +SLONG GetUsedMemory(void); +#define STATE_CCameraMarker_Main 1 + BOOL +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_CameraMarker_INCLUDED diff --git a/Sources/EntitiesMP/CameraMarker_tables.h b/Sources/EntitiesMP/CameraMarker_tables.h new file mode 100644 index 0000000..3afc244 --- /dev/null +++ b/Sources/EntitiesMP/CameraMarker_tables.h @@ -0,0 +1,49 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CCameraMarker + +CEntityProperty CCameraMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e0<<8)+1, offsetof(CCameraMarker, m_fDeltaTime), "Delta time", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e0<<8)+2, offsetof(CCameraMarker, m_fBias), "Bias", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e0<<8)+3, offsetof(CCameraMarker, m_fTension), "Tension", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e0<<8)+4, offsetof(CCameraMarker, m_fContinuity), "Continuity", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e0<<8)+5, offsetof(CCameraMarker, m_bStopMoving), "Stop moving", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e0<<8)+6, offsetof(CCameraMarker, m_fFOV), "FOV", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e0<<8)+7, offsetof(CCameraMarker, m_bSkipToNext), "Skip to next", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000e0<<8)+8, offsetof(CCameraMarker, m_colFade), "Fade Color", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e0<<8)+9, offsetof(CCameraMarker, m_penTrigger), "Trigger", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e0<<8)+10, offsetof(CCameraMarker, m_penViewTarget), "View Target", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000000e0<<8)+11, offsetof(CCameraMarker, m_vPosRatio), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e0<<8)+12, offsetof(CCameraMarker, m_fRatioX), "View pos ratio X", 'X', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e0<<8)+13, offsetof(CCameraMarker, m_fRatioY), "View pos ratio Y", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e0<<8)+14, offsetof(CCameraMarker, m_fRatioZ), "View pos ratio Z", 'Z', 0x7F0000FFUL, 0), +}; +#define CCameraMarker_propertiesct ARRAYCOUNT(CCameraMarker_properties) + +CEntityComponent CCameraMarker_components[] = { +#define MODEL_MARKER ((0x000000e0<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\CameraMarker.mdl"), +#define TEXTURE_MARKER ((0x000000e0<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\CameraMarker.tex"), +}; +#define CCameraMarker_componentsct ARRAYCOUNT(CCameraMarker_components) + +CEventHandlerEntry CCameraMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CCameraMarker:: +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/CameraMarker.es" +Main),DEBUGSTRING("CCameraMarker::Main")}, +}; +#define CCameraMarker_handlersct ARRAYCOUNT(CCameraMarker_handlers) + +CEntity *CCameraMarker_New(void) { return new CCameraMarker; }; +void CCameraMarker_OnInitClass(void) {}; +void CCameraMarker_OnEndClass(void) {}; +void CCameraMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CCameraMarker_OnWorldEnd(CWorld *pwo) {}; +void CCameraMarker_OnWorldInit(CWorld *pwo) {}; +void CCameraMarker_OnWorldTick(CWorld *pwo) {}; +void CCameraMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CCameraMarker, CMarker, "Camera Marker", "Thumbnails\\CameraMarker.tbn", 0x000000e0); +DECLARE_CTFILENAME(_fnmCCameraMarker_tbn, "Thumbnails\\CameraMarker.tbn"); diff --git a/Sources/EntitiesMP/Camera_tables.h b/Sources/EntitiesMP/Camera_tables.h new file mode 100644 index 0000000..b5131aa --- /dev/null +++ b/Sources/EntitiesMP/Camera_tables.h @@ -0,0 +1,105 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CCamera + +CEntityProperty CCamera_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+1, offsetof(CCamera, m_tmTime), "Time", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+2, offsetof(CCamera, m_fFOV), "FOV", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+5, offsetof(CCamera, m_fLastFOV), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000dc<<8)+3, offsetof(CCamera, m_penTarget), "Target", 'T', C_lBLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000dc<<8)+4, offsetof(CCamera, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000dc<<8)+6, offsetof(CCamera, m_penOnBreak), "OnBreak", 'B', C_lRED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000dc<<8)+7, offsetof(CCamera, m_bWideScreen), "WideScreen", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+10, offsetof(CCamera, m_tmAtMarker), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+11, offsetof(CCamera, m_tmDelta), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000000dc<<8)+13, offsetof(CCamera, m_vPNp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000000dc<<8)+14, offsetof(CCamera, m_vPNp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000000dc<<8)+15, offsetof(CCamera, m_vTNp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000000dc<<8)+16, offsetof(CCamera, m_vTNp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+17, offsetof(CCamera, m_fFOVp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+18, offsetof(CCamera, m_fFOVp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+19, offsetof(CCamera, m_fTFOVp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+20, offsetof(CCamera, m_fTFOVp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATQUAT3D, NULL, (0x000000dc<<8)+31, offsetof(CCamera, m_qPNp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATQUAT3D, NULL, (0x000000dc<<8)+32, offsetof(CCamera, m_qPNp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATQUAT3D, NULL, (0x000000dc<<8)+33, offsetof(CCamera, m_qANp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATQUAT3D, NULL, (0x000000dc<<8)+34, offsetof(CCamera, m_qANp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000dc<<8)+40, offsetof(CCamera, m_penLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000dc<<8)+41, offsetof(CCamera, m_penPlayer), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000dc<<8)+42, offsetof(CCamera, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000dc<<8)+43, offsetof(CCamera, m_bStopMoving), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000dc<<8)+50, offsetof(CCamera, m_colFade0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000dc<<8)+51, offsetof(CCamera, m_colFade1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000dc<<8)+52, offsetof(CCamera, m_bMoving), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000dc<<8)+53, offsetof(CCamera, m_penViewTarget0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000dc<<8)+54, offsetof(CCamera, m_penViewTarget1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000000dc<<8)+55, offsetof(CCamera, m_vPosRatio0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000000dc<<8)+56, offsetof(CCamera, m_vPosRatio1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+60, offsetof(CCamera, m_fMyTimer), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+61, offsetof(CCamera, m_fMyTimerLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000dc<<8)+62, offsetof(CCamera, m_bIgnoreTimeStretch), "Ignore time stretch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000dc<<8)+63, offsetof(CCamera, m_bAutoRotation), "Auto rotate (AR)", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+64, offsetof(CCamera, m_fStartHdg), "AR start heading", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+65, offsetof(CCamera, m_fRotateSpeed), "AR Rotate speed", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+66, offsetof(CCamera, m_fRotateTime), "AR Rotate time", 'I', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+67, offsetof(CCamera, m_fRadX), "AR Radius X", 'X', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+68, offsetof(CCamera, m_fHeight), "AR Height (controlls pitch)", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dc<<8)+69, offsetof(CCamera, m_fRadZ), "AR Radius Z", 'Z', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000dc<<8)+70, offsetof(CCamera, m_penAutoCameraEndTarget), "Auto camera end target", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000dc<<8)+71, offsetof(CCamera, m_eetAutoCameraEndEvent), "Auto camera end event", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000000dc<<8)+72, offsetof(CCamera, m_vRelTargetOffset), "", 0, 0, 0), +}; +#define CCamera_propertiesct ARRAYCOUNT(CCamera_properties) + +CEntityComponent CCamera_components[] = { +#define MODEL_CAMERA ((0x000000dc<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_CAMERA, "EFNM" "Models\\Editor\\Camera.mdl"), +#define TEXTURE_CAMERA ((0x000000dc<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_CAMERA, "EFNM" "Models\\Editor\\Camera.tex"), +}; +#define CCamera_componentsct ARRAYCOUNT(CCamera_components) + +CEventHandlerEntry CCamera_handlers[] = { + {0x00dc0000, -1, CEntity::pEventHandler(&CCamera:: +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayStaticCamera),DEBUGSTRING("CCamera::PlayStaticCamera")}, + {0x00dc0001, -1, CEntity::pEventHandler(&CCamera::H0x00dc0001_PlayStaticCamera_01), DEBUGSTRING("CCamera::H0x00dc0001_PlayStaticCamera_01")}, + {0x00dc0002, -1, CEntity::pEventHandler(&CCamera::H0x00dc0002_PlayStaticCamera_02), DEBUGSTRING("CCamera::H0x00dc0002_PlayStaticCamera_02")}, + {0x00dc0003, -1, CEntity::pEventHandler(&CCamera:: +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayAutoRotatingCamera),DEBUGSTRING("CCamera::PlayAutoRotatingCamera")}, + {0x00dc0004, -1, CEntity::pEventHandler(&CCamera::H0x00dc0004_PlayAutoRotatingCamera_01), DEBUGSTRING("CCamera::H0x00dc0004_PlayAutoRotatingCamera_01")}, + {0x00dc0005, -1, CEntity::pEventHandler(&CCamera::H0x00dc0005_PlayAutoRotatingCamera_02), DEBUGSTRING("CCamera::H0x00dc0005_PlayAutoRotatingCamera_02")}, + {0x00dc0006, -1, CEntity::pEventHandler(&CCamera:: +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayMovingCamera),DEBUGSTRING("CCamera::PlayMovingCamera")}, + {0x00dc0007, -1, CEntity::pEventHandler(&CCamera::H0x00dc0007_PlayMovingCamera_01), DEBUGSTRING("CCamera::H0x00dc0007_PlayMovingCamera_01")}, + {0x00dc0008, -1, CEntity::pEventHandler(&CCamera::H0x00dc0008_PlayMovingCamera_02), DEBUGSTRING("CCamera::H0x00dc0008_PlayMovingCamera_02")}, + {0x00dc0009, -1, CEntity::pEventHandler(&CCamera:: +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +PlayCamera),DEBUGSTRING("CCamera::PlayCamera")}, + {1, -1, CEntity::pEventHandler(&CCamera:: +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/Camera.es" +Main),DEBUGSTRING("CCamera::Main")}, + {0x00dc000a, -1, CEntity::pEventHandler(&CCamera::H0x00dc000a_Main_01), DEBUGSTRING("CCamera::H0x00dc000a_Main_01")}, + {0x00dc000b, -1, CEntity::pEventHandler(&CCamera::H0x00dc000b_Main_02), DEBUGSTRING("CCamera::H0x00dc000b_Main_02")}, + {0x00dc000c, -1, CEntity::pEventHandler(&CCamera::H0x00dc000c_Main_03), DEBUGSTRING("CCamera::H0x00dc000c_Main_03")}, + {0x00dc000d, -1, CEntity::pEventHandler(&CCamera::H0x00dc000d_Main_04), DEBUGSTRING("CCamera::H0x00dc000d_Main_04")}, + {0x00dc000e, -1, CEntity::pEventHandler(&CCamera::H0x00dc000e_Main_05), DEBUGSTRING("CCamera::H0x00dc000e_Main_05")}, + {0x00dc000f, -1, CEntity::pEventHandler(&CCamera::H0x00dc000f_Main_06), DEBUGSTRING("CCamera::H0x00dc000f_Main_06")}, + {0x00dc0010, -1, CEntity::pEventHandler(&CCamera::H0x00dc0010_Main_07), DEBUGSTRING("CCamera::H0x00dc0010_Main_07")}, +}; +#define CCamera_handlersct ARRAYCOUNT(CCamera_handlers) + +CEntity *CCamera_New(void) { return new CCamera; }; +void CCamera_OnInitClass(void) {}; +void CCamera_OnEndClass(void) {}; +void CCamera_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CCamera_OnWorldEnd(CWorld *pwo) {}; +void CCamera_OnWorldInit(CWorld *pwo) {}; +void CCamera_OnWorldTick(CWorld *pwo) {}; +void CCamera_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CCamera, CMovableModelEntity, "Camera", "Thumbnails\\Camera.tbn", 0x000000dc); +DECLARE_CTFILENAME(_fnmCCamera_tbn, "Thumbnails\\Camera.tbn"); diff --git a/Sources/EntitiesMP/CannonBall.cpp b/Sources/EntitiesMP/CannonBall.cpp new file mode 100644 index 0000000..c27aa60 --- /dev/null +++ b/Sources/EntitiesMP/CannonBall.cpp @@ -0,0 +1,911 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" + +#include "StdH.h" +#include "Models/Weapons/Cannon/Projectile/Cannonball.h" +#include "EntitiesMP/MovingBrush.h" +#include "EntitiesMP/DestroyableArchitecture.h" + +#include +#include +CEntityEvent *ELaunchCannonBall::MakeCopy(void) { CEntityEvent *peeCopy = new ELaunchCannonBall(*this); return peeCopy;} +ELaunchCannonBall::ELaunchCannonBall() : CEntityEvent(EVENTCODE_ELaunchCannonBall) {; + ClearToDefault(penLauncher); + ClearToDefault(cbtType); + ClearToDefault(fLaunchPower); + ClearToDefault(fSize); +}; +CEntityEvent *EForceExplode::MakeCopy(void) { CEntityEvent *peeCopy = new EForceExplode(*this); return peeCopy;} +EForceExplode::EForceExplode() : CEntityEvent(EVENTCODE_EForceExplode) {; +}; +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" + + +// projectile solid +#define ECF_CANNON_BALL ( \ + ((ECBI_MODEL|ECBI_BRUSH|ECBI_PROJECTILE_SOLID|ECBI_CORPSE|ECBI_MODEL_HOLDER|ECBI_MODEL_HOLDER)<PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNONEXPLOSIONSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNONSHOCKWAVE); + + pdec->PrecacheModel(MODEL_BALL); + pdec->PrecacheTexture(TEXTURE_IRON_BALL); + pdec->PrecacheTexture(TEXTURE_NUKE_BALL); + pdec->PrecacheTexture(TEX_REFL_BWRIPLES01); + pdec->PrecacheTexture(TEX_SPEC_MEDIUM); + pdec->PrecacheSound(SOUND_BALL_BOUNCE); +} + + +void CCannonBall::SetDefaultProperties(void) { + m_penLauncher = NULL; + m_fLaunchPower = 0.0f; + m_fCannonBallSize = 0.0f; + m_fIgnoreTime = 0.0f; + m_fStartTime = 0.0f; + m_iNextChannel = 0; + m_bSelfExploded = FALSE ; + m_soBounce0.SetOwner(this); +m_soBounce0.Stop_internal(); + m_soBounce1.SetOwner(this); +m_soBounce1.Stop_internal(); + m_soBounce2.SetOwner(this); +m_soBounce2.Stop_internal(); + m_soBounce3.SetOwner(this); +m_soBounce3.Stop_internal(); + m_soBounce4.SetOwner(this); +m_soBounce4.Stop_internal(); + m_cbtType = CBT_IRON ; + m_tmInvisibility = 0.0f; + m_tmExpandBox = 0.0f; + m_tmForceExplode = 0.0f; + CMovableModelEntity::SetDefaultProperties(); +} + +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void CCannonBall::PreMoving(void) { +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(m_tmExpandBox > 0){ +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(_pTimer -> CurrentTick () > m_fStartTime + m_tmExpandBox ){ +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ChangeCollisionBoxIndexWhenPossible (1); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_tmExpandBox = 0; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +CMovableModelEntity :: PreMoving (); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} + +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void CCannonBall::PostMoving(void) +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +CMovableModelEntity :: PostMoving (); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(en_vCurrentTranslationAbsolute . Length () < 1.0f || +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +_pTimer -> CurrentTick () >= m_tmForceExplode || +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +(GetCollisionBoxIndex () == 0 && +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +(_pTimer -> CurrentTick () > m_fStartTime + m_tmExpandBox + 0.5f))) +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SendEvent (EForceExplode ()); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void CCannonBall::Read_t(CTStream * istr) +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +CMovableModelEntity :: Read_t (istr ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} + +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL CCannonBall::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +CModelObject * pmo = GetModelObject (); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if((pmo != NULL ) && (_pTimer -> GetLerpedCurrentTick () < (m_fStartTime + m_tmInvisibility ))) +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +pmo -> mo_colBlendColor = 0; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +else +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +pmo -> mo_colBlendColor = C_WHITE | CT_OPAQUE ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +return CEntity :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} + +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void CCannonBall::RenderParticles(void) { +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(GetRenderType () != CEntity :: RT_MODEL ){ +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +return ; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT fSpeedRatio = Min (en_vCurrentTranslationAbsolute . Length () / 140.0f , 1.0f); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +INDEX ctFireParticles = INDEX ((Max (fSpeedRatio - 0.5f , 0.0f) * 2.0f) * 128); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(_pTimer -> GetLerpedCurrentTick () - m_fStartTime > 0.075) +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Particles_BeastBigProjectileTrail (this , 2.0f , 1.0f , 0.75f , ctFireParticles ); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} + +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void CCannonBall::Initialize(void) { +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +InitAsModel (); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetPhysicsFlags (EPF_MODEL_BOUNCING ); +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetCollisionFlags (ECF_CANNON_BALL ); +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetModel (MODEL_BALL ); +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(m_cbtType == CBT_IRON ) +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetModelMainTexture (TEXTURE_IRON_BALL ); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +else +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetModelMainTexture (TEXTURE_NUKE_BALL ); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fCannonBallSize , m_fCannonBallSize , m_fCannonBallSize )); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ModelChangeNotify (); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +GetModelObject () -> mo_toReflection . SetData (GetTextureDataForComponent (TEX_REFL_BWRIPLES01 )); +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +GetModelObject () -> mo_toSpecular . SetData (GetTextureDataForComponent (TEX_SPEC_MEDIUM )); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +LaunchAsFreeProjectile (FLOAT3D (0.0f , 0.0f , - m_fLaunchPower ) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +en_fBounceDampNormal = 0.5f; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +en_fBounceDampParallel = 0.75f; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +en_fAcceleration = 0.0f; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +en_fDeceleration = 5.0f; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +en_fCollisionSpeedLimit = 40.0f; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +en_fCollisionDamageFactor = 10.0f; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetHealth (50000.0f); +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +GetModelObject () -> PlayAnim (CANNONBALL_ANIM_FIRESLOW , 0); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} + +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT CCannonBall::CalculateDamageToInflict(void) +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT fMaxDamage = IRON_DAMAGE_MAX ; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(m_cbtType == CBT_NUKE ) +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +fMaxDamage = IRON_DAMAGE_MAX ; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT fSpeedRatio = en_vCurrentTranslationAbsolute . Length () / 140.0f; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT fApplyDamage = Clamp (fSpeedRatio * fMaxDamage , 0.0f , fMaxDamage ); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +return fApplyDamage ; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} + +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void CCannonBall::Explosion(FLOAT3D vCenter, +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +const FLOAT3D & vStretchExplosion, +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +const FLOAT3D & vStretchShockwave, +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +const FLOAT3D & vStretchStain, +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL bHasExplosion, +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL bHasShockWave, +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL bHasStain, +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL bHasLight) +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ESpawnEffect ese ; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT3D vOnPlane ; +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOATplane3D vPlaneNormal ; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT fDistanceToEdge ; +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(bHasExplosion ) +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(bHasLight ) +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . betType = BET_CANNON ; +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +else +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . betType = BET_CANNON_NOLIGHT ; +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . vStretch = vStretchExplosion ; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +CPlacement3D plHandle = GetPlacement (); +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +plHandle . pl_PositionVector += vCenter ; +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SpawnEffect (plHandle , ese ); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(IsDerivedFromClass (m_penLauncher , "Player")){ +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SpawnRangeSound (m_penLauncher , this , SNDT_PLAYER , 100.0f); +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(GetNearestPolygon (vOnPlane , vPlaneNormal , fDistanceToEdge )){ +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if((vOnPlane - GetPlacement () . pl_PositionVector ) . Length () < 3.5f){ +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(bHasStain ) +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . betType = BET_CANNONEXPLOSIONSTAIN ; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . vStretch = vStretchShockwave ; +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SpawnEffect (CPlacement3D (vOnPlane , ANGLE3D (0 , 0 , 0)) , ese ); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(bHasShockWave ) +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . betType = BET_CANNONSHOCKWAVE ; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ese . vStretch = vStretchShockwave ; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SpawnEffect (CPlacement3D (vOnPlane , ANGLE3D (0 , 0 , 0)) , ese ); +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +RangeDamage (); +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} + +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL CCannonBall::BallTouchExplode(CEntityPointer penHit) +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT fApplyDamage = CalculateDamageToInflict (); +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT fHealth = 100; +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL bForceCannonballToExplode = FALSE ; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(penHit -> GetPhysicsFlags () & EPF_MOVABLE ){ +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +fHealth = ((CMovableEntity &) * penHit ) . GetHealth (); +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(IsDerivedFromClass (penHit , "Enemy Base")) +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +bForceCannonballToExplode = ((CEnemyBase &) * penHit ) . ForcesCannonballToExplode (); +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +}else { +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(IsOfClass (penHit , "ModelHolder2") || IsOfClass (penHit , "ExotechLarvaBattery")){ +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +fHealth = ((CLiveEntity &) * penHit ) . GetHealth (); +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +}else { +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +return FALSE ; +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(IsOfClass (penHit , "ModelHolder2")) +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +bForceCannonballToExplode = TRUE ; +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(IsOfClass (penHit , "Player")){ +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +fHealth += ((CPlayer &) * penHit ) . m_fArmor * 2.0f; +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT3D vDirection = en_vCurrentTranslationAbsolute ; +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +vDirection . Normalize (); +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +const FLOAT fDamageMul = GetSeriousDamageMultiplier (m_penLauncher ); +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +InflictDirectDamage (penHit , m_penLauncher , DMT_CANNONBALL , fApplyDamage * fDamageMul , +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +GetPlacement () . pl_PositionVector , vDirection ); +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +return (fApplyDamage <= fHealth || bForceCannonballToExplode ); +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} + +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void CCannonBall::RangeDamage(void) +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +const FLOAT fDamageMul = GetSeriousDamageMultiplier (m_penLauncher ); +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(m_cbtType == CBT_IRON ){ +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +InflictRangeDamage (m_penLauncher , DMT_CANNONBALL_EXPLOSION , IRON_RANGE_DAMAGE * fDamageMul , +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +GetPlacement () . pl_PositionVector , IRON_RANGE_HOTSPOT , IRON_RANGE_FALLOFF ); +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +}else { +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +InflictRangeDamage (m_penLauncher , DMT_CANNONBALL_EXPLOSION , NUKE_RANGE_DAMAGE * fDamageMul , +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +GetPlacement () . pl_PositionVector , NUKE_RANGE_HOTSPOT , NUKE_RANGE_FALLOFF ); +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} + +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void CCannonBall::SpawnEffect(const CPlacement3D & plEffect,const ESpawnEffect & eSpawnEffect) { +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +CEntityPointer penEffect = CreateEntity (plEffect , CLASS_BASIC_EFFECT ); +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +penEffect -> Initialize (eSpawnEffect ); +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} + +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void CCannonBall::BounceSound(FLOAT fSpeed) { +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT fVolume = Clamp (fSpeed / 6.0f , 0.0f , 1.0f); +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(fVolume < 0.1f){ +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +return ; +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +CSoundObject & so = (& m_soBounce0 ) [ m_iNextChannel ]; +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_iNextChannel = (m_iNextChannel + 1) % 5; +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +so . Set3DParameters (70.0f , 10.0f , fVolume , 1.0f); +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +PlaySound (so , SOUND_BALL_BOUNCE , SOF_3D ); +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +BOOL CCannonBall:: +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Bounce(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonBall_Bounce + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonBall::Bounce expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +CEntity * penObstacle ; +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(CheckForCollisionNow (0 , & penObstacle )){ +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Return(STATE_CURRENT,EEnd ()); +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +return TRUE; +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT fWaitTime = IRON_LIFE_TIME ; +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(m_cbtType == CBT_NUKE ) +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +fWaitTime = NUKE_LIFE_TIME ; +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(fWaitTime ); +Jump(STATE_CURRENT, 0x01fa0003, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa0003_Bounce_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0003 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&epass= (EPass&)__eeInput; + +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL bHit ; +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +bHit = epass . penOther != m_penLauncher || _pTimer -> CurrentTick () > m_fIgnoreTime ; +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +bHit &= ! IsOfClass (epass . penOther , "Twister"); +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(bHit ) +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(BallTouchExplode (epass . penOther )){UnsetTimer();Jump(STATE_CURRENT,0x01fa0004, FALSE, EInternal());return TRUE;} +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +return TRUE; +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(IsOfClass (etouch . penOther , "Cannon ball")) +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +UnsetTimer();Jump(STATE_CURRENT,0x01fa0004, FALSE, EInternal());return TRUE; +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(IsOfClass (etouch . penOther , "Moving Brush")) +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +CMovingBrush & br = (CMovingBrush &) * etouch . penOther ; +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(br . m_fHealth > 0) +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT3D vDirection = en_vCurrentTranslationAbsolute ; +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +vDirection . Normalize (); +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +InflictDirectDamage (etouch . penOther , m_penLauncher , DMT_CANNONBALL , CalculateDamageToInflict () , +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +GetPlacement () . pl_PositionVector , vDirection ); +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_bSelfExploded = FALSE ; +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +UnsetTimer();Jump(STATE_CURRENT,0x01fa0004, FALSE, EInternal());return TRUE; +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(IsOfClass (etouch . penOther , "DestroyableArchitecture")) +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +CDestroyableArchitecture & br = (CDestroyableArchitecture &) * etouch . penOther ; +#line 491 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(br . m_fHealth > 0) +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT3D vDirection = en_vCurrentTranslationAbsolute ; +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +vDirection . Normalize (); +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +InflictDirectDamage (etouch . penOther , m_penLauncher , DMT_CANNONBALL , CalculateDamageToInflict () , +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +GetPlacement () . pl_PositionVector , vDirection ); +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_bSelfExploded = FALSE ; +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +UnsetTimer();Jump(STATE_CURRENT,0x01fa0004, FALSE, EInternal());return TRUE; +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BounceSound (((FLOAT3D &) etouch . plCollision ) % en_vCurrentTranslationAbsolute ); +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +return TRUE; +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +}ASSERT(FALSE);break;case(EVENTCODE_EForceExplode):{const EForceExplode&e= (EForceExplode&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01fa0004, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01fa0004, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01fa0004, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +}return TRUE;}BOOL CCannonBall::H0x01fa0004_Bounce_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0004 + +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_bSelfExploded = TRUE ; +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Return(STATE_CURRENT,EEnd ()); +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCannonBall:: +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonBall_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_ELaunchCannonBall, "CCannonBall::Main expects 'ELaunchCannonBall' as input!"); const ELaunchCannonBall &eLaunch = (const ELaunchCannonBall &)__eeInput; +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ASSERT (eLaunch . penLauncher != NULL ); +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_penLauncher = eLaunch . penLauncher ; +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_fLaunchPower = eLaunch . fLaunchPower ; +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_cbtType = eLaunch . cbtType ; +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_fCannonBallSize = eLaunch . fSize ; +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_tmInvisibility = 0.05f; +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_bSelfExploded = FALSE ; +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_tmExpandBox = 0.0001f; +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_tmForceExplode = _pTimer -> CurrentTick () + 30.0f; +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Initialize (); +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SendEvent (EReturn ()); +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01fa0005, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa0005_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0005 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01fa0006, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +}return TRUE;}BOOL CCannonBall::H0x01fa0006_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0006 + +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT tmCastCoverPath = _pTimer -> TickQuantum * 1.5f; +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +CCastRay crRay (m_penLauncher , GetPlacement () , m_fLaunchPower * tmCastCoverPath ); +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +crRay . cr_fTestR = 0.75f / 2.0f * m_fCannonBallSize ; +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +crRay . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ; +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +GetWorld () -> CastRay (crRay ); +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_fIgnoreTime = _pTimer -> CurrentTick () + 0.1f; +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_fStartTime = _pTimer -> CurrentTick (); +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(crRay . cr_penHit != NULL && crRay . cr_penHit -> GetRenderType () == RT_MODEL ) +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(BallTouchExplode (crRay . cr_penHit )) +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +{ +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +m_tmForceExplode = _pTimer -> CurrentTick () + tmCastCoverPath ; +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 559 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +STATE_CCannonBall_Bounce, TRUE; +Jump(STATE_CURRENT, 0x01fa0007, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa0007_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CCannonBall_Bounce, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01fa0008, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa0008_Main_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0008 +const EEnd&__e= (EEnd&)__eeInput; +; +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SwitchToEditorModel (); +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ForceFullStop (); +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +ESound eSound ; +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +eSound . EsndtSound = SNDT_EXPLOSION ; +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +eSound . penTarget = m_penLauncher ; +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(IsDerivedFromClass (this , "Player")){ +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SendEventInRange (eSound , FLOATaabbox3D (GetPlacement () . pl_PositionVector , SOUND_RANGE )); +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +} +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +if(!(m_cbtType == CBT_IRON )){ Jump(STATE_CURRENT,0x01fa0023, FALSE, EInternal());return TRUE;} +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (0.0f , 0.0f , 0.0f) , STRETCH_3 , STRETCH_3 , STRETCH_4 , TRUE , TRUE , TRUE , TRUE ); +#line 579 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (1.0f , 1.5f , 1.5f) , STRETCH_3 , STRETCH_3 , STRETCH_4 , TRUE , FALSE , FALSE , FALSE ); +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (- 2.0f , 1.0f , - 1.5f) , STRETCH_3 , STRETCH_3 , STRETCH_4 , TRUE , FALSE , FALSE , FALSE ); +#line 581 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (- 1.0f , 0.5f , 1.0f) , STRETCH_4 , STRETCH_4 , STRETCH_4 , TRUE , FALSE , FALSE , FALSE );Jump(STATE_CURRENT,0x01fa0022, FALSE, EInternal());return TRUE;}BOOL CCannonBall::H0x01fa0023_Main_31(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0023 +if(!(m_cbtType == CBT_NUKE )){ Jump(STATE_CURRENT,0x01fa0021, FALSE, EInternal());return TRUE;} +#line 585 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (0.0f , 0.0f , 0.0f) , STRETCH_6 , STRETCH_6 , STRETCH_10 , TRUE , TRUE , TRUE , TRUE ); +#line 586 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.15f); +Jump(STATE_CURRENT, 0x01fa0009, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa0009_Main_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa000a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa000a_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa000a +; +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (4.0f , 5.0f , 5.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , FALSE , FALSE , FALSE ); +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.2f); +Jump(STATE_CURRENT, 0x01fa000b, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa000b_Main_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa000b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa000c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa000c_Main_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa000c +; +#line 589 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (- 5.0f , 3.0f , - 4.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , FALSE , FALSE , FALSE ); +#line 590 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.15f); +Jump(STATE_CURRENT, 0x01fa000d, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa000d_Main_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa000d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa000e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa000e_Main_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa000e +; +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (- 3.0f , 2.0f , 3.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , FALSE , FALSE , FALSE ); +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.15f); +Jump(STATE_CURRENT, 0x01fa000f, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa000f_Main_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa000f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa0010, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa0010_Main_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0010 +; +#line 593 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (2.0f , 1.0f , 4.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , TRUE , FALSE , FALSE ); +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.2f); +Jump(STATE_CURRENT, 0x01fa0011, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa0011_Main_13(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0011 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa0012, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa0012_Main_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0012 +; +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (- 2.0f , 5.0f , - 4.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , FALSE , FALSE , FALSE ); +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.18f); +Jump(STATE_CURRENT, 0x01fa0013, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa0013_Main_15(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0013 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa0014, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa0014_Main_16(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0014 +; +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (- 3.0f , 2.0f , 2.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , FALSE , FALSE , FALSE ); +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x01fa0015, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa0015_Main_17(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa0016, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa0016_Main_18(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0016 +; +#line 599 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (0.0f , 4.0f , - 1.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , FALSE , FALSE , FALSE ); +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.15f); +Jump(STATE_CURRENT, 0x01fa0017, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa0017_Main_19(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0017 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa0018, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa0018_Main_20(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0018 +; +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (2.0f , 0.0f , - 3.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , TRUE , FALSE , FALSE ); +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x01fa0019, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa0019_Main_21(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0019 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa001a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa001a_Main_22(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa001a +; +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (- 1.0f , 2.0f , 0.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , FALSE , FALSE , FALSE ); +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.125f); +Jump(STATE_CURRENT, 0x01fa001b, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa001b_Main_23(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa001b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa001c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa001c_Main_24(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa001c +; +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (3.0f , 1.0f , 1.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , FALSE , FALSE , FALSE ); +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x01fa001d, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa001d_Main_25(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa001d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa001e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa001e_Main_26(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa001e +; +#line 607 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (3.0f , 2.0f , 2.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , FALSE , FALSE , FALSE ); +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +SetTimerAfter(0.125f); +Jump(STATE_CURRENT, 0x01fa001f, FALSE, EBegin());return TRUE;}BOOL CCannonBall::H0x01fa001f_Main_27(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa001f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fa0020, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonBall::H0x01fa0020_Main_28(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0020 +; +#line 609 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Explosion (FLOAT3D (3.0f , 2.0f , 2.0f) , STRETCH_4 , STRETCH_6 , STRETCH_10 , TRUE , TRUE , FALSE , FALSE );Jump(STATE_CURRENT,0x01fa0021, FALSE, EInternal());return TRUE;}BOOL CCannonBall::H0x01fa0021_Main_29(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0021 +Jump(STATE_CURRENT,0x01fa0022, FALSE, EInternal());return TRUE;} +BOOL CCannonBall::H0x01fa0022_Main_30(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fa0022 + +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Destroy (); +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Return(STATE_CURRENT,EVoid()); +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/CannonBall.es b/Sources/EntitiesMP/CannonBall.es new file mode 100644 index 0000000..408ce8f --- /dev/null +++ b/Sources/EntitiesMP/CannonBall.es @@ -0,0 +1,617 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +506 +%{ +#include "StdH.h" +#include "Models/Weapons/Cannon/Projectile/Cannonball.h" +#include "EntitiesMP/MovingBrush.h" +#include "EntitiesMP/DestroyableArchitecture.h" +%} + +uses "EntitiesMP/BasicEffects"; +uses "EntitiesMP/Light"; +uses "EntitiesMP/PlayerWeapons"; +uses "EntitiesMP/EnemyBase"; + +enum CannonBallType { + 0 CBT_IRON "", + 1 CBT_NUKE "", +}; + +// input parameter for launching the projectile +event ELaunchCannonBall { + CEntityPointer penLauncher, // who launched it + enum CannonBallType cbtType, // type of cannon ball + FLOAT fLaunchPower, // how fast will cannon be launched + FLOAT fSize, // the size of the cannonball +}; +event EForceExplode { +}; + +%{ + +// projectile solid +#define ECF_CANNON_BALL ( \ + ((ECBI_MODEL|ECBI_BRUSH|ECBI_PROJECTILE_SOLID|ECBI_CORPSE|ECBI_MODEL_HOLDER|ECBI_MODEL_HOLDER)<PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNONEXPLOSIONSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNONSHOCKWAVE); + + pdec->PrecacheModel(MODEL_BALL); + pdec->PrecacheTexture(TEXTURE_IRON_BALL); + pdec->PrecacheTexture(TEXTURE_NUKE_BALL); + pdec->PrecacheTexture(TEX_REFL_BWRIPLES01); + pdec->PrecacheTexture(TEX_SPEC_MEDIUM); + pdec->PrecacheSound(SOUND_BALL_BOUNCE); +} + +%} + + +class export CCannonBall : CMovableModelEntity { +name "Cannon ball"; +thumbnail ""; +features "ImplementsOnPrecache"; + +properties: + 1 CEntityPointer m_penLauncher, // who lanuched it + 2 FLOAT m_fLaunchPower = 0.0f, // how fast will cannon be launched + 3 FLOAT m_fCannonBallSize = 0.0f, // the size of the cannonball + 10 FLOAT m_fIgnoreTime = 0.0f, // time when laucher will be ignored + 11 FLOAT m_fStartTime = 0.0f, // start time when launched + + 12 INDEX m_iNextChannel = 0, // next channel to play sound on + + 13 BOOL m_bSelfExploded = FALSE, // if cannonball exploded because of time, not because of impact + + // sound channels for bouncing sound + 20 CSoundObject m_soBounce0, + 21 CSoundObject m_soBounce1, + 22 CSoundObject m_soBounce2, + 23 CSoundObject m_soBounce3, + 24 CSoundObject m_soBounce4, + + 30 enum CannonBallType m_cbtType = CBT_IRON, + 40 FLOAT m_tmInvisibility = 0.0f, // don't render before given time + 41 FLOAT m_tmExpandBox = 0.0f, // expand collision after a few seconds + 42 FLOAT m_tmForceExplode = 0.0f, // force explosion at given moment +/* +{ + CLightSource m_lsLightSource; +}*/ + +components: + 1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 2 class CLASS_LIGHT "Classes\\Light.ecl", + +// ********* PLAYER ROCKET ********* + 10 model MODEL_BALL "Models\\Weapons\\Cannon\\Projectile\\CannonBall.mdl", + 11 texture TEXTURE_NUKE_BALL "Models\\Weapons\\Cannon\\Projectile\\NukeBall.tex", + 13 texture TEXTURE_IRON_BALL "Models\\Weapons\\Cannon\\Projectile\\IronBall.tex", + 12 sound SOUND_BALL_BOUNCE "Models\\Weapons\\Cannon\\Sounds\\Bounce.wav", +200 texture TEX_REFL_BWRIPLES01 "Models\\ReflectionTextures\\BWRiples01.tex", +211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex", + +functions: + // premoving + void PreMoving(void) { + if (m_tmExpandBox>0) { + if (_pTimer->CurrentTick()>m_fStartTime+m_tmExpandBox) { + ChangeCollisionBoxIndexWhenPossible(1); + m_tmExpandBox = 0; + } + } + CMovableModelEntity::PreMoving(); + } + + void PostMoving(void) + { + CMovableModelEntity::PostMoving(); + if (en_vCurrentTranslationAbsolute.Length()<1.0f || // if very slow, allmost standing + _pTimer->CurrentTick()>=m_tmForceExplode || // if forced explosion + (GetCollisionBoxIndex()==0 && // if unable to change collision box for some time + (_pTimer->CurrentTick()>m_fStartTime+m_tmExpandBox+0.5f))) + { + SendEvent(EForceExplode()); + } + } + /* Read from stream. */ + void Read_t( CTStream *istr) // throw char * + { + CMovableModelEntity::Read_t(istr); + // setup light source +// SetupLightSource(); + } + + /* Get static light source information. */ +/* + CLightSource *GetLightSource(void) + { +// if (!IsPredictor()) { +// return &m_lsLightSource; +// } else { + return NULL; +// } + } +*/ + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + // if time now is inside invisibility time, don't render model + CModelObject *pmo = GetModelObject(); + if ( (pmo != NULL) && (_pTimer->GetLerpedCurrentTick() < (m_fStartTime+m_tmInvisibility) ) ) + { + // make it invisible + pmo->mo_colBlendColor = 0; + } + else + { + // make it visible + pmo->mo_colBlendColor = C_WHITE|CT_OPAQUE; + } + return CEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + } + +/* // Setup light source + void SetupLightSource(void) + { + // setup light source + CLightSource lsNew; + lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DARKLIGHT|LSF_DYNAMIC; + lsNew.ls_rHotSpot = 0.0f; + lsNew.ls_colColor = RGBToColor(128, 128, 128); + lsNew.ls_rFallOff = 5.0f; + lsNew.ls_plftLensFlare = NULL; + lsNew.ls_ubPolygonalMask = 0; + lsNew.ls_paoLightAnimation = NULL; + + m_lsLightSource.ls_penEntity = this; + m_lsLightSource.SetLightSource(lsNew); + } + */ + + // render particles + void RenderParticles(void) { + // no particles when not existing + if (GetRenderType()!=CEntity::RT_MODEL) { + return; + } + + FLOAT fSpeedRatio = Min( en_vCurrentTranslationAbsolute.Length()/140.0f, 1.0f); + INDEX ctFireParticles = INDEX( (Max( fSpeedRatio-0.5f, 0.0f)*2.0f)*128); + //CPrintF("fSpeedRatio=%g, ctFireParticles=%d\n", fSpeedRatio, ctFireParticles); + if( _pTimer->GetLerpedCurrentTick()-m_fStartTime>0.075) + { + Particles_BeastBigProjectileTrail( this, 2.0f, 1.0f, 0.75f, ctFireParticles); + } + } + +void Initialize(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_BOUNCING); + SetCollisionFlags(ECF_CANNON_BALL); + SetModel(MODEL_BALL); + if( m_cbtType == CBT_IRON) + { + SetModelMainTexture(TEXTURE_IRON_BALL); + } + else + { + SetModelMainTexture(TEXTURE_NUKE_BALL); + } + // stretch it + GetModelObject()->StretchModel(FLOAT3D(m_fCannonBallSize, m_fCannonBallSize, m_fCannonBallSize)); + ModelChangeNotify(); + + // reflection texture data + GetModelObject()->mo_toReflection.SetData(GetTextureDataForComponent(TEX_REFL_BWRIPLES01)); + // specular texture data + GetModelObject()->mo_toSpecular.SetData(GetTextureDataForComponent(TEX_SPEC_MEDIUM)); + // start moving + LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -m_fLaunchPower), (CMovableEntity*)(CEntity*)m_penLauncher); + en_fBounceDampNormal = 0.5f; + en_fBounceDampParallel = 0.75f; + en_fAcceleration = 0.0f; + en_fDeceleration = 5.0f; + en_fCollisionSpeedLimit = 40.0f; + en_fCollisionDamageFactor = 10.0f; + SetHealth(50000.0f); + GetModelObject()->PlayAnim(CANNONBALL_ANIM_FIRESLOW, 0); +}; + +FLOAT CalculateDamageToInflict(void) +{ + FLOAT fMaxDamage = IRON_DAMAGE_MAX; + if(m_cbtType == CBT_NUKE) + { + fMaxDamage = IRON_DAMAGE_MAX; + } + + // speed can range from + FLOAT fSpeedRatio = en_vCurrentTranslationAbsolute.Length()/140.0f; + // apply damage to range from 0 to damage max + FLOAT fApplyDamage = Clamp( fSpeedRatio*fMaxDamage, 0.0f, fMaxDamage); + return fApplyDamage; +} + +void Explosion(FLOAT3D vCenter, + const FLOAT3D &vStretchExplosion, + const FLOAT3D &vStretchShockwave, + const FLOAT3D &vStretchStain, + BOOL bHasExplosion, + BOOL bHasShockWave, + BOOL bHasStain, + BOOL bHasLight) +{ + ESpawnEffect ese; + FLOAT3D vOnPlane; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + // explosion + if( bHasExplosion) + { + ese.colMuliplier = C_WHITE|CT_OPAQUE; + if( bHasLight) + { + ese.betType = BET_CANNON; + } + else + { + ese.betType = BET_CANNON_NOLIGHT; + } + ese.vStretch = vStretchExplosion; + CPlacement3D plHandle = GetPlacement(); + plHandle.pl_PositionVector+=vCenter; + SpawnEffect(plHandle, ese); + // spawn sound event in range + if( IsDerivedFromClass( m_penLauncher, "Player")) { + SpawnRangeSound( m_penLauncher, this, SNDT_PLAYER, 100.0f); + } + } + // on plane + if (GetNearestPolygon(vOnPlane, vPlaneNormal, fDistanceToEdge)) { + if ((vOnPlane-GetPlacement().pl_PositionVector).Length() < 3.5f) { + if( bHasStain) + { + // wall stain + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_CANNONEXPLOSIONSTAIN; + ese.vNormal = FLOAT3D(vPlaneNormal); + ese.vStretch = vStretchShockwave; + SpawnEffect(CPlacement3D(vOnPlane, ANGLE3D(0, 0, 0)), ese); + } + if( bHasShockWave) + { + // shock wave horizontal + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_CANNONSHOCKWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + ese.vStretch = vStretchShockwave; + SpawnEffect(CPlacement3D(vOnPlane, ANGLE3D(0, 0, 0)), ese); + } + // shock wave vertical + /* + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_CANNONSHOCKWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + ese.vStretch = vStretchShockwave; + SpawnEffect(CPlacement3D(vOnPlane, ANGLE3D(0, 0.0f, 0)), ese); + */ + // second explosion on plane + /* + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_CANNON_PLANE; + ese.vNormal = FLOAT3D(vPlaneNormal); + ese.vStretch = vStretchExplosion; + SpawnEffect(CPlacement3D(vOnPlane+ese.vNormal/50.0f, ANGLE3D(0, 0, 0)), ese); + */ + } + } + + RangeDamage(); +}; + + + +/************************************************************ + * C O M M O N F U N C T I O N S * + ************************************************************/ + +// ball touch his valid target +BOOL BallTouchExplode(CEntityPointer penHit) +{ + FLOAT fApplyDamage = CalculateDamageToInflict(); + + // obtain touched entity health + FLOAT fHealth = 100; + BOOL bForceCannonballToExplode = FALSE; + + if (penHit->GetPhysicsFlags()&EPF_MOVABLE) { + fHealth = ((CMovableEntity&)*penHit).GetHealth(); + if( IsDerivedFromClass(penHit, "Enemy Base")) + { + bForceCannonballToExplode = ((CEnemyBase&)*penHit).ForcesCannonballToExplode(); + } + } else { + if (IsOfClass(penHit, "ModelHolder2") || IsOfClass(penHit, "ExotechLarvaBattery")) { + fHealth = ((CLiveEntity&)*penHit).GetHealth(); + } else { + return FALSE; + } + } + + if( IsOfClass(penHit, "ModelHolder2")) + { + bForceCannonballToExplode=TRUE; + } + + if (IsOfClass(penHit, "Player")) { + fHealth += ((CPlayer&)*penHit).m_fArmor * 2.0f; + } + // inflict direct damage to kill hitted entity + FLOAT3D vDirection = en_vCurrentTranslationAbsolute; + vDirection.Normalize(); +// CPrintF( "Applied damage %g\n", fApplyDamage); + const FLOAT fDamageMul = GetSeriousDamageMultiplier(m_penLauncher); + InflictDirectDamage(penHit, m_penLauncher, DMT_CANNONBALL, fApplyDamage*fDamageMul, + GetPlacement().pl_PositionVector, vDirection); + return(fApplyDamage <= fHealth || bForceCannonballToExplode); +}; + + +// infilict range damage by cannonball +void RangeDamage(void) +{ + const FLOAT fDamageMul = GetSeriousDamageMultiplier(m_penLauncher); + if(m_cbtType == CBT_IRON) { + InflictRangeDamage(m_penLauncher, DMT_CANNONBALL_EXPLOSION, IRON_RANGE_DAMAGE*fDamageMul, + GetPlacement().pl_PositionVector, IRON_RANGE_HOTSPOT, IRON_RANGE_FALLOFF); + } else { + // nuclear explosion ... + InflictRangeDamage(m_penLauncher, DMT_CANNONBALL_EXPLOSION, NUKE_RANGE_DAMAGE*fDamageMul, + GetPlacement().pl_PositionVector, NUKE_RANGE_HOTSPOT, NUKE_RANGE_FALLOFF); + } +}; + + +// spawn effect +void SpawnEffect(const CPlacement3D &plEffect, const ESpawnEffect &eSpawnEffect) { + CEntityPointer penEffect = CreateEntity(plEffect, CLASS_BASIC_EFFECT); + penEffect->Initialize(eSpawnEffect); +}; + + + +/************************************************************ + * S O U N D S * + ************************************************************/ +void BounceSound(FLOAT fSpeed) { + FLOAT fVolume = Clamp(fSpeed/6.0f, 0.0f, 1.0f); + if (fVolume<0.1f) { + return; + } + CSoundObject &so = (&m_soBounce0)[m_iNextChannel]; + m_iNextChannel = (m_iNextChannel+1)%5; + so.Set3DParameters(70.0f, 10.0f, fVolume, 1.0f); + PlaySound(so, SOUND_BALL_BOUNCE, SOF_3D); +}; + + + +/************************************************************ + * P R O C E D U R E S * + ************************************************************/ +procedures: + Bounce(EVoid) { + // if already inside some entity + CEntity *penObstacle; + if (CheckForCollisionNow(0, &penObstacle)) { + // explode now + return EEnd(); + } + + FLOAT fWaitTime = IRON_LIFE_TIME; + // if this is nuke ball + if(m_cbtType == CBT_NUKE) + { + fWaitTime = NUKE_LIFE_TIME; + } + // bounce loop + wait(fWaitTime) { + on (EBegin) : { resume; } + on (EPass epass) : { + BOOL bHit; + // ignore launcher within 1 second + bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime; + // ignore twister + bHit &= !IsOfClass(epass.penOther, "Twister"); + + if (bHit) + { + if (BallTouchExplode(epass.penOther)) { stop; } + } + resume; + } + on (ETouch etouch) : { + // explode if touched another cannon ball + if( IsOfClass(etouch.penOther, "Cannon ball")) + { + stop; + } + if( IsOfClass(etouch.penOther, "Moving Brush")) + { + CMovingBrush &br = (CMovingBrush &) *etouch.penOther; + if( br.m_fHealth>0) + { + FLOAT3D vDirection = en_vCurrentTranslationAbsolute; + vDirection.Normalize(); + InflictDirectDamage(etouch.penOther, m_penLauncher, DMT_CANNONBALL, CalculateDamageToInflict(), + GetPlacement().pl_PositionVector, vDirection); + m_bSelfExploded = FALSE; + stop; + } + } + if( IsOfClass(etouch.penOther, "DestroyableArchitecture")) + { + CDestroyableArchitecture &br = (CDestroyableArchitecture &) *etouch.penOther; + if( br.m_fHealth>0) + { + FLOAT3D vDirection = en_vCurrentTranslationAbsolute; + vDirection.Normalize(); + InflictDirectDamage(etouch.penOther, m_penLauncher, DMT_CANNONBALL, CalculateDamageToInflict(), + GetPlacement().pl_PositionVector, vDirection); + m_bSelfExploded = FALSE; + stop; + } + } + // clear time limit for launcher + //m_fIgnoreTime = 0.0f; + BounceSound(((FLOAT3D&)etouch.plCollision) % en_vCurrentTranslationAbsolute); + resume; + } + on (EForceExplode) : { stop; } + on (EDeath) : { stop; } + on (ETimer) : { stop; } + } + m_bSelfExploded = TRUE; + return EEnd(); + }; + + // --->>> MAIN + Main(ELaunchCannonBall eLaunch) { + // remember the initial parameters + ASSERT(eLaunch.penLauncher!=NULL); + m_penLauncher = eLaunch.penLauncher; + m_fLaunchPower = eLaunch.fLaunchPower; + m_cbtType = eLaunch.cbtType; + m_fCannonBallSize = eLaunch.fSize; + m_tmInvisibility = 0.05f; + m_bSelfExploded = FALSE; + m_tmExpandBox = 0.0001f; + // setup time for forced expolding + m_tmForceExplode=_pTimer->CurrentTick()+30.0f; + + // initialization + Initialize(); + + SendEvent(EReturn()); + wait() { + on (EBegin) : { resume;} + on (EReturn) : { stop;} + } + + // cast ray to check possible collision + FLOAT tmCastCoverPath = _pTimer->TickQuantum*1.5f; + CCastRay crRay(m_penLauncher, GetPlacement(), m_fLaunchPower*tmCastCoverPath); + crRay.cr_bHitTranslucentPortals = FALSE; + crRay.cr_fTestR = 0.75f/2.0f*m_fCannonBallSize; + crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX; + GetWorld()->CastRay(crRay); + + // can't hurt player time + m_fIgnoreTime = _pTimer->CurrentTick() + 0.1f; + + // bounce + m_fStartTime = _pTimer->CurrentTick(); + + if (crRay.cr_penHit!=NULL && crRay.cr_penHit->GetRenderType()==RT_MODEL) + { + if (BallTouchExplode(crRay.cr_penHit)) + { + m_tmForceExplode = _pTimer->CurrentTick()+tmCastCoverPath; + } + } + + autocall Bounce() EEnd; + + // dissapear + SwitchToEditorModel(); + // stop in place + ForceFullStop(); + + // sound event + ESound eSound; + eSound.EsndtSound = SNDT_EXPLOSION; + eSound.penTarget = m_penLauncher; + if (IsDerivedFromClass(this, "Player")) { + SendEventInRange(eSound, FLOATaabbox3D(GetPlacement().pl_PositionVector, SOUND_RANGE)); + } + + if(m_cbtType == CBT_IRON) + { + // Explosion( FLOAT3D(0.0f,0.0f,0.0f), STRETCH_3, STRETCH_3, STRETCH_3, TRUE, TRUE, TRUE, TRUE); + // autowait(0.15f); + Explosion( FLOAT3D(0.0f,0.0f,0.0f), STRETCH_3, STRETCH_3, STRETCH_4, TRUE, TRUE, TRUE, TRUE); + Explosion( FLOAT3D(1.0f,1.5f,1.5f), STRETCH_3, STRETCH_3, STRETCH_4, TRUE, FALSE, FALSE, FALSE); + Explosion( FLOAT3D(-2.0f,1.0f,-1.5f), STRETCH_3, STRETCH_3, STRETCH_4, TRUE, FALSE, FALSE, FALSE); + Explosion( FLOAT3D(-1.0f,0.5f,1.0f), STRETCH_4, STRETCH_4, STRETCH_4, TRUE, FALSE, FALSE, FALSE); + } + else if( m_cbtType == CBT_NUKE) + { + Explosion( FLOAT3D(0.0f,0.0f,0.0f), STRETCH_6, STRETCH_6, STRETCH_10, TRUE, TRUE, TRUE, TRUE); + autowait(0.15f); + Explosion( FLOAT3D(4.0f,5.0f,5.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE); + autowait(0.2f); + Explosion( FLOAT3D(-5.0f,3.0f,-4.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE); + autowait(0.15f); + Explosion( FLOAT3D(-3.0f,2.0f,3.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE); + autowait(0.15f); + Explosion( FLOAT3D(2.0f,1.0f,4.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, TRUE, FALSE, FALSE); + autowait(0.2f); + Explosion( FLOAT3D(-2.0f,5.0f,-4.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE); + autowait(0.18f); + Explosion( FLOAT3D(-3.0f,2.0f,2.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE); + autowait(0.25f); + Explosion( FLOAT3D(0.0f,4.0f,-1.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE); + autowait(0.15f); + Explosion( FLOAT3D(2.0f,0.0f,-3.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, TRUE, FALSE, FALSE); + autowait(0.25f); + Explosion( FLOAT3D(-1.0f,2.0f,0.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE); + autowait(0.125f); + Explosion( FLOAT3D(3.0f,1.0f,1.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE); + autowait(0.1f); + Explosion( FLOAT3D(3.0f,2.0f,2.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, FALSE, FALSE, FALSE); + autowait(0.125f); + Explosion( FLOAT3D(3.0f,2.0f,2.0f), STRETCH_4, STRETCH_6, STRETCH_10, TRUE, TRUE, FALSE, FALSE); + } + + // cease to exist + Destroy(); + + return; + } +}; diff --git a/Sources/EntitiesMP/CannonBall.h b/Sources/EntitiesMP/CannonBall.h new file mode 100644 index 0000000..d423238 --- /dev/null +++ b/Sources/EntitiesMP/CannonBall.h @@ -0,0 +1,147 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_CannonBall_INCLUDED +#define _EntitiesMP_CannonBall_INCLUDED 1 +#include +#include +#include +#include +extern DECL_DLL CEntityPropertyEnumType CannonBallType_enum; +enum CannonBallType { + CBT_IRON = 0, + CBT_NUKE = 1, +}; +DECL_DLL inline void ClearToDefault(CannonBallType &e) { e = (CannonBallType)0; } ; +#define EVENTCODE_ELaunchCannonBall 0x01fa0000 +class DECL_DLL ELaunchCannonBall : public CEntityEvent { +public: +ELaunchCannonBall(); +CEntityEvent *MakeCopy(void); +CEntityPointer penLauncher; +enum CannonBallType cbtType; +FLOAT fLaunchPower; +FLOAT fSize; +}; +DECL_DLL inline void ClearToDefault(ELaunchCannonBall &e) { e = ELaunchCannonBall(); } ; +#define EVENTCODE_EForceExplode 0x01fa0001 +class DECL_DLL EForceExplode : public CEntityEvent { +public: +EForceExplode(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EForceExplode &e) { e = EForceExplode(); } ; +extern "C" DECL_DLL CDLLEntityClass CCannonBall_DLLClass; +class DECL_DLL CCannonBall : public CMovableModelEntity { +public: + virtual void SetDefaultProperties(void); + CEntityPointer m_penLauncher; + FLOAT m_fLaunchPower; + FLOAT m_fCannonBallSize; + FLOAT m_fIgnoreTime; + FLOAT m_fStartTime; + INDEX m_iNextChannel; + BOOL m_bSelfExploded; + CSoundObject m_soBounce0; + CSoundObject m_soBounce1; + CSoundObject m_soBounce2; + CSoundObject m_soBounce3; + CSoundObject m_soBounce4; + enum CannonBallType m_cbtType; + FLOAT m_tmInvisibility; + FLOAT m_tmExpandBox; + FLOAT m_tmForceExplode; + +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void PreMoving(void); + +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void PostMoving(void); + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void Read_t(CTStream * istr); + +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void RenderParticles(void); + +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void Initialize(void); + +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +FLOAT CalculateDamageToInflict(void); + +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void Explosion(FLOAT3D vCenter, +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +const FLOAT3D & vStretchExplosion, +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +const FLOAT3D & vStretchShockwave, +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +const FLOAT3D & vStretchStain, +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL bHasExplosion, +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL bHasShockWave, +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL bHasStain, +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL bHasLight); + +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +BOOL BallTouchExplode(CEntityPointer penHit); + +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void RangeDamage(void); + +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void SpawnEffect(const CPlacement3D & plEffect,const ESpawnEffect & eSpawnEffect); + +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +void BounceSound(FLOAT fSpeed); +#define STATE_CCannonBall_Bounce 0x01fa0002 + BOOL +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Bounce(const CEntityEvent &__eeInput); + BOOL H0x01fa0003_Bounce_01(const CEntityEvent &__eeInput); + BOOL H0x01fa0004_Bounce_02(const CEntityEvent &__eeInput); +#define STATE_CCannonBall_Main 1 + BOOL +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01fa0005_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01fa0006_Main_02(const CEntityEvent &__eeInput); + BOOL H0x01fa0007_Main_03(const CEntityEvent &__eeInput); + BOOL H0x01fa0008_Main_04(const CEntityEvent &__eeInput); + BOOL H0x01fa0009_Main_05(const CEntityEvent &__eeInput); + BOOL H0x01fa000a_Main_06(const CEntityEvent &__eeInput); + BOOL H0x01fa000b_Main_07(const CEntityEvent &__eeInput); + BOOL H0x01fa000c_Main_08(const CEntityEvent &__eeInput); + BOOL H0x01fa000d_Main_09(const CEntityEvent &__eeInput); + BOOL H0x01fa000e_Main_10(const CEntityEvent &__eeInput); + BOOL H0x01fa000f_Main_11(const CEntityEvent &__eeInput); + BOOL H0x01fa0010_Main_12(const CEntityEvent &__eeInput); + BOOL H0x01fa0011_Main_13(const CEntityEvent &__eeInput); + BOOL H0x01fa0012_Main_14(const CEntityEvent &__eeInput); + BOOL H0x01fa0013_Main_15(const CEntityEvent &__eeInput); + BOOL H0x01fa0014_Main_16(const CEntityEvent &__eeInput); + BOOL H0x01fa0015_Main_17(const CEntityEvent &__eeInput); + BOOL H0x01fa0016_Main_18(const CEntityEvent &__eeInput); + BOOL H0x01fa0017_Main_19(const CEntityEvent &__eeInput); + BOOL H0x01fa0018_Main_20(const CEntityEvent &__eeInput); + BOOL H0x01fa0019_Main_21(const CEntityEvent &__eeInput); + BOOL H0x01fa001a_Main_22(const CEntityEvent &__eeInput); + BOOL H0x01fa001b_Main_23(const CEntityEvent &__eeInput); + BOOL H0x01fa001c_Main_24(const CEntityEvent &__eeInput); + BOOL H0x01fa001d_Main_25(const CEntityEvent &__eeInput); + BOOL H0x01fa001e_Main_26(const CEntityEvent &__eeInput); + BOOL H0x01fa001f_Main_27(const CEntityEvent &__eeInput); + BOOL H0x01fa0020_Main_28(const CEntityEvent &__eeInput); + BOOL H0x01fa0021_Main_29(const CEntityEvent &__eeInput); + BOOL H0x01fa0022_Main_30(const CEntityEvent &__eeInput); + BOOL H0x01fa0023_Main_31(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_CannonBall_INCLUDED diff --git a/Sources/EntitiesMP/CannonBall_tables.h b/Sources/EntitiesMP/CannonBall_tables.h new file mode 100644 index 0000000..1f0bb70 --- /dev/null +++ b/Sources/EntitiesMP/CannonBall_tables.h @@ -0,0 +1,104 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(CannonBallType) + EP_ENUMVALUE(CBT_IRON, ""), + EP_ENUMVALUE(CBT_NUKE, ""), +EP_ENUMEND(CannonBallType); + +#define ENTITYCLASS CCannonBall + +CEntityProperty CCannonBall_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001fa<<8)+1, offsetof(CCannonBall, m_penLauncher), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fa<<8)+2, offsetof(CCannonBall, m_fLaunchPower), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fa<<8)+3, offsetof(CCannonBall, m_fCannonBallSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fa<<8)+10, offsetof(CCannonBall, m_fIgnoreTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fa<<8)+11, offsetof(CCannonBall, m_fStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000001fa<<8)+12, offsetof(CCannonBall, m_iNextChannel), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001fa<<8)+13, offsetof(CCannonBall, m_bSelfExploded), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000001fa<<8)+20, offsetof(CCannonBall, m_soBounce0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000001fa<<8)+21, offsetof(CCannonBall, m_soBounce1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000001fa<<8)+22, offsetof(CCannonBall, m_soBounce2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000001fa<<8)+23, offsetof(CCannonBall, m_soBounce3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000001fa<<8)+24, offsetof(CCannonBall, m_soBounce4), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &CannonBallType_enum, (0x000001fa<<8)+30, offsetof(CCannonBall, m_cbtType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fa<<8)+40, offsetof(CCannonBall, m_tmInvisibility), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fa<<8)+41, offsetof(CCannonBall, m_tmExpandBox), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fa<<8)+42, offsetof(CCannonBall, m_tmForceExplode), "", 0, 0, 0), +}; +#define CCannonBall_propertiesct ARRAYCOUNT(CCannonBall_properties) + +CEntityComponent CCannonBall_components[] = { +#define CLASS_BASIC_EFFECT ((0x000001fa<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_LIGHT ((0x000001fa<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_LIGHT, "EFNM" "Classes\\Light.ecl"), +#define MODEL_BALL ((0x000001fa<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_BALL, "EFNM" "Models\\Weapons\\Cannon\\Projectile\\CannonBall.mdl"), +#define TEXTURE_NUKE_BALL ((0x000001fa<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_NUKE_BALL, "EFNM" "Models\\Weapons\\Cannon\\Projectile\\NukeBall.tex"), +#define TEXTURE_IRON_BALL ((0x000001fa<<8)+13) + CEntityComponent(ECT_TEXTURE, TEXTURE_IRON_BALL, "EFNM" "Models\\Weapons\\Cannon\\Projectile\\IronBall.tex"), +#define SOUND_BALL_BOUNCE ((0x000001fa<<8)+12) + CEntityComponent(ECT_SOUND, SOUND_BALL_BOUNCE, "EFNM" "Models\\Weapons\\Cannon\\Sounds\\Bounce.wav"), +#define TEX_REFL_BWRIPLES01 ((0x000001fa<<8)+200) + CEntityComponent(ECT_TEXTURE, TEX_REFL_BWRIPLES01, "EFNM" "Models\\ReflectionTextures\\BWRiples01.tex"), +#define TEX_SPEC_MEDIUM ((0x000001fa<<8)+211) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_MEDIUM, "EFNM" "Models\\SpecularTextures\\Medium.tex"), +}; +#define CCannonBall_componentsct ARRAYCOUNT(CCannonBall_components) + +CEventHandlerEntry CCannonBall_handlers[] = { + {0x01fa0002, -1, CEntity::pEventHandler(&CCannonBall:: +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Bounce),DEBUGSTRING("CCannonBall::Bounce")}, + {0x01fa0003, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0003_Bounce_01), DEBUGSTRING("CCannonBall::H0x01fa0003_Bounce_01")}, + {0x01fa0004, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0004_Bounce_02), DEBUGSTRING("CCannonBall::H0x01fa0004_Bounce_02")}, + {1, -1, CEntity::pEventHandler(&CCannonBall:: +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/CannonBall.es" +Main),DEBUGSTRING("CCannonBall::Main")}, + {0x01fa0005, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0005_Main_01), DEBUGSTRING("CCannonBall::H0x01fa0005_Main_01")}, + {0x01fa0006, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0006_Main_02), DEBUGSTRING("CCannonBall::H0x01fa0006_Main_02")}, + {0x01fa0007, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0007_Main_03), DEBUGSTRING("CCannonBall::H0x01fa0007_Main_03")}, + {0x01fa0008, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0008_Main_04), DEBUGSTRING("CCannonBall::H0x01fa0008_Main_04")}, + {0x01fa0009, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0009_Main_05), DEBUGSTRING("CCannonBall::H0x01fa0009_Main_05")}, + {0x01fa000a, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa000a_Main_06), DEBUGSTRING("CCannonBall::H0x01fa000a_Main_06")}, + {0x01fa000b, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa000b_Main_07), DEBUGSTRING("CCannonBall::H0x01fa000b_Main_07")}, + {0x01fa000c, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa000c_Main_08), DEBUGSTRING("CCannonBall::H0x01fa000c_Main_08")}, + {0x01fa000d, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa000d_Main_09), DEBUGSTRING("CCannonBall::H0x01fa000d_Main_09")}, + {0x01fa000e, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa000e_Main_10), DEBUGSTRING("CCannonBall::H0x01fa000e_Main_10")}, + {0x01fa000f, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa000f_Main_11), DEBUGSTRING("CCannonBall::H0x01fa000f_Main_11")}, + {0x01fa0010, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0010_Main_12), DEBUGSTRING("CCannonBall::H0x01fa0010_Main_12")}, + {0x01fa0011, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0011_Main_13), DEBUGSTRING("CCannonBall::H0x01fa0011_Main_13")}, + {0x01fa0012, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0012_Main_14), DEBUGSTRING("CCannonBall::H0x01fa0012_Main_14")}, + {0x01fa0013, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0013_Main_15), DEBUGSTRING("CCannonBall::H0x01fa0013_Main_15")}, + {0x01fa0014, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0014_Main_16), DEBUGSTRING("CCannonBall::H0x01fa0014_Main_16")}, + {0x01fa0015, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0015_Main_17), DEBUGSTRING("CCannonBall::H0x01fa0015_Main_17")}, + {0x01fa0016, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0016_Main_18), DEBUGSTRING("CCannonBall::H0x01fa0016_Main_18")}, + {0x01fa0017, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0017_Main_19), DEBUGSTRING("CCannonBall::H0x01fa0017_Main_19")}, + {0x01fa0018, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0018_Main_20), DEBUGSTRING("CCannonBall::H0x01fa0018_Main_20")}, + {0x01fa0019, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0019_Main_21), DEBUGSTRING("CCannonBall::H0x01fa0019_Main_21")}, + {0x01fa001a, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa001a_Main_22), DEBUGSTRING("CCannonBall::H0x01fa001a_Main_22")}, + {0x01fa001b, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa001b_Main_23), DEBUGSTRING("CCannonBall::H0x01fa001b_Main_23")}, + {0x01fa001c, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa001c_Main_24), DEBUGSTRING("CCannonBall::H0x01fa001c_Main_24")}, + {0x01fa001d, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa001d_Main_25), DEBUGSTRING("CCannonBall::H0x01fa001d_Main_25")}, + {0x01fa001e, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa001e_Main_26), DEBUGSTRING("CCannonBall::H0x01fa001e_Main_26")}, + {0x01fa001f, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa001f_Main_27), DEBUGSTRING("CCannonBall::H0x01fa001f_Main_27")}, + {0x01fa0020, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0020_Main_28), DEBUGSTRING("CCannonBall::H0x01fa0020_Main_28")}, + {0x01fa0021, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0021_Main_29), DEBUGSTRING("CCannonBall::H0x01fa0021_Main_29")}, + {0x01fa0022, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0022_Main_30), DEBUGSTRING("CCannonBall::H0x01fa0022_Main_30")}, + {0x01fa0023, -1, CEntity::pEventHandler(&CCannonBall::H0x01fa0023_Main_31), DEBUGSTRING("CCannonBall::H0x01fa0023_Main_31")}, +}; +#define CCannonBall_handlersct ARRAYCOUNT(CCannonBall_handlers) + +CEntity *CCannonBall_New(void) { return new CCannonBall; }; +void CCannonBall_OnInitClass(void) {}; +void CCannonBall_OnEndClass(void) {}; +void CCannonBall_OnPrecache(CDLLEntityClass *pdec, INDEX iUser); +void CCannonBall_OnWorldEnd(CWorld *pwo) {}; +void CCannonBall_OnWorldInit(CWorld *pwo) {}; +void CCannonBall_OnWorldTick(CWorld *pwo) {}; +void CCannonBall_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CCannonBall, CMovableModelEntity, "Cannon ball", "", 0x000001fa); +DECLARE_CTFILENAME(_fnmCCannonBall_tbn, ""); diff --git a/Sources/EntitiesMP/CannonRotating.cpp b/Sources/EntitiesMP/CannonRotating.cpp new file mode 100644 index 0000000..793aeb3 --- /dev/null +++ b/Sources/EntitiesMP/CannonRotating.cpp @@ -0,0 +1,848 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/CannonRotating/Turret.h" +#include "ModelsMP/Enemies/CannonRotating/RotatingMechanism.h" + +#include +#include +#line 16 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" + +#define CANNONR_SIZE 2.0f + +// info structure +static EntityInfo eiCannonRotating = { + EIBT_WOOD, 10000.0f, + 0.0f, 1.5f*CANNONR_SIZE, 0.0f, // source (eyes) + 0.0f, 0.5f*CANNONR_SIZE, 0.0f, // target (body) +}; + +#define FIRING_POSITION_MUZZLE FLOAT3D(0.0f, 0.0f, -1.0f) +#define MUZZLE_ROTATION_SPEED 45.0f //deg/sec + + +void CCannonRotating::SetDefaultProperties(void) { + m_fHealth = 100.0f; + m_fFiringRangeClose = 50.0f; + m_fFiringRangeFar = 150.0f; + m_fWaitAfterFire = 3.0f; + m_fSize = CANNONR_SIZE ; + m_fMaxPitch = 20.0f; + m_fViewAngle = 2.5f; + m_fScanAngle = 60.0f; + m_fRotationSpeed = 20.0f; + m_bActive = TRUE ; + m_fRotSpeedMuzzle = ANGLE3D(0.0f , 0.0f , 0.0f); + m_fRotSpeedRotator = ANGLE3D(0.0f , 0.0f , 0.0f); + m_fDistanceToPlayer = 0.0f; + m_fDesiredMuzzlePitch = 0.0f; + m_iMuzzleDir = 1.0f; + m_vFiringPos = FLOAT3D(0.0f , 0.0f , 0.0f); + m_vTarget = FLOAT3D(0.0f , 0.0f , 0.0f); + m_tmLastFireTime = -1000.0f; + m_aBeginMuzzleRotation = ANGLE3D(0.0f , 0.0f , 0.0f); + m_aEndMuzzleRotation = ANGLE3D(0.0f , 0.0f , 0.0f); + m_aBeginRotatorRotation = ANGLE3D(0.0f , 0.0f , 0.0f); + m_aEndRotatorRotation = ANGLE3D(0.0f , 0.0f , 0.0f); + CEnemyBase::SetDefaultProperties(); +} + CTString CCannonRotating::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +{ +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CTString str ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +str . PrintF (TRANS ("A Cannon killed %s") , strPlayerName ); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return str ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void * CCannonRotating::GetEntityInfo(void) { +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return & eiCannonRotating ; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + const CTFileName & CCannonRotating::GetComputerMessageName(void)const { +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +static DECLARE_CTFILENAME (fnmCannon , "DataMP\\Messages\\Enemies\\CannonRotating.txt"); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return fnmCannon ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void CCannonRotating::Precache(void) { +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CEnemyBase :: Precache (); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +PrecacheModel (MODEL_DEBRIS_MUZZLE ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +PrecacheModel (MODEL_DEBRIS_ROTATOR ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +PrecacheModel (MODEL_DEBRIS_BASE ); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +PrecacheModel (MODEL_BALL ); +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +PrecacheTexture (TEXTURE_BALL ); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +PrecacheSound (SOUND_FIRE ); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +PrecacheClass (CLASS_CANNONBALL ); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void CCannonRotating::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +{ +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(dmtType == DMT_BULLET && fDamageAmmount > 100.0f) +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +{ +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +fDamageAmmount *= 0.5f; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +vHitPoint , vDirection ); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +INDEX CCannonRotating::AnimForDamage(FLOAT fDamage) { +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return 0; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +INDEX CCannonRotating::AnimForDeath(void) { +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return 0; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +BOOL CCannonRotating::IsVisible(CEntity * penEntity) +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +{ +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +ASSERT (penEntity != NULL ); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vSource , vTarget ; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +GetPositionCastRay (this , penEntity , vSource , vTarget ); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CCastRay crRay (this , vSource , vTarget ); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +crRay . cr_ttHitModels = CCastRay :: TT_NONE ; +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +en_pwoWorld -> CastRay (crRay ); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return (crRay . cr_penHit == NULL ); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +BOOL CCannonRotating::IsInTheLineOfFire(CEntity * penEntity,FLOAT fAngle) +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +{ +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +ASSERT (penEntity != NULL ); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT fCosAngle ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vHeading ; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vToPlayer ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vSide = FLOAT3D (1.0f , 0.0f , 0.0f) * GetRotationMatrix (); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vFront = FLOAT3D (0.0f , 0.0f , - 1.0f) * GetRotationMatrix (); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOATmatrix3D m ; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +MakeRotationMatrixFast (m , m_aBeginRotatorRotation ); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +vSide = vSide * m ; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +vFront = vFront * m ; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +vToPlayer = penEntity -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +vToPlayer . Normalize (); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +fCosAngle = vToPlayer % vSide ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(Abs (fCosAngle ) < CosFast (90.0f - fAngle )){ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if((vToPlayer % vFront ) > 0.0f){ +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return TRUE ; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return FALSE ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CPlayer * CCannonRotating::AcquireTarget() { +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +INDEX ctMaxPlayers = GetMaxPlayers (); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CEntity * penPlayer ; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +for(INDEX i = 0;i < ctMaxPlayers ;i ++){ +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +penPlayer = GetPlayerEntity (i ); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(penPlayer != NULL && DistanceTo (this , penPlayer ) < m_fFiringRangeFar ){ +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(IsInTheLineOfFire (penPlayer , m_fViewAngle )){ +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(IsVisible (penPlayer )){ +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return (CPlayer *) penPlayer ; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return NULL ; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void CCannonRotating::CannonBlowUp(void) +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +{ +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vNormalizedDamage = m_vDamage - m_vDamage * (m_fBlowUpAmount / m_vDamage . Length ()); +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +vNormalizedDamage /= Sqrt (vNormalizedDamage . Length ()); +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +vNormalizedDamage *= 0.75f; +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +vNormalizedDamage += FLOAT3D (0.0f , 15.0f + FRnd () * 10.0f , 0.0f); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute - en_vGravityDir * (en_vGravityDir % en_vCurrentTranslationAbsolute ); +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Debris_Begin (EIBT_WOOD , DPT_NONE , BET_NONE , 1.0f , vNormalizedDamage , vBodySpeed , 5.0f , 2.0f); +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Debris_Spawn (this , this , MODEL_DEBRIS_MUZZLE , TEXTURE_CANNON , 0 , 0 , 0 , 0 , m_fSize , +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Debris_Spawn (this , this , MODEL_DEBRIS_ROTATOR , TEXTURE_ROTATOR , 0 , 0 , 0 , 0 , m_fSize , +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Debris_Spawn (this , this , MODEL_DEBRIS_ROTATOR , TEXTURE_ROTATOR , 0 , 0 , 0 , 0 , m_fSize , +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Debris_Spawn (this , this , MODEL_DEBRIS_BASE , TEXTURE_TURRET , 0 , 0 , 0 , 0 , m_fSize , +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Debris_Spawn (this , this , MODEL_BALL , TEXTURE_BALL , 0 , 0 , 0 , 0 , m_fSize / 2.0f , +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Debris_Spawn (this , this , MODEL_BALL , TEXTURE_BALL , 0 , 0 , 0 , 0 , m_fSize / 2.0f , +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CPlacement3D plExplosion = GetPlacement (); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CEntityPointer penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +ESpawnEffect eSpawnEffect ; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eSpawnEffect . betType = BET_CANNON ; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT fSize = m_fBlowUpSize * 1.0f; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eSpawnEffect . vStretch = FLOAT3D (fSize , fSize , fSize ); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +plExplosion = GetPlacement (); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eSpawnEffect . betType = BET_CANNONSHOCKWAVE ; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +fSize = m_fBlowUpSize * 1.0f; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eSpawnEffect . vStretch = FLOAT3D (fSize , fSize , fSize ); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SwitchToEditorModel (); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void CCannonRotating::PreMoving() { +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +UpdateAttachmentRotations (); +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CEnemyBase :: PreMoving (); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void CCannonRotating::PostMoving() { +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CEnemyBase :: PostMoving (); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetFlags (GetFlags () & ~ ENF_INRENDERING ); +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +BOOL CCannonRotating::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) { +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CAttachmentModelObject & amo0 = * GetModelObject () -> GetAttachmentModel (TURRET_ATTACHMENT_ROTATORHEADING ); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +amo0 . amo_plRelative . pl_OrientationAngle = Lerp (m_aBeginRotatorRotation , m_aEndRotatorRotation , _pTimer -> GetLerpFactor ()); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CAttachmentModelObject & amo1 = * amo0 . amo_moModelObject . GetAttachmentModel (ROTATINGMECHANISM_ATTACHMENT_CANNON ); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +amo1 . amo_plRelative . pl_OrientationAngle = Lerp (m_aBeginMuzzleRotation , m_aEndMuzzleRotation , _pTimer -> GetLerpFactor ()); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return CEnemyBase :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void CCannonRotating::UpdateAttachmentRotations(void) +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +{ +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_aBeginRotatorRotation = m_aEndRotatorRotation ; +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_aEndRotatorRotation += m_fRotSpeedRotator * _pTimer -> TickQuantum ; +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_aBeginMuzzleRotation = m_aEndMuzzleRotation ; +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_aEndMuzzleRotation += m_fRotSpeedMuzzle * _pTimer -> TickQuantum ; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} + +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void CCannonRotating::UpdateFiringPos() { +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOATmatrix3D m ; +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_vFiringPos = FIRING_POSITION_MUZZLE * m_fSize ; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +MakeRotationMatrixFast (m , m_aBeginRotatorRotation ); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_vFiringPos = m_vFiringPos * m ; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +MakeRotationMatrixFast (m , m_aBeginMuzzleRotation ); +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_vFiringPos = m_vFiringPos * m ; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CAttachmentModelObject & amo0 = * GetModelObject () -> GetAttachmentModel (TURRET_ATTACHMENT_ROTATORHEADING ); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CAttachmentModelObject & amo1 = * amo0 . amo_moModelObject . GetAttachmentModel (ROTATINGMECHANISM_ATTACHMENT_CANNON ); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_vFiringPos += amo0 . amo_plRelative . pl_PositionVector + amo1 . amo_plRelative . pl_PositionVector ; +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +BOOL CCannonRotating:: +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +MainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonRotating_MainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonRotating::MainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01590001, FALSE, EBegin());return TRUE;}BOOL CCannonRotating::H0x01590001_MainLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Call(STATE_CURRENT, STATE_CCannonRotating_Scan, TRUE, EVoid());return TRUE; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return TRUE; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Jump(STATE_CURRENT, STATE_CCannonRotating_Inactive, TRUE, EVoid());return TRUE; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Jump(STATE_CURRENT, STATE_CCannonRotating_Die, TRUE, eDeath );return TRUE; +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}return TRUE;}BOOL CCannonRotating::H0x01590002_MainLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590002 +; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Return(STATE_CURRENT,EVoid()); +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCannonRotating:: +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Scan(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonRotating_Scan + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonRotating::Scan expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Jump(STATE_CURRENT,0x0159000e, FALSE, EInternal());return TRUE;}BOOL CCannonRotating::H0x0159000e_Scan_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000e +if(!(TRUE )){ Jump(STATE_CURRENT,0x0159000f, FALSE, EInternal());return TRUE;} +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetTimerAfter(0.20f); +Jump(STATE_CURRENT, 0x01590004, FALSE, EBegin());return TRUE;}BOOL CCannonRotating::H0x01590004_Scan_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01590005, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonRotating::H0x01590005_Scan_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590005 +; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +BOOL bPause = FALSE ; +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(m_aBeginRotatorRotation (1) > (m_fScanAngle / 2.0f)){ +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fRotSpeedRotator = FLOAT3D (- m_fRotationSpeed , 0.0f , 0.0f); +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(m_iMuzzleDir != - 1.0f){ +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_iMuzzleDir = - 1.0f; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +bPause = TRUE ; +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}else if(m_aBeginRotatorRotation (1) < (- m_fScanAngle / 2.0f)){ +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fRotSpeedRotator = FLOAT3D (m_fRotationSpeed , 0.0f , 0.0f); +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(m_iMuzzleDir != 1.0f){ +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_iMuzzleDir = 1.0f; +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +bPause = TRUE ; +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}else if(TRUE ){ +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fRotSpeedRotator = FLOAT3D (m_iMuzzleDir * m_fRotationSpeed , 0.0f , 0.0f); +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(!(bPause )){ Jump(STATE_CURRENT,0x01590008, FALSE, EInternal());return TRUE;} +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fRotSpeedRotator = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x01590006, FALSE, EBegin());return TRUE;}BOOL CCannonRotating::H0x01590006_Scan_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01590007, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonRotating::H0x01590007_Scan_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590007 +;Jump(STATE_CURRENT,0x01590008, FALSE, EInternal());return TRUE;}BOOL CCannonRotating::H0x01590008_Scan_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590008 + +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CPlayer * pTarget = AcquireTarget (); +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(!(pTarget )){ Jump(STATE_CURRENT,0x0159000d, FALSE, EInternal());return TRUE;} +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(!((pTarget -> GetFlags () & ENF_ALIVE ) && ! (pTarget -> GetFlags () & ENF_DELETED ))){ Jump(STATE_CURRENT,0x0159000c, FALSE, EInternal());return TRUE;} +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fRotSpeedRotator = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_penEnemy = pTarget ; +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fDistanceToPlayer = DistanceTo (this , pTarget ); +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(!(m_tmLastFireTime + m_fWaitAfterFire < _pTimer -> CurrentTick ())){ Jump(STATE_CURRENT,0x0159000b, FALSE, EInternal());return TRUE;} +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +STATE_CCannonRotating_FireCannon, TRUE; +Jump(STATE_CURRENT, 0x01590009, FALSE, EBegin());return TRUE;}BOOL CCannonRotating::H0x01590009_Scan_06(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CCannonRotating_FireCannon, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0159000a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CCannonRotating::H0x0159000a_Scan_07(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000a +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x0159000b, FALSE, EInternal());return TRUE;}BOOL CCannonRotating::H0x0159000b_Scan_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000b +Jump(STATE_CURRENT,0x0159000c, FALSE, EInternal());return TRUE;}BOOL CCannonRotating::H0x0159000c_Scan_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000c +Jump(STATE_CURRENT,0x0159000d, FALSE, EInternal());return TRUE;}BOOL CCannonRotating::H0x0159000d_Scan_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000d +Jump(STATE_CURRENT,0x0159000e, FALSE, EInternal());return TRUE; +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}BOOL CCannonRotating::H0x0159000f_Scan_12(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000f + ASSERT(FALSE); return TRUE;};BOOL CCannonRotating:: +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Die(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonRotating_Die + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDeath, "CCannonRotating::Die expects 'EDeath' as input!"); const EDeath &eDeath = (const EDeath &)__eeInput; +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetFlags (GetFlags () & ~ ENF_ALIVE ); +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CEntityPointer penKiller = eDeath . eLastDamage . penInflictor ; +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(penKiller == NULL || ! IsOfClass (penKiller , "Player")){ +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +penKiller = m_penEnemy ; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(penKiller == NULL || ! IsOfClass (penKiller , "Player")){ +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +penKiller = FixupCausedToPlayer (this , penKiller , FALSE ); +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(penKiller != NULL ){ +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +EReceiveScore eScore ; +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eScore . iPoints = m_iScore ; +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +penKiller -> SendEvent (eScore ); +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(CountAsKill ()) +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +{ +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +penKiller -> SendEvent (EKilledEnemy ()); +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +EComputerMessage eMsg ; +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eMsg . fnmMessage = GetComputerMessageName (); +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(eMsg . fnmMessage != ""){ +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +penKiller -> SendEvent (eMsg ); +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SendToTarget (m_penDeathTarget , m_eetDeathType , penKiller ); +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(m_penSpawnerTarget ){ +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SendToTarget (m_penSpawnerTarget , EET_TRIGGER , this ); +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CannonBlowUp (); +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Destroy (); +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Return(STATE_CURRENT,EVoid()); +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCannonRotating:: +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +RotateMuzzle(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonRotating_RotateMuzzle + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonRotating::RotateMuzzle expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT fDeltaP = m_fDesiredMuzzlePitch - m_aBeginMuzzleRotation (2); +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(Abs (fDeltaP ) < 5.0f){Return(STATE_CURRENT,EReturn ());return TRUE;} +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fRotSpeedMuzzle = ANGLE3D (0.0f , MUZZLE_ROTATION_SPEED * Sgn (fDeltaP ) , 0.0f); +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetTimerAfter(Abs (fDeltaP / MUZZLE_ROTATION_SPEED )); +Jump(STATE_CURRENT, 0x01590012, FALSE, EBegin());return TRUE;}BOOL CCannonRotating::H0x01590012_RotateMuzzle_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590012 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01590013, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonRotating::H0x01590013_RotateMuzzle_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590013 +; +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fRotSpeedMuzzle = ANGLE3D (0.0f , 0.0f , 0.0f); +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Return(STATE_CURRENT,EReturn ()); +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCannonRotating:: +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FireCannon(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonRotating_FireCannon + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonRotating::FireCannon expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +UpdateFiringPos (); +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vToTarget = m_penEnemy -> GetPlacement () . pl_PositionVector - +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +GetPlacement () . pl_PositionVector + m_vFiringPos ; +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +vToTarget . Normalize (); +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vCannonFront = FLOAT3D (0.0f , 0.0f , - 1.0f) * GetRotationMatrix (); +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOATmatrix3D m ; +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +MakeRotationMatrixFast (m , m_aBeginRotatorRotation ); +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +vCannonFront = vCannonFront * m ; +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +ANGLE aToPlayer = ACos (vToTarget % vCannonFront ); +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT fPitch = aToPlayer + 5.0f; +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vCannonUp = FLOAT3D (0.0 , 1.0f , 0.0f) * GetRotationMatrix (); +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(m_fDistanceToPlayer > m_fFiringRangeFar ){ +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Return(STATE_CURRENT,EReturn ()); +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return TRUE; +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}else if(vToTarget % vCannonUp < 0.0f){ +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +fPitch = 5.0f; +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}else if(m_fDistanceToPlayer > m_fFiringRangeClose ){ +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(aToPlayer < m_fMaxPitch ){ +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +fPitch = aToPlayer + m_fMaxPitch * (m_fDistanceToPlayer - m_fFiringRangeClose ) / (m_fFiringRangeFar - m_fFiringRangeClose ); +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}else if(TRUE ){ +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +fPitch = aToPlayer + 10.0f + m_fMaxPitch * (m_fDistanceToPlayer - m_fFiringRangeClose ) / (m_fFiringRangeFar - m_fFiringRangeClose ); +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +fPitch = Clamp (fPitch , 1.0f , 60.0f); +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +} +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_vTarget = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fDesiredMuzzlePitch = fPitch ; +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +STATE_CCannonRotating_RotateMuzzle, TRUE; +Jump(STATE_CURRENT, 0x01590015, FALSE, EBegin());return TRUE;}BOOL CCannonRotating::H0x01590015_FireCannon_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CCannonRotating_RotateMuzzle, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01590016, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CCannonRotating::H0x01590016_FireCannon_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590016 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vShooting = GetPlacement () . pl_PositionVector + m_vFiringPos ; +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vSpeedDest = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT fLaunchSpeed ; +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT fRelativeHdg ; +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CalculateAngularLaunchParams (vShooting , peiTarget -> vTargetCenter [ 1 ] - 6.0f / 3.0f , m_vTarget , +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +vSpeedDest , m_fDesiredMuzzlePitch , fLaunchSpeed , fRelativeHdg ); +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT3D vShootTarget ; +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +GetEntityInfoPosition (m_penEnemy , peiTarget -> vTargetCenter , vShootTarget ); +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CPlacement3D pl ; +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +PrepareFreeFlyingProjectile (pl , vShootTarget , m_vFiringPos , ANGLE3D (fRelativeHdg , m_fDesiredMuzzlePitch , 0)); +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CEntityPointer penBall = CreateEntity (pl , CLASS_CANNONBALL ); +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +ELaunchCannonBall eLaunch ; +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eLaunch . penLauncher = this ; +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eLaunch . fLaunchPower = fLaunchSpeed ; +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eLaunch . cbtType = CBT_IRON ; +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +eLaunch . fSize = 1.0f; +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +penBall -> Initialize (eLaunch ); +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_tmLastFireTime = _pTimer -> CurrentTick (); +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Return(STATE_CURRENT,EReturn ()); +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCannonRotating:: +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Inactive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonRotating_Inactive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonRotating::Inactive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fRotSpeedMuzzle = ANGLE3D (0.0f , 0.0f , 0.0f); +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fRotSpeedRotator = ANGLE3D (0.0f , 0.0f , 0.0f); +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01590018, FALSE, EBegin());return TRUE;}BOOL CCannonRotating::H0x01590018_Inactive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590018 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Jump(STATE_CURRENT, STATE_CCannonRotating_MainLoop, TRUE, EVoid());return TRUE; +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Jump(STATE_CURRENT, STATE_CCannonRotating_Die, TRUE, eDeath );return TRUE; +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +}return TRUE;}BOOL CCannonRotating::H0x01590019_Inactive_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590019 + ASSERT(FALSE); return TRUE;};BOOL CCannonRotating:: +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonRotating_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonRotating::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +InitAsModel (); +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetCollisionFlags (ECF_MODEL ); +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +en_fDensity = 2000.0f; +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetModel (MODEL_TURRET ); +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetModelMainTexture (TEXTURE_TURRET ); +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +AddAttachment (TURRET_ATTACHMENT_ROTATORHEADING , MODEL_ROTATOR , TEXTURE_ROTATOR ); +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CModelObject & amo0 = GetModelObject () -> GetAttachmentModel (TURRET_ATTACHMENT_ROTATORHEADING ) -> amo_moModelObject ; +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +AddAttachmentToModel (this , amo0 , ROTATINGMECHANISM_ATTACHMENT_CANNON , MODEL_CANNON , TEXTURE_CANNON , 0 , 0 , 0); +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fWalkSpeed = 0.0f; +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_aWalkRotateSpeed = 0.0f; +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fAttackRunSpeed = 0.0f; +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_aAttackRotateSpeed = 0.0f; +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fCloseRunSpeed = 0.0f; +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_aCloseRotateSpeed = 0.0f; +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fStopDistance = 100.0f; +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fBlowUpAmount = 100.0f; +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fBodyParts = 4; +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fDamageWounded = 0.0f; +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_iScore = 1000; +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_sptType = SPT_WOOD ; +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(m_fHealth <= 0.0f){m_fHealth = 1.0f;} +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +m_fCloseFireTime = m_fAttackFireTime = m_fWaitAfterFire ; +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetHealth (m_fHealth );m_fMaxHealth = m_fHealth ; +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(m_fFiringRangeFar < m_fFiringRangeClose ){m_fFiringRangeFar = m_fFiringRangeClose + 1.0f;} +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fSize , m_fSize , m_fSize )); +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +ModelChangeNotify (); +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +StandingAnim (); +#line 573 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x0159001a, FALSE, EBegin());return TRUE;}BOOL CCannonRotating::H0x0159001a_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159001a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0159001b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonRotating::H0x0159001b_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159001b +; +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +UpdateFiringPos (); +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +if(! m_bActive ){Jump(STATE_CURRENT, STATE_CCannonRotating_Inactive, TRUE, EVoid());return TRUE;} +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Jump(STATE_CURRENT, STATE_CCannonRotating_MainLoop, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/CannonRotating.es b/Sources/EntitiesMP/CannonRotating.es new file mode 100644 index 0000000..04a95e6 --- /dev/null +++ b/Sources/EntitiesMP/CannonRotating.es @@ -0,0 +1,581 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +345 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/CannonRotating/Turret.h" +#include "ModelsMP/Enemies/CannonRotating/RotatingMechanism.h" +%} + +uses "EntitiesMP/ModelHolder2"; +uses "EntitiesMP/Projectile"; +uses "EntitiesMP/SoundHolder"; +uses "EntitiesMP/BloodSpray"; +uses "EntitiesMP/CannonBall"; + +%{ +#define CANNONR_SIZE 2.0f + +// info structure +static EntityInfo eiCannonRotating = { + EIBT_WOOD, 10000.0f, + 0.0f, 1.5f*CANNONR_SIZE, 0.0f, // source (eyes) + 0.0f, 0.5f*CANNONR_SIZE, 0.0f, // target (body) +}; + +#define FIRING_POSITION_MUZZLE FLOAT3D(0.0f, 0.0f, -1.0f) +#define MUZZLE_ROTATION_SPEED 45.0f //deg/sec + +%} + +class CCannonRotating: CEnemyBase { +name "CannonRotating"; +thumbnail "Thumbnails\\CannonRotating.tbn"; + +properties: + + 1 FLOAT m_fHealth "Cannon Health" = 100.0f, + 2 RANGE m_fFiringRangeClose "Cannon Firing Close Range" = 50.0f, + 3 RANGE m_fFiringRangeFar "Cannon Firing Far Range" = 150.0f, + 4 FLOAT m_fWaitAfterFire "Cannon Wait After Fire" = 3.0f, + 5 FLOAT m_fSize = CANNONR_SIZE, + 6 FLOAT m_fMaxPitch "Cannon Max Pitch" = 20.0f, + 7 FLOAT m_fViewAngle "Cannon View Angle" = 2.5f, + 8 FLOAT m_fScanAngle "Cannon Scanning Angle" = 60.0f, + 9 FLOAT m_fRotationSpeed "Cannon Rotation Speed" = 20.0f, + 10 BOOL m_bActive "Cannon Active" = TRUE, + + 20 FLOAT3D m_fRotSpeedMuzzle = ANGLE3D(0.0f, 0.0f, 0.0f), + 21 FLOAT3D m_fRotSpeedRotator = ANGLE3D(0.0f, 0.0f, 0.0f), + 25 FLOAT m_fDistanceToPlayer = 0.0f, + 26 FLOAT m_fDesiredMuzzlePitch = 0.0f, + 27 FLOAT m_iMuzzleDir = 1.0f, + 28 FLOAT3D m_vFiringPos = FLOAT3D(0.0f, 0.0f, 0.0f), + 29 FLOAT3D m_vTarget = FLOAT3D(0.0f, 0.0f, 0.0f), + 30 FLOAT m_tmLastFireTime = -1000.0f, + + 40 FLOAT3D m_aBeginMuzzleRotation = ANGLE3D(0.0f, 0.0f, 0.0f), + 41 FLOAT3D m_aEndMuzzleRotation = ANGLE3D(0.0f, 0.0f, 0.0f), + 42 FLOAT3D m_aBeginRotatorRotation = ANGLE3D(0.0f, 0.0f, 0.0f), + 43 FLOAT3D m_aEndRotatorRotation = ANGLE3D(0.0f, 0.0f, 0.0f), + + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + 2 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 3 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 4 class CLASS_CANNONBALL "Classes\\CannonBall.ecl", + + // ************** CANNON MODEL ************** + 10 model MODEL_TURRET "ModelsMP\\Enemies\\CannonRotating\\Turret.mdl", + 11 model MODEL_ROTATOR "ModelsMP\\Enemies\\CannonRotating\\RotatingMechanism.mdl", + 12 model MODEL_CANNON "ModelsMP\\Enemies\\CannonStatic\\Cannon.mdl", + 20 texture TEXTURE_TURRET "ModelsMP\\Enemies\\CannonRotating\\Turret.tex", + 21 texture TEXTURE_ROTATOR "ModelsMP\\Enemies\\CannonRotating\\RotatingMechanism.tex", + 22 texture TEXTURE_CANNON "Models\\Weapons\\Cannon\\Body.tex", + + // ************** CANNON PARTS ************** + 30 model MODEL_DEBRIS_MUZZLE "ModelsMP\\Enemies\\CannonRotating\\Debris\\Cannon.mdl", + 31 model MODEL_DEBRIS_ROTATOR "ModelsMP\\Enemies\\CannonRotating\\Debris\\RotatingMechanism.mdl", + 32 model MODEL_DEBRIS_BASE "ModelsMP\\Enemies\\CannonRotating\\Debris\\Turret.mdl", + 35 model MODEL_BALL "Models\\Weapons\\Cannon\\Projectile\\CannonBall.mdl", + 36 texture TEXTURE_BALL "Models\\Weapons\\Cannon\\Projectile\\IronBall.tex", + + // ************** SOUNDS ************** + 50 sound SOUND_FIRE "ModelsMP\\Enemies\\CannonRotating\\Sounds\\Fire.wav", + +functions: + +virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("A Cannon killed %s"), strPlayerName); + return str; + } + + /* Entity info */ + void *GetEntityInfo(void) { + return &eiCannonRotating; + }; + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnmCannon, "DataMP\\Messages\\Enemies\\CannonRotating.txt"); + return fnmCannon; + }; + + void Precache(void) { + CEnemyBase::Precache(); + PrecacheModel(MODEL_DEBRIS_MUZZLE); + PrecacheModel(MODEL_DEBRIS_ROTATOR); + PrecacheModel(MODEL_DEBRIS_BASE); + PrecacheModel(MODEL_BALL); + + PrecacheTexture(TEXTURE_BALL); + + PrecacheSound(SOUND_FIRE); + + PrecacheClass(CLASS_CANNONBALL); + }; + + + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // take less damage from heavy bullets (e.g. sniper) + if(dmtType==DMT_BULLET && fDamageAmmount>100.0f) + { + fDamageAmmount*=0.5f; + } + + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, + vHitPoint, vDirection); + }; + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + return 0; + }; + + // death + INDEX AnimForDeath(void) { + return 0; + }; + + // cast a ray to entity checking only for brushes + BOOL IsVisible(CEntity *penEntity) + { + ASSERT(penEntity!=NULL); + // get ray source and target + FLOAT3D vSource, vTarget; + GetPositionCastRay(this, penEntity, vSource, vTarget); + + // cast the ray + CCastRay crRay(this, vSource, vTarget); + crRay.cr_ttHitModels = CCastRay::TT_NONE; // check for brushes only + crRay.cr_bHitTranslucentPortals = FALSE; + en_pwoWorld->CastRay(crRay); + + // if hit nothing (no brush) the entity can be seen + return (crRay.cr_penHit==NULL); + }; + + BOOL IsInTheLineOfFire(CEntity *penEntity, FLOAT fAngle) + { + ASSERT(penEntity!=NULL); + + FLOAT fCosAngle; + FLOAT3D vHeading; + FLOAT3D vToPlayer; + + FLOAT3D vSide = FLOAT3D(1.0f, 0.0f, 0.0f)*GetRotationMatrix(); + FLOAT3D vFront = FLOAT3D(0.0f, 0.0f, -1.0f)*GetRotationMatrix(); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, m_aBeginRotatorRotation); + vSide = vSide*m; + vFront = vFront*m; + + vToPlayer = penEntity->GetPlacement().pl_PositionVector - GetPlacement().pl_PositionVector; + vToPlayer.Normalize(); + + fCosAngle = vToPlayer%vSide; + + // if on the firing plane + if (Abs(fCosAngle)0.0f) { + return TRUE; + } + } + return FALSE; + } + + CPlayer *AcquireTarget() { + // find actual number of players + INDEX ctMaxPlayers = GetMaxPlayers(); + CEntity *penPlayer; + + for(INDEX i=0; iInitialize(eSpawnEffect); + + // spawn shockwave + plExplosion = GetPlacement(); + penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNONSHOCKWAVE; + fSize = m_fBlowUpSize*1.0f; + eSpawnEffect.vStretch = FLOAT3D(fSize,fSize,fSize); + penExplosion->Initialize(eSpawnEffect); + + // hide yourself (must do this after spawning debris) + SwitchToEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + } + + void PreMoving() { + // manually update rotation of the attachments + UpdateAttachmentRotations(); + CEnemyBase::PreMoving(); + } + + void PostMoving() { + CEnemyBase::PostMoving(); + // make sure this entity stays in the moving list + SetFlags(GetFlags()&~ENF_INRENDERING); + } + + // rotate to between-tick position + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) { + // rotator + CAttachmentModelObject &amo0 = *GetModelObject()->GetAttachmentModel(TURRET_ATTACHMENT_ROTATORHEADING); + amo0.amo_plRelative.pl_OrientationAngle = Lerp(m_aBeginRotatorRotation, m_aEndRotatorRotation, _pTimer->GetLerpFactor()); + // muzzle + CAttachmentModelObject &amo1 = *amo0.amo_moModelObject.GetAttachmentModel(ROTATINGMECHANISM_ATTACHMENT_CANNON); + amo1.amo_plRelative.pl_OrientationAngle = Lerp(m_aBeginMuzzleRotation, m_aEndMuzzleRotation, _pTimer->GetLerpFactor()); + // finish by calling the default 'AdjustShadingParameters' + return CEnemyBase::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + }; + + + void UpdateAttachmentRotations( void ) + { + // rotator + m_aBeginRotatorRotation = m_aEndRotatorRotation; + m_aEndRotatorRotation += m_fRotSpeedRotator*_pTimer->TickQuantum; + // muzzle + m_aBeginMuzzleRotation = m_aEndMuzzleRotation; + m_aEndMuzzleRotation += m_fRotSpeedMuzzle*_pTimer->TickQuantum; + } + + void UpdateFiringPos() { + FLOATmatrix3D m; + // initial position + m_vFiringPos = FIRING_POSITION_MUZZLE*m_fSize; + + // heading rotation + MakeRotationMatrixFast(m, m_aBeginRotatorRotation); + m_vFiringPos = m_vFiringPos*m; + + // pitch rotation + MakeRotationMatrixFast(m, m_aBeginMuzzleRotation); + m_vFiringPos = m_vFiringPos*m; + + // add translations + CAttachmentModelObject &amo0 = *GetModelObject()->GetAttachmentModel(TURRET_ATTACHMENT_ROTATORHEADING); + CAttachmentModelObject &amo1 = *amo0.amo_moModelObject.GetAttachmentModel(ROTATINGMECHANISM_ATTACHMENT_CANNON); + m_vFiringPos += amo0.amo_plRelative.pl_PositionVector + amo1.amo_plRelative.pl_PositionVector; + } + +procedures: + + MainLoop() { + wait() { + on (EBegin) : { + call Scan(); + resume; + } + on (EDeactivate) : { + jump Inactive(); + } + on (EDeath eDeath) : { + // die + jump Die(eDeath); + } + }; + return; + }; + + Scan() { + // this is a kind of 'sleep' mode - check to see if any player entered + // the attack radius every once in a while, and change rotation when needed + while(TRUE) { + autowait(0.20f); + // adjust rotations + + BOOL bPause = FALSE; + if ( m_aBeginRotatorRotation(1)>(m_fScanAngle/2.0f) ) { + m_fRotSpeedRotator = FLOAT3D(-m_fRotationSpeed, 0.0f, 0.0f); + if (m_iMuzzleDir!=-1.0f) { + m_iMuzzleDir= -1.0f; + bPause = TRUE; + } + } else if ( m_aBeginRotatorRotation(1)<(-m_fScanAngle/2.0f) ) { + m_fRotSpeedRotator = FLOAT3D(m_fRotationSpeed, 0.0f, 0.0f); + if (m_iMuzzleDir!=1.0f) { + m_iMuzzleDir= 1.0f; + bPause = TRUE; + } + } else if (TRUE) { + m_fRotSpeedRotator = FLOAT3D(m_iMuzzleDir*m_fRotationSpeed, 0.0f, 0.0f); + } + + if (bPause) { + m_fRotSpeedRotator = FLOAT3D(0.0f, 0.0f, 0.0f); + autowait(0.5f); + } + + // check for players + CPlayer *pTarget = AcquireTarget(); + if (pTarget) { + if ((pTarget->GetFlags()&ENF_ALIVE) && !(pTarget->GetFlags()&ENF_DELETED)) { + // stop rotations + m_fRotSpeedRotator = FLOAT3D(0.0f, 0.0f, 0.0f); + m_penEnemy = pTarget; + m_fDistanceToPlayer = DistanceTo(this, pTarget); + // if it's time to fire, do so + if (m_tmLastFireTime+m_fWaitAfterFire<_pTimer->CurrentTick()) + { + autocall FireCannon() EReturn; + } + } + } + } + } + + Die(EDeath eDeath) { + // not alive anymore + SetFlags(GetFlags()&~ENF_ALIVE); + + // find the one who killed, or other best suitable player + CEntityPointer penKiller = eDeath.eLastDamage.penInflictor; + if (penKiller==NULL || !IsOfClass(penKiller, "Player")) { + penKiller = m_penEnemy; + } + + if (penKiller==NULL || !IsOfClass(penKiller, "Player")) { + penKiller = FixupCausedToPlayer(this, penKiller, /*bWarning=*/FALSE); + } + + // if killed by someone + if (penKiller!=NULL) { + // give him score + EReceiveScore eScore; + eScore.iPoints = m_iScore; + penKiller->SendEvent(eScore); + if( CountAsKill()) + { + penKiller->SendEvent(EKilledEnemy()); + } + // send computer message + EComputerMessage eMsg; + eMsg.fnmMessage = GetComputerMessageName(); + if (eMsg.fnmMessage!="") { + penKiller->SendEvent(eMsg); + } + } + + // send event to death target + SendToTarget(m_penDeathTarget, m_eetDeathType, penKiller); + // send event to spawner if any + // NOTE: trigger's penCaused has been changed from penKiller to THIS; + if (m_penSpawnerTarget) { + SendToTarget(m_penSpawnerTarget, EET_TRIGGER, this); + } + + // spawn debris + CannonBlowUp(); + Destroy(); + return; + }; + + RotateMuzzle() { + + FLOAT fDeltaP = m_fDesiredMuzzlePitch - m_aBeginMuzzleRotation(2); + + // if close enough to desired rotation, don't rotate + if (Abs(fDeltaP)<5.0f) { return EReturn(); } + + m_fRotSpeedMuzzle = ANGLE3D(0.0f, MUZZLE_ROTATION_SPEED*Sgn(fDeltaP), 0.0f); +//CPrintF("wait %f; beg:%f, end:%f at %f\n", Abs(fDeltaP/MUZZLE_ROTATION_SPEED), m_aBeginMuzzleRotation, m_aEndMuzzleRotation, _pTimer->CurrentTick()); + autowait(Abs(fDeltaP/MUZZLE_ROTATION_SPEED)); + m_fRotSpeedMuzzle = ANGLE3D(0.0f, 0.0f, 0.0f); + + return EReturn(); + }; + + FireCannon() { + + UpdateFiringPos(); + FLOAT3D vToTarget = m_penEnemy->GetPlacement().pl_PositionVector - + GetPlacement().pl_PositionVector + m_vFiringPos; + vToTarget.Normalize(); + + // get vector pointing in heading direction of the muzzle + FLOAT3D vCannonFront = FLOAT3D(0.0f, 0.0f, -1.0f)*GetRotationMatrix(); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, m_aBeginRotatorRotation); + vCannonFront = vCannonFront*m; + ANGLE aToPlayer = ACos(vToTarget%vCannonFront); + FLOAT fPitch = aToPlayer + 5.0f; + FLOAT3D vCannonUp = FLOAT3D(0.0, 1.0f, 0.0f)*GetRotationMatrix(); + + // if too far, do not fire + if (m_fDistanceToPlayer>m_fFiringRangeFar) { + return EReturn(); + // if player under cannon, minimize pitch + } else if (vToTarget%vCannonUp<0.0f) { + fPitch = 5.0f; + // if in far range + } else if (m_fDistanceToPlayer>m_fFiringRangeClose) { + if (aToPlayerGetPlacement().pl_PositionVector; + + m_fDesiredMuzzlePitch = fPitch; + autocall RotateMuzzle() EReturn; + + FLOAT3D vShooting = GetPlacement().pl_PositionVector + m_vFiringPos; + FLOAT3D vSpeedDest = FLOAT3D(0.0f, 0.0f, 0.0f); + FLOAT fLaunchSpeed; + FLOAT fRelativeHdg; + + // calculate parameters for predicted angular launch curve + EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); + CalculateAngularLaunchParams( vShooting, peiTarget->vTargetCenter[1]-6.0f/3.0f, m_vTarget, + vSpeedDest, m_fDesiredMuzzlePitch , fLaunchSpeed, fRelativeHdg); + + // target enemy body + FLOAT3D vShootTarget; + GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget); + // launch + CPlacement3D pl; + PrepareFreeFlyingProjectile(pl, vShootTarget, m_vFiringPos, ANGLE3D( fRelativeHdg, m_fDesiredMuzzlePitch, 0)); + CEntityPointer penBall = CreateEntity(pl, CLASS_CANNONBALL); + ELaunchCannonBall eLaunch; + eLaunch.penLauncher = this; + eLaunch.fLaunchPower = fLaunchSpeed; + eLaunch.cbtType = CBT_IRON; + eLaunch.fSize = 1.0f; + penBall->Initialize(eLaunch); + + m_tmLastFireTime = _pTimer->CurrentTick(); + + return EReturn(); + }; + + Inactive() + { + m_fRotSpeedMuzzle = ANGLE3D(0.0f, 0.0f, 0.0f); + m_fRotSpeedRotator = ANGLE3D(0.0f, 0.0f, 0.0f); + wait() { + on (EBegin) : { resume; } + on (EActivate) : { + jump MainLoop(); + } + on (EDeath eDeath) : { + jump Die(eDeath); + } + otherwise (): { resume; } + } + } + + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + en_fDensity = 2000.0f; + + // set your appearance + SetModel(MODEL_TURRET); + SetModelMainTexture(TEXTURE_TURRET); + + AddAttachment(TURRET_ATTACHMENT_ROTATORHEADING, MODEL_ROTATOR, TEXTURE_ROTATOR); + CModelObject &amo0 = GetModelObject()->GetAttachmentModel(TURRET_ATTACHMENT_ROTATORHEADING)->amo_moModelObject; + AddAttachmentToModel(this, amo0, ROTATINGMECHANISM_ATTACHMENT_CANNON, MODEL_CANNON, TEXTURE_CANNON, 0, 0, 0); + + // setup moving speed + m_fWalkSpeed = 0.0f; + m_aWalkRotateSpeed = 0.0f; + m_fAttackRunSpeed = 0.0f; + m_aAttackRotateSpeed = 0.0f; + m_fCloseRunSpeed = 0.0f; + m_aCloseRotateSpeed = 0.0f; + // setup attack distances + m_fStopDistance = 100.0f; + //m_fBlowUpAmount = 65.0f; + m_fBlowUpAmount = 100.0f; + m_fBodyParts = 4; + m_fDamageWounded = 0.0f; + m_iScore = 1000; + m_sptType = SPT_WOOD; + + // properties that modify EnemyBase properties + if (m_fHealth<=0.0f) { m_fHealth=1.0f; } + m_fCloseFireTime = m_fAttackFireTime = m_fWaitAfterFire; + SetHealth(m_fHealth); m_fMaxHealth = m_fHealth; + if (m_fFiringRangeFarStretchModel(FLOAT3D(m_fSize, m_fSize, m_fSize)); + + ModelChangeNotify(); + StandingAnim(); + + // don't continue behavior in base class! - this enemy is derived + // from CEnemyBase only because of its properties + autowait(0.05f); + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + UpdateFiringPos(); + + if (!m_bActive) { jump Inactive(); } + jump MainLoop(); + + }; +}; diff --git a/Sources/EntitiesMP/CannonRotating.h b/Sources/EntitiesMP/CannonRotating.h new file mode 100644 index 0000000..bf4d328 --- /dev/null +++ b/Sources/EntitiesMP/CannonRotating.h @@ -0,0 +1,139 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_CannonRotating_INCLUDED +#define _EntitiesMP_CannonRotating_INCLUDED 1 +#include +#include +#include +#include +#include +extern "C" DECL_DLL CDLLEntityClass CCannonRotating_DLLClass; +class CCannonRotating : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fHealth; + RANGE m_fFiringRangeClose; + RANGE m_fFiringRangeFar; + FLOAT m_fWaitAfterFire; + FLOAT m_fSize; + FLOAT m_fMaxPitch; + FLOAT m_fViewAngle; + FLOAT m_fScanAngle; + FLOAT m_fRotationSpeed; + BOOL m_bActive; + FLOAT3D m_fRotSpeedMuzzle; + FLOAT3D m_fRotSpeedRotator; + FLOAT m_fDistanceToPlayer; + FLOAT m_fDesiredMuzzlePitch; + FLOAT m_iMuzzleDir; + FLOAT3D m_vFiringPos; + FLOAT3D m_vTarget; + FLOAT m_tmLastFireTime; + FLOAT3D m_aBeginMuzzleRotation; + FLOAT3D m_aEndMuzzleRotation; + FLOAT3D m_aBeginRotatorRotation; + FLOAT3D m_aEndRotatorRotation; + +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void * GetEntityInfo(void); + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void Precache(void); + +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +INDEX AnimForDeath(void); + +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +BOOL IsVisible(CEntity * penEntity); + +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +BOOL IsInTheLineOfFire(CEntity * penEntity,FLOAT fAngle); + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +CPlayer * AcquireTarget(); + +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void CannonBlowUp(void); + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void PreMoving(); + +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void PostMoving(); + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void UpdateAttachmentRotations(void); + +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +void UpdateFiringPos(); +#define STATE_CCannonRotating_MainLoop 0x01590000 + BOOL +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +MainLoop(const CEntityEvent &__eeInput); + BOOL H0x01590001_MainLoop_01(const CEntityEvent &__eeInput); + BOOL H0x01590002_MainLoop_02(const CEntityEvent &__eeInput); +#define STATE_CCannonRotating_Scan 0x01590003 + BOOL +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Scan(const CEntityEvent &__eeInput); + BOOL H0x01590004_Scan_01(const CEntityEvent &__eeInput); + BOOL H0x01590005_Scan_02(const CEntityEvent &__eeInput); + BOOL H0x01590006_Scan_03(const CEntityEvent &__eeInput); + BOOL H0x01590007_Scan_04(const CEntityEvent &__eeInput); + BOOL H0x01590008_Scan_05(const CEntityEvent &__eeInput); + BOOL H0x01590009_Scan_06(const CEntityEvent &__eeInput); + BOOL H0x0159000a_Scan_07(const CEntityEvent &__eeInput); + BOOL H0x0159000b_Scan_08(const CEntityEvent &__eeInput); + BOOL H0x0159000c_Scan_09(const CEntityEvent &__eeInput); + BOOL H0x0159000d_Scan_10(const CEntityEvent &__eeInput); + BOOL H0x0159000e_Scan_11(const CEntityEvent &__eeInput); + BOOL H0x0159000f_Scan_12(const CEntityEvent &__eeInput); +#define STATE_CCannonRotating_Die 0x01590010 + BOOL +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Die(const CEntityEvent &__eeInput); +#define STATE_CCannonRotating_RotateMuzzle 0x01590011 + BOOL +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +RotateMuzzle(const CEntityEvent &__eeInput); + BOOL H0x01590012_RotateMuzzle_01(const CEntityEvent &__eeInput); + BOOL H0x01590013_RotateMuzzle_02(const CEntityEvent &__eeInput); +#define STATE_CCannonRotating_FireCannon 0x01590014 + BOOL +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FireCannon(const CEntityEvent &__eeInput); + BOOL H0x01590015_FireCannon_01(const CEntityEvent &__eeInput); + BOOL H0x01590016_FireCannon_02(const CEntityEvent &__eeInput); +#define STATE_CCannonRotating_Inactive 0x01590017 + BOOL +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Inactive(const CEntityEvent &__eeInput); + BOOL H0x01590018_Inactive_01(const CEntityEvent &__eeInput); + BOOL H0x01590019_Inactive_02(const CEntityEvent &__eeInput); +#define STATE_CCannonRotating_Main 1 + BOOL +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x0159001a_Main_01(const CEntityEvent &__eeInput); + BOOL H0x0159001b_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_CannonRotating_INCLUDED diff --git a/Sources/EntitiesMP/CannonRotating_tables.h b/Sources/EntitiesMP/CannonRotating_tables.h new file mode 100644 index 0000000..1004e6f --- /dev/null +++ b/Sources/EntitiesMP/CannonRotating_tables.h @@ -0,0 +1,125 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CCannonRotating + +CEntityProperty CCannonRotating_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+1, offsetof(CCannonRotating, m_fHealth), "Cannon Health", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000159<<8)+2, offsetof(CCannonRotating, m_fFiringRangeClose), "Cannon Firing Close Range", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000159<<8)+3, offsetof(CCannonRotating, m_fFiringRangeFar), "Cannon Firing Far Range", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+4, offsetof(CCannonRotating, m_fWaitAfterFire), "Cannon Wait After Fire", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+5, offsetof(CCannonRotating, m_fSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+6, offsetof(CCannonRotating, m_fMaxPitch), "Cannon Max Pitch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+7, offsetof(CCannonRotating, m_fViewAngle), "Cannon View Angle", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+8, offsetof(CCannonRotating, m_fScanAngle), "Cannon Scanning Angle", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+9, offsetof(CCannonRotating, m_fRotationSpeed), "Cannon Rotation Speed", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000159<<8)+10, offsetof(CCannonRotating, m_bActive), "Cannon Active", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+20, offsetof(CCannonRotating, m_fRotSpeedMuzzle), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+21, offsetof(CCannonRotating, m_fRotSpeedRotator), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+25, offsetof(CCannonRotating, m_fDistanceToPlayer), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+26, offsetof(CCannonRotating, m_fDesiredMuzzlePitch), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+27, offsetof(CCannonRotating, m_iMuzzleDir), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+28, offsetof(CCannonRotating, m_vFiringPos), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+29, offsetof(CCannonRotating, m_vTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+30, offsetof(CCannonRotating, m_tmLastFireTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+40, offsetof(CCannonRotating, m_aBeginMuzzleRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+41, offsetof(CCannonRotating, m_aEndMuzzleRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+42, offsetof(CCannonRotating, m_aBeginRotatorRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+43, offsetof(CCannonRotating, m_aEndRotatorRotation), "", 0, 0, 0), +}; +#define CCannonRotating_propertiesct ARRAYCOUNT(CCannonRotating_properties) + +CEntityComponent CCannonRotating_components[] = { +#define CLASS_BASE ((0x00000159<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000159<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_PROJECTILE ((0x00000159<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_CANNONBALL ((0x00000159<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_CANNONBALL, "EFNM" "Classes\\CannonBall.ecl"), +#define MODEL_TURRET ((0x00000159<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_TURRET, "EFNM" "ModelsMP\\Enemies\\CannonRotating\\Turret.mdl"), +#define MODEL_ROTATOR ((0x00000159<<8)+11) + CEntityComponent(ECT_MODEL, MODEL_ROTATOR, "EFNM" "ModelsMP\\Enemies\\CannonRotating\\RotatingMechanism.mdl"), +#define MODEL_CANNON ((0x00000159<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_CANNON, "EFNM" "ModelsMP\\Enemies\\CannonStatic\\Cannon.mdl"), +#define TEXTURE_TURRET ((0x00000159<<8)+20) + CEntityComponent(ECT_TEXTURE, TEXTURE_TURRET, "EFNM" "ModelsMP\\Enemies\\CannonRotating\\Turret.tex"), +#define TEXTURE_ROTATOR ((0x00000159<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_ROTATOR, "EFNM" "ModelsMP\\Enemies\\CannonRotating\\RotatingMechanism.tex"), +#define TEXTURE_CANNON ((0x00000159<<8)+22) + CEntityComponent(ECT_TEXTURE, TEXTURE_CANNON, "EFNM" "Models\\Weapons\\Cannon\\Body.tex"), +#define MODEL_DEBRIS_MUZZLE ((0x00000159<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS_MUZZLE, "EFNM" "ModelsMP\\Enemies\\CannonRotating\\Debris\\Cannon.mdl"), +#define MODEL_DEBRIS_ROTATOR ((0x00000159<<8)+31) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS_ROTATOR, "EFNM" "ModelsMP\\Enemies\\CannonRotating\\Debris\\RotatingMechanism.mdl"), +#define MODEL_DEBRIS_BASE ((0x00000159<<8)+32) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS_BASE, "EFNM" "ModelsMP\\Enemies\\CannonRotating\\Debris\\Turret.mdl"), +#define MODEL_BALL ((0x00000159<<8)+35) + CEntityComponent(ECT_MODEL, MODEL_BALL, "EFNM" "Models\\Weapons\\Cannon\\Projectile\\CannonBall.mdl"), +#define TEXTURE_BALL ((0x00000159<<8)+36) + CEntityComponent(ECT_TEXTURE, TEXTURE_BALL, "EFNM" "Models\\Weapons\\Cannon\\Projectile\\IronBall.tex"), +#define SOUND_FIRE ((0x00000159<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_FIRE, "EFNM" "ModelsMP\\Enemies\\CannonRotating\\Sounds\\Fire.wav"), +}; +#define CCannonRotating_componentsct ARRAYCOUNT(CCannonRotating_components) + +CEventHandlerEntry CCannonRotating_handlers[] = { + {0x01590000, -1, CEntity::pEventHandler(&CCannonRotating:: +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +MainLoop),DEBUGSTRING("CCannonRotating::MainLoop")}, + {0x01590001, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590001_MainLoop_01), DEBUGSTRING("CCannonRotating::H0x01590001_MainLoop_01")}, + {0x01590002, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590002_MainLoop_02), DEBUGSTRING("CCannonRotating::H0x01590002_MainLoop_02")}, + {0x01590003, -1, CEntity::pEventHandler(&CCannonRotating:: +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Scan),DEBUGSTRING("CCannonRotating::Scan")}, + {0x01590004, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590004_Scan_01), DEBUGSTRING("CCannonRotating::H0x01590004_Scan_01")}, + {0x01590005, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590005_Scan_02), DEBUGSTRING("CCannonRotating::H0x01590005_Scan_02")}, + {0x01590006, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590006_Scan_03), DEBUGSTRING("CCannonRotating::H0x01590006_Scan_03")}, + {0x01590007, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590007_Scan_04), DEBUGSTRING("CCannonRotating::H0x01590007_Scan_04")}, + {0x01590008, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590008_Scan_05), DEBUGSTRING("CCannonRotating::H0x01590008_Scan_05")}, + {0x01590009, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590009_Scan_06), DEBUGSTRING("CCannonRotating::H0x01590009_Scan_06")}, + {0x0159000a, -1, CEntity::pEventHandler(&CCannonRotating::H0x0159000a_Scan_07), DEBUGSTRING("CCannonRotating::H0x0159000a_Scan_07")}, + {0x0159000b, -1, CEntity::pEventHandler(&CCannonRotating::H0x0159000b_Scan_08), DEBUGSTRING("CCannonRotating::H0x0159000b_Scan_08")}, + {0x0159000c, -1, CEntity::pEventHandler(&CCannonRotating::H0x0159000c_Scan_09), DEBUGSTRING("CCannonRotating::H0x0159000c_Scan_09")}, + {0x0159000d, -1, CEntity::pEventHandler(&CCannonRotating::H0x0159000d_Scan_10), DEBUGSTRING("CCannonRotating::H0x0159000d_Scan_10")}, + {0x0159000e, -1, CEntity::pEventHandler(&CCannonRotating::H0x0159000e_Scan_11), DEBUGSTRING("CCannonRotating::H0x0159000e_Scan_11")}, + {0x0159000f, -1, CEntity::pEventHandler(&CCannonRotating::H0x0159000f_Scan_12), DEBUGSTRING("CCannonRotating::H0x0159000f_Scan_12")}, + {0x01590010, -1, CEntity::pEventHandler(&CCannonRotating:: +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Die),DEBUGSTRING("CCannonRotating::Die")}, + {0x01590011, -1, CEntity::pEventHandler(&CCannonRotating:: +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +RotateMuzzle),DEBUGSTRING("CCannonRotating::RotateMuzzle")}, + {0x01590012, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590012_RotateMuzzle_01), DEBUGSTRING("CCannonRotating::H0x01590012_RotateMuzzle_01")}, + {0x01590013, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590013_RotateMuzzle_02), DEBUGSTRING("CCannonRotating::H0x01590013_RotateMuzzle_02")}, + {0x01590014, -1, CEntity::pEventHandler(&CCannonRotating:: +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +FireCannon),DEBUGSTRING("CCannonRotating::FireCannon")}, + {0x01590015, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590015_FireCannon_01), DEBUGSTRING("CCannonRotating::H0x01590015_FireCannon_01")}, + {0x01590016, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590016_FireCannon_02), DEBUGSTRING("CCannonRotating::H0x01590016_FireCannon_02")}, + {0x01590017, -1, CEntity::pEventHandler(&CCannonRotating:: +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Inactive),DEBUGSTRING("CCannonRotating::Inactive")}, + {0x01590018, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590018_Inactive_01), DEBUGSTRING("CCannonRotating::H0x01590018_Inactive_01")}, + {0x01590019, -1, CEntity::pEventHandler(&CCannonRotating::H0x01590019_Inactive_02), DEBUGSTRING("CCannonRotating::H0x01590019_Inactive_02")}, + {1, -1, CEntity::pEventHandler(&CCannonRotating:: +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/CannonRotating.es" +Main),DEBUGSTRING("CCannonRotating::Main")}, + {0x0159001a, -1, CEntity::pEventHandler(&CCannonRotating::H0x0159001a_Main_01), DEBUGSTRING("CCannonRotating::H0x0159001a_Main_01")}, + {0x0159001b, -1, CEntity::pEventHandler(&CCannonRotating::H0x0159001b_Main_02), DEBUGSTRING("CCannonRotating::H0x0159001b_Main_02")}, +}; +#define CCannonRotating_handlersct ARRAYCOUNT(CCannonRotating_handlers) + +CEntity *CCannonRotating_New(void) { return new CCannonRotating; }; +void CCannonRotating_OnInitClass(void) {}; +void CCannonRotating_OnEndClass(void) {}; +void CCannonRotating_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CCannonRotating_OnWorldEnd(CWorld *pwo) {}; +void CCannonRotating_OnWorldInit(CWorld *pwo) {}; +void CCannonRotating_OnWorldTick(CWorld *pwo) {}; +void CCannonRotating_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CCannonRotating, CEnemyBase, "CannonRotating", "Thumbnails\\CannonRotating.tbn", 0x00000159); +DECLARE_CTFILENAME(_fnmCCannonRotating_tbn, "Thumbnails\\CannonRotating.tbn"); diff --git a/Sources/EntitiesMP/CannonStatic.cpp b/Sources/EntitiesMP/CannonStatic.cpp new file mode 100644 index 0000000..0f8442b --- /dev/null +++ b/Sources/EntitiesMP/CannonStatic.cpp @@ -0,0 +1,758 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/CannonStatic/Turret.h" + + +#include +#include +#line 16 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" + +#define CANNONS_SIZE 2.0f + +// info structure +static EntityInfo eiCannonStatic = { + EIBT_WOOD, 10000.0f, + 0.0f, 1.5f*CANNONS_SIZE, 0.0f, // source (eyes) + 0.0f, 0.5f*CANNONS_SIZE, 0.0f, // target (body) +}; + +#define FIRING_POSITION_MUZZLE FLOAT3D(0.0f, 0.4f, -1.0f) +#define MUZZLE_ROTATION_SPEED 45.0f //deg/sec + + +void CCannonStatic::SetDefaultProperties(void) { + m_fHealth = 100.0f; + m_fFiringRangeClose = 50.0f; + m_fFiringRangeFar = 150.0f; + m_fShootingPeriod = 5.0f; + m_fSize = CANNONS_SIZE ; + m_fMaxPitch = 20.0f; + m_fViewAngle = 2.5f; + m_bActive = TRUE ; + m_fRotSpeedMuzzle = ANGLE3D(0.0f , 0.0f , 0.0f); + m_fDistanceToPlayer = 0.0f; + m_fDesiredMuzzlePitch = 0.0f; + m_iMuzzleDir = 1; + m_vFiringPos = FLOAT3D(0.0f , 0.0f , 0.0f); + m_vTarget = FLOAT3D(0.0f , 0.0f , 0.0f); + m_aBeginMuzzleRotation = ANGLE3D(0.0f , 0.0f , 0.0f); + m_aEndMuzzleRotation = ANGLE3D(0.0f , 0.0f , 0.0f); + CEnemyBase::SetDefaultProperties(); +} + CTString CCannonStatic::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +{ +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CTString str ; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +str . PrintF (TRANS ("A Cannon killed %s") , strPlayerName ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return str ; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void * CCannonStatic::GetEntityInfo(void) { +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return & eiCannonStatic ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + const CTFileName & CCannonStatic::GetComputerMessageName(void)const { +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +static DECLARE_CTFILENAME (fnmCannon , "DataMP\\Messages\\Enemies\\CannonStatic.txt"); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return fnmCannon ; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void CCannonStatic::Precache(void) { +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CEnemyBase :: Precache (); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +PrecacheModel (MODEL_DEBRIS_MUZZLE ); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +PrecacheModel (MODEL_DEBRIS_WHEEL ); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +PrecacheModel (MODEL_DEBRIS_WOOD ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +PrecacheModel (MODEL_BALL ); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +PrecacheTexture (TEXTURE_BALL ); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +PrecacheSound (SOUND_FIRE ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +PrecacheClass (CLASS_CANNONBALL ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void CCannonStatic::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +{ +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(dmtType == DMT_BULLET && fDamageAmmount > 100.0f) +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +{ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +fDamageAmmount *= 0.5f; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +vHitPoint , vDirection ); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +INDEX CCannonStatic::AnimForDamage(FLOAT fDamage) { +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return 0; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +INDEX CCannonStatic::AnimForDeath(void) { +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return 0; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +BOOL CCannonStatic::IsVisible(CEntity * penEntity) +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +{ +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +ASSERT (penEntity != NULL ); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vSource , vTarget ; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +GetPositionCastRay (this , penEntity , vSource , vTarget ); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CCastRay crRay (this , vSource , vTarget ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +crRay . cr_ttHitModels = CCastRay :: TT_NONE ; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +en_pwoWorld -> CastRay (crRay ); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return (crRay . cr_penHit == NULL ); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +BOOL CCannonStatic::IsInTheLineOfFire(CEntity * penEntity,FLOAT fAngle) +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +{ +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +ASSERT (penEntity != NULL ); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT fCosAngle ; +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vHeading ; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vToPlayer ; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vSide = FLOAT3D (1.0f , 0.0f , 0.0f) * GetRotationMatrix (); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vFront = FLOAT3D (0.0f , 0.0f , - 1.0f) * GetRotationMatrix (); +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +vToPlayer = penEntity -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +vToPlayer . Normalize (); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +fCosAngle = vToPlayer % vSide ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(Abs (fCosAngle ) < CosFast (90.0f - fAngle )){ +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if((vToPlayer % vFront ) > 0.0f){ +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return TRUE ; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return FALSE ; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CPlayer * CCannonStatic::AcquireTarget() { +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +INDEX ctMaxPlayers = GetMaxPlayers (); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CEntity * penPlayer ; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +for(INDEX i = 0;i < ctMaxPlayers ;i ++){ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +penPlayer = GetPlayerEntity (i ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(penPlayer != NULL && DistanceTo (this , penPlayer ) < m_fFiringRangeFar ){ +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(IsInTheLineOfFire (penPlayer , m_fViewAngle )){ +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(IsVisible (penPlayer )){ +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return (CPlayer *) penPlayer ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return NULL ; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void CCannonStatic::CannonBlowUp(void) +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +{ +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vNormalizedDamage = m_vDamage - m_vDamage * (m_fBlowUpAmount / m_vDamage . Length ()); +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +vNormalizedDamage /= Sqrt (vNormalizedDamage . Length ()); +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +vNormalizedDamage *= 0.75f; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +vNormalizedDamage += FLOAT3D (0.0f , 10.0f + FRnd () * 10.0f , 0.0f); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute - en_vGravityDir * (en_vGravityDir % en_vCurrentTranslationAbsolute ); +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Debris_Begin (EIBT_WOOD , DPT_NONE , BET_NONE , 1.0f , vNormalizedDamage , vBodySpeed , 5.0f , 2.0f); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Debris_Spawn (this , this , MODEL_DEBRIS_MUZZLE , TEXTURE_CANNON , 0 , 0 , 0 , 0 , m_fSize , +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Debris_Spawn (this , this , MODEL_DEBRIS_WHEEL , TEXTURE_TURRET , 0 , 0 , 0 , 0 , m_fSize , +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Debris_Spawn (this , this , MODEL_DEBRIS_WHEEL , TEXTURE_TURRET , 0 , 0 , 0 , 0 , m_fSize , +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Debris_Spawn (this , this , MODEL_DEBRIS_WOOD , TEXTURE_TURRET , 0 , 0 , 0 , 0 , m_fSize , +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Debris_Spawn (this , this , MODEL_DEBRIS_WOOD , TEXTURE_TURRET , 0 , 0 , 0 , 0 , m_fSize , +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Debris_Spawn (this , this , MODEL_BALL , TEXTURE_BALL , 0 , 0 , 0 , 0 , m_fSize / 2.0f , +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CPlacement3D plExplosion = GetPlacement (); +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CEntityPointer penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +ESpawnEffect eSpawnEffect ; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eSpawnEffect . betType = BET_CANNON ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT fSize = m_fBlowUpSize * 1.0f; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eSpawnEffect . vStretch = FLOAT3D (fSize , fSize , fSize ); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +plExplosion = GetPlacement (); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eSpawnEffect . betType = BET_CANNONSHOCKWAVE ; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +fSize = m_fBlowUpSize * 1.0f; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eSpawnEffect . vStretch = FLOAT3D (fSize , fSize , fSize ); +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SwitchToEditorModel (); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void CCannonStatic::PreMoving() { +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +UpdateAttachmentRotations (); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CEnemyBase :: PreMoving (); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void CCannonStatic::PostMoving() { +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CEnemyBase :: PostMoving (); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetFlags (GetFlags () & ~ ENF_INRENDERING ); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +BOOL CCannonStatic::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) { +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CAttachmentModelObject & amo0 = * GetModelObject () -> GetAttachmentModel (TURRET_ATTACHMENT_CANNON ); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +amo0 . amo_plRelative . pl_OrientationAngle = Lerp (m_aBeginMuzzleRotation , m_aEndMuzzleRotation , _pTimer -> GetLerpFactor ()); +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return CEnemyBase :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void CCannonStatic::UpdateAttachmentRotations(void) +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +{ +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_aBeginMuzzleRotation = m_aEndMuzzleRotation ; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_aEndMuzzleRotation += m_fRotSpeedMuzzle * _pTimer -> TickQuantum ; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void CCannonStatic::UpdateFiringPos() { +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOATmatrix3D m ; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_vFiringPos = FIRING_POSITION_MUZZLE * m_fSize ; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +MakeRotationMatrixFast (m , m_aBeginMuzzleRotation ); +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_vFiringPos = m_vFiringPos * m ; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CAttachmentModelObject & amo0 = * GetModelObject () -> GetAttachmentModel (TURRET_ATTACHMENT_CANNON ); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_vFiringPos += amo0 . amo_plRelative . pl_PositionVector ; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +BOOL CCannonStatic:: +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +MainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonStatic_MainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonStatic::MainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01590001, FALSE, EBegin());return TRUE;}BOOL CCannonStatic::H0x01590001_MainLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Call(STATE_CURRENT, STATE_CCannonStatic_WatchPlayers, TRUE, EVoid());return TRUE; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return TRUE; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Jump(STATE_CURRENT, STATE_CCannonStatic_Inactive, TRUE, EVoid());return TRUE; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Jump(STATE_CURRENT, STATE_CCannonStatic_Die, TRUE, eDeath );return TRUE; +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +}return TRUE;}BOOL CCannonStatic::H0x01590002_MainLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590002 +; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Return(STATE_CURRENT,EVoid()); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCannonStatic:: +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Die(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonStatic_Die + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDeath, "CCannonStatic::Die expects 'EDeath' as input!"); const EDeath &eDeath = (const EDeath &)__eeInput; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetFlags (GetFlags () & ~ ENF_ALIVE ); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CEntityPointer penKiller = eDeath . eLastDamage . penInflictor ; +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(penKiller == NULL || ! IsOfClass (penKiller , "Player")){ +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +penKiller = m_penEnemy ; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(penKiller == NULL || ! IsOfClass (penKiller , "Player")){ +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +penKiller = FixupCausedToPlayer (this , penKiller , FALSE ); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(penKiller != NULL ){ +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +EReceiveScore eScore ; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eScore . iPoints = m_iScore ; +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +penKiller -> SendEvent (eScore ); +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(CountAsKill ()) +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +{ +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +penKiller -> SendEvent (EKilledEnemy ()); +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +EComputerMessage eMsg ; +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eMsg . fnmMessage = GetComputerMessageName (); +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(eMsg . fnmMessage != ""){ +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +penKiller -> SendEvent (eMsg ); +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SendToTarget (m_penDeathTarget , m_eetDeathType , penKiller ); +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(m_penSpawnerTarget ){ +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SendToTarget (m_penSpawnerTarget , EET_TRIGGER , this ); +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CannonBlowUp (); +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Destroy (); +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Return(STATE_CURRENT,EVoid()); +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCannonStatic:: +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +RotateMuzzle(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonStatic_RotateMuzzle + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonStatic::RotateMuzzle expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT fDeltaP = m_fDesiredMuzzlePitch - m_aBeginMuzzleRotation (2); +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(Abs (fDeltaP ) < 5.0f){Return(STATE_CURRENT,EReturn ());return TRUE;} +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fRotSpeedMuzzle = ANGLE3D (0.0f , MUZZLE_ROTATION_SPEED * Sgn (fDeltaP ) , 0.0f); +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetTimerAfter(Abs (fDeltaP / MUZZLE_ROTATION_SPEED )); +Jump(STATE_CURRENT, 0x01590005, FALSE, EBegin());return TRUE;}BOOL CCannonStatic::H0x01590005_RotateMuzzle_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01590006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonStatic::H0x01590006_RotateMuzzle_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590006 +; +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fRotSpeedMuzzle = ANGLE3D (0.0f , 0.0f , 0.0f); +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +UpdateFiringPos (); +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Return(STATE_CURRENT,EReturn ()); +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCannonStatic:: +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FireCannon(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonStatic_FireCannon + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonStatic::FireCannon expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vToTarget = m_penEnemy -> GetPlacement () . pl_PositionVector - +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +GetPlacement () . pl_PositionVector + m_vFiringPos ; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +vToTarget . Normalize (); +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vCannonFront = FLOAT3D (0.0f , 0.0f , - 1.0f) * GetRotationMatrix (); +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +ANGLE aToPlayer = ACos (vToTarget % vCannonFront ); +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT fPitch = aToPlayer + 5.0f; +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vCannonUp = FLOAT3D (0.0 , 1.0f , 0.0f) * GetRotationMatrix (); +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(m_fDistanceToPlayer > m_fFiringRangeFar ){ +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Return(STATE_CURRENT,EReturn ()); +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return TRUE; +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +}else if(vToTarget % vCannonUp < 0.0f){ +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +fPitch = 5.0f; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +}else if(m_fDistanceToPlayer > m_fFiringRangeClose ){ +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(aToPlayer < m_fMaxPitch ){ +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +fPitch = aToPlayer + m_fMaxPitch * (m_fDistanceToPlayer - m_fFiringRangeClose ) / (m_fFiringRangeFar - m_fFiringRangeClose ); +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +}else if(TRUE ){ +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +fPitch = aToPlayer + 10.0f + m_fMaxPitch * (m_fDistanceToPlayer - m_fFiringRangeClose ) / (m_fFiringRangeFar - m_fFiringRangeClose ); +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +fPitch = Clamp (fPitch , 1.0f , 80.0f); +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +} +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_vTarget = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fDesiredMuzzlePitch = fPitch ; +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +STATE_CCannonStatic_RotateMuzzle, TRUE; +Jump(STATE_CURRENT, 0x01590008, FALSE, EBegin());return TRUE;}BOOL CCannonStatic::H0x01590008_FireCannon_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CCannonStatic_RotateMuzzle, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01590009, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CCannonStatic::H0x01590009_FireCannon_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590009 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vShooting = GetPlacement () . pl_PositionVector + m_vFiringPos ; +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vSpeedDest = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT fLaunchSpeed ; +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT fRelativeHdg ; +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CalculateAngularLaunchParams (vShooting , peiTarget -> vTargetCenter [ 1 ] - 6.0f / 3.0f , m_vTarget , +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +vSpeedDest , m_fDesiredMuzzlePitch , fLaunchSpeed , fRelativeHdg ); +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT3D vShootTarget ; +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +GetEntityInfoPosition (m_penEnemy , peiTarget -> vTargetCenter , vShootTarget ); +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CPlacement3D pl ; +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +PrepareFreeFlyingProjectile (pl , vShootTarget , m_vFiringPos , ANGLE3D (fRelativeHdg , m_fDesiredMuzzlePitch , 0)); +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CEntityPointer penBall = CreateEntity (pl , CLASS_CANNONBALL ); +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +ELaunchCannonBall eLaunch ; +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eLaunch . penLauncher = this ; +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eLaunch . fLaunchPower = fLaunchSpeed ; +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eLaunch . cbtType = CBT_IRON ; +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +eLaunch . fSize = 1.0f; +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +penBall -> Initialize (eLaunch ); +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Return(STATE_CURRENT,EReturn ()); +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCannonStatic:: +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +WatchPlayers(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonStatic_WatchPlayers + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonStatic::WatchPlayers expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Jump(STATE_CURRENT,0x01590013, FALSE, EInternal());return TRUE;}BOOL CCannonStatic::H0x01590013_WatchPlayers_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590013 +if(!(TRUE )){ Jump(STATE_CURRENT,0x01590014, FALSE, EInternal());return TRUE;} +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetTimerAfter(0.20f); +Jump(STATE_CURRENT, 0x0159000b, FALSE, EBegin());return TRUE;}BOOL CCannonStatic::H0x0159000b_WatchPlayers_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0159000c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonStatic::H0x0159000c_WatchPlayers_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000c +; +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CPlayer * pTarget = AcquireTarget (); +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(!(pTarget )){ Jump(STATE_CURRENT,0x01590012, FALSE, EInternal());return TRUE;} +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(!((pTarget -> GetFlags () & ENF_ALIVE ) && ! (pTarget -> GetFlags () & ENF_DELETED ))){ Jump(STATE_CURRENT,0x01590011, FALSE, EInternal());return TRUE;} +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_penEnemy = pTarget ; +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fDistanceToPlayer = DistanceTo (this , pTarget ); +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +STATE_CCannonStatic_FireCannon, TRUE; +Jump(STATE_CURRENT, 0x0159000d, FALSE, EBegin());return TRUE;}BOOL CCannonStatic::H0x0159000d_WatchPlayers_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CCannonStatic_FireCannon, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0159000e, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CCannonStatic::H0x0159000e_WatchPlayers_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000e +const EReturn&__e= (EReturn&)__eeInput; +; +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetTimerAfter(m_fShootingPeriod ); +Jump(STATE_CURRENT, 0x0159000f, FALSE, EBegin());return TRUE;}BOOL CCannonStatic::H0x0159000f_WatchPlayers_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01590010, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonStatic::H0x01590010_WatchPlayers_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590010 +;Jump(STATE_CURRENT,0x01590011, FALSE, EInternal());return TRUE;}BOOL CCannonStatic::H0x01590011_WatchPlayers_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590011 +Jump(STATE_CURRENT,0x01590012, FALSE, EInternal());return TRUE;}BOOL CCannonStatic::H0x01590012_WatchPlayers_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590012 +Jump(STATE_CURRENT,0x01590013, FALSE, EInternal());return TRUE; +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +}BOOL CCannonStatic::H0x01590014_WatchPlayers_10(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590014 + ASSERT(FALSE); return TRUE;};BOOL CCannonStatic:: +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Inactive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonStatic_Inactive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonStatic::Inactive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fRotSpeedMuzzle = ANGLE3D (0.0f , 0.0f , 0.0f); +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01590016, FALSE, EBegin());return TRUE;}BOOL CCannonStatic::H0x01590016_Inactive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590016 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Jump(STATE_CURRENT, STATE_CCannonStatic_MainLoop, TRUE, EVoid());return TRUE; +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Jump(STATE_CURRENT, STATE_CCannonStatic_Die, TRUE, eDeath );return TRUE; +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +}return TRUE;}BOOL CCannonStatic::H0x01590017_Inactive_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590017 + ASSERT(FALSE); return TRUE;};BOOL CCannonStatic:: +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCannonStatic_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCannonStatic::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +InitAsModel (); +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetCollisionFlags (ECF_MODEL ); +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +en_fDensity = 2000.0f; +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetModel (MODEL_TURRET ); +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetModelMainTexture (TEXTURE_TURRET ); +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +AddAttachment (TURRET_ATTACHMENT_CANNON , MODEL_CANNON , TEXTURE_CANNON ); +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fWalkSpeed = 0.0f; +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_aWalkRotateSpeed = 0.0f; +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fAttackRunSpeed = 0.0f; +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_aAttackRotateSpeed = 0.0f; +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fCloseRunSpeed = 0.0f; +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_aCloseRotateSpeed = 0.0f; +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fStopDistance = 100.0f; +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fBlowUpAmount = 100.0f; +#line 491 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fBodyParts = 4; +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fDamageWounded = 0.0f; +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_iScore = 750; +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_sptType = SPT_WOOD ; +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(m_fHealth <= 0.0f){m_fHealth = 1.0f;} +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +m_fCloseFireTime = m_fAttackFireTime = m_fShootingPeriod ; +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetHealth (m_fHealth );m_fMaxHealth = m_fHealth ; +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(m_fFiringRangeFar < m_fFiringRangeClose ){m_fFiringRangeFar = m_fFiringRangeClose + 1.0f;} +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fSize , m_fSize , m_fSize )); +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +ModelChangeNotify (); +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +StandingAnim (); +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x01590018, FALSE, EBegin());return TRUE;}BOOL CCannonStatic::H0x01590018_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590018 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01590019, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCannonStatic::H0x01590019_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590019 +; +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +UpdateFiringPos (); +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +if(! m_bActive ){Jump(STATE_CURRENT, STATE_CCannonStatic_Inactive, TRUE, EVoid());return TRUE;} +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Jump(STATE_CURRENT, STATE_CCannonStatic_MainLoop, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/CannonStatic.es b/Sources/EntitiesMP/CannonStatic.es new file mode 100644 index 0000000..af71f62 --- /dev/null +++ b/Sources/EntitiesMP/CannonStatic.es @@ -0,0 +1,518 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +345 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/CannonStatic/Turret.h" + +%} + +uses "EntitiesMP/ModelHolder2"; +uses "EntitiesMP/Projectile"; +uses "EntitiesMP/SoundHolder"; +uses "EntitiesMP/BloodSpray"; +uses "EntitiesMP/CannonBall"; + +%{ +#define CANNONS_SIZE 2.0f + +// info structure +static EntityInfo eiCannonStatic = { + EIBT_WOOD, 10000.0f, + 0.0f, 1.5f*CANNONS_SIZE, 0.0f, // source (eyes) + 0.0f, 0.5f*CANNONS_SIZE, 0.0f, // target (body) +}; + +#define FIRING_POSITION_MUZZLE FLOAT3D(0.0f, 0.4f, -1.0f) +#define MUZZLE_ROTATION_SPEED 45.0f //deg/sec + +%} + +class CCannonStatic: CEnemyBase { +name "CannonStatic"; +thumbnail "Thumbnails\\CannonStatic.tbn"; + +properties: + + 1 FLOAT m_fHealth "Cannon Health" = 100.0f, + 2 RANGE m_fFiringRangeClose "Cannon Firing Close Range" = 50.0f, + 3 RANGE m_fFiringRangeFar "Cannon Firing Far Range" = 150.0f, + 4 FLOAT m_fShootingPeriod "Cannon Shooting Period" = 5.0f, + 5 FLOAT m_fSize = CANNONS_SIZE, + 6 FLOAT m_fMaxPitch "Cannon Max Pitch" = 20.0f, + 7 FLOAT m_fViewAngle "Cannon View Angle" = 2.5f, + 8 BOOL m_bActive "Cannon Active" = TRUE, + + 20 FLOAT3D m_fRotSpeedMuzzle = ANGLE3D(0.0f, 0.0f, 0.0f), + 25 FLOAT m_fDistanceToPlayer = 0.0f, + 26 FLOAT m_fDesiredMuzzlePitch = 0.0f, + 27 INDEX m_iMuzzleDir = 1, + 28 FLOAT3D m_vFiringPos = FLOAT3D(0.0f, 0.0f, 0.0f), + 29 FLOAT3D m_vTarget = FLOAT3D(0.0f, 0.0f, 0.0f), + + 40 FLOAT3D m_aBeginMuzzleRotation = ANGLE3D(0.0f, 0.0f, 0.0f), + 41 FLOAT3D m_aEndMuzzleRotation = ANGLE3D(0.0f, 0.0f, 0.0f), + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + 2 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 3 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 4 class CLASS_CANNONBALL "Classes\\CannonBall.ecl", + //5 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + + // ************** CANNON MODEL ************** + 10 model MODEL_TURRET "ModelsMP\\Enemies\\CannonStatic\\Turret.mdl", + 11 model MODEL_CANNON "ModelsMP\\Enemies\\CannonStatic\\Cannon.mdl", + 20 texture TEXTURE_TURRET "ModelsMP\\Enemies\\CannonStatic\\Turret.tex", + 21 texture TEXTURE_CANNON "Models\\Weapons\\Cannon\\Body.tex", + + // ************** CANNON PARTS ************** + 30 model MODEL_DEBRIS_MUZZLE "ModelsMP\\Enemies\\CannonStatic\\Debris\\Cannon.mdl", + 31 model MODEL_DEBRIS_WHEEL "ModelsMP\\Enemies\\CannonStatic\\Debris\\Wheel.mdl", + 32 model MODEL_DEBRIS_WOOD "ModelsMP\\Enemies\\CannonStatic\\Debris\\Wood.mdl", + 35 model MODEL_BALL "Models\\Weapons\\Cannon\\Projectile\\CannonBall.mdl", + 36 texture TEXTURE_BALL "Models\\Weapons\\Cannon\\Projectile\\IronBall.tex", + + // ************** SOUNDS ************** + 50 sound SOUND_FIRE "ModelsMP\\Enemies\\CannonStatic\\Sounds\\Fire.wav", + +functions: + +virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("A Cannon killed %s"), strPlayerName); + return str; + } + + /* Entity info */ + void *GetEntityInfo(void) { + return &eiCannonStatic; + }; + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnmCannon, "DataMP\\Messages\\Enemies\\CannonStatic.txt"); + return fnmCannon; + }; + + void Precache(void) { + CEnemyBase::Precache(); + PrecacheModel(MODEL_DEBRIS_MUZZLE); + PrecacheModel(MODEL_DEBRIS_WHEEL); + PrecacheModel(MODEL_DEBRIS_WOOD); + PrecacheModel(MODEL_BALL); + + PrecacheTexture(TEXTURE_BALL); + + PrecacheSound(SOUND_FIRE); + + PrecacheClass(CLASS_CANNONBALL); + }; + + + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // take less damage from heavy bullets (e.g. sniper) + if(dmtType==DMT_BULLET && fDamageAmmount>100.0f) + { + fDamageAmmount*=0.5f; + } + + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, + vHitPoint, vDirection); + }; + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + return 0; + }; + + // death + INDEX AnimForDeath(void) { + return 0; + }; + + // cast a ray to entity checking only for brushes + BOOL IsVisible(CEntity *penEntity) + { + ASSERT(penEntity!=NULL); + // get ray source and target + FLOAT3D vSource, vTarget; + GetPositionCastRay(this, penEntity, vSource, vTarget); + + // cast the ray + CCastRay crRay(this, vSource, vTarget); + crRay.cr_ttHitModels = CCastRay::TT_NONE; // check for brushes only + crRay.cr_bHitTranslucentPortals = FALSE; + en_pwoWorld->CastRay(crRay); + + // if hit nothing (no brush) the entity can be seen + return (crRay.cr_penHit==NULL); + }; + + BOOL IsInTheLineOfFire(CEntity *penEntity, FLOAT fAngle) + { + ASSERT(penEntity!=NULL); + + FLOAT fCosAngle; + FLOAT3D vHeading; + FLOAT3D vToPlayer; + + FLOAT3D vSide = FLOAT3D(1.0f, 0.0f, 0.0f)*GetRotationMatrix(); + FLOAT3D vFront = FLOAT3D(0.0f, 0.0f, -1.0f)*GetRotationMatrix(); + vToPlayer = penEntity->GetPlacement().pl_PositionVector - GetPlacement().pl_PositionVector; + vToPlayer.Normalize(); + + fCosAngle = vToPlayer%vSide; + + // if on the firing plane + if (Abs(fCosAngle)0.0f) { + return TRUE; + } + } + return FALSE; + } + + CPlayer *AcquireTarget() { + // find actual number of players + INDEX ctMaxPlayers = GetMaxPlayers(); + CEntity *penPlayer; + + for(INDEX i=0; iInitialize(eSpawnEffect); + + // spawn shockwave + plExplosion = GetPlacement(); + penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNONSHOCKWAVE; + fSize = m_fBlowUpSize*1.0f; + eSpawnEffect.vStretch = FLOAT3D(fSize,fSize,fSize); + penExplosion->Initialize(eSpawnEffect); + + // hide yourself (must do this after spawning debris) + SwitchToEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + } + + void PreMoving() { + // manually update rotation of the attachments + UpdateAttachmentRotations(); + CEnemyBase::PreMoving(); + } + + void PostMoving() { + CEnemyBase::PostMoving(); + // make sure this entity stays in the moving list + SetFlags(GetFlags()&~ENF_INRENDERING); + } + + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) { + CAttachmentModelObject &amo0 = *GetModelObject()->GetAttachmentModel(TURRET_ATTACHMENT_CANNON); + // rotate to between-tick position + amo0.amo_plRelative.pl_OrientationAngle = Lerp(m_aBeginMuzzleRotation, m_aEndMuzzleRotation, _pTimer->GetLerpFactor()); + return CEnemyBase::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + }; + + void UpdateAttachmentRotations( void ) + { + // muzzle + m_aBeginMuzzleRotation = m_aEndMuzzleRotation; + m_aEndMuzzleRotation += m_fRotSpeedMuzzle*_pTimer->TickQuantum; + } + + void UpdateFiringPos() { + FLOATmatrix3D m; + // initial position + m_vFiringPos = FIRING_POSITION_MUZZLE*m_fSize; + + // pitch rotation + MakeRotationMatrixFast(m, m_aBeginMuzzleRotation); + m_vFiringPos = m_vFiringPos*m; + + // add translation + CAttachmentModelObject &amo0 = *GetModelObject()->GetAttachmentModel(TURRET_ATTACHMENT_CANNON); + m_vFiringPos += amo0.amo_plRelative.pl_PositionVector; + } + +procedures: + + MainLoop() { + wait() { + on (EBegin) : { + call WatchPlayers(); + resume; + } + on (EDeactivate) : { + jump Inactive(); + } + on (EDeath eDeath) : { + jump Die(eDeath); + } + }; + return; + }; + + + Die(EDeath eDeath) { + // not alive anymore + SetFlags(GetFlags()&~ENF_ALIVE); + + // find the one who killed, or other best suitable player + CEntityPointer penKiller = eDeath.eLastDamage.penInflictor; + if (penKiller==NULL || !IsOfClass(penKiller, "Player")) { + penKiller = m_penEnemy; + } + + if (penKiller==NULL || !IsOfClass(penKiller, "Player")) { + penKiller = FixupCausedToPlayer(this, penKiller, /*bWarning=*/FALSE); + } + + // if killed by someone + if (penKiller!=NULL) { + // give him score + EReceiveScore eScore; + eScore.iPoints = m_iScore; + penKiller->SendEvent(eScore); + if( CountAsKill()) + { + penKiller->SendEvent(EKilledEnemy()); + } + // send computer message + EComputerMessage eMsg; + eMsg.fnmMessage = GetComputerMessageName(); + if (eMsg.fnmMessage!="") { + penKiller->SendEvent(eMsg); + } + } + + // send event to death target + SendToTarget(m_penDeathTarget, m_eetDeathType, penKiller); + // send event to spawner if any + // NOTE: trigger's penCaused has been changed from penKiller to THIS; + if (m_penSpawnerTarget) { + SendToTarget(m_penSpawnerTarget, EET_TRIGGER, this); + } + + // spawn debris + CannonBlowUp(); + Destroy(); + return; + }; + + + RotateMuzzle() { + + FLOAT fDeltaP = m_fDesiredMuzzlePitch - m_aBeginMuzzleRotation(2); + + // if close enough to desired rotation, don't rotate + if (Abs(fDeltaP)<5.0f) { return EReturn(); } + + m_fRotSpeedMuzzle = ANGLE3D(0.0f, MUZZLE_ROTATION_SPEED*Sgn(fDeltaP), 0.0f); + autowait(Abs(fDeltaP/MUZZLE_ROTATION_SPEED)); + m_fRotSpeedMuzzle = ANGLE3D(0.0f, 0.0f, 0.0f); + UpdateFiringPos(); + + return EReturn(); + }; + + FireCannon() { + + FLOAT3D vToTarget = m_penEnemy->GetPlacement().pl_PositionVector - + GetPlacement().pl_PositionVector + m_vFiringPos; + vToTarget.Normalize(); + + // get vector pointing in heading direction of the muzzle + FLOAT3D vCannonFront = FLOAT3D(0.0f, 0.0f, -1.0f)*GetRotationMatrix(); + ANGLE aToPlayer = ACos(vToTarget%vCannonFront); + + FLOAT fPitch = aToPlayer + 5.0f; + FLOAT3D vCannonUp = FLOAT3D(0.0, 1.0f, 0.0f)*GetRotationMatrix(); + + // if too far, do not fire + if (m_fDistanceToPlayer>m_fFiringRangeFar) { + return EReturn(); + // if player under cannon, minimize pitch + } else if (vToTarget%vCannonUp<0.0f) { + fPitch = 5.0f; + // if in far range + } else if (m_fDistanceToPlayer>m_fFiringRangeClose) { + if (aToPlayerGetPlacement().pl_PositionVector; + + m_fDesiredMuzzlePitch = fPitch; + autocall RotateMuzzle() EReturn; + + FLOAT3D vShooting = GetPlacement().pl_PositionVector + m_vFiringPos; + FLOAT3D vSpeedDest = FLOAT3D(0.0f, 0.0f, 0.0f); + FLOAT fLaunchSpeed; + FLOAT fRelativeHdg; + + // calculate parameters for predicted angular launch curve + EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); + CalculateAngularLaunchParams( vShooting, peiTarget->vTargetCenter[1]-6.0f/3.0f, m_vTarget, + vSpeedDest, m_fDesiredMuzzlePitch , fLaunchSpeed, fRelativeHdg); + + // target enemy body + FLOAT3D vShootTarget; + GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget); + // launch + CPlacement3D pl; + PrepareFreeFlyingProjectile(pl, vShootTarget, m_vFiringPos, ANGLE3D( fRelativeHdg, m_fDesiredMuzzlePitch, 0)); + CEntityPointer penBall = CreateEntity(pl, CLASS_CANNONBALL); + ELaunchCannonBall eLaunch; + eLaunch.penLauncher = this; + eLaunch.fLaunchPower = fLaunchSpeed; + eLaunch.cbtType = CBT_IRON; + eLaunch.fSize = 1.0f; + penBall->Initialize(eLaunch); + + return EReturn(); + }; + + + WatchPlayers() + { + // this is a kind of 'sleep' mode - check to see if any player entered + // the attack radius every once in a while + while(TRUE) { + autowait(0.20f); + CPlayer *pTarget = AcquireTarget(); + if (pTarget) { + if ((pTarget->GetFlags()&ENF_ALIVE) && !(pTarget->GetFlags()&ENF_DELETED)) { + m_penEnemy = pTarget; + m_fDistanceToPlayer = DistanceTo(this, pTarget); + autocall FireCannon() EReturn; + autowait(m_fShootingPeriod); + } + } + } + } + + Inactive() + { + m_fRotSpeedMuzzle = ANGLE3D(0.0f, 0.0f, 0.0f); + wait() { + on (EBegin) : { resume; } + on (EActivate) : { + jump MainLoop(); + } + on (EDeath eDeath) : { + jump Die(eDeath); + } + otherwise (): { resume; } + } + } + + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + en_fDensity = 2000.0f; + + // set your appearance + SetModel(MODEL_TURRET); + SetModelMainTexture(TEXTURE_TURRET); + + AddAttachment(TURRET_ATTACHMENT_CANNON, MODEL_CANNON, TEXTURE_CANNON); + // setup moving speed + m_fWalkSpeed = 0.0f; + m_aWalkRotateSpeed = 0.0f; + m_fAttackRunSpeed = 0.0f; + m_aAttackRotateSpeed = 0.0f; + m_fCloseRunSpeed = 0.0f; + m_aCloseRotateSpeed = 0.0f; + // setup attack distances + m_fStopDistance = 100.0f; + //m_fBlowUpAmount = 65.0f; + m_fBlowUpAmount = 100.0f; + m_fBodyParts = 4; + m_fDamageWounded = 0.0f; + m_iScore = 750; + m_sptType = SPT_WOOD; + + // properties that modify EnemyBase properties + if (m_fHealth<=0.0f) { m_fHealth=1.0f; } + m_fCloseFireTime = m_fAttackFireTime = m_fShootingPeriod; + SetHealth(m_fHealth); m_fMaxHealth = m_fHealth; + if (m_fFiringRangeFarStretchModel(FLOAT3D(m_fSize, m_fSize, m_fSize)); + + ModelChangeNotify(); + StandingAnim(); + + // don't continue behavior in base class! - this enemy is derived + // from CEnemyBase only because of its properties + autowait(0.05f); + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + UpdateFiringPos(); + + if (!m_bActive) { jump Inactive(); } + jump MainLoop(); + + }; +}; diff --git a/Sources/EntitiesMP/CannonStatic.h b/Sources/EntitiesMP/CannonStatic.h new file mode 100644 index 0000000..7dd7b20 --- /dev/null +++ b/Sources/EntitiesMP/CannonStatic.h @@ -0,0 +1,131 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_CannonStatic_INCLUDED +#define _EntitiesMP_CannonStatic_INCLUDED 1 +#include +#include +#include +#include +#include +extern "C" DECL_DLL CDLLEntityClass CCannonStatic_DLLClass; +class CCannonStatic : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fHealth; + RANGE m_fFiringRangeClose; + RANGE m_fFiringRangeFar; + FLOAT m_fShootingPeriod; + FLOAT m_fSize; + FLOAT m_fMaxPitch; + FLOAT m_fViewAngle; + BOOL m_bActive; + FLOAT3D m_fRotSpeedMuzzle; + FLOAT m_fDistanceToPlayer; + FLOAT m_fDesiredMuzzlePitch; + INDEX m_iMuzzleDir; + FLOAT3D m_vFiringPos; + FLOAT3D m_vTarget; + FLOAT3D m_aBeginMuzzleRotation; + FLOAT3D m_aEndMuzzleRotation; + +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void * GetEntityInfo(void); + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void Precache(void); + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +INDEX AnimForDeath(void); + +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +BOOL IsVisible(CEntity * penEntity); + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +BOOL IsInTheLineOfFire(CEntity * penEntity,FLOAT fAngle); + +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +CPlayer * AcquireTarget(); + +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void CannonBlowUp(void); + +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void PreMoving(); + +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void PostMoving(); + +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void UpdateAttachmentRotations(void); + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +void UpdateFiringPos(); +#define STATE_CCannonStatic_MainLoop 0x01590000 + BOOL +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +MainLoop(const CEntityEvent &__eeInput); + BOOL H0x01590001_MainLoop_01(const CEntityEvent &__eeInput); + BOOL H0x01590002_MainLoop_02(const CEntityEvent &__eeInput); +#define STATE_CCannonStatic_Die 0x01590003 + BOOL +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Die(const CEntityEvent &__eeInput); +#define STATE_CCannonStatic_RotateMuzzle 0x01590004 + BOOL +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +RotateMuzzle(const CEntityEvent &__eeInput); + BOOL H0x01590005_RotateMuzzle_01(const CEntityEvent &__eeInput); + BOOL H0x01590006_RotateMuzzle_02(const CEntityEvent &__eeInput); +#define STATE_CCannonStatic_FireCannon 0x01590007 + BOOL +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FireCannon(const CEntityEvent &__eeInput); + BOOL H0x01590008_FireCannon_01(const CEntityEvent &__eeInput); + BOOL H0x01590009_FireCannon_02(const CEntityEvent &__eeInput); +#define STATE_CCannonStatic_WatchPlayers 0x0159000a + BOOL +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +WatchPlayers(const CEntityEvent &__eeInput); + BOOL H0x0159000b_WatchPlayers_01(const CEntityEvent &__eeInput); + BOOL H0x0159000c_WatchPlayers_02(const CEntityEvent &__eeInput); + BOOL H0x0159000d_WatchPlayers_03(const CEntityEvent &__eeInput); + BOOL H0x0159000e_WatchPlayers_04(const CEntityEvent &__eeInput); + BOOL H0x0159000f_WatchPlayers_05(const CEntityEvent &__eeInput); + BOOL H0x01590010_WatchPlayers_06(const CEntityEvent &__eeInput); + BOOL H0x01590011_WatchPlayers_07(const CEntityEvent &__eeInput); + BOOL H0x01590012_WatchPlayers_08(const CEntityEvent &__eeInput); + BOOL H0x01590013_WatchPlayers_09(const CEntityEvent &__eeInput); + BOOL H0x01590014_WatchPlayers_10(const CEntityEvent &__eeInput); +#define STATE_CCannonStatic_Inactive 0x01590015 + BOOL +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Inactive(const CEntityEvent &__eeInput); + BOOL H0x01590016_Inactive_01(const CEntityEvent &__eeInput); + BOOL H0x01590017_Inactive_02(const CEntityEvent &__eeInput); +#define STATE_CCannonStatic_Main 1 + BOOL +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01590018_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01590019_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_CannonStatic_INCLUDED diff --git a/Sources/EntitiesMP/CannonStatic_tables.h b/Sources/EntitiesMP/CannonStatic_tables.h new file mode 100644 index 0000000..4e46bce --- /dev/null +++ b/Sources/EntitiesMP/CannonStatic_tables.h @@ -0,0 +1,113 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CCannonStatic + +CEntityProperty CCannonStatic_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+1, offsetof(CCannonStatic, m_fHealth), "Cannon Health", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000159<<8)+2, offsetof(CCannonStatic, m_fFiringRangeClose), "Cannon Firing Close Range", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000159<<8)+3, offsetof(CCannonStatic, m_fFiringRangeFar), "Cannon Firing Far Range", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+4, offsetof(CCannonStatic, m_fShootingPeriod), "Cannon Shooting Period", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+5, offsetof(CCannonStatic, m_fSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+6, offsetof(CCannonStatic, m_fMaxPitch), "Cannon Max Pitch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+7, offsetof(CCannonStatic, m_fViewAngle), "Cannon View Angle", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000159<<8)+8, offsetof(CCannonStatic, m_bActive), "Cannon Active", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+20, offsetof(CCannonStatic, m_fRotSpeedMuzzle), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+25, offsetof(CCannonStatic, m_fDistanceToPlayer), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+26, offsetof(CCannonStatic, m_fDesiredMuzzlePitch), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000159<<8)+27, offsetof(CCannonStatic, m_iMuzzleDir), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+28, offsetof(CCannonStatic, m_vFiringPos), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+29, offsetof(CCannonStatic, m_vTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+40, offsetof(CCannonStatic, m_aBeginMuzzleRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000159<<8)+41, offsetof(CCannonStatic, m_aEndMuzzleRotation), "", 0, 0, 0), +}; +#define CCannonStatic_propertiesct ARRAYCOUNT(CCannonStatic_properties) + +CEntityComponent CCannonStatic_components[] = { +#define CLASS_BASE ((0x00000159<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000159<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_PROJECTILE ((0x00000159<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_CANNONBALL ((0x00000159<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_CANNONBALL, "EFNM" "Classes\\CannonBall.ecl"), +#define MODEL_TURRET ((0x00000159<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_TURRET, "EFNM" "ModelsMP\\Enemies\\CannonStatic\\Turret.mdl"), +#define MODEL_CANNON ((0x00000159<<8)+11) + CEntityComponent(ECT_MODEL, MODEL_CANNON, "EFNM" "ModelsMP\\Enemies\\CannonStatic\\Cannon.mdl"), +#define TEXTURE_TURRET ((0x00000159<<8)+20) + CEntityComponent(ECT_TEXTURE, TEXTURE_TURRET, "EFNM" "ModelsMP\\Enemies\\CannonStatic\\Turret.tex"), +#define TEXTURE_CANNON ((0x00000159<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_CANNON, "EFNM" "Models\\Weapons\\Cannon\\Body.tex"), +#define MODEL_DEBRIS_MUZZLE ((0x00000159<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS_MUZZLE, "EFNM" "ModelsMP\\Enemies\\CannonStatic\\Debris\\Cannon.mdl"), +#define MODEL_DEBRIS_WHEEL ((0x00000159<<8)+31) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS_WHEEL, "EFNM" "ModelsMP\\Enemies\\CannonStatic\\Debris\\Wheel.mdl"), +#define MODEL_DEBRIS_WOOD ((0x00000159<<8)+32) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS_WOOD, "EFNM" "ModelsMP\\Enemies\\CannonStatic\\Debris\\Wood.mdl"), +#define MODEL_BALL ((0x00000159<<8)+35) + CEntityComponent(ECT_MODEL, MODEL_BALL, "EFNM" "Models\\Weapons\\Cannon\\Projectile\\CannonBall.mdl"), +#define TEXTURE_BALL ((0x00000159<<8)+36) + CEntityComponent(ECT_TEXTURE, TEXTURE_BALL, "EFNM" "Models\\Weapons\\Cannon\\Projectile\\IronBall.tex"), +#define SOUND_FIRE ((0x00000159<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_FIRE, "EFNM" "ModelsMP\\Enemies\\CannonStatic\\Sounds\\Fire.wav"), +}; +#define CCannonStatic_componentsct ARRAYCOUNT(CCannonStatic_components) + +CEventHandlerEntry CCannonStatic_handlers[] = { + {0x01590000, -1, CEntity::pEventHandler(&CCannonStatic:: +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +MainLoop),DEBUGSTRING("CCannonStatic::MainLoop")}, + {0x01590001, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590001_MainLoop_01), DEBUGSTRING("CCannonStatic::H0x01590001_MainLoop_01")}, + {0x01590002, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590002_MainLoop_02), DEBUGSTRING("CCannonStatic::H0x01590002_MainLoop_02")}, + {0x01590003, -1, CEntity::pEventHandler(&CCannonStatic:: +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Die),DEBUGSTRING("CCannonStatic::Die")}, + {0x01590004, -1, CEntity::pEventHandler(&CCannonStatic:: +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +RotateMuzzle),DEBUGSTRING("CCannonStatic::RotateMuzzle")}, + {0x01590005, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590005_RotateMuzzle_01), DEBUGSTRING("CCannonStatic::H0x01590005_RotateMuzzle_01")}, + {0x01590006, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590006_RotateMuzzle_02), DEBUGSTRING("CCannonStatic::H0x01590006_RotateMuzzle_02")}, + {0x01590007, -1, CEntity::pEventHandler(&CCannonStatic:: +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +FireCannon),DEBUGSTRING("CCannonStatic::FireCannon")}, + {0x01590008, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590008_FireCannon_01), DEBUGSTRING("CCannonStatic::H0x01590008_FireCannon_01")}, + {0x01590009, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590009_FireCannon_02), DEBUGSTRING("CCannonStatic::H0x01590009_FireCannon_02")}, + {0x0159000a, -1, CEntity::pEventHandler(&CCannonStatic:: +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +WatchPlayers),DEBUGSTRING("CCannonStatic::WatchPlayers")}, + {0x0159000b, -1, CEntity::pEventHandler(&CCannonStatic::H0x0159000b_WatchPlayers_01), DEBUGSTRING("CCannonStatic::H0x0159000b_WatchPlayers_01")}, + {0x0159000c, -1, CEntity::pEventHandler(&CCannonStatic::H0x0159000c_WatchPlayers_02), DEBUGSTRING("CCannonStatic::H0x0159000c_WatchPlayers_02")}, + {0x0159000d, -1, CEntity::pEventHandler(&CCannonStatic::H0x0159000d_WatchPlayers_03), DEBUGSTRING("CCannonStatic::H0x0159000d_WatchPlayers_03")}, + {0x0159000e, -1, CEntity::pEventHandler(&CCannonStatic::H0x0159000e_WatchPlayers_04), DEBUGSTRING("CCannonStatic::H0x0159000e_WatchPlayers_04")}, + {0x0159000f, -1, CEntity::pEventHandler(&CCannonStatic::H0x0159000f_WatchPlayers_05), DEBUGSTRING("CCannonStatic::H0x0159000f_WatchPlayers_05")}, + {0x01590010, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590010_WatchPlayers_06), DEBUGSTRING("CCannonStatic::H0x01590010_WatchPlayers_06")}, + {0x01590011, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590011_WatchPlayers_07), DEBUGSTRING("CCannonStatic::H0x01590011_WatchPlayers_07")}, + {0x01590012, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590012_WatchPlayers_08), DEBUGSTRING("CCannonStatic::H0x01590012_WatchPlayers_08")}, + {0x01590013, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590013_WatchPlayers_09), DEBUGSTRING("CCannonStatic::H0x01590013_WatchPlayers_09")}, + {0x01590014, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590014_WatchPlayers_10), DEBUGSTRING("CCannonStatic::H0x01590014_WatchPlayers_10")}, + {0x01590015, -1, CEntity::pEventHandler(&CCannonStatic:: +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Inactive),DEBUGSTRING("CCannonStatic::Inactive")}, + {0x01590016, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590016_Inactive_01), DEBUGSTRING("CCannonStatic::H0x01590016_Inactive_01")}, + {0x01590017, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590017_Inactive_02), DEBUGSTRING("CCannonStatic::H0x01590017_Inactive_02")}, + {1, -1, CEntity::pEventHandler(&CCannonStatic:: +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/CannonStatic.es" +Main),DEBUGSTRING("CCannonStatic::Main")}, + {0x01590018, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590018_Main_01), DEBUGSTRING("CCannonStatic::H0x01590018_Main_01")}, + {0x01590019, -1, CEntity::pEventHandler(&CCannonStatic::H0x01590019_Main_02), DEBUGSTRING("CCannonStatic::H0x01590019_Main_02")}, +}; +#define CCannonStatic_handlersct ARRAYCOUNT(CCannonStatic_handlers) + +CEntity *CCannonStatic_New(void) { return new CCannonStatic; }; +void CCannonStatic_OnInitClass(void) {}; +void CCannonStatic_OnEndClass(void) {}; +void CCannonStatic_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CCannonStatic_OnWorldEnd(CWorld *pwo) {}; +void CCannonStatic_OnWorldInit(CWorld *pwo) {}; +void CCannonStatic_OnWorldTick(CWorld *pwo) {}; +void CCannonStatic_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CCannonStatic, CEnemyBase, "CannonStatic", "Thumbnails\\CannonStatic.tbn", 0x00000159); +DECLARE_CTFILENAME(_fnmCCannonStatic_tbn, "Thumbnails\\CannonStatic.tbn"); diff --git a/Sources/EntitiesMP/ChainsawFreak.cpp b/Sources/EntitiesMP/ChainsawFreak.cpp new file mode 100644 index 0000000..5abd412 --- /dev/null +++ b/Sources/EntitiesMP/ChainsawFreak.cpp @@ -0,0 +1,631 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/ChainSawFreak/Freak.h" +#include "ModelsMP/Enemies/ChainSawFreak/Saw.h" + +#include +#include +#line 13 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" + +#define FREAK_SIZE 1.05f + +// info structure +static EntityInfo eiChainsawFreak = { + EIBT_FLESH, 350.0f, + 0.0f, 2.5f*FREAK_SIZE, 0.0f, // source (eyes) + 0.0f, 1.5f*FREAK_SIZE, 0.0f, // target (body) +}; + +#define HIT_DISTANCE 4.0f + +void CChainsawFreak::SetDefaultProperties(void) { + m_bRunAttack = FALSE ; + m_bSawHit = FALSE ; + m_penLastTouched = NULL; + m_soFeet.SetOwner(this); +m_soFeet.Stop_internal(); + m_bRunSoundPlaying = FALSE ; + m_iRunType = 0; + m_bAttacking = FALSE ; + m_fSightSoundBegin = 0.0f; + CEnemyRunInto::SetDefaultProperties(); +} + CTString CChainsawFreak::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +{ +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +CTString str ; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +str . PrintF (TRANS ("Chainsaw freak dismembered %s") , strPlayerName ); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +return str ; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::Precache(void) { +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +CEnemyBase :: Precache (); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PrecacheSound (SOUND_IDLE ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PrecacheSound (SOUND_RUN ); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PrecacheSound (SOUND_ATTACK ); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PrecacheSound (SOUND_WOUND ); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PrecacheSound (SOUND_DEATH ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PrecacheSound (SOUND_SIGHT ); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void * CChainsawFreak::GetEntityInfo(void) { +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +return & eiChainsawFreak ; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT CChainsawFreak::GetCrushHealth(void) +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +{ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +return 60.0f; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + const CTFileName & CChainsawFreak::GetComputerMessageName(void)const { +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +static DECLARE_CTFILENAME (fnm , "DataMP\\Messages\\Enemies\\ChainsawFreak.txt"); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +return fnm ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +{ +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(! IsOfClass (penInflictor , "ChainsawFreak")){ +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::AdjustDifficulty(void) +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +{ +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +INDEX CChainsawFreak::AnimForDeath(void) { +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +INDEX iAnim ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(en_vCurrentTranslationAbsolute . Length () > 5.0f){ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +iAnim = FREAK_ANIM_DEATHRUN ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +}else { +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +iAnim = FREAK_ANIM_DEATHSTAND ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +ChangeCollisionBoxIndexWhenPossible (FREAK_COLLISION_BOX_DEATHRUN ); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StartModelAnim (iAnim , 0); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_bAttacking = FALSE ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +DeactivateRunningSound (); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +return iAnim ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT CChainsawFreak::WaitForDust(FLOAT3D & vStretch) { +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(GetModelObject () -> GetAnim () == FREAK_ANIM_DEATHRUN ) +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +{ +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vStretch = FLOAT3D (1 , 1 , 2) * 1.0f; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +return 0.65f; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +else if(GetModelObject () -> GetAnim () == FREAK_ANIM_DEATHSTAND ) +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +{ +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vStretch = FLOAT3D (1 , 1 , 2) * 1.5f; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +return 0.72f; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +return - 1.0f; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::DeathNotify() { +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +ChangeCollisionBoxIndexWhenPossible (FREAK_COLLISION_BOX_DEATH ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetCollisionFlags (ECF_MODEL ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::StandingAnim(void) { +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StartModelAnim (FREAK_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::WalkingAnim(void) { +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StartModelAnim (FREAK_ANIM_WALK , AOF_LOOPING | AOF_NORESTART ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::RunningAnim(void) { +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +switch(m_iRunType ) +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +{ +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +case 0: +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StartModelAnim (FREAK_ANIM_ATTACKRUN , AOF_LOOPING | AOF_NORESTART ); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +break ; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +case 1: +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StartModelAnim (FREAK_ANIM_ATTACKRUNFAR , AOF_LOOPING | AOF_NORESTART ); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +break ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +case 2: +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StartModelAnim (FREAK_ANIM_ATTACKCHARGE , AOF_LOOPING | AOF_NORESTART ); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +break ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +default : +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +ASSERTALWAYS ("Unknown Chainsaw freak run type!"); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::ChargeAnim(void) { +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StartModelAnim (FREAK_ANIM_RUNSLASHING , AOF_LOOPING | AOF_NORESTART ); +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::RotatingAnim(void) { +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_iRunType = IRnd () % 3; +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StartModelAnim (FREAK_ANIM_ATTACKSTART , AOF_LOOPING | AOF_NORESTART ); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::IdleSound(void) { +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::WoundSound(void) { +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::DeathSound(void) { +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::ActivateRunningSound(void) +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +{ +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(! m_bRunSoundPlaying ){ +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PlaySound (m_soFeet , SOUND_RUN , SOF_3D | SOF_LOOP ); +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_bRunSoundPlaying = TRUE ; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::DeactivateRunningSound(void) +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +{ +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_soFeet . Stop (); +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_bRunSoundPlaying = FALSE ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::LiveEntityTouched(ETouch etouch) { +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(m_penLastTouched != etouch . penOther || _pTimer -> CurrentTick () >= m_fLastTouchedTime + 0.25f){ +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT3D vDirection = en_vCurrentTranslationAbsolute ; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vDirection . Normalize (); +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +ANGLE aHitAngle = FLOAT3D (etouch . plCollision ) % vDirection ; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(aHitAngle < 0.0f){ +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(! IsOfSameClass (this , etouch . penOther )){ +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +IncreaseKickedMass (etouch . penOther ); +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PlaySound (m_soSound , SOUND_ATTACK , SOF_3D ); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_penLastTouched = etouch . penOther ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fLastTouchedTime = _pTimer -> CurrentTick (); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vDirection . Normalize (); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +InflictDirectDamage (etouch . penOther , this , DMT_CHAINSAW , - aHitAngle * 40.0f , +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT3D (0 , 0 , 0) , vDirection ); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT3D vSpeed = - FLOAT3D (etouch . plCollision ); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vSpeed = vSpeed * 10.0f; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +const FLOATmatrix3D & m = GetRotationMatrix (); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT3D vSpeedRel = vSpeed * ! m ; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(vSpeedRel (1) < - 0.1f){ +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vSpeedRel (1) -= 5.0f; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +}else { +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vSpeedRel (1) += 5.0f; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vSpeedRel (2) = 5.0f; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vSpeed = vSpeedRel * m ; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +KickEntity (etouch . penOther , vSpeed ); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +BOOL CChainsawFreak::HigherMass(void) { +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +return (m_fMassKicked > 500.0f); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::EnemyPostInit(void) +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +{ +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_soFeet . Set3DParameters (500.0f , 50.0f , 1.0f , 1.0f); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_bRunSoundPlaying = FALSE ; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_soSound . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} + +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void CChainsawFreak::PreMoving() { +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(! m_bRunSoundPlaying && _pTimer -> CurrentTick () > m_fSightSoundBegin + 2.0f && m_bAttacking ) +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +{ +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +ActivateRunningSound (); +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +CEnemyBase :: PreMoving (); +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +BOOL CChainsawFreak:: +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CChainsawFreak_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CChainsawFreak::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(!(CalcDist (m_penEnemy ) < HIT_DISTANCE )){ Jump(STATE_CURRENT,0x01560009, FALSE, EInternal());return TRUE;} +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StartModelAnim (FREAK_ANIM_ATTACKSLASH , 0); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT3D vDir = (m_penEnemy -> GetPlacement () . pl_PositionVector - +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +GetPlacement () . pl_PositionVector ) . Normalize (); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vDir *= ! GetRotationMatrix (); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vDir *= m_fCloseRunSpeed * 1.5f; +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vDir (2) = 1.0f; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +GiveImpulseTranslationRelative (vDir ); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_bSawHit = FALSE ; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetTimerAfter(0.4f); +Jump(STATE_CURRENT, 0x01560001, FALSE, EBegin());return TRUE;}BOOL CChainsawFreak::H0x01560001_Hit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01560001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01560002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CChainsawFreak::H0x01560002_Hit_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01560002 +; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PlaySound (m_soSound , SOUND_ATTACK , SOF_3D ); +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(CalcDist (m_penEnemy ) < HIT_DISTANCE ){m_bSawHit = TRUE ;} +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x01560003, FALSE, EBegin());return TRUE;}BOOL CChainsawFreak::H0x01560003_Hit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01560003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01560004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CChainsawFreak::H0x01560004_Hit_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01560004 +; +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(CalcDist (m_penEnemy ) < HIT_DISTANCE ){m_bSawHit = TRUE ;} +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x01560005, FALSE, EBegin());return TRUE;}BOOL CChainsawFreak::H0x01560005_Hit_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01560005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01560006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CChainsawFreak::H0x01560006_Hit_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01560006 +; +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(CalcDist (m_penEnemy ) < HIT_DISTANCE ){m_bSawHit = TRUE ;} +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(m_bSawHit ){ +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vDirection . Normalize (); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +InflictDirectDamage (m_penEnemy , this , DMT_CHAINSAW , 20.0f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vDirection = vDirection * 10.0f; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOATmatrix3D mDirection ; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +MakeRotationMatrixFast (mDirection , ANGLE3D (0.0f , 30.0f , 0.0f)); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +vDirection = vDirection * mDirection ; +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +KickEntity (m_penEnemy , vDirection ); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetTimerAfter(0.6f); +Jump(STATE_CURRENT, 0x01560007, FALSE, EBegin());return TRUE;}BOOL CChainsawFreak::H0x01560007_Hit_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01560007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01560008, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CChainsawFreak::H0x01560008_Hit_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01560008 +;Jump(STATE_CURRENT,0x01560009, FALSE, EInternal());return TRUE;}BOOL CChainsawFreak::H0x01560009_Hit_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01560009 + +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fShootTime = _pTimer -> CurrentTick () + 0.5f; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +Return(STATE_CURRENT,EReturn ()); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CChainsawFreak:: +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +AttackEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CChainsawFreak_AttackEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CChainsawFreak::AttackEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_bAttacking = TRUE ; +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D | SOF_SMOOTHCHANGE ); +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fSightSoundBegin = _pTimer -> CurrentTick (); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_AttackEnemy, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CChainsawFreak:: +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +BeIdle(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CChainsawFreak_BeIdle + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CChainsawFreak::BeIdle expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_bAttacking = FALSE ; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +DeactivateRunningSound (); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_BeIdle, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CChainsawFreak:: +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PostRunAwayFromEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CChainsawFreak_PostRunAwayFromEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CChainsawFreak::PostRunAwayFromEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StartModelAnim (FREAK_ANIM_ATTACKRUNFAR , 0); +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x0156000d, FALSE, EBegin());return TRUE;}BOOL CChainsawFreak::H0x0156000d_PostRunAwayFromEnemy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0156000d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0156000e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CChainsawFreak::H0x0156000e_PostRunAwayFromEnemy_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0156000e +; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetDesiredTranslation (FLOAT3D (0 , 0 , 0)); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StartModelAnim (FREAK_ANIM_IDLE , 0); +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x0156000f, FALSE, EBegin());return TRUE;}BOOL CChainsawFreak::H0x0156000f_PostRunAwayFromEnemy_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0156000f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01560010, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CChainsawFreak::H0x01560010_PostRunAwayFromEnemy_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01560010 +; +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +Return(STATE_CURRENT,EReturn ()); +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CChainsawFreak:: +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CChainsawFreak_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CChainsawFreak::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +InitAsModel (); +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetCollisionFlags (ECF_MODEL ); +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetHealth (175.0f); +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fMaxHealth = 175.0f; +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +en_fDensity = 2000.0f; +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetModel (MODEL_FREAK ); +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +SetModelMainTexture (TEXTURE_FREAK ); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +AddAttachment (FREAK_ATTACHMENT_CHAINSAW , MODEL_CHAINSAW , TEXTURE_CHAINSAW ); +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +StandingAnim (); +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fWalkSpeed = FRnd () + 2.5f; +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 25.0f + 45.0f); +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fAttackRunSpeed = FRnd () * 2.0f + 13.0f; +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fAttackRotateRunInto = AngleDeg (FRnd () * 30 + 50.0f); +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_aAttackRotateSpeed = m_fAttackRotateRunInto ; +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fCloseRunSpeed = FRnd () + 10.5f; +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 250.0f); +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fAttackDistance = 50.0f; +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fCloseDistance = 7.0f; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fStopDistance = 0.0f; +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fAttackFireTime = 0.05f; +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fCloseFireTime = 1.0f; +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fIgnoreRange = 150.0f; +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fBlowUpAmount = 1E10f; +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fBodyParts = 6; +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fDamageWounded = 100000.0f; +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_iScore = 1500; +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +if(m_fStepHeight == - 1){ +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fStepHeight = 4.0f; +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +} +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fStopApproachDistance = 0.0f; +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +ASSERT (m_fStopApproachDistance < m_fCloseDistance ); +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_bUseChargeAnimation = TRUE ; +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fChargeDistance = 20.0f; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_fInertionRunTime = 0.15f; +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_iRunType = IRnd () % 3; +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +GetModelObject () -> StretchModel (FLOAT3D (FREAK_SIZE , FREAK_SIZE , FREAK_SIZE )); +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +ModelChangeNotify (); +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +m_bAttacking = FALSE ; +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +Jump(STATE_CURRENT, STATE_CEnemyRunInto_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ChainsawFreak.es b/Sources/EntitiesMP/ChainsawFreak.es new file mode 100644 index 0000000..e7f2b29 --- /dev/null +++ b/Sources/EntitiesMP/ChainsawFreak.es @@ -0,0 +1,402 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +342 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/ChainSawFreak/Freak.h" +#include "ModelsMP/Enemies/ChainSawFreak/Saw.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/EnemyRunInto"; + +%{ +#define FREAK_SIZE 1.05f + +// info structure +static EntityInfo eiChainsawFreak = { + EIBT_FLESH, 350.0f, + 0.0f, 2.5f*FREAK_SIZE, 0.0f, // source (eyes) + 0.0f, 1.5f*FREAK_SIZE, 0.0f, // target (body) +}; + +#define HIT_DISTANCE 4.0f +%} + + +class CChainsawFreak : CEnemyRunInto { +name "ChainsawFreak"; +thumbnail "Thumbnails\\ChainsawFreak.tbn"; + +properties: + 1 BOOL m_bRunAttack = FALSE, // run attack (attack local) + 2 BOOL m_bSawHit = FALSE, // close attack local + 3 CEntityPointer m_penLastTouched, // last touched + 4 CSoundObject m_soFeet, // for running sound + 5 BOOL m_bRunSoundPlaying = FALSE, + 6 INDEX m_iRunType = 0, // which running animation? + + 10 BOOL m_bAttacking = FALSE, + 11 FLOAT m_fSightSoundBegin = 0.0f, // when sight sound was played + +components: + 0 class CLASS_BASE "Classes\\EnemyRunInto.ecl", + 1 model MODEL_FREAK "ModelsMP\\Enemies\\ChainsawFreak\\Freak.mdl", + 2 model MODEL_CHAINSAW "ModelsMP\\Enemies\\ChainsawFreak\\Saw.mdl", + 3 texture TEXTURE_FREAK "ModelsMP\\Enemies\\ChainsawFreak\\Freak.tex", + 4 texture TEXTURE_CHAINSAW "ModelsMP\\Enemies\\ChainsawFreak\\Saw.tex", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Idle.wav", + 51 sound SOUND_RUN "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Run.wav", +// 53 sound SOUND_RUNATTACK "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\RunAttack.wav", + 54 sound SOUND_ATTACK "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Attack.wav", + 55 sound SOUND_WOUND "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Wound.wav", + 56 sound SOUND_DEATH "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Death.wav", + 57 sound SOUND_SIGHT "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Sight.wav", + +functions: + + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("Chainsaw freak dismembered %s"), strPlayerName); + return str; + } + + void Precache(void) { + CEnemyBase::Precache(); + PrecacheSound(SOUND_IDLE ); + PrecacheSound(SOUND_RUN ); +// PrecacheSound(SOUND_RUNATTACK); + PrecacheSound(SOUND_ATTACK ); + PrecacheSound(SOUND_WOUND ); + PrecacheSound(SOUND_DEATH ); + PrecacheSound(SOUND_SIGHT ); + }; + + /* Entity info */ + void *GetEntityInfo(void) { + return &eiChainsawFreak; + }; + + FLOAT GetCrushHealth(void) + { + return 60.0f; + } + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnm, "DataMP\\Messages\\Enemies\\ChainsawFreak.txt"); + return fnm; + }; + + // render particles + /*void RenderParticles(void) + { + Particles_RunningDust(this); + }*/ + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // note: chainsawfreaks can't hurt each others + if (!IsOfClass(penInflictor, "ChainsawFreak")) { + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + }; + + void AdjustDifficulty(void) + { + // chainsaw freak must not change his speed at different difficulties + } + + // death + INDEX AnimForDeath(void) { + INDEX iAnim; + if (en_vCurrentTranslationAbsolute.Length()>5.0f) { + iAnim = FREAK_ANIM_DEATHRUN; + } else { + iAnim = FREAK_ANIM_DEATHSTAND; + } + ChangeCollisionBoxIndexWhenPossible(FREAK_COLLISION_BOX_DEATHRUN); + StartModelAnim(iAnim, 0); + m_bAttacking = FALSE; + DeactivateRunningSound(); + return iAnim; + }; + + FLOAT WaitForDust(FLOAT3D &vStretch) { + if(GetModelObject()->GetAnim()==FREAK_ANIM_DEATHRUN) + { + vStretch=FLOAT3D(1,1,2)*1.0f; + return 0.65f; + } + else if(GetModelObject()->GetAnim()==FREAK_ANIM_DEATHSTAND) + { + vStretch=FLOAT3D(1,1,2)*1.5f; + return 0.72f; + } + return -1.0f; + }; + + void DeathNotify() { + ChangeCollisionBoxIndexWhenPossible(FREAK_COLLISION_BOX_DEATH); + SetCollisionFlags(ECF_MODEL); + }; + + // virtual anim functions + void StandingAnim(void) { + StartModelAnim(FREAK_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + //DeactivateRunningSound(); + }; + void WalkingAnim(void) { + StartModelAnim(FREAK_ANIM_WALK, AOF_LOOPING|AOF_NORESTART); + //DeactivateRunningSound(); + }; + void RunningAnim(void) { + switch(m_iRunType) + { + case 0: + StartModelAnim(FREAK_ANIM_ATTACKRUN, AOF_LOOPING|AOF_NORESTART); + break; + case 1: + StartModelAnim(FREAK_ANIM_ATTACKRUNFAR, AOF_LOOPING|AOF_NORESTART); + break; + case 2: + StartModelAnim(FREAK_ANIM_ATTACKCHARGE, AOF_LOOPING|AOF_NORESTART); + break; + default: + ASSERTALWAYS("Unknown Chainsaw freak run type!"); + } + //ActivateRunningSound(); + }; + void ChargeAnim(void) { + StartModelAnim(FREAK_ANIM_RUNSLASHING, AOF_LOOPING|AOF_NORESTART); + }; + void RotatingAnim(void) { + m_iRunType = IRnd()%3; + StartModelAnim(FREAK_ANIM_ATTACKSTART, AOF_LOOPING|AOF_NORESTART); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + /*void SightSound(void) { + PlaySound(m_soFeet, SOUND_SIGHT, SOF_3D|SOF_SMOOTHCHANGE); + };*/ + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + // running sounds + void ActivateRunningSound(void) + { + if (!m_bRunSoundPlaying) { + PlaySound(m_soFeet, SOUND_RUN, SOF_3D|SOF_LOOP); + m_bRunSoundPlaying = TRUE; + } + } + void DeactivateRunningSound(void) + { + m_soFeet.Stop(); + m_bRunSoundPlaying = FALSE; + } + + +/************************************************************ + * ATTACK FUNCTIONS * + ************************************************************/ + // touched another live entity + void LiveEntityTouched(ETouch etouch) { + if (m_penLastTouched!=etouch.penOther || _pTimer->CurrentTick()>=m_fLastTouchedTime+0.25f) { + // hit angle + FLOAT3D vDirection = en_vCurrentTranslationAbsolute; + vDirection.Normalize(); + ANGLE aHitAngle = FLOAT3D(etouch.plCollision)%vDirection; + // only hit target in front of you + if (aHitAngle < 0.0f) { + // increase mass - only if not another bull + if (!IsOfSameClass(this, etouch.penOther)) { + IncreaseKickedMass(etouch.penOther); + } + PlaySound(m_soSound, SOUND_ATTACK, SOF_3D); + // store last touched + m_penLastTouched = etouch.penOther; + m_fLastTouchedTime = _pTimer->CurrentTick(); + // damage + FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.Normalize(); + InflictDirectDamage(etouch.penOther, this, DMT_CHAINSAW, -aHitAngle*40.0f, + FLOAT3D(0, 0, 0), vDirection); + // kick touched entity + FLOAT3D vSpeed = -FLOAT3D(etouch.plCollision); + vSpeed = vSpeed*10.0f; + const FLOATmatrix3D &m = GetRotationMatrix(); + FLOAT3D vSpeedRel = vSpeed*!m; + if (vSpeedRel(1)<-0.1f) { + vSpeedRel(1)-=5.0f; + } else { + vSpeedRel(1)+=5.0f; + } + vSpeedRel(2)=5.0f; + + vSpeed = vSpeedRel*m; + KickEntity(etouch.penOther, vSpeed); + } + } + }; + + // touched entity with higher mass + BOOL HigherMass(void) { + return (m_fMassKicked > 500.0f); + }; + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + // set sound default parameters + m_soFeet.Set3DParameters(500.0f, 50.0f, 1.0f, 1.0f); + m_bRunSoundPlaying = FALSE; + m_soSound.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + }; + + void PreMoving() { + if (!m_bRunSoundPlaying && _pTimer->CurrentTick()>m_fSightSoundBegin+2.0f && m_bAttacking) + { + ActivateRunningSound(); + } + CEnemyBase::PreMoving(); + }; + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + // hit enemy + Hit(EVoid) : CEnemyBase::Hit { + if (CalcDist(m_penEnemy) < HIT_DISTANCE) { + // attack with saw + StartModelAnim(FREAK_ANIM_ATTACKSLASH, 0); + // jump + FLOAT3D vDir = (m_penEnemy->GetPlacement().pl_PositionVector - + GetPlacement().pl_PositionVector).Normalize(); + vDir *= !GetRotationMatrix(); + vDir *= m_fCloseRunSpeed*1.5f; + vDir(2) = 1.0f; + + GiveImpulseTranslationRelative(vDir); + + //DeactivateRunningSound(); + m_bSawHit = FALSE; + autowait(0.4f); + PlaySound(m_soSound, SOUND_ATTACK, SOF_3D); + if (CalcDist(m_penEnemy) < HIT_DISTANCE) { m_bSawHit = TRUE; } + autowait(0.1f); + if (CalcDist(m_penEnemy) < HIT_DISTANCE) { m_bSawHit = TRUE; } + autowait(0.1f); + if (CalcDist(m_penEnemy) < HIT_DISTANCE) { m_bSawHit = TRUE; } + if (m_bSawHit) { + FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.Normalize(); + InflictDirectDamage(m_penEnemy, this, DMT_CHAINSAW, 20.0f, FLOAT3D(0, 0, 0), vDirection); + + vDirection = vDirection * 10.0f; + //GetPitchDirection(AngleDeg(90.0f), vSpeed); + FLOATmatrix3D mDirection; + MakeRotationMatrixFast(mDirection, ANGLE3D(0.0f, 30.0f, 0.0f)); + vDirection = vDirection * mDirection; + KickEntity(m_penEnemy, vDirection); + } + autowait(0.6f); + } + + // run to enemy + m_fShootTime = _pTimer->CurrentTick() + 0.5f; + return EReturn(); + }; + + AttackEnemy(EVoid) : CEnemyBase::AttackEnemy { + m_bAttacking = TRUE; + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D|SOF_SMOOTHCHANGE); + m_fSightSoundBegin = _pTimer->CurrentTick(); + jump CEnemyBase::AttackEnemy(); + } + + BeIdle(EVoid) : CEnemyBase::BeIdle { + m_bAttacking = FALSE; + DeactivateRunningSound(); + jump CEnemyBase::BeIdle(); + } + + + PostRunAwayFromEnemy(EVoid) : CEnemyRunInto::PostRunAwayFromEnemy { + StartModelAnim(FREAK_ANIM_ATTACKRUNFAR, 0); + autowait(0.25f); + SetDesiredTranslation(FLOAT3D(0,0,0)); + StartModelAnim(FREAK_ANIM_IDLE, 0); + autowait(0.25f); + return EReturn(); + }; + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + SetHealth(175.0f); + m_fMaxHealth = 175.0f; + en_fDensity = 2000.0f; + // set your appearance + SetModel(MODEL_FREAK); + SetModelMainTexture(TEXTURE_FREAK); + AddAttachment(FREAK_ATTACHMENT_CHAINSAW, MODEL_CHAINSAW, TEXTURE_CHAINSAW); + StandingAnim(); + // setup moving speed + m_fWalkSpeed = FRnd() + 2.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*25.0f + 45.0f); + m_fAttackRunSpeed = FRnd()*2.0f + 13.0f; + m_fAttackRotateRunInto = AngleDeg(FRnd()*30 + 50.0f); + m_aAttackRotateSpeed = m_fAttackRotateRunInto; + m_fCloseRunSpeed = FRnd() + 10.5f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 250.0f); + // setup attack distances + m_fAttackDistance = 50.0f; + m_fCloseDistance = 7.0f; + m_fStopDistance = 0.0f; + m_fAttackFireTime = 0.05f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 150.0f; + // damage/explode properties6 + m_fBlowUpAmount = 1E10f; + m_fBodyParts = 6; + m_fDamageWounded = 100000.0f; + m_iScore = 1500; + if (m_fStepHeight==-1) { + m_fStepHeight = 4.0f; + } + m_fStopApproachDistance = 0.0f; + ASSERT(m_fStopApproachDistanceStretchModel(FLOAT3D(FREAK_SIZE, FREAK_SIZE, FREAK_SIZE)); + ModelChangeNotify(); + + m_bAttacking = FALSE; + + // continue behavior in base class + jump CEnemyRunInto::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/ChainsawFreak.h b/Sources/EntitiesMP/ChainsawFreak.h new file mode 100644 index 0000000..f8dc6d6 --- /dev/null +++ b/Sources/EntitiesMP/ChainsawFreak.h @@ -0,0 +1,129 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ChainsawFreak_INCLUDED +#define _EntitiesMP_ChainsawFreak_INCLUDED 1 +#include +#include +extern "C" DECL_DLL CDLLEntityClass CChainsawFreak_DLLClass; +class CChainsawFreak : public CEnemyRunInto { +public: + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bRunAttack; + BOOL m_bSawHit; + CEntityPointer m_penLastTouched; + CSoundObject m_soFeet; + BOOL m_bRunSoundPlaying; + INDEX m_iRunType; + BOOL m_bAttacking; + FLOAT m_fSightSoundBegin; + +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void Precache(void); + +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void * GetEntityInfo(void); + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT GetCrushHealth(void); + +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void AdjustDifficulty(void); + +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +INDEX AnimForDeath(void); + +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void DeathNotify(); + +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void StandingAnim(void); + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void WalkingAnim(void); + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void RunningAnim(void); + +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void ChargeAnim(void); + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void RotatingAnim(void); + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void IdleSound(void); + +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void WoundSound(void); + +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void DeathSound(void); + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void ActivateRunningSound(void); + +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void DeactivateRunningSound(void); + +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void LiveEntityTouched(ETouch etouch); + +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +BOOL HigherMass(void); + +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void EnemyPostInit(void); + +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +void PreMoving(); +#define STATE_CChainsawFreak_Hit 0x01560000 + BOOL +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +Hit(const CEntityEvent &__eeInput); + BOOL H0x01560001_Hit_01(const CEntityEvent &__eeInput); + BOOL H0x01560002_Hit_02(const CEntityEvent &__eeInput); + BOOL H0x01560003_Hit_03(const CEntityEvent &__eeInput); + BOOL H0x01560004_Hit_04(const CEntityEvent &__eeInput); + BOOL H0x01560005_Hit_05(const CEntityEvent &__eeInput); + BOOL H0x01560006_Hit_06(const CEntityEvent &__eeInput); + BOOL H0x01560007_Hit_07(const CEntityEvent &__eeInput); + BOOL H0x01560008_Hit_08(const CEntityEvent &__eeInput); + BOOL H0x01560009_Hit_09(const CEntityEvent &__eeInput); +#define STATE_CChainsawFreak_AttackEnemy 0x0156000a + BOOL +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +AttackEnemy(const CEntityEvent &__eeInput); +#define STATE_CChainsawFreak_BeIdle 0x0156000b + BOOL +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +BeIdle(const CEntityEvent &__eeInput); +#define STATE_CChainsawFreak_PostRunAwayFromEnemy 0x0156000c + BOOL +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PostRunAwayFromEnemy(const CEntityEvent &__eeInput); + BOOL H0x0156000d_PostRunAwayFromEnemy_01(const CEntityEvent &__eeInput); + BOOL H0x0156000e_PostRunAwayFromEnemy_02(const CEntityEvent &__eeInput); + BOOL H0x0156000f_PostRunAwayFromEnemy_03(const CEntityEvent &__eeInput); + BOOL H0x01560010_PostRunAwayFromEnemy_04(const CEntityEvent &__eeInput); +#define STATE_CChainsawFreak_Main 1 + BOOL +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ChainsawFreak_INCLUDED diff --git a/Sources/EntitiesMP/ChainsawFreak_tables.h b/Sources/EntitiesMP/ChainsawFreak_tables.h new file mode 100644 index 0000000..f997fe9 --- /dev/null +++ b/Sources/EntitiesMP/ChainsawFreak_tables.h @@ -0,0 +1,86 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CChainsawFreak + +CEntityProperty CChainsawFreak_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000156<<8)+1, offsetof(CChainsawFreak, m_bRunAttack), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000156<<8)+2, offsetof(CChainsawFreak, m_bSawHit), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000156<<8)+3, offsetof(CChainsawFreak, m_penLastTouched), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000156<<8)+4, offsetof(CChainsawFreak, m_soFeet), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000156<<8)+5, offsetof(CChainsawFreak, m_bRunSoundPlaying), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000156<<8)+6, offsetof(CChainsawFreak, m_iRunType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000156<<8)+10, offsetof(CChainsawFreak, m_bAttacking), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000156<<8)+11, offsetof(CChainsawFreak, m_fSightSoundBegin), "", 0, 0, 0), +}; +#define CChainsawFreak_propertiesct ARRAYCOUNT(CChainsawFreak_properties) + +CEntityComponent CChainsawFreak_components[] = { +#define CLASS_BASE ((0x00000156<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyRunInto.ecl"), +#define MODEL_FREAK ((0x00000156<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_FREAK, "EFNM" "ModelsMP\\Enemies\\ChainsawFreak\\Freak.mdl"), +#define MODEL_CHAINSAW ((0x00000156<<8)+2) + CEntityComponent(ECT_MODEL, MODEL_CHAINSAW, "EFNM" "ModelsMP\\Enemies\\ChainsawFreak\\Saw.mdl"), +#define TEXTURE_FREAK ((0x00000156<<8)+3) + CEntityComponent(ECT_TEXTURE, TEXTURE_FREAK, "EFNM" "ModelsMP\\Enemies\\ChainsawFreak\\Freak.tex"), +#define TEXTURE_CHAINSAW ((0x00000156<<8)+4) + CEntityComponent(ECT_TEXTURE, TEXTURE_CHAINSAW, "EFNM" "ModelsMP\\Enemies\\ChainsawFreak\\Saw.tex"), +#define SOUND_IDLE ((0x00000156<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Idle.wav"), +#define SOUND_RUN ((0x00000156<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_RUN, "EFNM" "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Run.wav"), +#define SOUND_ATTACK ((0x00000156<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_ATTACK, "EFNM" "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Attack.wav"), +#define SOUND_WOUND ((0x00000156<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Wound.wav"), +#define SOUND_DEATH ((0x00000156<<8)+56) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Death.wav"), +#define SOUND_SIGHT ((0x00000156<<8)+57) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "ModelsMP\\Enemies\\ChainsawFreak\\Sounds\\Sight.wav"), +}; +#define CChainsawFreak_componentsct ARRAYCOUNT(CChainsawFreak_components) + +CEventHandlerEntry CChainsawFreak_handlers[] = { + {0x01560000, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CChainsawFreak:: +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +Hit),DEBUGSTRING("CChainsawFreak::Hit")}, + {0x01560001, -1, CEntity::pEventHandler(&CChainsawFreak::H0x01560001_Hit_01), DEBUGSTRING("CChainsawFreak::H0x01560001_Hit_01")}, + {0x01560002, -1, CEntity::pEventHandler(&CChainsawFreak::H0x01560002_Hit_02), DEBUGSTRING("CChainsawFreak::H0x01560002_Hit_02")}, + {0x01560003, -1, CEntity::pEventHandler(&CChainsawFreak::H0x01560003_Hit_03), DEBUGSTRING("CChainsawFreak::H0x01560003_Hit_03")}, + {0x01560004, -1, CEntity::pEventHandler(&CChainsawFreak::H0x01560004_Hit_04), DEBUGSTRING("CChainsawFreak::H0x01560004_Hit_04")}, + {0x01560005, -1, CEntity::pEventHandler(&CChainsawFreak::H0x01560005_Hit_05), DEBUGSTRING("CChainsawFreak::H0x01560005_Hit_05")}, + {0x01560006, -1, CEntity::pEventHandler(&CChainsawFreak::H0x01560006_Hit_06), DEBUGSTRING("CChainsawFreak::H0x01560006_Hit_06")}, + {0x01560007, -1, CEntity::pEventHandler(&CChainsawFreak::H0x01560007_Hit_07), DEBUGSTRING("CChainsawFreak::H0x01560007_Hit_07")}, + {0x01560008, -1, CEntity::pEventHandler(&CChainsawFreak::H0x01560008_Hit_08), DEBUGSTRING("CChainsawFreak::H0x01560008_Hit_08")}, + {0x01560009, -1, CEntity::pEventHandler(&CChainsawFreak::H0x01560009_Hit_09), DEBUGSTRING("CChainsawFreak::H0x01560009_Hit_09")}, + {0x0156000a, STATE_CEnemyBase_AttackEnemy, CEntity::pEventHandler(&CChainsawFreak:: +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +AttackEnemy),DEBUGSTRING("CChainsawFreak::AttackEnemy")}, + {0x0156000b, STATE_CEnemyBase_BeIdle, CEntity::pEventHandler(&CChainsawFreak:: +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +BeIdle),DEBUGSTRING("CChainsawFreak::BeIdle")}, + {0x0156000c, STATE_CEnemyRunInto_PostRunAwayFromEnemy, CEntity::pEventHandler(&CChainsawFreak:: +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +PostRunAwayFromEnemy),DEBUGSTRING("CChainsawFreak::PostRunAwayFromEnemy")}, + {0x0156000d, -1, CEntity::pEventHandler(&CChainsawFreak::H0x0156000d_PostRunAwayFromEnemy_01), DEBUGSTRING("CChainsawFreak::H0x0156000d_PostRunAwayFromEnemy_01")}, + {0x0156000e, -1, CEntity::pEventHandler(&CChainsawFreak::H0x0156000e_PostRunAwayFromEnemy_02), DEBUGSTRING("CChainsawFreak::H0x0156000e_PostRunAwayFromEnemy_02")}, + {0x0156000f, -1, CEntity::pEventHandler(&CChainsawFreak::H0x0156000f_PostRunAwayFromEnemy_03), DEBUGSTRING("CChainsawFreak::H0x0156000f_PostRunAwayFromEnemy_03")}, + {0x01560010, -1, CEntity::pEventHandler(&CChainsawFreak::H0x01560010_PostRunAwayFromEnemy_04), DEBUGSTRING("CChainsawFreak::H0x01560010_PostRunAwayFromEnemy_04")}, + {1, -1, CEntity::pEventHandler(&CChainsawFreak:: +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/ChainsawFreak.es" +Main),DEBUGSTRING("CChainsawFreak::Main")}, +}; +#define CChainsawFreak_handlersct ARRAYCOUNT(CChainsawFreak_handlers) + +CEntity *CChainsawFreak_New(void) { return new CChainsawFreak; }; +void CChainsawFreak_OnInitClass(void) {}; +void CChainsawFreak_OnEndClass(void) {}; +void CChainsawFreak_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CChainsawFreak_OnWorldEnd(CWorld *pwo) {}; +void CChainsawFreak_OnWorldInit(CWorld *pwo) {}; +void CChainsawFreak_OnWorldTick(CWorld *pwo) {}; +void CChainsawFreak_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CChainsawFreak, CEnemyRunInto, "ChainsawFreak", "Thumbnails\\ChainsawFreak.tbn", 0x00000156); +DECLARE_CTFILENAME(_fnmCChainsawFreak_tbn, "Thumbnails\\ChainsawFreak.tbn"); diff --git a/Sources/EntitiesMP/Common/Common.cpp b/Sources/EntitiesMP/Common/Common.cpp new file mode 100644 index 0000000..9de8dbb --- /dev/null +++ b/Sources/EntitiesMP/Common/Common.cpp @@ -0,0 +1,1426 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" +#include +#include "EntitiesMP/Reminder.h" +#include "EntitiesMP/Flame.h" +#include "EntitiesMP/Debris.h" +#include "EntitiesMP/Player.h" +#include "EntitiesMP/Bullet.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/SoundHolder.h" +#include "GameMP/PlayerSettings.h" +#include "ModelsMP/Player/SeriousSam/Player.h" +#include "ModelsMP/Player/SeriousSam/Body.h" +#include "ModelsMP/Player/SeriousSam/Head.h" +extern INDEX ent_bReportBrokenChains; + +void CCompMessageID::Clear(void) +{ + cmi_fnmFileName.Clear(); + cmi_ulHash = 0; +} + +void CCompMessageID::Read_t(CTStream &strm) // throw char * +{ + strm>>cmi_fnmFileName; + strm>>(INDEX&)cmi_cmtType; + strm>>(INDEX&)cmi_bRead; + cmi_ulHash = cmi_fnmFileName.GetHash(); +} + +void CCompMessageID::Write_t(CTStream &strm) // throw char * +{ + strm<GetPlacement().pl_PositionVector; + if (pf != NULL) { + FLOATmatrix3D mRotation; + MakeRotationMatrixFast(mRotation, pen->GetPlacement().pl_OrientationAngle); + vPos += FLOAT3D(pf[0], pf[1], pf[2])*mRotation; + } +}; + +// get source and target positions for ray cast +void GetPositionCastRay(CEntity *penSource, CEntity *penTarget, FLOAT3D &vSource, FLOAT3D &vTarget) { + EntityInfo *peiSource = (EntityInfo*) (penSource->GetEntityInfo()); + EntityInfo *peiTarget = (EntityInfo*) (penTarget->GetEntityInfo()); + + ASSERT(peiSource!=NULL && peiTarget!=NULL); + + // source + if (peiSource!=NULL) { + GetEntityInfoPosition(penSource, peiSource->vSourceCenter, vSource); + } else { + vSource = penSource->GetPlacement().pl_PositionVector; + } + // target + if (peiTarget!=NULL) { + GetEntityInfoPosition(penTarget, peiTarget->vTargetCenter, vTarget); + } else { + vTarget = penTarget->GetPlacement().pl_PositionVector; + } +}; + +// set bool from bool enum type +void SetBoolFromBoolEType(BOOL &bSet, BoolEType bet) { + switch (bet) { + case BET_TRUE: + bSet = TRUE; + break; + case BET_FALSE: + bSet = FALSE; + break; + //case BET_IGNORE: + //bSet = bSet; + // break + } +}; + +// send event to target +void SendToTarget(CEntity *penSendEvent, EventEType eetEventType, CEntity *penCaused) { + // if target is valid + if (penSendEvent != NULL) { + switch (eetEventType) { + // send START event + case EET_START: { + EStart eStart; + eStart.penCaused = penCaused; + penSendEvent->SendEvent(eStart); + } break; + // send STOP event + case EET_STOP: + penSendEvent->SendEvent(EStop()); + break; + // send TRIGGER event + case EET_TRIGGER: { + ETrigger eTrigger; + eTrigger.penCaused = penCaused; + penSendEvent->SendEvent(eTrigger); + } break; + // don't send event (IGNORE) + case EET_IGNORE: + break; + // send ACTIVATE event + case EET_ACTIVATE: + penSendEvent->SendEvent(EActivate()); + break; + // send DEACTIVATE event + case EET_DEACTIVATE: + penSendEvent->SendEvent(EDeactivate()); + break; + // send ENVIRONMENTSTART event + case EET_ENVIRONMENTSTART: + penSendEvent->SendEvent(EEnvironmentStart()); + break; + // send ENVIRONMENTSTOP event + case EET_ENVIRONMENTSTOP: + penSendEvent->SendEvent(EEnvironmentStop()); + break; + // send STARTATTACK event + case EET_STARTATTACK: + penSendEvent->SendEvent(EStartAttack()); + break; + // send STOPATTACK event + case EET_STOPATTACK: + penSendEvent->SendEvent(EStopAttack()); + break; + case EET_STOPBLINDNESS: + penSendEvent->SendEvent(EStopBlindness()); + break; + case EET_STOPDEAFNESS: + penSendEvent->SendEvent(EStopDeafness()); + break; + case EET_TELEPORTMOVINGBRUSH: + penSendEvent->SendEvent(ETeleportMovingBrush()); + break; + } + } +}; + +// send event in range +void SendInRange(CEntity *penSource, EventEType eetEventType, const FLOATaabbox3D &boxRange) { + switch (eetEventType) { + // send START event + case EET_START: + penSource->SendEventInRange(EStart(), boxRange); + break; + // send STOP event + case EET_STOP: + penSource->SendEventInRange(EStop(), boxRange); + break; + // send TRIGGER event + case EET_TRIGGER: + penSource->SendEventInRange(ETrigger(), boxRange); + break; + // don't send event (IGNORE) + case EET_IGNORE: + break; + // send ACTIVATE event + case EET_ACTIVATE: + penSource->SendEventInRange(EActivate(), boxRange); + break; + // send DEACTIVATE event + case EET_DEACTIVATE: + penSource->SendEventInRange(EDeactivate(), boxRange); + break; + // send ENVIRONMENTSTART event + case EET_ENVIRONMENTSTART: + penSource->SendEventInRange(EEnvironmentStart(), boxRange); + break; + // send ENVIRONMENTSTOP event + case EET_ENVIRONMENTSTOP: + penSource->SendEventInRange(EEnvironmentStop(), boxRange); + break; + // send STARTATTACK event + case EET_STARTATTACK: + penSource->SendEventInRange(EStartAttack(), boxRange); + break; + // send STOPATTACK event + case EET_STOPATTACK: + penSource->SendEventInRange(EStopAttack(), boxRange); + break; + case EET_STOPBLINDNESS: + penSource->SendEventInRange(EStopBlindness(), boxRange); + break; + case EET_STOPDEAFNESS: + penSource->SendEventInRange(EStopDeafness(), boxRange); + break; + } +}; + +// spawn reminder +CEntityPointer SpawnReminder(CEntity *penOwner, FLOAT fWaitTime, INDEX iValue) { + CEntityPointer penReminder; + try { + penReminder = penOwner->GetWorld()->CreateEntity_t + (penOwner->GetPlacement(), CTFILENAME("Classes\\Reminder.ecl")); + } catch (char *strError) { + FatalError(TRANS("Cannot create reminder entity class: %s"), strError); + } + EReminderInit eri; + eri.penOwner = penOwner; + eri.fWaitTime = fWaitTime; + eri.iValue = iValue; + penReminder->Initialize(eri); + + return penReminder; +}; + +EffectParticlesType GetParticleEffectTypeForSurface(INDEX iSurfaceType) +{ + EffectParticlesType eptType = EPT_BULLET_STONE; + switch( iSurfaceType) + { + case SURFACE_SAND: {eptType=EPT_BULLET_SAND; break;} + case SURFACE_RED_SAND: {eptType=EPT_BULLET_RED_SAND; break;} + case SURFACE_WATER: {eptType=EPT_BULLET_WATER; break;} + case SURFACE_GRASS: + case SURFACE_GRASS_SLIDING: + case SURFACE_GRASS_NOIMPACT: + {eptType=EPT_BULLET_GRASS; break;} + case SURFACE_WOOD: {eptType=EPT_BULLET_WOOD; break;} + case SURFACE_SNOW: {eptType=EPT_BULLET_SNOW; break;} + } + return eptType; +} + +BulletHitType GetBulletHitTypeForSurface(INDEX iSurfaceType) +{ + BulletHitType bhtType = BHT_BRUSH_STONE; + switch( iSurfaceType) + { + case SURFACE_SAND: {bhtType=BHT_BRUSH_SAND; break;} + case SURFACE_RED_SAND: {bhtType=BHT_BRUSH_RED_SAND; break;} + case SURFACE_WATER: {bhtType=BHT_BRUSH_WATER; break;} + case SURFACE_GRASS: + case SURFACE_GRASS_SLIDING: + case SURFACE_GRASS_NOIMPACT: + {bhtType=BHT_BRUSH_GRASS; break;} + case SURFACE_WOOD: {bhtType=BHT_BRUSH_WOOD; break;} + case SURFACE_SNOW: {bhtType=BHT_BRUSH_SNOW; break;} + } + return bhtType; +} + +// spawn effect from hit type +void SpawnHitTypeEffect(CEntity *pen, enum BulletHitType bhtType, BOOL bSound, FLOAT3D vHitNormal, FLOAT3D vHitPoint, + FLOAT3D vIncommingBulletDir, FLOAT3D vDistance) +{ + switch (bhtType) + { + case BHT_BRUSH_STONE: + case BHT_BRUSH_SAND: + case BHT_BRUSH_RED_SAND: + case BHT_BRUSH_WATER: + case BHT_BRUSH_UNDER_WATER: + case BHT_BRUSH_GRASS: + case BHT_BRUSH_WOOD: + case BHT_BRUSH_SNOW: + { + // bullet stain + ESpawnEffect ese; + if( bSound) + { + if( bhtType == BHT_BRUSH_STONE) {ese.betType = BET_BULLETSTAINSTONE;}; + if( bhtType == BHT_BRUSH_SAND) {ese.betType = BET_BULLETSTAINSAND;}; + if( bhtType == BHT_BRUSH_RED_SAND) {ese.betType = BET_BULLETSTAINREDSAND;}; + if( bhtType == BHT_BRUSH_WATER) {ese.betType = BET_BULLETSTAINWATER;}; + if( bhtType == BHT_BRUSH_UNDER_WATER) {ese.betType = BET_BULLETSTAINUNDERWATER;}; + if( bhtType == BHT_BRUSH_GRASS) {ese.betType = BET_BULLETSTAINGRASS;}; + if( bhtType == BHT_BRUSH_WOOD) {ese.betType = BET_BULLETSTAINWOOD;}; + if( bhtType == BHT_BRUSH_SNOW) {ese.betType = BET_BULLETSTAINSNOW;}; + } + else + { + if( bhtType == BHT_BRUSH_STONE) {ese.betType = BET_BULLETSTAINSTONENOSOUND;}; + if( bhtType == BHT_BRUSH_SAND) {ese.betType = BET_BULLETSTAINSANDNOSOUND;}; + if( bhtType == BHT_BRUSH_RED_SAND) {ese.betType = BET_BULLETSTAINREDSANDNOSOUND;}; + if( bhtType == BHT_BRUSH_WATER) {ese.betType = BET_BULLETSTAINWATERNOSOUND;}; + if( bhtType == BHT_BRUSH_UNDER_WATER) {ese.betType = BET_BULLETSTAINUNDERWATERNOSOUND;}; + if( bhtType == BHT_BRUSH_GRASS) {ese.betType = BET_BULLETSTAINGRASSNOSOUND;}; + if( bhtType == BHT_BRUSH_WOOD) {ese.betType = BET_BULLETSTAINWOODNOSOUND;}; + if( bhtType == BHT_BRUSH_SNOW) {ese.betType = BET_BULLETSTAINSNOWNOSOUND;}; + } + + ese.vNormal = vHitNormal; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + // reflect direction arround normal + FLOAT fNx = vHitNormal(1); + FLOAT fNy = vHitNormal(2); + FLOAT fNz = vHitNormal(3); + FLOAT fNV = fNx*vIncommingBulletDir(1) + fNy*vIncommingBulletDir(2) + fNz*vIncommingBulletDir(3); + FLOAT fRVx = vIncommingBulletDir(1) - 2*fNx*fNV; + FLOAT fRVy = vIncommingBulletDir(2) - 2*fNy*fNV; + FLOAT fRVz = vIncommingBulletDir(3) - 2*fNz*fNV; + ese.vStretch = FLOAT3D( fRVx, fRVy, fRVz); + + try + { + // spawn effect + CPlacement3D plHit = CPlacement3D(vHitPoint-vIncommingBulletDir*0.1f, pen->GetPlacement().pl_OrientationAngle); + CEntityPointer penHit = pen->GetWorld()->CreateEntity_t(plHit , CTFILENAME("Classes\\BasicEffect.ecl")); + penHit->Initialize(ese); + } + catch (char *strError) + { + FatalError(TRANS("Cannot create basic effect class: %s"), strError); + } + break; + } + case BHT_FLESH: + case BHT_ACID: + { + // spawn bullet entry wound + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + // if there is exit wound blood spill place + FLOAT fDistance = vDistance.Length(); + if( fDistance>0.01f && !(pen->IRnd()%2) ) + { + // spawn bullet exit wound blood patch + ese.betType = BET_BLOODSPILL; + if( bhtType == BHT_ACID) + { + ese.colMuliplier = BLOOD_SPILL_GREEN; + } + else + { + ese.colMuliplier = BLOOD_SPILL_RED; + } + ese.vNormal = vHitNormal; + if (fDistance<25.0f) + { + GetNormalComponent( vDistance/fDistance, vHitNormal, ese.vDirection); + FLOAT fLength = ese.vDirection.Length(); + fLength = Clamp( fLength*3.0f, 1.0f, 3.0f); + fDistance = Clamp( (FLOAT)log10(fDistance), 0.5f, 2.0f); + ese.vStretch = FLOAT3D( fDistance, fLength*fDistance, 1.0f); + try + { + // spawn effect + CPlacement3D plHit = CPlacement3D(vHitPoint-vIncommingBulletDir*0.1f, pen->GetPlacement().pl_OrientationAngle); + CEntityPointer penHit = pen->GetWorld()->CreateEntity_t(plHit , CTFILENAME("Classes\\BasicEffect.ecl")); + penHit->Initialize(ese); + } + catch (char *strError) + { + FatalError(TRANS("Cannot create basic effect class: %s"), strError); + } + } + } + break; + } + } +} + +// spawn flame +CEntityPointer SpawnFlame(CEntity *penOwner, CEntity *penAttach, const FLOAT3D &vSource) +{ + // owner can't flame himself + if( penOwner==penAttach) return NULL; + FLOAT3D vPos = vSource; + // prepare flame event + EFlame ef; + ef.penOwner = penOwner; + ef.penAttach = penAttach; + + CEntityPointer penFlame; + + // if the target entity is model + if (penAttach->GetRenderType()==CEntity::RT_MODEL || + penAttach->GetRenderType()==CEntity::RT_SKAMODEL) { + + vPos = penAttach->GetPlacement().pl_PositionVector; + // if the entity already has a flame attached + penFlame = penAttach->GetChildOfClass("Flame"); + if (penFlame!=NULL) { + // just send it the event + penFlame->SendEvent(ef); + return penFlame; + } + } + + // create new flame + try { + CPlacement3D plFlame(vPos, ANGLE3D(0, 0, 0)); + penFlame = penAttach->GetWorld()->CreateEntity_t(plFlame, CTFILENAME("Classes\\Flame.ecl")); + } catch (char *strError) { + FatalError(TRANS("Cannot create flame entity class: %s"), strError); + } + penFlame->Initialize(ef); + + return penFlame; +}; + +// Kick entity +void KickEntity(CEntity *penTarget, FLOAT3D vSpeed) { + // if the entity is not allowed to execute now + if (!penTarget->IsAllowedForPrediction()) { + // do nothing + return; + } + EntityInfo *peiTarget = (EntityInfo*) (penTarget->GetEntityInfo()); + if (penTarget->GetPhysicsFlags()&EPF_MOVABLE && peiTarget!=NULL) { + // calc new speed acording to target mass + vSpeed *= 100.0f/peiTarget->fMass; + ((CMovableEntity&)*penTarget).en_vCurrentTranslationAbsolute = vSpeed; + ((CMovableEntity&)*penTarget).AddToMovers(); + } +}; + + + +/************************************************************ + * SET MODEL AND ATTACHMENT * + ************************************************************/ + // Set components + void SetComponents(CEntity *pen, CModelObject &mo, ULONG ulIDModel, ULONG ulIDTexture, + ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture) { + // model data + mo.SetData(pen->GetModelDataForComponent(ulIDModel)); + // texture data + mo.mo_toTexture.SetData(pen->GetTextureDataForComponent(ulIDTexture)); + // reflection texture data + if (ulIDReflectionTexture>0) { + mo.mo_toReflection.SetData(pen->GetTextureDataForComponent(ulIDReflectionTexture)); + } else { + mo.mo_toReflection.SetData(NULL); + } + // specular texture data + if (ulIDSpecularTexture>0) { + mo.mo_toSpecular.SetData(pen->GetTextureDataForComponent(ulIDSpecularTexture)); + } else { + mo.mo_toSpecular.SetData(NULL); + } + // bump texture data + if (ulIDBumpTexture>0) { + mo.mo_toBump.SetData(pen->GetTextureDataForComponent(ulIDBumpTexture)); + } else { + mo.mo_toBump.SetData(NULL); + } + }; + + // Add attachment to model + void AddAttachmentToModel(CEntity *pen, CModelObject &mo, INDEX iAttachment, ULONG ulIDModel, ULONG ulIDTexture, + ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture) { + SetComponents(pen, mo.AddAttachmentModel(iAttachment)->amo_moModelObject, ulIDModel, + ulIDTexture, ulIDReflectionTexture, ulIDSpecularTexture, ulIDBumpTexture); + }; + + // Remove attachment from model + void RemoveAttachmentFromModel(CModelObject &mo, INDEX iAttachment) { + mo.RemoveAttachmentModel(iAttachment); + }; + + + +/************************************************************ + * FLARES * + ************************************************************/ +// lens flare variables +CLensFlareType _lftStandard; +CLensFlareType _lftStandardReflections; +CLensFlareType _lftYellowStarRedRing; +CLensFlareType _lftYellowStarRedRingFar; +CLensFlareType _lftWhiteGlowStarRedRing; +CLensFlareType _lftWhiteGlowStar; +CLensFlareType _lftWhiteGlowStarNG; +CLensFlareType _lftWhiteStarRedRingStreaks; +CLensFlareType _lftWhiteStarRedReflections; +CLensFlareType _lftBlueStarBlueReflections; +CLensFlareType _lftProjectileStarGlow; +CLensFlareType _lftProjectileWhiteBubbleGlow; +CLensFlareType _lftProjectileYellowBubbleGlow; +CLensFlareType _lftPVSpaceShipWindowFlare; +CLensFlareType _lftCatmanFireGlow; +CLensFlareType _lftWhiteGlowFar; +static BOOL _bLensFlaresLoaded = FALSE; + +#define FLARE_CREATE(type,noof,tex,pos,rot,i,j,flags,amp,des,falloff)\ + type.lft_aolfFlares.New(noof);\ + type.lft_aolfFlares[0].olf_toTexture.SetData_t(CTFILENAME("Textures\\Effects\\Flares\\" tex));\ + type.lft_aolfFlares[0].olf_fReflectionPosition = pos;\ + type.lft_aolfFlares[0].olf_aRotationFactor = AngleDeg(rot);\ + type.lft_aolfFlares[0].olf_fSizeIOverScreenSizeI = i;\ + type.lft_aolfFlares[0].olf_fSizeJOverScreenSizeI = j;\ + type.lft_aolfFlares[0].olf_ulFlags = flags;\ + type.lft_aolfFlares[0].olf_fLightAmplification = amp;\ + type.lft_aolfFlares[0].olf_fLightDesaturation = des;\ + type.lft_aolfFlares[0].oft_fFallOffFactor = falloff; +#define FLARE_GLARE(type,compression,intensity,des,falloff)\ + type.lft_fGlareCompression = compression;\ + type.lft_fGlareIntensity = intensity;\ + type.lft_fGlareDesaturation = des;\ + type.lft_fGlareFallOffFactor = falloff; +#define REFLECTION(type,i,fnm,pos,size) \ + type.lft_aolfFlares[i].olf_toTexture.SetData_t(CTFILENAME("Textures\\Effects\\Flares\\" fnm));\ + type.lft_aolfFlares[i].olf_fReflectionPosition = pos;\ + type.lft_aolfFlares[i].olf_aRotationFactor = AngleDeg(0.0f);\ + type.lft_aolfFlares[i].olf_fSizeIOverScreenSizeI = size;\ + type.lft_aolfFlares[i].olf_fSizeJOverScreenSizeI = size;\ + type.lft_aolfFlares[i].olf_ulFlags = OLF_FADEINTENSITY|OLF_FADEOFCENTER;\ + type.lft_aolfFlares[i].olf_fLightAmplification = 7.0f;\ + type.lft_aolfFlares[i].olf_fLightDesaturation = 0.5f;\ + type.lft_aolfFlares[i].oft_fFallOffFactor = 5.0f; + +// init lens flare effects +void InitLensFlares(void) { + if (_bLensFlaresLoaded) { + return; // Player class is not auto-freed, so the engine may attempt to access this function several times + } + + // standard flare + FLARE_CREATE(_lftStandard, 1, "01\\WhiteRedRing2.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); + FLARE_GLARE(_lftStandard, 20.0f, 0.3f, 0.8f, 1.0f); + + // standard flare with huge reflections + FLARE_CREATE(_lftStandardReflections, 15, "01\\WhiteRedRing2.tex", 0.0f, 180.0f, 1.36f, 1.36f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); + FLARE_GLARE(_lftStandardReflections, 20.0f, 0.3f, 0.8f, 1.0f); + REFLECTION(_lftStandardReflections, 1, "01\\WhiteRing.tex", -0.3f, 0.1f); + REFLECTION(_lftStandardReflections, 2, "01\\BlueDisc.tex", 1-0.5f, 0.047f); + REFLECTION(_lftStandardReflections, 3, "01\\BlueDisc.tex", 1-0.41f, 0.078f); + REFLECTION(_lftStandardReflections, 4, "01\\BlueDiscWeak.tex", 1-0.45f, 0.15f); + REFLECTION(_lftStandardReflections, 5, "01\\BrownDisc.tex", 1-0.2f, 0.05f); + REFLECTION(_lftStandardReflections, 6, "01\\WhiteGradient.tex", 1-0.1f, 0.016f); + REFLECTION(_lftStandardReflections, 7, "01\\WhiteGradient.tex", 1+0.29f, 0.027f); + REFLECTION(_lftStandardReflections, 8, "01\\BrownDisc.tex", 1+0.5f, 0.05f); + REFLECTION(_lftStandardReflections, 9, "01\\BrownDisc.tex", 1+0.43f, 0.11f); + REFLECTION(_lftStandardReflections,10, "01\\BrownRing.tex", 1+0.49f, 0.19f); + REFLECTION(_lftStandardReflections,11, "01\\BlueDisc.tex", 1+0.68f, 0.08f); + REFLECTION(_lftStandardReflections,12, "01\\BlueGradient.tex", 1+0.7f, 0.043f); + REFLECTION(_lftStandardReflections,13, "01\\GreenRing.tex", 1+1.04f, 0.27f); + REFLECTION(_lftStandardReflections,14, "01\\RainbowRing.tex", 1+1.35f, 0.53f); + + // nice yellow star with red ring + FLARE_CREATE(_lftYellowStarRedRing, 1, "02\\Flare05.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); + FLARE_GLARE(_lftYellowStarRedRing, 20.0f, 0.3f, 0.8f, 1.0f); + + // same yellow star with red ring but visible from far away + FLARE_CREATE(_lftYellowStarRedRingFar, 1, "02\\Flare05.tex", 0.0f, 180.0f, 1/12.0f, 1/12.0f, OLF_FADESIZE, 0.25f, 0.5f, 128.0f); + FLARE_GLARE(_lftYellowStarRedRingFar, 20.0f, 0.3f, 0.8f, 1.0f); + + // nice yellow star with red ring + FLARE_CREATE(_lftWhiteGlowStarRedRing, 1, "03\\Flare06.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); + FLARE_GLARE(_lftWhiteGlowStarRedRing, 20.0f, 0.3f, 0.8f, 1.0f); + + FLARE_CREATE(_lftWhiteGlowStar, 1, "04\\Flare07.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); + FLARE_GLARE(_lftWhiteGlowStar, 20.0f, 0.3f, 0.8f, 1.0f); + + FLARE_CREATE(_lftWhiteGlowStarNG, 1, "04\\Flare07.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); + + FLARE_CREATE(_lftWhiteStarRedRingStreaks, 1, "05\\Flare09.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); + FLARE_GLARE(_lftWhiteStarRedRingStreaks, 20.0f, 0.3f, 0.8f, 1.0f); + + // white star flare with many red and brown hexagons + FLARE_CREATE(_lftWhiteStarRedReflections, 12, "06\\WhiteStarManyStreaks.tex", 0.0f, 0.0f, 0.20625f, 0.20625f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); + FLARE_GLARE(_lftWhiteStarRedReflections, 20.0f, 0.3f, 0.8f, 1.0f); + REFLECTION(_lftWhiteStarRedReflections, 1, "06\\DarkRedPentagram.tex" ,-0.92424242f,0.06875f); + REFLECTION(_lftWhiteStarRedReflections, 2, "06\\LillaPentagram.tex" ,0.28787879f,0.0296875f); + REFLECTION(_lftWhiteStarRedReflections, 3, "06\\MagentaPentagram.tex" ,0.43939394f,0.05f); + REFLECTION(_lftWhiteStarRedReflections, 4, "06\\MagentaGlow.tex" ,1.52272727f,0.009375f); + REFLECTION(_lftWhiteStarRedReflections, 5, "06\\DarkRedPentagram.tex" ,1.9469697f,0.06875f); + REFLECTION(_lftWhiteStarRedReflections, 6, "06\\MagentaGlow.tex" ,1.96212121f,0.05f); + REFLECTION(_lftWhiteStarRedReflections, 7, "06\\DarkRedPentagram.tex" ,1.08333333f,0.06875f); + REFLECTION(_lftWhiteStarRedReflections, 8, "06\\DarkRedPentagram.tex" ,1.59848485f,0.06875f); + REFLECTION(_lftWhiteStarRedReflections, 9, "06\\DarkRedPentagram.tex" ,1.67424242f,0.06875f); + REFLECTION(_lftWhiteStarRedReflections,10, "06\\DarkRedPentagram.tex" ,-0.12878788f,0.03125f); + REFLECTION(_lftWhiteStarRedReflections,11, "06\\BrownPentagram.tex" ,0.03030303f,0.021875f); + + // blue star flare with many blue flares + FLARE_CREATE(_lftBlueStarBlueReflections, 21, "07\\BlueStarManyStreaks.tex", 0.0f, 0.0f, 0.4f, 0.4f, OLF_FADESIZE, 7.0f, 0.5f, 5.0f); + FLARE_GLARE(_lftBlueStarBlueReflections, 20.0f, 0.3f, 0.8f, 1.0f); + REFLECTION(_lftBlueStarBlueReflections, 1, "07\\BlueGlow.tex", -0.5f,0.05f); + REFLECTION(_lftBlueStarBlueReflections, 2, "07\\BluePentagram.tex", -0.25f,0.03f); + REFLECTION(_lftBlueStarBlueReflections, 3, "07\\GreenGlow.tex", -0.05f,0.04f); + REFLECTION(_lftBlueStarBlueReflections, 4, "07\\GreenGlow.tex", 0.3f,0.02f); + REFLECTION(_lftBlueStarBlueReflections, 5, "07\\BluePentagram.tex", 0.5f,0.05f); + REFLECTION(_lftBlueStarBlueReflections, 6, "07\\DarkBluePentagram.tex", 0.8f,0.04f); + REFLECTION(_lftBlueStarBlueReflections, 7, "07\\LittleBluePentagram.tex", 1.2f,0.02f); + REFLECTION(_lftBlueStarBlueReflections, 8, "07\\MagentaPentagram.tex", 1.13f,0.08f); + REFLECTION(_lftBlueStarBlueReflections, 9, "07\\DarkBluePentagram.tex", 1.24f,0.03f); + REFLECTION(_lftBlueStarBlueReflections,10, "07\\BlueGlow.tex", 1.4f,0.06f); + REFLECTION(_lftBlueStarBlueReflections,11, "07\\GreenGlow.tex", 1.5f,0.02f); + REFLECTION(_lftBlueStarBlueReflections,12, "07\\BluePentagram.tex", 1.64f,0.05f); + REFLECTION(_lftBlueStarBlueReflections,13, "07\\LittleBluePentagram.tex", 1.7f,0.05f); + REFLECTION(_lftBlueStarBlueReflections,14, "07\\BluePentagram.tex", 1.8f,0.06f); + REFLECTION(_lftBlueStarBlueReflections,15, "07\\MagentaPentagram.tex", 2.0f,0.01f); + REFLECTION(_lftBlueStarBlueReflections,16, "07\\BlueGlow.tex", 2.0f,0.06f); + REFLECTION(_lftBlueStarBlueReflections,17, "07\\MagentaPentagram.tex", 2.0f,0.02f); + REFLECTION(_lftBlueStarBlueReflections,18, "07\\GreenGlow.tex", 2.1f,0.015f); + REFLECTION(_lftBlueStarBlueReflections,19, "07\\BluePentagram.tex", 2.4f,0.05f); + REFLECTION(_lftBlueStarBlueReflections,20, "07\\DarkBluePentagram.tex", 2.8f,0.03f); + + FLARE_CREATE(_lftProjectileStarGlow, 1, "08\\FlarePower.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 10.0f); + FLARE_GLARE(_lftProjectileStarGlow, 20.0f, 0.3f, 0.8f, 1.0f); + + FLARE_CREATE(_lftProjectileWhiteBubbleGlow, 1, "09\\FlareWhiteBubble.tex", 0.0f, 180.0f, 1/5.0f, 1/5.0f, OLF_FADESIZE, 7.0f, 0.5f, 10.0f); + FLARE_GLARE(_lftProjectileWhiteBubbleGlow, 20.0f, 0.3f, 0.8f, 1.0f); + + FLARE_CREATE(_lftProjectileYellowBubbleGlow, 1, "10\\FlareYellowBubble.tex", 0.0f, 180.0f, 1/10.0f, 1/10.0f, OLF_FADESIZE, 7.0f, 0.5f, 10.0f); + FLARE_GLARE(_lftProjectileYellowBubbleGlow, 20.0f, 0.3f, 0.8f, 1.0f); + + FLARE_CREATE(_lftPVSpaceShipWindowFlare, 1, "05\\Flare09.tex", 0.0f, 180.0f, 1/10.0f, 1/10.0f, OLF_FADESIZE, 1.0f, 0.0f, 10.0f); + + FLARE_CREATE(_lftCatmanFireGlow, 1, "12\\Flare12.tex", 0.0f, 180.0f, 1/12.0f, 1/12.0f, OLF_FADESIZE, 7.0f, 0.5f, 128.0f); + + FLARE_CREATE(_lftWhiteGlowFar, 1, "13\\Flare13.tex", 0.0f, 180.0f, 1/16.0f, 1/16.0f, OLF_FADESIZE, 7.0f, 0.5f, 128.0f); + + _bLensFlaresLoaded = TRUE; +}; + +// close lens flares effects +void CloseLensFlares(void) { + _lftStandard.lft_aolfFlares.Clear(); + _lftStandardReflections.lft_aolfFlares.Clear(); + _lftYellowStarRedRing.lft_aolfFlares.Clear(); + _lftYellowStarRedRingFar.lft_aolfFlares.Clear(); + _lftWhiteGlowStarRedRing.lft_aolfFlares.Clear(); + _lftWhiteGlowStar.lft_aolfFlares.Clear(); + _lftWhiteGlowStarNG.lft_aolfFlares.Clear(); + _lftWhiteStarRedRingStreaks.lft_aolfFlares.Clear(); + _lftWhiteStarRedReflections.lft_aolfFlares.Clear(); + _lftBlueStarBlueReflections.lft_aolfFlares.Clear(); + _lftProjectileStarGlow.lft_aolfFlares.Clear(); + _lftProjectileWhiteBubbleGlow.lft_aolfFlares.Clear(); + _lftProjectileYellowBubbleGlow.lft_aolfFlares.Clear(); + _lftPVSpaceShipWindowFlare.lft_aolfFlares.Clear(); + _lftCatmanFireGlow.lft_aolfFlares.Clear(); + _lftWhiteGlowFar.lft_aolfFlares.Clear(); + _bLensFlaresLoaded = FALSE; +}; + +static BOOL _bFatalChecks = FALSE; + + +/************************************************************ + * PLAYER APPEARANCE * + ************************************************************/ +/* Set the model data */ +void SetModelData_t(CModelObject *pmo, const CTFileName &fnmModel) { + ASSERT(pmo != NULL); + pmo->SetData_t(fnmModel); // load the new model data +}; + +/* Set the texture data */ +void SetTextureData_t(CModelObject *pmo, const CTFileName &fnmTexture) { + ASSERT(pmo != NULL); + pmo->mo_toTexture.SetData_t(fnmTexture); // load the texture data +}; + +/* Set model */ +void SetModel_t(CModelObject *pmo, const CTFileName &fnmModel, const CTFileName &fnmTexture) { + SetModelData_t(pmo, fnmModel); + SetTextureData_t(pmo, fnmTexture); +}; + +/* Add attachment to model */ +void ModelAddAttachment_t(CModelObject *pmo, INDEX iAttachment, + const CTFileName &fnmModel, const CTFileName &fnmTexture) { + ASSERT(pmo != NULL); + if (fnmModel==CTString("")) return; + if (pmo==NULL) return; + + CAttachmentModelObject *pamo = pmo->AddAttachmentModel(iAttachment); + SetModel_t(&(pamo->amo_moModelObject), fnmModel, fnmTexture); +}; + +CTString _strFile; +INDEX _ctLines; + +CTString GetNonEmptyLine_t(CTStream &strm) +{ + FOREVER { + if(strm.AtEOF()) { + ThrowF_t(TRANS("Unexpected end of file")); + } + CTString str; + _ctLines++; + strm.GetLine_t(str); + str.TrimSpacesLeft(); + if (str.RemovePrefix("//")) { // skip comments + continue; + } + if (str!="") { + str.TrimSpacesRight(); + return str; + } + } +} + +void FixupFileName_t(CTString &strFnm) +{ + strFnm.TrimSpacesLeft(); + if (!strFnm.RemovePrefix(CTString("TF") +"NM ")) { // must not directly have ids in code + ThrowF_t(TRANS("Expected %s%s before filename"), "TF", "NM"); + } +} + +// skip one block in pmc +void SkipBlock_t(CTStream &strm) +{ + CTString strLine; + // expect to begin with an open bracket + strLine = GetNonEmptyLine_t(strm); + if (strLine!="{") { + ThrowF_t(TRANS("Expected '{'")); + } + // start at level one + INDEX ctLevel = 1; + // repeat + do { + strLine = GetNonEmptyLine_t(strm); + // count brackets + if (strLine=="{") { + ctLevel++; + } else if (strLine=="}") { + ctLevel--; + } + // until we close down all brackets + } while(ctLevel>0); +} + +void ParseAMC_t(CModelObject *pmo, CTStream &strm, BOOL bPreview) +{ + CTString strLine; + // expect to begin with an open bracket + strLine = GetNonEmptyLine_t(strm); + if (strLine!="{") { + ThrowF_t(TRANS("Expected '{'")); + } + + // repeat + FOREVER { + // read one line + strLine = GetNonEmptyLine_t(strm); + + // if closed bracket + if (strLine == "}") { + // finish parsing + return; + } + + + // if a preview-only block + if (strLine.RemovePrefix("PreviewOnly")) { + // if this is a preview + if (bPreview) { + // keep parsing it + ParseAMC_t(pmo, strm, bPreview); + // if this is not a preview + } else { + // skip that block + SkipBlock_t(strm); + } + // if include block + } else if (strLine.RemovePrefix("Include:")) { + // open the new file + FixupFileName_t(strLine); + CTFileStream strmIncluded; + strmIncluded.Open_t(strLine); + + // include it + INDEX ctLinesOld = _ctLines; + CTString strFileOld = _strFile; + _ctLines = 0; + _strFile = strLine; + ParseAMC_t(pmo, strmIncluded, bPreview); + strmIncluded.Close(); + _ctLines = ctLinesOld; + _strFile = strFileOld; + + // if setting the model + } else if (strLine.RemovePrefix("Model:")) { + // set the model + FixupFileName_t(strLine); + pmo->SetData_t(strLine); + + // if setting an anim for the model + } else if (strLine.RemovePrefix("Animation:")) { + // get animation number + INDEX iAnim = -1; + strLine.ScanF("%d", &iAnim); + if (iAnim<0) { + ThrowF_t(TRANS("Invalid animation number")); + } + // check it + if (iAnim>=pmo->GetAnimsCt()) { + ThrowF_t(TRANS("Animation %d does not exist in that model"), iAnim); + }; + // set it + pmo->PlayAnim(iAnim, AOF_LOOPING); + + // if texture + } else if (strLine.RemovePrefix("Texture:")) { + // set texture + FixupFileName_t(strLine); + pmo->mo_toTexture.SetData_t(strLine); + + // if specular + } else if (strLine.RemovePrefix("Specular:")) { + // set texture + FixupFileName_t(strLine); + pmo->mo_toSpecular.SetData_t(strLine); + + // if reflection + } else if (strLine.RemovePrefix("Reflection:")) { + // set texture + FixupFileName_t(strLine); + pmo->mo_toReflection.SetData_t(strLine); + + // if specular + } else if (strLine.RemovePrefix("Bump:")) { + // set texture + FixupFileName_t(strLine); + pmo->mo_toBump.SetData_t(strLine); + + // if attachment + } else if (strLine.RemovePrefix("Attachment:")) { + // get attachment number + INDEX iAtt = -1; + strLine.ScanF("%d", &iAtt); + if (iAtt<0) { + ThrowF_t(TRANS("Invalid attachment number")); + } + // create attachment + CModelData *pmd = (CModelData*)pmo->GetData(); + if (iAtt>=pmd->md_aampAttachedPosition.Count()) { + ThrowF_t(TRANS("Attachment %d does not exist in that model"), iAtt); + }; + CAttachmentModelObject *pamo = pmo->AddAttachmentModel(iAtt); + + // recursively parse it + ParseAMC_t(&pamo->amo_moModelObject, strm, bPreview); + } else { + ThrowF_t(TRANS("Expected texture or attachment")); + } + } +} + +/* Set player appearance */ +BOOL SetPlayerAppearance_internal(CModelObject *pmo, const CTFileName &fnmAMC, CTString &strName, BOOL bPreview) +{ + // try to + try { + // open the config file + CTFileStream strm; + strm.Open_t(fnmAMC); + + _ctLines = 0; + _strFile = fnmAMC; + + // read the name + CTString strLine = GetNonEmptyLine_t(strm); + if (!strLine.RemovePrefix("Name: ")) { + ThrowF_t(TRANS("Expected name")); + } + strName = strLine; + strName.TrimSpacesLeft(); + + // parse the file recursively starting at root model object and add everything + ParseAMC_t(pmo, strm, bPreview); + return TRUE; + + // if anything failed + } catch (char *strError) { + // report error + CPrintF(TRANS("Cannot load player model:\n%s (%d) : %s\n"), + (const char*)_strFile, _ctLines, strError); + return FALSE; + } +} + +BOOL SetPlayerAppearance(CModelObject *pmo, CPlayerCharacter *ppc, CTString &strName, BOOL bPreview) +{ + // first kill any existing model + pmo->SetData(NULL); + pmo->mo_toTexture.SetData(NULL); + pmo->mo_toSpecular.SetData(NULL); + pmo->mo_toReflection.SetData(NULL); + pmo->mo_toBump.SetData(NULL); + pmo->RemoveAllAttachmentModels(); + + DECLARE_CTFILENAME(fnmDefault, "ModelsMP\\Player\\SeriousSam.amc"); + + // if no character, or player models are disabled + if (ppc==NULL) { + // set default appearance + BOOL bSucceeded = SetPlayerAppearance_internal(pmo, fnmDefault, strName, bPreview); + if (!bSucceeded) { + FatalError(TRANS("Cannot load default player model!")); + } + return FALSE; + } + + // get filename from the settings + CPlayerSettings *pps = (CPlayerSettings *)ppc->pc_aubAppearance; + CTFileName fnmModelFile = pps->GetModelFilename(); + // if dummy (empty settings) + if (fnmModelFile.FileName()=="") { + // use default + fnmModelFile = fnmDefault; + } + + extern INDEX plr_bOnlySam; + if (!plr_bOnlySam && SetPlayerAppearance_internal(pmo, fnmModelFile, strName, bPreview)) { + return TRUE; + } else if (SetPlayerAppearance_internal(pmo, fnmDefault, strName, bPreview)) { // HAVE TO SET DEFAULT HERE! + return TRUE; + } else { + return FALSE; + } +} + + +/************************************************************ + * DEBUGGING FUNCTIONS * + ************************************************************/ +// debugging functions +const char *PrintConsole(void) +{ + _RPT1(_CRT_WARN, "%s", CON_GetBuffer()); + return NULL; +} + +const char *PrintStack(CEntity *pen) +{ + return pen->PrintStackDebug(); +} + + + +/************************************************************ + * DEBRIS * + ************************************************************/ +EntityInfoBodyType _Eeibt; +enum DebrisParticlesType _dptParticles; +enum BasicEffectType _betStain; +FLOAT3D _vSpeed; +FLOAT3D _vSpawnerSpeed; +FLOAT _fEntitySize; +FLOAT _fConeSize; +FLOAT _fSpeedUp; +COLOR _colDebris; + +// debris spawning +void Debris_Begin( + EntityInfoBodyType Eeibt, + enum DebrisParticlesType dptParticles, + enum BasicEffectType betStain, + FLOAT fEntitySize, // entity size in meters + const FLOAT3D &vSpeed, + const FLOAT3D &vSpawnerSpeed, // how fast was the entity moving + const FLOAT fConeSize, // size multiplier for debris cone + const FLOAT fSpeedUp, // size multiplier for debris catapulting up (0-no multiply) + const COLOR colDebris /*=C_WHITE*/ // multiply color +) +{ + _Eeibt = Eeibt ; + _dptParticles = dptParticles; + _betStain = betStain ; + _vSpeed = vSpeed ; + _vSpawnerSpeed = vSpawnerSpeed; + _fEntitySize = fEntitySize ; + _fConeSize = fConeSize ; + _fSpeedUp = fSpeedUp ; + _colDebris = colDebris ; +} + +CEntityPointer Debris_Spawn( + CEntity *penSpawner, + CEntity *penComponents, + SLONG idModelComponent, + SLONG idTextureComponent, + SLONG idReflectionTextureComponent, + SLONG idSpecularTextureComponent, + SLONG idBumpTextureComponent, + INDEX iModelAnim, + FLOAT fSize, + const FLOAT3D &vPosRatio) +{ + // create debris at same world as spawner + FLOAT3D vPos; + FLOAT3D vStretch=FLOAT3D(1,1,1); + if( (penSpawner->en_RenderType==CEntity::RT_MODEL || + penSpawner->en_RenderType==CEntity::RT_EDITORMODEL) && + penSpawner->GetModelObject()!=NULL) + { + vStretch=penSpawner->GetModelObject()->mo_Stretch; + } + penSpawner->GetEntityPointRatio(vPosRatio, vPos); + CEntityPointer penDebris = penSpawner->GetWorld()->CreateEntity_t( + CPlacement3D(vPos, ANGLE3D(0,0,0)), CTFILENAME("Classes\\Debris.ecl")); + // prepare parameters + ESpawnDebris eSpawn; + eSpawn.bImmaterialASAP=FALSE; + eSpawn.bCustomShading=FALSE; + eSpawn.Eeibt = _Eeibt; + eSpawn.dptParticles = _dptParticles; + eSpawn.betStain = _betStain; + eSpawn.pmd = penComponents->GetModelDataForComponent(idModelComponent); + eSpawn.ptd = penComponents->GetTextureDataForComponent(idTextureComponent); + eSpawn.ptdRefl = penComponents->GetTextureDataForComponent(idReflectionTextureComponent); + eSpawn.ptdSpec = penComponents->GetTextureDataForComponent(idSpecularTextureComponent); + eSpawn.ptdBump = penComponents->GetTextureDataForComponent(idBumpTextureComponent); + eSpawn.iModelAnim = iModelAnim; + eSpawn.colDebris = _colDebris; + eSpawn.vStretch = FLOAT3D(1,1,1); + if (fSize==0) { + eSpawn.fSize = 1.0f; + } else { + eSpawn.fSize = _fEntitySize*fSize; + } + // initialize it + penDebris->Initialize(eSpawn); + + FLOAT fCone = _fEntitySize*1.0f; + if (_vSpeed.Length()==0) { + fCone = 0; + } + FLOAT fRndX = (penSpawner->FRnd()*2-1)*fCone*_fConeSize; + FLOAT fRndY = (penSpawner->FRnd()*2-1)*fCone*_fConeSize; + FLOAT fRndZ = (penSpawner->FRnd()*2-1)*fCone*_fConeSize; + + FLOAT fRndH = penSpawner->FRnd(); + FLOAT fRndP = penSpawner->FRnd(); + FLOAT fRndB = penSpawner->FRnd(); + + FLOAT3D vUp; + const FLOATmatrix3D &m = penSpawner->GetRotationMatrix(); + vUp(1) = m(1,2); + vUp(2) = m(2,2); + vUp(3) = m(3,2); + + //FLOAT fStrength = _vSpeed.Length(); + + // speed it up + ((CMovableEntity&)*penDebris).LaunchAsFreeProjectile( + _vSpawnerSpeed+_vSpeed+FLOAT3D(fRndX, fRndY, fRndZ)+vUp*_fSpeedUp, (CMovableEntity*)penSpawner); + ((CMovableEntity&)*penDebris).SetDesiredRotation( + ANGLE3D(fRndH*360.0f-180.0f, fRndP*360.0f-180.0f, fRndB*360.0f-180.0f)); + + return penDebris; +} + +CEntityPointer Debris_Spawn_Independent( + CEntity *penSpawner, + CEntity *penComponents, + SLONG idModelComponent, + SLONG idTextureComponent, + SLONG idReflectionTextureComponent, + SLONG idSpecularTextureComponent, + SLONG idBumpTextureComponent, + INDEX iModelAnim, + FLOAT fSize, + CPlacement3D plAbsolutePlacement, + FLOAT3D vTranslation, + ANGLE3D aRotation) +{ + // create debris at same world as spawner + CEntityPointer penDebris = penSpawner->GetWorld()->CreateEntity_t( + plAbsolutePlacement, CTFILENAME("Classes\\Debris.ecl")); + // prepare parameters + ESpawnDebris eSpawn; + eSpawn.bImmaterialASAP=FALSE; + eSpawn.bCustomShading=FALSE; + eSpawn.Eeibt = _Eeibt; + eSpawn.dptParticles = _dptParticles; + eSpawn.betStain = _betStain; + eSpawn.pmd = penComponents->GetModelDataForComponent(idModelComponent); + eSpawn.ptd = penComponents->GetTextureDataForComponent(idTextureComponent); + eSpawn.ptdRefl = penComponents->GetTextureDataForComponent(idReflectionTextureComponent); + eSpawn.ptdSpec = penComponents->GetTextureDataForComponent(idSpecularTextureComponent); + eSpawn.ptdBump = penComponents->GetTextureDataForComponent(idBumpTextureComponent); + eSpawn.iModelAnim = iModelAnim; + eSpawn.colDebris = _colDebris; + eSpawn.fSize = fSize; + eSpawn.vStretch = FLOAT3D(1,1,1); + + // initialize it + penDebris->Initialize(eSpawn); + + // move it + ((CMovableEntity&)*penDebris).LaunchAsFreeProjectile( + vTranslation, (CMovableEntity*)penSpawner); + ((CMovableEntity&)*penDebris).SetDesiredRotation(aRotation); + + return penDebris; +} + +CEntityPointer Debris_Spawn_Template( + EntityInfoBodyType eibt, + enum DebrisParticlesType dptParticles, + enum BasicEffectType betStain, + CModelHolder2 *penmhDestroyed, + CEntity *penComponents, + CModelHolder2 *penmhTemplate, + FLOAT3D vStretch, + FLOAT fSize, + CPlacement3D plAbsolutePlacement, + FLOAT3D vLaunchSpeed, + ANGLE3D aRotSpeed, + BOOL bDebrisImmaterialASAP, + FLOAT fDustStretch, + COLOR colBurning) +{ + if(penmhTemplate==NULL || penmhTemplate->GetModelObject()==NULL) + { + return NULL; + } + // create debris at same world as spawner + CEntityPointer penDebris = penmhDestroyed->GetWorld()->CreateEntity_t( + plAbsolutePlacement, CTFILENAME("Classes\\Debris.ecl")); + // prepare parameters + ESpawnDebris eSpawn; + eSpawn.bImmaterialASAP=bDebrisImmaterialASAP; + eSpawn.fDustStretch=fDustStretch; + eSpawn.Eeibt = eibt; + eSpawn.dptParticles = dptParticles; + eSpawn.betStain = betStain; + CModelObject &mo=*penmhTemplate->GetModelObject(); + eSpawn.pmd = mo.GetData(); + eSpawn.ptd = (CTextureData*)mo.mo_toTexture.GetData(); + eSpawn.ptdRefl = (CTextureData*)mo.mo_toReflection.GetData(); + eSpawn.ptdSpec = (CTextureData*)mo.mo_toSpecular.GetData(); + eSpawn.ptdBump = (CTextureData*)mo.mo_toBump.GetData(); + eSpawn.iModelAnim = mo.GetAnim(); + eSpawn.colDebris = colBurning; + eSpawn.fSize = 1.0f; + eSpawn.vStretch = vStretch; + eSpawn.bCustomShading=FALSE; + eSpawn.penFallFXPapa=penmhTemplate; + if( penmhDestroyed->m_cstCustomShading==CST_FULL_CUSTOMIZED) + { + eSpawn.bCustomShading=TRUE; + eSpawn.aShadingDirection=penmhDestroyed->m_aShadingDirection; + eSpawn.colCustomDiffuse=penmhDestroyed->m_colLight; + eSpawn.colCustomAmbient=penmhDestroyed->m_colAmbient; + } + + // initialize it + penDebris->Initialize(eSpawn); + + // move it + const FLOATmatrix3D &m = penDebris->GetRotationMatrix(); + ((CMovableEntity&)*penDebris).LaunchAsFreeProjectile( vLaunchSpeed*!m, (CMovableEntity*)penmhDestroyed); + ((CMovableEntity&)*penDebris).SetDesiredRotation(aRotSpeed); + + return penDebris; +} + +// info structure +static EntityInfo eiFlesh = {EIBT_FLESH}; +static EntityInfo eiWater = {EIBT_WATER}; +static EntityInfo eiRock = {EIBT_ROCK }; +static EntityInfo eiFire = {EIBT_FIRE }; +static EntityInfo eiAir = {EIBT_AIR }; +static EntityInfo eiBones = {EIBT_BONES}; +static EntityInfo eiWood = {EIBT_WOOD }; +static EntityInfo eiMetal = {EIBT_METAL}; +static EntityInfo eiRobot = {EIBT_ROBOT}; +static EntityInfo eiIce = {EIBT_ICE }; + +// get default entity info for given body type +EntityInfo *GetStdEntityInfo(EntityInfoBodyType eibt) +{ + switch(eibt) { + case EIBT_FLESH: {return &eiFlesh; } break; + case EIBT_WATER: {return &eiWater; } break; + case EIBT_ROCK : {return &eiRock ; } break; + case EIBT_FIRE : {return &eiFire ; } break; + case EIBT_AIR : {return &eiAir ; } break; + case EIBT_BONES: {return &eiBones; } break; + case EIBT_WOOD : {return &eiWood ; } break; + case EIBT_METAL: {return &eiMetal; } break; + case EIBT_ROBOT: {return &eiRobot; } break; + case EIBT_ICE : {return &eiIce ; } break; + default: {return NULL;} break; + }; +} + + + +/************************************************************ + * DAMAGE CONTROL FUNCTIONS * + ************************************************************/ +// damage control functions +FLOAT DamageStrength(EntityInfoBodyType eibtBody, enum DamageType dtDamage) +{ + switch(eibtBody) { + case EIBT_FLESH: + return 1.0f; + case EIBT_WATER: + switch(dtDamage) { + case DMT_CLOSERANGE: return 0.0f; + case DMT_BURNING: return 0.0f; + case DMT_DROWNING: return 0.0f; + } + return 1.0f; + case EIBT_ROCK : + switch(dtDamage) { + case DMT_CLOSERANGE: return 0.0f; + case DMT_BURNING: return 0.0f; + case DMT_FREEZING: return 0.0f; + } + return 1.0f; + case EIBT_ICE : + switch(dtDamage) { + case DMT_CLOSERANGE: return 0.5f; + case DMT_BURNING: return 3.0f; + case DMT_FREEZING: return 0.0f; + } + return 1.0f; + case EIBT_FIRE : + switch(dtDamage) { + case DMT_CLOSERANGE: return 0.5f; + case DMT_BURNING: return 0.0f; + } + return 1.0f; + case EIBT_AIR : + switch(dtDamage) { + case DMT_CLOSERANGE: return 0.0f; + case DMT_BURNING: return 0.5f; + } + return 1.0f; + case EIBT_BONES: + switch(dtDamage) { + case DMT_FREEZING: return 0.0f; + } + return 1.0f; + case EIBT_WOOD : + switch(dtDamage) { + case DMT_FREEZING: return 0.0f; + } + return 1.0f; + case EIBT_METAL: + switch(dtDamage) { + case DMT_CLOSERANGE: return 0.0f; + case DMT_BURNING: return 0.0f; + case DMT_FREEZING: return 0.0f; + } + return 1.0f; + case EIBT_ROBOT: + switch(dtDamage) { + case DMT_CLOSERANGE:return 0.5f; + case DMT_BURNING: return 0.5f; + case DMT_FREEZING: return 0.5f; + } + return 1.0f; + default: + ASSERT(FALSE); + return 1.0f; + } +} + +// Print center screen message +void PrintCenterMessage(CEntity *penThis, CEntity *penCaused, + const CTString &strMessage, TIME tmLength, enum MessageSound mssSound) +{ + penCaused = FixupCausedToPlayer(penThis, penCaused); + + ECenterMessage eMsg; + eMsg.strMessage = strMessage; + eMsg.tmLength = tmLength; + eMsg.mssSound = mssSound; + penCaused->SendEvent(eMsg); +} + + +// i.e. weapon sound when fireing or exploding +void SpawnRangeSound( CEntity *penPlayer, CEntity *penPos, enum SoundType st, FLOAT fRange) +{ + // if not really player + if (!IsDerivedFromClass(penPlayer, "Player")) { + // do nothing + return; + } + // sound event + ESound eSound; + eSound.EsndtSound = st; + eSound.penTarget = penPlayer; + penPos->SendEventInRange( eSound, FLOATaabbox3D(penPos->GetPlacement().pl_PositionVector, fRange)); +} + +// get some player for trigger source if any is existing +CEntity *FixupCausedToPlayer(CEntity *penThis, CEntity *penCaused, BOOL bWarning/*=TRUE*/) +{ + if (penCaused!=NULL && IsOfClass(penCaused, "Player")) { + return penCaused; + } + + if (bWarning && (ent_bReportBrokenChains || GetSP()->sp_bQuickTest)) { + CPrintF(TRANS("WARNING: Triggering chain broken, entity: %s-%s(%s)\n"), + (const char*)penThis->GetName(), + (const char*)penThis->GetDescription(), + (const char*)penThis->GetClass()->GetName()); + } + + INDEX ctPlayers = penThis->GetMaxPlayers(); + if (ctPlayers==0) { + return NULL; + } + + CEntity *penClosestPlayer = NULL; + FLOAT fClosestPlayer = UpperLimit(0.0f); + + // for all players + for (INDEX iPlayer=0; iPlayerGetMaxPlayers(); iPlayer++) { + CEntity *penPlayer = penThis->GetPlayerEntity(iPlayer); + // if player exists + if (penPlayer!=NULL) { + // calculate distance to player + FLOAT fDistance = + (penPlayer->GetPlacement().pl_PositionVector-penThis->GetPlacement().pl_PositionVector).Length(); + // update if closer + if (fDistance(fRatio, q0, q1); + FLOAT3D v = Lerp(v0, v1, fRatio); + + pl.pl_PositionVector = v; + + FLOATmatrix3D m; + q.ToMatrix(m); + DecomposeRotationMatrixNoSnap(pl.pl_OrientationAngle, m); + + return pl; +} + +FLOAT GetGameDamageMultiplier(void) +{ + FLOAT fGameDamageMultiplier = 1.0f; + FLOAT fExtraStrength = GetSP()->sp_fExtraEnemyStrength; + if (fExtraStrength>0) { + fGameDamageMultiplier*=1.0f/(1+fExtraStrength); + } + FLOAT fExtraStrengthPerPlayer = GetSP()->sp_fExtraEnemyStrengthPerPlayer; + if (fExtraStrengthPerPlayer>0) { + INDEX ctPlayers = _pNetwork->ga_sesSessionState.GetPlayersCount(); + fGameDamageMultiplier*=1.0f/(1+fExtraStrengthPerPlayer*ClampDn(ctPlayers-1.0f, 0.0f)); + } + if (GetSP()->sp_gdGameDifficulty==CSessionProperties::GD_TOURIST) { + fGameDamageMultiplier *= 2.0f; + } + return fGameDamageMultiplier; +} + + +// get entity's serious damage multiplier +FLOAT GetSeriousDamageMultiplier( CEntity *pen) +{ + if( !IsOfClass(pen,"Player")) return 1.0f; + const TIME tmNow = _pTimer->CurrentTick(); + const TIME tmDamage = ((CPlayer*)pen)->m_tmSeriousDamage; + if( tmDamage>tmNow) return 4.0f; + return 1.0f; +} + +class CWorldSettingsController *GetWSC(CEntity *pen) +{ + CWorldSettingsController *pwsc = NULL; + // obtain bcg viewer + class CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) pen->GetWorld()->GetBackgroundViewer(); + if( penBcgViewer != NULL) { + // obtain world settings controller + pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController; + } + return pwsc; +} + diff --git a/Sources/EntitiesMP/Common/Common.h b/Sources/EntitiesMP/Common/Common.h new file mode 100644 index 0000000..7a1a030 --- /dev/null +++ b/Sources/EntitiesMP/Common/Common.h @@ -0,0 +1,306 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// common headers for flesh entity classes + + +#define SURFACE_SAND 9 +#define SURFACE_WATER 12 +#define SURFACE_RED_SAND 13 +#define SURFACE_GRASS 17 +#define SURFACE_GRASS_SLIDING 19 +#define SURFACE_GRASS_NOIMPACT 20 +#define SURFACE_WOOD 18 +#define SURFACE_SNOW 21 + +// Max ammo +#define MAX_BULLETS INDEX(500) +#define MAX_SHELLS INDEX(100) +#define MAX_ROCKETS INDEX(50) +#define MAX_GRENADES INDEX(50) +#define MAX_NAPALM INDEX(500) +#define MAX_ELECTRICITY INDEX(400) +#define MAX_IRONBALLS INDEX(30) +//#define MAX_NUKEBALLS INDEX(3) +#define MAX_SNIPERBULLETS INDEX(50) + +// Bit shifters for ammo +#define AMMO_BULLETS 0 +#define AMMO_SHELLS 1 +#define AMMO_ROCKETS 2 +#define AMMO_GRENADES 3 +#define AMMO_NAPALM 4 +#define AMMO_ELECTRICITY 5 +//#define AMMO_NUKEBALLS 6 +#define AMMO_IRONBALLS 7 +#define AMMO_SNIPERBULLETS 8 + +#define BLOOD_SPILL_RED RGBAToColor(250,20,20,255) +#define BLOOD_SPILL_GREEN RGBAToColor(0,250,0,255) + +// Ammo mana Value +#define AV_SHELLS INDEX(70) +#define AV_BULLETS INDEX(10) +#define AV_ROCKETS INDEX(150) +#define AV_GRENADES INDEX(150) +#define AV_ELECTRICITY INDEX(250) +#define AV_IRONBALLS INDEX(700) +//#define AV_NUKEBALLS INDEX(1800) +#define AV_NAPALM INDEX(200) +#define AV_SNIPERBULLETS INDEX(200) + +// used for invisibility powerup +#define INVISIBILITY_ALPHA_LOCAL 0x55 +#define INVISIBILITY_ALPHA_REMOTE 0x11 + +enum EmptyShellType { + ESL_BULLET = 0, + ESL_SHOTGUN = 1, + ESL_BUBBLE = 2, + ESL_BULLET_SMOKE = 3, + ESL_SHOTGUN_SMOKE = 4, + ESL_COLT_SMOKE = 5, +}; +// empty shell launch info +#define MAX_FLYING_SHELLS 32 +struct ShellLaunchData { + FLOAT sld_fSize; // size multiplier + FLOAT3D sld_vPos; // launch position + FLOAT3D sld_vSpeed; // launch speed + FLOAT3D sld_vUp; // up vector in moment of launch + FLOAT sld_tmLaunch; // time of launch + EmptyShellType sld_estType; // shell type +}; +#define ShellLaunchData_array m_asldData[MAX_FLYING_SHELLS] + +// player bullet spray fx list +#define MAX_BULLET_SPRAYS 32 +struct BulletSprayLaunchData { + INDEX bsld_iRndBase; // random base + FLOAT3D bsld_vPos; // launch position + FLOAT3D bsld_vG; // gravity vector + EffectParticlesType bsld_eptType; // type + FLOAT bsld_tmLaunch; // time of launch + FLOAT3D bsld_vStretch; // stretch +}; +#define BulletSprayLaunchData_array m_absldData[MAX_BULLET_SPRAYS] + +#define MAX_GORE_SPRAYS 32 +struct GoreSprayLaunchData { + FLOAT3D gsld_vPos; // launch position + FLOAT3D gsld_v3rdPos; // launch position for 3rd perspective + FLOAT3D gsld_vG; // gravity vector + FLOAT gsld_fGA; // gravity strength + SprayParticlesType gsld_sptType; // type + FLOATaabbox3D gsld_boxHitted; // box of hitted object + FLOAT3D gsld_vSpilDirection; // spill direction + FLOAT gsld_fDamagePower; // damage power + FLOAT gsld_tmLaunch; // time of launch + COLOR gsld_colParticles; // color of particles +}; +#define GoreSprayLaunchData_array m_agsldData[MAX_GORE_SPRAYS] + +// world change +struct WorldChange { + CTString strGroup; // group name + CPlacement3D plLink; // link placement for relative change + INDEX iType; // change type +}; +extern struct WorldChange _SwcWorldChange; + +// entity info +struct EntityInfo { + EntityInfoBodyType Eeibt; // body type + FLOAT fMass; // mass (in kg) + FLOAT vSourceCenter[3]; // body point (offset from handle) when entity look another entity + FLOAT vTargetCenter[3]; // body point (offset from handle) when entity is target of look +}; + +// entity info +struct EntityStats { + CTString es_strName; + INDEX es_ctCount; + INDEX es_ctAmmount; + FLOAT es_fValue; + INDEX es_iScore; +}; + +// statistics data for player stats management +struct DECL_DLL PlayerStats { + INDEX ps_iScore; + INDEX ps_iKills; + INDEX ps_iDeaths; + INDEX ps_iSecrets; + TIME ps_tmTime; + + PlayerStats(void) + { + ps_iScore = 0; + ps_iKills = 0; + ps_iDeaths = 0; + ps_iSecrets = 0; + ps_tmTime = 0.0f; + } +}; + +// get info position for entity +DECL_DLL void GetEntityInfoPosition(CEntity *pen, FLOAT *pf, FLOAT3D &vPos); +// get source and target positions for ray cast +DECL_DLL void GetPositionCastRay(CEntity *penSource, CEntity *penTarget, FLOAT3D &vSource, FLOAT3D &vTarget); + +// set bool from bool enum type +DECL_DLL void SetBoolFromBoolEType(BOOL &bSet, BoolEType bet); +// send event to target +DECL_DLL void SendToTarget(CEntity *penSendEvent, EventEType eetEventType, CEntity *penCaused = NULL); +// send event in range +DECL_DLL void SendInRange(CEntity *penSource, EventEType eetEventType, const FLOATaabbox3D &boxRange); + +// spawn reminder +DECL_DLL CEntityPointer SpawnReminder(CEntity *penOwner, FLOAT fWaitTime, INDEX iValue); +// spawn flame +DECL_DLL CEntityPointer SpawnFlame(CEntity *penOwner, CEntity *penAttach, const FLOAT3D &vSource); + +// Set components +DECL_DLL void SetComponents(CEntity *pen, CModelObject &mo, ULONG ulIDModel, ULONG ulIDTexture, + ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture); +// Add attachment to model +DECL_DLL void AddAttachmentToModel(CEntity *pen, CModelObject &mo, INDEX iAttachment, ULONG ulIDModel, ULONG ulIDTexture, + ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture); +// Remove attachment from model +DECL_DLL void RemoveAttachmentFromModel(CModelObject &mo, INDEX iAttachment); + +// Kick entity +DECL_DLL void KickEntity(CEntity *penTarget, FLOAT3D vSpeed); + + +// lens flare variables +extern CLensFlareType _lftStandard; +extern CLensFlareType _lftStandardReflections; +extern CLensFlareType _lftYellowStarRedRing; +extern CLensFlareType _lftYellowStarRedRingFar; +extern CLensFlareType _lftWhiteGlowStarRedRing; +extern CLensFlareType _lftWhiteGlowStar; +extern CLensFlareType _lftWhiteGlowStarNG; +extern CLensFlareType _lftWhiteStarRedRingStreaks; +extern CLensFlareType _lftWhiteStarRedReflections; +extern CLensFlareType _lftBlueStarBlueReflections; +extern CLensFlareType _lftProjectileStarGlow; +extern CLensFlareType _lftProjectileWhiteBubbleGlow; +extern CLensFlareType _lftProjectileYellowBubbleGlow; +extern CLensFlareType _lftPVSpaceShipWindowFlare; +extern CLensFlareType _lftCatmanFireGlow; +extern CLensFlareType _lftWhiteGlowFar; +// init lens flare effects +void InitLensFlares(void); +// close lens flares effects +void CloseLensFlares(void); + +DECL_DLL BOOL SetPlayerAppearanceCfunc(void* pArgs); +DECL_DLL BOOL SetPlayerAppearance(CModelObject *mo, CPlayerCharacter *ppc, CTString &strName, BOOL bPreview); + +// debugging functions +DECL_DLL const char *PrintConsole(void); +DECL_DLL const char *PrintStack(CEntity *pen); + +// debris spawning +DECL_DLL void Debris_Begin( + EntityInfoBodyType Eeibt, + enum DebrisParticlesType dptParticles, + enum BasicEffectType betStain, + FLOAT fEntitySize, // entity size in meters + const FLOAT3D &vSpeed, + const FLOAT3D &vSpawnerSpeed, // how fast was the entity moving + const FLOAT fConeSize, // size multiplier for debris cone + const FLOAT fSpeedUp, // size multiplier for debris catapulting up (0-no multiply) + const COLOR colDebris=C_WHITE // multiply color +); +DECL_DLL CEntityPointer Debris_Spawn( + CEntity *penSpawner, + CEntity *penComponents, + SLONG idModelComponent, + SLONG idTextureComponent, + SLONG idReflectionTextureComponent, + SLONG idSpecularTextureComponent, + SLONG idBumpTextureComponent, + INDEX iModelAnim, + FLOAT fSize, // size relative to entity size (or 0 for absolute stretch of 1) + const FLOAT3D &vPosRatio); +DECL_DLL CEntityPointer Debris_Spawn_Independent( + CEntity *penSpawner, + CEntity *penComponents, + SLONG idModelComponent, + SLONG idTextureComponent, + SLONG idReflectionTextureComponent, + SLONG idSpecularTextureComponent, + SLONG idBumpTextureComponent, + INDEX iModelAnim, + FLOAT fSize, + CPlacement3D plAbsolutePlacement, + FLOAT3D vTranslation, + ANGLE3D aRotation); +DECL_DLL CEntityPointer Debris_Spawn_Template( + EntityInfoBodyType eibt, + enum DebrisParticlesType dptParticles, + enum BasicEffectType betStain, + class CModelHolder2 *penmhDestroyed, + CEntity *penComponents, + class CModelHolder2 *penmh2, + FLOAT3D vStretch, + FLOAT fSize, + CPlacement3D plAbsolutePlacement, + FLOAT3D vLaunchSpeed, + ANGLE3D aRotSpeed, + BOOL bDebrisImmaterialASAP, + FLOAT fDustStretch, + COLOR colBurning); + +// get default entity info for given body type +DECL_DLL EntityInfo *GetStdEntityInfo(EntityInfoBodyType eibt); +// damage control functions +DECL_DLL FLOAT DamageStrength(EntityInfoBodyType eibtBody, enum DamageType dtDamage); + +// Print center screen message +DECL_DLL void PrintCenterMessage(CEntity *penThis, CEntity *penTarget, + const CTString &strMessage, TIME tmLength, enum MessageSound mssSound); + +// get name of a key item +DECL_DLL const char *GetKeyName(enum KeyItemType kit); + +// get session properties +DECL_DLL inline const CSessionProperties *GetSP(void) +{ + return (const CSessionProperties *)_pNetwork->GetSessionProperties(); +} + +// i.e. weapon sound when fireing or exploding +DECL_DLL void SpawnRangeSound( CEntity *penPlayer, CEntity *penPos, enum SoundType st, FLOAT fRange); + +// get some player for trigger source if any is existing +DECL_DLL CEntity *FixupCausedToPlayer(CEntity *penThis, CEntity *penCaused, BOOL bWarning=TRUE); + +// precisely lerp between two placement using quaternions +DECL_DLL CPlacement3D LerpPlacementsPrecise(const CPlacement3D &pl0, const CPlacement3D &pl1, FLOAT fRatio); + +// obtain game extra damage per enemy and per player +DECL_DLL FLOAT GetGameDamageMultiplier(void); + +// get entity's serious damage multiplier +DECL_DLL FLOAT GetSeriousDamageMultiplier( CEntity *pen); + +// get current world settings controller +DECL_DLL class CWorldSettingsController *GetWSC(CEntity *pen); + +// helper functions + +// distance between two entities +DECL_DLL inline FLOAT DistanceTo(CEntity *penE1, CEntity *penE2) { + return (penE1->GetPlacement().pl_PositionVector - + penE2->GetPlacement().pl_PositionVector).Length(); +} + +BulletHitType GetBulletHitTypeForSurface(INDEX iSurfaceType); +EffectParticlesType GetParticleEffectTypeForSurface(INDEX iSurfaceType); +// spawn effect from hit type +void SpawnHitTypeEffect(CEntity *pen, enum BulletHitType bhtType, BOOL bSound, FLOAT3D vHitNormal, FLOAT3D vHitPoint, + FLOAT3D vIncommingBulletDir, FLOAT3D vDistance); + +#define FRndIn(a, b) (a + FRnd()*(b - a)) diff --git a/Sources/EntitiesMP/Common/EmanatingParticles.cpp b/Sources/EntitiesMP/Common/EmanatingParticles.cpp new file mode 100644 index 0000000..7de4cf4 --- /dev/null +++ b/Sources/EntitiesMP/Common/EmanatingParticles.cpp @@ -0,0 +1,188 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" + +#define ID_EMITER_VER "EMT0" + +CEmittedParticle::CEmittedParticle(void) +{ + ep_tmEmitted=-1; + ep_tmLife=1.0f; + ep_colColor=C_WHITE|CT_OPAQUE; + ep_vSpeed=FLOAT3D(0,0,0); + ep_vPos=FLOAT3D(0,0,0); + ep_fStretch=1; + ep_fRot=0; + ep_fRotSpeed=0; +} + +void CEmittedParticle::Write_t( CTStream &strm) +{ + strm.WriteRawChunk_t( this, sizeof(CEmittedParticle)); +} + +void CEmittedParticle::Read_t( CTStream &strm) +{ + strm.ReadRawChunk_t( this, sizeof(CEmittedParticle)); +} + +CEmiter::CEmiter(void) +{ + em_etType=ET_AIR_ELEMENTAL; + em_bInitialized=FALSE; + em_tmStart=-1; + em_tmLife=0; + em_vG=FLOAT3D(0,1,0); + em_colGlobal=C_WHITE|CT_OPAQUE; + em_iGlobal=0; + em_aepParticles.Clear(); +} + +void CEmiter::Initialize(CEntity *pen) +{ + em_vG=GetGravity(pen); + em_bInitialized=TRUE; + em_tmStart=_pTimer->CurrentTick(); + em_iGlobal=0; +} + +FLOAT3D CEmiter::GetGravity(CEntity *pen) +{ + if(pen->GetPhysicsFlags()&EPF_MOVABLE) + { + return ((CMovableEntity *)pen)->en_vGravityDir* + ((CMovableEntity *)pen)->en_fGravityA; + } + return FLOAT3D(0,-10.0f,0); +} + +void CEmiter::AddParticle(FLOAT3D vPos, FLOAT3D vSpeed, FLOAT fRot, FLOAT fRotSpeed, + FLOAT tmBirth, FLOAT tmLife, FLOAT fStretch, COLOR colColor) +{ + CEmittedParticle &em=em_aepParticles.Push(); + em.ep_fLastRot=fRot; + em.ep_fRot=fRot; + em.ep_fRotSpeed=fRotSpeed; + em.ep_vLastPos=vPos; + em.ep_vPos=vPos; + em.ep_vSpeed=vSpeed; + em.ep_colLastColor=colColor; + em.ep_colColor=colColor; + em.ep_tmEmitted=tmBirth; + em.ep_tmLife=tmLife; + em.ep_fStretch=fStretch; +} + +void CEmiter::AnimateParticles(void) +{ + FLOAT tmNow=_pTimer->CurrentTick(); + INDEX ctCount=em_aepParticles.Count(); + INDEX iCurrent=0; + while( iCurrentep.ep_tmEmitted+ep.ep_tmLife) + { + CEmittedParticle &emLast=em_aepParticles[ctCount-1]; + ep=emLast; + ctCount--; + } + // it is alive, animate it + else + { + // animate position + ep.ep_vLastPos=ep.ep_vPos; + ep.ep_vSpeed=ep.ep_vSpeed+em_vG*_pTimer->TickQuantum; + ep.ep_vPos=ep.ep_vPos+ep.ep_vSpeed*_pTimer->TickQuantum; + // animate rotation + ep.ep_fLastRot=ep.ep_fRot; + ep.ep_fRot+=ep.ep_fRotSpeed*_pTimer->TickQuantum; + // animate color + FLOAT fRatio=CalculateRatio(tmNow, ep.ep_tmEmitted, ep.ep_tmEmitted+ep.ep_tmLife, 1, 0); + ep.ep_colLastColor=ep.ep_colColor; + iCurrent++; + } + } + if( em_aepParticles.Count()==0) + { + em_aepParticles.PopAll(); + } + else if( em_aepParticles.Count()!=ctCount) + { + em_aepParticles.PopUntil(ctCount-1); + } +} + +void CEmiter::RenderParticles(void) +{ + switch(em_etType) + { + case ET_AIR_ELEMENTAL: + Particles_AirElementalBlow(*(CEmiter*)this); + break; + case ET_SUMMONER_STAFF: + Particles_SummonerStaff(*(CEmiter*)this); + break; + case ET_FIREWORKS01: + Particles_Fireworks01(*(CEmiter*)this); + break; + default: + { + } + } +} + +void CEmiter::Read_t( CTStream &strm) +{ + if (strm.PeekID_t()!=CChunkID(ID_EMITER_VER)) return; + strm.GetID_t(); + INDEX ctMaxParticles; + strm>>ctMaxParticles; + + em_bInitialized=TRUE; + INDEX ietType; + strm>>ietType; + em_etType=(CEmiterType) ietType; + strm>>em_tmStart; + strm>>em_tmLife; + strm>>em_vG; + strm>>em_colGlobal; + strm>>em_iGlobal; + + if(ctMaxParticles==0) return; + em_aepParticles.Push(ctMaxParticles); + + for(INDEX i=0; i em_aepParticles; + + /* Default constructor. */ + CEmiter(void); + void Initialize(CEntity *pen); + FLOAT3D GetGravity(CEntity *pen); + void RenderParticles(void); + void AnimateParticles(void); + void AddParticle(FLOAT3D vPos, FLOAT3D vSpeed, FLOAT fRot, FLOAT fRotSpeed, + FLOAT tmBirth, FLOAT tmLife, FLOAT fStretch, COLOR colColor); + void Read_t( CTStream &strm); + void Write_t( CTStream &strm); +}; + diff --git a/Sources/EntitiesMP/Common/Flags.h b/Sources/EntitiesMP/Common/Flags.h new file mode 100644 index 0000000..4a81bcf --- /dev/null +++ b/Sources/EntitiesMP/Common/Flags.h @@ -0,0 +1,159 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_FLAGS_H +#define SE_INCL_FLAGS_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// collision flags +#define ECBI_BRUSH (1UL<<0) +#define ECBI_MODEL (1UL<<1) +#define ECBI_PROJECTILE_MAGIC (1UL<<2) +#define ECBI_PROJECTILE_SOLID (1UL<<3) +#define ECBI_ITEM (1UL<<4) +#define ECBI_CORPSE (1UL<<5) +#define ECBI_MODEL_HOLDER (1UL<<6) +#define ECBI_CORPSE_SOLID (1UL<<7) +#define ECBI_PLAYER (1UL<<8) + +// standard flag combinations: + +/* + * COLLISION COMBINATIONS + */ +#define ECF_IMMATERIAL (0UL) + +// brush +#define ECF_BRUSH ( \ + ((ECBI_MODEL|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID|ECBI_ITEM|ECBI_CORPSE|ECBI_CORPSE_SOLID)< + +#include +#include +#include +#include +#include + +#define ENTITY_DEBUG + +// armor & health constants +// NOTE: these _do not_ reflect easy/tourist maxvalue adjustments. that is by design! +#define TOP_ARMOR 100 +#define TOP_HEALTH 100 + + +// cheats +extern INDEX cht_bEnable; +extern INDEX cht_bGod; +extern INDEX cht_bFly; +extern INDEX cht_bGhost; +extern INDEX cht_bInvisible; +extern FLOAT cht_fTranslationMultiplier; + +// interface control +extern INDEX hud_bShowInfo; +extern INDEX hud_bShowLatency; +extern INDEX hud_bShowMessages; +extern INDEX hud_iShowPlayers; +extern INDEX hud_iSortPlayers; +extern FLOAT hud_fOpacity; +extern FLOAT hud_fScaling; +extern FLOAT hud_tmWeaponsOnScreen; +extern INDEX hud_bShowMatchInfo; + +// player statistics sorting keys +enum SortKeys { + PSK_NAME = 1, + PSK_HEALTH = 2, + PSK_SCORE = 3, + PSK_MANA = 4, + PSK_FRAGS = 5, + PSK_DEATHS = 6, +}; + +// where is the bar lowest value +enum BarOrientations { + BO_LEFT = 1, + BO_RIGHT = 2, + BO_UP = 3, + BO_DOWN = 4, +}; + +extern const INDEX aiWeaponsRemap[19]; + +// maximal mana for master status +#define MANA_MASTER 10000 + +// drawing variables +static const CPlayer *_penPlayer; +static CPlayerWeapons *_penWeapons; +static CDrawPort *_pDP; +static PIX _pixDPWidth, _pixDPHeight; +static FLOAT _fResolutionScaling; +static FLOAT _fCustomScaling; +static ULONG _ulAlphaHUD; +static COLOR _colHUD; +static COLOR _colHUDText; +static TIME _tmNow = -1.0f; +static TIME _tmLast = -1.0f; +static CFontData _fdNumbersFont; + +// array for pointers of all players +extern CPlayer *_apenPlayers[NET_MAXGAMEPLAYERS] = {0}; + +// status bar textures +static CTextureObject _toHealth; +static CTextureObject _toOxygen; +static CTextureObject _toScore; +static CTextureObject _toHiScore; +static CTextureObject _toMessage; +static CTextureObject _toMana; +static CTextureObject _toFrags; +static CTextureObject _toDeaths; +static CTextureObject _toArmorSmall; +static CTextureObject _toArmorMedium; +static CTextureObject _toArmorLarge; + +// ammo textures +static CTextureObject _toAShells; +static CTextureObject _toABullets; +static CTextureObject _toARockets; +static CTextureObject _toAGrenades; +static CTextureObject _toANapalm; +static CTextureObject _toAElectricity; +static CTextureObject _toAIronBall; +static CTextureObject _toASniperBullets; +static CTextureObject _toASeriousBomb; +// weapon textures +static CTextureObject _toWKnife; +static CTextureObject _toWColt; +static CTextureObject _toWSingleShotgun; +static CTextureObject _toWDoubleShotgun; +static CTextureObject _toWTommygun; +static CTextureObject _toWSniper; +static CTextureObject _toWChainsaw; +static CTextureObject _toWMinigun; +static CTextureObject _toWRocketLauncher; +static CTextureObject _toWGrenadeLauncher; +static CTextureObject _toWFlamer; +static CTextureObject _toWLaser; +static CTextureObject _toWIronCannon; + +// powerup textures (ORDER IS THE SAME AS IN PLAYER.ES!) +#define MAX_POWERUPS 4 +static CTextureObject _atoPowerups[MAX_POWERUPS]; +// tile texture (one has corners, edges and center) +static CTextureObject _toTile; +// sniper mask texture +static CTextureObject _toSniperMask; +static CTextureObject _toSniperWheel; +static CTextureObject _toSniperArrow; +static CTextureObject _toSniperEye; +static CTextureObject _toSniperLed; + +// all info about color transitions +struct ColorTransitionTable { + COLOR ctt_colFine; // color for values over 1.0 + COLOR ctt_colHigh; // color for values from 1.0 to 'fMedium' + COLOR ctt_colMedium; // color for values from 'fMedium' to 'fLow' + COLOR ctt_colLow; // color for values under fLow + FLOAT ctt_fMediumHigh; // when to switch to high color (normalized float!) + FLOAT ctt_fLowMedium; // when to switch to medium color (normalized float!) + BOOL ctt_bSmooth; // should colors have smooth transition +}; +static struct ColorTransitionTable _cttHUD; + + +// ammo's info structure +struct AmmoInfo { + CTextureObject *ai_ptoAmmo; + struct WeaponInfo *ai_pwiWeapon1; + struct WeaponInfo *ai_pwiWeapon2; + INDEX ai_iAmmoAmmount; + INDEX ai_iMaxAmmoAmmount; + INDEX ai_iLastAmmoAmmount; + TIME ai_tmAmmoChanged; + BOOL ai_bHasWeapon; +}; + +// weapons' info structure +struct WeaponInfo { + enum WeaponType wi_wtWeapon; + CTextureObject *wi_ptoWeapon; + struct AmmoInfo *wi_paiAmmo; + BOOL wi_bHasWeapon; +}; + +extern struct WeaponInfo _awiWeapons[18]; +static struct AmmoInfo _aaiAmmo[8] = { + { &_toAShells, &_awiWeapons[4], &_awiWeapons[5], 0, 0, 0, -9, FALSE }, // 0 + { &_toABullets, &_awiWeapons[6], &_awiWeapons[7], 0, 0, 0, -9, FALSE }, // 1 + { &_toARockets, &_awiWeapons[8], NULL, 0, 0, 0, -9, FALSE }, // 2 + { &_toAGrenades, &_awiWeapons[9], NULL, 0, 0, 0, -9, FALSE }, // 3 + { &_toANapalm, &_awiWeapons[11], NULL, 0, 0, 0, -9, FALSE }, // 4 + { &_toAElectricity, &_awiWeapons[12], NULL, 0, 0, 0, -9, FALSE }, // 5 + { &_toAIronBall, &_awiWeapons[14], NULL, 0, 0, 0, -9, FALSE }, // 6 + { &_toASniperBullets, &_awiWeapons[13], NULL, 0, 0, 0, -9, FALSE }, // 7 +}; +static const INDEX aiAmmoRemap[8] = { 0, 1, 2, 3, 4, 7, 5, 6 }; + +struct WeaponInfo _awiWeapons[18] = { + { WEAPON_NONE, NULL, NULL, FALSE }, // 0 + { WEAPON_KNIFE, &_toWKnife, NULL, FALSE }, // 1 + { WEAPON_COLT, &_toWColt, NULL, FALSE }, // 2 + { WEAPON_DOUBLECOLT, &_toWColt, NULL, FALSE }, // 3 + { WEAPON_SINGLESHOTGUN, &_toWSingleShotgun, &_aaiAmmo[0], FALSE }, // 4 + { WEAPON_DOUBLESHOTGUN, &_toWDoubleShotgun, &_aaiAmmo[0], FALSE }, // 5 + { WEAPON_TOMMYGUN, &_toWTommygun, &_aaiAmmo[1], FALSE }, // 6 + { WEAPON_MINIGUN, &_toWMinigun, &_aaiAmmo[1], FALSE }, // 7 + { WEAPON_ROCKETLAUNCHER, &_toWRocketLauncher, &_aaiAmmo[2], FALSE }, // 8 + { WEAPON_GRENADELAUNCHER, &_toWGrenadeLauncher, &_aaiAmmo[3], FALSE }, // 9 + { WEAPON_CHAINSAW, &_toWChainsaw, NULL, FALSE }, // 10 + { WEAPON_FLAMER, &_toWFlamer, &_aaiAmmo[4], FALSE }, // 11 + { WEAPON_LASER, &_toWLaser, &_aaiAmmo[5], FALSE }, // 12 + { WEAPON_SNIPER, &_toWSniper, &_aaiAmmo[7], FALSE }, // 13 + { WEAPON_IRONCANNON, &_toWIronCannon, &_aaiAmmo[6], FALSE }, // 14 +//{ WEAPON_PIPEBOMB, &_toWPipeBomb, &_aaiAmmo[3], FALSE }, // 15 +//{ WEAPON_GHOSTBUSTER, &_toWGhostBuster, &_aaiAmmo[5], FALSE }, // 16 +//{ WEAPON_NUKECANNON, &_toWNukeCannon, &_aaiAmmo[7], FALSE }, // 17 + { WEAPON_NONE, NULL, NULL, FALSE }, // 15 + { WEAPON_NONE, NULL, NULL, FALSE }, // 16 + { WEAPON_NONE, NULL, NULL, FALSE }, // 17 +}; + + +// compare functions for qsort() +static int qsort_CompareNames( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + CTString strName0 = en0.GetPlayerName(); + CTString strName1 = en1.GetPlayerName(); + return strnicmp( strName0, strName1, 8); +} + +static int qsort_CompareScores( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = en0.m_psGameStats.ps_iScore; + SLONG sl1 = en1.m_psGameStats.ps_iScore; + if( sl0sl1) return -1; + else return 0; +} + +static int qsort_CompareHealth( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = (SLONG)ceil(en0.GetHealth()); + SLONG sl1 = (SLONG)ceil(en1.GetHealth()); + if( sl0sl1) return -1; + else return 0; +} + +static int qsort_CompareManas( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = en0.m_iMana; + SLONG sl1 = en1.m_iMana; + if( sl0sl1) return -1; + else return 0; +} + +static int qsort_CompareDeaths( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = en0.m_psGameStats.ps_iDeaths; + SLONG sl1 = en1.m_psGameStats.ps_iDeaths; + if( sl0sl1) return -1; + else return 0; +} + +static int qsort_CompareFrags( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = en0.m_psGameStats.ps_iKills; + SLONG sl1 = en1.m_psGameStats.ps_iKills; + if( sl0sl1) return -1; + else return -qsort_CompareDeaths(ppPEN0, ppPEN1); +} + +static int qsort_CompareLatencies( const void *ppPEN0, const void *ppPEN1) { + CPlayer &en0 = **(CPlayer**)ppPEN0; + CPlayer &en1 = **(CPlayer**)ppPEN1; + SLONG sl0 = (SLONG)ceil(en0.m_tmLatency); + SLONG sl1 = (SLONG)ceil(en1.m_tmLatency); + if( sl0sl1) return -1; + else return 0; +} + +// prepare color transitions +static void PrepareColorTransitions( COLOR colFine, COLOR colHigh, COLOR colMedium, COLOR colLow, + FLOAT fMediumHigh, FLOAT fLowMedium, BOOL bSmooth) +{ + _cttHUD.ctt_colFine = colFine; + _cttHUD.ctt_colHigh = colHigh; + _cttHUD.ctt_colMedium = colMedium; + _cttHUD.ctt_colLow = colLow; + _cttHUD.ctt_fMediumHigh = fMediumHigh; + _cttHUD.ctt_fLowMedium = fLowMedium; + _cttHUD.ctt_bSmooth = bSmooth; +} + + + +// calculates shake ammount and color value depanding on value change +#define SHAKE_TIME (2.0f) +static COLOR AddShaker( PIX const pixAmmount, INDEX const iCurrentValue, INDEX &iLastValue, + TIME &tmChanged, FLOAT &fMoverX, FLOAT &fMoverY) +{ + // update shaking if needed + fMoverX = fMoverY = 0.0f; + const TIME tmNow = _pTimer->GetLerpedCurrentTick(); + if( iCurrentValue != iLastValue) { + iLastValue = iCurrentValue; + tmChanged = tmNow; + } else { + // in case of loading (timer got reseted) + tmChanged = ClampUp( tmChanged, tmNow); + } + + // no shaker? + const TIME tmDelta = tmNow - tmChanged; + if( tmDelta > SHAKE_TIME) return NONE; + ASSERT( tmDelta>=0); + // shake, baby shake! + const FLOAT fAmmount = _fResolutionScaling * _fCustomScaling * pixAmmount; + const FLOAT fMultiplier = (SHAKE_TIME-tmDelta)/SHAKE_TIME *fAmmount; + const INDEX iRandomizer = (INDEX)(tmNow*511.0f)*fAmmount*iCurrentValue; + const FLOAT fNormRnd1 = (FLOAT)((iRandomizer ^ (iRandomizer>>9)) & 1023) * 0.0009775f; // 1/1023 - normalized + const FLOAT fNormRnd2 = (FLOAT)((iRandomizer ^ (iRandomizer>>7)) & 1023) * 0.0009775f; // 1/1023 - normalized + fMoverX = (fNormRnd1 -0.5f) * fMultiplier; + fMoverY = (fNormRnd2 -0.5f) * fMultiplier; + // clamp to adjusted ammount (pixels relative to resolution and HUD scale + fMoverX = Clamp( fMoverX, -fAmmount, fAmmount); + fMoverY = Clamp( fMoverY, -fAmmount, fAmmount); + if( tmDelta < SHAKE_TIME/3) return C_WHITE; + else return NONE; +//return FloatToInt(tmDelta*4) & 1 ? C_WHITE : NONE; +} + + +// get current color from local color transitions table +static COLOR GetCurrentColor( FLOAT fNormalizedValue) +{ + // if value is in 'low' zone just return plain 'low' alert color + if( fNormalizedValue < _cttHUD.ctt_fLowMedium) return( _cttHUD.ctt_colLow & 0xFFFFFF00); + // if value is in out of 'extreme' zone just return 'extreme' color + if( fNormalizedValue > 1.0f) return( _cttHUD.ctt_colFine & 0xFFFFFF00); + + COLOR col; + // should blend colors? + if( _cttHUD.ctt_bSmooth) + { // lets do some interpolations + FLOAT fd, f1, f2; + COLOR col1, col2; + UBYTE ubH,ubS,ubV, ubH2,ubS2,ubV2; + // determine two colors for interpolation + if( fNormalizedValue > _cttHUD.ctt_fMediumHigh) { + f1 = 1.0f; + f2 = _cttHUD.ctt_fMediumHigh; + col1 = _cttHUD.ctt_colHigh; + col2 = _cttHUD.ctt_colMedium; + } else { // fNormalizedValue > _cttHUD.ctt_fLowMedium == TRUE ! + f1 = _cttHUD.ctt_fMediumHigh; + f2 = _cttHUD.ctt_fLowMedium; + col1 = _cttHUD.ctt_colMedium; + col2 = _cttHUD.ctt_colLow; + } + // determine interpolation strength + fd = (fNormalizedValue-f2) / (f1-f2); + // convert colors to HSV + ColorToHSV( col1, ubH, ubS, ubV); + ColorToHSV( col2, ubH2, ubS2, ubV2); + // interpolate H, S and V components + ubH = (UBYTE)(ubH*fd + ubH2*(1.0f-fd)); + ubS = (UBYTE)(ubS*fd + ubS2*(1.0f-fd)); + ubV = (UBYTE)(ubV*fd + ubV2*(1.0f-fd)); + // convert HSV back to COLOR + col = HSVToColor( ubH, ubS, ubV); + } + else + { // simple color picker + col = _cttHUD.ctt_colMedium; + if( fNormalizedValue > _cttHUD.ctt_fMediumHigh) col = _cttHUD.ctt_colHigh; + } + // all done + return( col & 0xFFFFFF00); +} + + + +// fill array with players' statistics (returns current number of players in game) +extern INDEX SetAllPlayersStats( INDEX iSortKey) +{ + // determine maximum number of players for this session + INDEX iPlayers = 0; + INDEX iMaxPlayers = _penPlayer->GetMaxPlayers(); + CPlayer *penCurrent; + // loop thru potentional players + for( INDEX i=0; iGetPlayerEntity(i); + if( penCurrent==NULL) continue; + // fill in player parameters + _apenPlayers[iPlayers] = penCurrent; + // advance to next real player + iPlayers++; + } + // sort statistics by some key if needed + switch( iSortKey) { + case PSK_NAME: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareNames); break; + case PSK_SCORE: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareScores); break; + case PSK_HEALTH: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareHealth); break; + case PSK_MANA: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareManas); break; + case PSK_FRAGS: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareFrags); break; + case PSK_DEATHS: qsort( _apenPlayers, iPlayers, sizeof(CPlayer*), qsort_CompareDeaths); break; + default: break; // invalid or NONE key specified so do nothing + } + // all done + return iPlayers; +} + + + +// ----------------------- drawing functions + +// draw border with filter +static void HUD_DrawBorder( FLOAT fCenterX, FLOAT fCenterY, FLOAT fSizeX, FLOAT fSizeY, COLOR colTiles) +{ + // determine location + const FLOAT fCenterI = fCenterX*_pixDPWidth / 640.0f; + const FLOAT fCenterJ = fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment); + const FLOAT fSizeI = _fResolutionScaling*fSizeX; + const FLOAT fSizeJ = _fResolutionScaling*fSizeY; + const FLOAT fTileSize = 8*_fResolutionScaling*_fCustomScaling; + // determine exact positions + const FLOAT fLeft = fCenterI - fSizeI/2 -1; + const FLOAT fRight = fCenterI + fSizeI/2 +1; + const FLOAT fUp = fCenterJ - fSizeJ/2 -1; + const FLOAT fDown = fCenterJ + fSizeJ/2 +1; + const FLOAT fLeftEnd = fLeft + fTileSize; + const FLOAT fRightBeg = fRight - fTileSize; + const FLOAT fUpEnd = fUp + fTileSize; + const FLOAT fDownBeg = fDown - fTileSize; + // prepare texture + colTiles |= _ulAlphaHUD; + // put corners + _pDP->InitTexture( &_toTile, TRUE); // clamping on! + _pDP->AddTexture( fLeft, fUp, fLeftEnd, fUpEnd, colTiles); + _pDP->AddTexture( fRight,fUp, fRightBeg,fUpEnd, colTiles); + _pDP->AddTexture( fRight,fDown, fRightBeg,fDownBeg, colTiles); + _pDP->AddTexture( fLeft, fDown, fLeftEnd, fDownBeg, colTiles); + // put edges + _pDP->AddTexture( fLeftEnd,fUp, fRightBeg,fUpEnd, 0.4f,0.0f, 0.6f,1.0f, colTiles); + _pDP->AddTexture( fLeftEnd,fDown, fRightBeg,fDownBeg, 0.4f,0.0f, 0.6f,1.0f, colTiles); + _pDP->AddTexture( fLeft, fUpEnd, fLeftEnd, fDownBeg, 0.0f,0.4f, 1.0f,0.6f, colTiles); + _pDP->AddTexture( fRight, fUpEnd, fRightBeg,fDownBeg, 0.0f,0.4f, 1.0f,0.6f, colTiles); + // put center + _pDP->AddTexture( fLeftEnd, fUpEnd, fRightBeg, fDownBeg, 0.4f,0.4f, 0.6f,0.6f, colTiles); + _pDP->FlushRenderingQueue(); +} + + +// draw icon texture (if color = NONE, use colortransitions structure) +static void HUD_DrawIcon( FLOAT fCenterX, FLOAT fCenterY, CTextureObject &toIcon, + COLOR colDefault, FLOAT fNormValue, BOOL bBlink) +{ + // determine color + COLOR col = colDefault; + if( col==NONE) col = GetCurrentColor( fNormValue); + // determine blinking state + if( bBlink && fNormValue<=(_cttHUD.ctt_fLowMedium/2)) { + // activate blinking only if value is <= half the low edge + INDEX iCurrentTime = (INDEX)(_tmNow*4); + if( iCurrentTime&1) col = C_vdGRAY; + } + // determine location + const FLOAT fCenterI = fCenterX*_pixDPWidth / 640.0f; + const FLOAT fCenterJ = fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment); + // determine dimensions + CTextureData *ptd = (CTextureData*)toIcon.GetData(); + const FLOAT fHalfSizeI = _fResolutionScaling*_fCustomScaling * ptd->GetPixWidth() *0.5f; + const FLOAT fHalfSizeJ = _fResolutionScaling*_fCustomScaling * ptd->GetPixHeight() *0.5f; + // done + _pDP->InitTexture( &toIcon); + _pDP->AddTexture( fCenterI-fHalfSizeI, fCenterJ-fHalfSizeJ, + fCenterI+fHalfSizeI, fCenterJ+fHalfSizeJ, col|_ulAlphaHUD); + _pDP->FlushRenderingQueue(); +} + + +// draw text (or numbers, whatever) +static void HUD_DrawText( FLOAT fCenterX, FLOAT fCenterY, const CTString &strText, + COLOR colDefault, FLOAT fNormValue) +{ + // determine color + COLOR col = colDefault; + if( col==NONE) col = GetCurrentColor( fNormValue); + // determine location + PIX pixCenterI = (PIX)(fCenterX*_pixDPWidth / 640.0f); + PIX pixCenterJ = (PIX)(fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment)); + // done + _pDP->SetTextScaling( _fResolutionScaling*_fCustomScaling); + _pDP->PutTextCXY( strText, pixCenterI, pixCenterJ, col|_ulAlphaHUD); +} + + +// draw bar +static void HUD_DrawBar( FLOAT fCenterX, FLOAT fCenterY, PIX pixSizeX, PIX pixSizeY, + enum BarOrientations eBarOrientation, COLOR colDefault, FLOAT fNormValue) +{ + // determine color + COLOR col = colDefault; + if( col==NONE) col = GetCurrentColor( fNormValue); + // determine location and size + PIX pixCenterI = (PIX)(fCenterX*_pixDPWidth / 640.0f); + PIX pixCenterJ = (PIX)(fCenterY*_pixDPHeight / (480.0f * _pDP->dp_fWideAdjustment)); + PIX pixSizeI = (PIX)(_fResolutionScaling*pixSizeX); + PIX pixSizeJ = (PIX)(_fResolutionScaling*pixSizeY); + // fill bar background area + PIX pixLeft = pixCenterI-pixSizeI/2; + PIX pixUpper = pixCenterJ-pixSizeJ/2; + // determine bar position and inner size + switch( eBarOrientation) { + case BO_UP: + pixSizeJ *= fNormValue; + break; + case BO_DOWN: + pixUpper = pixUpper + (PIX)ceil(pixSizeJ * (1.0f-fNormValue)); + pixSizeJ *= fNormValue; + break; + case BO_LEFT: + pixSizeI *= fNormValue; + break; + case BO_RIGHT: + pixLeft = pixLeft + (PIX)ceil(pixSizeI * (1.0f-fNormValue)); + pixSizeI *= fNormValue; + break; + } + // done + _pDP->Fill( pixLeft, pixUpper, pixSizeI, pixSizeJ, col|_ulAlphaHUD); +} + +static void DrawRotatedQuad( class CTextureObject *_pTO, FLOAT fX, FLOAT fY, FLOAT fSize, ANGLE aAngle, COLOR col) +{ + FLOAT fSinA = Sin(aAngle); + FLOAT fCosA = Cos(aAngle); + FLOAT fSinPCos = fCosA*fSize+fSinA*fSize; + FLOAT fSinMCos = fSinA*fSize-fCosA*fSize; + FLOAT fI0, fJ0, fI1, fJ1, fI2, fJ2, fI3, fJ3; + + fI0 = fX-fSinPCos; fJ0 = fY-fSinMCos; + fI1 = fX+fSinMCos; fJ1 = fY-fSinPCos; + fI2 = fX+fSinPCos; fJ2 = fY+fSinMCos; + fI3 = fX-fSinMCos; fJ3 = fY+fSinPCos; + + _pDP->InitTexture( _pTO); + _pDP->AddTexture( fI0, fJ0, 0, 0, col, fI1, fJ1, 0, 1, col, + fI2, fJ2, 1, 1, col, fI3, fJ3, 1, 0, col); + _pDP->FlushRenderingQueue(); + +} + +static void DrawAspectCorrectTextureCentered( class CTextureObject *_pTO, FLOAT fX, FLOAT fY, FLOAT fWidth, COLOR col) +{ + CTextureData *ptd = (CTextureData*)_pTO->GetData(); + FLOAT fTexSizeI = ptd->GetPixWidth(); + FLOAT fTexSizeJ = ptd->GetPixHeight(); + FLOAT fHeight = fWidth*fTexSizeJ/fTexSizeJ; + + _pDP->InitTexture( _pTO); + _pDP->AddTexture( fX-fWidth*0.5f, fY-fHeight*0.5f, fX+fWidth*0.5f, fY+fHeight*0.5f, 0, 0, 1, 1, col); + _pDP->FlushRenderingQueue(); +} + +// draw sniper mask +static void HUD_DrawSniperMask( void ) +{ + // determine location + const FLOAT fSizeI = _pixDPWidth; + const FLOAT fSizeJ = _pixDPHeight; + const FLOAT fCenterI = fSizeI/2; + const FLOAT fCenterJ = fSizeJ/2; + const FLOAT fBlackStrip = (fSizeI-fSizeJ)/2; + + COLOR colMask = C_WHITE|CT_OPAQUE; + + CTextureData *ptd = (CTextureData*)_toSniperMask.GetData(); + const FLOAT fTexSizeI = ptd->GetPixWidth(); + const FLOAT fTexSizeJ = ptd->GetPixHeight(); + + // main sniper mask + _pDP->InitTexture( &_toSniperMask); + _pDP->AddTexture( fBlackStrip, 0, fCenterI, fCenterJ, 0.98f, 0.02f, 0, 1.0f, colMask); + _pDP->AddTexture( fCenterI, 0, fSizeI-fBlackStrip, fCenterJ, 0, 0.02f, 0.98f, 1.0f, colMask); + _pDP->AddTexture( fBlackStrip, fCenterJ, fCenterI, fSizeJ, 0.98f, 1.0f, 0, 0.02f, colMask); + _pDP->AddTexture( fCenterI, fCenterJ, fSizeI-fBlackStrip, fSizeJ, 0, 1, 0.98f, 0.02f, colMask); + _pDP->FlushRenderingQueue(); + _pDP->Fill( 0, 0, fBlackStrip+1, fSizeJ, C_BLACK|CT_OPAQUE); + _pDP->Fill( fSizeI-fBlackStrip-1, 0, fBlackStrip+1, fSizeJ, C_BLACK|CT_OPAQUE); + + colMask = LerpColor(SE_COL_BLUE_LIGHT, C_WHITE, 0.25f); + + FLOAT _fYResolutionScaling = (FLOAT)_pixDPHeight/480.0f; + + FLOAT fDistance = _penWeapons->m_fRayHitDistance; + FLOAT aFOV = Lerp(_penWeapons->m_fSniperFOVlast, _penWeapons->m_fSniperFOV, + _pTimer->GetLerpFactor()); + CTString strTmp; + + // wheel + FLOAT fZoom = 1.0f/tan(RadAngle(aFOV)*0.5f); // 2.0 - 8.0 + + FLOAT fAFact = (Clamp(aFOV, 14.2f, 53.1f)-14.2f)/(53.1f-14.2f); // only for zooms 2x-4x !!!!!! + ANGLE aAngle = 314.0f+fAFact*292.0f; + + DrawRotatedQuad(&_toSniperWheel, fCenterI, fCenterJ, 40.0f*_fYResolutionScaling, + aAngle, colMask|0x44); + + FLOAT fTM = _pTimer->GetLerpedCurrentTick(); + + COLOR colLED; + if (_penWeapons->m_tmLastSniperFire+1.25f=1.0f) + { + FLOAT _fIconSize; + FLOAT _fLeftX, _fLeftYU, _fLeftYD; + FLOAT _fRightX, _fRightYU, _fRightYD; + + if (_fResolutionScaling<=1.3f) { + _pDP->SetFont( _pfdConsoleFont); + _pDP->SetTextAspect( 1.0f); + _pDP->SetTextScaling(1.0f); + _fIconSize = 22.8f; + _fLeftX = 159.0f; + _fLeftYU = 8.0f; + _fLeftYD = 6.0f; + _fRightX = 159.0f; + _fRightYU = 11.0f; + _fRightYD = 6.0f; + } else { + _pDP->SetFont( _pfdDisplayFont); + _pDP->SetTextAspect( 1.0f); + _pDP->SetTextScaling(0.7f*_fYResolutionScaling); + _fIconSize = 19.0f; + _fLeftX = 162.0f; + _fLeftYU = 8.0f; + _fLeftYD = 6.0f; + _fRightX = 162.0f; + _fRightYU = 11.0f; + _fRightYD = 6.0f; + } + + // arrow + distance + DrawAspectCorrectTextureCentered(&_toSniperArrow, fCenterI-_fLeftX*_fYResolutionScaling, + fCenterJ-_fLeftYU*_fYResolutionScaling, _fIconSize*_fYResolutionScaling, 0xFFCC3399 ); + if (fDistance>9999.9f) { strTmp.PrintF("---.-"); } + else if (TRUE) { strTmp.PrintF("%.1f", fDistance); } + _pDP->PutTextC( strTmp, fCenterI-_fLeftX*_fYResolutionScaling, + fCenterJ+_fLeftYD*_fYResolutionScaling, colMask|0xaa); + + // eye + zoom level + DrawAspectCorrectTextureCentered(&_toSniperEye, fCenterI+_fRightX*_fYResolutionScaling, + fCenterJ-_fRightYU*_fYResolutionScaling, _fIconSize*_fYResolutionScaling, 0xFFCC3399 ); //SE_COL_ORANGE_L + strTmp.PrintF("%.1fx", fZoom); + _pDP->PutTextC( strTmp, fCenterI+_fRightX*_fYResolutionScaling, + fCenterJ+_fRightYD*_fYResolutionScaling, colMask|0xaa); + } +} + + +// helper functions + +// fill weapon and ammo table with current state +static void FillWeaponAmmoTables(void) +{ + // ammo quantities + _aaiAmmo[0].ai_iAmmoAmmount = _penWeapons->m_iShells; + _aaiAmmo[0].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxShells; + _aaiAmmo[1].ai_iAmmoAmmount = _penWeapons->m_iBullets; + _aaiAmmo[1].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxBullets; + _aaiAmmo[2].ai_iAmmoAmmount = _penWeapons->m_iRockets; + _aaiAmmo[2].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxRockets; + _aaiAmmo[3].ai_iAmmoAmmount = _penWeapons->m_iGrenades; + _aaiAmmo[3].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxGrenades; + _aaiAmmo[4].ai_iAmmoAmmount = _penWeapons->m_iNapalm; + _aaiAmmo[4].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxNapalm; + _aaiAmmo[5].ai_iAmmoAmmount = _penWeapons->m_iElectricity; + _aaiAmmo[5].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxElectricity; + _aaiAmmo[6].ai_iAmmoAmmount = _penWeapons->m_iIronBalls; + _aaiAmmo[6].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxIronBalls; + _aaiAmmo[7].ai_iAmmoAmmount = _penWeapons->m_iSniperBullets; + _aaiAmmo[7].ai_iMaxAmmoAmmount = _penWeapons->m_iMaxSniperBullets; + + // prepare ammo table for weapon possesion + INDEX i, iAvailableWeapons = _penWeapons->m_iAvailableWeapons; + for( i=0; i<8; i++) _aaiAmmo[i].ai_bHasWeapon = FALSE; + // weapon possesion + for( i=WEAPON_NONE+1; iai_bHasWeapon |= _awiWeapons[i].wi_bHasWeapon; + } + } +} + + +//<<<<<<< DEBUG FUNCTIONS >>>>>>> + +#ifdef ENTITY_DEBUG +CRationalEntity *DBG_prenStackOutputEntity = NULL; +#endif +void HUD_SetEntityForStackDisplay(CRationalEntity *pren) +{ +#ifdef ENTITY_DEBUG + DBG_prenStackOutputEntity = pren; +#endif + return; +} + +#ifdef ENTITY_DEBUG +static void HUD_DrawEntityStack() +{ + CTString strTemp; + PIX pixFontHeight; + ULONG pixTextBottom; + + if (tmp_ai[9]==12345) + { + if (DBG_prenStackOutputEntity!=NULL) + { + pixFontHeight = _pfdConsoleFont->fd_pixCharHeight; + pixTextBottom = _pixDPHeight*0.83; + _pDP->SetFont( _pfdConsoleFont); + _pDP->SetTextScaling( 1.0f); + + INDEX ctStates = DBG_prenStackOutputEntity->en_stslStateStack.Count(); + strTemp.PrintF("-- stack of '%s'(%s)@%gs\n", DBG_prenStackOutputEntity->GetName(), + DBG_prenStackOutputEntity->en_pecClass->ec_pdecDLLClass->dec_strName, + _pTimer->CurrentTick()); + _pDP->PutText( strTemp, 1, pixTextBottom-pixFontHeight*(ctStates+1), _colHUD|_ulAlphaHUD); + + for(INDEX iState=ctStates-1; iState>=0; iState--) { + SLONG slState = DBG_prenStackOutputEntity->en_stslStateStack[iState]; + strTemp.PrintF("0x%08x %s\n", slState, + DBG_prenStackOutputEntity->en_pecClass->ec_pdecDLLClass->HandlerNameForState(slState)); + _pDP->PutText( strTemp, 1, pixTextBottom-pixFontHeight*(iState+1), _colHUD|_ulAlphaHUD); + } + } + } +} +#endif +//<<<<<<< DEBUG FUNCTIONS >>>>>>> + +// main + +// render interface (frontend) to drawport +// (units are in pixels for 640x480 resolution - for other res HUD will be scalled automatically) +extern void DrawHUD( const CPlayer *penPlayerCurrent, CDrawPort *pdpCurrent, BOOL bSnooping, const CPlayer *penPlayerOwner) +{ + // no player - no info, sorry + if( penPlayerCurrent==NULL || (penPlayerCurrent->GetFlags()&ENF_DELETED)) return; + + // if snooping and owner player ins NULL, return + if ( bSnooping && penPlayerOwner==NULL) return; + + // find last values in case of predictor + CPlayer *penLast = (CPlayer*)penPlayerCurrent; + if( penPlayerCurrent->IsPredictor()) penLast = (CPlayer*)(((CPlayer*)penPlayerCurrent)->GetPredicted()); + ASSERT( penLast!=NULL); + if( penLast==NULL) return; // !!!! just in case + + // cache local variables + hud_fOpacity = Clamp( hud_fOpacity, 0.1f, 1.0f); + hud_fScaling = Clamp( hud_fScaling, 0.5f, 1.2f); + _penPlayer = penPlayerCurrent; + _penWeapons = (CPlayerWeapons*)&*_penPlayer->m_penWeapons; + _pDP = pdpCurrent; + _pixDPWidth = _pDP->GetWidth(); + _pixDPHeight = _pDP->GetHeight(); + _fCustomScaling = hud_fScaling; + _fResolutionScaling = (FLOAT)_pixDPWidth /640.0f; + _colHUD = 0x4C80BB00; + _colHUDText = SE_COL_ORANGE_LIGHT; + _ulAlphaHUD = NormFloatToByte(hud_fOpacity); + _tmNow = _pTimer->CurrentTick(); + + // determine hud colorization; + COLOR colMax = SE_COL_BLUEGREEN_LT; + COLOR colTop = SE_COL_ORANGE_LIGHT; + COLOR colMid = LerpColor(colTop, C_RED, 0.5f); + + // adjust borders color in case of spying mode + COLOR colBorder = _colHUD; + + if( bSnooping) { + colBorder = SE_COL_ORANGE_NEUTRAL; + if( ((ULONG)(_tmNow*5))&1) { + //colBorder = (colBorder>>1) & 0x7F7F7F00; // darken flash and scale + colBorder = SE_COL_ORANGE_DARK; + _fCustomScaling *= 0.933f; + } + } + + // draw sniper mask (original mask even if snooping) + if (((CPlayerWeapons*)&*penPlayerOwner->m_penWeapons)->m_iCurrentWeapon==WEAPON_SNIPER + &&((CPlayerWeapons*)&*penPlayerOwner->m_penWeapons)->m_bSniping) { + HUD_DrawSniperMask(); + } + + // prepare font and text dimensions + CTString strValue; + PIX pixCharWidth; + FLOAT fValue, fNormValue, fCol, fRow; + _pDP->SetFont( &_fdNumbersFont); + pixCharWidth = _fdNumbersFont.GetWidth() + _fdNumbersFont.GetCharSpacing() +1; + FLOAT fChrUnit = pixCharWidth * _fCustomScaling; + + const PIX pixTopBound = 6; + const PIX pixLeftBound = 6; + const PIX pixBottomBound = (480 * _pDP->dp_fWideAdjustment) -pixTopBound; + const PIX pixRightBound = 640-pixLeftBound; + FLOAT fOneUnit = (32+0) * _fCustomScaling; // unit size + FLOAT fAdvUnit = (32+4) * _fCustomScaling; // unit advancer + FLOAT fNextUnit = (32+8) * _fCustomScaling; // unit advancer + FLOAT fHalfUnit = fOneUnit * 0.5f; + FLOAT fMoverX, fMoverY; + COLOR colDefault; + + // prepare and draw health info + fValue = ClampDn( _penPlayer->GetHealth(), 0.0f); // never show negative health + fNormValue = fValue/TOP_HEALTH; + strValue.PrintF( "%d", (SLONG)ceil(fValue)); + PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); + fRow = pixBottomBound-fHalfUnit; + fCol = pixLeftBound+fHalfUnit; + colDefault = AddShaker( 5, fValue, penLast->m_iLastHealth, penLast->m_tmHealthChanged, fMoverX, fMoverY); + HUD_DrawBorder( fCol+fMoverX, fRow+fMoverY, fOneUnit, fOneUnit, colBorder); + fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fChrUnit*3, fOneUnit, colBorder); + HUD_DrawText( fCol, fRow, strValue, colDefault, fNormValue); + fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawIcon( fCol+fMoverX, fRow+fMoverY, _toHealth, C_WHITE /*_colHUD*/, fNormValue, TRUE); + + // prepare and draw armor info (eventually) + fValue = _penPlayer->m_fArmor; + if( fValue > 0.0f) { + fNormValue = fValue/TOP_ARMOR; + strValue.PrintF( "%d", (SLONG)ceil(fValue)); + PrepareColorTransitions( colMax, colTop, colMid, C_lGRAY, 0.5f, 0.25f, FALSE); + fRow = pixBottomBound- (fNextUnit+fHalfUnit);//*_pDP->dp_fWideAdjustment; + fCol = pixLeftBound+ fHalfUnit; + colDefault = AddShaker( 3, fValue, penLast->m_iLastArmor, penLast->m_tmArmorChanged, fMoverX, fMoverY); + HUD_DrawBorder( fCol+fMoverX, fRow+fMoverY, fOneUnit, fOneUnit, colBorder); + fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fChrUnit*3, fOneUnit, colBorder); + HUD_DrawText( fCol, fRow, strValue, NONE, fNormValue); + fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; + if (fValue<=50.5f) { + HUD_DrawIcon( fCol+fMoverX, fRow+fMoverY, _toArmorSmall, C_WHITE /*_colHUD*/, fNormValue, FALSE); + } else if (fValue<=100.5f) { + HUD_DrawIcon( fCol+fMoverX, fRow+fMoverY, _toArmorMedium, C_WHITE /*_colHUD*/, fNormValue, FALSE); + } else { + HUD_DrawIcon( fCol+fMoverX, fRow+fMoverY, _toArmorLarge, C_WHITE /*_colHUD*/, fNormValue, FALSE); + } + } + + // prepare and draw ammo and weapon info + CTextureObject *ptoCurrentAmmo=NULL, *ptoCurrentWeapon=NULL, *ptoWantedWeapon=NULL; + INDEX iCurrentWeapon = _penWeapons->m_iCurrentWeapon; + INDEX iWantedWeapon = _penWeapons->m_iWantedWeapon; + // determine corresponding ammo and weapon texture component + ptoCurrentWeapon = _awiWeapons[iCurrentWeapon].wi_ptoWeapon; + ptoWantedWeapon = _awiWeapons[iWantedWeapon].wi_ptoWeapon; + + AmmoInfo *paiCurrent = _awiWeapons[iCurrentWeapon].wi_paiAmmo; + if( paiCurrent!=NULL) ptoCurrentAmmo = paiCurrent->ai_ptoAmmo; + + // draw complete weapon info if knife isn't current weapon + if( ptoCurrentAmmo!=NULL && !GetSP()->sp_bInfiniteAmmo) { + // determine ammo quantities + FLOAT fMaxValue = _penWeapons->GetMaxAmmo(); + fValue = _penWeapons->GetAmmo(); + fNormValue = fValue / fMaxValue; + strValue.PrintF( "%d", (SLONG)ceil(fValue)); + PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.30f, 0.15f, FALSE); + BOOL bDrawAmmoIcon = _fCustomScaling<=1.0f; + // draw ammo, value and weapon + fRow = pixBottomBound-fHalfUnit; + fCol = 175 + fHalfUnit; + colDefault = AddShaker( 4, fValue, penLast->m_iLastAmmo, penLast->m_tmAmmoChanged, fMoverX, fMoverY); + HUD_DrawBorder( fCol+fMoverX, fRow+fMoverY, fOneUnit, fOneUnit, colBorder); + fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fChrUnit*3, fOneUnit, colBorder); + if( bDrawAmmoIcon) { + fCol += fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawIcon( fCol, fRow, *ptoCurrentAmmo, C_WHITE /*_colHUD*/, fNormValue, TRUE); + fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; + } + HUD_DrawText( fCol, fRow, strValue, NONE, fNormValue); + fCol -= fAdvUnit+fChrUnit*3/2 -fHalfUnit; + HUD_DrawIcon( fCol+fMoverX, fRow+fMoverY, *ptoCurrentWeapon, C_WHITE /*_colHUD*/, fNormValue, !bDrawAmmoIcon); + } else if( ptoCurrentWeapon!=NULL) { + // draw only knife or colt icons (ammo is irrelevant) + fRow = pixBottomBound-fHalfUnit; + fCol = 205 + fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawIcon( fCol, fRow, *ptoCurrentWeapon, C_WHITE /*_colHUD*/, fNormValue, FALSE); + } + + + // display all ammo infos + INDEX i; + FLOAT fAdv; + COLOR colIcon, colBar; + PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); + // reduce the size of icon slightly + _fCustomScaling = ClampDn( _fCustomScaling*0.8f, 0.5f); + const FLOAT fOneUnitS = fOneUnit *0.8f; + const FLOAT fAdvUnitS = fAdvUnit *0.8f; + const FLOAT fNextUnitS = fNextUnit *0.8f; + const FLOAT fHalfUnitS = fHalfUnit *0.8f; + + // prepare postition and ammo quantities + fRow = pixBottomBound-fHalfUnitS; + fCol = pixRightBound -fHalfUnitS; + const FLOAT fBarPos = fHalfUnitS*0.7f; + FillWeaponAmmoTables(); + + FLOAT fBombCount = penPlayerCurrent->m_iSeriousBombCount; + BOOL bBombFiring = FALSE; + // draw serious bomb +#define BOMB_FIRE_TIME 1.5f + if (penPlayerCurrent->m_tmSeriousBombFired+BOMB_FIRE_TIME>_pTimer->GetLerpedCurrentTick()) { + fBombCount++; + if (fBombCount>3) { fBombCount = 3; } + bBombFiring = TRUE; + } + if (fBombCount>0) { + fNormValue = (FLOAT) fBombCount / 3.0f; + COLOR colBombBorder = _colHUD; + COLOR colBombIcon = C_WHITE; + COLOR colBombBar = _colHUDText; if (fBombCount==1) { colBombBar = C_RED; } + if (bBombFiring) { + FLOAT fFactor = (_pTimer->GetLerpedCurrentTick() - penPlayerCurrent->m_tmSeriousBombFired)/BOMB_FIRE_TIME; + colBombBorder = LerpColor(colBombBorder, C_RED, fFactor); + colBombIcon = LerpColor(colBombIcon, C_RED, fFactor); + colBombBar = LerpColor(colBombBar, C_RED, fFactor); + } + HUD_DrawBorder( fCol, fRow, fOneUnitS, fOneUnitS, colBombBorder); + HUD_DrawIcon( fCol, fRow, _toASeriousBomb, colBombIcon, fNormValue, FALSE); + HUD_DrawBar( fCol+fBarPos, fRow, fOneUnitS/5, fOneUnitS-2, BO_DOWN, colBombBar, fNormValue); + // make space for serious bomb + fCol -= fAdvUnitS; + } + + // loop thru all ammo types + if (!GetSP()->sp_bInfiniteAmmo) { + for( INDEX ii=7; ii>=0; ii--) { + i = aiAmmoRemap[ii]; + // if no ammo and hasn't got that weapon - just skip this ammo + AmmoInfo &ai = _aaiAmmo[i]; + ASSERT( ai.ai_iAmmoAmmount>=0); + if( ai.ai_iAmmoAmmount==0 && !ai.ai_bHasWeapon) continue; + // display ammo info + colIcon = C_WHITE /*_colHUD*/; + if( ai.ai_iAmmoAmmount==0) colIcon = C_mdGRAY; + if( ptoCurrentAmmo == ai.ai_ptoAmmo) colIcon = C_WHITE; + fNormValue = (FLOAT)ai.ai_iAmmoAmmount / ai.ai_iMaxAmmoAmmount; + colBar = AddShaker( 4, ai.ai_iAmmoAmmount, ai.ai_iLastAmmoAmmount, ai.ai_tmAmmoChanged, fMoverX, fMoverY); + HUD_DrawBorder( fCol, fRow+fMoverY, fOneUnitS, fOneUnitS, colBorder); + HUD_DrawIcon( fCol, fRow+fMoverY, *_aaiAmmo[i].ai_ptoAmmo, colIcon, fNormValue, FALSE); + HUD_DrawBar( fCol+fBarPos, fRow+fMoverY, fOneUnitS/5, fOneUnitS-2, BO_DOWN, colBar, fNormValue); + // advance to next position + fCol -= fAdvUnitS; + } + } + + // draw powerup(s) if needed + PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.66f, 0.33f, FALSE); + TIME *ptmPowerups = (TIME*)&_penPlayer->m_tmInvisibility; + TIME *ptmPowerupsMax = (TIME*)&_penPlayer->m_tmInvisibilityMax; + fRow = pixBottomBound-fOneUnitS-fAdvUnitS; + fCol = pixRightBound -fHalfUnitS; + for( i=0; iPlayPowerUpSound(); + } + } + // advance to next position + fCol -= fAdvUnitS; + } + + + // if weapon change is in progress + _fCustomScaling = hud_fScaling; + hud_tmWeaponsOnScreen = Clamp( hud_tmWeaponsOnScreen, 0.0f, 10.0f); + if( (_tmNow - _penWeapons->m_tmWeaponChangeRequired) < hud_tmWeaponsOnScreen) { + // determine number of weapons that player has + INDEX ctWeapons = 0; + for( i=WEAPON_NONE+1; iai_iAmmoAmmount==0) { + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, 0x22334400); + HUD_DrawIcon( fCol, fRow, *_awiWeapons[i].wi_ptoWeapon, 0x22334400, 1.0f, FALSE); + // yes ammo + } else { + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawIcon( fCol, fRow, *_awiWeapons[i].wi_ptoWeapon, colIcon, 1.0f, FALSE); + } + // advance to next position + fCol += fAdvUnit; + } + } + + + // reduce icon sizes a bit + const FLOAT fUpperSize = ClampDn(_fCustomScaling*0.5f, 0.5f)/_fCustomScaling; + _fCustomScaling*=fUpperSize; + ASSERT( _fCustomScaling>=0.5f); + fChrUnit *= fUpperSize; + fOneUnit *= fUpperSize; + fHalfUnit *= fUpperSize; + fAdvUnit *= fUpperSize; + fNextUnit *= fUpperSize; + + // draw oxygen info if needed + BOOL bOxygenOnScreen = FALSE; + fValue = _penPlayer->en_tmMaxHoldBreath - (_pTimer->CurrentTick() - _penPlayer->en_tmLastBreathed); + if( _penPlayer->IsConnected() && (_penPlayer->GetFlags()&ENF_ALIVE) && fValue<30.0f) { + // prepare and draw oxygen info + fRow = pixTopBound + fOneUnit + fNextUnit; + fCol = 280.0f; + fAdv = fAdvUnit + fOneUnit*4/2 - fHalfUnit; + PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); + fNormValue = fValue/30.0f; + fNormValue = ClampDn(fNormValue, 0.0f); + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawBorder( fCol+fAdv, fRow, fOneUnit*4, fOneUnit, colBorder); + HUD_DrawBar( fCol+fAdv, fRow, fOneUnit*4*0.975, fOneUnit*0.9375, BO_LEFT, NONE, fNormValue); + HUD_DrawIcon( fCol, fRow, _toOxygen, C_WHITE /*_colHUD*/, fNormValue, TRUE); + bOxygenOnScreen = TRUE; + } + + // draw boss energy if needed + if( _penPlayer->m_penMainMusicHolder!=NULL) { + CMusicHolder &mh = (CMusicHolder&)*_penPlayer->m_penMainMusicHolder; + fNormValue = 0; + + if( mh.m_penBoss!=NULL && (mh.m_penBoss->en_ulFlags&ENF_ALIVE)) { + CEnemyBase &eb = (CEnemyBase&)*mh.m_penBoss; + ASSERT( eb.m_fMaxHealth>0); + fValue = eb.GetHealth(); + fNormValue = fValue/eb.m_fMaxHealth; + } + if( mh.m_penCounter!=NULL) { + CEnemyCounter &ec = (CEnemyCounter&)*mh.m_penCounter; + if (ec.m_iCount>0) { + fValue = ec.m_iCount; + fNormValue = fValue/ec.m_iCountFrom; + } + } + if( fNormValue>0) { + // prepare and draw boss energy info + //PrepareColorTransitions( colMax, colTop, colMid, C_RED, 0.5f, 0.25f, FALSE); + PrepareColorTransitions( colMax, colMax, colTop, C_RED, 0.5f, 0.25f, FALSE); + + fRow = pixTopBound + fOneUnit + fNextUnit; + fCol = 184.0f; + fAdv = fAdvUnit+ fOneUnit*16/2 -fHalfUnit; + if( bOxygenOnScreen) fRow += fNextUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawBorder( fCol+fAdv, fRow, fOneUnit*16, fOneUnit, colBorder); + HUD_DrawBar( fCol+fAdv, fRow, fOneUnit*16*0.995, fOneUnit*0.9375, BO_LEFT, NONE, fNormValue); + HUD_DrawIcon( fCol, fRow, _toHealth, C_WHITE /*_colHUD*/, fNormValue, FALSE); + } + } + + + // determine scaling of normal text and play mode + const FLOAT fTextScale = (_fResolutionScaling+1) *0.5f; + const BOOL bSinglePlay = GetSP()->sp_bSinglePlayer; + const BOOL bCooperative = GetSP()->sp_bCooperative && !bSinglePlay; + const BOOL bScoreMatch = !GetSP()->sp_bCooperative && !GetSP()->sp_bUseFrags; + const BOOL bFragMatch = !GetSP()->sp_bCooperative && GetSP()->sp_bUseFrags; + COLOR colMana, colFrags, colDeaths, colHealth, colArmor; + COLOR colScore = _colHUD; + INDEX iScoreSum = 0; + + // if not in single player mode, we'll have to calc (and maybe printout) other players' info + if( !bSinglePlay) + { + // set font and prepare font parameters + _pfdDisplayFont->SetVariableWidth(); + _pDP->SetFont( _pfdDisplayFont); + _pDP->SetTextScaling( fTextScale); + FLOAT fCharHeight = (_pfdDisplayFont->GetHeight()-2)*fTextScale; + // generate and sort by mana list of active players + BOOL bMaxScore=TRUE, bMaxMana=TRUE, bMaxFrags=TRUE, bMaxDeaths=TRUE; + hud_iSortPlayers = Clamp( hud_iSortPlayers, -1L, 6L); + SortKeys eKey = (SortKeys)hud_iSortPlayers; + if (hud_iSortPlayers==-1) { + if (bCooperative) eKey = PSK_HEALTH; + else if (bScoreMatch) eKey = PSK_SCORE; + else if (bFragMatch) eKey = PSK_FRAGS; + else { ASSERT(FALSE); eKey = PSK_NAME; } + } + if( bCooperative) eKey = (SortKeys)Clamp( (INDEX)eKey, 0L, 3L); + if( eKey==PSK_HEALTH && (bScoreMatch || bFragMatch)) { eKey = PSK_NAME; }; // prevent health snooping in deathmatch + INDEX iPlayers = SetAllPlayersStats(eKey); + // loop thru players + for( INDEX i=0; iGetPlayerName(); + const INDEX iScore = penPlayer->m_psGameStats.ps_iScore; + const INDEX iMana = penPlayer->m_iMana; + const INDEX iFrags = penPlayer->m_psGameStats.ps_iKills; + const INDEX iDeaths = penPlayer->m_psGameStats.ps_iDeaths; + const INDEX iHealth = ClampDn( (INDEX)ceil( penPlayer->GetHealth()), 0L); + const INDEX iArmor = ClampDn( (INDEX)ceil( penPlayer->m_fArmor), 0L); + CTString strScore, strMana, strFrags, strDeaths, strHealth, strArmor; + strScore.PrintF( "%d", iScore); + strMana.PrintF( "%d", iMana); + strFrags.PrintF( "%d", iFrags); + strDeaths.PrintF( "%d", iDeaths); + strHealth.PrintF( "%d", iHealth); + strArmor.PrintF( "%d", iArmor); + // detemine corresponding colors + colHealth = C_mlRED; + colMana = colScore = colFrags = colDeaths = colArmor = C_lGRAY; + if( iMana > _penPlayer->m_iMana) { bMaxMana = FALSE; colMana = C_WHITE; } + if( iScore > _penPlayer->m_psGameStats.ps_iScore) { bMaxScore = FALSE; colScore = C_WHITE; } + if( iFrags > _penPlayer->m_psGameStats.ps_iKills) { bMaxFrags = FALSE; colFrags = C_WHITE; } + if( iDeaths > _penPlayer->m_psGameStats.ps_iDeaths) { bMaxDeaths = FALSE; colDeaths = C_WHITE; } + if( penPlayer==_penPlayer) colScore = colMana = colFrags = colDeaths = _colHUD; // current player + if( iHealth>25) colHealth = _colHUD; + if( iArmor >25) colArmor = _colHUD; + // eventually print it out + if( hud_iShowPlayers==1 || hud_iShowPlayers==-1 && !bSinglePlay) { + // printout location and info aren't the same for deathmatch and coop play + const FLOAT fCharWidth = (PIX)((_pfdDisplayFont->GetWidth()-2) *fTextScale); + if( bCooperative) { + _pDP->PutTextR( strName+":", _pixDPWidth-8*fCharWidth, fCharHeight*i+fOneUnit*2, colScore |_ulAlphaHUD); + _pDP->PutText( "/", _pixDPWidth-4*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); + _pDP->PutTextC( strHealth, _pixDPWidth-6*fCharWidth, fCharHeight*i+fOneUnit*2, colHealth|_ulAlphaHUD); + _pDP->PutTextC( strArmor, _pixDPWidth-2*fCharWidth, fCharHeight*i+fOneUnit*2, colArmor |_ulAlphaHUD); + } else if( bScoreMatch) { + _pDP->PutTextR( strName+":", _pixDPWidth-12*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); + _pDP->PutText( "/", _pixDPWidth- 5*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); + _pDP->PutTextC( strScore, _pixDPWidth- 8*fCharWidth, fCharHeight*i+fOneUnit*2, colScore|_ulAlphaHUD); + _pDP->PutTextC( strMana, _pixDPWidth- 2*fCharWidth, fCharHeight*i+fOneUnit*2, colMana |_ulAlphaHUD); + } else { // fragmatch! + _pDP->PutTextR( strName+":", _pixDPWidth-8*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); + _pDP->PutText( "/", _pixDPWidth-4*fCharWidth, fCharHeight*i+fOneUnit*2, _colHUD |_ulAlphaHUD); + _pDP->PutTextC( strFrags, _pixDPWidth-6*fCharWidth, fCharHeight*i+fOneUnit*2, colFrags |_ulAlphaHUD); + _pDP->PutTextC( strDeaths, _pixDPWidth-2*fCharWidth, fCharHeight*i+fOneUnit*2, colDeaths|_ulAlphaHUD); + } + } + // calculate summ of scores (for coop mode) + iScoreSum += iScore; + } + // draw remaining time if time based death- or scorematch + if ((bScoreMatch || bFragMatch) && hud_bShowMatchInfo){ + CTString strLimitsInfo=""; + if (GetSP()->sp_iTimeLimit>0) { + FLOAT fTimeLeft = ClampDn(GetSP()->sp_iTimeLimit*60.0f - _pNetwork->GetGameTime(), 0.0f); + strLimitsInfo.PrintF("%s^cFFFFFF%s: %s\n", strLimitsInfo, TRANS("TIME LEFT"), TimeToString(fTimeLeft)); + } + extern INDEX SetAllPlayersStats( INDEX iSortKey); + // fill players table + const INDEX ctPlayers = SetAllPlayersStats(bFragMatch?5:3); // sort by frags or by score + // find maximum frags/score that one player has + INDEX iMaxFrags = LowerLimit(INDEX(0)); + INDEX iMaxScore = LowerLimit(INDEX(0)); + {for(INDEX iPlayer=0; iPlayerm_psLevelStats.ps_iKills); + iMaxScore = Max(iMaxScore, penPlayer->m_psLevelStats.ps_iScore); + }} + if (GetSP()->sp_iFragLimit>0) { + INDEX iFragsLeft = ClampDn(GetSP()->sp_iFragLimit-iMaxFrags, INDEX(0)); + strLimitsInfo.PrintF("%s^cFFFFFF%s: %d\n", strLimitsInfo, TRANS("FRAGS LEFT"), iFragsLeft); + } + if (GetSP()->sp_iScoreLimit>0) { + INDEX iScoreLeft = ClampDn(GetSP()->sp_iScoreLimit-iMaxScore, INDEX(0)); + strLimitsInfo.PrintF("%s^cFFFFFF%s: %d\n", strLimitsInfo, TRANS("SCORE LEFT"), iScoreLeft); + } + _pfdDisplayFont->SetFixedWidth(); + _pDP->SetFont( _pfdDisplayFont); + _pDP->SetTextScaling( fTextScale*0.8f ); + _pDP->SetTextCharSpacing( -2.0f*fTextScale); + _pDP->PutText( strLimitsInfo, 5.0f*_pixDPWidth/640.0f, 48.0f*_pixDPWidth/640.0f, C_WHITE|CT_OPAQUE); + } + + + // prepare color for local player printouts + bMaxScore ? colScore = C_WHITE : colScore = C_lGRAY; + bMaxMana ? colMana = C_WHITE : colMana = C_lGRAY; + bMaxFrags ? colFrags = C_WHITE : colFrags = C_lGRAY; + bMaxDeaths ? colDeaths = C_WHITE : colDeaths = C_lGRAY; + } + + // printout player latency if needed + if( hud_bShowLatency) { + CTString strLatency; + strLatency.PrintF( "%4.0fms", _penPlayer->m_tmLatency*1000.0f); + PIX pixFontHeight = (PIX)(_pfdDisplayFont->GetHeight() *fTextScale +fTextScale+1); + _pfdDisplayFont->SetFixedWidth(); + _pDP->SetFont( _pfdDisplayFont); + _pDP->SetTextScaling( fTextScale); + _pDP->SetTextCharSpacing( -2.0f*fTextScale); + _pDP->PutTextR( strLatency, _pixDPWidth, _pixDPHeight-pixFontHeight, C_WHITE|CT_OPAQUE); + } + // restore font defaults + _pfdDisplayFont->SetVariableWidth(); + _pDP->SetFont( &_fdNumbersFont); + _pDP->SetTextCharSpacing(1); + + // prepare output strings and formats depending on game type + FLOAT fWidthAdj = 8; + INDEX iScore = _penPlayer->m_psGameStats.ps_iScore; + INDEX iMana = _penPlayer->m_iMana; + if( bFragMatch) { + if (!hud_bShowMatchInfo) { fWidthAdj = 4; } + iScore = _penPlayer->m_psGameStats.ps_iKills; + iMana = _penPlayer->m_psGameStats.ps_iDeaths; + } else if( bCooperative) { + // in case of coop play, show squad (common) score + iScore = iScoreSum; + } + + // prepare and draw score or frags info + strValue.PrintF( "%d", iScore); + fRow = pixTopBound +fHalfUnit; + fCol = pixLeftBound +fHalfUnit; + fAdv = fAdvUnit+ fChrUnit*fWidthAdj/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*fWidthAdj, fOneUnit, colBorder); + HUD_DrawText( fCol+fAdv, fRow, strValue, colScore, 1.0f); + HUD_DrawIcon( fCol, fRow, _toFrags, C_WHITE /*colScore*/, 1.0f, FALSE); + + // eventually draw mana info + if( bScoreMatch || bFragMatch) { + strValue.PrintF( "%d", iMana); + fRow = pixTopBound + fNextUnit+fHalfUnit; + fCol = pixLeftBound + fHalfUnit; + fAdv = fAdvUnit+ fChrUnit*fWidthAdj/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*fWidthAdj, fOneUnit, colBorder); + HUD_DrawText( fCol+fAdv, fRow, strValue, colMana, 1.0f); + HUD_DrawIcon( fCol, fRow, _toDeaths, C_WHITE /*colMana*/, 1.0f, FALSE); + } + + // if single player or cooperative mode + if( bSinglePlay || bCooperative) + { + // prepare and draw hiscore info + strValue.PrintF( "%d", Max(_penPlayer->m_iHighScore, _penPlayer->m_psGameStats.ps_iScore)); + BOOL bBeating = _penPlayer->m_psGameStats.ps_iScore>_penPlayer->m_iHighScore; + fRow = pixTopBound+fHalfUnit; + fCol = 320.0f-fOneUnit-fChrUnit*8/2; + fAdv = fAdvUnit+ fChrUnit*8/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, colBorder); + HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*8, fOneUnit, colBorder); + HUD_DrawText( fCol+fAdv, fRow, strValue, NONE, bBeating ? 0.0f : 1.0f); + HUD_DrawIcon( fCol, fRow, _toHiScore, C_WHITE /*_colHUD*/, 1.0f, FALSE); + + // prepare and draw unread messages + if( hud_bShowMessages && _penPlayer->m_ctUnreadMessages>0) { + strValue.PrintF( "%d", _penPlayer->m_ctUnreadMessages); + fRow = pixTopBound+fHalfUnit; + fCol = pixRightBound-fHalfUnit-fAdvUnit-fChrUnit*4; + const FLOAT tmIn = 0.5f; + const FLOAT tmOut = 0.5f; + const FLOAT tmStay = 2.0f; + FLOAT tmDelta = _pTimer->GetLerpedCurrentTick()-_penPlayer->m_tmAnimateInbox; + COLOR col = _colHUD; + if (tmDelta>0 && tmDelta<(tmIn+tmStay+tmOut) && bSinglePlay) { + FLOAT fRatio = 0.0f; + if (tmDeltatmIn+tmStay) { + fRatio = (tmIn+tmStay+tmOut-tmDelta)/tmOut; + } else { + fRatio = 1.0f; + } + fRow+=fAdvUnit*5*fRatio; + fCol-=fAdvUnit*15*fRatio; + col = LerpColor(_colHUD, C_WHITE|0xFF, fRatio); + } + fAdv = fAdvUnit+ fChrUnit*4/2 -fHalfUnit; + HUD_DrawBorder( fCol, fRow, fOneUnit, fOneUnit, col); + HUD_DrawBorder( fCol+fAdv, fRow, fChrUnit*4, fOneUnit, col); + HUD_DrawText( fCol+fAdv, fRow, strValue, col, 1.0f); + HUD_DrawIcon( fCol, fRow, _toMessage, C_WHITE /*col*/, 0.0f, TRUE); + } + } + + #ifdef ENTITY_DEBUG + // if entity debug is on, draw entity stack + HUD_DrawEntityStack(); + #endif + + // draw cheat modes + if( GetSP()->sp_ctMaxPlayers==1) { + INDEX iLine=1; + ULONG ulAlpha = sin(_tmNow*16)*96 +128; + PIX pixFontHeight = _pfdConsoleFont->fd_pixCharHeight; + const COLOR colCheat = _colHUDText; + _pDP->SetFont( _pfdConsoleFont); + _pDP->SetTextScaling( 1.0f); + const FLOAT fchtTM = cht_fTranslationMultiplier; // for text formatting sake :) + if( fchtTM > 1.0f) { _pDP->PutTextR( "turbo", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } + if( cht_bInvisible) { _pDP->PutTextR( "invisible", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } + if( cht_bGhost) { _pDP->PutTextR( "ghost", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } + if( cht_bFly) { _pDP->PutTextR( "fly", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } + if( cht_bGod) { _pDP->PutTextR( "god", _pixDPWidth-1, _pixDPHeight-pixFontHeight*iLine, colCheat|ulAlpha); iLine++; } + } + + // in the end, remember the current time so it can be used in the next frame + _tmLast = _tmNow; + +} + + + +// initialize all that's needed for drawing the HUD +extern void InitHUD(void) +{ + // try to + try { + // initialize and load HUD numbers font + DECLARE_CTFILENAME( fnFont, "Fonts\\Numbers3.fnt"); + _fdNumbersFont.Load_t( fnFont); + //_fdNumbersFont.SetCharSpacing(0); + + // initialize status bar textures + _toHealth.SetData_t( CTFILENAME("TexturesMP\\Interface\\HSuper.tex")); + _toOxygen.SetData_t( CTFILENAME("TexturesMP\\Interface\\Oxygen-2.tex")); + _toFrags.SetData_t( CTFILENAME("TexturesMP\\Interface\\IBead.tex")); + _toDeaths.SetData_t( CTFILENAME("TexturesMP\\Interface\\ISkull.tex")); + _toScore.SetData_t( CTFILENAME("TexturesMP\\Interface\\IScore.tex")); + _toHiScore.SetData_t( CTFILENAME("TexturesMP\\Interface\\IHiScore.tex")); + _toMessage.SetData_t( CTFILENAME("TexturesMP\\Interface\\IMessage.tex")); + _toMana.SetData_t( CTFILENAME("TexturesMP\\Interface\\IValue.tex")); + _toArmorSmall.SetData_t( CTFILENAME("TexturesMP\\Interface\\ArSmall.tex")); + _toArmorMedium.SetData_t( CTFILENAME("TexturesMP\\Interface\\ArMedium.tex")); + _toArmorLarge.SetData_t( CTFILENAME("TexturesMP\\Interface\\ArStrong.tex")); + + // initialize ammo textures + _toAShells.SetData_t( CTFILENAME("TexturesMP\\Interface\\AmShells.tex")); + _toABullets.SetData_t( CTFILENAME("TexturesMP\\Interface\\AmBullets.tex")); + _toARockets.SetData_t( CTFILENAME("TexturesMP\\Interface\\AmRockets.tex")); + _toAGrenades.SetData_t( CTFILENAME("TexturesMP\\Interface\\AmGrenades.tex")); + _toANapalm.SetData_t( CTFILENAME("TexturesMP\\Interface\\AmFuelReservoir.tex")); + _toAElectricity.SetData_t( CTFILENAME("TexturesMP\\Interface\\AmElectricity.tex")); + _toAIronBall.SetData_t( CTFILENAME("TexturesMP\\Interface\\AmCannonBall.tex")); + _toASniperBullets.SetData_t( CTFILENAME("TexturesMP\\Interface\\AmSniperBullets.tex")); + _toASeriousBomb.SetData_t( CTFILENAME("TexturesMP\\Interface\\AmSeriousBomb.tex")); + // initialize weapon textures + _toWKnife.SetData_t( CTFILENAME("TexturesMP\\Interface\\WKnife.tex")); + _toWColt.SetData_t( CTFILENAME("TexturesMP\\Interface\\WColt.tex")); + _toWSingleShotgun.SetData_t( CTFILENAME("TexturesMP\\Interface\\WSingleShotgun.tex")); + _toWDoubleShotgun.SetData_t( CTFILENAME("TexturesMP\\Interface\\WDoubleShotgun.tex")); + _toWTommygun.SetData_t( CTFILENAME("TexturesMP\\Interface\\WTommygun.tex")); + _toWMinigun.SetData_t( CTFILENAME("TexturesMP\\Interface\\WMinigun.tex")); + _toWRocketLauncher.SetData_t( CTFILENAME("TexturesMP\\Interface\\WRocketLauncher.tex")); + _toWGrenadeLauncher.SetData_t( CTFILENAME("TexturesMP\\Interface\\WGrenadeLauncher.tex")); + _toWLaser.SetData_t( CTFILENAME("TexturesMP\\Interface\\WLaser.tex")); + _toWIronCannon.SetData_t( CTFILENAME("TexturesMP\\Interface\\WCannon.tex")); + _toWChainsaw.SetData_t( CTFILENAME("TexturesMP\\Interface\\WChainsaw.tex")); + _toWSniper.SetData_t( CTFILENAME("TexturesMP\\Interface\\WSniper.tex")); + _toWFlamer.SetData_t( CTFILENAME("TexturesMP\\Interface\\WFlamer.tex")); + + // initialize powerup textures (DO NOT CHANGE ORDER!) + _atoPowerups[0].SetData_t( CTFILENAME("TexturesMP\\Interface\\PInvisibility.tex")); + _atoPowerups[1].SetData_t( CTFILENAME("TexturesMP\\Interface\\PInvulnerability.tex")); + _atoPowerups[2].SetData_t( CTFILENAME("TexturesMP\\Interface\\PSeriousDamage.tex")); + _atoPowerups[3].SetData_t( CTFILENAME("TexturesMP\\Interface\\PSeriousSpeed.tex")); + // initialize sniper mask texture + _toSniperMask.SetData_t( CTFILENAME("TexturesMP\\Interface\\SniperMask.tex")); + _toSniperWheel.SetData_t( CTFILENAME("TexturesMP\\Interface\\SniperWheel.tex")); + _toSniperArrow.SetData_t( CTFILENAME("TexturesMP\\Interface\\SniperArrow.tex")); + _toSniperEye.SetData_t( CTFILENAME("TexturesMP\\Interface\\SniperEye.tex")); + _toSniperLed.SetData_t( CTFILENAME("TexturesMP\\Interface\\SniperLed.tex")); + + // initialize tile texture + _toTile.SetData_t( CTFILENAME("Textures\\Interface\\Tile.tex")); + + // set all textures as constant + ((CTextureData*)_toHealth .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toOxygen .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toFrags .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toDeaths .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toScore .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toHiScore.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toMessage.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toMana .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toArmorSmall.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toArmorMedium.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toArmorLarge.GetData())->Force(TEX_CONSTANT); + + ((CTextureData*)_toAShells .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toABullets .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toARockets .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toAGrenades .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toANapalm .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toAElectricity .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toAIronBall .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toASniperBullets.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toASeriousBomb .GetData())->Force(TEX_CONSTANT); + + ((CTextureData*)_toWKnife .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWColt .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWSingleShotgun .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWDoubleShotgun .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWTommygun .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWRocketLauncher .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWGrenadeLauncher.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWChainsaw .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWLaser .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWIronCannon .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWSniper .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWMinigun .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toWFlamer .GetData())->Force(TEX_CONSTANT); + + ((CTextureData*)_atoPowerups[0].GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_atoPowerups[1].GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_atoPowerups[2].GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_atoPowerups[3].GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toTile .GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toSniperMask.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toSniperWheel.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toSniperArrow.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toSniperEye.GetData())->Force(TEX_CONSTANT); + ((CTextureData*)_toSniperLed.GetData())->Force(TEX_CONSTANT); + + } + catch( char *strError) { + FatalError( strError); + } + +} + + +// clean up +extern void EndHUD(void) +{ + +} + diff --git a/Sources/EntitiesMP/Common/Particles.cpp b/Sources/EntitiesMP/Common/Particles.cpp new file mode 100644 index 0000000..4edbf9d --- /dev/null +++ b/Sources/EntitiesMP/Common/Particles.cpp @@ -0,0 +1,6045 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" +#include "EntitiesMP/BloodSpray.h" +#include "EntitiesMP/PlayerWeapons.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/EnvironmentParticlesHolder.h" + +static CTextureObject _toRomboidTrail; +static CTextureObject _toBombTrail; +static CTextureObject _toFirecrackerTrail; +static CTextureObject _toSpiralTrail; +static CTextureObject _toColoredStarsTrail; +static CTextureObject _toFireball01Trail; +static CTextureObject _toGrenadeTrail; +static CTextureObject _toCannonBall; +static CTextureObject _toRocketTrail; +static CTextureObject _toVerticalGradient; +static CTextureObject _toVerticalGradientAlpha; +static CTextureObject _toBlood01Trail; +static CTextureObject _toLavaTrailGradient; +static CTextureObject _toLavaTrailSmoke; +static CTextureObject _toFlamethrowerTrail01; +static CTextureObject _toFlamethrowerTrail02; +static CTextureObject _toFire; +static CTextureObject _toBoubble01; +static CTextureObject _toBoubble02; +static CTextureObject _toBoubble03; +static CTextureObject _toStar01; +static CTextureObject _toStar02; +static CTextureObject _toStar03; +static CTextureObject _toStar04; +static CTextureObject _toStar05; +static CTextureObject _toStar06; +static CTextureObject _toStar07; +static CTextureObject _toStar08; +static CTextureObject _toBlood; +static CTextureObject _toWaterfallGradient; +static CTextureObject _toGhostbusterBeam; +static CTextureObject _toLightning; +static CTextureObject _toSand; +static CTextureObject _toSandFlowGradient; +static CTextureObject _toWater; +static CTextureObject _toWaterFlowGradient; +static CTextureObject _toLava; +static CTextureObject _toLavaFlowGradient; +static CTextureObject _toBloodSprayTexture; +static CTextureObject _toFlowerSprayTexture; +static CTextureObject _toBonesSprayTexture; +static CTextureObject _toFeatherSprayTexture; +static CTextureObject _toStonesSprayTexture; +static CTextureObject _toLavaSprayTexture; +static CTextureObject _toBeastProjectileSprayTexture; +static CTextureObject _toLavaEruptingTexture; +static CTextureObject _toWoodSprayTexture; +static CTextureObject _toTreeSprayTexture; +static CTextureObject _toLavaBombTrailSmoke; +static CTextureObject _toLavaBombTrailGradient; +static CTextureObject _toElectricitySparks; +static CTextureObject _toBeastProjectileTrailTexture; +static CTextureObject _toBeastProjectileTrailGradient; +static CTextureObject _toBeastBigProjectileTrailTexture; +static CTextureObject _toBeastBigProjectileTrailGradient; +static CTextureObject _toBeastDebrisTrailGradient; +static CTextureObject _toBeastDebrisTrailTexture; +static CTextureObject _toRaindrop; +static CTextureObject _toSnowdrop; +static CTextureObject _toBulletStone; +static CTextureObject _toBulletSand; +static CTextureObject _toBulletSpark; +static CTextureObject _toBulletSmoke; +static CTextureObject _toBulletWater; +static CTextureObject _toPlayerParticles; +static CTextureObject _toWaterfallFoam; +static CTextureObject _toWaterfallFoam2; +static CTextureObject _toMetalSprayTexture; +static CTextureObject _toBulletGrass; +static CTextureObject _toBulletWood; +static CTextureObject _toBulletSnow; +static CTextureObject _toAirSprayTexture; +static CTextureObject _toFlameThrowerGradient; +static CTextureObject _toFlameThrowerStartGradient; +static CTextureObject _toSpawnerProjectile; +static CTextureObject _toExplosionDebris; +static CTextureObject _toExplosionDebrisGradient; +static CTextureObject _toExplosionSpark; +static CTextureObject _toChimneySmoke; +static CTextureObject _toChimneySmokeGradient; +static CTextureObject _toWaterfallGradient2; +static CTextureObject _toAfterBurner; +static CTextureObject _toAfterBurnerHead; +static CTextureObject _toAfterBurnerGradient; +static CTextureObject _toAfterBurnerGradientBlue; +static CTextureObject _toAfterBurnerGradientMeteor; +static CTextureObject _toTwisterGradient; +static CTextureObject _toTwister; +static CTextureObject _toLarvaLaser; +static CTextureObject _toLarvaProjectileSpray; +static CTextureObject _toGrowingTwirl; +static CTextureObject _toSummonerDisappearGradient; +static CTextureObject _toSEStar01; +static CTextureObject _toSummonerStaffGradient; +static CTextureObject _toMeteorTrail; +static CTextureObject _toFireworks01Gradient; + +struct FlameThrowerParticleRenderingData { + INDEX ftprd_iFrameX; + INDEX ftprd_iFrameY; + FLOAT3D ftprd_vPos; + FLOAT ftprd_fSize; + FLOAT ftprd_fAngle; + COLOR ftprd_colColor; +}; + +INDEX _ctFlameThrowerParticles=0; +//INDEX _ctFlameThrowerPipeParticles=0; +#define MAX_FLAME_PARTICLES INDEX(1024) +FlameThrowerParticleRenderingData _aftprdFlame[MAX_FLAME_PARTICLES]; +//FlameThrowerParticleRenderingData _aftprdFlamePipe[MAX_FLAME_PARTICLES]; + +BOOL UpdateGrowthCache(CEntity *pen, CTextureData *ptdGrowthMap, FLOATaabbox3D &boxGrowthMap, CEntity *penEPH, INDEX iDrawPort); + +// array for model vertices in absolute space +CStaticStackArray avVertices; + +// current player projection +extern CAnyProjection3D prPlayerProjection; + +extern FLOAT gfx_fEnvParticlesRange; + +#define CT_MAX_PARTICLES_TABLE 1024 + +FLOAT afTimeOffsets[CT_MAX_PARTICLES_TABLE]; +FLOAT afStarsPositions[CT_MAX_PARTICLES_TABLE][3]; +UBYTE auStarsColors[CT_MAX_PARTICLES_TABLE][3]; + +void InitParticleTables(void) +{ + for( INDEX iStar=0; iStarForce(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toLavaBombTrailGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toBeastDebrisTrailGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toBeastProjectileTrailGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toBeastBigProjectileTrailGradient.GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toWaterfallGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toSandFlowGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toWaterFlowGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toLavaFlowGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toFlameThrowerGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toFlameThrowerStartGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toExplosionDebrisGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toChimneySmokeGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toWaterfallGradient2 .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toAfterBurnerGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toAfterBurnerGradientBlue .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toAfterBurnerGradientMeteor .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toTwisterGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toSummonerDisappearGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toSummonerStaffGradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + ((CTextureData*)_toFireworks01Gradient .GetData())->Force(TEX_STATIC|TEX_CONSTANT); + } + catch(char *strError) + { + FatalError(TRANS("Unable to obtain texture: %s"), strError); + } + InitParticleTables(); +} + +// close particle effects +void CloseParticles(void) +{ + _toRomboidTrail.SetData(NULL); + _toBombTrail.SetData(NULL); + _toFirecrackerTrail.SetData(NULL); + _toSpiralTrail.SetData(NULL); + _toColoredStarsTrail.SetData(NULL); + _toFireball01Trail.SetData(NULL); + _toRocketTrail.SetData(NULL); + _toGrenadeTrail.SetData(NULL); + _toCannonBall.SetData(NULL); + _toVerticalGradient.SetData(NULL); + _toVerticalGradientAlpha.SetData(NULL); + _toBlood01Trail.SetData(NULL); + _toLavaTrailGradient.SetData(NULL); + _toWaterfallGradient.SetData(NULL); + _toGhostbusterBeam.SetData( NULL); + _toLightning.SetData( NULL); + _toLavaTrailSmoke.SetData(NULL); + _toFlamethrowerTrail01.SetData(NULL); + _toFlamethrowerTrail02.SetData(NULL); + _toFire.SetData(NULL); + _toBoubble01.SetData(NULL); + _toBoubble02.SetData(NULL); + _toBoubble03.SetData(NULL); + _toStar01.SetData(NULL); + _toStar02.SetData(NULL); + _toStar03.SetData(NULL); + _toStar04.SetData(NULL); + _toStar05.SetData(NULL); + _toStar06.SetData(NULL); + _toStar07.SetData(NULL); + _toStar08.SetData(NULL); + _toSand.SetData(NULL); + _toSandFlowGradient.SetData(NULL); + _toWater.SetData(NULL); + _toWaterFlowGradient.SetData(NULL); + _toLava.SetData(NULL); + _toLavaFlowGradient.SetData(NULL); + _toLavaBombTrailSmoke.SetData(NULL); + _toLavaBombTrailGradient.SetData(NULL); + _toBloodSprayTexture.SetData(NULL); + _toFlowerSprayTexture.SetData(NULL); + _toBonesSprayTexture.SetData(NULL); + _toFeatherSprayTexture.SetData(NULL); + _toStonesSprayTexture.SetData(NULL); + _toLavaSprayTexture.SetData(NULL); + _toBeastProjectileSprayTexture.SetData(NULL); + _toLavaEruptingTexture.SetData(NULL); + _toWoodSprayTexture.SetData(NULL); + _toTreeSprayTexture.SetData(NULL); + _toElectricitySparks.SetData(NULL); + _toBeastDebrisTrailGradient.SetData(NULL); + _toBeastProjectileTrailTexture.SetData(NULL); + _toBeastProjectileTrailGradient.SetData(NULL); + _toBeastBigProjectileTrailTexture.SetData(NULL); + _toBeastBigProjectileTrailGradient.SetData(NULL); + _toBeastDebrisTrailTexture.SetData(NULL); + _toRaindrop.SetData(NULL); + _toSnowdrop.SetData(NULL); + _toBulletStone.SetData(NULL); + _toBulletWater.SetData(NULL); + _toBulletSand.SetData(NULL); + _toBulletSpark.SetData(NULL); + _toBulletSmoke.SetData(NULL); + _toPlayerParticles.SetData(NULL); + _toWaterfallFoam.SetData(NULL); + _toWaterfallFoam2.SetData(NULL); + _toMetalSprayTexture.SetData(NULL); + _toBulletGrass.SetData(NULL); + _toBulletWood.SetData(NULL); + _toBulletSnow.SetData(NULL); + _toAirSprayTexture.SetData(NULL); + _toFlameThrowerGradient.SetData(NULL); + _toFlameThrowerStartGradient.SetData(NULL); + _toSpawnerProjectile.SetData(NULL); + _toExplosionDebris.SetData(NULL); + _toExplosionDebrisGradient.SetData(NULL); + _toExplosionSpark.SetData(NULL); + _toChimneySmoke.SetData(NULL); + _toTwister.SetData(NULL); + _toAfterBurner.SetData(NULL); + _toAfterBurnerHead.SetData(NULL); + _toAfterBurnerGradient.SetData(NULL); + _toAfterBurnerGradientBlue.SetData(NULL); + _toAfterBurnerGradientMeteor.SetData(NULL); + _toTwisterGradient.SetData(NULL); + _toChimneySmokeGradient.SetData(NULL); + _toWaterfallGradient2.SetData(NULL); + _toLarvaLaser.SetData(NULL); + _toLarvaProjectileSpray.SetData(NULL); + _toGrowingTwirl.SetData(NULL); + _toSummonerDisappearGradient.SetData(NULL); + _toSummonerStaffGradient.SetData(NULL); + _toFireworks01Gradient.SetData(NULL); + _toSEStar01.SetData(NULL); + _toMeteorTrail.SetData(NULL); +} + +void SetupParticleTexture(enum ParticleTexture ptTexture) +{ + switch(ptTexture) { + case PT_STAR01: Particle_PrepareTexture(&_toStar01, PBT_ADD); break; + case PT_STAR02: Particle_PrepareTexture(&_toStar02, PBT_ADD); break; + case PT_STAR03: Particle_PrepareTexture(&_toStar03, PBT_ADD); break; + case PT_STAR04: Particle_PrepareTexture(&_toStar04, PBT_ADD); break; + case PT_STAR05: Particle_PrepareTexture(&_toStar05, PBT_ADD); break; + case PT_STAR06: Particle_PrepareTexture(&_toStar06, PBT_ADD); break; + case PT_STAR07: Particle_PrepareTexture(&_toStar07, PBT_ADD); break; + case PT_STAR08: Particle_PrepareTexture(&_toStar08, PBT_ADD); break; + case PT_BOUBBLE01: Particle_PrepareTexture(&_toBoubble01, PBT_ADD); break; + case PT_BOUBBLE02: Particle_PrepareTexture(&_toBoubble02, PBT_ADD); break; + case PT_WATER01: Particle_PrepareTexture(&_toBoubble03, PBT_BLEND); break; + case PT_WATER02: Particle_PrepareTexture(&_toBoubble03, PBT_BLEND); break; + case PT_SANDFLOW: Particle_PrepareTexture(&_toSand, PBT_BLEND); break; + case PT_WATERFLOW: Particle_PrepareTexture(&_toWater, PBT_BLEND); break; + case PT_LAVAFLOW: Particle_PrepareTexture(&_toLava, PBT_BLEND); break; + default: ASSERT(FALSE); + } + Particle_SetTexturePart( 512, 512, 0, 0); +} + +void SetupParticleTextureWithAddAlpha(enum ParticleTexture ptTexture) +{ + switch(ptTexture) { + case PT_STAR01: Particle_PrepareTexture(&_toStar01, PBT_ADDALPHA); break; + case PT_STAR02: Particle_PrepareTexture(&_toStar02, PBT_ADDALPHA); break; + case PT_STAR03: Particle_PrepareTexture(&_toStar03, PBT_ADDALPHA); break; + case PT_STAR04: Particle_PrepareTexture(&_toStar04, PBT_ADDALPHA); break; + case PT_STAR05: Particle_PrepareTexture(&_toStar05, PBT_ADDALPHA); break; + case PT_STAR06: Particle_PrepareTexture(&_toStar06, PBT_ADDALPHA); break; + case PT_STAR07: Particle_PrepareTexture(&_toStar07, PBT_ADDALPHA); break; + case PT_STAR08: Particle_PrepareTexture(&_toStar08, PBT_ADDALPHA); break; + case PT_BOUBBLE01: Particle_PrepareTexture(&_toBoubble01, PBT_ADDALPHA); break; + case PT_BOUBBLE02: Particle_PrepareTexture(&_toBoubble02, PBT_ADDALPHA); break; + case PT_WATER01: Particle_PrepareTexture(&_toBoubble03, PBT_BLEND); break; + case PT_WATER02: Particle_PrepareTexture(&_toBoubble03, PBT_BLEND); break; + case PT_SANDFLOW: Particle_PrepareTexture(&_toSand, PBT_BLEND); break; + case PT_WATERFLOW: Particle_PrepareTexture(&_toWater, PBT_BLEND); break; + case PT_LAVAFLOW: Particle_PrepareTexture(&_toLava, PBT_BLEND); break; + default: ASSERT(FALSE); + } + Particle_SetTexturePart( 512, 512, 0, 0); +} + +void Particles_ViewerLocal(CEntity *penView) +{ + ASSERT(penView!=NULL); + + // obtain world settings controller + CWorldSettingsController *pwsc = NULL; + CEnvironmentParticlesHolder *eph = NULL; + // obtain bcg viewer + CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) penView->GetWorld()->GetBackgroundViewer(); + if (penBcgViewer != NULL) + { + // obtain world settings controller + pwsc = (CWorldSettingsController *)&*penBcgViewer->m_penWorldSettingsController; + if (pwsc != NULL) + { + // obtain environment particles holder + eph = (CEnvironmentParticlesHolder *)&*pwsc->m_penEnvPartHolder; + } + } + + FLOATaabbox3D boxViewer; + penView->GetBoundingBox(boxViewer); + + while (eph != NULL) + { + // calculate the bounding box inside which particles will be visible + FLOATaabbox3D boxViewTreshold; + boxViewTreshold = eph->m_boxHeightMap; + boxViewTreshold += eph->GetPlacement().pl_PositionVector; + + FLOAT fRangeMod = Clamp(gfx_fEnvParticlesRange, 0.1f, 2.0f); + if (eph->m_eptType == EPTH_GROWTH) { + boxViewTreshold.Expand(eph->m_fGrowthRenderingRadius*fRangeMod+5.0f); + } + + // shared height box variables + FLOATaabbox3D boxTerrainMap; + CTextureData *ptdTerrainMap; + + if (boxViewer.HasContactWith(boxViewTreshold)) { + switch (eph->m_eptType) { + + case EPTH_GROWTH: + // misc. growth - grass, bushes + if( pwsc != NULL ) + { + eph->GetHeightMapData( ptdTerrainMap, boxTerrainMap); + Particles_Growth( penView, ptdTerrainMap, boxTerrainMap, eph, Particle_GetDrawPortID()); + } + break; + + case EPTH_RAIN: { + // rain + FLOAT fRainFactor = eph->GetRainFactor(); + if( fRainFactor != 0.0f) + { + eph->GetHeightMapData( ptdTerrainMap, boxTerrainMap); + Particles_Rain( penView, 1.25f, 32, fRainFactor, ptdTerrainMap, boxTerrainMap); + } + break; } + + case EPTH_SNOW: { + // snow + FLOAT fSnowFactor = eph->GetSnowFactor(); + if( fSnowFactor != 0.0f) + { + eph->GetHeightMapData( ptdTerrainMap, boxTerrainMap); + Particles_Snow( penView, 2.0f, 32, fSnowFactor, ptdTerrainMap, boxTerrainMap, eph->m_tmSnowStart); + } + break; } + + case EPTH_NONE: + break; + + default: + ASSERT("Unknown environment particle type!"); + break; + } + // for those EPHs that are not rendered, clear possible + // growth caches + } else if (eph->m_eptType==EPTH_GROWTH) { + // delete the cache for this EPH and this DrawPort + INDEX iDrawPort = Particle_GetDrawPortID(); + {FORDELETELIST(CGrowthCache, cgc_Node, eph->lhCache, itCache) + if (itCache->ulID==iDrawPort) { + itCache->acgParticles.Clear(); + itCache->cgc_Node.Remove(); + delete &itCache.Current(); + //CPrintF("removed ph %s \n", eph->GetName()); + } + } + } + + // next environment particles holder + eph = (CEnvironmentParticlesHolder *)&*eph->m_penNextHolder; + if (!(IsOfClass(eph, "EnvironmentParticlesHolder"))) break; + } + + if(_ctFlameThrowerParticles!=0) + { + Particle_PrepareTexture( &_toFlamethrowerTrail02, PBT_ADDALPHA); + INDEX flt_iFramesInRaw=4; + INDEX flt_iFramesInColumn=4; + for( INDEX iFlame=0; iFlameGetLastPositions(ROMBOID_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toRomboidTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + for(INDEX iPos = 0; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + FLOAT fRand = rand()/FLOAT(RAND_MAX); + FLOAT fAngle = fSeconds*256+iPos*2.0f*PI/ROMBOID_TRAIL_POSITIONS; + FLOAT fSin = FLOAT(sin(fAngle)); + vPos(2) += fSin*iPos/ROMBOID_TRAIL_POSITIONS; + FLOAT fSize = (ROMBOID_TRAIL_POSITIONS-iPos)*0.5f/ROMBOID_TRAIL_POSITIONS+0.1f; + UBYTE ub = 255-iPos*255/ROMBOID_TRAIL_POSITIONS; + Particle_RenderSquare( vPos, fSize, fAngle, RGBToColor(255-ub,ub,255-ub)|ub); + } + // all done + Particle_Flush(); +} + +#define BOMB_TRAIL_POSITIONS 8 +#define BOMB_TRAIL_INTERPOSITIONS 4 +void Particles_BombTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(BOMB_TRAIL_POSITIONS); +} +void Particles_BombTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(BOMB_TRAIL_POSITIONS); + + Particle_PrepareTexture(&_toBombTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(plp->lp_ctUsed-1); + for(INDEX iPos = plp->lp_ctUsed-1; iPos>=1; iPos--) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + for (INDEX iInter=0; iInterGetLastPositions(FIRECRACKER_TRAIL_POSITIONS); +} +void Particles_FirecrackerTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(FIRECRACKER_TRAIL_POSITIONS); + Particle_PrepareTexture(&_toFirecrackerTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + if( plp->lp_ctUsed<2) return; + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(plp->lp_ctUsed-1); + INDEX iParticle = plp->lp_ctUsed*FIRECRACKER_TRAIL_INTERPOSITIONS; + for(INDEX iPos = plp->lp_ctUsed-2; iPos>=0; iPos--) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + for (INDEX iInter=0; iInterGetLastPositions(SPIRAL_TRAIL_POSITIONS); + + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + Particle_PrepareTexture(&_toSpiralTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + for(INDEX iPos = 0; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + FLOAT fAngle = fSeconds*32.0f+iPos*2*PI/SPIRAL_TRAIL_POSITIONS; + FLOAT fSin = FLOAT(sin(fAngle)); + FLOAT fCos = FLOAT(cos(fAngle)); + + vPos(1) += fSin*iPos*1.0f/SPIRAL_TRAIL_POSITIONS; + vPos(2) += fCos*iPos*1.0f/SPIRAL_TRAIL_POSITIONS; + + UBYTE ub = iPos*SPIRAL_TRAIL_POSITIONS; + Particle_RenderSquare( vPos, 0.2f, fAngle, RGBToColor(ub,ub,ub)|ub); + } + // all done + Particle_Flush(); +} + +static COLOR _aColors[] = { C_WHITE, C_GRAY, + C_RED, C_GREEN, C_BLUE, C_CYAN, C_MAGENTA, C_YELLOW, C_ORANGE, C_BROWN, C_PINK, + C_lRED, C_lGREEN, C_lBLUE, C_lCYAN, C_lMAGENTA, C_lYELLOW, C_lORANGE, C_lBROWN, C_lPINK +}; + +#define COLORED_STARS_TRAIL_POSITIONS 16 +void Particles_ColoredStarsTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(COLORED_STARS_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toColoredStarsTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + for(INDEX iPos = 0; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos1 = plp->GetPosition(iPos); + //FLOAT3D vPos2 = vPos1; + + FLOAT fAngle = fSeconds*64.0f+iPos*2*PI/COLORED_STARS_TRAIL_POSITIONS; + FLOAT fSin = FLOAT(sin(fAngle)); + //FLOAT fCos = FLOAT(cos(fAngle)); + + FLOAT fDeltaY = fSin/2.0f; + vPos1(2) += fDeltaY; + //vPos2(2) -= fDeltaY; + + FLOAT fRand = rand()/FLOAT(RAND_MAX); + INDEX iRandColor = INDEX(fRand*sizeof(_aColors)/sizeof(COLOR)); + COLOR colColor1 = _aColors[ iRandColor]; + Particle_RenderSquare( vPos1, 0.4f, fAngle, colColor1); + } + // all done + Particle_Flush(); +} + +#define WHITE_LINE_TRAIL_POSITIONS 8 +void Particles_WhiteLineTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(WHITE_LINE_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toSpiralTrail, PBT_ADD); + Particle_SetTexturePart( 1, 1, 256, 256); + + FLOAT3D vOldPos = plp->GetPosition(0); + for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + FLOAT fAngle = fSeconds*4.0f+iPos*PI/WHITE_LINE_TRAIL_POSITIONS; + FLOAT fSin = FLOAT(sin(fAngle)); + FLOAT fCos = FLOAT(cos(fAngle)); + + vPos(1) += fSin*iPos*1.0f/WHITE_LINE_TRAIL_POSITIONS; + vPos(2) += fCos*iPos*1.0f/WHITE_LINE_TRAIL_POSITIONS; + + UBYTE ub = 255-iPos*256/WHITE_LINE_TRAIL_POSITIONS; + FLOAT fLerpFactor = FLOAT(iPos)/WHITE_LINE_TRAIL_POSITIONS; + COLOR colColor = LerpColor( C_YELLOW, C_dRED, fLerpFactor); + Particle_RenderLine( vPos, vOldPos, 0.05f, colColor); + vOldPos =vPos; + } + // all done + Particle_Flush(); +} + + +#define FIREBALL01_TRAIL_POSITIONS 8 +#define FIREBALL01_TRAIL_INTERPOSITIONS 4 +#define FIREBALL01_TRAIL_PARTICLES (FIREBALL01_TRAIL_INTERPOSITIONS*FIREBALL01_TRAIL_POSITIONS) +void Particles_Fireball01Trail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(FIREBALL01_TRAIL_POSITIONS); +} +void Particles_Fireball01Trail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(FIREBALL01_TRAIL_POSITIONS); + Particle_PrepareTexture(&_toFireball01Trail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(plp->lp_ctUsed-1); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*FIREBALL01_TRAIL_INTERPOSITIONS; + for(INDEX iPos = plp->lp_ctUsed-2; iPos>=0; iPos--) { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + COLOR colColor; + for (INDEX iInter=0; iInterGetLastPositions(GRENADE_TRAIL_POSITIONS); +} +void Particles_GrenadeTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(GRENADE_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toGrenadeTrail, PBT_MULTIPLY); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(0); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*GRENADE_TRAIL_INTERPOSITIONS; + for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + for (INDEX iInter=0; iInterGetLastPositions(CANNON_TRAIL_POSITIONS); +} +void Particles_CannonBall(CEntity *pen, FLOAT fSpeedRatio) +{ + CLastPositions *plp = pen->GetLastPositions(CANNON_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toCannonBall, PBT_BLEND); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT3D vOldPos = plp->GetPosition(1); + for( INDEX iPos=2; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + UBYTE ub = UBYTE((255-iPos*256/plp->lp_ctUsed)*fSpeedRatio); + FLOAT fSize = (CANNON_TRAIL_POSITIONS-iPos)*0.04f+0.04f; + Particle_RenderLine( vPos, vOldPos, fSize, RGBToColor(ub,ub,ub)|ub); + vOldPos=vPos; + } + // all done + Particle_Flush(); +} + +#define LAVA_TRAIL_POSITIONS 32 +#define LAVA_TRAIL_INTERPOSITIONS 1 +void Particles_LavaTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(LAVA_TRAIL_POSITIONS); +} +void Particles_LavaTrail(CEntity *pen) +{ + CLastPositions *plp = pen->GetLastPositions(LAVA_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + CTextureData *pTD = (CTextureData *) _toLavaTrailGradient.GetData(); + Particle_PrepareTexture(&_toLavaTrailSmoke, PBT_BLEND); + //Particle_PrepareTexture(&_toLavaTrailSmoke, PBT_MULTIPLY); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(0); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*LAVA_TRAIL_INTERPOSITIONS; + for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + for (INDEX iInter=0; iInterGetTexel(PIX(FLOAT(iParticle)/iParticlesLiving*8*1024), 0); + Particle_RenderSquare( vPos, fSize, fAngle, col); + iParticle++; + } + } + // all done + Particle_Flush(); +} + +#define LAVA_BOMB_TRAIL_POSITIONS 16 +#define LAVA_BOMB_TRAIL_INTERPOSITIONS 1 +void Particles_LavaBombTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(LAVA_BOMB_TRAIL_POSITIONS); +} + +void Particles_LavaBombTrail(CEntity *pen, FLOAT fSizeMultiplier) +{ + CLastPositions *plp = pen->GetLastPositions(LAVA_BOMB_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + CTextureData *pTD = (CTextureData *) _toLavaBombTrailGradient.GetData(); + Particle_PrepareTexture(&_toLavaBombTrailSmoke, PBT_BLEND); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(0); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*LAVA_BOMB_TRAIL_INTERPOSITIONS; + for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) + { + INDEX iRnd = ((ULONG)fSeconds+iPos)%CT_MAX_PARTICLES_TABLE; + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + if( *pvPos1 == *pvPos2) continue; + for (INDEX iInter=0; iInterGetTexel(PIX(FLOAT(iParticle)/iParticlesLiving*8*1024), 0); + Particle_RenderSquare( vPos, fSize, fAngle, col); + iParticle++; + } + } + // all done + Particle_Flush(); +} + +#define BEAST_PROJECTILE_DEBRIS_TRAIL_POSITIONS 8 +#define BEAST_PROJECTILE_DEBRIS_TRAIL_INTERPOSITIONS 1 +void Particles_BeastProjectileDebrisTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(BEAST_PROJECTILE_DEBRIS_TRAIL_POSITIONS); +} + +void Particles_BeastProjectileDebrisTrail(CEntity *pen, FLOAT fSizeMultiplier) +{ + CLastPositions *plp = pen->GetLastPositions(BEAST_PROJECTILE_DEBRIS_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + CTextureData *pTD = (CTextureData *) _toBeastDebrisTrailGradient.GetData(); + Particle_PrepareTexture(&_toBeastDebrisTrailTexture, PBT_BLEND); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(0); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*BEAST_PROJECTILE_DEBRIS_TRAIL_INTERPOSITIONS; + for(INDEX iPos = 1; iPoslp_ctUsed; iPos++) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + for (INDEX iInter=0; iInterGetTexel(PIX(FLOAT(iParticle)/iParticlesLiving*8*1024), 0); + Particle_RenderSquare( vPos, fSize, fAngle, col); + iParticle++; + } + } + // all done + Particle_Flush(); +} + +#define BEAST_PROJECTILE_TRAIL_POSITIONS 32 +#define BEAST_PROJECTILE_TRAIL_INTERPOSITIONS 1 +void Particles_BeastProjectileTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(BEAST_PROJECTILE_TRAIL_POSITIONS); +} + +#define BEAST_PROJECTILE_LINE_PARTICLES 0.4f +#define BEAST_PROJECTILE_FADE_OUT 0.3f +#define BEAST_PROJECTILE_TOTAL_TIME 0.6f +void Particles_BeastProjectileTrail( CEntity *pen, FLOAT fSize, FLOAT fHeight, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toBeastProjectileTrailTexture, PBT_BLEND); + Particle_SetTexturePart( 512, 2048, 0, 0); + + CTextureData *pTD = (CTextureData *) _toBeastProjectileTrailGradient.GetData(); + + CPlacement3D pl = pen->GetLerpedPlacement(); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, pl.pl_OrientationAngle); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( -m(1,3), -m(2,3), -m(3,3)); + FLOAT3D vZ( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pl.pl_PositionVector+vY*fHeight; + + for( INDEX iStar=0; iStar(1.0f-BEAST_PROJECTILE_FADE_OUT)) fFade=(1-fT)*(1/BEAST_PROJECTILE_FADE_OUT); + else fFade=1.0f; + +#define GET_POS( time) vCenter + \ + vX*(afStarsPositions[iStar][0]*time*fSize*1.5) +\ + vY*(-time*time*10.0f+(afStarsPositions[iStar][1]*2+2.0f)*1.2f*time) +\ + vZ*(afStarsPositions[iStar][2]*time*fSize*1.5); + + FLOAT3D vPos = GET_POS( fT); + COLOR colStar = pTD->GetTexel( ClampUp(FloatToInt(fT*8192),8191L), 0); + + if( fT>BEAST_PROJECTILE_LINE_PARTICLES) + { + FLOAT fTimeOld = fT-0.25f; + FLOAT3D vOldPos = GET_POS( fTimeOld); + Particle_RenderLine( vOldPos, vPos, 0.4f, colStar); + } + else + { + Particle_RenderSquare( vPos, 0.5f, fT*360.0f, colStar); + } + } + // all done + Particle_Flush(); +} + +#define BEAST_BIG_PROJECTILE_TRAIL_POSITIONS 32 +#define BEAST_BIG_PROJECTILE_TRAIL_INTERPOSITIONS 1 +void Particles_BeastBigProjectileTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(BEAST_BIG_PROJECTILE_TRAIL_POSITIONS); +} + +#define BIG_BEAST_PROJECTILE_LINE_PARTICLES 0.4f +#define BIG_BEAST_PROJECTILE_FADE_OUT 0.4f +#define BIG_BEAST_PROJECTILE_TOTAL_TIME 0.6f +void Particles_BeastBigProjectileTrail( CEntity *pen, FLOAT fSize, FLOAT fZOffset, FLOAT fYOffset, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toBeastBigProjectileTrailTexture, PBT_BLEND); + Particle_SetTexturePart( 512, 2048, 0, 0); + + CTextureData *pTD = (CTextureData *) _toBeastBigProjectileTrailGradient.GetData(); + + CPlacement3D pl = pen->GetLerpedPlacement(); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, pl.pl_OrientationAngle); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( -m(1,3), -m(2,3), -m(3,3)); + FLOAT3D vZ( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pl.pl_PositionVector+vY*fZOffset+vZ*fYOffset; + + for( INDEX iStar=0; iStar(1.0f-BIG_BEAST_PROJECTILE_FADE_OUT)) fFade=(1-fT)*(1/BIG_BEAST_PROJECTILE_FADE_OUT); + else fFade=1.0f; + +#define GET_POS_BIG( time) vCenter + \ + vX*(afStarsPositions[iStar][0]*time*fSize*1.5) +\ + vY*(time*time*-15.0f+(afStarsPositions[iStar][1]*2+3.0f)*1.2f*time) +\ + vZ*(afStarsPositions[iStar][2]*time*fSize*1.5); + + FLOAT3D vPos = GET_POS_BIG( fT); + COLOR colStar = pTD->GetTexel( ClampUp(FloatToInt(fT*8192),8191L), 0); + + if( fT>BIG_BEAST_PROJECTILE_LINE_PARTICLES) + { + FLOAT fTimeOld = fT-0.125f; + FLOAT3D vOldPos = GET_POS_BIG( fTimeOld); + Particle_RenderLine( vOldPos, vPos, 0.6f*fFade, colStar); + } + else + { + Particle_RenderSquare( vPos, 0.5, fT*360.0f, colStar); + } + } + // all done + Particle_Flush(); +} + +#define ROCKET_TRAIL_POSITIONS 16 +#define ROCKET_TRAIL_INTERPOSITIONS 3 +void Particles_RocketTrail_Prepare(CEntity *pen) +{ + pen->GetLastPositions(ROCKET_TRAIL_POSITIONS); +} +void Particles_RocketTrail(CEntity *pen, FLOAT fStretch) +{ + CLastPositions *plp = pen->GetLastPositions(ROCKET_TRAIL_POSITIONS); + FLOAT fSeconds = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toRocketTrail, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(1); + INDEX iParticle = 0; + INDEX iParticlesLiving = plp->lp_ctUsed*ROCKET_TRAIL_INTERPOSITIONS; + INDEX iPos=2; + for( ; iPoslp_ctUsed; iPos++) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + if( (*pvPos2 - *pvPos1).Length() == 0.0f) + { + continue; + } + for (INDEX iInter=0; iInterGetPosition(1); + for( iPos=2; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + if( (vPos - vOldPos).Length() == 0.0f) + { + continue; + } + UBYTE ub = UBYTE(255-iPos*256/plp->lp_ctUsed); + FLOAT fSize = iPos*0.01f*fStretch+0.005f; + Particle_RenderLine( vPos, vOldPos, fSize, RGBToColor(ub,ub,ub)|ub); + vOldPos=vPos; + } + // all done + Particle_Flush(); +} + +#define TM_EXPLOSIONDEBRISLIFE1 0.75f +#define CT_EXPLOSIONDEBRIS1 128 +void Particles_ExplosionDebris1(CEntity *pen, FLOAT tmStart, FLOAT3D vStretch, COLOR colMultiply/*=C_WHITE|CT_OPAQUE*/) +{ + CTextureData *pTD = (CTextureData *) _toExplosionDebrisGradient.GetData(); + Particle_PrepareTexture( &_toLavaEruptingTexture, PBT_ADDALPHA); + + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*0.5f; + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fG=5.0f; + FLOAT fStretchSize=(vStretch(1)+vStretch(2)+vStretch(3))/3.0f; + + for( INDEX iDebris=0; iDebrisen_ulID+iDebris+INDEX(tmStart*123456.23465f))%CT_MAX_PARTICLES_TABLE; + INDEX iRnd2=(pen->en_ulID+iDebris+INDEX(tmStart*653542.129633))%CT_MAX_PARTICLES_TABLE; + INDEX iTexture = iRnd%3; + Particle_SetTexturePart( 512, 512, iTexture, 0); + FLOAT3D vSpeed=FLOAT3D(afStarsPositions[iRnd][0],afStarsPositions[iRnd][1],afStarsPositions[iRnd][2]); + FLOAT fT=tmNow-tmStart; + FLOAT fRatio=Clamp(fT/TM_EXPLOSIONDEBRISLIFE1*(afStarsPositions[iRnd][2]+1.0f), 0.0f, 1.0f); + FLOAT fTimeDeccelerator=Clamp(1.0f-(fT/2.0f)*(fT/2.0f), 0.5f, 1.0f); + FLOAT fSpeed=(afStarsPositions[iRnd][0]+afStarsPositions[iRnd][1]+afStarsPositions[iRnd][2]+0.5f*3)/3.0f*40.0f; + fSpeed*=fTimeDeccelerator; + FLOAT3D vRel=vSpeed*fSpeed*fT-vY*fG*fT*fT; + vRel(1)*=vStretch(1); + vRel(2)*=vStretch(2); + vRel(3)*=vStretch(3); + FLOAT3D vPos=vCenter+vRel; + + UBYTE ubR = 255; + UBYTE ubG = 240+afStarsPositions[iRnd][1]*32; + UBYTE ubB = 240+afStarsPositions[iRnd][2]*32; + COLOR colAlpha = pTD->GetTexel(PIX(ClampUp(fRatio*1024.0f, 1023.0f)), 0); + COLOR col= RGBToColor( ubR, ubG, ubB) | (colAlpha&0x000000FF); + col=MulColors(col, colMultiply); + + FLOAT fSize=(0.2f+afStarsPositions[iRnd2][0]*0.2f)*fStretchSize; + FLOAT fAngle=afStarsPositions[iRnd2][1]*720.0f*fT; + Particle_RenderSquare( vPos, fSize, fAngle, col); + } + // all done + Particle_Flush(); +} + +#define TM_EXPLOSIONDEBRISLIFE2 0.85f +#define CT_EXPLOSIONDEBRIS2 32 +void Particles_ExplosionDebris2(CEntity *pen, FLOAT tmStart, FLOAT3D vStretch, COLOR colMultiply/*=C_WHITE|CT_OPAQUE*/) +{ + Particle_PrepareTexture( &_toExplosionDebris, PBT_BLEND); + CTextureData *pTD = (CTextureData *) _toExplosionDebrisGradient.GetData(); + + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*0.5f; + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fG=5.0f; + FLOAT fStretchSize=(vStretch(1)+vStretch(2)+vStretch(3))/3.0f; + + for( INDEX iDebris=0; iDebrisen_ulID+iDebris+INDEX(tmStart*432256.32423f))%CT_MAX_PARTICLES_TABLE; + INDEX iRnd2=(pen->en_ulID+iDebris+INDEX(tmStart*631512.15464f))%CT_MAX_PARTICLES_TABLE; + Particle_SetTexturePart( 256, 256, iRnd%8, 0); + FLOAT3D vSpeed=FLOAT3D(afStarsPositions[iRnd][0],afStarsPositions[iRnd][1],afStarsPositions[iRnd][2]); + FLOAT fT=tmNow-tmStart; + FLOAT fRatio=Clamp(fT/TM_EXPLOSIONDEBRISLIFE2, 0.0f, 1.0f); + FLOAT fTimeDeccelerator=Clamp(1.0f-(fT/2.0f)*(fT/2.0f), 0.5f, 1.0f); + FLOAT fSpeed=(afStarsPositions[iRnd][0]+afStarsPositions[iRnd][1]+afStarsPositions[iRnd][2]+0.5f*3)/3.0f*60.0f; + fSpeed*=fTimeDeccelerator; + FLOAT3D vRel=vSpeed*fSpeed*fT-vY*fG*fT*fT; + vRel(1)*=vStretch(1); + vRel(2)*=vStretch(2); + vRel(3)*=vStretch(3); + FLOAT3D vPos=vCenter+vRel; + + COLOR colAlpha = pTD->GetTexel(PIX(ClampUp(fRatio*1024.0f, 1023.0f)), 0); + COLOR col= C_WHITE | (colAlpha&0x000000FF); + col=MulColors(col, colMultiply); + + FLOAT fSize=(0.15f+afStarsPositions[iRnd2][0]*0.1f)*fStretchSize; + FLOAT fAngle=afStarsPositions[iRnd2][1]*2000.0f*fT; + Particle_RenderSquare( vPos, fSize, fAngle, col); + } + // all done + Particle_Flush(); +} + +#define TM_EXPLOSIONDEBRISLIFE3 0.5f +#define CT_EXPLOSIONDEBRIS3 64 +void Particles_ExplosionDebris3(CEntity *pen, FLOAT tmStart, FLOAT3D vStretch, COLOR colMultiply/*=C_WHITE|CT_OPAQUE*/) +{ + Particle_PrepareTexture( &_toExplosionSpark, PBT_ADDALPHA); + Particle_SetTexturePart( 1024, 1024, 0, 0); + CTextureData *pTD = (CTextureData *) _toExplosionDebrisGradient.GetData(); + + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*0.5f; + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fG=0.0f; + FLOAT fStretchSize=(vStretch(1)+vStretch(2)+vStretch(3))/3.0f; + + for( INDEX iDebris=0; iDebrisen_ulID+iDebris+INDEX(tmStart*317309.14521f))%CT_MAX_PARTICLES_TABLE; + INDEX iRnd2=(pen->en_ulID+iDebris+INDEX(tmStart*421852.46521f))%CT_MAX_PARTICLES_TABLE; + FLOAT3D vSpeed=FLOAT3D(afStarsPositions[iRnd][0],afStarsPositions[iRnd][1],afStarsPositions[iRnd][2])*1.25f; + FLOAT fT=tmNow-tmStart; + FLOAT fRatio=Clamp(fT/TM_EXPLOSIONDEBRISLIFE3, 0.0f, 1.0f); + FLOAT fTimeDeccelerator=Clamp(1.0f-(fT/2.0f)*(fT/2.0f), 0.75f, 1.0f); + FLOAT fSpeed=(afStarsPositions[iRnd][0]+afStarsPositions[iRnd][1]+afStarsPositions[iRnd][2]+0.5f*3)/3.0f*50.0f; + fSpeed*=fTimeDeccelerator; + FLOAT fTOld=tmNow-tmStart-0.025f-0.1f*fRatio; + + FLOAT3D vRel=vSpeed*fSpeed*fT-vY*fG*fT*fT; + vRel(1)*=vStretch(1); + vRel(2)*=vStretch(2); + vRel(3)*=vStretch(3); + FLOAT3D vPos=vCenter+vRel; + + FLOAT3D vRelOld=vSpeed*fSpeed*fTOld-vY*fG*fTOld*fTOld; + vRelOld(1)*=vStretch(1); + vRelOld(2)*=vStretch(2); + vRelOld(3)*=vStretch(3); + FLOAT3D vOldPos=vCenter+vRelOld; + if( (vPos - vOldPos).Length() == 0.0f) {continue;} + + UBYTE ubR = 255; + UBYTE ubG = 200+afStarsPositions[iRnd][1]*32; + UBYTE ubB = 150+afStarsPositions[iRnd][2]*32; + COLOR colAlpha = pTD->GetTexel(PIX(ClampUp(fRatio*1024.0f, 1023.0f)), 0); + COLOR col= RGBToColor( ubR, ubG, ubB) | (colAlpha&0x000000FF); + col=MulColors(col, colMultiply); + + FLOAT fSize=(0.1f+afStarsPositions[iRnd2][0]*0.15f)*fStretchSize; + Particle_RenderLine( vOldPos, vPos, fSize, col); + } + // all done + Particle_Flush(); +} + +#define TM_ES_TOTAL_LIFE 4.0f +#define TM_ES_SMOKE_DELTA 0.4f +void Particles_ExplosionSmoke(CEntity *pen, FLOAT tmStart, FLOAT3D vStretch, COLOR colMultiply/*=C_WHITE|CT_OPAQUE*/) +{ + Particle_PrepareTexture( &_toBulletSmoke, PBT_BLEND); + CTextureData *pTD = (CTextureData *) _toExplosionDebrisGradient.GetData(); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*1.25f; + FLOAT fStretchSize=(vStretch(1)+vStretch(2)+vStretch(3))/3.0f; + + INDEX iCtRnd =(pen->en_ulID*2+INDEX(tmStart*5311234.12531))%CT_MAX_PARTICLES_TABLE; + INDEX ctSmokes=6+INDEX((afStarsPositions[iCtRnd][0]+0.5f)*2); + for(INDEX i=0; ien_ulID+i+INDEX(tmStart*317309.14521f))%CT_MAX_PARTICLES_TABLE; + INDEX iRnd2 =(pen->en_ulID+iRnd+i*i+INDEX(tmStart*125187.83754))%CT_MAX_PARTICLES_TABLE; + INDEX iRndTex = iRnd*324561+pen->en_ulID; + Particle_SetTexturePart( 512, 512, iRndTex%3, 0); + FLOAT fTRnd=afStarsPositions[iRnd][0]; + FLOAT tmBorn=tmStart+i*TM_ES_SMOKE_DELTA+(TM_ES_SMOKE_DELTA*fTRnd)/2.0f; + FLOAT fT=fNow-tmBorn; + FLOAT fRatio=Clamp(fT/TM_ES_TOTAL_LIFE, 0.0f, 1.0f); + if( fT>0) + { + FLOAT3D vSpeed=FLOAT3D(afStarsPositions[iRnd][0]*0.15f, + afStarsPositions[iRnd][1]*0.2f+1.0f,afStarsPositions[iRnd][2]*0.15f); + FLOAT fSpeed=1.5f+(afStarsPositions[iRnd][0]+0.5f)*0.5f+fSmokeNoRatio*1.0f; + FLOAT3D vRel=vSpeed*fSpeed*fT; + vRel(1)*=vStretch(1); + vRel(2)*=vStretch(2); + vRel(3)*=vStretch(3); + FLOAT3D vPos=vCenter+vRel; + FLOAT fSize=((fSmokeNoRatio+0.125f)*2.0f+(afStarsPositions[iRnd][1]+0.5f)*1.0f*fT)*fStretchSize; + FLOAT fAngle=afStarsPositions[iRnd2][0]*360+afStarsPositions[iRnd2][1]*90.0f*fT; + FLOAT fColorRatio=CalculateRatio(fT, 0, TM_ES_TOTAL_LIFE, 0.1f, 0.4f)*(ClampUp(0.25f+fSmokeNoRatio,1.0f)); + FLOAT fRndBlend = 64.0f+(afStarsPositions[iRnd][2]+0.5f)*32.0f; + UBYTE ubRndH=255; + UBYTE ubRndS=0; + UBYTE ubRndV = UBYTE( 96.0f+afStarsPositions[iRnd][0]*64.0f); + COLOR col = HSVToColor(ubRndH,ubRndS,ubRndV)|UBYTE(fRndBlend*fColorRatio); + col=MulColors(col, colMultiply); + Particle_RenderSquare( vPos, fSize, fAngle, col); + } + } + // all done + Particle_Flush(); +} + +#define TM_CS_TOTAL_LIFE 10.0f +void Particles_ChimneySmoke(CEntity *pen, INDEX ctCount, FLOAT fStretchAll, FLOAT fMipDisappearDistance) +{ + FLOAT fMipFactor = Particle_GetMipFactor(); + if( fMipFactor>fMipDisappearDistance) return; + FLOAT fMipBlender=CalculateRatio(fMipFactor, 0.0f, fMipDisappearDistance, 0.0f, 0.1f); + + Particle_PrepareTexture( &_toChimneySmoke, PBT_BLEND); + Particle_SetTexturePart( 1024, 1024, 0, 0); + CTextureData *pTD = (CTextureData *) _toChimneySmokeGradient.GetData(); + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*0.0f; + INDEX iPosRnd=INDEX(vCenter(1)*2343.1123f+vCenter(2)*3251.16732+vCenter(3)*2761.6323f); + INDEX iCtRnd = Abs(INDEX(pen->en_ulID+iPosRnd)); + INDEX ctSmokes=22+INDEX((afStarsPositions[iCtRnd%CT_MAX_PARTICLES_TABLE][0]+0.5f)*8); + for(INDEX i=0; ien_ulID+i)%CT_MAX_PARTICLES_TABLE; + FLOAT fT = tmNow+afTimeOffsets[i]; + // apply time strech + fT *= 1/TM_CS_TOTAL_LIFE; + // get fraction part + fT = fT-int(fT); + FLOAT fSlowFactor=1.0f-fT*0.25f; + FLOAT3D vSpeed=FLOAT3D(afStarsPositions[iRnd][0]*0.15f, + (afStarsPositions[iRnd][1]*0.1f+0.8f)*fSlowFactor,afStarsPositions[iRnd][2]*0.15f); + FLOAT fSpeed=25.0f+(afStarsPositions[iRnd][0]+0.5f)*2.0f; + FLOAT3D vPos=vCenter+vSpeed*fSpeed*fT*fStretchAll; + FLOAT fSize=(0.75f+(afStarsPositions[iRnd][1]+0.5f)*4.0f*fT)*fStretchAll; + FLOAT fAngle=afStarsPositions[iRnd][0]*360+afStarsPositions[iRnd][1]*360.0f*fT; + COLOR col = pTD->GetTexel(PIX((afStarsPositions[iRnd][2]+0.5f)*1024.0f), 0); + COLOR colA = pTD->GetTexel(PIX(ClampUp(fT*1024.0f, 1023.0f)), 0); + UBYTE ubA=UBYTE((colA&0xFF)*0.75f*fMipBlender); + COLOR colCombined=(col&0xFFFFFF00)|ubA; + Particle_RenderSquare( vPos, fSize, fAngle, colCombined); + } + // all done + Particle_Flush(); +} + +void DECL_DLL Particles_Waterfall(CEntity *pen, INDEX ctCount, FLOAT fStretchAll, FLOAT fStretchX, FLOAT fStretchY, + FLOAT fStretchZ, FLOAT fSize, FLOAT fMipDisappearDistance, + FLOAT fParam1) +{ + FLOAT fMipFactor = Particle_GetMipFactor(); + if( fMipFactor>fMipDisappearDistance) return; + FLOAT fMipBlender=CalculateRatio(fMipFactor, 0.0f, fMipDisappearDistance, 0.0f, 0.1f); + + Particle_PrepareTexture( &_toWaterfallFoam2, PBT_ADDALPHA); + CTextureData *pTD = (CTextureData *) _toWaterfallGradient2.GetData(); + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vG=vY; + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + vX=vX*fStretchX*fStretchAll; + vY=vY*fStretchY*fStretchAll; + vZ=vZ*fStretchZ*fStretchAll; + FLOAT fGA = 10.0f; + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*0.0f; + for(INDEX i=0; ien_ulID+i)%CT_MAX_PARTICLES_TABLE; + INDEX iFrame=iRnd%4; + Particle_SetTexturePart( 256, 256, iFrame, 0); + FLOAT fT = tmNow+afTimeOffsets[i]; + // apply time strech + fT *= 1/fParam1; + // get fraction part + fT = fT-int(fT); + FLOAT fSlowFactor=1.0f-fT*0.25f; + FLOAT3D vSpeed= + vX*(afStarsPositions[iRnd][0]*0.25f)+ + vY*(afStarsPositions[iRnd][0]*0.25f)+ + -vZ*(1.5f+afStarsPositions[iRnd][0]*0.25f); + FLOAT fSpeed=20.0f+(afStarsPositions[iRnd][0]+0.5f)*2.0f; + FLOAT3D vPos=vCenter+vSpeed*fSpeed*fT-vG*fGA/2.0f*(fT*fParam1)*(fT*fParam1); + FLOAT fFinalSize=(3.5f+(afStarsPositions[iRnd][1]+1.0f)*2.0f*fT)*fSize; + FLOAT fAngle=afStarsPositions[iRnd][0]*360+afStarsPositions[iRnd][1]*360.0f*fT*fParam1/2.0f; + if( iFrame>=2) + { + fAngle=0.0f; + } + COLOR col = pTD->GetTexel(PIX((afStarsPositions[iRnd][2]+0.5f)*1024.0f), 0); + COLOR colA = pTD->GetTexel(PIX(ClampUp(fT*1024.0f, 1023.0f)), 0); + UBYTE ubA=UBYTE((colA&0xFF)*0.75f*fMipBlender); + COLOR colCombined=(col&0xFFFFFF00)|ubA; + //colCombined = C_WHITE|CT_OPAQUE; + Particle_RenderSquare( vPos, fFinalSize, fAngle, colCombined); + } + // all done + Particle_Flush(); +} + +#define BLOOD01_TRAIL_POSITIONS 15 +void Particles_BloodTrail(CEntity *pen) +{ + // get blood type + const INDEX iBloodType = GetSP()->sp_iBlood; + if( iBloodType<1) return; + COLOR col; + if( iBloodType==3) Particle_PrepareTexture( &_toFlowerSprayTexture, PBT_BLEND); + else Particle_PrepareTexture( &_toBloodSprayTexture, PBT_BLEND); + + CLastPositions *plp = pen->GetLastPositions(BLOOD01_TRAIL_POSITIONS); + FLOAT fGA = ((CMovableEntity *)pen)->en_fGravityA; + FLOAT3D vGDir = ((CMovableEntity *)pen)->en_vGravityDir; + + for( INDEX iPos=0; iPoslp_ctUsed; iPos++) + { + Particle_SetTexturePart( 256, 256, iPos%8, 0); + FLOAT3D vPos = plp->GetPosition(iPos); + FLOAT fRand = rand()/FLOAT(RAND_MAX); + FLOAT fAngle = iPos*2.0f*PI/BLOOD01_TRAIL_POSITIONS; + FLOAT fSin = FLOAT(sin(fAngle)); + FLOAT fT = iPos*_pTimer->TickQuantum; + vPos += vGDir*fGA*fT*fT/8.0f; + FLOAT fSize = 0.2f-iPos*0.15f/BLOOD01_TRAIL_POSITIONS; + UBYTE ub = 255-iPos*255/BLOOD01_TRAIL_POSITIONS; + if( iBloodType==3) col = C_WHITE|ub; + else if( iBloodType==2) col = RGBAToColor(ub,20,20,ub); + else col = RGBAToColor(0,ub,0,ub); + Particle_RenderSquare( vPos, fSize, fAngle, col); + } + // all done + Particle_Flush(); +} + + +INDEX Particles_FireBreath(CEntity *pen, FLOAT3D vSource, FLOAT3D vTarget, FLOAT tmStart, FLOAT tmStop) +{ + Particle_PrepareTexture( &_toFlamethrowerTrail01, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fFlameLife = 2; + INDEX ctFlames = 32; + INDEX ctRendered = 0; + FLOAT tmFlameDelta = 0.25f; + FLOAT3D vFocus = Lerp( vSource, vTarget, 0.25f); + for( INDEX iFlame=0; iFlamefFlameLife || tmFakeStart>tmStop) continue; + // calculate fraction part + FLOAT fT=fPassedTime/fFlameLife; + fT=fT-INDEX(fT); + // lerp position + FLOAT3D vRnd = FLOAT3D( afStarsPositions[iFlame][0],afStarsPositions[iFlame][1], + afStarsPositions[iFlame][2])*10; + FLOAT3D vPos = Lerp( vSource, vFocus+vRnd, fT); + FLOAT fSize = 5.0f*fT+5.0f; + UBYTE ub = CalculateRatio( fT, 0.0f, 1.0f, 0.1f, 0.2f)*255; + Particle_RenderSquare( vPos, fSize, fT*(1.0f+afStarsPositions[iFlame*3][1])*360.0f, RGBToColor(ub,ub,ub)|0xFF); + ctRendered++; + } + // all done + Particle_Flush(); + return ctRendered; +} + +INDEX Particles_Regeneration(CEntity *pen, FLOAT tmStart, FLOAT tmStop, FLOAT fYFactor, BOOL bDeath) +{ + Particle_PrepareTexture( &_toElectricitySparks, PBT_BLEND); + Particle_SetTexturePart( 512, 1024, 0, 0); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fLife = 1.5; + INDEX ctRendered = 0; + FLOAT tmDelta = 0.001f; + for( INDEX iVtx=0; iVtx<1024*4; iVtx++) + { + FLOAT tmFakeStart = tmStart+iVtx*tmDelta; + FLOAT fPassedTime = fNow-tmFakeStart; + if(fPassedTime<0.0f || fPassedTime>fLife || tmFakeStart>tmStop) continue; + // calculate fraction part + FLOAT fT=fPassedTime/fLife; + fT=fT-INDEX(fT); + + INDEX iRnd = iVtx%CT_MAX_PARTICLES_TABLE; + FLOAT3D vRnd= FLOAT3D(afStarsPositions[iRnd][0],afStarsPositions[iRnd][1]+0.5f,afStarsPositions[iRnd][2]); + vRnd(1) *= 800.0f; + vRnd(2) *= 400.0f; + vRnd(3) *= 800.0f; + FLOAT3D vSource = vCenter+vRnd; + FLOAT3D vDestination = vCenter+vRnd*0.05f; + vDestination(2) += 40.0f*fYFactor+vRnd(2)/8.0f*fYFactor; + FLOAT3D vPos, vPos2; + // lerp position + if(bDeath) { + vPos = Lerp( vSource, vDestination, 1.0f-fT); + } else { + vPos = Lerp( vSource, vDestination, fT); + } + FLOAT fT2 = Clamp(fT-0.025f-fT*fT*0.025f, 0.0f, 1.0f); + + if(bDeath) { + vPos2 = Lerp( vSource, vDestination, 1.0f-fT2); + } else { + vPos2 = Lerp( vSource, vDestination, fT2); + } + + UBYTE ubR = 192+afStarsPositions[iRnd][1]*64; + UBYTE ubG = 192+afStarsPositions[iRnd][2]*64; + UBYTE ubB = 192+afStarsPositions[iRnd][3]*64; + UBYTE ubA = CalculateRatio( fT, 0.0f, 1.0f, 0.4f, 0.01f)*255; + COLOR colLine = RGBToColor( ubR, ubG, ubB) | ubA; + + FLOAT fSize = 1.0f; + Particle_RenderLine( vPos2, vPos, fSize, colLine); + ctRendered++; + } + + // flush array + avVertices.PopAll(); + // all done + Particle_Flush(); + return ctRendered; +} + + +#define FLAME_LIFETIME 1.0f +#define FLAME_INTERTIME 0.1f +void Particles_FlameThrower(const CPlacement3D &plLeader, const CPlacement3D &plFollower, + FLOAT3D vSpeedLeader, FLOAT3D vSpeedFollower, + FLOAT fLeaderLiving, FLOAT fFollowerLiving, + INDEX iRndSeed, BOOL bFollowerIsPipe) +{ + INDEX flt_iFramesInRaw=4; + INDEX flt_iFramesInColumn=4; + INDEX flt_iInterpolations=10; + FLOAT flt_fSizeStart=0.075f; + FLOAT flt_fSizeEnd=6; + + //Particle_PrepareTexture( &_toFlamethrowerTrail02, PBT_ADDALPHA); + CTextureData *pTD = (CTextureData *) _toFlameThrowerGradient.GetData(); + + const FLOAT3D &vFollower = plFollower.pl_PositionVector; + const FLOAT3D &vLeader = plLeader.pl_PositionVector; + + // control points + FLOAT x1=vFollower(1); + FLOAT y1=vFollower(2); + FLOAT z1=vFollower(3); + FLOAT x2=vLeader(1); + FLOAT y2=vLeader(2); + FLOAT z2=vLeader(3); + + // control directions (tangents) + FLOAT dx1=vSpeedLeader(1); + FLOAT dy1=vSpeedLeader(2); + FLOAT dz1=vSpeedLeader(3); + FLOAT dx2=vSpeedLeader(1); + FLOAT dy2=vSpeedLeader(2); + FLOAT dz2=vSpeedLeader(3); + + // calculate parameters of hermit spline + FLOAT ft3x=dx1+dx2+2.0f*x1-2.0f*x2; + FLOAT ft2x=-2.0f*dx1-dx2-3.0*(x1-x2); + FLOAT ft1x=dx1; + FLOAT ft0x=x1; + FLOAT ft3y=dy1+dy2+2.0f*y1-2.0f*y2; + FLOAT ft2y=-2.0f*dy1-dy2-3.0*(y1-y2); + FLOAT ft1y=dy1; + FLOAT ft0y=y1; + FLOAT ft3z=dz1+dz2+2.0f*z1-2.0f*z2; + FLOAT ft2z=-2.0f*dz1-dz2-3.0*(z1-z2); + FLOAT ft1z=dz1; + FLOAT ft0z=z1; + + INDEX iParticle=0; + FLOAT fLiving=fLeaderLiving; + while(fLiving>=fFollowerLiving) + { + FLOAT fOlderThanLeaderTime=fLeaderLiving-fLiving; + + // set frame + INDEX iFrame=ClampUp(INDEX(fLiving*flt_iFramesInRaw*flt_iFramesInColumn), INDEX(flt_iFramesInRaw*flt_iFramesInColumn-1)); + INDEX iFrameX=iFrame%flt_iFramesInRaw; + INDEX iFrameY=iFrame/flt_iFramesInRaw; + //Particle_SetTexturePart( 1024/flt_iFramesInRaw, 1024/flt_iFramesInColumn, iFrameX, iFrameY); + + // calculate time exponents + FLOAT ft1=1.0f-fOlderThanLeaderTime/(fLeaderLiving-fFollowerLiving); + FLOAT ft2=ft1*ft1; + FLOAT ft3=ft1*ft1*ft1; + + // calculate particle position + FLOAT fx=ft3*ft3x+ft2*ft2x+ft1*ft1x+1*ft0x; + FLOAT fy=ft3*ft3y+ft2*ft2y+ft1*ft1y+1*ft0y; + FLOAT fz=ft3*ft3z+ft2*ft2z+ft1*ft1z+1*ft0z; + FLOAT3D vPos=FLOAT3D(fx,fy,fz); + + // add random position + INDEX iRnd=(iParticle+iRndSeed)%CT_MAX_PARTICLES_TABLE; + vPos(1) += afStarsPositions[iRnd][0]*fLiving; + vPos(2) += afStarsPositions[iRnd][1]*fLiving + fLiving*fLiving*fLiving*2.0f; + vPos(3) += afStarsPositions[iRnd][2]*fLiving; + + // size + FLOAT fSize = flt_fSizeStart+fLiving*(fLiving*0.4f+(flt_fSizeEnd-flt_fSizeStart)*0.6f); + // angle + FLOAT fAngle = fLiving*180.0f*afStarsPositions[iParticle][0]; + // color + COLOR col = pTD->GetTexel(PIX(Clamp(fLiving*1024.0f, 0.0f, 1023.0f)), 0); + + FlameThrowerParticleRenderingData &ftprd=_aftprdFlame[_ctFlameThrowerParticles+iParticle]; + ftprd.ftprd_iFrameX=iFrameX; + ftprd.ftprd_iFrameY=iFrameY; + ftprd.ftprd_vPos=vPos; + ftprd.ftprd_fSize=fSize; + ftprd.ftprd_fAngle=fAngle; + ftprd.ftprd_colColor=col; + +// Particle_RenderSquare( vPos, fSize, fAngle, col); + iParticle++; + fLiving-=FLAME_INTERTIME/flt_iInterpolations; + } + // all done +// Particle_Flush(); + _ctFlameThrowerParticles+=iParticle; +} + +#define CT_FTSPARKS 64 +#define CT_FTSPARK_TRAIL 1 +#define FTSPARK_FADE_OUT 0.005f +#define FTSPARK_TOTAL_TIME 0.2f +#define FT_START_SPEED 1.5f +void Particles_FlameThrowerStart(const CPlacement3D &plPipe, FLOAT fStartTime, FLOAT fStopTime) +{ + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture( &_toLavaTrailSmoke, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + CTextureData *pTD = (CTextureData *) _toFlameThrowerStartGradient.GetData(); + + FLOATmatrix3D m; + MakeRotationMatrixFast(m, plPipe.pl_OrientationAngle); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = plPipe.pl_PositionVector; + + FLOAT fPowerFactor = Clamp((fNow - fStartTime)/2.0f,0.0f,1.0f); + fPowerFactor *= Clamp(1+(fStopTime-fNow)/2.0f,0.0f,1.0f); + INDEX ctParticles = FLOAT(CT_FTSPARKS) * fPowerFactor; + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + FLOAT fHeight = 1.0f*fPowerFactor; + INDEX iParticle=0; + for( INDEX iSpark=0; iSparkfStopTime+2.0f) ) continue; + FLOAT fFade; + if (fT>(1.0f-FTSPARK_FADE_OUT)) fFade=(1-fT)*(1/FTSPARK_FADE_OUT); + else fFade=1.0f; + fFade *= (CT_FTSPARK_TRAIL-iTrail)*(1.0f/CT_FTSPARK_TRAIL); + + FLOAT3D vPos = vCenter + + vX*(afStarsPositions[iSpark][0]*0.15f*fT) + + vY*(afStarsPositions[iSpark][1]*0.15f*fT) + + -vZ*(FT_START_SPEED*fT); + + FLOAT fSize=(afStarsPositions[iSpark+16][0]+0.5f)*0.040f/*+fT*0.075f*/; + COLOR col = pTD->GetTexel(PIX(ClampUp(fT*1024.0f, 1023.0f)), 0); + FLOAT fAng=afStarsPositions[iSpark+8][0]*fT*360.0f; + + /* + FlameThrowerParticleRenderingData &ftprd=_aftprdFlame[_ctFlameThrowerPipeParticles+iParticle]; + ftprd.ftprd_vPos=vPos; + ftprd.ftprd_fSize=fSize; + ftprd.ftprd_fAngle=fAng; + ftprd.ftprd_colColor=col; + iParticle++; + */ + + Particle_RenderSquare( vPos, fSize, fAng, col); + } + } + //_ctFlameThrowerPipeParticles+=iParticle; + // all done + Particle_Flush(); +} + + +void Particles_ShooterFlame(const CPlacement3D &plEnd, const CPlacement3D &plStart, + FLOAT fEndElapsed, FLOAT fStartElapsed) +{ + Particle_PrepareTexture( &_toFlamethrowerTrail02, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + + const FLOAT3D &vStart = plStart.pl_PositionVector; + const FLOAT3D &vEnd = plEnd.pl_PositionVector; + +#define SHOOTER_INTERFLAME_PARTICLES 10 + + for (INDEX i=0; i1.0f) ub = 0.0f; + else if(fTime>0.6f) ub = (1.0-fTime)*(1.0/0.4)*255; + // color with a bit of red tint before the burnout + COLOR col = RGBToColor(192, 192, 192); + if (fTime>0.95f) col = RGBToColor(192, 0, 0); + else if (fTime>0.4) col = RGBToColor(192, (1.0-fTime)*(1.0/0.6)*100+92, (1.0-fTime)*(1.0/0.6)*112+80); + + vPos(1) += afStarsPositions[iRndFact][0]*fTime; + vPos(2) += afStarsPositions[iRndFact][1]*fTime + 0.25*fTime*fTime; + vPos(3) += afStarsPositions[iRndFact][2]*fTime; + + Particle_RenderSquare( vPos, fSize, fAngle, col|ub); + } + // all done + Particle_Flush(); +} + +#define STARDUST_EXIST_TIME 0.15f +void Particles_Stardust( CEntity *pen, FLOAT fSize, FLOAT fHeight, + enum ParticleTexture ptTexture, INDEX ctParticles) +{ + INDEX ctOffsetSpace = 128; + + ASSERT( (ctParticles+ctOffsetSpace)<=CT_MAX_PARTICLES_TABLE); + if( Particle_GetMipFactor()>7.0f) return; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + CPlacement3D plSource = pen->GetLerpedPlacement(); + FLOAT3D vCenter = plSource.pl_PositionVector+vY*fHeight; + + for( INDEX iStar=0; iStarSTARDUST_EXIST_TIME) continue; + FLOAT fFade = -2.0f * Abs(fT*(1.0f/STARDUST_EXIST_TIME)-0.5f)+1.0f; + + INDEX iRandomFromPlacement = + (ULONG)(plSource.pl_PositionVector(1)+plSource.pl_PositionVector(3))&(ctOffsetSpace-1); + INDEX iMemeber = iStar+iRandomFromPlacement; + const FLOAT3D vPos = vCenter+FLOAT3D( afStarsPositions[iMemeber][0], + afStarsPositions[iMemeber][1], + afStarsPositions[iMemeber][2])*fSize; + COLOR colStar = RGBToColor( auStarsColors[iMemeber][0]*fFade, + auStarsColors[iMemeber][1]*fFade, + auStarsColors[iMemeber][2]*fFade); + Particle_RenderSquare( vPos, 0.15f, 0, colStar|0xFF); + } + // all done + Particle_Flush(); +} + +#define RISING_TOTAL_TIME 5.0f +#define RISING_EXIST_TIME 3.0f +#define RISING_FADE_IN 0.3f +#define RISING_FADE_OUT 0.3f + +void Particles_Rising(CEntity *pen, FLOAT fStartTime, FLOAT fStopTime, FLOAT fStretchAll, + FLOAT fStretchX, FLOAT fStretchY, FLOAT fStretchZ, FLOAT fSize, + enum ParticleTexture ptTexture, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + if( Particle_GetMipFactor()>7.0f) return; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fStretchY; + + FLOAT fPowerFactor = Clamp((fNow - fStartTime)/5.0f,0.0f,1.0f); + fPowerFactor *= Clamp(1+(fStopTime-fNow)/5.0f,0.0f,1.0f); + //ctParticles = FLOAT(ctParticles) * fPowerFactor; + + for( INDEX iStar=0; iStar1) continue; + FLOAT fFade; + if(fF<(RISING_FADE_IN*fPowerFactor)) fFade=fF*(1/(RISING_FADE_IN*fPowerFactor)); + else if (fF>(1.0f-RISING_FADE_OUT)) fFade=(1-fF)*(1/RISING_FADE_OUT); + else fFade=1.0f; + + FLOAT3D vPos = vCenter+FLOAT3D( + afStarsPositions[iStar][0]*fStretchX, + afStarsPositions[iStar][1]*fStretchY, + afStarsPositions[iStar][2]*fStretchZ)*fStretchAll+vY*(fF*fStretchAll*0.5f); + vPos(1)+=sin(fF*4.0f)*0.05f*fStretchAll; + vPos(3)+=cos(fF*4.0f)*0.05f*fStretchAll; + + UBYTE ub = NormFloatToByte( fFade); + COLOR colStar = RGBToColor( ub, ub, ub>>1); + Particle_RenderSquare( vPos, fSize*fPowerFactor, 0, colStar|(UBYTE(0xFF*fPowerFactor))); + } + // all done + Particle_Flush(); +} + +#define CT_SPIRAL_PARTICLES 4 +#define CT_SPIRAL_TRAIL 10 +void Particles_Spiral( CEntity *pen, FLOAT fSize, FLOAT fHeight, + enum ParticleTexture ptTexture, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + + FLOAT fMipFactor = Particle_GetMipFactor(); + if( fMipFactor>7.0f) return; + fMipFactor = 2.5f-fMipFactor*0.3f; + fMipFactor = Clamp( fMipFactor, 0.0f, 1.0f); + INDEX ctSpiralTrail = fMipFactor*CT_SPIRAL_TRAIL; + if( ctSpiralTrail<=0) return; + FLOAT fTrailDelta = 0.1f/fMipFactor; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; + + for( INDEX iStar=0; iStar>1); + Particle_RenderSquare( vPos, 0.2f, 0, colStar|0xFF); + } + } + // all done + Particle_Flush(); +} + +#define EMANATE_FADE_IN 0.2f +#define EMANATE_FADE_OUT 0.6f +#define EMANATE_TOTAL_TIME 1.0f +#define EMANATE_EXIST_TIME 0.5f +void Particles_Emanate( CEntity *pen, FLOAT fSize, FLOAT fHeight, + enum ParticleTexture ptTexture, INDEX ctParticles, FLOAT fMipFactorDisappear) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + if( Particle_GetMipFactor()>fMipFactorDisappear) return; + FLOAT fDisappearRatio=CalculateRatio(Particle_GetMipFactor(), 0, fMipFactorDisappear, 0, 0.1f); + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; + + for( INDEX iStar=0; iStar1) continue; + FLOAT fFade; + if(fF(1.0f-EMANATE_FADE_OUT)) fFade=(1-fF)*(1/EMANATE_FADE_OUT); + else fFade=1.0f; + + FLOAT3D vPos = vCenter+FLOAT3D( + afStarsPositions[iStar][0], + afStarsPositions[iStar][1], + afStarsPositions[iStar][2])*fSize*(fF+0.4f); + + UBYTE ub = NormFloatToByte( fFade*fDisappearRatio); + COLOR colStar = RGBToColor( ub, ub, ub>>1); + Particle_RenderSquare( vPos, 0.1f, 0, colStar|0xFF); + } + // all done + Particle_Flush(); +} + +#define WATERFALL_FOAM_FADE_IN 0.1f +#define WATERFALL_FOAM_FADE_OUT 0.4f +void Particles_WaterfallFoam(CEntity *pen, FLOAT fSizeX, FLOAT fSizeY, FLOAT fSizeZ, + FLOAT fParticleSize, FLOAT fSpeed, FLOAT fSpeedY, FLOAT fLife, INDEX ctParticles) +{ + if(fLife<=0) return; + + Particle_PrepareTexture( &_toWaterfallFoam, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + for( INDEX iFoam=0; iFoamfMipFactorDisappear) return; + FLOAT fDisappearRatio=CalculateRatio(Particle_GetMipFactor(), 0, fMipFactorDisappear, 0, 0.1f); + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + for( INDEX iStar=0; iStar1) continue; + FLOAT fFade; + if(fF(1.0f-EMANATE_FADE_OUT)) fFade=(1-fF)*(1/EMANATE_FADE_OUT); + else fFade=1.0f; + + FLOAT fX = (afStarsPositions[iStar][0]+0.5f)*fSizeX*(1+fF*fAway); + FLOAT fY = fSizeY*fF; + FLOAT fZ = (afStarsPositions[iStar][2]+0.5f)*fSizeZ*(1+fF*fAway); + FLOAT3D vPos = vCenter + vX*fX + vY*fY + vZ*fZ; + + UBYTE ub = NormFloatToByte( fFade*fDisappearRatio); + COLOR colStar = RGBToColor( ub, ub, ub); + Particle_RenderSquare( vPos, fParticleSize, 0, colStar|0xFF); + } + // all done + Particle_Flush(); +} + +#define CT_FOUNTAIN_TRAIL 3 +#define FOUNTAIN_FADE_IN 0.6f +#define FOUNTAIN_FADE_OUT 0.4f +#define FOUNTAIN_TOTAL_TIME 0.6f +void Particles_Fountain( CEntity *pen, FLOAT fSize, FLOAT fHeight, + enum ParticleTexture ptTexture, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + SetupParticleTexture( ptTexture); + CTextureData *pTD = (CTextureData *) _toWaterfallGradient.GetData(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; + + for( INDEX iStar=0; iStar(1.0f-FOUNTAIN_FADE_OUT)) fFade=(1-fT)*(1/FOUNTAIN_FADE_OUT); + else fFade=1.0f; + fFade *= (CT_FOUNTAIN_TRAIL-iTrail)*(1.0f/CT_FOUNTAIN_TRAIL); + + FLOAT3D vPos = vCenter + + vX*(afStarsPositions[iStar][0]*fT*fSize) + + vY*(fT*fT*-5.0f+(afStarsPositions[iStar][1]*2+4.0f)*1.2f*fT) + + vZ*(afStarsPositions[iStar][2]*fT*fSize); + + COLOR colStar = pTD->GetTexel( FloatToInt(fFade*2048), 0); + ULONG ulA = FloatToInt( ((colStar&CT_AMASK)>>CT_ASHIFT) * fFade); + colStar = (colStar&~CT_AMASK) | (ulA<en_ulID)%CT_MAX_PARTICLES_TABLE; + Particle_SetTexturePart( 512, 512, iRnd1%3, 0); + + FLOAT fT = _pTimer->GetLerpedCurrentTick()-tmStarted; + FLOAT fBoxSize = boxOwner.Size().Length(); + for(INDEX iSmoke=0; iSmoke<2+fDamage*2; iSmoke++) + { + INDEX iRnd2 = INDEX(tmStarted*12345.0f+iSmoke+fDamage*10.0f)%(CT_MAX_PARTICLES_TABLE/2); + FLOAT fLifeTime = 2.0f+(afStarsPositions[iRnd2][0]+0.5f)*2.0f; + FLOAT fRatio = CalculateRatio(fT, 0, fLifeTime, 0.4f, 0.6f); + + FLOAT fRndAppearX = afStarsPositions[iRnd2][0]*fBoxSize*0.125f; + FLOAT fRndAppearZ = afStarsPositions[iRnd2][2]*fBoxSize*0.125f; + FLOAT3D vPos = pen->GetLerpedPlacement().pl_PositionVector; + vPos(1) += fRndAppearX; + vPos(3) += fRndAppearZ; + vPos(2) += ((afStarsPositions[iRnd2+4][1]+0.5f)*2.0f+1.5f)*fT+boxOwner.Size()(2)*0.0025f; + + COLOR col = C_dGRAY|UBYTE(64.0f*fRatio); + FLOAT fRotation = afStarsPositions[iRnd2+5][0]*360+fT*200.0f*afStarsPositions[iRnd2+3][0]; + FLOAT fSize = + 0.025f*fDamage+ + (afStarsPositions[iRnd2+6][2]+0.5f)*0.075 + + (0.15f+(afStarsPositions[iRnd2+2][1]+0.5f)*0.075f*fBoxSize)*fT; + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + + // all done + Particle_Flush(); +} + +#define RUNNING_DUST_TRAIL_POSITIONS 3*20 +void Particles_RunningDust_Prepare(CEntity *pen) +{ + pen->GetLastPositions(RUNNING_DUST_TRAIL_POSITIONS); +} +void Particles_RunningDust(CEntity *pen) +{ + Particle_PrepareTexture( &_toBulletSmoke, PBT_BLEND); + CLastPositions *plp = pen->GetLastPositions(RUNNING_DUST_TRAIL_POSITIONS); + FLOAT3D vOldPos = plp->GetPosition(1); + for(INDEX iPos = 2; iPoslp_ctUsed; iPos++) + { + FLOAT3D vPos = plp->GetPosition(iPos); + if( (vPos-vOldPos).Length()<1.0f) continue; + FLOAT tmStarted = _pTimer->CurrentTick()-iPos*_pTimer->TickQuantum; + INDEX iRnd = INDEX(Abs(vPos(1)*1234.234f+vPos(2)*9834.123f+vPos(3)*543.532f+pen->en_ulID))%(CT_MAX_PARTICLES_TABLE/2); + if( iRnd&3) continue; + + INDEX iRndTex = iRnd*324561+pen->en_ulID; + Particle_SetTexturePart( 512, 512, iRndTex%3, 0); + + FLOAT fLifeTime = 2.8f-(afStarsPositions[iRnd][1]+0.5f)*1.0f; + + FLOAT fT = _pTimer->GetLerpedCurrentTick()-tmStarted; + FLOAT fRatio = CalculateRatio(fT, 0, fLifeTime, 0.1f, 0.25f); + + FLOAT fRndAppearX = afStarsPositions[iRnd][0]*1.0f; + FLOAT fRndSpeedY = (afStarsPositions[iRnd][1]+0.5f)*0.5f; + FLOAT fRndAppearZ = afStarsPositions[iRnd][2]*1.0f; + vPos(1) += fRndAppearX; + vPos(2) += (0.5f+fRndSpeedY)*fT; + vPos(3) += fRndAppearZ; + + FLOAT fRndBlend = 8.0f+(afStarsPositions[iRnd*2][1]+0.5f)*64.0f; + UBYTE ubRndH = UBYTE( (afStarsPositions[iRnd][0]+0.5f)*64); + UBYTE ubRndS = UBYTE( (afStarsPositions[iRnd][1]+0.5f)*32); + UBYTE ubRndV = UBYTE( 128+afStarsPositions[iRnd][0]*64.0f); + COLOR col = HSVToColor(ubRndH,ubRndS,ubRndV)|UBYTE(fRndBlend*fRatio); + //col=C_RED|CT_OPAQUE; + FLOAT fRotation = afStarsPositions[iRnd+5][0]*360+fT*50.0f*afStarsPositions[iRnd+3][0]; + FLOAT fSize = + 0.75f+(afStarsPositions[iRnd+6][2]+0.5f)*0.25 + // static size + (0.4f+(afStarsPositions[iRnd+2][1]+0.5f)*0.4f)*fT; // dinamic size + Particle_RenderSquare( vPos, fSize, fRotation, col); + vOldPos=vPos; + } + // all done + Particle_Flush(); +} + +void Particles_DustFall(CEntity *pen, FLOAT tmStarted, FLOAT3D vStretch) +{ + FLOAT fMipFactor=Particle_GetMipFactor(); + fMipFactor=Clamp(fMipFactor,2.0f,6.0f); + FLOAT fSizeRatio=0.125f+(1.0f-CalculateRatio(fMipFactor, 2.0f, 6.0f, 0.0, 1.0f))*0.875f; + + Particle_PrepareTexture( &_toBulletSmoke, PBT_BLEND); + // get entity position and orientation + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + FLOAT3D vG=-vY; + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fT = _pTimer->GetLerpedCurrentTick()-tmStarted; + FLOAT fStretch=vStretch.Length(); + + INDEX ctParticles=4+fSizeRatio*28; + for(INDEX iDust=0; iDust<32; iDust++) + { + INDEX iRnd = (pen->en_ulID*12345+iDust)%CT_MAX_PARTICLES_TABLE; + Particle_SetTexturePart( 512, 512, iRnd%3, 0); + + FLOAT fLifeTime = 1.5f; + FLOAT fRatio = fT/fLifeTime; + if( fRatio>1.0f) continue; + FLOAT fPower = CalculateRatio(fT, 0, fLifeTime, 0.1f, 0.4f); + FLOAT fSpeed=0.351f+0.0506f*log(fRatio+0.001f); + + FLOAT fRndAppearX = afStarsPositions[iRnd][0]*vStretch(1); + FLOAT fRndSpeedY = (afStarsPositions[iRnd][1]+0.5f)*0.125f*vStretch(2); + FLOAT fRndAppearZ = afStarsPositions[iRnd][2]*vStretch(3); + FLOAT3D vRndDir=FLOAT3D(afStarsPositions[iRnd][1],0,afStarsPositions[iRnd][3]); + vRndDir.Normalize(); + FLOAT fRiseTime=Max(fRatio-0.5f,0.0f); + FLOAT3D vPos=vCenter+vRndDir*fSpeed*3*fStretch+vY*fRiseTime*0.25f; + FLOAT fRndBlend = 8.0f+(afStarsPositions[iRnd][2]+0.5f)*64.0f; + UBYTE ubRndH = UBYTE( (afStarsPositions[iRnd][0]+0.5f)*64); + UBYTE ubRndS = UBYTE( (afStarsPositions[iRnd][1]+0.5f)*32); + UBYTE ubRndV = UBYTE( 128+afStarsPositions[iRnd][2]*64.0f); + COLOR col = HSVToColor(ubRndH,ubRndS,ubRndV)|UBYTE(fRndBlend*fPower); + FLOAT fRotation = afStarsPositions[iRnd][0]*360+fT*360.0f*afStarsPositions[iRnd][0]*fSpeed; + FLOAT fSize = + 0.75f+(afStarsPositions[iRnd][2]+0.5f)*0.25 + // static size + (0.4f+(afStarsPositions[iRnd][1]+0.5f)*0.4f)*fT; // dinamic size + fSize*=fSizeRatio; + Particle_RenderSquare( vPos, fSize*fStretch*0.2f, fRotation, col); + } + // all done + Particle_Flush(); +} + +void Particles_MetalParts( CEntity *pen, FLOAT tmStarted, FLOATaabbox3D boxOwner, FLOAT fDamage) +{ + Particle_PrepareTexture( &_toMetalSprayTexture, PBT_BLEND); + FLOAT fT = _pTimer->GetLerpedCurrentTick()-tmStarted; + FLOAT fGA = 30.0f; + + FLOAT fBoxSize = boxOwner.Size().Length(); + for(INDEX iPart=0; iPart<6+fDamage*3.0f; iPart++) + { + INDEX iRnd = INDEX(tmStarted*12345.0f+iPart)%CT_MAX_PARTICLES_TABLE; + FLOAT fLifeTime = 2.0f+(afStarsPositions[iRnd][0]+0.5f)*2.0f; + FLOAT fRatio = CalculateRatio(fT, 0, fLifeTime, 0.1f, 0.1f); + Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iPart)%8, 0); + + FLOAT3D vPos = pen->GetLerpedPlacement().pl_PositionVector; + vPos(1) += afStarsPositions[iRnd][0]*fT*15; + vPos(2) += afStarsPositions[iRnd][1]*fT*15-fGA/2.0f*fT*fT+boxOwner.Size()(2)*0.25f; + vPos(3) += afStarsPositions[iRnd][2]*fT*15; + + UBYTE ubRndH = UBYTE( 180+afStarsPositions[ int(iPart+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = UBYTE( 12+(afStarsPositions[ int(iPart+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1])*8); + UBYTE ubRndV = UBYTE( 192+(afStarsPositions[ int(iPart+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); + //ubRndS = 0; + ubRndV = 255; + COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|UBYTE(255.0f*fRatio); + FLOAT fRotation = fT*400.0f*afStarsPositions[iRnd][0]; + FLOAT fSize = fBoxSize*0.005f+0.125f+afStarsPositions[iRnd][1]*0.025f; + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + + // all done + Particle_Flush(); +} + +#define ELECTRICITY_SPARKS_FADE_OUT_TIME 0.4f +#define ELECTRICITY_SPARKS_TOTAL_TIME 1.0f +void Particles_ElectricitySparks( CEntity *pen, FLOAT fTimeAppear, FLOAT fSize, FLOAT fHeight, INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE/2); + FLOAT fT = _pTimer->GetLerpedCurrentTick()-fTimeAppear; + + Particle_PrepareTexture( &_toElectricitySparks, PBT_BLEND); + Particle_SetTexturePart( 512, 1024, 0, 0); + + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; + + for( INDEX iSpark=0; iSparkELECTRICITY_SPARKS_TOTAL_TIME) + { + fFade=0; + } + else if(fT>ELECTRICITY_SPARKS_FADE_OUT_TIME) + { + fFade=-1.0f/(ELECTRICITY_SPARKS_TOTAL_TIME-ELECTRICITY_SPARKS_FADE_OUT_TIME)*(fT-ELECTRICITY_SPARKS_TOTAL_TIME); + } + else + { + fFade=1.0f; + } + + FLOAT fTold = fT-0.05f; + +#define SPARK_CURVE( time) \ + vCenter + \ + vX*(afStarsPositions[iSpark][0]*time*fSize*3) + \ + vY*(afStarsPositions[iSpark][1]*10.0f*time-(15.0f+afStarsPositions[iSpark*2][1]*15.0f)*time*time) + \ + vZ*(afStarsPositions[iSpark][2]*time*fSize*3); + + FLOAT3D vPosOld = SPARK_CURVE( fTold); + FLOAT3D vPosNew = SPARK_CURVE( fT); + + UBYTE ubR = 224+(afStarsPositions[iSpark][2]+0.5f)*32; + UBYTE ubG = 224+(afStarsPositions[iSpark][2]+0.5f)*32; + UBYTE ubB = 160; + UBYTE ubA = FloatToInt( 255 * fFade); + COLOR colStar = RGBToColor( ubR, ubG, ubB) | ubA; + Particle_RenderLine( vPosOld, vPosNew, 0.075f, colStar); + } + // all done + Particle_Flush(); +} + +void Particles_LavaErupting(CEntity *pen, FLOAT fStretchAll, FLOAT fSize, + FLOAT fStretchX, FLOAT fStretchY, FLOAT fStretchZ, + FLOAT fActivateTime) +{ + FLOAT fT = _pTimer->GetLerpedCurrentTick()-fActivateTime; + if( fT>10.0f) return; + + Particle_PrepareTexture( &_toLavaEruptingTexture, PBT_ADD); + INDEX iTexture = ((ULONG)fActivateTime)%3; + Particle_SetTexturePart( 512, 512, iTexture, 0); + FLOAT fGA = ((CMovableEntity *)pen)->en_fGravityA; + + INDEX iRnd1 = ((ULONG)fActivateTime)%CT_MAX_PARTICLES_TABLE; + INDEX iRnd2 = (~(ULONG)fActivateTime)%CT_MAX_PARTICLES_TABLE; + + FLOAT fRndAppearX = afStarsPositions[iRnd2][0]*fStretchAll; + FLOAT fRndAppearZ = afStarsPositions[iRnd2][1]*fStretchAll; + FLOAT fRndRotation = afStarsPositions[iRnd2][2]; + + FLOAT3D vPos = pen->GetLerpedPlacement().pl_PositionVector; + vPos(1) += fRndAppearX+afStarsPositions[iRnd1][0]*fT*fStretchX*10; + vPos(2) += (fStretchY+(fStretchY*0.25f*afStarsPositions[iRnd1][1]))*fT-fGA/2.0f*fT*fT; + vPos(3) += fRndAppearZ+afStarsPositions[iRnd1][2]*fT*fStretchZ*10; + + Particle_RenderSquare( vPos, fSize+afStarsPositions[iRnd2][3]*fSize*0.5f, fRndRotation*300*fT, C_WHITE|CT_OPAQUE); + + // all done + Particle_Flush(); +} + +#define CT_ATOMIC_TRAIL 32 +void Particles_Atomic( CEntity *pen, FLOAT fSize, FLOAT fHeight, + enum ParticleTexture ptTexture, INDEX ctEllipses) +{ + ASSERT( ctEllipses<=CT_MAX_PARTICLES_TABLE); + FLOAT fMipFactor = Particle_GetMipFactor(); + if( fMipFactor>7.0f) return; + fMipFactor = 2.5f-fMipFactor*0.3f; + fMipFactor = Clamp(fMipFactor, 0.0f ,1.0f); + INDEX ctAtomicTrail = fMipFactor*CT_ATOMIC_TRAIL; + if( ctAtomicTrail<=0) return; + FLOAT fTrailDelta = 0.075f/fMipFactor; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*fHeight; + + for( INDEX iEllipse=0; iEllipse>3, ub>>3, ub>>2); + Particle_RenderSquare( vPos, 0.2f, 0, colStar|0xFF); + } + } + // all done + Particle_Flush(); +} + +void Particles_PowerUpIndicator( CEntity *pen, enum ParticleTexture ptTexture, FLOAT fSize, + FLOAT fScale, FLOAT fHeight, INDEX ctEllipses, INDEX iTrailCount) +{ + ASSERT( ctEllipses<=CT_MAX_PARTICLES_TABLE); + FLOAT fMipFactor = Particle_GetMipFactor(); + if( fMipFactor>7.0f) return; + fMipFactor = 2.5f-fMipFactor*0.3f; + fMipFactor = Clamp(fMipFactor, 0.0f ,1.0f); + INDEX ctAtomicTrail = fMipFactor*iTrailCount; + if( ctAtomicTrail<=0) return; + FLOAT fTrailDelta = 0.075f/fMipFactor; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + SetupParticleTexture( ptTexture); + //const FLOATmatrix3D &m = pen->GetRotationMatrix(); + CPlacement3D pl = pen->GetLerpedPlacement(); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, pl.pl_OrientationAngle); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pl.pl_PositionVector+vY*fHeight; + + for( INDEX iEllipse=0; iEllipse0.5) { + vX = FLOAT3D(1.0f, 0.0f, 0.0f)*vZ; + } else { + vX = FLOAT3D(0.0f, 1.0f, 0.0f)*vZ; + } + FLOAT3D vY = vZ*vX; + const FLOAT fStep = fLen/fKneeDivider; + + for(INDEX iRay = 0; iRayGetLerpedCurrentTick()/1.5f; + FLOAT fDT = fT-INDEX(fT); + FLOAT fFade = 1-fDT*4.0f; + + if( fFade>1 || fFade<=0) continue; + UBYTE ubFade = NormFloatToByte(fFade*fPower); + COLOR colFade = RGBToColor( ubFade, ubFade, ubFade); + for(FLOAT fPos=fStep; fPosfDistanceToViewer - + ((CGrowth *)pvGrowth0)->fDistanceToViewer) * 1000; + return FloatToInt(ret); +} + +BOOL UpdateGrowthCache(CEntity *pen, CTextureData *ptdGrowthMap, FLOATaabbox3D &boxGrowthMap, CEntity *penEPH, INDEX iDrawPort) +{ + + // if there is no texture in EPH, return + CEnvironmentParticlesHolder *eph = (CEnvironmentParticlesHolder *)&*penEPH; + if (eph->m_moParticleTextureHolder.mo_toTexture.GetData() == NULL) { + return FALSE; + } + + // don't ever render in editor + if (_pTimer->CurrentTick()==0.0f) + { + return FALSE; + } + + // calculate step + extern FLOAT gfx_fEnvParticlesDensity; + gfx_fEnvParticlesDensity = Clamp(gfx_fEnvParticlesDensity, 0.0f, 1.0f); + FLOAT fStep = 1.0f; + if (gfx_fEnvParticlesDensity<=0) { + fStep = 0; + } else { + fStep = 1/gfx_fEnvParticlesDensity; + } + + FLOAT GROWTH_RENDERING_STEP = eph->m_fGrowthRenderingStep; + + // viewer absolute position + FLOAT3D vPos = prPlayerProjection->pr_vViewerPosition; + // snap viewer to grid + FLOAT3D vSnapped = vPos; + SnapFloat(vSnapped(1), GROWTH_RENDERING_STEP); + SnapFloat(vSnapped(3), GROWTH_RENDERING_STEP); + vSnapped(2) = 0.0f; + + PIX pixGrowthMapH; + PIX pixGrowthMapW; + + if( ptdGrowthMap != NULL) + { + pixGrowthMapW = ptdGrowthMap->GetPixWidth(); + pixGrowthMapH = ptdGrowthMap->GetPixHeight(); + } else { + return FALSE; + } + + FLOAT3D vRender; + FLOAT texX; + FLOAT texY; + FLOAT fRawHeight; + + FLOAT fRangeMod = Clamp(gfx_fEnvParticlesRange, 0.1f, 2.0f); + FLOAT GROWTH_RENDERING_RADIUS_OPAQUE = (eph->m_fGrowthRenderingRadius - eph->m_fGrowthRenderingRadiusFade)*fRangeMod; + FLOAT GROWTH_RENDERING_RADIUS_FADE = eph->m_fGrowthRenderingRadius*fRangeMod; + BOOL GROWTH_HIGHRES_MAP = eph->m_bGrowthHighresMap; + + ASSERT(GROWTH_RENDERING_RADIUS_FADE>=GROWTH_RENDERING_RADIUS_OPAQUE); + + FLOAT fGridStep; + ULONG fXSpan; + UBYTE ubFade=0xff; + + fGridStep = GROWTH_RENDERING_STEP; + fXSpan = 1234; + + INDEX iGridX1 = GROWTH_RENDERING_RADIUS_FADE/GROWTH_RENDERING_STEP; + INDEX iGridX0 = -iGridX1; + INDEX iGridY1 = iGridX1; + INDEX iGridY0 = -iGridX1; + + // find growth cache and check if it is initialised + CGrowthCache *cgc = NULL; + {FOREACHINLIST(CGrowthCache, cgc_Node, eph->lhCache, itCache) + if (itCache->ulID==iDrawPort) cgc = itCache; + } + // if no cache found, create one + if (cgc==NULL) + { + cgc = new(CGrowthCache); + cgc->ulID = iDrawPort; + cgc->iGridSide = iGridX1*2+1; + cgc->vLastPos = vSnapped; + eph->lhCache.AddTail(cgc->cgc_Node); + //CPrintF("added ph %s \n", eph->GetName()); + } else { + if (cgc->vLastPos==vSnapped && cgc->fStep==fStep) { + cgc->vLastPos = vSnapped; + return TRUE; + } + //CPrintF("need recashe! at %f\n", _pTimer->CurrentTick()); + cgc->vLastPos = vSnapped; + cgc->fStep = fStep; + } + + cgc->acgParticles.PopAll(); + CGrowth cgParticle; + + if (fStep<1) { + return TRUE; + } + + INDEX iOffI = FloatToInt(vSnapped(1)/GROWTH_RENDERING_STEP); + INDEX iOffJ = FloatToInt(vSnapped(3)/GROWTH_RENDERING_STEP); + + FLOAT fStepSqrt = Sqrt(fStep); + FLOAT f1oGridSizeX = 1.0f/boxGrowthMap.Size()(1); + FLOAT f1oGridSizeZ = 1.0f/boxGrowthMap.Size()(3); + FLOAT f1oGridStepX = 1.0f/(boxGrowthMap.Size()(1)/pixGrowthMapW); + FLOAT f1oGridStepZ = 1.0f/(boxGrowthMap.Size()(3)/pixGrowthMapH); + + // loop through the whole particle grid + for ( INDEX iC=iGridY0; iC=1 || fmodj>=1) { + continue; + } + + // absolute positions : + INDEX i = iC*GROWTH_RENDERING_STEP + vSnapped(1); + INDEX j = jC*GROWTH_RENDERING_STEP + vSnapped(3); + + + // apply a bit of randomness: + UBYTE ubRndFact = (i*fXSpan+j)%CT_MAX_PARTICLES_TABLE; + + FLOAT iR, jR; + iR = (FLOAT)i + fGridStep * afStarsPositions[ubRndFact][0]; + jR = (FLOAT)j + fGridStep * afStarsPositions[ubRndFact][2]; + + // size: + cgParticle.fSize = Lerp(eph->m_fGrowthMinSize, eph->m_fGrowthMaxSize, + afStarsPositions[ubRndFact][2]+0.5f); + + texX = (iR-boxGrowthMap.Min()(1))*f1oGridSizeX*pixGrowthMapW; + texY = (jR-boxGrowthMap.Min()(3))*f1oGridSizeZ*pixGrowthMapH; + + // particles that fall inside the boundaries + if ((texX>0) && (texX0) && (texY=pixGrowthMapW) ulX2=pixGrowthMapW-1; + ULONG ulY1 = FloatToInt(floorf(texY)); + ULONG ulY2 = FloatToInt(ceilf(texY)); // if (ulY2>=pixGrowthMapH) ulY2=pixGrowthMapH-1; + + SLONG ulUL, ulUR, ulBL, ulBR; + if (GROWTH_HIGHRES_MAP) + { + ulUL = (ptdGrowthMap->GetTexel(ulX1, ulY1)>>8)&0xFFFF; + ulUR = (ptdGrowthMap->GetTexel(ulX2, ulY1)>>8)&0xFFFF; + ulBL = (ptdGrowthMap->GetTexel(ulX1, ulY2)>>8)&0xFFFF; + ulBR = (ptdGrowthMap->GetTexel(ulX2, ulY2)>>8)&0xFFFF; + } + else + { + ulUL = (ptdGrowthMap->GetTexel(ulX1, ulY1)>>8)&0xFF; + ulUR = (ptdGrowthMap->GetTexel(ulX2, ulY1)>>8)&0xFF; + ulBL = (ptdGrowthMap->GetTexel(ulX1, ulY2)>>8)&0xFF; + ulBR = (ptdGrowthMap->GetTexel(ulX2, ulY2)>>8)&0xFF; + } + + // bilinear formula + FLOAT fDX = texX - ulX1; + FLOAT fDY = texY - ulY1; + fRawHeight = ulUL*(1-fDX)*(1-fDY) + + ulUR*(fDX - fDX*fDY) + + ulBL*(fDY - fDX*fDY) + + ulBR*(fDX*fDY); + + // calculate maximum slope per meter on each axis + FLOAT fSlopeMul = 1.0f; + if (GROWTH_HIGHRES_MAP) { + fSlopeMul = boxGrowthMap.Size()(2)/65535.0f; + } else { + fSlopeMul = boxGrowthMap.Size()(2)/255.0f; + } + FLOAT fSlopeX = Max(Abs(ulUL-ulUR), Abs(ulBL-ulBR))*fSlopeMul; + FLOAT fSlopeY = Max(Abs(ulUL-ulBL), Abs(ulUR-ulBR))*fSlopeMul; + //CPrintF("%g %g\n", fSlopeX, fSlopeY); + fSlopeX*=f1oGridStepX; + fSlopeY*=f1oGridStepZ; + + // clamp to terrain height + FLOAT fHeight; + if (GROWTH_HIGHRES_MAP) + { + fHeight = boxGrowthMap.Min()(2) + fRawHeight*boxGrowthMap.Size()(2)/65535.0f + cgParticle.fSize; + } + else + { + fHeight = boxGrowthMap.Min()(2) + fRawHeight*boxGrowthMap.Size()(2)/255.0f; + } + // apply sink factor + fHeight -= eph->m_fParticlesSinkFactor*cgParticle.fSize*2.0f; + // also sink by maximum slope + FLOAT fSlopeSink = Max(fSlopeX, fSlopeY); + if (fSlopeSink>1.5f) { + continue; // if too great slope, don't render it + } + fHeight -= cgParticle.fSize*fSlopeSink*0.75f; // don't sink too much + + cgParticle.vRender = FLOAT3D (iR, fHeight, jR); + + ULONG ulTmp = ptdGrowthMap->GetTexel(ulX1, ulY1); + ULONG ulType = (((ulTmp>>24)&0xFF)*(eph->m_iGrowthMapX*eph->m_iGrowthMapY))>>8; + cgParticle.iShapeX = ulType % eph->m_iGrowthMapX; + cgParticle.iShapeY = ulType / eph->m_iGrowthMapX; + + cgParticle.ubShade = (ulTmp)&0xFF; + + cgc->acgParticles.Push() = cgParticle; + // these particles are not visible + } else { + cgParticle.ubShade = 0; + cgc->acgParticles.Push() = cgParticle; + } + } + } + return TRUE; +} + +void Particles_Growth(CEntity *pen, CTextureData *ptdGrowthMap, FLOATaabbox3D &boxGrowthMap, CEntity *penEPH, INDEX iDrawPort) +{ + + if (!UpdateGrowthCache( pen, ptdGrowthMap, boxGrowthMap, penEPH, iDrawPort)) { + return; + } + + // obtain pointer to environment particles holder + CEnvironmentParticlesHolder *eph = (CEnvironmentParticlesHolder *)&*penEPH; + if (eph->m_moParticleTextureHolder.mo_toTexture.GetData() == NULL) { + return; + } + + // calculate viewer position + FLOAT3D vPos = prPlayerProjection->pr_vViewerPosition; + + FLOAT fRangeMod = Clamp(gfx_fEnvParticlesRange, 0.1f, 2.0f); + FLOAT GROWTH_RENDERING_RADIUS_FADE = eph->m_fGrowthRenderingRadius*fRangeMod; + FLOAT GROWTH_RENDERING_RADIUS_OPAQUE = (eph->m_fGrowthRenderingRadius - eph->m_fGrowthRenderingRadiusFade)*fRangeMod; + + // fill structures from cache + CGrowthCache *cgc = NULL; + {FOREACHINLIST(CGrowthCache, cgc_Node, eph->lhCache, itCache) + if (itCache->ulID==iDrawPort) cgc = itCache; + } + ASSERT(cgc!=NULL); + static CStaticStackArray acgDraw; + for ( INDEX i=0; iacgParticles.Count(); i++ ) + { + if (cgc->acgParticles[i].ubShade!=0) + { + CGrowth *cgParticle = &cgc->acgParticles[i]; + + // calculate distance to viewer by projecting the particle vector onto the viewers z + cgParticle->fDistanceToViewer = (vPos - cgParticle->vRender)%(prPlayerProjection->pr_ViewerRotationMatrix.GetRow(3)); + + // continue only with particles that are in front of the player + if (cgParticle->fDistanceToViewer>0.0f) { + // calculate fade value + FLOAT fFadeOutStrip = GROWTH_RENDERING_RADIUS_FADE - GROWTH_RENDERING_RADIUS_OPAQUE; + + UBYTE ubFade = (UBYTE)(((GROWTH_RENDERING_RADIUS_FADE - cgParticle->fDistanceToViewer) / fFadeOutStrip)*255.0f); + if ( cgParticle->fDistanceToViewer < GROWTH_RENDERING_RADIUS_OPAQUE) { + cgParticle->ubFade = 255; + acgDraw.Push() = *cgParticle; + } + else if ( cgParticle->fDistanceToViewer < GROWTH_RENDERING_RADIUS_FADE) { + cgParticle->ubFade = (UBYTE)(((GROWTH_RENDERING_RADIUS_FADE - cgParticle->fDistanceToViewer) / fFadeOutStrip)*255.0f); + acgDraw.Push() = *cgParticle; + } + } + } + } + + if (acgDraw.Count()<=0) + { + return; + } + // sort particles from the farthest to the nearest + qsort(&acgDraw[0], acgDraw.sa_UsedCount, sizeof(CGrowth), qsort_CompareGrowth); + + // render particles + Particle_PrepareTexture( &(eph->m_moParticleTextureHolder.mo_toTexture), PBT_BLEND); + for(INDEX p=0; pm_moParticleTextureHolder.mo_toTexture.GetWidth() / eph->m_iGrowthMapX; + INDEX iMapTileSizeY = eph->m_moParticleTextureHolder.mo_toTexture.GetHeight() / eph->m_iGrowthMapY; + COLOR col = RGBToColor(acgDraw[p].ubShade, acgDraw[p].ubShade, acgDraw[p].ubShade)|acgDraw[p].ubFade; + Particle_SetTexturePart( iMapTileSizeX, iMapTileSizeY, acgDraw[p].iShapeX, acgDraw[p].iShapeY); + /* + Particle_RenderLine( acgDraw[p].vRender+FLOAT3D(0,acgDraw[p].fSize*2.0f,0), acgDraw[p].vRender, + acgDraw[p].fSize, col); + */ + //Particle_RenderSquare( acgDraw[p].vRender, acgDraw[p].fSize, 0, col); + + // radius + FLOAT fR=acgDraw[p].fSize; + /* + FLOAT fRndA=afStarsPositions[INDEX(acgDraw[p].vRender(1)*12345.65432)%CT_MAX_PARTICLES_TABLE][0]*360.0f; + FLOAT fdx=fR*SinFast(fRndA); + FLOAT fdz=fR*CosFast(fRndA); + + FLOAT3D v0=acgDraw[p].vRender+FLOAT3D(-fdx,fR,-fdz); + FLOAT3D v1=acgDraw[p].vRender+FLOAT3D(-fdx,-fR,-fdz); + FLOAT3D v2=acgDraw[p].vRender+FLOAT3D(fdx,-fR,fdz); + FLOAT3D v3=acgDraw[p].vRender+FLOAT3D(fdx,fR,fdz); + Particle_RenderQuad3D(v0, v1, v2, v3, col); + */ + + // along x + FLOAT3D v0=acgDraw[p].vRender+FLOAT3D(-fR,fR,0); + FLOAT3D v1=acgDraw[p].vRender+FLOAT3D(-fR,-fR,0); + FLOAT3D v2=acgDraw[p].vRender+FLOAT3D(fR,-fR,0); + FLOAT3D v3=acgDraw[p].vRender+FLOAT3D(fR,fR,0); + Particle_RenderQuad3D(v0, v1, v2, v3, col); + + // along y + v0=acgDraw[p].vRender+FLOAT3D(0,fR,-fR); + v1=acgDraw[p].vRender+FLOAT3D(0,-fR,-fR); + v2=acgDraw[p].vRender+FLOAT3D(0,-fR,fR); + v3=acgDraw[p].vRender+FLOAT3D(0,fR,fR); + Particle_RenderQuad3D(v0, v1, v2, v3, col); + } + Particle_Flush(); + acgDraw.PopAll(); +} + +/*void Particles_Growth123(CEntity *pen, CTextureData *ptdGrowthMap, FLOATaabbox3D &boxGrowthMap, CEntity *penEPH, INDEX dummy) +{ + + CEnvironmentParticlesHolder *eph = (CEnvironmentParticlesHolder *)&*penEPH; + + if (eph->m_moParticleTextureHolder.mo_toTexture.GetData() == NULL) { + return; + } + + FLOAT3D vPos = prPlayerProjection->pr_vViewerPosition; + + PIX pixGrowthMapH; + PIX pixGrowthMapW; + + if( ptdGrowthMap != NULL) + { + pixGrowthMapW = ptdGrowthMap->GetPixWidth(); + pixGrowthMapH = ptdGrowthMap->GetPixHeight(); + } else { + return; + } + + FLOAT3D vRender; + FLOAT texX; + FLOAT texY; + FLOAT fRawHeight; + + FLOAT GROWTH_RENDERING_STEP = eph->m_fGrowthRenderingStep; + FLOAT GROWTH_RENDERING_RADIUS_OPAQUE = eph->m_fGrowthRenderingRadius - eph->m_fGrowthRenderingRadiusFade; + FLOAT GROWTH_RENDERING_RADIUS_FADE = eph->m_fGrowthRenderingRadius; + BOOL GROWTH_HIGHRES_MAP = eph->m_bGrowthHighresMap; + + ASSERT(GROWTH_RENDERING_RADIUS_FADE>=GROWTH_RENDERING_RADIUS_OPAQUE); + + FLOAT fGridStep; + ULONG fXSpan; + UBYTE ubFade=0xff; + + fGridStep = GROWTH_RENDERING_STEP; + fXSpan = 1234; + + INDEX iGridX1 = GROWTH_RENDERING_RADIUS_FADE/GROWTH_RENDERING_STEP; + INDEX iGridX0 = -iGridX1; + INDEX iGridY1 = iGridX1; + INDEX iGridY0 = -iGridX1; + + static CStaticStackArray acgParticles; + CGrowth cgParticle; + + // snap viewer to grid + FLOAT3D vSnapped = vPos; + SnapFloat(vSnapped(1), GROWTH_RENDERING_STEP); + SnapFloat(vSnapped(3), GROWTH_RENDERING_STEP); + + // loop through the whole particle grid + for ( INDEX iC=iGridY0; iCm_fGrowthMinSize, eph->m_fGrowthMaxSize, + afStarsPositions[ubRndFact][2]+0.5f); + + texX = (iR-boxGrowthMap.Min()(1))/boxGrowthMap.Size()(1)*pixGrowthMapW; + texY = (jR-boxGrowthMap.Min()(3))/boxGrowthMap.Size()(3)*pixGrowthMapH; + + // particles that fall inside the boundaries + if ((texX>0) && (texX0) && (texY=pixGrowthMapW) ulX2=pixGrowthMapW-1; + ULONG ulY1 = (ULONG) texY; if (ulY1<0) ulY1=0; + ULONG ulY2 = (ULONG) ceilf(texY); if (ulY2>=pixGrowthMapH) ulY2=pixGrowthMapH-1; + + ULONG ulUL, ulUR, ulBL, ulBR; + if (GROWTH_HIGHRES_MAP) + { + ulUL = (ptdGrowthMap->GetTexel(ulX1, ulY1)>>8)&0xFFFF; + ulUR = (ptdGrowthMap->GetTexel(ulX2, ulY1)>>8)&0xFFFF; + ulBL = (ptdGrowthMap->GetTexel(ulX1, ulY2)>>8)&0xFFFF; + ulBR = (ptdGrowthMap->GetTexel(ulX2, ulY2)>>8)&0xFFFF; + } + else + { + ulUL = (ptdGrowthMap->GetTexel(ulX1, ulY1)>>8)&0xFF; + ulUR = (ptdGrowthMap->GetTexel(ulX2, ulY1)>>8)&0xFF; + ulBL = (ptdGrowthMap->GetTexel(ulX1, ulY2)>>8)&0xFF; + ulBR = (ptdGrowthMap->GetTexel(ulX2, ulY2)>>8)&0xFF; + } + + // bilinear formula + FLOAT fDX = texX - ulX1; + FLOAT fDY = texY - ulY1; + fRawHeight = ulUL*(1-fDX)*(1-fDY) + + ulUR*(fDX - fDX*fDY) + + ulBL*(fDY - fDX*fDY) + + ulBR*(fDX*fDY); + + // clamp to terrain height + FLOAT fHeight; + if (GROWTH_HIGHRES_MAP) + { + fHeight = boxGrowthMap.Min()(2) + fRawHeight*boxGrowthMap.Size()(2)/65535.0f + cgParticle.fSize; + } + else + { + fHeight = boxGrowthMap.Min()(2) + fRawHeight*boxGrowthMap.Size()(2)/255.0f; + } + // apply sink factor + fHeight -= eph->m_fParticlesSinkFactor*cgParticle.fSize*2.0f; + + cgParticle.vRender = FLOAT3D (iR, fHeight, jR); + + ULONG ulTmp = ptdGrowthMap->GetTexel(ulX1, ulY1); + ULONG ulType = (((ulTmp>>24)&0xFF)*(eph->m_iGrowthMapX*eph->m_iGrowthMapY))/255; + + cgParticle.iShapeX = ulType % eph->m_iGrowthMapX; + cgParticle.iShapeY = ulType / eph->m_iGrowthMapY; + + cgParticle.ubShade = (ulTmp)&0xFF; + + // skip particles that are totaly black - used to make areas with + // no particles on the height map + if( cgParticle.ubShade==0) { + continue; + } + + // calculate distance to viewer by projecting the particle vector onto the viewers z + cgParticle.fDistanceToViewer = (vPos - cgParticle.vRender)%(prPlayerProjection->pr_ViewerRotationMatrix.GetRow(3)); + + // continue only with particles that are in front of the player + if (cgParticle.fDistanceToViewer>0.0f) { + // calculate fade value + FLOAT fFadeOutStrip = GROWTH_RENDERING_RADIUS_FADE - GROWTH_RENDERING_RADIUS_OPAQUE; + + cgParticle.ubFade = (UBYTE)(((GROWTH_RENDERING_RADIUS_FADE - cgParticle.fDistanceToViewer) / fFadeOutStrip)*255.0f); + if ( cgParticle.fDistanceToViewer < GROWTH_RENDERING_RADIUS_OPAQUE) { + cgParticle.ubFade = 255; + acgParticles.Push() = cgParticle; + //acgParticlesSolid.Push() = cgParticle; + } + else if ( cgParticle.fDistanceToViewer < GROWTH_RENDERING_RADIUS_FADE) { + cgParticle.ubFade = (UBYTE)(((GROWTH_RENDERING_RADIUS_FADE - cgParticle.fDistanceToViewer) / fFadeOutStrip)*255.0f); + acgParticles.Push() = cgParticle; + //acgParticlesFading.Push() = cgParticle; + } + } + } + } + } + + // if no particles to render (at the edge of the visible box?) + //if (acgParticlesFading.sa_UsedCount<=0 && acgParticlesSolid.sa_UsedCount<=0) return; + if (acgParticles.sa_UsedCount<=0) return; + + // sort fading particles + //qsort(&acgParticlesFading[0], acgParticlesFading.sa_UsedCount, sizeof(CGrowth), qsort_CompareGrowth); + qsort(&acgParticles[0], acgParticles.sa_UsedCount, sizeof(CGrowth), qsort_CompareGrowth); + + // render particles + Particle_PrepareTexture( &(eph->m_moParticleTextureHolder.mo_toTexture), PBT_BLEND); + for(INDEX p=0; pm_moParticleTextureHolder.mo_toTexture.GetWidth() / eph->m_iGrowthMapX; + INDEX iMapTileSizeY = eph->m_moParticleTextureHolder.mo_toTexture.GetHeight() / eph->m_iGrowthMapY; + COLOR col = RGBToColor(acgParticles[p].ubShade, acgParticles[p].ubShade, acgParticles[p].ubShade)|acgParticles[p].ubFade; + Particle_SetTexturePart( iMapTileSizeX, iMapTileSizeY, acgParticles[p].iShapeX, acgParticles[p].iShapeY); + Particle_RenderSquare( acgParticles[p].vRender, acgParticles[p].fSize, 0, col); + } + Particle_Flush(); + + // all done + //acgParticlesFading.PopAll(); + //acgParticlesSolid.PopAll(); + acgParticles.PopAll(); +}*/ + + +#define RAIN_SOURCE_HEIGHT 16.0f +#define RAIN_SPEED 16.0f +#define RAIN_DROP_TIME (RAIN_SOURCE_HEIGHT/RAIN_SPEED) + +void Particles_Rain(CEntity *pen, FLOAT fGridSize, INDEX ctGrids, FLOAT fFactor, + CTextureData *ptdRainMap, FLOATaabbox3D &boxRainMap) +{ + FLOAT3D vPos = pen->GetLerpedPlacement().pl_PositionVector; + + vPos(1) -= fGridSize*ctGrids/2; + vPos(3) -= fGridSize*ctGrids/2; + + SnapFloat( vPos(1), fGridSize); + SnapFloat( vPos(2), fGridSize); + SnapFloat( vPos(3), fGridSize); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toRaindrop, PBT_BLEND); + Particle_SetTexturePart( 512, 4096, 0, 0); + + FLOAT fMinX = boxRainMap.Min()(1); + FLOAT fMinY = boxRainMap.Min()(2); + FLOAT fMinZ = boxRainMap.Min()(3); + FLOAT fSizeX = boxRainMap.Size()(1); + FLOAT fSizeY = boxRainMap.Size()(2); + FLOAT fSizeZ = boxRainMap.Size()(3); + PIX pixRainMapW = 1; + PIX pixRainMapH = 1; + + if( ptdRainMap != NULL) + { + pixRainMapW = ptdRainMap->GetPixWidth(); + pixRainMapH = ptdRainMap->GetPixHeight(); + } + + for( INDEX iZ=0; iZ=0 && pixX=0 && pixZGetTexel( pixX, pixZ); + FLOAT fRainMapY = fMinY+((col>>8)&0xFF)/255.0f*fSizeY; + + FLOAT fRainY = vRender(2); + // if tested raindrop is below ceiling + if( fRainY<=fRainMapY) + { + // don't render it + continue; + } else if (fRainY-fSizeGetLerpedPlacement().pl_PositionVector; + + vPos(1) -= fGridSize*ctGrids/2; + vPos(3) -= fGridSize*ctGrids/2; + + SnapFloat( vPos(1), fGridSize); + SnapFloat( vPos(2), YGRID_SIZE); + SnapFloat( vPos(3), fGridSize); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT tmSnowFalling=fNow-fSnowStart; + FLOAT fFlakePath=SNOW_SPEED*tmSnowFalling; + FLOAT fFlakeStartPos=vPos(2)-fFlakePath; + FLOAT fSnapFlakeStartPos=fFlakeStartPos; + SnapFloat(fSnapFlakeStartPos, YGRID_SIZE); + INDEX iRndFlakeStart=INDEX(fSnapFlakeStartPos)%CT_MAX_PARTICLES_TABLE; + FLOAT tmSnapSnowFalling = tmSnowFalling; + SnapFloat( tmSnapSnowFalling, SNOW_TILE_DROP_TIME); + FLOAT fTileRatio = (tmSnowFalling-tmSnapSnowFalling)/SNOW_TILE_DROP_TIME; + + Particle_PrepareTexture(&_toSnowdrop, PBT_BLEND); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT fMinX = boxSnowMap.Min()(1); + FLOAT fMinY = boxSnowMap.Min()(2); + FLOAT fMinZ = boxSnowMap.Min()(3); + FLOAT fSizeX = boxSnowMap.Size()(1); + FLOAT fSizeY = boxSnowMap.Size()(2); + FLOAT fSizeZ = boxSnowMap.Size()(3); + PIX pixSnowMapW = 1; + PIX pixSnowMapH = 1; + + if( ptdSnowMap != NULL) + { + pixSnowMapW = ptdSnowMap->GetPixWidth(); + pixSnowMapH = ptdSnowMap->GetPixHeight(); + } + + for( INDEX iZ=0; iZ=0 && pixX=0 && pixZGetTexel( pixX, pixZ); + FLOAT fRawHeight=(col>>8)&0xFFFF; + FLOAT fSnowMapY = fMinY+fRawHeight*fSizeY/65535.0f; + FLOAT fSnowY = vRender(2); + // if tested raindrop is below ceiling + if( fSnowY<=fSnowMapY) + { + // don't render it + continue; + } else if (fSnowY-fSize0.5) + { + vX = FLOAT3D(1.0f, 0.0f, 0.0f)*vZ; + } + else + { + vX = FLOAT3D(0.0f, 1.0f, 0.0f)*vZ; + } + // we found ortonormal vectors + FLOAT3D vY = vZ*vX; + + FLOAT fAllowRnd = 4.0f/fRandomDivider; + fRandomDivider+=1.0f; + vRenderDest = vSrc+ + vZ*fKneeLen + + vX*(fAllowRnd*afStarsPositions[iRnd][0]*fKneeLen) + + vY*(fAllowRnd*afStarsPositions[iRnd][1]*fKneeLen); + // get new rnd index + iRnd = (iRnd+1) % CT_MAX_PARTICLES_TABLE; + // see if we will spawn new branch of lightning + FLOAT fRnd = ((1-ctBranches/ctMaxBranches)*ctKnees)*afStarsPositions[iRnd][0]; + if( (fRnd < 2.0f) && (fPower>0.25f) ) + { + ctBranches++; + FLOAT3D vNewDirection = (vRenderDest-vSrc).Normalize(); + FLOAT3D vNewDst = vSrc + vNewDirection*fLen; + // recurse into new branch + RenderOneLightningBranch( vSrc, vNewDst, fPath, fTimeStart, fTimeNow, fPower/3.0f, iRnd); + } + } + + // calculate color + UBYTE ubA = UBYTE(fPower*255*fTimeKiller); + // render line + Particle_RenderLine( vSrc, vRenderDest, fPower*2, C_WHITE|ubA); + // add traveled path + fPath += (vRenderDest-vSrc).Length(); + if( fPath/LIGHTNING_SPEED > fPassedTime) + { + bRenderInProgress = FALSE; + } + vSrc = vRenderDest; + } +} + +void Particles_Lightning( FLOAT3D vSrc, FLOAT3D vDst, FLOAT fTimeStart) +{ + Particle_PrepareTexture(&_toLightning, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT fTimeNow = _pTimer->GetLerpedCurrentTick(); + // get rnd index + INDEX iRnd = (INDEX( fTimeStart*100))%CT_MAX_PARTICLES_TABLE; + RenderOneLightningBranch( vSrc, vDst, 0, fTimeStart, fTimeNow, 1.0f, iRnd); + + // all done + Particle_Flush(); +} + +#define CT_SANDFLOW_TRAIL 3 +#define SANDFLOW_FADE_OUT 0.25f +#define SANDFLOW_TOTAL_TIME 1.0f +void Particles_SandFlow( CEntity *pen, FLOAT fStretchAll, FLOAT fSize, FLOAT fHeight, FLOAT fStartTime, FLOAT fStopTime, + INDEX ctParticles) +{ + ASSERT( ctParticles<=CT_MAX_PARTICLES_TABLE); + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + SetupParticleTexture( PT_SANDFLOW); + CTextureData *pTD = (CTextureData *) _toSandFlowGradient.GetData(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + FLOAT fPowerFactor = Clamp((fNow - fStartTime)/2.0f,0.0f,1.0f); + fPowerFactor *= Clamp(1+(fStopTime-fNow)/2.0f,0.0f,1.0f); + ctParticles = FLOAT(ctParticles) * fPowerFactor; + fHeight *= fPowerFactor; + for( INDEX iStar=0; iStarfStopTime+2.0f) ) continue; + FLOAT fFade; + if (fT>(1.0f-SANDFLOW_FADE_OUT)) fFade=(1-fT)*(1/SANDFLOW_FADE_OUT); + else fFade=1.0f; + fFade *= (CT_SANDFLOW_TRAIL-iTrail)*(1.0f/CT_SANDFLOW_TRAIL); + + FLOAT3D vPos = vCenter + + vX*(afStarsPositions[iStar][0]*fStretchAll*fPowerFactor+fHeight*fT) + + vY*(fT*fT*-5.0f+(afStarsPositions[iStar][1]*fPowerFactor*0.1)) + + vZ*(afStarsPositions[iStar][2]*fPowerFactor*fT*fStretchAll); + + COLOR colSand = pTD->GetTexel( FloatToInt(fT*2048), 0); + ULONG ulA = FloatToInt( ((colSand&CT_AMASK)>>CT_ASHIFT) * fFade); + colSand = (colSand&~CT_AMASK) | (ulA<GetLerpedCurrentTick(); + + SetupParticleTexture( PT_WATERFLOW); + CTextureData *pTD = (CTextureData *) _toWaterFlowGradient.GetData(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + FLOAT fPowerFactor = Clamp((fNow - fStartTime)/2.0f,0.0f,1.0f); + fPowerFactor *= Clamp(1+(fStopTime-fNow)/2.0f,0.0f,1.0f); + ctParticles = FLOAT(ctParticles) * fPowerFactor; + fHeight *= fPowerFactor; + for( INDEX iStar=0; iStarfStopTime+2.0f) ) continue; + FLOAT fFade; + if (fT>(1.0f-WATER_FLOW_FADE_OUT)) fFade=(1-fT)*(1/WATER_FLOW_FADE_OUT); + else fFade=1.0f; + fFade *= (CT_WATER_FLOW_TRAIL-iTrail)*(1.0f/CT_WATER_FLOW_TRAIL); + + FLOAT3D vPos = vCenter + + vX*(afStarsPositions[iStar][0]*fStretchAll*fPowerFactor+fHeight*fT) + + vY*(fT*fT*-5.0f+(afStarsPositions[iStar][1]*fPowerFactor*0.1)) + + vZ*(afStarsPositions[iStar][2]*fPowerFactor*fT*fStretchAll); + + COLOR colWater = pTD->GetTexel( FloatToInt(fT*2048), 0); + ULONG ulA = FloatToInt( ((colWater&CT_AMASK)>>CT_ASHIFT) * fFade); + colWater = (colWater&~CT_AMASK) | (ulA<GetLerpedCurrentTick(); + + SetupParticleTexture( PT_LAVAFLOW); + CTextureData *pTD = (CTextureData *) _toLavaFlowGradient.GetData(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + FLOAT fPowerFactor = Clamp((fNow - fStartTime)/2.0f,0.0f,1.0f); + fPowerFactor *= Clamp(1+(fStopTime-fNow)/2.0f,0.0f,1.0f); + ctParticles = FLOAT(ctParticles) * fPowerFactor; + fHeight *= fPowerFactor; + for( INDEX iStar=0; iStarfStopTime+2.0f) ) continue; + FLOAT fFade; + if (fT>(1.0f-LAVA_FLOW_FADE_OUT)) fFade=(1-fT)*(1/LAVA_FLOW_FADE_OUT); + else fFade=1.0f; + fFade *= (CT_LAVA_FLOW_TRAIL-iTrail)*(1.0f/CT_LAVA_FLOW_TRAIL); + + FLOAT3D vPos = vCenter + + vX*(afStarsPositions[iStar][0]*fStretchAll*fPowerFactor+fHeight*fT) + + vY*(fT*fT*-4.0f+(afStarsPositions[iStar][1]*fPowerFactor*0.1)) + + vZ*(afStarsPositions[iStar][2]*fPowerFactor*fT*fStretchAll); + + COLOR colLava = pTD->GetTexel( ClampUp(FloatToInt(fT*2048),2047L), 0); + ULONG ulA = FloatToInt( ((colLava&CT_AMASK)>>CT_ASHIFT) * fFade); + colLava = (colLava&~CT_AMASK) | (ulA<8.0f) return; + if( fMipFactor>6.0f) + { + fDisappear = 1.0f-(fMipFactor-6.0f)/2.0f; + } + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fT=(fNow-tmSpawn); + if( fT>fLifeTotal) return; + INDEX iRnd = INDEX( (tmSpawn*1000.0f)+iRndBase) &63; + FLOAT fSizeStart; + FLOAT fSpeedStart; + FLOAT fConeMultiplier = 1.0f; + COLOR colSmoke; + + switch( eptType) + { + case EPT_BULLET_WATER: + { + Particle_PrepareTexture(&_toBulletWater, PBT_BLEND); + fSizeStart = 0.08f; + fSpeedStart = 1.75f; + fConeMultiplier = 0.125f; + + FLOAT fFadeStart = BULLET_SPRAY_WATER_FADEOUT_START; + FLOAT fLifeTotal = BULLET_SPRAY_WATER_TOTAL_TIME; + FLOAT fFadeLen = fLifeTotal-fFadeStart; + + break; + } + case EPT_BULLET_SAND: + { + colSmoke = 0xFFE8C000; + Particle_PrepareTexture(&_toBulletSand, PBT_BLEND); + fSizeStart = 0.15f; + fSpeedStart = 0.75f; + break; + } + case EPT_BULLET_RED_SAND: + { + colSmoke = 0xA0402000; + colStones = 0x80503000; + Particle_PrepareTexture(&_toBulletSand, PBT_BLEND); + fSizeStart = 0.15f; + fSpeedStart = 0.75f; + break; + } + case EPT_BULLET_GRASS: + { + colSmoke = 0xFFE8C000; + Particle_PrepareTexture(&_toBulletGrass, PBT_BLEND); + fSizeStart = 0.15f; + fSpeedStart = 1.75f; + break; + } + case EPT_BULLET_WOOD: + { + colSmoke = 0xFFE8C000; + Particle_PrepareTexture(&_toBulletWood, PBT_BLEND); + fSizeStart = 0.15f; + fSpeedStart = 1.25f; + break; + } + case EPT_BULLET_SNOW: + { + colSmoke = 0xFFE8C000; + Particle_PrepareTexture(&_toBulletSnow, PBT_BLEND); + fSizeStart = 0.15f; + fSpeedStart = 1.25f; + break; + } + default: + { + colSmoke = C_WHITE; + Particle_PrepareTexture(&_toBulletStone, PBT_BLEND); + fSizeStart = 0.05f; + fSpeedStart = 1.5f; + } + } + + FLOAT fGA = 10.0f; + + // render particles + for( INDEX iSpray=0; iSpray<12*fDisappear; iSpray++) + { + Particle_SetTexturePart( 512, 512, iSpray&3, 0); + + FLOAT3D vRandomAngle = FLOAT3D( + afStarsPositions[ iSpray+iRnd][0]*3.0f* fConeMultiplier, + (afStarsPositions[ iSpray+iRnd][1]+1.0f)*3.0f, + afStarsPositions[ iSpray+iRnd][2]*3.0f* fConeMultiplier); + FLOAT fSpeedRnd = fSpeedStart+afStarsPositions[ iSpray+iRnd*2][3]; + FLOAT3D vPos = vSource + (vDirection+vRandomAngle)*(fT*fSpeedRnd)+vGDir*(fT*fT*fGA); + + if( (eptType == EPT_BULLET_WATER) && (vPos(2) < vSource(2)) ) + { + continue; + } + + FLOAT fSize = (fSizeStart + afStarsPositions[ iSpray*2+iRnd*3][0]/20.0f)*fStretch; + FLOAT fRotation = fT*500.0f; + FLOAT fColorFactor = 1.0f; + if( fT>=fFadeStart) + { + fColorFactor = 1-fFadeLen*(fT-fFadeStart); + } + UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); + COLOR col = colStones|ubColor; + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + Particle_Flush(); + + //--------------------------------------- + if( (fT=BULLET_SPARK_FADEOUT_START) + { + fColorFactor = 1-BULLET_SPARK_FADEOUT_LEN*(fT-BULLET_SPARK_FADEOUT_START); + } + UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); + COLOR col = RGBToColor(ubColor,ubColor,ubColor)|CT_OPAQUE; + Particle_RenderLine( vPos0, vPos1, 0.05f, col); + } + Particle_Flush(); + } + + //--------------------------------------- + if( (fT0.5) { + // use cross product of +x axis and plane normal as +s axis + vX = FLOAT3D(1.0f, 0.0f, 0.0f)*vY; + // if the plane is mostly vertical + } else { + // use cross product of +y axis and plane normal as +s axis + vX = FLOAT3D(0.0f, 1.0f, 0.0f)*vY; + } + // make +s axis normalized + vX.Normalize(); + + // use cross product of plane normal and +s axis as +t axis + vZ = vX*vY; + vZ.Normalize(); +} + +void Particles_EmptyShells( CEntity *pen, ShellLaunchData *asldData) +{ + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fGA = ((CMovableEntity *)pen)->en_fGravityA; + FLOAT3D vGDir = ((CMovableEntity *)pen)->en_vGravityDir; + INDEX iRow, iColumn; + + for( INDEX iShell=0; iShell (tmLaunch+fLife) ) continue; + FLOAT fTRatio = fT/fLife; + INDEX iFrame = INDEX( fTRatio*16*8)%16; + iRow = iFrame/4; + iColumn = iFrame%4; + Particle_SetTexturePart( 256, 256, iColumn, iRow); + FLOAT3D vPos = (sld.sld_vPos)+(sld.sld_vSpeed*fT)+(vGDir*(fT*fT*fGA/2.0f)); + Particle_RenderSquare( vPos, 0.05f, 0, C_WHITE|CT_OPAQUE); + break; + } + case ESL_SHOTGUN: + { + FLOAT fLife = 1.5f; + if( tmNow > (tmLaunch+fLife) ) continue; + FLOAT fTRatio = fT/fLife; + INDEX iFrame = INDEX( fTRatio*16*8)%16; + iRow = 4+iFrame/4; + iColumn = iFrame%4; + Particle_SetTexturePart( 256, 256, iColumn, iRow); + FLOAT3D vPos = (sld.sld_vPos)+(sld.sld_vSpeed*fT)+(vGDir*(fT*fT*fGA/2.0f)); + Particle_RenderSquare( vPos, 0.05f, 0, C_WHITE|CT_OPAQUE); + break; + } + case ESL_BUBBLE: + { + INDEX iRnd = (INDEX(tmLaunch*1234))%CT_MAX_PARTICLES_TABLE; + FLOAT fLife = 4.0f; + if( tmNow > (tmLaunch+fLife) ) continue; + Particle_SetTexturePart( 512, 512, 2, 0); + + FLOAT3D vX, vZ; + MakeBaseFromVector( sld.sld_vUp, vX, vZ); + + FLOAT fZF = sin( afStarsPositions[iRnd+2][0]*PI); + FLOAT fXF = cos( afStarsPositions[iRnd+2][0]*PI); + + FLOAT fAmpl = ClampUp( fT+afStarsPositions[iRnd+1][1]+0.5f, 2.0f)/64; + FLOAT fFormulae = fAmpl * sin(afStarsPositions[iRnd][2]+fT*afStarsPositions[iRnd][3]*2); + + FLOAT fColorFactor = 1.0f; + if( fT>fLife/2) + { + fColorFactor = -fT+fLife; + } + UBYTE ubAlpha = UBYTE(CT_OPAQUE*fColorFactor); + ubAlpha = CT_OPAQUE; + FLOAT3D vSpeedPower = sld.sld_vSpeed/(1.0f+fT*fT); + + FLOAT3D vPos = sld.sld_vPos + + vX*fFormulae*fXF+ + vZ*fFormulae*fZF+ + sld.sld_vUp*fT/4.0f*(0.8f+afStarsPositions[iRnd][1]/8.0f)+ + vSpeedPower*fT; + FLOAT fSize = 0.02f + afStarsPositions[iRnd+3][1]*0.01f; + Particle_RenderSquare( vPos, fSize, 0, C_WHITE|ubAlpha); + break; + } + case ESL_SHOTGUN_SMOKE: + { + FLOAT fLife = 1.0f; + if( fT0.0f) + { + // render smoke + INDEX iRnd = (INDEX(tmLaunch*1234))%CT_MAX_PARTICLES_TABLE; + FLOAT fTRatio = fT/fLife; + INDEX iColumn = 4+INDEX( iShell)%4; + Particle_SetTexturePart( 256, 256, iColumn, 2); + + FLOAT3D vPos = sld.sld_vPos + sld.sld_vUp*(afStarsPositions[iRnd][0]/2.0f+0.5f)*fT + sld.sld_vSpeed*fT/(1+fT*fT); + FLOAT fColorFactor = (fLife-fT)/fLife/(afStarsPositions[iRnd+1][0]*2+4.0f); + FLOAT fRotation = afStarsPositions[iShell][1]*200*fT; + FLOAT fSize = (0.0125f+fT/(5.0f+afStarsPositions[iRnd+1][0]*2.0f))*sld.sld_fSize; + UBYTE ubAlpha = UBYTE(CT_OPAQUE*ClampUp(fColorFactor*sld.sld_fSize, 1.0f)); + COLOR colSmoke = C_WHITE; + Particle_RenderSquare( vPos, fSize, fRotation, colSmoke|ubAlpha); + } + break; + } + case ESL_COLT_SMOKE: + { + FLOAT fLife = 1.0f; + if( fT0.0f) + { + CPlayer &plr = (CPlayer&)*pen; + CPlacement3D plPipe; + plr.GetLerpedWeaponPosition(sld.sld_vPos, plPipe); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, plPipe.pl_OrientationAngle); + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + + INDEX iRnd = (INDEX(tmLaunch*1234))%CT_MAX_PARTICLES_TABLE; + FLOAT fTRatio = fT/fLife; + INDEX iColumn = 4+INDEX( iShell)%4; + Particle_SetTexturePart( 256, 256, iColumn, 2); + + FLOAT3D vPos = plPipe.pl_PositionVector+vUp*(afStarsPositions[iRnd][0]/4.0f+0.3f)*fT; + FLOAT fColorFactor = (fLife-fT)/fLife/(afStarsPositions[iRnd+1][0]*2+4.0f); + FLOAT fRotation = afStarsPositions[iShell][1]*500*fT; + FLOAT fSize = 0.0025f+fT/(10.0f+(afStarsPositions[iRnd+1][0]+0.5f)*10.0f); + UBYTE ubAlpha = UBYTE(CT_OPAQUE*fColorFactor); + COLOR colSmoke = C_WHITE; + Particle_RenderSquare( vPos, fSize, fRotation, colSmoke|ubAlpha); + } + break; + } + } + } + Particle_Flush(); +} + +#define FADE_IN_LENGHT 1.0f +#define FADE_OUT_LENGHT 1.5f +#define FADE_IN_START 0.0f +#define SPIRIT_SPIRAL_START 1.0f +#define FADE_OUT_START 1.75f + +#define FADE_IN_END (FADE_IN_START+FADE_IN_LENGHT) +#define FADE_OUT_END (FADE_OUT_START+FADE_OUT_LENGHT) + +void Particles_Death(CEntity *pen, TIME tmStart) +{ + FLOAT fMipFactor = Particle_GetMipFactor(); + + BOOL bVisible; + if(pen->en_RenderType == CEntity::RT_SKAMODEL) { + bVisible = pen->GetModelInstance()->IsModelVisible( fMipFactor); + } else { + bVisible = pen->en_pmoModelObject->IsModelVisible( fMipFactor); + } + if( !bVisible) return; + + FLOAT fTime = _pTimer->GetLerpedCurrentTick()-tmStart; + // don't render particles before fade in and after fadeout + if( (fTimeFADE_OUT_END)) { + return; + } + FLOAT fPowerTime = pow(fTime-SPIRIT_SPIRAL_START, 2.5f); + + FLOATaabbox3D box; + if(pen->en_RenderType == CEntity::RT_SKAMODEL) { + // fill array with absolute vertices of entity's model and its attached models + pen->GetModelVerticesAbsolute(avVertices, 0.05f, fMipFactor); + // get corp size + pen->GetModelInstance()->GetCurrentColisionBox(box); + } else { + // fill array with absolute vertices of entity's model and its attached models + pen->GetModelVerticesAbsolute(avVertices, 0.05f, fMipFactor); + // get corp size + pen->en_pmoModelObject->GetCurrentFrameBBox(box); + } + + // get entity position and orientation + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + SetupParticleTexture( PT_STAR07); + + // calculate color factor (for fade in/out) + FLOAT fColorFactor = 1.0f; + if( (fTime>=FADE_IN_START) && (fTime<=FADE_IN_END)) + { + fColorFactor = 1/FADE_IN_LENGHT*(fTime-FADE_IN_START); + } + else if( (fTime>=FADE_OUT_START) && (fTime<=FADE_OUT_END)) + { + fColorFactor = -1/FADE_OUT_LENGHT*(fTime-FADE_OUT_END); + } + + UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); + COLOR col = RGBToColor(ubColor,ubColor,ubColor)|CT_OPAQUE; + + INDEX ctVtx = avVertices.Count(); + FLOAT fSpeedFactor = 1.0f/ctVtx; + + FLOAT fHeightStretch = box.Size()(2); + + FLOAT fStep = ClampDn( fMipFactor, 1.0f); + for( FLOAT fVtx=0.0f; fVtxGetLerpedCurrentTick(); + + // fill array with absolute vertices of entity's model and its attached models + pen->GetModelVerticesAbsolute(avVertices, 0.0f, 0.0f); + + // get entity position and orientation + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + Particle_PrepareTexture( &_toFire, PBT_ADD); + + // calculate color factor (for fade in/out) + FLOAT fFade = fTimeRatio; + UBYTE ubColor = UBYTE(CT_OPAQUE*fFade); + COLOR col = RGBToColor(ubColor,ubColor,ubColor)|CT_OPAQUE; + + INDEX ctVtx = avVertices.Count(); + FLOAT fDensityFactor=1.0f-(Clamp(ctVtx, INDEX(500), INDEX(1000))-500.0f)/500.0f; + + // get corp size + FLOATaabbox3D box; + + if(pen->en_RenderType == CEntity::RT_SKAMODEL || pen->en_RenderType == CEntity::RT_SKAEDITORMODEL) { + pen->GetModelInstance()->GetCurrentColisionBox(box); + } else { + pen->GetBoundingBox(box); + } + + FLOAT fBoxSize=box.Size().Length(); + FLOAT fBoxHeight=box.Size()(2); + FLOAT fSizeRatio=(Clamp(fBoxSize,2.0f,12.0f)-2.0f)/10.0f; + FLOAT fSize=0.125f+ClampDn( FLOAT(pow(box.Size()(2),1.0f/4.0f)), 1.0f)*fPower/5.0f; + fSize+=(1.0f+fSizeRatio)*(1.0f+fSizeRatio)*0.125f; + INDEX iVtxSteep=(2+(2.0f-fSizeRatio-fDensityFactor)*6); + if( IsOfClass(pen, "Werebull")) + { + iVtxSteep=2; + } + for( INDEX iVtx=0; iVtxGetLerpedCurrentTick(); + + CPlacement3D plPlacement = pl; + + // fill array with absolute vertices of entity's model and its attached models + FLOATmatrix3D mRotation; + MakeRotationMatrixFast(mRotation, plPlacement.pl_OrientationAngle); + mo->GetModelVertices( avVertices, mRotation, plPlacement.pl_PositionVector, 0.0f, 0.0f); + + // get entity position and orientation + const FLOATmatrix3D &m = mRotation; + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = plPlacement.pl_PositionVector; + + Particle_PrepareTexture( &_toFire, PBT_ADD); + + UBYTE ubColor = UBYTE(CT_OPAQUE); + COLOR col = RGBToColor(ubColor,ubColor,ubColor)|CT_OPAQUE; + + INDEX ctVtx = avVertices.Count(); + FLOAT fDensityFactor=1.0f-(Clamp(ctVtx, INDEX(500), INDEX(1000))-500.0f)/500.0f; + + // get corp size + FLOATaabbox3D box; + mo->GetAllFramesBBox(box); + FLOAT fBoxSize=box.Size().Length(); + FLOAT fBoxHeight=box.Size()(2); + FLOAT fSizeRatio=(Clamp(fBoxSize,2.0f,12.0f)-2.0f)/10.0f; + //FLOAT fSize=0.125f+ClampDn( FLOAT(pow(box.Size()(2),1.0f/4.0f)), 0.1f)*fPower/5.0f; + //fSize+=(1.0f+fSizeRatio)*(1.0f+fSizeRatio)*0.125f; + FLOAT fSize = fPower; + INDEX iVtxSteep=(2+(2.0f-fSizeRatio-fDensityFactor)*6); + for( INDEX iVtx=0; iVtxGetParent(); + if (penBrush==NULL) return; + + INDEX iFramesInRaw=8; + INDEX iFramesInColumn=4; + INDEX ctFrames=iFramesInRaw*iFramesInColumn; + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + Particle_PrepareTexture( &_toFire, PBT_ADD); + + CPlacement3D plBrush = penBrush->GetLerpedPlacement(); + FLOAT3D vBrushPos = plBrush.pl_PositionVector; + FLOATmatrix3D mBrushRot; + MakeRotationMatrixFast(mBrushRot, plBrush.pl_OrientationAngle); + + FLOAT fFade = Clamp(fTimeRatio,0.0f, 1.0f); + FLOAT3D vG=FLOAT3D(0,-1.0f,0); + if( IsDerivedFromClass(pen, "MovableEntity")) + { + vG=((CMovableEntity *)pen)->en_vGravityDir; + } + FLOAT fMul=vG%vPlane; + if( fMul>0) return; + + // calculate frame 3D offsets + FLOAT3D vSlide=FLOAT3D(0,0,0); + FLOAT3D vPerD=vG*vPlane; + if( vPerD.Length()>0.01f) + { + vSlide=vPerD*vG; + vSlide.Normalize(); + } + + INDEX iRndEn=pen->en_ulID; + for( INDEX iFlame=0; iFlameen_pmoModelObject->IsModelVisible( fMipFactor); + if( !bVisible) return; + + FLOAT fTime = _pTimer->GetLerpedCurrentTick()-tmStart; + // don't render particles before fade in and after fadeout + if( (fTimeAPPEAR_OUT_END)) { + return; + } + FLOAT fPowerTime = pow(fTime-SPIRIT_SPIRAL_START, 2.5f); + + // fill array with absolute vertices of entity's model and its attached models + pen->GetModelVerticesAbsolute(avVertices, 0.05f, fMipFactor); + + // get entity position and orientation + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + SetupParticleTexture( PT_STAR07); + + // calculate color factor (for fade in/out) + FLOAT fColorFactor = 1.0f; + if( (fTime>=APPEAR_IN_START) && (fTime<=APPEAR_IN_END)) + { + fColorFactor = 1/APPEAR_IN_LENGHT*(fTime-APPEAR_IN_START); + } + else if( (fTime>=APPEAR_OUT_START) && (fTime<=APPEAR_OUT_END)) + { + fColorFactor = -1/APPEAR_OUT_LENGHT*(fTime-APPEAR_OUT_END); + } + + UBYTE ubColor = UBYTE(CT_OPAQUE*fColorFactor); + COLOR col = RGBToColor(ubColor,ubColor,ubColor)|CT_OPAQUE; + + INDEX ctVtx = avVertices.Count(); + FLOAT fSpeedFactor = 1.0f/ctVtx; + + // get corp size + FLOATaabbox3D box; + pen->en_pmoModelObject->GetCurrentFrameBBox(box); + FLOAT fHeightStretch = box.Size()(2); + + FLOAT fStep = ClampDn( fMipFactor, 1.0f); + for( FLOAT fVtx=0.0f; fVtxsp_iBlood; + + // determine time difference + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fSpeedModifier = 0; + FLOAT fT=(fNow-tmStarted); + + // prepare texture + switch(sptType) { + case SPT_BLOOD: + case SPT_SLIME: + case SPT_GOO: + { + if( iBloodType<1) return; + if( iBloodType==3) Particle_PrepareTexture( &_toFlowerSprayTexture, PBT_BLEND); + else Particle_PrepareTexture( &_toBloodSprayTexture, PBT_BLEND); + break; + } + case SPT_BONES: + { + Particle_PrepareTexture( &_toBonesSprayTexture, PBT_BLEND); + break; + } + case SPT_FEATHER: + { + Particle_PrepareTexture( &_toFeatherSprayTexture, PBT_BLEND); + fDamagePower*=2.0f; + break; + } + case SPT_STONES: + { + Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); + fDamagePower*=3.0f; + break; + } + case SPT_COLOREDSTONE: + { + Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); + fDamagePower*=2.0f; + fGA*=2.0f; + break; + } + case SPT_WOOD: + { + Particle_PrepareTexture( &_toWoodSprayTexture, PBT_BLEND); + fDamagePower*=6.0f; + fGA*=3.0f; + break; + } + case SPT_TREE01: + { + ctSprays*=1; + Particle_PrepareTexture( &_toWoodSprayTexture, PBT_BLEND); + fDamagePower*=1; + fSpeedModifier+=20; + fRotation = fT*1000.0f; + fGA*=4.0f; + break; + } + case SPT_SMALL_LAVA_STONES: + { + Particle_PrepareTexture( &_toLavaSprayTexture, PBT_BLEND); + fDamagePower *= 0.75f; + break; + } + case SPT_LAVA_STONES: + { + Particle_PrepareTexture( &_toLavaSprayTexture, PBT_BLEND); + fDamagePower *=3.0f; + break; + } + case SPT_BEAST_PROJECTILE_SPRAY: + { + Particle_PrepareTexture( &_toBeastProjectileSprayTexture, PBT_BLEND); + fDamagePower*=3.0f; + break; + } + case SPT_ELECTRICITY_SPARKS: + { + Particle_PrepareTexture( &_toMetalSprayTexture, PBT_BLEND); + break; + } + case SPT_AIRSPOUTS: + { + Particle_PrepareTexture( &_toAirSprayTexture, PBT_BLEND); + break; + } + case SPT_PLASMA: + { + Particle_PrepareTexture( &_toLarvaProjectileSpray, PBT_BLEND); + fDamagePower*=2.0f; + break; + } + case SPT_NONE: + { + return; + } + default: ASSERT(FALSE); + return; + } + + for( INDEX iSpray=0; iSprayBLOOD_SPRAY_FADE_OUT_START) + { + fSize=(-1/(BLOOD_SPRAY_TOTAL_TIME-BLOOD_SPRAY_FADE_OUT_START))*(fT-BLOOD_SPRAY_TOTAL_TIME); + fFade = fSize; + } + else if( fT>BLOOD_SPRAY_TOTAL_TIME) + { + fSize=0.0f; + fFade =0.0f; + } + else + { + fSize=1.0f; + fFade = fSize; + } + FLOAT fMipFactor = Particle_GetMipFactor(); + FLOAT fMipSizeAffector = Clamp( fMipFactor/4.0f, 0.05f, 1.0f); + fSize *= fMipSizeAffector*fDamagePower*fEnemySizeModifier; + + INDEX iRnd=(iSpray+INDEX(tmStarted*123.456))%CT_MAX_PARTICLES_TABLE; + FLOAT3D vRandomAngle = FLOAT3D( + afStarsPositions[ iRnd][0]*1.75f, + (afStarsPositions[ iRnd][1]+1.0f)*1.0f, + afStarsPositions[ iRnd][2]*1.75f); + FLOAT fSpilPower=vSpilDirection.Length(); + vRandomAngle=vRandomAngle.Normalize()*fSpilPower; + fSpeedModifier+=afStarsPositions[ iSpray+ctSprays][0]*0.5f; + + FLOAT fSpeed = BLOOD_SPRAY_SPEED_MIN+(BLOOD_SPRAY_TOTAL_TIME-fT)/BLOOD_SPRAY_TOTAL_TIME; + FLOAT3D vPos = vSource+ (vSpilDirection+vRandomAngle)*(fT*(fSpeed+fSpeedModifier))+vGDir*(fT*fT*fGA/4.0f); + + UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); + FLOAT fSizeModifier = afStarsPositions[ int(iSpray+tmStarted*50)%CT_MAX_PARTICLES_TABLE][1]*0.5+1.0f; + + COLOR col = C_WHITE|CT_OPAQUE; + // prepare texture + switch(sptType) { + case SPT_BLOOD: + { + UBYTE ubRndCol = UBYTE( 128+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*64); + if( iBloodType==2) col = RGBAToColor( ubRndCol, 0, 0, ubAlpha); + if( iBloodType==1) col = RGBAToColor( 0, ubRndCol, 0, ubAlpha); + break; + } + case SPT_SLIME: + { + UBYTE ubRndCol = UBYTE( 128+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*64); + if( iBloodType!=3) col = RGBAToColor(0, ubRndCol, 0, ubAlpha); + break; + } + case SPT_GOO: + { + UBYTE ubRndCol = UBYTE( 128+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*64); + if( iBloodType!=3) col = RGBAToColor(ubRndCol, 128, 12, ubAlpha); + break; + } + case SPT_BONES: + { + UBYTE ubRndH = UBYTE( 8+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); + UBYTE ubRndV = UBYTE( 64+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); + col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + fSize/=1.5f; + break; + } + case SPT_FEATHER: + { + if(iSpray>=ctSprays/2) + { + UBYTE ubRndCol = UBYTE( 128+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*64); + if( iBloodType==2) col = RGBAToColor( ubRndCol, 0, 0, ubAlpha); + if( iBloodType==1) col = RGBAToColor( 0, ubRndCol, 0, ubAlpha); + } + else + { + UBYTE ubRndH = UBYTE( 32+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = UBYTE( 127+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*128); + UBYTE ubRndV = UBYTE( 159+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*192); + col = HSVToColor(ubRndH, 0, ubRndV)|ubAlpha; + fSize/=2.0f; + fRotation = fT*200.0f; + } + break; + } + case SPT_STONES: + { + UBYTE ubRndH = UBYTE( 24+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = UBYTE( 32+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); + UBYTE ubRndV = UBYTE( 196+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*128); + col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + fSize*=0.10f; + fRotation = fT*200.0f; + break; + } + case SPT_COLOREDSTONE: + { + UBYTE ubH,ubS,ubV; + ColorToHSV( colMultiply, ubH, ubS, ubV); + UBYTE ubRndH = Clamp(ubH+INDEX(afStarsPositions[ int(iSpray+tmStarted*6)%CT_MAX_PARTICLES_TABLE][0]*16),INDEX(0),INDEX(255)); + UBYTE ubRndS = Clamp(ubS+INDEX(afStarsPositions[ int(iSpray+tmStarted*7)%CT_MAX_PARTICLES_TABLE][1]*64),INDEX(0),INDEX(255)); + UBYTE ubRndV = Clamp(ubV+INDEX(afStarsPositions[ int(iSpray+tmStarted*8)%CT_MAX_PARTICLES_TABLE][2]*64),INDEX(0),INDEX(255)); + col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + fSize*=0.10f/2.0f; + fRotation = fT*50.0f; + break; + } + case SPT_WOOD: + { + UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*32); + UBYTE ubRndV = UBYTE( 96+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*96); + col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + fSize*=0.15f; + fRotation = fT*300.0f; + break; + } + case SPT_TREE01: + { + UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*32); + UBYTE ubRndV = UBYTE( 96+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*96); + col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + fSize*=0.2f; + break; + } + case SPT_LAVA_STONES: + case SPT_SMALL_LAVA_STONES: + { + col = C_WHITE|ubAlpha; + fSize/=12.0f; + fRotation = fT*200.0f; + break; + } + case SPT_BEAST_PROJECTILE_SPRAY: + { + col = C_WHITE|ubAlpha; + fSize/=12.0f; + fRotation = fT*200.0f; + break; + } + case SPT_ELECTRICITY_SPARKS: + { + UBYTE ubRndH = UBYTE( 180+afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*16); + UBYTE ubRndS = UBYTE( 32+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*16); + UBYTE ubRndV = UBYTE( 192+(afStarsPositions[ int(iSpray+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); + ubRndS = 0; + ubRndV = 255; + col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + fSize/=32.0f; + fRotation = fT*200.0f; + break; + } + case SPT_AIRSPOUTS: + { + col = C_WHITE|(ubAlpha>>1); + break; + } + } + Particle_RenderSquare( vPos, 0.25f*fSize*fSizeModifier, fRotation, MulColors(col,colMultiply)); + } + + // all done + Particle_Flush(); +} + +// spray some stones along obelisk +void Particles_DestroyingObelisk(CEntity *penSpray, FLOAT tmStarted) +{ + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fT=(fNow-tmStarted); + Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); + + FLOAT fTotalTime = 10.0f; + FLOAT fFadeOutStart = 7.5f; + FLOAT fFadeInEnd = 1.0f; + FLOAT3D vG = FLOAT3D(0.0f,-20.0f,0.0f); + + for( INDEX iStone=0; iStone<128; iStone++) + { + INDEX idx = int(iStone+tmStarted*33)%CT_MAX_PARTICLES_TABLE; + FLOAT3D vSpeed = FLOAT3D( + afStarsPositions[ idx][0], + afStarsPositions[ idx][1], + afStarsPositions[ idx][2]); + vSpeed(2) += 0.25f; + vSpeed *= 50.0f; + + // calculate position + FLOAT3D vPos = penSpray->GetPlacement().pl_PositionVector + + vSpeed*fT + + vG*fT*fT; + vPos(2) += (afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][1]+0.5)*116.0f; + + FLOAT fFade; + // apply fade + if( fTfFadeOutStart) + { + fFade = (-1/(fTotalTime-fFadeOutStart))*(fT-fTotalTime); + } + else if( fT>fTotalTime) + { + fFade =0.0f; + } + else + { + fFade = 1.0f; + } + + UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*8); + UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); + UBYTE ubRndV = UBYTE( 128+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); + UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); + COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + + FLOAT fSize=(afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+1.0f)*1.5f; + FLOAT fRotation = fT*200.0f; + + Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iStone)%8, 0); + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + // all done + Particle_Flush(); +} + +// spray some stones along pylon +void Particles_DestroyingPylon(CEntity *penSpray, FLOAT3D vDamageDir, FLOAT tmStarted) +{ + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fT=(fNow-tmStarted); + Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); + + FLOAT fTotalTime = 10.0f; + FLOAT fFadeOutStart = 7.5f; + FLOAT fFadeInEnd = 1.0f; + FLOAT3D vG = FLOAT3D(0.0f,-20.0f,0.0f); + const FLOATmatrix3D &m = penSpray->GetRotationMatrix(); + + for( INDEX iStone=0; iStone<128; iStone++) + { + INDEX idx = int(iStone+tmStarted*33)%CT_MAX_PARTICLES_TABLE; + FLOAT3D vSpeed = vDamageDir+FLOAT3D( + afStarsPositions[ idx][0], + afStarsPositions[ idx][1], + afStarsPositions[ idx][2]); + vSpeed *= 50.0f; + + // calculate position + FLOAT3D vPos = penSpray->GetPlacement().pl_PositionVector + + vSpeed*fT*m + + vG*fT*fT; + FLOAT3D vOffset = FLOAT3D(0.0f,0.0f,0.0f); + vOffset(1) = (afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][1])*32.0f; + vOffset(2) = (afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+0.5)*56.0f; + vPos += vOffset*m; + + FLOAT fFade; + // apply fade + if( fTfFadeOutStart) + { + fFade = (-1/(fTotalTime-fFadeOutStart))*(fT-fTotalTime); + } + else if( fT>fTotalTime) + { + fFade =0.0f; + } + else + { + fFade = 1.0f; + } + + UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*8); + UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); + UBYTE ubRndV = UBYTE( 128+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); + UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); + COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + + FLOAT fSize=(afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+1.0f)*1.5f; + FLOAT fRotation = fT*200.0f; + + Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iStone)%8, 0); + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + // all done + Particle_Flush(); +} + +// spray some stones in the air +void Particles_HitGround(CEntity *penSpray, FLOAT tmStarted, FLOAT fSizeMultiplier) +{ + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fT=(fNow-tmStarted); + Particle_PrepareTexture( &_toStonesSprayTexture, PBT_BLEND); + + FLOAT fTotalTime = 10.0f; + FLOAT fFadeOutStart = 7.5f; + FLOAT fFadeInEnd = 1.0f; + FLOAT3D vG = FLOAT3D(0.0f,-30.0f,0.0f); + + for( INDEX iStone=0; iStone<64; iStone++) + { + INDEX idx = int(iStone+tmStarted*33)%CT_MAX_PARTICLES_TABLE; + FLOAT3D vSpeed = FLOAT3D( + afStarsPositions[ idx][0]*1.5f, + (afStarsPositions[ idx][1]+0.5f)*3, + afStarsPositions[ idx][2]*1.5f); + FLOAT fSpeedMultiplier = (fSizeMultiplier-1)*(0.5f-1.0f)/(0.025f-1.0f)+1.0f; + vSpeed *= 50.0f*fSpeedMultiplier; + + // calculate position + FLOAT3D vPos = penSpray->GetPlacement().pl_PositionVector + + vSpeed*fT + + vG*fT*fT; + + FLOAT fFade; + // apply fade + if( fTfFadeOutStart) + { + fFade = (-1/(fTotalTime-fFadeOutStart))*(fT-fTotalTime); + } + else if( fT>fTotalTime) + { + fFade =0.0f; + } + else + { + fFade = 1.0f; + } + + UBYTE ubRndH = UBYTE( 16+afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][0]*8); + UBYTE ubRndS = UBYTE( 96+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][1]+0.5)*64); + UBYTE ubRndV = UBYTE( 128+(afStarsPositions[ int(iStone+tmStarted*10)%CT_MAX_PARTICLES_TABLE][2])*64); + UBYTE ubAlpha = UBYTE(CT_OPAQUE*fFade); + COLOR col = HSVToColor(ubRndH, ubRndS, ubRndV)|ubAlpha; + + FLOAT fSize=(afStarsPositions[ int(iStone+tmStarted*100)%CT_MAX_PARTICLES_TABLE][2]+1.0f)*4.0f*fSizeMultiplier; + FLOAT fRotation = fT*200.0f; + + Particle_SetTexturePart( 256, 256, ((int(tmStarted*100.0f))%8+iStone)%8, 0); + Particle_RenderSquare( vPos, fSize, fRotation, col); + } + // all done + Particle_Flush(); +} + +#define CT_AFTERBURNER_SMOKES 32 +#define CT_AFTERBURNER_HEAD_POSITIONS 5 +#define CT_AFTERBURNER_HEAD_INTERPOSITIONS 4 +void Particles_AfterBurner_Prepare(CEntity *pen) +{ + pen->GetLastPositions(CT_AFTERBURNER_SMOKES); +} + +void Particles_AfterBurner(CEntity *pen, FLOAT tmSpawn, FLOAT fStretch, INDEX iGradientType) +{ + FLOAT3D vGDir = ((CMovableEntity *)pen)->en_vGravityDir; + FLOAT fGA = ((CMovableEntity *)pen)->en_fGravityA; + + CLastPositions *plp = pen->GetLastPositions(CT_AFTERBURNER_SMOKES); + Particle_PrepareTexture(&_toAfterBurner, PBT_BLEND); + CTextureData *pTD; + switch( iGradientType) + { + case 0: + default: + pTD=(CTextureData *) _toAfterBurnerGradient.GetData(); + break; + case 1: + pTD=(CTextureData *) _toAfterBurnerGradientBlue.GetData(); + break; + case 2: + pTD=(CTextureData *) _toAfterBurnerGradientMeteor.GetData(); + break; + } + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(plp->lp_ctUsed-1); + + ULONG *pcolFlare=pTD->GetRowPointer(0); // flare color + ULONG *pcolExp=pTD->GetRowPointer(1); // explosion color + ULONG *pcolSmoke=pTD->GetRowPointer(2); // smoke color + FLOAT aFlare_sol[256], aFlare_vol[256], aFlare_wol[256], aFlare_rol[256]; + FLOAT aExp_sol[256], aExp_vol[256], aExp_wol[256], aExp_rol[256]; + FLOAT aSmoke_sol[256], aSmoke_vol[256], aSmoke_rol[256]; + + pTD->FetchRow( 4, aFlare_sol); + pTD->FetchRow( 5, aFlare_vol); + pTD->FetchRow( 6, aFlare_wol); + pTD->FetchRow( 7, aFlare_rol); + pTD->FetchRow( 8, aExp_sol); + pTD->FetchRow( 9, aExp_vol); + pTD->FetchRow(10, aExp_wol); + pTD->FetchRow(11, aExp_rol); + pTD->FetchRow(12, aSmoke_sol); + pTD->FetchRow(13, aSmoke_vol); + pTD->FetchRow(14, aSmoke_rol); + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + for(INDEX iPos = plp->lp_ctUsed-1; iPos>=1; iPos--) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + if( *pvPos1==*pvPos2) continue; + + FLOAT fT=(iPos+_pTimer->GetLerpFactor())*_pTimer->TickQuantum; + FLOAT fRatio=fT/(CT_AFTERBURNER_SMOKES*_pTimer->TickQuantum); + INDEX iIndex=fRatio*255; + INDEX iRnd=INDEX(pvPos1)%CT_MAX_PARTICLES_TABLE; + + // smoke + FLOAT3D vPosS = *pvPos1; + Particle_SetTexturePart( 512, 512, 1, 0); + FLOAT fAngleS = afStarsPositions[iRnd][2]*360.0f+fT*120.0f*afStarsPositions[iRnd][3]; + FLOAT fSizeS = (0.5f+aSmoke_sol[iIndex]*2.5f)*fStretch; + FLOAT3D vVelocityS=FLOAT3D(afStarsPositions[iRnd][2], + afStarsPositions[iRnd][3], + afStarsPositions[iRnd][1])*5.0f; + vPosS=vPosS+vVelocityS*fT+vGDir*fGA/2.0f*(fT*fT)/32.0f; + Particle_RenderSquare( vPosS, fSizeS, fAngleS, ByteSwap(pcolSmoke[iIndex])); + + // explosion + FLOAT3D vPosE = (*pvPos1+*pvPos2)/2.0f;//Lerp(*pvPos1, *pvPos2, _pTimer->GetLerpFactor()); + Particle_SetTexturePart( 512, 512, 0, 0); + FLOAT fAngleE = afStarsPositions[iRnd][0]*360.0f;//+fT*360.0f; + FLOAT fSizeE = (0.5f+aExp_sol[iIndex]*2.0f)*fStretch; + FLOAT3D vVelocityE=FLOAT3D(afStarsPositions[iRnd][0], + afStarsPositions[iRnd][1], + afStarsPositions[iRnd][2])*3.0f; + vPosE=vPosE+vVelocityE*fT+vGDir*fGA/2.0f*(fT*fT)/32.0f; + Particle_RenderSquare( vPosE, fSizeE, fAngleE, ByteSwap(pcolExp[iIndex])); + + } + // all done + Particle_Flush(); + + if( IsOfClass(pen, "PyramidSpaceShip")) return; + Particle_PrepareTexture(&_toAfterBurnerHead, PBT_ADDALPHA); + Particle_SetTexturePart( 1024, 1024, 0, 0); + FLOAT fColMul=1.0f; + if( (fNow-tmSpawn)<1.0f) + { + fColMul=CalculateRatio(fNow-tmSpawn, 0, 1, 0.5f, 0.0f); + } + UBYTE ubColMul=UBYTE(CT_OPAQUE*fColMul); + COLOR colMul=RGBAToColor(ubColMul,ubColMul,ubColMul,ubColMul); + + INDEX ctParticles=CT_AFTERBURNER_HEAD_POSITIONS;//Min(CT_AFTERBURNER_HEAD_POSITIONS,plp->lp_ctUsed-1); + pvPos1 = &plp->GetPosition(ctParticles-1); + for(INDEX iFlare=ctParticles-2; iFlare>=0; iFlare--) + { + pvPos2 = pvPos1; + pvPos1 = &plp->GetPosition(iFlare); + if( *pvPos1==*pvPos2) continue; + + for (INDEX iInter=CT_AFTERBURNER_HEAD_INTERPOSITIONS-1; iInter>=0; iInter--) + { + FLOAT fT=(iFlare+_pTimer->GetLerpFactor()+iInter*1.0f/CT_AFTERBURNER_HEAD_INTERPOSITIONS)*_pTimer->TickQuantum; + FLOAT fRatio=fT/(ctParticles*_pTimer->TickQuantum); + INDEX iIndex=fRatio*255; + FLOAT fSize = (aFlare_sol[iIndex]*2.0f)*fStretch; + FLOAT3D vPos = Lerp(*pvPos1, *pvPos2, iInter*1.0f/CT_AFTERBURNER_HEAD_INTERPOSITIONS); + FLOAT fAngle = afStarsPositions[iInter][0]*360.0f+fRatio*360.0f; + Particle_RenderSquare( vPos, fSize, fAngle, MulColors( ByteSwap(pcolFlare[iIndex]), colMul)); + } + } + + // all done + Particle_Flush(); +} + +#define CT_ROCKETMOTOR_FLARES_BLEND ctCount +#define TM_ROCKETMOTOR_BLEND 1.5f +#define CT_ROCKETMOTOR_FLARES_ADD ctCount +#define TM_ROCKETMOTOR_ADD 1.0f +void Particles_RocketMotorBurning(CEntity *pen, FLOAT tmSpawn, FLOAT3D vStretch, FLOAT fStretch, FLOAT ctCount) +{ + FLOAT fMipDisappearDistance=13.0f; + FLOAT fMipFactor = Particle_GetMipFactor(); + if( fMipFactor>fMipDisappearDistance) return; + FLOAT fMipBlender=CalculateRatio(fMipFactor, 0.0f, fMipDisappearDistance, 0.0f, 0.1f); + + CPlacement3D pl = pen->GetLerpedPlacement(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pl.pl_PositionVector; + + CTextureData *pTD = (CTextureData *) _toAfterBurnerGradient.GetData(); + + ULONG *pcolFlare=pTD->GetRowPointer(0); // flare color + ULONG *pcolExp=pTD->GetRowPointer(1); // explosion color + ULONG *pcolSmoke=pTD->GetRowPointer(2); // smoke color + FLOAT aFlare_sol[256], aFlare_vol[256], aFlare_wol[256], aFlare_rol[256]; + FLOAT aExp_sol[256], aExp_vol[256], aExp_wol[256], aExp_rol[256]; + FLOAT aSmoke_sol[256], aSmoke_vol[256], aSmoke_rol[256]; + + pTD->FetchRow( 4, aFlare_sol); + pTD->FetchRow( 5, aFlare_vol); + pTD->FetchRow( 6, aFlare_wol); + pTD->FetchRow( 7, aFlare_rol); + pTD->FetchRow( 8, aExp_sol); + pTD->FetchRow( 9, aExp_vol); + pTD->FetchRow(10, aExp_wol); + pTD->FetchRow(11, aExp_rol); + pTD->FetchRow(12, aSmoke_sol); + pTD->FetchRow(13, aSmoke_vol); + pTD->FetchRow(14, aSmoke_rol); + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + + Particle_PrepareTexture(&_toAfterBurner, PBT_BLEND); + for(INDEX iFlare=0; iFlareen_ulID+iFlare)%CT_MAX_PARTICLES_TABLE; + FLOAT fFireDelta=TM_ROCKETMOTOR_BLEND/CT_ROCKETMOTOR_FLARES_BLEND; + FLOAT fT = fNow+iFlare*fFireDelta+afTimeOffsets[iFlare]*fFireDelta*0.1f; + // apply time strech + fT *= 1/TM_ROCKETMOTOR_BLEND; + // get fraction part + fT = fT-int(fT); + FLOAT3D vSpeed=FLOAT3D( + afStarsPositions[iRnd][0]*0.75f*vStretch(1), + afStarsPositions[iRnd][1]*0.5f*vStretch(2), + afStarsPositions[iRnd][2]*0.75f)*vStretch(3); + FLOAT fPosY=(0.926+0.202*(log(fT+0.01f))+0.2f)*60.0f; + FLOAT fSpeed=25.0f+(afStarsPositions[iRnd][0]+0.5f)*10.0f; + FLOAT3D vPosS=vCenter+vSpeed*fSpeed*fT; + vPosS=vPosS+vY*fPosY; + INDEX iIndex=fT*255; + // smoke + Particle_SetTexturePart( 512, 512, 1, 0); + FLOAT fAngleS = afStarsPositions[iRnd][2]*360.0f+fT*120.0f*afStarsPositions[iRnd][3]; + FLOAT fSizeS = (3.0f+fT*4.5f)*fStretch; + Particle_RenderSquare( vPosS, fSizeS, fAngleS, ByteSwap(pcolSmoke[iIndex])); + + // explosion + Particle_SetTexturePart( 512, 512, 0, 0); + FLOAT3D vPosE=vCenter+vSpeed*fSpeed*(fT+0.01f); + vPosE=vPosS-vY*0.1f; + FLOAT fAngleE = afStarsPositions[iRnd][0]*360.0f; + FLOAT fSizeE = (2.5f+fT*4.0f)*fStretch; + Particle_RenderSquare( vPosE, fSizeE, fAngleE, ByteSwap(pcolExp[iIndex])); + } + Particle_Flush(); + + FLOAT fFireStretch=0.6f; + Particle_PrepareTexture(&_toAfterBurner, PBT_ADDALPHA); + for(INDEX iFlame=0; iFlameen_ulID+iFlame)%CT_MAX_PARTICLES_TABLE; + FLOAT fFireDelta=TM_ROCKETMOTOR_ADD/CT_ROCKETMOTOR_FLARES_ADD; + FLOAT fT = fNow+iFlame*fFireDelta+afTimeOffsets[iFlame]*fFireDelta*0.1f; + // apply time strech + fT *= 1/TM_ROCKETMOTOR_ADD; + // get fraction part + fT = fT-int(fT); + FLOAT3D vSpeed=FLOAT3D(afStarsPositions[iRnd][0]*0.15f, + afStarsPositions[iRnd][1]*0.01f,afStarsPositions[iRnd][2]*0.15f); + FLOAT fPosY=(0.926+0.202*(log(fT+0.01f)))*60.0f/1.75f; + FLOAT fSpeed=25.0f+(afStarsPositions[iRnd][0]+0.5f)*2.0f; + FLOAT3D vPosS=vCenter+vSpeed*fSpeed*fT; + vPosS=vPosS+vY*fPosY; + INDEX iIndex=fT*255; + // smoke + Particle_SetTexturePart( 512, 512, 1, 0); + FLOAT fAngleS = afStarsPositions[iRnd][2]*360.0f+fT*120.0f*afStarsPositions[iRnd][3]; + FLOAT fSizeS = (1.5f+aSmoke_sol[iIndex]*2.5f)*fStretch*fFireStretch; + Particle_RenderSquare( vPosS, fSizeS, fAngleS, ByteSwap(pcolSmoke[iIndex])); + + // explosion + Particle_SetTexturePart( 512, 512, 0, 0); + FLOAT3D vPosE=vCenter+vSpeed*fSpeed*(fT+0.01f); + vPosE=vPosS-vY*0.1f; + FLOAT fAngleE = afStarsPositions[iRnd][0]*360.0f; + FLOAT fSizeE = (1.5f+aExp_sol[iIndex]*2.0f)*fStretch*fFireStretch; + Particle_RenderSquare( vPosE, fSizeE, fAngleE, ByteSwap(pcolExp[iIndex])); + } + // all done + Particle_Flush(); +} + +#define SP_EXPLODE_PARTICLES 25 +void Particles_SummonerProjectileExplode(CEntity *pen, FLOAT fSize, FLOAT fBeginTime, FLOAT fDuration, FLOAT fTimeAdjust) +{ + INDEX iRnd = (INDEX)(fTimeAdjust*10.0f)%(CT_MAX_PARTICLES_TABLE-SP_EXPLODE_PARTICLES); + + FLOAT fElapsed = _pTimer->GetLerpedCurrentTick() - fBeginTime; + Particle_PrepareTexture(&_toRocketTrail, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + fSize *= 2.0f; + + CTextureData *pTD = (CTextureData *) _toLavaBombTrailGradient.GetData(); + + for( INDEX iParticle=0; iParticlefFadeBegin) { + ub = 255 - (fElapsed-fFadeBegin)/(fDuration-fFadeBegin)*255; + } + if (fElapsed>fDuration) ub = 0; + + colColor = pTD->GetTexel(PIX(fElapsed*1024), 0); + colColor |= ub; + + Particle_RenderSquare( vPos, fParticleSize, fAngle, colColor); + } + + // all done + Particle_Flush(); +} + +#define SUM_EXPLODE_PARTICLES 1024 +void Particles_SummonerExplode(CEntity *pen, FLOAT3D vCenter, FLOAT fArea, FLOAT fSize, FLOAT fBeginTime, FLOAT fDuration) +{ + FLOAT fElapsed = _pTimer->GetLerpedCurrentTick() - fBeginTime; + Particle_PrepareTexture(&_toStar07, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + + + for( INDEX iParticle=0; iParticleGetLerpedCurrentTick(); + FLOAT fBirthStretcher = 1.0f; + if( fFadeOutStartTimeFetchRow( 1, arol); + pTD->FetchRow( 2, asol); + + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + vX=vX*fStretch*fDisperseFactor; + vY=vY*fStretch; + vZ=vZ*fStretch*fDisperseFactor; + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*0.0f; + INDEX ctSmokes=128; + for(INDEX i=0; ien_ulID+i)%CT_MAX_PARTICLES_TABLE; + INDEX iFrame=1+iRnd%7; + Particle_SetTexturePart( 128, 128, iFrame, 0); + FLOAT fT = tmNow+afTimeOffsets[i]; + // apply time strech + fT *= 1/TM_TWISTER_TOTAL_LIFE; + // get fraction part + fT = fT-int(fT); + INDEX iPos=fT*255; + FLOAT fSlowFactor=1.0f-fT*0.25f; + FLOAT fSpeed=25.0f+(afStarsPositions[iRnd][0]+0.5f)*2.0f; + FLOAT fR=arol[iPos]*8.0f; + FLOAT3D vPos=vCenter+vY*fSpeed*fT+ + vX*(fR*Sin(fT*360.0f*16.0f)/*+Sin((fNow+fT)*40.0f)*fT*8.0f*/)+ + vZ*(fR*Cos(fT*360.0f*16.0f)/*+Cos((fNow+fT)*40.0f)*fT*8.0f*/); + FLOAT fT2=fT+0.05f*(0.5f+fT); + FLOAT3D vPos2=vCenter+vY*fSpeed*fT2+ + vX*(fR*Sin(fT2*360.0f*16.0f)/*+Sin((fNow+fT2)*40.0f)*fT2*8.0f*/)+ + vZ*(fR*Cos(fT2*360.0f*16.0f)/*+Cos((fNow+fT2)*40.0f)*fT2*8.0f*/); + FLOAT fSize=(1.0f+afStarsPositions[iRnd][1]*0.125f)*asol[iPos]*8.0f; + if( iFrame>3) + { + fSize/=8.0f; + } + fSize*=fBirthStretcher; + FLOAT fAngle=afStarsPositions[iRnd][0]*360+(1.0f+afStarsPositions[iRnd][1])*360.0f*fT*32.0f; + COLOR col = pTD->GetTexel(PIX((afStarsPositions[iRnd][2]+0.5f)*1024.0f), 0); + COLOR colA = pTD->GetTexel(PIX(ClampUp(fT*1024.0f, 1023.0f)), 0); + UBYTE ubA=UBYTE((colA&0xFF)*0.75f*fFadeOut); + COLOR colCombined=(col&0xFFFFFF00)|ubA; + Particle_RenderSquare( vPos, fSize*fParticleStretch, fAngle, colCombined); + Particle_SetTexturePart( 128, 128, 0, 0); + Particle_RenderLine( vPos, vPos2, (0.25f+2.0f*fT)*fParticleStretch, colCombined); + } + // all done + Particle_Flush(); +} + +void Particles_ExotechLarvaLaser(CEntity *pen, FLOAT3D vSource, FLOAT3D vTarget) +{ + Particle_PrepareTexture(&_toLarvaLaser, PBT_ADD); + Particle_SetTexturePart( 512, 512, 0, 0); + + COLOR colColor; + FLOAT3D vMid; + + vMid = (vSource - vTarget).Normalize(); + vMid = vTarget + vMid * 2.5f; + + colColor = C_RED|0xff; + Particle_RenderLine( vSource, vMid, 0.5f, colColor); + Particle_RenderLine( vMid, vTarget, 0.5f, colColor); + + Particle_Flush(); + + // begin-end flares + Particle_PrepareTexture(&_toWater, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + Particle_RenderSquare( vSource, 0.5, 0.0f, colColor); + Particle_RenderSquare( vTarget, 0.5, 0.0f, colColor); + Particle_Flush(); + +} + +void Particles_Smoke(CEntity *pen, FLOAT3D vOffset, INDEX ctCount, FLOAT fLife, FLOAT fSpread, FLOAT fStretchAll, FLOAT fYSpeed) +{ + + Particle_PrepareTexture( &_toChimneySmoke, PBT_BLEND); + Particle_SetTexturePart( 1024, 1024, 0, 0); + CTextureData *pTD = (CTextureData *) _toChimneySmokeGradient.GetData(); + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*0.0f+vOffset*m; + INDEX iPosRnd=INDEX(vCenter(1)*2343.1123f+vCenter(2)*3251.16732+vCenter(3)*2761.6323f); + INDEX iCtRnd =pen->en_ulID+iPosRnd; + INDEX ctSmokes=22+INDEX((afStarsPositions[iCtRnd%CT_MAX_PARTICLES_TABLE][0]+0.5f)*8); + for(INDEX i=0; ien_ulID+i)%CT_MAX_PARTICLES_TABLE; + FLOAT fT = tmNow+afTimeOffsets[i]; + // apply time strech + fT *= 1/fLife; + // get fraction part + fT = fT-int(fT); + FLOAT fSlowFactor=1.0f-fT*0.25f; + FLOAT3D vSpeed=FLOAT3D(afStarsPositions[iRnd][0]*fSpread, + (afStarsPositions[iRnd][1]*0.1f+0.8f)*fSlowFactor,afStarsPositions[iRnd][2]*fSpread); + FLOAT fSpeed=25.0f+(afStarsPositions[iRnd][0]+0.5f)*fYSpeed; + FLOAT3D vPos=vCenter+vSpeed*fSpeed*fT+vOffset*m; + FLOAT fSize=0.25f*fStretchAll+(afStarsPositions[iRnd][1]+0.5f)*fStretchAll*fT; + FLOAT fAngle=afStarsPositions[iRnd][0]*360+afStarsPositions[iRnd][1]*360.0f*fT; + COLOR col = pTD->GetTexel(PIX((afStarsPositions[iRnd][2]+0.5f)*1024.0f), 0); + COLOR colA = pTD->GetTexel(PIX(ClampUp(fT*1024.0f, 1023.0f)), 0); + UBYTE ubA=UBYTE((colA&0xFF)*0.75f); + COLOR colCombined=(col&0xFFFFFF00)|ubA; + Particle_RenderSquare( vPos, fSize, fAngle, colCombined); + } + // all done + Particle_Flush(); +} + +#define TM_WINDBLAST_TOTAL_LIFE 2.0f +void Particles_Windblast( CEntity *pen, FLOAT fStretch, FLOAT fFadeOutStartTime) +{ + FLOAT fFadeOut=1.0f; + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + if( fFadeOutStartTimeFetchRow( 1, arol); + pTD->FetchRow( 2, asol); + + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + vX=vX*fStretch*fDisperseFactor; + vY=vY*fStretch; + vZ=vZ*fStretch*fDisperseFactor; + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector-vX*12.0f; + vX=vX*0.75f; + INDEX ctSmokes=16; + for(INDEX i=0; ien_ulID+i)%CT_MAX_PARTICLES_TABLE; + INDEX iFrame=1+iRnd%7; + Particle_SetTexturePart( 128, 128, iFrame, 0); + FLOAT fT = tmNow+afTimeOffsets[i]; + // apply time strech + fT *= 1/TM_WINDBLAST_TOTAL_LIFE; + // get fraction part + fT = fT-int(fT); + INDEX iPos=fT*255; + FLOAT fSlowFactor=1.0f-fT*0.25f; + FLOAT fSpeed=25.0f+(afStarsPositions[iRnd][0]+0.5f)*2.0f; + FLOAT fR=arol[iPos]*8.0f; + fR=3.0f; + FLOAT3D vPos=vCenter+vX*fSpeed*fT+ + vY*(fR*Sin(fT*360.0f*16.0f)/*+Sin((fNow+fT)*40.0f)*fT*8.0f*/)+ + vZ*(fR*Cos(fT*360.0f*16.0f)/*+Cos((fNow+fT)*40.0f)*fT*8.0f*/); + FLOAT fT2=fT+0.05f*(0.5f+fT); + FLOAT3D vPos2=vCenter+vX*fSpeed*fT2+ + vY*(fR*Sin(fT2*360.0f*16.0f)/*+Sin((fNow+fT2)*40.0f)*fT2*8.0f*/)+ + vZ*(fR*Cos(fT2*360.0f*16.0f)/*+Cos((fNow+fT2)*40.0f)*fT2*8.0f*/); + FLOAT fSize=3.0f; + if( iFrame>3) + { + fSize/=8.0f; + } + FLOAT fAngle=afStarsPositions[iRnd][0]*360+(1.0f+afStarsPositions[iRnd][1])*360.0f*fT*32.0f; + COLOR col = pTD->GetTexel(PIX((afStarsPositions[iRnd][2]+0.5f)*1024.0f), 0); + COLOR colA = pTD->GetTexel(PIX(ClampUp(fT*1024.0f, 1023.0f)), 0); + /* + colA = CT_OPAQUE; + col=C_WHITE; + */ + UBYTE ubA=UBYTE((colA&0xFF)*0.75f*fFadeOut); + COLOR colCombined=(col&0xFFFFFF00)|ubA; + Particle_RenderSquare( vPos, fSize, fAngle, colCombined); + Particle_SetTexturePart( 128, 128, 0, 0); + Particle_RenderLine( vPos, vPos2, 0.25f+2.0f*fT, colCombined); + } + // all done + Particle_Flush(); +} + +#define CT_COLLECT_ENERGY_PARTICLES 128 +#define CT_PROJECTILE_SPAWN_STARS 32 +void Particles_CollectEnergy(CEntity *pen, FLOAT tmStart, FLOAT tmStop) +{ + Particle_PrepareTexture( &_toElectricitySparks, PBT_BLEND); + Particle_SetTexturePart( 512, 1024, 0, 0); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fLife = 0.5; + INDEX ctRendered = 0; + FLOAT tmDelta = fLife/CT_COLLECT_ENERGY_PARTICLES; + for( INDEX iVtx=0; iVtxfLife || tmFakeStart>tmStop) continue; + // calculate fraction part + FLOAT fT=fPassedTime/fLife; + fT=fT-INDEX(fT); + + INDEX iRnd = iVtx%CT_MAX_PARTICLES_TABLE; + FLOAT3D vRnd= FLOAT3D(afStarsPositions[iRnd][0],afStarsPositions[iRnd][1],afStarsPositions[iRnd][2]); + vRnd(1) *= 40.0f; + vRnd(2) *= 40.0f; + vRnd(3) *= 40.0f; + FLOAT3D vSource = vCenter+vRnd; + FLOAT3D vDestination = vCenter+vRnd*0.05f; + FLOAT3D vPos, vPos2; + // lerp position + vPos = Lerp( vSource, vDestination, fT); + FLOAT fT2 = Clamp(fT-0.125f-fT*fT*0.125f, 0.0f, 1.0f); + vPos2 = Lerp( vSource, vDestination, fT2); + + UBYTE ubR = 255;//+afStarsPositions[iRnd][1]*64; + UBYTE ubG = 128+(1.0f-fT)*128;//223+afStarsPositions[iRnd][2]*64; + UBYTE ubB = 16+afStarsPositions[iRnd][3]*32+(1.0f-fT)*64; + UBYTE ubA = CalculateRatio( fT, 0.0f, 1.0f, 0.4f, 0.01f)*255; + COLOR colLine = RGBToColor( ubR, ubG, ubB) | ubA; + + FLOAT fSize = 0.125f; + Particle_RenderLine( vPos2, vPos, fSize, colLine); + ctRendered++; + } + + // all done + Particle_Flush(); + + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + + Particle_PrepareTexture(&_toStar03, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + FLOAT fStarLife=0.3f; + FLOAT tmDelta2 = 0.025f; + for( INDEX iStar=0; iStaren_pmoModelObject->IsModelVisible( fMipFactor); + if( !bVisible) return; + + Particle_PrepareTexture(&_toSEStar01, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + + CTextureData *pTD = (CTextureData *) _toSummonerDisappearGradient.GetData(); + FLOAT apol[256]; + ULONG *pcol=pTD->GetRowPointer(0); // flare rnd color + ULONG *pcolAdder=pTD->GetRowPointer(1); + pTD->FetchRow( 0, apol); + + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fLiving = tmNow-tmStart; + if( fLiving>SD_LIFE) return; + FLOAT fRatio=fLiving*1/SD_LIFE; + fRatio=fRatio-int(fRatio); + INDEX iIndex=INDEX(fRatio*255.0f); + FLOAT fG=10.0f*SD_LIFE*5.0f; + FLOAT fSpeed=0.0f; + FLOAT fGValue=0.0f; + FLOAT fExplodeRatio=0.2f; + if( fRatio>fExplodeRatio) + { + fSpeed=(0.351f+0.0506f*log(fRatio-fExplodeRatio))*2.0f; + fGValue=fG/2.0f*(fRatio-fExplodeRatio)*(fRatio-fExplodeRatio); + } + FLOAT fOut=fSpeed*32.0f; + // fill array with absolute vertices of entity's model and its attached models + pen->GetModelVerticesAbsolute(avVertices, 0.05f, fMipFactor); + + // get entity position and orientation + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + FLOAT3D vG=-vY; + + // calculate color factor (for fade in/out) + FLOAT fColorFactor=CalculateRatio(tmNow, tmStart, tmStart+SD_LIFE, 0.25f, 0.1f); + FLOAT fSizeStretcher=CalculateRatio(tmNow, tmStart, tmStart+SD_LIFE, 0.25f, 0.1f)*2.0f; + INDEX ctVtx = avVertices.Count(); + for( INDEX iVtx=0; iVtxGetLerpedCurrentTick(); + FLOAT fFadeFX=CalculateRatio(tmNow, fStartTime, fStartTime+TM_GROWING_SWIRL_FX_LIFE, 0.1f, 0.2f); + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + vX=vX*fStretch; + vY=vY*fStretch; + vZ=vZ*fStretch; + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector+vY*4.0f; + INDEX ctStars=TM_GROWING_SWIRL_FX_LIFE/TM_SWIRL_SPARK_LAUNCH; + for(INDEX i=0; ien_ulID+i)%CT_MAX_PARTICLES_TABLE; + FLOAT fBirth = fStartTime+i*TM_SWIRL_SPARK_LAUNCH-2.0f;//+afTimeOffsets[i]*TM_SWIRL_SPARK_LAUNCH/0.25f; + FLOAT fT = tmNow-fBirth; + FLOAT fFade=CalculateRatio(fT, 0, TM_GROWING_SWIRL_TOTAL_LIFE, 0.1f, 0.2f); + if( fFade==0.0f) continue; + // apply time strech + fT *= 1/TM_GROWING_SWIRL_TOTAL_LIFE; + // get fraction part + fT = fT-int(fT); + FLOAT fR=fT*64.0f; + FLOAT fAng=fT*600.0f; + FLOAT3D vPos=vCenter+ + vX*(fR*Sin(fAng))+ + vZ*(fR*Cos(fAng)); + FLOAT fSize=(1.0f+fT)*4.0f; + COLOR col = RGBToColor( 23, 112, 174); + UBYTE ubA=UBYTE(CT_OPAQUE*fFade*fFadeFX); + COLOR colCombined=(col&0xFFFFFF00)|ubA; + FLOAT fRot=fT*360.0f+afTimeOffsets[i]*360.0f; + Particle_RenderSquare( vPos, fSize, fRot, colCombined); + } + // all done + Particle_Flush(); +} + +void Particles_SniperResidue(CEntity *pen, FLOAT3D vSource, FLOAT3D vTarget) +{ + + Particle_PrepareTexture(&_toLightning, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + + COLOR colColor; + + FLOAT3D v1 = vSource; + FLOAT3D v2 = vTarget; + + colColor = C_YELLOW|0xff; + for (INDEX i=1; i<24; i++) { + for (INDEX j=0; j<2; j++) { + Particle_RenderLine( v1, v2, 0.05f, colColor); + } + v1 = v2; + v2 = Lerp(vSource, vTarget, NormByteToFloat(i*255/24)); + } + + Particle_Flush(); +} + +void Particles_SummonerStaff(CEmiter &em) +{ + /* + Particle_PrepareTexture(&_toSEStar01, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + */ + + Particle_PrepareTexture(&_toStar01, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + + CTextureData *pTD = (CTextureData *) _toSummonerStaffGradient.GetData(); + ULONG *pcol=pTD->GetRowPointer(0); // flare rnd color + + FLOAT fLerpFactor=_pTimer->GetLerpFactor(); + for(INDEX i=0; iGetLerpedCurrentTick(); + FLOAT fLerpFactor=_pTimer->GetLerpFactor(); + for(INDEX i=0; iGetTexel(PIX((afStarsPositions[iRnd][2]+0.5f)*1024.0f), 0); + COLOR colA = pTD->GetTexel(PIX(ClampUp(fRatio*1024.0f, 1023.0f)), 0); + UBYTE ubA=UBYTE((colA&0xFF)*0.75f); + COLOR colCombined=(col&0xFFFFFF00)|ubA; + + Particle_RenderSquare( vPos, (1.5f+1.5f*fRatio)*ep.ep_fStretch, fRot, colCombined); + } + // all done + Particle_Flush(); +} + +void Particles_AirElemental(CEntity *pen, FLOAT fStretch, FLOAT fFade, FLOAT tmDeath, COLOR colMultiply) +{ + // fill array with absolute vertices of entity's model and its attached models + pen->GetModelVerticesAbsolute(avVertices, 0.0f, 0.0f); + + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + // get entity position and orientation + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + FLOAT3D vG=-vY; + + FLOAT tmDying=ClampDn(tmNow-tmDeath, 0.0f); + FLOAT fSpeed=1.0f; + FLOAT fG=50.0f; + FLOAT fGValue=0.0f; + if( tmDying>0.0f) + { + fSpeed=(2.5f+log(2.0f*tmDying+0.22313016014842982893328047076401f))*2.0f; + fGValue=fG*((1.0f+tmDying)*(1.0f+tmDying)-1.0f); + } + + Particle_PrepareTexture( &_toTwister, PBT_BLEND); + CTextureData *pTD = (CTextureData *) _toTwisterGradient.GetData(); + + INDEX ctVtx = avVertices.Count(); + for( INDEX iVtx=0; iVtxGetTexel(PIX((afStarsPositions[iRnd][2]+0.5f)*1024.0f), 0); + COLOR colA = CT_OPAQUE; + UBYTE ubA=UBYTE((colA&0xFF)*0.75f); + COLOR colCombined=(col&0xFFFFFF00)|ubA; + colCombined=MulColors(colCombined, colMultiply); + FLOAT fRndRot=Sgn(afStarsPositions[iRnd][0])*(Abs(afStarsPositions[iRnd][1])+1.0f)*360.0f*2; + if( iFrame>3) + { + fSize/=5.0f; + } + //fSize*=fSpeed; + Particle_RenderSquare( vPos, fSize, tmNow*fRndRot, colCombined); + } + avVertices.PopAll(); + Particle_Sort(); + Particle_Flush(); +} + +void Particles_MeteorTrail(CEntity *pen, FLOAT fStretch, FLOAT fLength, FLOAT3D vSpeed) +{ + Particle_PrepareTexture( &_toMeteorTrail, PBT_ADD); + Particle_SetTexturePart( 1024, 2048, 0, 0); + CTextureData *pTD = (CTextureData *) _toExplosionDebrisGradient.GetData(); + FLOAT3D vPos0 = pen->GetLerpedPlacement().pl_PositionVector+vSpeed*0.05f; + FLOAT3D vPos1 = pen->GetLerpedPlacement().pl_PositionVector+vSpeed*0.05f-vSpeed*0.125f; + Particle_RenderLine( vPos1, vPos0, 3.0f, C_WHITE|CT_OPAQUE); + Particle_Flush(); +} + +#define TM_LEAVES_LIFE 5.0f +void Particles_Leaves(CEntity *penTree, FLOATaabbox3D boxSize, FLOAT3D vSource, FLOAT fDamagePower, + FLOAT fLaunchPower, FLOAT3D vGDir, FLOAT fGA, FLOAT tmStarted, COLOR colMax) +{ + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + Particle_PrepareTexture( &_toTreeSprayTexture, PBT_BLEND); + FLOAT fT=(fNow-tmStarted); + FLOAT fRatio=(fNow-tmStarted)/TM_LEAVES_LIFE; + + FLOAT3D vCenter = penTree->GetLerpedPlacement().pl_PositionVector; + + FLOAT fBoxWidth=boxSize.Size()(1); + FLOAT fBoxHeight=boxSize.Size()(2); + FLOAT fBoxLength=boxSize.Size()(3); + + UBYTE ubH,ubS,ubV; + ColorToHSV( colMax, ubH, ubS, ubV); + + INDEX ctSprays=128-Clamp(3.0f-fDamagePower,0.0f,3.0f)*32; + for( INDEX iSpray=0; iSprayGetLerpedPlacement().pl_PositionVector + vOffset; + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fLife = 0.5; + INDEX ctRendered = 0; + FLOAT tmDelta = fLife/CT_COLLECT_ENERGY_PARTICLES; + for( INDEX iVtx=0; iVtxfLife || tmFakeStart>tmStop) continue; + // calculate fraction part + FLOAT fT=fPassedTime/fLife; + fT=fT-INDEX(fT); + + INDEX iRnd = iVtx%CT_MAX_PARTICLES_TABLE; + FLOAT3D vRnd= FLOAT3D(afStarsPositions[iRnd][0],afStarsPositions[iRnd][1],afStarsPositions[iRnd][2]); + vRnd(1) *= 40.0f; + vRnd(2) *= 40.0f; + vRnd(3) *= 40.0f; + FLOAT3D vSource = vCenter+vRnd; + FLOAT3D vDestination = vCenter+vRnd*0.05f; + FLOAT3D vPos, vPos2; + // lerp position + vPos = Lerp( vSource, vDestination, fT); + FLOAT fT2 = Clamp(fT-0.125f-fT*fT*0.125f, 0.0f, 1.0f); + vPos2 = Lerp( vSource, vDestination, fT2); + + UBYTE ubR = 255;//+afStarsPositions[iRnd][1]*64; + UBYTE ubG = 128+(1.0f-fT)*128;//223+afStarsPositions[iRnd][2]*64; + UBYTE ubB = 16+afStarsPositions[iRnd][3]*32+(1.0f-fT)*64; + UBYTE ubA = CalculateRatio( fT, 0.0f, 1.0f, 0.4f, 0.01f)*255; + COLOR colLine = RGBToColor( ubR, ubG, ubB) | ubA; + + FLOAT fSize = 0.125f; + Particle_RenderLine( vPos2, vPos, fSize, colLine); + ctRendered++; + } + + // all done + Particle_Flush(); + + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + + Particle_PrepareTexture(&_toStar03, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + FLOAT fStarLife=0.3f; + FLOAT tmDelta2 = 0.025f; + for( INDEX iStar=0; iStarGetModelVertices( avVertices, mRotation, plPlacement.pl_PositionVector, 0.0f, 0.0f); + + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + // get entity position and orientation + const FLOATmatrix3D &m = mRotation; + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = plPlacement.pl_PositionVector; + FLOAT3D vG=-vY; + + FLOAT fSpeed=1.0f; + FLOAT fG=50.0f; + FLOAT fGValue=0.0f; + + Particle_PrepareTexture( &_toTwister, PBT_BLEND); + CTextureData *pTD = (CTextureData *) _toTwisterGradient.GetData(); + + INDEX ctVtx = avVertices.Count(); + for( INDEX iVtx=0; iVtxGetTexel(PIX((afStarsPositions[iRnd][2]+0.5f)*1024.0f), 0); + COLOR colA = CT_OPAQUE; + UBYTE ubA=UBYTE((colA&0xFF)*0.75f); + col = col&0xff000000; + COLOR colCombined=(col&0xFFFFFF00)|ubA; + FLOAT fRndRot=Sgn(afStarsPositions[iRnd][0])*(Abs(afStarsPositions[iRnd][1])+1.0f)*360.0f*2; + if( iFrame>3) + { + fSize/=5.0f; + } + //fSize*=fSpeed; + Particle_RenderSquare( vPos, fSize, tmNow*fRndRot, colCombined); + } + avVertices.PopAll(); + Particle_Sort(); + Particle_Flush(); +} + +void Particles_ModelGlow( CEntity *pen, FLOAT tmEnd, enum ParticleTexture ptTexture, FLOAT fSize, FLOAT iVtxStep, FLOAT fAnimSpd, COLOR iCol) +{ + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + + FLOAT fMipFactor = Particle_GetMipFactor(); + BOOL bVisible = pen->en_pmoModelObject->IsModelVisible( fMipFactor); + if( !bVisible) return; + + SetupParticleTextureWithAddAlpha( ptTexture ); + + // fill array with absolute vertices of entity's model and its attached models + pen->GetModelVerticesAbsolute(avVertices, fAnimSpd*(1.0f-0.5f*Sin(300.0f*tmNow)), fMipFactor); + + // get entity position and orientation + const FLOATmatrix3D &m = pen->GetRotationMatrix(); + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = pen->GetLerpedPlacement().pl_PositionVector; + + UBYTE ubCol=255; + if((tmEnd-tmNow)<5.0f) + { + ubCol = FloatToInt(255.0f*(0.5f-0.5f*cos((tmEnd-tmNow)*(9.0f*3.1415927f/5.0f)))); + } + + INDEX ctVtx = avVertices.Count(); + for( INDEX iVtx=0; iVtxGetLerpedCurrentTick(); + + SetupParticleTextureWithAddAlpha( ptTexture ); + + CPlacement3D plPlacement = pl; + + // fill array with absolute vertices of entity's model and its attached models + FLOATmatrix3D mRotation; + MakeRotationMatrixFast(mRotation, plPlacement.pl_OrientationAngle); + mo->GetModelVertices(avVertices, mRotation, plPlacement.pl_PositionVector, fAnimSpd*(1.0f-0.5f*Sin(300.0f*tmNow)), 0.0f); + + // get entity position and orientation + const FLOATmatrix3D &m = mRotation; + FLOAT3D vX( m(1,1), m(2,1), m(3,1)); + FLOAT3D vY( m(1,2), m(2,2), m(3,2)); + FLOAT3D vZ( m(1,3), m(2,3), m(3,3)); + FLOAT3D vCenter = plPlacement.pl_PositionVector; + + UBYTE ubCol=255; + if((tmEnd-tmNow)<5.0f) + { + ubCol = FloatToInt(255.0f*(0.5f-0.5f*cos((tmEnd-tmNow)*(9.0f*3.1415927f/5.0f)))); + } + + INDEX ctVtx = avVertices.Count(); + for( INDEX iVtx=0; iVtxen_vGravityDir; + FLOAT fGA = ((CMovableEntity *)pen)->en_fGravityA; + + CLastPositions *plp = pen->GetLastPositions(CT_AFTERBURNER_SMOKES); + Particle_PrepareTexture(&_toAfterBurner, PBT_BLEND); + CTextureData *pTD; + switch( iGradientType) + { + case 0: + default: + pTD=(CTextureData *) _toAfterBurnerGradient.GetData(); + break; + case 1: + pTD=(CTextureData *) _toAfterBurnerGradientBlue.GetData(); + break; + case 2: + pTD=(CTextureData *) _toAfterBurnerGradientMeteor.GetData(); + break; + } + + const FLOAT3D *pvPos1; + const FLOAT3D *pvPos2 = &plp->GetPosition(plp->lp_ctUsed-1); + + ULONG *pcolFlare=pTD->GetRowPointer(0); // flare color + ULONG *pcolExp=pTD->GetRowPointer(1); // explosion color + ULONG *pcolSmoke=pTD->GetRowPointer(2); // smoke color + FLOAT aFlare_sol[256], aFlare_vol[256], aFlare_wol[256], aFlare_rol[256]; + FLOAT aExp_sol[256], aExp_vol[256], aExp_wol[256], aExp_rol[256]; + FLOAT aSmoke_sol[256], aSmoke_vol[256], aSmoke_rol[256]; + + pTD->FetchRow( 4, aFlare_sol); + pTD->FetchRow( 5, aFlare_vol); + pTD->FetchRow( 6, aFlare_wol); + pTD->FetchRow( 7, aFlare_rol); + pTD->FetchRow( 8, aExp_sol); + pTD->FetchRow( 9, aExp_vol); + pTD->FetchRow(10, aExp_wol); + pTD->FetchRow(11, aExp_rol); + pTD->FetchRow(12, aSmoke_sol); + pTD->FetchRow(13, aSmoke_vol); + pTD->FetchRow(14, aSmoke_rol); + + FLOAT fNow = _pTimer->GetLerpedCurrentTick(); + FLOAT fColMul=1.0f; + UBYTE ubColMul=255; + if( (tmEnd-fNow)<6.0f) + { + fColMul = (tmEnd-fNow)/6.0f; + ubColMul = (INDEX) 255.0f*fColMul; + } + //UBYTE ubColMul=UBYTE(CT_OPAQUE*fColMul); + //COLOR colMul=RGBAToColor(ubColMul,ubColMul,ubColMul,ubColMul); + COLOR col; + + for(INDEX iPos = plp->lp_ctUsed-1; iPos>=1; iPos--) + { + pvPos1 = pvPos2; + pvPos2 = &plp->GetPosition(iPos); + if( *pvPos1==*pvPos2) continue; + + FLOAT fT=(iPos+_pTimer->GetLerpFactor())*_pTimer->TickQuantum; + FLOAT fRatio=fT/(CT_AFTERBURNER_SMOKES*_pTimer->TickQuantum); + INDEX iIndex=fRatio*255; + INDEX iRnd=INDEX(pvPos1)%CT_MAX_PARTICLES_TABLE; + + // smoke + FLOAT3D vPosS = *pvPos1; + Particle_SetTexturePart( 512, 512, 1, 0); + FLOAT fAngleS = afStarsPositions[iRnd][2]*360.0f+fT*120.0f*afStarsPositions[iRnd][3]; + FLOAT fSizeS = (0.5f+aSmoke_sol[iIndex]*2.5f)*fStretch; + FLOAT3D vVelocityS=FLOAT3D(afStarsPositions[iRnd][2], + afStarsPositions[iRnd][3], + afStarsPositions[iRnd][1])*5.0f; + vPosS=vPosS+vVelocityS*fT+vGDir*fGA/2.0f*(fT*fT)/32.0f; + col = ByteSwap(pcolSmoke[iIndex]); + col = (col&0xffffff00)|((col&0x000000ff)*ubColMul/255); + Particle_RenderSquare( vPosS, fSizeS, fAngleS, col); + + // explosion + FLOAT3D vPosE = (*pvPos1+*pvPos2)/2.0f;//Lerp(*pvPos1, *pvPos2, _pTimer->GetLerpFactor()); + Particle_SetTexturePart( 512, 512, 0, 0); + FLOAT fAngleE = afStarsPositions[iRnd][0]*360.0f;//+fT*360.0f; + FLOAT fSizeE = (0.5f+aExp_sol[iIndex]*2.0f)*fStretch; + FLOAT3D vVelocityE=FLOAT3D(afStarsPositions[iRnd][0], + afStarsPositions[iRnd][1], + afStarsPositions[iRnd][2])*3.0f; + vPosE=vPosE+vVelocityE*fT+vGDir*fGA/2.0f*(fT*fT)/32.0f; + col = ByteSwap(pcolExp[iIndex]); + col = (col&0xffffff00)|((col&0x000000ff)*ubColMul/255); + Particle_RenderSquare( vPosE, fSizeE, fAngleE, col); + + } + // all done + Particle_Flush(); + + if( IsOfClass(pen, "PyramidSpaceShip")) return; + Particle_PrepareTexture(&_toAfterBurnerHead, PBT_ADDALPHA); + Particle_SetTexturePart( 1024, 1024, 0, 0); + + INDEX ctParticles=CT_AFTERBURNER_HEAD_POSITIONS;//Min(CT_AFTERBURNER_HEAD_POSITIONS,plp->lp_ctUsed-1); + pvPos1 = &plp->GetPosition(ctParticles-1); + for(INDEX iFlare=ctParticles-2; iFlare>=0; iFlare--) + { + pvPos2 = pvPos1; + pvPos1 = &plp->GetPosition(iFlare); + if( *pvPos1==*pvPos2) continue; + + for (INDEX iInter=CT_AFTERBURNER_HEAD_INTERPOSITIONS-1; iInter>=0; iInter--) + { + FLOAT fT=(iFlare+_pTimer->GetLerpFactor()+iInter*1.0f/CT_AFTERBURNER_HEAD_INTERPOSITIONS)*_pTimer->TickQuantum; + FLOAT fRatio=fT/(ctParticles*_pTimer->TickQuantum); + INDEX iIndex=fRatio*255; + FLOAT fSize = (aFlare_sol[iIndex]*2.0f)*fStretch; + FLOAT3D vPos = Lerp(*pvPos1, *pvPos2, iInter*1.0f/CT_AFTERBURNER_HEAD_INTERPOSITIONS); + FLOAT fAngle = afStarsPositions[iInter][0]*360.0f+fRatio*360.0f; + Particle_RenderSquare( vPos, fSize, fAngle, C_WHITE|ubColMul); + } + } + + // all done + Particle_Flush(); +} + +void Particles_Fireworks01(CEmiter &em) +{ + Particle_PrepareTexture(&_toStar01, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + + CTextureData *pTD = (CTextureData *) _toFireworks01Gradient.GetData(); + ULONG *pcol=pTD->GetRowPointer(em.em_iGlobal); + + FLOAT fLerpFactor=_pTimer->GetLerpFactor(); + for(INDEX i=0; i acgParticles; +}; + +void DECL_DLL Particles_Growth(CEntity *pen, CTextureData *ptdGrowthMap, FLOATaabbox3D &boxGrowthMap, CEntity *penEPH, INDEX iDrawPort); + +void DECL_DLL Particles_Rain( CEntity *pen, FLOAT fGridSize, INDEX ctGrids, FLOAT fFactor, + CTextureData *ptdRainMap, FLOATaabbox3D &boxRainMap); +void DECL_DLL Particles_Snow( CEntity *pen, FLOAT fGridSize, INDEX ctGrids, FLOAT fPower, + CTextureData *ptdRainMap, FLOATaabbox3D &boxRainMap, FLOAT fSnowStart); +void DECL_DLL Particles_Lightning( FLOAT3D vSrc, FLOAT3D vDst, FLOAT fTimeStart); +void DECL_DLL Particles_BulletSpray(INDEX iRndBase, FLOAT3D vSource, FLOAT3D vGDir, enum EffectParticlesType eptType, FLOAT tmSpawn, + FLOAT3D vDirection, FLOAT fStretch); +void DECL_DLL Particles_MachineBullets( CEntity *pen, TIME tmStart, TIME tmEnd, FLOAT fFrequency); +void DECL_DLL Particles_EmptyShells( CEntity *pen, ShellLaunchData *asldData); +void DECL_DLL Particles_DestroyingObelisk(CEntity *penSpray, FLOAT tmStarted); +void DECL_DLL Particles_DestroyingPylon(CEntity *penSpray, FLOAT3D vDamageDir, FLOAT tmStarted); +void DECL_DLL Particles_HitGround(CEntity *penSpray, FLOAT tmStarted, FLOAT fSizeMultiplier); +void DECL_DLL Particles_MetalParts( CEntity *pen, FLOAT tmStarted, FLOATaabbox3D boxOwner, FLOAT fDamage); +void DECL_DLL Particles_DamageSmoke( CEntity *pen, FLOAT tmStarted, FLOATaabbox3D boxOwner, FLOAT fDamage); +void DECL_DLL Particles_RunningDust_Prepare(CEntity *pen); +void DECL_DLL Particles_RunningDust(CEntity *pen); +void DECL_DLL Particles_ShooterFlame(const CPlacement3D &plEnd, const CPlacement3D &plStart, + FLOAT fEndElapsed, FLOAT fStartElapsed); +void DECL_DLL Particles_SummonerProjectileFly(CEntity *pen, FLOAT fSize, FLOAT fTimeAdjust); +void DECL_DLL Particles_SummonerProjectileExplode(CEntity *pen, FLOAT fSize, FLOAT fBeginTime, FLOAT fDuration, FLOAT fTimeAdjust); +void DECL_DLL Particles_SummonerExplode(CEntity *pen, FLOAT3D vCenter, FLOAT fArea, FLOAT fSize, FLOAT fBeginTime, FLOAT fDuration); +void DECL_DLL Particles_ExotechLarvaLaser(CEntity *pen, FLOAT3D vSource, FLOAT3D vTarget); +void DECL_DLL Particles_Smoke(CEntity *pen, FLOAT3D vOffset, INDEX ctCount, FLOAT fLife, FLOAT fSpread, FLOAT fStretchAll, FLOAT fYSpeed); +void DECL_DLL Particles_Windblast( CEntity *pen, FLOAT fStretch, FLOAT fFadeOutStartTime); +void DECL_DLL Particles_CollectEnergy(CEntity *pen, FLOAT tmStart, FLOAT tmStop); +void DECL_DLL Particles_SniperResidue(CEntity *pen, FLOAT3D vSource, FLOAT3D vTarget); +void DECL_DLL Particles_GrowingSwirl( CEntity *pen, FLOAT fStretch, FLOAT fStartTime); +void DECL_DLL Particles_SummonerDisappear( CEntity *pen, FLOAT tmStart); +void DECL_DLL Particles_DisappearDust( CEntity *pen, FLOAT fStretch, FLOAT fStartTime); +void DECL_DLL Particles_DustFall(CEntity *pen, FLOAT tmStart, FLOAT3D vStretch); +void DECL_DLL Particles_AirElementalBlow(class CEmiter &em); +void DECL_DLL Particles_SummonerStaff(class CEmiter &em); +void DECL_DLL Particles_AirElemental(CEntity *pen, FLOAT fStretch, FLOAT fFade, FLOAT tmDeath, COLOR colMultiply); +void DECL_DLL Particles_MeteorTrail(CEntity *pen, FLOAT fStretch, FLOAT fLength, FLOAT3D vSpeed); +void DECL_DLL Particles_Leaves(CEntity *penTree, FLOATaabbox3D boxSize, FLOAT3D vSource, FLOAT fDamagePower, + FLOAT fLaunchPower, FLOAT3D vGDir, FLOAT fGA, FLOAT tmStarted, COLOR colMaxColor); +void DECL_DLL Particles_LarvaEnergy(CEntity *pen, FLOAT3D vOffset); +void DECL_DLL Particles_AirElemental_Comp(CModelObject *mo, FLOAT fStretch, FLOAT fFade, CPlacement3D pl); +void DECL_DLL Particles_Burning_Comp(CModelObject *mo, FLOAT fPower, CPlacement3D pl); +void DECL_DLL Particles_ModelGlow( CEntity *pen, FLOAT tmEnd, enum ParticleTexture ptTexture, FLOAT fSize, FLOAT iVtxStep, FLOAT fAnimSpd, COLOR iCol); +void DECL_DLL Particles_RunAfterBurner(CEntity *pen, FLOAT tmEnd, FLOAT fStretch, INDEX iGradientType); +void DECL_DLL Particles_Fireworks01(CEmiter &em); +void DECL_DLL Particles_ModelGlow2( CModelObject *mo, CPlacement3D pl, FLOAT tmEnd, enum ParticleTexture ptTexture, FLOAT fSize, FLOAT iVtxStep, FLOAT fAnimSpd, COLOR iCol); +void DECL_DLL Particles_RunAfterBurner(CEntity *pen, FLOAT tmEnd, FLOAT fStretch, INDEX iGradientType); diff --git a/Sources/EntitiesMP/Common/PathFinding.cpp b/Sources/EntitiesMP/Common/PathFinding.cpp new file mode 100644 index 0000000..014e0ef --- /dev/null +++ b/Sources/EntitiesMP/Common/PathFinding.cpp @@ -0,0 +1,282 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" +#include "EntitiesMP/Common/PathFinding.h" +#include "EntitiesMP/NavigationMarker.h" + +#define PRINTOUT(_dummy) +//#define PRINTOUT(something) something + +// open and closed lists of nodes +static CListHead _lhOpen; +static CListHead _lhClosed; + +FLOAT NodeDistance(CPathNode *ppn0, CPathNode *ppn1) +{ + return ( + ppn0->pn_pnmMarker->GetPlacement().pl_PositionVector - + ppn1->pn_pnmMarker->GetPlacement().pl_PositionVector).Length(); +} + +CPathNode::CPathNode(class CNavigationMarker *penMarker) +{ + pn_pnmMarker = penMarker; + pn_ppnParent = NULL; + pn_fG = 0.0f; + pn_fH = 0.0f; + pn_fF = 0.0f; +} + +CPathNode::~CPathNode(void) +{ + // detach from marker when deleting + ASSERT(pn_pnmMarker!=NULL); + pn_pnmMarker->m_ppnNode = NULL; +} + +// get name of this node +const CTString &CPathNode::GetName(void) +{ + static CTString strNone=""; + if (this==NULL || pn_pnmMarker==NULL) { + return strNone; + } else { + return pn_pnmMarker->GetName(); + } +} + +// get link with given index or null if no more (for iteration along the graph) +CPathNode *CPathNode::GetLink(INDEX i) +{ + if (this==NULL || pn_pnmMarker==NULL) { + ASSERT(FALSE); + return NULL; + } + CNavigationMarker *pnm = pn_pnmMarker->GetLink(i); + if (pnm==NULL) { + return NULL; + } + return pnm->GetPathNode(); +} + +// add given node to open list, sorting best first +static void SortIntoOpenList(CPathNode *ppnLink) +{ + // start at head of the open list + LISTITER(CPathNode, pn_lnInOpen) itpn(_lhOpen); + // while the given node is further than the one in list + while(ppnLink->pn_fF>itpn->pn_fF && !itpn.IsPastEnd()) { + // move to next node + itpn.MoveToNext(); + } + + // if past the end of list + if (itpn.IsPastEnd()) { + // add to the end of list + _lhOpen.AddTail(ppnLink->pn_lnInOpen); + // if not past end of list + } else { + // add before current node + itpn.InsertBeforeCurrent(ppnLink->pn_lnInOpen); + } +} + +// find shortest path from one marker to another +static BOOL FindPath(CNavigationMarker *pnmSrc, CNavigationMarker *pnmDst) +{ + + ASSERT(pnmSrc!=pnmDst); + CPathNode *ppnSrc = pnmSrc->GetPathNode(); + CPathNode *ppnDst = pnmDst->GetPathNode(); + + PRINTOUT(CPrintF("--------------------\n")); + PRINTOUT(CPrintF("FindPath(%s, %s)\n", ppnSrc->GetName(), ppnDst->GetName())); + + // start with empty open and closed lists + ASSERT(_lhOpen.IsEmpty()); + ASSERT(_lhClosed.IsEmpty()); + + // add the start node to open list + ppnSrc->pn_fG = 0.0f; + ppnSrc->pn_fH = NodeDistance(ppnSrc, ppnDst); + ppnSrc->pn_fF = ppnSrc->pn_fG +ppnSrc->pn_fH; + _lhOpen.AddTail(ppnSrc->pn_lnInOpen); + PRINTOUT(CPrintF("StartState: %s\n", ppnSrc->GetName())); + + // while the open list is not empty + while (!_lhOpen.IsEmpty()) { + // get the first node from open list (that is, the one with lowest F) + CPathNode *ppnNode = LIST_HEAD(_lhOpen, CPathNode, pn_lnInOpen); + ppnNode->pn_lnInOpen.Remove(); + _lhClosed.AddTail(ppnNode->pn_lnInClosed); + PRINTOUT(CPrintF("Node: %s - moved from OPEN to CLOSED\n", ppnNode->GetName())); + + // if this is the goal + if (ppnNode==ppnDst) { + PRINTOUT(CPrintF("PATH FOUND!\n")); + // the path is found + return TRUE; + } + + // for each link of current node + CPathNode *ppnLink = NULL; + for(INDEX i=0; (ppnLink=ppnNode->GetLink(i))!=NULL; i++) { + PRINTOUT(CPrintF(" Link %d: %s\n", i, ppnLink->GetName())); + // get cost to get to this node if coming from current node + FLOAT fNewG = ppnLink->pn_fG+NodeDistance(ppnNode, ppnLink); + // if a shorter path already exists + if ((ppnLink->pn_lnInOpen.IsLinked() || ppnLink->pn_lnInClosed.IsLinked()) && fNewG>=ppnLink->pn_fG) { + PRINTOUT(CPrintF(" shorter path exists through: %s\n", ppnLink->pn_ppnParent->GetName())); + // skip this link + continue; + } + // remember this path + ppnLink->pn_ppnParent = ppnNode; + ppnLink->pn_fG = fNewG; + ppnLink->pn_fH = NodeDistance(ppnLink, ppnDst); + ppnLink->pn_fF = ppnLink->pn_fG + ppnLink->pn_fH; + // remove from closed list, if in it + if (ppnLink->pn_lnInClosed.IsLinked()) { + ppnLink->pn_lnInClosed.Remove(); + PRINTOUT(CPrintF(" %s removed from CLOSED\n", ppnLink->GetName())); + } + // add to open if not in it + if (!ppnLink->pn_lnInOpen.IsLinked()) { + SortIntoOpenList(ppnLink); + PRINTOUT(CPrintF(" %s added to OPEN\n", ppnLink->GetName())); + } + } + } + + // if we get here, there is no path + PRINTOUT(CPrintF("PATH NOT FOUND!\n")); + return FALSE; +} + +// clear all temporary structures used for path finding +static void ClearPath(CEntity *penThis) +{ + {FORDELETELIST(CPathNode, pn_lnInOpen, _lhOpen, itpn) { + delete &itpn.Current(); + }} + {FORDELETELIST(CPathNode, pn_lnInClosed, _lhClosed, itpn) { + delete &itpn.Current(); + }} + +#ifndef NDEBUG + // for each navigation marker in the world + {FOREACHINDYNAMICCONTAINER(penThis->en_pwoWorld->wo_cenEntities, CEntity, iten) { + if (!IsOfClass(iten, "NavigationMarker")) { + continue; + } + CNavigationMarker &nm = (CNavigationMarker&)*iten; + ASSERT(nm.m_ppnNode==NULL); + }} +#endif +} + +// find marker closest to a given position +static void FindClosestMarker( + CEntity *penThis, const FLOAT3D &vSrc, CEntity *&penMarker, FLOAT3D &vPath) +{ + CNavigationMarker *pnmMin = NULL; + FLOAT fMinDist = UpperLimit(0.0f); + // for each sector this entity is in + {FOREACHSRCOFDST(penThis->en_rdSectors, CBrushSector, bsc_rsEntities, pbsc) + // for each navigation marker in that sector + {FOREACHDSTOFSRC(pbsc->bsc_rsEntities, CEntity, en_rdSectors, pen) + if (!IsOfClass(pen, "NavigationMarker")) { + continue; + } + CNavigationMarker &nm = (CNavigationMarker&)*pen; + + // get distance from source + FLOAT fDist = (vSrc-nm.GetPlacement().pl_PositionVector).Length(); + // if closer than best found + if(fDistGetPlacement().pl_PositionVector; + penMarker = pnmMin; +} + +// find first marker for path navigation +void PATH_FindFirstMarker(CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath) +{ + // find closest markers to source and destination positions + CNavigationMarker *pnmSrc; + FLOAT3D vSrcPath; + FindClosestMarker(penThis, vSrc, (CEntity*&)pnmSrc, vSrcPath); + CNavigationMarker *pnmDst; + FLOAT3D vDstPath; + FindClosestMarker(penThis, vDst, (CEntity*&)pnmDst, vDstPath); + + // if at least one is not found, or if they are same + if (pnmSrc==NULL || pnmDst==NULL || pnmSrc==pnmDst) { + // fail + penMarker = NULL; + vPath = vSrc; + return; + } + + // go to the source marker position + vPath = vSrcPath; + penMarker = pnmSrc; +} + +// find next marker for path navigation +void PATH_FindNextMarker(CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath) +{ + // find closest marker to destination position + CNavigationMarker *pnmDst; + FLOAT3D vDstPath; + FindClosestMarker(penThis, vDst, (CEntity*&)pnmDst, vDstPath); + + // if at not found, or if same as current + if (pnmDst==NULL || penMarker==pnmDst) { + // fail + penMarker = NULL; + vPath = vSrc; + return; + } + + // try to find shortest path to the destination + BOOL bFound = FindPath((CNavigationMarker*)penMarker, pnmDst); + + // if not found + if (!bFound) { + // just clean up and fail + delete pnmDst->GetPathNode(); + ClearPath(penThis); + penMarker = NULL; + vPath = vSrc; + return; + } + + // find the first marker position after current + CPathNode *ppn = pnmDst->GetPathNode(); + while (ppn->pn_ppnParent!=NULL && ppn->pn_ppnParent->pn_pnmMarker!=penMarker) { + ppn = ppn->pn_ppnParent; + } + penMarker = ppn->pn_pnmMarker; + + // go there + vPath = penMarker->GetPlacement().pl_PositionVector; + + // clean up + ClearPath(penThis); +} \ No newline at end of file diff --git a/Sources/EntitiesMP/Common/PathFinding.h b/Sources/EntitiesMP/Common/PathFinding.h new file mode 100644 index 0000000..5111e4c --- /dev/null +++ b/Sources/EntitiesMP/Common/PathFinding.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#ifndef SE_INCL_PATHFINDING_H +#define SE_INCL_PATHFINDING_H +#ifdef PRAGMA_ONCE + #pragma once +#endif + +// temporary structure used for path finding +class DECL_DLL CPathNode { +public: + // cunstruction/destruction + CPathNode(class CNavigationMarker *penMarker); + ~CPathNode(void); + + // get name of this node + const CTString &GetName(void); + + // get link with given index or null if no more (for iteration along the graph) + CPathNode *GetLink(INDEX i); + + class CNavigationMarker *pn_pnmMarker; // the marker itself + + CListNode pn_lnInOpen; // for linking in open/closed lists + CListNode pn_lnInClosed; + + CPathNode *pn_ppnParent; // best found parent in path yet + FLOAT pn_fG; // total cost to get here through the best parent + FLOAT pn_fH; // estimate of distance to the goal + FLOAT pn_fF; // total quality of the path going through this node +}; + +// find first marker for path navigation +DECL_DLL void PATH_FindFirstMarker( + CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath); +// find next marker for path navigation +DECL_DLL void PATH_FindNextMarker( + CEntity *penThis, const FLOAT3D &vSrc, const FLOAT3D &vDst, CEntity *&penMarker, FLOAT3D &vPath); + + +#endif /* include-once check. */ + diff --git a/Sources/EntitiesMP/Common/Stats.cpp b/Sources/EntitiesMP/Common/Stats.cpp new file mode 100644 index 0000000..1a53b22 --- /dev/null +++ b/Sources/EntitiesMP/Common/Stats.cpp @@ -0,0 +1,2 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + diff --git a/Sources/EntitiesMP/Common/WeaponPositions.h b/Sources/EntitiesMP/Common/WeaponPositions.h new file mode 100644 index 0000000..936a235 --- /dev/null +++ b/Sources/EntitiesMP/Common/WeaponPositions.h @@ -0,0 +1,380 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + + +#if 0 // use this part when manually setting weapon positions + + _pShell->DeclareSymbol("persistent user FLOAT wpn_fH[30+1];", &wpn_fH); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fP[30+1];", &wpn_fP); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fB[30+1];", &wpn_fB); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fX[30+1];", &wpn_fX); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fY[30+1];", &wpn_fY); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fZ[30+1];", &wpn_fZ); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fFOV[30+1];", &wpn_fFOV); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fClip[30+1];", &wpn_fClip); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fFX[30+1];", &wpn_fFX); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fFY[30+1];", &wpn_fFY); +//_pShell->DeclareSymbol("persistent user FLOAT wpn_fFZ[30+1];", &wpn_fFZ); +#else + /* + _pShell->DeclareSymbol("user FLOAT wpn_fFX[30+1];", &wpn_fFX); + _pShell->DeclareSymbol("user FLOAT wpn_fFY[30+1];", &wpn_fFY); + */ + +#pragma warning(disable: 4305) + + +wpn_fH[0]=(FLOAT)10; +wpn_fH[1]=(FLOAT)-1; +wpn_fH[2]=(FLOAT)-1; +wpn_fH[3]=(FLOAT)-1; +wpn_fH[4]=(FLOAT)2; +wpn_fH[5]=(FLOAT)2; +wpn_fH[6]=(FLOAT)4; +wpn_fH[7]=(FLOAT)2; +wpn_fH[8]=(FLOAT)2; +wpn_fH[9]=(FLOAT)2; +wpn_fH[10]=(FLOAT)5; +wpn_fH[11]=(FLOAT)4.6; +wpn_fH[12]=(FLOAT)1; +wpn_fH[13]=(FLOAT)4; +wpn_fH[14]=(FLOAT)2.5; +wpn_fH[15]=(FLOAT)4; +wpn_fH[16]=(FLOAT)2.5; +wpn_fH[17]=(FLOAT)0; +wpn_fH[18]=(FLOAT)0; +wpn_fH[19]=(FLOAT)0; +wpn_fH[20]=(FLOAT)0; +wpn_fH[21]=(FLOAT)0; +wpn_fH[22]=(FLOAT)0; +wpn_fH[23]=(FLOAT)0; +wpn_fH[24]=(FLOAT)0; +wpn_fH[25]=(FLOAT)0; +wpn_fH[26]=(FLOAT)0; +wpn_fH[27]=(FLOAT)0; +wpn_fH[28]=(FLOAT)0; +wpn_fH[29]=(FLOAT)0; +wpn_fH[30]=(FLOAT)0; +wpn_fP[0]=(FLOAT)0; +wpn_fP[1]=(FLOAT)10; +wpn_fP[2]=(FLOAT)0; +wpn_fP[3]=(FLOAT)0; +wpn_fP[4]=(FLOAT)2; +wpn_fP[5]=(FLOAT)1; +wpn_fP[6]=(FLOAT)3; +wpn_fP[7]=(FLOAT)0; +wpn_fP[8]=(FLOAT)1; +wpn_fP[9]=(FLOAT)6; +wpn_fP[10]=(FLOAT)6; +wpn_fP[11]=(FLOAT)2.8; +wpn_fP[12]=(FLOAT)3; +wpn_fP[13]=(FLOAT)2.5; +wpn_fP[14]=(FLOAT)6; +wpn_fP[15]=(FLOAT)0; +wpn_fP[16]=(FLOAT)6; +wpn_fP[17]=(FLOAT)0; +wpn_fP[18]=(FLOAT)0; +wpn_fP[19]=(FLOAT)0; +wpn_fP[20]=(FLOAT)0; +wpn_fP[21]=(FLOAT)0; +wpn_fP[22]=(FLOAT)0; +wpn_fP[23]=(FLOAT)0; +wpn_fP[24]=(FLOAT)0; +wpn_fP[25]=(FLOAT)0; +wpn_fP[26]=(FLOAT)0; +wpn_fP[27]=(FLOAT)0; +wpn_fP[28]=(FLOAT)0; +wpn_fP[29]=(FLOAT)0; +wpn_fP[30]=(FLOAT)0; +wpn_fB[0]=(FLOAT)0; +wpn_fB[1]=(FLOAT)6; +wpn_fB[2]=(FLOAT)0; +wpn_fB[3]=(FLOAT)0; +wpn_fB[4]=(FLOAT)0; +wpn_fB[5]=(FLOAT)0; +wpn_fB[6]=(FLOAT)0; +wpn_fB[7]=(FLOAT)0; +wpn_fB[8]=(FLOAT)0; +wpn_fB[9]=(FLOAT)0; +wpn_fB[10]=(FLOAT)-1; +wpn_fB[11]=(FLOAT)0; +wpn_fB[12]=(FLOAT)0; +wpn_fB[13]=(FLOAT)-0.5; +wpn_fB[14]=(FLOAT)0; +wpn_fB[15]=(FLOAT)0; +wpn_fB[16]=(FLOAT)0; +wpn_fB[17]=(FLOAT)0; +wpn_fB[18]=(FLOAT)0; +wpn_fB[19]=(FLOAT)0; +wpn_fB[20]=(FLOAT)0; +wpn_fB[21]=(FLOAT)0; +wpn_fB[22]=(FLOAT)0; +wpn_fB[23]=(FLOAT)0; +wpn_fB[24]=(FLOAT)0; +wpn_fB[25]=(FLOAT)0; +wpn_fB[26]=(FLOAT)0; +wpn_fB[27]=(FLOAT)0; +wpn_fB[28]=(FLOAT)0; +wpn_fB[29]=(FLOAT)0; +wpn_fB[30]=(FLOAT)0; +wpn_fX[0]=(FLOAT)0.08; +wpn_fX[1]=(FLOAT)0.23; +wpn_fX[2]=(FLOAT)0.19; +wpn_fX[3]=(FLOAT)0.19; +wpn_fX[4]=(FLOAT)0.12; +wpn_fX[5]=(FLOAT)0.13; +wpn_fX[6]=(FLOAT)0.121; +wpn_fX[7]=(FLOAT)0.137; +wpn_fX[8]=(FLOAT)0.17; +wpn_fX[9]=(FLOAT)0.14; +wpn_fX[10]=(FLOAT)0.125; +wpn_fX[11]=(FLOAT)0.204; +wpn_fX[12]=(FLOAT)0.141; +wpn_fX[13]=(FLOAT)0.095; +wpn_fX[14]=(FLOAT)0.17; +wpn_fX[15]=(FLOAT)0.169; +wpn_fX[16]=(FLOAT)0.225; +wpn_fX[17]=(FLOAT)0; +wpn_fX[18]=(FLOAT)0; +wpn_fX[19]=(FLOAT)0; +wpn_fX[20]=(FLOAT)0; +wpn_fX[21]=(FLOAT)0; +wpn_fX[22]=(FLOAT)0; +wpn_fX[23]=(FLOAT)0; +wpn_fX[24]=(FLOAT)0; +wpn_fX[25]=(FLOAT)0; +wpn_fX[26]=(FLOAT)0; +wpn_fX[27]=(FLOAT)0; +wpn_fX[28]=(FLOAT)0; +wpn_fX[29]=(FLOAT)0; +wpn_fX[30]=(FLOAT)0; +wpn_fY[0]=(FLOAT)0; +wpn_fY[1]=(FLOAT)-0.28; +wpn_fY[2]=(FLOAT)-0.21; +wpn_fY[3]=(FLOAT)-0.21; +wpn_fY[4]=(FLOAT)-0.22; +wpn_fY[5]=(FLOAT)-0.21; +wpn_fY[6]=(FLOAT)-0.213; +wpn_fY[7]=(FLOAT)-0.24; +wpn_fY[8]=(FLOAT)-0.325; +wpn_fY[9]=(FLOAT)-0.41; +wpn_fY[10]=(FLOAT)-0.29; +wpn_fY[11]=(FLOAT)-0.306; +wpn_fY[12]=(FLOAT)-0.174; +wpn_fY[13]=(FLOAT)-0.26; +wpn_fY[14]=(FLOAT)-0.3; +wpn_fY[15]=(FLOAT)-0.102; +wpn_fY[16]=(FLOAT)-0.345; +wpn_fY[17]=(FLOAT)0; +wpn_fY[18]=(FLOAT)0; +wpn_fY[19]=(FLOAT)0; +wpn_fY[20]=(FLOAT)0; +wpn_fY[21]=(FLOAT)0; +wpn_fY[22]=(FLOAT)0; +wpn_fY[23]=(FLOAT)0; +wpn_fY[24]=(FLOAT)0; +wpn_fY[25]=(FLOAT)0; +wpn_fY[26]=(FLOAT)0; +wpn_fY[27]=(FLOAT)0; +wpn_fY[28]=(FLOAT)0; +wpn_fY[29]=(FLOAT)0; +wpn_fY[30]=(FLOAT)0; +wpn_fZ[0]=(FLOAT)0; +wpn_fZ[1]=(FLOAT)-0.44; +wpn_fZ[2]=(FLOAT)-0.1; +wpn_fZ[3]=(FLOAT)-0.1; +wpn_fZ[4]=(FLOAT)-0.34; +wpn_fZ[5]=(FLOAT)-0.364; +wpn_fZ[6]=(FLOAT)-0.285; +wpn_fZ[7]=(FLOAT)-0.328; +wpn_fZ[8]=(FLOAT)-0.24; +wpn_fZ[9]=(FLOAT)-0.335001; +wpn_fZ[10]=(FLOAT)-0.405; +wpn_fZ[11]=(FLOAT)-0.57; +wpn_fZ[12]=(FLOAT)-0.175; +wpn_fZ[13]=(FLOAT)-0.85; +wpn_fZ[14]=(FLOAT)-0.625; +wpn_fZ[15]=(FLOAT)0; +wpn_fZ[16]=(FLOAT)-0.57; +wpn_fZ[17]=(FLOAT)0; +wpn_fZ[18]=(FLOAT)0; +wpn_fZ[19]=(FLOAT)0; +wpn_fZ[20]=(FLOAT)0; +wpn_fZ[21]=(FLOAT)0; +wpn_fZ[22]=(FLOAT)0; +wpn_fZ[23]=(FLOAT)0; +wpn_fZ[24]=(FLOAT)0; +wpn_fZ[25]=(FLOAT)0; +wpn_fZ[26]=(FLOAT)0; +wpn_fZ[27]=(FLOAT)0; +wpn_fZ[28]=(FLOAT)0; +wpn_fZ[29]=(FLOAT)0; +wpn_fZ[30]=(FLOAT)0; +wpn_fFOV[0]=(FLOAT)2; +wpn_fFOV[1]=(FLOAT)41.5; +wpn_fFOV[2]=(FLOAT)57; +wpn_fFOV[3]=(FLOAT)57; +wpn_fFOV[4]=(FLOAT)41; +wpn_fFOV[5]=(FLOAT)52.5; +wpn_fFOV[6]=(FLOAT)49; +wpn_fFOV[7]=(FLOAT)66.9; +wpn_fFOV[8]=(FLOAT)66; +wpn_fFOV[9]=(FLOAT)44.5; +wpn_fFOV[10]=(FLOAT)73.5; +wpn_fFOV[11]=(FLOAT)50; +wpn_fFOV[12]=(FLOAT)70.5; +wpn_fFOV[13]=(FLOAT)23; +wpn_fFOV[14]=(FLOAT)50; +wpn_fFOV[15]=(FLOAT)52.5; +wpn_fFOV[16]=(FLOAT)57; +wpn_fFOV[17]=(FLOAT)0; +wpn_fFOV[18]=(FLOAT)0; +wpn_fFOV[19]=(FLOAT)0; +wpn_fFOV[20]=(FLOAT)0; +wpn_fFOV[21]=(FLOAT)0; +wpn_fFOV[22]=(FLOAT)0; +wpn_fFOV[23]=(FLOAT)0; +wpn_fFOV[24]=(FLOAT)0; +wpn_fFOV[25]=(FLOAT)0; +wpn_fFOV[26]=(FLOAT)0; +wpn_fFOV[27]=(FLOAT)0; +wpn_fFOV[28]=(FLOAT)0; +wpn_fFOV[29]=(FLOAT)0; +wpn_fFOV[30]=(FLOAT)0; +wpn_fClip[0]=(FLOAT)0; +wpn_fClip[1]=(FLOAT)0.1; +wpn_fClip[2]=(FLOAT)0.1; +wpn_fClip[3]=(FLOAT)0.1; +wpn_fClip[4]=(FLOAT)0.1; +wpn_fClip[5]=(FLOAT)0.1; +wpn_fClip[6]=(FLOAT)0.1; +wpn_fClip[7]=(FLOAT)0.1; +wpn_fClip[8]=(FLOAT)0.1; +wpn_fClip[9]=(FLOAT)0.1; +wpn_fClip[10]=(FLOAT)0.1; +wpn_fClip[11]=(FLOAT)0.1; +wpn_fClip[12]=(FLOAT)0.1; +wpn_fClip[13]=(FLOAT)0.1; +wpn_fClip[14]=(FLOAT)0.1; +wpn_fClip[15]=(FLOAT)0; +wpn_fClip[16]=(FLOAT)0.1; +wpn_fClip[17]=(FLOAT)0; +wpn_fClip[18]=(FLOAT)0; +wpn_fClip[19]=(FLOAT)0; +wpn_fClip[20]=(FLOAT)0; +wpn_fClip[21]=(FLOAT)0; +wpn_fClip[22]=(FLOAT)0; +wpn_fClip[23]=(FLOAT)0; +wpn_fClip[24]=(FLOAT)0; +wpn_fClip[25]=(FLOAT)0; +wpn_fClip[26]=(FLOAT)0; +wpn_fClip[27]=(FLOAT)0; +wpn_fClip[28]=(FLOAT)0; +wpn_fClip[29]=(FLOAT)0; +wpn_fClip[30]=(FLOAT)0; +wpn_fFX[0]=(FLOAT)0; +wpn_fFX[1]=(FLOAT)0; +wpn_fFX[2]=(FLOAT)0; +wpn_fFX[3]=(FLOAT)0; +wpn_fFX[4]=(FLOAT)0; +wpn_fFX[5]=(FLOAT)0; +wpn_fFX[6]=(FLOAT)0; +wpn_fFX[7]=(FLOAT)0; +wpn_fFX[8]=(FLOAT)-0.1; +wpn_fFX[9]=(FLOAT)0; +wpn_fFX[10]=(FLOAT)0; +wpn_fFX[11]=(FLOAT)0.05; +wpn_fFX[12]=(FLOAT)-0.1; +wpn_fFX[13]=(FLOAT)0; +wpn_fFX[14]=(FLOAT)0.25; +wpn_fFX[15]=(FLOAT)0; +wpn_fFX[16]=(FLOAT)0.25; +wpn_fFX[17]=(FLOAT)0; +wpn_fFX[18]=(FLOAT)0; +wpn_fFX[19]=(FLOAT)0; +wpn_fFX[20]=(FLOAT)0; +wpn_fFX[21]=(FLOAT)0; +wpn_fFX[22]=(FLOAT)0; +wpn_fFX[23]=(FLOAT)0; +wpn_fFX[24]=(FLOAT)0; +wpn_fFX[25]=(FLOAT)0; +wpn_fFX[26]=(FLOAT)0; +wpn_fFX[27]=(FLOAT)0; +wpn_fFX[28]=(FLOAT)0; +wpn_fFX[29]=(FLOAT)0; +wpn_fFX[30]=(FLOAT)0; +wpn_fFY[0]=(FLOAT)0; +wpn_fFY[1]=(FLOAT)0; +wpn_fFY[2]=(FLOAT)0; +wpn_fFY[3]=(FLOAT)0; +wpn_fFY[4]=(FLOAT)0; +wpn_fFY[5]=(FLOAT)0; +wpn_fFY[6]=(FLOAT)0; +wpn_fFY[7]=(FLOAT)0; +wpn_fFY[8]=(FLOAT)0.11; +wpn_fFY[9]=(FLOAT)0; +wpn_fFY[10]=(FLOAT)0; +wpn_fFY[11]=(FLOAT)0.03; +wpn_fFY[12]=(FLOAT)-0.4; +wpn_fFY[13]=(FLOAT)0; +wpn_fFY[14]=(FLOAT)-0.5; +wpn_fFY[15]=(FLOAT)0; +wpn_fFY[16]=(FLOAT)-0.5; +wpn_fFY[17]=(FLOAT)0; +wpn_fFY[18]=(FLOAT)0; +wpn_fFY[19]=(FLOAT)0; +wpn_fFY[20]=(FLOAT)0; +wpn_fFY[21]=(FLOAT)0; +wpn_fFY[22]=(FLOAT)0; +wpn_fFY[23]=(FLOAT)0; +wpn_fFY[24]=(FLOAT)0; +wpn_fFY[25]=(FLOAT)0; +wpn_fFY[26]=(FLOAT)0; +wpn_fFY[27]=(FLOAT)0; +wpn_fFY[28]=(FLOAT)0; +wpn_fFY[29]=(FLOAT)0; +wpn_fFY[30]=(FLOAT)0; + + + +/* the following lines have been moved to the upper part */ + +/*// tommygun +wpn_fH[6]=(FLOAT)4; +wpn_fP[6]=(FLOAT)3; +wpn_fB[6]=(FLOAT)0; +wpn_fX[6]=(FLOAT)0.121; +wpn_fY[6]=(FLOAT)-0.213; +wpn_fZ[6]=(FLOAT)-0.285; +wpn_fFOV[6]=(FLOAT)49; +wpn_fClip[6]=0.1; +wpn_fFX[6]=(FLOAT)0; +wpn_fFY[6]=(FLOAT)0; + +// grenade launcher +wpn_fH[9]=(FLOAT)2; +wpn_fP[9]=(FLOAT)6; +wpn_fB[9]=(FLOAT)0; +wpn_fX[9]=(FLOAT)0.14; +wpn_fY[9]=(FLOAT)-0.41; +wpn_fZ[9]=(FLOAT)-0.335001; +wpn_fFOV[9]=(FLOAT)44.5; +wpn_fClip[9]=(FLOAT)0.1; +wpn_fFX[9]=(FLOAT)0; +wpn_fFY[9]=(FLOAT)0; + +// iron cannon +wpn_fH[16]=(FLOAT)2.5; +wpn_fP[16]=(FLOAT)6; +wpn_fB[16]=(FLOAT)0; +wpn_fX[16]=(FLOAT)0.225; +wpn_fY[16]=(FLOAT)-0.345; +wpn_fZ[16]=(FLOAT)-0.57; +wpn_fFOV[16]=(FLOAT)57; +wpn_fClip[16]=(FLOAT)0.1; +wpn_fFX[16]=(FLOAT)0.25; +wpn_fFY[16]=(FLOAT)-0.5;*/ + +#pragma warning(default: 4305) + +#endif + diff --git a/Sources/EntitiesMP/Copier.cpp b/Sources/EntitiesMP/Copier.cpp new file mode 100644 index 0000000..dbccd15 --- /dev/null +++ b/Sources/EntitiesMP/Copier.cpp @@ -0,0 +1,162 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" + +#include "StdH.h" + +#include +#include +void CCopier::SetDefaultProperties(void) { + m_strName = "Copier"; + m_strDescription = ""; + m_penTarget = NULL; + m_bSpawnEffect = TRUE ; + m_bTelefrag = TRUE ; + CRationalEntity::SetDefaultProperties(); +} + +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +const CTString & CCopier::GetDescription(void)const +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +{ +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +if(m_penTarget != NULL ){ +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , m_penTarget -> GetName ()); +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +} +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +return m_strDescription ; +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +} + +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +void CCopier::TeleportEntity() +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +{ +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +if(m_penTarget == NULL || (m_penTarget -> GetFlags () & ENF_DELETED )){ +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +return ; +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +} +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +CEntity * pen = GetWorld () -> CopyEntityInWorld (* m_penTarget , +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +CPlacement3D (FLOAT3D (- 32000.0f + FRnd () * 200.0f , - 32000.0f + FRnd () * 200.0f , 0) , ANGLE3D (0 , 0 , 0))); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +CPlacement3D pl = GetPlacement (); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +pl . pl_PositionVector += GetRotationMatrix () . GetColumn (2) * 0.05f; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +pen -> Teleport (pl , m_bTelefrag ); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +if(m_bSpawnEffect ){ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +ESpawnEffect ese ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +ese . betType = BET_TELEPORT ; +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +ese . vNormal = FLOAT3D (0 , 1 , 0); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +FLOATaabbox3D box ; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +pen -> GetBoundingBox (box ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +FLOAT fEntitySize = box . Size () . MaxNorm () * 2; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +ese . vStretch = FLOAT3D (fEntitySize , fEntitySize , fEntitySize ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +CEntityPointer penEffect = CreateEntity (GetPlacement () , CLASS_BASIC_EFFECT ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +penEffect -> Initialize (ese ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +} +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +} + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +SLONG CCopier::GetUsedMemory(void) +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +{ +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +SLONG slUsedMemory = sizeof (CCopier ) - sizeof (CRationalEntity ) + CRationalEntity :: GetUsedMemory (); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +slUsedMemory += m_strDescription . Length (); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +slUsedMemory += m_strName . Length (); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +return slUsedMemory ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +} +BOOL CCopier:: +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCopier_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCopier::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +InitAsEditorModel (); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +SetCollisionFlags (ECF_TOUCHMODEL ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +SetModel (MODEL_TELEPORT ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +SetModelMainTexture (TEXTURE_TELEPORT ); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +Jump(STATE_CURRENT,0x00e10004, FALSE, EInternal());return TRUE;}BOOL CCopier::H0x00e10004_Main_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e10004 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00e10005, FALSE, EInternal());return TRUE;} +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00e10000, FALSE, EBegin());return TRUE;}BOOL CCopier::H0x00e10000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e10000 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +if(m_penTarget != NULL ){ +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +TeleportEntity (); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +} +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +UnsetTimer();Jump(STATE_CURRENT,0x00e10001, FALSE, EInternal());return TRUE; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +}ASSERT(FALSE);break;default:{ +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +return TRUE; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +}ASSERT(FALSE);break; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +}return TRUE;}BOOL CCopier::H0x00e10001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e10001 +; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00e10002, FALSE, EBegin());return TRUE;}BOOL CCopier::H0x00e10002_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e10002 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00e10003, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCopier::H0x00e10003_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e10003 +;Jump(STATE_CURRENT,0x00e10004, FALSE, EInternal());return TRUE; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +}BOOL CCopier::H0x00e10005_Main_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e10005 + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Copier.es b/Sources/EntitiesMP/Copier.es new file mode 100644 index 0000000..938bcc2 --- /dev/null +++ b/Sources/EntitiesMP/Copier.es @@ -0,0 +1,119 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +225 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/BasicEffects"; + +class CCopier : CRationalEntity { +name "Copier"; +thumbnail "Thumbnails\\Copier.tbn"; +features "HasName", "HasTarget", "IsTargetable"; + +properties: + + 1 CTString m_strName "Name" 'N' = "Copier", + 3 CTString m_strDescription = "", + 2 CEntityPointer m_penTarget "Target" 'T' COLOR(C_BROWN|0xFF), + 4 BOOL m_bSpawnEffect "Spawn Effect" 'X' = TRUE, + 5 BOOL m_bTelefrag "Telefrag" 'F' = TRUE, + + +components: + + 1 model MODEL_TELEPORT "Models\\Editor\\Copier.mdl", + 2 texture TEXTURE_TELEPORT "Models\\Editor\\Copier.tex", + 3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + + +functions: + + const CTString &GetDescription(void) const + { + ((CTString&)m_strDescription).PrintF("->"); + if (m_penTarget!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", m_penTarget->GetName()); + } + return m_strDescription; + } + + void TeleportEntity() + { + // if the target doesn't exist, or is destroyed + if (m_penTarget==NULL || (m_penTarget->GetFlags()&ENF_DELETED)) { + // do nothing + return; + } + + CEntity *pen = GetWorld()->CopyEntityInWorld( *m_penTarget, + CPlacement3D(FLOAT3D(-32000.0f+FRnd()*200.0f, -32000.0f+FRnd()*200.0f, 0), ANGLE3D(0, 0, 0)) ); + + // teleport back + CPlacement3D pl = GetPlacement(); + pl.pl_PositionVector += GetRotationMatrix().GetColumn(2)*0.05f; + pen->Teleport(pl, m_bTelefrag); + + // spawn teleport effect + if (m_bSpawnEffect) { + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_TELEPORT; + ese.vNormal = FLOAT3D(0,1,0); + FLOATaabbox3D box; + pen->GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm()*2; + ese.vStretch = FLOAT3D(fEntitySize, fEntitySize, fEntitySize); + CEntityPointer penEffect = CreateEntity(GetPlacement(), CLASS_BASIC_EFFECT); + penEffect->Initialize(ese); + } + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CCopier) - sizeof(CRationalEntity) + CRationalEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strDescription.Length(); + slUsedMemory += m_strName.Length(); + return slUsedMemory; + } + + + +procedures: + + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_TOUCHMODEL); + + // set appearance + SetModel(MODEL_TELEPORT); + SetModelMainTexture(TEXTURE_TELEPORT); + + while (TRUE) { + // wait to someone enter and teleport it + wait() { + on (ETrigger eTrigger) : { + if (m_penTarget!=NULL) { + TeleportEntity(); + } + stop; + } + otherwise() : { + resume; + }; + }; + + // wait a bit to recover + autowait(0.1f); + } + } +}; + diff --git a/Sources/EntitiesMP/Copier.h b/Sources/EntitiesMP/Copier.h new file mode 100644 index 0000000..04a5764 --- /dev/null +++ b/Sources/EntitiesMP/Copier.h @@ -0,0 +1,40 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Copier_INCLUDED +#define _EntitiesMP_Copier_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CCopier_DLLClass; +class CCopier : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual CEntity *GetTarget(void) const { return m_penTarget; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CEntityPointer m_penTarget; + BOOL m_bSpawnEffect; + BOOL m_bTelefrag; + +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +const CTString & GetDescription(void)const; + +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +void TeleportEntity(); + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +SLONG GetUsedMemory(void); +#define STATE_CCopier_Main 1 + BOOL +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00e10000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00e10001_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00e10002_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00e10003_Main_04(const CEntityEvent &__eeInput); + BOOL H0x00e10004_Main_05(const CEntityEvent &__eeInput); + BOOL H0x00e10005_Main_06(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Copier_INCLUDED diff --git a/Sources/EntitiesMP/Copier_tables.h b/Sources/EntitiesMP/Copier_tables.h new file mode 100644 index 0000000..c0adf85 --- /dev/null +++ b/Sources/EntitiesMP/Copier_tables.h @@ -0,0 +1,48 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CCopier + +CEntityProperty CCopier_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e1<<8)+1, offsetof(CCopier, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e1<<8)+3, offsetof(CCopier, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e1<<8)+2, offsetof(CCopier, m_penTarget), "Target", 'T', C_BROWN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e1<<8)+4, offsetof(CCopier, m_bSpawnEffect), "Spawn Effect", 'X', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e1<<8)+5, offsetof(CCopier, m_bTelefrag), "Telefrag", 'F', 0x7F0000FFUL, 0), +}; +#define CCopier_propertiesct ARRAYCOUNT(CCopier_properties) + +CEntityComponent CCopier_components[] = { +#define MODEL_TELEPORT ((0x000000e1<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_TELEPORT, "EFNM" "Models\\Editor\\Copier.mdl"), +#define TEXTURE_TELEPORT ((0x000000e1<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_TELEPORT, "EFNM" "Models\\Editor\\Copier.tex"), +#define CLASS_BASIC_EFFECT ((0x000000e1<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +}; +#define CCopier_componentsct ARRAYCOUNT(CCopier_components) + +CEventHandlerEntry CCopier_handlers[] = { + {1, -1, CEntity::pEventHandler(&CCopier:: +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Copier.es" +Main),DEBUGSTRING("CCopier::Main")}, + {0x00e10000, -1, CEntity::pEventHandler(&CCopier::H0x00e10000_Main_01), DEBUGSTRING("CCopier::H0x00e10000_Main_01")}, + {0x00e10001, -1, CEntity::pEventHandler(&CCopier::H0x00e10001_Main_02), DEBUGSTRING("CCopier::H0x00e10001_Main_02")}, + {0x00e10002, -1, CEntity::pEventHandler(&CCopier::H0x00e10002_Main_03), DEBUGSTRING("CCopier::H0x00e10002_Main_03")}, + {0x00e10003, -1, CEntity::pEventHandler(&CCopier::H0x00e10003_Main_04), DEBUGSTRING("CCopier::H0x00e10003_Main_04")}, + {0x00e10004, -1, CEntity::pEventHandler(&CCopier::H0x00e10004_Main_05), DEBUGSTRING("CCopier::H0x00e10004_Main_05")}, + {0x00e10005, -1, CEntity::pEventHandler(&CCopier::H0x00e10005_Main_06), DEBUGSTRING("CCopier::H0x00e10005_Main_06")}, +}; +#define CCopier_handlersct ARRAYCOUNT(CCopier_handlers) + +CEntity *CCopier_New(void) { return new CCopier; }; +void CCopier_OnInitClass(void) {}; +void CCopier_OnEndClass(void) {}; +void CCopier_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CCopier_OnWorldEnd(CWorld *pwo) {}; +void CCopier_OnWorldInit(CWorld *pwo) {}; +void CCopier_OnWorldTick(CWorld *pwo) {}; +void CCopier_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CCopier, CRationalEntity, "Copier", "Thumbnails\\Copier.tbn", 0x000000e1); +DECLARE_CTFILENAME(_fnmCCopier_tbn, "Thumbnails\\Copier.tbn"); diff --git a/Sources/EntitiesMP/Counter.cpp b/Sources/EntitiesMP/Counter.cpp new file mode 100644 index 0000000..b549d5c --- /dev/null +++ b/Sources/EntitiesMP/Counter.cpp @@ -0,0 +1,207 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" + +#include "StdH.h" + +#include +#include +void CCounter::SetDefaultProperties(void) { + m_fCountdownSpeed = 12.0f; + m_penTarget = NULL; + m_fNumber = 0.0f; + m_tmStart = -1.0f; + m_strName = ""; + m_soSound.SetOwner(this); +m_soSound.Stop_internal(); + m_iCountFrom = 1023; + m_pen0 = NULL; + m_pen1 = NULL; + m_pen2 = NULL; + m_pen3 = NULL; + m_pen4 = NULL; + m_pen5 = NULL; + m_pen6 = NULL; + m_pen7 = NULL; + m_pen8 = NULL; + m_pen9 = NULL; + CRationalEntity::SetDefaultProperties(); +} + +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +void CCounter::Precache(void) +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +{ +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +PrecacheSound (SOUND_TICK ); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +CRationalEntity :: Precache (); +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +} + +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +void CCounter::DisplayNumber(void) +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +{ +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +for(INDEX iDigit = 0;iDigit < 10;iDigit ++) +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +{ +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +CModelHolder2 * pmh = (CModelHolder2 *) & * (& m_pen0 ) [ iDigit ]; +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +if(pmh != NULL && pmh -> GetModelObject () != NULL && +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +pmh -> GetModelObject () -> mo_toTexture . GetData () != NULL ) +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +{ +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +INDEX iOldAnim = pmh -> GetModelObject () -> mo_toTexture . GetAnim (); +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +INDEX iAnim = (INDEX (m_fNumber ) & (1 << iDigit )) >> iDigit ; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +pmh -> GetModelObject () -> mo_toTexture . PlayAnim (iAnim , 0); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +m_soSound . Set3DParameters (200.0f , 100.0f , 1.0f , +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +Clamp (1.0f + (m_iCountFrom - m_fNumber ) / m_iCountFrom * 2.0f , 1.0f , 3.0f)); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +if(iDigit == 0 && iOldAnim != iAnim && ! m_soSound . IsPlaying ()) +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +{ +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +PlaySound (m_soSound , SOUND_TICK , SOF_3D | SOF_VOLUMETRIC ); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +} +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +} +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +} +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +} +BOOL CCounter:: +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +CountDown(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCounter_CountDown + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCounter::CountDown expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +Jump(STATE_CURRENT,0x00e80003, FALSE, EInternal());return TRUE;}BOOL CCounter::H0x00e80003_CountDown_03(const CEntityEvent &__eeInput) +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e80003 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00e80004, FALSE, EInternal());return TRUE;} +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x00e80001, FALSE, EBegin());return TRUE;}BOOL CCounter::H0x00e80001_CountDown_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e80001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00e80002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCounter::H0x00e80002_CountDown_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e80002 +; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +FLOAT tmNow = _pTimer -> CurrentTick (); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +FLOAT tmDelta = tmNow - m_tmStart ; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +FLOAT fSub = Clamp (tmDelta / m_fCountdownSpeed , 0.01f , 1.0f); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +m_fNumber = Clamp (m_fNumber - fSub , 0.0f , FLOAT (m_iCountFrom )); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +DisplayNumber (); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +if(m_fNumber == 0) +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +{ +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +Return(STATE_CURRENT,EReturn ()); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +return TRUE; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +}Jump(STATE_CURRENT,0x00e80003, FALSE, EInternal());return TRUE; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +}BOOL CCounter::H0x00e80004_CountDown_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e80004 + ASSERT(FALSE); return TRUE;};BOOL CCounter:: +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCounter_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCounter::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +InitAsEditorModel (); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +SetModel (MODEL_MARKER ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00e80005, FALSE, EBegin());return TRUE;}BOOL CCounter::H0x00e80005_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e80005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00e80006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCounter::H0x00e80006_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e80006 +; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +m_fNumber = m_iCountFrom ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +DisplayNumber (); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00e80007, FALSE, EBegin());return TRUE;}BOOL CCounter::H0x00e80007_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e80007 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +return TRUE; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +m_fNumber = m_iCountFrom ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +DisplayNumber (); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +m_tmStart = _pTimer -> CurrentTick (); +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +Call(STATE_CURRENT, STATE_CCounter_CountDown, TRUE, EVoid());return TRUE; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; + +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +if(m_penTarget != NULL ) +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +{ +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +SendToTarget (m_penTarget , EET_TRIGGER ); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +} +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +UnsetTimer();Jump(STATE_CURRENT,0x00e80008, FALSE, EInternal());return TRUE; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +}return TRUE;}BOOL CCounter::H0x00e80008_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e80008 + +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +Return(STATE_CURRENT,EVoid()); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Counter.es b/Sources/EntitiesMP/Counter.es new file mode 100644 index 0000000..e495394 --- /dev/null +++ b/Sources/EntitiesMP/Counter.es @@ -0,0 +1,126 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +232 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/ModelHolder2"; + +class CCounter : CRationalEntity { +name "Counter"; +thumbnail "Thumbnails\\Counter.tbn"; +features "HasName", "IsTargetable", "IsImportant"; + +properties: + 1 FLOAT m_fCountdownSpeed "Countdown speed" 'S' = 12.0f, + 2 CEntityPointer m_penTarget "Zero target" 'T' COLOR(C_WHITE|0x80), + 3 FLOAT m_fNumber = 0.0f, + 4 FLOAT m_tmStart = -1.0f, + 5 CTString m_strName "Name" 'N' ="", + 6 CSoundObject m_soSound, + 7 INDEX m_iCountFrom "Count start" 'A' = 1023, + 10 CEntityPointer m_pen0 "Bit 0" COLOR(C_RED|0x30), + 11 CEntityPointer m_pen1 "Bit 1" COLOR(C_RED|0x30), + 12 CEntityPointer m_pen2 "Bit 2" COLOR(C_RED|0x30), + 13 CEntityPointer m_pen3 "Bit 3" COLOR(C_RED|0x30), + 14 CEntityPointer m_pen4 "Bit 4" COLOR(C_RED|0x30), + 15 CEntityPointer m_pen5 "Bit 5" COLOR(C_RED|0x30), + 16 CEntityPointer m_pen6 "Bit 6" COLOR(C_RED|0x30), + 17 CEntityPointer m_pen7 "Bit 7" COLOR(C_RED|0x30), + 18 CEntityPointer m_pen8 "Bit 8" COLOR(C_RED|0x30), + 19 CEntityPointer m_pen9 "Bit 9" COLOR(C_RED|0x30), + +components: + 0 sound SOUND_TICK "Sounds\\Menu\\Select.wav", + 1 model MODEL_MARKER "Models\\Editor\\Axis.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex" + +functions: + void Precache(void) + { + PrecacheSound( SOUND_TICK); + CRationalEntity::Precache(); + } + + void DisplayNumber(void) + { + for( INDEX iDigit=0; iDigit<10; iDigit++) + { + CModelHolder2 *pmh = (CModelHolder2 *)&*(&m_pen0)[iDigit]; + if( pmh!=NULL && pmh->GetModelObject()!=NULL && + pmh->GetModelObject()->mo_toTexture.GetData()!=NULL) + { + // set texture animation + INDEX iOldAnim = pmh->GetModelObject()->mo_toTexture.GetAnim(); + INDEX iAnim=(INDEX(m_fNumber)&(1<>iDigit; + pmh->GetModelObject()->mo_toTexture.PlayAnim(iAnim, 0); + + // play sound + m_soSound.Set3DParameters(200.0f, 100.0f, 1.0f, + Clamp(1.0f+(m_iCountFrom-m_fNumber)/m_iCountFrom*2.0f, 1.0f, 3.0f) ); + if( iDigit==0 && iOldAnim!=iAnim /*iOldAnim==1 && iAnim==0 */&& !m_soSound.IsPlaying()) + { + PlaySound(m_soSound, SOUND_TICK, SOF_3D|SOF_VOLUMETRIC); + } + } + } + } + +procedures: + CountDown() + { + while( TRUE) + { + autowait(_pTimer->TickQuantum); + FLOAT tmNow = _pTimer->CurrentTick(); + FLOAT tmDelta = tmNow-m_tmStart; + FLOAT fSub = Clamp( tmDelta/m_fCountdownSpeed, 0.01f, 1.0f); + m_fNumber = Clamp( m_fNumber-fSub, 0.0f, FLOAT(m_iCountFrom)); + DisplayNumber(); + if( m_fNumber==0) + { + return EReturn(); + } + } + } + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + autowait(0.1f); + m_fNumber = m_iCountFrom; + DisplayNumber(); + + wait() { + on(EBegin): { + resume; + } + on (ETrigger eTrigger): { + m_fNumber = m_iCountFrom; + DisplayNumber(); + m_tmStart = _pTimer->CurrentTick(); + call CountDown(); + } + on(EReturn): { + if( m_penTarget!= NULL) + { + SendToTarget(m_penTarget, EET_TRIGGER); + } + stop; + } + } + + return; + } +}; diff --git a/Sources/EntitiesMP/Counter.h b/Sources/EntitiesMP/Counter.h new file mode 100644 index 0000000..4d69c2e --- /dev/null +++ b/Sources/EntitiesMP/Counter.h @@ -0,0 +1,55 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Counter_INCLUDED +#define _EntitiesMP_Counter_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CCounter_DLLClass; +class CCounter : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fCountdownSpeed; + CEntityPointer m_penTarget; + FLOAT m_fNumber; + FLOAT m_tmStart; + CTString m_strName; + CSoundObject m_soSound; + INDEX m_iCountFrom; + CEntityPointer m_pen0; + CEntityPointer m_pen1; + CEntityPointer m_pen2; + CEntityPointer m_pen3; + CEntityPointer m_pen4; + CEntityPointer m_pen5; + CEntityPointer m_pen6; + CEntityPointer m_pen7; + CEntityPointer m_pen8; + CEntityPointer m_pen9; + +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +void Precache(void); + +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +void DisplayNumber(void); +#define STATE_CCounter_CountDown 0x00e80000 + BOOL +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +CountDown(const CEntityEvent &__eeInput); + BOOL H0x00e80001_CountDown_01(const CEntityEvent &__eeInput); + BOOL H0x00e80002_CountDown_02(const CEntityEvent &__eeInput); + BOOL H0x00e80003_CountDown_03(const CEntityEvent &__eeInput); + BOOL H0x00e80004_CountDown_04(const CEntityEvent &__eeInput); +#define STATE_CCounter_Main 1 + BOOL +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00e80005_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00e80006_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00e80007_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00e80008_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Counter_INCLUDED diff --git a/Sources/EntitiesMP/Counter_tables.h b/Sources/EntitiesMP/Counter_tables.h new file mode 100644 index 0000000..57daa59 --- /dev/null +++ b/Sources/EntitiesMP/Counter_tables.h @@ -0,0 +1,65 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CCounter + +CEntityProperty CCounter_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e8<<8)+1, offsetof(CCounter, m_fCountdownSpeed), "Countdown speed", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e8<<8)+2, offsetof(CCounter, m_penTarget), "Zero target", 'T', C_WHITE | 0x80, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e8<<8)+3, offsetof(CCounter, m_fNumber), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e8<<8)+4, offsetof(CCounter, m_tmStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e8<<8)+5, offsetof(CCounter, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000e8<<8)+6, offsetof(CCounter, m_soSound), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000e8<<8)+7, offsetof(CCounter, m_iCountFrom), "Count start", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e8<<8)+10, offsetof(CCounter, m_pen0), "Bit 0", 0, C_RED | 0x30, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e8<<8)+11, offsetof(CCounter, m_pen1), "Bit 1", 0, C_RED | 0x30, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e8<<8)+12, offsetof(CCounter, m_pen2), "Bit 2", 0, C_RED | 0x30, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e8<<8)+13, offsetof(CCounter, m_pen3), "Bit 3", 0, C_RED | 0x30, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e8<<8)+14, offsetof(CCounter, m_pen4), "Bit 4", 0, C_RED | 0x30, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e8<<8)+15, offsetof(CCounter, m_pen5), "Bit 5", 0, C_RED | 0x30, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e8<<8)+16, offsetof(CCounter, m_pen6), "Bit 6", 0, C_RED | 0x30, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e8<<8)+17, offsetof(CCounter, m_pen7), "Bit 7", 0, C_RED | 0x30, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e8<<8)+18, offsetof(CCounter, m_pen8), "Bit 8", 0, C_RED | 0x30, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e8<<8)+19, offsetof(CCounter, m_pen9), "Bit 9", 0, C_RED | 0x30, 0), +}; +#define CCounter_propertiesct ARRAYCOUNT(CCounter_properties) + +CEntityComponent CCounter_components[] = { +#define SOUND_TICK ((0x000000e8<<8)+0) + CEntityComponent(ECT_SOUND, SOUND_TICK, "EFNM" "Sounds\\Menu\\Select.wav"), +#define MODEL_MARKER ((0x000000e8<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_MARKER ((0x000000e8<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Vector.tex"), +}; +#define CCounter_componentsct ARRAYCOUNT(CCounter_components) + +CEventHandlerEntry CCounter_handlers[] = { + {0x00e80000, -1, CEntity::pEventHandler(&CCounter:: +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +CountDown),DEBUGSTRING("CCounter::CountDown")}, + {0x00e80001, -1, CEntity::pEventHandler(&CCounter::H0x00e80001_CountDown_01), DEBUGSTRING("CCounter::H0x00e80001_CountDown_01")}, + {0x00e80002, -1, CEntity::pEventHandler(&CCounter::H0x00e80002_CountDown_02), DEBUGSTRING("CCounter::H0x00e80002_CountDown_02")}, + {0x00e80003, -1, CEntity::pEventHandler(&CCounter::H0x00e80003_CountDown_03), DEBUGSTRING("CCounter::H0x00e80003_CountDown_03")}, + {0x00e80004, -1, CEntity::pEventHandler(&CCounter::H0x00e80004_CountDown_04), DEBUGSTRING("CCounter::H0x00e80004_CountDown_04")}, + {1, -1, CEntity::pEventHandler(&CCounter:: +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Counter.es" +Main),DEBUGSTRING("CCounter::Main")}, + {0x00e80005, -1, CEntity::pEventHandler(&CCounter::H0x00e80005_Main_01), DEBUGSTRING("CCounter::H0x00e80005_Main_01")}, + {0x00e80006, -1, CEntity::pEventHandler(&CCounter::H0x00e80006_Main_02), DEBUGSTRING("CCounter::H0x00e80006_Main_02")}, + {0x00e80007, -1, CEntity::pEventHandler(&CCounter::H0x00e80007_Main_03), DEBUGSTRING("CCounter::H0x00e80007_Main_03")}, + {0x00e80008, -1, CEntity::pEventHandler(&CCounter::H0x00e80008_Main_04), DEBUGSTRING("CCounter::H0x00e80008_Main_04")}, +}; +#define CCounter_handlersct ARRAYCOUNT(CCounter_handlers) + +CEntity *CCounter_New(void) { return new CCounter; }; +void CCounter_OnInitClass(void) {}; +void CCounter_OnEndClass(void) {}; +void CCounter_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CCounter_OnWorldEnd(CWorld *pwo) {}; +void CCounter_OnWorldInit(CWorld *pwo) {}; +void CCounter_OnWorldTick(CWorld *pwo) {}; +void CCounter_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CCounter, CRationalEntity, "Counter", "Thumbnails\\Counter.tbn", 0x000000e8); +DECLARE_CTFILENAME(_fnmCCounter_tbn, "Thumbnails\\Counter.tbn"); diff --git a/Sources/EntitiesMP/CrateBus.cpp b/Sources/EntitiesMP/CrateBus.cpp new file mode 100644 index 0000000..d92015d --- /dev/null +++ b/Sources/EntitiesMP/CrateBus.cpp @@ -0,0 +1,468 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" + +#include "StdH.h" +#include "ModelsMP/CutSequences/CrateBus/CrateBus.h" +#include "ModelsMP/Enemies/Mental/Mental.h" + +#include +#include +#line 14 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" + +INDEX _aiLeftAnimations[] = { + MENTAL_ANIM_LEFTWAVE01, + MENTAL_ANIM_LEFTWAVE02, + MENTAL_ANIM_LEFTWAVE03, + MENTAL_ANIM_LEFTWAVE04, + MENTAL_ANIM_LEFTWAVE05, + MENTAL_ANIM_LEFTWAVE06 +}; + +INDEX _aiRightAnimations[] = { + MENTAL_ANIM_RIGHTWAVE01, + MENTAL_ANIM_RIGHTWAVE02, + MENTAL_ANIM_RIGHTWAVE03, + MENTAL_ANIM_RIGHTWAVE04, + MENTAL_ANIM_RIGHTWAVE05, + MENTAL_ANIM_RIGHTWAVE06, + MENTAL_ANIM_RIGHTWAVE07, + MENTAL_ANIM_RIGHTWAVE08 +}; + + CAutoPrecacheSound m_aps; + CAutoPrecacheTexture m_apt; + +#define CT_BIGHEADS 24 + +void CCrateBus::SetDefaultProperties(void) { + m_bActive = TRUE ; + m_fExplosionStretch = 1.0f; + m_tmDeath = 0.0f; + m_strName = "Crate bus"; + m_ctMentals = 0; + m_bShowTrail = FALSE ; + m_fStretch = 1.0f; + m_fnmHeadTex01 = CTString(""); + m_fnmHeadTex02 = CTString(""); + m_fnmHeadTex03 = CTString(""); + m_fnmHeadTex04 = CTString(""); + m_fnmHeadTex05 = CTString(""); + m_fnmHeadTex06 = CTString(""); + m_fnmHeadTex07 = CTString(""); + m_fnmHeadTex08 = CTString(""); + m_fnmHeadTex09 = CTString(""); + m_fnmHeadTex10 = CTString(""); + m_fnmHeadTex11 = CTString(""); + m_fnmHeadTex12 = CTString(""); + m_fnmHeadTex13 = CTString(""); + m_fnmHeadTex14 = CTString(""); + m_fnmHeadTex15 = CTString(""); + m_fnmHeadTex16 = CTString(""); + m_fnmHeadTex17 = CTString(""); + m_fnmHeadTex18 = CTString(""); + m_fnmHeadTex19 = CTString(""); + m_fnmHeadTex20 = CTString(""); + m_fnmHeadTex21 = CTString(""); + m_fnmHeadTex22 = CTString(""); + m_fnmHeadTex23 = CTString(""); + m_fnmHeadTex24 = CTString(""); + CMovableModelEntity::SetDefaultProperties(); +} + +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +void CCrateBus::Precache(void) +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_BOMB ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +PrecacheTexture (TEXTURE_HEAD ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} + +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +void CCrateBus::AddRiders() +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +GetModelObject () -> RemoveAllAttachmentModels (); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +for(INDEX i = 0;i < CT_BIGHEADS ;i ++) +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +AddAttachment (CRATEBUS_ATTACHMENT_1 + i , MODEL_MENTAL , TEXTURE_MENTAL ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CAttachmentModelObject * pamoMental = GetModelObject () -> GetAttachmentModel (CRATEBUS_ATTACHMENT_1 + i ); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +if(pamoMental == NULL ){continue ;} +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CModelObject & moMental = pamoMental -> amo_moModelObject ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +AddAttachmentToModel (this , moMental , MENTAL_ATTACHMENT_HEAD , MODEL_HEAD , TEXTURE_HEAD , 0 , 0 , 0); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CAttachmentModelObject * pamoHead = moMental . GetAttachmentModel (MENTAL_ATTACHMENT_HEAD ); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +if(pamoHead == NULL ){continue ;} +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CTFileName fnm = (& m_fnmHeadTex01 ) [ i ]; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +if(fnm != "") +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +try +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +pamoHead -> amo_moModelObject . mo_toTexture . SetData_t (fnm ); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +catch (char * strError ) +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CPrintF ("%s\n" , strError ); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +INDEX iRndLeft = IRnd () % (sizeof (_aiLeftAnimations ) / sizeof (INDEX)); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +INDEX iRndRight = IRnd () % (sizeof (_aiRightAnimations ) / sizeof (INDEX)); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +if(i & 1) +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +moMental . PlayAnim (_aiRightAnimations [ iRndRight ] , AOF_LOOPING ); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +else +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +moMental . PlayAnim (_aiLeftAnimations [ iRndLeft ] , AOF_LOOPING ); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +FLOAT tmOffsetPhase = - FRnd () * 10.0f; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +moMental . OffsetPhase (tmOffsetPhase ); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} + +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +void CCrateBus::RenderParticles(void) +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CEntity * penParent = GetParent (); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +if(m_bShowTrail && penParent != NULL ) +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +Particles_AfterBurner (penParent , 0.0f , 0.5f); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} + +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +void CCrateBus::SpawnExplosion(INDEX iCharacter,FLOAT fAddY,FLOAT fSize) +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +FLOAT3D vOffset = FLOAT3D (0 , 0 , 0); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +if(iCharacter >= 0) +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CAttachmentModelObject * pamo = GetModelObject () -> GetAttachmentModel (iCharacter ); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +if(pamo == NULL && fAddY >= 0){return ;} +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +GetModelObject () -> RemoveAttachmentModel (iCharacter ); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +m_ctMentals --; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +INDEX iX = iCharacter % 2; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +INDEX iZ = iCharacter / 2; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +vOffset = FLOAT3D (- 1.0f + iX * 2.0f , 3.0f + (FRnd ()) * 1.0f + fAddY , - 14.5f + iZ * 2.8f) * m_fStretch ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +else +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +vOffset = FLOAT3D ((FRnd () - 0.5f) * 4.0f , 3.0f + (FRnd ()) * 1.0f + fAddY , (FRnd () - 0.5f) * 36.0f) * m_fStretch ; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CPlacement3D plExplosion = GetPlacement (); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +plExplosion . pl_PositionVector = plExplosion . pl_PositionVector + vOffset ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CEntityPointer penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +ESpawnEffect eSpawnEffect ; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawnEffect . betType = BET_BOMB ; +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawnEffect . vStretch = FLOAT3D (m_fExplosionStretch , m_fExplosionStretch , m_fExplosionStretch ); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawnEffect . betType = BET_EXPLOSION_DEBRIS ; +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CEntityPointer penExplosionDebris = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +penExplosionDebris -> Initialize (eSpawnEffect ); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawnEffect . betType = BET_EXPLOSION_SMOKE ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CEntityPointer penExplosionSmoke = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +penExplosionSmoke -> Initialize (eSpawnEffect ); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} + +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CPlacement3D CCrateBus::GetLerpedPlacement(void)const +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +return CEntity :: GetLerpedPlacement (); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +BOOL CCrateBus:: +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +Die(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCrateBus_Die + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCrateBus::Die expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , itenChild ){ +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +itenChild -> SendEvent (ERangeModelDestruction ()); +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +}} +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +for(INDEX iChar = 0;iChar < CT_BIGHEADS ;iChar += 1) +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +INDEX iX = iChar % 2; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +INDEX iZ = iChar / 2; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +FLOAT fAddY = 1.0f * m_fStretch ; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +FLOAT3D vOffset = FLOAT3D (- 1.0f + iX * 2.0f , 3.0f + (FRnd ()) * 1.0f + fAddY , - 14.5f + iZ * 2.8f) * m_fStretch ; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +FLOAT3D vPos = GetPlacement () . pl_PositionVector + vOffset ; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CEntityPointer penDebris = GetWorld () -> CreateEntity_t (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0)) , +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CTFILENAME ("Classes\\Debris.ecl")); +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +ESpawnDebris eSpawn ; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . bImmaterialASAP = FALSE ; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . fDustStretch = 4.0f; +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . bCustomShading = FALSE ; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . colDebris = C_WHITE | CT_OPAQUE ; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . Eeibt = EIBT_FLESH ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . dptParticles = DPT_AFTERBURNER ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . betStain = BET_BLOODSTAINGROW ; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . pmd = GetModelDataForComponent (MODEL_HEAD ); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . ptd = GetTextureDataForComponent (TEXTURE_HEAD ); +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . ptdRefl = NULL ; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . ptdSpec = NULL ; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . ptdBump = NULL ; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . iModelAnim = 0; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . fSize = m_fStretch ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . vStretch = FLOAT3D (1 , 1 , 1); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +eSpawn . penFallFXPapa = NULL ; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +penDebris -> Initialize (eSpawn ); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +FLOAT3D vSpeed = FLOAT3D (FRnd () - 0.5f , 0.25f + FRnd () * 0.75f , FRnd () - 0.5f) * 60.0f; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +FLOAT3D vRot = FLOAT3D (FRnd () - 0.5f , FRnd () - 0.5f , FRnd () - 0.5f) * 200.0f; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +((CMovableEntity &) * penDebris ) . LaunchAsFreeProjectile (vSpeed , NULL ); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +((CMovableEntity &) * penDebris ) . SetDesiredRotation (vRot ); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +GetModelObject () -> RemoveAttachmentModel (iChar ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{for(INDEX iChar = 0;iChar < CT_BIGHEADS ;iChar += 3) +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +SpawnExplosion (iChar , - 2.0f , 4.0f); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +}} +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +SwitchToEditorModel (); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +SetTimerAfter(2.0f); +Jump(STATE_CURRENT, 0x01600001, FALSE, EBegin());return TRUE;}BOOL CCrateBus::H0x01600001_Die_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01600001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01600002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCrateBus::H0x01600002_Die_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01600002 +; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +Destroy (); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +Return(STATE_CURRENT,EVoid()); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCrateBus:: +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCrateBus_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCrateBus::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +if(m_bActive ) +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +InitAsModel (); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +else +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +InitAsEditorModel (); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +SetModel (MODEL_CRATE_BUS ); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +SetModelMainTexture (TEXTURE_CRATE_BUS ); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +m_bShowTrail = FALSE ; +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +AddRiders (); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fStretch , m_fStretch , m_fStretch )); +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +ModelChangeNotify (); +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x01600003, FALSE, EBegin());return TRUE;}BOOL CCrateBus::H0x01600003_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01600003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01600004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCrateBus::H0x01600004_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01600004 +; +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CEntity * penParent = GetParent (); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +if(penParent != NULL ) +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{ +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +Particles_AfterBurner_Prepare (penParent ); +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +} +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01600005, FALSE, EBegin());return TRUE;}BOOL CCrateBus::H0x01600005_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01600005 +switch(__eeInput.ee_slEvent) +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +return TRUE; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +}ASSERT(FALSE);break;case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +SwitchToModel (); +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +m_bActive = TRUE ; +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +return TRUE; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +SwitchToEditorModel (); +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +m_bActive = FALSE ; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +return TRUE; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnvironmentStart):{const EEnvironmentStart&e= (EEnvironmentStart&)__eeInput; + +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +m_bShowTrail = TRUE ; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +return TRUE; +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +Jump(STATE_CURRENT, STATE_CCrateBus_Die, TRUE, EVoid());return TRUE; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +return TRUE; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +}ASSERT(FALSE);break;default:{ +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +return TRUE; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +}ASSERT(FALSE);break; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +}return TRUE;}BOOL CCrateBus::H0x01600006_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01600006 +; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/CrateBus.es b/Sources/EntitiesMP/CrateBus.es new file mode 100644 index 0000000..454b54f --- /dev/null +++ b/Sources/EntitiesMP/CrateBus.es @@ -0,0 +1,340 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +352 +%{ +#include "StdH.h" +#include "ModelsMP/CutSequences/CrateBus/CrateBus.h" +#include "ModelsMP/Enemies/Mental/Mental.h" +%} + +uses "EntitiesMP/SpawnerProjectile"; +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/BasicEffects"; + +%{ +INDEX _aiLeftAnimations[] = { + MENTAL_ANIM_LEFTWAVE01, + MENTAL_ANIM_LEFTWAVE02, + MENTAL_ANIM_LEFTWAVE03, + MENTAL_ANIM_LEFTWAVE04, + MENTAL_ANIM_LEFTWAVE05, + MENTAL_ANIM_LEFTWAVE06 +}; + +INDEX _aiRightAnimations[] = { + MENTAL_ANIM_RIGHTWAVE01, + MENTAL_ANIM_RIGHTWAVE02, + MENTAL_ANIM_RIGHTWAVE03, + MENTAL_ANIM_RIGHTWAVE04, + MENTAL_ANIM_RIGHTWAVE05, + MENTAL_ANIM_RIGHTWAVE06, + MENTAL_ANIM_RIGHTWAVE07, + MENTAL_ANIM_RIGHTWAVE08 +}; + + CAutoPrecacheSound m_aps; + CAutoPrecacheTexture m_apt; + +#define CT_BIGHEADS 24 +%} + +class CCrateBus: CMovableModelEntity { +name "CrateBus"; +thumbnail "Thumbnails\\Mental.tbn"; +features "IsTargetable", "HasName", "IsImportant"; + +properties: + 1 BOOL m_bActive "Active" = TRUE, + 2 FLOAT m_fExplosionStretch "Explosion Stretch" 'E' = 1.0f, + 3 FLOAT m_tmDeath = 0.0f, + 4 CTString m_strName "Name" 'N' = "Crate bus", + 5 INDEX m_ctMentals=0, + 6 BOOL m_bShowTrail=FALSE, + 7 FLOAT m_fStretch "Stretch" 'S' = 1.0f, + 11 CTFileName m_fnmHeadTex01 "Head texture 01" 'H' = CTString(""), + 12 CTFileName m_fnmHeadTex02 "Head texture 02" = CTString(""), + 13 CTFileName m_fnmHeadTex03 "Head texture 03" = CTString(""), + 14 CTFileName m_fnmHeadTex04 "Head texture 04" = CTString(""), + 15 CTFileName m_fnmHeadTex05 "Head texture 05" = CTString(""), + 16 CTFileName m_fnmHeadTex06 "Head texture 06" = CTString(""), + 17 CTFileName m_fnmHeadTex07 "Head texture 07" = CTString(""), + 18 CTFileName m_fnmHeadTex08 "Head texture 08" = CTString(""), + 19 CTFileName m_fnmHeadTex09 "Head texture 09" = CTString(""), + 20 CTFileName m_fnmHeadTex10 "Head texture 10" = CTString(""), + 21 CTFileName m_fnmHeadTex11 "Head texture 11" = CTString(""), + 22 CTFileName m_fnmHeadTex12 "Head texture 12" = CTString(""), + 23 CTFileName m_fnmHeadTex13 "Head texture 13" = CTString(""), + 24 CTFileName m_fnmHeadTex14 "Head texture 14" = CTString(""), + 25 CTFileName m_fnmHeadTex15 "Head texture 15" = CTString(""), + 26 CTFileName m_fnmHeadTex16 "Head texture 16" = CTString(""), + 27 CTFileName m_fnmHeadTex17 "Head texture 17" = CTString(""), + 28 CTFileName m_fnmHeadTex18 "Head texture 18" = CTString(""), + 29 CTFileName m_fnmHeadTex19 "Head texture 19" = CTString(""), + 30 CTFileName m_fnmHeadTex20 "Head texture 20" = CTString(""), + 31 CTFileName m_fnmHeadTex21 "Head texture 21" = CTString(""), + 32 CTFileName m_fnmHeadTex22 "Head texture 22" = CTString(""), + 33 CTFileName m_fnmHeadTex23 "Head texture 23" = CTString(""), + 34 CTFileName m_fnmHeadTex24 "Head texture 24" = CTString(""), + +components: + 1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 2 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 3 class CLASS_SPAWNER_PROJECTILE "Classes\\SpawnerProjectile.ecl", + +// ************** DATA ************** + 10 model MODEL_MENTAL "ModelsMP\\Enemies\\Mental\\Mental.mdl", + 11 texture TEXTURE_MENTAL "ModelsMP\\Enemies\\Mental\\Mental.tex", + 12 model MODEL_CRATE_BUS "ModelsMP\\CutSequences\\CrateBus\\CrateBus.mdl", + 13 texture TEXTURE_CRATE_BUS "ModelsMP\\CutSequences\\CrateBus\\CrateBus.tex", + 14 model MODEL_HEAD "ModelsMP\\Enemies\\Mental\\Head.mdl", + 15 texture TEXTURE_HEAD "ModelsMP\\Enemies\\Mental\\Head.tex", + +functions: + + void Precache(void) + { + PrecacheClass(CLASS_BASIC_EFFECT, BET_BOMB); + PrecacheTexture(TEXTURE_HEAD); + }; + + void AddRiders() + { + GetModelObject()->RemoveAllAttachmentModels(); + for( INDEX i=0; iGetAttachmentModel(CRATEBUS_ATTACHMENT_1+i); + if( pamoMental==NULL) { continue; } + CModelObject &moMental=pamoMental->amo_moModelObject; + AddAttachmentToModel(this, moMental, MENTAL_ATTACHMENT_HEAD, MODEL_HEAD, TEXTURE_HEAD, 0, 0, 0); + CAttachmentModelObject *pamoHead = moMental.GetAttachmentModel(MENTAL_ATTACHMENT_HEAD); + if (pamoHead==NULL) { continue; } + CTFileName fnm=(&m_fnmHeadTex01)[i]; + if (fnm!="") + { + // try to + try + { + pamoHead->amo_moModelObject.mo_toTexture.SetData_t(fnm); + } + // if anything failed + catch (char *strError) + { + // report error + CPrintF("%s\n", strError); + } + } + INDEX iRndLeft=IRnd()%(sizeof(_aiLeftAnimations)/sizeof(INDEX)); + INDEX iRndRight=IRnd()%(sizeof(_aiRightAnimations)/sizeof(INDEX)); + if(i&1) + { + moMental.PlayAnim(_aiRightAnimations[iRndRight], AOF_LOOPING); + } + else + { + moMental.PlayAnim(_aiLeftAnimations[iRndLeft], AOF_LOOPING); + } + FLOAT tmOffsetPhase=-FRnd()*10.0f; + moMental.OffsetPhase(tmOffsetPhase); + } + } + + // particles + void RenderParticles(void) + { + CEntity *penParent=GetParent(); + if( m_bShowTrail && penParent!=NULL) + { + Particles_AfterBurner( penParent, 0.0f, 0.5f); + //Particles_RocketTrail(penParent, 25.0f); + } + } + + void SpawnExplosion(INDEX iCharacter, FLOAT fAddY, FLOAT fSize) + { + FLOAT3D vOffset=FLOAT3D(0,0,0); + // spawn explosion + if(iCharacter>=0) + { + CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel(iCharacter); + if( pamo==NULL && fAddY>=0) {return;} + GetModelObject()->RemoveAttachmentModel(iCharacter); + m_ctMentals--; + // character pos + INDEX iX=iCharacter%2; + INDEX iZ=iCharacter/2; + vOffset=FLOAT3D(-1.0f+iX*2.0f, 3.0f+(FRnd())*1.0f+fAddY, -14.5f+iZ*2.8f)*m_fStretch; + } + else + { + // rnd pos + vOffset=FLOAT3D( (FRnd()-0.5f)*4.0f, 3.0f+(FRnd())*1.0f+fAddY, (FRnd()-0.5f)*36.0f)*m_fStretch; + } + + CPlacement3D plExplosion = GetPlacement(); + plExplosion.pl_PositionVector=plExplosion.pl_PositionVector+vOffset; + CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_BOMB; + eSpawnEffect.vStretch = FLOAT3D(m_fExplosionStretch,m_fExplosionStretch,m_fExplosionStretch); + penExplosion->Initialize(eSpawnEffect); + + // explosion debris + eSpawnEffect.betType = BET_EXPLOSION_DEBRIS; + CEntityPointer penExplosionDebris = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosionDebris->Initialize(eSpawnEffect); + + // explosion smoke + eSpawnEffect.betType = BET_EXPLOSION_SMOKE; + CEntityPointer penExplosionSmoke = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosionSmoke->Initialize(eSpawnEffect); + } + + CPlacement3D GetLerpedPlacement(void) const + { + return CEntity::GetLerpedPlacement(); // we never move anyway, so let's be able to be parented + } + +procedures: + Die() + { + // for each child of this entity + {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { + // send it destruction event + itenChild->SendEvent(ERangeModelDestruction()); + }} + + /* + m_tmDeath=_pTimer->CurrentTick(); + m_ctMentals=TEXTURE_HEAD20-TEXTURE_HEAD01; + while((_pTimer->CurrentTick()0)) + { + autowait(_pTimer->TickQuantum); + SpawnExplosion(IRnd()%(TEXTURE_HEAD20-TEXTURE_HEAD01),0,1); + if(IRnd()%1) { SpawnExplosion(-1,0,1);} + if(IRnd()%1) {SpawnExplosion(IRnd()%(TEXTURE_HEAD20-TEXTURE_HEAD01),0,1);} + if(IRnd()%1) { SpawnExplosion(-1,0,1);} + } + */ + + for(INDEX iChar=0; iCharCreateEntity_t( CPlacement3D(vPos, ANGLE3D(0,0,0)), + CTFILENAME("Classes\\Debris.ecl")); + // prepare parameters + ESpawnDebris eSpawn; + eSpawn.bImmaterialASAP=FALSE; + eSpawn.fDustStretch=4.0f; + eSpawn.bCustomShading=FALSE; + eSpawn.colDebris = C_WHITE|CT_OPAQUE; + eSpawn.Eeibt = EIBT_FLESH; + eSpawn.dptParticles = DPT_AFTERBURNER; + eSpawn.betStain = BET_BLOODSTAINGROW; + eSpawn.pmd = GetModelDataForComponent(MODEL_HEAD); + eSpawn.ptd = GetTextureDataForComponent(TEXTURE_HEAD); + eSpawn.ptdRefl = NULL; + eSpawn.ptdSpec = NULL; + eSpawn.ptdBump = NULL; + eSpawn.iModelAnim = 0; + eSpawn.fSize = m_fStretch; + eSpawn.vStretch = FLOAT3D(1,1,1); + eSpawn.penFallFXPapa=NULL; + // initialize it + penDebris->Initialize(eSpawn); + + // speed it up + FLOAT3D vSpeed = FLOAT3D( FRnd()-0.5f, 0.25f+FRnd()*0.75f, FRnd()-0.5f)*60.0f; + FLOAT3D vRot = FLOAT3D( FRnd()-0.5f, FRnd()-0.5f, FRnd()-0.5f)*200.0f; + ((CMovableEntity&)*penDebris).LaunchAsFreeProjectile( vSpeed, NULL); + ((CMovableEntity&)*penDebris).SetDesiredRotation( vRot); + + GetModelObject()->RemoveAttachmentModel(iChar); + } + + {for(INDEX iChar=0; iCharStretchModel( FLOAT3D(m_fStretch,m_fStretch,m_fStretch)); + ModelChangeNotify(); + + autowait(0.1f); + + CEntity *penParent=GetParent(); + if( penParent!=NULL) + { + //Particles_RocketTrail_Prepare(penParent); + Particles_AfterBurner_Prepare(penParent); + } + + wait() + { + // on the beginning + on(EBegin): { + resume; + } + // activate/deactivate shows/hides model + on (EActivate): { + SwitchToModel(); + m_bActive = TRUE; + resume; + } + on (EDeactivate): { + SwitchToEditorModel(); + m_bActive = FALSE; + resume; + } + on (EEnvironmentStart): { + m_bShowTrail=TRUE; + resume; + } + // when dead + on(EStop): { + jump Die(); + resume; + } + otherwise(): { + resume; + } + }; + }; +}; + diff --git a/Sources/EntitiesMP/CrateBus.h b/Sources/EntitiesMP/CrateBus.h new file mode 100644 index 0000000..342b565 --- /dev/null +++ b/Sources/EntitiesMP/CrateBus.h @@ -0,0 +1,78 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_CrateBus_INCLUDED +#define _EntitiesMP_CrateBus_INCLUDED 1 +#include +#include +#include +extern "C" DECL_DLL CDLLEntityClass CCrateBus_DLLClass; +class CCrateBus : public CMovableModelEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bActive; + FLOAT m_fExplosionStretch; + FLOAT m_tmDeath; + CTString m_strName; + INDEX m_ctMentals; + BOOL m_bShowTrail; + FLOAT m_fStretch; + CTFileName m_fnmHeadTex01; + CTFileName m_fnmHeadTex02; + CTFileName m_fnmHeadTex03; + CTFileName m_fnmHeadTex04; + CTFileName m_fnmHeadTex05; + CTFileName m_fnmHeadTex06; + CTFileName m_fnmHeadTex07; + CTFileName m_fnmHeadTex08; + CTFileName m_fnmHeadTex09; + CTFileName m_fnmHeadTex10; + CTFileName m_fnmHeadTex11; + CTFileName m_fnmHeadTex12; + CTFileName m_fnmHeadTex13; + CTFileName m_fnmHeadTex14; + CTFileName m_fnmHeadTex15; + CTFileName m_fnmHeadTex16; + CTFileName m_fnmHeadTex17; + CTFileName m_fnmHeadTex18; + CTFileName m_fnmHeadTex19; + CTFileName m_fnmHeadTex20; + CTFileName m_fnmHeadTex21; + CTFileName m_fnmHeadTex22; + CTFileName m_fnmHeadTex23; + CTFileName m_fnmHeadTex24; + +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +void Precache(void); + +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +void AddRiders(); + +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +void RenderParticles(void); + +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +void SpawnExplosion(INDEX iCharacter,FLOAT fAddY,FLOAT fSize); + +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +CPlacement3D GetLerpedPlacement(void)const; +#define STATE_CCrateBus_Die 0x01600000 + BOOL +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +Die(const CEntityEvent &__eeInput); + BOOL H0x01600001_Die_01(const CEntityEvent &__eeInput); + BOOL H0x01600002_Die_02(const CEntityEvent &__eeInput); +#define STATE_CCrateBus_Main 1 + BOOL +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01600003_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01600004_Main_02(const CEntityEvent &__eeInput); + BOOL H0x01600005_Main_03(const CEntityEvent &__eeInput); + BOOL H0x01600006_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_CrateBus_INCLUDED diff --git a/Sources/EntitiesMP/CrateBus_tables.h b/Sources/EntitiesMP/CrateBus_tables.h new file mode 100644 index 0000000..4d1e7c4 --- /dev/null +++ b/Sources/EntitiesMP/CrateBus_tables.h @@ -0,0 +1,89 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CCrateBus + +CEntityProperty CCrateBus_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000160<<8)+1, offsetof(CCrateBus, m_bActive), "Active", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000160<<8)+2, offsetof(CCrateBus, m_fExplosionStretch), "Explosion Stretch", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000160<<8)+3, offsetof(CCrateBus, m_tmDeath), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000160<<8)+4, offsetof(CCrateBus, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000160<<8)+5, offsetof(CCrateBus, m_ctMentals), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000160<<8)+6, offsetof(CCrateBus, m_bShowTrail), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000160<<8)+7, offsetof(CCrateBus, m_fStretch), "Stretch", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+11, offsetof(CCrateBus, m_fnmHeadTex01), "Head texture 01", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+12, offsetof(CCrateBus, m_fnmHeadTex02), "Head texture 02", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+13, offsetof(CCrateBus, m_fnmHeadTex03), "Head texture 03", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+14, offsetof(CCrateBus, m_fnmHeadTex04), "Head texture 04", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+15, offsetof(CCrateBus, m_fnmHeadTex05), "Head texture 05", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+16, offsetof(CCrateBus, m_fnmHeadTex06), "Head texture 06", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+17, offsetof(CCrateBus, m_fnmHeadTex07), "Head texture 07", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+18, offsetof(CCrateBus, m_fnmHeadTex08), "Head texture 08", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+19, offsetof(CCrateBus, m_fnmHeadTex09), "Head texture 09", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+20, offsetof(CCrateBus, m_fnmHeadTex10), "Head texture 10", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+21, offsetof(CCrateBus, m_fnmHeadTex11), "Head texture 11", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+22, offsetof(CCrateBus, m_fnmHeadTex12), "Head texture 12", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+23, offsetof(CCrateBus, m_fnmHeadTex13), "Head texture 13", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+24, offsetof(CCrateBus, m_fnmHeadTex14), "Head texture 14", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+25, offsetof(CCrateBus, m_fnmHeadTex15), "Head texture 15", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+26, offsetof(CCrateBus, m_fnmHeadTex16), "Head texture 16", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+27, offsetof(CCrateBus, m_fnmHeadTex17), "Head texture 17", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+28, offsetof(CCrateBus, m_fnmHeadTex18), "Head texture 18", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+29, offsetof(CCrateBus, m_fnmHeadTex19), "Head texture 19", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+30, offsetof(CCrateBus, m_fnmHeadTex20), "Head texture 20", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+31, offsetof(CCrateBus, m_fnmHeadTex21), "Head texture 21", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+32, offsetof(CCrateBus, m_fnmHeadTex22), "Head texture 22", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+33, offsetof(CCrateBus, m_fnmHeadTex23), "Head texture 23", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000160<<8)+34, offsetof(CCrateBus, m_fnmHeadTex24), "Head texture 24", 0, 0x7F0000FFUL, 0), +}; +#define CCrateBus_propertiesct ARRAYCOUNT(CCrateBus_properties) + +CEntityComponent CCrateBus_components[] = { +#define CLASS_BASIC_EFFECT ((0x00000160<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_PROJECTILE ((0x00000160<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_SPAWNER_PROJECTILE ((0x00000160<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_SPAWNER_PROJECTILE, "EFNM" "Classes\\SpawnerProjectile.ecl"), +#define MODEL_MENTAL ((0x00000160<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_MENTAL, "EFNM" "ModelsMP\\Enemies\\Mental\\Mental.mdl"), +#define TEXTURE_MENTAL ((0x00000160<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_MENTAL, "EFNM" "ModelsMP\\Enemies\\Mental\\Mental.tex"), +#define MODEL_CRATE_BUS ((0x00000160<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_CRATE_BUS, "EFNM" "ModelsMP\\CutSequences\\CrateBus\\CrateBus.mdl"), +#define TEXTURE_CRATE_BUS ((0x00000160<<8)+13) + CEntityComponent(ECT_TEXTURE, TEXTURE_CRATE_BUS, "EFNM" "ModelsMP\\CutSequences\\CrateBus\\CrateBus.tex"), +#define MODEL_HEAD ((0x00000160<<8)+14) + CEntityComponent(ECT_MODEL, MODEL_HEAD, "EFNM" "ModelsMP\\Enemies\\Mental\\Head.mdl"), +#define TEXTURE_HEAD ((0x00000160<<8)+15) + CEntityComponent(ECT_TEXTURE, TEXTURE_HEAD, "EFNM" "ModelsMP\\Enemies\\Mental\\Head.tex"), +}; +#define CCrateBus_componentsct ARRAYCOUNT(CCrateBus_components) + +CEventHandlerEntry CCrateBus_handlers[] = { + {0x01600000, -1, CEntity::pEventHandler(&CCrateBus:: +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +Die),DEBUGSTRING("CCrateBus::Die")}, + {0x01600001, -1, CEntity::pEventHandler(&CCrateBus::H0x01600001_Die_01), DEBUGSTRING("CCrateBus::H0x01600001_Die_01")}, + {0x01600002, -1, CEntity::pEventHandler(&CCrateBus::H0x01600002_Die_02), DEBUGSTRING("CCrateBus::H0x01600002_Die_02")}, + {1, -1, CEntity::pEventHandler(&CCrateBus:: +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/CrateBus.es" +Main),DEBUGSTRING("CCrateBus::Main")}, + {0x01600003, -1, CEntity::pEventHandler(&CCrateBus::H0x01600003_Main_01), DEBUGSTRING("CCrateBus::H0x01600003_Main_01")}, + {0x01600004, -1, CEntity::pEventHandler(&CCrateBus::H0x01600004_Main_02), DEBUGSTRING("CCrateBus::H0x01600004_Main_02")}, + {0x01600005, -1, CEntity::pEventHandler(&CCrateBus::H0x01600005_Main_03), DEBUGSTRING("CCrateBus::H0x01600005_Main_03")}, + {0x01600006, -1, CEntity::pEventHandler(&CCrateBus::H0x01600006_Main_04), DEBUGSTRING("CCrateBus::H0x01600006_Main_04")}, +}; +#define CCrateBus_handlersct ARRAYCOUNT(CCrateBus_handlers) + +CEntity *CCrateBus_New(void) { return new CCrateBus; }; +void CCrateBus_OnInitClass(void) {}; +void CCrateBus_OnEndClass(void) {}; +void CCrateBus_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CCrateBus_OnWorldEnd(CWorld *pwo) {}; +void CCrateBus_OnWorldInit(CWorld *pwo) {}; +void CCrateBus_OnWorldTick(CWorld *pwo) {}; +void CCrateBus_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CCrateBus, CMovableModelEntity, "CrateBus", "Thumbnails\\Mental.tbn", 0x00000160); +DECLARE_CTFILENAME(_fnmCCrateBus_tbn, "Thumbnails\\Mental.tbn"); diff --git a/Sources/EntitiesMP/CrateRider.cpp b/Sources/EntitiesMP/CrateRider.cpp new file mode 100644 index 0000000..b5208cd --- /dev/null +++ b/Sources/EntitiesMP/CrateRider.cpp @@ -0,0 +1,275 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" + +#include "StdH.h" +#include "Models/Enemies/Mental/Mental.h" +#include "Models/CutSequences/CrateRider/Crate.h" + +#include +#include +#line 13 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" + +// info structure +static EntityInfo eiCrate = { + EIBT_FLESH, 500.0f, + 0.0f, 1.5f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +#define GREET_SENSE_RANGE 10.0f +#define GREET_SENSE_DELAY 10.0f + + +void CCrateRider::SetDefaultProperties(void) { + m_fnmHeadTex1 = CTString(""); + m_fnmHeadTex2 = CTString(""); + m_fnmDriveSnd = CTString(""); + CEnemyBase::SetDefaultProperties(); +} + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void * CCrateRider::GetEntityInfo(void) +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +{ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +return & eiCrate ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void CCrateRider::Precache(void) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +{ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +CEnemyBase :: Precache (); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +PrecacheClass (CLASS_DEBRIS ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_apt1 . Precache (m_fnmHeadTex1 ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_apt2 . Precache (m_fnmHeadTex2 ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_aps . Precache (m_fnmDriveSnd ); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +INDEX CCrateRider::AnimForDamage(FLOAT fDamage) { +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +INDEX iAnim ; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +iAnim = 0; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +StartModelAnim (iAnim , 0); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +return iAnim ; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +INDEX CCrateRider::AnimForDeath(void) { +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +INDEX iAnim ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +iAnim = 0; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +StartModelAnim (iAnim , 0); +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +return iAnim ; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void CCrateRider::DeathNotify(void) { +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +en_fDensity = 500.0f; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void CCrateRider::StandingAnim(void) { +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +StartModelAnim (CRATE_ANIM_DEFAULT , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +CModelObject * pmo0 = & (GetModelObject () -> GetAttachmentModel (0) -> amo_moModelObject ); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +pmo0 -> PlayAnim (MENTAL_ANIM_CRATEANIMLEFTSEATING , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE ); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +CModelObject * pmo1 = & (GetModelObject () -> GetAttachmentModel (1) -> amo_moModelObject ); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +pmo1 -> PlayAnim (MENTAL_ANIM_CRATEANIMRIGHTSEATING , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_soSound . Stop (); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void CCrateRider::WalkingAnim(void) { +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +RunningAnim (); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +StartModelAnim (CRATE_ANIM_DRIVE , AOF_LOOPING | AOF_NORESTART ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void CCrateRider::RunningAnim(void) +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +{ +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +if(m_fnmDriveSnd != ""){ +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +PlaySound (m_soSound , m_fnmDriveSnd , SOF_3D ); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +CModelObject * pmo0 = & (GetModelObject () -> GetAttachmentModel (0) -> amo_moModelObject ); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +pmo0 -> PlayAnim (MENTAL_ANIM_CRATEANIMLEFT , AOF_LOOPING | AOF_NORESTART ); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +CModelObject * pmo1 = & (GetModelObject () -> GetAttachmentModel (1) -> amo_moModelObject ); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +pmo1 -> PlayAnim (MENTAL_ANIM_CRATEANIMRIGHT , AOF_LOOPING | AOF_NORESTART ); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +StartModelAnim (CRATE_ANIM_DRIVE , AOF_LOOPING | AOF_NORESTART ); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void CCrateRider::RotatingAnim(void) { +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +RunningAnim (); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void CCrateRider::IdleSound(void) { +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void CCrateRider::SightSound(void) { +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void CCrateRider::WoundSound(void) { +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void CCrateRider::DeathSound(void) { +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} + +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void CCrateRider::AddRider(INDEX i,const CTFileName & fnmHead) +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +{ +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +AddAttachment (i , MODEL_MENTAL , TEXTURE_MENTAL ); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +CModelObject * pmoMain = & (GetModelObject () -> GetAttachmentModel (i ) -> amo_moModelObject ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +pmoMain -> PlayAnim (i == 0 ? MENTAL_ANIM_CRATEANIMLEFT : MENTAL_ANIM_CRATEANIMRIGHT , AOF_LOOPING ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +AddAttachmentToModel (this , * pmoMain , 0 , MODEL_HEAD , TEXTURE_MENTAL , 0 , 0 , 0); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +CModelObject * pmoHead = & (pmoMain -> GetAttachmentModel (0) -> amo_moModelObject ); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +if(fnmHead != ""){ +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +try { +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +pmoHead -> mo_toTexture . SetData_t (fnmHead ); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +}catch (char * strError ){ +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +CPrintF ("%s\n" , strError ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +} +BOOL CCrateRider:: +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCrateRider_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCrateRider::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +InitAsModel (); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +SetCollisionFlags (ECF_MODEL ); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +SetHealth (1.0f); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fMaxHealth = 1.0f; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +en_tmMaxHoldBreath = 5.0f; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +en_fDensity = 2000.0f; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fBlowUpSize = 2.0f; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +SetModel (MODEL_CRATE ); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +SetModelMainTexture (TEXTURE_CRATE ); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +AddRider (0 , m_fnmHeadTex1 ); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +AddRider (1 , m_fnmHeadTex2 ); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fWalkSpeed = +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fAttackRunSpeed = +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fCloseRunSpeed = 1.0f; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_aWalkRotateSpeed = AngleDeg (30.0f); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_aAttackRotateSpeed = AngleDeg (30); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_aCloseRotateSpeed = AngleDeg (30); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fAttackDistance = 50.0f; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fCloseDistance = 0.0f; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fStopDistance = 5.0f; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fAttackFireTime = 2.0f; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fCloseFireTime = 1.0f; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fIgnoreRange = 200.0f; +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fBlowUpAmount = 0.0f; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fBodyParts = 4; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_fDamageWounded = 1.0f; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_iScore = 0; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_bBlind = TRUE ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +m_bRobotBlowup = TRUE ; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +const FLOAT fSize = 0.6f; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +GetModelObject () -> StretchModel (FLOAT3D (fSize , fSize , fSize )); +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +ModelChangeNotify (); +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +StandingAnim (); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/CrateRider.es b/Sources/EntitiesMP/CrateRider.es new file mode 100644 index 0000000..8902626 --- /dev/null +++ b/Sources/EntitiesMP/CrateRider.es @@ -0,0 +1,216 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +341 +%{ +#include "StdH.h" +#include "Models/Enemies/Mental/Mental.h" +#include "Models/CutSequences/CrateRider/Crate.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/BasicEffects"; + +%{ +// info structure +static EntityInfo eiCrate = { + EIBT_FLESH, 500.0f, + 0.0f, 1.5f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +#define GREET_SENSE_RANGE 10.0f +#define GREET_SENSE_DELAY 10.0f + +%} + +class CCrateRider: CEnemyBase { +name "CrateRider"; +thumbnail "Thumbnails\\Mental.tbn"; + +properties: + // class internal + 1 CTFileName m_fnmHeadTex1 "Head texture1" 'H' = CTString(""), + 2 CTFileName m_fnmHeadTex2 "Head texture2" = CTString(""), + 3 CTFileName m_fnmDriveSnd "Drive sound" 'S' = CTString(""), + + { + CAutoPrecacheSound m_aps; + CAutoPrecacheTexture m_apt1; + CAutoPrecacheTexture m_apt2; + } + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + 2 class CLASS_DEBRIS "Classes\\Debris.ecl", + 3 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + 4 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + +// ************** DATA ************** + 10 model MODEL_MENTAL "Models\\Enemies\\Mental\\Mental.mdl", + 11 texture TEXTURE_MENTAL "Models\\Enemies\\Mental\\Mental.tex", + 12 model MODEL_HEAD "Models\\Enemies\\Mental\\Head.mdl", + 13 model MODEL_CRATE "Models\\CutSequences\\CrateRider\\Crate.mdl", + 14 texture TEXTURE_CRATE "Models\\CutSequences\\CrateRider\\Crate.tex", + 15 texture TEXTURE_BUMP "Models\\CutSequences\\Bridge\\BridgeBump.tex", + +functions: + /* Entity info */ + void *GetEntityInfo(void) + { + return &eiCrate; + }; + + void Precache(void) + { + CEnemyBase::Precache(); + + PrecacheClass(CLASS_DEBRIS); + + m_apt1.Precache(m_fnmHeadTex1); + m_apt2.Precache(m_fnmHeadTex2); + m_aps.Precache(m_fnmDriveSnd); + }; + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim; + iAnim = 0; + StartModelAnim(iAnim, 0); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + INDEX iAnim; + iAnim = 0; + StartModelAnim(iAnim, 0); + return iAnim; + }; + + void DeathNotify(void) { +// ChangeCollisionBoxIndexWhenPossible(HEADMAN_COLLISION_BOX_DEATH); + en_fDensity = 500.0f; + }; + + // virtual anim functions + void StandingAnim(void) { + StartModelAnim(CRATE_ANIM_DEFAULT, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); + + CModelObject *pmo0 = &(GetModelObject()->GetAttachmentModel(0)->amo_moModelObject); + pmo0->PlayAnim(MENTAL_ANIM_CRATEANIMLEFTSEATING, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); + CModelObject *pmo1 = &(GetModelObject()->GetAttachmentModel(1)->amo_moModelObject); + pmo1->PlayAnim(MENTAL_ANIM_CRATEANIMRIGHTSEATING, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); + + m_soSound.Stop(); + }; + void WalkingAnim(void) { + RunningAnim(); + StartModelAnim(CRATE_ANIM_DRIVE, AOF_LOOPING|AOF_NORESTART); + }; + void RunningAnim(void) + { + if (m_fnmDriveSnd!="") { + PlaySound(m_soSound, m_fnmDriveSnd, SOF_3D); + } + CModelObject *pmo0 = &(GetModelObject()->GetAttachmentModel(0)->amo_moModelObject); + pmo0->PlayAnim(MENTAL_ANIM_CRATEANIMLEFT, AOF_LOOPING|AOF_NORESTART); + CModelObject *pmo1 = &(GetModelObject()->GetAttachmentModel(1)->amo_moModelObject); + pmo1->PlayAnim(MENTAL_ANIM_CRATEANIMRIGHT, AOF_LOOPING|AOF_NORESTART); + + StartModelAnim(CRATE_ANIM_DRIVE, AOF_LOOPING|AOF_NORESTART); + }; + void RotatingAnim(void) { + RunningAnim(); + }; + + // virtual sound functions + void IdleSound(void) { +// PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + + void SightSound(void) { +// PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { +// PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { +// PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + void AddRider(INDEX i, const CTFileName &fnmHead) + { + AddAttachment(i, MODEL_MENTAL, TEXTURE_MENTAL); + CModelObject *pmoMain = &(GetModelObject()->GetAttachmentModel(i)->amo_moModelObject); +// pmoMain->PlayAnim(i==0 ? MENTAL_ANIM_CRATEANIMLEFTSEATING : MENTAL_ANIM_CRATEANIMRIGHTSEATING, AOF_LOOPING); + pmoMain->PlayAnim(i==0 ? MENTAL_ANIM_CRATEANIMLEFT: MENTAL_ANIM_CRATEANIMRIGHT, AOF_LOOPING); + AddAttachmentToModel(this, *pmoMain, 0, MODEL_HEAD, TEXTURE_MENTAL, 0, 0, 0); + CModelObject *pmoHead = &(pmoMain->GetAttachmentModel(0)->amo_moModelObject); + if (fnmHead!="") { + // try to + try { + pmoHead->mo_toTexture.SetData_t(fnmHead); + // if anything failed + } catch (char *strError) { + // report error + CPrintF("%s\n", strError); + } + } + } + +procedures: + + /************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + SetHealth(1.0f); + m_fMaxHealth = 1.0f; + en_tmMaxHoldBreath = 5.0f; + en_fDensity = 2000.0f; + m_fBlowUpSize = 2.0f; + + // set your appearance + SetModel(MODEL_CRATE); + SetModelMainTexture(TEXTURE_CRATE); + AddRider(0, m_fnmHeadTex1); + AddRider(1, m_fnmHeadTex2); + + // setup moving speed + m_fWalkSpeed = + m_fAttackRunSpeed = + m_fCloseRunSpeed = 1.0f; + m_aWalkRotateSpeed = AngleDeg(30.0f); + m_aAttackRotateSpeed = AngleDeg(30); + m_aCloseRotateSpeed = AngleDeg(30); + // setup attack distances + m_fAttackDistance = 50.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 5.0f; // greeting distance + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 200.0f; + // damage/explode properties + m_fBlowUpAmount = 0.0f; + m_fBodyParts = 4; + m_fDamageWounded = 1.0f; + m_iScore = 0; + m_bBlind = TRUE; + m_bRobotBlowup = TRUE; +// m_fSenseRange = GREET_SENSE_RANGE; + + // set stretch factors for height and width + const FLOAT fSize = 0.6f; + GetModelObject()->StretchModel(FLOAT3D(fSize, fSize, fSize)); + ModelChangeNotify(); + StandingAnim(); + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/CrateRider.h b/Sources/EntitiesMP/CrateRider.h new file mode 100644 index 0000000..f6646e0 --- /dev/null +++ b/Sources/EntitiesMP/CrateRider.h @@ -0,0 +1,66 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_CrateRider_INCLUDED +#define _EntitiesMP_CrateRider_INCLUDED 1 +#include +#include +extern "C" DECL_DLL CDLLEntityClass CCrateRider_DLLClass; +class CCrateRider : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + CTFileName m_fnmHeadTex1; + CTFileName m_fnmHeadTex2; + CTFileName m_fnmDriveSnd; +CAutoPrecacheSound m_aps; +CAutoPrecacheTexture m_apt1; +CAutoPrecacheTexture m_apt2; + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void * GetEntityInfo(void); + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void Precache(void); + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +INDEX AnimForDeath(void); + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void DeathNotify(void); + +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void StandingAnim(void); + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void WalkingAnim(void); + +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void RunningAnim(void); + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void RotatingAnim(void); + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void IdleSound(void); + +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void SightSound(void); + +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void WoundSound(void); + +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void DeathSound(void); + +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +void AddRider(INDEX i,const CTFileName & fnmHead); +#define STATE_CCrateRider_Main 1 + BOOL +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_CrateRider_INCLUDED diff --git a/Sources/EntitiesMP/CrateRider_tables.h b/Sources/EntitiesMP/CrateRider_tables.h new file mode 100644 index 0000000..fe4d528 --- /dev/null +++ b/Sources/EntitiesMP/CrateRider_tables.h @@ -0,0 +1,54 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CCrateRider + +CEntityProperty CCrateRider_properties[] = { + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000155<<8)+1, offsetof(CCrateRider, m_fnmHeadTex1), "Head texture1", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000155<<8)+2, offsetof(CCrateRider, m_fnmHeadTex2), "Head texture2", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000155<<8)+3, offsetof(CCrateRider, m_fnmDriveSnd), "Drive sound", 'S', 0x7F0000FFUL, 0), +}; +#define CCrateRider_propertiesct ARRAYCOUNT(CCrateRider_properties) + +CEntityComponent CCrateRider_components[] = { +#define CLASS_BASE ((0x00000155<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_DEBRIS ((0x00000155<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_DEBRIS, "EFNM" "Classes\\Debris.ecl"), +#define CLASS_BLOOD_SPRAY ((0x00000155<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000155<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define MODEL_MENTAL ((0x00000155<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_MENTAL, "EFNM" "Models\\Enemies\\Mental\\Mental.mdl"), +#define TEXTURE_MENTAL ((0x00000155<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_MENTAL, "EFNM" "Models\\Enemies\\Mental\\Mental.tex"), +#define MODEL_HEAD ((0x00000155<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_HEAD, "EFNM" "Models\\Enemies\\Mental\\Head.mdl"), +#define MODEL_CRATE ((0x00000155<<8)+13) + CEntityComponent(ECT_MODEL, MODEL_CRATE, "EFNM" "Models\\CutSequences\\CrateRider\\Crate.mdl"), +#define TEXTURE_CRATE ((0x00000155<<8)+14) + CEntityComponent(ECT_TEXTURE, TEXTURE_CRATE, "EFNM" "Models\\CutSequences\\CrateRider\\Crate.tex"), +#define TEXTURE_BUMP ((0x00000155<<8)+15) + CEntityComponent(ECT_TEXTURE, TEXTURE_BUMP, "EFNM" "Models\\CutSequences\\Bridge\\BridgeBump.tex"), +}; +#define CCrateRider_componentsct ARRAYCOUNT(CCrateRider_components) + +CEventHandlerEntry CCrateRider_handlers[] = { + {1, -1, CEntity::pEventHandler(&CCrateRider:: +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/CrateRider.es" +Main),DEBUGSTRING("CCrateRider::Main")}, +}; +#define CCrateRider_handlersct ARRAYCOUNT(CCrateRider_handlers) + +CEntity *CCrateRider_New(void) { return new CCrateRider; }; +void CCrateRider_OnInitClass(void) {}; +void CCrateRider_OnEndClass(void) {}; +void CCrateRider_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CCrateRider_OnWorldEnd(CWorld *pwo) {}; +void CCrateRider_OnWorldInit(CWorld *pwo) {}; +void CCrateRider_OnWorldTick(CWorld *pwo) {}; +void CCrateRider_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CCrateRider, CEnemyBase, "CrateRider", "Thumbnails\\Mental.tbn", 0x00000155); +DECLARE_CTFILENAME(_fnmCCrateRider_tbn, "Thumbnails\\Mental.tbn"); diff --git a/Sources/EntitiesMP/CreditsHolder.cpp b/Sources/EntitiesMP/CreditsHolder.cpp new file mode 100644 index 0000000..b8021d8 --- /dev/null +++ b/Sources/EntitiesMP/CreditsHolder.cpp @@ -0,0 +1,640 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" + +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" + +#include +#include +#line 10 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" + + +#define CTA_LEFT 1 +#define CTA_RIGHT 2 +#define CTA_CENTER 3 + +class CCreditEntry { +public: + CTString strTitle; + CTString strName; + CTString strQuote; + INDEX iAlign; + INDEX iX, iY; + FLOAT fRelSize; + FLOAT fWait; +}; + +static CStaticStackArray _acceEntries; +#define BLANK_TIME 1.0f + +void CCreditsHolder::SetDefaultProperties(void) { + m_strName = "Credits holder"; + m_strDescription = ""; + m_fnmMessage = CTString(""); + m_fMyTimer = 0.0f; + m_fMyTimerLast = 0.0f; + m_iTotalEntries = 0; + m_bEnd = FALSE ; + m_penEndCreditsTrigger = NULL; + m_bDataError = FALSE ; + CRationalEntity::SetDefaultProperties(); +} + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +const CTString & CCreditsHolder::GetDescription(void)const { +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +((CTString &) m_strDescription ) . PrintF ("%s" , m_fnmMessage . FileName ()); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return m_strDescription ; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} + CCreditsHolder::CCreditsHolder(void) +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +bDataLoaded = FALSE ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} + +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +BOOL CCreditsHolder::ReloadData(void) +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +m_bDataError = FALSE ; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(! Credits_On (m_fnmMessage )) +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Credits_Off (); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return FALSE ; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(! LoadFont ()) +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Credits_Off (); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return FALSE ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return TRUE ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +BOOL CCreditsHolder::LoadOneFile(const CTFileName & fnm) +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(fnm == ""){return FALSE ;} +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +try +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CTFileStream strm ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . Open_t (fnm ); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CTString strCheck ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . GetLine_t (strCheck ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strCheck . TrimSpacesRight (); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(strCheck != "CREDITS"){return FALSE ;}; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +m_iTotalEntries = 0; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +while(! strm . AtEOF ()) +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CTString strLine ; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CTString strArgs ; +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CTString strTmp ; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CCreditEntry cceEntry ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . GetLine_t (strLine ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . GetLine_t (strLine ); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strLine . TrimSpacesRight (); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(strLine == "END"){ +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . Close (); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return TRUE ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +}else if(strLine != "ENTRY"){ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries . PopAll (); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return FALSE ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . GetLine_t (strArgs ); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strArgs . ScanF ("%d,%d" , & cceEntry . iX , & cceEntry . iY ); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . GetLine_t (strArgs ); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strArgs . ScanF ("%f" , & cceEntry . fRelSize ); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . GetLine_t (strArgs ); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strArgs . TrimSpacesRight (); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(strArgs == "CENTER"){cceEntry . iAlign = CTA_CENTER ;} +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +else if(strArgs == "RIGHT"){cceEntry . iAlign = CTA_RIGHT ;} +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +else if(TRUE ){cceEntry . iAlign = CTA_LEFT ;} +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . GetLine_t (cceEntry . strTitle ); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . GetLine_t (cceEntry . strName ); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . GetLine_t (cceEntry . strQuote ); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . GetLine_t (strArgs ); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strArgs . ScanF ("%f" , & cceEntry . fWait ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries . Push () = cceEntry ; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +m_iTotalEntries ++; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +strm . Close (); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return TRUE ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +catch (char * strError ) +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CPrintF ("%s\n" , strError ); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return FALSE ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} + +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +BOOL CCreditsHolder::LoadFont() +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +try +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_fdMedium . Load_t (CTFILENAME ("Fonts\\Display3-normal.fnt")); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +catch (char * strError ) +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CPrintF ("%s\n" , strError ); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return FALSE ; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return TRUE ; +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} + +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +BOOL CCreditsHolder::Credits_On(CTFileName fnCreditsText) +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries . PopAll (); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return LoadOneFile (fnCreditsText ); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +void CCreditsHolder::Credits_Off(void) +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries . Clear (); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} + +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT CCreditsHolder::Credits_Render(CCreditsHolder * penThis,CDrawPort * pdp) +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(m_bDataError ){return 0;} +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(! bDataLoaded ){ +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(! ReloadData ()){ +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +m_bDataError = TRUE ; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return 0; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +bDataLoaded = TRUE ; +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return 1; +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +PIX pixW = 0; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +PIX pixH = 0; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CTString strEmpty ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fTime = Lerp (m_fMyTimerLast , m_fMyTimer , _pTimer -> GetLerpFactor ()); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CDrawPort * pdpCurr = pdp ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> Unlock (); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdpCurr -> Lock (); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pixW = pdpCurr -> GetWidth (); +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pixH = pdpCurr -> GetHeight (); +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fResFactor = pixH / 480.0f; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdpCurr -> SetFont (_pfdDisplayFont ); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +BOOL bOver = FALSE ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fPassed = 0.0f; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fStart = 0.0f; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +INDEX iNextItem = 0; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +for(INDEX i = 0;i < _acceEntries . Count ();i ++){ +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(_acceEntries [ i ] . fWait != 0.0f){ +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +fPassed += _acceEntries [ i ] . fWait ; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(fPassed > fTime ){ +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +break ; +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +}else { +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +iNextItem = i + 1; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +fStart = fPassed ; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(iNextItem >= _acceEntries . Count ()) +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +bOver = TRUE ; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(! bOver ){ +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +while(TRUE ){ +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +BOOL bLast = FALSE ; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(_acceEntries [ iNextItem ] . fWait != 0.0f){bLast = TRUE ;}; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fFade = CalculateRatio (fTime , fStart , fPassed - BLANK_TIME , 0.2f , 0.2f); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetFont (_pfdDisplayFont ); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetTextAspect (1.0f); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fTextSize01 = 1.2f * _acceEntries [ iNextItem ] . fRelSize ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fTextSize02 = 2.0f * _acceEntries [ iNextItem ] . fRelSize ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fTextSize03 = 0.75f * _acceEntries [ iNextItem ] . fRelSize ; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fTextHeight = 15.0f; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fSpacing01 = 1.2f; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fSpacing02 = 1.1f; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(_acceEntries [ iNextItem ] . iAlign == CTA_CENTER ){ +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fYY = _acceEntries [ iNextItem ] . iY * fResFactor ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetTextScaling (fTextSize01 * fResFactor ); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> PutTextC (_acceEntries [ iNextItem ] . strTitle , +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries [ iNextItem ] . iX * fResFactor , fYY , +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +C_WHITE | (INDEX) (fFade * 255)); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +fYY += fTextSize01 * fResFactor * fTextHeight * fSpacing01 ; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetFont (& _fdMedium ); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetTextScaling (fTextSize02 * fResFactor ); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> PutTextC (_acceEntries [ iNextItem ] . strName , +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries [ iNextItem ] . iX * fResFactor , fYY , +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +C_WHITE | (INDEX) (fFade * 255)); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +fYY += fTextSize02 * fResFactor * fTextHeight * fSpacing02 ; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetTextScaling (fTextSize03 * fResFactor ); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> PutTextC (_acceEntries [ iNextItem ] . strQuote , +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries [ iNextItem ] . iX * fResFactor , fYY , +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +C_WHITE | (INDEX) (fFade * 255)); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +}else if(_acceEntries [ iNextItem ] . iAlign == CTA_RIGHT ){ +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fYY = _acceEntries [ iNextItem ] . iY * fResFactor ; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetTextScaling (fTextSize01 * fResFactor ); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> PutTextR (_acceEntries [ iNextItem ] . strTitle , +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries [ iNextItem ] . iX * fResFactor , fYY , +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +C_WHITE | (INDEX) (fFade * 255)); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +fYY += fTextSize01 * fResFactor * fTextHeight * fSpacing01 ; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetTextScaling (fTextSize02 * fResFactor ); +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> PutTextR (_acceEntries [ iNextItem ] . strName , +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries [ iNextItem ] . iX * fResFactor , fYY , +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +C_WHITE | (INDEX) (fFade * 255)); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +fYY += fTextSize02 * fResFactor * fTextHeight * fSpacing02 ; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetTextScaling (fTextSize03 * fResFactor ); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> PutTextR (_acceEntries [ iNextItem ] . strQuote , +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries [ iNextItem ] . iX * fResFactor , fYY , +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +C_WHITE | (INDEX) (fFade * 255)); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +}else if(TRUE ){ +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT fYY = _acceEntries [ iNextItem ] . iY * fResFactor ; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetTextScaling (fTextSize01 * fResFactor ); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> PutText (_acceEntries [ iNextItem ] . strTitle , +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries [ iNextItem ] . iX * fResFactor , fYY , +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +C_WHITE | (INDEX) (fFade * 255)); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +fYY += fTextSize01 * fResFactor * fTextHeight * fSpacing01 ; +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetTextScaling (fTextSize02 * fResFactor ); +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> PutText (_acceEntries [ iNextItem ] . strName , +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries [ iNextItem ] . iX * fResFactor , fYY , +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +C_WHITE | (INDEX) (fFade * 255)); +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +fYY += fTextSize02 * fResFactor * fTextHeight * fSpacing02 ; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> SetTextScaling (fTextSize03 * fResFactor ); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> PutText (_acceEntries [ iNextItem ] . strQuote , +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +_acceEntries [ iNextItem ] . iX * fResFactor , fYY , +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +C_WHITE | (INDEX) (fFade * 255)); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +iNextItem ++; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(iNextItem >= _acceEntries . Count () || bLast ){ +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +bOver = TRUE ; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +break ; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdpCurr -> Unlock (); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pdp -> Lock (); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(bOver ){ +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return 0; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +}else { +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return 1; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +BOOL CCreditsHolder:: +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +WaitScrollingToEnd(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCreditsHolder_WaitScrollingToEnd + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCreditsHolder::WaitScrollingToEnd expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Jump(STATE_CURRENT,0x00f00003, FALSE, EInternal());return TRUE;}BOOL CCreditsHolder::H0x00f00003_WaitScrollingToEnd_03(const CEntityEvent &__eeInput) +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f00003 +if(!(! m_bEnd )){ Jump(STATE_CURRENT,0x00f00004, FALSE, EInternal());return TRUE;} +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x00f00001, FALSE, EBegin());return TRUE;}BOOL CCreditsHolder::H0x00f00001_WaitScrollingToEnd_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f00001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00f00002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCreditsHolder::H0x00f00002_WaitScrollingToEnd_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f00002 +; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +m_fMyTimerLast = m_fMyTimer ; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +m_fMyTimer += _pTimer -> TickQuantum / _pNetwork -> GetRealTimeFactor ();Jump(STATE_CURRENT,0x00f00003, FALSE, EInternal());return TRUE; +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +}BOOL CCreditsHolder::H0x00f00004_WaitScrollingToEnd_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f00004 + +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Return(STATE_CURRENT,EStop ()); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CCreditsHolder:: +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CCreditsHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CCreditsHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +InitAsEditorModel (); +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +SetModel (MODEL_HOLDER ); +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +SetModelMainTexture (TEXTURE_HOLDER ); +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x00f00005, FALSE, EBegin());return TRUE;}BOOL CCreditsHolder::H0x00f00005_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f00005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00f00006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CCreditsHolder::H0x00f00006_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f00006 +; +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(! Credits_On (m_fnmMessage )) +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CPrintF ("Error loading credits file '%s'!\n" , m_fnmMessage ); +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Credits_Off (); +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return TRUE; +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +m_bDataError = FALSE ; +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00f00007, FALSE, EBegin());return TRUE;}BOOL CCreditsHolder::H0x00f00007_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f00007 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EStart): +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{const EStart&eStart= (EStart&)__eeInput; + +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(pwsc != NULL ) +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +m_fMyTimer = 0; +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +m_fMyTimerLast = 0; +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +ECredits ecr ; +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +ecr . bStart = TRUE ; +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +ecr . penSender = this ; +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pwsc -> SendEvent (ecr ); +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Call(STATE_CURRENT, STATE_CCreditsHolder_WaitScrollingToEnd, TRUE, EVoid());return TRUE; +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop): +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{const EStop&eStop= (EStop&)__eeInput; + +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(pwsc != NULL ) +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +{ +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +ECredits ecr ; +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +ecr . bStart = FALSE ; +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +ecr . penSender = this ; +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +pwsc -> SendEvent (ecr ); +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +UnsetTimer();Jump(STATE_CURRENT,0x00f00008, FALSE, EInternal());return TRUE; +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +}return TRUE;}BOOL CCreditsHolder::H0x00f00008_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f00008 + +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Credits_Off (); +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +if(m_penEndCreditsTrigger ){ +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +SendToTarget (m_penEndCreditsTrigger , EET_TRIGGER , FixupCausedToPlayer (this , NULL , FALSE )); +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +} +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/CreditsHolder.es b/Sources/EntitiesMP/CreditsHolder.es new file mode 100644 index 0000000..98f6831 --- /dev/null +++ b/Sources/EntitiesMP/CreditsHolder.es @@ -0,0 +1,393 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +240 +%{ +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" +%} + +%{ + +#define CTA_LEFT 1 +#define CTA_RIGHT 2 +#define CTA_CENTER 3 + +class CCreditEntry { +public: + CTString strTitle; + CTString strName; + CTString strQuote; + INDEX iAlign; + INDEX iX, iY; + FLOAT fRelSize; + FLOAT fWait; +}; + +static CStaticStackArray _acceEntries; +#define BLANK_TIME 1.0f +%} + +class CCreditsHolder: CRationalEntity { +name "CreditsHolder"; +thumbnail "Thumbnails\\ScrollHolder.tbn"; +features "IsTargetable", "HasName", "IsImportant"; + +properties: + + 1 CTString m_strName "Name" 'N' = "Credits holder", + 2 CTString m_strDescription = "", + 3 CTFileName m_fnmMessage "Scroll Text" 'T' = CTString(""), + 4 FLOAT m_fMyTimer = 0.0f, // time when started + 6 FLOAT m_fMyTimerLast = 0.0f, + 5 FLOAT m_iTotalEntries = 0, + 10 BOOL m_bEnd = FALSE, // set to TRUE to end + 15 CEntityPointer m_penEndCreditsTrigger "EndCredits trigger", + + 20 BOOL m_bDataError = FALSE, + + { + BOOL bDataLoaded; + CFontData _fdMedium; + } + +components: + 1 model MODEL_HOLDER "Models\\Editor\\MessageHolder.mdl", + 2 texture TEXTURE_HOLDER "Models\\Editor\\MessageHolder.tex" + +functions: + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("%s", m_fnmMessage.FileName()); + return m_strDescription; + } + + void CCreditsHolder(void) + { + bDataLoaded = FALSE; + } + + BOOL ReloadData(void) + { + m_bDataError = FALSE; + if (!Credits_On(m_fnmMessage)) + { + Credits_Off(); + return FALSE; + } + if(!LoadFont()) + { + Credits_Off(); + return FALSE; + } + return TRUE; + } + + + BOOL LoadOneFile(const CTFileName &fnm) + { + if(fnm=="") { return FALSE; } + + try + { + // open the file + CTFileStream strm; + strm.Open_t(fnm); + + CTString strCheck; + strm.GetLine_t(strCheck); + strCheck.TrimSpacesRight(); + if (strCheck!="CREDITS") { return FALSE; }; + + m_iTotalEntries = 0; + while(!strm.AtEOF()) + { + CTString strLine; + CTString strArgs; + CTString strTmp; + CCreditEntry cceEntry; + + strm.GetLine_t(strLine); + strm.GetLine_t(strLine); + strLine.TrimSpacesRight(); + if (strLine=="END") { + strm.Close(); + return TRUE; + } else if (strLine!="ENTRY") { + _acceEntries.PopAll(); + return FALSE; + } + strm.GetLine_t(strArgs); + strArgs.ScanF("%d,%d", &cceEntry.iX, &cceEntry.iY); + strm.GetLine_t(strArgs); + strArgs.ScanF("%f", &cceEntry.fRelSize); + strm.GetLine_t(strArgs); + strArgs.TrimSpacesRight(); + if (strArgs=="CENTER") { cceEntry.iAlign = CTA_CENTER; } + else if (strArgs=="RIGHT") { cceEntry.iAlign = CTA_RIGHT; } + else if (TRUE) { cceEntry.iAlign = CTA_LEFT; } + strm.GetLine_t(cceEntry.strTitle); + strm.GetLine_t(cceEntry.strName); + strm.GetLine_t(cceEntry.strQuote); + strm.GetLine_t(strArgs); + strArgs.ScanF("%f", &cceEntry.fWait); + _acceEntries.Push() = cceEntry; + m_iTotalEntries ++; + } + + strm.Close(); + return TRUE; + } + catch (char *strError) + { + CPrintF("%s\n", strError); + return FALSE; + } + } + + BOOL LoadFont() + { + try + { + _fdMedium.Load_t( CTFILENAME( "Fonts\\Display3-normal.fnt")); + } + catch (char *strError) + { + CPrintF("%s\n", strError); + return FALSE; + } + return TRUE; + } + + // turn credits on + BOOL Credits_On(CTFileName fnCreditsText) + { + _acceEntries.PopAll(); + return LoadOneFile(fnCreditsText); + } + + // turn credits off + void Credits_Off(void) + { + _acceEntries.Clear(); + } + + // render credits to given drawport + FLOAT Credits_Render(CCreditsHolder *penThis, CDrawPort *pdp) + { + if (m_bDataError) { return 0; } + + if (!bDataLoaded) { + if (!ReloadData()) { + m_bDataError = TRUE; + return 0; + } + bDataLoaded = TRUE; + return 1; + } + + PIX pixW = 0; + PIX pixH = 0; + //FLOAT fResolutionScaling; + CTString strEmpty; + + FLOAT fTime = Lerp(m_fMyTimerLast, m_fMyTimer, _pTimer->GetLerpFactor()); + CDrawPort *pdpCurr=pdp; + + pdp->Unlock(); + pdpCurr->Lock(); + + pixW = pdpCurr->GetWidth(); + pixH = pdpCurr->GetHeight(); + + FLOAT fResFactor = pixH/480.0f; + //fResolutionScaling = (FLOAT)pixH / 360.0f; + pdpCurr->SetFont( _pfdDisplayFont); + //PIX pixLineHeight = floor(20*fResolutionScaling); + + BOOL bOver = FALSE; + + FLOAT fPassed = 0.0f; + FLOAT fStart = 0.0f; + INDEX iNextItem = 0; + // go to active items + for (INDEX i = 0; i<_acceEntries.Count(); i++) { + if (_acceEntries[i].fWait!=0.0f) { + fPassed += _acceEntries[i].fWait; + if (fPassed>fTime) { + break; + } else { + iNextItem = i+1; + fStart = fPassed; + if (iNextItem>=_acceEntries.Count()) + { + bOver = TRUE; + } + } + } + } +//CPrintF("start:%f, passed:%f, time:%f\n", fStart, fPassed, fTime); + if (!bOver) { + while (TRUE) { + BOOL bLast = FALSE; + if (_acceEntries[iNextItem].fWait!=0.0f) { bLast = TRUE; }; + FLOAT fFade = CalculateRatio(fTime, fStart, fPassed-BLANK_TIME, 0.2f, 0.2f); + pdp->SetFont( _pfdDisplayFont); + pdp->SetTextAspect( 1.0f); + + FLOAT fTextSize01 = 1.2f*_acceEntries[iNextItem].fRelSize; + FLOAT fTextSize02 = 2.0f*_acceEntries[iNextItem].fRelSize; + FLOAT fTextSize03 = 0.75f*_acceEntries[iNextItem].fRelSize; + FLOAT fTextHeight = 15.0f; + FLOAT fSpacing01 = 1.2f; + FLOAT fSpacing02 = 1.1f; + + if (_acceEntries[iNextItem].iAlign == CTA_CENTER) { + FLOAT fYY = _acceEntries[iNextItem].iY*fResFactor; + + pdp->SetTextScaling(fTextSize01*fResFactor); + pdp->PutTextC( _acceEntries[iNextItem].strTitle, + _acceEntries[iNextItem].iX*fResFactor, fYY, + C_WHITE|(INDEX)(fFade*255)); + fYY += fTextSize01*fResFactor*fTextHeight*fSpacing01; + + pdp->SetFont( &_fdMedium); + pdp->SetTextScaling(fTextSize02*fResFactor); + pdp->PutTextC( _acceEntries[iNextItem].strName, + _acceEntries[iNextItem].iX*fResFactor, fYY, + C_WHITE|(INDEX)(fFade*255)); + fYY += fTextSize02*fResFactor*fTextHeight*fSpacing02; + + pdp->SetTextScaling(fTextSize03*fResFactor); + pdp->PutTextC( _acceEntries[iNextItem].strQuote, + _acceEntries[iNextItem].iX*fResFactor, fYY, + C_WHITE|(INDEX)(fFade*255)); + + } else if (_acceEntries[iNextItem].iAlign == CTA_RIGHT) { + FLOAT fYY = _acceEntries[iNextItem].iY*fResFactor; + + pdp->SetTextScaling(fTextSize01*fResFactor); + pdp->PutTextR( _acceEntries[iNextItem].strTitle, + _acceEntries[iNextItem].iX*fResFactor, fYY, + C_WHITE|(INDEX)(fFade*255)); + fYY += fTextSize01*fResFactor*fTextHeight*fSpacing01; + + pdp->SetTextScaling(fTextSize02*fResFactor); + pdp->PutTextR( _acceEntries[iNextItem].strName, + _acceEntries[iNextItem].iX*fResFactor, fYY, + C_WHITE|(INDEX)(fFade*255)); + fYY += fTextSize02*fResFactor*fTextHeight*fSpacing02; + + pdp->SetTextScaling(fTextSize03*fResFactor); + pdp->PutTextR( _acceEntries[iNextItem].strQuote, + _acceEntries[iNextItem].iX*fResFactor, fYY, + C_WHITE|(INDEX)(fFade*255)); + + } else if (TRUE) { + FLOAT fYY = _acceEntries[iNextItem].iY*fResFactor; + + pdp->SetTextScaling(fTextSize01*fResFactor); + pdp->PutText( _acceEntries[iNextItem].strTitle, + _acceEntries[iNextItem].iX*fResFactor, fYY, + C_WHITE|(INDEX)(fFade*255)); + fYY += fTextSize01*fResFactor*fTextHeight*fSpacing01; + + pdp->SetTextScaling(fTextSize02*fResFactor); + pdp->PutText( _acceEntries[iNextItem].strName, + _acceEntries[iNextItem].iX*fResFactor, fYY, + C_WHITE|(INDEX)(fFade*255)); + fYY += fTextSize02*fResFactor*fTextHeight*fSpacing02; + + pdp->SetTextScaling(fTextSize03*fResFactor); + pdp->PutText( _acceEntries[iNextItem].strQuote, + _acceEntries[iNextItem].iX*fResFactor, fYY, + C_WHITE|(INDEX)(fFade*255)); + + } + + iNextItem++; + if (iNextItem>=_acceEntries.Count() || bLast) { + bOver = TRUE; + break; + } + } + } + + pdpCurr->Unlock(); + pdp->Lock(); + + if (bOver) { + return 0; + } else { + return 1; + } + } + + +procedures: + WaitScrollingToEnd() + { + while (!m_bEnd) + { + autowait(_pTimer->TickQuantum); + m_fMyTimerLast = m_fMyTimer; + m_fMyTimer+=_pTimer->TickQuantum/_pNetwork->GetRealTimeFactor(); + } + return EStop(); + } + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_HOLDER); + SetModelMainTexture(TEXTURE_HOLDER); + + autowait(0.05f); + + if( !Credits_On(m_fnmMessage)) + { + CPrintF("Error loading credits file '%s'!\n", m_fnmMessage); + Credits_Off(); + return; + } + m_bDataError = FALSE; + + wait() { + on (EStart eStart): + { + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL) + { + m_fMyTimer = 0; + m_fMyTimerLast = 0; + ECredits ecr; + ecr.bStart=TRUE; + ecr.penSender=this; + pwsc->SendEvent(ecr); + } + call WaitScrollingToEnd(); + } + on (EStop eStop): + { + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL) + { + ECredits ecr; + ecr.bStart=FALSE; + ecr.penSender=this; + pwsc->SendEvent(ecr); + } + stop; + } + } + Credits_Off(); + if (m_penEndCreditsTrigger) { + SendToTarget(m_penEndCreditsTrigger, EET_TRIGGER, FixupCausedToPlayer(this, NULL, FALSE)); + } + return; + } +}; + diff --git a/Sources/EntitiesMP/CreditsHolder.h b/Sources/EntitiesMP/CreditsHolder.h new file mode 100644 index 0000000..25106eb --- /dev/null +++ b/Sources/EntitiesMP/CreditsHolder.h @@ -0,0 +1,64 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_CreditsHolder_INCLUDED +#define _EntitiesMP_CreditsHolder_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CCreditsHolder_DLLClass; +class CCreditsHolder : public CRationalEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CTFileName m_fnmMessage; + FLOAT m_fMyTimer; + FLOAT m_fMyTimerLast; + FLOAT m_iTotalEntries; + BOOL m_bEnd; + CEntityPointer m_penEndCreditsTrigger; + BOOL m_bDataError; +BOOL bDataLoaded; +CFontData _fdMedium; + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +const CTString & GetDescription(void)const; + CCreditsHolder(void); + +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +BOOL ReloadData(void); + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +BOOL LoadOneFile(const CTFileName & fnm); + +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +BOOL LoadFont(); + +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +BOOL Credits_On(CTFileName fnCreditsText); + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +void Credits_Off(void); + +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +FLOAT Credits_Render(CCreditsHolder * penThis,CDrawPort * pdp); +#define STATE_CCreditsHolder_WaitScrollingToEnd 0x00f00000 + BOOL +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +WaitScrollingToEnd(const CEntityEvent &__eeInput); + BOOL H0x00f00001_WaitScrollingToEnd_01(const CEntityEvent &__eeInput); + BOOL H0x00f00002_WaitScrollingToEnd_02(const CEntityEvent &__eeInput); + BOOL H0x00f00003_WaitScrollingToEnd_03(const CEntityEvent &__eeInput); + BOOL H0x00f00004_WaitScrollingToEnd_04(const CEntityEvent &__eeInput); +#define STATE_CCreditsHolder_Main 1 + BOOL +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00f00005_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00f00006_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00f00007_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00f00008_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_CreditsHolder_INCLUDED diff --git a/Sources/EntitiesMP/CreditsHolder_tables.h b/Sources/EntitiesMP/CreditsHolder_tables.h new file mode 100644 index 0000000..40fa29b --- /dev/null +++ b/Sources/EntitiesMP/CreditsHolder_tables.h @@ -0,0 +1,55 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CCreditsHolder + +CEntityProperty CCreditsHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000f0<<8)+1, offsetof(CCreditsHolder, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000f0<<8)+2, offsetof(CCreditsHolder, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000f0<<8)+3, offsetof(CCreditsHolder, m_fnmMessage), "Scroll Text", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f0<<8)+4, offsetof(CCreditsHolder, m_fMyTimer), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f0<<8)+6, offsetof(CCreditsHolder, m_fMyTimerLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f0<<8)+5, offsetof(CCreditsHolder, m_iTotalEntries), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000f0<<8)+10, offsetof(CCreditsHolder, m_bEnd), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000f0<<8)+15, offsetof(CCreditsHolder, m_penEndCreditsTrigger), "EndCredits trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000f0<<8)+20, offsetof(CCreditsHolder, m_bDataError), "", 0, 0, 0), +}; +#define CCreditsHolder_propertiesct ARRAYCOUNT(CCreditsHolder_properties) + +CEntityComponent CCreditsHolder_components[] = { +#define MODEL_HOLDER ((0x000000f0<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_HOLDER, "EFNM" "Models\\Editor\\MessageHolder.mdl"), +#define TEXTURE_HOLDER ((0x000000f0<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_HOLDER, "EFNM" "Models\\Editor\\MessageHolder.tex"), +}; +#define CCreditsHolder_componentsct ARRAYCOUNT(CCreditsHolder_components) + +CEventHandlerEntry CCreditsHolder_handlers[] = { + {0x00f00000, -1, CEntity::pEventHandler(&CCreditsHolder:: +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +WaitScrollingToEnd),DEBUGSTRING("CCreditsHolder::WaitScrollingToEnd")}, + {0x00f00001, -1, CEntity::pEventHandler(&CCreditsHolder::H0x00f00001_WaitScrollingToEnd_01), DEBUGSTRING("CCreditsHolder::H0x00f00001_WaitScrollingToEnd_01")}, + {0x00f00002, -1, CEntity::pEventHandler(&CCreditsHolder::H0x00f00002_WaitScrollingToEnd_02), DEBUGSTRING("CCreditsHolder::H0x00f00002_WaitScrollingToEnd_02")}, + {0x00f00003, -1, CEntity::pEventHandler(&CCreditsHolder::H0x00f00003_WaitScrollingToEnd_03), DEBUGSTRING("CCreditsHolder::H0x00f00003_WaitScrollingToEnd_03")}, + {0x00f00004, -1, CEntity::pEventHandler(&CCreditsHolder::H0x00f00004_WaitScrollingToEnd_04), DEBUGSTRING("CCreditsHolder::H0x00f00004_WaitScrollingToEnd_04")}, + {1, -1, CEntity::pEventHandler(&CCreditsHolder:: +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/CreditsHolder.es" +Main),DEBUGSTRING("CCreditsHolder::Main")}, + {0x00f00005, -1, CEntity::pEventHandler(&CCreditsHolder::H0x00f00005_Main_01), DEBUGSTRING("CCreditsHolder::H0x00f00005_Main_01")}, + {0x00f00006, -1, CEntity::pEventHandler(&CCreditsHolder::H0x00f00006_Main_02), DEBUGSTRING("CCreditsHolder::H0x00f00006_Main_02")}, + {0x00f00007, -1, CEntity::pEventHandler(&CCreditsHolder::H0x00f00007_Main_03), DEBUGSTRING("CCreditsHolder::H0x00f00007_Main_03")}, + {0x00f00008, -1, CEntity::pEventHandler(&CCreditsHolder::H0x00f00008_Main_04), DEBUGSTRING("CCreditsHolder::H0x00f00008_Main_04")}, +}; +#define CCreditsHolder_handlersct ARRAYCOUNT(CCreditsHolder_handlers) + +CEntity *CCreditsHolder_New(void) { return new CCreditsHolder; }; +void CCreditsHolder_OnInitClass(void) {}; +void CCreditsHolder_OnEndClass(void) {}; +void CCreditsHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CCreditsHolder_OnWorldEnd(CWorld *pwo) {}; +void CCreditsHolder_OnWorldInit(CWorld *pwo) {}; +void CCreditsHolder_OnWorldTick(CWorld *pwo) {}; +void CCreditsHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CCreditsHolder, CRationalEntity, "CreditsHolder", "Thumbnails\\ScrollHolder.tbn", 0x000000f0); +DECLARE_CTFILENAME(_fnmCCreditsHolder_tbn, "Thumbnails\\ScrollHolder.tbn"); diff --git a/Sources/EntitiesMP/Damager.cpp b/Sources/EntitiesMP/Damager.cpp new file mode 100644 index 0000000..e928458 --- /dev/null +++ b/Sources/EntitiesMP/Damager.cpp @@ -0,0 +1,119 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" + +#include "StdH.h" + +#include +#include +void CDamager::SetDefaultProperties(void) { + m_strName = "Damager"; + m_strDescription = ""; + m_dmtType = DMT_ABYSS ; + m_fAmmount = 1000.0f; + m_penToDamage = NULL; + m_bDamageFromTriggerer = FALSE ; + m_penLastDamaged = NULL; + m_tmLastDamage = 0.0f; + CRationalEntity::SetDefaultProperties(); +} + +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +const CTString & CDamager::GetDescription(void)const { +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +return m_strDescription ; +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +} +BOOL CDamager:: +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDamager_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDamager::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +InitAsEditorModel (); +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +SetModel (MODEL_TELEPORT ); +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +SetModelMainTexture (TEXTURE_TELEPORT ); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +((CTString &) m_strDescription ) . PrintF ("%s:%g" , +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +DamageType_enum . NameForValue (INDEX (m_dmtType )) , m_fAmmount ); +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +Jump(STATE_CURRENT,0x00e50002, FALSE, EInternal());return TRUE;}BOOL CDamager::H0x00e50002_Main_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e50002 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00e50003, FALSE, EInternal());return TRUE;} +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00e50000, FALSE, EBegin());return TRUE;}BOOL CDamager::H0x00e50000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e50000 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +CEntity * penInflictor = this ; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +if(m_bDamageFromTriggerer ){ +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +penInflictor = eTrigger . penCaused ; +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +} +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +CEntity * penVictim = NULL ; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +if(m_penToDamage != NULL ){ +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +penVictim = m_penToDamage ; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +}else if(eTrigger . penCaused != NULL ){ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +penVictim = eTrigger . penCaused ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +} +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +if(penVictim != NULL ){ +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +if(! (penVictim == m_penLastDamaged && _pTimer -> CurrentTick () < m_tmLastDamage + 0.1f)) +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +{ +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +InflictDirectDamage (penVictim , penInflictor , m_dmtType , m_fAmmount , +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +penVictim -> GetPlacement () . pl_PositionVector , FLOAT3D (0 , 1 , 0)); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +m_penLastDamaged = penVictim ; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +m_tmLastDamage = _pTimer -> CurrentTick (); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +} +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +} +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +UnsetTimer();Jump(STATE_CURRENT,0x00e50001, FALSE, EInternal());return TRUE; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +}ASSERT(FALSE);break;default:{ +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +return TRUE; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +}ASSERT(FALSE);break; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +}return TRUE;}BOOL CDamager::H0x00e50001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e50001 +;Jump(STATE_CURRENT,0x00e50002, FALSE, EInternal());return TRUE; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +}BOOL CDamager::H0x00e50003_Main_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e50003 + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Damager.es b/Sources/EntitiesMP/Damager.es new file mode 100644 index 0000000..3a128a8 --- /dev/null +++ b/Sources/EntitiesMP/Damager.es @@ -0,0 +1,84 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +229 +%{ +#include "StdH.h" +%} + +class CDamager: CRationalEntity { +name "Damager"; +thumbnail "Thumbnails\\Damager.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "Damager", + 2 CTString m_strDescription = "", + 3 enum DamageType m_dmtType "Type" 'Y' = DMT_ABYSS, // type of damage + 4 FLOAT m_fAmmount "Ammount" 'A' = 1000.0f, // ammount of damage + 5 CEntityPointer m_penToDamage "Entity to Damage" 'E', // entity to damage, NULL to damage the triggerer + 6 BOOL m_bDamageFromTriggerer "DamageFromTriggerer" 'S' = FALSE, // make the triggerer inflictor of the damage + 10 CEntityPointer m_penLastDamaged, + 11 FLOAT m_tmLastDamage = 0.0f, + +components: + 1 model MODEL_TELEPORT "Models\\Editor\\Copier.mdl", + 2 texture TEXTURE_TELEPORT "Models\\Editor\\Copier.tex", + +functions: + const CTString &GetDescription(void) const { + return m_strDescription; + } + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_TELEPORT); + SetModelMainTexture(TEXTURE_TELEPORT); + + ((CTString&)m_strDescription).PrintF("%s:%g", + DamageType_enum.NameForValue(INDEX(m_dmtType)), m_fAmmount); + + while (TRUE) { + // wait for someone to trigger you and then damage it + wait() { + on (ETrigger eTrigger) : { + + CEntity *penInflictor = this; + if (m_bDamageFromTriggerer) { + penInflictor = eTrigger.penCaused; + } + + CEntity *penVictim = NULL; + if (m_penToDamage!=NULL) { + penVictim = m_penToDamage; + } else if (eTrigger.penCaused!=NULL) { + penVictim = eTrigger.penCaused; + } + + if (penVictim!=NULL) { + if (!(penVictim==m_penLastDamaged && _pTimer->CurrentTick()GetPlacement().pl_PositionVector, FLOAT3D(0,1,0)); + m_penLastDamaged = penVictim; + m_tmLastDamage = _pTimer->CurrentTick(); + } + } + stop; + } + otherwise() : { + resume; + }; + }; + + // wait a bit to recover + // autowait(0.1f); + } + } +}; + diff --git a/Sources/EntitiesMP/Damager.h b/Sources/EntitiesMP/Damager.h new file mode 100644 index 0000000..f9cc4ee --- /dev/null +++ b/Sources/EntitiesMP/Damager.h @@ -0,0 +1,33 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Damager_INCLUDED +#define _EntitiesMP_Damager_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CDamager_DLLClass; +class CDamager : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + enum DamageType m_dmtType; + FLOAT m_fAmmount; + CEntityPointer m_penToDamage; + BOOL m_bDamageFromTriggerer; + CEntityPointer m_penLastDamaged; + FLOAT m_tmLastDamage; + +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +const CTString & GetDescription(void)const; +#define STATE_CDamager_Main 1 + BOOL +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00e50000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00e50001_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00e50002_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00e50003_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Damager_INCLUDED diff --git a/Sources/EntitiesMP/Damager_tables.h b/Sources/EntitiesMP/Damager_tables.h new file mode 100644 index 0000000..91e975c --- /dev/null +++ b/Sources/EntitiesMP/Damager_tables.h @@ -0,0 +1,47 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CDamager + +CEntityProperty CDamager_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e5<<8)+1, offsetof(CDamager, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e5<<8)+2, offsetof(CDamager, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DamageType_enum, (0x000000e5<<8)+3, offsetof(CDamager, m_dmtType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e5<<8)+4, offsetof(CDamager, m_fAmmount), "Ammount", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e5<<8)+5, offsetof(CDamager, m_penToDamage), "Entity to Damage", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e5<<8)+6, offsetof(CDamager, m_bDamageFromTriggerer), "DamageFromTriggerer", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e5<<8)+10, offsetof(CDamager, m_penLastDamaged), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e5<<8)+11, offsetof(CDamager, m_tmLastDamage), "", 0, 0, 0), +}; +#define CDamager_propertiesct ARRAYCOUNT(CDamager_properties) + +CEntityComponent CDamager_components[] = { +#define MODEL_TELEPORT ((0x000000e5<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_TELEPORT, "EFNM" "Models\\Editor\\Copier.mdl"), +#define TEXTURE_TELEPORT ((0x000000e5<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_TELEPORT, "EFNM" "Models\\Editor\\Copier.tex"), +}; +#define CDamager_componentsct ARRAYCOUNT(CDamager_components) + +CEventHandlerEntry CDamager_handlers[] = { + {1, -1, CEntity::pEventHandler(&CDamager:: +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/Damager.es" +Main),DEBUGSTRING("CDamager::Main")}, + {0x00e50000, -1, CEntity::pEventHandler(&CDamager::H0x00e50000_Main_01), DEBUGSTRING("CDamager::H0x00e50000_Main_01")}, + {0x00e50001, -1, CEntity::pEventHandler(&CDamager::H0x00e50001_Main_02), DEBUGSTRING("CDamager::H0x00e50001_Main_02")}, + {0x00e50002, -1, CEntity::pEventHandler(&CDamager::H0x00e50002_Main_03), DEBUGSTRING("CDamager::H0x00e50002_Main_03")}, + {0x00e50003, -1, CEntity::pEventHandler(&CDamager::H0x00e50003_Main_04), DEBUGSTRING("CDamager::H0x00e50003_Main_04")}, +}; +#define CDamager_handlersct ARRAYCOUNT(CDamager_handlers) + +CEntity *CDamager_New(void) { return new CDamager; }; +void CDamager_OnInitClass(void) {}; +void CDamager_OnEndClass(void) {}; +void CDamager_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CDamager_OnWorldEnd(CWorld *pwo) {}; +void CDamager_OnWorldInit(CWorld *pwo) {}; +void CDamager_OnWorldTick(CWorld *pwo) {}; +void CDamager_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CDamager, CRationalEntity, "Damager", "Thumbnails\\Damager.tbn", 0x000000e5); +DECLARE_CTFILENAME(_fnmCDamager_tbn, "Thumbnails\\Damager.tbn"); diff --git a/Sources/EntitiesMP/Debris.cpp b/Sources/EntitiesMP/Debris.cpp new file mode 100644 index 0000000..753cdd1 --- /dev/null +++ b/Sources/EntitiesMP/Debris.cpp @@ -0,0 +1,523 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *ESpawnDebris::MakeCopy(void) { CEntityEvent *peeCopy = new ESpawnDebris(*this); return peeCopy;} +ESpawnDebris::ESpawnDebris() : CEntityEvent(EVENTCODE_ESpawnDebris) {; + ClearToDefault(Eeibt); + ClearToDefault(pmd); + ClearToDefault(fSize); + ClearToDefault(ptd); + ClearToDefault(ptdRefl); + ClearToDefault(ptdSpec); + ClearToDefault(ptdBump); + ClearToDefault(iModelAnim); + ClearToDefault(dptParticles); + ClearToDefault(betStain); + ClearToDefault(colDebris); + ClearToDefault(bCustomShading); + ClearToDefault(aShadingDirection); + ClearToDefault(colCustomAmbient); + ClearToDefault(colCustomDiffuse); + ClearToDefault(bImmaterialASAP); + ClearToDefault(fDustStretch); + ClearToDefault(vStretch); + ClearToDefault(penFallFXPapa); +}; +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" + + +void CDebris::SetDefaultProperties(void) { + m_dptParticles = DPT_NONE ; + m_iBodyType = 0; + m_bFade = FALSE ; + m_fFadeStartTime = 0.0f; + m_fFadeTime = 0.0f; + m_fLastStainHitPoint = FLOAT3D(0 , 0 , 0); + m_betStain = BET_NONE ; + m_ctLeftStains = 0; + m_tmStarted = 0.0f; + m_fStretch = 1.0f; + m_aShadingDirection = ANGLE3D(0 , 0 , 0); + m_bCustomShading = FALSE ; + m_colCustomAmbient = COLOR(C_WHITE | CT_OPAQUE ); + m_colCustomDiffuse = COLOR(C_WHITE | CT_OPAQUE ); + m_bImmaterialASAP = FALSE ; + m_fDustStretch = 0.0f; + m_bTouchedGround = FALSE ; + m_penFallFXPapa = NULL; + CMovableModelEntity::SetDefaultProperties(); +} + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void * CDebris::GetEntityInfo(void) { +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +return GetStdEntityInfo ((EntityInfoBodyType ) m_iBodyType ); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void CDebris::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if((_pTimer -> CurrentTick () - m_tmStarted < 1.0f) +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +|| (dmtType == DMT_CANNONBALL_EXPLOSION ) && (_pTimer -> CurrentTick () - m_tmStarted < 5.0f)){ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +return ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +CMovableModelEntity :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} + +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +BOOL CDebris::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(m_bCustomShading ) +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +colLight = m_colCustomDiffuse ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +colAmbient = m_colCustomAmbient ; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +AnglesToDirectionVector (m_aShadingDirection , vLightDirection ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +vLightDirection = - vLightDirection ; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(m_bFade ){ +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +FLOAT fTimeRemain = m_fFadeStartTime + m_fFadeTime - _pTimer -> CurrentTick (); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(fTimeRemain < 0.0f){fTimeRemain = 0.0f;} +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +COLOR colAlpha = GetModelObject () -> mo_colBlendColor ; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +colAlpha = (colAlpha & 0xffffff00) + (COLOR (fTimeRemain / m_fFadeTime * 0xff) & 0xff); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> mo_colBlendColor = colAlpha ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +return FALSE ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void CDebris::LeaveStain(void) +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(m_betStain == BET_NONE ){ +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +return ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(m_ctLeftStains > 5){ +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +return ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ESpawnEffect ese ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +FLOAT3D vPoint ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +FLOATplane3D plPlaneNormal ; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +FLOAT fDistanceToEdge ; +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(GetNearestPolygon (vPoint , plPlaneNormal , fDistanceToEdge )){ +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if((m_fLastStainHitPoint - vPoint ) . Length () > 3.0f && +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +(vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f){ +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_fLastStainHitPoint = vPoint ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ese . betType = m_betStain ; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ese . vNormal = FLOAT3D (plPlaneNormal ); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetNormalComponent (en_vCurrentTranslationAbsolute , plPlaneNormal , ese . vDirection ); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +FLOAT fLength = ese . vDirection . Length () / 7.5f; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +fLength = Clamp (fLength , 1.0f , 15.0f); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ese . vStretch = FLOAT3D (1.0f , fLength * 1.0f , 1.0f); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +SpawnEffect (CPlacement3D (vPoint + ese . vNormal / 50.0f * (FRnd () + 0.5f) , ANGLE3D (0 , 0 , 0)) , ese ); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_ctLeftStains ++; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} + +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void CDebris::SpawnEffect(const CPlacement3D & plEffect,const class ESpawnEffect & eSpawnEffect) +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +CEntityPointer penEffect = CreateEntity (plEffect , CLASS_BASIC_EFFECT ); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +penEffect -> Initialize (eSpawnEffect ); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} + +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void CDebris::RenderParticles(void) +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(en_vCurrentTranslationAbsolute . Length () < 0.1f){ +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +return ; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +switch(m_dptParticles ){ +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +case DPT_BLOODTRAIL : { +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Particles_BloodTrail (this ); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +}break ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +case DPR_SMOKETRAIL : { +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Particles_GrenadeTrail (this ); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +}break ; +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +case DPR_SPARKS : { +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Particles_ColoredStarsTrail (this ); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +}break ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +case DPR_FLYINGTRAIL : { +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Particles_BombTrail (this ); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +}break ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +case DPT_AFTERBURNER : { +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Particles_AfterBurner (this , m_tmStarted , 0.5f); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +}break ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +default : ASSERT (FALSE ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +case DPT_NONE : +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +return ; +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} + +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void CDebris::Explode(void) +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +CPlacement3D plExplosion = GetPlacement (); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +CEntityPointer penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ESpawnEffect eSpawnEffect ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +eSpawnEffect . betType = BET_BOMB ; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +eSpawnEffect . vStretch = FLOAT3D (0.3f , 0.3f , 0.3f); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +BOOL CDebris:: +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDebris_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_ESpawnDebris, "CDebris::Main expects 'ESpawnDebris' as input!"); const ESpawnDebris &eSpawn = (const ESpawnDebris &)__eeInput; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +InitAsModel (); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +SetPhysicsFlags (EPF_MODEL_BOUNCING | EPF_CANFADESPINNING ); +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +SetCollisionFlags (ECF_DEBRIS ); +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +SetHealth (25.0f); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +en_fBounceDampNormal = 0.15f; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +en_fBounceDampParallel = 0.5f; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +en_fJumpControlMultiplier = 0.0f; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(eSpawn . Eeibt == EIBT_ICE ){ +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +en_fDensity = 500.0f; +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +}else if(eSpawn . Eeibt == EIBT_WOOD ){ +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +en_fDensity = 500.0f; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +}else if(eSpawn . Eeibt == EIBT_FLESH ){ +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +en_fDensity = 5000.0f; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +en_fBounceDampNormal = 0.25f; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +en_fBounceDampParallel = 0.75f; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +}else if(TRUE ){ +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +en_fDensity = 5000.0f; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_dptParticles = eSpawn . dptParticles ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(m_dptParticles == DPT_AFTERBURNER ) +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Particles_AfterBurner_Prepare (this ); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_betStain = eSpawn . betStain ; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_iBodyType = (INDEX) eSpawn . Eeibt ; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> SetData (eSpawn . pmd ); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> mo_toTexture . SetData (eSpawn . ptd ); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> mo_toReflection . SetData (eSpawn . ptdRefl ); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> mo_toSpecular . SetData (eSpawn . ptdSpec ); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> mo_toBump . SetData (eSpawn . ptdBump ); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> PlayAnim (eSpawn . iModelAnim , AOF_LOOPING ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> mo_Stretch = FLOAT3D (eSpawn . fSize , eSpawn . fSize , eSpawn . fSize ); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> mo_Stretch (1) *= eSpawn . vStretch (1); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> mo_Stretch (2) *= eSpawn . vStretch (2); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> mo_Stretch (3) *= eSpawn . vStretch (3); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetModelObject () -> mo_colBlendColor = eSpawn . colDebris | CT_OPAQUE ; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_bCustomShading = eSpawn . bCustomShading ; +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(m_bCustomShading ) +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +en_ulFlags |= ENF_NOSHADINGINFO ; +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_aShadingDirection = eSpawn . aShadingDirection ; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_colCustomAmbient = eSpawn . colCustomAmbient ; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_colCustomDiffuse = eSpawn . colCustomDiffuse ; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_bImmaterialASAP = eSpawn . bImmaterialASAP ; +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_fDustStretch = eSpawn . fDustStretch ; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_penFallFXPapa = eSpawn . penFallFXPapa ; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ModelChangeNotify (); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +FLOATaabbox3D box ; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +GetBoundingBox (box ); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +FLOAT fEntitySize = box . Size () . MaxNorm (); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(fEntitySize > 0.5f){ +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +SetCollisionFlags (ECF_MODEL ); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +en_fCollisionSpeedLimit += ClampDn (0.0f , fEntitySize * 10.0f); +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_bFade = FALSE ; +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_fLastStainHitPoint = FLOAT3D (32000.0f , 32000.0f , 32000.0f); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_ctLeftStains = 0; +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_tmStarted = _pTimer -> CurrentTick (); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_bTouchedGround = FALSE ; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +FLOAT fWaitBeforeFade = FRnd () * 2.0f + 3.0f; +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +SetTimerAfter(fWaitBeforeFade ); +Jump(STATE_CURRENT, 0x025a0001, FALSE, EBegin());return TRUE;}BOOL CDebris::H0x025a0001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025a0001 +switch(__eeInput.ee_slEvent) +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(etouch . penOther -> GetRenderType () == RT_BRUSH ) +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(m_penFallFXPapa != NULL && ! m_bTouchedGround ) +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +FOREACHINLIST (CEntity , en_lnInParent , m_penFallFXPapa -> en_lhChildren , iten ) +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +CEntity * penNew = GetWorld () -> CopyEntityInWorld (* iten , GetPlacement ()); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +penNew -> SetParent (NULL ); +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(IsOfClass (& * penNew , "SoundHolder")) +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +penNew -> SendEvent (EStart ()); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +else +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +penNew -> SendEvent (ETrigger ()); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(m_fDustStretch > 0 && ! m_bTouchedGround ) +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +CPlacement3D plDust = GetPlacement (); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +plDust . pl_PositionVector = plDust . pl_PositionVector + FLOAT3D (0 , m_fDustStretch * 0.25f , 0); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ESpawnEffect ese ; +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ese . vStretch = FLOAT3D (m_fDustStretch , m_fDustStretch , m_fDustStretch ); +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ese . vNormal = FLOAT3D (0 , 1 , 0); +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +ese . betType = BET_DUST_FALL ; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +CEntityPointer penFX = CreateEntity (plDust , CLASS_BASIC_EFFECT ); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +penFX -> Initialize (ese ); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_bTouchedGround = TRUE ; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +LeaveStain (); +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(m_iBodyType == EIBT_ROBOT ) +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Explode (); +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +SendEvent (EDeath ()); +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +return TRUE; +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +if(m_bImmaterialASAP ) +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +{ +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +SetCollisionFlags (ECF_DEBRIS ); +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +} +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +return TRUE; +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +Destroy ();Return(STATE_CURRENT,EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x025a0002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +}return TRUE;}BOOL CDebris::H0x025a0002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025a0002 + +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +SetCollisionFlags (ECF_DEBRIS ); +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_fFadeStartTime = _pTimer -> CurrentTick (); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_fFadeTime = 5.0f; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +m_bFade = TRUE ; +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +SetTimerAfter(m_fFadeTime ); +Jump(STATE_CURRENT, 0x025a0003, FALSE, EBegin());return TRUE;}BOOL CDebris::H0x025a0003_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025a0003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x025a0004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDebris::H0x025a0004_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025a0004 +; +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Destroy (); +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Return(STATE_CURRENT,EVoid()); +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Debris.es b/Sources/EntitiesMP/Debris.es new file mode 100644 index 0000000..4fc7852 --- /dev/null +++ b/Sources/EntitiesMP/Debris.es @@ -0,0 +1,371 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +602 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/BasicEffects"; + +enum DebrisParticlesType { + 0 DPT_NONE "", // no particles + 1 DPT_BLOODTRAIL "", // blood + 2 DPR_SMOKETRAIL "", // smoke + 3 DPR_SPARKS "", // sparks (for robots) + 4 DPR_FLYINGTRAIL "", // just flying object + 5 DPT_AFTERBURNER "", // afterburner trail +}; + +// input parameter for spawning a debris +event ESpawnDebris { + EntityInfoBodyType Eeibt, // body type + CModelData *pmd, // model for this debris + FLOAT fSize, // stretch factor + CTextureData *ptd, // texture for this debris + CTextureData *ptdRefl, // reflection texture + CTextureData *ptdSpec, // specular texture + CTextureData *ptdBump, // bump texture + INDEX iModelAnim, // animation for debris model + enum DebrisParticlesType dptParticles, // particles type + enum BasicEffectType betStain, // stain left when touching brushes + COLOR colDebris, // multiply color for debris + BOOL bCustomShading, // if debris uses custom shading + ANGLE3D aShadingDirection, // custom shading direction + COLOR colCustomAmbient, // custom shading ambient + COLOR colCustomDiffuse, // custom shading diffuse + BOOL bImmaterialASAP, // if should stop colliding as soon as it hits the ground + FLOAT fDustStretch, // if should spawn dust when it hits the ground and size + FLOAT3D vStretch, // stretch for spawned model template + CEntityPointer penFallFXPapa, // parent of all spawned child effects +}; + +%{ +%} + +class CDebris: CMovableModelEntity { +name "Debris"; +thumbnail ""; + +properties: + + 1 enum DebrisParticlesType m_dptParticles = DPT_NONE, // type of particles + 2 INDEX m_iBodyType = 0, // body type of this debris + 3 BOOL m_bFade = FALSE, // fade debris + 4 FLOAT m_fFadeStartTime = 0.0f, // fade start time + 5 FLOAT m_fFadeTime = 0.0f, // fade time + 6 FLOAT3D m_fLastStainHitPoint = FLOAT3D(0,0,0), // last stain hit point + 7 enum BasicEffectType m_betStain = BET_NONE, // type of stain left + 8 INDEX m_ctLeftStains = 0, // count of stains already left + 9 FLOAT m_tmStarted = 0.0f, // time when spawned + 10 FLOAT m_fStretch = 1.0f, // stretch + 11 ANGLE3D m_aShadingDirection = ANGLE3D(0,0,0), + 12 BOOL m_bCustomShading = FALSE, + 13 COLOR m_colCustomAmbient = COLOR(C_WHITE|CT_OPAQUE), + 14 COLOR m_colCustomDiffuse = COLOR(C_WHITE|CT_OPAQUE), + 15 BOOL m_bImmaterialASAP = FALSE, + 16 FLOAT m_fDustStretch = 0.0f, + 17 BOOL m_bTouchedGround=FALSE, + 18 CEntityPointer m_penFallFXPapa, + + +components: + + 1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + + +functions: + + /* Entity info */ + void *GetEntityInfo(void) { + return GetStdEntityInfo((EntityInfoBodyType)m_iBodyType); + }; + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // cannot be damaged immediately after spawning + if ((_pTimer->CurrentTick()-m_tmStarted<1.0f) + ||(dmtType==DMT_CANNONBALL_EXPLOSION) && (_pTimer->CurrentTick()-m_tmStarted<5.0f)) { + return; + } + CMovableModelEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + }; + +/************************************************************ + * FADE OUT * + ************************************************************/ + + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + if(m_bCustomShading) + { + colLight = m_colCustomDiffuse; + colAmbient = m_colCustomAmbient; + AnglesToDirectionVector(m_aShadingDirection, vLightDirection); + vLightDirection = -vLightDirection; + } + + if (m_bFade) { + FLOAT fTimeRemain = m_fFadeStartTime + m_fFadeTime - _pTimer->CurrentTick(); + if (fTimeRemain < 0.0f) { fTimeRemain = 0.0f; } + COLOR colAlpha = GetModelObject()->mo_colBlendColor; + colAlpha = (colAlpha&0xffffff00) + (COLOR(fTimeRemain/m_fFadeTime*0xff)&0xff); + GetModelObject()->mo_colBlendColor = colAlpha; + } + + return FALSE; + }; + + + +/************************************************************ + * EFFECTS * + ************************************************************/ + + // leave a stain where hit + void LeaveStain(void) + { + // if no stains + if (m_betStain==BET_NONE) { + // do nothing + return; + } + + // don't allow too many stains to be left + if (m_ctLeftStains>5) { + return; + } + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D plPlaneNormal; + FLOAT fDistanceToEdge; + + // on plane + if (GetNearestPolygon(vPoint, plPlaneNormal, fDistanceToEdge)) { + // away from last hit point and near to polygon + if ((m_fLastStainHitPoint-vPoint).Length()>3.0f && + (vPoint-GetPlacement().pl_PositionVector).Length()<3.5f) { + m_fLastStainHitPoint = vPoint; + // stain + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = m_betStain; + ese.vNormal = FLOAT3D(plPlaneNormal); + GetNormalComponent( en_vCurrentTranslationAbsolute, plPlaneNormal, ese.vDirection); + FLOAT fLength = ese.vDirection.Length() / 7.5f; + fLength = Clamp( fLength, 1.0f, 15.0f); + ese.vStretch = FLOAT3D( 1.0f, fLength*1.0f, 1.0f); + SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f*(FRnd()+0.5f), ANGLE3D(0, 0, 0)), ese); + m_ctLeftStains++; + } + } + }; + + // spawn effect + void SpawnEffect(const CPlacement3D &plEffect, const class ESpawnEffect &eSpawnEffect) + { + CEntityPointer penEffect = CreateEntity(plEffect, CLASS_BASIC_EFFECT); + penEffect->Initialize(eSpawnEffect); + }; + + // particles + void RenderParticles(void) + { + // if going too slow + if (en_vCurrentTranslationAbsolute.Length()<0.1f) { + // don't render particles + return; + } + switch(m_dptParticles) { + case DPT_BLOODTRAIL: { + Particles_BloodTrail( this); + } break; + case DPR_SMOKETRAIL: { + Particles_GrenadeTrail( this); + } break; + case DPR_SPARKS: { + Particles_ColoredStarsTrail( this); + } break; + case DPR_FLYINGTRAIL:{ + //Particles_WhiteLineTrail( this); + Particles_BombTrail( this); + } break; + case DPT_AFTERBURNER:{ + Particles_AfterBurner( this, m_tmStarted, 0.5f); + } break; + default: ASSERT(FALSE); + case DPT_NONE: + return; + } + }; + + // explode + void Explode(void) + { + // spawn explosion + CPlacement3D plExplosion = GetPlacement(); + CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_BOMB; + eSpawnEffect.vStretch = FLOAT3D(0.3f,0.3f,0.3f); + penExplosion->Initialize(eSpawnEffect); + } + +/************************************************************ + * MAIN * + ************************************************************/ + +procedures: + + Main(ESpawnDebris eSpawn) + { + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_BOUNCING|EPF_CANFADESPINNING); + SetCollisionFlags(ECF_DEBRIS); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetHealth(25.0f); + en_fBounceDampNormal = 0.15f; + en_fBounceDampParallel = 0.5f; + en_fJumpControlMultiplier = 0.0f; + + // set density + if (eSpawn.Eeibt==EIBT_ICE) { + en_fDensity = 500.0f; + } else if (eSpawn.Eeibt==EIBT_WOOD) { + en_fDensity = 500.0f; + } else if (eSpawn.Eeibt==EIBT_FLESH) { + en_fDensity = 5000.0f; + en_fBounceDampNormal = 0.25f; + en_fBounceDampParallel = 0.75f; + } else if (TRUE) { + en_fDensity = 5000.0f; + } + + // set appearance + m_dptParticles = eSpawn.dptParticles; + if(m_dptParticles==DPT_AFTERBURNER) + { + Particles_AfterBurner_Prepare(this); + } + m_betStain = eSpawn.betStain; + m_iBodyType = (INDEX)eSpawn.Eeibt; + GetModelObject()->SetData(eSpawn.pmd); + GetModelObject()->mo_toTexture.SetData(eSpawn.ptd); + GetModelObject()->mo_toReflection.SetData(eSpawn.ptdRefl); + GetModelObject()->mo_toSpecular.SetData(eSpawn.ptdSpec); + GetModelObject()->mo_toBump.SetData(eSpawn.ptdBump); + GetModelObject()->PlayAnim(eSpawn.iModelAnim, AOF_LOOPING); + GetModelObject()->mo_Stretch = FLOAT3D( eSpawn.fSize, eSpawn.fSize, eSpawn.fSize); + GetModelObject()->mo_Stretch(1)*=eSpawn.vStretch(1); + GetModelObject()->mo_Stretch(2)*=eSpawn.vStretch(2); + GetModelObject()->mo_Stretch(3)*=eSpawn.vStretch(3); + + // adjust color + GetModelObject()->mo_colBlendColor = eSpawn.colDebris|CT_OPAQUE; + m_bCustomShading = eSpawn.bCustomShading; + if( m_bCustomShading) + { + en_ulFlags|=ENF_NOSHADINGINFO; + } + m_aShadingDirection = eSpawn.aShadingDirection; + m_colCustomAmbient = eSpawn.colCustomAmbient; + m_colCustomDiffuse = eSpawn.colCustomDiffuse; + m_bImmaterialASAP = eSpawn.bImmaterialASAP; + m_fDustStretch = eSpawn.fDustStretch; + m_penFallFXPapa=eSpawn.penFallFXPapa; + + ModelChangeNotify(); + FLOATaabbox3D box; + GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm(); + if (fEntitySize>0.5f) { + SetCollisionFlags(ECF_MODEL); + } + en_fCollisionSpeedLimit+=ClampDn(0.0f, fEntitySize*10.0f); + m_bFade = FALSE; + m_fLastStainHitPoint = FLOAT3D(32000.0f, 32000.0f, 32000.0f); + m_ctLeftStains = 0; + m_tmStarted = _pTimer->CurrentTick(); + m_bTouchedGround=FALSE; + + // wait some time + FLOAT fWaitBeforeFade=FRnd()*2.0f + 3.0f; + wait(fWaitBeforeFade) + { + on (EBegin) : { resume; } + // if touched something + on (ETouch etouch) : { + // if it is brush + if (etouch.penOther->GetRenderType()==RT_BRUSH) + { + // shake or some other effect + if( m_penFallFXPapa!=NULL && !m_bTouchedGround) + { + // loop all children of FX papa + FOREACHINLIST( CEntity, en_lnInParent, m_penFallFXPapa->en_lhChildren, iten) + { + // start it + CEntity *penNew = GetWorld()->CopyEntityInWorld( *iten, GetPlacement()); + penNew->SetParent(NULL); + if( IsOfClass(&*penNew, "SoundHolder")) + { + penNew->SendEvent( EStart()); + } + else + { + penNew->SendEvent( ETrigger()); + } + } + } + + if( m_fDustStretch>0 && !m_bTouchedGround) + { + // spawn dust + CPlacement3D plDust=GetPlacement(); + plDust.pl_PositionVector=plDust.pl_PositionVector+FLOAT3D(0,m_fDustStretch*0.25f,0); + // spawn dust effect + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.vStretch = FLOAT3D(m_fDustStretch,m_fDustStretch,m_fDustStretch); + ese.vNormal = FLOAT3D(0,1,0); + ese.betType = BET_DUST_FALL; + CEntityPointer penFX = CreateEntity(plDust, CLASS_BASIC_EFFECT); + penFX->Initialize(ese); + } + m_bTouchedGround=TRUE; + + // maybe leave stain + LeaveStain(); + // if robot + if (m_iBodyType==EIBT_ROBOT) + { + // explode + Explode(); + SendEvent(EDeath()); + resume; + } + } + if( m_bImmaterialASAP) + { + SetCollisionFlags(ECF_DEBRIS); + } + resume; + } + on (EDeath) : { Destroy(); return; } + on (ETimer) : { stop; } + } + + // fade away + SetCollisionFlags(ECF_DEBRIS); + m_fFadeStartTime = _pTimer->CurrentTick(); + m_fFadeTime = 5.0f; + m_bFade = TRUE; + autowait(m_fFadeTime); + + // cease to exist + Destroy(); + + return; + } +}; diff --git a/Sources/EntitiesMP/Debris.h b/Sources/EntitiesMP/Debris.h new file mode 100644 index 0000000..a55fef0 --- /dev/null +++ b/Sources/EntitiesMP/Debris.h @@ -0,0 +1,98 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Debris_INCLUDED +#define _EntitiesMP_Debris_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType DebrisParticlesType_enum; +enum DebrisParticlesType { + DPT_NONE = 0, + DPT_BLOODTRAIL = 1, + DPR_SMOKETRAIL = 2, + DPR_SPARKS = 3, + DPR_FLYINGTRAIL = 4, + DPT_AFTERBURNER = 5, +}; +DECL_DLL inline void ClearToDefault(DebrisParticlesType &e) { e = (DebrisParticlesType)0; } ; +#define EVENTCODE_ESpawnDebris 0x025a0000 +class DECL_DLL ESpawnDebris : public CEntityEvent { +public: +ESpawnDebris(); +CEntityEvent *MakeCopy(void); +EntityInfoBodyType Eeibt; +CModelData * pmd; +FLOAT fSize; +CTextureData * ptd; +CTextureData * ptdRefl; +CTextureData * ptdSpec; +CTextureData * ptdBump; +INDEX iModelAnim; +enum DebrisParticlesType dptParticles; +enum BasicEffectType betStain; +COLOR colDebris; +BOOL bCustomShading; +ANGLE3D aShadingDirection; +COLOR colCustomAmbient; +COLOR colCustomDiffuse; +BOOL bImmaterialASAP; +FLOAT fDustStretch; +FLOAT3D vStretch; +CEntityPointer penFallFXPapa; +}; +DECL_DLL inline void ClearToDefault(ESpawnDebris &e) { e = ESpawnDebris(); } ; +extern "C" DECL_DLL CDLLEntityClass CDebris_DLLClass; +class CDebris : public CMovableModelEntity { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum DebrisParticlesType m_dptParticles; + INDEX m_iBodyType; + BOOL m_bFade; + FLOAT m_fFadeStartTime; + FLOAT m_fFadeTime; + FLOAT3D m_fLastStainHitPoint; + enum BasicEffectType m_betStain; + INDEX m_ctLeftStains; + FLOAT m_tmStarted; + FLOAT m_fStretch; + ANGLE3D m_aShadingDirection; + BOOL m_bCustomShading; + COLOR m_colCustomAmbient; + COLOR m_colCustomDiffuse; + BOOL m_bImmaterialASAP; + FLOAT m_fDustStretch; + BOOL m_bTouchedGround; + CEntityPointer m_penFallFXPapa; + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void * GetEntityInfo(void); + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void LeaveStain(void); + +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void SpawnEffect(const CPlacement3D & plEffect,const class ESpawnEffect & eSpawnEffect); + +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void RenderParticles(void); + +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +void Explode(void); +#define STATE_CDebris_Main 1 + BOOL +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x025a0001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x025a0002_Main_02(const CEntityEvent &__eeInput); + BOOL H0x025a0003_Main_03(const CEntityEvent &__eeInput); + BOOL H0x025a0004_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Debris_INCLUDED diff --git a/Sources/EntitiesMP/Debris_tables.h b/Sources/EntitiesMP/Debris_tables.h new file mode 100644 index 0000000..d26fbeb --- /dev/null +++ b/Sources/EntitiesMP/Debris_tables.h @@ -0,0 +1,64 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(DebrisParticlesType) + EP_ENUMVALUE(DPT_NONE, ""), + EP_ENUMVALUE(DPT_BLOODTRAIL, ""), + EP_ENUMVALUE(DPR_SMOKETRAIL, ""), + EP_ENUMVALUE(DPR_SPARKS, ""), + EP_ENUMVALUE(DPR_FLYINGTRAIL, ""), + EP_ENUMVALUE(DPT_AFTERBURNER, ""), +EP_ENUMEND(DebrisParticlesType); + +#define ENTITYCLASS CDebris + +CEntityProperty CDebris_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &DebrisParticlesType_enum, (0x0000025a<<8)+1, offsetof(CDebris, m_dptParticles), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000025a<<8)+2, offsetof(CDebris, m_iBodyType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000025a<<8)+3, offsetof(CDebris, m_bFade), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025a<<8)+4, offsetof(CDebris, m_fFadeStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025a<<8)+5, offsetof(CDebris, m_fFadeTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000025a<<8)+6, offsetof(CDebris, m_fLastStainHitPoint), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &BasicEffectType_enum, (0x0000025a<<8)+7, offsetof(CDebris, m_betStain), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000025a<<8)+8, offsetof(CDebris, m_ctLeftStains), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025a<<8)+9, offsetof(CDebris, m_tmStarted), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025a<<8)+10, offsetof(CDebris, m_fStretch), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x0000025a<<8)+11, offsetof(CDebris, m_aShadingDirection), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000025a<<8)+12, offsetof(CDebris, m_bCustomShading), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025a<<8)+13, offsetof(CDebris, m_colCustomAmbient), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025a<<8)+14, offsetof(CDebris, m_colCustomDiffuse), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000025a<<8)+15, offsetof(CDebris, m_bImmaterialASAP), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025a<<8)+16, offsetof(CDebris, m_fDustStretch), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000025a<<8)+17, offsetof(CDebris, m_bTouchedGround), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025a<<8)+18, offsetof(CDebris, m_penFallFXPapa), "", 0, 0, 0), +}; +#define CDebris_propertiesct ARRAYCOUNT(CDebris_properties) + +CEntityComponent CDebris_components[] = { +#define CLASS_BASIC_EFFECT ((0x0000025a<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +}; +#define CDebris_componentsct ARRAYCOUNT(CDebris_components) + +CEventHandlerEntry CDebris_handlers[] = { + {1, -1, CEntity::pEventHandler(&CDebris:: +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Debris.es" +Main),DEBUGSTRING("CDebris::Main")}, + {0x025a0001, -1, CEntity::pEventHandler(&CDebris::H0x025a0001_Main_01), DEBUGSTRING("CDebris::H0x025a0001_Main_01")}, + {0x025a0002, -1, CEntity::pEventHandler(&CDebris::H0x025a0002_Main_02), DEBUGSTRING("CDebris::H0x025a0002_Main_02")}, + {0x025a0003, -1, CEntity::pEventHandler(&CDebris::H0x025a0003_Main_03), DEBUGSTRING("CDebris::H0x025a0003_Main_03")}, + {0x025a0004, -1, CEntity::pEventHandler(&CDebris::H0x025a0004_Main_04), DEBUGSTRING("CDebris::H0x025a0004_Main_04")}, +}; +#define CDebris_handlersct ARRAYCOUNT(CDebris_handlers) + +CEntity *CDebris_New(void) { return new CDebris; }; +void CDebris_OnInitClass(void) {}; +void CDebris_OnEndClass(void) {}; +void CDebris_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CDebris_OnWorldEnd(CWorld *pwo) {}; +void CDebris_OnWorldInit(CWorld *pwo) {}; +void CDebris_OnWorldTick(CWorld *pwo) {}; +void CDebris_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CDebris, CMovableModelEntity, "Debris", "", 0x0000025a); +DECLARE_CTFILENAME(_fnmCDebris_tbn, ""); diff --git a/Sources/EntitiesMP/DebugEntityStatesDisplay.cpp b/Sources/EntitiesMP/DebugEntityStatesDisplay.cpp new file mode 100644 index 0000000..23517f1 --- /dev/null +++ b/Sources/EntitiesMP/DebugEntityStatesDisplay.cpp @@ -0,0 +1,91 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" + +#include "StdH.h" +void HUD_SetEntityForStackDisplay(CRationalEntity *pren); + +#include +#include +void CEntityStateDisplay::SetDefaultProperties(void) { + m_strName = "EntityStateDisplay"; + m_penTarget = NULL; + CRationalEntity::SetDefaultProperties(); +} + CEntityStateDisplay:: ~ CEntityStateDisplay() +#line 26 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +{ +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +HUD_SetEntityForStackDisplay (NULL ); +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +} +BOOL CEntityStateDisplay:: +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEntityStateDisplay_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEntityStateDisplay::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +InitAsEditorModel (); +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +SetModel (MODEL_MARKER ); +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +GetModelObject () -> StretchModel (FLOAT3D (0.4f , 0.4f , 0.4f)); +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +Jump(STATE_CURRENT,0x00e90002, FALSE, EInternal());return TRUE;}BOOL CEntityStateDisplay::H0x00e90002_Main_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e90002 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00e90003, FALSE, EInternal());return TRUE;} +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00e90000, FALSE, EBegin());return TRUE;}BOOL CEntityStateDisplay::H0x00e90000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e90000 +switch(__eeInput.ee_slEvent) +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +if(m_penTarget != NULL ){ +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +HUD_SetEntityForStackDisplay ((CRationalEntity *) & * m_penTarget ); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +}else { +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +HUD_SetEntityForStackDisplay (NULL ); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +} +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +return TRUE; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +UnsetTimer();Jump(STATE_CURRENT,0x00e90001, FALSE, EInternal());return TRUE; +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +}return TRUE;}BOOL CEntityStateDisplay::H0x00e90001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e90001 +Jump(STATE_CURRENT,0x00e90002, FALSE, EInternal());return TRUE; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +}BOOL CEntityStateDisplay::H0x00e90003_Main_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e90003 + +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +Return(STATE_CURRENT,EVoid()); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/DebugEntityStatesDisplay.es b/Sources/EntitiesMP/DebugEntityStatesDisplay.es new file mode 100644 index 0000000..40bd4c3 --- /dev/null +++ b/Sources/EntitiesMP/DebugEntityStatesDisplay.es @@ -0,0 +1,63 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +233 +%{ +#include "StdH.h" +void HUD_SetEntityForStackDisplay(CRationalEntity *pren); +%} + + +class CEntityStateDisplay : CRationalEntity { +name "EntityStateDisplay"; +thumbnail "Thumbnails\\EntityStateDisplay.tbn"; +features "HasTarget", "HasName"; + +properties: + 1 CTString m_strName "Name" 'N' = "EntityStateDisplay", + 2 CEntityPointer m_penTarget "Target" 'T' COLOR(C_dGREEN|0xFF), // entity which it points to + + +components: + 1 model MODEL_MARKER "ModelsMP\\Editor\\Debug_EntityStack.mdl", + 2 texture TEXTURE_MARKER "ModelsMP\\Editor\\Debug_EntityStack.tex" + +functions: + void ~CEntityStateDisplay() + { + HUD_SetEntityForStackDisplay(NULL); + } + +procedures: + Main() { + + // init as nothing + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + GetModelObject()->StretchModel(FLOAT3D(0.4f, 0.4f, 0.4f)); + + // setup target for stack display every 1/10th of the second so + // that after a reload or restart everything will work allright + while(TRUE) { + wait(0.1f) + { + on (EBegin) : { + if (m_penTarget!=NULL) { + HUD_SetEntityForStackDisplay((CRationalEntity *)&*m_penTarget); + } else { + HUD_SetEntityForStackDisplay(NULL); + } + resume; + } + on (ETimer) : { + stop; + } + } + } + return; + }; +}; \ No newline at end of file diff --git a/Sources/EntitiesMP/DebugEntityStatesDisplay.h b/Sources/EntitiesMP/DebugEntityStatesDisplay.h new file mode 100644 index 0000000..ac83f47 --- /dev/null +++ b/Sources/EntitiesMP/DebugEntityStatesDisplay.h @@ -0,0 +1,25 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_DebugEntityStatesDisplay_INCLUDED +#define _EntitiesMP_DebugEntityStatesDisplay_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CEntityStateDisplay_DLLClass; +class CEntityStateDisplay : public CRationalEntity { +public: +virtual CEntity *GetTarget(void) const { return m_penTarget; }; +virtual const CTString &GetName(void) const { return m_strName; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CEntityPointer m_penTarget; + ~ CEntityStateDisplay(); +#define STATE_CEntityStateDisplay_Main 1 + BOOL +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00e90000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00e90001_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00e90002_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00e90003_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_DebugEntityStatesDisplay_INCLUDED diff --git a/Sources/EntitiesMP/DebugEntityStatesDisplay_tables.h b/Sources/EntitiesMP/DebugEntityStatesDisplay_tables.h new file mode 100644 index 0000000..7159934 --- /dev/null +++ b/Sources/EntitiesMP/DebugEntityStatesDisplay_tables.h @@ -0,0 +1,41 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CEntityStateDisplay + +CEntityProperty CEntityStateDisplay_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e9<<8)+1, offsetof(CEntityStateDisplay, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e9<<8)+2, offsetof(CEntityStateDisplay, m_penTarget), "Target", 'T', C_dGREEN | 0xFF, 0), +}; +#define CEntityStateDisplay_propertiesct ARRAYCOUNT(CEntityStateDisplay_properties) + +CEntityComponent CEntityStateDisplay_components[] = { +#define MODEL_MARKER ((0x000000e9<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "ModelsMP\\Editor\\Debug_EntityStack.mdl"), +#define TEXTURE_MARKER ((0x000000e9<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "ModelsMP\\Editor\\Debug_EntityStack.tex"), +}; +#define CEntityStateDisplay_componentsct ARRAYCOUNT(CEntityStateDisplay_components) + +CEventHandlerEntry CEntityStateDisplay_handlers[] = { + {1, -1, CEntity::pEventHandler(&CEntityStateDisplay:: +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/DebugEntityStatesDisplay.es" +Main),DEBUGSTRING("CEntityStateDisplay::Main")}, + {0x00e90000, -1, CEntity::pEventHandler(&CEntityStateDisplay::H0x00e90000_Main_01), DEBUGSTRING("CEntityStateDisplay::H0x00e90000_Main_01")}, + {0x00e90001, -1, CEntity::pEventHandler(&CEntityStateDisplay::H0x00e90001_Main_02), DEBUGSTRING("CEntityStateDisplay::H0x00e90001_Main_02")}, + {0x00e90002, -1, CEntity::pEventHandler(&CEntityStateDisplay::H0x00e90002_Main_03), DEBUGSTRING("CEntityStateDisplay::H0x00e90002_Main_03")}, + {0x00e90003, -1, CEntity::pEventHandler(&CEntityStateDisplay::H0x00e90003_Main_04), DEBUGSTRING("CEntityStateDisplay::H0x00e90003_Main_04")}, +}; +#define CEntityStateDisplay_handlersct ARRAYCOUNT(CEntityStateDisplay_handlers) + +CEntity *CEntityStateDisplay_New(void) { return new CEntityStateDisplay; }; +void CEntityStateDisplay_OnInitClass(void) {}; +void CEntityStateDisplay_OnEndClass(void) {}; +void CEntityStateDisplay_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEntityStateDisplay_OnWorldEnd(CWorld *pwo) {}; +void CEntityStateDisplay_OnWorldInit(CWorld *pwo) {}; +void CEntityStateDisplay_OnWorldTick(CWorld *pwo) {}; +void CEntityStateDisplay_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEntityStateDisplay, CRationalEntity, "EntityStateDisplay", "Thumbnails\\EntityStateDisplay.tbn", 0x000000e9); +DECLARE_CTFILENAME(_fnmCEntityStateDisplay_tbn, "Thumbnails\\EntityStateDisplay.tbn"); diff --git a/Sources/EntitiesMP/Demon.cpp b/Sources/EntitiesMP/Demon.cpp new file mode 100644 index 0000000..9c91dc0 --- /dev/null +++ b/Sources/EntitiesMP/Demon.cpp @@ -0,0 +1,506 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 5 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/Demon/Demon.h" + +#include +#include +#line 14 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" + +#define REMINDER_DEATTACH_FIREBALL 666 +#define CLOSE_ATTACK_RANGE 10.0f +#define DEMON_STRETCH 2.5f +FLOAT3D vFireballLaunchPos = (FLOAT3D(0.06f, 2.6f, 0.15f)*DEMON_STRETCH); +static FLOAT _tmLastStandingAnim =0.0f; + +// info structure +static EntityInfo eiDemon = { + EIBT_FLESH, 1600.0f, + 0.0f, 2.0f, 0.0f, // source (eyes) + 0.0f, 1.5f, 0.0f, // target (body) +}; + +void CDemon::SetDefaultProperties(void) { + m_iCounter = 0; + m_penFireFX = NULL; + CEnemyBase::SetDefaultProperties(); +} + +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +BOOL CDemon::HandleEvent(const CEntityEvent & ee) +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +{ +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +if(ee . ee_slEvent == EVENTCODE_EReminder ) +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +{ +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +EReminder eReminder = ((EReminder &) ee ); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +if(eReminder . iValue == REMINDER_DEATTACH_FIREBALL ) +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +{ +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +RemoveAttachment (DEMON_ATTACHMENT_FIREBALL ); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +return TRUE ; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +return CEnemyBase :: HandleEvent (ee ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + CTString CDemon::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +{ +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +CTString str ; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +str . PrintF (TRANS ("A Demon executed %s") , strPlayerName ); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +return str ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + const CTFileName & CDemon::GetComputerMessageName(void)const { +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +static DECLARE_CTFILENAME (fnmDemon , "DataMP\\Messages\\Enemies\\Demon.txt"); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +return fnmDemon ; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::Precache(void) { +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +CEnemyBase :: Precache (); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PrecacheSound (SOUND_IDLE ); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PrecacheSound (SOUND_SIGHT ); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PrecacheSound (SOUND_WOUND ); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PrecacheSound (SOUND_DEATH ); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PrecacheSound (SOUND_CAST ); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PrecacheModel (MODEL_DEMON ); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PrecacheTexture (TEXTURE_DEMON ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PrecacheModel (MODEL_FIREBALL ); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PrecacheTexture (TEXTURE_FIREBALL ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PrecacheClass (CLASS_PROJECTILE , PRT_BEAST_PROJECTILE ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void * CDemon::GetEntityInfo(void) { +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +return & eiDemon ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +BOOL CDemon::ForcesCannonballToExplode(void) +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +{ +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +return TRUE ; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +{ +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +if(dmtType == DMT_BULLET && fDamageAmmount > 100.0f) +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +{ +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +fDamageAmmount *= 0.5f; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +if(! IsOfClass (penInflictor , "Demon")){ +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +INDEX CDemon::AnimForDamage(FLOAT fDamage) { +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +RemoveAttachment (DEMON_ATTACHMENT_FIREBALL ); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +StartModelAnim (DEMON_ANIM_WOUND , 0); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +return DEMON_ANIM_WOUND ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +INDEX CDemon::AnimForDeath(void) { +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +if(m_penFireFX != NULL ) +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +{ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_penFireFX -> SendEvent (EStop ()); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_penFireFX = NULL ; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +RemoveAttachment (DEMON_ATTACHMENT_FIREBALL ); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +StartModelAnim (DEMON_ANIM_DEATHFORWARD , 0); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +return DEMON_ANIM_DEATHFORWARD ; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +FLOAT CDemon::WaitForDust(FLOAT3D & vStretch) +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +{ +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +vStretch = FLOAT3D (1 , 1 , 2) * 3.0f; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +return 1.1f; +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::DeathNotify(void) { +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +ChangeCollisionBoxIndexWhenPossible (DEMON_COLLISION_BOX_DEATH ); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +en_fDensity = 500.0f; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::StandingAnim(void) { +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +StartModelAnim (DEMON_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::WalkingAnim(void) { +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +RunningAnim (); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::RunningAnim(void) { +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +StartModelAnim (DEMON_ANIM_RUN , AOF_LOOPING | AOF_NORESTART ); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::RotatingAnim(void) { +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +StartModelAnim (DEMON_ANIM_RUN , AOF_LOOPING | AOF_NORESTART ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::IdleSound(void) { +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::SightSound(void) { +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::WoundSound(void) { +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::DeathSound(void) { +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} + +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void CDemon::EnemyPostInit(void) +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +{ +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_soSound . Set3DParameters (160.0f , 50.0f , 2.0f , 1.0f); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} +BOOL CDemon:: +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDemon_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDemon::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +if(m_fMoveSpeed > 0.0f){ +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , - m_fMoveSpeed )); +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +StartModelAnim (DEMON_ANIM_ATTACK , 0); +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x01500001, FALSE, EBegin());return TRUE;}BOOL CDemon::H0x01500001_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01500002, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDemon::H0x01500002_Fire_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500002 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PlaySound (m_soSound , SOUND_CAST , SOF_3D ); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SpawnReminder (this , 3.0f , REMINDER_DEATTACH_FIREBALL ); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetTimerAfter(1.0f); +Jump(STATE_CURRENT, 0x01500003, FALSE, EBegin());return TRUE;}BOOL CDemon::H0x01500003_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01500004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDemon::H0x01500004_Fire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500004 +; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +CPlacement3D plFX = GetPlacement (); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +const FLOATmatrix3D & m = GetRotationMatrix (); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +plFX . pl_PositionVector = plFX . pl_PositionVector + vFireballLaunchPos * m ; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +ESpawnEffect ese ; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +ese . betType = BET_COLLECT_ENERGY ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +ese . vStretch = FLOAT3D (1.0f , 1.0f , 1.0f); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_penFireFX = CreateEntity (plFX , CLASS_BASIC_EFFECT ); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_penFireFX -> Initialize (ese ); +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetTimerAfter(1.4f); +Jump(STATE_CURRENT, 0x01500005, FALSE, EBegin());return TRUE;}BOOL CDemon::H0x01500005_Fire_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01500006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDemon::H0x01500006_Fire_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500006 +; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +AddAttachment (DEMON_ATTACHMENT_FIREBALL , MODEL_FIREBALL , TEXTURE_FIREBALL ); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +CModelObject * pmoFire = & GetModelObject () -> GetAttachmentModel (DEMON_ATTACHMENT_FIREBALL ) -> amo_moModelObject ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +pmoFire -> StretchModel (FLOAT3D (DEMON_STRETCH , DEMON_STRETCH , DEMON_STRETCH )); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetTimerAfter(2.94f - 2.4f); +Jump(STATE_CURRENT, 0x01500007, FALSE, EBegin());return TRUE;}BOOL CDemon::H0x01500007_Fire_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01500008, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDemon::H0x01500008_Fire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500008 +; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +RemoveAttachment (DEMON_ATTACHMENT_FIREBALL ); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +MaybeSwitchToAnotherPlayer (); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +if(IsVisible (m_penEnemy )){ +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +ShootProjectile (PRT_DEMON_FIREBALL , vFireballLaunchPos , ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +else { +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +ShootProjectileAt (m_vPlayerSpotted , PRT_DEMON_FIREBALL , vFireballLaunchPos , ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetTimerAfter(1.0f); +Jump(STATE_CURRENT, 0x01500009, FALSE, EBegin());return TRUE;}BOOL CDemon::H0x01500009_Fire_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0150000a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDemon::H0x0150000a_Fire_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150000a +; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Return(STATE_CURRENT,EReturn ()); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDemon:: +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDemon_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDemon::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +if(!(CalcDist (m_penEnemy ) < 6.0f)){ Jump(STATE_CURRENT,0x01500011, FALSE, EInternal());return TRUE;} +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +StartModelAnim (DEMON_ANIM_WOUND , 0); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetTimerAfter(0.45f); +Jump(STATE_CURRENT, 0x0150000c, FALSE, EBegin());return TRUE;}BOOL CDemon::H0x0150000c_Hit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150000c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0150000d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDemon::H0x0150000d_Hit_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150000d +; +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +if(CalcDist (m_penEnemy ) < CLOSE_ATTACK_RANGE +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +&& IsInPlaneFrustum (m_penEnemy , CosFast (60.0f))) +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +{ +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +vDirection . Normalize (); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 50.0f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +} +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetTimerAfter(1.5f); +Jump(STATE_CURRENT, 0x0150000e, FALSE, EBegin());return TRUE;}BOOL CDemon::H0x0150000e_Hit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0150000f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDemon::H0x0150000f_Hit_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0150000f +; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +MaybeSwitchToAnotherPlayer ();Jump(STATE_CURRENT,0x01500010, FALSE, EInternal());return TRUE;}BOOL CDemon::H0x01500011_Hit_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500011 +{ +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fShootTime = _pTimer -> CurrentTick () + 0.5f; +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +}Jump(STATE_CURRENT,0x01500010, FALSE, EInternal());return TRUE;} +BOOL CDemon::H0x01500010_Hit_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01500010 + +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Return(STATE_CURRENT,EReturn ()); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDemon:: +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDemon_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDemon::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +InitAsModel (); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetCollisionFlags (ECF_MODEL ); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +en_fDensity = 1100.0f; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetModel (MODEL_DEMON ); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +StandingAnim (); +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fWalkSpeed = FRnd () / 1.0f + 12.0f; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 20.0f + 50.0f); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fCloseRunSpeed = FRnd () / 1.0f + 13.0f; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 100 + 900.0f); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fAttackRunSpeed = FRnd () / 1.0f + 9.0f; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 100.0f + 900.0f); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fAttackDistance = 650.0f; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fCloseDistance = 12.0f; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fStopDistance = 0.0f; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fAttackFireTime = 5.0f; +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fCloseFireTime = 1.0f; +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fIgnoreRange = 800.0f; +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fStopDistance = 5.0f; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_tmGiveUp = Max (m_tmGiveUp , 10.0f); +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetHealth (500.0f); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fMaxHealth = GetHealth (); +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +SetModelMainTexture (TEXTURE_DEMON ); +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fBlowUpAmount = 10000.0f; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fBodyParts = 4; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fDamageWounded = 1000.0f; +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_iScore = 5000; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +m_fLockOnEnemyTime = 3.0f; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +GetModelObject () -> StretchModel (FLOAT3D (4.2f , 4.2f , 4.2f)); +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +ModelChangeNotify (); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Demon.es b/Sources/EntitiesMP/Demon.es new file mode 100644 index 0000000..d29f1d2 --- /dev/null +++ b/Sources/EntitiesMP/Demon.es @@ -0,0 +1,336 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +336 + +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/Demon/Demon.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/BasicEffects"; + + +%{ +#define REMINDER_DEATTACH_FIREBALL 666 +#define CLOSE_ATTACK_RANGE 10.0f +#define DEMON_STRETCH 2.5f +FLOAT3D vFireballLaunchPos = (FLOAT3D(0.06f, 2.6f, 0.15f)*DEMON_STRETCH); +static FLOAT _tmLastStandingAnim =0.0f; + +// info structure +static EntityInfo eiDemon = { + EIBT_FLESH, 1600.0f, + 0.0f, 2.0f, 0.0f, // source (eyes) + 0.0f, 1.5f, 0.0f, // target (body) +}; +%} + +class CDemon : CEnemyBase { +name "Demon"; +thumbnail "Thumbnails\\Demon.tbn"; + +properties: + 2 INDEX m_iCounter = 0, + 3 CEntityPointer m_penFireFX, + +components: + 0 class CLASS_BASE "Classes\\EnemyBase.ecl", + 1 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 2 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + + 10 model MODEL_DEMON "ModelsMP\\Enemies\\Demon\\Demon.mdl", + 11 texture TEXTURE_DEMON "ModelsMP\\Enemies\\Demon\\Demon.tex", + 15 model MODEL_FIREBALL "ModelsMP\\Enemies\\Demon\\Projectile\\Projectile.mdl", + 16 texture TEXTURE_FIREBALL "ModelsMP\\Enemies\\Demon\\Projectile\\Projectile.tex", + + // ************** SOUNDS ************** + 50 sound SOUND_IDLE "ModelsMP\\Enemies\\Demon\\Sounds\\Idle.wav", + 51 sound SOUND_SIGHT "ModelsMP\\Enemies\\Demon\\Sounds\\Sight.wav", + 52 sound SOUND_WOUND "ModelsMP\\Enemies\\Demon\\Sounds\\Wound.wav", + 55 sound SOUND_DEATH "ModelsMP\\Enemies\\Demon\\Sounds\\Death.wav", + 57 sound SOUND_CAST "ModelsMP\\Enemies\\Demon\\Sounds\\Cast.wav", + +functions: + + BOOL HandleEvent(const CEntityEvent &ee) + { + // when the shooting of projectile is over, this event comes + // to make sure we deattach the projectile attachment (in case + // the shooting was interrupted + if (ee.ee_slEvent==EVENTCODE_EReminder) + { + EReminder eReminder = ((EReminder &) ee); + if (eReminder.iValue==REMINDER_DEATTACH_FIREBALL) + { + RemoveAttachment(DEMON_ATTACHMENT_FIREBALL); + } + return TRUE; + } + return CEnemyBase::HandleEvent(ee); + } + + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("A Demon executed %s"), strPlayerName); + return str; + } + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnmDemon, "DataMP\\Messages\\Enemies\\Demon.txt"); + return fnmDemon; + } + + void Precache(void) { + CEnemyBase::Precache(); + PrecacheSound(SOUND_IDLE ); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_DEATH); + PrecacheSound(SOUND_CAST); + PrecacheModel(MODEL_DEMON); + PrecacheTexture(TEXTURE_DEMON); + PrecacheModel(MODEL_FIREBALL); + PrecacheTexture(TEXTURE_FIREBALL); + PrecacheClass(CLASS_PROJECTILE, PRT_BEAST_PROJECTILE); + }; + + /* Entity info */ + void *GetEntityInfo(void) { + return &eiDemon; + }; + + BOOL ForcesCannonballToExplode(void) + { + return TRUE; + } + + /*FLOAT GetCrushHealth(void) + { + if (m_bcType == BT_BIG) { + return 100.0f; + } + return 0.0f; + }*/ + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // take less damage from heavy bullets (e.g. sniper) + if(dmtType==DMT_BULLET && fDamageAmmount>100.0f) + { + fDamageAmmount*=0.5f; + } + + // can't harm own class + if (!IsOfClass(penInflictor, "Demon")) { + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + }; + + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + RemoveAttachment(DEMON_ATTACHMENT_FIREBALL); + StartModelAnim(DEMON_ANIM_WOUND, 0); + return DEMON_ANIM_WOUND; + }; + + // death + INDEX AnimForDeath(void) { + if( m_penFireFX != NULL) + { + m_penFireFX->SendEvent(EStop()); + m_penFireFX = NULL; + } + + RemoveAttachment(DEMON_ATTACHMENT_FIREBALL); + StartModelAnim(DEMON_ANIM_DEATHFORWARD, 0); + return DEMON_ANIM_DEATHFORWARD; + }; + + FLOAT WaitForDust(FLOAT3D &vStretch) + { + vStretch=FLOAT3D(1,1,2)*3.0f; + return 1.1f; + }; + + void DeathNotify(void) { + ChangeCollisionBoxIndexWhenPossible(DEMON_COLLISION_BOX_DEATH); + en_fDensity = 500.0f; + }; + + // virtual anim functions + void StandingAnim(void) { + //_tmLastStandingAnim = _pTimer->CurrentTick(); + StartModelAnim(DEMON_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + + void WalkingAnim(void) { + /*if(_pTimer->CurrentTick()>=_tmLastStandingAnim-_pTimer->TickQuantum && + _pTimer->CurrentTick()<=_tmLastStandingAnim+_pTimer->TickQuantum) + { + BREAKPOINT; + }*/ + RunningAnim(); + }; + + void RunningAnim(void) { + StartModelAnim(DEMON_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); + }; + void RotatingAnim(void) { + StartModelAnim(DEMON_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + m_soSound.Set3DParameters(160.0f, 50.0f, 2.0f, 1.0f); + }; + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + Fire(EVoid) : CEnemyBase::Fire + { + + // SetDesiredTranslation??? + if (m_fMoveSpeed>0.0f) { + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, -m_fMoveSpeed)); + } + + //StartModelAnim(DEMON_ANIM_ATTACK, AOF_SMOOTHCHANGE); + StartModelAnim(DEMON_ANIM_ATTACK, 0); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + + PlaySound(m_soSound, SOUND_CAST, SOF_3D); + SpawnReminder(this, 3.0f, REMINDER_DEATTACH_FIREBALL); + + autowait(1.0f); + + // spawn particle effect + CPlacement3D plFX=GetPlacement(); + const FLOATmatrix3D &m = GetRotationMatrix(); + plFX.pl_PositionVector=plFX.pl_PositionVector+vFireballLaunchPos*m; + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_COLLECT_ENERGY; + ese.vStretch = FLOAT3D(1.0f, 1.0f, 1.0f); + m_penFireFX = CreateEntity(plFX, CLASS_BASIC_EFFECT); + m_penFireFX->Initialize(ese); + + autowait(1.4f); + + AddAttachment(DEMON_ATTACHMENT_FIREBALL, MODEL_FIREBALL, TEXTURE_FIREBALL); + CModelObject *pmoFire = &GetModelObject()->GetAttachmentModel(DEMON_ATTACHMENT_FIREBALL)->amo_moModelObject; + pmoFire->StretchModel(FLOAT3D(DEMON_STRETCH, DEMON_STRETCH, DEMON_STRETCH)); + autowait(2.94f-2.4f); + + RemoveAttachment(DEMON_ATTACHMENT_FIREBALL); + MaybeSwitchToAnotherPlayer(); + + if (IsVisible(m_penEnemy)) { + ShootProjectile(PRT_DEMON_FIREBALL, vFireballLaunchPos, ANGLE3D(0.0f, 0.0f, 0.0f)); + } + else { + ShootProjectileAt(m_vPlayerSpotted, PRT_DEMON_FIREBALL, vFireballLaunchPos, ANGLE3D(0.0f, 0.0f, 0.0f)); + } + + autowait(1.0f); + + return EReturn(); + }; + + Hit(EVoid) : CEnemyBase::Hit { + // close attack + if (CalcDist(m_penEnemy) < 6.0f) { + StartModelAnim(DEMON_ANIM_WOUND, 0); + autowait(0.45f); + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + if (CalcDist(m_penEnemy) < CLOSE_ATTACK_RANGE + && IsInPlaneFrustum(m_penEnemy, CosFast(60.0f))) + { + FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.Normalize(); + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 50.0f, FLOAT3D(0, 0, 0), vDirection); + } + autowait(1.5f); + MaybeSwitchToAnotherPlayer(); + } else { + // run to enemy + m_fShootTime = _pTimer->CurrentTick() + 0.5f; + } + return EReturn(); + } + + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + + en_fDensity = 1100.0f; + // set your appearance + SetModel(MODEL_DEMON); + StandingAnim(); + // setup moving speed + m_fWalkSpeed = FRnd()/1.0f + 12.0f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*20.0f + 50.0f); + m_fCloseRunSpeed = FRnd()/1.0f + 13.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 900.0f); + m_fAttackRunSpeed = FRnd()/1.0f + 9.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*100.0f + 900.0f); + // setup attack distances + m_fAttackDistance = 650.0f; + m_fCloseDistance = 12.0f; + m_fStopDistance = 0.0f; + m_fAttackFireTime = 5.0f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 800.0f; + m_fStopDistance = 5.0f; + m_tmGiveUp = Max(m_tmGiveUp, 10.0f); + + // damage/explode properties + SetHealth(500.0f); + m_fMaxHealth = GetHealth(); + SetModelMainTexture(TEXTURE_DEMON); + m_fBlowUpAmount = 10000.0f; + m_fBodyParts = 4; + m_fDamageWounded = 1000.0f; + m_iScore = 5000; + m_fLockOnEnemyTime = 3.0f; + + // set stretch factor + GetModelObject()->StretchModel(FLOAT3D(4.2f, 4.2f, 4.2f)); + ModelChangeNotify(); + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Demon.h b/Sources/EntitiesMP/Demon.h new file mode 100644 index 0000000..9ef3f56 --- /dev/null +++ b/Sources/EntitiesMP/Demon.h @@ -0,0 +1,106 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Demon_INCLUDED +#define _EntitiesMP_Demon_INCLUDED 1 +#include +#include +extern "C" DECL_DLL CDLLEntityClass CDemon_DLLClass; +class CDemon : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + INDEX m_iCounter; + CEntityPointer m_penFireFX; + +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +BOOL HandleEvent(const CEntityEvent & ee); + +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void Precache(void); + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void * GetEntityInfo(void); + +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +BOOL ForcesCannonballToExplode(void); + +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +INDEX AnimForDeath(void); + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void DeathNotify(void); + +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void StandingAnim(void); + +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void WalkingAnim(void); + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void RunningAnim(void); + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void RotatingAnim(void); + +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void IdleSound(void); + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void SightSound(void); + +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void WoundSound(void); + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void DeathSound(void); + +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +void EnemyPostInit(void); +#define STATE_CDemon_Fire 0x01500000 + BOOL +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x01500001_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x01500002_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x01500003_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x01500004_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x01500005_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x01500006_Fire_06(const CEntityEvent &__eeInput); + BOOL H0x01500007_Fire_07(const CEntityEvent &__eeInput); + BOOL H0x01500008_Fire_08(const CEntityEvent &__eeInput); + BOOL H0x01500009_Fire_09(const CEntityEvent &__eeInput); + BOOL H0x0150000a_Fire_10(const CEntityEvent &__eeInput); +#define STATE_CDemon_Hit 0x0150000b + BOOL +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Hit(const CEntityEvent &__eeInput); + BOOL H0x0150000c_Hit_01(const CEntityEvent &__eeInput); + BOOL H0x0150000d_Hit_02(const CEntityEvent &__eeInput); + BOOL H0x0150000e_Hit_03(const CEntityEvent &__eeInput); + BOOL H0x0150000f_Hit_04(const CEntityEvent &__eeInput); + BOOL H0x01500010_Hit_05(const CEntityEvent &__eeInput); + BOOL H0x01500011_Hit_06(const CEntityEvent &__eeInput); +#define STATE_CDemon_Main 1 + BOOL +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Demon_INCLUDED diff --git a/Sources/EntitiesMP/Demon_tables.h b/Sources/EntitiesMP/Demon_tables.h new file mode 100644 index 0000000..06e68aa --- /dev/null +++ b/Sources/EntitiesMP/Demon_tables.h @@ -0,0 +1,79 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CDemon + +CEntityProperty CDemon_properties[] = { + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000150<<8)+2, offsetof(CDemon, m_iCounter), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000150<<8)+3, offsetof(CDemon, m_penFireFX), "", 0, 0, 0), +}; +#define CDemon_propertiesct ARRAYCOUNT(CDemon_properties) + +CEntityComponent CDemon_components[] = { +#define CLASS_BASE ((0x00000150<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_PROJECTILE ((0x00000150<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000150<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define MODEL_DEMON ((0x00000150<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_DEMON, "EFNM" "ModelsMP\\Enemies\\Demon\\Demon.mdl"), +#define TEXTURE_DEMON ((0x00000150<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_DEMON, "EFNM" "ModelsMP\\Enemies\\Demon\\Demon.tex"), +#define MODEL_FIREBALL ((0x00000150<<8)+15) + CEntityComponent(ECT_MODEL, MODEL_FIREBALL, "EFNM" "ModelsMP\\Enemies\\Demon\\Projectile\\Projectile.mdl"), +#define TEXTURE_FIREBALL ((0x00000150<<8)+16) + CEntityComponent(ECT_TEXTURE, TEXTURE_FIREBALL, "EFNM" "ModelsMP\\Enemies\\Demon\\Projectile\\Projectile.tex"), +#define SOUND_IDLE ((0x00000150<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "ModelsMP\\Enemies\\Demon\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000150<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "ModelsMP\\Enemies\\Demon\\Sounds\\Sight.wav"), +#define SOUND_WOUND ((0x00000150<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "ModelsMP\\Enemies\\Demon\\Sounds\\Wound.wav"), +#define SOUND_DEATH ((0x00000150<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "ModelsMP\\Enemies\\Demon\\Sounds\\Death.wav"), +#define SOUND_CAST ((0x00000150<<8)+57) + CEntityComponent(ECT_SOUND, SOUND_CAST, "EFNM" "ModelsMP\\Enemies\\Demon\\Sounds\\Cast.wav"), +}; +#define CDemon_componentsct ARRAYCOUNT(CDemon_components) + +CEventHandlerEntry CDemon_handlers[] = { + {0x01500000, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CDemon:: +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Fire),DEBUGSTRING("CDemon::Fire")}, + {0x01500001, -1, CEntity::pEventHandler(&CDemon::H0x01500001_Fire_01), DEBUGSTRING("CDemon::H0x01500001_Fire_01")}, + {0x01500002, -1, CEntity::pEventHandler(&CDemon::H0x01500002_Fire_02), DEBUGSTRING("CDemon::H0x01500002_Fire_02")}, + {0x01500003, -1, CEntity::pEventHandler(&CDemon::H0x01500003_Fire_03), DEBUGSTRING("CDemon::H0x01500003_Fire_03")}, + {0x01500004, -1, CEntity::pEventHandler(&CDemon::H0x01500004_Fire_04), DEBUGSTRING("CDemon::H0x01500004_Fire_04")}, + {0x01500005, -1, CEntity::pEventHandler(&CDemon::H0x01500005_Fire_05), DEBUGSTRING("CDemon::H0x01500005_Fire_05")}, + {0x01500006, -1, CEntity::pEventHandler(&CDemon::H0x01500006_Fire_06), DEBUGSTRING("CDemon::H0x01500006_Fire_06")}, + {0x01500007, -1, CEntity::pEventHandler(&CDemon::H0x01500007_Fire_07), DEBUGSTRING("CDemon::H0x01500007_Fire_07")}, + {0x01500008, -1, CEntity::pEventHandler(&CDemon::H0x01500008_Fire_08), DEBUGSTRING("CDemon::H0x01500008_Fire_08")}, + {0x01500009, -1, CEntity::pEventHandler(&CDemon::H0x01500009_Fire_09), DEBUGSTRING("CDemon::H0x01500009_Fire_09")}, + {0x0150000a, -1, CEntity::pEventHandler(&CDemon::H0x0150000a_Fire_10), DEBUGSTRING("CDemon::H0x0150000a_Fire_10")}, + {0x0150000b, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CDemon:: +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Hit),DEBUGSTRING("CDemon::Hit")}, + {0x0150000c, -1, CEntity::pEventHandler(&CDemon::H0x0150000c_Hit_01), DEBUGSTRING("CDemon::H0x0150000c_Hit_01")}, + {0x0150000d, -1, CEntity::pEventHandler(&CDemon::H0x0150000d_Hit_02), DEBUGSTRING("CDemon::H0x0150000d_Hit_02")}, + {0x0150000e, -1, CEntity::pEventHandler(&CDemon::H0x0150000e_Hit_03), DEBUGSTRING("CDemon::H0x0150000e_Hit_03")}, + {0x0150000f, -1, CEntity::pEventHandler(&CDemon::H0x0150000f_Hit_04), DEBUGSTRING("CDemon::H0x0150000f_Hit_04")}, + {0x01500010, -1, CEntity::pEventHandler(&CDemon::H0x01500010_Hit_05), DEBUGSTRING("CDemon::H0x01500010_Hit_05")}, + {0x01500011, -1, CEntity::pEventHandler(&CDemon::H0x01500011_Hit_06), DEBUGSTRING("CDemon::H0x01500011_Hit_06")}, + {1, -1, CEntity::pEventHandler(&CDemon:: +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Demon.es" +Main),DEBUGSTRING("CDemon::Main")}, +}; +#define CDemon_handlersct ARRAYCOUNT(CDemon_handlers) + +CEntity *CDemon_New(void) { return new CDemon; }; +void CDemon_OnInitClass(void) {}; +void CDemon_OnEndClass(void) {}; +void CDemon_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CDemon_OnWorldEnd(CWorld *pwo) {}; +void CDemon_OnWorldInit(CWorld *pwo) {}; +void CDemon_OnWorldTick(CWorld *pwo) {}; +void CDemon_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CDemon, CEnemyBase, "Demon", "Thumbnails\\Demon.tbn", 0x00000150); +DECLARE_CTFILENAME(_fnmCDemon_tbn, "Thumbnails\\Demon.tbn"); diff --git a/Sources/EntitiesMP/DestroyableArchitecture.cpp b/Sources/EntitiesMP/DestroyableArchitecture.cpp new file mode 100644 index 0000000..5dd6a8e --- /dev/null +++ b/Sources/EntitiesMP/DestroyableArchitecture.cpp @@ -0,0 +1,612 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" + +#include "StdH.h" +#include "EntitiesMP/Effector.h" +#include "EntitiesMP/MovingBrush.h" + +#include +#include +#line 13 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" + +struct DebrisInfo { + ULONG ulModelID; + ULONG ulTextureID; + FLOAT vOffset[3]; +}; + +static struct DebrisInfo _ObeliskDebrisInfo[] = +{ + { MODEL_OBELISK01, TEXTURE_OBELISK, 0.0f, 114.4989f, 0.0f}, + { MODEL_OBELISK02, TEXTURE_OBELISK, 0.035f, 106.8628f, 0.0f}, + { MODEL_OBELISK03, TEXTURE_OBELISK, 0.0f, 98.628f, 0.0f}, + { MODEL_OBELISK04, TEXTURE_OBELISK, 0.0f, 90.4996f, 0.0f}, + { MODEL_OBELISK05, TEXTURE_OBELISK, 0.0f, 82.174f, 0.0f}, + { MODEL_OBELISK06, TEXTURE_OBELISK, 0.0f, 71.0425f, 0.0f}, + { MODEL_OBELISK07, TEXTURE_OBELISK, 0.0f, 59.2f, 0.0f}, + { MODEL_OBELISK08, TEXTURE_OBELISK, 0.0f, 46.65f, 0.0f}, + { MODEL_OBELISK09, TEXTURE_OBELISK, 0.0f, 36.6f, 0.0f}, +}; + +static struct DebrisInfo _PylonDebrisInfo[] = +{ + { MODEL_PYLON01, TEXTURE_PYLON, -17.3379f, 55.92f, 0}, + { MODEL_PYLON02, TEXTURE_PYLON, -10.525f, 58.045f, 0}, + { MODEL_PYLON03, TEXTURE_PYLON, -17.66f, 42.32f, 0}, + { MODEL_PYLON04, TEXTURE_PYLON, -0.815000f, 54.69f, 0 }, + { MODEL_PYLON05, TEXTURE_PYLON, 14.795f, 51.65f, 0}, + { MODEL_PYLON06, TEXTURE_PYLON, 0.02f, 36.18f, 0}, + { MODEL_PYLON07, TEXTURE_PYLON, -10.289f, 33.982f, 0}, + { MODEL_PYLON08, TEXTURE_PYLON, -22.9152f, 28.6205f, 0}, + { MODEL_PYLON09, TEXTURE_PYLON, 21.932f, 47.2453f, 0}, +}; + +void CDestroyableArchitecture::SetDefaultProperties(void) { + m_strName = "DestroyableArchitecture"; + m_fHealth = -1.0f; + m_etType = ET_DESTROY_OBELISK ; + m_vDamageDir = FLOAT3D(0 , 0 , 0); + m_fStretch = 1.0f; + m_penGradient = NULL; + m_colDebrises = C_WHITE ; + m_ctDebrises = 12; + m_fCandyEffect = 0.0f; + m_fCubeFactor = 1.0f; + m_bBlowupByDamager = FALSE ; + m_fDustStretch = 0.0f; + CMovableBrushEntity::SetDefaultProperties(); +} + +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +void CDestroyableArchitecture::Precache(void) +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheClass (CLASS_DEBRIS , ET_DISAPPEAR_MODEL ); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheClass (CLASS_EFFECTOR , ET_DISAPPEAR_MODEL ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_STONE ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheTexture (TEXTURE_STONE ); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +switch(m_etType ) +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +case ET_DESTROY_OBELISK : +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheTexture (TEXTURE_OBELISK ); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_OBELISK01 ); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_OBELISK02 ); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_OBELISK03 ); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_OBELISK04 ); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_OBELISK05 ); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_OBELISK06 ); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_OBELISK07 ); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_OBELISK08 ); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_OBELISK09 ); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +break ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +case ET_DESTROY_PYLON : +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheTexture (TEXTURE_PYLON ); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_PYLON01 ); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_PYLON02 ); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_PYLON03 ); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_PYLON04 ); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_PYLON05 ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_PYLON06 ); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_PYLON07 ); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_PYLON08 ); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +PrecacheModel (MODEL_PYLON09 ); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +break ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} + +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +BOOL CDestroyableArchitecture::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if(penTarget == NULL ) +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return FALSE ; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if(slPropertyOffset == offsetof (CDestroyableArchitecture , m_penGradient )) +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return (IsDerivedFromClass (penTarget , "Gradient Marker")); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return CEntity :: IsTargetValid (slPropertyOffset , penTarget ); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +const CTString & CDestroyableArchitecture::GetGradientName(INDEX iGradient) +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +static const CTString strDummyName (""); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +static const CTString strMarkerUnused ("Marker not set"); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if(iGradient == 1) +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CGradientMarker * pgm = (CGradientMarker *) & * m_penGradient ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if(pgm != NULL ){ +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return pgm -> GetGradientName (); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +}else { +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return strMarkerUnused ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return strDummyName ; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} + +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +void CDestroyableArchitecture::UncacheShadowsForGradient(class CGradientMarker * penDiscard) +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CGradientMarker * pgm = (CGradientMarker *) & * m_penGradient ; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if(pgm == penDiscard ) +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CEntity :: UncacheShadowsForGradient (1); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +BOOL CDestroyableArchitecture::GetGradient(INDEX iGradient,class CGradientParameters & fpGradient) +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if(iGradient == 1) +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CGradientMarker * pgm = (CGradientMarker *) & * m_penGradient ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if(pgm != NULL ){ +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return pgm -> GetGradient (0 , fpGradient ); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return FALSE ; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} + +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +void CDestroyableArchitecture::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if(m_fHealth < 0){ +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if(m_bBlowupByDamager ) +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if(dmtType == DMT_DAMAGER ) +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CMovableBrushEntity :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +else +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if((dmtType == DMT_EXPLOSION ) || +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +(dmtType == DMT_PROJECTILE ) || +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +(dmtType == DMT_CANNONBALL )) +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CMovableBrushEntity :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} + +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +void CDestroyableArchitecture::DestroyObelisk() +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +for(INDEX iDebris = 0;iDebris < ARRAYCOUNT (_ObeliskDebrisInfo );iDebris ++) +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +DebrisInfo & di = _ObeliskDebrisInfo [ iDebris ]; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT3D vOffset = FLOAT3D (di . vOffset [ 0 ] , di . vOffset [ 1 ] , di . vOffset [ 2 ]) * m_fStretch ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT3D vPos = GetPlacement () . pl_PositionVector + vOffset ; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CEntityPointer penDebris = GetWorld () -> CreateEntity_t ( +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CPlacement3D (vPos , ANGLE3D (0 , 0 , 0)) , CTFILENAME ("Classes\\Debris.ecl")); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +ESpawnDebris eSpawn ; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . fDustStretch = m_fDustStretch ; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . bCustomShading = FALSE ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . bImmaterialASAP = FALSE ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . colDebris = C_WHITE | CT_OPAQUE ; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . Eeibt = EIBT_ROCK ; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . dptParticles = DPT_NONE ; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . betStain = BET_NONE ; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . pmd = GetModelDataForComponent (di . ulModelID ); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . ptd = GetTextureDataForComponent (di . ulTextureID ); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . ptdRefl = NULL ; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . ptdSpec = NULL ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . ptdBump = NULL ; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . iModelAnim = 0; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . fSize = m_fStretch ; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . vStretch = FLOAT3D (1 , 1 , 1); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . penFallFXPapa = NULL ; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +penDebris -> Initialize (eSpawn ); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT fHeightRatio = di . vOffset [ 1 ] * m_fStretch / 120.0f; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT3D vSpeed = FLOAT3D (FRnd () - 0.5f , 0.0f , FRnd () - 0.5f) * (1.0f - fHeightRatio ) * 160.0f; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT3D vRot = FLOAT3D (FRnd () - 0.5f , (FRnd () - 0.5f) * (1.0f - fHeightRatio ) , FRnd () - 0.5f) * 200.0f; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +((CMovableEntity &) * penDebris ) . LaunchAsFreeProjectile (vSpeed , NULL ); +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +((CMovableEntity &) * penDebris ) . SetDesiredRotation (vRot ); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , iten ){ +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +iten -> SendEvent (EBrushDestroyed ()); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +m_fHealth = - 1; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +ForceFullStop (); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetDefaultProperties (); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CPlacement3D plObelisk = GetPlacement (); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +NotifyCollisionChanged (); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetFlags (GetFlags () | ENF_HIDDEN ); +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CEntity * penEffector = CreateEntity (plObelisk , CLASS_EFFECTOR ); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +ESpawnEffector eSpawnEffector ; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawnEffector . tmLifeTime = 6.0f; +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawnEffector . eetType = ET_DESTROY_OBELISK ; +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +penEffector -> Initialize (eSpawnEffector ); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} + +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +void CDestroyableArchitecture::DestroyPylon() +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +for(INDEX iDebris = 0;iDebris < ARRAYCOUNT (_PylonDebrisInfo );iDebris ++) +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +DebrisInfo & di = _PylonDebrisInfo [ iDebris ]; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT3D vOffset = FLOAT3D (di . vOffset [ 0 ] , di . vOffset [ 1 ] , di . vOffset [ 2 ]) * m_fStretch ; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT3D vPos = GetPlacement () . pl_PositionVector + vOffset ; +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CEntityPointer penDebris = GetWorld () -> CreateEntity_t ( +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CPlacement3D (vPos , ANGLE3D (0 , 0 , 0)) , CTFILENAME ("Classes\\Debris.ecl")); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +ESpawnDebris eSpawn ; +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . fDustStretch = m_fDustStretch ; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . bImmaterialASAP = FALSE ; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . bCustomShading = FALSE ; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . colDebris = C_WHITE | CT_OPAQUE ; +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . Eeibt = EIBT_ROCK ; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . dptParticles = DPT_NONE ; +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . betStain = BET_NONE ; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . pmd = GetModelDataForComponent (di . ulModelID ); +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . ptd = GetTextureDataForComponent (di . ulTextureID ); +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . ptdRefl = NULL ; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . ptdSpec = NULL ; +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . ptdBump = NULL ; +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . iModelAnim = 0; +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . fSize = m_fStretch ; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . vStretch = FLOAT3D (1 , 1 , 1); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawn . penFallFXPapa = NULL ; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +penDebris -> Initialize (eSpawn ); +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT fHeightRatio = di . vOffset [ 1 ] * m_fStretch / 120.0f; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT3D vSpeed = (m_vDamageDir * 2.0f + FLOAT3D (FRnd () - 0.5f , 0.0f , FRnd ())) * fHeightRatio * 160.0f; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT3D vRot = FLOAT3D (FRnd () - 0.5f , (FRnd () - 0.5f) * fHeightRatio , FRnd () - 0.5f) * 300.0f; +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +((CMovableEntity &) * penDebris ) . LaunchAsFreeProjectile (vSpeed , NULL ); +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +((CMovableEntity &) * penDebris ) . SetDesiredRotation (vRot ); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , iten ){ +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +iten -> SendEvent (EBrushDestroyed ()); +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +m_fHealth = - 1; +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CPlacement3D plObelisk = GetPlacement (); +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +CEntity * penEffector = CreateEntity (plObelisk , CLASS_EFFECTOR ); +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +ESpawnEffector eSpawnEffector ; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawnEffector . eetType = ET_DESTROY_PYLON ; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawnEffector . tmLifeTime = 6.0f; +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +eSpawnEffector . vDamageDir = m_vDamageDir ; +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +penEffector -> Initialize (eSpawnEffector ); +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +ForceFullStop (); +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetDefaultProperties (); +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +NotifyCollisionChanged (); +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetFlags (GetFlags () | ENF_HIDDEN ); +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} + +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SLONG CDestroyableArchitecture::GetUsedMemory(void) +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SLONG slUsedMemory = sizeof (CDestroyableArchitecture ) - sizeof (CMovableBrushEntity ) + CMovableBrushEntity :: GetUsedMemory (); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +slUsedMemory += m_strName . Length (); +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return slUsedMemory ; +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +BOOL CDestroyableArchitecture:: +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDestroyableArchitecture_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDestroyableArchitecture::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +InitAsBrush (); +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetPhysicsFlags (EPF_BRUSH_MOVING ); +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetCollisionFlags (ECF_BRUSH ); +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetFlags (GetFlags () & ~ ENF_ZONING ); +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetHealth (m_fHealth ); +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x006b0000, FALSE, EBegin());return TRUE;}BOOL CDestroyableArchitecture::H0x006b0000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x006b0000 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return TRUE; +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +}ASSERT(FALSE);break;case(EVENTCODE_EBrushDestroyedByDevil): +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{const EBrushDestroyedByDevil&ebdbd= (EBrushDestroyedByDevil&)__eeInput; + +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +m_vDamageDir = ebdbd . vDamageDir ; +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +switch(m_etType ) +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +case ET_DESTROY_OBELISK : +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +DestroyObelisk (); +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +break ; +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +case ET_DESTROY_PYLON : +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +DestroyPylon (); +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +break ; +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +UnsetTimer();Jump(STATE_CURRENT,0x006b0001, FALSE, EInternal());return TRUE; +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOATaabbox3D box ; +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +GetSize (box ); +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +if(m_ctDebrises <= 0) +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{ +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +m_ctDebrises = 1; +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT fEntitySize = pow (box . Size () (1) * box . Size () (2) * box . Size () (3) / m_ctDebrises , 1.0f / 3.0f) * m_fCubeFactor ; +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +Debris_Begin (EIBT_ROCK , DPT_NONE , BET_NONE , fEntitySize , FLOAT3D (1.0f , 2.0f , 3.0f) , +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT3D (0 , 0 , 0) , 1.0f + m_fCandyEffect / 2.0f , m_fCandyEffect , m_colDebrises ); +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +for(INDEX iDebris = 0;iDebris < m_ctDebrises ;iDebris ++){ +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +Debris_Spawn (this , this , MODEL_STONE , TEXTURE_STONE , 0 , 0 , 0 , IRnd () % 4 , 1.0f , +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT3D (FRnd () * 0.8f + 0.1f , FRnd () * 0.8f + 0.1f , FRnd () * 0.8f + 0.1f)); +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , iten ){ +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +iten -> SendEvent (EBrushDestroyed ()); +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +} +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +m_fHealth = - 1; +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +ForceFullStop (); +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetDefaultProperties (); +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +NotifyCollisionChanged (); +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetFlags (GetFlags () | ENF_HIDDEN ); +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , itenChild ){ +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +itenChild -> SendEvent (ERangeModelDestruction ()); +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +}} +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +UnsetTimer();Jump(STATE_CURRENT,0x006b0001, FALSE, EInternal());return TRUE; +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn): +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +{const EReturn&e= (EReturn&)__eeInput; + +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +UnsetTimer();Jump(STATE_CURRENT,0x006b0001, FALSE, EInternal());return TRUE; +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +}return TRUE;}BOOL CDestroyableArchitecture::H0x006b0001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x006b0001 + +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +Return(STATE_CURRENT,EVoid()); +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/DestroyableArchitecture.es b/Sources/EntitiesMP/DestroyableArchitecture.es new file mode 100644 index 0000000..dfabe3a --- /dev/null +++ b/Sources/EntitiesMP/DestroyableArchitecture.es @@ -0,0 +1,445 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +107 +%{ +#include "StdH.h" +#include "EntitiesMP/Effector.h" +#include "EntitiesMP/MovingBrush.h" +%} +uses "EntitiesMP/Devil"; +uses "EntitiesMP/Debris"; +uses "EntitiesMP\GradientMarker"; + +%{ +struct DebrisInfo { + ULONG ulModelID; + ULONG ulTextureID; + FLOAT vOffset[3]; +}; + +static struct DebrisInfo _ObeliskDebrisInfo[] = +{ + { MODEL_OBELISK01, TEXTURE_OBELISK, 0.0f, 114.4989f, 0.0f}, + { MODEL_OBELISK02, TEXTURE_OBELISK, 0.035f, 106.8628f, 0.0f}, + { MODEL_OBELISK03, TEXTURE_OBELISK, 0.0f, 98.628f, 0.0f}, + { MODEL_OBELISK04, TEXTURE_OBELISK, 0.0f, 90.4996f, 0.0f}, + { MODEL_OBELISK05, TEXTURE_OBELISK, 0.0f, 82.174f, 0.0f}, + { MODEL_OBELISK06, TEXTURE_OBELISK, 0.0f, 71.0425f, 0.0f}, + { MODEL_OBELISK07, TEXTURE_OBELISK, 0.0f, 59.2f, 0.0f}, + { MODEL_OBELISK08, TEXTURE_OBELISK, 0.0f, 46.65f, 0.0f}, + { MODEL_OBELISK09, TEXTURE_OBELISK, 0.0f, 36.6f, 0.0f}, +}; + +static struct DebrisInfo _PylonDebrisInfo[] = +{ + { MODEL_PYLON01, TEXTURE_PYLON, -17.3379f, 55.92f, 0}, + { MODEL_PYLON02, TEXTURE_PYLON, -10.525f, 58.045f, 0}, + { MODEL_PYLON03, TEXTURE_PYLON, -17.66f, 42.32f, 0}, + { MODEL_PYLON04, TEXTURE_PYLON, -0.815000f, 54.69f, 0 }, + { MODEL_PYLON05, TEXTURE_PYLON, 14.795f, 51.65f, 0}, + { MODEL_PYLON06, TEXTURE_PYLON, 0.02f, 36.18f, 0}, + { MODEL_PYLON07, TEXTURE_PYLON, -10.289f, 33.982f, 0}, + { MODEL_PYLON08, TEXTURE_PYLON, -22.9152f, 28.6205f, 0}, + { MODEL_PYLON09, TEXTURE_PYLON, 21.932f, 47.2453f, 0}, +}; +%} + +class CDestroyableArchitecture: CMovableBrushEntity { +name "DestroyableArchitecture"; +thumbnail "Thumbnails\\DestroyableArchitecture.tbn"; +features "HasName", "IsTargetable"; + +properties: + + 1 CTString m_strName "Name" 'N' = "DestroyableArchitecture", // name + 2 FLOAT m_fHealth "Health" 'H' = -1.0f, // health + 3 enum EffectorEffectType m_etType "Type" 'Y' = ET_DESTROY_OBELISK, // name + 4 FLOAT3D m_vDamageDir = FLOAT3D(0,0,0), // direction of damage + 5 FLOAT m_fStretch "Stretch" 'S' = 1.0f, // debris stretch + 6 CEntityPointer m_penGradient "Gradient" 'R', + + 10 COLOR m_colDebrises "Color of debrises" = C_WHITE, + 11 INDEX m_ctDebrises "Debris count" = 12, + 12 FLOAT m_fCandyEffect "Debris blow power" = 0.0f, + 13 FLOAT m_fCubeFactor "Cube factor" = 1.0f, + 14 BOOL m_bBlowupByDamager "Blowup by Damager" = FALSE, // if only damager can destroy brush + 15 FLOAT m_fDustStretch "Dust stretch" = 0.0f, + + +components: + +// ************** DEBRIS PARTS ************** + 10 texture TEXTURE_OBELISK "Models\\CutSequences\\Obelisk\\Obelisk.tex", + 11 model MODEL_OBELISK01 "Models\\CutSequences\\Obelisk\\Part01.mdl", + 12 model MODEL_OBELISK02 "Models\\CutSequences\\Obelisk\\Part02.mdl", + 13 model MODEL_OBELISK03 "Models\\CutSequences\\Obelisk\\Part03.mdl", + 14 model MODEL_OBELISK04 "Models\\CutSequences\\Obelisk\\Part04.mdl", + 15 model MODEL_OBELISK05 "Models\\CutSequences\\Obelisk\\Part05.mdl", + 16 model MODEL_OBELISK06 "Models\\CutSequences\\Obelisk\\Part06.mdl", + 17 model MODEL_OBELISK07 "Models\\CutSequences\\Obelisk\\Part07.mdl", + 18 model MODEL_OBELISK08 "Models\\CutSequences\\Obelisk\\Part08.mdl", + 19 model MODEL_OBELISK09 "Models\\CutSequences\\Obelisk\\Part09.mdl", + + 20 texture TEXTURE_PYLON "Models\\CutSequences\\Pylon\\Pylon.tex", + 21 model MODEL_PYLON01 "Models\\CutSequences\\Pylon\\Part01.mdl", + 22 model MODEL_PYLON02 "Models\\CutSequences\\Pylon\\Part02.mdl", + 23 model MODEL_PYLON03 "Models\\CutSequences\\Pylon\\Part03.mdl", + 24 model MODEL_PYLON04 "Models\\CutSequences\\Pylon\\Part04.mdl", + 25 model MODEL_PYLON05 "Models\\CutSequences\\Pylon\\Part05.mdl", + 26 model MODEL_PYLON06 "Models\\CutSequences\\Pylon\\Part06.mdl", + 27 model MODEL_PYLON07 "Models\\CutSequences\\Pylon\\Part07.mdl", + 28 model MODEL_PYLON08 "Models\\CutSequences\\Pylon\\Part08.mdl", + 29 model MODEL_PYLON09 "Models\\CutSequences\\Pylon\\Part09.mdl", + +// ************** NEEDED CLASSES ************** + 30 class CLASS_DEBRIS "Classes\\Debris.ecl", + 31 class CLASS_EFFECTOR "Classes\\Effector.ecl", + +// ************** STONE PARTS ************** + 32 model MODEL_STONE "Models\\Effects\\Debris\\Stone\\Stone.mdl", + 33 texture TEXTURE_STONE "Models\\Effects\\Debris\\Stone\\Stone.tex", + + +functions: + + void Precache(void) + { + PrecacheClass (CLASS_DEBRIS , ET_DISAPPEAR_MODEL); + PrecacheClass (CLASS_EFFECTOR , ET_DISAPPEAR_MODEL); + PrecacheModel (MODEL_STONE ); + PrecacheTexture (TEXTURE_STONE ); + // precache acording to destroying architecture + switch( m_etType) + { + case ET_DESTROY_OBELISK: + PrecacheTexture (TEXTURE_OBELISK ); + PrecacheModel (MODEL_OBELISK01 ); + PrecacheModel (MODEL_OBELISK02 ); + PrecacheModel (MODEL_OBELISK03 ); + PrecacheModel (MODEL_OBELISK04 ); + PrecacheModel (MODEL_OBELISK05 ); + PrecacheModel (MODEL_OBELISK06 ); + PrecacheModel (MODEL_OBELISK07 ); + PrecacheModel (MODEL_OBELISK08 ); + PrecacheModel (MODEL_OBELISK09 ); + break; + case ET_DESTROY_PYLON: + PrecacheTexture (TEXTURE_PYLON ); + PrecacheModel (MODEL_PYLON01 ); + PrecacheModel (MODEL_PYLON02 ); + PrecacheModel (MODEL_PYLON03 ); + PrecacheModel (MODEL_PYLON04 ); + PrecacheModel (MODEL_PYLON05 ); + PrecacheModel (MODEL_PYLON06 ); + PrecacheModel (MODEL_PYLON07 ); + PrecacheModel (MODEL_PYLON08 ); + PrecacheModel (MODEL_PYLON09 ); + break; + } + } + + // Validate offered target for one property + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if(penTarget==NULL) + { + return FALSE; + } + + // if gradient marker + if( slPropertyOffset==offsetof(CDestroyableArchitecture, m_penGradient) ) + { + return (IsDerivedFromClass(penTarget, "Gradient Marker")); + } + return CEntity::IsTargetValid(slPropertyOffset, penTarget); + } + + /* Get gradient type name, return empty string if not used. */ + const CTString &GetGradientName(INDEX iGradient) + { + static const CTString strDummyName(""); + static const CTString strMarkerUnused("Marker not set"); + if (iGradient==1) + { + CGradientMarker *pgm = (CGradientMarker *)&*m_penGradient; + if (pgm != NULL) { + return pgm->GetGradientName(); + } else { + return strMarkerUnused; + } + } + return strDummyName; + } + /* Uncache shadows for given gradient */ + void UncacheShadowsForGradient(class CGradientMarker *penDiscard) + { + CGradientMarker *pgm = (CGradientMarker *)&*m_penGradient; + if(pgm == penDiscard) + { + CEntity::UncacheShadowsForGradient(1); + } + } + + /* Get gradient, return FALSE for none. */ + BOOL GetGradient(INDEX iGradient, class CGradientParameters &fpGradient) + { + if ( iGradient==1) + { + CGradientMarker *pgm = (CGradientMarker *)&*m_penGradient; + if (pgm != NULL) { + return pgm->GetGradient(0, fpGradient); + } + } + return FALSE; + } + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // if not destroyable + if(m_fHealth<0) { + // ignore damages + return; + } + + if(m_bBlowupByDamager) + { + if( dmtType == DMT_DAMAGER) + { + CMovableBrushEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + } + else + { + // react only on explosions + if( (dmtType == DMT_EXPLOSION) || + (dmtType == DMT_PROJECTILE) || + (dmtType == DMT_CANNONBALL) ) + { + CMovableBrushEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + } + } + + void DestroyObelisk() + { + for( INDEX iDebris=0; iDebrisCreateEntity_t( + CPlacement3D(vPos, ANGLE3D(0,0,0)), CTFILENAME("Classes\\Debris.ecl")); + // prepare parameters + ESpawnDebris eSpawn; + eSpawn.fDustStretch=m_fDustStretch; + eSpawn.bCustomShading=FALSE; + eSpawn.bImmaterialASAP=FALSE; + eSpawn.colDebris = C_WHITE|CT_OPAQUE; + eSpawn.Eeibt = EIBT_ROCK; + eSpawn.dptParticles = DPT_NONE; + eSpawn.betStain = BET_NONE; + eSpawn.pmd = GetModelDataForComponent(di.ulModelID); + eSpawn.ptd = GetTextureDataForComponent(di.ulTextureID); + eSpawn.ptdRefl = NULL; + eSpawn.ptdSpec = NULL; + eSpawn.ptdBump = NULL; + eSpawn.iModelAnim = 0; + eSpawn.fSize = m_fStretch; + eSpawn.vStretch = FLOAT3D(1,1,1); + eSpawn.penFallFXPapa=NULL; + // initialize it + penDebris->Initialize(eSpawn); + + // speed it up + FLOAT fHeightRatio = di.vOffset[1]*m_fStretch/120.0f; + FLOAT3D vSpeed = FLOAT3D( FRnd()-0.5f, 0.0f, FRnd()-0.5f)*(1.0f-fHeightRatio)*160.0f; + FLOAT3D vRot = FLOAT3D( FRnd()-0.5f, (FRnd()-0.5f)*(1.0f-fHeightRatio), FRnd()-0.5f)*200.0f; + /* + vSpeed = FLOAT3D( 0,0,0); + vRot = FLOAT3D( 0,0,0);*/ + ((CMovableEntity&)*penDebris).LaunchAsFreeProjectile( vSpeed, NULL); + ((CMovableEntity&)*penDebris).SetDesiredRotation( vRot); + } + + // notify children + FOREACHINLIST( CEntity, en_lnInParent, en_lhChildren, iten) { + iten->SendEvent( EBrushDestroyed()); + } + m_fHealth = -1; + ForceFullStop(); + SetDefaultProperties(); + + CPlacement3D plObelisk = GetPlacement(); + + // notify engine to kickstart entities that are cached in stationary position, + // before we turn off, so they can fall + NotifyCollisionChanged(); + SetFlags( GetFlags()|ENF_HIDDEN); + SetCollisionFlags(ECF_IMMATERIAL); + + // spawn spray spray + CEntity *penEffector = CreateEntity( plObelisk, CLASS_EFFECTOR); + // set spawn parameters + ESpawnEffector eSpawnEffector; + eSpawnEffector.tmLifeTime = 6.0f; + eSpawnEffector.eetType = ET_DESTROY_OBELISK; + // initialize spray + penEffector->Initialize( eSpawnEffector); + } + + void DestroyPylon() + { + for( INDEX iDebris=0; iDebrisCreateEntity_t( + CPlacement3D(vPos, ANGLE3D(0,0,0)), CTFILENAME("Classes\\Debris.ecl")); + // prepare parameters + ESpawnDebris eSpawn; + eSpawn.fDustStretch=m_fDustStretch; + eSpawn.bImmaterialASAP=FALSE; + eSpawn.bCustomShading=FALSE; + eSpawn.colDebris = C_WHITE|CT_OPAQUE; + eSpawn.Eeibt = EIBT_ROCK; + eSpawn.dptParticles = DPT_NONE; + eSpawn.betStain = BET_NONE; + eSpawn.pmd = GetModelDataForComponent(di.ulModelID); + eSpawn.ptd = GetTextureDataForComponent(di.ulTextureID); + eSpawn.ptdRefl = NULL; + eSpawn.ptdSpec = NULL; + eSpawn.ptdBump = NULL; + eSpawn.iModelAnim = 0; + eSpawn.fSize = m_fStretch; + eSpawn.vStretch = FLOAT3D(1,1,1); + eSpawn.penFallFXPapa=NULL; + // initialize it + penDebris->Initialize(eSpawn); + + // speed it up + FLOAT fHeightRatio = di.vOffset[1]*m_fStretch/120.0f; + FLOAT3D vSpeed = (m_vDamageDir*2.0f+FLOAT3D( FRnd()-0.5f, 0.0f, FRnd()))*fHeightRatio*160.0f; + FLOAT3D vRot = FLOAT3D( FRnd()-0.5f, (FRnd()-0.5f)*fHeightRatio, FRnd()-0.5f)*300.0f; + ((CMovableEntity&)*penDebris).LaunchAsFreeProjectile( vSpeed, NULL); + ((CMovableEntity&)*penDebris).SetDesiredRotation( vRot); + } + + // notify children + FOREACHINLIST( CEntity, en_lnInParent, en_lhChildren, iten) { + iten->SendEvent( EBrushDestroyed()); + } + m_fHealth = -1; + CPlacement3D plObelisk = GetPlacement(); + // spawn spray spray + CEntity *penEffector = CreateEntity( plObelisk, CLASS_EFFECTOR); + // set spawn parameters + ESpawnEffector eSpawnEffector; + eSpawnEffector.eetType = ET_DESTROY_PYLON; + eSpawnEffector.tmLifeTime = 6.0f; + eSpawnEffector.vDamageDir = m_vDamageDir; + // initialize spray + penEffector->Initialize( eSpawnEffector); + + ForceFullStop(); + SetDefaultProperties(); + // notify engine to kickstart entities that are cached in stationary position, + // before we turn off, so they can fall + NotifyCollisionChanged(); + SetFlags( GetFlags()|ENF_HIDDEN); + SetCollisionFlags(ECF_IMMATERIAL); + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CDestroyableArchitecture) - sizeof(CMovableBrushEntity) + CMovableBrushEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strName.Length(); + return slUsedMemory; + } + + + +procedures: + + + Main() { + // declare yourself as a brush + InitAsBrush(); + SetPhysicsFlags(EPF_BRUSH_MOVING); + SetCollisionFlags(ECF_BRUSH); + // non-zoning brush + SetFlags(GetFlags()&~ENF_ZONING); + SetHealth(m_fHealth); + + // start moving + wait() { + on (EBegin) : { + resume; + } + on (EBrushDestroyedByDevil ebdbd) : + { + m_vDamageDir = ebdbd.vDamageDir; + switch( m_etType) + { + case ET_DESTROY_OBELISK: + DestroyObelisk(); + break; + case ET_DESTROY_PYLON: + DestroyPylon(); + break; + } + stop; + } + on (EDeath eDeath) : { + // get your size + FLOATaabbox3D box; + GetSize(box); + if( m_ctDebrises<=0) + { + m_ctDebrises=1; + } + FLOAT fEntitySize = pow(box.Size()(1)*box.Size()(2)*box.Size()(3)/m_ctDebrises, 1.0f/3.0f)*m_fCubeFactor; + + Debris_Begin(EIBT_ROCK, DPT_NONE, BET_NONE, fEntitySize, FLOAT3D(1.0f,2.0f,3.0f), + FLOAT3D(0,0,0), 1.0f+m_fCandyEffect/2.0f, m_fCandyEffect, m_colDebrises); + for(INDEX iDebris = 0; iDebrisSendEvent( EBrushDestroyed()); + } + + m_fHealth = -1; + ForceFullStop(); + SetDefaultProperties(); + // notify engine to kickstart entities that are cached in stationary position, + // before we turn off, so they can fall + NotifyCollisionChanged(); + SetFlags( GetFlags()|ENF_HIDDEN); + SetCollisionFlags(ECF_IMMATERIAL); + + // for each child of this entity + {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { + // send it destruction event + itenChild->SendEvent(ERangeModelDestruction()); + }} + + stop; + } + on (EReturn) : + { + stop; + } + } + return; + } +}; diff --git a/Sources/EntitiesMP/DestroyableArchitecture.h b/Sources/EntitiesMP/DestroyableArchitecture.h new file mode 100644 index 0000000..69d6dc6 --- /dev/null +++ b/Sources/EntitiesMP/DestroyableArchitecture.h @@ -0,0 +1,64 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_DestroyableArchitecture_INCLUDED +#define _EntitiesMP_DestroyableArchitecture_INCLUDED 1 +#include +#include +#include +extern "C" DECL_DLL CDLLEntityClass CDestroyableArchitecture_DLLClass; +class CDestroyableArchitecture : public CMovableBrushEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + FLOAT m_fHealth; + enum EffectorEffectType m_etType; + FLOAT3D m_vDamageDir; + FLOAT m_fStretch; + CEntityPointer m_penGradient; + COLOR m_colDebrises; + INDEX m_ctDebrises; + FLOAT m_fCandyEffect; + FLOAT m_fCubeFactor; + BOOL m_bBlowupByDamager; + FLOAT m_fDustStretch; + +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +void Precache(void); + +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +const CTString & GetGradientName(INDEX iGradient); + +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +void UncacheShadowsForGradient(class CGradientMarker * penDiscard); + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +BOOL GetGradient(INDEX iGradient,class CGradientParameters & fpGradient); + +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +void DestroyObelisk(); + +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +void DestroyPylon(); + +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +SLONG GetUsedMemory(void); +#define STATE_CDestroyableArchitecture_Main 1 + BOOL +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x006b0000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x006b0001_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_DestroyableArchitecture_INCLUDED diff --git a/Sources/EntitiesMP/DestroyableArchitecture_tables.h b/Sources/EntitiesMP/DestroyableArchitecture_tables.h new file mode 100644 index 0000000..8354910 --- /dev/null +++ b/Sources/EntitiesMP/DestroyableArchitecture_tables.h @@ -0,0 +1,93 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CDestroyableArchitecture + +CEntityProperty CDestroyableArchitecture_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x0000006b<<8)+1, offsetof(CDestroyableArchitecture, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000006b<<8)+2, offsetof(CDestroyableArchitecture, m_fHealth), "Health", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EffectorEffectType_enum, (0x0000006b<<8)+3, offsetof(CDestroyableArchitecture, m_etType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000006b<<8)+4, offsetof(CDestroyableArchitecture, m_vDamageDir), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000006b<<8)+5, offsetof(CDestroyableArchitecture, m_fStretch), "Stretch", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000006b<<8)+6, offsetof(CDestroyableArchitecture, m_penGradient), "Gradient", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000006b<<8)+10, offsetof(CDestroyableArchitecture, m_colDebrises), "Color of debrises", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000006b<<8)+11, offsetof(CDestroyableArchitecture, m_ctDebrises), "Debris count", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000006b<<8)+12, offsetof(CDestroyableArchitecture, m_fCandyEffect), "Debris blow power", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000006b<<8)+13, offsetof(CDestroyableArchitecture, m_fCubeFactor), "Cube factor", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000006b<<8)+14, offsetof(CDestroyableArchitecture, m_bBlowupByDamager), "Blowup by Damager", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000006b<<8)+15, offsetof(CDestroyableArchitecture, m_fDustStretch), "Dust stretch", 0, 0x7F0000FFUL, 0), +}; +#define CDestroyableArchitecture_propertiesct ARRAYCOUNT(CDestroyableArchitecture_properties) + +CEntityComponent CDestroyableArchitecture_components[] = { +#define TEXTURE_OBELISK ((0x0000006b<<8)+10) + CEntityComponent(ECT_TEXTURE, TEXTURE_OBELISK, "EFNM" "Models\\CutSequences\\Obelisk\\Obelisk.tex"), +#define MODEL_OBELISK01 ((0x0000006b<<8)+11) + CEntityComponent(ECT_MODEL, MODEL_OBELISK01, "EFNM" "Models\\CutSequences\\Obelisk\\Part01.mdl"), +#define MODEL_OBELISK02 ((0x0000006b<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_OBELISK02, "EFNM" "Models\\CutSequences\\Obelisk\\Part02.mdl"), +#define MODEL_OBELISK03 ((0x0000006b<<8)+13) + CEntityComponent(ECT_MODEL, MODEL_OBELISK03, "EFNM" "Models\\CutSequences\\Obelisk\\Part03.mdl"), +#define MODEL_OBELISK04 ((0x0000006b<<8)+14) + CEntityComponent(ECT_MODEL, MODEL_OBELISK04, "EFNM" "Models\\CutSequences\\Obelisk\\Part04.mdl"), +#define MODEL_OBELISK05 ((0x0000006b<<8)+15) + CEntityComponent(ECT_MODEL, MODEL_OBELISK05, "EFNM" "Models\\CutSequences\\Obelisk\\Part05.mdl"), +#define MODEL_OBELISK06 ((0x0000006b<<8)+16) + CEntityComponent(ECT_MODEL, MODEL_OBELISK06, "EFNM" "Models\\CutSequences\\Obelisk\\Part06.mdl"), +#define MODEL_OBELISK07 ((0x0000006b<<8)+17) + CEntityComponent(ECT_MODEL, MODEL_OBELISK07, "EFNM" "Models\\CutSequences\\Obelisk\\Part07.mdl"), +#define MODEL_OBELISK08 ((0x0000006b<<8)+18) + CEntityComponent(ECT_MODEL, MODEL_OBELISK08, "EFNM" "Models\\CutSequences\\Obelisk\\Part08.mdl"), +#define MODEL_OBELISK09 ((0x0000006b<<8)+19) + CEntityComponent(ECT_MODEL, MODEL_OBELISK09, "EFNM" "Models\\CutSequences\\Obelisk\\Part09.mdl"), +#define TEXTURE_PYLON ((0x0000006b<<8)+20) + CEntityComponent(ECT_TEXTURE, TEXTURE_PYLON, "EFNM" "Models\\CutSequences\\Pylon\\Pylon.tex"), +#define MODEL_PYLON01 ((0x0000006b<<8)+21) + CEntityComponent(ECT_MODEL, MODEL_PYLON01, "EFNM" "Models\\CutSequences\\Pylon\\Part01.mdl"), +#define MODEL_PYLON02 ((0x0000006b<<8)+22) + CEntityComponent(ECT_MODEL, MODEL_PYLON02, "EFNM" "Models\\CutSequences\\Pylon\\Part02.mdl"), +#define MODEL_PYLON03 ((0x0000006b<<8)+23) + CEntityComponent(ECT_MODEL, MODEL_PYLON03, "EFNM" "Models\\CutSequences\\Pylon\\Part03.mdl"), +#define MODEL_PYLON04 ((0x0000006b<<8)+24) + CEntityComponent(ECT_MODEL, MODEL_PYLON04, "EFNM" "Models\\CutSequences\\Pylon\\Part04.mdl"), +#define MODEL_PYLON05 ((0x0000006b<<8)+25) + CEntityComponent(ECT_MODEL, MODEL_PYLON05, "EFNM" "Models\\CutSequences\\Pylon\\Part05.mdl"), +#define MODEL_PYLON06 ((0x0000006b<<8)+26) + CEntityComponent(ECT_MODEL, MODEL_PYLON06, "EFNM" "Models\\CutSequences\\Pylon\\Part06.mdl"), +#define MODEL_PYLON07 ((0x0000006b<<8)+27) + CEntityComponent(ECT_MODEL, MODEL_PYLON07, "EFNM" "Models\\CutSequences\\Pylon\\Part07.mdl"), +#define MODEL_PYLON08 ((0x0000006b<<8)+28) + CEntityComponent(ECT_MODEL, MODEL_PYLON08, "EFNM" "Models\\CutSequences\\Pylon\\Part08.mdl"), +#define MODEL_PYLON09 ((0x0000006b<<8)+29) + CEntityComponent(ECT_MODEL, MODEL_PYLON09, "EFNM" "Models\\CutSequences\\Pylon\\Part09.mdl"), +#define CLASS_DEBRIS ((0x0000006b<<8)+30) + CEntityComponent(ECT_CLASS, CLASS_DEBRIS, "EFNM" "Classes\\Debris.ecl"), +#define CLASS_EFFECTOR ((0x0000006b<<8)+31) + CEntityComponent(ECT_CLASS, CLASS_EFFECTOR, "EFNM" "Classes\\Effector.ecl"), +#define MODEL_STONE ((0x0000006b<<8)+32) + CEntityComponent(ECT_MODEL, MODEL_STONE, "EFNM" "Models\\Effects\\Debris\\Stone\\Stone.mdl"), +#define TEXTURE_STONE ((0x0000006b<<8)+33) + CEntityComponent(ECT_TEXTURE, TEXTURE_STONE, "EFNM" "Models\\Effects\\Debris\\Stone\\Stone.tex"), +}; +#define CDestroyableArchitecture_componentsct ARRAYCOUNT(CDestroyableArchitecture_components) + +CEventHandlerEntry CDestroyableArchitecture_handlers[] = { + {1, -1, CEntity::pEventHandler(&CDestroyableArchitecture:: +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/DestroyableArchitecture.es" +Main),DEBUGSTRING("CDestroyableArchitecture::Main")}, + {0x006b0000, -1, CEntity::pEventHandler(&CDestroyableArchitecture::H0x006b0000_Main_01), DEBUGSTRING("CDestroyableArchitecture::H0x006b0000_Main_01")}, + {0x006b0001, -1, CEntity::pEventHandler(&CDestroyableArchitecture::H0x006b0001_Main_02), DEBUGSTRING("CDestroyableArchitecture::H0x006b0001_Main_02")}, +}; +#define CDestroyableArchitecture_handlersct ARRAYCOUNT(CDestroyableArchitecture_handlers) + +CEntity *CDestroyableArchitecture_New(void) { return new CDestroyableArchitecture; }; +void CDestroyableArchitecture_OnInitClass(void) {}; +void CDestroyableArchitecture_OnEndClass(void) {}; +void CDestroyableArchitecture_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CDestroyableArchitecture_OnWorldEnd(CWorld *pwo) {}; +void CDestroyableArchitecture_OnWorldInit(CWorld *pwo) {}; +void CDestroyableArchitecture_OnWorldTick(CWorld *pwo) {}; +void CDestroyableArchitecture_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CDestroyableArchitecture, CMovableBrushEntity, "DestroyableArchitecture", "Thumbnails\\DestroyableArchitecture.tbn", 0x0000006b); +DECLARE_CTFILENAME(_fnmCDestroyableArchitecture_tbn, "Thumbnails\\DestroyableArchitecture.tbn"); diff --git a/Sources/EntitiesMP/Devil.cpp b/Sources/EntitiesMP/Devil.cpp new file mode 100644 index 0000000..da3a959 --- /dev/null +++ b/Sources/EntitiesMP/Devil.cpp @@ -0,0 +1,4726 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" + +#include "StdH.h" +#include "Models/Enemies/Devil/Devil.h" +#include "Models/Enemies/Devil/Weapons/Laser.h" +#include "Models/Weapons/RocketLauncher/RocketLauncherItem.h" +#include "EntitiesMP/Effector.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/PyramidSpaceShip.h" +#include "EntitiesMP/BackgroundViewer.h" + +#define DEVIL_LASER_SPEED 100.0f +#define DEVIL_ROCKET_SPEED 60.0f + +#include +#include +CEntityEvent *EBrushDestroyedByDevil::MakeCopy(void) { CEntityEvent *peeCopy = new EBrushDestroyedByDevil(*this); return peeCopy;} +EBrushDestroyedByDevil::EBrushDestroyedByDevil() : CEntityEvent(EVENTCODE_EBrushDestroyedByDevil) {; + ClearToDefault(vDamageDir); +}; +CEntityEvent *ERegenerationImpuls::MakeCopy(void) { CEntityEvent *peeCopy = new ERegenerationImpuls(*this); return peeCopy;} +ERegenerationImpuls::ERegenerationImpuls() : CEntityEvent(EVENTCODE_ERegenerationImpuls) {; +}; +CEntityEvent *EDevilCommand::MakeCopy(void) { CEntityEvent *peeCopy = new EDevilCommand(*this); return peeCopy;} +EDevilCommand::EDevilCommand() : CEntityEvent(EVENTCODE_EDevilCommand) {; + ClearToDefault(dctType); + ClearToDefault(penForcedAction); + ClearToDefault(fAttackRadius); + ClearToDefault(vCenterOfAttack); +}; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" + +static FLOAT3D vLastStartPosition; +static FLOAT vLastAttackRadius; + +extern INDEX cht_bKillFinalBoss; +extern INDEX cht_bDebugFinalBoss; +extern INDEX cht_bDumpFinalBossData; +extern INDEX cht_bDebugFinalBossAnimations; + +#define LIGHT_ANIM_FIRE 3 +#define LIGHT_ANIM_NONE 5 + +// parameters defining boss +#define SIZE 50.0f +#define DEVIL_HOOF_RADIUS 0.25f*SIZE +#define DEVIL_HIT_HOOF_OFFSET FLOAT3D(-0.149021f, 0.084463f, -0.294425f)*SIZE +#define DEVIL_WALK_HOOF_RIGHT_OFFSET FLOAT3D(0.374725f, 0.0776713f, 0.0754253f)*SIZE +#define DEVIL_WALK_HOOF_LEFT_OFFSET FLOAT3D(-0.402306f, 0.0864595f, 0.292397f)*SIZE + +#define ATT_PROJECTILE_GUN (FLOAT3D(-0.703544f, 1.12582f, -0.329834f)*SIZE) +#define ATT_LASER (FLOAT3D(0.63626f, 1.13841f, -0.033062f)*SIZE) +#define ATT_ELECTRICITYGUN (FLOAT3D(-0.764868f, 1.27992f, -0.311084f)*SIZE) +#define ATT_ROCKETLAUNCHER (FLOAT3D(0.654788f, 1.30318f, -0.259358f)*SIZE) +#define MAGIC_PROJECTILE_EXIT (FLOAT3D(0.035866f, 1.400f, -0.792264f)*SIZE) + +#define ELECTROGUN_PIPE (FLOAT3D(-0.00423616f, -0.0216781f, -0.506613f)*SIZE) +#define LASER_PIPE (FLOAT3D(0.0172566f, -0.123152f, -0.232228f)*SIZE) + +#define PROJECTILEGUN_PIPE (FLOAT3D(0.0359023f, -0.000490744f, -0.394403f)*SIZE) +#define ROCKETLAUNCHER_PIPE (FLOAT3D(4.68194e-005f, 0.0483391f, -0.475134f)*SIZE) + +#define HEALTH_MULTIPLIER 1.0f +#define BOSS_HEALTH (40000.0f*HEALTH_MULTIPLIER) +#define HEALTH_IMPULSE (10000.0f*HEALTH_MULTIPLIER) +#define HEALTH_CLASS_1 (5000*HEALTH_MULTIPLIER) +#define HEALTH_CLASS_2 (7500*HEALTH_MULTIPLIER) +#define HEALTH_CLASS_3 (10000*HEALTH_MULTIPLIER) +#define HEALTH_CLASS_4 (15000*HEALTH_MULTIPLIER) +#define CLASS_2_CANNON_FACTOR 0.75f +#define CLASS_3_ROCKETLAUNCHER_FACTOR 0.75f +#define CLASS_4_ROCKETLAUNCHER_FACTOR 0.25f +#define TM_HEALTH_IMPULSE 4.0f + +// info structure +static EntityInfo eiDevil = { + EIBT_FLESH, 50000.0f, + 0.0f, 2.0f*SIZE, 0.0f, + 0.0f, 1.4f*SIZE, 0.0f, +}; + + +void CDevil::SetDefaultProperties(void) { + m_iAttID = 0; + m_fDeltaWeaponPitch = 0.0f; + m_fDeltaWeaponHdg = 0.0f; + m_fFireTime = 0.0f; + m_aoLightAnimation.SetData(NULL); + + m_penAction = NULL; + m_iFiredProjectiles = 0; + m_iToFireProjectiles = 0; + m_fPauseStretcher = 0; + m_tmLastPause = 0.0f; + m_dsDevilState = DS_NOT_EXISTING ; + m_tmLastAngry = -1.0f; + m_plTeleport = CPlacement3D(FLOAT3D (0 , 0 , 0) , ANGLE3D (0 , 0 , 0)); + m_tmTemp = 0; + m_dsLastDevilState = DS_REGENERATION_IMPULSE ; + m_dapAttackPower = DAP_PLAYER_HUNT ; + m_dapLastAttackPower = DAP_NOT_ATTACKING ; + m_bHasUpperWeapons = FALSE ; + m_vElectricitySource = FLOAT3D(0 , 0 , 0); + m_vElectricityTarget = FLOAT3D(0 , 0 , 0); + m_bRenderElectricity = FALSE ; + m_fAdjustWeaponTime = 0.0f; + m_bWasOnceInMainLoop = FALSE ; + m_tmHitBySpaceShipBeam = -1; + m_soLeft.SetOwner(this); +m_soLeft.Stop_internal(); + m_soRight.SetOwner(this); +m_soRight.Stop_internal(); + m_fLastWalkTime = -1.0f; + m_tmFireBreathStart = UpperLimit(0.0f); + m_tmFireBreathStop = 0.0f; + m_vFireBreathSource = FLOAT3D(0 , 0 , 0); + m_vFireBreathTarget = FLOAT3D(0 , 0 , 0); + m_tmRegenerationStart = UpperLimit(0.0f); + m_tmRegenerationStop = 0.0f; + m_tmNextFXTime = 0.0f; + m_iNextChannel = 0; + m_soWeapon0.SetOwner(this); +m_soWeapon0.Stop_internal(); + m_soWeapon1.SetOwner(this); +m_soWeapon1.Stop_internal(); + m_soWeapon2.SetOwner(this); +m_soWeapon2.Stop_internal(); + m_soWeapon3.SetOwner(this); +m_soWeapon3.Stop_internal(); + m_soWeapon4.SetOwner(this); +m_soWeapon4.Stop_internal(); + m_iAngryAnim = 0; + m_iAngrySound = 0; + m_tmDeathTime = -1.0f; + m_iLastCurrentAnim = -1; + m_iLastScheduledAnim = -1; + m_dsPreRegenerationDevilState = DS_ENEMY ; + m_soClimb.SetOwner(this); +m_soClimb.Stop_internal(); + m_soGrabLowerWeapons.SetOwner(this); +m_soGrabLowerWeapons.Stop_internal(); + m_soGrabUpperWeapons.SetOwner(this); +m_soGrabUpperWeapons.Stop_internal(); + m_soJumpIntoPyramid.SetOwner(this); +m_soJumpIntoPyramid.Stop_internal(); + m_bForMPIntro = FALSE ; + CEnemyBase::SetDefaultProperties(); +} + CTString CDevil::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString str ; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +str . PrintF (TRANS ("Ugh Zan killed %s") , strPlayerName ); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return str ; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::Precache(void) { +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CEnemyBase :: Precache (); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheModel (MODEL_DEVIL ); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheTexture (TEXTURE_DEVIL ); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheModel (MODEL_LASER ); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheTexture (TEXTURE_LASER ); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheModel (MODEL_ROCKETLAUNCHER ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheTexture (TEXTURE_ROCKETLAUNCHER ); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheModel (MODEL_ELECTRICITYGUN ); +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheTexture (TEXTURE_ELECTRICITYGUN ); +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheModel (MODEL_PROJECTILEGUN ); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheTexture (TEXTURE_PROJECTILEGUN ); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheClass (CLASS_PROJECTILE , PRT_LAVAMAN_BIG_BOMB ); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheClass (CLASS_PROJECTILE , PRT_DEVIL_GUIDED_PROJECTILE ); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheClass (CLASS_PROJECTILE , PRT_DEVIL_LASER ); +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheClass (CLASS_PROJECTILE , PRT_DEVIL_ROCKET ); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_ANGER01 ); +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_ANGER02 ); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_ATTACKCLOSE ); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_CELEBRATE01 ); +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_DEATH ); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_DRAW_LOWER_WEAPONS ); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_DRAW_UPPER_WEAPONS ); +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_GETUP ); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_IDLE ); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_PUNCH ); +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_SMASH ); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_WALK_LEFT ); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_WALK_RIGHT ); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_WOUND ); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_ATTACK_BREATH_START ); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_ATTACK_BREATH_FIRE ); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_ATTACK_BREATH_END ); +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_HEAL ); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_ROCKETLAUNCHER ); +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_LASER ); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_LAVABOMB ); +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_GHOSTBUSTER ); +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_ATTACK_BREATH_LOOP ); +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_CLIMB ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_DEATHPARTICLES ); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrecacheSound (SOUND_DISAPPEAR ); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BOOL CDevil::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(penTarget == NULL ) +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return FALSE ; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return (IsDerivedFromClass (penTarget , "Devil Marker")); +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::Read_t(CTStream * istr) { +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CEnemyBase :: Read_t (istr ); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetupLightSource (); +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CLightSource * CDevil::GetLightSource(void) { +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! IsPredictor ()){ +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return & m_lsLightSource ; +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}else { +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return NULL ; +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::SetupLightSource(void) { +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CLightSource lsNew ; +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +lsNew . ls_ulFlags = LSF_NONPERSISTENT | LSF_DYNAMIC ; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +lsNew . ls_rHotSpot = 2.0f; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +lsNew . ls_rFallOff = 8.0f; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +lsNew . ls_colColor = RGBToColor (128 , 128 , 128); +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +lsNew . ls_plftLensFlare = NULL ; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +lsNew . ls_ubPolygonalMask = 0; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +lsNew . ls_paoLightAnimation = & m_aoLightAnimation ; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_lsLightSource . ls_penEntity = this ; +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::PlayLightAnim(INDEX iAnim,ULONG ulFlags) { +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_aoLightAnimation . PlayAnim (iAnim , ulFlags ); +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void * CDevil::GetEntityInfo(void) { +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return & eiDevil ; +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BOOL CDevil::ForcesCannonballToExplode(void) +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE ; +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::SetSpeedsToDesiredPosition(const FLOAT3D & vPosDelta,FLOAT fPosDist,BOOL bGoingToPlayer) +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_penEnemy != NULL ) +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fEnemyDistance = CalcDist (m_penEnemy ); +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fRadius1 = 75.0f; +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fRadius2 = 200.0f; +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fSpeedRadius1 = 6.0f; +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fSpeedRadius2 = 14.0f; +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fDistanceRatio = CalculateRatio (fEnemyDistance , fRadius1 , fRadius2 , 1 , 0); +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(fEnemyDistance >= fRadius2 ) +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +fDistanceRatio = 1.0f; +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackRunSpeed = fSpeedRadius1 + fDistanceRatio * (fSpeedRadius2 - fSpeedRadius1 ); +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fCloseRunSpeed = m_fAttackRunSpeed ; +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bDebugFinalBoss ) +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Enm dist:%g, Speed=%g\n" , fEnemyDistance , m_fAttackRunSpeed ); +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CEnemyBase :: SetSpeedsToDesiredPosition (vPosDelta , fPosDist , bGoingToPlayer ); +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT CDevil::GetCrushHealth(void) +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return 1000.0f; +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::SelectRandomAnger(void) +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(IRnd () % 2){ +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iAngryAnim = DEVIL_ANIM_ANGER01 ; +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iAngrySound = SOUND_ANGER01 ; +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}else { +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iAngryAnim = DEVIL_ANIM_ANGER02 ; +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iAngrySound = SOUND_ANGER02 ; +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + FLOAT CDevil::GetLockRotationSpeed(void) +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return m_aAttackRotateSpeed * 4; +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::ShakeItBaby(FLOAT tmShaketime,FLOAT fPower) +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(pwsc != NULL ){ +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_tmShakeStarted = tmShaketime ; +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_vShakePos = GetPlacement () . pl_PositionVector ; +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fShakeFalloff = 400.0f; +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fShakeFade = 3.0f; +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fShakeIntensityZ = 0.0f; +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_tmShakeFrequencyZ = 5.0f; +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fShakeIntensityY = 0.1f * fPower ; +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_tmShakeFrequencyY = 5.0f; +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fShakeIntensityB = 2.5f * fPower ; +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_tmShakeFrequencyB = 7.2f; +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_bShakeFadeIn = FALSE ; +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::ShakeItFarBaby(FLOAT tmShaketime,FLOAT fPower) +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(pwsc != NULL ){ +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_tmShakeStarted = tmShaketime ; +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_vShakePos = GetPlacement () . pl_PositionVector ; +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fShakeFalloff = 2048.0f; +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fShakeFade = 2.0f; +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fShakeIntensityZ = 0.0f; +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_tmShakeFrequencyZ = 5.0f; +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fShakeIntensityY = 0.1f * fPower ; +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_tmShakeFrequencyY = 5.0f; +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fShakeIntensityB = 2.5f * fPower ; +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_tmShakeFrequencyB = 7.2f; +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_bShakeFadeIn = FALSE ; +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::InflictHoofDamage(FLOAT3D vOffset) +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vFootRel = vOffset ; +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vFootAbs = vFootRel * GetRotationMatrix () + GetPlacement () . pl_PositionVector ; +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +InflictRangeDamage (this , DMT_IMPACT , 1000.0f , vFootAbs , DEVIL_HOOF_RADIUS , DEVIL_HOOF_RADIUS ); +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::ApplyFootQuake(void) +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CModelObject & mo = * GetModelObject (); +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT tmAnim = - 1; +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT tmWalkLen = mo . GetAnimLength (DEVIL_ANIM_WALK ); +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT tmLeftFootOffset = 0.4f; +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT tmRightFootOffset = 2.05f; +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(mo . ao_iLastAnim == DEVIL_ANIM_WALK && mo . ao_tmAnimStart > tmNow ) +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +tmAnim = mo . ao_tmAnimStart - tmWalkLen ; +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(mo . ao_iCurrentAnim == DEVIL_ANIM_WALK && mo . ao_tmAnimStart <= tmNow ) +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +tmAnim = mo . ao_tmAnimStart ; +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(mo . ao_iLastAnim == DEVIL_ANIM_FROMWALKTOIDLE && mo . ao_tmAnimStart > tmNow ) +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +tmAnim = mo . ao_tmAnimStart - tmWalkLen ; +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +tmLeftFootOffset = 0.6f; +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +tmRightFootOffset = 1.7f; +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(mo . ao_iCurrentAnim == DEVIL_ANIM_FROMWALKTOIDLE && mo . ao_tmAnimStart <= tmNow ) +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +tmAnim = mo . ao_tmAnimStart ; +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +tmLeftFootOffset = 0.6f; +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +tmRightFootOffset = 1.7f; +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(tmAnim != - 1) +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT tmAnimLast = tmAnim + INDEX ((tmNow - tmAnim ) / tmWalkLen ) * tmWalkLen ; +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT tmLeftFootDown = tmAnimLast + tmLeftFootOffset ; +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT tmRightFootDown = tmAnimLast + tmRightFootOffset ; +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(pwsc != NULL ) +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(tmNow >= tmRightFootDown && pwsc -> m_tmShakeStarted < tmRightFootDown - 0.1f) +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +InflictHoofDamage (DEVIL_WALK_HOOF_LEFT_OFFSET ); +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ShakeItBaby (tmRightFootDown , 1.0f); +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soRight , SOUND_WALK_RIGHT , SOF_3D ); +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(tmNow >= tmLeftFootDown && pwsc -> m_tmShakeStarted < tmLeftFootDown - 0.1f) +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +InflictHoofDamage (DEVIL_WALK_HOOF_RIGHT_OFFSET ); +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ShakeItBaby (tmLeftFootDown , 1.0f); +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soLeft , SOUND_WALK_LEFT , SOF_3D ); +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::StopFireBreathParticles(void) +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmFireBreathStop = _pTimer -> CurrentTick (); +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::StopRegenerationParticles(void) +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmRegenerationStop = _pTimer -> CurrentTick (); +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::TurnOnPhysics(void) +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 534 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetCollisionFlags (ECF_MODEL ); +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::TurnOffPhysics(void) +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetPhysicsFlags (EPF_MODEL_WALKING & ~ EPF_TRANSLATEDBYGRAVITY ); +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetCollisionFlags (((ECBI_MODEL ) << ECB_TEST ) | ((ECBI_MODEL ) << ECB_PASS ) | ((ECBI_ITEM ) << ECB_IS )); +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::RenderParticles(void) +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_bRenderElectricity ) +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Particles_Ghostbuster (m_vElectricitySource , m_vElectricityTarget , 24 , 2.0f , 2.0f , 96.0f); +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(_pTimer -> CurrentTick () > m_tmFireBreathStart ) +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +INDEX ctRendered = Particles_FireBreath (this , m_vFireBreathSource , m_vFireBreathTarget , +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmFireBreathStart , m_tmFireBreathStop ); +#line 559 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(_pTimer -> CurrentTick () > m_tmFireBreathStop && ctRendered == 0) +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmFireBreathStart = UpperLimit (0.0f); +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(_pTimer -> CurrentTick () > m_tmRegenerationStart ) +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +INDEX ctRendered = Particles_Regeneration (this , m_tmRegenerationStart , m_tmRegenerationStop , 1.0f , FALSE ); +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(_pTimer -> CurrentTick () > m_tmRegenerationStop && ctRendered == 0) +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 573 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmRegenerationStart = UpperLimit (0.0f); +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_tmDeathTime != - 1.0f && _pTimer -> CurrentTick () > m_tmDeathTime && _pTimer -> CurrentTick () < m_tmDeathTime + 4.0f) +#line 579 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +INDEX ctRendered = Particles_Regeneration (this , m_tmDeathTime , m_tmDeathTime + 2.0f , 0.25f , TRUE ); +#line 581 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 583 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CEnemyBase :: RenderParticles (); +#line 584 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 586 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D CDevil::GetWeaponPositionRelative(void) +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CAttachmentModelObject & amo = * GetModelObject () -> GetAttachmentModel (m_iAttID ); +#line 589 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vAttachment = FLOAT3D (0 , 0 , 0); +#line 590 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +switch(m_iAttID ) +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DEVIL_ATTACHMENT_LASER : +#line 593 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vAttachment = ATT_LASER ; +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DEVIL_ATTACHMENT_PROJECTILEGUN : +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vAttachment = ATT_PROJECTILE_GUN ; +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DEVIL_ATTACHMENT_ELETRICITYGUN : +#line 599 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vAttachment = ATT_ELECTRICITYGUN ; +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DEVIL_ATTACHMENT_ROCKETLAUNCHER : +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vAttachment = ATT_ROCKETLAUNCHER ; +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +default : +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ASSERTALWAYS ("Invalid attachment ID"); +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 607 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return (vAttachment ); +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D CDevil::GetWeaponPositionAbsolute(void) +#line 611 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return GetPlacement () . pl_PositionVector + GetWeaponPositionRelative () * GetRotationMatrix (); +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D CDevil::GetFireingPositionRelative(void) +#line 616 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CAttachmentModelObject & amo = * GetModelObject () -> GetAttachmentModel (m_iAttID ); +#line 618 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vWeaponPipe = FLOAT3D (0 , 0 , 0); +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vAttachment = FLOAT3D (0 , 0 , 0); +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +switch(m_iAttID ) +#line 621 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 622 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DEVIL_ATTACHMENT_LASER : +#line 623 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vWeaponPipe = LASER_PIPE ; +#line 624 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vAttachment = ATT_LASER ; +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 626 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DEVIL_ATTACHMENT_PROJECTILEGUN : +#line 627 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vWeaponPipe = PROJECTILEGUN_PIPE ; +#line 628 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vAttachment = ATT_PROJECTILE_GUN ; +#line 629 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DEVIL_ATTACHMENT_ELETRICITYGUN : +#line 631 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vWeaponPipe = ELECTROGUN_PIPE ; +#line 632 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vAttachment = ATT_ELECTRICITYGUN ; +#line 633 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 634 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DEVIL_ATTACHMENT_ROCKETLAUNCHER : +#line 635 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vWeaponPipe = ROCKETLAUNCHER_PIPE ; +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vAttachment = ATT_ROCKETLAUNCHER ; +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 638 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +default : +#line 639 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ASSERTALWAYS ("Invalid attachment ID"); +#line 640 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 643 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOATmatrix3D mWpn ; +#line 644 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +MakeRotationMatrixFast (mWpn , amo . amo_plRelative . pl_OrientationAngle ); +#line 645 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return (vAttachment + vWeaponPipe * mWpn ); +#line 646 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 648 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D CDevil::GetFireingPositionAbsolute(void) +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 650 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return GetPlacement () . pl_PositionVector + GetFireingPositionRelative () * GetRotationMatrix (); +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::ApplyTickRegeneration(void) +#line 664 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 665 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bKillFinalBoss && GetSP () -> sp_bSinglePlayer ) +#line 666 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 667 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +cht_bKillFinalBoss = FALSE ; +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetHealth (- 1); +#line 669 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return ; +#line 670 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 672 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_dsDevilState == DS_REGENERATION_IMPULSE || +#line 673 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetHealth () <= 0 || GetHealth () >= HEALTH_CLASS_4 || +#line 674 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +_pTimer -> CurrentTick () < m_tmHitBySpaceShipBeam + 0.5f) +#line 675 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 676 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return ; +#line 677 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 679 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fDmgRocketsPerTick = 1800.0f / 10.0f * _pTimer -> TickQuantum ; +#line 680 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fDmgCannonsPerTick = 2959.0f / 10.0f * _pTimer -> TickQuantum ; +#line 681 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fRegeneration = 0.0f; +#line 683 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(GetHealth () < HEALTH_CLASS_1 ) +#line 684 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 685 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SendEvent (ERegenerationImpuls ()); +#line 686 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 687 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(GetHealth () < HEALTH_CLASS_2 ) +#line 688 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 689 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +fRegeneration = fDmgCannonsPerTick * CLASS_2_CANNON_FACTOR ; +#line 690 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 691 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(GetHealth () < HEALTH_CLASS_3 ) +#line 692 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 693 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +fRegeneration = fDmgRocketsPerTick * CLASS_3_ROCKETLAUNCHER_FACTOR ; +#line 694 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 695 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(GetHealth () < HEALTH_CLASS_4 ) +#line 696 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 697 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +fRegeneration = fDmgRocketsPerTick * CLASS_4_ROCKETLAUNCHER_FACTOR ; +#line 698 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 700 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetHealth (GetHealth () + fRegeneration ); +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 704 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::PostMoving(void) +#line 705 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 706 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ApplyFootQuake (); +#line 707 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CEnemyBase :: PostMoving (); +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +en_ulFlags &= ~ ENF_INRENDERING ; +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ApplyTickRegeneration (); +#line 711 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 716 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 718 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(dmtType == DMT_TELEPORT ) +#line 719 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return ; +#line 721 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 723 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! (m_dsDevilState == DS_ENEMY || m_dsDevilState == DS_PYRAMID_FIGHT ) || penInflictor == this ) +#line 724 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 725 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return ; +#line 726 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 728 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_dsDevilState != DS_PYRAMID_FIGHT ) +#line 729 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 730 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(GetHealth () < 1000.0f) +#line 731 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 732 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return ; +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 734 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +fDamageAmmount = ClampUp (fDamageAmmount , GetHealth () / 2.0f); +#line 735 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 737 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 738 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 740 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BOOL CDevil::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 741 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 742 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bDebugFinalBoss ) +#line 743 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 745 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_dsDevilState != m_dsLastDevilState ) +#line 746 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 747 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsLastDevilState = m_dsDevilState ; +#line 748 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString strDevilState = DevilState_enum . NameForValue (INDEX (m_dsDevilState )); +#line 749 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("New devil state: %s\n" , strDevilState ); +#line 750 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 753 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_dapAttackPower != m_dapLastAttackPower ) +#line 754 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 755 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dapLastAttackPower = m_dapAttackPower ; +#line 756 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString strAttackPower = DevilAttackPower_enum . NameForValue (INDEX (m_dapAttackPower )); +#line 757 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("New attack power: %s\n" , strAttackPower ); +#line 758 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 761 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if((vLastStartPosition != m_vStartPosition ) || +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +(vLastAttackRadius != m_fAttackRadius )) +#line 763 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 764 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vLastStartPosition = m_vStartPosition ; +#line 765 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vLastAttackRadius = m_fAttackRadius ; +#line 766 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Coordinate of attack (%g, %g, %g), Radius of attack: %g\n" , +#line 767 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_vStartPosition (1) , m_vStartPosition (2) , m_vStartPosition (3) , +#line 768 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackRadius ); +#line 769 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 770 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 772 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bDebugFinalBossAnimations ) +#line 773 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 774 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 775 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CModelObject & mo = * GetModelObject (); +#line 777 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +INDEX iCurrentAnim , iScheduledAnim ; +#line 778 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(mo . ao_tmAnimStart > tmNow ) +#line 779 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 780 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +iCurrentAnim = mo . ao_iLastAnim ; +#line 781 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +iScheduledAnim = mo . ao_iCurrentAnim ; +#line 782 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 783 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else +#line 784 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 785 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +iCurrentAnim = mo . ao_iCurrentAnim ; +#line 786 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +iScheduledAnim = - 1; +#line 787 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 789 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(iCurrentAnim != m_iLastCurrentAnim || iScheduledAnim != m_iLastScheduledAnim ) +#line 790 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 791 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CAnimData * pad = mo . GetData (); +#line 792 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CAnimInfo aiCurrent ; +#line 793 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +mo . GetAnimInfo (iCurrentAnim , aiCurrent ); +#line 794 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString strCurrentAnimName = aiCurrent . ai_AnimName ; +#line 796 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString strScheduledAnimName = "....."; +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(iScheduledAnim != - 1) +#line 798 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 799 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CAnimInfo aiScheduled ; +#line 800 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +mo . GetAnimInfo (iScheduledAnim , aiScheduled ); +#line 801 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +strScheduledAnimName = aiScheduled . ai_AnimName ; +#line 802 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 803 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Time: %-10g %20s, %s\n" , +#line 804 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +_pTimer -> GetLerpedCurrentTick () , strCurrentAnimName , strScheduledAnimName ); +#line 805 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 806 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iLastCurrentAnim = iCurrentAnim ; +#line 807 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iLastScheduledAnim = iScheduledAnim ; +#line 808 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 810 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bDumpFinalBossData ) +#line 811 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 812 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +cht_bDumpFinalBossData = FALSE ; +#line 814 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("\n\n\n\n\n\n\n"); +#line 815 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Devil class data ...................\n"); +#line 816 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("\n\n"); +#line 818 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString strAttackPower = DevilAttackPower_enum . NameForValue (INDEX (m_dapAttackPower )); +#line 819 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Attack power: %s\n" , strAttackPower ); +#line 820 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString strDevilState = DevilState_enum . NameForValue (INDEX (m_dsDevilState )); +#line 821 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Devil state: %s\n" , strDevilState ); +#line 823 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fFireTime = %g\n" , m_fFireTime ); +#line 824 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_iFiredProjectiles = %d\n" , m_iFiredProjectiles ); +#line 825 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_iToFireProjectiles = %d\n" , m_iToFireProjectiles ); +#line 826 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmLastPause = %g\n" , m_tmLastPause ); +#line 827 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fPauseStretcher = %g\n" , m_fPauseStretcher ); +#line 828 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmLastAngry = %g\n" , m_tmLastAngry ); +#line 829 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_bHasUpperWeapons = %d\n" , m_bHasUpperWeapons ); +#line 830 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fAdjustWeaponTime = %g\n" , m_fAdjustWeaponTime ); +#line 831 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_bWasOnceInMainLoop = %d\n" , m_bWasOnceInMainLoop ); +#line 832 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmHitBySpaceShipBeam = %g\n" , m_tmHitBySpaceShipBeam ); +#line 833 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fLastWalkTime = %g\n" , m_fLastWalkTime ); +#line 834 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmFireBreathStart = %g\n" , m_tmFireBreathStart ); +#line 835 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmFireBreathStop = %g\n" , m_tmFireBreathStop ); +#line 836 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmRegenerationStart = %g\n" , m_tmRegenerationStart ); +#line 837 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmRegenerationStop = %g\n" , m_tmRegenerationStop ); +#line 838 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmNextFXTime = %g\n" , m_tmNextFXTime ); +#line 839 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmDeathTime = %g\n" , m_tmDeathTime ); +#line 840 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Health = %g\n" , GetHealth ()); +#line 842 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("\n\n\n\n\n\n\n"); +#line 843 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Enemy base data ...................\n"); +#line 844 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("\n\n"); +#line 846 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_ttTarget (type): %d\n" , INDEX (m_ttTarget )); +#line 848 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_penWatcher %x\n" , m_penWatcher ); +#line 849 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString strEnemyName = "Null ptr, no name"; +#line 850 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_penEnemy != NULL ) +#line 851 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 852 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +strEnemyName = m_penEnemy -> GetName (); +#line 853 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 854 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_penEnemy %x, enemy name: %s\n" , m_penEnemy , strEnemyName ); +#line 856 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_vStartPosition (%g, %g, %g)\n" , m_vStartPosition (1) , m_vStartPosition (2) , m_vStartPosition (3)); +#line 857 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_vStartDirection (%g, %g, %g)\n" , m_vStartDirection (1) , m_vStartDirection (2) , m_vStartDirection (3)); +#line 858 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_bOnStartPosition = %d\n" , m_bOnStartPosition ); +#line 859 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fFallHeight = %g\n" , m_fFallHeight ); +#line 860 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fStepHeight = %g\n" , m_fStepHeight ); +#line 861 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fSenseRange = %g\n" , m_fSenseRange ); +#line 862 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fViewAngle = %g\n" , m_fViewAngle ); +#line 864 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fWalkSpeed = %g\n" , m_fWalkSpeed ); +#line 865 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_aWalkRotateSpeed = %g\n" , m_aWalkRotateSpeed ); +#line 866 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fAttackRunSpeed = %g\n" , m_fAttackRunSpeed ); +#line 867 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_aAttackRotateSpeed = %g\n" , m_aAttackRotateSpeed ); +#line 868 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fCloseRunSpeed = %g\n" , m_fCloseRunSpeed ); +#line 869 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_aCloseRotateSpeed = %g\n" , m_aCloseRotateSpeed ); +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fAttackDistance = %g\n" , m_fAttackDistance ); +#line 871 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fCloseDistance = %g\n" , m_fCloseDistance ); +#line 872 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fAttackFireTime = %g\n" , m_fAttackFireTime ); +#line 873 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fCloseFireTime = %g\n" , m_fCloseFireTime ); +#line 874 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fStopDistance = %g\n" , m_fStopDistance ); +#line 875 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fIgnoreRange = %g\n" , m_fIgnoreRange ); +#line 876 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fLockOnEnemyTime = %g\n" , m_fLockOnEnemyTime ); +#line 878 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fMoveTime = %g\n" , m_fMoveTime ); +#line 879 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_vDesiredPosition (%g, %g, %g)\n" , m_vDesiredPosition (1) , m_vDesiredPosition (2) , m_vDesiredPosition (3)); +#line 881 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString strDestinationType = DestinationType_enum . NameForValue (INDEX (m_dtDestination )); +#line 882 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_dtDestination: %s\n" , strDestinationType ); +#line 883 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_penPathMarker %x\n" , m_penPathMarker ); +#line 885 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_vPlayerSpotted (%g, %g, %g)\n" , m_vPlayerSpotted (1) , m_vPlayerSpotted (2) , m_vPlayerSpotted (3)); +#line 886 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fMoveFrequency = %g\n" , m_fMoveFrequency ); +#line 887 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fMoveSpeed = %g\n" , m_fMoveSpeed ); +#line 888 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_aRotateSpeed = %g\n" , m_aRotateSpeed ); +#line 889 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fLockStartTime = %g\n" , m_fLockStartTime ); +#line 890 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fRangeLast = %g\n" , m_fRangeLast ); +#line 891 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fShootTime = %g\n" , m_fShootTime ); +#line 892 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fAttackRadius = %g\n" , m_fAttackRadius ); +#line 893 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmGiveUp = %g\n" , m_tmGiveUp ); +#line 894 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fActivityRange = %g\n" , m_fActivityRange ); +#line 896 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString strMarkerName = "Null ptr, no name"; +#line 897 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_penMarker != NULL ) +#line 898 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 899 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +strMarkerName = m_penMarker -> GetName (); +#line 900 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 901 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_penMarker %x, marker name: %s\n" , m_penMarker , strMarkerName ); +#line 903 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString strMainMusicHolderName = "Null ptr, no name"; +#line 904 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_penMainMusicHolder != NULL ) +#line 905 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 906 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +strMainMusicHolderName = m_penMainMusicHolder -> GetName (); +#line 907 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 908 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_penMainMusicHolder %x, MainMusicHolder name: %s\n" , m_penMainMusicHolder , strMainMusicHolderName ); +#line 909 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmLastFussTime = %g\n" , m_tmLastFussTime ); +#line 910 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_iScore = %d\n" , m_iScore ); +#line 911 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fMaxHealth = %g\n" , m_fMaxHealth ); +#line 912 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_bBoss = %d\n" , m_bBoss ); +#line 913 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fSpiritStartTime = %g\n" , m_fSpiritStartTime ); +#line 914 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_tmSpraySpawned = %g\n" , m_tmSpraySpawned ); +#line 915 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fSprayDamage = %g\n" , m_fSprayDamage ); +#line 916 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("m_fMaxDamageAmmount = %g\n" , m_fMaxDamageAmmount ); +#line 917 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 919 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vLightDirection = FLOAT3D (0.0f , 270.0f , 0.0f); +#line 920 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +colAmbient = RGBToColor (32 , 32 , 32); +#line 921 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +colLight = RGBToColor (255 , 235 , 145); +#line 923 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return CMovableModelEntity :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 925 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +INDEX CDevil::AnimForDamage(FLOAT fDamage) { +#line 929 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_WOUNDLOOP , 0); +#line 930 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return DEVIL_ANIM_WOUNDLOOP ; +#line 931 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 934 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +INDEX CDevil::AnimForDeath(void) { +#line 935 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_DEATH , 0); +#line 936 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return DEVIL_ANIM_DEATH ; +#line 937 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 939 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::DeathNotify(void) { +#line 940 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopFireBreathParticles (); +#line 941 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopRegenerationParticles (); +#line 942 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 945 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::StandingAnim(void) { +#line 946 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_IDLE , AOF_SMOOTHCHANGE | AOF_LOOPING | AOF_NORESTART ); +#line 947 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 949 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::WalkingAnim(void) { +#line 950 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! m_bForMPIntro ) +#line 951 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 952 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CModelObject & mo = * GetModelObject (); +#line 953 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +INDEX iAnim = mo . GetAnim (); +#line 954 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(iAnim == DEVIL_ANIM_WALK ) +#line 955 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 957 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}else if(iAnim == DEVIL_ANIM_FROMIDLETOWALK ){ +#line 958 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_WALK , AOF_LOOPING | AOF_SMOOTHCHANGE ); +#line 959 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}else { +#line 960 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_FROMIDLETOWALK , AOF_SMOOTHCHANGE ); +#line 961 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 962 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 963 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 964 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::RunningAnim(void) { +#line 965 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WalkingAnim (); +#line 966 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::RotatingAnim(void) { +#line 968 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WalkingAnim (); +#line 969 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 972 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::IdleSound(void) { +#line 973 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 974 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 975 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::SightSound(void) { +#line 977 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 978 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::WoundSound(void) { +#line 979 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 980 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 981 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::DeathSound(void) { +#line 982 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D | SOF_VOLUMETRIC ); +#line 983 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 987 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::StartFireLaser(void) { +#line 989 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayLightAnim (LIGHT_ANIM_FIRE , AOF_LOOPING | SOF_3D ); +#line 990 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 993 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::FireOneLaser(FLOAT fRatio,FLOAT fDeltaPitch) +#line 994 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 995 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayWeaponSound (SOUND_LASER ); +#line 996 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vWpnPipeRel = GetFireingPositionRelative (); +#line 997 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vWpnPipeAbs = GetFireingPositionAbsolute (); +#line 999 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vTarget = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 1000 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vSpeedDst = ((CMovableEntity &) * m_penEnemy ) . en_vCurrentTranslationAbsolute * fRatio ; +#line 1001 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fSpeedSrc = DEVIL_LASER_SPEED ; +#line 1002 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_vDesiredPosition = CalculatePredictedPosition (vWpnPipeAbs , vTarget , fSpeedSrc , +#line 1003 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vSpeedDst , GetPlacement () . pl_PositionVector (2)); +#line 1005 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ShootPredictedProjectile (PRT_DEVIL_LASER , m_vDesiredPosition , vWpnPipeRel , ANGLE3D (0 , fDeltaPitch , 0)); +#line 1007 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayLightAnim (LIGHT_ANIM_FIRE , AOF_LOOPING ); +#line 1008 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 1011 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::StopFireLaser(void) { +#line 1012 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soSound . Stop (); +#line 1013 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayLightAnim (LIGHT_ANIM_NONE , 0); +#line 1014 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 1017 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::StartFireRocket(void) { +#line 1019 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayLightAnim (LIGHT_ANIM_FIRE , AOF_LOOPING ); +#line 1020 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 1022 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::PlayWeaponSound(ULONG idSound) +#line 1023 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1024 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CSoundObject & so = (& m_soWeapon0 ) [ m_iNextChannel ]; +#line 1025 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iNextChannel = (m_iNextChannel + 1) % 5; +#line 1026 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (so , idSound , SOF_3D ); +#line 1027 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 1030 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::FireOneRocket(FLOAT fRatio) +#line 1031 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1032 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayWeaponSound (SOUND_ROCKETLAUNCHER ); +#line 1033 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vWpnPipeRel = GetFireingPositionRelative (); +#line 1034 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vWpnPipeAbs = GetFireingPositionAbsolute (); +#line 1036 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vTarget = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 1037 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vSpeedDst = ((CMovableEntity &) * m_penEnemy ) . en_vCurrentTranslationAbsolute * fRatio ; +#line 1038 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fSpeedSrc = DEVIL_ROCKET_SPEED ; +#line 1039 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_vDesiredPosition = CalculatePredictedPosition (vWpnPipeAbs , vTarget , fSpeedSrc , +#line 1040 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +vSpeedDst , GetPlacement () . pl_PositionVector (2)); +#line 1042 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ShootPredictedProjectile (PRT_DEVIL_ROCKET , m_vDesiredPosition , vWpnPipeRel , ANGLE3D (0 , 0 , 0)); +#line 1044 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayLightAnim (LIGHT_ANIM_FIRE , AOF_LOOPING ); +#line 1047 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayLightAnim (LIGHT_ANIM_FIRE , AOF_LOOPING ); +#line 1048 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 1051 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::StopFireRocket(void) { +#line 1052 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soSound . Stop (); +#line 1053 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayLightAnim (LIGHT_ANIM_NONE , 0); +#line 1054 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 1056 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::AddLowerWeapons(void) +#line 1057 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1059 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AddAttachmentToModel (this , * GetModelObject () , DEVIL_ATTACHMENT_LASER , MODEL_LASER , TEXTURE_LASER , 0 , 0 , 0); +#line 1061 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AddAttachmentToModel (this , * GetModelObject () , DEVIL_ATTACHMENT_PROJECTILEGUN , MODEL_PROJECTILEGUN , TEXTURE_PROJECTILEGUN , 0 , 0 , 0); +#line 1062 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> StretchModel (FLOAT3D (SIZE , SIZE , SIZE )); +#line 1063 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 1065 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::AddUpperWeapons(void) +#line 1066 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1068 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AddAttachmentToModel (this , * GetModelObject () , DEVIL_ATTACHMENT_ROCKETLAUNCHER , MODEL_ROCKETLAUNCHER , TEXTURE_ROCKETLAUNCHER , 0 , 0 , 0); +#line 1070 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AddAttachmentToModel (this , * GetModelObject () , DEVIL_ATTACHMENT_ELETRICITYGUN , MODEL_ELECTRICITYGUN , TEXTURE_ELECTRICITYGUN , 0 , 0 , 0); +#line 1071 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> StretchModel (FLOAT3D (SIZE , SIZE , SIZE )); +#line 1072 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 1074 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::RemoveWeapons(void) +#line 1075 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1077 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +RemoveAttachmentFromModel (* GetModelObject () , DEVIL_ATTACHMENT_LASER ); +#line 1078 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +RemoveAttachmentFromModel (* GetModelObject () , DEVIL_ATTACHMENT_PROJECTILEGUN ); +#line 1079 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +RemoveAttachmentFromModel (* GetModelObject () , DEVIL_ATTACHMENT_ELETRICITYGUN ); +#line 1080 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +RemoveAttachmentFromModel (* GetModelObject () , DEVIL_ATTACHMENT_ROCKETLAUNCHER ); +#line 1081 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 1083 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +class CDevilMarker * CDevil::GetAction(void) +#line 1084 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1085 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CDevilMarker * penAction = (CDevilMarker *) (CEntity *) m_penAction ; +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ASSERT (penAction != NULL ); +#line 1087 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return penAction ; +#line 1088 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 1093 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void CDevil::F_FirePredictedProjectile(void) +#line 1094 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1095 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayWeaponSound (SOUND_LAVABOMB ); +#line 1096 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vFireingRel = GetFireingPositionRelative (); +#line 1097 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vFireingAbs = GetFireingPositionAbsolute (); +#line 1099 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vTarget = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 1100 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vSpeedDest = ((CMovableEntity &) * m_penEnemy ) . en_vCurrentTranslationAbsolute ; +#line 1101 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fLaunchSpeed ; +#line 1102 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fRelativeHdg ; +#line 1105 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CAttachmentModelObject & amo = * GetModelObject () -> GetAttachmentModel (m_iAttID ); +#line 1106 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fPitch = amo . amo_plRelative . pl_OrientationAngle (2); +#line 1109 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 1110 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CalculateAngularLaunchParams (vFireingAbs , 0 , vTarget , vSpeedDest , fPitch , fLaunchSpeed , fRelativeHdg ); +#line 1113 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vShootTarget ; +#line 1114 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetEntityInfoPosition (m_penEnemy , peiTarget -> vTargetCenter , vShootTarget ); +#line 1116 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPlacement3D pl ; +#line 1117 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PrepareFreeFlyingProjectile (pl , vShootTarget , vFireingRel , ANGLE3D (fRelativeHdg , fPitch , 0)); +#line 1118 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 1119 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ELaunchProjectile eLaunch ; +#line 1120 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +eLaunch . penLauncher = this ; +#line 1121 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +eLaunch . prtType = PRT_LAVAMAN_BIG_BOMB ; +#line 1122 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +eLaunch . fSpeed = fLaunchSpeed ; +#line 1123 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +penProjectile -> Initialize (eLaunch ); +#line 1124 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} + +#line 1127 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BOOL CDevil::HandleEvent(const CEntityEvent & ee) +#line 1128 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1129 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(ee . ee_slEvent == EVENTCODE_EDevilCommand ) +#line 1130 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1131 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +EDevilCommand eDevilCommand = ((EDevilCommand &) ee ); +#line 1132 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(eDevilCommand . dctType == DC_FORCE_ATTACK_RADIUS ) +#line 1133 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1134 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackRadius = eDevilCommand . fAttackRadius ; +#line 1135 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_vStartPosition = eDevilCommand . vCenterOfAttack ; +#line 1136 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1137 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(eDevilCommand . dctType == DC_DECREASE_ATTACK_RADIUS ) +#line 1138 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1139 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_fAttackRadius > 21.0f) +#line 1140 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1141 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackRadius -= 20.0f; +#line 1142 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1143 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1144 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1146 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return CEnemyBase :: HandleEvent (ee ); +#line 1147 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +BOOL CDevil:: +#line 1154 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WalkTo(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_WalkTo + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::WalkTo expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1156 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitCurrentAnimEnd, TRUE; +Jump(STATE_CURRENT, 0x014c0004, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0004_WalkTo_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitCurrentAnimEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0005, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0005_WalkTo_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0005 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1157 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WalkingAnim (); +#line 1158 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_vDesiredPosition = GetAction () -> GetPlacement () . pl_PositionVector ; +#line 1160 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fMoveFrequency = 0.25f; +#line 1161 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fMoveSpeed = 15.0f; +#line 1162 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_aRotateSpeed = 60.0f; +#line 1163 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fMoveTime = _pTimer -> CurrentTick () + CalcDistanceInPlaneToDestination () / m_fMoveSpeed + 5.0f; +#line 1165 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c0008, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0008_WalkTo_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0008 +if(!(CalcDistanceInPlaneToDestination () > m_fMoveSpeed * m_fMoveFrequency * 4.0f && +#line 1166 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fMoveTime > _pTimer -> CurrentTick ())){ Jump(STATE_CURRENT,0x014c0009, FALSE, EInternal());return TRUE;} +#line 1168 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(m_fMoveFrequency ); +Jump(STATE_CURRENT, 0x014c0006, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0006_WalkTo_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0006 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 1171 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ULONG ulFlags = SetDesiredMovement (); +#line 1172 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +MovementAnimation (ulFlags ); +#line 1173 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 1174 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x014c0007, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 1176 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}return TRUE;}BOOL CDevil::H0x014c0007_WalkTo_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0007 +Jump(STATE_CURRENT,0x014c0008, FALSE, EInternal());return TRUE; +#line 1177 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c0009_WalkTo_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0009 + +#line 1179 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopMoving (); +#line 1181 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1181 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1187 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +DestroyCity(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_DestroyCity + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::DestroyCity expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1189 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soSound . Set3DParameters (1000.0f , 500.0f , 3.0f , 1.0f); +#line 1191 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c0030, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0030_DestroyCity_38(const CEntityEvent &__eeInput) +#line 1192 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0030 +if(!(TRUE )){ Jump(STATE_CURRENT,0x014c0031, FALSE, EInternal());return TRUE;} +#line 1193 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(!(GetAction () -> m_datType == DAT_RISE )){ Jump(STATE_CURRENT,0x014c002f, FALSE, EInternal());return TRUE;} +#line 1195 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_Rise, TRUE; +Jump(STATE_CURRENT, 0x014c000b, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c000b_DestroyCity_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c000b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_Rise, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c000c, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c000c_DestroyCity_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c000c +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x014c002e, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c002f_DestroyCity_37(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c002f +if(!(GetAction () -> m_datType == DAT_ROAR )){ Jump(STATE_CURRENT,0x014c002d, FALSE, EInternal());return TRUE;} +#line 1199 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SelectRandomAnger (); +#line 1200 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_Angry, TRUE; +Jump(STATE_CURRENT, 0x014c000d, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c000d_DestroyCity_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c000d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_Angry, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c000e, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c000e_DestroyCity_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c000e +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x014c002c, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c002d_DestroyCity_35(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c002d +if(!(GetAction () -> m_datType == DAT_SMASH )){ Jump(STATE_CURRENT,0x014c002b, FALSE, EInternal());return TRUE;} +#line 1204 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_Smash, TRUE; +Jump(STATE_CURRENT, 0x014c000f, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c000f_DestroyCity_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c000f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_Smash, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0010, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0010_DestroyCity_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0010 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x014c002a, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c002b_DestroyCity_33(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c002b +if(!(GetAction () -> m_datType == DAT_PUNCH )){ Jump(STATE_CURRENT,0x014c0029, FALSE, EInternal());return TRUE;} +#line 1208 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_Punch, TRUE; +Jump(STATE_CURRENT, 0x014c0011, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0011_DestroyCity_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0011 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_Punch, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0012, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0012_DestroyCity_08(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0012 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x014c0028, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0029_DestroyCity_31(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0029 +if(!(GetAction () -> m_datType == DAT_HIT_GROUND )){ Jump(STATE_CURRENT,0x014c0027, FALSE, EInternal());return TRUE;} +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_HitGround, TRUE; +Jump(STATE_CURRENT, 0x014c0013, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0013_DestroyCity_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0013 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_HitGround, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0014, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0014_DestroyCity_10(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0014 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x014c0026, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0027_DestroyCity_29(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0027 +if(!(GetAction () -> m_datType == DAT_JUMP )){ Jump(STATE_CURRENT,0x014c0025, FALSE, EInternal());return TRUE;}Jump(STATE_CURRENT,0x014c0024, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0025_DestroyCity_27(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0025 +if(!(GetAction () -> m_datType == DAT_WAIT )){ Jump(STATE_CURRENT,0x014c0023, FALSE, EInternal());return TRUE;} +#line 1220 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitCurrentAnimEnd, TRUE; +Jump(STATE_CURRENT, 0x014c0015, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0015_DestroyCity_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitCurrentAnimEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0016, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0016_DestroyCity_12(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0016 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1221 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_IDLE , 0); +#line 1222 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_IDLE ) * GetAction () -> m_iWaitIdles ); +Jump(STATE_CURRENT, 0x014c0017, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0017_DestroyCity_13(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0017 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0018, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0018_DestroyCity_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0018 +;Jump(STATE_CURRENT,0x014c0022, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0023_DestroyCity_25(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0023 +if(!(GetAction () -> m_datType == DAT_WALK )){ Jump(STATE_CURRENT,0x014c0021, FALSE, EInternal());return TRUE;} +#line 1226 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WalkTo, TRUE; +Jump(STATE_CURRENT, 0x014c0019, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0019_DestroyCity_15(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0019 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WalkTo, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c001a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c001a_DestroyCity_16(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c001a +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x014c0020, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0021_DestroyCity_23(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0021 +if(!(GetAction () -> m_datType == DAT_STOP_DESTROYING )){ Jump(STATE_CURRENT,0x014c001f, FALSE, EInternal());return TRUE;} +#line 1230 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1230 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE;Jump(STATE_CURRENT,0x014c001e, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c001f_DestroyCity_21(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c001f +if(!(TRUE )){ Jump(STATE_CURRENT,0x014c001d, FALSE, EInternal());return TRUE;} +#line 1234 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_IDLE , 0); +#line 1235 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_IDLE )); +Jump(STATE_CURRENT, 0x014c001b, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c001b_DestroyCity_17(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c001b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c001c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c001c_DestroyCity_18(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c001c +;Jump(STATE_CURRENT,0x014c001d, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c001d_DestroyCity_19(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c001d +Jump(STATE_CURRENT,0x014c001e, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c001e_DestroyCity_20(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c001e +Jump(STATE_CURRENT,0x014c0020, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c0020_DestroyCity_22(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0020 +Jump(STATE_CURRENT,0x014c0022, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c0022_DestroyCity_24(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0022 +Jump(STATE_CURRENT,0x014c0024, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c0024_DestroyCity_26(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0024 +Jump(STATE_CURRENT,0x014c0026, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c0026_DestroyCity_28(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0026 +Jump(STATE_CURRENT,0x014c0028, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c0028_DestroyCity_30(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0028 +Jump(STATE_CURRENT,0x014c002a, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c002a_DestroyCity_32(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c002a +Jump(STATE_CURRENT,0x014c002c, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c002c_DestroyCity_34(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c002c +Jump(STATE_CURRENT,0x014c002e, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c002e_DestroyCity_36(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c002e + +#line 1238 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_penAction = GetAction () -> m_penTarget ; +#line 1239 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(GetAction () -> m_penTrigger != NULL ) +#line 1240 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1241 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetAction () -> m_penTrigger -> SendEvent (ETrigger ()); +#line 1242 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}Jump(STATE_CURRENT,0x014c0030, FALSE, EInternal());return TRUE; +#line 1243 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c0031_DestroyCity_39(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0031 + ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WaitCurrentAnimEnd(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_WaitCurrentAnimEnd + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::WaitCurrentAnimEnd expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1248 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x014c0033, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0033_WaitCurrentAnimEnd_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0033 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0034, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0034_WaitCurrentAnimEnd_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0034 +; +#line 1249 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CModelObject & mo = * GetModelObject (); +#line 1250 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT tmWait = mo . GetAnimLength (mo . ao_iCurrentAnim ) - mo . GetPassedTime (); +#line 1251 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(!(tmWait > _pTimer -> TickQuantum )){ Jump(STATE_CURRENT,0x014c0038, FALSE, EInternal());return TRUE;} +#line 1253 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fTimeToWait = tmWait - _pTimer -> TickQuantum * 2; +#line 1254 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(!(fTimeToWait >= _pTimer -> TickQuantum )){ Jump(STATE_CURRENT,0x014c0037, FALSE, EInternal());return TRUE;} +#line 1256 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(fTimeToWait ); +Jump(STATE_CURRENT, 0x014c0035, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0035_WaitCurrentAnimEnd_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0035 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0036, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0036_WaitCurrentAnimEnd_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0036 +;Jump(STATE_CURRENT,0x014c0037, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0037_WaitCurrentAnimEnd_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0037 +Jump(STATE_CURRENT,0x014c0038, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0038_WaitCurrentAnimEnd_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0038 + +#line 1259 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1259 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1262 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WaitWalkToEnd(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_WaitWalkToEnd + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::WaitWalkToEnd expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1264 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(!(GetModelObject () -> GetAnim () == DEVIL_ANIM_WALK )){ Jump(STATE_CURRENT,0x014c003e, FALSE, EInternal());return TRUE;} +#line 1266 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitCurrentAnimEnd, TRUE; +Jump(STATE_CURRENT, 0x014c003a, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c003a_WaitWalkToEnd_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c003a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitCurrentAnimEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c003b, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c003b_WaitWalkToEnd_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c003b +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1267 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_FROMWALKTOIDLE , AOF_SMOOTHCHANGE ); +#line 1268 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_FROMWALKTOIDLE ) - 0.1f); +Jump(STATE_CURRENT, 0x014c003c, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c003c_WaitWalkToEnd_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c003c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c003d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c003d_WaitWalkToEnd_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c003d +;Jump(STATE_CURRENT,0x014c003e, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c003e_WaitWalkToEnd_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c003e + +#line 1270 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitCurrentAnimEnd, TRUE; +Jump(STATE_CURRENT, 0x014c003f, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c003f_WaitWalkToEnd_06(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c003f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitCurrentAnimEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0040, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0040_WaitWalkToEnd_07(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0040 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1271 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1271 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1274 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WaitWalkOrIdleToEnd(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_WaitWalkOrIdleToEnd + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::WaitWalkOrIdleToEnd expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1276 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(!(GetModelObject () -> GetAnim () == DEVIL_ANIM_WALK )){ Jump(STATE_CURRENT,0x014c0050, FALSE, EInternal());return TRUE;} +#line 1278 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitCurrentAnimEnd, TRUE; +Jump(STATE_CURRENT, 0x014c0042, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0042_WaitWalkOrIdleToEnd_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0042 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitCurrentAnimEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0043, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0043_WaitWalkOrIdleToEnd_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0043 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1279 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_FROMWALKTOIDLE , AOF_SMOOTHCHANGE ); +#line 1280 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_FROMWALKTOIDLE ) - 0.1f); +Jump(STATE_CURRENT, 0x014c0044, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0044_WaitWalkOrIdleToEnd_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0044 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0045, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0045_WaitWalkOrIdleToEnd_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0045 +;Jump(STATE_CURRENT,0x014c004f, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0050_WaitWalkOrIdleToEnd_15(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0050 +if(!(GetModelObject () -> GetAnim () == DEVIL_ANIM_FROMIDLETOWALK )){ Jump(STATE_CURRENT,0x014c004e, FALSE, EInternal());return TRUE;} +#line 1284 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitCurrentAnimEnd, TRUE; +Jump(STATE_CURRENT, 0x014c0046, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0046_WaitWalkOrIdleToEnd_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0046 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitCurrentAnimEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0047, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0047_WaitWalkOrIdleToEnd_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0047 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1285 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_FROMWALKTOIDLE , AOF_SMOOTHCHANGE ); +#line 1286 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_FROMWALKTOIDLE ) - 0.1f); +Jump(STATE_CURRENT, 0x014c0048, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0048_WaitWalkOrIdleToEnd_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0048 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0049, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0049_WaitWalkOrIdleToEnd_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0049 +;Jump(STATE_CURRENT,0x014c004d, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c004e_WaitWalkOrIdleToEnd_13(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c004e +if(!(GetModelObject () -> GetAnim () == DEVIL_ANIM_IDLE )){ Jump(STATE_CURRENT,0x014c004c, FALSE, EInternal());return TRUE;} +#line 1290 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitCurrentAnimEnd, TRUE; +Jump(STATE_CURRENT, 0x014c004a, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c004a_WaitWalkOrIdleToEnd_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c004a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitCurrentAnimEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c004b, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c004b_WaitWalkOrIdleToEnd_10(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c004b +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x014c004c, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c004c_WaitWalkOrIdleToEnd_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c004c +Jump(STATE_CURRENT,0x014c004d, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c004d_WaitWalkOrIdleToEnd_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c004d +Jump(STATE_CURRENT,0x014c004f, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c004f_WaitWalkOrIdleToEnd_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c004f + +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1295 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Rise(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_Rise + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::Rise expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1297 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitCurrentAnimEnd, TRUE; +Jump(STATE_CURRENT, 0x014c0052, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0052_Rise_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0052 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitCurrentAnimEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0053, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0053_Rise_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0053 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1298 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_GETUP , SOF_3D ); +#line 1299 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_GETUP , 0); +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Celebrate(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_Celebrate + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::Celebrate expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1305 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitWalkToEnd, TRUE; +Jump(STATE_CURRENT, 0x014c0055, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0055_Celebrate_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0055 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitWalkToEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0056, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0056_Celebrate_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0056 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1307 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_CELEBRATE01 , SOF_3D ); +#line 1308 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_CELEBRATE01 , AOF_SMOOTHCHANGE ); +#line 1309 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_CELEBRATE01 ) - 0.1f); +Jump(STATE_CURRENT, 0x014c0057, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0057_Celebrate_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0057 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0058, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0058_Celebrate_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0058 +; +#line 1310 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1310 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Angry(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_Angry + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::Angry expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1315 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitWalkToEnd, TRUE; +Jump(STATE_CURRENT, 0x014c005a, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c005a_Angry_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c005a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitWalkToEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c005b, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c005b_Angry_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c005b +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1317 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (m_iAngryAnim , AOF_SMOOTHCHANGE ); +#line 1318 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c005c, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c005c_Angry_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c005c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c005d, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c005d_Angry_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c005d +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1319 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , m_iAngrySound , SOF_3D ); +#line 1320 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (m_iAngryAnim ) - 0.1f); +Jump(STATE_CURRENT, 0x014c005e, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c005e_Angry_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c005e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c005f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c005f_Angry_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c005f +; +#line 1321 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1321 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SubBeamDamage1(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_SubBeamDamage1 + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::SubBeamDamage1 expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1327 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopMoving (); +#line 1328 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 1329 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_WOUNDSTART , AOF_SMOOTHCHANGE ); +#line 1330 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_WOUNDSTART ) - 0.1f); +Jump(STATE_CURRENT, 0x014c0061, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0061_SubBeamDamage1_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0061 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0062, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0062_SubBeamDamage1_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0062 +; +#line 1331 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_WOUNDLOOP , AOF_LOOPING | AOF_SMOOTHCHANGE ); +#line 1332 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CDevil_SubBeamDamage2, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1334 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SubBeamDamage2(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_SubBeamDamage2 + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::SubBeamDamage2 expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1336 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c0066, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0066_SubBeamDamage2_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0066 +if(!(TRUE )){ Jump(STATE_CURRENT,0x014c0067, FALSE, EInternal());return TRUE;} +#line 1337 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x014c0064, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0064_SubBeamDamage2_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0064 +switch(__eeInput.ee_slEvent) +#line 1338 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EHitBySpaceShipBeam):{const EHitBySpaceShipBeam&e= (EHitBySpaceShipBeam&)__eeInput; + +#line 1341 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmHitBySpaceShipBeam = _pTimer -> CurrentTick (); +#line 1342 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +UnsetTimer();Jump(STATE_CURRENT,0x014c0065, FALSE, EInternal());return TRUE; +#line 1343 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +Jump(STATE_CURRENT, STATE_CDevil_SubBeamDamage3, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 1345 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}return TRUE;}BOOL CDevil::H0x014c0065_SubBeamDamage2_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0065 +Jump(STATE_CURRENT,0x014c0066, FALSE, EInternal());return TRUE; +#line 1346 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c0067_SubBeamDamage2_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0067 + ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1348 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SubBeamDamage3(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_SubBeamDamage3 + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::SubBeamDamage3 expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_WOUNDEND , AOF_SMOOTHCHANGE ); +#line 1351 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_WOUNDEND ) - 0.1f); +Jump(STATE_CURRENT, 0x014c0069, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0069_SubBeamDamage3_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0069 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c006a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c006a_SubBeamDamage3_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c006a +; +#line 1352 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_IDLE , AOF_LOOPING | AOF_SMOOTHCHANGE ); +#line 1353 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1353 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1355 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BeamDamage(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_BeamDamage + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::BeamDamage expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1357 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x014c006c, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c006c_BeamDamage_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c006c +switch(__eeInput.ee_slEvent) +#line 1358 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +Call(STATE_CURRENT, STATE_CDevil_SubBeamDamage1, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EHitBySpaceShipBeam):{const EHitBySpaceShipBeam&e= (EHitBySpaceShipBeam&)__eeInput; + +#line 1361 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmHitBySpaceShipBeam = _pTimer -> CurrentTick (); +#line 1362 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 1363 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x014c006d, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 1365 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}return TRUE;}BOOL CDevil::H0x014c006d_BeamDamage_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c006d + +#line 1366 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1366 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Smash(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_Smash + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::Smash expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1374 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_FROMWALKTOIDLE , AOF_SMOOTHCHANGE ); +#line 1375 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c006f, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c006f_Smash_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c006f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0070, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0070_Smash_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0070 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1377 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_SMASH , AOF_SMOOTHCHANGE ); +#line 1378 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c0071, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0071_Smash_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0071 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0072, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0072_Smash_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0072 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1380 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x014c0073, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0073_Smash_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0073 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0074, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0074_Smash_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0074 +; +#line 1381 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_SMASH , SOF_3D ); +#line 1382 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.7f); +Jump(STATE_CURRENT, 0x014c0075, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0075_Smash_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0075 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0076, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0076_Smash_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0076 +; +#line 1383 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(GetAction () -> m_penToDestroy1 != NULL ) +#line 1384 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1385 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +EBrushDestroyedByDevil ebdbd ; +#line 1386 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ebdbd . vDamageDir = FLOAT3D (- 0.125f , 0.0f , - 0.5f); +#line 1387 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetAction () -> m_penToDestroy1 -> SendEvent (ebdbd ); +#line 1388 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1389 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(2.8f - 1.0f); +Jump(STATE_CURRENT, 0x014c0077, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0077_Smash_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0077 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0078, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0078_Smash_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0078 +; +#line 1390 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(GetAction () -> m_penToDestroy2 != NULL ) +#line 1391 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1392 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +EBrushDestroyedByDevil ebdbd ; +#line 1393 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ebdbd . vDamageDir = FLOAT3D (- 0.125f , 0.0f , - 0.5f); +#line 1394 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetAction () -> m_penToDestroy2 -> SendEvent (ebdbd ); +#line 1395 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1396 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1396 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Punch(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_Punch + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::Punch expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1403 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_FROMWALKTOIDLE , AOF_SMOOTHCHANGE ); +#line 1404 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c007a, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c007a_Punch_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c007a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c007b, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c007b_Punch_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c007b +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1406 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_PUNCH , AOF_SMOOTHCHANGE ); +#line 1407 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c007c, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c007c_Punch_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c007c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c007d, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c007d_Punch_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c007d +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1409 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x014c007e, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c007e_Punch_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c007e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c007f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c007f_Punch_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c007f +; +#line 1410 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_PUNCH , SOF_3D ); +#line 1411 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.8f); +Jump(STATE_CURRENT, 0x014c0080, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0080_Punch_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0080 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0081, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0081_Punch_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0081 +; +#line 1412 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(GetAction () -> m_penToDestroy1 != NULL ) +#line 1413 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1414 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +EBrushDestroyedByDevil ebdbd ; +#line 1415 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ebdbd . vDamageDir = FLOAT3D (- 0.125f , 0.0f , - 0.5f); +#line 1416 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetAction () -> m_penToDestroy1 -> SendEvent (ebdbd ); +#line 1417 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1418 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(2.8f - 1.1f); +Jump(STATE_CURRENT, 0x014c0082, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0082_Punch_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0082 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0083, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0083_Punch_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0083 +; +#line 1419 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(GetAction () -> m_penToDestroy2 != NULL ) +#line 1420 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1421 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +EBrushDestroyedByDevil ebdbd ; +#line 1422 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ebdbd . vDamageDir = FLOAT3D (0.125f , 0.0f , - 0.5f); +#line 1423 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetAction () -> m_penToDestroy2 -> SendEvent (ebdbd ); +#line 1424 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1426 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1426 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1429 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +HitGround(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_HitGround + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::HitGround expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1431 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitWalkToEnd, TRUE; +Jump(STATE_CURRENT, 0x014c0085, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0085_HitGround_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0085 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitWalkToEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0086, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0086_HitGround_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0086 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1433 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_ATTACKCLOSE , SOF_3D ); +#line 1434 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_ATTACKCLOSE , AOF_SMOOTHCHANGE ); +#line 1435 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(1.44f); +Jump(STATE_CURRENT, 0x014c0087, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0087_HitGround_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0087 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0088, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0088_HitGround_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0088 +; +#line 1436 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ShakeItBaby (_pTimer -> CurrentTick () , 5.0f); +#line 1438 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPlacement3D plObelisk = GetPlacement (); +#line 1440 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CEntity * penEffector = CreateEntity (plObelisk , CLASS_EFFECTOR ); +#line 1442 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ESpawnEffector eSpawnEffector ; +#line 1443 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +eSpawnEffector . tmLifeTime = 6.0f; +#line 1444 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +eSpawnEffector . fSize = 1.0f; +#line 1445 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +eSpawnEffector . eetType = ET_HIT_GROUND ; +#line 1446 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +eSpawnEffector . vDamageDir = FLOAT3D (0.0f , 2.0f , 0.0f); +#line 1448 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +penEffector -> Initialize (eSpawnEffector ); +#line 1450 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1450 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1453 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GrabLowerWeapons(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_GrabLowerWeapons + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::GrabLowerWeapons expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1455 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitWalkToEnd, TRUE; +Jump(STATE_CURRENT, 0x014c008a, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c008a_GrabLowerWeapons_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c008a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitWalkToEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c008b, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c008b_GrabLowerWeapons_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c008b +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1456 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_GRABWEAPONS01 , AOF_SMOOTHCHANGE ); +#line 1457 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c008c, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c008c_GrabLowerWeapons_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c008c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c008d, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c008d_GrabLowerWeapons_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c008d +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1458 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_DRAW_LOWER_WEAPONS , SOF_3D ); +#line 1459 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.84f); +Jump(STATE_CURRENT, 0x014c008e, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c008e_GrabLowerWeapons_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c008e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c008f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c008f_GrabLowerWeapons_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c008f +; +#line 1460 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AddLowerWeapons (); +#line 1461 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WalkingAnim (); +#line 1462 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c0090, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0090_GrabLowerWeapons_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0090 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0091, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0091_GrabLowerWeapons_08(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0091 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1463 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1463 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1466 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GrabUpperWeapons(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_GrabUpperWeapons + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::GrabUpperWeapons expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1468 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitWalkToEnd, TRUE; +Jump(STATE_CURRENT, 0x014c0093, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0093_GrabUpperWeapons_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0093 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitWalkToEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0094, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0094_GrabUpperWeapons_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0094 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1469 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_GRABWEAPONS02 , AOF_SMOOTHCHANGE ); +#line 1470 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c0095, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0095_GrabUpperWeapons_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0095 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0096, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0096_GrabUpperWeapons_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0096 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1471 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_DRAW_UPPER_WEAPONS , SOF_3D ); +#line 1472 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.84f); +Jump(STATE_CURRENT, 0x014c0097, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0097_GrabUpperWeapons_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0097 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0098, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0098_GrabUpperWeapons_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0098 +; +#line 1473 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AddUpperWeapons (); +#line 1474 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bHasUpperWeapons = TRUE ; +#line 1475 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WalkingAnim (); +#line 1476 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c0099, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0099_GrabUpperWeapons_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0099 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c009a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c009a_GrabUpperWeapons_08(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c009a +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1477 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1477 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1480 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GrabBothWeapons(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_GrabBothWeapons + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::GrabBothWeapons expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1482 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitWalkToEnd, TRUE; +Jump(STATE_CURRENT, 0x014c009c, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c009c_GrabBothWeapons_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c009c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitWalkToEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c009d, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c009d_GrabBothWeapons_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c009d +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1483 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_GRABWEAPONS01 , AOF_SMOOTHCHANGE ); +#line 1484 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c009e, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c009e_GrabBothWeapons_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c009e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c009f, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c009f_GrabBothWeapons_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c009f +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1485 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soGrabLowerWeapons , SOUND_DRAW_LOWER_WEAPONS , SOF_3D ); +#line 1486 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.84f); +Jump(STATE_CURRENT, 0x014c00a0, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00a0_GrabBothWeapons_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00a0 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00a1, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00a1_GrabBothWeapons_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00a1 +; +#line 1487 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AddLowerWeapons (); +#line 1488 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_GRABWEAPONS02 , AOF_SMOOTHCHANGE ); +#line 1489 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c00a2, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00a2_GrabBothWeapons_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00a2 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00a3, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00a3_GrabBothWeapons_08(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00a3 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1490 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soGrabUpperWeapons , SOUND_DRAW_UPPER_WEAPONS , SOF_3D ); +#line 1491 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.84f); +Jump(STATE_CURRENT, 0x014c00a4, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00a4_GrabBothWeapons_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00a4 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00a5, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00a5_GrabBothWeapons_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00a5 +; +#line 1492 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AddUpperWeapons (); +#line 1493 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bHasUpperWeapons = TRUE ; +#line 1494 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WalkingAnim (); +#line 1495 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c00a6, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00a6_GrabBothWeapons_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00a6 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00a7, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00a7_GrabBothWeapons_12(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00a7 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1496 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1496 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1499 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PreMainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_PreMainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::PreMainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1501 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soSound . Set3DParameters (1000.0f , 500.0f , 2.0f , 1.0f); +#line 1502 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soGrabLowerWeapons . Set3DParameters (1000.0f , 500.0f , 2.0f , 1.0f); +#line 1503 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soGrabUpperWeapons . Set3DParameters (1000.0f , 500.0f , 2.0f , 1.0f); +#line 1504 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soJumpIntoPyramid . Set3DParameters (1000.0f , 500.0f , 2.0f , 1.0f); +#line 1505 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soLeft . Set3DParameters (1000.0f , 500.0f , 2.0f , 1.0f); +#line 1506 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soRight . Set3DParameters (1000.0f , 500.0f , 2.0f , 1.0f); +#line 1507 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soWeapon0 . Set3DParameters (1000.0f , 500.0f , 1.0f , 1.0f); +#line 1508 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soWeapon1 . Set3DParameters (1000.0f , 500.0f , 1.0f , 1.0f); +#line 1509 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soWeapon2 . Set3DParameters (1000.0f , 500.0f , 1.0f , 1.0f); +#line 1510 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soWeapon3 . Set3DParameters (1000.0f , 500.0f , 1.0f , 1.0f); +#line 1511 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soWeapon4 . Set3DParameters (1000.0f , 500.0f , 1.0f , 1.0f); +#line 1513 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +TurnOnPhysics (); +#line 1515 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_penEnemy == NULL ) +#line 1516 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1518 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CEntity * penEnemy = FixupCausedToPlayer (this , m_penEnemy , FALSE ); +#line 1519 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(penEnemy != m_penEnemy ){ +#line 1520 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTargetSoft (penEnemy ); +#line 1521 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1522 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1524 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1524 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1531 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BeWounded(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_BeWounded + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDamage, "CDevil::BeWounded expects 'EDamage' as input!"); const EDamage &eDamage = (const EDamage &)__eeInput; +#line 1533 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopMoving (); +#line 1535 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (AnimForDamage (eDamage . fAmount ))); +Jump(STATE_CURRENT, 0x014c00aa, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00aa_BeWounded_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00aa +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00ab, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00ab_BeWounded_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ab +; +#line 1536 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1536 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1542 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1543 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitCurrentAnimEnd, TRUE; +Jump(STATE_CURRENT, 0x014c00ad, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00ad_Hit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ad +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitCurrentAnimEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00ae, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00ae_Hit_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ae +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1544 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_ATTACKCLOSE , AOF_SMOOTHCHANGE ); +#line 1545 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c00af, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00af_Hit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00af +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00b0, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00b0_Hit_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00b0 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1546 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_ATTACKCLOSE , SOF_3D ); +#line 1547 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(1.4f); +Jump(STATE_CURRENT, 0x014c00b1, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00b1_Hit_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00b1 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00b2, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00b2_Hit_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00b2 +; +#line 1548 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ShakeItBaby (_pTimer -> CurrentTick () , 5.0f); +#line 1549 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(CalcDist (m_penEnemy ) < m_fCloseDistance ) +#line 1550 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1551 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +InflictDirectDamage (m_penEnemy , this , DMT_IMPACT , 1000.0f , +#line 1552 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_penEnemy -> GetPlacement () . pl_PositionVector , FLOAT3D (0 , 1 , 0)); +#line 1553 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1554 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +InflictHoofDamage (DEVIL_HIT_HOOF_OFFSET ); +#line 1556 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_ATTACKCLOSE - 1.4f) - _pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x014c00b3, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00b3_Hit_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00b3 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00b4, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00b4_Hit_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00b4 +; +#line 1557 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1557 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1564 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +InitializeAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_InitializeAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::InitializeAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1565 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_InitializeAttack, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1568 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1570 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iToFireProjectiles = 0; +#line 1571 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackFireTime = 10.0f; +#line 1572 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fPauseStretcher = 1.0f; +#line 1574 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_dapAttackPower == DAP_MEDIUM_POWER_ATTACK && +#line 1575 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +(_pTimer -> CurrentTick () - m_fLastWalkTime ) > 6.0f) +#line 1576 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1577 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackFireTime = 6.0f; +#line 1578 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fLastWalkTime = _pTimer -> CurrentTick () + 6.0f; +#line 1579 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EVoid()); +#line 1579 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 1580 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1582 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +switch(m_dapAttackPower ) +#line 1583 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1584 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DAP_PLAYER_HUNT : +#line 1585 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(_pTimer -> CurrentTick () - m_tmLastAngry > 10.0f) +#line 1586 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1587 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackFireTime = 7.5 + FRnd () * 5; +#line 1588 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmLastAngry = _pTimer -> CurrentTick (); +#line 1589 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SelectRandomAnger (); +#line 1590 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CDevil_Angry, TRUE, EVoid());return TRUE; +#line 1591 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1592 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EVoid()); +#line 1592 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 1593 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 1594 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DAP_LOW_POWER_ATTACK : +#line 1595 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iToFireProjectiles = 2; +#line 1596 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackFireTime = 5.0f; +#line 1597 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fPauseStretcher = 1.0f; +#line 1598 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 1599 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DAP_MEDIUM_POWER_ATTACK : +#line 1600 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iToFireProjectiles = 3; +#line 1601 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackFireTime = 0.1f; +#line 1602 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fPauseStretcher = 0.5f; +#line 1603 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 1604 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case DAP_FULL_POWER_ATTACK : +#line 1605 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iToFireProjectiles = 4; +#line 1606 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackFireTime = 0.1f; +#line 1607 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fPauseStretcher = 0.1f; +#line 1608 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 1609 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1611 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +INDEX iRnd = IRnd () % 5; +#line 1612 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! m_bHasUpperWeapons ) +#line 1613 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1614 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +iRnd = IRnd () % 3; +#line 1615 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1618 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +switch(iRnd ) +#line 1619 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1620 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case 0: +#line 1621 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CDevil_FirePredictedProjectile, TRUE, EVoid());return TRUE; +#line 1622 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 1623 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case 1: +#line 1624 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CDevil_FireLaser, TRUE, EVoid());return TRUE; +#line 1625 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 1626 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case 2: +#line 1627 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CDevil_FireGuidedProjectile, TRUE, EVoid());return TRUE; +#line 1628 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 1629 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case 3: +#line 1630 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CDevil_FireRocketLauncher, TRUE, EVoid());return TRUE; +#line 1631 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 1632 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +case 4: +#line 1633 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CDevil_FireElectricityGun, TRUE, EVoid());return TRUE; +#line 1634 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +break ; +#line 1635 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1639 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +DevilLockOnEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_DevilLockOnEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::DevilLockOnEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1642 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopMoving (); +#line 1644 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ChargeAnim (); +#line 1646 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fLockStartTime = _pTimer -> CurrentTick (); +#line 1647 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c00ba, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c00ba_DevilLockOnEnemy_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ba +if(!(m_fLockStartTime + GetProp (m_fLockOnEnemyTime ) > _pTimer -> CurrentTick ())){ Jump(STATE_CURRENT,0x014c00bb, FALSE, EInternal());return TRUE;} +#line 1649 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fMoveFrequency = 0.05f; +#line 1650 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(m_fMoveFrequency ); +Jump(STATE_CURRENT, 0x014c00b8, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00b8_DevilLockOnEnemy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00b8 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x014c00b9, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 1653 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_vDesiredPosition = PlayerDestinationPos (); +#line 1655 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! IsInPlaneFrustum (m_penEnemy , CosFast (30.0f))){ +#line 1656 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fLockStartTime = - 10000.0f; +#line 1657 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +UnsetTimer();Jump(STATE_CURRENT,0x014c00b9, FALSE, EInternal());return TRUE; +#line 1658 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1671 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 1672 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 1673 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}return TRUE;}BOOL CDevil::H0x014c00b9_DevilLockOnEnemy_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00b9 +Jump(STATE_CURRENT,0x014c00ba, FALSE, EInternal());return TRUE; +#line 1674 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c00bb_DevilLockOnEnemy_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00bb + +#line 1676 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopRotating (); +#line 1679 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1679 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1682 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AdjustWeaponForFire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_AdjustWeaponForFire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::AdjustWeaponForFire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1684 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vRelWeapon = GetWeaponPositionRelative (); +#line 1685 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vAbsWeapon = GetPlacement () . pl_PositionVector + vRelWeapon * GetRotationMatrix (); +#line 1687 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fFireTime = _pTimer -> CurrentTick () + m_fAdjustWeaponTime ; +#line 1688 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vEnemy = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 1689 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vDir = (vEnemy - vAbsWeapon ) . Normalize (); +#line 1690 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ANGLE3D aAngles ; +#line 1691 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +DirectionVectorToAngles (vDir , aAngles ); +#line 1692 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPlacement3D plRelPl = CPlacement3D (FLOAT3D (0 , 0 , 0) , aAngles ); +#line 1693 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +plRelPl . AbsoluteToRelative (GetPlacement ()); +#line 1694 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fWantedHdg = plRelPl . pl_OrientationAngle (1); +#line 1695 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fWantedPitch = plRelPl . pl_OrientationAngle (2); +#line 1698 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_iAttID == DEVIL_ATTACHMENT_PROJECTILEGUN ) +#line 1699 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1700 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vShooting = GetPlacement () . pl_PositionVector ; +#line 1701 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vTarget = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 1702 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fDistanceFactor = 1.0f - ClampUp ((vShooting - vTarget ) . Length () / 250.0f , 1.0f); +#line 1703 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +fWantedPitch = 20 - fDistanceFactor * 50.0f; +#line 1704 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1706 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CAttachmentModelObject & amo = * GetModelObject () -> GetAttachmentModel (m_iAttID ); +#line 1707 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fDeltaWeaponHdg = (fWantedHdg - amo . amo_plRelative . pl_OrientationAngle (1)) / (m_fAdjustWeaponTime / _pTimer -> TickQuantum ); +#line 1708 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fDeltaWeaponPitch = (fWantedPitch - amo . amo_plRelative . pl_OrientationAngle (2)) / (m_fAdjustWeaponTime / _pTimer -> TickQuantum ); +#line 1709 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c00bf, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c00bf_AdjustWeaponForFire_03(const CEntityEvent &__eeInput) +#line 1710 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00bf +if(!(m_fFireTime > _pTimer -> CurrentTick ())){ Jump(STATE_CURRENT,0x014c00c0, FALSE, EInternal());return TRUE;} +#line 1711 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x014c00bd, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00bd_AdjustWeaponForFire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00bd +switch(__eeInput.ee_slEvent) +#line 1712 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{case(EVENTCODE_EBegin): +#line 1714 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{const EBegin&e= (EBegin&)__eeInput; + +#line 1715 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CAttachmentModelObject & amo = * GetModelObject () -> GetAttachmentModel (m_iAttID ); +#line 1716 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +amo . amo_plRelative . pl_OrientationAngle (1) += m_fDeltaWeaponHdg ; +#line 1717 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +amo . amo_plRelative . pl_OrientationAngle (2) += m_fDeltaWeaponPitch ; +#line 1718 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 1719 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x014c00be, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 1721 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}return TRUE;}BOOL CDevil::H0x014c00be_AdjustWeaponForFire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00be +Jump(STATE_CURRENT,0x014c00bf, FALSE, EInternal());return TRUE; +#line 1722 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c00c0_AdjustWeaponForFire_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00c0 + +#line 1723 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1723 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1726 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StraightenUpWeapon(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_StraightenUpWeapon + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::StraightenUpWeapon expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1728 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fAdjustWeaponTime = 0.25f; +#line 1729 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fFireTime = _pTimer -> CurrentTick () + fAdjustWeaponTime ; +#line 1731 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CAttachmentModelObject & amo = * GetModelObject () -> GetAttachmentModel (m_iAttID ); +#line 1732 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fDeltaWeaponHdg = amo . amo_plRelative . pl_OrientationAngle (1) / (fAdjustWeaponTime / _pTimer -> TickQuantum ); +#line 1733 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fDeltaWeaponPitch = amo . amo_plRelative . pl_OrientationAngle (2) / (fAdjustWeaponTime / _pTimer -> TickQuantum ); +#line 1734 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c00c4, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c00c4_StraightenUpWeapon_03(const CEntityEvent &__eeInput) +#line 1735 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00c4 +if(!(m_fFireTime > _pTimer -> CurrentTick ())){ Jump(STATE_CURRENT,0x014c00c5, FALSE, EInternal());return TRUE;} +#line 1736 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x014c00c2, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00c2_StraightenUpWeapon_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00c2 +switch(__eeInput.ee_slEvent) +#line 1737 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{case(EVENTCODE_EBegin): +#line 1739 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{const EBegin&e= (EBegin&)__eeInput; + +#line 1740 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CAttachmentModelObject & amo = * GetModelObject () -> GetAttachmentModel (m_iAttID ); +#line 1741 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +amo . amo_plRelative . pl_OrientationAngle (1) -= m_fDeltaWeaponHdg ; +#line 1742 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +amo . amo_plRelative . pl_OrientationAngle (2) -= m_fDeltaWeaponPitch ; +#line 1743 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 1744 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x014c00c3, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 1746 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}return TRUE;}BOOL CDevil::H0x014c00c3_StraightenUpWeapon_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00c3 +Jump(STATE_CURRENT,0x014c00c4, FALSE, EInternal());return TRUE; +#line 1747 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c00c5_StraightenUpWeapon_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00c5 + +#line 1748 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1748 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1751 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireLaser(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_FireLaser + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::FireLaser expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1753 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitWalkOrIdleToEnd, TRUE; +Jump(STATE_CURRENT, 0x014c00c7, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00c7_FireLaser_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00c7 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitWalkOrIdleToEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00c8, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00c8_FireLaser_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00c8 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1756 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_FROMIDLETOATTACK01 , AOF_SMOOTHCHANGE ); +#line 1757 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_FROMIDLETOATTACK01 ) - 0.1f); +Jump(STATE_CURRENT, 0x014c00c9, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00c9_FireLaser_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00c9 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00ca, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00ca_FireLaser_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ca +; +#line 1758 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_ATTACK01 , AOF_SMOOTHCHANGE | AOF_LOOPING ); +#line 1760 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iAttID = DEVIL_ATTACHMENT_LASER ; +#line 1761 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAdjustWeaponTime = 0.25f; +#line 1762 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_AdjustWeaponForFire, TRUE; +Jump(STATE_CURRENT, 0x014c00cb, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00cb_FireLaser_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00cb +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_AdjustWeaponForFire, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00cc, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00cc_FireLaser_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00cc +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1765 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartFireLaser (); +#line 1766 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles = 0; +#line 1767 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c00d1, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c00d1_FireLaser_11(const CEntityEvent &__eeInput) +#line 1768 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00d1 +if(!(m_iFiredProjectiles < m_iToFireProjectiles * 10)){ Jump(STATE_CURRENT,0x014c00d2, FALSE, EInternal());return TRUE;} +#line 1769 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_DevilLockOnEnemy, TRUE; +Jump(STATE_CURRENT, 0x014c00cd, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00cd_FireLaser_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00cd +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_DevilLockOnEnemy, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00ce, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00ce_FireLaser_08(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ce +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1770 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmLastPause = 0.1f * m_fPauseStretcher ; +#line 1771 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(m_tmLastPause ); +Jump(STATE_CURRENT, 0x014c00cf, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00cf_FireLaser_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00cf +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00d0, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00d0_FireLaser_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00d0 +; +#line 1773 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fPredictionRatio = (FRnd () - 0.5f) * 0.25f; +#line 1774 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_iFiredProjectiles & 1) +#line 1775 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1776 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +fPredictionRatio = 1.0f; +#line 1777 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1778 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fDeltaPitch = (FRnd () - 0.5f) * 1.0f; +#line 1779 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireOneLaser (fPredictionRatio , fDeltaPitch ); +#line 1780 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles ++; +#line 1781 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! IsInFrustum (m_penEnemy , CosFast (30.0f))){ +#line 1782 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles = 10000; +#line 1783 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}Jump(STATE_CURRENT,0x014c00d1, FALSE, EInternal());return TRUE; +#line 1784 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c00d2_FireLaser_12(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00d2 + +#line 1785 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_StraightenUpWeapon, TRUE; +Jump(STATE_CURRENT, 0x014c00d3, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00d3_FireLaser_13(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00d3 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_StraightenUpWeapon, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00d4, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00d4_FireLaser_14(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00d4 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1786 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopFireLaser (); +#line 1792 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +MaybeSwitchToAnotherPlayer (); +#line 1795 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1795 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1798 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireRocketLauncher(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_FireRocketLauncher + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::FireRocketLauncher expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1800 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitWalkOrIdleToEnd, TRUE; +Jump(STATE_CURRENT, 0x014c00d6, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00d6_FireRocketLauncher_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00d6 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitWalkOrIdleToEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00d7, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00d7_FireRocketLauncher_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00d7 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1803 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_FROMIDLETOATTACK02 , AOF_SMOOTHCHANGE ); +#line 1804 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_FROMIDLETOATTACK02 ) - 0.1f); +Jump(STATE_CURRENT, 0x014c00d8, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00d8_FireRocketLauncher_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00d8 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00d9, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00d9_FireRocketLauncher_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00d9 +; +#line 1805 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_ATTACK02 , AOF_SMOOTHCHANGE | AOF_LOOPING ); +#line 1807 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iAttID = DEVIL_ATTACHMENT_ROCKETLAUNCHER ; +#line 1808 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAdjustWeaponTime = 0.5f; +#line 1809 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_AdjustWeaponForFire, TRUE; +Jump(STATE_CURRENT, 0x014c00da, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00da_FireRocketLauncher_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00da +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_AdjustWeaponForFire, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00db, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00db_FireRocketLauncher_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00db +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1812 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartFireRocket (); +#line 1813 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles = 0; +#line 1814 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c00e0, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c00e0_FireRocketLauncher_11(const CEntityEvent &__eeInput) +#line 1815 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00e0 +if(!(m_iFiredProjectiles < m_iToFireProjectiles )){ Jump(STATE_CURRENT,0x014c00e1, FALSE, EInternal());return TRUE;} +#line 1816 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_DevilLockOnEnemy, TRUE; +Jump(STATE_CURRENT, 0x014c00dc, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00dc_FireRocketLauncher_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00dc +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_DevilLockOnEnemy, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00dd, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00dd_FireRocketLauncher_08(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00dd +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1817 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmLastPause = 0.5f + 0.3f * m_fPauseStretcher ; +#line 1818 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(m_tmLastPause ); +Jump(STATE_CURRENT, 0x014c00de, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00de_FireRocketLauncher_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00de +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00df, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00df_FireRocketLauncher_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00df +; +#line 1819 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fPredictionRatio = 0.25f + m_iFiredProjectiles * (0.75f / m_iToFireProjectiles ); +#line 1820 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +fPredictionRatio = 1.0f; +#line 1821 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles ++; +#line 1823 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireOneRocket (fPredictionRatio ); +#line 1824 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! IsInFrustum (m_penEnemy , CosFast (30.0f))){ +#line 1825 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles = 10000; +#line 1826 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}Jump(STATE_CURRENT,0x014c00e0, FALSE, EInternal());return TRUE; +#line 1827 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c00e1_FireRocketLauncher_12(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00e1 + +#line 1828 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_StraightenUpWeapon, TRUE; +Jump(STATE_CURRENT, 0x014c00e2, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00e2_FireRocketLauncher_13(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00e2 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_StraightenUpWeapon, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00e3, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00e3_FireRocketLauncher_14(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00e3 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1829 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopFireRocket (); +#line 1835 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +MaybeSwitchToAnotherPlayer (); +#line 1838 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1838 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1841 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FirePredictedProjectile(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_FirePredictedProjectile + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::FirePredictedProjectile expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1843 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitWalkOrIdleToEnd, TRUE; +Jump(STATE_CURRENT, 0x014c00e5, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00e5_FirePredictedProjectile_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00e5 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitWalkOrIdleToEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00e6, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00e6_FirePredictedProjectile_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00e6 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1846 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_FROMIDLETOATTACK01 , AOF_SMOOTHCHANGE ); +#line 1847 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_FROMIDLETOATTACK01 ) - 0.1f); +Jump(STATE_CURRENT, 0x014c00e7, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00e7_FirePredictedProjectile_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00e7 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00e8, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00e8_FirePredictedProjectile_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00e8 +; +#line 1848 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_ATTACK01 , AOF_SMOOTHCHANGE | AOF_LOOPING ); +#line 1850 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iAttID = DEVIL_ATTACHMENT_PROJECTILEGUN ; +#line 1851 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAdjustWeaponTime = 0.5f; +#line 1852 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_AdjustWeaponForFire, TRUE; +Jump(STATE_CURRENT, 0x014c00e9, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00e9_FirePredictedProjectile_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00e9 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_AdjustWeaponForFire, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00ea, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00ea_FirePredictedProjectile_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ea +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1855 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles = 0; +#line 1856 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c00ef, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c00ef_FirePredictedProjectile_11(const CEntityEvent &__eeInput) +#line 1857 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ef +if(!(m_iFiredProjectiles < m_iToFireProjectiles )){ Jump(STATE_CURRENT,0x014c00f0, FALSE, EInternal());return TRUE;} +#line 1858 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAdjustWeaponTime = 0.45f; +#line 1859 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_AdjustWeaponForFire, TRUE; +Jump(STATE_CURRENT, 0x014c00eb, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00eb_FirePredictedProjectile_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00eb +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_AdjustWeaponForFire, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00ec, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00ec_FirePredictedProjectile_08(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ec +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1860 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +F_FirePredictedProjectile (); +#line 1861 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.8f - m_fAdjustWeaponTime ); +Jump(STATE_CURRENT, 0x014c00ed, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00ed_FirePredictedProjectile_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ed +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00ee, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00ee_FirePredictedProjectile_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ee +; +#line 1862 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles ++; +#line 1863 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! IsInFrustum (m_penEnemy , CosFast (30.0f))){ +#line 1864 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles = 10000; +#line 1865 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}Jump(STATE_CURRENT,0x014c00ef, FALSE, EInternal());return TRUE; +#line 1866 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c00f0_FirePredictedProjectile_12(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00f0 + +#line 1867 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_StraightenUpWeapon, TRUE; +Jump(STATE_CURRENT, 0x014c00f1, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00f1_FirePredictedProjectile_13(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00f1 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_StraightenUpWeapon, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00f2, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00f2_FirePredictedProjectile_14(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00f2 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1870 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_FROMATTACK01TOIDLE , AOF_SMOOTHCHANGE ); +#line 1876 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +MaybeSwitchToAnotherPlayer (); +#line 1879 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1879 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1882 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireElectricityGun(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_FireElectricityGun + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::FireElectricityGun expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1884 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitWalkOrIdleToEnd, TRUE; +Jump(STATE_CURRENT, 0x014c00f4, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00f4_FireElectricityGun_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00f4 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitWalkOrIdleToEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00f5, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00f5_FireElectricityGun_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00f5 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1887 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_FROMIDLETOATTACK02 , AOF_SMOOTHCHANGE ); +#line 1888 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_FROMIDLETOATTACK02 ) - 0.1f); +Jump(STATE_CURRENT, 0x014c00f6, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00f6_FireElectricityGun_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00f6 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00f7, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00f7_FireElectricityGun_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00f7 +; +#line 1889 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_ATTACK02 , AOF_SMOOTHCHANGE | AOF_LOOPING ); +#line 1891 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iAttID = DEVIL_ATTACHMENT_ELETRICITYGUN ; +#line 1892 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAdjustWeaponTime = 0.5f; +#line 1896 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles = 0; +#line 1897 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c0102, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0102_FireElectricityGun_15(const CEntityEvent &__eeInput) +#line 1898 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0102 +if(!(m_iFiredProjectiles < m_iToFireProjectiles )){ Jump(STATE_CURRENT,0x014c0103, FALSE, EInternal());return TRUE;} +#line 1899 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAdjustWeaponTime = 0.45f; +#line 1900 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_AdjustWeaponForFire, TRUE; +Jump(STATE_CURRENT, 0x014c00f8, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00f8_FireElectricityGun_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00f8 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_AdjustWeaponForFire, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c00f9, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00f9_FireElectricityGun_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00f9 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1903 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +const FLOATmatrix3D & m = GetRotationMatrix (); +#line 1904 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_vElectricitySource = GetFireingPositionAbsolute (); +#line 1907 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 1908 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetEntityInfoPosition (m_penEnemy , peiTarget -> vTargetCenter , m_vElectricityTarget ); +#line 1911 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.4f); +Jump(STATE_CURRENT, 0x014c00fa, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00fa_FireElectricityGun_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00fa +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c00fb, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c00fb_FireElectricityGun_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00fb +; +#line 1914 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bRenderElectricity = TRUE ; +#line 1915 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmTemp = _pTimer -> CurrentTick (); +#line 1916 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmNextFXTime = m_tmTemp - _pTimer -> TickQuantum ; +#line 1917 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayWeaponSound (SOUND_GHOSTBUSTER ); +#line 1918 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c00fe, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c00fe_FireElectricityGun_11(const CEntityEvent &__eeInput) +#line 1919 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00fe +if(!(_pTimer -> CurrentTick () < m_tmTemp + 0.75f)){ Jump(STATE_CURRENT,0x014c00ff, FALSE, EInternal());return TRUE;} +#line 1920 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x014c00fc, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c00fc_FireElectricityGun_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00fc +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 1923 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vNewTarget ; +#line 1924 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 1925 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetEntityInfoPosition (m_penEnemy , peiTarget -> vTargetCenter , vNewTarget ); +#line 1926 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D vDiff = vNewTarget - m_vElectricityTarget ; +#line 1928 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(vDiff . Length () > 1.0f) +#line 1929 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1931 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_vElectricityTarget = m_vElectricityTarget + vDiff . Normalize () * 10.0f * _pTimer -> TickQuantum ; +#line 1932 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1935 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CCastRay crRay (this , m_vElectricitySource , m_vElectricityTarget ); +#line 1936 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 1937 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +crRay . cr_bPhysical = FALSE ; +#line 1938 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +crRay . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ; +#line 1939 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetWorld () -> CastRay (crRay ); +#line 1941 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(crRay . cr_penHit != NULL ) +#line 1942 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1944 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +InflictDirectDamage (crRay . cr_penHit , this , DMT_BULLET , 50.0f * _pTimer -> TickQuantum / 0.5f , +#line 1945 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D (0 , 0 , 0) , (m_vElectricitySource - m_vElectricityTarget ) . Normalize ()); +#line 1946 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1948 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(_pTimer -> CurrentTick () > m_tmNextFXTime ) +#line 1949 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 1950 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmNextFXTime = _pTimer -> CurrentTick () + 0.125f + FRnd () * 0.125f; +#line 1951 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPlacement3D plElectricityTarget = CPlacement3D (m_vElectricityTarget , ANGLE3D (0 , 0 , 0)); +#line 1952 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CEntity * penEffector = CreateEntity (plElectricityTarget , CLASS_EFFECTOR ); +#line 1954 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ESpawnEffector eSpawnEffector ; +#line 1955 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +eSpawnEffector . tmLifeTime = 6.0f; +#line 1956 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +eSpawnEffector . fSize = 0.025f; +#line 1957 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +eSpawnEffector . eetType = ET_HIT_GROUND ; +#line 1958 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +eSpawnEffector . vDamageDir = FLOAT3D (0.0f , 2.0f , 0.0f); +#line 1960 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +penEffector -> Initialize (eSpawnEffector ); +#line 1961 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 1963 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 1964 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x014c00fd, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 1966 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}return TRUE;}BOOL CDevil::H0x014c00fd_FireElectricityGun_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00fd +Jump(STATE_CURRENT,0x014c00fe, FALSE, EInternal());return TRUE; +#line 1967 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c00ff_FireElectricityGun_12(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c00ff + +#line 1968 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soSound . Stop (); +#line 1969 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bRenderElectricity = FALSE ; +#line 1971 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.8f - m_fAdjustWeaponTime ); +Jump(STATE_CURRENT, 0x014c0100, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0100_FireElectricityGun_13(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0100 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0101, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0101_FireElectricityGun_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0101 +; +#line 1972 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles ++; +#line 1973 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! IsInFrustum (m_penEnemy , CosFast (30.0f))){ +#line 1974 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles = 10000; +#line 1975 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}Jump(STATE_CURRENT,0x014c0102, FALSE, EInternal());return TRUE; +#line 1976 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c0103_FireElectricityGun_16(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0103 + +#line 1977 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_StraightenUpWeapon, TRUE; +Jump(STATE_CURRENT, 0x014c0104, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0104_FireElectricityGun_17(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0104 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_StraightenUpWeapon, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0105, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0105_FireElectricityGun_18(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0105 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1980 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_FROMATTACK02TOIDLE , AOF_SMOOTHCHANGE ); +#line 1984 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +MaybeSwitchToAnotherPlayer (); +#line 1987 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 1987 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 1990 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireGuidedProjectile(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_FireGuidedProjectile + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::FireGuidedProjectile expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1992 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitWalkOrIdleToEnd, TRUE; +Jump(STATE_CURRENT, 0x014c0107, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0107_FireGuidedProjectile_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0107 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitWalkOrIdleToEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0108, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0108_FireGuidedProjectile_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0108 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1994 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_ATTACKBREATHSTART , AOF_SMOOTHCHANGE ); +#line 1995 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c0109, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0109_FireGuidedProjectile_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0109 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c010a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c010a_FireGuidedProjectile_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c010a +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1996 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soLeft , SOUND_ATTACK_BREATH_START , SOF_3D ); +#line 1998 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_ATTACKBREATH , AOF_SMOOTHCHANGE ); +#line 1999 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x014c010b, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c010b_FireGuidedProjectile_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c010b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c010c, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c010c_FireGuidedProjectile_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c010c +const EReturn&__e= (EReturn&)__eeInput; +; +#line 2000 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soRight , SOUND_ATTACK_BREATH_LOOP , SOF_LOOP | SOF_3D ); +#line 2003 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles = 0; +#line 2004 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmFireBreathStart = _pTimer -> CurrentTick (); +#line 2005 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmFireBreathStop = UpperLimit (0.0f); +#line 2007 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +const FLOATmatrix3D & m = GetRotationMatrix (); +#line 2008 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_vFireBreathSource = GetPlacement () . pl_PositionVector + MAGIC_PROJECTILE_EXIT * m ; +#line 2009 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_vFireBreathTarget = m_penEnemy -> GetPlacement () . pl_PositionVector - FLOAT3D (0 , 20.0f , 0); +#line 2010 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c0111, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0111_FireGuidedProjectile_11(const CEntityEvent &__eeInput) +#line 2011 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0111 +if(!(m_iFiredProjectiles < m_iToFireProjectiles )){ Jump(STATE_CURRENT,0x014c0112, FALSE, EInternal());return TRUE;} +#line 2012 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmLastPause = 0.45f; +#line 2013 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(m_tmLastPause ); +Jump(STATE_CURRENT, 0x014c010d, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c010d_FireGuidedProjectile_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c010d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c010e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c010e_FireGuidedProjectile_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c010e +; +#line 2015 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ShootProjectile (PRT_DEVIL_GUIDED_PROJECTILE , MAGIC_PROJECTILE_EXIT , +#line 2016 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ANGLE3D (AngleDeg (10.0f * Cos (m_iFiredProjectiles * 360.0 / 6.0f)) , - AngleDeg (20.0f * Sin (m_iFiredProjectiles * 180.0 / 6.0f)) , 0)); +#line 2017 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayWeaponSound (SOUND_ATTACK_BREATH_FIRE ); +#line 2019 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.8f - m_tmLastPause ); +Jump(STATE_CURRENT, 0x014c010f, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c010f_FireGuidedProjectile_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c010f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0110, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0110_FireGuidedProjectile_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0110 +; +#line 2020 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iFiredProjectiles ++;Jump(STATE_CURRENT,0x014c0111, FALSE, EInternal());return TRUE; +#line 2021 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c0112_FireGuidedProjectile_12(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0112 + +#line 2022 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopFireBreathParticles (); +#line 2024 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_WaitCurrentAnimEnd, TRUE; +Jump(STATE_CURRENT, 0x014c0113, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0113_FireGuidedProjectile_13(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0113 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_WaitCurrentAnimEnd, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0114, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0114_FireGuidedProjectile_14(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0114 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 2025 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_ATTACK_BREATH_END , SOF_3D ); +#line 2026 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soRight . Stop (); +#line 2027 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_ATTACKBREATHEND , AOF_SMOOTHCHANGE ); +#line 2029 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +MaybeSwitchToAnotherPlayer (); +#line 2032 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 2032 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 2036 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +JumpIntoPyramid(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_JumpIntoPyramid + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::JumpIntoPyramid expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2039 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +TurnOffPhysics (); +#line 2040 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopMoving (); +#line 2043 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +RemoveWeapons (); +#line 2044 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTargetNone (); +#line 2045 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetPlacement (m_plTeleport ); +#line 2046 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_CLIMB , 0); +#line 2047 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soJumpIntoPyramid , SOUND_CLIMB , SOF_3D ); +#line 2048 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(7.0f); +Jump(STATE_CURRENT, 0x014c0116, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0116_JumpIntoPyramid_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0116 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0117, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0117_JumpIntoPyramid_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0117 +; +#line 2051 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmTemp = _pTimer -> CurrentTick (); +#line 2052 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c011a, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c011a_JumpIntoPyramid_05(const CEntityEvent &__eeInput) +#line 2053 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c011a +if(!(_pTimer -> CurrentTick () < m_tmTemp + 0.7f)){ Jump(STATE_CURRENT,0x014c011b, FALSE, EInternal());return TRUE;} +#line 2054 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x014c0118, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0118_JumpIntoPyramid_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0118 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x014c0119, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 2058 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}return TRUE;}BOOL CDevil::H0x014c0119_JumpIntoPyramid_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0119 + +#line 2059 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPlacement3D plCurrent = GetPlacement (); +#line 2060 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT aDelta = - 35.0f / 0.7f * _pTimer -> TickQuantum ; +#line 2061 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +plCurrent . pl_OrientationAngle += FLOAT3D (aDelta , 0 , 0); +#line 2062 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetPlacement (plCurrent );Jump(STATE_CURRENT,0x014c011a, FALSE, EInternal());return TRUE; +#line 2063 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c011b_JumpIntoPyramid_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c011b + +#line 2065 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ShakeItFarBaby (_pTimer -> CurrentTick () , 1.5f); +#line 2066 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_CLIMB ) - 7.335f - _pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x014c011c, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c011c_JumpIntoPyramid_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c011c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c011d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c011d_JumpIntoPyramid_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c011d +; +#line 2068 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SelectRandomAnger (); +#line 2069 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (m_iAngryAnim , 0); +#line 2070 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , m_iAngrySound , SOF_3D ); +#line 2071 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (m_iAngryAnim ) - 0.1f); +Jump(STATE_CURRENT, 0x014c011e, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c011e_JumpIntoPyramid_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c011e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c011f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c011f_JumpIntoPyramid_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c011f +; +#line 2073 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopMoving (); +#line 2074 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopRotating (); +#line 2075 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +TurnOnPhysics (); +#line 2076 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_GrabBothWeapons, TRUE; +Jump(STATE_CURRENT, 0x014c0120, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0120_JumpIntoPyramid_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0120 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_GrabBothWeapons, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0121, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0121_JumpIntoPyramid_12(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0121 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 2078 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsDevilState = DS_PYRAMID_FIGHT ; +#line 2079 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dapAttackPower = DAP_MEDIUM_POWER_ATTACK ; +#line 2080 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackRadius = 1e6f; +#line 2081 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackRunSpeed = 8.0f; +#line 2083 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 2083 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 2086 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +TeleportIntoPyramid(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_TeleportIntoPyramid + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::TeleportIntoPyramid expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2089 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +RemoveWeapons (); +#line 2090 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTargetNone (); +#line 2091 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Teleport (m_plTeleport , FALSE ); +#line 2092 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopMoving (); +#line 2093 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopRotating (); +#line 2095 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SelectRandomAnger (); +#line 2096 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (m_iAngryAnim , 0); +#line 2097 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , m_iAngrySound , SOF_3D ); +#line 2098 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (m_iAngryAnim ) - 0.1f); +Jump(STATE_CURRENT, 0x014c0123, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0123_TeleportIntoPyramid_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0123 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0124, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0124_TeleportIntoPyramid_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0124 +; +#line 2100 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +TurnOnPhysics (); +#line 2101 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_GrabBothWeapons, TRUE; +Jump(STATE_CURRENT, 0x014c0125, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0125_TeleportIntoPyramid_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0125 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_GrabBothWeapons, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c0126, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0126_TeleportIntoPyramid_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0126 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 2103 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsDevilState = DS_PYRAMID_FIGHT ; +#line 2104 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dapAttackPower = DAP_MEDIUM_POWER_ATTACK ; +#line 2105 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackRadius = 1e6f; +#line 2106 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackRunSpeed = 8.0f; +#line 2108 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 2108 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 2111 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +RegenerationImpulse(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_RegenerationImpulse + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::RegenerationImpulse expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2113 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsPreRegenerationDevilState = m_dsDevilState ; +#line 2114 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsDevilState = DS_REGENERATION_IMPULSE ; +#line 2115 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_HEAL , 0); +#line 2116 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soSound , SOUND_HEAL , SOF_3D ); +#line 2118 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopFireBreathParticles (); +#line 2119 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmRegenerationStart = _pTimer -> CurrentTick (); +#line 2120 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmRegenerationStop = m_tmRegenerationStart + TM_HEALTH_IMPULSE - 1.5f; +#line 2122 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmTemp = _pTimer -> CurrentTick (); +#line 2123 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT,0x014c012a, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c012a_RegenerationImpulse_03(const CEntityEvent &__eeInput) +#line 2124 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c012a +if(!(_pTimer -> CurrentTick () < m_tmTemp + TM_HEALTH_IMPULSE )){ Jump(STATE_CURRENT,0x014c012b, FALSE, EInternal());return TRUE;} +#line 2125 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x014c0128, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0128_RegenerationImpulse_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0128 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x014c0129, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 2129 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}return TRUE;}BOOL CDevil::H0x014c0129_RegenerationImpulse_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0129 + +#line 2130 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetHealth (GetHealth () + HEALTH_IMPULSE * _pTimer -> TickQuantum / TM_HEALTH_IMPULSE );Jump(STATE_CURRENT,0x014c012a, FALSE, EInternal());return TRUE; +#line 2131 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}BOOL CDevil::H0x014c012b_RegenerationImpulse_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c012b + +#line 2132 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsDevilState = m_dsPreRegenerationDevilState ; +#line 2134 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EReturn ()); +#line 2134 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 2137 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_StopAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::StopAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2138 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(!(m_penEnemy == NULL )){ Jump(STATE_CURRENT,0x014c012f, FALSE, EInternal());return TRUE;} +#line 2140 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +STATE_CDevil_Celebrate, TRUE; +Jump(STATE_CURRENT, 0x014c012d, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c012d_StopAttack_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c012d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevil_Celebrate, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014c012e, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c012e_StopAttack_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c012e +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x014c012f, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c012f_StopAttack_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c012f + +#line 2143 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_StopAttack, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 2146 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ContinueInMainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_ContinueInMainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::ContinueInMainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2148 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SwitchToModel (); +#line 2150 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! m_bWasOnceInMainLoop ) +#line 2151 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2152 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bWasOnceInMainLoop = TRUE ; +#line 2153 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; +#line 2154 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2155 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else +#line 2156 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2158 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CEntity * penEnemy = FixupCausedToPlayer (this , m_penEnemy , FALSE ); +#line 2159 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(penEnemy != m_penEnemy ){ +#line 2160 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTargetSoft (penEnemy ); +#line 2161 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2163 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_StandardBehavior, FALSE, EVoid());return TRUE; +#line 2164 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 2167 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +MPIntro(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_MPIntro + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::MPIntro expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2169 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsDevilState = DS_PYRAMID_FIGHT ; +#line 2170 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CDevil_ContinueInMainLoop, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 2176 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Death(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_Death + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::Death expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2177 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetFlags (GetFlags () & ~ ENF_ALIVE ); +#line 2178 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopFireBreathParticles (); +#line 2179 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopRegenerationParticles (); +#line 2181 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopMoving (); +#line 2182 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +DeathSound (); +#line 2184 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetCollisionFlags (ECF_MODEL ); +#line 2186 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AnimForDeath (); +#line 2187 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(4.66f); +Jump(STATE_CURRENT, 0x014c0133, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0133_Death_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0133 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0134, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0134_Death_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0134 +; +#line 2188 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ShakeItFarBaby (_pTimer -> CurrentTick () , 5.0f); +#line 2189 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (DEVIL_ANIM_DEATH ) - 4.66f); +Jump(STATE_CURRENT, 0x014c0135, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0135_Death_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0135 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0136, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0136_Death_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0136 +; +#line 2190 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmDeathTime = _pTimer -> CurrentTick (); +#line 2192 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 2193 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(pwsc != NULL ) +#line 2194 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2195 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_colGlade = C_WHITE ; +#line 2196 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_tmGlaringStarted = _pTimer -> CurrentTick () + 1.5f; +#line 2197 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_tmGlaringEnded = pwsc -> m_tmGlaringStarted + 1.0f , +#line 2198 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fGlaringFadeInRatio = 0.2f; +#line 2199 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +pwsc -> m_fGlaringFadeOutRatio = 0.7f; +#line 2200 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2201 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(1.5f); +Jump(STATE_CURRENT, 0x014c0137, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0137_Death_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0137 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c0138, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c0138_Death_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0138 +; +#line 2202 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soLeft , SOUND_DISAPPEAR , SOF_3D | SOF_VOLUMETRIC ); +#line 2203 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x014c0139, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0139_Death_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0139 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c013a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c013a_Death_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c013a +; +#line 2204 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SwitchToEditorModel (); +#line 2206 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlaySound (m_soRight , SOUND_DEATHPARTICLES , SOF_3D ); +#line 2207 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Return(STATE_CURRENT,EEnd ()); +#line 2207 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevil:: +#line 2213 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevil_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevil::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2214 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_sptType = SPT_NONE ; +#line 2216 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +InitAsEditorModel (); +#line 2217 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetPhysicsFlags (EPF_MODEL_WALKING & ~ EPF_TRANSLATEDBYGRAVITY ); +#line 2218 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetCollisionFlags (((ECBI_MODEL ) << ECB_TEST ) | ((ECBI_MODEL ) << ECB_PASS ) | ((ECBI_ITEM ) << ECB_IS )); +#line 2219 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 2222 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bBoss = TRUE ; +#line 2223 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! m_bForMPIntro ) +#line 2224 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2225 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetHealth (BOSS_HEALTH ); +#line 2226 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2227 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else +#line 2228 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2229 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetHealth (5000); +#line 2230 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2231 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fMaxHealth = BOSS_HEALTH ; +#line 2232 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fBlowUpAmount = 1e6; +#line 2233 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fBodyParts = 6; +#line 2234 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fDamageWounded = 1e9; +#line 2235 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +en_fDensity = 2500.0f; +#line 2236 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bHasUpperWeapons = FALSE ; +#line 2237 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bRenderElectricity = FALSE ; +#line 2238 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bOnStartPosition = FALSE ; +#line 2239 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmGiveUp = UpperLimit (0.0f); +#line 2240 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmDeathTime = - 1.0f; +#line 2255 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetComponents (this , * GetModelObject () , MODEL_DEVIL , TEXTURE_DEVIL , 0 , 0 , 0); +#line 2258 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> StretchModel (FLOAT3D (SIZE , SIZE , SIZE )); +#line 2259 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ModelChangeNotify (); +#line 2261 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StandingAnim (); +#line 2264 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fWalkSpeed = 10.0f; +#line 2265 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_aWalkRotateSpeed = AngleDeg (90.0f); +#line 2266 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackRunSpeed = 8.0f; +#line 2267 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_aAttackRotateSpeed = AngleDeg (90.0f); +#line 2268 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fCloseRunSpeed = 8.0f; +#line 2269 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_aCloseRotateSpeed = AngleDeg (90.0f); +#line 2271 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackDistance = 1e24f; +#line 2272 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fCloseDistance = 50.0f; +#line 2273 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fStopDistance = 10.0f; +#line 2274 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackFireTime = 10.0f; +#line 2275 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fCloseFireTime = 5.0f; +#line 2276 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fIgnoreRange = UpperLimit (0.0f); +#line 2277 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +en_fAcceleration = en_fDeceleration = 50.0f; +#line 2278 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fLockOnEnemyTime = 0.05f; +#line 2279 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fPauseStretcher = 1.0f; +#line 2280 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bWasOnceInMainLoop = FALSE ; +#line 2283 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetupLightSource (); +#line 2285 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +try { +#line 2286 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_aoLightAnimation . SetData_t (CTFILENAME ("Animations\\BasicEffects.ani")); +#line 2287 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}catch (char * strError ){ +#line 2288 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WarningMessage (TRANS ("Cannot load Animations\\BasicEffects.ani: %s") , strError ); +#line 2289 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2290 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PlayLightAnim (LIGHT_ANIM_NONE , 0); +#line 2292 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x014c013b, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c013b_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c013b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x014c013c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDevil::H0x014c013c_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c013c +; +#line 2294 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_iScore = 0; +#line 2296 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(!(! m_bForMPIntro )){ Jump(STATE_CURRENT,0x014c0140, FALSE, EInternal());return TRUE;} +#line 2298 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_POSEDOWN , 0); +#line 2299 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x014c013d, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c013d_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c013d +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x014c013e, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 2302 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}return TRUE;}BOOL CDevil::H0x014c013e_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c013e +Jump(STATE_CURRENT,0x014c013f, FALSE, EInternal());return TRUE;}BOOL CDevil::H0x014c0140_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0140 + +#line 2305 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2306 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StartModelAnim (DEVIL_ANIM_DEFAULT , 0); +#line 2307 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}Jump(STATE_CURRENT,0x014c013f, FALSE, EInternal());return TRUE;} +BOOL CDevil::H0x014c013f_Main_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c013f + +#line 2309 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SwitchToModel (); +#line 2312 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsDevilState = DS_NOT_EXISTING ; +#line 2314 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x014c0141, FALSE, EBegin());return TRUE;}BOOL CDevil::H0x014c0141_Main_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0141 +switch(__eeInput.ee_slEvent) +#line 2315 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 2317 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bDebugFinalBoss ) +#line 2318 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2319 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Main loop, event: Begin\n"); +#line 2320 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2321 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! m_bForMPIntro ) +#line 2322 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2323 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_dsDevilState == DS_NOT_EXISTING ) +#line 2324 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2325 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsDevilState = DS_DESTROYING_CITY ; +#line 2326 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Call(STATE_CURRENT, STATE_CDevil_DestroyCity, TRUE, EVoid());return TRUE; +#line 2327 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2328 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2329 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 2330 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger): +#line 2332 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{const ETrigger&e= (ETrigger&)__eeInput; + +#line 2333 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bDebugFinalBoss ) +#line 2334 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2335 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Main loop, event: Trigger\n"); +#line 2336 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2337 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 2338 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDevilCommand): +#line 2340 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{const EDevilCommand&eDevilCommand= (EDevilCommand&)__eeInput; + +#line 2341 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bDebugFinalBoss ) +#line 2342 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2343 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CTString strDevilCommand = DevilCommandType_enum . NameForValue (INDEX (eDevilCommand . dctType )); +#line 2344 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Main loop, event: Devil command: %s\n" , strDevilCommand ); +#line 2345 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2347 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(eDevilCommand . dctType == DC_GRAB_LOWER_WEAPONS ) +#line 2348 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2349 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dapAttackPower = DAP_LOW_POWER_ATTACK ; +#line 2350 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsDevilState = DS_ENEMY ; +#line 2351 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Call(STATE_CURRENT, STATE_CDevil_GrabLowerWeapons, TRUE, EVoid());return TRUE; +#line 2352 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2354 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(eDevilCommand . dctType == DC_FORCE_ACTION ) +#line 2355 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2356 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_penAction = eDevilCommand . penForcedAction ; +#line 2357 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Call(STATE_CURRENT, STATE_CDevil_DestroyCity, TRUE, EVoid());return TRUE; +#line 2358 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2359 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(eDevilCommand . dctType == DC_STOP_MOVING ) +#line 2360 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2361 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_vStartPosition = GetPlacement () . pl_PositionVector ; +#line 2362 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_fAttackRadius = 0.0f; +#line 2363 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2364 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(eDevilCommand . dctType == DC_STOP_ATTACK ) +#line 2365 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2366 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SetTargetNone (); +#line 2367 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2368 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(eDevilCommand . dctType == DC_JUMP_INTO_PYRAMID ) +#line 2369 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2370 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_IDLE , 0); +#line 2371 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_plTeleport = eDevilCommand . penForcedAction -> GetPlacement (); +#line 2372 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsDevilState = DS_JUMPING_INTO_PYRAMID ; +#line 2373 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Call(STATE_CURRENT, STATE_CDevil_JumpIntoPyramid, TRUE, EVoid());return TRUE; +#line 2374 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2375 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +else if(eDevilCommand . dctType == DC_TELEPORT_INTO_PYRAMID ) +#line 2376 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2377 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GetModelObject () -> PlayAnim (DEVIL_ANIM_IDLE , 0); +#line 2378 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_plTeleport = eDevilCommand . penForcedAction -> GetPlacement (); +#line 2379 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsDevilState = DS_JUMPING_INTO_PYRAMID ; +#line 2380 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Call(STATE_CURRENT, STATE_CDevil_TeleportIntoPyramid, TRUE, EVoid());return TRUE; +#line 2381 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2382 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 2383 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_ERegenerationImpuls): +#line 2385 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{const ERegenerationImpuls&e= (ERegenerationImpuls&)__eeInput; + +#line 2386 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bDebugFinalBoss ) +#line 2387 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2388 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Main loop, event: Regeneration impulse\n"); +#line 2389 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2390 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bRenderElectricity = FALSE ; +#line 2391 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Call(STATE_CURRENT, STATE_CDevil_RegenerationImpulse, TRUE, EVoid());return TRUE; +#line 2392 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 2393 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_EHitBySpaceShipBeam): +#line 2395 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{const EHitBySpaceShipBeam&e= (EHitBySpaceShipBeam&)__eeInput; + +#line 2396 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bDebugFinalBoss ) +#line 2397 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2398 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Main loop, event: Hit by space ship beam\n"); +#line 2399 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2400 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bRenderElectricity = FALSE ; +#line 2401 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_tmHitBySpaceShipBeam = _pTimer -> CurrentTick (); +#line 2402 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Call(STATE_CURRENT, STATE_CDevil_BeamDamage, TRUE, EVoid());return TRUE; +#line 2403 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 2404 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 2407 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(! (GetFlags () & ENF_ALIVE )) +#line 2408 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2409 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 2410 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2412 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bDebugFinalBoss ) +#line 2413 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2414 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Main loop, event: Death\n"); +#line 2415 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2417 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_bRenderElectricity = FALSE ; +#line 2418 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Die, FALSE, eDeath );return TRUE; +#line 2419 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnvironmentStart): +#line 2421 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{const EEnvironmentStart&e= (EEnvironmentStart&)__eeInput; + +#line 2422 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Call(STATE_CURRENT, STATE_CDevil_MPIntro, TRUE, EVoid());return TRUE; +#line 2423 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 2424 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn): +#line 2426 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{const EReturn&e= (EReturn&)__eeInput; + +#line 2427 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(cht_bDebugFinalBoss ) +#line 2428 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2429 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CPrintF ("Main loop, event: Return\n"); +#line 2430 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2431 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_dsDevilState == DS_DESTROYING_CITY ) +#line 2432 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2433 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_soSound . Set3DParameters (1000.0f , 500.0f , 2.0f , 1.0f); +#line 2434 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dsDevilState = DS_ENEMY ; +#line 2435 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +if(m_dapAttackPower == DAP_NOT_ATTACKING ) +#line 2436 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +{ +#line 2437 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +m_dapAttackPower = DAP_PLAYER_HUNT ; +#line 2438 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2439 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +} +#line 2440 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Call(STATE_CURRENT, STATE_CDevil_ContinueInMainLoop, TRUE, EVoid());return TRUE; +#line 2441 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +return TRUE; +#line 2442 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 2443 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +}return TRUE;}BOOL CDevil::H0x014c0142_Main_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014c0142 + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Devil.es b/Sources/EntitiesMP/Devil.es new file mode 100644 index 0000000..b6bef7b --- /dev/null +++ b/Sources/EntitiesMP/Devil.es @@ -0,0 +1,2445 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +332 +%{ +#include "StdH.h" +#include "Models/Enemies/Devil/Devil.h" +#include "Models/Enemies/Devil/Weapons/Laser.h" +#include "Models/Weapons/RocketLauncher/RocketLauncherItem.h" +#include "EntitiesMP/Effector.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/PyramidSpaceShip.h" +#include "EntitiesMP/BackgroundViewer.h" + +#define DEVIL_LASER_SPEED 100.0f +#define DEVIL_ROCKET_SPEED 60.0f +%} + +uses "EntitiesMP/DevilMarker"; +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/Projectile"; +uses "EntitiesMP/Bullet"; + +event EBrushDestroyedByDevil { + FLOAT3D vDamageDir, +}; + +event ERegenerationImpuls { +}; + +enum DevilCommandType { + 0 DC_GRAB_LOWER_WEAPONS "Grab lower weapons", + 1 DC_FORCE_ACTION "Force next action", + 2 DC_STOP_MOVING "Stop moving", + 3 DC_STOP_ATTACK "Stop attacking", + 4 DC_JUMP_INTO_PYRAMID "Jump into pyramid", + 5 DC_FORCE_ATTACK_RADIUS "Force attack radius", + 6 DC_DECREASE_ATTACK_RADIUS "Decrease attack radius", + 7 DC_TELEPORT_INTO_PYRAMID "Teleport into pyramid", +}; + +event EDevilCommand { + enum DevilCommandType dctType, + CEntityPointer penForcedAction, + FLOAT fAttackRadius, + FLOAT3D vCenterOfAttack, +}; + +enum DevilState { + 0 DS_NOT_EXISTING "Not existing", // idle + 1 DS_DESTROYING_CITY "Destroying city", // process of destroying city + 2 DS_ENEMY "Enemy", // behave as normal enemy + 3 DS_JUMPING_INTO_PYRAMID "Jumping into pyramid", // jumping into pyramid + 4 DS_PYRAMID_FIGHT "Pyramid fight", // pyramid fight + 5 DS_REGENERATION_IMPULSE "Regenerating with impulse", // drinking power +}; + +enum DevilAttackPower { + 1 DAP_PLAYER_HUNT "Player hunt", // process of hunting player + 2 DAP_LOW_POWER_ATTACK "Low power attack", // low power attack + 3 DAP_MEDIUM_POWER_ATTACK "Medium power attack", // medium power attack + 4 DAP_FULL_POWER_ATTACK "Full power attack", // full power attack + 5 DAP_NOT_ATTACKING "Not attacking", // not attacking +}; + +%{ +static FLOAT3D vLastStartPosition; +static FLOAT vLastAttackRadius; + +extern INDEX cht_bKillFinalBoss; +extern INDEX cht_bDebugFinalBoss; +extern INDEX cht_bDumpFinalBossData; +extern INDEX cht_bDebugFinalBossAnimations; + +#define LIGHT_ANIM_FIRE 3 +#define LIGHT_ANIM_NONE 5 + +// parameters defining boss +#define SIZE 50.0f +#define DEVIL_HOOF_RADIUS 0.25f*SIZE +#define DEVIL_HIT_HOOF_OFFSET FLOAT3D(-0.149021f, 0.084463f, -0.294425f)*SIZE +#define DEVIL_WALK_HOOF_RIGHT_OFFSET FLOAT3D(0.374725f, 0.0776713f, 0.0754253f)*SIZE +#define DEVIL_WALK_HOOF_LEFT_OFFSET FLOAT3D(-0.402306f, 0.0864595f, 0.292397f)*SIZE + +#define ATT_PROJECTILE_GUN (FLOAT3D(-0.703544f, 1.12582f, -0.329834f)*SIZE) +#define ATT_LASER (FLOAT3D(0.63626f, 1.13841f, -0.033062f)*SIZE) +#define ATT_ELECTRICITYGUN (FLOAT3D(-0.764868f, 1.27992f, -0.311084f)*SIZE) +#define ATT_ROCKETLAUNCHER (FLOAT3D(0.654788f, 1.30318f, -0.259358f)*SIZE) +#define MAGIC_PROJECTILE_EXIT (FLOAT3D(0.035866f, 1.400f, -0.792264f)*SIZE) + +#define ELECTROGUN_PIPE (FLOAT3D(-0.00423616f, -0.0216781f, -0.506613f)*SIZE) +#define LASER_PIPE (FLOAT3D(0.0172566f, -0.123152f, -0.232228f)*SIZE) + +#define PROJECTILEGUN_PIPE (FLOAT3D(0.0359023f, -0.000490744f, -0.394403f)*SIZE) +#define ROCKETLAUNCHER_PIPE (FLOAT3D(4.68194e-005f, 0.0483391f, -0.475134f)*SIZE) + +#define HEALTH_MULTIPLIER 1.0f +#define BOSS_HEALTH (40000.0f*HEALTH_MULTIPLIER) +#define HEALTH_IMPULSE (10000.0f*HEALTH_MULTIPLIER) +#define HEALTH_CLASS_1 (5000*HEALTH_MULTIPLIER) +#define HEALTH_CLASS_2 (7500*HEALTH_MULTIPLIER) +#define HEALTH_CLASS_3 (10000*HEALTH_MULTIPLIER) +#define HEALTH_CLASS_4 (15000*HEALTH_MULTIPLIER) +#define CLASS_2_CANNON_FACTOR 0.75f +#define CLASS_3_ROCKETLAUNCHER_FACTOR 0.75f +#define CLASS_4_ROCKETLAUNCHER_FACTOR 0.25f +#define TM_HEALTH_IMPULSE 4.0f + +// info structure +static EntityInfo eiDevil = { + EIBT_FLESH, 50000.0f, + 0.0f, 2.0f*SIZE, 0.0f, + 0.0f, 1.4f*SIZE, 0.0f, +}; + +%} + +class CDevil : CEnemyBase { +name "Devil"; +thumbnail "Thumbnails\\Devil.tbn"; + +properties: + 1 INDEX m_iAttID = 0, // internal temp var + 2 FLOAT m_fDeltaWeaponPitch = 0.0f, // for adjusting weapon pitch + 3 FLOAT m_fDeltaWeaponHdg = 0.0f, // for adjusting weapon hdg + 4 FLOAT m_fFireTime = 0.0f, // time to fire bullets + 5 CAnimObject m_aoLightAnimation, // light animation object + 6 CEntityPointer m_penAction "Action" 'O', // ptr to action marker entity + 8 INDEX m_iFiredProjectiles = 0, // internal counter of fired projectiles + 9 INDEX m_iToFireProjectiles = 0, // internal counter of projectiles that should be fired + 10 FLOAT m_fPauseStretcher = 0, // stretch factor for pauses between fireing + 11 FLOAT m_tmLastPause = 0.0f, // last pause between two fireings + 12 enum DevilState m_dsDevilState = DS_NOT_EXISTING,// current devil state + 13 FLOAT m_tmLastAngry = -1.0f, // last angry state + 14 CPlacement3D m_plTeleport = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)), + 16 FLOAT m_tmTemp = 0, + 17 enum DevilState m_dsLastDevilState = DS_REGENERATION_IMPULSE,// last devil state + 18 enum DevilAttackPower m_dapAttackPower = DAP_PLAYER_HUNT,// current devil state + 19 enum DevilAttackPower m_dapLastAttackPower = DAP_NOT_ATTACKING, + 20 BOOL m_bHasUpperWeapons = FALSE, + 21 FLOAT3D m_vElectricitySource = FLOAT3D( 0,0,0), // position of electricity ray target + 22 FLOAT3D m_vElectricityTarget = FLOAT3D( 0,0,0), // position of electricity ray target + 23 BOOL m_bRenderElectricity = FALSE, // if electricity particles are rendered + 24 FLOAT m_fAdjustWeaponTime = 0.0f, // time for weapon to lock enemy + 25 BOOL m_bWasOnceInMainLoop = FALSE, // if MainLoop was called at least once + 26 FLOAT m_tmHitBySpaceShipBeam = -1, // last time when was hit by space ship beam + 27 CSoundObject m_soLeft, // left foot sound + 28 CSoundObject m_soRight, // right foot sound + 29 FLOAT m_fLastWalkTime = -1.0f, // last walk time + 30 FLOAT m_tmFireBreathStart = UpperLimit(0.0f), // time when fire breath started + 31 FLOAT m_tmFireBreathStop = 0.0f, // time when fire breath stopped + 32 FLOAT3D m_vFireBreathSource = FLOAT3D( 0,0,0), // position of fire breath source + 33 FLOAT3D m_vFireBreathTarget = FLOAT3D( 0,0,0), // position of fire breath target + 34 FLOAT m_tmRegenerationStart = UpperLimit(0.0f), // time when regeneration started + 35 FLOAT m_tmRegenerationStop = 0.0f, // time when regeneration stopped + 36 FLOAT m_tmNextFXTime = 0.0f, // next effect time + + 37 INDEX m_iNextChannel = 0, // next channel to play sound on + // weapon sound channels + 38 CSoundObject m_soWeapon0, + 39 CSoundObject m_soWeapon1, + 40 CSoundObject m_soWeapon2, + 41 CSoundObject m_soWeapon3, + 42 CSoundObject m_soWeapon4, + + 43 INDEX m_iAngryAnim=0, // random angry animation + 44 INDEX m_iAngrySound=0, // random angry animation + 45 FLOAT m_tmDeathTime = -1.0f, // time of death + + 50 INDEX m_iLastCurrentAnim = -1, + 51 INDEX m_iLastScheduledAnim = -1, + + 52 enum DevilState m_dsPreRegenerationDevilState = DS_ENEMY, + 60 CSoundObject m_soClimb, // sound of climbing + 61 CSoundObject m_soGrabLowerWeapons, + 62 CSoundObject m_soGrabUpperWeapons, + 63 CSoundObject m_soJumpIntoPyramid, + + 70 BOOL m_bForMPIntro "MP Intro" = FALSE, + +{ + CEntity *penBullet; // bullet + CLightSource m_lsLightSource; +} + +components: + 0 class CLASS_BASE "Classes\\EnemyBase.ecl", + 1 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 2 class CLASS_EFFECTOR "Classes\\Effector.ecl", + +// ************** DEVIL ************** + 10 model MODEL_DEVIL "Models\\Enemies\\Devil\\Devil.mdl", + 11 texture TEXTURE_DEVIL "Models\\Enemies\\Devil\\Devil.tex", + +// ************** LASER ************** + 20 model MODEL_LASER "Models\\Enemies\\Devil\\Weapons\\Laser.mdl", + 21 texture TEXTURE_LASER "Models\\Enemies\\Devil\\Weapons\\Laser.tex", + +// ************** ROCKET LAUNCHER ************** + 22 model MODEL_ROCKETLAUNCHER "Models\\Enemies\\Devil\\Weapons\\RocketLauncher.mdl", + 23 texture TEXTURE_ROCKETLAUNCHER "Models\\Enemies\\Devil\\Weapons\\RocketLauncher.tex", + +// ************** PROJECTILE GUN ************** + 24 model MODEL_PROJECTILEGUN "Models\\Enemies\\Devil\\Weapons\\ProjectileGun.mdl", + 25 texture TEXTURE_PROJECTILEGUN "Models\\Enemies\\Devil\\Weapons\\ProjectileGun.tex", + +// ************** ELECTRICITY GUN ************* + 26 model MODEL_ELECTRICITYGUN "Models\\Enemies\\Devil\\Weapons\\ElectricityGun.mdl", + 27 texture TEXTURE_ELECTRICITYGUN "Models\\Enemies\\Devil\\Weapons\\ElectricityGun.tex", + +// ************** SOUNDS ************** + 60 sound SOUND_ANGER01 "Models\\Enemies\\Devil\\Sounds\\Anger01.wav", + 61 sound SOUND_ANGER02 "Models\\Enemies\\Devil\\Sounds\\Anger02.wav", + 62 sound SOUND_ATTACKCLOSE "Models\\Enemies\\Devil\\Sounds\\AttackClose.wav", + 63 sound SOUND_CELEBRATE01 "Models\\Enemies\\Devil\\Sounds\\Celebrate01.wav", + 65 sound SOUND_DEATH "Models\\Enemies\\Devil\\Sounds\\Death.wav", + 66 sound SOUND_DRAW_LOWER_WEAPONS "Models\\Enemies\\Devil\\Sounds\\GrabWeaponsLower.wav", + 67 sound SOUND_DRAW_UPPER_WEAPONS "Models\\Enemies\\Devil\\Sounds\\GrabWeaponsUpper.wav", + 68 sound SOUND_GETUP "Models\\Enemies\\Devil\\Sounds\\Getup.wav", + 69 sound SOUND_IDLE "Models\\Enemies\\Devil\\Sounds\\Idle.wav", + 70 sound SOUND_PUNCH "Models\\Enemies\\Devil\\Sounds\\Punch.wav", + 71 sound SOUND_SMASH "Models\\Enemies\\Devil\\Sounds\\Smash.wav", + 72 sound SOUND_WALK_LEFT "Models\\Enemies\\Devil\\Sounds\\WalkL.wav", + 73 sound SOUND_WALK_RIGHT "Models\\Enemies\\Devil\\Sounds\\WalkR.wav", + 74 sound SOUND_WOUND "Models\\Enemies\\Devil\\Sounds\\Wound.wav", + 75 sound SOUND_ATTACK_BREATH_START "Models\\Enemies\\Devil\\Sounds\\AttackBreathStart.wav", + 76 sound SOUND_ATTACK_BREATH_FIRE "Models\\Enemies\\Devil\\Sounds\\BreathProjectile.wav", + 77 sound SOUND_ATTACK_BREATH_END "Models\\Enemies\\Devil\\Sounds\\AttackBreathEnd.wav", + 78 sound SOUND_HEAL "Models\\Enemies\\Devil\\Sounds\\Heal.wav", + 79 sound SOUND_ROCKETLAUNCHER "Models\\Enemies\\Devil\\Sounds\\RocketLauncher.wav", + 80 sound SOUND_LASER "Models\\Enemies\\Devil\\Sounds\\Laser.wav", + 81 sound SOUND_LAVABOMB "Models\\Enemies\\Devil\\Sounds\\LavaBomb.wav", + 82 sound SOUND_GHOSTBUSTER "Models\\Enemies\\Devil\\Sounds\\Ghostbuster.wav", + 83 sound SOUND_ATTACK_BREATH_LOOP "Models\\Enemies\\Devil\\Sounds\\AttackBreath.wav", + 84 sound SOUND_CLIMB "Models\\Enemies\\Devil\\Sounds\\Enter.wav", + 85 sound SOUND_DEATHPARTICLES "Models\\Enemies\\Devil\\Sounds\\DeathParticles.wav", + 86 sound SOUND_DISAPPEAR "Models\\Enemies\\Devil\\Sounds\\Disappear.wav", + +functions: + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("Ugh Zan killed %s"), strPlayerName); + return str; + } + + void Precache(void) { + CEnemyBase::Precache(); +// ************** DEVIL ************** + PrecacheModel (MODEL_DEVIL ); + PrecacheTexture (TEXTURE_DEVIL ); + +// ************** LASER ************** + PrecacheModel (MODEL_LASER ); + PrecacheTexture (TEXTURE_LASER ); + +// ************** ROCKET LAUNCHER ************** + PrecacheModel (MODEL_ROCKETLAUNCHER ); + PrecacheTexture (TEXTURE_ROCKETLAUNCHER ); + +// ************** ELECTRICITY GUN ************** + PrecacheModel (MODEL_ELECTRICITYGUN); + PrecacheTexture (TEXTURE_ELECTRICITYGUN); + +// ************** PROJECTILE GUN ************** + PrecacheModel (MODEL_PROJECTILEGUN); + PrecacheTexture (TEXTURE_PROJECTILEGUN); + +// ************** PREDICTED PROJECTILE ************** + PrecacheClass(CLASS_PROJECTILE, PRT_LAVAMAN_BIG_BOMB); + PrecacheClass(CLASS_PROJECTILE, PRT_DEVIL_GUIDED_PROJECTILE); + PrecacheClass(CLASS_PROJECTILE, PRT_DEVIL_LASER); + PrecacheClass(CLASS_PROJECTILE, PRT_DEVIL_ROCKET); + +// ************** SOUNDS ************** + PrecacheSound (SOUND_ANGER01 ); + PrecacheSound (SOUND_ANGER02 ); + PrecacheSound (SOUND_ATTACKCLOSE ); + PrecacheSound (SOUND_CELEBRATE01 ); + PrecacheSound (SOUND_DEATH ); + PrecacheSound (SOUND_DRAW_LOWER_WEAPONS ); + PrecacheSound (SOUND_DRAW_UPPER_WEAPONS ); + PrecacheSound (SOUND_GETUP ); + PrecacheSound (SOUND_IDLE ); + PrecacheSound (SOUND_PUNCH ); + PrecacheSound (SOUND_SMASH ); + PrecacheSound (SOUND_WALK_LEFT ); + PrecacheSound (SOUND_WALK_RIGHT ); + PrecacheSound (SOUND_WOUND ); + PrecacheSound (SOUND_ATTACK_BREATH_START ); + PrecacheSound (SOUND_ATTACK_BREATH_FIRE ); + PrecacheSound (SOUND_ATTACK_BREATH_END ); + PrecacheSound (SOUND_HEAL ); + PrecacheSound (SOUND_ROCKETLAUNCHER ); + PrecacheSound (SOUND_LASER ); + PrecacheSound (SOUND_LAVABOMB ); + PrecacheSound (SOUND_GHOSTBUSTER ); + PrecacheSound (SOUND_ATTACK_BREATH_LOOP ); + PrecacheSound (SOUND_CLIMB ); + PrecacheSound (SOUND_DEATHPARTICLES ); + PrecacheSound (SOUND_DISAPPEAR ); + } + + // Validate offered target for one property + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if(penTarget==NULL) + { + return FALSE; + } + return (IsDerivedFromClass(penTarget, "Devil Marker")); + } + + /* Read from stream. */ + void Read_t( CTStream *istr) { // throw char * + CEnemyBase::Read_t(istr); + + // setup light source + SetupLightSource(); + } + + /* Get static light source information. */ + CLightSource *GetLightSource(void) { + if (!IsPredictor()) { + return &m_lsLightSource; + } else { + return NULL; + } + } + + // Setup light source + void SetupLightSource(void) { + // setup light source + CLightSource lsNew; + lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC; + lsNew.ls_rHotSpot = 2.0f; + lsNew.ls_rFallOff = 8.0f; + lsNew.ls_colColor = RGBToColor(128, 128, 128); + lsNew.ls_plftLensFlare = NULL; + lsNew.ls_ubPolygonalMask = 0; + lsNew.ls_paoLightAnimation = &m_aoLightAnimation; + + m_lsLightSource.ls_penEntity = this; + m_lsLightSource.SetLightSource(lsNew); + } + // play light animation + void PlayLightAnim(INDEX iAnim, ULONG ulFlags) { + if (m_aoLightAnimation.GetData()!=NULL) { + m_aoLightAnimation.PlayAnim(iAnim, ulFlags); + } + }; + + + /* Entity info */ + void *GetEntityInfo(void) { + return &eiDevil; + }; + + BOOL ForcesCannonballToExplode(void) + { + return TRUE; + } + + void SetSpeedsToDesiredPosition(const FLOAT3D &vPosDelta, FLOAT fPosDist, BOOL bGoingToPlayer) + { + if(m_penEnemy!=NULL) + { + FLOAT fEnemyDistance = CalcDist(m_penEnemy); + FLOAT fRadius1 = 75.0f; + FLOAT fRadius2 = 200.0f; + FLOAT fSpeedRadius1 = 6.0f; + FLOAT fSpeedRadius2 = 14.0f; + + FLOAT fDistanceRatio = CalculateRatio( fEnemyDistance, fRadius1, fRadius2, 1, 0); + if( fEnemyDistance>=fRadius2) + { + fDistanceRatio = 1.0f; + } + m_fAttackRunSpeed = fSpeedRadius1+fDistanceRatio*(fSpeedRadius2-fSpeedRadius1); + m_fCloseRunSpeed = m_fAttackRunSpeed; + if( cht_bDebugFinalBoss) + { + CPrintF( "Enm dist:%g, Speed=%g\n", fEnemyDistance, m_fAttackRunSpeed); + } + } + CEnemyBase::SetSpeedsToDesiredPosition(vPosDelta, fPosDist, bGoingToPlayer); + } + + FLOAT GetCrushHealth(void) + { + return 1000.0f; + } + + void SelectRandomAnger(void) + { + if( IRnd()%2) { + m_iAngryAnim = DEVIL_ANIM_ANGER01; + m_iAngrySound = SOUND_ANGER01; + } else { + m_iAngryAnim = DEVIL_ANIM_ANGER02; + m_iAngrySound = SOUND_ANGER02; + } + } + + virtual FLOAT GetLockRotationSpeed(void) + { + return m_aAttackRotateSpeed*4; + }; + + void ShakeItBaby(FLOAT tmShaketime, FLOAT fPower) + { + CWorldSettingsController *pwsc = GetWSC(this); + if (pwsc!=NULL) { + pwsc->m_tmShakeStarted = tmShaketime; + pwsc->m_vShakePos = GetPlacement().pl_PositionVector; + pwsc->m_fShakeFalloff = 400.0f; + pwsc->m_fShakeFade = 3.0f; + + pwsc->m_fShakeIntensityZ = 0.0f; + pwsc->m_tmShakeFrequencyZ = 5.0f; + pwsc->m_fShakeIntensityY = 0.1f*fPower; + pwsc->m_tmShakeFrequencyY = 5.0f; + pwsc->m_fShakeIntensityB = 2.5f*fPower; + pwsc->m_tmShakeFrequencyB = 7.2f; + + pwsc->m_bShakeFadeIn = FALSE; + } + } + + void ShakeItFarBaby(FLOAT tmShaketime, FLOAT fPower) + { + CWorldSettingsController *pwsc = GetWSC(this); + if (pwsc!=NULL) { + pwsc->m_tmShakeStarted = tmShaketime; + pwsc->m_vShakePos = GetPlacement().pl_PositionVector; + pwsc->m_fShakeFalloff = 2048.0f; + pwsc->m_fShakeFade = 2.0f; + + pwsc->m_fShakeIntensityZ = 0.0f; + pwsc->m_tmShakeFrequencyZ = 5.0f; + pwsc->m_fShakeIntensityY = 0.1f*fPower; + pwsc->m_tmShakeFrequencyY = 5.0f; + pwsc->m_fShakeIntensityB = 2.5f*fPower; + pwsc->m_tmShakeFrequencyB = 7.2f; + + pwsc->m_bShakeFadeIn = FALSE; + } + } + + void InflictHoofDamage( FLOAT3D vOffset) + { + // apply range damage for right foot + FLOAT3D vFootRel = vOffset; + FLOAT3D vFootAbs = vFootRel*GetRotationMatrix()+GetPlacement().pl_PositionVector; + InflictRangeDamage(this, DMT_IMPACT, 1000.0f, vFootAbs, DEVIL_HOOF_RADIUS, DEVIL_HOOF_RADIUS); + } + + void ApplyFootQuake(void) + { + CModelObject &mo = *GetModelObject(); + TIME tmNow = _pTimer->CurrentTick(); + FLOAT tmAnim = -1; + FLOAT tmWalkLen = mo.GetAnimLength(DEVIL_ANIM_WALK); + FLOAT tmLeftFootOffset = 0.4f; + FLOAT tmRightFootOffset = 2.05f; + + // if we are now playing walk anim, but another anim is scheduled to happen after walk + if (mo.ao_iLastAnim==DEVIL_ANIM_WALK && mo.ao_tmAnimStart>tmNow) + { + // we started one anim time back from anim start time + tmAnim = mo.ao_tmAnimStart-tmWalkLen; + } + else if (mo.ao_iCurrentAnim==DEVIL_ANIM_WALK && mo.ao_tmAnimStart<=tmNow) + { + tmAnim = mo.ao_tmAnimStart; + } + // if we are now playing walk wo idle anim, but another anim is scheduled to happen after walk to idle + else if (mo.ao_iLastAnim==DEVIL_ANIM_FROMWALKTOIDLE && mo.ao_tmAnimStart>tmNow) + { + // we started one anim time back from anim start time + tmAnim = mo.ao_tmAnimStart-tmWalkLen; + tmLeftFootOffset = 0.6f; + tmRightFootOffset = 1.7f; + } + else if (mo.ao_iCurrentAnim==DEVIL_ANIM_FROMWALKTOIDLE && mo.ao_tmAnimStart<=tmNow) + { + tmAnim = mo.ao_tmAnimStart; + tmLeftFootOffset = 0.6f; + tmRightFootOffset = 1.7f; + } + + // WARNING !!! foot variable names are switched + if( tmAnim!=-1) + { + FLOAT tmAnimLast = tmAnim+INDEX((tmNow-tmAnim)/tmWalkLen)*tmWalkLen; + FLOAT tmLeftFootDown = tmAnimLast+tmLeftFootOffset; + FLOAT tmRightFootDown = tmAnimLast+tmRightFootOffset; + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL) + { + if( tmNow>=tmRightFootDown && pwsc->m_tmShakeStarted=tmLeftFootDown && pwsc->m_tmShakeStartedCurrentTick(); + } + + void StopRegenerationParticles(void) + { + m_tmRegenerationStop = _pTimer->CurrentTick(); + } + + void TurnOnPhysics(void) + { + SetPhysicsFlags(EPF_MODEL_WALKING); + SetCollisionFlags(ECF_MODEL); + } + + void TurnOffPhysics(void) + { + SetPhysicsFlags(EPF_MODEL_WALKING&~EPF_TRANSLATEDBYGRAVITY); + SetCollisionFlags(((ECBI_MODEL)<CurrentTick()>m_tmFireBreathStart) + { + // render fire breath particles + INDEX ctRendered = Particles_FireBreath(this, m_vFireBreathSource, m_vFireBreathTarget, + m_tmFireBreathStart, m_tmFireBreathStop); + // if should stop rendering fire breath particles + if( _pTimer->CurrentTick()>m_tmFireBreathStop && ctRendered==0) + { + m_tmFireBreathStart = UpperLimit(0.0f); + } + } + + // regeneration particles + if( _pTimer->CurrentTick()>m_tmRegenerationStart) + { + // render fire breath particles + INDEX ctRendered = Particles_Regeneration(this, m_tmRegenerationStart, m_tmRegenerationStop, 1.0f, FALSE); + // if should stop rendering regeneration particles + if( _pTimer->CurrentTick()>m_tmRegenerationStop && ctRendered==0) + { + m_tmRegenerationStart = UpperLimit(0.0f); + } + } + + // if is dead + if( m_tmDeathTime != -1.0f && _pTimer->CurrentTick()>m_tmDeathTime && _pTimer->CurrentTick()GetAttachmentModel(m_iAttID); + FLOAT3D vAttachment = FLOAT3D(0,0,0); + switch(m_iAttID) + { + case DEVIL_ATTACHMENT_LASER: + vAttachment = ATT_LASER; + break; + case DEVIL_ATTACHMENT_PROJECTILEGUN: + vAttachment = ATT_PROJECTILE_GUN; + break; + case DEVIL_ATTACHMENT_ELETRICITYGUN: + vAttachment = ATT_ELECTRICITYGUN; + break; + case DEVIL_ATTACHMENT_ROCKETLAUNCHER: + vAttachment = ATT_ROCKETLAUNCHER; + break; + default: + ASSERTALWAYS("Invalid attachment ID"); + } + return(vAttachment); + } + + FLOAT3D GetWeaponPositionAbsolute(void) + { + return GetPlacement().pl_PositionVector + GetWeaponPositionRelative()*GetRotationMatrix(); + } + + FLOAT3D GetFireingPositionRelative(void) + { + CAttachmentModelObject &amo = *GetModelObject()->GetAttachmentModel(m_iAttID); + FLOAT3D vWeaponPipe = FLOAT3D(0,0,0); + FLOAT3D vAttachment = FLOAT3D(0,0,0); + switch(m_iAttID) + { + case DEVIL_ATTACHMENT_LASER: + vWeaponPipe = LASER_PIPE; + vAttachment = ATT_LASER; + break; + case DEVIL_ATTACHMENT_PROJECTILEGUN: + vWeaponPipe = PROJECTILEGUN_PIPE; + vAttachment = ATT_PROJECTILE_GUN; + break; + case DEVIL_ATTACHMENT_ELETRICITYGUN: + vWeaponPipe = ELECTROGUN_PIPE; + vAttachment = ATT_ELECTRICITYGUN; + break; + case DEVIL_ATTACHMENT_ROCKETLAUNCHER: + vWeaponPipe = ROCKETLAUNCHER_PIPE; + vAttachment = ATT_ROCKETLAUNCHER; + break; + default: + ASSERTALWAYS("Invalid attachment ID"); + } + + // create matrix + FLOATmatrix3D mWpn; + MakeRotationMatrixFast(mWpn, amo.amo_plRelative.pl_OrientationAngle); + return (vAttachment+vWeaponPipe*mWpn); + } + + FLOAT3D GetFireingPositionAbsolute(void) + { + return GetPlacement().pl_PositionVector + GetFireingPositionRelative()*GetRotationMatrix(); + } + + /* + Regeneration legend: + -------------------- + - if less than 0 -> no generation + - class 1 -> invoke impulse regeneration +HEALTH_IMPULSE + - class 2 -> drops when constantly hitted with cannonballs + - class 3 -> drops when constantly hitted with rockets + - class 4 -> drops when constantly hitted with rockets + - if greater than class 5 -> no regeneration + */ + void ApplyTickRegeneration(void) + { + if( cht_bKillFinalBoss && GetSP()->sp_bSinglePlayer) + { + cht_bKillFinalBoss=FALSE; + SetHealth(-1); + return; + } + // if currently regenerating or died or out of healing range or recently hit by space ship beam + if(m_dsDevilState == DS_REGENERATION_IMPULSE || + GetHealth()<=0 || GetHealth()>=HEALTH_CLASS_4 || + _pTimer->CurrentTick()TickQuantum; + FLOAT fDmgCannonsPerTick = 2959.0f/10.0f*_pTimer->TickQuantum; + FLOAT fRegeneration = 0.0f; + + if(GetHealth()CurrentTick(); + CModelObject &mo = *GetModelObject(); + // obtain current and scheduled animation + INDEX iCurrentAnim, iScheduledAnim; + if (mo.ao_tmAnimStart>tmNow) + { + iCurrentAnim = mo.ao_iLastAnim; + iScheduledAnim = mo.ao_iCurrentAnim; + } + else + { + iCurrentAnim = mo.ao_iCurrentAnim; + iScheduledAnim = -1; + } + + if( iCurrentAnim!=m_iLastCurrentAnim || iScheduledAnim!=m_iLastScheduledAnim) + { + CAnimData *pad = mo.GetData(); + CAnimInfo aiCurrent; + mo.GetAnimInfo(iCurrentAnim, aiCurrent); + CTString strCurrentAnimName = aiCurrent.ai_AnimName; + + CTString strScheduledAnimName = "....."; + if(iScheduledAnim != -1) + { + CAnimInfo aiScheduled; + mo.GetAnimInfo(iScheduledAnim, aiScheduled); + strScheduledAnimName = aiScheduled.ai_AnimName; + } + CPrintF("Time: %-10g %20s, %s\n", + _pTimer->GetLerpedCurrentTick(), strCurrentAnimName, strScheduledAnimName); + } + m_iLastCurrentAnim = iCurrentAnim; + m_iLastScheduledAnim = iScheduledAnim; + } + + if( cht_bDumpFinalBossData) + { + cht_bDumpFinalBossData=FALSE; + // dump devil data to console + CPrintF("\n\n\n\n\n\n\n"); + CPrintF("Devil class data ...................\n"); + CPrintF("\n\n"); + + CTString strAttackPower = DevilAttackPower_enum.NameForValue(INDEX(m_dapAttackPower)); + CPrintF( "Attack power: %s\n", strAttackPower); + CTString strDevilState = DevilState_enum.NameForValue(INDEX(m_dsDevilState)); + CPrintF( "Devil state: %s\n", strDevilState); + + CPrintF("m_fFireTime = %g\n", m_fFireTime); + CPrintF("m_iFiredProjectiles = %d\n", m_iFiredProjectiles); + CPrintF("m_iToFireProjectiles = %d\n", m_iToFireProjectiles); + CPrintF("m_tmLastPause = %g\n", m_tmLastPause); + CPrintF("m_fPauseStretcher = %g\n", m_fPauseStretcher); + CPrintF("m_tmLastAngry = %g\n", m_tmLastAngry); + CPrintF("m_bHasUpperWeapons = %d\n", m_bHasUpperWeapons); + CPrintF("m_fAdjustWeaponTime = %g\n", m_fAdjustWeaponTime); + CPrintF("m_bWasOnceInMainLoop = %d\n", m_bWasOnceInMainLoop); + CPrintF("m_tmHitBySpaceShipBeam = %g\n", m_tmHitBySpaceShipBeam); + CPrintF("m_fLastWalkTime = %g\n", m_fLastWalkTime); + CPrintF("m_tmFireBreathStart = %g\n", m_tmFireBreathStart); + CPrintF("m_tmFireBreathStop = %g\n", m_tmFireBreathStop); + CPrintF("m_tmRegenerationStart = %g\n", m_tmRegenerationStart); + CPrintF("m_tmRegenerationStop = %g\n", m_tmRegenerationStop); + CPrintF("m_tmNextFXTime = %g\n", m_tmNextFXTime); + CPrintF("m_tmDeathTime = %g\n", m_tmDeathTime); + CPrintF("Health = %g\n", GetHealth()); + + CPrintF("\n\n\n\n\n\n\n"); + CPrintF("Enemy base data ...................\n"); + CPrintF("\n\n"); + + CPrintF( "m_ttTarget (type): %d\n", INDEX(m_ttTarget)); + + CPrintF( "m_penWatcher %x\n", m_penWatcher); + CTString strEnemyName = "Null ptr, no name"; + if( m_penEnemy != NULL) + { + strEnemyName = m_penEnemy->GetName(); + } + CPrintF( "m_penEnemy %x, enemy name: %s\n", m_penEnemy, strEnemyName); + + CPrintF( "m_vStartPosition (%g, %g, %g)\n", m_vStartPosition(1), m_vStartPosition(2), m_vStartPosition(3)); + CPrintF( "m_vStartDirection (%g, %g, %g)\n", m_vStartDirection(1), m_vStartDirection(2), m_vStartDirection(3)); + CPrintF( "m_bOnStartPosition = %d\n", m_bOnStartPosition); + CPrintF( "m_fFallHeight = %g\n", m_fFallHeight); + CPrintF( "m_fStepHeight = %g\n", m_fStepHeight); + CPrintF( "m_fSenseRange = %g\n", m_fSenseRange); + CPrintF( "m_fViewAngle = %g\n", m_fViewAngle); + + CPrintF( "m_fWalkSpeed = %g\n", m_fWalkSpeed); + CPrintF( "m_aWalkRotateSpeed = %g\n", m_aWalkRotateSpeed); + CPrintF( "m_fAttackRunSpeed = %g\n", m_fAttackRunSpeed); + CPrintF( "m_aAttackRotateSpeed = %g\n", m_aAttackRotateSpeed); + CPrintF( "m_fCloseRunSpeed = %g\n", m_fCloseRunSpeed); + CPrintF( "m_aCloseRotateSpeed = %g\n", m_aCloseRotateSpeed); + CPrintF( "m_fAttackDistance = %g\n", m_fAttackDistance); + CPrintF( "m_fCloseDistance = %g\n", m_fCloseDistance); + CPrintF( "m_fAttackFireTime = %g\n", m_fAttackFireTime); + CPrintF( "m_fCloseFireTime = %g\n", m_fCloseFireTime); + CPrintF( "m_fStopDistance = %g\n", m_fStopDistance); + CPrintF( "m_fIgnoreRange = %g\n", m_fIgnoreRange); + CPrintF( "m_fLockOnEnemyTime = %g\n", m_fLockOnEnemyTime); + + CPrintF( "m_fMoveTime = %g\n", m_fMoveTime); + CPrintF( "m_vDesiredPosition (%g, %g, %g)\n", m_vDesiredPosition(1), m_vDesiredPosition(2), m_vDesiredPosition(3)); + + CTString strDestinationType = DestinationType_enum.NameForValue(INDEX(m_dtDestination)); + CPrintF( "m_dtDestination: %s\n", strDestinationType); + CPrintF( "m_penPathMarker %x\n", m_penPathMarker); + + CPrintF( "m_vPlayerSpotted (%g, %g, %g)\n", m_vPlayerSpotted(1), m_vPlayerSpotted(2), m_vPlayerSpotted(3)); + CPrintF( "m_fMoveFrequency = %g\n", m_fMoveFrequency); + CPrintF( "m_fMoveSpeed = %g\n", m_fMoveSpeed); + CPrintF( "m_aRotateSpeed = %g\n", m_aRotateSpeed); + CPrintF( "m_fLockStartTime = %g\n", m_fLockStartTime); + CPrintF( "m_fRangeLast = %g\n", m_fRangeLast); + CPrintF( "m_fShootTime = %g\n", m_fShootTime); + CPrintF( "m_fAttackRadius = %g\n", m_fAttackRadius); + CPrintF( "m_tmGiveUp = %g\n", m_tmGiveUp); + CPrintF( "m_fActivityRange = %g\n", m_fActivityRange); + + CTString strMarkerName = "Null ptr, no name"; + if( m_penMarker != NULL) + { + strMarkerName = m_penMarker->GetName(); + } + CPrintF( "m_penMarker %x, marker name: %s\n", m_penMarker, strMarkerName); + + CTString strMainMusicHolderName = "Null ptr, no name"; + if( m_penMainMusicHolder != NULL) + { + strMainMusicHolderName = m_penMainMusicHolder->GetName(); + } + CPrintF( "m_penMainMusicHolder %x, MainMusicHolder name: %s\n", m_penMainMusicHolder, strMainMusicHolderName); + CPrintF( "m_tmLastFussTime = %g\n", m_tmLastFussTime); + CPrintF( "m_iScore = %d\n", m_iScore); + CPrintF( "m_fMaxHealth = %g\n", m_fMaxHealth); + CPrintF( "m_bBoss = %d\n", m_bBoss); + CPrintF( "m_fSpiritStartTime = %g\n", m_fSpiritStartTime); + CPrintF( "m_tmSpraySpawned = %g\n", m_tmSpraySpawned); + CPrintF( "m_fSprayDamage = %g\n", m_fSprayDamage); + CPrintF( "m_fMaxDamageAmmount = %g\n", m_fMaxDamageAmmount ); + } + + vLightDirection = FLOAT3D(0.0f, 270.0f, 0.0f); + colAmbient = RGBToColor(32,32,32); + colLight = RGBToColor(255,235,145); + + return CMovableModelEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + //return CEnemyBase::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + }; + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + StartModelAnim(DEVIL_ANIM_WOUNDLOOP, 0); + return DEVIL_ANIM_WOUNDLOOP; + }; + + // death + INDEX AnimForDeath(void) { + StartModelAnim(DEVIL_ANIM_DEATH, 0); + return DEVIL_ANIM_DEATH; + }; + + void DeathNotify(void) { + StopFireBreathParticles(); + StopRegenerationParticles(); + }; + + // virtual anim functions + void StandingAnim(void) { + StartModelAnim(DEVIL_ANIM_IDLE, AOF_SMOOTHCHANGE|AOF_LOOPING|AOF_NORESTART); + }; + + void WalkingAnim(void) { + if( !m_bForMPIntro) + { + CModelObject &mo = *GetModelObject(); + INDEX iAnim = mo.GetAnim(); + if (iAnim==DEVIL_ANIM_WALK) + { + // do nothing + } else if (iAnim==DEVIL_ANIM_FROMIDLETOWALK) { + StartModelAnim(DEVIL_ANIM_WALK, AOF_LOOPING|AOF_SMOOTHCHANGE); + } else { + StartModelAnim(DEVIL_ANIM_FROMIDLETOWALK, AOF_SMOOTHCHANGE); + } + } + }; + void RunningAnim(void) { + WalkingAnim(); + }; + void RotatingAnim(void) { + WalkingAnim(); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + //PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D|SOF_VOLUMETRIC); + }; + + + // start fire laser + void StartFireLaser(void) { + //PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP); + PlayLightAnim(LIGHT_ANIM_FIRE, AOF_LOOPING|SOF_3D); + }; + + // fire one laser + void FireOneLaser(FLOAT fRatio, FLOAT fDeltaPitch) + { + PlayWeaponSound( SOUND_LASER); + FLOAT3D vWpnPipeRel = GetFireingPositionRelative(); + FLOAT3D vWpnPipeAbs = GetFireingPositionAbsolute(); + // calculate predicted position + FLOAT3D vTarget = m_penEnemy->GetPlacement().pl_PositionVector; + FLOAT3D vSpeedDst = ((CMovableEntity&) *m_penEnemy).en_vCurrentTranslationAbsolute*fRatio; + FLOAT fSpeedSrc = DEVIL_LASER_SPEED; + m_vDesiredPosition = CalculatePredictedPosition(vWpnPipeAbs, vTarget, fSpeedSrc, + vSpeedDst, GetPlacement().pl_PositionVector(2) ); + // shoot predicted propelled projectile + ShootPredictedProjectile(PRT_DEVIL_LASER, m_vDesiredPosition, vWpnPipeRel, ANGLE3D(0, fDeltaPitch, 0)); + //PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP); + PlayLightAnim(LIGHT_ANIM_FIRE, AOF_LOOPING); + }; + + // stop fire laser + void StopFireLaser(void) { + m_soSound.Stop(); + PlayLightAnim(LIGHT_ANIM_NONE, 0); + }; + + // start fire rocket + void StartFireRocket(void) { + //PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP); + PlayLightAnim(LIGHT_ANIM_FIRE, AOF_LOOPING); + }; + + void PlayWeaponSound( ULONG idSound) + { + CSoundObject &so = (&m_soWeapon0)[m_iNextChannel]; + m_iNextChannel = (m_iNextChannel+1)%5; + PlaySound(so, idSound, SOF_3D); + } + + // fire one rocket + void FireOneRocket(FLOAT fRatio) + { + PlayWeaponSound( SOUND_ROCKETLAUNCHER); + FLOAT3D vWpnPipeRel = GetFireingPositionRelative(); + FLOAT3D vWpnPipeAbs = GetFireingPositionAbsolute(); + // calculate predicted position + FLOAT3D vTarget = m_penEnemy->GetPlacement().pl_PositionVector; + FLOAT3D vSpeedDst = ((CMovableEntity&) *m_penEnemy).en_vCurrentTranslationAbsolute*fRatio; + FLOAT fSpeedSrc = DEVIL_ROCKET_SPEED; + m_vDesiredPosition = CalculatePredictedPosition(vWpnPipeAbs, vTarget, fSpeedSrc, + vSpeedDst, GetPlacement().pl_PositionVector(2) ); + // shoot predicted propelled projectile + ShootPredictedProjectile(PRT_DEVIL_ROCKET, m_vDesiredPosition, vWpnPipeRel, ANGLE3D(0, 0, 0)); + //PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP); + PlayLightAnim(LIGHT_ANIM_FIRE, AOF_LOOPING); + + //PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP); + PlayLightAnim(LIGHT_ANIM_FIRE, AOF_LOOPING); + }; + + // stop fire rocket + void StopFireRocket(void) { + m_soSound.Stop(); + PlayLightAnim(LIGHT_ANIM_NONE, 0); + }; + + void AddLowerWeapons(void) + { + // laser + AddAttachmentToModel(this, *GetModelObject(), DEVIL_ATTACHMENT_LASER, MODEL_LASER, TEXTURE_LASER, 0, 0, 0); + // projectile gun + AddAttachmentToModel(this, *GetModelObject(), DEVIL_ATTACHMENT_PROJECTILEGUN, MODEL_PROJECTILEGUN, TEXTURE_PROJECTILEGUN, 0, 0, 0); + GetModelObject()->StretchModel(FLOAT3D(SIZE, SIZE, SIZE)); + }; + + void AddUpperWeapons(void) + { + // rocket launcher + AddAttachmentToModel(this, *GetModelObject(), DEVIL_ATTACHMENT_ROCKETLAUNCHER, MODEL_ROCKETLAUNCHER, TEXTURE_ROCKETLAUNCHER, 0, 0, 0); + // electro gun + AddAttachmentToModel(this, *GetModelObject(), DEVIL_ATTACHMENT_ELETRICITYGUN, MODEL_ELECTRICITYGUN, TEXTURE_ELECTRICITYGUN, 0, 0, 0); + GetModelObject()->StretchModel(FLOAT3D(SIZE, SIZE, SIZE)); + }; + + void RemoveWeapons(void) + { + // remove all weapons + RemoveAttachmentFromModel(*GetModelObject(), DEVIL_ATTACHMENT_LASER); + RemoveAttachmentFromModel(*GetModelObject(), DEVIL_ATTACHMENT_PROJECTILEGUN); + RemoveAttachmentFromModel(*GetModelObject(), DEVIL_ATTACHMENT_ELETRICITYGUN); + RemoveAttachmentFromModel(*GetModelObject(), DEVIL_ATTACHMENT_ROCKETLAUNCHER); + } + + class CDevilMarker *GetAction(void) + { + CDevilMarker *penAction = (CDevilMarker *) (CEntity*) m_penAction; + ASSERT( penAction != NULL); + return penAction; + }; + +/************************************************************ + * PREDICTED PROJECTILE * + ************************************************************/ + void F_FirePredictedProjectile(void) + { + PlayWeaponSound( SOUND_LAVABOMB); + FLOAT3D vFireingRel = GetFireingPositionRelative(); + FLOAT3D vFireingAbs = GetFireingPositionAbsolute(); + + FLOAT3D vTarget = m_penEnemy->GetPlacement().pl_PositionVector; + FLOAT3D vSpeedDest = ((CMovableEntity&) *m_penEnemy).en_vCurrentTranslationAbsolute; + FLOAT fLaunchSpeed; + FLOAT fRelativeHdg; + + // obtain current gun orientation + CAttachmentModelObject &amo = *GetModelObject()->GetAttachmentModel(m_iAttID); + FLOAT fPitch = amo.amo_plRelative.pl_OrientationAngle(2); + + // calculate parameters for predicted angular launch curve + EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); + CalculateAngularLaunchParams( vFireingAbs, 0, vTarget, vSpeedDest, fPitch, fLaunchSpeed, fRelativeHdg); + + // target enemy body + FLOAT3D vShootTarget; + GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget); + // launch + CPlacement3D pl; + PrepareFreeFlyingProjectile(pl, vShootTarget, vFireingRel, ANGLE3D( fRelativeHdg, fPitch, 0)); + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_LAVAMAN_BIG_BOMB; + eLaunch.fSpeed = fLaunchSpeed; + penProjectile->Initialize(eLaunch); + } + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + if (ee.ee_slEvent==EVENTCODE_EDevilCommand) + { + EDevilCommand eDevilCommand = ((EDevilCommand &) ee); + if( eDevilCommand.dctType == DC_FORCE_ATTACK_RADIUS) + { + m_fAttackRadius = eDevilCommand.fAttackRadius; + m_vStartPosition = eDevilCommand.vCenterOfAttack; + } + if( eDevilCommand.dctType == DC_DECREASE_ATTACK_RADIUS) + { + if( m_fAttackRadius>21.0f) + { + m_fAttackRadius -= 20.0f; + } + } + } + + return CEnemyBase::HandleEvent(ee); + } + +procedures: +/************************************************************ + * TRY TO REACH DESTINATION * + ************************************************************/ + // move to given destination position + WalkTo(EVoid) + { + autocall WaitCurrentAnimEnd() EReturn; + WalkingAnim(); + m_vDesiredPosition = GetAction()->GetPlacement().pl_PositionVector; + // setup parameters + m_fMoveFrequency = 0.25f; + m_fMoveSpeed = 15.0f; + m_aRotateSpeed = 60.0f; + m_fMoveTime = _pTimer->CurrentTick() + CalcDistanceInPlaneToDestination()/m_fMoveSpeed + 5.0f; + // while not there and time not expired + while (CalcDistanceInPlaneToDestination()>m_fMoveSpeed*m_fMoveFrequency*4.0f && + m_fMoveTime>_pTimer->CurrentTick()) { + // every once in a while + wait (m_fMoveFrequency) { + on (EBegin) : { + // adjust direction and speed + ULONG ulFlags = SetDesiredMovement(); + MovementAnimation(ulFlags); + resume; + } + on (ETimer) : { stop; } + } + } + + StopMoving(); + // return to the caller + return EReturn(); + }; + +/************************************************************ + * CITY DESTROYING * + ************************************************************/ + DestroyCity() + { + m_soSound.Set3DParameters(1000.0f, 500.0f, 3.0f, 1.0f); + + while(TRUE) + { + if( GetAction()->m_datType == DAT_RISE) + { + autocall Rise() EReturn; + } + else if( GetAction()->m_datType == DAT_ROAR) + { + SelectRandomAnger(); + autocall Angry() EReturn; + } + else if( GetAction()->m_datType == DAT_SMASH) + { + autocall Smash() EReturn; + } + else if( GetAction()->m_datType == DAT_PUNCH) + { + autocall Punch() EReturn; + } + else if( GetAction()->m_datType == DAT_HIT_GROUND) + { + autocall HitGround() EReturn; + } + else if( GetAction()->m_datType == DAT_JUMP) + { + // do nothing, obsolete + } + else if( GetAction()->m_datType == DAT_WAIT) + { + autocall WaitCurrentAnimEnd() EReturn; + StartModelAnim(DEVIL_ANIM_IDLE, 0); + autowait(GetModelObject()->GetAnimLength(DEVIL_ANIM_IDLE)*GetAction()->m_iWaitIdles); + } + else if( GetAction()->m_datType == DAT_WALK) + { + autocall WalkTo() EReturn; + } + else if( GetAction()->m_datType == DAT_STOP_DESTROYING) + { + return EReturn(); + } + else if(TRUE) + { + StartModelAnim(DEVIL_ANIM_IDLE, 0); + autowait(GetModelObject()->GetAnimLength(DEVIL_ANIM_IDLE)); + } + // switch to next action + m_penAction = GetAction()->m_penTarget; + if( GetAction()->m_penTrigger != NULL) + { + GetAction()->m_penTrigger->SendEvent(ETrigger()); + } + } + }; + + WaitCurrentAnimEnd() + { + autowait(_pTimer->TickQuantum); + CModelObject &mo = *GetModelObject(); + FLOAT tmWait = mo.GetAnimLength( mo.ao_iCurrentAnim )-mo.GetPassedTime(); + if( tmWait > _pTimer->TickQuantum) + { + FLOAT fTimeToWait = tmWait-_pTimer->TickQuantum*2; + if( fTimeToWait>=_pTimer->TickQuantum) + { + autowait(fTimeToWait); + } + } + return EReturn(); + } + + WaitWalkToEnd() + { + if(GetModelObject()->GetAnim()==DEVIL_ANIM_WALK) + { + autocall WaitCurrentAnimEnd() EReturn; + StartModelAnim(DEVIL_ANIM_FROMWALKTOIDLE, AOF_SMOOTHCHANGE); + autowait( GetModelObject()->GetAnimLength(DEVIL_ANIM_FROMWALKTOIDLE)-0.1f); + } + autocall WaitCurrentAnimEnd() EReturn; + return EReturn(); + } + + WaitWalkOrIdleToEnd() + { + if(GetModelObject()->GetAnim()==DEVIL_ANIM_WALK) + { + autocall WaitCurrentAnimEnd() EReturn; + StartModelAnim(DEVIL_ANIM_FROMWALKTOIDLE, AOF_SMOOTHCHANGE); + autowait( GetModelObject()->GetAnimLength(DEVIL_ANIM_FROMWALKTOIDLE)-0.1f); + } + else if(GetModelObject()->GetAnim()==DEVIL_ANIM_FROMIDLETOWALK) + { + autocall WaitCurrentAnimEnd() EReturn; + StartModelAnim(DEVIL_ANIM_FROMWALKTOIDLE, AOF_SMOOTHCHANGE); + autowait( GetModelObject()->GetAnimLength(DEVIL_ANIM_FROMWALKTOIDLE)-0.1f); + } + else if(GetModelObject()->GetAnim()==DEVIL_ANIM_IDLE) + { + autocall WaitCurrentAnimEnd() EReturn; + } + return EReturn(); + } + + Rise() + { + autocall WaitCurrentAnimEnd() EReturn; + PlaySound(m_soSound, SOUND_GETUP, SOF_3D); + GetModelObject()->PlayAnim(DEVIL_ANIM_GETUP, 0); + return EReturn(); + } + + Celebrate() + { + autocall WaitWalkToEnd() EReturn; + + PlaySound(m_soSound, SOUND_CELEBRATE01, SOF_3D); + GetModelObject()->PlayAnim(DEVIL_ANIM_CELEBRATE01, AOF_SMOOTHCHANGE); + autowait( GetModelObject()->GetAnimLength(DEVIL_ANIM_CELEBRATE01)-0.1f); + return EReturn(); + } + + Angry() + { + autocall WaitWalkToEnd() EReturn; + + GetModelObject()->PlayAnim(m_iAngryAnim, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + PlaySound(m_soSound, m_iAngrySound, SOF_3D); + autowait( GetModelObject()->GetAnimLength(m_iAngryAnim)-0.1f); + return EReturn(); + } + + + SubBeamDamage1() + { + StopMoving(); + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + GetModelObject()->PlayAnim(DEVIL_ANIM_WOUNDSTART, AOF_SMOOTHCHANGE); + autowait( GetModelObject()->GetAnimLength(DEVIL_ANIM_WOUNDSTART)-0.1f); + GetModelObject()->PlayAnim(DEVIL_ANIM_WOUNDLOOP, AOF_LOOPING|AOF_SMOOTHCHANGE); + jump SubBeamDamage2(); + } + SubBeamDamage2() + { + while(TRUE) { + wait(0.1f) + { + on (EBegin) : { resume; } + on (EHitBySpaceShipBeam) : { + m_tmHitBySpaceShipBeam = _pTimer->CurrentTick(); + stop; + } + on (ETimer) : { jump SubBeamDamage3(); } + } + } + } + SubBeamDamage3() + { + GetModelObject()->PlayAnim(DEVIL_ANIM_WOUNDEND, AOF_SMOOTHCHANGE); + autowait( GetModelObject()->GetAnimLength(DEVIL_ANIM_WOUNDEND)-0.1f); + GetModelObject()->PlayAnim(DEVIL_ANIM_IDLE, AOF_LOOPING|AOF_SMOOTHCHANGE); + return EReturn(); + } + BeamDamage() + { + wait() + { + on (EBegin) : { call SubBeamDamage1(); } + on (EHitBySpaceShipBeam) : { + m_tmHitBySpaceShipBeam = _pTimer->CurrentTick(); + resume; + } + on (EReturn) : { stop; } + } + return EReturn(); + } + + Smash() + { + //autocall WaitCurrentAnimEnd() EReturn; + //autocall WaitWalkToEnd() EReturn; + + GetModelObject()->PlayAnim(DEVIL_ANIM_FROMWALKTOIDLE, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + + GetModelObject()->PlayAnim(DEVIL_ANIM_SMASH, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + + autowait(0.05f); + PlaySound(m_soSound, SOUND_SMASH, SOF_3D); + autowait(0.7f); + if( GetAction()->m_penToDestroy1 != NULL) + { + EBrushDestroyedByDevil ebdbd; + ebdbd.vDamageDir = FLOAT3D( -0.125f, 0.0f, -0.5f); + GetAction()->m_penToDestroy1->SendEvent(ebdbd); + } + autowait(2.8f-1.0f); + if( GetAction()->m_penToDestroy2 != NULL) + { + EBrushDestroyedByDevil ebdbd; + ebdbd.vDamageDir = FLOAT3D( -0.125f, 0.0f, -0.5f); + GetAction()->m_penToDestroy2->SendEvent(ebdbd); + } + return EReturn(); + } + + Punch() + { + //autocall WaitWalkToEnd() EReturn; + //autocall WaitCurrentAnimEnd() EReturn; + GetModelObject()->PlayAnim(DEVIL_ANIM_FROMWALKTOIDLE, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + + GetModelObject()->PlayAnim(DEVIL_ANIM_PUNCH, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + + autowait(0.05f); + PlaySound(m_soSound, SOUND_PUNCH, SOF_3D); + autowait(0.8f); + if( GetAction()->m_penToDestroy1 != NULL) + { + EBrushDestroyedByDevil ebdbd; + ebdbd.vDamageDir = FLOAT3D( -0.125f, 0.0f, -0.5f); + GetAction()->m_penToDestroy1->SendEvent(ebdbd); + } + autowait(2.8f-1.1f); + if( GetAction()->m_penToDestroy2 != NULL) + { + EBrushDestroyedByDevil ebdbd; + ebdbd.vDamageDir = FLOAT3D( 0.125f, 0.0f, -0.5f); + GetAction()->m_penToDestroy2->SendEvent(ebdbd); + } + + return EReturn(); + } + + HitGround() + { + autocall WaitWalkToEnd() EReturn; + + PlaySound(m_soSound, SOUND_ATTACKCLOSE, SOF_3D); + GetModelObject()->PlayAnim(DEVIL_ANIM_ATTACKCLOSE, AOF_SMOOTHCHANGE); + autowait(1.44f); + ShakeItBaby(_pTimer->CurrentTick(), 5.0f); + + CPlacement3D plObelisk = GetPlacement(); + // spawn spray spray + CEntity *penEffector = CreateEntity( plObelisk, CLASS_EFFECTOR); + // set spawn parameters + ESpawnEffector eSpawnEffector; + eSpawnEffector.tmLifeTime = 6.0f; + eSpawnEffector.fSize = 1.0f; + eSpawnEffector.eetType = ET_HIT_GROUND; + eSpawnEffector.vDamageDir = FLOAT3D( 0.0f, 2.0f, 0.0f); + // initialize spray + penEffector->Initialize( eSpawnEffector); + + return EReturn(); + } + + GrabLowerWeapons() + { + autocall WaitWalkToEnd() EReturn; + GetModelObject()->PlayAnim(DEVIL_ANIM_GRABWEAPONS01, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + PlaySound(m_soSound, SOUND_DRAW_LOWER_WEAPONS, SOF_3D); + autowait(0.84f); + AddLowerWeapons(); + WalkingAnim(); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + return EReturn(); + } + + GrabUpperWeapons() + { + autocall WaitWalkToEnd() EReturn; + GetModelObject()->PlayAnim(DEVIL_ANIM_GRABWEAPONS02, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + PlaySound(m_soSound, SOUND_DRAW_UPPER_WEAPONS, SOF_3D); + autowait(0.84f); + AddUpperWeapons(); + m_bHasUpperWeapons = TRUE; + WalkingAnim(); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + return EReturn(); + } + + GrabBothWeapons() + { + autocall WaitWalkToEnd() EReturn; + GetModelObject()->PlayAnim(DEVIL_ANIM_GRABWEAPONS01, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + PlaySound(m_soGrabLowerWeapons, SOUND_DRAW_LOWER_WEAPONS, SOF_3D); + autowait(0.84f); + AddLowerWeapons(); + GetModelObject()->PlayAnim(DEVIL_ANIM_GRABWEAPONS02, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + PlaySound(m_soGrabUpperWeapons, SOUND_DRAW_UPPER_WEAPONS, SOF_3D); + autowait(0.84f); + AddUpperWeapons(); + m_bHasUpperWeapons = TRUE; + WalkingAnim(); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + return EReturn(); + } + + PreMainLoop(EVoid) : CEnemyBase::PreMainLoop + { + m_soSound.Set3DParameters(1000.0f, 500.0f, 2.0f, 1.0f); + m_soGrabLowerWeapons.Set3DParameters(1000.0f, 500.0f, 2.0f, 1.0f); + m_soGrabUpperWeapons.Set3DParameters(1000.0f, 500.0f, 2.0f, 1.0f); + m_soJumpIntoPyramid.Set3DParameters(1000.0f, 500.0f, 2.0f, 1.0f); + m_soLeft.Set3DParameters(1000.0f, 500.0f, 2.0f, 1.0f); + m_soRight.Set3DParameters(1000.0f, 500.0f, 2.0f, 1.0f); + m_soWeapon0.Set3DParameters(1000.0f, 500.0f, 1.0f, 1.0f); + m_soWeapon1.Set3DParameters(1000.0f, 500.0f, 1.0f, 1.0f); + m_soWeapon2.Set3DParameters(1000.0f, 500.0f, 1.0f, 1.0f); + m_soWeapon3.Set3DParameters(1000.0f, 500.0f, 1.0f, 1.0f); + m_soWeapon4.Set3DParameters(1000.0f, 500.0f, 1.0f, 1.0f); + + TurnOnPhysics(); + + if (m_penEnemy==NULL) + { + // get some player for trigger source if any is existing + CEntity *penEnemy = FixupCausedToPlayer(this, m_penEnemy, /*bWarning=*/FALSE); + if (penEnemy!=m_penEnemy) { + SetTargetSoft(penEnemy); + } + } + + return EReturn(); + } + +/************************************************************ + * PROCEDURES WHEN HARMED * + ************************************************************/ + // Play wound animation + BeWounded(EDamage eDamage) : CEnemyBase::BeWounded + { + StopMoving(); + // determine damage anim and play the wounding + autowait(GetModelObject()->GetAnimLength(AnimForDamage(eDamage.fAmount))); + return EReturn(); + }; + +/************************************************************ + * C L O S E A T T A C K * + ************************************************************/ + Hit(EVoid) : CEnemyBase::Hit { + autocall WaitCurrentAnimEnd() EReturn; + StartModelAnim(DEVIL_ANIM_ATTACKCLOSE, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + PlaySound(m_soSound, SOUND_ATTACKCLOSE, SOF_3D); + autowait(1.4f); + ShakeItBaby(_pTimer->CurrentTick(), 5.0f); + if( CalcDist(m_penEnemy) < m_fCloseDistance) + { + InflictDirectDamage(m_penEnemy, this, DMT_IMPACT, 1000.0f, + m_penEnemy->GetPlacement().pl_PositionVector, FLOAT3D(0,1,0)); + } + InflictHoofDamage( DEVIL_HIT_HOOF_OFFSET); + + autowait(GetModelObject()->GetAnimLength(DEVIL_ANIM_ATTACKCLOSE-1.4f)-_pTimer->TickQuantum); + return EReturn(); + }; + +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + // initial preparation + InitializeAttack(EVoid) : CEnemyBase::InitializeAttack { + jump CEnemyBase::InitializeAttack(); + }; + + Fire(EVoid) : CEnemyBase::Fire + { + m_iToFireProjectiles = 0; + m_fAttackFireTime = 10.0f; + m_fPauseStretcher = 1.0f; + + if( m_dapAttackPower==DAP_MEDIUM_POWER_ATTACK && + (_pTimer->CurrentTick()-m_fLastWalkTime) > 6.0f) + { + m_fAttackFireTime = 6.0f; + m_fLastWalkTime = _pTimer->CurrentTick()+6.0f; + return; + } + + switch( m_dapAttackPower) + { + case DAP_PLAYER_HUNT: + if( _pTimer->CurrentTick()-m_tmLastAngry > 10.0f) + { + m_fAttackFireTime = 7.5+FRnd()*5; + m_tmLastAngry = _pTimer->CurrentTick(); + SelectRandomAnger(); + jump Angry(); + } + return; + break; + case DAP_LOW_POWER_ATTACK: + m_iToFireProjectiles = 2; + m_fAttackFireTime = 5.0f; + m_fPauseStretcher = 1.0f; + break; + case DAP_MEDIUM_POWER_ATTACK: + m_iToFireProjectiles = 3; + m_fAttackFireTime = 0.1f; + m_fPauseStretcher = 0.5f; + break; + case DAP_FULL_POWER_ATTACK: + m_iToFireProjectiles = 4; + m_fAttackFireTime = 0.1f; + m_fPauseStretcher = 0.1f; + break; + } + + INDEX iRnd = IRnd()%5; + if( !m_bHasUpperWeapons) + { + iRnd = IRnd()%3; + } + + /*iRnd = Clamp(INDEX(tmp_af[0]), INDEX(0), INDEX(4));*/ + switch(iRnd) + { + case 0: + jump FirePredictedProjectile(); + break; + case 1: + jump FireLaser(); + break; + case 2: + jump FireGuidedProjectile(); + break; + case 3: + jump FireRocketLauncher(); + break; + case 4: + jump FireElectricityGun(); + break; + } + }; + + // call this to lock on player for some time - set m_fLockOnEnemyTime before calling + DevilLockOnEnemy(EVoid) + { + // stop moving + StopMoving(); + // play animation for locking + ChargeAnim(); + // wait charge time + m_fLockStartTime = _pTimer->CurrentTick(); + while (m_fLockStartTime+GetProp(m_fLockOnEnemyTime) > _pTimer->CurrentTick()) { + // each tick + m_fMoveFrequency = 0.05f; + wait (m_fMoveFrequency) { + on (ETimer) : { stop; } + on (EBegin) : { + m_vDesiredPosition = PlayerDestinationPos(); + // if not heading towards enemy + if (!IsInPlaneFrustum(m_penEnemy, CosFast(30.0f))) { + m_fLockStartTime = -10000.0f; + stop; + } + +/* if (!IsInPlaneFrustum(m_penEnemy, CosFast(5.0f))) { + m_fMoveSpeed = 0.0f; + m_aRotateSpeed = GetLockRotationSpeed(); + // if heading towards enemy + } else { + m_fMoveSpeed = 0.0f; + m_aRotateSpeed = 0.0f; + }*/ + // adjust direction and speed + //ULONG ulFlags = SetDesiredMovement(); + //MovementAnimation(ulFlags); + resume; + } + } + } + // stop rotating + StopRotating(); + + // return to caller + return EReturn(); + }; + + AdjustWeaponForFire() + { + FLOAT3D vRelWeapon = GetWeaponPositionRelative(); + FLOAT3D vAbsWeapon = GetPlacement().pl_PositionVector + vRelWeapon*GetRotationMatrix(); + + m_fFireTime = _pTimer->CurrentTick()+m_fAdjustWeaponTime; + FLOAT3D vEnemy = m_penEnemy->GetPlacement().pl_PositionVector; + FLOAT3D vDir = (vEnemy-vAbsWeapon).Normalize(); + ANGLE3D aAngles; + DirectionVectorToAngles(vDir, aAngles); + CPlacement3D plRelPl = CPlacement3D(FLOAT3D(0,0,0),aAngles); + plRelPl.AbsoluteToRelative(GetPlacement()); + FLOAT fWantedHdg = plRelPl.pl_OrientationAngle(1); + FLOAT fWantedPitch = plRelPl.pl_OrientationAngle(2); + + // adjust angle of projectile gun + if( m_iAttID == DEVIL_ATTACHMENT_PROJECTILEGUN) + { + FLOAT3D vShooting = GetPlacement().pl_PositionVector; + FLOAT3D vTarget = m_penEnemy->GetPlacement().pl_PositionVector; + FLOAT fDistanceFactor = 1.0f-ClampUp( (vShooting-vTarget).Length()/250.0f, 1.0f); + fWantedPitch = 20-fDistanceFactor*50.0f; + } + + CAttachmentModelObject &amo = *GetModelObject()->GetAttachmentModel(m_iAttID); + m_fDeltaWeaponHdg = (fWantedHdg -amo.amo_plRelative.pl_OrientationAngle(1))/(m_fAdjustWeaponTime/_pTimer->TickQuantum); + m_fDeltaWeaponPitch = (fWantedPitch-amo.amo_plRelative.pl_OrientationAngle(2))/(m_fAdjustWeaponTime/_pTimer->TickQuantum); + while (m_fFireTime > _pTimer->CurrentTick()) + { + wait(_pTimer->TickQuantum) + { + on (EBegin) : + { + CAttachmentModelObject &amo = *GetModelObject()->GetAttachmentModel(m_iAttID); + amo.amo_plRelative.pl_OrientationAngle(1) += m_fDeltaWeaponHdg; + amo.amo_plRelative.pl_OrientationAngle(2) += m_fDeltaWeaponPitch; + resume; + } + on (ETimer) : { stop; } + } + } + return EReturn(); + } + + StraightenUpWeapon() + { + FLOAT fAdjustWeaponTime = 0.25f; + m_fFireTime = _pTimer->CurrentTick()+fAdjustWeaponTime; + + CAttachmentModelObject &amo = *GetModelObject()->GetAttachmentModel(m_iAttID); + m_fDeltaWeaponHdg = amo.amo_plRelative.pl_OrientationAngle(1)/(fAdjustWeaponTime/_pTimer->TickQuantum); + m_fDeltaWeaponPitch = amo.amo_plRelative.pl_OrientationAngle(2)/(fAdjustWeaponTime/_pTimer->TickQuantum); + while (m_fFireTime > _pTimer->CurrentTick()) + { + wait(_pTimer->TickQuantum) + { + on (EBegin) : + { + CAttachmentModelObject &amo = *GetModelObject()->GetAttachmentModel(m_iAttID); + amo.amo_plRelative.pl_OrientationAngle(1) -= m_fDeltaWeaponHdg; + amo.amo_plRelative.pl_OrientationAngle(2) -= m_fDeltaWeaponPitch; + resume; + } + on (ETimer) : { stop; } + } + } + return EReturn(); + } + + FireLaser(EVoid) + { + autocall WaitWalkOrIdleToEnd() EReturn; + + // to fire + StartModelAnim(DEVIL_ANIM_FROMIDLETOATTACK01, AOF_SMOOTHCHANGE); + autowait( GetModelObject()->GetAnimLength(DEVIL_ANIM_FROMIDLETOATTACK01)-0.1f); + StartModelAnim(DEVIL_ANIM_ATTACK01, AOF_SMOOTHCHANGE|AOF_LOOPING); + + m_iAttID = DEVIL_ATTACHMENT_LASER; + m_fAdjustWeaponTime = 0.25f; + autocall AdjustWeaponForFire() EReturn; + + // fire lasers + StartFireLaser(); + m_iFiredProjectiles = 0; + while (m_iFiredProjectilesGetAnimLength(DEVIL_ANIM_FROMIDLETOATTACK02)-0.1f); + StartModelAnim(DEVIL_ANIM_ATTACK02, AOF_SMOOTHCHANGE|AOF_LOOPING); + + m_iAttID = DEVIL_ATTACHMENT_ROCKETLAUNCHER; + m_fAdjustWeaponTime = 0.5f; + autocall AdjustWeaponForFire() EReturn; + + // fire rockets + StartFireRocket(); + m_iFiredProjectiles = 0; + while (m_iFiredProjectilesGetAnimLength(DEVIL_ANIM_FROMIDLETOATTACK01)-0.1f); + StartModelAnim(DEVIL_ANIM_ATTACK01, AOF_SMOOTHCHANGE|AOF_LOOPING); + + m_iAttID = DEVIL_ATTACHMENT_PROJECTILEGUN; + m_fAdjustWeaponTime = 0.5f; + autocall AdjustWeaponForFire() EReturn; + + // start fireing predicted magic projectile + m_iFiredProjectiles = 0; + while (m_iFiredProjectilesGetAnimLength(DEVIL_ANIM_FROMATTACK01TOIDLE)-0.1f); + //StartModelAnim(DEVIL_ANIM_IDLE, AOF_SMOOTHCHANGE|AOF_LOOPING); + + //autowait(0.25f*m_fPauseStretcher); + + MaybeSwitchToAnotherPlayer(); + + // shoot completed + return EReturn(); + } + + FireElectricityGun(EVoid) + { + autocall WaitWalkOrIdleToEnd() EReturn; + + // to fire + StartModelAnim(DEVIL_ANIM_FROMIDLETOATTACK02, AOF_SMOOTHCHANGE); + autowait( GetModelObject()->GetAnimLength(DEVIL_ANIM_FROMIDLETOATTACK02)-0.1f); + StartModelAnim(DEVIL_ANIM_ATTACK02, AOF_SMOOTHCHANGE|AOF_LOOPING); + + m_iAttID = DEVIL_ATTACHMENT_ELETRICITYGUN; + m_fAdjustWeaponTime = 0.5f; + //autocall AdjustWeaponForFire() EReturn; + + // start fireing electricity + m_iFiredProjectiles = 0; + while (m_iFiredProjectilesGetEntityInfo()); + GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, m_vElectricityTarget); + + // give some time so player can move away from electricity beam + autowait(0.4f); + + // fire electricity beam + m_bRenderElectricity = TRUE; + m_tmTemp = _pTimer->CurrentTick(); + m_tmNextFXTime = m_tmTemp-_pTimer->TickQuantum; + PlayWeaponSound( SOUND_GHOSTBUSTER); + while( _pTimer->CurrentTick() < m_tmTemp+0.75f) + { + wait(_pTimer->TickQuantum) { + on (EBegin): { + // correct electricity beam target + FLOAT3D vNewTarget; + EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); + GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vNewTarget); + FLOAT3D vDiff = vNewTarget-m_vElectricityTarget; + // if we have valid length + if( vDiff.Length() > 1.0f) + { + // calculate adjustment + m_vElectricityTarget = m_vElectricityTarget+vDiff.Normalize()*10.0f*_pTimer->TickQuantum; + } + + // cast ray + CCastRay crRay( this, m_vElectricitySource, m_vElectricityTarget); + crRay.cr_bHitTranslucentPortals = FALSE; + crRay.cr_bPhysical = FALSE; + crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX; + GetWorld()->CastRay(crRay); + // if entity is hit + if( crRay.cr_penHit != NULL) + { + // apply damage + InflictDirectDamage( crRay.cr_penHit, this, DMT_BULLET, 50.0f*_pTimer->TickQuantum/0.5f, + FLOAT3D(0, 0, 0), (m_vElectricitySource-m_vElectricityTarget).Normalize()); + } + + if( _pTimer->CurrentTick()>m_tmNextFXTime) + { + m_tmNextFXTime = _pTimer->CurrentTick()+0.125f+FRnd()*0.125f; + CPlacement3D plElectricityTarget = CPlacement3D( m_vElectricityTarget, ANGLE3D(0,0,0)); + CEntity *penEffector = CreateEntity( plElectricityTarget, CLASS_EFFECTOR); + // set spawn parameters + ESpawnEffector eSpawnEffector; + eSpawnEffector.tmLifeTime = 6.0f; + eSpawnEffector.fSize = 0.025f; + eSpawnEffector.eetType = ET_HIT_GROUND; + eSpawnEffector.vDamageDir = FLOAT3D( 0.0f, 2.0f, 0.0f); + // initialize spray + penEffector->Initialize( eSpawnEffector); + } + + resume; + }; + on (ETimer): { stop; }; + } + } + m_soSound.Stop(); + m_bRenderElectricity = FALSE; + + autowait( 0.8f-m_fAdjustWeaponTime); + m_iFiredProjectiles++; + if (!IsInFrustum(m_penEnemy, CosFast(30.0f))) { + m_iFiredProjectiles = 10000; + } + } + autocall StraightenUpWeapon() EReturn; + + // from idle + StartModelAnim(DEVIL_ANIM_FROMATTACK02TOIDLE, AOF_SMOOTHCHANGE); + //autowait( GetModelObject()->GetAnimLength(DEVIL_ANIM_FROMATTACK02TOIDLE)-0.1f); + //StartModelAnim(DEVIL_ANIM_IDLE, AOF_SMOOTHCHANGE|AOF_LOOPING); + + MaybeSwitchToAnotherPlayer(); + + // shoot completed + return EReturn(); + } + + FireGuidedProjectile(EVoid) + { + autocall WaitWalkOrIdleToEnd() EReturn; + + StartModelAnim(DEVIL_ANIM_ATTACKBREATHSTART, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + PlaySound(m_soLeft, SOUND_ATTACK_BREATH_START, SOF_3D); + + StartModelAnim(DEVIL_ANIM_ATTACKBREATH, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + PlaySound(m_soRight, SOUND_ATTACK_BREATH_LOOP, SOF_LOOP|SOF_3D); + + // start fireing predicted magic projectile + m_iFiredProjectiles = 0; + m_tmFireBreathStart = _pTimer->CurrentTick(); + m_tmFireBreathStop = UpperLimit(0.0f); + // calculate breath source and target positions + const FLOATmatrix3D &m = GetRotationMatrix(); + m_vFireBreathSource = GetPlacement().pl_PositionVector+MAGIC_PROJECTILE_EXIT*m; + m_vFireBreathTarget = m_penEnemy->GetPlacement().pl_PositionVector-FLOAT3D(0,20.0f,0); + while (m_iFiredProjectilesPlayAnim(DEVIL_ANIM_CLIMB, 0); + PlaySound(m_soJumpIntoPyramid, SOUND_CLIMB, SOF_3D); + autowait(7.0f); + + // turn it arround + m_tmTemp = _pTimer->CurrentTick(); + while( _pTimer->CurrentTick() < m_tmTemp+0.7f) + { + wait(_pTimer->TickQuantum) { + on (EBegin): { resume; }; + on (ETimer): { stop; }; + otherwise(): { resume; }; + } + CPlacement3D plCurrent = GetPlacement(); + FLOAT aDelta = -35.0f/0.7f*_pTimer->TickQuantum; + plCurrent.pl_OrientationAngle+=FLOAT3D(aDelta,0,0); + SetPlacement(plCurrent); + } + + ShakeItFarBaby(_pTimer->CurrentTick(), 1.5f); + autowait(GetModelObject()->GetAnimLength(DEVIL_ANIM_CLIMB)-7.335f-_pTimer->TickQuantum); + + SelectRandomAnger(); + GetModelObject()->PlayAnim(m_iAngryAnim, 0); + PlaySound(m_soSound, m_iAngrySound, SOF_3D); + autowait( GetModelObject()->GetAnimLength(m_iAngryAnim)-0.1f); + + StopMoving(); + StopRotating(); + TurnOnPhysics(); + autocall GrabBothWeapons() EReturn; + + m_dsDevilState = DS_PYRAMID_FIGHT; + m_dapAttackPower = DAP_MEDIUM_POWER_ATTACK; + m_fAttackRadius = 1e6f; + m_fAttackRunSpeed = 8.0f; + + return EReturn(); + } + + TeleportIntoPyramid(EVoid) + { + // remove weapons + RemoveWeapons(); + SetTargetNone(); + Teleport(m_plTeleport, FALSE); + StopMoving(); + StopRotating(); + + SelectRandomAnger(); + GetModelObject()->PlayAnim(m_iAngryAnim, 0); + PlaySound(m_soSound, m_iAngrySound, SOF_3D); + autowait( GetModelObject()->GetAnimLength(m_iAngryAnim)-0.1f); + + TurnOnPhysics(); + autocall GrabBothWeapons() EReturn; + + m_dsDevilState = DS_PYRAMID_FIGHT; + m_dapAttackPower = DAP_MEDIUM_POWER_ATTACK; + m_fAttackRadius = 1e6f; + m_fAttackRunSpeed = 8.0f; + + return EReturn(); + } + + RegenerationImpulse(EVoid) + { + m_dsPreRegenerationDevilState = m_dsDevilState; + m_dsDevilState = DS_REGENERATION_IMPULSE; + GetModelObject()->PlayAnim(DEVIL_ANIM_HEAL, 0); + PlaySound(m_soSound, SOUND_HEAL, SOF_3D); + + StopFireBreathParticles(); + m_tmRegenerationStart = _pTimer->CurrentTick(); + m_tmRegenerationStop = m_tmRegenerationStart+TM_HEALTH_IMPULSE-1.5f/*Regeneration particle life time*/; + // apply health impulse + m_tmTemp = _pTimer->CurrentTick(); + while( _pTimer->CurrentTick() < m_tmTemp+TM_HEALTH_IMPULSE) + { + wait(_pTimer->TickQuantum) { + on (EBegin): { resume; }; + on (ETimer): { stop; }; + otherwise(): { resume; }; + } + SetHealth(GetHealth()+HEALTH_IMPULSE*_pTimer->TickQuantum/TM_HEALTH_IMPULSE); + } + m_dsDevilState = m_dsPreRegenerationDevilState; + + return EReturn(); + } + + StopAttack(EVoid) : CEnemyBase::StopAttack { + if(m_penEnemy==NULL) + { + autocall Celebrate() EReturn; + } + + jump CEnemyBase::StopAttack(); + }; + + ContinueInMainLoop(EVoid) + { + SwitchToModel(); + // continue behavior in base class + if( !m_bWasOnceInMainLoop) + { + m_bWasOnceInMainLoop = TRUE; + jump CEnemyBase::MainLoop(); + } + else + { + // get some player for trigger source if any is existing + CEntity *penEnemy = FixupCausedToPlayer(this, m_penEnemy, /*bWarning=*/FALSE); + if (penEnemy!=m_penEnemy) { + SetTargetSoft(penEnemy); + } + + jump CEnemyBase::StandardBehavior(); + } + } + + MPIntro(EVoid) + { + m_dsDevilState=DS_PYRAMID_FIGHT; + jump ContinueInMainLoop(); + } + +/************************************************************ + * D E A T H * + ************************************************************/ + Death(EVoid) : CEnemyBase::Death { + SetFlags(GetFlags()&~ENF_ALIVE); + StopFireBreathParticles(); + StopRegenerationParticles(); + // stop moving + StopMoving(); + DeathSound(); // death sound + // set physic flags + SetCollisionFlags(ECF_MODEL); + // start death anim + AnimForDeath(); + autowait(4.66f); + ShakeItFarBaby(_pTimer->CurrentTick(), 5.0f); + autowait(GetModelObject()->GetAnimLength(DEVIL_ANIM_DEATH)-4.66f); + m_tmDeathTime = _pTimer->CurrentTick(); + + CWorldSettingsController *pwsc = GetWSC(this); + if (pwsc!=NULL) + { + pwsc->m_colGlade=C_WHITE; + pwsc->m_tmGlaringStarted = _pTimer->CurrentTick()+1.5f; + pwsc->m_tmGlaringEnded = pwsc->m_tmGlaringStarted+1.0f, + pwsc->m_fGlaringFadeInRatio = 0.2f; + pwsc->m_fGlaringFadeOutRatio = 0.7f; + } + autowait(1.5f); + PlaySound(m_soLeft, SOUND_DISAPPEAR, SOF_3D|SOF_VOLUMETRIC); + autowait(0.25f); + SwitchToEditorModel(); + + PlaySound(m_soRight, SOUND_DEATHPARTICLES, SOF_3D); + return EEnd(); + }; + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + m_sptType = SPT_NONE; + // declare yourself as a model + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_WALKING&~EPF_TRANSLATEDBYGRAVITY); + SetCollisionFlags(((ECBI_MODEL)<StretchModel(FLOAT3D(SIZE, SIZE, SIZE)); + ModelChangeNotify(); + + StandingAnim(); + + // setup moving speed + m_fWalkSpeed = 10.0f; + m_aWalkRotateSpeed = AngleDeg(90.0f); + m_fAttackRunSpeed = 8.0f; + m_aAttackRotateSpeed = AngleDeg(90.0f); + m_fCloseRunSpeed = 8.0f; + m_aCloseRotateSpeed = AngleDeg(90.0f); + // setup attack distances + m_fAttackDistance = 1e24f; + m_fCloseDistance = 50.0f; + m_fStopDistance = 10.0f; + m_fAttackFireTime = 10.0f; + m_fCloseFireTime = 5.0f; + m_fIgnoreRange = UpperLimit(0.0f); + en_fAcceleration = en_fDeceleration = 50.0f; + m_fLockOnEnemyTime = 0.05f; + m_fPauseStretcher = 1.0f; + m_bWasOnceInMainLoop = FALSE; + + // setup light source + SetupLightSource(); + // set light animation if available + try { + m_aoLightAnimation.SetData_t(CTFILENAME("Animations\\BasicEffects.ani")); + } catch (char *strError) { + WarningMessage(TRANS("Cannot load Animations\\BasicEffects.ani: %s"), strError); + } + PlayLightAnim(LIGHT_ANIM_NONE, 0); + + autowait(0.1f); + + m_iScore = 0; + + if( !m_bForMPIntro) + { + StartModelAnim(DEVIL_ANIM_POSEDOWN, 0); + wait() { + on (EBegin) : { resume; } + on (ETrigger) : { stop; } + } + } + else + { + StartModelAnim(DEVIL_ANIM_DEFAULT, 0); + } + + SwitchToModel(); + + // set initial state + m_dsDevilState = DS_NOT_EXISTING; + + wait() + { + on (EBegin) : { + if( cht_bDebugFinalBoss) + { + CPrintF("Main loop, event: Begin\n"); + } + if( !m_bForMPIntro) + { + if(m_dsDevilState == DS_NOT_EXISTING) + { + m_dsDevilState = DS_DESTROYING_CITY; + call DestroyCity(); + } + } + resume; + } + on (ETrigger) : + { + if( cht_bDebugFinalBoss) + { + CPrintF("Main loop, event: Trigger\n"); + } + resume; + } + on (EDevilCommand eDevilCommand) : + { + if( cht_bDebugFinalBoss) + { + CTString strDevilCommand = DevilCommandType_enum.NameForValue(INDEX(eDevilCommand.dctType)); + CPrintF("Main loop, event: Devil command: %s\n", strDevilCommand); + } + + if( eDevilCommand.dctType == DC_GRAB_LOWER_WEAPONS) + { + m_dapAttackPower = DAP_LOW_POWER_ATTACK; + m_dsDevilState = DS_ENEMY; + call GrabLowerWeapons(); + } + // force given action marker + else if( eDevilCommand.dctType == DC_FORCE_ACTION) + { + m_penAction = eDevilCommand.penForcedAction; + call DestroyCity(); + } + else if( eDevilCommand.dctType == DC_STOP_MOVING) + { + m_vStartPosition = GetPlacement().pl_PositionVector; + m_fAttackRadius = 0.0f; + } + else if( eDevilCommand.dctType == DC_STOP_ATTACK) + { + SetTargetNone(); + } + else if( eDevilCommand.dctType == DC_JUMP_INTO_PYRAMID) + { + GetModelObject()->PlayAnim( DEVIL_ANIM_IDLE, 0); + m_plTeleport = eDevilCommand.penForcedAction->GetPlacement(); + m_dsDevilState = DS_JUMPING_INTO_PYRAMID; + call JumpIntoPyramid(); + } + else if( eDevilCommand.dctType == DC_TELEPORT_INTO_PYRAMID) + { + GetModelObject()->PlayAnim( DEVIL_ANIM_IDLE, 0); + m_plTeleport = eDevilCommand.penForcedAction->GetPlacement(); + m_dsDevilState = DS_JUMPING_INTO_PYRAMID; + call TeleportIntoPyramid(); + } + resume; + } + on (ERegenerationImpuls) : + { + if( cht_bDebugFinalBoss) + { + CPrintF("Main loop, event: Regeneration impulse\n"); + } + m_bRenderElectricity = FALSE; + call RegenerationImpulse(); + resume; + } + on (EHitBySpaceShipBeam) : + { + if( cht_bDebugFinalBoss) + { + CPrintF("Main loop, event: Hit by space ship beam\n"); + } + m_bRenderElectricity = FALSE; + m_tmHitBySpaceShipBeam = _pTimer->CurrentTick(); + call BeamDamage(); + resume; + } + // if dead + on (EDeath eDeath) : { + if( !(GetFlags()&ENF_ALIVE)) + { + resume; + } + + if( cht_bDebugFinalBoss) + { + CPrintF("Main loop, event: Death\n"); + } + // die + m_bRenderElectricity = FALSE; + jump CEnemyBase::Die(eDeath); + } + on( EEnvironmentStart): + { + call MPIntro(); + resume; + } + on (EReturn) : + { + if( cht_bDebugFinalBoss) + { + CPrintF("Main loop, event: Return\n"); + } + if( m_dsDevilState==DS_DESTROYING_CITY) + { + m_soSound.Set3DParameters(1000.0f, 500.0f, 2.0f, 1.0f); + m_dsDevilState = DS_ENEMY; + if( m_dapAttackPower == DAP_NOT_ATTACKING) + { + m_dapAttackPower = DAP_PLAYER_HUNT; + } + } + call ContinueInMainLoop(); + resume; + } + } + }; +}; diff --git a/Sources/EntitiesMP/Devil.h b/Sources/EntitiesMP/Devil.h new file mode 100644 index 0000000..fe23ac4 --- /dev/null +++ b/Sources/EntitiesMP/Devil.h @@ -0,0 +1,728 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Devil_INCLUDED +#define _EntitiesMP_Devil_INCLUDED 1 +#include +#include +#include +#include +#define EVENTCODE_EBrushDestroyedByDevil 0x014c0000 +class DECL_DLL EBrushDestroyedByDevil : public CEntityEvent { +public: +EBrushDestroyedByDevil(); +CEntityEvent *MakeCopy(void); +FLOAT3D vDamageDir; +}; +DECL_DLL inline void ClearToDefault(EBrushDestroyedByDevil &e) { e = EBrushDestroyedByDevil(); } ; +#define EVENTCODE_ERegenerationImpuls 0x014c0001 +class DECL_DLL ERegenerationImpuls : public CEntityEvent { +public: +ERegenerationImpuls(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(ERegenerationImpuls &e) { e = ERegenerationImpuls(); } ; +extern DECL_DLL CEntityPropertyEnumType DevilCommandType_enum; +enum DevilCommandType { + DC_GRAB_LOWER_WEAPONS = 0, + DC_FORCE_ACTION = 1, + DC_STOP_MOVING = 2, + DC_STOP_ATTACK = 3, + DC_JUMP_INTO_PYRAMID = 4, + DC_FORCE_ATTACK_RADIUS = 5, + DC_DECREASE_ATTACK_RADIUS = 6, + DC_TELEPORT_INTO_PYRAMID = 7, +}; +DECL_DLL inline void ClearToDefault(DevilCommandType &e) { e = (DevilCommandType)0; } ; +#define EVENTCODE_EDevilCommand 0x014c0002 +class DECL_DLL EDevilCommand : public CEntityEvent { +public: +EDevilCommand(); +CEntityEvent *MakeCopy(void); +enum DevilCommandType dctType; +CEntityPointer penForcedAction; +FLOAT fAttackRadius; +FLOAT3D vCenterOfAttack; +}; +DECL_DLL inline void ClearToDefault(EDevilCommand &e) { e = EDevilCommand(); } ; +extern DECL_DLL CEntityPropertyEnumType DevilState_enum; +enum DevilState { + DS_NOT_EXISTING = 0, + DS_DESTROYING_CITY = 1, + DS_ENEMY = 2, + DS_JUMPING_INTO_PYRAMID = 3, + DS_PYRAMID_FIGHT = 4, + DS_REGENERATION_IMPULSE = 5, +}; +DECL_DLL inline void ClearToDefault(DevilState &e) { e = (DevilState)0; } ; +extern DECL_DLL CEntityPropertyEnumType DevilAttackPower_enum; +enum DevilAttackPower { + DAP_PLAYER_HUNT = 1, + DAP_LOW_POWER_ATTACK = 2, + DAP_MEDIUM_POWER_ATTACK = 3, + DAP_FULL_POWER_ATTACK = 4, + DAP_NOT_ATTACKING = 5, +}; +DECL_DLL inline void ClearToDefault(DevilAttackPower &e) { e = (DevilAttackPower)0; } ; +extern "C" DECL_DLL CDLLEntityClass CDevil_DLLClass; +class CDevil : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + INDEX m_iAttID; + FLOAT m_fDeltaWeaponPitch; + FLOAT m_fDeltaWeaponHdg; + FLOAT m_fFireTime; + CAnimObject m_aoLightAnimation; + CEntityPointer m_penAction; + INDEX m_iFiredProjectiles; + INDEX m_iToFireProjectiles; + FLOAT m_fPauseStretcher; + FLOAT m_tmLastPause; + enum DevilState m_dsDevilState; + FLOAT m_tmLastAngry; + CPlacement3D m_plTeleport; + FLOAT m_tmTemp; + enum DevilState m_dsLastDevilState; + enum DevilAttackPower m_dapAttackPower; + enum DevilAttackPower m_dapLastAttackPower; + BOOL m_bHasUpperWeapons; + FLOAT3D m_vElectricitySource; + FLOAT3D m_vElectricityTarget; + BOOL m_bRenderElectricity; + FLOAT m_fAdjustWeaponTime; + BOOL m_bWasOnceInMainLoop; + FLOAT m_tmHitBySpaceShipBeam; + CSoundObject m_soLeft; + CSoundObject m_soRight; + FLOAT m_fLastWalkTime; + FLOAT m_tmFireBreathStart; + FLOAT m_tmFireBreathStop; + FLOAT3D m_vFireBreathSource; + FLOAT3D m_vFireBreathTarget; + FLOAT m_tmRegenerationStart; + FLOAT m_tmRegenerationStop; + FLOAT m_tmNextFXTime; + INDEX m_iNextChannel; + CSoundObject m_soWeapon0; + CSoundObject m_soWeapon1; + CSoundObject m_soWeapon2; + CSoundObject m_soWeapon3; + CSoundObject m_soWeapon4; + INDEX m_iAngryAnim; + INDEX m_iAngrySound; + FLOAT m_tmDeathTime; + INDEX m_iLastCurrentAnim; + INDEX m_iLastScheduledAnim; + enum DevilState m_dsPreRegenerationDevilState; + CSoundObject m_soClimb; + CSoundObject m_soGrabLowerWeapons; + CSoundObject m_soGrabUpperWeapons; + CSoundObject m_soJumpIntoPyramid; + BOOL m_bForMPIntro; +CEntity * penBullet; +CLightSource m_lsLightSource; + +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void Precache(void); + +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void Read_t(CTStream * istr); + +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +CLightSource * GetLightSource(void); + +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void SetupLightSource(void); + +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void PlayLightAnim(INDEX iAnim,ULONG ulFlags); + +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void * GetEntityInfo(void); + +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BOOL ForcesCannonballToExplode(void); + +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void SetSpeedsToDesiredPosition(const FLOAT3D & vPosDelta,FLOAT fPosDist,BOOL bGoingToPlayer); + +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT GetCrushHealth(void); + +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void SelectRandomAnger(void); + +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +virtual FLOAT GetLockRotationSpeed(void); + +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void ShakeItBaby(FLOAT tmShaketime,FLOAT fPower); + +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void ShakeItFarBaby(FLOAT tmShaketime,FLOAT fPower); + +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void InflictHoofDamage(FLOAT3D vOffset); + +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void ApplyFootQuake(void); + +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void StopFireBreathParticles(void); + +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void StopRegenerationParticles(void); + +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void TurnOnPhysics(void); + +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void TurnOffPhysics(void); + +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void RenderParticles(void); + +#line 586 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D GetWeaponPositionRelative(void); + +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D GetWeaponPositionAbsolute(void); + +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D GetFireingPositionRelative(void); + +#line 648 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT3D GetFireingPositionAbsolute(void); + +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void ApplyTickRegeneration(void); + +#line 704 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void PostMoving(void); + +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 740 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 934 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +INDEX AnimForDeath(void); + +#line 939 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void DeathNotify(void); + +#line 945 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void StandingAnim(void); + +#line 949 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void WalkingAnim(void); + +#line 964 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void RunningAnim(void); + +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void RotatingAnim(void); + +#line 972 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void IdleSound(void); + +#line 975 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void SightSound(void); + +#line 978 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void WoundSound(void); + +#line 981 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void DeathSound(void); + +#line 987 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void StartFireLaser(void); + +#line 993 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void FireOneLaser(FLOAT fRatio,FLOAT fDeltaPitch); + +#line 1011 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void StopFireLaser(void); + +#line 1017 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void StartFireRocket(void); + +#line 1022 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void PlayWeaponSound(ULONG idSound); + +#line 1030 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void FireOneRocket(FLOAT fRatio); + +#line 1051 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void StopFireRocket(void); + +#line 1056 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void AddLowerWeapons(void); + +#line 1065 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void AddUpperWeapons(void); + +#line 1074 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void RemoveWeapons(void); + +#line 1083 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +class CDevilMarker * GetAction(void); + +#line 1093 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +void F_FirePredictedProjectile(void); + +#line 1127 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CDevil_WalkTo 0x014c0003 + BOOL +#line 1154 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WalkTo(const CEntityEvent &__eeInput); + BOOL H0x014c0004_WalkTo_01(const CEntityEvent &__eeInput); + BOOL H0x014c0005_WalkTo_02(const CEntityEvent &__eeInput); + BOOL H0x014c0006_WalkTo_03(const CEntityEvent &__eeInput); + BOOL H0x014c0007_WalkTo_04(const CEntityEvent &__eeInput); + BOOL H0x014c0008_WalkTo_05(const CEntityEvent &__eeInput); + BOOL H0x014c0009_WalkTo_06(const CEntityEvent &__eeInput); +#define STATE_CDevil_DestroyCity 0x014c000a + BOOL +#line 1187 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +DestroyCity(const CEntityEvent &__eeInput); + BOOL H0x014c000b_DestroyCity_01(const CEntityEvent &__eeInput); + BOOL H0x014c000c_DestroyCity_02(const CEntityEvent &__eeInput); + BOOL H0x014c000d_DestroyCity_03(const CEntityEvent &__eeInput); + BOOL H0x014c000e_DestroyCity_04(const CEntityEvent &__eeInput); + BOOL H0x014c000f_DestroyCity_05(const CEntityEvent &__eeInput); + BOOL H0x014c0010_DestroyCity_06(const CEntityEvent &__eeInput); + BOOL H0x014c0011_DestroyCity_07(const CEntityEvent &__eeInput); + BOOL H0x014c0012_DestroyCity_08(const CEntityEvent &__eeInput); + BOOL H0x014c0013_DestroyCity_09(const CEntityEvent &__eeInput); + BOOL H0x014c0014_DestroyCity_10(const CEntityEvent &__eeInput); + BOOL H0x014c0015_DestroyCity_11(const CEntityEvent &__eeInput); + BOOL H0x014c0016_DestroyCity_12(const CEntityEvent &__eeInput); + BOOL H0x014c0017_DestroyCity_13(const CEntityEvent &__eeInput); + BOOL H0x014c0018_DestroyCity_14(const CEntityEvent &__eeInput); + BOOL H0x014c0019_DestroyCity_15(const CEntityEvent &__eeInput); + BOOL H0x014c001a_DestroyCity_16(const CEntityEvent &__eeInput); + BOOL H0x014c001b_DestroyCity_17(const CEntityEvent &__eeInput); + BOOL H0x014c001c_DestroyCity_18(const CEntityEvent &__eeInput); + BOOL H0x014c001d_DestroyCity_19(const CEntityEvent &__eeInput); + BOOL H0x014c001e_DestroyCity_20(const CEntityEvent &__eeInput); + BOOL H0x014c001f_DestroyCity_21(const CEntityEvent &__eeInput); + BOOL H0x014c0020_DestroyCity_22(const CEntityEvent &__eeInput); + BOOL H0x014c0021_DestroyCity_23(const CEntityEvent &__eeInput); + BOOL H0x014c0022_DestroyCity_24(const CEntityEvent &__eeInput); + BOOL H0x014c0023_DestroyCity_25(const CEntityEvent &__eeInput); + BOOL H0x014c0024_DestroyCity_26(const CEntityEvent &__eeInput); + BOOL H0x014c0025_DestroyCity_27(const CEntityEvent &__eeInput); + BOOL H0x014c0026_DestroyCity_28(const CEntityEvent &__eeInput); + BOOL H0x014c0027_DestroyCity_29(const CEntityEvent &__eeInput); + BOOL H0x014c0028_DestroyCity_30(const CEntityEvent &__eeInput); + BOOL H0x014c0029_DestroyCity_31(const CEntityEvent &__eeInput); + BOOL H0x014c002a_DestroyCity_32(const CEntityEvent &__eeInput); + BOOL H0x014c002b_DestroyCity_33(const CEntityEvent &__eeInput); + BOOL H0x014c002c_DestroyCity_34(const CEntityEvent &__eeInput); + BOOL H0x014c002d_DestroyCity_35(const CEntityEvent &__eeInput); + BOOL H0x014c002e_DestroyCity_36(const CEntityEvent &__eeInput); + BOOL H0x014c002f_DestroyCity_37(const CEntityEvent &__eeInput); + BOOL H0x014c0030_DestroyCity_38(const CEntityEvent &__eeInput); + BOOL H0x014c0031_DestroyCity_39(const CEntityEvent &__eeInput); +#define STATE_CDevil_WaitCurrentAnimEnd 0x014c0032 + BOOL +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WaitCurrentAnimEnd(const CEntityEvent &__eeInput); + BOOL H0x014c0033_WaitCurrentAnimEnd_01(const CEntityEvent &__eeInput); + BOOL H0x014c0034_WaitCurrentAnimEnd_02(const CEntityEvent &__eeInput); + BOOL H0x014c0035_WaitCurrentAnimEnd_03(const CEntityEvent &__eeInput); + BOOL H0x014c0036_WaitCurrentAnimEnd_04(const CEntityEvent &__eeInput); + BOOL H0x014c0037_WaitCurrentAnimEnd_05(const CEntityEvent &__eeInput); + BOOL H0x014c0038_WaitCurrentAnimEnd_06(const CEntityEvent &__eeInput); +#define STATE_CDevil_WaitWalkToEnd 0x014c0039 + BOOL +#line 1262 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WaitWalkToEnd(const CEntityEvent &__eeInput); + BOOL H0x014c003a_WaitWalkToEnd_01(const CEntityEvent &__eeInput); + BOOL H0x014c003b_WaitWalkToEnd_02(const CEntityEvent &__eeInput); + BOOL H0x014c003c_WaitWalkToEnd_03(const CEntityEvent &__eeInput); + BOOL H0x014c003d_WaitWalkToEnd_04(const CEntityEvent &__eeInput); + BOOL H0x014c003e_WaitWalkToEnd_05(const CEntityEvent &__eeInput); + BOOL H0x014c003f_WaitWalkToEnd_06(const CEntityEvent &__eeInput); + BOOL H0x014c0040_WaitWalkToEnd_07(const CEntityEvent &__eeInput); +#define STATE_CDevil_WaitWalkOrIdleToEnd 0x014c0041 + BOOL +#line 1274 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WaitWalkOrIdleToEnd(const CEntityEvent &__eeInput); + BOOL H0x014c0042_WaitWalkOrIdleToEnd_01(const CEntityEvent &__eeInput); + BOOL H0x014c0043_WaitWalkOrIdleToEnd_02(const CEntityEvent &__eeInput); + BOOL H0x014c0044_WaitWalkOrIdleToEnd_03(const CEntityEvent &__eeInput); + BOOL H0x014c0045_WaitWalkOrIdleToEnd_04(const CEntityEvent &__eeInput); + BOOL H0x014c0046_WaitWalkOrIdleToEnd_05(const CEntityEvent &__eeInput); + BOOL H0x014c0047_WaitWalkOrIdleToEnd_06(const CEntityEvent &__eeInput); + BOOL H0x014c0048_WaitWalkOrIdleToEnd_07(const CEntityEvent &__eeInput); + BOOL H0x014c0049_WaitWalkOrIdleToEnd_08(const CEntityEvent &__eeInput); + BOOL H0x014c004a_WaitWalkOrIdleToEnd_09(const CEntityEvent &__eeInput); + BOOL H0x014c004b_WaitWalkOrIdleToEnd_10(const CEntityEvent &__eeInput); + BOOL H0x014c004c_WaitWalkOrIdleToEnd_11(const CEntityEvent &__eeInput); + BOOL H0x014c004d_WaitWalkOrIdleToEnd_12(const CEntityEvent &__eeInput); + BOOL H0x014c004e_WaitWalkOrIdleToEnd_13(const CEntityEvent &__eeInput); + BOOL H0x014c004f_WaitWalkOrIdleToEnd_14(const CEntityEvent &__eeInput); + BOOL H0x014c0050_WaitWalkOrIdleToEnd_15(const CEntityEvent &__eeInput); +#define STATE_CDevil_Rise 0x014c0051 + BOOL +#line 1295 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Rise(const CEntityEvent &__eeInput); + BOOL H0x014c0052_Rise_01(const CEntityEvent &__eeInput); + BOOL H0x014c0053_Rise_02(const CEntityEvent &__eeInput); +#define STATE_CDevil_Celebrate 0x014c0054 + BOOL +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Celebrate(const CEntityEvent &__eeInput); + BOOL H0x014c0055_Celebrate_01(const CEntityEvent &__eeInput); + BOOL H0x014c0056_Celebrate_02(const CEntityEvent &__eeInput); + BOOL H0x014c0057_Celebrate_03(const CEntityEvent &__eeInput); + BOOL H0x014c0058_Celebrate_04(const CEntityEvent &__eeInput); +#define STATE_CDevil_Angry 0x014c0059 + BOOL +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Angry(const CEntityEvent &__eeInput); + BOOL H0x014c005a_Angry_01(const CEntityEvent &__eeInput); + BOOL H0x014c005b_Angry_02(const CEntityEvent &__eeInput); + BOOL H0x014c005c_Angry_03(const CEntityEvent &__eeInput); + BOOL H0x014c005d_Angry_04(const CEntityEvent &__eeInput); + BOOL H0x014c005e_Angry_05(const CEntityEvent &__eeInput); + BOOL H0x014c005f_Angry_06(const CEntityEvent &__eeInput); +#define STATE_CDevil_SubBeamDamage1 0x014c0060 + BOOL +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SubBeamDamage1(const CEntityEvent &__eeInput); + BOOL H0x014c0061_SubBeamDamage1_01(const CEntityEvent &__eeInput); + BOOL H0x014c0062_SubBeamDamage1_02(const CEntityEvent &__eeInput); +#define STATE_CDevil_SubBeamDamage2 0x014c0063 + BOOL +#line 1334 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SubBeamDamage2(const CEntityEvent &__eeInput); + BOOL H0x014c0064_SubBeamDamage2_01(const CEntityEvent &__eeInput); + BOOL H0x014c0065_SubBeamDamage2_02(const CEntityEvent &__eeInput); + BOOL H0x014c0066_SubBeamDamage2_03(const CEntityEvent &__eeInput); + BOOL H0x014c0067_SubBeamDamage2_04(const CEntityEvent &__eeInput); +#define STATE_CDevil_SubBeamDamage3 0x014c0068 + BOOL +#line 1348 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SubBeamDamage3(const CEntityEvent &__eeInput); + BOOL H0x014c0069_SubBeamDamage3_01(const CEntityEvent &__eeInput); + BOOL H0x014c006a_SubBeamDamage3_02(const CEntityEvent &__eeInput); +#define STATE_CDevil_BeamDamage 0x014c006b + BOOL +#line 1355 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BeamDamage(const CEntityEvent &__eeInput); + BOOL H0x014c006c_BeamDamage_01(const CEntityEvent &__eeInput); + BOOL H0x014c006d_BeamDamage_02(const CEntityEvent &__eeInput); +#define STATE_CDevil_Smash 0x014c006e + BOOL +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Smash(const CEntityEvent &__eeInput); + BOOL H0x014c006f_Smash_01(const CEntityEvent &__eeInput); + BOOL H0x014c0070_Smash_02(const CEntityEvent &__eeInput); + BOOL H0x014c0071_Smash_03(const CEntityEvent &__eeInput); + BOOL H0x014c0072_Smash_04(const CEntityEvent &__eeInput); + BOOL H0x014c0073_Smash_05(const CEntityEvent &__eeInput); + BOOL H0x014c0074_Smash_06(const CEntityEvent &__eeInput); + BOOL H0x014c0075_Smash_07(const CEntityEvent &__eeInput); + BOOL H0x014c0076_Smash_08(const CEntityEvent &__eeInput); + BOOL H0x014c0077_Smash_09(const CEntityEvent &__eeInput); + BOOL H0x014c0078_Smash_10(const CEntityEvent &__eeInput); +#define STATE_CDevil_Punch 0x014c0079 + BOOL +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Punch(const CEntityEvent &__eeInput); + BOOL H0x014c007a_Punch_01(const CEntityEvent &__eeInput); + BOOL H0x014c007b_Punch_02(const CEntityEvent &__eeInput); + BOOL H0x014c007c_Punch_03(const CEntityEvent &__eeInput); + BOOL H0x014c007d_Punch_04(const CEntityEvent &__eeInput); + BOOL H0x014c007e_Punch_05(const CEntityEvent &__eeInput); + BOOL H0x014c007f_Punch_06(const CEntityEvent &__eeInput); + BOOL H0x014c0080_Punch_07(const CEntityEvent &__eeInput); + BOOL H0x014c0081_Punch_08(const CEntityEvent &__eeInput); + BOOL H0x014c0082_Punch_09(const CEntityEvent &__eeInput); + BOOL H0x014c0083_Punch_10(const CEntityEvent &__eeInput); +#define STATE_CDevil_HitGround 0x014c0084 + BOOL +#line 1429 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +HitGround(const CEntityEvent &__eeInput); + BOOL H0x014c0085_HitGround_01(const CEntityEvent &__eeInput); + BOOL H0x014c0086_HitGround_02(const CEntityEvent &__eeInput); + BOOL H0x014c0087_HitGround_03(const CEntityEvent &__eeInput); + BOOL H0x014c0088_HitGround_04(const CEntityEvent &__eeInput); +#define STATE_CDevil_GrabLowerWeapons 0x014c0089 + BOOL +#line 1453 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GrabLowerWeapons(const CEntityEvent &__eeInput); + BOOL H0x014c008a_GrabLowerWeapons_01(const CEntityEvent &__eeInput); + BOOL H0x014c008b_GrabLowerWeapons_02(const CEntityEvent &__eeInput); + BOOL H0x014c008c_GrabLowerWeapons_03(const CEntityEvent &__eeInput); + BOOL H0x014c008d_GrabLowerWeapons_04(const CEntityEvent &__eeInput); + BOOL H0x014c008e_GrabLowerWeapons_05(const CEntityEvent &__eeInput); + BOOL H0x014c008f_GrabLowerWeapons_06(const CEntityEvent &__eeInput); + BOOL H0x014c0090_GrabLowerWeapons_07(const CEntityEvent &__eeInput); + BOOL H0x014c0091_GrabLowerWeapons_08(const CEntityEvent &__eeInput); +#define STATE_CDevil_GrabUpperWeapons 0x014c0092 + BOOL +#line 1466 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GrabUpperWeapons(const CEntityEvent &__eeInput); + BOOL H0x014c0093_GrabUpperWeapons_01(const CEntityEvent &__eeInput); + BOOL H0x014c0094_GrabUpperWeapons_02(const CEntityEvent &__eeInput); + BOOL H0x014c0095_GrabUpperWeapons_03(const CEntityEvent &__eeInput); + BOOL H0x014c0096_GrabUpperWeapons_04(const CEntityEvent &__eeInput); + BOOL H0x014c0097_GrabUpperWeapons_05(const CEntityEvent &__eeInput); + BOOL H0x014c0098_GrabUpperWeapons_06(const CEntityEvent &__eeInput); + BOOL H0x014c0099_GrabUpperWeapons_07(const CEntityEvent &__eeInput); + BOOL H0x014c009a_GrabUpperWeapons_08(const CEntityEvent &__eeInput); +#define STATE_CDevil_GrabBothWeapons 0x014c009b + BOOL +#line 1480 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GrabBothWeapons(const CEntityEvent &__eeInput); + BOOL H0x014c009c_GrabBothWeapons_01(const CEntityEvent &__eeInput); + BOOL H0x014c009d_GrabBothWeapons_02(const CEntityEvent &__eeInput); + BOOL H0x014c009e_GrabBothWeapons_03(const CEntityEvent &__eeInput); + BOOL H0x014c009f_GrabBothWeapons_04(const CEntityEvent &__eeInput); + BOOL H0x014c00a0_GrabBothWeapons_05(const CEntityEvent &__eeInput); + BOOL H0x014c00a1_GrabBothWeapons_06(const CEntityEvent &__eeInput); + BOOL H0x014c00a2_GrabBothWeapons_07(const CEntityEvent &__eeInput); + BOOL H0x014c00a3_GrabBothWeapons_08(const CEntityEvent &__eeInput); + BOOL H0x014c00a4_GrabBothWeapons_09(const CEntityEvent &__eeInput); + BOOL H0x014c00a5_GrabBothWeapons_10(const CEntityEvent &__eeInput); + BOOL H0x014c00a6_GrabBothWeapons_11(const CEntityEvent &__eeInput); + BOOL H0x014c00a7_GrabBothWeapons_12(const CEntityEvent &__eeInput); +#define STATE_CDevil_PreMainLoop 0x014c00a8 + BOOL +#line 1499 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PreMainLoop(const CEntityEvent &__eeInput); +#define STATE_CDevil_BeWounded 0x014c00a9 + BOOL +#line 1531 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BeWounded(const CEntityEvent &__eeInput); + BOOL H0x014c00aa_BeWounded_01(const CEntityEvent &__eeInput); + BOOL H0x014c00ab_BeWounded_02(const CEntityEvent &__eeInput); +#define STATE_CDevil_Hit 0x014c00ac + BOOL +#line 1542 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Hit(const CEntityEvent &__eeInput); + BOOL H0x014c00ad_Hit_01(const CEntityEvent &__eeInput); + BOOL H0x014c00ae_Hit_02(const CEntityEvent &__eeInput); + BOOL H0x014c00af_Hit_03(const CEntityEvent &__eeInput); + BOOL H0x014c00b0_Hit_04(const CEntityEvent &__eeInput); + BOOL H0x014c00b1_Hit_05(const CEntityEvent &__eeInput); + BOOL H0x014c00b2_Hit_06(const CEntityEvent &__eeInput); + BOOL H0x014c00b3_Hit_07(const CEntityEvent &__eeInput); + BOOL H0x014c00b4_Hit_08(const CEntityEvent &__eeInput); +#define STATE_CDevil_InitializeAttack 0x014c00b5 + BOOL +#line 1564 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +InitializeAttack(const CEntityEvent &__eeInput); +#define STATE_CDevil_Fire 0x014c00b6 + BOOL +#line 1568 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Fire(const CEntityEvent &__eeInput); +#define STATE_CDevil_DevilLockOnEnemy 0x014c00b7 + BOOL +#line 1639 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +DevilLockOnEnemy(const CEntityEvent &__eeInput); + BOOL H0x014c00b8_DevilLockOnEnemy_01(const CEntityEvent &__eeInput); + BOOL H0x014c00b9_DevilLockOnEnemy_02(const CEntityEvent &__eeInput); + BOOL H0x014c00ba_DevilLockOnEnemy_03(const CEntityEvent &__eeInput); + BOOL H0x014c00bb_DevilLockOnEnemy_04(const CEntityEvent &__eeInput); +#define STATE_CDevil_AdjustWeaponForFire 0x014c00bc + BOOL +#line 1682 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AdjustWeaponForFire(const CEntityEvent &__eeInput); + BOOL H0x014c00bd_AdjustWeaponForFire_01(const CEntityEvent &__eeInput); + BOOL H0x014c00be_AdjustWeaponForFire_02(const CEntityEvent &__eeInput); + BOOL H0x014c00bf_AdjustWeaponForFire_03(const CEntityEvent &__eeInput); + BOOL H0x014c00c0_AdjustWeaponForFire_04(const CEntityEvent &__eeInput); +#define STATE_CDevil_StraightenUpWeapon 0x014c00c1 + BOOL +#line 1726 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StraightenUpWeapon(const CEntityEvent &__eeInput); + BOOL H0x014c00c2_StraightenUpWeapon_01(const CEntityEvent &__eeInput); + BOOL H0x014c00c3_StraightenUpWeapon_02(const CEntityEvent &__eeInput); + BOOL H0x014c00c4_StraightenUpWeapon_03(const CEntityEvent &__eeInput); + BOOL H0x014c00c5_StraightenUpWeapon_04(const CEntityEvent &__eeInput); +#define STATE_CDevil_FireLaser 0x014c00c6 + BOOL +#line 1751 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireLaser(const CEntityEvent &__eeInput); + BOOL H0x014c00c7_FireLaser_01(const CEntityEvent &__eeInput); + BOOL H0x014c00c8_FireLaser_02(const CEntityEvent &__eeInput); + BOOL H0x014c00c9_FireLaser_03(const CEntityEvent &__eeInput); + BOOL H0x014c00ca_FireLaser_04(const CEntityEvent &__eeInput); + BOOL H0x014c00cb_FireLaser_05(const CEntityEvent &__eeInput); + BOOL H0x014c00cc_FireLaser_06(const CEntityEvent &__eeInput); + BOOL H0x014c00cd_FireLaser_07(const CEntityEvent &__eeInput); + BOOL H0x014c00ce_FireLaser_08(const CEntityEvent &__eeInput); + BOOL H0x014c00cf_FireLaser_09(const CEntityEvent &__eeInput); + BOOL H0x014c00d0_FireLaser_10(const CEntityEvent &__eeInput); + BOOL H0x014c00d1_FireLaser_11(const CEntityEvent &__eeInput); + BOOL H0x014c00d2_FireLaser_12(const CEntityEvent &__eeInput); + BOOL H0x014c00d3_FireLaser_13(const CEntityEvent &__eeInput); + BOOL H0x014c00d4_FireLaser_14(const CEntityEvent &__eeInput); +#define STATE_CDevil_FireRocketLauncher 0x014c00d5 + BOOL +#line 1798 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireRocketLauncher(const CEntityEvent &__eeInput); + BOOL H0x014c00d6_FireRocketLauncher_01(const CEntityEvent &__eeInput); + BOOL H0x014c00d7_FireRocketLauncher_02(const CEntityEvent &__eeInput); + BOOL H0x014c00d8_FireRocketLauncher_03(const CEntityEvent &__eeInput); + BOOL H0x014c00d9_FireRocketLauncher_04(const CEntityEvent &__eeInput); + BOOL H0x014c00da_FireRocketLauncher_05(const CEntityEvent &__eeInput); + BOOL H0x014c00db_FireRocketLauncher_06(const CEntityEvent &__eeInput); + BOOL H0x014c00dc_FireRocketLauncher_07(const CEntityEvent &__eeInput); + BOOL H0x014c00dd_FireRocketLauncher_08(const CEntityEvent &__eeInput); + BOOL H0x014c00de_FireRocketLauncher_09(const CEntityEvent &__eeInput); + BOOL H0x014c00df_FireRocketLauncher_10(const CEntityEvent &__eeInput); + BOOL H0x014c00e0_FireRocketLauncher_11(const CEntityEvent &__eeInput); + BOOL H0x014c00e1_FireRocketLauncher_12(const CEntityEvent &__eeInput); + BOOL H0x014c00e2_FireRocketLauncher_13(const CEntityEvent &__eeInput); + BOOL H0x014c00e3_FireRocketLauncher_14(const CEntityEvent &__eeInput); +#define STATE_CDevil_FirePredictedProjectile 0x014c00e4 + BOOL +#line 1841 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FirePredictedProjectile(const CEntityEvent &__eeInput); + BOOL H0x014c00e5_FirePredictedProjectile_01(const CEntityEvent &__eeInput); + BOOL H0x014c00e6_FirePredictedProjectile_02(const CEntityEvent &__eeInput); + BOOL H0x014c00e7_FirePredictedProjectile_03(const CEntityEvent &__eeInput); + BOOL H0x014c00e8_FirePredictedProjectile_04(const CEntityEvent &__eeInput); + BOOL H0x014c00e9_FirePredictedProjectile_05(const CEntityEvent &__eeInput); + BOOL H0x014c00ea_FirePredictedProjectile_06(const CEntityEvent &__eeInput); + BOOL H0x014c00eb_FirePredictedProjectile_07(const CEntityEvent &__eeInput); + BOOL H0x014c00ec_FirePredictedProjectile_08(const CEntityEvent &__eeInput); + BOOL H0x014c00ed_FirePredictedProjectile_09(const CEntityEvent &__eeInput); + BOOL H0x014c00ee_FirePredictedProjectile_10(const CEntityEvent &__eeInput); + BOOL H0x014c00ef_FirePredictedProjectile_11(const CEntityEvent &__eeInput); + BOOL H0x014c00f0_FirePredictedProjectile_12(const CEntityEvent &__eeInput); + BOOL H0x014c00f1_FirePredictedProjectile_13(const CEntityEvent &__eeInput); + BOOL H0x014c00f2_FirePredictedProjectile_14(const CEntityEvent &__eeInput); +#define STATE_CDevil_FireElectricityGun 0x014c00f3 + BOOL +#line 1882 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireElectricityGun(const CEntityEvent &__eeInput); + BOOL H0x014c00f4_FireElectricityGun_01(const CEntityEvent &__eeInput); + BOOL H0x014c00f5_FireElectricityGun_02(const CEntityEvent &__eeInput); + BOOL H0x014c00f6_FireElectricityGun_03(const CEntityEvent &__eeInput); + BOOL H0x014c00f7_FireElectricityGun_04(const CEntityEvent &__eeInput); + BOOL H0x014c00f8_FireElectricityGun_05(const CEntityEvent &__eeInput); + BOOL H0x014c00f9_FireElectricityGun_06(const CEntityEvent &__eeInput); + BOOL H0x014c00fa_FireElectricityGun_07(const CEntityEvent &__eeInput); + BOOL H0x014c00fb_FireElectricityGun_08(const CEntityEvent &__eeInput); + BOOL H0x014c00fc_FireElectricityGun_09(const CEntityEvent &__eeInput); + BOOL H0x014c00fd_FireElectricityGun_10(const CEntityEvent &__eeInput); + BOOL H0x014c00fe_FireElectricityGun_11(const CEntityEvent &__eeInput); + BOOL H0x014c00ff_FireElectricityGun_12(const CEntityEvent &__eeInput); + BOOL H0x014c0100_FireElectricityGun_13(const CEntityEvent &__eeInput); + BOOL H0x014c0101_FireElectricityGun_14(const CEntityEvent &__eeInput); + BOOL H0x014c0102_FireElectricityGun_15(const CEntityEvent &__eeInput); + BOOL H0x014c0103_FireElectricityGun_16(const CEntityEvent &__eeInput); + BOOL H0x014c0104_FireElectricityGun_17(const CEntityEvent &__eeInput); + BOOL H0x014c0105_FireElectricityGun_18(const CEntityEvent &__eeInput); +#define STATE_CDevil_FireGuidedProjectile 0x014c0106 + BOOL +#line 1990 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireGuidedProjectile(const CEntityEvent &__eeInput); + BOOL H0x014c0107_FireGuidedProjectile_01(const CEntityEvent &__eeInput); + BOOL H0x014c0108_FireGuidedProjectile_02(const CEntityEvent &__eeInput); + BOOL H0x014c0109_FireGuidedProjectile_03(const CEntityEvent &__eeInput); + BOOL H0x014c010a_FireGuidedProjectile_04(const CEntityEvent &__eeInput); + BOOL H0x014c010b_FireGuidedProjectile_05(const CEntityEvent &__eeInput); + BOOL H0x014c010c_FireGuidedProjectile_06(const CEntityEvent &__eeInput); + BOOL H0x014c010d_FireGuidedProjectile_07(const CEntityEvent &__eeInput); + BOOL H0x014c010e_FireGuidedProjectile_08(const CEntityEvent &__eeInput); + BOOL H0x014c010f_FireGuidedProjectile_09(const CEntityEvent &__eeInput); + BOOL H0x014c0110_FireGuidedProjectile_10(const CEntityEvent &__eeInput); + BOOL H0x014c0111_FireGuidedProjectile_11(const CEntityEvent &__eeInput); + BOOL H0x014c0112_FireGuidedProjectile_12(const CEntityEvent &__eeInput); + BOOL H0x014c0113_FireGuidedProjectile_13(const CEntityEvent &__eeInput); + BOOL H0x014c0114_FireGuidedProjectile_14(const CEntityEvent &__eeInput); +#define STATE_CDevil_JumpIntoPyramid 0x014c0115 + BOOL +#line 2036 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +JumpIntoPyramid(const CEntityEvent &__eeInput); + BOOL H0x014c0116_JumpIntoPyramid_01(const CEntityEvent &__eeInput); + BOOL H0x014c0117_JumpIntoPyramid_02(const CEntityEvent &__eeInput); + BOOL H0x014c0118_JumpIntoPyramid_03(const CEntityEvent &__eeInput); + BOOL H0x014c0119_JumpIntoPyramid_04(const CEntityEvent &__eeInput); + BOOL H0x014c011a_JumpIntoPyramid_05(const CEntityEvent &__eeInput); + BOOL H0x014c011b_JumpIntoPyramid_06(const CEntityEvent &__eeInput); + BOOL H0x014c011c_JumpIntoPyramid_07(const CEntityEvent &__eeInput); + BOOL H0x014c011d_JumpIntoPyramid_08(const CEntityEvent &__eeInput); + BOOL H0x014c011e_JumpIntoPyramid_09(const CEntityEvent &__eeInput); + BOOL H0x014c011f_JumpIntoPyramid_10(const CEntityEvent &__eeInput); + BOOL H0x014c0120_JumpIntoPyramid_11(const CEntityEvent &__eeInput); + BOOL H0x014c0121_JumpIntoPyramid_12(const CEntityEvent &__eeInput); +#define STATE_CDevil_TeleportIntoPyramid 0x014c0122 + BOOL +#line 2086 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +TeleportIntoPyramid(const CEntityEvent &__eeInput); + BOOL H0x014c0123_TeleportIntoPyramid_01(const CEntityEvent &__eeInput); + BOOL H0x014c0124_TeleportIntoPyramid_02(const CEntityEvent &__eeInput); + BOOL H0x014c0125_TeleportIntoPyramid_03(const CEntityEvent &__eeInput); + BOOL H0x014c0126_TeleportIntoPyramid_04(const CEntityEvent &__eeInput); +#define STATE_CDevil_RegenerationImpulse 0x014c0127 + BOOL +#line 2111 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +RegenerationImpulse(const CEntityEvent &__eeInput); + BOOL H0x014c0128_RegenerationImpulse_01(const CEntityEvent &__eeInput); + BOOL H0x014c0129_RegenerationImpulse_02(const CEntityEvent &__eeInput); + BOOL H0x014c012a_RegenerationImpulse_03(const CEntityEvent &__eeInput); + BOOL H0x014c012b_RegenerationImpulse_04(const CEntityEvent &__eeInput); +#define STATE_CDevil_StopAttack 0x014c012c + BOOL +#line 2137 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopAttack(const CEntityEvent &__eeInput); + BOOL H0x014c012d_StopAttack_01(const CEntityEvent &__eeInput); + BOOL H0x014c012e_StopAttack_02(const CEntityEvent &__eeInput); + BOOL H0x014c012f_StopAttack_03(const CEntityEvent &__eeInput); +#define STATE_CDevil_ContinueInMainLoop 0x014c0130 + BOOL +#line 2146 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ContinueInMainLoop(const CEntityEvent &__eeInput); +#define STATE_CDevil_MPIntro 0x014c0131 + BOOL +#line 2167 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +MPIntro(const CEntityEvent &__eeInput); +#define STATE_CDevil_Death 0x014c0132 + BOOL +#line 2176 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Death(const CEntityEvent &__eeInput); + BOOL H0x014c0133_Death_01(const CEntityEvent &__eeInput); + BOOL H0x014c0134_Death_02(const CEntityEvent &__eeInput); + BOOL H0x014c0135_Death_03(const CEntityEvent &__eeInput); + BOOL H0x014c0136_Death_04(const CEntityEvent &__eeInput); + BOOL H0x014c0137_Death_05(const CEntityEvent &__eeInput); + BOOL H0x014c0138_Death_06(const CEntityEvent &__eeInput); + BOOL H0x014c0139_Death_07(const CEntityEvent &__eeInput); + BOOL H0x014c013a_Death_08(const CEntityEvent &__eeInput); +#define STATE_CDevil_Main 1 + BOOL +#line 2213 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x014c013b_Main_01(const CEntityEvent &__eeInput); + BOOL H0x014c013c_Main_02(const CEntityEvent &__eeInput); + BOOL H0x014c013d_Main_03(const CEntityEvent &__eeInput); + BOOL H0x014c013e_Main_04(const CEntityEvent &__eeInput); + BOOL H0x014c013f_Main_05(const CEntityEvent &__eeInput); + BOOL H0x014c0140_Main_06(const CEntityEvent &__eeInput); + BOOL H0x014c0141_Main_07(const CEntityEvent &__eeInput); + BOOL H0x014c0142_Main_08(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Devil_INCLUDED diff --git a/Sources/EntitiesMP/DevilMarker.cpp b/Sources/EntitiesMP/DevilMarker.cpp new file mode 100644 index 0000000..a7ccb03 --- /dev/null +++ b/Sources/EntitiesMP/DevilMarker.cpp @@ -0,0 +1,215 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" + +#include "StdH.h" + +#include +#include +void CDevilMarker::SetDefaultProperties(void) { + m_datType = DAT_NONE ; + m_iWaitIdles = 2; + m_penDevil = NULL; + m_penTrigger = NULL; + m_penToDestroy1 = NULL; + m_penToDestroy2 = NULL; + m_fAttackRadius = 100.0f; + CMarker::SetDefaultProperties(); +} + +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +void CDevilMarker::SetDefaultName(void) +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +{ +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +m_strName = DevilActionType_enum . NameForValue (INDEX (m_datType )); +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +const CTString & CDevilMarker::GetDescription(void)const { +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +CTString strAction = DevilActionType_enum . NameForValue (INDEX (m_datType )); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +if(m_penTarget == NULL ){ +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +((CTString &) m_strDescription ) . PrintF ("%s (%s)->" , m_strName , strAction ); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +}else { +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +((CTString &) m_strDescription ) . PrintF ("%s (%s)->%s" , m_strName , strAction , +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +m_penTarget -> GetName ()); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return m_strDescription ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} + +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +BOOL CDevilMarker::MovesByTargetedRoute(CTString & strTargetProperty)const { +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +strTargetProperty = "Target"; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return TRUE ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +BOOL CDevilMarker::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +fnmMarkerClass = CTFILENAME ("Classes\\DevilMarker.ecl"); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +strTargetProperty = "Target"; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return TRUE ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} + +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +BOOL CDevilMarker::HandleEvent(const CEntityEvent & ee) +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +{ +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +if(ee . ee_slEvent == EVENTCODE_ETrigger ) +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +{ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +if(m_datType == DAT_NEXT_ACTION && m_penDevil != NULL && m_penTarget != NULL ) +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +{ +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +EDevilCommand eDevilCommand ; +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . dctType = DC_FORCE_ACTION ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . penForcedAction = m_penTarget ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +m_penDevil -> SendEvent (eDevilCommand ); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return TRUE ; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +else if(m_datType == DAT_GRAB_LOWER_WEAPONS && m_penDevil != NULL ) +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +{ +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +EDevilCommand eDevilCommand ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . dctType = DC_GRAB_LOWER_WEAPONS ; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +m_penDevil -> SendEvent (eDevilCommand ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return TRUE ; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +else if(m_datType == DAT_STOP_MOVING && m_penDevil != NULL ) +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +{ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +EDevilCommand eDevilCommand ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . dctType = DC_STOP_MOVING ; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +m_penDevil -> SendEvent (eDevilCommand ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return TRUE ; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +else if(m_datType == DAT_JUMP_INTO_PYRAMID && m_penDevil != NULL ) +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +{ +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +EDevilCommand eDevilCommand ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . dctType = DC_JUMP_INTO_PYRAMID ; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . penForcedAction = this ; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +m_penDevil -> SendEvent (eDevilCommand ); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return TRUE ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +else if(m_datType == DAT_TELEPORT_INTO_PYRAMID && m_penDevil != NULL ) +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +{ +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +EDevilCommand eDevilCommand ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . dctType = DC_TELEPORT_INTO_PYRAMID ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . penForcedAction = this ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +m_penDevil -> SendEvent (eDevilCommand ); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return TRUE ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +else if(m_datType == DAT_FORCE_ATTACK_RADIUS && m_penDevil != NULL ) +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +{ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +EDevilCommand eDevilCommand ; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . dctType = DC_FORCE_ATTACK_RADIUS ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . fAttackRadius = m_fAttackRadius ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . vCenterOfAttack = GetPlacement () . pl_PositionVector ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +m_penDevil -> SendEvent (eDevilCommand ); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return TRUE ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +else if(m_datType == DAT_DECREASE_ATTACK_RADIUS && m_penDevil != NULL ) +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +{ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +EDevilCommand eDevilCommand ; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +eDevilCommand . dctType = DC_DECREASE_ATTACK_RADIUS ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +m_penDevil -> SendEvent (eDevilCommand ); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return TRUE ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return FALSE ; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +} +BOOL CDevilMarker:: +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevilMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevilMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +InitAsEditorModel (); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +SetDefaultName (); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +SetModel (MODEL_MARKER ); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/DevilMarker.es b/Sources/EntitiesMP/DevilMarker.es new file mode 100644 index 0000000..5ad4086 --- /dev/null +++ b/Sources/EntitiesMP/DevilMarker.es @@ -0,0 +1,157 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +338 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; +uses "EntitiesMP/Devil"; + +enum DevilActionType { + 0 DAT_NONE "None", + 1 DAT_WALK "Walk", + 2 DAT_RISE "Rise", + 3 DAT_ROAR "Roar", + 4 DAT_PUNCH_LEFT "Punch left - obsolete", + 5 DAT_PUNCH_RIGHT "Punch right - obsolete", + 6 DAT_HIT_GROUND "Hit ground", + 7 DAT_JUMP "Jump", + 8 DAT_WAIT "Wait", + 9 DAT_STOP_DESTROYING "Stop destroying", + 10 DAT_NEXT_ACTION "Next action", + 11 DAT_GRAB_LOWER_WEAPONS "Grab lower weapons", + 12 DAT_STOP_MOVING "Stop moving", + 13 DAT_JUMP_INTO_PYRAMID "Jump into pyramid", + 14 DAT_SMASH_LEFT "Smash left - obsolete", + 15 DAT_SMASH_RIGHT "Smash right - obsolete", + 16 DAT_PUNCH "Punch", + 17 DAT_SMASH "Smash", + 18 DAT_FORCE_ATTACK_RADIUS "Force attack radius", + 19 DAT_TELEPORT_INTO_PYRAMID "Teleport into pyramid", + 20 DAT_DECREASE_ATTACK_RADIUS "Decrease attack radius", +}; + +class CDevilMarker: CMarker { +name "Devil Marker"; +thumbnail "Thumbnails\\EnemyMarker.tbn"; + +properties: + 1 enum DevilActionType m_datType "Action" 'A' = DAT_NONE, + 4 INDEX m_iWaitIdles "Wait idles" 'W' = 2, + 5 CEntityPointer m_penDevil "Devil" 'D', + 6 CEntityPointer m_penTrigger "Trigger" 'G', + 7 CEntityPointer m_penToDestroy1 "Destroy target 1" 'E', + 8 CEntityPointer m_penToDestroy2 "Destroy target 2" 'R', + 9 RANGE m_fAttackRadius "Attack radius" 'S' = 100.0f, + +components: + 1 model MODEL_MARKER "Models\\Editor\\EnemyMarker.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\DevilMarker.tex" + +functions: + void SetDefaultName(void) + { + m_strName = DevilActionType_enum.NameForValue(INDEX(m_datType)); + } + + const CTString &GetDescription(void) const { + CTString strAction = DevilActionType_enum.NameForValue(INDEX(m_datType)); + if (m_penTarget==NULL) { + ((CTString&)m_strDescription).PrintF("%s (%s)->", m_strName, strAction); + } else { + ((CTString&)m_strDescription).PrintF("%s (%s)->%s", m_strName, strAction, + m_penTarget->GetName()); + } + return m_strDescription; + } + + /* Check if entity is moved on a route set up by its targets. */ + BOOL MovesByTargetedRoute(CTString &strTargetProperty) const { + strTargetProperty = "Target"; + return TRUE; + }; + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\DevilMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + if (ee.ee_slEvent==EVENTCODE_ETrigger) + { + if(m_datType==DAT_NEXT_ACTION && m_penDevil!=NULL && m_penTarget!=NULL) + { + EDevilCommand eDevilCommand; + eDevilCommand.dctType = DC_FORCE_ACTION; + eDevilCommand.penForcedAction = m_penTarget; + m_penDevil->SendEvent(eDevilCommand); + return TRUE; + } + else if(m_datType==DAT_GRAB_LOWER_WEAPONS && m_penDevil!=NULL) + { + EDevilCommand eDevilCommand; + eDevilCommand.dctType = DC_GRAB_LOWER_WEAPONS; + m_penDevil->SendEvent(eDevilCommand); + return TRUE; + } + else if(m_datType==DAT_STOP_MOVING && m_penDevil!=NULL) + { + EDevilCommand eDevilCommand; + eDevilCommand.dctType = DC_STOP_MOVING; + m_penDevil->SendEvent(eDevilCommand); + return TRUE; + } + else if(m_datType==DAT_JUMP_INTO_PYRAMID && m_penDevil!=NULL) + { + EDevilCommand eDevilCommand; + eDevilCommand.dctType = DC_JUMP_INTO_PYRAMID; + eDevilCommand.penForcedAction = this; + m_penDevil->SendEvent(eDevilCommand); + return TRUE; + } + else if(m_datType==DAT_TELEPORT_INTO_PYRAMID && m_penDevil!=NULL) + { + EDevilCommand eDevilCommand; + eDevilCommand.dctType = DC_TELEPORT_INTO_PYRAMID; + eDevilCommand.penForcedAction = this; + m_penDevil->SendEvent(eDevilCommand); + return TRUE; + } + else if(m_datType==DAT_FORCE_ATTACK_RADIUS && m_penDevil!=NULL) + { + EDevilCommand eDevilCommand; + eDevilCommand.dctType = DC_FORCE_ATTACK_RADIUS; + eDevilCommand.fAttackRadius = m_fAttackRadius; + eDevilCommand.vCenterOfAttack = GetPlacement().pl_PositionVector; + m_penDevil->SendEvent(eDevilCommand); + return TRUE; + } + else if(m_datType==DAT_DECREASE_ATTACK_RADIUS && m_penDevil!=NULL) + { + EDevilCommand eDevilCommand; + eDevilCommand.dctType = DC_DECREASE_ATTACK_RADIUS; + m_penDevil->SendEvent(eDevilCommand); + return TRUE; + } + } + return FALSE; + } + +procedures: + Main() { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + SetDefaultName(); + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + return; + } +}; + diff --git a/Sources/EntitiesMP/DevilMarker.h b/Sources/EntitiesMP/DevilMarker.h new file mode 100644 index 0000000..c9d7daa --- /dev/null +++ b/Sources/EntitiesMP/DevilMarker.h @@ -0,0 +1,65 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_DevilMarker_INCLUDED +#define _EntitiesMP_DevilMarker_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType DevilActionType_enum; +enum DevilActionType { + DAT_NONE = 0, + DAT_WALK = 1, + DAT_RISE = 2, + DAT_ROAR = 3, + DAT_PUNCH_LEFT = 4, + DAT_PUNCH_RIGHT = 5, + DAT_HIT_GROUND = 6, + DAT_JUMP = 7, + DAT_WAIT = 8, + DAT_STOP_DESTROYING = 9, + DAT_NEXT_ACTION = 10, + DAT_GRAB_LOWER_WEAPONS = 11, + DAT_STOP_MOVING = 12, + DAT_JUMP_INTO_PYRAMID = 13, + DAT_SMASH_LEFT = 14, + DAT_SMASH_RIGHT = 15, + DAT_PUNCH = 16, + DAT_SMASH = 17, + DAT_FORCE_ATTACK_RADIUS = 18, + DAT_TELEPORT_INTO_PYRAMID = 19, + DAT_DECREASE_ATTACK_RADIUS = 20, +}; +DECL_DLL inline void ClearToDefault(DevilActionType &e) { e = (DevilActionType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CDevilMarker_DLLClass; +class CDevilMarker : public CMarker { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum DevilActionType m_datType; + INDEX m_iWaitIdles; + CEntityPointer m_penDevil; + CEntityPointer m_penTrigger; + CEntityPointer m_penToDestroy1; + CEntityPointer m_penToDestroy2; + RANGE m_fAttackRadius; + +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +void SetDefaultName(void); + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +const CTString & GetDescription(void)const; + +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CDevilMarker_Main 1 + BOOL +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_DevilMarker_INCLUDED diff --git a/Sources/EntitiesMP/DevilMarker_tables.h b/Sources/EntitiesMP/DevilMarker_tables.h new file mode 100644 index 0000000..0a139ae --- /dev/null +++ b/Sources/EntitiesMP/DevilMarker_tables.h @@ -0,0 +1,66 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(DevilActionType) + EP_ENUMVALUE(DAT_NONE, "None"), + EP_ENUMVALUE(DAT_WALK, "Walk"), + EP_ENUMVALUE(DAT_RISE, "Rise"), + EP_ENUMVALUE(DAT_ROAR, "Roar"), + EP_ENUMVALUE(DAT_PUNCH_LEFT, "Punch left - obsolete"), + EP_ENUMVALUE(DAT_PUNCH_RIGHT, "Punch right - obsolete"), + EP_ENUMVALUE(DAT_HIT_GROUND, "Hit ground"), + EP_ENUMVALUE(DAT_JUMP, "Jump"), + EP_ENUMVALUE(DAT_WAIT, "Wait"), + EP_ENUMVALUE(DAT_STOP_DESTROYING, "Stop destroying"), + EP_ENUMVALUE(DAT_NEXT_ACTION, "Next action"), + EP_ENUMVALUE(DAT_GRAB_LOWER_WEAPONS, "Grab lower weapons"), + EP_ENUMVALUE(DAT_STOP_MOVING, "Stop moving"), + EP_ENUMVALUE(DAT_JUMP_INTO_PYRAMID, "Jump into pyramid"), + EP_ENUMVALUE(DAT_SMASH_LEFT, "Smash left - obsolete"), + EP_ENUMVALUE(DAT_SMASH_RIGHT, "Smash right - obsolete"), + EP_ENUMVALUE(DAT_PUNCH, "Punch"), + EP_ENUMVALUE(DAT_SMASH, "Smash"), + EP_ENUMVALUE(DAT_FORCE_ATTACK_RADIUS, "Force attack radius"), + EP_ENUMVALUE(DAT_TELEPORT_INTO_PYRAMID, "Teleport into pyramid"), + EP_ENUMVALUE(DAT_DECREASE_ATTACK_RADIUS, "Decrease attack radius"), +EP_ENUMEND(DevilActionType); + +#define ENTITYCLASS CDevilMarker + +CEntityProperty CDevilMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &DevilActionType_enum, (0x00000152<<8)+1, offsetof(CDevilMarker, m_datType), "Action", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000152<<8)+4, offsetof(CDevilMarker, m_iWaitIdles), "Wait idles", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000152<<8)+5, offsetof(CDevilMarker, m_penDevil), "Devil", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000152<<8)+6, offsetof(CDevilMarker, m_penTrigger), "Trigger", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000152<<8)+7, offsetof(CDevilMarker, m_penToDestroy1), "Destroy target 1", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000152<<8)+8, offsetof(CDevilMarker, m_penToDestroy2), "Destroy target 2", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000152<<8)+9, offsetof(CDevilMarker, m_fAttackRadius), "Attack radius", 'S', 0x7F0000FFUL, 0), +}; +#define CDevilMarker_propertiesct ARRAYCOUNT(CDevilMarker_properties) + +CEntityComponent CDevilMarker_components[] = { +#define MODEL_MARKER ((0x00000152<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\EnemyMarker.mdl"), +#define TEXTURE_MARKER ((0x00000152<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\DevilMarker.tex"), +}; +#define CDevilMarker_componentsct ARRAYCOUNT(CDevilMarker_components) + +CEventHandlerEntry CDevilMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CDevilMarker:: +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/DevilMarker.es" +Main),DEBUGSTRING("CDevilMarker::Main")}, +}; +#define CDevilMarker_handlersct ARRAYCOUNT(CDevilMarker_handlers) + +CEntity *CDevilMarker_New(void) { return new CDevilMarker; }; +void CDevilMarker_OnInitClass(void) {}; +void CDevilMarker_OnEndClass(void) {}; +void CDevilMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CDevilMarker_OnWorldEnd(CWorld *pwo) {}; +void CDevilMarker_OnWorldInit(CWorld *pwo) {}; +void CDevilMarker_OnWorldTick(CWorld *pwo) {}; +void CDevilMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CDevilMarker, CMarker, "Devil Marker", "Thumbnails\\EnemyMarker.tbn", 0x00000152); +DECLARE_CTFILENAME(_fnmCDevilMarker_tbn, "Thumbnails\\EnemyMarker.tbn"); diff --git a/Sources/EntitiesMP/DevilProjectile.cpp b/Sources/EntitiesMP/DevilProjectile.cpp new file mode 100644 index 0000000..d404997 --- /dev/null +++ b/Sources/EntitiesMP/DevilProjectile.cpp @@ -0,0 +1,335 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *EDevilProjectile::MakeCopy(void) { CEntityEvent *peeCopy = new EDevilProjectile(*this); return peeCopy;} +EDevilProjectile::EDevilProjectile() : CEntityEvent(EVENTCODE_EDevilProjectile) {; + ClearToDefault(penLauncher); + ClearToDefault(penTarget); +}; +#line 18 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" + +#define FLY_TIME 15.0f +#define ROTATE_SPEED 200.0f +#define MOVING_SPEED 30.0f +#define MOVING_FREQUENCY 0.1f + +void CDevilProjectile::SetDefaultProperties(void) { + m_penLauncher = NULL; + m_penTarget = NULL; + m_fIgnoreTime = 0.0f; + m_fStartTime = 0.0f; + m_vDesiredAngle = FLOAT3D(0 , 0 , 0); + m_bFly = FALSE ; + m_soEffect.SetOwner(this); +m_soEffect.Stop_internal(); + CMovableModelEntity::SetDefaultProperties(); +} + +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::Read_t(CTStream * istr) +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +{ +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +CMovableModelEntity :: Read_t (istr ); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +SetupLightSource (); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +CLightSource * CDevilProjectile::GetLightSource(void) +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +{ +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +if(! IsPredictor ()){ +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +return & m_lsLightSource ; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +}else { +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +return NULL ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::SetupLightSource(void) +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +{ +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +CLightSource lsNew ; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +lsNew . ls_ulFlags = LSF_NONPERSISTENT | LSF_DYNAMIC ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +lsNew . ls_rHotSpot = 0.0f; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +lsNew . ls_colColor = RGBToColor (0 , 128 , 128); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +lsNew . ls_rFallOff = 5.0f; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +lsNew . ls_ubPolygonalMask = 0; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +lsNew . ls_paoLightAnimation = NULL ; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_lsLightSource . ls_penEntity = this ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::CalcHeadingRotation(ANGLE aWantedHeadingRelative,ANGLE & aRotation) { +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +aWantedHeadingRelative = NormalizeAngle (aWantedHeadingRelative ); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +if(aWantedHeadingRelative < - ROTATE_SPEED * MOVING_FREQUENCY ){ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +aRotation = - ROTATE_SPEED ; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +}else if(aWantedHeadingRelative > ROTATE_SPEED * MOVING_FREQUENCY ){ +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +aRotation = + ROTATE_SPEED ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +}else { +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +aRotation = aWantedHeadingRelative / MOVING_FREQUENCY ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::CalcAngleFromPosition() { +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +FLOAT3D vTarget ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +vTarget = m_penTarget -> GetPlacement () . pl_PositionVector ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +vTarget += FLOAT3D (m_penTarget -> en_mRotation (1 , 2) , +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_penTarget -> en_mRotation (2 , 2) , +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_penTarget -> en_mRotation (3 , 2)) * 2.0f; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_vDesiredAngle = (vTarget - GetPlacement () . pl_PositionVector ) . Normalize (); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::RotateToAngle() { +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +ANGLE aRotation ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +CalcHeadingRotation (GetRelativeHeading (m_vDesiredAngle ) , aRotation ); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +SetDesiredRotation (ANGLE3D (aRotation , 0 , 0)); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::FlyInDirection() { +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +RotateToAngle (); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +FLOAT3D vTarget ; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +vTarget = m_penTarget -> GetPlacement () . pl_PositionVector ; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +vTarget += FLOAT3D (m_penTarget -> en_mRotation (1 , 2) , +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_penTarget -> en_mRotation (2 , 2) , +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_penTarget -> en_mRotation (3 , 2)) * 2.0f; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +FLOAT3D vTranslation = (vTarget - GetPlacement () . pl_PositionVector ) * ! en_mRotation ; +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +vTranslation (1) = 0.0f; +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +vTranslation . Normalize (); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +vTranslation *= MOVING_SPEED ; +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +SetDesiredTranslation (vTranslation ); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::FlyToPosition() { +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +CalcAngleFromPosition (); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +FlyInDirection (); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::RotateToPosition() { +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +CalcAngleFromPosition (); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +RotateToAngle (); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::StopMoving() { +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +StopRotating (); +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +StopTranslating (); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::StopRotating() { +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::StopTranslating() { +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} + +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CDevilProjectile::ProjectileTouch(CEntityPointer penHit) { +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +FLOAT3D vDirection ; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +AnglesToDirectionVector (GetPlacement () . pl_OrientationAngle , vDirection ); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +InflictDirectDamage (penHit , m_penLauncher , DMT_PROJECTILE , 15.0f , +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +GetPlacement () . pl_PositionVector , vDirection ); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} +BOOL CDevilProjectile:: +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +Fly(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevilProjectile_Fly + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDevilProjectile::Fly expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_bFly = TRUE ; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +Jump(STATE_CURRENT,0x01ff0004, FALSE, EInternal());return TRUE;}BOOL CDevilProjectile::H0x01ff0004_Fly_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01ff0004 +if(!(m_bFly && m_fStartTime + FLY_TIME > _pTimer -> CurrentTick ())){ Jump(STATE_CURRENT,0x01ff0005, FALSE, EInternal());return TRUE;} +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x01ff0002, FALSE, EBegin());return TRUE;}BOOL CDevilProjectile::H0x01ff0002_Fly_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01ff0002 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +FlyToPosition (); +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +return TRUE; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&epass= (EPass&)__eeInput; + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +BOOL bHit ; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +bHit = epass . penOther != m_penLauncher || _pTimer -> CurrentTick () > m_fIgnoreTime ; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +bHit &= ! IsOfClass (epass . penOther , "Twister"); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +if(bHit ){ +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +ProjectileTouch (epass . penOther ); +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_bFly = FALSE ; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01ff0003, FALSE, EInternal());return TRUE; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +} +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +return TRUE; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_fIgnoreTime = 0.0f; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +return TRUE; +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01ff0003, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +}return TRUE;}BOOL CDevilProjectile::H0x01ff0003_Fly_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01ff0003 +Jump(STATE_CURRENT,0x01ff0004, FALSE, EInternal());return TRUE; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +}BOOL CDevilProjectile::H0x01ff0005_Fly_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01ff0005 + +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CDevilProjectile:: +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDevilProjectile_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDevilProjectile, "CDevilProjectile::Main expects 'EDevilProjectile' as input!"); const EDevilProjectile &eLaunch = (const EDevilProjectile &)__eeInput; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +ASSERT (eLaunch . penLauncher != NULL ); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +ASSERT (eLaunch . penTarget != NULL ); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_penLauncher = eLaunch . penLauncher ; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_penTarget = eLaunch . penTarget ; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +InitAsModel (); +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +SetModel (MODEL_FLARE ); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +SetModelMainTexture (TEXTURE_FLARE ); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +SetupLightSource (); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_fIgnoreTime = _pTimer -> CurrentTick () + 1.0f; +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +m_fStartTime = _pTimer -> CurrentTick (); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +STATE_CDevilProjectile_Fly, TRUE; +Jump(STATE_CURRENT, 0x01ff0006, FALSE, EBegin());return TRUE;}BOOL CDevilProjectile::H0x01ff0006_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01ff0006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CDevilProjectile_Fly, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01ff0007, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CDevilProjectile::H0x01ff0007_Main_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01ff0007 +const EEnd&__e= (EEnd&)__eeInput; +; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +Destroy (); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +Return(STATE_CURRENT,EVoid()); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/DevilProjectile.es b/Sources/EntitiesMP/DevilProjectile.es new file mode 100644 index 0000000..1ad487d --- /dev/null +++ b/Sources/EntitiesMP/DevilProjectile.es @@ -0,0 +1,272 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +511 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/BasicEffects"; +uses "EntitiesMP/Light"; + +// input parameter for launching the projectile +event EDevilProjectile { + CEntityPointer penLauncher, // who launched it + CEntityPointer penTarget, // target entity +}; + + +%{ +#define FLY_TIME 15.0f +#define ROTATE_SPEED 200.0f +#define MOVING_SPEED 30.0f +#define MOVING_FREQUENCY 0.1f +%} + + +class CDevilProjectile : CMovableModelEntity { +name "Devil projectile"; +thumbnail ""; + +properties: + 1 CEntityPointer m_penLauncher, // who lanuched it + 2 CEntityPointer m_penTarget, // target entity + + 10 FLOAT m_fIgnoreTime = 0.0f, // time when laucher will be ignored + 11 FLOAT m_fStartTime = 0.0f, // start time when launched + 12 FLOAT3D m_vDesiredAngle = FLOAT3D(0,0,0), + 13 BOOL m_bFly = FALSE, + + 20 CSoundObject m_soEffect, // sound channel + +{ + CLightSource m_lsLightSource; +} + +components: + 1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 2 class CLASS_LIGHT "Classes\\Light.ecl", + +// ********* PLAYER ROCKET ********* + 10 model MODEL_FLARE "Models\\Enemies\\Devil\\Flare.mdl", + 11 texture TEXTURE_FLARE "Models\\Enemies\\Devil\\12.tex", + + +functions: + /* Read from stream. */ + void Read_t( CTStream *istr) // throw char * + { + CMovableModelEntity::Read_t(istr); + // setup light source + SetupLightSource(); + }; + + /* Get static light source information. */ + CLightSource *GetLightSource(void) + { + if (!IsPredictor()) { + return &m_lsLightSource; + } else { + return NULL; + } + }; + + // Setup light source + void SetupLightSource(void) + { + // setup light source + CLightSource lsNew; + lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC; + lsNew.ls_rHotSpot = 0.0f; + lsNew.ls_colColor = RGBToColor(0, 128, 128); + lsNew.ls_rFallOff = 5.0f; + lsNew.ls_plftLensFlare = NULL; + lsNew.ls_ubPolygonalMask = 0; + lsNew.ls_paoLightAnimation = NULL; + + m_lsLightSource.ls_penEntity = this; + m_lsLightSource.SetLightSource(lsNew); + }; + + + +/************************************************************ + * MOVING FUNCTIONS * + ************************************************************/ + // calculate rotation + void CalcHeadingRotation(ANGLE aWantedHeadingRelative, ANGLE &aRotation) { + // normalize it to [-180,+180] degrees + aWantedHeadingRelative = NormalizeAngle(aWantedHeadingRelative); + + // if desired position is left + if (aWantedHeadingRelative < -ROTATE_SPEED*MOVING_FREQUENCY) { + // start turning left + aRotation = -ROTATE_SPEED; + // if desired position is right + } else if (aWantedHeadingRelative > ROTATE_SPEED*MOVING_FREQUENCY) { + // start turning right + aRotation = +ROTATE_SPEED; + // if desired position is more-less ahead + } else { + aRotation = aWantedHeadingRelative/MOVING_FREQUENCY; + } + }; + + // calculate angle from position + void CalcAngleFromPosition() { + // target enemy body + FLOAT3D vTarget; +/* EntityInfo *peiTarget = (EntityInfo*) (m_penTarget->GetEntityInfo()); + GetEntityInfoPosition(m_penTarget, peiTarget->vTargetCenter, vTarget);*/ + vTarget = m_penTarget->GetPlacement().pl_PositionVector; + vTarget += FLOAT3D(m_penTarget->en_mRotation(1, 2), + m_penTarget->en_mRotation(2, 2), + m_penTarget->en_mRotation(3, 2)) * 2.0f; + + // find relative orientation towards the desired position + m_vDesiredAngle = (vTarget - GetPlacement().pl_PositionVector).Normalize(); + }; + + // rotate entity to desired angle + void RotateToAngle() { + // find relative heading towards the desired angle + ANGLE aRotation; + CalcHeadingRotation(GetRelativeHeading(m_vDesiredAngle), aRotation); + + // start rotating + SetDesiredRotation(ANGLE3D(aRotation, 0, 0)); + }; + + // fly move in direction + void FlyInDirection() { + RotateToAngle(); + + // target enemy body + FLOAT3D vTarget; +/* EntityInfo *peiTarget = (EntityInfo*) (m_penTarget->GetEntityInfo()); + GetEntityInfoPosition(m_penTarget, peiTarget->vTargetCenter, vTarget);*/ + vTarget = m_penTarget->GetPlacement().pl_PositionVector; + vTarget += FLOAT3D(m_penTarget->en_mRotation(1, 2), + m_penTarget->en_mRotation(2, 2), + m_penTarget->en_mRotation(3, 2)) * 2.0f; + + // determine translation speed + FLOAT3D vTranslation = (vTarget - GetPlacement().pl_PositionVector) * !en_mRotation; + vTranslation(1) = 0.0f; + vTranslation.Normalize(); + vTranslation *= MOVING_SPEED; + + // start moving + SetDesiredTranslation(vTranslation); + }; + + // fly entity to desired position + void FlyToPosition() { + CalcAngleFromPosition(); + FlyInDirection(); + }; + + // rotate entity to desired position + void RotateToPosition() { + CalcAngleFromPosition(); + RotateToAngle(); + }; + + // stop moving entity + void StopMoving() { + StopRotating(); + StopTranslating(); + }; + + // stop rotating entity + void StopRotating() { + SetDesiredRotation(ANGLE3D(0, 0, 0)); + }; + + // stop translating + void StopTranslating() { + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + }; + + + +/************************************************************ + * C O M M O N F U N C T I O N S * + ************************************************************/ + void ProjectileTouch(CEntityPointer penHit) { + // direct damage + FLOAT3D vDirection; + AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, vDirection); + InflictDirectDamage(penHit, m_penLauncher, DMT_PROJECTILE, 15.0f, + GetPlacement().pl_PositionVector, vDirection); + }; + + + +/************************************************************ + * P R O C E D U R E S * + ************************************************************/ +procedures: + Fly(EVoid) { + // bounce loop + m_bFly = TRUE; + while(m_bFly && m_fStartTime+FLY_TIME > _pTimer->CurrentTick()) { + wait(0.1f) { + on (EBegin) : { + FlyToPosition(); + resume; + } + on (EPass epass) : { + BOOL bHit; + // ignore launcher within 1 second + bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime; + // ignore twister + bHit &= !IsOfClass(epass.penOther, "Twister"); + if (bHit) { + ProjectileTouch(epass.penOther); + m_bFly = FALSE; + stop; + } + resume; + } + on (ETouch etouch) : { + // clear time limit for launcher + m_fIgnoreTime = 0.0f; + resume; + } + on (ETimer) : { stop; } + } + } + return EEnd(); + }; + + // --->>> MAIN + Main(EDevilProjectile eLaunch) { + // remember the initial parameters + ASSERT(eLaunch.penLauncher!=NULL); + ASSERT(eLaunch.penTarget!=NULL); + m_penLauncher = eLaunch.penLauncher; + m_penTarget = eLaunch.penTarget; + + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetModel(MODEL_FLARE); + SetModelMainTexture(TEXTURE_FLARE); + + // setup light source + SetupLightSource(); + + // remember lauching time + m_fIgnoreTime = _pTimer->CurrentTick() + 1.0f; + + // fly + m_fStartTime = _pTimer->CurrentTick(); + autocall Fly() EEnd; + + // cease to exist + Destroy(); + + return; + } +}; diff --git a/Sources/EntitiesMP/DevilProjectile.h b/Sources/EntitiesMP/DevilProjectile.h new file mode 100644 index 0000000..27678fb --- /dev/null +++ b/Sources/EntitiesMP/DevilProjectile.h @@ -0,0 +1,84 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_DevilProjectile_INCLUDED +#define _EntitiesMP_DevilProjectile_INCLUDED 1 +#include +#include +#define EVENTCODE_EDevilProjectile 0x01ff0000 +class DECL_DLL EDevilProjectile : public CEntityEvent { +public: +EDevilProjectile(); +CEntityEvent *MakeCopy(void); +CEntityPointer penLauncher; +CEntityPointer penTarget; +}; +DECL_DLL inline void ClearToDefault(EDevilProjectile &e) { e = EDevilProjectile(); } ; +extern "C" DECL_DLL CDLLEntityClass CDevilProjectile_DLLClass; +class CDevilProjectile : public CMovableModelEntity { +public: + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penLauncher; + CEntityPointer m_penTarget; + FLOAT m_fIgnoreTime; + FLOAT m_fStartTime; + FLOAT3D m_vDesiredAngle; + BOOL m_bFly; + CSoundObject m_soEffect; +CLightSource m_lsLightSource; + +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void Read_t(CTStream * istr); + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +CLightSource * GetLightSource(void); + +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void SetupLightSource(void); + +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CalcHeadingRotation(ANGLE aWantedHeadingRelative,ANGLE & aRotation); + +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void CalcAngleFromPosition(); + +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void RotateToAngle(); + +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void FlyInDirection(); + +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void FlyToPosition(); + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void RotateToPosition(); + +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void StopMoving(); + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void StopRotating(); + +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void StopTranslating(); + +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +void ProjectileTouch(CEntityPointer penHit); +#define STATE_CDevilProjectile_Fly 0x01ff0001 + BOOL +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +Fly(const CEntityEvent &__eeInput); + BOOL H0x01ff0002_Fly_01(const CEntityEvent &__eeInput); + BOOL H0x01ff0003_Fly_02(const CEntityEvent &__eeInput); + BOOL H0x01ff0004_Fly_03(const CEntityEvent &__eeInput); + BOOL H0x01ff0005_Fly_04(const CEntityEvent &__eeInput); +#define STATE_CDevilProjectile_Main 1 + BOOL +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01ff0006_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01ff0007_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_DevilProjectile_INCLUDED diff --git a/Sources/EntitiesMP/DevilProjectile_tables.h b/Sources/EntitiesMP/DevilProjectile_tables.h new file mode 100644 index 0000000..73fbf24 --- /dev/null +++ b/Sources/EntitiesMP/DevilProjectile_tables.h @@ -0,0 +1,55 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CDevilProjectile + +CEntityProperty CDevilProjectile_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001ff<<8)+1, offsetof(CDevilProjectile, m_penLauncher), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001ff<<8)+2, offsetof(CDevilProjectile, m_penTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001ff<<8)+10, offsetof(CDevilProjectile, m_fIgnoreTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001ff<<8)+11, offsetof(CDevilProjectile, m_fStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001ff<<8)+12, offsetof(CDevilProjectile, m_vDesiredAngle), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001ff<<8)+13, offsetof(CDevilProjectile, m_bFly), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000001ff<<8)+20, offsetof(CDevilProjectile, m_soEffect), "", 0, 0, 0), +}; +#define CDevilProjectile_propertiesct ARRAYCOUNT(CDevilProjectile_properties) + +CEntityComponent CDevilProjectile_components[] = { +#define CLASS_BASIC_EFFECT ((0x000001ff<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_LIGHT ((0x000001ff<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_LIGHT, "EFNM" "Classes\\Light.ecl"), +#define MODEL_FLARE ((0x000001ff<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_FLARE, "EFNM" "Models\\Enemies\\Devil\\Flare.mdl"), +#define TEXTURE_FLARE ((0x000001ff<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE, "EFNM" "Models\\Enemies\\Devil\\12.tex"), +}; +#define CDevilProjectile_componentsct ARRAYCOUNT(CDevilProjectile_components) + +CEventHandlerEntry CDevilProjectile_handlers[] = { + {0x01ff0001, -1, CEntity::pEventHandler(&CDevilProjectile:: +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +Fly),DEBUGSTRING("CDevilProjectile::Fly")}, + {0x01ff0002, -1, CEntity::pEventHandler(&CDevilProjectile::H0x01ff0002_Fly_01), DEBUGSTRING("CDevilProjectile::H0x01ff0002_Fly_01")}, + {0x01ff0003, -1, CEntity::pEventHandler(&CDevilProjectile::H0x01ff0003_Fly_02), DEBUGSTRING("CDevilProjectile::H0x01ff0003_Fly_02")}, + {0x01ff0004, -1, CEntity::pEventHandler(&CDevilProjectile::H0x01ff0004_Fly_03), DEBUGSTRING("CDevilProjectile::H0x01ff0004_Fly_03")}, + {0x01ff0005, -1, CEntity::pEventHandler(&CDevilProjectile::H0x01ff0005_Fly_04), DEBUGSTRING("CDevilProjectile::H0x01ff0005_Fly_04")}, + {1, -1, CEntity::pEventHandler(&CDevilProjectile:: +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/DevilProjectile.es" +Main),DEBUGSTRING("CDevilProjectile::Main")}, + {0x01ff0006, -1, CEntity::pEventHandler(&CDevilProjectile::H0x01ff0006_Main_01), DEBUGSTRING("CDevilProjectile::H0x01ff0006_Main_01")}, + {0x01ff0007, -1, CEntity::pEventHandler(&CDevilProjectile::H0x01ff0007_Main_02), DEBUGSTRING("CDevilProjectile::H0x01ff0007_Main_02")}, +}; +#define CDevilProjectile_handlersct ARRAYCOUNT(CDevilProjectile_handlers) + +CEntity *CDevilProjectile_New(void) { return new CDevilProjectile; }; +void CDevilProjectile_OnInitClass(void) {}; +void CDevilProjectile_OnEndClass(void) {}; +void CDevilProjectile_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CDevilProjectile_OnWorldEnd(CWorld *pwo) {}; +void CDevilProjectile_OnWorldInit(CWorld *pwo) {}; +void CDevilProjectile_OnWorldTick(CWorld *pwo) {}; +void CDevilProjectile_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CDevilProjectile, CMovableModelEntity, "Devil projectile", "", 0x000001ff); +DECLARE_CTFILENAME(_fnmCDevilProjectile_tbn, ""); diff --git a/Sources/EntitiesMP/Devil_tables.h b/Sources/EntitiesMP/Devil_tables.h new file mode 100644 index 0000000..de35e6f --- /dev/null +++ b/Sources/EntitiesMP/Devil_tables.h @@ -0,0 +1,584 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(DevilCommandType) + EP_ENUMVALUE(DC_GRAB_LOWER_WEAPONS, "Grab lower weapons"), + EP_ENUMVALUE(DC_FORCE_ACTION, "Force next action"), + EP_ENUMVALUE(DC_STOP_MOVING, "Stop moving"), + EP_ENUMVALUE(DC_STOP_ATTACK, "Stop attacking"), + EP_ENUMVALUE(DC_JUMP_INTO_PYRAMID, "Jump into pyramid"), + EP_ENUMVALUE(DC_FORCE_ATTACK_RADIUS, "Force attack radius"), + EP_ENUMVALUE(DC_DECREASE_ATTACK_RADIUS, "Decrease attack radius"), + EP_ENUMVALUE(DC_TELEPORT_INTO_PYRAMID, "Teleport into pyramid"), +EP_ENUMEND(DevilCommandType); + +EP_ENUMBEG(DevilState) + EP_ENUMVALUE(DS_NOT_EXISTING, "Not existing"), + EP_ENUMVALUE(DS_DESTROYING_CITY, "Destroying city"), + EP_ENUMVALUE(DS_ENEMY, "Enemy"), + EP_ENUMVALUE(DS_JUMPING_INTO_PYRAMID, "Jumping into pyramid"), + EP_ENUMVALUE(DS_PYRAMID_FIGHT, "Pyramid fight"), + EP_ENUMVALUE(DS_REGENERATION_IMPULSE, "Regenerating with impulse"), +EP_ENUMEND(DevilState); + +EP_ENUMBEG(DevilAttackPower) + EP_ENUMVALUE(DAP_PLAYER_HUNT, "Player hunt"), + EP_ENUMVALUE(DAP_LOW_POWER_ATTACK, "Low power attack"), + EP_ENUMVALUE(DAP_MEDIUM_POWER_ATTACK, "Medium power attack"), + EP_ENUMVALUE(DAP_FULL_POWER_ATTACK, "Full power attack"), + EP_ENUMVALUE(DAP_NOT_ATTACKING, "Not attacking"), +EP_ENUMEND(DevilAttackPower); + +#define ENTITYCLASS CDevil + +CEntityProperty CDevil_properties[] = { + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000014c<<8)+1, offsetof(CDevil, m_iAttID), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+2, offsetof(CDevil, m_fDeltaWeaponPitch), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+3, offsetof(CDevil, m_fDeltaWeaponHdg), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+4, offsetof(CDevil, m_fFireTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANIMOBJECT, NULL, (0x0000014c<<8)+5, offsetof(CDevil, m_aoLightAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000014c<<8)+6, offsetof(CDevil, m_penAction), "Action", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000014c<<8)+8, offsetof(CDevil, m_iFiredProjectiles), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000014c<<8)+9, offsetof(CDevil, m_iToFireProjectiles), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+10, offsetof(CDevil, m_fPauseStretcher), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+11, offsetof(CDevil, m_tmLastPause), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DevilState_enum, (0x0000014c<<8)+12, offsetof(CDevil, m_dsDevilState), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+13, offsetof(CDevil, m_tmLastAngry), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_PLACEMENT3D, NULL, (0x0000014c<<8)+14, offsetof(CDevil, m_plTeleport), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+16, offsetof(CDevil, m_tmTemp), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DevilState_enum, (0x0000014c<<8)+17, offsetof(CDevil, m_dsLastDevilState), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DevilAttackPower_enum, (0x0000014c<<8)+18, offsetof(CDevil, m_dapAttackPower), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DevilAttackPower_enum, (0x0000014c<<8)+19, offsetof(CDevil, m_dapLastAttackPower), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000014c<<8)+20, offsetof(CDevil, m_bHasUpperWeapons), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000014c<<8)+21, offsetof(CDevil, m_vElectricitySource), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000014c<<8)+22, offsetof(CDevil, m_vElectricityTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000014c<<8)+23, offsetof(CDevil, m_bRenderElectricity), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+24, offsetof(CDevil, m_fAdjustWeaponTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000014c<<8)+25, offsetof(CDevil, m_bWasOnceInMainLoop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+26, offsetof(CDevil, m_tmHitBySpaceShipBeam), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000014c<<8)+27, offsetof(CDevil, m_soLeft), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000014c<<8)+28, offsetof(CDevil, m_soRight), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+29, offsetof(CDevil, m_fLastWalkTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+30, offsetof(CDevil, m_tmFireBreathStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+31, offsetof(CDevil, m_tmFireBreathStop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000014c<<8)+32, offsetof(CDevil, m_vFireBreathSource), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000014c<<8)+33, offsetof(CDevil, m_vFireBreathTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+34, offsetof(CDevil, m_tmRegenerationStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+35, offsetof(CDevil, m_tmRegenerationStop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+36, offsetof(CDevil, m_tmNextFXTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000014c<<8)+37, offsetof(CDevil, m_iNextChannel), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000014c<<8)+38, offsetof(CDevil, m_soWeapon0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000014c<<8)+39, offsetof(CDevil, m_soWeapon1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000014c<<8)+40, offsetof(CDevil, m_soWeapon2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000014c<<8)+41, offsetof(CDevil, m_soWeapon3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000014c<<8)+42, offsetof(CDevil, m_soWeapon4), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000014c<<8)+43, offsetof(CDevil, m_iAngryAnim), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000014c<<8)+44, offsetof(CDevil, m_iAngrySound), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000014c<<8)+45, offsetof(CDevil, m_tmDeathTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000014c<<8)+50, offsetof(CDevil, m_iLastCurrentAnim), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000014c<<8)+51, offsetof(CDevil, m_iLastScheduledAnim), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DevilState_enum, (0x0000014c<<8)+52, offsetof(CDevil, m_dsPreRegenerationDevilState), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000014c<<8)+60, offsetof(CDevil, m_soClimb), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000014c<<8)+61, offsetof(CDevil, m_soGrabLowerWeapons), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000014c<<8)+62, offsetof(CDevil, m_soGrabUpperWeapons), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000014c<<8)+63, offsetof(CDevil, m_soJumpIntoPyramid), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000014c<<8)+70, offsetof(CDevil, m_bForMPIntro), "MP Intro", 0, 0x7F0000FFUL, 0), +}; +#define CDevil_propertiesct ARRAYCOUNT(CDevil_properties) + +CEntityComponent CDevil_components[] = { +#define CLASS_BASE ((0x0000014c<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_PROJECTILE ((0x0000014c<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_EFFECTOR ((0x0000014c<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_EFFECTOR, "EFNM" "Classes\\Effector.ecl"), +#define MODEL_DEVIL ((0x0000014c<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_DEVIL, "EFNM" "Models\\Enemies\\Devil\\Devil.mdl"), +#define TEXTURE_DEVIL ((0x0000014c<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_DEVIL, "EFNM" "Models\\Enemies\\Devil\\Devil.tex"), +#define MODEL_LASER ((0x0000014c<<8)+20) + CEntityComponent(ECT_MODEL, MODEL_LASER, "EFNM" "Models\\Enemies\\Devil\\Weapons\\Laser.mdl"), +#define TEXTURE_LASER ((0x0000014c<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_LASER, "EFNM" "Models\\Enemies\\Devil\\Weapons\\Laser.tex"), +#define MODEL_ROCKETLAUNCHER ((0x0000014c<<8)+22) + CEntityComponent(ECT_MODEL, MODEL_ROCKETLAUNCHER, "EFNM" "Models\\Enemies\\Devil\\Weapons\\RocketLauncher.mdl"), +#define TEXTURE_ROCKETLAUNCHER ((0x0000014c<<8)+23) + CEntityComponent(ECT_TEXTURE, TEXTURE_ROCKETLAUNCHER, "EFNM" "Models\\Enemies\\Devil\\Weapons\\RocketLauncher.tex"), +#define MODEL_PROJECTILEGUN ((0x0000014c<<8)+24) + CEntityComponent(ECT_MODEL, MODEL_PROJECTILEGUN, "EFNM" "Models\\Enemies\\Devil\\Weapons\\ProjectileGun.mdl"), +#define TEXTURE_PROJECTILEGUN ((0x0000014c<<8)+25) + CEntityComponent(ECT_TEXTURE, TEXTURE_PROJECTILEGUN, "EFNM" "Models\\Enemies\\Devil\\Weapons\\ProjectileGun.tex"), +#define MODEL_ELECTRICITYGUN ((0x0000014c<<8)+26) + CEntityComponent(ECT_MODEL, MODEL_ELECTRICITYGUN, "EFNM" "Models\\Enemies\\Devil\\Weapons\\ElectricityGun.mdl"), +#define TEXTURE_ELECTRICITYGUN ((0x0000014c<<8)+27) + CEntityComponent(ECT_TEXTURE, TEXTURE_ELECTRICITYGUN, "EFNM" "Models\\Enemies\\Devil\\Weapons\\ElectricityGun.tex"), +#define SOUND_ANGER01 ((0x0000014c<<8)+60) + CEntityComponent(ECT_SOUND, SOUND_ANGER01, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Anger01.wav"), +#define SOUND_ANGER02 ((0x0000014c<<8)+61) + CEntityComponent(ECT_SOUND, SOUND_ANGER02, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Anger02.wav"), +#define SOUND_ATTACKCLOSE ((0x0000014c<<8)+62) + CEntityComponent(ECT_SOUND, SOUND_ATTACKCLOSE, "EFNM" "Models\\Enemies\\Devil\\Sounds\\AttackClose.wav"), +#define SOUND_CELEBRATE01 ((0x0000014c<<8)+63) + CEntityComponent(ECT_SOUND, SOUND_CELEBRATE01, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Celebrate01.wav"), +#define SOUND_DEATH ((0x0000014c<<8)+65) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Death.wav"), +#define SOUND_DRAW_LOWER_WEAPONS ((0x0000014c<<8)+66) + CEntityComponent(ECT_SOUND, SOUND_DRAW_LOWER_WEAPONS, "EFNM" "Models\\Enemies\\Devil\\Sounds\\GrabWeaponsLower.wav"), +#define SOUND_DRAW_UPPER_WEAPONS ((0x0000014c<<8)+67) + CEntityComponent(ECT_SOUND, SOUND_DRAW_UPPER_WEAPONS, "EFNM" "Models\\Enemies\\Devil\\Sounds\\GrabWeaponsUpper.wav"), +#define SOUND_GETUP ((0x0000014c<<8)+68) + CEntityComponent(ECT_SOUND, SOUND_GETUP, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Getup.wav"), +#define SOUND_IDLE ((0x0000014c<<8)+69) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Idle.wav"), +#define SOUND_PUNCH ((0x0000014c<<8)+70) + CEntityComponent(ECT_SOUND, SOUND_PUNCH, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Punch.wav"), +#define SOUND_SMASH ((0x0000014c<<8)+71) + CEntityComponent(ECT_SOUND, SOUND_SMASH, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Smash.wav"), +#define SOUND_WALK_LEFT ((0x0000014c<<8)+72) + CEntityComponent(ECT_SOUND, SOUND_WALK_LEFT, "EFNM" "Models\\Enemies\\Devil\\Sounds\\WalkL.wav"), +#define SOUND_WALK_RIGHT ((0x0000014c<<8)+73) + CEntityComponent(ECT_SOUND, SOUND_WALK_RIGHT, "EFNM" "Models\\Enemies\\Devil\\Sounds\\WalkR.wav"), +#define SOUND_WOUND ((0x0000014c<<8)+74) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Wound.wav"), +#define SOUND_ATTACK_BREATH_START ((0x0000014c<<8)+75) + CEntityComponent(ECT_SOUND, SOUND_ATTACK_BREATH_START, "EFNM" "Models\\Enemies\\Devil\\Sounds\\AttackBreathStart.wav"), +#define SOUND_ATTACK_BREATH_FIRE ((0x0000014c<<8)+76) + CEntityComponent(ECT_SOUND, SOUND_ATTACK_BREATH_FIRE, "EFNM" "Models\\Enemies\\Devil\\Sounds\\BreathProjectile.wav"), +#define SOUND_ATTACK_BREATH_END ((0x0000014c<<8)+77) + CEntityComponent(ECT_SOUND, SOUND_ATTACK_BREATH_END, "EFNM" "Models\\Enemies\\Devil\\Sounds\\AttackBreathEnd.wav"), +#define SOUND_HEAL ((0x0000014c<<8)+78) + CEntityComponent(ECT_SOUND, SOUND_HEAL, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Heal.wav"), +#define SOUND_ROCKETLAUNCHER ((0x0000014c<<8)+79) + CEntityComponent(ECT_SOUND, SOUND_ROCKETLAUNCHER, "EFNM" "Models\\Enemies\\Devil\\Sounds\\RocketLauncher.wav"), +#define SOUND_LASER ((0x0000014c<<8)+80) + CEntityComponent(ECT_SOUND, SOUND_LASER, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Laser.wav"), +#define SOUND_LAVABOMB ((0x0000014c<<8)+81) + CEntityComponent(ECT_SOUND, SOUND_LAVABOMB, "EFNM" "Models\\Enemies\\Devil\\Sounds\\LavaBomb.wav"), +#define SOUND_GHOSTBUSTER ((0x0000014c<<8)+82) + CEntityComponent(ECT_SOUND, SOUND_GHOSTBUSTER, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Ghostbuster.wav"), +#define SOUND_ATTACK_BREATH_LOOP ((0x0000014c<<8)+83) + CEntityComponent(ECT_SOUND, SOUND_ATTACK_BREATH_LOOP, "EFNM" "Models\\Enemies\\Devil\\Sounds\\AttackBreath.wav"), +#define SOUND_CLIMB ((0x0000014c<<8)+84) + CEntityComponent(ECT_SOUND, SOUND_CLIMB, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Enter.wav"), +#define SOUND_DEATHPARTICLES ((0x0000014c<<8)+85) + CEntityComponent(ECT_SOUND, SOUND_DEATHPARTICLES, "EFNM" "Models\\Enemies\\Devil\\Sounds\\DeathParticles.wav"), +#define SOUND_DISAPPEAR ((0x0000014c<<8)+86) + CEntityComponent(ECT_SOUND, SOUND_DISAPPEAR, "EFNM" "Models\\Enemies\\Devil\\Sounds\\Disappear.wav"), +}; +#define CDevil_componentsct ARRAYCOUNT(CDevil_components) + +CEventHandlerEntry CDevil_handlers[] = { + {0x014c0003, -1, CEntity::pEventHandler(&CDevil:: +#line 1154 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WalkTo),DEBUGSTRING("CDevil::WalkTo")}, + {0x014c0004, -1, CEntity::pEventHandler(&CDevil::H0x014c0004_WalkTo_01), DEBUGSTRING("CDevil::H0x014c0004_WalkTo_01")}, + {0x014c0005, -1, CEntity::pEventHandler(&CDevil::H0x014c0005_WalkTo_02), DEBUGSTRING("CDevil::H0x014c0005_WalkTo_02")}, + {0x014c0006, -1, CEntity::pEventHandler(&CDevil::H0x014c0006_WalkTo_03), DEBUGSTRING("CDevil::H0x014c0006_WalkTo_03")}, + {0x014c0007, -1, CEntity::pEventHandler(&CDevil::H0x014c0007_WalkTo_04), DEBUGSTRING("CDevil::H0x014c0007_WalkTo_04")}, + {0x014c0008, -1, CEntity::pEventHandler(&CDevil::H0x014c0008_WalkTo_05), DEBUGSTRING("CDevil::H0x014c0008_WalkTo_05")}, + {0x014c0009, -1, CEntity::pEventHandler(&CDevil::H0x014c0009_WalkTo_06), DEBUGSTRING("CDevil::H0x014c0009_WalkTo_06")}, + {0x014c000a, -1, CEntity::pEventHandler(&CDevil:: +#line 1187 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +DestroyCity),DEBUGSTRING("CDevil::DestroyCity")}, + {0x014c000b, -1, CEntity::pEventHandler(&CDevil::H0x014c000b_DestroyCity_01), DEBUGSTRING("CDevil::H0x014c000b_DestroyCity_01")}, + {0x014c000c, -1, CEntity::pEventHandler(&CDevil::H0x014c000c_DestroyCity_02), DEBUGSTRING("CDevil::H0x014c000c_DestroyCity_02")}, + {0x014c000d, -1, CEntity::pEventHandler(&CDevil::H0x014c000d_DestroyCity_03), DEBUGSTRING("CDevil::H0x014c000d_DestroyCity_03")}, + {0x014c000e, -1, CEntity::pEventHandler(&CDevil::H0x014c000e_DestroyCity_04), DEBUGSTRING("CDevil::H0x014c000e_DestroyCity_04")}, + {0x014c000f, -1, CEntity::pEventHandler(&CDevil::H0x014c000f_DestroyCity_05), DEBUGSTRING("CDevil::H0x014c000f_DestroyCity_05")}, + {0x014c0010, -1, CEntity::pEventHandler(&CDevil::H0x014c0010_DestroyCity_06), DEBUGSTRING("CDevil::H0x014c0010_DestroyCity_06")}, + {0x014c0011, -1, CEntity::pEventHandler(&CDevil::H0x014c0011_DestroyCity_07), DEBUGSTRING("CDevil::H0x014c0011_DestroyCity_07")}, + {0x014c0012, -1, CEntity::pEventHandler(&CDevil::H0x014c0012_DestroyCity_08), DEBUGSTRING("CDevil::H0x014c0012_DestroyCity_08")}, + {0x014c0013, -1, CEntity::pEventHandler(&CDevil::H0x014c0013_DestroyCity_09), DEBUGSTRING("CDevil::H0x014c0013_DestroyCity_09")}, + {0x014c0014, -1, CEntity::pEventHandler(&CDevil::H0x014c0014_DestroyCity_10), DEBUGSTRING("CDevil::H0x014c0014_DestroyCity_10")}, + {0x014c0015, -1, CEntity::pEventHandler(&CDevil::H0x014c0015_DestroyCity_11), DEBUGSTRING("CDevil::H0x014c0015_DestroyCity_11")}, + {0x014c0016, -1, CEntity::pEventHandler(&CDevil::H0x014c0016_DestroyCity_12), DEBUGSTRING("CDevil::H0x014c0016_DestroyCity_12")}, + {0x014c0017, -1, CEntity::pEventHandler(&CDevil::H0x014c0017_DestroyCity_13), DEBUGSTRING("CDevil::H0x014c0017_DestroyCity_13")}, + {0x014c0018, -1, CEntity::pEventHandler(&CDevil::H0x014c0018_DestroyCity_14), DEBUGSTRING("CDevil::H0x014c0018_DestroyCity_14")}, + {0x014c0019, -1, CEntity::pEventHandler(&CDevil::H0x014c0019_DestroyCity_15), DEBUGSTRING("CDevil::H0x014c0019_DestroyCity_15")}, + {0x014c001a, -1, CEntity::pEventHandler(&CDevil::H0x014c001a_DestroyCity_16), DEBUGSTRING("CDevil::H0x014c001a_DestroyCity_16")}, + {0x014c001b, -1, CEntity::pEventHandler(&CDevil::H0x014c001b_DestroyCity_17), DEBUGSTRING("CDevil::H0x014c001b_DestroyCity_17")}, + {0x014c001c, -1, CEntity::pEventHandler(&CDevil::H0x014c001c_DestroyCity_18), DEBUGSTRING("CDevil::H0x014c001c_DestroyCity_18")}, + {0x014c001d, -1, CEntity::pEventHandler(&CDevil::H0x014c001d_DestroyCity_19), DEBUGSTRING("CDevil::H0x014c001d_DestroyCity_19")}, + {0x014c001e, -1, CEntity::pEventHandler(&CDevil::H0x014c001e_DestroyCity_20), DEBUGSTRING("CDevil::H0x014c001e_DestroyCity_20")}, + {0x014c001f, -1, CEntity::pEventHandler(&CDevil::H0x014c001f_DestroyCity_21), DEBUGSTRING("CDevil::H0x014c001f_DestroyCity_21")}, + {0x014c0020, -1, CEntity::pEventHandler(&CDevil::H0x014c0020_DestroyCity_22), DEBUGSTRING("CDevil::H0x014c0020_DestroyCity_22")}, + {0x014c0021, -1, CEntity::pEventHandler(&CDevil::H0x014c0021_DestroyCity_23), DEBUGSTRING("CDevil::H0x014c0021_DestroyCity_23")}, + {0x014c0022, -1, CEntity::pEventHandler(&CDevil::H0x014c0022_DestroyCity_24), DEBUGSTRING("CDevil::H0x014c0022_DestroyCity_24")}, + {0x014c0023, -1, CEntity::pEventHandler(&CDevil::H0x014c0023_DestroyCity_25), DEBUGSTRING("CDevil::H0x014c0023_DestroyCity_25")}, + {0x014c0024, -1, CEntity::pEventHandler(&CDevil::H0x014c0024_DestroyCity_26), DEBUGSTRING("CDevil::H0x014c0024_DestroyCity_26")}, + {0x014c0025, -1, CEntity::pEventHandler(&CDevil::H0x014c0025_DestroyCity_27), DEBUGSTRING("CDevil::H0x014c0025_DestroyCity_27")}, + {0x014c0026, -1, CEntity::pEventHandler(&CDevil::H0x014c0026_DestroyCity_28), DEBUGSTRING("CDevil::H0x014c0026_DestroyCity_28")}, + {0x014c0027, -1, CEntity::pEventHandler(&CDevil::H0x014c0027_DestroyCity_29), DEBUGSTRING("CDevil::H0x014c0027_DestroyCity_29")}, + {0x014c0028, -1, CEntity::pEventHandler(&CDevil::H0x014c0028_DestroyCity_30), DEBUGSTRING("CDevil::H0x014c0028_DestroyCity_30")}, + {0x014c0029, -1, CEntity::pEventHandler(&CDevil::H0x014c0029_DestroyCity_31), DEBUGSTRING("CDevil::H0x014c0029_DestroyCity_31")}, + {0x014c002a, -1, CEntity::pEventHandler(&CDevil::H0x014c002a_DestroyCity_32), DEBUGSTRING("CDevil::H0x014c002a_DestroyCity_32")}, + {0x014c002b, -1, CEntity::pEventHandler(&CDevil::H0x014c002b_DestroyCity_33), DEBUGSTRING("CDevil::H0x014c002b_DestroyCity_33")}, + {0x014c002c, -1, CEntity::pEventHandler(&CDevil::H0x014c002c_DestroyCity_34), DEBUGSTRING("CDevil::H0x014c002c_DestroyCity_34")}, + {0x014c002d, -1, CEntity::pEventHandler(&CDevil::H0x014c002d_DestroyCity_35), DEBUGSTRING("CDevil::H0x014c002d_DestroyCity_35")}, + {0x014c002e, -1, CEntity::pEventHandler(&CDevil::H0x014c002e_DestroyCity_36), DEBUGSTRING("CDevil::H0x014c002e_DestroyCity_36")}, + {0x014c002f, -1, CEntity::pEventHandler(&CDevil::H0x014c002f_DestroyCity_37), DEBUGSTRING("CDevil::H0x014c002f_DestroyCity_37")}, + {0x014c0030, -1, CEntity::pEventHandler(&CDevil::H0x014c0030_DestroyCity_38), DEBUGSTRING("CDevil::H0x014c0030_DestroyCity_38")}, + {0x014c0031, -1, CEntity::pEventHandler(&CDevil::H0x014c0031_DestroyCity_39), DEBUGSTRING("CDevil::H0x014c0031_DestroyCity_39")}, + {0x014c0032, -1, CEntity::pEventHandler(&CDevil:: +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WaitCurrentAnimEnd),DEBUGSTRING("CDevil::WaitCurrentAnimEnd")}, + {0x014c0033, -1, CEntity::pEventHandler(&CDevil::H0x014c0033_WaitCurrentAnimEnd_01), DEBUGSTRING("CDevil::H0x014c0033_WaitCurrentAnimEnd_01")}, + {0x014c0034, -1, CEntity::pEventHandler(&CDevil::H0x014c0034_WaitCurrentAnimEnd_02), DEBUGSTRING("CDevil::H0x014c0034_WaitCurrentAnimEnd_02")}, + {0x014c0035, -1, CEntity::pEventHandler(&CDevil::H0x014c0035_WaitCurrentAnimEnd_03), DEBUGSTRING("CDevil::H0x014c0035_WaitCurrentAnimEnd_03")}, + {0x014c0036, -1, CEntity::pEventHandler(&CDevil::H0x014c0036_WaitCurrentAnimEnd_04), DEBUGSTRING("CDevil::H0x014c0036_WaitCurrentAnimEnd_04")}, + {0x014c0037, -1, CEntity::pEventHandler(&CDevil::H0x014c0037_WaitCurrentAnimEnd_05), DEBUGSTRING("CDevil::H0x014c0037_WaitCurrentAnimEnd_05")}, + {0x014c0038, -1, CEntity::pEventHandler(&CDevil::H0x014c0038_WaitCurrentAnimEnd_06), DEBUGSTRING("CDevil::H0x014c0038_WaitCurrentAnimEnd_06")}, + {0x014c0039, -1, CEntity::pEventHandler(&CDevil:: +#line 1262 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WaitWalkToEnd),DEBUGSTRING("CDevil::WaitWalkToEnd")}, + {0x014c003a, -1, CEntity::pEventHandler(&CDevil::H0x014c003a_WaitWalkToEnd_01), DEBUGSTRING("CDevil::H0x014c003a_WaitWalkToEnd_01")}, + {0x014c003b, -1, CEntity::pEventHandler(&CDevil::H0x014c003b_WaitWalkToEnd_02), DEBUGSTRING("CDevil::H0x014c003b_WaitWalkToEnd_02")}, + {0x014c003c, -1, CEntity::pEventHandler(&CDevil::H0x014c003c_WaitWalkToEnd_03), DEBUGSTRING("CDevil::H0x014c003c_WaitWalkToEnd_03")}, + {0x014c003d, -1, CEntity::pEventHandler(&CDevil::H0x014c003d_WaitWalkToEnd_04), DEBUGSTRING("CDevil::H0x014c003d_WaitWalkToEnd_04")}, + {0x014c003e, -1, CEntity::pEventHandler(&CDevil::H0x014c003e_WaitWalkToEnd_05), DEBUGSTRING("CDevil::H0x014c003e_WaitWalkToEnd_05")}, + {0x014c003f, -1, CEntity::pEventHandler(&CDevil::H0x014c003f_WaitWalkToEnd_06), DEBUGSTRING("CDevil::H0x014c003f_WaitWalkToEnd_06")}, + {0x014c0040, -1, CEntity::pEventHandler(&CDevil::H0x014c0040_WaitWalkToEnd_07), DEBUGSTRING("CDevil::H0x014c0040_WaitWalkToEnd_07")}, + {0x014c0041, -1, CEntity::pEventHandler(&CDevil:: +#line 1274 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +WaitWalkOrIdleToEnd),DEBUGSTRING("CDevil::WaitWalkOrIdleToEnd")}, + {0x014c0042, -1, CEntity::pEventHandler(&CDevil::H0x014c0042_WaitWalkOrIdleToEnd_01), DEBUGSTRING("CDevil::H0x014c0042_WaitWalkOrIdleToEnd_01")}, + {0x014c0043, -1, CEntity::pEventHandler(&CDevil::H0x014c0043_WaitWalkOrIdleToEnd_02), DEBUGSTRING("CDevil::H0x014c0043_WaitWalkOrIdleToEnd_02")}, + {0x014c0044, -1, CEntity::pEventHandler(&CDevil::H0x014c0044_WaitWalkOrIdleToEnd_03), DEBUGSTRING("CDevil::H0x014c0044_WaitWalkOrIdleToEnd_03")}, + {0x014c0045, -1, CEntity::pEventHandler(&CDevil::H0x014c0045_WaitWalkOrIdleToEnd_04), DEBUGSTRING("CDevil::H0x014c0045_WaitWalkOrIdleToEnd_04")}, + {0x014c0046, -1, CEntity::pEventHandler(&CDevil::H0x014c0046_WaitWalkOrIdleToEnd_05), DEBUGSTRING("CDevil::H0x014c0046_WaitWalkOrIdleToEnd_05")}, + {0x014c0047, -1, CEntity::pEventHandler(&CDevil::H0x014c0047_WaitWalkOrIdleToEnd_06), DEBUGSTRING("CDevil::H0x014c0047_WaitWalkOrIdleToEnd_06")}, + {0x014c0048, -1, CEntity::pEventHandler(&CDevil::H0x014c0048_WaitWalkOrIdleToEnd_07), DEBUGSTRING("CDevil::H0x014c0048_WaitWalkOrIdleToEnd_07")}, + {0x014c0049, -1, CEntity::pEventHandler(&CDevil::H0x014c0049_WaitWalkOrIdleToEnd_08), DEBUGSTRING("CDevil::H0x014c0049_WaitWalkOrIdleToEnd_08")}, + {0x014c004a, -1, CEntity::pEventHandler(&CDevil::H0x014c004a_WaitWalkOrIdleToEnd_09), DEBUGSTRING("CDevil::H0x014c004a_WaitWalkOrIdleToEnd_09")}, + {0x014c004b, -1, CEntity::pEventHandler(&CDevil::H0x014c004b_WaitWalkOrIdleToEnd_10), DEBUGSTRING("CDevil::H0x014c004b_WaitWalkOrIdleToEnd_10")}, + {0x014c004c, -1, CEntity::pEventHandler(&CDevil::H0x014c004c_WaitWalkOrIdleToEnd_11), DEBUGSTRING("CDevil::H0x014c004c_WaitWalkOrIdleToEnd_11")}, + {0x014c004d, -1, CEntity::pEventHandler(&CDevil::H0x014c004d_WaitWalkOrIdleToEnd_12), DEBUGSTRING("CDevil::H0x014c004d_WaitWalkOrIdleToEnd_12")}, + {0x014c004e, -1, CEntity::pEventHandler(&CDevil::H0x014c004e_WaitWalkOrIdleToEnd_13), DEBUGSTRING("CDevil::H0x014c004e_WaitWalkOrIdleToEnd_13")}, + {0x014c004f, -1, CEntity::pEventHandler(&CDevil::H0x014c004f_WaitWalkOrIdleToEnd_14), DEBUGSTRING("CDevil::H0x014c004f_WaitWalkOrIdleToEnd_14")}, + {0x014c0050, -1, CEntity::pEventHandler(&CDevil::H0x014c0050_WaitWalkOrIdleToEnd_15), DEBUGSTRING("CDevil::H0x014c0050_WaitWalkOrIdleToEnd_15")}, + {0x014c0051, -1, CEntity::pEventHandler(&CDevil:: +#line 1295 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Rise),DEBUGSTRING("CDevil::Rise")}, + {0x014c0052, -1, CEntity::pEventHandler(&CDevil::H0x014c0052_Rise_01), DEBUGSTRING("CDevil::H0x014c0052_Rise_01")}, + {0x014c0053, -1, CEntity::pEventHandler(&CDevil::H0x014c0053_Rise_02), DEBUGSTRING("CDevil::H0x014c0053_Rise_02")}, + {0x014c0054, -1, CEntity::pEventHandler(&CDevil:: +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Celebrate),DEBUGSTRING("CDevil::Celebrate")}, + {0x014c0055, -1, CEntity::pEventHandler(&CDevil::H0x014c0055_Celebrate_01), DEBUGSTRING("CDevil::H0x014c0055_Celebrate_01")}, + {0x014c0056, -1, CEntity::pEventHandler(&CDevil::H0x014c0056_Celebrate_02), DEBUGSTRING("CDevil::H0x014c0056_Celebrate_02")}, + {0x014c0057, -1, CEntity::pEventHandler(&CDevil::H0x014c0057_Celebrate_03), DEBUGSTRING("CDevil::H0x014c0057_Celebrate_03")}, + {0x014c0058, -1, CEntity::pEventHandler(&CDevil::H0x014c0058_Celebrate_04), DEBUGSTRING("CDevil::H0x014c0058_Celebrate_04")}, + {0x014c0059, -1, CEntity::pEventHandler(&CDevil:: +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Angry),DEBUGSTRING("CDevil::Angry")}, + {0x014c005a, -1, CEntity::pEventHandler(&CDevil::H0x014c005a_Angry_01), DEBUGSTRING("CDevil::H0x014c005a_Angry_01")}, + {0x014c005b, -1, CEntity::pEventHandler(&CDevil::H0x014c005b_Angry_02), DEBUGSTRING("CDevil::H0x014c005b_Angry_02")}, + {0x014c005c, -1, CEntity::pEventHandler(&CDevil::H0x014c005c_Angry_03), DEBUGSTRING("CDevil::H0x014c005c_Angry_03")}, + {0x014c005d, -1, CEntity::pEventHandler(&CDevil::H0x014c005d_Angry_04), DEBUGSTRING("CDevil::H0x014c005d_Angry_04")}, + {0x014c005e, -1, CEntity::pEventHandler(&CDevil::H0x014c005e_Angry_05), DEBUGSTRING("CDevil::H0x014c005e_Angry_05")}, + {0x014c005f, -1, CEntity::pEventHandler(&CDevil::H0x014c005f_Angry_06), DEBUGSTRING("CDevil::H0x014c005f_Angry_06")}, + {0x014c0060, -1, CEntity::pEventHandler(&CDevil:: +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SubBeamDamage1),DEBUGSTRING("CDevil::SubBeamDamage1")}, + {0x014c0061, -1, CEntity::pEventHandler(&CDevil::H0x014c0061_SubBeamDamage1_01), DEBUGSTRING("CDevil::H0x014c0061_SubBeamDamage1_01")}, + {0x014c0062, -1, CEntity::pEventHandler(&CDevil::H0x014c0062_SubBeamDamage1_02), DEBUGSTRING("CDevil::H0x014c0062_SubBeamDamage1_02")}, + {0x014c0063, -1, CEntity::pEventHandler(&CDevil:: +#line 1334 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SubBeamDamage2),DEBUGSTRING("CDevil::SubBeamDamage2")}, + {0x014c0064, -1, CEntity::pEventHandler(&CDevil::H0x014c0064_SubBeamDamage2_01), DEBUGSTRING("CDevil::H0x014c0064_SubBeamDamage2_01")}, + {0x014c0065, -1, CEntity::pEventHandler(&CDevil::H0x014c0065_SubBeamDamage2_02), DEBUGSTRING("CDevil::H0x014c0065_SubBeamDamage2_02")}, + {0x014c0066, -1, CEntity::pEventHandler(&CDevil::H0x014c0066_SubBeamDamage2_03), DEBUGSTRING("CDevil::H0x014c0066_SubBeamDamage2_03")}, + {0x014c0067, -1, CEntity::pEventHandler(&CDevil::H0x014c0067_SubBeamDamage2_04), DEBUGSTRING("CDevil::H0x014c0067_SubBeamDamage2_04")}, + {0x014c0068, -1, CEntity::pEventHandler(&CDevil:: +#line 1348 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +SubBeamDamage3),DEBUGSTRING("CDevil::SubBeamDamage3")}, + {0x014c0069, -1, CEntity::pEventHandler(&CDevil::H0x014c0069_SubBeamDamage3_01), DEBUGSTRING("CDevil::H0x014c0069_SubBeamDamage3_01")}, + {0x014c006a, -1, CEntity::pEventHandler(&CDevil::H0x014c006a_SubBeamDamage3_02), DEBUGSTRING("CDevil::H0x014c006a_SubBeamDamage3_02")}, + {0x014c006b, -1, CEntity::pEventHandler(&CDevil:: +#line 1355 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BeamDamage),DEBUGSTRING("CDevil::BeamDamage")}, + {0x014c006c, -1, CEntity::pEventHandler(&CDevil::H0x014c006c_BeamDamage_01), DEBUGSTRING("CDevil::H0x014c006c_BeamDamage_01")}, + {0x014c006d, -1, CEntity::pEventHandler(&CDevil::H0x014c006d_BeamDamage_02), DEBUGSTRING("CDevil::H0x014c006d_BeamDamage_02")}, + {0x014c006e, -1, CEntity::pEventHandler(&CDevil:: +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Smash),DEBUGSTRING("CDevil::Smash")}, + {0x014c006f, -1, CEntity::pEventHandler(&CDevil::H0x014c006f_Smash_01), DEBUGSTRING("CDevil::H0x014c006f_Smash_01")}, + {0x014c0070, -1, CEntity::pEventHandler(&CDevil::H0x014c0070_Smash_02), DEBUGSTRING("CDevil::H0x014c0070_Smash_02")}, + {0x014c0071, -1, CEntity::pEventHandler(&CDevil::H0x014c0071_Smash_03), DEBUGSTRING("CDevil::H0x014c0071_Smash_03")}, + {0x014c0072, -1, CEntity::pEventHandler(&CDevil::H0x014c0072_Smash_04), DEBUGSTRING("CDevil::H0x014c0072_Smash_04")}, + {0x014c0073, -1, CEntity::pEventHandler(&CDevil::H0x014c0073_Smash_05), DEBUGSTRING("CDevil::H0x014c0073_Smash_05")}, + {0x014c0074, -1, CEntity::pEventHandler(&CDevil::H0x014c0074_Smash_06), DEBUGSTRING("CDevil::H0x014c0074_Smash_06")}, + {0x014c0075, -1, CEntity::pEventHandler(&CDevil::H0x014c0075_Smash_07), DEBUGSTRING("CDevil::H0x014c0075_Smash_07")}, + {0x014c0076, -1, CEntity::pEventHandler(&CDevil::H0x014c0076_Smash_08), DEBUGSTRING("CDevil::H0x014c0076_Smash_08")}, + {0x014c0077, -1, CEntity::pEventHandler(&CDevil::H0x014c0077_Smash_09), DEBUGSTRING("CDevil::H0x014c0077_Smash_09")}, + {0x014c0078, -1, CEntity::pEventHandler(&CDevil::H0x014c0078_Smash_10), DEBUGSTRING("CDevil::H0x014c0078_Smash_10")}, + {0x014c0079, -1, CEntity::pEventHandler(&CDevil:: +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Punch),DEBUGSTRING("CDevil::Punch")}, + {0x014c007a, -1, CEntity::pEventHandler(&CDevil::H0x014c007a_Punch_01), DEBUGSTRING("CDevil::H0x014c007a_Punch_01")}, + {0x014c007b, -1, CEntity::pEventHandler(&CDevil::H0x014c007b_Punch_02), DEBUGSTRING("CDevil::H0x014c007b_Punch_02")}, + {0x014c007c, -1, CEntity::pEventHandler(&CDevil::H0x014c007c_Punch_03), DEBUGSTRING("CDevil::H0x014c007c_Punch_03")}, + {0x014c007d, -1, CEntity::pEventHandler(&CDevil::H0x014c007d_Punch_04), DEBUGSTRING("CDevil::H0x014c007d_Punch_04")}, + {0x014c007e, -1, CEntity::pEventHandler(&CDevil::H0x014c007e_Punch_05), DEBUGSTRING("CDevil::H0x014c007e_Punch_05")}, + {0x014c007f, -1, CEntity::pEventHandler(&CDevil::H0x014c007f_Punch_06), DEBUGSTRING("CDevil::H0x014c007f_Punch_06")}, + {0x014c0080, -1, CEntity::pEventHandler(&CDevil::H0x014c0080_Punch_07), DEBUGSTRING("CDevil::H0x014c0080_Punch_07")}, + {0x014c0081, -1, CEntity::pEventHandler(&CDevil::H0x014c0081_Punch_08), DEBUGSTRING("CDevil::H0x014c0081_Punch_08")}, + {0x014c0082, -1, CEntity::pEventHandler(&CDevil::H0x014c0082_Punch_09), DEBUGSTRING("CDevil::H0x014c0082_Punch_09")}, + {0x014c0083, -1, CEntity::pEventHandler(&CDevil::H0x014c0083_Punch_10), DEBUGSTRING("CDevil::H0x014c0083_Punch_10")}, + {0x014c0084, -1, CEntity::pEventHandler(&CDevil:: +#line 1429 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +HitGround),DEBUGSTRING("CDevil::HitGround")}, + {0x014c0085, -1, CEntity::pEventHandler(&CDevil::H0x014c0085_HitGround_01), DEBUGSTRING("CDevil::H0x014c0085_HitGround_01")}, + {0x014c0086, -1, CEntity::pEventHandler(&CDevil::H0x014c0086_HitGround_02), DEBUGSTRING("CDevil::H0x014c0086_HitGround_02")}, + {0x014c0087, -1, CEntity::pEventHandler(&CDevil::H0x014c0087_HitGround_03), DEBUGSTRING("CDevil::H0x014c0087_HitGround_03")}, + {0x014c0088, -1, CEntity::pEventHandler(&CDevil::H0x014c0088_HitGround_04), DEBUGSTRING("CDevil::H0x014c0088_HitGround_04")}, + {0x014c0089, -1, CEntity::pEventHandler(&CDevil:: +#line 1453 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GrabLowerWeapons),DEBUGSTRING("CDevil::GrabLowerWeapons")}, + {0x014c008a, -1, CEntity::pEventHandler(&CDevil::H0x014c008a_GrabLowerWeapons_01), DEBUGSTRING("CDevil::H0x014c008a_GrabLowerWeapons_01")}, + {0x014c008b, -1, CEntity::pEventHandler(&CDevil::H0x014c008b_GrabLowerWeapons_02), DEBUGSTRING("CDevil::H0x014c008b_GrabLowerWeapons_02")}, + {0x014c008c, -1, CEntity::pEventHandler(&CDevil::H0x014c008c_GrabLowerWeapons_03), DEBUGSTRING("CDevil::H0x014c008c_GrabLowerWeapons_03")}, + {0x014c008d, -1, CEntity::pEventHandler(&CDevil::H0x014c008d_GrabLowerWeapons_04), DEBUGSTRING("CDevil::H0x014c008d_GrabLowerWeapons_04")}, + {0x014c008e, -1, CEntity::pEventHandler(&CDevil::H0x014c008e_GrabLowerWeapons_05), DEBUGSTRING("CDevil::H0x014c008e_GrabLowerWeapons_05")}, + {0x014c008f, -1, CEntity::pEventHandler(&CDevil::H0x014c008f_GrabLowerWeapons_06), DEBUGSTRING("CDevil::H0x014c008f_GrabLowerWeapons_06")}, + {0x014c0090, -1, CEntity::pEventHandler(&CDevil::H0x014c0090_GrabLowerWeapons_07), DEBUGSTRING("CDevil::H0x014c0090_GrabLowerWeapons_07")}, + {0x014c0091, -1, CEntity::pEventHandler(&CDevil::H0x014c0091_GrabLowerWeapons_08), DEBUGSTRING("CDevil::H0x014c0091_GrabLowerWeapons_08")}, + {0x014c0092, -1, CEntity::pEventHandler(&CDevil:: +#line 1466 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GrabUpperWeapons),DEBUGSTRING("CDevil::GrabUpperWeapons")}, + {0x014c0093, -1, CEntity::pEventHandler(&CDevil::H0x014c0093_GrabUpperWeapons_01), DEBUGSTRING("CDevil::H0x014c0093_GrabUpperWeapons_01")}, + {0x014c0094, -1, CEntity::pEventHandler(&CDevil::H0x014c0094_GrabUpperWeapons_02), DEBUGSTRING("CDevil::H0x014c0094_GrabUpperWeapons_02")}, + {0x014c0095, -1, CEntity::pEventHandler(&CDevil::H0x014c0095_GrabUpperWeapons_03), DEBUGSTRING("CDevil::H0x014c0095_GrabUpperWeapons_03")}, + {0x014c0096, -1, CEntity::pEventHandler(&CDevil::H0x014c0096_GrabUpperWeapons_04), DEBUGSTRING("CDevil::H0x014c0096_GrabUpperWeapons_04")}, + {0x014c0097, -1, CEntity::pEventHandler(&CDevil::H0x014c0097_GrabUpperWeapons_05), DEBUGSTRING("CDevil::H0x014c0097_GrabUpperWeapons_05")}, + {0x014c0098, -1, CEntity::pEventHandler(&CDevil::H0x014c0098_GrabUpperWeapons_06), DEBUGSTRING("CDevil::H0x014c0098_GrabUpperWeapons_06")}, + {0x014c0099, -1, CEntity::pEventHandler(&CDevil::H0x014c0099_GrabUpperWeapons_07), DEBUGSTRING("CDevil::H0x014c0099_GrabUpperWeapons_07")}, + {0x014c009a, -1, CEntity::pEventHandler(&CDevil::H0x014c009a_GrabUpperWeapons_08), DEBUGSTRING("CDevil::H0x014c009a_GrabUpperWeapons_08")}, + {0x014c009b, -1, CEntity::pEventHandler(&CDevil:: +#line 1480 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +GrabBothWeapons),DEBUGSTRING("CDevil::GrabBothWeapons")}, + {0x014c009c, -1, CEntity::pEventHandler(&CDevil::H0x014c009c_GrabBothWeapons_01), DEBUGSTRING("CDevil::H0x014c009c_GrabBothWeapons_01")}, + {0x014c009d, -1, CEntity::pEventHandler(&CDevil::H0x014c009d_GrabBothWeapons_02), DEBUGSTRING("CDevil::H0x014c009d_GrabBothWeapons_02")}, + {0x014c009e, -1, CEntity::pEventHandler(&CDevil::H0x014c009e_GrabBothWeapons_03), DEBUGSTRING("CDevil::H0x014c009e_GrabBothWeapons_03")}, + {0x014c009f, -1, CEntity::pEventHandler(&CDevil::H0x014c009f_GrabBothWeapons_04), DEBUGSTRING("CDevil::H0x014c009f_GrabBothWeapons_04")}, + {0x014c00a0, -1, CEntity::pEventHandler(&CDevil::H0x014c00a0_GrabBothWeapons_05), DEBUGSTRING("CDevil::H0x014c00a0_GrabBothWeapons_05")}, + {0x014c00a1, -1, CEntity::pEventHandler(&CDevil::H0x014c00a1_GrabBothWeapons_06), DEBUGSTRING("CDevil::H0x014c00a1_GrabBothWeapons_06")}, + {0x014c00a2, -1, CEntity::pEventHandler(&CDevil::H0x014c00a2_GrabBothWeapons_07), DEBUGSTRING("CDevil::H0x014c00a2_GrabBothWeapons_07")}, + {0x014c00a3, -1, CEntity::pEventHandler(&CDevil::H0x014c00a3_GrabBothWeapons_08), DEBUGSTRING("CDevil::H0x014c00a3_GrabBothWeapons_08")}, + {0x014c00a4, -1, CEntity::pEventHandler(&CDevil::H0x014c00a4_GrabBothWeapons_09), DEBUGSTRING("CDevil::H0x014c00a4_GrabBothWeapons_09")}, + {0x014c00a5, -1, CEntity::pEventHandler(&CDevil::H0x014c00a5_GrabBothWeapons_10), DEBUGSTRING("CDevil::H0x014c00a5_GrabBothWeapons_10")}, + {0x014c00a6, -1, CEntity::pEventHandler(&CDevil::H0x014c00a6_GrabBothWeapons_11), DEBUGSTRING("CDevil::H0x014c00a6_GrabBothWeapons_11")}, + {0x014c00a7, -1, CEntity::pEventHandler(&CDevil::H0x014c00a7_GrabBothWeapons_12), DEBUGSTRING("CDevil::H0x014c00a7_GrabBothWeapons_12")}, + {0x014c00a8, STATE_CEnemyBase_PreMainLoop, CEntity::pEventHandler(&CDevil:: +#line 1499 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +PreMainLoop),DEBUGSTRING("CDevil::PreMainLoop")}, + {0x014c00a9, STATE_CEnemyBase_BeWounded, CEntity::pEventHandler(&CDevil:: +#line 1531 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +BeWounded),DEBUGSTRING("CDevil::BeWounded")}, + {0x014c00aa, -1, CEntity::pEventHandler(&CDevil::H0x014c00aa_BeWounded_01), DEBUGSTRING("CDevil::H0x014c00aa_BeWounded_01")}, + {0x014c00ab, -1, CEntity::pEventHandler(&CDevil::H0x014c00ab_BeWounded_02), DEBUGSTRING("CDevil::H0x014c00ab_BeWounded_02")}, + {0x014c00ac, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CDevil:: +#line 1542 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Hit),DEBUGSTRING("CDevil::Hit")}, + {0x014c00ad, -1, CEntity::pEventHandler(&CDevil::H0x014c00ad_Hit_01), DEBUGSTRING("CDevil::H0x014c00ad_Hit_01")}, + {0x014c00ae, -1, CEntity::pEventHandler(&CDevil::H0x014c00ae_Hit_02), DEBUGSTRING("CDevil::H0x014c00ae_Hit_02")}, + {0x014c00af, -1, CEntity::pEventHandler(&CDevil::H0x014c00af_Hit_03), DEBUGSTRING("CDevil::H0x014c00af_Hit_03")}, + {0x014c00b0, -1, CEntity::pEventHandler(&CDevil::H0x014c00b0_Hit_04), DEBUGSTRING("CDevil::H0x014c00b0_Hit_04")}, + {0x014c00b1, -1, CEntity::pEventHandler(&CDevil::H0x014c00b1_Hit_05), DEBUGSTRING("CDevil::H0x014c00b1_Hit_05")}, + {0x014c00b2, -1, CEntity::pEventHandler(&CDevil::H0x014c00b2_Hit_06), DEBUGSTRING("CDevil::H0x014c00b2_Hit_06")}, + {0x014c00b3, -1, CEntity::pEventHandler(&CDevil::H0x014c00b3_Hit_07), DEBUGSTRING("CDevil::H0x014c00b3_Hit_07")}, + {0x014c00b4, -1, CEntity::pEventHandler(&CDevil::H0x014c00b4_Hit_08), DEBUGSTRING("CDevil::H0x014c00b4_Hit_08")}, + {0x014c00b5, STATE_CEnemyBase_InitializeAttack, CEntity::pEventHandler(&CDevil:: +#line 1564 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +InitializeAttack),DEBUGSTRING("CDevil::InitializeAttack")}, + {0x014c00b6, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CDevil:: +#line 1568 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Fire),DEBUGSTRING("CDevil::Fire")}, + {0x014c00b7, -1, CEntity::pEventHandler(&CDevil:: +#line 1639 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +DevilLockOnEnemy),DEBUGSTRING("CDevil::DevilLockOnEnemy")}, + {0x014c00b8, -1, CEntity::pEventHandler(&CDevil::H0x014c00b8_DevilLockOnEnemy_01), DEBUGSTRING("CDevil::H0x014c00b8_DevilLockOnEnemy_01")}, + {0x014c00b9, -1, CEntity::pEventHandler(&CDevil::H0x014c00b9_DevilLockOnEnemy_02), DEBUGSTRING("CDevil::H0x014c00b9_DevilLockOnEnemy_02")}, + {0x014c00ba, -1, CEntity::pEventHandler(&CDevil::H0x014c00ba_DevilLockOnEnemy_03), DEBUGSTRING("CDevil::H0x014c00ba_DevilLockOnEnemy_03")}, + {0x014c00bb, -1, CEntity::pEventHandler(&CDevil::H0x014c00bb_DevilLockOnEnemy_04), DEBUGSTRING("CDevil::H0x014c00bb_DevilLockOnEnemy_04")}, + {0x014c00bc, -1, CEntity::pEventHandler(&CDevil:: +#line 1682 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +AdjustWeaponForFire),DEBUGSTRING("CDevil::AdjustWeaponForFire")}, + {0x014c00bd, -1, CEntity::pEventHandler(&CDevil::H0x014c00bd_AdjustWeaponForFire_01), DEBUGSTRING("CDevil::H0x014c00bd_AdjustWeaponForFire_01")}, + {0x014c00be, -1, CEntity::pEventHandler(&CDevil::H0x014c00be_AdjustWeaponForFire_02), DEBUGSTRING("CDevil::H0x014c00be_AdjustWeaponForFire_02")}, + {0x014c00bf, -1, CEntity::pEventHandler(&CDevil::H0x014c00bf_AdjustWeaponForFire_03), DEBUGSTRING("CDevil::H0x014c00bf_AdjustWeaponForFire_03")}, + {0x014c00c0, -1, CEntity::pEventHandler(&CDevil::H0x014c00c0_AdjustWeaponForFire_04), DEBUGSTRING("CDevil::H0x014c00c0_AdjustWeaponForFire_04")}, + {0x014c00c1, -1, CEntity::pEventHandler(&CDevil:: +#line 1726 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StraightenUpWeapon),DEBUGSTRING("CDevil::StraightenUpWeapon")}, + {0x014c00c2, -1, CEntity::pEventHandler(&CDevil::H0x014c00c2_StraightenUpWeapon_01), DEBUGSTRING("CDevil::H0x014c00c2_StraightenUpWeapon_01")}, + {0x014c00c3, -1, CEntity::pEventHandler(&CDevil::H0x014c00c3_StraightenUpWeapon_02), DEBUGSTRING("CDevil::H0x014c00c3_StraightenUpWeapon_02")}, + {0x014c00c4, -1, CEntity::pEventHandler(&CDevil::H0x014c00c4_StraightenUpWeapon_03), DEBUGSTRING("CDevil::H0x014c00c4_StraightenUpWeapon_03")}, + {0x014c00c5, -1, CEntity::pEventHandler(&CDevil::H0x014c00c5_StraightenUpWeapon_04), DEBUGSTRING("CDevil::H0x014c00c5_StraightenUpWeapon_04")}, + {0x014c00c6, -1, CEntity::pEventHandler(&CDevil:: +#line 1751 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireLaser),DEBUGSTRING("CDevil::FireLaser")}, + {0x014c00c7, -1, CEntity::pEventHandler(&CDevil::H0x014c00c7_FireLaser_01), DEBUGSTRING("CDevil::H0x014c00c7_FireLaser_01")}, + {0x014c00c8, -1, CEntity::pEventHandler(&CDevil::H0x014c00c8_FireLaser_02), DEBUGSTRING("CDevil::H0x014c00c8_FireLaser_02")}, + {0x014c00c9, -1, CEntity::pEventHandler(&CDevil::H0x014c00c9_FireLaser_03), DEBUGSTRING("CDevil::H0x014c00c9_FireLaser_03")}, + {0x014c00ca, -1, CEntity::pEventHandler(&CDevil::H0x014c00ca_FireLaser_04), DEBUGSTRING("CDevil::H0x014c00ca_FireLaser_04")}, + {0x014c00cb, -1, CEntity::pEventHandler(&CDevil::H0x014c00cb_FireLaser_05), DEBUGSTRING("CDevil::H0x014c00cb_FireLaser_05")}, + {0x014c00cc, -1, CEntity::pEventHandler(&CDevil::H0x014c00cc_FireLaser_06), DEBUGSTRING("CDevil::H0x014c00cc_FireLaser_06")}, + {0x014c00cd, -1, CEntity::pEventHandler(&CDevil::H0x014c00cd_FireLaser_07), DEBUGSTRING("CDevil::H0x014c00cd_FireLaser_07")}, + {0x014c00ce, -1, CEntity::pEventHandler(&CDevil::H0x014c00ce_FireLaser_08), DEBUGSTRING("CDevil::H0x014c00ce_FireLaser_08")}, + {0x014c00cf, -1, CEntity::pEventHandler(&CDevil::H0x014c00cf_FireLaser_09), DEBUGSTRING("CDevil::H0x014c00cf_FireLaser_09")}, + {0x014c00d0, -1, CEntity::pEventHandler(&CDevil::H0x014c00d0_FireLaser_10), DEBUGSTRING("CDevil::H0x014c00d0_FireLaser_10")}, + {0x014c00d1, -1, CEntity::pEventHandler(&CDevil::H0x014c00d1_FireLaser_11), DEBUGSTRING("CDevil::H0x014c00d1_FireLaser_11")}, + {0x014c00d2, -1, CEntity::pEventHandler(&CDevil::H0x014c00d2_FireLaser_12), DEBUGSTRING("CDevil::H0x014c00d2_FireLaser_12")}, + {0x014c00d3, -1, CEntity::pEventHandler(&CDevil::H0x014c00d3_FireLaser_13), DEBUGSTRING("CDevil::H0x014c00d3_FireLaser_13")}, + {0x014c00d4, -1, CEntity::pEventHandler(&CDevil::H0x014c00d4_FireLaser_14), DEBUGSTRING("CDevil::H0x014c00d4_FireLaser_14")}, + {0x014c00d5, -1, CEntity::pEventHandler(&CDevil:: +#line 1798 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireRocketLauncher),DEBUGSTRING("CDevil::FireRocketLauncher")}, + {0x014c00d6, -1, CEntity::pEventHandler(&CDevil::H0x014c00d6_FireRocketLauncher_01), DEBUGSTRING("CDevil::H0x014c00d6_FireRocketLauncher_01")}, + {0x014c00d7, -1, CEntity::pEventHandler(&CDevil::H0x014c00d7_FireRocketLauncher_02), DEBUGSTRING("CDevil::H0x014c00d7_FireRocketLauncher_02")}, + {0x014c00d8, -1, CEntity::pEventHandler(&CDevil::H0x014c00d8_FireRocketLauncher_03), DEBUGSTRING("CDevil::H0x014c00d8_FireRocketLauncher_03")}, + {0x014c00d9, -1, CEntity::pEventHandler(&CDevil::H0x014c00d9_FireRocketLauncher_04), DEBUGSTRING("CDevil::H0x014c00d9_FireRocketLauncher_04")}, + {0x014c00da, -1, CEntity::pEventHandler(&CDevil::H0x014c00da_FireRocketLauncher_05), DEBUGSTRING("CDevil::H0x014c00da_FireRocketLauncher_05")}, + {0x014c00db, -1, CEntity::pEventHandler(&CDevil::H0x014c00db_FireRocketLauncher_06), DEBUGSTRING("CDevil::H0x014c00db_FireRocketLauncher_06")}, + {0x014c00dc, -1, CEntity::pEventHandler(&CDevil::H0x014c00dc_FireRocketLauncher_07), DEBUGSTRING("CDevil::H0x014c00dc_FireRocketLauncher_07")}, + {0x014c00dd, -1, CEntity::pEventHandler(&CDevil::H0x014c00dd_FireRocketLauncher_08), DEBUGSTRING("CDevil::H0x014c00dd_FireRocketLauncher_08")}, + {0x014c00de, -1, CEntity::pEventHandler(&CDevil::H0x014c00de_FireRocketLauncher_09), DEBUGSTRING("CDevil::H0x014c00de_FireRocketLauncher_09")}, + {0x014c00df, -1, CEntity::pEventHandler(&CDevil::H0x014c00df_FireRocketLauncher_10), DEBUGSTRING("CDevil::H0x014c00df_FireRocketLauncher_10")}, + {0x014c00e0, -1, CEntity::pEventHandler(&CDevil::H0x014c00e0_FireRocketLauncher_11), DEBUGSTRING("CDevil::H0x014c00e0_FireRocketLauncher_11")}, + {0x014c00e1, -1, CEntity::pEventHandler(&CDevil::H0x014c00e1_FireRocketLauncher_12), DEBUGSTRING("CDevil::H0x014c00e1_FireRocketLauncher_12")}, + {0x014c00e2, -1, CEntity::pEventHandler(&CDevil::H0x014c00e2_FireRocketLauncher_13), DEBUGSTRING("CDevil::H0x014c00e2_FireRocketLauncher_13")}, + {0x014c00e3, -1, CEntity::pEventHandler(&CDevil::H0x014c00e3_FireRocketLauncher_14), DEBUGSTRING("CDevil::H0x014c00e3_FireRocketLauncher_14")}, + {0x014c00e4, -1, CEntity::pEventHandler(&CDevil:: +#line 1841 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FirePredictedProjectile),DEBUGSTRING("CDevil::FirePredictedProjectile")}, + {0x014c00e5, -1, CEntity::pEventHandler(&CDevil::H0x014c00e5_FirePredictedProjectile_01), DEBUGSTRING("CDevil::H0x014c00e5_FirePredictedProjectile_01")}, + {0x014c00e6, -1, CEntity::pEventHandler(&CDevil::H0x014c00e6_FirePredictedProjectile_02), DEBUGSTRING("CDevil::H0x014c00e6_FirePredictedProjectile_02")}, + {0x014c00e7, -1, CEntity::pEventHandler(&CDevil::H0x014c00e7_FirePredictedProjectile_03), DEBUGSTRING("CDevil::H0x014c00e7_FirePredictedProjectile_03")}, + {0x014c00e8, -1, CEntity::pEventHandler(&CDevil::H0x014c00e8_FirePredictedProjectile_04), DEBUGSTRING("CDevil::H0x014c00e8_FirePredictedProjectile_04")}, + {0x014c00e9, -1, CEntity::pEventHandler(&CDevil::H0x014c00e9_FirePredictedProjectile_05), DEBUGSTRING("CDevil::H0x014c00e9_FirePredictedProjectile_05")}, + {0x014c00ea, -1, CEntity::pEventHandler(&CDevil::H0x014c00ea_FirePredictedProjectile_06), DEBUGSTRING("CDevil::H0x014c00ea_FirePredictedProjectile_06")}, + {0x014c00eb, -1, CEntity::pEventHandler(&CDevil::H0x014c00eb_FirePredictedProjectile_07), DEBUGSTRING("CDevil::H0x014c00eb_FirePredictedProjectile_07")}, + {0x014c00ec, -1, CEntity::pEventHandler(&CDevil::H0x014c00ec_FirePredictedProjectile_08), DEBUGSTRING("CDevil::H0x014c00ec_FirePredictedProjectile_08")}, + {0x014c00ed, -1, CEntity::pEventHandler(&CDevil::H0x014c00ed_FirePredictedProjectile_09), DEBUGSTRING("CDevil::H0x014c00ed_FirePredictedProjectile_09")}, + {0x014c00ee, -1, CEntity::pEventHandler(&CDevil::H0x014c00ee_FirePredictedProjectile_10), DEBUGSTRING("CDevil::H0x014c00ee_FirePredictedProjectile_10")}, + {0x014c00ef, -1, CEntity::pEventHandler(&CDevil::H0x014c00ef_FirePredictedProjectile_11), DEBUGSTRING("CDevil::H0x014c00ef_FirePredictedProjectile_11")}, + {0x014c00f0, -1, CEntity::pEventHandler(&CDevil::H0x014c00f0_FirePredictedProjectile_12), DEBUGSTRING("CDevil::H0x014c00f0_FirePredictedProjectile_12")}, + {0x014c00f1, -1, CEntity::pEventHandler(&CDevil::H0x014c00f1_FirePredictedProjectile_13), DEBUGSTRING("CDevil::H0x014c00f1_FirePredictedProjectile_13")}, + {0x014c00f2, -1, CEntity::pEventHandler(&CDevil::H0x014c00f2_FirePredictedProjectile_14), DEBUGSTRING("CDevil::H0x014c00f2_FirePredictedProjectile_14")}, + {0x014c00f3, -1, CEntity::pEventHandler(&CDevil:: +#line 1882 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireElectricityGun),DEBUGSTRING("CDevil::FireElectricityGun")}, + {0x014c00f4, -1, CEntity::pEventHandler(&CDevil::H0x014c00f4_FireElectricityGun_01), DEBUGSTRING("CDevil::H0x014c00f4_FireElectricityGun_01")}, + {0x014c00f5, -1, CEntity::pEventHandler(&CDevil::H0x014c00f5_FireElectricityGun_02), DEBUGSTRING("CDevil::H0x014c00f5_FireElectricityGun_02")}, + {0x014c00f6, -1, CEntity::pEventHandler(&CDevil::H0x014c00f6_FireElectricityGun_03), DEBUGSTRING("CDevil::H0x014c00f6_FireElectricityGun_03")}, + {0x014c00f7, -1, CEntity::pEventHandler(&CDevil::H0x014c00f7_FireElectricityGun_04), DEBUGSTRING("CDevil::H0x014c00f7_FireElectricityGun_04")}, + {0x014c00f8, -1, CEntity::pEventHandler(&CDevil::H0x014c00f8_FireElectricityGun_05), DEBUGSTRING("CDevil::H0x014c00f8_FireElectricityGun_05")}, + {0x014c00f9, -1, CEntity::pEventHandler(&CDevil::H0x014c00f9_FireElectricityGun_06), DEBUGSTRING("CDevil::H0x014c00f9_FireElectricityGun_06")}, + {0x014c00fa, -1, CEntity::pEventHandler(&CDevil::H0x014c00fa_FireElectricityGun_07), DEBUGSTRING("CDevil::H0x014c00fa_FireElectricityGun_07")}, + {0x014c00fb, -1, CEntity::pEventHandler(&CDevil::H0x014c00fb_FireElectricityGun_08), DEBUGSTRING("CDevil::H0x014c00fb_FireElectricityGun_08")}, + {0x014c00fc, -1, CEntity::pEventHandler(&CDevil::H0x014c00fc_FireElectricityGun_09), DEBUGSTRING("CDevil::H0x014c00fc_FireElectricityGun_09")}, + {0x014c00fd, -1, CEntity::pEventHandler(&CDevil::H0x014c00fd_FireElectricityGun_10), DEBUGSTRING("CDevil::H0x014c00fd_FireElectricityGun_10")}, + {0x014c00fe, -1, CEntity::pEventHandler(&CDevil::H0x014c00fe_FireElectricityGun_11), DEBUGSTRING("CDevil::H0x014c00fe_FireElectricityGun_11")}, + {0x014c00ff, -1, CEntity::pEventHandler(&CDevil::H0x014c00ff_FireElectricityGun_12), DEBUGSTRING("CDevil::H0x014c00ff_FireElectricityGun_12")}, + {0x014c0100, -1, CEntity::pEventHandler(&CDevil::H0x014c0100_FireElectricityGun_13), DEBUGSTRING("CDevil::H0x014c0100_FireElectricityGun_13")}, + {0x014c0101, -1, CEntity::pEventHandler(&CDevil::H0x014c0101_FireElectricityGun_14), DEBUGSTRING("CDevil::H0x014c0101_FireElectricityGun_14")}, + {0x014c0102, -1, CEntity::pEventHandler(&CDevil::H0x014c0102_FireElectricityGun_15), DEBUGSTRING("CDevil::H0x014c0102_FireElectricityGun_15")}, + {0x014c0103, -1, CEntity::pEventHandler(&CDevil::H0x014c0103_FireElectricityGun_16), DEBUGSTRING("CDevil::H0x014c0103_FireElectricityGun_16")}, + {0x014c0104, -1, CEntity::pEventHandler(&CDevil::H0x014c0104_FireElectricityGun_17), DEBUGSTRING("CDevil::H0x014c0104_FireElectricityGun_17")}, + {0x014c0105, -1, CEntity::pEventHandler(&CDevil::H0x014c0105_FireElectricityGun_18), DEBUGSTRING("CDevil::H0x014c0105_FireElectricityGun_18")}, + {0x014c0106, -1, CEntity::pEventHandler(&CDevil:: +#line 1990 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +FireGuidedProjectile),DEBUGSTRING("CDevil::FireGuidedProjectile")}, + {0x014c0107, -1, CEntity::pEventHandler(&CDevil::H0x014c0107_FireGuidedProjectile_01), DEBUGSTRING("CDevil::H0x014c0107_FireGuidedProjectile_01")}, + {0x014c0108, -1, CEntity::pEventHandler(&CDevil::H0x014c0108_FireGuidedProjectile_02), DEBUGSTRING("CDevil::H0x014c0108_FireGuidedProjectile_02")}, + {0x014c0109, -1, CEntity::pEventHandler(&CDevil::H0x014c0109_FireGuidedProjectile_03), DEBUGSTRING("CDevil::H0x014c0109_FireGuidedProjectile_03")}, + {0x014c010a, -1, CEntity::pEventHandler(&CDevil::H0x014c010a_FireGuidedProjectile_04), DEBUGSTRING("CDevil::H0x014c010a_FireGuidedProjectile_04")}, + {0x014c010b, -1, CEntity::pEventHandler(&CDevil::H0x014c010b_FireGuidedProjectile_05), DEBUGSTRING("CDevil::H0x014c010b_FireGuidedProjectile_05")}, + {0x014c010c, -1, CEntity::pEventHandler(&CDevil::H0x014c010c_FireGuidedProjectile_06), DEBUGSTRING("CDevil::H0x014c010c_FireGuidedProjectile_06")}, + {0x014c010d, -1, CEntity::pEventHandler(&CDevil::H0x014c010d_FireGuidedProjectile_07), DEBUGSTRING("CDevil::H0x014c010d_FireGuidedProjectile_07")}, + {0x014c010e, -1, CEntity::pEventHandler(&CDevil::H0x014c010e_FireGuidedProjectile_08), DEBUGSTRING("CDevil::H0x014c010e_FireGuidedProjectile_08")}, + {0x014c010f, -1, CEntity::pEventHandler(&CDevil::H0x014c010f_FireGuidedProjectile_09), DEBUGSTRING("CDevil::H0x014c010f_FireGuidedProjectile_09")}, + {0x014c0110, -1, CEntity::pEventHandler(&CDevil::H0x014c0110_FireGuidedProjectile_10), DEBUGSTRING("CDevil::H0x014c0110_FireGuidedProjectile_10")}, + {0x014c0111, -1, CEntity::pEventHandler(&CDevil::H0x014c0111_FireGuidedProjectile_11), DEBUGSTRING("CDevil::H0x014c0111_FireGuidedProjectile_11")}, + {0x014c0112, -1, CEntity::pEventHandler(&CDevil::H0x014c0112_FireGuidedProjectile_12), DEBUGSTRING("CDevil::H0x014c0112_FireGuidedProjectile_12")}, + {0x014c0113, -1, CEntity::pEventHandler(&CDevil::H0x014c0113_FireGuidedProjectile_13), DEBUGSTRING("CDevil::H0x014c0113_FireGuidedProjectile_13")}, + {0x014c0114, -1, CEntity::pEventHandler(&CDevil::H0x014c0114_FireGuidedProjectile_14), DEBUGSTRING("CDevil::H0x014c0114_FireGuidedProjectile_14")}, + {0x014c0115, -1, CEntity::pEventHandler(&CDevil:: +#line 2036 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +JumpIntoPyramid),DEBUGSTRING("CDevil::JumpIntoPyramid")}, + {0x014c0116, -1, CEntity::pEventHandler(&CDevil::H0x014c0116_JumpIntoPyramid_01), DEBUGSTRING("CDevil::H0x014c0116_JumpIntoPyramid_01")}, + {0x014c0117, -1, CEntity::pEventHandler(&CDevil::H0x014c0117_JumpIntoPyramid_02), DEBUGSTRING("CDevil::H0x014c0117_JumpIntoPyramid_02")}, + {0x014c0118, -1, CEntity::pEventHandler(&CDevil::H0x014c0118_JumpIntoPyramid_03), DEBUGSTRING("CDevil::H0x014c0118_JumpIntoPyramid_03")}, + {0x014c0119, -1, CEntity::pEventHandler(&CDevil::H0x014c0119_JumpIntoPyramid_04), DEBUGSTRING("CDevil::H0x014c0119_JumpIntoPyramid_04")}, + {0x014c011a, -1, CEntity::pEventHandler(&CDevil::H0x014c011a_JumpIntoPyramid_05), DEBUGSTRING("CDevil::H0x014c011a_JumpIntoPyramid_05")}, + {0x014c011b, -1, CEntity::pEventHandler(&CDevil::H0x014c011b_JumpIntoPyramid_06), DEBUGSTRING("CDevil::H0x014c011b_JumpIntoPyramid_06")}, + {0x014c011c, -1, CEntity::pEventHandler(&CDevil::H0x014c011c_JumpIntoPyramid_07), DEBUGSTRING("CDevil::H0x014c011c_JumpIntoPyramid_07")}, + {0x014c011d, -1, CEntity::pEventHandler(&CDevil::H0x014c011d_JumpIntoPyramid_08), DEBUGSTRING("CDevil::H0x014c011d_JumpIntoPyramid_08")}, + {0x014c011e, -1, CEntity::pEventHandler(&CDevil::H0x014c011e_JumpIntoPyramid_09), DEBUGSTRING("CDevil::H0x014c011e_JumpIntoPyramid_09")}, + {0x014c011f, -1, CEntity::pEventHandler(&CDevil::H0x014c011f_JumpIntoPyramid_10), DEBUGSTRING("CDevil::H0x014c011f_JumpIntoPyramid_10")}, + {0x014c0120, -1, CEntity::pEventHandler(&CDevil::H0x014c0120_JumpIntoPyramid_11), DEBUGSTRING("CDevil::H0x014c0120_JumpIntoPyramid_11")}, + {0x014c0121, -1, CEntity::pEventHandler(&CDevil::H0x014c0121_JumpIntoPyramid_12), DEBUGSTRING("CDevil::H0x014c0121_JumpIntoPyramid_12")}, + {0x014c0122, -1, CEntity::pEventHandler(&CDevil:: +#line 2086 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +TeleportIntoPyramid),DEBUGSTRING("CDevil::TeleportIntoPyramid")}, + {0x014c0123, -1, CEntity::pEventHandler(&CDevil::H0x014c0123_TeleportIntoPyramid_01), DEBUGSTRING("CDevil::H0x014c0123_TeleportIntoPyramid_01")}, + {0x014c0124, -1, CEntity::pEventHandler(&CDevil::H0x014c0124_TeleportIntoPyramid_02), DEBUGSTRING("CDevil::H0x014c0124_TeleportIntoPyramid_02")}, + {0x014c0125, -1, CEntity::pEventHandler(&CDevil::H0x014c0125_TeleportIntoPyramid_03), DEBUGSTRING("CDevil::H0x014c0125_TeleportIntoPyramid_03")}, + {0x014c0126, -1, CEntity::pEventHandler(&CDevil::H0x014c0126_TeleportIntoPyramid_04), DEBUGSTRING("CDevil::H0x014c0126_TeleportIntoPyramid_04")}, + {0x014c0127, -1, CEntity::pEventHandler(&CDevil:: +#line 2111 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +RegenerationImpulse),DEBUGSTRING("CDevil::RegenerationImpulse")}, + {0x014c0128, -1, CEntity::pEventHandler(&CDevil::H0x014c0128_RegenerationImpulse_01), DEBUGSTRING("CDevil::H0x014c0128_RegenerationImpulse_01")}, + {0x014c0129, -1, CEntity::pEventHandler(&CDevil::H0x014c0129_RegenerationImpulse_02), DEBUGSTRING("CDevil::H0x014c0129_RegenerationImpulse_02")}, + {0x014c012a, -1, CEntity::pEventHandler(&CDevil::H0x014c012a_RegenerationImpulse_03), DEBUGSTRING("CDevil::H0x014c012a_RegenerationImpulse_03")}, + {0x014c012b, -1, CEntity::pEventHandler(&CDevil::H0x014c012b_RegenerationImpulse_04), DEBUGSTRING("CDevil::H0x014c012b_RegenerationImpulse_04")}, + {0x014c012c, STATE_CEnemyBase_StopAttack, CEntity::pEventHandler(&CDevil:: +#line 2137 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +StopAttack),DEBUGSTRING("CDevil::StopAttack")}, + {0x014c012d, -1, CEntity::pEventHandler(&CDevil::H0x014c012d_StopAttack_01), DEBUGSTRING("CDevil::H0x014c012d_StopAttack_01")}, + {0x014c012e, -1, CEntity::pEventHandler(&CDevil::H0x014c012e_StopAttack_02), DEBUGSTRING("CDevil::H0x014c012e_StopAttack_02")}, + {0x014c012f, -1, CEntity::pEventHandler(&CDevil::H0x014c012f_StopAttack_03), DEBUGSTRING("CDevil::H0x014c012f_StopAttack_03")}, + {0x014c0130, -1, CEntity::pEventHandler(&CDevil:: +#line 2146 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +ContinueInMainLoop),DEBUGSTRING("CDevil::ContinueInMainLoop")}, + {0x014c0131, -1, CEntity::pEventHandler(&CDevil:: +#line 2167 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +MPIntro),DEBUGSTRING("CDevil::MPIntro")}, + {0x014c0132, STATE_CEnemyBase_Death, CEntity::pEventHandler(&CDevil:: +#line 2176 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Death),DEBUGSTRING("CDevil::Death")}, + {0x014c0133, -1, CEntity::pEventHandler(&CDevil::H0x014c0133_Death_01), DEBUGSTRING("CDevil::H0x014c0133_Death_01")}, + {0x014c0134, -1, CEntity::pEventHandler(&CDevil::H0x014c0134_Death_02), DEBUGSTRING("CDevil::H0x014c0134_Death_02")}, + {0x014c0135, -1, CEntity::pEventHandler(&CDevil::H0x014c0135_Death_03), DEBUGSTRING("CDevil::H0x014c0135_Death_03")}, + {0x014c0136, -1, CEntity::pEventHandler(&CDevil::H0x014c0136_Death_04), DEBUGSTRING("CDevil::H0x014c0136_Death_04")}, + {0x014c0137, -1, CEntity::pEventHandler(&CDevil::H0x014c0137_Death_05), DEBUGSTRING("CDevil::H0x014c0137_Death_05")}, + {0x014c0138, -1, CEntity::pEventHandler(&CDevil::H0x014c0138_Death_06), DEBUGSTRING("CDevil::H0x014c0138_Death_06")}, + {0x014c0139, -1, CEntity::pEventHandler(&CDevil::H0x014c0139_Death_07), DEBUGSTRING("CDevil::H0x014c0139_Death_07")}, + {0x014c013a, -1, CEntity::pEventHandler(&CDevil::H0x014c013a_Death_08), DEBUGSTRING("CDevil::H0x014c013a_Death_08")}, + {1, -1, CEntity::pEventHandler(&CDevil:: +#line 2213 "D:/SE1_GPL/Sources/EntitiesMP/Devil.es" +Main),DEBUGSTRING("CDevil::Main")}, + {0x014c013b, -1, CEntity::pEventHandler(&CDevil::H0x014c013b_Main_01), DEBUGSTRING("CDevil::H0x014c013b_Main_01")}, + {0x014c013c, -1, CEntity::pEventHandler(&CDevil::H0x014c013c_Main_02), DEBUGSTRING("CDevil::H0x014c013c_Main_02")}, + {0x014c013d, -1, CEntity::pEventHandler(&CDevil::H0x014c013d_Main_03), DEBUGSTRING("CDevil::H0x014c013d_Main_03")}, + {0x014c013e, -1, CEntity::pEventHandler(&CDevil::H0x014c013e_Main_04), DEBUGSTRING("CDevil::H0x014c013e_Main_04")}, + {0x014c013f, -1, CEntity::pEventHandler(&CDevil::H0x014c013f_Main_05), DEBUGSTRING("CDevil::H0x014c013f_Main_05")}, + {0x014c0140, -1, CEntity::pEventHandler(&CDevil::H0x014c0140_Main_06), DEBUGSTRING("CDevil::H0x014c0140_Main_06")}, + {0x014c0141, -1, CEntity::pEventHandler(&CDevil::H0x014c0141_Main_07), DEBUGSTRING("CDevil::H0x014c0141_Main_07")}, + {0x014c0142, -1, CEntity::pEventHandler(&CDevil::H0x014c0142_Main_08), DEBUGSTRING("CDevil::H0x014c0142_Main_08")}, +}; +#define CDevil_handlersct ARRAYCOUNT(CDevil_handlers) + +CEntity *CDevil_New(void) { return new CDevil; }; +void CDevil_OnInitClass(void) {}; +void CDevil_OnEndClass(void) {}; +void CDevil_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CDevil_OnWorldEnd(CWorld *pwo) {}; +void CDevil_OnWorldInit(CWorld *pwo) {}; +void CDevil_OnWorldTick(CWorld *pwo) {}; +void CDevil_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CDevil, CEnemyBase, "Devil", "Thumbnails\\Devil.tbn", 0x0000014c); +DECLARE_CTFILENAME(_fnmCDevil_tbn, "Thumbnails\\Devil.tbn"); diff --git a/Sources/EntitiesMP/DoorController.cpp b/Sources/EntitiesMP/DoorController.cpp new file mode 100644 index 0000000..919bbfd --- /dev/null +++ b/Sources/EntitiesMP/DoorController.cpp @@ -0,0 +1,588 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" + +#include "StdH.h" +#include + +#include +#include +void CDoorController::SetDefaultProperties(void) { + m_strName = "DoorController"; + m_strDescription = ""; + m_penTarget1 = NULL; + m_penTarget2 = NULL; + m_fWidth = 2.0f; + m_fHeight = 3.0f; + m_bPlayersOnly = TRUE ; + m_dtType = DT_AUTO ; + m_strLockedMessage = ""; + m_penLockedTarget = NULL; + m_kitKey = KIT_BOOKOFWISDOM ; + m_bTriggerOnAnything = FALSE ; + m_bActive = TRUE ; + m_bLocked = FALSE ; + m_penCaused = NULL; + CRationalEntity::SetDefaultProperties(); +} + +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +CEntity * CDoorController::GetTarget(void)const {return m_penTarget1 ;} + +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +const CTString & CDoorController::GetDescription(void)const +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +{ +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(m_penTarget1 != NULL && m_penTarget2 != NULL ){ +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +((CTString &) m_strDescription ) . PrintF ("->%s,%s" , +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +m_penTarget1 -> GetName () , m_penTarget2 -> GetName ()); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}else if(m_penTarget1 != NULL ){ +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +m_penTarget1 -> GetName ()); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}else { +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return m_strDescription ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} + +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +BOOL CDoorController::CanReactOnEntity(CEntity * pen) +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +{ +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(pen == NULL ){ +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return FALSE ; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(! (pen -> GetFlags () & ENF_ALIVE )){ +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return FALSE ; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(m_bPlayersOnly && ! IsDerivedFromClass (pen , "Player")){ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return FALSE ; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +BOOL CDoorController::CanTriggerOnEntity(CEntity * pen) +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +{ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return m_bTriggerOnAnything || CanReactOnEntity (pen ); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +void CDoorController::TriggerDoor(void) +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +{ +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(m_penTarget1 != NULL ){ +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SendToTarget (m_penTarget1 , EET_TRIGGER , m_penCaused ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(m_penTarget2 != NULL ){ +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SendToTarget (m_penTarget2 , EET_TRIGGER , m_penCaused ); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} + +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +void CDoorController::MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX) +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +{ +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +m_fWidth *= fStretch ; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +m_fHeight *= fStretch ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SLONG CDoorController::GetUsedMemory(void) +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +{ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SLONG slUsedMemory = sizeof (CDoorController ) - sizeof (CRationalEntity ) + CRationalEntity :: GetUsedMemory (); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +slUsedMemory += m_strDescription . Length (); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +slUsedMemory += m_strName . Length (); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +slUsedMemory += m_strLockedMessage . Length (); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return slUsedMemory ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +BOOL CDoorController:: +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorAuto(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDoorController_DoorAuto + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDoorController::DoorAuto expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(m_bActive ){ +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT, STATE_CDoorController_DoorAutoActive, TRUE, EVoid());return TRUE; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}else { +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT, STATE_CDoorController_DoorAutoInactive, TRUE, EVoid());return TRUE; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} ASSERT(FALSE); return TRUE;};BOOL CDoorController:: +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorAutoActive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDoorController_DoorAutoActive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDoorController::DoorAutoActive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +ASSERT (m_bActive ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT,0x00dd0006, FALSE, EInternal());return TRUE;}BOOL CDoorController::H0x00dd0006_DoorAutoActive_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0006 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00dd0007, FALSE, EInternal());return TRUE;} +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00dd0002, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd0002_DoorAutoActive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0002 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EPass):{const EPass&ePass= (EPass&)__eeInput; + +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(CanReactOnEntity (ePass . penOther )){ +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +m_penCaused = ePass . penOther ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +TriggerDoor (); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(_SE_DEMO && GetSP () -> sp_bCooperative && ! GetSP () -> sp_bSinglePlayer ){ +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(m_strName == "Appear gold amon"){ +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +CPlayer * penPlayer = (CPlayer *) & * ePass . penOther ; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +penPlayer -> SetGameEnd (); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +m_bActive = FALSE ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT, STATE_CDoorController_DoorAutoInactive, TRUE, EVoid());return TRUE; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break;default:{ +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}return TRUE;}BOOL CDoorController::H0x00dd0003_DoorAutoActive_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0003 +; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00dd0004, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd0004_DoorAutoActive_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00dd0005, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDoorController::H0x00dd0005_DoorAutoActive_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0005 +;Jump(STATE_CURRENT,0x00dd0006, FALSE, EInternal());return TRUE; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}BOOL CDoorController::H0x00dd0007_DoorAutoActive_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0007 + ASSERT(FALSE); return TRUE;};BOOL CDoorController:: +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorAutoInactive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDoorController_DoorAutoInactive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDoorController::DoorAutoInactive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +ASSERT (! m_bActive ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT,0x00dd000d, FALSE, EInternal());return TRUE;}BOOL CDoorController::H0x00dd000d_DoorAutoInactive_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd000d +if(!(TRUE )){ Jump(STATE_CURRENT,0x00dd000e, FALSE, EInternal());return TRUE;} +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00dd0009, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd0009_DoorAutoInactive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0009 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +m_bActive = TRUE ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT, STATE_CDoorController_DoorAutoActive, TRUE, EVoid());return TRUE; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break;default:{ +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}return TRUE;}BOOL CDoorController::H0x00dd000a_DoorAutoInactive_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd000a +; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00dd000b, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd000b_DoorAutoInactive_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd000b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00dd000c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDoorController::H0x00dd000c_DoorAutoInactive_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd000c +;Jump(STATE_CURRENT,0x00dd000d, FALSE, EInternal());return TRUE; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}BOOL CDoorController::H0x00dd000e_DoorAutoInactive_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd000e + ASSERT(FALSE); return TRUE;};BOOL CDoorController:: +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorDummy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDoorController_DoorDummy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDoorController::DoorDummy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00dd0010, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd0010_DoorDummy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0010 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break;default:{ +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}return TRUE;}BOOL CDoorController::H0x00dd0011_DoorDummy_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0011 + ASSERT(FALSE); return TRUE;};BOOL CDoorController:: +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorTriggered(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDoorController_DoorTriggered + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDoorController::DoorTriggered expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT,0x00dd0017, FALSE, EInternal());return TRUE;}BOOL CDoorController::H0x00dd0017_DoorTriggered_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0017 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00dd0018, FALSE, EInternal());return TRUE;} +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00dd0013, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd0013_DoorTriggered_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0013 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EPass):{const EPass&ePass= (EPass&)__eeInput; + +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(CanReactOnEntity (ePass . penOther )){ +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(m_strLockedMessage != ""){ +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +PrintCenterMessage (this , ePass . penOther , TranslateConst (m_strLockedMessage ) , 3.0f , MSS_INFO ); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(m_penLockedTarget != NULL ){ +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SendToTarget (m_penLockedTarget , EET_TRIGGER , ePass . penOther ); +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +m_penCaused = eTrigger . penCaused ; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +TriggerDoor (); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT, STATE_CDoorController_DoorDummy, TRUE, EVoid());return TRUE; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break;default:{ +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}return TRUE;}BOOL CDoorController::H0x00dd0014_DoorTriggered_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0014 +; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00dd0015, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd0015_DoorTriggered_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00dd0016, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDoorController::H0x00dd0016_DoorTriggered_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0016 +;Jump(STATE_CURRENT,0x00dd0017, FALSE, EInternal());return TRUE; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}BOOL CDoorController::H0x00dd0018_DoorTriggered_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0018 + ASSERT(FALSE); return TRUE;};BOOL CDoorController:: +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorLocked(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDoorController_DoorLocked + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDoorController::DoorLocked expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT,0x00dd001e, FALSE, EInternal());return TRUE;}BOOL CDoorController::H0x00dd001e_DoorLocked_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd001e +if(!(TRUE )){ Jump(STATE_CURRENT,0x00dd001f, FALSE, EInternal());return TRUE;} +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00dd001a, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd001a_DoorLocked_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd001a +switch(__eeInput.ee_slEvent){case(EVENTCODE_EPass):{const EPass&ePass= (EPass&)__eeInput; + +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(IsDerivedFromClass (ePass . penOther , "Player")){ +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +CPlayer * penPlayer = (CPlayer *) & * ePass . penOther ; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +ULONG ulKey = (1 << INDEX (m_kitKey )); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(penPlayer -> m_ulKeys & ulKey ){ +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +penPlayer -> m_ulKeys &= ~ ulKey ; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +TriggerDoor (); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT, STATE_CDoorController_DoorAuto, TRUE, EVoid());return TRUE; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}else { +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(m_penLockedTarget != NULL ){ +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SendToTarget (m_penLockedTarget , EET_TRIGGER , ePass . penOther ); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break;default:{ +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break; +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}return TRUE;}BOOL CDoorController::H0x00dd001b_DoorLocked_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd001b +; +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00dd001c, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd001c_DoorLocked_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd001c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00dd001d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDoorController::H0x00dd001d_DoorLocked_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd001d +;Jump(STATE_CURRENT,0x00dd001e, FALSE, EInternal());return TRUE; +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}BOOL CDoorController::H0x00dd001f_DoorLocked_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd001f + ASSERT(FALSE); return TRUE;};BOOL CDoorController:: +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorTriggeredAuto(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDoorController_DoorTriggeredAuto + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDoorController::DoorTriggeredAuto expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT,0x00dd0025, FALSE, EInternal());return TRUE;}BOOL CDoorController::H0x00dd0025_DoorTriggeredAuto_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0025 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00dd0026, FALSE, EInternal());return TRUE;} +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00dd0021, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd0021_DoorTriggeredAuto_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0021 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT, STATE_CDoorController_DoorAuto, TRUE, EVoid());return TRUE; +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&ePass= (EPass&)__eeInput; + +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(CanReactOnEntity (ePass . penOther )){ +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(m_strLockedMessage != ""){ +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +PrintCenterMessage (this , ePass . penOther , TranslateConst (m_strLockedMessage ) , 3.0f , MSS_INFO ); +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +if(m_penLockedTarget != NULL ){ +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SendToTarget (m_penLockedTarget , EET_TRIGGER , ePass . penOther ); +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break;default:{ +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +return TRUE; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}ASSERT(FALSE);break; +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}return TRUE;}BOOL CDoorController::H0x00dd0022_DoorTriggeredAuto_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0022 +; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00dd0023, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd0023_DoorTriggeredAuto_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0023 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00dd0024, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDoorController::H0x00dd0024_DoorTriggeredAuto_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0024 +;Jump(STATE_CURRENT,0x00dd0025, FALSE, EInternal());return TRUE; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}BOOL CDoorController::H0x00dd0026_DoorTriggeredAuto_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0026 + ASSERT(FALSE); return TRUE;};BOOL CDoorController:: +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CDoorController_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CDoorController::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +InitAsEditorModel (); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetCollisionFlags (ECF_TOUCHMODEL ); +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fWidth , m_fHeight , m_fWidth )); +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetModel (MODEL_DOORCONTROLLER ); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetModelMainTexture (TEXTURE_DOORCONTROLLER ); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +ModelChangeNotify (); +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00dd0027, FALSE, EBegin());return TRUE;}BOOL CDoorController::H0x00dd0027_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0027 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00dd0028, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CDoorController::H0x00dd0028_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00dd0028 +; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +switch(m_dtType ){ +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +case DT_AUTO : { +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT, STATE_CDoorController_DoorAuto, TRUE, EVoid());return TRUE; +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}break ; +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +case DT_TRIGGERED : { +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT, STATE_CDoorController_DoorTriggered, TRUE, EVoid());return TRUE; +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}break ; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +case DT_TRIGGEREDAUTO : { +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT, STATE_CDoorController_DoorTriggeredAuto, TRUE, EVoid());return TRUE; +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}break ; +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +case DT_LOCKED : { +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Jump(STATE_CURRENT, STATE_CDoorController_DoorLocked, TRUE, EVoid());return TRUE; +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +}break ; +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +} ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/DoorController.es b/Sources/EntitiesMP/DoorController.es new file mode 100644 index 0000000..be33e81 --- /dev/null +++ b/Sources/EntitiesMP/DoorController.es @@ -0,0 +1,357 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +221 +%{ +#include "StdH.h" +#include +%} + +uses "EntitiesMP/KeyItem"; +uses "EntitiesMP/Player"; + +enum DoorType { + 0 DT_AUTO "Auto", // opens automatically + 1 DT_TRIGGERED "Triggered", // opens when triggered + 2 DT_LOCKED "Locked", // requires a key + 3 DT_TRIGGEREDAUTO "Triggered Auto", // opens automatically after being triggered +}; + +class CDoorController : CRationalEntity { +name "DoorController"; +thumbnail "Thumbnails\\DoorController.tbn"; +features "HasName", "IsTargetable"; + + +properties: + + 1 CTString m_strName "Name" 'N' = "DoorController", + 2 CTString m_strDescription = "", + 3 CEntityPointer m_penTarget1 "Target1" 'T' COLOR(C_MAGENTA|0xFF), + 4 CEntityPointer m_penTarget2 "Target2" COLOR(C_MAGENTA|0xFF), + 5 FLOAT m_fWidth "Width" 'W' = 2.0f, + 6 FLOAT m_fHeight "Height" 'H' = 3.0f, + 7 BOOL m_bPlayersOnly "Players Only" 'P' = TRUE, + 8 enum DoorType m_dtType "Type" 'Y' = DT_AUTO, + 9 CTStringTrans m_strLockedMessage "Locked message" 'L' = "", + 13 CEntityPointer m_penLockedTarget "Locked target" COLOR(C_dMAGENTA|0xFF), // target to trigger when locked + 12 enum KeyItemType m_kitKey "Key" 'K' = KIT_BOOKOFWISDOM, // key type (for locked door) + 14 BOOL m_bTriggerOnAnything "Trigger on anything" = FALSE, + 15 BOOL m_bActive "Active" 'A' = TRUE, // automatic door function can be activated/deactivated + + 10 BOOL m_bLocked = FALSE, // for lock/unlock door + 11 CEntityPointer m_penCaused, // for trigger relaying + + +components: + + 1 model MODEL_DOORCONTROLLER "Models\\Editor\\DoorController.mdl", + 2 texture TEXTURE_DOORCONTROLLER "Models\\Editor\\DoorController.tex", + + +functions: + + CEntity *GetTarget(void) const { return m_penTarget1; }; + + const CTString &GetDescription(void) const + { + if (m_penTarget1!=NULL && m_penTarget2!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s,%s", + m_penTarget1->GetName(), m_penTarget2->GetName()); + } else if (m_penTarget1!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", + m_penTarget1->GetName()); + } else { + ((CTString&)m_strDescription).PrintF("->"); + } + return m_strDescription; + } + + // test if this door reacts on this entity + BOOL CanReactOnEntity(CEntity *pen) + { + if (pen==NULL) { + return FALSE; + } + // never react on non-live or dead entities + if (!(pen->GetFlags()&ENF_ALIVE)) { + return FALSE; + } + + if (m_bPlayersOnly && !IsDerivedFromClass(pen, "Player")) { + return FALSE; + } + + return TRUE; + } + + // test if this door can be triggered by this entity + BOOL CanTriggerOnEntity(CEntity *pen) + { + return m_bTriggerOnAnything || CanReactOnEntity(pen); + } + + void TriggerDoor(void) + { + if (m_penTarget1!=NULL) { + SendToTarget(m_penTarget1, EET_TRIGGER, m_penCaused); + } + if (m_penTarget2!=NULL) { + SendToTarget(m_penTarget2, EET_TRIGGER, m_penCaused); + } + } + + // apply mirror and stretch to the entity + void MirrorAndStretch(FLOAT fStretch, BOOL bMirrorX) + { + // stretch its ranges + m_fWidth*=fStretch; + m_fHeight*=fStretch; + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CDoorController) - sizeof(CRationalEntity) + CRationalEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strDescription.Length(); + slUsedMemory += m_strName.Length(); + slUsedMemory += m_strLockedMessage.Length(); + return slUsedMemory; + } + + +procedures: + + // entry point for automatic functioning + DoorAuto() + { + // go into active or inactive state + if (m_bActive) { + jump DoorAutoActive(); + } else { + jump DoorAutoInactive(); + } + } + + // automatic door active state + DoorAutoActive() + { + ASSERT(m_bActive); + while (TRUE) { + // wait + wait() { + // when someone enters + on (EPass ePass) : { + // if he can open the door + if (CanReactOnEntity(ePass.penOther)) { + // do it + m_penCaused = ePass.penOther; + TriggerDoor(); + + // this is a very ugly fix for cooperative not finishing in the demo level + // remove this when not needed any more!!!! + if(_SE_DEMO && GetSP()->sp_bCooperative && !GetSP()->sp_bSinglePlayer) { + if (m_strName=="Appear gold amon") { + CPlayer *penPlayer = (CPlayer*)&*ePass.penOther; + penPlayer->SetGameEnd(); + } + } + + resume; + } + resume; + } + // if door is deactivated + on (EDeactivate) : { + // go to inactive state + m_bActive = FALSE; + jump DoorAutoInactive(); + } + otherwise() : { + resume; + }; + }; + + // wait a bit to recover + autowait(0.1f); + } + } + + // automatic door inactive state + DoorAutoInactive() + { + ASSERT(!m_bActive); + while (TRUE) { + // wait + wait() { + // if door is activated + on (EActivate) : { + // go to active state + m_bActive = TRUE; + jump DoorAutoActive(); + } + otherwise() : { + resume; + }; + }; + + // wait a bit to recover + autowait(0.1f); + } + } + + // door when do not function anymore + DoorDummy() + { + wait() { + on (EBegin) : { + resume; + } + otherwise() : { + resume; + }; + } + } + + // door that wait to be triggered to open + DoorTriggered() + { + while (TRUE) { + // wait to someone enter + wait() { + on (EPass ePass) : { + if (CanReactOnEntity(ePass.penOther)) { + if (m_strLockedMessage!="") { + PrintCenterMessage(this, ePass.penOther, TranslateConst(m_strLockedMessage), 3.0f, MSS_INFO); + } + if (m_penLockedTarget!=NULL) { + SendToTarget(m_penLockedTarget, EET_TRIGGER, ePass.penOther); + } + resume; + } + } + on (ETrigger eTrigger) : { + m_penCaused = eTrigger.penCaused; + TriggerDoor(); + jump DoorDummy(); + } + otherwise() : { + resume; + }; + }; + + // wait a bit to recover + autowait(0.1f); + } + } + + // door that need a key to be unlocked to open + DoorLocked() + { + while (TRUE) { + // wait to someone enter + wait() { + on (EPass ePass) : { + if (IsDerivedFromClass(ePass.penOther, "Player")) { + CPlayer *penPlayer = (CPlayer*)&*ePass.penOther; + // if he has the key + ULONG ulKey = (1<m_ulKeys&ulKey) { + // use the key + penPlayer->m_ulKeys&=~ulKey; + // open the dook + TriggerDoor(); + + /* + // tell the key bearer that the key was used + CTString strMsg; + strMsg.PrintF(TRANS("%s used"), GetKeyName(m_kitKey)); + PrintCenterMessage(this, ePass.penOther, strMsg, 3.0f, MSS_INFO); + */ + // become automatic door + jump DoorAuto(); + // if he has no key + } else { + if (m_penLockedTarget!=NULL) { + SendToTarget(m_penLockedTarget, EET_TRIGGER, ePass.penOther); + } + } + resume; + } + } + otherwise() : { + resume; + }; + }; + + // wait a bit to recover + autowait(0.1f); + } + } + + // door that need to be triggered to start working automatically + DoorTriggeredAuto() + { + while (TRUE) { + // wait to be triggered + wait() { + on (ETrigger eTrigger) : { + // become auto door + jump DoorAuto(); + } + on (EPass ePass) : { + if (CanReactOnEntity(ePass.penOther)) { + if (m_strLockedMessage!="") { + PrintCenterMessage(this, ePass.penOther, TranslateConst(m_strLockedMessage), 3.0f, MSS_INFO); + } + if (m_penLockedTarget!=NULL) { + SendToTarget(m_penLockedTarget, EET_TRIGGER, ePass.penOther); + } + } + resume; + } + otherwise() : { + resume; + }; + }; + + // wait a bit to recover + autowait(0.1f); + } + } + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_TOUCHMODEL); + + // set appearance + GetModelObject()->StretchModel(FLOAT3D(m_fWidth, m_fHeight, m_fWidth)); + SetModel(MODEL_DOORCONTROLLER); + SetModelMainTexture(TEXTURE_DOORCONTROLLER); + ModelChangeNotify(); + + // don't start in wed + autowait(0.1f); + + // dispatch to aproppriate loop + switch(m_dtType) { + case DT_AUTO: { + jump DoorAuto(); + } break; + case DT_TRIGGERED: { + jump DoorTriggered(); + } break; + case DT_TRIGGEREDAUTO: { + jump DoorTriggeredAuto(); + } break; + case DT_LOCKED: { + jump DoorLocked(); + } break; + } + } +}; + diff --git a/Sources/EntitiesMP/DoorController.h b/Sources/EntitiesMP/DoorController.h new file mode 100644 index 0000000..a24ea3c --- /dev/null +++ b/Sources/EntitiesMP/DoorController.h @@ -0,0 +1,126 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_DoorController_INCLUDED +#define _EntitiesMP_DoorController_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType DoorType_enum; +enum DoorType { + DT_AUTO = 0, + DT_TRIGGERED = 1, + DT_LOCKED = 2, + DT_TRIGGEREDAUTO = 3, +}; +DECL_DLL inline void ClearToDefault(DoorType &e) { e = (DoorType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CDoorController_DLLClass; +class CDoorController : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CEntityPointer m_penTarget1; + CEntityPointer m_penTarget2; + FLOAT m_fWidth; + FLOAT m_fHeight; + BOOL m_bPlayersOnly; + enum DoorType m_dtType; + CTStringTrans m_strLockedMessage; + CEntityPointer m_penLockedTarget; + enum KeyItemType m_kitKey; + BOOL m_bTriggerOnAnything; + BOOL m_bActive; + BOOL m_bLocked; + CEntityPointer m_penCaused; + +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +CEntity * GetTarget(void)const; + +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +const CTString & GetDescription(void)const; + +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +BOOL CanReactOnEntity(CEntity * pen); + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +BOOL CanTriggerOnEntity(CEntity * pen); + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +void TriggerDoor(void); + +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +void MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX); + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +SLONG GetUsedMemory(void); +#define STATE_CDoorController_DoorAuto 0x00dd0000 + BOOL +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorAuto(const CEntityEvent &__eeInput); +#define STATE_CDoorController_DoorAutoActive 0x00dd0001 + BOOL +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorAutoActive(const CEntityEvent &__eeInput); + BOOL H0x00dd0002_DoorAutoActive_01(const CEntityEvent &__eeInput); + BOOL H0x00dd0003_DoorAutoActive_02(const CEntityEvent &__eeInput); + BOOL H0x00dd0004_DoorAutoActive_03(const CEntityEvent &__eeInput); + BOOL H0x00dd0005_DoorAutoActive_04(const CEntityEvent &__eeInput); + BOOL H0x00dd0006_DoorAutoActive_05(const CEntityEvent &__eeInput); + BOOL H0x00dd0007_DoorAutoActive_06(const CEntityEvent &__eeInput); +#define STATE_CDoorController_DoorAutoInactive 0x00dd0008 + BOOL +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorAutoInactive(const CEntityEvent &__eeInput); + BOOL H0x00dd0009_DoorAutoInactive_01(const CEntityEvent &__eeInput); + BOOL H0x00dd000a_DoorAutoInactive_02(const CEntityEvent &__eeInput); + BOOL H0x00dd000b_DoorAutoInactive_03(const CEntityEvent &__eeInput); + BOOL H0x00dd000c_DoorAutoInactive_04(const CEntityEvent &__eeInput); + BOOL H0x00dd000d_DoorAutoInactive_05(const CEntityEvent &__eeInput); + BOOL H0x00dd000e_DoorAutoInactive_06(const CEntityEvent &__eeInput); +#define STATE_CDoorController_DoorDummy 0x00dd000f + BOOL +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorDummy(const CEntityEvent &__eeInput); + BOOL H0x00dd0010_DoorDummy_01(const CEntityEvent &__eeInput); + BOOL H0x00dd0011_DoorDummy_02(const CEntityEvent &__eeInput); +#define STATE_CDoorController_DoorTriggered 0x00dd0012 + BOOL +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorTriggered(const CEntityEvent &__eeInput); + BOOL H0x00dd0013_DoorTriggered_01(const CEntityEvent &__eeInput); + BOOL H0x00dd0014_DoorTriggered_02(const CEntityEvent &__eeInput); + BOOL H0x00dd0015_DoorTriggered_03(const CEntityEvent &__eeInput); + BOOL H0x00dd0016_DoorTriggered_04(const CEntityEvent &__eeInput); + BOOL H0x00dd0017_DoorTriggered_05(const CEntityEvent &__eeInput); + BOOL H0x00dd0018_DoorTriggered_06(const CEntityEvent &__eeInput); +#define STATE_CDoorController_DoorLocked 0x00dd0019 + BOOL +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorLocked(const CEntityEvent &__eeInput); + BOOL H0x00dd001a_DoorLocked_01(const CEntityEvent &__eeInput); + BOOL H0x00dd001b_DoorLocked_02(const CEntityEvent &__eeInput); + BOOL H0x00dd001c_DoorLocked_03(const CEntityEvent &__eeInput); + BOOL H0x00dd001d_DoorLocked_04(const CEntityEvent &__eeInput); + BOOL H0x00dd001e_DoorLocked_05(const CEntityEvent &__eeInput); + BOOL H0x00dd001f_DoorLocked_06(const CEntityEvent &__eeInput); +#define STATE_CDoorController_DoorTriggeredAuto 0x00dd0020 + BOOL +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorTriggeredAuto(const CEntityEvent &__eeInput); + BOOL H0x00dd0021_DoorTriggeredAuto_01(const CEntityEvent &__eeInput); + BOOL H0x00dd0022_DoorTriggeredAuto_02(const CEntityEvent &__eeInput); + BOOL H0x00dd0023_DoorTriggeredAuto_03(const CEntityEvent &__eeInput); + BOOL H0x00dd0024_DoorTriggeredAuto_04(const CEntityEvent &__eeInput); + BOOL H0x00dd0025_DoorTriggeredAuto_05(const CEntityEvent &__eeInput); + BOOL H0x00dd0026_DoorTriggeredAuto_06(const CEntityEvent &__eeInput); +#define STATE_CDoorController_Main 1 + BOOL +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00dd0027_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00dd0028_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_DoorController_INCLUDED diff --git a/Sources/EntitiesMP/DoorController_tables.h b/Sources/EntitiesMP/DoorController_tables.h new file mode 100644 index 0000000..2796e8f --- /dev/null +++ b/Sources/EntitiesMP/DoorController_tables.h @@ -0,0 +1,112 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(DoorType) + EP_ENUMVALUE(DT_AUTO, "Auto"), + EP_ENUMVALUE(DT_TRIGGERED, "Triggered"), + EP_ENUMVALUE(DT_LOCKED, "Locked"), + EP_ENUMVALUE(DT_TRIGGEREDAUTO, "Triggered Auto"), +EP_ENUMEND(DoorType); + +#define ENTITYCLASS CDoorController + +CEntityProperty CDoorController_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000dd<<8)+1, offsetof(CDoorController, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000dd<<8)+2, offsetof(CDoorController, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000dd<<8)+3, offsetof(CDoorController, m_penTarget1), "Target1", 'T', C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000dd<<8)+4, offsetof(CDoorController, m_penTarget2), "Target2", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dd<<8)+5, offsetof(CDoorController, m_fWidth), "Width", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000dd<<8)+6, offsetof(CDoorController, m_fHeight), "Height", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000dd<<8)+7, offsetof(CDoorController, m_bPlayersOnly), "Players Only", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DoorType_enum, (0x000000dd<<8)+8, offsetof(CDoorController, m_dtType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRINGTRANS, NULL, (0x000000dd<<8)+9, offsetof(CDoorController, m_strLockedMessage), "Locked message", 'L', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000dd<<8)+13, offsetof(CDoorController, m_penLockedTarget), "Locked target", 0, C_dMAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &KeyItemType_enum, (0x000000dd<<8)+12, offsetof(CDoorController, m_kitKey), "Key", 'K', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000dd<<8)+14, offsetof(CDoorController, m_bTriggerOnAnything), "Trigger on anything", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000dd<<8)+15, offsetof(CDoorController, m_bActive), "Active", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000dd<<8)+10, offsetof(CDoorController, m_bLocked), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000dd<<8)+11, offsetof(CDoorController, m_penCaused), "", 0, 0, 0), +}; +#define CDoorController_propertiesct ARRAYCOUNT(CDoorController_properties) + +CEntityComponent CDoorController_components[] = { +#define MODEL_DOORCONTROLLER ((0x000000dd<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_DOORCONTROLLER, "EFNM" "Models\\Editor\\DoorController.mdl"), +#define TEXTURE_DOORCONTROLLER ((0x000000dd<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_DOORCONTROLLER, "EFNM" "Models\\Editor\\DoorController.tex"), +}; +#define CDoorController_componentsct ARRAYCOUNT(CDoorController_components) + +CEventHandlerEntry CDoorController_handlers[] = { + {0x00dd0000, -1, CEntity::pEventHandler(&CDoorController:: +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorAuto),DEBUGSTRING("CDoorController::DoorAuto")}, + {0x00dd0001, -1, CEntity::pEventHandler(&CDoorController:: +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorAutoActive),DEBUGSTRING("CDoorController::DoorAutoActive")}, + {0x00dd0002, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0002_DoorAutoActive_01), DEBUGSTRING("CDoorController::H0x00dd0002_DoorAutoActive_01")}, + {0x00dd0003, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0003_DoorAutoActive_02), DEBUGSTRING("CDoorController::H0x00dd0003_DoorAutoActive_02")}, + {0x00dd0004, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0004_DoorAutoActive_03), DEBUGSTRING("CDoorController::H0x00dd0004_DoorAutoActive_03")}, + {0x00dd0005, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0005_DoorAutoActive_04), DEBUGSTRING("CDoorController::H0x00dd0005_DoorAutoActive_04")}, + {0x00dd0006, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0006_DoorAutoActive_05), DEBUGSTRING("CDoorController::H0x00dd0006_DoorAutoActive_05")}, + {0x00dd0007, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0007_DoorAutoActive_06), DEBUGSTRING("CDoorController::H0x00dd0007_DoorAutoActive_06")}, + {0x00dd0008, -1, CEntity::pEventHandler(&CDoorController:: +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorAutoInactive),DEBUGSTRING("CDoorController::DoorAutoInactive")}, + {0x00dd0009, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0009_DoorAutoInactive_01), DEBUGSTRING("CDoorController::H0x00dd0009_DoorAutoInactive_01")}, + {0x00dd000a, -1, CEntity::pEventHandler(&CDoorController::H0x00dd000a_DoorAutoInactive_02), DEBUGSTRING("CDoorController::H0x00dd000a_DoorAutoInactive_02")}, + {0x00dd000b, -1, CEntity::pEventHandler(&CDoorController::H0x00dd000b_DoorAutoInactive_03), DEBUGSTRING("CDoorController::H0x00dd000b_DoorAutoInactive_03")}, + {0x00dd000c, -1, CEntity::pEventHandler(&CDoorController::H0x00dd000c_DoorAutoInactive_04), DEBUGSTRING("CDoorController::H0x00dd000c_DoorAutoInactive_04")}, + {0x00dd000d, -1, CEntity::pEventHandler(&CDoorController::H0x00dd000d_DoorAutoInactive_05), DEBUGSTRING("CDoorController::H0x00dd000d_DoorAutoInactive_05")}, + {0x00dd000e, -1, CEntity::pEventHandler(&CDoorController::H0x00dd000e_DoorAutoInactive_06), DEBUGSTRING("CDoorController::H0x00dd000e_DoorAutoInactive_06")}, + {0x00dd000f, -1, CEntity::pEventHandler(&CDoorController:: +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorDummy),DEBUGSTRING("CDoorController::DoorDummy")}, + {0x00dd0010, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0010_DoorDummy_01), DEBUGSTRING("CDoorController::H0x00dd0010_DoorDummy_01")}, + {0x00dd0011, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0011_DoorDummy_02), DEBUGSTRING("CDoorController::H0x00dd0011_DoorDummy_02")}, + {0x00dd0012, -1, CEntity::pEventHandler(&CDoorController:: +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorTriggered),DEBUGSTRING("CDoorController::DoorTriggered")}, + {0x00dd0013, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0013_DoorTriggered_01), DEBUGSTRING("CDoorController::H0x00dd0013_DoorTriggered_01")}, + {0x00dd0014, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0014_DoorTriggered_02), DEBUGSTRING("CDoorController::H0x00dd0014_DoorTriggered_02")}, + {0x00dd0015, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0015_DoorTriggered_03), DEBUGSTRING("CDoorController::H0x00dd0015_DoorTriggered_03")}, + {0x00dd0016, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0016_DoorTriggered_04), DEBUGSTRING("CDoorController::H0x00dd0016_DoorTriggered_04")}, + {0x00dd0017, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0017_DoorTriggered_05), DEBUGSTRING("CDoorController::H0x00dd0017_DoorTriggered_05")}, + {0x00dd0018, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0018_DoorTriggered_06), DEBUGSTRING("CDoorController::H0x00dd0018_DoorTriggered_06")}, + {0x00dd0019, -1, CEntity::pEventHandler(&CDoorController:: +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorLocked),DEBUGSTRING("CDoorController::DoorLocked")}, + {0x00dd001a, -1, CEntity::pEventHandler(&CDoorController::H0x00dd001a_DoorLocked_01), DEBUGSTRING("CDoorController::H0x00dd001a_DoorLocked_01")}, + {0x00dd001b, -1, CEntity::pEventHandler(&CDoorController::H0x00dd001b_DoorLocked_02), DEBUGSTRING("CDoorController::H0x00dd001b_DoorLocked_02")}, + {0x00dd001c, -1, CEntity::pEventHandler(&CDoorController::H0x00dd001c_DoorLocked_03), DEBUGSTRING("CDoorController::H0x00dd001c_DoorLocked_03")}, + {0x00dd001d, -1, CEntity::pEventHandler(&CDoorController::H0x00dd001d_DoorLocked_04), DEBUGSTRING("CDoorController::H0x00dd001d_DoorLocked_04")}, + {0x00dd001e, -1, CEntity::pEventHandler(&CDoorController::H0x00dd001e_DoorLocked_05), DEBUGSTRING("CDoorController::H0x00dd001e_DoorLocked_05")}, + {0x00dd001f, -1, CEntity::pEventHandler(&CDoorController::H0x00dd001f_DoorLocked_06), DEBUGSTRING("CDoorController::H0x00dd001f_DoorLocked_06")}, + {0x00dd0020, -1, CEntity::pEventHandler(&CDoorController:: +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +DoorTriggeredAuto),DEBUGSTRING("CDoorController::DoorTriggeredAuto")}, + {0x00dd0021, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0021_DoorTriggeredAuto_01), DEBUGSTRING("CDoorController::H0x00dd0021_DoorTriggeredAuto_01")}, + {0x00dd0022, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0022_DoorTriggeredAuto_02), DEBUGSTRING("CDoorController::H0x00dd0022_DoorTriggeredAuto_02")}, + {0x00dd0023, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0023_DoorTriggeredAuto_03), DEBUGSTRING("CDoorController::H0x00dd0023_DoorTriggeredAuto_03")}, + {0x00dd0024, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0024_DoorTriggeredAuto_04), DEBUGSTRING("CDoorController::H0x00dd0024_DoorTriggeredAuto_04")}, + {0x00dd0025, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0025_DoorTriggeredAuto_05), DEBUGSTRING("CDoorController::H0x00dd0025_DoorTriggeredAuto_05")}, + {0x00dd0026, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0026_DoorTriggeredAuto_06), DEBUGSTRING("CDoorController::H0x00dd0026_DoorTriggeredAuto_06")}, + {1, -1, CEntity::pEventHandler(&CDoorController:: +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/DoorController.es" +Main),DEBUGSTRING("CDoorController::Main")}, + {0x00dd0027, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0027_Main_01), DEBUGSTRING("CDoorController::H0x00dd0027_Main_01")}, + {0x00dd0028, -1, CEntity::pEventHandler(&CDoorController::H0x00dd0028_Main_02), DEBUGSTRING("CDoorController::H0x00dd0028_Main_02")}, +}; +#define CDoorController_handlersct ARRAYCOUNT(CDoorController_handlers) + +CEntity *CDoorController_New(void) { return new CDoorController; }; +void CDoorController_OnInitClass(void) {}; +void CDoorController_OnEndClass(void) {}; +void CDoorController_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CDoorController_OnWorldEnd(CWorld *pwo) {}; +void CDoorController_OnWorldInit(CWorld *pwo) {}; +void CDoorController_OnWorldTick(CWorld *pwo) {}; +void CDoorController_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CDoorController, CRationalEntity, "DoorController", "Thumbnails\\DoorController.tbn", 0x000000dd); +DECLARE_CTFILENAME(_fnmCDoorController_tbn, "Thumbnails\\DoorController.tbn"); diff --git a/Sources/EntitiesMP/Dragonman.es b/Sources/EntitiesMP/Dragonman.es new file mode 100644 index 0000000..14bd415 --- /dev/null +++ b/Sources/EntitiesMP/Dragonman.es @@ -0,0 +1,618 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +321 +%{ +#include "StdH.h" +#include "Models/Enemies/Dragonman/Dragonman.h" +%} + +uses "EntitiesMP/EnemyFly"; +uses "EntitiesMP/Projectile"; + +enum DragonmanType { + 0 DT_SOLDIER "Soldier", + 1 DT_SERGEANT "Sergeant", + 2 DT_MONSTER "Monster", +}; + +%{ +// info structure +static EntityInfo eiDragonmanStand1 = { + EIBT_FLESH, 200.0f, + 0.0f, 1.55f, 0.0f, + 0.0f, 1.0f, 0.0f, +}; +static EntityInfo eiDragonmanStand2 = { + EIBT_FLESH, 200.0f*2, + 0.0f, 1.55f*2, 0.0f, + 0.0f, 1.0f*2, 0.0f, +}; +static EntityInfo eiDragonmanStand4 = { + EIBT_FLESH, 200.0f*4, + 0.0f, 1.55f*4, 0.0f, + 0.0f, 1.0f*4, 0.0f, +}; + +static EntityInfo eiDragonmanFly1 = { + EIBT_FLESH, 100.0f*1, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, +}; +static EntityInfo eiDragonmanFly2 = { + EIBT_FLESH, 100.0f*2, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, +}; +static EntityInfo eiDragonmanFly4 = { + EIBT_FLESH, 100.0f*4, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, +}; + +#define FLY_FIRE1 FLOAT3D( 0.0f, 0.25f, -1.5f) +#define GROUND_RIGHT_FIRE1 FLOAT3D( 0.3f, 2.2f, -0.85f) +#define GROUND_LEFT_FIRE1 FLOAT3D(-0.3f, 1.7f, -0.85f) +#define FLAME_AIR1 FLOAT3D( 0.0f, 0.1f, -1.75f) +#define FLAME_GROUND1 FLOAT3D( 0.0f, 2.7f, -0.85f) +%} + + +class CDragonman : CEnemyFly { +name "Dragonman"; +thumbnail "Thumbnails\\Dragonman.tbn"; + +properties: + 1 enum DragonmanType m_EdtType "Character" 'C' = DT_SOLDIER, // type + 2 FLOAT3D m_vFlameSource = FLOAT3D(0,0,0), + 3 CEntityPointer m_penFlame, + 4 BOOL m_bBurnEnemy = FALSE, + 5 FLOAT m_fFireTime = 0.0f, + +components: + 0 class CLASS_BASE "Classes\\EnemyFly.ecl", + 1 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + + 5 model MODEL_DRAGONMAN "Models\\Enemies\\Dragonman\\Dragonman.mdl", + 6 texture TEXTURE_DRAGONMAN1 "Models\\Enemies\\Dragonman\\Dragonman01.tex", + 7 texture TEXTURE_DRAGONMAN2 "Models\\Enemies\\Dragonman\\Dragonman02.tex", + 8 texture TEXTURE_DRAGONMAN3 "Models\\Enemies\\Dragonman\\Dragonman03.tex", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "Models\\Enemies\\Dragonman\\Sounds\\Idle.wav", + 51 sound SOUND_SIGHT "Models\\Enemies\\Dragonman\\Sounds\\Sight.wav", + 52 sound SOUND_WOUND "Models\\Enemies\\Dragonman\\Sounds\\Wound.wav", + 53 sound SOUND_FIRE "Models\\Enemies\\Dragonman\\Sounds\\Fire.wav", + 54 sound SOUND_KICK "Models\\Enemies\\Dragonman\\Sounds\\Kick.wav", + 55 sound SOUND_DEATH "Models\\Enemies\\Dragonman\\Sounds\\Death.wav", + +functions: + /* Entity info */ + void *GetEntityInfo(void) { + if (m_bInAir) { + switch(m_EdtType) { + case DT_SOLDIER: + return &eiDragonmanFly1; + break; + case DT_SERGEANT: + return &eiDragonmanFly2; + break; + case DT_MONSTER: + return &eiDragonmanFly4; + break; + default: { + return &eiDragonmanFly1; + } break; + } + } else { + switch(m_EdtType) { + case DT_SOLDIER: + return &eiDragonmanStand1; + break; + case DT_SERGEANT: + return &eiDragonmanStand2; + break; + case DT_MONSTER: + return &eiDragonmanStand4; + break; + default: { + return &eiDragonmanStand1; + } break; + } + } + }; + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + CEnemyBase::FillEntityStatistics(pes); + switch(m_EdtType) { + case DT_SOLDIER : { pes->es_strName+=" Soldier"; } break; + case DT_SERGEANT : { pes->es_strName+=" Sergeant"; } break; + case DT_MONSTER : { pes->es_strName+=" Monster"; } break; + } + return TRUE; + } + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // woman can't harm woman + if (!IsOfClass(penInflictor, "Dragonman")) { + CEnemyFly::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + }; + + FLOAT3D GetStretchedVector(const FLOAT3D&v) + { + switch(m_EdtType) { + case DT_SOLDIER: + return v; + break; + case DT_SERGEANT: + return v*2.0f; + break; + case DT_MONSTER: + return v*4.0f; + break; + default: + ASSERT(FALSE); + return v; + } + } + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim; + if (m_bInAir) { + switch (IRnd()%2) { + case 0: iAnim = DRAGONMAN_ANIM_AIRWOUNDSLIGHT; break; + case 1: iAnim = DRAGONMAN_ANIM_AIRWOUND02CRITICAL; break; + default: ASSERTALWAYS("Dragonman unknown fly damage"); + } + } else { + switch (IRnd()%3) { + case 0: iAnim = DRAGONMAN_ANIM_GROUNDWOUNDCRITICALBACK; break; + case 1: iAnim = DRAGONMAN_ANIM_GROUNDWOUNDCRITICALFRONT; break; + case 2: iAnim = DRAGONMAN_ANIM_GROUNDWOUNDCRITICALBACK2; break; + default: ASSERTALWAYS("Dragonman unknown ground damage"); + } + } + StartModelAnim(iAnim, 0); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + INDEX iAnim; + if (m_bInAir) { + iAnim = DRAGONMAN_ANIM_AIRDEATH; + } else { + switch (IRnd()%2) { + case 0: iAnim = DRAGONMAN_ANIM_GROUNDDEATHBACK; break; + case 1: iAnim = DRAGONMAN_ANIM_GROUNDDEATHFRONT; break; + default: ASSERTALWAYS("Dragonman unknown ground death"); + } + } + StartModelAnim(iAnim, 0); + return iAnim; + }; + + void DeathNotify(void) { + ChangeCollisionBoxIndexWhenPossible(DRAGONMAN_COLLISION_BOX_DEATH); + en_fDensity = 500.0f; + }; + + // virtual anim functions + void StandingAnim(void) { + if (m_bInAir) { + StartModelAnim(DRAGONMAN_ANIM_AIRSTANDLOOP, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(DRAGONMAN_ANIM_GROUNDSTANDLOOP, AOF_LOOPING|AOF_NORESTART); + } + }; + void WalkingAnim(void) { + if (m_bInAir) { + StartModelAnim(DRAGONMAN_ANIM_AIRFLYLOOP, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(DRAGONMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART); + } + }; + void RunningAnim(void) { + if (m_bInAir) { + StartModelAnim(DRAGONMAN_ANIM_AIRFLYLOOP, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(DRAGONMAN_ANIM_GROUNDRUN, AOF_LOOPING|AOF_NORESTART); + } + }; + void RotatingAnim(void) { + if (m_bInAir) { + StartModelAnim(DRAGONMAN_ANIM_AIRFLYLOOP, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(DRAGONMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART); + } + }; + FLOAT AirToGroundAnim(void) { + StartModelAnim(DRAGONMAN_ANIM_AIRTOGROUND, 0); + return(GetModelObject()->GetAnimLength(DRAGONMAN_ANIM_AIRTOGROUND)); + }; + FLOAT GroundToAirAnim(void) { + StartModelAnim(DRAGONMAN_ANIM_GROUNDTOAIR, 0); + return(GetModelObject()->GetAnimLength(DRAGONMAN_ANIM_GROUNDTOAIR)); + }; + void ChangeCollisionToAir() { + ChangeCollisionBoxIndexWhenPossible(DRAGONMAN_COLLISION_BOX_AIR); + }; + void ChangeCollisionToGround() { + ChangeCollisionBoxIndexWhenPossible(DRAGONMAN_COLLISION_BOX_GROUND); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + // flame source + void GetFlamerSourcePlacement(CPlacement3D &plFlame) { + plFlame.pl_PositionVector = m_vFlameSource; + }; + + // fire flame + void FireFlame(void) { + FLOAT3D vFlamePos; + if (m_bInAir) { + vFlamePos = GetStretchedVector(FLAME_AIR1); + } else { + vFlamePos = GetStretchedVector(FLAME_GROUND1); + } + + // create flame + CEntityPointer penFlame = ShootProjectile(PRT_FLAME, vFlamePos, ANGLE3D(0, 0, 0)); + // link last flame with this one (if not NULL or deleted) + if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) { + ((CProjectile&)*m_penFlame).m_penParticles = penFlame; + } + // link to player weapons + ((CProjectile&)*penFlame).m_penParticles = this; + // store last flame + m_penFlame = penFlame; + // flame source position + m_vFlameSource = GetPlacement().pl_PositionVector + vFlamePos*GetRotationMatrix(); + }; + + +procedures: +/************************************************************ + * PROCEDURES WHEN HARMED * + ************************************************************/ + BeWounded(EDamage eDamage) : CEnemyFly::BeWounded { + m_penFlame = NULL; + jump CEnemyFly::BeWounded(eDamage); + }; + + + +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + FlyFire(EVoid) : CEnemyFly::FlyFire { + // fire projectile + StartModelAnim(DRAGONMAN_ANIM_AIRATTACK02, 0); + autowait(0.4f); + if (m_EdtType != DT_MONSTER) { + ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0)); + } else { + ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0)); + } + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(0.15f); + if (m_EdtType != DT_MONSTER) { + ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0)); + } else if (m_EdtType == DT_MONSTER) { + ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(FLY_FIRE1), ANGLE3D(0, 0, 0)); + } + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(0.85f); +/* StandingAnim(); + autowait(FRnd() + _pTimer->TickQuantum); + */ + + return EReturn(); + }; + + FlyHit(EVoid) : CEnemyFly::FlyHit { + // fly + if (CalcDist(m_penEnemy) <= 7.5f) { + if (m_EdtType == DT_SOLDIER) { + jump FlyOnEnemy(); + } else { + jump FlyBurn(); + } + } + + // run to enemy + m_fShootTime = _pTimer->CurrentTick() + 0.25f; + return EReturn(); + }; + + FlyOnEnemy(EVoid) { + StartModelAnim(DRAGONMAN_ANIM_AIRATTACKCLOSELOOP, 0); + + // jump + FLOAT3D vDir = PlayerDestinationPos(); + vDir = (vDir - GetPlacement().pl_PositionVector).Normalize(); + vDir *= !GetRotationMatrix(); + vDir *= m_fFlyCloseRunSpeed*1.9f; + SetDesiredTranslation(vDir); + PlaySound(m_soSound, SOUND_KICK, SOF_3D); + + // animation - IGNORE DAMAGE WOUND - + SpawnReminder(this, 0.9f, 0); + m_iChargeHitAnimation = DRAGONMAN_ANIM_AIRATTACKCLOSELOOP; + if (m_EdtType == DT_SOLDIER) { + m_fChargeHitDamage = 25.0f; + m_fChargeHitSpeed = 15.0f; + } else if (m_EdtType == DT_SERGEANT) { + m_fChargeHitDamage = 30.0f; + m_fChargeHitSpeed = 20.0f; + } else if (TRUE) { + m_fChargeHitDamage = 30.0f; + m_fChargeHitSpeed = 20.0f; + } + m_fChargeHitAngle = 0.0f; + autocall CEnemyBase::ChargeHitEnemy() EReturn; + + StandingAnim(); + autowait(0.3f); + return EReturn(); + }; + + FlyBurn(EVoid) { + StartModelAnim(DRAGONMAN_ANIM_AIRATTACK02, 0); + + // burn + m_fFireTime = _pTimer->CurrentTick(); + FireFlame(); + m_bBurnEnemy = TRUE; + PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP); + while (m_bBurnEnemy) { + m_fMoveFrequency = 0.1f; + wait(m_fMoveFrequency) { + // flame + on (EBegin) : { + m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector; + // rotate to enemy + m_aRotateSpeed = 10000.0f; + m_fMoveSpeed = 0.0f; + // flame + FireFlame(); + // stop + if (_pTimer->CurrentTick()-m_fFireTime >= 1.29f) { + m_bBurnEnemy = FALSE; + stop; + } + // adjust direction and speed + ULONG ulFlags = SetDesiredMovement(); + MovementAnimation(ulFlags); + resume; + } + on (ETimer) : { stop; } + } + } + m_soSound.Stop(); + + // link last flame with nothing (if not NULL or deleted) + if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) { + ((CProjectile&)*m_penFlame).m_penParticles = NULL; + m_penFlame = NULL; + } + + StandingAnim(); + autowait(0.3f); + return EReturn(); + }; + + Fire(EVoid) : CEnemyBase::Fire { + // fire projectile + StartModelAnim(DRAGONMAN_ANIM_GROUNDATTACKCLOSELOOP, 0); + autowait(0.3f); + if (m_EdtType != DT_MONSTER) { + ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(GROUND_RIGHT_FIRE1), ANGLE3D(0, 0, 0)); + } else { + ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(GROUND_RIGHT_FIRE1), ANGLE3D(0, 0, 0)); + } + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(0.8f); + if (m_EdtType != DT_MONSTER) { + ShootProjectile(PRT_DRAGONMAN_FIRE, GetStretchedVector(GROUND_LEFT_FIRE1), ANGLE3D(0, 0, 0)); + } else if (m_EdtType == DT_MONSTER) { + ShootProjectile(PRT_DRAGONMAN_STRONG_FIRE, GetStretchedVector(GROUND_LEFT_FIRE1), ANGLE3D(0, 0, 0)); + } + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(0.55f); + StandingAnim(); + autowait(FRnd() + _pTimer->TickQuantum); + return EReturn(); + }; + + Hit(EVoid) : CEnemyBase::Hit { + // burn enemy + if (m_EdtType == DT_SERGEANT && CalcDist(m_penEnemy) <= 6.0f || + m_EdtType == DT_MONSTER && CalcDist(m_penEnemy) <= 20.0f) { + jump BurnEnemy(); + } + + // run to enemy + m_fShootTime = _pTimer->CurrentTick() + 0.25f; + return EReturn(); + }; + + BurnEnemy(EVoid) { + StartModelAnim(DRAGONMAN_ANIM_GROUNDATTACKDISTANT, 0); + + // burn + m_fFireTime = _pTimer->CurrentTick(); + FireFlame(); + m_bBurnEnemy = TRUE; + PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP); + while (m_bBurnEnemy) { + m_fMoveFrequency = 0.1f; + wait(m_fMoveFrequency) { + // flame + on (EBegin) : { + m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector; + // rotate to enemy + m_fMoveSpeed = 0.0f; + m_aRotateSpeed = 10000.0f; + // adjust direction and speed + SetDesiredMovement(); + // flame + FireFlame(); + // stop + if (_pTimer->CurrentTick()-m_fFireTime >= 1.29f) { + m_bBurnEnemy = FALSE; + stop; + } + resume; + } + on (ETimer) : { stop; } + } + } + m_soSound.Stop(); + + // link last flame with nothing (if not NULL or deleted) + if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) { + ((CProjectile&)*m_penFlame).m_penParticles = NULL; + m_penFlame = NULL; + } + + StandingAnim(); + autowait(0.3f); + return EReturn(); + }; + + + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + + if (m_EdtType == DT_SOLDIER) { + GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f)); + ModelChangeNotify(); + SetHealth(150.0f); + m_fMaxHealth = 150.0f; + m_fDamageWounded = 100.0f; + } else if (m_EdtType == DT_SERGEANT) { + GetModelObject()->StretchModel(FLOAT3D(2.0f, 2.0f, 2.0f)); + ModelChangeNotify(); + SetHealth(450.0f); + m_fMaxHealth = 450.0f; + m_fDamageWounded = 300.0f; + } else if (TRUE) { + GetModelObject()->StretchModel(FLOAT3D(4.0f, 4.0f, 4.0f)); + ModelChangeNotify(); + SetHealth(1350.0f); + m_fMaxHealth = 1350.0f; + m_fDamageWounded = 1000.0f; + } + en_tmMaxHoldBreath = 10.0f; + en_fDensity = 2000.0f; + + // set your appearance + SetModel(MODEL_DRAGONMAN); + if (m_EdtType == DT_SOLDIER) { + SetModelMainTexture(TEXTURE_DRAGONMAN1); + } else if (m_EdtType == DT_SERGEANT) { + SetModelMainTexture(TEXTURE_DRAGONMAN2); + } else if (TRUE) { + SetModelMainTexture(TEXTURE_DRAGONMAN3); + } + // setup moving speed + if (m_EdtType == DT_SOLDIER) { + m_fWalkSpeed = FRnd()*1.5f + 2.5f; + m_aWalkRotateSpeed = FRnd()*20.0f + 50.0f; + m_fAttackRunSpeed = FRnd()*2.0f + 11.0f; + m_aAttackRotateSpeed = FRnd()*75 + 350.0f; + m_fCloseRunSpeed = FRnd()*2.0f + 6.0f; + m_aCloseRotateSpeed = FRnd()*50 + 500.0f; + } else if (m_EdtType == DT_SERGEANT) { + m_fWalkSpeed = (FRnd()*1.5f + 2.5f)*1.5f; + m_aWalkRotateSpeed = FRnd()*20.0f + 50.0f; + m_fAttackRunSpeed = (FRnd()*2.0f + 11.0f)*2; + m_aAttackRotateSpeed = FRnd()*75 + 350.0f; + m_fCloseRunSpeed = (FRnd()*2.0f + 6.0f)*1.5f; + m_aCloseRotateSpeed = FRnd()*50 + 500.0f; + } else if (TRUE) { + m_fWalkSpeed = (FRnd()*1.5f + 2.5f)*2; + m_aWalkRotateSpeed = FRnd()*20.0f + 50.0f; + m_fAttackRunSpeed = (FRnd()*2.0f + 11.0f)*4; + m_aAttackRotateSpeed = FRnd()*75 + 350.0f; + m_fCloseRunSpeed = (FRnd()*2.0f + 6.0f)*2; + m_aCloseRotateSpeed = FRnd()*50 + 500.0f; + } + // setup attack distances + m_fAttackDistance = 100.0f; + if (m_EdtType == DT_SOLDIER) { + m_fCloseDistance = 0.0f; + m_fStopDistance = 10.0f; + m_fFlyCloseDistance = 12.5f; + m_fFlyStopDistance = 0.0f; + m_iScore = 1000; + } else if (m_EdtType == DT_SERGEANT) { + m_fCloseDistance = 20.0f; + m_fStopDistance = 0.0f; + m_fFlyCloseDistance = 12.5f*2; + m_fFlyStopDistance = 0.0f; + m_iScore = 2000; + } else { + m_fCloseDistance = 40.0f; + m_fStopDistance = 0.0f; + m_fFlyCloseDistance = 12.5f*4; + m_fFlyStopDistance = 0.0f; + m_iScore = 10000; + } + m_fAttackFireTime = 3.0f; + m_fCloseFireTime = 2.0f; + m_fIgnoreRange = 200.0f; + // fly moving properties + m_fFlyWalkSpeed = FRnd()/2 + 2.0f; + m_aFlyWalkRotateSpeed = FRnd()*10.0f + 50.0f; + m_fFlyAttackRunSpeed = FRnd()*2.0f + 10.0f; + m_aFlyAttackRotateSpeed = FRnd()*75 + 350.0f; + m_fFlyCloseRunSpeed = FRnd()*2.0f + 9.0f; + m_aFlyCloseRotateSpeed = FRnd()*50 + 600.0f; + // attack properties - CAN BE SET + m_fFlyAttackDistance = 100.0f; + m_fFlyAttackFireTime = 3.0f; + m_fFlyCloseFireTime = 2.0f; + m_fFlyIgnoreRange = 200.0f; + // damage/explode properties + m_fBlowUpAmount = 100.0f; + m_fBodyParts = 8; + // flame source + m_vFlameSource = FLOAT3D(0, 0, 0); + m_fGroundToAirSpeed = m_fFlyAttackRunSpeed; + m_fAirToGroundSpeed = m_fFlyAttackRunSpeed*2; + m_fAirToGroundMin = 0.1f; + m_fAirToGroundMax = 0.1f; + + // continue behavior in base class + jump CEnemyFly::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/EffectMarker.cpp b/Sources/EntitiesMP/EffectMarker.cpp new file mode 100644 index 0000000..2f9fb41 --- /dev/null +++ b/Sources/EntitiesMP/EffectMarker.cpp @@ -0,0 +1,589 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" + +#include "StdH.h" +#include "EntitiesMP/Effector.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" + +#include +#include +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" + +extern void CBasicEffect_OnPrecache(CDLLEntityClass *pdec, INDEX iUser); + +void CEffectMarker::SetDefaultProperties(void) { + m_emtType = EMT_NONE ; + m_penModel = NULL; + m_tmEffectLife = 10.0f; + m_penModel2 = NULL; + m_penEffector = NULL; + m_fShakeFalloff = 250.0f; + m_fShakeFade = 3.0f; + m_fShakeIntensityY = 0.1f; + m_fShakeFrequencyY = 5.0f; + m_fShakeIntensityB = 2.5f; + m_fShakeFrequencyB = 7.2f; + m_fShakeIntensityZ = 0.0f; + m_fShakeFrequencyZ = 5.0f; + m_betType = BET_ROCKET ; + m_fStretch = 1.0f; + m_colColor = COLOR(C_WHITE | CT_TRANSPARENT ); + CMarker::SetDefaultProperties(); +} + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +void CEffectMarker::Precache(void) +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +switch(m_betType ) +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_BASIC_EFFECT : +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CDLLEntityClass * pdec = & CBasicEffect_DLLClass ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CBasicEffect_OnPrecache (pdec , m_emtType ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} + +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +BOOL CEffectMarker::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(penTarget == NULL ) +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +return FALSE ; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(slPropertyOffset == offsetof (CEffectMarker , m_penModel ) || +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +slPropertyOffset == offsetof (CEffectMarker , m_penModel2 )) +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +return IsOfClass (penTarget , "ModelHolder2"); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +return TRUE ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} + +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +BOOL CEffectMarker::HandleEvent(const CEntityEvent & ee) +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(ee . ee_slEvent == EVENTCODE_ETrigger ) +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +switch(m_emtType ) +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_SET_PLACEMENT : +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penModel != NULL && m_penModel2 != NULL ) +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penModel -> Teleport (m_penModel2 -> GetPlacement () , FALSE ); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_SET_PARENT : +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penModel != NULL && m_penModel2 != NULL ) +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penModel -> SetParent (m_penModel2 ); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_CLEAR_PARENT : +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penModel != NULL ) +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penModel -> SetParent (NULL ); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_SHAKE_IT_BABY : +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CWorldSettingsController * pwsc = NULL ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CBackgroundViewer * penBcgViewer = (CBackgroundViewer *) GetWorld () -> GetBackgroundViewer (); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(penBcgViewer != NULL && penBcgViewer -> m_penWorldSettingsController != NULL ) +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc = (CWorldSettingsController *) & * penBcgViewer -> m_penWorldSettingsController ; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_tmShakeStarted = _pTimer -> CurrentTick (); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_vShakePos = GetPlacement () . pl_PositionVector ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_fShakeFalloff = m_fShakeFalloff ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_fShakeFade = m_fShakeFade ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_fShakeIntensityZ = m_fShakeIntensityZ ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_tmShakeFrequencyZ = m_fShakeFrequencyZ ; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_fShakeIntensityY = m_fShakeIntensityY ; +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_tmShakeFrequencyY = m_fShakeFrequencyY ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_fShakeIntensityB = m_fShakeIntensityB ; +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_tmShakeFrequencyB = m_fShakeFrequencyB ; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_bShakeFadeIn = FALSE ; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_HIDE_ENTITY : +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penTarget != NULL ) +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penTarget -> SetFlags (m_penTarget -> GetFlags () | ENF_HIDDEN ); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_SHOW_ENTITY : +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penTarget != NULL ) +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penTarget -> SetFlags (m_penTarget -> GetFlags () & ~ ENF_HIDDEN ); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_PLAYER_APPEAR : +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penModel != NULL && IsOfClass (m_penModel , "ModelHolder2")) +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CModelObject * pmo = m_penModel -> GetModelObject (); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(pmo != NULL ) +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CPlacement3D plFX = m_penModel -> GetPlacement (); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CEntity * penFX = CreateEntity (plFX , CLASS_EFFECTOR ); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +ESpawnEffector eSpawnFX ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . tmLifeTime = m_tmEffectLife ; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . eetType = ET_PORTAL_LIGHTNING ; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . penModel = m_penModel ; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +penFX -> Initialize (eSpawnFX ); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_APPEARING_BIG_BLUE_FLARE : +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CPlacement3D plFX = GetPlacement (); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CEntity * penFX = CreateEntity (plFX , CLASS_EFFECTOR ); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +ESpawnEffector eSpawnFX ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . tmLifeTime = m_tmEffectLife ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . fSize = 1.0f; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . eetType = ET_SIZING_BIG_BLUE_FLARE ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +penFX -> Initialize (eSpawnFX ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_BLEND_MODELS : +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penModel != NULL && IsOfClass (m_penModel , "ModelHolder2") && +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penModel2 != NULL && IsOfClass (m_penModel2 , "ModelHolder2")) +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penEffector == NULL ) +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CModelObject * pmo1 = m_penModel -> GetModelObject (); +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CModelObject * pmo2 = m_penModel2 -> GetModelObject (); +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(pmo1 != NULL && pmo2 != NULL ) +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CPlacement3D plFX = m_penModel -> GetPlacement (); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CEntity * penFX = CreateEntity (plFX , CLASS_EFFECTOR ); +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +ESpawnEffector eSpawnFX ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . tmLifeTime = m_tmEffectLife ; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . eetType = ET_MORPH_MODELS ; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . penModel = m_penModel ; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . penModel2 = m_penModel2 ; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +penFX -> Initialize (eSpawnFX ); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penEffector = penFX ; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +else +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penEffector -> SendEvent (ETrigger ()); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_DISAPPEAR_MODEL : +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penModel != NULL && IsOfClass (m_penModel , "ModelHolder2")) +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penEffector == NULL ) +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CModelObject * pmo = m_penModel -> GetModelObject (); +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(pmo != NULL ) +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CPlacement3D plFX = m_penModel -> GetPlacement (); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CEntity * penFX = CreateEntity (plFX , CLASS_EFFECTOR ); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +ESpawnEffector eSpawnFX ; +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . tmLifeTime = m_tmEffectLife ; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . eetType = ET_DISAPPEAR_MODEL ; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . penModel = m_penModel ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +penFX -> Initialize (eSpawnFX ); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penEffector = penFX ; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +else +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penEffector -> SendEvent (ETrigger ()); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_APPEAR_MODEL : +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penModel != NULL && IsOfClass (m_penModel , "ModelHolder2")) +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penEffector == NULL ) +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CModelObject * pmo = m_penModel -> GetModelObject (); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(pmo != NULL ) +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CPlacement3D plFX = m_penModel -> GetPlacement (); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CEntity * penFX = CreateEntity (plFX , CLASS_EFFECTOR ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +ESpawnEffector eSpawnFX ; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . tmLifeTime = m_tmEffectLife ; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . eetType = ET_APPEAR_MODEL ; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . penModel = m_penModel ; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +penFX -> Initialize (eSpawnFX ); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penEffector = penFX ; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +else +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penEffector -> SendEvent (ETrigger ()); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_BASIC_EFFECT : +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CPlacement3D plEffect = GetPlacement (); +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CEntityPointer penEffect = CreateEntity (plEffect , CLASS_BASIC_EFFECT ); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +ESpawnEffect eSpawnEffect ; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnEffect . betType = m_betType ; +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnEffect . vStretch = FLOAT3D (m_fStretch , m_fStretch , m_fStretch ); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +penEffect -> Initialize (eSpawnEffect ); +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_GLARE : +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(pwsc != NULL ) +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_colGlade = m_colColor ; +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_tmGlaringStarted = _pTimer -> CurrentTick (); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_tmGlaringEnded = pwsc -> m_tmGlaringStarted + m_tmEffectLife , +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_fGlaringFadeInRatio = 0.2f; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +pwsc -> m_fGlaringFadeOutRatio = 0.7f; +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +else if(ee . ee_slEvent == EVENTCODE_EActivate ) +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +switch(m_emtType ) +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_APPEAR_DISAPPEAR : +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penModel != NULL && IsOfClass (m_penModel , "ModelHolder2")) +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CModelObject * pmo = m_penModel -> GetModelObject (); +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(pmo != NULL ) +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CPlacement3D plFX = m_penModel -> GetPlacement (); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CEntity * penFX = CreateEntity (plFX , CLASS_EFFECTOR ); +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +ESpawnEffector eSpawnFX ; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . tmLifeTime = m_tmEffectLife ; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . eetType = ET_APPEAR_MODEL_NOW ; +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . penModel = m_penModel ; +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +penFX -> Initialize (eSpawnFX ); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penEffector = penFX ; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +else if(ee . ee_slEvent == EVENTCODE_EDeactivate ) +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +switch(m_emtType ) +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +case EMT_APPEAR_DISAPPEAR : +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(m_penModel != NULL && IsOfClass (m_penModel , "ModelHolder2")) +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CModelObject * pmo = m_penModel -> GetModelObject (); +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +if(pmo != NULL ) +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +{ +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CPlacement3D plFX = m_penModel -> GetPlacement (); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +CEntity * penFX = CreateEntity (plFX , CLASS_EFFECTOR ); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +ESpawnEffector eSpawnFX ; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . tmLifeTime = m_tmEffectLife ; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . eetType = ET_DISAPPEAR_MODEL_NOW ; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +eSpawnFX . penModel = m_penModel ; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +penFX -> Initialize (eSpawnFX ); +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penEffector = penFX ; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +break ; +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +return FALSE ; +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +} +BOOL CEffectMarker:: +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEffectMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEffectMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +InitAsEditorModel (); +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +SetModel (MODEL_MARKER ); +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +m_penEffector = NULL ; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EffectMarker.es b/Sources/EntitiesMP/EffectMarker.es new file mode 100644 index 0000000..6b117ba --- /dev/null +++ b/Sources/EntitiesMP/EffectMarker.es @@ -0,0 +1,366 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +611 +%{ +#include "StdH.h" +#include "EntitiesMP/Effector.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +%} + +uses "EntitiesMP/Marker"; +uses "EntitiesMP/BasicEffects"; +enum EffectMarkerType { + 0 EMT_NONE "None", // no FX + 1 EMT_PLAYER_APPEAR "Player appear", // effect of player appearing + 2 EMT_APPEARING_BIG_BLUE_FLARE "Appear big blue flare", // appear big blue flare + 3 EMT_BLEND_MODELS "Blend two models", // blend between two models + 4 EMT_DISAPPEAR_MODEL "Disappear model", // disappear model + 5 EMT_APPEAR_MODEL "Appear model", // appear model + 6 EMT_HIDE_ENTITY "Hide entity", // hide entity + 7 EMT_SHOW_ENTITY "Show entity", // show entity + 8 EMT_SHAKE_IT_BABY "Shake it baby", // earth quaker + 9 EMT_APPEAR_DISAPPEAR "Appear or Disappear model", // appear/disappear model + 10 EMT_SET_PLACEMENT "Teleport", // teleport entity + 11 EMT_SET_PARENT "Set parent", // set parent + 12 EMT_CLEAR_PARENT "Clear parent", // clear parent + 13 EMT_BASIC_EFFECT "Basic effect", // spawn basic effect + 14 EMT_GLARE "Glare", // glare screen +}; + +%{ +extern void CBasicEffect_OnPrecache(CDLLEntityClass *pdec, INDEX iUser); +%} + +class CEffectMarker: CMarker +{ +name "Effect Marker"; +thumbnail "Thumbnails\\EffectMarker.tbn"; + +properties: + + 1 enum EffectMarkerType m_emtType "Effect type" 'Y' = EMT_NONE, // type of effect + 2 CEntityPointer m_penModel "FX Entity 1" 'E', // model holder used in this effect + 3 FLOAT m_tmEffectLife "FX Life time" 'L' = 10.0f, // life time of this effect + 4 CEntityPointer m_penModel2 "FX Entity 2" 'R', // second model holder used in this effect + 5 CEntityPointer m_penEffector, // ptr to spawned effector + 6 FLOAT m_fShakeFalloff "Shake fall off" = 250.0f, // ShakeFalloff + 7 FLOAT m_fShakeFade "Shake fade" = 3.0f, // ShakeFade + 8 FLOAT m_fShakeIntensityY "Shake intensity Y" = 0.1f, // ShakeIntensityY + 9 FLOAT m_fShakeFrequencyY "Shake frequency Y" = 5.0f, // ShakeFrequencyY + 10 FLOAT m_fShakeIntensityB "Shake intensity B" = 2.5f, // ShakeIntensityB + 11 FLOAT m_fShakeFrequencyB "Shake frequency B" = 7.2f, // ShakeFrequencyB + 12 FLOAT m_fShakeIntensityZ "Shake intensity Z" = 0.0f, // ShakeIntensityZ + 13 FLOAT m_fShakeFrequencyZ "Shake frequency Z" = 5.0f, // ShakeFrequencyZ + 20 enum BasicEffectType m_betType "Basic effect type" 'P' = BET_ROCKET, // type of basic effect + 21 FLOAT m_fStretch "Stretch" 'S' = 1.0f, + 22 COLOR m_colColor "FX color" 'C' = COLOR(C_WHITE|CT_TRANSPARENT), + +components: + + 1 model MODEL_MARKER "Models\\Editor\\Axis.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex", + 3 class CLASS_EFFECTOR "Classes\\Effector.ecl", + 4 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + + +functions: + void Precache(void) + { + switch(m_betType) + { + case EMT_BASIC_EFFECT: + CDLLEntityClass *pdec = &CBasicEffect_DLLClass; + // precache + CBasicEffect_OnPrecache(pdec, m_emtType); + break; + } + } + + // Validate offered target for one property + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if(penTarget==NULL) + { + return FALSE; + } + // if should be modelobject + if( slPropertyOffset==offsetof(CEffectMarker, m_penModel) || + slPropertyOffset==offsetof(CEffectMarker, m_penModel2) ) + { + return IsOfClass(penTarget, "ModelHolder2"); + } + return TRUE; + } + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + if (ee.ee_slEvent==EVENTCODE_ETrigger) + { + switch(m_emtType) + { + case EMT_SET_PLACEMENT: + { + if(m_penModel!=NULL && m_penModel2!=NULL) + { + m_penModel->Teleport(m_penModel2->GetPlacement(), FALSE); + } + break; + } + case EMT_SET_PARENT: + { + if(m_penModel!=NULL && m_penModel2!=NULL) + { + m_penModel->SetParent(m_penModel2); + } + break; + } + case EMT_CLEAR_PARENT: + { + if(m_penModel!=NULL) + { + m_penModel->SetParent(NULL); + } + break; + } + case EMT_SHAKE_IT_BABY: + { + // ---------- Apply shake + CWorldSettingsController *pwsc = NULL; + // obtain bcg viewer + CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) GetWorld()->GetBackgroundViewer(); + if( penBcgViewer!=NULL && penBcgViewer->m_penWorldSettingsController!=NULL) + { + pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController; + pwsc->m_tmShakeStarted = _pTimer->CurrentTick(); + pwsc->m_vShakePos = GetPlacement().pl_PositionVector; + pwsc->m_fShakeFalloff = m_fShakeFalloff; + pwsc->m_fShakeFade = m_fShakeFade; + pwsc->m_fShakeIntensityZ = m_fShakeIntensityZ; + pwsc->m_tmShakeFrequencyZ = m_fShakeFrequencyZ; + pwsc->m_fShakeIntensityY = m_fShakeIntensityY; + pwsc->m_tmShakeFrequencyY = m_fShakeFrequencyY; + pwsc->m_fShakeIntensityB = m_fShakeIntensityB; + pwsc->m_tmShakeFrequencyB = m_fShakeFrequencyB; + pwsc->m_bShakeFadeIn = FALSE; + } + break; + } + case EMT_HIDE_ENTITY: + { + if( m_penTarget!=NULL) + { + m_penTarget->SetFlags(m_penTarget->GetFlags()|ENF_HIDDEN); + } + break; + } + case EMT_SHOW_ENTITY: + { + if( m_penTarget!=NULL) + { + m_penTarget->SetFlags(m_penTarget->GetFlags()&~ENF_HIDDEN); + } + break; + } + case EMT_PLAYER_APPEAR: + if( m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2") ) + { + CModelObject *pmo = m_penModel->GetModelObject(); + if( pmo != NULL) + { + // spawn effect + CPlacement3D plFX= m_penModel->GetPlacement(); + CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR); + ESpawnEffector eSpawnFX; + eSpawnFX.tmLifeTime = m_tmEffectLife; + eSpawnFX.eetType = ET_PORTAL_LIGHTNING; + eSpawnFX.penModel = m_penModel; + penFX->Initialize( eSpawnFX); + } + } + break; + case EMT_APPEARING_BIG_BLUE_FLARE: + { + // spawn effect + CPlacement3D plFX= GetPlacement(); + CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR); + ESpawnEffector eSpawnFX; + eSpawnFX.tmLifeTime = m_tmEffectLife; + eSpawnFX.fSize = 1.0f; + eSpawnFX.eetType = ET_SIZING_BIG_BLUE_FLARE; + penFX->Initialize( eSpawnFX); + break; + } + case EMT_BLEND_MODELS: + if(m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2") && + m_penModel2!=NULL && IsOfClass(m_penModel2, "ModelHolder2") ) + { + if( m_penEffector == NULL) + { + CModelObject *pmo1 = m_penModel->GetModelObject(); + CModelObject *pmo2 = m_penModel2->GetModelObject(); + if( pmo1 != NULL && pmo2 != NULL) + { + // spawn effect + CPlacement3D plFX= m_penModel->GetPlacement(); + CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR); + ESpawnEffector eSpawnFX; + eSpawnFX.tmLifeTime = m_tmEffectLife; + eSpawnFX.eetType = ET_MORPH_MODELS; + eSpawnFX.penModel = m_penModel; + eSpawnFX.penModel2 = m_penModel2; + penFX->Initialize( eSpawnFX); + m_penEffector = penFX; + } + } + else + { + m_penEffector->SendEvent(ETrigger()); + } + } + break; + case EMT_DISAPPEAR_MODEL: + if(m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2")) + { + if( m_penEffector == NULL) + { + CModelObject *pmo = m_penModel->GetModelObject(); + if( pmo != NULL) + { + // spawn effect + CPlacement3D plFX= m_penModel->GetPlacement(); + CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR); + ESpawnEffector eSpawnFX; + eSpawnFX.tmLifeTime = m_tmEffectLife; + eSpawnFX.eetType = ET_DISAPPEAR_MODEL; + eSpawnFX.penModel = m_penModel; + penFX->Initialize( eSpawnFX); + m_penEffector = penFX; + } + } + else + { + m_penEffector->SendEvent(ETrigger()); + } + } + break; + case EMT_APPEAR_MODEL: + if(m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2")) + { + if( m_penEffector == NULL) + { + CModelObject *pmo = m_penModel->GetModelObject(); + if( pmo != NULL) + { + // spawn effect + CPlacement3D plFX= m_penModel->GetPlacement(); + CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR); + ESpawnEffector eSpawnFX; + eSpawnFX.tmLifeTime = m_tmEffectLife; + eSpawnFX.eetType = ET_APPEAR_MODEL; + eSpawnFX.penModel = m_penModel; + penFX->Initialize( eSpawnFX); + m_penEffector = penFX; + } + } + else + { + m_penEffector->SendEvent(ETrigger()); + } + } + break; + case EMT_BASIC_EFFECT: + { + // spawn effect + CPlacement3D plEffect = GetPlacement(); + CEntityPointer penEffect = CreateEntity(plEffect, CLASS_BASIC_EFFECT); + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = m_betType; + eSpawnEffect.vStretch = FLOAT3D(m_fStretch,m_fStretch,m_fStretch); + penEffect->Initialize(eSpawnEffect); + } + break; + case EMT_GLARE: + CWorldSettingsController *pwsc = GetWSC(this); + if (pwsc!=NULL) + { + pwsc->m_colGlade=m_colColor; + pwsc->m_tmGlaringStarted = _pTimer->CurrentTick(); + pwsc->m_tmGlaringEnded = pwsc->m_tmGlaringStarted+m_tmEffectLife, + pwsc->m_fGlaringFadeInRatio = 0.2f; + pwsc->m_fGlaringFadeOutRatio = 0.7f; + } + break; + } + } + else if (ee.ee_slEvent==EVENTCODE_EActivate) + { + switch(m_emtType) + { + case EMT_APPEAR_DISAPPEAR: + if(m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2")) + { + CModelObject *pmo = m_penModel->GetModelObject(); + if( pmo != NULL) + { + // spawn effect + CPlacement3D plFX= m_penModel->GetPlacement(); + CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR); + ESpawnEffector eSpawnFX; + eSpawnFX.tmLifeTime = m_tmEffectLife; + eSpawnFX.eetType = ET_APPEAR_MODEL_NOW; + eSpawnFX.penModel = m_penModel; + penFX->Initialize( eSpawnFX); + m_penEffector = penFX; + } + } + break; + } + } + else if (ee.ee_slEvent==EVENTCODE_EDeactivate) + { + switch(m_emtType) + { + case EMT_APPEAR_DISAPPEAR: + if(m_penModel!=NULL && IsOfClass(m_penModel, "ModelHolder2")) + { + CModelObject *pmo = m_penModel->GetModelObject(); + if( pmo != NULL) + { + // spawn effect + CPlacement3D plFX= m_penModel->GetPlacement(); + CEntity *penFX = CreateEntity( plFX, CLASS_EFFECTOR); + ESpawnEffector eSpawnFX; + eSpawnFX.tmLifeTime = m_tmEffectLife; + eSpawnFX.eetType = ET_DISAPPEAR_MODEL_NOW; + eSpawnFX.penModel = m_penModel; + penFX->Initialize( eSpawnFX); + m_penEffector = penFX; + } + } + break; + } + } + return FALSE; + } + +procedures: + + Main() + { + // init model + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + // reset entity ptr + m_penEffector = NULL; + return; + } +}; + diff --git a/Sources/EntitiesMP/EffectMarker.h b/Sources/EntitiesMP/EffectMarker.h new file mode 100644 index 0000000..721882a --- /dev/null +++ b/Sources/EntitiesMP/EffectMarker.h @@ -0,0 +1,62 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_EffectMarker_INCLUDED +#define _EntitiesMP_EffectMarker_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType EffectMarkerType_enum; +enum EffectMarkerType { + EMT_NONE = 0, + EMT_PLAYER_APPEAR = 1, + EMT_APPEARING_BIG_BLUE_FLARE = 2, + EMT_BLEND_MODELS = 3, + EMT_DISAPPEAR_MODEL = 4, + EMT_APPEAR_MODEL = 5, + EMT_HIDE_ENTITY = 6, + EMT_SHOW_ENTITY = 7, + EMT_SHAKE_IT_BABY = 8, + EMT_APPEAR_DISAPPEAR = 9, + EMT_SET_PLACEMENT = 10, + EMT_SET_PARENT = 11, + EMT_CLEAR_PARENT = 12, + EMT_BASIC_EFFECT = 13, + EMT_GLARE = 14, +}; +DECL_DLL inline void ClearToDefault(EffectMarkerType &e) { e = (EffectMarkerType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CEffectMarker_DLLClass; +class CEffectMarker : public CMarker { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum EffectMarkerType m_emtType; + CEntityPointer m_penModel; + FLOAT m_tmEffectLife; + CEntityPointer m_penModel2; + CEntityPointer m_penEffector; + FLOAT m_fShakeFalloff; + FLOAT m_fShakeFade; + FLOAT m_fShakeIntensityY; + FLOAT m_fShakeFrequencyY; + FLOAT m_fShakeIntensityB; + FLOAT m_fShakeFrequencyB; + FLOAT m_fShakeIntensityZ; + FLOAT m_fShakeFrequencyZ; + enum BasicEffectType m_betType; + FLOAT m_fStretch; + COLOR m_colColor; + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +void Precache(void); + +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CEffectMarker_Main 1 + BOOL +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_EffectMarker_INCLUDED diff --git a/Sources/EntitiesMP/EffectMarker_tables.h b/Sources/EntitiesMP/EffectMarker_tables.h new file mode 100644 index 0000000..ed6bd7e --- /dev/null +++ b/Sources/EntitiesMP/EffectMarker_tables.h @@ -0,0 +1,73 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(EffectMarkerType) + EP_ENUMVALUE(EMT_NONE, "None"), + EP_ENUMVALUE(EMT_PLAYER_APPEAR, "Player appear"), + EP_ENUMVALUE(EMT_APPEARING_BIG_BLUE_FLARE, "Appear big blue flare"), + EP_ENUMVALUE(EMT_BLEND_MODELS, "Blend two models"), + EP_ENUMVALUE(EMT_DISAPPEAR_MODEL, "Disappear model"), + EP_ENUMVALUE(EMT_APPEAR_MODEL, "Appear model"), + EP_ENUMVALUE(EMT_HIDE_ENTITY, "Hide entity"), + EP_ENUMVALUE(EMT_SHOW_ENTITY, "Show entity"), + EP_ENUMVALUE(EMT_SHAKE_IT_BABY, "Shake it baby"), + EP_ENUMVALUE(EMT_APPEAR_DISAPPEAR, "Appear or Disappear model"), + EP_ENUMVALUE(EMT_SET_PLACEMENT, "Teleport"), + EP_ENUMVALUE(EMT_SET_PARENT, "Set parent"), + EP_ENUMVALUE(EMT_CLEAR_PARENT, "Clear parent"), + EP_ENUMVALUE(EMT_BASIC_EFFECT, "Basic effect"), + EP_ENUMVALUE(EMT_GLARE, "Glare"), +EP_ENUMEND(EffectMarkerType); + +#define ENTITYCLASS CEffectMarker + +CEntityProperty CEffectMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &EffectMarkerType_enum, (0x00000263<<8)+1, offsetof(CEffectMarker, m_emtType), "Effect type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000263<<8)+2, offsetof(CEffectMarker, m_penModel), "FX Entity 1", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000263<<8)+3, offsetof(CEffectMarker, m_tmEffectLife), "FX Life time", 'L', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000263<<8)+4, offsetof(CEffectMarker, m_penModel2), "FX Entity 2", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000263<<8)+5, offsetof(CEffectMarker, m_penEffector), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000263<<8)+6, offsetof(CEffectMarker, m_fShakeFalloff), "Shake fall off", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000263<<8)+7, offsetof(CEffectMarker, m_fShakeFade), "Shake fade", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000263<<8)+8, offsetof(CEffectMarker, m_fShakeIntensityY), "Shake intensity Y", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000263<<8)+9, offsetof(CEffectMarker, m_fShakeFrequencyY), "Shake frequency Y", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000263<<8)+10, offsetof(CEffectMarker, m_fShakeIntensityB), "Shake intensity B", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000263<<8)+11, offsetof(CEffectMarker, m_fShakeFrequencyB), "Shake frequency B", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000263<<8)+12, offsetof(CEffectMarker, m_fShakeIntensityZ), "Shake intensity Z", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000263<<8)+13, offsetof(CEffectMarker, m_fShakeFrequencyZ), "Shake frequency Z", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &BasicEffectType_enum, (0x00000263<<8)+20, offsetof(CEffectMarker, m_betType), "Basic effect type", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000263<<8)+21, offsetof(CEffectMarker, m_fStretch), "Stretch", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x00000263<<8)+22, offsetof(CEffectMarker, m_colColor), "FX color", 'C', 0x7F0000FFUL, 0), +}; +#define CEffectMarker_propertiesct ARRAYCOUNT(CEffectMarker_properties) + +CEntityComponent CEffectMarker_components[] = { +#define MODEL_MARKER ((0x00000263<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_MARKER ((0x00000263<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Vector.tex"), +#define CLASS_EFFECTOR ((0x00000263<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_EFFECTOR, "EFNM" "Classes\\Effector.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000263<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +}; +#define CEffectMarker_componentsct ARRAYCOUNT(CEffectMarker_components) + +CEventHandlerEntry CEffectMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CEffectMarker:: +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/EffectMarker.es" +Main),DEBUGSTRING("CEffectMarker::Main")}, +}; +#define CEffectMarker_handlersct ARRAYCOUNT(CEffectMarker_handlers) + +CEntity *CEffectMarker_New(void) { return new CEffectMarker; }; +void CEffectMarker_OnInitClass(void) {}; +void CEffectMarker_OnEndClass(void) {}; +void CEffectMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEffectMarker_OnWorldEnd(CWorld *pwo) {}; +void CEffectMarker_OnWorldInit(CWorld *pwo) {}; +void CEffectMarker_OnWorldTick(CWorld *pwo) {}; +void CEffectMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEffectMarker, CMarker, "Effect Marker", "Thumbnails\\EffectMarker.tbn", 0x00000263); +DECLARE_CTFILENAME(_fnmCEffectMarker_tbn, "Thumbnails\\EffectMarker.tbn"); diff --git a/Sources/EntitiesMP/Effector.cpp b/Sources/EntitiesMP/Effector.cpp new file mode 100644 index 0000000..1b40062 --- /dev/null +++ b/Sources/EntitiesMP/Effector.cpp @@ -0,0 +1,730 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" + +#include "StdH.h" +#include "EntitiesMP/Effector.h" +#include + +#include +#include +CEntityEvent *ESpawnEffector::MakeCopy(void) { CEntityEvent *peeCopy = new ESpawnEffector(*this); return peeCopy;} +ESpawnEffector::ESpawnEffector() : CEntityEvent(EVENTCODE_ESpawnEffector) {; + ClearToDefault(eetType); + ClearToDefault(vDamageDir); + ClearToDefault(vDestination); + ClearToDefault(tmLifeTime); + ClearToDefault(fSize); + ClearToDefault(ctCount); + ClearToDefault(penModel); + ClearToDefault(penModel2); +}; +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" + +void CEffector_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + switch ((EffectorEffectType)iUser) + { + case ET_MOVING_RING : + pdec->PrecacheModel(MODEL_POWER_RING); + pdec->PrecacheTexture(TEXTURE_POWER_RING); + break; + case ET_DESTROY_OBELISK : + case ET_DESTROY_PYLON : + case ET_HIT_GROUND : + case ET_LIGHTNING : + case ET_SIZING_BIG_BLUE_FLARE : + case ET_SIZING_RING_FLARE : + case ET_PORTAL_LIGHTNING : + case ET_MORPH_MODELS : + case ET_DISAPPEAR_MODEL : + case ET_APPEAR_MODEL : + case ET_DISAPPEAR_MODEL_NOW : + case ET_APPEAR_MODEL_NOW : + // no precaching needed + break; + default: + ASSERT(FALSE); + } +} + +// array for model vertices in absolute space +CStaticStackArray avModelFXVertices; + +void CEffector::SetDefaultProperties(void) { + m_eetType = ET_NONE ; + m_tmStarted = 0.0f; + m_vDamageDir = FLOAT3D(0 , 0 , 0); + m_vFXDestination = FLOAT3D(0 , 0 , 0); + m_tmLifeTime = 5.0f; + m_fSize = 1.0f; + m_ctCount = 0; + m_bLightSource = FALSE ; + m_aoLightAnimation.SetData(NULL); + + m_iLightAnimation = -1; + m_bAlive = TRUE ; + m_penModel = NULL; + m_penModel2 = NULL; + m_bWaitTrigger = FALSE ; + CMovableModelEntity::SetDefaultProperties(); +} + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT CEffector::CalculateLifeRatio(FLOAT fFadeInRatio,FLOAT fFadeOutRatio) +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +TIME tmDelta = _pTimer -> GetLerpedCurrentTick () - m_tmStarted ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fLifeRatio = CalculateRatio (tmDelta , 0 , m_tmLifeTime , fFadeInRatio , fFadeOutRatio ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +return fLifeRatio ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +void CEffector::AdjustMipFactor(FLOAT & fMipFactor) +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_eetType == ET_DISAPPEAR_MODEL || m_eetType == ET_DISAPPEAR_MODEL_NOW && m_penModel != NULL ) +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +CModelObject * pmo = m_penModel -> GetModelObject (); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +TIME tmDelta = _pTimer -> GetLerpedCurrentTick () - m_tmStarted ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fLifeRatio ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_tmStarted == - 1) +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fLifeRatio = 1.0f; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +else if(tmDelta >= m_tmLifeTime ) +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fLifeRatio = 0.0f; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +else +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fLifeRatio = CalculateLifeRatio (0.0f , 1.0f); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +UBYTE ubAlpha = UBYTE (255.0f * fLifeRatio ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +COLOR col = C_WHITE | ubAlpha ; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +pmo -> mo_colBlendColor = col ; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_eetType == ET_APPEAR_MODEL || m_eetType == ET_APPEAR_MODEL_NOW && m_penModel != NULL ) +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +CModelObject * pmo = m_penModel -> GetModelObject (); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +TIME tmDelta = _pTimer -> GetLerpedCurrentTick () - m_tmStarted ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fLifeRatio ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_tmStarted == - 1) +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fLifeRatio = 0.0f; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +else if(tmDelta >= m_tmLifeTime ) +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fLifeRatio = 1.0f; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +else +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fLifeRatio = CalculateLifeRatio (1.0f , 0.0f); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +UBYTE ubAlpha = UBYTE (255.0f * fLifeRatio ); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +COLOR col = C_WHITE | ubAlpha ; +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +pmo -> mo_colBlendColor = col ; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_eetType == ET_MORPH_MODELS && m_penModel != NULL && m_penModel2 != NULL ) +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +CModelObject * pmo1 = m_penModel -> GetModelObject (); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +CModelObject * pmo2 = m_penModel2 -> GetModelObject (); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +TIME tmDelta = _pTimer -> GetLerpedCurrentTick () - m_tmStarted ; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fLifeRatio ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_tmStarted == - 1) +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fLifeRatio = 0.0f; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +else if(tmDelta >= m_tmLifeTime ) +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fLifeRatio = 1.0f; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +else +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fLifeRatio = CalculateLifeRatio (1.0f , 0.0f); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +UBYTE ubAlpha1 = UBYTE (255.0f * (1 - fLifeRatio )); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +UBYTE ubAlpha2 = 255 - ubAlpha1 ; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +COLOR col1 = C_WHITE | ubAlpha1 ; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +COLOR col2 = C_WHITE | ubAlpha2 ; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +pmo1 -> mo_colBlendColor = col1 ; +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +pmo2 -> mo_colBlendColor = col2 ; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +BOOL CEffector::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_eetType == ET_MOVING_RING ) +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fLifeRatio = CalculateLifeRatio (0.2f , 0.1f); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fT = _pTimer -> CurrentTick () - m_tmStarted ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fPulse = 1.0f; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +UBYTE ub = UBYTE (255.0f * fPulse * fLifeRatio ); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +COLOR col = RGBAToColor (ub , ub , ub , ub ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +GetModelObject () -> mo_colBlendColor = col ; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +return FALSE ; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} + +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +void CEffector::RenderMovingLightnings(void) +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fLifeRatio = CalculateLifeRatio (0.1f , 0.1f); +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_penModel -> GetModelVerticesAbsolute (avModelFXVertices , 0.05f , 0.0f); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +const FLOATmatrix3D & m = m_penModel -> GetRotationMatrix (); +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT3D vOrigin = m_penModel -> GetPlacement () . pl_PositionVector ; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fFXTime = 0.75f; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fMaxHeight = 6.0f; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fdh = 1.0f; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT tmDelta = _pTimer -> GetLerpedCurrentTick () - m_tmStarted ; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fY0 = tmDelta ; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +for(FLOAT fT = tmDelta ;fT > 0;fT -= fFXTime ) +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fY = fT * 2.0f; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(fY > fMaxHeight ) +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +continue ; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fHeightRatio = CalculateRatio (fY , 0 , fMaxHeight , 0.1f , 0.0f); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fMinY = 1e6f; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fMinY2 = - 1e6f; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +INDEX iLower = - 1; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +INDEX iUpper = - 1; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +for(INDEX iVtx = 0;iVtx < avModelFXVertices . Count ();iVtx ++) +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT3D v = (avModelFXVertices [ iVtx ] - vOrigin ) * ! m ; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(v (2) > fY && v (2) < fMinY && v (1) < 0) +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +iLower = iVtx ; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fMinY = v (2); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(v (2) <= fY && v (2) > fMinY2 && v (1) < 0) +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +iUpper = iVtx ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fMinY2 = v (2); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(iLower != - 1 && iUpper != - 1) +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT3D vRelHi = (avModelFXVertices [ iUpper ] - vOrigin ) * ! m ; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT3D vRelLow = (avModelFXVertices [ iLower ] - vOrigin ) * ! m ; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fLerpFactor = (fY - vRelLow (2)) / (vRelHi (2) - vRelLow (2)); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT3D vRel = Lerp (vRelLow , vRelHi , fLerpFactor ); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +vRel (2) = fY ; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT3D vAbs1 = vOrigin + vRel * m ; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +vRel (1) = - vRel (1); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT3D vAbs2 = vOrigin + vRel * m ; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +Particles_Ghostbuster (vAbs1 , vAbs2 , 16 , 0.325f , fHeightRatio * fLifeRatio , 5.0f); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +avModelFXVertices . Clear (); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} + +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +void CEffector::RenderParticles(void) +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fRatio ; +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +TIME tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +TIME tmDelta = tmNow - m_tmStarted ; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fLivingRatio = tmDelta / m_tmLifeTime ; +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(fLivingRatio < 0.25f){ +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fRatio = Clamp (fLivingRatio / 0.25f , 0.0f , 1.0f); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +}else if(fLivingRatio > 0.75f){ +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fRatio = Clamp ((- fLivingRatio + 1.0f) / 0.25f , 0.0f , 1.0f); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +}else { +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +fRatio = 1.0f; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +switch(m_eetType ) +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +case ET_DESTROY_OBELISK : +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +Particles_DestroyingObelisk (this , m_tmStarted ); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +break ; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +case ET_DESTROY_PYLON : +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +Particles_DestroyingPylon (this , m_vDamageDir , m_tmStarted ); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +break ; +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +case ET_HIT_GROUND : +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +Particles_HitGround (this , m_tmStarted , m_fSize ); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +break ; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +case ET_LIGHTNING : +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +Particles_Ghostbuster (GetPlacement () . pl_PositionVector , m_vFXDestination , m_ctCount , m_fSize , fRatio ); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +break ; +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +case ET_PORTAL_LIGHTNING : +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +RenderMovingLightnings (); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +break ; +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} + +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +void CEffector::Read_t(CTStream * istr) +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +CMovableModelEntity :: Read_t (istr ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_bLightSource ){ +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SetupLightSource (); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} + +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +CLightSource * CEffector::GetLightSource(void) +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_bLightSource && ! IsPredictor ()){ +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +return & m_lsLightSource ; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +}else { +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +return NULL ; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} + +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +void CEffector::SetupLightSource(void) +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_iLightAnimation >= 0) +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +try { +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_aoLightAnimation . SetData_t (CTFILENAME ("Animations\\Effector.ani")); +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +}catch (char * strError ){ +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +WarningMessage (TRANS ("Cannot load Animations\\Effector.ani: %s") , strError ); +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_aoLightAnimation . PlayAnim (m_iLightAnimation , 0); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +CLightSource lsNew ; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_ulFlags = LSF_LENSFLAREONLY ; +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_rHotSpot = 0.0f; +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +switch(m_eetType ){ +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +case ET_SIZING_RING_FLARE : +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_colColor = C_WHITE | CT_OPAQUE ; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_rHotSpot = 100.0f; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_rFallOff = 300.0f; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_plftLensFlare = & _lftWhiteGlowStarNG ; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +break ; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +case ET_SIZING_BIG_BLUE_FLARE : +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_colColor = C_WHITE | CT_OPAQUE ; +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_rHotSpot = 500.0f * m_fSize ; +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_rFallOff = 1000.0f * m_fSize ; +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_plftLensFlare = & _lftBlueStarBlueReflections ; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +break ; +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +default : +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +ASSERTALWAYS ("Unknown light source"); +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_ubPolygonalMask = 0; +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_paoLightAnimation = NULL ; +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_paoLightAnimation = NULL ; +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +lsNew . ls_paoLightAnimation = & m_aoLightAnimation ; +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_lsLightSource . ls_penEntity = this ; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +BOOL CEffector:: +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEffector_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_ESpawnEffector, "CEffector::Main expects 'ESpawnEffector' as input!"); const ESpawnEffector &eSpawn = (const ESpawnEffector &)__eeInput; +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +InitAsEditorModel (); +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL | EPF_MOVABLE ); +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SetCollisionFlags (ECF_TOUCHMODEL ); +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SetModel (MODEL_MARKER ); +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_eetType = eSpawn . eetType ; +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_vDamageDir = eSpawn . vDamageDir ; +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_tmStarted = _pTimer -> CurrentTick (); +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_tmLifeTime = eSpawn . tmLifeTime ; +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_vFXDestination = eSpawn . vDestination ; +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_fSize = eSpawn . fSize ; +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_ctCount = eSpawn . ctCount ; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_bAlive = TRUE ; +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_penModel = eSpawn . penModel ; +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_penModel2 = eSpawn . penModel2 ; +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_bWaitTrigger = FALSE ; +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x02600001, FALSE, EBegin());return TRUE;}BOOL CEffector::H0x02600001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02600001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02600002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEffector::H0x02600002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02600002 +; +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_eetType == ET_MOVING_RING ) +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SetModel (MODEL_POWER_RING ); +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SetModelMainTexture (TEXTURE_POWER_RING ); +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +en_fAcceleration = 1e6f; +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fSpeed = 550.0f; +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SetDesiredTranslation (FLOAT3D (0 , - fSpeed , 0)); +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fPathLen = GetPlacement () . pl_PositionVector (2) - m_vFXDestination (2); +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_tmLifeTime = fPathLen / fSpeed ; +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SwitchToModel (); +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT fSize = 36.0f; +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT3D vStretch = FLOAT3D (fSize , fSize * 2.0f , fSize ); +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +GetModelObject () -> StretchModel (vStretch ); +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +ModelChangeNotify (); +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_eetType == ET_SIZING_RING_FLARE ) +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_bLightSource = TRUE ; +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_iLightAnimation = 0; +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_eetType == ET_SIZING_BIG_BLUE_FLARE ) +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_bLightSource = TRUE ; +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_iLightAnimation = 1; +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_eetType == ET_MORPH_MODELS || m_eetType == ET_DISAPPEAR_MODEL || m_eetType == ET_APPEAR_MODEL ) +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_bWaitTrigger = TRUE ; +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_tmStarted = - 1; +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_eetType == ET_DISAPPEAR_MODEL_NOW || m_eetType == ET_APPEAR_MODEL_NOW ) +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_bWaitTrigger = FALSE ; +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_tmStarted = _pTimer -> CurrentTick (); +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_bLightSource ){SetupLightSource ();} +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +Jump(STATE_CURRENT,0x02600005, FALSE, EInternal());return TRUE;}BOOL CEffector::H0x02600005_Main_05(const CEntityEvent &__eeInput) +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02600005 +if(!(_pTimer -> CurrentTick () < m_tmStarted + m_tmLifeTime && m_bAlive || m_bWaitTrigger )){ Jump(STATE_CURRENT,0x02600006, FALSE, EInternal());return TRUE;} +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x02600003, FALSE, EBegin());return TRUE;}BOOL CEffector::H0x02600003_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02600003 +switch(__eeInput.ee_slEvent) +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETrigger): +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{const ETrigger&e= (ETrigger&)__eeInput; + +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_eetType == ET_MORPH_MODELS || m_eetType == ET_DISAPPEAR_MODEL || m_eetType == ET_APPEAR_MODEL ) +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_tmStarted = _pTimer -> CurrentTick (); +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_bWaitTrigger = FALSE ; +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_bAlive = TRUE ; +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +return TRUE; +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x02600004, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +}return TRUE;}BOOL CEffector::H0x02600004_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02600004 + +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(m_eetType == ET_MOVING_RING ) +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +if(GetPlacement () . pl_PositionVector (2) < m_vFXDestination (2)) +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +{ +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +m_bAlive = FALSE ; +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +} +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +}Jump(STATE_CURRENT,0x02600005, FALSE, EInternal());return TRUE; +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +}BOOL CEffector::H0x02600006_Main_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02600006 + +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +Destroy (); +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +Return(STATE_CURRENT,EVoid()); +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Effector.es b/Sources/EntitiesMP/Effector.es new file mode 100644 index 0000000..5e86bed --- /dev/null +++ b/Sources/EntitiesMP/Effector.es @@ -0,0 +1,470 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +608 +%{ +#include "StdH.h" +#include "EntitiesMP/Effector.h" +#include +%} + +enum EffectorEffectType { + 0 ET_NONE "None", // no particles + 1 ET_DESTROY_OBELISK "Destroy obelisk", // effect of obelisk destroying + 2 ET_DESTROY_PYLON "Destroy pylon", // effect of pylon destroying + 3 ET_HIT_GROUND "Hit ground", // effect of hitting ground + 4 ET_LIGHTNING "Lightning", // lightning effect + 5 ET_SIZING_BIG_BLUE_FLARE "Sizing big blue flare", // sizing big blue flare with reflections effect + 6 ET_SIZING_RING_FLARE "Sizing ring flare", // sizing ringed flare effect + 7 ET_MOVING_RING "Moving ring", // moving ring effect + 8 ET_PORTAL_LIGHTNING "Portal lightnings", // lightnings between portal vertices + 9 ET_MORPH_MODELS "Morph two models", // morph wto models + 10 ET_DISAPPEAR_MODEL "Disappear model", // disappear model + 11 ET_APPEAR_MODEL "Appear model", // appear model + 12 ET_DISAPPEAR_MODEL_NOW "Disappear model now", // disappear model now + 13 ET_APPEAR_MODEL_NOW "Appear model now", // appear model now +}; + +// input parameter for spawning effector +event ESpawnEffector { + enum EffectorEffectType eetType, // type of particles + FLOAT3D vDamageDir, // direction of damage + FLOAT3D vDestination, // FX Destination + FLOAT tmLifeTime, // FX's life period + FLOAT fSize, // misc size + INDEX ctCount, // misc count + CEntityPointer penModel, // ptr to model object used in this effect + CEntityPointer penModel2, // ptr to second model object used in this effect +}; + +%{ +void CEffector_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + switch ((EffectorEffectType)iUser) + { + case ET_MOVING_RING : + pdec->PrecacheModel(MODEL_POWER_RING); + pdec->PrecacheTexture(TEXTURE_POWER_RING); + break; + case ET_DESTROY_OBELISK : + case ET_DESTROY_PYLON : + case ET_HIT_GROUND : + case ET_LIGHTNING : + case ET_SIZING_BIG_BLUE_FLARE : + case ET_SIZING_RING_FLARE : + case ET_PORTAL_LIGHTNING : + case ET_MORPH_MODELS : + case ET_DISAPPEAR_MODEL : + case ET_APPEAR_MODEL : + case ET_DISAPPEAR_MODEL_NOW : + case ET_APPEAR_MODEL_NOW : + // no precaching needed + break; + default: + ASSERT(FALSE); + } +} + +// array for model vertices in absolute space +CStaticStackArray avModelFXVertices; +%} + +class CEffector: CMovableModelEntity { +name "Effector"; +thumbnail ""; +features "ImplementsOnPrecache"; +properties: + + 1 enum EffectorEffectType m_eetType = ET_NONE, // type of effect + 2 FLOAT m_tmStarted = 0.0f, // time when spawned + 3 FLOAT3D m_vDamageDir = FLOAT3D(0,0,0), // direction of damage + 4 FLOAT3D m_vFXDestination = FLOAT3D(0,0,0), // FX destination + 5 FLOAT m_tmLifeTime = 5.0f, // how long effect lives + 6 FLOAT m_fSize = 1.0f, // effect's stretcher + 8 INDEX m_ctCount = 0, // misc count + 10 BOOL m_bLightSource = FALSE, // effect is also light source + 11 CAnimObject m_aoLightAnimation, // light animation object + 12 INDEX m_iLightAnimation = -1, // light animation index + 13 BOOL m_bAlive = TRUE, // if effector is still alive + 14 CEntityPointer m_penModel, // ptr to model object used in this effect + 15 CEntityPointer m_penModel2, // ptr to second model object used in this effect + 16 BOOL m_bWaitTrigger = FALSE, // if effect is activated using trigger + + +{ + CLightSource m_lsLightSource; +} + +components: + 1 model MODEL_MARKER "Models\\Editor\\Axis.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex", + 3 model MODEL_POWER_RING "Models\\CutSequences\\SpaceShip\\PowerRing.mdl", + 4 texture TEXTURE_POWER_RING "Models\\CutSequences\\SpaceShip\\PowerRing.tex" + +functions: + + // calculate life ratio + FLOAT CalculateLifeRatio(FLOAT fFadeInRatio, FLOAT fFadeOutRatio) + { + TIME tmDelta = _pTimer->GetLerpedCurrentTick()-m_tmStarted; + FLOAT fLifeRatio = CalculateRatio( tmDelta, 0, m_tmLifeTime, fFadeInRatio, fFadeOutRatio); + return fLifeRatio; + } + + void AdjustMipFactor(FLOAT &fMipFactor) + { + if (m_eetType==ET_DISAPPEAR_MODEL || m_eetType==ET_DISAPPEAR_MODEL_NOW && m_penModel!=NULL) + { + CModelObject *pmo = m_penModel->GetModelObject(); + TIME tmDelta = _pTimer->GetLerpedCurrentTick()-m_tmStarted; + FLOAT fLifeRatio; + if( m_tmStarted == -1) + { + fLifeRatio = 1.0f; + } + else if( tmDelta>=m_tmLifeTime) + { + fLifeRatio = 0.0f; + } + else + { + fLifeRatio = CalculateLifeRatio(0.0f, 1.0f); + } + UBYTE ubAlpha = UBYTE(255.0f*fLifeRatio); + COLOR col = C_WHITE|ubAlpha; + pmo->mo_colBlendColor = col; + } + if (m_eetType==ET_APPEAR_MODEL || m_eetType==ET_APPEAR_MODEL_NOW && m_penModel!=NULL) + { + CModelObject *pmo = m_penModel->GetModelObject(); + TIME tmDelta = _pTimer->GetLerpedCurrentTick()-m_tmStarted; + FLOAT fLifeRatio; + if( m_tmStarted == -1) + { + fLifeRatio = 0.0f; + } + else if( tmDelta>=m_tmLifeTime) + { + fLifeRatio = 1.0f; + } + else + { + fLifeRatio = CalculateLifeRatio(1.0f, 0.0f); + } + UBYTE ubAlpha = UBYTE(255.0f*fLifeRatio); + COLOR col = C_WHITE|ubAlpha; + pmo->mo_colBlendColor = col; + } + if (m_eetType==ET_MORPH_MODELS && m_penModel!=NULL && m_penModel2!=NULL) + { + CModelObject *pmo1 = m_penModel->GetModelObject(); + CModelObject *pmo2 = m_penModel2->GetModelObject(); + TIME tmDelta = _pTimer->GetLerpedCurrentTick()-m_tmStarted; + FLOAT fLifeRatio; + if( m_tmStarted == -1) + { + fLifeRatio = 0.0f; + } + else if( tmDelta>=m_tmLifeTime) + { + fLifeRatio = 1.0f; + } + else + { + fLifeRatio = CalculateLifeRatio(1.0f, 0.0f); + } + UBYTE ubAlpha1 = UBYTE(255.0f*(1-fLifeRatio)); + UBYTE ubAlpha2 = 255-ubAlpha1; + COLOR col1 = C_WHITE|ubAlpha1; + COLOR col2 = C_WHITE|ubAlpha2; + pmo1->mo_colBlendColor = col1; + pmo2->mo_colBlendColor = col2; + } + } + + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + if(m_eetType==ET_MOVING_RING) + { + FLOAT fLifeRatio = CalculateLifeRatio(0.2f, 0.1f); + FLOAT fT = _pTimer->CurrentTick()-m_tmStarted; + FLOAT fPulse = 1.0f; + UBYTE ub = UBYTE (255.0f*fPulse*fLifeRatio); + COLOR col = RGBAToColor(ub,ub,ub,ub); + GetModelObject()->mo_colBlendColor = col; + } + + return FALSE; + } + + void RenderMovingLightnings(void) + { + // calculate life ratio + FLOAT fLifeRatio = CalculateLifeRatio(0.1f, 0.1f); + // fill array with absolute vertices of entity's model and its attached models + m_penModel->GetModelVerticesAbsolute(avModelFXVertices, 0.05f, 0.0f); + const FLOATmatrix3D &m = m_penModel->GetRotationMatrix(); + FLOAT3D vOrigin = m_penModel->GetPlacement().pl_PositionVector; + FLOAT fFXTime = 0.75f; + FLOAT fMaxHeight = 6.0f; + FLOAT fdh = 1.0f; + FLOAT tmDelta = _pTimer->GetLerpedCurrentTick()-m_tmStarted; + FLOAT fY0 = tmDelta; + + for(FLOAT fT=tmDelta; fT>0; fT-=fFXTime) + { + FLOAT fY = fT*2.0f; + if( fY>fMaxHeight) + { + continue; + } + // calculate height ratio + FLOAT fHeightRatio = CalculateRatio( fY, 0, fMaxHeight, 0.1f, 0.0f); + FLOAT fMinY = 1e6f; + FLOAT fMinY2 = -1e6f; + INDEX iLower = -1; + INDEX iUpper = -1; + for( INDEX iVtx=0; iVtxfY && v(2)fMinY2 && v(1)<0) + { + iUpper = iVtx; + fMinY2 = v(2); + } + } + // if we found valid vertex + if( iLower!=-1 && iUpper!=-1) + { + FLOAT3D vRelHi = (avModelFXVertices[iUpper]-vOrigin)*!m; + FLOAT3D vRelLow = (avModelFXVertices[iLower]-vOrigin)*!m; + FLOAT fLerpFactor = (fY-vRelLow(2))/(vRelHi(2)-vRelLow(2)); + FLOAT3D vRel = Lerp(vRelLow, vRelHi, fLerpFactor); + vRel(2) = fY; + FLOAT3D vAbs1 = vOrigin+vRel*m; + vRel(1)=-vRel(1); + FLOAT3D vAbs2 = vOrigin+vRel*m; + // render lightning + Particles_Ghostbuster( vAbs1, vAbs2, 16, 0.325f, fHeightRatio*fLifeRatio, 5.0f); + } + } + avModelFXVertices.Clear(); + } + + // particles + void RenderParticles(void) + { + // calculate ratio + FLOAT fRatio; + TIME tmNow = _pTimer->GetLerpedCurrentTick(); + TIME tmDelta = tmNow - m_tmStarted; + FLOAT fLivingRatio = tmDelta/m_tmLifeTime; + if(fLivingRatio<0.25f) { + fRatio = Clamp( fLivingRatio/0.25f, 0.0f, 1.0f); + } else if(fLivingRatio>0.75f) { + fRatio = Clamp( (-fLivingRatio+1.0f)/0.25f, 0.0f, 1.0f); + } else { + fRatio = 1.0f; + } + + switch( m_eetType) + { + case ET_DESTROY_OBELISK: + Particles_DestroyingObelisk( this, m_tmStarted); + break; + case ET_DESTROY_PYLON: + Particles_DestroyingPylon( this, m_vDamageDir, m_tmStarted); + break; + case ET_HIT_GROUND: + Particles_HitGround( this, m_tmStarted, m_fSize); + break; + case ET_LIGHTNING: + Particles_Ghostbuster(GetPlacement().pl_PositionVector, m_vFXDestination, m_ctCount, m_fSize, fRatio); + break; + case ET_PORTAL_LIGHTNING: + RenderMovingLightnings(); + break; + } + }; + + /* Read from stream. */ + void Read_t( CTStream *istr) // throw char * + { + CMovableModelEntity::Read_t(istr); + // setup light source + if( m_bLightSource) { + SetupLightSource(); + } + } + + /* Get static light source information. */ + CLightSource *GetLightSource(void) + { + if( m_bLightSource && !IsPredictor()) { + return &m_lsLightSource; + } else { + return NULL; + } + } + + // Setup light source + void SetupLightSource(void) + { + if( m_iLightAnimation>=0) + { // set light animation if available + try { + m_aoLightAnimation.SetData_t(CTFILENAME("Animations\\Effector.ani")); + } catch (char *strError) { + WarningMessage(TRANS("Cannot load Animations\\Effector.ani: %s"), strError); + } + // play light animation + if (m_aoLightAnimation.GetData()!=NULL) { + m_aoLightAnimation.PlayAnim(m_iLightAnimation, 0); + } + } + + // setup light source + CLightSource lsNew; + lsNew.ls_ulFlags = LSF_LENSFLAREONLY; + lsNew.ls_rHotSpot = 0.0f; + switch (m_eetType) { + case ET_SIZING_RING_FLARE: + lsNew.ls_colColor = C_WHITE|CT_OPAQUE; + lsNew.ls_rHotSpot = 100.0f; + lsNew.ls_rFallOff = 300.0f; + lsNew.ls_plftLensFlare = &_lftWhiteGlowStarNG; + break; + + case ET_SIZING_BIG_BLUE_FLARE: + lsNew.ls_colColor = C_WHITE|CT_OPAQUE; + lsNew.ls_rHotSpot = 500.0f*m_fSize; + lsNew.ls_rFallOff = 1000.0f*m_fSize; + lsNew.ls_plftLensFlare = &_lftBlueStarBlueReflections; + break; + + default: + ASSERTALWAYS("Unknown light source"); + } + lsNew.ls_ubPolygonalMask = 0; + lsNew.ls_paoLightAnimation = NULL; + + // setup light animation + lsNew.ls_paoLightAnimation = NULL; + if (m_aoLightAnimation.GetData()!=NULL) { + lsNew.ls_paoLightAnimation = &m_aoLightAnimation; + } + + m_lsLightSource.ls_penEntity = this; + m_lsLightSource.SetLightSource(lsNew); + } +/************************************************************ + * MAIN * + ************************************************************/ + +procedures: + + Main( ESpawnEffector eSpawn) + { + // set appearance + InitAsEditorModel(); + + SetPhysicsFlags(EPF_MODEL_IMMATERIAL|EPF_MOVABLE); + SetCollisionFlags(ECF_TOUCHMODEL); + SetFlags( GetFlags()|ENF_SEETHROUGH); + + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + // setup variables + m_eetType = eSpawn.eetType; + m_vDamageDir = eSpawn.vDamageDir; + m_tmStarted = _pTimer->CurrentTick(); + m_tmLifeTime = eSpawn.tmLifeTime; + m_vFXDestination = eSpawn.vDestination; + m_fSize = eSpawn.fSize; + m_ctCount = eSpawn.ctCount; + m_bAlive = TRUE; + m_penModel = eSpawn.penModel; + m_penModel2 = eSpawn.penModel2; + m_bWaitTrigger = FALSE; + + autowait(0.1f); + + if(m_eetType==ET_MOVING_RING) + { + SetModel(MODEL_POWER_RING); + SetModelMainTexture(TEXTURE_POWER_RING); + en_fAcceleration = 1e6f; + FLOAT fSpeed = 550.0f; + SetDesiredTranslation(FLOAT3D(0,-fSpeed,0)); + FLOAT fPathLen = GetPlacement().pl_PositionVector(2)-m_vFXDestination(2); + // t=s/v + m_tmLifeTime = fPathLen/fSpeed; + SwitchToModel(); + FLOAT fSize = 36.0f; + FLOAT3D vStretch = FLOAT3D(fSize, fSize*2.0f, fSize); + GetModelObject()->StretchModel(vStretch); + ModelChangeNotify(); + } + // spetial initializations + if(m_eetType==ET_SIZING_RING_FLARE) + { + m_bLightSource = TRUE; + m_iLightAnimation = 0; + } + if(m_eetType==ET_SIZING_BIG_BLUE_FLARE) + { + m_bLightSource = TRUE; + m_iLightAnimation = 1; + } + if(m_eetType==ET_MORPH_MODELS || m_eetType==ET_DISAPPEAR_MODEL || m_eetType==ET_APPEAR_MODEL) + { + m_bWaitTrigger = TRUE; + m_tmStarted = -1; + } + if(m_eetType==ET_DISAPPEAR_MODEL_NOW || m_eetType==ET_APPEAR_MODEL_NOW) + { + m_bWaitTrigger = FALSE; + m_tmStarted = _pTimer->CurrentTick(); + } + + // setup light source + if (m_bLightSource) { SetupLightSource(); } + + while(_pTimer->CurrentTick()CurrentTick(); + m_bWaitTrigger = FALSE; + // live forever + m_bAlive = TRUE; + } + resume; + } + on( ETimer):{ stop;} + } + // check if moving ring reached target position + if(m_eetType==ET_MOVING_RING) + { + if( GetPlacement().pl_PositionVector(2) < m_vFXDestination(2)) + { + m_bAlive = FALSE; + } + } + } + + Destroy(); + return; + } +}; diff --git a/Sources/EntitiesMP/Effector.h b/Sources/EntitiesMP/Effector.h new file mode 100644 index 0000000..67259dc --- /dev/null +++ b/Sources/EntitiesMP/Effector.h @@ -0,0 +1,94 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Effector_INCLUDED +#define _EntitiesMP_Effector_INCLUDED 1 +extern DECL_DLL CEntityPropertyEnumType EffectorEffectType_enum; +enum EffectorEffectType { + ET_NONE = 0, + ET_DESTROY_OBELISK = 1, + ET_DESTROY_PYLON = 2, + ET_HIT_GROUND = 3, + ET_LIGHTNING = 4, + ET_SIZING_BIG_BLUE_FLARE = 5, + ET_SIZING_RING_FLARE = 6, + ET_MOVING_RING = 7, + ET_PORTAL_LIGHTNING = 8, + ET_MORPH_MODELS = 9, + ET_DISAPPEAR_MODEL = 10, + ET_APPEAR_MODEL = 11, + ET_DISAPPEAR_MODEL_NOW = 12, + ET_APPEAR_MODEL_NOW = 13, +}; +DECL_DLL inline void ClearToDefault(EffectorEffectType &e) { e = (EffectorEffectType)0; } ; +#define EVENTCODE_ESpawnEffector 0x02600000 +class DECL_DLL ESpawnEffector : public CEntityEvent { +public: +ESpawnEffector(); +CEntityEvent *MakeCopy(void); +enum EffectorEffectType eetType; +FLOAT3D vDamageDir; +FLOAT3D vDestination; +FLOAT tmLifeTime; +FLOAT fSize; +INDEX ctCount; +CEntityPointer penModel; +CEntityPointer penModel2; +}; +DECL_DLL inline void ClearToDefault(ESpawnEffector &e) { e = ESpawnEffector(); } ; +extern "C" DECL_DLL CDLLEntityClass CEffector_DLLClass; +class CEffector : public CMovableModelEntity { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum EffectorEffectType m_eetType; + FLOAT m_tmStarted; + FLOAT3D m_vDamageDir; + FLOAT3D m_vFXDestination; + FLOAT m_tmLifeTime; + FLOAT m_fSize; + INDEX m_ctCount; + BOOL m_bLightSource; + CAnimObject m_aoLightAnimation; + INDEX m_iLightAnimation; + BOOL m_bAlive; + CEntityPointer m_penModel; + CEntityPointer m_penModel2; + BOOL m_bWaitTrigger; +CLightSource m_lsLightSource; + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +FLOAT CalculateLifeRatio(FLOAT fFadeInRatio,FLOAT fFadeOutRatio); + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +void AdjustMipFactor(FLOAT & fMipFactor); + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +void RenderMovingLightnings(void); + +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +void RenderParticles(void); + +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +void Read_t(CTStream * istr); + +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +CLightSource * GetLightSource(void); + +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +void SetupLightSource(void); +#define STATE_CEffector_Main 1 + BOOL +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x02600001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x02600002_Main_02(const CEntityEvent &__eeInput); + BOOL H0x02600003_Main_03(const CEntityEvent &__eeInput); + BOOL H0x02600004_Main_04(const CEntityEvent &__eeInput); + BOOL H0x02600005_Main_05(const CEntityEvent &__eeInput); + BOOL H0x02600006_Main_06(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Effector_INCLUDED diff --git a/Sources/EntitiesMP/Effector_tables.h b/Sources/EntitiesMP/Effector_tables.h new file mode 100644 index 0000000..a717e2c --- /dev/null +++ b/Sources/EntitiesMP/Effector_tables.h @@ -0,0 +1,76 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(EffectorEffectType) + EP_ENUMVALUE(ET_NONE, "None"), + EP_ENUMVALUE(ET_DESTROY_OBELISK, "Destroy obelisk"), + EP_ENUMVALUE(ET_DESTROY_PYLON, "Destroy pylon"), + EP_ENUMVALUE(ET_HIT_GROUND, "Hit ground"), + EP_ENUMVALUE(ET_LIGHTNING, "Lightning"), + EP_ENUMVALUE(ET_SIZING_BIG_BLUE_FLARE, "Sizing big blue flare"), + EP_ENUMVALUE(ET_SIZING_RING_FLARE, "Sizing ring flare"), + EP_ENUMVALUE(ET_MOVING_RING, "Moving ring"), + EP_ENUMVALUE(ET_PORTAL_LIGHTNING, "Portal lightnings"), + EP_ENUMVALUE(ET_MORPH_MODELS, "Morph two models"), + EP_ENUMVALUE(ET_DISAPPEAR_MODEL, "Disappear model"), + EP_ENUMVALUE(ET_APPEAR_MODEL, "Appear model"), + EP_ENUMVALUE(ET_DISAPPEAR_MODEL_NOW, "Disappear model now"), + EP_ENUMVALUE(ET_APPEAR_MODEL_NOW, "Appear model now"), +EP_ENUMEND(EffectorEffectType); + +#define ENTITYCLASS CEffector + +CEntityProperty CEffector_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &EffectorEffectType_enum, (0x00000260<<8)+1, offsetof(CEffector, m_eetType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000260<<8)+2, offsetof(CEffector, m_tmStarted), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000260<<8)+3, offsetof(CEffector, m_vDamageDir), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000260<<8)+4, offsetof(CEffector, m_vFXDestination), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000260<<8)+5, offsetof(CEffector, m_tmLifeTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000260<<8)+6, offsetof(CEffector, m_fSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000260<<8)+8, offsetof(CEffector, m_ctCount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000260<<8)+10, offsetof(CEffector, m_bLightSource), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANIMOBJECT, NULL, (0x00000260<<8)+11, offsetof(CEffector, m_aoLightAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000260<<8)+12, offsetof(CEffector, m_iLightAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000260<<8)+13, offsetof(CEffector, m_bAlive), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000260<<8)+14, offsetof(CEffector, m_penModel), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000260<<8)+15, offsetof(CEffector, m_penModel2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000260<<8)+16, offsetof(CEffector, m_bWaitTrigger), "", 0, 0, 0), +}; +#define CEffector_propertiesct ARRAYCOUNT(CEffector_properties) + +CEntityComponent CEffector_components[] = { +#define MODEL_MARKER ((0x00000260<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_MARKER ((0x00000260<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Vector.tex"), +#define MODEL_POWER_RING ((0x00000260<<8)+3) + CEntityComponent(ECT_MODEL, MODEL_POWER_RING, "EFNM" "Models\\CutSequences\\SpaceShip\\PowerRing.mdl"), +#define TEXTURE_POWER_RING ((0x00000260<<8)+4) + CEntityComponent(ECT_TEXTURE, TEXTURE_POWER_RING, "EFNM" "Models\\CutSequences\\SpaceShip\\PowerRing.tex"), +}; +#define CEffector_componentsct ARRAYCOUNT(CEffector_components) + +CEventHandlerEntry CEffector_handlers[] = { + {1, -1, CEntity::pEventHandler(&CEffector:: +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/Effector.es" +Main),DEBUGSTRING("CEffector::Main")}, + {0x02600001, -1, CEntity::pEventHandler(&CEffector::H0x02600001_Main_01), DEBUGSTRING("CEffector::H0x02600001_Main_01")}, + {0x02600002, -1, CEntity::pEventHandler(&CEffector::H0x02600002_Main_02), DEBUGSTRING("CEffector::H0x02600002_Main_02")}, + {0x02600003, -1, CEntity::pEventHandler(&CEffector::H0x02600003_Main_03), DEBUGSTRING("CEffector::H0x02600003_Main_03")}, + {0x02600004, -1, CEntity::pEventHandler(&CEffector::H0x02600004_Main_04), DEBUGSTRING("CEffector::H0x02600004_Main_04")}, + {0x02600005, -1, CEntity::pEventHandler(&CEffector::H0x02600005_Main_05), DEBUGSTRING("CEffector::H0x02600005_Main_05")}, + {0x02600006, -1, CEntity::pEventHandler(&CEffector::H0x02600006_Main_06), DEBUGSTRING("CEffector::H0x02600006_Main_06")}, +}; +#define CEffector_handlersct ARRAYCOUNT(CEffector_handlers) + +CEntity *CEffector_New(void) { return new CEffector; }; +void CEffector_OnInitClass(void) {}; +void CEffector_OnEndClass(void) {}; +void CEffector_OnPrecache(CDLLEntityClass *pdec, INDEX iUser); +void CEffector_OnWorldEnd(CWorld *pwo) {}; +void CEffector_OnWorldInit(CWorld *pwo) {}; +void CEffector_OnWorldTick(CWorld *pwo) {}; +void CEffector_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEffector, CMovableModelEntity, "Effector", "", 0x00000260); +DECLARE_CTFILENAME(_fnmCEffector_tbn, ""); diff --git a/Sources/EntitiesMP/Elemental.cpp b/Sources/EntitiesMP/Elemental.cpp new file mode 100644 index 0000000..cacd227 --- /dev/null +++ b/Sources/EntitiesMP/Elemental.cpp @@ -0,0 +1,2013 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" + +#include "StdH.h" +//#include "Models/Enemies/Elementals/AirMan.h" +//#include "Models/Enemies/Elementals/IceMan.h" +#include "Models/Enemies/Elementals/StoneMan.h" +//#include "Models/Enemies/Elementals/Twister.h" +//#include "Models/Enemies/Elementals/WaterMan.h" +//#include "Models/Enemies/Elementals/Projectile/IcePyramid.h" +#include "Models/Enemies/Elementals/Projectile/LavaStone.h" + +#include "Models/Enemies/ElementalLava/ElementalLava.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" + +// lava elemental definitions +#define LAVAMAN_SMALL_STRETCH (2.0f*0.75f) +#define LAVAMAN_BIG_STRETCH (4.0f*1.25f) +#define LAVAMAN_LARGE_STRETCH (16.0f*2.5f) + +#define LAVAMAN_BOSS_FIRE_RIGHT FLOAT3D(1.01069f, 0.989616f, -1.39743f) +#define LAVAMAN_BOSS_FIRE_LEFT FLOAT3D(-0.39656f, 1.08619f, -1.34373f) +#define LAVAMAN_FIRE_LEFT FLOAT3D(-0.432948f, 1.51133f, -0.476662f) + +#define LAVAMAN_FIRE_SMALL (LAVAMAN_FIRE_LEFT*LAVAMAN_SMALL_STRETCH) +#define LAVAMAN_FIRE_BIG (LAVAMAN_FIRE_LEFT*LAVAMAN_BIG_STRETCH) +#define LAVAMAN_FIRE_LARGE_LEFT (LAVAMAN_BOSS_FIRE_LEFT*LAVAMAN_LARGE_STRETCH) +#define LAVAMAN_FIRE_LARGE_RIGHT (LAVAMAN_BOSS_FIRE_RIGHT*LAVAMAN_LARGE_STRETCH) + +#define LAVAMAN_SPAWN_BIG (FLOAT3D(0.0171274f, 1.78397f, -0.291414f)*LAVAMAN_BIG_STRETCH) +#define LAVAMAN_SPAWN_LARGE (FLOAT3D(0.0171274f, 1.78397f, -0.291414f)*LAVAMAN_LARGE_STRETCH) +#define DEATH_BURN_TIME 1.0f + + +#include +#include +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" + +#define ECF_AIR ( \ + ((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)< CurrentTick () - m_fSpiritStartTime ) / DEATH_BURN_TIME , 0.0f , 1.0f); +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Particles_Burning (this , fPower , fTimeFactor * fDeathFactor ); +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::Precache(void) +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CEnemyBase :: Precache (); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EetType ) +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_LAVA : +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_LARGE ) +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheClass (CLASS_PROJECTILE , PRT_LAVAMAN_BIG_BOMB ); +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if((m_EecChar == ELC_LARGE ) || (m_EecChar == ELC_BIG )) +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheClass (CLASS_PROJECTILE , PRT_LAVAMAN_BOMB ); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheClass (CLASS_PROJECTILE , PRT_LAVAMAN_STONE ); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheModel (MODEL_LAVA ); +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheModel (MODEL_LAVA_BODY_FLARE ); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheModel (MODEL_LAVA_HAND_FLARE ); +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheTexture (TEXTURE_LAVA ); +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheTexture (TEXTURE_LAVA_DETAIL ); +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheTexture (TEXTURE_LAVA_FLARE ); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheSound (SOUND_LAVA_IDLE ); +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheSound (SOUND_LAVA_WOUND ); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheSound (SOUND_LAVA_FIRE ); +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheSound (SOUND_LAVA_KICK ); +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheSound (SOUND_LAVA_DEATH ); +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheSound (SOUND_LAVA_ANGER ); +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheSound (SOUND_LAVA_LAVABURN ); +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrecacheSound (SOUND_LAVA_GROW ); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ; +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void * CElemental::GetEntityInfo(void) { +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EetType ){ +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_AIR : +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EecChar ){ +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_LARGE : return & eiAirElementalLarge ; +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_BIG : return & eiAirElementalBig ; +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +default :{return & eiAirElementalSmall ;} +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ; +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_ICE : +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EecChar ){ +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_LARGE : return & eiIceElementalLarge ; +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_BIG : return & eiIceElementalBig ; +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +default :{return & eiIceElementalSmall ;} +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ; +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_LAVA : +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EecChar ){ +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_LARGE : return & eiLavaElementalLarge ; +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_BIG : return & eiLavaElementalBig ; +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +default :{return & eiLavaElementalSmall ;} +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_STONE : +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EecChar ){ +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_LARGE : return & eiStoneElementalLarge ; +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_BIG : return & eiStoneElementalBig ; +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +default :{return & eiStoneElementalSmall ;} +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ; +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +default :{ +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EecChar ){ +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_LARGE : return & eiWaterElementalLarge ; +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_BIG : return & eiWaterElementalBig ; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +default :{return & eiWaterElementalSmall ;} +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}} +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BOOL CElemental::FillEntityStatistics(EntityStats * pes) +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CEnemyBase :: FillEntityStatistics (pes ); +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EetType ){ +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_WATER : {pes -> es_strName += " Water";}break ; +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_AIR : {pes -> es_strName += " Air";}break ; +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_STONE : {pes -> es_strName += " Stone";}break ; +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_LAVA : {pes -> es_strName += " Lava";}break ; +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_ICE : {pes -> es_strName += " Ice";}break ; +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EecChar ){ +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_LARGE : pes -> es_strName += " Large";break ; +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_BIG : pes -> es_strName += " Big";break ; +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_SMALL : pes -> es_strName += " Small";break ; +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE ; +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(IsOfClass (penInflictor , "Elemental")){ +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return ; +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_LARGE && dmtType == DMT_TELEPORT ) +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return ; +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_BIG && dmtType == DMT_BULLET && fDamageAmmount > 100.0f) +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +fDamageAmmount /= 2.5f; +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +INDEX ctShouldSpawn = Clamp (INDEX ((m_fMaxHealth - GetHealth ()) / m_fSpawnDamage ) , INDEX (0) , INDEX (10)); +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CTString strChar = ElementalCharacter_enum . NameForValue (INDEX (m_EecChar )); +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_bSpawnEnabled && m_bSpawnWhenHarmed && (m_EecChar == ELC_LARGE || m_EecChar == ELC_BIG )) +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +INDEX ctShouldSpawn = Clamp (INDEX ((m_fMaxHealth - GetHealth ()) / m_fSpawnDamage ) , INDEX (0) , INDEX (10)); +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_ctSpawned < ctShouldSpawn ) +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SendEvent (EForceWound ()); +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EesCurrentState != ELS_NORMAL ){ +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return ; +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::LeaveStain(BOOL bGrow) +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return ; +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +INDEX CElemental::AnimForDamage(FLOAT fDamage) { +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +INDEX iAnim ; +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EetType == ELT_LAVA ){ +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(IRnd () % 3){ +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case 0: iAnim = ELEMENTALLAVA_ANIM_WOUND01 ;break ; +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case 1: iAnim = ELEMENTALLAVA_ANIM_WOUND02 ;break ; +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +default : iAnim = ELEMENTALLAVA_ANIM_WOUND03 ;break ; +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (iAnim , 0); +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return iAnim ; +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::StandingAnimFight(void) { +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_STANDFIGHT , AOF_LOOPING | AOF_NORESTART ); +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::StandingAnim(void) { +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EetType == ELT_LAVA ){ +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EesCurrentState ){ +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELS_NORMAL : StartModelAnim (ELEMENTALLAVA_ANIM_WALKBIG , AOF_LOOPING | AOF_NORESTART );break ; +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELS_BOX : StartModelAnim (ELEMENTALLAVA_ANIM_MELTFLY , AOF_LOOPING | AOF_NORESTART );break ; +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +default : StartModelAnim (ELEMENTALLAVA_ANIM_STANDPLANE , AOF_LOOPING | AOF_NORESTART );break ; +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::WalkingAnim(void) +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EetType == ELT_LAVA ){ +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_LARGE ){ +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_WALKBIG , AOF_LOOPING | AOF_NORESTART ); +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else if(m_EecChar == ELC_BIG ){ +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_RUNMEDIUM , AOF_LOOPING | AOF_NORESTART ); +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_RUNSMALL , AOF_LOOPING | AOF_NORESTART ); +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::RunningAnim(void) +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EetType == ELT_LAVA ){ +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +WalkingAnim (); +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::RotatingAnim(void) { +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EetType == ELT_LAVA ){ +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +WalkingAnim (); +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +INDEX CElemental::AnimForDeath(void) +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +INDEX iAnim ; +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EetType == ELT_LAVA ){ +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +iAnim = ELEMENTALLAVA_ANIM_DEATH03 ; +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (iAnim , 0); +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return iAnim ; +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::IdleSound(void) { +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soSound , SOUND_LAVA_IDLE , SOF_3D ); +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::SightSound(void) { +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::WoundSound(void) { +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soSound , SOUND_LAVA_WOUND , SOF_3D ); +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::DeathSound(void) { +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soSound , SOUND_LAVA_DEATH , SOF_3D ); +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BOOL CElemental::CountAsKill(void) +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return m_bCountAsKill ; +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::SpawnNewElemental(void) +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +INDEX ctShouldSpawn = Clamp (INDEX ((m_fMaxHealth - GetHealth ()) / m_fSpawnDamage ) , INDEX (0) , INDEX (10)); +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_bSpawnOnBlowUp && (m_EecChar == ELC_LARGE || m_EecChar == ELC_BIG ) && (GetHealth () <= 0.0f)) +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 559 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ctShouldSpawn += 2; +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ASSERT (m_ctSpawned <= ctShouldSpawn ); +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_ctSpawned >= ctShouldSpawn ) +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 565 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return ; +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CPlacement3D pl ; +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_LARGE ){ +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pl = CPlacement3D (LAVAMAN_SPAWN_LARGE , ANGLE3D (- 90.0f + FRnd () * 180.0f , 30 + FRnd () * 30 , 0)); +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 573 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pl = CPlacement3D (LAVAMAN_SPAWN_BIG , ANGLE3D (- 90.0f + FRnd () * 180.0f , 40 + FRnd () * 20 , 0)); +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pl . RelativeToAbsolute (GetPlacement ()); +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CEntityPointer pen = GetWorld () -> CreateEntity (pl , GetClass ()); +#line 579 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . m_EetType = m_EetType ; +#line 581 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_LARGE ){ +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . m_EecChar = ELC_BIG ; +#line 583 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 584 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . m_EecChar = ELC_SMALL ; +#line 585 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . m_EesStartState = ELS_BOX ; +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . m_fDensity = m_fDensity ; +#line 589 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . m_colColor = m_colColor ; +#line 590 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . m_penEnemy = m_penEnemy ; +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . m_ttTarget = m_ttTarget ; +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . m_bSpawned = TRUE ; +#line 593 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pen -> Initialize (EVoid ()); +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_LARGE ){ +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . LaunchAsFreeProjectile (FLOAT3D (0 , 0 , - 40.0f) , this ); +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . LaunchAsFreeProjectile (FLOAT3D (0 , 0 , - 20.0f) , this ); +#line 599 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +((CElemental &) * pen ) . SetDesiredRotation (ANGLE3D (0 , 0 , FRnd () * 360 - 180)); +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CEntity * penSpray = CreateEntity (pl , CLASS_BLOOD_SPRAY ); +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +penSpray -> SetParent (pen ); +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ESpawnSpray eSpawnSpray ; +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eSpawnSpray . fDamagePower = 4.0f; +#line 607 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eSpawnSpray . fSizeMultiplier = 0.5f; +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 609 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eSpawnSpray . vDirection = FLOAT3D (0 , - 0.5f , 0); +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 611 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eSpawnSpray . penOwner = pen ; +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +penSpray -> Initialize (eSpawnSpray ); +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_ctSpawned ++; +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::ThrowRocks(ProjectileType EptProjectile) { +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vPos ; +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ANGLE3D aAngle ; +#line 622 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EecChar ){ +#line 623 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_LARGE : { +#line 624 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +vPos = FIRE_ROCKS_LARGE ; +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShootProjectile (EptProjectile , vPos , ANGLE3D (0 , 0 , 0)); +#line 626 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +aAngle = ANGLE3D (FRnd () * 5.0f + 5.0f , FRnd () * 3.0f - 2.0f , 0); +#line 627 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShootProjectile (EptProjectile , vPos , aAngle ); +#line 628 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +aAngle = ANGLE3D (FRnd () * - 5.0f - 5.0f , FRnd () * 3.0f - 2.0f , 0); +#line 629 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShootProjectile (EptProjectile , vPos , aAngle ); +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ;} +#line 631 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_BIG : { +#line 632 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +vPos = FIRE_ROCKS_BIG ; +#line 633 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShootProjectile (EptProjectile , vPos , ANGLE3D (0 , 0 , 0)); +#line 634 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +aAngle = ANGLE3D (FRnd () * 4.0f + 4.0f , FRnd () * 3.0f - 2.0f , 0); +#line 635 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShootProjectile (EptProjectile , vPos , aAngle ); +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +aAngle = ANGLE3D (FRnd () * - 4.0f - 4.0f , FRnd () * 3.0f - 2.0f , 0); +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShootProjectile (EptProjectile , vPos , aAngle ); +#line 638 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ;} +#line 639 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +default :{ +#line 640 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +vPos = FIRE_ROCKS ; +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShootProjectile (EptProjectile , vPos , ANGLE3D (0 , 0 , 0)); +#line 642 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +aAngle = ANGLE3D (FRnd () * 3.0f + 3.0f , FRnd () * 3.0f - 2.0f , 0); +#line 643 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShootProjectile (EptProjectile , vPos , aAngle ); +#line 644 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +aAngle = ANGLE3D (FRnd () * - 3.0f - 3.0f , FRnd () * 3.0f - 2.0f , 0); +#line 645 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShootProjectile (EptProjectile , vPos , aAngle ); +#line 646 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 648 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 650 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::BossFirePredictedLavaRock(FLOAT3D vFireingRel) +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 652 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vShooting = GetPlacement () . pl_PositionVector + vFireingRel * GetRotationMatrix (); +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vTarget = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 654 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vSpeedDest = ((CMovableEntity &) * m_penEnemy ) . en_vCurrentTranslationAbsolute ; +#line 655 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT fLaunchSpeed ; +#line 656 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT fRelativeHdg ; +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT fDistanceFactor = ClampUp ((vShooting - vTarget ) . Length () / 150.0f , 1.0f) - 0.75f; +#line 659 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT fPitch = fDistanceFactor * 45.0f; +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CalculateAngularLaunchParams (vShooting , peiTarget -> vTargetCenter [ 1 ] - 6.0f / 3.0f , vTarget , +#line 664 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +vSpeedDest , fPitch , fLaunchSpeed , fRelativeHdg ); +#line 667 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vShootTarget ; +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +GetEntityInfoPosition (m_penEnemy , peiTarget -> vTargetCenter , vShootTarget ); +#line 670 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CPlacement3D pl ; +#line 671 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrepareFreeFlyingProjectile (pl , vShootTarget , vFireingRel , ANGLE3D (fRelativeHdg , fPitch , 0)); +#line 672 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 673 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ELaunchProjectile eLaunch ; +#line 674 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eLaunch . penLauncher = this ; +#line 675 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eLaunch . prtType = PRT_LAVAMAN_BIG_BOMB ; +#line 676 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eLaunch . fSpeed = fLaunchSpeed ; +#line 677 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +penProjectile -> Initialize (eLaunch ); +#line 678 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 681 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::ShakeItBaby(FLOAT tmShaketime,FLOAT fPower) +#line 682 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 683 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 684 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(pwsc != NULL ){ +#line 685 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pwsc -> m_tmShakeStarted = tmShaketime ; +#line 686 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pwsc -> m_vShakePos = GetPlacement () . pl_PositionVector ; +#line 687 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pwsc -> m_fShakeFalloff = 450.0f; +#line 688 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pwsc -> m_fShakeFade = 3.0f; +#line 690 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pwsc -> m_fShakeIntensityZ = 0; +#line 691 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pwsc -> m_tmShakeFrequencyZ = 5.0f; +#line 692 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pwsc -> m_fShakeIntensityY = 0.1f * fPower ; +#line 693 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pwsc -> m_tmShakeFrequencyY = 5.0f; +#line 694 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pwsc -> m_fShakeIntensityB = 2.5f * fPower ; +#line 695 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pwsc -> m_tmShakeFrequencyB = 7.2f; +#line 697 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pwsc -> m_bShakeFadeIn = FALSE ; +#line 698 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 699 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::SpawnShockwave(FLOAT fSize) +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 703 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CPlacement3D pl = GetPlacement (); +#line 704 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +pl . pl_PositionVector (2) += 0.1f; +#line 705 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CEntityPointer penShockwave = CreateEntity (pl , CLASS_BASIC_EFFECT ); +#line 707 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ESpawnEffect eSpawnEffect ; +#line 708 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eSpawnEffect . betType = BET_CANNONSHOCKWAVE ; +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eSpawnEffect . vStretch = FLOAT3D (fSize , fSize , fSize ); +#line 711 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +penShockwave -> Initialize (eSpawnEffect ); +#line 712 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::HitGround(void) { +#line 716 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vSource ; +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_penEnemy != NULL ) +#line 718 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 719 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +vSource = GetPlacement () . pl_PositionVector + +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D (m_penEnemy -> en_mRotation (1 , 2) , m_penEnemy -> en_mRotation (2 , 2) , m_penEnemy -> en_mRotation (3 , 2)); +#line 721 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 722 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +else +#line 723 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 724 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +vSource = GetPlacement () . pl_PositionVector ; +#line 725 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 728 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_LARGE ){ +#line 729 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +InflictRangeDamage (this , DMT_IMPACT , 150.0f , vSource , 7.5f , m_fCloseDistance ); +#line 730 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShakeItBaby (_pTimer -> CurrentTick () , 5.0f); +#line 731 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SpawnShockwave (10.0f); +#line 732 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else if(m_EecChar == ELC_BIG ){ +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +InflictRangeDamage (this , DMT_IMPACT , 75.0f , vSource , 5.0f , m_fCloseDistance ); +#line 734 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShakeItBaby (_pTimer -> CurrentTick () , 2.0f); +#line 735 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SpawnShockwave (3.0f); +#line 736 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 737 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +InflictRangeDamage (this , DMT_IMPACT , 25.0f , vSource , 2.5f , m_fCloseDistance ); +#line 738 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SpawnShockwave (1.0f); +#line 739 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 740 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 788 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::AddAttachments(void) { +#line 789 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EetType ){ +#line 803 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_LAVA : +#line 804 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(GetModelObject () -> GetAttachmentModel (ELEMENTALLAVA_ATTACHMENT_BODY_FLARE ) == NULL ){ +#line 805 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +AddAttachmentToModel (this , * GetModelObject () , ELEMENTALLAVA_ATTACHMENT_BODY_FLARE , MODEL_LAVA_BODY_FLARE , TEXTURE_LAVA_FLARE , 0 , 0 , 0); +#line 806 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +AddAttachmentToModel (this , * GetModelObject () , ELEMENTALLAVA_ATTACHMENT_RIGHT_HAND_FLARE , MODEL_LAVA_HAND_FLARE , TEXTURE_LAVA_FLARE , 0 , 0 , 0); +#line 807 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +AddAttachmentToModel (this , * GetModelObject () , ELEMENTALLAVA_ATTACHMENT_LEFT_HAND_FLARE , MODEL_LAVA_HAND_FLARE , TEXTURE_LAVA_FLARE , 0 , 0 , 0); +#line 808 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 809 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ; +#line 822 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 823 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +GetModelObject () -> StretchModel (GetModelObject () -> mo_Stretch ); +#line 824 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ModelChangeNotify (); +#line 825 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 828 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::RemoveAttachments(void) { +#line 829 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EetType ){ +#line 837 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_LAVA : +#line 838 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +RemoveAttachmentFromModel (* GetModelObject () , ELEMENTALLAVA_ATTACHMENT_BODY_FLARE ); +#line 839 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +RemoveAttachmentFromModel (* GetModelObject () , ELEMENTALLAVA_ATTACHMENT_RIGHT_HAND_FLARE ); +#line 840 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +RemoveAttachmentFromModel (* GetModelObject () , ELEMENTALLAVA_ATTACHMENT_LEFT_HAND_FLARE ); +#line 841 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ; +#line 848 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 849 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::BlowUp(void) { +#line 857 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOATaabbox3D box ; +#line 858 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +GetBoundingBox (box ); +#line 859 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT fEntitySize = box . Size () . MaxNorm () / 2; +#line 861 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +INDEX iCount = 1; +#line 862 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EecChar ){ +#line 863 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_SMALL : iCount = 3;break ; +#line 864 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_BIG : iCount = 5;break ; +#line 865 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELC_LARGE : iCount = 7;break ; +#line 866 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 868 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vNormalizedDamage = m_vDamage - m_vDamage * (m_fBlowUpAmount / m_vDamage . Length ()); +#line 869 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +vNormalizedDamage /= Sqrt (vNormalizedDamage . Length ()); +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +vNormalizedDamage *= 1.75f; +#line 871 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute - en_vGravityDir * (en_vGravityDir % en_vCurrentTranslationAbsolute ); +#line 911 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SwitchToEditorModel (); +#line 912 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 913 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 914 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} + +#line 918 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void CElemental::EnemyPostInit(void) +#line 919 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 920 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_LARGE && m_EetType == ELT_LAVA ) +#line 921 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 922 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_soBackground . Set3DParameters (400.0f , 0.0f , 1.0f , 1.0f); +#line 923 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_soSound . Set3DParameters (400.0f , 50.0f , 1.0f , 1.0f); +#line 924 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_soFireL . Set3DParameters (400.0f , 50.0f , 1.0f , 1.0f); +#line 925 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_soFireR . Set3DParameters (400.0f , 50.0f , 1.0f , 1.0f); +#line 926 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 927 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +else if(m_EecChar == ELC_BIG && m_EetType == ELT_LAVA ) +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 929 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_soBackground . Set3DParameters (150.0f , 15.0f , 0.5f , 1.0f); +#line 930 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_soSound . Set3DParameters (200.0f , 0.0f , 1.0f , 1.0f); +#line 931 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_soFireL . Set3DParameters (200.0f , 0.0f , 1.0f , 1.0f); +#line 932 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_soFireR . Set3DParameters (200.0f , 0.0f , 1.0f , 1.0f); +#line 933 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 934 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +BOOL CElemental:: +#line 940 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FallOnFloor(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_FallOnFloor + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::FallOnFloor expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 942 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 944 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(10.0f); +Jump(STATE_CURRENT, 0x01420001, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420001_FallOnFloor_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01420002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&et= (ETouch&)__eeInput; + +#line 949 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(et . penOther -> GetRenderType () & RT_BRUSH ){ +#line 951 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StopMoving (); +#line 952 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +UnsetTimer();Jump(STATE_CURRENT,0x01420002, FALSE, EInternal());return TRUE; +#line 953 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 954 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; +#line 955 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 957 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}return TRUE;}BOOL CElemental::H0x01420002_FallOnFloor_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420002 + +#line 958 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_MELTUP , 0); +#line 959 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 959 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1006 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +LavamanFire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_LavamanFire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::LavamanFire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1008 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_bSpawnEnabled = TRUE ; +#line 1010 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(!(m_EecChar == ELC_LARGE )){ Jump(STATE_CURRENT,0x01420012, FALSE, EInternal());return TRUE;} +#line 1012 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CModelObject & mo = * GetModelObject (); +#line 1013 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT tmWait = mo . GetAnimLength (mo . ao_iCurrentAnim ) - mo . GetPassedTime (); +#line 1014 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_ATTACKBOSS , AOF_SMOOTHCHANGE ); +#line 1015 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(tmWait + 0.95f); +Jump(STATE_CURRENT, 0x01420004, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420004_LavamanFire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420005, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420005_LavamanFire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420005 +; +#line 1016 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BossFirePredictedLavaRock (LAVAMAN_FIRE_LARGE_RIGHT ); +#line 1017 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soFireR , SOUND_LAVA_FIRE , SOF_3D ); +#line 1018 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(2.0150f - 0.95f); +Jump(STATE_CURRENT, 0x01420006, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420006_LavamanFire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420007, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420007_LavamanFire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420007 +; +#line 1019 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BossFirePredictedLavaRock (LAVAMAN_FIRE_LARGE_LEFT ); +#line 1020 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soFireL , SOUND_LAVA_FIRE , SOF_3D ); +#line 1021 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_WALKBIG , AOF_SMOOTHCHANGE ); +#line 1022 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x01420008, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420008_LavamanFire_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01420009, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420009_LavamanFire_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420009 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1023 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +MaybeSwitchToAnotherPlayer (); +#line 1025 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fShootTime = _pTimer -> CurrentTick () + m_fAttackFireTime * (1.0f + FRnd () / 5.0f); +#line 1026 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 1026 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE;Jump(STATE_CURRENT,0x01420011, FALSE, EInternal());return TRUE;}BOOL CElemental::H0x01420012_LavamanFire_15(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420012 +if(!(m_EecChar == ELC_BIG )){ Jump(STATE_CURRENT,0x01420010, FALSE, EInternal());return TRUE;} +#line 1030 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CModelObject & mo = * GetModelObject (); +#line 1031 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT tmWait = mo . GetAnimLength (mo . ao_iCurrentAnim ) - mo . GetPassedTime (); +#line 1032 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_ATTACKLEFTHAND , AOF_SMOOTHCHANGE ); +#line 1033 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(tmWait + 0.90f); +Jump(STATE_CURRENT, 0x0142000a, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x0142000a_LavamanFire_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0142000b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x0142000b_LavamanFire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142000b +; +#line 1034 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vShooting = GetPlacement () . pl_PositionVector ; +#line 1035 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vTarget = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 1036 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vSpeedDest = ((CMovableEntity &) * m_penEnemy ) . en_vCurrentTranslationAbsolute ; +#line 1037 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT fLaunchSpeed ; +#line 1038 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT fRelativeHdg ; +#line 1040 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT fPitch = 20.0f; +#line 1043 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 1044 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CalculateAngularLaunchParams (vShooting , LAVAMAN_FIRE_BIG (2) - peiTarget -> vTargetCenter [ 1 ] - 1.5f / 3.0f , vTarget , +#line 1045 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +vSpeedDest , fPitch , fLaunchSpeed , fRelativeHdg ); +#line 1048 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT3D vShootTarget ; +#line 1049 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +GetEntityInfoPosition (m_penEnemy , peiTarget -> vTargetCenter , vShootTarget ); +#line 1051 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CPlacement3D pl ; +#line 1052 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PrepareFreeFlyingProjectile (pl , vShootTarget , LAVAMAN_FIRE_BIG , ANGLE3D (fRelativeHdg , fPitch , 0)); +#line 1053 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 1054 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ELaunchProjectile eLaunch ; +#line 1055 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eLaunch . penLauncher = this ; +#line 1056 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eLaunch . prtType = PRT_LAVAMAN_BOMB ; +#line 1057 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +eLaunch . fSpeed = fLaunchSpeed ; +#line 1058 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +penProjectile -> Initialize (eLaunch ); +#line 1059 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soSound , SOUND_LAVA_FIRE , SOF_3D );Jump(STATE_CURRENT,0x0142000f, FALSE, EInternal());return TRUE;}BOOL CElemental::H0x01420010_LavamanFire_13(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420010 +if(!(TRUE )){ Jump(STATE_CURRENT,0x0142000e, FALSE, EInternal());return TRUE;} +#line 1063 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +CModelObject & mo = * GetModelObject (); +#line 1064 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT tmWait = mo . GetAnimLength (mo . ao_iCurrentAnim ) - mo . GetPassedTime (); +#line 1065 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_ATTACKLEFTHAND , AOF_SMOOTHCHANGE ); +#line 1066 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(tmWait + 0.8f); +Jump(STATE_CURRENT, 0x0142000c, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x0142000c_LavamanFire_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142000c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0142000d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x0142000d_LavamanFire_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142000d +; +#line 1067 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ShootProjectile (PRT_LAVAMAN_STONE , LAVAMAN_FIRE_SMALL , ANGLE3D (0 , 0 , 0)); +#line 1068 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soSound , SOUND_LAVA_FIRE , SOF_3D );Jump(STATE_CURRENT,0x0142000e, FALSE, EInternal());return TRUE;}BOOL CElemental::H0x0142000e_LavamanFire_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142000e +Jump(STATE_CURRENT,0x0142000f, FALSE, EInternal());return TRUE;} +BOOL CElemental::H0x0142000f_LavamanFire_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142000f +Jump(STATE_CURRENT,0x01420011, FALSE, EInternal());return TRUE;} +BOOL CElemental::H0x01420011_LavamanFire_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420011 + +#line 1071 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (ELEMENTALLAVA_ANIM_ATTACKLEFTHAND ) - 0.9f); +Jump(STATE_CURRENT, 0x01420013, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420013_LavamanFire_16(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420013 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420014, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420014_LavamanFire_17(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420014 +; +#line 1073 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StandingAnim (); +#line 1074 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01420015, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420015_LavamanFire_18(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420016, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420016_LavamanFire_19(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420016 +; +#line 1076 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar != ELC_SMALL ){ +#line 1077 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +MaybeSwitchToAnotherPlayer (); +#line 1078 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1081 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fShootTime = _pTimer -> CurrentTick () + m_fAttackFireTime * (1.0f + FRnd () / 5.0f); +#line 1083 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 1083 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +LavamanStones(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_LavamanStones + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::LavamanStones expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1088 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_ATTACKLEFTHAND , 0); +#line 1089 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(0.7f); +Jump(STATE_CURRENT, 0x01420018, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420018_LavamanStones_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420018 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420019, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420019_LavamanStones_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420019 +; +#line 1091 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_LARGE ){ +#line 1092 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ThrowRocks (PRT_LAVAMAN_STONE ); +#line 1093 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else if(m_EecChar == ELC_BIG ){ +#line 1094 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ThrowRocks (PRT_LAVAMAN_STONE ); +#line 1095 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 1096 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ThrowRocks (PRT_LAVAMAN_STONE ); +#line 1097 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1098 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soSound , SOUND_LAVA_FIRE , SOF_3D ); +#line 1099 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(0.9f); +Jump(STATE_CURRENT, 0x0142001a, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x0142001a_LavamanStones_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142001a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0142001b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x0142001b_LavamanStones_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142001b +; +#line 1101 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StandingAnim (); +#line 1102 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(FRnd () / 3 + _pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x0142001c, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x0142001c_LavamanStones_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142001c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0142001d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x0142001d_LavamanStones_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142001d +; +#line 1103 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 1103 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1106 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +LavamanHit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_LavamanHit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::LavamanHit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1108 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_ATTACKTWOHANDS , 0); +#line 1109 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(0.6f); +Jump(STATE_CURRENT, 0x0142001f, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x0142001f_LavamanHit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142001f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420020, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420020_LavamanHit_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420020 +; +#line 1110 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +HitGround (); +#line 1111 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soFireL , SOUND_LAVA_KICK , SOF_3D ); +#line 1112 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_WALKBIG , AOF_SMOOTHCHANGE ); +#line 1113 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE; +Jump(STATE_CURRENT, 0x01420021, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420021_LavamanHit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420021 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovableModelEntity_WaitUntilScheduledAnimStarts, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01420022, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420022_LavamanHit_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420022 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1114 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 1114 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1209 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BeWounded(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_BeWounded + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDamage, "CElemental::BeWounded expects 'EDamage' as input!"); const EDamage &eDamage = (const EDamage &)__eeInput; +#line 1211 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_bSpawnEnabled ) +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 1213 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SpawnNewElemental (); +#line 1214 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1215 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_BeWounded, FALSE, eDamage );return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1222 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BoxToNormal(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_BoxToNormal + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::BoxToNormal expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1223 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_EesCurrentState = ELS_NORMAL ; +#line 1224 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 1225 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ChangeCollisionBoxIndexWhenPossible (STONEMAN_COLLISION_BOX_NORMAL ); +#line 1226 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soFireL , SOUND_LAVA_GROW , SOF_3D ); +#line 1227 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (STONEMAN_ANIM_MORPHBOXUP , 0); +#line 1228 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +AddAttachments (); +#line 1229 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (STONEMAN_ANIM_MORPHBOXUP )); +Jump(STATE_CURRENT, 0x01420025, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420025_BoxToNormal_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420025 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420026, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420026_BoxToNormal_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420026 +; +#line 1230 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 1230 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1245 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaneToNormal(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_PlaneToNormal + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::PlaneToNormal expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_EesCurrentState = ELS_NORMAL ; +#line 1247 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SwitchToModel (); +#line 1248 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 1249 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ChangeCollisionBoxIndexWhenPossible (ELEMENTALLAVA_COLLISION_BOX_NORMAL ); +#line 1250 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soFireL , SOUND_LAVA_GROW , SOF_3D ); +#line 1251 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +INDEX iAnim ; +#line 1252 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EetType == ELT_LAVA ){ +#line 1253 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +iAnim = ELEMENTALLAVA_ANIM_MELTUP ; +#line 1254 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 1256 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1257 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (iAnim , 0); +#line 1258 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +AddAttachments (); +#line 1259 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (iAnim )); +Jump(STATE_CURRENT, 0x01420028, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420028_PlaneToNormal_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420028 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420029, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420029_PlaneToNormal_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420029 +; +#line 1260 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 1260 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1266 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +InitializeAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_InitializeAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::InitializeAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1268 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(!(m_EesCurrentState == ELS_BOX )){ Jump(STATE_CURRENT,0x01420031, FALSE, EInternal());return TRUE;} +#line 1270 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +STATE_CElemental_BoxToNormal, TRUE; +Jump(STATE_CURRENT, 0x0142002b, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x0142002b_InitializeAttack_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142002b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CElemental_BoxToNormal, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0142002c, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CElemental::H0x0142002c_InitializeAttack_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142002c +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01420030, FALSE, EInternal());return TRUE;}BOOL CElemental::H0x01420031_InitializeAttack_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420031 +if(!(m_EesCurrentState == ELS_PLANE )){ Jump(STATE_CURRENT,0x0142002f, FALSE, EInternal());return TRUE;} +#line 1275 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +STATE_CElemental_PlaneToNormal, TRUE; +Jump(STATE_CURRENT, 0x0142002d, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x0142002d_InitializeAttack_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142002d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CElemental_PlaneToNormal, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0142002e, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CElemental::H0x0142002e_InitializeAttack_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142002e +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x0142002f, FALSE, EInternal());return TRUE;}BOOL CElemental::H0x0142002f_InitializeAttack_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142002f +Jump(STATE_CURRENT,0x01420030, FALSE, EInternal());return TRUE;} +BOOL CElemental::H0x01420030_InitializeAttack_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420030 + +#line 1277 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_InitializeAttack, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1280 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1282 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EetType ){ +#line 1284 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_LAVA : Jump(STATE_CURRENT, STATE_CElemental_LavamanFire, TRUE, EVoid());return TRUE;break ; +#line 1288 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1294 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EetType ){ +#line 1296 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_LAVA : Jump(STATE_CURRENT, STATE_CElemental_LavamanHit, TRUE, EVoid());return TRUE;break ; +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1301 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 1301 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1307 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Death(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_Death + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::Death expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1309 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_bSpawnOnBlowUp && (m_EecChar == ELC_LARGE || m_EecChar == ELC_BIG )){ +#line 1310 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SpawnNewElemental (); +#line 1311 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SpawnNewElemental (); +#line 1312 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1314 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(!(m_EetType == ELT_AIR )){ Jump(STATE_CURRENT,0x01420037, FALSE, EInternal());return TRUE;} +#line 1315 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fFadeStartTime = _pTimer -> CurrentTick (); +#line 1316 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_bFadeOut = TRUE ; +#line 1317 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fFadeTime = 2.0f; +#line 1318 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(m_fFadeTime ); +Jump(STATE_CURRENT, 0x01420035, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420035_Death_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420035 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420036, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420036_Death_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420036 +;Jump(STATE_CURRENT,0x01420037, FALSE, EInternal());return TRUE;}BOOL CElemental::H0x01420037_Death_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420037 + +#line 1320 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +STATE_CEnemyBase_Death, FALSE; +Jump(STATE_CURRENT, 0x01420038, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420038_Death_04(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420038 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_Death, FALSE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01420039, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420039_Death_05(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420039 +const EEnd&__e= (EEnd&)__eeInput; +; +#line 1321 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +GetModelObject () -> mo_toBump . SetData (NULL ); +#line 1322 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EEnd ()); +#line 1322 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BossAppear(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_BossAppear + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::BossAppear expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1327 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(2.0f); +Jump(STATE_CURRENT, 0x0142003b, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x0142003b_BossAppear_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142003b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0142003c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x0142003c_BossAppear_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142003c +; +#line 1328 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fFadeStartTime = _pTimer -> CurrentTick (); +#line 1329 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +GetModelObject () -> PlayAnim (ELEMENTALLAVA_ANIM_ANGER , 0); +#line 1330 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soSound , SOUND_LAVA_ANGER , SOF_3D ); +#line 1331 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (ELEMENTALLAVA_ANIM_ANGER ) - _pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x0142003d, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x0142003d_BossAppear_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142003d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0142003e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x0142003e_BossAppear_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142003e +; +#line 1333 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_ATTACKTWOHANDS , AOF_SMOOTHCHANGE ); +#line 1334 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(0.7f); +Jump(STATE_CURRENT, 0x0142003f, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x0142003f_BossAppear_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142003f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420040, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420040_BossAppear_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420040 +; +#line 1335 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +HitGround (); +#line 1336 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soFireL , SOUND_LAVA_KICK , SOF_3D ); +#line 1337 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (ELEMENTALLAVA_ANIM_ATTACKTWOHANDS ) - 0.7f - _pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01420041, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420041_BossAppear_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420041 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420042, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420042_BossAppear_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420042 +; +#line 1339 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StartModelAnim (ELEMENTALLAVA_ANIM_ATTACKTWOHANDS , 0); +#line 1340 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(0.6f); +Jump(STATE_CURRENT, 0x01420043, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420043_BossAppear_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420043 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420044, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420044_BossAppear_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420044 +; +#line 1341 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +HitGround (); +#line 1342 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soFireR , SOUND_LAVA_KICK , SOF_3D ); +#line 1343 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (ELEMENTALLAVA_ANIM_ATTACKTWOHANDS ) - 0.6f - _pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01420045, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420045_BossAppear_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420045 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01420046, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420046_BossAppear_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420046 +; +#line 1346 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 1346 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PreMainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_PreMainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::PreMainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1353 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(!(m_bSpawned )){ Jump(STATE_CURRENT,0x0142004a, FALSE, EInternal());return TRUE;} +#line 1354 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_bSpawned = FALSE ; +#line 1355 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_bCountAsKill = FALSE ; +#line 1357 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +STATE_CElemental_FallOnFloor, TRUE; +Jump(STATE_CURRENT, 0x01420048, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x01420048_PreMainLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420048 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CElemental_FallOnFloor, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01420049, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CElemental::H0x01420049_PreMainLoop_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01420049 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x0142004a, FALSE, EInternal());return TRUE;}BOOL CElemental::H0x0142004a_PreMainLoop_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142004a + +#line 1360 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_LARGE || m_EecChar == ELC_BIG && m_EetType == ELT_LAVA ) +#line 1361 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 1362 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaySound (m_soBackground , SOUND_LAVA_LAVABURN , SOF_3D | SOF_LOOP ); +#line 1363 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1365 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(!(m_EecChar == ELC_LARGE )){ Jump(STATE_CURRENT,0x0142004d, FALSE, EInternal());return TRUE;} +#line 1367 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +STATE_CElemental_BossAppear, TRUE; +Jump(STATE_CURRENT, 0x0142004b, FALSE, EBegin());return TRUE;}BOOL CElemental::H0x0142004b_PreMainLoop_04(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142004b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CElemental_BossAppear, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0142004c, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CElemental::H0x0142004c_PreMainLoop_05(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142004c +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x0142004d, FALSE, EInternal());return TRUE;}BOOL CElemental::H0x0142004d_PreMainLoop_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0142004d + +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Return(STATE_CURRENT,EReturn ()); +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CElemental:: +#line 1375 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CElemental_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CElemental::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1376 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EetType != ELT_LAVA ){ +#line 1377 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_EetType = ELT_LAVA ; +#line 1378 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1380 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +InitAsModel (); +#line 1382 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_bMovable ){ +#line 1383 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 1385 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 1386 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL | EPF_MOVABLE ); +#line 1387 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1389 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EetType == ELT_AIR ){ +#line 1390 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetCollisionFlags (ECF_AIR ); +#line 1392 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else { +#line 1393 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetCollisionFlags (ECF_MODEL ); +#line 1394 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1395 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 1396 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +en_fDensity = m_fDensity ; +#line 1397 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fSpawnDamage = 1e6f; +#line 1398 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fDamageWounded = 1e6f; +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_bSpawnEnabled = FALSE ; +#line 1400 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_bBoss = FALSE ; +#line 1403 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EetType ){ +#line 1410 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELT_LAVA : +#line 1411 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fBlowUpAmount = 1E30f; +#line 1412 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetComponents (this , * GetModelObject () , MODEL_LAVA , TEXTURE_LAVA , 0 , 0 , TEXTURE_LAVA_DETAIL ); +#line 1413 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ; +#line 1420 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1421 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ModelChangeNotify (); +#line 1424 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_LARGE ) +#line 1425 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 1427 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_sptType = SPT_SMALL_LAVA_STONES ; +#line 1428 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_bBoss = TRUE ; +#line 1429 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetHealth (10000.0f); +#line 1430 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fMaxHealth = 10000.0f; +#line 1432 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fSpawnDamage = 2000.0f; +#line 1434 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fWalkSpeed = FRnd () / 2 + 1.0f; +#line 1435 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 25.0f); +#line 1436 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fAttackRunSpeed = FRnd () + 2.0f; +#line 1437 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 1438 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fCloseRunSpeed = FRnd () + 2.0f; +#line 1439 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 1441 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fAttackDistance = 300.0f; +#line 1442 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fCloseDistance = 60.0f; +#line 1443 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fStopDistance = 30.0f; +#line 1444 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fAttackFireTime = 0.5f; +#line 1445 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fCloseFireTime = 1.0f; +#line 1446 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fIgnoreRange = 600.0f; +#line 1447 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_iScore = 50000; +#line 1448 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1449 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +else if(m_EecChar == ELC_BIG ) +#line 1450 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 1451 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_sptType = SPT_LAVA_STONES ; +#line 1452 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetHealth (800.0f); +#line 1453 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fMaxHealth = 800.0f; +#line 1455 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fSpawnDamage = 500.0f; +#line 1457 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fWalkSpeed = FRnd () + 1.5f; +#line 1458 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 25.0f); +#line 1459 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fAttackRunSpeed = FRnd () * 1.0f + 6.0f; +#line 1460 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 300.0f); +#line 1461 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fCloseRunSpeed = FRnd () * 2.0f + 2.0f; +#line 1462 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 300.0f); +#line 1464 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fAttackDistance = 150.0f; +#line 1465 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fCloseDistance = 20.0f; +#line 1466 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fStopDistance = 5.0f; +#line 1467 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fAttackFireTime = 0.5f; +#line 1468 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fCloseFireTime = 1.0f; +#line 1469 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fIgnoreRange = 400.0f; +#line 1471 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_iScore = 2500; +#line 1472 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1473 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +else +#line 1474 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 1475 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_sptType = SPT_LAVA_STONES ; +#line 1476 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetHealth (100.0f); +#line 1477 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fMaxHealth = 100.0f; +#line 1479 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fWalkSpeed = FRnd () + 1.5f; +#line 1480 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 25.0f); +#line 1481 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fAttackRunSpeed = FRnd () * 2.0f + 6.0f; +#line 1482 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 500.0f); +#line 1483 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fCloseRunSpeed = FRnd () * 3.0f + 4.0f; +#line 1484 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 500.0f); +#line 1486 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fAttackDistance = 100.0f; +#line 1487 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fCloseDistance = 10.0f; +#line 1488 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fStopDistance = 5.0f; +#line 1489 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fAttackFireTime = 1.5f; +#line 1490 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fCloseFireTime = 1.0f; +#line 1491 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_fIgnoreRange = 200.0f; +#line 1493 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_iScore = 500; +#line 1494 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1497 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(! m_bMovable ) +#line 1498 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 1499 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_EesStartState = ELS_NORMAL ; +#line 1500 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_bSpawnWhenHarmed = FALSE ; +#line 1501 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_bSpawnOnBlowUp = FALSE ; +#line 1503 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_iFireCount <= 0) +#line 1504 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +{ +#line 1505 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +WarningMessage ("Entity: %s - Fire count must be greater than zero" , GetName ()); +#line 1506 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_iFireCount = 1; +#line 1507 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1508 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1511 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +m_EesCurrentState = m_EesStartState ; +#line 1512 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +RemoveAttachments (); +#line 1513 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +switch(m_EesCurrentState ){ +#line 1514 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELS_NORMAL : +#line 1515 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 1516 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +AddAttachments (); +#line 1517 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ; +#line 1518 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELS_BOX : +#line 1519 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetPhysicsFlags (EPF_BOX_PLANE_ELEMENTAL ); +#line 1520 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ; +#line 1521 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +case ELS_PLANE : +#line 1522 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL | EPF_MOVABLE ); +#line 1523 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +SwitchToEditorModel (); +#line 1524 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +break ; +#line 1525 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1526 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +StandingAnim (); +#line 1529 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +if(m_EecChar == ELC_SMALL ){ +#line 1530 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +GetModelObject () -> StretchModel (FLOAT3D (LAVAMAN_SMALL_STRETCH , LAVAMAN_SMALL_STRETCH , LAVAMAN_SMALL_STRETCH )); +#line 1531 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1532 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +else if(m_EecChar == ELC_LARGE ){ +#line 1533 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +GetModelObject () -> StretchModel (FLOAT3D (LAVAMAN_LARGE_STRETCH , LAVAMAN_LARGE_STRETCH , LAVAMAN_LARGE_STRETCH )); +#line 1534 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +}else if(m_EecChar == ELC_BIG ){ +#line 1535 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +GetModelObject () -> StretchModel (FLOAT3D (LAVAMAN_BIG_STRETCH , LAVAMAN_BIG_STRETCH , LAVAMAN_BIG_STRETCH )); +#line 1536 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +} +#line 1537 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +ModelChangeNotify (); +#line 1540 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Elemental.es b/Sources/EntitiesMP/Elemental.es new file mode 100644 index 0000000..83ef834 --- /dev/null +++ b/Sources/EntitiesMP/Elemental.es @@ -0,0 +1,1542 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +322 +%{ +#include "StdH.h" +//#include "Models/Enemies/Elementals/AirMan.h" +//#include "Models/Enemies/Elementals/IceMan.h" +#include "Models/Enemies/Elementals/StoneMan.h" +//#include "Models/Enemies/Elementals/Twister.h" +//#include "Models/Enemies/Elementals/WaterMan.h" +//#include "Models/Enemies/Elementals/Projectile/IcePyramid.h" +#include "Models/Enemies/Elementals/Projectile/LavaStone.h" + +#include "Models/Enemies/ElementalLava/ElementalLava.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" + +// lava elemental definitions +#define LAVAMAN_SMALL_STRETCH (2.0f*0.75f) +#define LAVAMAN_BIG_STRETCH (4.0f*1.25f) +#define LAVAMAN_LARGE_STRETCH (16.0f*2.5f) + +#define LAVAMAN_BOSS_FIRE_RIGHT FLOAT3D(1.01069f, 0.989616f, -1.39743f) +#define LAVAMAN_BOSS_FIRE_LEFT FLOAT3D(-0.39656f, 1.08619f, -1.34373f) +#define LAVAMAN_FIRE_LEFT FLOAT3D(-0.432948f, 1.51133f, -0.476662f) + +#define LAVAMAN_FIRE_SMALL (LAVAMAN_FIRE_LEFT*LAVAMAN_SMALL_STRETCH) +#define LAVAMAN_FIRE_BIG (LAVAMAN_FIRE_LEFT*LAVAMAN_BIG_STRETCH) +#define LAVAMAN_FIRE_LARGE_LEFT (LAVAMAN_BOSS_FIRE_LEFT*LAVAMAN_LARGE_STRETCH) +#define LAVAMAN_FIRE_LARGE_RIGHT (LAVAMAN_BOSS_FIRE_RIGHT*LAVAMAN_LARGE_STRETCH) + +#define LAVAMAN_SPAWN_BIG (FLOAT3D(0.0171274f, 1.78397f, -0.291414f)*LAVAMAN_BIG_STRETCH) +#define LAVAMAN_SPAWN_LARGE (FLOAT3D(0.0171274f, 1.78397f, -0.291414f)*LAVAMAN_LARGE_STRETCH) +#define DEATH_BURN_TIME 1.0f + +%} + +uses "EntitiesMP/EnemyBase"; +//uses "EntitiesMP/Twister"; +//uses "EntitiesMP/Water"; + +enum ElementalType { + 0 ELT_AIR "obsolete", // air elemental + 1 ELT_ICE "obsolete", // ice elemental + 2 ELT_LAVA "Lava", // lava elemental + 3 ELT_STONE "obsolete", // stone elemental + 4 ELT_WATER "obsolete", // water elemental +}; + + +enum ElementalCharacter { + 0 ELC_SMALL "Small", // small (fighter) + 1 ELC_BIG "Big", // big + 2 ELC_LARGE "Large", // large +}; + + +enum ElementalState { + 0 ELS_NORMAL "Normal", // normal state + 1 ELS_BOX "Box", // in box + 2 ELS_PLANE "Plane", // as plane +}; + + +%{ +#define ECF_AIR ( \ + ((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)<CurrentTick()-m_fSpiritStartTime)/DEATH_BURN_TIME, 0.0f, 1.0f); + } + Particles_Burning(this, fPower, fTimeFactor*fDeathFactor); + } + } + + void Precache(void) + { + CEnemyBase::Precache(); + + switch(m_EetType) + { + case ELT_LAVA: + { + if( m_EecChar == ELC_LARGE) + { + PrecacheClass(CLASS_PROJECTILE, PRT_LAVAMAN_BIG_BOMB); + } + if( (m_EecChar == ELC_LARGE) || (m_EecChar == ELC_BIG) ) + { + PrecacheClass(CLASS_PROJECTILE, PRT_LAVAMAN_BOMB); + } + + PrecacheClass(CLASS_PROJECTILE, PRT_LAVAMAN_STONE); + + PrecacheModel (MODEL_LAVA ); + PrecacheModel (MODEL_LAVA_BODY_FLARE ); + PrecacheModel (MODEL_LAVA_HAND_FLARE ); + PrecacheTexture(TEXTURE_LAVA ); + PrecacheTexture(TEXTURE_LAVA_DETAIL ); + PrecacheTexture(TEXTURE_LAVA_FLARE ); + + PrecacheSound(SOUND_LAVA_IDLE ); + PrecacheSound(SOUND_LAVA_WOUND ); + PrecacheSound(SOUND_LAVA_FIRE ); + PrecacheSound(SOUND_LAVA_KICK ); + PrecacheSound(SOUND_LAVA_DEATH ); + PrecacheSound(SOUND_LAVA_ANGER ); + PrecacheSound(SOUND_LAVA_LAVABURN); + PrecacheSound(SOUND_LAVA_GROW ); + break; + } + } + }; + + /* Entity info */ + void *GetEntityInfo(void) { + switch (m_EetType) { + case ELT_AIR: + switch(m_EecChar) { + case ELC_LARGE: return &eiAirElementalLarge; + case ELC_BIG: return &eiAirElementalBig; + default: { return &eiAirElementalSmall; } + } + break; + case ELT_ICE: + switch(m_EecChar) { + case ELC_LARGE: return &eiIceElementalLarge; + case ELC_BIG: return &eiIceElementalBig; + default: { return &eiIceElementalSmall; } + } + break; + case ELT_LAVA: + switch(m_EecChar) { + case ELC_LARGE: return &eiLavaElementalLarge; + case ELC_BIG: return &eiLavaElementalBig; + default: { return &eiLavaElementalSmall; } + } + break; + case ELT_STONE: + switch(m_EecChar) { + case ELC_LARGE: return &eiStoneElementalLarge; + case ELC_BIG: return &eiStoneElementalBig; + default: { return &eiStoneElementalSmall; } + } + break; + //case ELT_WATER: + default: { + switch(m_EecChar) { + case ELC_LARGE: return &eiWaterElementalLarge; + case ELC_BIG: return &eiWaterElementalBig; + default: { return &eiWaterElementalSmall; } + }} + } + }; + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + CEnemyBase::FillEntityStatistics(pes); + switch(m_EetType) { + case ELT_WATER : { pes->es_strName+=" Water"; } break; + case ELT_AIR : { pes->es_strName+=" Air"; } break; + case ELT_STONE : { pes->es_strName+=" Stone"; } break; + case ELT_LAVA : { pes->es_strName+=" Lava"; } break; + case ELT_ICE : { pes->es_strName+=" Ice"; } break; + } + switch(m_EecChar) { + case ELC_LARGE: pes->es_strName+=" Large"; break; + case ELC_BIG: pes->es_strName+=" Big"; break; + case ELC_SMALL: pes->es_strName+=" Small"; break; + } + return TRUE; + } + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // elemental can't harm elemental + if( IsOfClass(penInflictor, "Elemental")) { + return; + } + + // boss can't be telefragged + if( m_EecChar==ELC_LARGE && dmtType==DMT_TELEPORT) + { + return; + } + + // elementals take less damage from heavy bullets (e.g. sniper) + if( m_EecChar==ELC_BIG && dmtType==DMT_BULLET && fDamageAmmount>100.0f) + { + fDamageAmmount/=2.5f; + } + + + INDEX ctShouldSpawn = Clamp( INDEX((m_fMaxHealth-GetHealth())/m_fSpawnDamage), INDEX(0), INDEX(10)); + CTString strChar = ElementalCharacter_enum.NameForValue(INDEX(m_EecChar)); + //CPrintF( "Character: %s, MaxHlt = %g, Hlt = %g, SpwnDmg = %g, Spawned: %d, Should: %d\n", + // strChar, m_fMaxHealth, GetHealth(), m_fSpawnDamage, m_ctSpawned, ctShouldSpawn); + + if (m_bSpawnEnabled && m_bSpawnWhenHarmed && (m_EecChar==ELC_LARGE || m_EecChar==ELC_BIG)) + { + INDEX ctShouldSpawn = Clamp( INDEX((m_fMaxHealth-GetHealth())/m_fSpawnDamage), INDEX(0), INDEX(10)); + if(m_ctSpawned=ctShouldSpawn) + { + return; + } + + CPlacement3D pl; + // spawn placement + if (m_EecChar==ELC_LARGE) { + pl = CPlacement3D(LAVAMAN_SPAWN_LARGE, ANGLE3D(-90.0f+FRnd()*180.0f, 30+FRnd()*30, 0)); + } else { + pl = CPlacement3D(LAVAMAN_SPAWN_BIG, ANGLE3D(-90.0f+FRnd()*180.0f, 40+FRnd()*20, 0)); + } + pl.RelativeToAbsolute(GetPlacement()); + + // create entity + CEntityPointer pen = GetWorld()->CreateEntity(pl, GetClass()); + ((CElemental&)*pen).m_EetType = m_EetType; + // elemental size + if (m_EecChar==ELC_LARGE) { + ((CElemental&)*pen).m_EecChar = ELC_BIG; + } else { + ((CElemental&)*pen).m_EecChar = ELC_SMALL; + } + // start properties + ((CElemental&)*pen).m_EesStartState = ELS_BOX; + ((CElemental&)*pen).m_fDensity = m_fDensity; + ((CElemental&)*pen).m_colColor = m_colColor; + ((CElemental&)*pen).m_penEnemy = m_penEnemy; + ((CElemental&)*pen).m_ttTarget = m_ttTarget; + ((CElemental&)*pen).m_bSpawned = TRUE; + pen->Initialize(EVoid()); + // set moving + if (m_EecChar==ELC_LARGE) { + ((CElemental&)*pen).LaunchAsFreeProjectile(FLOAT3D(0, 0, -40.0f), this); + } else { + ((CElemental&)*pen).LaunchAsFreeProjectile(FLOAT3D(0, 0, -20.0f), this); + } + ((CElemental&)*pen).SetDesiredRotation(ANGLE3D(0, 0, FRnd()*360-180)); + + // spawn particle debris explosion + CEntity *penSpray = CreateEntity( pl, CLASS_BLOOD_SPRAY); + penSpray->SetParent( pen); + ESpawnSpray eSpawnSpray; + eSpawnSpray.fDamagePower = 4.0f; + eSpawnSpray.fSizeMultiplier = 0.5f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = FLOAT3D(0,-0.5f,0); + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.penOwner = pen; + penSpray->Initialize( eSpawnSpray); + m_ctSpawned++; + }; + + // throw rocks + void ThrowRocks(ProjectileType EptProjectile) { + // projectile type and position + FLOAT3D vPos; + ANGLE3D aAngle; + // throw rocks + switch (m_EecChar) { + case ELC_LARGE: { + vPos = FIRE_ROCKS_LARGE; + ShootProjectile(EptProjectile, vPos, ANGLE3D(0, 0, 0)); + aAngle = ANGLE3D(FRnd()*5.0f+5.0f, FRnd()*3.0f-2.0f, 0); + ShootProjectile(EptProjectile, vPos, aAngle); + aAngle = ANGLE3D(FRnd()*-5.0f-5.0f, FRnd()*3.0f-2.0f, 0); + ShootProjectile(EptProjectile, vPos, aAngle); + break; } + case ELC_BIG: { + vPos = FIRE_ROCKS_BIG; + ShootProjectile(EptProjectile, vPos, ANGLE3D(0, 0, 0)); + aAngle = ANGLE3D(FRnd()*4.0f+4.0f, FRnd()*3.0f-2.0f, 0); + ShootProjectile(EptProjectile, vPos, aAngle); + aAngle = ANGLE3D(FRnd()*-4.0f-4.0f, FRnd()*3.0f-2.0f, 0); + ShootProjectile(EptProjectile, vPos, aAngle); + break; } + default: { + vPos = FIRE_ROCKS; + ShootProjectile(EptProjectile, vPos, ANGLE3D(0, 0, 0)); + aAngle = ANGLE3D(FRnd()*3.0f+3.0f, FRnd()*3.0f-2.0f, 0); + ShootProjectile(EptProjectile, vPos, aAngle); + aAngle = ANGLE3D(FRnd()*-3.0f-3.0f, FRnd()*3.0f-2.0f, 0); + ShootProjectile(EptProjectile, vPos, aAngle); + } + } + }; + + void BossFirePredictedLavaRock(FLOAT3D vFireingRel) + { + FLOAT3D vShooting = GetPlacement().pl_PositionVector+vFireingRel*GetRotationMatrix(); + FLOAT3D vTarget = m_penEnemy->GetPlacement().pl_PositionVector; + FLOAT3D vSpeedDest = ((CMovableEntity&) *m_penEnemy).en_vCurrentTranslationAbsolute; + FLOAT fLaunchSpeed; + FLOAT fRelativeHdg; + + FLOAT fDistanceFactor = ClampUp( (vShooting-vTarget).Length()/150.0f, 1.0f)-0.75f; + FLOAT fPitch = fDistanceFactor*45.0f; + + // calculate parameters for predicted angular launch curve + EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); + CalculateAngularLaunchParams( vShooting, peiTarget->vTargetCenter[1]-6.0f/3.0f, vTarget, + vSpeedDest, fPitch, fLaunchSpeed, fRelativeHdg); + + // target enemy body + FLOAT3D vShootTarget; + GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget); + // launch + CPlacement3D pl; + PrepareFreeFlyingProjectile(pl, vShootTarget, vFireingRel, ANGLE3D( fRelativeHdg, fPitch, 0)); + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_LAVAMAN_BIG_BOMB; + eLaunch.fSpeed = fLaunchSpeed; + penProjectile->Initialize(eLaunch); + } + + /* Shake ground */ + void ShakeItBaby(FLOAT tmShaketime, FLOAT fPower) + { + CWorldSettingsController *pwsc = GetWSC(this); + if (pwsc!=NULL) { + pwsc->m_tmShakeStarted = tmShaketime; + pwsc->m_vShakePos = GetPlacement().pl_PositionVector; + pwsc->m_fShakeFalloff = 450.0f; + pwsc->m_fShakeFade = 3.0f; + + pwsc->m_fShakeIntensityZ = 0; + pwsc->m_tmShakeFrequencyZ = 5.0f; + pwsc->m_fShakeIntensityY = 0.1f*fPower; + pwsc->m_tmShakeFrequencyY = 5.0f; + pwsc->m_fShakeIntensityB = 2.5f*fPower; + pwsc->m_tmShakeFrequencyB = 7.2f; + + pwsc->m_bShakeFadeIn = FALSE; + } + } + + void SpawnShockwave(FLOAT fSize) + { + CPlacement3D pl = GetPlacement(); + pl.pl_PositionVector(2) += 0.1f; + CEntityPointer penShockwave = CreateEntity(pl, CLASS_BASIC_EFFECT); + + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNONSHOCKWAVE; + eSpawnEffect.vStretch = FLOAT3D(fSize, fSize, fSize); + penShockwave->Initialize(eSpawnEffect); + } + + // hit ground + void HitGround(void) { + FLOAT3D vSource; + if( m_penEnemy != NULL) + { + vSource = GetPlacement().pl_PositionVector + + FLOAT3D(m_penEnemy->en_mRotation(1, 2), m_penEnemy->en_mRotation(2, 2), m_penEnemy->en_mRotation(3, 2)); + } + else + { + vSource = GetPlacement().pl_PositionVector; + } + + // damage + if (m_EecChar==ELC_LARGE) { + InflictRangeDamage(this, DMT_IMPACT, 150.0f, vSource, 7.5f, m_fCloseDistance); + ShakeItBaby(_pTimer->CurrentTick(), 5.0f); + SpawnShockwave(10.0f); + } else if (m_EecChar==ELC_BIG) { + InflictRangeDamage(this, DMT_IMPACT, 75.0f, vSource, 5.0f, m_fCloseDistance); + ShakeItBaby(_pTimer->CurrentTick(), 2.0f); + SpawnShockwave(3.0f); + } else { + InflictRangeDamage(this, DMT_IMPACT, 25.0f, vSource, 2.5f, m_fCloseDistance); + SpawnShockwave(1.0f); + } + }; + + // fire water +/* void FireWater(void) { + // target enemy body + EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); + FLOAT3D vShootTarget; + GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget); + + // water projectile + CPlacement3D pl; + EWater ew; + ew.penLauncher = this; + if (m_EecChar==ELC_LARGE) { + ew.EwsSize = WTS_LARGE; + // launch + PreparePropelledProjectile(pl, vShootTarget, WATER_LARGE_LEFT, ANGLE3D(0, 0, 0)); + CEntityPointer penWater = CreateEntity(pl, CLASS_WATER); + penWater->Initialize(ew); + // launch + PreparePropelledProjectile(pl, vShootTarget, WATER_LARGE_RIGHT, ANGLE3D(0, 0, 0)); + penWater = CreateEntity(pl, CLASS_WATER); + penWater->Initialize(ew); + } else if (m_EecChar==ELC_BIG) { + ew.EwsSize = WTS_BIG; + // launch + PreparePropelledProjectile(pl, vShootTarget, WATER_BIG_LEFT, ANGLE3D(0, 0, 0)); + CEntityPointer penWater = CreateEntity(pl, CLASS_WATER); + penWater->Initialize(ew); + // launch + PreparePropelledProjectile(pl, vShootTarget, WATER_BIG_RIGHT, ANGLE3D(0, 0, 0)); + penWater = CreateEntity(pl, CLASS_WATER); + penWater->Initialize(ew); + } else { + ew.EwsSize = WTS_SMALL; + // launch + PreparePropelledProjectile(pl, vShootTarget, WATER_LEFT, ANGLE3D(0, 0, 0)); + CEntityPointer penWater = CreateEntity(pl, CLASS_WATER); + penWater->Initialize(ew); + // launch + PreparePropelledProjectile(pl, vShootTarget, WATER_RIGHT, ANGLE3D(0, 0, 0)); + penWater = CreateEntity(pl, CLASS_WATER); + penWater->Initialize(ew); + } + }; +*/ + + // add attachments + void AddAttachments(void) { + switch (m_EetType) { +/* case ELT_AIR: + if (GetModelObject()->GetAttachmentModel(AIRMAN_ATTACHMENT_TWISTER)==NULL) { + AddAttachmentToModel(this, *GetModelObject(), AIRMAN_ATTACHMENT_TWISTER, + MODEL_AIR_TWISTER, TEXTURE_AIR, 0, 0, 0); + GetModelObject()->mo_ColorMask &= ~AIRMAN_PART_BODYDOWN; + } + break; + case ELT_ICE: + if (GetModelObject()->GetAttachmentModel(ICEMAN_ATTACHMENT_ICEPICK)==NULL) { + AddAttachmentToModel(this, *GetModelObject(), ICEMAN_ATTACHMENT_ICEPICK, + MODEL_ICE_PICK, TEXTURE_ICE, TEXTURE_ICE, TEX_SPEC_STRONG, 0); + } + break;*/ + case ELT_LAVA: + if (GetModelObject()->GetAttachmentModel(ELEMENTALLAVA_ATTACHMENT_BODY_FLARE)==NULL) { + AddAttachmentToModel(this, *GetModelObject(), ELEMENTALLAVA_ATTACHMENT_BODY_FLARE, MODEL_LAVA_BODY_FLARE, TEXTURE_LAVA_FLARE, 0, 0, 0); + AddAttachmentToModel(this, *GetModelObject(), ELEMENTALLAVA_ATTACHMENT_RIGHT_HAND_FLARE, MODEL_LAVA_HAND_FLARE, TEXTURE_LAVA_FLARE, 0, 0, 0); + AddAttachmentToModel(this, *GetModelObject(), ELEMENTALLAVA_ATTACHMENT_LEFT_HAND_FLARE, MODEL_LAVA_HAND_FLARE, TEXTURE_LAVA_FLARE, 0, 0, 0); + } + break; +/* case ELT_STONE: + if (GetModelObject()->GetAttachmentModel(STONEMAN_ATTACHMENT_MAUL)==NULL) { + AddAttachmentToModel(this, *GetModelObject(), STONEMAN_ATTACHMENT_MAUL, + MODEL_STONE_MAUL, TEXTURE_STONE, 0, 0, 0); + } + break; + case ELT_WATER: + if (GetModelObject()->GetAttachmentModel(WATERMAN_ATTACHMENT_BODY_FLARE)==NULL) { + AddAttachmentToModel(this, *GetModelObject(), WATERMAN_ATTACHMENT_BODY_FLARE, + MODEL_WATER_BODY_FLARE, TEXTURE_WATER_FLARE, 0, 0, 0); + } + break;*/ + } + GetModelObject()->StretchModel(GetModelObject()->mo_Stretch); + ModelChangeNotify(); + }; + + // remove attachments + void RemoveAttachments(void) { + switch (m_EetType) { +/* case ELT_AIR: + RemoveAttachmentFromModel(*GetModelObject(), AIRMAN_ATTACHMENT_TWISTER); + GetModelObject()->mo_ColorMask |= AIRMAN_PART_BODYDOWN; + break; + case ELT_ICE: + RemoveAttachmentFromModel(*GetModelObject(), ICEMAN_ATTACHMENT_ICEPICK); + break;*/ + case ELT_LAVA: + RemoveAttachmentFromModel(*GetModelObject(), ELEMENTALLAVA_ATTACHMENT_BODY_FLARE); + RemoveAttachmentFromModel(*GetModelObject(), ELEMENTALLAVA_ATTACHMENT_RIGHT_HAND_FLARE); + RemoveAttachmentFromModel(*GetModelObject(), ELEMENTALLAVA_ATTACHMENT_LEFT_HAND_FLARE); + break; +/* case ELT_STONE: + RemoveAttachmentFromModel(*GetModelObject(), STONEMAN_ATTACHMENT_MAUL); + break; + case ELT_WATER: + RemoveAttachmentFromModel(*GetModelObject(), WATERMAN_ATTACHMENT_BODY_FLARE); + break;*/ + } + }; + +/************************************************************ + * BLOW UP FUNCTIONS * + ************************************************************/ + // spawn body parts + void BlowUp(void) { + // get your size + FLOATaabbox3D box; + GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm()/2; + + INDEX iCount = 1; + switch (m_EecChar) { + case ELC_SMALL: iCount = 3; break; + case ELC_BIG: iCount = 5; break; + case ELC_LARGE: iCount = 7; break; + } + + FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(m_fBlowUpAmount/m_vDamage.Length()); + vNormalizedDamage /= Sqrt(vNormalizedDamage.Length()); + vNormalizedDamage *= 1.75f; + FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute); + + // spawn debris +/* + switch (m_EetType) { + case ELT_ICE: { + Debris_Begin(EIBT_ICE, DPT_NONE, BET_NONE, fEntitySize, vNormalizedDamage, vBodySpeed, 1.0f, 0.0f); + for (iDebris=0; iDebrisGetModelObject()), ICEPYRAMID_ATTACHMENT_FLARE, + MODEL_ELEM_ICE_FLARE, TEXTURE_ELEM_FLARE, 0, 0, 0); + pen->GetModelObject()->StretchModel(pen->GetModelObject()->mo_Stretch); + ModelChangeNotify(); + }} + break; + case ELT_LAVA: { + Debris_Begin(EIBT_FIRE, DPT_NONE, BET_NONE, fEntitySize, vNormalizedDamage, vBodySpeed, 1.0f, 0.0f); + for (iDebris=0; iDebrisGetModelObject()), LAVASTONE_ATTACHMENT_FLARE, + MODEL_ELEM_LAVASTONE_FLARE, TEXTURE_ELEM_FLARE, 0, 0, 0); + pen->GetModelObject()->StretchModel(pen->GetModelObject()->mo_Stretch); + ModelChangeNotify(); + }} + break; + case ELT_STONE: { + Debris_Begin(EIBT_ROCK, DPT_NONE, BET_NONE, fEntitySize, vNormalizedDamage, vBodySpeed, 1.0f, 0.0f); + for (iDebris=0; iDebrisGetRenderType()&RT_BRUSH) { + // stop waiting + StopMoving(); + stop; + } + resume; + } + otherwise() : { resume; } + } + StartModelAnim(ELEMENTALLAVA_ANIM_MELTUP, 0); + return EReturn(); + }; + + + +/************************************************************ + * FIRE PROCEDURES * + ************************************************************/ + // + // STONEMAN + // +/* StonemanFire(EVoid) { + StartModelAnim(STONEMAN_ANIM_ATTACK05, 0); + autowait(0.7f); + // throw rocks + if (m_EecChar==ELC_LARGE) { + ThrowRocks(PRT_STONEMAN_LARGE_FIRE); + } else if (m_EecChar==ELC_BIG) { + ThrowRocks(PRT_STONEMAN_BIG_FIRE); + } else { + ThrowRocks(PRT_STONEMAN_FIRE); + } + PlaySound(m_soSound, SOUND_LAVA_FIRE, SOF_3D); + autowait(0.9f); + // stand a while + StandingAnim(); + autowait(FRnd()/3+_pTimer->TickQuantum); + return EReturn(); + }; + + StonemanHit(EVoid) { + StartModelAnim(STONEMAN_ANIM_ATTACK06, 0); + autowait(0.6f); + HitGround(); + PlaySound(m_soSound, SOUND_LAVA_KICK, SOF_3D); + autowait(0.5f); + // stand a while + StandingAnim(); + autowait(FRnd()/3+_pTimer->TickQuantum); + return EReturn(); + }; + */ + + // + // LAVAMAN + // + + LavamanFire(EVoid) + { + m_bSpawnEnabled = TRUE; + // shoot projectiles + if (m_EecChar==ELC_LARGE) + { + CModelObject &mo = *GetModelObject(); + FLOAT tmWait = mo.GetAnimLength( mo.ao_iCurrentAnim )-mo.GetPassedTime(); + StartModelAnim(ELEMENTALLAVA_ANIM_ATTACKBOSS, AOF_SMOOTHCHANGE); + autowait(tmWait+0.95f); + BossFirePredictedLavaRock(LAVAMAN_FIRE_LARGE_RIGHT); + PlaySound(m_soFireR, SOUND_LAVA_FIRE, SOF_3D); + autowait(2.0150f-0.95f); + BossFirePredictedLavaRock(LAVAMAN_FIRE_LARGE_LEFT); + PlaySound(m_soFireL, SOUND_LAVA_FIRE, SOF_3D); + StartModelAnim(ELEMENTALLAVA_ANIM_WALKBIG, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + MaybeSwitchToAnotherPlayer(); + // set next shoot time + m_fShootTime = _pTimer->CurrentTick() + m_fAttackFireTime*(1.0f + FRnd()/5.0f); + return EReturn(); + } + else if (m_EecChar==ELC_BIG) + { + CModelObject &mo = *GetModelObject(); + FLOAT tmWait = mo.GetAnimLength( mo.ao_iCurrentAnim )-mo.GetPassedTime(); + StartModelAnim(ELEMENTALLAVA_ANIM_ATTACKLEFTHAND, AOF_SMOOTHCHANGE); + autowait(tmWait+0.90f); + FLOAT3D vShooting = GetPlacement().pl_PositionVector; + FLOAT3D vTarget = m_penEnemy->GetPlacement().pl_PositionVector; + FLOAT3D vSpeedDest = ((CMovableEntity&) *m_penEnemy).en_vCurrentTranslationAbsolute; + FLOAT fLaunchSpeed; + FLOAT fRelativeHdg; + + FLOAT fPitch = 20.0f; + + // calculate parameters for predicted angular launch curve + EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); + CalculateAngularLaunchParams( vShooting, LAVAMAN_FIRE_BIG(2)-peiTarget->vTargetCenter[1]-1.5f/3.0f, vTarget, + vSpeedDest, fPitch, fLaunchSpeed, fRelativeHdg); + + // target enemy body + FLOAT3D vShootTarget; + GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget); + // launch + CPlacement3D pl; + PrepareFreeFlyingProjectile(pl, vShootTarget, LAVAMAN_FIRE_BIG, ANGLE3D( fRelativeHdg, fPitch, 0)); + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_LAVAMAN_BOMB; + eLaunch.fSpeed = fLaunchSpeed; + penProjectile->Initialize(eLaunch); + PlaySound(m_soSound, SOUND_LAVA_FIRE, SOF_3D); + } + else if (TRUE) + { + CModelObject &mo = *GetModelObject(); + FLOAT tmWait = mo.GetAnimLength( mo.ao_iCurrentAnim )-mo.GetPassedTime(); + StartModelAnim(ELEMENTALLAVA_ANIM_ATTACKLEFTHAND, AOF_SMOOTHCHANGE); + autowait(tmWait+0.8f); + ShootProjectile(PRT_LAVAMAN_STONE, LAVAMAN_FIRE_SMALL, ANGLE3D(0, 0, 0)); + PlaySound(m_soSound, SOUND_LAVA_FIRE, SOF_3D); + } + + autowait( GetModelObject()->GetAnimLength( ELEMENTALLAVA_ANIM_ATTACKLEFTHAND) - 0.9f); + + StandingAnim(); + autowait(_pTimer->TickQuantum); + + if (m_EecChar!=ELC_SMALL) { + MaybeSwitchToAnotherPlayer(); + } + + // set next shoot time + m_fShootTime = _pTimer->CurrentTick() + m_fAttackFireTime*(1.0f + FRnd()/5.0f); + + return EReturn(); + }; + + LavamanStones(EVoid) + { + StartModelAnim(ELEMENTALLAVA_ANIM_ATTACKLEFTHAND, 0); + autowait(0.7f); + // throw rocks + if (m_EecChar==ELC_LARGE) { + ThrowRocks(PRT_LAVAMAN_STONE); + } else if (m_EecChar==ELC_BIG) { + ThrowRocks(PRT_LAVAMAN_STONE); + } else { + ThrowRocks(PRT_LAVAMAN_STONE); + } + PlaySound(m_soSound, SOUND_LAVA_FIRE, SOF_3D); + autowait(0.9f); + // stand a while + StandingAnim(); + autowait(FRnd()/3+_pTimer->TickQuantum); + return EReturn(); + }; + + LavamanHit(EVoid) + { + StartModelAnim(ELEMENTALLAVA_ANIM_ATTACKTWOHANDS, 0); + autowait(0.6f); + HitGround(); + PlaySound(m_soFireL, SOUND_LAVA_KICK, SOF_3D); + StartModelAnim(ELEMENTALLAVA_ANIM_WALKBIG, AOF_SMOOTHCHANGE); + autocall CMovableModelEntity::WaitUntilScheduledAnimStarts() EReturn; + return EReturn(); + }; + +/* + // + // ICEMAN + // + IcemanFire(EVoid) { + StartModelAnim(STONEMAN_ANIM_ATTACK05, 0); + autowait(0.7f); + // throw rocks + if (m_EecChar==ELC_LARGE) { + ThrowRocks(PRT_ICEMAN_LARGE_FIRE); + } else if (m_EecChar==ELC_BIG) { + ThrowRocks(PRT_ICEMAN_BIG_FIRE); + } else { + ThrowRocks(PRT_ICEMAN_FIRE); + } + PlaySound(m_soSound, SOUND_LAVA_FIRE, SOF_3D); + autowait(0.9f); + // stand a while + StandingAnim(); + autowait(FRnd()/3+_pTimer->TickQuantum); + return EReturn(); + }; + + IcemanHit(EVoid) { + StartModelAnim(STONEMAN_ANIM_ATTACK01, 0); + autowait(0.6f); + HitGround(); + PlaySound(m_soSound, SOUND_LAVA_KICK, SOF_3D); + autowait(0.5f); + // stand a while + StandingAnim(); + autowait(FRnd()/3+_pTimer->TickQuantum); + return EReturn(); + }; + + + // + // AIRMAN + // + AirmanFire(EVoid) { + StartModelAnim(STONEMAN_ANIM_ATTACK06, 0); + autowait(1.0f); + // spawn twister + CPlacement3D pl = m_penEnemy->GetPlacement(); + FLOAT fR, fA; + ETwister et; + fA = FRnd()*360.0f; + if (m_EecChar==ELC_LARGE) { + fR = FRnd()*10.0f; + et.EtsSize = TWS_LARGE; + } else if (m_EecChar==ELC_BIG) { + fR = FRnd()*7.5f; + et.EtsSize = TWS_BIG; + } else { + fR = FRnd()*5.0f; + et.EtsSize = TWS_SMALL; + } + pl.pl_PositionVector += FLOAT3D(CosFast(fA)*fR, 0, SinFast(fA)*fR);; + CEntityPointer penTwister = CreateEntity(pl, CLASS_TWISTER); + et.penOwner = this; + penTwister->Initialize(et); + PlaySound(m_soSound, SOUND_LAVA_FIRE, SOF_3D); + autowait(0.6f); + // stand a while + StandingAnim(); + autowait(FRnd()/3+_pTimer->TickQuantum); + return EReturn(); + }; + + + // + // WATERMAN + // + WatermanFire(EVoid) { + StartModelAnim(STONEMAN_ANIM_ATTACK02, 0); + autowait(0.5f); + // throw rocks + FireWater(); + PlaySound(m_soSound, SOUND_LAVA_FIRE, SOF_3D); + autowait(0.6f); + // stand a while + StandingAnim(); + autowait(FRnd()/3+_pTimer->TickQuantum); + return EReturn(); + }; + */ + + +/************************************************************ + * PROCEDURES WHEN HARMED * + ************************************************************/ + // Play wound animation and falling body part + BeWounded(EDamage eDamage) : CEnemyBase::BeWounded { + // spawn additional elemental + if( m_bSpawnEnabled) + { + SpawnNewElemental(); + } + jump CEnemyBase::BeWounded(eDamage); + }; + +/************************************************************ + * CHANGE STATE PROCEDURES * + ************************************************************/ + // box to normal + BoxToNormal(EVoid) { + m_EesCurrentState = ELS_NORMAL; + SetPhysicsFlags(EPF_MODEL_WALKING); + ChangeCollisionBoxIndexWhenPossible(STONEMAN_COLLISION_BOX_NORMAL); + PlaySound(m_soFireL, SOUND_LAVA_GROW, SOF_3D); + StartModelAnim(STONEMAN_ANIM_MORPHBOXUP, 0); + AddAttachments(); + autowait(GetModelObject()->GetAnimLength(STONEMAN_ANIM_MORPHBOXUP)); + return EReturn(); + }; + + // normal to box +/* NormalToBox(EVoid) { + StartModelAnim(STONEMAN_ANIM_MORPHBOXDOWN, 0); + autowait(GetModelObject()->GetAnimLength(STONEMAN_ANIM_MORPHBOXDOWN)); + m_EesCurrentState = ELS_BOX; + SetPhysicsFlags(EPF_BOX_PLANE_ELEMENTAL); + ChangeCollisionBoxIndexWhenPossible(STONEMAN_COLLISION_BOX_BOX); + RemoveAttachments(); + return EReturn(); + };*/ + + // plane to normal + PlaneToNormal(EVoid) { + m_EesCurrentState = ELS_NORMAL; + SwitchToModel(); + SetPhysicsFlags(EPF_MODEL_WALKING); + ChangeCollisionBoxIndexWhenPossible(ELEMENTALLAVA_COLLISION_BOX_NORMAL); + PlaySound(m_soFireL, SOUND_LAVA_GROW, SOF_3D); + INDEX iAnim; + if (m_EetType == ELT_LAVA) { + iAnim = ELEMENTALLAVA_ANIM_MELTUP; + } else { +// iAnim = STONEMAN_ANIM_MORPHPLANEUP; + } + StartModelAnim(iAnim, 0); + AddAttachments(); + autowait(GetModelObject()->GetAnimLength(iAnim)); + return EReturn(); + }; + +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + InitializeAttack(EVoid) : CEnemyBase::InitializeAttack { + // change state from box to normal + if (m_EesCurrentState==ELS_BOX) + { + autocall BoxToNormal() EReturn; + } + // change state from plane to normal + else if (m_EesCurrentState==ELS_PLANE) + { + autocall PlaneToNormal() EReturn; + } + jump CEnemyBase::InitializeAttack(); + }; + + Fire(EVoid) : CEnemyBase::Fire { + // fire projectile + switch (m_EetType) { +// case ELT_STONE: jump StonemanFire(); break; + case ELT_LAVA: jump LavamanFire(); break; +// case ELT_ICE: jump IcemanFire(); break; +// case ELT_AIR: jump AirmanFire(); break; +// case ELT_WATER: jump WatermanFire(); break; + } + return EReturn(); + }; + + Hit(EVoid) : CEnemyBase::Hit { + // hit ground + switch (m_EetType) { +// case ELT_STONE: jump StonemanHit(); break; + case ELT_LAVA: jump LavamanHit(); break; +// case ELT_ICE: jump IcemanHit(); break; +// case ELT_AIR: jump AirmanFire(); break; +// case ELT_WATER: jump WatermanFire(); break; + } + return EReturn(); + }; + +/************************************************************ + * D E A T H * + ************************************************************/ + Death(EVoid) : CEnemyBase::Death + { + if (m_bSpawnOnBlowUp && (m_EecChar==ELC_LARGE || m_EecChar==ELC_BIG)) { + SpawnNewElemental(); + SpawnNewElemental(); + } + // air fade out + if (m_EetType == ELT_AIR) { + m_fFadeStartTime = _pTimer->CurrentTick(); + m_bFadeOut = TRUE; + m_fFadeTime = 2.0f; + autowait(m_fFadeTime); + } + autocall CEnemyBase::Death() EEnd; + GetModelObject()->mo_toBump.SetData( NULL); + return EEnd(); + }; + + BossAppear(EVoid) + { + autowait(2.0f); + m_fFadeStartTime = _pTimer->CurrentTick(); + GetModelObject()->PlayAnim(ELEMENTALLAVA_ANIM_ANGER, 0); + PlaySound(m_soSound, SOUND_LAVA_ANGER, SOF_3D); + autowait(GetModelObject()->GetAnimLength(ELEMENTALLAVA_ANIM_ANGER)-_pTimer->TickQuantum); + + StartModelAnim(ELEMENTALLAVA_ANIM_ATTACKTWOHANDS, AOF_SMOOTHCHANGE); + autowait(0.7f); + HitGround(); + PlaySound(m_soFireL, SOUND_LAVA_KICK, SOF_3D); + autowait(GetModelObject()->GetAnimLength(ELEMENTALLAVA_ANIM_ATTACKTWOHANDS)-0.7f-_pTimer->TickQuantum); + + StartModelAnim(ELEMENTALLAVA_ANIM_ATTACKTWOHANDS, 0); + autowait(0.6f); + HitGround(); + PlaySound(m_soFireR, SOUND_LAVA_KICK, SOF_3D); + autowait(GetModelObject()->GetAnimLength(ELEMENTALLAVA_ANIM_ATTACKTWOHANDS)-0.6f-_pTimer->TickQuantum); + + + return EReturn(); + } + + // overridable called before main enemy loop actually begins + PreMainLoop(EVoid) : CEnemyBase::PreMainLoop + { + // if spawned by other entity + if (m_bSpawned) { + m_bSpawned = FALSE; + m_bCountAsKill = FALSE; + // wait till touching the ground + autocall FallOnFloor() EReturn; + } + + if (m_EecChar==ELC_LARGE || m_EecChar==ELC_BIG && m_EetType==ELT_LAVA) + { + PlaySound(m_soBackground, SOUND_LAVA_LAVABURN, SOF_3D|SOF_LOOP); + } + + if( m_EecChar==ELC_LARGE) + { + autocall BossAppear() EReturn; + } + return EReturn(); + } + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + if (m_EetType!=ELT_LAVA) { + m_EetType=ELT_LAVA; + } + // declare yourself as a model + InitAsModel(); + // movable + if (m_bMovable) { + SetPhysicsFlags(EPF_MODEL_WALKING); + // non movable + } else { + SetPhysicsFlags(EPF_MODEL_IMMATERIAL|EPF_MOVABLE); + } + // air elemental + if (m_EetType==ELT_AIR) { + SetCollisionFlags(ECF_AIR); + // solid elemental + } else { + SetCollisionFlags(ECF_MODEL); + } + SetFlags(GetFlags()|ENF_ALIVE); + en_fDensity = m_fDensity; + m_fSpawnDamage = 1e6f; + m_fDamageWounded = 1e6f; + m_bSpawnEnabled = FALSE; + m_bBoss = FALSE; + + // set your appearance + switch (m_EetType) { +/* case ELT_AIR: + SetComponents(this, *GetModelObject(), MODEL_AIR, TEXTURE_AIR, 0, 0, 0); + break; + case ELT_ICE: + SetComponents(this, *GetModelObject(), MODEL_ICE, TEXTURE_ICE, TEXTURE_ICE, TEX_SPEC_STRONG, 0); + break;*/ + case ELT_LAVA: + m_fBlowUpAmount = 1E30f; + SetComponents(this, *GetModelObject(), MODEL_LAVA, TEXTURE_LAVA, 0, 0, TEXTURE_LAVA_DETAIL); + break; +/* case ELT_STONE: + SetComponents(this, *GetModelObject(), MODEL_STONE, TEXTURE_STONE, 0, 0, 0); + break; + case ELT_WATER: + SetComponents(this, *GetModelObject(), MODEL_WATER, TEXTURE_WATER, TEXTURE_WATER, TEX_SPEC_STRONG, 0); + break;*/ + } + ModelChangeNotify(); + + // character settings + if (m_EecChar==ELC_LARGE) + { + // this one is boss! + m_sptType = SPT_SMALL_LAVA_STONES; + m_bBoss = TRUE; + SetHealth(10000.0f); + m_fMaxHealth = 10000.0f; + // after loosing this ammount of damage we will spawn new elemental + m_fSpawnDamage = 2000.0f; + // setup moving speed + m_fWalkSpeed = FRnd()/2 + 1.0f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 25.0f); + m_fAttackRunSpeed = FRnd() + 2.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + m_fCloseRunSpeed = FRnd() + 2.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + // setup attack distances + m_fAttackDistance = 300.0f; + m_fCloseDistance = 60.0f; + m_fStopDistance = 30.0f; + m_fAttackFireTime = 0.5f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 600.0f; + m_iScore = 50000; + } + else if (m_EecChar==ELC_BIG) + { + m_sptType = SPT_LAVA_STONES; + SetHealth(800.0f); + m_fMaxHealth = 800.0f; + // after loosing this ammount of damage we will spawn new elemental + m_fSpawnDamage = 500.0f; + // setup moving speed + m_fWalkSpeed = FRnd() + 1.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 25.0f); + m_fAttackRunSpeed = FRnd()*1.0f + 6.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 300.0f); + m_fCloseRunSpeed = FRnd()*2.0f + 2.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 300.0f); + // setup attack distances + m_fAttackDistance = 150.0f; + m_fCloseDistance = 20.0f; + m_fStopDistance = 5.0f; + m_fAttackFireTime = 0.5f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 400.0f; + // damage/explode properties + m_iScore = 2500; + } + else + { + m_sptType = SPT_LAVA_STONES; + SetHealth(100.0f); + m_fMaxHealth = 100.0f; + // setup moving speed + m_fWalkSpeed = FRnd() + 1.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 25.0f); + m_fAttackRunSpeed = FRnd()*2.0f + 6.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 500.0f); + m_fCloseRunSpeed = FRnd()*3.0f + 4.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 500.0f); + // setup attack distances + m_fAttackDistance = 100.0f; + m_fCloseDistance = 10.0f; + m_fStopDistance = 5.0f; + m_fAttackFireTime = 1.5f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 200.0f; + // damage/explode properties + m_iScore = 500; + } + + // non movable + if (!m_bMovable) + { + m_EesStartState = ELS_NORMAL; + m_bSpawnWhenHarmed = FALSE; + m_bSpawnOnBlowUp = FALSE; + // fire count + if (m_iFireCount <= 0) + { + WarningMessage("Entity: %s - Fire count must be greater than zero", GetName()); + m_iFireCount = 1; + } + } + + // state and flare attachments + m_EesCurrentState = m_EesStartState; + RemoveAttachments(); + switch (m_EesCurrentState) { + case ELS_NORMAL: + SetPhysicsFlags(EPF_MODEL_WALKING); + AddAttachments(); + break; + case ELS_BOX: + SetPhysicsFlags(EPF_BOX_PLANE_ELEMENTAL); + break; + case ELS_PLANE: + SetPhysicsFlags(EPF_MODEL_IMMATERIAL|EPF_MOVABLE); + SwitchToEditorModel(); + break; + } + StandingAnim(); + + // stretch + if (m_EecChar==ELC_SMALL) { + GetModelObject()->StretchModel(FLOAT3D(LAVAMAN_SMALL_STRETCH, LAVAMAN_SMALL_STRETCH, LAVAMAN_SMALL_STRETCH)); + } + else if (m_EecChar==ELC_LARGE) { + GetModelObject()->StretchModel(FLOAT3D(LAVAMAN_LARGE_STRETCH, LAVAMAN_LARGE_STRETCH, LAVAMAN_LARGE_STRETCH)); + } else if (m_EecChar==ELC_BIG) { + GetModelObject()->StretchModel(FLOAT3D(LAVAMAN_BIG_STRETCH, LAVAMAN_BIG_STRETCH, LAVAMAN_BIG_STRETCH)); + } + ModelChangeNotify(); + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Elemental.h b/Sources/EntitiesMP/Elemental.h new file mode 100644 index 0000000..b04151e --- /dev/null +++ b/Sources/EntitiesMP/Elemental.h @@ -0,0 +1,275 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Elemental_INCLUDED +#define _EntitiesMP_Elemental_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType ElementalType_enum; +enum ElementalType { + ELT_AIR = 0, + ELT_ICE = 1, + ELT_LAVA = 2, + ELT_STONE = 3, + ELT_WATER = 4, +}; +DECL_DLL inline void ClearToDefault(ElementalType &e) { e = (ElementalType)0; } ; +extern DECL_DLL CEntityPropertyEnumType ElementalCharacter_enum; +enum ElementalCharacter { + ELC_SMALL = 0, + ELC_BIG = 1, + ELC_LARGE = 2, +}; +DECL_DLL inline void ClearToDefault(ElementalCharacter &e) { e = (ElementalCharacter)0; } ; +extern DECL_DLL CEntityPropertyEnumType ElementalState_enum; +enum ElementalState { + ELS_NORMAL = 0, + ELS_BOX = 1, + ELS_PLANE = 2, +}; +DECL_DLL inline void ClearToDefault(ElementalState &e) { e = (ElementalState)0; } ; +extern "C" DECL_DLL CDLLEntityClass CElemental_DLLClass; +class CElemental : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum ElementalType m_EetType; + enum ElementalCharacter m_EecChar; + enum ElementalState m_EesStartState; + BOOL m_bSpawnWhenHarmed; + BOOL m_bSpawnOnBlowUp; + enum ElementalState m_EesCurrentState; + BOOL m_bSpawned; + BOOL m_bMovable; + RANGE m_fLookRange; + INDEX m_iFireCount; + FLOAT m_fWaitTime; + INDEX m_iCounter; + FLOAT m_fDensity; + CEntityPointer m_penPosition1; + CEntityPointer m_penPosition2; + CEntityPointer m_penPosition3; + CEntityPointer m_penPosition4; + CEntityPointer m_penPosition5; + CEntityPointer m_penPosition6; + CSoundObject m_soBackground; + INDEX m_ctSpawned; + FLOAT m_fSpawnDamage; + BOOL m_bSpawnEnabled; + CSoundObject m_soFireL; + CSoundObject m_soFireR; + INDEX m_bCountAsKill; + +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void RenderParticles(void); + +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void Precache(void); + +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void * GetEntityInfo(void); + +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void LeaveStain(BOOL bGrow); + +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void StandingAnimFight(void); + +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void StandingAnim(void); + +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void WalkingAnim(void); + +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void RunningAnim(void); + +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void RotatingAnim(void); + +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +INDEX AnimForDeath(void); + +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void IdleSound(void); + +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void SightSound(void); + +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void WoundSound(void); + +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void DeathSound(void); + +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BOOL CountAsKill(void); + +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void SpawnNewElemental(void); + +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void ThrowRocks(ProjectileType EptProjectile); + +#line 650 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void BossFirePredictedLavaRock(FLOAT3D vFireingRel); + +#line 681 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void ShakeItBaby(FLOAT tmShaketime,FLOAT fPower); + +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void SpawnShockwave(FLOAT fSize); + +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void HitGround(void); + +#line 788 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void AddAttachments(void); + +#line 828 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void RemoveAttachments(void); + +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void BlowUp(void); + +#line 918 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +void EnemyPostInit(void); +#define STATE_CElemental_FallOnFloor 0x01420000 + BOOL +#line 940 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FallOnFloor(const CEntityEvent &__eeInput); + BOOL H0x01420001_FallOnFloor_01(const CEntityEvent &__eeInput); + BOOL H0x01420002_FallOnFloor_02(const CEntityEvent &__eeInput); +#define STATE_CElemental_LavamanFire 0x01420003 + BOOL +#line 1006 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +LavamanFire(const CEntityEvent &__eeInput); + BOOL H0x01420004_LavamanFire_01(const CEntityEvent &__eeInput); + BOOL H0x01420005_LavamanFire_02(const CEntityEvent &__eeInput); + BOOL H0x01420006_LavamanFire_03(const CEntityEvent &__eeInput); + BOOL H0x01420007_LavamanFire_04(const CEntityEvent &__eeInput); + BOOL H0x01420008_LavamanFire_05(const CEntityEvent &__eeInput); + BOOL H0x01420009_LavamanFire_06(const CEntityEvent &__eeInput); + BOOL H0x0142000a_LavamanFire_07(const CEntityEvent &__eeInput); + BOOL H0x0142000b_LavamanFire_08(const CEntityEvent &__eeInput); + BOOL H0x0142000c_LavamanFire_09(const CEntityEvent &__eeInput); + BOOL H0x0142000d_LavamanFire_10(const CEntityEvent &__eeInput); + BOOL H0x0142000e_LavamanFire_11(const CEntityEvent &__eeInput); + BOOL H0x0142000f_LavamanFire_12(const CEntityEvent &__eeInput); + BOOL H0x01420010_LavamanFire_13(const CEntityEvent &__eeInput); + BOOL H0x01420011_LavamanFire_14(const CEntityEvent &__eeInput); + BOOL H0x01420012_LavamanFire_15(const CEntityEvent &__eeInput); + BOOL H0x01420013_LavamanFire_16(const CEntityEvent &__eeInput); + BOOL H0x01420014_LavamanFire_17(const CEntityEvent &__eeInput); + BOOL H0x01420015_LavamanFire_18(const CEntityEvent &__eeInput); + BOOL H0x01420016_LavamanFire_19(const CEntityEvent &__eeInput); +#define STATE_CElemental_LavamanStones 0x01420017 + BOOL +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +LavamanStones(const CEntityEvent &__eeInput); + BOOL H0x01420018_LavamanStones_01(const CEntityEvent &__eeInput); + BOOL H0x01420019_LavamanStones_02(const CEntityEvent &__eeInput); + BOOL H0x0142001a_LavamanStones_03(const CEntityEvent &__eeInput); + BOOL H0x0142001b_LavamanStones_04(const CEntityEvent &__eeInput); + BOOL H0x0142001c_LavamanStones_05(const CEntityEvent &__eeInput); + BOOL H0x0142001d_LavamanStones_06(const CEntityEvent &__eeInput); +#define STATE_CElemental_LavamanHit 0x0142001e + BOOL +#line 1106 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +LavamanHit(const CEntityEvent &__eeInput); + BOOL H0x0142001f_LavamanHit_01(const CEntityEvent &__eeInput); + BOOL H0x01420020_LavamanHit_02(const CEntityEvent &__eeInput); + BOOL H0x01420021_LavamanHit_03(const CEntityEvent &__eeInput); + BOOL H0x01420022_LavamanHit_04(const CEntityEvent &__eeInput); +#define STATE_CElemental_BeWounded 0x01420023 + BOOL +#line 1209 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BeWounded(const CEntityEvent &__eeInput); +#define STATE_CElemental_BoxToNormal 0x01420024 + BOOL +#line 1222 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BoxToNormal(const CEntityEvent &__eeInput); + BOOL H0x01420025_BoxToNormal_01(const CEntityEvent &__eeInput); + BOOL H0x01420026_BoxToNormal_02(const CEntityEvent &__eeInput); +#define STATE_CElemental_PlaneToNormal 0x01420027 + BOOL +#line 1245 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaneToNormal(const CEntityEvent &__eeInput); + BOOL H0x01420028_PlaneToNormal_01(const CEntityEvent &__eeInput); + BOOL H0x01420029_PlaneToNormal_02(const CEntityEvent &__eeInput); +#define STATE_CElemental_InitializeAttack 0x0142002a + BOOL +#line 1266 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +InitializeAttack(const CEntityEvent &__eeInput); + BOOL H0x0142002b_InitializeAttack_01(const CEntityEvent &__eeInput); + BOOL H0x0142002c_InitializeAttack_02(const CEntityEvent &__eeInput); + BOOL H0x0142002d_InitializeAttack_03(const CEntityEvent &__eeInput); + BOOL H0x0142002e_InitializeAttack_04(const CEntityEvent &__eeInput); + BOOL H0x0142002f_InitializeAttack_05(const CEntityEvent &__eeInput); + BOOL H0x01420030_InitializeAttack_06(const CEntityEvent &__eeInput); + BOOL H0x01420031_InitializeAttack_07(const CEntityEvent &__eeInput); +#define STATE_CElemental_Fire 0x01420032 + BOOL +#line 1280 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Fire(const CEntityEvent &__eeInput); +#define STATE_CElemental_Hit 0x01420033 + BOOL +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Hit(const CEntityEvent &__eeInput); +#define STATE_CElemental_Death 0x01420034 + BOOL +#line 1307 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Death(const CEntityEvent &__eeInput); + BOOL H0x01420035_Death_01(const CEntityEvent &__eeInput); + BOOL H0x01420036_Death_02(const CEntityEvent &__eeInput); + BOOL H0x01420037_Death_03(const CEntityEvent &__eeInput); + BOOL H0x01420038_Death_04(const CEntityEvent &__eeInput); + BOOL H0x01420039_Death_05(const CEntityEvent &__eeInput); +#define STATE_CElemental_BossAppear 0x0142003a + BOOL +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BossAppear(const CEntityEvent &__eeInput); + BOOL H0x0142003b_BossAppear_01(const CEntityEvent &__eeInput); + BOOL H0x0142003c_BossAppear_02(const CEntityEvent &__eeInput); + BOOL H0x0142003d_BossAppear_03(const CEntityEvent &__eeInput); + BOOL H0x0142003e_BossAppear_04(const CEntityEvent &__eeInput); + BOOL H0x0142003f_BossAppear_05(const CEntityEvent &__eeInput); + BOOL H0x01420040_BossAppear_06(const CEntityEvent &__eeInput); + BOOL H0x01420041_BossAppear_07(const CEntityEvent &__eeInput); + BOOL H0x01420042_BossAppear_08(const CEntityEvent &__eeInput); + BOOL H0x01420043_BossAppear_09(const CEntityEvent &__eeInput); + BOOL H0x01420044_BossAppear_10(const CEntityEvent &__eeInput); + BOOL H0x01420045_BossAppear_11(const CEntityEvent &__eeInput); + BOOL H0x01420046_BossAppear_12(const CEntityEvent &__eeInput); +#define STATE_CElemental_PreMainLoop 0x01420047 + BOOL +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PreMainLoop(const CEntityEvent &__eeInput); + BOOL H0x01420048_PreMainLoop_01(const CEntityEvent &__eeInput); + BOOL H0x01420049_PreMainLoop_02(const CEntityEvent &__eeInput); + BOOL H0x0142004a_PreMainLoop_03(const CEntityEvent &__eeInput); + BOOL H0x0142004b_PreMainLoop_04(const CEntityEvent &__eeInput); + BOOL H0x0142004c_PreMainLoop_05(const CEntityEvent &__eeInput); + BOOL H0x0142004d_PreMainLoop_06(const CEntityEvent &__eeInput); +#define STATE_CElemental_Main 1 + BOOL +#line 1375 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Elemental_INCLUDED diff --git a/Sources/EntitiesMP/Elemental_tables.h b/Sources/EntitiesMP/Elemental_tables.h new file mode 100644 index 0000000..5880415 --- /dev/null +++ b/Sources/EntitiesMP/Elemental_tables.h @@ -0,0 +1,221 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(ElementalType) + EP_ENUMVALUE(ELT_AIR, "obsolete"), + EP_ENUMVALUE(ELT_ICE, "obsolete"), + EP_ENUMVALUE(ELT_LAVA, "Lava"), + EP_ENUMVALUE(ELT_STONE, "obsolete"), + EP_ENUMVALUE(ELT_WATER, "obsolete"), +EP_ENUMEND(ElementalType); + +EP_ENUMBEG(ElementalCharacter) + EP_ENUMVALUE(ELC_SMALL, "Small"), + EP_ENUMVALUE(ELC_BIG, "Big"), + EP_ENUMVALUE(ELC_LARGE, "Large"), +EP_ENUMEND(ElementalCharacter); + +EP_ENUMBEG(ElementalState) + EP_ENUMVALUE(ELS_NORMAL, "Normal"), + EP_ENUMVALUE(ELS_BOX, "Box"), + EP_ENUMVALUE(ELS_PLANE, "Plane"), +EP_ENUMEND(ElementalState); + +#define ENTITYCLASS CElemental + +CEntityProperty CElemental_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &ElementalType_enum, (0x00000142<<8)+1, offsetof(CElemental, m_EetType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &ElementalCharacter_enum, (0x00000142<<8)+2, offsetof(CElemental, m_EecChar), "Character", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &ElementalState_enum, (0x00000142<<8)+3, offsetof(CElemental, m_EesStartState), "State", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000142<<8)+4, offsetof(CElemental, m_bSpawnWhenHarmed), "Damage spawn", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000142<<8)+5, offsetof(CElemental, m_bSpawnOnBlowUp), "Blowup spawn", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &ElementalState_enum, (0x00000142<<8)+6, offsetof(CElemental, m_EesCurrentState), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000142<<8)+7, offsetof(CElemental, m_bSpawned), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000142<<8)+8, offsetof(CElemental, m_bMovable), "Movable", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000142<<8)+9, offsetof(CElemental, m_fLookRange), "Look range", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000142<<8)+10, offsetof(CElemental, m_iFireCount), "Fire count", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000142<<8)+11, offsetof(CElemental, m_fWaitTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000142<<8)+12, offsetof(CElemental, m_iCounter), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000142<<8)+13, offsetof(CElemental, m_fDensity), "Density", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000142<<8)+20, offsetof(CElemental, m_penPosition1), "Position 1", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000142<<8)+21, offsetof(CElemental, m_penPosition2), "Position 2", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000142<<8)+22, offsetof(CElemental, m_penPosition3), "Position 3", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000142<<8)+23, offsetof(CElemental, m_penPosition4), "Position 4", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000142<<8)+24, offsetof(CElemental, m_penPosition5), "Position 5", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000142<<8)+25, offsetof(CElemental, m_penPosition6), "Position 6", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000142<<8)+30, offsetof(CElemental, m_soBackground), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000142<<8)+31, offsetof(CElemental, m_ctSpawned), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000142<<8)+32, offsetof(CElemental, m_fSpawnDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000142<<8)+33, offsetof(CElemental, m_bSpawnEnabled), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000142<<8)+34, offsetof(CElemental, m_soFireL), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000142<<8)+35, offsetof(CElemental, m_soFireR), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000142<<8)+36, offsetof(CElemental, m_bCountAsKill), "", 0, 0, 0), +}; +#define CElemental_propertiesct ARRAYCOUNT(CElemental_properties) + +CEntityComponent CElemental_components[] = { +#define CLASS_BASE ((0x00000142<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_TWISTER ((0x00000142<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_TWISTER, "EFNM" "Classes\\Twister.ecl"), +#define CLASS_WATER ((0x00000142<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_WATER, "EFNM" "Classes\\Water.ecl"), +#define CLASS_PROJECTILE ((0x00000142<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_BLOOD_SPRAY ((0x00000142<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000142<<8)+5) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define MODEL_LAVA ((0x00000142<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_LAVA, "EFNM" "Models\\Enemies\\ElementalLava\\ElementalLava.mdl"), +#define MODEL_LAVA_BODY_FLARE ((0x00000142<<8)+31) + CEntityComponent(ECT_MODEL, MODEL_LAVA_BODY_FLARE, "EFNM" "Models\\Enemies\\ElementalLava\\BodyFlare.mdl"), +#define MODEL_LAVA_HAND_FLARE ((0x00000142<<8)+32) + CEntityComponent(ECT_MODEL, MODEL_LAVA_HAND_FLARE, "EFNM" "Models\\Enemies\\ElementalLava\\HandFlare.mdl"), +#define TEXTURE_LAVA ((0x00000142<<8)+33) + CEntityComponent(ECT_TEXTURE, TEXTURE_LAVA, "EFNM" "Models\\Enemies\\ElementalLava\\Lava04Fx.tex"), +#define TEXTURE_LAVA_DETAIL ((0x00000142<<8)+34) + CEntityComponent(ECT_TEXTURE, TEXTURE_LAVA_DETAIL, "EFNM" "Models\\Enemies\\ElementalLava\\Detail.tex"), +#define TEXTURE_LAVA_FLARE ((0x00000142<<8)+35) + CEntityComponent(ECT_TEXTURE, TEXTURE_LAVA_FLARE, "EFNM" "Models\\Enemies\\ElementalLava\\Flare.tex"), +#define SOUND_LAVA_IDLE ((0x00000142<<8)+250) + CEntityComponent(ECT_SOUND, SOUND_LAVA_IDLE, "EFNM" "Models\\Enemies\\ElementalLava\\Sounds\\Idle.wav"), +#define SOUND_LAVA_WOUND ((0x00000142<<8)+252) + CEntityComponent(ECT_SOUND, SOUND_LAVA_WOUND, "EFNM" "Models\\Enemies\\ElementalLava\\Sounds\\Wound.wav"), +#define SOUND_LAVA_FIRE ((0x00000142<<8)+253) + CEntityComponent(ECT_SOUND, SOUND_LAVA_FIRE, "EFNM" "Models\\Enemies\\ElementalLava\\Sounds\\Fire.wav"), +#define SOUND_LAVA_KICK ((0x00000142<<8)+254) + CEntityComponent(ECT_SOUND, SOUND_LAVA_KICK, "EFNM" "Models\\Enemies\\ElementalLava\\Sounds\\Kick.wav"), +#define SOUND_LAVA_DEATH ((0x00000142<<8)+255) + CEntityComponent(ECT_SOUND, SOUND_LAVA_DEATH, "EFNM" "Models\\Enemies\\ElementalLava\\Sounds\\Death.wav"), +#define SOUND_LAVA_LAVABURN ((0x00000142<<8)+220) + CEntityComponent(ECT_SOUND, SOUND_LAVA_LAVABURN, "EFNM" "Models\\Enemies\\ElementalLava\\Sounds\\LavaBurn.wav"), +#define SOUND_LAVA_ANGER ((0x00000142<<8)+221) + CEntityComponent(ECT_SOUND, SOUND_LAVA_ANGER, "EFNM" "Models\\Enemies\\ElementalLava\\Sounds\\Anger.wav"), +#define SOUND_LAVA_GROW ((0x00000142<<8)+222) + CEntityComponent(ECT_SOUND, SOUND_LAVA_GROW, "EFNM" "ModelsMP\\Enemies\\ElementalLava\\Sounds\\Grow.wav"), +}; +#define CElemental_componentsct ARRAYCOUNT(CElemental_components) + +CEventHandlerEntry CElemental_handlers[] = { + {0x01420000, -1, CEntity::pEventHandler(&CElemental:: +#line 940 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +FallOnFloor),DEBUGSTRING("CElemental::FallOnFloor")}, + {0x01420001, -1, CEntity::pEventHandler(&CElemental::H0x01420001_FallOnFloor_01), DEBUGSTRING("CElemental::H0x01420001_FallOnFloor_01")}, + {0x01420002, -1, CEntity::pEventHandler(&CElemental::H0x01420002_FallOnFloor_02), DEBUGSTRING("CElemental::H0x01420002_FallOnFloor_02")}, + {0x01420003, -1, CEntity::pEventHandler(&CElemental:: +#line 1006 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +LavamanFire),DEBUGSTRING("CElemental::LavamanFire")}, + {0x01420004, -1, CEntity::pEventHandler(&CElemental::H0x01420004_LavamanFire_01), DEBUGSTRING("CElemental::H0x01420004_LavamanFire_01")}, + {0x01420005, -1, CEntity::pEventHandler(&CElemental::H0x01420005_LavamanFire_02), DEBUGSTRING("CElemental::H0x01420005_LavamanFire_02")}, + {0x01420006, -1, CEntity::pEventHandler(&CElemental::H0x01420006_LavamanFire_03), DEBUGSTRING("CElemental::H0x01420006_LavamanFire_03")}, + {0x01420007, -1, CEntity::pEventHandler(&CElemental::H0x01420007_LavamanFire_04), DEBUGSTRING("CElemental::H0x01420007_LavamanFire_04")}, + {0x01420008, -1, CEntity::pEventHandler(&CElemental::H0x01420008_LavamanFire_05), DEBUGSTRING("CElemental::H0x01420008_LavamanFire_05")}, + {0x01420009, -1, CEntity::pEventHandler(&CElemental::H0x01420009_LavamanFire_06), DEBUGSTRING("CElemental::H0x01420009_LavamanFire_06")}, + {0x0142000a, -1, CEntity::pEventHandler(&CElemental::H0x0142000a_LavamanFire_07), DEBUGSTRING("CElemental::H0x0142000a_LavamanFire_07")}, + {0x0142000b, -1, CEntity::pEventHandler(&CElemental::H0x0142000b_LavamanFire_08), DEBUGSTRING("CElemental::H0x0142000b_LavamanFire_08")}, + {0x0142000c, -1, CEntity::pEventHandler(&CElemental::H0x0142000c_LavamanFire_09), DEBUGSTRING("CElemental::H0x0142000c_LavamanFire_09")}, + {0x0142000d, -1, CEntity::pEventHandler(&CElemental::H0x0142000d_LavamanFire_10), DEBUGSTRING("CElemental::H0x0142000d_LavamanFire_10")}, + {0x0142000e, -1, CEntity::pEventHandler(&CElemental::H0x0142000e_LavamanFire_11), DEBUGSTRING("CElemental::H0x0142000e_LavamanFire_11")}, + {0x0142000f, -1, CEntity::pEventHandler(&CElemental::H0x0142000f_LavamanFire_12), DEBUGSTRING("CElemental::H0x0142000f_LavamanFire_12")}, + {0x01420010, -1, CEntity::pEventHandler(&CElemental::H0x01420010_LavamanFire_13), DEBUGSTRING("CElemental::H0x01420010_LavamanFire_13")}, + {0x01420011, -1, CEntity::pEventHandler(&CElemental::H0x01420011_LavamanFire_14), DEBUGSTRING("CElemental::H0x01420011_LavamanFire_14")}, + {0x01420012, -1, CEntity::pEventHandler(&CElemental::H0x01420012_LavamanFire_15), DEBUGSTRING("CElemental::H0x01420012_LavamanFire_15")}, + {0x01420013, -1, CEntity::pEventHandler(&CElemental::H0x01420013_LavamanFire_16), DEBUGSTRING("CElemental::H0x01420013_LavamanFire_16")}, + {0x01420014, -1, CEntity::pEventHandler(&CElemental::H0x01420014_LavamanFire_17), DEBUGSTRING("CElemental::H0x01420014_LavamanFire_17")}, + {0x01420015, -1, CEntity::pEventHandler(&CElemental::H0x01420015_LavamanFire_18), DEBUGSTRING("CElemental::H0x01420015_LavamanFire_18")}, + {0x01420016, -1, CEntity::pEventHandler(&CElemental::H0x01420016_LavamanFire_19), DEBUGSTRING("CElemental::H0x01420016_LavamanFire_19")}, + {0x01420017, -1, CEntity::pEventHandler(&CElemental:: +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +LavamanStones),DEBUGSTRING("CElemental::LavamanStones")}, + {0x01420018, -1, CEntity::pEventHandler(&CElemental::H0x01420018_LavamanStones_01), DEBUGSTRING("CElemental::H0x01420018_LavamanStones_01")}, + {0x01420019, -1, CEntity::pEventHandler(&CElemental::H0x01420019_LavamanStones_02), DEBUGSTRING("CElemental::H0x01420019_LavamanStones_02")}, + {0x0142001a, -1, CEntity::pEventHandler(&CElemental::H0x0142001a_LavamanStones_03), DEBUGSTRING("CElemental::H0x0142001a_LavamanStones_03")}, + {0x0142001b, -1, CEntity::pEventHandler(&CElemental::H0x0142001b_LavamanStones_04), DEBUGSTRING("CElemental::H0x0142001b_LavamanStones_04")}, + {0x0142001c, -1, CEntity::pEventHandler(&CElemental::H0x0142001c_LavamanStones_05), DEBUGSTRING("CElemental::H0x0142001c_LavamanStones_05")}, + {0x0142001d, -1, CEntity::pEventHandler(&CElemental::H0x0142001d_LavamanStones_06), DEBUGSTRING("CElemental::H0x0142001d_LavamanStones_06")}, + {0x0142001e, -1, CEntity::pEventHandler(&CElemental:: +#line 1106 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +LavamanHit),DEBUGSTRING("CElemental::LavamanHit")}, + {0x0142001f, -1, CEntity::pEventHandler(&CElemental::H0x0142001f_LavamanHit_01), DEBUGSTRING("CElemental::H0x0142001f_LavamanHit_01")}, + {0x01420020, -1, CEntity::pEventHandler(&CElemental::H0x01420020_LavamanHit_02), DEBUGSTRING("CElemental::H0x01420020_LavamanHit_02")}, + {0x01420021, -1, CEntity::pEventHandler(&CElemental::H0x01420021_LavamanHit_03), DEBUGSTRING("CElemental::H0x01420021_LavamanHit_03")}, + {0x01420022, -1, CEntity::pEventHandler(&CElemental::H0x01420022_LavamanHit_04), DEBUGSTRING("CElemental::H0x01420022_LavamanHit_04")}, + {0x01420023, STATE_CEnemyBase_BeWounded, CEntity::pEventHandler(&CElemental:: +#line 1209 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BeWounded),DEBUGSTRING("CElemental::BeWounded")}, + {0x01420024, -1, CEntity::pEventHandler(&CElemental:: +#line 1222 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BoxToNormal),DEBUGSTRING("CElemental::BoxToNormal")}, + {0x01420025, -1, CEntity::pEventHandler(&CElemental::H0x01420025_BoxToNormal_01), DEBUGSTRING("CElemental::H0x01420025_BoxToNormal_01")}, + {0x01420026, -1, CEntity::pEventHandler(&CElemental::H0x01420026_BoxToNormal_02), DEBUGSTRING("CElemental::H0x01420026_BoxToNormal_02")}, + {0x01420027, -1, CEntity::pEventHandler(&CElemental:: +#line 1245 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PlaneToNormal),DEBUGSTRING("CElemental::PlaneToNormal")}, + {0x01420028, -1, CEntity::pEventHandler(&CElemental::H0x01420028_PlaneToNormal_01), DEBUGSTRING("CElemental::H0x01420028_PlaneToNormal_01")}, + {0x01420029, -1, CEntity::pEventHandler(&CElemental::H0x01420029_PlaneToNormal_02), DEBUGSTRING("CElemental::H0x01420029_PlaneToNormal_02")}, + {0x0142002a, STATE_CEnemyBase_InitializeAttack, CEntity::pEventHandler(&CElemental:: +#line 1266 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +InitializeAttack),DEBUGSTRING("CElemental::InitializeAttack")}, + {0x0142002b, -1, CEntity::pEventHandler(&CElemental::H0x0142002b_InitializeAttack_01), DEBUGSTRING("CElemental::H0x0142002b_InitializeAttack_01")}, + {0x0142002c, -1, CEntity::pEventHandler(&CElemental::H0x0142002c_InitializeAttack_02), DEBUGSTRING("CElemental::H0x0142002c_InitializeAttack_02")}, + {0x0142002d, -1, CEntity::pEventHandler(&CElemental::H0x0142002d_InitializeAttack_03), DEBUGSTRING("CElemental::H0x0142002d_InitializeAttack_03")}, + {0x0142002e, -1, CEntity::pEventHandler(&CElemental::H0x0142002e_InitializeAttack_04), DEBUGSTRING("CElemental::H0x0142002e_InitializeAttack_04")}, + {0x0142002f, -1, CEntity::pEventHandler(&CElemental::H0x0142002f_InitializeAttack_05), DEBUGSTRING("CElemental::H0x0142002f_InitializeAttack_05")}, + {0x01420030, -1, CEntity::pEventHandler(&CElemental::H0x01420030_InitializeAttack_06), DEBUGSTRING("CElemental::H0x01420030_InitializeAttack_06")}, + {0x01420031, -1, CEntity::pEventHandler(&CElemental::H0x01420031_InitializeAttack_07), DEBUGSTRING("CElemental::H0x01420031_InitializeAttack_07")}, + {0x01420032, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CElemental:: +#line 1280 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Fire),DEBUGSTRING("CElemental::Fire")}, + {0x01420033, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CElemental:: +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Hit),DEBUGSTRING("CElemental::Hit")}, + {0x01420034, STATE_CEnemyBase_Death, CEntity::pEventHandler(&CElemental:: +#line 1307 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Death),DEBUGSTRING("CElemental::Death")}, + {0x01420035, -1, CEntity::pEventHandler(&CElemental::H0x01420035_Death_01), DEBUGSTRING("CElemental::H0x01420035_Death_01")}, + {0x01420036, -1, CEntity::pEventHandler(&CElemental::H0x01420036_Death_02), DEBUGSTRING("CElemental::H0x01420036_Death_02")}, + {0x01420037, -1, CEntity::pEventHandler(&CElemental::H0x01420037_Death_03), DEBUGSTRING("CElemental::H0x01420037_Death_03")}, + {0x01420038, -1, CEntity::pEventHandler(&CElemental::H0x01420038_Death_04), DEBUGSTRING("CElemental::H0x01420038_Death_04")}, + {0x01420039, -1, CEntity::pEventHandler(&CElemental::H0x01420039_Death_05), DEBUGSTRING("CElemental::H0x01420039_Death_05")}, + {0x0142003a, -1, CEntity::pEventHandler(&CElemental:: +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +BossAppear),DEBUGSTRING("CElemental::BossAppear")}, + {0x0142003b, -1, CEntity::pEventHandler(&CElemental::H0x0142003b_BossAppear_01), DEBUGSTRING("CElemental::H0x0142003b_BossAppear_01")}, + {0x0142003c, -1, CEntity::pEventHandler(&CElemental::H0x0142003c_BossAppear_02), DEBUGSTRING("CElemental::H0x0142003c_BossAppear_02")}, + {0x0142003d, -1, CEntity::pEventHandler(&CElemental::H0x0142003d_BossAppear_03), DEBUGSTRING("CElemental::H0x0142003d_BossAppear_03")}, + {0x0142003e, -1, CEntity::pEventHandler(&CElemental::H0x0142003e_BossAppear_04), DEBUGSTRING("CElemental::H0x0142003e_BossAppear_04")}, + {0x0142003f, -1, CEntity::pEventHandler(&CElemental::H0x0142003f_BossAppear_05), DEBUGSTRING("CElemental::H0x0142003f_BossAppear_05")}, + {0x01420040, -1, CEntity::pEventHandler(&CElemental::H0x01420040_BossAppear_06), DEBUGSTRING("CElemental::H0x01420040_BossAppear_06")}, + {0x01420041, -1, CEntity::pEventHandler(&CElemental::H0x01420041_BossAppear_07), DEBUGSTRING("CElemental::H0x01420041_BossAppear_07")}, + {0x01420042, -1, CEntity::pEventHandler(&CElemental::H0x01420042_BossAppear_08), DEBUGSTRING("CElemental::H0x01420042_BossAppear_08")}, + {0x01420043, -1, CEntity::pEventHandler(&CElemental::H0x01420043_BossAppear_09), DEBUGSTRING("CElemental::H0x01420043_BossAppear_09")}, + {0x01420044, -1, CEntity::pEventHandler(&CElemental::H0x01420044_BossAppear_10), DEBUGSTRING("CElemental::H0x01420044_BossAppear_10")}, + {0x01420045, -1, CEntity::pEventHandler(&CElemental::H0x01420045_BossAppear_11), DEBUGSTRING("CElemental::H0x01420045_BossAppear_11")}, + {0x01420046, -1, CEntity::pEventHandler(&CElemental::H0x01420046_BossAppear_12), DEBUGSTRING("CElemental::H0x01420046_BossAppear_12")}, + {0x01420047, STATE_CEnemyBase_PreMainLoop, CEntity::pEventHandler(&CElemental:: +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +PreMainLoop),DEBUGSTRING("CElemental::PreMainLoop")}, + {0x01420048, -1, CEntity::pEventHandler(&CElemental::H0x01420048_PreMainLoop_01), DEBUGSTRING("CElemental::H0x01420048_PreMainLoop_01")}, + {0x01420049, -1, CEntity::pEventHandler(&CElemental::H0x01420049_PreMainLoop_02), DEBUGSTRING("CElemental::H0x01420049_PreMainLoop_02")}, + {0x0142004a, -1, CEntity::pEventHandler(&CElemental::H0x0142004a_PreMainLoop_03), DEBUGSTRING("CElemental::H0x0142004a_PreMainLoop_03")}, + {0x0142004b, -1, CEntity::pEventHandler(&CElemental::H0x0142004b_PreMainLoop_04), DEBUGSTRING("CElemental::H0x0142004b_PreMainLoop_04")}, + {0x0142004c, -1, CEntity::pEventHandler(&CElemental::H0x0142004c_PreMainLoop_05), DEBUGSTRING("CElemental::H0x0142004c_PreMainLoop_05")}, + {0x0142004d, -1, CEntity::pEventHandler(&CElemental::H0x0142004d_PreMainLoop_06), DEBUGSTRING("CElemental::H0x0142004d_PreMainLoop_06")}, + {1, -1, CEntity::pEventHandler(&CElemental:: +#line 1375 "D:/SE1_GPL/Sources/EntitiesMP/Elemental.es" +Main),DEBUGSTRING("CElemental::Main")}, +}; +#define CElemental_handlersct ARRAYCOUNT(CElemental_handlers) + +CEntity *CElemental_New(void) { return new CElemental; }; +void CElemental_OnInitClass(void) {}; +void CElemental_OnEndClass(void) {}; +void CElemental_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CElemental_OnWorldEnd(CWorld *pwo) {}; +void CElemental_OnWorldInit(CWorld *pwo) {}; +void CElemental_OnWorldTick(CWorld *pwo) {}; +void CElemental_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CElemental, CEnemyBase, "Elemental", "Thumbnails\\Elemental.tbn", 0x00000142); +DECLARE_CTFILENAME(_fnmCElemental_tbn, "Thumbnails\\Elemental.tbn"); diff --git a/Sources/EntitiesMP/EnemyBase.cpp b/Sources/EntitiesMP/EnemyBase.cpp new file mode 100644 index 0000000..85c4274 --- /dev/null +++ b/Sources/EntitiesMP/EnemyBase.cpp @@ -0,0 +1,4404 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" + +#include "StdH.h" +#include "EntitiesMP/Common/PathFinding.h" +#include "EntitiesMP/NavigationMarker.h" +#include "EntitiesMP/TacticsHolder.h" +extern void JumpFromBouncer(CEntity *penToBounce, CEntity *penBouncer); +extern INDEX ent_bReportBrokenChains; + +#include +#include +CEntityEvent *ERestartAttack::MakeCopy(void) { CEntityEvent *peeCopy = new ERestartAttack(*this); return peeCopy;} +ERestartAttack::ERestartAttack() : CEntityEvent(EVENTCODE_ERestartAttack) {; +}; +CEntityEvent *EReconsiderBehavior::MakeCopy(void) { CEntityEvent *peeCopy = new EReconsiderBehavior(*this); return peeCopy;} +EReconsiderBehavior::EReconsiderBehavior() : CEntityEvent(EVENTCODE_EReconsiderBehavior) {; +}; +CEntityEvent *EForceWound::MakeCopy(void) { CEntityEvent *peeCopy = new EForceWound(*this); return peeCopy;} +EForceWound::EForceWound() : CEntityEvent(EVENTCODE_EForceWound) {; +}; +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" + +#define MF_MOVEZ (1L<<0) +#define MF_ROTATEH (1L<<1) +#define MF_MOVEXZY (1L<<2) + +void CEnemyBase::SetDefaultProperties(void) { + m_penWatcher = NULL; + m_vStartPosition = FLOAT3D(0 , 0 , 0); + m_penEnemy = NULL; + m_ttTarget = TT_NONE ; + m_strDescription = "Enemy base"; + m_strName = "Enemy base"; + m_soSound.SetOwner(this); +m_soSound.Stop_internal(); + m_vStartDirection = FLOAT3D(0 , 0 , - 1); + m_bOnStartPosition = TRUE ; + m_fFallHeight = 8.0f; + m_fStepHeight = -1.0f; + m_fSenseRange = 0.0f; + m_fViewAngle = 360.0f; + m_fWalkSpeed = 1.0f; + m_aWalkRotateSpeed = AngleDeg(10.0f); + m_fAttackRunSpeed = 1.0f; + m_aAttackRotateSpeed = AngleDeg(10.0f); + m_fCloseRunSpeed = 1.0f; + m_aCloseRotateSpeed = AngleDeg(10.0f); + m_fAttackDistance = 50.0f; + m_fCloseDistance = 10.0f; + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 1.0f; + m_fStopDistance = 0.0f; + m_fIgnoreRange = 200.0f; + m_fLockOnEnemyTime = 0.0f; + m_fBlowUpAmount = 0.0f; + m_fBodyParts = 4; + m_fDamageWounded = 0.0f; + m_vDamage = FLOAT3D(0 , 0 , 0); + m_tmLastDamage = -1000.0f; + m_bRobotBlowup = FALSE ; + m_fBlowUpSize = 2.0f; + m_fMoveTime = 0.0f; + m_vDesiredPosition = FLOAT3D(0 , 0 , 0); + m_dtDestination = DT_PLAYERCURRENT ; + m_penPathMarker = NULL; + m_vPlayerSpotted = FLOAT3D(0 , 0 , 0); + m_fMoveFrequency = 0.0f; + m_fMoveSpeed = 0.0f; + m_aRotateSpeed = 0; + m_fLockStartTime = 0.0f; + m_fRangeLast = 0.0f; + m_bFadeOut = FALSE ; + m_fFadeStartTime = 0.0f; + m_fFadeTime = 0.0f; + m_fShootTime = 0.0f; + m_fDamageConfused = 0.0f; + m_iChargeHitAnimation = 0.0f; + m_fChargeHitDamage = 0.0f; + m_fChargeHitAngle = 0.0f; + m_fChargeHitSpeed = 0.0f; + m_penSpawnerTarget = NULL; + m_penDeathTarget = NULL; + m_eetDeathType = EET_TRIGGER ; + m_bTemplate = FALSE ; + m_fAttackRadius = 10000.0f; + m_colColor = 0x00; + m_bDeaf = FALSE ; + m_bBlind = FALSE ; + m_tmGiveUp = 5.0f; + m_tmReflexMin = 0.0f; + m_tmReflexMax = 0.0f; + m_fActivityRange = 0.0f; + m_bApplyRandomStretch = FALSE ; + m_fRandomStretchFactor = 0.1f; + m_fStretchMultiplier = 1.0f; + m_fRandomStretchMultiplier = 1.0f; + m_penMarker = NULL; + m_penMainMusicHolder = NULL; + m_tmLastFussTime = 0.0f; + m_iScore = -100000; + m_fMaxHealth = -1.0f; + m_bBoss = FALSE ; + m_fSpiritStartTime = 0.0f; + m_tmSpraySpawned = 0.0f; + m_fSprayDamage = 0.0f; + m_penSpray = NULL; + m_fMaxDamageAmmount = 0.0f; + m_vLastStain = FLOAT3D(0 , 0 , 0); + m_sptType = SPT_BLOOD ; + m_penTacticsHolder = NULL; + m_bTacticActive = FALSE ; + m_tmTacticsActivation = 0.0f; + m_vTacticsStartPosition = FLOAT3D(0 , 0 , 0); + m_fTacticVar1 = 0.0f; + m_fTacticVar2 = 0.0f; + m_fTacticVar3 = 0.0f; + m_fTacticVar4 = 0.0f; + m_fTacticVar5 = 0.0f; + m_bTacticsStartOnSense = FALSE ; + m_colBurning = COLOR(C_WHITE | CT_OPAQUE ); + m_bResizeAttachments = FALSE ; + m_penPrediction = NULL; + CMovableModelEntity::SetDefaultProperties(); +} + CEnemyBase::CEnemyBase(void) +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmPredict = 0; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::SetPredictionTime(TIME tmAdvance) +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (! IsPredictor ()); +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmPredict = _pTimer -> CurrentTick () + tmAdvance ; +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +TIME CEnemyBase::GetPredictionTime(void) +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return m_tmPredict ; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + CTString CEnemyBase::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CTString str ; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +str . PrintF (TRANS ("%s killed %s") , GetClass () -> ec_pdecDLLClass -> dec_strName , strPlayerName ); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return str ; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + FLOAT CEnemyBase::GetCrushHealth(void) +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return 0.0f; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + BOOL CEnemyBase::CountAsKill(void) +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + BOOL CEnemyBase::ForcesCannonballToExplode(void) +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + FLOAT & CEnemyBase::GetProp(FLOAT & m_fBase) +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return m_fBase ; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + FLOAT CEnemyBase::GetThreatDistance(void) +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return Max (GetProp (m_fCloseDistance ) , GetProp (m_fStopDistance )); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::MaybeSwitchToAnotherPlayer(void) +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(GetSP () -> sp_bSinglePlayer ){ +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(CalcDist (m_penEnemy ) < GetThreatDistance ()){ +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * penNewEnemy = GetWatcher () -> CheckAnotherPlayer (m_penEnemy ); +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(penNewEnemy != m_penEnemy && penNewEnemy != NULL ){ +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penEnemy = penNewEnemy ; +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SendEvent (EReconsiderBehavior ()); +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +class CWatcher * CEnemyBase::GetWatcher(void) +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (m_penWatcher != NULL ); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return (CWatcher *) & * m_penWatcher ; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::Copy(CEntity & enOther,ULONG ulFlags) +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CMovableModelEntity :: Copy (enOther , ulFlags ); +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEnemyBase * penOther = (CEnemyBase *) (& enOther ); +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::Precache(void) +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheModel (MODEL_FLESH ); +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheModel (MODEL_FLESH_APPLE ); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheModel (MODEL_FLESH_BANANA ); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheModel (MODEL_FLESH_BURGER ); +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheModel (MODEL_MACHINE ); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheTexture (TEXTURE_MACHINE ); +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheTexture (TEXTURE_FLESH_RED ); +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheTexture (TEXTURE_FLESH_GREEN ); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheTexture (TEXTURE_FLESH_APPLE ); +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheTexture (TEXTURE_FLESH_BANANA ); +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheTexture (TEXTURE_FLESH_BURGER ); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheTexture (TEXTURE_FLESH_LOLLY ); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheTexture (TEXTURE_FLESH_ORANGE ); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_BLOODSPILL ); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_BLOODSTAIN ); +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_BLOODSTAINGROW ); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_BLOODEXPLODE ); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_BOMB ); +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_EXPLOSIONSTAIN ); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PrecacheClass (CLASS_DEBRIS ); +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + FLOAT3D CEnemyBase::PlayerDestinationPos(void) +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D CEnemyBase::CalcDelta(CEntity * penEntity) +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (penEntity != NULL ); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return penEntity -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT CEnemyBase::CalcDist(CEntity * penEntity) +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return CalcDelta (penEntity ) . Length (); +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::IfTargetCrushed(CEntity * penOther,const FLOAT3D & vDirection) +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsOfClass (penOther , "ModelHolder2")) +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fCrushHealth = GetCrushHealth (); +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fCrushHealth > ((CRationalEntity &) * penOther ) . GetHealth ()) +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +InflictDirectDamage (penOther , this , +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +DMT_EXPLOSION , fCrushHealth , GetPlacement () . pl_PositionVector , vDirection ); +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE ; +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D CEnemyBase::CalcPlaneDelta(CEntity * penEntity) +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (penEntity != NULL ); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vPlaneDelta ; +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetNormalComponent ( +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penEntity -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector , +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +en_vGravityDir , vPlaneDelta ); +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return vPlaneDelta ; +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT CEnemyBase::CalcPlaneDist(CEntity * penEntity) +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return CalcPlaneDelta (penEntity ) . Length (); +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT CEnemyBase::GetFrustumAngle(const FLOAT3D & vDir) +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vFront = - GetRotationMatrix () . GetColumn (3); +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return (vDir / vDir . Length ()) % vFront ; +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT CEnemyBase::GetPlaneFrustumAngle(const FLOAT3D & vDir) +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vPlaneDelta ; +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetNormalComponent (vDir , en_vGravityDir , vPlaneDelta ); +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vFront = - GetRotationMatrix () . GetColumn (3); +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vPlaneFront ; +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetNormalComponent (vFront , en_vGravityDir , vPlaneFront ); +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vPlaneDelta . SafeNormalize (); +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vPlaneFront . SafeNormalize (); +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return vPlaneDelta % vPlaneFront ; +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::IsInFrustum(CEntity * penEntity,FLOAT fCosHalfFrustum) +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vDelta = CalcDelta (penEntity ); +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vFront = - GetRotationMatrix () . GetColumn (3); +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fDotProduct = (vDelta / vDelta . Length ()) % vFront ; +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return fDotProduct >= fCosHalfFrustum ; +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::IsInPlaneFrustum(CEntity * penEntity,FLOAT fCosHalfFrustum) +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vPlaneDelta = CalcPlaneDelta (penEntity ); +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vFront = - GetRotationMatrix () . GetColumn (3); +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vPlaneFront ; +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetNormalComponent (vFront , en_vGravityDir , vPlaneFront ); +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vPlaneDelta . SafeNormalize (); +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vPlaneFront . SafeNormalize (); +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fDot = vPlaneDelta % vPlaneFront ; +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return fDot >= fCosHalfFrustum ; +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::IsVisible(CEntity * penEntity) +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (penEntity != NULL ); +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vSource , vTarget ; +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetPositionCastRay (this , penEntity , vSource , vTarget ); +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CCastRay crRay (this , vSource , vTarget ); +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +crRay . cr_ttHitModels = CCastRay :: TT_NONE ; +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +en_pwoWorld -> CastRay (crRay ); +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return (crRay . cr_penHit == NULL ); +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::IsVisibleCheckAll(CEntity * penEntity) +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (penEntity != NULL ); +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vSource , vTarget ; +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetPositionCastRay (this , penEntity , vSource , vTarget ); +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CCastRay crRay (this , vSource , vTarget ); +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +crRay . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ; +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +en_pwoWorld -> CastRay (crRay ); +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return crRay . cr_penHit == penEntity ; +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::CalculateAngularLaunchParams( +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vShooting,FLOAT fShootHeight, +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vTarget,FLOAT3D vSpeedDest, +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ANGLE aPitch, +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT & fLaunchSpeed, +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT & fRelativeHdg) +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vNewTarget = vTarget ; +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D & vGravity = en_vGravityDir ; +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fYt ; +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fXt ; +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fA = TanFast (AngleDeg (aPitch )); +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fTime = 0.0f; +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fLastTime = 0.0f; +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +INDEX iIterations = 0; +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +do +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +iIterations ++; +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vDistance = vNewTarget - vShooting ; +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vXt , vYt ; +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetParallelAndNormalComponents (vDistance , vGravity , vYt , vXt ); +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fYt = vYt . Length (); +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(vGravity % vYt > 0){ +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fYt = - fYt ; +#line 491 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fXt = vXt . Length (); +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fLastTime = fTime ; +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fTime = Sqrt (2.0f) * Sqrt ((fA * fXt + fShootHeight - fYt ) / en_fGravityA ); +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vNewTarget = vTarget + vSpeedDest * fTime ; +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +while((Abs (fTime - fLastTime ) > _pTimer -> TickQuantum ) && (iIterations < 10)); +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fLaunchSpeed = fXt / (fTime * Cos (aPitch )); +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fHdgTargetNow = GetRelativeHeading ((vTarget - vShooting ) . SafeNormalize ()); +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fHdgTargetMoved = GetRelativeHeading ((vNewTarget - vShooting ) . SafeNormalize ()); +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fRelativeHdg = fHdgTargetMoved - fHdgTargetNow ; +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D CEnemyBase::CalculatePredictedPosition(FLOAT3D vShootPos,FLOAT3D vTarget, +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fSpeedSrc,FLOAT3D vSpeedDst,FLOAT fClampY) +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vNewTarget = vTarget ; +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D & vGravity = en_vGravityDir ; +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fTime = 0.0f; +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fLastTime = 0.0f; +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +INDEX iIterations = 0; +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vDistance = vNewTarget - vShootPos ; +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +do +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +iIterations ++; +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fLastTime = fTime ; +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fTime = vDistance . Length () / fSpeedSrc ; +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vNewTarget = vTarget + vSpeedDst * fTime + vGravity * 0.5f * fTime * fTime ; +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vNewTarget (2) = ClampDn (vNewTarget (2) , fClampY ); +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDistance = vNewTarget - vShootPos ; +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +while((Abs (fTime - fLastTime ) > _pTimer -> TickQuantum ) && (iIterations < 10)); +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return vNewTarget ; +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 534 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::MovesByTargetedRoute(CTString & strTargetProperty)const { +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +strTargetProperty = "Marker"; +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE ; +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fnmMarkerClass = CTFILENAME ("Classes\\EnemyMarker.ecl"); +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +strTargetProperty = "Marker"; +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE ; +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +const CTString & CEnemyBase::GetDescription(void)const { +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penMarker != NULL ){ +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , m_penMarker -> GetName ()); +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return m_strDescription ; +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + const CTFileName & CEnemyBase::GetComputerMessageName(void)const { +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +static CTFileName fnm (CTString ("")); +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return fnm ; +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::AddDependentsToPrediction(void) +#line 559 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penSpray -> AddToPrediction (); +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penWatcher != NULL ){ +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetWatcher () -> AddToPrediction (); +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::ChecksumForSync(ULONG & ulCRC,INDEX iExtensiveSyncCheck) { +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CMovableModelEntity :: ChecksumForSync (ulCRC , iExtensiveSyncCheck ); +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck) +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 573 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CMovableModelEntity :: DumpSync_t (strm , iExtensiveSyncCheck ); +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +strm . FPrintF_t ("enemy: "); +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penEnemy != NULL ){ +#line 576 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +strm . FPrintF_t ("id: %08X\n" , m_penEnemy -> en_ulID ); +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +strm . FPrintF_t ("none\n"); +#line 579 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::Read_t(CTStream * istr) { +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CMovableModelEntity :: Read_t (istr ); +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penMainMusicHolder != NULL ){ +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +((CMusicHolder &) * m_penMainMusicHolder ) . m_cenFussMakers . Add (this ); +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::FillEntityStatistics(EntityStats * pes) +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +pes -> es_strName = GetClass () -> ec_pdecDLLClass -> dec_strName ; +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bTemplate ){ +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +pes -> es_ctCount = 0; +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 607 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +pes -> es_ctCount = 1; +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 609 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +pes -> es_ctAmmount = 1; +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +pes -> es_fValue = GetHealth (); +#line 611 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +pes -> es_iScore = m_iScore ; +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE ; +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 616 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 618 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bTemplate ){ +#line 622 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 623 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fNewDamage = fDamageAmmount ; +#line 628 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fNewDamage *= DamageStrength (((EntityInfo *) GetEntityInfo ()) -> Eeibt , dmtType ); +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fNewDamage *= GetGameDamageMultiplier (); +#line 633 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fNewDamage == 0){ +#line 635 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fKickDamage = fNewDamage ; +#line 638 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if((dmtType == DMT_EXPLOSION ) || (dmtType == DMT_IMPACT ) || (dmtType == DMT_CANNONBALL_EXPLOSION )) +#line 639 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 640 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fKickDamage *= 1.5; +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 642 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(dmtType == DMT_DROWNING || dmtType == DMT_CLOSERANGE || dmtType == DMT_CHAINSAW ){ +#line 643 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fKickDamage /= 10; +#line 644 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 645 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(dmtType == DMT_BURNING ) +#line 646 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fKickDamage /= 100000; +#line 648 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +UBYTE ubR , ubG , ubB , ubA ; +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fColorFactor = fNewDamage / m_fMaxHealth * 255.0f; +#line 650 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ColorToRGBA (m_colBurning , ubR , ubG , ubB , ubA ); +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ubR = ClampDn (ubR - fColorFactor , 32.0f); +#line 652 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_colBurning = RGBAToColor (ubR , ubR , ubR , ubA ); +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 656 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 657 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +TIME tmDelta = tmNow - m_tmLastDamage ; +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmLastDamage = tmNow ; +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(tmDelta >= _pTimer -> TickQuantum * 3){ +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vDamage = FLOAT3D (0 , 0 , 0); +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 665 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vDirectionFixed ; +#line 666 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(vDirection . ManhattanNorm () > 0.5f){ +#line 667 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDirectionFixed = vDirection ; +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 669 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDirectionFixed = - en_vGravityDir ; +#line 670 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 671 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vDamageOld = m_vDamage ; +#line 677 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 678 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vDamage += (vDirectionFixed - en_vGravityDir / 2) * fKickDamage ; +#line 679 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 681 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fOldLen = vDamageOld . Length (); +#line 682 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fNewLen = m_vDamage . Length (); +#line 683 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fOldRootLen = Sqrt (fOldLen ); +#line 684 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fNewRootLen = Sqrt (fNewLen ); +#line 686 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fMassFactor = 300.0f / ((EntityInfo *) GetEntityInfo ()) -> fMass ; +#line 688 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(! (en_ulFlags & ENF_ALIVE )) +#line 689 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 690 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fMassFactor /= 3; +#line 691 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 693 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fOldLen != 0.0f) +#line 694 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 696 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GiveImpulseTranslationAbsolute (- vDamageOld / fOldRootLen * fMassFactor ); +#line 697 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GiveImpulseTranslationAbsolute (m_vDamage / fNewRootLen * fMassFactor ); +#line 708 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_fMaxDamageAmmount < fDamageAmmount ) +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMaxDamageAmmount = fDamageAmmount ; +#line 711 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 713 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if((m_tmSpraySpawned <= _pTimer -> CurrentTick () - _pTimer -> TickQuantum * 8 || +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fSprayDamage + fNewDamage > 50.0f) +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +&& m_fSpiritStartTime == 0 && +#line 716 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +dmtType != DMT_CHAINSAW && +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +! (dmtType == DMT_BURNING && GetHealth () < 0)){ +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CPlacement3D plSpray = CPlacement3D (vHitPoint , ANGLE3D (0 , 0 , 0)); +#line 721 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 722 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_sptType != SPT_ELECTRICITY_SPARKS ) +#line 723 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 724 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penSpray -> SetParent (this ); +#line 725 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 727 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ESpawnSpray eSpawnSpray ; +#line 728 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 730 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_fMaxDamageAmmount > 10.0f) +#line 731 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 732 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSpawnSpray . fDamagePower = 3.0f; +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 734 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +else if(m_fSprayDamage + fNewDamage > 50.0f) +#line 735 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 736 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSpawnSpray . fDamagePower = 2.0f; +#line 737 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 738 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +else +#line 739 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 740 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSpawnSpray . fDamagePower = 1.0f; +#line 741 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 743 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSpawnSpray . sptType = m_sptType ; +#line 744 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSpawnSpray . fSizeMultiplier = 1.0f; +#line 747 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vHitPointRelative = vHitPoint - GetPlacement () . pl_PositionVector ; +#line 748 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vReflectingNormal ; +#line 749 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetNormalComponent (vHitPointRelative , en_vGravityDir , vReflectingNormal ); +#line 750 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vReflectingNormal . SafeNormalize (); +#line 752 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vReflectingNormal (1) /= 5.0f; +#line 754 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vProjectedComponent = vReflectingNormal * (vDirection % vReflectingNormal ); +#line 755 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vSpilDirection = vDirection - vProjectedComponent * 2.0f - en_vGravityDir * 0.5f; +#line 757 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSpawnSpray . vDirection = vSpilDirection ; +#line 758 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSpawnSpray . penOwner = this ; +#line 766 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penSpray -> Initialize (eSpawnSpray ); +#line 767 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmSpraySpawned = _pTimer -> CurrentTick (); +#line 768 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fSprayDamage = 0.0f; +#line 769 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMaxDamageAmmount = 0.0f; +#line 770 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 771 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fSprayDamage += fNewDamage ; +#line 773 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CMovableModelEntity :: ReceiveDamage (penInflictor , +#line 774 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +dmtType , fNewDamage , vHitPoint , vDirection ); +#line 775 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 782 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 783 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 784 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +colAmbient = AddColors (colAmbient , m_colColor ); +#line 785 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bFadeOut ){ +#line 786 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fTimeRemain = m_fFadeStartTime + m_fFadeTime - _pTimer -> CurrentTick (); +#line 787 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fTimeRemain < 0.0f){fTimeRemain = 0.0f;} +#line 788 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +COLOR colAlpha ; +#line 789 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL ){ +#line 790 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +colAlpha = GetModelInstance () -> GetModelColor (); +#line 791 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +colAlpha = (colAlpha & 0xFFFFFF00) + (COLOR (fTimeRemain / m_fFadeTime * 0xFF) & 0xFF); +#line 792 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetModelInstance () -> SetModelColor (colAlpha ); +#line 793 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 794 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +else { +#line 795 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +colAlpha = GetModelObject () -> mo_colBlendColor ; +#line 796 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +colAlpha = (colAlpha & 0xFFFFFF00) + (COLOR (fTimeRemain / m_fFadeTime * 0xFF) & 0xFF); +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetModelObject () -> mo_colBlendColor = colAlpha ; +#line 798 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 800 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 801 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(GetSP () -> sp_bMental ){ +#line 802 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(GetHealth () <= 0){ +#line 803 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL ){ +#line 804 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetModelInstance () -> SetModelColor (C_WHITE & 0xFF); +#line 805 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 806 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetModelObject () -> mo_colBlendColor = C_WHITE & 0xFF; +#line 807 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 808 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 809 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +extern FLOAT ent_tmMentalIn ; +#line 810 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +extern FLOAT ent_tmMentalOut ; +#line 811 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +extern FLOAT ent_tmMentalFade ; +#line 812 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT tmIn = ent_tmMentalIn ; +#line 813 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT tmOut = ent_tmMentalOut ; +#line 814 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT tmFade = ent_tmMentalFade ; +#line 815 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT tmExist = tmFade + tmIn + tmFade ; +#line 816 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT tmTotal = tmFade + tmIn + tmFade + tmOut ; +#line 818 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT tmTime = _pTimer -> GetLerpedCurrentTick (); +#line 819 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fFactor = 1; +#line 820 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(tmTime > 0.1f){ +#line 821 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +tmTime += en_ulID * 123.456f; +#line 822 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +tmTime = fmod (tmTime , tmTotal ); +#line 823 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fFactor = CalculateRatio (tmTime , 0 , tmExist , tmFade / tmExist , tmFade / tmExist ); +#line 824 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 826 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL ){ +#line 827 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetModelInstance () -> SetModelColor (C_WHITE | INDEX (0xFF * fFactor )); +#line 828 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 829 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetModelObject () -> mo_colBlendColor = C_WHITE | INDEX (0xFF * fFactor ); +#line 830 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 831 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 832 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 833 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 834 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_colBurning != COLOR (C_WHITE | CT_OPAQUE )) +#line 835 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 836 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +colAmbient = MulColors (colAmbient , m_colBurning ); +#line 837 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +colLight = MulColors (colLight , m_colBurning ); +#line 838 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 839 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return CMovableModelEntity :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 840 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 844 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::AddToFuss(void) +#line 845 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 846 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsPredictor ()){ +#line 848 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmLastFussTime = _pTimer -> CurrentTick (); +#line 849 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 850 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 853 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penMainMusicHolder == NULL ){ +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penMainMusicHolder = _pNetwork -> GetEntityWithName ("MusicHolder" , 0); +#line 857 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penMainMusicHolder == NULL ){ +#line 859 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmLastFussTime = _pTimer -> CurrentTick (); +#line 861 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 862 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 864 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +((CMusicHolder &) * m_penMainMusicHolder ) . m_cenFussMakers . Add (this ); +#line 866 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bBoss ){ +#line 867 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +((CMusicHolder &) * m_penMainMusicHolder ) . m_penBoss = this ; +#line 868 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmLastFussTime = _pTimer -> CurrentTick (); +#line 873 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 875 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (((CMusicHolder &) * m_penMainMusicHolder ) . m_cenFussMakers . IsMember (this )); +#line 877 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bBoss ){ +#line 878 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +((CMusicHolder &) * m_penMainMusicHolder ) . m_penBoss = this ; +#line 879 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 881 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmLastFussTime = _pTimer -> CurrentTick (); +#line 882 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 883 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 884 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::RemoveFromFuss(void) +#line 885 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 886 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsPredictor ()){ +#line 887 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 888 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 890 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penMainMusicHolder == NULL ){ +#line 892 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 893 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 895 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +((CMusicHolder &) * m_penMainMusicHolder ) . m_cenFussMakers . Remove (this ); +#line 897 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bBoss ){ +#line 898 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(((CMusicHolder &) * m_penMainMusicHolder ) . m_penBoss != this ){ +#line 899 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CPrintF (TRANS ("More than one boss active!\n")); +#line 900 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +((CMusicHolder &) * m_penMainMusicHolder ) . m_penBoss = NULL ; +#line 901 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 902 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 903 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penMainMusicHolder = NULL ; +#line 904 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 907 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::ShouldCeaseAttack(void) +#line 908 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 910 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penEnemy == NULL || +#line 911 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +! (m_penEnemy -> GetFlags () & ENF_ALIVE ) || +#line 912 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +(m_penEnemy -> GetFlags () & ENF_DELETED )){ +#line 914 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE ; +#line 915 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 917 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(_pTimer -> CurrentTick () > m_tmLastFussTime + m_tmGiveUp ){ +#line 919 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE ; +#line 920 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 922 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 923 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::SizeModel(void) +#line 927 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vStretch = GetModelStretch (); +#line 931 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vStretch *= m_fStretchMultiplier ; +#line 934 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bApplyRandomStretch ) +#line 935 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 937 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bApplyRandomStretch = FALSE ; +#line 939 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fRandomStretchMultiplier = (FRnd () - 0.5f) * m_fRandomStretchFactor + 1.0f; +#line 940 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 943 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vStretch *= m_fRandomStretchMultiplier ; +#line 945 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bResizeAttachments ){ +#line 946 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StretchModel (vStretch ); +#line 947 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(TRUE ){ +#line 948 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StretchSingleModel (vStretch ); +#line 949 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 950 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ModelChangeNotify (); +#line 951 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 954 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::IsValidForEnemy(CEntity * penPlayer) +#line 955 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 956 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return +#line 957 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penPlayer != NULL && +#line 958 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +IsDerivedFromClass (penPlayer , "Player") && +#line 959 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penPlayer -> GetFlags () & ENF_ALIVE ; +#line 960 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 963 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::SetTargetNone(void) +#line 964 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 965 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_ttTarget = TT_NONE ; +#line 966 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERCURRENT ; +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penEnemy = NULL ; +#line 968 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 971 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::SetTargetSoft(CEntity * penPlayer) +#line 972 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 974 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(! IsValidForEnemy (penPlayer )){ +#line 976 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 977 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 979 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_ttTarget != TT_NONE ){ +#line 981 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 982 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 984 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * penOld = m_penEnemy ; +#line 985 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_ttTarget = TT_SOFT ; +#line 986 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERCURRENT ; +#line 987 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penEnemy = penPlayer ; +#line 988 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return penOld != penPlayer ; +#line 989 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 992 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::SetTargetHard(CEntity * penPlayer) +#line 993 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 995 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(! IsValidForEnemy (penPlayer )){ +#line 997 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 998 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1000 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_ttTarget == TT_HARD ){ +#line 1002 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1003 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1005 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * penOld = m_penEnemy ; +#line 1006 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_ttTarget = TT_HARD ; +#line 1007 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERCURRENT ; +#line 1008 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penEnemy = penPlayer ; +#line 1009 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return penOld != penPlayer ; +#line 1010 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1013 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::SetTargetHardForce(CEntity * penPlayer) +#line 1014 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1016 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(! IsValidForEnemy (penPlayer )){ +#line 1018 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1019 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1021 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * penOld = m_penEnemy ; +#line 1022 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_ttTarget = TT_HARD ; +#line 1023 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERCURRENT ; +#line 1024 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penEnemy = penPlayer ; +#line 1025 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return penOld != penPlayer ; +#line 1026 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + FLOAT CEnemyBase::GetAttackMoveFrequency(FLOAT fEnemyDistance) +#line 1034 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1035 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fEnemyDistance > GetProp (m_fCloseDistance )){ +#line 1036 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return 0.5f; +#line 1037 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1038 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return 0.25f; +#line 1039 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1040 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::SetSpeedsToDesiredPosition(const FLOAT3D & vPosDelta,FLOAT fPosDist,BOOL bGoingToPlayer) +#line 1044 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1045 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fEnemyDistance = CalcDist (m_penEnemy ); +#line 1046 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fCloseDistance = GetProp (m_fCloseDistance ); +#line 1047 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fStopDistance = GetProp (m_fStopDistance ); +#line 1049 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fCos = GetPlaneFrustumAngle (vPosDelta ); +#line 1051 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(MayMoveToAttack () && +#line 1053 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fCos > CosFast (45.0f) && +#line 1055 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fEnemyDistance > fStopDistance ){ +#line 1057 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fEnemyDistance < fCloseDistance ){ +#line 1058 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = GetProp (m_fCloseRunSpeed ); +#line 1059 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = GetProp (m_aCloseRotateSpeed ); +#line 1060 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1061 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = GetProp (m_fAttackRunSpeed ); +#line 1062 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = GetProp (m_aAttackRotateSpeed ); +#line 1063 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1066 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(m_bTacticActive ){ +#line 1068 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fEnemyDistance < fCloseDistance ){ +#line 1069 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = GetProp (m_fCloseRunSpeed ); +#line 1070 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = GetProp (m_aCloseRotateSpeed ); +#line 1071 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1072 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = GetProp (m_fAttackRunSpeed ); +#line 1073 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = GetProp (m_aAttackRotateSpeed ); +#line 1074 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1077 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(fCos < CosFast (15.0f)){ +#line 1079 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = 0; +#line 1080 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fEnemyDistance < fCloseDistance ){ +#line 1081 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = GetProp (m_aCloseRotateSpeed ); +#line 1082 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1083 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = GetProp (m_aAttackRotateSpeed ); +#line 1084 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1087 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1089 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(bGoingToPlayer || ! WouldNotLeaveAttackRadius ()){ +#line 1091 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = 0; +#line 1092 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = 0; +#line 1094 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1095 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = GetProp (m_fCloseRunSpeed ); +#line 1096 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = GetProp (m_aCloseRotateSpeed ); +#line 1097 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1098 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1099 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::MovementAnimation(ULONG ulFlags) +#line 1103 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1104 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(ulFlags & MF_MOVEZ ){ +#line 1105 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_fMoveSpeed == GetProp (m_fAttackRunSpeed ) || m_fMoveSpeed == GetProp (m_fCloseRunSpeed ) +#line 1106 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +|| m_fMoveSpeed > GetProp (m_fWalkSpeed )){ +#line 1107 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +RunningAnim (); +#line 1108 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1109 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +WalkingAnim (); +#line 1110 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1111 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(ulFlags & MF_ROTATEH ){ +#line 1112 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +RotatingAnim (); +#line 1113 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1114 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penEnemy != NULL ){ +#line 1115 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StandingAnimFight (); +#line 1116 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1117 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StandingAnim (); +#line 1118 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1119 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1120 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + ULONG CEnemyBase::SetDesiredMovement(void) +#line 1125 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1126 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ULONG ulFlags = 0; +#line 1129 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vDelta = m_vDesiredPosition - GetPlacement () . pl_PositionVector ; +#line 1131 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_dtDestination == DT_PLAYERCURRENT ){ +#line 1132 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ApplyTactics (vDelta ); +#line 1133 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1136 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_aRotateSpeed > 0.0f){ +#line 1138 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vDir = vDelta ; +#line 1139 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDir . SafeNormalize (); +#line 1140 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ANGLE aWantedHeadingRelative = GetRelativeHeading (vDir ); +#line 1143 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +aWantedHeadingRelative = NormalizeAngle (aWantedHeadingRelative ); +#line 1145 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ANGLE aHeadingRotation ; +#line 1147 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(aWantedHeadingRelative < - m_aRotateSpeed * m_fMoveFrequency ){ +#line 1149 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +aHeadingRotation = - m_aRotateSpeed ; +#line 1151 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(aWantedHeadingRelative > m_aRotateSpeed * m_fMoveFrequency ){ +#line 1153 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +aHeadingRotation = + m_aRotateSpeed ; +#line 1155 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1157 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +aHeadingRotation = aWantedHeadingRelative / m_fMoveFrequency ; +#line 1158 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1160 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetDesiredRotation (ANGLE3D (aHeadingRotation , 0 , 0)); +#line 1162 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(Abs (aHeadingRotation ) > 1.0f){ +#line 1163 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ulFlags |= MF_ROTATEH ; +#line 1164 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1167 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1169 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1170 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1173 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_fMoveSpeed > 0.0f){ +#line 1175 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vTranslation (0.0f , 0.0f , 0.0f); +#line 1176 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vTranslation (3) = - m_fMoveSpeed ; +#line 1179 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetDesiredTranslation (vTranslation ); +#line 1181 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ulFlags |= MF_MOVEZ ; +#line 1184 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1186 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetDesiredTranslation (FLOAT3D (0 , 0 , 0)); +#line 1187 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1189 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ulFlags ; +#line 1190 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1193 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::StopMoving() +#line 1194 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1195 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopRotating (); +#line 1196 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopTranslating (); +#line 1197 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1200 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::StopRotating() +#line 1201 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1202 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1203 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1206 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::StopTranslating() +#line 1207 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1208 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 1209 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT CEnemyBase::CalcDistanceInPlaneToDestination(void) +#line 1213 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1215 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vNormal ; +#line 1216 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetNormalComponent (m_vDesiredPosition - GetPlacement () . pl_PositionVector , en_vGravityDir , vNormal ); +#line 1217 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return vNormal . Length (); +#line 1218 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::StartPathFinding(void) +#line 1222 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1223 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (m_dtDestination == DT_PATHPERSISTENT || m_dtDestination == DT_PATHTEMPORARY ); +#line 1225 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * penMarker ; +#line 1226 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vPath ; +#line 1228 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PATH_FindFirstMarker (this , +#line 1229 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetPlacement () . pl_PositionVector , m_penEnemy -> GetPlacement () . pl_PositionVector , +#line 1230 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penMarker , vPath ); +#line 1232 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(penMarker == NULL || ! IsVisible (penMarker )){ +#line 1234 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERSPOTTED ; +#line 1236 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vPlayerSpotted = PlayerDestinationPos (); +#line 1237 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 1238 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1240 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vDesiredPosition = vPath , +#line 1241 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penPathMarker = penMarker ; +#line 1242 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::FindNextPathMarker(void) +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1248 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penPathMarker == NULL ){ +#line 1250 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (FALSE ); +#line 1252 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERCURRENT ; +#line 1253 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 1254 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1257 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * penMarker = m_penPathMarker ; +#line 1258 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vPath ; +#line 1259 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PATH_FindNextMarker (this , +#line 1260 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetPlacement () . pl_PositionVector , m_penEnemy -> GetPlacement () . pl_PositionVector , +#line 1261 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penMarker , vPath ); +#line 1264 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(penMarker == NULL || ! IsVisible (penMarker )){ +#line 1266 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERSPOTTED ; +#line 1268 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vPlayerSpotted = PlayerDestinationPos (); +#line 1269 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 1270 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1273 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vDesiredPosition = vPath , +#line 1274 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penPathMarker = penMarker ; +#line 1275 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1278 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::CheckTouchForPathFinding(const ETouch & eTouch) +#line 1279 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1281 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penEnemy == NULL ){ +#line 1283 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1284 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1287 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_dtDestination == DT_PATHPERSISTENT || m_dtDestination == DT_PATHTEMPORARY ){ +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1290 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vDir = en_vDesiredTranslationRelative ; +#line 1293 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDir . SafeNormalize (); +#line 1294 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDir *= GetRotationMatrix (); +#line 1296 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if((eTouch . plCollision % vDir ) < - 0.5f){ +#line 1297 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penEnemy != NULL && IsVisible (m_penEnemy )){ +#line 1298 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PATHPERSISTENT ; +#line 1299 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PATHTEMPORARY ; +#line 1301 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1302 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StartPathFinding (); +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return m_penPathMarker != NULL ; +#line 1304 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1305 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1306 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1307 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1310 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::CheckFallForPathFinding(const EWouldFall & eWouldFall) +#line 1311 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penEnemy == NULL ){ +#line 1315 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1316 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1319 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_dtDestination == DT_PATHPERSISTENT || m_dtDestination == DT_PATHTEMPORARY ){ +#line 1321 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1322 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1324 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penEnemy != NULL && IsVisible (m_penEnemy )){ +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PATHPERSISTENT ; +#line 1326 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1327 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PATHTEMPORARY ; +#line 1328 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1329 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StartPathFinding (); +#line 1331 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return m_penPathMarker != NULL ; +#line 1332 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1338 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::InitializeTactics(void) { +#line 1342 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penTacticsHolder == NULL || ! IsOfClass (m_penTacticsHolder , "TacticsHolder") +#line 1343 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +|| m_penEnemy == NULL ){ +#line 1344 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 1345 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1347 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CTacticsHolder * penTactics = & (CTacticsHolder &) * m_penTacticsHolder ; +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmTacticsActivation = _pTimer -> CurrentTick (); +#line 1351 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vTacticsStartPosition = GetPlacement () . pl_PositionVector ; +#line 1354 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fSign ; +#line 1356 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(Sgn (penTactics -> m_fParam2 ) > 0 && Sgn (penTactics -> m_fParam1 ) > 0){ +#line 1357 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fSign = + 1.0f; +#line 1358 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(Sgn (penTactics -> m_fParam2 ) < 0 && Sgn (penTactics -> m_fParam1 ) < 0){ +#line 1359 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fSign = - 1.0f; +#line 1360 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1361 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fSign = Sgn (FRnd () - 0.5f); +#line 1362 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1364 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +switch(penTactics -> m_tctType ){ +#line 1365 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +case TCT_DAMP_ANGLE_STRIFE : { +#line 1367 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar1 = Lerp (Abs (penTactics -> m_fParam1 ) , Abs (penTactics -> m_fParam2 ) , FRnd ()) * fSign ; +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar2 = penTactics -> m_fParam4 ; +#line 1371 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar3 = penTactics -> m_fParam3 ; +#line 1373 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar4 = (m_penEnemy -> GetPlacement () . pl_PositionVector - m_vTacticsStartPosition ) . Length (); +#line 1375 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar5 = penTactics -> m_fParam5 ; +#line 1376 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +break ;} +#line 1378 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +case TCT_PARALLEL_RANDOM_DISTANCE : +#line 1380 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar1 = Lerp (penTactics -> m_fParam4 , penTactics -> m_fParam5 , FRnd ()); +#line 1382 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar4 = Lerp (Abs (penTactics -> m_fParam1 ) , Abs (penTactics -> m_fParam2 ) , FRnd ()) * fSign ; +#line 1384 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar2 = m_fAttackRunSpeed * 2.0f * 90.0f / m_aAttackRotateSpeed ; +#line 1387 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar3 = penTactics -> m_fParam3 ; +#line 1389 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar5 = (GetPlacement () . pl_PositionVector - m_penEnemy -> GetPlacement () . pl_PositionVector ) . Length (); +#line 1391 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar2 = ClampDn (m_fTacticVar2 , 2.0f); +#line 1393 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +break ; +#line 1395 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +case TCT_STATIC_RANDOM_V_DISTANCE : +#line 1397 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar1 = Lerp (Abs (penTactics -> m_fParam1 ) , Abs (penTactics -> m_fParam2 ) , FRnd ()) * fSign ; +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar2 = Lerp (penTactics -> m_fParam3 , penTactics -> m_fParam4 , FRnd ()); +#line 1400 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +break ; +#line 1401 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1402 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::ApplyTactics(FLOAT3D & vDesiredPos) { +#line 1408 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penTacticsHolder == NULL || ! IsOfClass (m_penTacticsHolder , "TacticsHolder") +#line 1409 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +|| m_penEnemy == NULL ){ +#line 1410 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 1411 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1413 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CTacticsHolder * penTactics = & (CTacticsHolder &) * m_penTacticsHolder ; +#line 1417 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(penTactics -> m_tmLastActivation == - 1 || penTactics -> m_tctType == TCT_NONE ){ +#line 1418 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bTacticActive = FALSE ; +#line 1419 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(m_tmTacticsActivation < penTactics -> m_tmLastActivation ){ +#line 1420 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +InitializeTactics (); +#line 1421 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bTacticActive = TRUE ; +#line 1422 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1424 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bTacticActive ){ +#line 1427 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vEnemyDistance = m_vTacticsStartPosition - m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 1428 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fEnemyDistance = vEnemyDistance . Length (); +#line 1429 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vEnemyDistance . SafeNormalize (); +#line 1430 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ANGLE3D angEnemy = ANGLE3D (0.0f , 0.0f , 0.0f); +#line 1433 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fDistanceRatio = 0.0f; +#line 1434 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fTimeRatio = 0.0f; +#line 1436 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +switch(penTactics -> m_tctType ) +#line 1437 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1438 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +case TCT_DAMP_ANGLE_STRIFE : { +#line 1440 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(CalcDist (m_penEnemy ) < m_fTacticVar5 ){ +#line 1441 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bTacticActive = FALSE ; +#line 1442 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1444 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fDistanceRatio = 1.0f; +#line 1445 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_fTacticVar3 > 0){ +#line 1447 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fClamped = Clamp (CalcDist (m_penEnemy ) - (m_fTacticVar4 * m_fTacticVar3 ) , 0.0f , m_fTacticVar4 ); +#line 1448 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fDistanceRatio = fClamped / (m_fTacticVar4 * (1 - m_fTacticVar3 )); +#line 1449 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1451 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fTimeRatio = 1.0f; +#line 1452 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_fTacticVar2 > 0){ +#line 1453 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fTimeRatio = 1.0f - (ClampUp ((_pTimer -> CurrentTick () - m_tmTacticsActivation ) / m_fTacticVar2 , 1.0f)); +#line 1454 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1456 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (1) = m_fTacticVar1 * fDistanceRatio * fTimeRatio ; +#line 1457 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (2) = 0.0f; +#line 1458 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (3) = 0.0f; +#line 1460 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOATmatrix3D mHeading ; +#line 1461 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MakeRotationMatrixFast (mHeading , angEnemy ); +#line 1462 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * ! en_mRotation ; +#line 1463 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * mHeading ; +#line 1464 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * en_mRotation ; +#line 1466 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +break ;} +#line 1468 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +case TCT_PARALLEL_RANDOM_DISTANCE : { +#line 1470 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vLinePlayerToSpawn = m_vTacticsStartPosition - m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 1472 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vLinePlayerToThis = GetPlacement () . pl_PositionVector - m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 1474 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fThisOnLine = (vLinePlayerToThis % vLinePlayerToSpawn ) / vLinePlayerToSpawn . Length (); +#line 1475 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vThisOnLine = m_penEnemy -> GetPlacement () . pl_PositionVector + vLinePlayerToSpawn . SafeNormalize () * fThisOnLine ; +#line 1477 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fLineDist = (GetPlacement () . pl_PositionVector - vThisOnLine ) . Length (); +#line 1479 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOATmatrix3D mHeading ; +#line 1483 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(vLinePlayerToThis . Length () < m_fTacticVar1 ){ +#line 1484 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bTacticActive = FALSE ; +#line 1486 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(fLineDist < m_fTacticVar1 ){ +#line 1487 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fLineDist < 1.0f){fLineDist = 1.0f;} +#line 1488 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (1) = m_fTacticVar4 / fLineDist ; +#line 1489 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (2) = 0.0f; +#line 1490 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (3) = 0.0f; +#line 1492 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MakeRotationMatrixFast (mHeading , angEnemy ); +#line 1493 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * ! en_mRotation ; +#line 1494 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * mHeading ; +#line 1495 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * en_mRotation ; +#line 1497 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(fLineDist > m_fTacticVar1 + m_fTacticVar2 ){ +#line 1498 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fLineDist < 1.0f){fLineDist = 1.0f;} +#line 1499 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (1) = - m_fTacticVar4 / fLineDist ; +#line 1500 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (2) = 0.0f; +#line 1501 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (3) = 0.0f; +#line 1503 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MakeRotationMatrixFast (mHeading , angEnemy ); +#line 1504 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * ! en_mRotation ; +#line 1505 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * mHeading ; +#line 1506 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * en_mRotation ; +#line 1508 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1509 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = - vLinePlayerToSpawn ; +#line 1510 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1511 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +break ;} +#line 1513 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +case TCT_STATIC_RANDOM_V_DISTANCE : { +#line 1514 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(_pTimer -> CurrentTick () < m_tmTacticsActivation + m_fTacticVar2 ){ +#line 1515 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (1) = m_fTacticVar1 ; +#line 1516 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (2) = 0.0f; +#line 1517 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +angEnemy (3) = 0.0f; +#line 1518 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1519 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bTacticActive = FALSE ; +#line 1520 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1522 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOATmatrix3D mHeading ; +#line 1523 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MakeRotationMatrixFast (mHeading , angEnemy ); +#line 1524 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * ! en_mRotation ; +#line 1525 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * mHeading ; +#line 1526 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDesiredPos = vDesiredPos * en_mRotation ; +#line 1528 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +break ;} +#line 1529 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1530 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1531 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1533 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::StartTacticsNow(void) { +#line 1534 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmTacticsActivation = - 1.0f; +#line 1535 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1541 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::CanAttackEnemy(CEntity * penTarget,FLOAT fCosAngle) { +#line 1542 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsInPlaneFrustum (penTarget , fCosAngle )){ +#line 1543 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsVisibleCheckAll (penTarget )){ +#line 1544 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE ; +#line 1545 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1546 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1547 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1548 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + BOOL CEnemyBase::CanHitEnemy(CEntity * penTarget,FLOAT fCosAngle) { +#line 1552 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsInFrustum (penTarget , fCosAngle )){ +#line 1553 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return IsVisibleCheckAll (penTarget ); +#line 1554 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1555 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1556 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1559 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::SeeEntity(CEntity * pen,FLOAT fCosAngle) { +#line 1560 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsInFrustum (pen , fCosAngle )){ +#line 1561 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return IsVisible (pen ); +#line 1562 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1563 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1564 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1567 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::SeeEntityInPlane(CEntity * pen,FLOAT fCosAngle) { +#line 1568 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CalcPlaneDist (pen ); +#line 1569 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsInPlaneFrustum (pen , fCosAngle )){ +#line 1570 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return IsVisible (pen ); +#line 1571 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1572 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1573 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1576 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::PreparePropelledProjectile(CPlacement3D & plProjectile,FLOAT3D vShootTarget, +#line 1577 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D & vOffset,ANGLE3D & aOffset) +#line 1578 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1579 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vDiff = (vShootTarget - (GetPlacement () . pl_PositionVector + vOffset * GetRotationMatrix ())) . SafeNormalize (); +#line 1582 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D mToTargetX , mToTargetY , mToTargetZ ; +#line 1583 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTargetZ = - vDiff ; +#line 1584 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTargetY = - en_vGravityDir ; +#line 1585 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTargetX = (mToTargetY * mToTargetZ ) . SafeNormalize (); +#line 1586 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTargetY = (mToTargetZ * mToTargetX ) . SafeNormalize (); +#line 1587 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOATmatrix3D mToTarget ; +#line 1588 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTarget (1 , 1) = mToTargetX (1);mToTarget (1 , 2) = mToTargetY (1);mToTarget (1 , 3) = mToTargetZ (1); +#line 1589 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTarget (2 , 1) = mToTargetX (2);mToTarget (2 , 2) = mToTargetY (2);mToTarget (2 , 3) = mToTargetZ (2); +#line 1590 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTarget (3 , 1) = mToTargetX (3);mToTarget (3 , 2) = mToTargetY (3);mToTarget (3 , 3) = mToTargetZ (3); +#line 1593 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +plProjectile . pl_PositionVector = GetPlacement () . pl_PositionVector + vOffset * GetRotationMatrix (); +#line 1594 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOATmatrix3D mDirection ; +#line 1595 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MakeRotationMatrixFast (mDirection , aOffset ); +#line 1596 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +DecomposeRotationMatrixNoSnap (plProjectile . pl_OrientationAngle , mToTarget * mDirection ); +#line 1597 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1600 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::PrepareFreeFlyingProjectile(CPlacement3D & plProjectile,FLOAT3D vShootTarget, +#line 1601 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D & vOffset,ANGLE3D & aOffset) +#line 1602 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1603 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vDiff = (vShootTarget - (GetPlacement () . pl_PositionVector + vOffset * GetRotationMatrix ())) . SafeNormalize (); +#line 1606 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D mToTargetX , mToTargetY , mToTargetZ ; +#line 1607 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTargetZ = - vDiff ; +#line 1608 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTargetY = - en_vGravityDir ; +#line 1609 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTargetX = (mToTargetY * mToTargetZ ) . SafeNormalize (); +#line 1610 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTargetZ = (mToTargetX * mToTargetY ) . SafeNormalize (); +#line 1611 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOATmatrix3D mToTarget ; +#line 1612 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTarget (1 , 1) = mToTargetX (1);mToTarget (1 , 2) = mToTargetY (1);mToTarget (1 , 3) = mToTargetZ (1); +#line 1613 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTarget (2 , 1) = mToTargetX (2);mToTarget (2 , 2) = mToTargetY (2);mToTarget (2 , 3) = mToTargetZ (2); +#line 1614 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +mToTarget (3 , 1) = mToTargetX (3);mToTarget (3 , 2) = mToTargetY (3);mToTarget (3 , 3) = mToTargetZ (3); +#line 1617 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +plProjectile . pl_PositionVector = GetPlacement () . pl_PositionVector + vOffset * GetRotationMatrix (); +#line 1618 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOATmatrix3D mDirection ; +#line 1619 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MakeRotationMatrixFast (mDirection , aOffset ); +#line 1620 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +DecomposeRotationMatrixNoSnap (plProjectile . pl_OrientationAngle , mToTarget * mDirection ); +#line 1621 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1624 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * CEnemyBase::ShootProjectile(enum ProjectileType pt,FLOAT3D & vOffset,ANGLE3D & aOffset) { +#line 1625 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (m_penEnemy != NULL ); +#line 1628 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 1629 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vShootTarget ; +#line 1630 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetEntityInfoPosition (m_penEnemy , peiTarget -> vTargetCenter , vShootTarget ); +#line 1633 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CPlacement3D pl ; +#line 1634 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PreparePropelledProjectile (pl , vShootTarget , vOffset , aOffset ); +#line 1635 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 1636 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ELaunchProjectile eLaunch ; +#line 1637 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eLaunch . penLauncher = this ; +#line 1638 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eLaunch . fStretch = 1.0f; +#line 1639 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eLaunch . prtType = pt ; +#line 1640 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penProjectile -> Initialize (eLaunch ); +#line 1642 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return penProjectile ; +#line 1643 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1646 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * CEnemyBase::ShootProjectileAt(FLOAT3D vShootTarget,enum ProjectileType pt,FLOAT3D & vOffset,ANGLE3D & aOffset) { +#line 1649 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CPlacement3D pl ; +#line 1650 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PreparePropelledProjectile (pl , vShootTarget , vOffset , aOffset ); +#line 1651 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 1652 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ELaunchProjectile eLaunch ; +#line 1653 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eLaunch . penLauncher = this ; +#line 1654 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eLaunch . prtType = pt ; +#line 1655 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penProjectile -> Initialize (eLaunch ); +#line 1657 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return penProjectile ; +#line 1658 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1661 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * CEnemyBase::ShootPredictedProjectile(enum ProjectileType pt,FLOAT3D vPredictedPos,FLOAT3D & vOffset,ANGLE3D & aOffset) { +#line 1662 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (m_penEnemy != NULL ); +#line 1665 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 1666 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vShootTarget = vPredictedPos ; +#line 1667 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(peiTarget != NULL ) +#line 1668 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1670 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vBody = FLOAT3D (peiTarget -> vTargetCenter [ 0 ] , peiTarget -> vTargetCenter [ 1 ] , peiTarget -> vTargetCenter [ 2 ]); +#line 1671 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOATmatrix3D mRotation ; +#line 1672 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MakeRotationMatrixFast (mRotation , m_penEnemy -> GetPlacement () . pl_OrientationAngle ); +#line 1673 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vShootTarget = vPredictedPos + vBody * mRotation ; +#line 1674 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1676 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CPlacement3D pl ; +#line 1677 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PreparePropelledProjectile (pl , vShootTarget , vOffset , aOffset ); +#line 1678 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 1679 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ELaunchProjectile eLaunch ; +#line 1680 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eLaunch . penLauncher = this ; +#line 1681 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eLaunch . prtType = pt ; +#line 1682 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penProjectile -> Initialize (eLaunch ); +#line 1684 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return penProjectile ; +#line 1685 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1687 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::WouldNotLeaveAttackRadius(void) +#line 1688 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1689 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_fAttackRadius <= 0){ +#line 1690 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE ; +#line 1691 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1693 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL bInsideNow = (m_vStartPosition - GetPlacement () . pl_PositionVector ) . Length () < m_fAttackRadius ; +#line 1695 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL bEnemyTowardsCenter = +#line 1696 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +(m_vStartPosition - m_penEnemy -> GetPlacement () . pl_PositionVector ) . Length () < +#line 1697 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +(GetPlacement () . pl_PositionVector - m_penEnemy -> GetPlacement () . pl_PositionVector ) . Length (); +#line 1698 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return bInsideNow || bEnemyTowardsCenter ; +#line 1699 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + BOOL CEnemyBase::MayMoveToAttack(void) +#line 1703 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1705 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CMovableEntity * pen = (CMovableEntity *) & * m_penEnemy ; +#line 1706 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CContentType & ctUp = pen -> en_pwoWorld -> wo_actContentTypes [ pen -> en_iUpContent ]; +#line 1707 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL bEnemyDiving = ! (ctUp . ct_ulFlags & CTF_BREATHABLE_LUNGS ); +#line 1709 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return WouldNotLeaveAttackRadius () && ! bEnemyDiving ; +#line 1710 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + BOOL CEnemyBase::ShouldBlowUp(void) +#line 1718 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1720 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsOfClass (this , "ExotechLarva")){return TRUE ;} +#line 1723 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return +#line 1725 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetSP () -> sp_bGibs && +#line 1727 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetHealth () <= 0 && +#line 1729 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vDamage . Length () > m_fBlowUpAmount && +#line 1731 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fSpiritStartTime == 0; +#line 1732 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1736 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::BlowUpBase(void) +#line 1737 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1739 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BlowUp (); +#line 1740 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::BlowUp(void) +#line 1745 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1747 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BlowUpNotify (); +#line 1748 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +const BOOL bGibs = GetSP () -> sp_bGibs ; +#line 1750 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vNormalizedDamage = m_vDamage - m_vDamage * (m_fBlowUpAmount / m_vDamage . Length ()); +#line 1751 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vNormalizedDamage /= Sqrt (vNormalizedDamage . Length ()); +#line 1752 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vNormalizedDamage *= 0.75f; +#line 1753 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute - en_vGravityDir * (en_vGravityDir % en_vCurrentTranslationAbsolute ); +#line 1756 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(bGibs && ! m_bRobotBlowup ) +#line 1757 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1759 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +const INDEX iBloodType = GetSP () -> sp_iBlood ; +#line 1761 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ULONG ulFleshTexture = TEXTURE_FLESH_GREEN ; +#line 1762 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ULONG ulFleshModel = MODEL_FLESH ; +#line 1763 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(iBloodType == 2){ulFleshTexture = TEXTURE_FLESH_RED ;} +#line 1765 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Debris_Begin (EIBT_FLESH , DPT_BLOODTRAIL , BET_BLOODSTAIN , m_fBlowUpSize , vNormalizedDamage , vBodySpeed , 1.0f , 0.0f); +#line 1766 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +for(INDEX iDebris = 0;iDebris < m_fBodyParts ;iDebris ++){ +#line 1768 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(iBloodType == 3){ +#line 1769 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +switch(IRnd () % 5){ +#line 1770 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +case 1: {ulFleshModel = MODEL_FLESH_APPLE ;ulFleshTexture = TEXTURE_FLESH_APPLE ;break ;} +#line 1771 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +case 2: {ulFleshModel = MODEL_FLESH_BANANA ;ulFleshTexture = TEXTURE_FLESH_BANANA ;break ;} +#line 1772 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +case 3: {ulFleshModel = MODEL_FLESH_BURGER ;ulFleshTexture = TEXTURE_FLESH_BURGER ;break ;} +#line 1773 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +case 4: {ulFleshModel = MODEL_FLESH_LOLLY ;ulFleshTexture = TEXTURE_FLESH_LOLLY ;break ;} +#line 1774 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +default :{ulFleshModel = MODEL_FLESH_ORANGE ;ulFleshTexture = TEXTURE_FLESH_ORANGE ;break ;} +#line 1775 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1776 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1777 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Debris_Spawn (this , this , ulFleshModel , ulFleshTexture , 0 , 0 , 0 , IRnd () % 4 , 0.5f , +#line 1778 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 1779 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1781 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +LeaveStain (FALSE ); +#line 1782 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1785 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(bGibs && m_bRobotBlowup ) +#line 1786 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1788 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Debris_Begin (EIBT_ROBOT , DPR_SMOKETRAIL , BET_EXPLOSIONSTAIN , m_fBlowUpSize , vNormalizedDamage , vBodySpeed , 1.0f , 0.0f); +#line 1789 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +for(INDEX iDebris = 0;iDebris < m_fBodyParts ;iDebris ++){ +#line 1790 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Debris_Spawn (this , this , MODEL_MACHINE , TEXTURE_MACHINE , 0 , 0 , 0 , IRnd () % 4 , 0.2f , +#line 1791 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 1792 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1794 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CPlacement3D plExplosion = GetPlacement (); +#line 1795 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntityPointer penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 1796 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ESpawnEffect eSpawnEffect ; +#line 1797 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1798 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSpawnEffect . betType = BET_BOMB ; +#line 1799 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fSize = m_fBlowUpSize * 0.3f; +#line 1800 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSpawnEffect . vStretch = FLOAT3D (fSize , fSize , fSize ); +#line 1801 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1802 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1805 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SwitchToEditorModel (); +#line 1806 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 1807 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 1808 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::LeaveStain(BOOL bGrow) +#line 1817 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1818 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ESpawnEffect ese ; +#line 1819 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vPoint ; +#line 1820 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOATplane3D vPlaneNormal ; +#line 1821 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fDistanceToEdge ; +#line 1823 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOATaabbox3D box ; +#line 1824 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetBoundingBox (box ); +#line 1827 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )){ +#line 1829 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 0.5f +#line 1830 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +&& (m_vLastStain - vPoint ) . Length () > 1.0f){ +#line 1831 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vLastStain = vPoint ; +#line 1832 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fStretch = box . Size () . Length (); +#line 1833 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1835 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(bGrow ){ +#line 1836 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ese . betType = BET_BLOODSTAINGROW ; +#line 1837 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ese . vStretch = FLOAT3D (fStretch * 1.5f , fStretch * 1.5f , 1.0f); +#line 1838 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1839 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ese . betType = BET_BLOODSTAIN ; +#line 1840 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ese . vStretch = FLOAT3D (fStretch * 0.75f , fStretch * 0.75f , 1.0f); +#line 1841 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1842 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1843 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ese . vDirection = FLOAT3D (0 , 0 , 0); +#line 1844 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vPos = vPoint + ese . vNormal / 50.0f * (FRnd () + 0.5f); +#line 1845 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntityPointer penEffect = CreateEntity (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0)) , CLASS_BASIC_EFFECT ); +#line 1846 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penEffect -> Initialize (ese ); +#line 1847 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1848 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1849 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::AdjustDifficulty(void) +#line 1852 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1853 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fMoveSpeed = GetSP () -> sp_fEnemyMovementSpeed ; +#line 1854 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fAttackSpeed = GetSP () -> sp_fEnemyMovementSpeed ; +#line 1857 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fAttackRunSpeed *= fMoveSpeed ; +#line 1858 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aAttackRotateSpeed *= fMoveSpeed ; +#line 1859 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fCloseRunSpeed *= fMoveSpeed ; +#line 1860 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aCloseRotateSpeed *= fMoveSpeed ; +#line 1861 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fAttackFireTime *= 1 / fAttackSpeed ; +#line 1862 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fCloseFireTime *= 1 / fAttackSpeed ; +#line 1877 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1885 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::WoundedNotify(const EDamage & eDamage) +#line 1886 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1888 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penEnemy == NULL ){ +#line 1890 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 1891 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1894 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(eDamage . dmtType != DMT_CLOSERANGE && eDamage . dmtType != DMT_CHAINSAW ){ +#line 1896 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ESound eSound ; +#line 1897 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSound . EsndtSound = SNDT_YELL ; +#line 1898 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSound . penTarget = m_penEnemy ; +#line 1899 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SendEventInRange (eSound , FLOATaabbox3D (GetPlacement () . pl_PositionVector , 25.0f)); +#line 1900 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1901 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1904 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::SeeNotify() +#line 1905 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1907 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penEnemy == NULL ){ +#line 1909 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 1910 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1912 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ESound eSound ; +#line 1913 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSound . EsndtSound = SNDT_SHOUT ; +#line 1914 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eSound . penTarget = m_penEnemy ; +#line 1915 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SendEventInRange (eSound , FLOATaabbox3D (GetPlacement () . pl_PositionVector , 50.0f)); +#line 1916 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::StandingAnim(void) {} + void CEnemyBase::StandingAnimFight(void) {StandingAnim ();} + void CEnemyBase::WalkingAnim(void) {} + void CEnemyBase::RunningAnim(void) {} + void CEnemyBase::RotatingAnim(void) {} + void CEnemyBase::ChargeAnim(void) {} + INDEX CEnemyBase::AnimForDamage(FLOAT fDamage) {return 0;} + void CEnemyBase::BlowUpNotify(void) {} + INDEX CEnemyBase::AnimForDeath(void) {return 0;} + FLOAT CEnemyBase::WaitForDust(FLOAT3D & vStretch) {return - 1;} + void CEnemyBase::DeathNotify(void) {} + void CEnemyBase::IdleSound(void) {} + void CEnemyBase::SightSound(void) {} + void CEnemyBase::WoundSound(void) {} + void CEnemyBase::DeathSound(void) {} + FLOAT CEnemyBase::GetLockRotationSpeed(void) {return 2000.0f;} + +#line 1942 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::RenderParticles(void) { +#line 1944 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(GetRenderType () != CEntity :: RT_MODEL && GetRenderType () != CEntity :: RT_SKAMODEL ){ +#line 1945 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return ; +#line 1946 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1948 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_fSpiritStartTime != 0.0f) +#line 1949 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1952 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Particles_Death (this , m_fSpiritStartTime ); +#line 1953 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1954 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + void CEnemyBase::EnemyPostInit(void) {} + +#line 1960 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::HandleEvent(const CEntityEvent & ee) +#line 1961 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1962 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(ee . ee_slEvent == EVENTCODE_ETouch ) +#line 1963 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1964 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(GetCrushHealth () != 0.0f) +#line 1965 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1966 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ETouch eTouch = ((ETouch &) ee ); +#line 1967 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsOfClass (eTouch . penOther , "ModelHolder2") || +#line 1968 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +IsOfClass (eTouch . penOther , "MovingBrush") || +#line 1969 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +IsOfClass (eTouch . penOther , "DestroyableArchitecture")) +#line 1970 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1971 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +InflictDirectDamage (eTouch . penOther , this , DMT_EXPLOSION , GetCrushHealth () , +#line 1972 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eTouch . penOther -> GetPlacement () . pl_PositionVector , - (FLOAT3D &) eTouch . plCollision ); +#line 1973 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1974 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1975 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1976 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return CMovableModelEntity :: HandleEvent (ee ); +#line 1977 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1980 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT CEnemyBase::GetAnimLength(int iAnim) +#line 1981 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1982 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(en_RenderType == RT_SKAMODEL ){ +#line 1983 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return GetModelInstance () -> GetAnimLength (iAnim ); +#line 1984 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1985 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return GetModelObject () -> GetAnimLength (iAnim ); +#line 1986 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1987 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 1990 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT CEnemyBase::GetCurrentAnimLength() +#line 1991 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 1992 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(en_RenderType == RT_SKAMODEL ){ +#line 1993 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return 0.5f; +#line 1994 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 1995 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return GetModelObject () -> GetCurrentAnimLength (); +#line 1996 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 1997 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 2000 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CEnemyBase::IsAnimFinished() +#line 2001 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 2002 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(en_RenderType == RT_SKAMODEL ){ +#line 2003 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE ; +#line 2004 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2005 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return GetModelObject () -> IsAnimFinished (); +#line 2006 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2007 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 2010 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT CEnemyBase::GetPassedTime() +#line 2011 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 2012 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(en_RenderType == RT_SKAMODEL ){ +#line 2013 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return 0.0f; +#line 2014 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2015 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return GetModelObject () -> GetPassedTime (); +#line 2016 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2017 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 2019 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D & CEnemyBase::GetModelStretch() +#line 2020 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 2021 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(en_RenderType == RT_SKAMODEL ){ +#line 2022 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return GetModelInstance () -> mi_vStretch ; +#line 2023 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2024 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return GetModelObject () -> mo_Stretch ; +#line 2025 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2026 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 2029 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::StretchModel(FLOAT3D vStretch) +#line 2030 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 2031 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(en_RenderType == RT_SKAMODEL ){ +#line 2032 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetModelInstance () -> StretchModel (vStretch ); +#line 2033 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2034 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetModelObject () -> StretchModel (vStretch ); +#line 2035 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2036 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 2039 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CEnemyBase::StretchSingleModel(FLOAT3D vStretch) +#line 2040 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 2041 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(en_RenderType == RT_SKAMODEL ){ +#line 2042 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetModelInstance () -> StretchSingleModel (vStretch ); +#line 2043 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2044 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetModelObject () -> StretchSingleModel (vStretch ); +#line 2045 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2046 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} + +#line 2050 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SLONG CEnemyBase::GetUsedMemory(void) +#line 2051 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 2053 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SLONG slUsedMemory = sizeof (CEnemyBase ) - sizeof (CMovableModelEntity ) + CMovableModelEntity :: GetUsedMemory (); +#line 2055 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +slUsedMemory += m_strDescription . Length (); +#line 2056 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +slUsedMemory += m_strName . Length (); +#line 2057 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +slUsedMemory += 1 * sizeof (CSoundObject); +#line 2058 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return slUsedMemory ; +#line 2059 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +BOOL CEnemyBase:: +#line 2070 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MoveToDestination(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_MoveToDestination + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::MoveToDestination expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2073 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveFrequency = 0.25f; +#line 2074 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveTime = _pTimer -> CurrentTick () + 45.0f; +#line 2076 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT,0x01360006, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x01360006_MoveToDestination_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360006 +if(!(CalcDistanceInPlaneToDestination () > m_fMoveSpeed * m_fMoveFrequency * 2.0f && +#line 2077 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveTime > _pTimer -> CurrentTick ())){ Jump(STATE_CURRENT,0x01360007, FALSE, EInternal());return TRUE;} +#line 2079 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(m_fMoveFrequency ); +Jump(STATE_CURRENT, 0x01360004, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360004_MoveToDestination_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360004 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 2082 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ULONG ulFlags = SetDesiredMovement (); +#line 2083 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MovementAnimation (ulFlags ); +#line 2084 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2085 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01360005, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 2087 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}return TRUE;}BOOL CEnemyBase::H0x01360005_MoveToDestination_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360005 +Jump(STATE_CURRENT,0x01360006, FALSE, EInternal());return TRUE; +#line 2088 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}BOOL CEnemyBase::H0x01360007_MoveToDestination_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360007 + +#line 2091 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2091 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2095 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MoveToRandomPatrolPosition(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_MoveToRandomPatrolPosition + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::MoveToRandomPatrolPosition expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2098 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(! IsOfClass (m_penMarker , "Enemy Marker")){ +#line 2100 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (FALSE ); +#line 2102 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2102 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2103 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2105 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEnemyMarker * pem = (CEnemyMarker *) & * m_penMarker ; +#line 2108 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fMin = pem -> m_fPatrolAreaInner ; +#line 2109 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fMax = pem -> m_fPatrolAreaOuter ; +#line 2110 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fMin < 0){ +#line 2111 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fMin = 0; +#line 2112 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2113 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(fMax < fMin ){ +#line 2114 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fMax = fMin ; +#line 2115 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2116 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fR = Lerp (fMin , fMax , FRnd ()); +#line 2117 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fA = FRnd () * 360.0f; +#line 2118 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vOffsetDir ; +#line 2119 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetHeadingDirection (fA , vOffsetDir ); +#line 2120 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vDesiredPosition = m_vStartPosition + vOffsetDir * fR ; +#line 2123 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = GetProp (m_fWalkSpeed ); +#line 2124 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = GetProp (m_aWalkRotateSpeed ); +#line 2125 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +WalkingAnim (); +#line 2128 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +STATE_CEnemyBase_MoveToDestination, TRUE; +Jump(STATE_CURRENT, 0x01360009, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360009_MoveToRandomPatrolPosition_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_MoveToDestination, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0136000a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x0136000a_MoveToRandomPatrolPosition_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136000a +const EReturn&__e= (EReturn&)__eeInput; +; +#line 2131 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2131 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2135 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +DoPatrolling(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_DoPatrolling + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::DoPatrolling expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2138 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT,0x01360010, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x01360010_DoPatrolling_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360010 +if(!(TRUE )){ Jump(STATE_CURRENT,0x01360011, FALSE, EInternal());return TRUE;} +#line 2140 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2141 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StandingAnim (); +#line 2143 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(0.5f + FRnd () / 2); +Jump(STATE_CURRENT, 0x0136000c, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x0136000c_DoPatrolling_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136000c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0136000d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x0136000d_DoPatrolling_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136000d +; +#line 2145 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +STATE_CEnemyBase_MoveToRandomPatrolPosition, TRUE; +Jump(STATE_CURRENT, 0x0136000e, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x0136000e_DoPatrolling_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_MoveToRandomPatrolPosition, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0136000f, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x0136000f_DoPatrolling_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136000f +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01360010, FALSE, EInternal());return TRUE; +#line 2146 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}BOOL CEnemyBase::H0x01360011_DoPatrolling_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360011 + ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2150 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BeIdle(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_BeIdle + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::BeIdle expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2153 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetWatcher () -> SendEvent (EStart ()); +#line 2156 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StandingAnim (); +#line 2159 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT,0x01360015, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x01360015_BeIdle_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360015 +if(!(TRUE )){ Jump(STATE_CURRENT,0x01360016, FALSE, EInternal());return TRUE;} +#line 2161 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(Lerp (5.0f , 20.0f , FRnd ())); +Jump(STATE_CURRENT, 0x01360013, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360013_BeIdle_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360013 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01360014, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360014_BeIdle_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360014 +; +#line 2163 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +IdleSound ();Jump(STATE_CURRENT,0x01360015, FALSE, EInternal());return TRUE; +#line 2164 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}BOOL CEnemyBase::H0x01360016_BeIdle_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360016 + ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2168 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ReturnToStartPosition(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_ReturnToStartPosition + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::ReturnToStartPosition expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2170 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_BeIdle, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2212 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MoveThroughMarkers(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_MoveThroughMarkers + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::MoveThroughMarkers expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2215 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetWatcher () -> SendEvent (EStart ()); +#line 2218 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT,0x01360023, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x01360023_MoveThroughMarkers_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360023 +if(!(m_penMarker != NULL && IsOfClass (m_penMarker , "Enemy Marker"))){ Jump(STATE_CURRENT,0x01360024, FALSE, EInternal());return TRUE;} +#line 2219 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEnemyMarker * pem = (CEnemyMarker *) & * m_penMarker ; +#line 2222 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vStartPosition = m_penMarker -> GetPlacement () . pl_PositionVector ; +#line 2224 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fR = FRnd () * pem -> m_fMarkerRange ; +#line 2225 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fA = FRnd () * 360.0f; +#line 2226 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vDesiredPosition = m_vStartPosition + FLOAT3D (CosFast (fA ) * fR , 0 , SinFast (fA ) * fR ); +#line 2228 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(pem -> m_betRunToMarker == BET_TRUE ){ +#line 2230 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = GetProp (m_fAttackRunSpeed ); +#line 2231 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = GetProp (m_aAttackRotateSpeed ); +#line 2233 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +RunningAnim (); +#line 2235 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2237 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = GetProp (m_fWalkSpeed ); +#line 2238 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = GetProp (m_aWalkRotateSpeed ); +#line 2240 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +WalkingAnim (); +#line 2241 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2244 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +STATE_CEnemyBase_MoveToDestination, TRUE; +Jump(STATE_CURRENT, 0x01360019, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360019_MoveThroughMarkers_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360019 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_MoveToDestination, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0136001a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x0136001a_MoveThroughMarkers_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136001a +const EReturn&__e= (EReturn&)__eeInput; +; +#line 2247 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEnemyMarker * pem = (CEnemyMarker *) & * m_penMarker ; +#line 2248 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetBoolFromBoolEType (m_bBlind , pem -> m_betBlind ); +#line 2249 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetBoolFromBoolEType (m_bDeaf , pem -> m_betDeaf ); +#line 2252 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(pem -> m_bStartTactics ){ +#line 2254 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bBlind = FALSE ; +#line 2255 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bDeaf = FALSE ; +#line 2257 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StartTacticsNow (); +#line 2258 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2261 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(!(pem -> m_fPatrolTime > 0.0f)){ Jump(STATE_CURRENT,0x0136001d, FALSE, EInternal());return TRUE;} +#line 2263 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SpawnReminder (this , pem -> m_fPatrolTime , 0); +#line 2265 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x0136001b, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x0136001b_MoveThroughMarkers_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136001b +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 2269 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_DoPatrolling, TRUE, EVoid());return TRUE; +#line 2270 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReminder):{const EReminder&e= (EReminder&)__eeInput; + +#line 2274 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +UnsetTimer();Jump(STATE_CURRENT,0x0136001c, FALSE, EInternal());return TRUE; +#line 2275 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 2276 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}return TRUE;}BOOL CEnemyBase::H0x0136001c_MoveThroughMarkers_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136001c +Jump(STATE_CURRENT,0x0136001d, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x0136001d_MoveThroughMarkers_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136001d + +#line 2279 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEnemyMarker * pem = (CEnemyMarker *) & * m_penMarker ; +#line 2281 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(!(pem -> m_fWaitTime > 0.0f)){ Jump(STATE_CURRENT,0x01360020, FALSE, EInternal());return TRUE;} +#line 2283 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2284 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StandingAnim (); +#line 2286 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(pem -> m_fWaitTime ); +Jump(STATE_CURRENT, 0x0136001e, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x0136001e_MoveThroughMarkers_06(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136001e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0136001f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x0136001f_MoveThroughMarkers_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136001f +;Jump(STATE_CURRENT,0x01360020, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x01360020_MoveThroughMarkers_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360020 + +#line 2290 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x01360021, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360021_MoveThroughMarkers_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360021 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01360022, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360022_MoveThroughMarkers_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360022 +; +#line 2293 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penMarker = ((CEnemyMarker &) * m_penMarker ) . m_penTarget ;Jump(STATE_CURRENT,0x01360023, FALSE, EInternal());return TRUE; +#line 2294 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}BOOL CEnemyBase::H0x01360024_MoveThroughMarkers_12(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360024 + +#line 2297 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2298 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StandingAnim (); +#line 2301 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2301 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2310 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +NewEnemySpotted(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_NewEnemySpotted + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::NewEnemySpotted expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2313 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT tmReflex = Lerp (m_tmReflexMin , m_tmReflexMax , FRnd ()); +#line 2314 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +tmReflex = ClampDn (tmReflex , 0.0f); +#line 2317 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(!(tmReflex >= _pTimer -> TickQuantum )){ Jump(STATE_CURRENT,0x01360028, FALSE, EInternal());return TRUE;} +#line 2319 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2320 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StandingAnim (); +#line 2323 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(tmReflex ); +Jump(STATE_CURRENT, 0x01360026, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360026_NewEnemySpotted_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360026 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01360027, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDamage):{const EDamage&e= (EDamage&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_EHitBySpaceShipBeam):{const EHitBySpaceShipBeam&e= (EHitBySpaceShipBeam&)__eeInput; +return FALSE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 2331 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}return TRUE;}BOOL CEnemyBase::H0x01360027_NewEnemySpotted_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360027 +Jump(STATE_CURRENT,0x01360028, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x01360028_NewEnemySpotted_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360028 + +#line 2335 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SightSound (); +#line 2338 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2338 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2342 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_StopAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::StopAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2344 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetWatcher () -> SendEvent (EStart ()); +#line 2346 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTargetNone (); +#line 2347 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fDamageConfused = 0.0f; +#line 2349 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2351 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2351 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2355 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +InitializeAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_InitializeAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::InitializeAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2358 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bBlind = FALSE ; +#line 2359 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bDeaf = FALSE ; +#line 2361 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SeeNotify (); +#line 2362 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetWatcher () -> SendEvent (EStop ()); +#line 2364 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +AddToFuss (); +#line 2366 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vPlayerSpotted = PlayerDestinationPos (); +#line 2369 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(CalcDist (m_penEnemy ) < GetProp (m_fCloseDistance )){ +#line 2370 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fShootTime = 0.0f; +#line 2371 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2372 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fShootTime = _pTimer -> CurrentTick () + FRnd (); +#line 2373 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2374 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fDamageConfused = m_fDamageWounded ; +#line 2376 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2376 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2381 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +AttackEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_AttackEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::AttackEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2383 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +STATE_CEnemyBase_InitializeAttack, TRUE; +Jump(STATE_CURRENT, 0x0136002c, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x0136002c_AttackEnemy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136002c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_InitializeAttack, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0136002d, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x0136002d_AttackEnemy_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136002d +const EReturn&__e= (EReturn&)__eeInput; +; +#line 2386 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT,0x01360030, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x01360030_AttackEnemy_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360030 +if(!(m_penEnemy != NULL )){ Jump(STATE_CURRENT,0x01360031, FALSE, EInternal());return TRUE;} +#line 2388 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +STATE_CEnemyBase_PerformAttack, TRUE; +Jump(STATE_CURRENT, 0x0136002e, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x0136002e_AttackEnemy_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136002e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_PerformAttack, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0136002f, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x0136002f_AttackEnemy_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136002f +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01360030, FALSE, EInternal());return TRUE; +#line 2389 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}BOOL CEnemyBase::H0x01360031_AttackEnemy_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360031 + +#line 2392 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +STATE_CEnemyBase_StopAttack, TRUE; +Jump(STATE_CURRENT, 0x01360032, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360032_AttackEnemy_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360032 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_StopAttack, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01360033, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360033_AttackEnemy_08(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360033 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 2395 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EBegin ()); +#line 2395 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2399 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PerformAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_PerformAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::PerformAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2402 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fRangeLast = 1E9f; +#line 2405 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vDesiredPosition = PlayerDestinationPos (); +#line 2406 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERCURRENT ; +#line 2409 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT,0x01360037, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x01360037_PerformAttack_03(const CEntityEvent &__eeInput) +#line 2410 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360037 +if(!(TRUE )){ Jump(STATE_CURRENT,0x01360038, FALSE, EInternal());return TRUE;} +#line 2412 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(ShouldCeaseAttack ()){ +#line 2414 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTargetNone (); +#line 2415 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2415 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2416 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2419 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fEnemyDistance = CalcDist (m_penEnemy ); +#line 2421 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_fRangeLast > GetProp (m_fCloseDistance ) && fEnemyDistance <= GetProp (m_fCloseDistance )){ +#line 2423 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fShootTime = 0.0f; +#line 2424 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2425 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fRangeLast = fEnemyDistance ; +#line 2428 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveFrequency = GetAttackMoveFrequency (fEnemyDistance ); +#line 2429 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_dtDestination == DT_PATHPERSISTENT || m_dtDestination == DT_PATHTEMPORARY ){ +#line 2430 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveFrequency = 0.1f; +#line 2431 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2434 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(m_fMoveFrequency ); +Jump(STATE_CURRENT, 0x01360035, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360035_PerformAttack_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360035 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01360036, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 2440 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(_pTimer -> CurrentTick () > m_fShootTime ){ +#line 2443 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * penNewEnemy = GetWatcher () -> CheckCloserPlayer (m_penEnemy , GetThreatDistance ()); +#line 2444 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(penNewEnemy != NULL ){ +#line 2446 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTargetHardForce (penNewEnemy ); +#line 2448 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SendEvent (EReconsiderBehavior ()); +#line 2449 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +UnsetTimer();Jump(STATE_CURRENT,0x01360036, FALSE, EInternal());return TRUE; +#line 2450 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2453 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsVisible (m_penEnemy )){ +#line 2455 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vPlayerSpotted = PlayerDestinationPos (); +#line 2457 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_dtDestination == DT_PLAYERSPOTTED || m_dtDestination == DT_PATHTEMPORARY ){ +#line 2459 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERCURRENT ; +#line 2460 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2463 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2465 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_dtDestination == DT_PLAYERCURRENT ){ +#line 2467 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERSPOTTED ; +#line 2468 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2469 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2472 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_FireOrHit, TRUE, EVoid());return TRUE; +#line 2475 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2477 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if((m_dtDestination == DT_PLAYERSPOTTED || m_dtDestination == DT_PATHTEMPORARY ) +#line 2478 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +&& IsVisible (m_penEnemy )){ +#line 2480 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERCURRENT ; +#line 2482 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vPlayerSpotted = PlayerDestinationPos (); +#line 2483 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2484 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2487 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fAllowedError = m_fMoveSpeed * m_fMoveFrequency * 2.0f; +#line 2488 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_dtDestination == DT_PATHPERSISTENT || m_dtDestination == DT_PATHTEMPORARY ){ +#line 2489 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +fAllowedError = ((CNavigationMarker &) * m_penPathMarker ) . m_fMarkerRange ; +#line 2490 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2491 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_dtDestination != DT_PLAYERCURRENT && +#line 2492 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +(CalcDistanceInPlaneToDestination () < fAllowedError || fAllowedError < 0.1f)){ +#line 2494 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_dtDestination == DT_PLAYERSPOTTED ){ +#line 2496 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsVisible (m_penEnemy )){ +#line 2498 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PLAYERCURRENT ; +#line 2500 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2502 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_dtDestination = DT_PATHTEMPORARY ; +#line 2503 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StartPathFinding (); +#line 2504 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2506 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(m_dtDestination == DT_PATHTEMPORARY || m_dtDestination == DT_PATHPERSISTENT ){ +#line 2508 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FindNextPathMarker (); +#line 2509 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2510 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2513 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_dtDestination == DT_PLAYERCURRENT ){ +#line 2515 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vDesiredPosition = PlayerDestinationPos (); +#line 2518 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(m_dtDestination == DT_PLAYERSPOTTED ){ +#line 2520 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vDesiredPosition = m_vPlayerSpotted ; +#line 2521 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2524 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vPosDelta = m_vDesiredPosition - GetPlacement () . pl_PositionVector ; +#line 2525 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fPosDistance = vPosDelta . Length (); +#line 2527 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetSpeedsToDesiredPosition (vPosDelta , fPosDistance , m_dtDestination == DT_PLAYERCURRENT ); +#line 2530 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ULONG ulFlags = SetDesiredMovement (); +#line 2531 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MovementAnimation (ulFlags ); +#line 2532 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2533 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&eTouch= (ETouch&)__eeInput; + +#line 2536 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IfTargetCrushed (eTouch . penOther , (FLOAT3D &) eTouch . plCollision )) +#line 2537 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 2538 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2539 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2541 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +else if(CheckTouchForPathFinding (eTouch )){ +#line 2543 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +UnsetTimer();Jump(STATE_CURRENT,0x01360036, FALSE, EInternal());return TRUE; +#line 2545 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(m_bTacticActive ){ +#line 2547 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(eTouch . penOther -> GetRenderType () == CEntity :: RT_BRUSH ){ +#line 2548 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vDir = en_vDesiredTranslationRelative ; +#line 2549 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDir . SafeNormalize (); +#line 2550 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vDir *= GetRotationMatrix (); +#line 2552 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if((eTouch . plCollision % vDir ) < - 0.5f){m_bTacticActive = 0;} +#line 2553 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2554 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2555 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2556 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2557 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2559 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE; +#line 2560 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2561 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EWouldFall):{const EWouldFall&eWouldFall= (EWouldFall&)__eeInput; + +#line 2565 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(CheckFallForPathFinding (eWouldFall )){ +#line 2567 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +UnsetTimer();Jump(STATE_CURRENT,0x01360036, FALSE, EInternal());return TRUE; +#line 2568 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(m_bTacticActive ){ +#line 2570 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bTacticActive = 0; +#line 2571 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2573 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2575 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE; +#line 2576 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2577 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ESound):{const ESound&e= (ESound&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EWatch):{const EWatch&e= (EWatch&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01360036, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 2581 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}return TRUE;}BOOL CEnemyBase::H0x01360036_PerformAttack_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360036 +Jump(STATE_CURRENT,0x01360037, FALSE, EInternal());return TRUE; +#line 2582 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}BOOL CEnemyBase::H0x01360038_PerformAttack_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360038 + ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2587 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FireOrHit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_FireOrHit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::FireOrHit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2590 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(!(CalcDist (m_penEnemy ) < GetProp (m_fCloseDistance ) && CanHitEnemy (m_penEnemy , Cos (AngleDeg (45.0f))))){ Jump(STATE_CURRENT,0x01360041, FALSE, EInternal());return TRUE;} +#line 2592 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +AddToFuss (); +#line 2594 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2596 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fShootTime = _pTimer -> CurrentTick () + GetProp (m_fCloseFireTime ) * (1.0f + FRnd () / 3.0f); +#line 2598 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +STATE_CEnemyBase_Hit, TRUE; +Jump(STATE_CURRENT, 0x0136003a, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x0136003a_FireOrHit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136003a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_Hit, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0136003b, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x0136003b_FireOrHit_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136003b +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01360040, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x01360041_FireOrHit_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360041 +if(!(CalcDist (m_penEnemy ) < GetProp (m_fAttackDistance ) && CanAttackEnemy (m_penEnemy , Cos (AngleDeg (45.0f))))){ Jump(STATE_CURRENT,0x0136003f, FALSE, EInternal());return TRUE;} +#line 2603 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +AddToFuss (); +#line 2605 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2607 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(CalcDist (m_penEnemy ) < GetProp (m_fCloseDistance )){ +#line 2608 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fShootTime = _pTimer -> CurrentTick () + GetProp (m_fCloseFireTime ) * (1.0f + FRnd () / 3.0f); +#line 2609 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2610 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fShootTime = _pTimer -> CurrentTick () + GetProp (m_fAttackFireTime ) * (1.0f + FRnd () / 3.0f); +#line 2611 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2613 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +STATE_CEnemyBase_Fire, TRUE; +Jump(STATE_CURRENT, 0x0136003c, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x0136003c_FireOrHit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136003c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_Fire, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0136003d, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x0136003d_FireOrHit_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136003d +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x0136003e, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x0136003f_FireOrHit_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136003f +{ +#line 2618 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fShootTime = _pTimer -> CurrentTick () + 0.25f; +#line 2619 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}Jump(STATE_CURRENT,0x0136003e, FALSE, EInternal());return TRUE;} +BOOL CEnemyBase::H0x0136003e_FireOrHit_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136003e +Jump(STATE_CURRENT,0x01360040, FALSE, EInternal());return TRUE;} +BOOL CEnemyBase::H0x01360040_FireOrHit_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360040 + +#line 2622 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2622 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2630 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2632 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2632 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2636 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2638 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2638 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2646 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +LockOnEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_LockOnEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::LockOnEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2649 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2651 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ChargeAnim (); +#line 2653 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fLockStartTime = _pTimer -> CurrentTick (); +#line 2654 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT,0x01360047, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x01360047_LockOnEnemy_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360047 +if(!(m_fLockStartTime + GetProp (m_fLockOnEnemyTime ) > _pTimer -> CurrentTick ())){ Jump(STATE_CURRENT,0x01360048, FALSE, EInternal());return TRUE;} +#line 2656 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveFrequency = 0.05f; +#line 2657 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(m_fMoveFrequency ); +Jump(STATE_CURRENT, 0x01360045, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360045_LockOnEnemy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360045 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01360046, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 2660 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vDesiredPosition = PlayerDestinationPos (); +#line 2662 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(! IsInPlaneFrustum (m_penEnemy , CosFast (5.0f))){ +#line 2663 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = 0.0f; +#line 2664 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = GetLockRotationSpeed (); +#line 2666 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2667 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fMoveSpeed = 0.0f; +#line 2668 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_aRotateSpeed = 0.0f; +#line 2669 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2671 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ULONG ulFlags = SetDesiredMovement (); +#line 2673 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2674 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 2675 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}return TRUE;}BOOL CEnemyBase::H0x01360046_LockOnEnemy_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360046 +Jump(STATE_CURRENT,0x01360047, FALSE, EInternal());return TRUE; +#line 2676 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}BOOL CEnemyBase::H0x01360048_LockOnEnemy_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360048 + +#line 2678 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopRotating (); +#line 2681 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2681 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2685 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ChargeHitEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_ChargeHitEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::ChargeHitEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2688 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(GetAnimLength (m_iChargeHitAnimation )); +Jump(STATE_CURRENT, 0x0136004a, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x0136004a_ChargeHitEnemy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136004a +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x0136004b, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDamage):{const EDamage&e= (EDamage&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EReminder):{const EReminder&e= (EReminder&)__eeInput; + +#line 2696 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2697 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2698 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 2702 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if((etouch . penOther -> GetFlags () & ENF_ALIVE ) && IsInPlaneFrustum (etouch . penOther , CosFast (60.0f))){ +#line 2704 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vSpeed ; +#line 2705 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetHeadingDirection (m_fChargeHitAngle , vSpeed ); +#line 2707 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +InflictDirectDamage (etouch . penOther , this , DMT_CLOSERANGE , m_fChargeHitDamage , FLOAT3D (0 , 0 , 0) , vSpeed ); +#line 2709 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +vSpeed = vSpeed * m_fChargeHitSpeed ; +#line 2710 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +KickEntity (etouch . penOther , vSpeed ); +#line 2712 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +UnsetTimer();Jump(STATE_CURRENT,0x0136004b, FALSE, EInternal());return TRUE; +#line 2713 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2714 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE; +#line 2715 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 2716 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}return TRUE;}BOOL CEnemyBase::H0x0136004b_ChargeHitEnemy_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136004b + +#line 2718 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(!(! IsAnimFinished ())){ Jump(STATE_CURRENT,0x0136004e, FALSE, EInternal());return TRUE;} +#line 2720 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(GetCurrentAnimLength () - GetPassedTime ()); +Jump(STATE_CURRENT, 0x0136004c, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x0136004c_ChargeHitEnemy_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136004c +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x0136004d, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EReminder):{const EReminder&e= (EReminder&)__eeInput; + +#line 2726 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2727 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2728 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 2729 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}return TRUE;}BOOL CEnemyBase::H0x0136004d_ChargeHitEnemy_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136004d +Jump(STATE_CURRENT,0x0136004e, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x0136004e_ChargeHitEnemy_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136004e + +#line 2733 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2733 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2741 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BeWounded(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_BeWounded + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDamage, "CEnemyBase::BeWounded expects 'EDamage' as input!"); const EDamage &eDamage = (const EDamage &)__eeInput; +#line 2743 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2745 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(GetAnimLength (AnimForDamage (eDamage . fAmount ))); +Jump(STATE_CURRENT, 0x01360050, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360050_BeWounded_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360050 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01360051, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360051_BeWounded_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360051 +; +#line 2746 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 2746 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2750 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Die(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_Die + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDeath, "CEnemyBase::Die expects 'EDeath' as input!"); const EDeath &eDeath = (const EDeath &)__eeInput; +#line 2753 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetFlags (GetFlags () & ~ ENF_ALIVE ); +#line 2756 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntityPointer penKiller = eDeath . eLastDamage . penInflictor ; +#line 2757 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(penKiller == NULL || ! IsOfClass (penKiller , "Player")){ +#line 2758 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penKiller = m_penEnemy ; +#line 2759 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2761 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(penKiller == NULL || ! IsOfClass (penKiller , "Player")){ +#line 2762 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penKiller = FixupCausedToPlayer (this , penKiller , FALSE ); +#line 2763 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2766 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(penKiller != NULL ){ +#line 2768 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +EReceiveScore eScore ; +#line 2769 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eScore . iPoints = m_iScore ; +#line 2770 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penKiller -> SendEvent (eScore ); +#line 2771 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(CountAsKill ()) +#line 2772 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 2773 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penKiller -> SendEvent (EKilledEnemy ()); +#line 2774 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2776 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(GetSP () -> sp_bCooperative ){ +#line 2777 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +EComputerMessage eMsg ; +#line 2778 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eMsg . fnmMessage = GetComputerMessageName (); +#line 2779 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(eMsg . fnmMessage != ""){ +#line 2780 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penKiller -> SendEvent (eMsg ); +#line 2781 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2782 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2783 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2787 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetWatcher () -> SendEvent (EStop ()); +#line 2788 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetWatcher () -> SendEvent (EEnd ()); +#line 2791 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SendToTarget (m_penDeathTarget , m_eetDeathType , penKiller ); +#line 2794 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penSpawnerTarget ){ +#line 2795 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SendToTarget (m_penSpawnerTarget , EET_TRIGGER , this ); +#line 2796 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2800 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01360053, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360053_Die_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360053 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 2804 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(ShouldBlowUp ()){ +#line 2806 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BlowUpBase (); +#line 2808 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +UnsetTimer();Jump(STATE_CURRENT,0x01360054, FALSE, EInternal());return TRUE; +#line 2810 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2812 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_DeathSequence, TRUE, EVoid());return TRUE; +#line 2813 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2814 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDamage):{const EDamage&e= (EDamage&)__eeInput; + +#line 2818 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(ShouldBlowUp ()){ +#line 2820 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BlowUpBase (); +#line 2822 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +UnsetTimer();Jump(STATE_CURRENT,0x01360054, FALSE, EInternal());return TRUE; +#line 2823 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2825 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2826 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnd):{const EEnd&e= (EEnd&)__eeInput; + +#line 2830 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +UnsetTimer();Jump(STATE_CURRENT,0x01360054, FALSE, EInternal());return TRUE; +#line 2831 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 2832 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}return TRUE;}BOOL CEnemyBase::H0x01360054_Die_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360054 + +#line 2835 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +RemoveFromFuss (); +#line 2837 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Destroy (); +#line 2840 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EVoid()); +#line 2840 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2843 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Death(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_Death + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::Death expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2845 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 2846 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +DeathSound (); +#line 2847 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +LeaveStain (FALSE ); +#line 2850 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetPhysicsFlags (EPF_MODEL_CORPSE ); +#line 2851 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetCollisionFlags (ECF_CORPSE ); +#line 2852 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 2855 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +RemoveFromFuss (); +#line 2858 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +DeathNotify (); +#line 2861 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +INDEX iAnim = AnimForDeath (); +#line 2863 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vTacticsStartPosition = FLOAT3D (1 , 1 , 1); +#line 2864 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar4 = WaitForDust (m_vTacticsStartPosition ); +#line 2866 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar5 = _pTimer -> CurrentTick (); +#line 2868 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar3 = - 1; +#line 2870 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(!(m_fTacticVar4 < 0)){ Jump(STATE_CURRENT,0x0136005e, FALSE, EInternal());return TRUE;} +#line 2872 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(GetAnimLength (iAnim )); +Jump(STATE_CURRENT, 0x01360056, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360056_Death_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360056 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01360057, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360057_Death_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360057 +;Jump(STATE_CURRENT,0x0136005d, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x0136005e_Death_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136005e +if(!(TRUE )){ Jump(STATE_CURRENT,0x0136005c, FALSE, EInternal());return TRUE;} +#line 2877 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT,0x0136005a, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x0136005a_Death_05(const CEntityEvent &__eeInput) +#line 2878 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136005a +if(!(_pTimer -> CurrentTick () < m_fTacticVar5 + GetCurrentAnimLength ())){ Jump(STATE_CURRENT,0x0136005b, FALSE, EInternal());return TRUE;} +#line 2879 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01360058, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360058_Death_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360058 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01360059, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360059_Death_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360059 +; +#line 2880 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(en_penReference != NULL && _pTimer -> CurrentTick () >= m_fTacticVar5 + m_fTacticVar4 && m_fTacticVar3 < 0) +#line 2881 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 2883 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CPlacement3D plFX = GetPlacement (); +#line 2884 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ESpawnEffect ese ; +#line 2885 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 2886 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ese . vStretch = m_vTacticsStartPosition ; +#line 2887 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ese . vNormal = FLOAT3D (0 , 1 , 0); +#line 2888 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ese . betType = BET_DUST_FALL ; +#line 2889 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CPlacement3D plSmoke = plFX ; +#line 2890 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +plSmoke . pl_PositionVector += FLOAT3D (0 , 0.35f * m_vTacticsStartPosition (2) , 0); +#line 2891 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntityPointer penFX = CreateEntity (plSmoke , CLASS_BASIC_EFFECT ); +#line 2892 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penFX -> Initialize (ese ); +#line 2893 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penFX -> SetParent (this ); +#line 2895 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fTacticVar3 = 1; +#line 2896 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}Jump(STATE_CURRENT,0x0136005a, FALSE, EInternal());return TRUE; +#line 2897 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}BOOL CEnemyBase::H0x0136005b_Death_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136005b +Jump(STATE_CURRENT,0x0136005c, FALSE, EInternal());return TRUE;}BOOL CEnemyBase::H0x0136005c_Death_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136005c +Jump(STATE_CURRENT,0x0136005d, FALSE, EInternal());return TRUE;} +BOOL CEnemyBase::H0x0136005d_Death_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136005d + +#line 2900 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EEnd ()); +#line 2900 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2903 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +DeathSequence(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_DeathSequence + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::DeathSequence expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2906 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +STATE_CEnemyBase_Death, TRUE; +Jump(STATE_CURRENT, 0x01360060, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360060_DeathSequence_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360060 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_Death, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01360061, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360061_DeathSequence_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360061 +const EEnd&__e= (EEnd&)__eeInput; +; +#line 2909 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +LeaveStain (TRUE ); +#line 2912 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntityPointer penFlame = GetChildOfClass ("Flame"); +#line 2913 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(penFlame != NULL ) +#line 2914 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{ +#line 2916 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +EStopFlaming esf ; +#line 2917 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +esf . m_bNow = FALSE ; +#line 2918 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +penFlame -> SendEvent (esf ); +#line 2919 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2921 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(2.0f); +Jump(STATE_CURRENT, 0x01360062, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360062_DeathSequence_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360062 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01360063, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360063_DeathSequence_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360063 +; +#line 2924 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fSpiritStartTime = _pTimer -> CurrentTick (); +#line 2925 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fFadeStartTime = _pTimer -> CurrentTick (); +#line 2926 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fFadeTime = 1.0f , +#line 2927 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bFadeOut = TRUE ; +#line 2929 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetCollisionFlags (ECF_CORPSE & ~ ((ECBI_PROJECTILE_MAGIC | ECBI_PROJECTILE_SOLID ) << ECB_TEST )); +#line 2931 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(m_fFadeTime ); +Jump(STATE_CURRENT, 0x01360064, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360064_DeathSequence_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360064 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01360065, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360065_DeathSequence_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360065 +; +#line 2933 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(6.0f); +Jump(STATE_CURRENT, 0x01360066, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360066_DeathSequence_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360066 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01360067, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360067_DeathSequence_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360067 +; +#line 2935 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EEnd ()); +#line 2935 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 2942 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Active(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_Active + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::Active expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 2944 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fDamageConfused = 0.0f; +#line 2946 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01360069, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360069_Active_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360069 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 2950 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SendEvent (EReconsiderBehavior ()); +#line 2951 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2952 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReconsiderBehavior):{const EReconsiderBehavior&e= (EReconsiderBehavior&)__eeInput; + +#line 2956 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penEnemy != NULL ){ +#line 2958 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_AttackEnemy, TRUE, EVoid());return TRUE; +#line 2960 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(m_penMarker != NULL ){ +#line 2962 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_MoveThroughMarkers, TRUE, EVoid());return TRUE; +#line 2964 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else if(m_bOnStartPosition ){ +#line 2966 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bOnStartPosition = FALSE ; +#line 2967 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_BeIdle, TRUE, EVoid());return TRUE; +#line 2969 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 2971 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_ReturnToStartPosition, TRUE, EVoid());return TRUE; +#line 2972 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2973 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2974 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; + +#line 2978 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SendEvent (EReconsiderBehavior ()); +#line 2979 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2980 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ERestartAttack):{const ERestartAttack&e= (ERestartAttack&)__eeInput; + +#line 2984 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SendEvent (EReconsiderBehavior ()); +#line 2985 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2986 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EWatch):{const EWatch&eWatch= (EWatch&)__eeInput; + +#line 2990 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(SetTargetSoft (eWatch . penSeen )){ +#line 2992 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bBlind && m_bTacticsStartOnSense ){ +#line 2993 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StartTacticsNow (); +#line 2994 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2996 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_NewEnemySpotted, TRUE, EVoid());return TRUE; +#line 2997 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 2998 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 2999 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDamage):{const EDamage&eDamage= (EDamage&)__eeInput; + +#line 3003 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTargetHard (eDamage . penInflictor ); +#line 3006 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fDamageConfused -= eDamage . fAmount ; +#line 3007 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_fDamageConfused < 0.001f){ +#line 3008 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fDamageConfused = m_fDamageWounded ; +#line 3010 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +WoundedNotify (eDamage ); +#line 3012 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +WoundSound (); +#line 3014 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_BeWounded, TRUE, eDamage );return TRUE; +#line 3015 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3016 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3017 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EForceWound): +#line 3019 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +{const EForceWound&e= (EForceWound&)__eeInput; + +#line 3020 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_BeWounded, TRUE, EDamage ());return TRUE; +#line 3021 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3022 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ESound):{const ESound&eSound= (ESound&)__eeInput; + +#line 3026 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bDeaf ){ +#line 3028 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3029 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3032 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsVisible (eSound . penTarget ) && SetTargetSoft (eSound . penTarget )){ +#line 3034 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_NewEnemySpotted, TRUE, EVoid());return TRUE; +#line 3035 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3036 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3037 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&eTouch= (ETouch&)__eeInput; + +#line 3041 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL bTargetChanged = SetTargetHard (eTouch . penOther ); +#line 3043 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(bTargetChanged ){ +#line 3045 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SightSound (); +#line 3047 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SendEvent (EReconsiderBehavior ()); +#line 3048 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3049 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return FALSE; +#line 3050 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 3053 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * penCaused = FixupCausedToPlayer (this , eTrigger . penCaused ); +#line 3055 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(SetTargetSoft (penCaused )){ +#line 3057 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SightSound (); +#line 3059 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SendEvent (EReconsiderBehavior ()); +#line 3060 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3061 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3062 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 3065 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Inactive, TRUE, EVoid());return TRUE; +#line 3066 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStartAttack):{const EStartAttack&e= (EStartAttack&)__eeInput; + +#line 3071 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3072 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStopAttack):{const EStopAttack&e= (EStopAttack&)__eeInput; + +#line 3075 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3076 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 3077 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}return TRUE;}BOOL CEnemyBase::H0x0136006a_Active_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136006a + ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 3081 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Inactive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_Inactive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::Inactive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3084 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopMoving (); +#line 3085 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StandingAnim (); +#line 3087 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetWatcher () -> SendEvent (EStart ()); +#line 3089 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x0136006c, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x0136006c_Inactive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136006c +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; + +#line 3094 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Active, TRUE, EVoid());return TRUE; +#line 3095 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; + +#line 3099 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Active, TRUE, EVoid());return TRUE; +#line 3100 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 3103 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * penCaused = FixupCausedToPlayer (this , eTrigger . penCaused ); +#line 3105 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(SetTargetSoft (penCaused )){ +#line 3107 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Active, TRUE, EVoid());return TRUE; +#line 3108 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3109 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDamage):{const EDamage&eDamage= (EDamage&)__eeInput; + +#line 3113 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(SetTargetHard (eDamage . penInflictor )){ +#line 3115 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +WoundedNotify (eDamage ); +#line 3117 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +WoundSound (); +#line 3119 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_BeWounded, TRUE, eDamage );return TRUE; +#line 3120 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3121 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EVoid()); +#line 3121 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3122 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 3123 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}return TRUE;}BOOL CEnemyBase::H0x0136006d_Inactive_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0136006d + ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 3127 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PreMainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_PreMainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::PreMainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3129 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EReturn ()); +#line 3129 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 3133 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_MainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::MainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3136 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SizeModel (); +#line 3138 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (m_fMaxHealth == GetHealth () || IsOfClass (this , "Devil") || IsOfClass (this , "ExotechLarva") || IsOfClass (this , "AirElemental") || IsOfClass (this , "Summoner")); +#line 3141 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_tmReflexMin < 0){ +#line 3142 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmReflexMin = 0.0f; +#line 3143 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3144 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_tmReflexMin > m_tmReflexMax ){ +#line 3145 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_tmReflexMax = m_tmReflexMin ; +#line 3146 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3149 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_fStepHeight == - 1){ +#line 3150 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_fStepHeight = 2.0f; +#line 3151 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3154 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_bTemplate ){ +#line 3156 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EVoid()); +#line 3156 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3157 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3166 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01360070, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360070_MainLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360070 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01360071, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360071_MainLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360071 +; +#line 3169 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penWatcher = CreateEntity (GetPlacement () , CLASS_WATCHER ); +#line 3170 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +EWatcherInit eInitWatcher ; +#line 3171 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +eInitWatcher . penOwner = this ; +#line 3172 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetWatcher () -> Initialize (eInitWatcher ); +#line 3175 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penMarker != NULL && IsOfClass (m_penMarker , "Enemy Marker")){ +#line 3176 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEnemyMarker * pem = (CEnemyMarker *) & * m_penMarker ; +#line 3177 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_penMarker = pem -> m_penTarget ; +#line 3178 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3182 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_vStartPosition = GetPlacement () . pl_PositionVector ; +#line 3185 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_soSound . Set3DParameters (80.0f , 5.0f , 1.0f , 1.0f); +#line 3188 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +en_fStepUpHeight = m_fStepHeight + 0.01f; +#line 3189 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +en_fStepDnHeight = m_fFallHeight + 0.01f; +#line 3192 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +EnemyPostInit (); +#line 3195 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +AdjustDifficulty (); +#line 3198 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (m_fStopDistance >= 0); +#line 3199 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (m_fCloseDistance >= 0); +#line 3200 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (m_fAttackDistance > m_fCloseDistance ); +#line 3201 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ASSERT (m_fIgnoreRange > m_fAttackDistance ); +#line 3203 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetPredictable (TRUE ); +#line 3205 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +STATE_CEnemyBase_PreMainLoop, TRUE; +Jump(STATE_CURRENT, 0x01360072, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360072_MainLoop_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360072 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_PreMainLoop, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01360073, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyBase::H0x01360073_MainLoop_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360073 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 3207 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_StandardBehavior, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 3210 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StandardBehavior(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_StandardBehavior + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::StandardBehavior expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3213 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01360075, FALSE, EBegin());return TRUE;}BOOL CEnemyBase::H0x01360075_StandardBehavior_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360075 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 3217 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(m_penEnemy != NULL ){ +#line 3218 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_Active, TRUE, EVoid());return TRUE; +#line 3219 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}else { +#line 3220 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Call(STATE_CURRENT, STATE_CEnemyBase_Inactive, TRUE, EVoid());return TRUE; +#line 3221 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3222 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 3226 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Die, TRUE, eDeath );return TRUE; +#line 3227 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETeleport):{const ETeleport&et= (ETeleport&)__eeInput; + +#line 3231 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +GetWatcher () -> SendEvent (et ); +#line 3232 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3233 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStopBlindness):{const EStopBlindness&e= (EStopBlindness&)__eeInput; + +#line 3237 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bBlind = FALSE ; +#line 3238 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3239 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStopDeafness):{const EStopDeafness&e= (EStopDeafness&)__eeInput; + +#line 3243 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +m_bDeaf = FALSE ; +#line 3244 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3245 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&eTouch= (ETouch&)__eeInput; + +#line 3248 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +IfTargetCrushed (eTouch . penOther , (FLOAT3D &) eTouch . plCollision ); +#line 3249 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +if(IsOfClass (eTouch . penOther , "Bouncer")){ +#line 3250 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +JumpFromBouncer (this , eTouch . penOther ); +#line 3251 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +} +#line 3252 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; +#line 3253 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 3254 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +}return TRUE;}BOOL CEnemyBase::H0x01360076_StandardBehavior_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01360076 + ASSERT(FALSE); return TRUE;};BOOL CEnemyBase:: +#line 3258 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyBase_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyBase::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3259 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Return(STATE_CURRENT,EVoid()); +#line 3259 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EnemyBase.es b/Sources/EntitiesMP/EnemyBase.es new file mode 100644 index 0000000..f1bfda8 --- /dev/null +++ b/Sources/EntitiesMP/EnemyBase.es @@ -0,0 +1,3261 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +310 +%{ +#include "StdH.h" +#include "EntitiesMP/Common/PathFinding.h" +#include "EntitiesMP/NavigationMarker.h" +#include "EntitiesMP/TacticsHolder.h" +extern void JumpFromBouncer(CEntity *penToBounce, CEntity *penBouncer); +extern INDEX ent_bReportBrokenChains; +%} + +uses "EntitiesMP/Watcher"; +uses "EntitiesMP/BasicEffects"; +uses "EntitiesMP/Projectile"; +uses "EntitiesMP/Debris"; +uses "EntitiesMP/EnemyMarker"; +uses "EntitiesMP/MusicHolder"; +uses "EntitiesMP/BloodSpray"; + +event ERestartAttack { +}; + +// self sent in Active loop to reconsider what enemy should do +event EReconsiderBehavior { +}; + +// force wound +event EForceWound { +}; + +enum TargetType { + 0 TT_NONE "", // no target + 1 TT_SOFT "", // soft target - only spoted player but not heavily angry at him + 2 TT_HARD "", // hard target - player has provoked enemy and it is very angry +}; + +enum DestinationType { + 0 DT_PLAYERCURRENT "", // go to where player is now + 1 DT_PLAYERSPOTTED "", // go to where player was last seen + 2 DT_PATHTEMPORARY "", // go to navigation marker - temporary, only until you spot player again + 3 DT_PATHPERSISTENT "", // go to navigation marker - until you really get there +}; + +%{ +#define MF_MOVEZ (1L<<0) +#define MF_ROTATEH (1L<<1) +#define MF_MOVEXZY (1L<<2) +%} + +class export CEnemyBase : CMovableModelEntity { +name "Enemy Base"; +thumbnail ""; +features "HasName", "IsTargetable", "CanBePredictable"; + +properties: + 1 CEntityPointer m_penWatcher, // watcher + 2 FLOAT3D m_vStartPosition = FLOAT3D(0,0,0), // start position + 3 CEntityPointer m_penEnemy, // current enemy + 4 enum TargetType m_ttTarget = TT_NONE, // type of target + 5 CTString m_strDescription = "Enemy base", + 6 CTString m_strName "Name" 'N' = "Enemy base", + 7 CSoundObject m_soSound, + 8 FLOAT3D m_vStartDirection = FLOAT3D(0,0,-1), // for returning to start + 9 BOOL m_bOnStartPosition = TRUE, + 29 FLOAT m_fFallHeight "Fall height" = 8.0f, + 31 FLOAT m_fStepHeight "Step height" = -1.0f, + 17 RANGE m_fSenseRange "Sense Range" = 0.0f, // immediately spots any player that gets closer than this + 28 FLOAT m_fViewAngle "View angle" 'V' = 360.0f, // view frustum angle for spotting players + + // moving/attack properties - CAN BE SET + // these following must be ordered exactly like this for GetProp() to function + 10 FLOAT m_fWalkSpeed = 1.0f, // walk speed + 11 ANGLE m_aWalkRotateSpeed = AngleDeg(10.0f), // walk rotate speed + 12 FLOAT m_fAttackRunSpeed = 1.0f, // attack run speed + 13 ANGLE m_aAttackRotateSpeed = AngleDeg(10.0f), // attack rotate speed + 14 FLOAT m_fCloseRunSpeed = 1.0f, // close run speed + 15 ANGLE m_aCloseRotateSpeed = AngleDeg(10.0f), // close rotate speed + 20 FLOAT m_fAttackDistance = 50.0f, // attack distance mode + 21 FLOAT m_fCloseDistance = 10.0f, // close distance mode + 22 FLOAT m_fAttackFireTime = 2.0f, // attack distance fire time + 23 FLOAT m_fCloseFireTime = 1.0f, // close distance fire time + 24 FLOAT m_fStopDistance = 0.0f, // stop moving toward enemy if closer than stop distance + 25 FLOAT m_fIgnoreRange = 200.0f, // cease attack if enemy farther + 26 FLOAT m_fLockOnEnemyTime = 0.0f, // time needed to fire + + // damage/explode properties - CAN BE SET + 40 FLOAT m_fBlowUpAmount = 0.0f, // damage in minus for blow up + 41 INDEX m_fBodyParts = 4, // number of spawned body parts + 42 FLOAT m_fDamageWounded = 0.0f, // damage amount to be wounded + 43 FLOAT3D m_vDamage = FLOAT3D(0,0,0), // current damage impact + 44 FLOAT m_tmLastDamage = -1000.0f, + 46 BOOL m_bRobotBlowup = FALSE, // set for robots parts blowup, otherwise blowup flesh + 47 FLOAT m_fBlowUpSize = 2.0f, + + // logic temporary variables -> DO NOT USE +133 FLOAT m_fMoveTime = 0.0f, + 52 FLOAT3D m_vDesiredPosition = FLOAT3D(0,0,0), + 53 enum DestinationType m_dtDestination = DT_PLAYERCURRENT, // type of current desired position + 59 CEntityPointer m_penPathMarker, // current path finding marker + 18 FLOAT3D m_vPlayerSpotted = FLOAT3D(0,0,0), // where player was last spotted + 54 FLOAT m_fMoveFrequency = 0.0f, + 55 FLOAT m_fMoveSpeed = 0.0f, + 56 ANGLE m_aRotateSpeed = 0, + 57 FLOAT m_fLockStartTime = 0.0f, + 58 FLOAT m_fRangeLast = 0.0f, +130 BOOL m_bFadeOut = FALSE, +131 FLOAT m_fFadeStartTime = 0.0f, +132 FLOAT m_fFadeTime = 0.0f, + + // attack temporary -> DO NOT USE + 60 FLOAT m_fShootTime = 0.0f, // time when entity will try to shoot on enemy + 61 FLOAT m_fDamageConfused = 0.0f, // damage amount when entity shoot concentration is spoiled + 62 INDEX m_iChargeHitAnimation = 0.0f, // charge hit (close attack) properties + 63 FLOAT m_fChargeHitDamage = 0.0f, + 64 FLOAT m_fChargeHitAngle = 0.0f, + 65 FLOAT m_fChargeHitSpeed = 0.0f, + + // editor variables + 83 CEntityPointer m_penSpawnerTarget, // for re-spawning + 84 CEntityPointer m_penDeathTarget "Death target" 'D', // death target + 85 enum EventEType m_eetDeathType "Death event type" 'F' = EET_TRIGGER, // death event type + 86 BOOL m_bTemplate "Template" = FALSE, // template enemy for spawning new enemies + 88 RANGE m_fAttackRadius "Radius of attack" 'A' = 10000.0f, // attack sphere range radius + 89 COLOR m_colColor "Color" 'L' = 0x00, // color + 90 BOOL m_bDeaf "Deaf" = FALSE, // deaf + 91 BOOL m_bBlind "Blind" = FALSE, // blind + 92 FLOAT m_tmGiveUp "Give up time" = 5.0f, // how fast enemy gives up attack + 93 FLOAT m_tmReflexMin "Reflex Min" = 0.0f, // how much to wait before reacting on spotting the player + 94 FLOAT m_tmReflexMax "Reflex Max" = 0.0f, + 95 FLOAT m_fActivityRange "Activity Range" = 0.0f, + + // random values variables +106 BOOL m_bApplyRandomStretch "Apply random stretch" = FALSE, // apply random stretch +107 FLOAT m_fRandomStretchFactor "Random stretch factor" = 0.1f, // random stretch +108 FLOAT m_fStretchMultiplier "Stretch multiplier" = 1.0f, // stretch multiplier +109 FLOAT m_fRandomStretchMultiplier = 1.0f, // calculated random stretch + + // marker variables +120 CEntityPointer m_penMarker "Marker" 'M' COLOR(C_RED|0xFF), // enemy marker pointer + +// fuss variables +140 CEntityPointer m_penMainMusicHolder, +141 FLOAT m_tmLastFussTime = 0.0f, + +142 FLOAT m_iScore = -100000, // how many points this enemy gives when killed +143 FLOAT m_fMaxHealth = -1.0f, // must set this because of crosshair colorizing +144 BOOL m_bBoss = FALSE, // set for bosses (for health display) + +145 FLOAT m_fSpiritStartTime = 0.0f, // time when spirit effect has started + +146 FLOAT m_tmSpraySpawned = 0.0f, // time when damage has been applied +147 FLOAT m_fSprayDamage = 0.0f, // total ammount of damage +148 CEntityPointer m_penSpray, // the blood spray +149 FLOAT m_fMaxDamageAmmount = 0.0f, // max ammount of damage received in in last few ticks +150 FLOAT3D m_vLastStain = FLOAT3D(0,0,0), // where last stain was left +151 enum SprayParticlesType m_sptType = SPT_BLOOD, // type of particles + +160 CEntityPointer m_penTacticsHolder "Tactics Holder", +161 BOOL m_bTacticActive = FALSE, +162 FLOAT m_tmTacticsActivation = 0.0f, +// warning! tactic variables are also used for dust spawning +163 FLOAT3D m_vTacticsStartPosition = FLOAT3D(0,0,0), +165 FLOAT m_fTacticVar1 = 0.0f, +166 FLOAT m_fTacticVar2 = 0.0f, +167 FLOAT m_fTacticVar3 = 0.0f, +168 FLOAT m_fTacticVar4 = 0.0f, +169 FLOAT m_fTacticVar5 = 0.0f, +170 BOOL m_bTacticsStartOnSense "Tactics start on sense" = FALSE, +180 COLOR m_colBurning = COLOR(C_WHITE|CT_OPAQUE), // color applied when burning + +181 BOOL m_bResizeAttachments "Stretch attachments" = FALSE, // for small enemies with big guns + +//171 INDEX m_iTacticsRetried = 0, + + { + TIME m_tmPredict; // time to predict the entity to + } + + +components: + + 1 class CLASS_WATCHER "Classes\\Watcher.ecl", + 2 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 3 class CLASS_DEBRIS "Classes\\Debris.ecl", + 4 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 5 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + +// ************** FLESH PARTS ************** + 10 model MODEL_FLESH "Models\\Effects\\Debris\\Flesh\\Flesh.mdl", + 11 model MODEL_FLESH_APPLE "Models\\Effects\\Debris\\Fruits\\Apple.mdl", + 12 model MODEL_FLESH_BANANA "Models\\Effects\\Debris\\Fruits\\Banana.mdl", + 13 model MODEL_FLESH_BURGER "Models\\Effects\\Debris\\Fruits\\CheeseBurger.mdl", + 14 model MODEL_FLESH_LOLLY "Models\\Effects\\Debris\\Fruits\\LollyPop.mdl", + 15 model MODEL_FLESH_ORANGE "Models\\Effects\\Debris\\Fruits\\Orange.mdl", + + 20 texture TEXTURE_FLESH_RED "Models\\Effects\\Debris\\Flesh\\FleshRed.tex", + 21 texture TEXTURE_FLESH_GREEN "Models\\Effects\\Debris\\Flesh\\FleshGreen.tex", + 22 texture TEXTURE_FLESH_APPLE "Models\\Effects\\Debris\\Fruits\\Apple.tex", + 23 texture TEXTURE_FLESH_BANANA "Models\\Effects\\Debris\\Fruits\\Banana.tex", + 24 texture TEXTURE_FLESH_BURGER "Models\\Effects\\Debris\\Fruits\\CheeseBurger.tex", + 25 texture TEXTURE_FLESH_LOLLY "Models\\Effects\\Debris\\Fruits\\LollyPop.tex", + 26 texture TEXTURE_FLESH_ORANGE "Models\\Effects\\Debris\\Fruits\\Orange.tex", + +// ************** MACHINE PARTS ************** + 31 model MODEL_MACHINE "Models\\Effects\\Debris\\Stone\\Stone.mdl", + 32 texture TEXTURE_MACHINE "Models\\Effects\\Debris\\Stone\\Stone.tex", + + +functions: + + void CEnemyBase(void) + { + m_tmPredict = 0; + } + + // called by other entities to set time prediction parameter + void SetPredictionTime(TIME tmAdvance) // give time interval in advance to set + { + ASSERT(!IsPredictor()); + m_tmPredict = _pTimer->CurrentTick()+tmAdvance; + } + + // called by engine to get the upper time limit + TIME GetPredictionTime(void) // return moment in time up to which to predict this entity + { + return m_tmPredict; + } + + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("%s killed %s"), GetClass()->ec_pdecDLLClass->dec_strName, strPlayerName); + return str; + } + + virtual FLOAT GetCrushHealth(void) + { + return 0.0f; + } + + // if should be counted as kill + virtual BOOL CountAsKill(void) + { + return TRUE; + } + + virtual BOOL ForcesCannonballToExplode(void) + { + return FALSE; + } + + // overridable function for access to different properties of derived classes (flying/diving) + virtual FLOAT &GetProp(FLOAT &m_fBase) + { + return m_fBase; + } + + // overridable function to get range for switching to another player + virtual FLOAT GetThreatDistance(void) + { + // closer of close or stop range + return Max(GetProp(m_fCloseDistance), GetProp(m_fStopDistance)); + } + + // check if we maybe switch to some other player (for large beasts in coop) + void MaybeSwitchToAnotherPlayer(void) + { + // if in single player + if (GetSP()->sp_bSinglePlayer) { + // no need to check + return; + } + + // if current player is inside threat distance + if (CalcDist(m_penEnemy)CheckAnotherPlayer(m_penEnemy); + if (penNewEnemy!=m_penEnemy && penNewEnemy!=NULL) { + m_penEnemy = penNewEnemy; + SendEvent(EReconsiderBehavior()); + } + } + + class CWatcher *GetWatcher(void) + { + ASSERT(m_penWatcher!=NULL); + return (CWatcher*)&*m_penWatcher; + } + export void Copy(CEntity &enOther, ULONG ulFlags) + { + CMovableModelEntity::Copy(enOther, ulFlags); + CEnemyBase *penOther = (CEnemyBase *)(&enOther); + } + + void Precache(void) + { + PrecacheModel(MODEL_FLESH); + PrecacheModel(MODEL_FLESH_APPLE); + PrecacheModel(MODEL_FLESH_BANANA); + PrecacheModel(MODEL_FLESH_BURGER); + PrecacheModel(MODEL_MACHINE); + PrecacheTexture(TEXTURE_MACHINE); + PrecacheTexture(TEXTURE_FLESH_RED); + PrecacheTexture(TEXTURE_FLESH_GREEN); + PrecacheTexture(TEXTURE_FLESH_APPLE); + PrecacheTexture(TEXTURE_FLESH_BANANA); + PrecacheTexture(TEXTURE_FLESH_BURGER); + PrecacheTexture(TEXTURE_FLESH_LOLLY); + PrecacheTexture(TEXTURE_FLESH_ORANGE); + PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSPILL); + PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSTAIN); + PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSTAINGROW); + PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODEXPLODE); + PrecacheClass(CLASS_BASIC_EFFECT, BET_BOMB); + PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); + PrecacheClass(CLASS_DEBRIS); + } + + // get position you would like to go to when following player + virtual FLOAT3D PlayerDestinationPos(void) + { + return m_penEnemy->GetPlacement().pl_PositionVector; + } + + // calculate delta to given entity + FLOAT3D CalcDelta(CEntity *penEntity) + { + ASSERT(penEntity!=NULL); + // find vector from you to target + return penEntity->GetPlacement().pl_PositionVector - GetPlacement().pl_PositionVector; + }; + // calculate distance to given entity + FLOAT CalcDist(CEntity *penEntity) + { + return CalcDelta(penEntity).Length(); + }; + + BOOL IfTargetCrushed(CEntity *penOther, const FLOAT3D &vDirection) + { + if( IsOfClass(penOther, "ModelHolder2")) + { + FLOAT fCrushHealth = GetCrushHealth(); + if( fCrushHealth>((CRationalEntity &)*penOther).GetHealth()) + { + InflictDirectDamage(penOther, this, + DMT_EXPLOSION, fCrushHealth, GetPlacement().pl_PositionVector, vDirection); + return TRUE; + } + } + return FALSE; + } + + // calculate delta to given entity in current gravity plane + FLOAT3D CalcPlaneDelta(CEntity *penEntity) + { + ASSERT(penEntity!=NULL); + FLOAT3D vPlaneDelta; + // find vector from you to target in XZ plane + GetNormalComponent( + penEntity->GetPlacement().pl_PositionVector - GetPlacement().pl_PositionVector, + en_vGravityDir, vPlaneDelta); + return vPlaneDelta; + }; + + // calculate distance to given entity in current gravity plane + FLOAT CalcPlaneDist(CEntity *penEntity) + { + return CalcPlaneDelta(penEntity).Length(); + }; + + // get cos of angle in direction + FLOAT GetFrustumAngle(const FLOAT3D &vDir) + { + // find front vector + FLOAT3D vFront = -GetRotationMatrix().GetColumn(3); + // make dot product to determine if you can see target (view angle) + return (vDir/vDir.Length())%vFront; + } + + // get cos of angle in direction in current gravity plane + FLOAT GetPlaneFrustumAngle(const FLOAT3D &vDir) + { + FLOAT3D vPlaneDelta; + // find vector from you to target in XZ plane + GetNormalComponent(vDir, en_vGravityDir, vPlaneDelta); + // find front vector + FLOAT3D vFront = -GetRotationMatrix().GetColumn(3); + FLOAT3D vPlaneFront; + GetNormalComponent(vFront, en_vGravityDir, vPlaneFront); + // make dot product to determine if you can see target (view angle) + vPlaneDelta.SafeNormalize(); + vPlaneFront.SafeNormalize(); + return vPlaneDelta%vPlaneFront; + } + + // determine if you can see something in given direction + BOOL IsInFrustum(CEntity *penEntity, FLOAT fCosHalfFrustum) + { + // get direction to the entity + FLOAT3D vDelta = CalcDelta(penEntity); + // find front vector + FLOAT3D vFront = -GetRotationMatrix().GetColumn(3); + // make dot product to determine if you can see target (view angle) + FLOAT fDotProduct = (vDelta/vDelta.Length())%vFront; + return fDotProduct >= fCosHalfFrustum; + }; + + // determine if you can see something in given direction in current gravity plane + BOOL IsInPlaneFrustum(CEntity *penEntity, FLOAT fCosHalfFrustum) + { + // get direction to the entity + FLOAT3D vPlaneDelta = CalcPlaneDelta(penEntity); + // find front vector + FLOAT3D vFront = -GetRotationMatrix().GetColumn(3); + FLOAT3D vPlaneFront; + GetNormalComponent(vFront, en_vGravityDir, vPlaneFront); + // make dot product to determine if you can see target (view angle) + vPlaneDelta.SafeNormalize(); + vPlaneFront.SafeNormalize(); + FLOAT fDot = vPlaneDelta%vPlaneFront; + return fDot >= fCosHalfFrustum; + }; + + // cast a ray to entity checking only for brushes + BOOL IsVisible(CEntity *penEntity) + { + ASSERT(penEntity!=NULL); + // get ray source and target + FLOAT3D vSource, vTarget; + GetPositionCastRay(this, penEntity, vSource, vTarget); + + // cast the ray + CCastRay crRay(this, vSource, vTarget); + crRay.cr_ttHitModels = CCastRay::TT_NONE; // check for brushes only + crRay.cr_bHitTranslucentPortals = FALSE; + en_pwoWorld->CastRay(crRay); + + // if hit nothing (no brush) the entity can be seen + return (crRay.cr_penHit==NULL); + }; + + // cast a ray to entity checking all + BOOL IsVisibleCheckAll(CEntity *penEntity) + { + ASSERT(penEntity!=NULL); + // get ray source and target + FLOAT3D vSource, vTarget; + GetPositionCastRay(this, penEntity, vSource, vTarget); + + // cast the ray + CCastRay crRay(this, vSource, vTarget); + crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX; // check for model collision box + crRay.cr_bHitTranslucentPortals = FALSE; + en_pwoWorld->CastRay(crRay); + + // if the ray hits wanted entity + return crRay.cr_penHit==penEntity; + }; + + /* calculates launch velocity and heading correction for angular launch */ + void CalculateAngularLaunchParams( + FLOAT3D vShooting, FLOAT fShootHeight, + FLOAT3D vTarget, FLOAT3D vSpeedDest, + ANGLE aPitch, + FLOAT &fLaunchSpeed, + FLOAT &fRelativeHdg) + { + FLOAT3D vNewTarget = vTarget; + FLOAT3D &vGravity = en_vGravityDir; + FLOAT fYt; + FLOAT fXt; + FLOAT fA = TanFast(AngleDeg(aPitch)); + FLOAT fTime = 0.0f; + FLOAT fLastTime = 0.0f; + + INDEX iIterations = 0; + do + { + iIterations++; + FLOAT3D vDistance = vNewTarget-vShooting; + FLOAT3D vXt, vYt; + GetParallelAndNormalComponents(vDistance, vGravity, vYt, vXt); + fYt = vYt.Length(); + if (vGravity%vYt>0) { + fYt=-fYt; + } + fXt = vXt.Length(); + fLastTime=fTime; + fTime = Sqrt(2.0f)*Sqrt((fA*fXt+fShootHeight-fYt)/en_fGravityA); + vNewTarget = vTarget+vSpeedDest*fTime; + } + while( (Abs(fTime-fLastTime) > _pTimer->TickQuantum) && (iIterations<10) ); + + // calculate launch speed + fLaunchSpeed = fXt/(fTime*Cos(aPitch)); + + // calculate heading correction + FLOAT fHdgTargetNow = GetRelativeHeading( (vTarget-vShooting).SafeNormalize()); + FLOAT fHdgTargetMoved = GetRelativeHeading( (vNewTarget-vShooting).SafeNormalize()); + fRelativeHdg = fHdgTargetMoved-fHdgTargetNow; + } + + /* calculates predicted position for propelled projectile */ + FLOAT3D CalculatePredictedPosition( FLOAT3D vShootPos, FLOAT3D vTarget, + FLOAT fSpeedSrc, FLOAT3D vSpeedDst, FLOAT fClampY) + { + FLOAT3D vNewTarget = vTarget; + FLOAT3D &vGravity = en_vGravityDir; + FLOAT fTime = 0.0f; + FLOAT fLastTime = 0.0f; + INDEX iIterations = 0; + FLOAT3D vDistance = vNewTarget-vShootPos; + + // iterate to obtain accurate position + do + { + iIterations++; + fLastTime=fTime; + fTime = vDistance.Length()/fSpeedSrc; + vNewTarget = vTarget + vSpeedDst*fTime + vGravity*0.5f*fTime*fTime; + vNewTarget(2) = ClampDn( vNewTarget(2), fClampY); + vDistance = vNewTarget-vShootPos; + } + while( (Abs(fTime-fLastTime) > _pTimer->TickQuantum) && (iIterations<10) ); + return vNewTarget; + } + + /* Check if entity is moved on a route set up by its targets. */ + BOOL MovesByTargetedRoute(CTString &strTargetProperty) const { + strTargetProperty = "Marker"; + return TRUE; + }; + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\EnemyMarker.ecl"); + strTargetProperty = "Marker"; + return TRUE; + } + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("->"); + if (m_penMarker!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", m_penMarker->GetName()); + } + return m_strDescription; + } + + virtual const CTFileName &GetComputerMessageName(void) const { + static CTFileName fnm(CTString("")); + return fnm; + } + + // add to prediction any entities that this entity depends on + void AddDependentsToPrediction(void) + { + m_penSpray->AddToPrediction(); + if (m_penWatcher!=NULL) { + GetWatcher()->AddToPrediction(); + } + } + + // create a checksum value for sync-check + void ChecksumForSync(ULONG &ulCRC, INDEX iExtensiveSyncCheck) { + CMovableModelEntity::ChecksumForSync(ulCRC, iExtensiveSyncCheck); + } + // dump sync data to text file + void DumpSync_t(CTStream &strm, INDEX iExtensiveSyncCheck) // throw char * + { + CMovableModelEntity ::DumpSync_t(strm, iExtensiveSyncCheck); + strm.FPrintF_t("enemy: "); + if (m_penEnemy!=NULL) { + strm.FPrintF_t("id: %08X\n", m_penEnemy->en_ulID); + } else { + strm.FPrintF_t("none\n"); + } + + /*INDEX ctStates = en_stslStateStack.Count(); + strm.FPrintF_t("state stack @%gs:\n", _pTimer->CurrentTick()); + for(INDEX iState=ctStates-1; iState>=0; iState--) { + SLONG slState = en_stslStateStack[iState]; + strm.FPrintF_t(" 0x%08x %s\n", slState, en_pecClass->ec_pdecDLLClass->HandlerNameForState(slState)); + }*/ + + } + + /* Read from stream. */ + void Read_t( CTStream *istr) { + CMovableModelEntity::Read_t(istr); + + // add to fuss if needed + if (m_penMainMusicHolder!=NULL) { + ((CMusicHolder&)*m_penMainMusicHolder).m_cenFussMakers.Add(this); + } + }; + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + pes->es_strName = GetClass()->ec_pdecDLLClass->dec_strName; + if (m_bTemplate) { + pes->es_ctCount = 0; + } else { + pes->es_ctCount = 1; + } + pes->es_ctAmmount = 1; + pes->es_fValue = GetHealth(); + pes->es_iScore = m_iScore; + return TRUE; + } + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // if template + if (m_bTemplate) { + // do nothing + return; + } + + FLOAT fNewDamage = fDamageAmmount; + + // adjust damage + fNewDamage *=DamageStrength( ((EntityInfo*)GetEntityInfo())->Eeibt, dmtType); + // apply game extra damage per enemy and per player + fNewDamage *=GetGameDamageMultiplier(); + + // if no damage + if (fNewDamage==0) { + // do nothing + return; + } + FLOAT fKickDamage = fNewDamage; + if( (dmtType == DMT_EXPLOSION) || (dmtType == DMT_IMPACT) || (dmtType == DMT_CANNONBALL_EXPLOSION) ) + { + fKickDamage*=1.5; + } + if (dmtType==DMT_DROWNING || dmtType==DMT_CLOSERANGE || dmtType==DMT_CHAINSAW) { + fKickDamage /= 10; + } + if (dmtType==DMT_BURNING) + { + fKickDamage /= 100000; + UBYTE ubR, ubG, ubB, ubA; + FLOAT fColorFactor=fNewDamage/m_fMaxHealth*255.0f; + ColorToRGBA(m_colBurning, ubR, ubG, ubB, ubA); + ubR=ClampDn(ubR-fColorFactor, 32.0f); + m_colBurning=RGBAToColor(ubR, ubR, ubR, ubA); + } + + // get passed time since last damage + TIME tmNow = _pTimer->CurrentTick(); + TIME tmDelta = tmNow-m_tmLastDamage; + m_tmLastDamage = tmNow; + + // fade damage out + if (tmDelta>=_pTimer->TickQuantum*3) { + m_vDamage=FLOAT3D(0,0,0); + } + // add new damage + FLOAT3D vDirectionFixed; + if (vDirection.ManhattanNorm()>0.5f) { + vDirectionFixed = vDirection; + } else { + vDirectionFixed = -en_vGravityDir; + } + FLOAT3D vDamageOld = m_vDamage; +/* if( (dmtType == DMT_EXPLOSION) || (dmtType == DMT_CANNONBALL_EXPLOSION) ) + { + m_vDamage+=(vDirectionFixed/2-en_vGravityDir/2)*fKickDamage; + } + else*/ + { + m_vDamage+=(vDirectionFixed-en_vGravityDir/2)*fKickDamage; + } + + FLOAT fOldLen = vDamageOld.Length(); + FLOAT fNewLen = m_vDamage.Length(); + FLOAT fOldRootLen = Sqrt(fOldLen); + FLOAT fNewRootLen = Sqrt(fNewLen); + + FLOAT fMassFactor = 300.0f/((EntityInfo*)GetEntityInfo())->fMass; + + if( !(en_ulFlags & ENF_ALIVE)) + { + fMassFactor /= 3; + } + + if(fOldLen != 0.0f) + { + // cancel last push + GiveImpulseTranslationAbsolute( -vDamageOld/fOldRootLen*fMassFactor); + } + + //-en_vGravityDir*fPushStrength/10 + + // push it back + GiveImpulseTranslationAbsolute( m_vDamage/fNewRootLen*fMassFactor); + + /*if ((m_tmSpraySpawned<=_pTimer->CurrentTick()-_pTimer->TickQuantum || + m_fSprayDamage+fNewDamage>50.0f) + && m_fSpiritStartTime==0) {*/ + + if( m_fMaxDamageAmmountCurrentTick()-_pTimer->TickQuantum*8 || + m_fSprayDamage+fNewDamage>50.0f) + && m_fSpiritStartTime==0 && + dmtType!=DMT_CHAINSAW && + !(dmtType==DMT_BURNING && GetHealth()<0) ) { + + // spawn blood spray + CPlacement3D plSpray = CPlacement3D( vHitPoint, ANGLE3D(0, 0, 0)); + m_penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + if(m_sptType != SPT_ELECTRICITY_SPARKS) + { + m_penSpray->SetParent( this); + } + + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + + if( m_fMaxDamageAmmount > 10.0f) + { + eSpawnSpray.fDamagePower = 3.0f; + } + else if(m_fSprayDamage+fNewDamage>50.0f) + { + eSpawnSpray.fDamagePower = 2.0f; + } + else + { + eSpawnSpray.fDamagePower = 1.0f; + } + + eSpawnSpray.sptType = m_sptType; + eSpawnSpray.fSizeMultiplier = 1.0f; + + // setup direction of spray + FLOAT3D vHitPointRelative = vHitPoint - GetPlacement().pl_PositionVector; + FLOAT3D vReflectingNormal; + GetNormalComponent( vHitPointRelative, en_vGravityDir, vReflectingNormal); + vReflectingNormal.SafeNormalize(); + + vReflectingNormal(1)/=5.0f; + + FLOAT3D vProjectedComponent = vReflectingNormal*(vDirection%vReflectingNormal); + FLOAT3D vSpilDirection = vDirection-vProjectedComponent*2.0f-en_vGravityDir*0.5f; + + eSpawnSpray.vDirection = vSpilDirection; + eSpawnSpray.penOwner = this; + + /*if (dmtType==DMT_BURNING && GetHealth()<0) + { + eSpawnSpray.fDamagePower = 1.0f; + }*/ + + // initialize spray + m_penSpray->Initialize( eSpawnSpray); + m_tmSpraySpawned = _pTimer->CurrentTick(); + m_fSprayDamage = 0.0f; + m_fMaxDamageAmmount = 0.0f; + } + m_fSprayDamage+=fNewDamage; + + CMovableModelEntity::ReceiveDamage(penInflictor, + dmtType, fNewDamage, vHitPoint, vDirection); + }; + + +/************************************************************ + * FADE OUT * + ************************************************************/ + + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + colAmbient = AddColors( colAmbient, m_colColor); + if( m_bFadeOut) { + FLOAT fTimeRemain = m_fFadeStartTime + m_fFadeTime - _pTimer->CurrentTick(); + if( fTimeRemain < 0.0f) { fTimeRemain = 0.0f; } + COLOR colAlpha; + if(en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL) { + colAlpha = GetModelInstance()->GetModelColor(); + colAlpha = (colAlpha&0xFFFFFF00) + (COLOR(fTimeRemain/m_fFadeTime*0xFF)&0xFF); + GetModelInstance()->SetModelColor(colAlpha); + } + else { + colAlpha = GetModelObject()->mo_colBlendColor; + colAlpha = (colAlpha&0xFFFFFF00) + (COLOR(fTimeRemain/m_fFadeTime*0xFF)&0xFF); + GetModelObject()->mo_colBlendColor = colAlpha; + } + + } else { + if (GetSP()->sp_bMental) { + if (GetHealth()<=0) { + if(en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL) { + GetModelInstance()->SetModelColor(C_WHITE&0xFF); + } else { + GetModelObject()->mo_colBlendColor = C_WHITE&0xFF; + } + } else { + extern FLOAT ent_tmMentalIn ; + extern FLOAT ent_tmMentalOut ; + extern FLOAT ent_tmMentalFade; + FLOAT tmIn = ent_tmMentalIn ; + FLOAT tmOut = ent_tmMentalOut ; + FLOAT tmFade = ent_tmMentalFade; + FLOAT tmExist = tmFade+tmIn+tmFade; + FLOAT tmTotal = tmFade+tmIn+tmFade+tmOut; + + FLOAT tmTime = _pTimer->GetLerpedCurrentTick(); + FLOAT fFactor = 1; + if (tmTime>0.1f) { + tmTime += en_ulID*123.456f; + tmTime = fmod(tmTime, tmTotal); + fFactor = CalculateRatio(tmTime, 0, tmExist, tmFade/tmExist, tmFade/tmExist); + } + + if(en_RenderType == RT_SKAMODEL || en_RenderType == RT_SKAEDITORMODEL) { + GetModelInstance()->SetModelColor(C_WHITE|INDEX(0xFF*fFactor)); + } else { + GetModelObject()->mo_colBlendColor = C_WHITE|INDEX(0xFF*fFactor); + } + } + } + } + if(m_colBurning!=COLOR(C_WHITE|CT_OPAQUE)) + { + colAmbient = MulColors( colAmbient, m_colBurning); + colLight = MulColors( colLight, m_colBurning); + } + return CMovableModelEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + }; + + + // fuss functions + void AddToFuss(void) + { + if (IsPredictor()) { + // remember last fuss time + m_tmLastFussTime = _pTimer->CurrentTick(); + return; + } + + // if no music holder remembered - not in fuss + if (m_penMainMusicHolder==NULL) { + // find main music holder + m_penMainMusicHolder = _pNetwork->GetEntityWithName("MusicHolder", 0); + // if no music holder found + if (m_penMainMusicHolder==NULL) { + // just remember last fuss time + m_tmLastFussTime = _pTimer->CurrentTick(); + // cannot make fuss + return; + } + // add to end of fuss list + ((CMusicHolder&)*m_penMainMusicHolder).m_cenFussMakers.Add(this); + // if boss set as boss + if (m_bBoss) { + ((CMusicHolder&)*m_penMainMusicHolder).m_penBoss = this; + } + // remember last fuss time + m_tmLastFussTime = _pTimer->CurrentTick(); + + // if music holder remembered - still in fuss + } else { + // must be in list + ASSERT(((CMusicHolder&)*m_penMainMusicHolder).m_cenFussMakers.IsMember(this)); + // if boss set as boss + if (m_bBoss) { + ((CMusicHolder&)*m_penMainMusicHolder).m_penBoss = this; + } + // just remember last fuss time + m_tmLastFussTime = _pTimer->CurrentTick(); + } + } + void RemoveFromFuss(void) + { + if (IsPredictor()) { + return; + } + // if no music holder remembered + if (m_penMainMusicHolder==NULL) { + // not in fuss + return; + } + // just remove from list + ((CMusicHolder&)*m_penMainMusicHolder).m_cenFussMakers.Remove(this); + // if boss, clear boss + if (m_bBoss) { + if (((CMusicHolder&)*m_penMainMusicHolder).m_penBoss != this) { + CPrintF(TRANS("More than one boss active!\n")); + ((CMusicHolder&)*m_penMainMusicHolder).m_penBoss = NULL; + } + } + m_penMainMusicHolder = NULL; + } + + // check if should give up attacking + BOOL ShouldCeaseAttack(void) + { + // if there is no valid the enemy + if (m_penEnemy==NULL || + !(m_penEnemy->GetFlags()&ENF_ALIVE) || + (m_penEnemy->GetFlags()&ENF_DELETED)) { + // cease attack + return TRUE; + } + // if not active in fighting + if (_pTimer->CurrentTick()>m_tmLastFussTime+m_tmGiveUp) { + // cease attack + return TRUE; + } + // otherwise, continue + return FALSE; + } + + // Stretch model - MUST BE DONE BEFORE SETTING MODEL! + virtual void SizeModel(void) + { + FLOAT3D vStretch = GetModelStretch(); + + // apply defined stretch + vStretch *= m_fStretchMultiplier; + + // if should apply random stretch + if (m_bApplyRandomStretch) + { + // will be done only when user clicks "Apply random" switch + m_bApplyRandomStretch = FALSE; + // get rnd for random stretch + m_fRandomStretchMultiplier = (FRnd()-0.5f)*m_fRandomStretchFactor+1.0f; + } + + // apply random stretch + vStretch *= m_fRandomStretchMultiplier; + + if (m_bResizeAttachments) { + StretchModel( vStretch); + } else if (TRUE) { + StretchSingleModel( vStretch); + } + ModelChangeNotify(); + }; + + // check if an entity is valid for being your new enemy + BOOL IsValidForEnemy(CEntity *penPlayer) + { + return + penPlayer!=NULL && + IsDerivedFromClass(penPlayer, "Player") && + penPlayer->GetFlags()&ENF_ALIVE; + } + + // unset target + void SetTargetNone(void) + { + m_ttTarget = TT_NONE; + m_dtDestination = DT_PLAYERCURRENT; + m_penEnemy = NULL; + } + + // set new player as soft target if possible + BOOL SetTargetSoft(CEntity *penPlayer) + { + // if invalid target + if (!IsValidForEnemy(penPlayer)) { + // do nothing + return FALSE; + } + // if we already have any kind of target + if (m_ttTarget!=TT_NONE) { + // do nothing + return FALSE; + } + // remember new soft target + CEntity *penOld = m_penEnemy; + m_ttTarget = TT_SOFT; + m_dtDestination = DT_PLAYERCURRENT; + m_penEnemy = penPlayer; + return penOld!=penPlayer; + } + + // set new player as hard target if possible + BOOL SetTargetHard(CEntity *penPlayer) + { + // if invalid target + if (!IsValidForEnemy(penPlayer)) { + // do nothing + return FALSE; + } + // if we already have hard target + if (m_ttTarget==TT_HARD) { + // do nothing + return FALSE; + } + // remember new hard target + CEntity *penOld = m_penEnemy; + m_ttTarget = TT_HARD; + m_dtDestination = DT_PLAYERCURRENT; + m_penEnemy = penPlayer; + return penOld!=penPlayer; + } + + // force new player to be hard target + BOOL SetTargetHardForce(CEntity *penPlayer) + { + // if invalid target + if (!IsValidForEnemy(penPlayer)) { + // do nothing + return FALSE; + } + // remember new hard target + CEntity *penOld = m_penEnemy; + m_ttTarget = TT_HARD; + m_dtDestination = DT_PLAYERCURRENT; + m_penEnemy = penPlayer; + return penOld!=penPlayer; + } + +/************************************************************ + * MOVING FUNCTIONS * + ************************************************************/ + + // get movement frequency for attack + virtual FLOAT GetAttackMoveFrequency(FLOAT fEnemyDistance) + { + if (fEnemyDistance>GetProp(m_fCloseDistance)) { + return 0.5f; + } else { + return 0.25f; + } + } + + // set speeds for movement towards desired position + virtual void SetSpeedsToDesiredPosition(const FLOAT3D &vPosDelta, FLOAT fPosDist, BOOL bGoingToPlayer) + { + FLOAT fEnemyDistance = CalcDist(m_penEnemy); + FLOAT fCloseDistance = GetProp(m_fCloseDistance); + FLOAT fStopDistance = GetProp(m_fStopDistance); + // find relative direction angle + FLOAT fCos = GetPlaneFrustumAngle(vPosDelta); + // if may move and + if (MayMoveToAttack() && + // more or less ahead and + fCos>CosFast(45.0f) && + // not too close + fEnemyDistance>fStopDistance) { + // move and rotate towards it + if (fEnemyDistanceGetProp(m_fWalkSpeed)) { + RunningAnim(); + } else { + WalkingAnim(); + } + } else if (ulFlags&MF_ROTATEH) { + RotatingAnim(); + } else { + if (m_penEnemy!=NULL) { + StandingAnimFight(); + } else { + StandingAnim(); + } + } + } + + // set desired rotation and translation to go/orient towards desired position + // and get the resulting movement type + virtual ULONG SetDesiredMovement(void) + { + ULONG ulFlags = 0; + + // get delta to desired position + FLOAT3D vDelta = m_vDesiredPosition - GetPlacement().pl_PositionVector; + + if (m_dtDestination==DT_PLAYERCURRENT) { + ApplyTactics(vDelta); + } + + // if we may rotate + if (m_aRotateSpeed>0.0f) { + // get desired heading orientation + FLOAT3D vDir = vDelta; + vDir.SafeNormalize(); + ANGLE aWantedHeadingRelative = GetRelativeHeading(vDir); + + // normalize it to [-180,+180] degrees + aWantedHeadingRelative = NormalizeAngle(aWantedHeadingRelative); + + ANGLE aHeadingRotation; + // if desired position is left + if (aWantedHeadingRelative < -m_aRotateSpeed*m_fMoveFrequency) { + // start turning left + aHeadingRotation = -m_aRotateSpeed; + // if desired position is right + } else if (aWantedHeadingRelative > m_aRotateSpeed*m_fMoveFrequency) { + // start turning right + aHeadingRotation = +m_aRotateSpeed; + // if desired position is more-less ahead + } else { + // keep just the adjusting fraction of speed + aHeadingRotation = aWantedHeadingRelative/m_fMoveFrequency; + } + // start rotating + SetDesiredRotation(ANGLE3D(aHeadingRotation, 0, 0)); + + if (Abs(aHeadingRotation)>1.0f) { + ulFlags |= MF_ROTATEH; + } + + // if we may not rotate + } else { + // stop rotating + SetDesiredRotation(ANGLE3D(0, 0, 0)); + } + + // if we may move + if (m_fMoveSpeed>0.0f) { + // determine translation speed + FLOAT3D vTranslation(0.0f, 0.0f, 0.0f); + vTranslation(3) = -m_fMoveSpeed; + + // start moving + SetDesiredTranslation(vTranslation); + + ulFlags |= MF_MOVEZ; + + // if we may not move + } else { + // stop translating + SetDesiredTranslation(FLOAT3D(0, 0, 0)); + } + + return ulFlags; + }; + + // stop moving entity + void StopMoving() + { + StopRotating(); + StopTranslating(); + }; + + // stop desired rotation + void StopRotating() + { + SetDesiredRotation(ANGLE3D(0, 0, 0)); + }; + + // stop desired translation + void StopTranslating() + { + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + }; + + // calc distance to entity in one plane (relative to owner gravity) + FLOAT CalcDistanceInPlaneToDestination(void) + { + // find vector from you to target in XZ plane + FLOAT3D vNormal; + GetNormalComponent(m_vDesiredPosition - GetPlacement().pl_PositionVector, en_vGravityDir, vNormal); + return vNormal.Length(); + }; + + // initialize path finding + virtual void StartPathFinding(void) + { + ASSERT(m_dtDestination==DT_PATHPERSISTENT || m_dtDestination==DT_PATHTEMPORARY); + + CEntity *penMarker; + FLOAT3D vPath; + // find first marker to go to + PATH_FindFirstMarker(this, + GetPlacement().pl_PositionVector, m_penEnemy->GetPlacement().pl_PositionVector, + penMarker, vPath); + // if not found, or not visible + if (penMarker==NULL || !IsVisible(penMarker)) { + // no path finding + m_dtDestination=DT_PLAYERSPOTTED; + // remember as if spotted position + m_vPlayerSpotted = PlayerDestinationPos(); + return; + } + // remember the marker and position + m_vDesiredPosition = vPath, + m_penPathMarker = penMarker; + } + + // find next navigation marker to go to + virtual void FindNextPathMarker(void) + { + // if invalid situation + if (m_penPathMarker==NULL) { + // this should not happen + ASSERT(FALSE); + // no path finding + m_dtDestination=DT_PLAYERCURRENT; + return; + } + + // find first marker to go to + CEntity *penMarker = m_penPathMarker; + FLOAT3D vPath; + PATH_FindNextMarker(this, + GetPlacement().pl_PositionVector, m_penEnemy->GetPlacement().pl_PositionVector, + penMarker, vPath); + + // if not found + if (penMarker==NULL || !IsVisible(penMarker)) { + // no path finding + m_dtDestination=DT_PLAYERSPOTTED; + // remember as if spotted position + m_vPlayerSpotted = PlayerDestinationPos(); + return; + } + + // remember the marker and position + m_vDesiredPosition = vPath, + m_penPathMarker = penMarker; + } + + // check if a touch event triggers pathfinding + BOOL CheckTouchForPathFinding(const ETouch &eTouch) + { + // if no enemy + if (m_penEnemy==NULL) { + // do nothing + return FALSE; + } + + // if already path finding + if (m_dtDestination==DT_PATHPERSISTENT || m_dtDestination==DT_PATHTEMPORARY) { + // do nothing + return FALSE; + } + + FLOAT3D vDir = en_vDesiredTranslationRelative; + vDir.SafeNormalize(); + vDir*=GetRotationMatrix(); + // if the touched plane is more or less orthogonal to the current velocity + if ((eTouch.plCollision%vDir)<-0.5f) { + if (m_penEnemy!=NULL && IsVisible(m_penEnemy)) { + m_dtDestination = DT_PATHPERSISTENT; + } else { + m_dtDestination = DT_PATHTEMPORARY; + } + StartPathFinding(); + return m_penPathMarker!=NULL; + } else { + return FALSE; + } + } + + // check if a wouldfall event triggers pathfinding + BOOL CheckFallForPathFinding(const EWouldFall &eWouldFall) + { + // if no enemy + if (m_penEnemy==NULL) { + // do nothing + return FALSE; + } + + // if already path finding + if (m_dtDestination==DT_PATHPERSISTENT || m_dtDestination==DT_PATHTEMPORARY) { + // do nothing + return FALSE; + } + + if (m_penEnemy!=NULL && IsVisible(m_penEnemy)) { + m_dtDestination = DT_PATHPERSISTENT; + } else { + m_dtDestination = DT_PATHTEMPORARY; + } + StartPathFinding(); + + return m_penPathMarker!=NULL; + } + + /************************************************************ + * TACTICS FUNCTIONS * + ************************************************************/ + + void InitializeTactics( void ) { + + // return if there is no tactics manager or if it points to wrong type of entity + // or if there is no enemy + if (m_penTacticsHolder==NULL || !IsOfClass(m_penTacticsHolder, "TacticsHolder") + || m_penEnemy==NULL) { + return; + } + + CTacticsHolder *penTactics = &(CTacticsHolder &)*m_penTacticsHolder; + + //m_tmTacticsActivation = penTactics->m_tmLastActivation; + m_tmTacticsActivation = _pTimer->CurrentTick(); + m_vTacticsStartPosition = GetPlacement().pl_PositionVector; + //m_iTacticsRetried = penTactics->m_bRetryCount; + + FLOAT fSign; + // sign for randomized parameters + if (Sgn(penTactics->m_fParam2)>0 && Sgn(penTactics->m_fParam1)>0) { + fSign = +1.0f; + } else if (Sgn(penTactics->m_fParam2)<0 && Sgn(penTactics->m_fParam1)<0) { + fSign = -1.0f; + } else { + fSign = Sgn(FRnd()-0.5f); + } + + switch (penTactics->m_tctType) { + case TCT_DAMP_ANGLE_STRIFE: { + // 1) random angle (min) + m_fTacticVar1=Lerp(Abs(penTactics->m_fParam1), Abs(penTactics->m_fParam2), FRnd())*fSign; + // 2) time dump + m_fTacticVar2=penTactics->m_fParam4; + // 3) dump factor, factor (0-1) of min distance when linear behaviour begins + m_fTacticVar3=penTactics->m_fParam3; + // 4) initial distance + m_fTacticVar4=(m_penEnemy->GetPlacement().pl_PositionVector - m_vTacticsStartPosition).Length(); + // 5) tactics stop distance + m_fTacticVar5=penTactics->m_fParam5; + break; } + + case TCT_PARALLEL_RANDOM_DISTANCE: + // 1) randomized distance + m_fTacticVar1=Lerp(penTactics->m_fParam4, penTactics->m_fParam5, FRnd()); + // 4) emission angle + m_fTacticVar4=Lerp(Abs(penTactics->m_fParam1), Abs(penTactics->m_fParam2), FRnd())*fSign; + // 2) tolerance strip width + m_fTacticVar2=m_fAttackRunSpeed*2.0f*90.0f/m_aAttackRotateSpeed; + //m_fTacticVar2=2.0f*m_fAttackRunSpeed; + // 3) fade in/out ratio + m_fTacticVar3=penTactics->m_fParam3; + // 5) initial distance + m_fTacticVar5=(GetPlacement().pl_PositionVector - m_penEnemy->GetPlacement().pl_PositionVector).Length(); + // as a precausion, assume minimal strip width of 2m + m_fTacticVar2=ClampDn(m_fTacticVar2, 2.0f); + + break; + + case TCT_STATIC_RANDOM_V_DISTANCE: + // 1) starting angle + m_fTacticVar1=Lerp(Abs(penTactics->m_fParam1), Abs(penTactics->m_fParam2), FRnd())*fSign; + // 2) time to run in the desired V direction + m_fTacticVar2=Lerp(penTactics->m_fParam3, penTactics->m_fParam4, FRnd()); + break; + } + } + + virtual void ApplyTactics( FLOAT3D &vDesiredPos) { + + // return if there is no tactics manager or if it points to wrong type of entity + // or if there is no enemy + if (m_penTacticsHolder==NULL || !IsOfClass(m_penTacticsHolder, "TacticsHolder") + || m_penEnemy==NULL) { + return; + } + + CTacticsHolder *penTactics = &(CTacticsHolder &)*m_penTacticsHolder; + + // See if the last activation time of TacticsHolder is greater then the activation + // time of this monster. If so, start (or reinitialize) the tactics. + if (penTactics->m_tmLastActivation==-1 || penTactics->m_tctType==TCT_NONE) { + m_bTacticActive = FALSE; + } else if (m_tmTacticsActivation < penTactics->m_tmLastActivation) { + InitializeTactics(); + m_bTacticActive = TRUE; + } + + if (m_bTacticActive) { + + // calculate shared parameters + FLOAT3D vEnemyDistance=m_vTacticsStartPosition - m_penEnemy->GetPlacement().pl_PositionVector; + FLOAT fEnemyDistance=vEnemyDistance.Length(); + vEnemyDistance.SafeNormalize(); + ANGLE3D angEnemy = ANGLE3D(0.0f, 0.0f, 0.0f); + //DirectionVectorToAngles(vEnemyDistance, angEnemy); + + FLOAT fDistanceRatio = 0.0f; + FLOAT fTimeRatio = 0.0f; + + switch(penTactics->m_tctType) + { + case TCT_DAMP_ANGLE_STRIFE: { + // if very close to player, stop using tactics + if (CalcDist(m_penEnemy)0) { + // get enemy distance + FLOAT fClamped=Clamp(CalcDist(m_penEnemy)-(m_fTacticVar4*m_fTacticVar3), 0.0f, m_fTacticVar4); + fDistanceRatio=fClamped/(m_fTacticVar4*(1-m_fTacticVar3)); + } + + fTimeRatio=1.0f; + if(m_fTacticVar2>0) { + fTimeRatio=1.0f-(ClampUp((_pTimer->CurrentTick() - m_tmTacticsActivation)/m_fTacticVar2, 1.0f)); + } + + angEnemy(1) = m_fTacticVar1*fDistanceRatio*fTimeRatio; + angEnemy(2) = 0.0f; + angEnemy(3) = 0.0f; + + FLOATmatrix3D mHeading; + MakeRotationMatrixFast(mHeading, angEnemy); + vDesiredPos = vDesiredPos*!en_mRotation; + vDesiredPos = vDesiredPos*mHeading; + vDesiredPos = vDesiredPos*en_mRotation; + + break; } + + case TCT_PARALLEL_RANDOM_DISTANCE: { + // line from spawner to player + FLOAT3D vLinePlayerToSpawn = m_vTacticsStartPosition - m_penEnemy->GetPlacement().pl_PositionVector; + // line from *this to player + FLOAT3D vLinePlayerToThis = GetPlacement().pl_PositionVector - m_penEnemy->GetPlacement().pl_PositionVector; + + FLOAT fThisOnLine = (vLinePlayerToThis%vLinePlayerToSpawn)/vLinePlayerToSpawn.Length(); + FLOAT3D vThisOnLine = m_penEnemy->GetPlacement().pl_PositionVector + vLinePlayerToSpawn.SafeNormalize()*fThisOnLine; + + FLOAT fLineDist = (GetPlacement().pl_PositionVector - vThisOnLine).Length(); + + FLOATmatrix3D mHeading; + + //CPrintF("line dst = %f at %f\n", fLineDist, _pTimer->CurrentTick()); + // if close enough to enemy stop tactics and go linear + if (vLinePlayerToThis.Length()m_fTacticVar1+m_fTacticVar2) { + if (fLineDist<1.0f) { fLineDist=1.0f; } + angEnemy(1) = -m_fTacticVar4/fLineDist; + angEnemy(2) = 0.0f; + angEnemy(3) = 0.0f; + + MakeRotationMatrixFast(mHeading, angEnemy); + vDesiredPos = vDesiredPos*!en_mRotation; + vDesiredPos = vDesiredPos*mHeading; + vDesiredPos = vDesiredPos*en_mRotation; + // right on the line + } else { + vDesiredPos = -vLinePlayerToSpawn; + } + break; } + + case TCT_STATIC_RANDOM_V_DISTANCE: { + if (_pTimer->CurrentTick()GetEntityInfo()); + FLOAT3D vShootTarget; + GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget); + + // launch + CPlacement3D pl; + PreparePropelledProjectile(pl, vShootTarget, vOffset, aOffset); + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.fStretch=1.0f; + eLaunch.prtType = pt; + penProjectile->Initialize(eLaunch); + + return penProjectile; + }; + + // shoot projectile at an exact spot + CEntity *ShootProjectileAt(FLOAT3D vShootTarget, enum ProjectileType pt, FLOAT3D &vOffset, ANGLE3D &aOffset) { + + // launch + CPlacement3D pl; + PreparePropelledProjectile(pl, vShootTarget, vOffset, aOffset); + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = pt; + penProjectile->Initialize(eLaunch); + + return penProjectile; + }; + + // shoot projectile on enemy + CEntity *ShootPredictedProjectile(enum ProjectileType pt, FLOAT3D vPredictedPos, FLOAT3D &vOffset, ANGLE3D &aOffset) { + ASSERT(m_penEnemy != NULL); + + // target enemy body (predicted) + EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); + FLOAT3D vShootTarget = vPredictedPos; + if (peiTarget != NULL) + { + // get body center vector + FLOAT3D vBody = FLOAT3D(peiTarget->vTargetCenter[0],peiTarget->vTargetCenter[1],peiTarget->vTargetCenter[2]); + FLOATmatrix3D mRotation; + MakeRotationMatrixFast(mRotation, m_penEnemy->GetPlacement().pl_OrientationAngle); + vShootTarget = vPredictedPos + vBody*mRotation; + } + // launch + CPlacement3D pl; + PreparePropelledProjectile(pl, vShootTarget, vOffset, aOffset); + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = pt; + penProjectile->Initialize(eLaunch); + + return penProjectile; + }; + + BOOL WouldNotLeaveAttackRadius(void) + { + if (m_fAttackRadius<=0) { + return FALSE; + } + // test if we are inside radius + BOOL bInsideNow = (m_vStartPosition-GetPlacement().pl_PositionVector).Length() < m_fAttackRadius; + // test if going towards enemy leads us to center of attack radius circle + BOOL bEnemyTowardsCenter = + (m_vStartPosition-m_penEnemy->GetPlacement().pl_PositionVector).Length() < + (GetPlacement().pl_PositionVector-m_penEnemy->GetPlacement().pl_PositionVector).Length(); + return bInsideNow || bEnemyTowardsCenter; + } + + // check whether may move while attacking + virtual BOOL MayMoveToAttack(void) + { + // check if enemy is diving + CMovableEntity *pen = (CMovableEntity *)&*m_penEnemy; + CContentType &ctUp = pen->en_pwoWorld->wo_actContentTypes[pen->en_iUpContent]; + BOOL bEnemyDiving = !(ctUp.ct_ulFlags&CTF_BREATHABLE_LUNGS); + // may move if can go to enemy without leaving attack radius, and entity is not diving + return WouldNotLeaveAttackRadius() && !bEnemyDiving; + }; + + +/************************************************************ + * BLOW UP FUNCTIONS * + ************************************************************/ + // should this enemy blow up (spawn debris) + virtual BOOL ShouldBlowUp(void) + { + // exotech larva boss allways blows up + if (IsOfClass(this, "ExotechLarva")) { return TRUE; } + + // blow up if + return + // allowed + GetSP()->sp_bGibs && + // dead and + GetHealth()<=0 && + // has received large enough damage lately and + m_vDamage.Length() > m_fBlowUpAmount && + // not already disappearing + m_fSpiritStartTime==0; + } + + + // base function for blowing up + void BlowUpBase(void) + { + // call derived function + BlowUp(); + } + + + // spawn body parts + virtual void BlowUp(void) + { + // blow up notify + BlowUpNotify(); + const BOOL bGibs = GetSP()->sp_bGibs; + + FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(m_fBlowUpAmount/m_vDamage.Length()); + vNormalizedDamage /= Sqrt(vNormalizedDamage.Length()); + vNormalizedDamage *= 0.75f; + FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute); + + // if allowed and fleshy + if( bGibs && !m_bRobotBlowup) + { + // readout blood type + const INDEX iBloodType = GetSP()->sp_iBlood; + // determine debris texture (color) + ULONG ulFleshTexture = TEXTURE_FLESH_GREEN; + ULONG ulFleshModel = MODEL_FLESH; + if( iBloodType==2) { ulFleshTexture = TEXTURE_FLESH_RED; } + // spawn debris + Debris_Begin(EIBT_FLESH, DPT_BLOODTRAIL, BET_BLOODSTAIN, m_fBlowUpSize, vNormalizedDamage, vBodySpeed, 1.0f, 0.0f); + for( INDEX iDebris = 0; iDebrisInitialize(eSpawnEffect); + } + + // hide yourself (must do this after spawning debris) + SwitchToEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + } + + +/************************************************************ + * CLASS SUPPORT FUNCTIONS * + ************************************************************/ + + // leave stain + virtual void LeaveStain( BOOL bGrow) + { + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + // get your size + FLOATaabbox3D box; + GetBoundingBox(box); + + // on plane + if( GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + // if near to polygon and away from last stain point + if( (vPoint-GetPlacement().pl_PositionVector).Length()<0.5f + && (m_vLastStain-vPoint).Length()>1.0f ) { + m_vLastStain = vPoint; + FLOAT fStretch = box.Size().Length(); + ese.colMuliplier = C_WHITE|CT_OPAQUE; + // stain + if (bGrow) { + ese.betType = BET_BLOODSTAINGROW; + ese.vStretch = FLOAT3D( fStretch*1.5f, fStretch*1.5f, 1.0f); + } else { + ese.betType = BET_BLOODSTAIN; + ese.vStretch = FLOAT3D( fStretch*0.75f, fStretch*0.75f, 1.0f); + } + ese.vNormal = FLOAT3D( vPlaneNormal); + ese.vDirection = FLOAT3D( 0, 0, 0); + FLOAT3D vPos = vPoint+ese.vNormal/50.0f*(FRnd()+0.5f); + CEntityPointer penEffect = CreateEntity( CPlacement3D(vPos, ANGLE3D(0,0,0)), CLASS_BASIC_EFFECT); + penEffect->Initialize(ese); + } + } + }; + + virtual void AdjustDifficulty(void) + { + FLOAT fMoveSpeed = GetSP()->sp_fEnemyMovementSpeed; + FLOAT fAttackSpeed = GetSP()->sp_fEnemyMovementSpeed; +// m_fWalkSpeed *= fMoveSpeed; +// m_aWalkRotateSpeed *= fMoveSpeed; + m_fAttackRunSpeed *= fMoveSpeed; + m_aAttackRotateSpeed *= fMoveSpeed; + m_fCloseRunSpeed *= fMoveSpeed; + m_aCloseRotateSpeed *= fMoveSpeed; + m_fAttackFireTime *= 1/fAttackSpeed; + m_fCloseFireTime *= 1/fAttackSpeed; +/* + CSessionProperties::GameDificulty gd = GetSP()->sp_gdGameDificulty; + + switch(gd) { + case CSessionProperties::GD_EASY: { + } break; + case CSessionProperties::GD_NORMAL: { + } break; + case CSessionProperties::GD_HARD: { + } break; + case CSessionProperties::GD_SERIOUS: { + } break; + } + */ + } + + +/************************************************************ + * SOUND VIRTUAL FUNCTIONS * + ************************************************************/ + + // wounded -> yell + void WoundedNotify(const EDamage &eDamage) + { + // if no enemy + if (m_penEnemy==NULL) { + // do nothing + return; + } + + // if not killed from short distance + if (eDamage.dmtType!=DMT_CLOSERANGE && eDamage.dmtType!=DMT_CHAINSAW) { + // yell + ESound eSound; + eSound.EsndtSound = SNDT_YELL; + eSound.penTarget = m_penEnemy; + SendEventInRange(eSound, FLOATaabbox3D(GetPlacement().pl_PositionVector, 25.0f)); + } + }; + + // see enemy -> shout + void SeeNotify() + { + // if no enemy + if (m_penEnemy==NULL) { + // do nothing + return; + } + // yell + ESound eSound; + eSound.EsndtSound = SNDT_SHOUT; + eSound.penTarget = m_penEnemy; + SendEventInRange(eSound, FLOATaabbox3D(GetPlacement().pl_PositionVector, 50.0f)); + }; + + + +/************************************************************ + * VIRTUAL FUNCTIONS THAT NEED OVERRIDE * + ************************************************************/ + virtual void StandingAnim(void) {}; + virtual void StandingAnimFight(void) { StandingAnim(); }; + virtual void WalkingAnim(void) {}; + virtual void RunningAnim(void) {}; + virtual void RotatingAnim(void) {}; + virtual void ChargeAnim(void) {}; + virtual INDEX AnimForDamage(FLOAT fDamage) { return 0; }; + virtual void BlowUpNotify(void) {}; + virtual INDEX AnimForDeath(void) { return 0; }; + virtual FLOAT WaitForDust(FLOAT3D &vStretch) { return -1; }; + virtual void DeathNotify(void) {}; + virtual void IdleSound(void) {}; + virtual void SightSound(void) {}; + virtual void WoundSound(void) {}; + virtual void DeathSound(void) {}; + virtual FLOAT GetLockRotationSpeed(void) { return 2000.0f;}; + + + // render particles + void RenderParticles(void) { + // no particles when not existing + if (GetRenderType()!=CEntity::RT_MODEL && GetRenderType()!=CEntity::RT_SKAMODEL) { + return; + } + // if is dead + if( m_fSpiritStartTime != 0.0f) + { + // const FLOAT tmNow = _pTimer->CurrentTick(); + // Particles_ModelGlow(this, tmNow + 20,PT_STAR08, 0.15f, 2, 0.03f, 0xff00ff00); + Particles_Death(this, m_fSpiritStartTime); + } + } + + // adjust sound and watcher parameters here if needed + virtual void EnemyPostInit(void) {}; + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + if (ee.ee_slEvent==EVENTCODE_ETouch) + { + if( GetCrushHealth() != 0.0f) + { + ETouch eTouch = ((ETouch &) ee); + if (IsOfClass(eTouch.penOther, "ModelHolder2") || + IsOfClass(eTouch.penOther, "MovingBrush") || + IsOfClass(eTouch.penOther, "DestroyableArchitecture") ) + { + InflictDirectDamage(eTouch.penOther, this, DMT_EXPLOSION, GetCrushHealth(), + eTouch.penOther->GetPlacement().pl_PositionVector, -(FLOAT3D&)eTouch.plCollision); + } + } + } + return CMovableModelEntity::HandleEvent(ee); + } + + // returns length of animation + FLOAT GetAnimLength(int iAnim) + { + if(en_RenderType==RT_SKAMODEL) { + return GetModelInstance()->GetAnimLength(iAnim); + } else { + return GetModelObject()->GetAnimLength(iAnim); + } + } + + // returns lenght of current anim length + FLOAT GetCurrentAnimLength() + { + if(en_RenderType==RT_SKAMODEL) { + return 0.5f; + } else { + return GetModelObject()->GetCurrentAnimLength(); + } + } + + // is animation finished + BOOL IsAnimFinished() + { + if(en_RenderType==RT_SKAMODEL) { + return TRUE; + } else { + return GetModelObject()->IsAnimFinished(); + } + } + + // + FLOAT GetPassedTime() + { + if(en_RenderType==RT_SKAMODEL) { + return 0.0f; + } else { + return GetModelObject()->GetPassedTime(); + } + } + + FLOAT3D &GetModelStretch() + { + if(en_RenderType==RT_SKAMODEL) { + return GetModelInstance()->mi_vStretch; + } else { + return GetModelObject()->mo_Stretch; + } + } + + // Stretch model + void StretchModel(FLOAT3D vStretch) + { + if(en_RenderType==RT_SKAMODEL) { + GetModelInstance()->StretchModel( vStretch); + } else { + GetModelObject()->StretchModel( vStretch); + } + } + + // Stretch single model + void StretchSingleModel( FLOAT3D vStretch) + { + if(en_RenderType==RT_SKAMODEL) { + GetModelInstance()->StretchSingleModel( vStretch); + } else { + GetModelObject()->StretchSingleModel( vStretch); + } + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CEnemyBase) - sizeof(CMovableModelEntity) + CMovableModelEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strDescription.Length(); + slUsedMemory += m_strName.Length(); + slUsedMemory += 1* sizeof(CSoundObject); + return slUsedMemory; + } + + + +procedures: + +//********************************************************** +// MOVEMENT PROCEDURES +//********************************************************** + + // move to given destination position + MoveToDestination(EVoid) + { + // setup parameters + m_fMoveFrequency = 0.25f; + m_fMoveTime = _pTimer->CurrentTick() + 45.0f; + // while not there and time not expired + while (CalcDistanceInPlaneToDestination()>m_fMoveSpeed*m_fMoveFrequency*2.0f && + m_fMoveTime>_pTimer->CurrentTick()) { + // every once in a while + wait (m_fMoveFrequency) { + on (EBegin) : { + // adjust direction and speed + ULONG ulFlags = SetDesiredMovement(); + MovementAnimation(ulFlags); + resume; + } + on (ETimer) : { stop; } + } + } + + // return to the caller + return EReturn(); + }; + + // go to next randomly choosen position inside patrol range + MoveToRandomPatrolPosition(EVoid) + { + // if the marker is invalid + if (!IsOfClass(m_penMarker, "Enemy Marker")) { + // this should not happen + ASSERT(FALSE); + // return to caller + return EReturn(); + } + // get the marker + CEnemyMarker *pem = (CEnemyMarker *)&*m_penMarker; + + // get random destination position + FLOAT fMin = pem->m_fPatrolAreaInner; + FLOAT fMax = pem->m_fPatrolAreaOuter; + if (fMin<0) { + fMin = 0; + } + if (fMaxSendEvent(EStart()); + + // stand in place + StandingAnim(); + + // repeat forever + while(TRUE) { + // wait some time + autowait(Lerp(5.0f, 20.0f, FRnd())); + // play idle sound + IdleSound(); + } + } + + // return to start position + ReturnToStartPosition(EVoid) + { + jump BeIdle(); +/* + // start watching + GetWatcher()->SendEvent(EStart()); + + m_vDesiredPosition = m_vStartPosition; + m_vStartDirection = (GetPlacement().pl_PositionVector-m_vStartPosition).SafeNormalize(); + m_fMoveSpeed = GetProp(m_fAttackRunSpeed); + m_aRotateSpeed = GetProp(m_aAttackRotateSpeed); + RunningAnim(); + autocall MoveToDestination() EReturn; + + WalkingAnim(); + m_vDesiredAngle = m_vStartDirection; + StopTranslating(); + + autocall RotateToStartDirection() EReturn; + + StopMoving(); + StandingAnim(); + + jump BeIdle(); + */ + }; + /* + // rotate to destination + RotateToStartDirection(EVoid) + { + + m_fMoveFrequency = 0.1f; + m_fMoveTime = _pTimer->CurrentTick() + 45.0f; + while (Abs(GetRelativeHeading(GetDesiredPositionDir()))>GetProp(m_aRotateSpeed)*m_fMoveFrequency*1.5f && + m_fMoveTime>_pTimer->CurrentTick()) { + autowait(m_fMoveFrequency); + } + + return EReturn(); + }; + */ + + + // move through markers + MoveThroughMarkers() + { + // start watching + GetWatcher()->SendEvent(EStart()); + + // while there is a valid marker, take values from it + while (m_penMarker!=NULL && IsOfClass(m_penMarker, "Enemy Marker")) { + CEnemyMarker *pem = (CEnemyMarker *)&*m_penMarker; + + // the marker position is our new start position for attack range + m_vStartPosition = m_penMarker->GetPlacement().pl_PositionVector; + // make a random position to walk to at the marker + FLOAT fR = FRnd()*pem->m_fMarkerRange; + FLOAT fA = FRnd()*360.0f; + m_vDesiredPosition = m_vStartPosition+FLOAT3D(CosFast(fA)*fR, 0, SinFast(fA)*fR); + // if running + if (pem->m_betRunToMarker==BET_TRUE) { + // use attack speeds + m_fMoveSpeed = GetProp(m_fAttackRunSpeed); + m_aRotateSpeed = GetProp(m_aAttackRotateSpeed); + // start running anim + RunningAnim(); + // if not running + } else { + // use walk speeds + m_fMoveSpeed = GetProp(m_fWalkSpeed); + m_aRotateSpeed = GetProp(m_aWalkRotateSpeed); + // start walking anim + WalkingAnim(); + } + + // move to the new destination position + autocall MoveToDestination() EReturn; + + // read new blind/deaf values + CEnemyMarker *pem = (CEnemyMarker *)&*m_penMarker; + SetBoolFromBoolEType(m_bBlind, pem->m_betBlind); + SetBoolFromBoolEType(m_bDeaf, pem->m_betDeaf); + + // if should start tactics + if (pem->m_bStartTactics){ + // start to see/hear + m_bBlind = FALSE; + m_bDeaf = FALSE; + // unconditional tactics start + StartTacticsNow(); + } + + // if should patrol there + if (pem->m_fPatrolTime>0.0f) { + // spawn a reminder to notify us when the time is up + SpawnReminder(this, pem->m_fPatrolTime, 0); + // wait + wait() { + // initially + on (EBegin) : { + // start patroling + call DoPatrolling(); + } + // if time is up + on (EReminder) : { + // stop patroling + stop; + } + } + } + + CEnemyMarker *pem = (CEnemyMarker *)&*m_penMarker; + // if should wait on the marker + if (pem->m_fWaitTime > 0.0f) { + // stop there + StopMoving(); + StandingAnim(); + // wait + autowait(pem->m_fWaitTime); + } + + // wait a bit always (to prevent eventual busy-looping) + autowait(0.05f); + + // take next marker in loop + m_penMarker = ((CEnemyMarker&)*m_penMarker).m_penTarget; + } // when no more markers + + // stop where you are + StopMoving(); + StandingAnim(); + + // return to called + return EReturn(); + }; + + +//********************************************************** +// ATTACK PROCEDURES +//********************************************************** + + // sequence that is activated when a new player is spotted visually or heard + NewEnemySpotted() + { + // calculate reflex time + FLOAT tmReflex = Lerp(m_tmReflexMin, m_tmReflexMax, FRnd()); + tmReflex = ClampDn(tmReflex, 0.0f); + + // if should wait + if (tmReflex>=_pTimer->TickQuantum) { + // stop where you are + StopMoving(); + StandingAnim(); + + // wait the reflex time + wait(tmReflex) { + on (ETimer) : { stop; } + // pass all damage events + on (EDamage) : { pass; } + // pass space beam hit + on (EHitBySpaceShipBeam) : { pass;} + // ignore all other events + otherwise () : { resume; } + } + } + + // play sight sound + SightSound(); + + // return to caller + return EReturn(); + } + + // stop attack + StopAttack(EVoid) { + // start watching + GetWatcher()->SendEvent(EStart()); + // no damager + SetTargetNone(); + m_fDamageConfused = 0.0f; + // stop moving + StopMoving(); + + return EReturn(); + }; + + // initial preparation + InitializeAttack(EVoid) + { + // disable blind/deaf mode + m_bBlind = FALSE; + m_bDeaf = FALSE; + + SeeNotify(); // notify seeing + GetWatcher()->SendEvent(EStop()); // stop looking + // make fuss + AddToFuss(); + // remember spotted position + m_vPlayerSpotted = PlayerDestinationPos(); + + // set timers + if (CalcDist(m_penEnemy)CurrentTick() + FRnd(); + } + m_fDamageConfused = m_fDamageWounded; + + return EReturn(); + }; + + + // attack enemy + AttackEnemy(EVoid) { + // initial preparation + autocall InitializeAttack() EReturn; + + // while you have some enemy + while (m_penEnemy != NULL) { + // attack it + autocall PerformAttack() EReturn; + } + + // stop attack + autocall StopAttack() EReturn; + + // return to Active() procedure + return EBegin(); + }; + + // repeat attacking enemy until enemy is dead or you give up + PerformAttack() + { + // reset last range + m_fRangeLast = 1E9f; + + // set player's position as destination position + m_vDesiredPosition = PlayerDestinationPos(); + m_dtDestination = DT_PLAYERCURRENT; + + // repeat + while(TRUE) + { + // if attacking is futile + if (ShouldCeaseAttack()) { + // cease it + SetTargetNone(); + return EReturn(); + } + + // get distance from enemy + FLOAT fEnemyDistance = CalcDist(m_penEnemy); + // if just entered close range + if (m_fRangeLast>GetProp(m_fCloseDistance) && fEnemyDistance<=GetProp(m_fCloseDistance)) { + // reset shoot time to make it attack immediately + m_fShootTime = 0.0f; + } + m_fRangeLast = fEnemyDistance; + + // determine movement frequency depending on enemy distance or path finding + m_fMoveFrequency = GetAttackMoveFrequency(fEnemyDistance); + if (m_dtDestination==DT_PATHPERSISTENT||m_dtDestination==DT_PATHTEMPORARY) { + m_fMoveFrequency = 0.1f; + } + + // wait one time interval + wait(m_fMoveFrequency) { + on (ETimer) : { stop; } + // initially + on (EBegin) : { + + // if you haven't fired/hit enemy for some time + if (_pTimer->CurrentTick() > m_fShootTime) { + + // if you have new player visible closer than current and in threat distance + CEntity *penNewEnemy = GetWatcher()->CheckCloserPlayer(m_penEnemy, GetThreatDistance()); + if (penNewEnemy!=NULL) { + // switch to that player + SetTargetHardForce(penNewEnemy); + // start new behavior + SendEvent(EReconsiderBehavior()); + stop; + } + + // if you can see player + if (IsVisible(m_penEnemy)) { + // remember spotted position + m_vPlayerSpotted = PlayerDestinationPos(); + // if going to player spotted or temporary path position + if (m_dtDestination==DT_PLAYERSPOTTED||m_dtDestination==DT_PATHTEMPORARY) { + // switch to player current position + m_dtDestination=DT_PLAYERCURRENT; + } + + // if you cannot see player + } else { + // if going to player's current position + if (m_dtDestination==DT_PLAYERCURRENT) { + // switch to position where player was last seen + m_dtDestination=DT_PLAYERSPOTTED; + } + } + + // try firing/hitting again now + call FireOrHit(); + + // if between two fire/hit moments + } else { + // if going to player spotted or temporary path position and you just seen the player + if ((m_dtDestination==DT_PLAYERSPOTTED||m_dtDestination==DT_PATHTEMPORARY) + && IsVisible(m_penEnemy)) { + // switch to player current position + m_dtDestination=DT_PLAYERCURRENT; + // remember spotted position + m_vPlayerSpotted = PlayerDestinationPos(); + } + } + + // if you are not following the player and you are near current destination position + FLOAT fAllowedError = m_fMoveSpeed*m_fMoveFrequency*2.0f; + if (m_dtDestination==DT_PATHPERSISTENT||m_dtDestination==DT_PATHTEMPORARY) { + fAllowedError = ((CNavigationMarker&)*m_penPathMarker).m_fMarkerRange; + } + if (m_dtDestination!=DT_PLAYERCURRENT && + (CalcDistanceInPlaneToDestination()GetRenderType()==CEntity::RT_BRUSH) { + FLOAT3D vDir = en_vDesiredTranslationRelative; + vDir.SafeNormalize(); + vDir*=GetRotationMatrix(); + // if the touched plane is more or less orthogonal to the current velocity + if ((eTouch.plCollision%vDir)<-0.5f) { m_bTacticActive = 0; } + resume; + } else { + resume; + } + } else { + // pass the event + pass; + } + } + // if came to an edge + on (EWouldFall eWouldFall) : { + // if pathfinding must begin + if (CheckFallForPathFinding(eWouldFall)) { + // stop the loop + stop; + } else if (m_bTacticActive) { + // stop tactics + m_bTacticActive = 0; + resume; + // if edge is ignored + } else { + // pass the event + pass; + } + } + on (ESound) : { resume; } // ignore all sounds + on (EWatch) : { resume; } // ignore watch + on (EReturn) : { stop; } // returned from subprocedure + } + } + } + + + // fire or hit the enemy if possible + FireOrHit() + { + // if player is in close range and in front + if (CalcDist(m_penEnemy)CurrentTick() + GetProp(m_fCloseFireTime)*(1.0f + FRnd()/3.0f); + // hit + autocall Hit() EReturn; + + // else if player is in fire range and in front + } else if (CalcDist(m_penEnemy)CurrentTick() + GetProp(m_fCloseFireTime)*(1.0f + FRnd()/3.0f); + } else { + m_fShootTime = _pTimer->CurrentTick() + GetProp(m_fAttackFireTime)*(1.0f + FRnd()/3.0f); + } + // fire + autocall Fire() EReturn; + + // if cannot fire nor hit + } else { + // make sure we don't retry again too soon + m_fShootTime = _pTimer->CurrentTick() + 0.25f; + } + + // return to caller + return EReturn(); + }; + +//********************************************************** +// COMBAT IMPLEMENTATION +//********************************************************** + + // this is called to hit the player when near + Hit(EVoid) + { + return EReturn(); + } + + // this is called to shoot at player when far away or otherwise unreachable + Fire(EVoid) + { + return EReturn(); + } + +//********************************************************** +// COMBAT HELPERS +//********************************************************** + + // call this to lock on player for some time - set m_fLockOnEnemyTime before calling + LockOnEnemy(EVoid) + { + // stop moving + StopMoving(); + // play animation for locking + ChargeAnim(); + // wait charge time + m_fLockStartTime = _pTimer->CurrentTick(); + while (m_fLockStartTime+GetProp(m_fLockOnEnemyTime) > _pTimer->CurrentTick()) { + // each tick + m_fMoveFrequency = 0.05f; + wait (m_fMoveFrequency) { + on (ETimer) : { stop; } + on (EBegin) : { + m_vDesiredPosition = PlayerDestinationPos(); + // if not heading towards enemy + if (!IsInPlaneFrustum(m_penEnemy, CosFast(5.0f))) { + m_fMoveSpeed = 0.0f; + m_aRotateSpeed = GetLockRotationSpeed(); + // if heading towards enemy + } else { + m_fMoveSpeed = 0.0f; + m_aRotateSpeed = 0.0f; + } + // adjust direction and speed + ULONG ulFlags = SetDesiredMovement(); + //MovementAnimation(ulFlags); don't do this, or they start to jive + resume; + } + } + } + // stop rotating + StopRotating(); + + // return to caller + return EReturn(); + }; + + // call this to jump onto player - set charge properties before calling and spawn a reminder + ChargeHitEnemy(EVoid) + { + // wait for length of hit animation + wait(GetAnimLength(m_iChargeHitAnimation)) { + on (EBegin) : { resume; } + on (ETimer) : { stop; } + // ignore damages + on (EDamage) : { resume; } + // if user-set reminder expired + on (EReminder) : { + // stop moving + StopMoving(); + resume; + } + // if you touch some entity + on (ETouch etouch) : { + // if it is alive and in front + if ((etouch.penOther->GetFlags()&ENF_ALIVE) && IsInPlaneFrustum(etouch.penOther, CosFast(60.0f))) { + // get your direction + FLOAT3D vSpeed; + GetHeadingDirection(m_fChargeHitAngle, vSpeed); + // damage entity in that direction + InflictDirectDamage(etouch.penOther, this, DMT_CLOSERANGE, m_fChargeHitDamage, FLOAT3D(0, 0, 0), vSpeed); + // push it away + vSpeed = vSpeed * m_fChargeHitSpeed; + KickEntity(etouch.penOther, vSpeed); + // stop waiting + stop; + } + pass; + } + } + // if the anim is not yet finished + if (!IsAnimFinished()) { + // wait the rest of time till the anim end + wait(GetCurrentAnimLength() - GetPassedTime()) { + on (EBegin) : { resume; } + on (ETimer) : { stop; } + // if timer expired + on (EReminder) : { + // stop moving + StopMoving(); + resume; + } + } + } + + // return to caller + return EReturn(); + }; + +//********************************************************** +// WOUNDING AND DYING PROCEDURES +//********************************************************** + + // play wounding animation + BeWounded(EDamage eDamage) + { + StopMoving(); + // determine damage anim and play the wounding + autowait(GetAnimLength(AnimForDamage(eDamage.fAmount))); + return EReturn(); + }; + + // we get here once the enemy is dead + Die(EDeath eDeath) + { + // not alive anymore + SetFlags(GetFlags()&~ENF_ALIVE); + + // find the one who killed, or other best suitable player + CEntityPointer penKiller = eDeath.eLastDamage.penInflictor; + if (penKiller==NULL || !IsOfClass(penKiller, "Player")) { + penKiller = m_penEnemy; + } + + if (penKiller==NULL || !IsOfClass(penKiller, "Player")) { + penKiller = FixupCausedToPlayer(this, penKiller, /*bWarning=*/FALSE); + } + + // if killed by someone + if (penKiller!=NULL) { + // give him score + EReceiveScore eScore; + eScore.iPoints = m_iScore; + penKiller->SendEvent(eScore); + if( CountAsKill()) + { + penKiller->SendEvent(EKilledEnemy()); + } + // send computer message if in coop + if (GetSP()->sp_bCooperative) { + EComputerMessage eMsg; + eMsg.fnmMessage = GetComputerMessageName(); + if (eMsg.fnmMessage!="") { + penKiller->SendEvent(eMsg); + } + } + } + + + // destroy watcher class + GetWatcher()->SendEvent(EStop()); + GetWatcher()->SendEvent(EEnd()); + + // send event to death target + SendToTarget(m_penDeathTarget, m_eetDeathType, penKiller); + // send event to spawner if any + // NOTE: trigger's penCaused has been changed from penKiller to THIS; + if (m_penSpawnerTarget) { + SendToTarget(m_penSpawnerTarget, EET_TRIGGER, this); + } + + + // wait + wait() { + // initially + on (EBegin) : { + // if should already blow up + if (ShouldBlowUp()) { + // blow up now + BlowUpBase(); + // stop waiting + stop; + // if shouldn't blow up yet + } else { + // invoke death animation sequence + call DeathSequence(); + } + } + // if damaged + on (EDamage) : { + // if should already blow up + if (ShouldBlowUp()) { + // blow up now + BlowUpBase(); + // stop waiting + stop; + } + // otherwise, ignore the damage + resume; + } + // if death sequence is over + on (EEnd) : { + // stop waiting + stop; + } + } + + // stop making fuss + RemoveFromFuss(); + // cease to exist + Destroy(); + + // all is over now, entity will be deleted + return; + }; + + Death(EVoid) + { + StopMoving(); // stop moving + DeathSound(); // death sound + LeaveStain(FALSE); + + // set physic flags + SetPhysicsFlags(EPF_MODEL_CORPSE); + SetCollisionFlags(ECF_CORPSE); + SetFlags(GetFlags() | ENF_SEETHROUGH); + + // stop making fuss + RemoveFromFuss(); + + // death notify (usually change collision box and change body density) + DeathNotify(); + + // start death anim + INDEX iAnim = AnimForDeath(); + // use tactic variables for temporary data + m_vTacticsStartPosition=FLOAT3D(1,1,1); + m_fTacticVar4=WaitForDust(m_vTacticsStartPosition); + // remember start time + m_fTacticVar5=_pTimer->CurrentTick(); + // mark that we didn't spawned dust yet + m_fTacticVar3=-1; + // if no dust should be spawned + if( m_fTacticVar4<0) + { + autowait(GetAnimLength(iAnim)); + } + // should spawn dust + else if( TRUE) + { + while(_pTimer->CurrentTick()TickQuantum); + if(en_penReference!=NULL && _pTimer->CurrentTick()>=m_fTacticVar5+m_fTacticVar4 && m_fTacticVar3<0) + { + // spawn dust effect + CPlacement3D plFX=GetPlacement(); + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.vStretch = m_vTacticsStartPosition; + ese.vNormal = FLOAT3D(0,1,0); + ese.betType = BET_DUST_FALL; + CPlacement3D plSmoke=plFX; + plSmoke.pl_PositionVector+=FLOAT3D(0,0.35f*m_vTacticsStartPosition(2),0); + CEntityPointer penFX = CreateEntity(plSmoke, CLASS_BASIC_EFFECT); + penFX->Initialize(ese); + penFX->SetParent(this); + // mark that we spawned dust + m_fTacticVar3=1; + } + } + } + + return EEnd(); + }; + + DeathSequence(EVoid) + { + // entity death + autocall Death() EEnd; + + // start bloody stain growing out from beneath the corpse + LeaveStain(TRUE); + + // check if you have attached flame + CEntityPointer penFlame = GetChildOfClass("Flame"); + if (penFlame!=NULL) + { + // send the event to stop burning + EStopFlaming esf; + esf.m_bNow=FALSE; + penFlame->SendEvent(esf); + } + + autowait(2.0f); + + // start fading out and turning into stardust effect + m_fSpiritStartTime = _pTimer->CurrentTick(); + m_fFadeStartTime = _pTimer->CurrentTick(); + m_fFadeTime = 1.0f, + m_bFadeOut = TRUE; + // become passable even if very large corpse + SetCollisionFlags(ECF_CORPSE&~((ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)< stop enemy + on (EStop) : { + jump Inactive(); + } + + // warn for all obsolete events + on (EStartAttack) : { + //CPrintF("%s: StartAttack event is obsolete!\n", GetName()); + resume; + } + on (EStopAttack) : { + //CPrintF("%s: StopAttack event is obsolete!\n", GetName()); + resume; + } + } + }; + + // not doing anything, waiting until some player comes close enough to start patroling or similar + Inactive(EVoid) + { + // stop moving + StopMoving(); + StandingAnim(); + // start watching + GetWatcher()->SendEvent(EStart()); + // wait forever + wait() { + on (EBegin) : { resume; } + // if watcher detects that a player is near + on (EStart) : { + // become active (patroling etc.) + jump Active(); + } + // if returned from wounding + on (EReturn) : { + // become active (this will attack the enemy) + jump Active(); + } + // if triggered manually + on (ETrigger eTrigger) : { + CEntity *penCaused = FixupCausedToPlayer(this, eTrigger.penCaused); + // if can set the trigerer as soft target + if (SetTargetSoft(penCaused)) { + // become active (this will attack the player) + jump Active(); + } + } + // if you get damaged by someone + on (EDamage eDamage) : { + // if can set the damager as hard target + if (SetTargetHard(eDamage.penInflictor)) { + // notify wounding to others + WoundedNotify(eDamage); + // make pain sound + WoundSound(); + // play wounding animation + call BeWounded(eDamage); + } + return; + } + } + }; + + // overridable called before main enemy loop actually begins + PreMainLoop(EVoid) + { + return EReturn(); + } + + // main entry point for enemy behavior + MainLoop(EVoid) + { + // setup some model parameters that are global for all enemies + SizeModel(); + // check that max health is properly set + ASSERT(m_fMaxHealth==GetHealth() || IsOfClass(this, "Devil") || IsOfClass(this, "ExotechLarva") || IsOfClass(this, "AirElemental") || IsOfClass(this, "Summoner")); + + // normalize parameters + if (m_tmReflexMin<0) { + m_tmReflexMin = 0.0f; + } + if (m_tmReflexMin>m_tmReflexMax) { + m_tmReflexMax = m_tmReflexMin; + } + + // adjust falldown and step up values + if (m_fStepHeight==-1) { + m_fStepHeight = 2.0f; + } + + // if this is a template + if (m_bTemplate) { + // do nothing at all + return; + } + + // wait for just one tick + // NOTES: + // if spawned, we have to wait a bit after spawning for spawner to teleport us into proper place + // if placed directly, we have to wait for game to start (not to start behaving while in editor) + // IMPORTANT: + // this wait amount has to be lower than the one in music holder, so that the enemies are initialized before + // they get counted + autowait(_pTimer->TickQuantum); + + // spawn your watcher + m_penWatcher = CreateEntity(GetPlacement(), CLASS_WATCHER); + EWatcherInit eInitWatcher; + eInitWatcher.penOwner = this; + GetWatcher()->Initialize(eInitWatcher); + + // switch to next marker (enemies usually point to the marker they stand on) + if (m_penMarker!=NULL && IsOfClass(m_penMarker, "Enemy Marker")) { + CEnemyMarker *pem = (CEnemyMarker *)&*m_penMarker; + m_penMarker = pem->m_penTarget; + } + + + // store starting position + m_vStartPosition = GetPlacement().pl_PositionVector; + + // set sound default parameters + m_soSound.Set3DParameters(80.0f, 5.0f, 1.0f, 1.0f); + + // adjust falldown and step up values + en_fStepUpHeight = m_fStepHeight+0.01f; + en_fStepDnHeight = m_fFallHeight+0.01f; + + // let derived class(es) adjust parameters if needed + EnemyPostInit(); + + // adjust your difficulty + AdjustDifficulty(); + + // check enemy params + ASSERT(m_fStopDistance>=0); + ASSERT(m_fCloseDistance>=0); + ASSERT(m_fAttackDistance>m_fCloseDistance); + ASSERT(m_fIgnoreRange>m_fAttackDistance); + + SetPredictable(TRUE); + + autocall PreMainLoop() EReturn; + + jump StandardBehavior(); + } + + StandardBehavior(EVoid) + { + // this is the main enemy loop + wait() { + // initially + on (EBegin) : { + // start in active or inactive state + if (m_penEnemy!=NULL) { + call Active(); + } else { + call Inactive(); + } + }; + // if dead + on (EDeath eDeath) : { + // die + jump Die(eDeath); + } + // if an entity exits a teleport nearby + on (ETeleport et) : { + // proceed message to watcher (so watcher can quickly recheck for players) + GetWatcher()->SendEvent(et); + resume; + } + // if should stop being blind + on (EStopBlindness) : { + // stop being blind + m_bBlind = FALSE; + resume; + } + // if should stop being deaf + on (EStopDeafness) : { + // stop being deaf + m_bDeaf = FALSE; + resume; + } + // support for jumping using bouncers + on (ETouch eTouch) : { + IfTargetCrushed(eTouch.penOther, (FLOAT3D&)eTouch.plCollision); + if (IsOfClass(eTouch.penOther, "Bouncer")) { + JumpFromBouncer(this, eTouch.penOther); + } + resume; + } + } + }; + + // dummy main - never called + Main(EVoid) { + return; + }; +}; diff --git a/Sources/EntitiesMP/EnemyBase.h b/Sources/EntitiesMP/EnemyBase.h new file mode 100644 index 0000000..9db4548 --- /dev/null +++ b/Sources/EntitiesMP/EnemyBase.h @@ -0,0 +1,684 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_EnemyBase_INCLUDED +#define _EntitiesMP_EnemyBase_INCLUDED 1 +#include +#include +#include +#include +#include +#include +#include +#define EVENTCODE_ERestartAttack 0x01360000 +class DECL_DLL ERestartAttack : public CEntityEvent { +public: +ERestartAttack(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(ERestartAttack &e) { e = ERestartAttack(); } ; +#define EVENTCODE_EReconsiderBehavior 0x01360001 +class DECL_DLL EReconsiderBehavior : public CEntityEvent { +public: +EReconsiderBehavior(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EReconsiderBehavior &e) { e = EReconsiderBehavior(); } ; +#define EVENTCODE_EForceWound 0x01360002 +class DECL_DLL EForceWound : public CEntityEvent { +public: +EForceWound(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EForceWound &e) { e = EForceWound(); } ; +extern DECL_DLL CEntityPropertyEnumType TargetType_enum; +enum TargetType { + TT_NONE = 0, + TT_SOFT = 1, + TT_HARD = 2, +}; +DECL_DLL inline void ClearToDefault(TargetType &e) { e = (TargetType)0; } ; +extern DECL_DLL CEntityPropertyEnumType DestinationType_enum; +enum DestinationType { + DT_PLAYERCURRENT = 0, + DT_PLAYERSPOTTED = 1, + DT_PATHTEMPORARY = 2, + DT_PATHPERSISTENT = 3, +}; +DECL_DLL inline void ClearToDefault(DestinationType &e) { e = (DestinationType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CEnemyBase_DLLClass; +class DECL_DLL CEnemyBase : public CMovableModelEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + virtual void SetDefaultProperties(void); + CEntityPointer m_penWatcher; + FLOAT3D m_vStartPosition; + CEntityPointer m_penEnemy; + enum TargetType m_ttTarget; + CTString m_strDescription; + CTString m_strName; + CSoundObject m_soSound; + FLOAT3D m_vStartDirection; + BOOL m_bOnStartPosition; + FLOAT m_fFallHeight; + FLOAT m_fStepHeight; + RANGE m_fSenseRange; + FLOAT m_fViewAngle; + FLOAT m_fWalkSpeed; + ANGLE m_aWalkRotateSpeed; + FLOAT m_fAttackRunSpeed; + ANGLE m_aAttackRotateSpeed; + FLOAT m_fCloseRunSpeed; + ANGLE m_aCloseRotateSpeed; + FLOAT m_fAttackDistance; + FLOAT m_fCloseDistance; + FLOAT m_fAttackFireTime; + FLOAT m_fCloseFireTime; + FLOAT m_fStopDistance; + FLOAT m_fIgnoreRange; + FLOAT m_fLockOnEnemyTime; + FLOAT m_fBlowUpAmount; + INDEX m_fBodyParts; + FLOAT m_fDamageWounded; + FLOAT3D m_vDamage; + FLOAT m_tmLastDamage; + BOOL m_bRobotBlowup; + FLOAT m_fBlowUpSize; + FLOAT m_fMoveTime; + FLOAT3D m_vDesiredPosition; + enum DestinationType m_dtDestination; + CEntityPointer m_penPathMarker; + FLOAT3D m_vPlayerSpotted; + FLOAT m_fMoveFrequency; + FLOAT m_fMoveSpeed; + ANGLE m_aRotateSpeed; + FLOAT m_fLockStartTime; + FLOAT m_fRangeLast; + BOOL m_bFadeOut; + FLOAT m_fFadeStartTime; + FLOAT m_fFadeTime; + FLOAT m_fShootTime; + FLOAT m_fDamageConfused; + INDEX m_iChargeHitAnimation; + FLOAT m_fChargeHitDamage; + FLOAT m_fChargeHitAngle; + FLOAT m_fChargeHitSpeed; + CEntityPointer m_penSpawnerTarget; + CEntityPointer m_penDeathTarget; + enum EventEType m_eetDeathType; + BOOL m_bTemplate; + RANGE m_fAttackRadius; + COLOR m_colColor; + BOOL m_bDeaf; + BOOL m_bBlind; + FLOAT m_tmGiveUp; + FLOAT m_tmReflexMin; + FLOAT m_tmReflexMax; + FLOAT m_fActivityRange; + BOOL m_bApplyRandomStretch; + FLOAT m_fRandomStretchFactor; + FLOAT m_fStretchMultiplier; + FLOAT m_fRandomStretchMultiplier; + CEntityPointer m_penMarker; + CEntityPointer m_penMainMusicHolder; + FLOAT m_tmLastFussTime; + FLOAT m_iScore; + FLOAT m_fMaxHealth; + BOOL m_bBoss; + FLOAT m_fSpiritStartTime; + FLOAT m_tmSpraySpawned; + FLOAT m_fSprayDamage; + CEntityPointer m_penSpray; + FLOAT m_fMaxDamageAmmount; + FLOAT3D m_vLastStain; + enum SprayParticlesType m_sptType; + CEntityPointer m_penTacticsHolder; + BOOL m_bTacticActive; + FLOAT m_tmTacticsActivation; + FLOAT3D m_vTacticsStartPosition; + FLOAT m_fTacticVar1; + FLOAT m_fTacticVar2; + FLOAT m_fTacticVar3; + FLOAT m_fTacticVar4; + FLOAT m_fTacticVar5; + BOOL m_bTacticsStartOnSense; + COLOR m_colBurning; + BOOL m_bResizeAttachments; + CEntityPointer m_penPrediction; +TIME m_tmPredict; + CEnemyBase(void); + +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void SetPredictionTime(TIME tmAdvance); + +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +TIME GetPredictionTime(void); + +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual FLOAT GetCrushHealth(void); + +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual BOOL CountAsKill(void); + +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual BOOL ForcesCannonballToExplode(void); + +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual FLOAT & GetProp(FLOAT & m_fBase); + +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual FLOAT GetThreatDistance(void); + +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void MaybeSwitchToAnotherPlayer(void); + +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +class CWatcher * GetWatcher(void); + void Copy(CEntity & enOther,ULONG ulFlags); + +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void Precache(void); + +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual FLOAT3D PlayerDestinationPos(void); + +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D CalcDelta(CEntity * penEntity); + +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT CalcDist(CEntity * penEntity); + +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL IfTargetCrushed(CEntity * penOther,const FLOAT3D & vDirection); + +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D CalcPlaneDelta(CEntity * penEntity); + +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT CalcPlaneDist(CEntity * penEntity); + +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT GetFrustumAngle(const FLOAT3D & vDir); + +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT GetPlaneFrustumAngle(const FLOAT3D & vDir); + +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL IsInFrustum(CEntity * penEntity,FLOAT fCosHalfFrustum); + +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL IsInPlaneFrustum(CEntity * penEntity,FLOAT fCosHalfFrustum); + +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL IsVisible(CEntity * penEntity); + +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL IsVisibleCheckAll(CEntity * penEntity); + +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void CalculateAngularLaunchParams( +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vShooting,FLOAT fShootHeight, +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D vTarget,FLOAT3D vSpeedDest, +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ANGLE aPitch, +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT & fLaunchSpeed, +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT & fRelativeHdg); + +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D CalculatePredictedPosition(FLOAT3D vShootPos,FLOAT3D vTarget, +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fSpeedSrc,FLOAT3D vSpeedDst,FLOAT fClampY); + +#line 534 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +const CTString & GetDescription(void)const; + +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void AddDependentsToPrediction(void); + +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void ChecksumForSync(ULONG & ulCRC,INDEX iExtensiveSyncCheck); + +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck); + +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void Read_t(CTStream * istr); + +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 616 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 782 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 844 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void AddToFuss(void); + +#line 884 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void RemoveFromFuss(void); + +#line 907 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL ShouldCeaseAttack(void); + +#line 926 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void SizeModel(void); + +#line 954 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL IsValidForEnemy(CEntity * penPlayer); + +#line 963 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void SetTargetNone(void); + +#line 971 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL SetTargetSoft(CEntity * penPlayer); + +#line 992 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL SetTargetHard(CEntity * penPlayer); + +#line 1013 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL SetTargetHardForce(CEntity * penPlayer); + +#line 1033 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual FLOAT GetAttackMoveFrequency(FLOAT fEnemyDistance); + +#line 1043 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void SetSpeedsToDesiredPosition(const FLOAT3D & vPosDelta,FLOAT fPosDist,BOOL bGoingToPlayer); + +#line 1102 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void MovementAnimation(ULONG ulFlags); + +#line 1124 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual ULONG SetDesiredMovement(void); + +#line 1193 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void StopMoving(); + +#line 1200 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void StopRotating(); + +#line 1206 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void StopTranslating(); + +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT CalcDistanceInPlaneToDestination(void); + +#line 1221 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void StartPathFinding(void); + +#line 1245 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void FindNextPathMarker(void); + +#line 1278 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CheckTouchForPathFinding(const ETouch & eTouch); + +#line 1310 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CheckFallForPathFinding(const EWouldFall & eWouldFall); + +#line 1338 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void InitializeTactics(void); + +#line 1404 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void ApplyTactics(FLOAT3D & vDesiredPos); + +#line 1533 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void StartTacticsNow(void); + +#line 1541 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL CanAttackEnemy(CEntity * penTarget,FLOAT fCosAngle); + +#line 1551 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual BOOL CanHitEnemy(CEntity * penTarget,FLOAT fCosAngle); + +#line 1559 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL SeeEntity(CEntity * pen,FLOAT fCosAngle); + +#line 1567 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL SeeEntityInPlane(CEntity * pen,FLOAT fCosAngle); + +#line 1576 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void PreparePropelledProjectile(CPlacement3D & plProjectile,FLOAT3D vShootTarget, +#line 1577 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D & vOffset,ANGLE3D & aOffset); + +#line 1600 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void PrepareFreeFlyingProjectile(CPlacement3D & plProjectile,FLOAT3D vShootTarget, +#line 1601 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D & vOffset,ANGLE3D & aOffset); + +#line 1624 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * ShootProjectile(enum ProjectileType pt,FLOAT3D & vOffset,ANGLE3D & aOffset); + +#line 1646 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * ShootProjectileAt(FLOAT3D vShootTarget,enum ProjectileType pt,FLOAT3D & vOffset,ANGLE3D & aOffset); + +#line 1661 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +CEntity * ShootPredictedProjectile(enum ProjectileType pt,FLOAT3D vPredictedPos,FLOAT3D & vOffset,ANGLE3D & aOffset); + +#line 1687 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL WouldNotLeaveAttackRadius(void); + +#line 1702 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual BOOL MayMoveToAttack(void); + +#line 1717 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual BOOL ShouldBlowUp(void); + +#line 1736 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void BlowUpBase(void); + +#line 1744 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void BlowUp(void); + +#line 1816 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void LeaveStain(BOOL bGrow); + +#line 1851 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void AdjustDifficulty(void); + +#line 1885 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void WoundedNotify(const EDamage & eDamage); + +#line 1904 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void SeeNotify(); + +#line 1923 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void StandingAnim(void); + +#line 1924 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void StandingAnimFight(void); + +#line 1925 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void WalkingAnim(void); + +#line 1926 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void RunningAnim(void); + +#line 1927 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void RotatingAnim(void); + +#line 1928 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void ChargeAnim(void); + +#line 1929 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual INDEX AnimForDamage(FLOAT fDamage); + +#line 1930 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void BlowUpNotify(void); + +#line 1931 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual INDEX AnimForDeath(void); + +#line 1932 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 1933 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void DeathNotify(void); + +#line 1934 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void IdleSound(void); + +#line 1935 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void SightSound(void); + +#line 1936 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void WoundSound(void); + +#line 1937 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void DeathSound(void); + +#line 1938 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual FLOAT GetLockRotationSpeed(void); + +#line 1942 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void RenderParticles(void); + +#line 1957 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +virtual void EnemyPostInit(void); + +#line 1960 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL HandleEvent(const CEntityEvent & ee); + +#line 1980 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT GetAnimLength(int iAnim); + +#line 1990 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT GetCurrentAnimLength(); + +#line 2000 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BOOL IsAnimFinished(); + +#line 2010 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT GetPassedTime(); + +#line 2019 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FLOAT3D & GetModelStretch(); + +#line 2029 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void StretchModel(FLOAT3D vStretch); + +#line 2039 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +void StretchSingleModel(FLOAT3D vStretch); + +#line 2050 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +SLONG GetUsedMemory(void); +#define STATE_CEnemyBase_MoveToDestination 0x01360003 + BOOL +#line 2070 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MoveToDestination(const CEntityEvent &__eeInput); + BOOL H0x01360004_MoveToDestination_01(const CEntityEvent &__eeInput); + BOOL H0x01360005_MoveToDestination_02(const CEntityEvent &__eeInput); + BOOL H0x01360006_MoveToDestination_03(const CEntityEvent &__eeInput); + BOOL H0x01360007_MoveToDestination_04(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_MoveToRandomPatrolPosition 0x01360008 + BOOL +#line 2095 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MoveToRandomPatrolPosition(const CEntityEvent &__eeInput); + BOOL H0x01360009_MoveToRandomPatrolPosition_01(const CEntityEvent &__eeInput); + BOOL H0x0136000a_MoveToRandomPatrolPosition_02(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_DoPatrolling 0x0136000b + BOOL +#line 2135 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +DoPatrolling(const CEntityEvent &__eeInput); + BOOL H0x0136000c_DoPatrolling_01(const CEntityEvent &__eeInput); + BOOL H0x0136000d_DoPatrolling_02(const CEntityEvent &__eeInput); + BOOL H0x0136000e_DoPatrolling_03(const CEntityEvent &__eeInput); + BOOL H0x0136000f_DoPatrolling_04(const CEntityEvent &__eeInput); + BOOL H0x01360010_DoPatrolling_05(const CEntityEvent &__eeInput); + BOOL H0x01360011_DoPatrolling_06(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_BeIdle 0x01360012 + BOOL +#line 2150 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BeIdle(const CEntityEvent &__eeInput); + BOOL H0x01360013_BeIdle_01(const CEntityEvent &__eeInput); + BOOL H0x01360014_BeIdle_02(const CEntityEvent &__eeInput); + BOOL H0x01360015_BeIdle_03(const CEntityEvent &__eeInput); + BOOL H0x01360016_BeIdle_04(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_ReturnToStartPosition 0x01360017 + BOOL +#line 2168 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ReturnToStartPosition(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_MoveThroughMarkers 0x01360018 + BOOL +#line 2212 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MoveThroughMarkers(const CEntityEvent &__eeInput); + BOOL H0x01360019_MoveThroughMarkers_01(const CEntityEvent &__eeInput); + BOOL H0x0136001a_MoveThroughMarkers_02(const CEntityEvent &__eeInput); + BOOL H0x0136001b_MoveThroughMarkers_03(const CEntityEvent &__eeInput); + BOOL H0x0136001c_MoveThroughMarkers_04(const CEntityEvent &__eeInput); + BOOL H0x0136001d_MoveThroughMarkers_05(const CEntityEvent &__eeInput); + BOOL H0x0136001e_MoveThroughMarkers_06(const CEntityEvent &__eeInput); + BOOL H0x0136001f_MoveThroughMarkers_07(const CEntityEvent &__eeInput); + BOOL H0x01360020_MoveThroughMarkers_08(const CEntityEvent &__eeInput); + BOOL H0x01360021_MoveThroughMarkers_09(const CEntityEvent &__eeInput); + BOOL H0x01360022_MoveThroughMarkers_10(const CEntityEvent &__eeInput); + BOOL H0x01360023_MoveThroughMarkers_11(const CEntityEvent &__eeInput); + BOOL H0x01360024_MoveThroughMarkers_12(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_NewEnemySpotted 0x01360025 + BOOL +#line 2310 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +NewEnemySpotted(const CEntityEvent &__eeInput); + BOOL H0x01360026_NewEnemySpotted_01(const CEntityEvent &__eeInput); + BOOL H0x01360027_NewEnemySpotted_02(const CEntityEvent &__eeInput); + BOOL H0x01360028_NewEnemySpotted_03(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_StopAttack 0x01360029 + BOOL +#line 2342 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopAttack(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_InitializeAttack 0x0136002a + BOOL +#line 2355 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +InitializeAttack(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_AttackEnemy 0x0136002b + BOOL +#line 2381 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +AttackEnemy(const CEntityEvent &__eeInput); + BOOL H0x0136002c_AttackEnemy_01(const CEntityEvent &__eeInput); + BOOL H0x0136002d_AttackEnemy_02(const CEntityEvent &__eeInput); + BOOL H0x0136002e_AttackEnemy_03(const CEntityEvent &__eeInput); + BOOL H0x0136002f_AttackEnemy_04(const CEntityEvent &__eeInput); + BOOL H0x01360030_AttackEnemy_05(const CEntityEvent &__eeInput); + BOOL H0x01360031_AttackEnemy_06(const CEntityEvent &__eeInput); + BOOL H0x01360032_AttackEnemy_07(const CEntityEvent &__eeInput); + BOOL H0x01360033_AttackEnemy_08(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_PerformAttack 0x01360034 + BOOL +#line 2399 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PerformAttack(const CEntityEvent &__eeInput); + BOOL H0x01360035_PerformAttack_01(const CEntityEvent &__eeInput); + BOOL H0x01360036_PerformAttack_02(const CEntityEvent &__eeInput); + BOOL H0x01360037_PerformAttack_03(const CEntityEvent &__eeInput); + BOOL H0x01360038_PerformAttack_04(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_FireOrHit 0x01360039 + BOOL +#line 2587 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FireOrHit(const CEntityEvent &__eeInput); + BOOL H0x0136003a_FireOrHit_01(const CEntityEvent &__eeInput); + BOOL H0x0136003b_FireOrHit_02(const CEntityEvent &__eeInput); + BOOL H0x0136003c_FireOrHit_03(const CEntityEvent &__eeInput); + BOOL H0x0136003d_FireOrHit_04(const CEntityEvent &__eeInput); + BOOL H0x0136003e_FireOrHit_05(const CEntityEvent &__eeInput); + BOOL H0x0136003f_FireOrHit_06(const CEntityEvent &__eeInput); + BOOL H0x01360040_FireOrHit_07(const CEntityEvent &__eeInput); + BOOL H0x01360041_FireOrHit_08(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_Hit 0x01360042 + BOOL +#line 2630 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Hit(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_Fire 0x01360043 + BOOL +#line 2636 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Fire(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_LockOnEnemy 0x01360044 + BOOL +#line 2646 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +LockOnEnemy(const CEntityEvent &__eeInput); + BOOL H0x01360045_LockOnEnemy_01(const CEntityEvent &__eeInput); + BOOL H0x01360046_LockOnEnemy_02(const CEntityEvent &__eeInput); + BOOL H0x01360047_LockOnEnemy_03(const CEntityEvent &__eeInput); + BOOL H0x01360048_LockOnEnemy_04(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_ChargeHitEnemy 0x01360049 + BOOL +#line 2685 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ChargeHitEnemy(const CEntityEvent &__eeInput); + BOOL H0x0136004a_ChargeHitEnemy_01(const CEntityEvent &__eeInput); + BOOL H0x0136004b_ChargeHitEnemy_02(const CEntityEvent &__eeInput); + BOOL H0x0136004c_ChargeHitEnemy_03(const CEntityEvent &__eeInput); + BOOL H0x0136004d_ChargeHitEnemy_04(const CEntityEvent &__eeInput); + BOOL H0x0136004e_ChargeHitEnemy_05(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_BeWounded 0x0136004f + BOOL +#line 2741 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BeWounded(const CEntityEvent &__eeInput); + BOOL H0x01360050_BeWounded_01(const CEntityEvent &__eeInput); + BOOL H0x01360051_BeWounded_02(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_Die 0x01360052 + BOOL +#line 2750 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Die(const CEntityEvent &__eeInput); + BOOL H0x01360053_Die_01(const CEntityEvent &__eeInput); + BOOL H0x01360054_Die_02(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_Death 0x01360055 + BOOL +#line 2843 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Death(const CEntityEvent &__eeInput); + BOOL H0x01360056_Death_01(const CEntityEvent &__eeInput); + BOOL H0x01360057_Death_02(const CEntityEvent &__eeInput); + BOOL H0x01360058_Death_03(const CEntityEvent &__eeInput); + BOOL H0x01360059_Death_04(const CEntityEvent &__eeInput); + BOOL H0x0136005a_Death_05(const CEntityEvent &__eeInput); + BOOL H0x0136005b_Death_06(const CEntityEvent &__eeInput); + BOOL H0x0136005c_Death_07(const CEntityEvent &__eeInput); + BOOL H0x0136005d_Death_08(const CEntityEvent &__eeInput); + BOOL H0x0136005e_Death_09(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_DeathSequence 0x0136005f + BOOL +#line 2903 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +DeathSequence(const CEntityEvent &__eeInput); + BOOL H0x01360060_DeathSequence_01(const CEntityEvent &__eeInput); + BOOL H0x01360061_DeathSequence_02(const CEntityEvent &__eeInput); + BOOL H0x01360062_DeathSequence_03(const CEntityEvent &__eeInput); + BOOL H0x01360063_DeathSequence_04(const CEntityEvent &__eeInput); + BOOL H0x01360064_DeathSequence_05(const CEntityEvent &__eeInput); + BOOL H0x01360065_DeathSequence_06(const CEntityEvent &__eeInput); + BOOL H0x01360066_DeathSequence_07(const CEntityEvent &__eeInput); + BOOL H0x01360067_DeathSequence_08(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_Active 0x01360068 + BOOL +#line 2942 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Active(const CEntityEvent &__eeInput); + BOOL H0x01360069_Active_01(const CEntityEvent &__eeInput); + BOOL H0x0136006a_Active_02(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_Inactive 0x0136006b + BOOL +#line 3081 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Inactive(const CEntityEvent &__eeInput); + BOOL H0x0136006c_Inactive_01(const CEntityEvent &__eeInput); + BOOL H0x0136006d_Inactive_02(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_PreMainLoop 0x0136006e + BOOL +#line 3127 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PreMainLoop(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_MainLoop 0x0136006f + BOOL +#line 3133 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MainLoop(const CEntityEvent &__eeInput); + BOOL H0x01360070_MainLoop_01(const CEntityEvent &__eeInput); + BOOL H0x01360071_MainLoop_02(const CEntityEvent &__eeInput); + BOOL H0x01360072_MainLoop_03(const CEntityEvent &__eeInput); + BOOL H0x01360073_MainLoop_04(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_StandardBehavior 0x01360074 + BOOL +#line 3210 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StandardBehavior(const CEntityEvent &__eeInput); + BOOL H0x01360075_StandardBehavior_01(const CEntityEvent &__eeInput); + BOOL H0x01360076_StandardBehavior_02(const CEntityEvent &__eeInput); +#define STATE_CEnemyBase_Main 1 + BOOL +#line 3258 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_EnemyBase_INCLUDED diff --git a/Sources/EntitiesMP/EnemyBase_tables.h b/Sources/EntitiesMP/EnemyBase_tables.h new file mode 100644 index 0000000..dc975c5 --- /dev/null +++ b/Sources/EntitiesMP/EnemyBase_tables.h @@ -0,0 +1,344 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(TargetType) + EP_ENUMVALUE(TT_NONE, ""), + EP_ENUMVALUE(TT_SOFT, ""), + EP_ENUMVALUE(TT_HARD, ""), +EP_ENUMEND(TargetType); + +EP_ENUMBEG(DestinationType) + EP_ENUMVALUE(DT_PLAYERCURRENT, ""), + EP_ENUMVALUE(DT_PLAYERSPOTTED, ""), + EP_ENUMVALUE(DT_PATHTEMPORARY, ""), + EP_ENUMVALUE(DT_PATHPERSISTENT, ""), +EP_ENUMEND(DestinationType); + +#define ENTITYCLASS CEnemyBase + +CEntityProperty CEnemyBase_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000136<<8)+1, offsetof(CEnemyBase, m_penWatcher), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000136<<8)+2, offsetof(CEnemyBase, m_vStartPosition), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000136<<8)+3, offsetof(CEnemyBase, m_penEnemy), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &TargetType_enum, (0x00000136<<8)+4, offsetof(CEnemyBase, m_ttTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000136<<8)+5, offsetof(CEnemyBase, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000136<<8)+6, offsetof(CEnemyBase, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000136<<8)+7, offsetof(CEnemyBase, m_soSound), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000136<<8)+8, offsetof(CEnemyBase, m_vStartDirection), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000136<<8)+9, offsetof(CEnemyBase, m_bOnStartPosition), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+29, offsetof(CEnemyBase, m_fFallHeight), "Fall height", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+31, offsetof(CEnemyBase, m_fStepHeight), "Step height", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000136<<8)+17, offsetof(CEnemyBase, m_fSenseRange), "Sense Range", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+28, offsetof(CEnemyBase, m_fViewAngle), "View angle", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+10, offsetof(CEnemyBase, m_fWalkSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000136<<8)+11, offsetof(CEnemyBase, m_aWalkRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+12, offsetof(CEnemyBase, m_fAttackRunSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000136<<8)+13, offsetof(CEnemyBase, m_aAttackRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+14, offsetof(CEnemyBase, m_fCloseRunSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000136<<8)+15, offsetof(CEnemyBase, m_aCloseRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+20, offsetof(CEnemyBase, m_fAttackDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+21, offsetof(CEnemyBase, m_fCloseDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+22, offsetof(CEnemyBase, m_fAttackFireTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+23, offsetof(CEnemyBase, m_fCloseFireTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+24, offsetof(CEnemyBase, m_fStopDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+25, offsetof(CEnemyBase, m_fIgnoreRange), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+26, offsetof(CEnemyBase, m_fLockOnEnemyTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+40, offsetof(CEnemyBase, m_fBlowUpAmount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000136<<8)+41, offsetof(CEnemyBase, m_fBodyParts), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+42, offsetof(CEnemyBase, m_fDamageWounded), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000136<<8)+43, offsetof(CEnemyBase, m_vDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+44, offsetof(CEnemyBase, m_tmLastDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000136<<8)+46, offsetof(CEnemyBase, m_bRobotBlowup), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+47, offsetof(CEnemyBase, m_fBlowUpSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+133, offsetof(CEnemyBase, m_fMoveTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000136<<8)+52, offsetof(CEnemyBase, m_vDesiredPosition), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DestinationType_enum, (0x00000136<<8)+53, offsetof(CEnemyBase, m_dtDestination), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000136<<8)+59, offsetof(CEnemyBase, m_penPathMarker), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000136<<8)+18, offsetof(CEnemyBase, m_vPlayerSpotted), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+54, offsetof(CEnemyBase, m_fMoveFrequency), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+55, offsetof(CEnemyBase, m_fMoveSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000136<<8)+56, offsetof(CEnemyBase, m_aRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+57, offsetof(CEnemyBase, m_fLockStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+58, offsetof(CEnemyBase, m_fRangeLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000136<<8)+130, offsetof(CEnemyBase, m_bFadeOut), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+131, offsetof(CEnemyBase, m_fFadeStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+132, offsetof(CEnemyBase, m_fFadeTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+60, offsetof(CEnemyBase, m_fShootTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+61, offsetof(CEnemyBase, m_fDamageConfused), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000136<<8)+62, offsetof(CEnemyBase, m_iChargeHitAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+63, offsetof(CEnemyBase, m_fChargeHitDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+64, offsetof(CEnemyBase, m_fChargeHitAngle), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+65, offsetof(CEnemyBase, m_fChargeHitSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000136<<8)+83, offsetof(CEnemyBase, m_penSpawnerTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000136<<8)+84, offsetof(CEnemyBase, m_penDeathTarget), "Death target", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x00000136<<8)+85, offsetof(CEnemyBase, m_eetDeathType), "Death event type", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000136<<8)+86, offsetof(CEnemyBase, m_bTemplate), "Template", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000136<<8)+88, offsetof(CEnemyBase, m_fAttackRadius), "Radius of attack", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x00000136<<8)+89, offsetof(CEnemyBase, m_colColor), "Color", 'L', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000136<<8)+90, offsetof(CEnemyBase, m_bDeaf), "Deaf", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000136<<8)+91, offsetof(CEnemyBase, m_bBlind), "Blind", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+92, offsetof(CEnemyBase, m_tmGiveUp), "Give up time", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+93, offsetof(CEnemyBase, m_tmReflexMin), "Reflex Min", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+94, offsetof(CEnemyBase, m_tmReflexMax), "Reflex Max", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+95, offsetof(CEnemyBase, m_fActivityRange), "Activity Range", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000136<<8)+106, offsetof(CEnemyBase, m_bApplyRandomStretch), "Apply random stretch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+107, offsetof(CEnemyBase, m_fRandomStretchFactor), "Random stretch factor", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+108, offsetof(CEnemyBase, m_fStretchMultiplier), "Stretch multiplier", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+109, offsetof(CEnemyBase, m_fRandomStretchMultiplier), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000136<<8)+120, offsetof(CEnemyBase, m_penMarker), "Marker", 'M', C_RED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000136<<8)+140, offsetof(CEnemyBase, m_penMainMusicHolder), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+141, offsetof(CEnemyBase, m_tmLastFussTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+142, offsetof(CEnemyBase, m_iScore), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+143, offsetof(CEnemyBase, m_fMaxHealth), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000136<<8)+144, offsetof(CEnemyBase, m_bBoss), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+145, offsetof(CEnemyBase, m_fSpiritStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+146, offsetof(CEnemyBase, m_tmSpraySpawned), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+147, offsetof(CEnemyBase, m_fSprayDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000136<<8)+148, offsetof(CEnemyBase, m_penSpray), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+149, offsetof(CEnemyBase, m_fMaxDamageAmmount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000136<<8)+150, offsetof(CEnemyBase, m_vLastStain), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &SprayParticlesType_enum, (0x00000136<<8)+151, offsetof(CEnemyBase, m_sptType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000136<<8)+160, offsetof(CEnemyBase, m_penTacticsHolder), "Tactics Holder", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000136<<8)+161, offsetof(CEnemyBase, m_bTacticActive), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+162, offsetof(CEnemyBase, m_tmTacticsActivation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000136<<8)+163, offsetof(CEnemyBase, m_vTacticsStartPosition), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+165, offsetof(CEnemyBase, m_fTacticVar1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+166, offsetof(CEnemyBase, m_fTacticVar2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+167, offsetof(CEnemyBase, m_fTacticVar3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+168, offsetof(CEnemyBase, m_fTacticVar4), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000136<<8)+169, offsetof(CEnemyBase, m_fTacticVar5), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000136<<8)+170, offsetof(CEnemyBase, m_bTacticsStartOnSense), "Tactics start on sense", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x00000136<<8)+180, offsetof(CEnemyBase, m_colBurning), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000136<<8)+181, offsetof(CEnemyBase, m_bResizeAttachments), "Stretch attachments", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000136<<8)+255, offsetof(CEnemyBase, m_penPrediction), "", 0, 0, 0), +}; +#define CEnemyBase_propertiesct ARRAYCOUNT(CEnemyBase_properties) + +CEntityComponent CEnemyBase_components[] = { +#define CLASS_WATCHER ((0x00000136<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_WATCHER, "EFNM" "Classes\\Watcher.ecl"), +#define CLASS_PROJECTILE ((0x00000136<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_DEBRIS ((0x00000136<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_DEBRIS, "EFNM" "Classes\\Debris.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000136<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_BLOOD_SPRAY ((0x00000136<<8)+5) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define MODEL_FLESH ((0x00000136<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_FLESH, "EFNM" "Models\\Effects\\Debris\\Flesh\\Flesh.mdl"), +#define MODEL_FLESH_APPLE ((0x00000136<<8)+11) + CEntityComponent(ECT_MODEL, MODEL_FLESH_APPLE, "EFNM" "Models\\Effects\\Debris\\Fruits\\Apple.mdl"), +#define MODEL_FLESH_BANANA ((0x00000136<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_FLESH_BANANA, "EFNM" "Models\\Effects\\Debris\\Fruits\\Banana.mdl"), +#define MODEL_FLESH_BURGER ((0x00000136<<8)+13) + CEntityComponent(ECT_MODEL, MODEL_FLESH_BURGER, "EFNM" "Models\\Effects\\Debris\\Fruits\\CheeseBurger.mdl"), +#define MODEL_FLESH_LOLLY ((0x00000136<<8)+14) + CEntityComponent(ECT_MODEL, MODEL_FLESH_LOLLY, "EFNM" "Models\\Effects\\Debris\\Fruits\\LollyPop.mdl"), +#define MODEL_FLESH_ORANGE ((0x00000136<<8)+15) + CEntityComponent(ECT_MODEL, MODEL_FLESH_ORANGE, "EFNM" "Models\\Effects\\Debris\\Fruits\\Orange.mdl"), +#define TEXTURE_FLESH_RED ((0x00000136<<8)+20) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_RED, "EFNM" "Models\\Effects\\Debris\\Flesh\\FleshRed.tex"), +#define TEXTURE_FLESH_GREEN ((0x00000136<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_GREEN, "EFNM" "Models\\Effects\\Debris\\Flesh\\FleshGreen.tex"), +#define TEXTURE_FLESH_APPLE ((0x00000136<<8)+22) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_APPLE, "EFNM" "Models\\Effects\\Debris\\Fruits\\Apple.tex"), +#define TEXTURE_FLESH_BANANA ((0x00000136<<8)+23) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_BANANA, "EFNM" "Models\\Effects\\Debris\\Fruits\\Banana.tex"), +#define TEXTURE_FLESH_BURGER ((0x00000136<<8)+24) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_BURGER, "EFNM" "Models\\Effects\\Debris\\Fruits\\CheeseBurger.tex"), +#define TEXTURE_FLESH_LOLLY ((0x00000136<<8)+25) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_LOLLY, "EFNM" "Models\\Effects\\Debris\\Fruits\\LollyPop.tex"), +#define TEXTURE_FLESH_ORANGE ((0x00000136<<8)+26) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_ORANGE, "EFNM" "Models\\Effects\\Debris\\Fruits\\Orange.tex"), +#define MODEL_MACHINE ((0x00000136<<8)+31) + CEntityComponent(ECT_MODEL, MODEL_MACHINE, "EFNM" "Models\\Effects\\Debris\\Stone\\Stone.mdl"), +#define TEXTURE_MACHINE ((0x00000136<<8)+32) + CEntityComponent(ECT_TEXTURE, TEXTURE_MACHINE, "EFNM" "Models\\Effects\\Debris\\Stone\\Stone.tex"), +}; +#define CEnemyBase_componentsct ARRAYCOUNT(CEnemyBase_components) + +CEventHandlerEntry CEnemyBase_handlers[] = { + {0x01360003, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2070 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MoveToDestination),DEBUGSTRING("CEnemyBase::MoveToDestination")}, + {0x01360004, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360004_MoveToDestination_01), DEBUGSTRING("CEnemyBase::H0x01360004_MoveToDestination_01")}, + {0x01360005, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360005_MoveToDestination_02), DEBUGSTRING("CEnemyBase::H0x01360005_MoveToDestination_02")}, + {0x01360006, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360006_MoveToDestination_03), DEBUGSTRING("CEnemyBase::H0x01360006_MoveToDestination_03")}, + {0x01360007, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360007_MoveToDestination_04), DEBUGSTRING("CEnemyBase::H0x01360007_MoveToDestination_04")}, + {0x01360008, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2095 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MoveToRandomPatrolPosition),DEBUGSTRING("CEnemyBase::MoveToRandomPatrolPosition")}, + {0x01360009, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360009_MoveToRandomPatrolPosition_01), DEBUGSTRING("CEnemyBase::H0x01360009_MoveToRandomPatrolPosition_01")}, + {0x0136000a, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136000a_MoveToRandomPatrolPosition_02), DEBUGSTRING("CEnemyBase::H0x0136000a_MoveToRandomPatrolPosition_02")}, + {0x0136000b, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2135 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +DoPatrolling),DEBUGSTRING("CEnemyBase::DoPatrolling")}, + {0x0136000c, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136000c_DoPatrolling_01), DEBUGSTRING("CEnemyBase::H0x0136000c_DoPatrolling_01")}, + {0x0136000d, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136000d_DoPatrolling_02), DEBUGSTRING("CEnemyBase::H0x0136000d_DoPatrolling_02")}, + {0x0136000e, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136000e_DoPatrolling_03), DEBUGSTRING("CEnemyBase::H0x0136000e_DoPatrolling_03")}, + {0x0136000f, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136000f_DoPatrolling_04), DEBUGSTRING("CEnemyBase::H0x0136000f_DoPatrolling_04")}, + {0x01360010, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360010_DoPatrolling_05), DEBUGSTRING("CEnemyBase::H0x01360010_DoPatrolling_05")}, + {0x01360011, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360011_DoPatrolling_06), DEBUGSTRING("CEnemyBase::H0x01360011_DoPatrolling_06")}, + {0x01360012, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2150 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BeIdle),DEBUGSTRING("CEnemyBase::BeIdle")}, + {0x01360013, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360013_BeIdle_01), DEBUGSTRING("CEnemyBase::H0x01360013_BeIdle_01")}, + {0x01360014, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360014_BeIdle_02), DEBUGSTRING("CEnemyBase::H0x01360014_BeIdle_02")}, + {0x01360015, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360015_BeIdle_03), DEBUGSTRING("CEnemyBase::H0x01360015_BeIdle_03")}, + {0x01360016, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360016_BeIdle_04), DEBUGSTRING("CEnemyBase::H0x01360016_BeIdle_04")}, + {0x01360017, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2168 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ReturnToStartPosition),DEBUGSTRING("CEnemyBase::ReturnToStartPosition")}, + {0x01360018, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2212 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MoveThroughMarkers),DEBUGSTRING("CEnemyBase::MoveThroughMarkers")}, + {0x01360019, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360019_MoveThroughMarkers_01), DEBUGSTRING("CEnemyBase::H0x01360019_MoveThroughMarkers_01")}, + {0x0136001a, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136001a_MoveThroughMarkers_02), DEBUGSTRING("CEnemyBase::H0x0136001a_MoveThroughMarkers_02")}, + {0x0136001b, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136001b_MoveThroughMarkers_03), DEBUGSTRING("CEnemyBase::H0x0136001b_MoveThroughMarkers_03")}, + {0x0136001c, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136001c_MoveThroughMarkers_04), DEBUGSTRING("CEnemyBase::H0x0136001c_MoveThroughMarkers_04")}, + {0x0136001d, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136001d_MoveThroughMarkers_05), DEBUGSTRING("CEnemyBase::H0x0136001d_MoveThroughMarkers_05")}, + {0x0136001e, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136001e_MoveThroughMarkers_06), DEBUGSTRING("CEnemyBase::H0x0136001e_MoveThroughMarkers_06")}, + {0x0136001f, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136001f_MoveThroughMarkers_07), DEBUGSTRING("CEnemyBase::H0x0136001f_MoveThroughMarkers_07")}, + {0x01360020, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360020_MoveThroughMarkers_08), DEBUGSTRING("CEnemyBase::H0x01360020_MoveThroughMarkers_08")}, + {0x01360021, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360021_MoveThroughMarkers_09), DEBUGSTRING("CEnemyBase::H0x01360021_MoveThroughMarkers_09")}, + {0x01360022, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360022_MoveThroughMarkers_10), DEBUGSTRING("CEnemyBase::H0x01360022_MoveThroughMarkers_10")}, + {0x01360023, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360023_MoveThroughMarkers_11), DEBUGSTRING("CEnemyBase::H0x01360023_MoveThroughMarkers_11")}, + {0x01360024, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360024_MoveThroughMarkers_12), DEBUGSTRING("CEnemyBase::H0x01360024_MoveThroughMarkers_12")}, + {0x01360025, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2310 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +NewEnemySpotted),DEBUGSTRING("CEnemyBase::NewEnemySpotted")}, + {0x01360026, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360026_NewEnemySpotted_01), DEBUGSTRING("CEnemyBase::H0x01360026_NewEnemySpotted_01")}, + {0x01360027, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360027_NewEnemySpotted_02), DEBUGSTRING("CEnemyBase::H0x01360027_NewEnemySpotted_02")}, + {0x01360028, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360028_NewEnemySpotted_03), DEBUGSTRING("CEnemyBase::H0x01360028_NewEnemySpotted_03")}, + {0x01360029, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2342 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StopAttack),DEBUGSTRING("CEnemyBase::StopAttack")}, + {0x0136002a, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2355 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +InitializeAttack),DEBUGSTRING("CEnemyBase::InitializeAttack")}, + {0x0136002b, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2381 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +AttackEnemy),DEBUGSTRING("CEnemyBase::AttackEnemy")}, + {0x0136002c, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136002c_AttackEnemy_01), DEBUGSTRING("CEnemyBase::H0x0136002c_AttackEnemy_01")}, + {0x0136002d, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136002d_AttackEnemy_02), DEBUGSTRING("CEnemyBase::H0x0136002d_AttackEnemy_02")}, + {0x0136002e, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136002e_AttackEnemy_03), DEBUGSTRING("CEnemyBase::H0x0136002e_AttackEnemy_03")}, + {0x0136002f, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136002f_AttackEnemy_04), DEBUGSTRING("CEnemyBase::H0x0136002f_AttackEnemy_04")}, + {0x01360030, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360030_AttackEnemy_05), DEBUGSTRING("CEnemyBase::H0x01360030_AttackEnemy_05")}, + {0x01360031, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360031_AttackEnemy_06), DEBUGSTRING("CEnemyBase::H0x01360031_AttackEnemy_06")}, + {0x01360032, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360032_AttackEnemy_07), DEBUGSTRING("CEnemyBase::H0x01360032_AttackEnemy_07")}, + {0x01360033, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360033_AttackEnemy_08), DEBUGSTRING("CEnemyBase::H0x01360033_AttackEnemy_08")}, + {0x01360034, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2399 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PerformAttack),DEBUGSTRING("CEnemyBase::PerformAttack")}, + {0x01360035, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360035_PerformAttack_01), DEBUGSTRING("CEnemyBase::H0x01360035_PerformAttack_01")}, + {0x01360036, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360036_PerformAttack_02), DEBUGSTRING("CEnemyBase::H0x01360036_PerformAttack_02")}, + {0x01360037, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360037_PerformAttack_03), DEBUGSTRING("CEnemyBase::H0x01360037_PerformAttack_03")}, + {0x01360038, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360038_PerformAttack_04), DEBUGSTRING("CEnemyBase::H0x01360038_PerformAttack_04")}, + {0x01360039, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2587 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +FireOrHit),DEBUGSTRING("CEnemyBase::FireOrHit")}, + {0x0136003a, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136003a_FireOrHit_01), DEBUGSTRING("CEnemyBase::H0x0136003a_FireOrHit_01")}, + {0x0136003b, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136003b_FireOrHit_02), DEBUGSTRING("CEnemyBase::H0x0136003b_FireOrHit_02")}, + {0x0136003c, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136003c_FireOrHit_03), DEBUGSTRING("CEnemyBase::H0x0136003c_FireOrHit_03")}, + {0x0136003d, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136003d_FireOrHit_04), DEBUGSTRING("CEnemyBase::H0x0136003d_FireOrHit_04")}, + {0x0136003e, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136003e_FireOrHit_05), DEBUGSTRING("CEnemyBase::H0x0136003e_FireOrHit_05")}, + {0x0136003f, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136003f_FireOrHit_06), DEBUGSTRING("CEnemyBase::H0x0136003f_FireOrHit_06")}, + {0x01360040, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360040_FireOrHit_07), DEBUGSTRING("CEnemyBase::H0x01360040_FireOrHit_07")}, + {0x01360041, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360041_FireOrHit_08), DEBUGSTRING("CEnemyBase::H0x01360041_FireOrHit_08")}, + {0x01360042, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2630 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Hit),DEBUGSTRING("CEnemyBase::Hit")}, + {0x01360043, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2636 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Fire),DEBUGSTRING("CEnemyBase::Fire")}, + {0x01360044, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2646 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +LockOnEnemy),DEBUGSTRING("CEnemyBase::LockOnEnemy")}, + {0x01360045, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360045_LockOnEnemy_01), DEBUGSTRING("CEnemyBase::H0x01360045_LockOnEnemy_01")}, + {0x01360046, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360046_LockOnEnemy_02), DEBUGSTRING("CEnemyBase::H0x01360046_LockOnEnemy_02")}, + {0x01360047, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360047_LockOnEnemy_03), DEBUGSTRING("CEnemyBase::H0x01360047_LockOnEnemy_03")}, + {0x01360048, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360048_LockOnEnemy_04), DEBUGSTRING("CEnemyBase::H0x01360048_LockOnEnemy_04")}, + {0x01360049, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2685 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +ChargeHitEnemy),DEBUGSTRING("CEnemyBase::ChargeHitEnemy")}, + {0x0136004a, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136004a_ChargeHitEnemy_01), DEBUGSTRING("CEnemyBase::H0x0136004a_ChargeHitEnemy_01")}, + {0x0136004b, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136004b_ChargeHitEnemy_02), DEBUGSTRING("CEnemyBase::H0x0136004b_ChargeHitEnemy_02")}, + {0x0136004c, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136004c_ChargeHitEnemy_03), DEBUGSTRING("CEnemyBase::H0x0136004c_ChargeHitEnemy_03")}, + {0x0136004d, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136004d_ChargeHitEnemy_04), DEBUGSTRING("CEnemyBase::H0x0136004d_ChargeHitEnemy_04")}, + {0x0136004e, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136004e_ChargeHitEnemy_05), DEBUGSTRING("CEnemyBase::H0x0136004e_ChargeHitEnemy_05")}, + {0x0136004f, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2741 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +BeWounded),DEBUGSTRING("CEnemyBase::BeWounded")}, + {0x01360050, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360050_BeWounded_01), DEBUGSTRING("CEnemyBase::H0x01360050_BeWounded_01")}, + {0x01360051, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360051_BeWounded_02), DEBUGSTRING("CEnemyBase::H0x01360051_BeWounded_02")}, + {0x01360052, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2750 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Die),DEBUGSTRING("CEnemyBase::Die")}, + {0x01360053, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360053_Die_01), DEBUGSTRING("CEnemyBase::H0x01360053_Die_01")}, + {0x01360054, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360054_Die_02), DEBUGSTRING("CEnemyBase::H0x01360054_Die_02")}, + {0x01360055, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2843 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Death),DEBUGSTRING("CEnemyBase::Death")}, + {0x01360056, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360056_Death_01), DEBUGSTRING("CEnemyBase::H0x01360056_Death_01")}, + {0x01360057, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360057_Death_02), DEBUGSTRING("CEnemyBase::H0x01360057_Death_02")}, + {0x01360058, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360058_Death_03), DEBUGSTRING("CEnemyBase::H0x01360058_Death_03")}, + {0x01360059, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360059_Death_04), DEBUGSTRING("CEnemyBase::H0x01360059_Death_04")}, + {0x0136005a, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136005a_Death_05), DEBUGSTRING("CEnemyBase::H0x0136005a_Death_05")}, + {0x0136005b, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136005b_Death_06), DEBUGSTRING("CEnemyBase::H0x0136005b_Death_06")}, + {0x0136005c, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136005c_Death_07), DEBUGSTRING("CEnemyBase::H0x0136005c_Death_07")}, + {0x0136005d, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136005d_Death_08), DEBUGSTRING("CEnemyBase::H0x0136005d_Death_08")}, + {0x0136005e, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136005e_Death_09), DEBUGSTRING("CEnemyBase::H0x0136005e_Death_09")}, + {0x0136005f, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2903 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +DeathSequence),DEBUGSTRING("CEnemyBase::DeathSequence")}, + {0x01360060, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360060_DeathSequence_01), DEBUGSTRING("CEnemyBase::H0x01360060_DeathSequence_01")}, + {0x01360061, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360061_DeathSequence_02), DEBUGSTRING("CEnemyBase::H0x01360061_DeathSequence_02")}, + {0x01360062, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360062_DeathSequence_03), DEBUGSTRING("CEnemyBase::H0x01360062_DeathSequence_03")}, + {0x01360063, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360063_DeathSequence_04), DEBUGSTRING("CEnemyBase::H0x01360063_DeathSequence_04")}, + {0x01360064, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360064_DeathSequence_05), DEBUGSTRING("CEnemyBase::H0x01360064_DeathSequence_05")}, + {0x01360065, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360065_DeathSequence_06), DEBUGSTRING("CEnemyBase::H0x01360065_DeathSequence_06")}, + {0x01360066, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360066_DeathSequence_07), DEBUGSTRING("CEnemyBase::H0x01360066_DeathSequence_07")}, + {0x01360067, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360067_DeathSequence_08), DEBUGSTRING("CEnemyBase::H0x01360067_DeathSequence_08")}, + {0x01360068, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 2942 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Active),DEBUGSTRING("CEnemyBase::Active")}, + {0x01360069, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360069_Active_01), DEBUGSTRING("CEnemyBase::H0x01360069_Active_01")}, + {0x0136006a, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136006a_Active_02), DEBUGSTRING("CEnemyBase::H0x0136006a_Active_02")}, + {0x0136006b, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 3081 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Inactive),DEBUGSTRING("CEnemyBase::Inactive")}, + {0x0136006c, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136006c_Inactive_01), DEBUGSTRING("CEnemyBase::H0x0136006c_Inactive_01")}, + {0x0136006d, -1, CEntity::pEventHandler(&CEnemyBase::H0x0136006d_Inactive_02), DEBUGSTRING("CEnemyBase::H0x0136006d_Inactive_02")}, + {0x0136006e, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 3127 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +PreMainLoop),DEBUGSTRING("CEnemyBase::PreMainLoop")}, + {0x0136006f, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 3133 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +MainLoop),DEBUGSTRING("CEnemyBase::MainLoop")}, + {0x01360070, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360070_MainLoop_01), DEBUGSTRING("CEnemyBase::H0x01360070_MainLoop_01")}, + {0x01360071, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360071_MainLoop_02), DEBUGSTRING("CEnemyBase::H0x01360071_MainLoop_02")}, + {0x01360072, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360072_MainLoop_03), DEBUGSTRING("CEnemyBase::H0x01360072_MainLoop_03")}, + {0x01360073, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360073_MainLoop_04), DEBUGSTRING("CEnemyBase::H0x01360073_MainLoop_04")}, + {0x01360074, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 3210 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +StandardBehavior),DEBUGSTRING("CEnemyBase::StandardBehavior")}, + {0x01360075, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360075_StandardBehavior_01), DEBUGSTRING("CEnemyBase::H0x01360075_StandardBehavior_01")}, + {0x01360076, -1, CEntity::pEventHandler(&CEnemyBase::H0x01360076_StandardBehavior_02), DEBUGSTRING("CEnemyBase::H0x01360076_StandardBehavior_02")}, + {1, -1, CEntity::pEventHandler(&CEnemyBase:: +#line 3258 "D:/SE1_GPL/Sources/EntitiesMP/EnemyBase.es" +Main),DEBUGSTRING("CEnemyBase::Main")}, +}; +#define CEnemyBase_handlersct ARRAYCOUNT(CEnemyBase_handlers) + +CEntity *CEnemyBase_New(void) { return new CEnemyBase; }; +void CEnemyBase_OnInitClass(void) {}; +void CEnemyBase_OnEndClass(void) {}; +void CEnemyBase_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEnemyBase_OnWorldEnd(CWorld *pwo) {}; +void CEnemyBase_OnWorldInit(CWorld *pwo) {}; +void CEnemyBase_OnWorldTick(CWorld *pwo) {}; +void CEnemyBase_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEnemyBase, CMovableModelEntity, "Enemy Base", "", 0x00000136); +DECLARE_CTFILENAME(_fnmCEnemyBase_tbn, ""); diff --git a/Sources/EntitiesMP/EnemyCounter.cpp b/Sources/EntitiesMP/EnemyCounter.cpp new file mode 100644 index 0000000..0ad8a31 --- /dev/null +++ b/Sources/EntitiesMP/EnemyCounter.cpp @@ -0,0 +1,164 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" + +#include "StdH.h" +#include + +#include +#include +void CEnemyCounter::SetDefaultProperties(void) { + m_penMainMusicHolder = NULL; + m_strName = ""; + m_iCountFrom = 100; + m_iCount = -1; + CRationalEntity::SetDefaultProperties(); +} + +#line 26 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +class CMusicHolder * CEnemyCounter::GetMusicHolder() +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +{ +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +if(m_penMainMusicHolder == NULL ){ +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +m_penMainMusicHolder = _pNetwork -> GetEntityWithName ("MusicHolder" , 0); +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +} +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +return (CMusicHolder *) & * m_penMainMusicHolder ; +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +} + +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +void CEnemyCounter::StartCounting(void) +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +{ +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +CMusicHolder * pmh = GetMusicHolder (); +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +if(pmh == NULL ){ +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +return ; +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +} +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +pmh -> m_penCounter = this ; +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +m_iCount = m_iCountFrom ; +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +} + +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +void CEnemyCounter::CountOne(void) +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +{ +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +if(m_iCount > 0){ +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +m_iCount -= 1; +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +} +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +} + +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +void CEnemyCounter::StopCounting(void) +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +{ +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +CMusicHolder * pmh = GetMusicHolder (); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +if(pmh == NULL ){ +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +return ; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +} +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +m_iCount = 0; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +pmh -> m_penCounter = NULL ; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +} +BOOL CEnemyCounter:: +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyCounter_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyCounter::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +InitAsEditorModel (); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +SetModel (MODEL_MARKER ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x01530000, FALSE, EBegin());return TRUE;}BOOL CEnemyCounter::H0x01530000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01530000 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01530001, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemyCounter::H0x01530001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01530001 +; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01530002, FALSE, EBegin());return TRUE;}BOOL CEnemyCounter::H0x01530002_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01530002 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +return TRUE; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; + +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +StartCounting (); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +return TRUE; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +StopCounting (); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +return TRUE; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; + +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +if(m_iCount == - 1){ +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +StartCounting (); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +} +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +CountOne (); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +if(m_iCount == 0){ +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +StopCounting (); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +} +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +return TRUE; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +}return TRUE;}BOOL CEnemyCounter::H0x01530003_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01530003 + +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +Return(STATE_CURRENT,EVoid()); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EnemyCounter.es b/Sources/EntitiesMP/EnemyCounter.es new file mode 100644 index 0000000..1e4b1d7 --- /dev/null +++ b/Sources/EntitiesMP/EnemyCounter.es @@ -0,0 +1,107 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +339 +%{ +#include "StdH.h" +#include +%} + +class CEnemyCounter : CRationalEntity { +name "EnemyCounter"; +thumbnail "Thumbnails\\Counter.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CEntityPointer m_penMainMusicHolder, + 2 CTString m_strName "Name" 'N' ="", + 4 INDEX m_iCountFrom "Count start" 'A' = 100, + 5 INDEX m_iCount = -1, + +components: + 0 sound SOUND_TICK "Sounds\\Menu\\Select.wav", + 1 model MODEL_MARKER "Models\\Editor\\Axis.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex" + +functions: + class CMusicHolder *GetMusicHolder() + { + if (m_penMainMusicHolder==NULL) { + m_penMainMusicHolder = _pNetwork->GetEntityWithName("MusicHolder", 0); + } + return (CMusicHolder *)&*m_penMainMusicHolder; + } + void StartCounting(void) + { + CMusicHolder *pmh = GetMusicHolder(); + if (pmh==NULL) { + return; + } + pmh->m_penCounter = this; + m_iCount = m_iCountFrom; + } + void CountOne(void) + { + if (m_iCount>0) { + m_iCount-=1; + } + } + void StopCounting(void) + { + CMusicHolder *pmh = GetMusicHolder(); + if (pmh==NULL) { + return; + } + m_iCount = 0; + pmh->m_penCounter = NULL; + } +procedures: + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + autowait(0.1f); + + wait() { + on(EBegin): { + resume; + } + // when started + on (EStart): { + StartCounting(); + resume; + } + // when stopped + on (EStop): { + StopCounting(); + resume; + } + // when triggered + on (ETrigger): { + // if not started yet + if (m_iCount==-1) { + // start + StartCounting(); + } + CountOne(); + // if finished + if (m_iCount==0) { + // stop + StopCounting(); + } + resume; + } + } + + return; + } +}; diff --git a/Sources/EntitiesMP/EnemyCounter.h b/Sources/EntitiesMP/EnemyCounter.h new file mode 100644 index 0000000..e3ca974 --- /dev/null +++ b/Sources/EntitiesMP/EnemyCounter.h @@ -0,0 +1,38 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_EnemyCounter_INCLUDED +#define _EntitiesMP_EnemyCounter_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CEnemyCounter_DLLClass; +class CEnemyCounter : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penMainMusicHolder; + CTString m_strName; + INDEX m_iCountFrom; + INDEX m_iCount; + +#line 26 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +class CMusicHolder * GetMusicHolder(); + +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +void StartCounting(void); + +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +void CountOne(void); + +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +void StopCounting(void); +#define STATE_CEnemyCounter_Main 1 + BOOL +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01530000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01530001_Main_02(const CEntityEvent &__eeInput); + BOOL H0x01530002_Main_03(const CEntityEvent &__eeInput); + BOOL H0x01530003_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_EnemyCounter_INCLUDED diff --git a/Sources/EntitiesMP/EnemyCounter_tables.h b/Sources/EntitiesMP/EnemyCounter_tables.h new file mode 100644 index 0000000..542ed9c --- /dev/null +++ b/Sources/EntitiesMP/EnemyCounter_tables.h @@ -0,0 +1,45 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CEnemyCounter + +CEntityProperty CEnemyCounter_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000153<<8)+1, offsetof(CEnemyCounter, m_penMainMusicHolder), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000153<<8)+2, offsetof(CEnemyCounter, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000153<<8)+4, offsetof(CEnemyCounter, m_iCountFrom), "Count start", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000153<<8)+5, offsetof(CEnemyCounter, m_iCount), "", 0, 0, 0), +}; +#define CEnemyCounter_propertiesct ARRAYCOUNT(CEnemyCounter_properties) + +CEntityComponent CEnemyCounter_components[] = { +#define SOUND_TICK ((0x00000153<<8)+0) + CEntityComponent(ECT_SOUND, SOUND_TICK, "EFNM" "Sounds\\Menu\\Select.wav"), +#define MODEL_MARKER ((0x00000153<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_MARKER ((0x00000153<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Vector.tex"), +}; +#define CEnemyCounter_componentsct ARRAYCOUNT(CEnemyCounter_components) + +CEventHandlerEntry CEnemyCounter_handlers[] = { + {1, -1, CEntity::pEventHandler(&CEnemyCounter:: +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/EnemyCounter.es" +Main),DEBUGSTRING("CEnemyCounter::Main")}, + {0x01530000, -1, CEntity::pEventHandler(&CEnemyCounter::H0x01530000_Main_01), DEBUGSTRING("CEnemyCounter::H0x01530000_Main_01")}, + {0x01530001, -1, CEntity::pEventHandler(&CEnemyCounter::H0x01530001_Main_02), DEBUGSTRING("CEnemyCounter::H0x01530001_Main_02")}, + {0x01530002, -1, CEntity::pEventHandler(&CEnemyCounter::H0x01530002_Main_03), DEBUGSTRING("CEnemyCounter::H0x01530002_Main_03")}, + {0x01530003, -1, CEntity::pEventHandler(&CEnemyCounter::H0x01530003_Main_04), DEBUGSTRING("CEnemyCounter::H0x01530003_Main_04")}, +}; +#define CEnemyCounter_handlersct ARRAYCOUNT(CEnemyCounter_handlers) + +CEntity *CEnemyCounter_New(void) { return new CEnemyCounter; }; +void CEnemyCounter_OnInitClass(void) {}; +void CEnemyCounter_OnEndClass(void) {}; +void CEnemyCounter_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEnemyCounter_OnWorldEnd(CWorld *pwo) {}; +void CEnemyCounter_OnWorldInit(CWorld *pwo) {}; +void CEnemyCounter_OnWorldTick(CWorld *pwo) {}; +void CEnemyCounter_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEnemyCounter, CRationalEntity, "EnemyCounter", "Thumbnails\\Counter.tbn", 0x00000153); +DECLARE_CTFILENAME(_fnmCEnemyCounter_tbn, "Thumbnails\\Counter.tbn"); diff --git a/Sources/EntitiesMP/EnemyDive.cpp b/Sources/EntitiesMP/EnemyDive.cpp new file mode 100644 index 0000000..8b65916 --- /dev/null +++ b/Sources/EntitiesMP/EnemyDive.cpp @@ -0,0 +1,289 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" + +#include "StdH.h" + +#include +#include +void CEnemyDive::SetDefaultProperties(void) { + m_EedtType = EDT_DIVE_ONLY ; + m_bInLiquid = TRUE ; + m_fDiveWalkSpeed = 1.0f; + m_aDiveWalkRotateSpeed = AngleDeg(10.0f); + m_fDiveAttackRunSpeed = 1.0f; + m_aDiveAttackRotateSpeed = AngleDeg(10.0f); + m_fDiveCloseRunSpeed = 1.0f; + m_aDiveCloseRotateSpeed = AngleDeg(10.0f); + m_fDiveAttackDistance = 50.0f; + m_fDiveCloseDistance = 10.0f; + m_fDiveAttackFireTime = 2.0f; + m_fDiveCloseFireTime = 1.0f; + m_fDiveStopDistance = 0.0f; + m_fDiveIgnoreRange = 200.0f; + m_fDiveLockOnEnemyTime = 0.0f; + CEnemyBase::SetDefaultProperties(); +} + FLOAT & CEnemyDive::GetProp(FLOAT & m_fBase) +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +{ +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +if(m_bInLiquid ){ +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return * ((& m_fBase ) + (& m_fDiveWalkSpeed - & m_fWalkSpeed )); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +}else { +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return m_fBase ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +void CEnemyDive::StartPathFinding(void) +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +{ +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_dtDestination = DT_PLAYERSPOTTED ; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_vPlayerSpotted = PlayerDestinationPos (); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} + void CEnemyDive::AdjustDifficulty(void) +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +{ +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +FLOAT fMoveSpeed = GetSP () -> sp_fEnemyMovementSpeed ; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +FLOAT fAttackSpeed = GetSP () -> sp_fEnemyMovementSpeed ; +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_fDiveAttackRunSpeed *= fMoveSpeed ; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_aDiveAttackRotateSpeed *= fMoveSpeed ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_fDiveCloseRunSpeed *= fMoveSpeed ; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_aDiveCloseRotateSpeed *= fMoveSpeed ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_fDiveAttackFireTime *= 1 / fAttackSpeed ; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_fDiveCloseFireTime *= 1 / fAttackSpeed ; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_fDiveLockOnEnemyTime *= 1 / fAttackSpeed ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +CEnemyBase :: AdjustDifficulty (); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} + BOOL CEnemyDive::CanHitEnemy(CEntity * penTarget,FLOAT fCosAngle) { +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +if(IsInPlaneFrustum (penTarget , fCosAngle )){ +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return IsVisibleCheckAll (penTarget ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return FALSE ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} + +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +void CEnemyDive::PostMoving(void) { +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +CEnemyBase :: PostMoving (); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +if(m_EedtType != EDT_GROUND_ONLY && ! m_bInLiquid && en_fImmersionFactor > 0.9f && +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +(GetWorld () -> wo_actContentTypes [ en_iDnContent ] . ct_ulFlags & CTF_SWIMABLE )){ +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_bInLiquid = TRUE ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +ChangeCollisionToLiquid (); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +SendEvent (ERestartAttack ()); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +if(m_EedtType != EDT_DIVE_ONLY && m_bInLiquid && (en_fImmersionFactor < 0.5f || en_fImmersionFactor == 1.0f) && +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +en_penReference != NULL && ! (GetWorld () -> wo_actContentTypes [ en_iUpContent ] . ct_ulFlags & CTF_SWIMABLE )){ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_bInLiquid = FALSE ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +ChangeCollisionToGround (); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +SendEvent (ERestartAttack ()); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} + ULONG CEnemyDive::SetDesiredMovement(void) +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +{ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +if(! m_bInLiquid ){ +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return CEnemyBase :: SetDesiredMovement (); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +ULONG ulFlags = CEnemyBase :: SetDesiredMovement (); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +if(m_fMoveSpeed > 0.0f){ +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +FLOAT3D vTranslation = (m_vDesiredPosition - GetPlacement () . pl_PositionVector ) * ! en_mRotation ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +vTranslation (1) = 0.0f; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +if(vTranslation (3) > 0){ +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +vTranslation (3) = 0.0f; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +vTranslation . Normalize (); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +vTranslation *= m_fMoveSpeed ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +SetDesiredTranslation (vTranslation ); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return ulFlags ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +BOOL CEnemyDive::MayMoveToAttack(void) +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +{ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return WouldNotLeaveAttackRadius (); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} + +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +void CEnemyDive::SetEntityPosition() { +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +switch(m_EedtType ){ +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +case EDT_GROUND_ONLY : +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_bInLiquid = FALSE ; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +break ; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +case EDT_DIVE_ONLY : +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +m_bInLiquid = TRUE ; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +break ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +case EDT_GROUND_DIVE : +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +break ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +if(m_bInLiquid ){ +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +ChangeCollisionToLiquid (); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +}else { +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +ChangeCollisionToGround (); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +StandingAnim (); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} + void CEnemyDive::ChangeCollisionToLiquid(void) {} + void CEnemyDive::ChangeCollisionToGround(void) {} +BOOL CEnemyDive:: +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyDive_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyDive::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +if(m_bInLiquid ){ +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Jump(STATE_CURRENT, STATE_CEnemyDive_DiveHit, TRUE, EVoid());return TRUE; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +}else { +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Jump(STATE_CURRENT, STATE_CEnemyDive_GroundHit, TRUE, EVoid());return TRUE; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} ASSERT(FALSE); return TRUE;};BOOL CEnemyDive:: +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyDive_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyDive::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +if(m_bInLiquid ){ +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Jump(STATE_CURRENT, STATE_CEnemyDive_DiveFire, TRUE, EVoid());return TRUE; +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +}else { +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Jump(STATE_CURRENT, STATE_CEnemyDive_GroundFire, TRUE, EVoid());return TRUE; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +} ASSERT(FALSE); return TRUE;};BOOL CEnemyDive:: +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +MainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyDive_MainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyDive::MainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +SetEntityPosition (); +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyDive:: +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyDive_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyDive::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Return(STATE_CURRENT,EVoid()); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyDive:: +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +GroundHit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyDive_GroundHit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyDive::GroundHit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Return(STATE_CURRENT,EReturn ()); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyDive:: +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +GroundFire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyDive_GroundFire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyDive::GroundFire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Return(STATE_CURRENT,EReturn ()); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyDive:: +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +DiveHit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyDive_DiveHit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyDive::DiveHit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Return(STATE_CURRENT,EReturn ()); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyDive:: +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +DiveFire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyDive_DiveFire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyDive::DiveFire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Return(STATE_CURRENT,EReturn ()); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EnemyDive.es b/Sources/EntitiesMP/EnemyDive.es new file mode 100644 index 0000000..dd2748a --- /dev/null +++ b/Sources/EntitiesMP/EnemyDive.es @@ -0,0 +1,252 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +313 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/Debris"; +uses "EntitiesMP/EnemyMarker"; + + +enum EnemyDiveType { + 0 EDT_GROUND_ONLY "Ground only", // can't dive + 1 EDT_DIVE_ONLY "Dive only", // always dive can't walk + 2 EDT_GROUND_DIVE "Ground and dive", // dive and walk +}; + + +class export CEnemyDive : CEnemyBase { +name "Enemy Dive"; +thumbnail ""; + +properties: + 1 enum EnemyDiveType m_EedtType "Type" 'T' = EDT_DIVE_ONLY, // dive type + 2 BOOL m_bInLiquid "In liquid" 'Q' = TRUE, // entity is in liquid + + // moving/attack properties - CAN BE SET + // these following must be ordered exactly like this for GetProp() to function + 10 FLOAT m_fDiveWalkSpeed = 1.0f, // dive walk speed + 11 ANGLE m_aDiveWalkRotateSpeed = AngleDeg(10.0f), // dive walk rotate speed + 12 FLOAT m_fDiveAttackRunSpeed = 1.0f, // dive attack run speed + 13 ANGLE m_aDiveAttackRotateSpeed = AngleDeg(10.0f), // dive attack rotate speed + 14 FLOAT m_fDiveCloseRunSpeed = 1.0f, // dive close run speed + 15 ANGLE m_aDiveCloseRotateSpeed = AngleDeg(10.0f), // dive close rotate speed + 20 FLOAT m_fDiveAttackDistance = 50.0f, // dive attack distance mode + 21 FLOAT m_fDiveCloseDistance = 10.0f, // dive close distance mode + 22 FLOAT m_fDiveAttackFireTime = 2.0f, // dive attack distance fire time + 23 FLOAT m_fDiveCloseFireTime = 1.0f, // dive close distance fire time + 24 FLOAT m_fDiveStopDistance = 0.0f, // dive stop moving toward enemy if closer than stop distance + 25 FLOAT m_fDiveIgnoreRange = 200.0f, // dive cease attack if enemy farther + 26 FLOAT m_fDiveLockOnEnemyTime = 0.0f, // dive time needed to fire + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + +functions: + // overridable function for access to different properties of derived classes (flying/diving) + virtual FLOAT &GetProp(FLOAT &m_fBase) + { + if (m_bInLiquid) { + return *((&m_fBase)+(&m_fDiveWalkSpeed-&m_fWalkSpeed)); + } else { + return m_fBase; + } + } + + // diving enemies never use pathfinding + void StartPathFinding(void) + { + m_dtDestination=DT_PLAYERSPOTTED; + m_vPlayerSpotted = PlayerDestinationPos(); + } + + virtual void AdjustDifficulty(void) + { + FLOAT fMoveSpeed = GetSP()->sp_fEnemyMovementSpeed; + FLOAT fAttackSpeed = GetSP()->sp_fEnemyMovementSpeed; +// m_fDiveWalkSpeed *= fMoveSpeed; +// m_aDiveWalkRotateSpeed *= fMoveSpeed; + m_fDiveAttackRunSpeed *= fMoveSpeed; + m_aDiveAttackRotateSpeed *= fMoveSpeed; + m_fDiveCloseRunSpeed *= fMoveSpeed; + m_aDiveCloseRotateSpeed *= fMoveSpeed; + m_fDiveAttackFireTime *= 1/fAttackSpeed; + m_fDiveCloseFireTime *= 1/fAttackSpeed; + m_fDiveLockOnEnemyTime *= 1/fAttackSpeed; + + CEnemyBase::AdjustDifficulty(); + } + // close attack if possible + virtual BOOL CanHitEnemy(CEntity *penTarget, FLOAT fCosAngle) { + if (IsInPlaneFrustum(penTarget, fCosAngle)) { + return IsVisibleCheckAll(penTarget); + } + return FALSE; + }; +/************************************************************ + * POST MOVING * + ************************************************************/ + void PostMoving(void) { + CEnemyBase::PostMoving(); + // change to liquid + if (m_EedtType!=EDT_GROUND_ONLY && !m_bInLiquid && en_fImmersionFactor>0.9f && + (GetWorld()->wo_actContentTypes[en_iDnContent].ct_ulFlags&CTF_SWIMABLE)) { + m_bInLiquid = TRUE; + ChangeCollisionToLiquid(); + SendEvent(ERestartAttack()); + } + // change to ground + if (m_EedtType!=EDT_DIVE_ONLY && m_bInLiquid && (en_fImmersionFactor<0.5f || en_fImmersionFactor==1.0f) && + en_penReference!=NULL && !(GetWorld()->wo_actContentTypes[en_iUpContent].ct_ulFlags&CTF_SWIMABLE)) { + m_bInLiquid = FALSE; + ChangeCollisionToGround(); + SendEvent(ERestartAttack()); + } + }; + + + +/************************************************************ + * MOVING FUNCTIONS * + ************************************************************/ + // set desired rotation and translation to go/orient towards desired position + // and get the resulting movement type + virtual ULONG SetDesiredMovement(void) + { + // if not in air + if (!m_bInLiquid) { + // use base class + return CEnemyBase::SetDesiredMovement(); + } + + // get base rotation from base class + ULONG ulFlags = CEnemyBase::SetDesiredMovement(); + + // if we may move + if (m_fMoveSpeed>0.0f) { + // fix translation for 3d movement + FLOAT3D vTranslation = (m_vDesiredPosition - GetPlacement().pl_PositionVector) * !en_mRotation; + vTranslation(1) = 0.0f; + if (vTranslation(3)>0) { + vTranslation(3) = 0.0f; + } + vTranslation.Normalize(); + vTranslation *= m_fMoveSpeed; + SetDesiredTranslation(vTranslation); + } + + return ulFlags; + } + + // check whether may move while attacking + BOOL MayMoveToAttack(void) + { + return WouldNotLeaveAttackRadius(); + } + +/************************************************************ + * CLASS SUPPORT FUNCTIONS * + ************************************************************/ + // set entity position + void SetEntityPosition() { + switch (m_EedtType) { + case EDT_GROUND_ONLY: // can't dive + m_bInLiquid = FALSE; + break; + case EDT_DIVE_ONLY: // always dive can't walk + m_bInLiquid = TRUE; + break; + case EDT_GROUND_DIVE: // dive and walk + break; + } + + // in liquid + if (m_bInLiquid) { + ChangeCollisionToLiquid(); + } else { + ChangeCollisionToGround(); + } + + StandingAnim(); + }; + + +/************************************************************ + * VIRTUAL FUNCTIONS THAT NEED OVERRIDE * + ************************************************************/ + virtual void ChangeCollisionToLiquid(void) {} + virtual void ChangeCollisionToGround(void) {} + + + +procedures: +/************************************************************ + * PROCEDURES WHEN NO ANY SPECIAL ACTION * + ************************************************************/ +/************************************************************ + * ATTACK ENEMY PROCEDURES * + ************************************************************/ + // this is called to hit the player when near + Hit(EVoid) : CEnemyBase::Hit + { + if (m_bInLiquid) { + jump DiveHit(); + } else { + jump GroundHit(); + } + } + + // this is called to shoot at player when far away or otherwise unreachable + Fire(EVoid) : CEnemyBase::Fire + { + if (m_bInLiquid) { + jump DiveFire(); + } else { + jump GroundFire(); + } + } + +/************************************************************ + * M A I N L O O P * + ************************************************************/ + // main loop + MainLoop(EVoid) : CEnemyBase::MainLoop { + SetEntityPosition(); + jump CEnemyBase::MainLoop(); + }; + + // dummy main + Main(EVoid) { + return; + }; + + + +/************************************************************ + * VIRTUAL PROCEDURES THAT NEED OVERRIDE * + ************************************************************/ + // this is called to hit the player when near and you are on ground + GroundHit(EVoid) + { + return EReturn(); + } + // this is called to shoot at player when far away or otherwise unreachable and you are on ground + GroundFire(EVoid) + { + return EReturn(); + } + + // this is called to hit the player when near and you are in water + DiveHit(EVoid) + { + return EReturn(); + } + + // this is called to shoot at player when far away or otherwise unreachable and you are in water + DiveFire(EVoid) + { + return EReturn(); + } +}; diff --git a/Sources/EntitiesMP/EnemyDive.h b/Sources/EntitiesMP/EnemyDive.h new file mode 100644 index 0000000..bbfb1d9 --- /dev/null +++ b/Sources/EntitiesMP/EnemyDive.h @@ -0,0 +1,99 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_EnemyDive_INCLUDED +#define _EntitiesMP_EnemyDive_INCLUDED 1 +#include +#include +#include +extern DECL_DLL CEntityPropertyEnumType EnemyDiveType_enum; +enum EnemyDiveType { + EDT_GROUND_ONLY = 0, + EDT_DIVE_ONLY = 1, + EDT_GROUND_DIVE = 2, +}; +DECL_DLL inline void ClearToDefault(EnemyDiveType &e) { e = (EnemyDiveType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CEnemyDive_DLLClass; +class DECL_DLL CEnemyDive : public CEnemyBase { +public: + virtual void SetDefaultProperties(void); + enum EnemyDiveType m_EedtType; + BOOL m_bInLiquid; + FLOAT m_fDiveWalkSpeed; + ANGLE m_aDiveWalkRotateSpeed; + FLOAT m_fDiveAttackRunSpeed; + ANGLE m_aDiveAttackRotateSpeed; + FLOAT m_fDiveCloseRunSpeed; + ANGLE m_aDiveCloseRotateSpeed; + FLOAT m_fDiveAttackDistance; + FLOAT m_fDiveCloseDistance; + FLOAT m_fDiveAttackFireTime; + FLOAT m_fDiveCloseFireTime; + FLOAT m_fDiveStopDistance; + FLOAT m_fDiveIgnoreRange; + FLOAT m_fDiveLockOnEnemyTime; + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +virtual FLOAT & GetProp(FLOAT & m_fBase); + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +void StartPathFinding(void); + +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +virtual void AdjustDifficulty(void); + +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +virtual BOOL CanHitEnemy(CEntity * penTarget,FLOAT fCosAngle); + +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +void PostMoving(void); + +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +virtual ULONG SetDesiredMovement(void); + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +BOOL MayMoveToAttack(void); + +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +void SetEntityPosition(); + +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +virtual void ChangeCollisionToLiquid(void); + +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +virtual void ChangeCollisionToGround(void); +#define STATE_CEnemyDive_Hit 0x01390000 + BOOL +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Hit(const CEntityEvent &__eeInput); +#define STATE_CEnemyDive_Fire 0x01390001 + BOOL +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Fire(const CEntityEvent &__eeInput); +#define STATE_CEnemyDive_MainLoop 0x01390002 + BOOL +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +MainLoop(const CEntityEvent &__eeInput); +#define STATE_CEnemyDive_Main 1 + BOOL +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Main(const CEntityEvent &__eeInput); +#define STATE_CEnemyDive_GroundHit 0x01390003 + BOOL +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +GroundHit(const CEntityEvent &__eeInput); +#define STATE_CEnemyDive_GroundFire 0x01390004 + BOOL +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +GroundFire(const CEntityEvent &__eeInput); +#define STATE_CEnemyDive_DiveHit 0x01390005 + BOOL +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +DiveHit(const CEntityEvent &__eeInput); +#define STATE_CEnemyDive_DiveFire 0x01390006 + BOOL +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +DiveFire(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_EnemyDive_INCLUDED diff --git a/Sources/EntitiesMP/EnemyDive_tables.h b/Sources/EntitiesMP/EnemyDive_tables.h new file mode 100644 index 0000000..b0a7a98 --- /dev/null +++ b/Sources/EntitiesMP/EnemyDive_tables.h @@ -0,0 +1,75 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(EnemyDiveType) + EP_ENUMVALUE(EDT_GROUND_ONLY, "Ground only"), + EP_ENUMVALUE(EDT_DIVE_ONLY, "Dive only"), + EP_ENUMVALUE(EDT_GROUND_DIVE, "Ground and dive"), +EP_ENUMEND(EnemyDiveType); + +#define ENTITYCLASS CEnemyDive + +CEntityProperty CEnemyDive_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &EnemyDiveType_enum, (0x00000139<<8)+1, offsetof(CEnemyDive, m_EedtType), "Type", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000139<<8)+2, offsetof(CEnemyDive, m_bInLiquid), "In liquid", 'Q', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000139<<8)+10, offsetof(CEnemyDive, m_fDiveWalkSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000139<<8)+11, offsetof(CEnemyDive, m_aDiveWalkRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000139<<8)+12, offsetof(CEnemyDive, m_fDiveAttackRunSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000139<<8)+13, offsetof(CEnemyDive, m_aDiveAttackRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000139<<8)+14, offsetof(CEnemyDive, m_fDiveCloseRunSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000139<<8)+15, offsetof(CEnemyDive, m_aDiveCloseRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000139<<8)+20, offsetof(CEnemyDive, m_fDiveAttackDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000139<<8)+21, offsetof(CEnemyDive, m_fDiveCloseDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000139<<8)+22, offsetof(CEnemyDive, m_fDiveAttackFireTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000139<<8)+23, offsetof(CEnemyDive, m_fDiveCloseFireTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000139<<8)+24, offsetof(CEnemyDive, m_fDiveStopDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000139<<8)+25, offsetof(CEnemyDive, m_fDiveIgnoreRange), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000139<<8)+26, offsetof(CEnemyDive, m_fDiveLockOnEnemyTime), "", 0, 0, 0), +}; +#define CEnemyDive_propertiesct ARRAYCOUNT(CEnemyDive_properties) + +CEntityComponent CEnemyDive_components[] = { +#define CLASS_BASE ((0x00000139<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +}; +#define CEnemyDive_componentsct ARRAYCOUNT(CEnemyDive_components) + +CEventHandlerEntry CEnemyDive_handlers[] = { + {0x01390000, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CEnemyDive:: +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Hit),DEBUGSTRING("CEnemyDive::Hit")}, + {0x01390001, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CEnemyDive:: +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Fire),DEBUGSTRING("CEnemyDive::Fire")}, + {0x01390002, STATE_CEnemyBase_MainLoop, CEntity::pEventHandler(&CEnemyDive:: +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +MainLoop),DEBUGSTRING("CEnemyDive::MainLoop")}, + {1, -1, CEntity::pEventHandler(&CEnemyDive:: +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +Main),DEBUGSTRING("CEnemyDive::Main")}, + {0x01390003, -1, CEntity::pEventHandler(&CEnemyDive:: +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +GroundHit),DEBUGSTRING("CEnemyDive::GroundHit")}, + {0x01390004, -1, CEntity::pEventHandler(&CEnemyDive:: +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +GroundFire),DEBUGSTRING("CEnemyDive::GroundFire")}, + {0x01390005, -1, CEntity::pEventHandler(&CEnemyDive:: +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +DiveHit),DEBUGSTRING("CEnemyDive::DiveHit")}, + {0x01390006, -1, CEntity::pEventHandler(&CEnemyDive:: +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/EnemyDive.es" +DiveFire),DEBUGSTRING("CEnemyDive::DiveFire")}, +}; +#define CEnemyDive_handlersct ARRAYCOUNT(CEnemyDive_handlers) + +CEntity *CEnemyDive_New(void) { return new CEnemyDive; }; +void CEnemyDive_OnInitClass(void) {}; +void CEnemyDive_OnEndClass(void) {}; +void CEnemyDive_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEnemyDive_OnWorldEnd(CWorld *pwo) {}; +void CEnemyDive_OnWorldInit(CWorld *pwo) {}; +void CEnemyDive_OnWorldTick(CWorld *pwo) {}; +void CEnemyDive_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEnemyDive, CEnemyBase, "Enemy Dive", "", 0x00000139); +DECLARE_CTFILENAME(_fnmCEnemyDive_tbn, ""); diff --git a/Sources/EntitiesMP/EnemyFly.cpp b/Sources/EntitiesMP/EnemyFly.cpp new file mode 100644 index 0000000..2cefe9f --- /dev/null +++ b/Sources/EntitiesMP/EnemyFly.cpp @@ -0,0 +1,564 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" + +#include "StdH.h" + +#include +#include +void CEnemyFly::SetDefaultProperties(void) { + m_EeftType = EFT_FLY_GROUND_AIR ; + m_bInAir = FALSE ; + m_bAirAttack = FALSE ; + m_bStartInAir = FALSE ; + m_fGroundToAirSpeed = 2.0f; + m_fAirToGroundSpeed = 4.0f; + m_fAirToGroundMin = 1.0f; + m_fAirToGroundMax = 2.0f; + m_fFlyHeight = 2.0f; + m_fFlyWalkSpeed = 1.0f; + m_aFlyWalkRotateSpeed = AngleDeg(10.0f); + m_fFlyAttackRunSpeed = 1.0f; + m_aFlyAttackRotateSpeed = AngleDeg(10.0f); + m_fFlyCloseRunSpeed = 1.0f; + m_aFlyCloseRotateSpeed = AngleDeg(10.0f); + m_fFlyAttackDistance = 50.0f; + m_fFlyCloseDistance = 10.0f; + m_fFlyAttackFireTime = 2.0f; + m_fFlyCloseFireTime = 1.0f; + m_fFlyStopDistance = 0.0f; + m_fFlyIgnoreRange = 200.0f; + m_fFlyLockOnEnemyTime = 0.0f; + m_bFlyToMarker = FALSE ; + CEnemyBase::SetDefaultProperties(); +} + FLOAT & CEnemyFly::GetProp(FLOAT & m_fBase) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +{ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(m_bInAir ){ +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return * ((& m_fBase ) + (& m_fFlyWalkSpeed - & m_fWalkSpeed )); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +}else { +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return m_fBase ; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} + FLOAT3D CEnemyFly::PlayerDestinationPos(void) +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +{ +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(! m_bInAir ){ +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return CEnemyBase :: PlayerDestinationPos (); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +FLOAT fDist = CalcDist (m_penEnemy ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +FLOAT fHeight ; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(fDist <= m_fFlyCloseDistance ){ +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +fHeight = m_fFlyHeight ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +}else { +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +fHeight = m_fFlyHeight + fDist / 5.0f; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_penEnemy -> GetPlacement () . pl_PositionVector +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" ++ FLOAT3D (m_penEnemy -> en_mRotation (1 , 2) , m_penEnemy -> en_mRotation (2 , 2) , m_penEnemy -> en_mRotation (3 , 2)) +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +* fHeight ; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} + +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +void CEnemyFly::StartPathFinding(void) +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +{ +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(m_bInAir ){ +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_dtDestination = DT_PLAYERSPOTTED ; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_vPlayerSpotted = PlayerDestinationPos (); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +}else { +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +CEnemyBase :: StartPathFinding (); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} + void CEnemyFly::AdjustDifficulty(void) +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +{ +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +FLOAT fMoveSpeed = GetSP () -> sp_fEnemyMovementSpeed ; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +FLOAT fAttackSpeed = GetSP () -> sp_fEnemyMovementSpeed ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_fFlyAttackFireTime *= 1 / fAttackSpeed ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_fFlyCloseFireTime *= 1 / fAttackSpeed ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_fFlyLockOnEnemyTime *= 1 / fAttackSpeed ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_fFlyAttackRunSpeed *= fMoveSpeed ; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_aFlyAttackRotateSpeed *= fMoveSpeed ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_fFlyCloseRunSpeed *= fMoveSpeed ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_aFlyCloseRotateSpeed *= fMoveSpeed ; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_fGroundToAirSpeed *= fMoveSpeed ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_fAirToGroundSpeed *= fMoveSpeed ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +CEnemyBase :: AdjustDifficulty (); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} + BOOL CEnemyFly::CanHitEnemy(CEntity * penTarget,FLOAT fCosAngle) { +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(IsInPlaneFrustum (penTarget , fCosAngle )){ +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return IsVisibleCheckAll (penTarget ); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return FALSE ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} + ULONG CEnemyFly::SetDesiredMovement(void) +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +{ +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(! m_bInAir ){ +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return CEnemyBase :: SetDesiredMovement (); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +ULONG ulFlags = CEnemyBase :: SetDesiredMovement (); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(m_fMoveSpeed > 0.0f){ +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +FLOAT3D vTranslation = (m_vDesiredPosition - GetPlacement () . pl_PositionVector ) * ! en_mRotation ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +vTranslation (1) = 0.0f; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(vTranslation (3) > 0){ +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +vTranslation (3) = 0.0f; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +vTranslation . Normalize (); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +vTranslation *= m_fMoveSpeed ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetDesiredTranslation (vTranslation ); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return ulFlags ; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} + +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +void CEnemyFly::SetEntityPosition() { +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +switch(m_EeftType ){ +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +case EFT_GROUND_ONLY : +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +case EFT_FLY_GROUND_GROUND : +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bAirAttack = FALSE ; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bStartInAir = m_bInAir = FALSE ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bFlyToMarker = FALSE ; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetPhysicsFlags ((GetPhysicsFlags () & ~ EPF_MODEL_FLYING ) | EPF_MODEL_WALKING ); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +ChangeCollisionToGround (); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +break ; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +case EFT_FLY_GROUND_AIR : +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bAirAttack = TRUE ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bStartInAir = m_bInAir = FALSE ; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bFlyToMarker = FALSE ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetPhysicsFlags ((GetPhysicsFlags () & ~ EPF_MODEL_FLYING ) | EPF_MODEL_WALKING ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +ChangeCollisionToGround (); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +break ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +case EFT_FLY_AIR_GROUND : +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bAirAttack = FALSE ; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bStartInAir = m_bInAir = TRUE ; +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bFlyToMarker = TRUE ; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetPhysicsFlags ((GetPhysicsFlags () & ~ EPF_MODEL_WALKING ) | EPF_MODEL_FLYING ); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +ChangeCollisionToAir (); +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +break ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +case EFT_FLY_ONLY : +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +case EFT_FLY_AIR_AIR : +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bAirAttack = TRUE ; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bStartInAir = m_bInAir = TRUE ; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bFlyToMarker = TRUE ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetPhysicsFlags ((GetPhysicsFlags () & ~ EPF_MODEL_WALKING ) | EPF_MODEL_FLYING ); +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +ChangeCollisionToAir (); +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +break ; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +StandingAnim (); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} + FLOAT CEnemyFly::AirToGroundAnim(void) {return _pTimer -> TickQuantum ;} + FLOAT CEnemyFly::GroundToAirAnim(void) {return _pTimer -> TickQuantum ;} + void CEnemyFly::ChangeCollisionToAir(void) {} + void CEnemyFly::ChangeCollisionToGround(void) {} +BOOL CEnemyFly:: +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +ReturnToStartPosition(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_ReturnToStartPosition + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::ReturnToStartPosition expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_BeIdle, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +BeWounded(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_BeWounded + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDamage, "CEnemyFly::BeWounded expects 'EDamage' as input!"); const EDamage &eDamage = (const EDamage &)__eeInput; +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(!(! (m_EeftType != EFT_FLY_ONLY && m_bInAir && ((IRnd () & 3) == 0)))){ Jump(STATE_CURRENT,0x01370006, FALSE, EInternal());return TRUE;} +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_BeWounded, FALSE, eDamage );return TRUE;Jump(STATE_CURRENT,0x01370005, FALSE, EInternal());return TRUE;}BOOL CEnemyFly::H0x01370006_BeWounded_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370006 +if(!(TRUE )){ Jump(STATE_CURRENT,0x01370004, FALSE, EInternal());return TRUE;} +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bAirAttack = FALSE ; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +STATE_CEnemyFly_AirToGround, TRUE; +Jump(STATE_CURRENT, 0x01370002, FALSE, EBegin());return TRUE;}BOOL CEnemyFly::H0x01370002_BeWounded_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370002 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyFly_AirToGround, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01370003, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyFly::H0x01370003_BeWounded_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370003 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01370004, FALSE, EInternal());return TRUE;}BOOL CEnemyFly::H0x01370004_BeWounded_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370004 +Jump(STATE_CURRENT,0x01370005, FALSE, EInternal());return TRUE;} +BOOL CEnemyFly::H0x01370005_BeWounded_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370005 + +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Return(STATE_CURRENT,EReturn ()); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +AirToGround(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_AirToGround + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::AirToGround expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetDesiredTranslation (FLOAT3D (0 , - m_fAirToGroundSpeed , 0)); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +WalkingAnim (); +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01370008, FALSE, EBegin());return TRUE;}BOOL CEnemyFly::H0x01370008_AirToGround_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370008 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(etouch . penOther -> GetRenderType () & RT_BRUSH ){ +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetDesiredTranslation (FLOAT3D (0 , 0 , 0)); +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +UnsetTimer();Jump(STATE_CURRENT,0x01370009, FALSE, EInternal());return TRUE; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return TRUE; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +return FALSE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +}return TRUE;}BOOL CEnemyFly::H0x01370009_AirToGround_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370009 + +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetPhysicsFlags ((GetPhysicsFlags () & ~ EPF_MODEL_FLYING ) | EPF_MODEL_WALKING ); +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bInAir = FALSE ; +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +ChangeCollisionToGround (); +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetTimerAfter(AirToGroundAnim ()); +Jump(STATE_CURRENT, 0x0137000a, FALSE, EBegin());return TRUE;}BOOL CEnemyFly::H0x0137000a_AirToGround_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0137000a +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x0137000b, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +return FALSE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +}return TRUE;}BOOL CEnemyFly::H0x0137000b_AirToGround_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0137000b + +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Return(STATE_CURRENT,EReturn ()); +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +GroundToAir(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_GroundToAir + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::GroundToAir expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetPhysicsFlags ((GetPhysicsFlags () & ~ EPF_MODEL_WALKING ) | EPF_MODEL_FLYING ); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +m_bInAir = TRUE ; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetDesiredTranslation (FLOAT3D (0 , m_fGroundToAirSpeed , 0)); +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +ChangeCollisionToAir (); +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetTimerAfter(GroundToAirAnim ()); +Jump(STATE_CURRENT, 0x0137000d, FALSE, EBegin());return TRUE;}BOOL CEnemyFly::H0x0137000d_GroundToAir_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0137000d +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x0137000e, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +}return TRUE;}BOOL CEnemyFly::H0x0137000e_GroundToAir_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0137000e + +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +WalkingAnim (); +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetTimerAfter(Lerp (m_fAirToGroundMin , m_fAirToGroundMax , FRnd ())); +Jump(STATE_CURRENT, 0x0137000f, FALSE, EBegin());return TRUE;}BOOL CEnemyFly::H0x0137000f_GroundToAir_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0137000f +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01370010, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +}return TRUE;}BOOL CEnemyFly::H0x01370010_GroundToAir_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370010 + +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetDesiredTranslation (FLOAT3D (0 , 0 , 0)); +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Return(STATE_CURRENT,EReturn ()); +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +AttackEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_AttackEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::AttackEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(!(m_bAirAttack )){ Jump(STATE_CURRENT,0x0137001a, FALSE, EInternal());return TRUE;} +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(!(! m_bInAir )){ Jump(STATE_CURRENT,0x01370014, FALSE, EInternal());return TRUE;} +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +STATE_CEnemyFly_GroundToAir, TRUE; +Jump(STATE_CURRENT, 0x01370012, FALSE, EBegin());return TRUE;}BOOL CEnemyFly::H0x01370012_AttackEnemy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370012 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyFly_GroundToAir, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01370013, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyFly::H0x01370013_AttackEnemy_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370013 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01370014, FALSE, EInternal());return TRUE;}BOOL CEnemyFly::H0x01370014_AttackEnemy_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370014 +Jump(STATE_CURRENT,0x01370019, FALSE, EInternal());return TRUE;}BOOL CEnemyFly::H0x0137001a_AttackEnemy_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0137001a +if(!(TRUE )){ Jump(STATE_CURRENT,0x01370018, FALSE, EInternal());return TRUE;} +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(!(m_bInAir )){ Jump(STATE_CURRENT,0x01370017, FALSE, EInternal());return TRUE;} +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +STATE_CEnemyFly_AirToGround, TRUE; +Jump(STATE_CURRENT, 0x01370015, FALSE, EBegin());return TRUE;}BOOL CEnemyFly::H0x01370015_AttackEnemy_04(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyFly_AirToGround, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01370016, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyFly::H0x01370016_AttackEnemy_05(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370016 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01370017, FALSE, EInternal());return TRUE;}BOOL CEnemyFly::H0x01370017_AttackEnemy_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370017 +Jump(STATE_CURRENT,0x01370018, FALSE, EInternal());return TRUE;}BOOL CEnemyFly::H0x01370018_AttackEnemy_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370018 +Jump(STATE_CURRENT,0x01370019, FALSE, EInternal());return TRUE;} +BOOL CEnemyFly::H0x01370019_AttackEnemy_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01370019 + +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_AttackEnemy, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(m_bInAir ){ +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Jump(STATE_CURRENT, STATE_CEnemyFly_FlyHit, TRUE, EVoid());return TRUE; +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +}else { +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Jump(STATE_CURRENT, STATE_CEnemyFly_GroundHit, TRUE, EVoid());return TRUE; +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +if(m_bInAir ){ +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Jump(STATE_CURRENT, STATE_CEnemyFly_FlyFire, TRUE, EVoid());return TRUE; +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +}else { +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Jump(STATE_CURRENT, STATE_CEnemyFly_GroundFire, TRUE, EVoid());return TRUE; +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +} ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Death(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_Death + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::Death expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetPhysicsFlags ((GetPhysicsFlags () & ~ EPF_MODEL_FLYING ) | EPF_MODEL_WALKING ); +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +ChangeCollisionToGround (); +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Death, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +MainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_MainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::MainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +SetEntityPosition (); +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Return(STATE_CURRENT,EVoid()); +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +GroundHit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_GroundHit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::GroundHit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Return(STATE_CURRENT,EReturn ()); +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +GroundFire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_GroundFire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::GroundFire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Return(STATE_CURRENT,EReturn ()); +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +FlyHit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_FlyHit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::FlyHit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Return(STATE_CURRENT,EReturn ()); +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyFly:: +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +FlyFire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyFly_FlyFire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyFly::FlyFire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Return(STATE_CURRENT,EReturn ()); +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EnemyFly.es b/Sources/EntitiesMP/EnemyFly.es new file mode 100644 index 0000000..18ded8d --- /dev/null +++ b/Sources/EntitiesMP/EnemyFly.es @@ -0,0 +1,481 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +311 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/Debris"; +uses "EntitiesMP/EnemyMarker"; + + +enum EnemyFlyType { + 0 EFT_GROUND_ONLY "Ground only", // can't fly + 1 EFT_FLY_ONLY "Fly only", // always fly can't land + 2 EFT_FLY_GROUND_GROUND "Fly(ground) - ground attack", // start attack on ground - ground + 3 EFT_FLY_GROUND_AIR "Fly(ground) - air attack", // start attack in air - ground + 4 EFT_FLY_AIR_GROUND "Fly(air) - ground attack", // start attack on ground - air + 5 EFT_FLY_AIR_AIR "Fly(air) - air attack", // start attack in air - air +}; + + +class export CEnemyFly : CEnemyBase { +name "Enemy Fly"; +thumbnail ""; + +properties: + 1 enum EnemyFlyType m_EeftType "Type" 'T' = EFT_FLY_GROUND_AIR, // fly type + 2 BOOL m_bInAir = FALSE, // entity is in air + 3 BOOL m_bAirAttack = FALSE, // start air attack + 4 BOOL m_bStartInAir = FALSE, // initially in air + + // moving/attack properties - CAN BE SET + 16 FLOAT m_fGroundToAirSpeed = 2.0f, // ground to air speed + 17 FLOAT m_fAirToGroundSpeed = 4.0f, // air to ground speed + 18 FLOAT m_fAirToGroundMin = 1.0f, // how long to fly up before attacking + 19 FLOAT m_fAirToGroundMax = 2.0f, + 27 FLOAT m_fFlyHeight = 2.0f, // fly height above player handle + + // these following must be ordered exactly like this for GetProp() to function + 10 FLOAT m_fFlyWalkSpeed = 1.0f, // fly walk speed + 11 ANGLE m_aFlyWalkRotateSpeed = AngleDeg(10.0f), // fly walk rotate speed + 12 FLOAT m_fFlyAttackRunSpeed = 1.0f, // fly attack run speed + 13 ANGLE m_aFlyAttackRotateSpeed = AngleDeg(10.0f), // fly attack rotate speed + 14 FLOAT m_fFlyCloseRunSpeed = 1.0f, // fly close run speed + 15 ANGLE m_aFlyCloseRotateSpeed = AngleDeg(10.0f), // fly close rotate speed + 20 FLOAT m_fFlyAttackDistance = 50.0f, // fly attack distance mode + 21 FLOAT m_fFlyCloseDistance = 10.0f, // fly close distance mode + 22 FLOAT m_fFlyAttackFireTime = 2.0f, // fly attack distance fire time + 23 FLOAT m_fFlyCloseFireTime = 1.0f, // fly close distance fire time + 24 FLOAT m_fFlyStopDistance = 0.0f, // fly stop moving toward enemy if closer than stop distance + 25 FLOAT m_fFlyIgnoreRange = 200.0f, // fly cease attack if enemy farther + 26 FLOAT m_fFlyLockOnEnemyTime = 0.0f, // fly time needed to fire + + // marker variables +100 BOOL m_bFlyToMarker = FALSE, + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + +functions: + // overridable function for access to different properties of derived classes (flying/diving) + virtual FLOAT &GetProp(FLOAT &m_fBase) + { + if (m_bInAir) { + return *((&m_fBase)+(&m_fFlyWalkSpeed-&m_fWalkSpeed)); + } else { + return m_fBase; + } + } + + // get position you would like to go to when following player + virtual FLOAT3D PlayerDestinationPos(void) + { + // if not in air + if (!m_bInAir) { + // use base class + return CEnemyBase::PlayerDestinationPos(); + } + + // get distance to player + FLOAT fDist = CalcDist(m_penEnemy); + // determine height above from the distance + FLOAT fHeight; + // if in close attack range + if (fDist<=m_fFlyCloseDistance) { + // go to fixed height above player + fHeight = m_fFlyHeight; + // if in further + } else { + // fly more above if further + fHeight = m_fFlyHeight + fDist/5.0f; + } + + // calculate the position from the height + return + m_penEnemy->GetPlacement().pl_PositionVector + + FLOAT3D(m_penEnemy->en_mRotation(1, 2), m_penEnemy->en_mRotation(2, 2), m_penEnemy->en_mRotation(3, 2)) + * fHeight; + } + + // flying enemies never use pathfinding + void StartPathFinding(void) + { + if (m_bInAir) { + m_dtDestination=DT_PLAYERSPOTTED; + m_vPlayerSpotted = PlayerDestinationPos(); + } else { + CEnemyBase::StartPathFinding(); + } + } + + virtual void AdjustDifficulty(void) + { + FLOAT fMoveSpeed = GetSP()->sp_fEnemyMovementSpeed; + FLOAT fAttackSpeed = GetSP()->sp_fEnemyMovementSpeed; + + m_fFlyAttackFireTime *= 1/fAttackSpeed; + m_fFlyCloseFireTime *= 1/fAttackSpeed; + m_fFlyLockOnEnemyTime *= 1/fAttackSpeed; +// m_fFlyWalkSpeed *= fMoveSpeed; +// m_aFlyWalkRotateSpeed *= fMoveSpeed; + m_fFlyAttackRunSpeed *= fMoveSpeed; + m_aFlyAttackRotateSpeed *= fMoveSpeed; + m_fFlyCloseRunSpeed *= fMoveSpeed; + m_aFlyCloseRotateSpeed *= fMoveSpeed; + m_fGroundToAirSpeed *= fMoveSpeed; + m_fAirToGroundSpeed *= fMoveSpeed; + + CEnemyBase::AdjustDifficulty(); + } + + // close attack if possible + virtual BOOL CanHitEnemy(CEntity *penTarget, FLOAT fCosAngle) { + if (IsInPlaneFrustum(penTarget, fCosAngle)) { + return IsVisibleCheckAll(penTarget); + } + return FALSE; + }; +/************************************************************ + * MOVING FUNCTIONS * + ************************************************************/ + + // set desired rotation and translation to go/orient towards desired position + // and get the resulting movement type + virtual ULONG SetDesiredMovement(void) + { + // if not in air + if (!m_bInAir) { + // use base class + return CEnemyBase::SetDesiredMovement(); + } + + // get base rotation from base class + ULONG ulFlags = CEnemyBase::SetDesiredMovement(); + + // if we may move + if (m_fMoveSpeed>0.0f) { + // fix translation for 3d movement + FLOAT3D vTranslation = (m_vDesiredPosition - GetPlacement().pl_PositionVector) * !en_mRotation; + vTranslation(1) = 0.0f; + if (vTranslation(3)>0) { + vTranslation(3) = 0.0f; + } + vTranslation.Normalize(); + vTranslation *= m_fMoveSpeed; + SetDesiredTranslation(vTranslation); + } + + return ulFlags; + } + +/************************************************************ + * CLASS SUPPORT FUNCTIONS * + ************************************************************/ + // set entity position + void SetEntityPosition() { + switch (m_EeftType) { + case EFT_GROUND_ONLY: // ground only enemy + case EFT_FLY_GROUND_GROUND: // fly, on ground, start attack on ground + m_bAirAttack = FALSE; + m_bStartInAir = m_bInAir = FALSE; + m_bFlyToMarker = FALSE; + SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_FLYING) | EPF_MODEL_WALKING); + ChangeCollisionToGround(); + break; + + case EFT_FLY_GROUND_AIR: // fly, on ground, start attack in air + m_bAirAttack = TRUE; + m_bStartInAir = m_bInAir = FALSE; + m_bFlyToMarker = FALSE; + SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_FLYING) | EPF_MODEL_WALKING); + ChangeCollisionToGround(); + break; + + case EFT_FLY_AIR_GROUND: // fly, in air, start attack on ground + m_bAirAttack = FALSE; + m_bStartInAir = m_bInAir = TRUE; + m_bFlyToMarker = TRUE; + SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_WALKING) | EPF_MODEL_FLYING); + ChangeCollisionToAir(); + break; + + case EFT_FLY_ONLY: // air only enemy + case EFT_FLY_AIR_AIR: // fly, in air, start attack in air + m_bAirAttack = TRUE; + m_bStartInAir = m_bInAir = TRUE; + m_bFlyToMarker = TRUE; + SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_WALKING) | EPF_MODEL_FLYING); + ChangeCollisionToAir(); + break; + } + StandingAnim(); + }; + + +/************************************************************ + * VIRTUAL FUNCTIONS THAT NEED OVERRIDE * + ************************************************************/ + virtual FLOAT AirToGroundAnim(void) { return _pTimer->TickQuantum; } + virtual FLOAT GroundToAirAnim(void) { return _pTimer->TickQuantum; } + virtual void ChangeCollisionToAir(void) {} + virtual void ChangeCollisionToGround(void) {} + + + +procedures: +/************************************************************ + * PROCEDURES WHEN NO ANY SPECIAL ACTION * + ************************************************************/ +/* +#### !!!! + MoveToDestinationFlying(EVoid) { + m_fMoveFrequency = 0.25f; + m_fMoveTime = _pTimer->CurrentTick() + 45.0f; + while ((m_vDesiredPosition-GetPlacement().pl_PositionVector).Length()>m_fMoveSpeed*m_fMoveFrequency*2.0f && + m_fMoveTime>_pTimer->CurrentTick()) { + wait (m_fMoveFrequency) { + on (EBegin) : { FlyToPosition(); } + on (ETimer) : { stop; } + } + } + return EReturn(); + } + // Move to destination + MoveToDestination(EVoid) : CEnemyBase::MoveToDestination { + if (m_bFlyToMarker && !m_bInAir) { + autocall GroundToAir() EReturn; + } else if (!m_bFlyToMarker && m_bInAir) { + autocall AirToGround() EReturn; + } + + // animation + if (m_bRunToMarker) { + RunningAnim(); + } else { + WalkingAnim(); + } + // fly to position + if (m_bInAir) { + jump MoveToDestinationFlying(); + // move to position + } else { + jump CEnemyBase::MoveToDestination(); + } + };*/ + + // return to start position + ReturnToStartPosition(EVoid) : CEnemyBase::ReturnToStartPosition + { + jump CEnemyBase::BeIdle(); +/* // if on ground, but can fly + if (!m_bInAir && m_EeftType!=EFT_GROUND_ONLY) { + // fly up + autocall GroundToAir() EReturn; + } + + GetWatcher()->StartPlayers(); // start watching + m_vDesiredPosition = m_vStartPosition-en_vGravityDir*2.0f; + m_vStartDirection = (GetPlacement().pl_PositionVector-m_vStartPosition).Normalize(); + m_fMoveSpeed = m_fAttackRunSpeed; + m_aRotateSpeed = m_aAttackRotateSpeed; + RunningAnim(); + autocall MoveToDestinationFlying() EReturn; + + WalkingAnim(); + m_vDesiredAngle = m_vStartDirection; + StopTranslating(); + + autocall CEnemyBase::RotateToStartDirection() EReturn; + + // if should be on ground + if (m_bInAir && !m_bStartInAir) { + // fly down + autocall AirToGround() EReturn; + } + StopMoving(); + StandingAnim(); + + jump CEnemyBase::BeIdle();*/ + }; + +/************************************************************ + * PROCEDURES WHEN HARMED * + ************************************************************/ + // Play wound animation and falling body part + BeWounded(EDamage eDamage) : CEnemyBase::BeWounded { + // land on ground + if (!(m_EeftType!=EFT_FLY_ONLY && m_bInAir && ((IRnd()&3)==0))) { + jump CEnemyBase::BeWounded(eDamage); + } else if (TRUE) { + m_bAirAttack = FALSE; + autocall AirToGround() EReturn; + } + return EReturn(); + }; + + + +/************************************************************ + * AIR - GROUND PROCEDURES * + ************************************************************/ + // air to ground + AirToGround(EVoid) + { + // land on brush + SetDesiredTranslation(FLOAT3D(0, -m_fAirToGroundSpeed, 0)); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + WalkingAnim(); + wait() { + on (EBegin) : { resume; } + // on brush stop + on (ETouch etouch) : { + if (etouch.penOther->GetRenderType() & RT_BRUSH) { + SetDesiredTranslation(FLOAT3D(0, 0, 0)); + stop; + } + resume; + } + on (EDeath) : { pass; } + otherwise() : { resume; } + } + // on ground + SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_FLYING) | EPF_MODEL_WALKING); + m_bInAir = FALSE; + ChangeCollisionToGround(); + // animation + wait(AirToGroundAnim()) { + on (EBegin) : { resume; } + on (ETimer) : { stop; } + on (EDeath) : { pass; } + otherwise() : { resume; } + } + return EReturn(); + }; + + // ground to air + GroundToAir(EVoid) + { + // fly in air + SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_WALKING) | EPF_MODEL_FLYING); + m_bInAir = TRUE; + SetDesiredTranslation(FLOAT3D(0, m_fGroundToAirSpeed, 0)); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + ChangeCollisionToAir(); + // animation + wait(GroundToAirAnim()) { + on (EBegin) : { resume; } + on (EDeath) : { pass; } + on (ETimer) : { stop; } + otherwise() : { resume; } + } + // move in air further + WalkingAnim(); + wait(Lerp(m_fAirToGroundMin, m_fAirToGroundMax, FRnd())) { + on (EBegin) : { resume; } + on (EDeath) : { pass; } + on (ETimer) : { stop; } + otherwise() : { resume; } + } + SetDesiredTranslation(FLOAT3D(0, 0, 0)); + return EReturn(); + }; + + + +/************************************************************ + * ATTACK ENEMY PROCEDURES * + ************************************************************/ + // initialize attack is overridden to switch fly/walk modes if needed + AttackEnemy() : CEnemyBase::AttackEnemy + { + // air attack + if (m_bAirAttack) { + // ground to air + if (!m_bInAir) { + autocall GroundToAir() EReturn; + } + // ground attack + } else if (TRUE) { + // air to ground + if (m_bInAir) { + autocall AirToGround() EReturn; + } + } + + jump CEnemyBase::AttackEnemy(); + } + + // this is called to hit the player when near + Hit(EVoid) : CEnemyBase::Hit + { + if (m_bInAir) { + jump FlyHit(); + } else { + jump GroundHit(); + } + } + + // this is called to shoot at player when far away or otherwise unreachable + Fire(EVoid) : CEnemyBase::Fire + { + if (m_bInAir) { + jump FlyFire(); + } else { + jump GroundFire(); + } + } + +/************************************************************ + * D E A T H * + ************************************************************/ + Death(EVoid) : CEnemyBase::Death { + // clear fly flag + SetPhysicsFlags((GetPhysicsFlags() & ~EPF_MODEL_FLYING) | EPF_MODEL_WALKING); + ChangeCollisionToGround(); + jump CEnemyBase::Death(); + }; + + + +/************************************************************ + * M A I N L O O P * + ************************************************************/ + // main loop + MainLoop(EVoid) : CEnemyBase::MainLoop { + SetEntityPosition(); + jump CEnemyBase::MainLoop(); + }; + + // dummy main + Main(EVoid) { + return; + }; + +/************************************************************ + * VIRTUAL PROCEDURES THAT NEED OVERRIDE * + ************************************************************/ + // this is called to hit the player when near and you are on ground + GroundHit(EVoid) + { + return EReturn(); + } + // this is called to shoot at player when far away or otherwise unreachable and you are on ground + GroundFire(EVoid) + { + return EReturn(); + } + + // this is called to hit the player when near and you are in air + FlyHit(EVoid) + { + return EReturn(); + } + + // this is called to shoot at player when far away or otherwise unreachable and you are in air + FlyFire(EVoid) + { + return EReturn(); + } +}; diff --git a/Sources/EntitiesMP/EnemyFly.h b/Sources/EntitiesMP/EnemyFly.h new file mode 100644 index 0000000..5a46f04 --- /dev/null +++ b/Sources/EntitiesMP/EnemyFly.h @@ -0,0 +1,159 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_EnemyFly_INCLUDED +#define _EntitiesMP_EnemyFly_INCLUDED 1 +#include +#include +#include +extern DECL_DLL CEntityPropertyEnumType EnemyFlyType_enum; +enum EnemyFlyType { + EFT_GROUND_ONLY = 0, + EFT_FLY_ONLY = 1, + EFT_FLY_GROUND_GROUND = 2, + EFT_FLY_GROUND_AIR = 3, + EFT_FLY_AIR_GROUND = 4, + EFT_FLY_AIR_AIR = 5, +}; +DECL_DLL inline void ClearToDefault(EnemyFlyType &e) { e = (EnemyFlyType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CEnemyFly_DLLClass; +class DECL_DLL CEnemyFly : public CEnemyBase { +public: + virtual void SetDefaultProperties(void); + enum EnemyFlyType m_EeftType; + BOOL m_bInAir; + BOOL m_bAirAttack; + BOOL m_bStartInAir; + FLOAT m_fGroundToAirSpeed; + FLOAT m_fAirToGroundSpeed; + FLOAT m_fAirToGroundMin; + FLOAT m_fAirToGroundMax; + FLOAT m_fFlyHeight; + FLOAT m_fFlyWalkSpeed; + ANGLE m_aFlyWalkRotateSpeed; + FLOAT m_fFlyAttackRunSpeed; + ANGLE m_aFlyAttackRotateSpeed; + FLOAT m_fFlyCloseRunSpeed; + ANGLE m_aFlyCloseRotateSpeed; + FLOAT m_fFlyAttackDistance; + FLOAT m_fFlyCloseDistance; + FLOAT m_fFlyAttackFireTime; + FLOAT m_fFlyCloseFireTime; + FLOAT m_fFlyStopDistance; + FLOAT m_fFlyIgnoreRange; + FLOAT m_fFlyLockOnEnemyTime; + BOOL m_bFlyToMarker; + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +virtual FLOAT & GetProp(FLOAT & m_fBase); + +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +virtual FLOAT3D PlayerDestinationPos(void); + +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +void StartPathFinding(void); + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +virtual void AdjustDifficulty(void); + +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +virtual BOOL CanHitEnemy(CEntity * penTarget,FLOAT fCosAngle); + +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +virtual ULONG SetDesiredMovement(void); + +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +void SetEntityPosition(); + +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +virtual FLOAT AirToGroundAnim(void); + +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +virtual FLOAT GroundToAirAnim(void); + +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +virtual void ChangeCollisionToAir(void); + +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +virtual void ChangeCollisionToGround(void); +#define STATE_CEnemyFly_ReturnToStartPosition 0x01370000 + BOOL +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +ReturnToStartPosition(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_BeWounded 0x01370001 + BOOL +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +BeWounded(const CEntityEvent &__eeInput); + BOOL H0x01370002_BeWounded_01(const CEntityEvent &__eeInput); + BOOL H0x01370003_BeWounded_02(const CEntityEvent &__eeInput); + BOOL H0x01370004_BeWounded_03(const CEntityEvent &__eeInput); + BOOL H0x01370005_BeWounded_04(const CEntityEvent &__eeInput); + BOOL H0x01370006_BeWounded_05(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_AirToGround 0x01370007 + BOOL +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +AirToGround(const CEntityEvent &__eeInput); + BOOL H0x01370008_AirToGround_01(const CEntityEvent &__eeInput); + BOOL H0x01370009_AirToGround_02(const CEntityEvent &__eeInput); + BOOL H0x0137000a_AirToGround_03(const CEntityEvent &__eeInput); + BOOL H0x0137000b_AirToGround_04(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_GroundToAir 0x0137000c + BOOL +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +GroundToAir(const CEntityEvent &__eeInput); + BOOL H0x0137000d_GroundToAir_01(const CEntityEvent &__eeInput); + BOOL H0x0137000e_GroundToAir_02(const CEntityEvent &__eeInput); + BOOL H0x0137000f_GroundToAir_03(const CEntityEvent &__eeInput); + BOOL H0x01370010_GroundToAir_04(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_AttackEnemy 0x01370011 + BOOL +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +AttackEnemy(const CEntityEvent &__eeInput); + BOOL H0x01370012_AttackEnemy_01(const CEntityEvent &__eeInput); + BOOL H0x01370013_AttackEnemy_02(const CEntityEvent &__eeInput); + BOOL H0x01370014_AttackEnemy_03(const CEntityEvent &__eeInput); + BOOL H0x01370015_AttackEnemy_04(const CEntityEvent &__eeInput); + BOOL H0x01370016_AttackEnemy_05(const CEntityEvent &__eeInput); + BOOL H0x01370017_AttackEnemy_06(const CEntityEvent &__eeInput); + BOOL H0x01370018_AttackEnemy_07(const CEntityEvent &__eeInput); + BOOL H0x01370019_AttackEnemy_08(const CEntityEvent &__eeInput); + BOOL H0x0137001a_AttackEnemy_09(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_Hit 0x0137001b + BOOL +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Hit(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_Fire 0x0137001c + BOOL +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Fire(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_Death 0x0137001d + BOOL +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Death(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_MainLoop 0x0137001e + BOOL +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +MainLoop(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_Main 1 + BOOL +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Main(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_GroundHit 0x0137001f + BOOL +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +GroundHit(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_GroundFire 0x01370020 + BOOL +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +GroundFire(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_FlyHit 0x01370021 + BOOL +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +FlyHit(const CEntityEvent &__eeInput); +#define STATE_CEnemyFly_FlyFire 0x01370022 + BOOL +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +FlyFire(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_EnemyFly_INCLUDED diff --git a/Sources/EntitiesMP/EnemyFly_tables.h b/Sources/EntitiesMP/EnemyFly_tables.h new file mode 100644 index 0000000..c211dce --- /dev/null +++ b/Sources/EntitiesMP/EnemyFly_tables.h @@ -0,0 +1,126 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(EnemyFlyType) + EP_ENUMVALUE(EFT_GROUND_ONLY, "Ground only"), + EP_ENUMVALUE(EFT_FLY_ONLY, "Fly only"), + EP_ENUMVALUE(EFT_FLY_GROUND_GROUND, "Fly(ground) - ground attack"), + EP_ENUMVALUE(EFT_FLY_GROUND_AIR, "Fly(ground) - air attack"), + EP_ENUMVALUE(EFT_FLY_AIR_GROUND, "Fly(air) - ground attack"), + EP_ENUMVALUE(EFT_FLY_AIR_AIR, "Fly(air) - air attack"), +EP_ENUMEND(EnemyFlyType); + +#define ENTITYCLASS CEnemyFly + +CEntityProperty CEnemyFly_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &EnemyFlyType_enum, (0x00000137<<8)+1, offsetof(CEnemyFly, m_EeftType), "Type", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000137<<8)+2, offsetof(CEnemyFly, m_bInAir), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000137<<8)+3, offsetof(CEnemyFly, m_bAirAttack), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000137<<8)+4, offsetof(CEnemyFly, m_bStartInAir), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+16, offsetof(CEnemyFly, m_fGroundToAirSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+17, offsetof(CEnemyFly, m_fAirToGroundSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+18, offsetof(CEnemyFly, m_fAirToGroundMin), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+19, offsetof(CEnemyFly, m_fAirToGroundMax), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+27, offsetof(CEnemyFly, m_fFlyHeight), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+10, offsetof(CEnemyFly, m_fFlyWalkSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000137<<8)+11, offsetof(CEnemyFly, m_aFlyWalkRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+12, offsetof(CEnemyFly, m_fFlyAttackRunSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000137<<8)+13, offsetof(CEnemyFly, m_aFlyAttackRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+14, offsetof(CEnemyFly, m_fFlyCloseRunSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000137<<8)+15, offsetof(CEnemyFly, m_aFlyCloseRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+20, offsetof(CEnemyFly, m_fFlyAttackDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+21, offsetof(CEnemyFly, m_fFlyCloseDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+22, offsetof(CEnemyFly, m_fFlyAttackFireTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+23, offsetof(CEnemyFly, m_fFlyCloseFireTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+24, offsetof(CEnemyFly, m_fFlyStopDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+25, offsetof(CEnemyFly, m_fFlyIgnoreRange), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000137<<8)+26, offsetof(CEnemyFly, m_fFlyLockOnEnemyTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000137<<8)+100, offsetof(CEnemyFly, m_bFlyToMarker), "", 0, 0, 0), +}; +#define CEnemyFly_propertiesct ARRAYCOUNT(CEnemyFly_properties) + +CEntityComponent CEnemyFly_components[] = { +#define CLASS_BASE ((0x00000137<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +}; +#define CEnemyFly_componentsct ARRAYCOUNT(CEnemyFly_components) + +CEventHandlerEntry CEnemyFly_handlers[] = { + {0x01370000, STATE_CEnemyBase_ReturnToStartPosition, CEntity::pEventHandler(&CEnemyFly:: +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +ReturnToStartPosition),DEBUGSTRING("CEnemyFly::ReturnToStartPosition")}, + {0x01370001, STATE_CEnemyBase_BeWounded, CEntity::pEventHandler(&CEnemyFly:: +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +BeWounded),DEBUGSTRING("CEnemyFly::BeWounded")}, + {0x01370002, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370002_BeWounded_01), DEBUGSTRING("CEnemyFly::H0x01370002_BeWounded_01")}, + {0x01370003, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370003_BeWounded_02), DEBUGSTRING("CEnemyFly::H0x01370003_BeWounded_02")}, + {0x01370004, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370004_BeWounded_03), DEBUGSTRING("CEnemyFly::H0x01370004_BeWounded_03")}, + {0x01370005, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370005_BeWounded_04), DEBUGSTRING("CEnemyFly::H0x01370005_BeWounded_04")}, + {0x01370006, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370006_BeWounded_05), DEBUGSTRING("CEnemyFly::H0x01370006_BeWounded_05")}, + {0x01370007, -1, CEntity::pEventHandler(&CEnemyFly:: +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +AirToGround),DEBUGSTRING("CEnemyFly::AirToGround")}, + {0x01370008, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370008_AirToGround_01), DEBUGSTRING("CEnemyFly::H0x01370008_AirToGround_01")}, + {0x01370009, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370009_AirToGround_02), DEBUGSTRING("CEnemyFly::H0x01370009_AirToGround_02")}, + {0x0137000a, -1, CEntity::pEventHandler(&CEnemyFly::H0x0137000a_AirToGround_03), DEBUGSTRING("CEnemyFly::H0x0137000a_AirToGround_03")}, + {0x0137000b, -1, CEntity::pEventHandler(&CEnemyFly::H0x0137000b_AirToGround_04), DEBUGSTRING("CEnemyFly::H0x0137000b_AirToGround_04")}, + {0x0137000c, -1, CEntity::pEventHandler(&CEnemyFly:: +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +GroundToAir),DEBUGSTRING("CEnemyFly::GroundToAir")}, + {0x0137000d, -1, CEntity::pEventHandler(&CEnemyFly::H0x0137000d_GroundToAir_01), DEBUGSTRING("CEnemyFly::H0x0137000d_GroundToAir_01")}, + {0x0137000e, -1, CEntity::pEventHandler(&CEnemyFly::H0x0137000e_GroundToAir_02), DEBUGSTRING("CEnemyFly::H0x0137000e_GroundToAir_02")}, + {0x0137000f, -1, CEntity::pEventHandler(&CEnemyFly::H0x0137000f_GroundToAir_03), DEBUGSTRING("CEnemyFly::H0x0137000f_GroundToAir_03")}, + {0x01370010, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370010_GroundToAir_04), DEBUGSTRING("CEnemyFly::H0x01370010_GroundToAir_04")}, + {0x01370011, STATE_CEnemyBase_AttackEnemy, CEntity::pEventHandler(&CEnemyFly:: +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +AttackEnemy),DEBUGSTRING("CEnemyFly::AttackEnemy")}, + {0x01370012, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370012_AttackEnemy_01), DEBUGSTRING("CEnemyFly::H0x01370012_AttackEnemy_01")}, + {0x01370013, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370013_AttackEnemy_02), DEBUGSTRING("CEnemyFly::H0x01370013_AttackEnemy_02")}, + {0x01370014, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370014_AttackEnemy_03), DEBUGSTRING("CEnemyFly::H0x01370014_AttackEnemy_03")}, + {0x01370015, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370015_AttackEnemy_04), DEBUGSTRING("CEnemyFly::H0x01370015_AttackEnemy_04")}, + {0x01370016, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370016_AttackEnemy_05), DEBUGSTRING("CEnemyFly::H0x01370016_AttackEnemy_05")}, + {0x01370017, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370017_AttackEnemy_06), DEBUGSTRING("CEnemyFly::H0x01370017_AttackEnemy_06")}, + {0x01370018, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370018_AttackEnemy_07), DEBUGSTRING("CEnemyFly::H0x01370018_AttackEnemy_07")}, + {0x01370019, -1, CEntity::pEventHandler(&CEnemyFly::H0x01370019_AttackEnemy_08), DEBUGSTRING("CEnemyFly::H0x01370019_AttackEnemy_08")}, + {0x0137001a, -1, CEntity::pEventHandler(&CEnemyFly::H0x0137001a_AttackEnemy_09), DEBUGSTRING("CEnemyFly::H0x0137001a_AttackEnemy_09")}, + {0x0137001b, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CEnemyFly:: +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Hit),DEBUGSTRING("CEnemyFly::Hit")}, + {0x0137001c, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CEnemyFly:: +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Fire),DEBUGSTRING("CEnemyFly::Fire")}, + {0x0137001d, STATE_CEnemyBase_Death, CEntity::pEventHandler(&CEnemyFly:: +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Death),DEBUGSTRING("CEnemyFly::Death")}, + {0x0137001e, STATE_CEnemyBase_MainLoop, CEntity::pEventHandler(&CEnemyFly:: +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +MainLoop),DEBUGSTRING("CEnemyFly::MainLoop")}, + {1, -1, CEntity::pEventHandler(&CEnemyFly:: +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +Main),DEBUGSTRING("CEnemyFly::Main")}, + {0x0137001f, -1, CEntity::pEventHandler(&CEnemyFly:: +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +GroundHit),DEBUGSTRING("CEnemyFly::GroundHit")}, + {0x01370020, -1, CEntity::pEventHandler(&CEnemyFly:: +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +GroundFire),DEBUGSTRING("CEnemyFly::GroundFire")}, + {0x01370021, -1, CEntity::pEventHandler(&CEnemyFly:: +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +FlyHit),DEBUGSTRING("CEnemyFly::FlyHit")}, + {0x01370022, -1, CEntity::pEventHandler(&CEnemyFly:: +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/EnemyFly.es" +FlyFire),DEBUGSTRING("CEnemyFly::FlyFire")}, +}; +#define CEnemyFly_handlersct ARRAYCOUNT(CEnemyFly_handlers) + +CEntity *CEnemyFly_New(void) { return new CEnemyFly; }; +void CEnemyFly_OnInitClass(void) {}; +void CEnemyFly_OnEndClass(void) {}; +void CEnemyFly_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEnemyFly_OnWorldEnd(CWorld *pwo) {}; +void CEnemyFly_OnWorldInit(CWorld *pwo) {}; +void CEnemyFly_OnWorldTick(CWorld *pwo) {}; +void CEnemyFly_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEnemyFly, CEnemyBase, "Enemy Fly", "", 0x00000137); +DECLARE_CTFILENAME(_fnmCEnemyFly_tbn, ""); diff --git a/Sources/EntitiesMP/EnemyMarker.cpp b/Sources/EntitiesMP/EnemyMarker.cpp new file mode 100644 index 0000000..93533d6 --- /dev/null +++ b/Sources/EntitiesMP/EnemyMarker.cpp @@ -0,0 +1,88 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" + +#include "StdH.h" + +#include +#include +void CEnemyMarker::SetDefaultProperties(void) { + m_fWaitTime = 0.0f; + m_fMarkerRange = 0.0f; + m_fPatrolAreaInner = 0.0f; + m_fPatrolAreaOuter = 0.0f; + m_fPatrolTime = 0.0f; + m_betRunToMarker = BET_IGNORE ; + m_betFly = BET_IGNORE ; + m_betBlind = BET_IGNORE ; + m_betDeaf = BET_IGNORE ; + m_bStartTactics = FALSE ; + CMarker::SetDefaultProperties(); +} + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +BOOL CEnemyMarker::MovesByTargetedRoute(CTString & strTargetProperty)const { +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +strTargetProperty = "Target"; +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +return TRUE ; +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +} + +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +BOOL CEnemyMarker::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +fnmMarkerClass = CTFILENAME ("Classes\\EnemyMarker.ecl"); +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +strTargetProperty = "Target"; +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +return TRUE ; +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +} + +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +BOOL CEnemyMarker::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +{ +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +if(slPropertyOffset == offsetof (CMarker , m_penTarget )) +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +{ +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +if(IsOfClass (penTarget , "Enemy Marker")){return TRUE ;} +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +else {return FALSE ;} +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +} +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +return CEntity :: IsTargetValid (slPropertyOffset , penTarget ); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +} +BOOL CEnemyMarker:: +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +InitAsEditorModel (); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +if(m_strName == "Marker"){ +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +m_strName = "Enemy Marker"; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +} +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +SetModel (MODEL_MARKER ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EnemyMarker.es b/Sources/EntitiesMP/EnemyMarker.es new file mode 100644 index 0000000..81ed961 --- /dev/null +++ b/Sources/EntitiesMP/EnemyMarker.es @@ -0,0 +1,72 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +302 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; + +class CEnemyMarker: CMarker { +name "Enemy Marker"; +thumbnail "Thumbnails\\EnemyMarker.tbn"; + +properties: + 1 FLOAT m_fWaitTime = 0.0f, // time to wait(or do anything) until go to another marker + 3 RANGE m_fMarkerRange "Marker Range" 'M' = 0.0f, // range around marker (marker doesn't have to be hit directly) + + 11 RANGE m_fPatrolAreaInner "Patrol Area Inner" 'R' = 0.0f, // patrol area inner circle + 12 RANGE m_fPatrolAreaOuter "Patrol Area Outer" 'E' = 0.0f, // patrol area outer circle + 13 FLOAT m_fPatrolTime "Patrol Time" 'P' = 0.0f, // time to patrol around + 14 enum BoolEType m_betRunToMarker "Run to marker" 'O' = BET_IGNORE, // run to marker + 15 enum BoolEType m_betFly "Fly" 'F' = BET_IGNORE, // fly if you can + 16 enum BoolEType m_betBlind "Blind" 'B' = BET_IGNORE, + 17 enum BoolEType m_betDeaf "Deaf" 'D' = BET_IGNORE, + + 18 BOOL m_bStartTactics "Start Tactics" = FALSE, + +components: + 1 model MODEL_MARKER "Models\\Editor\\EnemyMarker.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\EnemyMarker.tex" + +functions: + /* Check if entity is moved on a route set up by its targets. */ + BOOL MovesByTargetedRoute(CTString &strTargetProperty) const { + strTargetProperty = "Target"; + return TRUE; + }; + + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\EnemyMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if( slPropertyOffset == offsetof(CMarker, m_penTarget)) + { + if (IsOfClass(penTarget, "Enemy Marker")) { return TRUE; } + else { return FALSE; } + } + return CEntity::IsTargetValid(slPropertyOffset, penTarget); + } + +procedures: + Main() { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + if (m_strName=="Marker") { + m_strName="Enemy Marker"; + } + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + return; + } +}; + diff --git a/Sources/EntitiesMP/EnemyMarker.h b/Sources/EntitiesMP/EnemyMarker.h new file mode 100644 index 0000000..a62b174 --- /dev/null +++ b/Sources/EntitiesMP/EnemyMarker.h @@ -0,0 +1,36 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_EnemyMarker_INCLUDED +#define _EntitiesMP_EnemyMarker_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CEnemyMarker_DLLClass; +class CEnemyMarker : public CMarker { +public: + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fWaitTime; + RANGE m_fMarkerRange; + RANGE m_fPatrolAreaInner; + RANGE m_fPatrolAreaOuter; + FLOAT m_fPatrolTime; + enum BoolEType m_betRunToMarker; + enum BoolEType m_betFly; + enum BoolEType m_betBlind; + enum BoolEType m_betDeaf; + BOOL m_bStartTactics; + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); +#define STATE_CEnemyMarker_Main 1 + BOOL +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_EnemyMarker_INCLUDED diff --git a/Sources/EntitiesMP/EnemyMarker_tables.h b/Sources/EntitiesMP/EnemyMarker_tables.h new file mode 100644 index 0000000..3c05117 --- /dev/null +++ b/Sources/EntitiesMP/EnemyMarker_tables.h @@ -0,0 +1,45 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CEnemyMarker + +CEntityProperty CEnemyMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000012e<<8)+1, offsetof(CEnemyMarker, m_fWaitTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x0000012e<<8)+3, offsetof(CEnemyMarker, m_fMarkerRange), "Marker Range", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x0000012e<<8)+11, offsetof(CEnemyMarker, m_fPatrolAreaInner), "Patrol Area Inner", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x0000012e<<8)+12, offsetof(CEnemyMarker, m_fPatrolAreaOuter), "Patrol Area Outer", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000012e<<8)+13, offsetof(CEnemyMarker, m_fPatrolTime), "Patrol Time", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &BoolEType_enum, (0x0000012e<<8)+14, offsetof(CEnemyMarker, m_betRunToMarker), "Run to marker", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &BoolEType_enum, (0x0000012e<<8)+15, offsetof(CEnemyMarker, m_betFly), "Fly", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &BoolEType_enum, (0x0000012e<<8)+16, offsetof(CEnemyMarker, m_betBlind), "Blind", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &BoolEType_enum, (0x0000012e<<8)+17, offsetof(CEnemyMarker, m_betDeaf), "Deaf", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000012e<<8)+18, offsetof(CEnemyMarker, m_bStartTactics), "Start Tactics", 0, 0x7F0000FFUL, 0), +}; +#define CEnemyMarker_propertiesct ARRAYCOUNT(CEnemyMarker_properties) + +CEntityComponent CEnemyMarker_components[] = { +#define MODEL_MARKER ((0x0000012e<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\EnemyMarker.mdl"), +#define TEXTURE_MARKER ((0x0000012e<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\EnemyMarker.tex"), +}; +#define CEnemyMarker_componentsct ARRAYCOUNT(CEnemyMarker_components) + +CEventHandlerEntry CEnemyMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CEnemyMarker:: +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/EnemyMarker.es" +Main),DEBUGSTRING("CEnemyMarker::Main")}, +}; +#define CEnemyMarker_handlersct ARRAYCOUNT(CEnemyMarker_handlers) + +CEntity *CEnemyMarker_New(void) { return new CEnemyMarker; }; +void CEnemyMarker_OnInitClass(void) {}; +void CEnemyMarker_OnEndClass(void) {}; +void CEnemyMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEnemyMarker_OnWorldEnd(CWorld *pwo) {}; +void CEnemyMarker_OnWorldInit(CWorld *pwo) {}; +void CEnemyMarker_OnWorldTick(CWorld *pwo) {}; +void CEnemyMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEnemyMarker, CMarker, "Enemy Marker", "Thumbnails\\EnemyMarker.tbn", 0x0000012e); +DECLARE_CTFILENAME(_fnmCEnemyMarker_tbn, "Thumbnails\\EnemyMarker.tbn"); diff --git a/Sources/EntitiesMP/EnemyRunInto.cpp b/Sources/EntitiesMP/EnemyRunInto.cpp new file mode 100644 index 0000000..bc0973c --- /dev/null +++ b/Sources/EntitiesMP/EnemyRunInto.cpp @@ -0,0 +1,359 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" + +#include "StdH.h" + +#include +#include +void CEnemyRunInto::SetDefaultProperties(void) { + m_penLastTouched = NULL; + m_fLastTouchedTime = 0.0f; + m_bWhileLoop = FALSE ; + m_fMassKicked = 0.0f; + m_fInertionRunTime = 1.3f; + m_fStopApproachDistance = 6.75f; + m_fChargeDistance = 15.0f; + m_bUseChargeAnimation = FALSE ; + m_fAttackRotateRunInto = 1.0f; + CEnemyBase::SetDefaultProperties(); +} + void CEnemyRunInto::AdjustDifficulty(void) +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +{ +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +FLOAT fMoveSpeed = GetSP () -> sp_fEnemyMovementSpeed ; +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_fAttackRotateRunInto *= fMoveSpeed ; +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +CEnemyBase :: AdjustDifficulty (); +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +void CEnemyRunInto::IncreaseKickedMass(CEntity * pen) { +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +EntityInfo * peiTarget = (EntityInfo *) (pen -> GetEntityInfo ()); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(peiTarget != NULL ){ +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_fMassKicked += peiTarget -> fMass ; +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} + void CEnemyRunInto::LiveEntityTouched(ETouch etouch) {} + BOOL CEnemyRunInto::HigherMass(void) {return FALSE ;} + void CEnemyRunInto::ChargeAnim(void) {} +BOOL CEnemyRunInto:: +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyRunInto_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyRunInto::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_fMassKicked = 0.0f; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_penLastTouched = NULL ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Jump(STATE_CURRENT, STATE_CEnemyRunInto_RotateToEnemy, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyRunInto:: +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +RotateToEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyRunInto_RotateToEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyRunInto::RotateToEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(! (m_penEnemy -> GetFlags () & ENF_ALIVE ) || m_penEnemy -> GetFlags () & ENF_DELETED ){ +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +SetTargetNone (); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Return(STATE_CURRENT,EReturn ()); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_bWhileLoop = TRUE ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Jump(STATE_CURRENT,0x01380004, FALSE, EInternal());return TRUE;}BOOL CEnemyRunInto::H0x01380004_RotateToEnemy_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01380004 +if(!(m_penEnemy != NULL && m_bWhileLoop )){ Jump(STATE_CURRENT,0x01380005, FALSE, EInternal());return TRUE;} +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_fMoveFrequency = 0.1f; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +SetTimerAfter(m_fMoveFrequency ); +Jump(STATE_CURRENT, 0x01380002, FALSE, EBegin());return TRUE;}BOOL CEnemyRunInto::H0x01380002_RotateToEnemy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01380002 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_vDesiredPosition = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(! IsInPlaneFrustum (m_penEnemy , CosFast (15.0f))){ +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_aRotateSpeed = m_fAttackRotateRunInto ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_fMoveSpeed = 0.0f; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +ULONG ulFlags = SetDesiredMovement (); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +MovementAnimation (ulFlags ); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}else { +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_aRotateSpeed = 0.0f; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_fMoveSpeed = 0.0f; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_bWhileLoop = FALSE ; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}ASSERT(FALSE);break;case(EVENTCODE_ESound):{const ESound&e= (ESound&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EWatch):{const EWatch&e= (EWatch&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01380003, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}return TRUE;}BOOL CEnemyRunInto::H0x01380003_RotateToEnemy_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01380003 +Jump(STATE_CURRENT,0x01380004, FALSE, EInternal());return TRUE; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}BOOL CEnemyRunInto::H0x01380005_RotateToEnemy_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01380005 + +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Jump(STATE_CURRENT, STATE_CEnemyRunInto_RunIntoEnemy, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyRunInto:: +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +RunIntoEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyRunInto_RunIntoEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyRunInto::RunIntoEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(! (m_penEnemy -> GetFlags () & ENF_ALIVE ) || m_penEnemy -> GetFlags () & ENF_DELETED ){ +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +SetTargetNone (); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Return(STATE_CURRENT,EReturn ()); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_bWhileLoop = TRUE ; +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Jump(STATE_CURRENT,0x01380009, FALSE, EInternal());return TRUE;}BOOL CEnemyRunInto::H0x01380009_RunIntoEnemy_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01380009 +if(!(m_penEnemy != NULL && m_bWhileLoop )){ Jump(STATE_CURRENT,0x0138000a, FALSE, EInternal());return TRUE;} +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_fMoveFrequency = 0.1f; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +SetTimerAfter(m_fMoveFrequency ); +Jump(STATE_CURRENT, 0x01380007, FALSE, EBegin());return TRUE;}BOOL CEnemyRunInto::H0x01380007_RunIntoEnemy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01380007 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(! SeeEntity (m_penEnemy , CosFast (90.0f)) || CalcDist (m_penEnemy ) < m_fStopApproachDistance ){ +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_bWhileLoop = FALSE ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +UnsetTimer();Jump(STATE_CURRENT,0x01380008, FALSE, EInternal());return TRUE; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_fMoveSpeed = m_fAttackRunSpeed ; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_aRotateSpeed = m_fAttackRotateRunInto ; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_vDesiredPosition = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +SetDesiredMovement (); +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(m_bUseChargeAnimation && CalcDist (m_penEnemy ) < m_fChargeDistance ){ +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +ChargeAnim (); +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}else { +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +RunningAnim (); +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +AddToFuss (); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(etouch . penOther -> GetFlags () & ENF_ALIVE ){ +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +LiveEntityTouched (etouch ); +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(HigherMass ()){ +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_penLastTouched = NULL ; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Return(STATE_CURRENT,EReturn ()); +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(etouch . penOther == m_penEnemy ){ +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_bWhileLoop = FALSE ; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +UnsetTimer();Jump(STATE_CURRENT,0x01380008, FALSE, EInternal());return TRUE; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}else if(! (etouch . penOther -> GetPhysicsFlags () & EPF_MOVABLE ) && +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +(FLOAT3D (etouch . plCollision ) % - en_vGravityDir ) < CosFast (50.0f)){ +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_penLastTouched = NULL ; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Return(STATE_CURRENT,EReturn ()); +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01380008, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +return FALSE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}return TRUE;}BOOL CEnemyRunInto::H0x01380008_RunIntoEnemy_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01380008 +Jump(STATE_CURRENT,0x01380009, FALSE, EInternal());return TRUE; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}BOOL CEnemyRunInto::H0x0138000a_RunIntoEnemy_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0138000a + +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Jump(STATE_CURRENT, STATE_CEnemyRunInto_RunAwayFromEnemy, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyRunInto:: +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +RunAwayFromEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyRunInto_RunAwayFromEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyRunInto::RunAwayFromEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(! (m_penEnemy -> GetFlags () & ENF_ALIVE ) || m_penEnemy -> GetFlags () & ENF_DELETED ){ +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +SetTargetNone (); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Return(STATE_CURRENT,EReturn ()); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +StopRotating (); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +SetTimerAfter(m_fInertionRunTime ); +Jump(STATE_CURRENT, 0x0138000c, FALSE, EBegin());return TRUE;}BOOL CEnemyRunInto::H0x0138000c_RunAwayFromEnemy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0138000c +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(etouch . penOther -> GetFlags () & ENF_ALIVE ){ +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +LiveEntityTouched (etouch ); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +if(HigherMass ()){ +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_penLastTouched = NULL ; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Return(STATE_CURRENT,EReturn ()); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}else if(! (etouch . penOther -> GetPhysicsFlags () & EPF_MOVABLE ) && +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +(FLOAT3D (etouch . plCollision ) % - en_vGravityDir ) < CosFast (50.0f)){ +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_penLastTouched = NULL ; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Return(STATE_CURRENT,EReturn ()); +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +} +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x0138000d, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +return FALSE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +}return TRUE;}BOOL CEnemyRunInto::H0x0138000d_RunAwayFromEnemy_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0138000d + +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +m_penLastTouched = NULL ; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +STATE_CEnemyRunInto_PostRunAwayFromEnemy, TRUE; +Jump(STATE_CURRENT, 0x0138000e, FALSE, EBegin());return TRUE;}BOOL CEnemyRunInto::H0x0138000e_RunAwayFromEnemy_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0138000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyRunInto_PostRunAwayFromEnemy, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0138000f, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemyRunInto::H0x0138000f_RunAwayFromEnemy_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0138000f +const EReturn&__e= (EReturn&)__eeInput; +; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Return(STATE_CURRENT,EReturn ()); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyRunInto:: +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +PostRunAwayFromEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyRunInto_PostRunAwayFromEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyRunInto::PostRunAwayFromEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Return(STATE_CURRENT,EReturn ()); +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyRunInto:: +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +MainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyRunInto_MainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyRunInto::MainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemyRunInto:: +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemyRunInto_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemyRunInto::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Return(STATE_CURRENT,EVoid()); +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EnemyRunInto.es b/Sources/EntitiesMP/EnemyRunInto.es new file mode 100644 index 0000000..0fada69 --- /dev/null +++ b/Sources/EntitiesMP/EnemyRunInto.es @@ -0,0 +1,295 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +312 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/EnemyBase"; + + +class export CEnemyRunInto : CEnemyBase { +name "Enemy Run Into"; +thumbnail ""; + +properties: + 1 CEntityPointer m_penLastTouched, // last touched live entity + 2 FLOAT m_fLastTouchedTime = 0.0f, // last touched live entity time + 3 BOOL m_bWhileLoop = FALSE, // internal for loops + 5 FLOAT m_fMassKicked = 0.0f, // total mass kicked in one attack + 7 FLOAT m_fInertionRunTime = 1.3f, // time to run before turning due to inertion + 8 FLOAT m_fStopApproachDistance = 6.75f, // at which distamce to start runnin away from enemy + 9 FLOAT m_fChargeDistance = 15.0f, // at which distance to prepare for charge + 10 BOOL m_bUseChargeAnimation = FALSE, // does this monster use charging animation? + // moving properties - CAN BE SET + 20 ANGLE m_fAttackRotateRunInto = 1.0f, // attack rotate speed before run into enemy + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + +functions: + virtual void AdjustDifficulty(void) + { + FLOAT fMoveSpeed = GetSP()->sp_fEnemyMovementSpeed; + m_fAttackRotateRunInto *= fMoveSpeed; + + CEnemyBase::AdjustDifficulty(); + } +/************************************************************ + * ATTACK SPECIFIC * + ************************************************************/ + void IncreaseKickedMass(CEntity *pen) { + EntityInfo *peiTarget = (EntityInfo*) (pen->GetEntityInfo()); + if (peiTarget!=NULL) { + m_fMassKicked += peiTarget->fMass; + } + }; + + + + +/************************************************************ + * VIRTUAL ATTACK FUNCTIONS THAT NEED OVERRIDE * + ************************************************************/ + // touched another live entity + virtual void LiveEntityTouched(ETouch etouch) {}; + // touched entity with higher mass + virtual BOOL HigherMass(void) { return FALSE; } + virtual void ChargeAnim(void) {}; + + +procedures: +/************************************************************ + * ATTACK ENEMY PROCEDURES * + ************************************************************/ + // attack range -> fire and move toward enemy + Fire() : CEnemyBase::Fire { + m_fMassKicked = 0.0f; + m_penLastTouched = NULL; + + jump RotateToEnemy(); + }; + + + RotateToEnemy() { + // if the enemy not alive or deleted + if (!(m_penEnemy->GetFlags()&ENF_ALIVE) || m_penEnemy->GetFlags()&ENF_DELETED) { + SetTargetNone(); + return EReturn(); + } + + // rotate to enemy + m_bWhileLoop = TRUE; + while (m_penEnemy!=NULL && m_bWhileLoop) { + m_fMoveFrequency = 0.1f; + wait(m_fMoveFrequency) { + // attack target + on (EBegin) : { + m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector; + // rotate to enemy + if (!IsInPlaneFrustum(m_penEnemy, CosFast(15.0f))) { + m_aRotateSpeed = m_fAttackRotateRunInto; + m_fMoveSpeed = 0.0f; + // adjust direction and speed + ULONG ulFlags = SetDesiredMovement(); + MovementAnimation(ulFlags); + } else { + m_aRotateSpeed = 0.0f; + m_fMoveSpeed = 0.0f; + m_bWhileLoop = FALSE; + } + resume; + } + on (ESound) : { resume; } // ignore all sounds + on (EWatch) : { resume; } // ignore watch + on (ETimer) : { stop; } // timer tick expire + } + } + + jump RunIntoEnemy(); + }; + + +/* WalkToEnemy() { + // if the enemy not alive or deleted + if (!(m_penEnemy->GetFlags()&ENF_ALIVE) || m_penEnemy->GetFlags()&ENF_DELETED) { + SetTargetNone(); + return EReturn(); + } + + // walk to enemy if can't be seen + while (!CanAttackEnemy(m_penEnemy, CosFast(30.0f))) { + m_fMoveFrequency = 0.1f; + wait(m_fMoveFrequency) { + // move to target + on (EBegin) : { + m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector; + m_fMoveSpeed = m_fWalkSpeed; + m_aRotateSpeed = m_aWalkRotateSpeed; + // adjust direction and speed + ULONG ulFlags = SetDesiredMovement(); + MovementAnimation(ulFlags); + } + on (ESound) : { resume; } // ignore all sounds + on (EWatch) : { resume; } // ignore watch + on (ETimer) : { stop; } // timer tick expire + } + } + + jump StartRunIntoEnemy(); + }; + + StartRunIntoEnemy() { + // if the enemy not alive or deleted + if (!(m_penEnemy->GetFlags()&ENF_ALIVE) || m_penEnemy->GetFlags()&ENF_DELETED) { + SetTargetNone(); + return EReturn(); + } + + // run to enemy + m_bWhileLoop = TRUE; + m_fMoveFrequency = 0.5f; + wait(m_fMoveFrequency) { + on (EBegin) : { + // if enemy can't be seen stop running + if (!SeeEntity(m_penEnemy, CosFast(90.0f))) { + m_bWhileLoop = FALSE; + stop; + } + m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector; + // move to enemy + m_fMoveSpeed = m_fAttackRunSpeed; + m_aRotateSpeed = m_aAttackRotateSpeed; + // adjust direction and speed + SetDesiredMovement(); + RunningAnim(); + resume; + } + on (ETouch) : { resume; } + on (ETimer) : { stop; } // timer tick expire + } + + jump RunIntoEnemy(); + }; + */ + + RunIntoEnemy() { + // if the enemy not alive or deleted + if (!(m_penEnemy->GetFlags()&ENF_ALIVE) || m_penEnemy->GetFlags()&ENF_DELETED) { + SetTargetNone(); + return EReturn(); + } + + // run to enemy + m_bWhileLoop = TRUE; + while(m_penEnemy!=NULL && m_bWhileLoop) { + m_fMoveFrequency = 0.1f; + wait(m_fMoveFrequency) { + on (EBegin) : { + // if enemy can't be seen, or too close + if (!SeeEntity(m_penEnemy, CosFast(90.0f)) || CalcDist(m_penEnemy)GetPlacement().pl_PositionVector; + SetDesiredMovement(); + if (m_bUseChargeAnimation && CalcDist(m_penEnemy)GetFlags()&ENF_ALIVE) { + // react to hitting it + LiveEntityTouched(etouch); + // if hit something bigger than us + if (HigherMass()) { + // stop attack + m_penLastTouched = NULL; + return EReturn(); + } + // if hit the enemy + if (etouch.penOther==m_penEnemy) { + // continue past it + m_bWhileLoop = FALSE; + stop; + } + // if hit wall + } else if (!(etouch.penOther->GetPhysicsFlags()&EPF_MOVABLE) && + (FLOAT3D(etouch.plCollision)% -en_vGravityDir)GetFlags()&ENF_ALIVE) || m_penEnemy->GetFlags()&ENF_DELETED) { + SetTargetNone(); + return EReturn(); + } + + // run in direction due to inertion before turning + StopRotating(); + wait(m_fInertionRunTime) { + on (EBegin) : { resume; } + on (ETouch etouch) : { + // live entity touched + if (etouch.penOther->GetFlags()&ENF_ALIVE) { + LiveEntityTouched(etouch); + // stop moving on higher mass + if (HigherMass()) { + m_penLastTouched = NULL; + return EReturn(); + } + // stop go away from enemy + } else if (!(etouch.penOther->GetPhysicsFlags()&EPF_MOVABLE) && + (FLOAT3D(etouch.plCollision)% -en_vGravityDir) +extern "C" DECL_DLL CDLLEntityClass CEnemyRunInto_DLLClass; +class DECL_DLL CEnemyRunInto : public CEnemyBase { +public: + virtual void SetDefaultProperties(void); + CEntityPointer m_penLastTouched; + FLOAT m_fLastTouchedTime; + BOOL m_bWhileLoop; + FLOAT m_fMassKicked; + FLOAT m_fInertionRunTime; + FLOAT m_fStopApproachDistance; + FLOAT m_fChargeDistance; + BOOL m_bUseChargeAnimation; + ANGLE m_fAttackRotateRunInto; + +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +virtual void AdjustDifficulty(void); + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +void IncreaseKickedMass(CEntity * pen); + +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +virtual void LiveEntityTouched(ETouch etouch); + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +virtual BOOL HigherMass(void); + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +virtual void ChargeAnim(void); +#define STATE_CEnemyRunInto_Fire 0x01380000 + BOOL +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Fire(const CEntityEvent &__eeInput); +#define STATE_CEnemyRunInto_RotateToEnemy 0x01380001 + BOOL +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +RotateToEnemy(const CEntityEvent &__eeInput); + BOOL H0x01380002_RotateToEnemy_01(const CEntityEvent &__eeInput); + BOOL H0x01380003_RotateToEnemy_02(const CEntityEvent &__eeInput); + BOOL H0x01380004_RotateToEnemy_03(const CEntityEvent &__eeInput); + BOOL H0x01380005_RotateToEnemy_04(const CEntityEvent &__eeInput); +#define STATE_CEnemyRunInto_RunIntoEnemy 0x01380006 + BOOL +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +RunIntoEnemy(const CEntityEvent &__eeInput); + BOOL H0x01380007_RunIntoEnemy_01(const CEntityEvent &__eeInput); + BOOL H0x01380008_RunIntoEnemy_02(const CEntityEvent &__eeInput); + BOOL H0x01380009_RunIntoEnemy_03(const CEntityEvent &__eeInput); + BOOL H0x0138000a_RunIntoEnemy_04(const CEntityEvent &__eeInput); +#define STATE_CEnemyRunInto_RunAwayFromEnemy 0x0138000b + BOOL +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +RunAwayFromEnemy(const CEntityEvent &__eeInput); + BOOL H0x0138000c_RunAwayFromEnemy_01(const CEntityEvent &__eeInput); + BOOL H0x0138000d_RunAwayFromEnemy_02(const CEntityEvent &__eeInput); + BOOL H0x0138000e_RunAwayFromEnemy_03(const CEntityEvent &__eeInput); + BOOL H0x0138000f_RunAwayFromEnemy_04(const CEntityEvent &__eeInput); +#define STATE_CEnemyRunInto_PostRunAwayFromEnemy 0x01380010 + BOOL +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +PostRunAwayFromEnemy(const CEntityEvent &__eeInput); +#define STATE_CEnemyRunInto_MainLoop 0x01380011 + BOOL +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +MainLoop(const CEntityEvent &__eeInput); +#define STATE_CEnemyRunInto_Main 1 + BOOL +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_EnemyRunInto_INCLUDED diff --git a/Sources/EntitiesMP/EnemyRunInto_tables.h b/Sources/EntitiesMP/EnemyRunInto_tables.h new file mode 100644 index 0000000..2f51905 --- /dev/null +++ b/Sources/EntitiesMP/EnemyRunInto_tables.h @@ -0,0 +1,72 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CEnemyRunInto + +CEntityProperty CEnemyRunInto_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000138<<8)+1, offsetof(CEnemyRunInto, m_penLastTouched), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000138<<8)+2, offsetof(CEnemyRunInto, m_fLastTouchedTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000138<<8)+3, offsetof(CEnemyRunInto, m_bWhileLoop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000138<<8)+5, offsetof(CEnemyRunInto, m_fMassKicked), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000138<<8)+7, offsetof(CEnemyRunInto, m_fInertionRunTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000138<<8)+8, offsetof(CEnemyRunInto, m_fStopApproachDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000138<<8)+9, offsetof(CEnemyRunInto, m_fChargeDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000138<<8)+10, offsetof(CEnemyRunInto, m_bUseChargeAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000138<<8)+20, offsetof(CEnemyRunInto, m_fAttackRotateRunInto), "", 0, 0, 0), +}; +#define CEnemyRunInto_propertiesct ARRAYCOUNT(CEnemyRunInto_properties) + +CEntityComponent CEnemyRunInto_components[] = { +#define CLASS_BASE ((0x00000138<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +}; +#define CEnemyRunInto_componentsct ARRAYCOUNT(CEnemyRunInto_components) + +CEventHandlerEntry CEnemyRunInto_handlers[] = { + {0x01380000, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CEnemyRunInto:: +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Fire),DEBUGSTRING("CEnemyRunInto::Fire")}, + {0x01380001, -1, CEntity::pEventHandler(&CEnemyRunInto:: +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +RotateToEnemy),DEBUGSTRING("CEnemyRunInto::RotateToEnemy")}, + {0x01380002, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x01380002_RotateToEnemy_01), DEBUGSTRING("CEnemyRunInto::H0x01380002_RotateToEnemy_01")}, + {0x01380003, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x01380003_RotateToEnemy_02), DEBUGSTRING("CEnemyRunInto::H0x01380003_RotateToEnemy_02")}, + {0x01380004, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x01380004_RotateToEnemy_03), DEBUGSTRING("CEnemyRunInto::H0x01380004_RotateToEnemy_03")}, + {0x01380005, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x01380005_RotateToEnemy_04), DEBUGSTRING("CEnemyRunInto::H0x01380005_RotateToEnemy_04")}, + {0x01380006, -1, CEntity::pEventHandler(&CEnemyRunInto:: +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +RunIntoEnemy),DEBUGSTRING("CEnemyRunInto::RunIntoEnemy")}, + {0x01380007, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x01380007_RunIntoEnemy_01), DEBUGSTRING("CEnemyRunInto::H0x01380007_RunIntoEnemy_01")}, + {0x01380008, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x01380008_RunIntoEnemy_02), DEBUGSTRING("CEnemyRunInto::H0x01380008_RunIntoEnemy_02")}, + {0x01380009, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x01380009_RunIntoEnemy_03), DEBUGSTRING("CEnemyRunInto::H0x01380009_RunIntoEnemy_03")}, + {0x0138000a, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x0138000a_RunIntoEnemy_04), DEBUGSTRING("CEnemyRunInto::H0x0138000a_RunIntoEnemy_04")}, + {0x0138000b, -1, CEntity::pEventHandler(&CEnemyRunInto:: +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +RunAwayFromEnemy),DEBUGSTRING("CEnemyRunInto::RunAwayFromEnemy")}, + {0x0138000c, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x0138000c_RunAwayFromEnemy_01), DEBUGSTRING("CEnemyRunInto::H0x0138000c_RunAwayFromEnemy_01")}, + {0x0138000d, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x0138000d_RunAwayFromEnemy_02), DEBUGSTRING("CEnemyRunInto::H0x0138000d_RunAwayFromEnemy_02")}, + {0x0138000e, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x0138000e_RunAwayFromEnemy_03), DEBUGSTRING("CEnemyRunInto::H0x0138000e_RunAwayFromEnemy_03")}, + {0x0138000f, -1, CEntity::pEventHandler(&CEnemyRunInto::H0x0138000f_RunAwayFromEnemy_04), DEBUGSTRING("CEnemyRunInto::H0x0138000f_RunAwayFromEnemy_04")}, + {0x01380010, -1, CEntity::pEventHandler(&CEnemyRunInto:: +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +PostRunAwayFromEnemy),DEBUGSTRING("CEnemyRunInto::PostRunAwayFromEnemy")}, + {0x01380011, STATE_CEnemyBase_MainLoop, CEntity::pEventHandler(&CEnemyRunInto:: +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +MainLoop),DEBUGSTRING("CEnemyRunInto::MainLoop")}, + {1, -1, CEntity::pEventHandler(&CEnemyRunInto:: +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/EnemyRunInto.es" +Main),DEBUGSTRING("CEnemyRunInto::Main")}, +}; +#define CEnemyRunInto_handlersct ARRAYCOUNT(CEnemyRunInto_handlers) + +CEntity *CEnemyRunInto_New(void) { return new CEnemyRunInto; }; +void CEnemyRunInto_OnInitClass(void) {}; +void CEnemyRunInto_OnEndClass(void) {}; +void CEnemyRunInto_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEnemyRunInto_OnWorldEnd(CWorld *pwo) {}; +void CEnemyRunInto_OnWorldInit(CWorld *pwo) {}; +void CEnemyRunInto_OnWorldTick(CWorld *pwo) {}; +void CEnemyRunInto_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEnemyRunInto, CEnemyBase, "Enemy Run Into", "", 0x00000138); +DECLARE_CTFILENAME(_fnmCEnemyRunInto_tbn, ""); diff --git a/Sources/EntitiesMP/EnemySpawner.cpp b/Sources/EntitiesMP/EnemySpawner.cpp new file mode 100644 index 0000000..abccdd7 --- /dev/null +++ b/Sources/EntitiesMP/EnemySpawner.cpp @@ -0,0 +1,917 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" + +#include "StdH.h" + +#include +#include +void CEnemySpawner::SetDefaultProperties(void) { + m_penTarget = NULL; + m_strDescription = ""; + m_strName = "Enemy spawner"; + m_fInnerCircle = 0.0f; + m_fOuterCircle = 0.0f; + m_tmDelay = 0.0f; + m_tmSingleWait = 0.1f; + m_tmGroupWait = 0.1f; + m_ctGroupSize = 1; + m_ctTotal = 1; + m_penPatrol = NULL; + m_estType = EST_SIMPLE ; + m_bTelefrag = FALSE ; + m_bSpawnEffect = TRUE ; + m_bDoubleInSerious = FALSE ; + m_penSeriousTarget = NULL; + m_bFirstPass = TRUE ; + m_soSpawn.SetOwner(this); +m_soSpawn.Stop_internal(); + m_iInGroup = 0; + m_iEnemiesTriggered = 0; + m_penTacticsHolder = NULL; + m_bTacticsAutostart = TRUE ; + CRationalEntity::SetDefaultProperties(); +} + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +void CEnemySpawner::Precache(void) +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_TELEPORT ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} + +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +const CTString & CEnemySpawner::GetDescription(void)const +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_penTarget != NULL ){ +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , m_penTarget -> GetName ()); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_penSeriousTarget != NULL ){ +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +((CTString &) m_strDescription ) . PrintF ("->%s, %s" , +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_penTarget -> GetName () , m_penSeriousTarget -> GetName ()); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +((CTString &) m_strDescription ) = EnemySpawnerType_enum . NameForValue (INDEX (m_estType )) +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" ++ m_strDescription ; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return m_strDescription ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} + +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +BOOL CEnemySpawner::CheckTemplateValid(CEntity * pen) +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(pen == NULL || ! IsDerivedFromClass (pen , "Enemy Base")){ +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return FALSE ; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_estType == EST_TELEPORTER ){ +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return ! (((CEnemyBase &) * pen ) . m_bTemplate ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}else { +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return ((CEnemyBase &) * pen ) . m_bTemplate ; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} + +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +BOOL CEnemySpawner::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(slPropertyOffset == offsetof (CEnemySpawner , m_penTarget )) +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return CheckTemplateValid (penTarget ); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +else if(slPropertyOffset == offsetof (CEnemySpawner , m_penPatrol )) +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return (penTarget != NULL && IsDerivedFromClass (penTarget , "Enemy Marker")); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +else if(slPropertyOffset == offsetof (CEnemySpawner , m_penSeriousTarget )) +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return CheckTemplateValid (penTarget ); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +else if(slPropertyOffset == offsetof (CEnemySpawner , m_penTacticsHolder )) +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(IsOfClass (penTarget , "TacticsHolder")){return TRUE ;} +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +else {return FALSE ;} +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return CEntity :: IsTargetValid (slPropertyOffset , penTarget ); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +BOOL CEnemySpawner::FillEntityStatistics(EntityStats * pes) +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_penTarget == NULL ){return FALSE ;} +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_penTarget -> FillEntityStatistics (pes ); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +pes -> es_ctCount = m_ctTotal ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +pes -> es_strName += " (spawned)"; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_penSeriousTarget != NULL ){ +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +pes -> es_strName += " (has serious)"; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return TRUE ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} + +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +void CEnemySpawner::SpawnEntity(BOOL bCopy) { +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(CheckTemplateValid (m_penTarget )){ +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +CEntity * pen = NULL ; +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(bCopy ){ +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +pen = GetWorld () -> CopyEntityInWorld (* m_penTarget , +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +CPlacement3D (FLOAT3D (- 32000.0f + FRnd () * 200.0f , - 32000.0f + FRnd () * 200.0f , 0) , ANGLE3D (0 , 0 , 0))); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +pen -> End (); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +CEnemyBase * peb = ((CEnemyBase *) pen ); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +peb -> m_bTemplate = FALSE ; +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_estType == EST_RESPAWNER +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +|| m_estType == EST_MAINTAINGROUP || m_estType == EST_RESPAWNGROUP ){ +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +peb -> m_penSpawnerTarget = this ; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_penPatrol != NULL ){ +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +peb -> m_penMarker = m_penPatrol ; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +pen -> Initialize (); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}else { +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +pen = m_penTarget ; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_penTarget = NULL ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +FLOAT fEntityR = 0; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(pen -> en_pciCollisionInfo != NULL ){ +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +fEntityR = pen -> en_pciCollisionInfo -> GetMaxFloorRadius (); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +FLOAT fOuterCircle = ClampDn (m_fOuterCircle - fEntityR , 0.0f); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +FLOAT fInnerCircle = ClampUp (m_fInnerCircle + fEntityR , fOuterCircle ); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +FLOAT fR = fInnerCircle + FRnd () * (fOuterCircle - fInnerCircle ); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +FLOAT fA = FRnd () * 360.0f; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +CPlacement3D pl (FLOAT3D (CosFast (fA ) * fR , 0.05f , SinFast (fA ) * fR ) , ANGLE3D (0 , 0 , 0)); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +pl . RelativeToAbsolute (GetPlacement ()); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +pen -> Teleport (pl , m_bTelefrag ); +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_bSpawnEffect ){ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +ESpawnEffect ese ; +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +ese . betType = BET_TELEPORT ; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +ese . vNormal = FLOAT3D (0 , 1 , 0); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +FLOATaabbox3D box ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +pen -> GetBoundingBox (box ); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +FLOAT fEntitySize = box . Size () . MaxNorm () * 2; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +ese . vStretch = FLOAT3D (fEntitySize , fEntitySize , fEntitySize ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +CEntityPointer penEffect = CreateEntity (pl , CLASS_BASIC_EFFECT ); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +penEffect -> Initialize (ese ); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_penTacticsHolder != NULL ){ +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(IsOfClass (m_penTacticsHolder , "TacticsHolder")){ +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +CEnemyBase * peb = ((CEnemyBase *) pen ); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +peb -> m_penTacticsHolder = m_penTacticsHolder ; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_bTacticsAutostart ){ +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +peb -> StartTacticsNow (); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} + +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +BOOL CEnemySpawner::HandleEvent(const CEntityEvent & ee) +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(ee . ee_slEvent == EVENTCODE_ETrigger ) +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +ETrigger eTrigger = ((ETrigger &) ee ); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(IsDerivedFromClass (eTrigger . penCaused , "Enemy Base") +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +&& (m_estType == EST_MAINTAINGROUP || m_estType == EST_RESPAWNGROUP )){ +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_iEnemiesTriggered ++; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return CRationalEntity :: HandleEvent (ee ); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} + +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SLONG CEnemySpawner::GetUsedMemory(void) +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +{ +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SLONG slUsedMemory = sizeof (CEnemySpawner ) - sizeof (CRationalEntity ) + CRationalEntity :: GetUsedMemory (); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +slUsedMemory += m_strDescription . Length (); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +slUsedMemory += m_strName . Length (); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +slUsedMemory += 1 * sizeof (CSoundObject); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return slUsedMemory ; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +BOOL CEnemySpawner:: +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SpawnGroup(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemySpawner_SpawnGroup + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemySpawner::SpawnGroup expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_iInGroup = 0; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Jump(STATE_CURRENT,0x01300003, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x01300003_SpawnGroup_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300003 +if(!(TRUE )){ Jump(STATE_CURRENT,0x01300004, FALSE, EInternal());return TRUE;} +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SpawnEntity (TRUE ); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_ctTotal --; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_ctTotal <= 0){ +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Return(STATE_CURRENT,EEnd ()); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return TRUE; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_iInGroup ++; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_iEnemiesTriggered > 0 && m_estType == EST_RESPAWNGROUP ){ +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(! m_bFirstPass ){ +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_iEnemiesTriggered --; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}else if(m_iEnemiesTriggered > 0){ +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_iEnemiesTriggered --; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_iInGroup >= m_ctGroupSize ){ +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(! (m_estType == EST_MAINTAINGROUP && m_iEnemiesTriggered > 0)){ +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Return(STATE_CURRENT,EReturn ()); +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return TRUE; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAfter(m_tmSingleWait ); +Jump(STATE_CURRENT, 0x01300001, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300001_SpawnGroup_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01300002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return FALSE;}ASSERT(FALSE);break; +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}return TRUE;}BOOL CEnemySpawner::H0x01300002_SpawnGroup_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300002 +Jump(STATE_CURRENT,0x01300003, FALSE, EInternal());return TRUE; +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}BOOL CEnemySpawner::H0x01300004_SpawnGroup_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300004 + ASSERT(FALSE); return TRUE;};BOOL CEnemySpawner:: +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Simple(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemySpawner_Simple + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemySpawner::Simple expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01300006, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300006_Simple_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300006 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01300007, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01300007, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return FALSE;}ASSERT(FALSE);break; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}return TRUE;}BOOL CEnemySpawner::H0x01300007_Simple_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300007 + +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(!(m_tmDelay > 0)){ Jump(STATE_CURRENT,0x0130000a, FALSE, EInternal());return TRUE;} +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAfter(m_tmDelay ); +Jump(STATE_CURRENT, 0x01300008, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300008_Simple_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01300009, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x01300009_Simple_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300009 +;Jump(STATE_CURRENT,0x0130000a, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x0130000a_Simple_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130000a + +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Jump(STATE_CURRENT,0x0130000f, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x0130000f_Simple_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130000f +if(!(TRUE )){ Jump(STATE_CURRENT,0x01300010, FALSE, EInternal());return TRUE;} +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +STATE_CEnemySpawner_SpawnGroup, TRUE; +Jump(STATE_CURRENT, 0x0130000b, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x0130000b_Simple_06(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130000b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemySpawner_SpawnGroup, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0130000c, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x0130000c_Simple_07(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130000c +const EReturn&__e= (EReturn&)__eeInput; +; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAfter(m_tmGroupWait ); +Jump(STATE_CURRENT, 0x0130000d, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x0130000d_Simple_08(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130000d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0130000e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x0130000e_Simple_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130000e +;Jump(STATE_CURRENT,0x0130000f, FALSE, EInternal());return TRUE; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}BOOL CEnemySpawner::H0x01300010_Simple_11(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300010 + ASSERT(FALSE); return TRUE;};BOOL CEnemySpawner:: +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Teleporter(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemySpawner_Teleporter + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemySpawner::Teleporter expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01300012, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300012_Teleporter_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300012 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01300013, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01300013, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return FALSE;}ASSERT(FALSE);break; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}return TRUE;}BOOL CEnemySpawner::H0x01300013_Teleporter_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300013 + +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(!(m_tmDelay > 0)){ Jump(STATE_CURRENT,0x01300016, FALSE, EInternal());return TRUE;} +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAfter(m_tmDelay ); +Jump(STATE_CURRENT, 0x01300014, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300014_Teleporter_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300014 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01300015, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x01300015_Teleporter_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300015 +;Jump(STATE_CURRENT,0x01300016, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x01300016_Teleporter_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300016 + +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SpawnEntity (FALSE ); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Return(STATE_CURRENT,EEnd ()); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemySpawner:: +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Respawner(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemySpawner_Respawner + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemySpawner::Respawner expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Jump(STATE_CURRENT,0x01300031, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x01300031_Respawner_26(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300031 +if(!(TRUE )){ Jump(STATE_CURRENT,0x01300032, FALSE, EInternal());return TRUE;} +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01300018, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300018_Respawner_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300018 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(! m_bFirstPass && m_iEnemiesTriggered > 0){ +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +UnsetTimer();Jump(STATE_CURRENT,0x01300019, FALSE, EInternal());return TRUE; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return TRUE; +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01300019, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01300019, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return FALSE;}ASSERT(FALSE);break; +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}return TRUE;}BOOL CEnemySpawner::H0x01300019_Respawner_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300019 + +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(!(m_tmDelay > 0 && m_bFirstPass )){ Jump(STATE_CURRENT,0x0130001c, FALSE, EInternal());return TRUE;} +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAfter(m_tmDelay ); +Jump(STATE_CURRENT, 0x0130001a, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x0130001a_Respawner_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130001a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0130001b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x0130001b_Respawner_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130001b +;Jump(STATE_CURRENT,0x0130001c, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x0130001c_Respawner_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130001c + +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(!(m_estType == EST_RESPAWNGROUP )){ Jump(STATE_CURRENT,0x0130002e, FALSE, EInternal());return TRUE;} +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(!(m_bFirstPass )){ Jump(STATE_CURRENT,0x01300026, FALSE, EInternal());return TRUE;} +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +STATE_CEnemySpawner_SpawnGroup, TRUE; +Jump(STATE_CURRENT, 0x0130001d, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x0130001d_Respawner_06(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130001d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemySpawner_SpawnGroup, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0130001e, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x0130001e_Respawner_07(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130001e +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01300025, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x01300026_Respawner_15(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300026 +if(!(m_iEnemiesTriggered >= m_ctGroupSize )){ Jump(STATE_CURRENT,0x01300024, FALSE, EInternal());return TRUE;} +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(!(m_tmGroupWait > 0)){ Jump(STATE_CURRENT,0x01300021, FALSE, EInternal());return TRUE;}SetTimerAfter(m_tmGroupWait ); +Jump(STATE_CURRENT, 0x0130001f, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x0130001f_Respawner_08(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130001f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01300020, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x01300020_Respawner_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300020 +;Jump(STATE_CURRENT,0x01300021, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x01300021_Respawner_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300021 + +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +STATE_CEnemySpawner_SpawnGroup, TRUE; +Jump(STATE_CURRENT, 0x01300022, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300022_Respawner_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300022 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemySpawner_SpawnGroup, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01300023, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x01300023_Respawner_12(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300023 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01300024, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x01300024_Respawner_13(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300024 +Jump(STATE_CURRENT,0x01300025, FALSE, EInternal());return TRUE;} +BOOL CEnemySpawner::H0x01300025_Respawner_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300025 +Jump(STATE_CURRENT,0x0130002d, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x0130002e_Respawner_23(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130002e +if(!(TRUE )){ Jump(STATE_CURRENT,0x0130002c, FALSE, EInternal());return TRUE;} +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(!(m_tmGroupWait > 0 && ! m_bFirstPass )){ Jump(STATE_CURRENT,0x01300029, FALSE, EInternal());return TRUE;}SetTimerAfter(m_tmGroupWait ); +Jump(STATE_CURRENT, 0x01300027, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300027_Respawner_16(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300027 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01300028, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x01300028_Respawner_17(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300028 +;Jump(STATE_CURRENT,0x01300029, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x01300029_Respawner_18(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300029 + +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +STATE_CEnemySpawner_SpawnGroup, TRUE; +Jump(STATE_CURRENT, 0x0130002a, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x0130002a_Respawner_19(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130002a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemySpawner_SpawnGroup, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0130002b, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x0130002b_Respawner_20(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130002b +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x0130002c, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x0130002c_Respawner_21(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130002c +Jump(STATE_CURRENT,0x0130002d, FALSE, EInternal());return TRUE;} +BOOL CEnemySpawner::H0x0130002d_Respawner_22(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130002d + +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_estType == EST_MAINTAINGROUP ){ +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_ctGroupSize = 1; +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_bFirstPass = FALSE ; +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x0130002f, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x0130002f_Respawner_24(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130002f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01300030, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x01300030_Respawner_25(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300030 +;Jump(STATE_CURRENT,0x01300031, FALSE, EInternal());return TRUE; +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}BOOL CEnemySpawner::H0x01300032_Respawner_27(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300032 + ASSERT(FALSE); return TRUE;};BOOL CEnemySpawner:: +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +DestroyableInactive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemySpawner_DestroyableInactive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemySpawner::DestroyableInactive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01300034, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300034_DestroyableInactive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300034 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_EActivate: Jump(STATE_CURRENT,0x01300035, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x01300035_DestroyableInactive_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300035 +const EActivate&__e= (EActivate&)__eeInput; +; +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Jump(STATE_CURRENT, STATE_CEnemySpawner_DestroyableActive, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemySpawner:: +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +DestroyableActiveSpawning(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemySpawner_DestroyableActiveSpawning + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemySpawner::DestroyableActiveSpawning expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Jump(STATE_CURRENT,0x0130003b, FALSE, EInternal());return TRUE;}BOOL CEnemySpawner::H0x0130003b_DestroyableActiveSpawning_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130003b +if(!(TRUE )){ Jump(STATE_CURRENT,0x0130003c, FALSE, EInternal());return TRUE;} +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +STATE_CEnemySpawner_SpawnGroup, TRUE; +Jump(STATE_CURRENT, 0x01300037, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300037_DestroyableActiveSpawning_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300037 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemySpawner_SpawnGroup, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01300038, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x01300038_DestroyableActiveSpawning_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300038 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAfter(m_tmGroupWait ); +Jump(STATE_CURRENT, 0x01300039, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300039_DestroyableActiveSpawning_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300039 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0130003a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x0130003a_DestroyableActiveSpawning_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130003a +;Jump(STATE_CURRENT,0x0130003b, FALSE, EInternal());return TRUE; +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}BOOL CEnemySpawner::H0x0130003c_DestroyableActiveSpawning_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130003c + ASSERT(FALSE); return TRUE;};BOOL CEnemySpawner:: +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +DestroyableActive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemySpawner_DestroyableActive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemySpawner::DestroyableActive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +STATE_CEnemySpawner_DestroyableActiveSpawning, TRUE; +Jump(STATE_CURRENT, 0x0130003e, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x0130003e_DestroyableActive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130003e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemySpawner_DestroyableActiveSpawning, TRUE, EVoid());return TRUE;case EVENTCODE_EDeactivate: Jump(STATE_CURRENT,0x0130003f, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x0130003f_DestroyableActive_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0130003f +const EDeactivate&__e= (EDeactivate&)__eeInput; +; +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Jump(STATE_CURRENT, STATE_CEnemySpawner_DestroyableInactive, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemySpawner:: +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Destroyable(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemySpawner_Destroyable + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemySpawner::Destroyable expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +STATE_CEnemySpawner_DestroyableInactive, TRUE; +Jump(STATE_CURRENT, 0x01300041, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300041_Destroyable_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300041 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemySpawner_DestroyableInactive, TRUE, EVoid());return TRUE;case EVENTCODE_EStop: Jump(STATE_CURRENT,0x01300042, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x01300042_Destroyable_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300042 +const EStop&__e= (EStop&)__eeInput; +; +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Return(STATE_CURRENT,EEnd ()); +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnemySpawner:: +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnemySpawner_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnemySpawner::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +InitAsEditorModel (); +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetModel (MODEL_ENEMYSPAWNER ); +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetModelMainTexture (TEXTURE_ENEMYSPAWNER ); +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_tmSingleWait <= 0.0f){m_tmSingleWait = 0.05f;} +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_tmGroupWait <= 0.0f){m_tmGroupWait = 0.05f;} +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_fInnerCircle > m_fOuterCircle ){ +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_fInnerCircle = m_fOuterCircle ; +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_estType == EST_RESPAWNERBYONE ){ +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_estType = EST_MAINTAINGROUP ; +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_penTarget != NULL ){ +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(! IsDerivedFromClass (m_penTarget , "Enemy Base")){ +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +WarningMessage ("Target '%s' is of wrong class!" , m_penTarget -> GetName ()); +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_penTarget = NULL ; +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_penSeriousTarget != NULL ){ +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(! IsDerivedFromClass (m_penSeriousTarget , "Enemy Base")){ +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +WarningMessage ("Target '%s' is of wrong class!" , m_penSeriousTarget -> GetName ()); +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_penSeriousTarget = NULL ; +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01300043, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300043_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300043 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01300044, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnemySpawner::H0x01300044_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300044 +; +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(! GetSP () -> sp_bUseExtraEnemies && ! GetSP () -> sp_bSinglePlayer +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +&& ! (GetSpawnFlags () & SPF_SINGLEPLAYER )){ +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Destroy (); +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Return(STATE_CURRENT,EVoid()); +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return TRUE; +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_bDoubleInSerious && GetSP () -> sp_gdGameDifficulty == CSessionProperties :: GD_EXTREME ){ +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_ctGroupSize *= 2; +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_ctTotal *= 2; +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_penSeriousTarget != NULL && GetSP () -> sp_gdGameDifficulty == CSessionProperties :: GD_EXTREME ){ +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_penTarget = m_penSeriousTarget ; +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_estType == EST_MAINTAINGROUP ){ +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_iEnemiesTriggered = m_ctGroupSize ; +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_bFirstPass = TRUE ; +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01300045, FALSE, EBegin());return TRUE;}BOOL CEnemySpawner::H0x01300045_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300045 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +if(m_estType == EST_SIMPLE ){ +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Call(STATE_CURRENT, STATE_CEnemySpawner_Simple, TRUE, EVoid());return TRUE; +#line 491 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}else if(m_estType == EST_TELEPORTER ){ +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Call(STATE_CURRENT, STATE_CEnemySpawner_Teleporter, TRUE, EVoid());return TRUE; +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}else if(m_estType == EST_RESPAWNER +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +|| m_estType == EST_TRIGGERED || m_estType == EST_RESPAWNGROUP ){ +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Call(STATE_CURRENT, STATE_CEnemySpawner_Respawner, TRUE, EVoid());return TRUE; +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}else if(m_estType == EST_MAINTAINGROUP ){ +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +m_ctGroupSize = 1; +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Call(STATE_CURRENT, STATE_CEnemySpawner_Respawner, TRUE, EVoid());return TRUE; +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +else if(m_estType == EST_DESTROYABLE ){ +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Call(STATE_CURRENT, STATE_CEnemySpawner_Destroyable, TRUE, EVoid());return TRUE; +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +} +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +UnsetTimer();Jump(STATE_CURRENT,0x01300046, FALSE, EInternal());return TRUE; +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +UnsetTimer();Jump(STATE_CURRENT,0x01300046, FALSE, EInternal());return TRUE; +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnd):{const EEnd&e= (EEnd&)__eeInput; + +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +UnsetTimer();Jump(STATE_CURRENT,0x01300046, FALSE, EInternal());return TRUE; +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +}return TRUE;}BOOL CEnemySpawner::H0x01300046_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01300046 + +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Destroy (); +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Return(STATE_CURRENT,EVoid()); +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EnemySpawner.es b/Sources/EntitiesMP/EnemySpawner.es new file mode 100644 index 0000000..7c2dd3a --- /dev/null +++ b/Sources/EntitiesMP/EnemySpawner.es @@ -0,0 +1,519 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +304 +%{ +#include "StdH.h" +%} + + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/BasicEffects"; + +enum EnemySpawnerType { + 0 EST_SIMPLE "Simple", // spawns on trigger + 1 EST_RESPAWNER "Respawner", // respawn after death + 2 EST_DESTROYABLE "Destroyable", // spawns untill killed + 3 EST_TRIGGERED "Triggered", // spawn one group on each trigger + 4 EST_TELEPORTER "Teleporter", // teleport the target instead copying it - usable only once + 5 EST_RESPAWNERBYONE "OBSOLETE - Don't use!", // respawn only one (not entire group) after death + 6 EST_MAINTAINGROUP "MaintainGroup", // respawn by need to maintain the number of active enemies + 7 EST_RESPAWNGROUP "RespawnerByGroup", // respawn the whole group when it's destroyed +}; + + +class CEnemySpawner: CRationalEntity { +name "Enemy Spawner"; +thumbnail "Thumbnails\\EnemySpawner.tbn"; +features "HasName", "HasTarget", "IsTargetable"; + +properties: + + 1 CEntityPointer m_penTarget "Template Target" 'T' COLOR(C_BLUE|0x20), // template entity to duplicate + 2 CTString m_strDescription = "", + 3 CTString m_strName "Name" 'N' = "Enemy spawner", + + 6 RANGE m_fInnerCircle "Circle inner" 'V' = 0.0f, // inner circle for creation + 7 RANGE m_fOuterCircle "Circle outer" 'B' = 0.0f, // outer circle for creation + 9 FLOAT m_tmDelay "Delay initial" 'W' = 0.0f, // how long to delay before spawning + 16 FLOAT m_tmSingleWait "Delay single" 'O' = 0.1f, // delay inside one group + 5 FLOAT m_tmGroupWait "Delay group" 'G' = 0.1f, // delay between two groups + 17 INDEX m_ctGroupSize "Count group" = 1, + 8 INDEX m_ctTotal "Count total" 'C' = 1, // max. number of spawned enemies + 13 CEntityPointer m_penPatrol "Patrol target" 'P' COLOR(C_lGREEN|0xFF), // for spawning patrolling + 15 enum EnemySpawnerType m_estType "Type" 'Y' = EST_SIMPLE, // type of spawner + 18 BOOL m_bTelefrag "Telefrag" 'F' = FALSE, // telefrag when spawning + 19 BOOL m_bSpawnEffect "SpawnEffect" 'S' = TRUE, // show effect and play sound + 20 BOOL m_bDoubleInSerious "Double in serious mode" = FALSE, + 21 CEntityPointer m_penSeriousTarget "Template for Serious" COLOR(C_RED|0x20), + 22 BOOL m_bFirstPass = TRUE, + + 50 CSoundObject m_soSpawn, // sound channel + 51 INDEX m_iInGroup=0, // in group counter for loops + 52 INDEX m_iEnemiesTriggered=0, // number of times enemies triggered the spawner on death + + 60 CEntityPointer m_penTacticsHolder "Tactics Holder", + 61 BOOL m_bTacticsAutostart "Tactics autostart" = TRUE, + + + +components: + + 1 model MODEL_ENEMYSPAWNER "Models\\Editor\\EnemySpawner.mdl", + 2 texture TEXTURE_ENEMYSPAWNER "Models\\Editor\\EnemySpawner.tex", + 3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + + +functions: + + void Precache(void) + { + PrecacheClass(CLASS_BASIC_EFFECT, BET_TELEPORT); + } + + + const CTString &GetDescription(void) const + { + ((CTString&)m_strDescription).PrintF("->"); + if (m_penTarget!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", m_penTarget->GetName()); + if (m_penSeriousTarget!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s, %s", + m_penTarget->GetName(), m_penSeriousTarget->GetName()); + } + } + ((CTString&)m_strDescription) = EnemySpawnerType_enum.NameForValue(INDEX(m_estType)) + + m_strDescription; + return m_strDescription; + } + + + // check if one template is valid for this spawner + BOOL CheckTemplateValid(CEntity *pen) + { + if (pen==NULL || !IsDerivedFromClass(pen, "Enemy Base")) { + return FALSE; + } + if (m_estType==EST_TELEPORTER) { + return !(((CEnemyBase&)*pen).m_bTemplate); + } else { + return ((CEnemyBase&)*pen).m_bTemplate; + } + } + + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if( slPropertyOffset == offsetof(CEnemySpawner, m_penTarget)) + { + return CheckTemplateValid(penTarget); + } + else if( slPropertyOffset == offsetof(CEnemySpawner, m_penPatrol)) + { + return (penTarget!=NULL && IsDerivedFromClass(penTarget, "Enemy Marker")); + } + else if( slPropertyOffset == offsetof(CEnemySpawner, m_penSeriousTarget)) + { + return CheckTemplateValid(penTarget); + } + else if( slPropertyOffset == offsetof(CEnemySpawner, m_penTacticsHolder)) + { + if (IsOfClass(penTarget, "TacticsHolder")) { return TRUE; } + else { return FALSE; } + } + return CEntity::IsTargetValid(slPropertyOffset, penTarget); + } + + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + if (m_penTarget==NULL) { return FALSE; } + m_penTarget->FillEntityStatistics(pes); + pes->es_ctCount = m_ctTotal; + pes->es_strName += " (spawned)"; + if (m_penSeriousTarget!=NULL) { + pes->es_strName += " (has serious)"; + } + return TRUE; + } + + // spawn new entity + void SpawnEntity(BOOL bCopy) { + // spawn new entity if of class basic enemy + if (CheckTemplateValid(m_penTarget)) { + + CEntity *pen = NULL; + if (bCopy) { + // copy template entity + pen = GetWorld()->CopyEntityInWorld( *m_penTarget, + CPlacement3D(FLOAT3D(-32000.0f+FRnd()*200.0f, -32000.0f+FRnd()*200.0f, 0), ANGLE3D(0, 0, 0)) ); + + // change needed properties + pen->End(); + CEnemyBase *peb = ((CEnemyBase*)pen); + peb->m_bTemplate = FALSE; + if (m_estType==EST_RESPAWNER /*|| m_estType==EST_RESPAWNERBYONE*/ + || m_estType==EST_MAINTAINGROUP || m_estType==EST_RESPAWNGROUP) { + peb->m_penSpawnerTarget = this; + } + if (m_penPatrol!=NULL) { + peb->m_penMarker = m_penPatrol; + } + pen->Initialize(); + } else { + pen = m_penTarget; + m_penTarget = NULL; + } + + // adjust circle radii to account for enemy size + FLOAT fEntityR = 0; + if (pen->en_pciCollisionInfo!=NULL) { + fEntityR = pen->en_pciCollisionInfo->GetMaxFloorRadius(); + } + FLOAT fOuterCircle = ClampDn(m_fOuterCircle-fEntityR, 0.0f); + FLOAT fInnerCircle = ClampUp(m_fInnerCircle+fEntityR, fOuterCircle); + // calculate new position + FLOAT fR = fInnerCircle + FRnd()*(fOuterCircle-fInnerCircle); + FLOAT fA = FRnd()*360.0f; + CPlacement3D pl(FLOAT3D(CosFast(fA)*fR, 0.05f, SinFast(fA)*fR), ANGLE3D(0, 0, 0)); + pl.RelativeToAbsolute(GetPlacement()); + + // teleport back + pen->Teleport(pl, m_bTelefrag); + + // spawn teleport effect + if (m_bSpawnEffect) { + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_TELEPORT; + ese.vNormal = FLOAT3D(0,1,0); + FLOATaabbox3D box; + pen->GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm()*2; + ese.vStretch = FLOAT3D(fEntitySize, fEntitySize, fEntitySize); + CEntityPointer penEffect = CreateEntity(pl, CLASS_BASIC_EFFECT); + penEffect->Initialize(ese); + } + + // initialize tactics + if (m_penTacticsHolder!=NULL) { + if (IsOfClass(m_penTacticsHolder, "TacticsHolder")) { + CEnemyBase *peb = ((CEnemyBase*)pen); + peb->m_penTacticsHolder = m_penTacticsHolder; + if (m_bTacticsAutostart) { + // start tactics + peb->StartTacticsNow(); + } + } + } + + } + }; + + // Handle an event, return false if the event is not handled + BOOL HandleEvent(const CEntityEvent &ee) + { + if (ee.ee_slEvent==EVENTCODE_ETrigger) + { + ETrigger eTrigger = ((ETrigger &) ee); + if(IsDerivedFromClass(eTrigger.penCaused, "Enemy Base") + && (m_estType==EST_MAINTAINGROUP || m_estType==EST_RESPAWNGROUP)) { + m_iEnemiesTriggered++; + } + } + return CRationalEntity::HandleEvent(ee); + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CEnemySpawner) - sizeof(CRationalEntity) + CRationalEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strDescription.Length(); + slUsedMemory += m_strName.Length(); + slUsedMemory += 1* sizeof(CSoundObject); + return slUsedMemory; + } + +procedures: + + // spawn one group of entities + SpawnGroup() + { + // no enemies in group yet + m_iInGroup = 0; + // repeat forever + while(TRUE) { + + // spawn one enemy + SpawnEntity(TRUE); + + // count total enemies spawned + m_ctTotal--; + // if no more left + if (m_ctTotal<=0) { + // finish entire spawner + return EEnd(); + } + + // count enemies in group + m_iInGroup++; + // decrease the needed count + if (m_iEnemiesTriggered>0 && m_estType==EST_RESPAWNGROUP) { + if (!m_bFirstPass) { + m_iEnemiesTriggered--; + } + } else if (m_iEnemiesTriggered>0) { + m_iEnemiesTriggered--; + } + + // if entire group spawned + if (m_iInGroup>=m_ctGroupSize) { + if (!(m_estType==EST_MAINTAINGROUP && m_iEnemiesTriggered>0)) { + // finish + return EReturn(); + } + } + + // wait between two entities in group + wait(m_tmSingleWait) { + on (EBegin) : { resume; } + on (ETimer) : { stop; } + otherwise() : { pass; } + } + } + } + + // simple spawner + Simple() + { + // wait to be triggered + wait() { + on (EBegin) : { resume; } + on (ETrigger) : { stop; }; + on (EStart) : { stop; }; + otherwise() : { pass; } + } + + // if should delay + if (m_tmDelay>0) { + // wait delay + autowait(m_tmDelay); + } + + // repeat + while(TRUE) { + // spawn one group + autocall SpawnGroup() EReturn; + // delay between groups + autowait(m_tmGroupWait); + } + } + + // teleports the template + Teleporter() + { + // wait to be triggered + wait() { + on (EBegin) : { resume; } + on (ETrigger) : { stop; }; + on (EStart) : { stop; }; + otherwise() : { pass; } + } + + // if should delay + if (m_tmDelay>0) { + // wait delay + autowait(m_tmDelay); + } + + // teleport it + SpawnEntity(FALSE); + + // end the spawner + return EEnd(); + } + + // respawn enemies when killed + Respawner() + { + // repeat + while(TRUE) { + // wait to be triggered + wait() { + on (EBegin) : { + if (!m_bFirstPass && m_iEnemiesTriggered>0) { + stop; + } + resume; + } + on (ETrigger) : { stop; }; + on (EStart) : { stop; }; + otherwise() : { pass; } + } + + // if should delay - only once, on beginning + if (m_tmDelay>0 && m_bFirstPass) { + // initial delay + autowait(m_tmDelay); + } + + if (m_estType==EST_RESPAWNGROUP) { + if (m_bFirstPass) { + autocall SpawnGroup() EReturn; + } else if (m_iEnemiesTriggered>=m_ctGroupSize) { + if (m_tmGroupWait>0) { autowait(m_tmGroupWait); } + autocall SpawnGroup() EReturn; + } + } else if (TRUE) { + // spawn one group + if (m_tmGroupWait>0 && !m_bFirstPass) { autowait(m_tmGroupWait); } + autocall SpawnGroup() EReturn; + } + + // if should continue respawning by one + /*if (m_estType==EST_RESPAWNERBYONE) { + // set group size to 1 + if (m_tmGroupWait>0 && !m_bFirstPass) { autowait(m_tmGroupWait); } + m_ctGroupSize = 1; + }*/ + + // if should continue maintaining group + if (m_estType==EST_MAINTAINGROUP) { + // set group size to 1 + m_ctGroupSize = 1; + } + + // never do an initial delay again - set FirstPass to FALSE + m_bFirstPass = FALSE; + + // wait a bit to recover + autowait(0.1f); + } + } + + DestroyableInactive() + { + waitevent() EActivate; + jump DestroyableActive(); + } + + DestroyableActiveSpawning() + { + // repeat + while(TRUE) { + // spawn one group + autocall SpawnGroup() EReturn; + // delay between groups + autowait(m_tmGroupWait); + } + } + DestroyableActive() + { + autocall DestroyableActiveSpawning() EDeactivate; + jump DestroyableInactive(); + } + + // spawn new entities until you are stopped + Destroyable() + { + // start in inactive state and do until stopped + autocall DestroyableInactive() EStop; + // finish + return EEnd(); + } + + Main() { + // init as nothing + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_ENEMYSPAWNER); + SetModelMainTexture(TEXTURE_ENEMYSPAWNER); + + if (m_tmSingleWait<=0.0f) { m_tmSingleWait=0.05f; } + if (m_tmGroupWait<=0.0f) { m_tmGroupWait=0.05f; } + + // set range + if (m_fInnerCircle > m_fOuterCircle) { + m_fInnerCircle = m_fOuterCircle; + } + + if (m_estType==EST_RESPAWNERBYONE) { + m_estType=EST_MAINTAINGROUP; + } + + // check target + if (m_penTarget!=NULL) { + if (!IsDerivedFromClass(m_penTarget, "Enemy Base")) { + WarningMessage("Target '%s' is of wrong class!", m_penTarget->GetName()); + m_penTarget = NULL; + } + } + if (m_penSeriousTarget!=NULL) { + if (!IsDerivedFromClass(m_penSeriousTarget, "Enemy Base")) { + WarningMessage("Target '%s' is of wrong class!", m_penSeriousTarget->GetName()); + m_penSeriousTarget = NULL; + } + } + + // never start ai in wed + autowait(_pTimer->TickQuantum); + + // destroy self if this is a multiplayer-only spawner, and flags indicate no extra enemies + if ( !GetSP()->sp_bUseExtraEnemies && !GetSP()->sp_bSinglePlayer + && !(GetSpawnFlags()&SPF_SINGLEPLAYER)) { + Destroy(); + return; + } + + if (m_bDoubleInSerious && GetSP()->sp_gdGameDifficulty==CSessionProperties::GD_EXTREME) { + m_ctGroupSize*=2; + m_ctTotal*=2; + } + if (m_penSeriousTarget!=NULL && GetSP()->sp_gdGameDifficulty==CSessionProperties::GD_EXTREME) { + m_penTarget = m_penSeriousTarget; + } + + if (m_estType==EST_MAINTAINGROUP) { + m_iEnemiesTriggered = m_ctGroupSize; + } + + m_bFirstPass = TRUE; + + wait() { + on(EBegin) : { + if(m_estType==EST_SIMPLE) { + call Simple(); + } else if(m_estType==EST_TELEPORTER) { + call Teleporter(); + } else if(m_estType==EST_RESPAWNER /*|| m_estType==EST_RESPAWNERBYONE*/ + || m_estType==EST_TRIGGERED || m_estType==EST_RESPAWNGROUP) { + call Respawner(); + } else if(m_estType==EST_MAINTAINGROUP) { + m_ctGroupSize = 1; + call Respawner(); + } + else if(m_estType==EST_DESTROYABLE) { + call Destroyable(); + } + } + on(EDeactivate) : { + stop; + } + on(EStop) : { + stop; + } + on(EEnd) : { + stop; + } + } + + Destroy(); + + return; + }; +}; diff --git a/Sources/EntitiesMP/EnemySpawner.h b/Sources/EntitiesMP/EnemySpawner.h new file mode 100644 index 0000000..cb7b67b --- /dev/null +++ b/Sources/EntitiesMP/EnemySpawner.h @@ -0,0 +1,174 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_EnemySpawner_INCLUDED +#define _EntitiesMP_EnemySpawner_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType EnemySpawnerType_enum; +enum EnemySpawnerType { + EST_SIMPLE = 0, + EST_RESPAWNER = 1, + EST_DESTROYABLE = 2, + EST_TRIGGERED = 3, + EST_TELEPORTER = 4, + EST_RESPAWNERBYONE = 5, + EST_MAINTAINGROUP = 6, + EST_RESPAWNGROUP = 7, +}; +DECL_DLL inline void ClearToDefault(EnemySpawnerType &e) { e = (EnemySpawnerType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CEnemySpawner_DLLClass; +class CEnemySpawner : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual CEntity *GetTarget(void) const { return m_penTarget; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penTarget; + CTString m_strDescription; + CTString m_strName; + RANGE m_fInnerCircle; + RANGE m_fOuterCircle; + FLOAT m_tmDelay; + FLOAT m_tmSingleWait; + FLOAT m_tmGroupWait; + INDEX m_ctGroupSize; + INDEX m_ctTotal; + CEntityPointer m_penPatrol; + enum EnemySpawnerType m_estType; + BOOL m_bTelefrag; + BOOL m_bSpawnEffect; + BOOL m_bDoubleInSerious; + CEntityPointer m_penSeriousTarget; + BOOL m_bFirstPass; + CSoundObject m_soSpawn; + INDEX m_iInGroup; + INDEX m_iEnemiesTriggered; + CEntityPointer m_penTacticsHolder; + BOOL m_bTacticsAutostart; + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +void Precache(void); + +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +const CTString & GetDescription(void)const; + +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +BOOL CheckTemplateValid(CEntity * pen); + +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +void SpawnEntity(BOOL bCopy); + +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +BOOL HandleEvent(const CEntityEvent & ee); + +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SLONG GetUsedMemory(void); +#define STATE_CEnemySpawner_SpawnGroup 0x01300000 + BOOL +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SpawnGroup(const CEntityEvent &__eeInput); + BOOL H0x01300001_SpawnGroup_01(const CEntityEvent &__eeInput); + BOOL H0x01300002_SpawnGroup_02(const CEntityEvent &__eeInput); + BOOL H0x01300003_SpawnGroup_03(const CEntityEvent &__eeInput); + BOOL H0x01300004_SpawnGroup_04(const CEntityEvent &__eeInput); +#define STATE_CEnemySpawner_Simple 0x01300005 + BOOL +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Simple(const CEntityEvent &__eeInput); + BOOL H0x01300006_Simple_01(const CEntityEvent &__eeInput); + BOOL H0x01300007_Simple_02(const CEntityEvent &__eeInput); + BOOL H0x01300008_Simple_03(const CEntityEvent &__eeInput); + BOOL H0x01300009_Simple_04(const CEntityEvent &__eeInput); + BOOL H0x0130000a_Simple_05(const CEntityEvent &__eeInput); + BOOL H0x0130000b_Simple_06(const CEntityEvent &__eeInput); + BOOL H0x0130000c_Simple_07(const CEntityEvent &__eeInput); + BOOL H0x0130000d_Simple_08(const CEntityEvent &__eeInput); + BOOL H0x0130000e_Simple_09(const CEntityEvent &__eeInput); + BOOL H0x0130000f_Simple_10(const CEntityEvent &__eeInput); + BOOL H0x01300010_Simple_11(const CEntityEvent &__eeInput); +#define STATE_CEnemySpawner_Teleporter 0x01300011 + BOOL +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Teleporter(const CEntityEvent &__eeInput); + BOOL H0x01300012_Teleporter_01(const CEntityEvent &__eeInput); + BOOL H0x01300013_Teleporter_02(const CEntityEvent &__eeInput); + BOOL H0x01300014_Teleporter_03(const CEntityEvent &__eeInput); + BOOL H0x01300015_Teleporter_04(const CEntityEvent &__eeInput); + BOOL H0x01300016_Teleporter_05(const CEntityEvent &__eeInput); +#define STATE_CEnemySpawner_Respawner 0x01300017 + BOOL +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Respawner(const CEntityEvent &__eeInput); + BOOL H0x01300018_Respawner_01(const CEntityEvent &__eeInput); + BOOL H0x01300019_Respawner_02(const CEntityEvent &__eeInput); + BOOL H0x0130001a_Respawner_03(const CEntityEvent &__eeInput); + BOOL H0x0130001b_Respawner_04(const CEntityEvent &__eeInput); + BOOL H0x0130001c_Respawner_05(const CEntityEvent &__eeInput); + BOOL H0x0130001d_Respawner_06(const CEntityEvent &__eeInput); + BOOL H0x0130001e_Respawner_07(const CEntityEvent &__eeInput); + BOOL H0x0130001f_Respawner_08(const CEntityEvent &__eeInput); + BOOL H0x01300020_Respawner_09(const CEntityEvent &__eeInput); + BOOL H0x01300021_Respawner_10(const CEntityEvent &__eeInput); + BOOL H0x01300022_Respawner_11(const CEntityEvent &__eeInput); + BOOL H0x01300023_Respawner_12(const CEntityEvent &__eeInput); + BOOL H0x01300024_Respawner_13(const CEntityEvent &__eeInput); + BOOL H0x01300025_Respawner_14(const CEntityEvent &__eeInput); + BOOL H0x01300026_Respawner_15(const CEntityEvent &__eeInput); + BOOL H0x01300027_Respawner_16(const CEntityEvent &__eeInput); + BOOL H0x01300028_Respawner_17(const CEntityEvent &__eeInput); + BOOL H0x01300029_Respawner_18(const CEntityEvent &__eeInput); + BOOL H0x0130002a_Respawner_19(const CEntityEvent &__eeInput); + BOOL H0x0130002b_Respawner_20(const CEntityEvent &__eeInput); + BOOL H0x0130002c_Respawner_21(const CEntityEvent &__eeInput); + BOOL H0x0130002d_Respawner_22(const CEntityEvent &__eeInput); + BOOL H0x0130002e_Respawner_23(const CEntityEvent &__eeInput); + BOOL H0x0130002f_Respawner_24(const CEntityEvent &__eeInput); + BOOL H0x01300030_Respawner_25(const CEntityEvent &__eeInput); + BOOL H0x01300031_Respawner_26(const CEntityEvent &__eeInput); + BOOL H0x01300032_Respawner_27(const CEntityEvent &__eeInput); +#define STATE_CEnemySpawner_DestroyableInactive 0x01300033 + BOOL +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +DestroyableInactive(const CEntityEvent &__eeInput); + BOOL H0x01300034_DestroyableInactive_01(const CEntityEvent &__eeInput); + BOOL H0x01300035_DestroyableInactive_02(const CEntityEvent &__eeInput); +#define STATE_CEnemySpawner_DestroyableActiveSpawning 0x01300036 + BOOL +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +DestroyableActiveSpawning(const CEntityEvent &__eeInput); + BOOL H0x01300037_DestroyableActiveSpawning_01(const CEntityEvent &__eeInput); + BOOL H0x01300038_DestroyableActiveSpawning_02(const CEntityEvent &__eeInput); + BOOL H0x01300039_DestroyableActiveSpawning_03(const CEntityEvent &__eeInput); + BOOL H0x0130003a_DestroyableActiveSpawning_04(const CEntityEvent &__eeInput); + BOOL H0x0130003b_DestroyableActiveSpawning_05(const CEntityEvent &__eeInput); + BOOL H0x0130003c_DestroyableActiveSpawning_06(const CEntityEvent &__eeInput); +#define STATE_CEnemySpawner_DestroyableActive 0x0130003d + BOOL +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +DestroyableActive(const CEntityEvent &__eeInput); + BOOL H0x0130003e_DestroyableActive_01(const CEntityEvent &__eeInput); + BOOL H0x0130003f_DestroyableActive_02(const CEntityEvent &__eeInput); +#define STATE_CEnemySpawner_Destroyable 0x01300040 + BOOL +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Destroyable(const CEntityEvent &__eeInput); + BOOL H0x01300041_Destroyable_01(const CEntityEvent &__eeInput); + BOOL H0x01300042_Destroyable_02(const CEntityEvent &__eeInput); +#define STATE_CEnemySpawner_Main 1 + BOOL +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01300043_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01300044_Main_02(const CEntityEvent &__eeInput); + BOOL H0x01300045_Main_03(const CEntityEvent &__eeInput); + BOOL H0x01300046_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_EnemySpawner_INCLUDED diff --git a/Sources/EntitiesMP/EnemySpawner_tables.h b/Sources/EntitiesMP/EnemySpawner_tables.h new file mode 100644 index 0000000..9fc9816 --- /dev/null +++ b/Sources/EntitiesMP/EnemySpawner_tables.h @@ -0,0 +1,157 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(EnemySpawnerType) + EP_ENUMVALUE(EST_SIMPLE, "Simple"), + EP_ENUMVALUE(EST_RESPAWNER, "Respawner"), + EP_ENUMVALUE(EST_DESTROYABLE, "Destroyable"), + EP_ENUMVALUE(EST_TRIGGERED, "Triggered"), + EP_ENUMVALUE(EST_TELEPORTER, "Teleporter"), + EP_ENUMVALUE(EST_RESPAWNERBYONE, "OBSOLETE - Don't use!"), + EP_ENUMVALUE(EST_MAINTAINGROUP, "MaintainGroup"), + EP_ENUMVALUE(EST_RESPAWNGROUP, "RespawnerByGroup"), +EP_ENUMEND(EnemySpawnerType); + +#define ENTITYCLASS CEnemySpawner + +CEntityProperty CEnemySpawner_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000130<<8)+1, offsetof(CEnemySpawner, m_penTarget), "Template Target", 'T', C_BLUE | 0x20, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000130<<8)+2, offsetof(CEnemySpawner, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000130<<8)+3, offsetof(CEnemySpawner, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000130<<8)+6, offsetof(CEnemySpawner, m_fInnerCircle), "Circle inner", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000130<<8)+7, offsetof(CEnemySpawner, m_fOuterCircle), "Circle outer", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000130<<8)+9, offsetof(CEnemySpawner, m_tmDelay), "Delay initial", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000130<<8)+16, offsetof(CEnemySpawner, m_tmSingleWait), "Delay single", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000130<<8)+5, offsetof(CEnemySpawner, m_tmGroupWait), "Delay group", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000130<<8)+17, offsetof(CEnemySpawner, m_ctGroupSize), "Count group", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000130<<8)+8, offsetof(CEnemySpawner, m_ctTotal), "Count total", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000130<<8)+13, offsetof(CEnemySpawner, m_penPatrol), "Patrol target", 'P', C_lGREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EnemySpawnerType_enum, (0x00000130<<8)+15, offsetof(CEnemySpawner, m_estType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000130<<8)+18, offsetof(CEnemySpawner, m_bTelefrag), "Telefrag", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000130<<8)+19, offsetof(CEnemySpawner, m_bSpawnEffect), "SpawnEffect", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000130<<8)+20, offsetof(CEnemySpawner, m_bDoubleInSerious), "Double in serious mode", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000130<<8)+21, offsetof(CEnemySpawner, m_penSeriousTarget), "Template for Serious", 0, C_RED | 0x20, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000130<<8)+22, offsetof(CEnemySpawner, m_bFirstPass), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000130<<8)+50, offsetof(CEnemySpawner, m_soSpawn), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000130<<8)+51, offsetof(CEnemySpawner, m_iInGroup), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000130<<8)+52, offsetof(CEnemySpawner, m_iEnemiesTriggered), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000130<<8)+60, offsetof(CEnemySpawner, m_penTacticsHolder), "Tactics Holder", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000130<<8)+61, offsetof(CEnemySpawner, m_bTacticsAutostart), "Tactics autostart", 0, 0x7F0000FFUL, 0), +}; +#define CEnemySpawner_propertiesct ARRAYCOUNT(CEnemySpawner_properties) + +CEntityComponent CEnemySpawner_components[] = { +#define MODEL_ENEMYSPAWNER ((0x00000130<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_ENEMYSPAWNER, "EFNM" "Models\\Editor\\EnemySpawner.mdl"), +#define TEXTURE_ENEMYSPAWNER ((0x00000130<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_ENEMYSPAWNER, "EFNM" "Models\\Editor\\EnemySpawner.tex"), +#define CLASS_BASIC_EFFECT ((0x00000130<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +}; +#define CEnemySpawner_componentsct ARRAYCOUNT(CEnemySpawner_components) + +CEventHandlerEntry CEnemySpawner_handlers[] = { + {0x01300000, -1, CEntity::pEventHandler(&CEnemySpawner:: +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +SpawnGroup),DEBUGSTRING("CEnemySpawner::SpawnGroup")}, + {0x01300001, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300001_SpawnGroup_01), DEBUGSTRING("CEnemySpawner::H0x01300001_SpawnGroup_01")}, + {0x01300002, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300002_SpawnGroup_02), DEBUGSTRING("CEnemySpawner::H0x01300002_SpawnGroup_02")}, + {0x01300003, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300003_SpawnGroup_03), DEBUGSTRING("CEnemySpawner::H0x01300003_SpawnGroup_03")}, + {0x01300004, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300004_SpawnGroup_04), DEBUGSTRING("CEnemySpawner::H0x01300004_SpawnGroup_04")}, + {0x01300005, -1, CEntity::pEventHandler(&CEnemySpawner:: +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Simple),DEBUGSTRING("CEnemySpawner::Simple")}, + {0x01300006, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300006_Simple_01), DEBUGSTRING("CEnemySpawner::H0x01300006_Simple_01")}, + {0x01300007, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300007_Simple_02), DEBUGSTRING("CEnemySpawner::H0x01300007_Simple_02")}, + {0x01300008, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300008_Simple_03), DEBUGSTRING("CEnemySpawner::H0x01300008_Simple_03")}, + {0x01300009, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300009_Simple_04), DEBUGSTRING("CEnemySpawner::H0x01300009_Simple_04")}, + {0x0130000a, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130000a_Simple_05), DEBUGSTRING("CEnemySpawner::H0x0130000a_Simple_05")}, + {0x0130000b, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130000b_Simple_06), DEBUGSTRING("CEnemySpawner::H0x0130000b_Simple_06")}, + {0x0130000c, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130000c_Simple_07), DEBUGSTRING("CEnemySpawner::H0x0130000c_Simple_07")}, + {0x0130000d, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130000d_Simple_08), DEBUGSTRING("CEnemySpawner::H0x0130000d_Simple_08")}, + {0x0130000e, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130000e_Simple_09), DEBUGSTRING("CEnemySpawner::H0x0130000e_Simple_09")}, + {0x0130000f, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130000f_Simple_10), DEBUGSTRING("CEnemySpawner::H0x0130000f_Simple_10")}, + {0x01300010, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300010_Simple_11), DEBUGSTRING("CEnemySpawner::H0x01300010_Simple_11")}, + {0x01300011, -1, CEntity::pEventHandler(&CEnemySpawner:: +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Teleporter),DEBUGSTRING("CEnemySpawner::Teleporter")}, + {0x01300012, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300012_Teleporter_01), DEBUGSTRING("CEnemySpawner::H0x01300012_Teleporter_01")}, + {0x01300013, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300013_Teleporter_02), DEBUGSTRING("CEnemySpawner::H0x01300013_Teleporter_02")}, + {0x01300014, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300014_Teleporter_03), DEBUGSTRING("CEnemySpawner::H0x01300014_Teleporter_03")}, + {0x01300015, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300015_Teleporter_04), DEBUGSTRING("CEnemySpawner::H0x01300015_Teleporter_04")}, + {0x01300016, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300016_Teleporter_05), DEBUGSTRING("CEnemySpawner::H0x01300016_Teleporter_05")}, + {0x01300017, -1, CEntity::pEventHandler(&CEnemySpawner:: +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Respawner),DEBUGSTRING("CEnemySpawner::Respawner")}, + {0x01300018, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300018_Respawner_01), DEBUGSTRING("CEnemySpawner::H0x01300018_Respawner_01")}, + {0x01300019, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300019_Respawner_02), DEBUGSTRING("CEnemySpawner::H0x01300019_Respawner_02")}, + {0x0130001a, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130001a_Respawner_03), DEBUGSTRING("CEnemySpawner::H0x0130001a_Respawner_03")}, + {0x0130001b, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130001b_Respawner_04), DEBUGSTRING("CEnemySpawner::H0x0130001b_Respawner_04")}, + {0x0130001c, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130001c_Respawner_05), DEBUGSTRING("CEnemySpawner::H0x0130001c_Respawner_05")}, + {0x0130001d, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130001d_Respawner_06), DEBUGSTRING("CEnemySpawner::H0x0130001d_Respawner_06")}, + {0x0130001e, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130001e_Respawner_07), DEBUGSTRING("CEnemySpawner::H0x0130001e_Respawner_07")}, + {0x0130001f, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130001f_Respawner_08), DEBUGSTRING("CEnemySpawner::H0x0130001f_Respawner_08")}, + {0x01300020, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300020_Respawner_09), DEBUGSTRING("CEnemySpawner::H0x01300020_Respawner_09")}, + {0x01300021, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300021_Respawner_10), DEBUGSTRING("CEnemySpawner::H0x01300021_Respawner_10")}, + {0x01300022, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300022_Respawner_11), DEBUGSTRING("CEnemySpawner::H0x01300022_Respawner_11")}, + {0x01300023, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300023_Respawner_12), DEBUGSTRING("CEnemySpawner::H0x01300023_Respawner_12")}, + {0x01300024, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300024_Respawner_13), DEBUGSTRING("CEnemySpawner::H0x01300024_Respawner_13")}, + {0x01300025, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300025_Respawner_14), DEBUGSTRING("CEnemySpawner::H0x01300025_Respawner_14")}, + {0x01300026, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300026_Respawner_15), DEBUGSTRING("CEnemySpawner::H0x01300026_Respawner_15")}, + {0x01300027, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300027_Respawner_16), DEBUGSTRING("CEnemySpawner::H0x01300027_Respawner_16")}, + {0x01300028, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300028_Respawner_17), DEBUGSTRING("CEnemySpawner::H0x01300028_Respawner_17")}, + {0x01300029, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300029_Respawner_18), DEBUGSTRING("CEnemySpawner::H0x01300029_Respawner_18")}, + {0x0130002a, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130002a_Respawner_19), DEBUGSTRING("CEnemySpawner::H0x0130002a_Respawner_19")}, + {0x0130002b, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130002b_Respawner_20), DEBUGSTRING("CEnemySpawner::H0x0130002b_Respawner_20")}, + {0x0130002c, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130002c_Respawner_21), DEBUGSTRING("CEnemySpawner::H0x0130002c_Respawner_21")}, + {0x0130002d, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130002d_Respawner_22), DEBUGSTRING("CEnemySpawner::H0x0130002d_Respawner_22")}, + {0x0130002e, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130002e_Respawner_23), DEBUGSTRING("CEnemySpawner::H0x0130002e_Respawner_23")}, + {0x0130002f, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130002f_Respawner_24), DEBUGSTRING("CEnemySpawner::H0x0130002f_Respawner_24")}, + {0x01300030, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300030_Respawner_25), DEBUGSTRING("CEnemySpawner::H0x01300030_Respawner_25")}, + {0x01300031, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300031_Respawner_26), DEBUGSTRING("CEnemySpawner::H0x01300031_Respawner_26")}, + {0x01300032, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300032_Respawner_27), DEBUGSTRING("CEnemySpawner::H0x01300032_Respawner_27")}, + {0x01300033, -1, CEntity::pEventHandler(&CEnemySpawner:: +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +DestroyableInactive),DEBUGSTRING("CEnemySpawner::DestroyableInactive")}, + {0x01300034, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300034_DestroyableInactive_01), DEBUGSTRING("CEnemySpawner::H0x01300034_DestroyableInactive_01")}, + {0x01300035, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300035_DestroyableInactive_02), DEBUGSTRING("CEnemySpawner::H0x01300035_DestroyableInactive_02")}, + {0x01300036, -1, CEntity::pEventHandler(&CEnemySpawner:: +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +DestroyableActiveSpawning),DEBUGSTRING("CEnemySpawner::DestroyableActiveSpawning")}, + {0x01300037, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300037_DestroyableActiveSpawning_01), DEBUGSTRING("CEnemySpawner::H0x01300037_DestroyableActiveSpawning_01")}, + {0x01300038, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300038_DestroyableActiveSpawning_02), DEBUGSTRING("CEnemySpawner::H0x01300038_DestroyableActiveSpawning_02")}, + {0x01300039, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300039_DestroyableActiveSpawning_03), DEBUGSTRING("CEnemySpawner::H0x01300039_DestroyableActiveSpawning_03")}, + {0x0130003a, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130003a_DestroyableActiveSpawning_04), DEBUGSTRING("CEnemySpawner::H0x0130003a_DestroyableActiveSpawning_04")}, + {0x0130003b, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130003b_DestroyableActiveSpawning_05), DEBUGSTRING("CEnemySpawner::H0x0130003b_DestroyableActiveSpawning_05")}, + {0x0130003c, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130003c_DestroyableActiveSpawning_06), DEBUGSTRING("CEnemySpawner::H0x0130003c_DestroyableActiveSpawning_06")}, + {0x0130003d, -1, CEntity::pEventHandler(&CEnemySpawner:: +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +DestroyableActive),DEBUGSTRING("CEnemySpawner::DestroyableActive")}, + {0x0130003e, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130003e_DestroyableActive_01), DEBUGSTRING("CEnemySpawner::H0x0130003e_DestroyableActive_01")}, + {0x0130003f, -1, CEntity::pEventHandler(&CEnemySpawner::H0x0130003f_DestroyableActive_02), DEBUGSTRING("CEnemySpawner::H0x0130003f_DestroyableActive_02")}, + {0x01300040, -1, CEntity::pEventHandler(&CEnemySpawner:: +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Destroyable),DEBUGSTRING("CEnemySpawner::Destroyable")}, + {0x01300041, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300041_Destroyable_01), DEBUGSTRING("CEnemySpawner::H0x01300041_Destroyable_01")}, + {0x01300042, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300042_Destroyable_02), DEBUGSTRING("CEnemySpawner::H0x01300042_Destroyable_02")}, + {1, -1, CEntity::pEventHandler(&CEnemySpawner:: +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/EnemySpawner.es" +Main),DEBUGSTRING("CEnemySpawner::Main")}, + {0x01300043, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300043_Main_01), DEBUGSTRING("CEnemySpawner::H0x01300043_Main_01")}, + {0x01300044, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300044_Main_02), DEBUGSTRING("CEnemySpawner::H0x01300044_Main_02")}, + {0x01300045, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300045_Main_03), DEBUGSTRING("CEnemySpawner::H0x01300045_Main_03")}, + {0x01300046, -1, CEntity::pEventHandler(&CEnemySpawner::H0x01300046_Main_04), DEBUGSTRING("CEnemySpawner::H0x01300046_Main_04")}, +}; +#define CEnemySpawner_handlersct ARRAYCOUNT(CEnemySpawner_handlers) + +CEntity *CEnemySpawner_New(void) { return new CEnemySpawner; }; +void CEnemySpawner_OnInitClass(void) {}; +void CEnemySpawner_OnEndClass(void) {}; +void CEnemySpawner_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEnemySpawner_OnWorldEnd(CWorld *pwo) {}; +void CEnemySpawner_OnWorldInit(CWorld *pwo) {}; +void CEnemySpawner_OnWorldTick(CWorld *pwo) {}; +void CEnemySpawner_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEnemySpawner, CRationalEntity, "Enemy Spawner", "Thumbnails\\EnemySpawner.tbn", 0x00000130); +DECLARE_CTFILENAME(_fnmCEnemySpawner_tbn, "Thumbnails\\EnemySpawner.tbn"); diff --git a/Sources/EntitiesMP/EntitiesMP.vcxproj b/Sources/EntitiesMP/EntitiesMP.vcxproj new file mode 100644 index 0000000..402445e --- /dev/null +++ b/Sources/EntitiesMP/EntitiesMP.vcxproj @@ -0,0 +1,2662 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + + + MFCProj + {D9F67AA1-970A-BFDD-6BE9-BD0CDCE98A10} + + + + Application + v120 + Unicode + + + DynamicLibrary + Dynamic + v120 + Unicode + + + DynamicLibrary + Dynamic + Unicode + v120 + + + + + + + + + + + + + + + + + + Release\ + Release\ + false + $(SolutionDir)..\Bin;$(ExecutablePath) + $(SolutionDir);$(SolutionDir)EntitiesMP;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + $(ProjectName) + + + Debug\ + Debug\ + false + $(SolutionDir)..\Bin\Debug;$(ExecutablePath) + $(SolutionDir);$(SolutionDir)Engine\;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin\Debug;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + $(ProjectName)D + + + + MultiThreadedDLL + OnlyExplicitInline + false + MaxSpeed + true + Level3 + Speed + true + false + true + WIN32;NDEBUG;_WINDOWS;_WINDLL;_USRDLL;_USE_32BIT_TIME_T;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\EntitiesMP.pch + Use + StdH.h + .\Release\ + .\Release\ + 4996;4333 + + + true + NDEBUG;%(PreprocessorDefinitions) + .\Release\EntitiesMP.tlb + true + Win32 + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\EntitiesMP.bsc + + + true + true + true + Windows + Release\EntitiesMP.dll + .\Release\EntitiesMP.lib + + + copy Release\$(TargetName).dll $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).lib $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to \Bin + $(SolutionDir)..\Bin\$(InputName).dll;%(Outputs) + + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + WIN32;_DEBUG;_WINDOWS;_WINDLL;_USE_32BIT_TIME_T;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + Debug\ + .\Debug\EntitiesMP.pch + Use + StdH.h + Debug\ + Debug\ + 4996;4333 + + + true + _DEBUG;%(PreprocessorDefinitions) + .\Debug\EntitiesMP.tlb + true + Win32 + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\EntitiesMP.bsc + + + true + true + true + Windows + Debug/EntitiesMPD.dll + .\Debug\EntitiesMPD.lib + EngineD.lib;%(AdditionalDependencies) + + + copy Debug\$(TargetName).dll $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).lib $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to \Bin\Debug + $(SolutionDir)..\Bin\Debug\$(InputName).dll;%(Outputs) + + + + + + + + + + Create + StdH.h + Create + StdH.h + + + + true + + + true + true + + + + + + + + + + + + + + + + + + + + + + + true + true + + + + + + + + + true + true + + + true + true + + + + + + + + + + + + true + true + + + + + + + + + + + + + + + + + + + + + + + true + true + + + + + true + true + + + + + + + + + + + + + + true + true + + + + + + + + + true + true + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + + + true + true + + + + + + + + + + + + + + + true + true + + + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Use + StdH.h + Use + StdH.h + + + + + + + + + + + + + + + + true + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + + + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + Document + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + cd $(SolutionDir) +ecc EntitiesMP/%(Filename).es + EntitiesMP/%(Filename).es + %(Filename).cpp;%(Outputs) + + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + Document + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Sources/EntitiesMP/EntitiesMP.vcxproj.filters b/Sources/EntitiesMP/EntitiesMP.vcxproj.filters new file mode 100644 index 0000000..de71878 --- /dev/null +++ b/Sources/EntitiesMP/EntitiesMP.vcxproj.filters @@ -0,0 +1,2364 @@ + + + + + {e7d59bc4-af0d-42fb-80c4-0a3810d10b3b} + cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90 + + + {eff72727-f56f-4f0e-afac-b202a832273c} + + + {40c44e31-3be4-44a9-8aef-92eb0d62e66c} + h;hpp;hxx;hm;inl;fi;fd + + + {b1b59106-4305-4614-9d3a-a199972e8e55} + + + {d652878a-c578-4041-b62b-f0edb3642a60} + es + + + {15e23bb9-693a-4bc5-884f-56deebba6370} + es + + + {a2bbac85-6836-400a-808a-fe3b3e2fc728} + es + + + {2ae3f057-e63c-47f1-93e5-a85f7712842a} + es + + + {80a55b57-0a3c-4e6e-877c-499b03e05fef} + es + + + {bd7d8803-b844-4ab6-9ca5-c53fc8711029} + es + + + {57aa098f-2862-44ef-a6cf-3bdc5620a09f} + es + + + {718f2278-5d32-45f7-af15-7e3aaf411822} + es + + + {bd9fdc67-9e8f-47b1-b6e0-3e745f85d39a} + es + + + {306a9fdd-9552-40eb-b911-73bcd3cc4ef0} + es + + + {e16e502e-9450-4331-8926-8687b03c9153} + ecl + + + {7a1dcaf7-0837-41e6-9e0c-6a85f796cc5c} + + + + + Source Files\Common sources + + + Source Files\Common sources + + + Source Files\Common sources + + + Source Files\Common sources + + + Source Files\Common sources + + + Source Files\Common sources + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files\Common headers + + + Header Files\Common headers + + + Header Files\Common headers + + + Header Files\Common headers + + + Header Files\Common headers + + + Header Files\Common headers + + + Header Files\Common headers + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Class Files\AI + + + Class Files\AI + + + Class Files\AI + + + Class Files\AI + + + Class Files\AI + + + Class Files\AI + + + Class Files\AI + + + Class Files\Brushes + + + Class Files\Brushes + + + Class Files\Brushes + + + Class Files\Brushes + + + Class Files\Brushes + + + Class Files\Brushes + + + Class Files\Brushes + + + Class Files\Brushes + + + Class Files\Brushes + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Effects + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Enemies + + + Class Files\Environment + + + Class Files\Environment + + + Class Files\Environment + + + Class Files\Items + + + Class Files\Items + + + Class Files\Items + + + Class Files\Items + + + Class Files\Items + + + Class Files\Items + + + Class Files\Items + + + Class Files\Items + + + Class Files\Items + + + Class Files\Players + + + Class Files\Players + + + Class Files\Players + + + Class Files\Players + + + Class Files\Players + + + Class Files\Players + + + Class Files\Players + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Tools + + + Class Files\Weapons + + + Class Files\Weapons + + + Class Files\Weapons + + + Class Files\Weapons + + + Class Files\Weapons + + + Class Files\Weapons + + + Class Files\Weapons + + + Class Files\Weapons + + + Class Files\Weapons + + + Class Files\Weapons + + + Class Files\Weapons + + + Class Files + + + Class Files + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Links To Package + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + Messages + + + \ No newline at end of file diff --git a/Sources/EntitiesMP/EntitiesMP.vcxproj.user b/Sources/EntitiesMP/EntitiesMP.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/Sources/EntitiesMP/EntitiesMP.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Sources/EntitiesMP/EnvironmentBase.cpp b/Sources/EntitiesMP/EnvironmentBase.cpp new file mode 100644 index 0000000..e1d25d5 --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentBase.cpp @@ -0,0 +1,601 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" + +#include "StdH.h" + +#include +#include +void CEnvironmentBase::SetDefaultProperties(void) { + m_strName = "Base Environment"; + m_strDescription = ""; + m_fDistance = 100.0f; + m_fStretch = 1.0f; + m_penTarget = NULL; + m_penWatcher = NULL; + m_fWatcherFrequency = 2.0f; + m_vDesiredPosition = FLOAT3D(0 , 0 , 0); + m_fMoveSpeed = 2.0f; + m_fRotateSpeed = 60.0f; + m_fMoveFrequency = 0.5f; + m_bUseWatcher = FALSE ; + m_bFlying = FALSE ; + m_fWaitTime = 0.0f; + m_fnMdl = CTFILENAME("Models\\Editor\\Axis.mdl"); + m_fnTex = CTString(""); + m_iAnim = 0; + m_fnAtt1Mdl = CTString(""); + m_fnAtt1Tex = CTString(""); + m_iAtt1Position = 0; + m_iAtt1Anim = 0; + m_fnAtt2Mdl = CTString(""); + m_fnAtt2Tex = CTString(""); + m_iAtt2Position = 1; + m_iAtt2Anim = 0; + m_fnAtt3Mdl = CTString(""); + m_fnAtt3Tex = CTString(""); + m_iAtt3Position = 1; + m_iAtt3Anim = 0; + CMovableEntity::SetDefaultProperties(); +} + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +BOOL CEnvironmentBase::MovesByTargetedRoute(CTString & strTargetProperty)const { +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +strTargetProperty = "Target"; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return TRUE ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +BOOL CEnvironmentBase::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +fnmMarkerClass = CTFILENAME ("Classes\\EnvironmentMarker.ecl"); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +strTargetProperty = "Target"; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return TRUE ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +const CTString & CEnvironmentBase::GetDescription(void)const { +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(m_penTarget != NULL ){ +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , m_penTarget -> GetName ()); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return m_strDescription ; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CAnimData * CEnvironmentBase::GetAnimData(SLONG slPropertyOffset) { +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(slPropertyOffset == offsetof (CEnvironmentBase , m_iAnim )){ +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return GetModelObject () -> GetData (); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}else if(slPropertyOffset == offsetof (CEnvironmentBase , m_iAtt1Anim )){ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CAttachmentModelObject * pamo = GetModelObject () -> GetAttachmentModel (m_iAtt1Position ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(pamo != NULL ){return pamo -> amo_moModelObject . GetData ();} +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return CEntity :: GetAnimData (slPropertyOffset ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}else if(slPropertyOffset == offsetof (CEnvironmentBase , m_iAtt2Anim )){ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CAttachmentModelObject * pamo = GetModelObject () -> GetAttachmentModel (m_iAtt2Position ); +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(pamo != NULL ){return pamo -> amo_moModelObject . GetData ();} +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return CEntity :: GetAnimData (slPropertyOffset ); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}else if(slPropertyOffset == offsetof (CEnvironmentBase , m_iAtt3Anim )){ +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CAttachmentModelObject * pamo = GetModelObject () -> GetAttachmentModel (m_iAtt3Position ); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(pamo != NULL ){return pamo -> amo_moModelObject . GetData ();} +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return CEntity :: GetAnimData (slPropertyOffset ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}else { +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return CEntity :: GetAnimData (slPropertyOffset ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +BOOL CEnvironmentBase::NextMarker(void) { +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(m_penTarget == NULL ){ +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return FALSE ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(m_penTarget != NULL && ! IsOfClass (m_penTarget , "Environment Marker")){ +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +WarningMessage ("Target '%s' is not of Environment Marker class!" , m_penTarget -> GetName ()); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_penTarget = NULL ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return FALSE ; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CMarker * penTarget = (CMarker *) (CEntity *) m_penTarget ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CMarker * penNextTarget = (CMarker *) (CEntity *) penTarget -> m_penTarget ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(penNextTarget == NULL ){ +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return FALSE ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_penTarget = penNextTarget ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return TRUE ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CEnvironmentBase::CalcRotation(ANGLE aWantedHeadingRelative,ANGLE3D & aRotation) { +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +aWantedHeadingRelative = NormalizeAngle (aWantedHeadingRelative ); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(aWantedHeadingRelative < - m_fRotateSpeed * m_fMoveFrequency ){ +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +aRotation (1) = - m_fRotateSpeed ; +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}else if(aWantedHeadingRelative > m_fRotateSpeed * m_fMoveFrequency ){ +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +aRotation (1) = + m_fRotateSpeed ; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}else { +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +aRotation (1) = aWantedHeadingRelative / m_fMoveFrequency ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CEnvironmentBase::StopMoving(void) { +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CEnvironmentBase::MoveToPosition(void) { +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +FLOAT3D vDesiredAngle ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +vDesiredAngle = (m_vDesiredPosition - GetPlacement () . pl_PositionVector ) . Normalize (); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +ANGLE3D aRotation (0 , 0 , 0); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CalcRotation (GetRelativeHeading (vDesiredAngle ) , aRotation ); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +FLOAT3D vTranslation (0.0f , 0.0f , 0.0f); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +vTranslation (3) = - m_fMoveSpeed ; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(m_bFlying ){ +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +vTranslation (2) = Sgn (vDesiredAngle (2)) * m_fMoveSpeed / 10; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetDesiredRotation (aRotation ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetDesiredTranslation (vTranslation ); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CEnvironmentBase::CalcDestination() { +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +FLOAT fR = FRnd () * ((CEnvironmentMarker &) * m_penTarget ) . m_fMarkerRange ; +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +FLOAT fA = FRnd () * 360.0f; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_vDesiredPosition = m_penTarget -> GetPlacement () . pl_PositionVector + +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +FLOAT3D (CosFast (fA ) * fR , 0 , SinFast (fA ) * fR ); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CEnvironmentBase::MarkerParameters() { +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(m_penTarget != NULL ){ +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CEnvironmentMarker & em = (CEnvironmentMarker &) * m_penTarget ; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(em . m_fMoveSpeed > 0.0f){ +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_fMoveSpeed = em . m_fMoveSpeed ; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(em . m_fRotateSpeed > 0.0f){ +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_fRotateSpeed = em . m_fRotateSpeed ; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CEnvironmentBase::Initialize(void) { +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +InitAsModel (); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetPhysicsFlags (EPF_MODEL_WALKING & ~ (EPF_ORIENTEDBYGRAVITY | EPF_TRANSLATEDBYGRAVITY )); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetCollisionFlags (ECF_MODEL ); +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +GetModelObject () -> mo_Stretch = FLOAT3D (m_fStretch , m_fStretch , m_fStretch ); +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetModel (m_fnMdl ); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +GetModelObject () -> PlayAnim (m_iAnim , AOF_LOOPING ); +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(m_fnTex != CTString ("")){ +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +GetModelObject () -> mo_toTexture . SetData_t (m_fnTex ); +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +GetModelObject () -> RemoveAllAttachmentModels (); +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +AddAttachment (m_iAtt1Position , m_fnAtt1Mdl , m_fnAtt1Tex ); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CAttachmentModelObject * pamo = GetModelObject () -> GetAttachmentModel (m_iAtt1Position ); +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(pamo != NULL ){ +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +pamo -> amo_moModelObject . StartAnim (m_iAtt1Anim ); +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if((m_iAtt2Position != m_iAtt1Position ) && (m_fnAtt1Mdl != m_fnAtt2Mdl )){ +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +AddAttachment (m_iAtt2Position , m_fnAtt2Mdl , m_fnAtt2Tex ); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CAttachmentModelObject * pamo = GetModelObject () -> GetAttachmentModel (m_iAtt2Position ); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(pamo != NULL ){ +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +pamo -> amo_moModelObject . StartAnim (m_iAtt2Anim ); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if((m_iAtt3Position != m_iAtt1Position ) && (m_fnAtt1Mdl != m_fnAtt3Mdl ) && +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +(m_iAtt3Position != m_iAtt2Position ) && (m_fnAtt2Mdl != m_fnAtt3Mdl )){ +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +AddAttachment (m_iAtt3Position , m_fnAtt3Mdl , m_fnAtt3Tex ); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CAttachmentModelObject * pamo = GetModelObject () -> GetAttachmentModel (m_iAtt3Position ); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(pamo != NULL ){ +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +pamo -> amo_moModelObject . StartAnim (m_iAtt3Anim ); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(m_penTarget != NULL && ! IsOfClass (m_penTarget , "Environment Marker")){ +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +WarningMessage ("Target '%s' is not of Environment Marker class!" , m_penTarget -> GetName ()); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_penTarget = NULL ; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CEnvironmentBase::InitializeWatcher(FLOAT fWaitTime) { +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_penWatcher = CreateEntity (GetPlacement () , CLASS_WATCHPLAYERS ); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_penWatcher -> Initialize (EVoid ()); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CWatchPlayers & pw = (CWatchPlayers &) * m_penWatcher ; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +pw . m_penOwner = this ; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +pw . m_fWaitTime = 2.0f; +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +pw . m_fDistance = m_fDistance ; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +pw . m_bRangeWatcher = FALSE ; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +pw . m_eetEventClose = EET_ENVIRONMENTSTART ; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +pw . m_eetEventFar = EET_ENVIRONMENTSTOP ; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CEnvironmentBase::PlayDefaultAnim(void) { +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +GetModelObject () -> PlayAnim (m_iAnim , AOF_LOOPING | AOF_NORESTART ); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CEnvironmentBase::PlayMarkerAnimation(void) { +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(m_penTarget != NULL ){ +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +GetModelObject () -> PlayAnim (((CEnvironmentMarker &) * m_penTarget ) . m_iAnim , AOF_LOOPING | AOF_NORESTART ); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CEnvironmentBase::ChangeDefaultAnim(void) { +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(m_penTarget != NULL && ((CEnvironmentMarker &) * m_penTarget ) . m_bChangeDefaultAnim ){ +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_iAnim = ((CEnvironmentMarker &) * m_penTarget ) . m_iAnim ; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} + +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CEnvironmentBase::WaitOnMarker(void) { +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(m_penTarget != NULL ){ +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CEnvironmentMarker & em = (CEnvironmentMarker &) * m_penTarget ; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_fWaitTime = em . m_fWaitTime ; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_fWaitTime += FRnd () * em . m_fRandomTime ; +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(em . m_bFixedAnimLength ){ +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_fWaitTime = floor (m_fWaitTime + 0.5f); +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +BOOL CEnvironmentBase:: +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +MoveToMarker(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnvironmentBase_MoveToMarker + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnvironmentBase::MoveToMarker expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(!(NextMarker ())){ Jump(STATE_CURRENT,0x03840005, FALSE, EInternal());return TRUE;} +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CalcDestination (); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Jump(STATE_CURRENT,0x03840003, FALSE, EInternal());return TRUE;}BOOL CEnvironmentBase::H0x03840003_MoveToMarker_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840003 +if(!((m_vDesiredPosition - GetPlacement () . pl_PositionVector ) . Length () > 5.0f)){ Jump(STATE_CURRENT,0x03840004, FALSE, EInternal());return TRUE;} +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetTimerAfter(m_fMoveFrequency ); +Jump(STATE_CURRENT, 0x03840001, FALSE, EBegin());return TRUE;}BOOL CEnvironmentBase::H0x03840001_MoveToMarker_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +MoveToPosition (); +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return TRUE; +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x03840002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}return TRUE;}BOOL CEnvironmentBase::H0x03840002_MoveToMarker_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840002 +Jump(STATE_CURRENT,0x03840003, FALSE, EInternal());return TRUE; +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}BOOL CEnvironmentBase::H0x03840004_MoveToMarker_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840004 +Jump(STATE_CURRENT,0x03840005, FALSE, EInternal());return TRUE;}BOOL CEnvironmentBase::H0x03840005_MoveToMarker_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840005 + +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +StopMoving (); +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Return(STATE_CURRENT,EEnd ()); +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnvironmentBase:: +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Activate(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnvironmentBase_Activate + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnvironmentBase::Activate expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x03840007, FALSE, EBegin());return TRUE;}BOOL CEnvironmentBase::H0x03840007_Activate_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840007 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +Call(STATE_CURRENT, STATE_CEnvironmentBase_DoAction, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EEnvironmentStop):{const EEnvironmentStop&e= (EEnvironmentStop&)__eeInput; +Jump(STATE_CURRENT, STATE_CEnvironmentBase_Stop, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}return TRUE;}BOOL CEnvironmentBase::H0x03840008_Activate_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840008 + ASSERT(FALSE); return TRUE;};BOOL CEnvironmentBase:: +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Stop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnvironmentBase_Stop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnvironmentBase::Stop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +StopMoving (); +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x0384000a, FALSE, EBegin());return TRUE;}BOOL CEnvironmentBase::H0x0384000a_Stop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0384000a +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EEnvironmentStart):{const EEnvironmentStart&e= (EEnvironmentStart&)__eeInput; +Jump(STATE_CURRENT, STATE_CEnvironmentBase_Activate, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}return TRUE;}BOOL CEnvironmentBase::H0x0384000b_Stop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0384000b + ASSERT(FALSE); return TRUE;};BOOL CEnvironmentBase:: +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +DoAction(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnvironmentBase_DoAction + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnvironmentBase::DoAction expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Jump(STATE_CURRENT,0x03840015, FALSE, EInternal());return TRUE;}BOOL CEnvironmentBase::H0x03840015_DoAction_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840015 +if(!(TRUE )){ Jump(STATE_CURRENT,0x03840016, FALSE, EInternal());return TRUE;} +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +WaitOnMarker (); +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(!(m_fWaitTime > 0.0f)){ Jump(STATE_CURRENT,0x0384000f, FALSE, EInternal());return TRUE;} +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +PlayMarkerAnimation (); +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetTimerAfter(m_fWaitTime ); +Jump(STATE_CURRENT, 0x0384000d, FALSE, EBegin());return TRUE;}BOOL CEnvironmentBase::H0x0384000d_DoAction_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0384000d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0384000e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnvironmentBase::H0x0384000e_DoAction_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0384000e +;Jump(STATE_CURRENT,0x0384000f, FALSE, EInternal());return TRUE;}BOOL CEnvironmentBase::H0x0384000f_DoAction_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0384000f + +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +ChangeDefaultAnim (); +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +MarkerParameters (); +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +PlayDefaultAnim (); +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +STATE_CEnvironmentBase_MoveToMarker, TRUE; +Jump(STATE_CURRENT, 0x03840010, FALSE, EBegin());return TRUE;}BOOL CEnvironmentBase::H0x03840010_DoAction_04(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840010 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnvironmentBase_MoveToMarker, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x03840011, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnvironmentBase::H0x03840011_DoAction_05(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840011 +const EEnd&__e= (EEnd&)__eeInput; +; +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(!(m_penTarget == NULL || ((CEnvironmentMarker &) * m_penTarget ) . m_penTarget == NULL )){ Jump(STATE_CURRENT,0x03840014, FALSE, EInternal());return TRUE;} +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x03840012, FALSE, EBegin());return TRUE;}BOOL CEnvironmentBase::H0x03840012_DoAction_06(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840012 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x03840013, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnvironmentBase::H0x03840013_DoAction_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840013 +;Jump(STATE_CURRENT,0x03840014, FALSE, EInternal());return TRUE;}BOOL CEnvironmentBase::H0x03840014_DoAction_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840014 +Jump(STATE_CURRENT,0x03840015, FALSE, EInternal());return TRUE; +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +}BOOL CEnvironmentBase::H0x03840016_DoAction_10(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840016 + ASSERT(FALSE); return TRUE;};BOOL CEnvironmentBase:: +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +MainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnvironmentBase_MainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnvironmentBase::MainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +STATE_CEnvironmentBase_Stop, TRUE; +Jump(STATE_CURRENT, 0x03840018, FALSE, EBegin());return TRUE;}BOOL CEnvironmentBase::H0x03840018_MainLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840018 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnvironmentBase_Stop, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x03840019, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CEnvironmentBase::H0x03840019_MainLoop_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x03840019 +const EEnd&__e= (EEnd&)__eeInput; +; +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_penWatcher -> SendEvent (EEnd ()); +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Destroy (); +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Return(STATE_CURRENT,EVoid()); +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEnvironmentBase:: +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnvironmentBase_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnvironmentBase::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Initialize (); +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +SetTimerAfter(FRnd () * 2.0f + 1.0f); +Jump(STATE_CURRENT, 0x0384001a, FALSE, EBegin());return TRUE;}BOOL CEnvironmentBase::H0x0384001a_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0384001a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0384001b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEnvironmentBase::H0x0384001b_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0384001b +; +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +if(m_bUseWatcher ){ +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +InitializeWatcher (m_fWatcherFrequency ); +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +} +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +m_strDescription = "Environment base"; +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Jump(STATE_CURRENT, STATE_CEnvironmentBase_MainLoop, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EnvironmentBase.es b/Sources/EntitiesMP/EnvironmentBase.es new file mode 100644 index 0000000..97add26 --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentBase.es @@ -0,0 +1,418 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +900 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/EnvironmentMarker"; +uses "EntitiesMP/WatchPlayers"; + +class CEnvironmentBase: CMovableEntity { +name "Environment Base"; +thumbnail "Thumbnails\\EnvironmentBase.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "Base Environment", + 2 CTString m_strDescription = "", + 3 RANGE m_fDistance "Range" 'R' = 100.0f, // distance when player is seen + 4 FLOAT m_fStretch "Stretch" 'S' = 1.0f, + + 5 CEntityPointer m_penTarget "Target" 'T', + 6 CEntityPointer m_penWatcher, + 7 FLOAT m_fWatcherFrequency "Watcher frequency" = 2.0f, // watcher will look every x seconds for players + 8 FLOAT3D m_vDesiredPosition = FLOAT3D(0, 0, 0), // desired position for moving + + 10 FLOAT m_fMoveSpeed "Move speed" 'V' = 2.0f, + 11 FLOAT m_fRotateSpeed "Rotate speed" 'B' = 60.0f, + 12 FLOAT m_fMoveFrequency "Move frequency" = 0.5f, + 13 BOOL m_bUseWatcher "Use watcher" = FALSE, // use individual watcher + 14 BOOL m_bFlying "Flying" 'F' = FALSE, // flying model + 16 FLOAT m_fWaitTime = 0.0f, + + 20 CTFileName m_fnMdl "Model" 'M' = CTFILENAME("Models\\Editor\\Axis.mdl"), + 21 CTFileName m_fnTex "Texture" 'X' = CTString(""), + 22 ANIMATION m_iAnim "Animation" =0, + + 25 CTFileName m_fnAtt1Mdl "Attachment 1 Model" = CTString(""), + 26 CTFileName m_fnAtt1Tex "Attachment 1 Texture" = CTString(""), + 27 INDEX m_iAtt1Position "Attachment 1 position"=0, + 28 ANIMATION m_iAtt1Anim "Attachment 1 animation"=0, + + 30 CTFileName m_fnAtt2Mdl "Attachment 2 Model" = CTString(""), + 31 CTFileName m_fnAtt2Tex "Attachment 2 Texture" = CTString(""), + 32 INDEX m_iAtt2Position "Attachment 2 position"=1, + 33 ANIMATION m_iAtt2Anim "Attachment 2 animation"=0, + + 35 CTFileName m_fnAtt3Mdl "Attachment 3 Model" = CTString(""), + 36 CTFileName m_fnAtt3Tex "Attachment 3 Texture" = CTString(""), + 37 INDEX m_iAtt3Position "Attachment 3 position"=1, + 38 ANIMATION m_iAtt3Anim "Attachment 3 animation"=0, + +components: + 1 class CLASS_WATCHPLAYERS "Classes\\WatchPlayers.ecl", + +functions: + /* Check if entity is moved on a route set up by its targets. */ + BOOL MovesByTargetedRoute(CTString &strTargetProperty) const { + strTargetProperty = "Target"; + return TRUE; + }; + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\EnvironmentMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + }; + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("->"); + if (m_penTarget!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", m_penTarget->GetName()); + } + return m_strDescription; + }; + /* Get anim data for given animation property - return NULL for none. */ + CAnimData *GetAnimData(SLONG slPropertyOffset) { + if(slPropertyOffset==offsetof(CEnvironmentBase, m_iAnim)) { + return GetModelObject()->GetData(); + + } else if(slPropertyOffset==offsetof(CEnvironmentBase, m_iAtt1Anim)) { + CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel(m_iAtt1Position); + if( pamo != NULL) { return pamo->amo_moModelObject.GetData(); } + return CEntity::GetAnimData(slPropertyOffset); + + } else if(slPropertyOffset==offsetof(CEnvironmentBase, m_iAtt2Anim)) { + CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel(m_iAtt2Position); + if( pamo != NULL) { return pamo->amo_moModelObject.GetData(); } + return CEntity::GetAnimData(slPropertyOffset); + + } else if(slPropertyOffset==offsetof(CEnvironmentBase, m_iAtt3Anim)) { + CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel(m_iAtt3Position); + if( pamo != NULL) { return pamo->amo_moModelObject.GetData(); } + return CEntity::GetAnimData(slPropertyOffset); + + } else { + return CEntity::GetAnimData(slPropertyOffset); + } + }; + + + +/************************************************************ + * MOVE FUNCTIONS * + ************************************************************/ + // switch to next marker + BOOL NextMarker(void) { + if (m_penTarget==NULL) { + return FALSE; + } + + // assure valid target + if (m_penTarget!=NULL && !IsOfClass(m_penTarget, "Environment Marker")) { + WarningMessage("Target '%s' is not of Environment Marker class!", m_penTarget->GetName()); + m_penTarget = NULL; + return FALSE; + } + + // get next marker + CMarker *penTarget = (CMarker *)(CEntity*)m_penTarget; + CMarker *penNextTarget = (CMarker *)(CEntity*)penTarget->m_penTarget; + + // if got to end + if (penNextTarget==NULL) { + return FALSE; + } + + // remember next marker as current target + m_penTarget = penNextTarget; + + return TRUE; + }; + + // calculate rotation + void CalcRotation(ANGLE aWantedHeadingRelative, ANGLE3D &aRotation) { + // normalize it to [-180,+180] degrees + aWantedHeadingRelative = NormalizeAngle(aWantedHeadingRelative); + + // if desired position is left + if (aWantedHeadingRelative<-m_fRotateSpeed*m_fMoveFrequency) { + // start turning left + aRotation(1) = -m_fRotateSpeed; + // if desired position is right + } else if (aWantedHeadingRelative>m_fRotateSpeed*m_fMoveFrequency) { + // start turning right + aRotation(1) = +m_fRotateSpeed; + // if desired position is more-less ahead + } else { + aRotation(1) = aWantedHeadingRelative/m_fMoveFrequency; + } + }; + + // stop moving + void StopMoving(void) { + SetDesiredRotation(ANGLE3D(0, 0, 0)); + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + }; + + // move to position + void MoveToPosition(void) { + FLOAT3D vDesiredAngle; + + // desired angle vector + vDesiredAngle = (m_vDesiredPosition - GetPlacement().pl_PositionVector).Normalize(); + // find relative heading towards the desired angle + ANGLE3D aRotation(0,0,0); + CalcRotation(GetRelativeHeading(vDesiredAngle), aRotation); + + // determine translation speed + FLOAT3D vTranslation(0.0f, 0.0f, 0.0f); + vTranslation(3) = -m_fMoveSpeed; + + // if flying set y axis translation speed + if (m_bFlying) { + vTranslation(2) = Sgn(vDesiredAngle(2)) * m_fMoveSpeed/10; + } + + // start moving + SetDesiredRotation(aRotation); + SetDesiredTranslation(vTranslation); + }; + + // calc destination + void CalcDestination() { + // new position to walk to + FLOAT fR = FRnd()*((CEnvironmentMarker&)*m_penTarget).m_fMarkerRange; + FLOAT fA = FRnd()*360.0f; + m_vDesiredPosition = m_penTarget->GetPlacement().pl_PositionVector + + FLOAT3D(CosFast(fA)*fR, 0, SinFast(fA)*fR); + }; + + // marker parameters + void MarkerParameters() { + if (m_penTarget != NULL) { + CEnvironmentMarker &em = (CEnvironmentMarker&)*m_penTarget; + if (em.m_fMoveSpeed > 0.0f) { + m_fMoveSpeed = em.m_fMoveSpeed; + } + if (em.m_fRotateSpeed > 0.0f) { + m_fRotateSpeed = em.m_fRotateSpeed; + } + } + }; + + + +/************************************************************ + * INITIALIZE FUNCTIONS * + ************************************************************/ + void Initialize(void) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING&~(EPF_ORIENTEDBYGRAVITY|EPF_TRANSLATEDBYGRAVITY)); + SetCollisionFlags(ECF_MODEL); + + // set model stretch -- MUST BE DONE BEFORE SETTING MODEL! + GetModelObject()->mo_Stretch = FLOAT3D( m_fStretch, m_fStretch, m_fStretch); + + // set appearance + SetModel(m_fnMdl); + GetModelObject()->PlayAnim(m_iAnim, AOF_LOOPING); + if( m_fnTex != CTString("")) { + GetModelObject()->mo_toTexture.SetData_t(m_fnTex); + } + + GetModelObject()->RemoveAllAttachmentModels(); + + AddAttachment( m_iAtt1Position, m_fnAtt1Mdl, m_fnAtt1Tex); + CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel( m_iAtt1Position); + if( pamo != NULL) { + pamo->amo_moModelObject.StartAnim( m_iAtt1Anim); + } + + if( (m_iAtt2Position != m_iAtt1Position) && (m_fnAtt1Mdl != m_fnAtt2Mdl) ) { + AddAttachment( m_iAtt2Position, m_fnAtt2Mdl, m_fnAtt2Tex); + CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel( m_iAtt2Position); + if( pamo != NULL) { + pamo->amo_moModelObject.StartAnim( m_iAtt2Anim); + } + } + + if( (m_iAtt3Position != m_iAtt1Position) && (m_fnAtt1Mdl != m_fnAtt3Mdl) && + (m_iAtt3Position != m_iAtt2Position) && (m_fnAtt2Mdl != m_fnAtt3Mdl) ) { + AddAttachment( m_iAtt3Position, m_fnAtt3Mdl, m_fnAtt3Tex); + CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel( m_iAtt3Position); + if( pamo != NULL) { + pamo->amo_moModelObject.StartAnim( m_iAtt3Anim); + } + } + + // assure valid target + if (m_penTarget!=NULL && !IsOfClass(m_penTarget, "Environment Marker")) { + WarningMessage("Target '%s' is not of Environment Marker class!", m_penTarget->GetName()); + m_penTarget = NULL; + } +}; + + +/************************************************************ + * WATCHER FUNCTIONS * + ************************************************************/ + void InitializeWatcher(FLOAT fWaitTime) { + // spawn player watcher + m_penWatcher = CreateEntity(GetPlacement(), CLASS_WATCHPLAYERS); + m_penWatcher->Initialize(EVoid()); + + // setup player watcher + CWatchPlayers &pw = (CWatchPlayers&)*m_penWatcher; + pw.m_penOwner = this; + pw.m_fWaitTime = 2.0f; + pw.m_fDistance = m_fDistance; + pw.m_bRangeWatcher = FALSE; + pw.m_eetEventClose = EET_ENVIRONMENTSTART; + pw.m_eetEventFar = EET_ENVIRONMENTSTOP; + }; + + + +/************************************************************ + * ANIMATION FUCNTIONS * + ************************************************************/ + // play default anim + void PlayDefaultAnim(void) { + GetModelObject()->PlayAnim(m_iAnim, AOF_LOOPING|AOF_NORESTART); + }; + + // play marker animation + void PlayMarkerAnimation(void) { + if (m_penTarget != NULL) { + GetModelObject()->PlayAnim(((CEnvironmentMarker&)*m_penTarget).m_iAnim, AOF_LOOPING|AOF_NORESTART); + } + }; + + // change default anim + void ChangeDefaultAnim(void) { + if (m_penTarget != NULL && ((CEnvironmentMarker&)*m_penTarget).m_bChangeDefaultAnim) { + m_iAnim = ((CEnvironmentMarker&)*m_penTarget).m_iAnim; + } + }; + + // wait on marker + void WaitOnMarker(void) { + if (m_penTarget != NULL) { + CEnvironmentMarker &em = (CEnvironmentMarker&)*m_penTarget; + m_fWaitTime = em.m_fWaitTime; // wait time + m_fWaitTime += FRnd() * em.m_fRandomTime; // random wait time + // fixed anim length + if (em.m_bFixedAnimLength) { + m_fWaitTime = floor(m_fWaitTime + 0.5f); + } + } + }; + + + +procedures: +/************************************************************ + * SUPPORT PROCEDURES * + ************************************************************/ + // move to marker + MoveToMarker(EVoid) { + // if next marker exist + if (NextMarker()) { + // destination + CalcDestination(); + // move to marker + while ((m_vDesiredPosition-GetPlacement().pl_PositionVector).Length() > 5.0f) { + wait(m_fMoveFrequency) { + on (EBegin) : { + MoveToPosition(); + resume; + } + on (ETimer) : { stop; } + } + } + } + // stop moving + StopMoving(); + return EEnd(); + }; + + + +/************************************************************ + * A C T I O N S * + ************************************************************/ + // activate + Activate(EVoid) { + wait() { + on (EBegin) : { call DoAction(); } + on (EEnvironmentStop) : { jump Stop(); } + } + }; + + // just wait + Stop(EVoid) { + StopMoving(); + wait() { + on (EBegin) : { resume; } + on (EEnvironmentStart) : { jump Activate(); } + } + }; + + // do actions + DoAction(EVoid) { + while (TRUE) { + WaitOnMarker(); + if (m_fWaitTime > 0.0f) { + PlayMarkerAnimation(); + autowait(m_fWaitTime); + } + ChangeDefaultAnim(); + + MarkerParameters(); + PlayDefaultAnim(); + autocall MoveToMarker() EEnd; + + // if no more targets wait forever in last anim (if marker anim exist otherwise in default anim) + if (m_penTarget==NULL || ((CEnvironmentMarker&)*m_penTarget).m_penTarget==NULL) { + autowait(); + } + } + }; + + + +/************************************************************ + * M A I N L O O P * + ************************************************************/ + // main loop + MainLoop(EVoid) { + autocall Stop() EEnd; + + // destroy player watcher + m_penWatcher->SendEvent(EEnd()); + + // cease to exist + Destroy(); + + return; + }; + + Main() { + // initialize + Initialize(); + + // wait until game starts + autowait(FRnd()*2.0f+1.0f); + + // initialize watcher + if (m_bUseWatcher) { + InitializeWatcher(m_fWatcherFrequency); + } + + m_strDescription = "Environment base"; + + jump MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/EnvironmentBase.h b/Sources/EntitiesMP/EnvironmentBase.h new file mode 100644 index 0000000..b6c97b6 --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentBase.h @@ -0,0 +1,140 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_EnvironmentBase_INCLUDED +#define _EntitiesMP_EnvironmentBase_INCLUDED 1 +#include +#include +extern "C" DECL_DLL CDLLEntityClass CEnvironmentBase_DLLClass; +class CEnvironmentBase : public CMovableEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + RANGE m_fDistance; + FLOAT m_fStretch; + CEntityPointer m_penTarget; + CEntityPointer m_penWatcher; + FLOAT m_fWatcherFrequency; + FLOAT3D m_vDesiredPosition; + FLOAT m_fMoveSpeed; + FLOAT m_fRotateSpeed; + FLOAT m_fMoveFrequency; + BOOL m_bUseWatcher; + BOOL m_bFlying; + FLOAT m_fWaitTime; + CTFileName m_fnMdl; + CTFileName m_fnTex; + ANIMATION m_iAnim; + CTFileName m_fnAtt1Mdl; + CTFileName m_fnAtt1Tex; + INDEX m_iAtt1Position; + ANIMATION m_iAtt1Anim; + CTFileName m_fnAtt2Mdl; + CTFileName m_fnAtt2Tex; + INDEX m_iAtt2Position; + ANIMATION m_iAtt2Anim; + CTFileName m_fnAtt3Mdl; + CTFileName m_fnAtt3Tex; + INDEX m_iAtt3Position; + ANIMATION m_iAtt3Anim; + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +const CTString & GetDescription(void)const; + +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +CAnimData * GetAnimData(SLONG slPropertyOffset); + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +BOOL NextMarker(void); + +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CalcRotation(ANGLE aWantedHeadingRelative,ANGLE3D & aRotation); + +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void StopMoving(void); + +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void MoveToPosition(void); + +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void CalcDestination(); + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void MarkerParameters(); + +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void Initialize(void); + +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void InitializeWatcher(FLOAT fWaitTime); + +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void PlayDefaultAnim(void); + +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void PlayMarkerAnimation(void); + +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void ChangeDefaultAnim(void); + +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +void WaitOnMarker(void); +#define STATE_CEnvironmentBase_MoveToMarker 0x03840000 + BOOL +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +MoveToMarker(const CEntityEvent &__eeInput); + BOOL H0x03840001_MoveToMarker_01(const CEntityEvent &__eeInput); + BOOL H0x03840002_MoveToMarker_02(const CEntityEvent &__eeInput); + BOOL H0x03840003_MoveToMarker_03(const CEntityEvent &__eeInput); + BOOL H0x03840004_MoveToMarker_04(const CEntityEvent &__eeInput); + BOOL H0x03840005_MoveToMarker_05(const CEntityEvent &__eeInput); +#define STATE_CEnvironmentBase_Activate 0x03840006 + BOOL +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Activate(const CEntityEvent &__eeInput); + BOOL H0x03840007_Activate_01(const CEntityEvent &__eeInput); + BOOL H0x03840008_Activate_02(const CEntityEvent &__eeInput); +#define STATE_CEnvironmentBase_Stop 0x03840009 + BOOL +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Stop(const CEntityEvent &__eeInput); + BOOL H0x0384000a_Stop_01(const CEntityEvent &__eeInput); + BOOL H0x0384000b_Stop_02(const CEntityEvent &__eeInput); +#define STATE_CEnvironmentBase_DoAction 0x0384000c + BOOL +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +DoAction(const CEntityEvent &__eeInput); + BOOL H0x0384000d_DoAction_01(const CEntityEvent &__eeInput); + BOOL H0x0384000e_DoAction_02(const CEntityEvent &__eeInput); + BOOL H0x0384000f_DoAction_03(const CEntityEvent &__eeInput); + BOOL H0x03840010_DoAction_04(const CEntityEvent &__eeInput); + BOOL H0x03840011_DoAction_05(const CEntityEvent &__eeInput); + BOOL H0x03840012_DoAction_06(const CEntityEvent &__eeInput); + BOOL H0x03840013_DoAction_07(const CEntityEvent &__eeInput); + BOOL H0x03840014_DoAction_08(const CEntityEvent &__eeInput); + BOOL H0x03840015_DoAction_09(const CEntityEvent &__eeInput); + BOOL H0x03840016_DoAction_10(const CEntityEvent &__eeInput); +#define STATE_CEnvironmentBase_MainLoop 0x03840017 + BOOL +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +MainLoop(const CEntityEvent &__eeInput); + BOOL H0x03840018_MainLoop_01(const CEntityEvent &__eeInput); + BOOL H0x03840019_MainLoop_02(const CEntityEvent &__eeInput); +#define STATE_CEnvironmentBase_Main 1 + BOOL +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x0384001a_Main_01(const CEntityEvent &__eeInput); + BOOL H0x0384001b_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_EnvironmentBase_INCLUDED diff --git a/Sources/EntitiesMP/EnvironmentBase_tables.h b/Sources/EntitiesMP/EnvironmentBase_tables.h new file mode 100644 index 0000000..ee5768a --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentBase_tables.h @@ -0,0 +1,100 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CEnvironmentBase + +CEntityProperty CEnvironmentBase_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000384<<8)+1, offsetof(CEnvironmentBase, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000384<<8)+2, offsetof(CEnvironmentBase, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000384<<8)+3, offsetof(CEnvironmentBase, m_fDistance), "Range", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000384<<8)+4, offsetof(CEnvironmentBase, m_fStretch), "Stretch", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000384<<8)+5, offsetof(CEnvironmentBase, m_penTarget), "Target", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000384<<8)+6, offsetof(CEnvironmentBase, m_penWatcher), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000384<<8)+7, offsetof(CEnvironmentBase, m_fWatcherFrequency), "Watcher frequency", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000384<<8)+8, offsetof(CEnvironmentBase, m_vDesiredPosition), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000384<<8)+10, offsetof(CEnvironmentBase, m_fMoveSpeed), "Move speed", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000384<<8)+11, offsetof(CEnvironmentBase, m_fRotateSpeed), "Rotate speed", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000384<<8)+12, offsetof(CEnvironmentBase, m_fMoveFrequency), "Move frequency", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000384<<8)+13, offsetof(CEnvironmentBase, m_bUseWatcher), "Use watcher", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000384<<8)+14, offsetof(CEnvironmentBase, m_bFlying), "Flying", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000384<<8)+16, offsetof(CEnvironmentBase, m_fWaitTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000384<<8)+20, offsetof(CEnvironmentBase, m_fnMdl), "Model", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000384<<8)+21, offsetof(CEnvironmentBase, m_fnTex), "Texture", 'X', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000384<<8)+22, offsetof(CEnvironmentBase, m_iAnim), "Animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000384<<8)+25, offsetof(CEnvironmentBase, m_fnAtt1Mdl), "Attachment 1 Model", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000384<<8)+26, offsetof(CEnvironmentBase, m_fnAtt1Tex), "Attachment 1 Texture", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000384<<8)+27, offsetof(CEnvironmentBase, m_iAtt1Position), "Attachment 1 position", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000384<<8)+28, offsetof(CEnvironmentBase, m_iAtt1Anim), "Attachment 1 animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000384<<8)+30, offsetof(CEnvironmentBase, m_fnAtt2Mdl), "Attachment 2 Model", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000384<<8)+31, offsetof(CEnvironmentBase, m_fnAtt2Tex), "Attachment 2 Texture", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000384<<8)+32, offsetof(CEnvironmentBase, m_iAtt2Position), "Attachment 2 position", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000384<<8)+33, offsetof(CEnvironmentBase, m_iAtt2Anim), "Attachment 2 animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000384<<8)+35, offsetof(CEnvironmentBase, m_fnAtt3Mdl), "Attachment 3 Model", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000384<<8)+36, offsetof(CEnvironmentBase, m_fnAtt3Tex), "Attachment 3 Texture", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000384<<8)+37, offsetof(CEnvironmentBase, m_iAtt3Position), "Attachment 3 position", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000384<<8)+38, offsetof(CEnvironmentBase, m_iAtt3Anim), "Attachment 3 animation", 0, 0x7F0000FFUL, 0), +}; +#define CEnvironmentBase_propertiesct ARRAYCOUNT(CEnvironmentBase_properties) + +CEntityComponent CEnvironmentBase_components[] = { +#define CLASS_WATCHPLAYERS ((0x00000384<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_WATCHPLAYERS, "EFNM" "Classes\\WatchPlayers.ecl"), +}; +#define CEnvironmentBase_componentsct ARRAYCOUNT(CEnvironmentBase_components) + +CEventHandlerEntry CEnvironmentBase_handlers[] = { + {0x03840000, -1, CEntity::pEventHandler(&CEnvironmentBase:: +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +MoveToMarker),DEBUGSTRING("CEnvironmentBase::MoveToMarker")}, + {0x03840001, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840001_MoveToMarker_01), DEBUGSTRING("CEnvironmentBase::H0x03840001_MoveToMarker_01")}, + {0x03840002, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840002_MoveToMarker_02), DEBUGSTRING("CEnvironmentBase::H0x03840002_MoveToMarker_02")}, + {0x03840003, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840003_MoveToMarker_03), DEBUGSTRING("CEnvironmentBase::H0x03840003_MoveToMarker_03")}, + {0x03840004, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840004_MoveToMarker_04), DEBUGSTRING("CEnvironmentBase::H0x03840004_MoveToMarker_04")}, + {0x03840005, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840005_MoveToMarker_05), DEBUGSTRING("CEnvironmentBase::H0x03840005_MoveToMarker_05")}, + {0x03840006, -1, CEntity::pEventHandler(&CEnvironmentBase:: +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Activate),DEBUGSTRING("CEnvironmentBase::Activate")}, + {0x03840007, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840007_Activate_01), DEBUGSTRING("CEnvironmentBase::H0x03840007_Activate_01")}, + {0x03840008, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840008_Activate_02), DEBUGSTRING("CEnvironmentBase::H0x03840008_Activate_02")}, + {0x03840009, -1, CEntity::pEventHandler(&CEnvironmentBase:: +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Stop),DEBUGSTRING("CEnvironmentBase::Stop")}, + {0x0384000a, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x0384000a_Stop_01), DEBUGSTRING("CEnvironmentBase::H0x0384000a_Stop_01")}, + {0x0384000b, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x0384000b_Stop_02), DEBUGSTRING("CEnvironmentBase::H0x0384000b_Stop_02")}, + {0x0384000c, -1, CEntity::pEventHandler(&CEnvironmentBase:: +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +DoAction),DEBUGSTRING("CEnvironmentBase::DoAction")}, + {0x0384000d, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x0384000d_DoAction_01), DEBUGSTRING("CEnvironmentBase::H0x0384000d_DoAction_01")}, + {0x0384000e, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x0384000e_DoAction_02), DEBUGSTRING("CEnvironmentBase::H0x0384000e_DoAction_02")}, + {0x0384000f, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x0384000f_DoAction_03), DEBUGSTRING("CEnvironmentBase::H0x0384000f_DoAction_03")}, + {0x03840010, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840010_DoAction_04), DEBUGSTRING("CEnvironmentBase::H0x03840010_DoAction_04")}, + {0x03840011, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840011_DoAction_05), DEBUGSTRING("CEnvironmentBase::H0x03840011_DoAction_05")}, + {0x03840012, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840012_DoAction_06), DEBUGSTRING("CEnvironmentBase::H0x03840012_DoAction_06")}, + {0x03840013, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840013_DoAction_07), DEBUGSTRING("CEnvironmentBase::H0x03840013_DoAction_07")}, + {0x03840014, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840014_DoAction_08), DEBUGSTRING("CEnvironmentBase::H0x03840014_DoAction_08")}, + {0x03840015, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840015_DoAction_09), DEBUGSTRING("CEnvironmentBase::H0x03840015_DoAction_09")}, + {0x03840016, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840016_DoAction_10), DEBUGSTRING("CEnvironmentBase::H0x03840016_DoAction_10")}, + {0x03840017, -1, CEntity::pEventHandler(&CEnvironmentBase:: +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +MainLoop),DEBUGSTRING("CEnvironmentBase::MainLoop")}, + {0x03840018, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840018_MainLoop_01), DEBUGSTRING("CEnvironmentBase::H0x03840018_MainLoop_01")}, + {0x03840019, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x03840019_MainLoop_02), DEBUGSTRING("CEnvironmentBase::H0x03840019_MainLoop_02")}, + {1, -1, CEntity::pEventHandler(&CEnvironmentBase:: +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentBase.es" +Main),DEBUGSTRING("CEnvironmentBase::Main")}, + {0x0384001a, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x0384001a_Main_01), DEBUGSTRING("CEnvironmentBase::H0x0384001a_Main_01")}, + {0x0384001b, -1, CEntity::pEventHandler(&CEnvironmentBase::H0x0384001b_Main_02), DEBUGSTRING("CEnvironmentBase::H0x0384001b_Main_02")}, +}; +#define CEnvironmentBase_handlersct ARRAYCOUNT(CEnvironmentBase_handlers) + +CEntity *CEnvironmentBase_New(void) { return new CEnvironmentBase; }; +void CEnvironmentBase_OnInitClass(void) {}; +void CEnvironmentBase_OnEndClass(void) {}; +void CEnvironmentBase_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEnvironmentBase_OnWorldEnd(CWorld *pwo) {}; +void CEnvironmentBase_OnWorldInit(CWorld *pwo) {}; +void CEnvironmentBase_OnWorldTick(CWorld *pwo) {}; +void CEnvironmentBase_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEnvironmentBase, CMovableEntity, "Environment Base", "Thumbnails\\EnvironmentBase.tbn", 0x00000384); +DECLARE_CTFILENAME(_fnmCEnvironmentBase_tbn, "Thumbnails\\EnvironmentBase.tbn"); diff --git a/Sources/EntitiesMP/EnvironmentMarker.cpp b/Sources/EntitiesMP/EnvironmentMarker.cpp new file mode 100644 index 0000000..0417d31 --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentMarker.cpp @@ -0,0 +1,110 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" + +#include "StdH.h" + +#include +#include +void CEnvironmentMarker::SetDefaultProperties(void) { + m_fWaitTime = 0.0f; + m_fRandomTime = 0.0f; + m_fMarkerRange = 5.0f; + m_bFixedAnimLength = FALSE ; + m_bChangeDefaultAnim = FALSE ; + m_fMoveSpeed = -1.0f; + m_fRotateSpeed = -1.0f; + m_fnMdl = CTFILENAME("Models\\Editor\\Axis.mdl"); + m_iAnim = 0; + m_moAnimData.SetData(NULL); +m_moAnimData.mo_toTexture.SetData(NULL); + CMarker::SetDefaultProperties(); +} + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +BOOL CEnvironmentMarker::MovesByTargetedRoute(CTString & strTargetProperty)const { +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +strTargetProperty = "Target"; +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +return TRUE ; +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +} + +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +BOOL CEnvironmentMarker::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +fnmMarkerClass = CTFILENAME ("Classes\\EnvironmentMarker.ecl"); +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +strTargetProperty = "Target"; +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +return TRUE ; +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +} + +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +CAnimData * CEnvironmentMarker::GetAnimData(SLONG slPropertyOffset) { +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +if(slPropertyOffset == offsetof (CEnvironmentMarker , m_iAnim )){ +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +return m_moAnimData . GetData (); +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +}else { +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +return CEntity :: GetAnimData (slPropertyOffset ); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +} +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +} + +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +void CEnvironmentMarker::SetModelObject(void) { +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +try { +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +m_moAnimData . SetData_t (m_fnMdl ); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +}catch (char * strError ){ +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +strError ; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +DECLARE_CTFILENAME (fnmDefault , "Models\\Editor\\Axis.mdl"); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +try { +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +m_moAnimData . SetData_t (fnmDefault ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +}catch (char * strErrorDefault ){ +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +FatalError (TRANS ("Cannot load default model '%s':\n%s") , +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +(CTString &) fnmDefault , strErrorDefault ); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +} +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +} +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +} +BOOL CEnvironmentMarker:: +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnvironmentMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnvironmentMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +InitAsEditorModel (); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +SetModel (MODEL_MARKER ); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +SetModelObject (); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EnvironmentMarker.es b/Sources/EntitiesMP/EnvironmentMarker.es new file mode 100644 index 0000000..70f17b5 --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentMarker.es @@ -0,0 +1,94 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +901 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; + +class CEnvironmentMarker: CMarker { +name "Environment Marker"; +thumbnail "Thumbnails\\EnvironmentMarker.tbn"; + +properties: + 1 FLOAT m_fWaitTime "Wait time" 'W' = 0.0f, // time to wait (or do anything until go to another marker) + 2 FLOAT m_fRandomTime "Random time" 'E' = 0.0f, // random time to wait (or do anything until go to another marker) + 3 RANGE m_fMarkerRange "Marker range" 'R' = 5.0f, // range around marker (marker doesn't have to be hit directly) + 4 BOOL m_bFixedAnimLength "Fixed anim length" 'F' = FALSE, // fixed anim length (like play once) + 5 BOOL m_bChangeDefaultAnim "Change default anim" 'C' = FALSE, // change default anim + 6 FLOAT m_fMoveSpeed "Move speed" 'V' = -1.0f, // moving speed + 7 FLOAT m_fRotateSpeed "Rotate speed" 'B' = -1.0f, // rotate speed + + // for browsing animations on marker for base environment model + 20 CTFileName m_fnMdl "Model" 'M' = CTFILENAME("Models\\Editor\\Axis.mdl"), + 21 ANIMATION m_iAnim "Animation" 'A' =0, + 22 CModelObject m_moAnimData, + +components: + 1 model MODEL_MARKER "Models\\Editor\\EnvironmentMarker.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\EnvironmentMarker.tex" + +functions: + /* Check if entity is moved on a route set up by its targets. */ + BOOL MovesByTargetedRoute(CTString &strTargetProperty) const { + strTargetProperty = "Target"; + return TRUE; + }; + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\EnvironmentMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + }; + /* Get anim data for given animation property - return NULL for none. */ + CAnimData *GetAnimData(SLONG slPropertyOffset) { + if(slPropertyOffset==offsetof(CEnvironmentMarker, m_iAnim)) { + return m_moAnimData.GetData(); + + } else { + return CEntity::GetAnimData(slPropertyOffset); + } + }; + + // >>> original source from CEntity::SetModel <<< + // set mdoel object + void SetModelObject(void) { + // try to + try { + // load the new model data + m_moAnimData.SetData_t(m_fnMdl); + // if failed + } catch(char *strError) { + strError; + DECLARE_CTFILENAME(fnmDefault, "Models\\Editor\\Axis.mdl"); + // try to + try { + // load the default model data + m_moAnimData.SetData_t(fnmDefault); + // if failed + } catch(char *strErrorDefault) { + FatalError(TRANS("Cannot load default model '%s':\n%s"), + (CTString&)fnmDefault, strErrorDefault); + } + } + }; + + +procedures: + Main() { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + // set model data for anim browser + SetModelObject(); + + return; + } +}; + diff --git a/Sources/EntitiesMP/EnvironmentMarker.h b/Sources/EntitiesMP/EnvironmentMarker.h new file mode 100644 index 0000000..9ea6a37 --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentMarker.h @@ -0,0 +1,39 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_EnvironmentMarker_INCLUDED +#define _EntitiesMP_EnvironmentMarker_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CEnvironmentMarker_DLLClass; +class CEnvironmentMarker : public CMarker { +public: + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fWaitTime; + FLOAT m_fRandomTime; + RANGE m_fMarkerRange; + BOOL m_bFixedAnimLength; + BOOL m_bChangeDefaultAnim; + FLOAT m_fMoveSpeed; + FLOAT m_fRotateSpeed; + CTFileName m_fnMdl; + ANIMATION m_iAnim; + CModelObject m_moAnimData; + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +CAnimData * GetAnimData(SLONG slPropertyOffset); + +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +void SetModelObject(void); +#define STATE_CEnvironmentMarker_Main 1 + BOOL +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_EnvironmentMarker_INCLUDED diff --git a/Sources/EntitiesMP/EnvironmentMarker_tables.h b/Sources/EntitiesMP/EnvironmentMarker_tables.h new file mode 100644 index 0000000..0d496fe --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentMarker_tables.h @@ -0,0 +1,45 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CEnvironmentMarker + +CEntityProperty CEnvironmentMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000385<<8)+1, offsetof(CEnvironmentMarker, m_fWaitTime), "Wait time", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000385<<8)+2, offsetof(CEnvironmentMarker, m_fRandomTime), "Random time", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000385<<8)+3, offsetof(CEnvironmentMarker, m_fMarkerRange), "Marker range", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000385<<8)+4, offsetof(CEnvironmentMarker, m_bFixedAnimLength), "Fixed anim length", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000385<<8)+5, offsetof(CEnvironmentMarker, m_bChangeDefaultAnim), "Change default anim", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000385<<8)+6, offsetof(CEnvironmentMarker, m_fMoveSpeed), "Move speed", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000385<<8)+7, offsetof(CEnvironmentMarker, m_fRotateSpeed), "Rotate speed", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000385<<8)+20, offsetof(CEnvironmentMarker, m_fnMdl), "Model", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000385<<8)+21, offsetof(CEnvironmentMarker, m_iAnim), "Animation", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_MODELOBJECT, NULL, (0x00000385<<8)+22, offsetof(CEnvironmentMarker, m_moAnimData), "", 0, 0, 0), +}; +#define CEnvironmentMarker_propertiesct ARRAYCOUNT(CEnvironmentMarker_properties) + +CEntityComponent CEnvironmentMarker_components[] = { +#define MODEL_MARKER ((0x00000385<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\EnvironmentMarker.mdl"), +#define TEXTURE_MARKER ((0x00000385<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\EnvironmentMarker.tex"), +}; +#define CEnvironmentMarker_componentsct ARRAYCOUNT(CEnvironmentMarker_components) + +CEventHandlerEntry CEnvironmentMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CEnvironmentMarker:: +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentMarker.es" +Main),DEBUGSTRING("CEnvironmentMarker::Main")}, +}; +#define CEnvironmentMarker_handlersct ARRAYCOUNT(CEnvironmentMarker_handlers) + +CEntity *CEnvironmentMarker_New(void) { return new CEnvironmentMarker; }; +void CEnvironmentMarker_OnInitClass(void) {}; +void CEnvironmentMarker_OnEndClass(void) {}; +void CEnvironmentMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEnvironmentMarker_OnWorldEnd(CWorld *pwo) {}; +void CEnvironmentMarker_OnWorldInit(CWorld *pwo) {}; +void CEnvironmentMarker_OnWorldTick(CWorld *pwo) {}; +void CEnvironmentMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEnvironmentMarker, CMarker, "Environment Marker", "Thumbnails\\EnvironmentMarker.tbn", 0x00000385); +DECLARE_CTFILENAME(_fnmCEnvironmentMarker_tbn, "Thumbnails\\EnvironmentMarker.tbn"); diff --git a/Sources/EntitiesMP/EnvironmentParticlesHolder.cpp b/Sources/EntitiesMP/EnvironmentParticlesHolder.cpp new file mode 100644 index 0000000..b5dd10d --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentParticlesHolder.cpp @@ -0,0 +1,328 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" + +#include "StdH.h" + +#include +#include +void CEnvironmentParticlesHolder::SetDefaultProperties(void) { + m_strName = "Env. particles holder"; + m_strDescription = ""; + m_fnHeightMap = CTString(""); + m_boxHeightMap = FLOATaabbox3D(FLOAT3D (0 , 0 , 0) , FLOAT3D (1 , 1 , 1)); + m_eptType = EPTH_NONE ; + m_penNextHolder = NULL; + m_tmRainStart = -1.0f; + m_tmRainEnd = -1.0f; + m_tmSnowStart = -1.0f; + m_tmSnowEnd = -1.0f; + m_moHeightMapHolder.SetData(NULL); +m_moHeightMapHolder.mo_toTexture.SetData(NULL); + m_moParticleTextureHolder.SetData(NULL); +m_moParticleTextureHolder.mo_toTexture.SetData(NULL); + m_fnTexture = CTString(""); + m_fGrowthRenderingStep = 1.0f; + m_fGrowthRenderingRadius = 50; + m_fGrowthRenderingRadiusFade = 50; + m_bGrowthHighresMap = TRUE ; + m_iGrowthMapX = 1; + m_iGrowthMapY = 1; + m_fGrowthMinSize = 1.0f; + m_fGrowthMaxSize = 1.0f; + m_fParticlesSinkFactor = 0.0; + m_fRainAppearLen = 10.0f; + m_fSnowAppearLen = 10.0f; + CRationalEntity::SetDefaultProperties(); +} + +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +void CEnvironmentParticlesHolder::Precache(void) +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +CTextureData * ptdHeightMap = (CTextureData *) m_moHeightMapHolder . mo_toTexture . GetData (); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +if(ptdHeightMap != NULL ){ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +ptdHeightMap -> Force (TEX_CONSTANT | TEX_STATIC | TEX_KEEPCOLOR ); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +BOOL CEnvironmentParticlesHolder::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +if(slPropertyOffset == offsetof (CEnvironmentParticlesHolder , m_penNextHolder )) +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +if(IsOfClass (penTarget , "EnvironmentParticlesHolder")){return TRUE ;} +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +else {return FALSE ;} +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +return CEntity :: IsTargetValid (slPropertyOffset , penTarget ); +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +FLOAT CEnvironmentParticlesHolder::GetRainFactor(void) +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +FLOAT fRainFactor = 0.0f; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +TIME tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +if(tmNow > m_tmRainStart && tmNow < m_tmRainEnd + m_fRainAppearLen ) +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +if(tmNow > m_tmRainStart + m_fRainAppearLen && tmNow < m_tmRainEnd ) +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +fRainFactor = 1.0f; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +else if(tmNow > m_tmRainEnd ) +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +fRainFactor = 1.0f - (tmNow - m_tmRainEnd ) / m_fRainAppearLen ; +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +else +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +fRainFactor = (tmNow - m_tmRainStart ) / m_fRainAppearLen ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +return fRainFactor ; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} + +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +FLOAT CEnvironmentParticlesHolder::GetSnowFactor(void) +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +FLOAT fSnowFactor = 0.0f; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +TIME tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +if(tmNow > m_tmSnowStart && tmNow < m_tmSnowEnd + m_fSnowAppearLen ) +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +if(tmNow > m_tmSnowStart + m_fSnowAppearLen && tmNow < m_tmSnowEnd ) +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +fSnowFactor = 1.0f; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +else if(tmNow > m_tmSnowEnd ) +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +fSnowFactor = 1.0f - (tmNow - m_tmSnowEnd ) / m_fSnowAppearLen ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +else +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +fSnowFactor = (tmNow - m_tmSnowStart ) / m_fSnowAppearLen ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +return fSnowFactor ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +void CEnvironmentParticlesHolder::GetHeightMapData(CTextureData * & ptdHeightMap,FLOATaabbox3D & boxHeightMap) +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +ptdHeightMap = (CTextureData *) m_moHeightMapHolder . mo_toTexture . GetData (); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +if(ptdHeightMap != NULL ){ +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +ptdHeightMap -> Force (TEX_CONSTANT | TEX_STATIC | TEX_KEEPCOLOR ); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +boxHeightMap = m_boxHeightMap ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +boxHeightMap += GetPlacement () . pl_PositionVector ; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +void CEnvironmentParticlesHolder::GetParticleTexture() +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +BOOL CEnvironmentParticlesHolder:: +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEnvironmentParticlesHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEnvironmentParticlesHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +InitAsEditorModel (); +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +if(m_fnHeightMap != CTString ("")) +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +try +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_moHeightMapHolder . mo_toTexture . SetData_t (m_fnHeightMap ); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +}catch (char * strError ){ +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +WarningMessage (strError ); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +if(m_fnTexture != CTString ("")) +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +try +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{ +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_moParticleTextureHolder . mo_toTexture . SetData_t (m_fnTexture ); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +}catch (char * strError ){ +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +WarningMessage (strError ); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +if(m_fGrowthRenderingRadius < m_fGrowthRenderingRadiusFade ){ +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_fGrowthRenderingRadiusFade = m_fGrowthRenderingRadius ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_fParticlesSinkFactor = Clamp (m_fParticlesSinkFactor , 0.0f , 1.0f); +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +SetModel (MODEL_ENVIRONMENT_PARTICLES_HOLDER ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +SetModelMainTexture (TEXTURE_ENVIRONMENT_PARTICLES_HOLDER ); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_tmRainStart = 1e5 - 1.0f; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_tmRainEnd = 1e5; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_tmSnowStart = 1e5 - 1.0f; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_tmSnowEnd = 1e5; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +switch(m_eptType ){ +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +case EPTH_GROWTH : +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_strDescription = "Growth"; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +break ; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +case EPTH_RAIN : +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_strDescription = "Rain"; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +break ; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +case EPTH_NONE : +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_strDescription = "None"; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +break ; +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +} +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00ed0000, FALSE, EBegin());return TRUE;}BOOL CEnvironmentParticlesHolder::H0x00ed0000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ed0000 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin): +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{const EBegin&e= (EBegin&)__eeInput; + +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +return TRUE; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart): +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{const EStart&e= (EStart&)__eeInput; + +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_tmRainStart = tmNow ; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_tmRainEnd = 1e6; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_tmSnowStart = tmNow ; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_tmSnowEnd = 1e6; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +return TRUE; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop): +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +{const EStop&e= (EStop&)__eeInput; + +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_tmRainEnd = tmNow ; +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +m_tmSnowEnd = tmNow ; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +return TRUE; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +}return TRUE;}BOOL CEnvironmentParticlesHolder::H0x00ed0001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ed0001 + +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EnvironmentParticlesHolder.es b/Sources/EntitiesMP/EnvironmentParticlesHolder.es new file mode 100644 index 0000000..a884511 --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentParticlesHolder.es @@ -0,0 +1,243 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +237 +%{ +#include "StdH.h" +%} + +enum EnvironmentParticlesHolderType { + 0 EPTH_NONE "None", + 1 EPTH_GROWTH "Growth", + 2 EPTH_RAIN "Rain", + 3 EPTH_SNOW "Snow", +}; + +class CEnvironmentParticlesHolder: CRationalEntity { +name "EnvironmentParticlesHolder"; +thumbnail "Thumbnails\\EnvironmentParticlesHolder.tbn"; +features "IsTargetable", "HasName", "HasDescription", "IsImportant"; + +properties: + + 1 CTString m_strName "Name" 'N' = "Env. particles holder", // class name + 6 CTString m_strDescription = "", + 2 CTFileName m_fnHeightMap "Height map" 'R' = CTString(""), + 3 FLOATaabbox3D m_boxHeightMap "Height map box" 'B' = FLOATaabbox3D(FLOAT3D(0,0,0), FLOAT3D(1,1,1)), + 4 enum EnvironmentParticlesHolderType m_eptType "Type" 'Y' = EPTH_NONE, + 5 CEntityPointer m_penNextHolder "Next env. particles holder" 'T', + + 10 FLOAT m_tmRainStart = -1.0f, // Rain start time + 11 FLOAT m_tmRainEnd = -1.0f, // Rain end time + + 12 FLOAT m_tmSnowStart = -1.0f, // Snow start time + 13 FLOAT m_tmSnowEnd = -1.0f, // Snow end time + + 20 CModelObject m_moHeightMapHolder, + 22 CModelObject m_moParticleTextureHolder, + + // particle type specific properties + + // shared particles texture + 40 CTFileName m_fnTexture "Particle Texture" = CTString(""), + + // growth + 50 FLOAT m_fGrowthRenderingStep "Growth frequency" = 1.0f, + 51 FLOAT m_fGrowthRenderingRadius "Growth radius" = 50, + 52 FLOAT m_fGrowthRenderingRadiusFade "Growth fade radius" = 50, + 53 BOOL m_bGrowthHighresMap "Growth high res map" = TRUE, + 54 INDEX m_iGrowthMapX "Growth map tiles X" = 1, + 55 INDEX m_iGrowthMapY "Growth map tiles Y" = 1, + 56 FLOAT m_fGrowthMinSize "Growth min. size" = 1.0f, + 57 FLOAT m_fGrowthMaxSize "Growth max. size" = 1.0f, + 58 FLOAT m_fParticlesSinkFactor "Growth sink factor" = 0.0, + + // rain + 70 FLOAT m_fRainAppearLen "Rain start duration" = 10.0f, + 71 FLOAT m_fSnowAppearLen "Snow start duration" = 10.0f, + + { + // linked list of growth caches + CListHead lhCache; + } + +components: + 1 model MODEL_ENVIRONMENT_PARTICLES_HOLDER "ModelsMP\\Editor\\EnvironmentParticlesHolder.mdl", + 2 texture TEXTURE_ENVIRONMENT_PARTICLES_HOLDER "ModelsMP\\Editor\\EnvironmentParticlesHolder.tex" + + +functions: + + void Precache(void) + { + CTextureData *ptdHeightMap = (CTextureData *) m_moHeightMapHolder.mo_toTexture.GetData(); + if( ptdHeightMap!=NULL) { + ptdHeightMap->Force(TEX_CONSTANT|TEX_STATIC|TEX_KEEPCOLOR); + } + } + + + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if( slPropertyOffset == offsetof(CEnvironmentParticlesHolder, m_penNextHolder)) + { + if (IsOfClass(penTarget, "EnvironmentParticlesHolder")) { return TRUE; } + else { return FALSE; } + } + return CEntity::IsTargetValid(slPropertyOffset, penTarget); + } + + + FLOAT GetRainFactor(void) + { + FLOAT fRainFactor = 0.0f; + TIME tmNow = _pTimer->GetLerpedCurrentTick(); + // if we have Rain + if( tmNow>m_tmRainStart && tmNowm_tmRainStart+m_fRainAppearLen && tmNowm_tmRainEnd) + { + fRainFactor = 1.0f-(tmNow-m_tmRainEnd)/m_fRainAppearLen; + } + // Rain is turning on + else + { + fRainFactor = (tmNow-m_tmRainStart)/m_fRainAppearLen; + } + } + return fRainFactor; + } + + + FLOAT GetSnowFactor(void) + { + FLOAT fSnowFactor = 0.0f; + TIME tmNow = _pTimer->GetLerpedCurrentTick(); + // if we have Snow + if( tmNow>m_tmSnowStart && tmNowm_tmSnowStart+m_fSnowAppearLen && tmNowm_tmSnowEnd) + { + fSnowFactor = 1.0f-(tmNow-m_tmSnowEnd)/m_fSnowAppearLen; + } + // Snow is turning on + else + { + fSnowFactor = (tmNow-m_tmSnowStart)/m_fSnowAppearLen; + } + } + return fSnowFactor; + } + + + void GetHeightMapData(CTextureData *&ptdHeightMap, FLOATaabbox3D &boxHeightMap) + { + ptdHeightMap = (CTextureData *) m_moHeightMapHolder.mo_toTexture.GetData(); + if (ptdHeightMap!=NULL) { + ptdHeightMap->Force(TEX_CONSTANT|TEX_STATIC|TEX_KEEPCOLOR); + } + boxHeightMap = m_boxHeightMap; + boxHeightMap += GetPlacement().pl_PositionVector; + } + + void GetParticleTexture() + { + + } + +procedures: + Main(EVoid) + { + // set appearance + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // try to obtain height map + if( m_fnHeightMap != CTString("")) + { + try + { + m_moHeightMapHolder.mo_toTexture.SetData_t(m_fnHeightMap); + } catch (char *strError) { + WarningMessage(strError); + } + } + + if( m_fnTexture != CTString("")) + { + try + { + m_moParticleTextureHolder.mo_toTexture.SetData_t(m_fnTexture); + } catch (char *strError) { + WarningMessage(strError); + } + } + + + // validate parameters + if (m_fGrowthRenderingRadius < m_fGrowthRenderingRadiusFade) { + m_fGrowthRenderingRadiusFade = m_fGrowthRenderingRadius; + } + m_fParticlesSinkFactor = Clamp(m_fParticlesSinkFactor, 0.0f, 1.0f); + + // set appearance + SetModel(MODEL_ENVIRONMENT_PARTICLES_HOLDER); + SetModelMainTexture(TEXTURE_ENVIRONMENT_PARTICLES_HOLDER); + + m_tmRainStart = 1e5-1.0f; + m_tmRainEnd = 1e5; + m_tmSnowStart = 1e5-1.0f; + m_tmSnowEnd = 1e5; + + switch(m_eptType) { + case EPTH_GROWTH: + m_strDescription = "Growth"; + break; + case EPTH_RAIN: + m_strDescription = "Rain"; + break; + case EPTH_NONE: + m_strDescription = "None"; + break; + } + + wait() { + + on (EBegin) : + { + resume; + } + on (EStart) : + { + TIME tmNow = _pTimer->CurrentTick(); + m_tmRainStart = tmNow; + m_tmRainEnd = 1e6; + m_tmSnowStart = tmNow; + m_tmSnowEnd = 1e6; + resume; + } + on (EStop) : + { + TIME tmNow = _pTimer->CurrentTick(); + m_tmRainEnd = tmNow; + m_tmSnowEnd = tmNow; + resume; + } + } + // do nothing + return; + } + +}; \ No newline at end of file diff --git a/Sources/EntitiesMP/EnvironmentParticlesHolder.h b/Sources/EntitiesMP/EnvironmentParticlesHolder.h new file mode 100644 index 0000000..95e2bd7 --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentParticlesHolder.h @@ -0,0 +1,73 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_EnvironmentParticlesHolder_INCLUDED +#define _EntitiesMP_EnvironmentParticlesHolder_INCLUDED 1 +extern DECL_DLL CEntityPropertyEnumType EnvironmentParticlesHolderType_enum; +enum EnvironmentParticlesHolderType { + EPTH_NONE = 0, + EPTH_GROWTH = 1, + EPTH_RAIN = 2, + EPTH_SNOW = 3, +}; +DECL_DLL inline void ClearToDefault(EnvironmentParticlesHolderType &e) { e = (EnvironmentParticlesHolderType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CEnvironmentParticlesHolder_DLLClass; +class CEnvironmentParticlesHolder : public CRationalEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; +virtual const CTString &GetDescription(void) const { return m_strDescription; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CTFileName m_fnHeightMap; + FLOATaabbox3D m_boxHeightMap; + enum EnvironmentParticlesHolderType m_eptType; + CEntityPointer m_penNextHolder; + FLOAT m_tmRainStart; + FLOAT m_tmRainEnd; + FLOAT m_tmSnowStart; + FLOAT m_tmSnowEnd; + CModelObject m_moHeightMapHolder; + CModelObject m_moParticleTextureHolder; + CTFileName m_fnTexture; + FLOAT m_fGrowthRenderingStep; + FLOAT m_fGrowthRenderingRadius; + FLOAT m_fGrowthRenderingRadiusFade; + BOOL m_bGrowthHighresMap; + INDEX m_iGrowthMapX; + INDEX m_iGrowthMapY; + FLOAT m_fGrowthMinSize; + FLOAT m_fGrowthMaxSize; + FLOAT m_fParticlesSinkFactor; + FLOAT m_fRainAppearLen; + FLOAT m_fSnowAppearLen; +CListHead lhCache; + +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +void Precache(void); + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +FLOAT GetRainFactor(void); + +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +FLOAT GetSnowFactor(void); + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +void GetHeightMapData(CTextureData * & ptdHeightMap,FLOATaabbox3D & boxHeightMap); + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +void GetParticleTexture(); +#define STATE_CEnvironmentParticlesHolder_Main 1 + BOOL +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00ed0000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00ed0001_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_EnvironmentParticlesHolder_INCLUDED diff --git a/Sources/EntitiesMP/EnvironmentParticlesHolder_tables.h b/Sources/EntitiesMP/EnvironmentParticlesHolder_tables.h new file mode 100644 index 0000000..f5207b8 --- /dev/null +++ b/Sources/EntitiesMP/EnvironmentParticlesHolder_tables.h @@ -0,0 +1,68 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(EnvironmentParticlesHolderType) + EP_ENUMVALUE(EPTH_NONE, "None"), + EP_ENUMVALUE(EPTH_GROWTH, "Growth"), + EP_ENUMVALUE(EPTH_RAIN, "Rain"), + EP_ENUMVALUE(EPTH_SNOW, "Snow"), +EP_ENUMEND(EnvironmentParticlesHolderType); + +#define ENTITYCLASS CEnvironmentParticlesHolder + +CEntityProperty CEnvironmentParticlesHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ed<<8)+1, offsetof(CEnvironmentParticlesHolder, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ed<<8)+6, offsetof(CEnvironmentParticlesHolder, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000ed<<8)+2, offsetof(CEnvironmentParticlesHolder, m_fnHeightMap), "Height map", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOATAABBOX3D, NULL, (0x000000ed<<8)+3, offsetof(CEnvironmentParticlesHolder, m_boxHeightMap), "Height map box", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EnvironmentParticlesHolderType_enum, (0x000000ed<<8)+4, offsetof(CEnvironmentParticlesHolder, m_eptType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000ed<<8)+5, offsetof(CEnvironmentParticlesHolder, m_penNextHolder), "Next env. particles holder", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+10, offsetof(CEnvironmentParticlesHolder, m_tmRainStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+11, offsetof(CEnvironmentParticlesHolder, m_tmRainEnd), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+12, offsetof(CEnvironmentParticlesHolder, m_tmSnowStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+13, offsetof(CEnvironmentParticlesHolder, m_tmSnowEnd), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_MODELOBJECT, NULL, (0x000000ed<<8)+20, offsetof(CEnvironmentParticlesHolder, m_moHeightMapHolder), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_MODELOBJECT, NULL, (0x000000ed<<8)+22, offsetof(CEnvironmentParticlesHolder, m_moParticleTextureHolder), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000ed<<8)+40, offsetof(CEnvironmentParticlesHolder, m_fnTexture), "Particle Texture", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+50, offsetof(CEnvironmentParticlesHolder, m_fGrowthRenderingStep), "Growth frequency", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+51, offsetof(CEnvironmentParticlesHolder, m_fGrowthRenderingRadius), "Growth radius", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+52, offsetof(CEnvironmentParticlesHolder, m_fGrowthRenderingRadiusFade), "Growth fade radius", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000ed<<8)+53, offsetof(CEnvironmentParticlesHolder, m_bGrowthHighresMap), "Growth high res map", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000ed<<8)+54, offsetof(CEnvironmentParticlesHolder, m_iGrowthMapX), "Growth map tiles X", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000ed<<8)+55, offsetof(CEnvironmentParticlesHolder, m_iGrowthMapY), "Growth map tiles Y", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+56, offsetof(CEnvironmentParticlesHolder, m_fGrowthMinSize), "Growth min. size", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+57, offsetof(CEnvironmentParticlesHolder, m_fGrowthMaxSize), "Growth max. size", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+58, offsetof(CEnvironmentParticlesHolder, m_fParticlesSinkFactor), "Growth sink factor", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+70, offsetof(CEnvironmentParticlesHolder, m_fRainAppearLen), "Rain start duration", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ed<<8)+71, offsetof(CEnvironmentParticlesHolder, m_fSnowAppearLen), "Snow start duration", 0, 0x7F0000FFUL, 0), +}; +#define CEnvironmentParticlesHolder_propertiesct ARRAYCOUNT(CEnvironmentParticlesHolder_properties) + +CEntityComponent CEnvironmentParticlesHolder_components[] = { +#define MODEL_ENVIRONMENT_PARTICLES_HOLDER ((0x000000ed<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_ENVIRONMENT_PARTICLES_HOLDER, "EFNM" "ModelsMP\\Editor\\EnvironmentParticlesHolder.mdl"), +#define TEXTURE_ENVIRONMENT_PARTICLES_HOLDER ((0x000000ed<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_ENVIRONMENT_PARTICLES_HOLDER, "EFNM" "ModelsMP\\Editor\\EnvironmentParticlesHolder.tex"), +}; +#define CEnvironmentParticlesHolder_componentsct ARRAYCOUNT(CEnvironmentParticlesHolder_components) + +CEventHandlerEntry CEnvironmentParticlesHolder_handlers[] = { + {1, -1, CEntity::pEventHandler(&CEnvironmentParticlesHolder:: +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/EnvironmentParticlesHolder.es" +Main),DEBUGSTRING("CEnvironmentParticlesHolder::Main")}, + {0x00ed0000, -1, CEntity::pEventHandler(&CEnvironmentParticlesHolder::H0x00ed0000_Main_01), DEBUGSTRING("CEnvironmentParticlesHolder::H0x00ed0000_Main_01")}, + {0x00ed0001, -1, CEntity::pEventHandler(&CEnvironmentParticlesHolder::H0x00ed0001_Main_02), DEBUGSTRING("CEnvironmentParticlesHolder::H0x00ed0001_Main_02")}, +}; +#define CEnvironmentParticlesHolder_handlersct ARRAYCOUNT(CEnvironmentParticlesHolder_handlers) + +CEntity *CEnvironmentParticlesHolder_New(void) { return new CEnvironmentParticlesHolder; }; +void CEnvironmentParticlesHolder_OnInitClass(void) {}; +void CEnvironmentParticlesHolder_OnEndClass(void) {}; +void CEnvironmentParticlesHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEnvironmentParticlesHolder_OnWorldEnd(CWorld *pwo) {}; +void CEnvironmentParticlesHolder_OnWorldInit(CWorld *pwo) {}; +void CEnvironmentParticlesHolder_OnWorldTick(CWorld *pwo) {}; +void CEnvironmentParticlesHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEnvironmentParticlesHolder, CRationalEntity, "EnvironmentParticlesHolder", "Thumbnails\\EnvironmentParticlesHolder.tbn", 0x000000ed); +DECLARE_CTFILENAME(_fnmCEnvironmentParticlesHolder_tbn, "Thumbnails\\EnvironmentParticlesHolder.tbn"); diff --git a/Sources/EntitiesMP/Eruptor.cpp b/Sources/EntitiesMP/Eruptor.cpp new file mode 100644 index 0000000..cd9d437 --- /dev/null +++ b/Sources/EntitiesMP/Eruptor.cpp @@ -0,0 +1,396 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" + +#include "StdH.h" + +#include +#include +void CEruptor::SetDefaultProperties(void) { + m_fStretchAll = 1.0f; + m_fStretchX = 1.0f; + m_fStretchY = 1.0f; + m_fStretchZ = 1.0f; + m_bRandomStretch = FALSE ; + m_fStretchHeight = 0.2f; + m_fStretchWidth = 0.2f; + m_fStretchDepth = 0.2f; + m_fAngle = 45.0f; + m_fMaxSpeed = 20.0f; + m_fMinSpeed = 10.0f; + m_fTime = 1.0f; + m_fRandomWait = 0.0f; + m_ptType = PRT_LAVA_COMET ; + m_bShootInArc = TRUE ; + m_fProjectileStretch = 1.0f; + CModelHolder2::SetDefaultProperties(); +} + +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +void CEruptor::Precache(void) { +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +PrecacheClass (CLASS_PROJECTILE , m_ptType ); +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +void CEruptor::CalculateAngularLaunchParams( +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +CMovableEntity * penTarget, +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D vShooting, +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D vTarget,FLOAT3D vSpeedDest, +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +ANGLE aPitch, +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +ANGLE & aHeading, +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT & fLaunchSpeed) +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +{ +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D vNewTarget = vTarget ; +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D & vGravity = penTarget -> en_vGravityDir ; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT fa = TanFast (AngleDeg (aPitch )); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D vd , vyd0 ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT fd , fyd0 ; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT fTime = 0.0f; +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT fLastTime = 0.0f; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +INDEX iIterations = 0; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +do +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +{ +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +iIterations ++; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D vDistance = vNewTarget - vShooting ; +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +GetParallelAndNormalComponents (vDistance , vGravity , vyd0 , vd ); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +fd = vd . Length (); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +fyd0 = vyd0 . Length (); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +fLastTime = fTime ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +fTime = Sqrt (2.0f) * Sqrt ((fa * fd - fyd0 ) / penTarget -> en_fGravityA ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +vNewTarget = vTarget + vSpeedDest * fTime ; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +while(Abs (fTime - fLastTime ) > _pTimer -> TickQuantum && iIterations < 10); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +fLaunchSpeed = 0.707108f * fd / +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +(Cos (AngleDeg (aPitch )) * Sqrt ((fa * fd - fyd0 ) / penTarget -> en_fGravityA )); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D vDir = (vNewTarget - vShooting ) . Normalize (); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +ANGLE3D aAngles ; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +DirectionVectorToAngles (vDir , aAngles ); +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +aHeading = aAngles (1); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} + +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +void CEruptor::SpawnShoot(CEntity * penTarget) +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +{ +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(penTarget == NULL || ! (penTarget -> GetPhysicsFlags () & EPF_MOVABLE )){ +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +return ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +CPlacement3D plLava = GetPlacement (); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT fSpeed = (m_fMaxSpeed - m_fMinSpeed ) * FRnd () + m_fMinSpeed ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_bShootInArc ){ +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT fPitch = GetPlacement () . pl_OrientationAngle (2); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT fHeading ; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +CalculateAngularLaunchParams ((CMovableEntity *) penTarget , +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +GetPlacement () . pl_PositionVector , +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +penTarget -> GetPlacement () . pl_PositionVector , +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +((CMovableEntity *) penTarget ) -> en_vCurrentTranslationAbsolute , +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +fPitch , fHeading , fSpeed ); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(Abs (NormalizeAngle (GetPlacement () . pl_OrientationAngle (1) - fHeading )) > m_fAngle ){ +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +return ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +plLava . pl_OrientationAngle (1) = fHeading ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +}else { +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D vTargetDir = (penTarget -> GetPlacement () . pl_PositionVector - +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +GetPlacement () . pl_PositionVector ) . Normalize (); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D vShootDir ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +AnglesToDirectionVector (GetPlacement () . pl_OrientationAngle , vShootDir ); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(Abs (vTargetDir % vShootDir ) < Cos (m_fAngle )){ +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +return ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +DirectionVectorToAngles (vTargetDir , plLava . pl_OrientationAngle ); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +SpawnProjectile (plLava , fSpeed ); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} + +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +void CEruptor::SpawnRandom(void) +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +{ +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT fSpeed = (m_fMaxSpeed - m_fMinSpeed ) * FRnd () + m_fMinSpeed ; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +ANGLE3D aAngle ((FRnd () * 2 - 1) * m_fAngle , (FRnd () * 2 - 1) * m_fAngle , 0); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +CPlacement3D plLava (FLOAT3D (0 , 0 , 0) , aAngle ); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +plLava . RelativeToAbsolute (GetPlacement ()); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +SpawnProjectile (plLava , fSpeed ); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +void CEruptor::SpawnProjectile(const CPlacement3D & pl,FLOAT fSpeed) +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +{ +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +CEntityPointer penLava = CreateEntity (pl , CLASS_PROJECTILE ); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +ELaunchProjectile eLaunch ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +eLaunch . penLauncher = this ; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +eLaunch . prtType = m_ptType ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +eLaunch . fSpeed = fSpeed ; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +eLaunch . fStretch = m_fProjectileStretch ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +penLava -> Initialize (eLaunch ); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(! (penLava -> GetFlags () & ENF_DELETED )){ +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D fStretchRandom (1 , 1 , 1); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_bRandomStretch ){ +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +fStretchRandom (1) = (FRnd () * m_fStretchWidth * 2 - m_fStretchWidth ) + 1; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +fStretchRandom (2) = (FRnd () * m_fStretchHeight * 2 - m_fStretchHeight ) + 1; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +fStretchRandom (3) = (FRnd () * m_fStretchDepth * 2 - m_fStretchDepth ) + 1; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D vOldStretch = penLava -> GetModelObject () -> mo_Stretch ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +penLava -> GetModelObject () -> mo_Stretch = FLOAT3D ( +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +m_fStretchAll * m_fStretchX * fStretchRandom (1) * vOldStretch (1) , +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +m_fStretchAll * m_fStretchY * fStretchRandom (2) * vOldStretch (2) , +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +m_fStretchAll * m_fStretchZ * fStretchRandom (3) * vOldStretch (3)); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +penLava -> ModelChangeNotify (); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +} +BOOL CEruptor:: +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Active(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEruptor_Active + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEruptor::Active expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00d50001, FALSE, EBegin());return TRUE;}BOOL CEruptor::H0x00d50001_Active_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d50001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +Call(STATE_CURRENT, STATE_CEruptor_AutoSpawns, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EEnvironmentStop):{const EEnvironmentStop&e= (EEnvironmentStop&)__eeInput; +Jump(STATE_CURRENT, STATE_CEruptor_Inactive, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +}return TRUE;}BOOL CEruptor::H0x00d50002_Active_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d50002 + ASSERT(FALSE); return TRUE;};BOOL CEruptor:: +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Inactive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEruptor_Inactive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEruptor::Inactive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00d50004, FALSE, EBegin());return TRUE;}BOOL CEruptor::H0x00d50004_Inactive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d50004 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EEnvironmentStart):{const EEnvironmentStart&e= (EEnvironmentStart&)__eeInput; +Jump(STATE_CURRENT, STATE_CEruptor_Active, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +}return TRUE;}BOOL CEruptor::H0x00d50005_Inactive_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d50005 + ASSERT(FALSE); return TRUE;};BOOL CEruptor:: +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +AutoSpawns(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEruptor_AutoSpawns + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEruptor::AutoSpawns expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Jump(STATE_CURRENT,0x00d5000c, FALSE, EInternal());return TRUE;}BOOL CEruptor::H0x00d5000c_AutoSpawns_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d5000c +if(!(TRUE )){ Jump(STATE_CURRENT,0x00d5000d, FALSE, EInternal());return TRUE;} +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +SetTimerAfter(m_fTime ); +Jump(STATE_CURRENT, 0x00d50007, FALSE, EBegin());return TRUE;}BOOL CEruptor::H0x00d50007_AutoSpawns_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d50007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00d50008, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEruptor::H0x00d50008_AutoSpawns_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d50008 +; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +SpawnRandom (); +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(!(m_fRandomWait > 0.0f)){ Jump(STATE_CURRENT,0x00d5000b, FALSE, EInternal());return TRUE;}SetTimerAfter(m_fRandomWait ); +Jump(STATE_CURRENT, 0x00d50009, FALSE, EBegin());return TRUE;}BOOL CEruptor::H0x00d50009_AutoSpawns_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d50009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00d5000a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEruptor::H0x00d5000a_AutoSpawns_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d5000a +;Jump(STATE_CURRENT,0x00d5000b, FALSE, EInternal());return TRUE;}BOOL CEruptor::H0x00d5000b_AutoSpawns_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d5000b +Jump(STATE_CURRENT,0x00d5000c, FALSE, EInternal());return TRUE; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +}BOOL CEruptor::H0x00d5000d_AutoSpawns_07(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d5000d + ASSERT(FALSE); return TRUE;};BOOL CEruptor:: +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +MainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEruptor_MainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEruptor::MainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00d5000f, FALSE, EBegin());return TRUE;}BOOL CEruptor::H0x00d5000f_MainLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d5000f +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Call(STATE_CURRENT, STATE_CEruptor_Inactive, TRUE, EVoid());return TRUE; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +SpawnShoot (eTrigger . penCaused ); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +return TRUE; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +}return TRUE;}BOOL CEruptor::H0x00d50010_MainLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d50010 + +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Destroy (); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Return(STATE_CURRENT,EVoid()); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEruptor:: +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEruptor_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEruptor::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +CModelHolder2 :: InitModelHolder (); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_fTime <= 0.0f){m_fTime = 0.05f;} +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_fMaxSpeed < m_fMinSpeed ){m_fMaxSpeed = m_fMinSpeed ;} +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_fAngle < 0.0f){m_fAngle = 0.0f;} +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(Abs (m_fStretchX ) < 0.01f){m_fStretchX = 0.01f;} +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(Abs (m_fStretchY ) < 0.01f){m_fStretchY = 0.01f;} +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(Abs (m_fStretchZ ) < 0.01f){m_fStretchZ = 0.01f;} +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_fStretchAll < 0.01f){m_fStretchAll = 0.01f;} +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(Abs (m_fStretchX ) > 100.0f){m_fStretchX = 100.0f * Sgn (m_fStretchX );} +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(Abs (m_fStretchY ) > 100.0f){m_fStretchY = 100.0f * Sgn (m_fStretchY );} +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(Abs (m_fStretchZ ) > 100.0f){m_fStretchZ = 100.0f * Sgn (m_fStretchZ );} +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_fStretchAll > 100.0f){m_fStretchAll = 100.0f;} +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_fStretchWidth < 0.0f){m_fStretchWidth = 0.0f;}; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_fStretchHeight < 0.0f){m_fStretchHeight = 0.0f;}; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_fStretchDepth < 0.0f){m_fStretchDepth = 0.0f;}; +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_fStretchWidth > 1.0f){m_fStretchWidth = 1.0f;}; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_fStretchHeight > 1.0f){m_fStretchHeight = 1.0f;}; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +if(m_fStretchDepth > 1.0f){m_fStretchDepth = 1.0f;}; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Jump(STATE_CURRENT, STATE_CEruptor_MainLoop, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Eruptor.es b/Sources/EntitiesMP/Eruptor.es new file mode 100644 index 0000000..75bd049 --- /dev/null +++ b/Sources/EntitiesMP/Eruptor.es @@ -0,0 +1,273 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +213 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/ModelHolder2"; +uses "EntitiesMP/Projectile"; + +class CEruptor : CModelHolder2 { +name "Eruptor"; +thumbnail "Thumbnails\\Eruptor.tbn"; +features "HasName", "IsTargetable"; + +properties: + // stretch + 10 FLOAT m_fStretchAll "Er StretchAll" = 1.0f, + 11 FLOAT m_fStretchX "Er StretchX" = 1.0f, + 12 FLOAT m_fStretchY "Er StretchY" = 1.0f, + 13 FLOAT m_fStretchZ "Er StretchZ" = 1.0f, + + // random stretch + 15 BOOL m_bRandomStretch "Er Stretch Random" = FALSE, // random stretch + 16 FLOAT m_fStretchHeight "Er Stretch Height (Y%)" = 0.2f, // stretch height + 17 FLOAT m_fStretchWidth "Er Stretch Width (X%)" = 0.2f, // stretch width + 18 FLOAT m_fStretchDepth "Er Stretch Depth (Z%)" = 0.2f, // strecth depth + + // spawn properties + 20 FLOAT m_fAngle "Er Angle" 'Q' = 45.0f, // spawn spatial angle + 21 FLOAT m_fMaxSpeed "Er Speed max" 'V' = 20.0f, // max speed + 22 FLOAT m_fMinSpeed "Er Speed min" 'B' = 10.0f, // min speed + 23 FLOAT m_fTime "Er Spawn time" 'F' = 1.0f, // spawn every x seconds + 24 FLOAT m_fRandomWait "Er Random wait" 'G' = 0.0f, // wait between two spawns + 25 enum ProjectileType m_ptType "Er Type" 'T' = PRT_LAVA_COMET, + 26 BOOL m_bShootInArc "Er Shoot In Arc" 'S' = TRUE, + + 27 FLOAT m_fProjectileStretch "Er projectile stretch" = 1.0f, // strecth + +components: + 1 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + +functions: + void Precache(void) { + PrecacheClass(CLASS_PROJECTILE, m_ptType); + } + + /* calculates launch velocity and heading correction for angular launch */ + void CalculateAngularLaunchParams( + CMovableEntity *penTarget, + FLOAT3D vShooting, + FLOAT3D vTarget, FLOAT3D vSpeedDest, + ANGLE aPitch, + ANGLE &aHeading, + FLOAT &fLaunchSpeed) + { + FLOAT3D vNewTarget = vTarget; + FLOAT3D &vGravity = penTarget->en_vGravityDir; + FLOAT fa = TanFast(AngleDeg(aPitch)); + FLOAT3D vd, vyd0; + FLOAT fd, fyd0; + FLOAT fTime = 0.0f; + FLOAT fLastTime = 0.0f; + + INDEX iIterations = 0; + + do + { + iIterations++; + FLOAT3D vDistance = vNewTarget-vShooting; + GetParallelAndNormalComponents(vDistance, vGravity, vyd0, vd); + fd = vd.Length(); + fyd0 = vyd0.Length(); + fLastTime=fTime; + fTime = Sqrt(2.0f)*Sqrt((fa*fd-fyd0)/penTarget->en_fGravityA); + vNewTarget = vTarget+vSpeedDest*fTime; + } + while( Abs(fTime-fLastTime) > _pTimer->TickQuantum && iIterations<10); + + // calculate launch speed + fLaunchSpeed = 0.707108f*fd/ + (Cos(AngleDeg(aPitch))*Sqrt((fa*fd-fyd0)/penTarget->en_fGravityA)); + // calculate heading correction + FLOAT3D vDir = (vNewTarget-vShooting).Normalize(); + ANGLE3D aAngles; + DirectionVectorToAngles(vDir, aAngles); + aHeading = aAngles(1); + } + + // spawn one projectile towards the target + void SpawnShoot(CEntity *penTarget) + { + // if not movable entity + if (penTarget==NULL || !(penTarget->GetPhysicsFlags()&EPF_MOVABLE)) { + // do nothing + return; + } + + CPlacement3D plLava = GetPlacement(); + + FLOAT fSpeed = (m_fMaxSpeed-m_fMinSpeed)*FRnd() + m_fMinSpeed; + + // if shootind with free falling projectile + if (m_bShootInArc) { + // calculate speed for angular launch + FLOAT fPitch = GetPlacement().pl_OrientationAngle(2); + FLOAT fHeading; + CalculateAngularLaunchParams((CMovableEntity*)penTarget, + GetPlacement().pl_PositionVector, + penTarget->GetPlacement().pl_PositionVector, + ((CMovableEntity*)penTarget)->en_vCurrentTranslationAbsolute, + fPitch, fHeading, fSpeed); + + // if the heading is out of range + if (Abs(NormalizeAngle(GetPlacement().pl_OrientationAngle(1)-fHeading)) >m_fAngle) { + // do nothing + return; + } + plLava.pl_OrientationAngle(1) = fHeading; + // if shootind with propelled projectile + } else { + // calculate direction + FLOAT3D vTargetDir = (penTarget->GetPlacement().pl_PositionVector- + GetPlacement().pl_PositionVector).Normalize(); + FLOAT3D vShootDir; + AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, vShootDir); + + // if the heading is out of range + if (Abs(vTargetDir%vShootDir) < Cos(m_fAngle)) { + // do nothing + return; + } + + DirectionVectorToAngles(vTargetDir, plLava.pl_OrientationAngle); + } + + // create lava + SpawnProjectile(plLava, fSpeed); + } + + // spawn one projectile in random direction + void SpawnRandom(void) + { + // generate speed + FLOAT fSpeed = (m_fMaxSpeed-m_fMinSpeed)*FRnd() + m_fMinSpeed; + ANGLE3D aAngle((FRnd()*2-1)*m_fAngle, (FRnd()*2-1)*m_fAngle, 0); + // create placement + CPlacement3D plLava(FLOAT3D(0, 0, 0), aAngle); + plLava.RelativeToAbsolute(GetPlacement()); + + SpawnProjectile(plLava, fSpeed); + } + + // fire projectile in given direction with given speed + void SpawnProjectile(const CPlacement3D &pl, FLOAT fSpeed) + { + CEntityPointer penLava = CreateEntity(pl, CLASS_PROJECTILE); + + // launch + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = m_ptType; + eLaunch.fSpeed = fSpeed; + eLaunch.fStretch=m_fProjectileStretch; + penLava->Initialize(eLaunch); + + // stretch + if (!(penLava->GetFlags()&ENF_DELETED)) { + FLOAT3D fStretchRandom(1, 1, 1); + if (m_bRandomStretch) { + fStretchRandom(1) = (FRnd()*m_fStretchWidth *2 - m_fStretchWidth ) + 1; + fStretchRandom(2) = (FRnd()*m_fStretchHeight*2 - m_fStretchHeight) + 1; + fStretchRandom(3) = (FRnd()*m_fStretchDepth *2 - m_fStretchDepth ) + 1; + } + FLOAT3D vOldStretch = penLava->GetModelObject()->mo_Stretch; + penLava->GetModelObject()->mo_Stretch = FLOAT3D( + m_fStretchAll*m_fStretchX*fStretchRandom(1)*vOldStretch(1), + m_fStretchAll*m_fStretchY*fStretchRandom(2)*vOldStretch(2), + m_fStretchAll*m_fStretchZ*fStretchRandom(3)*vOldStretch(3)); + penLava->ModelChangeNotify(); + } + } +procedures: +/************************************************************ + * A C T I O N S * + ************************************************************/ + // active state + Active(EVoid) + { + wait() { + on (EBegin) : { call AutoSpawns(); } + on (EEnvironmentStop) : { jump Inactive(); } + } + }; + + // inactive state + Inactive(EVoid) + { + wait() { + on (EBegin) : { resume; } + on (EEnvironmentStart) : { jump Active(); } + } + }; + + // spawn projectiles automatically + AutoSpawns(EVoid) + { + while (TRUE) { + // wait before spawn next + autowait(m_fTime); + + // spawn one projectile + SpawnRandom(); + + // random wait + if (m_fRandomWait > 0.0f) { autowait(m_fRandomWait); } + } + }; + + + +/************************************************************ + * M A I N L O O P * + ************************************************************/ + // main loop + MainLoop(EVoid) { + wait() { + on(EBegin) : { + call Inactive(); + }; + on(ETrigger eTrigger) : { + SpawnShoot(eTrigger.penCaused); + resume; + } + otherwise() : {resume;}; + } + + // cease to exist + Destroy(); + + return; + }; + + Main(EVoid) { + // init as model + CModelHolder2::InitModelHolder(); + + // limit values + if (m_fTime <= 0.0f) { m_fTime = 0.05f; } + if (m_fMaxSpeed < m_fMinSpeed) { m_fMaxSpeed = m_fMinSpeed; } + if (m_fAngle < 0.0f) { m_fAngle = 0.0f; } + + // stretch factors must not have extreme values + if (Abs(m_fStretchX) < 0.01f) { m_fStretchX = 0.01f; } + if (Abs(m_fStretchY) < 0.01f) { m_fStretchY = 0.01f; } + if (Abs(m_fStretchZ) < 0.01f) { m_fStretchZ = 0.01f; } + if (m_fStretchAll< 0.01f) { m_fStretchAll = 0.01f; } + + if (Abs(m_fStretchX) >100.0f) { m_fStretchX = 100.0f*Sgn(m_fStretchX); } + if (Abs(m_fStretchY) >100.0f) { m_fStretchY = 100.0f*Sgn(m_fStretchY); } + if (Abs(m_fStretchZ) >100.0f) { m_fStretchZ = 100.0f*Sgn(m_fStretchZ); } + if (m_fStretchAll>100.0f) { m_fStretchAll = 100.0f; } + + if (m_fStretchWidth <0.0f) { m_fStretchWidth = 0.0f; }; + if (m_fStretchHeight<0.0f) { m_fStretchHeight = 0.0f; }; + if (m_fStretchDepth <0.0f) { m_fStretchDepth = 0.0f; }; + if (m_fStretchWidth >1.0f) { m_fStretchWidth = 1.0f; }; + if (m_fStretchHeight>1.0f) { m_fStretchHeight = 1.0f; }; + if (m_fStretchDepth >1.0f) { m_fStretchDepth = 1.0f; }; + + jump MainLoop(); + } +}; diff --git a/Sources/EntitiesMP/Eruptor.h b/Sources/EntitiesMP/Eruptor.h new file mode 100644 index 0000000..8032dfc --- /dev/null +++ b/Sources/EntitiesMP/Eruptor.h @@ -0,0 +1,92 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Eruptor_INCLUDED +#define _EntitiesMP_Eruptor_INCLUDED 1 +#include +#include +extern "C" DECL_DLL CDLLEntityClass CEruptor_DLLClass; +class CEruptor : public CModelHolder2 { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fStretchAll; + FLOAT m_fStretchX; + FLOAT m_fStretchY; + FLOAT m_fStretchZ; + BOOL m_bRandomStretch; + FLOAT m_fStretchHeight; + FLOAT m_fStretchWidth; + FLOAT m_fStretchDepth; + FLOAT m_fAngle; + FLOAT m_fMaxSpeed; + FLOAT m_fMinSpeed; + FLOAT m_fTime; + FLOAT m_fRandomWait; + enum ProjectileType m_ptType; + BOOL m_bShootInArc; + FLOAT m_fProjectileStretch; + +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +void Precache(void); + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +void CalculateAngularLaunchParams( +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +CMovableEntity * penTarget, +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D vShooting, +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT3D vTarget,FLOAT3D vSpeedDest, +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +ANGLE aPitch, +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +ANGLE & aHeading, +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +FLOAT & fLaunchSpeed); + +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +void SpawnShoot(CEntity * penTarget); + +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +void SpawnRandom(void); + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +void SpawnProjectile(const CPlacement3D & pl,FLOAT fSpeed); +#define STATE_CEruptor_Active 0x00d50000 + BOOL +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Active(const CEntityEvent &__eeInput); + BOOL H0x00d50001_Active_01(const CEntityEvent &__eeInput); + BOOL H0x00d50002_Active_02(const CEntityEvent &__eeInput); +#define STATE_CEruptor_Inactive 0x00d50003 + BOOL +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Inactive(const CEntityEvent &__eeInput); + BOOL H0x00d50004_Inactive_01(const CEntityEvent &__eeInput); + BOOL H0x00d50005_Inactive_02(const CEntityEvent &__eeInput); +#define STATE_CEruptor_AutoSpawns 0x00d50006 + BOOL +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +AutoSpawns(const CEntityEvent &__eeInput); + BOOL H0x00d50007_AutoSpawns_01(const CEntityEvent &__eeInput); + BOOL H0x00d50008_AutoSpawns_02(const CEntityEvent &__eeInput); + BOOL H0x00d50009_AutoSpawns_03(const CEntityEvent &__eeInput); + BOOL H0x00d5000a_AutoSpawns_04(const CEntityEvent &__eeInput); + BOOL H0x00d5000b_AutoSpawns_05(const CEntityEvent &__eeInput); + BOOL H0x00d5000c_AutoSpawns_06(const CEntityEvent &__eeInput); + BOOL H0x00d5000d_AutoSpawns_07(const CEntityEvent &__eeInput); +#define STATE_CEruptor_MainLoop 0x00d5000e + BOOL +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +MainLoop(const CEntityEvent &__eeInput); + BOOL H0x00d5000f_MainLoop_01(const CEntityEvent &__eeInput); + BOOL H0x00d50010_MainLoop_02(const CEntityEvent &__eeInput); +#define STATE_CEruptor_Main 1 + BOOL +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Eruptor_INCLUDED diff --git a/Sources/EntitiesMP/Eruptor_tables.h b/Sources/EntitiesMP/Eruptor_tables.h new file mode 100644 index 0000000..fa1f901 --- /dev/null +++ b/Sources/EntitiesMP/Eruptor_tables.h @@ -0,0 +1,74 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CEruptor + +CEntityProperty CEruptor_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+10, offsetof(CEruptor, m_fStretchAll), "Er StretchAll", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+11, offsetof(CEruptor, m_fStretchX), "Er StretchX", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+12, offsetof(CEruptor, m_fStretchY), "Er StretchY", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+13, offsetof(CEruptor, m_fStretchZ), "Er StretchZ", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d5<<8)+15, offsetof(CEruptor, m_bRandomStretch), "Er Stretch Random", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+16, offsetof(CEruptor, m_fStretchHeight), "Er Stretch Height (Y%)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+17, offsetof(CEruptor, m_fStretchWidth), "Er Stretch Width (X%)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+18, offsetof(CEruptor, m_fStretchDepth), "Er Stretch Depth (Z%)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+20, offsetof(CEruptor, m_fAngle), "Er Angle", 'Q', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+21, offsetof(CEruptor, m_fMaxSpeed), "Er Speed max", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+22, offsetof(CEruptor, m_fMinSpeed), "Er Speed min", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+23, offsetof(CEruptor, m_fTime), "Er Spawn time", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+24, offsetof(CEruptor, m_fRandomWait), "Er Random wait", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &ProjectileType_enum, (0x000000d5<<8)+25, offsetof(CEruptor, m_ptType), "Er Type", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d5<<8)+26, offsetof(CEruptor, m_bShootInArc), "Er Shoot In Arc", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d5<<8)+27, offsetof(CEruptor, m_fProjectileStretch), "Er projectile stretch", 0, 0x7F0000FFUL, 0), +}; +#define CEruptor_propertiesct ARRAYCOUNT(CEruptor_properties) + +CEntityComponent CEruptor_components[] = { +#define CLASS_PROJECTILE ((0x000000d5<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +}; +#define CEruptor_componentsct ARRAYCOUNT(CEruptor_components) + +CEventHandlerEntry CEruptor_handlers[] = { + {0x00d50000, -1, CEntity::pEventHandler(&CEruptor:: +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Active),DEBUGSTRING("CEruptor::Active")}, + {0x00d50001, -1, CEntity::pEventHandler(&CEruptor::H0x00d50001_Active_01), DEBUGSTRING("CEruptor::H0x00d50001_Active_01")}, + {0x00d50002, -1, CEntity::pEventHandler(&CEruptor::H0x00d50002_Active_02), DEBUGSTRING("CEruptor::H0x00d50002_Active_02")}, + {0x00d50003, -1, CEntity::pEventHandler(&CEruptor:: +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Inactive),DEBUGSTRING("CEruptor::Inactive")}, + {0x00d50004, -1, CEntity::pEventHandler(&CEruptor::H0x00d50004_Inactive_01), DEBUGSTRING("CEruptor::H0x00d50004_Inactive_01")}, + {0x00d50005, -1, CEntity::pEventHandler(&CEruptor::H0x00d50005_Inactive_02), DEBUGSTRING("CEruptor::H0x00d50005_Inactive_02")}, + {0x00d50006, -1, CEntity::pEventHandler(&CEruptor:: +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +AutoSpawns),DEBUGSTRING("CEruptor::AutoSpawns")}, + {0x00d50007, -1, CEntity::pEventHandler(&CEruptor::H0x00d50007_AutoSpawns_01), DEBUGSTRING("CEruptor::H0x00d50007_AutoSpawns_01")}, + {0x00d50008, -1, CEntity::pEventHandler(&CEruptor::H0x00d50008_AutoSpawns_02), DEBUGSTRING("CEruptor::H0x00d50008_AutoSpawns_02")}, + {0x00d50009, -1, CEntity::pEventHandler(&CEruptor::H0x00d50009_AutoSpawns_03), DEBUGSTRING("CEruptor::H0x00d50009_AutoSpawns_03")}, + {0x00d5000a, -1, CEntity::pEventHandler(&CEruptor::H0x00d5000a_AutoSpawns_04), DEBUGSTRING("CEruptor::H0x00d5000a_AutoSpawns_04")}, + {0x00d5000b, -1, CEntity::pEventHandler(&CEruptor::H0x00d5000b_AutoSpawns_05), DEBUGSTRING("CEruptor::H0x00d5000b_AutoSpawns_05")}, + {0x00d5000c, -1, CEntity::pEventHandler(&CEruptor::H0x00d5000c_AutoSpawns_06), DEBUGSTRING("CEruptor::H0x00d5000c_AutoSpawns_06")}, + {0x00d5000d, -1, CEntity::pEventHandler(&CEruptor::H0x00d5000d_AutoSpawns_07), DEBUGSTRING("CEruptor::H0x00d5000d_AutoSpawns_07")}, + {0x00d5000e, -1, CEntity::pEventHandler(&CEruptor:: +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +MainLoop),DEBUGSTRING("CEruptor::MainLoop")}, + {0x00d5000f, -1, CEntity::pEventHandler(&CEruptor::H0x00d5000f_MainLoop_01), DEBUGSTRING("CEruptor::H0x00d5000f_MainLoop_01")}, + {0x00d50010, -1, CEntity::pEventHandler(&CEruptor::H0x00d50010_MainLoop_02), DEBUGSTRING("CEruptor::H0x00d50010_MainLoop_02")}, + {1, -1, CEntity::pEventHandler(&CEruptor:: +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Eruptor.es" +Main),DEBUGSTRING("CEruptor::Main")}, +}; +#define CEruptor_handlersct ARRAYCOUNT(CEruptor_handlers) + +CEntity *CEruptor_New(void) { return new CEruptor; }; +void CEruptor_OnInitClass(void) {}; +void CEruptor_OnEndClass(void) {}; +void CEruptor_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEruptor_OnWorldEnd(CWorld *pwo) {}; +void CEruptor_OnWorldInit(CWorld *pwo) {}; +void CEruptor_OnWorldTick(CWorld *pwo) {}; +void CEruptor_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEruptor, CModelHolder2, "Eruptor", "Thumbnails\\Eruptor.tbn", 0x000000d5); +DECLARE_CTFILENAME(_fnmCEruptor_tbn, "Thumbnails\\Eruptor.tbn"); diff --git a/Sources/EntitiesMP/ExotechLarva.cpp b/Sources/EntitiesMP/ExotechLarva.cpp new file mode 100644 index 0000000..5aaeb44 --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarva.cpp @@ -0,0 +1,2210 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" + +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/Common/PathFinding.h" +#include "EntitiesMP/NavigationMarker.h" +#include "ModelsMP/Enemies/ExotechLarva/ExotechLarva.h" +#include "ModelsMP/Enemies/ExotechLarva/Body.h" +#include "ModelsMP/Enemies/ExotechLarva/Arm.h" +#include "ModelsMP/Enemies/ExotechLarva/BackArms.h" +#include "ModelsMP/Enemies/ExotechLarva/Weapons/PlasmaGun.h" + +#include +#include +CEntityEvent *ELarvaArmDestroyed::MakeCopy(void) { CEntityEvent *peeCopy = new ELarvaArmDestroyed(*this); return peeCopy;} +ELarvaArmDestroyed::ELarvaArmDestroyed() : CEntityEvent(EVENTCODE_ELarvaArmDestroyed) {; + ClearToDefault(iArm); +}; +CEntityEvent *ELarvaRechargePose::MakeCopy(void) { CEntityEvent *peeCopy = new ELarvaRechargePose(*this); return peeCopy;} +ELarvaRechargePose::ELarvaRechargePose() : CEntityEvent(EVENTCODE_ELarvaRechargePose) {; + ClearToDefault(bStart); +}; +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" + +// info structure +static EntityInfo eiExotechLarva = { + EIBT_FLESH, 9999999999.9f, + 0.0f, -1.0f, 0.0f, // source (eyes) + 0.0f, -1.5f, 0.0f, // target (body) + }; + +#define MF_MOVEZ (1L<<0) + +#define LARVA_HANDLE_TRANSLATE 4.4f +#define FIREPOS_PLASMA_RIGHT FLOAT3D(+3.08f, -1.20f+LARVA_HANDLE_TRANSLATE, -0.16f) +#define FIREPOS_PLASMA_LEFT FLOAT3D(-3.08f, -1.20f+LARVA_HANDLE_TRANSLATE, -0.16f) +#define FIREPOS_LASER_RIGHT FLOAT3D(+2.31f, 0.16f+LARVA_HANDLE_TRANSLATE, -3.57f) +#define FIREPOS_LASER_LEFT FLOAT3D(-2.20f, 0.18f+LARVA_HANDLE_TRANSLATE, -3.57f) +#define FIREPOS_TAIL FLOAT3D( 0.00f, -2.64f+LARVA_HANDLE_TRANSLATE, -0.22f) +//#define FIREPOS_MOUTH FLOAT3D( 0.00f, -0.75f, -2.09f) + + +// PERCENT_RIGHTBLOW has to be greater then PERCENT_LEFTBLOW or some things +// won't work correctly +#define PERCENT_RIGHTBLOW 0.6666f +#define PERCENT_LEFTBLOW 0.3333f + +#define ARM_LEFT (1L<<0) +#define ARM_RIGHT (1L<<1) + + +void CExotechLarva::SetDefaultProperties(void) { + m_penMarkerNew = NULL; + m_penMarkerOld = NULL; + m_fStopRadius = 25.0f; + m_fStretch = 2.5f; + m_fLarvaHealth = 20000.0f; + m_fRechargePerSecond = 100.0f; + m_ltTarget = LT_ENEMY ; + m_penFirstRechargeTarget = NULL; + m_bRechargedAtLeastOnce = FALSE ; + m_vFirePosLeftPlasmaRel = FLOAT3D(0.0f , 0.0f , 0.0f); + m_vFirePosRightPlasmaRel = FLOAT3D(0.0f , 0.0f , 0.0f); + m_vFirePosTailRel = FLOAT3D(0.0f , 0.0f , 0.0f); + m_vFirePosLeftLaserAbs = FLOAT3D(0.0f , 0.0f , 0.0f); + m_vFirePosRightLaserAbs = FLOAT3D(0.0f , 0.0f , 0.0f); + m_bLeftArmActive = TRUE ; + m_bRightArmActive = TRUE ; + m_iExplodingArm = 1; + m_fMaxRechargedHealth = 1.0f; + m_bExploding = FALSE ; + m_bActive = TRUE ; + m_bRechargePose = FALSE ; + m_bLaserActive = FALSE ; + m_bInitialMove = TRUE ; + m_penRecharger = NULL; + m_tmLastTargateChange = 0.0f; + m_plExpArmPos = CPlacement3D(FLOAT3D (0 , 0 , 0) , ANGLE3D (0 , 0 , 0)); + m_aExpArmRot = FLOAT3D(0.0f , 0.0f , 0.0f); + m_plExpGunPos = CPlacement3D(FLOAT3D (0 , 0 , 0) , ANGLE3D (0 , 0 , 0)); + m_aExpGunRot = FLOAT3D(0.0f , 0.0f , 0.0f); + m_vExpDamage = FLOAT3D(0.0f , 0.0f , 0.0f); + m_iExplosions = 0; + m_iRnd = 0; + m_bRecharging = FALSE ; + m_penDeathInflictor = NULL; + m_tmDontFireLaserBefore = 0.0f; + m_fMinimumLaserWait = 5.0f; + m_bRenderLeftLaser = FALSE ; + m_bRenderRightLaser = FALSE ; + m_vLeftLaserTarget = FLOAT3D(0.0f , 0.0f , 0.0f); + m_vRightLaserTarget = FLOAT3D(0.0f , 0.0f , 0.0f); + m_bInvulnerable = FALSE ; + m_penLeftArmDestroyTarget = NULL; + m_penRightArmDestroyTarget = NULL; + m_penDeathTarget = NULL; + m_soFire1.SetOwner(this); +m_soFire1.Stop_internal(); + m_soFire2.SetOwner(this); +m_soFire2.Stop_internal(); + m_soFire3.SetOwner(this); +m_soFire3.Stop_internal(); + m_soVoice.SetOwner(this); +m_soVoice.Stop_internal(); + m_soChirp.SetOwner(this); +m_soChirp.Stop_internal(); + m_soLaser.SetOwner(this); +m_soLaser.Stop_internal(); + CEnemyBase::SetDefaultProperties(); +} + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BOOL CExotechLarva::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(slPropertyOffset == offsetof (CExotechLarva , m_penMarkerNew )) +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(IsOfClass (penTarget , "NavigationMarker")){return TRUE ;} +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +else {return FALSE ;} +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(slPropertyOffset == offsetof (CExotechLarva , m_penRecharger )) +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(IsOfClass (penTarget , "ExotechLarvaCharger")){return TRUE ;} +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +else {return FALSE ;} +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return CEntity :: IsTargetValid (slPropertyOffset , penTarget ); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BOOL CExotechLarva::DoSafetyChecks(void) { +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_penMarkerNew == NULL ){ +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +WarningMessage ("First ExotechLarva marker not set! Destroying Larva...\n"); +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return FALSE ; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_penRecharger == NULL ){ +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +WarningMessage ("ExotechLarva Recharger target not set! Destroying Larva...\n"); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return FALSE ; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE ; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::FindNewTarget() { +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_penEnemy != NULL ){ +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_penEnemy -> GetFlags () & ENF_ALIVE && ! (m_penEnemy -> GetFlags () & ENF_DELETED )){ +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return ; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +INDEX ctMaxPlayers = GetMaxPlayers (); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntity * penPlayer ; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +for(INDEX i = 0;i < ctMaxPlayers ;i ++){ +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penPlayer = GetPlayerEntity (i ); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(penPlayer != NULL && DistanceTo (this , penPlayer ) < 200.0f){ +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(penPlayer != NULL && (penPlayer -> GetFlags () & ENF_ALIVE ) && +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +! (penPlayer -> GetFlags () & ENF_DELETED )){ +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_penEnemy = penPlayer ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BOOL CExotechLarva::AnyPlayerCloserThen(FLOAT fDistance) { +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BOOL bClose = FALSE ; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +INDEX ctMaxPlayers = GetMaxPlayers (); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntity * penPlayer ; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +for(INDEX i = 0;i < ctMaxPlayers ;i ++){ +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penPlayer = GetPlayerEntity (i ); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(penPlayer != NULL ){ +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if((penPlayer -> GetFlags () & ENF_ALIVE ) && +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +! (penPlayer -> GetFlags () & ENF_DELETED ) && +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +DistanceTo (this , penPlayer ) < fDistance ) +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +bClose = TRUE ; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return bClose ; +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::PerhapsChangeTarget() { +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(! m_penEnemy ){return ;} +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_tmLastTargateChange + 5.0f < _pTimer -> CurrentTick ()){ +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +MaybeSwitchToAnotherPlayer (); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_tmLastTargateChange = _pTimer -> CurrentTick (); +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +class CWorldSettingsController * CExotechLarva::GetWSC(void) +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CWorldSettingsController * pwsc = NULL ; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CBackgroundViewer * penBcgViewer = (CBackgroundViewer *) GetWorld () -> GetBackgroundViewer (); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(penBcgViewer != NULL ){ +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc = (CWorldSettingsController *) & * penBcgViewer -> m_penWorldSettingsController ; +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return pwsc ; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::ShakeItBaby(FLOAT tmShaketime,FLOAT fPower,BOOL bFadeIn) +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CWorldSettingsController * pwsc = GetWSC (); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(pwsc != NULL ){ +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc -> m_tmShakeStarted = tmShaketime ; +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc -> m_vShakePos = GetPlacement () . pl_PositionVector ; +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc -> m_fShakeFalloff = 450.0f; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc -> m_fShakeFade = 3.0f; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc -> m_fShakeIntensityZ = 0; +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc -> m_tmShakeFrequencyZ = 5.0f; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc -> m_fShakeIntensityY = 0.1f * fPower ; +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc -> m_tmShakeFrequencyY = 5.0f; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc -> m_fShakeIntensityB = 2.5f * fPower ; +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc -> m_tmShakeFrequencyB = 7.2f; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pwsc -> m_bShakeFadeIn = bFadeIn ; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::ShootTailProjectile(void) { +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_penEnemy == NULL ){return ;} +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vShootTarget ; +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetEntityInfoPosition (m_penEnemy , peiTarget -> vTargetCenter , vShootTarget ); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CPlacement3D pl ; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PreparePropelledProjectile (pl , vShootTarget , m_vFirePosTailRel , ANGLE3D (0 , - 10 , 0)); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_LARVAOFFSPRING ); +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ELaunchLarvaOffspring ello ; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ello . penLauncher = this ; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penProjectile -> Initialize (ello ); +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BOOL CExotechLarva::IsOnMarker(CEntity * penMarker) { +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(penMarker == NULL ){return FALSE ;} +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(DistanceTo (this , penMarker ) < 0.1f){return TRUE ;} +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return FALSE ; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT CExotechLarva::DistanceXZ(CEntity * E1,CEntity * E2) +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vE1pos = E1 -> GetPlacement () . pl_PositionVector ; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vE2pos = E2 -> GetPlacement () . pl_PositionVector ; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vE1pos (2) = 0.0f; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vE2pos (2) = 0.0f; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return (vE2pos - vE1pos ) . Length (); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::SpawnWingDebris() +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vTranslation = m_vExpDamage + en_vCurrentTranslationAbsolute ; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Debris_Begin (EIBT_FLESH , DPT_BLOODTRAIL , BET_BLOODSTAIN , 1.0f , m_vExpDamage , en_vCurrentTranslationAbsolute , 5.0f , 2.0f); +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Debris_Spawn_Independent (this , this , MODEL_WING , TEXTURE_WING , 0 , 0 , 0 , 0 , m_fStretch , +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_plExpArmPos , vTranslation , m_aExpArmRot ); +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vTranslation += FLOAT3D (FRnd () * 4.0f - 2.0f , FRnd () * 4.0f - 2.0f , FRnd () * 4.0f - 2.0f); +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Debris_Spawn_Independent (this , this , MODEL_PLASMAGUN , TEXTURE_PLASMAGUN , 0 , 0 , 0 , 0 , m_fStretch , +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_plExpGunPos , vTranslation , m_aExpGunRot ); +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bInvulnerable ){ +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return ; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(IsOfClass (penInflictor , "ExotechLarva")){ +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return ; +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(dmtType == DMT_BULLET && fDamageAmmount > 100.0f) +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +fDamageAmmount *= 0.66f; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(dmtType == DMT_CANNONBALL ) +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +fDamageAmmount *= 0.5f; +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT fHealthNow = GetHealth (); +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT fHealthAfter = GetHealth () - fDamageAmmount ; +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT fHealthBlow01 = m_fMaxHealth * PERCENT_RIGHTBLOW ; +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT fHealthBlow02 = m_fMaxHealth * PERCENT_LEFTBLOW ; +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +fDamageAmmount *= DamageStrength (((EntityInfo *) GetEntityInfo ()) -> Eeibt , dmtType ); +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +fDamageAmmount *= GetGameDamageMultiplier (); +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(fHealthNow > fHealthBlow01 && fHealthAfter < fHealthBlow02 ){ +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +fDamageAmmount = fHealthNow - fHealthBlow01 - 1; +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(m_bExploding ){ +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(fHealthNow > fHealthBlow02 && fHealthAfter < fHealthBlow02 ){ +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +fDamageAmmount = fHealthNow - fHealthBlow02 - 1; +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(fHealthAfter < 0.0f){ +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +fDamageAmmount = fHealthNow - 1; +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(fHealthNow > fHealthBlow02 && fHealthAfter < 0){ +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +fDamageAmmount = fHealthNow - 1; +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(fDamageAmmount == 0){ +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return ; +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CPlacement3D plSpray = CPlacement3D (vHitPoint , ANGLE3D (0 , 0 , 0)); +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ESpawnSpray eSpawnSpray ; +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_fMaxDamageAmmount > 10.0f) +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnSpray . fDamagePower = 3.0f; +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +else if(m_fSprayDamage + fDamageAmmount > 50.0f) +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnSpray . fDamagePower = 2.0f; +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +else +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnSpray . fDamagePower = 1.0f; +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +switch(IRnd () % 4){ +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +case 0: case 1: case 2: +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_penSpray -> SetParent (this ); +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnSpray . sptType = SPT_BLOOD ; +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +break ; +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +case 3: +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnSpray . sptType = SPT_ELECTRICITY_SPARKS ; +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +break ; +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnSpray . fSizeMultiplier = 1.0f; +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vHitPointRelative = vHitPoint - GetPlacement () . pl_PositionVector ; +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vReflectingNormal ; +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetNormalComponent (vHitPointRelative , en_vGravityDir , vReflectingNormal ); +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vReflectingNormal . Normalize (); +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vReflectingNormal (1) /= 5.0f; +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vProjectedComponent = vReflectingNormal * (vDirection % vReflectingNormal ); +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vSpilDirection = vDirection - vProjectedComponent * 2.0f - en_vGravityDir * 0.5f; +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnSpray . vDirection = vSpilDirection ; +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnSpray . penOwner = this ; +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_penSpray -> Initialize (eSpawnSpray ); +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_tmSpraySpawned = _pTimer -> CurrentTick (); +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fSprayDamage = 0.0f; +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fMaxDamageAmmount = 0.0f; +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +en_fHealth -= fDamageAmmount ; +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(en_fHealth <= 0){ +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +EDeath eDeath ; +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendEvent (eDeath ); +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bRightArmActive ){ +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(GetHealth () < m_fMaxHealth * PERCENT_RIGHTBLOW ){ +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ELarvaArmDestroyed ead ; +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ead . iArm = ARM_RIGHT ; +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendEvent (ead ); +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bExploding = TRUE ; +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bLeftArmActive ){ +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(GetHealth () < m_fMaxHealth * PERCENT_LEFTBLOW ){ +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ELarvaArmDestroyed ead ; +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ead . iArm = ARM_LEFT ; +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendEvent (ead ); +#line 491 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bExploding = TRUE ; +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_colBurning = COLOR (C_WHITE | CT_OPAQUE ); +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + CTString CExotechLarva::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) { +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CTString str ; +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +str . PrintF (TRANS ("Exotech larva reduced %s to pulp.") , strPlayerName ); +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return str ; +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void * CExotechLarva::GetEntityInfo(void) { +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return & eiExotechLarva ; +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + const CTFileName & CExotechLarva::GetComputerMessageName(void)const { +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +static DECLARE_CTFILENAME (fnmLarva , "DataMP\\Messages\\Enemies\\ExotechLarva.txt"); +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return fnmLarva ; +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::Precache(void) { +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEnemyBase :: Precache (); +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_ROCKET ); +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_CANNON ); +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheClass (CLASS_BLOOD_SPRAY ); +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheClass (CLASS_PROJECTILE , PRT_LARVA_TAIL_PROJECTILE ); +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheClass (CLASS_PROJECTILE , PRT_LARVA_PLASMA ); +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_EXOTECHLARVA ); +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheTexture (TEXTURE_EXOTECHLARVA ); +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_BODY ); +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheTexture (TEXTURE_BODY ); +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_BEAM ); +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheTexture (TEXTURE_BEAM ); +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_ENERGYBEAMS ); +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheTexture (TEXTURE_ENERGYBEAMS ); +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_FLARE ); +#line 534 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheTexture (TEXTURE_FLARE ); +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_WING ); +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheTexture (TEXTURE_WING ); +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_PLASMAGUN ); +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheTexture (TEXTURE_PLASMAGUN ); +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_BLADES ); +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_DEBRIS_BODY ); +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_DEBRIS_TAIL01 ); +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_DEBRIS_TAIL02 ); +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_DEBRIS_FLESH ); +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheTexture (TEXTURE_DEBRIS_FLESH ); +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_PLASMA ); +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheTexture (TEXTURE_PLASMA ); +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheModel (MODEL_BODY ); +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheTexture (TEXTURE_BODY ); +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheSound (SOUND_FIRE_PLASMA ); +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheSound (SOUND_FIRE_TAIL ); +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheSound (SOUND_LASER_CHARGE ); +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheSound (SOUND_DEATH ); +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheSound (SOUND_ARMDESTROY ); +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheSound (SOUND_CHIRP ); +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PrecacheSound (SOUND_DEPLOYLASER ); +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CModelObject * CExotechLarva::PlasmaLeftModel(void) { +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CAttachmentModelObject * amo = GetModelObject () -> GetAttachmentModel (BODY_ATTACHMENT_ARM_LEFT ); +#line 565 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +amo = amo -> amo_moModelObject . GetAttachmentModel (ARM_ATTACHMENT_PLASMAGUN ); +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return & (amo -> amo_moModelObject ); +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CModelObject * CExotechLarva::PlasmaRightModel(void) { +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CAttachmentModelObject * amo = GetModelObject () -> GetAttachmentModel (BODY_ATTACHMENT_ARM_RIGHT ); +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +amo = amo -> amo_moModelObject . GetAttachmentModel (ARM_ATTACHMENT_PLASMAGUN ); +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return & (amo -> amo_moModelObject ); +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BOOL CExotechLarva::RechargerActive() { +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(((CExotechLarvaCharger *) & * m_penRecharger ) -> m_bActive ){ +#line 576 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE ; +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return FALSE ; +#line 579 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::RemoveWing(INDEX iArm) { +#line 643 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(iArm == ARM_RIGHT ){ +#line 644 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +RemoveAttachmentFromModel (* GetModelObject () , BODY_ATTACHMENT_ARM_RIGHT ); +#line 645 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(iArm == ARM_LEFT ){ +#line 648 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +RemoveAttachmentFromModel (* GetModelObject () , BODY_ATTACHMENT_ARM_LEFT ); +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 650 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 652 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ANGLE CExotechLarva::GetArmsPitch(void) { +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bLeftArmActive ){ +#line 654 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CAttachmentModelObject & amo = * GetModelObject () -> GetAttachmentModel (BODY_ATTACHMENT_ARM_LEFT ); +#line 655 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return (amo . amo_plRelative . pl_OrientationAngle (2) + GetPlacement () . pl_OrientationAngle (2)); +#line 656 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 657 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return 0.0f; +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 660 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ULONG CExotechLarva::SetDesiredMovement(void) +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ULONG ulFlags = 0; +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vPos ; +#line 664 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntity * penMarker = m_penMarkerNew ; +#line 665 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntity * penTarget ; +#line 667 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_ltTarget == LT_ENEMY && m_penEnemy ){penTarget = m_penEnemy ;} +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +else if(m_ltTarget == LT_RECHARGER ){penTarget = m_penRecharger ;} +#line 669 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +else {return ulFlags ;} +#line 673 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(IsOnMarker (m_penMarkerNew )){ +#line 674 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PATH_FindNextMarker (penTarget , GetPlacement () . pl_PositionVector , +#line 675 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penTarget -> GetPlacement () . pl_PositionVector , penMarker , vPos ); +#line 676 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(penMarker != NULL ){ +#line 678 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_penMarkerOld = m_penMarkerNew ; +#line 680 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_penMarkerNew = penMarker ; +#line 681 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 682 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +MoveToMarker (m_penMarkerNew ); +#line 683 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ulFlags |= MF_MOVEZ ; +#line 684 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else { +#line 685 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +MoveToMarker (m_penMarkerNew ); +#line 686 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ulFlags |= MF_MOVEZ ; +#line 687 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 689 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_ltTarget == LT_ENEMY && DistanceTo (this , penTarget ) < m_fStopRadius ){ +#line 690 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ForceFullStop (); +#line 691 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 693 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return ulFlags ; +#line 694 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 696 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::MoveToMarker(CEntity * penMarker) { +#line 697 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(penMarker == NULL ){return ;} +#line 698 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vDesiredDir = penMarker -> GetPlacement () . pl_PositionVector - +#line 699 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetPlacement () . pl_PositionVector ; +#line 700 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(vDesiredDir . Length () > 0.0f){ +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vDesiredDir . Normalize (); +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vSpeed = vDesiredDir * m_fAttackRunSpeed ; +#line 703 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetDesiredTranslation (vSpeed ); +#line 704 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 705 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 708 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::PreMoving() { +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bActive && ! m_bRenderLeftLaser && ! m_bRenderRightLaser ){ +#line 713 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_penEnemy != NULL ){ +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vToEnemy ; +#line 716 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vToEnemy = (m_penEnemy -> GetPlacement () . pl_PositionVector - +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetPlacement () . pl_PositionVector ) . Normalize (); +#line 718 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ANGLE3D aAngle ; +#line 719 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +DirectionVectorToAngles (vToEnemy , aAngle ); +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +aAngle (1) = aAngle (1) - GetPlacement () . pl_OrientationAngle (1); +#line 721 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +aAngle (1) = NormalizeAngle (aAngle (1)); +#line 722 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetDesiredRotation (FLOAT3D (aAngle (1) * 2.0f , 0.0f , 0.0f)); +#line 723 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else { +#line 724 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetDesiredRotation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 725 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 728 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(en_vCurrentTranslationAbsolute . Length () * _pTimer -> TickQuantum * 2.0f > +#line 729 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +DistanceTo (this , m_penMarkerNew )){ +#line 730 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vToMarker = m_penMarkerNew -> GetPlacement () . pl_PositionVector - +#line 731 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetPlacement () . pl_PositionVector ; +#line 732 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetDesiredTranslation (vToMarker / _pTimer -> TickQuantum ); +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 736 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(IsOnMarker (m_penMarkerNew )){ +#line 737 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ForceStopTranslation (); +#line 738 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 739 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else { +#line 740 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ForceFullStop (); +#line 741 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 743 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEnemyBase :: PreMoving (); +#line 744 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 746 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::RenderParticles(void) +#line 747 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 749 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOATmatrix3D m ; +#line 750 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CPlacement3D plLarva ; +#line 752 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bRenderLeftLaser || m_bRenderRightLaser ){ +#line 753 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plLarva = GetLerpedPlacement (); +#line 754 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +MakeRotationMatrix (m , plLarva . pl_OrientationAngle ); +#line 755 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 757 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bRenderLeftLaser ){ +#line 758 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vSource = (FIREPOS_LASER_LEFT * m_fStretch ) * m + plLarva . pl_PositionVector ; +#line 759 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Particles_ExotechLarvaLaser (this , vSource , m_vLeftLaserTarget ); +#line 760 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 761 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bRenderRightLaser ){ +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vSource = (FIREPOS_LASER_RIGHT * m_fStretch ) * m + plLarva . pl_PositionVector ; +#line 763 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Particles_ExotechLarvaLaser (this , vSource , m_vRightLaserTarget ); +#line 764 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 765 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bRechargePose && ((CExotechLarvaCharger *) & * m_penRecharger ) -> m_bBeamActive ) +#line 766 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 767 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Particles_LarvaEnergy (this , FLOAT3D (0.0f , LARVA_HANDLE_TRANSLATE , 0.0f) * m_fStretch ); +#line 768 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 769 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 771 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::SizeModel(void) +#line 772 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 773 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return ; +#line 774 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 776 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::UpdateFiringPos() { +#line 777 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vFirePosLeftLaserAbs = (FIREPOS_LASER_LEFT * m_fStretch ) * GetRotationMatrix () + GetPlacement () . pl_PositionVector ; +#line 778 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vFirePosRightLaserAbs = (FIREPOS_LASER_RIGHT * m_fStretch ) * GetRotationMatrix () + GetPlacement () . pl_PositionVector ; +#line 779 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 781 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::BlowUp(void) +#line 782 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 783 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +NOTHING ; +#line 784 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 787 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::EnemyPostInit(void) +#line 788 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 789 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_soFire1 . Set3DParameters (600.0f , 150.0f , 2.0f , 1.0f); +#line 790 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_soFire2 . Set3DParameters (600.0f , 150.0f , 2.0f , 1.0f); +#line 791 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_soFire3 . Set3DParameters (600.0f , 150.0f , 2.0f , 1.0f); +#line 792 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_soVoice . Set3DParameters (600.0f , 150.0f , 2.0f , 1.0f); +#line 793 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_soChirp . Set3DParameters (150.0f , 50.0f , 2.0f , 1.0f); +#line 794 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_soLaser . Set3DParameters (300.0f , 200.0f , 3.0f , 1.0f); +#line 795 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::FireLaser(void) +#line 798 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 800 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vLaserTarget ; +#line 802 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(! m_penEnemy ){return ;} +#line 804 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(IsVisible (m_penEnemy )){ +#line 805 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vLaserTarget = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 806 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(TRUE ){ +#line 807 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vLaserTarget = m_vPlayerSpotted ; +#line 808 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 811 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CCastRay crRay1 (this , m_vFirePosLeftLaserAbs , vLaserTarget ); +#line 812 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +crRay1 . cr_fTestR = 0.10f; +#line 813 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +crRay1 . cr_bHitTranslucentPortals = FALSE ; +#line 814 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +crRay1 . cr_bPhysical = FALSE ; +#line 815 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +crRay1 . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ; +#line 816 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetWorld () -> CastRay (crRay1 ); +#line 819 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(crRay1 . cr_penHit != NULL ){ +#line 820 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRenderLeftLaser = TRUE ; +#line 821 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vLeftLaserTarget = crRay1 . cr_vHit ; +#line 824 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +InflictDirectDamage (crRay1 . cr_penHit , this , DMT_BURNING , 25.0f , +#line 825 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D (0 , 0 , 0) , (m_vFirePosLeftLaserAbs - m_vLeftLaserTarget ) . Normalize ()); +#line 827 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(crRay1 . cr_penHit -> GetRenderType () != RT_BRUSH ){ +#line 828 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +crRay1 . cr_ttHitModels = CCastRay :: TT_NONE ; +#line 829 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetWorld () -> ContinueCast (crRay1 ); +#line 830 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(crRay1 . cr_penHit != NULL ){ +#line 831 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vLeftLaserTarget = crRay1 . cr_vHit ; +#line 832 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 833 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 834 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(TRUE ){ +#line 835 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRenderLeftLaser = FALSE ; +#line 836 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 839 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CCastRay crRay2 (this , m_vFirePosRightLaserAbs , vLaserTarget ); +#line 840 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +crRay2 . cr_fTestR = 0.10f; +#line 841 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +crRay2 . cr_bHitTranslucentPortals = FALSE ; +#line 842 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +crRay2 . cr_bPhysical = FALSE ; +#line 843 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +crRay2 . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ; +#line 844 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetWorld () -> CastRay (crRay2 ); +#line 847 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(crRay2 . cr_penHit != NULL ){ +#line 848 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRenderRightLaser = TRUE ; +#line 849 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vRightLaserTarget = crRay2 . cr_vHit ; +#line 852 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +InflictDirectDamage (crRay2 . cr_penHit , this , DMT_BURNING , 25.0f , +#line 853 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D (0 , 0 , 0) , (m_vFirePosRightLaserAbs - m_vRightLaserTarget ) . Normalize ()); +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(crRay2 . cr_penHit -> GetRenderType () != RT_BRUSH ){ +#line 856 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +crRay2 . cr_ttHitModels = CCastRay :: TT_NONE ; +#line 857 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetWorld () -> ContinueCast (crRay2 ); +#line 858 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(crRay2 . cr_penHit != NULL ){ +#line 859 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vRightLaserTarget = crRay2 . cr_vHit ; +#line 860 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 861 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 862 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(TRUE ){ +#line 863 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRenderRightLaser = FALSE ; +#line 864 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 865 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} + +#line 867 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void CExotechLarva::ExplodeLaser(void) +#line 868 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 869 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bRenderLeftLaser ){ +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ESpawnEffect eSpawnEffect ; +#line 871 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 872 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_CANNON ; +#line 873 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . vStretch = FLOAT3D (m_fStretch * 0.5 , m_fStretch * 0.5 , m_fStretch * 0.5); +#line 874 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntityPointer penExplosion = CreateEntity (CPlacement3D (m_vLeftLaserTarget , +#line 875 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ANGLE3D (0.0f , 0.0f , 0.0f)) , CLASS_BASIC_EFFECT ); +#line 876 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 879 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_EXPLOSION_DEBRIS ; +#line 880 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion = CreateEntity (CPlacement3D (m_vLeftLaserTarget , +#line 881 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ANGLE3D (0.0f , 0.0f , 0.0f)) , CLASS_BASIC_EFFECT ); +#line 882 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 885 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_EXPLOSION_SMOKE ; +#line 886 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion = CreateEntity (CPlacement3D (m_vLeftLaserTarget , +#line 887 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ANGLE3D (0.0f , 0.0f , 0.0f)) , CLASS_BASIC_EFFECT ); +#line 888 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 890 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +InflictRangeDamage (this , DMT_EXPLOSION , 25.0f , +#line 891 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vLeftLaserTarget , 5.0f , 25.0f); +#line 892 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 894 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bRenderRightLaser ){ +#line 895 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ESpawnEffect eSpawnEffect ; +#line 896 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 897 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_CANNON ; +#line 898 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . vStretch = FLOAT3D (m_fStretch * 0.5 , m_fStretch * 0.5 , m_fStretch * 0.5); +#line 899 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntityPointer penExplosion = CreateEntity (CPlacement3D (m_vLeftLaserTarget , +#line 900 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ANGLE3D (0.0f , 0.0f , 0.0f)) , CLASS_BASIC_EFFECT ); +#line 901 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 904 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_EXPLOSION_DEBRIS ; +#line 905 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion = CreateEntity (CPlacement3D (m_vLeftLaserTarget , +#line 906 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ANGLE3D (0.0f , 0.0f , 0.0f)) , CLASS_BASIC_EFFECT ); +#line 907 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 910 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_EXPLOSION_SMOKE ; +#line 911 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion = CreateEntity (CPlacement3D (m_vLeftLaserTarget , +#line 912 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ANGLE3D (0.0f , 0.0f , 0.0f)) , CLASS_BASIC_EFFECT ); +#line 913 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 915 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +InflictRangeDamage (this , DMT_EXPLOSION , 25.0f , +#line 916 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vLeftLaserTarget , 5.0f , 25.0f); +#line 917 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 918 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +BOOL CExotechLarva:: +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BeWounded(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarva_BeWounded + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDamage, "CExotechLarva::BeWounded expects 'EDamage' as input!"); const EDamage &eDamage = (const EDamage &)__eeInput; +#line 929 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Return(STATE_CURRENT,EReturn ()); +#line 929 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CExotechLarva:: +#line 932 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ArmExplosion(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarva_ArmExplosion + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CExotechLarva::ArmExplosion expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 934 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOATmatrix3D mRot ; +#line 935 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vPos ; +#line 937 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bActive = FALSE ; +#line 940 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_iExplodingArm == ARM_RIGHT ){ +#line 941 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +MakeRotationMatrixFast (mRot , ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 942 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vPos = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 943 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetModelForRendering () -> GetAttachmentTransformations (BODY_ATTACHMENT_ARM_RIGHT , mRot , vPos , FALSE ); +#line 944 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_plExpArmPos . pl_PositionVector = vPos * GetRotationMatrix () + GetPlacement () . pl_PositionVector ; +#line 945 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_plExpArmPos . pl_OrientationAngle = GetPlacement () . pl_OrientationAngle ; +#line 946 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CAttachmentModelObject & amo0 = * GetModelObject () -> GetAttachmentModel (BODY_ATTACHMENT_ARM_RIGHT ); +#line 947 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +amo0 . amo_moModelObject . GetAttachmentTransformations (ARM_ATTACHMENT_PLASMAGUN , mRot , vPos , FALSE ); +#line 948 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_plExpGunPos . pl_PositionVector = vPos * GetRotationMatrix () + GetPlacement () . pl_PositionVector ; +#line 949 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_plExpGunPos . pl_OrientationAngle = GetPlacement () . pl_OrientationAngle ; +#line 950 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vExpDamage = FLOAT3D (+ 12.0f , 15.0f , 0.0f); +#line 952 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_penLeftArmDestroyTarget ){ +#line 953 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendToTarget (m_penLeftArmDestroyTarget , EET_TRIGGER , FixupCausedToPlayer (this , m_penEnemy )); +#line 954 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 955 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 958 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_iExplodingArm == ARM_LEFT ){ +#line 959 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +MakeRotationMatrixFast (mRot , ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 960 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vPos = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 961 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetModelForRendering () -> GetAttachmentTransformations (BODY_ATTACHMENT_ARM_LEFT , mRot , vPos , FALSE ); +#line 962 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_plExpArmPos . pl_PositionVector = vPos * GetRotationMatrix () + GetPlacement () . pl_PositionVector ; +#line 963 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_plExpArmPos . pl_OrientationAngle = GetPlacement () . pl_OrientationAngle ; +#line 964 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_plExpArmPos . pl_OrientationAngle (1) += 180.0f; +#line 965 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CAttachmentModelObject & amo0 = * GetModelObject () -> GetAttachmentModel (BODY_ATTACHMENT_ARM_LEFT ); +#line 966 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +amo0 . amo_moModelObject . GetAttachmentTransformations (ARM_ATTACHMENT_PLASMAGUN , mRot , vPos , FALSE ); +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_plExpGunPos . pl_PositionVector = vPos * GetRotationMatrix () + GetPlacement () . pl_PositionVector ; +#line 968 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_plExpGunPos . pl_OrientationAngle = GetPlacement () . pl_OrientationAngle ; +#line 969 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vExpDamage = FLOAT3D (- 12.0f , 15.0f , 0.0f); +#line 971 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_penRightArmDestroyTarget ){ +#line 972 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendToTarget (m_penRightArmDestroyTarget , EET_TRIGGER , FixupCausedToPlayer (this , m_penEnemy )); +#line 973 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 974 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 975 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_aExpArmRot = ANGLE3D (FRnd () * 360.0f - 180.0f , FRnd () * 360.0f - 180.0f , FRnd () * 360.0f - 180.0f); +#line 976 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_aExpGunRot = ANGLE3D (FRnd () * 360.0f - 180.0f , FRnd () * 360.0f - 180.0f , FRnd () * 360.0f - 180.0f); +#line 977 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vExpDamage = m_vExpDamage * GetRotationMatrix (); +#line 979 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_iExplodingArm == ARM_RIGHT ){m_bRightArmActive = FALSE ;} +#line 980 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_iExplodingArm == ARM_LEFT ){m_bLeftArmActive = FALSE ;} +#line 982 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlaySound (m_soVoice , SOUND_ARMDESTROY , SOF_3D ); +#line 984 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CPlacement3D pl = GetPlacement (); +#line 985 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pl . pl_PositionVector += FLOAT3D (0.0f , LARVA_HANDLE_TRANSLATE , 0.0f); +#line 986 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ShakeItBaby (_pTimer -> CurrentTick () , 0.5f , FALSE ); +#line 987 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ESpawnEffect eSpawnEffect ; +#line 988 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 989 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_CANNON ; +#line 990 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . vStretch = FLOAT3D (m_fStretch * 0.5 , m_fStretch * 0.5 , m_fStretch * 0.5); +#line 991 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntityPointer penExplosion = CreateEntity (pl , CLASS_BASIC_EFFECT ); +#line 992 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 993 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(FRnd () * 0.25f + 0.15f); +Jump(STATE_CURRENT, 0x015a0004, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a0004_ArmExplosion_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015a0005, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarva::H0x015a0005_ArmExplosion_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0005 +; +#line 995 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ShakeItBaby (_pTimer -> CurrentTick () , 0.5f , FALSE ); +#line 996 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ESpawnEffect eSpawnEffect ; +#line 997 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 998 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_CANNON ; +#line 999 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . vStretch = FLOAT3D (m_fStretch , m_fStretch , m_fStretch ); +#line 1000 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CPlacement3D plMiddle ; +#line 1001 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plMiddle . pl_PositionVector = (m_plExpArmPos . pl_PositionVector + m_plExpGunPos . pl_PositionVector ) / 2.0f; +#line 1002 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plMiddle . pl_OrientationAngle = m_plExpArmPos . pl_OrientationAngle ; +#line 1003 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntityPointer penExplosion = CreateEntity (plMiddle , CLASS_BASIC_EFFECT ); +#line 1004 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1005 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(FRnd () * 0.15f + 0.15f); +Jump(STATE_CURRENT, 0x015a0006, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a0006_ArmExplosion_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015a0007, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarva::H0x015a0007_ArmExplosion_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0007 +; +#line 1007 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CPlacement3D pl = GetPlacement (); +#line 1008 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +pl . pl_PositionVector += FLOAT3D (0.0f , LARVA_HANDLE_TRANSLATE , 0.0f); +#line 1009 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ShakeItBaby (_pTimer -> CurrentTick () , 1.0f , FALSE ); +#line 1010 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ESpawnEffect eSpawnEffect ; +#line 1011 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1012 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_CANNON ; +#line 1013 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . vStretch = FLOAT3D (m_fStretch * 1.5 , m_fStretch * 1.5 , m_fStretch * 1.5); +#line 1014 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntityPointer penExplosion = CreateEntity (pl , CLASS_BASIC_EFFECT ); +#line 1015 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1016 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_ROCKET ; +#line 1017 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion = CreateEntity (m_plExpGunPos , CLASS_BASIC_EFFECT ); +#line 1018 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1020 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SpawnWingDebris (); +#line 1021 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +RemoveWing (m_iExplodingArm ); +#line 1024 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(1.5f); +Jump(STATE_CURRENT, 0x015a0008, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a0008_ArmExplosion_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015a0009, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarva::H0x015a0009_ArmExplosion_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0009 +; +#line 1026 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bExploding = FALSE ; +#line 1027 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bActive = TRUE ; +#line 1030 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendEvent (EBegin ()); +#line 1032 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Return(STATE_CURRENT,EReturn ()); +#line 1032 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CExotechLarva:: +#line 1035 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Die(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarva_Die + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDeath, "CExotechLarva::Die expects 'EDeath' as input!"); const EDeath &eDeath = (const EDeath &)__eeInput; +#line 1037 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_penDeathInflictor = eDeath . eLastDamage . penInflictor ; +#line 1039 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bActive = FALSE ; +#line 1040 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_iExplosions = 8; +#line 1042 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlaySound (m_soChirp , SOUND_DEATH , SOF_3D ); +#line 1043 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_soLaser . Stop (); +#line 1046 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Jump(STATE_CURRENT,0x015a000d, FALSE, EInternal());return TRUE;}BOOL CExotechLarva::H0x015a000d_Die_03(const CEntityEvent &__eeInput) +#line 1047 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a000d +if(!((m_iExplosions --) > 0)){ Jump(STATE_CURRENT,0x015a000e, FALSE, EInternal());return TRUE;} +#line 1048 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ShakeItBaby (_pTimer -> CurrentTick () , 0.5f , FALSE ); +#line 1051 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CPlacement3D plExplosion ; +#line 1052 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plExplosion . pl_OrientationAngle = ANGLE3D (0.0f , 0.0f , 0.0f); +#line 1053 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plExplosion . pl_PositionVector = FLOAT3D (FRnd () * 2.0 - 1.0f , FRnd () * 3.0 - 1.5f + LARVA_HANDLE_TRANSLATE , FRnd () * 2.0 - 1.0f) * m_fStretch + GetPlacement () . pl_PositionVector ; +#line 1054 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT vExpSize = (FRnd () * 0.7f + 0.7f) * m_fStretch ; +#line 1056 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ESpawnEffect eSpawnEffect ; +#line 1057 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1058 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_CANNON ; +#line 1059 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . vStretch = FLOAT3D (vExpSize , vExpSize , vExpSize ); +#line 1060 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntityPointer penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 1061 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1062 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(FRnd () * 0.05f + 0.35f); +Jump(STATE_CURRENT, 0x015a000b, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a000b_Die_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a000b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015a000c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarva::H0x015a000c_Die_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a000c +;Jump(STATE_CURRENT,0x015a000d, FALSE, EInternal());return TRUE; +#line 1063 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}BOOL CExotechLarva::H0x015a000e_Die_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a000e + +#line 1065 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ShakeItBaby (_pTimer -> CurrentTick () , 2.0f , FALSE ); +#line 1068 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CPlacement3D plExplosion ; +#line 1069 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plExplosion . pl_OrientationAngle = ANGLE3D (0.0f , 0.0f , 0.0f); +#line 1070 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plExplosion . pl_PositionVector = FLOAT3D (0.0f , - 1.5f + LARVA_HANDLE_TRANSLATE , 1.5f) * m_fStretch + GetPlacement () . pl_PositionVector ; +#line 1071 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ESpawnEffect eSpawnEffect ; +#line 1072 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1073 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_CANNON ; +#line 1074 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . vStretch = FLOAT3D (m_fStretch , m_fStretch , m_fStretch ) * 2.0f; +#line 1075 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CEntityPointer penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 1076 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1077 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plExplosion . pl_PositionVector = FLOAT3D (- 1.0f , - 0.2f + LARVA_HANDLE_TRANSLATE , - 1.5f) * m_fStretch + GetPlacement () . pl_PositionVector ; +#line 1078 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 1079 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1080 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plExplosion . pl_PositionVector = FLOAT3D (1.0f , 1.7f + LARVA_HANDLE_TRANSLATE , 0.1f) * m_fStretch + GetPlacement () . pl_PositionVector ; +#line 1081 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 1082 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1083 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plExplosion . pl_PositionVector = GetPlacement () . pl_PositionVector ; +#line 1084 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_ROCKET ; +#line 1085 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1088 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vExpDamage = FLOAT3D (0.0f , 15.0f , 0.0f); +#line 1089 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vTranslation = m_vExpDamage ; +#line 1090 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CPlacement3D plDebris = GetPlacement (); +#line 1091 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plDebris . pl_PositionVector += FLOAT3D (0.0f , LARVA_HANDLE_TRANSLATE , 0.0f); +#line 1092 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Debris_Begin (EIBT_FLESH , DPT_BLOODTRAIL , BET_BLOODSTAIN , 1.0f , m_vExpDamage , en_vCurrentTranslationAbsolute , 5.0f , 2.0f); +#line 1093 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Debris_Spawn_Independent (this , this , MODEL_DEBRIS_BODY , TEXTURE_BODY , 0 , 0 , 0 , 0 , m_fStretch , +#line 1094 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plDebris , vTranslation , ANGLE3D (45.0f , 230.0f , 0.0f)); +#line 1095 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vTranslation += FLOAT3D (FRnd () * 4.0f - 2.0f , FRnd () * 4.0f - 2.0f , FRnd () * 4.0f - 2.0f); +#line 1096 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Debris_Spawn_Independent (this , this , MODEL_DEBRIS_TAIL01 , TEXTURE_BODY , 0 , 0 , 0 , 0 , m_fStretch , +#line 1097 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plDebris , vTranslation , ANGLE3D (15.0f , 130.0f , 0.0f)); +#line 1098 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vTranslation += FLOAT3D (FRnd () * 4.0f - 2.0f , FRnd () * 4.0f - 2.0f , FRnd () * 4.0f - 2.0f); +#line 1099 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Debris_Spawn_Independent (this , this , MODEL_DEBRIS_TAIL02 , TEXTURE_BODY , 0 , 0 , 0 , 0 , m_fStretch , +#line 1100 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +plDebris , vTranslation , ANGLE3D (145.0f , 30.0f , 0.0f)); +#line 1101 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +for(INDEX i = 0;i < 8;i ++){ +#line 1102 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Debris_Spawn (this , this , MODEL_DEBRIS_FLESH , TEXTURE_DEBRIS_FLESH , 0 , 0 , 0 , 0 , m_fStretch , +#line 1103 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f + LARVA_HANDLE_TRANSLATE , FRnd () * 0.6f + 0.2f)); +#line 1104 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1107 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1108 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_EXPLOSION_DEBRIS ; +#line 1109 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . vStretch = FLOAT3D (1 , 1 , 1); +#line 1110 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 1111 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1113 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eSpawnEffect . betType = BET_EXPLOSION_SMOKE ; +#line 1114 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 1115 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1117 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +EDeath eDeath ; +#line 1118 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eDeath . eLastDamage . penInflictor = m_penDeathInflictor ; +#line 1120 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +EActivateBeam eab ; +#line 1121 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eab . bTurnOn = FALSE ; +#line 1122 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_penRecharger -> SendEvent (eab ); +#line 1124 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_penDeathTarget ){ +#line 1125 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendToTarget (m_penDeathTarget , EET_TRIGGER , FixupCausedToPlayer (this , m_penEnemy )); +#line 1126 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1128 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Die, FALSE, eDeath );return TRUE; ASSERT(FALSE); return TRUE;};BOOL CExotechLarva:: +#line 1132 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarva_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CExotechLarva::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1134 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +UpdateFiringPos (); +#line 1136 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(!(m_bLeftArmActive || m_bRightArmActive )){ Jump(STATE_CURRENT,0x015a001d, FALSE, EInternal());return TRUE;} +#line 1137 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_iRnd = IRnd () % 9; +#line 1138 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_iRnd > 6 && ! m_bRechargePose && GetHealth () > 0.1f * m_fMaxHealth ){ +#line 1139 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlaySound (m_soFire3 , SOUND_FIRE_TAIL , SOF_3D ); +#line 1140 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ShootTailProjectile (); +#line 1141 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1142 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_iRnd > 6 && m_bRechargePose ){ +#line 1143 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_iRnd = 3; +#line 1144 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1146 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_iRnd > 3){ +#line 1147 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Return(STATE_CURRENT,EReturn ()); +#line 1147 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; +#line 1148 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1150 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Jump(STATE_CURRENT,0x015a001a, FALSE, EInternal());return TRUE;}BOOL CExotechLarva::H0x015a001a_Fire_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a001a +if(!(m_iRnd > 0)){ Jump(STATE_CURRENT,0x015a001b, FALSE, EInternal());return TRUE;} +#line 1151 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(!(m_bLeftArmActive )){ Jump(STATE_CURRENT,0x015a0014, FALSE, EInternal());return TRUE;} +#line 1152 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlaySound (m_soFire1 , SOUND_FIRE_PLASMA , SOF_3D ); +#line 1153 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ShootProjectile (PRT_LARVA_PLASMA , m_vFirePosLeftPlasmaRel , ANGLE3D (0 , 0 , 0)); +#line 1154 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +RemoveAttachmentFromModel (* PlasmaLeftModel () , PLASMAGUN_ATTACHMENT_PROJECTILE ); +#line 1155 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x015a0010, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a0010_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0010 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015a0011, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarva::H0x015a0011_Fire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0011 +; +#line 1156 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlasmaLeftModel () -> PlayAnim (PLASMAGUN_ANIM_SPAWNING , 0); +#line 1157 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x015a0012, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a0012_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0012 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015a0013, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarva::H0x015a0013_Fire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0013 +; +#line 1158 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , * PlasmaLeftModel () , PLASMAGUN_ATTACHMENT_PROJECTILE , MODEL_PLASMA , TEXTURE_PLASMA , 0 , 0 , 0); +#line 1159 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CAttachmentModelObject * amo = PlasmaLeftModel () -> GetAttachmentModel (BODY_ATTACHMENT_ARM_LEFT ); +#line 1160 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +amo -> amo_moModelObject . StretchModel (FLOAT3D (m_fStretch , m_fStretch , m_fStretch ));Jump(STATE_CURRENT,0x015a0014, FALSE, EInternal());return TRUE;}BOOL CExotechLarva::H0x015a0014_Fire_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0014 + +#line 1162 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(!(m_bRightArmActive )){ Jump(STATE_CURRENT,0x015a0019, FALSE, EInternal());return TRUE;} +#line 1163 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlaySound (m_soFire2 , SOUND_FIRE_PLASMA , SOF_3D ); +#line 1164 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ShootProjectile (PRT_LARVA_PLASMA , m_vFirePosRightPlasmaRel , ANGLE3D (0 , 0 , 0)); +#line 1165 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +RemoveAttachmentFromModel (* PlasmaRightModel () , PLASMAGUN_ATTACHMENT_PROJECTILE ); +#line 1166 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x015a0015, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a0015_Fire_06(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015a0016, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarva::H0x015a0016_Fire_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0016 +; +#line 1167 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlasmaRightModel () -> PlayAnim (PLASMAGUN_ANIM_SPAWNING , 0); +#line 1168 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x015a0017, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a0017_Fire_08(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0017 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015a0018, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarva::H0x015a0018_Fire_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0018 +; +#line 1169 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , * PlasmaRightModel () , PLASMAGUN_ATTACHMENT_PROJECTILE , MODEL_PLASMA , TEXTURE_PLASMA , 0 , 0 , 0); +#line 1170 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CAttachmentModelObject * amo = PlasmaRightModel () -> GetAttachmentModel (BODY_ATTACHMENT_ARM_LEFT ); +#line 1171 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +amo -> amo_moModelObject . StretchModel (FLOAT3D (m_fStretch , m_fStretch , m_fStretch ));Jump(STATE_CURRENT,0x015a0019, FALSE, EInternal());return TRUE;}BOOL CExotechLarva::H0x015a0019_Fire_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0019 + +#line 1173 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_iRnd --;Jump(STATE_CURRENT,0x015a001a, FALSE, EInternal());return TRUE; +#line 1174 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}BOOL CExotechLarva::H0x015a001b_Fire_12(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a001b +Jump(STATE_CURRENT,0x015a001c, FALSE, EInternal());return TRUE;}BOOL CExotechLarva::H0x015a001d_Fire_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a001d +if(TRUE ){ +#line 1177 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_iRnd = IRnd () % 10; +#line 1178 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_iRnd > 6 && ! m_bRechargePose && GetHealth () > 0.1f * m_fMaxHealth ){ +#line 1179 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlaySound (m_soFire3 , SOUND_FIRE_TAIL , SOF_3D ); +#line 1180 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ShootTailProjectile (); +#line 1181 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1182 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_iRnd < 4 && _pTimer -> CurrentTick () > m_tmDontFireLaserBefore ){ +#line 1183 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlaySound (m_soLaser , SOUND_LASER_CHARGE , SOF_3D ); +#line 1184 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SpawnReminder (this , 3.0f , 129); +#line 1185 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_tmDontFireLaserBefore = _pTimer -> CurrentTick () + m_fMinimumLaserWait ; +#line 1186 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1187 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}Jump(STATE_CURRENT,0x015a001c, FALSE, EInternal());return TRUE;} +BOOL CExotechLarva::H0x015a001c_Fire_13(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a001c + +#line 1189 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PerhapsChangeTarget (); +#line 1191 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Return(STATE_CURRENT,EReturn ()); +#line 1191 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CExotechLarva:: +#line 1194 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarva_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CExotechLarva::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1195 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Return(STATE_CURRENT,EReturn ()); +#line 1195 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CExotechLarva:: +#line 1198 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BeIdle(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarva_BeIdle + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CExotechLarva::BeIdle expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1200 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PerhapsChangeTarget (); +#line 1202 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x015a0020, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a0020_BeIdle_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0020 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015a0021, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarva::H0x015a0021_BeIdle_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0021 +; +#line 1204 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Jump(STATE_CURRENT,0x015a0024, FALSE, EInternal());return TRUE;}BOOL CExotechLarva::H0x015a0024_BeIdle_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0024 +if(!(TRUE )){ Jump(STATE_CURRENT,0x015a0025, FALSE, EInternal());return TRUE;} +#line 1205 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FindNewTarget (); +#line 1206 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendEvent (EReconsiderBehavior ()); +#line 1207 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x015a0022, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a0022_BeIdle_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0022 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015a0023, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarva::H0x015a0023_BeIdle_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0023 +;Jump(STATE_CURRENT,0x015a0024, FALSE, EInternal());return TRUE; +#line 1208 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}BOOL CExotechLarva::H0x015a0025_BeIdle_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0025 + ASSERT(FALSE); return TRUE;};BOOL CExotechLarva:: +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +LarvaLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarva_LarvaLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CExotechLarva::LarvaLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1214 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FindNewTarget (); +#line 1215 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendEvent (EReconsiderBehavior ()); +#line 1217 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +StartModelAnim (BODY_ANIM_IDLE , AOF_SMOOTHCHANGE | AOF_LOOPING ); +#line 1219 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SpawnReminder (this , 0.5f , 128); +#line 1220 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SpawnReminder (this , 0.5f , 145); +#line 1221 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x015a0027, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a0027_LarvaLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0027 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin): +#line 1223 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{const EBegin&e= (EBegin&)__eeInput; + +#line 1224 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(! m_bLeftArmActive && ! m_bRightArmActive ){ +#line 1225 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CModelObject & amo = GetModelObject () -> GetAttachmentModel (BODY_ATTACHMENT_BACKARMS ) -> amo_moModelObject ; +#line 1226 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +amo . PlayAnim (BACKARMS_ANIM_ACTIVATING , AOF_SMOOTHCHANGE | AOF_NORESTART ); +#line 1227 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlaySound (m_soFire1 , SOUND_DEPLOYLASER , SOF_3D ); +#line 1228 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SpawnReminder (this , amo . GetAnimLength (BACKARMS_ANIM_ACTIVATING ) , 160); +#line 1229 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1230 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Call(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; +#line 1231 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}ASSERT(FALSE);break;case(EVENTCODE_ELarvaArmDestroyed): +#line 1234 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{const ELarvaArmDestroyed&ead= (ELarvaArmDestroyed&)__eeInput; + +#line 1235 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_iExplodingArm = ead . iArm ; +#line 1236 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Call(STATE_CURRENT, STATE_CExotechLarva_ArmExplosion, TRUE, EVoid());return TRUE; +#line 1237 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}ASSERT(FALSE);break;case(EVENTCODE_ELarvaRechargePose): +#line 1240 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{const ELarvaRechargePose&elrp= (ELarvaRechargePose&)__eeInput; + +#line 1241 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(elrp . bStart == TRUE && m_bRechargePose != TRUE ){ +#line 1242 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +StartModelAnim (BODY_ANIM_TORECHARGING , AOF_SMOOTHCHANGE | AOF_NORESTART ); +#line 1243 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SpawnReminder (this , GetModelObject () -> GetAnimLength (BODY_ANIM_TORECHARGING ) , 156); +#line 1244 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1245 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(elrp . bStart == FALSE && m_bRechargePose != FALSE ){ +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +StartModelAnim (BODY_ANIM_FROMRECHARGING , AOF_SMOOTHCHANGE | AOF_NORESTART ); +#line 1247 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SpawnReminder (this , GetModelObject () -> GetAnimLength (BODY_ANIM_FROMRECHARGING ) , 157); +#line 1248 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1249 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; +#line 1250 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReminder): +#line 1253 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{const EReminder&er= (EReminder&)__eeInput; + +#line 1255 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(er . iValue == 128){ +#line 1257 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(RechargerActive ()){ +#line 1258 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SpawnReminder (this , 1.0f , 128); +#line 1259 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else { +#line 1260 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRecharging = FALSE ; +#line 1261 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_ltTarget = LT_ENEMY ; +#line 1263 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ELarvaRechargePose elrp ; +#line 1264 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +elrp . bStart = FALSE ; +#line 1265 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendEvent (elrp ); +#line 1266 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1268 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bActive && m_bRecharging && DistanceXZ (this , m_penRecharger ) < 5.0f){ +#line 1269 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bRechargePose ){ +#line 1270 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(((CExotechLarvaCharger *) & * m_penRecharger ) -> m_bBeamActive ) +#line 1271 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +{ +#line 1272 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(! m_bRechargedAtLeastOnce ){ +#line 1273 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_penFirstRechargeTarget ){ +#line 1274 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendToTarget (m_penFirstRechargeTarget , EET_TRIGGER , FixupCausedToPlayer (this , m_penEnemy )); +#line 1275 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1276 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRechargedAtLeastOnce = TRUE ; +#line 1277 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1278 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetHealth (ClampUp (GetHealth () + m_fRechargePerSecond , m_fMaxHealth * m_fMaxRechargedHealth )); +#line 1279 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(GetHealth () > m_fMaxHealth * 0.95){ +#line 1280 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_ltTarget = LT_ENEMY ; +#line 1281 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRecharging = FALSE ; +#line 1283 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +EActivateBeam eab ; +#line 1284 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eab . bTurnOn = FALSE ; +#line 1285 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_penRecharger -> SendEvent (eab ); +#line 1287 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ELarvaRechargePose elrp ; +#line 1288 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +elrp . bStart = FALSE ; +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendEvent (elrp ); +#line 1290 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1291 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(TRUE ){ +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +EActivateBeam eab ; +#line 1293 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +eab . bTurnOn = TRUE ; +#line 1294 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_penRecharger -> SendEvent (eab ); +#line 1295 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1296 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else { +#line 1297 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ELarvaRechargePose elrp ; +#line 1298 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +elrp . bStart = TRUE ; +#line 1299 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SendEvent (elrp ); +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1301 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +else if(TRUE ){ +#line 1304 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(GetHealth () < (m_fLarvaHealth * 0.7f)){ +#line 1305 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(! RechargerActive ()){ +#line 1306 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_ltTarget = LT_ENEMY ; +#line 1307 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else { +#line 1308 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRecharging = TRUE ; +#line 1309 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_ltTarget = LT_RECHARGER ; +#line 1310 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1311 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1312 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; +#line 1315 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(er . iValue == 145){ +#line 1316 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FindNewTarget (); +#line 1317 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(AnyPlayerCloserThen (9.0f) && GetHealth () > 0.1f * m_fMaxHealth ){ +#line 1318 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +UpdateFiringPos (); +#line 1319 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlaySound (m_soFire3 , SOUND_FIRE_TAIL , SOF_3D ); +#line 1320 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ShootTailProjectile (); +#line 1321 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1322 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +else if(m_penEnemy && GetHealth () > 0.1f * m_fMaxHealth ){ +#line 1323 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(! IsVisible (m_penEnemy )){ +#line 1324 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +INDEX iRnd = IRnd () % 6; +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(iRnd > 4){ +#line 1326 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +UpdateFiringPos (); +#line 1327 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlaySound (m_soFire3 , SOUND_FIRE_TAIL , SOF_3D ); +#line 1328 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ShootTailProjectile (); +#line 1329 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1330 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1331 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1332 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SpawnReminder (this , 0.5f , 145); +#line 1333 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; +#line 1335 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(er . iValue == 129){ +#line 1336 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bActive && m_bLaserActive ){FireLaser ();} +#line 1337 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SpawnReminder (this , 0.35f , 130); +#line 1338 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; +#line 1340 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(er . iValue == 130){ +#line 1341 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(m_bActive ){ExplodeLaser ();} +#line 1342 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SpawnReminder (this , 0.75f , 131); +#line 1343 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; +#line 1345 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(er . iValue == 131){ +#line 1346 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRenderLeftLaser = FALSE ; +#line 1347 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRenderRightLaser = FALSE ; +#line 1348 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(er . iValue == 156){ +#line 1351 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRechargePose = TRUE ; +#line 1352 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +StartModelAnim (BODY_ANIM_RECHARGING , AOF_SMOOTHCHANGE | AOF_LOOPING ); +#line 1353 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; +#line 1355 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(er . iValue == 157){ +#line 1356 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bRechargePose = FALSE ; +#line 1357 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +StartModelAnim (BODY_ANIM_IDLE , AOF_SMOOTHCHANGE | AOF_LOOPING ); +#line 1359 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}else if(er . iValue == 160){ +#line 1360 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CModelObject & amo = GetModelObject () -> GetAttachmentModel (BODY_ATTACHMENT_BACKARMS ) -> amo_moModelObject ; +#line 1361 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +amo . PlayAnim (BACKARMS_ANIM_ACTIVE , AOF_SMOOTHCHANGE | AOF_LOOPING ); +#line 1362 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bLaserActive = TRUE ; +#line 1363 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1364 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; +#line 1365 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 1366 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}return TRUE;}BOOL CExotechLarva::H0x015a0028_LarvaLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0028 + ASSERT(FALSE); return TRUE;};BOOL CExotechLarva:: +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarva_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CExotechLarva::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1371 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +InitAsModel (); +#line 1372 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetPhysicsFlags (EPF_MODEL_FLYING | EPF_HASLUNGS | EPF_ABSOLUTETRANSLATE ); +#line 1373 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetCollisionFlags (ECF_MODEL ); +#line 1374 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 1375 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +en_fDensity = 2000.0f; +#line 1378 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetModel (MODEL_BODY ); +#line 1379 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetModelMainTexture (TEXTURE_BODY ); +#line 1382 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , * GetModelObject () , BODY_ATTACHMENT_ARM_LEFT , MODEL_WING , TEXTURE_WING , 0 , 0 , 0); +#line 1383 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CModelObject & amo0 = GetModelObject () -> GetAttachmentModel (BODY_ATTACHMENT_ARM_LEFT ) -> amo_moModelObject ; +#line 1384 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , amo0 , ARM_ATTACHMENT_PLASMAGUN , MODEL_PLASMAGUN , TEXTURE_PLASMAGUN , 0 , 0 , 0); +#line 1387 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , * GetModelObject () , BODY_ATTACHMENT_ARM_RIGHT , MODEL_WING , TEXTURE_WING , 0 , 0 , 0); +#line 1388 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CModelObject & amo1 = GetModelObject () -> GetAttachmentModel (BODY_ATTACHMENT_ARM_RIGHT ) -> amo_moModelObject ; +#line 1389 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +amo1 . StretchModel (FLOAT3D (- 1.0f , 1.0f , 1.0f)); +#line 1390 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , amo1 , ARM_ATTACHMENT_PLASMAGUN , MODEL_PLASMAGUN , TEXTURE_PLASMAGUN , 0 , 0 , 0); +#line 1391 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CModelObject & amo2 = amo1 . GetAttachmentModel (ARM_ATTACHMENT_PLASMAGUN ) -> amo_moModelObject ; +#line 1392 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +amo2 . StretchModel (FLOAT3D (- 1.0f , 1.0f , 1.0f)); +#line 1395 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , * GetModelObject () , BODY_ATTACHMENT_BACKARMS , MODEL_BLADES , TEXTURE_BODY , 0 , 0 , 0); +#line 1398 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , * GetModelObject () , BODY_ATTACHMENT_EXOTECHLARVA , MODEL_EXOTECHLARVA , TEXTURE_EXOTECHLARVA , 0 , 0 , 0); +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CModelObject & amo3 = GetModelObject () -> GetAttachmentModel (BODY_ATTACHMENT_EXOTECHLARVA ) -> amo_moModelObject ; +#line 1400 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , amo3 , EXOTECHLARVA_ATTACHMENT_BEAM , MODEL_BEAM , TEXTURE_BEAM , 0 , 0 , 0); +#line 1401 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , amo3 , EXOTECHLARVA_ATTACHMENT_ENERGYBEAMS , MODEL_ENERGYBEAMS , TEXTURE_ENERGYBEAMS , 0 , 0 , 0); +#line 1402 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , amo3 , EXOTECHLARVA_ATTACHMENT_FLARE , MODEL_FLARE , TEXTURE_FLARE , 0 , 0 , 0); +#line 1404 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , * PlasmaLeftModel () , PLASMAGUN_ATTACHMENT_PROJECTILE , MODEL_PLASMA , TEXTURE_PLASMA , 0 , 0 , 0); +#line 1405 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +AddAttachmentToModel (this , * PlasmaRightModel () , PLASMAGUN_ATTACHMENT_PROJECTILE , MODEL_PLASMA , TEXTURE_PLASMA , 0 , 0 , 0); +#line 1408 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +GetModelObject () -> StretchModelRelative (FLOAT3D (m_fStretch , m_fStretch , m_fStretch )); +#line 1410 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vFirePosLeftPlasmaRel = FIREPOS_PLASMA_LEFT * m_fStretch ; +#line 1411 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vFirePosRightPlasmaRel = FIREPOS_PLASMA_RIGHT * m_fStretch ; +#line 1413 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_vFirePosTailRel = FIREPOS_TAIL * m_fStretch ; +#line 1416 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bBoss = TRUE ; +#line 1419 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fWalkSpeed = 0.0f; +#line 1420 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_aWalkRotateSpeed = 100.0f; +#line 1421 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fAttackRunSpeed = 7.5f; +#line 1422 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_aAttackRotateSpeed = 100.0f; +#line 1424 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fStopDistance = m_fStopRadius ; +#line 1425 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fBlowUpAmount = 100.0f; +#line 1426 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fBodyParts = 0; +#line 1427 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fDamageWounded = 0.0f; +#line 1428 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_iScore = 750000; +#line 1429 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_sptType = SPT_BLOOD ; +#line 1430 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fAttackDistance = 100.0f; +#line 1431 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fCloseDistance = 0.0f; +#line 1433 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fAttackFireTime = 0.5f; +#line 1434 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fCloseFireTime = 0.5f; +#line 1437 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +en_fAcceleration = UpperLimit (1.0f); +#line 1438 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +en_fDeceleration = UpperLimit (1.0f); +#line 1441 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetHealth (m_fLarvaHealth ); +#line 1442 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_fMaxHealth = m_fLarvaHealth ; +#line 1444 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bActive = TRUE ; +#line 1445 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bExploding = FALSE ; +#line 1446 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bLaserActive = FALSE ; +#line 1451 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ModelChangeNotify (); +#line 1452 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +StandingAnim (); +#line 1454 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x015a0029, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a0029_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0029 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015a002a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarva::H0x015a002a_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a002a +; +#line 1457 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bInvulnerable = TRUE ; +#line 1459 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +if(! DoSafetyChecks ()){ +#line 1460 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Destroy (); +#line 1461 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Return(STATE_CURRENT,EVoid()); +#line 1461 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +return TRUE; +#line 1462 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +} +#line 1465 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x015a002b, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a002b_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a002b +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x015a002c, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 1469 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}return TRUE;}BOOL CExotechLarva::H0x015a002c_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a002c + +#line 1471 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +PlaySound (m_soChirp , SOUND_CHIRP , SOF_3D | SOF_LOOP ); +#line 1474 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Jump(STATE_CURRENT,0x015a002f, FALSE, EInternal());return TRUE;}BOOL CExotechLarva::H0x015a002f_Main_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a002f +if(!(DistanceTo (this , m_penMarkerNew ) > 5.0f)){ Jump(STATE_CURRENT,0x015a0030, FALSE, EInternal());return TRUE;} +#line 1475 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x015a002d, FALSE, EBegin());return TRUE;}BOOL CExotechLarva::H0x015a002d_Main_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a002d +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; + +#line 1478 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT3D vToMarker = m_penMarkerNew -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 1479 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +vToMarker . Normalize (); +#line 1480 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +SetDesiredTranslation (vToMarker * m_fAttackRunSpeed ); +#line 1481 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +UnsetTimer();Jump(STATE_CURRENT,0x015a002e, FALSE, EInternal());return TRUE; +#line 1482 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 1483 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}return TRUE;}BOOL CExotechLarva::H0x015a002e_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a002e +Jump(STATE_CURRENT,0x015a002f, FALSE, EInternal());return TRUE; +#line 1484 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +}BOOL CExotechLarva::H0x015a0030_Main_08(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015a0030 + +#line 1486 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +m_bInvulnerable = FALSE ; +#line 1489 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Jump(STATE_CURRENT, STATE_CExotechLarva_LarvaLoop, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ExotechLarva.es b/Sources/EntitiesMP/ExotechLarva.es new file mode 100644 index 0000000..336aa47 --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarva.es @@ -0,0 +1,1492 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +346 +%{ +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/Common/PathFinding.h" +#include "EntitiesMP/NavigationMarker.h" +#include "ModelsMP/Enemies/ExotechLarva/ExotechLarva.h" +#include "ModelsMP/Enemies/ExotechLarva/Body.h" +#include "ModelsMP/Enemies/ExotechLarva/Arm.h" +#include "ModelsMP/Enemies/ExotechLarva/BackArms.h" +#include "ModelsMP/Enemies/ExotechLarva/Weapons/PlasmaGun.h" +%} + +uses "EntitiesMP/ModelHolder2"; +uses "EntitiesMP/Projectile"; +uses "EntitiesMP/SoundHolder"; +uses "EntitiesMP/BloodSpray"; +uses "EntitiesMP/CannonBall"; +uses "EntitiesMP/ExotechLarvaCharger"; +uses "EntitiesMP/LarvaOffspring"; + +enum LarvaTarget { + 0 LT_NONE "", // no target + 1 LT_ENEMY "", // follow enemy + 2 LT_RECHARGER "", // go to a recharger point +}; + +event ELarvaArmDestroyed { + INDEX iArm, +}; +event ELarvaRechargePose { + BOOL bStart, // animate to pose, or return to default +}; + + +%{ +// info structure +static EntityInfo eiExotechLarva = { + EIBT_FLESH, 9999999999.9f, + 0.0f, -1.0f, 0.0f, // source (eyes) + 0.0f, -1.5f, 0.0f, // target (body) + }; + +#define MF_MOVEZ (1L<<0) + +#define LARVA_HANDLE_TRANSLATE 4.4f +#define FIREPOS_PLASMA_RIGHT FLOAT3D(+3.08f, -1.20f+LARVA_HANDLE_TRANSLATE, -0.16f) +#define FIREPOS_PLASMA_LEFT FLOAT3D(-3.08f, -1.20f+LARVA_HANDLE_TRANSLATE, -0.16f) +#define FIREPOS_LASER_RIGHT FLOAT3D(+2.31f, 0.16f+LARVA_HANDLE_TRANSLATE, -3.57f) +#define FIREPOS_LASER_LEFT FLOAT3D(-2.20f, 0.18f+LARVA_HANDLE_TRANSLATE, -3.57f) +#define FIREPOS_TAIL FLOAT3D( 0.00f, -2.64f+LARVA_HANDLE_TRANSLATE, -0.22f) +//#define FIREPOS_MOUTH FLOAT3D( 0.00f, -0.75f, -2.09f) + + +// PERCENT_RIGHTBLOW has to be greater then PERCENT_LEFTBLOW or some things +// won't work correctly +#define PERCENT_RIGHTBLOW 0.6666f +#define PERCENT_LEFTBLOW 0.3333f + +#define ARM_LEFT (1L<<0) +#define ARM_RIGHT (1L<<1) + +%} + +class CExotechLarva: CEnemyBase { +name "ExotechLarva"; +thumbnail "Thumbnails\\ExotechLarva.tbn"; + +properties: + + 10 CEntityPointer m_penMarkerNew "Larva 1st Grid Marker", + 11 CEntityPointer m_penMarkerOld, + 15 FLOAT m_fStopRadius "Larva MinDist From Player" = 25.0f, + 16 FLOAT m_fStretch = 2.5f, + 17 FLOAT m_fLarvaHealth = 20000.0f, + 19 FLOAT m_fRechargePerSecond "Larva Recharge health/sec" = 100.0f, + 18 enum LarvaTarget m_ltTarget = LT_ENEMY, // type of target + 30 CEntityPointer m_penFirstRechargeTarget "Larva First Recharge target", + 31 BOOL m_bRechargedAtLeastOnce = FALSE, + + 20 FLOAT3D m_vFirePosLeftPlasmaRel = FLOAT3D(0.0f, 0.0f, 0.0f), + 21 FLOAT3D m_vFirePosRightPlasmaRel = FLOAT3D(0.0f, 0.0f, 0.0f), + //22 FLOAT3D m_vFirePosMouthRel = FLOAT3D(0.0f, 0.0f, 0.0f), + 23 FLOAT3D m_vFirePosTailRel = FLOAT3D(0.0f, 0.0f, 0.0f), + 24 FLOAT3D m_vFirePosLeftLaserAbs = FLOAT3D(0.0f, 0.0f, 0.0f), + 25 FLOAT3D m_vFirePosRightLaserAbs = FLOAT3D(0.0f, 0.0f, 0.0f), + + 40 BOOL m_bLeftArmActive = TRUE, + 41 BOOL m_bRightArmActive = TRUE, + 42 INDEX m_iExplodingArm = 1, + 45 FLOAT m_fMaxRechargedHealth = 1.0f, + 46 BOOL m_bExploding = FALSE, + 47 BOOL m_bActive = TRUE, + 48 BOOL m_bRechargePose = FALSE, + 49 BOOL m_bLaserActive = FALSE, + + 51 BOOL m_bInitialMove = TRUE, + + 54 CEntityPointer m_penRecharger "Larva Recharger" COLOR(C_GREEN|0xFF), + + 60 FLOAT m_tmLastTargateChange = 0.0f, + + // internal positions for explosions + 70 CPlacement3D m_plExpArmPos = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)), + 71 FLOAT3D m_aExpArmRot = FLOAT3D(0.0f, 0.0f, 0.0f), + 72 CPlacement3D m_plExpGunPos = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)), + 73 FLOAT3D m_aExpGunRot = FLOAT3D(0.0f, 0.0f, 0.0f), + 74 FLOAT3D m_vExpDamage = FLOAT3D(0.0f, 0.0f, 0.0f), + 75 INDEX m_iExplosions = 0, + + 80 INDEX m_iRnd = 0, // temporary holder for random variable + 81 BOOL m_bRecharging = FALSE, // internal + + // temporary variables for reconstructing lost events + 90 CEntityPointer m_penDeathInflictor, + + 100 FLOAT m_tmDontFireLaserBefore = 0.0f, + 101 FLOAT m_fMinimumLaserWait "Larva min. laser interval" = 5.0f, + 102 BOOL m_bRenderLeftLaser = FALSE, + 103 BOOL m_bRenderRightLaser = FALSE, + 104 FLOAT3D m_vLeftLaserTarget = FLOAT3D(0.0f, 0.0f, 0.0f), + 105 FLOAT3D m_vRightLaserTarget = FLOAT3D(0.0f, 0.0f, 0.0f), + + 110 BOOL m_bInvulnerable = FALSE, + + 150 CEntityPointer m_penLeftArmDestroyTarget "Larva ArmBlow#1 Target", + 151 CEntityPointer m_penRightArmDestroyTarget "Larva ArmBlow#2 Target", + 152 CEntityPointer m_penDeathTarget "Larva Death Target", + + 200 CSoundObject m_soFire1, // sound channel for firing + 201 CSoundObject m_soFire2, // sound channel for firing + 202 CSoundObject m_soFire3, // sound channel for firing + 203 CSoundObject m_soVoice, // sound channel for voice + 204 CSoundObject m_soChirp, // sound channel for chirping + 205 CSoundObject m_soLaser, // sound channel for laser + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + 2 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 3 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 4 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + 5 class CLASS_LARVAOFFSPRING "Classes\\LarvaOffspring.ecl", + + 10 model MODEL_EXOTECHLARVA "ModelsMP\\Enemies\\ExotechLarva\\ExotechLarva.mdl", + 11 texture TEXTURE_EXOTECHLARVA "ModelsMP\\Enemies\\ExotechLarva\\ExotechLarva.tex", + + 12 model MODEL_BODY "ModelsMP\\Enemies\\ExotechLarva\\Body.mdl", + 13 texture TEXTURE_BODY "ModelsMP\\Enemies\\ExotechLarva\\Body.tex", + + 14 model MODEL_BEAM "ModelsMP\\Enemies\\ExotechLarva\\Beam.mdl", + 15 texture TEXTURE_BEAM "ModelsMP\\Effects\\Laser\\Laser.tex", + + 16 model MODEL_ENERGYBEAMS "ModelsMP\\Enemies\\ExotechLarva\\EnergyBeams.mdl", + 17 texture TEXTURE_ENERGYBEAMS "ModelsMP\\Enemies\\ExotechLarva\\EnergyBeams.tex", + + 18 model MODEL_FLARE "ModelsMP\\Enemies\\ExotechLarva\\EffectFlare.mdl", + 19 texture TEXTURE_FLARE "ModelsMP\\Enemies\\ExotechLarva\\EffectFlare.tex", + + 30 model MODEL_WING "ModelsMP\\Enemies\\ExotechLarva\\Arm.mdl", + 31 texture TEXTURE_WING "ModelsMP\\Enemies\\ExotechLarva\\Arm.tex", + + 32 model MODEL_PLASMAGUN "ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.mdl", + 33 texture TEXTURE_PLASMAGUN "ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.tex", + + 34 model MODEL_BLADES "ModelsMP\\Enemies\\ExotechLarva\\BackArms.mdl", + + 36 model MODEL_DEBRIS_BODY "ModelsMP\\Enemies\\ExotechLarva\\Debris\\BodyDebris.mdl", + 37 model MODEL_DEBRIS_TAIL01 "ModelsMP\\Enemies\\ExotechLarva\\Debris\\TailDebris01.mdl", + 38 model MODEL_DEBRIS_TAIL02 "ModelsMP\\Enemies\\ExotechLarva\\Debris\\TailDebris02.mdl", + + 39 model MODEL_DEBRIS_FLESH "Models\\Effects\\Debris\\Flesh\\Flesh.mdl", + 40 texture TEXTURE_DEBRIS_FLESH "Models\\Effects\\Debris\\Flesh\\FleshRed.tex", + + 41 model MODEL_PLASMA "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\Projectile.mdl", + 42 texture TEXTURE_PLASMA "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\Projectile.tex", + + + // ************** SOUNDS ************** + 50 sound SOUND_FIRE_PLASMA "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\FirePlasma.wav", + 51 sound SOUND_FIRE_TAIL "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\FireTail.wav", + 52 sound SOUND_LASER_CHARGE "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\LaserCharge.wav", + 53 sound SOUND_DEATH "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\Death.wav", + 54 sound SOUND_ARMDESTROY "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\ArmDestroy.wav", + 55 sound SOUND_CHIRP "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\Chirp.wav", + 56 sound SOUND_DEPLOYLASER "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\DeployLaser.wav", + +functions: + + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if( slPropertyOffset == offsetof(CExotechLarva, m_penMarkerNew)) + { + if (IsOfClass(penTarget, "NavigationMarker")) { return TRUE; } + else { return FALSE; } + } + if( slPropertyOffset == offsetof(CExotechLarva, m_penRecharger)) + { + if (IsOfClass(penTarget, "ExotechLarvaCharger")) { return TRUE; } + else { return FALSE; } + } + return CEntity::IsTargetValid(slPropertyOffset, penTarget); + } + + BOOL DoSafetyChecks(void) { + if (m_penMarkerNew==NULL) { + WarningMessage("First ExotechLarva marker not set! Destroying Larva...\n"); + return FALSE; + } + if (m_penRecharger==NULL) { + WarningMessage("ExotechLarva Recharger target not set! Destroying Larva...\n"); + return FALSE; + } + return TRUE; + } + + void FindNewTarget() { + + // if we have a valid enemy, return + if (m_penEnemy!=NULL) { + if (m_penEnemy->GetFlags()&ENF_ALIVE && !(m_penEnemy->GetFlags()&ENF_DELETED)) { + return; + } + } + + // find actual number of players + INDEX ctMaxPlayers = GetMaxPlayers(); + CEntity *penPlayer; + + for(INDEX i=0; iGetFlags()&ENF_ALIVE) && + !(penPlayer->GetFlags()&ENF_DELETED)) { + m_penEnemy = penPlayer; + } + } + } + } + + BOOL AnyPlayerCloserThen(FLOAT fDistance) { + + BOOL bClose = FALSE; + + // find actual number of players + INDEX ctMaxPlayers = GetMaxPlayers(); + CEntity *penPlayer; + + for(INDEX i=0; iGetFlags()&ENF_ALIVE) && + !(penPlayer->GetFlags()&ENF_DELETED) && + DistanceTo(this, penPlayer)CurrentTick()) { + MaybeSwitchToAnotherPlayer(); + m_tmLastTargateChange = _pTimer->CurrentTick(); + } + } + + class CWorldSettingsController *GetWSC(void) + { + CWorldSettingsController *pwsc = NULL; + // obtain bcg viewer + CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) GetWorld()->GetBackgroundViewer(); + if( penBcgViewer != NULL) { + // obtain world settings controller + pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController; + } + return pwsc; + } + + /* Shake ground */ + void ShakeItBaby(FLOAT tmShaketime, FLOAT fPower, BOOL bFadeIn) + { + CWorldSettingsController *pwsc = GetWSC(); + if (pwsc!=NULL) { + pwsc->m_tmShakeStarted = tmShaketime; + pwsc->m_vShakePos = GetPlacement().pl_PositionVector; + pwsc->m_fShakeFalloff = 450.0f; + pwsc->m_fShakeFade = 3.0f; + + pwsc->m_fShakeIntensityZ = 0; + pwsc->m_tmShakeFrequencyZ = 5.0f; + pwsc->m_fShakeIntensityY = 0.1f*fPower; + pwsc->m_tmShakeFrequencyY = 5.0f; + pwsc->m_fShakeIntensityB = 2.5f*fPower; + pwsc->m_tmShakeFrequencyB = 7.2f; + + pwsc->m_bShakeFadeIn = bFadeIn; + } + } + + void ShootTailProjectile(void) { + //ShootProjectile(PRT_LARVA_TAIL_PROJECTILE, m_vFirePosTailRel, ANGLE3D(0, -10, 0)); + if (m_penEnemy == NULL) { return; } + + // target enemy body + EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); + FLOAT3D vShootTarget; + GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget); + + // launch + CPlacement3D pl; + PreparePropelledProjectile(pl, vShootTarget, m_vFirePosTailRel, ANGLE3D(0, -10, 0)); + CEntityPointer penProjectile = CreateEntity(pl, CLASS_LARVAOFFSPRING); + ELaunchLarvaOffspring ello; + ello.penLauncher = this; + penProjectile->Initialize(ello); + } + + BOOL IsOnMarker(CEntity *penMarker) { + + if (penMarker==NULL) { return FALSE; } + if (DistanceTo(this, penMarker)<0.1f) { return TRUE; } + // else + return FALSE; + } + + FLOAT DistanceXZ(CEntity *E1, CEntity *E2) + { + FLOAT3D vE1pos = E1->GetPlacement().pl_PositionVector; + FLOAT3D vE2pos = E2->GetPlacement().pl_PositionVector; + vE1pos(2)=0.0f; + vE2pos(2)=0.0f; + return (vE2pos - vE1pos).Length(); + } + + void SpawnWingDebris() + { + FLOAT3D vTranslation = m_vExpDamage + en_vCurrentTranslationAbsolute; + + Debris_Begin(EIBT_FLESH, DPT_BLOODTRAIL, BET_BLOODSTAIN, 1.0f, m_vExpDamage, en_vCurrentTranslationAbsolute, 5.0f, 2.0f); + Debris_Spawn_Independent(this, this, MODEL_WING, TEXTURE_WING, 0, 0, 0, 0, m_fStretch, + m_plExpArmPos, vTranslation , m_aExpArmRot); + vTranslation += FLOAT3D(FRnd()*4.0f-2.0f, FRnd()*4.0f-2.0f, FRnd()*4.0f-2.0f); + Debris_Spawn_Independent(this, this, MODEL_PLASMAGUN, TEXTURE_PLASMAGUN, 0, 0, 0, 0, m_fStretch, + m_plExpGunPos, vTranslation , m_aExpGunRot); + } + + + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + + if (m_bInvulnerable) { + return; + } + + // cannot hurt ourselves + if (IsOfClass(penInflictor, "ExotechLarva")) { + return; + } + + // preliminary adjustment of damage + // take less damage from heavy bullets (e.g. sniper) + if(dmtType==DMT_BULLET && fDamageAmmount>100.0f) + { + fDamageAmmount *= 0.66f; + } + // cannonballs inflict less damage then the default + if(dmtType==DMT_CANNONBALL) + { + fDamageAmmount *= 0.5f; + } + + + + FLOAT fHealthNow = GetHealth(); + FLOAT fHealthAfter = GetHealth() - fDamageAmmount; + FLOAT fHealthBlow01 = m_fMaxHealth*PERCENT_RIGHTBLOW; + FLOAT fHealthBlow02 = m_fMaxHealth*PERCENT_LEFTBLOW; + + // adjust damage + fDamageAmmount *=DamageStrength( ((EntityInfo*)GetEntityInfo())->Eeibt, dmtType); + // apply game extra damage per enemy and per player + fDamageAmmount *=GetGameDamageMultiplier(); + + // enough damage to blow both arms + if (fHealthNow>fHealthBlow01 && fHealthAfterfHealthBlow02 && fHealthAfterfHealthBlow02 && fHealthAfter<0) { + fDamageAmmount = fHealthNow - 1; + } + + // if no damage + if (fDamageAmmount ==0) { + // do nothing + return; + } + + // spawn blood spray + CPlacement3D plSpray = CPlacement3D( vHitPoint, ANGLE3D(0, 0, 0)); + m_penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + if( m_fMaxDamageAmmount > 10.0f) + { + eSpawnSpray.fDamagePower = 3.0f; + } + else if(m_fSprayDamage+fDamageAmmount>50.0f) + { + eSpawnSpray.fDamagePower = 2.0f; + } + else + { + eSpawnSpray.fDamagePower = 1.0f; + } + switch(IRnd()%4) { + case 0: case 1: case 2: + // blood spray + m_penSpray->SetParent(this); + eSpawnSpray.sptType = SPT_BLOOD; + break; + case 3: + // sparks spray + eSpawnSpray.sptType = SPT_ELECTRICITY_SPARKS; + break; + } + eSpawnSpray.fSizeMultiplier = 1.0f; + // setup direction of spray + FLOAT3D vHitPointRelative = vHitPoint - GetPlacement().pl_PositionVector; + FLOAT3D vReflectingNormal; + GetNormalComponent( vHitPointRelative, en_vGravityDir, vReflectingNormal); + vReflectingNormal.Normalize(); + + vReflectingNormal(1)/=5.0f; + + FLOAT3D vProjectedComponent = vReflectingNormal*(vDirection%vReflectingNormal); + FLOAT3D vSpilDirection = vDirection-vProjectedComponent*2.0f-en_vGravityDir*0.5f; + + eSpawnSpray.vDirection = vSpilDirection; + eSpawnSpray.penOwner = this; + + // initialize spray + m_penSpray->Initialize( eSpawnSpray); + m_tmSpraySpawned = _pTimer->CurrentTick(); + m_fSprayDamage = 0.0f; + m_fMaxDamageAmmount = 0.0f; + + // instead of: + // CMovableModelEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, + // vHitPoint, vDirection); + // do this (because we don't want an event posted each time we're damaged): + + // reduce your health + en_fHealth-=fDamageAmmount; + // if health reached zero + if (en_fHealth<=0) { + // throw an event that you have died + EDeath eDeath; + SendEvent(eDeath); + } + + if (m_bRightArmActive) { + if (GetHealth()GetAttachmentModel(BODY_ATTACHMENT_ARM_LEFT); + amo = amo->amo_moModelObject.GetAttachmentModel(ARM_ATTACHMENT_PLASMAGUN); + return &(amo->amo_moModelObject); + }; + CModelObject *PlasmaRightModel(void) { + CAttachmentModelObject *amo = GetModelObject()->GetAttachmentModel(BODY_ATTACHMENT_ARM_RIGHT); + amo = amo->amo_moModelObject.GetAttachmentModel(ARM_ATTACHMENT_PLASMAGUN); + return &(amo->amo_moModelObject); + }; + + BOOL RechargerActive() { + if (((CExotechLarvaCharger *)&*m_penRecharger)->m_bActive) { + return TRUE; + } + return FALSE; + } + + /*void CheckRechargerTargets(void) { + m_bRechargerExists = FALSE; + + CEntityPointer *penModel = &m_penRCModel01; + CEntityPointer *penMarker = &m_penRCMarker01; + + for (INDEX i=0; i<4; i++) { + // if model pointer is valid and model is not destroyed + if (&*penModel[i]) { + if (!((*penModel[i]).en_ulFlags&ENF_DELETED)) { + // at least one exists + m_bRechargerExists = TRUE; + } else if (m_penRechargerTarget==&*penMarker[i]) { + m_penRechargerTarget=NULL; + penMarker[i] = NULL; + } + // otherwise make sure it is not the current recharging target + } else if (m_penRechargerTarget==&*penMarker[i]) { + m_penRechargerTarget=NULL; + penMarker[i] = NULL; + } + } + } + + BOOL CurrentRechargerExists(void) { + if (m_penRechargerTarget) { + if (!(m_penRechargerTarget->en_ulFlags&ENF_DELETED)) { return TRUE; }; + } + return FALSE; + } + + BOOL FindClosestRecharger(void) { + FLOAT fDistance = UpperLimit(1.0f); + m_penRechargerTarget = NULL; + if (m_penRCMarker01) { + if (DistanceTo(this, m_penRCMarker01)GetAttachmentModel(BODY_ATTACHMENT_ARM_LEFT); + return (amo.amo_plRelative.pl_OrientationAngle(2) + GetPlacement().pl_OrientationAngle(2)); + } + return 0.0f; + } + + ULONG SetDesiredMovement(void) + { + ULONG ulFlags = 0; + FLOAT3D vPos; + CEntity *penMarker = m_penMarkerNew; + CEntity *penTarget; + + if (m_ltTarget==LT_ENEMY && m_penEnemy) { penTarget = m_penEnemy; } + else if (m_ltTarget==LT_RECHARGER) { penTarget = m_penRecharger; } + else { return ulFlags; } + + // CPrintF("target = %s at %f\n", penTarget->GetName(), _pTimer->CurrentTick()); + + if (IsOnMarker(m_penMarkerNew)) { + PATH_FindNextMarker(penTarget, GetPlacement().pl_PositionVector, + penTarget->GetPlacement().pl_PositionVector, penMarker, vPos); + if (penMarker!=NULL) { + // remember the old marker + m_penMarkerOld = m_penMarkerNew; + // and set the new target + m_penMarkerNew = penMarker; + } + MoveToMarker(m_penMarkerNew); + ulFlags |= MF_MOVEZ; + } else { + MoveToMarker(m_penMarkerNew); + ulFlags |= MF_MOVEZ; + } + + if (m_ltTarget==LT_ENEMY && DistanceTo(this, penTarget)GetPlacement().pl_PositionVector - + GetPlacement().pl_PositionVector; + if (vDesiredDir.Length()>0.0f) { + vDesiredDir.Normalize(); + FLOAT3D vSpeed = vDesiredDir*m_fAttackRunSpeed; + SetDesiredTranslation(vSpeed); + } + } + + // pre moving + void PreMoving() { + + if (m_bActive && !m_bRenderLeftLaser && !m_bRenderRightLaser) { + + // rotate to enemy + if (m_penEnemy!=NULL) { + + FLOAT3D vToEnemy; + vToEnemy = (m_penEnemy->GetPlacement().pl_PositionVector - + GetPlacement().pl_PositionVector).Normalize(); + ANGLE3D aAngle; + DirectionVectorToAngles(vToEnemy, aAngle); + aAngle(1) = aAngle(1) - GetPlacement().pl_OrientationAngle(1); + aAngle(1) = NormalizeAngle(aAngle(1)); + SetDesiredRotation(FLOAT3D(aAngle(1)*2.0f, 0.0f, 0.0f)); + } else { + SetDesiredRotation(FLOAT3D(0.0f, 0.0f, 0.0f)); + } + + // lower speed if needed, not to miss the marker + if (en_vCurrentTranslationAbsolute.Length()*_pTimer->TickQuantum*2.0f > + DistanceTo(this, m_penMarkerNew)) { + FLOAT3D vToMarker = m_penMarkerNew->GetPlacement().pl_PositionVector - + GetPlacement().pl_PositionVector; + SetDesiredTranslation(vToMarker/_pTimer->TickQuantum) ; + } + + // stop when on marker + if (IsOnMarker(m_penMarkerNew)) { + ForceStopTranslation(); + } + } else { + ForceFullStop(); + } + + CEnemyBase::PreMoving(); + } + + void RenderParticles(void) + { + + FLOATmatrix3D m; + CPlacement3D plLarva; + + if (m_bRenderLeftLaser || m_bRenderRightLaser) { + plLarva = GetLerpedPlacement(); + MakeRotationMatrix(m, plLarva.pl_OrientationAngle); + } + + if (m_bRenderLeftLaser) { + FLOAT3D vSource = (FIREPOS_LASER_LEFT*m_fStretch)*m + plLarva.pl_PositionVector; + Particles_ExotechLarvaLaser(this, vSource, m_vLeftLaserTarget); + } + if (m_bRenderRightLaser) { + FLOAT3D vSource = (FIREPOS_LASER_RIGHT*m_fStretch)*m + plLarva.pl_PositionVector; + Particles_ExotechLarvaLaser(this, vSource, m_vRightLaserTarget); + } + if (m_bRechargePose && ((CExotechLarvaCharger *)&*m_penRecharger)->m_bBeamActive) + { + Particles_LarvaEnergy(this, FLOAT3D(0.0f, LARVA_HANDLE_TRANSLATE, 0.0f)*m_fStretch); + } + } + + void SizeModel(void) + { + return; + } + + void UpdateFiringPos() { + m_vFirePosLeftLaserAbs = (FIREPOS_LASER_LEFT*m_fStretch)*GetRotationMatrix() + GetPlacement().pl_PositionVector; + m_vFirePosRightLaserAbs = (FIREPOS_LASER_RIGHT*m_fStretch)*GetRotationMatrix() + GetPlacement().pl_PositionVector; + } + + void BlowUp(void) + { + NOTHING; + } + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + m_soFire1.Set3DParameters(600.0f, 150.0f, 2.0f, 1.0f); + m_soFire2.Set3DParameters(600.0f, 150.0f, 2.0f, 1.0f); + m_soFire3.Set3DParameters(600.0f, 150.0f, 2.0f, 1.0f); + m_soVoice.Set3DParameters(600.0f, 150.0f, 2.0f, 1.0f); + m_soChirp.Set3DParameters(150.0f, 50.0f, 2.0f, 1.0f); + m_soLaser.Set3DParameters(300.0f, 200.0f, 3.0f, 1.0f); + } + + void FireLaser(void) + { + + FLOAT3D vLaserTarget; + + if (!m_penEnemy) { return; } + + if (IsVisible(m_penEnemy)) { + vLaserTarget = m_penEnemy->GetPlacement().pl_PositionVector; + } else if (TRUE) { + vLaserTarget = m_vPlayerSpotted; + } + + // cast 1st ray + CCastRay crRay1( this, m_vFirePosLeftLaserAbs, vLaserTarget); + crRay1.cr_fTestR = 0.10f; + crRay1.cr_bHitTranslucentPortals = FALSE; + crRay1.cr_bPhysical = FALSE; + crRay1.cr_ttHitModels = CCastRay::TT_COLLISIONBOX; + GetWorld()->CastRay(crRay1); + + // if entity is hit + if( crRay1.cr_penHit != NULL) { + m_bRenderLeftLaser = TRUE; + m_vLeftLaserTarget = crRay1.cr_vHit; + + // apply damage + InflictDirectDamage( crRay1.cr_penHit, this, DMT_BURNING, 25.0f, + FLOAT3D(0, 0, 0), (m_vFirePosLeftLaserAbs-m_vLeftLaserTarget).Normalize()); + + if (crRay1.cr_penHit->GetRenderType()!=RT_BRUSH) { + crRay1.cr_ttHitModels = CCastRay::TT_NONE; + GetWorld()->ContinueCast(crRay1); + if (crRay1.cr_penHit != NULL) { + m_vLeftLaserTarget = crRay1.cr_vHit; + } + } + } else if (TRUE) { + m_bRenderLeftLaser = FALSE; + } + + // cast 2nd ray + CCastRay crRay2( this, m_vFirePosRightLaserAbs, vLaserTarget); + crRay2.cr_fTestR = 0.10f; + crRay2.cr_bHitTranslucentPortals = FALSE; + crRay2.cr_bPhysical = FALSE; + crRay2.cr_ttHitModels = CCastRay::TT_COLLISIONBOX; + GetWorld()->CastRay(crRay2); + + // if entity is hit + if( crRay2.cr_penHit != NULL) { + m_bRenderRightLaser = TRUE; + m_vRightLaserTarget = crRay2.cr_vHit; + + // apply damage + InflictDirectDamage( crRay2.cr_penHit, this, DMT_BURNING, 25.0f, + FLOAT3D(0, 0, 0), (m_vFirePosRightLaserAbs-m_vRightLaserTarget).Normalize()); + + if (crRay2.cr_penHit->GetRenderType()!=RT_BRUSH) { + crRay2.cr_ttHitModels = CCastRay::TT_NONE; + GetWorld()->ContinueCast(crRay2); + if (crRay2.cr_penHit != NULL) { + m_vRightLaserTarget = crRay2.cr_vHit; + } + } + } else if (TRUE) { + m_bRenderRightLaser = FALSE; + } + } + + void ExplodeLaser(void) + { + if (m_bRenderLeftLaser) { + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNON; + eSpawnEffect.vStretch = FLOAT3D(m_fStretch*0.5, m_fStretch*0.5, m_fStretch*0.5); + CEntityPointer penExplosion = CreateEntity(CPlacement3D(m_vLeftLaserTarget, + ANGLE3D(0.0f, 0.0f, 0.0f)), CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + + // explosion debris + eSpawnEffect.betType = BET_EXPLOSION_DEBRIS; + penExplosion = CreateEntity(CPlacement3D(m_vLeftLaserTarget, + ANGLE3D(0.0f, 0.0f, 0.0f)), CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + + // explosion smoke + eSpawnEffect.betType = BET_EXPLOSION_SMOKE; + penExplosion = CreateEntity(CPlacement3D(m_vLeftLaserTarget, + ANGLE3D(0.0f, 0.0f, 0.0f)), CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + + InflictRangeDamage( this, DMT_EXPLOSION, 25.0f, + m_vLeftLaserTarget, 5.0f, 25.0f); + } + + if (m_bRenderRightLaser) { + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNON; + eSpawnEffect.vStretch = FLOAT3D(m_fStretch*0.5, m_fStretch*0.5, m_fStretch*0.5); + CEntityPointer penExplosion = CreateEntity(CPlacement3D(m_vLeftLaserTarget, + ANGLE3D(0.0f, 0.0f, 0.0f)), CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + + // explosion debris + eSpawnEffect.betType = BET_EXPLOSION_DEBRIS; + penExplosion = CreateEntity(CPlacement3D(m_vLeftLaserTarget, + ANGLE3D(0.0f, 0.0f, 0.0f)), CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + + // explosion smoke + eSpawnEffect.betType = BET_EXPLOSION_SMOKE; + penExplosion = CreateEntity(CPlacement3D(m_vLeftLaserTarget, + ANGLE3D(0.0f, 0.0f, 0.0f)), CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + + InflictRangeDamage( this, DMT_EXPLOSION, 25.0f, + m_vLeftLaserTarget, 5.0f, 25.0f); + } + } + + +/****************************************/ +/* P R O C E D U R E S */ +/****************************************/ + +procedures: + + // override wounding so that Larva doesn't stutter + BeWounded(EDamage eDamage) : CEnemyBase::BeWounded { + return EReturn(); + }; + + ArmExplosion() + { + FLOATmatrix3D mRot; + FLOAT3D vPos; + + m_bActive = FALSE; + + // right arm + if (m_iExplodingArm==ARM_RIGHT) { + MakeRotationMatrixFast(mRot, ANGLE3D(0.0f, 0.0f, 0.0f)); + vPos = FLOAT3D(0.0f, 0.0f, 0.0f); + GetModelForRendering()->GetAttachmentTransformations(BODY_ATTACHMENT_ARM_RIGHT, mRot, vPos, FALSE); + m_plExpArmPos.pl_PositionVector = vPos*GetRotationMatrix() + GetPlacement().pl_PositionVector; + m_plExpArmPos.pl_OrientationAngle = GetPlacement().pl_OrientationAngle; + CAttachmentModelObject &amo0 = *GetModelObject()->GetAttachmentModel(BODY_ATTACHMENT_ARM_RIGHT); + amo0.amo_moModelObject.GetAttachmentTransformations(ARM_ATTACHMENT_PLASMAGUN, mRot, vPos, FALSE); + m_plExpGunPos.pl_PositionVector = vPos*GetRotationMatrix() + GetPlacement().pl_PositionVector; + m_plExpGunPos.pl_OrientationAngle = GetPlacement().pl_OrientationAngle; + m_vExpDamage = FLOAT3D( +12.0f, 15.0f, 0.0f); + + if (m_penLeftArmDestroyTarget) { + SendToTarget(m_penLeftArmDestroyTarget, EET_TRIGGER, FixupCausedToPlayer(this, m_penEnemy)); + } + } + + // left arm + if (m_iExplodingArm==ARM_LEFT) { + MakeRotationMatrixFast(mRot, ANGLE3D(0.0f, 0.0f, 0.0f)); + vPos = FLOAT3D(0.0f, 0.0f, 0.0f); + GetModelForRendering()->GetAttachmentTransformations(BODY_ATTACHMENT_ARM_LEFT, mRot, vPos, FALSE); + m_plExpArmPos.pl_PositionVector = vPos*GetRotationMatrix() + GetPlacement().pl_PositionVector; + m_plExpArmPos.pl_OrientationAngle = GetPlacement().pl_OrientationAngle; + m_plExpArmPos.pl_OrientationAngle(1)+=180.0f; + CAttachmentModelObject &amo0 = *GetModelObject()->GetAttachmentModel(BODY_ATTACHMENT_ARM_LEFT); + amo0.amo_moModelObject.GetAttachmentTransformations(ARM_ATTACHMENT_PLASMAGUN, mRot, vPos, FALSE); + m_plExpGunPos.pl_PositionVector = vPos*GetRotationMatrix() + GetPlacement().pl_PositionVector; + m_plExpGunPos.pl_OrientationAngle = GetPlacement().pl_OrientationAngle; + m_vExpDamage = FLOAT3D( -12.0f, 15.0f, 0.0f); + + if (m_penRightArmDestroyTarget) { + SendToTarget(m_penRightArmDestroyTarget, EET_TRIGGER, FixupCausedToPlayer(this, m_penEnemy)); + } + } + m_aExpArmRot = ANGLE3D(FRnd()*360.0f-180.0f, FRnd()*360.0f-180.0f, FRnd()*360.0f-180.0f); + m_aExpGunRot = ANGLE3D(FRnd()*360.0f-180.0f, FRnd()*360.0f-180.0f, FRnd()*360.0f-180.0f); + m_vExpDamage = m_vExpDamage*GetRotationMatrix(); + + if (m_iExplodingArm==ARM_RIGHT) { m_bRightArmActive = FALSE; } + if (m_iExplodingArm==ARM_LEFT) { m_bLeftArmActive = FALSE; } + + PlaySound(m_soVoice, SOUND_ARMDESTROY, SOF_3D); + // spawn explosion #1 + CPlacement3D pl = GetPlacement(); + pl.pl_PositionVector += FLOAT3D(0.0f, LARVA_HANDLE_TRANSLATE, 0.0f); + ShakeItBaby(_pTimer->CurrentTick(), 0.5f, FALSE); + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNON; + eSpawnEffect.vStretch = FLOAT3D(m_fStretch*0.5, m_fStretch*0.5, m_fStretch*0.5); + CEntityPointer penExplosion = CreateEntity(pl, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + autowait(FRnd()*0.25f+0.15f); + // spawn explosion #2 + ShakeItBaby(_pTimer->CurrentTick(), 0.5f, FALSE); + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNON; + eSpawnEffect.vStretch = FLOAT3D(m_fStretch, m_fStretch, m_fStretch); + CPlacement3D plMiddle; + plMiddle.pl_PositionVector = (m_plExpArmPos.pl_PositionVector + m_plExpGunPos.pl_PositionVector)/2.0f; + plMiddle.pl_OrientationAngle = m_plExpArmPos.pl_OrientationAngle; + CEntityPointer penExplosion = CreateEntity(plMiddle, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + autowait(FRnd()*0.15f+0.15f); + // spawn explosion #3 & #4 + CPlacement3D pl = GetPlacement(); + pl.pl_PositionVector += FLOAT3D(0.0f, LARVA_HANDLE_TRANSLATE, 0.0f); + ShakeItBaby(_pTimer->CurrentTick(), 1.0f, FALSE); + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNON; + eSpawnEffect.vStretch = FLOAT3D(m_fStretch*1.5,m_fStretch*1.5,m_fStretch*1.5); + CEntityPointer penExplosion = CreateEntity(pl, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + eSpawnEffect.betType = BET_ROCKET; + penExplosion = CreateEntity(m_plExpGunPos, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + + SpawnWingDebris(); + RemoveWing(m_iExplodingArm); + + // wait a little bit 'to recover' + autowait(1.5f); + + m_bExploding = FALSE; + m_bActive = TRUE; + + // restart behaveour + SendEvent(EBegin()); + + return EReturn(); + } + + Die(EDeath eDeath) : CEnemyBase::Die { + + m_penDeathInflictor = eDeath.eLastDamage.penInflictor; + + m_bActive = FALSE; + m_iExplosions = 8; + + PlaySound(m_soChirp, SOUND_DEATH, SOF_3D); + m_soLaser.Stop(); + + // spawn explosions + while ((m_iExplosions--)>0) + { + ShakeItBaby(_pTimer->CurrentTick(), 0.5f, FALSE); + + // randomize explosion position and size + CPlacement3D plExplosion; + plExplosion.pl_OrientationAngle = ANGLE3D(0.0f, 0.0f, 0.0f); + plExplosion.pl_PositionVector = FLOAT3D(FRnd()*2.0-1.0f, FRnd()*3.0-1.5f+LARVA_HANDLE_TRANSLATE, FRnd()*2.0-1.0f)*m_fStretch + GetPlacement().pl_PositionVector; + FLOAT vExpSize = (FRnd()*0.7f+0.7f)*m_fStretch; + + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNON; + eSpawnEffect.vStretch = FLOAT3D(vExpSize, vExpSize, vExpSize); + CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + autowait(FRnd()*0.05f+0.35f); + } + + ShakeItBaby(_pTimer->CurrentTick(), 2.0f, FALSE); + + // final explosions + CPlacement3D plExplosion; + plExplosion.pl_OrientationAngle = ANGLE3D(0.0f, 0.0f, 0.0f); + plExplosion.pl_PositionVector = FLOAT3D(0.0f,-1.5f+LARVA_HANDLE_TRANSLATE, 1.5f)*m_fStretch + GetPlacement().pl_PositionVector; + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNON; + eSpawnEffect.vStretch = FLOAT3D(m_fStretch, m_fStretch, m_fStretch)*2.0f; + CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + plExplosion.pl_PositionVector = FLOAT3D(-1.0f,-0.2f+LARVA_HANDLE_TRANSLATE,-1.5f)*m_fStretch + GetPlacement().pl_PositionVector; + penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + plExplosion.pl_PositionVector = FLOAT3D(1.0f, 1.7f+LARVA_HANDLE_TRANSLATE, 0.1f)*m_fStretch + GetPlacement().pl_PositionVector; + penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + plExplosion.pl_PositionVector = GetPlacement().pl_PositionVector; + eSpawnEffect.betType = BET_ROCKET; + penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + // end debris + m_vExpDamage = FLOAT3D( 0.0f, 15.0f, 0.0f); + FLOAT3D vTranslation = m_vExpDamage; + CPlacement3D plDebris = GetPlacement(); + plDebris.pl_PositionVector += FLOAT3D(0.0f, LARVA_HANDLE_TRANSLATE, 0.0f); + Debris_Begin(EIBT_FLESH, DPT_BLOODTRAIL, BET_BLOODSTAIN, 1.0f, m_vExpDamage, en_vCurrentTranslationAbsolute, 5.0f, 2.0f); + Debris_Spawn_Independent(this, this, MODEL_DEBRIS_BODY, TEXTURE_BODY, 0, 0, 0, 0, m_fStretch, + plDebris, vTranslation, ANGLE3D(45.0f, 230.0f, 0.0f)); + vTranslation += FLOAT3D(FRnd()*4.0f-2.0f, FRnd()*4.0f-2.0f, FRnd()*4.0f-2.0f); + Debris_Spawn_Independent(this, this, MODEL_DEBRIS_TAIL01, TEXTURE_BODY, 0, 0, 0, 0, m_fStretch, + plDebris, vTranslation, ANGLE3D(15.0f, 130.0f, 0.0f)); + vTranslation += FLOAT3D(FRnd()*4.0f-2.0f, FRnd()*4.0f-2.0f, FRnd()*4.0f-2.0f); + Debris_Spawn_Independent(this, this, MODEL_DEBRIS_TAIL02, TEXTURE_BODY, 0, 0, 0, 0, m_fStretch, + plDebris, vTranslation, ANGLE3D(145.0f, 30.0f, 0.0f)); + for (INDEX i=0; i<8; i++) { + Debris_Spawn(this, this, MODEL_DEBRIS_FLESH, TEXTURE_DEBRIS_FLESH , 0, 0, 0, 0, m_fStretch, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f+LARVA_HANDLE_TRANSLATE, FRnd()*0.6f+0.2f)); + } + + // explosion + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_EXPLOSION_DEBRIS; + eSpawnEffect.vStretch = FLOAT3D(1,1,1); + penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + // explosion smoke + eSpawnEffect.betType = BET_EXPLOSION_SMOKE; + penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + + EDeath eDeath; + eDeath.eLastDamage.penInflictor = m_penDeathInflictor; + + EActivateBeam eab; + eab.bTurnOn = FALSE; + m_penRecharger->SendEvent(eab); + + if (m_penDeathTarget) { + SendToTarget(m_penDeathTarget, EET_TRIGGER, FixupCausedToPlayer(this, m_penEnemy)); + } + + jump CEnemyBase::Die(eDeath); + } + + + Fire(EVoid) : CEnemyBase::Fire { + + UpdateFiringPos(); + // if larva has at least one wing + if (m_bLeftArmActive || m_bRightArmActive) { + m_iRnd = IRnd()%9; + if (m_iRnd>6 && !m_bRechargePose && GetHealth()>0.1f*m_fMaxHealth) { + PlaySound(m_soFire3, SOUND_FIRE_TAIL, SOF_3D); + ShootTailProjectile(); + } + if (m_iRnd>6 && m_bRechargePose) { + m_iRnd = 3; + } + + if (m_iRnd>3) { + return EReturn(); + } + + while(m_iRnd>0) { + if (m_bLeftArmActive) { + PlaySound(m_soFire1, SOUND_FIRE_PLASMA, SOF_3D); + ShootProjectile(PRT_LARVA_PLASMA, m_vFirePosLeftPlasmaRel, ANGLE3D(0, 0, 0)); + RemoveAttachmentFromModel(*PlasmaLeftModel(), PLASMAGUN_ATTACHMENT_PROJECTILE); + autowait(0.25f); + PlasmaLeftModel()->PlayAnim(PLASMAGUN_ANIM_SPAWNING, 0); + autowait(0.25f); + AddAttachmentToModel(this, *PlasmaLeftModel(), PLASMAGUN_ATTACHMENT_PROJECTILE, MODEL_PLASMA, TEXTURE_PLASMA, 0, 0, 0); + CAttachmentModelObject *amo = PlasmaLeftModel()->GetAttachmentModel(BODY_ATTACHMENT_ARM_LEFT); + amo->amo_moModelObject.StretchModel(FLOAT3D(m_fStretch, m_fStretch, m_fStretch)); + } + if (m_bRightArmActive) { + PlaySound(m_soFire2, SOUND_FIRE_PLASMA, SOF_3D); + ShootProjectile(PRT_LARVA_PLASMA, m_vFirePosRightPlasmaRel, ANGLE3D(0, 0, 0)); + RemoveAttachmentFromModel(*PlasmaRightModel(), PLASMAGUN_ATTACHMENT_PROJECTILE); + autowait(0.25f); + PlasmaRightModel()->PlayAnim(PLASMAGUN_ANIM_SPAWNING, 0); + autowait(0.25f); + AddAttachmentToModel(this, *PlasmaRightModel(), PLASMAGUN_ATTACHMENT_PROJECTILE, MODEL_PLASMA, TEXTURE_PLASMA, 0, 0, 0); + CAttachmentModelObject *amo = PlasmaRightModel()->GetAttachmentModel(BODY_ATTACHMENT_ARM_LEFT); + amo->amo_moModelObject.StretchModel(FLOAT3D(m_fStretch, m_fStretch, m_fStretch)); + } + m_iRnd--; + } + // if no wings left fire laser + } else if (TRUE) { + m_iRnd = IRnd()%10; + if (m_iRnd>6 && !m_bRechargePose && GetHealth()>0.1f*m_fMaxHealth) { + PlaySound(m_soFire3, SOUND_FIRE_TAIL, SOF_3D); + ShootTailProjectile(); + } + if (m_iRnd<4 && _pTimer->CurrentTick()>m_tmDontFireLaserBefore) { + PlaySound(m_soLaser, SOUND_LASER_CHARGE, SOF_3D); + SpawnReminder(this, 3.0f, 129); + m_tmDontFireLaserBefore = _pTimer->CurrentTick()+m_fMinimumLaserWait; + } + } + + PerhapsChangeTarget(); + + return EReturn(); + } + + Hit(EVoid) : CEnemyBase::Hit { + return EReturn(); + } + + BeIdle(EVoid) : CEnemyBase::BeIdle { + + PerhapsChangeTarget(); + + autowait(0.5f); + + while (TRUE) { + FindNewTarget(); + SendEvent(EReconsiderBehavior()); + autowait(0.5f); + } + }; + + + LarvaLoop() { + + FindNewTarget(); + SendEvent(EReconsiderBehavior()); + + StartModelAnim(BODY_ANIM_IDLE, AOF_SMOOTHCHANGE|AOF_LOOPING); + + SpawnReminder(this, 0.5f, 128); + SpawnReminder(this, 0.5f, 145); // fire guided reminder + wait () { + on (EBegin) : + { + if (!m_bLeftArmActive && !m_bRightArmActive) { + CModelObject &amo = GetModelObject()->GetAttachmentModel(BODY_ATTACHMENT_BACKARMS)->amo_moModelObject; + amo.PlayAnim(BACKARMS_ANIM_ACTIVATING, AOF_SMOOTHCHANGE|AOF_NORESTART); + PlaySound(m_soFire1, SOUND_DEPLOYLASER, SOF_3D); + SpawnReminder(this, amo.GetAnimLength(BACKARMS_ANIM_ACTIVATING), 160); + } + call CEnemyBase::MainLoop(); + } + + on (ELarvaArmDestroyed ead) : + { + m_iExplodingArm = ead.iArm; + call ArmExplosion(); + } + + on (ELarvaRechargePose elrp) : + { + if (elrp.bStart==TRUE && m_bRechargePose!=TRUE) { + StartModelAnim(BODY_ANIM_TORECHARGING, AOF_SMOOTHCHANGE|AOF_NORESTART); + SpawnReminder(this, GetModelObject()->GetAnimLength(BODY_ANIM_TORECHARGING), 156); + } + if (elrp.bStart==FALSE && m_bRechargePose!=FALSE) { + StartModelAnim(BODY_ANIM_FROMRECHARGING, AOF_SMOOTHCHANGE|AOF_NORESTART); + SpawnReminder(this, GetModelObject()->GetAnimLength(BODY_ANIM_FROMRECHARGING), 157); + } + resume; + } + + on (EReminder er) : + { + // if this is not our reminder, pass (although there are no states below this?) + if (er.iValue==128) { + // while recharger is active keep respawning the reminder to return here + if (RechargerActive()) { + SpawnReminder(this, 1.0f, 128); + } else { + m_bRecharging = FALSE; + m_ltTarget = LT_ENEMY; + // return to idle pose + ELarvaRechargePose elrp; + elrp.bStart = FALSE; + SendEvent(elrp); + } + // if larva is in recharge mode and close enough to recharger and beam is up + if (m_bActive && m_bRecharging && DistanceXZ(this, m_penRecharger)<5.0f) { + if (m_bRechargePose) { + if (((CExotechLarvaCharger *)&*m_penRecharger)->m_bBeamActive) + { + if (!m_bRechargedAtLeastOnce) { + if (m_penFirstRechargeTarget) { + SendToTarget(m_penFirstRechargeTarget , EET_TRIGGER, FixupCausedToPlayer(this, m_penEnemy)); + } + m_bRechargedAtLeastOnce = TRUE; + } + SetHealth(ClampUp(GetHealth()+m_fRechargePerSecond, m_fMaxHealth*m_fMaxRechargedHealth)); + if (GetHealth()>m_fMaxHealth*0.95) { + m_ltTarget = LT_ENEMY; + m_bRecharging = FALSE; + // deactivate beam + EActivateBeam eab; + eab.bTurnOn = FALSE; + m_penRecharger->SendEvent(eab); + // return to idle pose + ELarvaRechargePose elrp; + elrp.bStart = FALSE; + SendEvent(elrp); + } + } else if (TRUE) { + EActivateBeam eab; + eab.bTurnOn = TRUE; + m_penRecharger->SendEvent(eab); + } + } else { + ELarvaRechargePose elrp; + elrp.bStart = TRUE; + SendEvent(elrp); + } + } + // if larva is in normal mode + else if (TRUE) { + if (GetHealth()<(m_fLarvaHealth*0.7f)) { + if (!RechargerActive()) { + m_ltTarget = LT_ENEMY; + } else { + m_bRecharging = TRUE; + m_ltTarget = LT_RECHARGER; + } + } + } + resume; + // check to see if guided missile firing is needed + } else if (er.iValue==145) { + FindNewTarget(); + if (AnyPlayerCloserThen(9.0f) && GetHealth()>0.1f*m_fMaxHealth) { + UpdateFiringPos(); + PlaySound(m_soFire3, SOUND_FIRE_TAIL, SOF_3D); + ShootTailProjectile(); + } + else if (m_penEnemy && GetHealth()>0.1f*m_fMaxHealth) { + if (!IsVisible(m_penEnemy)) { + INDEX iRnd = IRnd()%6; + if (iRnd>4) { + UpdateFiringPos(); + PlaySound(m_soFire3, SOUND_FIRE_TAIL, SOF_3D); + ShootTailProjectile(); + } + } + } + SpawnReminder(this, 0.5f, 145); + resume; + // begin rendering laser + } else if (er.iValue==129) { + if (m_bActive && m_bLaserActive) { FireLaser(); } + SpawnReminder(this, 0.35f, 130); + resume; + // explode the laser without turning it off + } else if (er.iValue==130) { + if (m_bActive) { ExplodeLaser(); } + SpawnReminder(this, 0.75f, 131); + resume; + // finally stop rendering the laser + } else if (er.iValue==131) { + m_bRenderLeftLaser = FALSE; + m_bRenderRightLaser = FALSE; + resume; + // start charging anim + } else if (er.iValue==156) { + m_bRechargePose = TRUE; + StartModelAnim(BODY_ANIM_RECHARGING, AOF_SMOOTHCHANGE|AOF_LOOPING); + resume; + // return to idle anim + } else if (er.iValue==157) { + m_bRechargePose = FALSE; + StartModelAnim(BODY_ANIM_IDLE, AOF_SMOOTHCHANGE|AOF_LOOPING); + // stop charging anim + } else if (er.iValue==160) { + CModelObject &amo = GetModelObject()->GetAttachmentModel(BODY_ATTACHMENT_BACKARMS)->amo_moModelObject; + amo.PlayAnim(BACKARMS_ANIM_ACTIVE, AOF_SMOOTHCHANGE|AOF_LOOPING); + m_bLaserActive = TRUE; + } + resume; + } + } + } + + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_FLYING|EPF_HASLUNGS|EPF_ABSOLUTETRANSLATE); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + en_fDensity = 2000.0f; + + // set your appearance + SetModel(MODEL_BODY); + SetModelMainTexture(TEXTURE_BODY); + + // add left side attachments + AddAttachmentToModel(this, *GetModelObject(), BODY_ATTACHMENT_ARM_LEFT, MODEL_WING, TEXTURE_WING, 0, 0, 0); + CModelObject &amo0 = GetModelObject()->GetAttachmentModel(BODY_ATTACHMENT_ARM_LEFT)->amo_moModelObject; + AddAttachmentToModel(this, amo0, ARM_ATTACHMENT_PLASMAGUN, MODEL_PLASMAGUN, TEXTURE_PLASMAGUN, 0, 0, 0); + + // add right side attachments + AddAttachmentToModel(this, *GetModelObject(), BODY_ATTACHMENT_ARM_RIGHT, MODEL_WING, TEXTURE_WING, 0, 0, 0); + CModelObject &amo1 = GetModelObject()->GetAttachmentModel(BODY_ATTACHMENT_ARM_RIGHT)->amo_moModelObject; + amo1.StretchModel(FLOAT3D(-1.0f, 1.0f, 1.0f)); + AddAttachmentToModel(this, amo1, ARM_ATTACHMENT_PLASMAGUN, MODEL_PLASMAGUN, TEXTURE_PLASMAGUN, 0, 0, 0); + CModelObject &amo2 = amo1.GetAttachmentModel(ARM_ATTACHMENT_PLASMAGUN)->amo_moModelObject; + amo2.StretchModel(FLOAT3D(-1.0f, 1.0f, 1.0f)); + + // add blades + AddAttachmentToModel(this, *GetModelObject(), BODY_ATTACHMENT_BACKARMS, MODEL_BLADES, TEXTURE_BODY, 0, 0, 0); + + // add holder + AddAttachmentToModel(this, *GetModelObject(), BODY_ATTACHMENT_EXOTECHLARVA, MODEL_EXOTECHLARVA, TEXTURE_EXOTECHLARVA, 0, 0, 0); + CModelObject &amo3 = GetModelObject()->GetAttachmentModel(BODY_ATTACHMENT_EXOTECHLARVA)->amo_moModelObject; + AddAttachmentToModel(this, amo3, EXOTECHLARVA_ATTACHMENT_BEAM, MODEL_BEAM, TEXTURE_BEAM, 0, 0, 0); + AddAttachmentToModel(this, amo3, EXOTECHLARVA_ATTACHMENT_ENERGYBEAMS, MODEL_ENERGYBEAMS, TEXTURE_ENERGYBEAMS, 0, 0, 0); + AddAttachmentToModel(this, amo3, EXOTECHLARVA_ATTACHMENT_FLARE, MODEL_FLARE, TEXTURE_FLARE, 0, 0, 0); + + AddAttachmentToModel(this, *PlasmaLeftModel(), PLASMAGUN_ATTACHMENT_PROJECTILE, MODEL_PLASMA, TEXTURE_PLASMA, 0, 0, 0); + AddAttachmentToModel(this, *PlasmaRightModel(), PLASMAGUN_ATTACHMENT_PROJECTILE, MODEL_PLASMA, TEXTURE_PLASMA, 0, 0, 0); + + // set the size of this model + GetModelObject()->StretchModelRelative(FLOAT3D(m_fStretch, m_fStretch, m_fStretch)); + + m_vFirePosLeftPlasmaRel = FIREPOS_PLASMA_LEFT*m_fStretch; + m_vFirePosRightPlasmaRel = FIREPOS_PLASMA_RIGHT*m_fStretch; + //m_vFirePosMouthRel = FIREPOS_MOUTH*m_fStretch; + m_vFirePosTailRel = FIREPOS_TAIL*m_fStretch; + + // this is a boss + m_bBoss = TRUE; + + // setup moving speed + m_fWalkSpeed = 0.0f; + m_aWalkRotateSpeed = 100.0f; + m_fAttackRunSpeed = 7.5f; + m_aAttackRotateSpeed = 100.0f; + // setup attack distances + m_fStopDistance = m_fStopRadius; + m_fBlowUpAmount = 100.0f; + m_fBodyParts = 0; + m_fDamageWounded = 0.0f; + m_iScore = 750000; + m_sptType = SPT_BLOOD; + m_fAttackDistance = 100.0f; + m_fCloseDistance = 0.0f; + + m_fAttackFireTime = 0.5f; + m_fCloseFireTime = 0.5f; + + // set acceleration/deceleration + en_fAcceleration = UpperLimit(1.0f); + en_fDeceleration = UpperLimit(1.0f); + + // set health + SetHealth(m_fLarvaHealth); + m_fMaxHealth = m_fLarvaHealth; + + m_bActive = TRUE; + m_bExploding = FALSE; + m_bLaserActive = FALSE; + + // set stretch factors for height and width + //GetModelObject()->StretchModel(FLOAT3D(2.0f, 2.0f, 2.0f)); + + ModelChangeNotify(); + StandingAnim(); + + autowait(0.05f); + + // make larva invulnerable 'till start marker + m_bInvulnerable = TRUE; + + if (!DoSafetyChecks()) { + Destroy(); + return; + } + + // wait to be triggered + wait() { + on (EBegin) : { resume; } + on (ETrigger) : { stop; } + otherwise (): { resume; } + } + + PlaySound(m_soChirp, SOUND_CHIRP, SOF_3D|SOF_LOOP); + + // move to first marker + while (DistanceTo(this, m_penMarkerNew)>5.0f) { + wait(0.05f) { + on (EBegin) : { resume; } + on (ETimer) : { + FLOAT3D vToMarker = m_penMarkerNew->GetPlacement().pl_PositionVector - GetPlacement().pl_PositionVector; + vToMarker.Normalize(); + SetDesiredTranslation(vToMarker*m_fAttackRunSpeed); + stop; + } + } + } + + m_bInvulnerable = FALSE; + + // one state under base class to intercept some events + jump LarvaLoop(); + //jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/ExotechLarva.h b/Sources/EntitiesMP/ExotechLarva.h new file mode 100644 index 0000000..b4816bb --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarva.h @@ -0,0 +1,259 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ExotechLarva_INCLUDED +#define _EntitiesMP_ExotechLarva_INCLUDED 1 +#include +#include +#include +#include +#include +#include +#include +extern DECL_DLL CEntityPropertyEnumType LarvaTarget_enum; +enum LarvaTarget { + LT_NONE = 0, + LT_ENEMY = 1, + LT_RECHARGER = 2, +}; +DECL_DLL inline void ClearToDefault(LarvaTarget &e) { e = (LarvaTarget)0; } ; +#define EVENTCODE_ELarvaArmDestroyed 0x015a0000 +class DECL_DLL ELarvaArmDestroyed : public CEntityEvent { +public: +ELarvaArmDestroyed(); +CEntityEvent *MakeCopy(void); +INDEX iArm; +}; +DECL_DLL inline void ClearToDefault(ELarvaArmDestroyed &e) { e = ELarvaArmDestroyed(); } ; +#define EVENTCODE_ELarvaRechargePose 0x015a0001 +class DECL_DLL ELarvaRechargePose : public CEntityEvent { +public: +ELarvaRechargePose(); +CEntityEvent *MakeCopy(void); +BOOL bStart; +}; +DECL_DLL inline void ClearToDefault(ELarvaRechargePose &e) { e = ELarvaRechargePose(); } ; +extern "C" DECL_DLL CDLLEntityClass CExotechLarva_DLLClass; +class CExotechLarva : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penMarkerNew; + CEntityPointer m_penMarkerOld; + FLOAT m_fStopRadius; + FLOAT m_fStretch; + FLOAT m_fLarvaHealth; + FLOAT m_fRechargePerSecond; + enum LarvaTarget m_ltTarget; + CEntityPointer m_penFirstRechargeTarget; + BOOL m_bRechargedAtLeastOnce; + FLOAT3D m_vFirePosLeftPlasmaRel; + FLOAT3D m_vFirePosRightPlasmaRel; + FLOAT3D m_vFirePosTailRel; + FLOAT3D m_vFirePosLeftLaserAbs; + FLOAT3D m_vFirePosRightLaserAbs; + BOOL m_bLeftArmActive; + BOOL m_bRightArmActive; + INDEX m_iExplodingArm; + FLOAT m_fMaxRechargedHealth; + BOOL m_bExploding; + BOOL m_bActive; + BOOL m_bRechargePose; + BOOL m_bLaserActive; + BOOL m_bInitialMove; + CEntityPointer m_penRecharger; + FLOAT m_tmLastTargateChange; + CPlacement3D m_plExpArmPos; + FLOAT3D m_aExpArmRot; + CPlacement3D m_plExpGunPos; + FLOAT3D m_aExpGunRot; + FLOAT3D m_vExpDamage; + INDEX m_iExplosions; + INDEX m_iRnd; + BOOL m_bRecharging; + CEntityPointer m_penDeathInflictor; + FLOAT m_tmDontFireLaserBefore; + FLOAT m_fMinimumLaserWait; + BOOL m_bRenderLeftLaser; + BOOL m_bRenderRightLaser; + FLOAT3D m_vLeftLaserTarget; + FLOAT3D m_vRightLaserTarget; + BOOL m_bInvulnerable; + CEntityPointer m_penLeftArmDestroyTarget; + CEntityPointer m_penRightArmDestroyTarget; + CEntityPointer m_penDeathTarget; + CSoundObject m_soFire1; + CSoundObject m_soFire2; + CSoundObject m_soFire3; + CSoundObject m_soVoice; + CSoundObject m_soChirp; + CSoundObject m_soLaser; + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BOOL DoSafetyChecks(void); + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void FindNewTarget(); + +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BOOL AnyPlayerCloserThen(FLOAT fDistance); + +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void PerhapsChangeTarget(); + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +class CWorldSettingsController * GetWSC(void); + +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void ShakeItBaby(FLOAT tmShaketime,FLOAT fPower,BOOL bFadeIn); + +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void ShootTailProjectile(void); + +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BOOL IsOnMarker(CEntity * penMarker); + +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT DistanceXZ(CEntity * E1,CEntity * E2); + +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void SpawnWingDebris(); + +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void * GetEntityInfo(void); + +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void Precache(void); + +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CModelObject * PlasmaLeftModel(void); + +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +CModelObject * PlasmaRightModel(void); + +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BOOL RechargerActive(); + +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void RemoveWing(INDEX iArm); + +#line 652 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ANGLE GetArmsPitch(void); + +#line 660 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ULONG SetDesiredMovement(void); + +#line 696 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void MoveToMarker(CEntity * penMarker); + +#line 708 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void PreMoving(); + +#line 746 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void RenderParticles(void); + +#line 771 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void SizeModel(void); + +#line 776 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void UpdateFiringPos(); + +#line 781 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void BlowUp(void); + +#line 787 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void EnemyPostInit(void); + +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void FireLaser(void); + +#line 867 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +void ExplodeLaser(void); +#define STATE_CExotechLarva_BeWounded 0x015a0002 + BOOL +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BeWounded(const CEntityEvent &__eeInput); +#define STATE_CExotechLarva_ArmExplosion 0x015a0003 + BOOL +#line 932 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ArmExplosion(const CEntityEvent &__eeInput); + BOOL H0x015a0004_ArmExplosion_01(const CEntityEvent &__eeInput); + BOOL H0x015a0005_ArmExplosion_02(const CEntityEvent &__eeInput); + BOOL H0x015a0006_ArmExplosion_03(const CEntityEvent &__eeInput); + BOOL H0x015a0007_ArmExplosion_04(const CEntityEvent &__eeInput); + BOOL H0x015a0008_ArmExplosion_05(const CEntityEvent &__eeInput); + BOOL H0x015a0009_ArmExplosion_06(const CEntityEvent &__eeInput); +#define STATE_CExotechLarva_Die 0x015a000a + BOOL +#line 1035 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Die(const CEntityEvent &__eeInput); + BOOL H0x015a000b_Die_01(const CEntityEvent &__eeInput); + BOOL H0x015a000c_Die_02(const CEntityEvent &__eeInput); + BOOL H0x015a000d_Die_03(const CEntityEvent &__eeInput); + BOOL H0x015a000e_Die_04(const CEntityEvent &__eeInput); +#define STATE_CExotechLarva_Fire 0x015a000f + BOOL +#line 1132 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x015a0010_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x015a0011_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x015a0012_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x015a0013_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x015a0014_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x015a0015_Fire_06(const CEntityEvent &__eeInput); + BOOL H0x015a0016_Fire_07(const CEntityEvent &__eeInput); + BOOL H0x015a0017_Fire_08(const CEntityEvent &__eeInput); + BOOL H0x015a0018_Fire_09(const CEntityEvent &__eeInput); + BOOL H0x015a0019_Fire_10(const CEntityEvent &__eeInput); + BOOL H0x015a001a_Fire_11(const CEntityEvent &__eeInput); + BOOL H0x015a001b_Fire_12(const CEntityEvent &__eeInput); + BOOL H0x015a001c_Fire_13(const CEntityEvent &__eeInput); + BOOL H0x015a001d_Fire_14(const CEntityEvent &__eeInput); +#define STATE_CExotechLarva_Hit 0x015a001e + BOOL +#line 1194 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Hit(const CEntityEvent &__eeInput); +#define STATE_CExotechLarva_BeIdle 0x015a001f + BOOL +#line 1198 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BeIdle(const CEntityEvent &__eeInput); + BOOL H0x015a0020_BeIdle_01(const CEntityEvent &__eeInput); + BOOL H0x015a0021_BeIdle_02(const CEntityEvent &__eeInput); + BOOL H0x015a0022_BeIdle_03(const CEntityEvent &__eeInput); + BOOL H0x015a0023_BeIdle_04(const CEntityEvent &__eeInput); + BOOL H0x015a0024_BeIdle_05(const CEntityEvent &__eeInput); + BOOL H0x015a0025_BeIdle_06(const CEntityEvent &__eeInput); +#define STATE_CExotechLarva_LarvaLoop 0x015a0026 + BOOL +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +LarvaLoop(const CEntityEvent &__eeInput); + BOOL H0x015a0027_LarvaLoop_01(const CEntityEvent &__eeInput); + BOOL H0x015a0028_LarvaLoop_02(const CEntityEvent &__eeInput); +#define STATE_CExotechLarva_Main 1 + BOOL +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x015a0029_Main_01(const CEntityEvent &__eeInput); + BOOL H0x015a002a_Main_02(const CEntityEvent &__eeInput); + BOOL H0x015a002b_Main_03(const CEntityEvent &__eeInput); + BOOL H0x015a002c_Main_04(const CEntityEvent &__eeInput); + BOOL H0x015a002d_Main_05(const CEntityEvent &__eeInput); + BOOL H0x015a002e_Main_06(const CEntityEvent &__eeInput); + BOOL H0x015a002f_Main_07(const CEntityEvent &__eeInput); + BOOL H0x015a0030_Main_08(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ExotechLarva_INCLUDED diff --git a/Sources/EntitiesMP/ExotechLarvaBattery.cpp b/Sources/EntitiesMP/ExotechLarvaBattery.cpp new file mode 100644 index 0000000..8375db4 --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarvaBattery.cpp @@ -0,0 +1,337 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/ExotechLarva/Charger/WallCharger.h" + +#include +#include +void CExotechLarvaBattery::SetDefaultProperties(void) { + m_bActive = TRUE ; + m_fMaxHealth = 100.0f; + m_fStretch = 1.0f; + m_fBurnTreshold = 0.0f; + m_penSpray = NULL; + m_tmSpraySpawned = 0.0f; + m_strName = "ExotechLarva Wall Battery"; + m_bCustomShading = FALSE ; + m_aShadingDirection = ANGLE3D(AngleDeg (45.0f) , AngleDeg (45.0f) , AngleDeg (45.0f)); + m_colLight = C_WHITE ; + m_colAmbient = C_BLACK ; + m_soSound.SetOwner(this); +m_soSound.Stop_internal(); + CRationalEntity::SetDefaultProperties(); +} + +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void CExotechLarvaBattery::Precache(void) { +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +CRationalEntity :: Precache (); +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +PrecacheSound (SOUND_SHUTDOWN ); +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +PrecacheModel (MODEL_BATTERY ); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +PrecacheTexture (TEXTURE_BATTERY ); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +PrecacheModel (MODEL_PLASMA ); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +PrecacheTexture (TEXTURE_PLASMA ); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +PrecacheModel (MODEL_ELECTRO ); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +PrecacheTexture (TEXTURE_ELECTRO ); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +BOOL CExotechLarvaBattery::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +{ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +if(m_bCustomShading ) +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +{ +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +colLight = m_colLight ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +colAmbient = m_colAmbient ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +AnglesToDirectionVector (m_aShadingDirection , vLightDirection ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +vLightDirection = - vLightDirection ; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +return TRUE ; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} + +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void CExotechLarvaBattery::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +{ +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +if(GetHealth () < 0.0f){ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +return ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +if((dmtType != DMT_BURNING ) && (m_tmSpraySpawned <= _pTimer -> CurrentTick () - _pTimer -> TickQuantum * 8)) +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +{ +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +CPlacement3D plSpray = CPlacement3D (vHitPoint , ANGLE3D (0 , 0 , 0)); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +m_penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +m_penSpray -> SetParent (this ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +ESpawnSpray eSpawnSpray ; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +eSpawnSpray . fDamagePower = 3.0f; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +eSpawnSpray . sptType = SPT_ELECTRICITY_SPARKS_NO_BLOOD ; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +eSpawnSpray . fSizeMultiplier = 1.0f; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +eSpawnSpray . vDirection = FLOAT3D (0.0f , 1.0f , 0.0f); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +eSpawnSpray . penOwner = this ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +m_penSpray -> Initialize (eSpawnSpray ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +m_tmSpraySpawned = _pTimer -> CurrentTick (); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +FLOAT fLastHealth = GetHealth (); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +CRationalEntity :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +vHitPoint , vDirection ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +FLOAT fNewHealth = GetHealth (); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +if(fNewHealth <= 0.66f * m_fMaxHealth && fLastHealth > 0.66f * m_fMaxHealth ){ +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +RemoveAttachment (WALLCHARGER_ATTACHMENT_LIGHT ); +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +GetModelObject () -> PlayAnim (WALLCHARGER_ANIM_DAMAGE01 , AOF_SMOOTHCHANGE | AOF_NORESTART ); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SpawnExplosions (); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +}else if(fNewHealth <= 0.33 * m_fMaxHealth && fLastHealth > 0.33 * m_fMaxHealth ){ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +RemoveAttachment (WALLCHARGER_ATTACHMENT_PLASMA ); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +GetModelObject () -> PlayAnim (WALLCHARGER_ANIM_DAMAGE02 , AOF_SMOOTHCHANGE | AOF_NORESTART ); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SpawnExplosions (); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void CExotechLarvaBattery::RenderParticles(void) +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +{ +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +FLOAT fBurnStrength ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +FLOAT fHealth = GetHealth (); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +if(fHealth < m_fBurnTreshold ){ +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +fBurnStrength = 1.0f - fHealth / m_fBurnTreshold ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +if(fBurnStrength > 0.99f){fBurnStrength = 0.99f;} +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Particles_Burning (this , 1.0f , fBurnStrength ); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +if(fHealth < 1.0f){ +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Particles_Smoke (this , FLOAT3D (0.0f , 0.0f , 0.25f) * m_fStretch , 100 , 6.0f , 0.4f , 4.0f * m_fStretch , 2.5f); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} + +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void CExotechLarvaBattery::SpawnExplosions(void) { +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +CPlacement3D pl = GetPlacement (); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +ESpawnEffect eSpawnEffect ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +eSpawnEffect . betType = BET_CANNON ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +eSpawnEffect . vStretch = FLOAT3D (m_fStretch * 1.5f , m_fStretch * 1.5f , m_fStretch * 1.5f); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +CEntityPointer penExplosion = CreateEntity (pl , CLASS_BASIC_EFFECT ); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +pl . pl_PositionVector += FLOAT3D (FRnd () * 0.5f , FRnd () * 0.5f , 0.0f); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +penExplosion = CreateEntity (pl , CLASS_BASIC_EFFECT ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +pl . pl_PositionVector += FLOAT3D (FRnd () * 0.5f , FRnd () * 0.5f , 0.0f); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +penExplosion = CreateEntity (pl , CLASS_BASIC_EFFECT ); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +InflictRangeDamage (this , DMT_EXPLOSION , 25.0f , GetPlacement () . pl_PositionVector , 5.0f , 25.0f); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} + +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void CExotechLarvaBattery::AddAttachments(void) { +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +AddAttachmentToModel (this , * GetModelObject () , WALLCHARGER_ATTACHMENT_LIGHT , MODEL_BEAM , TEXTURE_BEAM , 0 , 0 , 0); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +AddAttachmentToModel (this , * GetModelObject () , WALLCHARGER_ATTACHMENT_PLASMA , MODEL_PLASMA , TEXTURE_PLASMA , 0 , 0 , 0); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +AddAttachmentToModel (this , * GetModelObject () , WALLCHARGER_ATTACHMENT_ELECTRICITY , MODEL_ELECTRO , TEXTURE_ELECTRO , 0 , 0 , 0); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +AddAttachmentToModel (this , * GetModelObject () , WALLCHARGER_ATTACHMENT_ELECTRICITY2 , MODEL_ELECTRO , TEXTURE_ELECTRO , 0 , 0 , 0); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void CExotechLarvaBattery::RemoveAttachment(INDEX iAtt) { +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +RemoveAttachmentFromModel (* GetModelObject () , iAtt ); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +} +BOOL CExotechLarvaBattery:: +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Destroyed(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarvaBattery_Destroyed + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CExotechLarvaBattery::Destroyed expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +m_bActive = FALSE ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +RemoveAttachment (WALLCHARGER_ATTACHMENT_ELECTRICITY ); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +RemoveAttachment (WALLCHARGER_ATTACHMENT_ELECTRICITY2 ); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +PlaySound (m_soSound , SOUND_SHUTDOWN , SOF_3D ); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +GetModelObject () -> PlayAnim (WALLCHARGER_ANIM_DAMAGE03 , AOF_SMOOTHCHANGE | AOF_NORESTART ); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SpawnExplosions (); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Jump(STATE_CURRENT,0x015f0003, FALSE, EInternal());return TRUE;}BOOL CExotechLarvaBattery::H0x015f0003_Destroyed_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0003 +if(!(TRUE )){ Jump(STATE_CURRENT,0x015f0004, FALSE, EInternal());return TRUE;} +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SetTimerAfter(1.0f); +Jump(STATE_CURRENT, 0x015f0001, FALSE, EBegin());return TRUE;}BOOL CExotechLarvaBattery::H0x015f0001_Destroyed_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015f0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarvaBattery::H0x015f0002_Destroyed_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0002 +;Jump(STATE_CURRENT,0x015f0003, FALSE, EInternal());return TRUE; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +}BOOL CExotechLarvaBattery::H0x015f0004_Destroyed_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0004 + +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Return(STATE_CURRENT,EVoid()); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CExotechLarvaBattery:: +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarvaBattery_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CExotechLarvaBattery::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +InitAsModel (); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SetPhysicsFlags (EPF_MODEL_FIXED ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SetCollisionFlags (ECF_MODEL ); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SetModel (MODEL_BATTERY ); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SetModelMainTexture (TEXTURE_BATTERY ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +AddAttachments (); +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fStretch , m_fStretch , m_fStretch )); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +ModelChangeNotify (); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SetHealth (m_fMaxHealth ); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x015f0005, FALSE, EBegin());return TRUE;}BOOL CExotechLarvaBattery::H0x015f0005_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015f0006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarvaBattery::H0x015f0006_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0006 +; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +m_soSound . Set3DParameters (100.0f , 50.0f , 3.5f , 1.0f); +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +m_bActive = TRUE ; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +m_fBurnTreshold = 0.66f * m_fMaxHealth ; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +StartModelAnim (WALLCHARGER_ANIM_DEFAULT , 0); +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x015f0007, FALSE, EBegin());return TRUE;}BOOL CExotechLarvaBattery::H0x015f0007_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0007 +switch(__eeInput.ee_slEvent) +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +return TRUE; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Jump(STATE_CURRENT, STATE_CExotechLarvaBattery_Destroyed, TRUE, EVoid());return TRUE; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +}return TRUE;}BOOL CExotechLarvaBattery::H0x015f0008_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0008 + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Return(STATE_CURRENT,EVoid()); +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ExotechLarvaBattery.es b/Sources/EntitiesMP/ExotechLarvaBattery.es new file mode 100644 index 0000000..34bb55a --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarvaBattery.es @@ -0,0 +1,221 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +351 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/ExotechLarva/Charger/WallCharger.h" +%} + +uses "EntitiesMP/BloodSpray"; +uses "EntitiesMP/Projectile"; + +class CExotechLarvaBattery : CRationalEntity { +name "ExotechLarvaBattery"; +thumbnail "Thumbnails\\ExotechLarvaBattery.tbn"; +features "HasName", "IsTargetable"; + +properties: + + 1 BOOL m_bActive = TRUE, + 2 FLOAT m_fMaxHealth "Health" 'H' = 100.0f, + 3 FLOAT m_fStretch "Stretch" 'S' = 1.0f, + 4 FLOAT m_fBurnTreshold = 0.0f, + 5 CEntityPointer m_penSpray, // debris spray + 6 FLOAT m_tmSpraySpawned = 0.0f, + 7 CTString m_strName "Name" 'N' = "ExotechLarva Wall Battery", + + 10 BOOL m_bCustomShading "Custom Shading" = FALSE, + 11 ANGLE3D m_aShadingDirection "Light direction" 'D' = ANGLE3D( AngleDeg(45.0f),AngleDeg(45.0f),AngleDeg(45.0f)), + 12 COLOR m_colLight "Light Color" = C_WHITE, + 13 COLOR m_colAmbient "Ambient Light Color" = C_BLACK, + + 20 CSoundObject m_soSound, + +components: + + 1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 2 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + + 5 model MODEL_BATTERY "ModelsMP\\Enemies\\ExotechLarva\\Charger\\WallCharger.mdl", + 6 texture TEXTURE_BATTERY "ModelsMP\\Enemies\\ExotechLarva\\Charger\\WallCharger.tex", + + 7 model MODEL_BEAM "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Beam.mdl", + 8 texture TEXTURE_BEAM "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Beam.tex", + + 10 model MODEL_PLASMA "ModelsMP\\Enemies\\ExotechLarva\\Charger\\PlasmaBeam.mdl", + 11 texture TEXTURE_PLASMA "ModelsMP\\Effects\\Laser\\Laser_Red.tex", + + 12 model MODEL_ELECTRO "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Electricity.mdl", + 13 texture TEXTURE_ELECTRO "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\Projectile.tex", + + 50 sound SOUND_SHUTDOWN "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Sounds\\WallChargerShutdown.wav", + +functions: + + void Precache(void) { + CRationalEntity::Precache(); + PrecacheSound( SOUND_SHUTDOWN ); + PrecacheModel( MODEL_BATTERY ); + PrecacheTexture( TEXTURE_BATTERY ); + PrecacheModel( MODEL_PLASMA ); + PrecacheTexture( TEXTURE_PLASMA ); + PrecacheModel( MODEL_ELECTRO ); + PrecacheTexture( TEXTURE_ELECTRO ); + } + + + /* Adjust model shading parameters if needed. */ + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + if (m_bCustomShading) + { + colLight = m_colLight; + colAmbient = m_colAmbient; + + AnglesToDirectionVector(m_aShadingDirection, vLightDirection); + vLightDirection = -vLightDirection; + } + + return TRUE; + }; + + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + if (GetHealth()<0.0f) { + return; + } + + if((dmtType!=DMT_BURNING) && (m_tmSpraySpawned<=_pTimer->CurrentTick()-_pTimer->TickQuantum*8)) + { + // spawn blood spray + CPlacement3D plSpray = CPlacement3D( vHitPoint, ANGLE3D(0, 0, 0)); + m_penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + m_penSpray->SetParent(this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 3.0f; + eSpawnSpray.sptType = SPT_ELECTRICITY_SPARKS_NO_BLOOD; + eSpawnSpray.fSizeMultiplier = 1.0f; + eSpawnSpray.vDirection = FLOAT3D(0.0f, 1.0f, 0.0f); + eSpawnSpray.penOwner = this; + m_penSpray->Initialize( eSpawnSpray); + + m_tmSpraySpawned = _pTimer->CurrentTick(); + } + + FLOAT fLastHealth = GetHealth(); + CRationalEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, + vHitPoint, vDirection); + FLOAT fNewHealth = GetHealth(); + if (fNewHealth<=0.66f*m_fMaxHealth && fLastHealth>0.66f*m_fMaxHealth) { + RemoveAttachment(WALLCHARGER_ATTACHMENT_LIGHT); + GetModelObject()->PlayAnim(WALLCHARGER_ANIM_DAMAGE01, AOF_SMOOTHCHANGE|AOF_NORESTART); + SpawnExplosions(); + } else if (fNewHealth<=0.33*m_fMaxHealth && fLastHealth>0.33*m_fMaxHealth) { + RemoveAttachment(WALLCHARGER_ATTACHMENT_PLASMA); + GetModelObject()->PlayAnim(WALLCHARGER_ANIM_DAMAGE02, AOF_SMOOTHCHANGE|AOF_NORESTART); + SpawnExplosions(); + } + }; + + void RenderParticles(void) + { + FLOAT fBurnStrength; + FLOAT fHealth = GetHealth(); + if (fHealth0.99f) { fBurnStrength=0.99f; } + Particles_Burning(this, 1.0f, fBurnStrength); + } + if (fHealth<1.0f) { + Particles_Smoke(this, FLOAT3D(0.0f, 0.0f, 0.25f)*m_fStretch, 100, 6.0f, 0.4f, 4.0f*m_fStretch, 2.5f); + } + }; + + void SpawnExplosions(void) { + CPlacement3D pl = GetPlacement(); + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNON; + eSpawnEffect.vStretch = FLOAT3D(m_fStretch*1.5f, m_fStretch*1.5f, m_fStretch*1.5f); + CEntityPointer penExplosion = CreateEntity(pl, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + pl.pl_PositionVector += FLOAT3D(FRnd()*0.5f, FRnd()*0.5f, 0.0f); + penExplosion = CreateEntity(pl, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + pl.pl_PositionVector += FLOAT3D(FRnd()*0.5f, FRnd()*0.5f, 0.0f); + penExplosion = CreateEntity(pl, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + InflictRangeDamage( this, DMT_EXPLOSION, 25.0f, GetPlacement().pl_PositionVector, 5.0f, 25.0f); + } + + void AddAttachments(void) { + AddAttachmentToModel(this, *GetModelObject(), WALLCHARGER_ATTACHMENT_LIGHT, MODEL_BEAM, TEXTURE_BEAM, 0, 0, 0); + AddAttachmentToModel(this, *GetModelObject(), WALLCHARGER_ATTACHMENT_PLASMA, MODEL_PLASMA, TEXTURE_PLASMA, 0, 0, 0); + AddAttachmentToModel(this, *GetModelObject(), WALLCHARGER_ATTACHMENT_ELECTRICITY, MODEL_ELECTRO, TEXTURE_ELECTRO, 0, 0, 0); + AddAttachmentToModel(this, *GetModelObject(), WALLCHARGER_ATTACHMENT_ELECTRICITY2, MODEL_ELECTRO, TEXTURE_ELECTRO, 0, 0, 0); + } + + void RemoveAttachment(INDEX iAtt) { + RemoveAttachmentFromModel(*GetModelObject(), iAtt); + } + +procedures: + Destroyed() + { + m_bActive = FALSE; + + RemoveAttachment(WALLCHARGER_ATTACHMENT_ELECTRICITY); + RemoveAttachment(WALLCHARGER_ATTACHMENT_ELECTRICITY2); + PlaySound(m_soSound, SOUND_SHUTDOWN, SOF_3D); + GetModelObject()->PlayAnim(WALLCHARGER_ANIM_DAMAGE03, AOF_SMOOTHCHANGE|AOF_NORESTART); + SpawnExplosions(); + + //wait forever + while (TRUE) { + autowait(1.0f); + } + return; + } + + Main() + { + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_FIXED); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + + // set your appearance + SetModel(MODEL_BATTERY); + SetModelMainTexture(TEXTURE_BATTERY); + + AddAttachments(); + + // set stretch factors for height and width + GetModelObject()->StretchModel(FLOAT3D(m_fStretch, m_fStretch, m_fStretch)); + ModelChangeNotify(); + + SetHealth(m_fMaxHealth); + + autowait(0.05f); + + m_soSound.Set3DParameters(100.0f, 50.0f, 3.5f, 1.0f); + m_bActive = TRUE; + m_fBurnTreshold = 0.66f*m_fMaxHealth; + + StartModelAnim(WALLCHARGER_ANIM_DEFAULT, 0); + + wait() + { + on (EBegin) : { + resume; + } + on (EDeath eDeath) : { + jump Destroyed(); + } + } + + return; + } +}; diff --git a/Sources/EntitiesMP/ExotechLarvaBattery.h b/Sources/EntitiesMP/ExotechLarvaBattery.h new file mode 100644 index 0000000..b68e4da --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarvaBattery.h @@ -0,0 +1,67 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ExotechLarvaBattery_INCLUDED +#define _EntitiesMP_ExotechLarvaBattery_INCLUDED 1 +#include +#include +extern "C" DECL_DLL CDLLEntityClass CExotechLarvaBattery_DLLClass; +class CExotechLarvaBattery : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bActive; + FLOAT m_fMaxHealth; + FLOAT m_fStretch; + FLOAT m_fBurnTreshold; + CEntityPointer m_penSpray; + FLOAT m_tmSpraySpawned; + CTString m_strName; + BOOL m_bCustomShading; + ANGLE3D m_aShadingDirection; + COLOR m_colLight; + COLOR m_colAmbient; + CSoundObject m_soSound; + +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void Precache(void); + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void RenderParticles(void); + +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void SpawnExplosions(void); + +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void AddAttachments(void); + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +void RemoveAttachment(INDEX iAtt); +#define STATE_CExotechLarvaBattery_Destroyed 0x015f0000 + BOOL +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Destroyed(const CEntityEvent &__eeInput); + BOOL H0x015f0001_Destroyed_01(const CEntityEvent &__eeInput); + BOOL H0x015f0002_Destroyed_02(const CEntityEvent &__eeInput); + BOOL H0x015f0003_Destroyed_03(const CEntityEvent &__eeInput); + BOOL H0x015f0004_Destroyed_04(const CEntityEvent &__eeInput); +#define STATE_CExotechLarvaBattery_Main 1 + BOOL +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x015f0005_Main_01(const CEntityEvent &__eeInput); + BOOL H0x015f0006_Main_02(const CEntityEvent &__eeInput); + BOOL H0x015f0007_Main_03(const CEntityEvent &__eeInput); + BOOL H0x015f0008_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ExotechLarvaBattery_INCLUDED diff --git a/Sources/EntitiesMP/ExotechLarvaBattery_tables.h b/Sources/EntitiesMP/ExotechLarvaBattery_tables.h new file mode 100644 index 0000000..6d8b463 --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarvaBattery_tables.h @@ -0,0 +1,76 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CExotechLarvaBattery + +CEntityProperty CExotechLarvaBattery_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015f<<8)+1, offsetof(CExotechLarvaBattery, m_bActive), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015f<<8)+2, offsetof(CExotechLarvaBattery, m_fMaxHealth), "Health", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015f<<8)+3, offsetof(CExotechLarvaBattery, m_fStretch), "Stretch", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015f<<8)+4, offsetof(CExotechLarvaBattery, m_fBurnTreshold), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015f<<8)+5, offsetof(CExotechLarvaBattery, m_penSpray), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015f<<8)+6, offsetof(CExotechLarvaBattery, m_tmSpraySpawned), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x0000015f<<8)+7, offsetof(CExotechLarvaBattery, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015f<<8)+10, offsetof(CExotechLarvaBattery, m_bCustomShading), "Custom Shading", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x0000015f<<8)+11, offsetof(CExotechLarvaBattery, m_aShadingDirection), "Light direction", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000015f<<8)+12, offsetof(CExotechLarvaBattery, m_colLight), "Light Color", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000015f<<8)+13, offsetof(CExotechLarvaBattery, m_colAmbient), "Ambient Light Color", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015f<<8)+20, offsetof(CExotechLarvaBattery, m_soSound), "", 0, 0, 0), +}; +#define CExotechLarvaBattery_propertiesct ARRAYCOUNT(CExotechLarvaBattery_properties) + +CEntityComponent CExotechLarvaBattery_components[] = { +#define CLASS_BASIC_EFFECT ((0x0000015f<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_BLOOD_SPRAY ((0x0000015f<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define MODEL_BATTERY ((0x0000015f<<8)+5) + CEntityComponent(ECT_MODEL, MODEL_BATTERY, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\WallCharger.mdl"), +#define TEXTURE_BATTERY ((0x0000015f<<8)+6) + CEntityComponent(ECT_TEXTURE, TEXTURE_BATTERY, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\WallCharger.tex"), +#define MODEL_BEAM ((0x0000015f<<8)+7) + CEntityComponent(ECT_MODEL, MODEL_BEAM, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Beam.mdl"), +#define TEXTURE_BEAM ((0x0000015f<<8)+8) + CEntityComponent(ECT_TEXTURE, TEXTURE_BEAM, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Beam.tex"), +#define MODEL_PLASMA ((0x0000015f<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_PLASMA, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\PlasmaBeam.mdl"), +#define TEXTURE_PLASMA ((0x0000015f<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_PLASMA, "EFNM" "ModelsMP\\Effects\\Laser\\Laser_Red.tex"), +#define MODEL_ELECTRO ((0x0000015f<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_ELECTRO, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Electricity.mdl"), +#define TEXTURE_ELECTRO ((0x0000015f<<8)+13) + CEntityComponent(ECT_TEXTURE, TEXTURE_ELECTRO, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\Projectile.tex"), +#define SOUND_SHUTDOWN ((0x0000015f<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_SHUTDOWN, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Sounds\\WallChargerShutdown.wav"), +}; +#define CExotechLarvaBattery_componentsct ARRAYCOUNT(CExotechLarvaBattery_components) + +CEventHandlerEntry CExotechLarvaBattery_handlers[] = { + {0x015f0000, -1, CEntity::pEventHandler(&CExotechLarvaBattery:: +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Destroyed),DEBUGSTRING("CExotechLarvaBattery::Destroyed")}, + {0x015f0001, -1, CEntity::pEventHandler(&CExotechLarvaBattery::H0x015f0001_Destroyed_01), DEBUGSTRING("CExotechLarvaBattery::H0x015f0001_Destroyed_01")}, + {0x015f0002, -1, CEntity::pEventHandler(&CExotechLarvaBattery::H0x015f0002_Destroyed_02), DEBUGSTRING("CExotechLarvaBattery::H0x015f0002_Destroyed_02")}, + {0x015f0003, -1, CEntity::pEventHandler(&CExotechLarvaBattery::H0x015f0003_Destroyed_03), DEBUGSTRING("CExotechLarvaBattery::H0x015f0003_Destroyed_03")}, + {0x015f0004, -1, CEntity::pEventHandler(&CExotechLarvaBattery::H0x015f0004_Destroyed_04), DEBUGSTRING("CExotechLarvaBattery::H0x015f0004_Destroyed_04")}, + {1, -1, CEntity::pEventHandler(&CExotechLarvaBattery:: +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaBattery.es" +Main),DEBUGSTRING("CExotechLarvaBattery::Main")}, + {0x015f0005, -1, CEntity::pEventHandler(&CExotechLarvaBattery::H0x015f0005_Main_01), DEBUGSTRING("CExotechLarvaBattery::H0x015f0005_Main_01")}, + {0x015f0006, -1, CEntity::pEventHandler(&CExotechLarvaBattery::H0x015f0006_Main_02), DEBUGSTRING("CExotechLarvaBattery::H0x015f0006_Main_02")}, + {0x015f0007, -1, CEntity::pEventHandler(&CExotechLarvaBattery::H0x015f0007_Main_03), DEBUGSTRING("CExotechLarvaBattery::H0x015f0007_Main_03")}, + {0x015f0008, -1, CEntity::pEventHandler(&CExotechLarvaBattery::H0x015f0008_Main_04), DEBUGSTRING("CExotechLarvaBattery::H0x015f0008_Main_04")}, +}; +#define CExotechLarvaBattery_handlersct ARRAYCOUNT(CExotechLarvaBattery_handlers) + +CEntity *CExotechLarvaBattery_New(void) { return new CExotechLarvaBattery; }; +void CExotechLarvaBattery_OnInitClass(void) {}; +void CExotechLarvaBattery_OnEndClass(void) {}; +void CExotechLarvaBattery_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CExotechLarvaBattery_OnWorldEnd(CWorld *pwo) {}; +void CExotechLarvaBattery_OnWorldInit(CWorld *pwo) {}; +void CExotechLarvaBattery_OnWorldTick(CWorld *pwo) {}; +void CExotechLarvaBattery_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CExotechLarvaBattery, CRationalEntity, "ExotechLarvaBattery", "Thumbnails\\ExotechLarvaBattery.tbn", 0x0000015f); +DECLARE_CTFILENAME(_fnmCExotechLarvaBattery_tbn, "Thumbnails\\ExotechLarvaBattery.tbn"); diff --git a/Sources/EntitiesMP/ExotechLarvaCharger.cpp b/Sources/EntitiesMP/ExotechLarvaCharger.cpp new file mode 100644 index 0000000..fba6fe9 --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarvaCharger.cpp @@ -0,0 +1,350 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/ExotechLarva/Charger/FloorCharger.h" + +#include +#include +CEntityEvent *EActivateBeam::MakeCopy(void) { CEntityEvent *peeCopy = new EActivateBeam(*this); return peeCopy;} +EActivateBeam::EActivateBeam() : CEntityEvent(EVENTCODE_EActivateBeam) {; + ClearToDefault(bTurnOn); +}; +void CExotechLarvaCharger::SetDefaultProperties(void) { + m_bActive = TRUE ; + m_bBeamActive = FALSE ; + m_fStretch = 1.0f; + m_strName = "ExotechLarva Floor Charger"; + m_rSound = 100.0f; + m_penBattery01 = NULL; + m_penBattery02 = NULL; + m_penBattery03 = NULL; + m_penBattery04 = NULL; + m_penBattery05 = NULL; + m_penBattery06 = NULL; + m_bCustomShading = FALSE ; + m_aShadingDirection = ANGLE3D(AngleDeg (45.0f) , AngleDeg (45.0f) , AngleDeg (45.0f)); + m_colLight = C_WHITE ; + m_colAmbient = C_BLACK ; + m_soSound.SetOwner(this); +m_soSound.Stop_internal(); + CRationalEntity::SetDefaultProperties(); +} + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +BOOL CExotechLarvaCharger::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +{ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +if(slPropertyOffset == offsetof (CExotechLarvaCharger , m_penBattery01 ) || +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +slPropertyOffset == offsetof (CExotechLarvaCharger , m_penBattery02 ) || +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +slPropertyOffset == offsetof (CExotechLarvaCharger , m_penBattery03 ) || +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +slPropertyOffset == offsetof (CExotechLarvaCharger , m_penBattery04 ) || +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +slPropertyOffset == offsetof (CExotechLarvaCharger , m_penBattery05 ) || +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +slPropertyOffset == offsetof (CExotechLarvaCharger , m_penBattery06 )) +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +{ +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +if(IsOfClass (penTarget , "ExotechLarvaBattery")){return TRUE ;} +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +else {return FALSE ;} +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +return CEntity :: IsTargetValid (slPropertyOffset , penTarget ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +void CExotechLarvaCharger::Precache(void) { +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +CRationalEntity :: Precache (); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +PrecacheModel (MODEL_ELECTRICITY ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +PrecacheTexture (TEXTURE_ELECTRICITY ); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +PrecacheModel (MODEL_BEAM ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +PrecacheTexture (TEXTURE_BEAM ); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +PrecacheSound (SOUND_HUM ); +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +PrecacheSound (SOUND_SHUTDOWN ); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} + +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +BOOL CExotechLarvaCharger::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +{ +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +if(m_bCustomShading ) +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +{ +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +colLight = m_colLight ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +colAmbient = m_colAmbient ; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +AnglesToDirectionVector (m_aShadingDirection , vLightDirection ); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +vLightDirection = - vLightDirection ; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +return TRUE ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} + +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +void CExotechLarvaCharger::UpdateOperationalState(void) { +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +CEntityPointer * penFirst = & m_penBattery01 ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +for(INDEX i = 0;i < 6;i ++){ +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +CExotechLarvaBattery * penBattery = (CExotechLarvaBattery *) & (* penFirst [ i ]); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +if(penBattery ){ +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +if(penBattery -> m_bActive ){ +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +m_bActive = TRUE ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +return ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +m_bActive = FALSE ; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +EActivateBeam eab ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +eab . bTurnOn = FALSE ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +SendEvent (eab ); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +PlaySound (m_soSound , SOUND_SHUTDOWN , SOF_3D ); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +RemoveAttachmentFromModel (* GetModelObject () , FLOORCHARGER_ATTACHMENT_ELECTRICITY ); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} + +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +void CExotechLarvaCharger::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +{ +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +NOTHING ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} + +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +void CExotechLarvaCharger::RenderParticles(void) +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +{ +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +if(m_bBeamActive ) +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +{ +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +CEntityPointer * penFirst = & m_penBattery01 ; +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +for(INDEX i = 0;i < 6;i ++){ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +CExotechLarvaBattery * penBattery = (CExotechLarvaBattery *) & (* penFirst [ i ]); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +if(penBattery ){ +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +if(penBattery -> m_bActive ){ +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +FLOAT tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +Particles_Ghostbuster (GetPlacement () . pl_PositionVector + FLOAT3D (0.0f , 0.2f , 0.0f) , +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +penBattery -> GetPlacement () . pl_PositionVector + FLOAT3D (0.0f , 0.2f , 0.0f) , +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +32 , 1.0f); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +Particles_ModelGlow (penBattery , 1e6 , PT_STAR05 , 1.0f + 0.5f * sin (4.0f * tmNow ) , 4 , 0.0f , C_WHITE ); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +BOOL CExotechLarvaCharger:: +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +ActivateBeam(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarvaCharger_ActivateBeam + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CExotechLarvaCharger::ActivateBeam expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +AddAttachmentToModel (this , * GetModelObject () , FLOORCHARGER_ATTACHMENT_BEAM , MODEL_BEAM , TEXTURE_BEAM , 0 , 0 , 0); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +CModelObject & amo = GetModelObject () -> GetAttachmentModel (FLOORCHARGER_ATTACHMENT_BEAM ) -> amo_moModelObject ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +amo . StretchModelRelative (FLOAT3D (m_fStretch , m_fStretch , m_fStretch )); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +m_bBeamActive = TRUE ; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +Return(STATE_CURRENT,EVoid()); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CExotechLarvaCharger:: +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +DeactivateBeam(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarvaCharger_DeactivateBeam + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CExotechLarvaCharger::DeactivateBeam expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +RemoveAttachmentFromModel (* GetModelObject () , FLOORCHARGER_ATTACHMENT_BEAM ); +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +m_bBeamActive = FALSE ; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +Return(STATE_CURRENT,EVoid()); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CExotechLarvaCharger:: +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CExotechLarvaCharger_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CExotechLarvaCharger::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +InitAsModel (); +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +SetPhysicsFlags (EPF_MODEL_FIXED ); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +SetModel (MODEL_CHARGER ); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +SetModelMainTexture (TEXTURE_CHARGER ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fStretch , m_fStretch , m_fStretch )); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +ModelChangeNotify (); +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x015f0003, FALSE, EBegin());return TRUE;}BOOL CExotechLarvaCharger::H0x015f0003_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015f0004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CExotechLarvaCharger::H0x015f0004_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0004 +; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +m_soSound . Set3DParameters (m_rSound , m_rSound / 2.0f , 2.0f , 1.0f); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +m_bActive = FALSE ; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +m_bBeamActive = FALSE ; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x015f0005, FALSE, EBegin());return TRUE;}BOOL CExotechLarvaCharger::H0x015f0005_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0005 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x015f0006, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +}return TRUE;}BOOL CExotechLarvaCharger::H0x015f0006_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0006 + +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +UpdateOperationalState (); +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +if(m_bActive ){ +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +AddAttachmentToModel (this , * GetModelObject () , FLOORCHARGER_ATTACHMENT_ELECTRICITY , MODEL_ELECTRICITY , TEXTURE_ELECTRICITY , 0 , 0 , 0); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +CAttachmentModelObject * amo = GetModelObject () -> GetAttachmentModel (FLOORCHARGER_ATTACHMENT_ELECTRICITY ); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +amo -> amo_moModelObject . StretchModel (FLOAT3D (m_fStretch , m_fStretch , m_fStretch )); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +PlaySound (m_soSound , SOUND_HUM , SOF_3D | SOF_LOOP ); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +Jump(STATE_CURRENT,0x015f0009, FALSE, EInternal());return TRUE;}BOOL CExotechLarvaCharger::H0x015f0009_Main_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0009 +if(!(TRUE )){ Jump(STATE_CURRENT,0x015f000a, FALSE, EInternal());return TRUE;} +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x015f0007, FALSE, EBegin());return TRUE;}BOOL CExotechLarvaCharger::H0x015f0007_Main_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0007 +switch(__eeInput.ee_slEvent) +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +return TRUE; +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; + +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +if(m_bActive ){ +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +UpdateOperationalState (); +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +UnsetTimer();Jump(STATE_CURRENT,0x015f0008, FALSE, EInternal());return TRUE; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +}ASSERT(FALSE);break;case(EVENTCODE_EActivateBeam):{const EActivateBeam&eab= (EActivateBeam&)__eeInput; + +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +if(eab . bTurnOn == TRUE && m_bBeamActive != TRUE ){ +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +Call(STATE_CURRENT, STATE_CExotechLarvaCharger_ActivateBeam, TRUE, EVoid());return TRUE; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +}else if(eab . bTurnOn == FALSE && m_bBeamActive != FALSE ){ +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +Call(STATE_CURRENT, STATE_CExotechLarvaCharger_DeactivateBeam, TRUE, EVoid());return TRUE; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +} +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +return TRUE; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +}return TRUE;}BOOL CExotechLarvaCharger::H0x015f0008_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f0008 +Jump(STATE_CURRENT,0x015f0009, FALSE, EInternal());return TRUE; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +}BOOL CExotechLarvaCharger::H0x015f000a_Main_08(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015f000a + +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +Return(STATE_CURRENT,EVoid()); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ExotechLarvaCharger.es b/Sources/EntitiesMP/ExotechLarvaCharger.es new file mode 100644 index 0000000..3a0f3de --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarvaCharger.es @@ -0,0 +1,242 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +351 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/ExotechLarva/Charger/FloorCharger.h" +%} + +uses "EntitiesMP/BloodSpray"; +uses "EntitiesMP/Projectile"; +uses "EntitiesMP/ExotechLarvaBattery"; + +event EActivateBeam { + BOOL bTurnOn, +}; + +class CExotechLarvaCharger : CRationalEntity { +name "ExotechLarvaCharger"; +thumbnail "Thumbnails\\ExotechLarvaCharger.tbn"; +features "HasName", "IsTargetable"; + +properties: + + 1 BOOL m_bActive = TRUE, + 2 BOOL m_bBeamActive = FALSE, + 3 FLOAT m_fStretch "Stretch" 'S' = 1.0f, + 7 CTString m_strName "Name" 'N' = "ExotechLarva Floor Charger", + 8 RANGE m_rSound "Sound Range" = 100.0f, + + 10 CEntityPointer m_penBattery01 "Wall Battery 01", + 11 CEntityPointer m_penBattery02 "Wall Battery 02", + 12 CEntityPointer m_penBattery03 "Wall Battery 03", + 13 CEntityPointer m_penBattery04 "Wall Battery 04", + 14 CEntityPointer m_penBattery05 "Wall Battery 05", + 15 CEntityPointer m_penBattery06 "Wall Battery 06", + + 20 BOOL m_bCustomShading "Custom Shading" = FALSE, + 21 ANGLE3D m_aShadingDirection "Light direction" 'D' = ANGLE3D( AngleDeg(45.0f),AngleDeg(45.0f),AngleDeg(45.0f)), + 22 COLOR m_colLight "Light Color" = C_WHITE, + 23 COLOR m_colAmbient "Ambient Light Color" = C_BLACK, + + 50 CSoundObject m_soSound, + +components: + + 1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 2 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + + 5 model MODEL_CHARGER "ModelsMP\\Enemies\\ExotechLarva\\Charger\\FloorCharger.mdl", + 6 texture TEXTURE_CHARGER "ModelsMP\\Enemies\\ExotechLarva\\Charger\\FloorCharger.tex", + + 7 model MODEL_BEAM "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Beam.mdl", + 8 texture TEXTURE_BEAM "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Beam.tex", + + 9 model MODEL_ELECTRICITY "ModelsMP\\Enemies\\ExotechLarva\\Charger\\ElectricityBeams.mdl", + 10 texture TEXTURE_ELECTRICITY "ModelsMP\\Effects\\Laser\\Laser_Red.tex", + + 50 sound SOUND_HUM "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Sounds\\FloorChargerHum.wav", + 51 sound SOUND_SHUTDOWN "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Sounds\\FloorChargerShutdown.wav", + +functions: + + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if( slPropertyOffset == offsetof(CExotechLarvaCharger, m_penBattery01) || + slPropertyOffset == offsetof(CExotechLarvaCharger, m_penBattery02) || + slPropertyOffset == offsetof(CExotechLarvaCharger, m_penBattery03) || + slPropertyOffset == offsetof(CExotechLarvaCharger, m_penBattery04) || + slPropertyOffset == offsetof(CExotechLarvaCharger, m_penBattery05) || + slPropertyOffset == offsetof(CExotechLarvaCharger, m_penBattery06)) + { + if (IsOfClass(penTarget, "ExotechLarvaBattery")) { return TRUE; } + else { return FALSE; } + } + return CEntity::IsTargetValid(slPropertyOffset, penTarget); + } + + void Precache(void) { + CRationalEntity::Precache(); + + PrecacheModel (MODEL_ELECTRICITY ); + PrecacheTexture (TEXTURE_ELECTRICITY ); + PrecacheModel (MODEL_BEAM ); + PrecacheTexture (TEXTURE_BEAM ); + + PrecacheSound (SOUND_HUM ); + PrecacheSound (SOUND_SHUTDOWN ); + } + + + /* Adjust model shading parameters if needed. */ + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + if (m_bCustomShading) + { + colLight = m_colLight; + colAmbient = m_colAmbient; + + AnglesToDirectionVector(m_aShadingDirection, vLightDirection); + vLightDirection = -vLightDirection; + } + + return TRUE; + }; + + + void UpdateOperationalState(void) { + + CEntityPointer *penFirst = &m_penBattery01; + + for (INDEX i=0; i<6; i++) { + CExotechLarvaBattery *penBattery = (CExotechLarvaBattery *)&(*penFirst[i]); + // if model pointer is valid + if (penBattery) { + if (penBattery->m_bActive) { + // at least one exists, so we are still active + m_bActive = TRUE; + return; + } + } + } + // if no batteries found, change the state to inactive + m_bActive = FALSE; + EActivateBeam eab; + eab.bTurnOn = FALSE; + SendEvent(eab); + + PlaySound(m_soSound, SOUND_SHUTDOWN, SOF_3D); + + RemoveAttachmentFromModel(*GetModelObject(), FLOORCHARGER_ATTACHMENT_ELECTRICITY); + } + + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + NOTHING; + }; + + void RenderParticles(void) + { + if (m_bBeamActive) + { + CEntityPointer *penFirst = &m_penBattery01; + + for (INDEX i=0; i<6; i++) { + CExotechLarvaBattery *penBattery = (CExotechLarvaBattery *)&(*penFirst[i]); + // if model pointer is valid + if (penBattery) { + if (penBattery->m_bActive) { + // render electricity + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + Particles_Ghostbuster(GetPlacement().pl_PositionVector + FLOAT3D(0.0f, 0.2f, 0.0f), + penBattery->GetPlacement().pl_PositionVector + FLOAT3D(0.0f, 0.2f, 0.0f), + 32, 1.0f); + Particles_ModelGlow(penBattery, 1e6, PT_STAR05, 1.0f+0.5f*sin(4.0f*tmNow), 4, 0.0f, C_WHITE); + } + } + } + + } + }; + +procedures: + + ActivateBeam() + { + AddAttachmentToModel(this, *GetModelObject(), FLOORCHARGER_ATTACHMENT_BEAM, MODEL_BEAM, TEXTURE_BEAM, 0, 0, 0); + CModelObject &amo = GetModelObject()->GetAttachmentModel(FLOORCHARGER_ATTACHMENT_BEAM)->amo_moModelObject; + amo.StretchModelRelative(FLOAT3D(m_fStretch, m_fStretch, m_fStretch)); + m_bBeamActive = TRUE; + return; + } + + DeactivateBeam() + { + RemoveAttachmentFromModel(*GetModelObject(), FLOORCHARGER_ATTACHMENT_BEAM); + m_bBeamActive = FALSE; + return; + } + + Main() + { + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_FIXED); + SetCollisionFlags(ECF_IMMATERIAL); + SetFlags(GetFlags()|ENF_ALIVE); + + // set your appearance + SetModel(MODEL_CHARGER); + SetModelMainTexture(TEXTURE_CHARGER); + + // set stretch factors for height and width + GetModelObject()->StretchModel(FLOAT3D(m_fStretch, m_fStretch, m_fStretch)); + ModelChangeNotify(); + + autowait(0.05f); + + m_soSound.Set3DParameters(m_rSound, m_rSound/2.0f, 2.0f, 1.0f); + m_bActive = FALSE; + m_bBeamActive = FALSE; + + // wait to be triggered + wait() { + on (EBegin) : { resume; } + on (ETrigger) : { stop; } + otherwise (): { resume; } + } + + UpdateOperationalState(); + if (m_bActive) { + AddAttachmentToModel(this, *GetModelObject(), FLOORCHARGER_ATTACHMENT_ELECTRICITY, MODEL_ELECTRICITY, TEXTURE_ELECTRICITY, 0, 0, 0); + CAttachmentModelObject *amo = GetModelObject()->GetAttachmentModel(FLOORCHARGER_ATTACHMENT_ELECTRICITY); + amo->amo_moModelObject.StretchModel(FLOAT3D(m_fStretch, m_fStretch, m_fStretch)); + PlaySound(m_soSound, SOUND_HUM, SOF_3D|SOF_LOOP); + } + + while (TRUE) { + wait(0.5f) + { + on (EBegin) : { + resume; + } + on (ETimer) : { + if (m_bActive) { + UpdateOperationalState(); + } + stop; + } + on (EActivateBeam eab) : { + if (eab.bTurnOn==TRUE && m_bBeamActive!=TRUE) { + call ActivateBeam(); + } else if (eab.bTurnOn==FALSE && m_bBeamActive!=FALSE) { + call DeactivateBeam(); + } + resume; + } + } + } + return; + } + +}; diff --git a/Sources/EntitiesMP/ExotechLarvaCharger.h b/Sources/EntitiesMP/ExotechLarvaCharger.h new file mode 100644 index 0000000..03e0286 --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarvaCharger.h @@ -0,0 +1,81 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ExotechLarvaCharger_INCLUDED +#define _EntitiesMP_ExotechLarvaCharger_INCLUDED 1 +#include +#include +#include +#define EVENTCODE_EActivateBeam 0x015f0000 +class DECL_DLL EActivateBeam : public CEntityEvent { +public: +EActivateBeam(); +CEntityEvent *MakeCopy(void); +BOOL bTurnOn; +}; +DECL_DLL inline void ClearToDefault(EActivateBeam &e) { e = EActivateBeam(); } ; +extern "C" DECL_DLL CDLLEntityClass CExotechLarvaCharger_DLLClass; +class CExotechLarvaCharger : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bActive; + BOOL m_bBeamActive; + FLOAT m_fStretch; + CTString m_strName; + RANGE m_rSound; + CEntityPointer m_penBattery01; + CEntityPointer m_penBattery02; + CEntityPointer m_penBattery03; + CEntityPointer m_penBattery04; + CEntityPointer m_penBattery05; + CEntityPointer m_penBattery06; + BOOL m_bCustomShading; + ANGLE3D m_aShadingDirection; + COLOR m_colLight; + COLOR m_colAmbient; + CSoundObject m_soSound; + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +void Precache(void); + +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +void UpdateOperationalState(void); + +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +void RenderParticles(void); +#define STATE_CExotechLarvaCharger_ActivateBeam 0x015f0001 + BOOL +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +ActivateBeam(const CEntityEvent &__eeInput); +#define STATE_CExotechLarvaCharger_DeactivateBeam 0x015f0002 + BOOL +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +DeactivateBeam(const CEntityEvent &__eeInput); +#define STATE_CExotechLarvaCharger_Main 1 + BOOL +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x015f0003_Main_01(const CEntityEvent &__eeInput); + BOOL H0x015f0004_Main_02(const CEntityEvent &__eeInput); + BOOL H0x015f0005_Main_03(const CEntityEvent &__eeInput); + BOOL H0x015f0006_Main_04(const CEntityEvent &__eeInput); + BOOL H0x015f0007_Main_05(const CEntityEvent &__eeInput); + BOOL H0x015f0008_Main_06(const CEntityEvent &__eeInput); + BOOL H0x015f0009_Main_07(const CEntityEvent &__eeInput); + BOOL H0x015f000a_Main_08(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ExotechLarvaCharger_INCLUDED diff --git a/Sources/EntitiesMP/ExotechLarvaCharger_tables.h b/Sources/EntitiesMP/ExotechLarvaCharger_tables.h new file mode 100644 index 0000000..a638cbd --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarvaCharger_tables.h @@ -0,0 +1,81 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CExotechLarvaCharger + +CEntityProperty CExotechLarvaCharger_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015f<<8)+1, offsetof(CExotechLarvaCharger, m_bActive), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015f<<8)+2, offsetof(CExotechLarvaCharger, m_bBeamActive), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015f<<8)+3, offsetof(CExotechLarvaCharger, m_fStretch), "Stretch", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x0000015f<<8)+7, offsetof(CExotechLarvaCharger, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x0000015f<<8)+8, offsetof(CExotechLarvaCharger, m_rSound), "Sound Range", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015f<<8)+10, offsetof(CExotechLarvaCharger, m_penBattery01), "Wall Battery 01", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015f<<8)+11, offsetof(CExotechLarvaCharger, m_penBattery02), "Wall Battery 02", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015f<<8)+12, offsetof(CExotechLarvaCharger, m_penBattery03), "Wall Battery 03", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015f<<8)+13, offsetof(CExotechLarvaCharger, m_penBattery04), "Wall Battery 04", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015f<<8)+14, offsetof(CExotechLarvaCharger, m_penBattery05), "Wall Battery 05", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015f<<8)+15, offsetof(CExotechLarvaCharger, m_penBattery06), "Wall Battery 06", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015f<<8)+20, offsetof(CExotechLarvaCharger, m_bCustomShading), "Custom Shading", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x0000015f<<8)+21, offsetof(CExotechLarvaCharger, m_aShadingDirection), "Light direction", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000015f<<8)+22, offsetof(CExotechLarvaCharger, m_colLight), "Light Color", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000015f<<8)+23, offsetof(CExotechLarvaCharger, m_colAmbient), "Ambient Light Color", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015f<<8)+50, offsetof(CExotechLarvaCharger, m_soSound), "", 0, 0, 0), +}; +#define CExotechLarvaCharger_propertiesct ARRAYCOUNT(CExotechLarvaCharger_properties) + +CEntityComponent CExotechLarvaCharger_components[] = { +#define CLASS_BASIC_EFFECT ((0x0000015f<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_BLOOD_SPRAY ((0x0000015f<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define MODEL_CHARGER ((0x0000015f<<8)+5) + CEntityComponent(ECT_MODEL, MODEL_CHARGER, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\FloorCharger.mdl"), +#define TEXTURE_CHARGER ((0x0000015f<<8)+6) + CEntityComponent(ECT_TEXTURE, TEXTURE_CHARGER, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\FloorCharger.tex"), +#define MODEL_BEAM ((0x0000015f<<8)+7) + CEntityComponent(ECT_MODEL, MODEL_BEAM, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Beam.mdl"), +#define TEXTURE_BEAM ((0x0000015f<<8)+8) + CEntityComponent(ECT_TEXTURE, TEXTURE_BEAM, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Beam.tex"), +#define MODEL_ELECTRICITY ((0x0000015f<<8)+9) + CEntityComponent(ECT_MODEL, MODEL_ELECTRICITY, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\ElectricityBeams.mdl"), +#define TEXTURE_ELECTRICITY ((0x0000015f<<8)+10) + CEntityComponent(ECT_TEXTURE, TEXTURE_ELECTRICITY, "EFNM" "ModelsMP\\Effects\\Laser\\Laser_Red.tex"), +#define SOUND_HUM ((0x0000015f<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_HUM, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Sounds\\FloorChargerHum.wav"), +#define SOUND_SHUTDOWN ((0x0000015f<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_SHUTDOWN, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Charger\\Sounds\\FloorChargerShutdown.wav"), +}; +#define CExotechLarvaCharger_componentsct ARRAYCOUNT(CExotechLarvaCharger_components) + +CEventHandlerEntry CExotechLarvaCharger_handlers[] = { + {0x015f0001, -1, CEntity::pEventHandler(&CExotechLarvaCharger:: +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +ActivateBeam),DEBUGSTRING("CExotechLarvaCharger::ActivateBeam")}, + {0x015f0002, -1, CEntity::pEventHandler(&CExotechLarvaCharger:: +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +DeactivateBeam),DEBUGSTRING("CExotechLarvaCharger::DeactivateBeam")}, + {1, -1, CEntity::pEventHandler(&CExotechLarvaCharger:: +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarvaCharger.es" +Main),DEBUGSTRING("CExotechLarvaCharger::Main")}, + {0x015f0003, -1, CEntity::pEventHandler(&CExotechLarvaCharger::H0x015f0003_Main_01), DEBUGSTRING("CExotechLarvaCharger::H0x015f0003_Main_01")}, + {0x015f0004, -1, CEntity::pEventHandler(&CExotechLarvaCharger::H0x015f0004_Main_02), DEBUGSTRING("CExotechLarvaCharger::H0x015f0004_Main_02")}, + {0x015f0005, -1, CEntity::pEventHandler(&CExotechLarvaCharger::H0x015f0005_Main_03), DEBUGSTRING("CExotechLarvaCharger::H0x015f0005_Main_03")}, + {0x015f0006, -1, CEntity::pEventHandler(&CExotechLarvaCharger::H0x015f0006_Main_04), DEBUGSTRING("CExotechLarvaCharger::H0x015f0006_Main_04")}, + {0x015f0007, -1, CEntity::pEventHandler(&CExotechLarvaCharger::H0x015f0007_Main_05), DEBUGSTRING("CExotechLarvaCharger::H0x015f0007_Main_05")}, + {0x015f0008, -1, CEntity::pEventHandler(&CExotechLarvaCharger::H0x015f0008_Main_06), DEBUGSTRING("CExotechLarvaCharger::H0x015f0008_Main_06")}, + {0x015f0009, -1, CEntity::pEventHandler(&CExotechLarvaCharger::H0x015f0009_Main_07), DEBUGSTRING("CExotechLarvaCharger::H0x015f0009_Main_07")}, + {0x015f000a, -1, CEntity::pEventHandler(&CExotechLarvaCharger::H0x015f000a_Main_08), DEBUGSTRING("CExotechLarvaCharger::H0x015f000a_Main_08")}, +}; +#define CExotechLarvaCharger_handlersct ARRAYCOUNT(CExotechLarvaCharger_handlers) + +CEntity *CExotechLarvaCharger_New(void) { return new CExotechLarvaCharger; }; +void CExotechLarvaCharger_OnInitClass(void) {}; +void CExotechLarvaCharger_OnEndClass(void) {}; +void CExotechLarvaCharger_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CExotechLarvaCharger_OnWorldEnd(CWorld *pwo) {}; +void CExotechLarvaCharger_OnWorldInit(CWorld *pwo) {}; +void CExotechLarvaCharger_OnWorldTick(CWorld *pwo) {}; +void CExotechLarvaCharger_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CExotechLarvaCharger, CRationalEntity, "ExotechLarvaCharger", "Thumbnails\\ExotechLarvaCharger.tbn", 0x0000015f); +DECLARE_CTFILENAME(_fnmCExotechLarvaCharger_tbn, "Thumbnails\\ExotechLarvaCharger.tbn"); diff --git a/Sources/EntitiesMP/ExotechLarva_tables.h b/Sources/EntitiesMP/ExotechLarva_tables.h new file mode 100644 index 0000000..a3df806 --- /dev/null +++ b/Sources/EntitiesMP/ExotechLarva_tables.h @@ -0,0 +1,216 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(LarvaTarget) + EP_ENUMVALUE(LT_NONE, ""), + EP_ENUMVALUE(LT_ENEMY, ""), + EP_ENUMVALUE(LT_RECHARGER, ""), +EP_ENUMEND(LarvaTarget); + +#define ENTITYCLASS CExotechLarva + +CEntityProperty CExotechLarva_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015a<<8)+10, offsetof(CExotechLarva, m_penMarkerNew), "Larva 1st Grid Marker", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015a<<8)+11, offsetof(CExotechLarva, m_penMarkerOld), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015a<<8)+15, offsetof(CExotechLarva, m_fStopRadius), "Larva MinDist From Player", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015a<<8)+16, offsetof(CExotechLarva, m_fStretch), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015a<<8)+17, offsetof(CExotechLarva, m_fLarvaHealth), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015a<<8)+19, offsetof(CExotechLarva, m_fRechargePerSecond), "Larva Recharge health/sec", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &LarvaTarget_enum, (0x0000015a<<8)+18, offsetof(CExotechLarva, m_ltTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015a<<8)+30, offsetof(CExotechLarva, m_penFirstRechargeTarget), "Larva First Recharge target", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+31, offsetof(CExotechLarva, m_bRechargedAtLeastOnce), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015a<<8)+20, offsetof(CExotechLarva, m_vFirePosLeftPlasmaRel), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015a<<8)+21, offsetof(CExotechLarva, m_vFirePosRightPlasmaRel), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015a<<8)+23, offsetof(CExotechLarva, m_vFirePosTailRel), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015a<<8)+24, offsetof(CExotechLarva, m_vFirePosLeftLaserAbs), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015a<<8)+25, offsetof(CExotechLarva, m_vFirePosRightLaserAbs), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+40, offsetof(CExotechLarva, m_bLeftArmActive), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+41, offsetof(CExotechLarva, m_bRightArmActive), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015a<<8)+42, offsetof(CExotechLarva, m_iExplodingArm), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015a<<8)+45, offsetof(CExotechLarva, m_fMaxRechargedHealth), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+46, offsetof(CExotechLarva, m_bExploding), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+47, offsetof(CExotechLarva, m_bActive), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+48, offsetof(CExotechLarva, m_bRechargePose), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+49, offsetof(CExotechLarva, m_bLaserActive), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+51, offsetof(CExotechLarva, m_bInitialMove), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015a<<8)+54, offsetof(CExotechLarva, m_penRecharger), "Larva Recharger", 0, C_GREEN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015a<<8)+60, offsetof(CExotechLarva, m_tmLastTargateChange), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_PLACEMENT3D, NULL, (0x0000015a<<8)+70, offsetof(CExotechLarva, m_plExpArmPos), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015a<<8)+71, offsetof(CExotechLarva, m_aExpArmRot), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_PLACEMENT3D, NULL, (0x0000015a<<8)+72, offsetof(CExotechLarva, m_plExpGunPos), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015a<<8)+73, offsetof(CExotechLarva, m_aExpGunRot), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015a<<8)+74, offsetof(CExotechLarva, m_vExpDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015a<<8)+75, offsetof(CExotechLarva, m_iExplosions), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015a<<8)+80, offsetof(CExotechLarva, m_iRnd), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+81, offsetof(CExotechLarva, m_bRecharging), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015a<<8)+90, offsetof(CExotechLarva, m_penDeathInflictor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015a<<8)+100, offsetof(CExotechLarva, m_tmDontFireLaserBefore), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015a<<8)+101, offsetof(CExotechLarva, m_fMinimumLaserWait), "Larva min. laser interval", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+102, offsetof(CExotechLarva, m_bRenderLeftLaser), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+103, offsetof(CExotechLarva, m_bRenderRightLaser), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015a<<8)+104, offsetof(CExotechLarva, m_vLeftLaserTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015a<<8)+105, offsetof(CExotechLarva, m_vRightLaserTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015a<<8)+110, offsetof(CExotechLarva, m_bInvulnerable), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015a<<8)+150, offsetof(CExotechLarva, m_penLeftArmDestroyTarget), "Larva ArmBlow#1 Target", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015a<<8)+151, offsetof(CExotechLarva, m_penRightArmDestroyTarget), "Larva ArmBlow#2 Target", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015a<<8)+152, offsetof(CExotechLarva, m_penDeathTarget), "Larva Death Target", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015a<<8)+200, offsetof(CExotechLarva, m_soFire1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015a<<8)+201, offsetof(CExotechLarva, m_soFire2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015a<<8)+202, offsetof(CExotechLarva, m_soFire3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015a<<8)+203, offsetof(CExotechLarva, m_soVoice), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015a<<8)+204, offsetof(CExotechLarva, m_soChirp), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015a<<8)+205, offsetof(CExotechLarva, m_soLaser), "", 0, 0, 0), +}; +#define CExotechLarva_propertiesct ARRAYCOUNT(CExotechLarva_properties) + +CEntityComponent CExotechLarva_components[] = { +#define CLASS_BASE ((0x0000015a<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_BASIC_EFFECT ((0x0000015a<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_PROJECTILE ((0x0000015a<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_BLOOD_SPRAY ((0x0000015a<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define CLASS_LARVAOFFSPRING ((0x0000015a<<8)+5) + CEntityComponent(ECT_CLASS, CLASS_LARVAOFFSPRING, "EFNM" "Classes\\LarvaOffspring.ecl"), +#define MODEL_EXOTECHLARVA ((0x0000015a<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_EXOTECHLARVA, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\ExotechLarva.mdl"), +#define TEXTURE_EXOTECHLARVA ((0x0000015a<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_EXOTECHLARVA, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\ExotechLarva.tex"), +#define MODEL_BODY ((0x0000015a<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_BODY, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Body.mdl"), +#define TEXTURE_BODY ((0x0000015a<<8)+13) + CEntityComponent(ECT_TEXTURE, TEXTURE_BODY, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Body.tex"), +#define MODEL_BEAM ((0x0000015a<<8)+14) + CEntityComponent(ECT_MODEL, MODEL_BEAM, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Beam.mdl"), +#define TEXTURE_BEAM ((0x0000015a<<8)+15) + CEntityComponent(ECT_TEXTURE, TEXTURE_BEAM, "EFNM" "ModelsMP\\Effects\\Laser\\Laser.tex"), +#define MODEL_ENERGYBEAMS ((0x0000015a<<8)+16) + CEntityComponent(ECT_MODEL, MODEL_ENERGYBEAMS, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\EnergyBeams.mdl"), +#define TEXTURE_ENERGYBEAMS ((0x0000015a<<8)+17) + CEntityComponent(ECT_TEXTURE, TEXTURE_ENERGYBEAMS, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\EnergyBeams.tex"), +#define MODEL_FLARE ((0x0000015a<<8)+18) + CEntityComponent(ECT_MODEL, MODEL_FLARE, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\EffectFlare.mdl"), +#define TEXTURE_FLARE ((0x0000015a<<8)+19) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\EffectFlare.tex"), +#define MODEL_WING ((0x0000015a<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_WING, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Arm.mdl"), +#define TEXTURE_WING ((0x0000015a<<8)+31) + CEntityComponent(ECT_TEXTURE, TEXTURE_WING, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Arm.tex"), +#define MODEL_PLASMAGUN ((0x0000015a<<8)+32) + CEntityComponent(ECT_MODEL, MODEL_PLASMAGUN, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.mdl"), +#define TEXTURE_PLASMAGUN ((0x0000015a<<8)+33) + CEntityComponent(ECT_TEXTURE, TEXTURE_PLASMAGUN, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.tex"), +#define MODEL_BLADES ((0x0000015a<<8)+34) + CEntityComponent(ECT_MODEL, MODEL_BLADES, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\BackArms.mdl"), +#define MODEL_DEBRIS_BODY ((0x0000015a<<8)+36) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS_BODY, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Debris\\BodyDebris.mdl"), +#define MODEL_DEBRIS_TAIL01 ((0x0000015a<<8)+37) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS_TAIL01, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Debris\\TailDebris01.mdl"), +#define MODEL_DEBRIS_TAIL02 ((0x0000015a<<8)+38) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS_TAIL02, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Debris\\TailDebris02.mdl"), +#define MODEL_DEBRIS_FLESH ((0x0000015a<<8)+39) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS_FLESH, "EFNM" "Models\\Effects\\Debris\\Flesh\\Flesh.mdl"), +#define TEXTURE_DEBRIS_FLESH ((0x0000015a<<8)+40) + CEntityComponent(ECT_TEXTURE, TEXTURE_DEBRIS_FLESH, "EFNM" "Models\\Effects\\Debris\\Flesh\\FleshRed.tex"), +#define MODEL_PLASMA ((0x0000015a<<8)+41) + CEntityComponent(ECT_MODEL, MODEL_PLASMA, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\Projectile.mdl"), +#define TEXTURE_PLASMA ((0x0000015a<<8)+42) + CEntityComponent(ECT_TEXTURE, TEXTURE_PLASMA, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\Projectile.tex"), +#define SOUND_FIRE_PLASMA ((0x0000015a<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_FIRE_PLASMA, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\FirePlasma.wav"), +#define SOUND_FIRE_TAIL ((0x0000015a<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_FIRE_TAIL, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\FireTail.wav"), +#define SOUND_LASER_CHARGE ((0x0000015a<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_LASER_CHARGE, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\LaserCharge.wav"), +#define SOUND_DEATH ((0x0000015a<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\Death.wav"), +#define SOUND_ARMDESTROY ((0x0000015a<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_ARMDESTROY, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\ArmDestroy.wav"), +#define SOUND_CHIRP ((0x0000015a<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_CHIRP, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\Chirp.wav"), +#define SOUND_DEPLOYLASER ((0x0000015a<<8)+56) + CEntityComponent(ECT_SOUND, SOUND_DEPLOYLASER, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\DeployLaser.wav"), +}; +#define CExotechLarva_componentsct ARRAYCOUNT(CExotechLarva_components) + +CEventHandlerEntry CExotechLarva_handlers[] = { + {0x015a0002, STATE_CEnemyBase_BeWounded, CEntity::pEventHandler(&CExotechLarva:: +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BeWounded),DEBUGSTRING("CExotechLarva::BeWounded")}, + {0x015a0003, -1, CEntity::pEventHandler(&CExotechLarva:: +#line 932 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +ArmExplosion),DEBUGSTRING("CExotechLarva::ArmExplosion")}, + {0x015a0004, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0004_ArmExplosion_01), DEBUGSTRING("CExotechLarva::H0x015a0004_ArmExplosion_01")}, + {0x015a0005, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0005_ArmExplosion_02), DEBUGSTRING("CExotechLarva::H0x015a0005_ArmExplosion_02")}, + {0x015a0006, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0006_ArmExplosion_03), DEBUGSTRING("CExotechLarva::H0x015a0006_ArmExplosion_03")}, + {0x015a0007, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0007_ArmExplosion_04), DEBUGSTRING("CExotechLarva::H0x015a0007_ArmExplosion_04")}, + {0x015a0008, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0008_ArmExplosion_05), DEBUGSTRING("CExotechLarva::H0x015a0008_ArmExplosion_05")}, + {0x015a0009, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0009_ArmExplosion_06), DEBUGSTRING("CExotechLarva::H0x015a0009_ArmExplosion_06")}, + {0x015a000a, STATE_CEnemyBase_Die, CEntity::pEventHandler(&CExotechLarva:: +#line 1035 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Die),DEBUGSTRING("CExotechLarva::Die")}, + {0x015a000b, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a000b_Die_01), DEBUGSTRING("CExotechLarva::H0x015a000b_Die_01")}, + {0x015a000c, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a000c_Die_02), DEBUGSTRING("CExotechLarva::H0x015a000c_Die_02")}, + {0x015a000d, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a000d_Die_03), DEBUGSTRING("CExotechLarva::H0x015a000d_Die_03")}, + {0x015a000e, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a000e_Die_04), DEBUGSTRING("CExotechLarva::H0x015a000e_Die_04")}, + {0x015a000f, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CExotechLarva:: +#line 1132 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Fire),DEBUGSTRING("CExotechLarva::Fire")}, + {0x015a0010, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0010_Fire_01), DEBUGSTRING("CExotechLarva::H0x015a0010_Fire_01")}, + {0x015a0011, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0011_Fire_02), DEBUGSTRING("CExotechLarva::H0x015a0011_Fire_02")}, + {0x015a0012, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0012_Fire_03), DEBUGSTRING("CExotechLarva::H0x015a0012_Fire_03")}, + {0x015a0013, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0013_Fire_04), DEBUGSTRING("CExotechLarva::H0x015a0013_Fire_04")}, + {0x015a0014, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0014_Fire_05), DEBUGSTRING("CExotechLarva::H0x015a0014_Fire_05")}, + {0x015a0015, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0015_Fire_06), DEBUGSTRING("CExotechLarva::H0x015a0015_Fire_06")}, + {0x015a0016, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0016_Fire_07), DEBUGSTRING("CExotechLarva::H0x015a0016_Fire_07")}, + {0x015a0017, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0017_Fire_08), DEBUGSTRING("CExotechLarva::H0x015a0017_Fire_08")}, + {0x015a0018, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0018_Fire_09), DEBUGSTRING("CExotechLarva::H0x015a0018_Fire_09")}, + {0x015a0019, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0019_Fire_10), DEBUGSTRING("CExotechLarva::H0x015a0019_Fire_10")}, + {0x015a001a, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a001a_Fire_11), DEBUGSTRING("CExotechLarva::H0x015a001a_Fire_11")}, + {0x015a001b, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a001b_Fire_12), DEBUGSTRING("CExotechLarva::H0x015a001b_Fire_12")}, + {0x015a001c, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a001c_Fire_13), DEBUGSTRING("CExotechLarva::H0x015a001c_Fire_13")}, + {0x015a001d, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a001d_Fire_14), DEBUGSTRING("CExotechLarva::H0x015a001d_Fire_14")}, + {0x015a001e, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CExotechLarva:: +#line 1194 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Hit),DEBUGSTRING("CExotechLarva::Hit")}, + {0x015a001f, STATE_CEnemyBase_BeIdle, CEntity::pEventHandler(&CExotechLarva:: +#line 1198 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +BeIdle),DEBUGSTRING("CExotechLarva::BeIdle")}, + {0x015a0020, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0020_BeIdle_01), DEBUGSTRING("CExotechLarva::H0x015a0020_BeIdle_01")}, + {0x015a0021, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0021_BeIdle_02), DEBUGSTRING("CExotechLarva::H0x015a0021_BeIdle_02")}, + {0x015a0022, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0022_BeIdle_03), DEBUGSTRING("CExotechLarva::H0x015a0022_BeIdle_03")}, + {0x015a0023, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0023_BeIdle_04), DEBUGSTRING("CExotechLarva::H0x015a0023_BeIdle_04")}, + {0x015a0024, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0024_BeIdle_05), DEBUGSTRING("CExotechLarva::H0x015a0024_BeIdle_05")}, + {0x015a0025, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0025_BeIdle_06), DEBUGSTRING("CExotechLarva::H0x015a0025_BeIdle_06")}, + {0x015a0026, -1, CEntity::pEventHandler(&CExotechLarva:: +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +LarvaLoop),DEBUGSTRING("CExotechLarva::LarvaLoop")}, + {0x015a0027, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0027_LarvaLoop_01), DEBUGSTRING("CExotechLarva::H0x015a0027_LarvaLoop_01")}, + {0x015a0028, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0028_LarvaLoop_02), DEBUGSTRING("CExotechLarva::H0x015a0028_LarvaLoop_02")}, + {1, -1, CEntity::pEventHandler(&CExotechLarva:: +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/ExotechLarva.es" +Main),DEBUGSTRING("CExotechLarva::Main")}, + {0x015a0029, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0029_Main_01), DEBUGSTRING("CExotechLarva::H0x015a0029_Main_01")}, + {0x015a002a, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a002a_Main_02), DEBUGSTRING("CExotechLarva::H0x015a002a_Main_02")}, + {0x015a002b, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a002b_Main_03), DEBUGSTRING("CExotechLarva::H0x015a002b_Main_03")}, + {0x015a002c, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a002c_Main_04), DEBUGSTRING("CExotechLarva::H0x015a002c_Main_04")}, + {0x015a002d, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a002d_Main_05), DEBUGSTRING("CExotechLarva::H0x015a002d_Main_05")}, + {0x015a002e, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a002e_Main_06), DEBUGSTRING("CExotechLarva::H0x015a002e_Main_06")}, + {0x015a002f, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a002f_Main_07), DEBUGSTRING("CExotechLarva::H0x015a002f_Main_07")}, + {0x015a0030, -1, CEntity::pEventHandler(&CExotechLarva::H0x015a0030_Main_08), DEBUGSTRING("CExotechLarva::H0x015a0030_Main_08")}, +}; +#define CExotechLarva_handlersct ARRAYCOUNT(CExotechLarva_handlers) + +CEntity *CExotechLarva_New(void) { return new CExotechLarva; }; +void CExotechLarva_OnInitClass(void) {}; +void CExotechLarva_OnEndClass(void) {}; +void CExotechLarva_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CExotechLarva_OnWorldEnd(CWorld *pwo) {}; +void CExotechLarva_OnWorldInit(CWorld *pwo) {}; +void CExotechLarva_OnWorldTick(CWorld *pwo) {}; +void CExotechLarva_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CExotechLarva, CEnemyBase, "ExotechLarva", "Thumbnails\\ExotechLarva.tbn", 0x0000015a); +DECLARE_CTFILENAME(_fnmCExotechLarva_tbn, "Thumbnails\\ExotechLarva.tbn"); diff --git a/Sources/EntitiesMP/Eyeman.cpp b/Sources/EntitiesMP/Eyeman.cpp new file mode 100644 index 0000000..de38fd6 --- /dev/null +++ b/Sources/EntitiesMP/Eyeman.cpp @@ -0,0 +1,843 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" + +#include "StdH.h" +#include "Models/Enemies/Eyeman/Eyeman.h" + +#include +#include +#line 21 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" + +// info structure +static EntityInfo eiEyemanBig = { + EIBT_FLESH, 140.0f, + 0.0f, 1.4f, 0.0f, + 0.0f, 1.0f, 0.0f, +}; +static EntityInfo eiEyemanSmall = { + EIBT_FLESH, 120.0f, + 0.0f, 1.4f, 0.0f, + 0.0f, 1.0f, 0.0f, +}; + +#define BITE_AIR 3.0f +#define HIT_GROUND 2.0f +#define FIRE_GROUND FLOAT3D(0.75f, 1.5f, -1.25f) + +void CEyeman::SetDefaultProperties(void) { + m_EecChar = EYC_SOLDIER ; + m_bInvisible = FALSE ; + m_eeEnv = EYE_NORMAL ; + m_bMumbleSoundPlaying = FALSE ; + m_soMumble.SetOwner(this); +m_soMumble.Stop_internal(); + CEnemyFly::SetDefaultProperties(); +} + CTString CEyeman::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +{ +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +CTString str ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_bInAir ){ +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +str . PrintF (TRANS ("A Gnaar bit %s to death") , strPlayerName ); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +str . PrintF (TRANS ("%s was beaten up by a Gnaar") , strPlayerName ); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return str ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::Precache(void) { +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +CEnemyBase :: Precache (); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PrecacheSound (SOUND_IDLE ); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PrecacheSound (SOUND_SIGHT ); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PrecacheSound (SOUND_WOUND ); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PrecacheSound (SOUND_BITE ); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PrecacheSound (SOUND_PUNCH ); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PrecacheSound (SOUND_DEATH ); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PrecacheSound (SOUND_MUMBLE ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void * CEyeman::GetEntityInfo(void) { +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_EecChar == EYC_SERGEANT ){ +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return & eiEyemanBig ; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return & eiEyemanSmall ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +{ +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(! IsOfClass (penInflictor , "Eyeman")){ +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +CEnemyFly :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(dmtType == DMT_CHAINSAW && GetHealth () <= 0){ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fBlowUpAmount = 0; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +BOOL CEyeman::FillEntityStatistics(EntityStats * pes) +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +{ +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +CEnemyBase :: FillEntityStatistics (pes ); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +switch(m_EecChar ){ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +case EYC_SERGEANT : {pes -> es_strName += " Sergeant";}break ; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +case EYC_SOLDIER : {pes -> es_strName += " Soldier";}break ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_bInvisible ){ +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +pes -> es_strName += " Invisible"; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return TRUE ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + const CTFileName & CEyeman::GetComputerMessageName(void)const { +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +static DECLARE_CTFILENAME (fnmSergeant , "Data\\Messages\\Enemies\\EyemanGreen.txt"); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +static DECLARE_CTFILENAME (fnmSoldier , "Data\\Messages\\Enemies\\EyemanPurple.txt"); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +switch(m_EecChar ){ +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +default : ASSERT (FALSE ); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +case EYC_SERGEANT : return fnmSergeant ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +case EYC_SOLDIER : return fnmSoldier ; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +BOOL CEyeman::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +{ +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_bInvisible ){ +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +colAmbient = C_WHITE ; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return FALSE ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return CEnemyBase :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +INDEX CEyeman::AnimForDamage(FLOAT fDamage) { +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +DeactivateMumblingSound (); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +INDEX iAnim ; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_bInAir ){ +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +switch(IRnd () % 2){ +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +case 0: iAnim = EYEMAN_ANIM_MORPHWOUND01 ;break ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +case 1: iAnim = EYEMAN_ANIM_MORPHWOUND02 ;break ; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +default : ASSERTALWAYS ("Eyeman unknown fly damage"); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT3D vFront ; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +GetHeadingDirection (0 , vFront ); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT fDamageDir = m_vDamage % vFront ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(Abs (fDamageDir ) <= 10){ +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +switch(IRnd () % 3){ +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +case 0: iAnim = EYEMAN_ANIM_WOUND03 ;break ; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +case 1: iAnim = EYEMAN_ANIM_WOUND06 ;break ; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +case 2: iAnim = EYEMAN_ANIM_WOUND07 ;break ; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(fDamageDir < 0){ +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +iAnim = EYEMAN_ANIM_FALL01 ; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +iAnim = EYEMAN_ANIM_FALL02 ; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (iAnim , 0); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return iAnim ; +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +INDEX CEyeman::AnimForDeath(void) { +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +DeactivateMumblingSound (); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +INDEX iAnim ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_bInAir ){ +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +iAnim = EYEMAN_ANIM_MORPHDEATH ; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT3D vFront ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +GetHeadingDirection (0 , vFront ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT fDamageDir = m_vDamage % vFront ; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(fDamageDir < 0){ +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +iAnim = EYEMAN_ANIM_DEATH02 ; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +iAnim = EYEMAN_ANIM_DEATH01 ; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (iAnim , 0); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return iAnim ; +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT CEyeman::WaitForDust(FLOAT3D & vStretch) { +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(GetModelObject () -> GetAnim () == EYEMAN_ANIM_DEATH01 ) +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +{ +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +vStretch = FLOAT3D (1 , 1 , 1) * 0.75f; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return 0.5f; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +else if(GetModelObject () -> GetAnim () == EYEMAN_ANIM_DEATH02 ) +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +{ +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +vStretch = FLOAT3D (1 , 1 , 1) * 0.75f; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return 0.5f; +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +else if(GetModelObject () -> GetAnim () == EYEMAN_ANIM_MORPHDEATH ) +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +{ +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +vStretch = FLOAT3D (1 , 1 , 1) * 1.0f; +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return 0.5f; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return - 1.0f; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::DeathNotify(void) { +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +ChangeCollisionBoxIndexWhenPossible (EYEMAN_COLLISION_BOX_DEATH ); +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +en_fDensity = 500.0f; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::ActivateMumblingSound(void) +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +{ +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(! m_bMumbleSoundPlaying ){ +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PlaySound (m_soMumble , SOUND_MUMBLE , SOF_3D | SOF_LOOP ); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_bMumbleSoundPlaying = TRUE ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::DeactivateMumblingSound(void) +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +{ +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_soMumble . Stop (); +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_bMumbleSoundPlaying = FALSE ; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::StandingAnim(void) { +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +DeactivateMumblingSound (); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_bInAir ){ +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_MORPHATTACKFLY , AOF_LOOPING | AOF_NORESTART ); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_STAND , AOF_LOOPING | AOF_NORESTART ); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::WalkingAnim(void) { +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +ActivateMumblingSound (); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_bInAir ){ +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_MORPHATTACKFLY , AOF_LOOPING | AOF_NORESTART ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_WALK , AOF_LOOPING | AOF_NORESTART ); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::RunningAnim(void) { +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +ActivateMumblingSound (); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_bInAir ){ +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_MORPHATTACKFLY , AOF_LOOPING | AOF_NORESTART ); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_RUN , AOF_LOOPING | AOF_NORESTART ); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::RotatingAnim(void) { +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_bInAir ){ +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_MORPHATTACKFLY , AOF_LOOPING | AOF_NORESTART ); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_RUN , AOF_LOOPING | AOF_NORESTART ); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT CEyeman::AirToGroundAnim(void) { +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_MORPHUP , 0); +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return (GetModelObject () -> GetAnimLength (EYEMAN_ANIM_MORPHUP )); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT CEyeman::GroundToAirAnim(void) { +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_MORPHDOWN , 0); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return (GetModelObject () -> GetAnimLength (EYEMAN_ANIM_MORPHDOWN )); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::ChangeCollisionToAir() { +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +ChangeCollisionBoxIndexWhenPossible (EYEMAN_COLLISION_BOX_AIR ); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::ChangeCollisionToGround() { +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +ChangeCollisionBoxIndexWhenPossible (EYEMAN_COLLISION_BOX_GROUND ); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::IdleSound(void) { +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::SightSound(void) { +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::WoundSound(void) { +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void CEyeman::DeathSound(void) { +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +BOOL CEyeman::MayMoveToAttack(void) +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +{ +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_bInAir ){ +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return WouldNotLeaveAttackRadius (); +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return CEnemyBase :: MayMoveToAttack (); +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} + +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +BOOL CEyeman::CanHitEnemy(CEntity * penTarget,FLOAT fCosAngle) { +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(IsInPlaneFrustum (penTarget , fCosAngle )){ +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return IsVisibleCheckAll (penTarget ); +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return FALSE ; +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +BOOL CEyeman:: +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FlyHit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEyeman_FlyHit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEyeman::FlyHit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(CalcDist (m_penEnemy ) > BITE_AIR ){ +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fShootTime = _pTimer -> CurrentTick () + 0.25f; +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +Return(STATE_CURRENT,EReturn ()); +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return TRUE; +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_MORPHATTACK , 0); +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StopMoving (); +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PlaySound (m_soSound , SOUND_BITE , SOF_3D ); +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetTimerAfter(0.4f); +Jump(STATE_CURRENT, 0x01430001, FALSE, EBegin());return TRUE;}BOOL CEyeman::H0x01430001_FlyHit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01430001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01430002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEyeman::H0x01430002_FlyHit_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01430002 +; +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(CalcDist (m_penEnemy ) < BITE_AIR ){ +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +vDirection . SafeNormalize (); +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 3.5f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +ESpawnEffect eSpawnEffect ; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +eSpawnEffect . betType = BET_BLOODEXPLODE ; +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +eSpawnEffect . vStretch = FLOAT3D (1 , 1 , 1); +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +CPlacement3D plOne = GetPlacement (); +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +GetEntityPointRatio ( +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT3D (Lerp (- 0.2f , + 0.2f , FRnd ()) , Lerp (- 0.2f , + 0.2f , FRnd ()) , - 1.0f) , +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +plOne . pl_PositionVector ); +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +CEntityPointer penBloodCloud = CreateEntity (plOne , CLASS_BASIC_EFFECT ); +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +penBloodCloud -> Initialize (eSpawnEffect ); +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetTimerAfter(0.24f); +Jump(STATE_CURRENT, 0x01430003, FALSE, EBegin());return TRUE;}BOOL CEyeman::H0x01430003_FlyHit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01430003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01430004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEyeman::H0x01430004_FlyHit_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01430004 +; +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StandingAnim (); +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +Return(STATE_CURRENT,EReturn ()); +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEyeman:: +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +GroundHit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEyeman_GroundHit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEyeman::GroundHit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(CalcDist (m_penEnemy ) > HIT_GROUND ){ +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fShootTime = _pTimer -> CurrentTick () + 0.25f; +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +Return(STATE_CURRENT,EReturn ()); +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return TRUE; +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StartModelAnim (EYEMAN_ANIM_ATTACK02 , 0); +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StopMoving (); +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetTimerAfter(0.2f); +Jump(STATE_CURRENT, 0x01430006, FALSE, EBegin());return TRUE;}BOOL CEyeman::H0x01430006_GroundHit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01430006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01430007, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEyeman::H0x01430007_GroundHit_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01430007 +; +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(CalcDist (m_penEnemy ) < HIT_GROUND ){ +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +vDirection . SafeNormalize (); +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 3.5f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PlaySound (m_soSound , SOUND_PUNCH , SOF_3D ); +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetTimerAfter(0.3f); +Jump(STATE_CURRENT, 0x01430008, FALSE, EBegin());return TRUE;}BOOL CEyeman::H0x01430008_GroundHit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01430008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01430009, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEyeman::H0x01430009_GroundHit_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01430009 +; +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(CalcDist (m_penEnemy ) < HIT_GROUND ){ +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +vDirection . SafeNormalize (); +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 3.5f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +PlaySound (m_soSound , SOUND_PUNCH , SOF_3D ); +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetTimerAfter(0.4f); +Jump(STATE_CURRENT, 0x0143000a, FALSE, EBegin());return TRUE;}BOOL CEyeman::H0x0143000a_GroundHit_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0143000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0143000b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CEyeman::H0x0143000b_GroundHit_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0143000b +; +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +StandingAnim (); +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +Return(STATE_CURRENT,EReturn ()); +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CEyeman:: +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CEyeman_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CEyeman::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +InitAsModel (); +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetCollisionFlags (ECF_MODEL ); +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_EecChar == EYC_SERGEANT ){ +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetHealth (90.0f); +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fMaxHealth = 90.0f; +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fBlowUpAmount = 130.0f; +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fBodyParts = 5; +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fBlowUpSize = 2.5f; +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fDamageWounded = 40.0f; +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetHealth (60.0f); +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fMaxHealth = 60.0f; +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fBlowUpAmount = 100.0f; +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fBodyParts = 5; +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fBlowUpSize = 2.0f; +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fDamageWounded = 25.0f; +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +en_fDensity = 2000.0f; +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_EeftType == EFT_GROUND_ONLY ){ +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +en_tmMaxHoldBreath = 5.0f; +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +en_tmMaxHoldBreath = 30.0f; +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetModel (MODEL_EYEMAN ); +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_EecChar == EYC_SERGEANT ){ +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetModelMainTexture (TEXTURE_EYEMAN_SERGEANT ); +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +GetModelObject () -> StretchModel (FLOAT3D (1.3f , 1.3f , 1.3f)); +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +ModelChangeNotify (); +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_iScore = 1000; +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_iScore = 500; +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_eeEnv == EYE_LAVA ){ +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetModelMainTexture (TEXTURE_EYEMAN_LAVA ); +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +SetModelMainTexture (TEXTURE_EYEMAN_SOLDIER ); +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +GetModelObject () -> StretchModel (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +ModelChangeNotify (); +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_bInvisible ){ +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +GetModelObject () -> mo_colBlendColor = C_WHITE | 0x25; +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_iScore *= 2; +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fWalkSpeed = FRnd () + 1.5f; +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_aWalkRotateSpeed = FRnd () * 10.0f + 500.0f; +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_EecChar == EYC_SERGEANT ){ +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fAttackRunSpeed = FRnd () * 2.0f + 10.0f; +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 100 + 600.0f); +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fCloseRunSpeed = FRnd () * 2.0f + 10.0f; +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 100 + 600.0f); +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fAttackRunSpeed = FRnd () * 2.0f + 9.0f; +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 100 + 600.0f); +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fCloseRunSpeed = FRnd () * 2.0f + 9.0f; +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 100 + 600.0f); +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fAttackDistance = 100.0f; +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fCloseDistance = 3.5f; +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fStopDistance = 1.5f; +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fAttackFireTime = 2.0f; +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fCloseFireTime = 0.5f; +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fIgnoreRange = 200.0f; +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyWalkSpeed = FRnd () * 2.0f + 3.0f; +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_aFlyWalkRotateSpeed = FRnd () * 20.0f + 600.0f; +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +if(m_EecChar == EYC_SERGEANT ){ +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyAttackRunSpeed = FRnd () * 2.0f + 9.5f; +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_aFlyAttackRotateSpeed = FRnd () * 25 + 350.0f; +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyCloseRunSpeed = FRnd () * 2.0f + 9.5f; +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_aFlyCloseRotateSpeed = FRnd () * 50 + 400.0f; +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +}else { +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyAttackRunSpeed = FRnd () * 2.0f + 9.5f; +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_aFlyAttackRotateSpeed = FRnd () * 25 + 300.0f; +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyCloseRunSpeed = FRnd () * 2.0f + 9.5f; +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_aFlyCloseRotateSpeed = FRnd () * 50 + 300.0f; +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +} +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fGroundToAirSpeed = 2.5f; +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fAirToGroundSpeed = 2.5f; +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fAirToGroundMin = 0.1f; +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fAirToGroundMax = 0.1f; +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyHeight = 1.0f; +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyAttackDistance = 100.0f; +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyCloseDistance = 10.0f; +#line 534 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyStopDistance = 1.5f; +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyAttackFireTime = 2.0f; +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyCloseFireTime = 0.5f; +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_fFlyIgnoreRange = 200.0f; +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +m_soMumble . Set3DParameters (25.0f , 0.0f , 1.0f , 1.0f); +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +Jump(STATE_CURRENT, STATE_CEnemyFly_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Eyeman.es b/Sources/EntitiesMP/Eyeman.es new file mode 100644 index 0000000..3c7cca4 --- /dev/null +++ b/Sources/EntitiesMP/Eyeman.es @@ -0,0 +1,543 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +323 +%{ +#include "StdH.h" +#include "Models/Enemies/Eyeman/Eyeman.h" +%} + +uses "EntitiesMP/EnemyFly"; + +enum EyemanChar { + 0 EYC_SOLDIER "Soldier", // soldier + 1 EYC_SERGEANT "Sergeant", // sergeant +}; + +enum EyemanEnv { + 0 EYE_NORMAL "Normal", + 1 EYE_LAVA "Lava", +}; + +%{ +// info structure +static EntityInfo eiEyemanBig = { + EIBT_FLESH, 140.0f, + 0.0f, 1.4f, 0.0f, + 0.0f, 1.0f, 0.0f, +}; +static EntityInfo eiEyemanSmall = { + EIBT_FLESH, 120.0f, + 0.0f, 1.4f, 0.0f, + 0.0f, 1.0f, 0.0f, +}; + +#define BITE_AIR 3.0f +#define HIT_GROUND 2.0f +#define FIRE_GROUND FLOAT3D(0.75f, 1.5f, -1.25f) +%} + + +class CEyeman : CEnemyFly { +name "Eyeman"; +thumbnail "Thumbnails\\Eyeman.tbn"; + +properties: + 1 enum EyemanChar m_EecChar "Character" 'C' = EYC_SOLDIER, // character + 2 BOOL m_bInvisible "Invisible" 'I'=FALSE, + 3 enum EyemanEnv m_eeEnv "Environment" 'E' = EYE_NORMAL, + 4 BOOL m_bMumbleSoundPlaying = FALSE, + 5 CSoundObject m_soMumble, + +components: + 0 class CLASS_BASE "Classes\\EnemyFly.ecl", + 1 model MODEL_EYEMAN "Models\\Enemies\\Eyeman\\Eyeman.mdl", + 2 texture TEXTURE_EYEMAN_SOLDIER "Models\\Enemies\\Eyeman\\Eyeman4.tex", + 3 texture TEXTURE_EYEMAN_SERGEANT "Models\\Enemies\\Eyeman\\Eyeman5.tex", + 5 texture TEXTURE_EYEMAN_LAVA "Models\\Enemies\\Eyeman\\Eyeman6.tex", + 4 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "Models\\Enemies\\Eyeman\\Sounds\\Idle.wav", + 51 sound SOUND_SIGHT "Models\\Enemies\\Eyeman\\Sounds\\Sight.wav", + 52 sound SOUND_WOUND "Models\\Enemies\\Eyeman\\Sounds\\Wound.wav", + 53 sound SOUND_BITE "Models\\Enemies\\Eyeman\\Sounds\\Bite.wav", + 54 sound SOUND_PUNCH "Models\\Enemies\\Eyeman\\Sounds\\Punch.wav", + 55 sound SOUND_DEATH "Models\\Enemies\\Eyeman\\Sounds\\Death.wav", + 56 sound SOUND_MUMBLE "Models\\Enemies\\Eyeman\\Sounds\\Mumble.wav", + + /* + 60 model MODEL_EYEMAN_BODY "Models\\Enemies\\Eyeman\\Debris\\Torso.mdl", + 61 model MODEL_EYEMAN_HAND "Models\\Enemies\\Eyeman\\Debris\\Arm.mdl", + 62 model MODEL_EYEMAN_LEGS "Models\\Enemies\\Eyeman\\Debris\\Leg.mdl", + */ + +functions: + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + if (m_bInAir) { + str.PrintF(TRANS("A Gnaar bit %s to death"), strPlayerName); + } else { + str.PrintF(TRANS("%s was beaten up by a Gnaar"), strPlayerName); + } + return str; + } + void Precache(void) { + CEnemyBase::Precache(); + PrecacheSound(SOUND_IDLE ); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_BITE ); + PrecacheSound(SOUND_PUNCH); + PrecacheSound(SOUND_DEATH); + PrecacheSound(SOUND_MUMBLE); + }; + + /* Entity info */ + void *GetEntityInfo(void) { + if (m_EecChar==EYC_SERGEANT) { + return &eiEyemanBig; + } else { + return &eiEyemanSmall; + } + }; + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // eyeman can't harm eyeman + if (!IsOfClass(penInflictor, "Eyeman")) { + CEnemyFly::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + // if died of chainsaw + if (dmtType==DMT_CHAINSAW && GetHealth()<=0) { + // must always blowup + m_fBlowUpAmount = 0; + } + } + }; + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + CEnemyBase::FillEntityStatistics(pes); + switch(m_EecChar) { + case EYC_SERGEANT: { pes->es_strName+=" Sergeant"; } break; + case EYC_SOLDIER : { pes->es_strName+=" Soldier"; } break; + } + if (m_bInvisible) { + pes->es_strName+=" Invisible"; + } + return TRUE; + } + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnmSergeant, "Data\\Messages\\Enemies\\EyemanGreen.txt"); + static DECLARE_CTFILENAME(fnmSoldier , "Data\\Messages\\Enemies\\EyemanPurple.txt"); + switch(m_EecChar) { + default: ASSERT(FALSE); + case EYC_SERGEANT: return fnmSergeant; + case EYC_SOLDIER : return fnmSoldier; + } + }; + /* Adjust model shading parameters if needed. */ + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + // no shadows for invisibles + if (m_bInvisible) { + colAmbient = C_WHITE; + return FALSE; + } else { + return CEnemyBase::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + } + } + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + DeactivateMumblingSound(); + INDEX iAnim; + if (m_bInAir) { + switch (IRnd()%2) { + case 0: iAnim = EYEMAN_ANIM_MORPHWOUND01; break; + case 1: iAnim = EYEMAN_ANIM_MORPHWOUND02; break; + default: ASSERTALWAYS("Eyeman unknown fly damage"); + } + } else { + FLOAT3D vFront; + GetHeadingDirection(0, vFront); + FLOAT fDamageDir = m_vDamage%vFront; + if (Abs(fDamageDir)<=10) { + switch (IRnd()%3) { + case 0: iAnim = EYEMAN_ANIM_WOUND03; break; + case 1: iAnim = EYEMAN_ANIM_WOUND06; break; + case 2: iAnim = EYEMAN_ANIM_WOUND07; break; + } + } else { + if (fDamageDir<0) { + iAnim = EYEMAN_ANIM_FALL01; + } else { + iAnim = EYEMAN_ANIM_FALL02; + } + } + } + StartModelAnim(iAnim, 0); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + DeactivateMumblingSound(); + INDEX iAnim; + if (m_bInAir) { + iAnim = EYEMAN_ANIM_MORPHDEATH; + } else { + FLOAT3D vFront; + GetHeadingDirection(0, vFront); + FLOAT fDamageDir = m_vDamage%vFront; + if (fDamageDir<0) { + iAnim = EYEMAN_ANIM_DEATH02; + } else { + iAnim = EYEMAN_ANIM_DEATH01; + } + } + StartModelAnim(iAnim, 0); + return iAnim; + }; + + FLOAT WaitForDust(FLOAT3D &vStretch) { + if(GetModelObject()->GetAnim()==EYEMAN_ANIM_DEATH01) + { + vStretch=FLOAT3D(1,1,1)*0.75f; + return 0.5f; + } + else if(GetModelObject()->GetAnim()==EYEMAN_ANIM_DEATH02) + { + vStretch=FLOAT3D(1,1,1)*0.75f; + return 0.5f; + } + else if(GetModelObject()->GetAnim()==EYEMAN_ANIM_MORPHDEATH) + { + vStretch=FLOAT3D(1,1,1)*1.0f; + return 0.5f; + } + return -1.0f; + }; + + void DeathNotify(void) { + ChangeCollisionBoxIndexWhenPossible(EYEMAN_COLLISION_BOX_DEATH); + en_fDensity = 500.0f; + }; + + // mumbling sounds + void ActivateMumblingSound(void) + { + if (!m_bMumbleSoundPlaying) { + PlaySound(m_soMumble, SOUND_MUMBLE, SOF_3D|SOF_LOOP); + m_bMumbleSoundPlaying = TRUE; + } + } + void DeactivateMumblingSound(void) + { + m_soMumble.Stop(); + m_bMumbleSoundPlaying = FALSE; + } + + // virtual anim functions + void StandingAnim(void) { + DeactivateMumblingSound(); + if (m_bInAir) { + StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(EYEMAN_ANIM_STAND, AOF_LOOPING|AOF_NORESTART); + } + }; + void WalkingAnim(void) { + ActivateMumblingSound(); + if (m_bInAir) { + StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(EYEMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART); + } + }; + void RunningAnim(void) { + ActivateMumblingSound(); + if (m_bInAir) { + StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(EYEMAN_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); + } + }; + void RotatingAnim(void) { + if (m_bInAir) { + StartModelAnim(EYEMAN_ANIM_MORPHATTACKFLY, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(EYEMAN_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); + } + }; + FLOAT AirToGroundAnim(void) { + StartModelAnim(EYEMAN_ANIM_MORPHUP, 0); + return(GetModelObject()->GetAnimLength(EYEMAN_ANIM_MORPHUP)); + }; + FLOAT GroundToAirAnim(void) { + StartModelAnim(EYEMAN_ANIM_MORPHDOWN, 0); + return(GetModelObject()->GetAnimLength(EYEMAN_ANIM_MORPHDOWN)); + }; + void ChangeCollisionToAir() { + ChangeCollisionBoxIndexWhenPossible(EYEMAN_COLLISION_BOX_AIR); + }; + void ChangeCollisionToGround() { + ChangeCollisionBoxIndexWhenPossible(EYEMAN_COLLISION_BOX_GROUND); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + +/************************************************************ + * BLOW UP FUNCTIONS * + ************************************************************/ + // spawn body parts + /*void BlowUp(void) + { + // get your size + FLOATaabbox3D box; + GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm(); + + FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(m_fBlowUpAmount/m_vDamage.Length()); + vNormalizedDamage /= Sqrt(vNormalizedDamage.Length()); + + vNormalizedDamage *= 0.75f; + + FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute); + + // spawn debris + Debris_Begin(EIBT_FLESH, DPT_BLOODTRAIL, BET_BLOODSTAIN, fEntitySize, vNormalizedDamage, vBodySpeed, 1.0f, 0.0f); + + INDEX iTextureID = TEXTURE_EYEMAN_SOLDIER; + if (m_EecChar==EYC_SERGEANT) + { + iTextureID = TEXTURE_EYEMAN_SERGEANT; + } + + Debris_Spawn(this, this, MODEL_EYEMAN_BODY, iTextureID, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_EYEMAN_HAND, iTextureID, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_EYEMAN_HAND, iTextureID, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_EYEMAN_LEGS, iTextureID, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + + // hide yourself (must do this after spawning debris) + SwitchToEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + };*/ + +/************************************************************ + * MOVING FUNCTIONS * + ************************************************************/ + // check whether may move while attacking + BOOL MayMoveToAttack(void) + { + if (m_bInAir) { + return WouldNotLeaveAttackRadius(); + } else { + return CEnemyBase::MayMoveToAttack(); + } + } + + // must be more relaxed about hitting then usual enemies + BOOL CanHitEnemy(CEntity *penTarget, FLOAT fCosAngle) { + if (IsInPlaneFrustum(penTarget, fCosAngle)) { + return IsVisibleCheckAll(penTarget); + } + return FALSE; + }; +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + + FlyHit(EVoid) : CEnemyFly::FlyHit { + if (CalcDist(m_penEnemy) > BITE_AIR) { + m_fShootTime = _pTimer->CurrentTick() + 0.25f; + return EReturn(); + } + StartModelAnim(EYEMAN_ANIM_MORPHATTACK, 0); + StopMoving(); + PlaySound(m_soSound, SOUND_BITE, SOF_3D); + // damage enemy + autowait(0.4f); + // damage enemy + if (CalcDist(m_penEnemy) < BITE_AIR) { + FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.SafeNormalize(); + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 3.5f, FLOAT3D(0, 0, 0), vDirection); + // spawn blood cloud + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_BLOODEXPLODE; + eSpawnEffect.vStretch = FLOAT3D(1,1,1); + CPlacement3D plOne = GetPlacement(); + GetEntityPointRatio( + FLOAT3D(Lerp(-0.2f, +0.2f, FRnd()), Lerp(-0.2f, +0.2f, FRnd()), -1.0f), + plOne.pl_PositionVector); + CEntityPointer penBloodCloud = CreateEntity( plOne, CLASS_BASIC_EFFECT); + penBloodCloud->Initialize( eSpawnEffect); + } + autowait(0.24f); + + StandingAnim(); + return EReturn(); + }; + + GroundHit(EVoid) : CEnemyFly::GroundHit { + if (CalcDist(m_penEnemy) > HIT_GROUND) { + m_fShootTime = _pTimer->CurrentTick() + 0.25f; + return EReturn(); + } + StartModelAnim(EYEMAN_ANIM_ATTACK02, 0); + StopMoving(); + // damage enemy + autowait(0.2f); + // damage enemy + if (CalcDist(m_penEnemy) < HIT_GROUND) { + FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.SafeNormalize(); + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 3.5f, FLOAT3D(0, 0, 0), vDirection); + PlaySound(m_soSound, SOUND_PUNCH, SOF_3D); + } + autowait(0.3f); + // damage enemy + if (CalcDist(m_penEnemy) < HIT_GROUND) { + FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.SafeNormalize(); + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 3.5f, FLOAT3D(0, 0, 0), vDirection); + PlaySound(m_soSound, SOUND_PUNCH, SOF_3D); + } + autowait(0.4f); + + StandingAnim(); + return EReturn(); + }; + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + if (m_EecChar==EYC_SERGEANT) { + SetHealth(90.0f); + m_fMaxHealth = 90.0f; + // damage/explode properties + m_fBlowUpAmount = 130.0f; + m_fBodyParts = 5; + m_fBlowUpSize = 2.5f; + m_fDamageWounded = 40.0f; + } else { + SetHealth(60.0f); + m_fMaxHealth = 60.0f; + // damage/explode properties + m_fBlowUpAmount = 100.0f; + m_fBodyParts = 5; + m_fBlowUpSize = 2.0f; + m_fDamageWounded = 25.0f; + } + en_fDensity = 2000.0f; + if (m_EeftType == EFT_GROUND_ONLY) { + en_tmMaxHoldBreath = 5.0f; + } else { + en_tmMaxHoldBreath = 30.0f; + } + + // set your appearance + SetModel(MODEL_EYEMAN); + if (m_EecChar==EYC_SERGEANT) { + SetModelMainTexture(TEXTURE_EYEMAN_SERGEANT); + GetModelObject()->StretchModel(FLOAT3D(1.3f, 1.3f, 1.3f)); + ModelChangeNotify(); + m_iScore = 1000; + } else { + m_iScore = 500; + if (m_eeEnv == EYE_LAVA) { + SetModelMainTexture(TEXTURE_EYEMAN_LAVA); + } else { + SetModelMainTexture(TEXTURE_EYEMAN_SOLDIER); + } + GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f)); + ModelChangeNotify(); + } + if (m_bInvisible) { + GetModelObject()->mo_colBlendColor = C_WHITE|0x25; + m_iScore*=2; + } + // setup moving speed + m_fWalkSpeed = FRnd() + 1.5f; + m_aWalkRotateSpeed = FRnd()*10.0f + 500.0f; + if (m_EecChar==EYC_SERGEANT) { + m_fAttackRunSpeed = FRnd()*2.0f + 10.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*100 + 600.0f); + m_fCloseRunSpeed = FRnd()*2.0f + 10.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 600.0f); + } else { + m_fAttackRunSpeed = FRnd()*2.0f + 9.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*100 + 600.0f); + m_fCloseRunSpeed = FRnd()*2.0f + 9.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 600.0f); + } + // setup attack distances + m_fAttackDistance = 100.0f; + m_fCloseDistance = 3.5f; + m_fStopDistance = 1.5f; + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 0.5f; + m_fIgnoreRange = 200.0f; + // fly moving properties + m_fFlyWalkSpeed = FRnd()*2.0f + 3.0f; + m_aFlyWalkRotateSpeed = FRnd()*20.0f + 600.0f; + if (m_EecChar==EYC_SERGEANT) { + m_fFlyAttackRunSpeed = FRnd()*2.0f + 9.5f; + m_aFlyAttackRotateSpeed = FRnd()*25 + 350.0f; + m_fFlyCloseRunSpeed = FRnd()*2.0f + 9.5f; + m_aFlyCloseRotateSpeed = FRnd()*50 + 400.0f; + } else { + m_fFlyAttackRunSpeed = FRnd()*2.0f + 9.5f; + m_aFlyAttackRotateSpeed = FRnd()*25 + 300.0f; + m_fFlyCloseRunSpeed = FRnd()*2.0f + 9.5f; + m_aFlyCloseRotateSpeed = FRnd()*50 + 300.0f; + } + m_fGroundToAirSpeed = 2.5f; + m_fAirToGroundSpeed = 2.5f; + m_fAirToGroundMin = 0.1f; + m_fAirToGroundMax = 0.1f; + m_fFlyHeight = 1.0f; + // attack properties - CAN BE SET + m_fFlyAttackDistance = 100.0f; + m_fFlyCloseDistance = 10.0f; + m_fFlyStopDistance = 1.5f; + m_fFlyAttackFireTime = 2.0f; + m_fFlyCloseFireTime = 0.5f; + m_fFlyIgnoreRange = 200.0f; + m_soMumble.Set3DParameters(25.0f, 0.0f, 1.0f, 1.0f); + + // continue behavior in base class + jump CEnemyFly::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Eyeman.h b/Sources/EntitiesMP/Eyeman.h new file mode 100644 index 0000000..2ac22c5 --- /dev/null +++ b/Sources/EntitiesMP/Eyeman.h @@ -0,0 +1,135 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Eyeman_INCLUDED +#define _EntitiesMP_Eyeman_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType EyemanChar_enum; +enum EyemanChar { + EYC_SOLDIER = 0, + EYC_SERGEANT = 1, +}; +DECL_DLL inline void ClearToDefault(EyemanChar &e) { e = (EyemanChar)0; } ; +extern DECL_DLL CEntityPropertyEnumType EyemanEnv_enum; +enum EyemanEnv { + EYE_NORMAL = 0, + EYE_LAVA = 1, +}; +DECL_DLL inline void ClearToDefault(EyemanEnv &e) { e = (EyemanEnv)0; } ; +extern "C" DECL_DLL CDLLEntityClass CEyeman_DLLClass; +class CEyeman : public CEnemyFly { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum EyemanChar m_EecChar; + BOOL m_bInvisible; + enum EyemanEnv m_eeEnv; + BOOL m_bMumbleSoundPlaying; + CSoundObject m_soMumble; + +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void Precache(void); + +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void * GetEntityInfo(void); + +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +INDEX AnimForDeath(void); + +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void DeathNotify(void); + +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void ActivateMumblingSound(void); + +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void DeactivateMumblingSound(void); + +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void StandingAnim(void); + +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void WalkingAnim(void); + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void RunningAnim(void); + +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void RotatingAnim(void); + +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT AirToGroundAnim(void); + +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FLOAT GroundToAirAnim(void); + +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void ChangeCollisionToAir(); + +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void ChangeCollisionToGround(); + +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void IdleSound(void); + +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void SightSound(void); + +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void WoundSound(void); + +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +void DeathSound(void); + +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +BOOL MayMoveToAttack(void); + +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +BOOL CanHitEnemy(CEntity * penTarget,FLOAT fCosAngle); +#define STATE_CEyeman_FlyHit 0x01430000 + BOOL +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FlyHit(const CEntityEvent &__eeInput); + BOOL H0x01430001_FlyHit_01(const CEntityEvent &__eeInput); + BOOL H0x01430002_FlyHit_02(const CEntityEvent &__eeInput); + BOOL H0x01430003_FlyHit_03(const CEntityEvent &__eeInput); + BOOL H0x01430004_FlyHit_04(const CEntityEvent &__eeInput); +#define STATE_CEyeman_GroundHit 0x01430005 + BOOL +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +GroundHit(const CEntityEvent &__eeInput); + BOOL H0x01430006_GroundHit_01(const CEntityEvent &__eeInput); + BOOL H0x01430007_GroundHit_02(const CEntityEvent &__eeInput); + BOOL H0x01430008_GroundHit_03(const CEntityEvent &__eeInput); + BOOL H0x01430009_GroundHit_04(const CEntityEvent &__eeInput); + BOOL H0x0143000a_GroundHit_05(const CEntityEvent &__eeInput); + BOOL H0x0143000b_GroundHit_06(const CEntityEvent &__eeInput); +#define STATE_CEyeman_Main 1 + BOOL +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Eyeman_INCLUDED diff --git a/Sources/EntitiesMP/Eyeman_tables.h b/Sources/EntitiesMP/Eyeman_tables.h new file mode 100644 index 0000000..48db9f5 --- /dev/null +++ b/Sources/EntitiesMP/Eyeman_tables.h @@ -0,0 +1,88 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(EyemanChar) + EP_ENUMVALUE(EYC_SOLDIER, "Soldier"), + EP_ENUMVALUE(EYC_SERGEANT, "Sergeant"), +EP_ENUMEND(EyemanChar); + +EP_ENUMBEG(EyemanEnv) + EP_ENUMVALUE(EYE_NORMAL, "Normal"), + EP_ENUMVALUE(EYE_LAVA, "Lava"), +EP_ENUMEND(EyemanEnv); + +#define ENTITYCLASS CEyeman + +CEntityProperty CEyeman_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &EyemanChar_enum, (0x00000143<<8)+1, offsetof(CEyeman, m_EecChar), "Character", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000143<<8)+2, offsetof(CEyeman, m_bInvisible), "Invisible", 'I', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EyemanEnv_enum, (0x00000143<<8)+3, offsetof(CEyeman, m_eeEnv), "Environment", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000143<<8)+4, offsetof(CEyeman, m_bMumbleSoundPlaying), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000143<<8)+5, offsetof(CEyeman, m_soMumble), "", 0, 0, 0), +}; +#define CEyeman_propertiesct ARRAYCOUNT(CEyeman_properties) + +CEntityComponent CEyeman_components[] = { +#define CLASS_BASE ((0x00000143<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyFly.ecl"), +#define MODEL_EYEMAN ((0x00000143<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_EYEMAN, "EFNM" "Models\\Enemies\\Eyeman\\Eyeman.mdl"), +#define TEXTURE_EYEMAN_SOLDIER ((0x00000143<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_EYEMAN_SOLDIER, "EFNM" "Models\\Enemies\\Eyeman\\Eyeman4.tex"), +#define TEXTURE_EYEMAN_SERGEANT ((0x00000143<<8)+3) + CEntityComponent(ECT_TEXTURE, TEXTURE_EYEMAN_SERGEANT, "EFNM" "Models\\Enemies\\Eyeman\\Eyeman5.tex"), +#define TEXTURE_EYEMAN_LAVA ((0x00000143<<8)+5) + CEntityComponent(ECT_TEXTURE, TEXTURE_EYEMAN_LAVA, "EFNM" "Models\\Enemies\\Eyeman\\Eyeman6.tex"), +#define CLASS_BASIC_EFFECT ((0x00000143<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define SOUND_IDLE ((0x00000143<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "Models\\Enemies\\Eyeman\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000143<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "Models\\Enemies\\Eyeman\\Sounds\\Sight.wav"), +#define SOUND_WOUND ((0x00000143<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "Models\\Enemies\\Eyeman\\Sounds\\Wound.wav"), +#define SOUND_BITE ((0x00000143<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_BITE, "EFNM" "Models\\Enemies\\Eyeman\\Sounds\\Bite.wav"), +#define SOUND_PUNCH ((0x00000143<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_PUNCH, "EFNM" "Models\\Enemies\\Eyeman\\Sounds\\Punch.wav"), +#define SOUND_DEATH ((0x00000143<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "Models\\Enemies\\Eyeman\\Sounds\\Death.wav"), +#define SOUND_MUMBLE ((0x00000143<<8)+56) + CEntityComponent(ECT_SOUND, SOUND_MUMBLE, "EFNM" "Models\\Enemies\\Eyeman\\Sounds\\Mumble.wav"), +}; +#define CEyeman_componentsct ARRAYCOUNT(CEyeman_components) + +CEventHandlerEntry CEyeman_handlers[] = { + {0x01430000, STATE_CEnemyFly_FlyHit, CEntity::pEventHandler(&CEyeman:: +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +FlyHit),DEBUGSTRING("CEyeman::FlyHit")}, + {0x01430001, -1, CEntity::pEventHandler(&CEyeman::H0x01430001_FlyHit_01), DEBUGSTRING("CEyeman::H0x01430001_FlyHit_01")}, + {0x01430002, -1, CEntity::pEventHandler(&CEyeman::H0x01430002_FlyHit_02), DEBUGSTRING("CEyeman::H0x01430002_FlyHit_02")}, + {0x01430003, -1, CEntity::pEventHandler(&CEyeman::H0x01430003_FlyHit_03), DEBUGSTRING("CEyeman::H0x01430003_FlyHit_03")}, + {0x01430004, -1, CEntity::pEventHandler(&CEyeman::H0x01430004_FlyHit_04), DEBUGSTRING("CEyeman::H0x01430004_FlyHit_04")}, + {0x01430005, STATE_CEnemyFly_GroundHit, CEntity::pEventHandler(&CEyeman:: +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +GroundHit),DEBUGSTRING("CEyeman::GroundHit")}, + {0x01430006, -1, CEntity::pEventHandler(&CEyeman::H0x01430006_GroundHit_01), DEBUGSTRING("CEyeman::H0x01430006_GroundHit_01")}, + {0x01430007, -1, CEntity::pEventHandler(&CEyeman::H0x01430007_GroundHit_02), DEBUGSTRING("CEyeman::H0x01430007_GroundHit_02")}, + {0x01430008, -1, CEntity::pEventHandler(&CEyeman::H0x01430008_GroundHit_03), DEBUGSTRING("CEyeman::H0x01430008_GroundHit_03")}, + {0x01430009, -1, CEntity::pEventHandler(&CEyeman::H0x01430009_GroundHit_04), DEBUGSTRING("CEyeman::H0x01430009_GroundHit_04")}, + {0x0143000a, -1, CEntity::pEventHandler(&CEyeman::H0x0143000a_GroundHit_05), DEBUGSTRING("CEyeman::H0x0143000a_GroundHit_05")}, + {0x0143000b, -1, CEntity::pEventHandler(&CEyeman::H0x0143000b_GroundHit_06), DEBUGSTRING("CEyeman::H0x0143000b_GroundHit_06")}, + {1, -1, CEntity::pEventHandler(&CEyeman:: +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Eyeman.es" +Main),DEBUGSTRING("CEyeman::Main")}, +}; +#define CEyeman_handlersct ARRAYCOUNT(CEyeman_handlers) + +CEntity *CEyeman_New(void) { return new CEyeman; }; +void CEyeman_OnInitClass(void) {}; +void CEyeman_OnEndClass(void) {}; +void CEyeman_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CEyeman_OnWorldEnd(CWorld *pwo) {}; +void CEyeman_OnWorldInit(CWorld *pwo) {}; +void CEyeman_OnWorldTick(CWorld *pwo) {}; +void CEyeman_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CEyeman, CEnemyFly, "Eyeman", "Thumbnails\\Eyeman.tbn", 0x00000143); +DECLARE_CTFILENAME(_fnmCEyeman_tbn, "Thumbnails\\Eyeman.tbn"); diff --git a/Sources/EntitiesMP/Fireworks.cpp b/Sources/EntitiesMP/Fireworks.cpp new file mode 100644 index 0000000..ba84cbb --- /dev/null +++ b/Sources/EntitiesMP/Fireworks.cpp @@ -0,0 +1,231 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" + +#include "StdH.h" +#define RAND_05 (FLOAT(rand())/RAND_MAX-0.5f) +#define LAUNCH_SPEED 32.0f + +#include +#include +void CFireworks::SetDefaultProperties(void) { + m_rRndRadius = 50.0f; + m_soFly.SetOwner(this); +m_soFly.Stop_internal(); + m_soExplosion.SetOwner(this); +m_soExplosion.Stop_internal(); + m_tmActivated = 0.0f; + m_strName = ""; + m_tmLastAnimation = 0.0f; + CRationalEntity::SetDefaultProperties(); +} + +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +void CFireworks::Read_t(CTStream * istr) +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +{ +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +CRationalEntity :: Read_t (istr ); +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_emEmiter . Read_t (* istr ); +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +} + +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +void CFireworks::Write_t(CTStream * istr) +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +{ +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +CRationalEntity :: Write_t (istr ); +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_emEmiter . Write_t (* istr ); +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +} + +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +void CFireworks::RenderParticles(void) +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +{ +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT tmNow = _pTimer -> CurrentTick (); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +if(tmNow > m_tmLastAnimation ) +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +{ +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT fRatio = CalculateRatio (m_tmActivated - tmNow , 0.0f , 6.0f , 1 , 0); +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT fGPower = (Min (fRatio , 0.5f) - 0.5f) * 2.0f * 10.0f; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_emEmiter . em_vG = FLOAT3D (0 , fGPower , 0); +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_emEmiter . AnimateParticles (); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_tmLastAnimation = tmNow ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +for(INDEX i = 0;i < m_emEmiter . em_aepParticles . Count ();i ++) +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +{ +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +CEmittedParticle & ep = m_emEmiter . em_aepParticles [ i ]; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +if(ep . ep_tmEmitted < 0){continue ;}; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT fLiving = tmNow - ep . ep_tmEmitted ; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT fSpeed = 0.0f; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +if(fLiving >= 6.0f) +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +{ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +fSpeed = 0.0f; +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +} +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +else +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +{ +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +fSpeed = (1.77f * pow (0.421f , fLiving )) * LAUNCH_SPEED ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +} +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT3D vNormalized = ep . ep_vSpeed ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +vNormalized . Normalize (); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +ep . ep_vSpeed = vNormalized * (4.0f + fSpeed ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +} +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +} +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_emEmiter . RenderParticles (); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +} +BOOL CFireworks:: +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +SpawnFireworks(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CFireworks_SpawnFireworks + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CFireworks::SpawnFireworks expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +PlaySound (m_soFly , SOUND_FLY , 0); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +SetTimerAfter(GetSoundLength (SOUND_FLY )); +Jump(STATE_CURRENT, 0x02680001, FALSE, EBegin());return TRUE;}BOOL CFireworks::H0x02680001_SpawnFireworks_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02680001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02680002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CFireworks::H0x02680002_SpawnFireworks_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02680002 +; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +PlaySound (m_soExplosion , SOUND_EXPLODE , 0); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT3D vRndPos = FLOAT3D (RAND_05 , RAND_05 , RAND_05 ) * m_rRndRadius ; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT3D vPos = GetPlacement () . pl_PositionVector + vRndPos ; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_emEmiter . em_vG = FLOAT3D (0 , 0 , 0); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_emEmiter . em_iGlobal = FRnd () * 16; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +UBYTE ubRndH = UBYTE (FRnd () * 255); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +UBYTE ubRndS = UBYTE (255); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +UBYTE ubRndV = UBYTE (255); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_emEmiter . em_colGlobal = C_WHITE | CT_OPAQUE ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT tmNow = _pTimer -> CurrentTick (); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_tmActivated = tmNow ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +INDEX ctSparks = 128; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +for(INDEX iSpark = 0;iSpark < ctSparks ;iSpark ++) +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +{ +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT tmBirth = tmNow + (iSpark + RAND_05 ) * _pTimer -> TickQuantum / ctSparks * 2.0f; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT fLife = 4.0f + RAND_05 * 2.0f; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT fStretch = (1.0f + RAND_05 * 0.25f) * 2.5f; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT3D vSpeed = FLOAT3D (RAND_05 , RAND_05 , RAND_05 ); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +vSpeed = vSpeed . Normalize () * LAUNCH_SPEED ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +FLOAT fRotSpeed = RAND_05 * 360.0f; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +COLOR col = C_WHITE | CT_OPAQUE ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_emEmiter . AddParticle (vPos , vSpeed , RAND_05 * 360.0f , fRotSpeed , tmBirth , fLife , fStretch , col ); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +} +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +Return(STATE_CURRENT,EReturn ()); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CFireworks:: +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CFireworks_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CFireworks::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +InitAsEditorModel (); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +SetModel (MODEL_MARKER ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +GetModelObject () -> StretchModel (FLOAT3D (4.0f , 4.0f , 4.0f)); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x02680003, FALSE, EBegin());return TRUE;}BOOL CFireworks::H0x02680003_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02680003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02680004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CFireworks::H0x02680004_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02680004 +; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_emEmiter . Initialize (this ); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +m_emEmiter . em_etType = ET_FIREWORKS01 ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x02680005, FALSE, EBegin());return TRUE;}BOOL CFireworks::H0x02680005_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02680005 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETrigger): +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +{const ETrigger&e= (ETrigger&)__eeInput; + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +Call(STATE_CURRENT, STATE_CFireworks_SpawnFireworks, TRUE, EVoid());return TRUE; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +}return TRUE;}BOOL CFireworks::H0x02680006_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02680006 + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +Return(STATE_CURRENT,EVoid()); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Fireworks.es b/Sources/EntitiesMP/Fireworks.es new file mode 100644 index 0000000..877ccf0 --- /dev/null +++ b/Sources/EntitiesMP/Fireworks.es @@ -0,0 +1,163 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +616 +%{ +#include "StdH.h" +#define RAND_05 (FLOAT(rand())/RAND_MAX-0.5f) +#define LAUNCH_SPEED 32.0f +%} + +class CFireworks : CRationalEntity { +name "Fireworks"; +thumbnail "Thumbnails\\Eruptor.tbn"; +features "IsTargetable", "HasName"; + +properties: + + 1 RANGE m_rRndRadius "Random radius" = 50.0f, + 10 CSoundObject m_soFly, + 11 CSoundObject m_soExplosion, + 12 FLOAT m_tmActivated=0.0f, + + 20 CTString m_strName "Name" 'N' ="", + + 50 FLOAT m_tmLastAnimation=0.0f, + +{ + CEmiter m_emEmiter; +} + +components: + + 1 model MODEL_MARKER "Models\\Editor\\Axis.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex", + 3 sound SOUND_FLY "SoundsMP\\Misc\\Whizz.wav", + 4 sound SOUND_EXPLODE "SoundsMP\\Misc\\Firecrackers.wav", + +functions: + void Read_t( CTStream *istr) // throw char * + { + CRationalEntity::Read_t(istr); + m_emEmiter.Read_t(*istr); + } + + void Write_t( CTStream *istr) // throw char * + { + CRationalEntity::Write_t(istr); + m_emEmiter.Write_t(*istr); + } + + void RenderParticles(void) + { + FLOAT tmNow = _pTimer->CurrentTick(); + if( tmNow>m_tmLastAnimation) + { + FLOAT fRatio=CalculateRatio(m_tmActivated-tmNow,0.0f,6.0f,1,0); + FLOAT fGPower=(Min(fRatio,0.5f)-0.5f)*2.0f*10.0f; + m_emEmiter.em_vG=FLOAT3D(0, fGPower, 0); + m_emEmiter.AnimateParticles(); + m_tmLastAnimation=tmNow; + + for(INDEX i=0; i=6.0f) + { + fSpeed=0.0f; + } + else + { + //fSpeed=(0.996f+0.387f*fLiving-0.158f*fLiving*fLiving)*LAUNCH_SPEED; + + fSpeed=(1.77f*pow(0.421f,fLiving))*LAUNCH_SPEED; + /* + FLOAT fSpeedRatio=1.0f-(Clamp(fLiving,2.0f,4.0f)-2.0f)/2.0f; + fSpeed=fSpeedRatio*LAUNCH_SPEED; + */ + } + FLOAT3D vNormalized=ep.ep_vSpeed; + vNormalized.Normalize(); + ep.ep_vSpeed=vNormalized*(4.0f+fSpeed); + } + } + m_emEmiter.RenderParticles(); + } + +procedures: + SpawnFireworks() + { + PlaySound(m_soFly, SOUND_FLY, 0); + autowait(GetSoundLength(SOUND_FLY)); + PlaySound(m_soExplosion, SOUND_EXPLODE, 0); + + // add emited firework sparks + FLOAT3D vRndPos=FLOAT3D( RAND_05, RAND_05, RAND_05)*m_rRndRadius; + FLOAT3D vPos=GetPlacement().pl_PositionVector+vRndPos; + + m_emEmiter.em_vG=FLOAT3D(0,0,0); + m_emEmiter.em_iGlobal=FRnd()*16; + + UBYTE ubRndH = UBYTE( FRnd()*255); + UBYTE ubRndS = UBYTE( 255); + UBYTE ubRndV = UBYTE( 255); + m_emEmiter.em_colGlobal=C_WHITE|CT_OPAQUE;//HSVToColor(ubRndH, ubRndS, ubRndV)|CT_OPAQUE; + + FLOAT tmNow = _pTimer->CurrentTick(); + m_tmActivated=tmNow; + INDEX ctSparks=128; + for( INDEX iSpark=0; iSparkTickQuantum/ctSparks*2.0f; + FLOAT fLife=4.0f+RAND_05*2.0f; + FLOAT fStretch=(1.0f+RAND_05*0.25f)*2.5f; + FLOAT3D vSpeed=FLOAT3D( RAND_05, RAND_05, RAND_05); + vSpeed=vSpeed.Normalize()*LAUNCH_SPEED; + FLOAT fRotSpeed=RAND_05*360.0f; + + /* + UBYTE ubRndH = UBYTE( FRnd()*16); + UBYTE ubRndS = UBYTE( 255); + UBYTE ubRndV = UBYTE( 255); + COLOR col=HSVToColor(ubRndH, ubRndS, ubRndV)|CT_OPAQUE; + */ + COLOR col=C_WHITE|CT_OPAQUE; + m_emEmiter.AddParticle(vPos, vSpeed, RAND_05*360.0f, fRotSpeed, tmBirth, fLife, fStretch, col); + } + return EReturn(); + } + + Main() + { + // init model + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + GetModelObject()->StretchModel(FLOAT3D(4.0f, 4.0f, 4.0f)); + + autowait(_pTimer->TickQuantum); + + m_emEmiter.Initialize(this); + m_emEmiter.em_etType=ET_FIREWORKS01; + + // wait to be triggered + wait() { + on (EBegin) : { resume; } + on (ETrigger) : + { + call SpawnFireworks(); + } + otherwise (): { resume; } + } + + return; + } +}; + diff --git a/Sources/EntitiesMP/Fireworks.h b/Sources/EntitiesMP/Fireworks.h new file mode 100644 index 0000000..8e65963 --- /dev/null +++ b/Sources/EntitiesMP/Fireworks.h @@ -0,0 +1,44 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Fireworks_INCLUDED +#define _EntitiesMP_Fireworks_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CFireworks_DLLClass; +class CFireworks : public CRationalEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; + DECL_DLL virtual void SetDefaultProperties(void); + RANGE m_rRndRadius; + CSoundObject m_soFly; + CSoundObject m_soExplosion; + FLOAT m_tmActivated; + CTString m_strName; + FLOAT m_tmLastAnimation; +CEmiter m_emEmiter; + +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +void Read_t(CTStream * istr); + +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +void Write_t(CTStream * istr); + +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +void RenderParticles(void); +#define STATE_CFireworks_SpawnFireworks 0x02680000 + BOOL +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +SpawnFireworks(const CEntityEvent &__eeInput); + BOOL H0x02680001_SpawnFireworks_01(const CEntityEvent &__eeInput); + BOOL H0x02680002_SpawnFireworks_02(const CEntityEvent &__eeInput); +#define STATE_CFireworks_Main 1 + BOOL +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x02680003_Main_01(const CEntityEvent &__eeInput); + BOOL H0x02680004_Main_02(const CEntityEvent &__eeInput); + BOOL H0x02680005_Main_03(const CEntityEvent &__eeInput); + BOOL H0x02680006_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Fireworks_INCLUDED diff --git a/Sources/EntitiesMP/Fireworks_tables.h b/Sources/EntitiesMP/Fireworks_tables.h new file mode 100644 index 0000000..b16eb57 --- /dev/null +++ b/Sources/EntitiesMP/Fireworks_tables.h @@ -0,0 +1,54 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CFireworks + +CEntityProperty CFireworks_properties[] = { + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000268<<8)+1, offsetof(CFireworks, m_rRndRadius), "Random radius", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000268<<8)+10, offsetof(CFireworks, m_soFly), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000268<<8)+11, offsetof(CFireworks, m_soExplosion), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000268<<8)+12, offsetof(CFireworks, m_tmActivated), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000268<<8)+20, offsetof(CFireworks, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000268<<8)+50, offsetof(CFireworks, m_tmLastAnimation), "", 0, 0, 0), +}; +#define CFireworks_propertiesct ARRAYCOUNT(CFireworks_properties) + +CEntityComponent CFireworks_components[] = { +#define MODEL_MARKER ((0x00000268<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_MARKER ((0x00000268<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Vector.tex"), +#define SOUND_FLY ((0x00000268<<8)+3) + CEntityComponent(ECT_SOUND, SOUND_FLY, "EFNM" "SoundsMP\\Misc\\Whizz.wav"), +#define SOUND_EXPLODE ((0x00000268<<8)+4) + CEntityComponent(ECT_SOUND, SOUND_EXPLODE, "EFNM" "SoundsMP\\Misc\\Firecrackers.wav"), +}; +#define CFireworks_componentsct ARRAYCOUNT(CFireworks_components) + +CEventHandlerEntry CFireworks_handlers[] = { + {0x02680000, -1, CEntity::pEventHandler(&CFireworks:: +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +SpawnFireworks),DEBUGSTRING("CFireworks::SpawnFireworks")}, + {0x02680001, -1, CEntity::pEventHandler(&CFireworks::H0x02680001_SpawnFireworks_01), DEBUGSTRING("CFireworks::H0x02680001_SpawnFireworks_01")}, + {0x02680002, -1, CEntity::pEventHandler(&CFireworks::H0x02680002_SpawnFireworks_02), DEBUGSTRING("CFireworks::H0x02680002_SpawnFireworks_02")}, + {1, -1, CEntity::pEventHandler(&CFireworks:: +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Fireworks.es" +Main),DEBUGSTRING("CFireworks::Main")}, + {0x02680003, -1, CEntity::pEventHandler(&CFireworks::H0x02680003_Main_01), DEBUGSTRING("CFireworks::H0x02680003_Main_01")}, + {0x02680004, -1, CEntity::pEventHandler(&CFireworks::H0x02680004_Main_02), DEBUGSTRING("CFireworks::H0x02680004_Main_02")}, + {0x02680005, -1, CEntity::pEventHandler(&CFireworks::H0x02680005_Main_03), DEBUGSTRING("CFireworks::H0x02680005_Main_03")}, + {0x02680006, -1, CEntity::pEventHandler(&CFireworks::H0x02680006_Main_04), DEBUGSTRING("CFireworks::H0x02680006_Main_04")}, +}; +#define CFireworks_handlersct ARRAYCOUNT(CFireworks_handlers) + +CEntity *CFireworks_New(void) { return new CFireworks; }; +void CFireworks_OnInitClass(void) {}; +void CFireworks_OnEndClass(void) {}; +void CFireworks_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CFireworks_OnWorldEnd(CWorld *pwo) {}; +void CFireworks_OnWorldInit(CWorld *pwo) {}; +void CFireworks_OnWorldTick(CWorld *pwo) {}; +void CFireworks_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CFireworks, CRationalEntity, "Fireworks", "Thumbnails\\Eruptor.tbn", 0x00000268); +DECLARE_CTFILENAME(_fnmCFireworks_tbn, "Thumbnails\\Eruptor.tbn"); diff --git a/Sources/EntitiesMP/Fish.cpp b/Sources/EntitiesMP/Fish.cpp new file mode 100644 index 0000000..4e0e4fa --- /dev/null +++ b/Sources/EntitiesMP/Fish.cpp @@ -0,0 +1,524 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" + +#include "StdH.h" +#include "Models/Enemies/Fish/Fish.h" + +#include +#include +#line 11 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" + +static EntityInfo eiFish = { + EIBT_FLESH, 100.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, +}; + +#define DISTANCE_ELECTRICITY 8.0f + +void CFish::SetDefaultProperties(void) { + m_bAttackingByElectricity = FALSE ; + m_tmElectricityTimeStart = 0.0f; + CEnemyDive::SetDefaultProperties(); +} + CTString CFish::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +CTString str ; +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +str . PrintF (TRANS ("%s was electrocuted by a fish") , strPlayerName ); +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +return str ; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + const CTFileName & CFish::GetComputerMessageName(void)const { +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +static DECLARE_CTFILENAME (fnm , "Data\\Messages\\Enemies\\Fish.txt"); +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +return fnm ; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::Precache(void) { +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +CEnemyBase :: Precache (); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PrecacheModel (MODEL_GLOW ); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PrecacheTexture (TEXTURE_GLOW ); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PrecacheSound (SOUND_IDLE ); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PrecacheSound (SOUND_SIGHT ); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PrecacheSound (SOUND_WOUND ); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PrecacheSound (SOUND_DEATH ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PrecacheSound (SOUND_WOUNDAIR ); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PrecacheSound (SOUND_DEATHAIR ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PrecacheSound (SOUND_ATTACK ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void * CFish::GetEntityInfo(void) +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +return & eiFish ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +if(dmtType == DMT_DROWNING ){ +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +fDamageAmmount /= 2.0f; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +if(! IsOfClass (penInflictor , "Fish")){ +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +CEnemyDive :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +INDEX CFish::AnimForDamage(FLOAT fDamage) +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_bAttackingByElectricity = FALSE ; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +INDEX iAnim = FISH_ANIM_WOUND ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +StartModelAnim (iAnim , 0); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +return iAnim ; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +INDEX CFish::AnimForDeath(void) { +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +if(! m_bInLiquid ){ +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +return AnimForDamage (10.0f); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +INDEX iAnim ; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +switch(IRnd () % 3){ +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +default : iAnim = FISH_ANIM_DEATH ;break ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +case 0: iAnim = FISH_ANIM_DEATH ;break ; +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +case 1: iAnim = FISH_ANIM_DEATH02 ;break ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +case 2: iAnim = FISH_ANIM_DEATH03 ;break ; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +StartModelAnim (iAnim , 0); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +return iAnim ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::DeathNotify(void) +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_bAttackingByElectricity = FALSE ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +en_fDensity = 500.0f; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::RenderParticles(void) +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +if(m_bAttackingByElectricity && m_penEnemy != NULL ) +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT3D vSource = GetPlacement () . pl_PositionVector ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT3D vTarget = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT3D vDirection = (vTarget - vSource ) . Normalize (); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Particles_Ghostbuster (vSource , vTarget , 32 , 1.0f); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +for(INDEX i = 0;i < 4;i ++) +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT3D vDirection = vSource ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +vDirection (1) += ((FLOAT (rand ()) / RAND_MAX ) - 0.5f) * DISTANCE_ELECTRICITY / 1.0f; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +vDirection (2) += ((FLOAT (rand ()) / RAND_MAX ) - 0.5f) * DISTANCE_ELECTRICITY / 1.0f; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +vDirection (3) += ((FLOAT (rand ()) / RAND_MAX ) - 0.5f) * DISTANCE_ELECTRICITY / 1.0f; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Particles_Ghostbuster (vSource , vDirection , 32 , 1.0f); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +CEnemyBase :: RenderParticles (); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::StandingAnim(void) +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +StartModelAnim (FISH_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::WalkingAnim(void) +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +if(m_bInLiquid ){ +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +StartModelAnim (FISH_ANIM_SWIM , AOF_LOOPING | AOF_NORESTART ); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +}else { +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +StartModelAnim (FISH_ANIM_WOUND , AOF_LOOPING | AOF_NORESTART ); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::RunningAnim(void) +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +WalkingAnim (); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::RotatingAnim(void) +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +WalkingAnim (); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::IdleSound(void) +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D | SOF_NOFILTER ); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::SightSound(void) +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D | SOF_NOFILTER ); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::WoundSound(void) +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +if(m_bInLiquid ){ +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D | SOF_NOFILTER ); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +}else { +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PlaySound (m_soSound , SOUND_WOUNDAIR , SOF_3D | SOF_NOFILTER ); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void CFish::DeathSound(void) +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +if(m_bInLiquid ){ +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D | SOF_NOFILTER ); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +}else { +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PlaySound (m_soSound , SOUND_DEATHAIR , SOF_3D | SOF_NOFILTER ); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} + +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +BOOL CFish::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT fTimePassed = _pTimer -> GetLerpedCurrentTick () - m_tmElectricityTimeStart ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +if(m_bAttackingByElectricity && (fTimePassed > 0)) +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT fDieFactor = 1.0f; +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +if(fTimePassed > 0.25f) +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +fDieFactor = 1.0 - (ClampUp (fTimePassed - 0.25f , 0.5f) / 0.5f); +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT fR = 0.7f + 0.1f * (FLOAT (rand ()) / RAND_MAX ); +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT fG = 0.7f + 0.2f * (FLOAT (rand ()) / RAND_MAX ); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT fB = 0.7f + 0.3f * (FLOAT (rand ()) / RAND_MAX ); +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +colAmbient = RGBToColor (fR * 128 * fDieFactor , fG * 128 * fDieFactor , fB * 128 * fDieFactor ); +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +colLight = C_WHITE ; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +return CEnemyBase :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +return CEnemyBase :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +BOOL CFish:: +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +DiveHit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CFish_DiveHit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CFish::DiveHit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +if(CalcDist (m_penEnemy ) > DISTANCE_ELECTRICITY ) +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fShootTime = _pTimer -> CurrentTick () + 0.25f; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Return(STATE_CURRENT,EReturn ()); +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +return TRUE; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +SetTimerAfter(0.6f); +Jump(STATE_CURRENT, 0x01510001, FALSE, EBegin());return TRUE;}BOOL CFish::H0x01510001_DiveHit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01510001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01510002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CFish::H0x01510002_DiveHit_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01510002 +; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_bAttackingByElectricity = TRUE ; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_tmElectricityTimeStart = _pTimer -> CurrentTick (); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +AddAttachmentToModel (this , * GetModelObject () , FISH_ATTACHMENT_GLOW , MODEL_GLOW , TEXTURE_GLOW , 0 , 0 , 0); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +CModelObject & moGlow = GetModelObject () -> GetAttachmentModel (FISH_ATTACHMENT_GLOW ) -> amo_moModelObject ; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +moGlow . StretchModel (FLOAT3D (4.0f , 4.0f , 4.0f)); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +StartModelAnim (FISH_ANIM_ATTACK , 0); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +PlaySound (m_soSound , SOUND_ATTACK , SOF_3D | SOF_NOFILTER ); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +if(CalcDist (m_penEnemy ) < DISTANCE_ELECTRICITY ) +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +InflictRangeDamage (this , DMT_CLOSERANGE , 15.0f , GetPlacement () . pl_PositionVector , 1.0f , DISTANCE_ELECTRICITY ); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT3D vSpeed ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +GetHeadingDirection (0.0f , vSpeed ); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +vSpeed = vSpeed * 30.0f; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +KickEntity (m_penEnemy , vSpeed ); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x01510003, FALSE, EBegin());return TRUE;}BOOL CFish::H0x01510003_DiveHit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01510003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01510004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CFish::H0x01510004_DiveHit_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01510004 +; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_bAttackingByElectricity = FALSE ; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +GetModelObject () -> RemoveAttachmentModel (FISH_ATTACHMENT_GLOW ); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +StandingAnim (); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +SetTimerAfter(0.2f + FRnd () / 3); +Jump(STATE_CURRENT, 0x01510005, FALSE, EBegin());return TRUE;}BOOL CFish::H0x01510005_DiveHit_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01510005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01510006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CFish::H0x01510006_DiveHit_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01510006 +; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Return(STATE_CURRENT,EReturn ()); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CFish:: +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CFish_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CFish::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Jump(STATE_CURRENT, STATE_CFish_DiveHit, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CFish:: +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CFish_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CFish::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +InitAsModel (); +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +SetPhysicsFlags ((EPF_MODEL_WALKING | EPF_HASGILLS ) & ~ EPF_ONBLOCK_CLIMBORSLIDE | EPF_ONBLOCK_SLIDE ); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +SetCollisionFlags (ECF_MODEL ); +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +SetHealth (30.0f); +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fMaxHealth = 30.0f; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +en_tmMaxHoldBreath = 15.0f; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +en_fDensity = 1000.0f; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_EedtType = EDT_GROUND_DIVE ; +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +SetModel (MODEL_FISH ); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +SetModelMainTexture (TEXTURE_FISH ); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +SetModelSpecularTexture (TEXTURE_SPECULAR ); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fDiveWalkSpeed = 15.0f; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fDiveAttackRunSpeed = 20.0f; +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fDiveCloseRunSpeed = 25.0f; +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fWalkSpeed = 15.0f; +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_aWalkRotateSpeed = 900.0f; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fAttackRunSpeed = 10.0f; +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fCloseRunSpeed = 12.0f; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_aDiveWalkRotateSpeed = 360.0f; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_aDiveAttackRotateSpeed = 1800.0f; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_aDiveCloseRotateSpeed = 3600.0f; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fDiveIgnoreRange = 200.0f; +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fDiveAttackDistance = 100.0f; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fDiveCloseDistance = 15.0f; +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fDiveStopDistance = 2.0f; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fDiveAttackFireTime = 0.0f; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fDiveCloseFireTime = 0.0f; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fBlowUpAmount = 80.0f; +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fBodyParts = 2; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fDamageWounded = 1.0f; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_iScore = 500; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +{ +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_aWalkRotateSpeed = 360.0f; +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_aAttackRotateSpeed = 1800.0f; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_aCloseRotateSpeed = 3600.0f; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fIgnoreRange = 200.0f; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fAttackDistance = 100.0f; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fCloseDistance = 15.0f; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fStopDistance = 2.0f; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fAttackFireTime = 0.0f; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +m_fCloseFireTime = 0.0f; +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +} +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +GetModelObject () -> StretchModel (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +ModelChangeNotify (); +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +en_fAcceleration = 200.0f; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +en_fDeceleration = 200.0f; +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Jump(STATE_CURRENT, STATE_CEnemyDive_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Fish.es b/Sources/EntitiesMP/Fish.es new file mode 100644 index 0000000..8500336 --- /dev/null +++ b/Sources/EntitiesMP/Fish.es @@ -0,0 +1,337 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +337 +%{ +#include "StdH.h" +#include "Models/Enemies/Fish/Fish.h" +%} + +uses "EntitiesMP/EnemyDive"; + +%{ +static EntityInfo eiFish = { + EIBT_FLESH, 100.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, +}; + +#define DISTANCE_ELECTRICITY 8.0f +%} + +class CFish : CEnemyDive { +name "Fish"; +thumbnail "Thumbnails\\Fish.tbn"; + +properties: + 0 BOOL m_bAttackingByElectricity = FALSE, + 1 FLOAT m_tmElectricityTimeStart = 0.0f, + +components: + 0 class CLASS_BASE "Classes\\EnemyDive.ecl", + 1 model MODEL_FISH "Models\\Enemies\\Fish\\Fish.mdl", + 2 texture TEXTURE_FISH "Models\\Enemies\\Fish\\Fish1.tex", + 3 model MODEL_GLOW "Models\\Enemies\\Fish\\Glow.mdl", + 4 texture TEXTURE_GLOW "Models\\Enemies\\Fish\\Glow.tex", + 5 texture TEXTURE_SPECULAR "Models\\SpecularTextures\\Medium.tex", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "Models\\Enemies\\Fish\\Sounds\\Idle.wav", + 51 sound SOUND_SIGHT "Models\\Enemies\\Fish\\Sounds\\Sight.wav", + 52 sound SOUND_WOUND "Models\\Enemies\\Fish\\Sounds\\Wound.wav", + 53 sound SOUND_DEATH "Models\\Enemies\\Fish\\Sounds\\Death.wav", + 54 sound SOUND_ATTACK "Models\\Enemies\\Fish\\Sounds\\Attack.wav", + 55 sound SOUND_WOUNDAIR "Models\\Enemies\\Fish\\Sounds\\WoundAir.wav", + 56 sound SOUND_DEATHAIR "Models\\Enemies\\Fish\\Sounds\\DeathAir.wav", + +functions: + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("%s was electrocuted by a fish"), strPlayerName); + return str; + } + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnm, "Data\\Messages\\Enemies\\Fish.txt"); + return fnm; + }; + void Precache(void) { + CEnemyBase::Precache(); + PrecacheModel(MODEL_GLOW ); + PrecacheTexture(TEXTURE_GLOW); + PrecacheSound(SOUND_IDLE); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_DEATH); + PrecacheSound(SOUND_WOUNDAIR); + PrecacheSound(SOUND_DEATHAIR); + PrecacheSound(SOUND_ATTACK); + }; + + /* Entity info */ + void *GetEntityInfo(void) + { + return &eiFish; + }; + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + if (dmtType==DMT_DROWNING) { + //en_tmMaxHoldBreath = -5.0f; + fDamageAmmount/=2.0f; + } + // fish can't harm fish + if (!IsOfClass(penInflictor, "Fish")) { + CEnemyDive::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + }; + + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) + { + m_bAttackingByElectricity = FALSE; + INDEX iAnim = FISH_ANIM_WOUND; + StartModelAnim(iAnim, 0); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + if (!m_bInLiquid) { + return AnimForDamage(10.0f); + } + INDEX iAnim; + switch (IRnd()%3) { + default: iAnim = FISH_ANIM_DEATH; break; + case 0: iAnim = FISH_ANIM_DEATH; break; + case 1: iAnim = FISH_ANIM_DEATH02; break; + case 2: iAnim = FISH_ANIM_DEATH03; break; + } + StartModelAnim(iAnim, 0); + return iAnim; + }; + + void DeathNotify(void) + { + m_bAttackingByElectricity = FALSE; + en_fDensity = 500.0f; + }; + + void RenderParticles(void) + { + if( m_bAttackingByElectricity && m_penEnemy!=NULL) + { + // render one lightning toward enemy + FLOAT3D vSource = GetPlacement().pl_PositionVector; + FLOAT3D vTarget = m_penEnemy->GetPlacement().pl_PositionVector; + FLOAT3D vDirection = (vTarget-vSource).Normalize(); + Particles_Ghostbuster(vSource, vTarget, 32, 1.0f); + + // random lightnings arround + for( INDEX i=0; i<4; i++) + { + FLOAT3D vDirection = vSource; + vDirection(1) += ((FLOAT(rand())/RAND_MAX)-0.5f) * DISTANCE_ELECTRICITY/1.0f; + vDirection(2) += ((FLOAT(rand())/RAND_MAX)-0.5f) * DISTANCE_ELECTRICITY/1.0f; + vDirection(3) += ((FLOAT(rand())/RAND_MAX)-0.5f) * DISTANCE_ELECTRICITY/1.0f; + Particles_Ghostbuster(vSource, vDirection, 32, 1.0f); + } + } + CEnemyBase::RenderParticles(); + } + // virtual anim functions + void StandingAnim(void) + { + StartModelAnim(FISH_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + void WalkingAnim(void) + { + if (m_bInLiquid) { + StartModelAnim(FISH_ANIM_SWIM, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(FISH_ANIM_WOUND, AOF_LOOPING|AOF_NORESTART); + } + }; + void RunningAnim(void) + { + WalkingAnim(); + }; + void RotatingAnim(void) + { + WalkingAnim(); + }; + + // virtual sound functions + void IdleSound(void) + { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D|SOF_NOFILTER); + }; + void SightSound(void) + { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D|SOF_NOFILTER); + }; + void WoundSound(void) + { + if (m_bInLiquid) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D|SOF_NOFILTER); + } else { + PlaySound(m_soSound, SOUND_WOUNDAIR, SOF_3D|SOF_NOFILTER); + } + }; + void DeathSound(void) + { + if (m_bInLiquid) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D|SOF_NOFILTER); + } else { + PlaySound(m_soSound, SOUND_DEATHAIR, SOF_3D|SOF_NOFILTER); + } + }; + + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + FLOAT fTimePassed = _pTimer->GetLerpedCurrentTick()-m_tmElectricityTimeStart; + if( m_bAttackingByElectricity && (fTimePassed>0)) + { + FLOAT fDieFactor = 1.0f; + if( fTimePassed > 0.25f) + { + // calculate light dying factor + fDieFactor = 1.0-(ClampUp(fTimePassed-0.25f,0.5f)/0.5f); + } + // adjust light fx + FLOAT fR = 0.7f+0.1f*(FLOAT(rand())/RAND_MAX); + FLOAT fG = 0.7f+0.2f*(FLOAT(rand())/RAND_MAX); + FLOAT fB = 0.7f+0.3f*(FLOAT(rand())/RAND_MAX); + colAmbient = RGBToColor( fR*128*fDieFactor, fG*128*fDieFactor, fB*128*fDieFactor); + colLight = C_WHITE; + return CEnemyBase::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + } + return CEnemyBase::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + }; + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + DiveHit(EVoid) : CEnemyDive::DiveHit + { + if (CalcDist(m_penEnemy) > DISTANCE_ELECTRICITY) + { + // swim to enemy + m_fShootTime = _pTimer->CurrentTick() + 0.25f; + return EReturn(); + } + + // wait to allow enemy to go aoutside bite range + autowait(0.6f); + + m_bAttackingByElectricity = TRUE; + m_tmElectricityTimeStart = _pTimer->CurrentTick(); + + AddAttachmentToModel(this, *GetModelObject(), FISH_ATTACHMENT_GLOW, MODEL_GLOW, TEXTURE_GLOW, 0, 0, 0); + CModelObject &moGlow = GetModelObject()->GetAttachmentModel(FISH_ATTACHMENT_GLOW)->amo_moModelObject; + moGlow.StretchModel(FLOAT3D(4.0f, 4.0f, 4.0f)); + + // bite + StartModelAnim(FISH_ANIM_ATTACK, 0); + PlaySound(m_soSound, SOUND_ATTACK, SOF_3D|SOF_NOFILTER); + if (CalcDist(m_penEnemy)RemoveAttachmentModel(FISH_ATTACHMENT_GLOW); + + StandingAnim(); + autowait(0.2f + FRnd()/3); + return EReturn(); + }; + + Hit(EVoid) : CEnemyBase::Hit + { + jump DiveHit(); + } + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + // fish must not go upstairs, or it will get out of water + SetPhysicsFlags((EPF_MODEL_WALKING|EPF_HASGILLS)&~EPF_ONBLOCK_CLIMBORSLIDE|EPF_ONBLOCK_SLIDE); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + SetHealth(30.0f); + m_fMaxHealth = 30.0f; + en_tmMaxHoldBreath = 15.0f; + en_fDensity = 1000.0f; + m_EedtType = EDT_GROUND_DIVE; + + // set your appearance + SetModel(MODEL_FISH); + SetModelMainTexture(TEXTURE_FISH); + SetModelSpecularTexture(TEXTURE_SPECULAR); + // rotation speeds + m_fDiveWalkSpeed = 15.0f; + m_fDiveAttackRunSpeed = 20.0f; + m_fDiveCloseRunSpeed = 25.0f; + + m_fWalkSpeed = 15.0f; + m_aWalkRotateSpeed = 900.0f; + m_fAttackRunSpeed = 10.0f; + m_fCloseRunSpeed = 12.0f; + // translation speeds + m_aDiveWalkRotateSpeed = 360.0f; + m_aDiveAttackRotateSpeed = 1800.0f; + m_aDiveCloseRotateSpeed = 3600.0f; + // distances + m_fDiveIgnoreRange = 200.0f; + m_fDiveAttackDistance = 100.0f; + m_fDiveCloseDistance = 15.0f; + m_fDiveStopDistance = 2.0f; + // frequencies + m_fDiveAttackFireTime = 0.0f; + m_fDiveCloseFireTime = 0.0f; + // damage/explode properties + m_fBlowUpAmount = 80.0f; + m_fBodyParts = 2; + m_fDamageWounded = 1.0f; + m_iScore = 500; + + { + // translation speeds + m_aWalkRotateSpeed = 360.0f; + m_aAttackRotateSpeed = 1800.0f; + m_aCloseRotateSpeed = 3600.0f; + // distances + m_fIgnoreRange = 200.0f; + m_fAttackDistance = 100.0f; + m_fCloseDistance = 15.0f; + m_fStopDistance = 2.0f; + // frequencies + m_fAttackFireTime = 0.0f; + m_fCloseFireTime = 0.0f; + } + // set stretch factors for height and width + GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f)); + ModelChangeNotify(); + + en_fAcceleration = 200.0f; + en_fDeceleration = 200.0f; + + // continue behavior in base class + jump CEnemyDive::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Fish.h b/Sources/EntitiesMP/Fish.h new file mode 100644 index 0000000..8e5b750 --- /dev/null +++ b/Sources/EntitiesMP/Fish.h @@ -0,0 +1,89 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Fish_INCLUDED +#define _EntitiesMP_Fish_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CFish_DLLClass; +class CFish : public CEnemyDive { +public: + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bAttackingByElectricity; + FLOAT m_tmElectricityTimeStart; + +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void Precache(void); + +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void * GetEntityInfo(void); + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +INDEX AnimForDeath(void); + +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void DeathNotify(void); + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void RenderParticles(void); + +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void StandingAnim(void); + +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void WalkingAnim(void); + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void RunningAnim(void); + +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void RotatingAnim(void); + +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void IdleSound(void); + +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void SightSound(void); + +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void WoundSound(void); + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +void DeathSound(void); + +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); +#define STATE_CFish_DiveHit 0x01510000 + BOOL +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +DiveHit(const CEntityEvent &__eeInput); + BOOL H0x01510001_DiveHit_01(const CEntityEvent &__eeInput); + BOOL H0x01510002_DiveHit_02(const CEntityEvent &__eeInput); + BOOL H0x01510003_DiveHit_03(const CEntityEvent &__eeInput); + BOOL H0x01510004_DiveHit_04(const CEntityEvent &__eeInput); + BOOL H0x01510005_DiveHit_05(const CEntityEvent &__eeInput); + BOOL H0x01510006_DiveHit_06(const CEntityEvent &__eeInput); +#define STATE_CFish_Hit 0x01510007 + BOOL +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Hit(const CEntityEvent &__eeInput); +#define STATE_CFish_Main 1 + BOOL +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Fish_INCLUDED diff --git a/Sources/EntitiesMP/Fish_tables.h b/Sources/EntitiesMP/Fish_tables.h new file mode 100644 index 0000000..48b4c51 --- /dev/null +++ b/Sources/EntitiesMP/Fish_tables.h @@ -0,0 +1,71 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CFish + +CEntityProperty CFish_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000151<<8)+0, offsetof(CFish, m_bAttackingByElectricity), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000151<<8)+1, offsetof(CFish, m_tmElectricityTimeStart), "", 0, 0, 0), +}; +#define CFish_propertiesct ARRAYCOUNT(CFish_properties) + +CEntityComponent CFish_components[] = { +#define CLASS_BASE ((0x00000151<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyDive.ecl"), +#define MODEL_FISH ((0x00000151<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_FISH, "EFNM" "Models\\Enemies\\Fish\\Fish.mdl"), +#define TEXTURE_FISH ((0x00000151<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_FISH, "EFNM" "Models\\Enemies\\Fish\\Fish1.tex"), +#define MODEL_GLOW ((0x00000151<<8)+3) + CEntityComponent(ECT_MODEL, MODEL_GLOW, "EFNM" "Models\\Enemies\\Fish\\Glow.mdl"), +#define TEXTURE_GLOW ((0x00000151<<8)+4) + CEntityComponent(ECT_TEXTURE, TEXTURE_GLOW, "EFNM" "Models\\Enemies\\Fish\\Glow.tex"), +#define TEXTURE_SPECULAR ((0x00000151<<8)+5) + CEntityComponent(ECT_TEXTURE, TEXTURE_SPECULAR, "EFNM" "Models\\SpecularTextures\\Medium.tex"), +#define SOUND_IDLE ((0x00000151<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "Models\\Enemies\\Fish\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000151<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "Models\\Enemies\\Fish\\Sounds\\Sight.wav"), +#define SOUND_WOUND ((0x00000151<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "Models\\Enemies\\Fish\\Sounds\\Wound.wav"), +#define SOUND_DEATH ((0x00000151<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "Models\\Enemies\\Fish\\Sounds\\Death.wav"), +#define SOUND_ATTACK ((0x00000151<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_ATTACK, "EFNM" "Models\\Enemies\\Fish\\Sounds\\Attack.wav"), +#define SOUND_WOUNDAIR ((0x00000151<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_WOUNDAIR, "EFNM" "Models\\Enemies\\Fish\\Sounds\\WoundAir.wav"), +#define SOUND_DEATHAIR ((0x00000151<<8)+56) + CEntityComponent(ECT_SOUND, SOUND_DEATHAIR, "EFNM" "Models\\Enemies\\Fish\\Sounds\\DeathAir.wav"), +}; +#define CFish_componentsct ARRAYCOUNT(CFish_components) + +CEventHandlerEntry CFish_handlers[] = { + {0x01510000, STATE_CEnemyDive_DiveHit, CEntity::pEventHandler(&CFish:: +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +DiveHit),DEBUGSTRING("CFish::DiveHit")}, + {0x01510001, -1, CEntity::pEventHandler(&CFish::H0x01510001_DiveHit_01), DEBUGSTRING("CFish::H0x01510001_DiveHit_01")}, + {0x01510002, -1, CEntity::pEventHandler(&CFish::H0x01510002_DiveHit_02), DEBUGSTRING("CFish::H0x01510002_DiveHit_02")}, + {0x01510003, -1, CEntity::pEventHandler(&CFish::H0x01510003_DiveHit_03), DEBUGSTRING("CFish::H0x01510003_DiveHit_03")}, + {0x01510004, -1, CEntity::pEventHandler(&CFish::H0x01510004_DiveHit_04), DEBUGSTRING("CFish::H0x01510004_DiveHit_04")}, + {0x01510005, -1, CEntity::pEventHandler(&CFish::H0x01510005_DiveHit_05), DEBUGSTRING("CFish::H0x01510005_DiveHit_05")}, + {0x01510006, -1, CEntity::pEventHandler(&CFish::H0x01510006_DiveHit_06), DEBUGSTRING("CFish::H0x01510006_DiveHit_06")}, + {0x01510007, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CFish:: +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Hit),DEBUGSTRING("CFish::Hit")}, + {1, -1, CEntity::pEventHandler(&CFish:: +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Fish.es" +Main),DEBUGSTRING("CFish::Main")}, +}; +#define CFish_handlersct ARRAYCOUNT(CFish_handlers) + +CEntity *CFish_New(void) { return new CFish; }; +void CFish_OnInitClass(void) {}; +void CFish_OnEndClass(void) {}; +void CFish_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CFish_OnWorldEnd(CWorld *pwo) {}; +void CFish_OnWorldInit(CWorld *pwo) {}; +void CFish_OnWorldTick(CWorld *pwo) {}; +void CFish_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CFish, CEnemyDive, "Fish", "Thumbnails\\Fish.tbn", 0x00000151); +DECLARE_CTFILENAME(_fnmCFish_tbn, "Thumbnails\\Fish.tbn"); diff --git a/Sources/EntitiesMP/Flame.cpp b/Sources/EntitiesMP/Flame.cpp new file mode 100644 index 0000000..d630629 --- /dev/null +++ b/Sources/EntitiesMP/Flame.cpp @@ -0,0 +1,531 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" + +#include "StdH.h" +#define TM_APPLY_DAMAGE_QUANTUM 0.25f +#define TM_APPLY_WHOLE_DAMAGE 7.5f +#define DAMAGE_AMMOUNT 30.0f +#define MIN_DAMAGE_QUANTUM (DAMAGE_AMMOUNT/TM_APPLY_WHOLE_DAMAGE*TM_APPLY_DAMAGE_QUANTUM) +#define MAX_DAMAGE_QUANTUM (MIN_DAMAGE_QUANTUM*10.0f) +#define DEATH_BURN_TIME 4.0f + +#include "EntitiesMP/MovingBrush.h" + +#include +#include +CEntityEvent *EFlame::MakeCopy(void) { CEntityEvent *peeCopy = new EFlame(*this); return peeCopy;} +EFlame::EFlame() : CEntityEvent(EVENTCODE_EFlame) {; + ClearToDefault(penOwner); + ClearToDefault(penAttach); +}; +CEntityEvent *EStopFlaming::MakeCopy(void) { CEntityEvent *peeCopy = new EStopFlaming(*this); return peeCopy;} +EStopFlaming::EStopFlaming() : CEntityEvent(EVENTCODE_EStopFlaming) {; + ClearToDefault(m_bNow); +}; +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" + +void CFlame_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + pdec->PrecacheModel(MODEL_FLAME); + pdec->PrecacheTexture(TEXTURE_FLAME); + pdec->PrecacheSound(SOUND_FLAME); +} + +void CFlame::SetDefaultProperties(void) { + m_penOwner = NULL; + m_penAttach = NULL; + m_bLoop = FALSE ; + m_vHitPoint = FLOAT3D(0.0f , 0.0f , 0.0f); + m_soEffect.SetOwner(this); +m_soEffect.Stop_internal(); + m_tmStart = 0.0f; + m_fDamageToApply = 0.0f; + m_fDamageStep = 0.0f; + m_fAppliedDamage = 0.0f; + m_tmFirstStart = 0.0f; + m_ctFlames = 0; + m_vPos01 = FLOAT3D(0 , 0 , 0); + m_vPos02 = FLOAT3D(0 , 0 , 0); + m_vPos03 = FLOAT3D(0 , 0 , 0); + m_vPos04 = FLOAT3D(0 , 0 , 0); + m_vPos05 = FLOAT3D(0 , 0 , 0); + m_vPos06 = FLOAT3D(0 , 0 , 0); + m_vPos07 = FLOAT3D(0 , 0 , 0); + m_vPos08 = FLOAT3D(0 , 0 , 0); + m_vPos09 = FLOAT3D(0 , 0 , 0); + m_vPos10 = FLOAT3D(0 , 0 , 0); + m_vPlaneNormal = FLOAT3D(0 , 0 , 0); + m_bBurningBrush = FALSE ; + m_tmDeathParticlesStart = 1e6; + m_penPrediction = NULL; + CMovableModelEntity::SetDefaultProperties(); +} + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +void CFlame::AddDependentsToPrediction(void) +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_penOwner -> AddToPrediction (); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +void CFlame::PostMoving(void) { +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +CMovableModelEntity :: PostMoving (); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +CContentType & ctDn = GetWorld () -> wo_actContentTypes [ en_iDnContent ]; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(! (ctDn . ct_ulFlags & CTF_BREATHABLE_LUNGS )){ +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +EStopFlaming esf ; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +esf . m_bNow = TRUE ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +SendEvent (esf ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +en_ulFlags &= ~ ENF_INRENDERING ; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +en_plLastPlacement = en_plPlacement ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +void CFlame::Read_t(CTStream * istr) +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +CMovableModelEntity :: Read_t (istr ); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +SetupLightSource (); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} + +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +BOOL CFlame::IsPointInsidePolygon(const FLOAT3D & vPos,CBrushPolygon * pbpo) +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOATplane3D & plPlane = pbpo -> bpo_pbplPlane -> bpl_plAbsolute ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +INDEX iMajorAxis1 , iMajorAxis2 ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +GetMajorAxesForPlane (plPlane , iMajorAxis1 , iMajorAxis2 ); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +CIntersector isIntersector (vPos (iMajorAxis1 ) , vPos (iMajorAxis2 )); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FOREACHINSTATICARRAY (pbpo -> bpo_abpePolygonEdges , CBrushPolygonEdge , itbpePolygonEdge ){ +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +const FLOAT3D & vVertex0 = itbpePolygonEdge -> bpe_pbedEdge -> bed_pbvxVertex0 -> bvx_vAbsolute ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +const FLOAT3D & vVertex1 = itbpePolygonEdge -> bpe_pbedEdge -> bed_pbvxVertex1 -> bvx_vAbsolute ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +isIntersector . AddEdge ( +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +vVertex0 (iMajorAxis1 ) , vVertex0 (iMajorAxis2 ) , +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +vVertex1 (iMajorAxis1 ) , vVertex1 (iMajorAxis2 )); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +return isIntersector . IsIntersecting (); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} + +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +CLightSource * CFlame::GetLightSource(void) +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(! IsPredictor ()){ +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +return & m_lsLightSource ; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +}else { +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +return NULL ; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +void CFlame::RenderParticles(void) +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT fTimeFactor = CalculateRatio (_pTimer -> CurrentTick () , m_tmFirstStart , m_tmStart + TM_APPLY_WHOLE_DAMAGE , 0.05f , 0.2f); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT fDeathFactor = 1.0f; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(_pTimer -> CurrentTick () > m_tmDeathParticlesStart ) +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +fDeathFactor = 1.0f - Clamp ((_pTimer -> CurrentTick () - m_tmDeathParticlesStart ) / DEATH_BURN_TIME , 0.0f , 1.0f); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +CEntity * penParent = GetParent (); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT fPower = ClampUp (m_fDamageStep - MIN_DAMAGE_QUANTUM , MAX_DAMAGE_QUANTUM ) / MAX_DAMAGE_QUANTUM ; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(penParent != NULL ) +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if((penParent -> en_RenderType == CEntity :: RT_MODEL || penParent -> en_RenderType == CEntity :: RT_EDITORMODEL || +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +penParent -> en_RenderType == CEntity :: RT_SKAMODEL || penParent -> en_RenderType == CEntity :: RT_SKAEDITORMODEL ) && +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +(Particle_GetViewer () != penParent )) +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +Particles_Burning (penParent , fPower , fTimeFactor * fDeathFactor ); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +else +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +Particles_BrushBurning (this , & m_vPos01 , m_ctFlames , m_vPlaneNormal , fPower , fTimeFactor * fDeathFactor ); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +void CFlame::SetupLightSource(void) +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +CLightSource lsNew ; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +lsNew . ls_ulFlags = LSF_NONPERSISTENT | LSF_DYNAMIC ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(m_bBurningBrush ) +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +UBYTE ubRndH = UBYTE (25 + (FLOAT (rand ()) / RAND_MAX - 0.5f) * 28); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +UBYTE ubRndS = 166; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +UBYTE ubRndV = 48; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +lsNew . ls_colColor = HSVToColor (ubRndH , ubRndS , ubRndV ); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +lsNew . ls_rFallOff = 4.0f; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +lsNew . ls_rHotSpot = 0.2f; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +else +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +lsNew . ls_colColor = 0x8F8F5000; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +lsNew . ls_rFallOff = 6.0f; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +lsNew . ls_rHotSpot = 0.50f; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +lsNew . ls_plftLensFlare = NULL ; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +lsNew . ls_ubPolygonalMask = 0; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +lsNew . ls_paoLightAnimation = NULL ; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_lsLightSource . ls_penEntity = this ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +BOOL CFlame:: +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CFlame_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EFlame, "CFlame::Main expects 'EFlame' as input!"); const EFlame &ef = (const EFlame &)__eeInput; +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +ASSERT (ef . penOwner != NULL ); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +ASSERT (ef . penAttach != NULL ); +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_penOwner = ef . penOwner ; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_penAttach = ef . penAttach ; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_tmStart = _pTimer -> CurrentTick (); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_tmFirstStart = m_tmStart ; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +SetParent (ef . penAttach ); +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +InitAsEditorModel (); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +SetPhysicsFlags (EPF_MODEL_FLYING ); +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +SetCollisionFlags (ECF_FLAME ); +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +SetModel (MODEL_FLAME ); +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +SetModelMainTexture (TEXTURE_FLAME ); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +ModelChangeNotify (); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_soEffect . Set3DParameters (10.0f , 1.0f , 1.0f , 1.0f); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +PlaySound (m_soEffect , SOUND_FLAME , SOF_3D | SOF_LOOP ); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +AddToMovers (); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_bBurningBrush = FALSE ; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +BOOL bAllowFlame = TRUE ; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(! (ef . penAttach -> en_RenderType == CEntity :: RT_MODEL || ef . penAttach -> en_RenderType == CEntity :: RT_EDITORMODEL || +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +ef . penAttach -> en_RenderType == CEntity :: RT_SKAMODEL || ef . penAttach -> en_RenderType == CEntity :: RT_SKAEDITORMODEL )) +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_bBurningBrush = TRUE ; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT3D vPos = GetPlacement () . pl_PositionVector ; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOATplane3D plPlane ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT fDistanceToEdge ; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FindSectorsAroundEntity (); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +CBrushPolygon * pbpo = NULL ; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +pbpo = GetNearestPolygon (vPos , plPlane , fDistanceToEdge ); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT3D vBrushPos = ef . penAttach -> GetPlacement () . pl_PositionVector ; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOATmatrix3D mBrushRotInv = ! ef . penAttach -> GetRotationMatrix (); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(pbpo != NULL && pbpo -> bpo_pbscSector -> bsc_pbmBrushMip -> bm_pbrBrush -> br_penEntity == ef . penAttach ) +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +plPlane = pbpo -> bpo_pbplPlane -> bpl_plAbsolute ; +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_vPlaneNormal = (FLOAT3D &) plPlane ; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_vPlaneNormal . Normalize (); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT3D vU , vV ; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(plPlane (2) < - 0.1f) +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +bAllowFlame = FALSE ; +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(Abs (plPlane (2)) > 0.5){ +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +vU = FLOAT3D (1.0f , 0.0f , 0.0f) * m_vPlaneNormal ; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +}else { +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +vU = FLOAT3D (0.0f , 1.0f , 0.0f) * m_vPlaneNormal ; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +vU . Normalize (); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +vV = vU * m_vPlaneNormal ; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +vV . Normalize (); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_ctFlames = 0; +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +for(INDEX iTest = 0;iTest < 20;iTest ++) +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT fA = FRnd () * 360.0f; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT fR = FRnd () * 2.0f; +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT3D vRndV = vV * fR * SinFast (fA ); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT3D vRndU = vU * fR * CosFast (fA ); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT3D vRndPos = vPos ; +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(iTest != 0) +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +vRndPos += vRndV + vRndU ; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT3D vProjectedRndPos = plPlane . ProjectPoint (vRndPos ); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(IsPointInsidePolygon (vProjectedRndPos , pbpo )) +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +(& m_vPos01 ) [ m_ctFlames ] = (vProjectedRndPos - vBrushPos ) * mBrushRotInv ; +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_ctFlames ++; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(m_ctFlames == 6){break ;}; +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +else +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +bAllowFlame = FALSE ; +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(bAllowFlame ) +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +SetupLightSource (); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_bLoop = bAllowFlame ; +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +Jump(STATE_CURRENT,0x01f80004, FALSE, EInternal());return TRUE;}BOOL CFlame::H0x01f80004_Main_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f80004 +if(!(m_bLoop )){ Jump(STATE_CURRENT,0x01f80005, FALSE, EInternal());return TRUE;} +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +SetTimerAfter(TM_APPLY_DAMAGE_QUANTUM ); +Jump(STATE_CURRENT, 0x01f80002, FALSE, EBegin());return TRUE;}BOOL CFlame::H0x01f80002_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f80002 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(m_penAttach == NULL || (m_penAttach -> GetFlags () & ENF_DELETED )){ +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_bLoop = FALSE ; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f80003, FALSE, EInternal());return TRUE; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +const FLOAT fDamageMul = GetSeriousDamageMultiplier (m_penOwner ); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT fDamageToApply = fDamageMul * (m_fDamageToApply / TM_APPLY_WHOLE_DAMAGE * TM_APPLY_DAMAGE_QUANTUM ) * m_fDamageStep ; +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_penAttach -> InflictDirectDamage (m_penAttach , m_penOwner , DMT_BURNING , fDamageToApply , +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +GetPlacement () . pl_PositionVector , - en_vGravityDir ); +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_fAppliedDamage += fDamageToApply ; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +return TRUE; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +}ASSERT(FALSE);break;case(EVENTCODE_EFlame):{const EFlame&ef= (EFlame&)__eeInput; + +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_penOwner = ef . penOwner ; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT fTimeLeft = m_tmStart + TM_APPLY_WHOLE_DAMAGE - _pTimer -> CurrentTick (); +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +FLOAT fDamageLeft = (fTimeLeft / TM_APPLY_DAMAGE_QUANTUM ) * m_fDamageStep ; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_fDamageToApply = ClampUp (fDamageLeft + DAMAGE_AMMOUNT , 80.0f); +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_tmStart = _pTimer -> CurrentTick (); +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_fDamageStep = m_fDamageToApply / (TM_APPLY_WHOLE_DAMAGE / TM_APPLY_DAMAGE_QUANTUM ); +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +return TRUE; +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStopFlaming):{const EStopFlaming&esf= (EStopFlaming&)__eeInput; + +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(! esf . m_bNow ) +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_tmDeathParticlesStart = _pTimer -> CurrentTick (); +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +return TRUE; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +else +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_bLoop = FALSE ; +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f80003, FALSE, EInternal());return TRUE; +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +} +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +}ASSERT(FALSE);break;case(EVENTCODE_EBrushDestroyed):{const EBrushDestroyed&e= (EBrushDestroyed&)__eeInput; + +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_bLoop = FALSE ; +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f80003, FALSE, EInternal());return TRUE; +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01f80003, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +}return TRUE;}BOOL CFlame::H0x01f80003_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f80003 + +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +if(_pTimer -> CurrentTick () > m_tmStart + TM_APPLY_WHOLE_DAMAGE ) +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +{ +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +m_bLoop = FALSE ; +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +}Jump(STATE_CURRENT,0x01f80004, FALSE, EInternal());return TRUE; +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +}BOOL CFlame::H0x01f80005_Main_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f80005 + +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +Destroy (); +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +Return(STATE_CURRENT,EVoid()); +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Flame.es b/Sources/EntitiesMP/Flame.es new file mode 100644 index 0000000..c93a218 --- /dev/null +++ b/Sources/EntitiesMP/Flame.es @@ -0,0 +1,371 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +504 +%{ +#include "StdH.h" +#define TM_APPLY_DAMAGE_QUANTUM 0.25f +#define TM_APPLY_WHOLE_DAMAGE 7.5f +#define DAMAGE_AMMOUNT 30.0f +#define MIN_DAMAGE_QUANTUM (DAMAGE_AMMOUNT/TM_APPLY_WHOLE_DAMAGE*TM_APPLY_DAMAGE_QUANTUM) +#define MAX_DAMAGE_QUANTUM (MIN_DAMAGE_QUANTUM*10.0f) +#define DEATH_BURN_TIME 4.0f + +#include "EntitiesMP/MovingBrush.h" +%} + +uses "EntitiesMP/Light"; + +// input parameter for flame +event EFlame { + CEntityPointer penOwner, // entity which owns it + CEntityPointer penAttach, // entity on which flame is attached (his parent) +}; + +// event for stop burning +event EStopFlaming { + BOOL m_bNow, +}; + +%{ +void CFlame_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + pdec->PrecacheModel(MODEL_FLAME); + pdec->PrecacheTexture(TEXTURE_FLAME); + pdec->PrecacheSound(SOUND_FLAME); +} +%} + +class CFlame : CMovableModelEntity { +name "Flame"; +thumbnail ""; +features "ImplementsOnPrecache", "CanBePredictable"; + +properties: + 1 CEntityPointer m_penOwner, // entity which owns it + 2 CEntityPointer m_penAttach, // entity on which flame is attached (his parent) + 5 BOOL m_bLoop = FALSE, // internal for loops + 8 FLOAT3D m_vHitPoint = FLOAT3D(0.0f, 0.0f, 0.0f), // where the flame hit the entity + + 10 CSoundObject m_soEffect, // sound channel + + + 20 FLOAT m_tmStart = 0.0f, + 21 FLOAT m_fDamageToApply = 0.0f, + 22 FLOAT m_fDamageStep = 0.0f, + 23 FLOAT m_fAppliedDamage=0.0f, + 24 FLOAT m_tmFirstStart = 0.0f, // when the burning started + + 29 INDEX m_ctFlames=0, + 30 FLOAT3D m_vPos01=FLOAT3D(0,0,0), + 31 FLOAT3D m_vPos02=FLOAT3D(0,0,0), + 32 FLOAT3D m_vPos03=FLOAT3D(0,0,0), + 33 FLOAT3D m_vPos04=FLOAT3D(0,0,0), + 34 FLOAT3D m_vPos05=FLOAT3D(0,0,0), + 35 FLOAT3D m_vPos06=FLOAT3D(0,0,0), + 36 FLOAT3D m_vPos07=FLOAT3D(0,0,0), + 37 FLOAT3D m_vPos08=FLOAT3D(0,0,0), + 38 FLOAT3D m_vPos09=FLOAT3D(0,0,0), + 39 FLOAT3D m_vPos10=FLOAT3D(0,0,0), + 40 FLOAT3D m_vPlaneNormal=FLOAT3D(0,0,0), + 51 BOOL m_bBurningBrush=FALSE, + 52 FLOAT m_tmDeathParticlesStart=1e6, + +{ + CLightSource m_lsLightSource; + +} + +components: + 1 class CLASS_LIGHT "Classes\\Light.ecl", + +// ********* FLAME ********* + 10 model MODEL_FLAME "ModelsMP\\Effects\\Flame\\Flame.mdl", + 11 texture TEXTURE_FLAME "ModelsMP\\Effects\\Flame\\Flame.tex", + 12 sound SOUND_FLAME "SoundsMP\\Fire\\Burning.wav", + +functions: + // add to prediction any entities that this entity depends on + void AddDependentsToPrediction(void) + { + m_penOwner->AddToPrediction(); + } + // postmoving + void PostMoving(void) { + CMovableModelEntity::PostMoving(); + + // if no air + CContentType &ctDn = GetWorld()->wo_actContentTypes[en_iDnContent]; + // stop existing + if (!(ctDn.ct_ulFlags&CTF_BREATHABLE_LUNGS)) { + EStopFlaming esf; + esf.m_bNow = TRUE; + SendEvent(esf); + } + + // never remove from list of movers + en_ulFlags &= ~ENF_INRENDERING; + // not moving in fact, only moving with its parent + en_plLastPlacement = en_plPlacement; + }; + + /* Read from stream. */ + void Read_t( CTStream *istr) // throw char * + { + CMovableModelEntity::Read_t(istr); + SetupLightSource(); + } + + BOOL IsPointInsidePolygon(const FLOAT3D &vPos, CBrushPolygon *pbpo) + { + FLOATplane3D &plPlane=pbpo->bpo_pbplPlane->bpl_plAbsolute; + // find major axes of the polygon plane + INDEX iMajorAxis1, iMajorAxis2; + GetMajorAxesForPlane(plPlane, iMajorAxis1, iMajorAxis2); + + // create an intersector + CIntersector isIntersector(vPos(iMajorAxis1), vPos(iMajorAxis2)); + // for all edges in the polygon + FOREACHINSTATICARRAY(pbpo->bpo_abpePolygonEdges, CBrushPolygonEdge, itbpePolygonEdge) { + // get edge vertices (edge direction is irrelevant here!) + const FLOAT3D &vVertex0 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex0->bvx_vAbsolute; + const FLOAT3D &vVertex1 = itbpePolygonEdge->bpe_pbedEdge->bed_pbvxVertex1->bvx_vAbsolute; + // pass the edge to the intersector + isIntersector.AddEdge( + vVertex0(iMajorAxis1), vVertex0(iMajorAxis2), + vVertex1(iMajorAxis1), vVertex1(iMajorAxis2)); + } + // return result of polygon intersection + return isIntersector.IsIntersecting(); + } + + /* Get static light source information. */ + CLightSource *GetLightSource(void) + { + if (!IsPredictor()) { + return &m_lsLightSource; + } else { + return NULL; + } + } + + // render particles + void RenderParticles(void) + { + FLOAT fTimeFactor=CalculateRatio(_pTimer->CurrentTick(), m_tmFirstStart, m_tmStart+TM_APPLY_WHOLE_DAMAGE, 0.05f, 0.2f); + FLOAT fDeathFactor=1.0f; + if( _pTimer->CurrentTick()>m_tmDeathParticlesStart) + { + fDeathFactor=1.0f-Clamp((_pTimer->CurrentTick()-m_tmDeathParticlesStart)/DEATH_BURN_TIME, 0.0f, 1.0f); + } + CEntity *penParent= GetParent(); + FLOAT fPower=ClampUp(m_fDamageStep-MIN_DAMAGE_QUANTUM, MAX_DAMAGE_QUANTUM)/MAX_DAMAGE_QUANTUM; + if( penParent!= NULL) + { + if( (penParent->en_RenderType==CEntity::RT_MODEL || penParent->en_RenderType==CEntity::RT_EDITORMODEL || + penParent->en_RenderType==CEntity::RT_SKAMODEL || penParent->en_RenderType==CEntity::RT_SKAEDITORMODEL) && + (Particle_GetViewer()!=penParent) ) + { + Particles_Burning(penParent, fPower, fTimeFactor*fDeathFactor); + } + else + { + Particles_BrushBurning(this, &m_vPos01, m_ctFlames, m_vPlaneNormal, fPower, fTimeFactor*fDeathFactor); + } + } + } + + // Setup light source + void SetupLightSource(void) + { + // setup light source + CLightSource lsNew; + lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC; + if(m_bBurningBrush) + { + UBYTE ubRndH = UBYTE( 25+(FLOAT(rand())/RAND_MAX-0.5f)*28); + UBYTE ubRndS = 166; + UBYTE ubRndV = 48; + lsNew.ls_colColor = HSVToColor(ubRndH, ubRndS, ubRndV); + //lsNew.ls_colColor = 0x3F3F1600; + lsNew.ls_rFallOff = 4.0f; + lsNew.ls_rHotSpot = 0.2f; + } + else + { + lsNew.ls_colColor = 0x8F8F5000; + lsNew.ls_rFallOff = 6.0f; + lsNew.ls_rHotSpot = 0.50f; + } + lsNew.ls_plftLensFlare = NULL; + lsNew.ls_ubPolygonalMask = 0; + lsNew.ls_paoLightAnimation = NULL; + + m_lsLightSource.ls_penEntity = this; + m_lsLightSource.SetLightSource(lsNew); + } + +/************************************************************ + * P R O C E D U R E S * + ************************************************************/ +procedures: + // --->>> MAIN + Main(EFlame ef) { + // attach to parent (another entity) + ASSERT(ef.penOwner!=NULL); + ASSERT(ef.penAttach!=NULL); + m_penOwner = ef.penOwner; + m_penAttach = ef.penAttach; + + m_tmStart = _pTimer->CurrentTick(); + m_tmFirstStart=m_tmStart; + SetParent(ef.penAttach); + // initialization + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_FLYING); + SetCollisionFlags(ECF_FLAME); + SetFlags(GetFlags() | ENF_SEETHROUGH); + + SetModel(MODEL_FLAME); + SetModelMainTexture(TEXTURE_FLAME); + ModelChangeNotify(); + + // play the burning sound + m_soEffect.Set3DParameters(10.0f, 1.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_FLAME, SOF_3D|SOF_LOOP); + + // must always be in movers, to find sector content type + AddToMovers(); + + m_bBurningBrush=FALSE; + BOOL bAllowFlame=TRUE; + if( !(ef.penAttach->en_RenderType==CEntity::RT_MODEL || ef.penAttach->en_RenderType==CEntity::RT_EDITORMODEL || + ef.penAttach->en_RenderType==CEntity::RT_SKAMODEL || ef.penAttach->en_RenderType==CEntity::RT_SKAEDITORMODEL )) + { + m_bBurningBrush=TRUE; + FLOAT3D vPos=GetPlacement().pl_PositionVector; + FLOATplane3D plPlane; + FLOAT fDistanceToEdge; + FindSectorsAroundEntity(); + CBrushPolygon *pbpo=NULL; + pbpo=GetNearestPolygon(vPos, plPlane, fDistanceToEdge); + FLOAT3D vBrushPos = ef.penAttach->GetPlacement().pl_PositionVector; + FLOATmatrix3D mBrushRotInv = !ef.penAttach->GetRotationMatrix(); + if( pbpo!=NULL && pbpo->bpo_pbscSector->bsc_pbmBrushMip->bm_pbrBrush->br_penEntity==ef.penAttach) + { + plPlane = pbpo->bpo_pbplPlane->bpl_plAbsolute; + m_vPlaneNormal=(FLOAT3D &)plPlane; + m_vPlaneNormal.Normalize(); + // ------ Calculate plane-paralel normal vectors + FLOAT3D vU, vV; + //CPrintF("plPlane %g\n", plPlane(2)); + if(plPlane(2)<-0.1f) + { + bAllowFlame=FALSE; + } + + // if the plane is mostly horizontal + if (Abs(plPlane(2))>0.5) { + // use cross product of +x axis and plane normal as +s axis + vU = FLOAT3D(1.0f, 0.0f, 0.0f)*m_vPlaneNormal; + // if the plane is mostly vertical + } else { + // use cross product of +y axis and plane normal as +s axis + vU = FLOAT3D(0.0f, 1.0f, 0.0f)*m_vPlaneNormal; + } + // make +s axis normalized + vU.Normalize(); + // use cross product of plane normal and +s axis as +t axis + vV = vU*m_vPlaneNormal; + vV.Normalize(); + + // counter of valid flames + m_ctFlames=0; + for(INDEX iTest=0; iTest<20; iTest++) + { + FLOAT fA=FRnd()*360.0f; + FLOAT fR=FRnd()*2.0f; + FLOAT3D vRndV=vV*fR*SinFast(fA); + FLOAT3D vRndU=vU*fR*CosFast(fA); + FLOAT3D vRndPos=vPos; + if( iTest!=0) + { + vRndPos+=vRndV+vRndU; + } + // project point to a plane + FLOAT3D vProjectedRndPos=plPlane.ProjectPoint(vRndPos); + if( IsPointInsidePolygon(vProjectedRndPos, pbpo)) + { + (&m_vPos01)[ m_ctFlames]=(vProjectedRndPos-vBrushPos)*mBrushRotInv; + m_ctFlames++; + if( m_ctFlames==6) { break; }; + } + } + } + else + { + bAllowFlame=FALSE; + } + } + // setup light source + if( bAllowFlame) + { + SetupLightSource(); + } + + m_bLoop = bAllowFlame; + while(m_bLoop) { + wait(TM_APPLY_DAMAGE_QUANTUM) { + // damage to parent + on (EBegin) : { + // if parent does not exist anymore + if (m_penAttach==NULL || (m_penAttach->GetFlags()&ENF_DELETED)) { + // stop existing + m_bLoop = FALSE; + stop; + } + // inflict damage to parent + const FLOAT fDamageMul = GetSeriousDamageMultiplier(m_penOwner); + FLOAT fDamageToApply=fDamageMul*(m_fDamageToApply/TM_APPLY_WHOLE_DAMAGE*TM_APPLY_DAMAGE_QUANTUM)*m_fDamageStep; + m_penAttach->InflictDirectDamage( m_penAttach, m_penOwner, DMT_BURNING, fDamageToApply, + GetPlacement().pl_PositionVector, -en_vGravityDir); + m_fAppliedDamage+=fDamageToApply; + resume; + } + on (EFlame ef) : { + m_penOwner = ef.penOwner; + FLOAT fTimeLeft=m_tmStart+TM_APPLY_WHOLE_DAMAGE-_pTimer->CurrentTick(); + FLOAT fDamageLeft=(fTimeLeft/TM_APPLY_DAMAGE_QUANTUM)*m_fDamageStep; + m_fDamageToApply=ClampUp(fDamageLeft+DAMAGE_AMMOUNT, 80.0f); + m_tmStart=_pTimer->CurrentTick(); + m_fDamageStep=m_fDamageToApply/(TM_APPLY_WHOLE_DAMAGE/TM_APPLY_DAMAGE_QUANTUM); + resume; + }; + on (EStopFlaming esf) : { + if( !esf.m_bNow) + { + m_tmDeathParticlesStart=_pTimer->CurrentTick(); + resume; + } + else + { + m_bLoop = FALSE; + stop; + } + }; + on (EBrushDestroyed) : { + m_bLoop = FALSE; + stop; + }; + on (ETimer) : { stop; } + } + if(_pTimer->CurrentTick()>m_tmStart+TM_APPLY_WHOLE_DAMAGE) + { + m_bLoop = FALSE; + } + } + + // cease to exist + Destroy(); + return; + } +}; diff --git a/Sources/EntitiesMP/Flame.h b/Sources/EntitiesMP/Flame.h new file mode 100644 index 0000000..9d2734e --- /dev/null +++ b/Sources/EntitiesMP/Flame.h @@ -0,0 +1,87 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Flame_INCLUDED +#define _EntitiesMP_Flame_INCLUDED 1 +#include +#define EVENTCODE_EFlame 0x01f80000 +class DECL_DLL EFlame : public CEntityEvent { +public: +EFlame(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOwner; +CEntityPointer penAttach; +}; +DECL_DLL inline void ClearToDefault(EFlame &e) { e = EFlame(); } ; +#define EVENTCODE_EStopFlaming 0x01f80001 +class DECL_DLL EStopFlaming : public CEntityEvent { +public: +EStopFlaming(); +CEntityEvent *MakeCopy(void); +BOOL m_bNow; +}; +DECL_DLL inline void ClearToDefault(EStopFlaming &e) { e = EStopFlaming(); } ; +extern "C" DECL_DLL CDLLEntityClass CFlame_DLLClass; +class CFlame : public CMovableModelEntity { +public: +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penOwner; + CEntityPointer m_penAttach; + BOOL m_bLoop; + FLOAT3D m_vHitPoint; + CSoundObject m_soEffect; + FLOAT m_tmStart; + FLOAT m_fDamageToApply; + FLOAT m_fDamageStep; + FLOAT m_fAppliedDamage; + FLOAT m_tmFirstStart; + INDEX m_ctFlames; + FLOAT3D m_vPos01; + FLOAT3D m_vPos02; + FLOAT3D m_vPos03; + FLOAT3D m_vPos04; + FLOAT3D m_vPos05; + FLOAT3D m_vPos06; + FLOAT3D m_vPos07; + FLOAT3D m_vPos08; + FLOAT3D m_vPos09; + FLOAT3D m_vPos10; + FLOAT3D m_vPlaneNormal; + BOOL m_bBurningBrush; + FLOAT m_tmDeathParticlesStart; + CEntityPointer m_penPrediction; +CLightSource m_lsLightSource; + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +void AddDependentsToPrediction(void); + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +void PostMoving(void); + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +void Read_t(CTStream * istr); + +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +BOOL IsPointInsidePolygon(const FLOAT3D & vPos,CBrushPolygon * pbpo); + +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +CLightSource * GetLightSource(void); + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +void RenderParticles(void); + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +void SetupLightSource(void); +#define STATE_CFlame_Main 1 + BOOL +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01f80002_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01f80003_Main_02(const CEntityEvent &__eeInput); + BOOL H0x01f80004_Main_03(const CEntityEvent &__eeInput); + BOOL H0x01f80005_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Flame_INCLUDED diff --git a/Sources/EntitiesMP/Flame_tables.h b/Sources/EntitiesMP/Flame_tables.h new file mode 100644 index 0000000..b9da735 --- /dev/null +++ b/Sources/EntitiesMP/Flame_tables.h @@ -0,0 +1,68 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CFlame + +CEntityProperty CFlame_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001f8<<8)+1, offsetof(CFlame, m_penOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001f8<<8)+2, offsetof(CFlame, m_penAttach), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001f8<<8)+5, offsetof(CFlame, m_bLoop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+8, offsetof(CFlame, m_vHitPoint), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000001f8<<8)+10, offsetof(CFlame, m_soEffect), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f8<<8)+20, offsetof(CFlame, m_tmStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f8<<8)+21, offsetof(CFlame, m_fDamageToApply), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f8<<8)+22, offsetof(CFlame, m_fDamageStep), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f8<<8)+23, offsetof(CFlame, m_fAppliedDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f8<<8)+24, offsetof(CFlame, m_tmFirstStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000001f8<<8)+29, offsetof(CFlame, m_ctFlames), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+30, offsetof(CFlame, m_vPos01), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+31, offsetof(CFlame, m_vPos02), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+32, offsetof(CFlame, m_vPos03), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+33, offsetof(CFlame, m_vPos04), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+34, offsetof(CFlame, m_vPos05), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+35, offsetof(CFlame, m_vPos06), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+36, offsetof(CFlame, m_vPos07), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+37, offsetof(CFlame, m_vPos08), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+38, offsetof(CFlame, m_vPos09), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+39, offsetof(CFlame, m_vPos10), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001f8<<8)+40, offsetof(CFlame, m_vPlaneNormal), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001f8<<8)+51, offsetof(CFlame, m_bBurningBrush), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f8<<8)+52, offsetof(CFlame, m_tmDeathParticlesStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001f8<<8)+255, offsetof(CFlame, m_penPrediction), "", 0, 0, 0), +}; +#define CFlame_propertiesct ARRAYCOUNT(CFlame_properties) + +CEntityComponent CFlame_components[] = { +#define CLASS_LIGHT ((0x000001f8<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_LIGHT, "EFNM" "Classes\\Light.ecl"), +#define MODEL_FLAME ((0x000001f8<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_FLAME, "EFNM" "ModelsMP\\Effects\\Flame\\Flame.mdl"), +#define TEXTURE_FLAME ((0x000001f8<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLAME, "EFNM" "ModelsMP\\Effects\\Flame\\Flame.tex"), +#define SOUND_FLAME ((0x000001f8<<8)+12) + CEntityComponent(ECT_SOUND, SOUND_FLAME, "EFNM" "SoundsMP\\Fire\\Burning.wav"), +}; +#define CFlame_componentsct ARRAYCOUNT(CFlame_components) + +CEventHandlerEntry CFlame_handlers[] = { + {1, -1, CEntity::pEventHandler(&CFlame:: +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Flame.es" +Main),DEBUGSTRING("CFlame::Main")}, + {0x01f80002, -1, CEntity::pEventHandler(&CFlame::H0x01f80002_Main_01), DEBUGSTRING("CFlame::H0x01f80002_Main_01")}, + {0x01f80003, -1, CEntity::pEventHandler(&CFlame::H0x01f80003_Main_02), DEBUGSTRING("CFlame::H0x01f80003_Main_02")}, + {0x01f80004, -1, CEntity::pEventHandler(&CFlame::H0x01f80004_Main_03), DEBUGSTRING("CFlame::H0x01f80004_Main_03")}, + {0x01f80005, -1, CEntity::pEventHandler(&CFlame::H0x01f80005_Main_04), DEBUGSTRING("CFlame::H0x01f80005_Main_04")}, +}; +#define CFlame_handlersct ARRAYCOUNT(CFlame_handlers) + +CEntity *CFlame_New(void) { return new CFlame; }; +void CFlame_OnInitClass(void) {}; +void CFlame_OnEndClass(void) {}; +void CFlame_OnPrecache(CDLLEntityClass *pdec, INDEX iUser); +void CFlame_OnWorldEnd(CWorld *pwo) {}; +void CFlame_OnWorldInit(CWorld *pwo) {}; +void CFlame_OnWorldTick(CWorld *pwo) {}; +void CFlame_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CFlame, CMovableModelEntity, "Flame", "", 0x000001f8); +DECLARE_CTFILENAME(_fnmCFlame_tbn, ""); diff --git a/Sources/EntitiesMP/FogMarker.cpp b/Sources/EntitiesMP/FogMarker.cpp new file mode 100644 index 0000000..6b8d8d6 --- /dev/null +++ b/Sources/EntitiesMP/FogMarker.cpp @@ -0,0 +1,170 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" + +#include "StdH.h" + +#include +#include +void CFogMarker::SetDefaultProperties(void) { + m_fDepth = 10.0f; + m_fAbove = 20.0f; + m_fBelow = 20.0f; + m_fFar = 100.0f; + m_faType = FA_EXP ; + m_fDensity = 0.1f; + m_fgType = FG_CONSTANT ; + m_fGraduation = 0.1f; + m_bDensityDirect = TRUE ; + m_fDensityPercentage = 0.95f; + m_fDensityDistance = 10.0f; + m_bGraduationDirect = TRUE ; + m_fGraduationPercentage = 0.95f; + m_fGraduationDistance = 10.0f; + m_iSizeL = 32; + m_iSizeH = 16; + m_colColor = (C_WHITE | CT_OPAQUE ); + CMarker::SetDefaultProperties(); +} + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +const CTString & CFogMarker::GetFogName(void) +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +{ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +return m_strName ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +} + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +void CFogMarker::GetFog(class CFogParameters & fpFog) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +{ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +const FLOATmatrix3D & m = GetRotationMatrix (); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_vFogDir (1) = m (1 , 2); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_vFogDir (2) = m (2 , 2); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_vFogDir (3) = m (3 , 2); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +FLOAT fPos = fpFog . fp_vFogDir % GetPlacement () . pl_PositionVector ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_colColor = m_colColor ; +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_atType = (AttenuationType ) m_faType ; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_fDensity = m_fDensity ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_fgtType = (FogGraduationType ) m_fgType ; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_fGraduation = m_fGraduation ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_fH0 = fPos - m_fDepth - m_fBelow ; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_fH1 = fPos - m_fDepth ; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_fH2 = fPos ; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_fH3 = fPos + m_fAbove ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_fFar = m_fFar ; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_iSizeH = m_iSizeH ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +fpFog . fp_iSizeL = m_iSizeL ; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +} +BOOL CFogMarker:: +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CFogMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CFogMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +InitAsEditorModel (); +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +SetModel (MODEL_MARKER ); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +if(m_strName == "Marker"){ +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_strName = "Fog marker"; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +} +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +if(! m_bDensityDirect ){ +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +switch(m_faType ){ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +case FA_LINEAR : +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_fDensity = m_fDensityPercentage / m_fDensityDistance ; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +break ; +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +case FA_EXP : +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_fDensity = - log (1 - m_fDensityPercentage ) / m_fDensityDistance ; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +break ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +case FA_EXP2 : +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_fDensity = Sqrt (- log (1 - m_fDensityPercentage )) / m_fDensityDistance ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +break ; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +} +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +} +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +if(! m_bGraduationDirect ){ +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +switch(m_fgType ){ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +case FG_LINEAR : +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_fGraduation = m_fGraduationPercentage / m_fGraduationDistance ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +break ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +case FG_EXP : +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_fGraduation = - log (1 - m_fGraduationPercentage ) / m_fGraduationDistance ; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +break ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +} +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +} +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_fDensity = ClampDn (m_fDensity , 1E-6f); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_fDepth = ClampDn (m_fDepth , 0.001f); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_fAbove = ClampDn (m_fAbove , 0.001f); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_fBelow = ClampDn (m_fBelow , 0.001f); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_fFar = ClampDn (m_fFar , 0.001f); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_iSizeL = 1 << INDEX (Log2 (m_iSizeL )); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_iSizeH = 1 << INDEX (Log2 (m_iSizeH )); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_iSizeL = Clamp (m_iSizeL , INDEX (2) , INDEX (256)); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +m_iSizeH = Clamp (m_iSizeH , INDEX (2) , INDEX (256)); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/FogMarker.es b/Sources/EntitiesMP/FogMarker.es new file mode 100644 index 0000000..ad4f878 --- /dev/null +++ b/Sources/EntitiesMP/FogMarker.es @@ -0,0 +1,144 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +215 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; + +enum FogAttenuationType { + 0 FA_LINEAR "Linear", + 1 FA_EXP "Exp", + 2 FA_EXP2 "Exp2", +}; +enum FogGraduationType2 { + 0 FG_CONSTANT "Constant", + 1 FG_LINEAR "Linear", + 2 FG_EXP "Exp", +}; + +class CFogMarker: CMarker { +name "Fog Marker"; +thumbnail "Thumbnails\\FogMarker.tbn"; +features "IsImportant"; + +properties: + 1 FLOAT m_fDepth "Depth" 'E' = 10.0f, + 2 FLOAT m_fAbove "Above" 'O' = 20.0f, + 3 FLOAT m_fBelow "Below" 'B' = 20.0f, + 4 FLOAT m_fFar "Far" 'F' = 100.0f, + + 10 enum FogAttenuationType m_faType "Attenuation Type" 'A' =FA_EXP, + 11 FLOAT m_fDensity "Density" 'D' = 0.1f, + 12 enum FogGraduationType2 m_fgType "Graduation Type" 'G' =FG_CONSTANT, + 13 FLOAT m_fGraduation "Graduation" 'R' = 0.1f, + + // for indirect density calculation + 14 BOOL m_bDensityDirect "Density Direct" = TRUE, + 15 FLOAT m_fDensityPercentage "DensityPercentage" = 0.95f, + 16 FLOAT m_fDensityDistance "DensityDistance" = 10.0f, + + // for indirect graduation calculation + 17 BOOL m_bGraduationDirect "Graduation Direct" = TRUE, + 18 FLOAT m_fGraduationPercentage "GraduationPercentage" = 0.95f, + 19 FLOAT m_fGraduationDistance "GraduationDistance" = 10.0f, + + 22 INDEX m_iSizeL "Size Distance" 'S' = 32, + 23 INDEX m_iSizeH "Size Depth" 'I' = 16, + 24 COLOR m_colColor "Color" 'C' = (C_WHITE|CT_OPAQUE), + +components: + 1 model MODEL_MARKER "Models\\Editor\\Fog.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Fog.tex" + +functions: + + /* Get fog type name, return empty string if not used. */ + const CTString &GetFogName(void) + { + return m_strName; + } + /* Get fog. */ + void GetFog(class CFogParameters &fpFog) + { + const FLOATmatrix3D &m = GetRotationMatrix(); + fpFog.fp_vFogDir(1) = m(1,2); + fpFog.fp_vFogDir(2) = m(2,2); + fpFog.fp_vFogDir(3) = m(3,2); + FLOAT fPos = fpFog.fp_vFogDir%GetPlacement().pl_PositionVector; + fpFog.fp_colColor = m_colColor; + fpFog.fp_atType = (AttenuationType) m_faType; + fpFog.fp_fDensity = m_fDensity; + fpFog.fp_fgtType = (FogGraduationType) m_fgType; + fpFog.fp_fGraduation = m_fGraduation; + fpFog.fp_fH0 = fPos-m_fDepth-m_fBelow; + fpFog.fp_fH1 = fPos-m_fDepth; + fpFog.fp_fH2 = fPos; + fpFog.fp_fH3 = fPos+m_fAbove; + fpFog.fp_fFar = m_fFar; + fpFog.fp_iSizeH = m_iSizeH; + fpFog.fp_iSizeL = m_iSizeL; + } +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + // set name + if (m_strName=="Marker") { + m_strName = "Fog marker"; + } + + // if density is calculated indirectly + if (!m_bDensityDirect) { + // calculate density to have given percentage at given distance + switch(m_faType) { + case FA_LINEAR: + m_fDensity = m_fDensityPercentage/m_fDensityDistance; + break; + case FA_EXP: + m_fDensity = -log(1-m_fDensityPercentage)/m_fDensityDistance; + break; + case FA_EXP2: + m_fDensity = Sqrt(-log(1-m_fDensityPercentage))/m_fDensityDistance; + break; + } + } + + // if graduation is calculated indirectly + if (!m_bGraduationDirect) { + // calculate graduation to have given percentage at given depth + switch(m_fgType) { + case FG_LINEAR: + m_fGraduation = m_fGraduationPercentage/m_fGraduationDistance; + break; + case FG_EXP: + m_fGraduation = -log(1-m_fGraduationPercentage)/m_fGraduationDistance; + break; + } + } + + + // clamp values to valid ranges + m_fDensity = ClampDn(m_fDensity, 1E-6f); + + m_fDepth = ClampDn(m_fDepth , 0.001f); + m_fAbove = ClampDn(m_fAbove , 0.001f); + m_fBelow = ClampDn(m_fBelow , 0.001f); + m_fFar = ClampDn(m_fFar, 0.001f); + + m_iSizeL = 1< +extern DECL_DLL CEntityPropertyEnumType FogAttenuationType_enum; +enum FogAttenuationType { + FA_LINEAR = 0, + FA_EXP = 1, + FA_EXP2 = 2, +}; +DECL_DLL inline void ClearToDefault(FogAttenuationType &e) { e = (FogAttenuationType)0; } ; +extern DECL_DLL CEntityPropertyEnumType FogGraduationType2_enum; +enum FogGraduationType2 { + FG_CONSTANT = 0, + FG_LINEAR = 1, + FG_EXP = 2, +}; +DECL_DLL inline void ClearToDefault(FogGraduationType2 &e) { e = (FogGraduationType2)0; } ; +extern "C" DECL_DLL CDLLEntityClass CFogMarker_DLLClass; +class CFogMarker : public CMarker { +public: +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fDepth; + FLOAT m_fAbove; + FLOAT m_fBelow; + FLOAT m_fFar; + enum FogAttenuationType m_faType; + FLOAT m_fDensity; + enum FogGraduationType2 m_fgType; + FLOAT m_fGraduation; + BOOL m_bDensityDirect; + FLOAT m_fDensityPercentage; + FLOAT m_fDensityDistance; + BOOL m_bGraduationDirect; + FLOAT m_fGraduationPercentage; + FLOAT m_fGraduationDistance; + INDEX m_iSizeL; + INDEX m_iSizeH; + COLOR m_colColor; + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +const CTString & GetFogName(void); + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +void GetFog(class CFogParameters & fpFog); +#define STATE_CFogMarker_Main 1 + BOOL +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_FogMarker_INCLUDED diff --git a/Sources/EntitiesMP/FogMarker_tables.h b/Sources/EntitiesMP/FogMarker_tables.h new file mode 100644 index 0000000..409805d --- /dev/null +++ b/Sources/EntitiesMP/FogMarker_tables.h @@ -0,0 +1,64 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(FogAttenuationType) + EP_ENUMVALUE(FA_LINEAR, "Linear"), + EP_ENUMVALUE(FA_EXP, "Exp"), + EP_ENUMVALUE(FA_EXP2, "Exp2"), +EP_ENUMEND(FogAttenuationType); + +EP_ENUMBEG(FogGraduationType2) + EP_ENUMVALUE(FG_CONSTANT, "Constant"), + EP_ENUMVALUE(FG_LINEAR, "Linear"), + EP_ENUMVALUE(FG_EXP, "Exp"), +EP_ENUMEND(FogGraduationType2); + +#define ENTITYCLASS CFogMarker + +CEntityProperty CFogMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d7<<8)+1, offsetof(CFogMarker, m_fDepth), "Depth", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d7<<8)+2, offsetof(CFogMarker, m_fAbove), "Above", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d7<<8)+3, offsetof(CFogMarker, m_fBelow), "Below", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d7<<8)+4, offsetof(CFogMarker, m_fFar), "Far", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &FogAttenuationType_enum, (0x000000d7<<8)+10, offsetof(CFogMarker, m_faType), "Attenuation Type", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d7<<8)+11, offsetof(CFogMarker, m_fDensity), "Density", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &FogGraduationType2_enum, (0x000000d7<<8)+12, offsetof(CFogMarker, m_fgType), "Graduation Type", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d7<<8)+13, offsetof(CFogMarker, m_fGraduation), "Graduation", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d7<<8)+14, offsetof(CFogMarker, m_bDensityDirect), "Density Direct", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d7<<8)+15, offsetof(CFogMarker, m_fDensityPercentage), "DensityPercentage", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d7<<8)+16, offsetof(CFogMarker, m_fDensityDistance), "DensityDistance", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d7<<8)+17, offsetof(CFogMarker, m_bGraduationDirect), "Graduation Direct", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d7<<8)+18, offsetof(CFogMarker, m_fGraduationPercentage), "GraduationPercentage", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d7<<8)+19, offsetof(CFogMarker, m_fGraduationDistance), "GraduationDistance", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000d7<<8)+22, offsetof(CFogMarker, m_iSizeL), "Size Distance", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000d7<<8)+23, offsetof(CFogMarker, m_iSizeH), "Size Depth", 'I', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d7<<8)+24, offsetof(CFogMarker, m_colColor), "Color", 'C', 0x7F0000FFUL, 0), +}; +#define CFogMarker_propertiesct ARRAYCOUNT(CFogMarker_properties) + +CEntityComponent CFogMarker_components[] = { +#define MODEL_MARKER ((0x000000d7<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Fog.mdl"), +#define TEXTURE_MARKER ((0x000000d7<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Fog.tex"), +}; +#define CFogMarker_componentsct ARRAYCOUNT(CFogMarker_components) + +CEventHandlerEntry CFogMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CFogMarker:: +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/FogMarker.es" +Main),DEBUGSTRING("CFogMarker::Main")}, +}; +#define CFogMarker_handlersct ARRAYCOUNT(CFogMarker_handlers) + +CEntity *CFogMarker_New(void) { return new CFogMarker; }; +void CFogMarker_OnInitClass(void) {}; +void CFogMarker_OnEndClass(void) {}; +void CFogMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CFogMarker_OnWorldEnd(CWorld *pwo) {}; +void CFogMarker_OnWorldInit(CWorld *pwo) {}; +void CFogMarker_OnWorldTick(CWorld *pwo) {}; +void CFogMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CFogMarker, CMarker, "Fog Marker", "Thumbnails\\FogMarker.tbn", 0x000000d7); +DECLARE_CTFILENAME(_fnmCFogMarker_tbn, "Thumbnails\\FogMarker.tbn"); diff --git a/Sources/EntitiesMP/Gizmo.cpp b/Sources/EntitiesMP/Gizmo.cpp new file mode 100644 index 0000000..e9778b3 --- /dev/null +++ b/Sources/EntitiesMP/Gizmo.cpp @@ -0,0 +1,516 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" + +#include "StdH.h" +#include "Models/Enemies/Gizmo/Gizmo.h" + +#include +#include +#line 12 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" + +// info structure +static EntityInfo eiGizmo = { + EIBT_FLESH, 100.0f, + 0.0f, 1.3f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +#define EXPLODE_GIZMO 2.5f + +void CGizmo::SetDefaultProperties(void) { + m_bExploded = FALSE ; + CEnemyBase::SetDefaultProperties(); +} + CTString CGizmo::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +CTString str ; +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +str . PrintF (TRANS ("%s ate a marsh hopper") , strPlayerName ); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +return str ; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + const CTFileName & CGizmo::GetComputerMessageName(void)const { +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +static DECLARE_CTFILENAME (fnm , "Data\\Messages\\Enemies\\Gizmo.txt"); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +return fnm ; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void * CGizmo::GetEntityInfo(void) +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +return & eiGizmo ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void CGizmo::Precache(void) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +CEnemyBase :: Precache (); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PrecacheSound (SOUND_SIGHT ); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PrecacheSound (SOUND_IDLE ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PrecacheSound (SOUND_JUMP ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PrecacheSound (SOUND_DEATH_JUMP ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_GIZMO_SPLASH_FX ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PrecacheClass (CLASS_BLOOD_SPRAY ); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void CGizmo::SightSound(void) { +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void CGizmo::RunningAnim(void) +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +StartModelAnim (GIZMO_ANIM_RUN , 0); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void CGizmo::MortalJumpAnim(void) +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +StartModelAnim (GIZMO_ANIM_RUN , 0); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void CGizmo::StandAnim(void) +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +StartModelAnim (GIZMO_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void CGizmo::IdleSound(void) { +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void CGizmo::BlowUpNotify(void) { +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +Explode (); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void CGizmo::Explode(void) +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +if(! m_bExploded ) +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_bExploded = TRUE ; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +CPlacement3D plSpray = GetPlacement (); +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +CEntity * penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +penSpray -> SetParent (this ); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +ESpawnSpray eSpawnSpray ; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +eSpawnSpray . fDamagePower = 2.0f; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +eSpawnSpray . fSizeMultiplier = 1.0f; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +eSpawnSpray . sptType = SPT_SLIME ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +eSpawnSpray . vDirection = en_vCurrentTranslationAbsolute / 8.0f; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +eSpawnSpray . penOwner = this ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +penSpray -> Initialize (eSpawnSpray ); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +CPlacement3D plSplash = GetPlacement (); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +CEntityPointer penSplash = CreateEntity (plSplash , CLASS_BASIC_EFFECT ); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +ESpawnEffect ese ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +ese . betType = BET_GIZMO_SPLASH_FX ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +penSplash -> Initialize (ese ); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +BOOL CGizmo::ShouldBlowUp(void) +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +return TRUE ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} + void CGizmo::LeaveStain(BOOL bGrow) +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +ESpawnEffect ese ; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT3D vPoint ; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOATplane3D vPlaneNormal ; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT fDistanceToEdge ; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOATaabbox3D box ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +GetBoundingBox (box ); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )) +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 0.5f) +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT fStretch = box . Size () . Length (); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +ese . betType = BET_GIZMOSTAIN ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +ese . vStretch = FLOAT3D (fStretch * 0.75f , fStretch * 0.75f , 1.0f); +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +ese . vDirection = FLOAT3D (0 , 0 , 0); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT3D vPos = vPoint + ese . vNormal / 50.0f * (FRnd () + 0.5f); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +CEntityPointer penEffect = CreateEntity (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0)) , CLASS_BASIC_EFFECT ); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +penEffect -> Initialize (ese ); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} +BOOL CGizmo:: +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PerformAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGizmo_PerformAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGizmo::PerformAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +Jump(STATE_CURRENT,0x014f0005, FALSE, EInternal());return TRUE;}BOOL CGizmo::H0x014f0005_PerformAttack_05(const CEntityEvent &__eeInput) +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014f0005 +if(!(TRUE )){ Jump(STATE_CURRENT,0x014f0006, FALSE, EInternal());return TRUE;} +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +if(ShouldCeaseAttack ()) +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetTargetNone (); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +Return(STATE_CURRENT,EReturn ()); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +return TRUE; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT fWaitTime = 0.25f + FRnd () * 0.4f; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetTimerAfter(fWaitTime ); +Jump(STATE_CURRENT, 0x014f0001, FALSE, EBegin());return TRUE;}BOOL CGizmo::H0x014f0001_PerformAttack_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014f0001 +switch(__eeInput.ee_slEvent) +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ESound):{const ESound&e= (ESound&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EWatch):{const EWatch&e= (EWatch&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x014f0002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +}return TRUE;}BOOL CGizmo::H0x014f0002_PerformAttack_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014f0002 + +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +STATE_CGizmo_JumpOnce, TRUE; +Jump(STATE_CURRENT, 0x014f0003, FALSE, EBegin());return TRUE;}BOOL CGizmo::H0x014f0003_PerformAttack_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014f0003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CGizmo_JumpOnce, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x014f0004, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CGizmo::H0x014f0004_PerformAttack_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x014f0004 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x014f0005, FALSE, EInternal());return TRUE; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +}BOOL CGizmo::H0x014f0006_PerformAttack_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014f0006 + ASSERT(FALSE); return TRUE;};BOOL CGizmo:: +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +JumpOnce(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGizmo_JumpOnce + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGizmo::JumpOnce expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_vDesiredPosition = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fMoveFrequency = 0.1f; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +if(CalcPlaneDist (m_penEnemy ) < 10.0f) +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fMoveSpeed = m_fCloseRunSpeed * 1.5f; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_aRotateSpeed = m_aCloseRotateSpeed * 0.5f; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT fSpeedX = 0.0f; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT fSpeedY = 10.0f; +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT fSpeedZ = - m_fMoveSpeed ; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +if(! IsInFrustum (m_penEnemy , CosFast (30.0f))) +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_aRotateSpeed = m_aCloseRotateSpeed * 1.5f; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +fSpeedY /= 2.0f; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +fSpeedZ /= 4.0f; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PlaySound (m_soSound , SOUND_JUMP , SOF_3D ); +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +else +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PlaySound (m_soSound , SOUND_DEATH_JUMP , SOF_3D ); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT3D vTranslation (fSpeedX , fSpeedY , fSpeedZ ); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetDesiredTranslation (vTranslation ); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +MortalJumpAnim (); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +else +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fMoveSpeed = m_fCloseRunSpeed ; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_aRotateSpeed = m_aCloseRotateSpeed ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT fSpeedX = (FRnd () - 0.5f) * 10.0f; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT fSpeedY = FRnd () * 5.0f + 5.0f; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT fSpeedZ = - m_fMoveSpeed - FRnd () * 2.5f; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT3D vTranslation (fSpeedX , fSpeedY , fSpeedZ ); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetDesiredTranslation (vTranslation ); +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +RunningAnim (); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PlaySound (m_soSound , SOUND_JUMP , SOF_3D ); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +Jump(STATE_CURRENT,0x014f000a, FALSE, EInternal());return TRUE;}BOOL CGizmo::H0x014f000a_JumpOnce_03(const CEntityEvent &__eeInput) +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014f000a +if(!(TRUE )){ Jump(STATE_CURRENT,0x014f000b, FALSE, EInternal());return TRUE;} +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fMoveSpeed = 0.0f; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_aRotateSpeed = m_aCloseRotateSpeed ; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +FLOAT3D vTranslation = GetDesiredTranslation (); +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetDesiredMovement (); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetDesiredTranslation (vTranslation ); +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetTimerAfter(m_fMoveFrequency ); +Jump(STATE_CURRENT, 0x014f0008, FALSE, EBegin());return TRUE;}BOOL CGizmo::H0x014f0008_JumpOnce_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x014f0008 +switch(__eeInput.ee_slEvent) +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ESound):{const ESound&e= (ESound&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EWatch):{const EWatch&e= (EWatch&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x014f0009, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETouch): +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{const ETouch&etouch= (ETouch&)__eeInput; + +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +if(etouch . penOther -> GetRenderType () & RT_BRUSH ) +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +Return(STATE_CURRENT,EReturn ()); +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +return TRUE; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +else if(IsDerivedFromClass (etouch . penOther , "Player")) +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +{ +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +InflictDirectDamage (etouch . penOther , this , DMT_IMPACT , 10.0f , +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +GetPlacement () . pl_PositionVector , - en_vGravityDir ); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetHealth (- 10000.0f); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_vDamage = FLOAT3D (0 , 10000 , 0); +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SendEvent (EDeath ()); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +} +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +return TRUE; +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +}return TRUE;}BOOL CGizmo::H0x014f0009_JumpOnce_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014f0009 +Jump(STATE_CURRENT,0x014f000a, FALSE, EInternal());return TRUE; +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +}BOOL CGizmo::H0x014f000b_JumpOnce_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x014f000b + ASSERT(FALSE); return TRUE;};BOOL CGizmo:: +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGizmo_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGizmo::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +InitAsModel (); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetCollisionFlags (ECF_MODEL ); +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetHealth (9.5f); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fMaxHealth = 9.5f; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +en_tmMaxHoldBreath = 5.0f; +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +en_fDensity = 2000.0f; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fBlowUpSize = 2.0f; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetModel (MODEL_GIZMO ); +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +SetModelMainTexture (TEXTURE_GIZMO ); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fWalkSpeed = FRnd () + 1.5f; +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 500.0f); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fAttackRunSpeed = FRnd () * 5.0f + 15.0f; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 100 + 600.0f); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fCloseRunSpeed = FRnd () * 5.0f + 15.0f; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_aCloseRotateSpeed = AngleDeg (360.0f); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fAttackDistance = 400.0f; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fCloseDistance = 250.0f; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fStopDistance = 0.0f; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fAttackFireTime = 2.0f; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fCloseFireTime = 0.5f; +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fIgnoreRange = 500.0f; +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fBlowUpAmount = 0.0f; +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fBodyParts = 0; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_fDamageWounded = 0.0f; +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_iScore = 500; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +m_sptType = SPT_SLIME ; +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +en_fDeceleration = 150.0f; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +GetModelObject () -> StretchModel (FLOAT3D (1.25f , 1.25f , 1.25f)); +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +ModelChangeNotify (); +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +StandingAnim (); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Gizmo.es b/Sources/EntitiesMP/Gizmo.es new file mode 100644 index 0000000..2c6be11 --- /dev/null +++ b/Sources/EntitiesMP/Gizmo.es @@ -0,0 +1,344 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +335 +%{ +#include "StdH.h" +#include "Models/Enemies/Gizmo/Gizmo.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/BasicEffects"; + +%{ +// info structure +static EntityInfo eiGizmo = { + EIBT_FLESH, 100.0f, + 0.0f, 1.3f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +#define EXPLODE_GIZMO 2.5f +%} + +class CGizmo: CEnemyBase { +name "Gizmo"; +thumbnail "Thumbnails\\Gizmo.tbn"; + +properties: + // class internal + 1 BOOL m_bExploded = FALSE, + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + 2 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + 3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + +// ************** DATA ************** + 10 model MODEL_GIZMO "Models\\Enemies\\Gizmo\\Gizmo.mdl", + 20 texture TEXTURE_GIZMO "Models\\Enemies\\Gizmo\\Gizmo.tex", + + 50 sound SOUND_IDLE "Models\\Enemies\\Gizmo\\Sounds\\Idle.wav", + 51 sound SOUND_JUMP "Models\\Enemies\\Gizmo\\Sounds\\Jump.wav", + 52 sound SOUND_DEATH_JUMP "Models\\Enemies\\Gizmo\\Sounds\\JumpDeath.wav", + 53 sound SOUND_SIGHT "Models\\Enemies\\Gizmo\\Sounds\\Sight.wav", + +functions: + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("%s ate a marsh hopper"), strPlayerName); + return str; + } + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnm, "Data\\Messages\\Enemies\\Gizmo.txt"); + return fnm; + }; + /* Entity info */ + void *GetEntityInfo(void) + { + return &eiGizmo; + }; + + void Precache(void) + { + CEnemyBase::Precache(); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_IDLE); + PrecacheSound(SOUND_JUMP); + PrecacheSound(SOUND_DEATH_JUMP); + PrecacheClass(CLASS_BASIC_EFFECT, BET_GIZMO_SPLASH_FX); + PrecacheClass(CLASS_BLOOD_SPRAY); + }; + + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + + void RunningAnim(void) + { + StartModelAnim(GIZMO_ANIM_RUN, 0); + }; + + void MortalJumpAnim(void) + { + StartModelAnim(GIZMO_ANIM_RUN, 0); + }; + + void StandAnim(void) + { + StartModelAnim(GIZMO_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + +/************************************************************ + * BLOW UP FUNCTIONS * + ************************************************************/ + void BlowUpNotify(void) { + Explode(); + }; + + // explode only once + void Explode(void) + { + if (!m_bExploded) + { + m_bExploded = TRUE; + // spawn blood spray + CPlacement3D plSpray = GetPlacement(); + CEntity *penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 2.0f; + eSpawnSpray.fSizeMultiplier = 1.0f; + eSpawnSpray.sptType = SPT_SLIME; + eSpawnSpray.vDirection = en_vCurrentTranslationAbsolute/8.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); + + // spawn splash fx (sound) + CPlacement3D plSplash = GetPlacement(); + CEntityPointer penSplash = CreateEntity(plSplash, CLASS_BASIC_EFFECT); + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_GIZMO_SPLASH_FX; + penSplash->Initialize(ese); + } + }; + + + // gizmo should always blow up + BOOL ShouldBlowUp(void) + { + return TRUE; + } + + + // leave stain + virtual void LeaveStain(BOOL bGrow) + { + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + // get your size + FLOATaabbox3D box; + GetBoundingBox(box); + + // on plane + if( GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) + { + // if near to polygon and away from last stain point + if( (vPoint-GetPlacement().pl_PositionVector).Length()<0.5f ) + { + FLOAT fStretch = box.Size().Length(); + // stain + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_GIZMOSTAIN; + ese.vStretch = FLOAT3D( fStretch*0.75f, fStretch*0.75f, 1.0f); + ese.vNormal = FLOAT3D( vPlaneNormal); + ese.vDirection = FLOAT3D( 0, 0, 0); + FLOAT3D vPos = vPoint+ese.vNormal/50.0f*(FRnd()+0.5f); + CEntityPointer penEffect = CreateEntity( CPlacement3D(vPos, ANGLE3D(0,0,0)), CLASS_BASIC_EFFECT); + penEffect->Initialize(ese); + } + } + }; + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + // close range -> move toward enemy and try to jump onto it + PerformAttack(EVoid) : CEnemyBase::PerformAttack + { + while (TRUE) + { + // ------------ Exit close attack if out of range or enemy is dead + // if attacking is futile + if (ShouldCeaseAttack()) + { + SetTargetNone(); + return EReturn(); + } + + // stop moving + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + + // ------------ Wait for some time on the ground + FLOAT fWaitTime = 0.25f+FRnd()*0.4f; + wait( fWaitTime) + { + on (EBegin) : { resume; }; + on (ESound) : { resume; } // ignore all sounds + on (EWatch) : { resume; } // ignore watch + on (ETimer) : { stop; } // timer tick expire + } + + autocall JumpOnce() EReturn; + } + } + + JumpOnce(EVoid) + { + // ------------ Jump either in slightly randomized direction or mortal, streight and fast toward enemy + // we are always going for enemy + m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector; + m_fMoveFrequency = 0.1f; + // if we are close enough for mortal jump + if( CalcPlaneDist(m_penEnemy) < 10.0f) + { + // set mortal jump parameters (no random) + m_fMoveSpeed = m_fCloseRunSpeed*1.5f; + m_aRotateSpeed = m_aCloseRotateSpeed*0.5f; + FLOAT fSpeedX = 0.0f; + FLOAT fSpeedY = 10.0f; + FLOAT fSpeedZ = -m_fMoveSpeed; + // if can't see enemy + if( !IsInFrustum(m_penEnemy, CosFast(30.0f))) + { + // rotate a lot + m_aRotateSpeed = m_aCloseRotateSpeed*1.5f; + // but don't jump too much + fSpeedY /= 2.0f; + fSpeedZ /= 4.0f; + PlaySound(m_soSound, SOUND_JUMP, SOF_3D); + } + else + { + PlaySound(m_soSound, SOUND_DEATH_JUMP, SOF_3D); + } + FLOAT3D vTranslation(fSpeedX, fSpeedY, fSpeedZ); + SetDesiredTranslation(vTranslation); + MortalJumpAnim(); + } + // start slightly randomized jump + else + { + m_fMoveSpeed = m_fCloseRunSpeed; + m_aRotateSpeed = m_aCloseRotateSpeed; + // set random jump parameters + FLOAT fSpeedX = (FRnd()-0.5f)*10.0f; + FLOAT fSpeedY = FRnd()*5.0f+5.0f; + FLOAT fSpeedZ = -m_fMoveSpeed-FRnd()*2.5f; + FLOAT3D vTranslation(fSpeedX, fSpeedY, fSpeedZ); + SetDesiredTranslation(vTranslation); + RunningAnim(); + PlaySound(m_soSound, SOUND_JUMP, SOF_3D); + } + + // ------------ While in air, adjust directions, on touch start new jump or explode + while (TRUE) + { + // adjust direction and speed + m_fMoveSpeed = 0.0f; + m_aRotateSpeed = m_aCloseRotateSpeed; + FLOAT3D vTranslation = GetDesiredTranslation(); + SetDesiredMovement(); + SetDesiredTranslation(vTranslation); + + wait(m_fMoveFrequency) + { + on (EBegin) : { resume; }; + on (ESound) : { resume; } // ignore all sounds + on (EWatch) : { resume; } // ignore watch + on (ETimer) : { stop; } // timer tick expire + on (ETouch etouch) : + { + // if we touched ground + if( etouch.penOther->GetRenderType() & RT_BRUSH) + { + return EReturn(); + } + // we touched player, explode + else if ( IsDerivedFromClass( etouch.penOther, "Player")) + { + InflictDirectDamage(etouch.penOther, this, DMT_IMPACT, 10.0f, + GetPlacement().pl_PositionVector, -en_vGravityDir); + SetHealth(-10000.0f); + m_vDamage = FLOAT3D(0,10000,0); + SendEvent(EDeath()); + } + // we didn't touch ground nor player, ignore + resume; + } + } + } + }; + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + SetHealth(9.5f); + m_fMaxHealth = 9.5f; + en_tmMaxHoldBreath = 5.0f; + en_fDensity = 2000.0f; + m_fBlowUpSize = 2.0f; + + // set your appearance + SetModel(MODEL_GIZMO); + SetModelMainTexture(TEXTURE_GIZMO); + // setup moving speed + m_fWalkSpeed = FRnd() + 1.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f); + m_fAttackRunSpeed = FRnd()*5.0f + 15.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*100 + 600.0f); + m_fCloseRunSpeed = FRnd()*5.0f + 15.0f; + m_aCloseRotateSpeed = AngleDeg(360.0f); + // setup attack distances + m_fAttackDistance = 400.0f; + m_fCloseDistance = 250.0f; + m_fStopDistance = 0.0f; + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 0.5f; + m_fIgnoreRange = 500.0f; + // damage/explode properties + m_fBlowUpAmount = 0.0f; + m_fBodyParts = 0; + m_fDamageWounded = 0.0f; + m_iScore = 500; + m_sptType = SPT_SLIME; + + en_fDeceleration = 150.0f; + + // set stretch factors for height and width + GetModelObject()->StretchModel(FLOAT3D(1.25f, 1.25f, 1.25f)); + ModelChangeNotify(); + StandingAnim(); + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Gizmo.h b/Sources/EntitiesMP/Gizmo.h new file mode 100644 index 0000000..37975d3 --- /dev/null +++ b/Sources/EntitiesMP/Gizmo.h @@ -0,0 +1,76 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Gizmo_INCLUDED +#define _EntitiesMP_Gizmo_INCLUDED 1 +#include +#include +extern "C" DECL_DLL CDLLEntityClass CGizmo_DLLClass; +class CGizmo : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bExploded; + +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void * GetEntityInfo(void); + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void Precache(void); + +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void SightSound(void); + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void RunningAnim(void); + +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void MortalJumpAnim(void); + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void StandAnim(void); + +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void IdleSound(void); + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void BlowUpNotify(void); + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +void Explode(void); + +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +BOOL ShouldBlowUp(void); + +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +virtual void LeaveStain(BOOL bGrow); +#define STATE_CGizmo_PerformAttack 0x014f0000 + BOOL +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PerformAttack(const CEntityEvent &__eeInput); + BOOL H0x014f0001_PerformAttack_01(const CEntityEvent &__eeInput); + BOOL H0x014f0002_PerformAttack_02(const CEntityEvent &__eeInput); + BOOL H0x014f0003_PerformAttack_03(const CEntityEvent &__eeInput); + BOOL H0x014f0004_PerformAttack_04(const CEntityEvent &__eeInput); + BOOL H0x014f0005_PerformAttack_05(const CEntityEvent &__eeInput); + BOOL H0x014f0006_PerformAttack_06(const CEntityEvent &__eeInput); +#define STATE_CGizmo_JumpOnce 0x014f0007 + BOOL +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +JumpOnce(const CEntityEvent &__eeInput); + BOOL H0x014f0008_JumpOnce_01(const CEntityEvent &__eeInput); + BOOL H0x014f0009_JumpOnce_02(const CEntityEvent &__eeInput); + BOOL H0x014f000a_JumpOnce_03(const CEntityEvent &__eeInput); + BOOL H0x014f000b_JumpOnce_04(const CEntityEvent &__eeInput); +#define STATE_CGizmo_Main 1 + BOOL +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Gizmo_INCLUDED diff --git a/Sources/EntitiesMP/Gizmo_tables.h b/Sources/EntitiesMP/Gizmo_tables.h new file mode 100644 index 0000000..9453607 --- /dev/null +++ b/Sources/EntitiesMP/Gizmo_tables.h @@ -0,0 +1,66 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CGizmo + +CEntityProperty CGizmo_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000014f<<8)+1, offsetof(CGizmo, m_bExploded), "", 0, 0, 0), +}; +#define CGizmo_propertiesct ARRAYCOUNT(CGizmo_properties) + +CEntityComponent CGizmo_components[] = { +#define CLASS_BASE ((0x0000014f<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_BLOOD_SPRAY ((0x0000014f<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define CLASS_BASIC_EFFECT ((0x0000014f<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define MODEL_GIZMO ((0x0000014f<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_GIZMO, "EFNM" "Models\\Enemies\\Gizmo\\Gizmo.mdl"), +#define TEXTURE_GIZMO ((0x0000014f<<8)+20) + CEntityComponent(ECT_TEXTURE, TEXTURE_GIZMO, "EFNM" "Models\\Enemies\\Gizmo\\Gizmo.tex"), +#define SOUND_IDLE ((0x0000014f<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "Models\\Enemies\\Gizmo\\Sounds\\Idle.wav"), +#define SOUND_JUMP ((0x0000014f<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_JUMP, "EFNM" "Models\\Enemies\\Gizmo\\Sounds\\Jump.wav"), +#define SOUND_DEATH_JUMP ((0x0000014f<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_DEATH_JUMP, "EFNM" "Models\\Enemies\\Gizmo\\Sounds\\JumpDeath.wav"), +#define SOUND_SIGHT ((0x0000014f<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "Models\\Enemies\\Gizmo\\Sounds\\Sight.wav"), +}; +#define CGizmo_componentsct ARRAYCOUNT(CGizmo_components) + +CEventHandlerEntry CGizmo_handlers[] = { + {0x014f0000, STATE_CEnemyBase_PerformAttack, CEntity::pEventHandler(&CGizmo:: +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +PerformAttack),DEBUGSTRING("CGizmo::PerformAttack")}, + {0x014f0001, -1, CEntity::pEventHandler(&CGizmo::H0x014f0001_PerformAttack_01), DEBUGSTRING("CGizmo::H0x014f0001_PerformAttack_01")}, + {0x014f0002, -1, CEntity::pEventHandler(&CGizmo::H0x014f0002_PerformAttack_02), DEBUGSTRING("CGizmo::H0x014f0002_PerformAttack_02")}, + {0x014f0003, -1, CEntity::pEventHandler(&CGizmo::H0x014f0003_PerformAttack_03), DEBUGSTRING("CGizmo::H0x014f0003_PerformAttack_03")}, + {0x014f0004, -1, CEntity::pEventHandler(&CGizmo::H0x014f0004_PerformAttack_04), DEBUGSTRING("CGizmo::H0x014f0004_PerformAttack_04")}, + {0x014f0005, -1, CEntity::pEventHandler(&CGizmo::H0x014f0005_PerformAttack_05), DEBUGSTRING("CGizmo::H0x014f0005_PerformAttack_05")}, + {0x014f0006, -1, CEntity::pEventHandler(&CGizmo::H0x014f0006_PerformAttack_06), DEBUGSTRING("CGizmo::H0x014f0006_PerformAttack_06")}, + {0x014f0007, -1, CEntity::pEventHandler(&CGizmo:: +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +JumpOnce),DEBUGSTRING("CGizmo::JumpOnce")}, + {0x014f0008, -1, CEntity::pEventHandler(&CGizmo::H0x014f0008_JumpOnce_01), DEBUGSTRING("CGizmo::H0x014f0008_JumpOnce_01")}, + {0x014f0009, -1, CEntity::pEventHandler(&CGizmo::H0x014f0009_JumpOnce_02), DEBUGSTRING("CGizmo::H0x014f0009_JumpOnce_02")}, + {0x014f000a, -1, CEntity::pEventHandler(&CGizmo::H0x014f000a_JumpOnce_03), DEBUGSTRING("CGizmo::H0x014f000a_JumpOnce_03")}, + {0x014f000b, -1, CEntity::pEventHandler(&CGizmo::H0x014f000b_JumpOnce_04), DEBUGSTRING("CGizmo::H0x014f000b_JumpOnce_04")}, + {1, -1, CEntity::pEventHandler(&CGizmo:: +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Gizmo.es" +Main),DEBUGSTRING("CGizmo::Main")}, +}; +#define CGizmo_handlersct ARRAYCOUNT(CGizmo_handlers) + +CEntity *CGizmo_New(void) { return new CGizmo; }; +void CGizmo_OnInitClass(void) {}; +void CGizmo_OnEndClass(void) {}; +void CGizmo_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CGizmo_OnWorldEnd(CWorld *pwo) {}; +void CGizmo_OnWorldInit(CWorld *pwo) {}; +void CGizmo_OnWorldTick(CWorld *pwo) {}; +void CGizmo_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CGizmo, CEnemyBase, "Gizmo", "Thumbnails\\Gizmo.tbn", 0x0000014f); +DECLARE_CTFILENAME(_fnmCGizmo_tbn, "Thumbnails\\Gizmo.tbn"); diff --git a/Sources/EntitiesMP/Global.cpp b/Sources/EntitiesMP/Global.cpp new file mode 100644 index 0000000..c601b16 --- /dev/null +++ b/Sources/EntitiesMP/Global.cpp @@ -0,0 +1,118 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Global.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *EStop::MakeCopy(void) { CEntityEvent *peeCopy = new EStop(*this); return peeCopy;} +EStop::EStop() : CEntityEvent(EVENTCODE_EStop) {; +}; +CEntityEvent *EStart::MakeCopy(void) { CEntityEvent *peeCopy = new EStart(*this); return peeCopy;} +EStart::EStart() : CEntityEvent(EVENTCODE_EStart) {; + ClearToDefault(penCaused); +}; +CEntityEvent *EActivate::MakeCopy(void) { CEntityEvent *peeCopy = new EActivate(*this); return peeCopy;} +EActivate::EActivate() : CEntityEvent(EVENTCODE_EActivate) {; +}; +CEntityEvent *EDeactivate::MakeCopy(void) { CEntityEvent *peeCopy = new EDeactivate(*this); return peeCopy;} +EDeactivate::EDeactivate() : CEntityEvent(EVENTCODE_EDeactivate) {; +}; +CEntityEvent *EEnvironmentStart::MakeCopy(void) { CEntityEvent *peeCopy = new EEnvironmentStart(*this); return peeCopy;} +EEnvironmentStart::EEnvironmentStart() : CEntityEvent(EVENTCODE_EEnvironmentStart) {; +}; +CEntityEvent *EEnvironmentStop::MakeCopy(void) { CEntityEvent *peeCopy = new EEnvironmentStop(*this); return peeCopy;} +EEnvironmentStop::EEnvironmentStop() : CEntityEvent(EVENTCODE_EEnvironmentStop) {; +}; +CEntityEvent *EEnd::MakeCopy(void) { CEntityEvent *peeCopy = new EEnd(*this); return peeCopy;} +EEnd::EEnd() : CEntityEvent(EVENTCODE_EEnd) {; +}; +CEntityEvent *ETrigger::MakeCopy(void) { CEntityEvent *peeCopy = new ETrigger(*this); return peeCopy;} +ETrigger::ETrigger() : CEntityEvent(EVENTCODE_ETrigger) {; + ClearToDefault(penCaused); +}; +CEntityEvent *ETeleportMovingBrush::MakeCopy(void) { CEntityEvent *peeCopy = new ETeleportMovingBrush(*this); return peeCopy;} +ETeleportMovingBrush::ETeleportMovingBrush() : CEntityEvent(EVENTCODE_ETeleportMovingBrush) {; +}; +CEntityEvent *EReminder::MakeCopy(void) { CEntityEvent *peeCopy = new EReminder(*this); return peeCopy;} +EReminder::EReminder() : CEntityEvent(EVENTCODE_EReminder) {; + ClearToDefault(iValue); +}; +CEntityEvent *EStartAttack::MakeCopy(void) { CEntityEvent *peeCopy = new EStartAttack(*this); return peeCopy;} +EStartAttack::EStartAttack() : CEntityEvent(EVENTCODE_EStartAttack) {; +}; +CEntityEvent *EStopAttack::MakeCopy(void) { CEntityEvent *peeCopy = new EStopAttack(*this); return peeCopy;} +EStopAttack::EStopAttack() : CEntityEvent(EVENTCODE_EStopAttack) {; +}; +CEntityEvent *EStopBlindness::MakeCopy(void) { CEntityEvent *peeCopy = new EStopBlindness(*this); return peeCopy;} +EStopBlindness::EStopBlindness() : CEntityEvent(EVENTCODE_EStopBlindness) {; +}; +CEntityEvent *EStopDeafness::MakeCopy(void) { CEntityEvent *peeCopy = new EStopDeafness(*this); return peeCopy;} +EStopDeafness::EStopDeafness() : CEntityEvent(EVENTCODE_EStopDeafness) {; +}; +CEntityEvent *EReceiveScore::MakeCopy(void) { CEntityEvent *peeCopy = new EReceiveScore(*this); return peeCopy;} +EReceiveScore::EReceiveScore() : CEntityEvent(EVENTCODE_EReceiveScore) {; + ClearToDefault(iPoints); +}; +CEntityEvent *EKilledEnemy::MakeCopy(void) { CEntityEvent *peeCopy = new EKilledEnemy(*this); return peeCopy;} +EKilledEnemy::EKilledEnemy() : CEntityEvent(EVENTCODE_EKilledEnemy) {; +}; +CEntityEvent *ESecretFound::MakeCopy(void) { CEntityEvent *peeCopy = new ESecretFound(*this); return peeCopy;} +ESecretFound::ESecretFound() : CEntityEvent(EVENTCODE_ESecretFound) {; +}; +CEntityEvent *ESound::MakeCopy(void) { CEntityEvent *peeCopy = new ESound(*this); return peeCopy;} +ESound::ESound() : CEntityEvent(EVENTCODE_ESound) {; + ClearToDefault(EsndtSound); + ClearToDefault(penTarget); +}; +CEntityEvent *EScroll::MakeCopy(void) { CEntityEvent *peeCopy = new EScroll(*this); return peeCopy;} +EScroll::EScroll() : CEntityEvent(EVENTCODE_EScroll) {; + ClearToDefault(bStart); + ClearToDefault(penSender); +}; +CEntityEvent *ETextFX::MakeCopy(void) { CEntityEvent *peeCopy = new ETextFX(*this); return peeCopy;} +ETextFX::ETextFX() : CEntityEvent(EVENTCODE_ETextFX) {; + ClearToDefault(bStart); + ClearToDefault(penSender); +}; +CEntityEvent *EHudPicFX::MakeCopy(void) { CEntityEvent *peeCopy = new EHudPicFX(*this); return peeCopy;} +EHudPicFX::EHudPicFX() : CEntityEvent(EVENTCODE_EHudPicFX) {; + ClearToDefault(bStart); + ClearToDefault(penSender); +}; +CEntityEvent *ECredits::MakeCopy(void) { CEntityEvent *peeCopy = new ECredits(*this); return peeCopy;} +ECredits::ECredits() : CEntityEvent(EVENTCODE_ECredits) {; + ClearToDefault(bStart); + ClearToDefault(penSender); +}; +CEntityEvent *ECenterMessage::MakeCopy(void) { CEntityEvent *peeCopy = new ECenterMessage(*this); return peeCopy;} +ECenterMessage::ECenterMessage() : CEntityEvent(EVENTCODE_ECenterMessage) {; + ClearToDefault(strMessage); + ClearToDefault(tmLength); + ClearToDefault(mssSound); +}; +CEntityEvent *EComputerMessage::MakeCopy(void) { CEntityEvent *peeCopy = new EComputerMessage(*this); return peeCopy;} +EComputerMessage::EComputerMessage() : CEntityEvent(EVENTCODE_EComputerMessage) {; + ClearToDefault(fnmMessage); +}; +CEntityEvent *EVoiceMessage::MakeCopy(void) { CEntityEvent *peeCopy = new EVoiceMessage(*this); return peeCopy;} +EVoiceMessage::EVoiceMessage() : CEntityEvent(EVENTCODE_EVoiceMessage) {; + ClearToDefault(fnmMessage); +}; +CEntityEvent *EHitBySpaceShipBeam::MakeCopy(void) { CEntityEvent *peeCopy = new EHitBySpaceShipBeam(*this); return peeCopy;} +EHitBySpaceShipBeam::EHitBySpaceShipBeam() : CEntityEvent(EVENTCODE_EHitBySpaceShipBeam) {; +}; +void CGlobal::SetDefaultProperties(void) { + CEntity::SetDefaultProperties(); +} +BOOL CGlobal:: +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Global.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGlobal_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGlobal::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Global.es" +ASSERTALWAYS ("DON'T INSTANTIATE THIS CLASS"); ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Global.es b/Sources/EntitiesMP/Global.es new file mode 100644 index 0000000..90a7785 --- /dev/null +++ b/Sources/EntitiesMP/Global.es @@ -0,0 +1,300 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +0 +%{ +#include "StdH.h" +%} + +/* + * + * --->>> DON'T INSTANTIATE THIS CLASS <<<--- + * + */ + +event EStop { // stop your actions +}; +event EStart { // start your actions + CEntityPointer penCaused, // who caused the trigger (transitive) +}; +event EActivate { // activate class (usually touch field) +}; +event EDeactivate { // deactivate class (usually touch field) +}; +event EEnvironmentStart { // activate environment classes +}; +event EEnvironmentStop { // deactivate environment classes +}; +event EEnd { // general purpose end of procedure event +}; +event ETrigger { // sent by trigger class + CEntityPointer penCaused, // who caused the trigger (transitive) +}; +event ETeleportMovingBrush { // teleport moving brush +}; +event EReminder { // reminder event + INDEX iValue, // value for return +}; +event EStartAttack { // OBSOLETE! +}; +event EStopAttack { // OBSOLETE! +}; +event EStopBlindness { // make enemy not blind any more +}; +event EStopDeafness { // make enemy not blind any more +}; +event EReceiveScore { // sent to player when enemy is killed + INDEX iPoints +}; +event EKilledEnemy { // sent to player when enemy is killed +}; +event ESecretFound { // sent to player secret is found +}; + +enum BoolEType { + 0 BET_TRUE "True", // true + 1 BET_FALSE "False", // false + 2 BET_IGNORE "Ignore", // ignore +}; + +enum EventEType { + 0 EET_START "Start event", // start event + 1 EET_STOP "Stop event", // stop event + 2 EET_TRIGGER "Trigger event", // trigger event + 3 EET_IGNORE "Don't send event", // don't send event (ignore) + 4 EET_ACTIVATE "Activate event", // activate event + 5 EET_DEACTIVATE "Deactivate event", // deactivate event + 6 EET_ENVIRONMENTSTART "Start environment event", // start environment event + 7 EET_ENVIRONMENTSTOP "Stop environment event", // stop environment event + 8 EET_STARTATTACK "OBSOLETE! - Start attack event", // start attack enemy + 9 EET_STOPATTACK "OBSOLETE! - Stop attack event", // stop attack enemy + 10 EET_STOPBLINDNESS "Stop blindness event", // enemy stop being blind + 11 EET_STOPDEAFNESS "Stop deafness event", // enemy stop being deaf + 12 EET_TELEPORTMOVINGBRUSH "Teleport moving brush", // moving brush teleporting event +}; + + +// entity info structure enums +enum EntityInfoBodyType { + 1 EIBT_FLESH "Flesh", + 2 EIBT_WATER "Water", + 3 EIBT_ROCK "Rock ", + 4 EIBT_FIRE "Fire ", + 5 EIBT_AIR "Air ", + 6 EIBT_BONES "Bones", + 7 EIBT_WOOD "Wood ", + 8 EIBT_METAL "Metal", + 9 EIBT_ROBOT "Robot", + 10 EIBT_ICE "Ice", +}; + +enum MessageSound { + 0 MSS_NONE "None", // no sound + 1 MSS_INFO "Info", // just simple info +}; + +enum ParticleTexture { + 1 PT_STAR01 "Star01", + 2 PT_STAR02 "Star02", + 3 PT_STAR03 "Star03", + 4 PT_STAR04 "Star04", + 5 PT_STAR05 "Star05", + 6 PT_STAR06 "Star06", + 7 PT_STAR07 "Star07", + 8 PT_STAR08 "Star08", + 9 PT_BOUBBLE01 "Boubble01", + 10 PT_BOUBBLE02 "Boubble02", + 11 PT_WATER01 "Water01", + 12 PT_WATER02 "Water02", + 13 PT_SANDFLOW "Sand flow", + 14 PT_WATERFLOW "Water flow", + 15 PT_LAVAFLOW "Lava flow", +}; + +enum SoundType { + 0 SNDT_NONE "", // internal + 1 SNDT_SHOUT "", // enemy shout when see player + 2 SNDT_YELL "", // enemy is wounded (or death) + 3 SNDT_EXPLOSION "", // explosion of rocket or grenade (or similar) + 4 SNDT_PLAYER "", // sound from player weapon or player is wounded +}; + +// hit enum +enum BulletHitType { + 0 BHT_NONE "", // none + 1 BHT_FLESH "", // flesh + 2 BHT_BRUSH_STONE "", // brush stone + 3 BHT_BRUSH_SAND "", // brush sand + 4 BHT_BRUSH_WATER "", // brush water + 5 BHT_BRUSH_UNDER_WATER "", // brush under water + 6 BHT_ACID "", // acid + 7 BHT_BRUSH_RED_SAND "", // brush red sand + 8 BHT_BRUSH_GRASS "", // brush grass + 9 BHT_BRUSH_WOOD "", // brush wood + 10 BHT_BRUSH_SNOW "", // brush snow +}; + +enum EffectParticlesType { + 0 EPT_NONE "", // no partcicles + 1 EPT_BULLET_STONE "", // bullet particles on stone + 2 EPT_BULLET_SAND "", // bullet particles on sand + 3 EPT_BULLET_WATER "", // bullet particles on water + 4 EPT_BULLET_UNDER_WATER "", // bullet particles underwater + 5 EPT_BULLET_RED_SAND "", // bullet particles on red sand + 6 EPT_BULLET_GRASS "", // bullet particles on sand + 7 EPT_BULLET_WOOD "", // bullet particles on sand + 8 EPT_BULLET_SNOW "", // bullet particles on snow +}; + +enum SprayParticlesType { + 0 SPT_NONE "None", // no particles + 1 SPT_BLOOD "Blood", // blood + 2 SPT_BONES "Bones", // bones + 3 SPT_FEATHER "Feather", // feather + 4 SPT_STONES "Stones", // stones + 5 SPT_WOOD "Wood", // wood + 6 SPT_SLIME "Slime", // gizmo/beast slime + 7 SPT_LAVA_STONES "Lava Stones", // lava stones + 8 SPT_ELECTRICITY_SPARKS "Electricity sparks", // electricity sparks with blood + 9 SPT_BEAST_PROJECTILE_SPRAY "Beast projectile spray", // beast projectile explosion sparks + 10 SPT_SMALL_LAVA_STONES "Small Lava Stones", // small lava stones + 11 SPT_AIRSPOUTS "Air", // air + 12 SPT_ELECTRICITY_SPARKS_NO_BLOOD "Electricity w/o blood", // no blood electricity + 13 SPT_PLASMA "Plasma", // plasma + 14 SPT_GOO "Goo", // yellow bloodlike substance + 15 SPT_TREE01 "Tree 01", // tree 01 + 16 SPT_COLOREDSTONE "Colored stone", // colored stone +}; + +// weapon bits +enum WeaponBits { + 0 WB_00 "Knife", + 1 WB_01 "Colt", + 2 WB_02 "Double colt", + 3 WB_03 "Single shotgun", + 4 WB_04 "Double shotgun", + 5 WB_05 "Tommygun", + 6 WB_06 "Minigun", + 7 WB_07 "Rocket launcher", + 8 WB_08 "Grenade launcher", + 9 WB_09 "Chainsaw", + 10 WB_10 "Flamer", + 11 WB_11 "Laser", + 12 WB_12 "Sniper", + 13 WB_13 "Ironcannon", + 14 WB_14 "", + 15 WB_15 "", + 16 WB_16 "", + 17 WB_17 "", + 18 WB_18 "", + 19 WB_19 "", + 20 WB_20 "", + 21 WB_21 "", + 22 WB_22 "", + 23 WB_23 "", + 24 WB_24 "", + 25 WB_25 "", + 26 WB_26 "", + 27 WB_27 "", + 28 WB_28 "", + 29 WB_29 "", + 30 WB_30 "", + 31 WB_31 "", +}; + +// clasification bits +enum ClasificationBits { + 16 CB_00 "Bit 16", + 17 CB_01 "Bit 17", + 18 CB_02 "Bit 18", + 19 CB_03 "Bit 19", + 20 CB_04 "Bit 20", + 21 CB_05 "Bit 21", + 22 CB_06 "Bit 22", + 23 CB_07 "Bit 23", + 24 CB_08 "Bit 24", + 25 CB_09 "Bit 25", + 26 CB_10 "Bit 26", + 27 CB_11 "Bit 27", + 28 CB_12 "Bit 28", + 29 CB_13 "Bit 29", + 30 CB_14 "Bit 30", + 31 CB_15 "Bit 31", +}; + +// visibility bits +enum VisibilityBits { + 0 VB_00 "Bit 00", + 1 VB_01 "Bit 01", + 2 VB_02 "Bit 02", + 3 VB_03 "Bit 03", + 4 VB_04 "Bit 04", + 5 VB_05 "Bit 05", + 6 VB_06 "Bit 06", + 7 VB_07 "Bit 07", + 8 VB_08 "Bit 08", + 9 VB_09 "Bit 09", + 10 VB_10 "Bit 10", + 11 VB_11 "Bit 11", + 12 VB_12 "Bit 12", + 13 VB_13 "Bit 13", + 14 VB_14 "Bit 14", + 15 VB_15 "Bit 15", +}; + +event ESound { + enum SoundType EsndtSound, + CEntityPointer penTarget, +}; + +event EScroll { + BOOL bStart, + CEntityPointer penSender, +}; + +event ETextFX { + BOOL bStart, + CEntityPointer penSender, +}; + +event EHudPicFX { + BOOL bStart, + CEntityPointer penSender, +}; + +event ECredits { + BOOL bStart, + CEntityPointer penSender, +}; + +// event for printing centered message +event ECenterMessage { + CTString strMessage, // the message + TIME tmLength, // how long to keep it + enum MessageSound mssSound, // sound to play +}; + +// event for sending computer message to a player +event EComputerMessage { + CTFileName fnmMessage, // the message file +}; + +// event for voice message to a player +event EVoiceMessage { + CTFileName fnmMessage, // the message file +}; + +event EHitBySpaceShipBeam { +}; + +class CGlobal : CEntity { +name ""; +thumbnail ""; + +properties: +components: +functions: +procedures: + Main(EVoid) { + ASSERTALWAYS("DON'T INSTANTIATE THIS CLASS"); + } +}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Global.h b/Sources/EntitiesMP/Global.h new file mode 100644 index 0000000..7a8b762 --- /dev/null +++ b/Sources/EntitiesMP/Global.h @@ -0,0 +1,414 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Global_INCLUDED +#define _EntitiesMP_Global_INCLUDED 1 +#define EVENTCODE_EStop 0x00000000 +class DECL_DLL EStop : public CEntityEvent { +public: +EStop(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EStop &e) { e = EStop(); } ; +#define EVENTCODE_EStart 0x00000001 +class DECL_DLL EStart : public CEntityEvent { +public: +EStart(); +CEntityEvent *MakeCopy(void); +CEntityPointer penCaused; +}; +DECL_DLL inline void ClearToDefault(EStart &e) { e = EStart(); } ; +#define EVENTCODE_EActivate 0x00000002 +class DECL_DLL EActivate : public CEntityEvent { +public: +EActivate(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EActivate &e) { e = EActivate(); } ; +#define EVENTCODE_EDeactivate 0x00000003 +class DECL_DLL EDeactivate : public CEntityEvent { +public: +EDeactivate(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EDeactivate &e) { e = EDeactivate(); } ; +#define EVENTCODE_EEnvironmentStart 0x00000004 +class DECL_DLL EEnvironmentStart : public CEntityEvent { +public: +EEnvironmentStart(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EEnvironmentStart &e) { e = EEnvironmentStart(); } ; +#define EVENTCODE_EEnvironmentStop 0x00000005 +class DECL_DLL EEnvironmentStop : public CEntityEvent { +public: +EEnvironmentStop(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EEnvironmentStop &e) { e = EEnvironmentStop(); } ; +#define EVENTCODE_EEnd 0x00000006 +class DECL_DLL EEnd : public CEntityEvent { +public: +EEnd(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EEnd &e) { e = EEnd(); } ; +#define EVENTCODE_ETrigger 0x00000007 +class DECL_DLL ETrigger : public CEntityEvent { +public: +ETrigger(); +CEntityEvent *MakeCopy(void); +CEntityPointer penCaused; +}; +DECL_DLL inline void ClearToDefault(ETrigger &e) { e = ETrigger(); } ; +#define EVENTCODE_ETeleportMovingBrush 0x00000008 +class DECL_DLL ETeleportMovingBrush : public CEntityEvent { +public: +ETeleportMovingBrush(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(ETeleportMovingBrush &e) { e = ETeleportMovingBrush(); } ; +#define EVENTCODE_EReminder 0x00000009 +class DECL_DLL EReminder : public CEntityEvent { +public: +EReminder(); +CEntityEvent *MakeCopy(void); +INDEX iValue; +}; +DECL_DLL inline void ClearToDefault(EReminder &e) { e = EReminder(); } ; +#define EVENTCODE_EStartAttack 0x0000000a +class DECL_DLL EStartAttack : public CEntityEvent { +public: +EStartAttack(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EStartAttack &e) { e = EStartAttack(); } ; +#define EVENTCODE_EStopAttack 0x0000000b +class DECL_DLL EStopAttack : public CEntityEvent { +public: +EStopAttack(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EStopAttack &e) { e = EStopAttack(); } ; +#define EVENTCODE_EStopBlindness 0x0000000c +class DECL_DLL EStopBlindness : public CEntityEvent { +public: +EStopBlindness(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EStopBlindness &e) { e = EStopBlindness(); } ; +#define EVENTCODE_EStopDeafness 0x0000000d +class DECL_DLL EStopDeafness : public CEntityEvent { +public: +EStopDeafness(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EStopDeafness &e) { e = EStopDeafness(); } ; +#define EVENTCODE_EReceiveScore 0x0000000e +class DECL_DLL EReceiveScore : public CEntityEvent { +public: +EReceiveScore(); +CEntityEvent *MakeCopy(void); +INDEX iPoints; +}; +DECL_DLL inline void ClearToDefault(EReceiveScore &e) { e = EReceiveScore(); } ; +#define EVENTCODE_EKilledEnemy 0x0000000f +class DECL_DLL EKilledEnemy : public CEntityEvent { +public: +EKilledEnemy(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EKilledEnemy &e) { e = EKilledEnemy(); } ; +#define EVENTCODE_ESecretFound 0x00000010 +class DECL_DLL ESecretFound : public CEntityEvent { +public: +ESecretFound(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(ESecretFound &e) { e = ESecretFound(); } ; +extern DECL_DLL CEntityPropertyEnumType BoolEType_enum; +enum BoolEType { + BET_TRUE = 0, + BET_FALSE = 1, + BET_IGNORE = 2, +}; +DECL_DLL inline void ClearToDefault(BoolEType &e) { e = (BoolEType)0; } ; +extern DECL_DLL CEntityPropertyEnumType EventEType_enum; +enum EventEType { + EET_START = 0, + EET_STOP = 1, + EET_TRIGGER = 2, + EET_IGNORE = 3, + EET_ACTIVATE = 4, + EET_DEACTIVATE = 5, + EET_ENVIRONMENTSTART = 6, + EET_ENVIRONMENTSTOP = 7, + EET_STARTATTACK = 8, + EET_STOPATTACK = 9, + EET_STOPBLINDNESS = 10, + EET_STOPDEAFNESS = 11, + EET_TELEPORTMOVINGBRUSH = 12, +}; +DECL_DLL inline void ClearToDefault(EventEType &e) { e = (EventEType)0; } ; +extern DECL_DLL CEntityPropertyEnumType EntityInfoBodyType_enum; +enum EntityInfoBodyType { + EIBT_FLESH = 1, + EIBT_WATER = 2, + EIBT_ROCK = 3, + EIBT_FIRE = 4, + EIBT_AIR = 5, + EIBT_BONES = 6, + EIBT_WOOD = 7, + EIBT_METAL = 8, + EIBT_ROBOT = 9, + EIBT_ICE = 10, +}; +DECL_DLL inline void ClearToDefault(EntityInfoBodyType &e) { e = (EntityInfoBodyType)0; } ; +extern DECL_DLL CEntityPropertyEnumType MessageSound_enum; +enum MessageSound { + MSS_NONE = 0, + MSS_INFO = 1, +}; +DECL_DLL inline void ClearToDefault(MessageSound &e) { e = (MessageSound)0; } ; +extern DECL_DLL CEntityPropertyEnumType ParticleTexture_enum; +enum ParticleTexture { + PT_STAR01 = 1, + PT_STAR02 = 2, + PT_STAR03 = 3, + PT_STAR04 = 4, + PT_STAR05 = 5, + PT_STAR06 = 6, + PT_STAR07 = 7, + PT_STAR08 = 8, + PT_BOUBBLE01 = 9, + PT_BOUBBLE02 = 10, + PT_WATER01 = 11, + PT_WATER02 = 12, + PT_SANDFLOW = 13, + PT_WATERFLOW = 14, + PT_LAVAFLOW = 15, +}; +DECL_DLL inline void ClearToDefault(ParticleTexture &e) { e = (ParticleTexture)0; } ; +extern DECL_DLL CEntityPropertyEnumType SoundType_enum; +enum SoundType { + SNDT_NONE = 0, + SNDT_SHOUT = 1, + SNDT_YELL = 2, + SNDT_EXPLOSION = 3, + SNDT_PLAYER = 4, +}; +DECL_DLL inline void ClearToDefault(SoundType &e) { e = (SoundType)0; } ; +extern DECL_DLL CEntityPropertyEnumType BulletHitType_enum; +enum BulletHitType { + BHT_NONE = 0, + BHT_FLESH = 1, + BHT_BRUSH_STONE = 2, + BHT_BRUSH_SAND = 3, + BHT_BRUSH_WATER = 4, + BHT_BRUSH_UNDER_WATER = 5, + BHT_ACID = 6, + BHT_BRUSH_RED_SAND = 7, + BHT_BRUSH_GRASS = 8, + BHT_BRUSH_WOOD = 9, + BHT_BRUSH_SNOW = 10, +}; +DECL_DLL inline void ClearToDefault(BulletHitType &e) { e = (BulletHitType)0; } ; +extern DECL_DLL CEntityPropertyEnumType EffectParticlesType_enum; +enum EffectParticlesType { + EPT_NONE = 0, + EPT_BULLET_STONE = 1, + EPT_BULLET_SAND = 2, + EPT_BULLET_WATER = 3, + EPT_BULLET_UNDER_WATER = 4, + EPT_BULLET_RED_SAND = 5, + EPT_BULLET_GRASS = 6, + EPT_BULLET_WOOD = 7, + EPT_BULLET_SNOW = 8, +}; +DECL_DLL inline void ClearToDefault(EffectParticlesType &e) { e = (EffectParticlesType)0; } ; +extern DECL_DLL CEntityPropertyEnumType SprayParticlesType_enum; +enum SprayParticlesType { + SPT_NONE = 0, + SPT_BLOOD = 1, + SPT_BONES = 2, + SPT_FEATHER = 3, + SPT_STONES = 4, + SPT_WOOD = 5, + SPT_SLIME = 6, + SPT_LAVA_STONES = 7, + SPT_ELECTRICITY_SPARKS = 8, + SPT_BEAST_PROJECTILE_SPRAY = 9, + SPT_SMALL_LAVA_STONES = 10, + SPT_AIRSPOUTS = 11, + SPT_ELECTRICITY_SPARKS_NO_BLOOD = 12, + SPT_PLASMA = 13, + SPT_GOO = 14, + SPT_TREE01 = 15, + SPT_COLOREDSTONE = 16, +}; +DECL_DLL inline void ClearToDefault(SprayParticlesType &e) { e = (SprayParticlesType)0; } ; +extern DECL_DLL CEntityPropertyEnumType WeaponBits_enum; +enum WeaponBits { + WB_00 = 0, + WB_01 = 1, + WB_02 = 2, + WB_03 = 3, + WB_04 = 4, + WB_05 = 5, + WB_06 = 6, + WB_07 = 7, + WB_08 = 8, + WB_09 = 9, + WB_10 = 10, + WB_11 = 11, + WB_12 = 12, + WB_13 = 13, + WB_14 = 14, + WB_15 = 15, + WB_16 = 16, + WB_17 = 17, + WB_18 = 18, + WB_19 = 19, + WB_20 = 20, + WB_21 = 21, + WB_22 = 22, + WB_23 = 23, + WB_24 = 24, + WB_25 = 25, + WB_26 = 26, + WB_27 = 27, + WB_28 = 28, + WB_29 = 29, + WB_30 = 30, + WB_31 = 31, +}; +DECL_DLL inline void ClearToDefault(WeaponBits &e) { e = (WeaponBits)0; } ; +extern DECL_DLL CEntityPropertyEnumType ClasificationBits_enum; +enum ClasificationBits { + CB_00 = 16, + CB_01 = 17, + CB_02 = 18, + CB_03 = 19, + CB_04 = 20, + CB_05 = 21, + CB_06 = 22, + CB_07 = 23, + CB_08 = 24, + CB_09 = 25, + CB_10 = 26, + CB_11 = 27, + CB_12 = 28, + CB_13 = 29, + CB_14 = 30, + CB_15 = 31, +}; +DECL_DLL inline void ClearToDefault(ClasificationBits &e) { e = (ClasificationBits)0; } ; +extern DECL_DLL CEntityPropertyEnumType VisibilityBits_enum; +enum VisibilityBits { + VB_00 = 0, + VB_01 = 1, + VB_02 = 2, + VB_03 = 3, + VB_04 = 4, + VB_05 = 5, + VB_06 = 6, + VB_07 = 7, + VB_08 = 8, + VB_09 = 9, + VB_10 = 10, + VB_11 = 11, + VB_12 = 12, + VB_13 = 13, + VB_14 = 14, + VB_15 = 15, +}; +DECL_DLL inline void ClearToDefault(VisibilityBits &e) { e = (VisibilityBits)0; } ; +#define EVENTCODE_ESound 0x00000011 +class DECL_DLL ESound : public CEntityEvent { +public: +ESound(); +CEntityEvent *MakeCopy(void); +enum SoundType EsndtSound; +CEntityPointer penTarget; +}; +DECL_DLL inline void ClearToDefault(ESound &e) { e = ESound(); } ; +#define EVENTCODE_EScroll 0x00000012 +class DECL_DLL EScroll : public CEntityEvent { +public: +EScroll(); +CEntityEvent *MakeCopy(void); +BOOL bStart; +CEntityPointer penSender; +}; +DECL_DLL inline void ClearToDefault(EScroll &e) { e = EScroll(); } ; +#define EVENTCODE_ETextFX 0x00000013 +class DECL_DLL ETextFX : public CEntityEvent { +public: +ETextFX(); +CEntityEvent *MakeCopy(void); +BOOL bStart; +CEntityPointer penSender; +}; +DECL_DLL inline void ClearToDefault(ETextFX &e) { e = ETextFX(); } ; +#define EVENTCODE_EHudPicFX 0x00000014 +class DECL_DLL EHudPicFX : public CEntityEvent { +public: +EHudPicFX(); +CEntityEvent *MakeCopy(void); +BOOL bStart; +CEntityPointer penSender; +}; +DECL_DLL inline void ClearToDefault(EHudPicFX &e) { e = EHudPicFX(); } ; +#define EVENTCODE_ECredits 0x00000015 +class DECL_DLL ECredits : public CEntityEvent { +public: +ECredits(); +CEntityEvent *MakeCopy(void); +BOOL bStart; +CEntityPointer penSender; +}; +DECL_DLL inline void ClearToDefault(ECredits &e) { e = ECredits(); } ; +#define EVENTCODE_ECenterMessage 0x00000016 +class DECL_DLL ECenterMessage : public CEntityEvent { +public: +ECenterMessage(); +CEntityEvent *MakeCopy(void); +CTString strMessage; +TIME tmLength; +enum MessageSound mssSound; +}; +DECL_DLL inline void ClearToDefault(ECenterMessage &e) { e = ECenterMessage(); } ; +#define EVENTCODE_EComputerMessage 0x00000017 +class DECL_DLL EComputerMessage : public CEntityEvent { +public: +EComputerMessage(); +CEntityEvent *MakeCopy(void); +CTFileName fnmMessage; +}; +DECL_DLL inline void ClearToDefault(EComputerMessage &e) { e = EComputerMessage(); } ; +#define EVENTCODE_EVoiceMessage 0x00000018 +class DECL_DLL EVoiceMessage : public CEntityEvent { +public: +EVoiceMessage(); +CEntityEvent *MakeCopy(void); +CTFileName fnmMessage; +}; +DECL_DLL inline void ClearToDefault(EVoiceMessage &e) { e = EVoiceMessage(); } ; +#define EVENTCODE_EHitBySpaceShipBeam 0x00000019 +class DECL_DLL EHitBySpaceShipBeam : public CEntityEvent { +public: +EHitBySpaceShipBeam(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EHitBySpaceShipBeam &e) { e = EHitBySpaceShipBeam(); } ; +extern "C" DECL_DLL CDLLEntityClass CGlobal_DLLClass; +class CGlobal : public CEntity { +public: + DECL_DLL virtual void SetDefaultProperties(void); +#define STATE_CGlobal_Main 1 + BOOL +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Global.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Global_INCLUDED diff --git a/Sources/EntitiesMP/Global_tables.h b/Sources/EntitiesMP/Global_tables.h new file mode 100644 index 0000000..39b5c72 --- /dev/null +++ b/Sources/EntitiesMP/Global_tables.h @@ -0,0 +1,220 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(BoolEType) + EP_ENUMVALUE(BET_TRUE, "True"), + EP_ENUMVALUE(BET_FALSE, "False"), + EP_ENUMVALUE(BET_IGNORE, "Ignore"), +EP_ENUMEND(BoolEType); + +EP_ENUMBEG(EventEType) + EP_ENUMVALUE(EET_START, "Start event"), + EP_ENUMVALUE(EET_STOP, "Stop event"), + EP_ENUMVALUE(EET_TRIGGER, "Trigger event"), + EP_ENUMVALUE(EET_IGNORE, "Don't send event"), + EP_ENUMVALUE(EET_ACTIVATE, "Activate event"), + EP_ENUMVALUE(EET_DEACTIVATE, "Deactivate event"), + EP_ENUMVALUE(EET_ENVIRONMENTSTART, "Start environment event"), + EP_ENUMVALUE(EET_ENVIRONMENTSTOP, "Stop environment event"), + EP_ENUMVALUE(EET_STARTATTACK, "OBSOLETE! - Start attack event"), + EP_ENUMVALUE(EET_STOPATTACK, "OBSOLETE! - Stop attack event"), + EP_ENUMVALUE(EET_STOPBLINDNESS, "Stop blindness event"), + EP_ENUMVALUE(EET_STOPDEAFNESS, "Stop deafness event"), + EP_ENUMVALUE(EET_TELEPORTMOVINGBRUSH, "Teleport moving brush"), +EP_ENUMEND(EventEType); + +EP_ENUMBEG(EntityInfoBodyType) + EP_ENUMVALUE(EIBT_FLESH, "Flesh"), + EP_ENUMVALUE(EIBT_WATER, "Water"), + EP_ENUMVALUE(EIBT_ROCK, "Rock "), + EP_ENUMVALUE(EIBT_FIRE, "Fire "), + EP_ENUMVALUE(EIBT_AIR, "Air "), + EP_ENUMVALUE(EIBT_BONES, "Bones"), + EP_ENUMVALUE(EIBT_WOOD, "Wood "), + EP_ENUMVALUE(EIBT_METAL, "Metal"), + EP_ENUMVALUE(EIBT_ROBOT, "Robot"), + EP_ENUMVALUE(EIBT_ICE, "Ice"), +EP_ENUMEND(EntityInfoBodyType); + +EP_ENUMBEG(MessageSound) + EP_ENUMVALUE(MSS_NONE, "None"), + EP_ENUMVALUE(MSS_INFO, "Info"), +EP_ENUMEND(MessageSound); + +EP_ENUMBEG(ParticleTexture) + EP_ENUMVALUE(PT_STAR01, "Star01"), + EP_ENUMVALUE(PT_STAR02, "Star02"), + EP_ENUMVALUE(PT_STAR03, "Star03"), + EP_ENUMVALUE(PT_STAR04, "Star04"), + EP_ENUMVALUE(PT_STAR05, "Star05"), + EP_ENUMVALUE(PT_STAR06, "Star06"), + EP_ENUMVALUE(PT_STAR07, "Star07"), + EP_ENUMVALUE(PT_STAR08, "Star08"), + EP_ENUMVALUE(PT_BOUBBLE01, "Boubble01"), + EP_ENUMVALUE(PT_BOUBBLE02, "Boubble02"), + EP_ENUMVALUE(PT_WATER01, "Water01"), + EP_ENUMVALUE(PT_WATER02, "Water02"), + EP_ENUMVALUE(PT_SANDFLOW, "Sand flow"), + EP_ENUMVALUE(PT_WATERFLOW, "Water flow"), + EP_ENUMVALUE(PT_LAVAFLOW, "Lava flow"), +EP_ENUMEND(ParticleTexture); + +EP_ENUMBEG(SoundType) + EP_ENUMVALUE(SNDT_NONE, ""), + EP_ENUMVALUE(SNDT_SHOUT, ""), + EP_ENUMVALUE(SNDT_YELL, ""), + EP_ENUMVALUE(SNDT_EXPLOSION, ""), + EP_ENUMVALUE(SNDT_PLAYER, ""), +EP_ENUMEND(SoundType); + +EP_ENUMBEG(BulletHitType) + EP_ENUMVALUE(BHT_NONE, ""), + EP_ENUMVALUE(BHT_FLESH, ""), + EP_ENUMVALUE(BHT_BRUSH_STONE, ""), + EP_ENUMVALUE(BHT_BRUSH_SAND, ""), + EP_ENUMVALUE(BHT_BRUSH_WATER, ""), + EP_ENUMVALUE(BHT_BRUSH_UNDER_WATER, ""), + EP_ENUMVALUE(BHT_ACID, ""), + EP_ENUMVALUE(BHT_BRUSH_RED_SAND, ""), + EP_ENUMVALUE(BHT_BRUSH_GRASS, ""), + EP_ENUMVALUE(BHT_BRUSH_WOOD, ""), + EP_ENUMVALUE(BHT_BRUSH_SNOW, ""), +EP_ENUMEND(BulletHitType); + +EP_ENUMBEG(EffectParticlesType) + EP_ENUMVALUE(EPT_NONE, ""), + EP_ENUMVALUE(EPT_BULLET_STONE, ""), + EP_ENUMVALUE(EPT_BULLET_SAND, ""), + EP_ENUMVALUE(EPT_BULLET_WATER, ""), + EP_ENUMVALUE(EPT_BULLET_UNDER_WATER, ""), + EP_ENUMVALUE(EPT_BULLET_RED_SAND, ""), + EP_ENUMVALUE(EPT_BULLET_GRASS, ""), + EP_ENUMVALUE(EPT_BULLET_WOOD, ""), + EP_ENUMVALUE(EPT_BULLET_SNOW, ""), +EP_ENUMEND(EffectParticlesType); + +EP_ENUMBEG(SprayParticlesType) + EP_ENUMVALUE(SPT_NONE, "None"), + EP_ENUMVALUE(SPT_BLOOD, "Blood"), + EP_ENUMVALUE(SPT_BONES, "Bones"), + EP_ENUMVALUE(SPT_FEATHER, "Feather"), + EP_ENUMVALUE(SPT_STONES, "Stones"), + EP_ENUMVALUE(SPT_WOOD, "Wood"), + EP_ENUMVALUE(SPT_SLIME, "Slime"), + EP_ENUMVALUE(SPT_LAVA_STONES, "Lava Stones"), + EP_ENUMVALUE(SPT_ELECTRICITY_SPARKS, "Electricity sparks"), + EP_ENUMVALUE(SPT_BEAST_PROJECTILE_SPRAY, "Beast projectile spray"), + EP_ENUMVALUE(SPT_SMALL_LAVA_STONES, "Small Lava Stones"), + EP_ENUMVALUE(SPT_AIRSPOUTS, "Air"), + EP_ENUMVALUE(SPT_ELECTRICITY_SPARKS_NO_BLOOD, "Electricity w/o blood"), + EP_ENUMVALUE(SPT_PLASMA, "Plasma"), + EP_ENUMVALUE(SPT_GOO, "Goo"), + EP_ENUMVALUE(SPT_TREE01, "Tree 01"), + EP_ENUMVALUE(SPT_COLOREDSTONE, "Colored stone"), +EP_ENUMEND(SprayParticlesType); + +EP_ENUMBEG(WeaponBits) + EP_ENUMVALUE(WB_00, "Knife"), + EP_ENUMVALUE(WB_01, "Colt"), + EP_ENUMVALUE(WB_02, "Double colt"), + EP_ENUMVALUE(WB_03, "Single shotgun"), + EP_ENUMVALUE(WB_04, "Double shotgun"), + EP_ENUMVALUE(WB_05, "Tommygun"), + EP_ENUMVALUE(WB_06, "Minigun"), + EP_ENUMVALUE(WB_07, "Rocket launcher"), + EP_ENUMVALUE(WB_08, "Grenade launcher"), + EP_ENUMVALUE(WB_09, "Chainsaw"), + EP_ENUMVALUE(WB_10, "Flamer"), + EP_ENUMVALUE(WB_11, "Laser"), + EP_ENUMVALUE(WB_12, "Sniper"), + EP_ENUMVALUE(WB_13, "Ironcannon"), + EP_ENUMVALUE(WB_14, ""), + EP_ENUMVALUE(WB_15, ""), + EP_ENUMVALUE(WB_16, ""), + EP_ENUMVALUE(WB_17, ""), + EP_ENUMVALUE(WB_18, ""), + EP_ENUMVALUE(WB_19, ""), + EP_ENUMVALUE(WB_20, ""), + EP_ENUMVALUE(WB_21, ""), + EP_ENUMVALUE(WB_22, ""), + EP_ENUMVALUE(WB_23, ""), + EP_ENUMVALUE(WB_24, ""), + EP_ENUMVALUE(WB_25, ""), + EP_ENUMVALUE(WB_26, ""), + EP_ENUMVALUE(WB_27, ""), + EP_ENUMVALUE(WB_28, ""), + EP_ENUMVALUE(WB_29, ""), + EP_ENUMVALUE(WB_30, ""), + EP_ENUMVALUE(WB_31, ""), +EP_ENUMEND(WeaponBits); + +EP_ENUMBEG(ClasificationBits) + EP_ENUMVALUE(CB_00, "Bit 16"), + EP_ENUMVALUE(CB_01, "Bit 17"), + EP_ENUMVALUE(CB_02, "Bit 18"), + EP_ENUMVALUE(CB_03, "Bit 19"), + EP_ENUMVALUE(CB_04, "Bit 20"), + EP_ENUMVALUE(CB_05, "Bit 21"), + EP_ENUMVALUE(CB_06, "Bit 22"), + EP_ENUMVALUE(CB_07, "Bit 23"), + EP_ENUMVALUE(CB_08, "Bit 24"), + EP_ENUMVALUE(CB_09, "Bit 25"), + EP_ENUMVALUE(CB_10, "Bit 26"), + EP_ENUMVALUE(CB_11, "Bit 27"), + EP_ENUMVALUE(CB_12, "Bit 28"), + EP_ENUMVALUE(CB_13, "Bit 29"), + EP_ENUMVALUE(CB_14, "Bit 30"), + EP_ENUMVALUE(CB_15, "Bit 31"), +EP_ENUMEND(ClasificationBits); + +EP_ENUMBEG(VisibilityBits) + EP_ENUMVALUE(VB_00, "Bit 00"), + EP_ENUMVALUE(VB_01, "Bit 01"), + EP_ENUMVALUE(VB_02, "Bit 02"), + EP_ENUMVALUE(VB_03, "Bit 03"), + EP_ENUMVALUE(VB_04, "Bit 04"), + EP_ENUMVALUE(VB_05, "Bit 05"), + EP_ENUMVALUE(VB_06, "Bit 06"), + EP_ENUMVALUE(VB_07, "Bit 07"), + EP_ENUMVALUE(VB_08, "Bit 08"), + EP_ENUMVALUE(VB_09, "Bit 09"), + EP_ENUMVALUE(VB_10, "Bit 10"), + EP_ENUMVALUE(VB_11, "Bit 11"), + EP_ENUMVALUE(VB_12, "Bit 12"), + EP_ENUMVALUE(VB_13, "Bit 13"), + EP_ENUMVALUE(VB_14, "Bit 14"), + EP_ENUMVALUE(VB_15, "Bit 15"), +EP_ENUMEND(VisibilityBits); + +#define ENTITYCLASS CGlobal + +CEntityProperty CGlobal_properties[] = { + CEntityProperty() +}; +#define CGlobal_propertiesct 0 + + +CEntityComponent CGlobal_components[] = { + CEntityComponent() +}; +#define CGlobal_componentsct 0 + + +CEventHandlerEntry CGlobal_handlers[] = { + {1, -1, CEntity::pEventHandler(&CGlobal:: +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Global.es" +Main),DEBUGSTRING("CGlobal::Main")}, +}; +#define CGlobal_handlersct ARRAYCOUNT(CGlobal_handlers) + +CEntity *CGlobal_New(void) { return new CGlobal; }; +void CGlobal_OnInitClass(void) {}; +void CGlobal_OnEndClass(void) {}; +void CGlobal_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CGlobal_OnWorldEnd(CWorld *pwo) {}; +void CGlobal_OnWorldInit(CWorld *pwo) {}; +void CGlobal_OnWorldTick(CWorld *pwo) {}; +void CGlobal_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CGlobal, CEntity, "", "", 0x00000000); +DECLARE_CTFILENAME(_fnmCGlobal_tbn, ""); diff --git a/Sources/EntitiesMP/GradientMarker.cpp b/Sources/EntitiesMP/GradientMarker.cpp new file mode 100644 index 0000000..1988a22 --- /dev/null +++ b/Sources/EntitiesMP/GradientMarker.cpp @@ -0,0 +1,126 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" + +#include "StdH.h" + +#include +#include +void CGradientMarker::SetDefaultProperties(void) { + m_fHeight = -10.0f; + m_bDarkLight = TRUE ; + m_colColor0 = (C_GRAY | CT_OPAQUE ); + m_colColor1 = (C_WHITE | CT_OPAQUE ); + CMarker::SetDefaultProperties(); +} + +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +const CTString & CGradientMarker::GetGradientName(void) +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +{ +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +return m_strName ; +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +} + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +BOOL CGradientMarker::GetGradient(INDEX iGradient,class CGradientParameters & gpGradient) +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +{ +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +const FLOATmatrix3D & m = GetRotationMatrix (); +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +gpGradient . gp_vGradientDir (1) = m (1 , 2); +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +gpGradient . gp_vGradientDir (2) = m (2 , 2); +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +gpGradient . gp_vGradientDir (3) = m (3 , 2); +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +FLOAT fPos = gpGradient . gp_vGradientDir % GetPlacement () . pl_PositionVector ; +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +gpGradient . gp_bDark = m_bDarkLight ; +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +if(m_fHeight >= 0 && m_fHeight < + 0.001f){m_fHeight = + 0.001f;} +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +if(m_fHeight <= 0 && m_fHeight > - 0.001f){m_fHeight = - 0.001f;} +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +gpGradient . gp_fH0 = fPos ; +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +gpGradient . gp_fH1 = fPos + m_fHeight ; +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +gpGradient . gp_col0 = m_colColor0 ; +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +gpGradient . gp_col1 = m_colColor1 ; +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +return TRUE ; +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +} + +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +void CGradientMarker::UncacheShadowsForGradient(void) +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +{ +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +FOREACHINDYNAMICCONTAINER (GetWorld () -> wo_cenEntities , CEntity , iten ){ +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +if(IsOfClass (& * iten , "WorldBase")){ +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +((CWorldBase *) & * iten ) -> UncacheShadowsForGradient (this ); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +} +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +} +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +} + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +void CGradientMarker::SetPlacement_internal(const CPlacement3D & plNew,const FLOATmatrix3D & mRotation,BOOL bNear) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +{ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +CEntity :: SetPlacement_internal (plNew , mRotation , bNear ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +UncacheShadowsForGradient (); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +} + +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +void CGradientMarker::OnEnd(void) +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +{ +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +UncacheShadowsForGradient (); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +CEntity :: OnEnd (); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +} +BOOL CGradientMarker:: +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGradientMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGradientMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +InitAsEditorModel (); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +SetModel (MODEL_MARKER ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +if(m_strName == "Marker"){ +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +m_strName = "Gradient marker"; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +} +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +UncacheShadowsForGradient (); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/GradientMarker.es b/Sources/EntitiesMP/GradientMarker.es new file mode 100644 index 0000000..8a86bac --- /dev/null +++ b/Sources/EntitiesMP/GradientMarker.es @@ -0,0 +1,95 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +230 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; +uses "EntitiesMP/WorldBase"; + +class CGradientMarker: CMarker { +name "Gradient Marker"; +thumbnail "Thumbnails\\GradientMarker.tbn"; +features "IsImportant"; + +properties: + 1 FLOAT m_fHeight "Height" 'H' = -10.0f, + 2 BOOL m_bDarkLight "Dark light" 'D' = TRUE, + 3 COLOR m_colColor0 "Color 0" 'C' = (C_GRAY|CT_OPAQUE), + 4 COLOR m_colColor1 "Color 1" 'A' = (C_WHITE|CT_OPAQUE), + +components: + 1 model MODEL_MARKER "Models\\Editor\\GradientMarker.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\GradientMarker.tex" + +functions: + + /* Get gradient type name, return empty string if not used. */ + const CTString &GetGradientName(void) + { + return m_strName; + } + /* Get gradient. */ + BOOL GetGradient(INDEX iGradient, class CGradientParameters &gpGradient) + { + const FLOATmatrix3D &m = GetRotationMatrix(); + gpGradient.gp_vGradientDir(1) = m(1,2); + gpGradient.gp_vGradientDir(2) = m(2,2); + gpGradient.gp_vGradientDir(3) = m(3,2); + FLOAT fPos = gpGradient.gp_vGradientDir%GetPlacement().pl_PositionVector; + gpGradient.gp_bDark = m_bDarkLight; + if( m_fHeight>=0 && m_fHeight<+0.001f) { m_fHeight = +0.001f; } + if( m_fHeight<=0 && m_fHeight>-0.001f) { m_fHeight = -0.001f; } + gpGradient.gp_fH0 = fPos; + gpGradient.gp_fH1 = fPos+m_fHeight; + gpGradient.gp_col0 = m_colColor0; + gpGradient.gp_col1 = m_colColor1; + return TRUE; + } + + void UncacheShadowsForGradient(void) + { + // for all entities in world + FOREACHINDYNAMICCONTAINER(GetWorld()->wo_cenEntities, CEntity, iten) { + // if it is world base entity + if( IsOfClass(&*iten, "WorldBase")) { + // uncache shadows for gradient + ((CWorldBase *)&*iten)->UncacheShadowsForGradient(this); + } + } + } + + void SetPlacement_internal(const CPlacement3D &plNew, const FLOATmatrix3D &mRotation, BOOL bNear) + { + CEntity::SetPlacement_internal(plNew, mRotation, bNear); + UncacheShadowsForGradient(); + } + + void OnEnd(void) + { + UncacheShadowsForGradient(); + CEntity::OnEnd(); + } + +procedures: + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + // set name + if( m_strName=="Marker") { + m_strName = "Gradient marker"; + } + + UncacheShadowsForGradient(); + return; + } +}; diff --git a/Sources/EntitiesMP/GradientMarker.h b/Sources/EntitiesMP/GradientMarker.h new file mode 100644 index 0000000..4d3cc07 --- /dev/null +++ b/Sources/EntitiesMP/GradientMarker.h @@ -0,0 +1,38 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_GradientMarker_INCLUDED +#define _EntitiesMP_GradientMarker_INCLUDED 1 +#include +#include +extern "C" DECL_DLL CDLLEntityClass CGradientMarker_DLLClass; +class CGradientMarker : public CMarker { +public: +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fHeight; + BOOL m_bDarkLight; + COLOR m_colColor0; + COLOR m_colColor1; + +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +const CTString & GetGradientName(void); + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +BOOL GetGradient(INDEX iGradient,class CGradientParameters & gpGradient); + +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +void UncacheShadowsForGradient(void); + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +void SetPlacement_internal(const CPlacement3D & plNew,const FLOATmatrix3D & mRotation,BOOL bNear); + +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +void OnEnd(void); +#define STATE_CGradientMarker_Main 1 + BOOL +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_GradientMarker_INCLUDED diff --git a/Sources/EntitiesMP/GradientMarker_tables.h b/Sources/EntitiesMP/GradientMarker_tables.h new file mode 100644 index 0000000..3f52c51 --- /dev/null +++ b/Sources/EntitiesMP/GradientMarker_tables.h @@ -0,0 +1,39 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CGradientMarker + +CEntityProperty CGradientMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e6<<8)+1, offsetof(CGradientMarker, m_fHeight), "Height", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e6<<8)+2, offsetof(CGradientMarker, m_bDarkLight), "Dark light", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000e6<<8)+3, offsetof(CGradientMarker, m_colColor0), "Color 0", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000e6<<8)+4, offsetof(CGradientMarker, m_colColor1), "Color 1", 'A', 0x7F0000FFUL, 0), +}; +#define CGradientMarker_propertiesct ARRAYCOUNT(CGradientMarker_properties) + +CEntityComponent CGradientMarker_components[] = { +#define MODEL_MARKER ((0x000000e6<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\GradientMarker.mdl"), +#define TEXTURE_MARKER ((0x000000e6<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\GradientMarker.tex"), +}; +#define CGradientMarker_componentsct ARRAYCOUNT(CGradientMarker_components) + +CEventHandlerEntry CGradientMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CGradientMarker:: +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/GradientMarker.es" +Main),DEBUGSTRING("CGradientMarker::Main")}, +}; +#define CGradientMarker_handlersct ARRAYCOUNT(CGradientMarker_handlers) + +CEntity *CGradientMarker_New(void) { return new CGradientMarker; }; +void CGradientMarker_OnInitClass(void) {}; +void CGradientMarker_OnEndClass(void) {}; +void CGradientMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CGradientMarker_OnWorldEnd(CWorld *pwo) {}; +void CGradientMarker_OnWorldInit(CWorld *pwo) {}; +void CGradientMarker_OnWorldTick(CWorld *pwo) {}; +void CGradientMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CGradientMarker, CMarker, "Gradient Marker", "Thumbnails\\GradientMarker.tbn", 0x000000e6); +DECLARE_CTFILENAME(_fnmCGradientMarker_tbn, "Thumbnails\\GradientMarker.tbn"); diff --git a/Sources/EntitiesMP/GravityMarker.cpp b/Sources/EntitiesMP/GravityMarker.cpp new file mode 100644 index 0000000..d92f8c2 --- /dev/null +++ b/Sources/EntitiesMP/GravityMarker.cpp @@ -0,0 +1,229 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" + +#include "StdH.h" + +#include +#include +void CGravityMarker::SetDefaultProperties(void) { + m_gtType = LT_PARALLEL ; + m_fStrength = 1; + m_rFallOff = 50; + m_rHotSpot = 50; + m_rTorusR = 100; + m_fAcc = 0; + m_fSign = 1; + m_fStep = 0; + m_aForceDir = ANGLE3D(0 , 0 , 0); + m_fForceA = 0.0f; + m_fForceV = 0.0f; + m_vForceDir = FLOAT3D(1 , 0 , 0); + CMarker::SetDefaultProperties(); +} + +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +inline FLOAT CGravityMarker::StrengthAtDistance(FLOAT fDistance) +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +{ +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +FLOAT fStrength = (m_rFallOff - fDistance ) * m_fStep ; +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +return Clamp (fStrength , 0.0f , m_fAcc ); +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +} + +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +const CTString & CGravityMarker::GetForceName(INDEX i) +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +{ +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +return m_strName ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +} + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +void CGravityMarker::GetForce(INDEX i,const FLOAT3D & vPoint, +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +CForceStrength & fsGravity,CForceStrength & fsField) +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +{ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +const FLOATmatrix3D & m = GetRotationMatrix (); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +switch(m_gtType ){ +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +case LT_PARALLEL : { +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_vDirection (1) = - m (1 , 2) * m_fSign ; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_vDirection (2) = - m (2 , 2) * m_fSign ; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_vDirection (3) = - m (3 , 2) * m_fSign ; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +FLOAT fDistance = (vPoint - GetPlacement () . pl_PositionVector ) % fsGravity . fs_vDirection ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_fAcceleration = StrengthAtDistance (fDistance ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_fVelocity = 70; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +}break ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +case LT_CENTRAL : { +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_vDirection = (GetPlacement () . pl_PositionVector - vPoint ) * m_fSign ; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +FLOAT fDistance = fsGravity . fs_vDirection . Length (); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +if(fDistance > 0.01f){ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_vDirection /= fDistance ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +} +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_fAcceleration = StrengthAtDistance (fDistance ); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_fVelocity = 70; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +}break ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +case LT_CYLINDRICAL : { +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +FLOAT3D vDelta = GetPlacement () . pl_PositionVector - vPoint ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +FLOAT3D vAxis ; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +vAxis (1) = m (1 , 2); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +vAxis (2) = m (2 , 2); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +vAxis (3) = m (3 , 2); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +GetNormalComponent (vDelta , vAxis , fsGravity . fs_vDirection ); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_vDirection *= m_fSign ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +FLOAT fDistance = fsGravity . fs_vDirection . Length (); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +if(fDistance > 0.01f){ +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_vDirection /= fDistance ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +} +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_fAcceleration = StrengthAtDistance (fDistance ); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_fVelocity = 70; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +}break ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +case LT_TORUS : { +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +FLOAT3D vDelta = vPoint - GetPlacement () . pl_PositionVector ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +FLOAT3D vAxis ; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +vAxis (1) = m (1 , 2); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +vAxis (2) = m (2 , 2); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +vAxis (3) = m (3 , 2); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +FLOAT3D vR ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +GetNormalComponent (vDelta , vAxis , vR ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +vR . Normalize (); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_vDirection = (vDelta - vR * m_rTorusR ) * m_fSign ; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +FLOAT fDistance = fsGravity . fs_vDirection . Length (); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +if(fDistance > 0.01f){ +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_vDirection /= fDistance ; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +} +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_fAcceleration = StrengthAtDistance (fDistance ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_fVelocity = 70; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +}break ; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +default : +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_fAcceleration = m_fAcc ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_fVelocity = 70; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsGravity . fs_vDirection = FLOAT3D (0 , - 1 , 0); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +} +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsField . fs_fAcceleration = m_fForceA ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsField . fs_fVelocity = m_fForceV ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +fsField . fs_vDirection = m_vForceDir ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +} + +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +BOOL CGravityMarker::HandleEvent(const CEntityEvent & ee) +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +{ +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +if(ee . ee_slEvent == EVENTCODE_ETrigger ) +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +{ +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +EChangeGravity eChangeGravity ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +eChangeGravity . penNewGravity = this ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +m_penTarget -> SendEvent (eChangeGravity ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +return TRUE ; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +} +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +return FALSE ; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +} +BOOL CGravityMarker:: +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGravityMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGravityMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +InitAsEditorModel (); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +SetModel (MODEL_MARKER ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +if(m_strName == "Marker"){ +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +m_strName = "Gravity Marker"; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +} +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +m_fAcc = Abs (30 * m_fStrength ) , +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +m_fSign = SgnNZ (m_fStrength ) , +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +m_fStep = m_fAcc / (m_rFallOff - m_rHotSpot ); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +AnglesToDirectionVector (m_aForceDir , m_vForceDir ); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/GravityMarker.es b/Sources/EntitiesMP/GravityMarker.es new file mode 100644 index 0000000..5880f97 --- /dev/null +++ b/Sources/EntitiesMP/GravityMarker.es @@ -0,0 +1,164 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +212 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; +uses "EntitiesMP/GravityRouter"; + +enum GravityType { + 0 LT_PARALLEL "Parallel", + 1 LT_CENTRAL "Central", + 2 LT_CYLINDRICAL "Cylindirical", + 3 LT_TORUS "Torus", +}; + +class CGravityMarker: CMarker { +name "Gravity Marker"; +thumbnail "Thumbnails\\GravityMarker.tbn"; +features "IsImportant"; + +properties: + 1 enum GravityType m_gtType "Type" 'Y' =LT_PARALLEL, + 2 FLOAT m_fStrength "Strength" 'S' = 1, + 3 RANGE m_rFallOff "FallOff" 'F' = 50, + 4 RANGE m_rHotSpot "HotSpot" 'H' = 50, + 5 RANGE m_rTorusR "Torus Radius" 'R' = 100, + + 10 FLOAT m_fAcc = 0, + 11 FLOAT m_fSign = 1, + 12 FLOAT m_fStep = 0, + + 20 ANGLE3D m_aForceDir "Forcefield Direction" 'F' = ANGLE3D(0,0,0), + 21 FLOAT m_fForceA "Forcefield Acceleration" = 0.0f, + 22 FLOAT m_fForceV "Forcefield Velocity" = 0.0f, + 23 FLOAT3D m_vForceDir = FLOAT3D(1,0,0), + +components: + 1 model MODEL_MARKER "Models\\Editor\\GravityMarker.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\GravityMarker.tex" + +functions: + // find strength at given distance + inline FLOAT StrengthAtDistance(FLOAT fDistance) + { + FLOAT fStrength = (m_rFallOff-fDistance)*m_fStep; + return Clamp(fStrength, 0.0f, m_fAcc); + } + + /* Get force type name, return empty string if not used. */ + const CTString &GetForceName(INDEX i) + { + return m_strName; + } + /* Get force in given point. */ + void GetForce(INDEX i, const FLOAT3D &vPoint, + CForceStrength &fsGravity, CForceStrength &fsField) + { + const FLOATmatrix3D &m = GetRotationMatrix(); + switch (m_gtType) { + case LT_PARALLEL: { + fsGravity.fs_vDirection(1) = -m(1,2) * m_fSign; + fsGravity.fs_vDirection(2) = -m(2,2) * m_fSign; + fsGravity.fs_vDirection(3) = -m(3,2) * m_fSign; + FLOAT fDistance = (vPoint-GetPlacement().pl_PositionVector)%fsGravity.fs_vDirection; + fsGravity.fs_fAcceleration = StrengthAtDistance(fDistance); + fsGravity.fs_fVelocity = 70; + } break; + case LT_CENTRAL: { + fsGravity.fs_vDirection = (GetPlacement().pl_PositionVector-vPoint)*m_fSign; + FLOAT fDistance = fsGravity.fs_vDirection.Length(); + if (fDistance>0.01f) { + fsGravity.fs_vDirection/=fDistance; + } + fsGravity.fs_fAcceleration = StrengthAtDistance(fDistance); + fsGravity.fs_fVelocity = 70; + } break; + case LT_CYLINDRICAL: { + FLOAT3D vDelta = GetPlacement().pl_PositionVector-vPoint; + FLOAT3D vAxis; + vAxis(1) = m(1,2); + vAxis(2) = m(2,2); + vAxis(3) = m(3,2); + GetNormalComponent(vDelta, vAxis, fsGravity.fs_vDirection); + fsGravity.fs_vDirection*=m_fSign; + FLOAT fDistance = fsGravity.fs_vDirection.Length(); + if (fDistance>0.01f) { + fsGravity.fs_vDirection/=fDistance; + } + fsGravity.fs_fAcceleration = StrengthAtDistance(fDistance); + fsGravity.fs_fVelocity = 70; + } break; + case LT_TORUS: { + // get referent point + FLOAT3D vDelta = vPoint-GetPlacement().pl_PositionVector; + FLOAT3D vAxis; + vAxis(1) = m(1,2); + vAxis(2) = m(2,2); + vAxis(3) = m(3,2); + FLOAT3D vR; + GetNormalComponent(vDelta, vAxis, vR); + vR.Normalize(); + fsGravity.fs_vDirection = (vDelta-vR*m_rTorusR)*m_fSign; + FLOAT fDistance = fsGravity.fs_vDirection.Length(); + if (fDistance>0.01f) { + fsGravity.fs_vDirection/=fDistance; + } + fsGravity.fs_fAcceleration = StrengthAtDistance(fDistance); + fsGravity.fs_fVelocity = 70; + + } break; + default: + fsGravity.fs_fAcceleration = m_fAcc; + fsGravity.fs_fVelocity = 70; + fsGravity.fs_vDirection = FLOAT3D(0,-1,0); + } + + // calculate forcefield influence + fsField.fs_fAcceleration = m_fForceA; + fsField.fs_fVelocity = m_fForceV; + fsField.fs_vDirection = m_vForceDir; + } + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + if( ee.ee_slEvent==EVENTCODE_ETrigger) + { + EChangeGravity eChangeGravity; + eChangeGravity.penNewGravity = this; + m_penTarget->SendEvent( eChangeGravity); + return TRUE; + } + return FALSE; + } + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + // set name + if (m_strName=="Marker") { + m_strName = "Gravity Marker"; + } + + // precalc fast gravity parameters + m_fAcc = Abs(30*m_fStrength), + m_fSign = SgnNZ(m_fStrength), + m_fStep = m_fAcc/(m_rFallOff-m_rHotSpot); + + AnglesToDirectionVector(m_aForceDir, m_vForceDir); + + return; + } +}; + diff --git a/Sources/EntitiesMP/GravityMarker.h b/Sources/EntitiesMP/GravityMarker.h new file mode 100644 index 0000000..097fc78 --- /dev/null +++ b/Sources/EntitiesMP/GravityMarker.h @@ -0,0 +1,53 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_GravityMarker_INCLUDED +#define _EntitiesMP_GravityMarker_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType GravityType_enum; +enum GravityType { + LT_PARALLEL = 0, + LT_CENTRAL = 1, + LT_CYLINDRICAL = 2, + LT_TORUS = 3, +}; +DECL_DLL inline void ClearToDefault(GravityType &e) { e = (GravityType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CGravityMarker_DLLClass; +class CGravityMarker : public CMarker { +public: +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + enum GravityType m_gtType; + FLOAT m_fStrength; + RANGE m_rFallOff; + RANGE m_rHotSpot; + RANGE m_rTorusR; + FLOAT m_fAcc; + FLOAT m_fSign; + FLOAT m_fStep; + ANGLE3D m_aForceDir; + FLOAT m_fForceA; + FLOAT m_fForceV; + FLOAT3D m_vForceDir; + +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +inline FLOAT StrengthAtDistance(FLOAT fDistance); + +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +const CTString & GetForceName(INDEX i); + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +void GetForce(INDEX i,const FLOAT3D & vPoint, +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +CForceStrength & fsGravity,CForceStrength & fsField); + +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CGravityMarker_Main 1 + BOOL +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_GravityMarker_INCLUDED diff --git a/Sources/EntitiesMP/GravityMarker_tables.h b/Sources/EntitiesMP/GravityMarker_tables.h new file mode 100644 index 0000000..263e00e --- /dev/null +++ b/Sources/EntitiesMP/GravityMarker_tables.h @@ -0,0 +1,54 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(GravityType) + EP_ENUMVALUE(LT_PARALLEL, "Parallel"), + EP_ENUMVALUE(LT_CENTRAL, "Central"), + EP_ENUMVALUE(LT_CYLINDRICAL, "Cylindirical"), + EP_ENUMVALUE(LT_TORUS, "Torus"), +EP_ENUMEND(GravityType); + +#define ENTITYCLASS CGravityMarker + +CEntityProperty CGravityMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &GravityType_enum, (0x000000d4<<8)+1, offsetof(CGravityMarker, m_gtType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d4<<8)+2, offsetof(CGravityMarker, m_fStrength), "Strength", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x000000d4<<8)+3, offsetof(CGravityMarker, m_rFallOff), "FallOff", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x000000d4<<8)+4, offsetof(CGravityMarker, m_rHotSpot), "HotSpot", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x000000d4<<8)+5, offsetof(CGravityMarker, m_rTorusR), "Torus Radius", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d4<<8)+10, offsetof(CGravityMarker, m_fAcc), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d4<<8)+11, offsetof(CGravityMarker, m_fSign), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d4<<8)+12, offsetof(CGravityMarker, m_fStep), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x000000d4<<8)+20, offsetof(CGravityMarker, m_aForceDir), "Forcefield Direction", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d4<<8)+21, offsetof(CGravityMarker, m_fForceA), "Forcefield Acceleration", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d4<<8)+22, offsetof(CGravityMarker, m_fForceV), "Forcefield Velocity", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000000d4<<8)+23, offsetof(CGravityMarker, m_vForceDir), "", 0, 0, 0), +}; +#define CGravityMarker_propertiesct ARRAYCOUNT(CGravityMarker_properties) + +CEntityComponent CGravityMarker_components[] = { +#define MODEL_MARKER ((0x000000d4<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\GravityMarker.mdl"), +#define TEXTURE_MARKER ((0x000000d4<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\GravityMarker.tex"), +}; +#define CGravityMarker_componentsct ARRAYCOUNT(CGravityMarker_components) + +CEventHandlerEntry CGravityMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CGravityMarker:: +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/GravityMarker.es" +Main),DEBUGSTRING("CGravityMarker::Main")}, +}; +#define CGravityMarker_handlersct ARRAYCOUNT(CGravityMarker_handlers) + +CEntity *CGravityMarker_New(void) { return new CGravityMarker; }; +void CGravityMarker_OnInitClass(void) {}; +void CGravityMarker_OnEndClass(void) {}; +void CGravityMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CGravityMarker_OnWorldEnd(CWorld *pwo) {}; +void CGravityMarker_OnWorldInit(CWorld *pwo) {}; +void CGravityMarker_OnWorldTick(CWorld *pwo) {}; +void CGravityMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CGravityMarker, CMarker, "Gravity Marker", "Thumbnails\\GravityMarker.tbn", 0x000000d4); +DECLARE_CTFILENAME(_fnmCGravityMarker_tbn, "Thumbnails\\GravityMarker.tbn"); diff --git a/Sources/EntitiesMP/GravityRouter.cpp b/Sources/EntitiesMP/GravityRouter.cpp new file mode 100644 index 0000000..3e3707e --- /dev/null +++ b/Sources/EntitiesMP/GravityRouter.cpp @@ -0,0 +1,107 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *EChangeGravity::MakeCopy(void) { CEntityEvent *peeCopy = new EChangeGravity(*this); return peeCopy;} +EChangeGravity::EChangeGravity() : CEntityEvent(EVENTCODE_EChangeGravity) {; + ClearToDefault(penNewGravity); +}; +void CGravityRouter::SetDefaultProperties(void) { + CMarker::SetDefaultProperties(); +} + +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +const CTString & CGravityRouter::GetForceName(INDEX i) +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +{ +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +return m_strName ; +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +} + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +void CGravityRouter::GetForce(INDEX i,const FLOAT3D & vPoint, +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +CForceStrength & fsGravity,CForceStrength & fsField) +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +{ +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +if((m_penTarget != NULL ) && (IsOfClass (m_penTarget , "Gravity Marker"))) +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +{ +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +m_penTarget -> GetForce (i , vPoint , fsGravity , fsField ); +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +} +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +} + +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +CEntity * CGravityRouter::GetForceController(INDEX iForce) +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +{ +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +return this ; +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +} + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +BOOL CGravityRouter::HandleEvent(const CEntityEvent & ee) +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +{ +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +if(((EChangeGravity &) ee ) . ee_slEvent == EVENTCODE_EChangeGravity ) +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +{ +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +m_penTarget = ((EChangeGravity &) ee ) . penNewGravity ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +NotifyGravityChanged (); +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +return TRUE ; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +} +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +return FALSE ; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +} +BOOL CGravityRouter:: +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGravityRouter_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGravityRouter::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +InitAsEditorModel (); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +SetModel (MODEL_MARKER ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +if(m_strName == "Marker"){ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +m_strName = "Gravity Router"; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +} +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +if(m_penTarget != NULL && ! IsOfClass (m_penTarget , "Gravity Marker")){ +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +WarningMessage ("Entity '%s' is not of Gravity Marker class!" , m_penTarget ); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +m_penTarget = NULL ; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +} +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +Return(STATE_CURRENT,EVoid()); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/GravityRouter.es b/Sources/EntitiesMP/GravityRouter.es new file mode 100644 index 0000000..5794885 --- /dev/null +++ b/Sources/EntitiesMP/GravityRouter.es @@ -0,0 +1,85 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +227 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; + +event EChangeGravity { + CEntityPointer penNewGravity, +}; + +class CGravityRouter: CMarker { +name "Gravity Router"; +thumbnail "Thumbnails\\GravityRouter.tbn"; +features "IsImportant"; + +properties: + +components: + 1 model MODEL_MARKER "Models\\Editor\\GravityRouter.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\GravityRouter.tex" + +functions: + + /* Get force type name, return empty string if not used. */ + const CTString &GetForceName(INDEX i) + { + return m_strName; + } + + /* Get force in given point. */ + void GetForce(INDEX i, const FLOAT3D &vPoint, + CForceStrength &fsGravity, CForceStrength &fsField) + { + if( (m_penTarget != NULL) && (IsOfClass( m_penTarget, "Gravity Marker"))) + { + m_penTarget->GetForce(i, vPoint, fsGravity, fsField); + } + } + /* Get entity that controls the force, used for change notification checking. */ + CEntity *GetForceController(INDEX iForce) + { + return this; + } + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + if( ((EChangeGravity &) ee).ee_slEvent==EVENTCODE_EChangeGravity) + { + m_penTarget = ((EChangeGravity &) ee).penNewGravity; + // notify engine that gravity defined by this entity has changed + NotifyGravityChanged(); + return TRUE; + } + return FALSE; + } + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + // set name + if (m_strName=="Marker") { + m_strName = "Gravity Router"; + } + + if( m_penTarget!=NULL && !IsOfClass( m_penTarget, "Gravity Marker")) { + WarningMessage( "Entity '%s' is not of Gravity Marker class!", m_penTarget); + m_penTarget = NULL; + } + + return; + } +}; + diff --git a/Sources/EntitiesMP/GravityRouter.h b/Sources/EntitiesMP/GravityRouter.h new file mode 100644 index 0000000..82af366 --- /dev/null +++ b/Sources/EntitiesMP/GravityRouter.h @@ -0,0 +1,40 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_GravityRouter_INCLUDED +#define _EntitiesMP_GravityRouter_INCLUDED 1 +#include +#define EVENTCODE_EChangeGravity 0x00e30000 +class DECL_DLL EChangeGravity : public CEntityEvent { +public: +EChangeGravity(); +CEntityEvent *MakeCopy(void); +CEntityPointer penNewGravity; +}; +DECL_DLL inline void ClearToDefault(EChangeGravity &e) { e = EChangeGravity(); } ; +extern "C" DECL_DLL CDLLEntityClass CGravityRouter_DLLClass; +class CGravityRouter : public CMarker { +public: +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +const CTString & GetForceName(INDEX i); + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +void GetForce(INDEX i,const FLOAT3D & vPoint, +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +CForceStrength & fsGravity,CForceStrength & fsField); + +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +CEntity * GetForceController(INDEX iForce); + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CGravityRouter_Main 1 + BOOL +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_GravityRouter_INCLUDED diff --git a/Sources/EntitiesMP/GravityRouter_tables.h b/Sources/EntitiesMP/GravityRouter_tables.h new file mode 100644 index 0000000..51872a2 --- /dev/null +++ b/Sources/EntitiesMP/GravityRouter_tables.h @@ -0,0 +1,37 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CGravityRouter + +CEntityProperty CGravityRouter_properties[] = { + CEntityProperty() +}; +#define CGravityRouter_propertiesct 0 + + +CEntityComponent CGravityRouter_components[] = { +#define MODEL_MARKER ((0x000000e3<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\GravityRouter.mdl"), +#define TEXTURE_MARKER ((0x000000e3<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\GravityRouter.tex"), +}; +#define CGravityRouter_componentsct ARRAYCOUNT(CGravityRouter_components) + +CEventHandlerEntry CGravityRouter_handlers[] = { + {1, -1, CEntity::pEventHandler(&CGravityRouter:: +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/GravityRouter.es" +Main),DEBUGSTRING("CGravityRouter::Main")}, +}; +#define CGravityRouter_handlersct ARRAYCOUNT(CGravityRouter_handlers) + +CEntity *CGravityRouter_New(void) { return new CGravityRouter; }; +void CGravityRouter_OnInitClass(void) {}; +void CGravityRouter_OnEndClass(void) {}; +void CGravityRouter_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CGravityRouter_OnWorldEnd(CWorld *pwo) {}; +void CGravityRouter_OnWorldInit(CWorld *pwo) {}; +void CGravityRouter_OnWorldTick(CWorld *pwo) {}; +void CGravityRouter_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CGravityRouter, CMarker, "Gravity Router", "Thumbnails\\GravityRouter.tbn", 0x000000e3); +DECLARE_CTFILENAME(_fnmCGravityRouter_tbn, "Thumbnails\\GravityRouter.tbn"); diff --git a/Sources/EntitiesMP/Grunt.cpp b/Sources/EntitiesMP/Grunt.cpp new file mode 100644 index 0000000..3c7179b --- /dev/null +++ b/Sources/EntitiesMP/Grunt.cpp @@ -0,0 +1,598 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/Grunt/Grunt.h" + +#include +#include +#line 17 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" + +#define STRETCH_SOLDIER 1.2f +#define STRETCH_COMMANDER 1.4f + +// info structure +static EntityInfo eiGruntSoldier = { + EIBT_FLESH, 200.0f, + 0.0f, 1.9f*STRETCH_SOLDIER, 0.0f, // source (eyes) + 0.0f, 1.3f*STRETCH_SOLDIER, 0.0f, // target (body) +}; + +static EntityInfo eiGruntCommander = { + EIBT_FLESH, 250.0f, + 0.0f, 1.9f*STRETCH_COMMANDER, 0.0f, // source (eyes) + 0.0f, 1.3f*STRETCH_COMMANDER, 0.0f, // target (body) +}; + +#define FIREPOS_SOLDIER FLOAT3D(0.07f, 1.36f, -0.78f)*STRETCH_SOLDIER +#define FIREPOS_COMMANDER_UP FLOAT3D(0.09f, 1.45f, -0.62f)*STRETCH_COMMANDER +#define FIREPOS_COMMANDER_DN FLOAT3D(0.10f, 1.30f, -0.60f)*STRETCH_COMMANDER + +void CGrunt::SetDefaultProperties(void) { + m_gtType = GT_SOLDIER ; + m_soFire1.SetOwner(this); +m_soFire1.Stop_internal(); + m_soFire2.SetOwner(this); +m_soFire2.Stop_internal(); + CEnemyBase::SetDefaultProperties(); +} + CTString CGrunt::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +{ +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +CTString str ; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +str . PrintF (TRANS ("A Grunt sent %s into the halls of Valhalla") , strPlayerName ); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return str ; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void * CGrunt::GetEntityInfo(void) { +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +if(m_gtType == GT_SOLDIER ){ +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return & eiGruntSoldier ; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +}else if(m_gtType == GT_COMMANDER ){ +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return & eiGruntSoldier ; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +}else { +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +ASSERT ("Unknown grunt type!"); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return NULL ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + const CTFileName & CGrunt::GetComputerMessageName(void)const { +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +static DECLARE_CTFILENAME (fnmSoldier , "DataMP\\Messages\\Enemies\\GruntSoldier.txt"); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +static DECLARE_CTFILENAME (fnmCommander , "DataMP\\Messages\\Enemies\\GruntCommander.txt"); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +switch(m_gtType ){ +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +default : ASSERT (FALSE ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +case GT_SOLDIER : return fnmSoldier ; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +case GT_COMMANDER : return fnmCommander ; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::Precache(void) { +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +CEnemyBase :: Precache (); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +if(m_gtType == GT_SOLDIER ){ +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PrecacheClass (CLASS_PROJECTILE , PRT_GRUNT_PROJECTILE_SOL ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +if(m_gtType == GT_COMMANDER ){ +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PrecacheClass (CLASS_PROJECTILE , PRT_GRUNT_PROJECTILE_COM ); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PrecacheSound (SOUND_IDLE ); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PrecacheSound (SOUND_SIGHT ); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PrecacheSound (SOUND_WOUND ); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PrecacheSound (SOUND_FIRE ); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PrecacheSound (SOUND_DEATH ); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +{ +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +INDEX CGrunt::AnimForDamage(FLOAT fDamage) { +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +INDEX iAnim ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +iAnim = GRUNT_ANIM_WOUND01 ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StartModelAnim (iAnim , 0); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return iAnim ; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +INDEX CGrunt::AnimForDeath(void) { +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +INDEX iAnim ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +FLOAT3D vFront ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +GetHeadingDirection (0 , vFront ); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +FLOAT fDamageDir = m_vDamage % vFront ; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +if(fDamageDir < 0){ +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +iAnim = GRUNT_ANIM_DEATHBACKWARD ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +}else { +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +iAnim = GRUNT_ANIM_DEATHFORWARD ; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StartModelAnim (iAnim , 0); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return iAnim ; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +FLOAT CGrunt::WaitForDust(FLOAT3D & vStretch) { +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +vStretch = FLOAT3D (1 , 1 , 2); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +if(GetModelObject () -> GetAnim () == GRUNT_ANIM_DEATHBACKWARD ) +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +{ +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return 0.5f; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +else if(GetModelObject () -> GetAnim () == GRUNT_ANIM_DEATHFORWARD ) +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +{ +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return 1.0f; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return - 1.0f; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::DeathNotify(void) { +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +ChangeCollisionBoxIndexWhenPossible (GRUNT_COLLISION_BOX_DEATH ); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +en_fDensity = 500.0f; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::StandingAnim(void) { +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StartModelAnim (GRUNT_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::RunningAnim(void) { +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StartModelAnim (GRUNT_ANIM_RUN , AOF_LOOPING | AOF_NORESTART ); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::WalkingAnim(void) { +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +RunningAnim (); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::RotatingAnim(void) { +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +RunningAnim (); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::IdleSound(void) { +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::SightSound(void) { +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::WoundSound(void) { +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::DeathSound(void) { +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} + +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void CGrunt::EnemyPostInit(void) +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +{ +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_soFire1 . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_soFire2 . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} +BOOL CGrunt:: +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGrunt_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGrunt::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +if(!(m_gtType == GT_SOLDIER )){ Jump(STATE_CURRENT,0x01570008, FALSE, EInternal());return TRUE;} +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +STATE_CGrunt_SoldierAttack, TRUE; +Jump(STATE_CURRENT, 0x01570001, FALSE, EBegin());return TRUE;}BOOL CGrunt::H0x01570001_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CGrunt_SoldierAttack, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01570002, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CGrunt::H0x01570002_Fire_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570002 +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x01570007, FALSE, EInternal());return TRUE;}BOOL CGrunt::H0x01570008_Fire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570008 +if(!(m_gtType == GT_COMMANDER )){ Jump(STATE_CURRENT,0x01570006, FALSE, EInternal());return TRUE;} +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +STATE_CGrunt_CommanderAttack, TRUE; +Jump(STATE_CURRENT, 0x01570003, FALSE, EBegin());return TRUE;}BOOL CGrunt::H0x01570003_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CGrunt_CommanderAttack, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01570004, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CGrunt::H0x01570004_Fire_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570004 +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x01570005, FALSE, EInternal());return TRUE;}BOOL CGrunt::H0x01570006_Fire_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570006 +{ +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +ASSERT (FALSE ); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +}Jump(STATE_CURRENT,0x01570005, FALSE, EInternal());return TRUE;} +BOOL CGrunt::H0x01570005_Fire_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570005 +Jump(STATE_CURRENT,0x01570007, FALSE, EInternal());return TRUE;} +BOOL CGrunt::H0x01570007_Fire_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570007 + +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +Return(STATE_CURRENT,EReturn ()); +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CGrunt:: +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SoldierAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGrunt_SoldierAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGrunt::SoldierAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StandingAnimFight (); +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetTimerAfter(0.2f + FRnd () * 0.25f); +Jump(STATE_CURRENT, 0x0157000a, FALSE, EBegin());return TRUE;}BOOL CGrunt::H0x0157000a_SoldierAttack_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0157000b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGrunt::H0x0157000b_SoldierAttack_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000b +; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StartModelAnim (GRUNT_ANIM_FIRE , 0); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_SOL , FIREPOS_SOLDIER , ANGLE3D (0 , 0 , 0)); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PlaySound (m_soFire1 , SOUND_FIRE , SOF_3D ); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetTimerAfter(0.15f + FRnd () * 0.1f); +Jump(STATE_CURRENT, 0x0157000c, FALSE, EBegin());return TRUE;}BOOL CGrunt::H0x0157000c_SoldierAttack_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0157000d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGrunt::H0x0157000d_SoldierAttack_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000d +; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StartModelAnim (GRUNT_ANIM_FIRE , 0); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_SOL , FIREPOS_SOLDIER , ANGLE3D (0 , 0 , 0)); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PlaySound (m_soFire2 , SOUND_FIRE , SOF_3D ); +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetTimerAfter(FRnd () * 0.333f); +Jump(STATE_CURRENT, 0x0157000e, FALSE, EBegin());return TRUE;}BOOL CGrunt::H0x0157000e_SoldierAttack_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0157000f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGrunt::H0x0157000f_SoldierAttack_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000f +; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +Return(STATE_CURRENT,EEnd ()); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CGrunt:: +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +CommanderAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGrunt_CommanderAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGrunt::CommanderAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StandingAnimFight (); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetTimerAfter(0.2f + FRnd () * 0.25f); +Jump(STATE_CURRENT, 0x01570011, FALSE, EBegin());return TRUE;}BOOL CGrunt::H0x01570011_CommanderAttack_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570011 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01570012, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGrunt::H0x01570012_CommanderAttack_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570012 +; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StartModelAnim (GRUNT_ANIM_FIRE , 0); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_COM , FIREPOS_COMMANDER_DN , ANGLE3D (- 20 , 0 , 0)); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PlaySound (m_soFire1 , SOUND_FIRE , SOF_3D ); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetTimerAfter(0.035f); +Jump(STATE_CURRENT, 0x01570013, FALSE, EBegin());return TRUE;}BOOL CGrunt::H0x01570013_CommanderAttack_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570013 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01570014, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGrunt::H0x01570014_CommanderAttack_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570014 +; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StartModelAnim (GRUNT_ANIM_FIRE , 0); +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_COM , FIREPOS_COMMANDER_DN , ANGLE3D (- 10 , 0 , 0)); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PlaySound (m_soFire2 , SOUND_FIRE , SOF_3D ); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetTimerAfter(0.035f); +Jump(STATE_CURRENT, 0x01570015, FALSE, EBegin());return TRUE;}BOOL CGrunt::H0x01570015_CommanderAttack_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01570016, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGrunt::H0x01570016_CommanderAttack_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570016 +; +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StartModelAnim (GRUNT_ANIM_FIRE , 0); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_COM , FIREPOS_COMMANDER_DN , ANGLE3D (0 , 0 , 0)); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PlaySound (m_soFire1 , SOUND_FIRE , SOF_3D ); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetTimerAfter(0.035f); +Jump(STATE_CURRENT, 0x01570017, FALSE, EBegin());return TRUE;}BOOL CGrunt::H0x01570017_CommanderAttack_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570017 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01570018, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGrunt::H0x01570018_CommanderAttack_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570018 +; +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StartModelAnim (GRUNT_ANIM_FIRE , 0); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_COM , FIREPOS_COMMANDER_DN , ANGLE3D (10 , 0 , 0)); +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PlaySound (m_soFire2 , SOUND_FIRE , SOF_3D ); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetTimerAfter(0.035f); +Jump(STATE_CURRENT, 0x01570019, FALSE, EBegin());return TRUE;}BOOL CGrunt::H0x01570019_CommanderAttack_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570019 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0157001a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGrunt::H0x0157001a_CommanderAttack_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157001a +; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StartModelAnim (GRUNT_ANIM_FIRE , 0); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_COM , FIREPOS_COMMANDER_DN , ANGLE3D (20 , 0 , 0)); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +PlaySound (m_soFire2 , SOUND_FIRE , SOF_3D ); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetTimerAfter(FRnd () * 0.5f); +Jump(STATE_CURRENT, 0x0157001b, FALSE, EBegin());return TRUE;}BOOL CGrunt::H0x0157001b_CommanderAttack_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157001b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0157001c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGrunt::H0x0157001c_CommanderAttack_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157001c +; +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +Return(STATE_CURRENT,EEnd ()); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CGrunt:: +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGrunt_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGrunt::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +InitAsModel (); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetCollisionFlags (ECF_MODEL ); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +en_tmMaxHoldBreath = 5.0f; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +en_fDensity = 2000.0f; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetModel (MODEL_GRUNT ); +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +switch(m_gtType ){ +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +case GT_SOLDIER : +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetModelMainTexture (TEXTURE_SOLDIER ); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +AddAttachment (GRUNT_ATTACHMENT_GUN_SMALL , MODEL_GUN_SOLDIER , TEXTURE_GUN_SOLDIER ); +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fWalkSpeed = FRnd () + 2.5f; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 500.0f); +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fAttackRunSpeed = FRnd () + 6.5f; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fCloseRunSpeed = FRnd () + 6.5f; +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fAttackDistance = 80.0f; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fCloseDistance = 0.0f; +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fStopDistance = 8.0f; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fAttackFireTime = 2.0f; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fCloseFireTime = 1.0f; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fIgnoreRange = 200.0f; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fBlowUpAmount = 80.0f; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fBodyParts = 4; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fDamageWounded = 0.0f; +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_iScore = 500; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetHealth (40.0f); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fMaxHealth = 40.0f; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +GetModelObject () -> StretchModel (FLOAT3D (STRETCH_SOLDIER , STRETCH_SOLDIER , STRETCH_SOLDIER )); +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +break ; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +case GT_COMMANDER : +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetModelMainTexture (TEXTURE_COMMANDER ); +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +AddAttachment (GRUNT_ATTACHMENT_GUN_COMMANDER , MODEL_GUN_COMMANDER , TEXTURE_GUN_COMMANDER ); +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fWalkSpeed = FRnd () + 2.5f; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 500.0f); +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fAttackRunSpeed = FRnd () + 8.0f; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fCloseRunSpeed = FRnd () + 8.0f; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fAttackDistance = 90.0f; +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fCloseDistance = 0.0f; +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fStopDistance = 15.0f; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fAttackFireTime = 4.0f; +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fCloseFireTime = 2.0f; +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fIgnoreRange = 200.0f; +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fBodyParts = 5; +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fDamageWounded = 0.0f; +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_iScore = 800; +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SetHealth (60.0f); +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +m_fMaxHealth = 60.0f; +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +GetModelObject () -> StretchModel (FLOAT3D (STRETCH_COMMANDER , STRETCH_COMMANDER , STRETCH_COMMANDER )); +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +break ; +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +} +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +ModelChangeNotify (); +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +StandingAnim (); +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Grunt.es b/Sources/EntitiesMP/Grunt.es new file mode 100644 index 0000000..16a1c28 --- /dev/null +++ b/Sources/EntitiesMP/Grunt.es @@ -0,0 +1,369 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +343 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/Grunt/Grunt.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/BasicEffects"; + +enum GruntType { + 0 GT_SOLDIER "Grunt soldier", + 1 GT_COMMANDER "Grunt commander", +}; + +%{ +#define STRETCH_SOLDIER 1.2f +#define STRETCH_COMMANDER 1.4f + +// info structure +static EntityInfo eiGruntSoldier = { + EIBT_FLESH, 200.0f, + 0.0f, 1.9f*STRETCH_SOLDIER, 0.0f, // source (eyes) + 0.0f, 1.3f*STRETCH_SOLDIER, 0.0f, // target (body) +}; + +static EntityInfo eiGruntCommander = { + EIBT_FLESH, 250.0f, + 0.0f, 1.9f*STRETCH_COMMANDER, 0.0f, // source (eyes) + 0.0f, 1.3f*STRETCH_COMMANDER, 0.0f, // target (body) +}; + +#define FIREPOS_SOLDIER FLOAT3D(0.07f, 1.36f, -0.78f)*STRETCH_SOLDIER +#define FIREPOS_COMMANDER_UP FLOAT3D(0.09f, 1.45f, -0.62f)*STRETCH_COMMANDER +#define FIREPOS_COMMANDER_DN FLOAT3D(0.10f, 1.30f, -0.60f)*STRETCH_COMMANDER +%} + + +class CGrunt: CEnemyBase { +name "Grunt"; +thumbnail "Thumbnails\\Grunt.tbn"; + +properties: + 1 enum GruntType m_gtType "Type" 'Y' = GT_SOLDIER, + + 10 CSoundObject m_soFire1, + 11 CSoundObject m_soFire2, + +// class internal + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + 3 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + + 10 model MODEL_GRUNT "ModelsMP\\Enemies\\Grunt\\Grunt.mdl", + 11 model MODEL_GUN_COMMANDER "ModelsMP\\Enemies\\Grunt\\Gun_Commander.mdl", + 12 model MODEL_GUN_SOLDIER "ModelsMP\\Enemies\\Grunt\\Gun.mdl", + + 20 texture TEXTURE_SOLDIER "ModelsMP\\Enemies\\Grunt\\Soldier.tex", + 21 texture TEXTURE_COMMANDER "ModelsMP\\Enemies\\Grunt\\Commander.tex", + 22 texture TEXTURE_GUN_COMMANDER "ModelsMP\\Enemies\\Grunt\\Gun_Commander.tex", + 23 texture TEXTURE_GUN_SOLDIER "ModelsMP\\Enemies\\Grunt\\Gun.tex", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "ModelsMP\\Enemies\\Grunt\\Sounds\\Idle.wav", + 52 sound SOUND_SIGHT "ModelsMP\\Enemies\\Grunt\\Sounds\\Sight.wav", + 53 sound SOUND_WOUND "ModelsMP\\Enemies\\Grunt\\Sounds\\Wound.wav", + 57 sound SOUND_FIRE "ModelsMP\\Enemies\\Grunt\\Sounds\\Fire.wav", + 58 sound SOUND_DEATH "ModelsMP\\Enemies\\Grunt\\Sounds\\Death.wav", + +functions: + + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("A Grunt sent %s into the halls of Valhalla"), strPlayerName); + return str; + } + + /* Entity info */ + void *GetEntityInfo(void) { + if (m_gtType==GT_SOLDIER) { + return &eiGruntSoldier; + } else if (m_gtType==GT_COMMANDER) { + return &eiGruntSoldier; + } else { + ASSERT("Unknown grunt type!"); + return NULL; + } + }; + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnmSoldier, "DataMP\\Messages\\Enemies\\GruntSoldier.txt"); + static DECLARE_CTFILENAME(fnmCommander, "DataMP\\Messages\\Enemies\\GruntCommander.txt"); + switch(m_gtType) { + default: ASSERT(FALSE); + case GT_SOLDIER: return fnmSoldier; + case GT_COMMANDER: return fnmCommander; + } + }; + + void Precache(void) { + CEnemyBase::Precache(); + + if (m_gtType==GT_SOLDIER) { + PrecacheClass(CLASS_PROJECTILE, PRT_GRUNT_PROJECTILE_SOL); + } + if (m_gtType==GT_COMMANDER) { + PrecacheClass(CLASS_PROJECTILE, PRT_GRUNT_PROJECTILE_COM); + } + + PrecacheSound(SOUND_IDLE); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_FIRE); + PrecacheSound(SOUND_DEATH); + }; + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + }; + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim; + iAnim = GRUNT_ANIM_WOUND01; + StartModelAnim(iAnim, 0); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + INDEX iAnim; + FLOAT3D vFront; + GetHeadingDirection(0, vFront); + FLOAT fDamageDir = m_vDamage%vFront; + if (fDamageDir<0) { + iAnim = GRUNT_ANIM_DEATHBACKWARD; + } else { + iAnim = GRUNT_ANIM_DEATHFORWARD; + } + + StartModelAnim(iAnim, 0); + return iAnim; + }; + + FLOAT WaitForDust(FLOAT3D &vStretch) { + vStretch=FLOAT3D(1,1,2); + if(GetModelObject()->GetAnim()==GRUNT_ANIM_DEATHBACKWARD) + { + return 0.5f; + } + else if(GetModelObject()->GetAnim()==GRUNT_ANIM_DEATHFORWARD) + { + return 1.0f; + } + return -1.0f; + }; + + void DeathNotify(void) { + ChangeCollisionBoxIndexWhenPossible(GRUNT_COLLISION_BOX_DEATH); + en_fDensity = 500.0f; + }; + + // virtual anim functions + void StandingAnim(void) { + StartModelAnim(GRUNT_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + /*void StandingAnimFight(void) + { + StartModelAnim(HEADMAN_ANIM_IDLE_FIGHT, AOF_LOOPING|AOF_NORESTART); + }*/ + void RunningAnim(void) { + StartModelAnim(GRUNT_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); + }; + void WalkingAnim(void) { + RunningAnim(); + }; + void RotatingAnim(void) { + RunningAnim(); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + // set sound default parameters + m_soFire1.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + m_soFire2.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + }; + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + Fire(EVoid) : CEnemyBase::Fire { + // soldier + if (m_gtType == GT_SOLDIER) { + autocall SoldierAttack() EEnd; + // commander + } else if (m_gtType == GT_COMMANDER) { + autocall CommanderAttack() EEnd; + // should never get here + } else{ + ASSERT(FALSE); + } + return EReturn(); + }; + + // Soldier attack + SoldierAttack(EVoid) { + StandingAnimFight(); + autowait(0.2f + FRnd()*0.25f); + + StartModelAnim(GRUNT_ANIM_FIRE, 0); + ShootProjectile(PRT_GRUNT_PROJECTILE_SOL, FIREPOS_SOLDIER, ANGLE3D(0, 0, 0)); + PlaySound(m_soFire1, SOUND_FIRE, SOF_3D); + + autowait(0.15f + FRnd()*0.1f); + StartModelAnim(GRUNT_ANIM_FIRE, 0); + ShootProjectile(PRT_GRUNT_PROJECTILE_SOL, FIREPOS_SOLDIER, ANGLE3D(0, 0, 0)); + PlaySound(m_soFire2, SOUND_FIRE, SOF_3D); + + + autowait(FRnd()*0.333f); + return EEnd(); + }; + + // Commander attack (predicted firing on moving player) + CommanderAttack(EVoid) { + StandingAnimFight(); + autowait(0.2f + FRnd()*0.25f); + + /*FLOAT3D vGunPosAbs = GetPlacement().pl_PositionVector + FLOAT3D(0.0f, 1.0f, 0.0f)*GetRotationMatrix(); + FLOAT3D vEnemySpeed = ((CMovableEntity&) *m_penEnemy).en_vCurrentTranslationAbsolute; + FLOAT3D vEnemyPos = ((CMovableEntity&) *m_penEnemy).GetPlacement().pl_PositionVector; + FLOAT fLaserSpeed = 45.0f; // m/s + FLOAT3D vPredictedEnemyPosition = CalculatePredictedPosition(vGunPosAbs, + vEnemyPos, fLaserSpeed, vEnemySpeed, GetPlacement().pl_PositionVector(2) ); + ShootPredictedProjectile(PRT_GRUNT_LASER, vPredictedEnemyPosition, FLOAT3D(0.0f, 1.0f, 0.0f), ANGLE3D(0, 0, 0));*/ + + StartModelAnim(GRUNT_ANIM_FIRE, 0); + ShootProjectile(PRT_GRUNT_PROJECTILE_COM, FIREPOS_COMMANDER_DN, ANGLE3D(-20, 0, 0)); + PlaySound(m_soFire1, SOUND_FIRE, SOF_3D); + + autowait(0.035f); + StartModelAnim(GRUNT_ANIM_FIRE, 0); + ShootProjectile(PRT_GRUNT_PROJECTILE_COM, FIREPOS_COMMANDER_DN, ANGLE3D(-10, 0, 0)); + PlaySound(m_soFire2, SOUND_FIRE, SOF_3D); + + autowait(0.035f); + StartModelAnim(GRUNT_ANIM_FIRE, 0); + ShootProjectile(PRT_GRUNT_PROJECTILE_COM, FIREPOS_COMMANDER_DN, ANGLE3D(0, 0, 0)); + PlaySound(m_soFire1, SOUND_FIRE, SOF_3D); + + autowait(0.035f); + StartModelAnim(GRUNT_ANIM_FIRE, 0); + ShootProjectile(PRT_GRUNT_PROJECTILE_COM, FIREPOS_COMMANDER_DN, ANGLE3D(10, 0, 0)); + PlaySound(m_soFire2, SOUND_FIRE, SOF_3D); + + autowait(0.035f); + StartModelAnim(GRUNT_ANIM_FIRE, 0); + ShootProjectile(PRT_GRUNT_PROJECTILE_COM, FIREPOS_COMMANDER_DN, ANGLE3D(20, 0, 0)); + PlaySound(m_soFire2, SOUND_FIRE, SOF_3D); + + autowait(FRnd()*0.5f); + return EEnd(); + }; + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + en_tmMaxHoldBreath = 5.0f; + en_fDensity = 2000.0f; + //m_fBlowUpSize = 2.0f; + + // set your appearance + SetModel(MODEL_GRUNT); + switch (m_gtType) { + case GT_SOLDIER: + // set your texture + SetModelMainTexture(TEXTURE_SOLDIER); + AddAttachment(GRUNT_ATTACHMENT_GUN_SMALL, MODEL_GUN_SOLDIER, TEXTURE_GUN_SOLDIER); + // setup moving speed + m_fWalkSpeed = FRnd() + 2.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f); + m_fAttackRunSpeed = FRnd() + 6.5f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + m_fCloseRunSpeed = FRnd() + 6.5f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + // setup attack distances + m_fAttackDistance = 80.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 8.0f; + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 200.0f; + //m_fBlowUpAmount = 65.0f; + m_fBlowUpAmount = 80.0f; + m_fBodyParts = 4; + m_fDamageWounded = 0.0f; + m_iScore = 500; + SetHealth(40.0f); + m_fMaxHealth = 40.0f; + // set stretch factors for height and width + GetModelObject()->StretchModel(FLOAT3D(STRETCH_SOLDIER, STRETCH_SOLDIER, STRETCH_SOLDIER)); + break; + + case GT_COMMANDER: + // set your texture + SetModelMainTexture(TEXTURE_COMMANDER); + AddAttachment(GRUNT_ATTACHMENT_GUN_COMMANDER, MODEL_GUN_COMMANDER, TEXTURE_GUN_COMMANDER); + // setup moving speed + m_fWalkSpeed = FRnd() + 2.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f); + m_fAttackRunSpeed = FRnd() + 8.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + m_fCloseRunSpeed = FRnd() + 8.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + // setup attack distances + m_fAttackDistance = 90.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 15.0f; + m_fAttackFireTime = 4.0f; + m_fCloseFireTime = 2.0f; + //m_fBlowUpAmount = 180.0f; + m_fIgnoreRange = 200.0f; + // damage/explode properties + m_fBodyParts = 5; + m_fDamageWounded = 0.0f; + m_iScore = 800; + SetHealth(60.0f); + m_fMaxHealth = 60.0f; + // set stretch factors for height and width + GetModelObject()->StretchModel(FLOAT3D(STRETCH_COMMANDER, STRETCH_COMMANDER, STRETCH_COMMANDER)); + break; + } + + ModelChangeNotify(); + StandingAnim(); + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Grunt.h b/Sources/EntitiesMP/Grunt.h new file mode 100644 index 0000000..b07bb9c --- /dev/null +++ b/Sources/EntitiesMP/Grunt.h @@ -0,0 +1,121 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Grunt_INCLUDED +#define _EntitiesMP_Grunt_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType GruntType_enum; +enum GruntType { + GT_SOLDIER = 0, + GT_COMMANDER = 1, +}; +DECL_DLL inline void ClearToDefault(GruntType &e) { e = (GruntType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CGrunt_DLLClass; +class CGrunt : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum GruntType m_gtType; + CSoundObject m_soFire1; + CSoundObject m_soFire2; + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void * GetEntityInfo(void); + +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void Precache(void); + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +INDEX AnimForDeath(void); + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void DeathNotify(void); + +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void StandingAnim(void); + +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void RunningAnim(void); + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void WalkingAnim(void); + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void RotatingAnim(void); + +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void IdleSound(void); + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void SightSound(void); + +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void WoundSound(void); + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void DeathSound(void); + +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +void EnemyPostInit(void); +#define STATE_CGrunt_Fire 0x01570000 + BOOL +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x01570001_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x01570002_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x01570003_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x01570004_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x01570005_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x01570006_Fire_06(const CEntityEvent &__eeInput); + BOOL H0x01570007_Fire_07(const CEntityEvent &__eeInput); + BOOL H0x01570008_Fire_08(const CEntityEvent &__eeInput); +#define STATE_CGrunt_SoldierAttack 0x01570009 + BOOL +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SoldierAttack(const CEntityEvent &__eeInput); + BOOL H0x0157000a_SoldierAttack_01(const CEntityEvent &__eeInput); + BOOL H0x0157000b_SoldierAttack_02(const CEntityEvent &__eeInput); + BOOL H0x0157000c_SoldierAttack_03(const CEntityEvent &__eeInput); + BOOL H0x0157000d_SoldierAttack_04(const CEntityEvent &__eeInput); + BOOL H0x0157000e_SoldierAttack_05(const CEntityEvent &__eeInput); + BOOL H0x0157000f_SoldierAttack_06(const CEntityEvent &__eeInput); +#define STATE_CGrunt_CommanderAttack 0x01570010 + BOOL +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +CommanderAttack(const CEntityEvent &__eeInput); + BOOL H0x01570011_CommanderAttack_01(const CEntityEvent &__eeInput); + BOOL H0x01570012_CommanderAttack_02(const CEntityEvent &__eeInput); + BOOL H0x01570013_CommanderAttack_03(const CEntityEvent &__eeInput); + BOOL H0x01570014_CommanderAttack_04(const CEntityEvent &__eeInput); + BOOL H0x01570015_CommanderAttack_05(const CEntityEvent &__eeInput); + BOOL H0x01570016_CommanderAttack_06(const CEntityEvent &__eeInput); + BOOL H0x01570017_CommanderAttack_07(const CEntityEvent &__eeInput); + BOOL H0x01570018_CommanderAttack_08(const CEntityEvent &__eeInput); + BOOL H0x01570019_CommanderAttack_09(const CEntityEvent &__eeInput); + BOOL H0x0157001a_CommanderAttack_10(const CEntityEvent &__eeInput); + BOOL H0x0157001b_CommanderAttack_11(const CEntityEvent &__eeInput); + BOOL H0x0157001c_CommanderAttack_12(const CEntityEvent &__eeInput); +#define STATE_CGrunt_Main 1 + BOOL +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Grunt_INCLUDED diff --git a/Sources/EntitiesMP/GruntSka.cpp b/Sources/EntitiesMP/GruntSka.cpp new file mode 100644 index 0000000..b3b6625 --- /dev/null +++ b/Sources/EntitiesMP/GruntSka.cpp @@ -0,0 +1,753 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" + +#include "StdH.h" +//#include "ModelsMP/Enemies/Grunt/Grunt.h" + +#include +#include +#line 17 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" + +#define STRETCH_SOLDIER 1.2f +#define STRETCH_COMMANDER 1.4f + +// info structure +static EntityInfo eiGruntSoldier = { + EIBT_FLESH, 200.0f, + 0.0f, 1.9f*STRETCH_SOLDIER, 0.0f, // source (eyes) + 0.0f, 1.3f*STRETCH_SOLDIER, 0.0f, // target (body) +}; + +static EntityInfo eiGruntCommander = { + EIBT_FLESH, 250.0f, + 0.0f, 1.9f*STRETCH_COMMANDER, 0.0f, // source (eyes) + 0.0f, 1.3f*STRETCH_COMMANDER, 0.0f, // target (body) +}; + +#define FIREPOS_SOLDIER FLOAT3D(0.07f, 1.36f, -0.78f)*STRETCH_SOLDIER +#define FIREPOS_COMMANDER_UP FLOAT3D(0.09f, 1.45f, -0.62f)*STRETCH_COMMANDER +#define FIREPOS_COMMANDER_DN FLOAT3D(0.10f, 1.30f, -0.60f)*STRETCH_COMMANDER + +#define COMANDER_SMC_MODEL "ModelsSKA\\Enemies\\Grunt\\Commander.smc" +#define SOLIDER_SMC_MODEL "ModelsSKA\\Enemies\\Grunt\\Grunt.smc" + +#define GRUNT_MESH +#define GRUNT_SKELETON +#define GRUNT_ANIMSET +#define GRUNT_TEXTURE + +#define CLEAR_ANIM_TIME 0.2f + +static INDEX idGrunt_Wound = -1; +static INDEX idGrunt_Run = -1; +static INDEX idGrunt_IdlePatrol = -1; +static INDEX idGrunt_IdleAttack = -1; +static INDEX idGrunt_Fire = -1; +static INDEX idGrunt_Default = -1; +static INDEX idGrunt_DeathForward = -1; +static INDEX idGrunt_DeathBackward = -1; +static INDEX idGrunt_GunModel = -1; + +static INDEX idGrund_NormalBox = -1; +static INDEX idGrund_DeathBox = -1; + +static CTextureObject _toStar01; + +#define SHP_BASE_TEXTURE 0 + + +void CGruntSka::SetDefaultProperties(void) { + m_gtType = GT_SOLDIER ; + m_soFire1.SetOwner(this); +m_soFire1.Stop_internal(); + m_soFire2.SetOwner(this); +m_soFire2.Stop_internal(); + m_fMidBoneRot = 0.0f; + m_miTest.Clear(); + + CEnemyBase::SetDefaultProperties(); +} + CGruntSka::CGruntSka(void) +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +{ +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idGrunt_Wound = ska_GetIDFromStringTable ("Grunt_Wound"); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idGrunt_Run = ska_GetIDFromStringTable ("Grunt_Run"); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idGrunt_IdlePatrol = ska_GetIDFromStringTable ("Grunt_IdlePatrol"); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idGrunt_IdleAttack = ska_GetIDFromStringTable ("Grunt_IdleAttack"); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idGrunt_Fire = ska_GetIDFromStringTable ("Grunt_Fire"); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idGrunt_Default = ska_GetIDFromStringTable ("Grunt_Default"); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idGrunt_DeathForward = ska_GetIDFromStringTable ("Grunt_DeathForward"); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idGrunt_DeathBackward = ska_GetIDFromStringTable ("Grunt_DeathBackward"); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idGrunt_GunModel = ska_GetIDFromStringTable ("Flamer"); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idGrund_NormalBox = ska_GetIDFromStringTable ("Normal"); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idGrund_DeathBox = ska_GetIDFromStringTable ("Death"); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::CreateTestModelInstance() +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +{ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +try { +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_miTest . AddMesh_t ((CTString) "ModelsSKA\\Test\\Arm\\Arm.bm"); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_miTest . AddSkeleton_t ((CTString) "ModelsSKA\\Test\\Arm\\Arm.bs"); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_miTest . AddAnimSet_t ((CTString) "ModelsSKA\\Test\\Arm\\Arm.ba"); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_miTest . AddTexture_t ((CTString) "ModelsSKA\\Test\\Arm\\Objects\\Arm.tex" , "Arm" , NULL ); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_miTest . AddColisionBox ("Default" , FLOAT3D (- 0.5f , 0.0f , - 0.5f) , FLOAT3D (0.5f , 2.0f , 0.5f)); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +}catch (char * strErr ){ +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +FatalError (strErr ); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::BuildGruntModel() +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +{ +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +en_pmiModelInstance = CreateModelInstance ("GruntSka"); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +CModelInstance * pmi = GetModelInstance (); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +try { +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmi -> AddMesh_t ((CTString) "ModelsSKA\\Enemies\\Grunt\\Grunt.bm"); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmi -> AddSkeleton_t ((CTString) "ModelsSKA\\Enemies\\Grunt\\Grunt.bs"); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmi -> AddAnimSet_t ((CTString) "ModelsSKA\\Enemies\\Grunt\\Grunt.ba"); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmi -> AddTexture_t ((CTString) "ModelsSKA\\Enemies\\Grunt\\Soldier.tex" , "Grunt" , NULL ); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmi -> AddColisionBox ("Default" , FLOAT3D (- 0.5f , 0.0f , - 0.5f) , FLOAT3D (0.5f , 2.0f , 0.5f)); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +CModelInstance * pmiFlamer = CreateModelInstance ("Flamer"); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmiFlamer -> AddMesh_t ((CTString) "ModelsSKA\\Weapons\\Flamer\\Flamer.bm"); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmiFlamer -> AddSkeleton_t ((CTString) "ModelsSKA\\Weapons\\Flamer\\Flamer.bs"); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmiFlamer -> AddAnimSet_t ((CTString) "ModelsSKA\\Weapons\\Flamer\\Flamer.ba"); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmiFlamer -> AddTexture_t ((CTString) "ModelsSKA\\Weapons\\Flamer\\Flamer.tex" , "Flamer" , NULL ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmiFlamer -> AddTexture_t ((CTString) "ModelsSKA\\Enemies\\Grunt\\Lava04FX.tex" , "Lava04FX" , NULL ); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmiFlamer -> SetOffsetRot (ANGLE3D (0 , 0 , 180)); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmi -> AddChild (pmiFlamer ); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +INDEX iParenBoneID = ska_GetIDFromStringTable ("R_Hand"); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmiFlamer -> SetParentBone (iParenBoneID ); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetSkaColisionInfo (); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +}catch (char * strErr ){ +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +FatalError (strErr ); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::BuildCommanderModel(CEntity * penGrunt) +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +{ +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetSkaModel ("ModelsSKA\\Enemies\\Grunt\\CommanderNoGun.smc"); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +CModelInstance * pmiFlamer = NULL ; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +try { +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmiFlamer = ParseSmcFile_t ("ModelsSKA\\Weapons\\Flamer\\Flamer.smc"); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +}catch (char * strErr ){ +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +FatalError (strErr ); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +INDEX iParenBoneID = ska_GetIDFromStringTable ("R_Hand"); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +CModelInstance * pmi = GetModelInstance (); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmi -> AddChild (pmiFlamer ); +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmiFlamer -> SetParentBone (iParenBoneID ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +pmiFlamer -> SetOffsetRot (ANGLE3D (0 , 0 , 180)); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetSkaColisionInfo (); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + CTString CGruntSka::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +{ +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +CTString str ; +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +str . PrintF (TRANS ("A Grunt sent %s into the halls of Valhalla") , strPlayerName ); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return str ; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void * CGruntSka::GetEntityInfo(void) { +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +if(m_gtType == GT_SOLDIER ){ +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return & eiGruntSoldier ; +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +}else if(m_gtType == GT_COMMANDER ){ +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return & eiGruntSoldier ; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +}else { +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ASSERT ("Unknown grunt type!"); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return NULL ; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + const CTFileName & CGruntSka::GetComputerMessageName(void)const { +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +static DECLARE_CTFILENAME (fnmSoldier , "DataMP\\Messages\\Enemies\\GruntSoldier.txt"); +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +static DECLARE_CTFILENAME (fnmCommander , "DataMP\\Messages\\Enemies\\GruntCommander.txt"); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +switch(m_gtType ){ +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +default : ASSERT (FALSE ); +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +case GT_SOLDIER : return fnmSoldier ; +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +case GT_COMMANDER : return fnmCommander ; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::Precache(void) { +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +CEnemyBase :: Precache (); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +if(m_gtType == GT_SOLDIER ){ +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PrecacheClass (CLASS_PROJECTILE , PRT_GRUNT_PROJECTILE_SOL ); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +if(m_gtType == GT_COMMANDER ){ +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PrecacheClass (CLASS_PROJECTILE , PRT_GRUNT_PROJECTILE_COM ); +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PrecacheSound (SOUND_IDLE ); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PrecacheSound (SOUND_SIGHT ); +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PrecacheSound (SOUND_WOUND ); +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PrecacheSound (SOUND_FIRE ); +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PrecacheSound (SOUND_DEATH ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +{ +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +INDEX CGruntSka::AnimForDamage(FLOAT fDamage) { +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> AddAnimation (idGrunt_Wound , AN_CLEAR , 1 , 0); +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return idGrunt_Wound ; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +INDEX CGruntSka::AnimForDeath(void) { +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +INDEX idAnimDeath ; +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +FLOAT3D vFront ; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetHeadingDirection (0 , vFront ); +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +FLOAT fDamageDir = m_vDamage % vFront ; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +if(fDamageDir < 0){ +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idAnimDeath = idGrunt_DeathBackward ; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +}else { +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +idAnimDeath = idGrunt_DeathForward ; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> AddAnimation (idAnimDeath , AN_CLEAR , 1 , 0); +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return idAnimDeath ; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +FLOAT CGruntSka::WaitForDust(FLOAT3D & vStretch) { +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +vStretch = FLOAT3D (1 , 1 , 2); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +if(GetModelInstance () -> IsAnimationPlaying (idGrunt_DeathBackward )){ +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return 0.5f; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +}else if(GetModelInstance () -> IsAnimationPlaying (idGrunt_DeathForward )){ +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return 1.0f; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return - 1.0f; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::DeathNotify(void) { +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +INDEX iBoxIndex = GetModelInstance () -> GetColisionBoxIndex (idGrund_DeathBox ); +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ASSERT (iBoxIndex >= 0); +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ChangeCollisionBoxIndexWhenPossible (iBoxIndex ); +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +en_fDensity = 500.0f; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::StandingAnim(void) { +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> AddAnimation (idGrunt_IdleAttack , AN_LOOPING | AN_NORESTART | AN_CLEAR , 1 , 0); +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::RunningAnim(void) { +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> AddAnimation (idGrunt_Run , AN_LOOPING | AN_NORESTART | AN_CLEAR , 1 , 0); +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::WalkingAnim(void) { +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +RunningAnim (); +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::RotatingAnim(void) { +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +RunningAnim (); +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::IdleSound(void) { +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::SightSound(void) { +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::WoundSound(void) { +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::DeathSound(void) { +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} + +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CGruntSka::EnemyPostInit(void) +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +{ +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_soFire1 . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_soFire2 . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} +BOOL CGruntSka:: +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGruntSka_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGruntSka::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +if(!(m_gtType == GT_SOLDIER )){ Jump(STATE_CURRENT,0x01570008, FALSE, EInternal());return TRUE;} +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +STATE_CGruntSka_SoldierAttack, TRUE; +Jump(STATE_CURRENT, 0x01570001, FALSE, EBegin());return TRUE;}BOOL CGruntSka::H0x01570001_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CGruntSka_SoldierAttack, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01570002, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CGruntSka::H0x01570002_Fire_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570002 +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x01570007, FALSE, EInternal());return TRUE;}BOOL CGruntSka::H0x01570008_Fire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570008 +if(!(m_gtType == GT_COMMANDER )){ Jump(STATE_CURRENT,0x01570006, FALSE, EInternal());return TRUE;} +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +STATE_CGruntSka_CommanderAttack, TRUE; +Jump(STATE_CURRENT, 0x01570003, FALSE, EBegin());return TRUE;}BOOL CGruntSka::H0x01570003_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CGruntSka_CommanderAttack, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01570004, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CGruntSka::H0x01570004_Fire_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570004 +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x01570005, FALSE, EInternal());return TRUE;}BOOL CGruntSka::H0x01570006_Fire_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570006 +{ +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ASSERT (FALSE ); +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +}Jump(STATE_CURRENT,0x01570005, FALSE, EInternal());return TRUE;} +BOOL CGruntSka::H0x01570005_Fire_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570005 +Jump(STATE_CURRENT,0x01570007, FALSE, EInternal());return TRUE;} +BOOL CGruntSka::H0x01570007_Fire_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570007 + +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +Return(STATE_CURRENT,EReturn ()); +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CGruntSka:: +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SoldierAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGruntSka_SoldierAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGruntSka::SoldierAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +StandingAnimFight (); +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetTimerAfter(0.2f + FRnd () * 0.25f); +Jump(STATE_CURRENT, 0x0157000a, FALSE, EBegin());return TRUE;}BOOL CGruntSka::H0x0157000a_SoldierAttack_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0157000b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGruntSka::H0x0157000b_SoldierAttack_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000b +; +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> AddAnimation (idGrunt_Fire , AN_CLEAR , 1.0f , 0); +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_SOL , FIREPOS_SOLDIER , ANGLE3D (0 , 0 , 0)); +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PlaySound (m_soFire1 , SOUND_FIRE , SOF_3D ); +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetTimerAfter(0.15f + FRnd () * 0.1f); +Jump(STATE_CURRENT, 0x0157000c, FALSE, EBegin());return TRUE;}BOOL CGruntSka::H0x0157000c_SoldierAttack_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0157000d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGruntSka::H0x0157000d_SoldierAttack_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000d +; +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> AddAnimation (idGrunt_Fire , AN_CLEAR , 1.0f , 0); +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_SOL , FIREPOS_SOLDIER , ANGLE3D (0 , 0 , 0)); +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PlaySound (m_soFire2 , SOUND_FIRE , SOF_3D ); +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetTimerAfter(FRnd () * 0.333f); +Jump(STATE_CURRENT, 0x0157000e, FALSE, EBegin());return TRUE;}BOOL CGruntSka::H0x0157000e_SoldierAttack_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0157000f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGruntSka::H0x0157000f_SoldierAttack_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157000f +; +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +Return(STATE_CURRENT,EEnd ()); +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CGruntSka:: +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +CommanderAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGruntSka_CommanderAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGruntSka::CommanderAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +StandingAnimFight (); +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetTimerAfter(0.2f + FRnd () * 0.25f); +Jump(STATE_CURRENT, 0x01570011, FALSE, EBegin());return TRUE;}BOOL CGruntSka::H0x01570011_CommanderAttack_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570011 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01570012, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGruntSka::H0x01570012_CommanderAttack_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570012 +; +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> AddAnimation (idGrunt_Fire , AN_CLEAR , 1 , 0); +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_COM , FIREPOS_COMMANDER_DN , ANGLE3D (- 20 , 0 , 0)); +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PlaySound (m_soFire1 , SOUND_FIRE , SOF_3D ); +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetTimerAfter(0.035f); +Jump(STATE_CURRENT, 0x01570013, FALSE, EBegin());return TRUE;}BOOL CGruntSka::H0x01570013_CommanderAttack_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570013 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01570014, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGruntSka::H0x01570014_CommanderAttack_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570014 +; +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> AddAnimation (idGrunt_Fire , AN_CLEAR , 1 , 0); +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_COM , FIREPOS_COMMANDER_DN , ANGLE3D (- 10 , 0 , 0)); +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PlaySound (m_soFire2 , SOUND_FIRE , SOF_3D ); +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetTimerAfter(0.035f); +Jump(STATE_CURRENT, 0x01570015, FALSE, EBegin());return TRUE;}BOOL CGruntSka::H0x01570015_CommanderAttack_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01570016, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGruntSka::H0x01570016_CommanderAttack_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570016 +; +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> AddAnimation (idGrunt_Fire , AN_CLEAR , 1 , 0); +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_COM , FIREPOS_COMMANDER_DN , ANGLE3D (0 , 0 , 0)); +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PlaySound (m_soFire1 , SOUND_FIRE , SOF_3D ); +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetTimerAfter(0.035f); +Jump(STATE_CURRENT, 0x01570017, FALSE, EBegin());return TRUE;}BOOL CGruntSka::H0x01570017_CommanderAttack_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570017 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01570018, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGruntSka::H0x01570018_CommanderAttack_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570018 +; +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> AddAnimation (idGrunt_Fire , AN_CLEAR , 1 , 0); +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_COM , FIREPOS_COMMANDER_DN , ANGLE3D (10 , 0 , 0)); +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PlaySound (m_soFire2 , SOUND_FIRE , SOF_3D ); +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetTimerAfter(0.035f); +Jump(STATE_CURRENT, 0x01570019, FALSE, EBegin());return TRUE;}BOOL CGruntSka::H0x01570019_CommanderAttack_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01570019 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0157001a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGruntSka::H0x0157001a_CommanderAttack_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157001a +; +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> AddAnimation (idGrunt_Fire , AN_CLEAR , 1 , 0); +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ShootProjectile (PRT_GRUNT_PROJECTILE_COM , FIREPOS_COMMANDER_DN , ANGLE3D (20 , 0 , 0)); +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +PlaySound (m_soFire2 , SOUND_FIRE , SOF_3D ); +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetTimerAfter(FRnd () * 0.5f); +Jump(STATE_CURRENT, 0x0157001b, FALSE, EBegin());return TRUE;}BOOL CGruntSka::H0x0157001b_CommanderAttack_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157001b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0157001c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGruntSka::H0x0157001c_CommanderAttack_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0157001c +; +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +Return(STATE_CURRENT,EEnd ()); +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CGruntSka:: +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGruntSka_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGruntSka::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +InitAsSkaModel (); +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetCollisionFlags (ECF_MODEL ); +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +en_tmMaxHoldBreath = 5.0f; +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +en_fDensity = 2000.0f; +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +switch(m_gtType ){ +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +case GT_SOLDIER : +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetSkaModel (SOLIDER_SMC_MODEL ); +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fWalkSpeed = FRnd () + 2.5f; +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 500.0f); +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fAttackRunSpeed = FRnd () + 6.5f; +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fCloseRunSpeed = FRnd () + 6.5f; +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fAttackDistance = 80.0f; +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fCloseDistance = 0.0f; +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fStopDistance = 8.0f; +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fAttackFireTime = 2.0f; +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fCloseFireTime = 1.0f; +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fIgnoreRange = 200.0f; +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fBlowUpAmount = 80.0f; +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fBodyParts = 4; +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fDamageWounded = 0.0f; +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_iScore = 500; +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetHealth (40.0f); +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fMaxHealth = 40.0f; +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> StretchModel (FLOAT3D (STRETCH_SOLDIER , STRETCH_SOLDIER , STRETCH_SOLDIER )); +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +break ; +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +case GT_COMMANDER : +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetSkaModel (COMANDER_SMC_MODEL ); +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fWalkSpeed = FRnd () + 2.5f; +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 500.0f); +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fAttackRunSpeed = FRnd () + 8.0f; +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fCloseRunSpeed = FRnd () + 8.0f; +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fAttackDistance = 90.0f; +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fCloseDistance = 0.0f; +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fStopDistance = 15.0f; +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fAttackFireTime = 4.0f; +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fCloseFireTime = 2.0f; +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fIgnoreRange = 200.0f; +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fBodyParts = 5; +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fDamageWounded = 0.0f; +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_iScore = 800; +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SetHealth (60.0f); +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +m_fMaxHealth = 60.0f; +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +GetModelInstance () -> StretchModel (FLOAT3D (STRETCH_COMMANDER , STRETCH_COMMANDER , STRETCH_COMMANDER )); +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +break ; +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +} +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +ModelChangeNotify (); +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +StandingAnim (); +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/GruntSka.es b/Sources/EntitiesMP/GruntSka.es new file mode 100644 index 0000000..ec2a1c7 --- /dev/null +++ b/Sources/EntitiesMP/GruntSka.es @@ -0,0 +1,553 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +343 +%{ +#include "StdH.h" +//#include "ModelsMP/Enemies/Grunt/Grunt.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/BasicEffects"; + +enum GruntSkaType { + 0 GT_SOLDIER "Grunt soldier", + 1 GT_COMMANDER "Grunt commander", +}; + +%{ +#define STRETCH_SOLDIER 1.2f +#define STRETCH_COMMANDER 1.4f + +// info structure +static EntityInfo eiGruntSoldier = { + EIBT_FLESH, 200.0f, + 0.0f, 1.9f*STRETCH_SOLDIER, 0.0f, // source (eyes) + 0.0f, 1.3f*STRETCH_SOLDIER, 0.0f, // target (body) +}; + +static EntityInfo eiGruntCommander = { + EIBT_FLESH, 250.0f, + 0.0f, 1.9f*STRETCH_COMMANDER, 0.0f, // source (eyes) + 0.0f, 1.3f*STRETCH_COMMANDER, 0.0f, // target (body) +}; + +#define FIREPOS_SOLDIER FLOAT3D(0.07f, 1.36f, -0.78f)*STRETCH_SOLDIER +#define FIREPOS_COMMANDER_UP FLOAT3D(0.09f, 1.45f, -0.62f)*STRETCH_COMMANDER +#define FIREPOS_COMMANDER_DN FLOAT3D(0.10f, 1.30f, -0.60f)*STRETCH_COMMANDER + +#define COMANDER_SMC_MODEL "ModelsSKA\\Enemies\\Grunt\\Commander.smc" +#define SOLIDER_SMC_MODEL "ModelsSKA\\Enemies\\Grunt\\Grunt.smc" + +#define GRUNT_MESH +#define GRUNT_SKELETON +#define GRUNT_ANIMSET +#define GRUNT_TEXTURE + +#define CLEAR_ANIM_TIME 0.2f + +static INDEX idGrunt_Wound = -1; +static INDEX idGrunt_Run = -1; +static INDEX idGrunt_IdlePatrol = -1; +static INDEX idGrunt_IdleAttack = -1; +static INDEX idGrunt_Fire = -1; +static INDEX idGrunt_Default = -1; +static INDEX idGrunt_DeathForward = -1; +static INDEX idGrunt_DeathBackward = -1; +static INDEX idGrunt_GunModel = -1; + +static INDEX idGrund_NormalBox = -1; +static INDEX idGrund_DeathBox = -1; + +static CTextureObject _toStar01; + +#define SHP_BASE_TEXTURE 0 + +%} + + +class CGruntSka: CEnemyBase { +name "GruntSka"; +thumbnail "Thumbnails\\Grunt.tbn"; + +properties: + 1 enum GruntSkaType m_gtType "Type" 'Y' = GT_SOLDIER, + + 10 CSoundObject m_soFire1, + 11 CSoundObject m_soFire2, + 20 FLOAT m_fMidBoneRot = 0.0f, + 30 CModelInstance m_miTest, + + +// class internal + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + 3 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "ModelsMP\\Enemies\\Grunt\\Sounds\\Idle.wav", + 52 sound SOUND_SIGHT "ModelsMP\\Enemies\\Grunt\\Sounds\\Sight.wav", + 53 sound SOUND_WOUND "ModelsMP\\Enemies\\Grunt\\Sounds\\Wound.wav", + 57 sound SOUND_FIRE "ModelsMP\\Enemies\\Grunt\\Sounds\\Fire.wav", + 58 sound SOUND_DEATH "ModelsMP\\Enemies\\Grunt\\Sounds\\Death.wav", + +functions: + + void CGruntSka(void) + { + // Get animation id's + idGrunt_Wound = ska_GetIDFromStringTable("Grunt_Wound"); + idGrunt_Run = ska_GetIDFromStringTable("Grunt_Run"); + idGrunt_IdlePatrol = ska_GetIDFromStringTable("Grunt_IdlePatrol"); + idGrunt_IdleAttack = ska_GetIDFromStringTable("Grunt_IdleAttack"); + idGrunt_Fire = ska_GetIDFromStringTable("Grunt_Fire"); + idGrunt_Default = ska_GetIDFromStringTable("Grunt_Default"); + idGrunt_DeathForward = ska_GetIDFromStringTable("Grunt_DeathForward"); + idGrunt_DeathBackward = ska_GetIDFromStringTable("Grunt_DeathBackward"); + idGrunt_GunModel = ska_GetIDFromStringTable("Flamer"); + + // Get colision box id's + idGrund_NormalBox = ska_GetIDFromStringTable("Normal"); + idGrund_DeathBox = ska_GetIDFromStringTable("Death"); + }; + + void CreateTestModelInstance() + { + try { + m_miTest.AddMesh_t((CTString)"ModelsSKA\\Test\\Arm\\Arm.bm"); + m_miTest.AddSkeleton_t((CTString)"ModelsSKA\\Test\\Arm\\Arm.bs"); + m_miTest.AddAnimSet_t((CTString)"ModelsSKA\\Test\\Arm\\Arm.ba"); + m_miTest.AddTexture_t((CTString)"ModelsSKA\\Test\\Arm\\Objects\\Arm.tex","Arm",NULL); + m_miTest.AddColisionBox("Default",FLOAT3D(-0.5f,0.0f,-0.5f),FLOAT3D(0.5f,2.0f,0.5f)); + } catch (char *strErr) { + FatalError(strErr); + } + } + + void BuildGruntModel() + { + // CreateTestModelInstance(); + + en_pmiModelInstance = CreateModelInstance("GruntSka"); + CModelInstance *pmi = GetModelInstance(); + try{ + // setup grunt solider + pmi->AddMesh_t((CTString)"ModelsSKA\\Enemies\\Grunt\\Grunt.bm"); + pmi->AddSkeleton_t((CTString)"ModelsSKA\\Enemies\\Grunt\\Grunt.bs"); + pmi->AddAnimSet_t((CTString)"ModelsSKA\\Enemies\\Grunt\\Grunt.ba"); + pmi->AddTexture_t((CTString)"ModelsSKA\\Enemies\\Grunt\\Soldier.tex","Grunt",NULL); + pmi->AddColisionBox("Default",FLOAT3D(-0.5f,0.0f,-0.5f),FLOAT3D(0.5f,2.0f,0.5f)); + + // setup weapon + CModelInstance *pmiFlamer = CreateModelInstance("Flamer"); + pmiFlamer->AddMesh_t((CTString)"ModelsSKA\\Weapons\\Flamer\\Flamer.bm"); + pmiFlamer->AddSkeleton_t((CTString)"ModelsSKA\\Weapons\\Flamer\\Flamer.bs"); + pmiFlamer->AddAnimSet_t((CTString)"ModelsSKA\\Weapons\\Flamer\\Flamer.ba"); + pmiFlamer->AddTexture_t((CTString)"ModelsSKA\\Weapons\\Flamer\\Flamer.tex","Flamer",NULL); + pmiFlamer->AddTexture_t((CTString)"ModelsSKA\\Enemies\\Grunt\\Lava04FX.tex","Lava04FX",NULL); + // Set flamer offset + pmiFlamer->SetOffsetRot(ANGLE3D(0,0,180)); + // Attach flamer to grunt + pmi->AddChild(pmiFlamer); + + // Set flamer parent bone + INDEX iParenBoneID = ska_GetIDFromStringTable("R_Hand"); + pmiFlamer->SetParentBone(iParenBoneID); + + // Set colision info + SetSkaColisionInfo(); + } catch(char *strErr) { + FatalError(strErr); + } + }; + + void BuildCommanderModel(CEntity *penGrunt) + { + SetSkaModel("ModelsSKA\\Enemies\\Grunt\\CommanderNoGun.smc"); + CModelInstance *pmiFlamer = NULL; + try{ + pmiFlamer = ParseSmcFile_t("ModelsSKA\\Weapons\\Flamer\\Flamer.smc"); + } catch(char *strErr) { + FatalError(strErr); + } + // Set flamer parent bone + INDEX iParenBoneID = ska_GetIDFromStringTable("R_Hand"); + CModelInstance *pmi = GetModelInstance(); + pmi->AddChild(pmiFlamer); + pmiFlamer->SetParentBone(iParenBoneID); + // Set flamer offset + pmiFlamer->SetOffsetRot(ANGLE3D(0,0,180)); + // Set colision info + SetSkaColisionInfo(); + }; +/* + void Particles_OneParticle( FLOAT3D vPos ) + { + Particle_PrepareTexture(&_toStar01, PBT_ADDALPHA); + Particle_SetTexturePart( 512, 512, 0, 0); + + COLOR col = RGBAToColor(128, 128, 128, 128); + Particle_RenderSquare( vPos, 1.0f, 0.0f, col); + Particle_Flush(); + } + + void RenderParticles(void) { + INDEX iBoneID = ska_GetIDFromStringTable("R_Hand"); + FLOAT3D vStartPoint; + FLOAT3D vEndPoint; + if(GetBoneAbsPosition(iBoneID,vStartPoint,vEndPoint)) { + Particles_OneParticle(vStartPoint); + } + }; + */ + /* + void AdjustBones() + { + INDEX iBoneID = ska_GetIDFromStringTable("MidTorso"); + RenBone *rb = RM_FindRenBone(iBoneID); + if(rb!=NULL) { + FLOATquat3D quat; + quat.FromEuler(ANGLE3D(0,0,AngleRad(Sin(m_fMidBoneRot)/3.0f))); + rb->rb_arRot.ar_qRot = quat; + } + m_fMidBoneRot+=1; + }; +*/ + /* + void AdjustBones() + { + INDEX ctrb = 0; + RenBone *pRenBones=RM_GetRenBoneArray(ctrb); + // for each t ren bones after first dummy one + for(INDEX irb=1;irbGetShaderDesc(sdDesc); + if(sdDesc.sd_astrTextureNames.Count() > SHP_BASE_TEXTURE) { + spParams.sp_aiTextureIDs[SHP_BASE_TEXTURE] = ska_GetIDFromStringTable("Lava04FX"); + } + } + } + } + */ +/* + CModelInstance *GetModelInstanceForRendering() + { + return &m_miTest; + }; +*/ + + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("A Grunt sent %s into the halls of Valhalla"), strPlayerName); + return str; + } + + /* Entity info */ + void *GetEntityInfo(void) { + if (m_gtType==GT_SOLDIER) { + return &eiGruntSoldier; + } else if (m_gtType==GT_COMMANDER) { + return &eiGruntSoldier; + } else { + ASSERT("Unknown grunt type!"); + return NULL; + } + }; + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnmSoldier, "DataMP\\Messages\\Enemies\\GruntSoldier.txt"); + static DECLARE_CTFILENAME(fnmCommander, "DataMP\\Messages\\Enemies\\GruntCommander.txt"); + switch(m_gtType) { + default: ASSERT(FALSE); + case GT_SOLDIER: return fnmSoldier; + case GT_COMMANDER: return fnmCommander; + } + }; + + void Precache(void) { + CEnemyBase::Precache(); + + if (m_gtType==GT_SOLDIER) { + PrecacheClass(CLASS_PROJECTILE, PRT_GRUNT_PROJECTILE_SOL); + } + if (m_gtType==GT_COMMANDER) { + PrecacheClass(CLASS_PROJECTILE, PRT_GRUNT_PROJECTILE_COM); + } + + PrecacheSound(SOUND_IDLE); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_FIRE); + PrecacheSound(SOUND_DEATH); + }; + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + }; + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + GetModelInstance()->AddAnimation(idGrunt_Wound,AN_CLEAR,1,0); + return idGrunt_Wound; + }; + + // death + INDEX AnimForDeath(void) { + INDEX idAnimDeath; + FLOAT3D vFront; + GetHeadingDirection(0, vFront); + FLOAT fDamageDir = m_vDamage%vFront; + if (fDamageDir<0) { + idAnimDeath = idGrunt_DeathBackward; + } else { + idAnimDeath = idGrunt_DeathForward; + } + + GetModelInstance()->AddAnimation(idAnimDeath,AN_CLEAR,1,0); + + return idAnimDeath; + }; + + FLOAT WaitForDust(FLOAT3D &vStretch) { + + vStretch=FLOAT3D(1,1,2); + if(GetModelInstance()->IsAnimationPlaying(idGrunt_DeathBackward)) { + return 0.5f; + } else if(GetModelInstance()->IsAnimationPlaying(idGrunt_DeathForward)) { + return 1.0f; + } + return -1.0f; + }; + + void DeathNotify(void) { + INDEX iBoxIndex = GetModelInstance()->GetColisionBoxIndex(idGrund_DeathBox); + ASSERT(iBoxIndex>=0); + ChangeCollisionBoxIndexWhenPossible(iBoxIndex); + en_fDensity = 500.0f; + }; + + // virtual anim functions + void StandingAnim(void) { + GetModelInstance()->AddAnimation(idGrunt_IdleAttack,AN_LOOPING|AN_NORESTART|AN_CLEAR,1,0); + }; + /*void StandingAnimFight(void) + { + StartModelAnim(HEADMAN_ANIM_IDLE_FIGHT, AOF_LOOPING|AOF_NORESTART); + }*/ + void RunningAnim(void) { + GetModelInstance()->AddAnimation(idGrunt_Run,AN_LOOPING|AN_NORESTART|AN_CLEAR,1,0); + }; + void WalkingAnim(void) { + RunningAnim(); + }; + void RotatingAnim(void) { + RunningAnim(); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + // set sound default parameters + m_soFire1.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + m_soFire2.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + }; + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + Fire(EVoid) : CEnemyBase::Fire { + // soldier + if (m_gtType == GT_SOLDIER) { + autocall SoldierAttack() EEnd; + // commander + } else if (m_gtType == GT_COMMANDER) { + autocall CommanderAttack() EEnd; + // should never get here + } else{ + ASSERT(FALSE); + } + return EReturn(); + }; + + // Soldier attack + SoldierAttack(EVoid) { + + StandingAnimFight(); + autowait(0.2f + FRnd()*0.25f); + + GetModelInstance()->AddAnimation(idGrunt_Fire,AN_CLEAR,1.0f,0); + + ShootProjectile(PRT_GRUNT_PROJECTILE_SOL, FIREPOS_SOLDIER, ANGLE3D(0, 0, 0)); + PlaySound(m_soFire1, SOUND_FIRE, SOF_3D); + + autowait(0.15f + FRnd()*0.1f); + GetModelInstance()->AddAnimation(idGrunt_Fire,AN_CLEAR,1.0f,0); + ShootProjectile(PRT_GRUNT_PROJECTILE_SOL, FIREPOS_SOLDIER, ANGLE3D(0, 0, 0)); + PlaySound(m_soFire2, SOUND_FIRE, SOF_3D); + + + autowait(FRnd()*0.333f); + return EEnd(); + }; + + // Commander attack (predicted firing on moving player) + CommanderAttack(EVoid) { + StandingAnimFight(); + autowait(0.2f + FRnd()*0.25f); + + /*FLOAT3D vGunPosAbs = GetPlacement().pl_PositionVector + FLOAT3D(0.0f, 1.0f, 0.0f)*GetRotationMatrix(); + FLOAT3D vEnemySpeed = ((CMovableEntity&) *m_penEnemy).en_vCurrentTranslationAbsolute; + FLOAT3D vEnemyPos = ((CMovableEntity&) *m_penEnemy).GetPlacement().pl_PositionVector; + FLOAT fLaserSpeed = 45.0f; // m/s + FLOAT3D vPredictedEnemyPosition = CalculatePredictedPosition(vGunPosAbs, + vEnemyPos, fLaserSpeed, vEnemySpeed, GetPlacement().pl_PositionVector(2) ); + ShootPredictedProjectile(PRT_GRUNT_LASER, vPredictedEnemyPosition, FLOAT3D(0.0f, 1.0f, 0.0f), ANGLE3D(0, 0, 0));*/ + + GetModelInstance()->AddAnimation(idGrunt_Fire,AN_CLEAR,1,0); + ShootProjectile(PRT_GRUNT_PROJECTILE_COM, FIREPOS_COMMANDER_DN, ANGLE3D(-20, 0, 0)); + PlaySound(m_soFire1, SOUND_FIRE, SOF_3D); + + autowait(0.035f); + GetModelInstance()->AddAnimation(idGrunt_Fire,AN_CLEAR,1,0); + ShootProjectile(PRT_GRUNT_PROJECTILE_COM, FIREPOS_COMMANDER_DN, ANGLE3D(-10, 0, 0)); + PlaySound(m_soFire2, SOUND_FIRE, SOF_3D); + + autowait(0.035f); + GetModelInstance()->AddAnimation(idGrunt_Fire,AN_CLEAR,1,0); + ShootProjectile(PRT_GRUNT_PROJECTILE_COM, FIREPOS_COMMANDER_DN, ANGLE3D(0, 0, 0)); + PlaySound(m_soFire1, SOUND_FIRE, SOF_3D); + + autowait(0.035f); + GetModelInstance()->AddAnimation(idGrunt_Fire,AN_CLEAR,1,0); + ShootProjectile(PRT_GRUNT_PROJECTILE_COM, FIREPOS_COMMANDER_DN, ANGLE3D(10, 0, 0)); + PlaySound(m_soFire2, SOUND_FIRE, SOF_3D); + + autowait(0.035f); + GetModelInstance()->AddAnimation(idGrunt_Fire,AN_CLEAR,1,0); + ShootProjectile(PRT_GRUNT_PROJECTILE_COM, FIREPOS_COMMANDER_DN, ANGLE3D(20, 0, 0)); + PlaySound(m_soFire2, SOUND_FIRE, SOF_3D); + + autowait(FRnd()*0.5f); + return EEnd(); + }; + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsSkaModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + en_tmMaxHoldBreath = 5.0f; + en_fDensity = 2000.0f; + //m_fBlowUpSize = 2.0f; + + //_toStar01.SetData_t(CTFILENAME("Models\\Items\\Particles\\Star01.tex")); + + + // set your appearance + switch (m_gtType) { + case GT_SOLDIER: + SetSkaModel(SOLIDER_SMC_MODEL); + // BuildGruntModel(); + + // setup moving speed + m_fWalkSpeed = FRnd() + 2.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f); + m_fAttackRunSpeed = FRnd() + 6.5f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + m_fCloseRunSpeed = FRnd() + 6.5f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + // setup attack distances + m_fAttackDistance = 80.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 8.0f; + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 200.0f; + //m_fBlowUpAmount = 65.0f; + m_fBlowUpAmount = 80.0f; + m_fBodyParts = 4; + m_fDamageWounded = 0.0f; + m_iScore = 500; + SetHealth(40.0f); + m_fMaxHealth = 40.0f; + // set stretch factors for height and width + GetModelInstance()->StretchModel(FLOAT3D(STRETCH_SOLDIER, STRETCH_SOLDIER, STRETCH_SOLDIER)); + break; + + case GT_COMMANDER: + + SetSkaModel(COMANDER_SMC_MODEL); + // BuildCommanderModel(); + + m_fWalkSpeed = FRnd() + 2.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f); + m_fAttackRunSpeed = FRnd() + 8.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + m_fCloseRunSpeed = FRnd() + 8.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + // setup attack distances + m_fAttackDistance = 90.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 15.0f; + m_fAttackFireTime = 4.0f; + m_fCloseFireTime = 2.0f; + //m_fBlowUpAmount = 180.0f; + m_fIgnoreRange = 200.0f; + // damage/explode properties + m_fBodyParts = 5; + m_fDamageWounded = 0.0f; + m_iScore = 800; + SetHealth(60.0f); + m_fMaxHealth = 60.0f; + // set stretch factors for height and width + GetModelInstance()->StretchModel(FLOAT3D(STRETCH_COMMANDER, STRETCH_COMMANDER, STRETCH_COMMANDER)); + break; + } + + ModelChangeNotify(); + StandingAnim(); + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/GruntSka.h b/Sources/EntitiesMP/GruntSka.h new file mode 100644 index 0000000..98c6e85 --- /dev/null +++ b/Sources/EntitiesMP/GruntSka.h @@ -0,0 +1,133 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_GruntSka_INCLUDED +#define _EntitiesMP_GruntSka_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType GruntSkaType_enum; +enum GruntSkaType { + GT_SOLDIER = 0, + GT_COMMANDER = 1, +}; +DECL_DLL inline void ClearToDefault(GruntSkaType &e) { e = (GruntSkaType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CGruntSka_DLLClass; +class CGruntSka : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum GruntSkaType m_gtType; + CSoundObject m_soFire1; + CSoundObject m_soFire2; + FLOAT m_fMidBoneRot; + CModelInstance m_miTest; + CGruntSka(void); + +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void CreateTestModelInstance(); + +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void BuildGruntModel(); + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void BuildCommanderModel(CEntity * penGrunt); + +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void * GetEntityInfo(void); + +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void Precache(void); + +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +INDEX AnimForDeath(void); + +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void DeathNotify(void); + +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void StandingAnim(void); + +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void RunningAnim(void); + +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void WalkingAnim(void); + +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void RotatingAnim(void); + +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void IdleSound(void); + +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void SightSound(void); + +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void WoundSound(void); + +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void DeathSound(void); + +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +void EnemyPostInit(void); +#define STATE_CGruntSka_Fire 0x01570000 + BOOL +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x01570001_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x01570002_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x01570003_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x01570004_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x01570005_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x01570006_Fire_06(const CEntityEvent &__eeInput); + BOOL H0x01570007_Fire_07(const CEntityEvent &__eeInput); + BOOL H0x01570008_Fire_08(const CEntityEvent &__eeInput); +#define STATE_CGruntSka_SoldierAttack 0x01570009 + BOOL +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SoldierAttack(const CEntityEvent &__eeInput); + BOOL H0x0157000a_SoldierAttack_01(const CEntityEvent &__eeInput); + BOOL H0x0157000b_SoldierAttack_02(const CEntityEvent &__eeInput); + BOOL H0x0157000c_SoldierAttack_03(const CEntityEvent &__eeInput); + BOOL H0x0157000d_SoldierAttack_04(const CEntityEvent &__eeInput); + BOOL H0x0157000e_SoldierAttack_05(const CEntityEvent &__eeInput); + BOOL H0x0157000f_SoldierAttack_06(const CEntityEvent &__eeInput); +#define STATE_CGruntSka_CommanderAttack 0x01570010 + BOOL +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +CommanderAttack(const CEntityEvent &__eeInput); + BOOL H0x01570011_CommanderAttack_01(const CEntityEvent &__eeInput); + BOOL H0x01570012_CommanderAttack_02(const CEntityEvent &__eeInput); + BOOL H0x01570013_CommanderAttack_03(const CEntityEvent &__eeInput); + BOOL H0x01570014_CommanderAttack_04(const CEntityEvent &__eeInput); + BOOL H0x01570015_CommanderAttack_05(const CEntityEvent &__eeInput); + BOOL H0x01570016_CommanderAttack_06(const CEntityEvent &__eeInput); + BOOL H0x01570017_CommanderAttack_07(const CEntityEvent &__eeInput); + BOOL H0x01570018_CommanderAttack_08(const CEntityEvent &__eeInput); + BOOL H0x01570019_CommanderAttack_09(const CEntityEvent &__eeInput); + BOOL H0x0157001a_CommanderAttack_10(const CEntityEvent &__eeInput); + BOOL H0x0157001b_CommanderAttack_11(const CEntityEvent &__eeInput); + BOOL H0x0157001c_CommanderAttack_12(const CEntityEvent &__eeInput); +#define STATE_CGruntSka_Main 1 + BOOL +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_GruntSka_INCLUDED diff --git a/Sources/EntitiesMP/GruntSka_tables.h b/Sources/EntitiesMP/GruntSka_tables.h new file mode 100644 index 0000000..788d01e --- /dev/null +++ b/Sources/EntitiesMP/GruntSka_tables.h @@ -0,0 +1,90 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(GruntSkaType) + EP_ENUMVALUE(GT_SOLDIER, "Grunt soldier"), + EP_ENUMVALUE(GT_COMMANDER, "Grunt commander"), +EP_ENUMEND(GruntSkaType); + +#define ENTITYCLASS CGruntSka + +CEntityProperty CGruntSka_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &GruntSkaType_enum, (0x00000157<<8)+1, offsetof(CGruntSka, m_gtType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000157<<8)+10, offsetof(CGruntSka, m_soFire1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000157<<8)+11, offsetof(CGruntSka, m_soFire2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000157<<8)+20, offsetof(CGruntSka, m_fMidBoneRot), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_MODELINSTANCE, NULL, (0x00000157<<8)+30, offsetof(CGruntSka, m_miTest), "", 0, 0, 0), +}; +#define CGruntSka_propertiesct ARRAYCOUNT(CGruntSka_properties) + +CEntityComponent CGruntSka_components[] = { +#define CLASS_BASE ((0x00000157<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_PROJECTILE ((0x00000157<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define SOUND_IDLE ((0x00000157<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "ModelsMP\\Enemies\\Grunt\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000157<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "ModelsMP\\Enemies\\Grunt\\Sounds\\Sight.wav"), +#define SOUND_WOUND ((0x00000157<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "ModelsMP\\Enemies\\Grunt\\Sounds\\Wound.wav"), +#define SOUND_FIRE ((0x00000157<<8)+57) + CEntityComponent(ECT_SOUND, SOUND_FIRE, "EFNM" "ModelsMP\\Enemies\\Grunt\\Sounds\\Fire.wav"), +#define SOUND_DEATH ((0x00000157<<8)+58) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "ModelsMP\\Enemies\\Grunt\\Sounds\\Death.wav"), +}; +#define CGruntSka_componentsct ARRAYCOUNT(CGruntSka_components) + +CEventHandlerEntry CGruntSka_handlers[] = { + {0x01570000, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CGruntSka:: +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +Fire),DEBUGSTRING("CGruntSka::Fire")}, + {0x01570001, -1, CEntity::pEventHandler(&CGruntSka::H0x01570001_Fire_01), DEBUGSTRING("CGruntSka::H0x01570001_Fire_01")}, + {0x01570002, -1, CEntity::pEventHandler(&CGruntSka::H0x01570002_Fire_02), DEBUGSTRING("CGruntSka::H0x01570002_Fire_02")}, + {0x01570003, -1, CEntity::pEventHandler(&CGruntSka::H0x01570003_Fire_03), DEBUGSTRING("CGruntSka::H0x01570003_Fire_03")}, + {0x01570004, -1, CEntity::pEventHandler(&CGruntSka::H0x01570004_Fire_04), DEBUGSTRING("CGruntSka::H0x01570004_Fire_04")}, + {0x01570005, -1, CEntity::pEventHandler(&CGruntSka::H0x01570005_Fire_05), DEBUGSTRING("CGruntSka::H0x01570005_Fire_05")}, + {0x01570006, -1, CEntity::pEventHandler(&CGruntSka::H0x01570006_Fire_06), DEBUGSTRING("CGruntSka::H0x01570006_Fire_06")}, + {0x01570007, -1, CEntity::pEventHandler(&CGruntSka::H0x01570007_Fire_07), DEBUGSTRING("CGruntSka::H0x01570007_Fire_07")}, + {0x01570008, -1, CEntity::pEventHandler(&CGruntSka::H0x01570008_Fire_08), DEBUGSTRING("CGruntSka::H0x01570008_Fire_08")}, + {0x01570009, -1, CEntity::pEventHandler(&CGruntSka:: +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +SoldierAttack),DEBUGSTRING("CGruntSka::SoldierAttack")}, + {0x0157000a, -1, CEntity::pEventHandler(&CGruntSka::H0x0157000a_SoldierAttack_01), DEBUGSTRING("CGruntSka::H0x0157000a_SoldierAttack_01")}, + {0x0157000b, -1, CEntity::pEventHandler(&CGruntSka::H0x0157000b_SoldierAttack_02), DEBUGSTRING("CGruntSka::H0x0157000b_SoldierAttack_02")}, + {0x0157000c, -1, CEntity::pEventHandler(&CGruntSka::H0x0157000c_SoldierAttack_03), DEBUGSTRING("CGruntSka::H0x0157000c_SoldierAttack_03")}, + {0x0157000d, -1, CEntity::pEventHandler(&CGruntSka::H0x0157000d_SoldierAttack_04), DEBUGSTRING("CGruntSka::H0x0157000d_SoldierAttack_04")}, + {0x0157000e, -1, CEntity::pEventHandler(&CGruntSka::H0x0157000e_SoldierAttack_05), DEBUGSTRING("CGruntSka::H0x0157000e_SoldierAttack_05")}, + {0x0157000f, -1, CEntity::pEventHandler(&CGruntSka::H0x0157000f_SoldierAttack_06), DEBUGSTRING("CGruntSka::H0x0157000f_SoldierAttack_06")}, + {0x01570010, -1, CEntity::pEventHandler(&CGruntSka:: +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +CommanderAttack),DEBUGSTRING("CGruntSka::CommanderAttack")}, + {0x01570011, -1, CEntity::pEventHandler(&CGruntSka::H0x01570011_CommanderAttack_01), DEBUGSTRING("CGruntSka::H0x01570011_CommanderAttack_01")}, + {0x01570012, -1, CEntity::pEventHandler(&CGruntSka::H0x01570012_CommanderAttack_02), DEBUGSTRING("CGruntSka::H0x01570012_CommanderAttack_02")}, + {0x01570013, -1, CEntity::pEventHandler(&CGruntSka::H0x01570013_CommanderAttack_03), DEBUGSTRING("CGruntSka::H0x01570013_CommanderAttack_03")}, + {0x01570014, -1, CEntity::pEventHandler(&CGruntSka::H0x01570014_CommanderAttack_04), DEBUGSTRING("CGruntSka::H0x01570014_CommanderAttack_04")}, + {0x01570015, -1, CEntity::pEventHandler(&CGruntSka::H0x01570015_CommanderAttack_05), DEBUGSTRING("CGruntSka::H0x01570015_CommanderAttack_05")}, + {0x01570016, -1, CEntity::pEventHandler(&CGruntSka::H0x01570016_CommanderAttack_06), DEBUGSTRING("CGruntSka::H0x01570016_CommanderAttack_06")}, + {0x01570017, -1, CEntity::pEventHandler(&CGruntSka::H0x01570017_CommanderAttack_07), DEBUGSTRING("CGruntSka::H0x01570017_CommanderAttack_07")}, + {0x01570018, -1, CEntity::pEventHandler(&CGruntSka::H0x01570018_CommanderAttack_08), DEBUGSTRING("CGruntSka::H0x01570018_CommanderAttack_08")}, + {0x01570019, -1, CEntity::pEventHandler(&CGruntSka::H0x01570019_CommanderAttack_09), DEBUGSTRING("CGruntSka::H0x01570019_CommanderAttack_09")}, + {0x0157001a, -1, CEntity::pEventHandler(&CGruntSka::H0x0157001a_CommanderAttack_10), DEBUGSTRING("CGruntSka::H0x0157001a_CommanderAttack_10")}, + {0x0157001b, -1, CEntity::pEventHandler(&CGruntSka::H0x0157001b_CommanderAttack_11), DEBUGSTRING("CGruntSka::H0x0157001b_CommanderAttack_11")}, + {0x0157001c, -1, CEntity::pEventHandler(&CGruntSka::H0x0157001c_CommanderAttack_12), DEBUGSTRING("CGruntSka::H0x0157001c_CommanderAttack_12")}, + {1, -1, CEntity::pEventHandler(&CGruntSka:: +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/GruntSka.es" +Main),DEBUGSTRING("CGruntSka::Main")}, +}; +#define CGruntSka_handlersct ARRAYCOUNT(CGruntSka_handlers) + +CEntity *CGruntSka_New(void) { return new CGruntSka; }; +void CGruntSka_OnInitClass(void) {}; +void CGruntSka_OnEndClass(void) {}; +void CGruntSka_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CGruntSka_OnWorldEnd(CWorld *pwo) {}; +void CGruntSka_OnWorldInit(CWorld *pwo) {}; +void CGruntSka_OnWorldTick(CWorld *pwo) {}; +void CGruntSka_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CGruntSka, CEnemyBase, "GruntSka", "Thumbnails\\Grunt.tbn", 0x00000157); +DECLARE_CTFILENAME(_fnmCGruntSka_tbn, "Thumbnails\\Grunt.tbn"); diff --git a/Sources/EntitiesMP/Grunt_tables.h b/Sources/EntitiesMP/Grunt_tables.h new file mode 100644 index 0000000..2cdd2e5 --- /dev/null +++ b/Sources/EntitiesMP/Grunt_tables.h @@ -0,0 +1,102 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(GruntType) + EP_ENUMVALUE(GT_SOLDIER, "Grunt soldier"), + EP_ENUMVALUE(GT_COMMANDER, "Grunt commander"), +EP_ENUMEND(GruntType); + +#define ENTITYCLASS CGrunt + +CEntityProperty CGrunt_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &GruntType_enum, (0x00000157<<8)+1, offsetof(CGrunt, m_gtType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000157<<8)+10, offsetof(CGrunt, m_soFire1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000157<<8)+11, offsetof(CGrunt, m_soFire2), "", 0, 0, 0), +}; +#define CGrunt_propertiesct ARRAYCOUNT(CGrunt_properties) + +CEntityComponent CGrunt_components[] = { +#define CLASS_BASE ((0x00000157<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_PROJECTILE ((0x00000157<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define MODEL_GRUNT ((0x00000157<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_GRUNT, "EFNM" "ModelsMP\\Enemies\\Grunt\\Grunt.mdl"), +#define MODEL_GUN_COMMANDER ((0x00000157<<8)+11) + CEntityComponent(ECT_MODEL, MODEL_GUN_COMMANDER, "EFNM" "ModelsMP\\Enemies\\Grunt\\Gun_Commander.mdl"), +#define MODEL_GUN_SOLDIER ((0x00000157<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_GUN_SOLDIER, "EFNM" "ModelsMP\\Enemies\\Grunt\\Gun.mdl"), +#define TEXTURE_SOLDIER ((0x00000157<<8)+20) + CEntityComponent(ECT_TEXTURE, TEXTURE_SOLDIER, "EFNM" "ModelsMP\\Enemies\\Grunt\\Soldier.tex"), +#define TEXTURE_COMMANDER ((0x00000157<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_COMMANDER, "EFNM" "ModelsMP\\Enemies\\Grunt\\Commander.tex"), +#define TEXTURE_GUN_COMMANDER ((0x00000157<<8)+22) + CEntityComponent(ECT_TEXTURE, TEXTURE_GUN_COMMANDER, "EFNM" "ModelsMP\\Enemies\\Grunt\\Gun_Commander.tex"), +#define TEXTURE_GUN_SOLDIER ((0x00000157<<8)+23) + CEntityComponent(ECT_TEXTURE, TEXTURE_GUN_SOLDIER, "EFNM" "ModelsMP\\Enemies\\Grunt\\Gun.tex"), +#define SOUND_IDLE ((0x00000157<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "ModelsMP\\Enemies\\Grunt\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000157<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "ModelsMP\\Enemies\\Grunt\\Sounds\\Sight.wav"), +#define SOUND_WOUND ((0x00000157<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "ModelsMP\\Enemies\\Grunt\\Sounds\\Wound.wav"), +#define SOUND_FIRE ((0x00000157<<8)+57) + CEntityComponent(ECT_SOUND, SOUND_FIRE, "EFNM" "ModelsMP\\Enemies\\Grunt\\Sounds\\Fire.wav"), +#define SOUND_DEATH ((0x00000157<<8)+58) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "ModelsMP\\Enemies\\Grunt\\Sounds\\Death.wav"), +}; +#define CGrunt_componentsct ARRAYCOUNT(CGrunt_components) + +CEventHandlerEntry CGrunt_handlers[] = { + {0x01570000, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CGrunt:: +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +Fire),DEBUGSTRING("CGrunt::Fire")}, + {0x01570001, -1, CEntity::pEventHandler(&CGrunt::H0x01570001_Fire_01), DEBUGSTRING("CGrunt::H0x01570001_Fire_01")}, + {0x01570002, -1, CEntity::pEventHandler(&CGrunt::H0x01570002_Fire_02), DEBUGSTRING("CGrunt::H0x01570002_Fire_02")}, + {0x01570003, -1, CEntity::pEventHandler(&CGrunt::H0x01570003_Fire_03), DEBUGSTRING("CGrunt::H0x01570003_Fire_03")}, + {0x01570004, -1, CEntity::pEventHandler(&CGrunt::H0x01570004_Fire_04), DEBUGSTRING("CGrunt::H0x01570004_Fire_04")}, + {0x01570005, -1, CEntity::pEventHandler(&CGrunt::H0x01570005_Fire_05), DEBUGSTRING("CGrunt::H0x01570005_Fire_05")}, + {0x01570006, -1, CEntity::pEventHandler(&CGrunt::H0x01570006_Fire_06), DEBUGSTRING("CGrunt::H0x01570006_Fire_06")}, + {0x01570007, -1, CEntity::pEventHandler(&CGrunt::H0x01570007_Fire_07), DEBUGSTRING("CGrunt::H0x01570007_Fire_07")}, + {0x01570008, -1, CEntity::pEventHandler(&CGrunt::H0x01570008_Fire_08), DEBUGSTRING("CGrunt::H0x01570008_Fire_08")}, + {0x01570009, -1, CEntity::pEventHandler(&CGrunt:: +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +SoldierAttack),DEBUGSTRING("CGrunt::SoldierAttack")}, + {0x0157000a, -1, CEntity::pEventHandler(&CGrunt::H0x0157000a_SoldierAttack_01), DEBUGSTRING("CGrunt::H0x0157000a_SoldierAttack_01")}, + {0x0157000b, -1, CEntity::pEventHandler(&CGrunt::H0x0157000b_SoldierAttack_02), DEBUGSTRING("CGrunt::H0x0157000b_SoldierAttack_02")}, + {0x0157000c, -1, CEntity::pEventHandler(&CGrunt::H0x0157000c_SoldierAttack_03), DEBUGSTRING("CGrunt::H0x0157000c_SoldierAttack_03")}, + {0x0157000d, -1, CEntity::pEventHandler(&CGrunt::H0x0157000d_SoldierAttack_04), DEBUGSTRING("CGrunt::H0x0157000d_SoldierAttack_04")}, + {0x0157000e, -1, CEntity::pEventHandler(&CGrunt::H0x0157000e_SoldierAttack_05), DEBUGSTRING("CGrunt::H0x0157000e_SoldierAttack_05")}, + {0x0157000f, -1, CEntity::pEventHandler(&CGrunt::H0x0157000f_SoldierAttack_06), DEBUGSTRING("CGrunt::H0x0157000f_SoldierAttack_06")}, + {0x01570010, -1, CEntity::pEventHandler(&CGrunt:: +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +CommanderAttack),DEBUGSTRING("CGrunt::CommanderAttack")}, + {0x01570011, -1, CEntity::pEventHandler(&CGrunt::H0x01570011_CommanderAttack_01), DEBUGSTRING("CGrunt::H0x01570011_CommanderAttack_01")}, + {0x01570012, -1, CEntity::pEventHandler(&CGrunt::H0x01570012_CommanderAttack_02), DEBUGSTRING("CGrunt::H0x01570012_CommanderAttack_02")}, + {0x01570013, -1, CEntity::pEventHandler(&CGrunt::H0x01570013_CommanderAttack_03), DEBUGSTRING("CGrunt::H0x01570013_CommanderAttack_03")}, + {0x01570014, -1, CEntity::pEventHandler(&CGrunt::H0x01570014_CommanderAttack_04), DEBUGSTRING("CGrunt::H0x01570014_CommanderAttack_04")}, + {0x01570015, -1, CEntity::pEventHandler(&CGrunt::H0x01570015_CommanderAttack_05), DEBUGSTRING("CGrunt::H0x01570015_CommanderAttack_05")}, + {0x01570016, -1, CEntity::pEventHandler(&CGrunt::H0x01570016_CommanderAttack_06), DEBUGSTRING("CGrunt::H0x01570016_CommanderAttack_06")}, + {0x01570017, -1, CEntity::pEventHandler(&CGrunt::H0x01570017_CommanderAttack_07), DEBUGSTRING("CGrunt::H0x01570017_CommanderAttack_07")}, + {0x01570018, -1, CEntity::pEventHandler(&CGrunt::H0x01570018_CommanderAttack_08), DEBUGSTRING("CGrunt::H0x01570018_CommanderAttack_08")}, + {0x01570019, -1, CEntity::pEventHandler(&CGrunt::H0x01570019_CommanderAttack_09), DEBUGSTRING("CGrunt::H0x01570019_CommanderAttack_09")}, + {0x0157001a, -1, CEntity::pEventHandler(&CGrunt::H0x0157001a_CommanderAttack_10), DEBUGSTRING("CGrunt::H0x0157001a_CommanderAttack_10")}, + {0x0157001b, -1, CEntity::pEventHandler(&CGrunt::H0x0157001b_CommanderAttack_11), DEBUGSTRING("CGrunt::H0x0157001b_CommanderAttack_11")}, + {0x0157001c, -1, CEntity::pEventHandler(&CGrunt::H0x0157001c_CommanderAttack_12), DEBUGSTRING("CGrunt::H0x0157001c_CommanderAttack_12")}, + {1, -1, CEntity::pEventHandler(&CGrunt:: +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Grunt.es" +Main),DEBUGSTRING("CGrunt::Main")}, +}; +#define CGrunt_handlersct ARRAYCOUNT(CGrunt_handlers) + +CEntity *CGrunt_New(void) { return new CGrunt; }; +void CGrunt_OnInitClass(void) {}; +void CGrunt_OnEndClass(void) {}; +void CGrunt_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CGrunt_OnWorldEnd(CWorld *pwo) {}; +void CGrunt_OnWorldInit(CWorld *pwo) {}; +void CGrunt_OnWorldTick(CWorld *pwo) {}; +void CGrunt_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CGrunt, CEnemyBase, "Grunt", "Thumbnails\\Grunt.tbn", 0x00000157); +DECLARE_CTFILENAME(_fnmCGrunt_tbn, "Thumbnails\\Grunt.tbn"); diff --git a/Sources/EntitiesMP/Guffy.cpp b/Sources/EntitiesMP/Guffy.cpp new file mode 100644 index 0000000..d7b4e0e --- /dev/null +++ b/Sources/EntitiesMP/Guffy.cpp @@ -0,0 +1,422 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/Guffy/Guffy.h" + +#include +#include +#line 13 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" + +// info structure +static EntityInfo eiGuffy = { + EIBT_FLESH, 800.0f, + 0.0f, 1.9f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +#define FIRE_LEFT_ARM FLOAT3D(-0.56f, +1.125f, -1.32f) +#define FIRE_RIGHT_ARM FLOAT3D(+0.50f, +1.060f, -0.82f) + +//#define FIRE_DEATH_LEFT FLOAT3D( 0.0f, 7.0f, -2.0f) +//#define FIRE_DEATH_RIGHT FLOAT3D(3.75f, 4.2f, -2.5f) + + +void CGuffy::SetDefaultProperties(void) { + m_iLoopCounter = 0; + m_fSize = 1.0f; + m_bWalkSoundPlaying = FALSE ; + m_fThreatDistance = 5.0f; + m_bEnemyToTheLeft = FALSE ; + m_soFire1.SetOwner(this); +m_soFire1.Stop_internal(); + m_soFire2.SetOwner(this); +m_soFire2.Stop_internal(); + CEnemyBase::SetDefaultProperties(); +} + CTString CGuffy::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +{ +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +CTString str ; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +str . PrintF (TRANS ("Guffy gunned %s down") , strPlayerName ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +return str ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + const CTFileName & CGuffy::GetComputerMessageName(void)const { +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +static DECLARE_CTFILENAME (fnmSoldier , "DataMP\\Messages\\Enemies\\Guffy.txt"); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +return fnmSoldier ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::Precache(void) { +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +CEnemyBase :: Precache (); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PrecacheModel (MODEL_GUFFY ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PrecacheTexture (TEXTURE_GUFFY ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PrecacheModel (MODEL_GUN ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PrecacheTexture (TEXTURE_GUN ); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PrecacheSound (SOUND_IDLE ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PrecacheSound (SOUND_SIGHT ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PrecacheSound (SOUND_DEATH ); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PrecacheSound (SOUND_FIRE ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PrecacheSound (SOUND_WOUND ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PrecacheClass (CLASS_PROJECTILE , PRT_GUFFY_PROJECTILE ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void * CGuffy::GetEntityInfo(void) { +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +return & eiGuffy ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +{ +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +if(! IsOfClass (penInflictor , "Guffy")){ +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::StandingAnim(void) { +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +StartModelAnim (GUFFY_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::RunningAnim(void) { +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +StartModelAnim (GUFFY_ANIM_RUN , AOF_LOOPING | AOF_NORESTART ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::WalkingAnim(void) { +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +RunningAnim (); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::RotatingAnim(void) { +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +StartModelAnim (GUFFY_ANIM_RUN , AOF_LOOPING | AOF_NORESTART ); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::IdleSound(void) { +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::SightSound(void) { +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::WoundSound(void) { +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::DeathSound(void) { +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::FireRocket(FLOAT3D & vPos) { +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +CPlacement3D plRocket ; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +plRocket . pl_PositionVector = vPos ; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +plRocket . pl_OrientationAngle = ANGLE3D (0 , - 5.0f - FRnd () * 10.0f , 0); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +plRocket . RelativeToAbsolute (GetPlacement ()); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +CEntityPointer penProjectile = CreateEntity (plRocket , CLASS_PROJECTILE ); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +ELaunchProjectile eLaunch ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +eLaunch . penLauncher = this ; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +eLaunch . prtType = PRT_GUFFY_PROJECTILE ; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +penProjectile -> Initialize (eLaunch ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void CGuffy::EnemyPostInit(void) +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +{ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_soSound . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_soFire1 . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_soFire2 . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +INDEX CGuffy::AnimForDamage(FLOAT fDamage) { +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +INDEX iAnim ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +iAnim = GUFFY_ANIM_WOUND ; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +StartModelAnim (iAnim , 0); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +return iAnim ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +INDEX CGuffy::AnimForDeath(void) { +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +INDEX iAnim ; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +FLOAT3D vFront ; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +GetHeadingDirection (0 , vFront ); +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +FLOAT fDamageDir = m_vDamage % vFront ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +if(fDamageDir < 0){ +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +iAnim = GUFFY_ANIM_DEATHBACKWARD ; +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +}else { +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +iAnim = GUFFY_ANIM_DEATHFORWARD ; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +StartModelAnim (iAnim , 0); +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +return iAnim ; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} + +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +FLOAT CGuffy::WaitForDust(FLOAT3D & vStretch) { +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +vStretch = FLOAT3D (1 , 1 , 2) * 1.5f; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +if(GetModelObject () -> GetAnim () == GUFFY_ANIM_DEATHBACKWARD ) +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +{ +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +return 0.48f; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +else if(GetModelObject () -> GetAnim () == GUFFY_ANIM_DEATHFORWARD ) +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +{ +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +return 1.0f; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +return - 1.0f; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} +BOOL CGuffy:: +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGuffy_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGuffy::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +StartModelAnim (GUFFY_ANIM_FIRE , AOF_LOOPING ); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x01580001, FALSE, EBegin());return TRUE;}BOOL CGuffy::H0x01580001_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01580001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01580002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGuffy::H0x01580002_Fire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01580002 +; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +FLOATmatrix3D m ; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +FLOAT3D fLookRight = FLOAT3D (1.0f , 0.0f , 0.0f); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +MakeRotationMatrixFast (m , GetPlacement () . pl_OrientationAngle ); +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +fLookRight = fLookRight * m ; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +BOOL bEnemyRight = fLookRight % (m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +if(bEnemyRight >= 0){ +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +ShootProjectile (PRT_GUFFY_PROJECTILE , FIRE_LEFT_ARM * m_fSize , ANGLE3D (0 , 0 , 0)); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PlaySound (m_soFire1 , SOUND_FIRE , SOF_3D ); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +ShootProjectile (PRT_GUFFY_PROJECTILE , FIRE_RIGHT_ARM * m_fSize , ANGLE3D (- 9 , 0 , 0)); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PlaySound (m_soFire2 , SOUND_FIRE , SOF_3D ); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +}else { +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +ShootProjectile (PRT_GUFFY_PROJECTILE , FIRE_LEFT_ARM * m_fSize , ANGLE3D (9 , 0 , 0)); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PlaySound (m_soFire1 , SOUND_FIRE , SOF_3D ); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +ShootProjectile (PRT_GUFFY_PROJECTILE , FIRE_RIGHT_ARM * m_fSize , ANGLE3D (0 , 0 , 0)); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +PlaySound (m_soFire2 , SOUND_FIRE , SOF_3D ); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +SetTimerAfter(1.0f); +Jump(STATE_CURRENT, 0x01580003, FALSE, EBegin());return TRUE;}BOOL CGuffy::H0x01580003_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01580003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01580004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGuffy::H0x01580004_Fire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01580004 +; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +StopMoving (); +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +MaybeSwitchToAnotherPlayer (); +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +StandingAnimFight (); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +SetTimerAfter(FRnd () * 0.25f + 0.25f); +Jump(STATE_CURRENT, 0x01580005, FALSE, EBegin());return TRUE;}BOOL CGuffy::H0x01580005_Fire_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01580005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01580006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CGuffy::H0x01580006_Fire_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01580006 +; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +Return(STATE_CURRENT,EReturn ()); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CGuffy:: +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CGuffy_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CGuffy::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +InitAsModel (); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +SetCollisionFlags (ECF_MODEL ); +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +SetHealth (210.0f); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fMaxHealth = 210.0f; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +en_fDensity = 2000.0f; +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +SetModel (MODEL_GUFFY ); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fSize = 1.5f; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +SetModelMainTexture (TEXTURE_GUFFY ); +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +AddAttachment (GUFFY_ATTACHMENT_GUNRIGHT , MODEL_GUN , TEXTURE_GUN ); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +AddAttachment (GUFFY_ATTACHMENT_GUNLEFT , MODEL_GUN , TEXTURE_GUN ); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fSize , m_fSize , m_fSize )); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +ModelChangeNotify (); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +CModelObject * pmoRight = & GetModelObject () -> GetAttachmentModel (GUFFY_ATTACHMENT_GUNRIGHT ) -> amo_moModelObject ; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +pmoRight -> StretchModel (FLOAT3D (- 1 , 1 , 1)); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fBlowUpAmount = 10000.0f; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_iScore = 3000; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +if(m_fStepHeight == - 1){ +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fStepHeight = 4.0f; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +} +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +StandingAnim (); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fWalkSpeed = FRnd () + 2.5f; +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 500.0f); +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fAttackRunSpeed = FRnd () + 5.0f; +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fCloseRunSpeed = FRnd () + 5.0f; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fAttackDistance = 150.0f; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fCloseDistance = 0.0f; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fStopDistance = 25.0f; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fAttackFireTime = 5.0f; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fCloseFireTime = 5.0f; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fIgnoreRange = 250.0f; +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fBodyParts = 5; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +m_fDamageWounded = 100.0f; +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Guffy.es b/Sources/EntitiesMP/Guffy.es new file mode 100644 index 0000000..aeb4f36 --- /dev/null +++ b/Sources/EntitiesMP/Guffy.es @@ -0,0 +1,348 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +344 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/Guffy/Guffy.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/Projectile"; + + +%{ +// info structure +static EntityInfo eiGuffy = { + EIBT_FLESH, 800.0f, + 0.0f, 1.9f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +#define FIRE_LEFT_ARM FLOAT3D(-0.56f, +1.125f, -1.32f) +#define FIRE_RIGHT_ARM FLOAT3D(+0.50f, +1.060f, -0.82f) + +//#define FIRE_DEATH_LEFT FLOAT3D( 0.0f, 7.0f, -2.0f) +//#define FIRE_DEATH_RIGHT FLOAT3D(3.75f, 4.2f, -2.5f) + +%} + + +class CGuffy : CEnemyBase { +name "Guffy"; +thumbnail "Thumbnails\\Guffy.tbn"; + +properties: + + 2 INDEX m_iLoopCounter = 0, + 3 FLOAT m_fSize = 1.0f, + 4 BOOL m_bWalkSoundPlaying = FALSE, + 5 FLOAT m_fThreatDistance = 5.0f, + 6 BOOL m_bEnemyToTheLeft = FALSE, + + //10 CSoundObject m_soFeet, + 10 CSoundObject m_soFire1, + 11 CSoundObject m_soFire2, + +components: + 0 class CLASS_BASE "Classes\\EnemyBase.ecl", + 1 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + + 10 model MODEL_GUFFY "ModelsMP\\Enemies\\Guffy\\Guffy.mdl", + 11 texture TEXTURE_GUFFY "ModelsMP\\Enemies\\Guffy\\Guffy.tex", + 12 model MODEL_GUN "ModelsMP\\Enemies\\Guffy\\Gun.mdl", + 13 texture TEXTURE_GUN "ModelsMP\\Enemies\\Guffy\\Gun.tex", + +// ************** SOUNDS ************** + 40 sound SOUND_IDLE "ModelsMP\\Enemies\\Guffy\\Sounds\\Idle.wav", + 41 sound SOUND_SIGHT "ModelsMP\\Enemies\\Guffy\\Sounds\\Sight.wav", + 43 sound SOUND_FIRE "ModelsMP\\Enemies\\Guffy\\Sounds\\Fire.wav", + 44 sound SOUND_WOUND "ModelsMP\\Enemies\\Guffy\\Sounds\\Wound.wav", + 45 sound SOUND_DEATH "ModelsMP\\Enemies\\Guffy\\Sounds\\Death.wav", + +functions: + +// describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("Guffy gunned %s down"), strPlayerName); + return str; + } + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnmSoldier, "DataMP\\Messages\\Enemies\\Guffy.txt"); + return fnmSoldier; + } + /*// overridable function to get range for switching to another player + FLOAT GetThreatDistance(void) + { + return m_fThreatDistance; + }*/ + + /*BOOL ForcesCannonballToExplode(void) + { + if (m_EwcChar==WLC_SERGEANT) { + return TRUE; + } + return CEnemyBase::ForcesCannonballToExplode(); + }*/ + + void Precache(void) { + CEnemyBase::Precache(); + + // guffy + PrecacheModel(MODEL_GUFFY); + PrecacheTexture(TEXTURE_GUFFY); + + // weapon + PrecacheModel(MODEL_GUN); + PrecacheTexture(TEXTURE_GUN); + + // sounds + PrecacheSound(SOUND_IDLE ); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_DEATH); + PrecacheSound(SOUND_FIRE); + PrecacheSound(SOUND_WOUND); + + // projectile + PrecacheClass(CLASS_PROJECTILE, PRT_GUFFY_PROJECTILE); + }; + + // Entity info + void *GetEntityInfo(void) { + return &eiGuffy; + }; + + /*FLOAT GetCrushHealth(void) + { + if (m_EwcChar==WLC_SERGEANT) { + return 100.0f; + } + return 0.0f; + }*/ + + // Receive damage + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // guffy can't harm guffy + if (!IsOfClass(penInflictor, "Guffy")) { + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + }; + + + // virtual anim functions + void StandingAnim(void) { + StartModelAnim(GUFFY_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + /*void StandingAnimFight(void) + { + StartModelAnim(GUFFY_ANIM_FIRE, AOF_LOOPING|AOF_NORESTART); + }*/ + void RunningAnim(void) { + StartModelAnim(GUFFY_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); + }; + void WalkingAnim(void) { + RunningAnim(); + }; + void RotatingAnim(void) { + StartModelAnim(GUFFY_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + // fire rocket + void FireRocket(FLOAT3D &vPos) { + CPlacement3D plRocket; + plRocket.pl_PositionVector = vPos; + plRocket.pl_OrientationAngle = ANGLE3D(0, -5.0f-FRnd()*10.0f, 0); + plRocket.RelativeToAbsolute(GetPlacement()); + CEntityPointer penProjectile = CreateEntity(plRocket, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_GUFFY_PROJECTILE; + penProjectile->Initialize(eLaunch); + }; + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + // set sound default parameters + m_soSound.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + m_soFire1.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + m_soFire2.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + }; + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim; + iAnim = GUFFY_ANIM_WOUND; + StartModelAnim(iAnim, 0); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + INDEX iAnim; + FLOAT3D vFront; + GetHeadingDirection(0, vFront); + FLOAT fDamageDir = m_vDamage%vFront; + if (fDamageDir<0) { + iAnim = GUFFY_ANIM_DEATHBACKWARD; + } else { + iAnim = GUFFY_ANIM_DEATHFORWARD; + } + + StartModelAnim(iAnim, 0); + return iAnim; + }; + + // death + FLOAT WaitForDust(FLOAT3D &vStretch) { + vStretch=FLOAT3D(1,1,2)*1.5f; + if(GetModelObject()->GetAnim()==GUFFY_ANIM_DEATHBACKWARD) + { + return 0.48f; + } + else if(GetModelObject()->GetAnim()==GUFFY_ANIM_DEATHFORWARD) + { + return 1.0f; + } + return -1.0f; + }; + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + Fire(EVoid) : CEnemyBase::Fire { + + StartModelAnim(GUFFY_ANIM_FIRE, AOF_LOOPING); + + // wait for animation to bring the left hand into firing position + autowait(0.1f); + + FLOATmatrix3D m; + FLOAT3D fLookRight = FLOAT3D(1.0f, 0.0f, 0.0f); + MakeRotationMatrixFast(m, GetPlacement().pl_OrientationAngle); + fLookRight = fLookRight * m; + BOOL bEnemyRight = fLookRight % (m_penEnemy->GetPlacement().pl_PositionVector - GetPlacement().pl_PositionVector); + + if (bEnemyRight>=0) { // enemy is to the right of guffy + ShootProjectile(PRT_GUFFY_PROJECTILE, FIRE_LEFT_ARM*m_fSize, ANGLE3D(0, 0, 0)); + PlaySound(m_soFire1, SOUND_FIRE, SOF_3D); + + ShootProjectile(PRT_GUFFY_PROJECTILE, FIRE_RIGHT_ARM*m_fSize, ANGLE3D(-9, 0, 0)); + PlaySound(m_soFire2, SOUND_FIRE, SOF_3D); + } else { // enemy is to the left of guffy + ShootProjectile(PRT_GUFFY_PROJECTILE, FIRE_LEFT_ARM*m_fSize, ANGLE3D(9, 0, 0)); + PlaySound(m_soFire1, SOUND_FIRE, SOF_3D); + + ShootProjectile(PRT_GUFFY_PROJECTILE, FIRE_RIGHT_ARM*m_fSize, ANGLE3D(0, 0, 0)); + PlaySound(m_soFire2, SOUND_FIRE, SOF_3D); + } + + autowait(1.0f); + + StopMoving(); + + MaybeSwitchToAnotherPlayer(); + + // wait for a while + StandingAnimFight(); + autowait(FRnd()*0.25f+0.25f); + + return EReturn(); + }; + + +/************************************************************ + * D E A T H * + ************************************************************/ + /*Death(EVoid) : CEnemyBase::Death { + // stop moving + StopMoving(); + DeathSound(); // death sound + + // set physic flags + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags() | ENF_SEETHROUGH); + + // death notify (change collision box) + ChangeCollisionBoxIndexWhenPossible(GUFFY_COLLISION_BOX_DEATH); + + // start death anim + StartModelAnim(GUFFY_ANIM_DEATHFORWARD, 0); + autowait(GetModelObject()->GetAnimLength(GUFFY_ANIM_TOFIRE)); + + return EEnd(); + };*/ + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + SetHealth(210.0f); + m_fMaxHealth = 210.0f; + en_fDensity = 2000.0f; + + // set your appearance + SetModel(MODEL_GUFFY); + m_fSize = 1.5f; + SetModelMainTexture(TEXTURE_GUFFY); + AddAttachment(GUFFY_ATTACHMENT_GUNRIGHT, MODEL_GUN, TEXTURE_GUN); + AddAttachment(GUFFY_ATTACHMENT_GUNLEFT, MODEL_GUN, TEXTURE_GUN); + GetModelObject()->StretchModel(FLOAT3D(m_fSize, m_fSize, m_fSize)); + ModelChangeNotify(); + CModelObject *pmoRight = &GetModelObject()->GetAttachmentModel(GUFFY_ATTACHMENT_GUNRIGHT)->amo_moModelObject; + pmoRight->StretchModel(FLOAT3D(-1,1,1)); + m_fBlowUpAmount = 10000.0f; + m_iScore = 3000; + //m_fThreatDistance = 15; + + if (m_fStepHeight==-1) { + m_fStepHeight = 4.0f; + } + + StandingAnim(); + // setup moving speed + m_fWalkSpeed = FRnd() + 2.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f); + m_fAttackRunSpeed = FRnd() + 5.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + m_fCloseRunSpeed = FRnd() + 5.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + // setup attack distances + m_fAttackDistance = 150.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 25.0f; + m_fAttackFireTime = 5.0f; + m_fCloseFireTime = 5.0f; + m_fIgnoreRange = 250.0f; + // damage/explode properties + m_fBodyParts = 5; + m_fDamageWounded = 100.0f; + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Guffy.h b/Sources/EntitiesMP/Guffy.h new file mode 100644 index 0000000..60a7b83 --- /dev/null +++ b/Sources/EntitiesMP/Guffy.h @@ -0,0 +1,91 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Guffy_INCLUDED +#define _EntitiesMP_Guffy_INCLUDED 1 +#include +#include +extern "C" DECL_DLL CDLLEntityClass CGuffy_DLLClass; +class CGuffy : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + INDEX m_iLoopCounter; + FLOAT m_fSize; + BOOL m_bWalkSoundPlaying; + FLOAT m_fThreatDistance; + BOOL m_bEnemyToTheLeft; + CSoundObject m_soFire1; + CSoundObject m_soFire2; + +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void Precache(void); + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void * GetEntityInfo(void); + +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void StandingAnim(void); + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void RunningAnim(void); + +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void WalkingAnim(void); + +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void RotatingAnim(void); + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void IdleSound(void); + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void SightSound(void); + +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void WoundSound(void); + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void DeathSound(void); + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void FireRocket(FLOAT3D & vPos); + +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +void EnemyPostInit(void); + +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +INDEX AnimForDeath(void); + +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +FLOAT WaitForDust(FLOAT3D & vStretch); +#define STATE_CGuffy_Fire 0x01580000 + BOOL +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x01580001_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x01580002_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x01580003_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x01580004_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x01580005_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x01580006_Fire_06(const CEntityEvent &__eeInput); +#define STATE_CGuffy_Main 1 + BOOL +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Guffy_INCLUDED diff --git a/Sources/EntitiesMP/Guffy_tables.h b/Sources/EntitiesMP/Guffy_tables.h new file mode 100644 index 0000000..04de8df --- /dev/null +++ b/Sources/EntitiesMP/Guffy_tables.h @@ -0,0 +1,69 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CGuffy + +CEntityProperty CGuffy_properties[] = { + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000158<<8)+2, offsetof(CGuffy, m_iLoopCounter), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000158<<8)+3, offsetof(CGuffy, m_fSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000158<<8)+4, offsetof(CGuffy, m_bWalkSoundPlaying), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000158<<8)+5, offsetof(CGuffy, m_fThreatDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000158<<8)+6, offsetof(CGuffy, m_bEnemyToTheLeft), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000158<<8)+10, offsetof(CGuffy, m_soFire1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000158<<8)+11, offsetof(CGuffy, m_soFire2), "", 0, 0, 0), +}; +#define CGuffy_propertiesct ARRAYCOUNT(CGuffy_properties) + +CEntityComponent CGuffy_components[] = { +#define CLASS_BASE ((0x00000158<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_PROJECTILE ((0x00000158<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define MODEL_GUFFY ((0x00000158<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_GUFFY, "EFNM" "ModelsMP\\Enemies\\Guffy\\Guffy.mdl"), +#define TEXTURE_GUFFY ((0x00000158<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_GUFFY, "EFNM" "ModelsMP\\Enemies\\Guffy\\Guffy.tex"), +#define MODEL_GUN ((0x00000158<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_GUN, "EFNM" "ModelsMP\\Enemies\\Guffy\\Gun.mdl"), +#define TEXTURE_GUN ((0x00000158<<8)+13) + CEntityComponent(ECT_TEXTURE, TEXTURE_GUN, "EFNM" "ModelsMP\\Enemies\\Guffy\\Gun.tex"), +#define SOUND_IDLE ((0x00000158<<8)+40) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "ModelsMP\\Enemies\\Guffy\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000158<<8)+41) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "ModelsMP\\Enemies\\Guffy\\Sounds\\Sight.wav"), +#define SOUND_FIRE ((0x00000158<<8)+43) + CEntityComponent(ECT_SOUND, SOUND_FIRE, "EFNM" "ModelsMP\\Enemies\\Guffy\\Sounds\\Fire.wav"), +#define SOUND_WOUND ((0x00000158<<8)+44) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "ModelsMP\\Enemies\\Guffy\\Sounds\\Wound.wav"), +#define SOUND_DEATH ((0x00000158<<8)+45) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "ModelsMP\\Enemies\\Guffy\\Sounds\\Death.wav"), +}; +#define CGuffy_componentsct ARRAYCOUNT(CGuffy_components) + +CEventHandlerEntry CGuffy_handlers[] = { + {0x01580000, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CGuffy:: +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +Fire),DEBUGSTRING("CGuffy::Fire")}, + {0x01580001, -1, CEntity::pEventHandler(&CGuffy::H0x01580001_Fire_01), DEBUGSTRING("CGuffy::H0x01580001_Fire_01")}, + {0x01580002, -1, CEntity::pEventHandler(&CGuffy::H0x01580002_Fire_02), DEBUGSTRING("CGuffy::H0x01580002_Fire_02")}, + {0x01580003, -1, CEntity::pEventHandler(&CGuffy::H0x01580003_Fire_03), DEBUGSTRING("CGuffy::H0x01580003_Fire_03")}, + {0x01580004, -1, CEntity::pEventHandler(&CGuffy::H0x01580004_Fire_04), DEBUGSTRING("CGuffy::H0x01580004_Fire_04")}, + {0x01580005, -1, CEntity::pEventHandler(&CGuffy::H0x01580005_Fire_05), DEBUGSTRING("CGuffy::H0x01580005_Fire_05")}, + {0x01580006, -1, CEntity::pEventHandler(&CGuffy::H0x01580006_Fire_06), DEBUGSTRING("CGuffy::H0x01580006_Fire_06")}, + {1, -1, CEntity::pEventHandler(&CGuffy:: +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Guffy.es" +Main),DEBUGSTRING("CGuffy::Main")}, +}; +#define CGuffy_handlersct ARRAYCOUNT(CGuffy_handlers) + +CEntity *CGuffy_New(void) { return new CGuffy; }; +void CGuffy_OnInitClass(void) {}; +void CGuffy_OnEndClass(void) {}; +void CGuffy_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CGuffy_OnWorldEnd(CWorld *pwo) {}; +void CGuffy_OnWorldInit(CWorld *pwo) {}; +void CGuffy_OnWorldTick(CWorld *pwo) {}; +void CGuffy_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CGuffy, CEnemyBase, "Guffy", "Thumbnails\\Guffy.tbn", 0x00000158); +DECLARE_CTFILENAME(_fnmCGuffy_tbn, "Thumbnails\\Guffy.tbn"); diff --git a/Sources/EntitiesMP/HazeMarker.cpp b/Sources/EntitiesMP/HazeMarker.cpp new file mode 100644 index 0000000..09c1254 --- /dev/null +++ b/Sources/EntitiesMP/HazeMarker.cpp @@ -0,0 +1,168 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" + +#include "StdH.h" + +#include +#include +void CHazeMarker::SetDefaultProperties(void) { + m_faType = FA_EXP ; + m_fDensity = 0.1f; + m_fNear = 100.0f; + m_fFar = 1000.0f; + m_bVisibleFromOutside = FALSE ; + m_iSize = 32; + m_colBase = (C_WHITE | CT_OPAQUE ); + m_colUp = (C_BLACK | CT_TRANSPARENT ); + m_colDown = (C_BLACK | CT_TRANSPARENT ); + m_colNorth = (C_BLACK | CT_TRANSPARENT ); + m_colSouth = (C_BLACK | CT_TRANSPARENT ); + m_colEast = (C_BLACK | CT_TRANSPARENT ); + m_colWest = (C_BLACK | CT_TRANSPARENT ); + CMarker::SetDefaultProperties(); +} + +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +const CTString & CHazeMarker::GetHazeName(void) +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +{ +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +return m_strName ; +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +} + +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +void CHazeMarker::GetHaze(class CHazeParameters & hpHaze,FLOAT3D & vViewDir) +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +{ +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +COLOR colDir = C_BLACK , colMul ; +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +FLOAT fR = 0.0f , fG = 0.0f , fB = 0.0f , fA = 0.0f; +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +FLOAT fSum = 255.0f / (Abs (vViewDir (1)) + Abs (vViewDir (2)) + Abs (vViewDir (3))); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +if(vViewDir (1) < 0.0f){ +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (COLOR) (- vViewDir (1) * fSum ); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (colMul << CT_RSHIFT ) | (colMul << CT_GSHIFT ) | (colMul << CT_BSHIFT ) | (colMul << CT_ASHIFT ); +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colDir = AddColors (colDir , MulColors (m_colWest , colMul )); +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +} +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +if(vViewDir (1) > 0.0f){ +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (COLOR) (+ vViewDir (1) * fSum ); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (colMul << CT_RSHIFT ) | (colMul << CT_GSHIFT ) | (colMul << CT_BSHIFT ) | (colMul << CT_ASHIFT ); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colDir = AddColors (colDir , MulColors (m_colEast , colMul )); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +} +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +if(vViewDir (2) < 0.0f){ +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (COLOR) (- vViewDir (2) * fSum ); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (colMul << CT_RSHIFT ) | (colMul << CT_GSHIFT ) | (colMul << CT_BSHIFT ) | (colMul << CT_ASHIFT ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colDir = AddColors (colDir , MulColors (m_colDown , colMul )); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +} +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +if(vViewDir (2) > 0.0f){ +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (COLOR) (+ vViewDir (2) * fSum ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (colMul << CT_RSHIFT ) | (colMul << CT_GSHIFT ) | (colMul << CT_BSHIFT ) | (colMul << CT_ASHIFT ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colDir = AddColors (colDir , MulColors (m_colUp , colMul )); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +} +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +if(vViewDir (3) < 0.0f){ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (COLOR) (- vViewDir (3) * fSum ); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (colMul << CT_RSHIFT ) | (colMul << CT_GSHIFT ) | (colMul << CT_BSHIFT ) | (colMul << CT_ASHIFT ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colDir = AddColors (colDir , MulColors (m_colNorth , colMul )); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +} +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +if(vViewDir (3) > 0.0f){ +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (COLOR) (+ vViewDir (3) * fSum ); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colMul = (colMul << CT_RSHIFT ) | (colMul << CT_GSHIFT ) | (colMul << CT_BSHIFT ) | (colMul << CT_ASHIFT ); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colDir = AddColors (colDir , MulColors (m_colSouth , colMul )); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +} +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +colDir = AddColors (colDir , m_colBase ); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +hpHaze . hp_colColor = colDir ; +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +hpHaze . hp_atType = (AttenuationType ) m_faType ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +hpHaze . hp_fDensity = m_fDensity ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +hpHaze . hp_fNear = m_fNear ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +hpHaze . hp_fFar = m_fFar ; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +hpHaze . hp_iSize = m_iSize ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +hpHaze . hp_ulFlags = 0; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +if(m_bVisibleFromOutside ){ +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +hpHaze . hp_ulFlags |= HPF_VISIBLEFROMOUTSIDE ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +} +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +} +BOOL CHazeMarker:: +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHazeMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHazeMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +InitAsEditorModel (); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +SetModel (MODEL_MARKER ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +if(m_strName == "Marker"){ +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +m_strName = "Haze marker"; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +} +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +m_fDensity = ClampDn (m_fDensity , 1E-6f); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +m_fFar = ClampDn (m_fFar , 0.001f); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +m_fNear = Clamp (m_fNear , 0.0f , m_fFar - 0.0005f); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +ASSERT (m_fNear >= 0 && m_fNear < m_fFar ); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +m_iSize = 1 << INDEX (Log2 (m_iSize )); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +m_iSize = Clamp (m_iSize , INDEX (2) , INDEX (256)); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/HazeMarker.es b/Sources/EntitiesMP/HazeMarker.es new file mode 100644 index 0000000..53f4434 --- /dev/null +++ b/Sources/EntitiesMP/HazeMarker.es @@ -0,0 +1,128 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +216 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; +uses "EntitiesMP/FogMarker"; + + +class CHazeMarker: CMarker { +name "Haze Marker"; +thumbnail "Thumbnails\\HazeMarker.tbn"; +features "IsImportant"; + +properties: + 10 enum FogAttenuationType m_faType "Attenuation Type" 'A' =FA_EXP, + 11 FLOAT m_fDensity "Density" 'D' = 0.1f, + 12 FLOAT m_fNear "Near" = 100.0f, + 13 FLOAT m_fFar "Far" = 1000.0f, + 14 BOOL m_bVisibleFromOutside "Visible from outside" = FALSE, + + 22 INDEX m_iSize "Size" = 32, + 23 COLOR m_colBase "Base Color" 'C' = (C_WHITE|CT_OPAQUE), + 24 COLOR m_colUp "Color (up)" = (C_BLACK|CT_TRANSPARENT), + 25 COLOR m_colDown "Color (down)" = (C_BLACK|CT_TRANSPARENT), + 26 COLOR m_colNorth "Color (north)" = (C_BLACK|CT_TRANSPARENT), + 27 COLOR m_colSouth "Color (south)" = (C_BLACK|CT_TRANSPARENT), + 28 COLOR m_colEast "Color (east)" = (C_BLACK|CT_TRANSPARENT), + 29 COLOR m_colWest "Color (west)" = (C_BLACK|CT_TRANSPARENT), + +components: + 1 model MODEL_MARKER "Models\\Editor\\Haze.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Haze.tex" + +functions: + + /* Get haze type name, return empty string if not used. */ + const CTString &GetHazeName(void) + { + return m_strName; + } + + /* Get haze. */ + void GetHaze(class CHazeParameters &hpHaze, FLOAT3D &vViewDir) + { + // calculate directional haze color + COLOR colDir=C_BLACK, colMul; + FLOAT fR=0.0f, fG=0.0f, fB=0.0f, fA=0.0f; + FLOAT fSum = 255.0f / (Abs(vViewDir(1))+Abs(vViewDir(2))+Abs(vViewDir(3))); + + if( vViewDir(1) < 0.0f) { + colMul = (COLOR)(-vViewDir(1)*fSum); + colMul = (colMul< 0.0f) { + colMul = (COLOR)(+vViewDir(1)*fSum); + colMul = (colMul< 0.0f) { + colMul = (COLOR)(+vViewDir(2)*fSum); + colMul = (colMul< 0.0f) { + colMul = (COLOR)(+vViewDir(3)*fSum); + colMul = (colMul<=0 && m_fNear +#include +extern "C" DECL_DLL CDLLEntityClass CHazeMarker_DLLClass; +class CHazeMarker : public CMarker { +public: +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + enum FogAttenuationType m_faType; + FLOAT m_fDensity; + FLOAT m_fNear; + FLOAT m_fFar; + BOOL m_bVisibleFromOutside; + INDEX m_iSize; + COLOR m_colBase; + COLOR m_colUp; + COLOR m_colDown; + COLOR m_colNorth; + COLOR m_colSouth; + COLOR m_colEast; + COLOR m_colWest; + +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +const CTString & GetHazeName(void); + +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +void GetHaze(class CHazeParameters & hpHaze,FLOAT3D & vViewDir); +#define STATE_CHazeMarker_Main 1 + BOOL +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_HazeMarker_INCLUDED diff --git a/Sources/EntitiesMP/HazeMarker_tables.h b/Sources/EntitiesMP/HazeMarker_tables.h new file mode 100644 index 0000000..b12dbe0 --- /dev/null +++ b/Sources/EntitiesMP/HazeMarker_tables.h @@ -0,0 +1,48 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CHazeMarker + +CEntityProperty CHazeMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &FogAttenuationType_enum, (0x000000d8<<8)+10, offsetof(CHazeMarker, m_faType), "Attenuation Type", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d8<<8)+11, offsetof(CHazeMarker, m_fDensity), "Density", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d8<<8)+12, offsetof(CHazeMarker, m_fNear), "Near", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d8<<8)+13, offsetof(CHazeMarker, m_fFar), "Far", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d8<<8)+14, offsetof(CHazeMarker, m_bVisibleFromOutside), "Visible from outside", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000d8<<8)+22, offsetof(CHazeMarker, m_iSize), "Size", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d8<<8)+23, offsetof(CHazeMarker, m_colBase), "Base Color", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d8<<8)+24, offsetof(CHazeMarker, m_colUp), "Color (up)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d8<<8)+25, offsetof(CHazeMarker, m_colDown), "Color (down)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d8<<8)+26, offsetof(CHazeMarker, m_colNorth), "Color (north)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d8<<8)+27, offsetof(CHazeMarker, m_colSouth), "Color (south)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d8<<8)+28, offsetof(CHazeMarker, m_colEast), "Color (east)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d8<<8)+29, offsetof(CHazeMarker, m_colWest), "Color (west)", 0, 0x7F0000FFUL, 0), +}; +#define CHazeMarker_propertiesct ARRAYCOUNT(CHazeMarker_properties) + +CEntityComponent CHazeMarker_components[] = { +#define MODEL_MARKER ((0x000000d8<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Haze.mdl"), +#define TEXTURE_MARKER ((0x000000d8<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Haze.tex"), +}; +#define CHazeMarker_componentsct ARRAYCOUNT(CHazeMarker_components) + +CEventHandlerEntry CHazeMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CHazeMarker:: +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/HazeMarker.es" +Main),DEBUGSTRING("CHazeMarker::Main")}, +}; +#define CHazeMarker_handlersct ARRAYCOUNT(CHazeMarker_handlers) + +CEntity *CHazeMarker_New(void) { return new CHazeMarker; }; +void CHazeMarker_OnInitClass(void) {}; +void CHazeMarker_OnEndClass(void) {}; +void CHazeMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CHazeMarker_OnWorldEnd(CWorld *pwo) {}; +void CHazeMarker_OnWorldInit(CWorld *pwo) {}; +void CHazeMarker_OnWorldTick(CWorld *pwo) {}; +void CHazeMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CHazeMarker, CMarker, "Haze Marker", "Thumbnails\\HazeMarker.tbn", 0x000000d8); +DECLARE_CTFILENAME(_fnmCHazeMarker_tbn, "Thumbnails\\HazeMarker.tbn"); diff --git a/Sources/EntitiesMP/Headman.cpp b/Sources/EntitiesMP/Headman.cpp new file mode 100644 index 0000000..fc5660f --- /dev/null +++ b/Sources/EntitiesMP/Headman.cpp @@ -0,0 +1,1172 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" + +#include "StdH.h" +#include "Models/Enemies/Headman/Headman.h" + +#include +#include +#line 20 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" + +// info structure +static EntityInfo eiHeadman = { + EIBT_FLESH, 100.0f, + 0.0f, 1.9f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +#define EXPLODE_KAMIKAZE 2.5f +#define BOMBERMAN_ANGLE (45.0f) +#define BOMBERMAN_LAUNCH (FLOAT3D(0.0f, 1.5f, 0.0f)) + +void CHeadman::SetDefaultProperties(void) { + m_hdtType = HDT_FIRECRACKER ; + m_bExploded = FALSE ; + m_bAttackSound = FALSE ; + CEnemyBase::SetDefaultProperties(); +} + CTString CHeadman::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +{ +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CTString str ; +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(eDeath . eLastDamage . dmtType == DMT_EXPLOSION ){ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_BOMBERMAN ){ +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +str . PrintF (TRANS ("%s was bombed by a Bomberman") , strPlayerName ); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else { +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +str . PrintF (TRANS ("%s fell victim of a Kamikaze") , strPlayerName ); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else if(m_hdtType == HDT_ROCKETMAN ){ +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +str . PrintF (TRANS ("A Rocketeer tickled %s to death") , strPlayerName ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else if(m_hdtType == HDT_FIRECRACKER ){ +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +str . PrintF (TRANS ("A Firecracker tickled %s to death") , strPlayerName ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return str ; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void * CHeadman::GetEntityInfo(void) { +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return & eiHeadman ; +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + const CTFileName & CHeadman::GetComputerMessageName(void)const { +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +static DECLARE_CTFILENAME (fnmRocketman , "Data\\Messages\\Enemies\\Rocketman.txt"); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +static DECLARE_CTFILENAME (fnmFirecracker , "Data\\Messages\\Enemies\\Firecracker.txt"); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +static DECLARE_CTFILENAME (fnmBomberman , "Data\\Messages\\Enemies\\Bomberman.txt"); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +static DECLARE_CTFILENAME (fnmKamikaze , "Data\\Messages\\Enemies\\Kamikaze.txt"); +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +switch(m_hdtType ){ +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +default : ASSERT (FALSE ); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_ROCKETMAN : return fnmRocketman ; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_FIRECRACKER : return fnmFirecracker ; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_BOMBERMAN : return fnmBomberman ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_KAMIKAZE : return fnmKamikaze ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::Precache(void) { +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CEnemyBase :: Precache (); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheSound (SOUND_IDLE ); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheSound (SOUND_SIGHT ); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheSound (SOUND_WOUND ); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheSound (SOUND_DEATH ); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +switch(m_hdtType ){ +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_FIRECRACKER : { +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheSound (SOUND_FIREFIRECRACKER ); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheClass (CLASS_PROJECTILE , PRT_HEADMAN_FIRECRACKER ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}break ; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_ROCKETMAN : { +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheSound (SOUND_FIREROCKETMAN ); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheClass (CLASS_PROJECTILE , PRT_HEADMAN_ROCKETMAN ); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}break ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_BOMBERMAN : { +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheSound (SOUND_FIREBOMBERMAN ); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheClass (CLASS_PROJECTILE , PRT_HEADMAN_BOMBERMAN ); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheModel (MODEL_BOMB ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheTexture (TEXTURE_BOMB ); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}break ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_KAMIKAZE : { +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheSound (SOUND_ATTACKKAMIKAZE ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheSound (SOUND_IDLEKAMIKAZE ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_BOMB ); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheModel (MODEL_BOMB ); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrecacheTexture (TEXTURE_BOMB ); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}break ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +BOOL CHeadman::FillEntityStatistics(EntityStats * pes) +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +{ +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CEnemyBase :: FillEntityStatistics (pes ); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +switch(m_hdtType ){ +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_FIRECRACKER : {pes -> es_strName += " Firecracker";}break ; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_ROCKETMAN : {pes -> es_strName += " Rocketman";}break ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_BOMBERMAN : {pes -> es_strName += " Bomberman";}break ; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_KAMIKAZE : {pes -> es_strName += " Kamikaze";}break ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return TRUE ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +{ +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(! IsOfClass (penInflictor , "Headman") || +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +! (((CHeadman *) penInflictor ) -> m_hdtType == HDT_FIRECRACKER || +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +((CHeadman *) penInflictor ) -> m_hdtType == HDT_ROCKETMAN )){ +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(dmtType == DMT_CHAINSAW && GetHealth () <= 0){ +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fBlowUpAmount = 0; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +INDEX CHeadman::AnimForDamage(FLOAT fDamage) { +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +INDEX iAnim ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(IRnd () % 2){ +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +iAnim = HEADMAN_ANIM_WOUND1 ; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else { +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +iAnim = HEADMAN_ANIM_WOUND2 ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StartModelAnim (iAnim , 0); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return iAnim ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +INDEX CHeadman::AnimForDeath(void) { +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +INDEX iAnim ; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FLOAT3D vFront ; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +GetHeadingDirection (0 , vFront ); +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FLOAT fDamageDir = m_vDamage % vFront ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(fDamageDir < 0){ +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(Abs (fDamageDir ) < 10.0f){ +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +iAnim = HEADMAN_ANIM_DEATH_EASY_FALL_BACK ; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else { +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +iAnim = HEADMAN_ANIM_DEATH_FALL_BACK ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else { +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(Abs (fDamageDir ) < 10.0f){ +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +iAnim = HEADMAN_ANIM_DEATH_EASY_FALL_FORWARD ; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else { +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +iAnim = HEADMAN_ANIM_DEATH_FALL_ON_KNEES ; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StartModelAnim (iAnim , 0); +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return iAnim ; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FLOAT CHeadman::WaitForDust(FLOAT3D & vStretch) { +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +vStretch = FLOAT3D (1 , 1 , 2); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(GetModelObject () -> GetAnim () == HEADMAN_ANIM_DEATH_EASY_FALL_BACK ) +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +{ +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +vStretch = vStretch * 0.3f; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return 0.864f; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(GetModelObject () -> GetAnim () == HEADMAN_ANIM_DEATH_FALL_BACK ) +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +{ +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +vStretch = vStretch * 0.75f; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return 0.48f; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(GetModelObject () -> GetAnim () == HEADMAN_ANIM_DEATH_EASY_FALL_FORWARD ) +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +{ +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +vStretch = vStretch * 0.3f; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return 1.12f; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +else if(GetModelObject () -> GetAnim () == HEADMAN_ANIM_DEATH_FALL_ON_KNEES ) +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +{ +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +vStretch = vStretch * 0.75f; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return 1.035f; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return - 1.0f; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +BOOL CHeadman::ShouldBlowUp(void) +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +{ +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_KAMIKAZE && GetHealth () <= 0){ +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return TRUE ; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else { +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return CEnemyBase :: ShouldBlowUp (); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::DeathNotify(void) { +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +ChangeCollisionBoxIndexWhenPossible (HEADMAN_COLLISION_BOX_DEATH ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +en_fDensity = 500.0f; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::StandingAnim(void) { +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StartModelAnim (HEADMAN_ANIM_IDLE_PATROL , AOF_LOOPING | AOF_NORESTART ); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_KAMIKAZE ){ +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +KamikazeSoundOff (); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::StandingAnimFight(void) +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +{ +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StartModelAnim (HEADMAN_ANIM_IDLE_FIGHT , AOF_LOOPING | AOF_NORESTART ); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_KAMIKAZE ){ +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +KamikazeSoundOff (); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::WalkingAnim(void) { +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StartModelAnim (HEADMAN_ANIM_WALK , AOF_LOOPING | AOF_NORESTART ); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::RunningAnim(void) { +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_KAMIKAZE ){ +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +KamikazeSoundOn (); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StartModelAnim (HEADMAN_ANIM_KAMIKAZE_ATTACK , AOF_LOOPING | AOF_NORESTART ); +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else { +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StartModelAnim (HEADMAN_ANIM_RUN , AOF_LOOPING | AOF_NORESTART ); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::RotatingAnim(void) { +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +RunningAnim (); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::IdleSound(void) { +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_bAttackSound ){ +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return ; +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_KAMIKAZE ){ +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PlaySound (m_soSound , SOUND_IDLEKAMIKAZE , SOF_3D ); +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else { +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::SightSound(void) { +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_bAttackSound ){ +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return ; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::WoundSound(void) { +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_bAttackSound ){ +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return ; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::DeathSound(void) { +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_bAttackSound ){ +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return ; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::KamikazeSoundOn(void) { +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(! m_bAttackSound ){ +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_bAttackSound = TRUE ; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PlaySound (m_soSound , SOUND_ATTACKKAMIKAZE , SOF_3D | SOF_LOOP ); +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::KamikazeSoundOff(void) { +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_bAttackSound ){ +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_soSound . Stop (); +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_bAttackSound = FALSE ; +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::BlowUpNotify(void) { +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_KAMIKAZE || m_hdtType == HDT_BOMBERMAN ){ +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Explode (); +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::Explode(void) { +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(! m_bExploded ){ +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_bExploded = TRUE ; +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FLOAT3D vSource ; +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +GetEntityInfoPosition (this , eiHeadman . vTargetCenter , vSource ); +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_BOMBERMAN ){ +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +InflictDirectDamage (this , this , DMT_EXPLOSION , 100.0f , vSource , +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +- en_vGravityDir ); +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +InflictRangeDamage (this , DMT_EXPLOSION , 15.0f , vSource , 1.0f , 6.0f); +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else { +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +InflictDirectDamage (this , this , DMT_CLOSERANGE , 100.0f , vSource , +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +- en_vGravityDir ); +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +InflictRangeDamage (this , DMT_EXPLOSION , 30.0f , vSource , 2.75f , 8.0f); +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CPlacement3D plExplosion = GetPlacement (); +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CEntityPointer penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +ESpawnEffect eSpawnEffect ; +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +eSpawnEffect . betType = BET_BOMB ; +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +eSpawnEffect . vStretch = FLOAT3D (1.0f , 1.0f , 1.0f); +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +eSpawnEffect . betType = BET_EXPLOSION_DEBRIS ; +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CEntityPointer penExplosionDebris = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +penExplosionDebris -> Initialize (eSpawnEffect ); +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +eSpawnEffect . betType = BET_EXPLOSION_SMOKE ; +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CEntityPointer penExplosionSmoke = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +penExplosionSmoke -> Initialize (eSpawnEffect ); +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void CHeadman::SetSpeedsToDesiredPosition(const FLOAT3D & vPosDelta,FLOAT fPosDistance,BOOL bGoingToPlayer) +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +{ +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_KAMIKAZE && CalcDist (m_penEnemy ) < EXPLODE_KAMIKAZE ){ +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetHealth (- 10000.0f); +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_vDamage = FLOAT3D (0 , 10000 , 0); +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SendEvent (EDeath ()); +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else { +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CEnemyBase :: SetSpeedsToDesiredPosition (vPosDelta , fPosDistance , bGoingToPlayer ); +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} + FLOAT CHeadman::GetAttackMoveFrequency(FLOAT fEnemyDistance) +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +{ +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_KAMIKAZE && fEnemyDistance < m_fCloseDistance ){ +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return 0.1f; +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}else { +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return CEnemyBase :: GetAttackMoveFrequency (fEnemyDistance ); +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +BOOL CHeadman:: +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +InitializeAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHeadman_InitializeAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHeadman::InitializeAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_KAMIKAZE ){ +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +KamikazeSoundOn (); +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_InitializeAttack, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CHeadman:: +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StopAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHeadman_StopAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHeadman::StopAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +KamikazeSoundOff (); +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_StopAttack, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CHeadman:: +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHeadman_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHeadman::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(!(m_hdtType == HDT_FIRECRACKER )){ Jump(STATE_CURRENT,0x012f000e, FALSE, EInternal());return TRUE;} +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +STATE_CHeadman_FirecrackerAttack, TRUE; +Jump(STATE_CURRENT, 0x012f0003, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0003_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CHeadman_FirecrackerAttack, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x012f0004, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0004_Fire_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0004 +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x012f000d, FALSE, EInternal());return TRUE;}BOOL CHeadman::H0x012f000e_Fire_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f000e +if(!(m_hdtType == HDT_ROCKETMAN )){ Jump(STATE_CURRENT,0x012f000c, FALSE, EInternal());return TRUE;} +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +STATE_CHeadman_RocketmanAttack, TRUE; +Jump(STATE_CURRENT, 0x012f0005, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0005_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CHeadman_RocketmanAttack, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x012f0006, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0006_Fire_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0006 +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x012f000b, FALSE, EInternal());return TRUE;}BOOL CHeadman::H0x012f000c_Fire_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f000c +if(!(m_hdtType == HDT_BOMBERMAN )){ Jump(STATE_CURRENT,0x012f000a, FALSE, EInternal());return TRUE;} +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +STATE_CHeadman_BombermanAttack, TRUE; +Jump(STATE_CURRENT, 0x012f0007, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0007_Fire_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CHeadman_BombermanAttack, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x012f0008, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0008_Fire_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0008 +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x012f0009, FALSE, EInternal());return TRUE;}BOOL CHeadman::H0x012f000a_Fire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f000a +if(m_hdtType == HDT_KAMIKAZE ){ +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +}Jump(STATE_CURRENT,0x012f0009, FALSE, EInternal());return TRUE;} +BOOL CHeadman::H0x012f0009_Fire_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0009 +Jump(STATE_CURRENT,0x012f000b, FALSE, EInternal());return TRUE;} +BOOL CHeadman::H0x012f000b_Fire_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f000b +Jump(STATE_CURRENT,0x012f000d, FALSE, EInternal());return TRUE;} +BOOL CHeadman::H0x012f000d_Fire_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f000d + +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Return(STATE_CURRENT,EReturn ()); +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CHeadman:: +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +BombermanAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHeadman_BombermanAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHeadman::BombermanAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(! IsInFrustum (m_penEnemy , CosFast (80.0f))){ +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Return(STATE_CURRENT,EEnd ()); +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return TRUE; +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.2f + FRnd () / 4); +Jump(STATE_CURRENT, 0x012f0010, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0010_BombermanAttack_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0010 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f0011, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0011_BombermanAttack_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0011 +; +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StartModelAnim (HEADMAN_ANIM_BOMBERMAN_ATTACK , 0); +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PlaySound (m_soSound , SOUND_FIREBOMBERMAN , SOF_3D ); +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.15f); +Jump(STATE_CURRENT, 0x012f0012, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0012_BombermanAttack_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0012 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f0013, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0013_BombermanAttack_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0013 +; +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +AddAttachment (HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND , MODEL_BOMB , TEXTURE_BOMB ); +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.30f); +Jump(STATE_CURRENT, 0x012f0014, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0014_BombermanAttack_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0014 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f0015, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0015_BombermanAttack_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0015 +; +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +RemoveAttachment (HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND ); +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FLOAT fLaunchSpeed ; +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FLOAT fRelativeHdg ; +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CalculateAngularLaunchParams ( +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +GetPlacement () . pl_PositionVector , BOMBERMAN_LAUNCH (2) - 1.5f , +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_penEnemy -> GetPlacement () . pl_PositionVector , FLOAT3D (0 , 0 , 0) , +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +BOMBERMAN_ANGLE , +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +fLaunchSpeed , +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +fRelativeHdg ); +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +EntityInfo * peiTarget = (EntityInfo *) (m_penEnemy -> GetEntityInfo ()); +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FLOAT3D vShootTarget ; +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +GetEntityInfoPosition (m_penEnemy , peiTarget -> vTargetCenter , vShootTarget ); +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CPlacement3D pl ; +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PrepareFreeFlyingProjectile (pl , vShootTarget , BOMBERMAN_LAUNCH , ANGLE3D (0 , BOMBERMAN_ANGLE , 0)); +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +ELaunchProjectile eLaunch ; +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +eLaunch . penLauncher = this ; +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +eLaunch . prtType = PRT_HEADMAN_BOMBERMAN ; +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +eLaunch . fSpeed = fLaunchSpeed ; +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +penProjectile -> Initialize (eLaunch ); +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +RemoveAttachment (HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND ); +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.45f + FRnd () / 2); +Jump(STATE_CURRENT, 0x012f0016, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0016_BombermanAttack_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0016 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f0017, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0017_BombermanAttack_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0017 +; +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Return(STATE_CURRENT,EEnd ()); +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CHeadman:: +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FirecrackerAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHeadman_FirecrackerAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHeadman::FirecrackerAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(- en_vGravityDir % CalcDelta (m_penEnemy ) > CalcDist (m_penEnemy ) / 1.41421f){ +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Return(STATE_CURRENT,EEnd ()); +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return TRUE; +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.2f + FRnd () / 4); +Jump(STATE_CURRENT, 0x012f0019, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0019_FirecrackerAttack_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0019 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f001a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f001a_FirecrackerAttack_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f001a +; +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StartModelAnim (HEADMAN_ANIM_FIRECRACKER_ATTACK , 0); +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.15f); +Jump(STATE_CURRENT, 0x012f001b, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f001b_FirecrackerAttack_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f001b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f001c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f001c_FirecrackerAttack_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f001c +; +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PlaySound (m_soSound , SOUND_FIREFIRECRACKER , SOF_3D ); +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.52f); +Jump(STATE_CURRENT, 0x012f001d, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f001d_FirecrackerAttack_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f001d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f001e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f001e_FirecrackerAttack_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f001e +; +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +ShootProjectile (PRT_HEADMAN_FIRECRACKER , FLOAT3D (0.0f , 0.5f , 0.0f) , ANGLE3D (- 16.0f , 0 , 0)); +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x012f001f, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f001f_FirecrackerAttack_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f001f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f0020, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0020_FirecrackerAttack_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0020 +; +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +ShootProjectile (PRT_HEADMAN_FIRECRACKER , FLOAT3D (0.0f , 0.5f , 0.0f) , ANGLE3D (- 8 , 0 , 0)); +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x012f0021, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0021_FirecrackerAttack_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0021 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f0022, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0022_FirecrackerAttack_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0022 +; +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +ShootProjectile (PRT_HEADMAN_FIRECRACKER , FLOAT3D (0.0f , 0.5f , 0.0f) , ANGLE3D (0.0f , 0 , 0)); +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x012f0023, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0023_FirecrackerAttack_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0023 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f0024, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0024_FirecrackerAttack_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0024 +; +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +ShootProjectile (PRT_HEADMAN_FIRECRACKER , FLOAT3D (0.0f , 0.5f , 0.0f) , ANGLE3D (8.0f , 0 , 0)); +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x012f0025, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0025_FirecrackerAttack_13(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0025 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f0026, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0026_FirecrackerAttack_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0026 +; +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +ShootProjectile (PRT_HEADMAN_FIRECRACKER , FLOAT3D (0.0f , 0.5f , 0.0f) , ANGLE3D (16.0f , 0 , 0)); +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.5f + FRnd () / 3); +Jump(STATE_CURRENT, 0x012f0027, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f0027_FirecrackerAttack_15(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0027 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f0028, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0028_FirecrackerAttack_16(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0028 +; +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Return(STATE_CURRENT,EEnd ()); +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CHeadman:: +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +RocketmanAttack(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHeadman_RocketmanAttack + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHeadman::RocketmanAttack expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StandingAnimFight (); +#line 576 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(0.2f + FRnd () / 4); +Jump(STATE_CURRENT, 0x012f002a, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f002a_RocketmanAttack_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f002a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f002b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f002b_RocketmanAttack_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f002b +; +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StartModelAnim (HEADMAN_ANIM_ROCKETMAN_ATTACK , 0); +#line 579 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +ShootProjectile (PRT_HEADMAN_ROCKETMAN , FLOAT3D (0.0f , 1.0f , 0.0f) , ANGLE3D (0 , 0 , 0)); +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +PlaySound (m_soSound , SOUND_FIREROCKETMAN , SOF_3D ); +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetTimerAfter(1.0f + FRnd () / 3); +Jump(STATE_CURRENT, 0x012f002c, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f002c_RocketmanAttack_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f002c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x012f002d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f002d_RocketmanAttack_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f002d +; +#line 583 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Return(STATE_CURRENT,EEnd ()); +#line 583 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CHeadman:: +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Death(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHeadman_Death + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHeadman::Death expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_KAMIKAZE ){ +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +KamikazeSoundOff (); +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 599 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +STATE_CEnemyBase_Death, FALSE; +Jump(STATE_CURRENT, 0x012f002f, FALSE, EBegin());return TRUE;}BOOL CHeadman::H0x012f002f_Death_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f002f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_Death, FALSE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x012f0030, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CHeadman::H0x012f0030_Death_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x012f0030 +const EEnd&__e= (EEnd&)__eeInput; +; +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +if(m_hdtType == HDT_BOMBERMAN ){ +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Explode (); +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Return(STATE_CURRENT,EEnd ()); +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CHeadman:: +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHeadman_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHeadman::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +InitAsModel (); +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 616 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetCollisionFlags (ECF_MODEL ); +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 618 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetHealth (19.5f); +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fMaxHealth = 19.5f; +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +en_tmMaxHoldBreath = 5.0f; +#line 621 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +en_fDensity = 2000.0f; +#line 622 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fBlowUpSize = 2.0f; +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetModel (MODEL_HEADMAN ); +#line 626 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +switch(m_hdtType ){ +#line 627 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_FIRECRACKER : +#line 629 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetModelMainTexture (TEXTURE_FIRECRACKER ); +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +AddAttachment (HEADMAN_ATTACHMENT_HEAD , MODEL_FIRECRACKERHEAD , TEXTURE_FIRECRACKERHEAD ); +#line 631 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +AddAttachment (HEADMAN_ATTACHMENT_CHAINSAW , MODEL_CHAINSAW , TEXTURE_CHAINSAW ); +#line 633 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fWalkSpeed = FRnd () + 1.5f; +#line 634 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 500.0f); +#line 635 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackRunSpeed = FRnd () + 5.0f; +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseRunSpeed = FRnd () + 5.0f; +#line 638 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 640 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackDistance = 50.0f; +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseDistance = 0.0f; +#line 642 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fStopDistance = 8.0f; +#line 643 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackFireTime = 2.0f; +#line 644 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseFireTime = 1.0f; +#line 645 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fIgnoreRange = 200.0f; +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fBlowUpAmount = 65.0f; +#line 648 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fBodyParts = 4; +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fDamageWounded = 0.0f; +#line 650 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_iScore = 200; +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +break ; +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_ROCKETMAN : +#line 655 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetModelMainTexture (TEXTURE_ROCKETMAN ); +#line 656 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +AddAttachment (HEADMAN_ATTACHMENT_HEAD , MODEL_HEAD , TEXTURE_HEAD ); +#line 657 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +AddAttachment (HEADMAN_ATTACHMENT_ROCKET_LAUNCHER , MODEL_ROCKETLAUNCHER , TEXTURE_ROCKETLAUNCHER ); +#line 659 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fWalkSpeed = FRnd () + 1.5f; +#line 660 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 500.0f); +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackRunSpeed = FRnd () * 2.0f + 6.0f; +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseRunSpeed = FRnd () * 2.0f + 6.0f; +#line 664 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 666 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackDistance = 50.0f; +#line 667 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseDistance = 0.0f; +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fStopDistance = 8.0f; +#line 669 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackFireTime = 2.0f; +#line 670 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseFireTime = 1.0f; +#line 671 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fIgnoreRange = 200.0f; +#line 673 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fBlowUpAmount = 65.0f; +#line 674 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fBodyParts = 4; +#line 675 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fDamageWounded = 0.0f; +#line 676 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_iScore = 100; +#line 677 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +break ; +#line 679 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_BOMBERMAN : +#line 681 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetModelMainTexture (TEXTURE_BOMBERMAN ); +#line 682 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +AddAttachment (HEADMAN_ATTACHMENT_HEAD , MODEL_HEAD , TEXTURE_HEAD ); +#line 684 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fWalkSpeed = FRnd () + 1.5f; +#line 685 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 500.0f); +#line 686 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackRunSpeed = FRnd () + 4.0f; +#line 687 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 688 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseRunSpeed = FRnd () + 4.0f; +#line 689 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 245.0f); +#line 691 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackDistance = 45.0f; +#line 692 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseDistance = 0.0f; +#line 693 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fStopDistance = 20.0f; +#line 694 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackFireTime = 2.0f; +#line 695 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseFireTime = 1.5f; +#line 696 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fIgnoreRange = 150.0f; +#line 698 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fBlowUpAmount = 65.0f; +#line 699 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fBodyParts = 4; +#line 700 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fDamageWounded = 0.0f; +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_iScore = 500; +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +break ; +#line 704 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +case HDT_KAMIKAZE : +#line 706 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +SetModelMainTexture (TEXTURE_KAMIKAZE ); +#line 707 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +AddAttachment (HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND , MODEL_BOMB , TEXTURE_BOMB ); +#line 708 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +AddAttachment (HEADMAN_ATTACHMENT_BOMB_LEFT_HAND , MODEL_BOMB , TEXTURE_BOMB ); +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fWalkSpeed = FRnd () + 1.5f; +#line 711 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 10.0f + 500.0f); +#line 712 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackRunSpeed = FRnd () * 2.0f + 10.0f; +#line 713 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 100 + 600.0f); +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseRunSpeed = FRnd () * 2.0f + 10.0f; +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 100 + 600.0f); +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackDistance = 50.0f; +#line 718 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseDistance = 10.0f; +#line 719 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fStopDistance = 0.0f; +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fAttackFireTime = 2.0f; +#line 721 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fCloseFireTime = 0.5f; +#line 722 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fIgnoreRange = 250.0f; +#line 724 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fBlowUpAmount = 0.0f; +#line 725 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fBodyParts = 4; +#line 726 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_fDamageWounded = 0.0f; +#line 727 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +m_iScore = 2500; +#line 728 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +break ; +#line 729 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +} +#line 732 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +GetModelObject () -> StretchModel (FLOAT3D (1.25f , 1.25f , 1.25f)); +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +ModelChangeNotify (); +#line 734 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StandingAnim (); +#line 737 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Headman.es b/Sources/EntitiesMP/Headman.es new file mode 100644 index 0000000..d2458c1 --- /dev/null +++ b/Sources/EntitiesMP/Headman.es @@ -0,0 +1,739 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +303 +%{ +#include "StdH.h" +#include "Models/Enemies/Headman/Headman.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/BasicEffects"; + +enum HeadmanType { + 0 HDT_FIRECRACKER "Fire Cracker", + 1 HDT_ROCKETMAN "Rocketman", + 2 HDT_BOMBERMAN "Bomberman", + 3 HDT_KAMIKAZE "Kamikaze", +}; + + +%{ +// info structure +static EntityInfo eiHeadman = { + EIBT_FLESH, 100.0f, + 0.0f, 1.9f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +#define EXPLODE_KAMIKAZE 2.5f +#define BOMBERMAN_ANGLE (45.0f) +#define BOMBERMAN_LAUNCH (FLOAT3D(0.0f, 1.5f, 0.0f)) +%} + + +class CHeadman: CEnemyBase { +name "Headman"; +thumbnail "Thumbnails\\Headman.tbn"; + +properties: + 1 enum HeadmanType m_hdtType "Type" 'Y' = HDT_FIRECRACKER, + + // class internal + 5 BOOL m_bExploded = FALSE, + 6 BOOL m_bAttackSound = FALSE, // playing kamikaze yelling sound + +components: + 1 class CLASS_BASE "Classes\\EnemyBase.ecl", + 2 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 3 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + + 10 model MODEL_HEADMAN "Models\\Enemies\\Headman\\Headman.mdl", + 11 model MODEL_HEAD "Models\\Enemies\\Headman\\Head.mdl", + 12 model MODEL_FIRECRACKERHEAD "Models\\Enemies\\Headman\\FirecrackerHead.mdl", + 13 model MODEL_CHAINSAW "Models\\Enemies\\Headman\\ChainSaw.mdl", + 15 model MODEL_ROCKETLAUNCHER "Models\\Enemies\\Headman\\RocketLauncher.mdl", + 17 model MODEL_BOMB "Models\\Enemies\\Headman\\Projectile\\Bomb.mdl", + + 20 texture TEXTURE_BOMBERMAN "Models\\Enemies\\Headman\\Bomberman.tex", + 21 texture TEXTURE_FIRECRACKER "Models\\Enemies\\Headman\\Firecracker.tex", + 22 texture TEXTURE_KAMIKAZE "Models\\Enemies\\Headman\\Kamikaze.tex", + 23 texture TEXTURE_ROCKETMAN "Models\\Enemies\\Headman\\Rocketman.tex", + 24 texture TEXTURE_HEAD "Models\\Enemies\\Headman\\Head.tex", + 25 texture TEXTURE_FIRECRACKERHEAD "Models\\Enemies\\Headman\\FirecrackerHead.tex", + 26 texture TEXTURE_CHAINSAW "Models\\Enemies\\Headman\\Chainsaw.tex", + 28 texture TEXTURE_ROCKETLAUNCHER "Models\\Enemies\\Headman\\RocketLauncher.tex", + 29 texture TEXTURE_BOMB "Models\\Enemies\\Headman\\Projectile\\Bomb.tex", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "Models\\Enemies\\Headman\\Sounds\\Idle.wav", + 51 sound SOUND_IDLEKAMIKAZE "Models\\Enemies\\Headman\\Sounds\\IdleKamikaze.wav", + 52 sound SOUND_SIGHT "Models\\Enemies\\Headman\\Sounds\\Sight.wav", + 53 sound SOUND_WOUND "Models\\Enemies\\Headman\\Sounds\\Wound.wav", + 54 sound SOUND_FIREROCKETMAN "Models\\Enemies\\Headman\\Sounds\\FireRocketman.wav", + 55 sound SOUND_FIREFIRECRACKER "Models\\Enemies\\Headman\\Sounds\\FireFirecracker.wav", + 56 sound SOUND_FIREBOMBERMAN "Models\\Enemies\\Headman\\Sounds\\FireBomberman.wav", + 57 sound SOUND_ATTACKKAMIKAZE "Models\\Enemies\\Headman\\Sounds\\AttackKamikaze.wav", + 58 sound SOUND_DEATH "Models\\Enemies\\Headman\\Sounds\\Death.wav", + + /* + 60 model MODEL_HEADMAN_BODY "Models\\Enemies\\Headman\\Debris\\Torso.mdl", + 61 model MODEL_HEADMAN_HAND "Models\\Enemies\\Headman\\Debris\\Arm.mdl", + 62 model MODEL_HEADMAN_LEGS "Models\\Enemies\\Headman\\Debris\\Leg.mdl", + */ + +functions: + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + if (eDeath.eLastDamage.dmtType==DMT_EXPLOSION) { + if (m_hdtType==HDT_BOMBERMAN) { + str.PrintF(TRANS("%s was bombed by a Bomberman"), strPlayerName); + } else { + str.PrintF(TRANS("%s fell victim of a Kamikaze"), strPlayerName); + } + } else if (m_hdtType==HDT_ROCKETMAN) { + str.PrintF(TRANS("A Rocketeer tickled %s to death"), strPlayerName); + } else if (m_hdtType==HDT_FIRECRACKER) { + str.PrintF(TRANS("A Firecracker tickled %s to death"), strPlayerName); + } + return str; + } + + /* Entity info */ + void *GetEntityInfo(void) { + return &eiHeadman; + }; + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnmRocketman, "Data\\Messages\\Enemies\\Rocketman.txt"); + static DECLARE_CTFILENAME(fnmFirecracker, "Data\\Messages\\Enemies\\Firecracker.txt"); + static DECLARE_CTFILENAME(fnmBomberman, "Data\\Messages\\Enemies\\Bomberman.txt"); + static DECLARE_CTFILENAME(fnmKamikaze, "Data\\Messages\\Enemies\\Kamikaze.txt"); + switch(m_hdtType) { + default: ASSERT(FALSE); + case HDT_ROCKETMAN: return fnmRocketman; + case HDT_FIRECRACKER: return fnmFirecracker; + case HDT_BOMBERMAN: return fnmBomberman; + case HDT_KAMIKAZE: return fnmKamikaze; + } + }; + + void Precache(void) { + CEnemyBase::Precache(); + PrecacheSound(SOUND_IDLE); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_DEATH); + + switch(m_hdtType) { + case HDT_FIRECRACKER: { + PrecacheSound(SOUND_FIREFIRECRACKER); + PrecacheClass(CLASS_PROJECTILE, PRT_HEADMAN_FIRECRACKER); + } break; + case HDT_ROCKETMAN: { + PrecacheSound(SOUND_FIREROCKETMAN); + PrecacheClass(CLASS_PROJECTILE, PRT_HEADMAN_ROCKETMAN); + } break; + case HDT_BOMBERMAN: { + PrecacheSound(SOUND_FIREBOMBERMAN); + PrecacheClass(CLASS_PROJECTILE, PRT_HEADMAN_BOMBERMAN); + PrecacheModel(MODEL_BOMB); + PrecacheTexture(TEXTURE_BOMB); + } break; + case HDT_KAMIKAZE: { + PrecacheSound(SOUND_ATTACKKAMIKAZE); + PrecacheSound(SOUND_IDLEKAMIKAZE); + PrecacheClass(CLASS_BASIC_EFFECT, BET_BOMB); + PrecacheModel(MODEL_BOMB); + PrecacheTexture(TEXTURE_BOMB); + } break; + } + }; + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + CEnemyBase::FillEntityStatistics(pes); + switch(m_hdtType) { + case HDT_FIRECRACKER: { pes->es_strName+=" Firecracker"; } break; + case HDT_ROCKETMAN: { pes->es_strName+=" Rocketman"; } break; + case HDT_BOMBERMAN: { pes->es_strName+=" Bomberman"; } break; + case HDT_KAMIKAZE: { pes->es_strName+=" Kamikaze"; } break; + } + return TRUE; + } + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // firecracker and rocketman can't harm headman + if (!IsOfClass(penInflictor, "Headman") || + !(((CHeadman*)penInflictor)->m_hdtType==HDT_FIRECRACKER || + ((CHeadman*)penInflictor)->m_hdtType==HDT_ROCKETMAN)) { + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + + // if died of chainsaw + if (dmtType==DMT_CHAINSAW && GetHealth()<=0) { + // must always blowup + m_fBlowUpAmount = 0; + } + } + }; + + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim; + if (IRnd()%2) { + iAnim = HEADMAN_ANIM_WOUND1; + } else { + iAnim = HEADMAN_ANIM_WOUND2; + } + StartModelAnim(iAnim, 0); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + INDEX iAnim; + FLOAT3D vFront; + GetHeadingDirection(0, vFront); + FLOAT fDamageDir = m_vDamage%vFront; + if (fDamageDir<0) { + if (Abs(fDamageDir)<10.0f) { + iAnim = HEADMAN_ANIM_DEATH_EASY_FALL_BACK; + } else { + iAnim = HEADMAN_ANIM_DEATH_FALL_BACK; + } + } else { + if (Abs(fDamageDir)<10.0f) { + iAnim = HEADMAN_ANIM_DEATH_EASY_FALL_FORWARD; + } else { + iAnim = HEADMAN_ANIM_DEATH_FALL_ON_KNEES; + } + } + + StartModelAnim(iAnim, 0); + return iAnim; + }; + + FLOAT WaitForDust(FLOAT3D &vStretch) { + vStretch=FLOAT3D(1,1,2); + if(GetModelObject()->GetAnim()==HEADMAN_ANIM_DEATH_EASY_FALL_BACK) + { + vStretch=vStretch*0.3f; + return 0.864f; + } + if(GetModelObject()->GetAnim()==HEADMAN_ANIM_DEATH_FALL_BACK) + { + vStretch=vStretch*0.75f; + return 0.48f; + } + if(GetModelObject()->GetAnim()==HEADMAN_ANIM_DEATH_EASY_FALL_FORWARD) + { + vStretch=vStretch*0.3f; + return 1.12f; + } + else if(GetModelObject()->GetAnim()==HEADMAN_ANIM_DEATH_FALL_ON_KNEES) + { + vStretch=vStretch*0.75f; + return 1.035f; + } + return -1.0f; + }; + + // should this enemy blow up (spawn debris) + BOOL ShouldBlowUp(void) + { + if (m_hdtType==HDT_KAMIKAZE && GetHealth()<=0) { + return TRUE; + } else { + return CEnemyBase::ShouldBlowUp(); + } + } + + void DeathNotify(void) { + ChangeCollisionBoxIndexWhenPossible(HEADMAN_COLLISION_BOX_DEATH); + en_fDensity = 500.0f; + }; + + // virtual anim functions + void StandingAnim(void) { + StartModelAnim(HEADMAN_ANIM_IDLE_PATROL, AOF_LOOPING|AOF_NORESTART); + if (m_hdtType==HDT_KAMIKAZE) { + KamikazeSoundOff(); + } + }; + void StandingAnimFight(void) + { + StartModelAnim(HEADMAN_ANIM_IDLE_FIGHT, AOF_LOOPING|AOF_NORESTART); + if (m_hdtType==HDT_KAMIKAZE) { + KamikazeSoundOff(); + } + } + void WalkingAnim(void) { + StartModelAnim(HEADMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART); + }; + void RunningAnim(void) { + if (m_hdtType==HDT_KAMIKAZE) { + KamikazeSoundOn(); + StartModelAnim(HEADMAN_ANIM_KAMIKAZE_ATTACK, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(HEADMAN_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); + } + }; + void RotatingAnim(void) { + RunningAnim(); + }; + + // virtual sound functions + void IdleSound(void) { + if (m_bAttackSound) { + return; + } + if (m_hdtType==HDT_KAMIKAZE) { + PlaySound(m_soSound, SOUND_IDLEKAMIKAZE, SOF_3D); + } else { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + } + }; + void SightSound(void) { + if (m_bAttackSound) { + return; + } + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + if (m_bAttackSound) { + return; + } + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + if (m_bAttackSound) { + return; + } + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + void KamikazeSoundOn(void) { + if (!m_bAttackSound) { + m_bAttackSound = TRUE; + PlaySound(m_soSound, SOUND_ATTACKKAMIKAZE, SOF_3D|SOF_LOOP); + } + } + void KamikazeSoundOff(void) { + if (m_bAttackSound) { + m_soSound.Stop(); + m_bAttackSound = FALSE; + } + } + +/************************************************************ + * BLOW UP FUNCTIONS * + ************************************************************/ + void BlowUpNotify(void) { + // kamikaze and bomberman explode if is not already exploded + if (m_hdtType==HDT_KAMIKAZE || m_hdtType==HDT_BOMBERMAN) { + Explode(); + } + }; + + // spawn body parts + /*void BlowUp(void) + { + if( m_hdtType==HDT_FIRECRACKER || m_hdtType==HDT_ROCKETMAN) + { + // get your size + FLOATaabbox3D box; + GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm(); + + FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(m_fBlowUpAmount/m_vDamage.Length()); + vNormalizedDamage /= Sqrt(vNormalizedDamage.Length()); + + vNormalizedDamage *= 0.75f; + + FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute); + + // spawn debris + Debris_Begin(EIBT_FLESH, DPT_BLOODTRAIL, BET_BLOODSTAIN, fEntitySize, vNormalizedDamage, vBodySpeed, 5.0f, 2.0f); + + INDEX iTextureID = TEXTURE_ROCKETMAN; + if( m_hdtType==HDT_FIRECRACKER) + { + iTextureID = TEXTURE_FIRECRACKER; + } + + Debris_Spawn(this, this, MODEL_HEADMAN_BODY, iTextureID, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_HEADMAN_HAND, iTextureID, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_HEADMAN_HAND, iTextureID, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_HEADMAN_LEGS, iTextureID, 0, 0, 0, 0, 0.0f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + + // hide yourself (must do this after spawning debris) + SwitchToEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + } + else + { + CEnemyBase::BlowUp(); + } + };*/ + + // bomberman and kamikaze explode only once + void Explode(void) { + if (!m_bExploded) { + m_bExploded = TRUE; + + // inflict damage + FLOAT3D vSource; + GetEntityInfoPosition(this, eiHeadman.vTargetCenter, vSource); + if (m_hdtType==HDT_BOMBERMAN) { + InflictDirectDamage(this, this, DMT_EXPLOSION, 100.0f, vSource, + -en_vGravityDir); + InflictRangeDamage(this, DMT_EXPLOSION, 15.0f, vSource, 1.0f, 6.0f); + } else { + InflictDirectDamage(this, this, DMT_CLOSERANGE, 100.0f, vSource, + -en_vGravityDir); + InflictRangeDamage(this, DMT_EXPLOSION, 30.0f, vSource, 2.75f, 8.0f); + } + + // spawn explosion + CPlacement3D plExplosion = GetPlacement(); + CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_BOMB; + eSpawnEffect.vStretch = FLOAT3D(1.0f,1.0f,1.0f); + penExplosion->Initialize(eSpawnEffect); + + // explosion debris + eSpawnEffect.betType = BET_EXPLOSION_DEBRIS; + CEntityPointer penExplosionDebris = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosionDebris->Initialize(eSpawnEffect); + + // explosion smoke + eSpawnEffect.betType = BET_EXPLOSION_SMOKE; + CEntityPointer penExplosionSmoke = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosionSmoke->Initialize(eSpawnEffect); + } + }; + +// ****** +// overrides from CEnemyBase to provide exploding on close range + + // set speeds for movement towards desired position + void SetSpeedsToDesiredPosition(const FLOAT3D &vPosDelta, FLOAT fPosDistance, BOOL bGoingToPlayer) + { + // if very close to player + if (m_hdtType==HDT_KAMIKAZE && CalcDist(m_penEnemy) < EXPLODE_KAMIKAZE) { + // explode + SetHealth(-10000.0f); + m_vDamage = FLOAT3D(0,10000,0); + SendEvent(EDeath()); + + // if not close + } else { + // behave as usual + CEnemyBase::SetSpeedsToDesiredPosition(vPosDelta, fPosDistance, bGoingToPlayer); + } + } + + // get movement frequency for attack + virtual FLOAT GetAttackMoveFrequency(FLOAT fEnemyDistance) + { + // kamikaze must have sharp reflexes when close + if (m_hdtType==HDT_KAMIKAZE && fEnemyDistance < m_fCloseDistance) { + return 0.1f; + } else { + return CEnemyBase::GetAttackMoveFrequency(fEnemyDistance); + } + } + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + InitializeAttack(EVoid) : CEnemyBase::InitializeAttack { + if (m_hdtType==HDT_KAMIKAZE) { + KamikazeSoundOn(); + } + jump CEnemyBase::InitializeAttack(); + }; + + StopAttack(EVoid) : CEnemyBase::StopAttack { + KamikazeSoundOff(); + jump CEnemyBase::StopAttack(); + }; + + Fire(EVoid) : CEnemyBase::Fire { + // firecracker + if (m_hdtType == HDT_FIRECRACKER) { + autocall FirecrackerAttack() EEnd; + // rocketman + } else if (m_hdtType == HDT_ROCKETMAN) { + autocall RocketmanAttack() EEnd; + // bomber + } else if (m_hdtType == HDT_BOMBERMAN) { + autocall BombermanAttack() EEnd; + // kamikaze + } else if (m_hdtType == HDT_KAMIKAZE) { + } + + return EReturn(); + }; + + // Bomberman attack + BombermanAttack(EVoid) { + // don't shoot if enemy above or below you too much + if ( !IsInFrustum(m_penEnemy, CosFast(80.0f)) ) { + return EEnd(); + } + + autowait(0.2f + FRnd()/4); + + StartModelAnim(HEADMAN_ANIM_BOMBERMAN_ATTACK, 0); + PlaySound(m_soSound, SOUND_FIREBOMBERMAN, SOF_3D); + autowait(0.15f); + + AddAttachment(HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND, MODEL_BOMB, TEXTURE_BOMB); + autowait(0.30f); + RemoveAttachment(HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND); + + // hit bomb + // calculate launch velocity and heading correction for angular launch + FLOAT fLaunchSpeed; + FLOAT fRelativeHdg; + CalculateAngularLaunchParams( + GetPlacement().pl_PositionVector, BOMBERMAN_LAUNCH(2)-1.5f, + m_penEnemy->GetPlacement().pl_PositionVector, FLOAT3D(0,0,0), + BOMBERMAN_ANGLE, + fLaunchSpeed, + fRelativeHdg); + + // target enemy body + EntityInfo *peiTarget = (EntityInfo*) (m_penEnemy->GetEntityInfo()); + FLOAT3D vShootTarget; + GetEntityInfoPosition(m_penEnemy, peiTarget->vTargetCenter, vShootTarget); + // launch + CPlacement3D pl; + PrepareFreeFlyingProjectile(pl, vShootTarget, BOMBERMAN_LAUNCH, ANGLE3D(0, BOMBERMAN_ANGLE, 0)); + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_HEADMAN_BOMBERMAN; + eLaunch.fSpeed = fLaunchSpeed; + penProjectile->Initialize(eLaunch); + + // safety remove - if hitted (EWounded) while have bomb in his hand, bomb will never be removed + RemoveAttachment(HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND); + + autowait(0.45f + FRnd()/2); + return EEnd(); + }; + + // Firecraker attack + FirecrackerAttack(EVoid) { + // don't shoot if enemy above you more than quare of two far from you + if (-en_vGravityDir%CalcDelta(m_penEnemy) > CalcDist(m_penEnemy)/1.41421f) { + return EEnd(); + } + + autowait(0.2f + FRnd()/4); + + StartModelAnim(HEADMAN_ANIM_FIRECRACKER_ATTACK, 0); + autowait(0.15f); + PlaySound(m_soSound, SOUND_FIREFIRECRACKER, SOF_3D); + autowait(0.52f); + ShootProjectile(PRT_HEADMAN_FIRECRACKER, FLOAT3D(0.0f, 0.5f, 0.0f), ANGLE3D(-16.0f, 0, 0)); + + autowait(0.05f); + ShootProjectile(PRT_HEADMAN_FIRECRACKER, FLOAT3D(0.0f, 0.5f, 0.0f), ANGLE3D(-8, 0, 0)); + + autowait(0.05f); + ShootProjectile(PRT_HEADMAN_FIRECRACKER, FLOAT3D(0.0f, 0.5f, 0.0f), ANGLE3D(0.0f, 0, 0)); + + autowait(0.05f); + ShootProjectile(PRT_HEADMAN_FIRECRACKER, FLOAT3D(0.0f, 0.5f, 0.0f), ANGLE3D(8.0f, 0, 0)); + + autowait(0.05f); + ShootProjectile(PRT_HEADMAN_FIRECRACKER, FLOAT3D(0.0f, 0.5f, 0.0f), ANGLE3D(16.0f, 0, 0)); + + autowait(0.5f + FRnd()/3); + return EEnd(); + }; + + // Rocketman attack + RocketmanAttack(EVoid) { + StandingAnimFight(); //StartModelAnim(_ANIM_STAND, AOF_LOOPING|AOF_NORESTART); + autowait(0.2f + FRnd()/4); + + StartModelAnim(HEADMAN_ANIM_ROCKETMAN_ATTACK, 0); + ShootProjectile(PRT_HEADMAN_ROCKETMAN, FLOAT3D(0.0f, 1.0f, 0.0f), ANGLE3D(0, 0, 0)); + PlaySound(m_soSound, SOUND_FIREROCKETMAN, SOF_3D); + + autowait(1.0f + FRnd()/3); + return EEnd(); + }; + + + +/************************************************************ + * D E A T H * + ************************************************************/ + Death(EVoid) : CEnemyBase::Death { + // don't check this because summoner can send death event even to kamikaze + // ASSERT(m_hdtType!=HDT_KAMIKAZE); + // instead, stop playing the yelling sound + if (m_hdtType==HDT_KAMIKAZE) { + KamikazeSoundOff(); + } + // death + autocall CEnemyBase::Death() EEnd; + // bomberman explode + if (m_hdtType==HDT_BOMBERMAN) { + Explode(); + } + return EEnd(); + }; + + + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + SetHealth(19.5f); + m_fMaxHealth = 19.5f; + en_tmMaxHoldBreath = 5.0f; + en_fDensity = 2000.0f; + m_fBlowUpSize = 2.0f; + + // set your appearance + SetModel(MODEL_HEADMAN); + switch (m_hdtType) { + case HDT_FIRECRACKER: + // set your texture + SetModelMainTexture(TEXTURE_FIRECRACKER); + AddAttachment(HEADMAN_ATTACHMENT_HEAD, MODEL_FIRECRACKERHEAD, TEXTURE_FIRECRACKERHEAD); + AddAttachment(HEADMAN_ATTACHMENT_CHAINSAW, MODEL_CHAINSAW, TEXTURE_CHAINSAW); + // setup moving speed + m_fWalkSpeed = FRnd() + 1.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f); + m_fAttackRunSpeed = FRnd() + 5.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + m_fCloseRunSpeed = FRnd() + 5.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + // setup attack distances + m_fAttackDistance = 50.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 8.0f; + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 200.0f; + // damage/explode properties + m_fBlowUpAmount = 65.0f; + m_fBodyParts = 4; + m_fDamageWounded = 0.0f; + m_iScore = 200; + break; + + case HDT_ROCKETMAN: + // set your texture + SetModelMainTexture(TEXTURE_ROCKETMAN); + AddAttachment(HEADMAN_ATTACHMENT_HEAD, MODEL_HEAD, TEXTURE_HEAD); + AddAttachment(HEADMAN_ATTACHMENT_ROCKET_LAUNCHER, MODEL_ROCKETLAUNCHER, TEXTURE_ROCKETLAUNCHER); + // setup moving speed + m_fWalkSpeed = FRnd() + 1.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f); + m_fAttackRunSpeed = FRnd()*2.0f + 6.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + m_fCloseRunSpeed = FRnd()*2.0f + 6.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + // setup attack distances + m_fAttackDistance = 50.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 8.0f; + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 200.0f; + // damage/explode properties + m_fBlowUpAmount = 65.0f; + m_fBodyParts = 4; + m_fDamageWounded = 0.0f; + m_iScore = 100; + break; + + case HDT_BOMBERMAN: + // set your texture + SetModelMainTexture(TEXTURE_BOMBERMAN); + AddAttachment(HEADMAN_ATTACHMENT_HEAD, MODEL_HEAD, TEXTURE_HEAD); + // setup moving speed + m_fWalkSpeed = FRnd() + 1.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f); + m_fAttackRunSpeed = FRnd() + 4.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + m_fCloseRunSpeed = FRnd() + 4.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 245.0f); + // setup attack distances + m_fAttackDistance = 45.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 20.0f; + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 1.5f; + m_fIgnoreRange = 150.0f; + // damage/explode properties + m_fBlowUpAmount = 65.0f; + m_fBodyParts = 4; + m_fDamageWounded = 0.0f; + m_iScore = 500; + break; + + case HDT_KAMIKAZE: + // set your texture + SetModelMainTexture(TEXTURE_KAMIKAZE); + AddAttachment(HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND, MODEL_BOMB, TEXTURE_BOMB); + AddAttachment(HEADMAN_ATTACHMENT_BOMB_LEFT_HAND, MODEL_BOMB, TEXTURE_BOMB); + // setup moving speed + m_fWalkSpeed = FRnd() + 1.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*10.0f + 500.0f); + m_fAttackRunSpeed = FRnd()*2.0f + 10.0f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*100 + 600.0f); + m_fCloseRunSpeed = FRnd()*2.0f + 10.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*100 + 600.0f); + // setup attack distances + m_fAttackDistance = 50.0f; + m_fCloseDistance = 10.0f; + m_fStopDistance = 0.0f; + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 0.5f; + m_fIgnoreRange = 250.0f; + // damage/explode properties + m_fBlowUpAmount = 0.0f; + m_fBodyParts = 4; + m_fDamageWounded = 0.0f; + m_iScore = 2500; + break; + } + + // set stretch factors for height and width + GetModelObject()->StretchModel(FLOAT3D(1.25f, 1.25f, 1.25f)); + ModelChangeNotify(); + StandingAnim(); + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Headman.h b/Sources/EntitiesMP/Headman.h new file mode 100644 index 0000000..dac3035 --- /dev/null +++ b/Sources/EntitiesMP/Headman.h @@ -0,0 +1,179 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Headman_INCLUDED +#define _EntitiesMP_Headman_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType HeadmanType_enum; +enum HeadmanType { + HDT_FIRECRACKER = 0, + HDT_ROCKETMAN = 1, + HDT_BOMBERMAN = 2, + HDT_KAMIKAZE = 3, +}; +DECL_DLL inline void ClearToDefault(HeadmanType &e) { e = (HeadmanType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CHeadman_DLLClass; +class CHeadman : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum HeadmanType m_hdtType; + BOOL m_bExploded; + BOOL m_bAttackSound; + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void * GetEntityInfo(void); + +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void Precache(void); + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +INDEX AnimForDeath(void); + +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +BOOL ShouldBlowUp(void); + +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void DeathNotify(void); + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void StandingAnim(void); + +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void StandingAnimFight(void); + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void WalkingAnim(void); + +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void RunningAnim(void); + +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void RotatingAnim(void); + +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void IdleSound(void); + +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void SightSound(void); + +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void WoundSound(void); + +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void DeathSound(void); + +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void KamikazeSoundOn(void); + +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void KamikazeSoundOff(void); + +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void BlowUpNotify(void); + +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void Explode(void); + +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +void SetSpeedsToDesiredPosition(const FLOAT3D & vPosDelta,FLOAT fPosDistance,BOOL bGoingToPlayer); + +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +virtual FLOAT GetAttackMoveFrequency(FLOAT fEnemyDistance); +#define STATE_CHeadman_InitializeAttack 0x012f0000 + BOOL +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +InitializeAttack(const CEntityEvent &__eeInput); +#define STATE_CHeadman_StopAttack 0x012f0001 + BOOL +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StopAttack(const CEntityEvent &__eeInput); +#define STATE_CHeadman_Fire 0x012f0002 + BOOL +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x012f0003_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x012f0004_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x012f0005_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x012f0006_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x012f0007_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x012f0008_Fire_06(const CEntityEvent &__eeInput); + BOOL H0x012f0009_Fire_07(const CEntityEvent &__eeInput); + BOOL H0x012f000a_Fire_08(const CEntityEvent &__eeInput); + BOOL H0x012f000b_Fire_09(const CEntityEvent &__eeInput); + BOOL H0x012f000c_Fire_10(const CEntityEvent &__eeInput); + BOOL H0x012f000d_Fire_11(const CEntityEvent &__eeInput); + BOOL H0x012f000e_Fire_12(const CEntityEvent &__eeInput); +#define STATE_CHeadman_BombermanAttack 0x012f000f + BOOL +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +BombermanAttack(const CEntityEvent &__eeInput); + BOOL H0x012f0010_BombermanAttack_01(const CEntityEvent &__eeInput); + BOOL H0x012f0011_BombermanAttack_02(const CEntityEvent &__eeInput); + BOOL H0x012f0012_BombermanAttack_03(const CEntityEvent &__eeInput); + BOOL H0x012f0013_BombermanAttack_04(const CEntityEvent &__eeInput); + BOOL H0x012f0014_BombermanAttack_05(const CEntityEvent &__eeInput); + BOOL H0x012f0015_BombermanAttack_06(const CEntityEvent &__eeInput); + BOOL H0x012f0016_BombermanAttack_07(const CEntityEvent &__eeInput); + BOOL H0x012f0017_BombermanAttack_08(const CEntityEvent &__eeInput); +#define STATE_CHeadman_FirecrackerAttack 0x012f0018 + BOOL +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FirecrackerAttack(const CEntityEvent &__eeInput); + BOOL H0x012f0019_FirecrackerAttack_01(const CEntityEvent &__eeInput); + BOOL H0x012f001a_FirecrackerAttack_02(const CEntityEvent &__eeInput); + BOOL H0x012f001b_FirecrackerAttack_03(const CEntityEvent &__eeInput); + BOOL H0x012f001c_FirecrackerAttack_04(const CEntityEvent &__eeInput); + BOOL H0x012f001d_FirecrackerAttack_05(const CEntityEvent &__eeInput); + BOOL H0x012f001e_FirecrackerAttack_06(const CEntityEvent &__eeInput); + BOOL H0x012f001f_FirecrackerAttack_07(const CEntityEvent &__eeInput); + BOOL H0x012f0020_FirecrackerAttack_08(const CEntityEvent &__eeInput); + BOOL H0x012f0021_FirecrackerAttack_09(const CEntityEvent &__eeInput); + BOOL H0x012f0022_FirecrackerAttack_10(const CEntityEvent &__eeInput); + BOOL H0x012f0023_FirecrackerAttack_11(const CEntityEvent &__eeInput); + BOOL H0x012f0024_FirecrackerAttack_12(const CEntityEvent &__eeInput); + BOOL H0x012f0025_FirecrackerAttack_13(const CEntityEvent &__eeInput); + BOOL H0x012f0026_FirecrackerAttack_14(const CEntityEvent &__eeInput); + BOOL H0x012f0027_FirecrackerAttack_15(const CEntityEvent &__eeInput); + BOOL H0x012f0028_FirecrackerAttack_16(const CEntityEvent &__eeInput); +#define STATE_CHeadman_RocketmanAttack 0x012f0029 + BOOL +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +RocketmanAttack(const CEntityEvent &__eeInput); + BOOL H0x012f002a_RocketmanAttack_01(const CEntityEvent &__eeInput); + BOOL H0x012f002b_RocketmanAttack_02(const CEntityEvent &__eeInput); + BOOL H0x012f002c_RocketmanAttack_03(const CEntityEvent &__eeInput); + BOOL H0x012f002d_RocketmanAttack_04(const CEntityEvent &__eeInput); +#define STATE_CHeadman_Death 0x012f002e + BOOL +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Death(const CEntityEvent &__eeInput); + BOOL H0x012f002f_Death_01(const CEntityEvent &__eeInput); + BOOL H0x012f0030_Death_02(const CEntityEvent &__eeInput); +#define STATE_CHeadman_Main 1 + BOOL +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Headman_INCLUDED diff --git a/Sources/EntitiesMP/Headman_tables.h b/Sources/EntitiesMP/Headman_tables.h new file mode 100644 index 0000000..4ba6c00 --- /dev/null +++ b/Sources/EntitiesMP/Headman_tables.h @@ -0,0 +1,158 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(HeadmanType) + EP_ENUMVALUE(HDT_FIRECRACKER, "Fire Cracker"), + EP_ENUMVALUE(HDT_ROCKETMAN, "Rocketman"), + EP_ENUMVALUE(HDT_BOMBERMAN, "Bomberman"), + EP_ENUMVALUE(HDT_KAMIKAZE, "Kamikaze"), +EP_ENUMEND(HeadmanType); + +#define ENTITYCLASS CHeadman + +CEntityProperty CHeadman_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &HeadmanType_enum, (0x0000012f<<8)+1, offsetof(CHeadman, m_hdtType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000012f<<8)+5, offsetof(CHeadman, m_bExploded), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000012f<<8)+6, offsetof(CHeadman, m_bAttackSound), "", 0, 0, 0), +}; +#define CHeadman_propertiesct ARRAYCOUNT(CHeadman_properties) + +CEntityComponent CHeadman_components[] = { +#define CLASS_BASE ((0x0000012f<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_BASIC_EFFECT ((0x0000012f<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_PROJECTILE ((0x0000012f<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define MODEL_HEADMAN ((0x0000012f<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_HEADMAN, "EFNM" "Models\\Enemies\\Headman\\Headman.mdl"), +#define MODEL_HEAD ((0x0000012f<<8)+11) + CEntityComponent(ECT_MODEL, MODEL_HEAD, "EFNM" "Models\\Enemies\\Headman\\Head.mdl"), +#define MODEL_FIRECRACKERHEAD ((0x0000012f<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_FIRECRACKERHEAD, "EFNM" "Models\\Enemies\\Headman\\FirecrackerHead.mdl"), +#define MODEL_CHAINSAW ((0x0000012f<<8)+13) + CEntityComponent(ECT_MODEL, MODEL_CHAINSAW, "EFNM" "Models\\Enemies\\Headman\\ChainSaw.mdl"), +#define MODEL_ROCKETLAUNCHER ((0x0000012f<<8)+15) + CEntityComponent(ECT_MODEL, MODEL_ROCKETLAUNCHER, "EFNM" "Models\\Enemies\\Headman\\RocketLauncher.mdl"), +#define MODEL_BOMB ((0x0000012f<<8)+17) + CEntityComponent(ECT_MODEL, MODEL_BOMB, "EFNM" "Models\\Enemies\\Headman\\Projectile\\Bomb.mdl"), +#define TEXTURE_BOMBERMAN ((0x0000012f<<8)+20) + CEntityComponent(ECT_TEXTURE, TEXTURE_BOMBERMAN, "EFNM" "Models\\Enemies\\Headman\\Bomberman.tex"), +#define TEXTURE_FIRECRACKER ((0x0000012f<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_FIRECRACKER, "EFNM" "Models\\Enemies\\Headman\\Firecracker.tex"), +#define TEXTURE_KAMIKAZE ((0x0000012f<<8)+22) + CEntityComponent(ECT_TEXTURE, TEXTURE_KAMIKAZE, "EFNM" "Models\\Enemies\\Headman\\Kamikaze.tex"), +#define TEXTURE_ROCKETMAN ((0x0000012f<<8)+23) + CEntityComponent(ECT_TEXTURE, TEXTURE_ROCKETMAN, "EFNM" "Models\\Enemies\\Headman\\Rocketman.tex"), +#define TEXTURE_HEAD ((0x0000012f<<8)+24) + CEntityComponent(ECT_TEXTURE, TEXTURE_HEAD, "EFNM" "Models\\Enemies\\Headman\\Head.tex"), +#define TEXTURE_FIRECRACKERHEAD ((0x0000012f<<8)+25) + CEntityComponent(ECT_TEXTURE, TEXTURE_FIRECRACKERHEAD, "EFNM" "Models\\Enemies\\Headman\\FirecrackerHead.tex"), +#define TEXTURE_CHAINSAW ((0x0000012f<<8)+26) + CEntityComponent(ECT_TEXTURE, TEXTURE_CHAINSAW, "EFNM" "Models\\Enemies\\Headman\\Chainsaw.tex"), +#define TEXTURE_ROCKETLAUNCHER ((0x0000012f<<8)+28) + CEntityComponent(ECT_TEXTURE, TEXTURE_ROCKETLAUNCHER, "EFNM" "Models\\Enemies\\Headman\\RocketLauncher.tex"), +#define TEXTURE_BOMB ((0x0000012f<<8)+29) + CEntityComponent(ECT_TEXTURE, TEXTURE_BOMB, "EFNM" "Models\\Enemies\\Headman\\Projectile\\Bomb.tex"), +#define SOUND_IDLE ((0x0000012f<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "Models\\Enemies\\Headman\\Sounds\\Idle.wav"), +#define SOUND_IDLEKAMIKAZE ((0x0000012f<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_IDLEKAMIKAZE, "EFNM" "Models\\Enemies\\Headman\\Sounds\\IdleKamikaze.wav"), +#define SOUND_SIGHT ((0x0000012f<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "Models\\Enemies\\Headman\\Sounds\\Sight.wav"), +#define SOUND_WOUND ((0x0000012f<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "Models\\Enemies\\Headman\\Sounds\\Wound.wav"), +#define SOUND_FIREROCKETMAN ((0x0000012f<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_FIREROCKETMAN, "EFNM" "Models\\Enemies\\Headman\\Sounds\\FireRocketman.wav"), +#define SOUND_FIREFIRECRACKER ((0x0000012f<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_FIREFIRECRACKER, "EFNM" "Models\\Enemies\\Headman\\Sounds\\FireFirecracker.wav"), +#define SOUND_FIREBOMBERMAN ((0x0000012f<<8)+56) + CEntityComponent(ECT_SOUND, SOUND_FIREBOMBERMAN, "EFNM" "Models\\Enemies\\Headman\\Sounds\\FireBomberman.wav"), +#define SOUND_ATTACKKAMIKAZE ((0x0000012f<<8)+57) + CEntityComponent(ECT_SOUND, SOUND_ATTACKKAMIKAZE, "EFNM" "Models\\Enemies\\Headman\\Sounds\\AttackKamikaze.wav"), +#define SOUND_DEATH ((0x0000012f<<8)+58) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "Models\\Enemies\\Headman\\Sounds\\Death.wav"), +}; +#define CHeadman_componentsct ARRAYCOUNT(CHeadman_components) + +CEventHandlerEntry CHeadman_handlers[] = { + {0x012f0000, STATE_CEnemyBase_InitializeAttack, CEntity::pEventHandler(&CHeadman:: +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +InitializeAttack),DEBUGSTRING("CHeadman::InitializeAttack")}, + {0x012f0001, STATE_CEnemyBase_StopAttack, CEntity::pEventHandler(&CHeadman:: +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +StopAttack),DEBUGSTRING("CHeadman::StopAttack")}, + {0x012f0002, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CHeadman:: +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Fire),DEBUGSTRING("CHeadman::Fire")}, + {0x012f0003, -1, CEntity::pEventHandler(&CHeadman::H0x012f0003_Fire_01), DEBUGSTRING("CHeadman::H0x012f0003_Fire_01")}, + {0x012f0004, -1, CEntity::pEventHandler(&CHeadman::H0x012f0004_Fire_02), DEBUGSTRING("CHeadman::H0x012f0004_Fire_02")}, + {0x012f0005, -1, CEntity::pEventHandler(&CHeadman::H0x012f0005_Fire_03), DEBUGSTRING("CHeadman::H0x012f0005_Fire_03")}, + {0x012f0006, -1, CEntity::pEventHandler(&CHeadman::H0x012f0006_Fire_04), DEBUGSTRING("CHeadman::H0x012f0006_Fire_04")}, + {0x012f0007, -1, CEntity::pEventHandler(&CHeadman::H0x012f0007_Fire_05), DEBUGSTRING("CHeadman::H0x012f0007_Fire_05")}, + {0x012f0008, -1, CEntity::pEventHandler(&CHeadman::H0x012f0008_Fire_06), DEBUGSTRING("CHeadman::H0x012f0008_Fire_06")}, + {0x012f0009, -1, CEntity::pEventHandler(&CHeadman::H0x012f0009_Fire_07), DEBUGSTRING("CHeadman::H0x012f0009_Fire_07")}, + {0x012f000a, -1, CEntity::pEventHandler(&CHeadman::H0x012f000a_Fire_08), DEBUGSTRING("CHeadman::H0x012f000a_Fire_08")}, + {0x012f000b, -1, CEntity::pEventHandler(&CHeadman::H0x012f000b_Fire_09), DEBUGSTRING("CHeadman::H0x012f000b_Fire_09")}, + {0x012f000c, -1, CEntity::pEventHandler(&CHeadman::H0x012f000c_Fire_10), DEBUGSTRING("CHeadman::H0x012f000c_Fire_10")}, + {0x012f000d, -1, CEntity::pEventHandler(&CHeadman::H0x012f000d_Fire_11), DEBUGSTRING("CHeadman::H0x012f000d_Fire_11")}, + {0x012f000e, -1, CEntity::pEventHandler(&CHeadman::H0x012f000e_Fire_12), DEBUGSTRING("CHeadman::H0x012f000e_Fire_12")}, + {0x012f000f, -1, CEntity::pEventHandler(&CHeadman:: +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +BombermanAttack),DEBUGSTRING("CHeadman::BombermanAttack")}, + {0x012f0010, -1, CEntity::pEventHandler(&CHeadman::H0x012f0010_BombermanAttack_01), DEBUGSTRING("CHeadman::H0x012f0010_BombermanAttack_01")}, + {0x012f0011, -1, CEntity::pEventHandler(&CHeadman::H0x012f0011_BombermanAttack_02), DEBUGSTRING("CHeadman::H0x012f0011_BombermanAttack_02")}, + {0x012f0012, -1, CEntity::pEventHandler(&CHeadman::H0x012f0012_BombermanAttack_03), DEBUGSTRING("CHeadman::H0x012f0012_BombermanAttack_03")}, + {0x012f0013, -1, CEntity::pEventHandler(&CHeadman::H0x012f0013_BombermanAttack_04), DEBUGSTRING("CHeadman::H0x012f0013_BombermanAttack_04")}, + {0x012f0014, -1, CEntity::pEventHandler(&CHeadman::H0x012f0014_BombermanAttack_05), DEBUGSTRING("CHeadman::H0x012f0014_BombermanAttack_05")}, + {0x012f0015, -1, CEntity::pEventHandler(&CHeadman::H0x012f0015_BombermanAttack_06), DEBUGSTRING("CHeadman::H0x012f0015_BombermanAttack_06")}, + {0x012f0016, -1, CEntity::pEventHandler(&CHeadman::H0x012f0016_BombermanAttack_07), DEBUGSTRING("CHeadman::H0x012f0016_BombermanAttack_07")}, + {0x012f0017, -1, CEntity::pEventHandler(&CHeadman::H0x012f0017_BombermanAttack_08), DEBUGSTRING("CHeadman::H0x012f0017_BombermanAttack_08")}, + {0x012f0018, -1, CEntity::pEventHandler(&CHeadman:: +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +FirecrackerAttack),DEBUGSTRING("CHeadman::FirecrackerAttack")}, + {0x012f0019, -1, CEntity::pEventHandler(&CHeadman::H0x012f0019_FirecrackerAttack_01), DEBUGSTRING("CHeadman::H0x012f0019_FirecrackerAttack_01")}, + {0x012f001a, -1, CEntity::pEventHandler(&CHeadman::H0x012f001a_FirecrackerAttack_02), DEBUGSTRING("CHeadman::H0x012f001a_FirecrackerAttack_02")}, + {0x012f001b, -1, CEntity::pEventHandler(&CHeadman::H0x012f001b_FirecrackerAttack_03), DEBUGSTRING("CHeadman::H0x012f001b_FirecrackerAttack_03")}, + {0x012f001c, -1, CEntity::pEventHandler(&CHeadman::H0x012f001c_FirecrackerAttack_04), DEBUGSTRING("CHeadman::H0x012f001c_FirecrackerAttack_04")}, + {0x012f001d, -1, CEntity::pEventHandler(&CHeadman::H0x012f001d_FirecrackerAttack_05), DEBUGSTRING("CHeadman::H0x012f001d_FirecrackerAttack_05")}, + {0x012f001e, -1, CEntity::pEventHandler(&CHeadman::H0x012f001e_FirecrackerAttack_06), DEBUGSTRING("CHeadman::H0x012f001e_FirecrackerAttack_06")}, + {0x012f001f, -1, CEntity::pEventHandler(&CHeadman::H0x012f001f_FirecrackerAttack_07), DEBUGSTRING("CHeadman::H0x012f001f_FirecrackerAttack_07")}, + {0x012f0020, -1, CEntity::pEventHandler(&CHeadman::H0x012f0020_FirecrackerAttack_08), DEBUGSTRING("CHeadman::H0x012f0020_FirecrackerAttack_08")}, + {0x012f0021, -1, CEntity::pEventHandler(&CHeadman::H0x012f0021_FirecrackerAttack_09), DEBUGSTRING("CHeadman::H0x012f0021_FirecrackerAttack_09")}, + {0x012f0022, -1, CEntity::pEventHandler(&CHeadman::H0x012f0022_FirecrackerAttack_10), DEBUGSTRING("CHeadman::H0x012f0022_FirecrackerAttack_10")}, + {0x012f0023, -1, CEntity::pEventHandler(&CHeadman::H0x012f0023_FirecrackerAttack_11), DEBUGSTRING("CHeadman::H0x012f0023_FirecrackerAttack_11")}, + {0x012f0024, -1, CEntity::pEventHandler(&CHeadman::H0x012f0024_FirecrackerAttack_12), DEBUGSTRING("CHeadman::H0x012f0024_FirecrackerAttack_12")}, + {0x012f0025, -1, CEntity::pEventHandler(&CHeadman::H0x012f0025_FirecrackerAttack_13), DEBUGSTRING("CHeadman::H0x012f0025_FirecrackerAttack_13")}, + {0x012f0026, -1, CEntity::pEventHandler(&CHeadman::H0x012f0026_FirecrackerAttack_14), DEBUGSTRING("CHeadman::H0x012f0026_FirecrackerAttack_14")}, + {0x012f0027, -1, CEntity::pEventHandler(&CHeadman::H0x012f0027_FirecrackerAttack_15), DEBUGSTRING("CHeadman::H0x012f0027_FirecrackerAttack_15")}, + {0x012f0028, -1, CEntity::pEventHandler(&CHeadman::H0x012f0028_FirecrackerAttack_16), DEBUGSTRING("CHeadman::H0x012f0028_FirecrackerAttack_16")}, + {0x012f0029, -1, CEntity::pEventHandler(&CHeadman:: +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +RocketmanAttack),DEBUGSTRING("CHeadman::RocketmanAttack")}, + {0x012f002a, -1, CEntity::pEventHandler(&CHeadman::H0x012f002a_RocketmanAttack_01), DEBUGSTRING("CHeadman::H0x012f002a_RocketmanAttack_01")}, + {0x012f002b, -1, CEntity::pEventHandler(&CHeadman::H0x012f002b_RocketmanAttack_02), DEBUGSTRING("CHeadman::H0x012f002b_RocketmanAttack_02")}, + {0x012f002c, -1, CEntity::pEventHandler(&CHeadman::H0x012f002c_RocketmanAttack_03), DEBUGSTRING("CHeadman::H0x012f002c_RocketmanAttack_03")}, + {0x012f002d, -1, CEntity::pEventHandler(&CHeadman::H0x012f002d_RocketmanAttack_04), DEBUGSTRING("CHeadman::H0x012f002d_RocketmanAttack_04")}, + {0x012f002e, STATE_CEnemyBase_Death, CEntity::pEventHandler(&CHeadman:: +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Death),DEBUGSTRING("CHeadman::Death")}, + {0x012f002f, -1, CEntity::pEventHandler(&CHeadman::H0x012f002f_Death_01), DEBUGSTRING("CHeadman::H0x012f002f_Death_01")}, + {0x012f0030, -1, CEntity::pEventHandler(&CHeadman::H0x012f0030_Death_02), DEBUGSTRING("CHeadman::H0x012f0030_Death_02")}, + {1, -1, CEntity::pEventHandler(&CHeadman:: +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/Headman.es" +Main),DEBUGSTRING("CHeadman::Main")}, +}; +#define CHeadman_handlersct ARRAYCOUNT(CHeadman_handlers) + +CEntity *CHeadman_New(void) { return new CHeadman; }; +void CHeadman_OnInitClass(void) {}; +void CHeadman_OnEndClass(void) {}; +void CHeadman_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CHeadman_OnWorldEnd(CWorld *pwo) {}; +void CHeadman_OnWorldInit(CWorld *pwo) {}; +void CHeadman_OnWorldTick(CWorld *pwo) {}; +void CHeadman_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CHeadman, CEnemyBase, "Headman", "Thumbnails\\Headman.tbn", 0x0000012f); +DECLARE_CTFILENAME(_fnmCHeadman_tbn, "Thumbnails\\Headman.tbn"); diff --git a/Sources/EntitiesMP/HealthItem.cpp b/Sources/EntitiesMP/HealthItem.cpp new file mode 100644 index 0000000..3f10702 --- /dev/null +++ b/Sources/EntitiesMP/HealthItem.cpp @@ -0,0 +1,350 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" + +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" + +#include +#include +CEntityEvent *EHealth::MakeCopy(void) { CEntityEvent *peeCopy = new EHealth(*this); return peeCopy;} +EHealth::EHealth() : CEntityEvent(EVENTCODE_EHealth) {; + ClearToDefault(fHealth); + ClearToDefault(bOverTopHealth); +}; +void CHealthItem::SetDefaultProperties(void) { + m_EhitType = HIT_SMALL ; + m_bOverTopHealth = FALSE ; + m_iSoundComponent = 0; + CItem::SetDefaultProperties(); +} + +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +void CHealthItem::Precache(void) { +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +switch(m_EhitType ){ +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_PILL : PrecacheSound (SOUND_PILL );break ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_SMALL : PrecacheSound (SOUND_SMALL );break ; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_MEDIUM : PrecacheSound (SOUND_MEDIUM );break ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_LARGE : PrecacheSound (SOUND_LARGE );break ; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_SUPER : PrecacheSound (SOUND_SUPER );break ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +BOOL CHealthItem::FillEntityStatistics(EntityStats * pes) +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +{ +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +pes -> es_strName = "Health"; +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +pes -> es_ctCount = 1; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +pes -> es_ctAmmount = m_fValue ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +pes -> es_fValue = m_fValue ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +pes -> es_iScore = 0; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +switch(m_EhitType ){ +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_PILL : pes -> es_strName += " pill";break ; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_SMALL : pes -> es_strName += " small";break ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_MEDIUM : pes -> es_strName += " medium";break ; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_LARGE : pes -> es_strName += " large";break ; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_SUPER : pes -> es_strName += " super";break ; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +return TRUE ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +void CHealthItem::RenderParticles(void) { +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +if(GetRenderType () != CEntity :: RT_MODEL || GetSP () -> sp_gmGameMode > CSessionProperties :: GM_COOPERATIVE +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +|| ! ShowItemParticles ()) +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +{ +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +return ; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +switch(m_EhitType ){ +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_PILL : +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Particles_Stardust (this , 0.9f * 0.75f , 0.70f * 0.75f , PT_STAR08 , 32); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +break ; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_SMALL : +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Particles_Stardust (this , 1.0f * 0.75f , 0.75f * 0.75f , PT_STAR08 , 128); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +break ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_MEDIUM : +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Particles_Stardust (this , 1.0f * 0.75f , 0.75f * 0.75f , PT_STAR08 , 128); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +break ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_LARGE : +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Particles_Stardust (this , 2.0f * 0.75f , 1.0f * 0.75f , PT_STAR08 , 192); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +break ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_SUPER : +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Particles_Stardust (this , 2.3f * 0.75f , 1.5f * 0.75f , PT_STAR08 , 320); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +break ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} + +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +void CHealthItem::SetProperties(void) { +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +switch(m_EhitType ){ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_PILL : +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_SMALL ); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_fValue = 1.0f; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_bOverTopHealth = TRUE ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_strDescription . PrintF ("Pill - H:%g T:%g" , m_fValue , m_fRespawnTime ); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +AddItem (MODEL_PILL , TEXTURE_PILL , 0 , TEXTURE_SPECULAR_STRONG , TEXTURE_PILL_BUMP ); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +StretchItem (FLOAT3D (1.0f * 0.75f , 1.0f * 0.75f , 1.0f * 0.75)); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_iSoundComponent = SOUND_PILL ; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +break ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_SMALL : +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_MEDIUM ); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_fValue = 10.0f; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_bOverTopHealth = FALSE ; +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_strDescription . PrintF ("Small - H:%g T:%g" , m_fValue , m_fRespawnTime ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +AddItem (MODEL_SMALL , TEXTURE_SMALL , TEXTURE_REFLECTION_LIGHTMETAL01 , TEXTURE_SPECULAR_MEDIUM , 0); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.4f , 0) , FLOAT3D (2 , 2 , 0.4f)); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +StretchItem (FLOAT3D (1.0f * 0.75f , 1.0f * 0.75f , 1.0f * 0.75)); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_iSoundComponent = SOUND_SMALL ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +break ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_MEDIUM : +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_MEDIUM ); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_fValue = 25.0f; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_bOverTopHealth = FALSE ; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 25.0f; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_strDescription . PrintF ("Medium - H:%g T:%g" , m_fValue , m_fRespawnTime ); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +AddItem (MODEL_MEDIUM , TEXTURE_MEDIUM , TEXTURE_REFLECTION_LIGHTMETAL01 , TEXTURE_SPECULAR_MEDIUM , 0); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.6f , 0) , FLOAT3D (2.5f , 2.5f , 0.5f)); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +StretchItem (FLOAT3D (1.5f * 0.75f , 1.5f * 0.75f , 1.5f * 0.75)); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_iSoundComponent = SOUND_MEDIUM ; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +break ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_LARGE : +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_MEDIUM ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_fValue = 50.0f; +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_bOverTopHealth = FALSE ; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 60.0f; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_strDescription . PrintF ("Large - H:%g T:%g" , m_fValue , m_fRespawnTime ); +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +AddItem (MODEL_LARGE , TEXTURE_LARGE , TEXTURE_REFLECTION_GOLD01 , TEXTURE_SPECULAR_STRONG , 0); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.8f , 0) , FLOAT3D (2.8f , 2.8f , 1.0f)); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +StretchItem (FLOAT3D (1.2f * 0.75f , 1.2f * 0.75f , 1.2f * 0.75)); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_iSoundComponent = SOUND_LARGE ; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +break ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_SUPER : +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_MEDIUM ); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_fValue = 100.0f; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_bOverTopHealth = TRUE ; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 120.0f; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_strDescription . PrintF ("Super - H:%g T:%g" , m_fValue , m_fRespawnTime ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +AddItem (MODEL_SUPER , TEXTURE_SUPER , 0 , TEXTURE_SPECULAR_MEDIUM , 0); +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 1.0f , 0) , FLOAT3D (3 , 3 , 1.0f)); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +StretchItem (FLOAT3D (1.0f * 0.75f , 1.0f * 0.75f , 1.0f * 0.75)); +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +CModelObject & mo = GetModelObject () -> GetAttachmentModel (ITEMHOLDER_ATTACHMENT_ITEM ) -> amo_moModelObject ; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +mo . PlayAnim (0 , AOF_LOOPING ); +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_iSoundComponent = SOUND_SUPER ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +break ; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} + +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +void CHealthItem::AdjustDifficulty(void) +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +{ +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +if(! GetSP () -> sp_bAllowHealth && m_penTarget == NULL ){ +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Destroy (); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +BOOL CHealthItem:: +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +ItemCollected(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHealthItem_ItemCollected + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EPass, "CHealthItem::ItemCollected expects 'EPass' as input!"); const EPass &epass = (const EPass &)__eeInput; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +ASSERT (epass . penOther != NULL ); +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +if(GetSP () -> sp_bHealthArmorStays && ! (m_bPickupOnce || m_bRespawn )){ +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +BOOL bWasPicked = MarkPickedBy (epass . penOther ); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +if(bWasPicked ){ +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Return(STATE_CURRENT,EVoid()); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +return TRUE; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +EHealth eHealth ; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +eHealth . fHealth = m_fValue ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +eHealth . bOverTopHealth = m_bOverTopHealth ; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +if(epass . penOther -> ReceiveItem (eHealth )){ +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +if(_pNetwork -> IsPlayerLocal (epass . penOther )) +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +{ +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +switch(m_EhitType ) +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +{ +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_PILL : IFeel_PlayEffect ("PU_HealthPill");break ; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_SMALL : IFeel_PlayEffect ("PU_HealthSmall");break ; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_MEDIUM : IFeel_PlayEffect ("PU_HealthMedium");break ; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_LARGE : IFeel_PlayEffect ("PU_HealthLarge");break ; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +case HIT_SUPER : IFeel_PlayEffect ("PU_HealthSuper");break ; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_soPick . Set3DParameters (50.0f , 1.0f , 1.0f , 1.0f); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +PlaySound (m_soPick , m_iSoundComponent , SOF_3D ); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +m_fPickSoundLen = GetSoundLength (m_iSoundComponent ); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +if(! GetSP () -> sp_bHealthArmorStays || (m_bPickupOnce || m_bRespawn )){ +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemReceived, FALSE, EVoid());return TRUE; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +} +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Return(STATE_CURRENT,EVoid()); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CHealthItem:: +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHealthItem_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHealthItem::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Initialize (); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +SetProperties (); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/HealthItem.es b/Sources/EntitiesMP/HealthItem.es new file mode 100644 index 0000000..4b89186 --- /dev/null +++ b/Sources/EntitiesMP/HealthItem.es @@ -0,0 +1,264 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +801 +%{ +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" +%} + +uses "EntitiesMP/Item"; + +// health type +enum HealthItemType { + 0 HIT_PILL "Pill", // pill health + 1 HIT_SMALL "Small", // small health + 2 HIT_MEDIUM "Medium", // medium health + 3 HIT_LARGE "Large", // large health + 4 HIT_SUPER "Super", // super health +}; + +// event for sending through receive item +event EHealth { + FLOAT fHealth, // health to receive + BOOL bOverTopHealth, // can be received over top health +}; + +class CHealthItem : CItem { +name "Health Item"; +thumbnail "Thumbnails\\HealthItem.tbn"; + +properties: + 1 enum HealthItemType m_EhitType "Type" 'Y' = HIT_SMALL, // health type + 2 BOOL m_bOverTopHealth = FALSE, // can be received over top health + 3 INDEX m_iSoundComponent = 0, + +components: + 0 class CLASS_BASE "Classes\\Item.ecl", + +// ********* PILL HEALTH ********* + 1 model MODEL_PILL "Models\\Items\\Health\\Pill\\Pill.mdl", + 2 texture TEXTURE_PILL "Models\\Items\\Health\\Pill\\Pill.tex", + 3 texture TEXTURE_PILL_BUMP "Models\\Items\\Health\\Pill\\PillBump.tex", + +// ********* SMALL HEALTH ********* + 10 model MODEL_SMALL "Models\\Items\\Health\\Small\\Small.mdl", + 11 texture TEXTURE_SMALL "Models\\Items\\Health\\Small\\Small.tex", + +// ********* MEDIUM HEALTH ********* + 20 model MODEL_MEDIUM "Models\\Items\\Health\\Medium\\Medium.mdl", + 21 texture TEXTURE_MEDIUM "Models\\Items\\Health\\Medium\\Medium.tex", + +// ********* LARGE HEALTH ********* + 30 model MODEL_LARGE "Models\\Items\\Health\\Large\\Large.mdl", + 31 texture TEXTURE_LARGE "Models\\Items\\Health\\Large\\Large.tex", + +// ********* SUPER HEALTH ********* + 40 model MODEL_SUPER "Models\\Items\\Health\\Super\\Super.mdl", + 41 texture TEXTURE_SUPER "Models\\Items\\Health\\Super\\Super.tex", + +// ********* MISC ********* + 50 texture TEXTURE_SPECULAR_STRONG "Models\\SpecularTextures\\Strong.tex", + 51 texture TEXTURE_SPECULAR_MEDIUM "Models\\SpecularTextures\\Medium.tex", + 52 texture TEXTURE_REFLECTION_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex", + 53 texture TEXTURE_REFLECTION_GOLD01 "Models\\ReflectionTextures\\Gold01.tex", + 54 texture TEXTURE_REFLECTION_PUPLE01 "Models\\ReflectionTextures\\Purple01.tex", + 55 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex", + 56 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl", + +// ************** SOUNDS ************** +301 sound SOUND_PILL "Sounds\\Items\\HealthPill.wav", +302 sound SOUND_SMALL "Sounds\\Items\\HealthSmall.wav", +303 sound SOUND_MEDIUM "Sounds\\Items\\HealthMedium.wav", +304 sound SOUND_LARGE "Sounds\\Items\\HealthLarge.wav", +305 sound SOUND_SUPER "Sounds\\Items\\HealthSuper.wav", + +functions: + void Precache(void) { + switch (m_EhitType) { + case HIT_PILL: PrecacheSound(SOUND_PILL ); break; + case HIT_SMALL: PrecacheSound(SOUND_SMALL ); break; + case HIT_MEDIUM: PrecacheSound(SOUND_MEDIUM); break; + case HIT_LARGE: PrecacheSound(SOUND_LARGE ); break; + case HIT_SUPER: PrecacheSound(SOUND_SUPER ); break; + } + } + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + pes->es_strName = "Health"; + pes->es_ctCount = 1; + pes->es_ctAmmount = m_fValue; + pes->es_fValue = m_fValue; + pes->es_iScore = 0;//m_iScore; + + switch (m_EhitType) { + case HIT_PILL: pes->es_strName+=" pill"; break; + case HIT_SMALL: pes->es_strName+=" small"; break; + case HIT_MEDIUM:pes->es_strName+=" medium"; break; + case HIT_LARGE: pes->es_strName+=" large"; break; + case HIT_SUPER: pes->es_strName+=" super"; break; + } + + return TRUE; + } + + // render particles + void RenderParticles(void) { + // no particles when not existing or in DM modes + if (GetRenderType()!=CEntity::RT_MODEL || GetSP()->sp_gmGameMode>CSessionProperties::GM_COOPERATIVE + || !ShowItemParticles()) + { + return; + } + switch (m_EhitType) { + case HIT_PILL: + Particles_Stardust(this, 0.9f*0.75f, 0.70f*0.75f, PT_STAR08, 32); + break; + case HIT_SMALL: + Particles_Stardust(this, 1.0f*0.75f, 0.75f*0.75f, PT_STAR08, 128); + break; + case HIT_MEDIUM: + Particles_Stardust(this, 1.0f*0.75f, 0.75f*0.75f, PT_STAR08, 128); + break; + case HIT_LARGE: + Particles_Stardust(this, 2.0f*0.75f, 1.0f*0.75f, PT_STAR08, 192); + break; + case HIT_SUPER: + Particles_Stardust(this, 2.3f*0.75f, 1.5f*0.75f, PT_STAR08, 320); + break; + } + } + + // set health properties depending on health type + void SetProperties(void) { + switch (m_EhitType) { + case HIT_PILL: + StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_SMALL); + m_fValue = 1.0f; + m_bOverTopHealth = TRUE; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Pill - H:%g T:%g", m_fValue, m_fRespawnTime); + // set appearance + AddItem(MODEL_PILL, TEXTURE_PILL, 0, TEXTURE_SPECULAR_STRONG, TEXTURE_PILL_BUMP); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f*0.75f, 1.0f*0.75f, 1.0f*0.75)); + m_iSoundComponent = SOUND_PILL; + break; + case HIT_SMALL: + StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM); + m_fValue = 10.0f; + m_bOverTopHealth = FALSE; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Small - H:%g T:%g", m_fValue, m_fRespawnTime); + // set appearance + AddItem(MODEL_SMALL, TEXTURE_SMALL, TEXTURE_REFLECTION_LIGHTMETAL01, TEXTURE_SPECULAR_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.4f,0), FLOAT3D(2,2,0.4f) ); + StretchItem(FLOAT3D(1.0f*0.75f, 1.0f*0.75f, 1.0f*0.75)); + m_iSoundComponent = SOUND_SMALL; + break; // add flare + + case HIT_MEDIUM: + StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM); + m_fValue = 25.0f; + m_bOverTopHealth = FALSE; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 25.0f; + m_strDescription.PrintF("Medium - H:%g T:%g", m_fValue, m_fRespawnTime); + // set appearance + AddItem(MODEL_MEDIUM, TEXTURE_MEDIUM, TEXTURE_REFLECTION_LIGHTMETAL01, TEXTURE_SPECULAR_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(2.5f,2.5f,0.5f) ); + StretchItem(FLOAT3D(1.5f*0.75f, 1.5f*0.75f, 1.5f*0.75)); + m_iSoundComponent = SOUND_MEDIUM; + break; + case HIT_LARGE: + StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM); + m_fValue = 50.0f; + m_bOverTopHealth = FALSE; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 60.0f; + m_strDescription.PrintF("Large - H:%g T:%g", m_fValue, m_fRespawnTime); + // set appearance + AddItem(MODEL_LARGE, TEXTURE_LARGE, TEXTURE_REFLECTION_GOLD01, TEXTURE_SPECULAR_STRONG, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.8f,0), FLOAT3D(2.8f,2.8f,1.0f) ); + StretchItem(FLOAT3D(1.2f*0.75f, 1.2f*0.75f, 1.2f*0.75)); + m_iSoundComponent = SOUND_LARGE; + break; + case HIT_SUPER: + StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_MEDIUM); + m_fValue = 100.0f; + m_bOverTopHealth = TRUE; + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 120.0f; + m_strDescription.PrintF("Super - H:%g T:%g", m_fValue, m_fRespawnTime); + // set appearance + AddItem(MODEL_SUPER, TEXTURE_SUPER, 0, TEXTURE_SPECULAR_MEDIUM, 0); + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,1.0f,0), FLOAT3D(3,3,1.0f) ); + StretchItem(FLOAT3D(1.0f*0.75f, 1.0f*0.75f, 1.0f*0.75)); + CModelObject &mo = GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_ITEM)->amo_moModelObject; + mo.PlayAnim(0, AOF_LOOPING); + + m_iSoundComponent = SOUND_SUPER; + break; + } + }; + + void AdjustDifficulty(void) + { + if (!GetSP()->sp_bAllowHealth && m_penTarget==NULL) { + Destroy(); + } + } +procedures: + ItemCollected(EPass epass) : CItem::ItemCollected { + ASSERT(epass.penOther!=NULL); + + // if health stays + if (GetSP()->sp_bHealthArmorStays && !(m_bPickupOnce||m_bRespawn)) { + // if already picked by this player + BOOL bWasPicked = MarkPickedBy(epass.penOther); + if (bWasPicked) { + // don't pick again + return; + } + } + + // send health to entity + EHealth eHealth; + eHealth.fHealth = m_fValue; + eHealth.bOverTopHealth = m_bOverTopHealth; + // if health is received + if (epass.penOther->ReceiveItem(eHealth)) { + + if(_pNetwork->IsPlayerLocal(epass.penOther)) + { + switch (m_EhitType) + { + case HIT_PILL: IFeel_PlayEffect("PU_HealthPill"); break; + case HIT_SMALL: IFeel_PlayEffect("PU_HealthSmall"); break; + case HIT_MEDIUM:IFeel_PlayEffect("PU_HealthMedium"); break; + case HIT_LARGE: IFeel_PlayEffect("PU_HealthLarge"); break; + case HIT_SUPER: IFeel_PlayEffect("PU_HealthSuper"); break; + } + } + + // play the pickup sound + m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f); + PlaySound(m_soPick, m_iSoundComponent, SOF_3D); + m_fPickSoundLen = GetSoundLength(m_iSoundComponent); + if (!GetSP()->sp_bHealthArmorStays || (m_bPickupOnce||m_bRespawn)) { + jump CItem::ItemReceived(); + } + } + return; + }; + + Main() { + Initialize(); // initialize base class + SetProperties(); // set properties + + jump CItem::ItemLoop(); + }; +}; diff --git a/Sources/EntitiesMP/HealthItem.h b/Sources/EntitiesMP/HealthItem.h new file mode 100644 index 0000000..b0337b4 --- /dev/null +++ b/Sources/EntitiesMP/HealthItem.h @@ -0,0 +1,57 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_HealthItem_INCLUDED +#define _EntitiesMP_HealthItem_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType HealthItemType_enum; +enum HealthItemType { + HIT_PILL = 0, + HIT_SMALL = 1, + HIT_MEDIUM = 2, + HIT_LARGE = 3, + HIT_SUPER = 4, +}; +DECL_DLL inline void ClearToDefault(HealthItemType &e) { e = (HealthItemType)0; } ; +#define EVENTCODE_EHealth 0x03210000 +class DECL_DLL EHealth : public CEntityEvent { +public: +EHealth(); +CEntityEvent *MakeCopy(void); +FLOAT fHealth; +BOOL bOverTopHealth; +}; +DECL_DLL inline void ClearToDefault(EHealth &e) { e = EHealth(); } ; +extern "C" DECL_DLL CDLLEntityClass CHealthItem_DLLClass; +class CHealthItem : public CItem { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum HealthItemType m_EhitType; + BOOL m_bOverTopHealth; + INDEX m_iSoundComponent; + +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +void Precache(void); + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +void RenderParticles(void); + +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +void SetProperties(void); + +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +void AdjustDifficulty(void); +#define STATE_CHealthItem_ItemCollected 0x03210001 + BOOL +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +ItemCollected(const CEntityEvent &__eeInput); +#define STATE_CHealthItem_Main 1 + BOOL +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_HealthItem_INCLUDED diff --git a/Sources/EntitiesMP/HealthItem_tables.h b/Sources/EntitiesMP/HealthItem_tables.h new file mode 100644 index 0000000..a23d705 --- /dev/null +++ b/Sources/EntitiesMP/HealthItem_tables.h @@ -0,0 +1,93 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(HealthItemType) + EP_ENUMVALUE(HIT_PILL, "Pill"), + EP_ENUMVALUE(HIT_SMALL, "Small"), + EP_ENUMVALUE(HIT_MEDIUM, "Medium"), + EP_ENUMVALUE(HIT_LARGE, "Large"), + EP_ENUMVALUE(HIT_SUPER, "Super"), +EP_ENUMEND(HealthItemType); + +#define ENTITYCLASS CHealthItem + +CEntityProperty CHealthItem_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &HealthItemType_enum, (0x00000321<<8)+1, offsetof(CHealthItem, m_EhitType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000321<<8)+2, offsetof(CHealthItem, m_bOverTopHealth), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000321<<8)+3, offsetof(CHealthItem, m_iSoundComponent), "", 0, 0, 0), +}; +#define CHealthItem_propertiesct ARRAYCOUNT(CHealthItem_properties) + +CEntityComponent CHealthItem_components[] = { +#define CLASS_BASE ((0x00000321<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\Item.ecl"), +#define MODEL_PILL ((0x00000321<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_PILL, "EFNM" "Models\\Items\\Health\\Pill\\Pill.mdl"), +#define TEXTURE_PILL ((0x00000321<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_PILL, "EFNM" "Models\\Items\\Health\\Pill\\Pill.tex"), +#define TEXTURE_PILL_BUMP ((0x00000321<<8)+3) + CEntityComponent(ECT_TEXTURE, TEXTURE_PILL_BUMP, "EFNM" "Models\\Items\\Health\\Pill\\PillBump.tex"), +#define MODEL_SMALL ((0x00000321<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_SMALL, "EFNM" "Models\\Items\\Health\\Small\\Small.mdl"), +#define TEXTURE_SMALL ((0x00000321<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_SMALL, "EFNM" "Models\\Items\\Health\\Small\\Small.tex"), +#define MODEL_MEDIUM ((0x00000321<<8)+20) + CEntityComponent(ECT_MODEL, MODEL_MEDIUM, "EFNM" "Models\\Items\\Health\\Medium\\Medium.mdl"), +#define TEXTURE_MEDIUM ((0x00000321<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_MEDIUM, "EFNM" "Models\\Items\\Health\\Medium\\Medium.tex"), +#define MODEL_LARGE ((0x00000321<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_LARGE, "EFNM" "Models\\Items\\Health\\Large\\Large.mdl"), +#define TEXTURE_LARGE ((0x00000321<<8)+31) + CEntityComponent(ECT_TEXTURE, TEXTURE_LARGE, "EFNM" "Models\\Items\\Health\\Large\\Large.tex"), +#define MODEL_SUPER ((0x00000321<<8)+40) + CEntityComponent(ECT_MODEL, MODEL_SUPER, "EFNM" "Models\\Items\\Health\\Super\\Super.mdl"), +#define TEXTURE_SUPER ((0x00000321<<8)+41) + CEntityComponent(ECT_TEXTURE, TEXTURE_SUPER, "EFNM" "Models\\Items\\Health\\Super\\Super.tex"), +#define TEXTURE_SPECULAR_STRONG ((0x00000321<<8)+50) + CEntityComponent(ECT_TEXTURE, TEXTURE_SPECULAR_STRONG, "EFNM" "Models\\SpecularTextures\\Strong.tex"), +#define TEXTURE_SPECULAR_MEDIUM ((0x00000321<<8)+51) + CEntityComponent(ECT_TEXTURE, TEXTURE_SPECULAR_MEDIUM, "EFNM" "Models\\SpecularTextures\\Medium.tex"), +#define TEXTURE_REFLECTION_LIGHTMETAL01 ((0x00000321<<8)+52) + CEntityComponent(ECT_TEXTURE, TEXTURE_REFLECTION_LIGHTMETAL01, "EFNM" "Models\\ReflectionTextures\\LightMetal01.tex"), +#define TEXTURE_REFLECTION_GOLD01 ((0x00000321<<8)+53) + CEntityComponent(ECT_TEXTURE, TEXTURE_REFLECTION_GOLD01, "EFNM" "Models\\ReflectionTextures\\Gold01.tex"), +#define TEXTURE_REFLECTION_PUPLE01 ((0x00000321<<8)+54) + CEntityComponent(ECT_TEXTURE, TEXTURE_REFLECTION_PUPLE01, "EFNM" "Models\\ReflectionTextures\\Purple01.tex"), +#define TEXTURE_FLARE ((0x00000321<<8)+55) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.tex"), +#define MODEL_FLARE ((0x00000321<<8)+56) + CEntityComponent(ECT_MODEL, MODEL_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.mdl"), +#define SOUND_PILL ((0x00000321<<8)+301) + CEntityComponent(ECT_SOUND, SOUND_PILL, "EFNM" "Sounds\\Items\\HealthPill.wav"), +#define SOUND_SMALL ((0x00000321<<8)+302) + CEntityComponent(ECT_SOUND, SOUND_SMALL, "EFNM" "Sounds\\Items\\HealthSmall.wav"), +#define SOUND_MEDIUM ((0x00000321<<8)+303) + CEntityComponent(ECT_SOUND, SOUND_MEDIUM, "EFNM" "Sounds\\Items\\HealthMedium.wav"), +#define SOUND_LARGE ((0x00000321<<8)+304) + CEntityComponent(ECT_SOUND, SOUND_LARGE, "EFNM" "Sounds\\Items\\HealthLarge.wav"), +#define SOUND_SUPER ((0x00000321<<8)+305) + CEntityComponent(ECT_SOUND, SOUND_SUPER, "EFNM" "Sounds\\Items\\HealthSuper.wav"), +}; +#define CHealthItem_componentsct ARRAYCOUNT(CHealthItem_components) + +CEventHandlerEntry CHealthItem_handlers[] = { + {0x03210001, STATE_CItem_ItemCollected, CEntity::pEventHandler(&CHealthItem:: +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +ItemCollected),DEBUGSTRING("CHealthItem::ItemCollected")}, + {1, -1, CEntity::pEventHandler(&CHealthItem:: +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/HealthItem.es" +Main),DEBUGSTRING("CHealthItem::Main")}, +}; +#define CHealthItem_handlersct ARRAYCOUNT(CHealthItem_handlers) + +CEntity *CHealthItem_New(void) { return new CHealthItem; }; +void CHealthItem_OnInitClass(void) {}; +void CHealthItem_OnEndClass(void) {}; +void CHealthItem_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CHealthItem_OnWorldEnd(CWorld *pwo) {}; +void CHealthItem_OnWorldInit(CWorld *pwo) {}; +void CHealthItem_OnWorldTick(CWorld *pwo) {}; +void CHealthItem_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CHealthItem, CItem, "Health Item", "Thumbnails\\HealthItem.tbn", 0x00000321); +DECLARE_CTFILENAME(_fnmCHealthItem_tbn, "Thumbnails\\HealthItem.tbn"); diff --git a/Sources/EntitiesMP/HudPicHolder.cpp b/Sources/EntitiesMP/HudPicHolder.cpp new file mode 100644 index 0000000..e0b0f85 --- /dev/null +++ b/Sources/EntitiesMP/HudPicHolder.cpp @@ -0,0 +1,382 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" + +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" + +#include +#include +#line 11 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" + +BOOL _bDataLoaded = FALSE; +BOOL _bDataError = FALSE; +CTextureObject _toTexture; + +void CHudPicHolder::SetDefaultProperties(void) { + m_strName = "Hud pic holder"; + m_strDescription = ""; + m_fnmPicture = CTString(""); + m_tmFadeInStart = 1e6; + m_tmFadeOutStart = 1e6; + m_tmFadeInLen = 0.5f; + m_tmFadeOutLen = 0.5f; + m_tmAutoFadeOut = -1.0f; + m_fYRatio = 0.5f; + m_fXRatio = 0.5f; + m_fPictureStretch = 1.0f; + CRationalEntity::SetDefaultProperties(); +} + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +const CTString & CHudPicHolder::GetDescription(void)const { +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +((CTString &) m_strDescription ) . PrintF ("%s" , m_fnmPicture . FileName ()); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return m_strDescription ; +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} + +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +BOOL CHudPicHolder::ReloadData(void) +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +_bDataError = FALSE ; +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(! Picture_On (m_fnmPicture )) +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Picture_Off (); +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return FALSE ; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return TRUE ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +BOOL CHudPicHolder::LoadOneFile(const CTFileName & fnm) +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(fnm == ""){return FALSE ;} +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +try +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +_toTexture . SetData_t (fnm ); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return TRUE ; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +catch (char * strError ) +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +CPrintF ("%s\n" , strError ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return FALSE ; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} + +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +BOOL CHudPicHolder::Picture_On(CTFileName fnPic) +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return LoadOneFile (fnPic ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +void CHudPicHolder::Picture_Off(void) +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +_toTexture . SetData (NULL ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} + +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +FLOAT CHudPicHolder::HudPic_Render(CHudPicHolder * penThis,CDrawPort * pdp) +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(_bDataError ){return 0;} +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(! _bDataLoaded ){ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(! ReloadData ()){ +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +_bDataError = TRUE ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return 0; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +_bDataLoaded = TRUE ; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return 1; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +FLOAT fNow = _pTimer -> CurrentTick (); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(fNow < m_tmFadeInStart ){return 0;} +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(fNow > m_tmFadeOutStart + m_tmFadeOutLen ){return 0;} +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +CDrawPort * pdpCurr = pdp ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +pdp -> Unlock (); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +pdpCurr -> Lock (); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +FLOAT fRatio = 1.0f; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(fNow > m_tmFadeOutStart ) +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +fRatio = CalculateRatio (fNow , m_tmFadeOutStart , m_tmFadeOutStart + m_tmFadeOutLen , 0 , 1); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(fNow < m_tmFadeInStart + m_tmFadeInLen ) +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +fRatio = CalculateRatio (fNow , m_tmFadeInStart , m_tmFadeInStart + m_tmFadeInLen , 1 , 0); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +UBYTE ubA = ClampUp (UBYTE (fRatio * 255.0f) , UBYTE (255)); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +CTextureData * ptd = (CTextureData *) _toTexture . GetData (); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +FLOAT fResScale = (FLOAT) pdpCurr -> GetHeight () / 480.0f; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +const MEX mexTexW = ptd -> GetWidth (); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +const MEX mexTexH = ptd -> GetHeight (); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +FLOAT fPicRatioW , fPicRatioH ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(mexTexW > mexTexH ){ +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +fPicRatioW = mexTexW / mexTexH ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +fPicRatioH = 1.0f; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +}else { +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +fPicRatioW = 1.0f; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +fPicRatioH = mexTexH / mexTexW ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +PIX picW = 128 * m_fPictureStretch * fResScale * fPicRatioW ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +PIX picH = 128 * m_fPictureStretch * fResScale * fPicRatioH ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +FLOAT fXCenter = m_fXRatio * pdpCurr -> GetWidth (); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +FLOAT fYCenter = m_fYRatio * pdpCurr -> GetHeight (); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +PIXaabbox2D boxScr = PIXaabbox2D ( +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +PIX2D (fXCenter - picW / 2 , fYCenter - picH / 2) , +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +PIX2D (fXCenter + picW / 2 , fYCenter + picH / 2)); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +pdpCurr -> PutTexture (& _toTexture , boxScr , C_WHITE | ubA ); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +pdpCurr -> Unlock (); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +pdp -> Lock (); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return 1; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +BOOL CHudPicHolder:: +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +WaitAndFadeOut(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHudPicHolder_WaitAndFadeOut + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHudPicHolder::WaitAndFadeOut expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +SetTimerAfter(m_tmAutoFadeOut ); +Jump(STATE_CURRENT, 0x00f10001, FALSE, EBegin());return TRUE;}BOOL CHudPicHolder::H0x00f10001_WaitAndFadeOut_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f10001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00f10002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHudPicHolder::H0x00f10002_WaitAndFadeOut_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f10002 +; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Jump(STATE_CURRENT, STATE_CHudPicHolder_ApplyFadeOut, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CHudPicHolder:: +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +ApplyFadeOut(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHudPicHolder_ApplyFadeOut + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHudPicHolder::ApplyFadeOut expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +m_tmFadeOutStart = _pTimer -> CurrentTick (); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(!(pwsc != NULL )){ Jump(STATE_CURRENT,0x00f10006, FALSE, EInternal());return TRUE;} +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +SetTimerAfter(m_tmFadeOutLen ); +Jump(STATE_CURRENT, 0x00f10004, FALSE, EBegin());return TRUE;}BOOL CHudPicHolder::H0x00f10004_ApplyFadeOut_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f10004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00f10005, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHudPicHolder::H0x00f10005_ApplyFadeOut_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f10005 +; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +ETextFX etfx ; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +etfx . bStart = FALSE ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +etfx . penSender = this ; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +pwsc -> SendEvent (etfx );Jump(STATE_CURRENT,0x00f10006, FALSE, EInternal());return TRUE;}BOOL CHudPicHolder::H0x00f10006_ApplyFadeOut_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f10006 + +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Return(STATE_CURRENT,EReturn ()); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CHudPicHolder:: +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CHudPicHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CHudPicHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +InitAsEditorModel (); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +SetModel (MODEL_MARKER ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x00f10007, FALSE, EBegin());return TRUE;}BOOL CHudPicHolder::H0x00f10007_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f10007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00f10008, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CHudPicHolder::H0x00f10008_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f10008 +; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(! Picture_On (m_fnmPicture )) +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Picture_Off (); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return TRUE; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +_bDataError = FALSE ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00f10009, FALSE, EBegin());return TRUE;}BOOL CHudPicHolder::H0x00f10009_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f10009 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin): +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{const EBegin&e= (EBegin&)__eeInput; + +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return TRUE; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart): +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{const EStart&eStart= (EStart&)__eeInput; + +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(pwsc != NULL ) +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +m_tmFadeInStart = _pTimer -> CurrentTick (); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +EHudPicFX etfx ; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +etfx . bStart = TRUE ; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +etfx . penSender = this ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +pwsc -> SendEvent (etfx ); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +if(m_tmAutoFadeOut != - 1) +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{ +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Call(STATE_CURRENT, STATE_CHudPicHolder_WaitAndFadeOut, TRUE, EVoid());return TRUE; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +} +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return TRUE; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop): +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{const EStop&eStop= (EStop&)__eeInput; + +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Call(STATE_CURRENT, STATE_CHudPicHolder_ApplyFadeOut, TRUE, EVoid());return TRUE; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return TRUE; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn): +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +{const EReturn&e= (EReturn&)__eeInput; + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return TRUE; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +}return TRUE;}BOOL CHudPicHolder::H0x00f1000a_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f1000a + +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Picture_Off (); +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/HudPicHolder.es b/Sources/EntitiesMP/HudPicHolder.es new file mode 100644 index 0000000..bda91e1 --- /dev/null +++ b/Sources/EntitiesMP/HudPicHolder.es @@ -0,0 +1,226 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +241 +%{ +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" +%} + + +%{ +BOOL _bDataLoaded = FALSE; +BOOL _bDataError = FALSE; +CTextureObject _toTexture; +%} + +class CHudPicHolder: CRationalEntity { +name "HudPicHolder"; +thumbnail "Thumbnails\\HudPicHolder.tbn"; +features "IsTargetable", "HasName", "IsImportant"; + +properties: + + 1 CTString m_strName "Name" 'N' = "Hud pic holder", + 2 CTString m_strDescription = "", + 3 CTFileName m_fnmPicture "Picture file" 'P' = CTString(""), + 4 FLOAT m_tmFadeInStart = 1e6, + 5 FLOAT m_tmFadeOutStart = 1e6, + 6 FLOAT m_tmFadeInLen "Fade in time" 'I' = 0.5f, + 7 FLOAT m_tmFadeOutLen "Fade out time" 'O' = 0.5f, + 8 FLOAT m_tmAutoFadeOut "Auto fade out time" 'A' = -1.0f, + 9 FLOAT m_fYRatio "Vertical position ratio" 'Y' = 0.5f, + 10 FLOAT m_fXRatio "Horizontal position ratio" 'X' = 0.5f, + 11 FLOAT m_fPictureStretch "Picture stretch" 'S' = 1.0f, + +components: + 1 model MODEL_MARKER "Models\\Editor\\MessageHolder.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\MessageHolder.tex" + +functions: + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("%s", m_fnmPicture.FileName()); + return m_strDescription; + } + + BOOL ReloadData(void) + { + _bDataError = FALSE; + if (!Picture_On(m_fnmPicture)) + { + Picture_Off(); + return FALSE; + } + return TRUE; + } + + BOOL LoadOneFile(const CTFileName &fnm) + { + if(fnm=="") { return FALSE; } + try + { + _toTexture.SetData_t(fnm); + return TRUE; + } + catch (char *strError) + { + CPrintF("%s\n", strError); + return FALSE; + } + } + + // turn text on + BOOL Picture_On(CTFileName fnPic) + { + return LoadOneFile(fnPic); + } + + // turn text off + void Picture_Off(void) + { + _toTexture.SetData(NULL); + } + + // render credits to given drawport + FLOAT HudPic_Render(CHudPicHolder *penThis, CDrawPort *pdp) + { + if (_bDataError) { return 0; } + + if (!_bDataLoaded) { + if (!ReloadData()) { + _bDataError = TRUE; + return 0; + } + _bDataLoaded = TRUE; + return 1; + } + + FLOAT fNow=_pTimer->CurrentTick(); + if( fNowm_tmFadeOutStart+m_tmFadeOutLen) { return 0;} + + CDrawPort *pdpCurr=pdp; + pdp->Unlock(); + pdpCurr->Lock(); + + FLOAT fRatio=1.0f; + if( fNow>m_tmFadeOutStart) + { + fRatio=CalculateRatio(fNow, m_tmFadeOutStart, m_tmFadeOutStart+m_tmFadeOutLen, 0, 1); + } + if( fNowGetHeight() / 480.0f; + const MEX mexTexW = ptd->GetWidth(); + const MEX mexTexH = ptd->GetHeight(); + FLOAT fPicRatioW, fPicRatioH; + if( mexTexW > mexTexH) { + fPicRatioW = mexTexW/mexTexH; + fPicRatioH = 1.0f; + } else { + fPicRatioW = 1.0f; + fPicRatioH = mexTexH/mexTexW; + } + PIX picW = 128*m_fPictureStretch*fResScale*fPicRatioW; + PIX picH = 128*m_fPictureStretch*fResScale*fPicRatioH; + + FLOAT fXCenter = m_fXRatio * pdpCurr->GetWidth(); + FLOAT fYCenter = m_fYRatio * pdpCurr->GetHeight(); + PIXaabbox2D boxScr=PIXaabbox2D( + PIX2D(fXCenter-picW/2, fYCenter-picH/2), + PIX2D(fXCenter+picW/2, fYCenter+picH/2) ); + pdpCurr->PutTexture(&_toTexture, boxScr, C_WHITE|ubA); + + pdpCurr->Unlock(); + pdp->Lock(); + + return 1; + } + + +procedures: + + WaitAndFadeOut(EVoid) + { + autowait( m_tmAutoFadeOut); + jump ApplyFadeOut(); + } + + ApplyFadeOut(EVoid) + { + m_tmFadeOutStart = _pTimer->CurrentTick(); + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL) + { + autowait(m_tmFadeOutLen); + CWorldSettingsController *pwsc = GetWSC(this); + ETextFX etfx; + etfx.bStart=FALSE; + etfx.penSender=this; + pwsc->SendEvent(etfx); + } + return EReturn(); + } + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + autowait(0.05f); + + if( !Picture_On(m_fnmPicture)) + { + Picture_Off(); + return; + } + _bDataError = FALSE; + + wait() { + on (EBegin): + { + resume; + } + on (EStart eStart): + { + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL) + { + m_tmFadeInStart = _pTimer->CurrentTick(); + EHudPicFX etfx; + etfx.bStart=TRUE; + etfx.penSender=this; + pwsc->SendEvent(etfx); + if( m_tmAutoFadeOut!=-1) + { + call WaitAndFadeOut(); + } + } + resume; + } + on (EStop eStop): + { + call ApplyFadeOut(); + resume; + } + on (EReturn): + { + resume; + } + } + Picture_Off(); + return; + } +}; + diff --git a/Sources/EntitiesMP/HudPicHolder.h b/Sources/EntitiesMP/HudPicHolder.h new file mode 100644 index 0000000..bf5618f --- /dev/null +++ b/Sources/EntitiesMP/HudPicHolder.h @@ -0,0 +1,65 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_HudPicHolder_INCLUDED +#define _EntitiesMP_HudPicHolder_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CHudPicHolder_DLLClass; +class CHudPicHolder : public CRationalEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CTFileName m_fnmPicture; + FLOAT m_tmFadeInStart; + FLOAT m_tmFadeOutStart; + FLOAT m_tmFadeInLen; + FLOAT m_tmFadeOutLen; + FLOAT m_tmAutoFadeOut; + FLOAT m_fYRatio; + FLOAT m_fXRatio; + FLOAT m_fPictureStretch; + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +const CTString & GetDescription(void)const; + +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +BOOL ReloadData(void); + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +BOOL LoadOneFile(const CTFileName & fnm); + +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +BOOL Picture_On(CTFileName fnPic); + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +void Picture_Off(void); + +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +FLOAT HudPic_Render(CHudPicHolder * penThis,CDrawPort * pdp); +#define STATE_CHudPicHolder_WaitAndFadeOut 0x00f10000 + BOOL +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +WaitAndFadeOut(const CEntityEvent &__eeInput); + BOOL H0x00f10001_WaitAndFadeOut_01(const CEntityEvent &__eeInput); + BOOL H0x00f10002_WaitAndFadeOut_02(const CEntityEvent &__eeInput); +#define STATE_CHudPicHolder_ApplyFadeOut 0x00f10003 + BOOL +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +ApplyFadeOut(const CEntityEvent &__eeInput); + BOOL H0x00f10004_ApplyFadeOut_01(const CEntityEvent &__eeInput); + BOOL H0x00f10005_ApplyFadeOut_02(const CEntityEvent &__eeInput); + BOOL H0x00f10006_ApplyFadeOut_03(const CEntityEvent &__eeInput); +#define STATE_CHudPicHolder_Main 1 + BOOL +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00f10007_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00f10008_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00f10009_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00f1000a_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_HudPicHolder_INCLUDED diff --git a/Sources/EntitiesMP/HudPicHolder_tables.h b/Sources/EntitiesMP/HudPicHolder_tables.h new file mode 100644 index 0000000..41bbd2d --- /dev/null +++ b/Sources/EntitiesMP/HudPicHolder_tables.h @@ -0,0 +1,61 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CHudPicHolder + +CEntityProperty CHudPicHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000f1<<8)+1, offsetof(CHudPicHolder, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000f1<<8)+2, offsetof(CHudPicHolder, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000f1<<8)+3, offsetof(CHudPicHolder, m_fnmPicture), "Picture file", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f1<<8)+4, offsetof(CHudPicHolder, m_tmFadeInStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f1<<8)+5, offsetof(CHudPicHolder, m_tmFadeOutStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f1<<8)+6, offsetof(CHudPicHolder, m_tmFadeInLen), "Fade in time", 'I', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f1<<8)+7, offsetof(CHudPicHolder, m_tmFadeOutLen), "Fade out time", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f1<<8)+8, offsetof(CHudPicHolder, m_tmAutoFadeOut), "Auto fade out time", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f1<<8)+9, offsetof(CHudPicHolder, m_fYRatio), "Vertical position ratio", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f1<<8)+10, offsetof(CHudPicHolder, m_fXRatio), "Horizontal position ratio", 'X', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f1<<8)+11, offsetof(CHudPicHolder, m_fPictureStretch), "Picture stretch", 'S', 0x7F0000FFUL, 0), +}; +#define CHudPicHolder_propertiesct ARRAYCOUNT(CHudPicHolder_properties) + +CEntityComponent CHudPicHolder_components[] = { +#define MODEL_MARKER ((0x000000f1<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\MessageHolder.mdl"), +#define TEXTURE_MARKER ((0x000000f1<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\MessageHolder.tex"), +}; +#define CHudPicHolder_componentsct ARRAYCOUNT(CHudPicHolder_components) + +CEventHandlerEntry CHudPicHolder_handlers[] = { + {0x00f10000, -1, CEntity::pEventHandler(&CHudPicHolder:: +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +WaitAndFadeOut),DEBUGSTRING("CHudPicHolder::WaitAndFadeOut")}, + {0x00f10001, -1, CEntity::pEventHandler(&CHudPicHolder::H0x00f10001_WaitAndFadeOut_01), DEBUGSTRING("CHudPicHolder::H0x00f10001_WaitAndFadeOut_01")}, + {0x00f10002, -1, CEntity::pEventHandler(&CHudPicHolder::H0x00f10002_WaitAndFadeOut_02), DEBUGSTRING("CHudPicHolder::H0x00f10002_WaitAndFadeOut_02")}, + {0x00f10003, -1, CEntity::pEventHandler(&CHudPicHolder:: +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +ApplyFadeOut),DEBUGSTRING("CHudPicHolder::ApplyFadeOut")}, + {0x00f10004, -1, CEntity::pEventHandler(&CHudPicHolder::H0x00f10004_ApplyFadeOut_01), DEBUGSTRING("CHudPicHolder::H0x00f10004_ApplyFadeOut_01")}, + {0x00f10005, -1, CEntity::pEventHandler(&CHudPicHolder::H0x00f10005_ApplyFadeOut_02), DEBUGSTRING("CHudPicHolder::H0x00f10005_ApplyFadeOut_02")}, + {0x00f10006, -1, CEntity::pEventHandler(&CHudPicHolder::H0x00f10006_ApplyFadeOut_03), DEBUGSTRING("CHudPicHolder::H0x00f10006_ApplyFadeOut_03")}, + {1, -1, CEntity::pEventHandler(&CHudPicHolder:: +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/HudPicHolder.es" +Main),DEBUGSTRING("CHudPicHolder::Main")}, + {0x00f10007, -1, CEntity::pEventHandler(&CHudPicHolder::H0x00f10007_Main_01), DEBUGSTRING("CHudPicHolder::H0x00f10007_Main_01")}, + {0x00f10008, -1, CEntity::pEventHandler(&CHudPicHolder::H0x00f10008_Main_02), DEBUGSTRING("CHudPicHolder::H0x00f10008_Main_02")}, + {0x00f10009, -1, CEntity::pEventHandler(&CHudPicHolder::H0x00f10009_Main_03), DEBUGSTRING("CHudPicHolder::H0x00f10009_Main_03")}, + {0x00f1000a, -1, CEntity::pEventHandler(&CHudPicHolder::H0x00f1000a_Main_04), DEBUGSTRING("CHudPicHolder::H0x00f1000a_Main_04")}, +}; +#define CHudPicHolder_handlersct ARRAYCOUNT(CHudPicHolder_handlers) + +CEntity *CHudPicHolder_New(void) { return new CHudPicHolder; }; +void CHudPicHolder_OnInitClass(void) {}; +void CHudPicHolder_OnEndClass(void) {}; +void CHudPicHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CHudPicHolder_OnWorldEnd(CWorld *pwo) {}; +void CHudPicHolder_OnWorldInit(CWorld *pwo) {}; +void CHudPicHolder_OnWorldTick(CWorld *pwo) {}; +void CHudPicHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CHudPicHolder, CRationalEntity, "HudPicHolder", "Thumbnails\\HudPicHolder.tbn", 0x000000f1); +DECLARE_CTFILENAME(_fnmCHudPicHolder_tbn, "Thumbnails\\HudPicHolder.tbn"); diff --git a/Sources/EntitiesMP/Item.cpp b/Sources/EntitiesMP/Item.cpp new file mode 100644 index 0000000..4bce190 --- /dev/null +++ b/Sources/EntitiesMP/Item.cpp @@ -0,0 +1,424 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" + +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" + +#include +#include +#line 9 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" + +// used to render certain entities only for certain players (like picked items, etc.) +extern ULONG _ulPlayerRenderingMask; + +void CItem::SetDefaultProperties(void) { + m_strName = "Item"; + m_strDescription = ""; + m_fValue = 0.0f; + m_fRespawnTime = 0.0f; + m_fCustomRespawnTime = 0.0f; + m_bRespawn = FALSE ; + m_penTarget = NULL; + m_bPickupOnce = FALSE ; + m_soPick.SetOwner(this); +m_soPick.Stop_internal(); + m_fPickSoundLen = 0.0f; + m_bDropped = FALSE ; + m_ulPickedMask = 0; + m_bFloating = FALSE ; + m_penPrediction = NULL; + CMovableModelEntity::SetDefaultProperties(); +} + void CItem::AdjustDifficulty(void) +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void CItem::AdjustMipFactor(FLOAT & fMipFactor) +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +CAttachmentModelObject * pamo = GetModelObject () -> GetAttachmentModel (ITEMHOLDER_ATTACHMENT_FLARE ); +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(pamo != NULL ) +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +FLOAT fRatio = (Clamp (fMipFactor , 5.0f , 7.0f) - 5.0f) / 2.0f; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +UBYTE ubRatio = UBYTE (255 * fRatio ); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +COLOR colMutiply = RGBToColor (ubRatio , ubRatio , ubRatio ) | CT_OPAQUE ; +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +pamo -> amo_moModelObject . mo_colBlendColor = colMutiply ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(m_ulPickedMask == 0){ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +BOOL bFlare = TRUE ; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(_ulPlayerRenderingMask & m_ulPickedMask ){ +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +extern INDEX plr_bRenderPicked ; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(! plr_bRenderPicked ){ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +fMipFactor = UpperLimit (0.0f); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +extern INDEX plr_bRenderPickedParticles ; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(! plr_bRenderPickedParticles ){ +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +bFlare = FALSE ; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +BOOL CItem::ShowItemParticles(void) +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(_ulPlayerRenderingMask & m_ulPickedMask ){ +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +extern INDEX plr_bRenderPickedParticles ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(! plr_bRenderPickedParticles ){ +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return FALSE ; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return TRUE ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +BOOL CItem::MarkPickedBy(CEntity * pen) +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(! IsOfClass (pen , "Player")){ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return FALSE ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +INDEX iPlayer = ((CPlayerEntity *) pen ) -> GetMyPlayerIndex (); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +BOOL bPickedAlready = (1 << iPlayer ) & m_ulPickedMask ; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +m_ulPickedMask |= (1 << iPlayer ); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return bPickedAlready ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +FLOAT CItem::GetPredictionRange(void) +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +extern FLOAT cli_fPredictItemsRange ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return cli_fPredictItemsRange ; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +BOOL CItem::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +colLight = 0x40404040; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +colAmbient = 0x60606060; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +vLightDirection = FLOAT3D (- 1 , - 1 , - 1); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +vLightDirection . Normalize (); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +vLightDirection *= GetRotationMatrix (); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return FALSE ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void CItem::Initialize(void) { +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +InitAsModel (); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(m_bFloating ){ +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SetPhysicsFlags (EPF_MODEL_FLYING ); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +}else { +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SetPhysicsFlags (EPF_MODEL_SLIDING ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SetCollisionFlags (ECF_ITEM ); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +en_fDeceleration = 60.0f; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SetModel (MODEL_ITEM ); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SetDesiredTranslation (FLOAT3D (0 , 0 , 0)); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void CItem::AddItem(ULONG ulIDModel,ULONG ulIDTexture, +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture) { +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +AddAttachmentToModel (this , * GetModelObject () , ITEMHOLDER_ATTACHMENT_ITEM , ulIDModel , ulIDTexture , +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ulIDReflectionTexture , ulIDSpecularTexture , ulIDBumpTexture ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void CItem::AddItemSpecial(INDEX iAttachmentPos,ULONG ulIDModel,ULONG ulIDTexture, +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture) { +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +AddAttachmentToModel (this , * GetModelObject () , iAttachmentPos , ulIDModel , ulIDTexture , +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ulIDReflectionTexture , ulIDSpecularTexture , ulIDBumpTexture ); +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void CItem::AddItemAttachment(INDEX iAttachment,ULONG ulIDModel,ULONG ulIDTexture, +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture) { +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +CModelObject & mo = GetModelObject () -> GetAttachmentModel (ITEMHOLDER_ATTACHMENT_ITEM ) -> amo_moModelObject ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +AddAttachmentToModel (this , mo , iAttachment , ulIDModel , ulIDTexture , +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ulIDReflectionTexture , ulIDSpecularTexture , ulIDBumpTexture ); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void CItem::SetItemAttachmentAnim(INDEX iAttachment,INDEX iAnim) +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +CModelObject & mo = +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +GetModelObject () -> GetAttachmentModel (ITEMHOLDER_ATTACHMENT_ITEM ) -> amo_moModelObject . +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +GetAttachmentModel (iAttachment ) -> amo_moModelObject ; +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +mo . PlayAnim (iAnim , 0); +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void CItem::AddFlare(ULONG ulIDModel,ULONG ulIDTexture, +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +const FLOAT3D & vPos,const FLOAT3D & vStretch) +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(! m_bRespawn && ! m_bDropped ) +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +AddAttachmentToModel (this , * GetModelObject () , +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ITEMHOLDER_ATTACHMENT_FLARE , ulIDModel , ulIDTexture , 0 , 0 , 0); +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +CAttachmentModelObject & amo = * GetModelObject () -> GetAttachmentModel (ITEMHOLDER_ATTACHMENT_FLARE ); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +amo . amo_moModelObject . StretchModel (vStretch ); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +amo . amo_plRelative . pl_PositionVector = vPos ; +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void CItem::StretchItem(const FLOAT3D & vStretch) { +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +CModelObject & mo = GetModelObject () -> GetAttachmentModel (ITEMHOLDER_ATTACHMENT_ITEM ) -> amo_moModelObject ; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +mo . StretchModel (vStretch ); +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ModelChangeNotify (); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} + +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SLONG CItem::GetUsedMemory(void) +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +{ +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SLONG slUsedMemory = sizeof (CItem ) - sizeof (CMovableModelEntity ) + CMovableModelEntity :: GetUsedMemory (); +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +slUsedMemory += m_strDescription . Length (); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +slUsedMemory += m_strName . Length (); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +slUsedMemory += 1 * sizeof (CSoundObject); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return slUsedMemory ; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +BOOL CItem:: +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ItemCollected(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CItem_ItemCollected + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EPass, "CItem::ItemCollected expects 'EPass' as input!"); const EPass &epass = (const EPass &)__eeInput;Return(STATE_CURRENT,EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CItem:: +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ItemLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CItem_ItemLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CItem::ItemLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +m_fCustomRespawnTime = ClampDn (m_fCustomRespawnTime , 0.0f); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x03200002, FALSE, EBegin());return TRUE;}BOOL CItem::H0x03200002_ItemLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x03200002 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x03200003, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CItem::H0x03200003_ItemLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03200003 +; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SetPredictable (TRUE ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +AdjustDifficulty (); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x03200004, FALSE, EBegin());return TRUE;}BOOL CItem::H0x03200004_ItemLoop_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x03200004 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&epass= (EPass&)__eeInput; + +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(! IsOfClass (epass . penOther , "Player")){ +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return FALSE; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(! (m_bPickupOnce || m_bRespawn )){ +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SendToTarget (m_penTarget , EET_TRIGGER , epass . penOther ); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +m_penTarget = NULL ; +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +Call(STATE_CURRENT, STATE_CItem_ItemCollected, TRUE, epass );return TRUE; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnd):{const EEnd&e= (EEnd&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x03200005, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +}return TRUE;}BOOL CItem::H0x03200005_ItemLoop_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03200005 + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SetTimerAfter(m_fPickSoundLen + 0.5f); +Jump(STATE_CURRENT, 0x03200006, FALSE, EBegin());return TRUE;}BOOL CItem::H0x03200006_ItemLoop_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x03200006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x03200007, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CItem::H0x03200007_ItemLoop_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03200007 +; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +Destroy (); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +Return(STATE_CURRENT,EVoid()); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CItem:: +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ItemReceived(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CItem_ItemReceived + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CItem::ItemReceived expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SwitchToEditorModel (); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if((m_bPickupOnce || m_bRespawn )){ +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SendToTarget (m_penTarget , EET_TRIGGER , NULL ); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +} +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +if(!(m_bRespawn )){ Jump(STATE_CURRENT,0x0320000c, FALSE, EInternal());return TRUE;} +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ASSERT (m_fRespawnTime > 0.0f); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SetTimerAfter(m_fRespawnTime ); +Jump(STATE_CURRENT, 0x03200009, FALSE, EBegin());return TRUE;}BOOL CItem::H0x03200009_ItemReceived_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x03200009 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x0320000a, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +}return TRUE;}BOOL CItem::H0x0320000a_ItemReceived_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0320000a + +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SwitchToModel ();Jump(STATE_CURRENT,0x0320000b, FALSE, EInternal());return TRUE;}BOOL CItem::H0x0320000c_ItemReceived_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0320000c +{ +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +Return(STATE_CURRENT,EEnd ()); +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return TRUE; +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +}Jump(STATE_CURRENT,0x0320000b, FALSE, EInternal());return TRUE;} +BOOL CItem::H0x0320000b_ItemReceived_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0320000b + +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +Return(STATE_CURRENT,EVoid()); +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Item.es b/Sources/EntitiesMP/Item.es new file mode 100644 index 0000000..ba954ba --- /dev/null +++ b/Sources/EntitiesMP/Item.es @@ -0,0 +1,311 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +800 +%{ +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" +%} + +%{ +// used to render certain entities only for certain players (like picked items, etc.) +extern ULONG _ulPlayerRenderingMask; +%} + +class export CItem : CMovableModelEntity { +name "Item"; +thumbnail ""; +features "HasName", "HasDescription", "IsTargetable", "CanBePredictable"; + +properties: + 1 CTString m_strName "Name" 'N' = "Item", + 2 CTString m_strDescription = "", + + // class properties + 5 FLOAT m_fValue = 0.0f, // value + 6 FLOAT m_fRespawnTime = 0.0f, // default respawn time + 26 FLOAT m_fCustomRespawnTime "Respawn Time" = 0.0f, // custom respawn time + 7 BOOL m_bRespawn "Respawn" 'R' = FALSE, // respawn item + 8 CEntityPointer m_penTarget "Target" 'T' COLOR(C_dGRAY|0xFF), // target to trigger when crossed over + 9 BOOL m_bPickupOnce "PickupOnce" 'P' = FALSE, // can be picked by only one player, triggers only when really picked + 10 CSoundObject m_soPick, // sound channel + 12 FLOAT m_fPickSoundLen = 0.0f, + 14 BOOL m_bDropped = FALSE, // dropped by a player during a deathmatch game + 15 INDEX m_ulPickedMask = 0, // mask for which players picked this item + 16 BOOL m_bFloating "Floating" 'F' = FALSE, + +components: + 1 model MODEL_ITEM "Models\\Items\\ItemHolder\\ItemHolder.mdl", + +functions: + virtual void AdjustDifficulty(void) + { + } + + /* Adjust model mip factor if needed. */ + void AdjustMipFactor(FLOAT &fMipFactor) + { + // adjust flare glow, to decrease power with how you get closer + CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_FLARE); + if( pamo != NULL) + { + FLOAT fRatio = (Clamp( fMipFactor, 5.0f, 7.0f)-5.0f)/2.0f; + UBYTE ubRatio = UBYTE(255*fRatio); + COLOR colMutiply = RGBToColor(ubRatio,ubRatio,ubRatio)|CT_OPAQUE; + pamo->amo_moModelObject.mo_colBlendColor = colMutiply; + } + + // if never picked + if (m_ulPickedMask==0) { + // don't bother testing + return; + } + + BOOL bFlare = TRUE; + // if current player has already picked this item + if (_ulPlayerRenderingMask&m_ulPickedMask) { + // if picked items are not rendered + extern INDEX plr_bRenderPicked; + if (!plr_bRenderPicked) { + // kill mip factor + fMipFactor = UpperLimit(0.0f); + } + // if picked item particles are not rendered + extern INDEX plr_bRenderPickedParticles; + if (!plr_bRenderPickedParticles) { + // kill flare + bFlare = FALSE; + } + } + + // implement flare on/off ? + } + + // check whether should render particles for this item + BOOL ShowItemParticles(void) + { + // if current player has already picked this item + if (_ulPlayerRenderingMask&m_ulPickedMask) { + // if picked item particles are not rendered + extern INDEX plr_bRenderPickedParticles; + if (!plr_bRenderPickedParticles) { + // don't render + return FALSE; + } + } + // otherwise, render + return TRUE; + } + + // check if given player already picked this item, and mark if not + BOOL MarkPickedBy(CEntity *pen) + { + if (!IsOfClass(pen, "Player")) { + return FALSE; + } + INDEX iPlayer = ((CPlayerEntity*)pen)->GetMyPlayerIndex(); + BOOL bPickedAlready = (1<GetAttachmentModel(ITEMHOLDER_ATTACHMENT_ITEM)->amo_moModelObject; + AddAttachmentToModel(this, mo, iAttachment, ulIDModel, ulIDTexture, + ulIDReflectionTexture, ulIDSpecularTexture, ulIDBumpTexture); + }; + // set animation of attachment + void SetItemAttachmentAnim(INDEX iAttachment, INDEX iAnim) + { + CModelObject &mo = + GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_ITEM)->amo_moModelObject. + GetAttachmentModel(iAttachment)->amo_moModelObject; + mo.PlayAnim(iAnim, 0); + } + + // Add flare + void AddFlare(ULONG ulIDModel, ULONG ulIDTexture, + const FLOAT3D &vPos, const FLOAT3D &vStretch) + { + // add flare to items if not respawn + if( !m_bRespawn && !m_bDropped) + { + AddAttachmentToModel(this, *GetModelObject(), + ITEMHOLDER_ATTACHMENT_FLARE, ulIDModel, ulIDTexture, 0,0,0); + CAttachmentModelObject &amo = *GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_FLARE); + amo.amo_moModelObject.StretchModel(vStretch); + amo.amo_plRelative.pl_PositionVector = vPos; + } + }; + + // Stretch item + void StretchItem(const FLOAT3D &vStretch) { + CModelObject &mo = GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_ITEM)->amo_moModelObject; + mo.StretchModel(vStretch); + ModelChangeNotify(); + }; + + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CItem) - sizeof(CMovableModelEntity) + CMovableModelEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strDescription.Length(); + slUsedMemory += m_strName.Length(); + slUsedMemory += 1* sizeof(CSoundObject); + return slUsedMemory; + } + + + +procedures: + +/************************************************************ + * VIRTUAL PROCEDURES THAT NEED OVERRIDE * + ************************************************************/ + ItemCollected(EPass epass) { return; }; + + + +/************************************************************ + * I T E M L O O P * + ************************************************************/ + + ItemLoop(EVoid) + { + m_fCustomRespawnTime = ClampDn( m_fCustomRespawnTime, 0.0f); + autowait(0.1f); + + SetPredictable(TRUE); + AdjustDifficulty(); + + wait() { + on (EBegin) : { resume; } + on (EPass epass) : { + if (!IsOfClass(epass.penOther, "Player")) { + pass; + } + if (!(m_bPickupOnce||m_bRespawn)) { + SendToTarget(m_penTarget, EET_TRIGGER, epass.penOther); + m_penTarget = NULL; + } + call ItemCollected(epass); + } + on (EEnd) : { stop; } + } + // wait for sound to end + autowait(m_fPickSoundLen+0.5f); + // cease to exist + Destroy(); + return; + }; + + + ItemReceived(EVoid) + { + // hide yourself + SwitchToEditorModel(); + if ((m_bPickupOnce||m_bRespawn)) { + SendToTarget(m_penTarget, EET_TRIGGER, NULL); + } + + // respawn item + if (m_bRespawn) { + ASSERT(m_fRespawnTime>0.0f); + + // wait to respawn + wait(m_fRespawnTime) { + on (EBegin) : { resume; } + on (ETimer) : { stop; } + otherwise() : { resume; } + } + // show yourself + SwitchToModel(); + + // cease to exist + } else { + return EEnd(); + } + return; + }; +}; + diff --git a/Sources/EntitiesMP/Item.h b/Sources/EntitiesMP/Item.h new file mode 100644 index 0000000..62b91ab --- /dev/null +++ b/Sources/EntitiesMP/Item.h @@ -0,0 +1,103 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Item_INCLUDED +#define _EntitiesMP_Item_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CItem_DLLClass; +class DECL_DLL CItem : public CMovableModelEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual const CTString &GetDescription(void) const { return m_strDescription; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + FLOAT m_fValue; + FLOAT m_fRespawnTime; + FLOAT m_fCustomRespawnTime; + BOOL m_bRespawn; + CEntityPointer m_penTarget; + BOOL m_bPickupOnce; + CSoundObject m_soPick; + FLOAT m_fPickSoundLen; + BOOL m_bDropped; + INDEX m_ulPickedMask; + BOOL m_bFloating; + CEntityPointer m_penPrediction; + +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +virtual void AdjustDifficulty(void); + +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void AdjustMipFactor(FLOAT & fMipFactor); + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +BOOL ShowItemParticles(void); + +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +BOOL MarkPickedBy(CEntity * pen); + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +FLOAT GetPredictionRange(void); + +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void Initialize(void); + +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void AddItem(ULONG ulIDModel,ULONG ulIDTexture, +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture); + +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void AddItemSpecial(INDEX iAttachmentPos,ULONG ulIDModel,ULONG ulIDTexture, +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture); + +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void AddItemAttachment(INDEX iAttachment,ULONG ulIDModel,ULONG ulIDTexture, +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture); + +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void SetItemAttachmentAnim(INDEX iAttachment,INDEX iAnim); + +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void AddFlare(ULONG ulIDModel,ULONG ulIDTexture, +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +const FLOAT3D & vPos,const FLOAT3D & vStretch); + +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +void StretchItem(const FLOAT3D & vStretch); + +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +SLONG GetUsedMemory(void); +#define STATE_CItem_ItemCollected 0x03200000 + BOOL +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ItemCollected(const CEntityEvent &__eeInput); +#define STATE_CItem_ItemLoop 0x03200001 + BOOL +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ItemLoop(const CEntityEvent &__eeInput); + BOOL H0x03200002_ItemLoop_01(const CEntityEvent &__eeInput); + BOOL H0x03200003_ItemLoop_02(const CEntityEvent &__eeInput); + BOOL H0x03200004_ItemLoop_03(const CEntityEvent &__eeInput); + BOOL H0x03200005_ItemLoop_04(const CEntityEvent &__eeInput); + BOOL H0x03200006_ItemLoop_05(const CEntityEvent &__eeInput); + BOOL H0x03200007_ItemLoop_06(const CEntityEvent &__eeInput); +#define STATE_CItem_ItemReceived 0x03200008 + BOOL +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ItemReceived(const CEntityEvent &__eeInput); + BOOL H0x03200009_ItemReceived_01(const CEntityEvent &__eeInput); + BOOL H0x0320000a_ItemReceived_02(const CEntityEvent &__eeInput); + BOOL H0x0320000b_ItemReceived_03(const CEntityEvent &__eeInput); + BOOL H0x0320000c_ItemReceived_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Item_INCLUDED diff --git a/Sources/EntitiesMP/Item_tables.h b/Sources/EntitiesMP/Item_tables.h new file mode 100644 index 0000000..a7f5ac9 --- /dev/null +++ b/Sources/EntitiesMP/Item_tables.h @@ -0,0 +1,63 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CItem + +CEntityProperty CItem_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000320<<8)+1, offsetof(CItem, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000320<<8)+2, offsetof(CItem, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000320<<8)+5, offsetof(CItem, m_fValue), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000320<<8)+6, offsetof(CItem, m_fRespawnTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000320<<8)+26, offsetof(CItem, m_fCustomRespawnTime), "Respawn Time", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000320<<8)+7, offsetof(CItem, m_bRespawn), "Respawn", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000320<<8)+8, offsetof(CItem, m_penTarget), "Target", 'T', C_dGRAY | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000320<<8)+9, offsetof(CItem, m_bPickupOnce), "PickupOnce", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000320<<8)+10, offsetof(CItem, m_soPick), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000320<<8)+12, offsetof(CItem, m_fPickSoundLen), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000320<<8)+14, offsetof(CItem, m_bDropped), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000320<<8)+15, offsetof(CItem, m_ulPickedMask), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000320<<8)+16, offsetof(CItem, m_bFloating), "Floating", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000320<<8)+255, offsetof(CItem, m_penPrediction), "", 0, 0, 0), +}; +#define CItem_propertiesct ARRAYCOUNT(CItem_properties) + +CEntityComponent CItem_components[] = { +#define MODEL_ITEM ((0x00000320<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_ITEM, "EFNM" "Models\\Items\\ItemHolder\\ItemHolder.mdl"), +}; +#define CItem_componentsct ARRAYCOUNT(CItem_components) + +CEventHandlerEntry CItem_handlers[] = { + {0x03200000, -1, CEntity::pEventHandler(&CItem:: +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ItemCollected),DEBUGSTRING("CItem::ItemCollected")}, + {0x03200001, -1, CEntity::pEventHandler(&CItem:: +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ItemLoop),DEBUGSTRING("CItem::ItemLoop")}, + {0x03200002, -1, CEntity::pEventHandler(&CItem::H0x03200002_ItemLoop_01), DEBUGSTRING("CItem::H0x03200002_ItemLoop_01")}, + {0x03200003, -1, CEntity::pEventHandler(&CItem::H0x03200003_ItemLoop_02), DEBUGSTRING("CItem::H0x03200003_ItemLoop_02")}, + {0x03200004, -1, CEntity::pEventHandler(&CItem::H0x03200004_ItemLoop_03), DEBUGSTRING("CItem::H0x03200004_ItemLoop_03")}, + {0x03200005, -1, CEntity::pEventHandler(&CItem::H0x03200005_ItemLoop_04), DEBUGSTRING("CItem::H0x03200005_ItemLoop_04")}, + {0x03200006, -1, CEntity::pEventHandler(&CItem::H0x03200006_ItemLoop_05), DEBUGSTRING("CItem::H0x03200006_ItemLoop_05")}, + {0x03200007, -1, CEntity::pEventHandler(&CItem::H0x03200007_ItemLoop_06), DEBUGSTRING("CItem::H0x03200007_ItemLoop_06")}, + {0x03200008, -1, CEntity::pEventHandler(&CItem:: +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Item.es" +ItemReceived),DEBUGSTRING("CItem::ItemReceived")}, + {0x03200009, -1, CEntity::pEventHandler(&CItem::H0x03200009_ItemReceived_01), DEBUGSTRING("CItem::H0x03200009_ItemReceived_01")}, + {0x0320000a, -1, CEntity::pEventHandler(&CItem::H0x0320000a_ItemReceived_02), DEBUGSTRING("CItem::H0x0320000a_ItemReceived_02")}, + {0x0320000b, -1, CEntity::pEventHandler(&CItem::H0x0320000b_ItemReceived_03), DEBUGSTRING("CItem::H0x0320000b_ItemReceived_03")}, + {0x0320000c, -1, CEntity::pEventHandler(&CItem::H0x0320000c_ItemReceived_04), DEBUGSTRING("CItem::H0x0320000c_ItemReceived_04")}, +}; +#define CItem_handlersct ARRAYCOUNT(CItem_handlers) + +CEntity *CItem_New(void) { return new CItem; }; +void CItem_OnInitClass(void) {}; +void CItem_OnEndClass(void) {}; +void CItem_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CItem_OnWorldEnd(CWorld *pwo) {}; +void CItem_OnWorldInit(CWorld *pwo) {}; +void CItem_OnWorldTick(CWorld *pwo) {}; +void CItem_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CItem, CMovableModelEntity, "Item", "", 0x00000320); +DECLARE_CTFILENAME(_fnmCItem_tbn, ""); diff --git a/Sources/EntitiesMP/KeyItem.cpp b/Sources/EntitiesMP/KeyItem.cpp new file mode 100644 index 0000000..01944db --- /dev/null +++ b/Sources/EntitiesMP/KeyItem.cpp @@ -0,0 +1,389 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" + +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" + +#include +#include +CEntityEvent *EKey::MakeCopy(void) { CEntityEvent *peeCopy = new EKey(*this); return peeCopy;} +EKey::EKey() : CEntityEvent(EVENTCODE_EKey) {; + ClearToDefault(kitType); +}; +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" + + +const char *GetKeyName(enum KeyItemType kit) +{ + switch(kit) { + case KIT_BOOKOFWISDOM : return TRANS("Book of wisdom"); break; + case KIT_CROSSWOODEN : return TRANS("Wooden cross"); break; + case KIT_CROSSGOLD : return TRANS("Gold cross"); break; + case KIT_CROSSMETAL : return TRANS("Silver cross"); break; + case KIT_JAGUARGOLDDUMMY : return TRANS("Gold jaguar"); break; + case KIT_HAWKWINGS01DUMMY : return TRANS("Hawk wings - part 1"); break; + case KIT_HAWKWINGS02DUMMY : return TRANS("Hawk wings - part 2"); break; + case KIT_HOLYGRAIL : return TRANS("Holy grail"); break; + case KIT_TABLESDUMMY : return TRANS("Tablet of wisdom"); break; + case KIT_WINGEDLION : return TRANS("Winged lion"); break; + case KIT_ELEPHANTGOLD : return TRANS("Gold elephant"); break; + case KIT_STATUEHEAD01 : return TRANS("Seriously scary ceremonial mask"); break; + case KIT_STATUEHEAD02 : return TRANS("Hilariously happy ceremonial mask"); break; + case KIT_STATUEHEAD03 : return TRANS("Ix Chel mask"); break; + case KIT_KINGSTATUE : return TRANS("Statue of King Tilmun"); break; + case KIT_CRYSTALSKULL : return TRANS("Crystal Skull"); break; + default: return TRANS("unknown item"); break; + }; +} + + +void CKeyItem::SetDefaultProperties(void) { + m_kitType = KIT_BOOKOFWISDOM ; + m_iSoundComponent = 0; + m_fSize = 1.0f; + CItem::SetDefaultProperties(); +} + +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +void CKeyItem::Precache(void) { +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +PrecacheSound (SOUND_KEY ); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +} + +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +BOOL CKeyItem::FillEntityStatistics(EntityStats * pes) +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +{ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +pes -> es_strName = GetKeyName (m_kitType ); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +pes -> es_ctCount = 1; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +pes -> es_ctAmmount = 1; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +pes -> es_fValue = 1; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +pes -> es_iScore = 0; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +return TRUE ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +} + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +void CKeyItem::RenderParticles(void) { +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +if(GetRenderType () != CEntity :: RT_MODEL || ! ShowItemParticles ()){ +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +return ; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +} +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +switch(m_kitType ){ +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_BOOKOFWISDOM : +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_CRYSTALSKULL : +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_HOLYGRAIL : +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +Particles_Stardust (this , 1.0f , 0.5f , PT_STAR08 , 64); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_JAGUARGOLDDUMMY : +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +Particles_Stardust (this , 2.0f , 2.0f , PT_STAR08 , 64); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_CROSSWOODEN : +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_CROSSMETAL : +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_CROSSGOLD : +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_HAWKWINGS01DUMMY : +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_HAWKWINGS02DUMMY : +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_TABLESDUMMY : +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_WINGEDLION : +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_ELEPHANTGOLD : +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_STATUEHEAD01 : +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_STATUEHEAD02 : +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_STATUEHEAD03 : +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_KINGSTATUE : +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +default : +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +Particles_Stardust (this , 1.5f , 1.1f , PT_STAR08 , 64); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +} +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +} + +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +void CKeyItem::SetProperties(void) +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +{ +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_strDescription = GetKeyName (m_kitType ); +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +switch(m_kitType ){ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_BOOKOFWISDOM : +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_BOOKOFWISDOM , TEXTURE_BOOKOFWISDOM , 0 , 0 , 0); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_CROSSWOODEN : +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_CROSSWOODEN , TEXTURE_CROSSWOODEN , 0 , 0 , 0); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_CROSSMETAL : +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_CROSSMETAL , TEXTURE_CROSSMETAL , TEX_REFL_METAL01 , TEX_SPEC_MEDIUM , 0); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_CROSSGOLD : +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_CROSSGOLD , TEXTURE_CROSSGOLD , TEX_REFL_GOLD01 , TEX_SPEC_MEDIUM , 0); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_JAGUARGOLDDUMMY : +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_JAGUARGOLD , TEX_REFL_GOLD01 , TEX_REFL_GOLD01 , TEX_SPEC_MEDIUM , 0); +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.5f , 0) , FLOAT3D (2 , 2 , 0.3f)); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_HAWKWINGS01DUMMY : +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_HAWKWINGS01 , TEXTURE_HAWKWINGS , 0 , 0 , 0); +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_HAWKWINGS02DUMMY : +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_HAWKWINGS02 , TEXTURE_HAWKWINGS , 0 , 0 , 0); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_HOLYGRAIL : +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_HOLYGRAIL , TEXTURE_HOLYGRAIL , TEX_REFL_METAL01 , TEX_SPEC_MEDIUM , 0); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_TABLESDUMMY : +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_TABLESOFWISDOM , TEXTURE_TABLESOFWISDOM , TEX_REFL_METAL01 , TEX_SPEC_MEDIUM , 0); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_WINGEDLION : +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_WINGEDLION , TEX_REFL_GOLD01 , TEX_REFL_GOLD01 , TEX_SPEC_MEDIUM , 0); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_ELEPHANTGOLD : +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_ELEPHANTGOLD , TEX_REFL_GOLD01 , TEX_REFL_GOLD01 , TEX_SPEC_MEDIUM , 0); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.5f , 0) , FLOAT3D (2 , 2 , 0.3f)); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_STATUEHEAD01 : +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_STATUEHEAD01 , TEXTURE_STATUEHEAD01 , 0 , 0 , 0); +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_STATUEHEAD02 : +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_STATUEHEAD02 , TEXTURE_STATUEHEAD02 , 0 , 0 , 0); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_STATUEHEAD03 : +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_STATUEHEAD03 , TEXTURE_STATUEHEAD03 , 0 , 0 , 0); +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_KINGSTATUE : +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_KINGSTATUE , TEX_REFL_GOLD01 , TEX_REFL_GOLD01 , TEX_SPEC_MEDIUM , 0); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +case KIT_CRYSTALSKULL : +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddItem (MODEL_CRYSTALSKULL , TEXTURE_CRYSTALSKULL , TEX_REFL_METAL01 , TEX_SPEC_MEDIUM , 0); +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +break ; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +} +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fSize , m_fSize , m_fSize )); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +} +BOOL CKeyItem:: +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +ItemCollected(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CKeyItem_ItemCollected + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EPass, "CKeyItem::ItemCollected expects 'EPass' as input!"); const EPass &epass = (const EPass &)__eeInput; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +ASSERT (epass . penOther != NULL ); +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +EKey eKey ; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +eKey . kitType = m_kitType ; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +if(epass . penOther -> ReceiveItem (eKey )){ +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +if(_pNetwork -> IsPlayerLocal (epass . penOther )){IFeel_PlayEffect ("PU_Key");} +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_soPick . Set3DParameters (50.0f , 1.0f , 1.0f , 1.0f); +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +PlaySound (m_soPick , m_iSoundComponent , SOF_3D ); +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +m_fPickSoundLen = GetSoundLength (m_iSoundComponent ); +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemReceived, FALSE, EVoid());return TRUE; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +} +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +Return(STATE_CURRENT,EVoid()); +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CKeyItem:: +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CKeyItem_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CKeyItem::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +Initialize (); +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_BIG ); +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +SetProperties (); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/KeyItem.es b/Sources/EntitiesMP/KeyItem.es new file mode 100644 index 0000000..636e9bf --- /dev/null +++ b/Sources/EntitiesMP/KeyItem.es @@ -0,0 +1,344 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +805 +%{ +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" +%} + +uses "EntitiesMP/Item"; + +// key type +enum KeyItemType { + 0 KIT_BOOKOFWISDOM "Book of wisdom", + 1 KIT_CROSSWOODEN "Wooden cross", + 2 KIT_CROSSMETAL "Silver cross", + 3 KIT_CROSSGOLD "Gold cross", + 4 KIT_JAGUARGOLDDUMMY "Gold jaguar", + 5 KIT_HAWKWINGS01DUMMY "Hawk wings - part 1", + 6 KIT_HAWKWINGS02DUMMY "Hawk wings - part 2", + 7 KIT_HOLYGRAIL "Holy grail", + 8 KIT_TABLESDUMMY "Tablet of wisdom", + 9 KIT_WINGEDLION "Winged lion", + 10 KIT_ELEPHANTGOLD "Gold elephant", + 11 KIT_STATUEHEAD01 "Seriously scary ceremonial mask", + 12 KIT_STATUEHEAD02 "Hilariously happy ceremonial mask", + 13 KIT_STATUEHEAD03 "Ix Chel mask", + 14 KIT_KINGSTATUE "Statue of King Tilmun", + 15 KIT_CRYSTALSKULL "Crystal Skull", +}; + +// event for sending through receive item +event EKey { + enum KeyItemType kitType, +}; + +%{ + +const char *GetKeyName(enum KeyItemType kit) +{ + switch(kit) { + case KIT_BOOKOFWISDOM : return TRANS("Book of wisdom"); break; + case KIT_CROSSWOODEN : return TRANS("Wooden cross"); break; + case KIT_CROSSGOLD : return TRANS("Gold cross"); break; + case KIT_CROSSMETAL : return TRANS("Silver cross"); break; + case KIT_JAGUARGOLDDUMMY : return TRANS("Gold jaguar"); break; + case KIT_HAWKWINGS01DUMMY : return TRANS("Hawk wings - part 1"); break; + case KIT_HAWKWINGS02DUMMY : return TRANS("Hawk wings - part 2"); break; + case KIT_HOLYGRAIL : return TRANS("Holy grail"); break; + case KIT_TABLESDUMMY : return TRANS("Tablet of wisdom"); break; + case KIT_WINGEDLION : return TRANS("Winged lion"); break; + case KIT_ELEPHANTGOLD : return TRANS("Gold elephant"); break; + case KIT_STATUEHEAD01 : return TRANS("Seriously scary ceremonial mask"); break; + case KIT_STATUEHEAD02 : return TRANS("Hilariously happy ceremonial mask"); break; + case KIT_STATUEHEAD03 : return TRANS("Ix Chel mask"); break; + case KIT_KINGSTATUE : return TRANS("Statue of King Tilmun"); break; + case KIT_CRYSTALSKULL : return TRANS("Crystal Skull"); break; + default: return TRANS("unknown item"); break; + }; +} + +%} + +class CKeyItem : CItem { +name "KeyItem"; +thumbnail "Thumbnails\\KeyItem.tbn"; +features "IsImportant"; + +properties: + 1 enum KeyItemType m_kitType "Type" 'Y' = KIT_BOOKOFWISDOM, // key type + 3 INDEX m_iSoundComponent = 0, + 5 FLOAT m_fSize "Size" = 1.0f, + +components: + 0 class CLASS_BASE "Classes\\Item.ecl", + +// ********* ANKH KEY ********* + 1 model MODEL_BOOKOFWISDOM "ModelsMP\\Items\\Keys\\BookOfWisdom\\Book.mdl", + 2 texture TEXTURE_BOOKOFWISDOM "ModelsMP\\Items\\Keys\\BookOfWisdom\\Book.tex", + + 5 model MODEL_CROSSWOODEN "ModelsMP\\Items\\Keys\\Cross\\Cross.mdl", + 6 texture TEXTURE_CROSSWOODEN "ModelsMP\\Items\\Keys\\Cross\\CrossWooden.tex", + + 7 model MODEL_CROSSMETAL "ModelsMP\\Items\\Keys\\Cross\\Cross.mdl", + 8 texture TEXTURE_CROSSMETAL "ModelsMP\\Items\\Keys\\Cross\\CrossMetal.tex", + + 10 model MODEL_CROSSGOLD "ModelsMP\\Items\\Keys\\GoldCross\\Cross.mdl", + 11 texture TEXTURE_CROSSGOLD "ModelsMP\\Items\\Keys\\GoldCross\\Cross.tex", + + 15 model MODEL_JAGUARGOLD "ModelsMP\\Items\\Keys\\GoldJaguar\\Jaguar.mdl", + + 20 model MODEL_HAWKWINGS01 "ModelsMP\\Items\\Keys\\HawkWings\\WingRight.mdl", + 21 model MODEL_HAWKWINGS02 "ModelsMP\\Items\\Keys\\HawkWings\\WingLeft.mdl", + 22 texture TEXTURE_HAWKWINGS "ModelsMP\\Items\\Keys\\HawkWings\\Wings.tex", + + 30 model MODEL_HOLYGRAIL "ModelsMP\\Items\\Keys\\HolyGrail\\Grail.mdl", + 31 texture TEXTURE_HOLYGRAIL "ModelsMP\\Items\\Keys\\HolyGrail\\Grail.tex", + + 35 model MODEL_TABLESOFWISDOM "ModelsMP\\Items\\Keys\\TablesOfWisdom\\Tables.mdl", + 36 texture TEXTURE_TABLESOFWISDOM "ModelsMP\\Items\\Keys\\TablesOfWisdom\\Tables.tex", + + 40 model MODEL_WINGEDLION "ModelsMP\\Items\\Keys\\WingLion\\WingLion.mdl", + + 45 model MODEL_ELEPHANTGOLD "ModelsMP\\Items\\Keys\\GoldElephant\\Elephant.mdl", + + 50 model MODEL_STATUEHEAD01 "ModelsMP\\Items\\Keys\\Statue01\\Statue.mdl", + 51 texture TEXTURE_STATUEHEAD01 "ModelsMP\\Items\\Keys\\Statue01\\Statue.tex", + 52 model MODEL_STATUEHEAD02 "ModelsMP\\Items\\Keys\\Statue02\\Statue.mdl", + 53 texture TEXTURE_STATUEHEAD02 "ModelsMP\\Items\\Keys\\Statue02\\Statue.tex", + 54 model MODEL_STATUEHEAD03 "ModelsMP\\Items\\Keys\\Statue03\\Statue.mdl", + 55 texture TEXTURE_STATUEHEAD03 "ModelsMP\\Items\\Keys\\Statue03\\Statue.tex", + + 58 model MODEL_KINGSTATUE "ModelsMP\\Items\\Keys\\ManStatue\\Statue.mdl", + + 60 model MODEL_CRYSTALSKULL "ModelsMP\\Items\\Keys\\CrystalSkull\\Skull.mdl", + 61 texture TEXTURE_CRYSTALSKULL "ModelsMP\\Items\\Keys\\CrystalSkull\\Skull.tex", + + // ********* MISC ********* +250 texture TEXTURE_FLARE "ModelsMP\\Items\\Flares\\Flare.tex", +251 model MODEL_FLARE "ModelsMP\\Items\\Flares\\Flare.mdl", +252 texture TEX_REFL_GOLD01 "ModelsMP\\ReflectionTextures\\Gold01.tex", +253 texture TEX_REFL_METAL01 "ModelsMP\\ReflectionTextures\\LightMetal01.tex", +254 texture TEX_SPEC_MEDIUM "ModelsMP\\SpecularTextures\\Medium.tex", +255 texture TEX_SPEC_STRONG "ModelsMP\\SpecularTextures\\Strong.tex", + +// ************** SOUNDS ************** +300 sound SOUND_KEY "Sounds\\Items\\Key.wav", + +functions: + void Precache(void) { + PrecacheSound(SOUND_KEY); + } + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + pes->es_strName = GetKeyName(m_kitType); + pes->es_ctCount = 1; + pes->es_ctAmmount = 1; + pes->es_fValue = 1; + pes->es_iScore = 0;//m_iScore; + return TRUE; + } + + // render particles + void RenderParticles(void) { + // no particles when not existing + if (GetRenderType()!=CEntity::RT_MODEL || !ShowItemParticles()) { + return; + } + switch (m_kitType) { + case KIT_BOOKOFWISDOM : + case KIT_CRYSTALSKULL : + case KIT_HOLYGRAIL : + Particles_Stardust(this, 1.0f, 0.5f, PT_STAR08, 64); + break; + case KIT_JAGUARGOLDDUMMY : + Particles_Stardust(this, 2.0f, 2.0f, PT_STAR08, 64); + break; + case KIT_CROSSWOODEN : + case KIT_CROSSMETAL : + case KIT_CROSSGOLD : + case KIT_HAWKWINGS01DUMMY: + case KIT_HAWKWINGS02DUMMY: + case KIT_TABLESDUMMY : + case KIT_WINGEDLION : + case KIT_ELEPHANTGOLD : + case KIT_STATUEHEAD01 : + case KIT_STATUEHEAD02 : + case KIT_STATUEHEAD03 : + case KIT_KINGSTATUE : + default: + Particles_Stardust(this, 1.5f, 1.1f, PT_STAR08, 64); + break; + } + } + + + + // set health properties depending on type + void SetProperties(void) + { + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription = GetKeyName(m_kitType); + + switch (m_kitType) { + case KIT_BOOKOFWISDOM : + // set appearance + AddItem(MODEL_BOOKOFWISDOM, TEXTURE_BOOKOFWISDOM , 0, 0, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_CROSSWOODEN: + // set appearance + AddItem(MODEL_CROSSWOODEN, TEXTURE_CROSSWOODEN, 0, 0, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_CROSSMETAL: + // set appearance + AddItem(MODEL_CROSSMETAL, TEXTURE_CROSSMETAL, TEX_REFL_METAL01, TEX_SPEC_MEDIUM, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_CROSSGOLD: + // set appearance + AddItem(MODEL_CROSSGOLD, TEXTURE_CROSSGOLD, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_JAGUARGOLDDUMMY: + // set appearance + AddItem(MODEL_JAGUARGOLD, TEX_REFL_GOLD01, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.5f,0), FLOAT3D(2,2,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_HAWKWINGS01DUMMY: + // set appearance + AddItem(MODEL_HAWKWINGS01, TEXTURE_HAWKWINGS, 0, 0, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_HAWKWINGS02DUMMY: + // set appearance + AddItem(MODEL_HAWKWINGS02, TEXTURE_HAWKWINGS, 0, 0, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_HOLYGRAIL: + // set appearance + AddItem(MODEL_HOLYGRAIL, TEXTURE_HOLYGRAIL, TEX_REFL_METAL01, TEX_SPEC_MEDIUM, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_TABLESDUMMY: + // set appearance + AddItem(MODEL_TABLESOFWISDOM, TEXTURE_TABLESOFWISDOM, TEX_REFL_METAL01, TEX_SPEC_MEDIUM, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_WINGEDLION: + // set appearance + AddItem(MODEL_WINGEDLION, TEX_REFL_GOLD01, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_ELEPHANTGOLD: + // set appearance + AddItem(MODEL_ELEPHANTGOLD, TEX_REFL_GOLD01, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.5f,0), FLOAT3D(2,2,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_STATUEHEAD01: + // set appearance + AddItem(MODEL_STATUEHEAD01, TEXTURE_STATUEHEAD01, 0, 0, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_STATUEHEAD02: + // set appearance + AddItem(MODEL_STATUEHEAD02, TEXTURE_STATUEHEAD02, 0, 0, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_STATUEHEAD03: + // set appearance + AddItem(MODEL_STATUEHEAD03, TEXTURE_STATUEHEAD03, 0, 0, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_KINGSTATUE: + // set appearance + AddItem(MODEL_KINGSTATUE, TEX_REFL_GOLD01, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + case KIT_CRYSTALSKULL: + // set appearance + AddItem(MODEL_CRYSTALSKULL, TEXTURE_CRYSTALSKULL, TEX_REFL_METAL01, TEX_SPEC_MEDIUM, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + break; + } + GetModelObject()->StretchModel(FLOAT3D(m_fSize, m_fSize, m_fSize)); + }; + +procedures: + ItemCollected(EPass epass) : CItem::ItemCollected { + ASSERT(epass.penOther!=NULL); + + // send key to entity + EKey eKey; + eKey.kitType = m_kitType; + // if health is received + if (epass.penOther->ReceiveItem(eKey)) { + if(_pNetwork->IsPlayerLocal(epass.penOther)) {IFeel_PlayEffect("PU_Key");} + // play the pickup sound + m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f); + PlaySound(m_soPick, m_iSoundComponent, SOF_3D); + m_fPickSoundLen = GetSoundLength(m_iSoundComponent); + jump CItem::ItemReceived(); + } + return; + }; + + Main() { + Initialize(); // initialize base class + StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_BIG); + SetProperties(); // set properties + + jump CItem::ItemLoop(); + }; +}; diff --git a/Sources/EntitiesMP/KeyItem.h b/Sources/EntitiesMP/KeyItem.h new file mode 100644 index 0000000..00e3ed5 --- /dev/null +++ b/Sources/EntitiesMP/KeyItem.h @@ -0,0 +1,65 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_KeyItem_INCLUDED +#define _EntitiesMP_KeyItem_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType KeyItemType_enum; +enum KeyItemType { + KIT_BOOKOFWISDOM = 0, + KIT_CROSSWOODEN = 1, + KIT_CROSSMETAL = 2, + KIT_CROSSGOLD = 3, + KIT_JAGUARGOLDDUMMY = 4, + KIT_HAWKWINGS01DUMMY = 5, + KIT_HAWKWINGS02DUMMY = 6, + KIT_HOLYGRAIL = 7, + KIT_TABLESDUMMY = 8, + KIT_WINGEDLION = 9, + KIT_ELEPHANTGOLD = 10, + KIT_STATUEHEAD01 = 11, + KIT_STATUEHEAD02 = 12, + KIT_STATUEHEAD03 = 13, + KIT_KINGSTATUE = 14, + KIT_CRYSTALSKULL = 15, +}; +DECL_DLL inline void ClearToDefault(KeyItemType &e) { e = (KeyItemType)0; } ; +#define EVENTCODE_EKey 0x03250000 +class DECL_DLL EKey : public CEntityEvent { +public: +EKey(); +CEntityEvent *MakeCopy(void); +enum KeyItemType kitType; +}; +DECL_DLL inline void ClearToDefault(EKey &e) { e = EKey(); } ; +extern "C" DECL_DLL CDLLEntityClass CKeyItem_DLLClass; +class CKeyItem : public CItem { +public: +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + enum KeyItemType m_kitType; + INDEX m_iSoundComponent; + FLOAT m_fSize; + +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +void Precache(void); + +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +void RenderParticles(void); + +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +void SetProperties(void); +#define STATE_CKeyItem_ItemCollected 0x03250001 + BOOL +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +ItemCollected(const CEntityEvent &__eeInput); +#define STATE_CKeyItem_Main 1 + BOOL +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_KeyItem_INCLUDED diff --git a/Sources/EntitiesMP/KeyItem_tables.h b/Sources/EntitiesMP/KeyItem_tables.h new file mode 100644 index 0000000..222c9bc --- /dev/null +++ b/Sources/EntitiesMP/KeyItem_tables.h @@ -0,0 +1,126 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(KeyItemType) + EP_ENUMVALUE(KIT_BOOKOFWISDOM, "Book of wisdom"), + EP_ENUMVALUE(KIT_CROSSWOODEN, "Wooden cross"), + EP_ENUMVALUE(KIT_CROSSMETAL, "Silver cross"), + EP_ENUMVALUE(KIT_CROSSGOLD, "Gold cross"), + EP_ENUMVALUE(KIT_JAGUARGOLDDUMMY, "Gold jaguar"), + EP_ENUMVALUE(KIT_HAWKWINGS01DUMMY, "Hawk wings - part 1"), + EP_ENUMVALUE(KIT_HAWKWINGS02DUMMY, "Hawk wings - part 2"), + EP_ENUMVALUE(KIT_HOLYGRAIL, "Holy grail"), + EP_ENUMVALUE(KIT_TABLESDUMMY, "Tablet of wisdom"), + EP_ENUMVALUE(KIT_WINGEDLION, "Winged lion"), + EP_ENUMVALUE(KIT_ELEPHANTGOLD, "Gold elephant"), + EP_ENUMVALUE(KIT_STATUEHEAD01, "Seriously scary ceremonial mask"), + EP_ENUMVALUE(KIT_STATUEHEAD02, "Hilariously happy ceremonial mask"), + EP_ENUMVALUE(KIT_STATUEHEAD03, "Ix Chel mask"), + EP_ENUMVALUE(KIT_KINGSTATUE, "Statue of King Tilmun"), + EP_ENUMVALUE(KIT_CRYSTALSKULL, "Crystal Skull"), +EP_ENUMEND(KeyItemType); + +#define ENTITYCLASS CKeyItem + +CEntityProperty CKeyItem_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &KeyItemType_enum, (0x00000325<<8)+1, offsetof(CKeyItem, m_kitType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000325<<8)+3, offsetof(CKeyItem, m_iSoundComponent), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000325<<8)+5, offsetof(CKeyItem, m_fSize), "Size", 0, 0x7F0000FFUL, 0), +}; +#define CKeyItem_propertiesct ARRAYCOUNT(CKeyItem_properties) + +CEntityComponent CKeyItem_components[] = { +#define CLASS_BASE ((0x00000325<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\Item.ecl"), +#define MODEL_BOOKOFWISDOM ((0x00000325<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_BOOKOFWISDOM, "EFNM" "ModelsMP\\Items\\Keys\\BookOfWisdom\\Book.mdl"), +#define TEXTURE_BOOKOFWISDOM ((0x00000325<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_BOOKOFWISDOM, "EFNM" "ModelsMP\\Items\\Keys\\BookOfWisdom\\Book.tex"), +#define MODEL_CROSSWOODEN ((0x00000325<<8)+5) + CEntityComponent(ECT_MODEL, MODEL_CROSSWOODEN, "EFNM" "ModelsMP\\Items\\Keys\\Cross\\Cross.mdl"), +#define TEXTURE_CROSSWOODEN ((0x00000325<<8)+6) + CEntityComponent(ECT_TEXTURE, TEXTURE_CROSSWOODEN, "EFNM" "ModelsMP\\Items\\Keys\\Cross\\CrossWooden.tex"), +#define MODEL_CROSSMETAL ((0x00000325<<8)+7) + CEntityComponent(ECT_MODEL, MODEL_CROSSMETAL, "EFNM" "ModelsMP\\Items\\Keys\\Cross\\Cross.mdl"), +#define TEXTURE_CROSSMETAL ((0x00000325<<8)+8) + CEntityComponent(ECT_TEXTURE, TEXTURE_CROSSMETAL, "EFNM" "ModelsMP\\Items\\Keys\\Cross\\CrossMetal.tex"), +#define MODEL_CROSSGOLD ((0x00000325<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_CROSSGOLD, "EFNM" "ModelsMP\\Items\\Keys\\GoldCross\\Cross.mdl"), +#define TEXTURE_CROSSGOLD ((0x00000325<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_CROSSGOLD, "EFNM" "ModelsMP\\Items\\Keys\\GoldCross\\Cross.tex"), +#define MODEL_JAGUARGOLD ((0x00000325<<8)+15) + CEntityComponent(ECT_MODEL, MODEL_JAGUARGOLD, "EFNM" "ModelsMP\\Items\\Keys\\GoldJaguar\\Jaguar.mdl"), +#define MODEL_HAWKWINGS01 ((0x00000325<<8)+20) + CEntityComponent(ECT_MODEL, MODEL_HAWKWINGS01, "EFNM" "ModelsMP\\Items\\Keys\\HawkWings\\WingRight.mdl"), +#define MODEL_HAWKWINGS02 ((0x00000325<<8)+21) + CEntityComponent(ECT_MODEL, MODEL_HAWKWINGS02, "EFNM" "ModelsMP\\Items\\Keys\\HawkWings\\WingLeft.mdl"), +#define TEXTURE_HAWKWINGS ((0x00000325<<8)+22) + CEntityComponent(ECT_TEXTURE, TEXTURE_HAWKWINGS, "EFNM" "ModelsMP\\Items\\Keys\\HawkWings\\Wings.tex"), +#define MODEL_HOLYGRAIL ((0x00000325<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_HOLYGRAIL, "EFNM" "ModelsMP\\Items\\Keys\\HolyGrail\\Grail.mdl"), +#define TEXTURE_HOLYGRAIL ((0x00000325<<8)+31) + CEntityComponent(ECT_TEXTURE, TEXTURE_HOLYGRAIL, "EFNM" "ModelsMP\\Items\\Keys\\HolyGrail\\Grail.tex"), +#define MODEL_TABLESOFWISDOM ((0x00000325<<8)+35) + CEntityComponent(ECT_MODEL, MODEL_TABLESOFWISDOM, "EFNM" "ModelsMP\\Items\\Keys\\TablesOfWisdom\\Tables.mdl"), +#define TEXTURE_TABLESOFWISDOM ((0x00000325<<8)+36) + CEntityComponent(ECT_TEXTURE, TEXTURE_TABLESOFWISDOM, "EFNM" "ModelsMP\\Items\\Keys\\TablesOfWisdom\\Tables.tex"), +#define MODEL_WINGEDLION ((0x00000325<<8)+40) + CEntityComponent(ECT_MODEL, MODEL_WINGEDLION, "EFNM" "ModelsMP\\Items\\Keys\\WingLion\\WingLion.mdl"), +#define MODEL_ELEPHANTGOLD ((0x00000325<<8)+45) + CEntityComponent(ECT_MODEL, MODEL_ELEPHANTGOLD, "EFNM" "ModelsMP\\Items\\Keys\\GoldElephant\\Elephant.mdl"), +#define MODEL_STATUEHEAD01 ((0x00000325<<8)+50) + CEntityComponent(ECT_MODEL, MODEL_STATUEHEAD01, "EFNM" "ModelsMP\\Items\\Keys\\Statue01\\Statue.mdl"), +#define TEXTURE_STATUEHEAD01 ((0x00000325<<8)+51) + CEntityComponent(ECT_TEXTURE, TEXTURE_STATUEHEAD01, "EFNM" "ModelsMP\\Items\\Keys\\Statue01\\Statue.tex"), +#define MODEL_STATUEHEAD02 ((0x00000325<<8)+52) + CEntityComponent(ECT_MODEL, MODEL_STATUEHEAD02, "EFNM" "ModelsMP\\Items\\Keys\\Statue02\\Statue.mdl"), +#define TEXTURE_STATUEHEAD02 ((0x00000325<<8)+53) + CEntityComponent(ECT_TEXTURE, TEXTURE_STATUEHEAD02, "EFNM" "ModelsMP\\Items\\Keys\\Statue02\\Statue.tex"), +#define MODEL_STATUEHEAD03 ((0x00000325<<8)+54) + CEntityComponent(ECT_MODEL, MODEL_STATUEHEAD03, "EFNM" "ModelsMP\\Items\\Keys\\Statue03\\Statue.mdl"), +#define TEXTURE_STATUEHEAD03 ((0x00000325<<8)+55) + CEntityComponent(ECT_TEXTURE, TEXTURE_STATUEHEAD03, "EFNM" "ModelsMP\\Items\\Keys\\Statue03\\Statue.tex"), +#define MODEL_KINGSTATUE ((0x00000325<<8)+58) + CEntityComponent(ECT_MODEL, MODEL_KINGSTATUE, "EFNM" "ModelsMP\\Items\\Keys\\ManStatue\\Statue.mdl"), +#define MODEL_CRYSTALSKULL ((0x00000325<<8)+60) + CEntityComponent(ECT_MODEL, MODEL_CRYSTALSKULL, "EFNM" "ModelsMP\\Items\\Keys\\CrystalSkull\\Skull.mdl"), +#define TEXTURE_CRYSTALSKULL ((0x00000325<<8)+61) + CEntityComponent(ECT_TEXTURE, TEXTURE_CRYSTALSKULL, "EFNM" "ModelsMP\\Items\\Keys\\CrystalSkull\\Skull.tex"), +#define TEXTURE_FLARE ((0x00000325<<8)+250) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE, "EFNM" "ModelsMP\\Items\\Flares\\Flare.tex"), +#define MODEL_FLARE ((0x00000325<<8)+251) + CEntityComponent(ECT_MODEL, MODEL_FLARE, "EFNM" "ModelsMP\\Items\\Flares\\Flare.mdl"), +#define TEX_REFL_GOLD01 ((0x00000325<<8)+252) + CEntityComponent(ECT_TEXTURE, TEX_REFL_GOLD01, "EFNM" "ModelsMP\\ReflectionTextures\\Gold01.tex"), +#define TEX_REFL_METAL01 ((0x00000325<<8)+253) + CEntityComponent(ECT_TEXTURE, TEX_REFL_METAL01, "EFNM" "ModelsMP\\ReflectionTextures\\LightMetal01.tex"), +#define TEX_SPEC_MEDIUM ((0x00000325<<8)+254) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_MEDIUM, "EFNM" "ModelsMP\\SpecularTextures\\Medium.tex"), +#define TEX_SPEC_STRONG ((0x00000325<<8)+255) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_STRONG, "EFNM" "ModelsMP\\SpecularTextures\\Strong.tex"), +#define SOUND_KEY ((0x00000325<<8)+300) + CEntityComponent(ECT_SOUND, SOUND_KEY, "EFNM" "Sounds\\Items\\Key.wav"), +}; +#define CKeyItem_componentsct ARRAYCOUNT(CKeyItem_components) + +CEventHandlerEntry CKeyItem_handlers[] = { + {0x03250001, STATE_CItem_ItemCollected, CEntity::pEventHandler(&CKeyItem:: +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +ItemCollected),DEBUGSTRING("CKeyItem::ItemCollected")}, + {1, -1, CEntity::pEventHandler(&CKeyItem:: +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/KeyItem.es" +Main),DEBUGSTRING("CKeyItem::Main")}, +}; +#define CKeyItem_handlersct ARRAYCOUNT(CKeyItem_handlers) + +CEntity *CKeyItem_New(void) { return new CKeyItem; }; +void CKeyItem_OnInitClass(void) {}; +void CKeyItem_OnEndClass(void) {}; +void CKeyItem_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CKeyItem_OnWorldEnd(CWorld *pwo) {}; +void CKeyItem_OnWorldInit(CWorld *pwo) {}; +void CKeyItem_OnWorldTick(CWorld *pwo) {}; +void CKeyItem_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CKeyItem, CItem, "KeyItem", "Thumbnails\\KeyItem.tbn", 0x00000325); +DECLARE_CTFILENAME(_fnmCKeyItem_tbn, "Thumbnails\\KeyItem.tbn"); diff --git a/Sources/EntitiesMP/LarvaOffspring.cpp b/Sources/EntitiesMP/LarvaOffspring.cpp new file mode 100644 index 0000000..c72e987 --- /dev/null +++ b/Sources/EntitiesMP/LarvaOffspring.cpp @@ -0,0 +1,474 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" + +#include "StdH.h" + +#include "EntitiesMP/EnemyBase.h" +#include "ModelsMP/Enemies/ExotechLarva/Projectile/TailProjectile.h" + + +#include +#include +CEntityEvent *ELaunchLarvaOffspring::MakeCopy(void) { CEntityEvent *peeCopy = new ELaunchLarvaOffspring(*this); return peeCopy;} +ELaunchLarvaOffspring::ELaunchLarvaOffspring() : CEntityEvent(EVENTCODE_ELaunchLarvaOffspring) {; + ClearToDefault(penLauncher); +}; +#line 23 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" + +#define ECF_OFFSPRING ( \ + ((ECBI_MODEL|ECBI_BRUSH|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID|ECBI_ITEM|ECBI_MODEL_HOLDER|ECBI_CORPSE_SOLID)< 0){ +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(_pTimer -> CurrentTick () > m_fStartTime + m_tmExpandBox ){ +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ChangeCollisionBoxIndexWhenPossible (1); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +m_tmExpandBox = 0; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +CMovableModelEntity :: PreMoving (); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void CLarvaOffspring::Precache() +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +PrecacheSound (SOUND_LARVETTE ); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +PrecacheModel (MODEL_LARVA_TAIL ); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +PrecacheTexture (TEXTURE_LARVA_TAIL ); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_ROCKET ); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_SHOCKWAVE ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void CLarvaOffspring::InitializeProjectile(void) { +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(IsDerivedFromClass (m_penLauncher , "Enemy Base")){ +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +m_penTarget = ((CEnemyBase *) & * m_penLauncher ) -> m_penEnemy ; +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +InitAsModel (); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SetPhysicsFlags (EPF_MODEL_SLIDING ); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SetCollisionFlags (ECF_OFFSPRING ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SetModel (MODEL_LARVA_TAIL ); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SetModelMainTexture (TEXTURE_LARVA_TAIL ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +GetModelObject () -> StretchModel (FLOAT3D (4.0f , 4.0f , 4.0f)); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ModelChangeNotify (); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +m_soEffect . Set3DParameters (50.0f , 10.0f , 1.0f , 1.0f); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +PlaySound (m_soEffect , SOUND_LARVETTE , SOF_3D | SOF_LOOP ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +m_fFlyTime = 12.0f; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +m_fDamageAmount = 10.0f; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +m_aRotateSpeed = 275.0f; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SetHealth (10.0f); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void CLarvaOffspring::LarvaTailExplosion(void) { +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ESpawnEffect ese ; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT3D vPoint ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOATplane3D vPlaneNormal ; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT fDistanceToEdge ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ese . betType = BET_ROCKET ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ese . vStretch = FLOAT3D (1 , 1 , 1); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SpawnEffect (GetPlacement () , ese ); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(IsDerivedFromClass (m_penLauncher , "Player")){ +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SpawnRangeSound (m_penLauncher , this , SNDT_PLAYER , m_fSoundRange ); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ese . betType = BET_EXPLOSION_DEBRIS ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SpawnEffect (GetPlacement () , ese ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ese . betType = BET_EXPLOSION_SMOKE ; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SpawnEffect (GetPlacement () , ese ); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )){ +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f){ +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ese . betType = BET_EXPLOSIONSTAIN ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ese . betType = BET_SHOCKWAVE ; +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ese . betType = BET_ROCKET_PLANE ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SpawnEffect (CPlacement3D (vPoint + ese . vNormal / 50.0f , ANGLE3D (0 , 0 , 0)) , ese ); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void CLarvaOffspring::ProjectileTouch(CEntityPointer penHit) +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ProjectileHit (); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT3D vDirection ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT fTransLen = en_vIntendedTranslation . Length (); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(fTransLen > 0.5f) +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +vDirection = en_vIntendedTranslation / fTransLen ; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +else +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +vDirection = - en_vGravityDir ; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +const FLOAT fDamageMul = GetSeriousDamageMultiplier (m_penLauncher ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +InflictDirectDamage (penHit , m_penLauncher , DMT_PROJECTILE , m_fDamageAmount * fDamageMul , +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +GetPlacement () . pl_PositionVector , vDirection ); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} + +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void CLarvaOffspring::ProjectileHit(void) +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(m_bExplode ){ +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +const FLOAT fDamageMul = GetSeriousDamageMultiplier (m_penLauncher ); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +InflictRangeDamage (m_penLauncher , DMT_EXPLOSION , m_fRangeDamageAmount * fDamageMul , +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +GetPlacement () . pl_PositionVector , m_fDamageHotSpotRange , m_fDamageFallOffRange ); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(m_fSoundRange > 0.0f){ +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ESound eSound ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +eSound . EsndtSound = SNDT_EXPLOSION ; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +eSound . penTarget = m_penLauncher ; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SendEventInRange (eSound , FLOATaabbox3D (GetPlacement () . pl_PositionVector , m_fSoundRange )); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} + +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void CLarvaOffspring::SpawnEffect(const CPlacement3D & plEffect,const ESpawnEffect & eSpawnEffect) { +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +CEntityPointer penEffect = CreateEntity (plEffect , CLASS_BASIC_EFFECT ); +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +penEffect -> Initialize (eSpawnEffect ); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} + +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ANGLE CLarvaOffspring::GetRotationSpeed(ANGLE aWantedAngle,ANGLE aRotateSpeed,FLOAT fWaitFrequency) +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ANGLE aResult ; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(aWantedAngle < - aRotateSpeed * fWaitFrequency ) +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +aResult = - aRotateSpeed ; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +else if(aWantedAngle > aRotateSpeed * fWaitFrequency ) +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +aResult = + aRotateSpeed ; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +else +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +aResult = aWantedAngle / fWaitFrequency ; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +return aResult ; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +BOOL CLarvaOffspring:: +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +LarvaOffspringGuidedSlide(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CLarvaOffspring_LarvaOffspringGuidedSlide + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CLarvaOffspring::LarvaOffspringGuidedSlide expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +CEntity * penObstacle ; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(CheckForCollisionNow (0 , & penObstacle )){ +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ProjectileTouch (penObstacle ); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +Return(STATE_CURRENT,EEnd ()); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +return TRUE; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +Jump(STATE_CURRENT,0x01610004, FALSE, EInternal());return TRUE;}BOOL CLarvaOffspring::H0x01610004_LarvaOffspringGuidedSlide_03(const CEntityEvent &__eeInput) +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01610004 +if(!(_pTimer -> CurrentTick () < (m_fStartTime + m_fFlyTime ))){ Jump(STATE_CURRENT,0x01610005, FALSE, EInternal());return TRUE;} +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT fWaitFrequency = 0.1f; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(m_penTarget != NULL ){ +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +EntityInfo * pei = (EntityInfo *) (m_penTarget -> GetEntityInfo ()); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT3D vDesiredPosition ; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +GetEntityInfoPosition (m_penTarget , pei -> vSourceCenter , vDesiredPosition ); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT3D vDesiredDirection = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Normalize (); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ANGLE aWantedHeading = GetRelativeHeading (vDesiredDirection ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ANGLE aHeading = GetRotationSpeed (aWantedHeading , m_aRotateSpeed , fWaitFrequency ); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT fSpeedDecreasingFactor = ((180 - Abs (aWantedHeading )) / 180.0f); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT fSpeedIncreasingFactor = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Length () / 100; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +fSpeedIncreasingFactor = ClampDn (fSpeedIncreasingFactor , 1.0f); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT fMaxSpeed = 30.0f * fSpeedIncreasingFactor ; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT fMinSpeedRatio = 0.5f; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT fWantedSpeed = fMaxSpeed * (fMinSpeedRatio + (1 - fMinSpeedRatio ) * fSpeedDecreasingFactor ); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SetDesiredTranslation (FLOAT3D (0 , 0 , - fWantedSpeed )); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +m_aRotateSpeed = 75.0f * (1 + 0.5f * fSpeedDecreasingFactor ); +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT fDistanceFactor = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Length () / 50.0; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +fDistanceFactor = ClampUp (fDistanceFactor , 4.0f); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +FLOAT fRNDHeading = (FRnd () - 0.5f) * 180 * fDistanceFactor ; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(Abs (aWantedHeading ) < 30.0f) +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SetDesiredRotation (ANGLE3D (aHeading + fRNDHeading , 0 , 0)); +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +else +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{ +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SetDesiredRotation (ANGLE3D (aHeading , 0 , 0)); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SetTimerAfter(fWaitFrequency ); +Jump(STATE_CURRENT, 0x01610002, FALSE, EBegin());return TRUE;}BOOL CLarvaOffspring::H0x01610002_LarvaOffspringGuidedSlide_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01610002 +switch(__eeInput.ee_slEvent) +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&epass= (EPass&)__eeInput; + +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +BOOL bHit ; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +bHit = epass . penOther != m_penLauncher || _pTimer -> CurrentTick () > m_fIgnoreTime ; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +bHit &= ! IsOfClass (epass . penOther , "LarvaOffspring"); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +bHit &= ! IsOfClass (epass . penOther , "Twister"); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +if(bHit ){ +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ProjectileTouch (epass . penOther ); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +Return(STATE_CURRENT,EEnd ()); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +return TRUE; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +} +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +return TRUE; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath): +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{const EDeath&e= (EDeath&)__eeInput; + +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ProjectileHit (); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +Return(STATE_CURRENT,EEnd ()); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +return TRUE; +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer): +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +{const ETimer&e= (ETimer&)__eeInput; + +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +UnsetTimer();Jump(STATE_CURRENT,0x01610003, FALSE, EInternal());return TRUE; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +}return TRUE;}BOOL CLarvaOffspring::H0x01610003_LarvaOffspringGuidedSlide_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01610003 +Jump(STATE_CURRENT,0x01610004, FALSE, EInternal());return TRUE; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +}BOOL CLarvaOffspring::H0x01610005_LarvaOffspringGuidedSlide_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01610005 + +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +Return(STATE_CURRENT,EEnd ()); +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CLarvaOffspring:: +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CLarvaOffspring_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_ELaunchLarvaOffspring, "CLarvaOffspring::Main expects 'ELaunchLarvaOffspring' as input!"); const ELaunchLarvaOffspring &eLaunch = (const ELaunchLarvaOffspring &)__eeInput; +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ASSERT (eLaunch . penLauncher != NULL ); +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +m_penLauncher = eLaunch . penLauncher ; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +SetPredictable (TRUE ); +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +m_fIgnoreTime = _pTimer -> CurrentTick () + 1.0f; +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +InitializeProjectile (); +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +m_fStartTime = _pTimer -> CurrentTick (); +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +STATE_CLarvaOffspring_LarvaOffspringGuidedSlide, TRUE; +Jump(STATE_CURRENT, 0x01610006, FALSE, EBegin());return TRUE;}BOOL CLarvaOffspring::H0x01610006_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01610006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CLarvaOffspring_LarvaOffspringGuidedSlide, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01610007, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CLarvaOffspring::H0x01610007_Main_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01610007 +const EEnd&__e= (EEnd&)__eeInput; +; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +LarvaTailExplosion (); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +Destroy (); +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +Return(STATE_CURRENT,EVoid()); +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/LarvaOffspring.es b/Sources/EntitiesMP/LarvaOffspring.es new file mode 100644 index 0000000..38d35bf --- /dev/null +++ b/Sources/EntitiesMP/LarvaOffspring.es @@ -0,0 +1,346 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +353 +%{ +#include "StdH.h" + +#include "EntitiesMP/EnemyBase.h" +#include "ModelsMP/Enemies/ExotechLarva/Projectile/TailProjectile.h" + +%} + +uses "EntitiesMP/BasicEffects"; +uses "EntitiesMP/Light"; +uses "EntitiesMP/Flame"; + + +// input parameter for launching the LarvaOffspring +event ELaunchLarvaOffspring { + CEntityPointer penLauncher, // who launched it +}; + + +%{ +#define ECF_OFFSPRING ( \ + ((ECBI_MODEL|ECBI_BRUSH|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID|ECBI_ITEM|ECBI_MODEL_HOLDER|ECBI_CORPSE_SOLID)< range damage + 24 FLOAT m_aRotateSpeed = 0.0f, // speed of rotation for guided LarvaOffsprings*/ + 25 FLOAT m_tmExpandBox = 0.0f, // expand collision after a few seconds + 30 CSoundObject m_soEffect, // sound channel + + 50 BOOL bLockedOn = TRUE, + + +components: + 1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + +10 model MODEL_LARVA_TAIL "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\TailProjectile.mdl", +11 texture TEXTURE_LARVA_TAIL "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\TailProjectile.tex", +12 sound SOUND_LARVETTE "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\Squeak.wav", + + +functions: + // premoving + void PreMoving(void) { + if (m_tmExpandBox>0) { + if (_pTimer->CurrentTick()>m_fStartTime+m_tmExpandBox) { + ChangeCollisionBoxIndexWhenPossible(1); + m_tmExpandBox = 0; + } + } + CMovableModelEntity::PreMoving(); + } + + void Precache() + { + PrecacheSound(SOUND_LARVETTE); + PrecacheModel(MODEL_LARVA_TAIL); + PrecacheTexture(TEXTURE_LARVA_TAIL); + PrecacheClass(CLASS_BASIC_EFFECT, BET_ROCKET); + PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + } + +void InitializeProjectile(void) { + + // we need target for guided misile + if (IsDerivedFromClass(m_penLauncher, "Enemy Base")) { + m_penTarget = ((CEnemyBase *) &*m_penLauncher)->m_penEnemy; + } + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_SLIDING); + SetCollisionFlags(ECF_OFFSPRING); + + SetModel(MODEL_LARVA_TAIL); + SetModelMainTexture(TEXTURE_LARVA_TAIL); + GetModelObject()->StretchModel(FLOAT3D(4.0f, 4.0f, 4.0f)); + + ModelChangeNotify(); + // play the flying sound + m_soEffect.Set3DParameters(50.0f, 10.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_LARVETTE, SOF_3D|SOF_LOOP); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 12.0f; + m_fDamageAmount = 10.0f; + m_aRotateSpeed = 275.0f; + SetHealth(10.0f); +} + +void LarvaTailExplosion(void) { + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + // explosion + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_ROCKET; + ese.vStretch = FLOAT3D(1,1,1); + SpawnEffect(GetPlacement(), ese); + // spawn sound event in range + if( IsDerivedFromClass( m_penLauncher, "Player")) { + SpawnRangeSound( m_penLauncher, this, SNDT_PLAYER, m_fSoundRange); + } + + // explosion debris + ese.betType = BET_EXPLOSION_DEBRIS; + SpawnEffect(GetPlacement(), ese); + + // explosion smoke + ese.betType = BET_EXPLOSION_SMOKE; + SpawnEffect(GetPlacement(), ese); + + // on plane + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) { + // stain + ese.betType = BET_EXPLOSIONSTAIN; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // shock wave + ese.betType = BET_SHOCKWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // second explosion on plane + ese.betType = BET_ROCKET_PLANE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f, ANGLE3D(0, 0, 0)), ese); + } + } +} + + +/************************************************************ + * C O M M O N F U N C T I O N S * + ************************************************************/ + +void ProjectileTouch(CEntityPointer penHit) +{ + // explode if needed + ProjectileHit(); + + // direct damage + FLOAT3D vDirection; + FLOAT fTransLen = en_vIntendedTranslation.Length(); + if( fTransLen>0.5f) + { + vDirection = en_vIntendedTranslation/fTransLen; + } + else + { + vDirection = -en_vGravityDir; + } + + const FLOAT fDamageMul = GetSeriousDamageMultiplier(m_penLauncher); + + InflictDirectDamage(penHit, m_penLauncher, DMT_PROJECTILE, m_fDamageAmount*fDamageMul, + GetPlacement().pl_PositionVector, vDirection); + +}; + + +void ProjectileHit(void) +{ + // explode ... + if (m_bExplode) { + const FLOAT fDamageMul = GetSeriousDamageMultiplier(m_penLauncher); + InflictRangeDamage(m_penLauncher, DMT_EXPLOSION, m_fRangeDamageAmount*fDamageMul, + GetPlacement().pl_PositionVector, m_fDamageHotSpotRange, m_fDamageFallOffRange); + } + // sound event + if (m_fSoundRange > 0.0f) { + ESound eSound; + eSound.EsndtSound = SNDT_EXPLOSION; + eSound.penTarget = m_penLauncher; + SendEventInRange(eSound, FLOATaabbox3D(GetPlacement().pl_PositionVector, m_fSoundRange)); + } +}; + + +// spawn effect +void SpawnEffect(const CPlacement3D &plEffect, const ESpawnEffect &eSpawnEffect) { + CEntityPointer penEffect = CreateEntity(plEffect, CLASS_BASIC_EFFECT); + penEffect->Initialize(eSpawnEffect); +}; + + +// Calculate current rotation speed to rich given orientation in future +ANGLE GetRotationSpeed(ANGLE aWantedAngle, ANGLE aRotateSpeed, FLOAT fWaitFrequency) +{ + ANGLE aResult; + // if desired position is smaller + if ( aWantedAngle<-aRotateSpeed*fWaitFrequency) + { + // start decreasing + aResult = -aRotateSpeed; + } + // if desired position is bigger + else if (aWantedAngle>aRotateSpeed*fWaitFrequency) + { + // start increasing + aResult = +aRotateSpeed; + } + // if desired position is more-less ahead + else + { + aResult = aWantedAngle/fWaitFrequency; + } + return aResult; +} + +/************************************************************ + * P R O C E D U R E S * + ************************************************************/ +procedures: + + LarvaOffspringGuidedSlide(EVoid) { + // if already inside some entity + CEntity *penObstacle; + if (CheckForCollisionNow(0, &penObstacle)) { + // explode now + ProjectileTouch(penObstacle); + return EEnd(); + } + // fly loop + while( _pTimer->CurrentTick()<(m_fStartTime+m_fFlyTime)) + { + FLOAT fWaitFrequency = 0.1f; + if (m_penTarget!=NULL) { + // calculate desired position and angle + EntityInfo *pei= (EntityInfo*) (m_penTarget->GetEntityInfo()); + FLOAT3D vDesiredPosition; + GetEntityInfoPosition( m_penTarget, pei->vSourceCenter, vDesiredPosition); + FLOAT3D vDesiredDirection = (vDesiredPosition-GetPlacement().pl_PositionVector).Normalize(); + // for heading + ANGLE aWantedHeading = GetRelativeHeading( vDesiredDirection); + ANGLE aHeading = GetRotationSpeed( aWantedHeading, m_aRotateSpeed, fWaitFrequency); + + // factor used to decrease speed of LarvaOffsprings oriented opposite of its target + FLOAT fSpeedDecreasingFactor = ((180-Abs(aWantedHeading))/180.0f); + // factor used to increase speed when far away from target + FLOAT fSpeedIncreasingFactor = (vDesiredPosition-GetPlacement().pl_PositionVector).Length()/100; + fSpeedIncreasingFactor = ClampDn(fSpeedIncreasingFactor, 1.0f); + // decrease speed acodring to target's direction + FLOAT fMaxSpeed = 30.0f*fSpeedIncreasingFactor; + FLOAT fMinSpeedRatio = 0.5f; + FLOAT fWantedSpeed = fMaxSpeed*( fMinSpeedRatio+(1-fMinSpeedRatio)*fSpeedDecreasingFactor); + // adjust translation velocity + SetDesiredTranslation( FLOAT3D(0, 0, -fWantedSpeed)); + + // adjust rotation speed + m_aRotateSpeed = 75.0f*(1+0.5f*fSpeedDecreasingFactor); + + // calculate distance factor + FLOAT fDistanceFactor = (vDesiredPosition-GetPlacement().pl_PositionVector).Length()/50.0; + fDistanceFactor = ClampUp(fDistanceFactor, 4.0f); + FLOAT fRNDHeading = (FRnd()-0.5f)*180*fDistanceFactor; + + // if we are looking near direction of target + if( Abs( aWantedHeading) < 30.0f) + { + // adjust heading and pich + SetDesiredRotation(ANGLE3D(aHeading+fRNDHeading,0,0)); + } + // just adjust heading + else + { + SetDesiredRotation(ANGLE3D(aHeading,0,0)); + } + } + + wait( fWaitFrequency) + { + on (EBegin) : { resume; } + on (EPass epass) : { + BOOL bHit; + // ignore launcher within 1 second + bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime; + // ignore another LarvaOffspring + bHit &= !IsOfClass(epass.penOther, "LarvaOffspring"); + // ignore twister + bHit &= !IsOfClass(epass.penOther, "Twister"); + if (bHit) { + ProjectileTouch(epass.penOther); + return EEnd(); + } + resume; + } + on (EDeath) : + { + ProjectileHit(); + return EEnd(); + } + on (ETimer) : + { + stop; + } + } + } + return EEnd(); + }; + + + Main(ELaunchLarvaOffspring eLaunch) { + // remember the initial parameters + ASSERT(eLaunch.penLauncher!=NULL); + m_penLauncher = eLaunch.penLauncher; + SetPredictable(TRUE); + // remember lauching time + m_fIgnoreTime = _pTimer->CurrentTick() + 1.0f; + + InitializeProjectile(); + + // fly + m_fStartTime = _pTimer->CurrentTick(); + autocall LarvaOffspringGuidedSlide() EEnd; + + LarvaTailExplosion(); + + Destroy(); + + return; + } +}; diff --git a/Sources/EntitiesMP/LarvaOffspring.h b/Sources/EntitiesMP/LarvaOffspring.h new file mode 100644 index 0000000..192694f --- /dev/null +++ b/Sources/EntitiesMP/LarvaOffspring.h @@ -0,0 +1,79 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_LarvaOffspring_INCLUDED +#define _EntitiesMP_LarvaOffspring_INCLUDED 1 +#include +#include +#include +#define EVENTCODE_ELaunchLarvaOffspring 0x01610000 +class DECL_DLL ELaunchLarvaOffspring : public CEntityEvent { +public: +ELaunchLarvaOffspring(); +CEntityEvent *MakeCopy(void); +CEntityPointer penLauncher; +}; +DECL_DLL inline void ClearToDefault(ELaunchLarvaOffspring &e) { e = ELaunchLarvaOffspring(); } ; +extern "C" DECL_DLL CDLLEntityClass CLarvaOffspring_DLLClass; +class DECL_DLL CLarvaOffspring : public CMovableModelEntity { +public: +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + virtual void SetDefaultProperties(void); + CEntityPointer m_penLauncher; + CEntityPointer m_penTarget; + FLOAT m_fIgnoreTime; + FLOAT m_fFlyTime; + FLOAT m_fStartTime; + FLOAT m_fDamageAmount; + FLOAT m_fRangeDamageAmount; + FLOAT m_fDamageHotSpotRange; + FLOAT m_fDamageFallOffRange; + FLOAT m_fSoundRange; + BOOL m_bExplode; + FLOAT m_aRotateSpeed; + FLOAT m_tmExpandBox; + CSoundObject m_soEffect; + BOOL bLockedOn; + CEntityPointer m_penPrediction; + +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void PreMoving(void); + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void Precache(); + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void InitializeProjectile(void); + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void LarvaTailExplosion(void); + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void ProjectileTouch(CEntityPointer penHit); + +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void ProjectileHit(void); + +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +void SpawnEffect(const CPlacement3D & plEffect,const ESpawnEffect & eSpawnEffect); + +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +ANGLE GetRotationSpeed(ANGLE aWantedAngle,ANGLE aRotateSpeed,FLOAT fWaitFrequency); +#define STATE_CLarvaOffspring_LarvaOffspringGuidedSlide 0x01610001 + BOOL +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +LarvaOffspringGuidedSlide(const CEntityEvent &__eeInput); + BOOL H0x01610002_LarvaOffspringGuidedSlide_01(const CEntityEvent &__eeInput); + BOOL H0x01610003_LarvaOffspringGuidedSlide_02(const CEntityEvent &__eeInput); + BOOL H0x01610004_LarvaOffspringGuidedSlide_03(const CEntityEvent &__eeInput); + BOOL H0x01610005_LarvaOffspringGuidedSlide_04(const CEntityEvent &__eeInput); +#define STATE_CLarvaOffspring_Main 1 + BOOL +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01610006_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01610007_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_LarvaOffspring_INCLUDED diff --git a/Sources/EntitiesMP/LarvaOffspring_tables.h b/Sources/EntitiesMP/LarvaOffspring_tables.h new file mode 100644 index 0000000..658091d --- /dev/null +++ b/Sources/EntitiesMP/LarvaOffspring_tables.h @@ -0,0 +1,64 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CLarvaOffspring + +CEntityProperty CLarvaOffspring_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000161<<8)+1, offsetof(CLarvaOffspring, m_penLauncher), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000161<<8)+5, offsetof(CLarvaOffspring, m_penTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000161<<8)+11, offsetof(CLarvaOffspring, m_fIgnoreTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000161<<8)+12, offsetof(CLarvaOffspring, m_fFlyTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000161<<8)+13, offsetof(CLarvaOffspring, m_fStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000161<<8)+14, offsetof(CLarvaOffspring, m_fDamageAmount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000161<<8)+15, offsetof(CLarvaOffspring, m_fRangeDamageAmount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000161<<8)+16, offsetof(CLarvaOffspring, m_fDamageHotSpotRange), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000161<<8)+17, offsetof(CLarvaOffspring, m_fDamageFallOffRange), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000161<<8)+18, offsetof(CLarvaOffspring, m_fSoundRange), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000161<<8)+19, offsetof(CLarvaOffspring, m_bExplode), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000161<<8)+24, offsetof(CLarvaOffspring, m_aRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000161<<8)+25, offsetof(CLarvaOffspring, m_tmExpandBox), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000161<<8)+30, offsetof(CLarvaOffspring, m_soEffect), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000161<<8)+50, offsetof(CLarvaOffspring, bLockedOn), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000161<<8)+255, offsetof(CLarvaOffspring, m_penPrediction), "", 0, 0, 0), +}; +#define CLarvaOffspring_propertiesct ARRAYCOUNT(CLarvaOffspring_properties) + +CEntityComponent CLarvaOffspring_components[] = { +#define CLASS_BASIC_EFFECT ((0x00000161<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define MODEL_LARVA_TAIL ((0x00000161<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_LARVA_TAIL, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\TailProjectile.mdl"), +#define TEXTURE_LARVA_TAIL ((0x00000161<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_LARVA_TAIL, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\TailProjectile.tex"), +#define SOUND_LARVETTE ((0x00000161<<8)+12) + CEntityComponent(ECT_SOUND, SOUND_LARVETTE, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\Squeak.wav"), +}; +#define CLarvaOffspring_componentsct ARRAYCOUNT(CLarvaOffspring_components) + +CEventHandlerEntry CLarvaOffspring_handlers[] = { + {0x01610001, -1, CEntity::pEventHandler(&CLarvaOffspring:: +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +LarvaOffspringGuidedSlide),DEBUGSTRING("CLarvaOffspring::LarvaOffspringGuidedSlide")}, + {0x01610002, -1, CEntity::pEventHandler(&CLarvaOffspring::H0x01610002_LarvaOffspringGuidedSlide_01), DEBUGSTRING("CLarvaOffspring::H0x01610002_LarvaOffspringGuidedSlide_01")}, + {0x01610003, -1, CEntity::pEventHandler(&CLarvaOffspring::H0x01610003_LarvaOffspringGuidedSlide_02), DEBUGSTRING("CLarvaOffspring::H0x01610003_LarvaOffspringGuidedSlide_02")}, + {0x01610004, -1, CEntity::pEventHandler(&CLarvaOffspring::H0x01610004_LarvaOffspringGuidedSlide_03), DEBUGSTRING("CLarvaOffspring::H0x01610004_LarvaOffspringGuidedSlide_03")}, + {0x01610005, -1, CEntity::pEventHandler(&CLarvaOffspring::H0x01610005_LarvaOffspringGuidedSlide_04), DEBUGSTRING("CLarvaOffspring::H0x01610005_LarvaOffspringGuidedSlide_04")}, + {1, -1, CEntity::pEventHandler(&CLarvaOffspring:: +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/LarvaOffspring.es" +Main),DEBUGSTRING("CLarvaOffspring::Main")}, + {0x01610006, -1, CEntity::pEventHandler(&CLarvaOffspring::H0x01610006_Main_01), DEBUGSTRING("CLarvaOffspring::H0x01610006_Main_01")}, + {0x01610007, -1, CEntity::pEventHandler(&CLarvaOffspring::H0x01610007_Main_02), DEBUGSTRING("CLarvaOffspring::H0x01610007_Main_02")}, +}; +#define CLarvaOffspring_handlersct ARRAYCOUNT(CLarvaOffspring_handlers) + +CEntity *CLarvaOffspring_New(void) { return new CLarvaOffspring; }; +void CLarvaOffspring_OnInitClass(void) {}; +void CLarvaOffspring_OnEndClass(void) {}; +void CLarvaOffspring_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CLarvaOffspring_OnWorldEnd(CWorld *pwo) {}; +void CLarvaOffspring_OnWorldInit(CWorld *pwo) {}; +void CLarvaOffspring_OnWorldTick(CWorld *pwo) {}; +void CLarvaOffspring_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CLarvaOffspring, CMovableModelEntity, "LarvaOffspring", "", 0x00000161); +DECLARE_CTFILENAME(_fnmCLarvaOffspring_tbn, ""); diff --git a/Sources/EntitiesMP/LastFileID.txt b/Sources/EntitiesMP/LastFileID.txt new file mode 100644 index 0000000..89451e3 --- /dev/null +++ b/Sources/EntitiesMP/LastFileID.txt @@ -0,0 +1,7 @@ +Last ES ID number: + +Enemies: 356 (GruntSka) +Tools: 241 (HudPicHolder) +Items: 807 (MessageItem) +Weapons: 354 (Serious Bomb) +Effects: 616 (Fireworks) diff --git a/Sources/EntitiesMP/Light.cpp b/Sources/EntitiesMP/Light.cpp new file mode 100644 index 0000000..be1ea17 --- /dev/null +++ b/Sources/EntitiesMP/Light.cpp @@ -0,0 +1,649 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" + +#include "StdH.h" + +#include +#include +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" + + +void CLight_OnInitClass(void) +{ + // init lens flares effects + InitLensFlares(); +} + +void CLight_OnEndClass(void) +{ + // close lens flares effects + CloseLensFlares(); +} + + +void CLight::SetDefaultProperties(void) { + m_colColor = C_GRAY ; + m_colAmbient = C_BLACK ; + m_rFallOffRange = 8.0f; + m_rHotSpotRange = 0.0f; + m_itIllumination = 0; + m_ltType = LT_POINT ; + m_strDescription = ""; + m_strName = "Light"; + m_bDarkLight = FALSE ; + m_fNearClip = 0.1f; + m_fFarClip = 0.01f; + m_bSubstractSectorAmbient = FALSE ; + m_bRenderAsSmallLight = FALSE ; + m_lftLensFlare = LFT_NONE ; + m_bBackground = FALSE ; + m_bLensFlareOnly = FALSE ; + m_fnmLightAnimation = CTString(""); + m_iLightAnimation = 0; + m_tmOffsetPhase = 0.0f; + m_aoLightAnimation.SetData(NULL); + + m_bTargetable = FALSE ; + m_bDynamic = FALSE ; + m_bDiffusion = TRUE ; + m_fnmAmbientLightAnimation = CTString(""); + m_iAmbientLightAnimation = 0; + m_aoAmbientLightAnimation.SetData(NULL); + + CEntity::SetDefaultProperties(); +} + +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +CAnimData * CLight::GetAnimData(SLONG slPropertyOffset) +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(slPropertyOffset == offsetof (CLight , m_iLightAnimation )) +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return m_aoLightAnimation . GetData (); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +else if(slPropertyOffset == offsetof (CLight , m_iAmbientLightAnimation )) +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return m_aoAmbientLightAnimation . GetData (); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +else +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return CEntity :: GetAnimData (slPropertyOffset ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +BOOL CLight::IsTargetable(void)const +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return m_bTargetable ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} + +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +BOOL CLight::IsImportant(void)const +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return (m_ltType == LT_DIRECTIONAL ); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +BOOL CLight::HandleEvent(const CEntityEvent & ee) +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(ee . ee_slEvent == EVENTCODE_ERangeModelDestruction ) +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_colColor = C_BLACK ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_colAmbient = C_BLACK ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +CLightSource lsNew ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetupLightSource (lsNew ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return TRUE ; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +else if(ee . ee_slEvent == EVENTCODE_EChangeAnim ) +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +EChangeAnim & eChange = (EChangeAnim &) ee ; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_iLightAnimation = eChange . iLightAnim ; +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_aoLightAnimation . GetData () != NULL ) +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_aoLightAnimation . PlayAnim (m_iLightAnimation , eChange . bLightLoop ? AOF_LOOPING : 0); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_iAmbientLightAnimation = eChange . iAmbientLightAnim ; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_aoAmbientLightAnimation . GetData () != NULL ) +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_aoAmbientLightAnimation . PlayAnim (m_iAmbientLightAnimation , eChange . bAmbientLightLoop ? AOF_LOOPING : 0); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if((m_aoLightAnimation . GetData () == NULL ) && (m_aoAmbientLightAnimation . GetData () == NULL )) +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_colColor = eChange . colDiffuse ; +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_colAmbient = eChange . colAmbient ; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +CLightSource lsNew ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetupLightSource (lsNew ); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return TRUE ; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return FALSE ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} + +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +void CLight::MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX) +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_rFallOffRange *= fStretch ; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_rHotSpotRange *= fStretch ; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_fNearClip *= fStretch ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_fFarClip *= fStretch ; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +CLightSource * CLight::GetLightSource(void) +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(! m_bdfInitialized . bdf_bValue ){ +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +CLightSource lsNew ; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetupLightSource (lsNew ); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_lsLightSource . SetLightSourceWithNoDiscarding (lsNew ); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_bdfInitialized . bdf_bValue = TRUE ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(! IsPredictor ()){ +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return & m_lsLightSource ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +}else { +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return NULL ; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} + +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +void CLight::SetupLightSource(CLightSource & lsNew) +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +switch(m_ltType ){ +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LT_POINT : +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LT_STRONG_POINT : +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_ulFlags = LSF_CASTSHADOWS ; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LT_DIRECTIONAL : +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_ulFlags = LSF_DIRECTIONAL | LSF_CASTSHADOWS ; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LT_STRONG_AMBIENT : +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LT_AMBIENT : +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_ulFlags = 0; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_bSubstractSectorAmbient ){lsNew . ls_ulFlags |= LSF_SUBSTRACTSECTORAMBIENT ;} +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_bLensFlareOnly ){lsNew . ls_ulFlags |= LSF_LENSFLAREONLY ;} +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_bDynamic ){lsNew . ls_ulFlags |= LSF_DYNAMIC ;} +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_bDarkLight ){ +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_ltType == LT_DIRECTIONAL ){ +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_ulFlags &= ~ LSF_DARKLIGHT ; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_bDarkLight = FALSE ; +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +}else { +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_ulFlags |= LSF_DARKLIGHT ; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_bDiffusion ){ +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_bDynamic || m_ltType == LT_AMBIENT || m_ltType == LT_STRONG_AMBIENT ){ +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_ulFlags &= ~ LSF_DIFFUSION ; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_bDiffusion = FALSE ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +}else { +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_ulFlags |= LSF_DIFFUSION ; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_rHotSpot = m_rHotSpotRange ; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_rFallOff = m_rFallOffRange ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_fNearClipDistance = m_fNearClip ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_fFarClipDistance = m_fFarClip ; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_ltType == LT_STRONG_AMBIENT || m_ltType == LT_STRONG_POINT ){ +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_rHotSpot = lsNew . ls_rFallOff * 0.9f; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_colColor = m_colColor ; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_colAmbient = C_BLACK ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(lsNew . ls_ulFlags & LSF_DIRECTIONAL ){lsNew . ls_colAmbient = m_colAmbient ;} +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_ubPolygonalMask = (UBYTE ) m_itIllumination ; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +switch(m_lftLensFlare ) +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_NONE : +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = NULL ; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_STANDARD : +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftStandard ; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_STANDARD_REFLECTIONS : +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftStandardReflections ; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_YELLOW_STAR_RED_RING : +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftYellowStarRedRing ; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_WHITE_GLOW_STAR_RED_RING : +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftWhiteGlowStarRedRing ; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_WHITE_GLOW_STAR : +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftWhiteGlowStar ; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_WHITE_STAR_RED_RING_STREAKS : +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftWhiteStarRedRingStreaks ; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_WHITE_STAR_RED_REFLECTIONS : +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftWhiteStarRedReflections ; +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_BLUE_STAR_BLUE_REFLECTIONS : +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftBlueStarBlueReflections ; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_PV_SPACE_SHIP_WINDOW_FLARE : +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftPVSpaceShipWindowFlare ; +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_WHITE_GLOW_STAR_RED_RING_FAR : +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftYellowStarRedRingFar ; +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_WHITE_GLOW_FAR : +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftWhiteGlowFar ; +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +case LFT_WHITE_GLOW_STAR_NG : +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_plftLensFlare = & _lftWhiteGlowStarNG ; +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +break ; +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_paoLightAnimation = NULL ; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_paoLightAnimation = & m_aoLightAnimation ; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_paoAmbientLightAnimation = NULL ; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_aoAmbientLightAnimation . GetData () != NULL ){ +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +lsNew . ls_paoAmbientLightAnimation = & m_aoAmbientLightAnimation ; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} + +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SLONG CLight::GetUsedMemory(void) +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SLONG slUsedMemory = sizeof (CLight ) - sizeof (CEntity ) + CEntity :: GetUsedMemory (); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +slUsedMemory += m_strDescription . Length (); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +slUsedMemory += m_strName . Length (); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +slUsedMemory += m_fnmLightAnimation . Length (); +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +slUsedMemory += m_fnmAmbientLightAnimation . Length (); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +slUsedMemory += 2 * sizeof (CAnimObject); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return slUsedMemory ; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +BOOL CLight:: +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CLight_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CLight::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_rFallOffRange < 0){ +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_rFallOffRange = 0.0f; +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_rHotSpotRange < 0){ +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_rHotSpotRange = 0.0f; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_rHotSpotRange > m_rFallOffRange ){ +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_rHotSpotRange = m_rFallOffRange ; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_fNearClip <= 0.01f){ +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_fNearClip = 0.01f; +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_fFarClip <= 0){ +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_fFarClip = 0.0f; +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_ltType != LT_DIRECTIONAL ){ +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_colAmbient = C_BLACK ; +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +InitAsEditorModel (); +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_bRenderAsSmallLight ) +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +GetModelObject () -> mo_Stretch = FLOAT3D (0.25f , 0.25f , 0.25f); +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +else +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_ltType != LT_DIRECTIONAL ){ +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +const float LIGHT_MINSIZE = 0.5f; +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +FLOAT fFactor = Log2 (m_rFallOffRange ) * LIGHT_MINSIZE ; +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(fFactor < LIGHT_MINSIZE ){ +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +fFactor = LIGHT_MINSIZE ; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +GetModelObject () -> mo_Stretch = FLOAT3D (fFactor , fFactor , fFactor ); +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +CTString strType ; +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_ltType == LT_POINT || m_ltType == LT_STRONG_POINT ) +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +strType = "point"; +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetModel (MODEL_LIGHT_SOURCE ); +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetModelMainTexture (TEXTURE_POINT_LIGHT ); +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +else if(m_ltType == LT_AMBIENT ) +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +strType = "ambient"; +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetModel (MODEL_LIGHT_SOURCE ); +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetModelMainTexture (TEXTURE_AMBIENT_LIGHT ); +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +else if(m_ltType == LT_STRONG_AMBIENT ) +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +strType = "ambient"; +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetModel (MODEL_LIGHT_SOURCE ); +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetModelMainTexture (TEXTURE_REAL_AMBIENT_LIGHT ); +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +else if(m_ltType == LT_DIRECTIONAL ) +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +strType = "directional"; +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetModel (MODEL_SPOT_LIGHT ); +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetModelMainTexture (TEXTURE_SPOT_LIGHT ); +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_bDarkLight ) +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +{ +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +strType = strType + ", dark"; +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +try { +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_aoLightAnimation . SetData_t (m_fnmLightAnimation ); +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +}catch (char * strError ){ +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +WarningMessage (TRANS ("Cannot load '%s': %s") , (CTString &) m_fnmLightAnimation , strError ); +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_fnmLightAnimation = ""; +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_aoLightAnimation . PlayAnim (m_iLightAnimation , AOF_LOOPING ); +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_aoLightAnimation . OffsetPhase (m_tmOffsetPhase * m_aoLightAnimation . GetCurrentAnimLength ()); +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +try { +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_aoAmbientLightAnimation . SetData_t (m_fnmAmbientLightAnimation ); +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +}catch (char * strError ){ +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +WarningMessage (TRANS ("Cannot load '%s': %s") , (CTString &) m_fnmAmbientLightAnimation , strError ); +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_fnmAmbientLightAnimation = ""; +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_aoAmbientLightAnimation . GetData () != NULL ){ +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_aoAmbientLightAnimation . PlayAnim (m_iAmbientLightAnimation , AOF_LOOPING ); +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_aoAmbientLightAnimation . OffsetPhase (m_tmOffsetPhase * m_aoAmbientLightAnimation . GetCurrentAnimLength ()); +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +CLightSource lsNew ; +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetupLightSource (lsNew ); +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(m_bBackground ){ +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetFlags (GetFlags () | ENF_BACKGROUND ); +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +}else { +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SetFlags (GetFlags () & ~ ENF_BACKGROUND ); +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_lsLightSource . ls_penEntity = this ; +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +if(! m_bdfInitialized . bdf_bValue ){ +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_lsLightSource . SetLightSourceWithNoDiscarding (lsNew ); +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_bdfInitialized . bdf_bValue = TRUE ; +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +}else { +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +} +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +m_strDescription . PrintF ("%s:%g-%g" , +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +strType , m_rHotSpotRange , m_rFallOffRange ); +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +Return(STATE_CURRENT,EVoid()); +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Light.es b/Sources/EntitiesMP/Light.es new file mode 100644 index 0000000..2872526 --- /dev/null +++ b/Sources/EntitiesMP/Light.es @@ -0,0 +1,471 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +200 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/ModelDestruction"; +uses "EntitiesMP/AnimationChanger"; + +enum LightType { + 0 LT_POINT "Point light", + 1 LT_AMBIENT "Ambient light", + 2 LT_STRONG_AMBIENT "Strong ambient light", + 3 LT_DIRECTIONAL "Directional light", + 4 LT_STRONG_POINT "Strong point light", +}; + +enum LensFlareType { + 0 LFT_NONE "None", + 1 LFT_STANDARD "Standard", + 2 LFT_STANDARD_REFLECTIONS "Standard reflections", + 3 LFT_YELLOW_STAR_RED_RING "Yellow star with red ring", + 4 LFT_WHITE_GLOW_STAR_RED_RING "White glow star with red ring", + 5 LFT_WHITE_GLOW_STAR "White glow star", + 6 LFT_WHITE_STAR_RED_RING_STREAKS "White star with red ring and streaks", + 7 LFT_WHITE_STAR_RED_REFLECTIONS "White star with red reflections", + 8 LFT_BLUE_STAR_BLUE_REFLECTIONS "Blue star with blue reflections", + 9 LFT_PV_SPACE_SHIP_WINDOW_FLARE "Pyramid valley space ship window flare", + 10 LFT_WHITE_GLOW_STAR_RED_RING_FAR "Yellow star with red ring far", + 11 LFT_WHITE_GLOW_FAR "White glow far", + 12 LFT_WHITE_GLOW_STAR_NG "White glow star no glare", +}; + +%{ + +void CLight_OnInitClass(void) +{ + // init lens flares effects + InitLensFlares(); +} + +void CLight_OnEndClass(void) +{ + // close lens flares effects + CloseLensFlares(); +} + +%} + +class CLight : CEntity { +name "Light"; +thumbnail "Thumbnails\\Light.tbn"; +features "HasName", "HasDescription", "ImplementsOnInitClass", "ImplementsOnEndClass"; +properties: + 2 COLOR m_colColor "Color" 'C' =C_GRAY, + 9 COLOR m_colAmbient "Directional ambient" 'E' =C_BLACK, + 1 RANGE m_rFallOffRange "Fall-off" 'F' =8.0f features(EPROPF_HIDEINPERSPECTIVE), + 4 RANGE m_rHotSpotRange "Hot-spot" 'H' =0.0f features(EPROPF_HIDEINPERSPECTIVE), + 7 ILLUMINATIONTYPE m_itIllumination "Polygon illumination" 'I' =0, + 8 enum LightType m_ltType "Type" 'Y' =LT_POINT, + 10 CTString m_strDescription = "", + 11 CTString m_strName "Name" 'N' = "Light", + 12 BOOL m_bDarkLight "Dark light" 'A' = FALSE, + 13 FLOAT m_fNearClip "Clip near" = 0.1f, + 14 FLOAT m_fFarClip "Clip far" = 0.01f, + 15 BOOL m_bSubstractSectorAmbient "Substract sector ambient" 'S' = FALSE, + 16 BOOL m_bRenderAsSmallLight "Render as small" 'R' = FALSE, + 17 enum LensFlareType m_lftLensFlare "Lens flare" 'L' = LFT_NONE, + 18 BOOL m_bBackground "Background" 'B' = FALSE, + 19 BOOL m_bLensFlareOnly "Lens flare only" 'O' = FALSE, + 20 CTFileName m_fnmLightAnimation "Light animation file" = CTString(""), + 21 ANIMATION m_iLightAnimation "Light animation" = 0, + 25 FLOAT m_tmOffsetPhase "Light animation offset" = 0.0f, + 22 CAnimObject m_aoLightAnimation, + 24 BOOL m_bTargetable "Targetable" = FALSE, + 26 BOOL m_bDynamic "Dynamic" = FALSE, + 27 BOOL m_bDiffusion "Diffusion" 'D' = TRUE, + 30 CTFileName m_fnmAmbientLightAnimation "Ambient light animation file" = CTString(""), + 31 ANIMATION m_iAmbientLightAnimation "Ambient light animation" = 0, + 32 CAnimObject m_aoAmbientLightAnimation, +{ + CLightSource m_lsLightSource; + CBoolDefaultFalse m_bdfInitialized; // set if already initialized once +} +components: + 1 model MODEL_LIGHT_SOURCE "Models\\Editor\\LightSource.mdl", + 2 texture TEXTURE_POINT_LIGHT "Models\\Editor\\PointLight.tex", + 3 texture TEXTURE_AMBIENT_LIGHT "Models\\Editor\\AmbientLight.tex", + 4 texture TEXTURE_REAL_AMBIENT_LIGHT "Models\\Editor\\RealAmbientLight.tex", + 5 model MODEL_SPOT_LIGHT "Models\\Editor\\SpotLight.mdl", + 6 texture TEXTURE_SPOT_LIGHT "Models\\Editor\\SpotLight.tex", + +functions: + /* Get anim data for given animation property - return NULL for none. */ + CAnimData *GetAnimData(SLONG slPropertyOffset) + { + if (slPropertyOffset==offsetof(CLight, m_iLightAnimation)) + { + return m_aoLightAnimation.GetData(); + } + else if (slPropertyOffset==offsetof(CLight, m_iAmbientLightAnimation)) + { + return m_aoAmbientLightAnimation.GetData(); + } + else + { + return CEntity::GetAnimData(slPropertyOffset); + } + }; + + BOOL IsTargetable(void) const + { + return m_bTargetable; + } + + BOOL IsImportant(void) const + { + return(m_ltType==LT_DIRECTIONAL); + } + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + // when someone in range is destroyed + if (ee.ee_slEvent==EVENTCODE_ERangeModelDestruction) + { + // fade out completely + m_colColor = C_BLACK; + m_colAmbient = C_BLACK; + CLightSource lsNew; + SetupLightSource(lsNew); + m_lsLightSource.SetLightSource(lsNew); + return TRUE; + // when animation should be changed + } + else if (ee.ee_slEvent==EVENTCODE_EChangeAnim) + { + EChangeAnim &eChange = (EChangeAnim &)ee; + + // for diffuse component of light + m_iLightAnimation = eChange.iLightAnim; + if (m_aoLightAnimation.GetData()!=NULL) + { + m_aoLightAnimation.PlayAnim(m_iLightAnimation, eChange.bLightLoop?AOF_LOOPING:0); + } + + // for ambient component of light + m_iAmbientLightAnimation = eChange.iAmbientLightAnim; + if (m_aoAmbientLightAnimation.GetData()!=NULL) + { + m_aoAmbientLightAnimation.PlayAnim(m_iAmbientLightAnimation, eChange.bAmbientLightLoop?AOF_LOOPING:0); + } + + // if neither ambient nor difuse animation is set, apply direct color change + if( (m_aoLightAnimation.GetData()==NULL) && (m_aoAmbientLightAnimation.GetData()==NULL) ) + { + m_colColor = eChange.colDiffuse; + m_colAmbient = eChange.colAmbient; + CLightSource lsNew; + SetupLightSource(lsNew); + m_lsLightSource.SetLightSource(lsNew); + return TRUE; + } + } + return FALSE; + } + + // apply mirror and stretch to the entity + void MirrorAndStretch(FLOAT fStretch, BOOL bMirrorX) + { + // stretch its ranges + m_rFallOffRange*=fStretch; + m_rHotSpotRange*=fStretch; + m_fNearClip *=fStretch; + m_fFarClip *=fStretch; + //(void)bMirrorX; // no mirror for lights + } + + /* Get static light source information. */ + CLightSource *GetLightSource(void) + { + // if never initialized before (happens after loading) + if (!m_bdfInitialized.bdf_bValue) { + // initialize now + CLightSource lsNew; + SetupLightSource(lsNew); + m_lsLightSource.SetLightSourceWithNoDiscarding(lsNew); + m_bdfInitialized.bdf_bValue = TRUE; + } + if (!IsPredictor()) { + return &m_lsLightSource; + } else { + return NULL; + } + } + + // prepare and transfer light source variables + void SetupLightSource( CLightSource &lsNew) + { + switch( m_ltType) { + case LT_POINT: + case LT_STRONG_POINT: + lsNew.ls_ulFlags = LSF_CASTSHADOWS; + break; + case LT_DIRECTIONAL: + lsNew.ls_ulFlags = LSF_DIRECTIONAL|LSF_CASTSHADOWS; + break; + case LT_STRONG_AMBIENT: + case LT_AMBIENT: + lsNew.ls_ulFlags = 0; + break; + } + if( m_bSubstractSectorAmbient) { lsNew.ls_ulFlags |= LSF_SUBSTRACTSECTORAMBIENT; } + if( m_bLensFlareOnly) { lsNew.ls_ulFlags |= LSF_LENSFLAREONLY; } + if( m_bDynamic) { lsNew.ls_ulFlags |= LSF_DYNAMIC; } + // directional light cannot be dark + if( m_bDarkLight) { + if( m_ltType==LT_DIRECTIONAL) { + lsNew.ls_ulFlags &= ~LSF_DARKLIGHT; + m_bDarkLight = FALSE; + } else { + lsNew.ls_ulFlags |= LSF_DARKLIGHT; + } + } + // ambient and directional lights doesn't support diffusion + if( m_bDiffusion) { + if( m_bDynamic || m_ltType==LT_AMBIENT || m_ltType==LT_STRONG_AMBIENT) { + lsNew.ls_ulFlags &= ~LSF_DIFFUSION; + m_bDiffusion = FALSE; + } else { + lsNew.ls_ulFlags |= LSF_DIFFUSION; + } + } + + lsNew.ls_rHotSpot = m_rHotSpotRange; + lsNew.ls_rFallOff = m_rFallOffRange; + lsNew.ls_fNearClipDistance = m_fNearClip; + lsNew.ls_fFarClipDistance = m_fFarClip; + // hot spot for strong lights is 90% of light range + if( m_ltType == LT_STRONG_AMBIENT || m_ltType == LT_STRONG_POINT) { + lsNew.ls_rHotSpot = lsNew.ls_rFallOff*0.9f; + } + + lsNew.ls_colColor = m_colColor; + lsNew.ls_colAmbient = C_BLACK; // only directional lights are allowed to have ambient component + if( lsNew.ls_ulFlags&LSF_DIRECTIONAL) { lsNew.ls_colAmbient = m_colAmbient; } + lsNew.ls_ubPolygonalMask = (UBYTE) m_itIllumination; + + switch(m_lftLensFlare) + { + case LFT_NONE: + lsNew.ls_plftLensFlare = NULL; + break; + case LFT_STANDARD: + lsNew.ls_plftLensFlare = &_lftStandard; + break; + case LFT_STANDARD_REFLECTIONS: + lsNew.ls_plftLensFlare = &_lftStandardReflections; + break; + case LFT_YELLOW_STAR_RED_RING: + lsNew.ls_plftLensFlare = &_lftYellowStarRedRing; + break; + case LFT_WHITE_GLOW_STAR_RED_RING: + lsNew.ls_plftLensFlare = &_lftWhiteGlowStarRedRing; + break; + case LFT_WHITE_GLOW_STAR: + lsNew.ls_plftLensFlare = &_lftWhiteGlowStar; + break; + case LFT_WHITE_STAR_RED_RING_STREAKS: + lsNew.ls_plftLensFlare = &_lftWhiteStarRedRingStreaks; + break; + case LFT_WHITE_STAR_RED_REFLECTIONS: + lsNew.ls_plftLensFlare = &_lftWhiteStarRedReflections; + break; + case LFT_BLUE_STAR_BLUE_REFLECTIONS: + lsNew.ls_plftLensFlare = &_lftBlueStarBlueReflections; + break; + case LFT_PV_SPACE_SHIP_WINDOW_FLARE: + lsNew.ls_plftLensFlare = &_lftPVSpaceShipWindowFlare; + break; + case LFT_WHITE_GLOW_STAR_RED_RING_FAR: + lsNew.ls_plftLensFlare = &_lftYellowStarRedRingFar; + break; + case LFT_WHITE_GLOW_FAR: + lsNew.ls_plftLensFlare = &_lftWhiteGlowFar; + break; + case LFT_WHITE_GLOW_STAR_NG: + lsNew.ls_plftLensFlare = &_lftWhiteGlowStarNG; + break; + } + + // --------- Setup light animations + // diffuse + lsNew.ls_paoLightAnimation = NULL; + if (m_aoLightAnimation.GetData()!=NULL) { + lsNew.ls_paoLightAnimation = &m_aoLightAnimation; + } + + // ambient + lsNew.ls_paoAmbientLightAnimation = NULL; + if (m_aoAmbientLightAnimation.GetData()!=NULL) { + lsNew.ls_paoAmbientLightAnimation = &m_aoAmbientLightAnimation; + } + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CLight) - sizeof(CEntity) + CEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strDescription.Length(); + slUsedMemory += m_strName.Length(); + slUsedMemory += m_fnmLightAnimation.Length(); + slUsedMemory += m_fnmAmbientLightAnimation.Length(); + slUsedMemory += 2* sizeof(CAnimObject); // 2 of them + return slUsedMemory; + } + + +procedures: + Main() + { + // fall off and hot spot must be positive values + if (m_rFallOffRange<0) { + m_rFallOffRange = 0.0f; + } + if (m_rHotSpotRange<0) { + m_rHotSpotRange = 0.0f; + } + // hot spot must be less or equal falloff + if (m_rHotSpotRange>m_rFallOffRange) { + m_rHotSpotRange = m_rFallOffRange; + } + + // near clip must not be too small relatively to falloff + // (crashes on shadow rendering otherwise!) + //if (m_fNearClipmo_Stretch = FLOAT3D( 0.25f, 0.25f, 0.25f); + } + else + { + // set stretch factor of the light (directional lights don't have stretch) + if ( m_ltType != LT_DIRECTIONAL) { + const float LIGHT_MINSIZE=0.5f; + FLOAT fFactor = Log2(m_rFallOffRange)*LIGHT_MINSIZE; + if (fFactormo_Stretch = FLOAT3D( fFactor, fFactor, fFactor); + } + } + + CTString strType; + if( m_ltType == LT_POINT || m_ltType == LT_STRONG_POINT) + { + strType = "point"; + // set model to light source + SetModel(MODEL_LIGHT_SOURCE); + // set texture of point light model + SetModelMainTexture(TEXTURE_POINT_LIGHT); + } + // initialize ambient light + else if( m_ltType == LT_AMBIENT) + { + strType = "ambient"; + // set model to light source + SetModel(MODEL_LIGHT_SOURCE); + // set texture of ambient light model + SetModelMainTexture(TEXTURE_AMBIENT_LIGHT); + } + // initialize real ambient light + else if( m_ltType == LT_STRONG_AMBIENT) + { + strType = "ambient"; + // set model to light source + SetModel(MODEL_LIGHT_SOURCE); + // set texture of real ambient light model + SetModelMainTexture(TEXTURE_REAL_AMBIENT_LIGHT); + } + // initialize spot light + else if( m_ltType == LT_DIRECTIONAL) + { + strType = "directional"; + // set model to spot light + SetModel(MODEL_SPOT_LIGHT); + // set texture of spot light model + SetModelMainTexture(TEXTURE_SPOT_LIGHT); + } + + if( m_bDarkLight) + { + strType = strType+", dark"; + } + + // set diffuse light animation if available + try { + m_aoLightAnimation.SetData_t(m_fnmLightAnimation); + } catch (char *strError) { + WarningMessage(TRANS("Cannot load '%s': %s"), (CTString&)m_fnmLightAnimation, strError); + m_fnmLightAnimation = ""; + } + if (m_aoLightAnimation.GetData()!=NULL) { + m_aoLightAnimation.PlayAnim(m_iLightAnimation, AOF_LOOPING); + m_aoLightAnimation.OffsetPhase(m_tmOffsetPhase*m_aoLightAnimation.GetCurrentAnimLength()); + } + + // set ambient light animation if available + try { + m_aoAmbientLightAnimation.SetData_t(m_fnmAmbientLightAnimation); + } catch (char *strError) { + WarningMessage(TRANS("Cannot load '%s': %s"), (CTString&)m_fnmAmbientLightAnimation, strError); + m_fnmAmbientLightAnimation = ""; + } + if (m_aoAmbientLightAnimation.GetData()!=NULL) { + m_aoAmbientLightAnimation.PlayAnim(m_iAmbientLightAnimation, AOF_LOOPING); + m_aoAmbientLightAnimation.OffsetPhase(m_tmOffsetPhase*m_aoAmbientLightAnimation.GetCurrentAnimLength()); + } + + // set a new light source with light properties + CLightSource lsNew; + SetupLightSource(lsNew); + + // setup background rendering flag + if (m_bBackground) { + SetFlags(GetFlags()|ENF_BACKGROUND); + } else { + SetFlags(GetFlags()&~ENF_BACKGROUND); + } + + // set up this light source from the new properties + m_lsLightSource.ls_penEntity = this; + if (!m_bdfInitialized.bdf_bValue) { + m_lsLightSource.SetLightSourceWithNoDiscarding(lsNew); + m_bdfInitialized.bdf_bValue = TRUE; + } else { + m_lsLightSource.SetLightSource(lsNew); + } + + m_strDescription.PrintF("%s:%g-%g", + strType, m_rHotSpotRange, m_rFallOffRange); + + return; + }; +}; diff --git a/Sources/EntitiesMP/Light.h b/Sources/EntitiesMP/Light.h new file mode 100644 index 0000000..94478dd --- /dev/null +++ b/Sources/EntitiesMP/Light.h @@ -0,0 +1,98 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Light_INCLUDED +#define _EntitiesMP_Light_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType LightType_enum; +enum LightType { + LT_POINT = 0, + LT_AMBIENT = 1, + LT_STRONG_AMBIENT = 2, + LT_DIRECTIONAL = 3, + LT_STRONG_POINT = 4, +}; +DECL_DLL inline void ClearToDefault(LightType &e) { e = (LightType)0; } ; +extern DECL_DLL CEntityPropertyEnumType LensFlareType_enum; +enum LensFlareType { + LFT_NONE = 0, + LFT_STANDARD = 1, + LFT_STANDARD_REFLECTIONS = 2, + LFT_YELLOW_STAR_RED_RING = 3, + LFT_WHITE_GLOW_STAR_RED_RING = 4, + LFT_WHITE_GLOW_STAR = 5, + LFT_WHITE_STAR_RED_RING_STREAKS = 6, + LFT_WHITE_STAR_RED_REFLECTIONS = 7, + LFT_BLUE_STAR_BLUE_REFLECTIONS = 8, + LFT_PV_SPACE_SHIP_WINDOW_FLARE = 9, + LFT_WHITE_GLOW_STAR_RED_RING_FAR = 10, + LFT_WHITE_GLOW_FAR = 11, + LFT_WHITE_GLOW_STAR_NG = 12, +}; +DECL_DLL inline void ClearToDefault(LensFlareType &e) { e = (LensFlareType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CLight_DLLClass; +class CLight : public CEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual const CTString &GetDescription(void) const { return m_strDescription; }; + DECL_DLL virtual void SetDefaultProperties(void); + COLOR m_colColor; + COLOR m_colAmbient; + RANGE m_rFallOffRange; + RANGE m_rHotSpotRange; + ILLUMINATIONTYPE m_itIllumination; + enum LightType m_ltType; + CTString m_strDescription; + CTString m_strName; + BOOL m_bDarkLight; + FLOAT m_fNearClip; + FLOAT m_fFarClip; + BOOL m_bSubstractSectorAmbient; + BOOL m_bRenderAsSmallLight; + enum LensFlareType m_lftLensFlare; + BOOL m_bBackground; + BOOL m_bLensFlareOnly; + CTFileName m_fnmLightAnimation; + ANIMATION m_iLightAnimation; + FLOAT m_tmOffsetPhase; + CAnimObject m_aoLightAnimation; + BOOL m_bTargetable; + BOOL m_bDynamic; + BOOL m_bDiffusion; + CTFileName m_fnmAmbientLightAnimation; + ANIMATION m_iAmbientLightAnimation; + CAnimObject m_aoAmbientLightAnimation; +CLightSource m_lsLightSource; +CBoolDefaultFalse m_bdfInitialized; + +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +CAnimData * GetAnimData(SLONG slPropertyOffset); + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +BOOL IsTargetable(void)const; + +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +BOOL IsImportant(void)const; + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +BOOL HandleEvent(const CEntityEvent & ee); + +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +void MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX); + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +CLightSource * GetLightSource(void); + +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +void SetupLightSource(CLightSource & lsNew); + +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +SLONG GetUsedMemory(void); +#define STATE_CLight_Main 1 + BOOL +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Light_INCLUDED diff --git a/Sources/EntitiesMP/Light_tables.h b/Sources/EntitiesMP/Light_tables.h new file mode 100644 index 0000000..e8b9fe6 --- /dev/null +++ b/Sources/EntitiesMP/Light_tables.h @@ -0,0 +1,93 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(LightType) + EP_ENUMVALUE(LT_POINT, "Point light"), + EP_ENUMVALUE(LT_AMBIENT, "Ambient light"), + EP_ENUMVALUE(LT_STRONG_AMBIENT, "Strong ambient light"), + EP_ENUMVALUE(LT_DIRECTIONAL, "Directional light"), + EP_ENUMVALUE(LT_STRONG_POINT, "Strong point light"), +EP_ENUMEND(LightType); + +EP_ENUMBEG(LensFlareType) + EP_ENUMVALUE(LFT_NONE, "None"), + EP_ENUMVALUE(LFT_STANDARD, "Standard"), + EP_ENUMVALUE(LFT_STANDARD_REFLECTIONS, "Standard reflections"), + EP_ENUMVALUE(LFT_YELLOW_STAR_RED_RING, "Yellow star with red ring"), + EP_ENUMVALUE(LFT_WHITE_GLOW_STAR_RED_RING, "White glow star with red ring"), + EP_ENUMVALUE(LFT_WHITE_GLOW_STAR, "White glow star"), + EP_ENUMVALUE(LFT_WHITE_STAR_RED_RING_STREAKS, "White star with red ring and streaks"), + EP_ENUMVALUE(LFT_WHITE_STAR_RED_REFLECTIONS, "White star with red reflections"), + EP_ENUMVALUE(LFT_BLUE_STAR_BLUE_REFLECTIONS, "Blue star with blue reflections"), + EP_ENUMVALUE(LFT_PV_SPACE_SHIP_WINDOW_FLARE, "Pyramid valley space ship window flare"), + EP_ENUMVALUE(LFT_WHITE_GLOW_STAR_RED_RING_FAR, "Yellow star with red ring far"), + EP_ENUMVALUE(LFT_WHITE_GLOW_FAR, "White glow far"), + EP_ENUMVALUE(LFT_WHITE_GLOW_STAR_NG, "White glow star no glare"), +EP_ENUMEND(LensFlareType); + +#define ENTITYCLASS CLight + +CEntityProperty CLight_properties[] = { + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000c8<<8)+2, offsetof(CLight, m_colColor), "Color", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000c8<<8)+9, offsetof(CLight, m_colAmbient), "Directional ambient", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x000000c8<<8)+1, offsetof(CLight, m_rFallOffRange), "Fall-off", 'F', 0x7F0000FFUL, EPROPF_HIDEINPERSPECTIVE ), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x000000c8<<8)+4, offsetof(CLight, m_rHotSpotRange), "Hot-spot", 'H', 0x7F0000FFUL, EPROPF_HIDEINPERSPECTIVE ), + CEntityProperty(CEntityProperty::EPT_ILLUMINATIONTYPE, NULL, (0x000000c8<<8)+7, offsetof(CLight, m_itIllumination), "Polygon illumination", 'I', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &LightType_enum, (0x000000c8<<8)+8, offsetof(CLight, m_ltType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000c8<<8)+10, offsetof(CLight, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000c8<<8)+11, offsetof(CLight, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000c8<<8)+12, offsetof(CLight, m_bDarkLight), "Dark light", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000c8<<8)+13, offsetof(CLight, m_fNearClip), "Clip near", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000c8<<8)+14, offsetof(CLight, m_fFarClip), "Clip far", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000c8<<8)+15, offsetof(CLight, m_bSubstractSectorAmbient), "Substract sector ambient", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000c8<<8)+16, offsetof(CLight, m_bRenderAsSmallLight), "Render as small", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &LensFlareType_enum, (0x000000c8<<8)+17, offsetof(CLight, m_lftLensFlare), "Lens flare", 'L', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000c8<<8)+18, offsetof(CLight, m_bBackground), "Background", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000c8<<8)+19, offsetof(CLight, m_bLensFlareOnly), "Lens flare only", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000c8<<8)+20, offsetof(CLight, m_fnmLightAnimation), "Light animation file", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000c8<<8)+21, offsetof(CLight, m_iLightAnimation), "Light animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000c8<<8)+25, offsetof(CLight, m_tmOffsetPhase), "Light animation offset", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMOBJECT, NULL, (0x000000c8<<8)+22, offsetof(CLight, m_aoLightAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000c8<<8)+24, offsetof(CLight, m_bTargetable), "Targetable", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000c8<<8)+26, offsetof(CLight, m_bDynamic), "Dynamic", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000c8<<8)+27, offsetof(CLight, m_bDiffusion), "Diffusion", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000c8<<8)+30, offsetof(CLight, m_fnmAmbientLightAnimation), "Ambient light animation file", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000c8<<8)+31, offsetof(CLight, m_iAmbientLightAnimation), "Ambient light animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMOBJECT, NULL, (0x000000c8<<8)+32, offsetof(CLight, m_aoAmbientLightAnimation), "", 0, 0, 0), +}; +#define CLight_propertiesct ARRAYCOUNT(CLight_properties) + +CEntityComponent CLight_components[] = { +#define MODEL_LIGHT_SOURCE ((0x000000c8<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_LIGHT_SOURCE, "EFNM" "Models\\Editor\\LightSource.mdl"), +#define TEXTURE_POINT_LIGHT ((0x000000c8<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_POINT_LIGHT, "EFNM" "Models\\Editor\\PointLight.tex"), +#define TEXTURE_AMBIENT_LIGHT ((0x000000c8<<8)+3) + CEntityComponent(ECT_TEXTURE, TEXTURE_AMBIENT_LIGHT, "EFNM" "Models\\Editor\\AmbientLight.tex"), +#define TEXTURE_REAL_AMBIENT_LIGHT ((0x000000c8<<8)+4) + CEntityComponent(ECT_TEXTURE, TEXTURE_REAL_AMBIENT_LIGHT, "EFNM" "Models\\Editor\\RealAmbientLight.tex"), +#define MODEL_SPOT_LIGHT ((0x000000c8<<8)+5) + CEntityComponent(ECT_MODEL, MODEL_SPOT_LIGHT, "EFNM" "Models\\Editor\\SpotLight.mdl"), +#define TEXTURE_SPOT_LIGHT ((0x000000c8<<8)+6) + CEntityComponent(ECT_TEXTURE, TEXTURE_SPOT_LIGHT, "EFNM" "Models\\Editor\\SpotLight.tex"), +}; +#define CLight_componentsct ARRAYCOUNT(CLight_components) + +CEventHandlerEntry CLight_handlers[] = { + {1, -1, CEntity::pEventHandler(&CLight:: +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Light.es" +Main),DEBUGSTRING("CLight::Main")}, +}; +#define CLight_handlersct ARRAYCOUNT(CLight_handlers) + +CEntity *CLight_New(void) { return new CLight; }; +void CLight_OnInitClass(void); +void CLight_OnEndClass(void); +void CLight_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CLight_OnWorldEnd(CWorld *pwo) {}; +void CLight_OnWorldInit(CWorld *pwo) {}; +void CLight_OnWorldTick(CWorld *pwo) {}; +void CLight_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CLight, CEntity, "Light", "Thumbnails\\Light.tbn", 0x000000c8); +DECLARE_CTFILENAME(_fnmCLight_tbn, "Thumbnails\\Light.tbn"); diff --git a/Sources/EntitiesMP/Lightning.cpp b/Sources/EntitiesMP/Lightning.cpp new file mode 100644 index 0000000..09ad66f --- /dev/null +++ b/Sources/EntitiesMP/Lightning.cpp @@ -0,0 +1,404 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" + +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/Light.h" + +#include +#include +#line 11 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" + + struct ThunderInfo + { + INDEX ti_iSound; + FLOAT ti_fThunderStrikeDelay; + }; + + struct ThunderInfo _atiThunderSounds[3] = + { + { SOUND_THUNDER1, 0.6f}, + { SOUND_THUNDER2, 0.0f}, + { SOUND_THUNDER3, 0.0f}, + }; + +void CLightning::SetDefaultProperties(void) { + m_penTarget = NULL; + m_penwsc = NULL; + m_strName = "Lightning"; + m_tmLightningStart = -1.0f; + m_soThunder.SetOwner(this); +m_soThunder.Stop_internal(); + m_bBackground = FALSE ; + m_penLight = NULL; + m_iLightAnim = 0; + m_iSoundPlaying = 0; + m_fLightningPower = 1.0f; + m_fSoundDelay = 0.0f; + CMovableModelEntity::SetDefaultProperties(); +} + +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +void CLightning::Precache(void) +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +CMovableModelEntity :: Precache (); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +PrecacheSound (SOUND_THUNDER1 ); +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +PrecacheSound (SOUND_THUNDER2 ); +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +PrecacheSound (SOUND_THUNDER3 ); +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} + +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +CAnimData * CLightning::GetAnimData(SLONG slPropertyOffset) +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(m_penLight == NULL ){ +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +return NULL ; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(IsOfClass (m_penLight , "Light")) +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +CLight * penLight = (CLight *) & * m_penLight ; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(slPropertyOffset == offsetof (CLightning , m_iLightAnim )) +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +return penLight -> m_aoLightAnimation . GetData (); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +else +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +WarningMessage ("Target '%s' is not of light class!" , m_penLight -> GetName ()); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +return NULL ; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +void CLightning::RenderParticles(void) +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(m_penTarget == NULL || m_tmLightningStart == - 1){return ;}; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +TIME tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if( +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +((tmNow - m_tmLightningStart ) > 0.0f) && +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +((tmNow - m_tmLightningStart ) < 1.5f)) +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +FLOAT3D vSrc = GetPlacement () . pl_PositionVector ; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +FLOAT3D vDst = m_penTarget -> GetPlacement () . pl_PositionVector ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +Particles_Lightning (vSrc , vDst , m_tmLightningStart ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +BOOL CLightning:: +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +LightningStike(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CLightning_LightningStike + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CLightning::LightningStike expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +m_iSoundPlaying = 1 + IRnd () % (ARRAYCOUNT (_atiThunderSounds ) - 1); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(m_fSoundDelay != 0) +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +m_iSoundPlaying = 0; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +m_soThunder . SetVolume (1.5f * m_fLightningPower , 1.5f * m_fLightningPower ); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +m_soThunder . SetPitch (Lerp (0.9f , 1.2f , FRnd ())); +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(m_fSoundDelay == 0.0f) +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +PlaySound (m_soThunder , _atiThunderSounds [ m_iSoundPlaying ] . ti_iSound , 0); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(!(_atiThunderSounds [ m_iSoundPlaying ] . ti_fThunderStrikeDelay > 0.0f)){ Jump(STATE_CURRENT,0x025f0003, FALSE, EInternal());return TRUE;} +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetTimerAfter(_atiThunderSounds [ m_iSoundPlaying ] . ti_fThunderStrikeDelay ); +Jump(STATE_CURRENT, 0x025f0001, FALSE, EBegin());return TRUE;}BOOL CLightning::H0x025f0001_LightningStike_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x025f0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CLightning::H0x025f0002_LightningStike_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f0002 +;Jump(STATE_CURRENT,0x025f0003, FALSE, EInternal());return TRUE;}BOOL CLightning::H0x025f0003_LightningStike_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f0003 + +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +m_tmLightningStart = tmNow ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +((CWorldSettingsController *) & * m_penwsc ) -> m_tmLightningStart = tmNow ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +((CWorldSettingsController *) & * m_penwsc ) -> m_fLightningPower = m_fLightningPower ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(m_penLight != NULL ) +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +EChangeAnim eChange ; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +eChange . iLightAnim = m_iLightAnim ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +eChange . bLightLoop = FALSE ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +m_penLight -> SendEvent (eChange ); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(!(m_fSoundDelay != 0.0f)){ Jump(STATE_CURRENT,0x025f0006, FALSE, EInternal());return TRUE;} +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetTimerAfter(m_fSoundDelay ); +Jump(STATE_CURRENT, 0x025f0004, FALSE, EBegin());return TRUE;}BOOL CLightning::H0x025f0004_LightningStike_04(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f0004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x025f0005, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CLightning::H0x025f0005_LightningStike_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f0005 +; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +PlaySound (m_soThunder , _atiThunderSounds [ m_iSoundPlaying ] . ti_iSound , 0);Jump(STATE_CURRENT,0x025f0006, FALSE, EInternal());return TRUE;}BOOL CLightning::H0x025f0006_LightningStike_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f0006 + +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetTimerAfter(GetSoundLength (_atiThunderSounds [ m_iSoundPlaying ] . ti_iSound ) - +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +_atiThunderSounds [ m_iSoundPlaying ] . ti_fThunderStrikeDelay ); +Jump(STATE_CURRENT, 0x025f0007, FALSE, EBegin());return TRUE;}BOOL CLightning::H0x025f0007_LightningStike_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f0007 +switch(__eeInput.ee_slEvent) +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{case(EVENTCODE_ETimer): +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{const ETimer&e= (ETimer&)__eeInput; + +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +UnsetTimer();Jump(STATE_CURRENT,0x025f0008, FALSE, EInternal());return TRUE; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +}ASSERT(FALSE);break;default: +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +return TRUE; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +}ASSERT(FALSE);break; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +}return TRUE;}BOOL CLightning::H0x025f0008_LightningStike_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f0008 + +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +Return(STATE_CURRENT,EBegin ()); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CLightning:: +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CLightning_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CLightning::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +InitAsEditorModel (); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetModel (MODEL_TELEPORT ); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetModelMainTexture (TEXTURE_TELEPORT ); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(m_bBackground ) +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetFlags (GetFlags () | ENF_BACKGROUND ); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +else +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetFlags (GetFlags () & ~ ENF_BACKGROUND ); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +CBackgroundViewer * penBcgViewer = (CBackgroundViewer *) GetWorld () -> GetBackgroundViewer (); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(penBcgViewer == NULL ) +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +Return(STATE_CURRENT,EVoid()); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +return TRUE; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +m_penwsc = penBcgViewer -> m_penWorldSettingsController ; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(m_penwsc == NULL ) +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +Return(STATE_CURRENT,EVoid()); +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +return TRUE; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(! IsOfClass (m_penwsc , "WorldSettingsController")) +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +Return(STATE_CURRENT,EVoid()); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +return TRUE; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if((m_penTarget == NULL ) || (! IsOfClass (m_penTarget , "Marker"))) +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +if(m_penTarget != NULL ) +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +WarningMessage ("Target '%s' is not of Marker class!" , m_penTarget -> GetName ()); +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +Return(STATE_CURRENT,EVoid()); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +return TRUE; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +} +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +FLOAT3D vDirection = +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +(m_penTarget -> GetPlacement () . pl_PositionVector - +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +GetPlacement () . pl_PositionVector ); +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +FLOAT3D vStretch = vDirection ; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +vStretch (1) = 1.0f; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +vStretch (2) = 1.0f; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +vStretch (3) = - vDirection . Length (); +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +CPlacement3D pl = GetPlacement (); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +DirectionVectorToAngles (vDirection . Normalize () , pl . pl_OrientationAngle ); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetPlacement (pl ); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +GetModelObject () -> StretchModel (vStretch ); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +ModelChangeNotify (); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +m_fLightningPower = Clamp (m_fLightningPower , 0.0f , 1.0f); +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x025f0009, FALSE, EBegin());return TRUE;}BOOL CLightning::H0x025f0009_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f0009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x025f000a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CLightning::H0x025f000a_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f000a +; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +Jump(STATE_CURRENT,0x025f000d, FALSE, EInternal());return TRUE;}BOOL CLightning::H0x025f000d_Main_05(const CEntityEvent &__eeInput) +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f000d +if(!(TRUE )){ Jump(STATE_CURRENT,0x025f000e, FALSE, EInternal());return TRUE;} +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x025f000b, FALSE, EBegin());return TRUE;}BOOL CLightning::H0x025f000b_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f000b +switch(__eeInput.ee_slEvent) +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETrigger): +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +Call(STATE_CURRENT, STATE_CLightning_LightningStike, TRUE, EVoid());return TRUE; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +return TRUE; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +}ASSERT(FALSE);break;default: +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +{ +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +return TRUE; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +}ASSERT(FALSE);break; +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +}return TRUE;}BOOL CLightning::H0x025f000c_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f000c +;Jump(STATE_CURRENT,0x025f000d, FALSE, EInternal());return TRUE; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +}BOOL CLightning::H0x025f000e_Main_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025f000e + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Lightning.es b/Sources/EntitiesMP/Lightning.es new file mode 100644 index 0000000..31287c0 --- /dev/null +++ b/Sources/EntitiesMP/Lightning.es @@ -0,0 +1,262 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +607 +%{ +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/Light.h" +%} + +%{ + struct ThunderInfo + { + INDEX ti_iSound; + FLOAT ti_fThunderStrikeDelay; + }; + + struct ThunderInfo _atiThunderSounds[3] = + { + { SOUND_THUNDER1, 0.6f}, + { SOUND_THUNDER2, 0.0f}, + { SOUND_THUNDER3, 0.0f}, + }; +%} + +class CLightning: CMovableModelEntity { +name "Lightning"; +thumbnail "Thumbnails\\Lightning.tbn"; +features "IsTargetable", "HasName"; + +properties: + 1 CEntityPointer m_penTarget "Target" 'T' COLOR(C_BLUE|0xFF), // ptr to lightninig target + 2 CEntityPointer m_penwsc, // ptr to world settings controller + 3 CTString m_strName "Name" 'N' = "Lightning", // class name + 4 FLOAT m_tmLightningStart = -1.0f, // lightning start time + 5 CSoundObject m_soThunder, // sound channel + 6 BOOL m_bBackground "Background" 'B' =FALSE, + 7 CEntityPointer m_penLight "Light" 'L' COLOR(C_CYAN|0xFF), // ptr to light + 8 ANIMATION m_iLightAnim "Light Animation" 'A' = 0, + 9 INDEX m_iSoundPlaying = 0, + 10 FLOAT m_fLightningPower "Lightning power" 'P' = 1.0f, // lightning's ligting power + 11 FLOAT m_fSoundDelay "Sound delay" 'D' = 0.0f, // thunder's delay + +components: + 1 model MODEL_TELEPORT "Models\\Editor\\Teleport.mdl", + 2 texture TEXTURE_TELEPORT "Models\\Editor\\BoundingBox.tex", + 3 sound SOUND_THUNDER1 "Sounds\\Environment\\Thunders\\Thunder1.wav", + 4 sound SOUND_THUNDER2 "Sounds\\Environment\\Thunders\\Thunder2.wav", + 5 sound SOUND_THUNDER3 "Sounds\\Environment\\Thunders\\Thunder3.wav", + +functions: + void Precache(void) + { + CMovableModelEntity::Precache(); + PrecacheSound(SOUND_THUNDER1); + PrecacheSound(SOUND_THUNDER2); + PrecacheSound(SOUND_THUNDER3); + } + + /* Get anim data for given animation property - return NULL for none. */ + CAnimData *GetAnimData(SLONG slPropertyOffset) + { + if (m_penLight==NULL) { + return NULL; + } + + // if light entity + if (IsOfClass(m_penLight, "Light")) + { + CLight *penLight = (CLight*)&*m_penLight; + + if (slPropertyOffset==offsetof(CLightning, m_iLightAnim)) + { + return penLight->m_aoLightAnimation.GetData(); + } + } + else + { + WarningMessage("Target '%s' is not of light class!", m_penLight->GetName()); + } + return NULL; + }; + + void RenderParticles(void) + { + if( m_penTarget==NULL || m_tmLightningStart == -1) {return;}; + + TIME tmNow = _pTimer->GetLerpedCurrentTick(); + // if lightning is traveling + if( + ((tmNow-m_tmLightningStart) > 0.0f) && + ((tmNow-m_tmLightningStart) < 1.5f) ) + { + // render lightning particles + FLOAT3D vSrc = GetPlacement().pl_PositionVector; + FLOAT3D vDst = m_penTarget->GetPlacement().pl_PositionVector; + Particles_Lightning( vSrc, vDst, m_tmLightningStart); + } + } + +procedures: + LightningStike() + { + // choose random sound + m_iSoundPlaying = 1+IRnd()%( ARRAYCOUNT(_atiThunderSounds)-1); + if( m_fSoundDelay != 0) + { + m_iSoundPlaying=0; + } + m_soThunder.SetVolume(1.5f*m_fLightningPower, 1.5f*m_fLightningPower); + m_soThunder.SetPitch(Lerp(0.9f, 1.2f, FRnd())); + + if( m_fSoundDelay == 0.0f) + { + // play thunder ! + PlaySound(m_soThunder, _atiThunderSounds[ m_iSoundPlaying].ti_iSound, 0); + } + + // wait for sound to progress to lightning strike + if (_atiThunderSounds[ m_iSoundPlaying].ti_fThunderStrikeDelay>0.0f) { + autowait( _atiThunderSounds[ m_iSoundPlaying].ti_fThunderStrikeDelay); + } + + // remember current time as lightning start time + TIME tmNow = _pTimer->CurrentTick(); + m_tmLightningStart = tmNow; + // also in world settings controller + ((CWorldSettingsController *)&*m_penwsc)->m_tmLightningStart = tmNow; + // set power of lightning + ((CWorldSettingsController *)&*m_penwsc)->m_fLightningPower = m_fLightningPower; + + // trigger light animation + if( m_penLight != NULL) + { + EChangeAnim eChange; + eChange.iLightAnim = m_iLightAnim; + eChange.bLightLoop = FALSE; + m_penLight->SendEvent(eChange); + } + + if( m_fSoundDelay != 0.0f) + { + // wait given delay time + autowait( m_fSoundDelay); + // play thunder ! + PlaySound(m_soThunder, _atiThunderSounds[ m_iSoundPlaying].ti_iSound, 0); + } + + // wait until end of sound + wait( GetSoundLength(_atiThunderSounds[ m_iSoundPlaying].ti_iSound)- + _atiThunderSounds[ m_iSoundPlaying].ti_fThunderStrikeDelay) + { + on (ETimer) : + { + stop; + } + otherwise() : + { + resume; + }; + } + + return EBegin(); + } + + Main(EVoid) + { + // set appearance + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_TELEPORT); + SetModelMainTexture(TEXTURE_TELEPORT); + + // see if it is lightning on background + if (m_bBackground) + { + SetFlags(GetFlags()|ENF_BACKGROUND); + } + else + { + SetFlags(GetFlags()&~ENF_BACKGROUND); + } + + // obtain bcg viewer entity + CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) GetWorld()->GetBackgroundViewer(); + if( penBcgViewer == NULL) + { + // don't do anything + return; + } + + // obtain world settings controller + m_penwsc = penBcgViewer->m_penWorldSettingsController; + if( m_penwsc == NULL) + { + // don't do anything + return; + } + + // must be world settings controller entity + if (!IsOfClass(m_penwsc, "WorldSettingsController")) + { + // don't do anything + return; + } + + // lightning target must be marker + if( (m_penTarget == NULL) || (!IsOfClass(m_penTarget, "Marker")) ) + { + if( m_penTarget != NULL) + { + WarningMessage("Target '%s' is not of Marker class!", m_penTarget->GetName()); + } + // don't do anything + return; + } + + // stretch model + FLOAT3D vDirection = + (m_penTarget->GetPlacement().pl_PositionVector- + GetPlacement().pl_PositionVector); + + FLOAT3D vStretch = vDirection; + vStretch(1) = 1.0f; + vStretch(2) = 1.0f; + vStretch(3) = -vDirection.Length(); + + // set entity orientation + CPlacement3D pl = GetPlacement(); + DirectionVectorToAngles(vDirection.Normalize(), pl.pl_OrientationAngle); + SetPlacement(pl); + + GetModelObject()->StretchModel(vStretch); + ModelChangeNotify(); + + // correct power factor to fall under 0-1 boundaries + m_fLightningPower = Clamp( m_fLightningPower, 0.0f, 1.0f); + + // spawn in world editor + autowait(0.1f); + + while (TRUE) + { + wait() + { + on (EBegin) : { resume; } + on (ETrigger eTrigger) : + { + call LightningStike(); + resume; + } + otherwise() : + { + resume; + }; + }; + } + } +}; diff --git a/Sources/EntitiesMP/Lightning.h b/Sources/EntitiesMP/Lightning.h new file mode 100644 index 0000000..26a3596 --- /dev/null +++ b/Sources/EntitiesMP/Lightning.h @@ -0,0 +1,56 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Lightning_INCLUDED +#define _EntitiesMP_Lightning_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CLightning_DLLClass; +class CLightning : public CMovableModelEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penTarget; + CEntityPointer m_penwsc; + CTString m_strName; + FLOAT m_tmLightningStart; + CSoundObject m_soThunder; + BOOL m_bBackground; + CEntityPointer m_penLight; + ANIMATION m_iLightAnim; + INDEX m_iSoundPlaying; + FLOAT m_fLightningPower; + FLOAT m_fSoundDelay; + +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +void Precache(void); + +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +CAnimData * GetAnimData(SLONG slPropertyOffset); + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +void RenderParticles(void); +#define STATE_CLightning_LightningStike 0x025f0000 + BOOL +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +LightningStike(const CEntityEvent &__eeInput); + BOOL H0x025f0001_LightningStike_01(const CEntityEvent &__eeInput); + BOOL H0x025f0002_LightningStike_02(const CEntityEvent &__eeInput); + BOOL H0x025f0003_LightningStike_03(const CEntityEvent &__eeInput); + BOOL H0x025f0004_LightningStike_04(const CEntityEvent &__eeInput); + BOOL H0x025f0005_LightningStike_05(const CEntityEvent &__eeInput); + BOOL H0x025f0006_LightningStike_06(const CEntityEvent &__eeInput); + BOOL H0x025f0007_LightningStike_07(const CEntityEvent &__eeInput); + BOOL H0x025f0008_LightningStike_08(const CEntityEvent &__eeInput); +#define STATE_CLightning_Main 1 + BOOL +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x025f0009_Main_01(const CEntityEvent &__eeInput); + BOOL H0x025f000a_Main_02(const CEntityEvent &__eeInput); + BOOL H0x025f000b_Main_03(const CEntityEvent &__eeInput); + BOOL H0x025f000c_Main_04(const CEntityEvent &__eeInput); + BOOL H0x025f000d_Main_05(const CEntityEvent &__eeInput); + BOOL H0x025f000e_Main_06(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Lightning_INCLUDED diff --git a/Sources/EntitiesMP/Lightning_tables.h b/Sources/EntitiesMP/Lightning_tables.h new file mode 100644 index 0000000..8fee827 --- /dev/null +++ b/Sources/EntitiesMP/Lightning_tables.h @@ -0,0 +1,69 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CLightning + +CEntityProperty CLightning_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025f<<8)+1, offsetof(CLightning, m_penTarget), "Target", 'T', C_BLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025f<<8)+2, offsetof(CLightning, m_penwsc), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x0000025f<<8)+3, offsetof(CLightning, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025f<<8)+4, offsetof(CLightning, m_tmLightningStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000025f<<8)+5, offsetof(CLightning, m_soThunder), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000025f<<8)+6, offsetof(CLightning, m_bBackground), "Background", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025f<<8)+7, offsetof(CLightning, m_penLight), "Light", 'L', C_CYAN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x0000025f<<8)+8, offsetof(CLightning, m_iLightAnim), "Light Animation", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000025f<<8)+9, offsetof(CLightning, m_iSoundPlaying), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025f<<8)+10, offsetof(CLightning, m_fLightningPower), "Lightning power", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025f<<8)+11, offsetof(CLightning, m_fSoundDelay), "Sound delay", 'D', 0x7F0000FFUL, 0), +}; +#define CLightning_propertiesct ARRAYCOUNT(CLightning_properties) + +CEntityComponent CLightning_components[] = { +#define MODEL_TELEPORT ((0x0000025f<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_TELEPORT, "EFNM" "Models\\Editor\\Teleport.mdl"), +#define TEXTURE_TELEPORT ((0x0000025f<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_TELEPORT, "EFNM" "Models\\Editor\\BoundingBox.tex"), +#define SOUND_THUNDER1 ((0x0000025f<<8)+3) + CEntityComponent(ECT_SOUND, SOUND_THUNDER1, "EFNM" "Sounds\\Environment\\Thunders\\Thunder1.wav"), +#define SOUND_THUNDER2 ((0x0000025f<<8)+4) + CEntityComponent(ECT_SOUND, SOUND_THUNDER2, "EFNM" "Sounds\\Environment\\Thunders\\Thunder2.wav"), +#define SOUND_THUNDER3 ((0x0000025f<<8)+5) + CEntityComponent(ECT_SOUND, SOUND_THUNDER3, "EFNM" "Sounds\\Environment\\Thunders\\Thunder3.wav"), +}; +#define CLightning_componentsct ARRAYCOUNT(CLightning_components) + +CEventHandlerEntry CLightning_handlers[] = { + {0x025f0000, -1, CEntity::pEventHandler(&CLightning:: +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +LightningStike),DEBUGSTRING("CLightning::LightningStike")}, + {0x025f0001, -1, CEntity::pEventHandler(&CLightning::H0x025f0001_LightningStike_01), DEBUGSTRING("CLightning::H0x025f0001_LightningStike_01")}, + {0x025f0002, -1, CEntity::pEventHandler(&CLightning::H0x025f0002_LightningStike_02), DEBUGSTRING("CLightning::H0x025f0002_LightningStike_02")}, + {0x025f0003, -1, CEntity::pEventHandler(&CLightning::H0x025f0003_LightningStike_03), DEBUGSTRING("CLightning::H0x025f0003_LightningStike_03")}, + {0x025f0004, -1, CEntity::pEventHandler(&CLightning::H0x025f0004_LightningStike_04), DEBUGSTRING("CLightning::H0x025f0004_LightningStike_04")}, + {0x025f0005, -1, CEntity::pEventHandler(&CLightning::H0x025f0005_LightningStike_05), DEBUGSTRING("CLightning::H0x025f0005_LightningStike_05")}, + {0x025f0006, -1, CEntity::pEventHandler(&CLightning::H0x025f0006_LightningStike_06), DEBUGSTRING("CLightning::H0x025f0006_LightningStike_06")}, + {0x025f0007, -1, CEntity::pEventHandler(&CLightning::H0x025f0007_LightningStike_07), DEBUGSTRING("CLightning::H0x025f0007_LightningStike_07")}, + {0x025f0008, -1, CEntity::pEventHandler(&CLightning::H0x025f0008_LightningStike_08), DEBUGSTRING("CLightning::H0x025f0008_LightningStike_08")}, + {1, -1, CEntity::pEventHandler(&CLightning:: +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Lightning.es" +Main),DEBUGSTRING("CLightning::Main")}, + {0x025f0009, -1, CEntity::pEventHandler(&CLightning::H0x025f0009_Main_01), DEBUGSTRING("CLightning::H0x025f0009_Main_01")}, + {0x025f000a, -1, CEntity::pEventHandler(&CLightning::H0x025f000a_Main_02), DEBUGSTRING("CLightning::H0x025f000a_Main_02")}, + {0x025f000b, -1, CEntity::pEventHandler(&CLightning::H0x025f000b_Main_03), DEBUGSTRING("CLightning::H0x025f000b_Main_03")}, + {0x025f000c, -1, CEntity::pEventHandler(&CLightning::H0x025f000c_Main_04), DEBUGSTRING("CLightning::H0x025f000c_Main_04")}, + {0x025f000d, -1, CEntity::pEventHandler(&CLightning::H0x025f000d_Main_05), DEBUGSTRING("CLightning::H0x025f000d_Main_05")}, + {0x025f000e, -1, CEntity::pEventHandler(&CLightning::H0x025f000e_Main_06), DEBUGSTRING("CLightning::H0x025f000e_Main_06")}, +}; +#define CLightning_handlersct ARRAYCOUNT(CLightning_handlers) + +CEntity *CLightning_New(void) { return new CLightning; }; +void CLightning_OnInitClass(void) {}; +void CLightning_OnEndClass(void) {}; +void CLightning_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CLightning_OnWorldEnd(CWorld *pwo) {}; +void CLightning_OnWorldInit(CWorld *pwo) {}; +void CLightning_OnWorldTick(CWorld *pwo) {}; +void CLightning_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CLightning, CMovableModelEntity, "Lightning", "Thumbnails\\Lightning.tbn", 0x0000025f); +DECLARE_CTFILENAME(_fnmCLightning_tbn, "Thumbnails\\Lightning.tbn"); diff --git a/Sources/EntitiesMP/Marker.cpp b/Sources/EntitiesMP/Marker.cpp new file mode 100644 index 0000000..f0d3971 --- /dev/null +++ b/Sources/EntitiesMP/Marker.cpp @@ -0,0 +1,95 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" + +#include "StdH.h" + +#include +#include +void CMarker::SetDefaultProperties(void) { + m_strName = "Marker"; + m_strDescription = ""; + m_penTarget = NULL; + CEntity::SetDefaultProperties(); +} + +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +const CTString & CMarker::GetDescription(void)const +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +{ +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +if(m_penTarget != NULL ){ +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , m_penTarget -> GetName ()); +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +} +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +return m_strDescription ; +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +} + +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +BOOL CMarker::MovesByTargetedRoute(CTString & strTargetProperty)const { +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +strTargetProperty = "Target"; +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +return TRUE ; +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +} + +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +BOOL CMarker::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +fnmMarkerClass = CTFILENAME ("Classes\\Marker.ecl"); +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +strTargetProperty = "Target"; +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +return TRUE ; +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +} + BOOL CMarker::IsMarker(void)const +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +{ +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +return TRUE ; +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +} + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +SLONG CMarker::GetUsedMemory(void) +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +{ +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +SLONG slUsedMemory = sizeof (CMarker ) - sizeof (CEntity ) + CEntity :: GetUsedMemory (); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +slUsedMemory += m_strName . Length (); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +slUsedMemory += m_strDescription . Length (); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +return slUsedMemory ; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +} +BOOL CMarker:: +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +InitAsEditorModel (); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +SetModel (MODEL_MARKER ); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +Return(STATE_CURRENT,EVoid()); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Marker.es b/Sources/EntitiesMP/Marker.es new file mode 100644 index 0000000..bcc7cfc --- /dev/null +++ b/Sources/EntitiesMP/Marker.es @@ -0,0 +1,85 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +202 +%{ +#include "StdH.h" +%} + +class CMarker: CEntity { +name "Marker"; +thumbnail "Thumbnails\\Marker.tbn"; +features "HasName", "HasTarget", "IsTargetable"; + +properties: + + 1 CTString m_strName "Name" 'N' = "Marker", + 3 CTString m_strDescription = "", + 2 CEntityPointer m_penTarget "Target" 'T' COLOR(C_dGREEN|0xFF), + + +components: + + 1 model MODEL_MARKER "Models\\Editor\\Axis.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex" + + +functions: + + const CTString &GetDescription(void) const + { + ((CTString&)m_strDescription).PrintF("->"); + if (m_penTarget!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", m_penTarget->GetName()); + } + return m_strDescription; + } + + /* Check if entity is moved on a route set up by its targets. */ + BOOL MovesByTargetedRoute(CTString &strTargetProperty) const { + strTargetProperty = "Target"; + return TRUE; + }; + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\Marker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + + + // this is MARKER !!!! + virtual BOOL IsMarker(void) const + { + return TRUE; + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CMarker) - sizeof(CEntity) + CEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strName.Length(); + slUsedMemory += m_strDescription.Length(); + return slUsedMemory; + } + + +procedures: + + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + return; + } +}; + diff --git a/Sources/EntitiesMP/Marker.h b/Sources/EntitiesMP/Marker.h new file mode 100644 index 0000000..2c69374 --- /dev/null +++ b/Sources/EntitiesMP/Marker.h @@ -0,0 +1,37 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Marker_INCLUDED +#define _EntitiesMP_Marker_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CMarker_DLLClass; +class CMarker : public CEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual CEntity *GetTarget(void) const { return m_penTarget; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CEntityPointer m_penTarget; + +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +const CTString & GetDescription(void)const; + +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +virtual BOOL IsMarker(void)const; + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +SLONG GetUsedMemory(void); +#define STATE_CMarker_Main 1 + BOOL +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Marker_INCLUDED diff --git a/Sources/EntitiesMP/Marker_tables.h b/Sources/EntitiesMP/Marker_tables.h new file mode 100644 index 0000000..260d726 --- /dev/null +++ b/Sources/EntitiesMP/Marker_tables.h @@ -0,0 +1,38 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CMarker + +CEntityProperty CMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ca<<8)+1, offsetof(CMarker, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ca<<8)+3, offsetof(CMarker, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000ca<<8)+2, offsetof(CMarker, m_penTarget), "Target", 'T', C_dGREEN | 0xFF, 0), +}; +#define CMarker_propertiesct ARRAYCOUNT(CMarker_properties) + +CEntityComponent CMarker_components[] = { +#define MODEL_MARKER ((0x000000ca<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_MARKER ((0x000000ca<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Vector.tex"), +}; +#define CMarker_componentsct ARRAYCOUNT(CMarker_components) + +CEventHandlerEntry CMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CMarker:: +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Marker.es" +Main),DEBUGSTRING("CMarker::Main")}, +}; +#define CMarker_handlersct ARRAYCOUNT(CMarker_handlers) + +CEntity *CMarker_New(void) { return new CMarker; }; +void CMarker_OnInitClass(void) {}; +void CMarker_OnEndClass(void) {}; +void CMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMarker_OnWorldEnd(CWorld *pwo) {}; +void CMarker_OnWorldInit(CWorld *pwo) {}; +void CMarker_OnWorldTick(CWorld *pwo) {}; +void CMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMarker, CEntity, "Marker", "Thumbnails\\Marker.tbn", 0x000000ca); +DECLARE_CTFILENAME(_fnmCMarker_tbn, "Thumbnails\\Marker.tbn"); diff --git a/Sources/EntitiesMP/MessageHolder.cpp b/Sources/EntitiesMP/MessageHolder.cpp new file mode 100644 index 0000000..5cdedf2 --- /dev/null +++ b/Sources/EntitiesMP/MessageHolder.cpp @@ -0,0 +1,94 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" + +#include "StdH.h" +extern INDEX ent_bReportBrokenChains; + +#include +#include +void CMessageHolder::SetDefaultProperties(void) { + m_strName = "MessageHolder"; + m_strDescription = ""; + m_fnmMessage = CTString(""); + m_fDistance = 2.0f; + m_bActive = TRUE ; + m_penNext = NULL; + CRationalEntity::SetDefaultProperties(); +} + +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +const CTString & CMessageHolder::GetDescription(void)const { +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +((CTString &) m_strDescription ) . PrintF ("%s" , m_fnmMessage . FileName ()); +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +return m_strDescription ; +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +} +BOOL CMessageHolder:: +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMessageHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMessageHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +InitAsEditorModel (); +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +SetModel (MODEL_MARKER ); +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00e20000, FALSE, EBegin());return TRUE;}BOOL CMessageHolder::H0x00e20000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e20000 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +if(! m_bActive ){ +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +return TRUE; +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +} +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +CEntity * penCaused = FixupCausedToPlayer (this , eTrigger . penCaused ); +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +EComputerMessage eMsg ; +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +eMsg . fnmMessage = m_fnmMessage ; +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +penCaused -> SendEvent (eMsg ); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +return TRUE; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +m_bActive = TRUE ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +return TRUE; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +m_bActive = FALSE ; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +return TRUE; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +}return TRUE;}BOOL CMessageHolder::H0x00e20001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e20001 + +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/MessageHolder.es b/Sources/EntitiesMP/MessageHolder.es new file mode 100644 index 0000000..29ce68c --- /dev/null +++ b/Sources/EntitiesMP/MessageHolder.es @@ -0,0 +1,65 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +226 +%{ +#include "StdH.h" +extern INDEX ent_bReportBrokenChains; +%} + +class CMessageHolder : CRationalEntity { +name "MessageHolder"; +thumbnail "Thumbnails\\MessageHolder.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "MessageHolder", + 3 CTString m_strDescription = "", + 2 CTFileName m_fnmMessage "Message" 'M' = CTString(""), + 4 FLOAT m_fDistance "Distance" 'D' = 2.0f, + 5 BOOL m_bActive "Active" 'A' = TRUE, + 6 CEntityPointer m_penNext "Next" 'X', + +components: + 1 model MODEL_MARKER "Models\\Editor\\MessageHolder.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\MessageHolder.tex" + +functions: + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("%s", m_fnmMessage.FileName()); + return m_strDescription; + } + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + wait() { + on (ETrigger eTrigger): { + if (!m_bActive) { + resume; + } + CEntity *penCaused = FixupCausedToPlayer(this, eTrigger.penCaused); + EComputerMessage eMsg; + eMsg.fnmMessage = m_fnmMessage; + penCaused->SendEvent(eMsg); + resume; + } + on (EActivate): { + m_bActive = TRUE; + resume; + } + on (EDeactivate): { + m_bActive = FALSE; + resume; + } + } + return; + } +}; + diff --git a/Sources/EntitiesMP/MessageHolder.h b/Sources/EntitiesMP/MessageHolder.h new file mode 100644 index 0000000..267ce20 --- /dev/null +++ b/Sources/EntitiesMP/MessageHolder.h @@ -0,0 +1,29 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_MessageHolder_INCLUDED +#define _EntitiesMP_MessageHolder_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CMessageHolder_DLLClass; +class CMessageHolder : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CTFileName m_fnmMessage; + FLOAT m_fDistance; + BOOL m_bActive; + CEntityPointer m_penNext; + +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +const CTString & GetDescription(void)const; +#define STATE_CMessageHolder_Main 1 + BOOL +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00e20000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00e20001_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_MessageHolder_INCLUDED diff --git a/Sources/EntitiesMP/MessageHolder_tables.h b/Sources/EntitiesMP/MessageHolder_tables.h new file mode 100644 index 0000000..03c6231 --- /dev/null +++ b/Sources/EntitiesMP/MessageHolder_tables.h @@ -0,0 +1,43 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CMessageHolder + +CEntityProperty CMessageHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e2<<8)+1, offsetof(CMessageHolder, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e2<<8)+3, offsetof(CMessageHolder, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000e2<<8)+2, offsetof(CMessageHolder, m_fnmMessage), "Message", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e2<<8)+4, offsetof(CMessageHolder, m_fDistance), "Distance", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e2<<8)+5, offsetof(CMessageHolder, m_bActive), "Active", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000e2<<8)+6, offsetof(CMessageHolder, m_penNext), "Next", 'X', 0x7F0000FFUL, 0), +}; +#define CMessageHolder_propertiesct ARRAYCOUNT(CMessageHolder_properties) + +CEntityComponent CMessageHolder_components[] = { +#define MODEL_MARKER ((0x000000e2<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\MessageHolder.mdl"), +#define TEXTURE_MARKER ((0x000000e2<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\MessageHolder.tex"), +}; +#define CMessageHolder_componentsct ARRAYCOUNT(CMessageHolder_components) + +CEventHandlerEntry CMessageHolder_handlers[] = { + {1, -1, CEntity::pEventHandler(&CMessageHolder:: +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/MessageHolder.es" +Main),DEBUGSTRING("CMessageHolder::Main")}, + {0x00e20000, -1, CEntity::pEventHandler(&CMessageHolder::H0x00e20000_Main_01), DEBUGSTRING("CMessageHolder::H0x00e20000_Main_01")}, + {0x00e20001, -1, CEntity::pEventHandler(&CMessageHolder::H0x00e20001_Main_02), DEBUGSTRING("CMessageHolder::H0x00e20001_Main_02")}, +}; +#define CMessageHolder_handlersct ARRAYCOUNT(CMessageHolder_handlers) + +CEntity *CMessageHolder_New(void) { return new CMessageHolder; }; +void CMessageHolder_OnInitClass(void) {}; +void CMessageHolder_OnEndClass(void) {}; +void CMessageHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMessageHolder_OnWorldEnd(CWorld *pwo) {}; +void CMessageHolder_OnWorldInit(CWorld *pwo) {}; +void CMessageHolder_OnWorldTick(CWorld *pwo) {}; +void CMessageHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMessageHolder, CRationalEntity, "MessageHolder", "Thumbnails\\MessageHolder.tbn", 0x000000e2); +DECLARE_CTFILENAME(_fnmCMessageHolder_tbn, "Thumbnails\\MessageHolder.tbn"); diff --git a/Sources/EntitiesMP/MessageItem.cpp b/Sources/EntitiesMP/MessageItem.cpp new file mode 100644 index 0000000..d28b334 --- /dev/null +++ b/Sources/EntitiesMP/MessageItem.cpp @@ -0,0 +1,126 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" + +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" + +#include +#include +CEntityEvent *EMessageItem::MakeCopy(void) { CEntityEvent *peeCopy = new EMessageItem(*this); return peeCopy;} +EMessageItem::EMessageItem() : CEntityEvent(EVENTCODE_EMessageItem) {; + ClearToDefault(fnmMessage); +}; +#line 16 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" + + +void CMessageItem::SetDefaultProperties(void) { + m_strName = "MessageItem"; + m_strDescription = ""; + m_fnmMessage = CTString(""); + m_iSoundComponent = 0; + CItem::SetDefaultProperties(); +} + +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +void CMessageItem::Precache(void) { +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +PrecacheSound (SOUND_KEY ); +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +} + +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +BOOL CMessageItem::FillEntityStatistics(EntityStats * pes) +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +{ +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +pes -> es_strName = "Pergament"; +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +pes -> es_ctCount = 1; +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +pes -> es_ctAmmount = 1; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +pes -> es_fValue = 1; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +pes -> es_iScore = 0; +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +return TRUE ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +} + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +void CMessageItem::RenderParticles(void) { +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +if(GetRenderType () != CEntity :: RT_MODEL ){ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +return ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +} +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +Particles_Stardust (this , 0.9f , 0.70f , PT_STAR08 , 32); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +} + +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +void CMessageItem::SetProperties(void) +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +{ +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +m_strDescription = m_fnmMessage . FileName (); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +AddItem (MODEL_PERGAMENT , TEXTURE_PERGAMENT , 0 , 0 , 0); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +StretchItem (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +m_iSoundComponent = SOUND_KEY ; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +} +BOOL CMessageItem:: +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +ItemCollected(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMessageItem_ItemCollected + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EPass, "CMessageItem::ItemCollected expects 'EPass' as input!"); const EPass &epass = (const EPass &)__eeInput; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +ASSERT (epass . penOther != NULL ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +EMessageItem eMessage ; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +eMessage . fnmMessage = m_fnmMessage ; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +if(epass . penOther -> ReceiveItem (eMessage )){ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +m_soPick . Set3DParameters (50.0f , 1.0f , 1.0f , 1.0f); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +PlaySound (m_soPick , m_iSoundComponent , SOF_3D ); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +m_fPickSoundLen = GetSoundLength (m_iSoundComponent ); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemReceived, FALSE, EVoid());return TRUE; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +} +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +Return(STATE_CURRENT,EVoid()); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CMessageItem:: +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMessageItem_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMessageItem::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +Initialize (); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_SMALL ); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +SetProperties (); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/MessageItem.es b/Sources/EntitiesMP/MessageItem.es new file mode 100644 index 0000000..fcd8abf --- /dev/null +++ b/Sources/EntitiesMP/MessageItem.es @@ -0,0 +1,106 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +807 +%{ +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" +%} + +uses "EntitiesMP/Item"; + +// event for sending through receive item +event EMessageItem { + CTFileName fnmMessage, +}; + +%{ +%} + +class CMessageItem : CItem { +name "MessageItem"; +thumbnail "Thumbnails\\MessageItem.tbn"; + +properties: + 1 CTString m_strName "Name" 'N' = "MessageItem", + 2 CTString m_strDescription = "", + 3 CTFileName m_fnmMessage "Message" 'M' = CTString(""), + 4 INDEX m_iSoundComponent = 0, + +components: + 0 class CLASS_BASE "Classes\\Item.ecl", + + 1 model MODEL_PERGAMENT "Models\\Items\\Pergament\\Pergament.mdl", + 2 texture TEXTURE_PERGAMENT "Models\\Items\\Pergament\\Pergament.tex", + + // ********* MISC ********* +255 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex", +256 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl", + +// ************** SOUNDS ************** +301 sound SOUND_KEY "Sounds\\Items\\Key.wav", + +functions: + void Precache(void) { + PrecacheSound(SOUND_KEY); + } + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + pes->es_strName = "Pergament"; + pes->es_ctCount = 1; + pes->es_ctAmmount = 1; + pes->es_fValue = 1; + pes->es_iScore = 0;//m_iScore; + return TRUE; + } + // render particles + void RenderParticles(void) { + // no particles when not existing + if (GetRenderType()!=CEntity::RT_MODEL) { + return; + } + Particles_Stardust(this, 0.9f, 0.70f, PT_STAR08, 32); + } + + + // set health properties depending on type + void SetProperties(void) + { + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription = m_fnmMessage.FileName(); + + // set appearance + AddItem(MODEL_PERGAMENT, TEXTURE_PERGAMENT, 0, 0, 0); + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); + StretchItem(FLOAT3D(1.0f, 1.0f, 1.0f)); + m_iSoundComponent = SOUND_KEY; + }; + +procedures: + ItemCollected(EPass epass) : CItem::ItemCollected { + ASSERT(epass.penOther!=NULL); + + // send key to entity + EMessageItem eMessage; + eMessage.fnmMessage = m_fnmMessage; + // if health is received + if (epass.penOther->ReceiveItem(eMessage)) { + // play the pickup sound + m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f); + PlaySound(m_soPick, m_iSoundComponent, SOF_3D); + m_fPickSoundLen = GetSoundLength(m_iSoundComponent); + jump CItem::ItemReceived(); + } + return; + }; + + Main() { + Initialize(); // initialize base class + StartModelAnim(ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_SMALL); + SetProperties(); // set properties + + jump CItem::ItemLoop(); + }; +}; diff --git a/Sources/EntitiesMP/MessageItem.h b/Sources/EntitiesMP/MessageItem.h new file mode 100644 index 0000000..1bf1724 --- /dev/null +++ b/Sources/EntitiesMP/MessageItem.h @@ -0,0 +1,45 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_MessageItem_INCLUDED +#define _EntitiesMP_MessageItem_INCLUDED 1 +#include +#define EVENTCODE_EMessageItem 0x03270000 +class DECL_DLL EMessageItem : public CEntityEvent { +public: +EMessageItem(); +CEntityEvent *MakeCopy(void); +CTFileName fnmMessage; +}; +DECL_DLL inline void ClearToDefault(EMessageItem &e) { e = EMessageItem(); } ; +extern "C" DECL_DLL CDLLEntityClass CMessageItem_DLLClass; +class CMessageItem : public CItem { +public: + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CTFileName m_fnmMessage; + INDEX m_iSoundComponent; + +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +void Precache(void); + +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +void RenderParticles(void); + +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +void SetProperties(void); +#define STATE_CMessageItem_ItemCollected 0x03270001 + BOOL +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +ItemCollected(const CEntityEvent &__eeInput); +#define STATE_CMessageItem_Main 1 + BOOL +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_MessageItem_INCLUDED diff --git a/Sources/EntitiesMP/MessageItem_tables.h b/Sources/EntitiesMP/MessageItem_tables.h new file mode 100644 index 0000000..c592fa6 --- /dev/null +++ b/Sources/EntitiesMP/MessageItem_tables.h @@ -0,0 +1,50 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CMessageItem + +CEntityProperty CMessageItem_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000327<<8)+1, offsetof(CMessageItem, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000327<<8)+2, offsetof(CMessageItem, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x00000327<<8)+3, offsetof(CMessageItem, m_fnmMessage), "Message", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000327<<8)+4, offsetof(CMessageItem, m_iSoundComponent), "", 0, 0, 0), +}; +#define CMessageItem_propertiesct ARRAYCOUNT(CMessageItem_properties) + +CEntityComponent CMessageItem_components[] = { +#define CLASS_BASE ((0x00000327<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\Item.ecl"), +#define MODEL_PERGAMENT ((0x00000327<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_PERGAMENT, "EFNM" "Models\\Items\\Pergament\\Pergament.mdl"), +#define TEXTURE_PERGAMENT ((0x00000327<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_PERGAMENT, "EFNM" "Models\\Items\\Pergament\\Pergament.tex"), +#define TEXTURE_FLARE ((0x00000327<<8)+255) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.tex"), +#define MODEL_FLARE ((0x00000327<<8)+256) + CEntityComponent(ECT_MODEL, MODEL_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.mdl"), +#define SOUND_KEY ((0x00000327<<8)+301) + CEntityComponent(ECT_SOUND, SOUND_KEY, "EFNM" "Sounds\\Items\\Key.wav"), +}; +#define CMessageItem_componentsct ARRAYCOUNT(CMessageItem_components) + +CEventHandlerEntry CMessageItem_handlers[] = { + {0x03270001, STATE_CItem_ItemCollected, CEntity::pEventHandler(&CMessageItem:: +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +ItemCollected),DEBUGSTRING("CMessageItem::ItemCollected")}, + {1, -1, CEntity::pEventHandler(&CMessageItem:: +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/MessageItem.es" +Main),DEBUGSTRING("CMessageItem::Main")}, +}; +#define CMessageItem_handlersct ARRAYCOUNT(CMessageItem_handlers) + +CEntity *CMessageItem_New(void) { return new CMessageItem; }; +void CMessageItem_OnInitClass(void) {}; +void CMessageItem_OnEndClass(void) {}; +void CMessageItem_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMessageItem_OnWorldEnd(CWorld *pwo) {}; +void CMessageItem_OnWorldInit(CWorld *pwo) {}; +void CMessageItem_OnWorldTick(CWorld *pwo) {}; +void CMessageItem_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMessageItem, CItem, "MessageItem", "Thumbnails\\MessageItem.tbn", 0x00000327); +DECLARE_CTFILENAME(_fnmCMessageItem_tbn, "Thumbnails\\MessageItem.tbn"); diff --git a/Sources/EntitiesMP/MeteorShower.cpp b/Sources/EntitiesMP/MeteorShower.cpp new file mode 100644 index 0000000..2bf0ad9 --- /dev/null +++ b/Sources/EntitiesMP/MeteorShower.cpp @@ -0,0 +1,186 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" + +#include "StdH.h" + +#include +#include +void CMeteorShower::SetDefaultProperties(void) { + m_strName = "Meteor Shower"; + m_aAngle = ANGLE3D(AngleDeg (0.0f) , AngleDeg (0.0f) , AngleDeg (0.0f)); + m_iPerTickLaunchChance = 10; + m_fMinStretch = 1.0f; + m_fMaxStretch = 1.1f; + m_rSafeArea = 10.0f; + m_rArea = 50.0f; + m_fSpeed = 300.0f; + m_fLaunchDistance = 500.0f; + CRationalEntity::SetDefaultProperties(); +} + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +void CMeteorShower::Precache(void) { +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +PrecacheClass (CLASS_PROJECTILE , PRT_METEOR ); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +} + +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +void CMeteorShower::SpawnProjectile(const CPlacement3D & pl) +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +{ +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +CEntityPointer pen = CreateEntity (pl , CLASS_PROJECTILE ); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +ELaunchProjectile eLaunch ; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +eLaunch . penLauncher = this ; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +eLaunch . prtType = PRT_METEOR ; +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +eLaunch . fStretch = Lerp (m_fMinStretch , m_fMaxStretch , FRnd ()); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +eLaunch . fSpeed = m_fSpeed ; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +pen -> Initialize (eLaunch ); +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +} + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +void CMeteorShower::MaybeShootMeteor(void) +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +{ +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +INDEX iShoot = IRnd () % 100; +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +if(iShoot <= m_iPerTickLaunchChance ) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +{ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +CPlacement3D plFall ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +plFall . pl_PositionVector = GetPlacement () . pl_PositionVector ; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +FLOAT fR = Lerp (m_rSafeArea , m_rArea , FRnd ()); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +FLOAT fA = FRnd () * 360.0f; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +plFall . pl_PositionVector += FLOAT3D (CosFast (fA ) * fR , 0.05f , SinFast (fA ) * fR ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +FLOAT3D vDir ; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +AnglesToDirectionVector (m_aAngle , vDir ); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +vDir . Normalize (); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +CPlacement3D plLaunch = plFall ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +plLaunch . pl_PositionVector = plFall . pl_PositionVector - vDir * m_fLaunchDistance ; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +plLaunch . pl_OrientationAngle = m_aAngle ; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +SpawnProjectile (plLaunch ); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +} +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +} +BOOL CMeteorShower:: +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Active(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMeteorShower_Active + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMeteorShower::Active expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Jump(STATE_CURRENT,0x02670003, FALSE, EInternal());return TRUE;}BOOL CMeteorShower::H0x02670003_Active_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02670003 +if(!(TRUE )){ Jump(STATE_CURRENT,0x02670004, FALSE, EInternal());return TRUE;} +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x02670001, FALSE, EBegin());return TRUE;}BOOL CMeteorShower::H0x02670001_Active_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02670001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +return TRUE; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnvironmentStop):{const EEnvironmentStop&e= (EEnvironmentStop&)__eeInput; + +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Jump(STATE_CURRENT, STATE_CMeteorShower_Inactive, TRUE, EVoid());return TRUE; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; + +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +MaybeShootMeteor (); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +UnsetTimer();Jump(STATE_CURRENT,0x02670002, FALSE, EInternal());return TRUE; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +}return TRUE;}BOOL CMeteorShower::H0x02670002_Active_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02670002 +Jump(STATE_CURRENT,0x02670003, FALSE, EInternal());return TRUE; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +}BOOL CMeteorShower::H0x02670004_Active_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02670004 + ASSERT(FALSE); return TRUE;};BOOL CMeteorShower:: +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Inactive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMeteorShower_Inactive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMeteorShower::Inactive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x02670006, FALSE, EBegin());return TRUE;}BOOL CMeteorShower::H0x02670006_Inactive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02670006 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EEnvironmentStart):{const EEnvironmentStart&e= (EEnvironmentStart&)__eeInput; +Jump(STATE_CURRENT, STATE_CMeteorShower_Active, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +}return TRUE;}BOOL CMeteorShower::H0x02670007_Inactive_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02670007 + ASSERT(FALSE); return TRUE;};BOOL CMeteorShower:: +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMeteorShower_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMeteorShower::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +if(m_fMinStretch > m_fMaxStretch ){m_fMinStretch = m_fMaxStretch ;} +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +if(m_rSafeArea > m_rArea ){m_rSafeArea = m_rArea ;} +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +InitAsEditorModel (); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +SetModel (MODEL_MARKER ); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x02670008, FALSE, EBegin());return TRUE;}BOOL CMeteorShower::H0x02670008_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02670008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02670009, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CMeteorShower::H0x02670009_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02670009 +; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Jump(STATE_CURRENT, STATE_CMeteorShower_Inactive, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/MeteorShower.es b/Sources/EntitiesMP/MeteorShower.es new file mode 100644 index 0000000..809c331 --- /dev/null +++ b/Sources/EntitiesMP/MeteorShower.es @@ -0,0 +1,134 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +615 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Projectile"; +//uses "Entities/EnemyMarker"; + +class CMeteorShower : CRationalEntity { +name "MeteorShower"; +thumbnail "Thumbnails\\Eruptor.tbn"; +features "IsTargetable", "HasName"; + +properties: + + 1 CTString m_strName "Name" 'N' = "Meteor Shower", // class name + + 10 ANGLE3D m_aAngle "Shoot Angle" 'S' = ANGLE3D( AngleDeg(0.0f),AngleDeg(0.0f),AngleDeg(0.0f)), + 11 INDEX m_iPerTickLaunchChance "Density (1-100)" 'D' = 10, // 0-100 + + 15 FLOAT m_fMinStretch "Min. Stretch" = 1.0f, + 16 FLOAT m_fMaxStretch "Max. Stretch" = 1.1f, + + 19 RANGE m_rSafeArea "Safe Area" = 10.0f, + 20 RANGE m_rArea "Area" = 50.0f, + + 30 FLOAT m_fSpeed "Speed" 'P' = 300.0f, + 40 FLOAT m_fLaunchDistance "Launch distance" 'L' = 500.0f, + + +components: + + 1 model MODEL_MARKER "ModelsMP\\Editor\\EffectMarker.mdl", + 2 texture TEXTURE_MARKER "ModelsMP\\Editor\\EffectMarker.tex", + + 5 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + +functions: + void Precache(void) { + PrecacheClass(CLASS_PROJECTILE, PRT_METEOR); + } + + // fire projectile in given direction with given speed + void SpawnProjectile(const CPlacement3D &pl) + { + CEntityPointer pen = CreateEntity(pl, CLASS_PROJECTILE); + + // launch + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_METEOR; + eLaunch.fStretch = Lerp(m_fMinStretch, m_fMaxStretch, FRnd()); + eLaunch.fSpeed = m_fSpeed; + pen->Initialize(eLaunch); + } + + void MaybeShootMeteor(void) + { + INDEX iShoot = IRnd()%100; + + if (iShoot<=m_iPerTickLaunchChance) + { + CPlacement3D plFall; + + plFall.pl_PositionVector = GetPlacement().pl_PositionVector; + FLOAT fR = Lerp(m_rSafeArea, m_rArea, FRnd()); + FLOAT fA = FRnd()*360.0f; + plFall.pl_PositionVector += FLOAT3D(CosFast(fA)*fR, 0.05f, SinFast(fA)*fR); + FLOAT3D vDir; + AnglesToDirectionVector(m_aAngle, vDir); + vDir.Normalize(); + CPlacement3D plLaunch=plFall; + plLaunch.pl_PositionVector=plFall.pl_PositionVector-vDir*m_fLaunchDistance; + plLaunch.pl_OrientationAngle = m_aAngle; + SpawnProjectile(plLaunch); + } + } + +procedures: +/************************************************************ + * A C T I O N S * + ************************************************************/ + // active state + Active(EVoid) + { + while (TRUE) { + + wait(_pTimer->TickQuantum) { + on (EBegin) : { + resume; + } + on (EEnvironmentStop) : { + jump Inactive(); + } + on (ETimer) : { + MaybeShootMeteor(); + stop; + } + } // wait + + } + }; + + // inactive state + Inactive(EVoid) + { + wait() { + on (EBegin) : { resume; } + on (EEnvironmentStart) : { jump Active(); } + } + }; + + + Main(EVoid) { + + if (m_fMinStretch>m_fMaxStretch) { m_fMinStretch = m_fMaxStretch; } + if (m_rSafeArea>m_rArea) { m_rSafeArea = m_rArea; } + + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + autowait(0.05f); + + jump Inactive(); + } + +}; diff --git a/Sources/EntitiesMP/MeteorShower.h b/Sources/EntitiesMP/MeteorShower.h new file mode 100644 index 0000000..4295ee5 --- /dev/null +++ b/Sources/EntitiesMP/MeteorShower.h @@ -0,0 +1,53 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_MeteorShower_INCLUDED +#define _EntitiesMP_MeteorShower_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CMeteorShower_DLLClass; +class CMeteorShower : public CRationalEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + ANGLE3D m_aAngle; + INDEX m_iPerTickLaunchChance; + FLOAT m_fMinStretch; + FLOAT m_fMaxStretch; + RANGE m_rSafeArea; + RANGE m_rArea; + FLOAT m_fSpeed; + FLOAT m_fLaunchDistance; + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +void Precache(void); + +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +void SpawnProjectile(const CPlacement3D & pl); + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +void MaybeShootMeteor(void); +#define STATE_CMeteorShower_Active 0x02670000 + BOOL +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Active(const CEntityEvent &__eeInput); + BOOL H0x02670001_Active_01(const CEntityEvent &__eeInput); + BOOL H0x02670002_Active_02(const CEntityEvent &__eeInput); + BOOL H0x02670003_Active_03(const CEntityEvent &__eeInput); + BOOL H0x02670004_Active_04(const CEntityEvent &__eeInput); +#define STATE_CMeteorShower_Inactive 0x02670005 + BOOL +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Inactive(const CEntityEvent &__eeInput); + BOOL H0x02670006_Inactive_01(const CEntityEvent &__eeInput); + BOOL H0x02670007_Inactive_02(const CEntityEvent &__eeInput); +#define STATE_CMeteorShower_Main 1 + BOOL +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x02670008_Main_01(const CEntityEvent &__eeInput); + BOOL H0x02670009_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_MeteorShower_INCLUDED diff --git a/Sources/EntitiesMP/MeteorShower_tables.h b/Sources/EntitiesMP/MeteorShower_tables.h new file mode 100644 index 0000000..4bd1830 --- /dev/null +++ b/Sources/EntitiesMP/MeteorShower_tables.h @@ -0,0 +1,60 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CMeteorShower + +CEntityProperty CMeteorShower_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000267<<8)+1, offsetof(CMeteorShower, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x00000267<<8)+10, offsetof(CMeteorShower, m_aAngle), "Shoot Angle", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000267<<8)+11, offsetof(CMeteorShower, m_iPerTickLaunchChance), "Density (1-100)", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000267<<8)+15, offsetof(CMeteorShower, m_fMinStretch), "Min. Stretch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000267<<8)+16, offsetof(CMeteorShower, m_fMaxStretch), "Max. Stretch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000267<<8)+19, offsetof(CMeteorShower, m_rSafeArea), "Safe Area", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000267<<8)+20, offsetof(CMeteorShower, m_rArea), "Area", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000267<<8)+30, offsetof(CMeteorShower, m_fSpeed), "Speed", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000267<<8)+40, offsetof(CMeteorShower, m_fLaunchDistance), "Launch distance", 'L', 0x7F0000FFUL, 0), +}; +#define CMeteorShower_propertiesct ARRAYCOUNT(CMeteorShower_properties) + +CEntityComponent CMeteorShower_components[] = { +#define MODEL_MARKER ((0x00000267<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "ModelsMP\\Editor\\EffectMarker.mdl"), +#define TEXTURE_MARKER ((0x00000267<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "ModelsMP\\Editor\\EffectMarker.tex"), +#define CLASS_PROJECTILE ((0x00000267<<8)+5) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +}; +#define CMeteorShower_componentsct ARRAYCOUNT(CMeteorShower_components) + +CEventHandlerEntry CMeteorShower_handlers[] = { + {0x02670000, -1, CEntity::pEventHandler(&CMeteorShower:: +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Active),DEBUGSTRING("CMeteorShower::Active")}, + {0x02670001, -1, CEntity::pEventHandler(&CMeteorShower::H0x02670001_Active_01), DEBUGSTRING("CMeteorShower::H0x02670001_Active_01")}, + {0x02670002, -1, CEntity::pEventHandler(&CMeteorShower::H0x02670002_Active_02), DEBUGSTRING("CMeteorShower::H0x02670002_Active_02")}, + {0x02670003, -1, CEntity::pEventHandler(&CMeteorShower::H0x02670003_Active_03), DEBUGSTRING("CMeteorShower::H0x02670003_Active_03")}, + {0x02670004, -1, CEntity::pEventHandler(&CMeteorShower::H0x02670004_Active_04), DEBUGSTRING("CMeteorShower::H0x02670004_Active_04")}, + {0x02670005, -1, CEntity::pEventHandler(&CMeteorShower:: +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Inactive),DEBUGSTRING("CMeteorShower::Inactive")}, + {0x02670006, -1, CEntity::pEventHandler(&CMeteorShower::H0x02670006_Inactive_01), DEBUGSTRING("CMeteorShower::H0x02670006_Inactive_01")}, + {0x02670007, -1, CEntity::pEventHandler(&CMeteorShower::H0x02670007_Inactive_02), DEBUGSTRING("CMeteorShower::H0x02670007_Inactive_02")}, + {1, -1, CEntity::pEventHandler(&CMeteorShower:: +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/MeteorShower.es" +Main),DEBUGSTRING("CMeteorShower::Main")}, + {0x02670008, -1, CEntity::pEventHandler(&CMeteorShower::H0x02670008_Main_01), DEBUGSTRING("CMeteorShower::H0x02670008_Main_01")}, + {0x02670009, -1, CEntity::pEventHandler(&CMeteorShower::H0x02670009_Main_02), DEBUGSTRING("CMeteorShower::H0x02670009_Main_02")}, +}; +#define CMeteorShower_handlersct ARRAYCOUNT(CMeteorShower_handlers) + +CEntity *CMeteorShower_New(void) { return new CMeteorShower; }; +void CMeteorShower_OnInitClass(void) {}; +void CMeteorShower_OnEndClass(void) {}; +void CMeteorShower_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMeteorShower_OnWorldEnd(CWorld *pwo) {}; +void CMeteorShower_OnWorldInit(CWorld *pwo) {}; +void CMeteorShower_OnWorldTick(CWorld *pwo) {}; +void CMeteorShower_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMeteorShower, CRationalEntity, "MeteorShower", "Thumbnails\\Eruptor.tbn", 0x00000267); +DECLARE_CTFILENAME(_fnmCMeteorShower_tbn, "Thumbnails\\Eruptor.tbn"); diff --git a/Sources/EntitiesMP/MirrorMarker.cpp b/Sources/EntitiesMP/MirrorMarker.cpp new file mode 100644 index 0000000..c010092 --- /dev/null +++ b/Sources/EntitiesMP/MirrorMarker.cpp @@ -0,0 +1,109 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" + +#include "StdH.h" + +#include +#include +void CMirrorMarker::SetDefaultProperties(void) { + m_wrRotation = WR_NONE ; + m_fRotationSpeed = 90.0f; + CMarker::SetDefaultProperties(); +} + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +const CTString & CMirrorMarker::GetMirrorName(void) +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +{ +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +return m_strName ; +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +} + +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +void CMirrorMarker::GetMirror(class CMirrorParameters & mpMirror) +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +{ +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +mpMirror . mp_ulFlags = MPF_WARP ; +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +mpMirror . mp_plWarpIn = GetLerpedPlacement (); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +if(m_penTarget != NULL ){ +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +mpMirror . mp_penWarpViewer = m_penTarget ; +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +mpMirror . mp_plWarpOut = m_penTarget -> GetLerpedPlacement (); +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +}else { +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +mpMirror . mp_penWarpViewer = this ; +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +mpMirror . mp_plWarpOut = GetLerpedPlacement (); +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +} +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +FLOAT tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +mpMirror . mp_fWarpFOV = - 1.0f; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +if(m_wrRotation == WR_BANKING ){ +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +mpMirror . mp_plWarpOut . Rotate_Airplane (ANGLE3D (0 , 0 , m_fRotationSpeed * tmNow )); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +}else if(m_wrRotation == WR_TWIRLING ){ +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +ANGLE3D a ; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +a (1) = sin (tmNow * 3.9) * 5.0f; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +a (2) = sin (tmNow * 2.7) * 5.0f; +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +a (3) = sin (tmNow * 4.5) * 5.0f; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +mpMirror . mp_plWarpOut . Rotate_Airplane (a ); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +mpMirror . mp_fWarpFOV = 90.0f + sin (tmNow * 7.79f) * 5.0f; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +} +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +} +BOOL CMirrorMarker:: +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMirrorMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMirrorMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +InitAsEditorModel (); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +if(m_penTarget != NULL ){ +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +SetModel (MODEL_IN ); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +SetModelMainTexture (TEXTURE_IN ); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +}else { +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +SetModel (MODEL_OUT ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +SetModelMainTexture (TEXTURE_OUT ); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +} +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +if(m_strName == "Marker"){ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +m_strName = "Mirror marker"; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +} +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/MirrorMarker.es b/Sources/EntitiesMP/MirrorMarker.es new file mode 100644 index 0000000..ff079f7 --- /dev/null +++ b/Sources/EntitiesMP/MirrorMarker.es @@ -0,0 +1,85 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +218 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; + +enum WarpRotation { + 0 WR_NONE "none", + 1 WR_BANKING "banking", + 2 WR_TWIRLING "twirling", +}; + +class CMirrorMarker: CMarker { +name "Mirror Marker"; +thumbnail "Thumbnails\\WarpMarker.tbn"; +features "IsImportant"; + + +properties: + 1 enum WarpRotation m_wrRotation "Rotation Type" 'R' = WR_NONE, + 2 FLOAT m_fRotationSpeed "Rotation Speed" 'S' = 90.0f, +components: + 1 model MODEL_IN "Models\\Editor\\WarpEntrance.mdl", + 2 texture TEXTURE_IN "Models\\Editor\\Warp.tex", + 3 model MODEL_OUT "Models\\Editor\\WarpExit.mdl", + 4 texture TEXTURE_OUT "Models\\Editor\\Warp.tex" + +functions: + + /* Get mirror type name, return empty string if not used. */ + const CTString &GetMirrorName(void) + { + return m_strName; + } + /* Get mirror. */ + void GetMirror(class CMirrorParameters &mpMirror) + { + mpMirror.mp_ulFlags = MPF_WARP; + mpMirror.mp_plWarpIn = GetLerpedPlacement(); + if (m_penTarget!=NULL) { + mpMirror.mp_penWarpViewer = m_penTarget; + mpMirror.mp_plWarpOut = m_penTarget->GetLerpedPlacement(); + } else { + mpMirror.mp_penWarpViewer = this; + mpMirror.mp_plWarpOut = GetLerpedPlacement(); + } + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + mpMirror.mp_fWarpFOV = -1.0f; + if (m_wrRotation==WR_BANKING) { + mpMirror.mp_plWarpOut.Rotate_Airplane(ANGLE3D(0,0,m_fRotationSpeed*tmNow)); + } else if (m_wrRotation==WR_TWIRLING) { + ANGLE3D a; + a(1) = sin(tmNow*3.9)*5.0f; + a(2) = sin(tmNow*2.7)*5.0f; + a(3) = sin(tmNow*4.5)*5.0f; + mpMirror.mp_plWarpOut.Rotate_Airplane(a); + mpMirror.mp_fWarpFOV = 90.0f+sin(tmNow*7.79f)*5.0f; + } + } +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + if (m_penTarget!=NULL) { + SetModel(MODEL_IN); + SetModelMainTexture(TEXTURE_IN); + } else { + SetModel(MODEL_OUT); + SetModelMainTexture(TEXTURE_OUT); + } + + // set name + if (m_strName=="Marker") { + m_strName = "Mirror marker"; + } + return; + } +}; diff --git a/Sources/EntitiesMP/MirrorMarker.h b/Sources/EntitiesMP/MirrorMarker.h new file mode 100644 index 0000000..2933453 --- /dev/null +++ b/Sources/EntitiesMP/MirrorMarker.h @@ -0,0 +1,33 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_MirrorMarker_INCLUDED +#define _EntitiesMP_MirrorMarker_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType WarpRotation_enum; +enum WarpRotation { + WR_NONE = 0, + WR_BANKING = 1, + WR_TWIRLING = 2, +}; +DECL_DLL inline void ClearToDefault(WarpRotation &e) { e = (WarpRotation)0; } ; +extern "C" DECL_DLL CDLLEntityClass CMirrorMarker_DLLClass; +class CMirrorMarker : public CMarker { +public: +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + enum WarpRotation m_wrRotation; + FLOAT m_fRotationSpeed; + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +const CTString & GetMirrorName(void); + +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +void GetMirror(class CMirrorParameters & mpMirror); +#define STATE_CMirrorMarker_Main 1 + BOOL +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_MirrorMarker_INCLUDED diff --git a/Sources/EntitiesMP/MirrorMarker_tables.h b/Sources/EntitiesMP/MirrorMarker_tables.h new file mode 100644 index 0000000..f2a6c69 --- /dev/null +++ b/Sources/EntitiesMP/MirrorMarker_tables.h @@ -0,0 +1,47 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(WarpRotation) + EP_ENUMVALUE(WR_NONE, "none"), + EP_ENUMVALUE(WR_BANKING, "banking"), + EP_ENUMVALUE(WR_TWIRLING, "twirling"), +EP_ENUMEND(WarpRotation); + +#define ENTITYCLASS CMirrorMarker + +CEntityProperty CMirrorMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &WarpRotation_enum, (0x000000da<<8)+1, offsetof(CMirrorMarker, m_wrRotation), "Rotation Type", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000da<<8)+2, offsetof(CMirrorMarker, m_fRotationSpeed), "Rotation Speed", 'S', 0x7F0000FFUL, 0), +}; +#define CMirrorMarker_propertiesct ARRAYCOUNT(CMirrorMarker_properties) + +CEntityComponent CMirrorMarker_components[] = { +#define MODEL_IN ((0x000000da<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_IN, "EFNM" "Models\\Editor\\WarpEntrance.mdl"), +#define TEXTURE_IN ((0x000000da<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_IN, "EFNM" "Models\\Editor\\Warp.tex"), +#define MODEL_OUT ((0x000000da<<8)+3) + CEntityComponent(ECT_MODEL, MODEL_OUT, "EFNM" "Models\\Editor\\WarpExit.mdl"), +#define TEXTURE_OUT ((0x000000da<<8)+4) + CEntityComponent(ECT_TEXTURE, TEXTURE_OUT, "EFNM" "Models\\Editor\\Warp.tex"), +}; +#define CMirrorMarker_componentsct ARRAYCOUNT(CMirrorMarker_components) + +CEventHandlerEntry CMirrorMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CMirrorMarker:: +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/MirrorMarker.es" +Main),DEBUGSTRING("CMirrorMarker::Main")}, +}; +#define CMirrorMarker_handlersct ARRAYCOUNT(CMirrorMarker_handlers) + +CEntity *CMirrorMarker_New(void) { return new CMirrorMarker; }; +void CMirrorMarker_OnInitClass(void) {}; +void CMirrorMarker_OnEndClass(void) {}; +void CMirrorMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMirrorMarker_OnWorldEnd(CWorld *pwo) {}; +void CMirrorMarker_OnWorldInit(CWorld *pwo) {}; +void CMirrorMarker_OnWorldTick(CWorld *pwo) {}; +void CMirrorMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMirrorMarker, CMarker, "Mirror Marker", "Thumbnails\\WarpMarker.tbn", 0x000000da); +DECLARE_CTFILENAME(_fnmCMirrorMarker_tbn, "Thumbnails\\WarpMarker.tbn"); diff --git a/Sources/EntitiesMP/ModelDestruction.cpp b/Sources/EntitiesMP/ModelDestruction.cpp new file mode 100644 index 0000000..26b8cd1 --- /dev/null +++ b/Sources/EntitiesMP/ModelDestruction.cpp @@ -0,0 +1,457 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *ERangeModelDestruction::MakeCopy(void) { CEntityEvent *peeCopy = new ERangeModelDestruction(*this); return peeCopy;} +ERangeModelDestruction::ERangeModelDestruction() : CEntityEvent(EVENTCODE_ERangeModelDestruction) {; +}; +void CModelDestruction::SetDefaultProperties(void) { + m_strName = "ModelDestruction"; + m_strDescription = ""; + m_penModel0 = NULL; + m_penModel1 = NULL; + m_penModel2 = NULL; + m_penModel3 = NULL; + m_penModel4 = NULL; + m_fHealth = 50.0f; + m_ddtDebris = DDT_STONE ; + m_ctDebris = 3; + m_fDebrisSize = 1.0f; + m_eibtBodyType = EIBT_ROCK ; + m_sptType = SPT_NONE ; + m_fParticleSize = 1.0f; + m_bRequireExplosion = FALSE ; + m_fDebrisLaunchPower = 1.0f; + m_dptParticles = DPT_NONE ; + m_betStain = BET_NONE ; + m_fLaunchCone = 45.0f; + m_fRndRotH = 720.0f; + m_fRndRotP = 720.0f; + m_fRndRotB = 720.0f; + m_fParticleLaunchPower = 1.0f; + m_colParticles = COLOR(C_WHITE | CT_OPAQUE ); + m_iStartAnim = -1; + m_bDebrisImmaterialASAP = TRUE ; + m_ctDustFall = 1; + m_fMinDustFallHeightRatio = 0.1f; + m_fMaxDustFallHeightRatio = 0.6f; + m_fDustStretch = 1.0f; + m_fDebrisDustRandom = 0.25f; + m_fDebrisDustStretch = 1.0f; + m_penShake = NULL; + CEntity::SetDefaultProperties(); +} + +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +void CModelDestruction::Precache(void) { +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_EXPLOSIONSTAIN ); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +switch(m_ddtDebris ){ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +case DDT_STONE : { +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +PrecacheModel (MODEL_STONE ); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +PrecacheTexture (TEXTURE_STONE ); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +}break ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +case DDT_WOOD : { +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +PrecacheModel (MODEL_WOOD ); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +PrecacheTexture (TEXTURE_WOOD ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +}break ; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +case DDT_PALM : { +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +PrecacheModel (MODEL_WOOD ); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +PrecacheTexture (TEXTURE_WOOD ); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +}break ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CAnimData * CModelDestruction::GetAnimData(SLONG slPropertyOffset) +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(slPropertyOffset == offsetof (CModelDestruction , m_iStartAnim )) +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CModelHolder2 * pmh = GetModel (0); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(pmh != NULL ) +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +return pmh -> GetModelObject () -> GetData (); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +return CEntity :: GetAnimData (slPropertyOffset ); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} + +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +const CTString & CModelDestruction::GetDescription(void)const { +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +INDEX ct = GetModelsCount (); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(ct == 0){ +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +((CTString &) m_strDescription ) . PrintF ("(%g): no more" , m_fHealth ); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +}else if(ct == 1){ +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +((CTString &) m_strDescription ) . PrintF ("(%g): %s" , m_fHealth , m_penModel0 -> GetName ()); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +}else if(TRUE ){ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +((CTString &) m_strDescription ) . PrintF ("(%g): %s,...(%d)" , m_fHealth , m_penModel0 -> GetName () , ct ); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +return m_strDescription ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +void CModelDestruction::CheckOneModelTarget(CEntityPointer & pen) +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(pen != NULL && ! IsOfClass (pen , "ModelHolder2")){ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +WarningMessage ("Model '%s' is not ModelHolder2!" , pen -> GetName ()); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +pen = NULL ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} + +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +class CModelHolder2 * CModelDestruction::GetNextPhase(void) +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +INDEX ct = GetModelsCount (); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(ct == 0){ +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +return NULL ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +}else { +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +return GetModel (IRnd () % ct ); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} + +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +INDEX CModelDestruction::GetModelsCount(void)const +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(m_penModel0 == NULL ){return 0;}; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(m_penModel1 == NULL ){return 1;}; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(m_penModel2 == NULL ){return 2;}; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(m_penModel3 == NULL ){return 3;}; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(m_penModel4 == NULL ){return 4;}; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +return 5; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} + +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +class CModelHolder2 * CModelDestruction::GetModel(INDEX iModel) +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +ASSERT (iModel <= GetModelsCount ()); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +iModel = Clamp (iModel , INDEX (0) , GetModelsCount ()); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +return (CModelHolder2 *) & * (& m_penModel0 ) [ iModel ]; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} + +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +void CModelDestruction::SpawnDebris(CModelHolder2 * penmhDestroyed) +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOATaabbox3D box ; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +penmhDestroyed -> GetBoundingBox (box ); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT fEntitySize = box . Size () . MaxNorm (); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +switch(m_ddtDebris ){ +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +case DDT_STONE : { +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Begin (EIBT_ROCK , DPT_NONE , BET_NONE , fEntitySize , FLOAT3D (0 , 0 , 0) , FLOAT3D (0 , 0 , 0) , 1.0f , 0.0f); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +for(INDEX iDebris = 0;iDebris < m_ctDebris ;iDebris ++){ +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Spawn (penmhDestroyed , this , MODEL_STONE , TEXTURE_STONE , 0 , 0 , 0 , IRnd () % 4 , m_fDebrisSize , +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D (FRnd () * 0.8f + 0.1f , FRnd () * 0.8f + 0.1f , FRnd () * 0.8f + 0.1f)); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +}break ; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +case DDT_WOOD : +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Begin (EIBT_WOOD , DPT_NONE , BET_NONE , fEntitySize , FLOAT3D (0 , 0 , 0) , FLOAT3D (0 , 0 , 0) , 1.0f , 0.0f); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +for(INDEX iDebris = 0;iDebris < m_ctDebris ;iDebris ++) +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Spawn (penmhDestroyed , this , MODEL_WOOD , TEXTURE_WOOD , 0 , 0 , 0 , 0 , m_fDebrisSize , +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D (0.5f , 0.5f , 0.5f)); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +break ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +case DDT_CHILDREN_CUSTOM : +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Begin (EIBT_WOOD , DPT_NONE , BET_NONE , 1.0f , FLOAT3D (10 , 10 , 10) , FLOAT3D (0 , 0 , 0) , 5.0f , 2.0f); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , iten ) +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(IsOfClass (& * iten , "ModelHolder2")) +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CModelHolder2 & mhTemplate = (CModelHolder2 &) * iten ; +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(mhTemplate . GetModelObject () == NULL || penmhDestroyed -> GetModelObject () == NULL ) +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +continue ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CModelObject & moNew = * mhTemplate . GetModelObject (); +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CModelObject & moOld = * penmhDestroyed -> GetModelObject (); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CPlacement3D plRel = mhTemplate . GetPlacement (); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +plRel . AbsoluteToRelative (this -> GetPlacement ()); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CPlacement3D plLaunch = plRel ; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D vStretch = moOld . mo_Stretch ; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +plLaunch . pl_PositionVector (1) = plLaunch . pl_PositionVector (1) * vStretch (1); +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +plLaunch . pl_PositionVector (2) = plLaunch . pl_PositionVector (2) * vStretch (2); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +plLaunch . pl_PositionVector (3) = plLaunch . pl_PositionVector (3) * vStretch (3); +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +plLaunch . RelativeToAbsolute (penmhDestroyed -> GetPlacement ()); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +ANGLE3D angLaunch = ANGLE3D (FRnd () * 360.0f , 90.0f + m_fLaunchCone * (FRnd () - 0.5f) , 0); +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D vLaunchDir ; +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D vStretchTemplate = FLOAT3D ( +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +moOld . mo_Stretch (1) * moNew . mo_Stretch (1) , +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +moOld . mo_Stretch (2) * moNew . mo_Stretch (2) , +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +moOld . mo_Stretch (3) * moNew . mo_Stretch (3)); +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +AnglesToDirectionVector (angLaunch , vLaunchDir ); +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +vLaunchDir . Normalize (); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +vLaunchDir = vLaunchDir * m_fDebrisLaunchPower ; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +ANGLE3D angRotSpeed = ANGLE3D (m_fRndRotH * 2.0f * (FRnd () - 0.5f) , m_fRndRotP * (FRnd () - 0.5f) , m_fRndRotB * (FRnd () - 0.5f)); +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT fDustSize = 0.0f; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(FRnd () < m_fDebrisDustRandom ) +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +fDustSize = m_fDebrisDustStretch ; +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Spawn_Template (m_eibtBodyType , m_dptParticles , m_betStain , +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +penmhDestroyed , this , & mhTemplate , vStretchTemplate , mhTemplate . m_fStretchAll , plLaunch , +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +vLaunchDir , angRotSpeed , m_bDebrisImmaterialASAP , fDustSize , penmhDestroyed -> m_colBurning ); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(IsOfClass (& * iten , "SoundHolder")) +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CSoundHolder & ensh = (CSoundHolder &) * iten ; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CEntity * penNewSH = GetWorld () -> CopyEntityInWorld (ensh , penmhDestroyed -> GetPlacement ()); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +penNewSH -> SetParent (NULL ); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +penNewSH -> SendEvent (EStart ()); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +break ; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +case DDT_PALM : { +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Begin (EIBT_WOOD , DPT_NONE , BET_NONE , fEntitySize , penmhDestroyed -> m_vDamage * 0.3f , FLOAT3D (0 , 0 , 0) , 1.0f , 0.0f); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Spawn (penmhDestroyed , this , MODEL_WOOD , TEXTURE_WOOD , 0 , 0 , 0 , 0 , m_fDebrisSize , +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D (0.5f , 0.2f , 0.5f)); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Spawn (penmhDestroyed , this , MODEL_WOOD , TEXTURE_WOOD , 0 , 0 , 0 , 1 , m_fDebrisSize , +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D (0.5f , 0.3f , 0.5f)); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Spawn (penmhDestroyed , this , MODEL_WOOD , TEXTURE_WOOD , 0 , 0 , 0 , 2 , m_fDebrisSize , +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D (0.5f , 0.4f , 0.5f)); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Spawn (penmhDestroyed , this , MODEL_WOOD , TEXTURE_WOOD , 0 , 0 , 0 , 3 , m_fDebrisSize , +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D (0.5f , 0.5f , 0.5f)); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Spawn (penmhDestroyed , this , MODEL_WOOD , TEXTURE_WOOD , 0 , 0 , 0 , 1 , m_fDebrisSize , +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D (0.5f , 0.6f , 0.5f)); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Spawn (penmhDestroyed , this , MODEL_WOOD , TEXTURE_WOOD , 0 , 0 , 0 , 2 , m_fDebrisSize , +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D (0.5f , 0.8f , 0.5f)); +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Debris_Spawn (penmhDestroyed , this , MODEL_WOOD , TEXTURE_WOOD , 0 , 0 , 0 , 1 , m_fDebrisSize , +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT3D (0.5f , 0.9f , 0.5f)); +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +}break ; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +default :{}break ; +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +}; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +if(m_ctDustFall > 0) +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT fHeight = box . Size () (2); +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT fMinHeight = fHeight * m_fMinDustFallHeightRatio ; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT fMaxHeight = fHeight * m_fMaxDustFallHeightRatio ; +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT fHeightSteep = (fMaxHeight - fMinHeight ) / m_ctDustFall ; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +for(INDEX iDust = 0;iDust < m_ctDustFall ;iDust ++) +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +{ +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +FLOAT fY = fMinHeight + iDust * fHeightSteep ; +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CPlacement3D plDust = penmhDestroyed -> GetPlacement (); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +plDust . pl_PositionVector = plDust . pl_PositionVector + FLOAT3D (0 , fY , 0); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +ESpawnEffect ese ; +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +ese . vStretch = FLOAT3D (m_fDustStretch , m_fDustStretch , m_fDustStretch ); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +ese . vNormal = FLOAT3D (0 , 1 , 0); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +ese . betType = BET_DUST_FALL ; +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CEntityPointer penFX = CreateEntity (plDust , CLASS_BASIC_EFFECT ); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +penFX -> Initialize (ese ); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +} +BOOL CModelDestruction:: +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CModelDestruction_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CModelDestruction::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CheckOneModelTarget (m_penModel0 ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CheckOneModelTarget (m_penModel1 ); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CheckOneModelTarget (m_penModel2 ); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CheckOneModelTarget (m_penModel3 ); +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CheckOneModelTarget (m_penModel4 ); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +InitAsEditorModel (); +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +SetModel (MODEL_MODELDESTRUCTION ); +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +SetModelMainTexture (TEXTURE_MODELDESTRUCTION ); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Return(STATE_CURRENT,EVoid()); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ModelDestruction.es b/Sources/EntitiesMP/ModelDestruction.es new file mode 100644 index 0000000..baea38c --- /dev/null +++ b/Sources/EntitiesMP/ModelDestruction.es @@ -0,0 +1,316 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +217 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/ModelHolder2"; +uses "EntitiesMP/BasicEffects"; +uses "EntitiesMP/Debris"; +uses "EntitiesMP/BloodSpray"; +uses "EntitiesMP/SoundHolder"; + +// event sent to entities in range of model destroy +// (e.g light can turn off) +event ERangeModelDestruction { +}; + +// type of debris +enum DestructionDebrisType { + 1 DDT_STONE "Stone", + 2 DDT_WOOD "Wood", + 3 DDT_PALM "Palm", + 4 DDT_CHILDREN_CUSTOM "Custom (children)", +}; + +class CModelDestruction : CEntity { +name "ModelDestruction"; +thumbnail "Thumbnails\\ModelDestruction.tbn"; +features "HasName", "IsTargetable", "IsImportant"; + +properties: + 1 CTString m_strName "Name" 'N' = "ModelDestruction", + 2 CTString m_strDescription = "", + + 10 CEntityPointer m_penModel0 "Model 0" 'M' COLOR(C_RED|0x80), + 11 CEntityPointer m_penModel1 "Model 1" COLOR(C_RED|0x80), + 12 CEntityPointer m_penModel2 "Model 2" COLOR(C_RED|0x80), + 13 CEntityPointer m_penModel3 "Model 3" COLOR(C_RED|0x80), + 14 CEntityPointer m_penModel4 "Model 4" COLOR(C_RED|0x80), + + 20 FLOAT m_fHealth "Health" 'H' = 50.0f, // health of the model pointing to this + 22 enum DestructionDebrisType m_ddtDebris "Debris" 'D' = DDT_STONE, // type of debris + 23 INDEX m_ctDebris "Debris Count" = 3, + 24 FLOAT m_fDebrisSize "Debris Size" = 1.0f, + 25 enum EntityInfoBodyType m_eibtBodyType "Body Type" = EIBT_ROCK, + 26 enum SprayParticlesType m_sptType "Particle Type" = SPT_NONE, // type of particles + 27 FLOAT m_fParticleSize "Particle Size" 'Z' = 1.0f, // size of particles + 28 BOOL m_bRequireExplosion "Requires Explosion" = FALSE, + 29 FLOAT m_fDebrisLaunchPower "CC: Debris Launch Power" 'L' = 1.0f, // launch power of debris + 30 enum DebrisParticlesType m_dptParticles "CC: Trail particles" = DPT_NONE, + 31 enum BasicEffectType m_betStain "CC: Leave stain" = BET_NONE, + 32 FLOAT m_fLaunchCone "CC: Launch cone" = 45.0f, + 33 FLOAT m_fRndRotH "CC: Rotation heading" = 720.0f, + 34 FLOAT m_fRndRotP "CC: Rotation pitch" = 720.0f, + 35 FLOAT m_fRndRotB "CC: Rotation banking" = 720.0f, + 36 FLOAT m_fParticleLaunchPower "Particle Launch Power" 'P' = 1.0f, // launch power of particles + 37 COLOR m_colParticles "Central Particle Color" 'C' = COLOR(C_WHITE|CT_OPAQUE), + 40 ANIMATION m_iStartAnim "Start anim" = -1, + 41 BOOL m_bDebrisImmaterialASAP "Immaterial ASAP" = TRUE, + + 50 INDEX m_ctDustFall "Dusts Count" = 1, // count of spawned dust falls + 51 FLOAT m_fMinDustFallHeightRatio "Dust Min Height Ratio" = 0.1f, // min ratio of model height for dust + 52 FLOAT m_fMaxDustFallHeightRatio "Dust Max Height Ratio" = 0.6f, // max ratio of model height for dust + 53 FLOAT m_fDustStretch "Dust Stretch" = 1.0f, // dust stretch + 54 FLOAT m_fDebrisDustRandom "Dust Debris Random" = 0.25f, // random for spawning dusts on debris fall + 55 FLOAT m_fDebrisDustStretch "Dust Debris Stretch" = 1.0f, // size of spawned dust + 56 CEntityPointer m_penShake "Shake marker" 'A', + +components: + 1 model MODEL_MODELDESTRUCTION "Models\\Editor\\ModelDestruction.mdl", + 2 texture TEXTURE_MODELDESTRUCTION "Models\\Editor\\ModelDestruction.tex", + 3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + +// ************** WOOD PARTS ************** + 10 model MODEL_WOOD "Models\\Effects\\Debris\\Wood01\\Wood.mdl", + 11 texture TEXTURE_WOOD "Models\\Effects\\Debris\\Wood01\\Wood.tex", + + 12 model MODEL_BRANCH "ModelsMP\\Effects\\Debris\\Tree\\Tree.mdl", + 13 texture TEXTURE_BRANCH "ModelsMP\\Plants\\Tree01\\Tree01.tex", + +// ************** STONE PARTS ************** + 14 model MODEL_STONE "Models\\Effects\\Debris\\Stone\\Stone.mdl", + 15 texture TEXTURE_STONE "Models\\Effects\\Debris\\Stone\\Stone.tex", + +functions: + void Precache(void) { + PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); + switch(m_ddtDebris) { + case DDT_STONE: { + PrecacheModel(MODEL_STONE); + PrecacheTexture(TEXTURE_STONE); + } break; + case DDT_WOOD: { + PrecacheModel(MODEL_WOOD); + PrecacheTexture(TEXTURE_WOOD); + } break; + case DDT_PALM: { + PrecacheModel(MODEL_WOOD); + PrecacheTexture(TEXTURE_WOOD); + } break; + } + }; + + /* Get anim data for given animation property - return NULL for none. */ + CAnimData *GetAnimData(SLONG slPropertyOffset) + { + if(slPropertyOffset==offsetof(CModelDestruction, m_iStartAnim)) + { + CModelHolder2 *pmh=GetModel(0); + if(pmh!=NULL) + { + return pmh->GetModelObject()->GetData(); + } + } + return CEntity::GetAnimData(slPropertyOffset); + } + + const CTString &GetDescription(void) const { + INDEX ct = GetModelsCount(); + if(ct==0) { + ((CTString&)m_strDescription).PrintF("(%g): no more", m_fHealth); + } else if(ct==1) { + ((CTString&)m_strDescription).PrintF("(%g): %s", m_fHealth, m_penModel0->GetName()); + } else if (TRUE) { + ((CTString&)m_strDescription).PrintF("(%g): %s,...(%d)", m_fHealth, m_penModel0->GetName(), ct); + } + return m_strDescription; + } + + // check if one model target is valid + void CheckOneModelTarget(CEntityPointer &pen) + { + if (pen!=NULL && !IsOfClass(pen, "ModelHolder2")) { + WarningMessage("Model '%s' is not ModelHolder2!", pen->GetName()); + pen=NULL; + } + } + + // get next phase in destruction + class CModelHolder2 *GetNextPhase(void) + { + INDEX ct = GetModelsCount(); + // if not more models + if (ct==0) { + // return none + return NULL; + // if there are some + } else { + // choose by random + return GetModel(IRnd()%ct); + } + } + + // get number of models set by user + INDEX GetModelsCount(void) const + { + // note: only first N that are no NULL are used + if (m_penModel0==NULL) { return 0; }; + if (m_penModel1==NULL) { return 1; }; + if (m_penModel2==NULL) { return 2; }; + if (m_penModel3==NULL) { return 3; }; + if (m_penModel4==NULL) { return 4; }; + return 5; + } + // get model by its index + class CModelHolder2 *GetModel(INDEX iModel) + { + ASSERT(iModel<=GetModelsCount()); + iModel = Clamp(iModel, INDEX(0), GetModelsCount()); + return (CModelHolder2 *)&*(&m_penModel0)[iModel]; + } + // spawn debris for given model + void SpawnDebris(CModelHolder2 *penmhDestroyed) + { + FLOATaabbox3D box; + penmhDestroyed->GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm(); + switch(m_ddtDebris) { + case DDT_STONE: { + Debris_Begin(EIBT_ROCK, DPT_NONE, BET_NONE, fEntitySize, FLOAT3D(0,0,0), FLOAT3D(0,0,0), 1.0f, 0.0f); + for(INDEX iDebris = 0; iDebrisGetModelObject()==NULL) + { + continue; + } + CModelObject &moNew=*mhTemplate.GetModelObject(); + CModelObject &moOld=*penmhDestroyed->GetModelObject(); + CPlacement3D plRel=mhTemplate.GetPlacement(); + plRel.AbsoluteToRelative(this->GetPlacement()); + CPlacement3D plLaunch=plRel; + FLOAT3D vStretch=moOld.mo_Stretch; + plLaunch.pl_PositionVector(1)=plLaunch.pl_PositionVector(1)*vStretch(1); + plLaunch.pl_PositionVector(2)=plLaunch.pl_PositionVector(2)*vStretch(2); + plLaunch.pl_PositionVector(3)=plLaunch.pl_PositionVector(3)*vStretch(3); + plLaunch.RelativeToAbsolute(penmhDestroyed->GetPlacement()); + ANGLE3D angLaunch=ANGLE3D(FRnd()*360.0f,90.0f+m_fLaunchCone*(FRnd()-0.5f),0); + FLOAT3D vLaunchDir; + FLOAT3D vStretchTemplate=FLOAT3D( + moOld.mo_Stretch(1)*moNew.mo_Stretch(1), + moOld.mo_Stretch(2)*moNew.mo_Stretch(2), + moOld.mo_Stretch(3)*moNew.mo_Stretch(3)); + AnglesToDirectionVector(angLaunch, vLaunchDir); + vLaunchDir.Normalize(); + vLaunchDir=vLaunchDir*m_fDebrisLaunchPower; + ANGLE3D angRotSpeed=ANGLE3D(m_fRndRotH*2.0f*(FRnd()-0.5f),m_fRndRotP*(FRnd()-0.5f),m_fRndRotB*(FRnd()-0.5f)); + + FLOAT fDustSize=0.0f; + if( FRnd()m_colBurning); + } + if( IsOfClass(&*iten, "SoundHolder")) + { + CSoundHolder &ensh=(CSoundHolder &)*iten; + // copy it at the placement of destroyed model + CEntity *penNewSH = GetWorld()->CopyEntityInWorld( ensh, penmhDestroyed->GetPlacement()); + penNewSH->SetParent(NULL); + penNewSH->SendEvent(EStart()); + } + } + break; + } + case DDT_PALM: { + Debris_Begin(EIBT_WOOD, DPT_NONE, BET_NONE, fEntitySize, penmhDestroyed->m_vDamage*0.3f, FLOAT3D(0,0,0), 1.0f, 0.0f); + Debris_Spawn(penmhDestroyed, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 0, m_fDebrisSize, + FLOAT3D(0.5f, 0.2f, 0.5f)); + Debris_Spawn(penmhDestroyed, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 1, m_fDebrisSize, + FLOAT3D(0.5f, 0.3f, 0.5f)); + Debris_Spawn(penmhDestroyed, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 2, m_fDebrisSize, + FLOAT3D(0.5f, 0.4f, 0.5f)); + Debris_Spawn(penmhDestroyed, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 3, m_fDebrisSize, + FLOAT3D(0.5f, 0.5f, 0.5f)); + Debris_Spawn(penmhDestroyed, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 1, m_fDebrisSize, + FLOAT3D(0.5f, 0.6f, 0.5f)); + Debris_Spawn(penmhDestroyed, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 2, m_fDebrisSize, + FLOAT3D(0.5f, 0.8f, 0.5f)); + Debris_Spawn(penmhDestroyed, this, MODEL_WOOD, TEXTURE_WOOD, 0, 0, 0, 1, m_fDebrisSize, + FLOAT3D(0.5f, 0.9f, 0.5f)); + } break; + default: {} break; + }; + + if( m_ctDustFall>0) + { + FLOAT fHeight=box.Size()(2); + FLOAT fMinHeight=fHeight*m_fMinDustFallHeightRatio; + FLOAT fMaxHeight=fHeight*m_fMaxDustFallHeightRatio; + FLOAT fHeightSteep=(fMaxHeight-fMinHeight)/m_ctDustFall; + for(INDEX iDust=0; iDustGetPlacement(); + plDust.pl_PositionVector=plDust.pl_PositionVector+FLOAT3D(0,fY,0); + // spawn dust effect + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.vStretch = FLOAT3D(m_fDustStretch,m_fDustStretch,m_fDustStretch); + ese.vNormal = FLOAT3D(0,1,0); + ese.betType = BET_DUST_FALL; + CEntityPointer penFX = CreateEntity(plDust, CLASS_BASIC_EFFECT); + penFX->Initialize(ese); + } + } + } + +procedures: + Main() + { + // must not allow invalid classes + CheckOneModelTarget(m_penModel0); + CheckOneModelTarget(m_penModel1); + CheckOneModelTarget(m_penModel2); + CheckOneModelTarget(m_penModel3); + CheckOneModelTarget(m_penModel4); + + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MODELDESTRUCTION); + SetModelMainTexture(TEXTURE_MODELDESTRUCTION); + + return; + } +}; + diff --git a/Sources/EntitiesMP/ModelDestruction.h b/Sources/EntitiesMP/ModelDestruction.h new file mode 100644 index 0000000..a4748d7 --- /dev/null +++ b/Sources/EntitiesMP/ModelDestruction.h @@ -0,0 +1,96 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ModelDestruction_INCLUDED +#define _EntitiesMP_ModelDestruction_INCLUDED 1 +#include +#include +#include +#include +#include +#define EVENTCODE_ERangeModelDestruction 0x00d90000 +class DECL_DLL ERangeModelDestruction : public CEntityEvent { +public: +ERangeModelDestruction(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(ERangeModelDestruction &e) { e = ERangeModelDestruction(); } ; +extern DECL_DLL CEntityPropertyEnumType DestructionDebrisType_enum; +enum DestructionDebrisType { + DDT_STONE = 1, + DDT_WOOD = 2, + DDT_PALM = 3, + DDT_CHILDREN_CUSTOM = 4, +}; +DECL_DLL inline void ClearToDefault(DestructionDebrisType &e) { e = (DestructionDebrisType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CModelDestruction_DLLClass; +class CModelDestruction : public CEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CEntityPointer m_penModel0; + CEntityPointer m_penModel1; + CEntityPointer m_penModel2; + CEntityPointer m_penModel3; + CEntityPointer m_penModel4; + FLOAT m_fHealth; + enum DestructionDebrisType m_ddtDebris; + INDEX m_ctDebris; + FLOAT m_fDebrisSize; + enum EntityInfoBodyType m_eibtBodyType; + enum SprayParticlesType m_sptType; + FLOAT m_fParticleSize; + BOOL m_bRequireExplosion; + FLOAT m_fDebrisLaunchPower; + enum DebrisParticlesType m_dptParticles; + enum BasicEffectType m_betStain; + FLOAT m_fLaunchCone; + FLOAT m_fRndRotH; + FLOAT m_fRndRotP; + FLOAT m_fRndRotB; + FLOAT m_fParticleLaunchPower; + COLOR m_colParticles; + ANIMATION m_iStartAnim; + BOOL m_bDebrisImmaterialASAP; + INDEX m_ctDustFall; + FLOAT m_fMinDustFallHeightRatio; + FLOAT m_fMaxDustFallHeightRatio; + FLOAT m_fDustStretch; + FLOAT m_fDebrisDustRandom; + FLOAT m_fDebrisDustStretch; + CEntityPointer m_penShake; + +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +void Precache(void); + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +CAnimData * GetAnimData(SLONG slPropertyOffset); + +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +const CTString & GetDescription(void)const; + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +void CheckOneModelTarget(CEntityPointer & pen); + +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +class CModelHolder2 * GetNextPhase(void); + +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +INDEX GetModelsCount(void)const; + +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +class CModelHolder2 * GetModel(INDEX iModel); + +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +void SpawnDebris(CModelHolder2 * penmhDestroyed); +#define STATE_CModelDestruction_Main 1 + BOOL +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ModelDestruction_INCLUDED diff --git a/Sources/EntitiesMP/ModelDestruction_tables.h b/Sources/EntitiesMP/ModelDestruction_tables.h new file mode 100644 index 0000000..da59fa9 --- /dev/null +++ b/Sources/EntitiesMP/ModelDestruction_tables.h @@ -0,0 +1,89 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(DestructionDebrisType) + EP_ENUMVALUE(DDT_STONE, "Stone"), + EP_ENUMVALUE(DDT_WOOD, "Wood"), + EP_ENUMVALUE(DDT_PALM, "Palm"), + EP_ENUMVALUE(DDT_CHILDREN_CUSTOM, "Custom (children)"), +EP_ENUMEND(DestructionDebrisType); + +#define ENTITYCLASS CModelDestruction + +CEntityProperty CModelDestruction_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000d9<<8)+1, offsetof(CModelDestruction, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000d9<<8)+2, offsetof(CModelDestruction, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d9<<8)+10, offsetof(CModelDestruction, m_penModel0), "Model 0", 'M', C_RED | 0x80, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d9<<8)+11, offsetof(CModelDestruction, m_penModel1), "Model 1", 0, C_RED | 0x80, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d9<<8)+12, offsetof(CModelDestruction, m_penModel2), "Model 2", 0, C_RED | 0x80, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d9<<8)+13, offsetof(CModelDestruction, m_penModel3), "Model 3", 0, C_RED | 0x80, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d9<<8)+14, offsetof(CModelDestruction, m_penModel4), "Model 4", 0, C_RED | 0x80, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+20, offsetof(CModelDestruction, m_fHealth), "Health", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DestructionDebrisType_enum, (0x000000d9<<8)+22, offsetof(CModelDestruction, m_ddtDebris), "Debris", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000d9<<8)+23, offsetof(CModelDestruction, m_ctDebris), "Debris Count", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+24, offsetof(CModelDestruction, m_fDebrisSize), "Debris Size", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EntityInfoBodyType_enum, (0x000000d9<<8)+25, offsetof(CModelDestruction, m_eibtBodyType), "Body Type", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &SprayParticlesType_enum, (0x000000d9<<8)+26, offsetof(CModelDestruction, m_sptType), "Particle Type", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+27, offsetof(CModelDestruction, m_fParticleSize), "Particle Size", 'Z', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d9<<8)+28, offsetof(CModelDestruction, m_bRequireExplosion), "Requires Explosion", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+29, offsetof(CModelDestruction, m_fDebrisLaunchPower), "CC: Debris Launch Power", 'L', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DebrisParticlesType_enum, (0x000000d9<<8)+30, offsetof(CModelDestruction, m_dptParticles), "CC: Trail particles", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &BasicEffectType_enum, (0x000000d9<<8)+31, offsetof(CModelDestruction, m_betStain), "CC: Leave stain", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+32, offsetof(CModelDestruction, m_fLaunchCone), "CC: Launch cone", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+33, offsetof(CModelDestruction, m_fRndRotH), "CC: Rotation heading", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+34, offsetof(CModelDestruction, m_fRndRotP), "CC: Rotation pitch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+35, offsetof(CModelDestruction, m_fRndRotB), "CC: Rotation banking", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+36, offsetof(CModelDestruction, m_fParticleLaunchPower), "Particle Launch Power", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d9<<8)+37, offsetof(CModelDestruction, m_colParticles), "Central Particle Color", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000d9<<8)+40, offsetof(CModelDestruction, m_iStartAnim), "Start anim", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d9<<8)+41, offsetof(CModelDestruction, m_bDebrisImmaterialASAP), "Immaterial ASAP", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000d9<<8)+50, offsetof(CModelDestruction, m_ctDustFall), "Dusts Count", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+51, offsetof(CModelDestruction, m_fMinDustFallHeightRatio), "Dust Min Height Ratio", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+52, offsetof(CModelDestruction, m_fMaxDustFallHeightRatio), "Dust Max Height Ratio", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+53, offsetof(CModelDestruction, m_fDustStretch), "Dust Stretch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+54, offsetof(CModelDestruction, m_fDebrisDustRandom), "Dust Debris Random", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d9<<8)+55, offsetof(CModelDestruction, m_fDebrisDustStretch), "Dust Debris Stretch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d9<<8)+56, offsetof(CModelDestruction, m_penShake), "Shake marker", 'A', 0x7F0000FFUL, 0), +}; +#define CModelDestruction_propertiesct ARRAYCOUNT(CModelDestruction_properties) + +CEntityComponent CModelDestruction_components[] = { +#define MODEL_MODELDESTRUCTION ((0x000000d9<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MODELDESTRUCTION, "EFNM" "Models\\Editor\\ModelDestruction.mdl"), +#define TEXTURE_MODELDESTRUCTION ((0x000000d9<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MODELDESTRUCTION, "EFNM" "Models\\Editor\\ModelDestruction.tex"), +#define CLASS_BASIC_EFFECT ((0x000000d9<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define MODEL_WOOD ((0x000000d9<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_WOOD, "EFNM" "Models\\Effects\\Debris\\Wood01\\Wood.mdl"), +#define TEXTURE_WOOD ((0x000000d9<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_WOOD, "EFNM" "Models\\Effects\\Debris\\Wood01\\Wood.tex"), +#define MODEL_BRANCH ((0x000000d9<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_BRANCH, "EFNM" "ModelsMP\\Effects\\Debris\\Tree\\Tree.mdl"), +#define TEXTURE_BRANCH ((0x000000d9<<8)+13) + CEntityComponent(ECT_TEXTURE, TEXTURE_BRANCH, "EFNM" "ModelsMP\\Plants\\Tree01\\Tree01.tex"), +#define MODEL_STONE ((0x000000d9<<8)+14) + CEntityComponent(ECT_MODEL, MODEL_STONE, "EFNM" "Models\\Effects\\Debris\\Stone\\Stone.mdl"), +#define TEXTURE_STONE ((0x000000d9<<8)+15) + CEntityComponent(ECT_TEXTURE, TEXTURE_STONE, "EFNM" "Models\\Effects\\Debris\\Stone\\Stone.tex"), +}; +#define CModelDestruction_componentsct ARRAYCOUNT(CModelDestruction_components) + +CEventHandlerEntry CModelDestruction_handlers[] = { + {1, -1, CEntity::pEventHandler(&CModelDestruction:: +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/ModelDestruction.es" +Main),DEBUGSTRING("CModelDestruction::Main")}, +}; +#define CModelDestruction_handlersct ARRAYCOUNT(CModelDestruction_handlers) + +CEntity *CModelDestruction_New(void) { return new CModelDestruction; }; +void CModelDestruction_OnInitClass(void) {}; +void CModelDestruction_OnEndClass(void) {}; +void CModelDestruction_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CModelDestruction_OnWorldEnd(CWorld *pwo) {}; +void CModelDestruction_OnWorldInit(CWorld *pwo) {}; +void CModelDestruction_OnWorldTick(CWorld *pwo) {}; +void CModelDestruction_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CModelDestruction, CEntity, "ModelDestruction", "Thumbnails\\ModelDestruction.tbn", 0x000000d9); +DECLARE_CTFILENAME(_fnmCModelDestruction_tbn, "Thumbnails\\ModelDestruction.tbn"); diff --git a/Sources/EntitiesMP/ModelHolder.cpp b/Sources/EntitiesMP/ModelHolder.cpp new file mode 100644 index 0000000..3123d88 --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder.cpp @@ -0,0 +1,239 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" + +#include "StdH.h" + +#include +#include +void CModelHolder::SetDefaultProperties(void) { + m_fnModel = CTFILENAME("Models\\Editor\\Axis.mdl"); + m_fnTexture = CTFILENAME("Models\\Editor\\Vector.tex"); + m_fStretchAll = 1.0f; + m_fStretchX = 1.0f; + m_fStretchY = 1.0f; + m_fStretchZ = 1.0f; + m_strName = ""; + m_strDescription = ""; + m_bColliding = FALSE ; + m_iModelAnimation = 0; + m_iTextureAnimation = 0; + m_bClusterShadows = FALSE ; + m_bBackground = FALSE ; + m_bCustomShading = FALSE ; + m_aShadingDirection = ANGLE3D(AngleDeg (45.0f) , AngleDeg (45.0f) , AngleDeg (45.0f)); + m_colLight = C_WHITE ; + m_colAmbient = C_BLACK ; + m_fnmLightAnimation = CTString(""); + m_iLightAnimation = 0; + m_aoLightAnimation.SetData(NULL); + + CEntity::SetDefaultProperties(); +} + +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +CAnimData * CModelHolder::GetAnimData(SLONG slPropertyOffset) +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +{ +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(slPropertyOffset == offsetof (CModelHolder , m_iModelAnimation )){ +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +return GetModelObject () -> GetData (); +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +}else if(slPropertyOffset == offsetof (CModelHolder , m_iTextureAnimation )){ +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +return GetModelObject () -> mo_toTexture . GetData (); +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +}else if(slPropertyOffset == offsetof (CModelHolder , m_iLightAnimation )){ +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +return m_aoLightAnimation . GetData (); +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +}else { +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +return CEntity :: GetAnimData (slPropertyOffset ); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +BOOL CModelHolder::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +{ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_bCustomShading ){ +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +SLONG colFrame0 , colFrame1 ;FLOAT fRatio ; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +m_aoLightAnimation . GetFrame (colFrame0 , colFrame1 , fRatio ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +UBYTE ubAnimR0 , ubAnimG0 , ubAnimB0 ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +UBYTE ubAnimR1 , ubAnimG1 , ubAnimB1 ; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +ColorToRGB (colFrame0 , ubAnimR0 , ubAnimG0 , ubAnimB0 ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +ColorToRGB (colFrame1 , ubAnimR1 , ubAnimG1 , ubAnimB1 ); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +FLOAT fAnimR = NormByteToFloat (Lerp (ubAnimR0 , ubAnimR1 , fRatio )); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +FLOAT fAnimG = NormByteToFloat (Lerp (ubAnimG0 , ubAnimG1 , fRatio )); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +FLOAT fAnimB = NormByteToFloat (Lerp (ubAnimB0 , ubAnimB1 , fRatio )); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +UBYTE ubLightR , ubLightG , ubLightB ; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +UBYTE ubAmbientR , ubAmbientG , ubAmbientB ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +ColorToRGB (m_colLight , ubLightR , ubLightG , ubLightB ); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +ColorToRGB (m_colAmbient , ubAmbientR , ubAmbientG , ubAmbientB ); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +colLight = RGBToColor (ubLightR * fAnimR , ubLightG * fAnimG , ubLightB * fAnimB ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +colAmbient = RGBToColor (ubAmbientR * fAnimR , ubAmbientG * fAnimG , ubAmbientB * fAnimB ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +}else { +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +colLight = m_colLight ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +colAmbient = m_colAmbient ; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +AnglesToDirectionVector (m_aShadingDirection , vLightDirection ); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +vLightDirection = - vLightDirection ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +return TRUE ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} + +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +void CModelHolder::InitModelHolder(void) { +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_fStretchX < 0.01f){m_fStretchX = 0.01f;} +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_fStretchY < 0.01f){m_fStretchY = 0.01f;} +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_fStretchZ < 0.01f){m_fStretchZ = 0.01f;} +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_fStretchAll < 0.01f){m_fStretchAll = 0.01f;} +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_fStretchX > 100.0f){m_fStretchX = 100.0f;} +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_fStretchY > 100.0f){m_fStretchY = 100.0f;} +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_fStretchZ > 100.0f){m_fStretchZ = 100.0f;} +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_fStretchAll > 100.0f){m_fStretchAll = 100.0f;} +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_fnOldModel == ""){ +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +m_fnOldModel = m_fnModel ; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +}else { +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_fnOldModel != m_fnModel ){ +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +m_fnTexture = m_fnModel . FileDir () + m_fnModel . FileName () + CTString (".tex"); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +m_fnOldModel = m_fnModel ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +InitAsModel (); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_bColliding ){ +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +SetPhysicsFlags (EPF_MODEL_FIXED ); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +SetCollisionFlags (ECF_MODEL_HOLDER ); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +}else { +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_bClusterShadows ){ +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +SetFlags (GetFlags () | ENF_CLUSTERSHADOWS ); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +}else { +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +SetFlags (GetFlags () & ~ ENF_CLUSTERSHADOWS ); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_bBackground ){ +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +SetFlags (GetFlags () | ENF_BACKGROUND ); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +}else { +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +SetFlags (GetFlags () & ~ ENF_BACKGROUND ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +GetModelObject () -> mo_Stretch = FLOAT3D ( +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +m_fStretchAll * m_fStretchX , +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +m_fStretchAll * m_fStretchY , +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +m_fStretchAll * m_fStretchZ ); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +SetModel (m_fnModel ); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +SetModelMainTexture (m_fnTexture ); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +GetModelObject () -> PlayAnim (m_iModelAnimation , AOF_LOOPING ); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +GetModelObject () -> mo_toTexture . PlayAnim (m_iTextureAnimation , AOF_LOOPING ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +try { +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +m_aoLightAnimation . SetData_t (m_fnmLightAnimation ); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +}catch (char * strError ){ +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +WarningMessage (TRANS ("Cannot load '%s': %s") , (CTString &) m_fnmLightAnimation , strError ); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +m_fnmLightAnimation = ""; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +m_aoLightAnimation . PlayAnim (m_iLightAnimation , AOF_LOOPING ); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +m_strDescription . PrintF ("%s,%s" , (CTString &) m_fnModel . FileName () , (CTString &) m_fnTexture . FileName ()); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +return ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +} +BOOL CModelHolder:: +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CModelHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CModelHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +InitModelHolder (); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ModelHolder.es b/Sources/EntitiesMP/ModelHolder.es new file mode 100644 index 0000000..7288954 --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder.es @@ -0,0 +1,178 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +203 +%{ +#include "StdH.h" +%} + +class CModelHolder : CEntity { +name "ModelHolder"; +thumbnail ""; +features "HasName", "HasDescription"; + +properties: + 1 CTFileName m_fnModel "Model" 'M' =CTFILENAME("Models\\Editor\\Axis.mdl"), + 2 CTFileName m_fnTexture "Texture" 'T' =CTFILENAME("Models\\Editor\\Vector.tex"), + 3 FLOAT m_fStretchAll "StretchAll" 'S' = 1.0f, + 4 FLOAT m_fStretchX "StretchX" 'X' = 1.0f, + 5 FLOAT m_fStretchY "StretchY" 'Y' = 1.0f, + 6 FLOAT m_fStretchZ "StretchZ" 'Z' = 1.0f, + 7 CTString m_strName "Name" 'N' ="", + 12 CTString m_strDescription = "", + 8 BOOL m_bColliding "Colliding" 'C' = FALSE, // set if model is not immatierial + 9 ANIMATION m_iModelAnimation "Model animation" 'A' = 0, + 10 ANIMATION m_iTextureAnimation "Texture animation" = 0, + 11 BOOL m_bClusterShadows "Cluster shadows" = FALSE, // set if model uses cluster shadows + 13 BOOL m_bBackground "Background" = FALSE, // set if model is rendered in background + + // parameters for custom shading of a model (overrides automatic shading calculation) + 14 BOOL m_bCustomShading "Custom shading" 'H' = FALSE, + 15 ANGLE3D m_aShadingDirection "Light direction" = ANGLE3D( AngleDeg(45.0f),AngleDeg(45.0f),AngleDeg(45.0f)), + 16 COLOR m_colLight "Light color" = C_WHITE, + 17 COLOR m_colAmbient "Ambient color" = C_BLACK, + 18 CTFileName m_fnmLightAnimation "Light animation file" = CTString(""), + 19 ANIMATION m_iLightAnimation "Light animation" = 0, + 20 CAnimObject m_aoLightAnimation, +{ + CTFileName m_fnOldModel; // used for remembering last selected model (not saved at all) +} + +components: + +functions: + /* Get anim data for given animation property - return NULL for none. */ + CAnimData *GetAnimData(SLONG slPropertyOffset) + { + if (slPropertyOffset==offsetof(CModelHolder, m_iModelAnimation)) { + return GetModelObject()->GetData(); + } else if (slPropertyOffset==offsetof(CModelHolder, m_iTextureAnimation)) { + return GetModelObject()->mo_toTexture.GetData(); + } else if (slPropertyOffset==offsetof(CModelHolder, m_iLightAnimation)) { + return m_aoLightAnimation.GetData(); + } else { + return CEntity::GetAnimData(slPropertyOffset); + } + }; + + /* Adjust model shading parameters if needed. */ + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + if (m_bCustomShading) { + // if there is color animation + if (m_aoLightAnimation.GetData()!=NULL) { + // get lerping info + SLONG colFrame0, colFrame1; FLOAT fRatio; + m_aoLightAnimation.GetFrame( colFrame0, colFrame1, fRatio); + UBYTE ubAnimR0, ubAnimG0, ubAnimB0; + UBYTE ubAnimR1, ubAnimG1, ubAnimB1; + ColorToRGB( colFrame0, ubAnimR0, ubAnimG0, ubAnimB0); + ColorToRGB( colFrame1, ubAnimR1, ubAnimG1, ubAnimB1); + + // calculate current animation color + FLOAT fAnimR = NormByteToFloat( Lerp( ubAnimR0, ubAnimR1, fRatio)); + FLOAT fAnimG = NormByteToFloat( Lerp( ubAnimG0, ubAnimG1, fRatio)); + FLOAT fAnimB = NormByteToFloat( Lerp( ubAnimB0, ubAnimB1, fRatio)); + + // decompose constant colors + UBYTE ubLightR, ubLightG, ubLightB; + UBYTE ubAmbientR, ubAmbientG, ubAmbientB; + ColorToRGB( m_colLight, ubLightR, ubLightG, ubLightB); + ColorToRGB( m_colAmbient, ubAmbientR, ubAmbientG, ubAmbientB); + colLight = RGBToColor( ubLightR *fAnimR, ubLightG *fAnimG, ubLightB *fAnimB); + colAmbient = RGBToColor( ubAmbientR*fAnimR, ubAmbientG*fAnimG, ubAmbientB*fAnimB); + + // if there is no color animation + } else { + colLight = m_colLight; + colAmbient = m_colAmbient; + } + + AnglesToDirectionVector(m_aShadingDirection, vLightDirection); + vLightDirection = -vLightDirection; + } + return TRUE; + }; + + /* Init model holder*/ + void InitModelHolder(void) { + // stretch factors must not have extreme values + if (m_fStretchX < 0.01f) { m_fStretchX = 0.01f; } + if (m_fStretchY < 0.01f) { m_fStretchY = 0.01f; } + if (m_fStretchZ < 0.01f) { m_fStretchZ = 0.01f; } + if (m_fStretchAll< 0.01f) { m_fStretchAll = 0.01f; } + if (m_fStretchX >100.0f) { m_fStretchX = 100.0f; } + if (m_fStretchY >100.0f) { m_fStretchY = 100.0f; } + if (m_fStretchZ >100.0f) { m_fStretchZ = 100.0f; } + if (m_fStretchAll>100.0f) { m_fStretchAll = 100.0f; } + + // if initialized for the first time + if (m_fnOldModel=="") { + // just remember the model filename + m_fnOldModel = m_fnModel; + // if re-initialized + } else { + // if the model filename has changed + if (m_fnOldModel != m_fnModel) { + // set texture filename to same as the model filename with texture extension + m_fnTexture = m_fnModel.FileDir()+m_fnModel.FileName()+CTString(".tex"); + // remember the model filename + m_fnOldModel = m_fnModel; + } + } + + InitAsModel(); + if (m_bColliding) { + SetPhysicsFlags(EPF_MODEL_FIXED); + SetCollisionFlags(ECF_MODEL_HOLDER); + } else { + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + } + + if (m_bClusterShadows) { + SetFlags(GetFlags()|ENF_CLUSTERSHADOWS); + } else { + SetFlags(GetFlags()&~ENF_CLUSTERSHADOWS); + } + + if (m_bBackground) { + SetFlags(GetFlags()|ENF_BACKGROUND); + } else { + SetFlags(GetFlags()&~ENF_BACKGROUND); + } + + // set model stretch -- MUST BE DONE BEFORE SETTING MODEL! + GetModelObject()->mo_Stretch = FLOAT3D( + m_fStretchAll*m_fStretchX, + m_fStretchAll*m_fStretchY, + m_fStretchAll*m_fStretchZ); + + // set appearance + SetModel(m_fnModel); + SetModelMainTexture(m_fnTexture); + + GetModelObject()->PlayAnim(m_iModelAnimation, AOF_LOOPING); + GetModelObject()->mo_toTexture.PlayAnim(m_iTextureAnimation, AOF_LOOPING); + + try { + m_aoLightAnimation.SetData_t(m_fnmLightAnimation); + } catch (char *strError) { + WarningMessage(TRANS("Cannot load '%s': %s"), (CTString&)m_fnmLightAnimation, strError); + m_fnmLightAnimation = ""; + } + if (m_aoLightAnimation.GetData()!=NULL) { + m_aoLightAnimation.PlayAnim(m_iLightAnimation, AOF_LOOPING); + } + + m_strDescription.PrintF("%s,%s", (CTString&)m_fnModel.FileName(), (CTString&)m_fnTexture.FileName()); + + return; + }; + +procedures: + Main() + { + InitModelHolder(); + return; + } +}; diff --git a/Sources/EntitiesMP/ModelHolder.h b/Sources/EntitiesMP/ModelHolder.h new file mode 100644 index 0000000..c68b33b --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder.h @@ -0,0 +1,48 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ModelHolder_INCLUDED +#define _EntitiesMP_ModelHolder_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CModelHolder_DLLClass; +class CModelHolder : public CEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual const CTString &GetDescription(void) const { return m_strDescription; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTFileName m_fnModel; + CTFileName m_fnTexture; + FLOAT m_fStretchAll; + FLOAT m_fStretchX; + FLOAT m_fStretchY; + FLOAT m_fStretchZ; + CTString m_strName; + CTString m_strDescription; + BOOL m_bColliding; + ANIMATION m_iModelAnimation; + ANIMATION m_iTextureAnimation; + BOOL m_bClusterShadows; + BOOL m_bBackground; + BOOL m_bCustomShading; + ANGLE3D m_aShadingDirection; + COLOR m_colLight; + COLOR m_colAmbient; + CTFileName m_fnmLightAnimation; + ANIMATION m_iLightAnimation; + CAnimObject m_aoLightAnimation; +CTFileName m_fnOldModel; + +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +CAnimData * GetAnimData(SLONG slPropertyOffset); + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +void InitModelHolder(void); +#define STATE_CModelHolder_Main 1 + BOOL +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ModelHolder_INCLUDED diff --git a/Sources/EntitiesMP/ModelHolder2.cpp b/Sources/EntitiesMP/ModelHolder2.cpp new file mode 100644 index 0000000..f6cd9ce --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder2.cpp @@ -0,0 +1,1132 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" + +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" + +#include +#include +#line 25 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" + +#define MIPRATIO 0.003125f //(2*tan(90/2))/640 + +void CModelHolder2::SetDefaultProperties(void) { + m_fnModel = CTFILENAME("Models\\Editor\\Axis.mdl"); + m_fnTexture = CTFILENAME("Models\\Editor\\Vector.tex"); + m_fnReflection = CTString(""); + m_fnSpecular = CTString(""); + m_fnBump = CTString(""); + m_fStretchAll = 1.0f; + m_fStretchX = 1.0f; + m_fStretchY = 1.0f; + m_fStretchZ = 1.0f; + m_strName = ""; + m_strDescription = ""; + m_bColliding = FALSE ; + m_iModelAnimation = 0; + m_iTextureAnimation = 0; + m_stClusterShadows = ST_CLUSTER ; + m_bBackground = FALSE ; + m_bTargetable = FALSE ; + m_cstCustomShading = CST_NONE ; + m_aShadingDirection = ANGLE3D(AngleDeg (45.0f) , AngleDeg (45.0f) , AngleDeg (45.0f)); + m_colLight = C_WHITE ; + m_colAmbient = C_BLACK ; + m_fnmLightAnimation = CTString(""); + m_iLightAnimation = 0; + m_aoLightAnimation.SetData(NULL); + + m_bAttachments = TRUE ; + m_bActive = TRUE ; + m_fMipAdd = 0.0f; + m_fMipMul = 1.0f; + m_fMipFadeDist = 0.0f; + m_fMipFadeLen = 0.0f; + m_rMipFadeDistMetric = -1.0f; + m_fMipFadeLenMetric = -1.0f; + m_bRandomStretch = FALSE ; + m_fStretchRndX = 0.2f; + m_fStretchRndY = 0.2f; + m_fStretchRndZ = 0.2f; + m_fStretchRndAll = 0.0f; + m_fStretchRandom = FLOAT3D(1 , 1 , 1); + m_penDestruction = NULL; + m_vDamage = FLOAT3D(0 , 0 , 0); + m_tmLastDamage = -1000.0f; + m_penDestroyTarget = NULL; + m_penLastDamager = NULL; + m_tmSpraySpawned = 0.0f; + m_fSprayDamage = 0.0f; + m_penSpray = NULL; + m_fMaxDamageAmmount = 0.0f; + m_fClassificationStretch = 1.0f; + m_colBurning = COLOR(C_WHITE | CT_OPAQUE ); + m_dmtLastDamageType = DMT_CHAINSAW ; + m_fChainSawCutDamage = 300.0f; + m_iFirstRandomAnimation = -1; + m_fMaxTessellationLevel = 0.0f; + CRationalEntity::SetDefaultProperties(); +} + +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void CModelHolder2::Precache(void) { +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +PrecacheClass (CLASS_BLOOD_SPRAY , 0); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +BOOL CModelHolder2::FillEntityStatistics(EntityStats * pes) +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +pes -> es_strName = m_fnModel . FileName () + ", " + m_fnTexture . FileName (); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +pes -> es_ctCount = 1; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +pes -> es_ctAmmount = 1; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_penDestruction != NULL ){ +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +pes -> es_strName += " (destroyable)"; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +pes -> es_fValue = GetDestruction () -> m_fHealth ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +pes -> es_iScore = 0; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +pes -> es_fValue = 0; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +pes -> es_iScore = 0; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return TRUE ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT3D CModelHolder2::GetClassificationBoxStretch(void) +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return FLOAT3D (m_fClassificationStretch , m_fClassificationStretch , m_fClassificationStretch ); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT CModelHolder2::GetMaxTessellationLevel(void) +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return m_fMaxTessellationLevel ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void CModelHolder2::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT fNewDamage = fDamageAmmount ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_penDestruction == NULL ){ +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return ; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(dmtType == DMT_BURNING ) +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +UBYTE ubR , ubG , ubB , ubA ; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ColorToRGBA (m_colBurning , ubR , ubG , ubB , ubA ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ubR = ClampDn (ubR - 4 , 32); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_colBurning = RGBAToColor (ubR , ubR , ubR , ubA ); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +CModelDestruction * penDestruction = GetDestruction (); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +fNewDamage *= DamageStrength (penDestruction -> m_eibtBodyType , dmtType ); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(fNewDamage == 0){ +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return ; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT fKickDamage = fNewDamage ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if((dmtType == DMT_EXPLOSION ) || (dmtType == DMT_IMPACT ) || (dmtType == DMT_CANNONBALL_EXPLOSION )) +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +fKickDamage *= 1.5f; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(dmtType == DMT_CLOSERANGE ){ +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +fKickDamage = 0.0f; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(dmtType == DMT_CHAINSAW ){ +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +fKickDamage = 0.0f; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(dmtType == DMT_BULLET && penDestruction -> m_eibtBodyType == EIBT_ROCK ){ +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +fKickDamage = 0.0f; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(dmtType == DMT_BURNING ) +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +fKickDamage = 0.0f; +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +TIME tmDelta = tmNow - m_tmLastDamage ; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_tmLastDamage = tmNow ; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_penLastDamager = penInflictor ; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(tmDelta >= _pTimer -> TickQuantum * 3){ +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_vDamage = FLOAT3D (0 , 0 , 0); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT3D vDirectionFixed ; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(vDirection . ManhattanNorm () > 0.5f){ +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +vDirectionFixed = vDirection ; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +vDirectionFixed = FLOAT3D (0 , 1 , 0); +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT3D vDamageOld = m_vDamage ; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_vDamage += vDirectionFixed * fKickDamage ; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_vDamage . Length () > GetHealth ()){ +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(! penDestruction -> m_bRequireExplosion || +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +dmtType == DMT_EXPLOSION || dmtType == DMT_CANNONBALL || dmtType == DMT_CANNONBALL_EXPLOSION ) +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +EDeath eDeath ; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SendEvent (eDeath ); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_dmtLastDamageType = dmtType ; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fMaxDamageAmmount < fDamageAmmount ){ +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fMaxDamageAmmount = fDamageAmmount ; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if((dmtType != DMT_BURNING ) && (dmtType != DMT_CHAINSAW ) && +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +(m_tmSpraySpawned <= _pTimer -> CurrentTick () - _pTimer -> TickQuantum * 8 || +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fSprayDamage + fNewDamage > 50.0f)) +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +CPlacement3D plSpray = CPlacement3D (vHitPoint , ANGLE3D (0 , 0 , 0)); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_penSpray -> SetParent (this ); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ESpawnSpray eSpawnSpray ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fMaxDamageAmmount > 10.0f){ +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +eSpawnSpray . fDamagePower = 3.0f; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else if(m_fSprayDamage + fNewDamage > 50.0f){ +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +eSpawnSpray . fDamagePower = 2.0f; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +eSpawnSpray . fDamagePower = 1.0f; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +eSpawnSpray . sptType = penDestruction -> m_sptType ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +eSpawnSpray . fSizeMultiplier = penDestruction -> m_fParticleSize ; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT3D vDn (- en_mRotation (1 , 2) , - en_mRotation (2 , 2) , - en_mRotation (3 , 2)); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT3D vHitPointRelative = vHitPoint - GetPlacement () . pl_PositionVector ; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT3D vReflectingNormal ; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetNormalComponent (vHitPointRelative , vDn , vReflectingNormal ); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +vReflectingNormal . Normalize (); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT3D vProjectedComponent = vReflectingNormal * (vDirection % vReflectingNormal ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT3D vSpilDirection = vDirection - vProjectedComponent * 2.0f - vDn * 0.5f; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +eSpawnSpray . vDirection = vSpilDirection ; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +eSpawnSpray . penOwner = this ; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +eSpawnSpray . colCentralColor = penDestruction -> m_colParticles ; +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +eSpawnSpray . colBurnColor = m_colBurning ; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +eSpawnSpray . fLaunchPower = penDestruction -> m_fParticleLaunchPower ; +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_penSpray -> Initialize (eSpawnSpray ); +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_tmSpraySpawned = _pTimer -> CurrentTick (); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fSprayDamage = 0.0f; +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fMaxDamageAmmount = 0.0f; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(dmtType == DMT_CHAINSAW && m_fChainSawCutDamage > 0) +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fChainSawCutDamage -= fDamageAmmount ; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fChainSawCutDamage <= 0) +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +EDeath eDeath ; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SendEvent (eDeath ); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_dmtLastDamageType = dmtType ; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fSprayDamage += fNewDamage ; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void * CModelHolder2::GetEntityInfo(void) { +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +CModelDestruction * pmd = GetDestruction (); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(pmd != NULL ) +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return GetStdEntityInfo (pmd -> m_eibtBodyType ); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return CEntity :: GetEntityInfo (); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +class CModelDestruction * CModelHolder2::GetDestruction(void) +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ASSERT (m_penDestruction == NULL || IsOfClass (m_penDestruction , "ModelDestruction")); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return (CModelDestruction *) & * m_penDestruction ; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +BOOL CModelHolder2::IsTargetable(void)const +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return m_bTargetable ; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +CAnimData * CModelHolder2::GetAnimData(SLONG slPropertyOffset) +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(slPropertyOffset == offsetof (CModelHolder2 , m_iModelAnimation )){ +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return GetModelObject () -> GetData (); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else if(slPropertyOffset == offsetof (CModelHolder2 , m_iTextureAnimation )){ +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return GetModelObject () -> mo_toTexture . GetData (); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else if(slPropertyOffset == offsetof (CModelHolder2 , m_iLightAnimation )){ +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return m_aoLightAnimation . GetData (); +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return CEntity :: GetAnimData (slPropertyOffset ); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void CModelHolder2::AdjustMipFactor(FLOAT & fMipFactor) +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fMipFadeDist > 0){ +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +CModelObject * pmo = GetModelObject (); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(pmo == NULL ){ +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return ; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT fMipForFade = fMipFactor ; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(fMipForFade > m_fMipFadeDist ){ +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +fMipFactor = UpperLimit (0.0f); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return ; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT fFade = (m_fMipFadeDist - fMipForFade ); +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fMipFadeLen > 0){ +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +fFade /= m_fMipFadeLen ; +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(fFade > 0){ +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +fFade = 1.0f; +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +fFade = Clamp (fFade , 0.0f , 1.0f); +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +pmo -> mo_colBlendColor = (pmo -> mo_colBlendColor & ~ 255) | UBYTE (255 * fFade ); +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +fMipFactor = fMipFactor * m_fMipMul + m_fMipAdd ; +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +BOOL CModelHolder2::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +switch(m_cstCustomShading ) +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +case CST_FULL_CUSTOMIZED : +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SLONG colFrame0 , colFrame1 ;FLOAT fRatio ; +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_aoLightAnimation . GetFrame (colFrame0 , colFrame1 , fRatio ); +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +UBYTE ubAnimR0 , ubAnimG0 , ubAnimB0 ; +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +UBYTE ubAnimR1 , ubAnimG1 , ubAnimB1 ; +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ColorToRGB (colFrame0 , ubAnimR0 , ubAnimG0 , ubAnimB0 ); +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ColorToRGB (colFrame1 , ubAnimR1 , ubAnimG1 , ubAnimB1 ); +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT fAnimR = NormByteToFloat (Lerp (ubAnimR0 , ubAnimR1 , fRatio )); +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT fAnimG = NormByteToFloat (Lerp (ubAnimG0 , ubAnimG1 , fRatio )); +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT fAnimB = NormByteToFloat (Lerp (ubAnimB0 , ubAnimB1 , fRatio )); +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +UBYTE ubLightR , ubLightG , ubLightB ; +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +UBYTE ubAmbientR , ubAmbientG , ubAmbientB ; +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ColorToRGB (m_colLight , ubLightR , ubLightG , ubLightB ); +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ColorToRGB (m_colAmbient , ubAmbientR , ubAmbientG , ubAmbientB ); +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +colLight = RGBToColor (ubLightR * fAnimR , ubLightG * fAnimG , ubLightB * fAnimB ); +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +colAmbient = RGBToColor (ubAmbientR * fAnimR , ubAmbientG * fAnimG , ubAmbientB * fAnimB ); +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +colLight = m_colLight ; +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +colAmbient = m_colAmbient ; +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(pwsc != NULL && pwsc -> m_bApplyShadingToModels ) +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +COLOR colShade = GetWorld () -> wo_atbTextureBlendings [ 9 ] . tb_colMultiply ; +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +colLight = MulColors (colLight , colShade ); +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +colAmbient = MulColors (colAmbient , colShade ); +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +AnglesToDirectionVector (m_aShadingDirection , vLightDirection ); +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +vLightDirection = - vLightDirection ; +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +break ; +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +case CST_CONSTANT_SHADING : +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +UBYTE lR , lG , lB , aR , aG , aB , rR , rG , rB ; +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ColorToRGB (colLight , lR , lG , lB ); +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ColorToRGB (colAmbient , aR , aG , aB ); +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +colLight = 0; +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +rR = (UBYTE ) Clamp ((ULONG ) lR + aR , (ULONG ) 0 , (ULONG ) 255); +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +rG = (UBYTE ) Clamp ((ULONG ) lG + aG , (ULONG ) 0 , (ULONG ) 255); +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +rB = (UBYTE ) Clamp ((ULONG ) lB + aB , (ULONG ) 0 , (ULONG ) 255); +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +colAmbient = RGBToColor (rR , rG , rB ); +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +break ; +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +case CST_NONE : +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +break ; +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_colBurning != COLOR (C_WHITE | CT_OPAQUE )) +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +colAmbient = MulColors (colAmbient , m_colBurning ); +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +colLight = MulColors (colLight , m_colBurning ); +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return TRUE ; +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return m_stClusterShadows != ST_NONE ; +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void CModelHolder2::MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX) +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchAll *= fStretch ; +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(bMirrorX ){ +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchX = - m_fStretchX ; +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void CModelHolder2::StretchModel(void) { +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(Abs (m_fStretchX ) < 0.01f){m_fStretchX = 0.01f;} +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(Abs (m_fStretchY ) < 0.01f){m_fStretchY = 0.01f;} +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(Abs (m_fStretchZ ) < 0.01f){m_fStretchZ = 0.01f;} +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fStretchAll < 0.01f){m_fStretchAll = 0.01f;} +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(Abs (m_fStretchX ) > 1000.0f){m_fStretchX = 1000.0f * Sgn (m_fStretchX );} +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(Abs (m_fStretchY ) > 1000.0f){m_fStretchY = 1000.0f * Sgn (m_fStretchY );} +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(Abs (m_fStretchZ ) > 1000.0f){m_fStretchZ = 1000.0f * Sgn (m_fStretchZ );} +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fStretchAll > 1000.0f){m_fStretchAll = 1000.0f;} +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_bRandomStretch ){ +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_bRandomStretch = FALSE ; +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchRndX = Clamp (m_fStretchRndX , 0.0f , 1.0f); +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchRndY = Clamp (m_fStretchRndY , 0.0f , 1.0f); +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchRndZ = Clamp (m_fStretchRndZ , 0.0f , 1.0f); +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchRndAll = Clamp (m_fStretchRndAll , 0.0f , 1.0f); +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchRandom (1) = (FRnd () * m_fStretchRndX * 2 - m_fStretchRndX ) + 1; +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchRandom (2) = (FRnd () * m_fStretchRndY * 2 - m_fStretchRndY ) + 1; +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchRandom (3) = (FRnd () * m_fStretchRndZ * 2 - m_fStretchRndZ ) + 1; +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT fRNDAll = (FRnd () * m_fStretchRndAll * 2 - m_fStretchRndAll ) + 1; +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchRandom (1) *= fRNDAll ; +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchRandom (2) *= fRNDAll ; +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchRandom (3) *= fRNDAll ; +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> StretchModel (FLOAT3D ( +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchAll * m_fStretchX * m_fStretchRandom (1) , +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchAll * m_fStretchY * m_fStretchRandom (2) , +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fStretchAll * m_fStretchZ * m_fStretchRandom (3))); +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ModelChangeNotify (); +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void CModelHolder2::InitModelHolder(void) { +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fnModel == ""){ +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fnModel = CTFILENAME ("Models\\Editor\\Axis.mdl"); +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fnReflection == CTString ("Models\\Editor\\Vector.tex")){ +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fnReflection = CTString (""); +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fnSpecular == CTString ("Models\\Editor\\Vector.tex")){ +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fnSpecular = CTString (""); +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fnBump == CTString ("Models\\Editor\\Vector.tex")){ +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fnBump = CTString (""); +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_bActive ){ +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +InitAsModel (); +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +InitAsEditorModel (); +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetModel (m_fnModel ); +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +INDEX iAnim = m_iModelAnimation ; +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT tmOffsetPhase = 0.0f; +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_iFirstRandomAnimation >= 0) +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +INDEX ctAnims = GetModelObject () -> GetAnimsCt () - m_iFirstRandomAnimation ; +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +iAnim = m_iFirstRandomAnimation + Clamp (INDEX (FRnd () * ctAnims ) , INDEX (0) , ctAnims ); +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +tmOffsetPhase = FRnd () * 10.0f; +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> PlayAnim (iAnim , AOF_LOOPING ); +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> OffsetPhase (tmOffsetPhase ); +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fnOldModel == ""){ +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fnOldModel = m_fnModel ; +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fnOldModel != m_fnModel ){ +#line 534 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fnOldModel = m_fnModel ; +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> AutoSetTextures (); +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fnTexture = GetModelObject () -> mo_toTexture . GetName (); +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fnReflection = GetModelObject () -> mo_toReflection . GetName (); +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fnSpecular = GetModelObject () -> mo_toSpecular . GetName (); +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fnBump = GetModelObject () -> mo_toBump . GetName (); +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_bAttachments ) +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> AutoSetAttachments (); +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +else +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> RemoveAllAttachmentModels (); +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +try +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> mo_toTexture . SetData_t (m_fnTexture ); +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> mo_toTexture . PlayAnim (m_iTextureAnimation , AOF_LOOPING ); +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> mo_toReflection . SetData_t (m_fnReflection ); +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> mo_toSpecular . SetData_t (m_fnSpecular ); +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> mo_toBump . SetData_t (m_fnBump ); +#line 559 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}catch (char * strError ){ +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +WarningMessage (strError ); +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +StretchModel (); +#line 565 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +ModelChangeNotify (); +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_bColliding && m_bActive ){ +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetPhysicsFlags (EPF_MODEL_FIXED ); +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetCollisionFlags (ECF_MODEL_HOLDER ); +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 573 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +switch(m_stClusterShadows ){ +#line 576 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +case ST_NONE : +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetFlags (GetFlags () & ~ ENF_CLUSTERSHADOWS ); +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +break ; +#line 581 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +case ST_CLUSTER : +#line 583 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 584 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetFlags (GetFlags () | ENF_CLUSTERSHADOWS ); +#line 586 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +break ; +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +case ST_POLYGONAL : +#line 589 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetFlags (GetFlags () & ~ ENF_CLUSTERSHADOWS ); +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +break ; +#line 593 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_bBackground ){ +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetFlags (GetFlags () | ENF_BACKGROUND ); +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 599 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetFlags (GetFlags () & ~ ENF_BACKGROUND ); +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +try { +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_aoLightAnimation . SetData_t (m_fnmLightAnimation ); +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}catch (char * strError ){ +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +WarningMessage (TRANS ("Cannot load '%s': %s") , (CTString &) m_fnmLightAnimation , strError ); +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fnmLightAnimation = ""; +#line 607 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 609 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_aoLightAnimation . PlayAnim (m_iLightAnimation , AOF_LOOPING ); +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_penDestruction == NULL ){ +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_strDescription . PrintF ("%s,%s undestroyable" , (CTString &) m_fnModel . FileName () , (CTString &) m_fnTexture . FileName ()); +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_strDescription . PrintF ("%s,%s -> %s" , (CTString &) m_fnModel . FileName () , (CTString &) m_fnTexture . FileName () , +#line 616 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_penDestruction -> GetName ()); +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return ; +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} + +#line 624 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SLONG CModelHolder2::GetUsedMemory(void) +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 627 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SLONG slUsedMemory = sizeof (CLight ) - sizeof (CRationalEntity ) + CRationalEntity :: GetUsedMemory (); +#line 629 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +slUsedMemory += m_fnModel . Length (); +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +slUsedMemory += m_fnTexture . Length (); +#line 631 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +slUsedMemory += m_fnReflection . Length (); +#line 632 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +slUsedMemory += m_fnSpecular . Length (); +#line 633 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +slUsedMemory += m_fnBump . Length (); +#line 634 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +slUsedMemory += m_strName . Length (); +#line 635 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +slUsedMemory += m_strDescription . Length (); +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +slUsedMemory += m_fnmLightAnimation . Length (); +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +slUsedMemory += 1 * sizeof (CAnimObject); +#line 638 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return slUsedMemory ; +#line 639 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +BOOL CModelHolder2:: +#line 644 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +Die(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CModelHolder2_Die + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CModelHolder2::Die expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , itenChild ){ +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +itenChild -> SendEvent (ERangeModelDestruction ()); +#line 650 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}} +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +CModelDestruction * pmd = GetDestruction (); +#line 654 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +pmd -> SpawnDebris (this ); +#line 656 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +CModelHolder2 * penNext = pmd -> GetNextPhase (); +#line 657 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(penNext != NULL ){ +#line 659 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +CEntity * penNew = GetWorld () -> CopyEntityInWorld (* penNext , GetPlacement ()); +#line 660 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +penNew -> GetModelObject () -> StretchModel (GetModelObject () -> mo_Stretch ); +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +penNew -> ModelChangeNotify (); +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +((CModelHolder2 *) penNew ) -> m_colBurning = m_colBurning ; +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +((CModelHolder2 *) penNew ) -> m_fChainSawCutDamage = m_fChainSawCutDamage ; +#line 665 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(pmd -> m_iStartAnim != - 1) +#line 666 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 667 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +penNew -> GetModelObject () -> PlayAnim (pmd -> m_iStartAnim , 0); +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 671 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +CModelHolder2 & mhNew = * ((CModelHolder2 *) penNew ); +#line 672 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +mhNew . m_cstCustomShading = m_cstCustomShading ; +#line 673 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +mhNew . m_colLight = m_colLight ; +#line 674 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +mhNew . m_colAmbient = m_colAmbient ; +#line 675 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +mhNew . m_fMipFadeDist = m_fMipFadeDist ; +#line 676 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +mhNew . m_fMipFadeLen = m_fMipFadeLen ; +#line 677 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +mhNew . m_fMipAdd = m_fMipAdd ; +#line 678 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +mhNew . m_fMipMul = m_fMipMul ; +#line 681 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_dmtLastDamageType == DMT_CHAINSAW ) +#line 682 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{ +#line 683 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +EDeath eDeath ; +#line 684 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +mhNew . m_fChainSawCutDamage = 0.0f; +#line 685 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +mhNew . m_dmtLastDamageType = DMT_CHAINSAW ; +#line 686 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +penNew -> SendEvent (eDeath ); +#line 687 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 688 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 700 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_penDestroyTarget != NULL ){ +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SendToTarget (m_penDestroyTarget , EET_TRIGGER , m_penLastDamager ); +#line 703 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 706 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +Destroy (); +#line 707 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +Return(STATE_CURRENT,EVoid()); +#line 707 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CModelHolder2:: +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CModelHolder2_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CModelHolder2::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 712 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +InitModelHolder (); +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_fMipFadeLenMetric > m_rMipFadeDistMetric ){m_fMipFadeLenMetric = m_rMipFadeDistMetric ;} +#line 738 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_rMipFadeDistMetric > 0.0f){ +#line 739 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fMipFadeDist = Log2 (m_rMipFadeDistMetric * 1024.0f * MIPRATIO ); +#line 740 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fMipFadeLen = Log2 ((m_rMipFadeDistMetric + m_fMipFadeLenMetric ) * 1024.0f * MIPRATIO ) - m_fMipFadeDist ; +#line 741 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}else { +#line 742 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fMipFadeDist = 0.0f; +#line 743 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_fMipFadeLen = 0.0f; +#line 744 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 748 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_penDestruction != NULL && ! IsOfClass (m_penDestruction , "ModelDestruction")){ +#line 749 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +WarningMessage ("Destruction '%s' is wrong class!" , m_penDestruction -> GetName ()); +#line 750 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_penDestruction = NULL ; +#line 751 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 754 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00d20001, FALSE, EBegin());return TRUE;}BOOL CModelHolder2::H0x00d20001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d20001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 758 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_penDestruction != NULL ){ +#line 759 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetHealth (GetDestruction () -> m_fHealth ); +#line 760 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 761 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return TRUE; +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}ASSERT(FALSE);break;case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 765 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SwitchToModel (); +#line 766 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_bActive = TRUE ; +#line 767 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_bColliding ){ +#line 768 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetPhysicsFlags (EPF_MODEL_FIXED ); +#line 769 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetCollisionFlags (ECF_MODEL_HOLDER ); +#line 770 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 771 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return TRUE; +#line 772 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 774 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SwitchToEditorModel (); +#line 775 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 776 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 777 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_bActive = FALSE ; +#line 778 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 779 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 780 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return TRUE; +#line 781 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}ASSERT(FALSE);break;case(EVENTCODE_ERangeModelDestruction):{const ERangeModelDestruction&e= (ERangeModelDestruction&)__eeInput; + +#line 785 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +{FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , itenChild ){ +#line 787 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +itenChild -> SendEvent (ERangeModelDestruction ()); +#line 788 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}} +#line 790 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +Destroy (); +#line 791 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return TRUE; +#line 792 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; + +#line 795 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_penDestruction != NULL ){ +#line 796 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +Jump(STATE_CURRENT, STATE_CModelHolder2_Die, TRUE, EVoid());return TRUE; +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 798 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return TRUE; +#line 799 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}ASSERT(FALSE);break;case(EVENTCODE_EChangeAnim):{const EChangeAnim&eChange= (EChangeAnim&)__eeInput; + +#line 802 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_iModelAnimation = eChange . iModelAnim ; +#line 803 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_iTextureAnimation = eChange . iTextureAnim ; +#line 804 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_iLightAnimation = eChange . iLightAnim ; +#line 805 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 806 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +m_aoLightAnimation . PlayAnim (m_iLightAnimation , eChange . bLightLoop ? AOF_LOOPING : 0); +#line 807 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 808 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(GetModelObject () -> GetData () != NULL ){ +#line 809 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> PlayAnim (m_iModelAnimation , eChange . bModelLoop ? AOF_LOOPING : 0); +#line 810 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 811 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +if(GetModelObject () -> mo_toTexture . GetData () != NULL ){ +#line 812 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +GetModelObject () -> mo_toTexture . PlayAnim (m_iTextureAnimation , eChange . bTextureLoop ? AOF_LOOPING : 0); +#line 813 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +} +#line 814 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return TRUE; +#line 815 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}ASSERT(FALSE);break;default:{ +#line 817 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +return TRUE; +#line 818 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}ASSERT(FALSE);break; +#line 819 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +}return TRUE;}BOOL CModelHolder2::H0x00d20002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d20002 +; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ModelHolder2.es b/Sources/EntitiesMP/ModelHolder2.es new file mode 100644 index 0000000..d85ef3b --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder2.es @@ -0,0 +1,821 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +210 +%{ +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +%} + +uses "EntitiesMP/ModelDestruction"; +uses "EntitiesMP/AnimationChanger"; +uses "EntitiesMP/BloodSpray"; + +enum CustomShadingType { + 0 CST_NONE "None", + 1 CST_FULL_CUSTOMIZED "Full customized", + 2 CST_CONSTANT_SHADING "Constant shading" +}; + +enum ShadowType { + 0 ST_NONE "None", + 1 ST_CLUSTER "Cluster shadows", + 2 ST_POLYGONAL "Polygonal" +}; + +%{ +#define MIPRATIO 0.003125f //(2*tan(90/2))/640 +%} + +class CModelHolder2 : CRationalEntity { +name "ModelHolder2"; +thumbnail "Thumbnails\\ModelHolder.tbn"; +features "HasName", "HasDescription"; + +properties: + 1 CTFileName m_fnModel "Model" 'M' =CTFILENAME("Models\\Editor\\Axis.mdl"), + 2 CTFileName m_fnTexture "Texture" 'T' =CTFILENAME("Models\\Editor\\Vector.tex"), + 22 CTFileName m_fnReflection "Reflection" =CTString(""), + 23 CTFileName m_fnSpecular "Specular" =CTString(""), + 24 CTFileName m_fnBump "Bump" =CTString(""), + 3 FLOAT m_fStretchAll "StretchAll" 'S' = 1.0f, + 4 FLOAT m_fStretchX "StretchX" 'X' = 1.0f, + 5 FLOAT m_fStretchY "StretchY" 'Y' = 1.0f, + 6 FLOAT m_fStretchZ "StretchZ" 'Z' = 1.0f, + 7 CTString m_strName "Name" 'N' ="", + 12 CTString m_strDescription = "", + 8 BOOL m_bColliding "Colliding" 'L' = FALSE, // set if model is not immatierial + 9 ANIMATION m_iModelAnimation "Model animation" = 0, + 10 ANIMATION m_iTextureAnimation "Texture animation" = 0, + 11 enum ShadowType m_stClusterShadows "Shadows" 'W' = ST_CLUSTER, // set if model uses cluster shadows + 13 BOOL m_bBackground "Background" 'B' = FALSE, // set if model is rendered in background + 21 BOOL m_bTargetable "Targetable" = FALSE, // st if model should be targetable + + // parameters for custom shading of a model (overrides automatic shading calculation) + 14 enum CustomShadingType m_cstCustomShading "Custom shading" 'H' = CST_NONE, + 15 ANGLE3D m_aShadingDirection "Light direction" 'D' = ANGLE3D( AngleDeg(45.0f),AngleDeg(45.0f),AngleDeg(45.0f)), + 16 COLOR m_colLight "Light color" 'O' = C_WHITE, + 17 COLOR m_colAmbient "Ambient color" 'A' = C_BLACK, + 18 CTFileName m_fnmLightAnimation "Light animation file" = CTString(""), + 19 ANIMATION m_iLightAnimation "Light animation" = 0, + 20 CAnimObject m_aoLightAnimation, + 25 BOOL m_bAttachments "Attachments" = TRUE, // set if model should auto load attachments + 26 BOOL m_bActive "Active" = TRUE, + 31 FLOAT m_fMipAdd "Mip Add" = 0.0f, + 32 FLOAT m_fMipMul "Mip Mul" = 1.0f, + //33 FLOAT m_fMipFadeDist "Mip Fade Dist" = 0.0f, + //34 FLOAT m_fMipFadeLen "Mip Fade Len" = 0.0f, + 33 FLOAT m_fMipFadeDist = 0.0f, + 34 FLOAT m_fMipFadeLen = 0.0f, + 35 RANGE m_rMipFadeDistMetric "Mip Fade Dist (Metric)" = -1.0f, + 36 FLOAT m_fMipFadeLenMetric "Mip Fade Len (Metric)" = -1.0f, + + // random values variables + 50 BOOL m_bRandomStretch "Apply RND stretch" = FALSE, // apply random stretch + 52 FLOAT m_fStretchRndX "Stretch RND X (%)" = 0.2f, // random stretch width + 51 FLOAT m_fStretchRndY "Stretch RND Y (%)" = 0.2f, // random stretch height + 53 FLOAT m_fStretchRndZ "Stretch RND Z (%)" = 0.2f, // random stretch depth + 54 FLOAT m_fStretchRndAll "Stretch RND All (%)" = 0.0f, // random stretch all + 55 FLOAT3D m_fStretchRandom = FLOAT3D(1, 1, 1), + + // destruction values + 60 CEntityPointer m_penDestruction "Destruction" 'Q' COLOR(C_BLACK|0x20), // model destruction entity + 61 FLOAT3D m_vDamage = FLOAT3D(0,0,0), // current damage impact + 62 FLOAT m_tmLastDamage = -1000.0f, + 63 CEntityPointer m_penDestroyTarget "Destruction Target" COLOR(C_WHITE|0xFF), // targeted when destroyed + 64 CEntityPointer m_penLastDamager, + 65 FLOAT m_tmSpraySpawned = 0.0f, // time when damage has been applied + 66 FLOAT m_fSprayDamage = 0.0f, // total ammount of damage + 67 CEntityPointer m_penSpray, // the blood spray + 68 FLOAT m_fMaxDamageAmmount = 0.0f, // max ammount of damage recived in in last xxx ticks + + 70 FLOAT m_fClassificationStretch "Classification stretch" = 1.0f, // classification box multiplier + 80 COLOR m_colBurning = COLOR(C_WHITE|CT_OPAQUE), // color applied when burning + + 90 enum DamageType m_dmtLastDamageType=DMT_CHAINSAW, + 91 FLOAT m_fChainSawCutDamage "Chain saw cut dammage" 'C' = 300.0f, + 93 INDEX m_iFirstRandomAnimation "First random animation" 'R' = -1, +100 FLOAT m_fMaxTessellationLevel "Max tessellation level" = 0.0f, + +{ + CTFileName m_fnOldModel; // used for remembering last selected model (not saved at all) +} + +components: + 1 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + +functions: + void Precache(void) { + PrecacheClass(CLASS_BLOOD_SPRAY, 0); + }; + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + pes->es_strName = m_fnModel.FileName()+", "+m_fnTexture.FileName(); + pes->es_ctCount = 1; + pes->es_ctAmmount = 1; + if (m_penDestruction!=NULL) { + pes->es_strName += " (destroyable)"; + pes->es_fValue = GetDestruction()->m_fHealth; + pes->es_iScore = 0; + } else { + pes->es_fValue = 0; + pes->es_iScore = 0; + } + return TRUE; + } + + // classification box multiplier + FLOAT3D GetClassificationBoxStretch(void) + { + return FLOAT3D( m_fClassificationStretch, m_fClassificationStretch, m_fClassificationStretch); + } + + + // maximum allowed tessellation level for this model (for Truform/N-Patches support) + FLOAT GetMaxTessellationLevel(void) + { + return m_fMaxTessellationLevel; + } + + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + FLOAT fNewDamage = fDamageAmmount; + + // if not destroyable + if (m_penDestruction==NULL) { + // do nothing + return; + } + if( dmtType==DMT_BURNING) + { + UBYTE ubR, ubG, ubB, ubA; + ColorToRGBA(m_colBurning, ubR, ubG, ubB, ubA); + ubR=ClampDn(ubR-4, 32); + m_colBurning=RGBAToColor(ubR, ubR, ubR, ubA); + } + + CModelDestruction *penDestruction = GetDestruction(); + // adjust damage + fNewDamage *=DamageStrength(penDestruction->m_eibtBodyType, dmtType); + // if no damage + if (fNewDamage==0) { + // do nothing + return; + } + FLOAT fKickDamage = fNewDamage; + if( (dmtType == DMT_EXPLOSION) || (dmtType == DMT_IMPACT) || (dmtType == DMT_CANNONBALL_EXPLOSION) ) + { + fKickDamage*=1.5f; + } + if (dmtType == DMT_CLOSERANGE) { + fKickDamage=0.0f; + } + if (dmtType == DMT_CHAINSAW) { + fKickDamage=0.0f; + } + if(dmtType == DMT_BULLET && penDestruction->m_eibtBodyType==EIBT_ROCK) { + fKickDamage=0.0f; + } + if( dmtType==DMT_BURNING) + { + fKickDamage=0.0f; + } + + // get passed time since last damage + TIME tmNow = _pTimer->CurrentTick(); + TIME tmDelta = tmNow-m_tmLastDamage; + m_tmLastDamage = tmNow; + + // remember who damaged you + m_penLastDamager = penInflictor; + + // fade damage out + if (tmDelta>=_pTimer->TickQuantum*3) { + m_vDamage=FLOAT3D(0,0,0); + } + // add new damage + FLOAT3D vDirectionFixed; + if (vDirection.ManhattanNorm()>0.5f) { + vDirectionFixed = vDirection; + } else { + vDirectionFixed = FLOAT3D(0,1,0); + } + FLOAT3D vDamageOld = m_vDamage; + m_vDamage += vDirectionFixed*fKickDamage; + + // NOTE: we don't receive damage here, but handle death differently + if (m_vDamage.Length()>GetHealth()) { + if (!penDestruction->m_bRequireExplosion || + dmtType==DMT_EXPLOSION || dmtType==DMT_CANNONBALL || dmtType==DMT_CANNONBALL_EXPLOSION) + { + EDeath eDeath; // we don't need any extra parameters + SendEvent(eDeath); + //remember last dammage type + m_dmtLastDamageType=dmtType; + } + } + + if( m_fMaxDamageAmmountCurrentTick()-_pTimer->TickQuantum*8 || + m_fSprayDamage+fNewDamage>50.0f)) + { + // spawn blood spray + CPlacement3D plSpray = CPlacement3D( vHitPoint, ANGLE3D(0, 0, 0)); + m_penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + m_penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + + // adjust spray power + if( m_fMaxDamageAmmount > 10.0f) { + eSpawnSpray.fDamagePower = 3.0f; + } else if(m_fSprayDamage+fNewDamage>50.0f) { + eSpawnSpray.fDamagePower = 2.0f; + } else { + eSpawnSpray.fDamagePower = 1.0f; + } + + eSpawnSpray.sptType = penDestruction->m_sptType; + eSpawnSpray.fSizeMultiplier = penDestruction->m_fParticleSize; + + // get your down vector (simulates gravity) + FLOAT3D vDn(-en_mRotation(1,2), -en_mRotation(2,2), -en_mRotation(3,2)); + + // setup direction of spray + FLOAT3D vHitPointRelative = vHitPoint - GetPlacement().pl_PositionVector; + FLOAT3D vReflectingNormal; + GetNormalComponent( vHitPointRelative, vDn, vReflectingNormal); + vReflectingNormal.Normalize(); + + FLOAT3D vProjectedComponent = vReflectingNormal*(vDirection%vReflectingNormal); + FLOAT3D vSpilDirection = vDirection-vProjectedComponent*2.0f-vDn*0.5f; + + eSpawnSpray.vDirection = vSpilDirection; + eSpawnSpray.penOwner = this; + eSpawnSpray.colCentralColor=penDestruction->m_colParticles; + eSpawnSpray.colBurnColor=m_colBurning; + eSpawnSpray.fLaunchPower=penDestruction->m_fParticleLaunchPower; + // initialize spray + m_penSpray->Initialize( eSpawnSpray); + m_tmSpraySpawned = _pTimer->CurrentTick(); + m_fSprayDamage = 0.0f; + m_fMaxDamageAmmount = 0.0f; + } + + if( dmtType==DMT_CHAINSAW && m_fChainSawCutDamage>0) + { + m_fChainSawCutDamage-=fDamageAmmount; + if(m_fChainSawCutDamage<=0) + { + EDeath eDeath; // we don't need any extra parameters + SendEvent(eDeath); + //remember last dammage type + m_dmtLastDamageType=dmtType; + } + } + + m_fSprayDamage+=fNewDamage; + }; + + // Entity info + void *GetEntityInfo(void) { + CModelDestruction *pmd=GetDestruction(); + if( pmd!=NULL) + { + return GetStdEntityInfo(pmd->m_eibtBodyType); + } + return CEntity::GetEntityInfo(); + }; + + class CModelDestruction *GetDestruction(void) + { + ASSERT(m_penDestruction==NULL || IsOfClass(m_penDestruction, "ModelDestruction")); + return (CModelDestruction*)&*m_penDestruction; + } + BOOL IsTargetable(void) const + { + return m_bTargetable; + } + + /* Get anim data for given animation property - return NULL for none. */ + CAnimData *GetAnimData(SLONG slPropertyOffset) + { + if (slPropertyOffset==offsetof(CModelHolder2, m_iModelAnimation)) { + return GetModelObject()->GetData(); + } else if (slPropertyOffset==offsetof(CModelHolder2, m_iTextureAnimation)) { + return GetModelObject()->mo_toTexture.GetData(); + } else if (slPropertyOffset==offsetof(CModelHolder2, m_iLightAnimation)) { + return m_aoLightAnimation.GetData(); + } else { + return CEntity::GetAnimData(slPropertyOffset); + } + }; + + /* Adjust model mip factor if needed. */ + void AdjustMipFactor(FLOAT &fMipFactor) + { + // if should fade last mip + if (m_fMipFadeDist>0) { + CModelObject *pmo = GetModelObject(); + if(pmo==NULL) { + return; + } + // adjust for stretch + FLOAT fMipForFade = fMipFactor; + // TODO: comment the next 3 lines for mip factors conversion + /*if (pmo->mo_Stretch != FLOAT3D(1,1,1)) { + fMipForFade -= Log2( Max(pmo->mo_Stretch(1),Max(pmo->mo_Stretch(2),pmo->mo_Stretch(3)))); + }*/ + + // if not visible + if (fMipForFade>m_fMipFadeDist) { + // set mip factor so that model is never rendered + fMipFactor = UpperLimit(0.0f); + return; + } + + // adjust fading + FLOAT fFade = (m_fMipFadeDist-fMipForFade); + if (m_fMipFadeLen>0) { + fFade/=m_fMipFadeLen; + } else { + if (fFade>0) { + fFade = 1.0f; + } + } + + fFade = Clamp(fFade, 0.0f, 1.0f); + // make it invisible + pmo->mo_colBlendColor = (pmo->mo_colBlendColor&~255)|UBYTE(255*fFade); + } + + fMipFactor = fMipFactor*m_fMipMul+m_fMipAdd; + } + + /* Adjust model shading parameters if needed. */ + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + switch( m_cstCustomShading) + { + case CST_FULL_CUSTOMIZED: + { + // if there is color animation + if (m_aoLightAnimation.GetData()!=NULL) { + // get lerping info + SLONG colFrame0, colFrame1; FLOAT fRatio; + m_aoLightAnimation.GetFrame( colFrame0, colFrame1, fRatio); + UBYTE ubAnimR0, ubAnimG0, ubAnimB0; + UBYTE ubAnimR1, ubAnimG1, ubAnimB1; + ColorToRGB( colFrame0, ubAnimR0, ubAnimG0, ubAnimB0); + ColorToRGB( colFrame1, ubAnimR1, ubAnimG1, ubAnimB1); + + // calculate current animation color + FLOAT fAnimR = NormByteToFloat( Lerp( ubAnimR0, ubAnimR1, fRatio)); + FLOAT fAnimG = NormByteToFloat( Lerp( ubAnimG0, ubAnimG1, fRatio)); + FLOAT fAnimB = NormByteToFloat( Lerp( ubAnimB0, ubAnimB1, fRatio)); + + // decompose constant colors + UBYTE ubLightR, ubLightG, ubLightB; + UBYTE ubAmbientR, ubAmbientG, ubAmbientB; + ColorToRGB( m_colLight, ubLightR, ubLightG, ubLightB); + ColorToRGB( m_colAmbient, ubAmbientR, ubAmbientG, ubAmbientB); + colLight = RGBToColor( ubLightR *fAnimR, ubLightG *fAnimG, ubLightB *fAnimB); + colAmbient = RGBToColor( ubAmbientR*fAnimR, ubAmbientG*fAnimG, ubAmbientB*fAnimB); + + // if there is no color animation + } else { + colLight = m_colLight; + colAmbient = m_colAmbient; + } + + // obtain world settings controller + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL && pwsc->m_bApplyShadingToModels) + { + // apply animating shading + COLOR colShade = GetWorld()->wo_atbTextureBlendings[9].tb_colMultiply; + colLight=MulColors(colLight, colShade); + colAmbient=MulColors(colAmbient, colShade); + } + + AnglesToDirectionVector(m_aShadingDirection, vLightDirection); + vLightDirection = -vLightDirection; + break; + } + case CST_CONSTANT_SHADING: + { + // combine colors with clamp + UBYTE lR,lG,lB,aR,aG,aB,rR,rG,rB; + ColorToRGB( colLight, lR, lG, lB); + ColorToRGB( colAmbient, aR, aG, aB); + colLight = 0; + rR = (UBYTE) Clamp( (ULONG)lR+aR, (ULONG)0, (ULONG)255); + rG = (UBYTE) Clamp( (ULONG)lG+aG, (ULONG)0, (ULONG)255); + rB = (UBYTE) Clamp( (ULONG)lB+aB, (ULONG)0, (ULONG)255); + colAmbient = RGBToColor( rR, rG, rB); + break; + } + case CST_NONE: + { + // do nothing + break; + } + } + + if(m_colBurning!=COLOR(C_WHITE|CT_OPAQUE)) + { + colAmbient = MulColors( colAmbient, m_colBurning); + colLight = MulColors( colLight, m_colBurning); + return TRUE; + } + return m_stClusterShadows!=ST_NONE; + }; + + // apply mirror and stretch to the entity + void MirrorAndStretch(FLOAT fStretch, BOOL bMirrorX) + { + m_fStretchAll*=fStretch; + if (bMirrorX) { + m_fStretchX = -m_fStretchX; + } + } + + // Stretch model + void StretchModel(void) { + // stretch factors must not have extreme values + if (Abs(m_fStretchX) < 0.01f) { m_fStretchX = 0.01f; } + if (Abs(m_fStretchY) < 0.01f) { m_fStretchY = 0.01f; } + if (Abs(m_fStretchZ) < 0.01f) { m_fStretchZ = 0.01f; } + if (m_fStretchAll< 0.01f) { m_fStretchAll = 0.01f; } + + if (Abs(m_fStretchX) >1000.0f) { m_fStretchX = 1000.0f*Sgn(m_fStretchX); } + if (Abs(m_fStretchY) >1000.0f) { m_fStretchY = 1000.0f*Sgn(m_fStretchY); } + if (Abs(m_fStretchZ) >1000.0f) { m_fStretchZ = 1000.0f*Sgn(m_fStretchZ); } + if (m_fStretchAll>1000.0f) { m_fStretchAll = 1000.0f; } + + if (m_bRandomStretch) { + m_bRandomStretch = FALSE; + // stretch + m_fStretchRndX = Clamp( m_fStretchRndX , 0.0f, 1.0f); + m_fStretchRndY = Clamp( m_fStretchRndY , 0.0f, 1.0f); + m_fStretchRndZ = Clamp( m_fStretchRndZ , 0.0f, 1.0f); + m_fStretchRndAll = Clamp( m_fStretchRndAll , 0.0f, 1.0f); + + m_fStretchRandom(1) = (FRnd()*m_fStretchRndX*2 - m_fStretchRndX) + 1; + m_fStretchRandom(2) = (FRnd()*m_fStretchRndY*2 - m_fStretchRndY) + 1; + m_fStretchRandom(3) = (FRnd()*m_fStretchRndZ*2 - m_fStretchRndZ) + 1; + + FLOAT fRNDAll = (FRnd()*m_fStretchRndAll*2 - m_fStretchRndAll) + 1; + m_fStretchRandom(1) *= fRNDAll; + m_fStretchRandom(2) *= fRNDAll; + m_fStretchRandom(3) *= fRNDAll; + } + + GetModelObject()->StretchModel( FLOAT3D( + m_fStretchAll*m_fStretchX*m_fStretchRandom(1), + m_fStretchAll*m_fStretchY*m_fStretchRandom(2), + m_fStretchAll*m_fStretchZ*m_fStretchRandom(3)) ); + ModelChangeNotify(); + }; + + /* Init model holder*/ + void InitModelHolder(void) { + + // must not crash when model is removed + if (m_fnModel=="") { + m_fnModel=CTFILENAME("Models\\Editor\\Axis.mdl"); + } + + if( m_fnReflection == CTString("Models\\Editor\\Vector.tex")) { + m_fnReflection = CTString(""); + } + if( m_fnSpecular == CTString("Models\\Editor\\Vector.tex")) { + m_fnSpecular = CTString(""); + } + if( m_fnBump == CTString("Models\\Editor\\Vector.tex")) { + m_fnBump = CTString(""); + } + + if (m_bActive) { + InitAsModel(); + } else { + InitAsEditorModel(); + } + // set appearance + SetModel(m_fnModel); + INDEX iAnim=m_iModelAnimation; + FLOAT tmOffsetPhase=0.0f; + if(m_iFirstRandomAnimation>=0) + { + INDEX ctAnims=GetModelObject()->GetAnimsCt()-m_iFirstRandomAnimation; + iAnim=m_iFirstRandomAnimation+Clamp(INDEX(FRnd()*ctAnims), INDEX(0), ctAnims); + tmOffsetPhase=FRnd()*10.0f; + } + + GetModelObject()->PlayAnim(iAnim, AOF_LOOPING); + GetModelObject()->OffsetPhase(tmOffsetPhase); + + // if initialized for the first time + if (m_fnOldModel=="") { + // just remember the model filename + m_fnOldModel = m_fnModel; + // if re-initialized + } else { + // if the model filename has changed + if (m_fnOldModel != m_fnModel) { + m_fnOldModel = m_fnModel; + GetModelObject()->AutoSetTextures(); + m_fnTexture = GetModelObject()->mo_toTexture.GetName(); + m_fnReflection = GetModelObject()->mo_toReflection.GetName(); + m_fnSpecular = GetModelObject()->mo_toSpecular.GetName(); + m_fnBump = GetModelObject()->mo_toBump.GetName(); + } + } + + if( m_bAttachments) + { + GetModelObject()->AutoSetAttachments(); + } + else + { + GetModelObject()->RemoveAllAttachmentModels(); + } + + try + { + GetModelObject()->mo_toTexture.SetData_t(m_fnTexture); + GetModelObject()->mo_toTexture.PlayAnim(m_iTextureAnimation, AOF_LOOPING); + GetModelObject()->mo_toReflection.SetData_t(m_fnReflection); + GetModelObject()->mo_toSpecular.SetData_t(m_fnSpecular); + GetModelObject()->mo_toBump.SetData_t(m_fnBump); + } catch (char *strError) { + WarningMessage(strError); + } + + // set model stretch + StretchModel(); + ModelChangeNotify(); + + if (m_bColliding&&m_bActive) { + SetPhysicsFlags(EPF_MODEL_FIXED); + SetCollisionFlags(ECF_MODEL_HOLDER); + } else { + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + } + + switch(m_stClusterShadows) { + case ST_NONE: + { + SetFlags(GetFlags()&~ENF_CLUSTERSHADOWS); + //SetFlags(GetFlags()&~ENF_POLYGONALSHADOWS); + break; + } + case ST_CLUSTER: + { + SetFlags(GetFlags()|ENF_CLUSTERSHADOWS); + //SetFlags(GetFlags()&~ENF_POLYGONALSHADOWS); + break; + } + case ST_POLYGONAL: + { + //SetFlags(GetFlags()|ENF_POLYGONALSHADOWS); + SetFlags(GetFlags()&~ENF_CLUSTERSHADOWS); + break; + } + } + + if (m_bBackground) { + SetFlags(GetFlags()|ENF_BACKGROUND); + } else { + SetFlags(GetFlags()&~ENF_BACKGROUND); + } + + try { + m_aoLightAnimation.SetData_t(m_fnmLightAnimation); + } catch (char *strError) { + WarningMessage(TRANS("Cannot load '%s': %s"), (CTString&)m_fnmLightAnimation, strError); + m_fnmLightAnimation = ""; + } + if (m_aoLightAnimation.GetData()!=NULL) { + m_aoLightAnimation.PlayAnim(m_iLightAnimation, AOF_LOOPING); + } + + if (m_penDestruction==NULL) { + m_strDescription.PrintF("%s,%s undestroyable", (CTString&)m_fnModel.FileName(), (CTString&)m_fnTexture.FileName()); + } else { + m_strDescription.PrintF("%s,%s -> %s", (CTString&)m_fnModel.FileName(), (CTString&)m_fnTexture.FileName(), + m_penDestruction->GetName()); + } + + return; + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CLight) - sizeof(CRationalEntity) + CRationalEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_fnModel.Length(); + slUsedMemory += m_fnTexture.Length(); + slUsedMemory += m_fnReflection.Length(); + slUsedMemory += m_fnSpecular.Length(); + slUsedMemory += m_fnBump.Length(); + slUsedMemory += m_strName.Length(); + slUsedMemory += m_strDescription.Length(); + slUsedMemory += m_fnmLightAnimation.Length(); + slUsedMemory += 1* sizeof(CAnimObject); // only 1 + return slUsedMemory; + } + + + +procedures: + Die() + { + // for each child of this entity + {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { + // send it destruction event + itenChild->SendEvent(ERangeModelDestruction()); + }} + + // spawn debris + CModelDestruction *pmd=GetDestruction(); + pmd->SpawnDebris(this); + // if there is another phase in destruction + CModelHolder2 *penNext = pmd->GetNextPhase(); + if (penNext!=NULL) { + // copy it here + CEntity *penNew = GetWorld()->CopyEntityInWorld( *penNext, GetPlacement() ); + penNew->GetModelObject()->StretchModel(GetModelObject()->mo_Stretch); + penNew->ModelChangeNotify(); + ((CModelHolder2 *)penNew)->m_colBurning=m_colBurning; + ((CModelHolder2 *)penNew)->m_fChainSawCutDamage=m_fChainSawCutDamage; + + if( pmd->m_iStartAnim!=-1) + { + penNew->GetModelObject()->PlayAnim(pmd->m_iStartAnim, 0); + } + + // copy custom shading parameters + CModelHolder2 &mhNew=*((CModelHolder2 *)penNew); + mhNew.m_cstCustomShading=m_cstCustomShading; + mhNew.m_colLight=m_colLight; + mhNew.m_colAmbient=m_colAmbient; + mhNew.m_fMipFadeDist = m_fMipFadeDist; + mhNew.m_fMipFadeLen = m_fMipFadeLen; + mhNew.m_fMipAdd = m_fMipAdd; + mhNew.m_fMipMul = m_fMipMul; + + // domino death for cannonball + if( /*m_dmtLastDamageType==DMT_CANNONBALL ||*/ m_dmtLastDamageType==DMT_CHAINSAW) + { + EDeath eDeath; // we don't need any extra parameters + mhNew.m_fChainSawCutDamage=0.0f; + mhNew.m_dmtLastDamageType=DMT_CHAINSAW; + penNew->SendEvent(eDeath); + } + } + +/* currently, environment destruction does not yield score. + update statistics, if score is re-enabled! + // send score to who killed you + if (m_penLastDamager!=NULL) { + EReceiveScore eScore; + eScore.fPoints = 10.0f; + m_penLastDamager->SendEvent(eScore); + }*/ + + // if there is a destruction target + if (m_penDestroyTarget!=NULL) { + // notify it + SendToTarget(m_penDestroyTarget, EET_TRIGGER, m_penLastDamager); + } + + // destroy yourself + Destroy(); + return; + } + Main() + { + // initialize the model + InitModelHolder(); + + // TODO: decomment this AFTER mip factors conversion + if (m_fMipFadeLenMetric>m_rMipFadeDistMetric) { m_fMipFadeLenMetric = m_rMipFadeDistMetric; } + // TODO: decomment this for mip factors conversion + /*if (m_fMipFadeLen<0.0f) { m_fMipFadeLen = 0.0f; } + if (m_fMipFadeDist<0.0f) { m_fMipFadeDist = 0.0f; } + if (m_fMipFadeLen>m_fMipFadeDist) { m_fMipFadeLen = m_fMipFadeDist; } + + // if metric mip values are not initialized, get values from old mip factors + if ( m_fMipFadeDist>0.0f ) { + CModelObject *pmo = GetModelObject(); + if (pmo!=NULL) { + FLOAT fMipSizeFact = Log2( Max(pmo->mo_Stretch(1),Max(pmo->mo_Stretch(2),pmo->mo_Stretch(3)))); + m_rMipFadeDistMetric = pow(2.0f, m_fMipFadeDist+fMipSizeFact)/(1024.0f*MIPRATIO); + m_fMipFadeLenMetric = m_rMipFadeDistMetric - pow(2.0f, m_fMipFadeDist+fMipSizeFact-m_fMipFadeLen)/(1024.0f*MIPRATIO); + } else { + m_rMipFadeDistMetric = 0.0f; + m_fMipFadeLenMetric = 0.0f; + } + } else { + m_rMipFadeDistMetric = 0.0f; + m_fMipFadeLenMetric = 0.0f; + }*/ + + // convert metric factors to mip factors + if (m_rMipFadeDistMetric>0.0f) { + m_fMipFadeDist = Log2(m_rMipFadeDistMetric*1024.0f*MIPRATIO); + m_fMipFadeLen = Log2((m_rMipFadeDistMetric+m_fMipFadeLenMetric)*1024.0f*MIPRATIO) - m_fMipFadeDist; + } else { + m_fMipFadeDist = 0.0f; + m_fMipFadeLen = 0.0f; + } + + + // check your destruction pointer + if (m_penDestruction!=NULL && !IsOfClass(m_penDestruction, "ModelDestruction")) { + WarningMessage("Destruction '%s' is wrong class!", m_penDestruction->GetName()); + m_penDestruction=NULL; + } + + // wait forever + wait() { + // on the beginning + on(EBegin): { + // set your health + if (m_penDestruction!=NULL) { + SetHealth(GetDestruction()->m_fHealth); + } + resume; + } + // activate/deactivate shows/hides model + on (EActivate): { + SwitchToModel(); + m_bActive = TRUE; + if (m_bColliding) { + SetPhysicsFlags(EPF_MODEL_FIXED); + SetCollisionFlags(ECF_MODEL_HOLDER); + } + resume; + } + on (EDeactivate): { + SwitchToEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + m_bActive = FALSE; + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + resume; + } + // when your parent is destroyed + on(ERangeModelDestruction): { + // for each child of this entity + {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { + // send it destruction event + itenChild->SendEvent(ERangeModelDestruction()); + }} + // destroy yourself + Destroy(); + resume; + } + // when dead + on(EDeath): { + if (m_penDestruction!=NULL) { + jump Die(); + } + resume; + } + // when animation should be changed + on(EChangeAnim eChange): { + m_iModelAnimation = eChange.iModelAnim; + m_iTextureAnimation = eChange.iTextureAnim; + m_iLightAnimation = eChange.iLightAnim; + if (m_aoLightAnimation.GetData()!=NULL) { + m_aoLightAnimation.PlayAnim(m_iLightAnimation, eChange.bLightLoop?AOF_LOOPING:0); + } + if (GetModelObject()->GetData()!=NULL) { + GetModelObject()->PlayAnim(m_iModelAnimation, eChange.bModelLoop?AOF_LOOPING:0); + } + if (GetModelObject()->mo_toTexture.GetData()!=NULL) { + GetModelObject()->mo_toTexture.PlayAnim(m_iTextureAnimation, eChange.bTextureLoop?AOF_LOOPING:0); + } + resume; + } + otherwise(): { + resume; + } + }; + } +}; diff --git a/Sources/EntitiesMP/ModelHolder2.h b/Sources/EntitiesMP/ModelHolder2.h new file mode 100644 index 0000000..eda02d7 --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder2.h @@ -0,0 +1,142 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ModelHolder2_INCLUDED +#define _EntitiesMP_ModelHolder2_INCLUDED 1 +#include +#include +#include +extern DECL_DLL CEntityPropertyEnumType CustomShadingType_enum; +enum CustomShadingType { + CST_NONE = 0, + CST_FULL_CUSTOMIZED = 1, + CST_CONSTANT_SHADING = 2, +}; +DECL_DLL inline void ClearToDefault(CustomShadingType &e) { e = (CustomShadingType)0; } ; +extern DECL_DLL CEntityPropertyEnumType ShadowType_enum; +enum ShadowType { + ST_NONE = 0, + ST_CLUSTER = 1, + ST_POLYGONAL = 2, +}; +DECL_DLL inline void ClearToDefault(ShadowType &e) { e = (ShadowType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CModelHolder2_DLLClass; +class CModelHolder2 : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual const CTString &GetDescription(void) const { return m_strDescription; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTFileName m_fnModel; + CTFileName m_fnTexture; + CTFileName m_fnReflection; + CTFileName m_fnSpecular; + CTFileName m_fnBump; + FLOAT m_fStretchAll; + FLOAT m_fStretchX; + FLOAT m_fStretchY; + FLOAT m_fStretchZ; + CTString m_strName; + CTString m_strDescription; + BOOL m_bColliding; + ANIMATION m_iModelAnimation; + ANIMATION m_iTextureAnimation; + enum ShadowType m_stClusterShadows; + BOOL m_bBackground; + BOOL m_bTargetable; + enum CustomShadingType m_cstCustomShading; + ANGLE3D m_aShadingDirection; + COLOR m_colLight; + COLOR m_colAmbient; + CTFileName m_fnmLightAnimation; + ANIMATION m_iLightAnimation; + CAnimObject m_aoLightAnimation; + BOOL m_bAttachments; + BOOL m_bActive; + FLOAT m_fMipAdd; + FLOAT m_fMipMul; + FLOAT m_fMipFadeDist; + FLOAT m_fMipFadeLen; + RANGE m_rMipFadeDistMetric; + FLOAT m_fMipFadeLenMetric; + BOOL m_bRandomStretch; + FLOAT m_fStretchRndX; + FLOAT m_fStretchRndY; + FLOAT m_fStretchRndZ; + FLOAT m_fStretchRndAll; + FLOAT3D m_fStretchRandom; + CEntityPointer m_penDestruction; + FLOAT3D m_vDamage; + FLOAT m_tmLastDamage; + CEntityPointer m_penDestroyTarget; + CEntityPointer m_penLastDamager; + FLOAT m_tmSpraySpawned; + FLOAT m_fSprayDamage; + CEntityPointer m_penSpray; + FLOAT m_fMaxDamageAmmount; + FLOAT m_fClassificationStretch; + COLOR m_colBurning; + enum DamageType m_dmtLastDamageType; + FLOAT m_fChainSawCutDamage; + INDEX m_iFirstRandomAnimation; + FLOAT m_fMaxTessellationLevel; +CTFileName m_fnOldModel; + +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void Precache(void); + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT3D GetClassificationBoxStretch(void); + +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT GetMaxTessellationLevel(void); + +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void * GetEntityInfo(void); + +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +class CModelDestruction * GetDestruction(void); + +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +BOOL IsTargetable(void)const; + +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +CAnimData * GetAnimData(SLONG slPropertyOffset); + +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void AdjustMipFactor(FLOAT & fMipFactor); + +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX); + +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void StretchModel(void); + +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +void InitModelHolder(void); + +#line 624 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +SLONG GetUsedMemory(void); +#define STATE_CModelHolder2_Die 0x00d20000 + BOOL +#line 644 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +Die(const CEntityEvent &__eeInput); +#define STATE_CModelHolder2_Main 1 + BOOL +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00d20001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00d20002_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ModelHolder2_INCLUDED diff --git a/Sources/EntitiesMP/ModelHolder2_tables.h b/Sources/EntitiesMP/ModelHolder2_tables.h new file mode 100644 index 0000000..02fb01f --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder2_tables.h @@ -0,0 +1,103 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(CustomShadingType) + EP_ENUMVALUE(CST_NONE, "None"), + EP_ENUMVALUE(CST_FULL_CUSTOMIZED, "Full customized"), + EP_ENUMVALUE(CST_CONSTANT_SHADING, "Constant shading"), +EP_ENUMEND(CustomShadingType); + +EP_ENUMBEG(ShadowType) + EP_ENUMVALUE(ST_NONE, "None"), + EP_ENUMVALUE(ST_CLUSTER, "Cluster shadows"), + EP_ENUMVALUE(ST_POLYGONAL, "Polygonal"), +EP_ENUMEND(ShadowType); + +#define ENTITYCLASS CModelHolder2 + +CEntityProperty CModelHolder2_properties[] = { + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000d2<<8)+1, offsetof(CModelHolder2, m_fnModel), "Model", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000d2<<8)+2, offsetof(CModelHolder2, m_fnTexture), "Texture", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000d2<<8)+22, offsetof(CModelHolder2, m_fnReflection), "Reflection", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000d2<<8)+23, offsetof(CModelHolder2, m_fnSpecular), "Specular", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000d2<<8)+24, offsetof(CModelHolder2, m_fnBump), "Bump", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+3, offsetof(CModelHolder2, m_fStretchAll), "StretchAll", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+4, offsetof(CModelHolder2, m_fStretchX), "StretchX", 'X', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+5, offsetof(CModelHolder2, m_fStretchY), "StretchY", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+6, offsetof(CModelHolder2, m_fStretchZ), "StretchZ", 'Z', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000d2<<8)+7, offsetof(CModelHolder2, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000d2<<8)+12, offsetof(CModelHolder2, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d2<<8)+8, offsetof(CModelHolder2, m_bColliding), "Colliding", 'L', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000d2<<8)+9, offsetof(CModelHolder2, m_iModelAnimation), "Model animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000d2<<8)+10, offsetof(CModelHolder2, m_iTextureAnimation), "Texture animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &ShadowType_enum, (0x000000d2<<8)+11, offsetof(CModelHolder2, m_stClusterShadows), "Shadows", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d2<<8)+13, offsetof(CModelHolder2, m_bBackground), "Background", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d2<<8)+21, offsetof(CModelHolder2, m_bTargetable), "Targetable", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &CustomShadingType_enum, (0x000000d2<<8)+14, offsetof(CModelHolder2, m_cstCustomShading), "Custom shading", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x000000d2<<8)+15, offsetof(CModelHolder2, m_aShadingDirection), "Light direction", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d2<<8)+16, offsetof(CModelHolder2, m_colLight), "Light color", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d2<<8)+17, offsetof(CModelHolder2, m_colAmbient), "Ambient color", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000d2<<8)+18, offsetof(CModelHolder2, m_fnmLightAnimation), "Light animation file", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000d2<<8)+19, offsetof(CModelHolder2, m_iLightAnimation), "Light animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMOBJECT, NULL, (0x000000d2<<8)+20, offsetof(CModelHolder2, m_aoLightAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d2<<8)+25, offsetof(CModelHolder2, m_bAttachments), "Attachments", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d2<<8)+26, offsetof(CModelHolder2, m_bActive), "Active", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+31, offsetof(CModelHolder2, m_fMipAdd), "Mip Add", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+32, offsetof(CModelHolder2, m_fMipMul), "Mip Mul", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+33, offsetof(CModelHolder2, m_fMipFadeDist), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+34, offsetof(CModelHolder2, m_fMipFadeLen), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x000000d2<<8)+35, offsetof(CModelHolder2, m_rMipFadeDistMetric), "Mip Fade Dist (Metric)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+36, offsetof(CModelHolder2, m_fMipFadeLenMetric), "Mip Fade Len (Metric)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d2<<8)+50, offsetof(CModelHolder2, m_bRandomStretch), "Apply RND stretch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+52, offsetof(CModelHolder2, m_fStretchRndX), "Stretch RND X (%)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+51, offsetof(CModelHolder2, m_fStretchRndY), "Stretch RND Y (%)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+53, offsetof(CModelHolder2, m_fStretchRndZ), "Stretch RND Z (%)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+54, offsetof(CModelHolder2, m_fStretchRndAll), "Stretch RND All (%)", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000000d2<<8)+55, offsetof(CModelHolder2, m_fStretchRandom), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d2<<8)+60, offsetof(CModelHolder2, m_penDestruction), "Destruction", 'Q', C_BLACK | 0x20, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000000d2<<8)+61, offsetof(CModelHolder2, m_vDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+62, offsetof(CModelHolder2, m_tmLastDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d2<<8)+63, offsetof(CModelHolder2, m_penDestroyTarget), "Destruction Target", 0, C_WHITE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d2<<8)+64, offsetof(CModelHolder2, m_penLastDamager), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+65, offsetof(CModelHolder2, m_tmSpraySpawned), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+66, offsetof(CModelHolder2, m_fSprayDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d2<<8)+67, offsetof(CModelHolder2, m_penSpray), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+68, offsetof(CModelHolder2, m_fMaxDamageAmmount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+70, offsetof(CModelHolder2, m_fClassificationStretch), "Classification stretch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000d2<<8)+80, offsetof(CModelHolder2, m_colBurning), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &DamageType_enum, (0x000000d2<<8)+90, offsetof(CModelHolder2, m_dmtLastDamageType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+91, offsetof(CModelHolder2, m_fChainSawCutDamage), "Chain saw cut dammage", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000d2<<8)+93, offsetof(CModelHolder2, m_iFirstRandomAnimation), "First random animation", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000d2<<8)+100, offsetof(CModelHolder2, m_fMaxTessellationLevel), "Max tessellation level", 0, 0x7F0000FFUL, 0), +}; +#define CModelHolder2_propertiesct ARRAYCOUNT(CModelHolder2_properties) + +CEntityComponent CModelHolder2_components[] = { +#define CLASS_BLOOD_SPRAY ((0x000000d2<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +}; +#define CModelHolder2_componentsct ARRAYCOUNT(CModelHolder2_components) + +CEventHandlerEntry CModelHolder2_handlers[] = { + {0x00d20000, -1, CEntity::pEventHandler(&CModelHolder2:: +#line 644 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +Die),DEBUGSTRING("CModelHolder2::Die")}, + {1, -1, CEntity::pEventHandler(&CModelHolder2:: +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder2.es" +Main),DEBUGSTRING("CModelHolder2::Main")}, + {0x00d20001, -1, CEntity::pEventHandler(&CModelHolder2::H0x00d20001_Main_01), DEBUGSTRING("CModelHolder2::H0x00d20001_Main_01")}, + {0x00d20002, -1, CEntity::pEventHandler(&CModelHolder2::H0x00d20002_Main_02), DEBUGSTRING("CModelHolder2::H0x00d20002_Main_02")}, +}; +#define CModelHolder2_handlersct ARRAYCOUNT(CModelHolder2_handlers) + +CEntity *CModelHolder2_New(void) { return new CModelHolder2; }; +void CModelHolder2_OnInitClass(void) {}; +void CModelHolder2_OnEndClass(void) {}; +void CModelHolder2_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CModelHolder2_OnWorldEnd(CWorld *pwo) {}; +void CModelHolder2_OnWorldInit(CWorld *pwo) {}; +void CModelHolder2_OnWorldTick(CWorld *pwo) {}; +void CModelHolder2_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CModelHolder2, CRationalEntity, "ModelHolder2", "Thumbnails\\ModelHolder.tbn", 0x000000d2); +DECLARE_CTFILENAME(_fnmCModelHolder2_tbn, "Thumbnails\\ModelHolder.tbn"); diff --git a/Sources/EntitiesMP/ModelHolder3.cpp b/Sources/EntitiesMP/ModelHolder3.cpp new file mode 100644 index 0000000..f94d5a3 --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder3.cpp @@ -0,0 +1,404 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" + +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" + +#include +#include +#line 25 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" + +// #define MIPRATIO 0.003125f //(2*tan(90/2))/640 + +void CModelHolder3::SetDefaultProperties(void) { + m_fnModel = CTFILENAME(""); + m_fStretchAll = 1.0f; + m_vStretchXYZ = FLOAT3D(1.0f , 1.0f , 1.0f); + m_strName = ""; + m_strDescription = ""; + m_bColliding = FALSE ; + m_stClusterShadows = SST_CLUSTER ; + m_bBackground = FALSE ; + m_bTargetable = FALSE ; + m_cstCustomShading = SCST_NONE ; + m_aShadingDirection = ANGLE3D(AngleDeg (45.0f) , AngleDeg (45.0f) , AngleDeg (45.0f)); + m_colLight = C_WHITE ; + m_colAmbient = C_BLACK ; + m_bActive = TRUE ; + m_fClassificationStretch = 1.0f; + m_fMaxTessellationLevel = 0.0f; + CRationalEntity::SetDefaultProperties(); +} + +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +BOOL CModelHolder3::FillEntityStatistics(EntityStats * pes) +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +pes -> es_strName = m_fnModel . FileName (); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +pes -> es_ctCount = 1; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +pes -> es_ctAmmount = 1; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +pes -> es_fValue = 0; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +pes -> es_iScore = 0; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return TRUE ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} + +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +FLOAT3D CModelHolder3::GetClassificationBoxStretch(void) +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return FLOAT3D (m_fClassificationStretch , m_fClassificationStretch , m_fClassificationStretch ); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} + +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +FLOAT CModelHolder3::GetMaxTessellationLevel(void) +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return m_fMaxTessellationLevel ; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +void CModelHolder3::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} + +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +void * CModelHolder3::GetEntityInfo(void) { +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return CEntity :: GetEntityInfo (); +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} + +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +BOOL CModelHolder3::IsTargetable(void)const +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return m_bTargetable ; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} + +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +BOOL CModelHolder3::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +switch(m_cstCustomShading ) +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +case SCST_FULL_CUSTOMIZED : +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +colLight = m_colLight ; +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +colAmbient = m_colAmbient ; +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +AnglesToDirectionVector (m_aShadingDirection , vLightDirection ); +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +vLightDirection = - vLightDirection ; +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +break ; +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +case SCST_CONSTANT_SHADING : +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +UBYTE lR , lG , lB , aR , aG , aB , rR , rG , rB ; +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +ColorToRGB (colLight , lR , lG , lB ); +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +ColorToRGB (colAmbient , aR , aG , aB ); +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +colLight = 0; +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +rR = (UBYTE ) Clamp ((ULONG ) lR + aR , (ULONG ) 0 , (ULONG ) 255); +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +rG = (UBYTE ) Clamp ((ULONG ) lG + aG , (ULONG ) 0 , (ULONG ) 255); +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +rB = (UBYTE ) Clamp ((ULONG ) lB + aB , (ULONG ) 0 , (ULONG ) 255); +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +colAmbient = RGBToColor (rR , rG , rB ); +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +break ; +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +case SCST_NONE : +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +break ; +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return m_stClusterShadows != SST_NONE ; +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} + +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +void CModelHolder3::MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX) +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +m_fStretchAll *= fStretch ; +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(bMirrorX ){ +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +m_vStretchXYZ (1) = - m_vStretchXYZ (1); +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} + +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +void CModelHolder3::StretchModel(void) { +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(Abs (m_vStretchXYZ (1)) < 0.01f){m_vStretchXYZ (1) = 0.01f;} +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(Abs (m_vStretchXYZ (2)) < 0.01f){m_vStretchXYZ (2) = 0.01f;} +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(Abs (m_vStretchXYZ (3)) < 0.01f){m_vStretchXYZ (3) = 0.01f;} +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(m_fStretchAll < 0.01f){m_fStretchAll = 0.01f;} +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(Abs (m_vStretchXYZ (1)) > 1000.0f){m_vStretchXYZ (1) = 1000.0f * Sgn (m_vStretchXYZ (1));} +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(Abs (m_vStretchXYZ (2)) > 1000.0f){m_vStretchXYZ (2) = 1000.0f * Sgn (m_vStretchXYZ (2));} +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(Abs (m_vStretchXYZ (3)) > 1000.0f){m_vStretchXYZ (3) = 1000.0f * Sgn (m_vStretchXYZ (3));} +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(m_fStretchAll > 1000.0f){m_fStretchAll = 1000.0f;} +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +GetModelInstance () -> StretchModel (m_vStretchXYZ * m_fStretchAll ); +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +ModelChangeNotify (); +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} + +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +void CModelHolder3::InitModelHolder(void) { +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(m_fnModel == ""){ +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +m_fnModel = CTFILENAME ("Models\\Editor\\Ska\\Axis.smc"); +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(m_bActive ){ +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +InitAsSkaModel (); +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}else { +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +InitAsSkaEditorModel (); +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +BOOL bLoadOK = TRUE ; +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +try { +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetSkaModel_t (m_fnModel ); +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}catch (char * strError ){ +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +WarningMessage (TRANS ("Cannot load ska model '%s':\n%s") , (CTString &) m_fnModel , strError ); +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +bLoadOK = FALSE ; +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(! bLoadOK ){ +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetSkaModel (CTFILENAME ("Models\\Editor\\Ska\\Axis.smc")); +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +StretchModel (); +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +ModelChangeNotify (); +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(m_bColliding && m_bActive ){ +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetPhysicsFlags (EPF_MODEL_FIXED ); +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetCollisionFlags (ECF_MODEL_HOLDER ); +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}else { +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +switch(m_stClusterShadows ){ +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +case SST_NONE : +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetFlags (GetFlags () & ~ ENF_CLUSTERSHADOWS ); +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +break ; +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +case SST_CLUSTER : +#line 559 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetFlags (GetFlags () | ENF_CLUSTERSHADOWS ); +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +break ; +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +case SST_POLYGONAL : +#line 565 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{ +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetFlags (GetFlags () & ~ ENF_CLUSTERSHADOWS ); +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +break ; +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(m_bBackground ){ +#line 573 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetFlags (GetFlags () | ENF_BACKGROUND ); +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}else { +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetFlags (GetFlags () & ~ ENF_BACKGROUND ); +#line 576 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 599 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +m_strDescription . PrintF ("%s" , (CTString &) m_fnModel . FileName ()); +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return ; +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +BOOL CModelHolder3:: +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +Die(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CModelHolder3_Die + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CModelHolder3::Die expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , itenChild ){ +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +itenChild -> SendEvent (ERangeModelDestruction ()); +#line 611 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}} +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +Destroy (); +#line 659 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +Return(STATE_CURRENT,EVoid()); +#line 659 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CModelHolder3:: +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CModelHolder3_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CModelHolder3::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 665 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +InitModelHolder (); +#line 684 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00f20001, FALSE, EBegin());return TRUE;}BOOL CModelHolder3::H0x00f20001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f20001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 691 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return TRUE; +#line 692 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}ASSERT(FALSE);break;case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 695 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SwitchToModel (); +#line 696 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +m_bActive = TRUE ; +#line 697 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +if(m_bColliding ){ +#line 698 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetPhysicsFlags (EPF_MODEL_FIXED ); +#line 699 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetCollisionFlags (ECF_MODEL_HOLDER ); +#line 700 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +} +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return TRUE; +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 704 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SwitchToEditorModel (); +#line 705 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 706 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 707 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +m_bActive = FALSE ; +#line 708 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return TRUE; +#line 711 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}ASSERT(FALSE);break;case(EVENTCODE_ERangeModelDestruction):{const ERangeModelDestruction&e= (ERangeModelDestruction&)__eeInput; + +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +{FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , itenChild ){ +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +itenChild -> SendEvent (ERangeModelDestruction ()); +#line 718 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}} +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +Destroy (); +#line 721 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return TRUE; +#line 722 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; + +#line 728 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return TRUE; +#line 729 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}ASSERT(FALSE);break;default:{ +#line 760 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +return TRUE; +#line 761 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}ASSERT(FALSE);break; +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +}return TRUE;}BOOL CModelHolder3::H0x00f20002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00f20002 +; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ModelHolder3.es b/Sources/EntitiesMP/ModelHolder3.es new file mode 100644 index 0000000..56ca2ed --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder3.es @@ -0,0 +1,764 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +242 +%{ +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +%} + +uses "EntitiesMP/ModelDestruction"; +uses "EntitiesMP/AnimationChanger"; +uses "EntitiesMP/BloodSpray"; + +enum SkaCustomShadingType { + 0 SCST_NONE "Automatic shading", + 1 SCST_CONSTANT_SHADING "Constant shading", + 2 SCST_FULL_CUSTOMIZED "Customized shading" +}; + +enum SkaShadowType { + 0 SST_NONE "None", + 1 SST_CLUSTER "Cluster shadows", + 2 SST_POLYGONAL "Polygonal" +}; + +%{ +// #define MIPRATIO 0.003125f //(2*tan(90/2))/640 +%} + +class CModelHolder3 : CRationalEntity { +name "ModelHolder3"; +thumbnail "Thumbnails\\ModelHolder3.tbn"; +features "HasName", "HasDescription"; + +properties: + 1 CTFileName m_fnModel "Model file (.smc)" 'M' = CTFILENAME(""), //("Models\\Editor\\Axis.mdl"), +// 2 CTFileName m_fnTexture "Texture" 'T' =CTFILENAME("Models\\Editor\\Vector.tex"), +// 22 CTFileName m_fnReflection "Reflection" =CTString(""), +// 23 CTFileName m_fnSpecular "Specular" =CTString(""), +// 24 CTFileName m_fnBump "Bump" =CTString(""), + 3 FLOAT m_fStretchAll "StretchAll" 'S' = 1.0f, + 4 ANGLE3D m_vStretchXYZ "StretchXYZ" 'X' = FLOAT3D(1.0f, 1.0f, 1.0f), +// 4 FLOAT m_vStretchXYZ(1) "StretchX" 'X' = 1.0f, +// 5 FLOAT m_vStretchXYZ(2) "StretchY" 'Y' = 1.0f, +// 6 FLOAT m_vStretchXYZ(3) "StretchZ" 'Z' = 1.0f, + 7 CTString m_strName "Name" 'N' ="", + 12 CTString m_strDescription = "", + 8 BOOL m_bColliding "Collision" 'L' = FALSE, // set if model is not immatierial +// 9 ANIMATION m_iModelAnimation "Model animation" = 0, +// 10 ANIMATION m_iTextureAnimation "Texture animation" = 0, + 11 enum SkaShadowType m_stClusterShadows "Shadows" 'W' = SST_CLUSTER, // set if model uses cluster shadows + 13 BOOL m_bBackground "Background" 'B' = FALSE, // set if model is rendered in background + 21 BOOL m_bTargetable "Targetable" = FALSE, // st if model should be targetable + + // parameters for custom shading of a model (overrides automatic shading calculation) + 14 enum SkaCustomShadingType m_cstCustomShading "Shading mode" 'H' = SCST_NONE, + 15 ANGLE3D m_aShadingDirection "Shade. Light direction" 'D' = ANGLE3D( AngleDeg(45.0f),AngleDeg(45.0f),AngleDeg(45.0f)), + 16 COLOR m_colLight "Shade. Light color" 'O' = C_WHITE, + 17 COLOR m_colAmbient "Shade. Ambient color" 'A' = C_BLACK, +// 18 CTFileName m_fnmLightAnimation "Light animation file" = CTString(""), +// 19 ANIMATION m_iLightAnimation "Light animation" = 0, +// 20 CAnimObject m_aoLightAnimation, +// 25 BOOL m_bAttachments "Attachments" = TRUE, // set if model should auto load attachments*/ + 26 BOOL m_bActive "Active" = TRUE, +// 31 FLOAT m_fMipAdd "Mip Add" = 0.0f, +// 32 FLOAT m_fMipMul "Mip Mul" = 1.0f, + //33 FLOAT m_fMipFadeDist "Mip Fade Dist" = 0.0f, + //34 FLOAT m_fMipFadeLen "Mip Fade Len" = 0.0f, +// 33 FLOAT m_fMipFadeDist = 0.0f, +// 34 FLOAT m_fMipFadeLen = 0.0f, +// 35 RANGE m_rMipFadeDistMetric "Mip Fade Dist (Metric)" = -1.0f, +// 36 FLOAT m_fMipFadeLenMetric "Mip Fade Len (Metric)" = -1.0f, + + // random values variables +// 50 BOOL m_bRandomStretch "Apply RND stretch" = FALSE, // apply random stretch +// 52 FLOAT m_fStretchRndX "Stretch RND X (%)" = 0.2f, // random stretch width +// 51 FLOAT m_fStretchRndY "Stretch RND Y (%)" = 0.2f, // random stretch height +// 53 FLOAT m_fStretchRndZ "Stretch RND Z (%)" = 0.2f, // random stretch depth +// 54 FLOAT m_fStretchRndAll "Stretch RND All (%)" = 0.0f, // random stretch all +// 55 FLOAT3D m_fStretchRandom = FLOAT3D(1, 1, 1), + + // destruction values +// 60 CEntityPointer m_penDestruction "Destruction" 'Q' COLOR(C_BLACK|0x20), // model destruction entity +// 61 FLOAT3D m_vDamage = FLOAT3D(0,0,0), // current damage impact +// 62 FLOAT m_tmLastDamage = -1000.0f, +// 63 CEntityPointer m_penDestroyTarget "Destruction Target" COLOR(C_WHITE|0xFF), // targeted when destroyed +// 64 CEntityPointer m_penLastDamager, +// 65 FLOAT m_tmSpraySpawned = 0.0f, // time when damage has been applied +// 66 FLOAT m_fSprayDamage = 0.0f, // total ammount of damage +// 67 CEntityPointer m_penSpray, // the blood spray +// 68 FLOAT m_fMaxDamageAmmount = 0.0f, // max ammount of damage recived in in last xxx ticks + + 70 FLOAT m_fClassificationStretch "Classification stretch" = 1.0f, // classification box multiplier +// 80 COLOR m_colBurning = COLOR(C_WHITE|CT_OPAQUE), // color applied when burning + +// 90 enum DamageType m_dmtLastDamageType=DMT_CHAINSAW, +// 91 FLOAT m_fChainSawCutDamage "Chain saw cut dammage" 'C' = 300.0f, +// 93 INDEX m_iFirstRandomAnimation "First random animation" 'R' = -1, +100 FLOAT m_fMaxTessellationLevel "Max tessellation level" = 0.0f, + +/*201 FLOAT m_tmFadeStart = -1.0f, // time when model starts fading +202 FLOAT m_tmFadeEnd = -1.0f, // time when model stops fading +203 INDEX m_iMinModelOpacity "Faded Min. Alpha" = 32, +205 FLOAT m_fFadeSpeed "Fadeout Speed" = 0.25f, +206 FLOAT m_fFadeEndWait "Fade end delay" = 0.1f, +207 BOOL m_bFadeChildren "Fade Children" = TRUE, +210 BOOL m_bFade "Fade" = TRUE,*/ + +/*{ + CTFileName m_fnOldModel; // used for remembering last selected model (not saved at all) +}*/ + +components: +// 1 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + +functions: +// void Precache(void) { +// PrecacheClass(CLASS_BLOOD_SPRAY, 0); +// }; + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + //pes->es_strName = m_fnModel.FileName()+", "+m_fnTexture.FileName(); + pes->es_strName = m_fnModel.FileName(); + + pes->es_ctCount = 1; + pes->es_ctAmmount = 1; + /*if (m_penDestruction!=NULL) { + pes->es_strName += " (destroyable)"; + pes->es_fValue = GetDestruction()->m_fHealth; + pes->es_iScore = 0; + } else {*/ + pes->es_fValue = 0; + pes->es_iScore = 0; + /*}*/ + return TRUE; + } + + // classification box multiplier + FLOAT3D GetClassificationBoxStretch(void) + { + return FLOAT3D( m_fClassificationStretch, m_fClassificationStretch, m_fClassificationStretch); + } + + + // maximum allowed tessellation level for this model (for Truform/N-Patches support) + FLOAT GetMaxTessellationLevel(void) + { + return m_fMaxTessellationLevel; + } + + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // if not destroyable + /*if (m_penDestruction==NULL) { + // do nothing + return; + } + + FLOAT fNewDamage = fDamageAmmount; + + if( dmtType==DMT_BURNING) + { + UBYTE ubR, ubG, ubB, ubA; + ColorToRGBA(m_colBurning, ubR, ubG, ubB, ubA); + ubR=ClampDn(ubR-4, 32); + m_colBurning=RGBAToColor(ubR, ubR, ubR, ubA); + } + + CModelDestruction *penDestruction = GetDestruction(); + // adjust damage + fNewDamage *=DamageStrength(penDestruction->m_eibtBodyType, dmtType); + // if no damage + if (fNewDamage==0) { + // do nothing + return; + } + FLOAT fKickDamage = fNewDamage; + if( (dmtType == DMT_EXPLOSION) || (dmtType == DMT_IMPACT) || (dmtType == DMT_CANNONBALL_EXPLOSION) ) + { + fKickDamage*=1.5f; + } + if (dmtType == DMT_CLOSERANGE) { + fKickDamage=0.0f; + } + if (dmtType == DMT_CHAINSAW) { + fKickDamage=0.0f; + } + if(dmtType == DMT_BULLET && penDestruction->m_eibtBodyType==EIBT_ROCK) { + fKickDamage=0.0f; + } + if( dmtType==DMT_BURNING) + { + fKickDamage=0.0f; + } + + // get passed time since last damage + TIME tmNow = _pTimer->CurrentTick(); + TIME tmDelta = tmNow-m_tmLastDamage; + m_tmLastDamage = tmNow; + + // remember who damaged you + m_penLastDamager = penInflictor; + + // fade damage out + if (tmDelta>=_pTimer->TickQuantum*3) { + m_vDamage=FLOAT3D(0,0,0); + } + // add new damage + FLOAT3D vDirectionFixed; + if (vDirection.ManhattanNorm()>0.5f) { + vDirectionFixed = vDirection; + } else { + vDirectionFixed = FLOAT3D(0,1,0); + } + FLOAT3D vDamageOld = m_vDamage; + m_vDamage += vDirectionFixed*fKickDamage; + + // NOTE: we don't receive damage here, but handle death differently + if (m_vDamage.Length()>GetHealth()) { + if (!penDestruction->m_bRequireExplosion || + dmtType==DMT_EXPLOSION || dmtType==DMT_CANNONBALL || dmtType==DMT_CANNONBALL_EXPLOSION) + { + EDeath eDeath; // we don't need any extra parameters + SendEvent(eDeath); + //remember last dammage type + m_dmtLastDamageType=dmtType; + } + } + + if( m_fMaxDamageAmmountCurrentTick()-_pTimer->TickQuantum*8 || + m_fSprayDamage+fNewDamage>50.0f)) + { + // spawn blood spray + CPlacement3D plSpray = CPlacement3D( vHitPoint, ANGLE3D(0, 0, 0)); + m_penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + m_penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + + // adjust spray power + if( m_fMaxDamageAmmount > 10.0f) { + eSpawnSpray.fDamagePower = 3.0f; + } else if(m_fSprayDamage+fNewDamage>50.0f) { + eSpawnSpray.fDamagePower = 2.0f; + } else { + eSpawnSpray.fDamagePower = 1.0f; + } + + eSpawnSpray.sptType = penDestruction->m_sptType; + eSpawnSpray.fSizeMultiplier = penDestruction->m_fParticleSize; + + // get your down vector (simulates gravity) + FLOAT3D vDn(-en_mRotation(1,2), -en_mRotation(2,2), -en_mRotation(3,2)); + + // setup direction of spray + FLOAT3D vHitPointRelative = vHitPoint - GetPlacement().pl_PositionVector; + FLOAT3D vReflectingNormal; + GetNormalComponent( vHitPointRelative, vDn, vReflectingNormal); + vReflectingNormal.Normalize(); + + FLOAT3D vProjectedComponent = vReflectingNormal*(vDirection%vReflectingNormal); + FLOAT3D vSpilDirection = vDirection-vProjectedComponent*2.0f-vDn*0.5f; + + eSpawnSpray.vDirection = vSpilDirection; + eSpawnSpray.penOwner = this; + eSpawnSpray.colCentralColor=penDestruction->m_colParticles; + eSpawnSpray.colBurnColor=m_colBurning; + eSpawnSpray.fLaunchPower=penDestruction->m_fParticleLaunchPower; + // initialize spray + m_penSpray->Initialize( eSpawnSpray); + m_tmSpraySpawned = _pTimer->CurrentTick(); + m_fSprayDamage = 0.0f; + m_fMaxDamageAmmount = 0.0f; + } + + if( dmtType==DMT_CHAINSAW && m_fChainSawCutDamage>0) + { + m_fChainSawCutDamage-=fDamageAmmount; + if(m_fChainSawCutDamage<=0) + { + EDeath eDeath; // we don't need any extra parameters + SendEvent(eDeath); + //remember last dammage type + m_dmtLastDamageType=dmtType; + } + } + + m_fSprayDamage+=fNewDamage; + */ + }; + + // Entity info + void *GetEntityInfo(void) { + /*CModelDestruction *pmd=GetDestruction(); + if( pmd!=NULL) + { + return GetStdEntityInfo(pmd->m_eibtBodyType); + }*/ + return CEntity::GetEntityInfo(); + }; + +/* class CModelDestruction *GetDestruction(void) + { + ASSERT(m_penDestruction==NULL || IsOfClass(m_penDestruction, "ModelDestruction")); + return (CModelDestruction*)&*m_penDestruction; + }*/ + + BOOL IsTargetable(void) const + { + return m_bTargetable; + } + + /* Get anim data for given animation property - return NULL for none. */ +/* CAnimData *GetAnimData(SLONG slPropertyOffset) + { + if (slPropertyOffset==offsetof(CModelHolder3, m_iModelAnimation)) { + return GetModelObject()->GetData(); + } else if (slPropertyOffset==offsetof(CModelHolder3, m_iTextureAnimation)) { + return GetModelObject()->mo_toTexture.GetData(); + } else if (slPropertyOffset==offsetof(CModelHolder3, m_iLightAnimation)) { + return m_aoLightAnimation.GetData(); + } else { + return CEntity::GetAnimData(slPropertyOffset); + } + };*/ + + /* Adjust model mip factor if needed. */ +/* void AdjustMipFactor(FLOAT &fMipFactor) + { + // if should fade last mip + if (m_fMipFadeDist>0) { + CModelObject *pmo = GetModelObject(); + if(pmo==NULL) { + return; + } + // adjust for stretch + FLOAT fMipForFade = fMipFactor; + + // if not visible + if (fMipForFade>m_fMipFadeDist) { + // set mip factor so that model is never rendered + fMipFactor = UpperLimit(0.0f); + return; + } + + // adjust fading + FLOAT fFade = (m_fMipFadeDist-fMipForFade); + if (m_fMipFadeLen>0) { + fFade/=m_fMipFadeLen; + } else { + if (fFade>0) { + fFade = 1.0f; + } + } + + fFade = Clamp(fFade, 0.0f, 1.0f); + // make it invisible + pmo->mo_colBlendColor = (pmo->mo_colBlendColor&~255)|UBYTE(255*fFade); + } + + fMipFactor = fMipFactor*m_fMipMul+m_fMipAdd; + }*/ + + /* Adjust model shading parameters if needed. */ + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + switch(m_cstCustomShading) + { + case SCST_FULL_CUSTOMIZED: + { + // if there is color animation + /*if (m_aoLightAnimation.GetData()!=NULL) { + // get lerping info + SLONG colFrame0, colFrame1; FLOAT fRatio; + m_aoLightAnimation.GetFrame( colFrame0, colFrame1, fRatio); + UBYTE ubAnimR0, ubAnimG0, ubAnimB0; + UBYTE ubAnimR1, ubAnimG1, ubAnimB1; + ColorToRGB( colFrame0, ubAnimR0, ubAnimG0, ubAnimB0); + ColorToRGB( colFrame1, ubAnimR1, ubAnimG1, ubAnimB1); + + // calculate current animation color + FLOAT fAnimR = NormByteToFloat( Lerp( ubAnimR0, ubAnimR1, fRatio)); + FLOAT fAnimG = NormByteToFloat( Lerp( ubAnimG0, ubAnimG1, fRatio)); + FLOAT fAnimB = NormByteToFloat( Lerp( ubAnimB0, ubAnimB1, fRatio)); + + // decompose constant colors + UBYTE ubLightR, ubLightG, ubLightB; + UBYTE ubAmbientR, ubAmbientG, ubAmbientB; + ColorToRGB( m_colLight, ubLightR, ubLightG, ubLightB); + ColorToRGB( m_colAmbient, ubAmbientR, ubAmbientG, ubAmbientB); + colLight = RGBToColor( ubLightR *fAnimR, ubLightG *fAnimG, ubLightB *fAnimB); + colAmbient = RGBToColor( ubAmbientR*fAnimR, ubAmbientG*fAnimG, ubAmbientB*fAnimB); + + // if there is no color animation + } else {*/ + colLight = m_colLight; + colAmbient = m_colAmbient; + //} + + // obtain world settings controller + /*CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL && pwsc->m_bApplyShadingToModels) + { + // apply animating shading + COLOR colShade = GetWorld()->wo_atbTextureBlendings[9].tb_colMultiply; + colLight=MulColors(colLight, colShade); + colAmbient=MulColors(colAmbient, colShade); + }*/ + + AnglesToDirectionVector(m_aShadingDirection, vLightDirection); + vLightDirection = -vLightDirection; + break; + } + case SCST_CONSTANT_SHADING: + { + // combine colors with clamp + UBYTE lR,lG,lB,aR,aG,aB,rR,rG,rB; + ColorToRGB( colLight, lR, lG, lB); + ColorToRGB( colAmbient, aR, aG, aB); + colLight = 0; + rR = (UBYTE) Clamp( (ULONG)lR+aR, (ULONG)0, (ULONG)255); + rG = (UBYTE) Clamp( (ULONG)lG+aG, (ULONG)0, (ULONG)255); + rB = (UBYTE) Clamp( (ULONG)lB+aB, (ULONG)0, (ULONG)255); + colAmbient = RGBToColor( rR, rG, rB); + break; + } + case SCST_NONE: + { + // do nothing + break; + } + } + + /* if(m_colBurning!=COLOR(C_WHITE|CT_OPAQUE)) + { + colAmbient = MulColors( colAmbient, m_colBurning); + colLight = MulColors( colLight, m_colBurning); + return TRUE; + }*/ + + return m_stClusterShadows!=SST_NONE; + }; + + // apply mirror and stretch to the entity + void MirrorAndStretch(FLOAT fStretch, BOOL bMirrorX) + { + m_fStretchAll*=fStretch; + if (bMirrorX) { + m_vStretchXYZ(1)=-m_vStretchXYZ(1); + } + } + + +// Stretch model + void StretchModel(void) { + // stretch factors must not have extreme values + if (Abs(m_vStretchXYZ(1)) < 0.01f) { m_vStretchXYZ(1) = 0.01f; } + if (Abs(m_vStretchXYZ(2)) < 0.01f) { m_vStretchXYZ(2) = 0.01f; } + if (Abs(m_vStretchXYZ(3)) < 0.01f) { m_vStretchXYZ(3) = 0.01f; } + if (m_fStretchAll< 0.01f) { m_fStretchAll = 0.01f; } + + if (Abs(m_vStretchXYZ(1)) >1000.0f) { m_vStretchXYZ(1) = 1000.0f*Sgn(m_vStretchXYZ(1)); } + if (Abs(m_vStretchXYZ(2)) >1000.0f) { m_vStretchXYZ(2) = 1000.0f*Sgn(m_vStretchXYZ(2)); } + if (Abs(m_vStretchXYZ(3)) >1000.0f) { m_vStretchXYZ(3) = 1000.0f*Sgn(m_vStretchXYZ(3)); } + if (m_fStretchAll>1000.0f) { m_fStretchAll = 1000.0f; } + +/* if (m_bRandomStretch) { + m_bRandomStretch = FALSE; + // stretch + m_fStretchRndX = Clamp( m_fStretchRndX , 0.0f, 1.0f); + m_fStretchRndY = Clamp( m_fStretchRndY , 0.0f, 1.0f); + m_fStretchRndZ = Clamp( m_fStretchRndZ , 0.0f, 1.0f); + m_fStretchRndAll = Clamp( m_fStretchRndAll , 0.0f, 1.0f); + + m_fStretchRandom(1) = (FRnd()*m_fStretchRndX*2 - m_fStretchRndX) + 1; + m_fStretchRandom(2) = (FRnd()*m_fStretchRndY*2 - m_fStretchRndY) + 1; + m_fStretchRandom(3) = (FRnd()*m_fStretchRndZ*2 - m_fStretchRndZ) + 1; + + FLOAT fRNDAll = (FRnd()*m_fStretchRndAll*2 - m_fStretchRndAll) + 1; + m_fStretchRandom(1) *= fRNDAll; + m_fStretchRandom(2) *= fRNDAll; + m_fStretchRandom(3) *= fRNDAll; + }*/ + + GetModelInstance()->StretchModel( m_vStretchXYZ*m_fStretchAll ); + ModelChangeNotify(); + }; + + + /* Init model holder*/ + void InitModelHolder(void) { + + // must not crash when model is removed + if (m_fnModel=="") { + m_fnModel=CTFILENAME("Models\\Editor\\Ska\\Axis.smc"); + } + + if (m_bActive) { + InitAsSkaModel(); + } else { + InitAsSkaEditorModel(); + } + + BOOL bLoadOK = TRUE; + // try to load the model + try { + SetSkaModel_t(m_fnModel); + // if failed + } catch(char *strError) { + WarningMessage(TRANS("Cannot load ska model '%s':\n%s"), (CTString&)m_fnModel, strError); + bLoadOK = FALSE; + // set colision info for default model + //SetSkaColisionInfo(); + } + if (!bLoadOK) { + SetSkaModel(CTFILENAME("Models\\Editor\\Ska\\Axis.smc")); + } + + /*try + { + GetModelObject()->mo_toTexture.SetData_t(m_fnTexture); + GetModelObject()->mo_toTexture.PlayAnim(m_iTextureAnimation, AOF_LOOPING); + GetModelObject()->mo_toReflection.SetData_t(m_fnReflection); + GetModelObject()->mo_toSpecular.SetData_t(m_fnSpecular); + GetModelObject()->mo_toBump.SetData_t(m_fnBump); + } catch (char *strError) { + WarningMessage(strError); + }*/ + + // set model stretch + StretchModel(); + ModelChangeNotify(); + + if (m_bColliding&&m_bActive) { + SetPhysicsFlags(EPF_MODEL_FIXED); + SetCollisionFlags(ECF_MODEL_HOLDER); + } else { + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + } + + switch(m_stClusterShadows) { + case SST_NONE: + { + SetFlags(GetFlags()&~ENF_CLUSTERSHADOWS); + //SetFlags(GetFlags()&~ENF_POLYGONALSHADOWS); + break; + } + case SST_CLUSTER: + { + SetFlags(GetFlags()|ENF_CLUSTERSHADOWS); + //SetFlags(GetFlags()&~ENF_POLYGONALSHADOWS); + break; + } + case SST_POLYGONAL: + { + //SetFlags(GetFlags()|ENF_POLYGONALSHADOWS); + SetFlags(GetFlags()&~ENF_CLUSTERSHADOWS); + break; + } + } + + if (m_bBackground) { + SetFlags(GetFlags()|ENF_BACKGROUND); + } else { + SetFlags(GetFlags()&~ENF_BACKGROUND); + } + +/* try { + m_aoLightAnimation.SetData_t(m_fnmLightAnimation); + } catch (char *strError) { + WarningMessage(TRANS("Cannot load '%s': %s"), (CTString&)m_fnmLightAnimation, strError); + m_fnmLightAnimation = ""; + } + if (m_aoLightAnimation.GetData()!=NULL) { + m_aoLightAnimation.PlayAnim(m_iLightAnimation, AOF_LOOPING); + } + + if (m_penDestruction==NULL) { + m_strDescription.PrintF("%s,%s undestroyable", (CTString&)m_fnModel.FileName(), (CTString&)m_fnTexture.FileName()); + } else { + m_strDescription.PrintF("%s,%s -> %s", (CTString&)m_fnModel.FileName(), (CTString&)m_fnTexture.FileName(), + m_penDestruction->GetName()); + }*/ + + /*m_iMinModelOpacity = Clamp(m_iMinModelOpacity, (INDEX)0, (INDEX)255); + m_fFadeEndWait = ClampDn(m_fFadeEndWait, 0.05f); + m_fFadeSpeed = ClampDn(m_fFadeSpeed, 0.05f);*/ + + m_strDescription.PrintF("%s", (CTString&)m_fnModel.FileName()); + + return; + }; + +procedures: + Die() + { + // for each child of this entity + {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { + // send it destruction event + itenChild->SendEvent(ERangeModelDestruction()); + }} + +/* // spawn debris + CModelDestruction *pmd=GetDestruction(); + pmd->SpawnDebris(this); + // if there is another phase in destruction + CModelHolder3 *penNext = pmd->GetNextPhase(); + if (penNext!=NULL) { + // copy it here + CEntity *penNew = GetWorld()->CopyEntityInWorld( *penNext, GetPlacement() ); + penNew->GetModelObject()->StretchModel(GetModelObject()->mo_Stretch); + penNew->ModelChangeNotify(); + ((CModelHolder3 *)penNew)->m_colBurning=m_colBurning; + ((CModelHolder3 *)penNew)->m_fChainSawCutDamage=m_fChainSawCutDamage; + + if( pmd->m_iStartAnim!=-1) + { + penNew->GetModelObject()->PlayAnim(pmd->m_iStartAnim, 0); + } + + // copy custom shading parameters + CModelHolder3 &mhNew=*((CModelHolder3 *)penNew); + mhNew.m_cstCustomShading=m_cstCustomShading; + mhNew.m_colLight=m_colLight; + mhNew.m_colAmbient=m_colAmbient; + mhNew.m_fMipFadeDist = m_fMipFadeDist; + mhNew.m_fMipFadeLen = m_fMipFadeLen; + mhNew.m_fMipAdd = m_fMipAdd; + mhNew.m_fMipMul = m_fMipMul; + + // domino death for cannonball + if(m_dmtLastDamageType==DMT_CHAINSAW) + { + EDeath eDeath; // we don't need any extra parameters + mhNew.m_fChainSawCutDamage=0.0f; + mhNew.m_dmtLastDamageType=DMT_CHAINSAW; + penNew->SendEvent(eDeath); + } + } + + // if there is a destruction target + if (m_penDestroyTarget!=NULL) { + // notify it + SendToTarget(m_penDestroyTarget, EET_TRIGGER, m_penLastDamager); + }*/ + + // destroy yourself + Destroy(); + return; + } + + Main() + { + // initialize the model + InitModelHolder(); + + /*if (m_fMipFadeLenMetric>m_rMipFadeDistMetric) { m_fMipFadeLenMetric = m_rMipFadeDistMetric; } + // convert metric factors to mip factors + if (m_rMipFadeDistMetric>0.0f) { + m_fMipFadeDist = Log2(m_rMipFadeDistMetric*1024.0f*MIPRATIO); + m_fMipFadeLen = Log2((m_rMipFadeDistMetric+m_fMipFadeLenMetric)*1024.0f*MIPRATIO) - m_fMipFadeDist; + } else { + m_fMipFadeDist = 0.0f; + m_fMipFadeLen = 0.0f; + }*/ + + // check your destruction pointer + /*if (m_penDestruction!=NULL && !IsOfClass(m_penDestruction, "ModelDestruction")) { + WarningMessage("Destruction '%s' is wrong class!", m_penDestruction->GetName()); + m_penDestruction=NULL; + }*/ + + // wait forever + wait() { + // on the beginning + on(EBegin): { + // set your health + /*if (m_penDestruction!=NULL) { + SetHealth(GetDestruction()->m_fHealth); + }*/ + resume; + } + // activate/deactivate shows/hides model + on (EActivate): { + SwitchToModel(); + m_bActive = TRUE; + if (m_bColliding) { + SetPhysicsFlags(EPF_MODEL_FIXED); + SetCollisionFlags(ECF_MODEL_HOLDER); + } + resume; + } + on (EDeactivate): { + SwitchToEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + m_bActive = FALSE; + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + resume; + } + // when your parent is destroyed + on(ERangeModelDestruction): { + // for each child of this entity + {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { + // send it destruction event + itenChild->SendEvent(ERangeModelDestruction()); + }} + // destroy yourself + Destroy(); + resume; + } + // when dead + on(EDeath): { + /*if (m_penDestruction!=NULL) { + jump Die(); + }*/ + resume; + } +/* on(EFade): { + if (_pTimer->CurrentTick()>m_tmFadeEnd) { + m_tmFadeStart = _pTimer->CurrentTick(); + } + m_tmFadeEnd = _pTimer->CurrentTick() + m_fFadeSpeed + m_fFadeEndWait; + // perhaps fade all entities children + if (m_bFadeChildren) { + {FOREACHINLIST( CEntity, en_lnInParent, en_lhChildren, iten) { + iten->SendEvent(EFade()); + }} + } + resume; + }*/ + // when animation should be changed + /*on(EChangeAnim eChange): { + m_iModelAnimation = eChange.iModelAnim; + m_iTextureAnimation = eChange.iTextureAnim; + m_iLightAnimation = eChange.iLightAnim; + if (m_aoLightAnimation.GetData()!=NULL) { + m_aoLightAnimation.PlayAnim(m_iLightAnimation, eChange.bLightLoop?AOF_LOOPING:0); + } + if (GetModelObject()->GetData()!=NULL) { + GetModelObject()->PlayAnim(m_iModelAnimation, eChange.bModelLoop?AOF_LOOPING:0); + } + if (GetModelObject()->mo_toTexture.GetData()!=NULL) { + GetModelObject()->mo_toTexture.PlayAnim(m_iTextureAnimation, eChange.bTextureLoop?AOF_LOOPING:0); + } + resume; + }*/ + otherwise(): { + resume; + } + }; + } +}; diff --git a/Sources/EntitiesMP/ModelHolder3.h b/Sources/EntitiesMP/ModelHolder3.h new file mode 100644 index 0000000..4a65ff3 --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder3.h @@ -0,0 +1,89 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ModelHolder3_INCLUDED +#define _EntitiesMP_ModelHolder3_INCLUDED 1 +#include +#include +#include +extern DECL_DLL CEntityPropertyEnumType SkaCustomShadingType_enum; +enum SkaCustomShadingType { + SCST_NONE = 0, + SCST_CONSTANT_SHADING = 1, + SCST_FULL_CUSTOMIZED = 2, +}; +DECL_DLL inline void ClearToDefault(SkaCustomShadingType &e) { e = (SkaCustomShadingType)0; } ; +extern DECL_DLL CEntityPropertyEnumType SkaShadowType_enum; +enum SkaShadowType { + SST_NONE = 0, + SST_CLUSTER = 1, + SST_POLYGONAL = 2, +}; +DECL_DLL inline void ClearToDefault(SkaShadowType &e) { e = (SkaShadowType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CModelHolder3_DLLClass; +class CModelHolder3 : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual const CTString &GetDescription(void) const { return m_strDescription; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTFileName m_fnModel; + FLOAT m_fStretchAll; + ANGLE3D m_vStretchXYZ; + CTString m_strName; + CTString m_strDescription; + BOOL m_bColliding; + enum SkaShadowType m_stClusterShadows; + BOOL m_bBackground; + BOOL m_bTargetable; + enum SkaCustomShadingType m_cstCustomShading; + ANGLE3D m_aShadingDirection; + COLOR m_colLight; + COLOR m_colAmbient; + BOOL m_bActive; + FLOAT m_fClassificationStretch; + FLOAT m_fMaxTessellationLevel; + +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +FLOAT3D GetClassificationBoxStretch(void); + +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +FLOAT GetMaxTessellationLevel(void); + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +void * GetEntityInfo(void); + +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +BOOL IsTargetable(void)const; + +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +void MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX); + +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +void StretchModel(void); + +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +void InitModelHolder(void); +#define STATE_CModelHolder3_Die 0x00f20000 + BOOL +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +Die(const CEntityEvent &__eeInput); +#define STATE_CModelHolder3_Main 1 + BOOL +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00f20001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00f20002_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ModelHolder3_INCLUDED diff --git a/Sources/EntitiesMP/ModelHolder3_tables.h b/Sources/EntitiesMP/ModelHolder3_tables.h new file mode 100644 index 0000000..52a55e6 --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder3_tables.h @@ -0,0 +1,66 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(SkaCustomShadingType) + EP_ENUMVALUE(SCST_NONE, "Automatic shading"), + EP_ENUMVALUE(SCST_CONSTANT_SHADING, "Constant shading"), + EP_ENUMVALUE(SCST_FULL_CUSTOMIZED, "Customized shading"), +EP_ENUMEND(SkaCustomShadingType); + +EP_ENUMBEG(SkaShadowType) + EP_ENUMVALUE(SST_NONE, "None"), + EP_ENUMVALUE(SST_CLUSTER, "Cluster shadows"), + EP_ENUMVALUE(SST_POLYGONAL, "Polygonal"), +EP_ENUMEND(SkaShadowType); + +#define ENTITYCLASS CModelHolder3 + +CEntityProperty CModelHolder3_properties[] = { + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000f2<<8)+1, offsetof(CModelHolder3, m_fnModel), "Model file (.smc)", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f2<<8)+3, offsetof(CModelHolder3, m_fStretchAll), "StretchAll", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x000000f2<<8)+4, offsetof(CModelHolder3, m_vStretchXYZ), "StretchXYZ", 'X', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000f2<<8)+7, offsetof(CModelHolder3, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000f2<<8)+12, offsetof(CModelHolder3, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000f2<<8)+8, offsetof(CModelHolder3, m_bColliding), "Collision", 'L', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &SkaShadowType_enum, (0x000000f2<<8)+11, offsetof(CModelHolder3, m_stClusterShadows), "Shadows", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000f2<<8)+13, offsetof(CModelHolder3, m_bBackground), "Background", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000f2<<8)+21, offsetof(CModelHolder3, m_bTargetable), "Targetable", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &SkaCustomShadingType_enum, (0x000000f2<<8)+14, offsetof(CModelHolder3, m_cstCustomShading), "Shading mode", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x000000f2<<8)+15, offsetof(CModelHolder3, m_aShadingDirection), "Shade. Light direction", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000f2<<8)+16, offsetof(CModelHolder3, m_colLight), "Shade. Light color", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000f2<<8)+17, offsetof(CModelHolder3, m_colAmbient), "Shade. Ambient color", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000f2<<8)+26, offsetof(CModelHolder3, m_bActive), "Active", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f2<<8)+70, offsetof(CModelHolder3, m_fClassificationStretch), "Classification stretch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000f2<<8)+100, offsetof(CModelHolder3, m_fMaxTessellationLevel), "Max tessellation level", 0, 0x7F0000FFUL, 0), +}; +#define CModelHolder3_propertiesct ARRAYCOUNT(CModelHolder3_properties) + +CEntityComponent CModelHolder3_components[] = { + CEntityComponent() +}; +#define CModelHolder3_componentsct 0 + + +CEventHandlerEntry CModelHolder3_handlers[] = { + {0x00f20000, -1, CEntity::pEventHandler(&CModelHolder3:: +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +Die),DEBUGSTRING("CModelHolder3::Die")}, + {1, -1, CEntity::pEventHandler(&CModelHolder3:: +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder3.es" +Main),DEBUGSTRING("CModelHolder3::Main")}, + {0x00f20001, -1, CEntity::pEventHandler(&CModelHolder3::H0x00f20001_Main_01), DEBUGSTRING("CModelHolder3::H0x00f20001_Main_01")}, + {0x00f20002, -1, CEntity::pEventHandler(&CModelHolder3::H0x00f20002_Main_02), DEBUGSTRING("CModelHolder3::H0x00f20002_Main_02")}, +}; +#define CModelHolder3_handlersct ARRAYCOUNT(CModelHolder3_handlers) + +CEntity *CModelHolder3_New(void) { return new CModelHolder3; }; +void CModelHolder3_OnInitClass(void) {}; +void CModelHolder3_OnEndClass(void) {}; +void CModelHolder3_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CModelHolder3_OnWorldEnd(CWorld *pwo) {}; +void CModelHolder3_OnWorldInit(CWorld *pwo) {}; +void CModelHolder3_OnWorldTick(CWorld *pwo) {}; +void CModelHolder3_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CModelHolder3, CRationalEntity, "ModelHolder3", "Thumbnails\\ModelHolder3.tbn", 0x000000f2); +DECLARE_CTFILENAME(_fnmCModelHolder3_tbn, "Thumbnails\\ModelHolder3.tbn"); diff --git a/Sources/EntitiesMP/ModelHolder_tables.h b/Sources/EntitiesMP/ModelHolder_tables.h new file mode 100644 index 0000000..370a45e --- /dev/null +++ b/Sources/EntitiesMP/ModelHolder_tables.h @@ -0,0 +1,53 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CModelHolder + +CEntityProperty CModelHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000cb<<8)+1, offsetof(CModelHolder, m_fnModel), "Model", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000cb<<8)+2, offsetof(CModelHolder, m_fnTexture), "Texture", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000cb<<8)+3, offsetof(CModelHolder, m_fStretchAll), "StretchAll", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000cb<<8)+4, offsetof(CModelHolder, m_fStretchX), "StretchX", 'X', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000cb<<8)+5, offsetof(CModelHolder, m_fStretchY), "StretchY", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000cb<<8)+6, offsetof(CModelHolder, m_fStretchZ), "StretchZ", 'Z', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000cb<<8)+7, offsetof(CModelHolder, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000cb<<8)+12, offsetof(CModelHolder, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cb<<8)+8, offsetof(CModelHolder, m_bColliding), "Colliding", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000cb<<8)+9, offsetof(CModelHolder, m_iModelAnimation), "Model animation", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000cb<<8)+10, offsetof(CModelHolder, m_iTextureAnimation), "Texture animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cb<<8)+11, offsetof(CModelHolder, m_bClusterShadows), "Cluster shadows", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cb<<8)+13, offsetof(CModelHolder, m_bBackground), "Background", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cb<<8)+14, offsetof(CModelHolder, m_bCustomShading), "Custom shading", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x000000cb<<8)+15, offsetof(CModelHolder, m_aShadingDirection), "Light direction", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000cb<<8)+16, offsetof(CModelHolder, m_colLight), "Light color", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x000000cb<<8)+17, offsetof(CModelHolder, m_colAmbient), "Ambient color", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000cb<<8)+18, offsetof(CModelHolder, m_fnmLightAnimation), "Light animation file", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000cb<<8)+19, offsetof(CModelHolder, m_iLightAnimation), "Light animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMOBJECT, NULL, (0x000000cb<<8)+20, offsetof(CModelHolder, m_aoLightAnimation), "", 0, 0, 0), +}; +#define CModelHolder_propertiesct ARRAYCOUNT(CModelHolder_properties) + +CEntityComponent CModelHolder_components[] = { + CEntityComponent() +}; +#define CModelHolder_componentsct 0 + + +CEventHandlerEntry CModelHolder_handlers[] = { + {1, -1, CEntity::pEventHandler(&CModelHolder:: +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/ModelHolder.es" +Main),DEBUGSTRING("CModelHolder::Main")}, +}; +#define CModelHolder_handlersct ARRAYCOUNT(CModelHolder_handlers) + +CEntity *CModelHolder_New(void) { return new CModelHolder; }; +void CModelHolder_OnInitClass(void) {}; +void CModelHolder_OnEndClass(void) {}; +void CModelHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CModelHolder_OnWorldEnd(CWorld *pwo) {}; +void CModelHolder_OnWorldInit(CWorld *pwo) {}; +void CModelHolder_OnWorldTick(CWorld *pwo) {}; +void CModelHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CModelHolder, CEntity, "ModelHolder", "", 0x000000cb); +DECLARE_CTFILENAME(_fnmCModelHolder_tbn, ""); diff --git a/Sources/EntitiesMP/MovingBrush.cpp b/Sources/EntitiesMP/MovingBrush.cpp new file mode 100644 index 0000000..ae11189 --- /dev/null +++ b/Sources/EntitiesMP/MovingBrush.cpp @@ -0,0 +1,1417 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *EHit::MakeCopy(void) { CEntityEvent *peeCopy = new EHit(*this); return peeCopy;} +EHit::EHit() : CEntityEvent(EVENTCODE_EHit) {; +}; +CEntityEvent *EBrushDestroyed::MakeCopy(void) { CEntityEvent *peeCopy = new EBrushDestroyed(*this); return peeCopy;} +EBrushDestroyed::EBrushDestroyed() : CEntityEvent(EVENTCODE_EBrushDestroyed) {; +}; +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" + +static const float TRANSLATION_EPSILON=0.05f; +static const float ROTATION_EPSILON=0.05f; +extern void GetDefaultForce(INDEX iForce, const FLOAT3D &vPoint, + CForceStrength &fsGravity, CForceStrength &fsField); + +void CMovingBrush::SetDefaultProperties(void) { + m_strName = "Moving Brush"; + m_strDescription = ""; + m_penTarget = NULL; + m_bAutoStart = FALSE ; + m_fSpeed = 1.0f; + m_fWaitTime = 0.0f; + m_bMoveOnTouch = FALSE ; + m_ebaAction = BA_NONE ; + m_fBlockDamage = 10.0f; + m_bPlayersOnly = TRUE ; + m_bDynamicShadows = FALSE ; + m_bVeryBigBrush = FALSE ; + m_eetTouchEvent = EET_IGNORE ; + m_penTouchEvent = NULL; + m_tdeSendEventOnDamage = TDE_TOUCHONLY ; + m_penSwitch = NULL; + m_eetMarkerEvent = EET_IGNORE ; + m_penMarkerEvent = NULL; + m_tmBankingRotation = 0.0f; + m_bMoving = FALSE ; + m_bRotating = FALSE ; + m_bForceStop = FALSE ; + m_bNoRotation = FALSE ; + m_vDesiredTranslation = FLOAT3D(0 , 0 , 0); + m_aDesiredRotation = FLOAT3D(0 , 0 , 0); + m_bInverseRotate = FALSE ; + m_bStopMoving = FALSE ; + m_bMoveToMarker = FALSE ; + m_bSkipMarker = FALSE ; + m_bValidMarker = FALSE ; + m_fXLimitSign = 0.0f; + m_fYLimitSign = 0.0f; + m_fZLimitSign = 0.0f; + m_aHLimitSign = 0.0f; + m_aPLimitSign = 0.0f; + m_aBLimitSign = 0.0f; + m_vStartTranslation = FLOAT3D(0 , 0 , 0); + m_aStartRotation = ANGLE3D(0 , 0 , 0); + m_fCourseLength = 0.0f; + m_aHeadLenght = 0.0f; + m_aPitchLenght = 0.0f; + m_aBankLenght = 0.0f; + m_penSoundStart = NULL; + m_penSoundStop = NULL; + m_penSoundFollow = NULL; + m_soStart.SetOwner(this); +m_soStart.Stop_internal(); + m_soStop.SetOwner(this); +m_soStop.Stop_internal(); + m_soFollow.SetOwner(this); +m_soFollow.Stop_internal(); + m_penMirror0 = NULL; + m_penMirror1 = NULL; + m_penMirror2 = NULL; + m_penMirror3 = NULL; + m_penMirror4 = NULL; + m_fHealth = -1.0f; + m_bBlowupByBull = FALSE ; + m_eetBlowupEvent = EET_IGNORE ; + m_penBlowupEvent = NULL; + m_bZoning = FALSE ; + m_bMoveOnDamage = FALSE ; + m_fTouchDamage = 0.0f; + m_colDebrises = C_WHITE ; + m_ctDebrises = 12; + m_fCandyEffect = 0.0f; + m_fCubeFactor = 1.0f; + m_bBlowupByDamager = FALSE ; + m_cbClassificationBits = 0; + m_vbVisibilityBits = 0; + CMovableBrushEntity::SetDefaultProperties(); +} + +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +ULONG CMovingBrush::GetVisTweaks(void) +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return m_cbClassificationBits | m_vbVisibilityBits ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::Precache(void) +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +PrecacheClass (CLASS_DEBRIS ); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +PrecacheModel (MODEL_STONE ); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +PrecacheTexture (TEXTURE_STONE ); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::GetForce(INDEX iForce,const FLOAT3D & vPoint, +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CForceStrength & fsGravity,CForceStrength & fsField) +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +GetDefaultForce (iForce , vPoint , fsGravity , fsField ); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bMoveOnDamage ) +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +EHit eHit ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SendEvent (eHit ); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return ; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_tdeSendEventOnDamage != TDE_TOUCHONLY && CanReactOnEntity (penInflictor )){ +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SendToTarget (m_penTouchEvent , m_eetTouchEvent , penInflictor ); +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_fHealth < 0){ +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bBlowupByBull ) +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(dmtType == DMT_IMPACT && IsOfClass (penInflictor , "Werebull")) +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CMovableBrushEntity :: ReceiveDamage (penInflictor , dmtType , m_fHealth * 2 , vHitPoint , vDirection ); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +((CLiveEntity *) penInflictor ) -> SetHealth (0.0f); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +InflictDirectDamage (penInflictor , this , DMT_IMPACT , 1.0f , +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +GetPlacement () . pl_PositionVector , FLOAT3D (0 , 1 , 0)); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +else if(m_bBlowupByDamager ) +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(dmtType == DMT_DAMAGER ) +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CMovableBrushEntity :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +else +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if((dmtType == DMT_EXPLOSION ) || +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +(dmtType == DMT_PROJECTILE ) || +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +(dmtType == DMT_CANNONBALL )) +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CMovableBrushEntity :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::AdjustAngle(ANGLE & a) { +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bInverseRotate ){ +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(a > 0){a = a - 360;} +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +else if(a < 0){a = 360 + a ;} +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BOOL CMovingBrush::MovesByTargetedRoute(CTString & strTargetProperty)const { +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +strTargetProperty = "Target"; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BOOL CMovingBrush::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +fnmMarkerClass = CTFILENAME ("Classes\\MovingBrushMarker.ecl"); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +strTargetProperty = "Target"; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE ; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const CTString & CMovingBrush::GetDescription(void)const { +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_penTarget != NULL ){ +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , m_penTarget -> GetName ()); +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return m_strDescription ; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const CTString & CMovingBrush::GetMirrorName(INDEX iMirror) +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +static const CTString strDummyName (""); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +static const CTString strMarkerUnused ("Marker not set"); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(iMirror == 0){ +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return strDummyName ; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +switch(iMirror ){ +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +case 1: {static const CTString str ("std mirror 1");return str ;};break ; +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +case 2: {static const CTString str ("std mirror 2");return str ;};break ; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +case 3: {static const CTString str ("std mirror 3");return str ;};break ; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +case 4: {static const CTString str ("std mirror 4");return str ;};break ; +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +case 5: {static const CTString str ("std mirror 5");return str ;};break ; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +case 6: {static const CTString str ("std mirror 6");return str ;};break ; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +case 7: {static const CTString str ("std mirror 7");return str ;};break ; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +case 8: {static const CTString str ("std mirror 8");return str ;};break ; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +default :{ +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +iMirror -= 9; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +INDEX ctMirrorMarkers = & m_penMirror4 - & m_penMirror0 ; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(iMirror < ctMirrorMarkers ){ +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CMirrorMarker * pfm = (CMirrorMarker *) & * (& m_penMirror0 ) [ iMirror ]; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(pfm != NULL ){ +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return pfm -> GetMirrorName (); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else { +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return strMarkerUnused ; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return strDummyName ; +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BOOL CMovingBrush::GetMirror(INDEX iMirror,class CMirrorParameters & mpMirror) +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(iMirror == 0){ +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return FALSE ; +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(iMirror >= 1 && iMirror <= 8){ +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +mpMirror . mp_ulFlags = 0; +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE ; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +iMirror -= 9; +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +INDEX ctMirrorMarkers = & m_penMirror4 - & m_penMirror0 ; +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(iMirror < ctMirrorMarkers ){ +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CMirrorMarker * pmm = (CMirrorMarker *) & * (& m_penMirror0 ) [ iMirror ]; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(pmm != NULL ){ +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +pmm -> GetMirror (mpMirror ); +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE ; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return FALSE ; +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::PreMoving() { +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bMoveToMarker ){ +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const FLOAT3D & vTarget = m_penTarget -> GetPlacement () . pl_PositionVector ; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const ANGLE3D & aTarget = m_penTarget -> GetPlacement () . pl_OrientationAngle ; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const FLOAT3D & vSource = GetPlacement () . pl_PositionVector ; +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const ANGLE3D & aSource = GetPlacement () . pl_OrientationAngle ; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FLOAT3D vSpeed = (vTarget - vSource ) / _pTimer -> TickQuantum ; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(Abs (vSpeed (1)) < TRANSLATION_EPSILON ){ +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +vSpeed (1) = 0.0f; +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if((vSpeed (1) - m_vDesiredTranslation (1)) * m_fXLimitSign > 0){ +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +vSpeed (1) = m_vDesiredTranslation (1); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(Abs (vSpeed (2)) < TRANSLATION_EPSILON ){ +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +vSpeed (2) = 0.0f; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if((vSpeed (2) - m_vDesiredTranslation (2)) * m_fYLimitSign > 0){ +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +vSpeed (2) = m_vDesiredTranslation (2); +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(Abs (vSpeed (3)) < TRANSLATION_EPSILON ){ +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +vSpeed (3) = 0.0f; +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if((vSpeed (3) - m_vDesiredTranslation (3)) * m_fZLimitSign > 0){ +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +vSpeed (3) = m_vDesiredTranslation (3); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +ANGLE3D aSpeed ; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (1) = NormalizeAngle (aTarget (1) - aSource (1)); +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +AdjustAngle (aSpeed (1)); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (1) = Abs (aSpeed (1)) * m_aHLimitSign ; +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (1) /= _pTimer -> TickQuantum ; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (2) = NormalizeAngle (aTarget (2) - aSource (2)); +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +AdjustAngle (aSpeed (2)); +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (2) = Abs (aSpeed (2)) * m_aPLimitSign ; +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (2) /= _pTimer -> TickQuantum ; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (3) = NormalizeAngle (aTarget (3) - aSource (3)); +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +AdjustAngle (aSpeed (3)); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (3) = Abs (aSpeed (3)) * m_aBLimitSign ; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (3) /= _pTimer -> TickQuantum ; +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(Abs (aSpeed (1)) < ROTATION_EPSILON ){ +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (1) = 0.0f; +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if((aSpeed (1) - m_aDesiredRotation (1)) * m_aHLimitSign > 0){ +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (1) = m_aDesiredRotation (1); +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(Abs (aSpeed (2)) < ROTATION_EPSILON ){ +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (2) = 0.0f; +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if((aSpeed (2) - m_aDesiredRotation (2)) * m_aPLimitSign > 0){ +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (2) = m_aDesiredRotation (2); +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(Abs (aSpeed (3)) < ROTATION_EPSILON ){ +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (3) = 0.0f; +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if((aSpeed (3) - m_aDesiredRotation (3)) * m_aBLimitSign > 0){ +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aSpeed (3) = m_aDesiredRotation (3); +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(vSpeed (1) == 0.0f && vSpeed (2) == 0.0f && vSpeed (3) == 0.0f +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +&& ((m_tmBankingRotation != 0 || m_bNoRotation ) || (aSpeed (1) == 0.0f && aSpeed (2) == 0.0f && aSpeed (3) == 0.0f))) +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +ForceFullStop (); +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bMoveToMarker = FALSE ; +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SendEvent (EEnd ()); +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else { +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredTranslation (vSpeed ); +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bRotating ){ +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MaybeActivateRotation (); +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if(! m_tmBankingRotation && ! m_bNoRotation ){ +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (aSpeed ); +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else { +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CMovableBrushEntity :: PreMoving (); +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BOOL CMovingBrush::LoadMarkerParameters() { +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_penTarget == NULL ){ +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return FALSE ; +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(! IsOfClass (m_penTarget , "Moving Brush Marker")){ +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +WarningMessage ("Entity '%s' is not of Moving Brush Marker class!" , m_penTarget -> GetName ()); +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return FALSE ; +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CMovingBrushMarker & mbm = (CMovingBrushMarker &) * m_penTarget ; +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(mbm . m_penTarget == NULL ){ +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return FALSE ; +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(mbm . m_fSpeed > 0.0f){m_fSpeed = mbm . m_fSpeed ;} +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(mbm . m_fWaitTime >= 0.0f){m_fWaitTime = mbm . m_fWaitTime ;} +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bInverseRotate = mbm . m_bInverseRotate ; +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetBoolFromBoolEType (m_bMoveOnTouch , mbm . m_betMoveOnTouch ); +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bStopMoving = mbm . m_bStopMoving ; +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(mbm . m_fBlockDamage >= 0.0f){ +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_fBlockDamage = mbm . m_fBlockDamage ; +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(mbm . m_penTouchEvent != NULL ){ +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_penTouchEvent = mbm . m_penTouchEvent ; +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_eetTouchEvent = mbm . m_eetTouchEvent ; +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SendToTarget (mbm . m_penMarkerEvent , mbm . m_eetMarkerEvent ); +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(mbm . m_penSoundStart != NULL ){ +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_penSoundStart = mbm . m_penSoundStart ; +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(mbm . m_penSoundStop != NULL ){ +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_penSoundStop = mbm . m_penSoundStop ; +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(mbm . m_penSoundFollow != NULL ){ +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_penSoundFollow = mbm . m_penSoundFollow ; +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bNoRotation = mbm . m_bNoRotation ; +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(mbm . m_tmBankingRotation >= 0.0f){ +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_tmBankingRotation = mbm . m_tmBankingRotation ; +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(! mbm . m_bBankingClockwise ){ +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_tmBankingRotation *= - 1; +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE ; +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BOOL CMovingBrush::CanReactOnEntity(CEntity * pen) +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(pen == NULL ){ +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return FALSE ; +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(! (pen -> GetFlags () & ENF_ALIVE )){ +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return FALSE ; +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bPlayersOnly && ! IsDerivedFromClass (pen , "Player")){ +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return FALSE ; +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE ; +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::PlayStartSound(void) { +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_penSoundStart != NULL ){ +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CSoundHolder & sh = (CSoundHolder &) * m_penSoundStart ; +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_soStart . Set3DParameters (FLOAT (sh . m_rFallOffRange ) , FLOAT (sh . m_rHotSpotRange ) , sh . m_fVolume , 1.0f); +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +PlaySound (m_soStart , sh . m_fnSound , sh . m_iPlayType ); +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::PlayStopSound(void) { +#line 491 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_penSoundStop != NULL ){ +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CSoundHolder & sh = (CSoundHolder &) * m_penSoundStop ; +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_soStop . Set3DParameters (FLOAT (sh . m_rFallOffRange ) , FLOAT (sh . m_rHotSpotRange ) , sh . m_fVolume , 1.0f); +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +PlaySound (m_soStop , sh . m_fnSound , sh . m_iPlayType ); +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::PlayFollowSound(void) { +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_penSoundFollow != NULL ){ +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CSoundHolder & sh = (CSoundHolder &) * m_penSoundFollow ; +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_soFollow . Set3DParameters (FLOAT (sh . m_rFallOffRange ) , FLOAT (sh . m_rHotSpotRange ) , sh . m_fVolume , 1.0f); +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +PlaySound (m_soFollow , sh . m_fnSound , sh . m_iPlayType ); +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::StopFollowSound(void) { +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_soFollow . Stop (); +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::MovingOn(void) +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bMoving ){ +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return ; +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bVeryBigBrush ){ +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetCollisionFlags (ECF_BRUSH | ECF_IGNOREMODELS ); +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bMoving = TRUE ; +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::MovingOff(void) +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(! m_bMoving ){ +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return ; +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bVeryBigBrush ){ +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetCollisionFlags (ECF_BRUSH ); +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bMoving = FALSE ; +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::MaybeActivateRotation(void) +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_tmBankingRotation != 0){ +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bRotating = TRUE ; +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 360.0f / m_tmBankingRotation )); +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +else { +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bRotating = FALSE ; +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::DeactivateRotation(void) +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bRotating = FALSE ; +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void CMovingBrush::SetCombinedRotation(ANGLE3D aRotAngle,ANGLE3D aAddAngle) +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aRotAngle (1) += aAddAngle (1); +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aRotAngle (2) += aAddAngle (2); +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aRotAngle (3) += aAddAngle (3); +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} + +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SLONG CMovingBrush::GetUsedMemory(void) +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SLONG slUsedMemory = sizeof (CMovingBrush ) - sizeof (CMovableBrushEntity ) + CMovableBrushEntity :: GetUsedMemory (); +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +slUsedMemory += m_strName . Length (); +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +slUsedMemory += m_strDescription . Length (); +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +slUsedMemory += 3 * sizeof (CSoundObject); +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return slUsedMemory ; +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +BOOL CMovingBrush:: +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MoveToMarker(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMovingBrush_MoveToMarker + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMovingBrush::MoveToMarker expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 579 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const FLOAT3D & vTarget = m_penTarget -> GetPlacement () . pl_PositionVector ; +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const ANGLE3D & aTarget = m_penTarget -> GetPlacement () . pl_OrientationAngle ; +#line 581 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const FLOAT3D & vSource = GetPlacement () . pl_PositionVector ; +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const ANGLE3D & aSource = GetPlacement () . pl_OrientationAngle ; +#line 585 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_vDesiredTranslation = (vTarget - vSource ) / m_fSpeed ; +#line 586 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_fXLimitSign = Sgn (vTarget (1) - vSource (1)); +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_fYLimitSign = Sgn (vTarget (2) - vSource (2)); +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_fZLimitSign = Sgn (vTarget (3) - vSource (3)); +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +ANGLE aDelta = NormalizeAngle (aTarget (1) - aSource (1)); +#line 593 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +AdjustAngle (aDelta ); +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_aDesiredRotation (1) = aDelta / m_fSpeed ; +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_aHLimitSign = Sgn (aDelta ); +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aDelta = NormalizeAngle (aTarget (2) - aSource (2)); +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +AdjustAngle (aDelta ); +#line 599 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_aDesiredRotation (2) = aDelta / m_fSpeed ; +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_aPLimitSign = Sgn (aDelta ); +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +aDelta = NormalizeAngle (aTarget (3) - aSource (3)); +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +AdjustAngle (aDelta ); +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_aDesiredRotation (3) = aDelta / m_fSpeed ; +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_aBLimitSign = Sgn (aDelta ); +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bMoveToMarker = TRUE ; +#line 609 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredTranslation (m_vDesiredTranslation ); +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bRotating ){ +#line 611 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MaybeActivateRotation (); +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if(! m_tmBankingRotation ){ +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (m_aDesiredRotation ); +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00650003, FALSE, EBegin());return TRUE;}BOOL CMovingBrush::H0x00650003_MoveToMarker_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650003 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 621 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 622 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_tmBankingRotation == 0){ +#line 623 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 624 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bForceStop = TRUE ; +#line 627 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bMoveToMarker = FALSE ; +#line 628 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bStopMoving = TRUE ; +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Return(STATE_CURRENT,EEnd ()); +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 631 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;case(EVENTCODE_EBlock):{const EBlock&eBlock= (EBlock&)__eeInput; + +#line 635 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +InflictDirectDamage (eBlock . penOther , this , DMT_BRUSH , m_fBlockDamage , +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FLOAT3D (0.0f , 0.0f , 0.0f) , (FLOAT3D &) eBlock . plCollision ); +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_ebaAction == BA_BOUNCE ){ +#line 639 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredTranslation (- m_vDesiredTranslation ); +#line 640 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bRotating ){ +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MaybeActivateRotation (); +#line 642 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if(! m_tmBankingRotation ){ +#line 643 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (- m_aDesiredRotation ); +#line 644 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 646 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Call(STATE_CURRENT, STATE_CMovingBrush_BounceObstructed, TRUE, EVoid());return TRUE; +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if(m_ebaAction == BA_SKIPMARKER ){ +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +ForceFullStop (); +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bMoveToMarker = FALSE ; +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bSkipMarker = TRUE ; +#line 654 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Return(STATE_CURRENT,EEnd ()); +#line 654 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 655 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 656 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 657 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}return TRUE;}BOOL CMovingBrush::H0x00650004_MoveToMarker_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650004 + ASSERT(FALSE); return TRUE;};BOOL CMovingBrush:: +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BounceObstructed(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMovingBrush_BounceObstructed + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMovingBrush::BounceObstructed expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetTimerAfter(0.2f); +Jump(STATE_CURRENT, 0x00650006, FALSE, EBegin());return TRUE;}BOOL CMovingBrush::H0x00650006_BounceObstructed_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00650007, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CMovingBrush::H0x00650007_BounceObstructed_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650007 +; +#line 664 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredTranslation (m_vDesiredTranslation ); +#line 665 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bRotating ){ +#line 666 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 360.0f / m_tmBankingRotation )); +#line 667 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if(! m_tmBankingRotation ){ +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (m_aDesiredRotation ); +#line 669 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 670 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Return(STATE_CURRENT,EVoid()); +#line 670 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CMovingBrush:: +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MoveBrush(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMovingBrush_MoveBrush + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMovingBrush::MoveBrush expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 712 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_penTarget == NULL ){ +#line 713 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MovingOff (); +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Return(STATE_CURRENT,EVoid()); +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MovingOn (); +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Jump(STATE_CURRENT,0x00650011, FALSE, EInternal());return TRUE;}BOOL CMovingBrush::H0x00650011_MoveBrush_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650011 + +#line 722 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bForceStop == FALSE ) +#line 723 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 725 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_penTarget = m_penTarget -> GetTarget (); +#line 726 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 727 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +else { +#line 728 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bForceStop = FALSE ; +#line 729 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 731 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_penTarget == NULL ){ +#line 732 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MovingOff (); +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Return(STATE_CURRENT,EVoid ()); +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 734 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 737 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(!(m_bSkipMarker )){ Jump(STATE_CURRENT,0x0065000d, FALSE, EInternal());return TRUE;} +#line 738 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bSkipMarker = FALSE ;Jump(STATE_CURRENT,0x0065000c, FALSE, EInternal());return TRUE;}BOOL CMovingBrush::H0x0065000d_MoveBrush_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0065000d +if(!(m_fWaitTime > 0.0f)){ Jump(STATE_CURRENT,0x0065000b, FALSE, EInternal());return TRUE;} +#line 742 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetTimerAfter(m_fWaitTime ); +Jump(STATE_CURRENT, 0x00650009, FALSE, EBegin());return TRUE;}BOOL CMovingBrush::H0x00650009_MoveBrush_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650009 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 746 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 747 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_tmBankingRotation == 0){ +#line 748 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 749 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 750 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bForceStop = TRUE ; +#line 752 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bMoveToMarker = FALSE ; +#line 753 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bStopMoving = TRUE ; +#line 755 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x0065000a, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 757 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}return TRUE;}BOOL CMovingBrush::H0x0065000a_MoveBrush_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0065000a +Jump(STATE_CURRENT,0x0065000b, FALSE, EInternal());return TRUE;}BOOL CMovingBrush::H0x0065000b_MoveBrush_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0065000b +Jump(STATE_CURRENT,0x0065000c, FALSE, EInternal());return TRUE;} +BOOL CMovingBrush::H0x0065000c_MoveBrush_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0065000c + +#line 760 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(!(! m_bForceStop )){ Jump(STATE_CURRENT,0x00650010, FALSE, EInternal());return TRUE;} +#line 761 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MaybeActivateRotation (); +#line 763 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +PlayStartSound (); +#line 764 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +PlayFollowSound (); +#line 765 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +STATE_CMovingBrush_MoveToMarker, TRUE; +Jump(STATE_CURRENT, 0x0065000e, FALSE, EBegin());return TRUE;}BOOL CMovingBrush::H0x0065000e_MoveBrush_06(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0065000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CMovingBrush_MoveToMarker, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x0065000f, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CMovingBrush::H0x0065000f_MoveBrush_07(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0065000f +const EEnd&__e= (EEnd&)__eeInput; +; +#line 766 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +StopFollowSound (); +#line 767 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +PlayStopSound ();Jump(STATE_CURRENT,0x00650010, FALSE, EInternal());return TRUE;}BOOL CMovingBrush::H0x00650010_MoveBrush_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650010 + +#line 771 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(! m_bForceStop ){ +#line 772 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bValidMarker = LoadMarkerParameters (); +#line 773 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 776 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bSkipMarker ){ +#line 777 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bStopMoving = FALSE ; +#line 778 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}if(!(! m_bStopMoving && m_bValidMarker && ! m_bForceStop )){ Jump(STATE_CURRENT,0x00650012, FALSE, EInternal());return TRUE;}Jump(STATE_CURRENT,0x00650011, FALSE, EInternal());return TRUE; +#line 779 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}BOOL CMovingBrush::H0x00650012_MoveBrush_10(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650012 + +#line 780 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MovingOff (); +#line 781 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Return(STATE_CURRENT,EVoid()); +#line 781 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CMovingBrush:: +#line 784 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +TeleportToStopMarker(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMovingBrush_TeleportToStopMarker + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMovingBrush::TeleportToStopMarker expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 786 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MovingOn (); +#line 788 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +INDEX ctMarkers = 0; +#line 790 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CMovingBrushMarker * pmbm = (CMovingBrushMarker *) & * m_penTarget ; +#line 791 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +while(pmbm != NULL && IsOfClass (pmbm -> m_penTarget , "Moving Brush Marker") && ! pmbm -> m_bStopMoving && ctMarkers < 50) +#line 792 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 793 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +pmbm = (CMovingBrushMarker *) & * pmbm -> m_penTarget ; +#line 794 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +ctMarkers ++; +#line 795 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(pmbm != NULL && IsOfClass (pmbm , "Moving Brush Marker") && ctMarkers < 50) +#line 798 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 799 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetPlacement (pmbm -> GetPlacement ()); +#line 800 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +en_plLastPlacement = pmbm -> GetPlacement (); +#line 801 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +ForceFullStop (); +#line 802 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_soStart . Stop (); +#line 803 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_soStop . Stop (); +#line 804 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_soFollow . Stop (); +#line 805 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 808 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bMoveToMarker = FALSE ; +#line 809 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MovingOff (); +#line 810 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Return(STATE_CURRENT,EReturn ()); +#line 810 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CMovingBrush:: +#line 813 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMovingBrush_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMovingBrush::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 815 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +InitAsBrush (); +#line 816 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetPhysicsFlags (EPF_BRUSH_MOVING ); +#line 817 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetCollisionFlags (ECF_BRUSH ); +#line 818 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetHealth (m_fHealth ); +#line 821 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bZoning ){ +#line 822 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetFlags (GetFlags () | ENF_ZONING ); +#line 823 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else { +#line 824 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetFlags (GetFlags () & ~ ENF_ZONING ); +#line 825 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 829 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bDynamicShadows ){ +#line 830 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetFlags (GetFlags () | ENF_DYNAMICSHADOWS ); +#line 831 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else { +#line 832 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetFlags (GetFlags () & ~ ENF_DYNAMICSHADOWS ); +#line 833 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 836 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +ForceFullStop (); +#line 838 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00650014, FALSE, EBegin());return TRUE;}BOOL CMovingBrush::H0x00650014_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650014 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00650015, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CMovingBrush::H0x00650015_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650015 +; +#line 841 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bValidMarker = LoadMarkerParameters (); +#line 848 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00650016, FALSE, EBegin());return TRUE;}BOOL CMovingBrush::H0x00650016_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650016 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 850 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bAutoStart ){ +#line 852 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MaybeActivateRotation (); +#line 853 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(! m_bMoving && m_bValidMarker ){ +#line 854 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Call(STATE_CURRENT, STATE_CMovingBrush_MoveBrush, TRUE, EVoid());return TRUE; +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 856 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 857 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 858 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;case(EVENTCODE_EHit):{const EHit&eHit= (EHit&)__eeInput; + +#line 860 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(! m_bMoving ){ +#line 861 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MaybeActivateRotation (); +#line 862 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Call(STATE_CURRENT, STATE_CMovingBrush_MoveBrush, TRUE, EVoid());return TRUE; +#line 863 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 864 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 865 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&eTouch= (ETouch&)__eeInput; + +#line 869 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_fTouchDamage != 0.0f) +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 871 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +InflictDirectDamage (eTouch . penOther , this , DMT_SPIKESTAB , m_fTouchDamage , +#line 872 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +eTouch . penOther -> GetPlacement () . pl_PositionVector , eTouch . plCollision ); +#line 873 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 875 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_tdeSendEventOnDamage != TDE_DAMAGEONLY && CanReactOnEntity (eTouch . penOther )){ +#line 876 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SendToTarget (m_penTouchEvent , m_eetTouchEvent ); +#line 877 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 879 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(! m_bMoving ){ +#line 881 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bMoveOnTouch && CanReactOnEntity (eTouch . penOther ) && m_bValidMarker ){ +#line 882 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MaybeActivateRotation (); +#line 883 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Call(STATE_CURRENT, STATE_CMovingBrush_MoveBrush, TRUE, EVoid());return TRUE; +#line 884 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 885 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 887 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bBlowupByBull ){ +#line 889 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(IsOfClass (eTouch . penOther , "Werebull")){ +#line 891 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FLOAT fImpactSpeed = +#line 892 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +((CMovableEntity &) * eTouch . penOther ) . en_vCurrentTranslationAbsolute % +#line 893 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +- (FLOAT3D &) eTouch . plCollision ; +#line 896 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(fImpactSpeed > m_fHealth ){ +#line 898 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +ReceiveDamage (eTouch . penOther , DMT_IMPACT , m_fHealth * 2 , +#line 899 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FLOAT3D (0 , 0 , 0) , FLOAT3D (0 , 0 , 0)); +#line 900 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 901 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 902 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 903 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 904 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;case(EVENTCODE_EBlock):{const EBlock&eBlock= (EBlock&)__eeInput; + +#line 907 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +InflictDirectDamage (eBlock . penOther , this , DMT_BRUSH , m_fBlockDamage , +#line 908 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FLOAT3D (0.0f , 0.0f , 0.0f) , (FLOAT3D &) eBlock . plCollision ); +#line 909 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_ebaAction == BA_BOUNCE ){ +#line 911 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredTranslation (- m_vDesiredTranslation ); +#line 912 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_bRotating ){ +#line 913 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (- ANGLE3D (0.0f , 0.0f , 360.0f / m_tmBankingRotation )); +#line 914 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}else if(! m_tmBankingRotation ){ +#line 915 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDesiredRotation (- m_aDesiredRotation ); +#line 916 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 919 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Call(STATE_CURRENT, STATE_CMovingBrush_BounceObstructed, TRUE, EVoid());return TRUE; +#line 920 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 921 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 922 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; + +#line 926 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(! m_bMoving && m_bValidMarker ){ +#line 927 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Call(STATE_CURRENT, STATE_CMovingBrush_MoveBrush, TRUE, EVoid());return TRUE; +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 929 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 930 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 933 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 934 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETeleportMovingBrush):{const ETeleportMovingBrush&e= (ETeleportMovingBrush&)__eeInput; + +#line 936 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Call(STATE_CURRENT, STATE_CMovingBrush_TeleportToStopMarker, TRUE, EVoid());return TRUE; +#line 937 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 938 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; + +#line 941 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(! m_bMoving && m_bValidMarker ){ +#line 942 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Call(STATE_CURRENT, STATE_CMovingBrush_MoveBrush, TRUE, EVoid());return TRUE; +#line 943 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 944 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 945 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 947 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(! m_bRotating ){ +#line 948 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MaybeActivateRotation (); +#line 949 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 950 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 951 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 953 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +DeactivateRotation (); +#line 954 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; +#line 955 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 958 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FLOATaabbox3D box ; +#line 959 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +GetSize (box ); +#line 960 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +if(m_ctDebrises > 0) +#line 961 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{ +#line 962 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FLOAT fEntitySize = pow (box . Size () (1) * box . Size () (2) * box . Size () (3) / m_ctDebrises , 1.0f / 3.0f) * m_fCubeFactor ; +#line 964 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Debris_Begin (EIBT_ROCK , DPT_NONE , BET_NONE , fEntitySize , FLOAT3D (1.0f , 2.0f , 3.0f) , +#line 965 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FLOAT3D (0 , 0 , 0) , 1.0f + m_fCandyEffect / 2.0f , m_fCandyEffect , m_colDebrises ); +#line 966 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +for(INDEX iDebris = 0;iDebris < m_ctDebrises ;iDebris ++){ +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Debris_Spawn (this , this , MODEL_STONE , TEXTURE_STONE , 0 , 0 , 0 , IRnd () % 4 , 1.0f , +#line 968 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FLOAT3D (FRnd () * 0.8f + 0.1f , FRnd () * 0.8f + 0.1f , FRnd () * 0.8f + 0.1f)); +#line 969 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 970 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 973 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , iten ){ +#line 974 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +iten -> SendEvent (EBrushDestroyed ()); +#line 975 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +} +#line 977 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SendToTarget (m_penBlowupEvent , m_eetBlowupEvent , eDeath . eLastDamage . penInflictor ); +#line 980 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_tdeSendEventOnDamage = TDE_TOUCHONLY ; +#line 981 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_fHealth = - 1; +#line 982 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +m_bMoveOnDamage = FALSE ; +#line 983 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +ForceFullStop (); +#line 984 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetDefaultProperties (); +#line 988 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +NotifyCollisionChanged (); +#line 990 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetFlags (GetFlags () | ENF_HIDDEN ); +#line 991 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 994 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +{FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , itenChild ){ +#line 996 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +itenChild -> SendEvent (ERangeModelDestruction ()); +#line 997 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}} +#line 999 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +UnsetTimer();Jump(STATE_CURRENT,0x00650017, FALSE, EInternal());return TRUE; +#line 1000 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 1001 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +}return TRUE;}BOOL CMovingBrush::H0x00650017_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00650017 + +#line 1002 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Return(STATE_CURRENT,EVoid()); +#line 1002 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/MovingBrush.es b/Sources/EntitiesMP/MovingBrush.es new file mode 100644 index 0000000..fc13eff --- /dev/null +++ b/Sources/EntitiesMP/MovingBrush.es @@ -0,0 +1,1004 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +101 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/MovingBrushMarker"; +uses "EntitiesMP/SoundHolder"; +uses "EntitiesMP\MirrorMarker"; +uses "EntitiesMP/Debris"; + +event EHit { +}; +event EBrushDestroyed { // sent to all children of a moving brush when it is destroyed +}; + +enum BlockAction { + 0 BA_NONE "None", // continue moving + 1 BA_BOUNCE "Bounce", // bounce when obstructed + 2 BA_SKIPMARKER "Skip marker", // skip moving to next marker +}; + +enum TouchOrDamageEvent { + 0 TDE_TOUCHONLY "Touch Only", + 1 TDE_DAMAGEONLY "Damage Only", + 2 TDE_BOTH "Both", +}; + +%{ +static const float TRANSLATION_EPSILON=0.05f; +static const float ROTATION_EPSILON=0.05f; +extern void GetDefaultForce(INDEX iForce, const FLOAT3D &vPoint, + CForceStrength &fsGravity, CForceStrength &fsField); +%} + +class CMovingBrush : CMovableBrushEntity { +name "Moving Brush"; +thumbnail "Thumbnails\\MovingBrush.tbn"; +features "HasName", "IsTargetable"; + +properties: + + 1 CTString m_strName "Name" 'N' = "Moving Brush", + 2 CTString m_strDescription = "", + + 3 CEntityPointer m_penTarget "Target" 'T' COLOR(C_BLUE|0xFF), + 4 BOOL m_bAutoStart "Auto start" 'A' = FALSE, + 5 FLOAT m_fSpeed "Speed" 'S' = 1.0f, + 6 FLOAT m_fWaitTime "Wait time" 'W' = 0.0f, + 7 BOOL m_bMoveOnTouch "Move on touch" 'M' = FALSE, + 8 enum BlockAction m_ebaAction "Block action" 'B' = BA_NONE, + 9 FLOAT m_fBlockDamage "Block damage" 'D' = 10.0f, + 10 BOOL m_bPlayersOnly "Players Only" 'P' = TRUE, + 11 BOOL m_bDynamicShadows "Dynamic shadows" = FALSE, + 12 BOOL m_bVeryBigBrush "Very Big Brush" = FALSE, + + // send event on touch + 13 enum EventEType m_eetTouchEvent "Touch Event - Type" 'U' = EET_IGNORE, // type of event to send + 14 CEntityPointer m_penTouchEvent "Touch Event - Target" 'I' COLOR(C_dCYAN|0xFF), // target to send event to + 19 enum TouchOrDamageEvent m_tdeSendEventOnDamage "Send touch event on damage" = TDE_TOUCHONLY, + + 15 CEntityPointer m_penSwitch "Switch", // for switch relaying + + // send event on marker + 16 enum EventEType m_eetMarkerEvent = EET_IGNORE, + 17 CEntityPointer m_penMarkerEvent, + + // rotation + 18 FLOAT m_tmBankingRotation "Banking rotation speed" = 0.0f, // set if only banking rotation + + // class properties + 20 BOOL m_bMoving = FALSE, // the brush is moving + 78 BOOL m_bRotating = FALSE, // the brush is rotating + 79 BOOL m_bForceStop = FALSE, // the brush should stop immediately + 80 BOOL m_bNoRotation = FALSE, // don't rotate to marker orientation + 21 FLOAT3D m_vDesiredTranslation = FLOAT3D(0,0,0), // desired translation + 22 ANGLE3D m_aDesiredRotation = FLOAT3D(0,0,0), // desired rotation + 23 BOOL m_bInverseRotate = FALSE, // use inverse rotation to target + 24 BOOL m_bStopMoving = FALSE, // stop moving brush on next target + 25 BOOL m_bMoveToMarker = FALSE, // PerMoving acknowledge od brush moving + 26 BOOL m_bSkipMarker = FALSE, // when obstructed skip next marker (actually stop moving) + 27 BOOL m_bValidMarker = FALSE, // internal for moving through valid markers + + // moving limits + 30 FLOAT m_fXLimitSign = 0.0f, + 31 FLOAT m_fYLimitSign = 0.0f, + 32 FLOAT m_fZLimitSign = 0.0f, + 33 ANGLE m_aHLimitSign = 0.0f, + 34 ANGLE m_aPLimitSign = 0.0f, + 35 ANGLE m_aBLimitSign = 0.0f, + + // continuous speed change + 40 FLOAT3D m_vStartTranslation = FLOAT3D(0,0,0), // start translation + 41 ANGLE3D m_aStartRotation = ANGLE3D(0,0,0), // start rotation + 42 FLOAT m_fCourseLength = 0.0f, // course length + 43 ANGLE m_aHeadLenght = 0.0f, // head lenght + 44 ANGLE m_aPitchLenght = 0.0f, // pitch lenght + 45 ANGLE m_aBankLenght = 0.0f, // bank lenght + + // sound target + 50 CEntityPointer m_penSoundStart "Sound start entity" 'Q', // sound start entity + 51 CEntityPointer m_penSoundStop "Sound stop entity" 'Z', // sound stop entity + 52 CEntityPointer m_penSoundFollow "Sound follow entity" 'F', // sound follow entity + 53 CSoundObject m_soStart, + 54 CSoundObject m_soStop, + 55 CSoundObject m_soFollow, + + + 60 CEntityPointer m_penMirror0 "Mirror 0" 'M', + 61 CEntityPointer m_penMirror1 "Mirror 1", + 62 CEntityPointer m_penMirror2 "Mirror 2", + 63 CEntityPointer m_penMirror3 "Mirror 3", + 64 CEntityPointer m_penMirror4 "Mirror 4", + + 65 FLOAT m_fHealth "Health" 'H' = -1.0f, + 66 BOOL m_bBlowupByBull "Blowup by Bull" = FALSE, // special feature for bull crushing doors + // send event on touch + 67 enum EventEType m_eetBlowupEvent "Blowup Event - Type" = EET_IGNORE, // type of event to send + 68 CEntityPointer m_penBlowupEvent "Blowup Event - Target" COLOR(C_BLACK|0xFF), // target to send event to + 69 BOOL m_bZoning "Zoning" 'Z' =FALSE, + 70 BOOL m_bMoveOnDamage "Move on damage" = FALSE, // move when recive damage + 71 FLOAT m_fTouchDamage "Touch damage" = 0.0f, + 72 COLOR m_colDebrises "Color of debrises" = C_WHITE, + 74 INDEX m_ctDebrises "Debris count" = 12, + 75 FLOAT m_fCandyEffect "Debris blow power" = 0.0f, + 76 FLOAT m_fCubeFactor "Cube factor" = 1.0f, + 77 BOOL m_bBlowupByDamager "Blowup by Damager" = FALSE, // if only damager can destroy brush + + 81 flags ClasificationBits m_cbClassificationBits "Clasification bits" 'C' = 0, + 82 flags VisibilityBits m_vbVisibilityBits "Visibility bits" 'V' = 0, + + +components: + +// ************** STONE PARTS ************** + 14 model MODEL_STONE "Models\\Effects\\Debris\\Stone\\Stone.mdl", + 15 texture TEXTURE_STONE "Models\\Effects\\Debris\\Stone\\Stone.tex", + 16 class CLASS_DEBRIS "Classes\\Debris.ecl", + 4 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + + +functions: + + // get visibility tweaking bits + ULONG GetVisTweaks(void) + { + return m_cbClassificationBits|m_vbVisibilityBits; + } + + void Precache(void) + { + PrecacheClass(CLASS_DEBRIS); + PrecacheModel(MODEL_STONE); + PrecacheTexture(TEXTURE_STONE); + } + /* Get force in given point. */ + void GetForce(INDEX iForce, const FLOAT3D &vPoint, + CForceStrength &fsGravity, CForceStrength &fsField) + { + GetDefaultForce(iForce, vPoint, fsGravity, fsField); + } + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + if( m_bMoveOnDamage) + { + EHit eHit; + SendEvent( eHit); + return; + } + + // send event on damage + if(m_tdeSendEventOnDamage!=TDE_TOUCHONLY && CanReactOnEntity(penInflictor)) { + SendToTarget(m_penTouchEvent, m_eetTouchEvent, penInflictor); + } + + // if not destroyable + if(m_fHealth<0) { + // ignore damages + return; + } + + // if special feature for bull crushing doors + if (m_bBlowupByBull) + { + // if impact by bull + if( dmtType == DMT_IMPACT && IsOfClass(penInflictor, "Werebull")) + { + // receive the damage so large to blowup + CMovableBrushEntity::ReceiveDamage(penInflictor, dmtType, m_fHealth*2, vHitPoint, vDirection); + // kill the bull in place, but make sure it doesn't blow up + ((CLiveEntity*)penInflictor)->SetHealth(0.0f); + InflictDirectDamage(penInflictor, this, DMT_IMPACT, 1.0f, + GetPlacement().pl_PositionVector, FLOAT3D(0,1,0)); + } + } + else if(m_bBlowupByDamager) + { + if( dmtType == DMT_DAMAGER) + { + CMovableBrushEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + } + else + { + // react only on explosions + if( (dmtType == DMT_EXPLOSION) || + (dmtType == DMT_PROJECTILE) || + (dmtType == DMT_CANNONBALL) ) + { + CMovableBrushEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + } + }; + + // adjust angle + void AdjustAngle(ANGLE &a) { + if (m_bInverseRotate) { + if (a>0) { a = a - 360; } + else if (a<0) { a = 360 + a; } + } + }; + + + /* Check if entity is moved on a route set up by its targets. */ + BOOL MovesByTargetedRoute(CTString &strTargetProperty) const { + strTargetProperty = "Target"; + return TRUE; + }; + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\MovingBrushMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("->"); + if (m_penTarget!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", m_penTarget->GetName()); + } + return m_strDescription; + } + /* Get mirror type name, return empty string if not used. */ + const CTString &GetMirrorName(INDEX iMirror) + { + static const CTString strDummyName(""); + static const CTString strMarkerUnused("Marker not set"); + if (iMirror==0) { + return strDummyName; + } + + switch (iMirror) { + case 1: { static const CTString str("std mirror 1"); return str; }; break; + case 2: { static const CTString str("std mirror 2"); return str; }; break; + case 3: { static const CTString str("std mirror 3"); return str; }; break; + case 4: { static const CTString str("std mirror 4"); return str; }; break; + case 5: { static const CTString str("std mirror 5"); return str; }; break; + case 6: { static const CTString str("std mirror 6"); return str; }; break; + case 7: { static const CTString str("std mirror 7"); return str; }; break; + case 8: { static const CTString str("std mirror 8"); return str; }; break; + default: { + iMirror-=9; + INDEX ctMirrorMarkers = &m_penMirror4-&m_penMirror0; + if (iMirrorGetMirrorName(); + } else { + return strMarkerUnused; + } + } + } + } + return strDummyName; + } + + /* Get mirror, return FALSE for none. */ + BOOL GetMirror(INDEX iMirror, class CMirrorParameters &mpMirror) + { + if (iMirror==0) { + return FALSE; + } + if (iMirror>=1 && iMirror<=8) { + mpMirror.mp_ulFlags = 0; + return TRUE; + } + iMirror-=9; + INDEX ctMirrorMarkers = &m_penMirror4-&m_penMirror0; + if (iMirrorGetMirror(mpMirror); + return TRUE; + } + } + return FALSE; + } + + // pre moving + void PreMoving() { + if (m_bMoveToMarker) { + const FLOAT3D &vTarget = m_penTarget->GetPlacement().pl_PositionVector; + const ANGLE3D &aTarget = m_penTarget->GetPlacement().pl_OrientationAngle; + const FLOAT3D &vSource = GetPlacement().pl_PositionVector; + const ANGLE3D &aSource = GetPlacement().pl_OrientationAngle; + + // translation + FLOAT3D vSpeed = (vTarget-vSource)/_pTimer->TickQuantum; + // X axis + if (Abs(vSpeed(1))0) { + vSpeed(1) = m_vDesiredTranslation(1); + } + // Y axis + if (Abs(vSpeed(2))0) { + vSpeed(2) = m_vDesiredTranslation(2); + } + // Z axis + if (Abs(vSpeed(3))0) { + vSpeed(3) = m_vDesiredTranslation(3); + } + + // rotation + ANGLE3D aSpeed; + aSpeed(1) = NormalizeAngle(aTarget(1)-aSource(1)); // normalize angle + AdjustAngle(aSpeed(1)); // adjust angle (inverse rotation) + aSpeed(1) = Abs(aSpeed(1)) * m_aHLimitSign; // set sign (direction) + aSpeed(1) /= _pTimer->TickQuantum; // transform to tick speed + aSpeed(2) = NormalizeAngle(aTarget(2)-aSource(2)); + AdjustAngle(aSpeed(2)); + aSpeed(2) = Abs(aSpeed(2)) * m_aPLimitSign; + aSpeed(2) /= _pTimer->TickQuantum; + aSpeed(3) = NormalizeAngle(aTarget(3)-aSource(3)); + AdjustAngle(aSpeed(3)); + aSpeed(3) = Abs(aSpeed(3)) * m_aBLimitSign; + aSpeed(3) /= _pTimer->TickQuantum; + // Heading + if (Abs(aSpeed(1))0) { + aSpeed(1) = m_aDesiredRotation(1); + } + // Pitch + if (Abs(aSpeed(2))0) { + aSpeed(2) = m_aDesiredRotation(2); + } + // Banking + if (Abs(aSpeed(3))0) { + aSpeed(3) = m_aDesiredRotation(3); + } + + // stop moving ? + if (vSpeed(1)==0.0f && vSpeed(2)==0.0f && vSpeed(3)==0.0f + && ((m_tmBankingRotation!=0 || m_bNoRotation)||(aSpeed(1)==0.0f && aSpeed(2)==0.0f && aSpeed(3)==0.0f)) ) + { + // stop brush + ForceFullStop(); + // stop PreMoving check + m_bMoveToMarker = FALSE; + // this EEnd event will end MoveToMarker autowait() and return to MoveBrush + SendEvent(EEnd()); + + // move brush + } else { + SetDesiredTranslation(vSpeed); + if (m_bRotating) { + MaybeActivateRotation(); + } else if (!m_tmBankingRotation && !m_bNoRotation) { + SetDesiredRotation(aSpeed); + } else { + SetDesiredRotation(ANGLE3D(0,0,0)); + } + } + + } + CMovableBrushEntity::PreMoving(); + }; + + + // load marker parameters + BOOL LoadMarkerParameters() { + if (m_penTarget==NULL) { + return FALSE; + } + + if (!IsOfClass(m_penTarget, "Moving Brush Marker")) { + WarningMessage("Entity '%s' is not of Moving Brush Marker class!", m_penTarget->GetName()); + return FALSE; + } + + CMovingBrushMarker &mbm = (CMovingBrushMarker&) *m_penTarget; + if (mbm.m_penTarget==NULL) { + return FALSE; + } + + // speed + if (mbm.m_fSpeed > 0.0f) { m_fSpeed = mbm.m_fSpeed; } + + // wait time + if (mbm.m_fWaitTime >= 0.0f) { m_fWaitTime = mbm.m_fWaitTime; } + + // inverse rotate + m_bInverseRotate = mbm.m_bInverseRotate; + + // move on touch + SetBoolFromBoolEType(m_bMoveOnTouch, mbm.m_betMoveOnTouch); + + // stop moving + m_bStopMoving = mbm.m_bStopMoving; + + // block damage + if (mbm.m_fBlockDamage >= 0.0f) { + m_fBlockDamage = mbm.m_fBlockDamage; + } + + // touch event + if (mbm.m_penTouchEvent != NULL) { + m_penTouchEvent = mbm.m_penTouchEvent; + m_eetTouchEvent = mbm.m_eetTouchEvent; + } + + // marker event -> SEND ALWAYS (if target is valid) !!! + SendToTarget(mbm.m_penMarkerEvent, mbm.m_eetMarkerEvent); + + // sound entity + if (mbm.m_penSoundStart!=NULL) { + m_penSoundStart = mbm.m_penSoundStart; + } + if (mbm.m_penSoundStop!=NULL) { + m_penSoundStop = mbm.m_penSoundStop; + } + if (mbm.m_penSoundFollow!=NULL) { + m_penSoundFollow = mbm.m_penSoundFollow; + } + + m_bNoRotation = mbm.m_bNoRotation; + + if (mbm.m_tmBankingRotation>=0.0f) { + m_tmBankingRotation = mbm.m_tmBankingRotation; + if (!mbm.m_bBankingClockwise) { + m_tmBankingRotation *= -1; + } + } + + return TRUE; + }; + + + // test if this door reacts on this entity + BOOL CanReactOnEntity(CEntity *pen) + { + if (pen==NULL) { + return FALSE; + } + // never react on non-live or dead entities + if (!(pen->GetFlags()&ENF_ALIVE)) { + return FALSE; + } + + if (m_bPlayersOnly && !IsDerivedFromClass(pen, "Player")) { + return FALSE; + } + + return TRUE; + } + + // play start sound + void PlayStartSound(void) { + // if sound entity exists + if (m_penSoundStart!=NULL) { + CSoundHolder &sh = (CSoundHolder&)*m_penSoundStart; + m_soStart.Set3DParameters(FLOAT(sh.m_rFallOffRange), FLOAT(sh.m_rHotSpotRange), sh.m_fVolume, 1.0f); + PlaySound(m_soStart, sh.m_fnSound, sh.m_iPlayType); + } + }; + + // play stop sound + void PlayStopSound(void) { + // if sound entity exists + if (m_penSoundStop!=NULL) { + CSoundHolder &sh = (CSoundHolder&)*m_penSoundStop; + m_soStop.Set3DParameters(FLOAT(sh.m_rFallOffRange), FLOAT(sh.m_rHotSpotRange), sh.m_fVolume, 1.0f); + PlaySound(m_soStop, sh.m_fnSound, sh.m_iPlayType); + } + }; + + // play follow sound + void PlayFollowSound(void) { + // if sound entity exists + if (m_penSoundFollow!=NULL) { + CSoundHolder &sh = (CSoundHolder&)*m_penSoundFollow; + m_soFollow.Set3DParameters(FLOAT(sh.m_rFallOffRange), FLOAT(sh.m_rHotSpotRange), sh.m_fVolume, 1.0f); + PlaySound(m_soFollow, sh.m_fnSound, sh.m_iPlayType); + } + }; + + // stop follow sound + void StopFollowSound(void) { + m_soFollow.Stop(); + }; + + + void MovingOn(void) + { + if (m_bMoving) { + return; + } + if (m_bVeryBigBrush) { + SetCollisionFlags(ECF_BRUSH|ECF_IGNOREMODELS); + } + m_bMoving = TRUE; + } + void MovingOff(void) + { + if (!m_bMoving) { + return; + } + if (m_bVeryBigBrush) { + SetCollisionFlags(ECF_BRUSH); + } + m_bMoving = FALSE; + } + + void MaybeActivateRotation(void) + { + if (m_tmBankingRotation!=0) { + m_bRotating = TRUE; + SetDesiredRotation(ANGLE3D(0.0f,0.0f,360.0f/m_tmBankingRotation)); + } + else { + m_bRotating = FALSE; + } + } + + void DeactivateRotation(void) + { + m_bRotating = FALSE; + SetDesiredRotation(ANGLE3D(0.0f,0.0f,0.0f)); + } + + void SetCombinedRotation(ANGLE3D aRotAngle, ANGLE3D aAddAngle) + { + aRotAngle(1) += aAddAngle(1); + aRotAngle(2) += aAddAngle(2); + aRotAngle(3) += aAddAngle(3); + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CMovingBrush) - sizeof(CMovableBrushEntity) + CMovableBrushEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strName.Length(); + slUsedMemory += m_strDescription.Length(); + slUsedMemory += 3* sizeof(CSoundObject); // 3 of them + return slUsedMemory; + } + + + +procedures: + + + MoveToMarker() { + // move to target + const FLOAT3D &vTarget = m_penTarget->GetPlacement().pl_PositionVector; + const ANGLE3D &aTarget = m_penTarget->GetPlacement().pl_OrientationAngle; + const FLOAT3D &vSource = GetPlacement().pl_PositionVector; + const ANGLE3D &aSource = GetPlacement().pl_OrientationAngle; + + // set new translation + m_vDesiredTranslation = (vTarget-vSource)/m_fSpeed; + m_fXLimitSign = Sgn(vTarget(1)-vSource(1)); + m_fYLimitSign = Sgn(vTarget(2)-vSource(2)); + m_fZLimitSign = Sgn(vTarget(3)-vSource(3)); + + // set new rotation + // heading + ANGLE aDelta = NormalizeAngle(aTarget(1)-aSource(1)); + AdjustAngle(aDelta); + m_aDesiredRotation(1) = aDelta/m_fSpeed; + m_aHLimitSign = Sgn(aDelta); + // pitch + aDelta = NormalizeAngle(aTarget(2)-aSource(2)); + AdjustAngle(aDelta); + m_aDesiredRotation(2) = aDelta/m_fSpeed; + m_aPLimitSign = Sgn(aDelta); + // banking + aDelta = NormalizeAngle(aTarget(3)-aSource(3)); + AdjustAngle(aDelta); + m_aDesiredRotation(3) = aDelta/m_fSpeed; + m_aBLimitSign = Sgn(aDelta); + + // start moving + m_bMoveToMarker = TRUE; + SetDesiredTranslation(m_vDesiredTranslation); + if (m_bRotating) { + MaybeActivateRotation(); + } else if (!m_tmBankingRotation) { + SetDesiredRotation(m_aDesiredRotation); + } + + // PreMoving will send EEnd event to end + wait() { + on (EBegin) : { resume; } + on (EStop) : { + //SetCollisionFlags(ECF_IMMATERIAL); + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + if (m_tmBankingRotation==0) { + SetDesiredRotation(ANGLE3D(0.0f, 0.0f, 0.0f)); + } + m_bForceStop = TRUE; + // stop PreMoving check + m_bMoveToMarker = FALSE; + m_bStopMoving = TRUE; + + return EEnd(); + } + // move is obstructed + on (EBlock eBlock) : { + // inflict damage to entity that block brush + InflictDirectDamage(eBlock.penOther, this, DMT_BRUSH, m_fBlockDamage, + FLOAT3D(0.0f,0.0f,0.0f), (FLOAT3D &)eBlock.plCollision); + if (m_ebaAction == BA_BOUNCE) { + // change direction for two ticks + SetDesiredTranslation(-m_vDesiredTranslation); + if (m_bRotating) { + MaybeActivateRotation(); + } else if (!m_tmBankingRotation) { + SetDesiredRotation(-m_aDesiredRotation); + } + // wait for two ticks and reset direction + call BounceObstructed(); + } else if (m_ebaAction == BA_SKIPMARKER) { + // stop moving brush + ForceFullStop(); + // stop PreMoving check + m_bMoveToMarker = FALSE; + // skip this marker and move to next one + m_bSkipMarker = TRUE; + return EEnd(); + } + resume; + } + } + } + + BounceObstructed() { + autowait(0.2f); + // return to standard direction + SetDesiredTranslation(m_vDesiredTranslation); + if (m_bRotating) { + SetDesiredRotation(ANGLE3D(0.0f, 0.0f, 360.0f/m_tmBankingRotation)); + } else if (!m_tmBankingRotation) { + SetDesiredRotation(m_aDesiredRotation); + } + return; + } + + /*Rotating() + { + if (m_bAutoStart) { + jump RotActive(); + } else { + jump RotInactive(); + } + } + + RotInactive() + { + SetDesiredRotation(ANGLE3D(0,0,0)); + wait() { + on (EActivate) : { + jump RotActive(); + } + otherwise() : { + resume; + } + }; + } + + RotActive() + { + SetDesiredRotation(ANGLE3D(0,0,360.0f/m_tmBankingRotation)); + + wait() { + on (EDeactivate) : { + jump RotInactive(); + } + otherwise() : { + resume; + } + }; + }*/ + + // move brush + MoveBrush() + { + if (m_penTarget==NULL) { + MovingOff(); + return; + } + + MovingOn(); + + // move through markers + do { + + if (m_bForceStop==FALSE) + { + // new moving target + m_penTarget = m_penTarget->GetTarget(); + } + else { + m_bForceStop=FALSE; + } + + if (m_penTarget==NULL) { + MovingOff(); + return EVoid(); + } + + // skip this marker / ignore wait time + if (m_bSkipMarker) { + m_bSkipMarker = FALSE; + // wait for a while + } else if (m_fWaitTime > 0.0f) { + //autowait(m_fWaitTime); + wait(m_fWaitTime) { + on (EBegin) : { resume; } + on (EStop) : { + //SetCollisionFlags(ECF_IMMATERIAL); + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + if (m_tmBankingRotation==0) { + SetDesiredRotation(ANGLE3D(0.0f, 0.0f, 0.0f)); + } + m_bForceStop = TRUE; + // stop PreMoving check + m_bMoveToMarker = FALSE; + m_bStopMoving = TRUE; + + resume; }//return; } + on (ETimer) : { stop; } + } + } + + if (!m_bForceStop) { + MaybeActivateRotation(); + + PlayStartSound(); + PlayFollowSound(); + autocall MoveToMarker() EEnd; + StopFollowSound(); + PlayStopSound(); + } + + // load marker parameters or stop moving if there is no marker + if (!m_bForceStop) { + m_bValidMarker = LoadMarkerParameters(); + } + + // skip this marker / ignore stop moving + if (m_bSkipMarker) { + m_bStopMoving = FALSE; + } + } while (!m_bStopMoving && m_bValidMarker && !m_bForceStop); + MovingOff(); + return; + } + + TeleportToStopMarker() + { + MovingOn(); + + INDEX ctMarkers=0; + // new moving target + CMovingBrushMarker *pmbm = (CMovingBrushMarker *) &*m_penTarget; + while( pmbm!=NULL && IsOfClass(pmbm->m_penTarget, "Moving Brush Marker") && !pmbm->m_bStopMoving && ctMarkers<50) + { + pmbm = (CMovingBrushMarker *) &*pmbm->m_penTarget; + ctMarkers++; + } + + if( pmbm!=NULL && IsOfClass(pmbm, "Moving Brush Marker") && ctMarkers<50) + { + SetPlacement(pmbm->GetPlacement()); + en_plLastPlacement=pmbm->GetPlacement(); + ForceFullStop(); + m_soStart.Stop(); + m_soStop.Stop(); + m_soFollow.Stop(); + } + + // stop PreMoving check + m_bMoveToMarker = FALSE; + MovingOff(); + return EReturn(); + } + + Main() { + // declare yourself as a brush + InitAsBrush(); + SetPhysicsFlags(EPF_BRUSH_MOVING); + SetCollisionFlags(ECF_BRUSH); + SetHealth(m_fHealth); + + // set zoning flag + if (m_bZoning) { + SetFlags(GetFlags()|ENF_ZONING); + } else { + SetFlags(GetFlags()&~ENF_ZONING); + } + + + // set dynamic shadows as needed + if (m_bDynamicShadows) { + SetFlags(GetFlags()|ENF_DYNAMICSHADOWS); + } else { + SetFlags(GetFlags()&~ENF_DYNAMICSHADOWS); + } + + // stop moving brush + ForceFullStop(); + + autowait(0.1f); + + // load marker parameters + m_bValidMarker = LoadMarkerParameters(); + + /*if (m_tmBankingRotation!=0) { + jump Rotating(); + }*/ + + // start moving + wait() { + on (EBegin) : { + if (m_bAutoStart) { + // if not already moving and have target + MaybeActivateRotation(); + if(!m_bMoving && m_bValidMarker) { + call MoveBrush(); + } + } + resume; + } + on (EHit eHit) : { + if (!m_bMoving) { + MaybeActivateRotation(); + call MoveBrush(); + } + resume; + } + // move on touch + on (ETouch eTouch) : { + // inflict damage if required + if( m_fTouchDamage != 0.0f) + { + InflictDirectDamage( eTouch.penOther, this, DMT_SPIKESTAB, m_fTouchDamage, + eTouch.penOther->GetPlacement().pl_PositionVector, eTouch.plCollision); + } + // send event on touch + if(m_tdeSendEventOnDamage!=TDE_DAMAGEONLY && CanReactOnEntity(eTouch.penOther)) { + SendToTarget(m_penTouchEvent, m_eetTouchEvent); + } + // if not already moving + if(!m_bMoving) { + // move brush + if (m_bMoveOnTouch && CanReactOnEntity(eTouch.penOther) && m_bValidMarker) { + MaybeActivateRotation(); + call MoveBrush(); + } + } + // if special feature for bull crushing doors + if (m_bBlowupByBull) { + // if hit by bull + if (IsOfClass(eTouch.penOther, "Werebull")) { + // calculate speed along impact normal + FLOAT fImpactSpeed = + ((CMovableEntity&)*eTouch.penOther).en_vCurrentTranslationAbsolute% + -(FLOAT3D&)eTouch.plCollision; + + // if strong collision + if (fImpactSpeed>m_fHealth) { + // receive artificial impact damage + ReceiveDamage(eTouch.penOther, DMT_IMPACT, m_fHealth*2, + FLOAT3D(0,0,0), FLOAT3D(0,0,0)); + } + } + } + resume; + } + on (EBlock eBlock) : { + // inflict damage to entity that block brush + InflictDirectDamage(eBlock.penOther, this, DMT_BRUSH, m_fBlockDamage, + FLOAT3D(0.0f,0.0f,0.0f), (FLOAT3D &)eBlock.plCollision); + if (m_ebaAction == BA_BOUNCE) { + // change direction for two ticks + SetDesiredTranslation(-m_vDesiredTranslation); + if (m_bRotating) { + SetDesiredRotation(-ANGLE3D(0.0f, 0.0f, 360.0f/m_tmBankingRotation)); + } else if (!m_tmBankingRotation) { + SetDesiredRotation(-m_aDesiredRotation); + } + + // wait for two ticks and reset direction + call BounceObstructed(); + } + resume; + } + // move on start (usually trigger) + on (EStart) : { + // if not already moving and have target + if(!m_bMoving && m_bValidMarker) { + call MoveBrush(); + } + resume; + } + on (EStop) : { + //SetCollisionFlags(ECF_IMMATERIAL); + resume; + } + on (ETeleportMovingBrush) : { + call TeleportToStopMarker(); + resume; + } + on (ETrigger) : { + // if not already moving and have target + if(!m_bMoving && m_bValidMarker) { + call MoveBrush(); + } + resume; + } + on (EActivate) : { + if (!m_bRotating) { + MaybeActivateRotation(); + } + resume; + } + on (EDeactivate) : { + DeactivateRotation(); + resume; + } + on (EDeath eDeath) : { + // get your size + FLOATaabbox3D box; + GetSize(box); + if( m_ctDebrises>0) + { + FLOAT fEntitySize = pow(box.Size()(1)*box.Size()(2)*box.Size()(3)/m_ctDebrises, 1.0f/3.0f)*m_fCubeFactor; + + Debris_Begin(EIBT_ROCK, DPT_NONE, BET_NONE, fEntitySize, FLOAT3D(1.0f,2.0f,3.0f), + FLOAT3D(0,0,0), 1.0f+m_fCandyEffect/2.0f, m_fCandyEffect, m_colDebrises); + for(INDEX iDebris = 0; iDebrisSendEvent( EBrushDestroyed()); + } + // send event to blowup target + SendToTarget(m_penBlowupEvent, m_eetBlowupEvent, eDeath.eLastDamage.penInflictor); + + // make sure it doesn't loop with destroying itself + m_tdeSendEventOnDamage = TDE_TOUCHONLY; + m_fHealth = -1; + m_bMoveOnDamage = FALSE; + ForceFullStop(); + SetDefaultProperties(); + + // notify engine to kickstart entities that are cached in stationary position, + // before we turn off, so they can fall + NotifyCollisionChanged(); + + SetFlags( GetFlags()|ENF_HIDDEN); + SetCollisionFlags(ECF_IMMATERIAL); + + // for each child of this entity + {FOREACHINLIST(CEntity, en_lnInParent, en_lhChildren, itenChild) { + // send it destruction event + itenChild->SendEvent(ERangeModelDestruction()); + }} + + stop; + } + } + return; + } +}; diff --git a/Sources/EntitiesMP/MovingBrush.h b/Sources/EntitiesMP/MovingBrush.h new file mode 100644 index 0000000..1251ce0 --- /dev/null +++ b/Sources/EntitiesMP/MovingBrush.h @@ -0,0 +1,224 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_MovingBrush_INCLUDED +#define _EntitiesMP_MovingBrush_INCLUDED 1 +#include +#include +#include +#include +#define EVENTCODE_EHit 0x00650000 +class DECL_DLL EHit : public CEntityEvent { +public: +EHit(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EHit &e) { e = EHit(); } ; +#define EVENTCODE_EBrushDestroyed 0x00650001 +class DECL_DLL EBrushDestroyed : public CEntityEvent { +public: +EBrushDestroyed(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EBrushDestroyed &e) { e = EBrushDestroyed(); } ; +extern DECL_DLL CEntityPropertyEnumType BlockAction_enum; +enum BlockAction { + BA_NONE = 0, + BA_BOUNCE = 1, + BA_SKIPMARKER = 2, +}; +DECL_DLL inline void ClearToDefault(BlockAction &e) { e = (BlockAction)0; } ; +extern DECL_DLL CEntityPropertyEnumType TouchOrDamageEvent_enum; +enum TouchOrDamageEvent { + TDE_TOUCHONLY = 0, + TDE_DAMAGEONLY = 1, + TDE_BOTH = 2, +}; +DECL_DLL inline void ClearToDefault(TouchOrDamageEvent &e) { e = (TouchOrDamageEvent)0; } ; +extern "C" DECL_DLL CDLLEntityClass CMovingBrush_DLLClass; +class CMovingBrush : public CMovableBrushEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CEntityPointer m_penTarget; + BOOL m_bAutoStart; + FLOAT m_fSpeed; + FLOAT m_fWaitTime; + BOOL m_bMoveOnTouch; + enum BlockAction m_ebaAction; + FLOAT m_fBlockDamage; + BOOL m_bPlayersOnly; + BOOL m_bDynamicShadows; + BOOL m_bVeryBigBrush; + enum EventEType m_eetTouchEvent; + CEntityPointer m_penTouchEvent; + enum TouchOrDamageEvent m_tdeSendEventOnDamage; + CEntityPointer m_penSwitch; + enum EventEType m_eetMarkerEvent; + CEntityPointer m_penMarkerEvent; + FLOAT m_tmBankingRotation; + BOOL m_bMoving; + BOOL m_bRotating; + BOOL m_bForceStop; + BOOL m_bNoRotation; + FLOAT3D m_vDesiredTranslation; + ANGLE3D m_aDesiredRotation; + BOOL m_bInverseRotate; + BOOL m_bStopMoving; + BOOL m_bMoveToMarker; + BOOL m_bSkipMarker; + BOOL m_bValidMarker; + FLOAT m_fXLimitSign; + FLOAT m_fYLimitSign; + FLOAT m_fZLimitSign; + ANGLE m_aHLimitSign; + ANGLE m_aPLimitSign; + ANGLE m_aBLimitSign; + FLOAT3D m_vStartTranslation; + ANGLE3D m_aStartRotation; + FLOAT m_fCourseLength; + ANGLE m_aHeadLenght; + ANGLE m_aPitchLenght; + ANGLE m_aBankLenght; + CEntityPointer m_penSoundStart; + CEntityPointer m_penSoundStop; + CEntityPointer m_penSoundFollow; + CSoundObject m_soStart; + CSoundObject m_soStop; + CSoundObject m_soFollow; + CEntityPointer m_penMirror0; + CEntityPointer m_penMirror1; + CEntityPointer m_penMirror2; + CEntityPointer m_penMirror3; + CEntityPointer m_penMirror4; + FLOAT m_fHealth; + BOOL m_bBlowupByBull; + enum EventEType m_eetBlowupEvent; + CEntityPointer m_penBlowupEvent; + BOOL m_bZoning; + BOOL m_bMoveOnDamage; + FLOAT m_fTouchDamage; + COLOR m_colDebrises; + INDEX m_ctDebrises; + FLOAT m_fCandyEffect; + FLOAT m_fCubeFactor; + BOOL m_bBlowupByDamager; + ULONG m_cbClassificationBits; + ULONG m_vbVisibilityBits; + +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +ULONG GetVisTweaks(void); + +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void Precache(void); + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void GetForce(INDEX iForce,const FLOAT3D & vPoint, +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +CForceStrength & fsGravity,CForceStrength & fsField); + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void AdjustAngle(ANGLE & a); + +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const CTString & GetDescription(void)const; + +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +const CTString & GetMirrorName(INDEX iMirror); + +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BOOL GetMirror(INDEX iMirror,class CMirrorParameters & mpMirror); + +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void PreMoving(); + +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BOOL LoadMarkerParameters(); + +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BOOL CanReactOnEntity(CEntity * pen); + +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void PlayStartSound(void); + +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void PlayStopSound(void); + +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void PlayFollowSound(void); + +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void StopFollowSound(void); + +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void MovingOn(void); + +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void MovingOff(void); + +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void MaybeActivateRotation(void); + +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void DeactivateRotation(void); + +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +void SetCombinedRotation(ANGLE3D aRotAngle,ANGLE3D aAddAngle); + +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +SLONG GetUsedMemory(void); +#define STATE_CMovingBrush_MoveToMarker 0x00650002 + BOOL +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MoveToMarker(const CEntityEvent &__eeInput); + BOOL H0x00650003_MoveToMarker_01(const CEntityEvent &__eeInput); + BOOL H0x00650004_MoveToMarker_02(const CEntityEvent &__eeInput); +#define STATE_CMovingBrush_BounceObstructed 0x00650005 + BOOL +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BounceObstructed(const CEntityEvent &__eeInput); + BOOL H0x00650006_BounceObstructed_01(const CEntityEvent &__eeInput); + BOOL H0x00650007_BounceObstructed_02(const CEntityEvent &__eeInput); +#define STATE_CMovingBrush_MoveBrush 0x00650008 + BOOL +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MoveBrush(const CEntityEvent &__eeInput); + BOOL H0x00650009_MoveBrush_01(const CEntityEvent &__eeInput); + BOOL H0x0065000a_MoveBrush_02(const CEntityEvent &__eeInput); + BOOL H0x0065000b_MoveBrush_03(const CEntityEvent &__eeInput); + BOOL H0x0065000c_MoveBrush_04(const CEntityEvent &__eeInput); + BOOL H0x0065000d_MoveBrush_05(const CEntityEvent &__eeInput); + BOOL H0x0065000e_MoveBrush_06(const CEntityEvent &__eeInput); + BOOL H0x0065000f_MoveBrush_07(const CEntityEvent &__eeInput); + BOOL H0x00650010_MoveBrush_08(const CEntityEvent &__eeInput); + BOOL H0x00650011_MoveBrush_09(const CEntityEvent &__eeInput); + BOOL H0x00650012_MoveBrush_10(const CEntityEvent &__eeInput); +#define STATE_CMovingBrush_TeleportToStopMarker 0x00650013 + BOOL +#line 784 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +TeleportToStopMarker(const CEntityEvent &__eeInput); +#define STATE_CMovingBrush_Main 1 + BOOL +#line 813 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00650014_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00650015_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00650016_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00650017_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_MovingBrush_INCLUDED diff --git a/Sources/EntitiesMP/MovingBrushMarker.cpp b/Sources/EntitiesMP/MovingBrushMarker.cpp new file mode 100644 index 0000000..2e51ffd --- /dev/null +++ b/Sources/EntitiesMP/MovingBrushMarker.cpp @@ -0,0 +1,69 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" + +#include "StdH.h" + +#include +#include +void CMovingBrushMarker::SetDefaultProperties(void) { + m_bInverseRotate = FALSE ; + m_fSpeed = -1.0f; + m_fWaitTime = -1.0f; + m_bStopMoving = FALSE ; + m_betMoveOnTouch = BET_IGNORE ; + m_fBlockDamage = -1.0f; + m_tmBankingRotation = -1.0f; + m_bBankingClockwise = TRUE ; + m_bNoRotation = FALSE ; + m_eetMarkerEvent = EET_IGNORE ; + m_penMarkerEvent = NULL; + m_eetTouchEvent = EET_IGNORE ; + m_penTouchEvent = NULL; + m_penSoundStart = NULL; + m_penSoundStop = NULL; + m_penSoundFollow = NULL; + CMarker::SetDefaultProperties(); +} + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +BOOL CMovingBrushMarker::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +fnmMarkerClass = CTFILENAME ("Classes\\MovingBrushMarker.ecl"); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +strTargetProperty = "Target"; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +return TRUE ; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +} + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +SLONG CMovingBrushMarker::GetUsedMemory(void) +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +{ +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +return (sizeof (CMovingBrushMarker ) - sizeof (CMarker ) + CMarker :: GetUsedMemory ()); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +} +BOOL CMovingBrushMarker:: +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMovingBrushMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMovingBrushMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +InitAsEditorModel (); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +SetModel (MODEL_MARKER ); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/MovingBrushMarker.es b/Sources/EntitiesMP/MovingBrushMarker.es new file mode 100644 index 0000000..bf35049 --- /dev/null +++ b/Sources/EntitiesMP/MovingBrushMarker.es @@ -0,0 +1,79 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +102 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; + +class CMovingBrushMarker: CMarker { +name "Moving Brush Marker"; +thumbnail "Thumbnails\\MovingBrushMarker.tbn"; + +properties: + + 1 BOOL m_bInverseRotate "Inverse Rotate" 'R' = FALSE, + 2 FLOAT m_fSpeed "Speed" 'S' = -1.0f, + 3 FLOAT m_fWaitTime "Wait time" 'W' = -1.0f, + 4 BOOL m_bStopMoving "Stop moving" 'O' = FALSE, + 6 enum BoolEType m_betMoveOnTouch "Move on touch" 'M' = BET_IGNORE, + 7 FLOAT m_fBlockDamage "Block damage" 'D' = -1.0f, + 8 FLOAT m_tmBankingRotation "Banking rotation speed" = -1.0f, + 9 BOOL m_bBankingClockwise "Banking rotation clockwise" = TRUE, + 14 BOOL m_bNoRotation "Don't use marker orientation" = FALSE, + + // send event on marker + 10 enum EventEType m_eetMarkerEvent "Marker Event - Type" 'J' = EET_IGNORE, // type of event to send + 11 CEntityPointer m_penMarkerEvent "Marker Event - Target" 'K', // target to send event to + + // send event on touch + 16 enum EventEType m_eetTouchEvent "Touch Event - Type" 'U' = EET_IGNORE, // type of event to send + 17 CEntityPointer m_penTouchEvent "Touch Event - Target" 'I', // target to send event to + + // sound target + 20 CEntityPointer m_penSoundStart "Sound start entity" 'Q', // sound start entity + 21 CEntityPointer m_penSoundStop "Sound stop entity" 'Z', // sound stop entity + 22 CEntityPointer m_penSoundFollow "Sound follow entity" 'F', // sound follow entity + + +components: + + 1 model MODEL_MARKER "Models\\Editor\\MovingBrushMarker.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\GravityMarker.tex" + + +functions: + + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\MovingBrushMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + return( sizeof(CMovingBrushMarker) - sizeof(CMarker) + CMarker::GetUsedMemory()); + } + + +procedures: + + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + return; + } +}; + diff --git a/Sources/EntitiesMP/MovingBrushMarker.h b/Sources/EntitiesMP/MovingBrushMarker.h new file mode 100644 index 0000000..4e177da --- /dev/null +++ b/Sources/EntitiesMP/MovingBrushMarker.h @@ -0,0 +1,39 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_MovingBrushMarker_INCLUDED +#define _EntitiesMP_MovingBrushMarker_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CMovingBrushMarker_DLLClass; +class CMovingBrushMarker : public CMarker { +public: + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bInverseRotate; + FLOAT m_fSpeed; + FLOAT m_fWaitTime; + BOOL m_bStopMoving; + enum BoolEType m_betMoveOnTouch; + FLOAT m_fBlockDamage; + FLOAT m_tmBankingRotation; + BOOL m_bBankingClockwise; + BOOL m_bNoRotation; + enum EventEType m_eetMarkerEvent; + CEntityPointer m_penMarkerEvent; + enum EventEType m_eetTouchEvent; + CEntityPointer m_penTouchEvent; + CEntityPointer m_penSoundStart; + CEntityPointer m_penSoundStop; + CEntityPointer m_penSoundFollow; + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +SLONG GetUsedMemory(void); +#define STATE_CMovingBrushMarker_Main 1 + BOOL +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_MovingBrushMarker_INCLUDED diff --git a/Sources/EntitiesMP/MovingBrushMarker_tables.h b/Sources/EntitiesMP/MovingBrushMarker_tables.h new file mode 100644 index 0000000..b069a10 --- /dev/null +++ b/Sources/EntitiesMP/MovingBrushMarker_tables.h @@ -0,0 +1,51 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CMovingBrushMarker + +CEntityProperty CMovingBrushMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000066<<8)+1, offsetof(CMovingBrushMarker, m_bInverseRotate), "Inverse Rotate", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000066<<8)+2, offsetof(CMovingBrushMarker, m_fSpeed), "Speed", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000066<<8)+3, offsetof(CMovingBrushMarker, m_fWaitTime), "Wait time", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000066<<8)+4, offsetof(CMovingBrushMarker, m_bStopMoving), "Stop moving", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &BoolEType_enum, (0x00000066<<8)+6, offsetof(CMovingBrushMarker, m_betMoveOnTouch), "Move on touch", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000066<<8)+7, offsetof(CMovingBrushMarker, m_fBlockDamage), "Block damage", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000066<<8)+8, offsetof(CMovingBrushMarker, m_tmBankingRotation), "Banking rotation speed", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000066<<8)+9, offsetof(CMovingBrushMarker, m_bBankingClockwise), "Banking rotation clockwise", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000066<<8)+14, offsetof(CMovingBrushMarker, m_bNoRotation), "Don't use marker orientation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x00000066<<8)+10, offsetof(CMovingBrushMarker, m_eetMarkerEvent), "Marker Event - Type", 'J', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000066<<8)+11, offsetof(CMovingBrushMarker, m_penMarkerEvent), "Marker Event - Target", 'K', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x00000066<<8)+16, offsetof(CMovingBrushMarker, m_eetTouchEvent), "Touch Event - Type", 'U', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000066<<8)+17, offsetof(CMovingBrushMarker, m_penTouchEvent), "Touch Event - Target", 'I', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000066<<8)+20, offsetof(CMovingBrushMarker, m_penSoundStart), "Sound start entity", 'Q', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000066<<8)+21, offsetof(CMovingBrushMarker, m_penSoundStop), "Sound stop entity", 'Z', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000066<<8)+22, offsetof(CMovingBrushMarker, m_penSoundFollow), "Sound follow entity", 'F', 0x7F0000FFUL, 0), +}; +#define CMovingBrushMarker_propertiesct ARRAYCOUNT(CMovingBrushMarker_properties) + +CEntityComponent CMovingBrushMarker_components[] = { +#define MODEL_MARKER ((0x00000066<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\MovingBrushMarker.mdl"), +#define TEXTURE_MARKER ((0x00000066<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\GravityMarker.tex"), +}; +#define CMovingBrushMarker_componentsct ARRAYCOUNT(CMovingBrushMarker_components) + +CEventHandlerEntry CMovingBrushMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CMovingBrushMarker:: +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrushMarker.es" +Main),DEBUGSTRING("CMovingBrushMarker::Main")}, +}; +#define CMovingBrushMarker_handlersct ARRAYCOUNT(CMovingBrushMarker_handlers) + +CEntity *CMovingBrushMarker_New(void) { return new CMovingBrushMarker; }; +void CMovingBrushMarker_OnInitClass(void) {}; +void CMovingBrushMarker_OnEndClass(void) {}; +void CMovingBrushMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMovingBrushMarker_OnWorldEnd(CWorld *pwo) {}; +void CMovingBrushMarker_OnWorldInit(CWorld *pwo) {}; +void CMovingBrushMarker_OnWorldTick(CWorld *pwo) {}; +void CMovingBrushMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMovingBrushMarker, CMarker, "Moving Brush Marker", "Thumbnails\\MovingBrushMarker.tbn", 0x00000066); +DECLARE_CTFILENAME(_fnmCMovingBrushMarker_tbn, "Thumbnails\\MovingBrushMarker.tbn"); diff --git a/Sources/EntitiesMP/MovingBrush_tables.h b/Sources/EntitiesMP/MovingBrush_tables.h new file mode 100644 index 0000000..396ebb4 --- /dev/null +++ b/Sources/EntitiesMP/MovingBrush_tables.h @@ -0,0 +1,148 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(BlockAction) + EP_ENUMVALUE(BA_NONE, "None"), + EP_ENUMVALUE(BA_BOUNCE, "Bounce"), + EP_ENUMVALUE(BA_SKIPMARKER, "Skip marker"), +EP_ENUMEND(BlockAction); + +EP_ENUMBEG(TouchOrDamageEvent) + EP_ENUMVALUE(TDE_TOUCHONLY, "Touch Only"), + EP_ENUMVALUE(TDE_DAMAGEONLY, "Damage Only"), + EP_ENUMVALUE(TDE_BOTH, "Both"), +EP_ENUMEND(TouchOrDamageEvent); + +#define ENTITYCLASS CMovingBrush + +CEntityProperty CMovingBrush_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000065<<8)+1, offsetof(CMovingBrush, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000065<<8)+2, offsetof(CMovingBrush, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+3, offsetof(CMovingBrush, m_penTarget), "Target", 'T', C_BLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+4, offsetof(CMovingBrush, m_bAutoStart), "Auto start", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+5, offsetof(CMovingBrush, m_fSpeed), "Speed", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+6, offsetof(CMovingBrush, m_fWaitTime), "Wait time", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+7, offsetof(CMovingBrush, m_bMoveOnTouch), "Move on touch", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &BlockAction_enum, (0x00000065<<8)+8, offsetof(CMovingBrush, m_ebaAction), "Block action", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+9, offsetof(CMovingBrush, m_fBlockDamage), "Block damage", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+10, offsetof(CMovingBrush, m_bPlayersOnly), "Players Only", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+11, offsetof(CMovingBrush, m_bDynamicShadows), "Dynamic shadows", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+12, offsetof(CMovingBrush, m_bVeryBigBrush), "Very Big Brush", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x00000065<<8)+13, offsetof(CMovingBrush, m_eetTouchEvent), "Touch Event - Type", 'U', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+14, offsetof(CMovingBrush, m_penTouchEvent), "Touch Event - Target", 'I', C_dCYAN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &TouchOrDamageEvent_enum, (0x00000065<<8)+19, offsetof(CMovingBrush, m_tdeSendEventOnDamage), "Send touch event on damage", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+15, offsetof(CMovingBrush, m_penSwitch), "Switch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x00000065<<8)+16, offsetof(CMovingBrush, m_eetMarkerEvent), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+17, offsetof(CMovingBrush, m_penMarkerEvent), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+18, offsetof(CMovingBrush, m_tmBankingRotation), "Banking rotation speed", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+20, offsetof(CMovingBrush, m_bMoving), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+78, offsetof(CMovingBrush, m_bRotating), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+79, offsetof(CMovingBrush, m_bForceStop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+80, offsetof(CMovingBrush, m_bNoRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000065<<8)+21, offsetof(CMovingBrush, m_vDesiredTranslation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x00000065<<8)+22, offsetof(CMovingBrush, m_aDesiredRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+23, offsetof(CMovingBrush, m_bInverseRotate), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+24, offsetof(CMovingBrush, m_bStopMoving), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+25, offsetof(CMovingBrush, m_bMoveToMarker), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+26, offsetof(CMovingBrush, m_bSkipMarker), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+27, offsetof(CMovingBrush, m_bValidMarker), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+30, offsetof(CMovingBrush, m_fXLimitSign), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+31, offsetof(CMovingBrush, m_fYLimitSign), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+32, offsetof(CMovingBrush, m_fZLimitSign), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000065<<8)+33, offsetof(CMovingBrush, m_aHLimitSign), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000065<<8)+34, offsetof(CMovingBrush, m_aPLimitSign), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000065<<8)+35, offsetof(CMovingBrush, m_aBLimitSign), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000065<<8)+40, offsetof(CMovingBrush, m_vStartTranslation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x00000065<<8)+41, offsetof(CMovingBrush, m_aStartRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+42, offsetof(CMovingBrush, m_fCourseLength), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000065<<8)+43, offsetof(CMovingBrush, m_aHeadLenght), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000065<<8)+44, offsetof(CMovingBrush, m_aPitchLenght), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE, NULL, (0x00000065<<8)+45, offsetof(CMovingBrush, m_aBankLenght), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+50, offsetof(CMovingBrush, m_penSoundStart), "Sound start entity", 'Q', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+51, offsetof(CMovingBrush, m_penSoundStop), "Sound stop entity", 'Z', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+52, offsetof(CMovingBrush, m_penSoundFollow), "Sound follow entity", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000065<<8)+53, offsetof(CMovingBrush, m_soStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000065<<8)+54, offsetof(CMovingBrush, m_soStop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000065<<8)+55, offsetof(CMovingBrush, m_soFollow), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+60, offsetof(CMovingBrush, m_penMirror0), "Mirror 0", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+61, offsetof(CMovingBrush, m_penMirror1), "Mirror 1", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+62, offsetof(CMovingBrush, m_penMirror2), "Mirror 2", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+63, offsetof(CMovingBrush, m_penMirror3), "Mirror 3", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+64, offsetof(CMovingBrush, m_penMirror4), "Mirror 4", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+65, offsetof(CMovingBrush, m_fHealth), "Health", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+66, offsetof(CMovingBrush, m_bBlowupByBull), "Blowup by Bull", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x00000065<<8)+67, offsetof(CMovingBrush, m_eetBlowupEvent), "Blowup Event - Type", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000065<<8)+68, offsetof(CMovingBrush, m_penBlowupEvent), "Blowup Event - Target", 0, C_BLACK | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+69, offsetof(CMovingBrush, m_bZoning), "Zoning", 'Z', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+70, offsetof(CMovingBrush, m_bMoveOnDamage), "Move on damage", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+71, offsetof(CMovingBrush, m_fTouchDamage), "Touch damage", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x00000065<<8)+72, offsetof(CMovingBrush, m_colDebrises), "Color of debrises", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000065<<8)+74, offsetof(CMovingBrush, m_ctDebrises), "Debris count", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+75, offsetof(CMovingBrush, m_fCandyEffect), "Debris blow power", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000065<<8)+76, offsetof(CMovingBrush, m_fCubeFactor), "Cube factor", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000065<<8)+77, offsetof(CMovingBrush, m_bBlowupByDamager), "Blowup by Damager", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLAGS, &ClasificationBits_enum, (0x00000065<<8)+81, offsetof(CMovingBrush, m_cbClassificationBits), "Clasification bits", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLAGS, &VisibilityBits_enum, (0x00000065<<8)+82, offsetof(CMovingBrush, m_vbVisibilityBits), "Visibility bits", 'V', 0x7F0000FFUL, 0), +}; +#define CMovingBrush_propertiesct ARRAYCOUNT(CMovingBrush_properties) + +CEntityComponent CMovingBrush_components[] = { +#define MODEL_STONE ((0x00000065<<8)+14) + CEntityComponent(ECT_MODEL, MODEL_STONE, "EFNM" "Models\\Effects\\Debris\\Stone\\Stone.mdl"), +#define TEXTURE_STONE ((0x00000065<<8)+15) + CEntityComponent(ECT_TEXTURE, TEXTURE_STONE, "EFNM" "Models\\Effects\\Debris\\Stone\\Stone.tex"), +#define CLASS_DEBRIS ((0x00000065<<8)+16) + CEntityComponent(ECT_CLASS, CLASS_DEBRIS, "EFNM" "Classes\\Debris.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000065<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +}; +#define CMovingBrush_componentsct ARRAYCOUNT(CMovingBrush_components) + +CEventHandlerEntry CMovingBrush_handlers[] = { + {0x00650002, -1, CEntity::pEventHandler(&CMovingBrush:: +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MoveToMarker),DEBUGSTRING("CMovingBrush::MoveToMarker")}, + {0x00650003, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650003_MoveToMarker_01), DEBUGSTRING("CMovingBrush::H0x00650003_MoveToMarker_01")}, + {0x00650004, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650004_MoveToMarker_02), DEBUGSTRING("CMovingBrush::H0x00650004_MoveToMarker_02")}, + {0x00650005, -1, CEntity::pEventHandler(&CMovingBrush:: +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +BounceObstructed),DEBUGSTRING("CMovingBrush::BounceObstructed")}, + {0x00650006, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650006_BounceObstructed_01), DEBUGSTRING("CMovingBrush::H0x00650006_BounceObstructed_01")}, + {0x00650007, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650007_BounceObstructed_02), DEBUGSTRING("CMovingBrush::H0x00650007_BounceObstructed_02")}, + {0x00650008, -1, CEntity::pEventHandler(&CMovingBrush:: +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +MoveBrush),DEBUGSTRING("CMovingBrush::MoveBrush")}, + {0x00650009, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650009_MoveBrush_01), DEBUGSTRING("CMovingBrush::H0x00650009_MoveBrush_01")}, + {0x0065000a, -1, CEntity::pEventHandler(&CMovingBrush::H0x0065000a_MoveBrush_02), DEBUGSTRING("CMovingBrush::H0x0065000a_MoveBrush_02")}, + {0x0065000b, -1, CEntity::pEventHandler(&CMovingBrush::H0x0065000b_MoveBrush_03), DEBUGSTRING("CMovingBrush::H0x0065000b_MoveBrush_03")}, + {0x0065000c, -1, CEntity::pEventHandler(&CMovingBrush::H0x0065000c_MoveBrush_04), DEBUGSTRING("CMovingBrush::H0x0065000c_MoveBrush_04")}, + {0x0065000d, -1, CEntity::pEventHandler(&CMovingBrush::H0x0065000d_MoveBrush_05), DEBUGSTRING("CMovingBrush::H0x0065000d_MoveBrush_05")}, + {0x0065000e, -1, CEntity::pEventHandler(&CMovingBrush::H0x0065000e_MoveBrush_06), DEBUGSTRING("CMovingBrush::H0x0065000e_MoveBrush_06")}, + {0x0065000f, -1, CEntity::pEventHandler(&CMovingBrush::H0x0065000f_MoveBrush_07), DEBUGSTRING("CMovingBrush::H0x0065000f_MoveBrush_07")}, + {0x00650010, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650010_MoveBrush_08), DEBUGSTRING("CMovingBrush::H0x00650010_MoveBrush_08")}, + {0x00650011, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650011_MoveBrush_09), DEBUGSTRING("CMovingBrush::H0x00650011_MoveBrush_09")}, + {0x00650012, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650012_MoveBrush_10), DEBUGSTRING("CMovingBrush::H0x00650012_MoveBrush_10")}, + {0x00650013, -1, CEntity::pEventHandler(&CMovingBrush:: +#line 784 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +TeleportToStopMarker),DEBUGSTRING("CMovingBrush::TeleportToStopMarker")}, + {1, -1, CEntity::pEventHandler(&CMovingBrush:: +#line 813 "D:/SE1_GPL/Sources/EntitiesMP/MovingBrush.es" +Main),DEBUGSTRING("CMovingBrush::Main")}, + {0x00650014, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650014_Main_01), DEBUGSTRING("CMovingBrush::H0x00650014_Main_01")}, + {0x00650015, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650015_Main_02), DEBUGSTRING("CMovingBrush::H0x00650015_Main_02")}, + {0x00650016, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650016_Main_03), DEBUGSTRING("CMovingBrush::H0x00650016_Main_03")}, + {0x00650017, -1, CEntity::pEventHandler(&CMovingBrush::H0x00650017_Main_04), DEBUGSTRING("CMovingBrush::H0x00650017_Main_04")}, +}; +#define CMovingBrush_handlersct ARRAYCOUNT(CMovingBrush_handlers) + +CEntity *CMovingBrush_New(void) { return new CMovingBrush; }; +void CMovingBrush_OnInitClass(void) {}; +void CMovingBrush_OnEndClass(void) {}; +void CMovingBrush_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMovingBrush_OnWorldEnd(CWorld *pwo) {}; +void CMovingBrush_OnWorldInit(CWorld *pwo) {}; +void CMovingBrush_OnWorldTick(CWorld *pwo) {}; +void CMovingBrush_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMovingBrush, CMovableBrushEntity, "Moving Brush", "Thumbnails\\MovingBrush.tbn", 0x00000065); +DECLARE_CTFILENAME(_fnmCMovingBrush_tbn, "Thumbnails\\MovingBrush.tbn"); diff --git a/Sources/EntitiesMP/MusicChanger.cpp b/Sources/EntitiesMP/MusicChanger.cpp new file mode 100644 index 0000000..6fc2b91 --- /dev/null +++ b/Sources/EntitiesMP/MusicChanger.cpp @@ -0,0 +1,99 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" + +#include "StdH.h" + +#include +#include +#line 10 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" + + +void CMusicChanger::SetDefaultProperties(void) { + m_strName = ""; + m_strDescription = ""; + m_fnMusic = CTFILENAME(""); + m_fVolume = 1.0f; + m_mtType = MT_EVENT ; + m_bForceStart = TRUE ; + CRationalEntity::SetDefaultProperties(); +} +BOOL CMusicChanger:: +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMusicChanger_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMusicChanger::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +InitAsEditorModel (); +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +SetModel (MODEL_MARKER ); +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +m_strDescription . PrintF ("%s: %s (%g)" , +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +MusicType_enum . NameForValue ((INDEX) m_mtType ) , +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +(CTString &) m_fnMusic . FileName () , +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +m_fVolume ); +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00e10000, FALSE, EBegin());return TRUE;}BOOL CMusicChanger::H0x00e10000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e10000 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00e10001, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CMusicChanger::H0x00e10001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e10001 +; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00e10002, FALSE, EBegin());return TRUE;}BOOL CMusicChanger::H0x00e10002_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e10002 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +CEntity * penMusicHolder = _pNetwork -> GetEntityWithName ("MusicHolder" , 0); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +if(penMusicHolder == NULL ){ +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +CPrintF ("No MusicHolder on this level, cannot change music!\n"); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +}else { +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +EChangeMusic ecm ; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +ecm . fnMusic = m_fnMusic ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +ecm . fVolume = m_fVolume ; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +ecm . mtType = m_mtType ; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +ecm . bForceStart = m_bForceStart ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +penMusicHolder -> SendEvent (ecm ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +} +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +return TRUE; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +}return TRUE;}BOOL CMusicChanger::H0x00e10003_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e10003 + +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +Return(STATE_CURRENT,EVoid()); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/MusicChanger.es b/Sources/EntitiesMP/MusicChanger.es new file mode 100644 index 0000000..7a80fd4 --- /dev/null +++ b/Sources/EntitiesMP/MusicChanger.es @@ -0,0 +1,78 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +225 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/MusicHolder"; + +%{ +%} + +class CMusicChanger : CRationalEntity { +name "MusicChanger"; +thumbnail "Thumbnails\\MusicChanger.tbn"; +features "HasName", "HasDescription", "IsTargetable", "IsImportant"; + +properties: + 1 CTString m_strName "Name" 'N' = "", + 2 CTString m_strDescription = "", + 3 CTFileName m_fnMusic "Music" 'M' = CTFILENAME(""), + 4 FLOAT m_fVolume "Volume" 'V' = 1.0f, + 5 enum MusicType m_mtType "Type" 'Y' = MT_EVENT, + 6 BOOL m_bForceStart "Force start" 'F' = TRUE, + +components: + 1 model MODEL_MARKER "Models\\Editor\\MusicChanger.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\MusicChanger.tex" + +functions: +procedures: + // initialize music + Main(EVoid) { + + // init as model + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + m_strDescription.PrintF("%s: %s (%g)", + MusicType_enum.NameForValue((INDEX)m_mtType), + (CTString&)m_fnMusic.FileName(), + m_fVolume); + + // wait for game to start + autowait(0.1f); + + // repeat forever + wait() { + // when triggered + on (ETrigger) : { + // find music holder for this level + CEntity *penMusicHolder = _pNetwork->GetEntityWithName("MusicHolder", 0); + // if not existing + if (penMusicHolder==NULL) { + // error + CPrintF("No MusicHolder on this level, cannot change music!\n"); + // if existing + } else { + // send event to change music + EChangeMusic ecm; + ecm.fnMusic = m_fnMusic; + ecm.fVolume = m_fVolume; + ecm.mtType = m_mtType; + ecm.bForceStart = m_bForceStart; + penMusicHolder->SendEvent(ecm); + } + resume; + }; + } + + return; + } +}; diff --git a/Sources/EntitiesMP/MusicChanger.h b/Sources/EntitiesMP/MusicChanger.h new file mode 100644 index 0000000..c1b55c0 --- /dev/null +++ b/Sources/EntitiesMP/MusicChanger.h @@ -0,0 +1,31 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_MusicChanger_INCLUDED +#define _EntitiesMP_MusicChanger_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CMusicChanger_DLLClass; +class CMusicChanger : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual const CTString &GetDescription(void) const { return m_strDescription; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CTFileName m_fnMusic; + FLOAT m_fVolume; + enum MusicType m_mtType; + BOOL m_bForceStart; +#define STATE_CMusicChanger_Main 1 + BOOL +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00e10000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00e10001_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00e10002_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00e10003_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_MusicChanger_INCLUDED diff --git a/Sources/EntitiesMP/MusicChanger_tables.h b/Sources/EntitiesMP/MusicChanger_tables.h new file mode 100644 index 0000000..44e4fe9 --- /dev/null +++ b/Sources/EntitiesMP/MusicChanger_tables.h @@ -0,0 +1,45 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CMusicChanger + +CEntityProperty CMusicChanger_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e1<<8)+1, offsetof(CMusicChanger, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e1<<8)+2, offsetof(CMusicChanger, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000e1<<8)+3, offsetof(CMusicChanger, m_fnMusic), "Music", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000e1<<8)+4, offsetof(CMusicChanger, m_fVolume), "Volume", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &MusicType_enum, (0x000000e1<<8)+5, offsetof(CMusicChanger, m_mtType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e1<<8)+6, offsetof(CMusicChanger, m_bForceStart), "Force start", 'F', 0x7F0000FFUL, 0), +}; +#define CMusicChanger_propertiesct ARRAYCOUNT(CMusicChanger_properties) + +CEntityComponent CMusicChanger_components[] = { +#define MODEL_MARKER ((0x000000e1<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\MusicChanger.mdl"), +#define TEXTURE_MARKER ((0x000000e1<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\MusicChanger.tex"), +}; +#define CMusicChanger_componentsct ARRAYCOUNT(CMusicChanger_components) + +CEventHandlerEntry CMusicChanger_handlers[] = { + {1, -1, CEntity::pEventHandler(&CMusicChanger:: +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/MusicChanger.es" +Main),DEBUGSTRING("CMusicChanger::Main")}, + {0x00e10000, -1, CEntity::pEventHandler(&CMusicChanger::H0x00e10000_Main_01), DEBUGSTRING("CMusicChanger::H0x00e10000_Main_01")}, + {0x00e10001, -1, CEntity::pEventHandler(&CMusicChanger::H0x00e10001_Main_02), DEBUGSTRING("CMusicChanger::H0x00e10001_Main_02")}, + {0x00e10002, -1, CEntity::pEventHandler(&CMusicChanger::H0x00e10002_Main_03), DEBUGSTRING("CMusicChanger::H0x00e10002_Main_03")}, + {0x00e10003, -1, CEntity::pEventHandler(&CMusicChanger::H0x00e10003_Main_04), DEBUGSTRING("CMusicChanger::H0x00e10003_Main_04")}, +}; +#define CMusicChanger_handlersct ARRAYCOUNT(CMusicChanger_handlers) + +CEntity *CMusicChanger_New(void) { return new CMusicChanger; }; +void CMusicChanger_OnInitClass(void) {}; +void CMusicChanger_OnEndClass(void) {}; +void CMusicChanger_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMusicChanger_OnWorldEnd(CWorld *pwo) {}; +void CMusicChanger_OnWorldInit(CWorld *pwo) {}; +void CMusicChanger_OnWorldTick(CWorld *pwo) {}; +void CMusicChanger_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMusicChanger, CRationalEntity, "MusicChanger", "Thumbnails\\MusicChanger.tbn", 0x000000e1); +DECLARE_CTFILENAME(_fnmCMusicChanger_tbn, "Thumbnails\\MusicChanger.tbn"); diff --git a/Sources/EntitiesMP/MusicHolder.cpp b/Sources/EntitiesMP/MusicHolder.cpp new file mode 100644 index 0000000..f3f2bb4 --- /dev/null +++ b/Sources/EntitiesMP/MusicHolder.cpp @@ -0,0 +1,518 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" + +#include "StdH.h" +#include "EntitiesMP/EnemyBase.h" +#include "EntitiesMP/EnemySpawner.h" +#include "EntitiesMP/Trigger.h" +#include "EntitiesMP/Woman.h" + +#include +#include +CEntityEvent *EChangeMusic::MakeCopy(void) { CEntityEvent *peeCopy = new EChangeMusic(*this); return peeCopy;} +EChangeMusic::EChangeMusic() : CEntityEvent(EVENTCODE_EChangeMusic) {; + ClearToDefault(mtType); + ClearToDefault(fnMusic); + ClearToDefault(fVolume); + ClearToDefault(bForceStart); +}; +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" + +#define MUSIC_VOLUMEMIN 0.02f // minimum volume (considered off) +#define MUSIC_VOLUMEMAX 0.98f // maximum volume (considered full) + +float FadeInFactor(TIME fFadeTime) +{ + return (float) pow(MUSIC_VOLUMEMAX/MUSIC_VOLUMEMIN, 1/(fFadeTime/_pTimer->TickQuantum)); +} +float FadeOutFactor(TIME fFadeTime) +{ + return (float) pow(MUSIC_VOLUMEMIN/MUSIC_VOLUMEMAX, 1/(fFadeTime/_pTimer->TickQuantum)); +} + +void CMusicHolder::SetDefaultProperties(void) { + m_strName = "MusicHolder"; + m_fScoreMedium = 100.0f; + m_fScoreHeavy = 1000.0f; + m_fnMusic0 = CTFILENAME(""); + m_fnMusic1 = CTFILENAME(""); + m_fnMusic2 = CTFILENAME(""); + m_fnMusic3 = CTFILENAME(""); + m_fnMusic4 = CTFILENAME(""); + m_fVolume0 = 1.0f; + m_fVolume1 = 1.0f; + m_fVolume2 = 1.0f; + m_fVolume3 = 1.0f; + m_fVolume4 = 1.0f; + m_penBoss = NULL; + m_penCounter = NULL; + m_ctEnemiesInWorld = 0; + m_penRespawnMarker = NULL; + m_ctSecretsInWorld = 0; + m_tmFade = 1.0f; + m_mtCurrentMusic = MT_LIGHT ; + m_fCurrentVolume0a = 1.0f; + m_fCurrentVolume0b = 1.0f; + m_fCurrentVolume1a = 1.0f; + m_fCurrentVolume1b = 1.0f; + m_fCurrentVolume2a = 1.0f; + m_fCurrentVolume2b = 1.0f; + m_fCurrentVolume3a = 1.0f; + m_fCurrentVolume3b = 1.0f; + m_fCurrentVolume4a = 1.0f; + m_fCurrentVolume4b = 1.0f; + m_soMusic0a.SetOwner(this); +m_soMusic0a.Stop_internal(); + m_soMusic0b.SetOwner(this); +m_soMusic0b.Stop_internal(); + m_soMusic1a.SetOwner(this); +m_soMusic1a.Stop_internal(); + m_soMusic1b.SetOwner(this); +m_soMusic1b.Stop_internal(); + m_soMusic2a.SetOwner(this); +m_soMusic2a.Stop_internal(); + m_soMusic2b.SetOwner(this); +m_soMusic2b.Stop_internal(); + m_soMusic3a.SetOwner(this); +m_soMusic3a.Stop_internal(); + m_soMusic3b.SetOwner(this); +m_soMusic3b.Stop_internal(); + m_soMusic4a.SetOwner(this); +m_soMusic4a.Stop_internal(); + m_soMusic4b.SetOwner(this); +m_soMusic4b.Stop_internal(); + m_iSubChannel0 = 1; + m_iSubChannel1 = 1; + m_iSubChannel2 = 1; + m_iSubChannel3 = 1; + m_iSubChannel4 = 1; + CRationalEntity::SetDefaultProperties(); +} + +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void CMusicHolder::CountEnemies(void) +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +{ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_ctEnemiesInWorld = 0; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_ctSecretsInWorld = 0; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +{FOREACHINDYNAMICCONTAINER (GetWorld () -> wo_cenEntities , CEntity , iten ){ +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CEntity * pen = iten ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(IsDerivedFromClass (pen , "Enemy Base")){ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CEnemyBase * penEnemy = (CEnemyBase *) pen ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(! penEnemy -> m_bTemplate ){ +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_ctEnemiesInWorld ++; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(IsOfClass (pen , "Woman")){ +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(((CWoman *) & * pen ) -> m_bKamikazeCarrier ){m_ctEnemiesInWorld ++;} +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else if(IsDerivedFromClass (pen , "Enemy Spawner")){ +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CEnemySpawner * penSpawner = (CEnemySpawner *) pen ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(penSpawner -> m_estType != EST_TELEPORTER ){ +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_ctEnemiesInWorld += penSpawner -> m_ctTotal ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(penSpawner -> m_penTarget ){ +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(IsOfClass (penSpawner -> m_penTarget , "Woman")){ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(((CWoman *) & * penSpawner -> m_penTarget ) -> m_bKamikazeCarrier ){m_ctEnemiesInWorld += penSpawner -> m_ctTotal ;} +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else if(IsDerivedFromClass (pen , "Trigger")){ +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CTrigger * penTrigger = (CTrigger *) pen ; +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(penTrigger -> m_fScore > 0){ +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_ctSecretsInWorld ++; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}} +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} + +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void CMusicHolder::CheckOldFussMakers(void) +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +{ +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +TIME tmTooOld = tmNow - 10.0f; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CDynamicContainer < CEntity > cenOldFussMakers ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +{FOREACHINDYNAMICCONTAINER (m_cenFussMakers , CEntity , itenFussMaker ){ +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CEnemyBase & enFussMaker = (CEnemyBase &) * itenFussMaker ; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(enFussMaker . m_tmLastFussTime < tmTooOld ){ +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +cenOldFussMakers . Add (& enFussMaker ); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}} +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +{FOREACHINDYNAMICCONTAINER (cenOldFussMakers , CEntity , itenOldFussMaker ){ +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CEnemyBase & enOldFussMaker = (CEnemyBase &) * itenOldFussMaker ; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +enOldFussMaker . RemoveFromFuss (); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}} +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} + +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +INDEX CMusicHolder::GetFussMakersScore(void) { +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +INDEX iScore = 0; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +{FOREACHINDYNAMICCONTAINER (m_cenFussMakers , CEntity , itenFussMaker ){ +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CEnemyBase & enFussMaker = (CEnemyBase &) * itenFussMaker ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +iScore += enFussMaker . m_iScore ; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}} +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +return iScore ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} + +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void CMusicHolder::ChangeMusicChannel(enum MusicType mtType,const CTFileName & fnNewMusic,FLOAT fNewVolume) +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +{ +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +INDEX & iSubChannel = (& m_iSubChannel0 ) [ mtType ]; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(fnNewMusic != ""){ +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +iSubChannel = (iSubChannel + 1) % 2; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +FLOAT & fVolume = (& m_fVolume0 ) [ mtType ]; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CSoundObject & soMusic = (& m_soMusic0a ) [ mtType * 2 + iSubChannel ]; +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +FLOAT & fCurrentVolume = (& m_fCurrentVolume0a ) [ mtType * 2 + iSubChannel ]; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +ULONG ulFlags ; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(mtType == MT_EVENT ){ +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +ulFlags = SOF_MUSIC ; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else { +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +ulFlags = SOF_MUSIC | SOF_LOOP | SOF_NONGAME ; +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +fVolume = fNewVolume ; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(fnNewMusic != ""){ +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +PlaySound (soMusic , fnNewMusic , ulFlags ); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +fCurrentVolume = MUSIC_VOLUMEMIN ; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +soMusic . Pause (); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +soMusic . SetVolume (fCurrentVolume , fCurrentVolume ); +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} + +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void CMusicHolder::FadeOutChannel(INDEX iChannel,INDEX iSubChannel) +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +{ +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +FLOAT & fVolume = (& m_fVolume0 ) [ iChannel ]; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CSoundObject & soMusic = (& m_soMusic0a ) [ iChannel * 2 + iSubChannel ]; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +FLOAT & fCurrentVolume = (& m_fCurrentVolume0a ) [ iChannel * 2 + iSubChannel ]; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(! soMusic . IsPlaying ()){return ;} +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(soMusic . IsPaused ()){return ;} +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(fCurrentVolume < MUSIC_VOLUMEMIN ){ +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +soMusic . Pause (); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else { +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +fCurrentVolume *= FadeOutFactor (m_tmFade ); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +soMusic . SetVolume (fCurrentVolume * fVolume , fCurrentVolume * fVolume ); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} + +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void CMusicHolder::FadeInChannel(INDEX iChannel,INDEX iSubChannel) +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +{ +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +FLOAT & fVolume = (& m_fVolume0 ) [ iChannel ]; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CSoundObject & soMusic = (& m_soMusic0a ) [ iChannel * 2 + iSubChannel ]; +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +FLOAT & fCurrentVolume = (& m_fCurrentVolume0a ) [ iChannel * 2 + iSubChannel ]; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(! soMusic . IsPlaying ()){return ;} +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(soMusic . IsPaused ()){ +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +soMusic . Resume (); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(fCurrentVolume < MUSIC_VOLUMEMAX ){ +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +fCurrentVolume *= FadeInFactor (m_tmFade ); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +fCurrentVolume = ClampUp (fCurrentVolume , 1.0f); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +soMusic . SetVolume (fCurrentVolume * fVolume , fCurrentVolume * fVolume ); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} + +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void CMusicHolder::CrossFadeOneChannel(enum MusicType mtType) +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +{ +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +INDEX iSubChannelActive = (& m_iSubChannel0 ) [ mtType ]; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +INDEX iSubChannelInactive = (iSubChannelActive + 1) % 2; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(mtType == m_mtCurrentMusic ){ +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +FadeInChannel (mtType , iSubChannelActive ); +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +FadeOutChannel (mtType , iSubChannelInactive ); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else { +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +FadeOutChannel (mtType , 0); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +FadeOutChannel (mtType , 1); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +BOOL CMusicHolder:: +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CMusicHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CMusicHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +InitAsEditorModel (); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +SetModel (MODEL_MARKER ); +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x00de0001, FALSE, EBegin());return TRUE;}BOOL CMusicHolder::H0x00de0001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00de0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00de0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CMusicHolder::H0x00de0002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00de0002 +; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +ChangeMusicChannel (MT_LIGHT , m_fnMusic0 , m_fVolume0 ); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +ChangeMusicChannel (MT_MEDIUM , m_fnMusic1 , m_fVolume1 ); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +ChangeMusicChannel (MT_HEAVY , m_fnMusic2 , m_fVolume2 ); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +ChangeMusicChannel (MT_EVENT , m_fnMusic3 , m_fVolume3 ); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +ChangeMusicChannel (MT_CONTINUOUS , m_fnMusic4 , m_fVolume4 ); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_mtCurrentMusic = MT_LIGHT ; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_fCurrentVolume0a = MUSIC_VOLUMEMAX * 0.98f; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_tmFade = 0.01f; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CrossFadeOneChannel (MT_LIGHT ); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x00de0003, FALSE, EBegin());return TRUE;}BOOL CMusicHolder::H0x00de0003_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00de0003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00de0004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CMusicHolder::H0x00de0004_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00de0004 +; +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CountEnemies (); +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +Jump(STATE_CURRENT,0x00de0007, FALSE, EInternal());return TRUE;}BOOL CMusicHolder::H0x00de0007_Main_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00de0007 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00de0008, FALSE, EInternal());return TRUE;} +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00de0005, FALSE, EBegin());return TRUE;}BOOL CMusicHolder::H0x00de0005_Main_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00de0005 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; + +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +UnsetTimer();Jump(STATE_CURRENT,0x00de0006, FALSE, EInternal());return TRUE; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EChangeMusic):{const EChangeMusic&ecm= (EChangeMusic&)__eeInput; + +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +ChangeMusicChannel (ecm . mtType , ecm . fnMusic , ecm . fVolume ); +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(ecm . bForceStart ){ +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_mtCurrentMusic = ecm . mtType ; +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +UnsetTimer();Jump(STATE_CURRENT,0x00de0006, FALSE, EInternal());return TRUE; +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}return TRUE;}BOOL CMusicHolder::H0x00de0006_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00de0006 + +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CheckOldFussMakers (); +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +FLOAT fFussScore = GetFussMakersScore (); +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(m_mtCurrentMusic == MT_EVENT ){ +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(! m_soMusic3a . IsPlaying () && ! m_soMusic3b . IsPlaying ()){ +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_mtCurrentMusic = MT_LIGHT ; +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(m_mtCurrentMusic == MT_HEAVY ){ +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(fFussScore <= 0.0f){ +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_mtCurrentMusic = MT_LIGHT ; +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else if(m_mtCurrentMusic == MT_MEDIUM ){ +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(fFussScore <= 0.0f){ +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_mtCurrentMusic = MT_LIGHT ; +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else if(fFussScore >= m_fScoreHeavy ){ +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_mtCurrentMusic = MT_HEAVY ; +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else if(m_mtCurrentMusic == MT_LIGHT ){ +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(fFussScore >= m_fScoreHeavy ){ +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_mtCurrentMusic = MT_HEAVY ; +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else if(fFussScore >= m_fScoreMedium ){ +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_mtCurrentMusic = MT_MEDIUM ; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +if(m_mtCurrentMusic == MT_LIGHT ){ +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_tmFade = 2.0f; +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else if(m_mtCurrentMusic == MT_MEDIUM ){ +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_tmFade = 1.0f; +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else if(m_mtCurrentMusic == MT_HEAVY ){ +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_tmFade = 1.0f; +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}else if(m_mtCurrentMusic == MT_EVENT || m_mtCurrentMusic == MT_CONTINUOUS ){ +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +m_tmFade = 0.5f; +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +} +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CrossFadeOneChannel (MT_LIGHT ); +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CrossFadeOneChannel (MT_MEDIUM ); +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CrossFadeOneChannel (MT_HEAVY ); +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CrossFadeOneChannel (MT_EVENT ); +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +CrossFadeOneChannel (MT_CONTINUOUS );Jump(STATE_CURRENT,0x00de0007, FALSE, EInternal());return TRUE; +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +}BOOL CMusicHolder::H0x00de0008_Main_08(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00de0008 + +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/MusicHolder.es b/Sources/EntitiesMP/MusicHolder.es new file mode 100644 index 0000000..aabf5eb --- /dev/null +++ b/Sources/EntitiesMP/MusicHolder.es @@ -0,0 +1,414 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +222 +%{ +#include "StdH.h" +#include "EntitiesMP/EnemyBase.h" +#include "EntitiesMP/EnemySpawner.h" +#include "EntitiesMP/Trigger.h" +#include "EntitiesMP/Woman.h" +%} + + +enum MusicType { + 0 MT_LIGHT "light", + 1 MT_MEDIUM "medium", + 2 MT_HEAVY "heavy", + 3 MT_EVENT "event", + 4 MT_CONTINUOUS "continuous", +}; + +event EChangeMusic { + enum MusicType mtType, + CTFileName fnMusic, + FLOAT fVolume, + BOOL bForceStart, +}; + +%{ +#define MUSIC_VOLUMEMIN 0.02f // minimum volume (considered off) +#define MUSIC_VOLUMEMAX 0.98f // maximum volume (considered full) + +float FadeInFactor(TIME fFadeTime) +{ + return (float) pow(MUSIC_VOLUMEMAX/MUSIC_VOLUMEMIN, 1/(fFadeTime/_pTimer->TickQuantum)); +} +float FadeOutFactor(TIME fFadeTime) +{ + return (float) pow(MUSIC_VOLUMEMIN/MUSIC_VOLUMEMAX, 1/(fFadeTime/_pTimer->TickQuantum)); +} +%} + +class CMusicHolder : CRationalEntity { +name "MusicHolder"; +thumbnail "Thumbnails\\MusicHolder.tbn"; +features "HasName", "IsTargetable", "IsImportant"; + +properties: + 1 CTString m_strName "" = "MusicHolder", + 2 FLOAT m_fScoreMedium "Score Medium" = 100.0f, + 3 FLOAT m_fScoreHeavy "Score Heavy" = 1000.0f, + + 10 CTFileName m_fnMusic0 "Music Light" 'M' = CTFILENAME(""), + 11 CTFileName m_fnMusic1 "Music Medium" = CTFILENAME(""), + 12 CTFileName m_fnMusic2 "Music Heavy" = CTFILENAME(""), + 13 CTFileName m_fnMusic3 = CTFILENAME(""), // event music + 14 CTFileName m_fnMusic4 = CTFILENAME(""), // continuous music + + 20 FLOAT m_fVolume0 "Volume Light" 'V' = 1.0f, + 21 FLOAT m_fVolume1 "Volume Medium" = 1.0f, + 22 FLOAT m_fVolume2 "Volume Heavy" = 1.0f, + 23 FLOAT m_fVolume3 = 1.0f, // event volume + 24 FLOAT m_fVolume4 = 1.0f, // continuous volume + +// internals + +100 CEntityPointer m_penBoss, // current boss if any +102 CEntityPointer m_penCounter, // enemy counter for wave-fight progress display +104 INDEX m_ctEnemiesInWorld = 0, // count of total enemies in world +105 CEntityPointer m_penRespawnMarker, // respawn marker for coop +106 INDEX m_ctSecretsInWorld = 0, // count of total secrets in world +101 FLOAT m_tmFade = 1.0f, // music cross-fade speed +103 enum MusicType m_mtCurrentMusic = MT_LIGHT, // current active channel + +// for cross-fade purposes +110 FLOAT m_fCurrentVolume0a = 1.0f, +210 FLOAT m_fCurrentVolume0b = 1.0f, +111 FLOAT m_fCurrentVolume1a = 1.0f, +211 FLOAT m_fCurrentVolume1b = 1.0f, +112 FLOAT m_fCurrentVolume2a = 1.0f, +212 FLOAT m_fCurrentVolume2b = 1.0f, +113 FLOAT m_fCurrentVolume3a = 1.0f, +213 FLOAT m_fCurrentVolume3b = 1.0f, +114 FLOAT m_fCurrentVolume4a = 1.0f, +214 FLOAT m_fCurrentVolume4b = 1.0f, + +// the music channels +120 CSoundObject m_soMusic0a, +220 CSoundObject m_soMusic0b, +121 CSoundObject m_soMusic1a, +221 CSoundObject m_soMusic1b, +122 CSoundObject m_soMusic2a, +222 CSoundObject m_soMusic2b, +123 CSoundObject m_soMusic3a, +223 CSoundObject m_soMusic3b, +124 CSoundObject m_soMusic4a, +224 CSoundObject m_soMusic4b, + +// next free subchannel markers (all starts at subchannel 1(b), first switch goes to subchannel 0(a)) +130 INDEX m_iSubChannel0 = 1, +131 INDEX m_iSubChannel1 = 1, +132 INDEX m_iSubChannel2 = 1, +133 INDEX m_iSubChannel3 = 1, +134 INDEX m_iSubChannel4 = 1, + + { + // array of enemies that make fuss + CDynamicContainer m_cenFussMakers; + } + +components: + 1 model MODEL_MARKER "Models\\Editor\\MusicHolder.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\MusicHolder.tex" + + +functions: + // count enemies in current world + void CountEnemies(void) + { + m_ctEnemiesInWorld = 0; + m_ctSecretsInWorld = 0; + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(GetWorld()->wo_cenEntities, CEntity, iten) { + CEntity *pen = iten; + // if enemybase + if (IsDerivedFromClass(pen, "Enemy Base")) { + CEnemyBase *penEnemy = (CEnemyBase *)pen; + // if not template + if (!penEnemy->m_bTemplate) { + // count one + m_ctEnemiesInWorld++; + // if this is a woman kamikaze carrier, add another one to count + if (IsOfClass(pen, "Woman")) { + if (((CWoman *)&*pen)->m_bKamikazeCarrier) { m_ctEnemiesInWorld++; } + } + } + // if spawner + } else if (IsDerivedFromClass(pen, "Enemy Spawner")) { + CEnemySpawner *penSpawner = (CEnemySpawner *)pen; + // if not teleporting + if (penSpawner->m_estType!=EST_TELEPORTER) { + // add total count + m_ctEnemiesInWorld+=penSpawner->m_ctTotal; + // if this spawner points to a woman kamikaze carrier template, increase count once more + if (penSpawner->m_penTarget) { + if (IsOfClass(penSpawner->m_penTarget, "Woman")) { + if (((CWoman *)&*penSpawner->m_penTarget)->m_bKamikazeCarrier) { m_ctEnemiesInWorld+=penSpawner->m_ctTotal; } + } + } + } + // if trigger + } else if (IsDerivedFromClass(pen, "Trigger")) { + CTrigger *penTrigger = (CTrigger *)pen; + // if has score + if (penTrigger->m_fScore>0) { + // it counts as a secret + m_ctSecretsInWorld++; + } + } + }} + } + + // check for stale fuss-makers + void CheckOldFussMakers(void) + { + TIME tmNow = _pTimer->CurrentTick(); + TIME tmTooOld = tmNow-10.0f; + CDynamicContainer cenOldFussMakers; + // for each fussmaker + {FOREACHINDYNAMICCONTAINER(m_cenFussMakers, CEntity, itenFussMaker) { + CEnemyBase & enFussMaker = (CEnemyBase&)*itenFussMaker; + // if haven't done fuss for too long + if (enFussMaker.m_tmLastFussTimeTickQuantum); + + // prepare initial music channel values + ChangeMusicChannel(MT_LIGHT, m_fnMusic0, m_fVolume0); + ChangeMusicChannel(MT_MEDIUM, m_fnMusic1, m_fVolume1); + ChangeMusicChannel(MT_HEAVY, m_fnMusic2, m_fVolume2); + ChangeMusicChannel(MT_EVENT, m_fnMusic3, m_fVolume3); + ChangeMusicChannel(MT_CONTINUOUS, m_fnMusic4, m_fVolume4); + + // start with light music + m_mtCurrentMusic = MT_LIGHT; + m_fCurrentVolume0a = MUSIC_VOLUMEMAX*0.98f; + m_tmFade = 0.01f; + CrossFadeOneChannel(MT_LIGHT); + + // must react after enemyspawner and all enemies, but before player for proper enemy counting + // (total wait is two ticks so far) + autowait(_pTimer->TickQuantum); + + // count enemies in current world + CountEnemies(); + + // main loop + while(TRUE) { + // wait a bit + wait(0.1f) { + on (ETimer) : { + stop; + }; + // if music is to be changed + on (EChangeMusic ecm) : { + // change parameters + ChangeMusicChannel(ecm.mtType, ecm.fnMusic, ecm.fVolume); + // if force started + if (ecm.bForceStart) { + // set as current music + m_mtCurrentMusic = ecm.mtType; + } + // stop waiting + stop; + } + } + // check fuss + CheckOldFussMakers(); + // get total score of all active fuss makers + FLOAT fFussScore = GetFussMakersScore(); + // if event is on + if (m_mtCurrentMusic==MT_EVENT) { + // if event has ceased playing + if (!m_soMusic3a.IsPlaying() && !m_soMusic3b.IsPlaying()) { + // switch to light music + m_mtCurrentMusic=MT_LIGHT; + } + } + // if heavy fight is on + if (m_mtCurrentMusic==MT_HEAVY) { + // if no more fuss + if (fFussScore<=0.0f) { + // switch to no fight + m_mtCurrentMusic=MT_LIGHT; + } + // if medium fight is on + } else if (m_mtCurrentMusic==MT_MEDIUM) { + // if no more fuss + if (fFussScore<=0.0f) { + // switch to no fight + m_mtCurrentMusic=MT_LIGHT; + // if larger fuss + } else if (fFussScore>=m_fScoreHeavy) { + // switch to heavy fight + m_mtCurrentMusic=MT_HEAVY; + } + // if no fight is on + } else if (m_mtCurrentMusic==MT_LIGHT) { + // if heavy fuss + if (fFussScore>=m_fScoreHeavy) { + // switch to heavy fight + m_mtCurrentMusic=MT_HEAVY; + // if medium fuss + } else if (fFussScore>=m_fScoreMedium) { + // switch to medium fight + m_mtCurrentMusic=MT_MEDIUM; + } + } + + // setup fade speed depending on music type + if (m_mtCurrentMusic==MT_LIGHT) { + m_tmFade = 2.0f; + } else if (m_mtCurrentMusic==MT_MEDIUM) { + m_tmFade = 1.0f; + } else if (m_mtCurrentMusic==MT_HEAVY) { + m_tmFade = 1.0f; + } else if (m_mtCurrentMusic==MT_EVENT || m_mtCurrentMusic==MT_CONTINUOUS) { + m_tmFade = 0.5f; + } + + // fade all channels + CrossFadeOneChannel(MT_LIGHT); + CrossFadeOneChannel(MT_MEDIUM); + CrossFadeOneChannel(MT_HEAVY); + CrossFadeOneChannel(MT_EVENT); + CrossFadeOneChannel(MT_CONTINUOUS); + } + return; + } +}; diff --git a/Sources/EntitiesMP/MusicHolder.h b/Sources/EntitiesMP/MusicHolder.h new file mode 100644 index 0000000..e2041de --- /dev/null +++ b/Sources/EntitiesMP/MusicHolder.h @@ -0,0 +1,114 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_MusicHolder_INCLUDED +#define _EntitiesMP_MusicHolder_INCLUDED 1 +extern DECL_DLL CEntityPropertyEnumType MusicType_enum; +enum MusicType { + MT_LIGHT = 0, + MT_MEDIUM = 1, + MT_HEAVY = 2, + MT_EVENT = 3, + MT_CONTINUOUS = 4, +}; +DECL_DLL inline void ClearToDefault(MusicType &e) { e = (MusicType)0; } ; +#define EVENTCODE_EChangeMusic 0x00de0000 +class DECL_DLL EChangeMusic : public CEntityEvent { +public: +EChangeMusic(); +CEntityEvent *MakeCopy(void); +enum MusicType mtType; +CTFileName fnMusic; +FLOAT fVolume; +BOOL bForceStart; +}; +DECL_DLL inline void ClearToDefault(EChangeMusic &e) { e = EChangeMusic(); } ; +extern "C" DECL_DLL CDLLEntityClass CMusicHolder_DLLClass; +class CMusicHolder : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + FLOAT m_fScoreMedium; + FLOAT m_fScoreHeavy; + CTFileName m_fnMusic0; + CTFileName m_fnMusic1; + CTFileName m_fnMusic2; + CTFileName m_fnMusic3; + CTFileName m_fnMusic4; + FLOAT m_fVolume0; + FLOAT m_fVolume1; + FLOAT m_fVolume2; + FLOAT m_fVolume3; + FLOAT m_fVolume4; + CEntityPointer m_penBoss; + CEntityPointer m_penCounter; + INDEX m_ctEnemiesInWorld; + CEntityPointer m_penRespawnMarker; + INDEX m_ctSecretsInWorld; + FLOAT m_tmFade; + enum MusicType m_mtCurrentMusic; + FLOAT m_fCurrentVolume0a; + FLOAT m_fCurrentVolume0b; + FLOAT m_fCurrentVolume1a; + FLOAT m_fCurrentVolume1b; + FLOAT m_fCurrentVolume2a; + FLOAT m_fCurrentVolume2b; + FLOAT m_fCurrentVolume3a; + FLOAT m_fCurrentVolume3b; + FLOAT m_fCurrentVolume4a; + FLOAT m_fCurrentVolume4b; + CSoundObject m_soMusic0a; + CSoundObject m_soMusic0b; + CSoundObject m_soMusic1a; + CSoundObject m_soMusic1b; + CSoundObject m_soMusic2a; + CSoundObject m_soMusic2b; + CSoundObject m_soMusic3a; + CSoundObject m_soMusic3b; + CSoundObject m_soMusic4a; + CSoundObject m_soMusic4b; + INDEX m_iSubChannel0; + INDEX m_iSubChannel1; + INDEX m_iSubChannel2; + INDEX m_iSubChannel3; + INDEX m_iSubChannel4; +CDynamicContainer < CEntity > m_cenFussMakers; + +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void CountEnemies(void); + +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void CheckOldFussMakers(void); + +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +INDEX GetFussMakersScore(void); + +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void ChangeMusicChannel(enum MusicType mtType,const CTFileName & fnNewMusic,FLOAT fNewVolume); + +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void FadeOutChannel(INDEX iChannel,INDEX iSubChannel); + +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void FadeInChannel(INDEX iChannel,INDEX iSubChannel); + +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +void CrossFadeOneChannel(enum MusicType mtType); +#define STATE_CMusicHolder_Main 1 + BOOL +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00de0001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00de0002_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00de0003_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00de0004_Main_04(const CEntityEvent &__eeInput); + BOOL H0x00de0005_Main_05(const CEntityEvent &__eeInput); + BOOL H0x00de0006_Main_06(const CEntityEvent &__eeInput); + BOOL H0x00de0007_Main_07(const CEntityEvent &__eeInput); + BOOL H0x00de0008_Main_08(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_MusicHolder_INCLUDED diff --git a/Sources/EntitiesMP/MusicHolder_tables.h b/Sources/EntitiesMP/MusicHolder_tables.h new file mode 100644 index 0000000..dfb21e4 --- /dev/null +++ b/Sources/EntitiesMP/MusicHolder_tables.h @@ -0,0 +1,96 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(MusicType) + EP_ENUMVALUE(MT_LIGHT, "light"), + EP_ENUMVALUE(MT_MEDIUM, "medium"), + EP_ENUMVALUE(MT_HEAVY, "heavy"), + EP_ENUMVALUE(MT_EVENT, "event"), + EP_ENUMVALUE(MT_CONTINUOUS, "continuous"), +EP_ENUMEND(MusicType); + +#define ENTITYCLASS CMusicHolder + +CEntityProperty CMusicHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000de<<8)+1, offsetof(CMusicHolder, m_strName), "", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+2, offsetof(CMusicHolder, m_fScoreMedium), "Score Medium", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+3, offsetof(CMusicHolder, m_fScoreHeavy), "Score Heavy", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000de<<8)+10, offsetof(CMusicHolder, m_fnMusic0), "Music Light", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000de<<8)+11, offsetof(CMusicHolder, m_fnMusic1), "Music Medium", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000de<<8)+12, offsetof(CMusicHolder, m_fnMusic2), "Music Heavy", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000de<<8)+13, offsetof(CMusicHolder, m_fnMusic3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000de<<8)+14, offsetof(CMusicHolder, m_fnMusic4), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+20, offsetof(CMusicHolder, m_fVolume0), "Volume Light", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+21, offsetof(CMusicHolder, m_fVolume1), "Volume Medium", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+22, offsetof(CMusicHolder, m_fVolume2), "Volume Heavy", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+23, offsetof(CMusicHolder, m_fVolume3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+24, offsetof(CMusicHolder, m_fVolume4), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000de<<8)+100, offsetof(CMusicHolder, m_penBoss), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000de<<8)+102, offsetof(CMusicHolder, m_penCounter), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000de<<8)+104, offsetof(CMusicHolder, m_ctEnemiesInWorld), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000de<<8)+105, offsetof(CMusicHolder, m_penRespawnMarker), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000de<<8)+106, offsetof(CMusicHolder, m_ctSecretsInWorld), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+101, offsetof(CMusicHolder, m_tmFade), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &MusicType_enum, (0x000000de<<8)+103, offsetof(CMusicHolder, m_mtCurrentMusic), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+110, offsetof(CMusicHolder, m_fCurrentVolume0a), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+210, offsetof(CMusicHolder, m_fCurrentVolume0b), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+111, offsetof(CMusicHolder, m_fCurrentVolume1a), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+211, offsetof(CMusicHolder, m_fCurrentVolume1b), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+112, offsetof(CMusicHolder, m_fCurrentVolume2a), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+212, offsetof(CMusicHolder, m_fCurrentVolume2b), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+113, offsetof(CMusicHolder, m_fCurrentVolume3a), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+213, offsetof(CMusicHolder, m_fCurrentVolume3b), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+114, offsetof(CMusicHolder, m_fCurrentVolume4a), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000de<<8)+214, offsetof(CMusicHolder, m_fCurrentVolume4b), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000de<<8)+120, offsetof(CMusicHolder, m_soMusic0a), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000de<<8)+220, offsetof(CMusicHolder, m_soMusic0b), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000de<<8)+121, offsetof(CMusicHolder, m_soMusic1a), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000de<<8)+221, offsetof(CMusicHolder, m_soMusic1b), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000de<<8)+122, offsetof(CMusicHolder, m_soMusic2a), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000de<<8)+222, offsetof(CMusicHolder, m_soMusic2b), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000de<<8)+123, offsetof(CMusicHolder, m_soMusic3a), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000de<<8)+223, offsetof(CMusicHolder, m_soMusic3b), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000de<<8)+124, offsetof(CMusicHolder, m_soMusic4a), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000de<<8)+224, offsetof(CMusicHolder, m_soMusic4b), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000de<<8)+130, offsetof(CMusicHolder, m_iSubChannel0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000de<<8)+131, offsetof(CMusicHolder, m_iSubChannel1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000de<<8)+132, offsetof(CMusicHolder, m_iSubChannel2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000de<<8)+133, offsetof(CMusicHolder, m_iSubChannel3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000de<<8)+134, offsetof(CMusicHolder, m_iSubChannel4), "", 0, 0, 0), +}; +#define CMusicHolder_propertiesct ARRAYCOUNT(CMusicHolder_properties) + +CEntityComponent CMusicHolder_components[] = { +#define MODEL_MARKER ((0x000000de<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\MusicHolder.mdl"), +#define TEXTURE_MARKER ((0x000000de<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\MusicHolder.tex"), +}; +#define CMusicHolder_componentsct ARRAYCOUNT(CMusicHolder_components) + +CEventHandlerEntry CMusicHolder_handlers[] = { + {1, -1, CEntity::pEventHandler(&CMusicHolder:: +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/MusicHolder.es" +Main),DEBUGSTRING("CMusicHolder::Main")}, + {0x00de0001, -1, CEntity::pEventHandler(&CMusicHolder::H0x00de0001_Main_01), DEBUGSTRING("CMusicHolder::H0x00de0001_Main_01")}, + {0x00de0002, -1, CEntity::pEventHandler(&CMusicHolder::H0x00de0002_Main_02), DEBUGSTRING("CMusicHolder::H0x00de0002_Main_02")}, + {0x00de0003, -1, CEntity::pEventHandler(&CMusicHolder::H0x00de0003_Main_03), DEBUGSTRING("CMusicHolder::H0x00de0003_Main_03")}, + {0x00de0004, -1, CEntity::pEventHandler(&CMusicHolder::H0x00de0004_Main_04), DEBUGSTRING("CMusicHolder::H0x00de0004_Main_04")}, + {0x00de0005, -1, CEntity::pEventHandler(&CMusicHolder::H0x00de0005_Main_05), DEBUGSTRING("CMusicHolder::H0x00de0005_Main_05")}, + {0x00de0006, -1, CEntity::pEventHandler(&CMusicHolder::H0x00de0006_Main_06), DEBUGSTRING("CMusicHolder::H0x00de0006_Main_06")}, + {0x00de0007, -1, CEntity::pEventHandler(&CMusicHolder::H0x00de0007_Main_07), DEBUGSTRING("CMusicHolder::H0x00de0007_Main_07")}, + {0x00de0008, -1, CEntity::pEventHandler(&CMusicHolder::H0x00de0008_Main_08), DEBUGSTRING("CMusicHolder::H0x00de0008_Main_08")}, +}; +#define CMusicHolder_handlersct ARRAYCOUNT(CMusicHolder_handlers) + +CEntity *CMusicHolder_New(void) { return new CMusicHolder; }; +void CMusicHolder_OnInitClass(void) {}; +void CMusicHolder_OnEndClass(void) {}; +void CMusicHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CMusicHolder_OnWorldEnd(CWorld *pwo) {}; +void CMusicHolder_OnWorldInit(CWorld *pwo) {}; +void CMusicHolder_OnWorldTick(CWorld *pwo) {}; +void CMusicHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CMusicHolder, CRationalEntity, "MusicHolder", "Thumbnails\\MusicHolder.tbn", 0x000000de); +DECLARE_CTFILENAME(_fnmCMusicHolder_tbn, "Thumbnails\\MusicHolder.tbn"); diff --git a/Sources/EntitiesMP/NavigationMarker.cpp b/Sources/EntitiesMP/NavigationMarker.cpp new file mode 100644 index 0000000..2b79aeb --- /dev/null +++ b/Sources/EntitiesMP/NavigationMarker.cpp @@ -0,0 +1,245 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" + +#include "StdH.h" +#include "EntitiesMP/Common/PathFinding.h" + +#define MAX_TARGETS 6 + +#include +#include +#line 13 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" + +// info structure +static EntityInfo eiMarker = { + EIBT_ROCK, 10.0f, + 0.0f, 1.0f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + + +void CNavigationMarker::SetDefaultProperties(void) { + m_strName = "Marker"; + m_fMarkerRange = 1.0f; + m_penTarget0 = NULL; + m_penTarget1 = NULL; + m_penTarget2 = NULL; + m_penTarget3 = NULL; + m_penTarget4 = NULL; + m_penTarget5 = NULL; + CEntity::SetDefaultProperties(); +} + CNavigationMarker::CNavigationMarker(void) +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +{ +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +m_ppnNode = NULL ; +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} + CNavigationMarker:: ~ CNavigationMarker(void) +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +{ +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +ASSERT (m_ppnNode == NULL ); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +void CNavigationMarker::Read_t(CTStream * istr) +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +{ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CEntity :: Read_t (istr ); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +m_ppnNode = NULL ; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CEntity * CNavigationMarker::GetTarget(void)const {return m_penTarget0 ;} + +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +void * CNavigationMarker::GetEntityInfo(void) { +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +return & eiMarker ; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} + +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CPathNode * CNavigationMarker::GetPathNode(void) +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +{ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +if(m_ppnNode == NULL ){ +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +m_ppnNode = new CPathNode (this ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +return m_ppnNode ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} + +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CEntityPointer & CNavigationMarker::TargetPointer(INDEX i) +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +{ +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +ASSERT (i >= 0 && i < MAX_TARGETS ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +return (& m_penTarget0 ) [ i ]; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CNavigationMarker & CNavigationMarker::Target(INDEX i) +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +{ +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +return (CNavigationMarker &) * TargetPointer (i ); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} + +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CNavigationMarker * CNavigationMarker::GetLink(INDEX i) +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +{ +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +for(INDEX iTarget = 0;iTarget < MAX_TARGETS ;iTarget ++){ +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CNavigationMarker * penLink = & Target (iTarget ); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +if(penLink == NULL ){ +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +continue ; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +if(iTarget == i ){ +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +return penLink ; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +return NULL ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +const CTString & CNavigationMarker::GetDescription(void)const { +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +return m_strName ; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} + +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +BOOL CNavigationMarker::MovesByTargetedRoute(CTString & strTargetProperty)const { +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +strTargetProperty = "Target 0"; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +return TRUE ; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} + +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +BOOL CNavigationMarker::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +fnmMarkerClass = CTFILENAME ("Classes\\NavigationMarker.ecl"); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +strTargetProperty = "Target 0"; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +return TRUE ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} + BOOL CNavigationMarker::IsMarker(void)const { +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +return TRUE ; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +BOOL CNavigationMarker:: +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CNavigationMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CNavigationMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +InitAsEditorModel (); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +const FLOAT fSize = 0.25f; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +GetModelObject () -> StretchModel (FLOAT3D (fSize , fSize , fSize )); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +SetModel (MODEL_MARKER ); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +ModelChangeNotify (); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +for(INDEX iTarget = 0;iTarget < MAX_TARGETS ;iTarget ++){ +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CEntityPointer & penTarget = TargetPointer (iTarget ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +if(penTarget == NULL ){ +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +continue ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +if(! IsOfClass (penTarget , "NavigationMarker")){ +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +penTarget = NULL ; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +continue ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CNavigationMarker & nmOther = (CNavigationMarker &) * penTarget ; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +BOOL bFound = FALSE ; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +for(INDEX iTarget2 = 0;iTarget2 < MAX_TARGETS ;iTarget2 ++){ +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CEntityPointer & penTarget2 = nmOther . TargetPointer (iTarget2 ); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +if(penTarget2 == this ){ +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +bFound = TRUE ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +break ; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +if(! bFound ){ +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +for(INDEX iTarget2 = 0;iTarget2 < MAX_TARGETS ;iTarget2 ++){ +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CEntityPointer & penTarget2 = nmOther . TargetPointer (iTarget2 ); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +if(penTarget2 == NULL ){ +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +penTarget2 = this ; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +break ; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +} +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/NavigationMarker.es b/Sources/EntitiesMP/NavigationMarker.es new file mode 100644 index 0000000..44416cc --- /dev/null +++ b/Sources/EntitiesMP/NavigationMarker.es @@ -0,0 +1,180 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +704 +%{ +#include "StdH.h" +#include "EntitiesMP/Common/PathFinding.h" + +#define MAX_TARGETS 6 +%} + +uses "EntitiesMP/Marker"; + +%{ +// info structure +static EntityInfo eiMarker = { + EIBT_ROCK, 10.0f, + 0.0f, 1.0f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +%} + +class export CNavigationMarker : CEntity { +name "NavigationMarker"; +thumbnail "Thumbnails\\NavigationMarker.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "Marker", + 2 RANGE m_fMarkerRange "Marker Range" 'M' = 1.0f, // range around marker (marker doesn't have to be hit directly) + + 100 CEntityPointer m_penTarget0 "Target 0" 'T' COLOR(C_dBLUE|0xFF), + 101 CEntityPointer m_penTarget1 "Target 1" COLOR(C_dBLUE|0xFF), + 102 CEntityPointer m_penTarget2 "Target 2" COLOR(C_dBLUE|0xFF), + 103 CEntityPointer m_penTarget3 "Target 3" COLOR(C_dBLUE|0xFF), + 104 CEntityPointer m_penTarget4 "Target 4" COLOR(C_dBLUE|0xFF), + 105 CEntityPointer m_penTarget5 "Target 5" COLOR(C_dBLUE|0xFF), + + { + CPathNode *m_ppnNode; // for pathfinding algorithm + } + +components: + 1 model MODEL_MARKER "Models\\Editor\\NavigationMarker.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\NavigationMarker.tex" + +functions: + void CNavigationMarker(void) + { + m_ppnNode = NULL; + } + void ~CNavigationMarker(void) + { + ASSERT(m_ppnNode == NULL); + } + + /* Read from stream. */ + void Read_t( CTStream *istr) // throw char * + { + CEntity::Read_t(istr); + m_ppnNode = NULL; + } + + CEntity *GetTarget(void) const { return m_penTarget0; }; + + /* Entity info */ + void *GetEntityInfo(void) { + return &eiMarker; + }; + + // get node used for pathfinding algorithm + CPathNode *GetPathNode(void) + { + if (m_ppnNode==NULL) { + m_ppnNode = new CPathNode(this); + } + + return m_ppnNode; + } + + CEntityPointer &TargetPointer(INDEX i) + { + ASSERT(i>=0 && iStretchModel(FLOAT3D(fSize, fSize, fSize)); + SetModel(MODEL_MARKER); + ModelChangeNotify(); + SetModelMainTexture(TEXTURE_MARKER); + + // for each non-empty target + for (INDEX iTarget=0; iTarget +extern "C" DECL_DLL CDLLEntityClass CNavigationMarker_DLLClass; +class DECL_DLL CNavigationMarker : public CEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + virtual void SetDefaultProperties(void); + CTString m_strName; + RANGE m_fMarkerRange; + CEntityPointer m_penTarget0; + CEntityPointer m_penTarget1; + CEntityPointer m_penTarget2; + CEntityPointer m_penTarget3; + CEntityPointer m_penTarget4; + CEntityPointer m_penTarget5; +CPathNode * m_ppnNode; + CNavigationMarker(void); + ~ CNavigationMarker(void); + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +void Read_t(CTStream * istr); + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CEntity * GetTarget(void)const; + +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +void * GetEntityInfo(void); + +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CPathNode * GetPathNode(void); + +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CEntityPointer & TargetPointer(INDEX i); + +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CNavigationMarker & Target(INDEX i); + +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +CNavigationMarker * GetLink(INDEX i); + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +const CTString & GetDescription(void)const; + +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +virtual BOOL IsMarker(void)const; +#define STATE_CNavigationMarker_Main 1 + BOOL +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_NavigationMarker_INCLUDED diff --git a/Sources/EntitiesMP/NavigationMarker_tables.h b/Sources/EntitiesMP/NavigationMarker_tables.h new file mode 100644 index 0000000..e1c1750 --- /dev/null +++ b/Sources/EntitiesMP/NavigationMarker_tables.h @@ -0,0 +1,43 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CNavigationMarker + +CEntityProperty CNavigationMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000002c0<<8)+1, offsetof(CNavigationMarker, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x000002c0<<8)+2, offsetof(CNavigationMarker, m_fMarkerRange), "Marker Range", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000002c0<<8)+100, offsetof(CNavigationMarker, m_penTarget0), "Target 0", 'T', C_dBLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000002c0<<8)+101, offsetof(CNavigationMarker, m_penTarget1), "Target 1", 0, C_dBLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000002c0<<8)+102, offsetof(CNavigationMarker, m_penTarget2), "Target 2", 0, C_dBLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000002c0<<8)+103, offsetof(CNavigationMarker, m_penTarget3), "Target 3", 0, C_dBLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000002c0<<8)+104, offsetof(CNavigationMarker, m_penTarget4), "Target 4", 0, C_dBLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000002c0<<8)+105, offsetof(CNavigationMarker, m_penTarget5), "Target 5", 0, C_dBLUE | 0xFF, 0), +}; +#define CNavigationMarker_propertiesct ARRAYCOUNT(CNavigationMarker_properties) + +CEntityComponent CNavigationMarker_components[] = { +#define MODEL_MARKER ((0x000002c0<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\NavigationMarker.mdl"), +#define TEXTURE_MARKER ((0x000002c0<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\NavigationMarker.tex"), +}; +#define CNavigationMarker_componentsct ARRAYCOUNT(CNavigationMarker_components) + +CEventHandlerEntry CNavigationMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CNavigationMarker:: +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/NavigationMarker.es" +Main),DEBUGSTRING("CNavigationMarker::Main")}, +}; +#define CNavigationMarker_handlersct ARRAYCOUNT(CNavigationMarker_handlers) + +CEntity *CNavigationMarker_New(void) { return new CNavigationMarker; }; +void CNavigationMarker_OnInitClass(void) {}; +void CNavigationMarker_OnEndClass(void) {}; +void CNavigationMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CNavigationMarker_OnWorldEnd(CWorld *pwo) {}; +void CNavigationMarker_OnWorldInit(CWorld *pwo) {}; +void CNavigationMarker_OnWorldTick(CWorld *pwo) {}; +void CNavigationMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CNavigationMarker, CEntity, "NavigationMarker", "Thumbnails\\NavigationMarker.tbn", 0x000002c0); +DECLARE_CTFILENAME(_fnmCNavigationMarker_tbn, "Thumbnails\\NavigationMarker.tbn"); diff --git a/Sources/EntitiesMP/ParticleCloudsHolder.es b/Sources/EntitiesMP/ParticleCloudsHolder.es new file mode 100644 index 0000000..1a53b22 --- /dev/null +++ b/Sources/EntitiesMP/ParticleCloudsHolder.es @@ -0,0 +1,2 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + diff --git a/Sources/EntitiesMP/ParticleCloudsMarker.es b/Sources/EntitiesMP/ParticleCloudsMarker.es new file mode 100644 index 0000000..1a53b22 --- /dev/null +++ b/Sources/EntitiesMP/ParticleCloudsMarker.es @@ -0,0 +1,2 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + diff --git a/Sources/EntitiesMP/ParticlesHolder.cpp b/Sources/EntitiesMP/ParticlesHolder.cpp new file mode 100644 index 0000000..8cc2b2a --- /dev/null +++ b/Sources/EntitiesMP/ParticlesHolder.cpp @@ -0,0 +1,409 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" + +#include "StdH.h" + +#include +#include +void CParticlesHolder::SetDefaultProperties(void) { + m_phtType = PHT_SPIRAL ; + m_ptTexture = PT_STAR01 ; + m_ctCount = 16; + m_fStretchAll = 1.0f; + m_fStretchX = 1.0f; + m_fStretchY = 1.0f; + m_fStretchZ = 1.0f; + m_strName = ""; + m_strDescription = ""; + m_bBackground = FALSE ; + m_bTargetable = FALSE ; + m_fSize = 0.1f; + m_fParam1 = 1.0f; + m_fParam2 = 1.0f; + m_fParam3 = 1.0f; + m_bActive = TRUE ; + m_fActivateTime = 0.0f; + m_fDeactivateTime = -10000.0f; + m_fMipFactorDisappear = 8.0f; + CMovableModelEntity::SetDefaultProperties(); +} + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +void CParticlesHolder::RenderParticles(void) +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(! m_bActive ) +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{ +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +return ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +switch(m_phtType ) +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{ +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_SPIRAL : +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_Spiral (this , m_fStretchAll , m_fStretchAll / 2 , m_ptTexture , m_ctCount ); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_EMANATE : +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_Emanate (this , m_fStretchAll , m_fStretchAll / 2 , m_ptTexture , m_ctCount , m_fMipFactorDisappear ); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_STARDUST : +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_Stardust (this , m_fStretchAll , m_fStretchAll / 2 , m_ptTexture , m_ctCount ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_ATOMIC : +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_Atomic (this , m_fStretchAll , m_fStretchAll / 2 , m_ptTexture , m_ctCount ); +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_RISING : +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_Rising (this , m_fActivateTime , m_fDeactivateTime , m_fStretchAll , m_fStretchX , m_fStretchY , m_fStretchZ , m_fSize , m_ptTexture , m_ctCount ); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_FOUNTAIN : +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_Fountain (this , m_fStretchAll , m_fStretchAll / 2 , m_ptTexture , m_ctCount ); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_SMOKE : +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_GrenadeTrail (this ); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_BLOOD : +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_BloodTrail (this ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_EMANATEPLANE : +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_EmanatePlane (this , +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fStretchX , m_fStretchY , m_fStretchZ , m_fSize , +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fParam1 , m_fParam2 , m_ptTexture , m_ctCount , m_fMipFactorDisappear ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_SANDFLOW : +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_SandFlow (this , m_fStretchAll , m_fSize , m_fParam1 , m_fActivateTime , m_fDeactivateTime , m_ctCount ); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_WATERFLOW : +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_WaterFlow (this , m_fStretchAll , m_fSize , m_fParam1 , m_fActivateTime , m_fDeactivateTime , m_ctCount ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_LAVAFLOW : +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_LavaFlow (this , m_fStretchAll , m_fSize , m_fParam1 , m_fActivateTime , m_fDeactivateTime , m_ctCount ); +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_LAVAERUPTING : +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_LavaErupting (this , m_fStretchAll , m_fSize , m_fStretchX , m_fStretchY , m_fStretchZ , m_fActivateTime ); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_WATERFALLFOAM : +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_WaterfallFoam (this , +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fStretchX , m_fStretchY , m_fStretchZ , m_fSize , +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fParam1 , m_fParam2 , m_fParam3 , m_ctCount ); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_CHIMNEYSMOKE : +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_ChimneySmoke (this , m_ctCount , m_fStretchAll , m_fMipFactorDisappear ); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_ROCKETMOTOR : +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_RocketMotorBurning (this , m_ctCount , +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +FLOAT3D (m_fStretchX , m_fStretchY , m_fStretchZ ) , m_fSize , m_ctCount ); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_COLLECT_ENERGY : +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_CollectEnergy (this , m_fActivateTime , m_fActivateTime + 2.0f); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_TWISTER : +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_Twister (this , 1.0f , 0.0f , 1e6 , 1.0f); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +case PHT_WATERFALL : +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Particles_Waterfall (this , m_ctCount , m_fStretchAll , m_fStretchX , m_fStretchY , m_fStretchZ , +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fSize , m_fMipFactorDisappear , m_fParam1 ); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +break ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} + +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +BOOL CParticlesHolder::IsTargetable(void)const +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{ +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +return m_bTargetable ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} + +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +void CParticlesHolder::MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX) +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{ +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fStretchAll *= fStretch ; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(bMirrorX ){ +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fStretchX = - m_fStretchX ; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} + +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +void CParticlesHolder::StretchModel(void) { +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(Abs (m_fStretchX ) < 0.01f){m_fStretchX = 0.01f;} +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(Abs (m_fStretchY ) < 0.01f){m_fStretchY = 0.01f;} +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(Abs (m_fStretchZ ) < 0.01f){m_fStretchZ = 0.01f;} +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(m_fStretchAll < 0.01f){m_fStretchAll = 0.01f;} +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(Abs (m_fStretchX ) > 100.0f){m_fStretchX = 100.0f * Sgn (m_fStretchX );} +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(Abs (m_fStretchY ) > 100.0f){m_fStretchY = 100.0f * Sgn (m_fStretchY );} +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(Abs (m_fStretchZ ) > 100.0f){m_fStretchZ = 100.0f * Sgn (m_fStretchZ );} +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(m_fStretchAll > 100.0f){m_fStretchAll = 100.0f;} +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +GetModelObject () -> StretchModel (FLOAT3D ( +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fStretchAll * m_fStretchX , +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fStretchAll * m_fStretchY , +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fStretchAll * m_fStretchZ )); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +ModelChangeNotify (); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} + +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +CPlacement3D CParticlesHolder::GetLerpedPlacement(void)const +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{ +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +return CEntity :: GetLerpedPlacement (); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} + +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +SLONG CParticlesHolder::GetUsedMemory(void) +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +SLONG slUsedMemory = sizeof (CParticlesHolder ) - sizeof (CMovableModelEntity ) + CMovableModelEntity :: GetUsedMemory (); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +slUsedMemory += m_strName . Length (); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +slUsedMemory += m_strDescription . Length (); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +return slUsedMemory ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} +BOOL CParticlesHolder:: +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Active(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CParticlesHolder_Active + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CParticlesHolder::Active expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_bActive = TRUE ; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Jump(STATE_CURRENT,0x00df0003, FALSE, EInternal());return TRUE;}BOOL CParticlesHolder::H0x00df0003_Active_03(const CEntityEvent &__eeInput) +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00df0003 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00df0004, FALSE, EInternal());return TRUE;} +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +SetTimerAfter(m_fParam2 + FRnd () * m_fParam3 ); +Jump(STATE_CURRENT, 0x00df0001, FALSE, EBegin());return TRUE;}BOOL CParticlesHolder::H0x00df0001_Active_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00df0001 +switch(__eeInput.ee_slEvent) +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{case(EVENTCODE_ETimer): +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{const ETimer&e= (ETimer&)__eeInput; + +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(m_phtType == PHT_LAVAERUPTING ) +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{ +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fActivateTime = _pTimer -> CurrentTick (); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +UnsetTimer();Jump(STATE_CURRENT,0x00df0002, FALSE, EInternal());return TRUE; +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EBegin): +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{const EBegin&e= (EBegin&)__eeInput; + +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +return TRUE; +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate): +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fDeactivateTime = _pTimer -> CurrentTick (); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Jump(STATE_CURRENT, STATE_CParticlesHolder_Inactive, TRUE, EVoid());return TRUE; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +}return TRUE;}BOOL CParticlesHolder::H0x00df0002_Active_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00df0002 +Jump(STATE_CURRENT,0x00df0003, FALSE, EInternal());return TRUE; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +}BOOL CParticlesHolder::H0x00df0004_Active_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00df0004 + ASSERT(FALSE); return TRUE;};BOOL CParticlesHolder:: +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Inactive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CParticlesHolder_Inactive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CParticlesHolder::Inactive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_bActive = FALSE ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00df0006, FALSE, EBegin());return TRUE;}BOOL CParticlesHolder::H0x00df0006_Inactive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00df0006 +switch(__eeInput.ee_slEvent) +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EActivate): +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +{const EActivate&e= (EActivate&)__eeInput; + +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fActivateTime = _pTimer -> CurrentTick (); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fDeactivateTime = _pTimer -> CurrentTick () + 10000.0f; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Jump(STATE_CURRENT, STATE_CParticlesHolder_Active, TRUE, EVoid());return TRUE; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +}return TRUE;}BOOL CParticlesHolder::H0x00df0007_Inactive_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00df0007 + ASSERT(FALSE); return TRUE;};BOOL CParticlesHolder:: +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CParticlesHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CParticlesHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +InitAsEditorModel (); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +StretchModel (); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +SetModel (MODEL_TELEPORT ); +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +ModelChangeNotify (); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +SetModelMainTexture (TEXTURE_TELEPORT ); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(m_bBackground ){ +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +SetFlags (GetFlags () | ENF_BACKGROUND ); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +}else { +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +SetFlags (GetFlags () & ~ ENF_BACKGROUND ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +en_fGravityA = 30.0f; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +GetPitchDirection (- 90.0f , en_vGravityDir ); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fActivateTime = 0.0f; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +m_fDeactivateTime = - 10000.0f; +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +if(m_bActive ){ +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Jump(STATE_CURRENT, STATE_CParticlesHolder_Active, TRUE, EVoid());return TRUE; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +}else { +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Jump(STATE_CURRENT, STATE_CParticlesHolder_Inactive, TRUE, EVoid());return TRUE; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +} +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ParticlesHolder.es b/Sources/EntitiesMP/ParticlesHolder.es new file mode 100644 index 0000000..9774f22 --- /dev/null +++ b/Sources/EntitiesMP/ParticlesHolder.es @@ -0,0 +1,276 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +223 +%{ +#include "StdH.h" +%} + +enum ParticlesHolderType { + 1 PHT_SPIRAL "Spiral", + 2 PHT_EMANATE "Emanate", + 3 PHT_STARDUST "Stardust", + 4 PHT_ATOMIC "Atomic", + 5 PHT_RISING "Rising", + 6 PHT_FOUNTAIN "Fountain", + 7 PHT_SMOKE "Smoke", + 8 PHT_BLOOD "Blood", + 9 PHT_EMANATEPLANE "EmanatePlane", + 10 PHT_SANDFLOW "SandFlow", + 11 PHT_WATERFLOW "WaterFlow", + 12 PHT_LAVAFLOW "Lava Flow", + 13 PHT_LAVAERUPTING "Lava Erupting", + 14 PHT_WATERFALLFOAM "Waterfall foam", + 15 PHT_CHIMNEYSMOKE "Chimney smoke", + 16 PHT_WATERFALL "Waterfall", + 17 PHT_TWISTER "Twister", + 18 PHT_ROCKETMOTOR "Rocket motor", + 19 PHT_COLLECT_ENERGY "Collect energy", +}; + +class CParticlesHolder : CMovableModelEntity { +name "ParticlesHolder"; +thumbnail "Thumbnails\\ParticlesHolder.tbn"; +features "HasName", "HasDescription"; + + +properties: + + 1 enum ParticlesHolderType m_phtType "Type" 'Y' = PHT_SPIRAL, + 2 enum ParticleTexture m_ptTexture "Texture" 'T' = PT_STAR01, + 3 INDEX m_ctCount "Count" 'C' = 16, + 4 FLOAT m_fStretchAll "StretchAll" 'S' = 1.0f, + 5 FLOAT m_fStretchX "StretchX" 'X' = 1.0f, + 6 FLOAT m_fStretchY "StretchY" 'Y' = 1.0f, + 7 FLOAT m_fStretchZ "StretchZ" 'Z' = 1.0f, + 8 CTString m_strName "Name" 'N' ="", + 12 CTString m_strDescription = "", + 13 BOOL m_bBackground "Background" 'B' = FALSE, // set if model is rendered in background + 21 BOOL m_bTargetable "Targetable" = FALSE, // st if model should be targetable + 30 FLOAT m_fSize "Size" = 0.1f, + 31 FLOAT m_fParam1 "Param1" 'P' = 1.0f, + 32 FLOAT m_fParam2 "Param2" = 1.0f, + 33 FLOAT m_fParam3 "Param3" = 1.0f, + 34 BOOL m_bActive "Active" 'A' = TRUE, // is particles are active + 35 FLOAT m_fActivateTime = 0.0f, + 36 FLOAT m_fDeactivateTime = -10000.0f, + 37 FLOAT m_fMipFactorDisappear "Disappear mip factor" = 8.0f, + + +components: + + 1 model MODEL_TELEPORT "Models\\Editor\\Teleport.mdl", + 2 texture TEXTURE_TELEPORT "Models\\Editor\\BoundingBox.tex", + + +functions: + + // render particles + void RenderParticles(void) + { + if( !m_bActive) + { + return; + } + switch (m_phtType) + { + case PHT_SPIRAL : + Particles_Spiral(this, m_fStretchAll, m_fStretchAll/2, m_ptTexture, m_ctCount); + break; + case PHT_EMANATE : + Particles_Emanate(this, m_fStretchAll, m_fStretchAll/2, m_ptTexture, m_ctCount, m_fMipFactorDisappear); + break; + case PHT_STARDUST : + Particles_Stardust(this, m_fStretchAll, m_fStretchAll/2, m_ptTexture, m_ctCount); + break; + case PHT_ATOMIC : + Particles_Atomic(this, m_fStretchAll, m_fStretchAll/2, m_ptTexture, m_ctCount); + break; + case PHT_RISING : + Particles_Rising(this, m_fActivateTime, m_fDeactivateTime, m_fStretchAll, m_fStretchX, m_fStretchY, m_fStretchZ, m_fSize, m_ptTexture, m_ctCount); + break; + case PHT_FOUNTAIN : + Particles_Fountain(this, m_fStretchAll, m_fStretchAll/2, m_ptTexture, m_ctCount); + break; + case PHT_SMOKE : + Particles_GrenadeTrail(this); + break; + case PHT_BLOOD : + Particles_BloodTrail(this); + break; + case PHT_EMANATEPLANE: + Particles_EmanatePlane(this, + m_fStretchX, m_fStretchY, m_fStretchZ, m_fSize, + m_fParam1, m_fParam2, m_ptTexture, m_ctCount, m_fMipFactorDisappear); + break; + case PHT_SANDFLOW : + Particles_SandFlow(this, m_fStretchAll, m_fSize, m_fParam1, m_fActivateTime, m_fDeactivateTime, m_ctCount); + break; + case PHT_WATERFLOW : + Particles_WaterFlow(this, m_fStretchAll, m_fSize, m_fParam1, m_fActivateTime, m_fDeactivateTime, m_ctCount); + break; + case PHT_LAVAFLOW : + Particles_LavaFlow(this, m_fStretchAll, m_fSize, m_fParam1, m_fActivateTime, m_fDeactivateTime, m_ctCount); + break; + case PHT_LAVAERUPTING: + Particles_LavaErupting(this, m_fStretchAll, m_fSize, m_fStretchX, m_fStretchY, m_fStretchZ, m_fActivateTime); + break; + case PHT_WATERFALLFOAM: + Particles_WaterfallFoam(this, + m_fStretchX, m_fStretchY, m_fStretchZ, m_fSize, + m_fParam1, m_fParam2, m_fParam3, m_ctCount); + break; + case PHT_CHIMNEYSMOKE: + Particles_ChimneySmoke(this, m_ctCount, m_fStretchAll, m_fMipFactorDisappear); + break; + case PHT_ROCKETMOTOR: + Particles_RocketMotorBurning(this, m_ctCount, + FLOAT3D(m_fStretchX,m_fStretchY,m_fStretchZ), m_fSize, m_ctCount); + break; + case PHT_COLLECT_ENERGY: + Particles_CollectEnergy(this, m_fActivateTime, m_fActivateTime+2.0f); + break; + case PHT_TWISTER: + Particles_Twister(this, 1.0f, 0.0f, 1e6, 1.0f); + break; + case PHT_WATERFALL: + Particles_Waterfall(this, m_ctCount, m_fStretchAll, m_fStretchX, m_fStretchY, m_fStretchZ, + m_fSize, m_fMipFactorDisappear, m_fParam1); + break; + } + } + BOOL IsTargetable(void) const + { + return m_bTargetable; + } + + // apply mirror and stretch to the entity + void MirrorAndStretch(FLOAT fStretch, BOOL bMirrorX) + { + m_fStretchAll*=fStretch; + if (bMirrorX) { + m_fStretchX = -m_fStretchX; + } + } + + // Stretch model + void StretchModel(void) { + // stretch factors must not have extreme values + if (Abs(m_fStretchX) < 0.01f) { m_fStretchX = 0.01f; } + if (Abs(m_fStretchY) < 0.01f) { m_fStretchY = 0.01f; } + if (Abs(m_fStretchZ) < 0.01f) { m_fStretchZ = 0.01f; } + if (m_fStretchAll< 0.01f) { m_fStretchAll = 0.01f; } + + if (Abs(m_fStretchX) >100.0f) { m_fStretchX = 100.0f*Sgn(m_fStretchX); } + if (Abs(m_fStretchY) >100.0f) { m_fStretchY = 100.0f*Sgn(m_fStretchY); } + if (Abs(m_fStretchZ) >100.0f) { m_fStretchZ = 100.0f*Sgn(m_fStretchZ); } + if (m_fStretchAll>100.0f) { m_fStretchAll = 100.0f; } + + GetModelObject()->StretchModel( FLOAT3D( + m_fStretchAll*m_fStretchX, + m_fStretchAll*m_fStretchY, + m_fStretchAll*m_fStretchZ) ); + ModelChangeNotify(); + }; + + CPlacement3D GetLerpedPlacement(void) const + { + return CEntity::GetLerpedPlacement(); // we never move anyway, so let's be able to be parented + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CParticlesHolder) - sizeof(CMovableModelEntity) + CMovableModelEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strName.Length(); + slUsedMemory += m_strDescription.Length(); + return slUsedMemory; + } + + +procedures: + + + // particles are active + Active() + { + m_bActive = TRUE; + while( TRUE) + { + // wait defined time + wait( m_fParam2+FRnd()*m_fParam3) + { + on (ETimer) : + { + // for randomly spawned particles + if( m_phtType == PHT_LAVAERUPTING) + { + // spawn new particles + m_fActivateTime = _pTimer->CurrentTick(); + } + stop; + } + on (EBegin) : + { + resume; + } + on (EDeactivate) : + { + m_fDeactivateTime = _pTimer->CurrentTick(); + jump Inactive(); + } + } + } + }; + + // particles are not active + Inactive() { + m_bActive = FALSE; + wait() + { + on (EBegin) : { resume; } + on (EActivate) : + { + m_fActivateTime = _pTimer->CurrentTick(); + m_fDeactivateTime = _pTimer->CurrentTick()+10000.0f; + jump Active(); + } + } + }; + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + StretchModel(); + SetModel(MODEL_TELEPORT); + ModelChangeNotify(); + SetModelMainTexture(TEXTURE_TELEPORT); + + if (m_bBackground) { + SetFlags(GetFlags()|ENF_BACKGROUND); + } else { + SetFlags(GetFlags()&~ENF_BACKGROUND); + } + + en_fGravityA = 30.0f; + GetPitchDirection(-90.0f, en_vGravityDir); + + m_fActivateTime = 0.0f; + m_fDeactivateTime = -10000.0f; + + if (m_bActive) { + jump Active(); + } else { + jump Inactive(); + } + + + return; + } +}; diff --git a/Sources/EntitiesMP/ParticlesHolder.h b/Sources/EntitiesMP/ParticlesHolder.h new file mode 100644 index 0000000..2bd7b2f --- /dev/null +++ b/Sources/EntitiesMP/ParticlesHolder.h @@ -0,0 +1,92 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ParticlesHolder_INCLUDED +#define _EntitiesMP_ParticlesHolder_INCLUDED 1 +extern DECL_DLL CEntityPropertyEnumType ParticlesHolderType_enum; +enum ParticlesHolderType { + PHT_SPIRAL = 1, + PHT_EMANATE = 2, + PHT_STARDUST = 3, + PHT_ATOMIC = 4, + PHT_RISING = 5, + PHT_FOUNTAIN = 6, + PHT_SMOKE = 7, + PHT_BLOOD = 8, + PHT_EMANATEPLANE = 9, + PHT_SANDFLOW = 10, + PHT_WATERFLOW = 11, + PHT_LAVAFLOW = 12, + PHT_LAVAERUPTING = 13, + PHT_WATERFALLFOAM = 14, + PHT_CHIMNEYSMOKE = 15, + PHT_WATERFALL = 16, + PHT_TWISTER = 17, + PHT_ROCKETMOTOR = 18, + PHT_COLLECT_ENERGY = 19, +}; +DECL_DLL inline void ClearToDefault(ParticlesHolderType &e) { e = (ParticlesHolderType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CParticlesHolder_DLLClass; +class CParticlesHolder : public CMovableModelEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual const CTString &GetDescription(void) const { return m_strDescription; }; + DECL_DLL virtual void SetDefaultProperties(void); + enum ParticlesHolderType m_phtType; + enum ParticleTexture m_ptTexture; + INDEX m_ctCount; + FLOAT m_fStretchAll; + FLOAT m_fStretchX; + FLOAT m_fStretchY; + FLOAT m_fStretchZ; + CTString m_strName; + CTString m_strDescription; + BOOL m_bBackground; + BOOL m_bTargetable; + FLOAT m_fSize; + FLOAT m_fParam1; + FLOAT m_fParam2; + FLOAT m_fParam3; + BOOL m_bActive; + FLOAT m_fActivateTime; + FLOAT m_fDeactivateTime; + FLOAT m_fMipFactorDisappear; + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +void RenderParticles(void); + +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +BOOL IsTargetable(void)const; + +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +void MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX); + +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +void StretchModel(void); + +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +CPlacement3D GetLerpedPlacement(void)const; + +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +SLONG GetUsedMemory(void); +#define STATE_CParticlesHolder_Active 0x00df0000 + BOOL +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Active(const CEntityEvent &__eeInput); + BOOL H0x00df0001_Active_01(const CEntityEvent &__eeInput); + BOOL H0x00df0002_Active_02(const CEntityEvent &__eeInput); + BOOL H0x00df0003_Active_03(const CEntityEvent &__eeInput); + BOOL H0x00df0004_Active_04(const CEntityEvent &__eeInput); +#define STATE_CParticlesHolder_Inactive 0x00df0005 + BOOL +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Inactive(const CEntityEvent &__eeInput); + BOOL H0x00df0006_Inactive_01(const CEntityEvent &__eeInput); + BOOL H0x00df0007_Inactive_02(const CEntityEvent &__eeInput); +#define STATE_CParticlesHolder_Main 1 + BOOL +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ParticlesHolder_INCLUDED diff --git a/Sources/EntitiesMP/ParticlesHolder_tables.h b/Sources/EntitiesMP/ParticlesHolder_tables.h new file mode 100644 index 0000000..407e58d --- /dev/null +++ b/Sources/EntitiesMP/ParticlesHolder_tables.h @@ -0,0 +1,88 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(ParticlesHolderType) + EP_ENUMVALUE(PHT_SPIRAL, "Spiral"), + EP_ENUMVALUE(PHT_EMANATE, "Emanate"), + EP_ENUMVALUE(PHT_STARDUST, "Stardust"), + EP_ENUMVALUE(PHT_ATOMIC, "Atomic"), + EP_ENUMVALUE(PHT_RISING, "Rising"), + EP_ENUMVALUE(PHT_FOUNTAIN, "Fountain"), + EP_ENUMVALUE(PHT_SMOKE, "Smoke"), + EP_ENUMVALUE(PHT_BLOOD, "Blood"), + EP_ENUMVALUE(PHT_EMANATEPLANE, "EmanatePlane"), + EP_ENUMVALUE(PHT_SANDFLOW, "SandFlow"), + EP_ENUMVALUE(PHT_WATERFLOW, "WaterFlow"), + EP_ENUMVALUE(PHT_LAVAFLOW, "Lava Flow"), + EP_ENUMVALUE(PHT_LAVAERUPTING, "Lava Erupting"), + EP_ENUMVALUE(PHT_WATERFALLFOAM, "Waterfall foam"), + EP_ENUMVALUE(PHT_CHIMNEYSMOKE, "Chimney smoke"), + EP_ENUMVALUE(PHT_WATERFALL, "Waterfall"), + EP_ENUMVALUE(PHT_TWISTER, "Twister"), + EP_ENUMVALUE(PHT_ROCKETMOTOR, "Rocket motor"), + EP_ENUMVALUE(PHT_COLLECT_ENERGY, "Collect energy"), +EP_ENUMEND(ParticlesHolderType); + +#define ENTITYCLASS CParticlesHolder + +CEntityProperty CParticlesHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &ParticlesHolderType_enum, (0x000000df<<8)+1, offsetof(CParticlesHolder, m_phtType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &ParticleTexture_enum, (0x000000df<<8)+2, offsetof(CParticlesHolder, m_ptTexture), "Texture", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000df<<8)+3, offsetof(CParticlesHolder, m_ctCount), "Count", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000df<<8)+4, offsetof(CParticlesHolder, m_fStretchAll), "StretchAll", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000df<<8)+5, offsetof(CParticlesHolder, m_fStretchX), "StretchX", 'X', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000df<<8)+6, offsetof(CParticlesHolder, m_fStretchY), "StretchY", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000df<<8)+7, offsetof(CParticlesHolder, m_fStretchZ), "StretchZ", 'Z', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000df<<8)+8, offsetof(CParticlesHolder, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000df<<8)+12, offsetof(CParticlesHolder, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000df<<8)+13, offsetof(CParticlesHolder, m_bBackground), "Background", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000df<<8)+21, offsetof(CParticlesHolder, m_bTargetable), "Targetable", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000df<<8)+30, offsetof(CParticlesHolder, m_fSize), "Size", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000df<<8)+31, offsetof(CParticlesHolder, m_fParam1), "Param1", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000df<<8)+32, offsetof(CParticlesHolder, m_fParam2), "Param2", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000df<<8)+33, offsetof(CParticlesHolder, m_fParam3), "Param3", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000df<<8)+34, offsetof(CParticlesHolder, m_bActive), "Active", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000df<<8)+35, offsetof(CParticlesHolder, m_fActivateTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000df<<8)+36, offsetof(CParticlesHolder, m_fDeactivateTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000df<<8)+37, offsetof(CParticlesHolder, m_fMipFactorDisappear), "Disappear mip factor", 0, 0x7F0000FFUL, 0), +}; +#define CParticlesHolder_propertiesct ARRAYCOUNT(CParticlesHolder_properties) + +CEntityComponent CParticlesHolder_components[] = { +#define MODEL_TELEPORT ((0x000000df<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_TELEPORT, "EFNM" "Models\\Editor\\Teleport.mdl"), +#define TEXTURE_TELEPORT ((0x000000df<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_TELEPORT, "EFNM" "Models\\Editor\\BoundingBox.tex"), +}; +#define CParticlesHolder_componentsct ARRAYCOUNT(CParticlesHolder_components) + +CEventHandlerEntry CParticlesHolder_handlers[] = { + {0x00df0000, -1, CEntity::pEventHandler(&CParticlesHolder:: +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Active),DEBUGSTRING("CParticlesHolder::Active")}, + {0x00df0001, -1, CEntity::pEventHandler(&CParticlesHolder::H0x00df0001_Active_01), DEBUGSTRING("CParticlesHolder::H0x00df0001_Active_01")}, + {0x00df0002, -1, CEntity::pEventHandler(&CParticlesHolder::H0x00df0002_Active_02), DEBUGSTRING("CParticlesHolder::H0x00df0002_Active_02")}, + {0x00df0003, -1, CEntity::pEventHandler(&CParticlesHolder::H0x00df0003_Active_03), DEBUGSTRING("CParticlesHolder::H0x00df0003_Active_03")}, + {0x00df0004, -1, CEntity::pEventHandler(&CParticlesHolder::H0x00df0004_Active_04), DEBUGSTRING("CParticlesHolder::H0x00df0004_Active_04")}, + {0x00df0005, -1, CEntity::pEventHandler(&CParticlesHolder:: +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Inactive),DEBUGSTRING("CParticlesHolder::Inactive")}, + {0x00df0006, -1, CEntity::pEventHandler(&CParticlesHolder::H0x00df0006_Inactive_01), DEBUGSTRING("CParticlesHolder::H0x00df0006_Inactive_01")}, + {0x00df0007, -1, CEntity::pEventHandler(&CParticlesHolder::H0x00df0007_Inactive_02), DEBUGSTRING("CParticlesHolder::H0x00df0007_Inactive_02")}, + {1, -1, CEntity::pEventHandler(&CParticlesHolder:: +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/ParticlesHolder.es" +Main),DEBUGSTRING("CParticlesHolder::Main")}, +}; +#define CParticlesHolder_handlersct ARRAYCOUNT(CParticlesHolder_handlers) + +CEntity *CParticlesHolder_New(void) { return new CParticlesHolder; }; +void CParticlesHolder_OnInitClass(void) {}; +void CParticlesHolder_OnEndClass(void) {}; +void CParticlesHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CParticlesHolder_OnWorldEnd(CWorld *pwo) {}; +void CParticlesHolder_OnWorldInit(CWorld *pwo) {}; +void CParticlesHolder_OnWorldTick(CWorld *pwo) {}; +void CParticlesHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CParticlesHolder, CMovableModelEntity, "ParticlesHolder", "Thumbnails\\ParticlesHolder.tbn", 0x000000df); +DECLARE_CTFILENAME(_fnmCParticlesHolder_tbn, "Thumbnails\\ParticlesHolder.tbn"); diff --git a/Sources/EntitiesMP/Pendulum.cpp b/Sources/EntitiesMP/Pendulum.cpp new file mode 100644 index 0000000..e596c4c --- /dev/null +++ b/Sources/EntitiesMP/Pendulum.cpp @@ -0,0 +1,163 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" + +#include "StdH.h" + +#include +#include +void CPendulum::SetDefaultProperties(void) { + m_strName = "Pendulum"; + m_bDynamicShadows = FALSE ; + m_fMaxAngle = 60.0f; + m_fSpeed = 0.0f; + m_fDampFactor = 0.9f; + m_fPendulumFactor = 1.0f; + m_fImpulseFactor = 0.01f; + m_fTriggerImpulse = 10.0f; + m_bActive = TRUE ; + CMovableBrushEntity::SetDefaultProperties(); +} + +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +void CPendulum::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +{ +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +if(! m_bActive ) +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +{ +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +return ; +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +} +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +FLOAT3D vOscilatingDirection ; +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +GetHeadingDirection (- 90.0f , vOscilatingDirection ); +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +FLOAT fImpulse = vDirection % vOscilatingDirection ; +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +fImpulse *= fDamageAmmount * m_fImpulseFactor ; +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +m_fSpeed += fImpulse ; +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +SetDesiredRotation (ANGLE3D (0 , 0 , m_fSpeed )); +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +} + +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +void CPendulum::PostMoving() +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +{ +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +CMovableBrushEntity :: PostMoving (); +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +ANGLE fCurrentBanking = GetPlacement () . pl_OrientationAngle (3); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +FLOAT fNewSpeed = m_fSpeed * m_fDampFactor - m_fPendulumFactor * fCurrentBanking ; +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +if(Abs (fCurrentBanking ) > m_fMaxAngle && Sgn (fNewSpeed ) == Sgn (fCurrentBanking )) +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +{ +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +fNewSpeed = 0.0f; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +} +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +m_fSpeed = fNewSpeed ; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +SetDesiredRotation (ANGLE3D (0 , 0 , fNewSpeed )); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +if(Abs (fCurrentBanking ) > 1.0f) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +{ +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +SetFlags (GetFlags () & ~ ENF_INRENDERING ); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +} +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +} +BOOL CPendulum:: +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPendulum_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPendulum::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +InitAsBrush (); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +SetPhysicsFlags (EPF_BRUSH_MOVING ); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +SetCollisionFlags (ECF_BRUSH ); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +SetFlags (GetFlags () & ~ ENF_ZONING ); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +if(m_bDynamicShadows ){ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +SetFlags (GetFlags () | ENF_DYNAMICSHADOWS ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +}else { +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +SetFlags (GetFlags () & ~ ENF_DYNAMICSHADOWS ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +} +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x006a0000, FALSE, EBegin());return TRUE;}BOOL CPendulum::H0x006a0000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x006a0000 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EActivate): +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +{const EActivate&e= (EActivate&)__eeInput; + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +m_bActive = TRUE ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +return TRUE; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate): +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +m_bActive = FALSE ; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +return TRUE; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger): +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +{const ETrigger&e= (ETrigger&)__eeInput; + +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +if(m_bActive ) +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +{ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +m_fSpeed += m_fTriggerImpulse ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +AddToMovers (); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +} +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +return TRUE; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +}return TRUE;}BOOL CPendulum::H0x006a0001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x006a0001 + +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +Destroy (); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +UnsetTimer();Jump(STATE_CURRENT,0x006a0001, FALSE, EInternal());return TRUE; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +Return(STATE_CURRENT,EVoid()); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Pendulum.es b/Sources/EntitiesMP/Pendulum.es new file mode 100644 index 0000000..e3a833b --- /dev/null +++ b/Sources/EntitiesMP/Pendulum.es @@ -0,0 +1,114 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +106 +%{ +#include "StdH.h" +%} + + +class CPendulum: CMovableBrushEntity { +name "Pendulum"; +thumbnail "Thumbnails\\Pendulum.tbn"; +features "HasName", "IsTargetable"; +properties: + 1 CTString m_strName "Name" 'N' = "Pendulum", // name + 2 BOOL m_bDynamicShadows "Dynamic shadows" = FALSE, // if has dynamic shadows + 3 FLOAT m_fMaxAngle "Maximum angle" = 60.0f, // pendulum will never go over this angle + 5 FLOAT m_fSpeed = 0.0f, // current speed + 6 FLOAT m_fDampFactor "Damp factor" = 0.9f, // dump factor + 7 FLOAT m_fPendulumFactor "Pendulum factor" = 1.0f, // pendulum factor + 8 FLOAT m_fImpulseFactor "Damage impulse factor" = 0.01f, // factor applied to damage ammount + 9 FLOAT m_fTriggerImpulse "Impulse on trigger" = 10.0f, // ipulse given on trigger + 10 BOOL m_bActive "Active" 'A' = TRUE, // if pendulum is active by default + +components: +functions: + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + if( !m_bActive) + { + return; + } + // get vector in direction of oscilation + FLOAT3D vOscilatingDirection; + GetHeadingDirection( -90.0f, vOscilatingDirection); + // project damage direction onto oscilating direction + FLOAT fImpulse = vDirection%vOscilatingDirection; + // calculate impulse strength + fImpulse *= fDamageAmmount*m_fImpulseFactor; + // apply impulse + m_fSpeed += fImpulse; + SetDesiredRotation( ANGLE3D(0, 0, m_fSpeed)); + } + + /* Post moving */ + void PostMoving() + { + CMovableBrushEntity::PostMoving(); + ANGLE fCurrentBanking = GetPlacement().pl_OrientationAngle(3); + FLOAT fNewSpeed = m_fSpeed*m_fDampFactor-m_fPendulumFactor*fCurrentBanking; + + // if maximum angle achieved, stop in place and turn back + if( Abs( fCurrentBanking) > m_fMaxAngle && Sgn(fNewSpeed)==Sgn(fCurrentBanking)) + { + fNewSpeed = 0.0f; + } + + m_fSpeed = fNewSpeed; + SetDesiredRotation( ANGLE3D(0, 0, fNewSpeed)); + + // if angle is not zero + if (Abs( fCurrentBanking) > 1.0f) + { + // clear in rendering flag + SetFlags(GetFlags()&~ENF_INRENDERING); + } + }; + +procedures: + Main() { + // declare yourself as a brush + InitAsBrush(); + SetPhysicsFlags(EPF_BRUSH_MOVING); + SetCollisionFlags(ECF_BRUSH); + // non-zoning brush + SetFlags(GetFlags()&~ENF_ZONING); + + // set dynamic shadows as needed + if (m_bDynamicShadows) { + SetFlags(GetFlags()|ENF_DYNAMICSHADOWS); + } else { + SetFlags(GetFlags()&~ENF_DYNAMICSHADOWS); + } + + // start moving + wait() { + on( EActivate): + { + m_bActive = TRUE; + resume; + } + on( EDeactivate): + { + m_bActive = FALSE; + resume; + } + on( ETrigger): + { + if( m_bActive) + { + // apply impulse + m_fSpeed += m_fTriggerImpulse; + AddToMovers(); + } + resume; + } + } + + Destroy(); + stop; + return; + } +}; diff --git a/Sources/EntitiesMP/Pendulum.h b/Sources/EntitiesMP/Pendulum.h new file mode 100644 index 0000000..6b5f59f --- /dev/null +++ b/Sources/EntitiesMP/Pendulum.h @@ -0,0 +1,37 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Pendulum_INCLUDED +#define _EntitiesMP_Pendulum_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CPendulum_DLLClass; +class CPendulum : public CMovableBrushEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + BOOL m_bDynamicShadows; + FLOAT m_fMaxAngle; + FLOAT m_fSpeed; + FLOAT m_fDampFactor; + FLOAT m_fPendulumFactor; + FLOAT m_fImpulseFactor; + FLOAT m_fTriggerImpulse; + BOOL m_bActive; + +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +void PostMoving(); +#define STATE_CPendulum_Main 1 + BOOL +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x006a0000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x006a0001_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Pendulum_INCLUDED diff --git a/Sources/EntitiesMP/Pendulum_tables.h b/Sources/EntitiesMP/Pendulum_tables.h new file mode 100644 index 0000000..fbab4f3 --- /dev/null +++ b/Sources/EntitiesMP/Pendulum_tables.h @@ -0,0 +1,44 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CPendulum + +CEntityProperty CPendulum_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x0000006a<<8)+1, offsetof(CPendulum, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000006a<<8)+2, offsetof(CPendulum, m_bDynamicShadows), "Dynamic shadows", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000006a<<8)+3, offsetof(CPendulum, m_fMaxAngle), "Maximum angle", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000006a<<8)+5, offsetof(CPendulum, m_fSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000006a<<8)+6, offsetof(CPendulum, m_fDampFactor), "Damp factor", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000006a<<8)+7, offsetof(CPendulum, m_fPendulumFactor), "Pendulum factor", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000006a<<8)+8, offsetof(CPendulum, m_fImpulseFactor), "Damage impulse factor", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000006a<<8)+9, offsetof(CPendulum, m_fTriggerImpulse), "Impulse on trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000006a<<8)+10, offsetof(CPendulum, m_bActive), "Active", 'A', 0x7F0000FFUL, 0), +}; +#define CPendulum_propertiesct ARRAYCOUNT(CPendulum_properties) + +CEntityComponent CPendulum_components[] = { + CEntityComponent() +}; +#define CPendulum_componentsct 0 + + +CEventHandlerEntry CPendulum_handlers[] = { + {1, -1, CEntity::pEventHandler(&CPendulum:: +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Pendulum.es" +Main),DEBUGSTRING("CPendulum::Main")}, + {0x006a0000, -1, CEntity::pEventHandler(&CPendulum::H0x006a0000_Main_01), DEBUGSTRING("CPendulum::H0x006a0000_Main_01")}, + {0x006a0001, -1, CEntity::pEventHandler(&CPendulum::H0x006a0001_Main_02), DEBUGSTRING("CPendulum::H0x006a0001_Main_02")}, +}; +#define CPendulum_handlersct ARRAYCOUNT(CPendulum_handlers) + +CEntity *CPendulum_New(void) { return new CPendulum; }; +void CPendulum_OnInitClass(void) {}; +void CPendulum_OnEndClass(void) {}; +void CPendulum_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPendulum_OnWorldEnd(CWorld *pwo) {}; +void CPendulum_OnWorldInit(CWorld *pwo) {}; +void CPendulum_OnWorldTick(CWorld *pwo) {}; +void CPendulum_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPendulum, CMovableBrushEntity, "Pendulum", "Thumbnails\\Pendulum.tbn", 0x0000006a); +DECLARE_CTFILENAME(_fnmCPendulum_tbn, "Thumbnails\\Pendulum.tbn"); diff --git a/Sources/EntitiesMP/PhotoAlbum.cpp b/Sources/EntitiesMP/PhotoAlbum.cpp new file mode 100644 index 0000000..afb5ffb --- /dev/null +++ b/Sources/EntitiesMP/PhotoAlbum.cpp @@ -0,0 +1,230 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" + +#include "StdH.h" +#include "ModelsMP/CutSequences/Book/Book.h" +#include "ModelsMP/CutSequences/Book/CoverPages.h" + +#include +#include +void CPhotoAlbum::SetDefaultProperties(void) { + m_fStretch = 1.0f; + m_strName = "Photo album"; + m_iCurrentPage = -1; + m_tmPageWait = 0.5f; + m_soPage.SetOwner(this); +m_soPage.Stop_internal(); + CMovableModelEntity::SetDefaultProperties(); +} + +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +void CPhotoAlbum::Precache(void) { +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PrecacheTexture (TEXTURE_PAGE01 ); +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PrecacheTexture (TEXTURE_PAGE02 ); +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PrecacheTexture (TEXTURE_PAGE03 ); +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PrecacheTexture (TEXTURE_PAGE04 ); +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PrecacheTexture (TEXTURE_PAGE_JOKE ); +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PrecacheTexture (TEXTURE_PAGE05 ); +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PrecacheTexture (TEXTURE_PAGE06 ); +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PrecacheTexture (TEXTURE_PAGE07 ); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PrecacheTexture (TEXTURE_BLANK_PAGE ); +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PrecacheSound (SOUND_PAGE ); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +} +BOOL CPhotoAlbum:: +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +OpenBook(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPhotoAlbum_OpenBook + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPhotoAlbum::OpenBook expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +GetModelObject () -> PlayAnim (BOOK_ANIM_OPENING , 0); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +CModelObject & mo1 = GetModelObject () -> GetAttachmentModel (BOOK_ATTACHMENT_PAGE01 ) -> amo_moModelObject ; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +mo1 . PlayAnim (COVERPAGES_ANIM_OPENING , 0); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +CModelObject & mo2 = GetModelObject () -> GetAttachmentModel (BOOK_ATTACHMENT_PAGE02 ) -> amo_moModelObject ; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +mo2 . PlayAnim (COVERPAGES_ANIM_RIGHTOPENING , 0); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +m_soPage . Set3DParameters (1000.0f , 500.0f , 2.0f , 1.0f); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PlaySound (m_soPage , SOUND_PAGE , SOF_3D ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (BOOK_ANIM_OPENING )); +Jump(STATE_CURRENT, 0x02660001, FALSE, EBegin());return TRUE;}BOOL CPhotoAlbum::H0x02660001_OpenBook_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02660001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02660002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPhotoAlbum::H0x02660002_OpenBook_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02660002 +; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x02660003, FALSE, EBegin());return TRUE;}BOOL CPhotoAlbum::H0x02660003_OpenBook_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02660003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02660004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPhotoAlbum::H0x02660004_OpenBook_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02660004 +; +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +m_iCurrentPage = TEXTURE_PAGE01 ; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +Jump(STATE_CURRENT,0x0266000b, FALSE, EInternal());return TRUE;}BOOL CPhotoAlbum::H0x0266000b_OpenBook_11(const CEntityEvent &__eeInput) +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0266000b +if(!(m_iCurrentPage < TEXTURE_PAGE07 )){ Jump(STATE_CURRENT,0x0266000c, FALSE, EInternal());return TRUE;} +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +SetTimerAfter(m_tmPageWait ); +Jump(STATE_CURRENT, 0x02660005, FALSE, EBegin());return TRUE;}BOOL CPhotoAlbum::H0x02660005_OpenBook_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02660005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02660006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPhotoAlbum::H0x02660006_OpenBook_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02660006 +; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +AddAttachment (BOOK_ATTACHMENT_PAGE03 , MODEL_PAGE , m_iCurrentPage ); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fStretch , m_fStretch , m_fStretch )); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +CModelObject & mo3 = GetModelObject () -> GetAttachmentModel (BOOK_ATTACHMENT_PAGE03 ) -> amo_moModelObject ; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +mo3 . PlayAnim (COVERPAGES_ANIM_OPENING , 0); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +PlaySound (m_soPage , SOUND_PAGE , SOF_3D ); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +CModelObject & mo2 = GetModelObject () -> GetAttachmentModel (BOOK_ATTACHMENT_PAGE02 ) -> amo_moModelObject ; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +mo2 . SetTextureData (GetTextureDataForComponent (m_iCurrentPage + 1)); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +SetTimerAfter(1.0f); +Jump(STATE_CURRENT, 0x02660007, FALSE, EBegin());return TRUE;}BOOL CPhotoAlbum::H0x02660007_OpenBook_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02660007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02660008, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPhotoAlbum::H0x02660008_OpenBook_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02660008 +; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +CModelObject & mo3 = GetModelObject () -> GetAttachmentModel (BOOK_ATTACHMENT_PAGE03 ) -> amo_moModelObject ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +mo3 . SetTextureData (GetTextureDataForComponent (TEXTURE_BLANK_PAGE )); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +SetTimerAfter(mo3 . GetAnimLength (COVERPAGES_ANIM_OPENING ) - 1.0f); +Jump(STATE_CURRENT, 0x02660009, FALSE, EBegin());return TRUE;}BOOL CPhotoAlbum::H0x02660009_OpenBook_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02660009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0266000a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPhotoAlbum::H0x0266000a_OpenBook_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0266000a +; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +RemoveAttachment (BOOK_ATTACHMENT_PAGE03 ); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +m_iCurrentPage += 1;Jump(STATE_CURRENT,0x0266000b, FALSE, EInternal());return TRUE; +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +}BOOL CPhotoAlbum::H0x0266000c_OpenBook_12(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0266000c + +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +Return(STATE_CURRENT,EReturn ()); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPhotoAlbum:: +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPhotoAlbum_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPhotoAlbum::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +InitAsModel (); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +SetModel (MODEL_ALBUM ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +SetModelMainTexture (TEXTURE_ALBUM ); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +GetModelObject () -> StartAnim (BOOK_ANIM_CLOSED ); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +AddAttachment (BOOK_ATTACHMENT_PAGE01 , MODEL_PAGE , TEXTURE_BLANK_PAGE ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +AddAttachment (BOOK_ATTACHMENT_PAGE02 , MODEL_PAGE , TEXTURE_PAGE01 ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +CAttachmentModelObject * pamo ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +pamo = GetModelObject () -> GetAttachmentModel (BOOK_ATTACHMENT_PAGE01 ); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +CModelObject * pmo ; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +pmo = & pamo -> amo_moModelObject ; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +pmo -> PlayAnim (COVERPAGES_ANIM_LEFTCLOSED , 0); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +pamo = GetModelObject () -> GetAttachmentModel (BOOK_ATTACHMENT_PAGE02 ); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +pmo = & pamo -> amo_moModelObject ; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +pmo -> PlayAnim (COVERPAGES_ANIM_RIGHTCLOSED , 0); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fStretch , m_fStretch , m_fStretch )); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +ModelChangeNotify (); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x0266000d, FALSE, EBegin());return TRUE;}BOOL CPhotoAlbum::H0x0266000d_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0266000d +switch(__eeInput.ee_slEvent) +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +return TRUE; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; + +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +Call(STATE_CURRENT, STATE_CPhotoAlbum_OpenBook, TRUE, EVoid());return TRUE; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +return TRUE; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; + +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +return TRUE; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +}return TRUE;}BOOL CPhotoAlbum::H0x0266000e_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0266000e +; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/PhotoAlbum.es b/Sources/EntitiesMP/PhotoAlbum.es new file mode 100644 index 0000000..406fa8b --- /dev/null +++ b/Sources/EntitiesMP/PhotoAlbum.es @@ -0,0 +1,138 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +614 +%{ +#include "StdH.h" +#include "ModelsMP/CutSequences/Book/Book.h" +#include "ModelsMP/CutSequences/Book/CoverPages.h" +%} + +class CPhotoAlbum: CMovableModelEntity { +name "PhotoAlbum"; +thumbnail "Thumbnails\\PhotoAlbum.tbn"; +features "IsTargetable", "HasName", "IsImportant"; + +properties: + 1 FLOAT m_fStretch "Stretch" 'S' = 1.0f, + 2 CTString m_strName "Name" 'N' = "Photo album", + 3 INDEX m_iCurrentPage = -1, + 4 FLOAT m_tmPageWait "Page wait" 'W' = 0.5f, + + 10 CSoundObject m_soPage, + +components: + +// ************** DATA ************** + 10 model MODEL_ALBUM "ModelsMP\\CutSequences\\Book\\Book.mdl", + 11 texture TEXTURE_ALBUM "ModelsMP\\CutSequences\\Book\\Book.tex", + 12 model MODEL_PAGE "ModelsMP\\CutSequences\\Book\\CoverPages.mdl", + 13 texture TEXTURE_PAGE01 "ModelsMP\\CutSequences\\Book\\Page01.tex", + 14 texture TEXTURE_PAGE02 "ModelsMP\\CutSequences\\Book\\Page02.tex", + 15 texture TEXTURE_PAGE03 "ModelsMP\\CutSequences\\Book\\Page03.tex", + 16 texture TEXTURE_PAGE04 "ModelsMP\\CutSequences\\Book\\Page04.tex", + 17 texture TEXTURE_PAGE_JOKE "ModelsMP\\CutSequences\\Book\\PageJoke.tex", + 18 texture TEXTURE_PAGE05 "ModelsMP\\CutSequences\\Book\\Page05.tex", + 19 texture TEXTURE_PAGE06 "ModelsMP\\CutSequences\\Book\\Page06.tex", + 20 texture TEXTURE_PAGE07 "ModelsMP\\CutSequences\\Book\\Page07.tex", + 21 texture TEXTURE_BLANK_PAGE "ModelsMP\\CutSequences\\Book\\Blank_Page.tex", + + 50 sound SOUND_PAGE "ModelsMP\\CutSequences\\Book\\Sounds\\PageFlip.wav", + +functions: + void Precache(void) { + PrecacheTexture(TEXTURE_PAGE01); + PrecacheTexture(TEXTURE_PAGE02); + PrecacheTexture(TEXTURE_PAGE03); + PrecacheTexture(TEXTURE_PAGE04); + PrecacheTexture(TEXTURE_PAGE_JOKE); + PrecacheTexture(TEXTURE_PAGE05); + PrecacheTexture(TEXTURE_PAGE06); + PrecacheTexture(TEXTURE_PAGE07); + PrecacheTexture(TEXTURE_BLANK_PAGE); + PrecacheSound(SOUND_PAGE); + } + +procedures: + OpenBook(EVoid) + { + // main book + GetModelObject()->PlayAnim(BOOK_ANIM_OPENING, 0); + // left cover + CModelObject &mo1=GetModelObject()->GetAttachmentModel(BOOK_ATTACHMENT_PAGE01)->amo_moModelObject; + mo1.PlayAnim(COVERPAGES_ANIM_OPENING, 0); + // right cover + CModelObject &mo2=GetModelObject()->GetAttachmentModel(BOOK_ATTACHMENT_PAGE02)->amo_moModelObject; + mo2.PlayAnim(COVERPAGES_ANIM_RIGHTOPENING, 0); + m_soPage.Set3DParameters(1000.0f, 500.0f, 2.0f, 1.0f); + PlaySound(m_soPage, SOUND_PAGE, SOF_3D); + // wait book to open + autowait( GetModelObject()->GetAnimLength(BOOK_ANIM_OPENING)); + autowait( 0.1f); + m_iCurrentPage=TEXTURE_PAGE01; + while(m_iCurrentPageStretchModel( FLOAT3D(m_fStretch,m_fStretch,m_fStretch)); + CModelObject &mo3=GetModelObject()->GetAttachmentModel(BOOK_ATTACHMENT_PAGE03)->amo_moModelObject; + mo3.PlayAnim(COVERPAGES_ANIM_OPENING, 0); + PlaySound(m_soPage, SOUND_PAGE, SOF_3D); + // switch page 2 to blank page texture + CModelObject &mo2=GetModelObject()->GetAttachmentModel(BOOK_ATTACHMENT_PAGE02)->amo_moModelObject; + mo2.SetTextureData(GetTextureDataForComponent(m_iCurrentPage+1)); + autowait(1.0f); + CModelObject &mo3=GetModelObject()->GetAttachmentModel(BOOK_ATTACHMENT_PAGE03)->amo_moModelObject; + mo3.SetTextureData(GetTextureDataForComponent(TEXTURE_BLANK_PAGE)); + autowait( mo3.GetAnimLength(COVERPAGES_ANIM_OPENING)-1.0f); + RemoveAttachment(BOOK_ATTACHMENT_PAGE03); + m_iCurrentPage+=1; + } + + return EReturn(); + } + + /************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set your appearance + SetModel(MODEL_ALBUM); + SetModelMainTexture(TEXTURE_ALBUM); + GetModelObject()->StartAnim(BOOK_ANIM_CLOSED); + AddAttachment(BOOK_ATTACHMENT_PAGE01, MODEL_PAGE, TEXTURE_BLANK_PAGE); + AddAttachment(BOOK_ATTACHMENT_PAGE02, MODEL_PAGE, TEXTURE_PAGE01); + CAttachmentModelObject *pamo; + pamo = GetModelObject()->GetAttachmentModel(BOOK_ATTACHMENT_PAGE01); + CModelObject *pmo; + pmo=&pamo->amo_moModelObject; + pmo->PlayAnim(COVERPAGES_ANIM_LEFTCLOSED, 0); + pamo = GetModelObject()->GetAttachmentModel(BOOK_ATTACHMENT_PAGE02); + pmo=&pamo->amo_moModelObject; + pmo->PlayAnim(COVERPAGES_ANIM_RIGHTCLOSED, 0); + + GetModelObject()->StretchModel( FLOAT3D(m_fStretch,m_fStretch,m_fStretch)); + ModelChangeNotify(); + + wait() + { + // on the beginning + on(EBegin): { + resume; + } + on(EStart): { + call OpenBook(); + resume; + } + on(EReturn): { + resume; + } + }; + }; +}; + diff --git a/Sources/EntitiesMP/PhotoAlbum.h b/Sources/EntitiesMP/PhotoAlbum.h new file mode 100644 index 0000000..bfea191 --- /dev/null +++ b/Sources/EntitiesMP/PhotoAlbum.h @@ -0,0 +1,45 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_PhotoAlbum_INCLUDED +#define _EntitiesMP_PhotoAlbum_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CPhotoAlbum_DLLClass; +class CPhotoAlbum : public CMovableModelEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fStretch; + CTString m_strName; + INDEX m_iCurrentPage; + FLOAT m_tmPageWait; + CSoundObject m_soPage; + +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +void Precache(void); +#define STATE_CPhotoAlbum_OpenBook 0x02660000 + BOOL +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +OpenBook(const CEntityEvent &__eeInput); + BOOL H0x02660001_OpenBook_01(const CEntityEvent &__eeInput); + BOOL H0x02660002_OpenBook_02(const CEntityEvent &__eeInput); + BOOL H0x02660003_OpenBook_03(const CEntityEvent &__eeInput); + BOOL H0x02660004_OpenBook_04(const CEntityEvent &__eeInput); + BOOL H0x02660005_OpenBook_05(const CEntityEvent &__eeInput); + BOOL H0x02660006_OpenBook_06(const CEntityEvent &__eeInput); + BOOL H0x02660007_OpenBook_07(const CEntityEvent &__eeInput); + BOOL H0x02660008_OpenBook_08(const CEntityEvent &__eeInput); + BOOL H0x02660009_OpenBook_09(const CEntityEvent &__eeInput); + BOOL H0x0266000a_OpenBook_10(const CEntityEvent &__eeInput); + BOOL H0x0266000b_OpenBook_11(const CEntityEvent &__eeInput); + BOOL H0x0266000c_OpenBook_12(const CEntityEvent &__eeInput); +#define STATE_CPhotoAlbum_Main 1 + BOOL +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x0266000d_Main_01(const CEntityEvent &__eeInput); + BOOL H0x0266000e_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_PhotoAlbum_INCLUDED diff --git a/Sources/EntitiesMP/PhotoAlbum_tables.h b/Sources/EntitiesMP/PhotoAlbum_tables.h new file mode 100644 index 0000000..df2d048 --- /dev/null +++ b/Sources/EntitiesMP/PhotoAlbum_tables.h @@ -0,0 +1,79 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CPhotoAlbum + +CEntityProperty CPhotoAlbum_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000266<<8)+1, offsetof(CPhotoAlbum, m_fStretch), "Stretch", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000266<<8)+2, offsetof(CPhotoAlbum, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000266<<8)+3, offsetof(CPhotoAlbum, m_iCurrentPage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000266<<8)+4, offsetof(CPhotoAlbum, m_tmPageWait), "Page wait", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000266<<8)+10, offsetof(CPhotoAlbum, m_soPage), "", 0, 0, 0), +}; +#define CPhotoAlbum_propertiesct ARRAYCOUNT(CPhotoAlbum_properties) + +CEntityComponent CPhotoAlbum_components[] = { +#define MODEL_ALBUM ((0x00000266<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_ALBUM, "EFNM" "ModelsMP\\CutSequences\\Book\\Book.mdl"), +#define TEXTURE_ALBUM ((0x00000266<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_ALBUM, "EFNM" "ModelsMP\\CutSequences\\Book\\Book.tex"), +#define MODEL_PAGE ((0x00000266<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_PAGE, "EFNM" "ModelsMP\\CutSequences\\Book\\CoverPages.mdl"), +#define TEXTURE_PAGE01 ((0x00000266<<8)+13) + CEntityComponent(ECT_TEXTURE, TEXTURE_PAGE01, "EFNM" "ModelsMP\\CutSequences\\Book\\Page01.tex"), +#define TEXTURE_PAGE02 ((0x00000266<<8)+14) + CEntityComponent(ECT_TEXTURE, TEXTURE_PAGE02, "EFNM" "ModelsMP\\CutSequences\\Book\\Page02.tex"), +#define TEXTURE_PAGE03 ((0x00000266<<8)+15) + CEntityComponent(ECT_TEXTURE, TEXTURE_PAGE03, "EFNM" "ModelsMP\\CutSequences\\Book\\Page03.tex"), +#define TEXTURE_PAGE04 ((0x00000266<<8)+16) + CEntityComponent(ECT_TEXTURE, TEXTURE_PAGE04, "EFNM" "ModelsMP\\CutSequences\\Book\\Page04.tex"), +#define TEXTURE_PAGE_JOKE ((0x00000266<<8)+17) + CEntityComponent(ECT_TEXTURE, TEXTURE_PAGE_JOKE, "EFNM" "ModelsMP\\CutSequences\\Book\\PageJoke.tex"), +#define TEXTURE_PAGE05 ((0x00000266<<8)+18) + CEntityComponent(ECT_TEXTURE, TEXTURE_PAGE05, "EFNM" "ModelsMP\\CutSequences\\Book\\Page05.tex"), +#define TEXTURE_PAGE06 ((0x00000266<<8)+19) + CEntityComponent(ECT_TEXTURE, TEXTURE_PAGE06, "EFNM" "ModelsMP\\CutSequences\\Book\\Page06.tex"), +#define TEXTURE_PAGE07 ((0x00000266<<8)+20) + CEntityComponent(ECT_TEXTURE, TEXTURE_PAGE07, "EFNM" "ModelsMP\\CutSequences\\Book\\Page07.tex"), +#define TEXTURE_BLANK_PAGE ((0x00000266<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLANK_PAGE, "EFNM" "ModelsMP\\CutSequences\\Book\\Blank_Page.tex"), +#define SOUND_PAGE ((0x00000266<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_PAGE, "EFNM" "ModelsMP\\CutSequences\\Book\\Sounds\\PageFlip.wav"), +}; +#define CPhotoAlbum_componentsct ARRAYCOUNT(CPhotoAlbum_components) + +CEventHandlerEntry CPhotoAlbum_handlers[] = { + {0x02660000, -1, CEntity::pEventHandler(&CPhotoAlbum:: +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +OpenBook),DEBUGSTRING("CPhotoAlbum::OpenBook")}, + {0x02660001, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x02660001_OpenBook_01), DEBUGSTRING("CPhotoAlbum::H0x02660001_OpenBook_01")}, + {0x02660002, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x02660002_OpenBook_02), DEBUGSTRING("CPhotoAlbum::H0x02660002_OpenBook_02")}, + {0x02660003, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x02660003_OpenBook_03), DEBUGSTRING("CPhotoAlbum::H0x02660003_OpenBook_03")}, + {0x02660004, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x02660004_OpenBook_04), DEBUGSTRING("CPhotoAlbum::H0x02660004_OpenBook_04")}, + {0x02660005, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x02660005_OpenBook_05), DEBUGSTRING("CPhotoAlbum::H0x02660005_OpenBook_05")}, + {0x02660006, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x02660006_OpenBook_06), DEBUGSTRING("CPhotoAlbum::H0x02660006_OpenBook_06")}, + {0x02660007, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x02660007_OpenBook_07), DEBUGSTRING("CPhotoAlbum::H0x02660007_OpenBook_07")}, + {0x02660008, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x02660008_OpenBook_08), DEBUGSTRING("CPhotoAlbum::H0x02660008_OpenBook_08")}, + {0x02660009, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x02660009_OpenBook_09), DEBUGSTRING("CPhotoAlbum::H0x02660009_OpenBook_09")}, + {0x0266000a, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x0266000a_OpenBook_10), DEBUGSTRING("CPhotoAlbum::H0x0266000a_OpenBook_10")}, + {0x0266000b, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x0266000b_OpenBook_11), DEBUGSTRING("CPhotoAlbum::H0x0266000b_OpenBook_11")}, + {0x0266000c, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x0266000c_OpenBook_12), DEBUGSTRING("CPhotoAlbum::H0x0266000c_OpenBook_12")}, + {1, -1, CEntity::pEventHandler(&CPhotoAlbum:: +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/PhotoAlbum.es" +Main),DEBUGSTRING("CPhotoAlbum::Main")}, + {0x0266000d, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x0266000d_Main_01), DEBUGSTRING("CPhotoAlbum::H0x0266000d_Main_01")}, + {0x0266000e, -1, CEntity::pEventHandler(&CPhotoAlbum::H0x0266000e_Main_02), DEBUGSTRING("CPhotoAlbum::H0x0266000e_Main_02")}, +}; +#define CPhotoAlbum_handlersct ARRAYCOUNT(CPhotoAlbum_handlers) + +CEntity *CPhotoAlbum_New(void) { return new CPhotoAlbum; }; +void CPhotoAlbum_OnInitClass(void) {}; +void CPhotoAlbum_OnEndClass(void) {}; +void CPhotoAlbum_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPhotoAlbum_OnWorldEnd(CWorld *pwo) {}; +void CPhotoAlbum_OnWorldInit(CWorld *pwo) {}; +void CPhotoAlbum_OnWorldTick(CWorld *pwo) {}; +void CPhotoAlbum_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPhotoAlbum, CMovableModelEntity, "PhotoAlbum", "Thumbnails\\PhotoAlbum.tbn", 0x00000266); +DECLARE_CTFILENAME(_fnmCPhotoAlbum_tbn, "Thumbnails\\PhotoAlbum.tbn"); diff --git a/Sources/EntitiesMP/Pipebomb.es b/Sources/EntitiesMP/Pipebomb.es new file mode 100644 index 0000000..471709d --- /dev/null +++ b/Sources/EntitiesMP/Pipebomb.es @@ -0,0 +1,260 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +503 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/BasicEffects"; +uses "EntitiesMP/Light"; +uses "EntitiesMP/AmmoItem"; + +// input parameter for launching the projectile +event EDropPipebomb { + CEntityPointer penLauncher, // who launched it + FLOAT fSpeed, // launch speed +}; + +%{ +#define ECF_PIPEBOMB ( \ + ((ECBI_MODEL|ECBI_BRUSH|ECBI_PROJECTILE_SOLID|ECBI_MODEL_HOLDER)<PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE_PLANE); + pdec->PrecacheModel(MODEL_PIPEBOMB); + pdec->PrecacheTexture(TEXTURE_PIPEBOMB); + pdec->PrecacheSound(SOUND_LAUNCH); +} +%} + +class CPipebomb : CMovableModelEntity { +name "Pipebomb"; +thumbnail ""; +features "ImplementsOnPrecache", "CanBePredictable"; + +properties: + 1 CEntityPointer m_penLauncher, // who lanuched it + 2 FLOAT m_fIgnoreTime = 0.0f, // time when laucher will be ignored + 3 FLOAT m_fSpeed = 0.0f, // launch speed + 4 BOOL m_bCollected = FALSE, // collect -> do not explode + +{ + CLightSource m_lsLightSource; +} + +components: + 1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 2 class CLASS_LIGHT "Classes\\Light.ecl", + +// ********* PIPEBOMB (GRENADE) ********* + 10 model MODEL_PIPEBOMB "Models\\Weapons\\Pipebomb\\Grenade\\Grenade.mdl", + 11 texture TEXTURE_PIPEBOMB "Models\\Weapons\\Pipebomb\\Grenade\\Grenade.tex", + 12 sound SOUND_LAUNCH "Sounds\\Weapons\\RocketFired.wav", + +functions: + /* Read from stream. */ + void Read_t( CTStream *istr) // throw char * + { + CMovableModelEntity::Read_t(istr); + SetupLightSource(); + } + + /* Get static light source information. */ + CLightSource *GetLightSource(void) + { + if (!IsPredictor()) { + return &m_lsLightSource; + } else { + return NULL; + } + } + + // Setup light source + void SetupLightSource(void) + { + // setup light source + CLightSource lsNew; + lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC; + lsNew.ls_colColor = C_vdRED; + lsNew.ls_rFallOff = 1.0f; + lsNew.ls_rHotSpot = 0.1f; + lsNew.ls_plftLensFlare = &_lftYellowStarRedRingFar; + lsNew.ls_ubPolygonalMask = 0; + lsNew.ls_paoLightAnimation = NULL; + + m_lsLightSource.ls_penEntity = this; + m_lsLightSource.SetLightSource(lsNew); + } + + // render particles + void RenderParticles(void) { + Particles_GrenadeTrail(this); + } + +/************************************************************ + * PIPEBOMB * + ************************************************************/ +void Pipebomb(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_BOUNCING); + SetCollisionFlags(ECF_PIPEBOMB); + //GetModelObject()->StretchModel(FLOAT3D(2.5f, 2.5f, 2.5f)); + //ModelChangeNotify(); + SetModel(MODEL_PIPEBOMB); + SetModelMainTexture(TEXTURE_PIPEBOMB); + // start moving + LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -m_fSpeed), (CMovableEntity*)&*m_penLauncher); + SetDesiredRotation(ANGLE3D(0, FRnd()*120.0f+120.0f, FRnd()*250.0f-125.0f)); + en_fBounceDampNormal = 0.7f; + en_fBounceDampParallel = 0.7f; + en_fJumpControlMultiplier = 0.0f; + en_fCollisionSpeedLimit = 45.0f; + en_fCollisionDamageFactor = 10.0f; + SetHealth(20.0f); +}; + +void PipebombExplosion(void) { + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + // explosion + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_GRENADE; + ese.vStretch = FLOAT3D(1,1,1); + SpawnEffect(GetPlacement(), ese); + // spawn sound event in range + if( IsDerivedFromClass( m_penLauncher, "Player")) { + SpawnRangeSound( m_penLauncher, this, SNDT_PLAYER, 50.0f); + } + + // on plane + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) { + // wall stain + ese.betType = BET_EXPLOSIONSTAIN; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // shock wave + ese.betType = BET_SHOCKWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // second explosion on plane + ese.betType = BET_GRENADE_PLANE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f, ANGLE3D(0, 0, 0)), ese); + } + } +}; + + + + +/************************************************************ + * C O M M O N F U N C T I O N S * + ************************************************************/ +// projectile hitted (or time expired or can't move any more) +void ProjectileHit(void) { + // explode ... + InflictRangeDamage(m_penLauncher, DMT_EXPLOSION, 100.0f, + GetPlacement().pl_PositionVector, 4.0f, 8.0f); + // sound event + ESound eSound; + eSound.EsndtSound = SNDT_EXPLOSION; + eSound.penTarget = m_penLauncher; + SendEventInRange(eSound, FLOATaabbox3D(GetPlacement().pl_PositionVector, 50.0f)); +}; + + +// spawn effect +void SpawnEffect(const CPlacement3D &plEffect, const ESpawnEffect &eSpawnEffect) { + CEntityPointer penEffect = CreateEntity(plEffect, CLASS_BASIC_EFFECT); + penEffect->Initialize(eSpawnEffect); +}; + + + + +/************************************************************ + * P R O C E D U R E S * + ************************************************************/ +procedures: + // --->>> PROJECTILE SLIDE ON BRUSH + ProjectileSlide(EVoid) { + m_bCollected = FALSE; + // fly loop + wait() { + on (EBegin) : { resume; } + // collected + on (ETouch etouch) : { + // clear time limit for launcher + if (etouch.penOther->GetRenderType() & RT_BRUSH) { + m_fIgnoreTime = 0.0f; + resume; + } + + BOOL bCollect; + // ignore launcher within 0.5 second + bCollect = etouch.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime; + // speed must be almost zero + bCollect &= (en_vCurrentTranslationAbsolute.Length() < 0.25f); + // only if can be collected + EAmmoItem eai; + eai.EaitType = AIT_GRENADES; + eai.iQuantity = 1; + if (bCollect && etouch.penOther->ReceiveItem(eai)) { + m_bCollected = TRUE; + stop; + } + resume; + } + // killed + on (EDeath) : { + ProjectileHit(); + stop; + } + // activated + on (EStart) : { + ProjectileHit(); + stop; + } + } + return EEnd(); + }; + + // --->>> MAIN + Main(EDropPipebomb edrop) { + // remember the initial parameters + ASSERT(edrop.penLauncher!=NULL); + m_penLauncher = edrop.penLauncher; + m_fSpeed = edrop.fSpeed; + + // projectile initialization + Pipebomb(); + + // setup light source + SetupLightSource(); + + // remember lauching time + m_fIgnoreTime = _pTimer->CurrentTick() + 0.5f; + + // slide + autocall ProjectileSlide() EEnd; + + // pipebomb explosion if not collected + if (!m_bCollected) { + PipebombExplosion(); + } + + Destroy(); + + return; + } +}; diff --git a/Sources/EntitiesMP/Player.cpp b/Sources/EntitiesMP/Player.cpp new file mode 100644 index 0000000..9c450da --- /dev/null +++ b/Sources/EntitiesMP/Player.cpp @@ -0,0 +1,9611 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" + + +#include "StdH.h" +#include "GameMP/SEColors.h" + +#include +#include +#include + +#include "ModelsMP/Player/SeriousSam/Player.h" +#include "ModelsMP/Player/SeriousSam/Body.h" +#include "ModelsMP/Player/SeriousSam/Head.h" + +#include "EntitiesMP/PlayerMarker.h" +#include "EntitiesMP/PlayerWeapons.h" +#include "EntitiesMP/PlayerAnimator.h" +#include "EntitiesMP/PlayerView.h" +#include "EntitiesMP/MovingBrush.h" +#include "EntitiesMP/Switch.h" +#include "EntitiesMP/MessageHolder.h" +#include "EntitiesMP/Camera.h" +#include "EntitiesMP/WorldLink.h" +#include "EntitiesMP/HealthItem.h" +#include "EntitiesMP/ArmorItem.h" +#include "EntitiesMP/WeaponItem.h" +#include "EntitiesMP/AmmoItem.h" +#include "EntitiesMP/PowerUpItem.h" +#include "EntitiesMP/MessageItem.h" +#include "EntitiesMP/AmmoPack.h" +#include "EntitiesMP/KeyItem.h" +#include "EntitiesMP/MusicHolder.h" +#include "EntitiesMP/EnemyBase.h" +#include "EntitiesMP/PlayerActionMarker.h" +#include "EntitiesMP/BasicEffects.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/ScrollHolder.h" +#include "EntitiesMP/TextFXHolder.h" +#include "EntitiesMP/SeriousBomb.h" +#include "EntitiesMP/CreditsHolder.h" +#include "EntitiesMP/HudPicHolder.h" + +extern void JumpFromBouncer(CEntity *penToBounce, CEntity *penBouncer); +// from game +#define GRV_SHOWEXTRAS (1L<<0) // add extra stuff like console, weapon, pause + +#define GENDER_MALE 0 +#define GENDER_FEMALE 1 +#define GENDEROFFSET 100 // sound components for genders are offset by this value + + +#include +#include +CEntityEvent *ECameraStart::MakeCopy(void) { CEntityEvent *peeCopy = new ECameraStart(*this); return peeCopy;} +ECameraStart::ECameraStart() : CEntityEvent(EVENTCODE_ECameraStart) {; + ClearToDefault(penCamera); +}; +CEntityEvent *ECameraStop::MakeCopy(void) { CEntityEvent *peeCopy = new ECameraStop(*this); return peeCopy;} +ECameraStop::ECameraStop() : CEntityEvent(EVENTCODE_ECameraStop) {; + ClearToDefault(penCamera); +}; +CEntityEvent *ERebirth::MakeCopy(void) { CEntityEvent *peeCopy = new ERebirth(*this); return peeCopy;} +ERebirth::ERebirth() : CEntityEvent(EVENTCODE_ERebirth) {; +}; +CEntityEvent *EDisconnected::MakeCopy(void) { CEntityEvent *peeCopy = new EDisconnected(*this); return peeCopy;} +EDisconnected::EDisconnected() : CEntityEvent(EVENTCODE_EDisconnected) {; +}; +CEntityEvent *EAutoAction::MakeCopy(void) { CEntityEvent *peeCopy = new EAutoAction(*this); return peeCopy;} +EAutoAction::EAutoAction() : CEntityEvent(EVENTCODE_EAutoAction) {; + ClearToDefault(penFirstMarker); +}; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" + +extern void DrawHUD( const CPlayer *penPlayerCurrent, CDrawPort *pdpCurrent, BOOL bSnooping, const CPlayer *penPlayerOwner); +extern void InitHUD(void); +extern void EndHUD(void); + +static CTimerValue _tvProbingLast; + +// used to render certain entities only for certain players (like picked items, etc.) +extern ULONG _ulPlayerRenderingMask = 0; + +// temporary BOOL used to discard calculating of 3rd view when calculating absolute view placement +BOOL _bDiscard3rdView=FALSE; + +#define NAME name + +const FLOAT _fBlowUpAmmount = 70.0f; + +// computer message adding flags +#define CMF_READ (1L<<0) +#define CMF_ANALYZE (1L<<1) + +struct MarkerDistance { +public: + FLOAT md_fMinD; + CPlayerMarker *md_ppm; + void Clear(void); +}; + +// export current player projection +CAnyProjection3D prPlayerProjection; + + +int qsort_CompareMarkerDistance(const void *pv0, const void *pv1) +{ + MarkerDistance &md0 = *(MarkerDistance*)pv0; + MarkerDistance &md1 = *(MarkerDistance*)pv1; + if( md0.md_fMinDmd1.md_fMinD) return -1; + else return 0; +} + +static inline FLOAT IntensityAtDistance( FLOAT fFallOff, FLOAT fHotSpot, FLOAT fDistance) +{ + // intensity is zero if further than fall-off range + if( fDistance>fFallOff) return 0.0f; + // intensity is maximum if closer than hot-spot range + if( fDistanceGetWorld()->wo_cenEntities, CEntity, iten) { + CEntity *pen = iten; + if (IsDerivedFromClass(pen, "Enemy Base") && !IsOfClass(pen, "Devil")) { + CEnemyBase *penEnemy = (CEnemyBase *)pen; + if (penEnemy->m_penEnemy==NULL) { + continue; + } + penKiller->InflictDirectDamage(pen, penKiller, DMT_BULLET, + penEnemy->GetHealth()+1, pen->GetPlacement().pl_PositionVector, FLOAT3D(0,1,0)); + } + }} +} + + +#define HEADING_MAX 45.0f +#define PITCH_MAX 90.0f +#define BANKING_MAX 45.0f + +// player flags +#define PLF_INITIALIZED (1UL<<0) // set when player entity is ready to function +#define PLF_VIEWROTATIONCHANGED (1UL<<1) // for adjusting view rotation separately from legs +#define PLF_JUMPALLOWED (1UL<<2) // if jumping is allowed +#define PLF_SYNCWEAPON (1UL<<3) // weapon model needs to be synchronized before rendering +#define PLF_AUTOMOVEMENTS (1UL<<4) // complete automatic control of movements +#define PLF_DONTRENDER (1UL<<5) // don't render view (used at end of level) +#define PLF_CHANGINGLEVEL (1UL<<6) // mark that we next are to appear at start of new level +#define PLF_APPLIEDACTION (1UL<<7) // used to detect when player is not connected +#define PLF_NOTCONNECTED (1UL<<8) // set if the player is not connected +#define PLF_LEVELSTARTED (1UL<<9) // marks that level start time was recorded +#define PLF_ISZOOMING (1UL<<10) // marks that player is zoomed in with the sniper +#define PLF_RESPAWNINPLACE (1UL<<11) // don't move to marker when respawning (for current death only) + +// defines representing flags used to fill player buttoned actions +#define PLACT_FIRE (1L<<0) +#define PLACT_RELOAD (1L<<1) +#define PLACT_WEAPON_NEXT (1L<<2) +#define PLACT_WEAPON_PREV (1L<<3) +#define PLACT_WEAPON_FLIP (1L<<4) +#define PLACT_USE (1L<<5) +#define PLACT_COMPUTER (1L<<6) +#define PLACT_3RD_PERSON_VIEW (1L<<7) +#define PLACT_CENTER_VIEW (1L<<8) +#define PLACT_USE_HELD (1L<<9) +#define PLACT_SNIPER_ZOOMIN (1L<<10) +#define PLACT_SNIPER_ZOOMOUT (1L<<11) +#define PLACT_SNIPER_USE (1L<<12) +#define PLACT_FIREBOMB (1L<<13) +#define PLACT_SELECT_WEAPON_SHIFT (14) +#define PLACT_SELECT_WEAPON_MASK (0x1FL<en_pcCharacter==pc) { + penThis = pen; + break; + } + } + // if not found + if (penThis==NULL) { + // do nothing + return; + } + + // accumulate local rotation + penThis->m_aLocalRotation +=paAction.pa_aRotation; + penThis->m_aLocalViewRotation+=paAction.pa_aViewRotation; + penThis->m_vLocalTranslation +=paAction.pa_vTranslation; + + // if prescanning + if (bPreScan) { + // no button checking + return; + } + + // add button movement/rotation/look actions to the axis actions + if(pctlCurrent.bMoveForward ) paAction.pa_vTranslation(3) -= plr_fSpeedForward; + if(pctlCurrent.bMoveBackward ) paAction.pa_vTranslation(3) += plr_fSpeedBackward; + if(pctlCurrent.bMoveLeft || pctlCurrent.bStrafe&&pctlCurrent.bTurnLeft) paAction.pa_vTranslation(1) -= plr_fSpeedSide; + if(pctlCurrent.bMoveRight || pctlCurrent.bStrafe&&pctlCurrent.bTurnRight) paAction.pa_vTranslation(1) += plr_fSpeedSide; + if(pctlCurrent.bMoveUp ) paAction.pa_vTranslation(2) += plr_fSpeedUp; + if(pctlCurrent.bMoveDown ) paAction.pa_vTranslation(2) -= plr_fSpeedUp; + + const FLOAT fQuantum = _pTimer->TickQuantum; + if(pctlCurrent.bTurnLeft && !pctlCurrent.bStrafe) penThis->m_aLocalRotation(1) += ctl_fButtonRotationSpeedH*fQuantum; + if(pctlCurrent.bTurnRight && !pctlCurrent.bStrafe) penThis->m_aLocalRotation(1) -= ctl_fButtonRotationSpeedH*fQuantum; + if(pctlCurrent.bTurnUp ) penThis->m_aLocalRotation(2) += ctl_fButtonRotationSpeedP*fQuantum; + if(pctlCurrent.bTurnDown ) penThis->m_aLocalRotation(2) -= ctl_fButtonRotationSpeedP*fQuantum; + if(pctlCurrent.bTurnBankingLeft ) penThis->m_aLocalRotation(3) += ctl_fButtonRotationSpeedB*fQuantum; + if(pctlCurrent.bTurnBankingRight ) penThis->m_aLocalRotation(3) -= ctl_fButtonRotationSpeedB*fQuantum; + + if(pctlCurrent.bLookLeft ) penThis->m_aLocalViewRotation(1) += ctl_fButtonRotationSpeedH*fQuantum; + if(pctlCurrent.bLookRight ) penThis->m_aLocalViewRotation(1) -= ctl_fButtonRotationSpeedH*fQuantum; + if(pctlCurrent.bLookUp ) penThis->m_aLocalViewRotation(2) += ctl_fButtonRotationSpeedP*fQuantum; + if(pctlCurrent.bLookDown ) penThis->m_aLocalViewRotation(2) -= ctl_fButtonRotationSpeedP*fQuantum; + if(pctlCurrent.bLookBankingLeft ) penThis->m_aLocalViewRotation(3) += ctl_fButtonRotationSpeedB*fQuantum; + if(pctlCurrent.bLookBankingRight ) penThis->m_aLocalViewRotation(3) -= ctl_fButtonRotationSpeedB*fQuantum; + + // use current accumulated rotation + paAction.pa_aRotation = penThis->m_aLocalRotation; + paAction.pa_aViewRotation = penThis->m_aLocalViewRotation; + //paAction.pa_vTranslation = penThis->m_vLocalTranslation; + + // if walking + if(pctlCurrent.bWalk) { + // make forward/backward and sidestep speeds slower + paAction.pa_vTranslation(3) /= 2.0f; + paAction.pa_vTranslation(1) /= 2.0f; + } + + // reset all button actions + paAction.pa_ulButtons = 0; + + // set weapon selection bits + for(INDEX i=1; ips_ulFlags&PSF_COMPSINGLECLICK)) { + // press both + paAction.pa_ulButtons |= PLACT_USE|PLACT_COMPUTER; + // if double-click is on + } else { + // if double click + if (_pTimer->GetRealTimeTick()<=_tmLastUseOrCompPressed+ctl_tmComputerDoubleClick) { + // computer pressed + paAction.pa_ulButtons |= PLACT_COMPUTER; + // if single click + } else { + // use pressed + paAction.pa_ulButtons |= PLACT_USE; + } + } + _tmLastUseOrCompPressed = _pTimer->GetRealTimeTick(); + } + // remember old userorcomp pressed state + pctlCurrent.bUseOrComputerLast = pctlCurrent.bUseOrComputer; +}; + +void CPlayer_Precache(void) +{ + CDLLEntityClass *pdec = &CPlayer_DLLClass; + + // precache view + extern void CPlayerView_Precache(void); + CPlayerView_Precache(); + + // precache all player sounds + pdec->PrecacheSound(SOUND_WATER_ENTER ); + pdec->PrecacheSound(SOUND_WATER_LEAVE ); + pdec->PrecacheSound(SOUND_WALK_L ); + pdec->PrecacheSound(SOUND_WALK_R ); + pdec->PrecacheSound(SOUND_WALK_SAND_L ); + pdec->PrecacheSound(SOUND_WALK_SAND_R ); + pdec->PrecacheSound(SOUND_SWIM_L ); + pdec->PrecacheSound(SOUND_SWIM_R ); + pdec->PrecacheSound(SOUND_DIVE_L ); + pdec->PrecacheSound(SOUND_DIVE_R ); + pdec->PrecacheSound(SOUND_DIVEIN ); + pdec->PrecacheSound(SOUND_DIVEOUT ); + pdec->PrecacheSound(SOUND_DROWN ); + pdec->PrecacheSound(SOUND_INHALE0 ); + pdec->PrecacheSound(SOUND_JUMP ); + pdec->PrecacheSound(SOUND_LAND ); + pdec->PrecacheSound(SOUND_WOUNDWEAK ); + pdec->PrecacheSound(SOUND_WOUNDMEDIUM ); + pdec->PrecacheSound(SOUND_WOUNDSTRONG ); + pdec->PrecacheSound(SOUND_WOUNDWATER ); + pdec->PrecacheSound(SOUND_DEATH ); + pdec->PrecacheSound(SOUND_DEATHWATER ); + pdec->PrecacheSound(SOUND_WATERAMBIENT ); + pdec->PrecacheSound(SOUND_WATERBUBBLES ); + pdec->PrecacheSound(SOUND_WATERWALK_L ); + pdec->PrecacheSound(SOUND_WATERWALK_R ); + pdec->PrecacheSound(SOUND_INHALE1 ); + pdec->PrecacheSound(SOUND_INHALE2 ); + pdec->PrecacheSound(SOUND_INFO ); + pdec->PrecacheSound(SOUND_WALK_GRASS_L ); + pdec->PrecacheSound(SOUND_WALK_GRASS_R ); + pdec->PrecacheSound(SOUND_WALK_WOOD_L ); + pdec->PrecacheSound(SOUND_WALK_WOOD_R ); + pdec->PrecacheSound(SOUND_WALK_SNOW_L ); + pdec->PrecacheSound(SOUND_WALK_SNOW_R ); +//pdec->PrecacheSound(SOUND_HIGHSCORE ); + pdec->PrecacheSound(SOUND_SNIPER_ZOOM ); + pdec->PrecacheSound(SOUND_SNIPER_QZOOM ); + pdec->PrecacheSound(SOUND_SILENCE ); + pdec->PrecacheSound(SOUND_POWERUP_BEEP ); + + pdec->PrecacheSound(SOUND_F_WATER_ENTER ); + pdec->PrecacheSound(SOUND_F_WATER_LEAVE ); + pdec->PrecacheSound(SOUND_F_WALK_L ); + pdec->PrecacheSound(SOUND_F_WALK_R ); + pdec->PrecacheSound(SOUND_F_WALK_SAND_L ); + pdec->PrecacheSound(SOUND_F_WALK_SAND_R ); + pdec->PrecacheSound(SOUND_F_SWIM_L ); + pdec->PrecacheSound(SOUND_F_SWIM_R ); + pdec->PrecacheSound(SOUND_F_DIVE_L ); + pdec->PrecacheSound(SOUND_F_DIVE_R ); + pdec->PrecacheSound(SOUND_F_DIVEIN ); + pdec->PrecacheSound(SOUND_F_DIVEOUT ); + pdec->PrecacheSound(SOUND_F_DROWN ); + pdec->PrecacheSound(SOUND_F_INHALE0 ); + pdec->PrecacheSound(SOUND_F_JUMP ); + pdec->PrecacheSound(SOUND_F_LAND ); + pdec->PrecacheSound(SOUND_F_WOUNDWEAK ); + pdec->PrecacheSound(SOUND_F_WOUNDMEDIUM ); + pdec->PrecacheSound(SOUND_F_WOUNDSTRONG ); + pdec->PrecacheSound(SOUND_F_WOUNDWATER ); + pdec->PrecacheSound(SOUND_F_DEATH ); + pdec->PrecacheSound(SOUND_F_DEATHWATER ); + pdec->PrecacheSound(SOUND_F_WATERWALK_L ); + pdec->PrecacheSound(SOUND_F_WATERWALK_R ); + pdec->PrecacheSound(SOUND_F_INHALE1 ); + pdec->PrecacheSound(SOUND_F_INHALE2 ); + pdec->PrecacheSound(SOUND_F_WALK_GRASS_L ); + pdec->PrecacheSound(SOUND_F_WALK_GRASS_R ); + pdec->PrecacheSound(SOUND_F_WALK_WOOD_L ); + pdec->PrecacheSound(SOUND_F_WALK_WOOD_R ); + pdec->PrecacheSound(SOUND_F_WALK_SNOW_L ); + pdec->PrecacheSound(SOUND_F_WALK_SNOW_R ); +//pdec->PrecacheSound(SOUND_F_HIGHSCORE ); + pdec->PrecacheSound(SOUND_BLOWUP ); + + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_TELEPORT); + pdec->PrecacheClass(CLASS_SERIOUSBOMB); + + pdec->PrecacheModel(MODEL_FLESH); + pdec->PrecacheModel(MODEL_FLESH_APPLE); + pdec->PrecacheModel(MODEL_FLESH_BANANA); + pdec->PrecacheModel(MODEL_FLESH_BURGER); + pdec->PrecacheTexture(TEXTURE_FLESH_RED); + pdec->PrecacheTexture(TEXTURE_FLESH_GREEN); + pdec->PrecacheTexture(TEXTURE_FLESH_APPLE); + pdec->PrecacheTexture(TEXTURE_FLESH_BANANA); + pdec->PrecacheTexture(TEXTURE_FLESH_BURGER); + pdec->PrecacheTexture(TEXTURE_FLESH_LOLLY); + pdec->PrecacheTexture(TEXTURE_FLESH_ORANGE); + + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSPILL); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSTAINGROW); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODEXPLODE); +} + +void CPlayer_OnInitClass(void) +{ + // clear current player controls + memset(&pctlCurrent, 0, sizeof(pctlCurrent)); + // declare player control variables + _pShell->DeclareSymbol("user INDEX ctl_bMoveForward;", &pctlCurrent.bMoveForward); + _pShell->DeclareSymbol("user INDEX ctl_bMoveBackward;", &pctlCurrent.bMoveBackward); + _pShell->DeclareSymbol("user INDEX ctl_bMoveLeft;", &pctlCurrent.bMoveLeft); + _pShell->DeclareSymbol("user INDEX ctl_bMoveRight;", &pctlCurrent.bMoveRight); + _pShell->DeclareSymbol("user INDEX ctl_bMoveUp;", &pctlCurrent.bMoveUp); + _pShell->DeclareSymbol("user INDEX ctl_bMoveDown;", &pctlCurrent.bMoveDown); + _pShell->DeclareSymbol("user INDEX ctl_bTurnLeft;", &pctlCurrent.bTurnLeft); + _pShell->DeclareSymbol("user INDEX ctl_bTurnRight;", &pctlCurrent.bTurnRight); + _pShell->DeclareSymbol("user INDEX ctl_bTurnUp;", &pctlCurrent.bTurnUp); + _pShell->DeclareSymbol("user INDEX ctl_bTurnDown;", &pctlCurrent.bTurnDown); + _pShell->DeclareSymbol("user INDEX ctl_bTurnBankingLeft;", &pctlCurrent.bTurnBankingLeft); + _pShell->DeclareSymbol("user INDEX ctl_bTurnBankingRight;", &pctlCurrent.bTurnBankingRight); + _pShell->DeclareSymbol("user INDEX ctl_bCenterView;", &pctlCurrent.bCenterView); + _pShell->DeclareSymbol("user INDEX ctl_bLookLeft;", &pctlCurrent.bLookLeft); + _pShell->DeclareSymbol("user INDEX ctl_bLookRight;", &pctlCurrent.bLookRight); + _pShell->DeclareSymbol("user INDEX ctl_bLookUp;", &pctlCurrent.bLookUp); + _pShell->DeclareSymbol("user INDEX ctl_bLookDown;", &pctlCurrent.bLookDown); + _pShell->DeclareSymbol("user INDEX ctl_bLookBankingLeft;", &pctlCurrent.bLookBankingLeft); + _pShell->DeclareSymbol("user INDEX ctl_bLookBankingRight;", &pctlCurrent.bLookBankingRight ); + _pShell->DeclareSymbol("user INDEX ctl_bWalk;", &pctlCurrent.bWalk); + _pShell->DeclareSymbol("user INDEX ctl_bStrafe;", &pctlCurrent.bStrafe); + _pShell->DeclareSymbol("user INDEX ctl_bFire;", &pctlCurrent.bFire); + _pShell->DeclareSymbol("user INDEX ctl_bReload;", &pctlCurrent.bReload); + _pShell->DeclareSymbol("user INDEX ctl_bUse;", &pctlCurrent.bUse); + _pShell->DeclareSymbol("user INDEX ctl_bComputer;", &pctlCurrent.bComputer); + _pShell->DeclareSymbol("user INDEX ctl_bUseOrComputer;", &pctlCurrent.bUseOrComputer); + _pShell->DeclareSymbol("user INDEX ctl_b3rdPersonView;", &pctlCurrent.b3rdPersonView); + _pShell->DeclareSymbol("user INDEX ctl_bWeaponNext;", &pctlCurrent.bWeaponNext); + _pShell->DeclareSymbol("user INDEX ctl_bWeaponPrev;", &pctlCurrent.bWeaponPrev); + _pShell->DeclareSymbol("user INDEX ctl_bWeaponFlip;", &pctlCurrent.bWeaponFlip); + _pShell->DeclareSymbol("user INDEX ctl_bSelectWeapon[30+1];", &pctlCurrent.bSelectWeapon); + _pShell->DeclareSymbol("persistent user FLOAT ctl_tmComputerDoubleClick;", &ctl_tmComputerDoubleClick); + _pShell->DeclareSymbol("persistent user FLOAT ctl_fButtonRotationSpeedH;", &ctl_fButtonRotationSpeedH); + _pShell->DeclareSymbol("persistent user FLOAT ctl_fButtonRotationSpeedP;", &ctl_fButtonRotationSpeedP); + _pShell->DeclareSymbol("persistent user FLOAT ctl_fButtonRotationSpeedB;", &ctl_fButtonRotationSpeedB); + _pShell->DeclareSymbol("persistent user FLOAT ctl_fAxisStrafingModifier;", &ctl_fAxisStrafingModifier); + //new + _pShell->DeclareSymbol("user INDEX ctl_bSniperZoomIn;", &pctlCurrent.bSniperZoomIn); + _pShell->DeclareSymbol("user INDEX ctl_bSniperZoomOut;", &pctlCurrent.bSniperZoomOut); + _pShell->DeclareSymbol("user INDEX ctl_bFireBomb;", &pctlCurrent.bFireBomb); + + _pShell->DeclareSymbol("user FLOAT plr_fSwimSoundDelay;", &plr_fSwimSoundDelay); + _pShell->DeclareSymbol("user FLOAT plr_fDiveSoundDelay;", &plr_fDiveSoundDelay); + _pShell->DeclareSymbol("user FLOAT plr_fWalkSoundDelay;", &plr_fWalkSoundDelay); + _pShell->DeclareSymbol("user FLOAT plr_fRunSoundDelay;", &plr_fRunSoundDelay); + + _pShell->DeclareSymbol("persistent user FLOAT cli_fPredictPlayersRange;",&cli_fPredictPlayersRange); + _pShell->DeclareSymbol("persistent user FLOAT cli_fPredictItemsRange;", &cli_fPredictItemsRange ); + _pShell->DeclareSymbol("persistent user FLOAT cli_tmPredictFoe;", &cli_tmPredictFoe ); + _pShell->DeclareSymbol("persistent user FLOAT cli_tmPredictAlly;", &cli_tmPredictAlly ); + _pShell->DeclareSymbol("persistent user FLOAT cli_tmPredictEnemy;", &cli_tmPredictEnemy ); + + _pShell->DeclareSymbol(" INDEX hud_bShowAll;", &hud_bShowAll); + _pShell->DeclareSymbol("user INDEX hud_bShowInfo;", &hud_bShowInfo); + _pShell->DeclareSymbol("user const FLOAT net_tmLatencyAvg;", &net_tmLatencyAvg); + _pShell->DeclareSymbol("persistent user INDEX hud_bShowLatency;", &hud_bShowLatency); + _pShell->DeclareSymbol("persistent user INDEX hud_iShowPlayers;", &hud_iShowPlayers); + _pShell->DeclareSymbol("persistent user INDEX hud_iSortPlayers;", &hud_iSortPlayers); + _pShell->DeclareSymbol("persistent user INDEX hud_bShowWeapon;", &hud_bShowWeapon); + _pShell->DeclareSymbol("persistent user INDEX hud_bShowMessages;",&hud_bShowMessages); + _pShell->DeclareSymbol("persistent user FLOAT hud_fScaling;", &hud_fScaling); + _pShell->DeclareSymbol("persistent user FLOAT hud_fOpacity;", &hud_fOpacity); + _pShell->DeclareSymbol("persistent user FLOAT hud_tmWeaponsOnScreen;", &hud_tmWeaponsOnScreen); + _pShell->DeclareSymbol("persistent user FLOAT hud_tmLatencySnapshot;", &hud_tmLatencySnapshot); + _pShell->DeclareSymbol("persistent user FLOAT plr_fBreathingStrength;", &plr_fBreathingStrength); + _pShell->DeclareSymbol("INDEX cht_bKillFinalBoss;", &cht_bKillFinalBoss); + _pShell->DeclareSymbol("INDEX cht_bDebugFinalBoss;", &cht_bDebugFinalBoss); + _pShell->DeclareSymbol("INDEX cht_bDumpFinalBossData;", &cht_bDumpFinalBossData); + _pShell->DeclareSymbol("INDEX cht_bDebugFinalBossAnimations;", &cht_bDebugFinalBossAnimations); + _pShell->DeclareSymbol("INDEX cht_bDumpPlayerShading;", &cht_bDumpPlayerShading); + _pShell->DeclareSymbol("persistent user INDEX hud_bShowMatchInfo;", &hud_bShowMatchInfo); + + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilSpeed[17];", &wpn_fRecoilSpeed); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilLimit[17];", &wpn_fRecoilLimit); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilDampUp[17];", &wpn_fRecoilDampUp); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilDampDn[17];", &wpn_fRecoilDampDn); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilOffset[17];", &wpn_fRecoilOffset); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilFactorP[17];", &wpn_fRecoilFactorP); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilFactorZ[17];", &wpn_fRecoilFactorZ); + + // cheats + _pShell->DeclareSymbol("user INDEX cht_bGod;", &cht_bGod); + _pShell->DeclareSymbol("user INDEX cht_bFly;", &cht_bFly); + _pShell->DeclareSymbol("user INDEX cht_bGhost;", &cht_bGhost); + _pShell->DeclareSymbol("user INDEX cht_bInvisible;", &cht_bInvisible); + _pShell->DeclareSymbol("user INDEX cht_bGiveAll;", &cht_bGiveAll); + _pShell->DeclareSymbol("user INDEX cht_bKillAll;", &cht_bKillAll); + _pShell->DeclareSymbol("user INDEX cht_bOpen;", &cht_bOpen); + _pShell->DeclareSymbol("user INDEX cht_bAllMessages;", &cht_bAllMessages); + _pShell->DeclareSymbol("user FLOAT cht_fTranslationMultiplier ;", &cht_fTranslationMultiplier); + _pShell->DeclareSymbol("user INDEX cht_bRefresh;", &cht_bRefresh); + // this one is masqueraded cheat enable variable + _pShell->DeclareSymbol("INDEX cht_bEnable;", &cht_bEnable); + + // this cheat is always enabled + _pShell->DeclareSymbol("user INDEX cht_iGoToMarker;", &cht_iGoToMarker); + + // player speed and view parameters, not declared except in internal build + #if 0 + _pShell->DeclareSymbol("user FLOAT plr_fViewHeightStand;", &plr_fViewHeightStand); + _pShell->DeclareSymbol("user FLOAT plr_fViewHeightCrouch;",&plr_fViewHeightCrouch); + _pShell->DeclareSymbol("user FLOAT plr_fViewHeightSwim;", &plr_fViewHeightSwim); + _pShell->DeclareSymbol("user FLOAT plr_fViewHeightDive;", &plr_fViewHeightDive); + _pShell->DeclareSymbol("user FLOAT plr_fViewDampFactor;", &plr_fViewDampFactor); + _pShell->DeclareSymbol("user FLOAT plr_fViewDampLimitGroundUp;", &plr_fViewDampLimitGroundUp); + _pShell->DeclareSymbol("user FLOAT plr_fViewDampLimitGroundDn;", &plr_fViewDampLimitGroundDn); + _pShell->DeclareSymbol("user FLOAT plr_fViewDampLimitWater;", &plr_fViewDampLimitWater); + _pShell->DeclareSymbol("user FLOAT plr_fAcceleration;", &plr_fAcceleration); + _pShell->DeclareSymbol("user FLOAT plr_fDeceleration;", &plr_fDeceleration); + _pShell->DeclareSymbol("user FLOAT plr_fSpeedForward;", &plr_fSpeedForward); + _pShell->DeclareSymbol("user FLOAT plr_fSpeedBackward;", &plr_fSpeedBackward); + _pShell->DeclareSymbol("user FLOAT plr_fSpeedSide;", &plr_fSpeedSide); + _pShell->DeclareSymbol("user FLOAT plr_fSpeedUp;", &plr_fSpeedUp); + #endif + _pShell->DeclareSymbol("persistent user FLOAT plr_fFOV;", &plr_fFOV); + _pShell->DeclareSymbol("persistent user FLOAT plr_fFrontClipDistance;", &plr_fFrontClipDistance); + _pShell->DeclareSymbol("persistent user INDEX plr_bRenderPicked;", &plr_bRenderPicked); + _pShell->DeclareSymbol("persistent user INDEX plr_bRenderPickedParticles;", &plr_bRenderPickedParticles); + _pShell->DeclareSymbol("persistent user INDEX plr_bOnlySam;", &plr_bOnlySam); + _pShell->DeclareSymbol("persistent user INDEX ent_bReportBrokenChains;", &ent_bReportBrokenChains); + _pShell->DeclareSymbol("persistent user FLOAT ent_tmMentalIn ;", &ent_tmMentalIn ); + _pShell->DeclareSymbol("persistent user FLOAT ent_tmMentalOut ;", &ent_tmMentalOut ); + _pShell->DeclareSymbol("persistent user FLOAT ent_tmMentalFade;", &ent_tmMentalFade); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fEnvParticlesDensity;", &gfx_fEnvParticlesDensity); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fEnvParticlesRange;", &gfx_fEnvParticlesRange); + + // player appearance interface + _pShell->DeclareSymbol("INDEX SetPlayerAppearance(INDEX, INDEX, INDEX, INDEX);", &SetPlayerAppearance); + + // call player weapons persistant variable initialization + extern void CPlayerWeapons_Init(void); + CPlayerWeapons_Init(); + + // initialize HUD + InitHUD(); + + // precache + CPlayer_Precache(); +} + +// clean up +void CPlayer_OnEndClass(void) +{ + EndHUD(); +} + +CTString GetDifficultyString(void) +{ + if (GetSP()->sp_bMental) { return TRANS("Mental"); } + + switch (GetSP()->sp_gdGameDifficulty) { + case CSessionProperties::GD_TOURIST: return TRANS("Tourist"); + case CSessionProperties::GD_EASY: return TRANS("Easy"); + default: + case CSessionProperties::GD_NORMAL: return TRANS("Normal"); + case CSessionProperties::GD_HARD: return TRANS("Hard"); + case CSessionProperties::GD_EXTREME: return TRANS("Serious"); + } +} +// armor & health constants getters + +FLOAT MaxArmor(void) +{ + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + return 300; + } else { + return 200; + } +} +FLOAT TopArmor(void) +{ + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + return 200; + } else { + return 100; + } +} +FLOAT MaxHealth(void) +{ + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + return 300; + } else { + return 200; + } +} +FLOAT TopHealth(void) +{ + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + return 200; + } else { + return 100; + } +} + +// info structure +static EntityInfo eiPlayerGround = { + EIBT_FLESH, 80.0f, + 0.0f, 1.7f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; +static EntityInfo eiPlayerCrouch = { + EIBT_FLESH, 80.0f, + 0.0f, 1.2f, 0.0f, // source (eyes) + 0.0f, 0.7f, 0.0f, // target (body) +}; +static EntityInfo eiPlayerSwim = { + EIBT_FLESH, 40.0f, + 0.0f, 0.0f, 0.0f, // source (eyes) + 0.0f, 0.0f, 0.0f, // target (body) +}; + + +// animation light specific +#define LIGHT_ANIM_MINIGUN 2 +#define LIGHT_ANIM_TOMMYGUN 3 +#define LIGHT_ANIM_COLT_SHOTGUN 4 +#define LIGHT_ANIM_NONE 5 + +const char *NameForState(PlayerState pst) +{ + switch(pst) { + case PST_STAND: return "stand"; + case PST_CROUCH: return "crouch"; + case PST_FALL: return "fall"; + case PST_SWIM: return "swim"; + case PST_DIVE: return "dive"; + default: return "???"; + }; +} + + +// print explanation on how a player died +void PrintPlayerDeathMessage(CPlayer *ppl, const EDeath &eDeath) +{ + CTString strMyName = ppl->GetPlayerName(); + CEntity *penKiller = eDeath.eLastDamage.penInflictor; + // if killed by a valid entity + if (penKiller!=NULL) { + // if killed by a player + if (IsOfClass(penKiller, "Player")) { + // if not self + if (penKiller!=ppl) { + CTString strKillerName = ((CPlayer*)penKiller)->GetPlayerName(); + + if(eDeath.eLastDamage.dmtType==DMT_TELEPORT) { + CPrintF(TRANS("%s telefragged %s\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_CLOSERANGE) { + CPrintF(TRANS("%s cut %s into pieces\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_CHAINSAW) { + CPrintF(TRANS("%s cut %s into pieces\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_BULLET) { + CPrintF(TRANS("%s poured lead into %s\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_PROJECTILE || eDeath.eLastDamage.dmtType==DMT_EXPLOSION) { + CPrintF(TRANS("%s blew %s away\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_CANNONBALL) { + CPrintF(TRANS("%s smashed %s with a cannon\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_CANNONBALL_EXPLOSION) { + CPrintF(TRANS("%s nuked %s\n"), strKillerName, strMyName); + } else { + CPrintF(TRANS("%s killed %s\n"), strKillerName, strMyName); + } + } else { + // make message from damage type + switch(eDeath.eLastDamage.dmtType) { + case DMT_DROWNING: CPrintF(TRANS("%s drowned\n"), strMyName); break; + case DMT_BURNING: CPrintF(TRANS("%s burst into flames\n"), strMyName); break; + case DMT_SPIKESTAB: CPrintF(TRANS("%s fell into a spike-hole\n"), strMyName); break; + case DMT_FREEZING: CPrintF(TRANS("%s has frozen\n"), strMyName); break; + case DMT_ACID: CPrintF(TRANS("%s dissolved\n"), strMyName); break; + case DMT_PROJECTILE: + case DMT_EXPLOSION: + CPrintF(TRANS("%s blew himself away\n"), strMyName); break; + default: CPrintF(TRANS("%s has committed suicide\n"), strMyName); + } + } + // if killed by an enemy + } else if (IsDerivedFromClass(penKiller, "Enemy Base")) { + // check for telefrag first + if(eDeath.eLastDamage.dmtType==DMT_TELEPORT) { + CPrintF(TRANS("%s was telefragged\n"), strMyName); + return; + } + // describe how this enemy killed player + CPrintF("%s\n", (const char*)((CEnemyBase*)penKiller)->GetPlayerKillDescription(strMyName, eDeath)); + + // if killed by some other entity + } else { + // make message from damage type + switch(eDeath.eLastDamage.dmtType) { + case DMT_SPIKESTAB: CPrintF(TRANS("%s was pierced\n"), strMyName); break; + case DMT_BRUSH: CPrintF(TRANS("%s was squashed\n"), strMyName); break; + case DMT_ABYSS: CPrintF(TRANS("%s went over the edge\n"), strMyName); break; + case DMT_IMPACT: CPrintF(TRANS("%s swashed\n"), strMyName); break; + case DMT_HEAT: CPrintF(TRANS("%s stood in the sun for too long\n"), strMyName); break; + default: CPrintF(TRANS("%s passed away\n"), strMyName); + } + } + // if no entity pointer (shouldn't happen) + } else { + CPrintF(TRANS("%s is missing in action\n"), strMyName); + } +} + + +void CPlayer::SetDefaultProperties(void) { + m_strName = ""; + m_ulLastButtons = 0x0; + m_fArmor = 0.0f; + m_strGroup = ""; + m_ulKeys = 0; + m_fMaxHealth = 1; + m_ulFlags = 0; + m_penWeapons = NULL; + m_penAnimator = NULL; + m_penView = NULL; + m_pen3rdPersonView = NULL; + m_iViewState = PVT_PLAYEREYES ; + m_iLastViewState = PVT_PLAYEREYES ; + m_aoLightAnimation.SetData(NULL); + + m_fDamageAmmount = 0.0f; + m_tmWoundedTime = 0.0f; + m_tmScreamTime = 0.0f; + m_iGender = GENDER_MALE ; + m_pstState = PST_STAND ; + m_fFallTime = 0.0f; + m_fSwimTime = 0.0f; + m_tmOutOfWater = 0.0f; + m_tmMoveSound = 0.0f; + m_bMoveSoundLeft = TRUE ; + m_tmNextAmbientOnce = 0.0f; + m_tmMouthSoundLast = 0.0f; + m_penCamera = NULL; + m_strCenterMessage = ""; + m_tmCenterMessageEnd = 0.0f; + m_bPendingMessage = FALSE ; + m_tmMessagePlay = 0.0f; + m_tmAnalyseEnd = 0.0f; + m_bComputerInvoked = FALSE ; + m_tmAnimateInbox = -100.0f; + m_penMainMusicHolder = NULL; + m_tmLastDamage = -1.0f; + m_fMaxDamageAmmount = 0.0f; + m_vDamage = FLOAT3D(0 , 0 , 0); + m_tmSpraySpawned = -1.0f; + m_fSprayDamage = 0.0f; + m_penSpray = NULL; + m_soWeapon0.SetOwner(this); +m_soWeapon0.Stop_internal(); + m_soWeapon1.SetOwner(this); +m_soWeapon1.Stop_internal(); + m_soWeapon2.SetOwner(this); +m_soWeapon2.Stop_internal(); + m_soWeapon3.SetOwner(this); +m_soWeapon3.Stop_internal(); + m_soWeaponAmbient.SetOwner(this); +m_soWeaponAmbient.Stop_internal(); + m_soPowerUpBeep.SetOwner(this); +m_soPowerUpBeep.Stop_internal(); + m_soMouth.SetOwner(this); +m_soMouth.Stop_internal(); + m_soFootL.SetOwner(this); +m_soFootL.Stop_internal(); + m_soFootR.SetOwner(this); +m_soFootR.Stop_internal(); + m_soBody.SetOwner(this); +m_soBody.Stop_internal(); + m_soLocalAmbientLoop.SetOwner(this); +m_soLocalAmbientLoop.Stop_internal(); + m_soLocalAmbientOnce.SetOwner(this); +m_soLocalAmbientOnce.Stop_internal(); + m_soMessage.SetOwner(this); +m_soMessage.Stop_internal(); + m_soHighScore.SetOwner(this); +m_soHighScore.Stop_internal(); + m_soSpeech.SetOwner(this); +m_soSpeech.Stop_internal(); + m_soSniperZoom.SetOwner(this); +m_soSniperZoom.Stop_internal(); + m_iMana = 0; + m_fManaFraction = 0.0f; + m_iHighScore = 0; + m_iBeatenHighScore = 0; + m_tmLatency = 0.0f; + m_tmLatencyLastAvg = 0.0f; + m_tmLatencyAvgSum = 0.0f; + m_ctLatencyAvg = 0; + m_bEndOfLevel = FALSE ; + m_bEndOfGame = FALSE ; + m_iMayRespawn = 0; + m_tmSpawned = 0.0f; + m_vDied = FLOAT3D(0 , 0 , 0); + m_aDied = FLOAT3D(0 , 0 , 0); + m_tmEstTime = 0.0f; + m_iTimeScore = 0; + m_iStartTime = 0; + m_iEndTime = 0; + m_tmLevelStarted = 0.0f; + m_strLevelStats = ""; + m_penActionMarker = NULL; + m_fAutoSpeed = 0.0f; + m_iAutoOrgWeapon = 0; + m_vAutoSpeed = FLOAT3D(0 , 0 , 0); + m_tmSpiritStart = 0.0f; + m_tmFadeStart = 0.0f; + m_tmLastPicked = -10000.0f; + m_strPickedName = ""; + m_fPickedAmmount = 0.0f; + m_fPickedMana = 0.0f; + m_iLastHealth = 0; + m_iLastArmor = 0; + m_iLastAmmo = 0; + m_tmHealthChanged = -9; + m_tmArmorChanged = -9; + m_tmAmmoChanged = -9; + m_tmMinigunAutoFireStart = -1.0f; + m_vLastStain = FLOAT3D(0 , 0 , 0); + m_aLastRotation = FLOAT3D(0 , 0 , 0); + m_aLastViewRotation = FLOAT3D(0 , 0 , 0); + m_vLastTranslation = FLOAT3D(0 , 0 , 0); + m_aLocalRotation = FLOAT3D(0 , 0 , 0); + m_aLocalViewRotation = FLOAT3D(0 , 0 , 0); + m_vLocalTranslation = FLOAT3D(0 , 0 , 0); + m_tmInvisibility = 0.0f; + m_tmInvulnerability = 0.0f; + m_tmSeriousDamage = 0.0f; + m_tmSeriousSpeed = 0.0f; + m_tmInvisibilityMax = 30.0f; + m_tmInvulnerabilityMax = 30.0f; + m_tmSeriousDamageMax = 40.0f; + m_tmSeriousSpeedMax = 20.0f; + m_tmChainShakeEnd = 0.0f; + m_fChainShakeStrength = 1.0f; + m_fChainShakeFreqMod = 1.0f; + m_fChainsawShakeDX = 0.0f; + m_fChainsawShakeDY = 0.0f; + m_iSeriousBombCount = 0; + m_iLastSeriousBombCount = 0; + m_tmSeriousBombFired = -10.0f; + m_penPrediction = NULL; + CPlayerEntity::SetDefaultProperties(); +} + +#line 1284 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX CPlayer::GenderSound(INDEX iSound) +#line 1285 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1286 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return iSound + m_iGender * GENDEROFFSET ; +#line 1287 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::AddBouble(FLOAT3D vPos,FLOAT3D vSpeedRelative) +#line 1290 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1291 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ShellLaunchData & sld = m_asldData [ m_iFirstEmptySLD ]; +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sld . sld_vPos = vPos ; +#line 1293 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const FLOATmatrix3D & m = GetRotationMatrix (); +#line 1294 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vUp (m (1 , 2) , m (2 , 2) , m (3 , 2)); +#line 1295 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sld . sld_vUp = vUp ; +#line 1296 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sld . sld_vSpeed = vSpeedRelative * m ; +#line 1297 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sld . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 1298 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sld . sld_estType = ESL_BUBBLE ; +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iFirstEmptySLD = (m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 1301 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ClearShellLaunchData(void) +#line 1304 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1306 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iFirstEmptySLD = 0; +#line 1307 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iShell = 0;iShell < MAX_FLYING_SHELLS ;iShell ++) +#line 1308 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1309 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_asldData [ iShell ] . sld_tmLaunch = - 100.0f; +#line 1310 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1311 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::AddBulletSpray(FLOAT3D vPos,EffectParticlesType eptType,FLOAT3D vStretch) +#line 1314 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1315 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BulletSprayLaunchData & bsld = m_absldData [ m_iFirstEmptyBSLD ]; +#line 1316 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bsld . bsld_vPos = vPos ; +#line 1317 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bsld . bsld_vG = en_vGravityDir ; +#line 1318 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bsld . bsld_eptType = eptType ; +#line 1319 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bsld . bsld_iRndBase = FRnd () * 123456; +#line 1320 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bsld . bsld_tmLaunch = _pTimer -> CurrentTick (); +#line 1321 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bsld . bsld_vStretch = vStretch ; +#line 1323 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iFirstEmptyBSLD = (m_iFirstEmptyBSLD + 1) % MAX_BULLET_SPRAYS ; +#line 1324 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1326 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ClearBulletSprayLaunchData(void) +#line 1327 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1328 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iFirstEmptyBSLD = 0; +#line 1329 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iBulletSpray = 0;iBulletSpray < MAX_BULLET_SPRAYS ;iBulletSpray ++) +#line 1330 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1331 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_absldData [ iBulletSpray ] . bsld_tmLaunch = - 100.0f; +#line 1332 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1333 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1335 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::AddGoreSpray(FLOAT3D vPos,FLOAT3D v3rdPos,SprayParticlesType sptType,FLOAT3D vSpilDirection, +#line 1336 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATaabbox3D boxHitted,FLOAT fDamagePower,COLOR colParticles) +#line 1337 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1338 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GoreSprayLaunchData & gsld = m_agsldData [ m_iFirstEmptyGSLD ]; +#line 1339 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_vPos = vPos ; +#line 1340 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_v3rdPos = v3rdPos ; +#line 1341 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_vG = en_vGravityDir ; +#line 1342 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_fGA = en_fGravityA ; +#line 1343 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_sptType = sptType ; +#line 1344 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_boxHitted = boxHitted ; +#line 1345 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_vSpilDirection = vSpilDirection ; +#line 1346 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_fDamagePower = fDamagePower ; +#line 1347 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_tmLaunch = _pTimer -> CurrentTick (); +#line 1348 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_colParticles = colParticles ; +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iFirstEmptyGSLD = (m_iFirstEmptyGSLD + 1) % MAX_GORE_SPRAYS ; +#line 1351 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1353 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ClearGoreSprayLaunchData(void) +#line 1354 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1355 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iFirstEmptyGSLD = 0; +#line 1356 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iGoreSpray = 0;iGoreSpray < MAX_GORE_SPRAYS ;iGoreSpray ++) +#line 1357 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1358 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_agsldData [ iGoreSpray ] . gsld_tmLaunch = - 100.0f; +#line 1359 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1360 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + CPlayer::CPlayer(void) +#line 1363 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1365 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bUseButtonHeld = FALSE ; +#line 1366 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ClearShellLaunchData (); +#line 1367 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ClearBulletSprayLaunchData (); +#line 1368 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ClearGoreSprayLaunchData (); +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmPredict = 0; +#line 1375 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1377 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +class CPlayerWeapons * CPlayer::GetPlayerWeapons(void) +#line 1378 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1379 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (m_penWeapons != NULL ); +#line 1380 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return (CPlayerWeapons *) & * m_penWeapons ; +#line 1381 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1382 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +class CPlayerAnimator * CPlayer::GetPlayerAnimator(void) +#line 1383 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1384 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (m_penAnimator != NULL ); +#line 1385 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return (CPlayerAnimator *) & * m_penAnimator ; +#line 1386 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1388 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerSettings * CPlayer::GetSettings(void) +#line 1389 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1390 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return (CPlayerSettings *) en_pcCharacter . pc_aubAppearance ; +#line 1391 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + void CPlayer::Copy(CEntity & enOther,ULONG ulFlags) +#line 1394 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1395 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerEntity :: Copy (enOther , ulFlags ); +#line 1396 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * penOther = (CPlayer *) (& enOther ); +#line 1397 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_moRender . Copy (penOther -> m_moRender ); +#line 1398 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats = penOther -> m_psLevelStats ; +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelTotal = penOther -> m_psLevelTotal ; +#line 1400 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats = penOther -> m_psGameStats ; +#line 1401 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameTotal = penOther -> m_psGameTotal ; +#line 1404 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulFlags & COPY_PREDICTOR ) +#line 1405 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1407 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +memcpy (m_asldData , penOther -> m_asldData , sizeof (m_asldData )); +#line 1408 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iFirstEmptySLD = penOther -> m_iFirstEmptySLD ; +#line 1410 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_acmiMessages . Clear (); +#line 1411 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ctUnreadMessages = 0; +#line 1413 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetupLightSource (); +#line 1416 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1418 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_acmiMessages = penOther -> m_acmiMessages ; +#line 1419 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ctUnreadMessages = penOther -> m_ctUnreadMessages ; +#line 1420 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1421 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1424 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::UpdateLatency(FLOAT tmLatencyNow) +#line 1425 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1426 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME tmNow = _pTimer -> GetHighPrecisionTimer () . GetSeconds (); +#line 1429 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmNow < m_tmLatencyLastAvg + hud_tmLatencySnapshot ){ +#line 1431 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmLatencyAvgSum += tmLatencyNow ; +#line 1432 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ctLatencyAvg ++; +#line 1435 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1437 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmLatency = m_tmLatencyAvgSum / m_ctLatencyAvg ; +#line 1439 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmLatencyAvgSum = 0.0f; +#line 1440 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ctLatencyAvg = 0; +#line 1441 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmLatencyLastAvg = tmNow ; +#line 1442 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1444 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){ +#line 1445 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_tmPing = m_tmLatency ; +#line 1446 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +net_tmLatencyAvg = en_tmPing ; +#line 1447 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1448 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1451 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ValidateCharacter(void) +#line 1452 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1454 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bSinglePlayer ){ +#line 1456 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerSettings * pps = (CPlayerSettings *) en_pcCharacter . pc_aubAppearance ; +#line 1457 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +memset (pps -> ps_achModelFile , 0 , sizeof (pps -> ps_achModelFile )); +#line 1458 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1459 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1461 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ParseGender(CTString & strName) +#line 1462 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1463 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(strName . RemovePrefix ("#male#")){ +#line 1464 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iGender = GENDER_MALE ; +#line 1465 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(strName . RemovePrefix ("#female#")){ +#line 1466 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iGender = GENDER_FEMALE ; +#line 1467 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1468 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iGender = GENDER_MALE ; +#line 1469 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1470 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1472 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::CheckHighScore(void) +#line 1473 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1475 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! _pNetwork -> IsPlayingDemo ()){ +#line 1477 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(plr_iHiScore > m_iHighScore ){ +#line 1478 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iHighScore = plr_iHiScore ; +#line 1479 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1480 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1483 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_psGameStats . ps_iScore > m_iHighScore ){ +#line 1485 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_iHighScore > m_iBeatenHighScore ){ +#line 1487 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iBeatenHighScore = m_iHighScore ; +#line 1489 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soHighScore . Set3DParameters (25.0f , 5.0f , 1.0f , 1.0f); +#line 1491 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1492 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1493 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1495 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString CPlayer::GetPredictName(void)const +#line 1496 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1497 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsPredicted ()){ +#line 1498 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return "PREDICTED"; +#line 1499 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(IsPredictor ()){ +#line 1500 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return "predictor"; +#line 1501 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(GetFlags () & ENF_WILLBEPREDICTED ){ +#line 1502 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return "WILLBEPREDICTED"; +#line 1503 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1504 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return "no prediction"; +#line 1505 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1506 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1508 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::Write_t(CTStream * ostr) +#line 1509 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1510 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerEntity :: Write_t (ostr ); +#line 1512 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ostr -> WriteID_t ("MSGS"); +#line 1513 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX ctMsg = m_acmiMessages . Count (); +#line 1514 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(* ostr ) << ctMsg ; +#line 1515 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iMsg = 0;iMsg < ctMsg ;iMsg ++){ +#line 1516 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_acmiMessages [ iMsg ] . Write_t (* ostr ); +#line 1517 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1518 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ostr -> Write_t (& m_psLevelStats , sizeof (m_psLevelStats )); +#line 1519 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ostr -> Write_t (& m_psLevelTotal , sizeof (m_psLevelTotal )); +#line 1520 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ostr -> Write_t (& m_psGameStats , sizeof (m_psGameStats )); +#line 1521 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ostr -> Write_t (& m_psGameTotal , sizeof (m_psGameTotal )); +#line 1522 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1524 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::Read_t(CTStream * istr) +#line 1525 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1526 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerEntity :: Read_t (istr ); +#line 1528 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ClearShellLaunchData (); +#line 1529 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ClearBulletSprayLaunchData (); +#line 1530 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ClearGoreSprayLaunchData (); +#line 1532 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +istr -> ExpectID_t ("MSGS"); +#line 1533 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX ctMsg ; +#line 1534 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(* istr ) >> ctMsg ; +#line 1535 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_acmiMessages . Clear (); +#line 1536 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ctUnreadMessages = 0; +#line 1537 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ctMsg > 0){ +#line 1538 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_acmiMessages . Push (ctMsg ); +#line 1539 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iMsg = 0;iMsg < ctMsg ;iMsg ++){ +#line 1540 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_acmiMessages [ iMsg ] . Read_t (* istr ); +#line 1541 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! m_acmiMessages [ iMsg ] . cmi_bRead ){ +#line 1542 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ctUnreadMessages ++; +#line 1543 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1544 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1545 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1547 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +istr -> Read_t (& m_psLevelStats , sizeof (m_psLevelStats )); +#line 1548 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +istr -> Read_t (& m_psLevelTotal , sizeof (m_psLevelTotal )); +#line 1549 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +istr -> Read_t (& m_psGameStats , sizeof (m_psGameStats )); +#line 1550 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +istr -> Read_t (& m_psGameTotal , sizeof (m_psGameTotal )); +#line 1553 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ValidateCharacter (); +#line 1554 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strDummy ; +#line 1555 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPlayerAppearance (& m_moRender , & en_pcCharacter , strDummy , FALSE ); +#line 1556 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ParseGender (strDummy ); +#line 1557 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_SYNCWEAPON ; +#line 1559 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetupLightSource (); +#line 1560 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1563 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CLightSource * CPlayer::GetLightSource(void) +#line 1564 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1565 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! IsPredictor ()){ +#line 1566 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return & m_lsLightSource ; +#line 1567 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1568 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return NULL ; +#line 1569 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1570 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1573 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SetPredictionTime(TIME tmAdvance) +#line 1574 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1575 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmPredict = _pTimer -> CurrentTick () + tmAdvance ; +#line 1576 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1579 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME CPlayer::GetPredictionTime(void) +#line 1580 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1581 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return m_tmPredict ; +#line 1582 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1585 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT CPlayer::GetPredictionRange(void) +#line 1586 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1587 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return cli_fPredictPlayersRange ; +#line 1588 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1591 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::AddDependentsToPrediction(void) +#line 1592 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1593 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penWeapons -> AddToPrediction (); +#line 1594 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penAnimator -> AddToPrediction (); +#line 1595 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penView -> AddToPrediction (); +#line 1596 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pen3rdPersonView -> AddToPrediction (); +#line 1597 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1600 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME CPlayer::GetStatsInGameTimeLevel(void) +#line 1601 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1602 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_bEndOfLevel ){ +#line 1603 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return m_psLevelStats . ps_tmTime ; +#line 1604 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1605 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return _pNetwork -> GetGameTime () - m_tmLevelStarted ; +#line 1606 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1607 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1608 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME CPlayer::GetStatsInGameTimeGame(void) +#line 1609 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1610 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_bEndOfLevel ){ +#line 1611 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return m_psGameStats . ps_tmTime ; +#line 1612 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1613 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return m_psGameStats . ps_tmTime + (_pNetwork -> GetGameTime () - m_tmLevelStarted ); +#line 1614 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1615 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1617 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT CPlayer::GetStatsRealWorldTime(void) +#line 1618 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1619 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +time_t timeNow ; +#line 1620 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_bEndOfLevel ){ +#line 1621 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +timeNow = m_iEndTime ; +#line 1622 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1623 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +time (& timeNow ); +#line 1624 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1625 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return (FLOAT) difftime (timeNow , m_iStartTime ); +#line 1626 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1628 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString CPlayer::GetStatsRealWorldStarted(void) +#line 1629 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1630 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +struct tm * newtime ; +#line 1631 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +newtime = localtime ((const time_t *) & m_iStartTime ); +#line 1633 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +setlocale (LC_ALL , ""); +#line 1634 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strTimeline ; +#line 1635 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +char achTimeLine [ 256 ]; +#line 1636 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strftime (achTimeLine , sizeof (achTimeLine ) - 1 , "%a %x %H:%M" , newtime ); +#line 1637 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strTimeline = achTimeLine ; +#line 1638 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +setlocale (LC_ALL , "C"); +#line 1639 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return strTimeline ; +#line 1640 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + void CPlayer::GetStats(CTString & strStats,const CompStatType csType,INDEX ctCharsPerRow) +#line 1644 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1647 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(csType == CST_SHORT ){ +#line 1648 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetShortStats (strStats ); +#line 1649 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1650 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (csType == CST_DETAIL ); +#line 1652 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats = "\n"; +#line 1653 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_ctAlignWidth = Min (ctCharsPerRow , INDEX (60)); +#line 1655 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bCooperative ){ +#line 1656 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bSinglePlayer ){ +#line 1657 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetDetailStatsSP (strStats , 0); +#line 1658 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1659 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetDetailStatsCoop (strStats ); +#line 1660 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1661 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1662 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetDetailStatsDM (strStats ); +#line 1663 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1664 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1665 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1668 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::GetShortStats(CTString & strStats) +#line 1669 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1670 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats . PrintF (TRANS ("%s %s Score: %d Kills: %d/%d") , +#line 1671 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetDifficultyString () , TimeToString (GetStatsInGameTimeLevel ()) , +#line 1672 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iScore , m_psLevelStats . ps_iKills , m_psLevelTotal . ps_iKills ); +#line 1673 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1676 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::GetDetailStatsDM(CTString & strStats) +#line 1677 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1678 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +extern INDEX SetAllPlayersStats (INDEX iSortKey ); +#line 1679 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +extern CPlayer * _apenPlayers [ NET_MAXGAMEPLAYERS ]; +#line 1681 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const BOOL bFragMatch = GetSP () -> sp_bUseFrags ; +#line 1684 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const INDEX ctPlayers = SetAllPlayersStats (bFragMatch ? 5 : 3); +#line 1687 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , "^cFFFFFF%s:^r\n%s" , TRANS ("TIME") , TimeToString (_pNetwork -> GetGameTime ()))); +#line 1688 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1691 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iMaxFrags = LowerLimit (INDEX (0)); +#line 1692 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iMaxScore = LowerLimit (INDEX (0)); +#line 1693 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{for(INDEX iPlayer = 0;iPlayer < ctPlayers ;iPlayer ++){ +#line 1694 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * penPlayer = _apenPlayers [ iPlayer ]; +#line 1695 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iMaxFrags = Max (iMaxFrags , penPlayer -> m_psLevelStats . ps_iKills ); +#line 1696 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iMaxScore = Max (iMaxScore , penPlayer -> m_psLevelStats . ps_iScore ); +#line 1697 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}} +#line 1700 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const CSessionProperties & sp = * GetSP (); +#line 1701 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(sp . sp_iTimeLimit > 0){ +#line 1702 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fTimeLeft = ClampDn (sp . sp_iTimeLimit * 60.0f - _pNetwork -> GetGameTime () , 0.0f); +#line 1703 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , "^cFFFFFF%s:^r\n%s" , TRANS ("TIME LEFT") , TimeToString (fTimeLeft ))); +#line 1704 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1705 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1706 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bFragMatch && sp . sp_iFragLimit > 0){ +#line 1707 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iFragsLeft = ClampDn (sp . sp_iFragLimit - iMaxFrags , INDEX (0)); +#line 1708 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , "^cFFFFFF%s:^r\n%d" , TRANS ("FRAGS LEFT") , iFragsLeft )); +#line 1709 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1710 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1711 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! bFragMatch && sp . sp_iScoreLimit > 0){ +#line 1712 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iScoreLeft = ClampDn (sp . sp_iScoreLimit - iMaxScore , INDEX (0)); +#line 1713 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , "^cFFFFFF%s:^r\n%d" , TRANS ("SCORE LEFT") , iScoreLeft )); +#line 1714 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1715 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1716 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1718 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strRank = TRANS ("NO."); +#line 1719 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strFrag = bFragMatch ? TRANS ("FRAGS") : TRANS ("SCORE"); +#line 1720 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strPing = TRANS ("PING"); +#line 1721 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strName = TRANS ("PLAYER"); +#line 1722 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX ctRankChars = Max (strRank . Length () , INDEX (3)); +#line 1723 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX ctFragChars = Max (strFrag . Length () , INDEX (7)); +#line 1724 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX ctPingChars = Max (strPing . Length () , INDEX (5)); +#line 1725 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX ctNameChars = Max (strName . Length () , INDEX (20)); +#line 1728 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "^cFFFFFF"; +#line 1729 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += PadStringRight (strRank , ctRankChars ) + " "; +#line 1730 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += PadStringLeft (strFrag , ctFragChars ) + " "; +#line 1731 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += PadStringLeft (strPing , ctPingChars ) + " "; +#line 1732 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += PadStringRight (strName , ctNameChars ) + " "; +#line 1733 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "^r"; +#line 1734 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n\n"; +#line 1735 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{for(INDEX iPlayer = 0;iPlayer < ctPlayers ;iPlayer ++){ +#line 1736 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strLine ; +#line 1737 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * penPlayer = _apenPlayers [ iPlayer ]; +#line 1738 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iPing = ceil (penPlayer -> en_tmPing * 1000.0f); +#line 1739 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iScore = bFragMatch ? penPlayer -> m_psLevelStats . ps_iKills : penPlayer -> m_psLevelStats . ps_iScore ; +#line 1740 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strName = penPlayer -> GetPlayerName (); +#line 1742 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += PadStringRight (CTString (0 , "%d" , iPlayer + 1) , ctRankChars ) + " "; +#line 1743 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += PadStringLeft (CTString (0 , "%d" , iScore ) , ctFragChars ) + " "; +#line 1744 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += PadStringLeft (CTString (0 , "%d" , iPing ) , ctPingChars ) + " "; +#line 1745 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += PadStringRight (strName , ctNameChars ) + " "; +#line 1746 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1747 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}} +#line 1748 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1751 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::GetDetailStatsCoop(CTString & strStats) +#line 1752 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1754 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "^b" + CenterString (TRANS ("YOUR STATS")) + "^r\n"; +#line 1755 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1756 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetDetailStatsSP (strStats , 1); +#line 1759 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +extern INDEX SetAllPlayersStats (INDEX iSortKey ); +#line 1760 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +extern CPlayer * _apenPlayers [ NET_MAXGAMEPLAYERS ]; +#line 1761 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const INDEX ctPlayers = SetAllPlayersStats (3); +#line 1764 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlayerStats psSquadLevel = PlayerStats (); +#line 1765 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlayerStats psSquadGame = PlayerStats (); +#line 1766 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{for(INDEX iPlayer = 0;iPlayer < ctPlayers ;iPlayer ++){ +#line 1767 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * penPlayer = _apenPlayers [ iPlayer ]; +#line 1769 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (penPlayer != NULL ); +#line 1770 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlayerStats psLevel = penPlayer -> m_psLevelStats ; +#line 1771 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlayerStats psGame = penPlayer -> m_psGameStats ; +#line 1772 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +psSquadLevel . ps_iScore += psLevel . ps_iScore ; +#line 1773 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +psSquadLevel . ps_iKills += psLevel . ps_iKills ; +#line 1774 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +psSquadLevel . ps_iDeaths += psLevel . ps_iDeaths ; +#line 1775 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +psSquadLevel . ps_iSecrets += psLevel . ps_iSecrets ; +#line 1776 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +psSquadGame . ps_iScore += psGame . ps_iScore ; +#line 1777 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +psSquadGame . ps_iKills += psGame . ps_iKills ; +#line 1778 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +psSquadGame . ps_iDeaths += psGame . ps_iDeaths ; +#line 1779 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +psSquadGame . ps_iSecrets += psGame . ps_iSecrets ; +#line 1780 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}} +#line 1783 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1784 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "^b" + CenterString (TRANS ("SQUAD TOTAL")) + "^r\n"; +#line 1785 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1786 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += CTString (0 , "^cFFFFFF%s^r" , TranslateConst (en_pwoWorld -> GetName () , 0)); +#line 1787 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1788 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d" , TRANS ("SCORE") , psSquadLevel . ps_iScore )); +#line 1789 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1790 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d" , TRANS ("DEATHS") , psSquadLevel . ps_iDeaths )); +#line 1791 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1792 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d/%d" , TRANS ("KILLS") , psSquadLevel . ps_iKills , m_psLevelTotal . ps_iKills )); +#line 1793 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1794 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d/%d" , TRANS ("SECRETS") , psSquadLevel . ps_iSecrets , m_psLevelTotal . ps_iSecrets )); +#line 1795 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1796 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1797 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += CTString ("^cFFFFFF") + TRANS ("TOTAL") + "^r\n"; +#line 1798 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d" , TRANS ("SCORE") , psSquadGame . ps_iScore )); +#line 1799 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1800 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d" , TRANS ("DEATHS") , psSquadGame . ps_iDeaths )); +#line 1801 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1802 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d/%d" , TRANS ("KILLS") , psSquadGame . ps_iKills , m_psGameTotal . ps_iKills )); +#line 1803 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1804 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d/%d" , TRANS ("SECRETS") , psSquadGame . ps_iSecrets , m_psGameTotal . ps_iSecrets )); +#line 1805 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1806 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1809 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1810 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "^b" + CenterString (TRANS ("OTHER PLAYERS")) + "^r\n"; +#line 1811 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1814 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{for(INDEX iPlayer = 0;iPlayer < ctPlayers ;iPlayer ++){ +#line 1815 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * penPlayer = _apenPlayers [ iPlayer ]; +#line 1817 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penPlayer == this ){ +#line 1819 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +continue ; +#line 1820 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1822 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "^cFFFFFF" + CenterString (penPlayer -> GetPlayerName ()) + "^r\n\n"; +#line 1823 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penPlayer -> GetDetailStatsSP (strStats , 2); +#line 1824 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1825 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}} +#line 1826 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1829 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::GetDetailStatsSP(CTString & strStats,INDEX iCoopType) +#line 1830 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1831 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iCoopType <= 1){ +#line 1832 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_bEndOfGame ){ +#line 1833 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_gdGameDifficulty == CSessionProperties :: GD_EXTREME ){ +#line 1834 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += TRANS ("^f4SERIOUS GAME FINISHED,\nMENTAL MODE IS NOW ENABLED!^F\n\n"); +#line 1835 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(GetSP () -> sp_bMental ){ +#line 1836 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += TRANS ("^f4YOU HAVE MASTERED THE GAME!^F\n\n"); +#line 1837 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1838 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1839 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1841 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iCoopType <= 1){ +#line 1843 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , "^cFFFFFF%s:^r\n%d" , TRANS ("TOTAL SCORE") , m_psGameStats . ps_iScore )); +#line 1844 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1845 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , "^cFFFFFF%s:^r\n%s" , TRANS ("DIFFICULTY") , GetDifficultyString ())); +#line 1846 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1847 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , "^cFFFFFF%s:^r\n%s" , TRANS ("STARTED") , GetStatsRealWorldStarted ())); +#line 1848 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1849 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , "^cFFFFFF%s:^r\n%s" , TRANS ("PLAYING TIME") , TimeToString (GetStatsRealWorldTime ()))); +#line 1850 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1851 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_psGameStats . ps_iScore <= plr_iHiScore ){ +#line 1852 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , "^cFFFFFF%s:^r\n%d" , TRANS ("HI-SCORE") , plr_iHiScore )); +#line 1853 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1854 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += TRANS ("YOU BEAT THE HI-SCORE!"); +#line 1855 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1856 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n\n"; +#line 1857 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1860 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += CTString (0 , "^cFFFFFF%s^r" , TranslateConst (en_pwoWorld -> GetName () , 0)); +#line 1861 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1862 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iCoopType <= 1){ +#line 1863 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_bEndOfLevel ){ +#line 1864 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%s" , TRANS ("ESTIMATED TIME") , TimeToString (m_tmEstTime ))); +#line 1865 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1866 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d" , TRANS ("TIME BONUS") , m_iTimeScore )); +#line 1867 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1868 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1869 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1872 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1873 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d" , TRANS ("SCORE") , m_psLevelStats . ps_iScore )); +#line 1874 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1875 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d/%d" , TRANS ("KILLS") , m_psLevelStats . ps_iKills , m_psLevelTotal . ps_iKills )); +#line 1876 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1877 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iCoopType >= 1){ +#line 1878 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d" , TRANS ("DEATHS") , m_psLevelStats . ps_iDeaths , m_psLevelTotal . ps_iDeaths )); +#line 1879 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1880 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1881 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d/%d" , TRANS ("SECRETS") , m_psLevelStats . ps_iSecrets , m_psLevelTotal . ps_iSecrets )); +#line 1882 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1883 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iCoopType <= 1){ +#line 1884 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%s" , TRANS ("TIME") , TimeToString (GetStatsInGameTimeLevel ()))); +#line 1885 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1886 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1887 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1890 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += CTString ("^cFFFFFF") + TRANS ("TOTAL") + "^r"; +#line 1891 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1892 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d" , TRANS ("SCORE") , m_psGameStats . ps_iScore )); +#line 1893 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1894 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d/%d" , TRANS ("KILLS") , m_psGameStats . ps_iKills , m_psGameTotal . ps_iKills )); +#line 1895 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1896 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iCoopType >= 1){ +#line 1897 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d" , TRANS ("DEATHS") , m_psGameStats . ps_iDeaths , m_psGameTotal . ps_iDeaths )); +#line 1898 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1899 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1900 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%d/%d" , TRANS ("SECRETS") , m_psGameStats . ps_iSecrets , m_psGameTotal . ps_iSecrets )); +#line 1901 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1902 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iCoopType <= 1){ +#line 1903 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += AlignString (CTString (0 , " %s:\n%s" , TRANS ("GAME TIME") , TimeToString (GetStatsInGameTimeGame ()))); +#line 1904 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1905 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1906 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += "\n"; +#line 1909 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iCoopType < 1){ +#line 1910 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_strLevelStats != ""){ +#line 1911 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats += CTString ("^cFFFFFF") + TRANS ("Per level statistics") + "^r\n\n" + m_strLevelStats ; +#line 1912 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1913 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1914 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1917 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::GetGameAgentPlayerInfo(INDEX iPlayer,CTString & strOut) +#line 1918 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1919 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strPlayerName = GetPlayerName (); +#line 1920 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iLen = strlen (strPlayerName ); +#line 1921 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX i = 0;i < iLen ;i ++){ +#line 1922 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(strPlayerName [ i ] == '\r' || strPlayerName [ i ] == '\n'){ +#line 1924 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strPlayerName = "\x11"; +#line 1925 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 1926 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(strPlayerName [ i ] < 32){ +#line 1928 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strPlayerName = "\x12"; +#line 1929 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 1930 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1931 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1933 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strKey ; +#line 1934 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strKey . PrintF ("player_%d\x02%s\x03" , iPlayer , (const char *) strPlayerName ); +#line 1935 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strOut += strKey ; +#line 1936 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bUseFrags ){ +#line 1937 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strKey . PrintF ("frags_%d\x02%d\x03" , iPlayer , m_psLevelStats . ps_iKills ); +#line 1938 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strOut += strKey ; +#line 1939 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 1940 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strKey . PrintF ("frags_%d\x02%d\x03" , iPlayer , m_psLevelStats . ps_iScore ); +#line 1941 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strOut += strKey ; +#line 1942 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1943 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strKey . PrintF ("ping_%d\x02%d\x03" , iPlayer , INDEX (ceil (en_tmPing * 1000.0f))); +#line 1944 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strOut += strKey ; +#line 1945 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1948 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL CPlayer::HasMessage(const CTFileName & fnmMessage) +#line 1949 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1950 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ULONG ulHash = fnmMessage . GetHash (); +#line 1951 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX ctMsg = m_acmiMessages . Count (); +#line 1952 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iMsg = 0;iMsg < ctMsg ;iMsg ++){ +#line 1953 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_acmiMessages [ iMsg ] . cmi_ulHash == ulHash && +#line 1954 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_acmiMessages [ iMsg ] . cmi_fnmFileName == fnmMessage ){ +#line 1955 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE ; +#line 1956 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1957 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1958 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return FALSE ; +#line 1959 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1962 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ReceiveComputerMessage(const CTFileName & fnmMessage,ULONG ulFlags) +#line 1963 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1965 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(HasMessage (fnmMessage )){ +#line 1967 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 1968 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1970 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CCompMessageID & cmi = m_acmiMessages . Push (); +#line 1971 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cmi . NewMessage (fnmMessage ); +#line 1972 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cmi . cmi_bRead = ulFlags & CMF_READ ; +#line 1973 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (ulFlags & CMF_READ )){ +#line 1974 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ctUnreadMessages ++; +#line 1975 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cmp_bUpdateInBackground = TRUE ; +#line 1976 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1977 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (ulFlags & CMF_READ ) && (ulFlags & CMF_ANALYZE )){ +#line 1978 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmAnalyseEnd = _pTimer -> CurrentTick () + 2.0f; +#line 1979 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soMessage . Set3DParameters (25.0f , 5.0f , 1.0f , 1.0f); +#line 1980 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMessage , SOUND_INFO , SOF_3D | SOF_VOLUMETRIC | SOF_LOCAL ); +#line 1981 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1982 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1984 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SayVoiceMessage(const CTFileName & fnmMessage) +#line 1985 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1986 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSettings () -> ps_ulFlags & PSF_NOQUOTES ){ +#line 1987 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 1988 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 1989 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetSpeakMouthPitch (); +#line 1990 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soSpeech , fnmMessage , SOF_3D | SOF_VOLUMETRIC ); +#line 1991 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 1994 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::CheatAllMessagesDir(const CTString & strDir,ULONG ulFlags) +#line 1995 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 1997 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CDynamicStackArray < CTFileName > afnmDir ; +#line 1998 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +MakeDirList (afnmDir , strDir , "*.txt" , DLI_RECURSIVE ); +#line 2001 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX i = 0;i < afnmDir . Count ();i ++){ +#line 2002 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTFileName fnm = afnmDir [ i ]; +#line 2004 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ReceiveComputerMessage (fnm , ulFlags ); +#line 2005 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2006 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2009 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::CheatAllMessages(void) +#line 2010 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2014 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheatAllMessagesDir ("Data\\Messages\\weapons\\" , 0); +#line 2015 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheatAllMessagesDir ("Data\\Messages\\enemies\\" , 0); +#line 2016 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheatAllMessagesDir ("DataMP\\Messages\\enemies\\" , 0); +#line 2017 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheatAllMessagesDir ("DataMP\\Messages\\information\\" , 0); +#line 2018 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheatAllMessagesDir ("DataMP\\Messages\\statistics\\" , 0); +#line 2019 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheatAllMessagesDir ("DataMP\\Messages\\weapons\\" , 0); +#line 2020 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheatAllMessagesDir ("DataMP\\Messages\\background\\" , 0); +#line 2021 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2024 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ItemPicked(const CTString & strName,FLOAT fAmmount) +#line 2025 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2027 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pTimer -> CurrentTick () > m_tmLastPicked + PICKEDREPORT_TIME ){ +#line 2029 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_strPickedName = ""; +#line 2031 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fPickedMana = 0; +#line 2032 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2034 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_strPickedName != strName ){ +#line 2036 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_strPickedName = strName ; +#line 2038 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fPickedAmmount = 0; +#line 2039 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2041 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fPickedAmmount += fAmmount ; +#line 2042 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmLastPicked = _pTimer -> CurrentTick (); +#line 2043 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2046 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SetupLightSource(void) +#line 2047 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2049 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CLightSource lsNew ; +#line 2050 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +lsNew . ls_ulFlags = LSF_NONPERSISTENT | LSF_DYNAMIC ; +#line 2051 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +lsNew . ls_rHotSpot = 1.0f; +#line 2052 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +lsNew . ls_colColor = C_WHITE ; +#line 2053 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +lsNew . ls_rFallOff = 2.5f; +#line 2054 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +lsNew . ls_plftLensFlare = NULL ; +#line 2055 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +lsNew . ls_ubPolygonalMask = 0; +#line 2056 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +lsNew . ls_paoLightAnimation = & m_aoLightAnimation ; +#line 2058 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_lsLightSource . ls_penEntity = this ; +#line 2059 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 2060 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2063 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::PlayLightAnim(INDEX iAnim,ULONG ulFlags) { +#line 2064 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 2065 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_aoLightAnimation . PlayAnim (iAnim , ulFlags ); +#line 2066 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2067 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2070 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL CPlayer::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 2071 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2072 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_bDumpPlayerShading ) +#line 2073 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2074 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ANGLE3D a3dHPB ; +#line 2075 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +DirectionVectorToAngles (- vLightDirection , a3dHPB ); +#line 2076 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UBYTE ubAR , ubAG , ubAB ; +#line 2077 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UBYTE ubCR , ubCG , ubCB ; +#line 2078 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ColorToRGB (colAmbient , ubAR , ubAG , ubAB ); +#line 2079 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ColorToRGB (colLight , ubCR , ubCG , ubCB ); +#line 2080 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF ("Ambient: %d,%d,%d, Color: %d,%d,%d, Direction HPB (%g,%g,%g)\n" , +#line 2081 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ubAR , ubAG , ubAB , ubCR , ubCG , ubCB , a3dHPB (1) , a3dHPB (2) , a3dHPB (3)); +#line 2082 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2085 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! GetSP () -> sp_bCooperative ){ +#line 2086 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UBYTE ubH , ubS , ubV ; +#line 2087 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ColorToHSV (colAmbient , ubH , ubS , ubV ); +#line 2088 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ubV < 22){ +#line 2089 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ubV = 22; +#line 2090 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +colAmbient = HSVToColor (ubH , ubS , ubV ); +#line 2091 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2092 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2094 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return CPlayerEntity :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 2095 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2098 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject * CPlayer::GetModelForRendering(void) +#line 2099 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2101 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (m_ulFlags & PLF_INITIALIZED )){ +#line 2103 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return GetModelObject (); +#line 2104 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2107 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plView ; +#line 2108 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plView . Lerp (en_plLastViewpoint , en_plViewpoint , _pTimer -> GetLerpFactor ()); +#line 2110 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . BodyAndHeadOrientation (plView ); +#line 2111 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . OnPreRender (); +#line 2113 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_moRender . Synchronize (* GetModelObject ()); +#line 2114 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulFlags & PLF_SYNCWEAPON ){ +#line 2115 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_SYNCWEAPON ; +#line 2116 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerAnimator () -> SyncWeapon (); +#line 2117 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2119 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 2121 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fFading = 1.0f; +#line 2122 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_tmFadeStart != 0){ +#line 2123 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fFactor = (tmNow - m_tmFadeStart ) / 5.0f; +#line 2124 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fFactor = Clamp (fFactor , 0.0f , 1.0f); +#line 2125 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fFading *= fFactor ; +#line 2126 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2129 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT tmSpawnInvulnerability = GetSP () -> sp_tmSpawnInvulnerability ; +#line 2130 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmSpawnInvulnerability > 0 && tmNow - m_tmSpawned < tmSpawnInvulnerability ){ +#line 2132 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDelta = tmNow - m_tmSpawned ; +#line 2133 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fFading *= 0.75f + 0.25f * Sin (fDelta / 0.5f * 360); +#line 2134 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2136 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +COLOR colAlpha = m_moRender . mo_colBlendColor ; +#line 2137 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +colAlpha = (colAlpha & 0xffffff00) + (COLOR (fFading * 0xff) & 0xff); +#line 2138 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_moRender . mo_colBlendColor = colAlpha ; +#line 2141 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulFlags & PLF_NOTCONNECTED ){ +#line 2143 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fFading *= 0.25f + 0.25f * Sin (tmNow / 2.0f * 360); +#line 2145 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_tmInvisibility > tmNow ){ +#line 2146 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fIntensity = 0.0f; +#line 2147 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((m_tmInvisibility - tmNow ) < 3.0f) +#line 2148 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2149 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fIntensity = 0.5f - 0.5f * cos ((m_tmInvisibility - tmNow ) * (6.0f * 3.1415927f / 3.0f)); +#line 2150 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2151 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_ulPlayerRenderingMask == 1 << GetMyPlayerIndex ()){ +#line 2152 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +colAlpha = (colAlpha & 0xffffff00) | (INDEX) (INVISIBILITY_ALPHA_LOCAL + (FLOAT) (254 - INVISIBILITY_ALPHA_LOCAL ) * fIntensity ); +#line 2153 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(TRUE ){ +#line 2154 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((m_tmInvisibility - tmNow ) < 1.28f){ +#line 2155 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +colAlpha = (colAlpha & 0xffffff00) | (INDEX) (INVISIBILITY_ALPHA_REMOTE + (FLOAT) (254 - INVISIBILITY_ALPHA_REMOTE ) * fIntensity ); +#line 2156 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(TRUE ){ +#line 2157 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +colAlpha = (colAlpha & 0xffffff00) | INVISIBILITY_ALPHA_REMOTE ; +#line 2158 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2159 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2160 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_moRender . mo_colBlendColor = colAlpha ; +#line 2161 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2164 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return & m_moRender ; +#line 2165 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2168 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +class CPlayerActionMarker * CPlayer::GetActionMarker(void) { +#line 2169 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return (CPlayerActionMarker *) & * m_penActionMarker ; +#line 2170 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2173 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::FindMusicHolder(void) +#line 2174 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2175 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penMainMusicHolder == NULL ){ +#line 2176 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penMainMusicHolder = _pNetwork -> GetEntityWithName ("MusicHolder" , 0); +#line 2177 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2178 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2181 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::UpdateLevelStats(void) +#line 2182 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2184 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats = PlayerStats (); +#line 2187 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penMainMusicHolder == NULL ){ +#line 2188 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 2189 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2190 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CMusicHolder & mh = (CMusicHolder &) * m_penMainMusicHolder ; +#line 2193 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(mh . m_ctEnemiesInWorld == 0){ +#line 2194 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +mh . CountEnemies (); +#line 2195 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2197 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelTotal . ps_iKills = mh . m_ctEnemiesInWorld ; +#line 2198 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameTotal . ps_iKills += mh . m_ctEnemiesInWorld ; +#line 2199 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelTotal . ps_iSecrets = mh . m_ctSecretsInWorld ; +#line 2200 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameTotal . ps_iSecrets += mh . m_ctSecretsInWorld ; +#line 2201 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2204 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL CPlayer::IsFuss(void) +#line 2205 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2207 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penMainMusicHolder == NULL ){ +#line 2209 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return FALSE ; +#line 2210 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2212 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ((CMusicHolder *) & * m_penMainMusicHolder ) -> m_cenFussMakers . Count () > 0; +#line 2213 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2215 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SetDefaultMouthPitch(void) +#line 2216 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2217 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soMouth . Set3DParameters (50.0f , 10.0f , 1.0f , 1.0f); +#line 2218 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2219 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SetRandomMouthPitch(FLOAT fMin,FLOAT fMax) +#line 2220 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2221 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soMouth . Set3DParameters (50.0f , 10.0f , 1.0f , Lerp (fMin , fMax , FRnd ())); +#line 2222 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2223 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SetSpeakMouthPitch(void) +#line 2224 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2225 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soSpeech . Set3DParameters (50.0f , 10.0f , 2.0f , 1.0f); +#line 2226 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2229 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ApplyShaking(CPlacement3D & plViewer) +#line 2230 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2232 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fT = _pTimer -> GetLerpedCurrentTick (); +#line 2233 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fT < m_tmChainShakeEnd ) +#line 2234 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2235 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fChainsawShakeDX = 0.03f * m_fChainShakeStrength * SinFast (fT * m_fChainShakeFreqMod * 3300.0f); +#line 2236 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fChainsawShakeDY = 0.03f * m_fChainShakeStrength * SinFast (fT * m_fChainShakeFreqMod * 2900.0f); +#line 2238 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plViewer . pl_PositionVector (1) += m_fChainsawShakeDX ; +#line 2239 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plViewer . pl_PositionVector (3) += m_fChainsawShakeDY ; +#line 2240 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2242 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 2243 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pwsc == NULL || pwsc -> m_tmShakeStarted < 0){ +#line 2244 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 2245 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2247 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME tm = _pTimer -> GetLerpedCurrentTick () - pwsc -> m_tmShakeStarted ; +#line 2248 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tm < 0){ +#line 2249 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 2250 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2251 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDistance = (plViewer . pl_PositionVector - pwsc -> m_vShakePos ) . Length (); +#line 2252 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fIntensity = IntensityAtDistance (pwsc -> m_fShakeFalloff , 0 , fDistance ); +#line 2253 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fShakeY , fShakeB , fShakeZ ; +#line 2254 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! pwsc -> m_bShakeFadeIn ){ +#line 2255 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fShakeY = SinFast (tm * pwsc -> m_tmShakeFrequencyY * 360.0f) * +#line 2256 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +exp (- tm * (pwsc -> m_fShakeFade )) * +#line 2257 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fIntensity * pwsc -> m_fShakeIntensityY ; +#line 2258 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fShakeB = SinFast (tm * pwsc -> m_tmShakeFrequencyB * 360.0f) * +#line 2259 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +exp (- tm * (pwsc -> m_fShakeFade )) * +#line 2260 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fIntensity * pwsc -> m_fShakeIntensityB ; +#line 2261 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fShakeZ = SinFast (tm * pwsc -> m_tmShakeFrequencyZ * 360.0f) * +#line 2262 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +exp (- tm * (pwsc -> m_fShakeFade )) * +#line 2263 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fIntensity * pwsc -> m_fShakeIntensityZ ; +#line 2264 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 2265 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT ootm = 1.0f / tm ; +#line 2266 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fShakeY = SinFast (tm * pwsc -> m_tmShakeFrequencyY * 360.0f) * +#line 2267 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +exp ((tm - 2) * ootm * (pwsc -> m_fShakeFade )) * +#line 2268 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fIntensity * pwsc -> m_fShakeIntensityY ; +#line 2269 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fShakeB = SinFast (tm * pwsc -> m_tmShakeFrequencyB * 360.0f) * +#line 2270 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +exp ((tm - 2) * ootm * (pwsc -> m_fShakeFade )) * +#line 2271 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fIntensity * pwsc -> m_fShakeIntensityB ; +#line 2272 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fShakeZ = SinFast (tm * pwsc -> m_tmShakeFrequencyZ * 360.0f) * +#line 2273 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +exp ((tm - 2) * ootm * (pwsc -> m_fShakeFade )) * +#line 2274 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fIntensity * pwsc -> m_fShakeIntensityZ ; +#line 2275 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2276 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plViewer . pl_PositionVector (2) += fShakeY ; +#line 2277 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plViewer . pl_PositionVector (3) += fShakeZ ; +#line 2278 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plViewer . pl_OrientationAngle (3) += fShakeB ; +#line 2280 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2282 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +COLOR CPlayer::GetWorldGlaring(void) +#line 2283 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2284 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 2285 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pwsc == NULL || pwsc -> m_tmGlaringStarted < 0){ +#line 2286 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return 0; +#line 2287 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2288 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME tm = _pTimer -> GetLerpedCurrentTick (); +#line 2289 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fRatio = CalculateRatio (tm , pwsc -> m_tmGlaringStarted , pwsc -> m_tmGlaringEnded , +#line 2290 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pwsc -> m_fGlaringFadeInRatio , pwsc -> m_fGlaringFadeOutRatio ); +#line 2291 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +COLOR colResult = (pwsc -> m_colGlade & 0xFFFFFF00) | (UBYTE (fRatio * 255.0f)); +#line 2292 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return colResult ; +#line 2293 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2295 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RenderScroll(CDrawPort * pdp) +#line 2296 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2297 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 2298 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pwsc != NULL && pwsc -> m_penScrollHolder != NULL ) +#line 2299 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2300 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CScrollHolder & sch = (CScrollHolder &) * pwsc -> m_penScrollHolder ; +#line 2301 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sch . Credits_Render (& sch , pdp ); +#line 2302 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2303 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2305 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RenderCredits(CDrawPort * pdp) +#line 2306 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2307 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 2308 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pwsc != NULL && pwsc -> m_penCreditsHolder != NULL ) +#line 2309 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2310 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CCreditsHolder & cch = (CCreditsHolder &) * pwsc -> m_penCreditsHolder ; +#line 2311 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cch . Credits_Render (& cch , pdp ); +#line 2312 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2313 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2315 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RenderTextFX(CDrawPort * pdp) +#line 2316 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2317 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 2318 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pwsc != NULL && pwsc -> m_penTextFXHolder != NULL ) +#line 2319 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2320 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTextFXHolder & tfx = (CTextFXHolder &) * pwsc -> m_penTextFXHolder ; +#line 2321 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +tfx . TextFX_Render (& tfx , pdp ); +#line 2322 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2323 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2325 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RenderHudPicFX(CDrawPort * pdp) +#line 2326 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2327 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 2328 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pwsc != NULL && pwsc -> m_penHudPicFXHolder != NULL ) +#line 2329 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2330 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CHudPicHolder & hpfx = (CHudPicHolder &) * pwsc -> m_penHudPicFXHolder ; +#line 2331 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +hpfx . HudPic_Render (& hpfx , pdp ); +#line 2332 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2333 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2340 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SetupView(CDrawPort * pdp,CAnyProjection3D & apr,CEntity * & penViewer, +#line 2341 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D & plViewer,COLOR & colBlend,BOOL bCamera) +#line 2342 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2344 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetLerpedAbsoluteViewPlacement (plViewer ); +#line 2345 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (IsValidFloat (plViewer . pl_OrientationAngle (1)) && IsValidFloat (plViewer . pl_OrientationAngle (2)) && IsValidFloat (plViewer . pl_OrientationAngle (3))); +#line 2347 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penViewer = GetViewEntity (); +#line 2349 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iViewState = m_iViewState ; +#line 2351 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penCamera != NULL && bCamera ){ +#line 2352 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iViewState = PVT_SCENECAMERA ; +#line 2353 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plViewer = m_penCamera -> GetLerpedPlacement (); +#line 2354 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penViewer = m_penCamera ; +#line 2355 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2358 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPerspectiveProjection3D prPerspectiveProjection ; +#line 2359 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plr_fFOV = Clamp (plr_fFOV , 1.0f , 160.0f); +#line 2360 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ANGLE aFOV = plr_fFOV ; +#line 2362 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! GetSP () -> sp_bCooperative ){ +#line 2363 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aFOV = 90.0f; +#line 2364 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2366 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((CPlayerWeapons &) * m_penWeapons ) . m_iCurrentWeapon == WEAPON_SNIPER ) +#line 2367 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2368 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aFOV = Lerp (((CPlayerWeapons &) * m_penWeapons ) . m_fSniperFOVlast , +#line 2369 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . m_fSniperFOV , +#line 2370 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pTimer -> GetLerpFactor ()); +#line 2371 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2373 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_DIVE && iViewState == PVT_PLAYEREYES ){ +#line 2374 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 2375 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aFOV += sin (tmNow * 0.79f) * 2.0f; +#line 2376 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2377 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ApplyShaking (plViewer ); +#line 2379 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +colBlend = 0; +#line 2380 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iViewState == PVT_SCENECAMERA ){ +#line 2381 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CCamera * pcm = (CCamera *) & * m_penCamera ; +#line 2382 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +prPerspectiveProjection . FOVL () = +#line 2383 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Lerp (pcm -> m_fLastFOV , pcm -> m_fFOV , _pTimer -> GetLerpFactor ()); +#line 2384 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pcm -> m_tmDelta > 0.001f){ +#line 2385 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fFactor = (_pTimer -> GetLerpedCurrentTick () - pcm -> m_tmAtMarker ) / pcm -> m_tmDelta ; +#line 2386 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fFactor = Clamp (fFactor , 0.0f , 1.0f); +#line 2387 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +colBlend = LerpColor (pcm -> m_colFade0 , pcm -> m_colFade1 , fFactor ); +#line 2388 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 2389 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +colBlend = pcm -> m_colFade0 ; +#line 2390 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2391 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 2392 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +prPerspectiveProjection . FOVL () = aFOV ; +#line 2393 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2394 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +prPerspectiveProjection . ScreenBBoxL () = FLOATaabbox2D ( +#line 2395 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT2D (0.0f , 0.0f) , +#line 2396 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT2D ((FLOAT) pdp -> GetWidth () , (FLOAT) pdp -> GetHeight ()) +#line 2397 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +); +#line 2399 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plr_fFrontClipDistance = Clamp (plr_fFrontClipDistance , 0.05f , 0.50f); +#line 2400 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fFCD = plr_fFrontClipDistance ; +#line 2402 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_SWIM && iViewState == PVT_PLAYEREYES ){fFCD *= 0.6666f;} +#line 2403 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +prPerspectiveProjection . FrontClipDistanceL () = fFCD ; +#line 2404 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +prPerspectiveProjection . AspectRatioL () = 1.0f; +#line 2406 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +apr = prPerspectiveProjection ; +#line 2407 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +apr -> ViewerPlacementL () = plViewer ; +#line 2408 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +apr -> ObjectPlacementL () = CPlacement3D (FLOAT3D (0 , 0 , 0) , ANGLE3D (0 , 0 , 0)); +#line 2409 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +prPlayerProjection = apr ; +#line 2410 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +prPlayerProjection -> Prepare (); +#line 2411 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2414 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ListenFromEntity(CEntity * penListener,const CPlacement3D & plSound) +#line 2415 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2416 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATmatrix3D mRotation ; +#line 2417 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +MakeRotationMatrixFast (mRotation , plSound . pl_OrientationAngle ); +#line 2418 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sliSound . sli_vPosition = plSound . pl_PositionVector ; +#line 2419 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sliSound . sli_mRotation = mRotation ; +#line 2420 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sliSound . sli_fVolume = 1.0f; +#line 2421 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sliSound . sli_vSpeed = en_vCurrentTranslationAbsolute ; +#line 2422 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sliSound . sli_penEntity = penListener ; +#line 2423 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_DIVE ){ +#line 2424 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sliSound . sli_fFilter = 20.0f; +#line 2425 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 2426 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sliSound . sli_fFilter = 0.0f; +#line 2427 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2428 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iEnv = 0; +#line 2430 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CBrushSector * pbsc = penListener -> GetSectorFromPoint (plSound . pl_PositionVector ); +#line 2433 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pbsc != NULL ){ +#line 2434 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iEnv = pbsc -> GetEnvironmentType (); +#line 2435 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2438 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEnvironmentType & et = GetWorld () -> wo_aetEnvironmentTypes [ iEnv ]; +#line 2439 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sliSound . sli_iEnvironmentType = et . et_iType ; +#line 2440 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +sliSound . sli_fEnvironmentSize = et . et_fSize ; +#line 2441 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pSound -> Listen (sliSound ); +#line 2442 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2445 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RenderDummyView(CDrawPort * pdp) +#line 2446 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2448 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> Fill (C_BLACK | CT_OPAQUE ); +#line 2451 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! GetSP () -> sp_bSinglePlayer ){ +#line 2453 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PIX pixDPWidth = pdp -> GetWidth (); +#line 2454 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PIX pixDPHeight = pdp -> GetHeight (); +#line 2455 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fScale = (FLOAT) pixDPWidth / 640.0f; +#line 2456 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetFont (_pfdDisplayFont ); +#line 2457 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetTextScaling (fScale ); +#line 2458 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetTextAspect (1.0f); +#line 2459 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strMsg ; +#line 2460 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strMsg . PrintF (TRANS ("%s connected") , GetPlayerName ()); +#line 2461 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> PutTextCXY (strMsg , pixDPWidth * 0.5f , pixDPHeight * 0.5f , SE_COL_BLUE_NEUTRAL_LT | CT_OPAQUE ); +#line 2462 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2463 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2466 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RenderPlayerView(CDrawPort * pdp,BOOL bShowExtras) +#line 2467 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2469 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CAnyProjection3D apr ; +#line 2470 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * penViewer ; +#line 2471 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plViewer ; +#line 2472 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +COLOR colBlend ; +#line 2475 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iEye = STEREO_LEFT ;iEye <= (Stereo_IsEnabled () ? STEREO_RIGHT : STEREO_LEFT );iEye ++){ +#line 2478 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetupView (pdp , apr , penViewer , plViewer , colBlend , FALSE ); +#line 2481 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Stereo_SetBuffer (iEye ); +#line 2482 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Stereo_AdjustProjection (* apr , iEye , 1); +#line 2485 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (IsValidFloat (plViewer . pl_OrientationAngle (1)) && IsValidFloat (plViewer . pl_OrientationAngle (2)) && IsValidFloat (plViewer . pl_OrientationAngle (3))); +#line 2486 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_ulPlayerRenderingMask = 1 << GetMyPlayerIndex (); +#line 2487 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderView (* en_pwoWorld , * penViewer , apr , * pdp ); +#line 2488 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_ulPlayerRenderingMask = 0; +#line 2490 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iEye == STEREO_LEFT ){ +#line 2492 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ListenFromEntity (this , plViewer ); +#line 2493 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2495 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderScroll (pdp ); +#line 2496 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderTextFX (pdp ); +#line 2497 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderCredits (pdp ); +#line 2498 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderHudPicFX (pdp ); +#line 2500 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(hud_bShowAll && bShowExtras ){ +#line 2502 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plLight (_vViewerLightDirection , ANGLE3D (0 , 0 , 0)); +#line 2503 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plLight . AbsoluteToRelative (plViewer ); +#line 2504 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderHUD (* (CPerspectiveProjection3D *) (CProjection3D *) apr , pdp , +#line 2505 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plLight . pl_PositionVector , _colViewerLight , _colViewerAmbient , +#line 2506 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penViewer == this && (GetFlags () & ENF_ALIVE ) , iEye ); +#line 2507 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2508 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2509 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Stereo_SetBuffer (STEREO_BOTH ); +#line 2512 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PIX pixDPWidth = pdp -> GetWidth (); +#line 2513 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PIX pixDPHeight = pdp -> GetHeight (); +#line 2514 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fScale = (FLOAT) pixDPWidth / 640.0f; +#line 2517 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pTimer -> CurrentTick () < m_tmCenterMessageEnd ){ +#line 2518 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetFont (_pfdDisplayFont ); +#line 2519 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetTextScaling (fScale ); +#line 2520 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetTextAspect (1.0f); +#line 2521 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> PutTextCXY (m_strCenterMessage , pixDPWidth * 0.5f , pixDPHeight * 0.85f , C_WHITE | 0xDD); +#line 2523 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(_pTimer -> CurrentTick () < m_tmLastPicked + PICKEDREPORT_TIME ){ +#line 2524 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetFont (_pfdDisplayFont ); +#line 2525 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetTextScaling (fScale ); +#line 2526 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetTextAspect (1.0f); +#line 2527 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strPicked ; +#line 2528 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_fPickedAmmount == 0){ +#line 2529 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strPicked = m_strPickedName ; +#line 2530 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 2531 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strPicked . PrintF ("%s +%d" , m_strPickedName , int (m_fPickedAmmount )); +#line 2532 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2533 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> PutTextCXY (strPicked , pixDPWidth * 0.5f , pixDPHeight * 0.82f , C_WHITE | 0xDD); +#line 2534 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! GetSP () -> sp_bCooperative && ! GetSP () -> sp_bUseFrags && m_fPickedMana >= 1){ +#line 2535 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strValue ; +#line 2536 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strValue . PrintF ("%s +%d" , TRANS ("Value") , INDEX (m_fPickedMana )); +#line 2537 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> PutTextCXY (strValue , pixDPWidth * 0.5f , pixDPHeight * 0.85f , C_WHITE | 0xDD); +#line 2538 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2539 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2541 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pTimer -> CurrentTick () < m_tmAnalyseEnd ){ +#line 2542 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetFont (_pfdDisplayFont ); +#line 2543 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetTextScaling (fScale ); +#line 2544 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetTextAspect (1.0f); +#line 2545 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UBYTE ubA = int (sin (_pTimer -> CurrentTick () * 10.0f) * 127 + 128); +#line 2546 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> PutTextCXY (TRANS ("Analyzing...") , pixDPWidth * 0.5f , pixDPHeight * 0.2f , SE_COL_BLUE_NEUTRAL_LT | ubA ); +#line 2547 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2548 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2551 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RenderCameraView(CDrawPort * pdp,BOOL bListen) +#line 2552 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2553 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CDrawPort dpCamera ; +#line 2554 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CDrawPort * pdpCamera = pdp ; +#line 2555 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penCamera != NULL && ((CCamera &) * m_penCamera ) . m_bWideScreen ){ +#line 2556 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> MakeWideScreen (& dpCamera ); +#line 2557 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdpCamera = & dpCamera ; +#line 2558 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2560 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> Unlock (); +#line 2561 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdpCamera -> Lock (); +#line 2563 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CAnyProjection3D apr ; +#line 2564 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * penViewer ; +#line 2565 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plViewer ; +#line 2566 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +COLOR colBlend ; +#line 2569 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iEye = STEREO_LEFT ;iEye <= (Stereo_IsEnabled () ? STEREO_RIGHT : STEREO_LEFT );iEye ++){ +#line 2572 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetupView (pdpCamera , apr , penViewer , plViewer , colBlend , TRUE ); +#line 2575 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Stereo_SetBuffer (iEye ); +#line 2576 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Stereo_AdjustProjection (* apr , iEye , 1); +#line 2579 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (IsValidFloat (plViewer . pl_OrientationAngle (1)) && IsValidFloat (plViewer . pl_OrientationAngle (2)) && IsValidFloat (plViewer . pl_OrientationAngle (3))); +#line 2580 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_ulPlayerRenderingMask = 1 << GetMyPlayerIndex (); +#line 2581 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderView (* en_pwoWorld , * penViewer , apr , * pdpCamera ); +#line 2582 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_ulPlayerRenderingMask = 0; +#line 2585 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bListen && iEye == STEREO_LEFT ){ +#line 2586 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ListenFromEntity (penViewer , plViewer ); +#line 2587 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2588 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2589 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Stereo_SetBuffer (STEREO_BOTH ); +#line 2591 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderScroll (pdpCamera ); +#line 2592 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderTextFX (pdpCamera ); +#line 2593 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderCredits (pdpCamera ); +#line 2594 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderHudPicFX (pdpCamera ); +#line 2597 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2598 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +COLOR colGlare = GetWorldGlaring (); +#line 2599 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UBYTE ubR , ubG , ubB , ubA ; +#line 2600 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ColorToRGBA (colGlare , ubR , ubG , ubB , ubA ); +#line 2601 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ubA != 0){ +#line 2602 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdpCamera -> dp_ulBlendingRA += ULONG (ubR ) * ULONG (ubA ); +#line 2603 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdpCamera -> dp_ulBlendingGA += ULONG (ubG ) * ULONG (ubA ); +#line 2604 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdpCamera -> dp_ulBlendingBA += ULONG (ubB ) * ULONG (ubA ); +#line 2605 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdpCamera -> dp_ulBlendingA += ULONG (ubA ); +#line 2606 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2608 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdpCamera -> BlendScreen (); +#line 2609 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2611 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdpCamera -> Unlock (); +#line 2612 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> Lock (); +#line 2615 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((colBlend & CT_AMASK ) != 0){ +#line 2616 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> Fill (colBlend ); +#line 2617 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2620 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pTimer -> CurrentTick () < m_tmCenterMessageEnd ){ +#line 2621 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PIX pixDPWidth = pdp -> GetWidth (); +#line 2622 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PIX pixDPHeight = pdp -> GetHeight (); +#line 2623 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fScale = (FLOAT) pixDPWidth / 640.0f; +#line 2624 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetFont (_pfdDisplayFont ); +#line 2625 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetTextScaling (fScale ); +#line 2626 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> SetTextAspect (1.0f); +#line 2627 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> PutTextCXY (m_strCenterMessage , pixDPWidth * 0.5f , pixDPHeight * 0.85f , C_WHITE | 0xDD); +#line 2628 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2629 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2632 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RenderGameView(CDrawPort * pdp,void * pvUserData) +#line 2633 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2634 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bShowExtras = (ULONG (pvUserData ) & GRV_SHOWEXTRAS ); +#line 2635 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> Unlock (); +#line 2638 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (m_ulFlags & PLF_INITIALIZED ) || (m_ulFlags & PLF_DONTRENDER )){ +#line 2640 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CDrawPort dpView (pdp , TRUE ); +#line 2641 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(dpView . Lock ()){ +#line 2642 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderDummyView (& dpView ); +#line 2643 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +dpView . Unlock (); +#line 2644 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2645 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> Lock (); +#line 2646 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 2647 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2650 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pvUserData != 0){ +#line 2652 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTimerValue tvNow = _pTimer -> GetHighPrecisionTimer (); +#line 2653 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((tvNow - _tvProbingLast ) . GetSeconds () < 0.1){ +#line 2655 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pGfx -> gl_bAllowProbing = TRUE ; +#line 2656 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2657 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_tvProbingLast = tvNow ; +#line 2658 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2663 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bDualHead = +#line 2664 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> IsDualHead () && +#line 2665 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetSP () -> sp_gmGameMode != CSessionProperties :: GM_FLYOVER && +#line 2666 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penActionMarker == NULL ; +#line 2669 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bDualHead || m_penCamera == NULL ){ +#line 2671 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CDrawPort dpView (pdp , TRUE ); +#line 2672 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(dpView . Lock ()){ +#line 2674 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderPlayerView (& dpView , bShowExtras ); +#line 2675 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +dpView . Unlock (); +#line 2676 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2677 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2680 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penCamera != NULL ){ +#line 2682 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CDrawPort dpView (pdp , m_penActionMarker != NULL ); +#line 2683 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(dpView . Lock ()){ +#line 2685 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderCameraView (& dpView , ! bDualHead ); +#line 2686 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +dpView . Unlock (); +#line 2687 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2689 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 2691 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bDualHead ){ +#line 2693 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cmp_ppenDHPlayer = this ; +#line 2694 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2695 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2697 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> Lock (); +#line 2698 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2708 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::PreMoving(void) { +#line 2715 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . StoreLast (); +#line 2716 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerEntity :: PreMoving (); +#line 2717 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2720 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::DoMoving(void) { +#line 2721 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerEntity :: DoMoving (); +#line 2722 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . AnimateBanking (); +#line 2724 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penView != NULL ){ +#line 2725 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerView &) * m_penView ) . DoMoving (); +#line 2726 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2727 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pen3rdPersonView != NULL ){ +#line 2728 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerView &) * m_pen3rdPersonView ) . DoMoving (); +#line 2729 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2730 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2734 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::PostMoving(void) +#line 2735 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2736 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerEntity :: PostMoving (); +#line 2738 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_ulFlags &= ~ ENF_INRENDERING ; +#line 2740 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . AnimateSoftEyes (); +#line 2744 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetFlags () & ENF_ALIVE ) +#line 2745 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2746 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fManaFraction += +#line 2747 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ClampDn (1.0f - en_vCurrentTranslationAbsolute . Length () / 20.0f , 0.0f) * 20.0f +#line 2748 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +* _pTimer -> TickQuantum ; +#line 2749 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iNewMana = m_fManaFraction ; +#line 2750 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iMana += iNewMana ; +#line 2751 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fManaFraction -= iNewMana ; +#line 2752 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2755 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_gdGameDifficulty == CSessionProperties :: GD_TOURIST && GetFlags () & ENF_ALIVE ){ +#line 2757 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fHealth = GetHealth (); +#line 2758 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fTopHealth = TopHealth (); +#line 2759 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fHealth < fTopHealth ){ +#line 2760 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetHealth (ClampUp (fHealth + _pTimer -> TickQuantum , fTopHealth )); +#line 2761 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2762 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2765 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerWeapons () -> UpdateTargetingInfo (); +#line 2767 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pen3rdPersonView != NULL ){ +#line 2768 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerView &) * m_pen3rdPersonView ) . PostMoving (); +#line 2769 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2770 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penView != NULL ){ +#line 2771 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerView &) * m_penView ) . PostMoving (); +#line 2772 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2775 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (m_ulFlags & PLF_APPLIEDACTION )){ +#line 2777 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetUnconnected (); +#line 2778 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2781 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_APPLIEDACTION ; +#line 2782 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2785 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SetUnconnected(void) +#line 2786 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2787 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulFlags & PLF_NOTCONNECTED ){ +#line 2788 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 2789 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2790 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_NOTCONNECTED ; +#line 2793 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ForceFullStop (); +#line 2794 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPhysicsFlags (GetPhysicsFlags () & ~ (EPF_TRANSLATEDBYGRAVITY | EPF_ORIENTEDBYGRAVITY )); +#line 2795 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetCollisionFlags (GetCollisionFlags () & ~ ((ECBI_BRUSH | ECBI_MODEL ) << ECB_TEST )); +#line 2796 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plLastViewpoint . pl_OrientationAngle = en_plViewpoint . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 2798 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_STAND , 0); +#line 2799 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerAnimator () -> BodyAnimationTemplate ( +#line 2800 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BODY_ANIM_NORMALWALK , BODY_ANIM_COLT_STAND , BODY_ANIM_SHOTGUN_STAND , BODY_ANIM_MINIGUN_STAND , +#line 2801 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AOF_LOOPING | AOF_NORESTART ); +#line 2802 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2805 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SetConnected(void) +#line 2806 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2807 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (m_ulFlags & PLF_NOTCONNECTED )){ +#line 2808 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 2809 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2810 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_NOTCONNECTED ; +#line 2812 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPhysicsFlags (GetPhysicsFlags () | (EPF_TRANSLATEDBYGRAVITY | EPF_ORIENTEDBYGRAVITY )); +#line 2813 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetCollisionFlags (GetCollisionFlags () | ((ECBI_BRUSH | ECBI_MODEL ) << ECB_TEST )); +#line 2814 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2817 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL CPlayer::IsConnected(void)const +#line 2818 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2819 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ! (m_ulFlags & PLF_NOTCONNECTED ); +#line 2820 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2823 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ChecksumForSync(ULONG & ulCRC,INDEX iExtensiveSyncCheck) +#line 2824 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2825 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerEntity :: ChecksumForSync (ulCRC , iExtensiveSyncCheck ); +#line 2826 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CRC_AddLONG (ulCRC , m_psLevelStats . ps_iScore ); +#line 2827 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CRC_AddLONG (ulCRC , m_iMana ); +#line 2828 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iExtensiveSyncCheck > 0){ +#line 2829 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CRC_AddFLOAT (ulCRC , m_fManaFraction ); +#line 2830 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2831 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CRC_AddFLOAT (ulCRC , m_fArmor ); +#line 2832 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2836 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck) +#line 2837 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2838 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerEntity :: DumpSync_t (strm , iExtensiveSyncCheck ); +#line 2839 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strm . FPrintF_t ("Score: %d\n" , m_psLevelStats . ps_iScore ); +#line 2840 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strm . FPrintF_t ("m_iMana: %d\n" , m_iMana ); +#line 2841 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strm . FPrintF_t ("m_fManaFraction: %g(%08x)\n" , m_fManaFraction , (ULONG &) m_fManaFraction ); +#line 2842 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strm . FPrintF_t ("m_fArmor: %g(%08x)\n" , m_fArmor , (ULONG &) m_fArmor ); +#line 2843 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + void CPlayer::LeaveStain(BOOL bGrow) +#line 2852 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2853 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESpawnEffect ese ; +#line 2854 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vPoint ; +#line 2855 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATplane3D vPlaneNormal ; +#line 2856 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDistanceToEdge ; +#line 2858 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATaabbox3D box ; +#line 2859 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetBoundingBox (box ); +#line 2862 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )){ +#line 2864 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 0.5f +#line 2865 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +&& (m_vLastStain - vPoint ) . Length () > 1.0f){ +#line 2866 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_vLastStain = vPoint ; +#line 2867 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fStretch = box . Size () . Length (); +#line 2868 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 2870 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bGrow ){ +#line 2871 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ese . betType = BET_BLOODSTAINGROW ; +#line 2872 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ese . vStretch = FLOAT3D (fStretch * 1.5f , fStretch * 1.5f , 1.0f); +#line 2873 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 2874 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ese . betType = BET_BLOODSTAIN ; +#line 2875 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ese . vStretch = FLOAT3D (fStretch * 0.75f , fStretch * 0.75f , 1.0f); +#line 2876 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2877 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 2878 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ese . vDirection = FLOAT3D (0 , 0 , 0); +#line 2879 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vPos = vPoint + ese . vNormal / 50.0f * (FRnd () + 0.5f); +#line 2880 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntityPointer penEffect = CreateEntity (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0)) , CLASS_BASIC_EFFECT ); +#line 2881 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penEffect -> Initialize (ese ); +#line 2882 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2883 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2884 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 2887 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::DamageImpact(enum DamageType dmtType, +#line 2888 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 2889 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2891 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetRenderType () != RT_MODEL ){ +#line 2893 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 2894 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2896 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(dmtType == DMT_ABYSS || dmtType == DMT_SPIKESTAB ){ +#line 2897 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 2898 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2900 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fDamageAmmount = Clamp (fDamageAmmount , 0.0f , 5000.0f); +#line 2902 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fKickDamage = fDamageAmmount ; +#line 2903 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((dmtType == DMT_EXPLOSION ) || (dmtType == DMT_IMPACT ) || (dmtType == DMT_CANNONBALL_EXPLOSION )) +#line 2904 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2905 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fKickDamage *= 1.5; +#line 2906 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2907 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(dmtType == DMT_DROWNING || dmtType == DMT_CLOSERANGE ){ +#line 2908 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fKickDamage /= 10; +#line 2909 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2910 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(dmtType == DMT_CHAINSAW ) +#line 2911 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2912 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fKickDamage /= 10; +#line 2913 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2916 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 2917 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME tmDelta = tmNow - m_tmLastDamage ; +#line 2918 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmLastDamage = tmNow ; +#line 2921 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmDelta >= _pTimer -> TickQuantum * 3){ +#line 2922 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_vDamage = FLOAT3D (0 , 0 , 0); +#line 2923 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2925 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vDirectionFixed ; +#line 2926 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(vDirection . ManhattanNorm () > 0.5f){ +#line 2927 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vDirectionFixed = vDirection ; +#line 2928 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 2929 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vDirectionFixed = - en_vGravityDir ; +#line 2930 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2931 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vDamageOld = m_vDamage ; +#line 2932 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_vDamage += (vDirectionFixed ) * fKickDamage ; +#line 2934 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fOldLen = vDamageOld . Length (); +#line 2935 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fNewLen = m_vDamage . Length (); +#line 2936 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fOldRootLen = Sqrt (fOldLen ); +#line 2937 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fNewRootLen = Sqrt (fNewLen ); +#line 2939 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fMassFactor = 200.0f / ((EntityInfo *) GetEntityInfo ()) -> fMass ; +#line 2941 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (en_ulFlags & ENF_ALIVE )) +#line 2942 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2943 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fMassFactor /= 3; +#line 2944 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2946 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +switch(dmtType ) +#line 2947 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2948 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case DMT_CLOSERANGE : +#line 2949 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case DMT_CHAINSAW : +#line 2950 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case DMT_DROWNING : +#line 2951 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case DMT_IMPACT : +#line 2952 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case DMT_BRUSH : +#line 2953 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case DMT_BURNING : +#line 2955 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 2956 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +default : +#line 2957 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2958 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fOldLen != 0.0f) +#line 2959 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2961 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GiveImpulseTranslationAbsolute (- vDamageOld / fOldRootLen * fMassFactor ); +#line 2962 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2970 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GiveImpulseTranslationAbsolute (m_vDamage / fNewRootLen * fMassFactor ); +#line 2971 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2972 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2974 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_fMaxDamageAmmount < fDamageAmmount ) +#line 2975 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2976 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fMaxDamageAmmount = fDamageAmmount ; +#line 2977 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2979 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((m_tmSpraySpawned <= _pTimer -> CurrentTick () - _pTimer -> TickQuantum * 8 || +#line 2980 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fSprayDamage + fDamageAmmount > 50.0f)){ +#line 2983 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plSpray = CPlacement3D (vHitPoint , ANGLE3D (0 , 0 , 0)); +#line 2984 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 2985 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penSpray -> SetParent (this ); +#line 2986 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESpawnSpray eSpawnSpray ; +#line 2987 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 2989 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_fMaxDamageAmmount > 10.0f) +#line 2990 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2991 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSpawnSpray . fDamagePower = 3.0f; +#line 2992 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2993 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(m_fSprayDamage + fDamageAmmount > 50.0f) +#line 2994 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2995 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSpawnSpray . fDamagePower = 2.0f; +#line 2996 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 2997 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else +#line 2998 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 2999 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSpawnSpray . fDamagePower = 1.0f; +#line 3000 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3002 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSpawnSpray . sptType = SPT_BLOOD ; +#line 3003 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSpawnSpray . fSizeMultiplier = 1.0f; +#line 3006 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vHitPointRelative = vHitPoint - GetPlacement () . pl_PositionVector ; +#line 3007 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vReflectingNormal ; +#line 3008 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetNormalComponent (vHitPointRelative , en_vGravityDir , vReflectingNormal ); +#line 3009 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vReflectingNormal . Normalize (); +#line 3011 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vReflectingNormal (1) /= 5.0f; +#line 3013 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vProjectedComponent = vReflectingNormal * (vDirection % vReflectingNormal ); +#line 3014 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vSpilDirection = vDirection - vProjectedComponent * 2.0f - en_vGravityDir * 0.5f; +#line 3016 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSpawnSpray . vDirection = vSpilDirection ; +#line 3017 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSpawnSpray . penOwner = this ; +#line 3020 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penSpray -> Initialize (eSpawnSpray ); +#line 3021 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmSpraySpawned = _pTimer -> CurrentTick (); +#line 3022 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fSprayDamage = 0.0f; +#line 3023 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fMaxDamageAmmount = 0.0f; +#line 3024 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3025 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fSprayDamage += fDamageAmmount ; +#line 3026 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3030 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 3031 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 3032 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3034 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penInflictor == this && (dmtType == DMT_CLOSERANGE || dmtType == DMT_CHAINSAW || +#line 3035 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((dmtType == DMT_EXPLOSION || dmtType == DMT_CANNONBALL_EXPLOSION || dmtType == DMT_PROJECTILE ) && +#line 3036 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetSP () -> sp_gdGameDifficulty <= CSessionProperties :: GD_EASY ))){ +#line 3037 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 3038 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3041 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulFlags & PLF_NOTCONNECTED ){ +#line 3043 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 3044 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3047 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_bGod && CheatsEnabled ()){return ;} +#line 3050 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const TIME tmDelta = m_tmInvulnerability - _pTimer -> CurrentTick (); +#line 3051 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmDelta > 0 && dmtType != DMT_ABYSS && dmtType != DMT_TELEPORT ){return ;} +#line 3054 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT tmSpawnInvulnerability = GetSP () -> sp_tmSpawnInvulnerability ; +#line 3055 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmSpawnInvulnerability > 0 && _pTimer -> CurrentTick () - m_tmSpawned < tmSpawnInvulnerability ){ +#line 3057 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 3058 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3061 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! GetSP () -> sp_bFriendlyFire && GetSP () -> sp_bCooperative ){ +#line 3062 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsOfClass (penInflictor , "Player") && penInflictor != this ){ +#line 3063 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 3064 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3065 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3068 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(dmtType == DMT_HEAT && ! (GetFlags () & ENF_ALIVE )){ +#line 3069 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 3070 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3073 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDifficultyDamage = GetSP () -> sp_fDamageStrength ; +#line 3074 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fDifficultyDamage <= 1.0f || penInflictor != this ){ +#line 3075 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fDamageAmmount *= fDifficultyDamage ; +#line 3076 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3079 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fDamageAmmount <= 0){ +#line 3080 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 3081 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3083 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fSubHealth , fSubArmor ; +#line 3084 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(dmtType == DMT_DROWNING ){ +#line 3086 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fSubHealth = fDamageAmmount ; +#line 3087 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3088 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else { +#line 3090 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fSubArmor = fDamageAmmount * 2.0f / 3.0f; +#line 3091 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fSubHealth = fDamageAmmount - fSubArmor ; +#line 3092 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fArmor -= fSubArmor ; +#line 3093 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_fArmor < 0){ +#line 3094 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fSubHealth -= m_fArmor ; +#line 3095 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fArmor = 0.0f; +#line 3096 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3097 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3100 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fSubHealth > 0){ +#line 3102 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penCamera != NULL ){ +#line 3104 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * penOnBreak = ((CCamera &) * m_penCamera ) . m_penOnBreak ; +#line 3105 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penOnBreak != NULL ){ +#line 3107 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendToTarget (penOnBreak , EET_TRIGGER , this ); +#line 3109 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 3111 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penCamera = NULL ; +#line 3112 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3113 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3115 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3118 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penActionMarker != NULL ){ +#line 3120 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 3121 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3123 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +DamageImpact (dmtType , fSubHealth , vHitPoint , vDirection ); +#line 3126 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerEntity :: ReceiveDamage (penInflictor , dmtType , fSubHealth , vHitPoint , vDirection ); +#line 3129 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fDamageAmmount > 1.0f){ +#line 3131 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(dmtType == DMT_EXPLOSION || dmtType == DMT_PROJECTILE || dmtType == DMT_BULLET +#line 3132 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +|| dmtType == DMT_IMPACT || dmtType == DMT_CANNONBALL || dmtType == DMT_CANNONBALL_EXPLOSION ){ +#line 3135 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3136 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetFlags () & ENF_ALIVE ){ +#line 3137 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fDamageAmmount += fDamageAmmount ; +#line 3138 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmWoundedTime = _pTimer -> CurrentTick (); +#line 3139 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3140 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3143 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESound eSound ; +#line 3144 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSound . EsndtSound = SNDT_PLAYER ; +#line 3145 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSound . penTarget = this ; +#line 3146 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendEventInRange (eSound , FLOATaabbox3D (GetPlacement () . pl_PositionVector , 10.0f)); +#line 3149 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(dmtType == DMT_DROWNING ){ +#line 3150 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetRandomMouthPitch (0.9f , 1.1f); +#line 3151 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMouth , GenderSound (SOUND_DROWN ) , SOF_3D ); +#line 3152 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_PlayEffect ("WoundWater");} +#line 3153 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMouthSoundLast = _pTimer -> CurrentTick (); +#line 3154 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soLocalAmbientOnce , SOUND_WATERBUBBLES , SOF_3D | SOF_VOLUMETRIC | SOF_LOCAL ); +#line 3155 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soLocalAmbientOnce . Set3DParameters (25.0f , 5.0f , 2.0f , Lerp (0.5f , 1.5f , FRnd ())); +#line 3156 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SpawnBubbles (10 + INDEX (FRnd () * 10)); +#line 3157 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_fDamageAmmount > 1.0f){ +#line 3159 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetFlags () & ENF_ALIVE ){ +#line 3161 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iSound ; +#line 3162 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +char * strIFeel = NULL ; +#line 3163 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_fDamageAmmount < 5.0f){ +#line 3164 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSound = GenderSound (SOUND_WOUNDWEAK ); +#line 3165 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strIFeel = "WoundWeak"; +#line 3166 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3167 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(m_fDamageAmmount < 25.0f){ +#line 3168 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSound = GenderSound (SOUND_WOUNDMEDIUM ); +#line 3169 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strIFeel = "WoundMedium"; +#line 3170 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3171 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else { +#line 3172 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSound = GenderSound (SOUND_WOUNDSTRONG ); +#line 3173 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strIFeel = "WoundStrong"; +#line 3174 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3175 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_DIVE ){ +#line 3176 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSound = GenderSound (SOUND_WOUNDWATER ); +#line 3177 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strIFeel = "WoundWater"; +#line 3178 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3179 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetRandomMouthPitch (0.9f , 1.1f); +#line 3181 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 3182 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((tmNow - m_tmScreamTime ) > 1.0f){ +#line 3183 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmScreamTime = tmNow ; +#line 3184 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMouth , iSound , SOF_3D ); +#line 3185 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_PlayEffect (strIFeel );} +#line 3186 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3187 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3188 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3189 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3192 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL CPlayer::ShouldBlowUp(void) +#line 3193 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3195 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return +#line 3197 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetSP () -> sp_bGibs && +#line 3199 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(GetHealth () <= 0) && +#line 3201 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(m_vDamage . Length () > _fBlowUpAmmount ) && +#line 3203 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetRenderType () == RT_MODEL ; +#line 3204 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3207 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::BlowUp(void) +#line 3208 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3209 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vNormalizedDamage = m_vDamage - m_vDamage * (_fBlowUpAmmount / m_vDamage . Length ()); +#line 3210 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vNormalizedDamage /= Sqrt (vNormalizedDamage . Length ()); +#line 3211 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vNormalizedDamage *= 0.75f; +#line 3213 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute - en_vGravityDir * (en_vGravityDir % en_vCurrentTranslationAbsolute ); +#line 3214 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const FLOAT fBlowUpSize = 2.0f; +#line 3217 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const INDEX iBloodType = GetSP () -> sp_iBlood ; +#line 3219 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ULONG ulFleshTexture = TEXTURE_FLESH_GREEN ; +#line 3220 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ULONG ulFleshModel = MODEL_FLESH ; +#line 3221 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iBloodType == 2){ulFleshTexture = TEXTURE_FLESH_RED ;} +#line 3223 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Debris_Begin (EIBT_FLESH , DPT_BLOODTRAIL , BET_BLOODSTAIN , fBlowUpSize , vNormalizedDamage , vBodySpeed , 1.0f , 0.0f); +#line 3224 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iDebris = 0;iDebris < 4;iDebris ++){ +#line 3226 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iBloodType == 3){ +#line 3227 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +switch(IRnd () % 5){ +#line 3228 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 1: {ulFleshModel = MODEL_FLESH_APPLE ;ulFleshTexture = TEXTURE_FLESH_APPLE ;break ;} +#line 3229 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 2: {ulFleshModel = MODEL_FLESH_BANANA ;ulFleshTexture = TEXTURE_FLESH_BANANA ;break ;} +#line 3230 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 3: {ulFleshModel = MODEL_FLESH_BURGER ;ulFleshTexture = TEXTURE_FLESH_BURGER ;break ;} +#line 3231 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 4: {ulFleshModel = MODEL_FLESH_LOLLY ;ulFleshTexture = TEXTURE_FLESH_LOLLY ;break ;} +#line 3232 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +default :{ulFleshModel = MODEL_FLESH_ORANGE ;ulFleshTexture = TEXTURE_FLESH_ORANGE ;break ;} +#line 3233 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3234 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3235 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Debris_Spawn (this , this , ulFleshModel , ulFleshTexture , 0 , 0 , 0 , IRnd () % 4 , 0.5f , +#line 3236 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D (FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f , FRnd () * 0.6f + 0.2f)); +#line 3237 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3240 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +LeaveStain (FALSE ); +#line 3242 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soBody , SOUND_BLOWUP , SOF_3D ); +#line 3245 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SwitchToEditorModel (); +#line 3247 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fSpeedOrg = en_vCurrentTranslationAbsolute . Length (); +#line 3248 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const FLOAT fSpeedMax = 30.0f; +#line 3249 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fSpeedOrg > fSpeedMax ){ +#line 3250 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_vCurrentTranslationAbsolute *= fSpeedMax / fSpeedOrg ; +#line 3251 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3255 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3261 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void * CPlayer::GetEntityInfo(void) +#line 3262 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3263 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +switch(m_pstState ){ +#line 3264 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PST_STAND : case PST_FALL : +#line 3265 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return & eiPlayerGround ; +#line 3266 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 3267 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PST_CROUCH : +#line 3268 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return & eiPlayerCrouch ; +#line 3269 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 3270 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PST_SWIM : case PST_DIVE : +#line 3271 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return & eiPlayerSwim ; +#line 3272 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 3273 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3274 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return & eiPlayerGround ; +#line 3275 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3279 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL CPlayer::ReceiveItem(const CEntityEvent & ee) +#line 3280 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3282 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ee . ee_slEvent == EVENTCODE_EHealth ) +#line 3283 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3285 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fHealthOld = GetHealth (); +#line 3286 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fHealthNew = fHealthOld + ((EHealth &) ee ) . fHealth ; +#line 3287 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((EHealth &) ee ) . bOverTopHealth ){ +#line 3288 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fHealthNew = ClampUp (fHealthNew , MaxHealth ()); +#line 3289 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 3290 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fHealthNew = ClampUp (fHealthNew , TopHealth ()); +#line 3291 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3294 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ceil (fHealthNew ) > ceil (fHealthOld )){ +#line 3296 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetHealth (fHealthNew ); +#line 3297 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ItemPicked (TRANS ("Health") , ((EHealth &) ee ) . fHealth ); +#line 3298 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iMana += (INDEX) (((EHealth &) ee ) . fHealth ); +#line 3299 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fPickedMana += ((EHealth &) ee ) . fHealth ; +#line 3300 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE ; +#line 3301 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3302 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3305 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(ee . ee_slEvent == EVENTCODE_EArmor ) +#line 3306 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3308 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fArmorOld = m_fArmor ; +#line 3309 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fArmorNew = fArmorOld + ((EArmor &) ee ) . fArmor ; +#line 3310 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((EArmor &) ee ) . bOverTopArmor ){ +#line 3311 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fArmorNew = ClampUp (fArmorNew , MaxArmor ()); +#line 3312 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 3313 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fArmorNew = ClampUp (fArmorNew , TopArmor ()); +#line 3314 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3316 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ceil (fArmorNew ) > ceil (fArmorOld )){ +#line 3318 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fArmor = fArmorNew ; +#line 3319 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ItemPicked (TRANS ("Armor") , ((EArmor &) ee ) . fArmor ); +#line 3320 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iMana += (INDEX) (((EArmor &) ee ) . fArmor ); +#line 3321 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fPickedMana += ((EArmor &) ee ) . fArmor ; +#line 3322 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE ; +#line 3323 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3324 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3327 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(ee . ee_slEvent == EVENTCODE_EMessageItem ){ +#line 3328 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +EMessageItem & eMI = (EMessageItem &) ee ; +#line 3329 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ReceiveComputerMessage (eMI . fnmMessage , CMF_ANALYZE ); +#line 3330 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ItemPicked (TRANS ("Ancient papyrus") , 0); +#line 3331 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE ; +#line 3332 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3335 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(ee . ee_slEvent == EVENTCODE_EWeaponItem ){ +#line 3336 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ((CPlayerWeapons &) * m_penWeapons ) . ReceiveWeapon (ee ); +#line 3337 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3340 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(ee . ee_slEvent == EVENTCODE_EAmmoItem ){ +#line 3341 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ((CPlayerWeapons &) * m_penWeapons ) . ReceiveAmmo (ee ); +#line 3342 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3344 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(ee . ee_slEvent == EVENTCODE_EAmmoPackItem ){ +#line 3345 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ((CPlayerWeapons &) * m_penWeapons ) . ReceivePackAmmo (ee ); +#line 3346 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3349 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(ee . ee_slEvent == EVENTCODE_EKey ){ +#line 3351 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penActionMarker != NULL ){ +#line 3352 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return FALSE ; +#line 3353 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3355 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ULONG ulKey = 1 << INDEX (((EKey &) ee ) . kitType ); +#line 3356 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +EKey & eKey = (EKey &) ee ; +#line 3357 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(eKey . kitType == KIT_HAWKWINGS01DUMMY || eKey . kitType == KIT_HAWKWINGS02DUMMY +#line 3358 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +|| eKey . kitType == KIT_TABLESDUMMY || eKey . kitType == KIT_JAGUARGOLDDUMMY ) +#line 3359 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3360 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ulKey = 0; +#line 3361 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3363 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulKeys & ulKey ){ +#line 3365 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return FALSE ; +#line 3367 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 3369 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulKeys |= ulKey ; +#line 3370 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strKey = GetKeyName (((EKey &) ee ) . kitType ); +#line 3371 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ItemPicked (strKey , 0); +#line 3373 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bCooperative && ! GetSP () -> sp_bSinglePlayer ){ +#line 3374 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS ("^cFFFFFF%s - %s^r\n") , GetPlayerName () , strKey ); +#line 3375 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3376 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE ; +#line 3377 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3378 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3381 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(ee . ee_slEvent == EVENTCODE_EPowerUp ){ +#line 3382 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const FLOAT tmNow = _pTimer -> CurrentTick (); +#line 3383 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +switch(((EPowerUp &) ee ) . puitType ){ +#line 3384 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PUIT_INVISIB : m_tmInvisibility = tmNow + m_tmInvisibilityMax ; +#line 3385 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ItemPicked (TRANS ("^cABE3FFInvisibility") , 0); +#line 3386 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE ; +#line 3387 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PUIT_INVULNER : m_tmInvulnerability = tmNow + m_tmInvulnerabilityMax ; +#line 3388 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ItemPicked (TRANS ("^c00B440Invulnerability") , 0); +#line 3389 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE ; +#line 3390 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PUIT_DAMAGE : m_tmSeriousDamage = tmNow + m_tmSeriousDamageMax ; +#line 3391 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ItemPicked (TRANS ("^cFF0000Serious Damage!") , 0); +#line 3392 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE ; +#line 3393 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PUIT_SPEED : m_tmSeriousSpeed = tmNow + m_tmSeriousSpeedMax ; +#line 3394 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ItemPicked (TRANS ("^cFF9400Serious Speed") , 0); +#line 3395 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE ; +#line 3396 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PUIT_BOMB : +#line 3397 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iSeriousBombCount ++; +#line 3398 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ItemPicked (TRANS ("^cFF0000Serious Bomb!") , 0); +#line 3401 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bCooperative ){ +#line 3402 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +EComputerMessage eMsg ; +#line 3403 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eMsg . fnmMessage = CTFILENAME ("DataMP\\Messages\\Weapons\\seriousbomb.txt"); +#line 3404 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +this -> SendEvent (eMsg ); +#line 3405 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3406 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE ; +#line 3407 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3408 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3411 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return FALSE ; +#line 3412 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3417 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ChangePlayerView() +#line 3418 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3420 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_iViewState == PVT_PLAYEREYES ){ +#line 3422 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (m_pen3rdPersonView == NULL ); +#line 3423 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pen3rdPersonView == NULL ){ +#line 3424 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pen3rdPersonView = CreateEntity (GetPlacement () , CLASS_PLAYER_VIEW ); +#line 3425 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +EViewInit eInit ; +#line 3426 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eInit . penOwner = this ; +#line 3427 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eInit . penCamera = NULL ; +#line 3428 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eInit . vtView = VT_3RDPERSONVIEW ; +#line 3429 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eInit . bDeathFixed = FALSE ; +#line 3430 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pen3rdPersonView -> Initialize (eInit ); +#line 3431 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3433 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iViewState = PVT_3RDPERSONVIEW ; +#line 3436 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_iViewState == PVT_3RDPERSONVIEW ){ +#line 3437 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iViewState = PVT_PLAYEREYES ; +#line 3440 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pen3rdPersonView != NULL ){ +#line 3441 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerView &) * m_pen3rdPersonView ) . SendEvent (EEnd ()); +#line 3442 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pen3rdPersonView = NULL ; +#line 3443 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3444 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3445 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3448 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ComputerPressed(void) +#line 3449 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3452 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cmp_ppenPlayer == NULL && _pNetwork -> IsPlayerLocal (this )){ +#line 3453 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cmp_ppenPlayer = this ; +#line 3454 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3455 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bComputerInvoked = TRUE ; +#line 3457 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmAnalyseEnd = 0; +#line 3458 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bPendingMessage = FALSE ; +#line 3459 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMessagePlay = 0; +#line 3461 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3465 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::UsePressed(BOOL bOrComputer) +#line 3466 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3468 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerWeapons * penWeapons = GetPlayerWeapons (); +#line 3469 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * pen = penWeapons -> m_penRayHit ; +#line 3470 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bSomethingToUse = FALSE ; +#line 3473 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pen != NULL ){ +#line 3475 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsOfClass (pen , "Moving Brush")){ +#line 3476 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((CMovingBrush &) * pen ) . m_penSwitch != NULL ){ +#line 3477 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pen = ((CMovingBrush &) * pen ) . m_penSwitch ; +#line 3478 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3479 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3482 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsOfClass (pen , "Switch") && penWeapons -> m_fRayHitDistance < 2.0f){ +#line 3483 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CSwitch & enSwitch = (CSwitch &) * pen ; +#line 3485 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(enSwitch . m_bUseable ){ +#line 3487 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendToTarget (pen , EET_TRIGGER , this ); +#line 3488 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bSomethingToUse = TRUE ; +#line 3489 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3490 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3493 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsOfClass (pen , "MessageHolder") +#line 3494 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +&& penWeapons -> m_fRayHitDistance < ((CMessageHolder *) & * pen ) -> m_fDistance +#line 3495 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +&& ((CMessageHolder *) & * pen ) -> m_bActive ){ +#line 3496 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const CTFileName & fnmMessage = ((CMessageHolder *) & * pen ) -> m_fnmMessage ; +#line 3498 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! HasMessage (fnmMessage )){ +#line 3500 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ReceiveComputerMessage (fnmMessage , CMF_ANALYZE ); +#line 3501 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bSomethingToUse = TRUE ; +#line 3502 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3503 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3504 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3506 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! bSomethingToUse && bOrComputer ){ +#line 3508 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ComputerPressed (); +#line 3509 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3510 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(! bSomethingToUse ) +#line 3511 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3512 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerWeapons * penWeapon = GetPlayerWeapons (); +#line 3516 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penWeapon -> m_iCurrentWeapon == WEAPON_SNIPER && +#line 3517 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_iWantedWeapon == WEAPON_SNIPER ){ +#line 3518 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulFlags & PLF_ISZOOMING ){ +#line 3519 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_ISZOOMING ; +#line 3520 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_bSniping = FALSE ; +#line 3521 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_fSniperFOVlast = penWeapon -> m_fSniperFOV = penWeapon -> m_fSniperMaxFOV ; +#line 3522 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soSniperZoom , SOUND_SILENCE , SOF_3D ); +#line 3523 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_StopEffect ("SniperZoom");} +#line 3524 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3525 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else { +#line 3526 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_bSniping = TRUE ; +#line 3527 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_ISZOOMING ; +#line 3528 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_fSniperFOVlast = penWeapon -> m_fSniperFOV = penWeapon -> m_fMinimumZoomFOV ; +#line 3529 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soSniperZoom , SOUND_SNIPER_ZOOM , SOF_3D | SOF_LOOP ); +#line 3530 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_PlayEffect ("SniperZoom");} +#line 3531 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3532 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3533 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3534 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3540 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SetGameEnd(void) +#line 3541 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3542 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pNetwork -> SetGameFinished (); +#line 3544 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iPlayer = 0;iPlayer < GetMaxPlayers ();iPlayer ++){ +#line 3545 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * pen = GetPlayerEntity (iPlayer ); +#line 3546 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pen != NULL ){ +#line 3547 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cmp_ppenPlayer == NULL && _pNetwork -> IsPlayerLocal (pen )){ +#line 3548 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cmp_ppenPlayer = (CPlayer *) pen ; +#line 3549 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3550 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3551 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3552 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3554 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::CheckGameEnd(void) +#line 3555 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3556 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bFinished = FALSE ; +#line 3558 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iTimeLimit = GetSP () -> sp_iTimeLimit ; +#line 3559 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iTimeLimit > 0 && _pTimer -> CurrentTick () >= iTimeLimit * 60.0f){ +#line 3560 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bFinished = TRUE ; +#line 3561 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3563 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iFragLimit = GetSP () -> sp_iFragLimit ; +#line 3564 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iFragLimit > 0 && m_psLevelStats . ps_iKills >= iFragLimit ){ +#line 3565 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bFinished = TRUE ; +#line 3566 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3568 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iScoreLimit = GetSP () -> sp_iScoreLimit ; +#line 3569 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iScoreLimit > 0 && m_psLevelStats . ps_iScore >= iScoreLimit ){ +#line 3570 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bFinished = TRUE ; +#line 3571 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3573 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bFinished ){ +#line 3574 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetGameEnd (); +#line 3575 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3576 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3579 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::PreapplyAction(const CPlayerAction & paAction) +#line 3580 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3581 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3584 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ApplyAction(const CPlayerAction & paOriginal,FLOAT tmLatency) +#line 3585 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3586 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (m_ulFlags & PLF_INITIALIZED )){return ;} +#line 3590 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulFlags & PLF_NOTCONNECTED ){ +#line 3592 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetConnected (); +#line 3593 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3595 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_APPLIEDACTION ; +#line 3598 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAction paAction = paOriginal ; +#line 3603 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ANGLE3D aDeltaRotation = paAction . pa_aRotation - m_aLastRotation ; +#line 3604 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ANGLE3D aDeltaViewRotation = paAction . pa_aViewRotation - m_aLastViewRotation ; +#line 3606 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulFlags & PLF_ISZOOMING ){ +#line 3607 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fRotationDamping = ((CPlayerWeapons &) * m_penWeapons ) . m_fSniperFOV / ((CPlayerWeapons &) * m_penWeapons ) . m_fSniperMaxFOV ; +#line 3608 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aDeltaRotation *= fRotationDamping ; +#line 3609 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aDeltaViewRotation *= fRotationDamping ; +#line 3610 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3612 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_aLastRotation = paAction . pa_aRotation ; +#line 3613 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_aLastViewRotation = paAction . pa_aViewRotation ; +#line 3615 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_aRotation = aDeltaRotation ; +#line 3616 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_aViewRotation = aDeltaViewRotation ; +#line 3620 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_aRotation /= _pTimer -> TickQuantum ; +#line 3621 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_aViewRotation /= _pTimer -> TickQuantum ; +#line 3624 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * penMe = this ; +#line 3625 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsPredictor ()){ +#line 3626 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penMe = penMe -> GetPredicted (); +#line 3627 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3628 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPredictable (! _pNetwork -> IsPlayerLocal (penMe )); +#line 3631 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! IsPredictor ()){ +#line 3632 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheckGameEnd (); +#line 3633 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3636 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_vTranslation (1) = Clamp (paAction . pa_vTranslation (1) , - plr_fSpeedSide , plr_fSpeedSide ); +#line 3637 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_vTranslation (2) = Clamp (paAction . pa_vTranslation (2) , - plr_fSpeedUp , plr_fSpeedUp ); +#line 3638 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_vTranslation (3) = Clamp (paAction . pa_vTranslation (3) , - plr_fSpeedForward , plr_fSpeedBackward ); +#line 3641 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(Abs (paAction . pa_vTranslation (3)) < plr_fSpeedForward / 1.99f +#line 3642 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +&& Abs (paAction . pa_vTranslation (1)) < plr_fSpeedSide / 1.99f){ +#line 3644 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_fStepDnHeight = 1.5f; +#line 3647 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 3649 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_fStepDnHeight = - 1; +#line 3650 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3653 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D & v = paAction . pa_vTranslation ; +#line 3654 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDiag = Sqrt (v (1) * v (1) + v (3) * v (3)); +#line 3655 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fDiag > 0.01f){ +#line 3656 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDiagLimited = Min (fDiag , plr_fSpeedForward ); +#line 3657 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fFactor = fDiagLimited / fDiag ; +#line 3658 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +v (1) *= fFactor ; +#line 3659 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +v (3) *= fFactor ; +#line 3660 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3662 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ulButtonsNow = paAction . pa_ulButtons ; +#line 3663 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ulButtonsBefore = m_ulLastButtons ; +#line 3664 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ulNewButtons = ulButtonsNow & ~ ulButtonsBefore ; +#line 3665 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ulReleasedButtons = (~ ulButtonsNow ) & (ulButtonsBefore ); +#line 3667 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulLastButtons = ulButtonsNow ; +#line 3668 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plLastViewpoint = en_plViewpoint ; +#line 3671 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerWeapons * penWeapon = GetPlayerWeapons (); +#line 3672 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penWeapon -> m_iCurrentWeapon == WEAPON_SNIPER ) +#line 3673 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3674 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bUseButtonHeld && m_ulFlags & PLF_ISZOOMING ) +#line 3675 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3676 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_fSniperFOVlast = penWeapon -> m_fSniperFOV ; +#line 3677 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_fSniperFOV -= penWeapon -> m_fSnipingZoomSpeed ; +#line 3678 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penWeapon -> m_fSniperFOV < penWeapon -> m_fSniperMinFOV ) +#line 3679 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3680 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_fSniperFOVlast = penWeapon -> m_fSniperFOV = penWeapon -> m_fSniperMinFOV ; +#line 3681 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soSniperZoom , SOUND_SILENCE , SOF_3D ); +#line 3682 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_StopEffect ("SniperZoom");} +#line 3683 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3684 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3685 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulReleasedButtons & PLACT_USE_HELD ) +#line 3686 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3687 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_fSniperFOVlast = penWeapon -> m_fSniperFOV ; +#line 3688 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soSniperZoom , SOUND_SILENCE , SOF_3D ); +#line 3689 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_StopEffect ("SniperZoom");} +#line 3690 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3691 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3694 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetFlags () & ENF_ALIVE ){ +#line 3696 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penActionMarker == NULL ){ +#line 3698 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AliveActions (paAction ); +#line 3700 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 3702 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoActions (paAction ); +#line 3703 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3705 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 3706 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +DeathActions (paAction ); +#line 3707 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3709 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(Abs (_pTimer -> CurrentTick () - m_tmAnalyseEnd ) < _pTimer -> TickQuantum * 2){ +#line 3710 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmAnalyseEnd = 0; +#line 3711 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bPendingMessage = TRUE ; +#line 3712 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMessagePlay = 0; +#line 3713 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3714 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_bPendingMessage && ! IsFuss ()){ +#line 3715 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bPendingMessage = FALSE ; +#line 3716 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMessagePlay = _pTimer -> CurrentTick () + 1.0f; +#line 3717 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmAnimateInbox = _pTimer -> CurrentTick (); +#line 3718 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3719 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(Abs (_pTimer -> CurrentTick () - m_tmMessagePlay ) < _pTimer -> TickQuantum * 2){ +#line 3720 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bPendingMessage = FALSE ; +#line 3721 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmAnalyseEnd = 0; +#line 3723 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! m_bComputerInvoked && GetSP () -> sp_bSinglePlayer ){ +#line 3724 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PrintCenterMessage (this , this , +#line 3725 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TRANS ("Press USE to read the message!") , 5.0f , MSS_NONE ); +#line 3726 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3727 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3730 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(CheatsEnabled ()){ +#line 3731 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Cheats (); +#line 3732 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3735 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_iGoToMarker > 0 && (GetFlags () & ENF_ALIVE )){ +#line 3737 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iLastViewState = m_iViewState ; +#line 3738 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendEvent (ERebirth ()); +#line 3739 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3742 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UpdateLatency (tmLatency ); +#line 3745 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheckHighScore (); +#line 3746 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3750 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::Disconnect(void) +#line 3751 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3753 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_strName = GetPlayerName (); +#line 3755 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_pcCharacter = CPlayerCharacter (); +#line 3757 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendEvent (EDisconnected ()); +#line 3758 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3761 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::CharacterChanged(const CPlayerCharacter & pcNew) +#line 3762 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3764 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerCharacter pcOrg = en_pcCharacter ; +#line 3767 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_pcCharacter = pcNew ; +#line 3768 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ValidateCharacter (); +#line 3771 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pcOrg . GetName () != pcNew . GetName ()){ +#line 3773 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS ("%s is now known as %s\n") , +#line 3774 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pcOrg . GetNameForPrinting () , pcNew . GetNameForPrinting ()); +#line 3775 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3778 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pcOrg . GetTeam () != pcNew . GetTeam ()){ +#line 3780 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS ("%s switched to team %s\n") , +#line 3781 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pcNew . GetNameForPrinting () , pcNew . GetTeamForPrinting ()); +#line 3782 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3785 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerSettings * ppsOrg = (CPlayerSettings *) pcOrg . pc_aubAppearance ; +#line 3786 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerSettings * ppsNew = (CPlayerSettings *) pcNew . pc_aubAppearance ; +#line 3787 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(memcmp (ppsOrg -> ps_achModelFile , ppsNew -> ps_achModelFile , sizeof (ppsOrg -> ps_achModelFile )) != 0){ +#line 3789 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strNewLook ; +#line 3790 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bSuccess = SetPlayerAppearance (& m_moRender , & en_pcCharacter , strNewLook , FALSE ); +#line 3792 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bSuccess ){ +#line 3793 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ParseGender (strNewLook ); +#line 3795 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS ("%s now appears as %s\n") , +#line 3796 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pcNew . GetNameForPrinting () , strNewLook ); +#line 3798 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 3800 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS ("Cannot change appearance for %s: setting '%s' is unavailable\n") , +#line 3801 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pcNew . GetNameForPrinting () , (const char *) ppsNew -> GetModelFilename ()); +#line 3802 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3804 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerAnimator () -> SyncWeapon (); +#line 3805 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3807 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL b3RDPersonOld = ppsOrg -> ps_ulFlags & PSF_PREFER3RDPERSON ; +#line 3808 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL b3RDPersonNew = ppsNew -> ps_ulFlags & PSF_PREFER3RDPERSON ; +#line 3809 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((b3RDPersonOld && ! b3RDPersonNew && m_iViewState == PVT_3RDPERSONVIEW ) +#line 3810 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +|| (b3RDPersonNew && ! b3RDPersonOld && m_iViewState == PVT_PLAYEREYES )){ +#line 3811 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ChangePlayerView (); +#line 3812 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3813 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3817 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::AliveActions(const CPlayerAction & pa) +#line 3818 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3819 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAction paAction = pa ; +#line 3822 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penCamera != NULL ){ +#line 3824 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_vTranslation = FLOAT3D (0 , 0 , 0); +#line 3825 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_aRotation = ANGLE3D (0 , 0 , 0); +#line 3826 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_aViewRotation = ANGLE3D (0 , 0 , 0); +#line 3828 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & (PLACT_FIRE | PLACT_USE )){ +#line 3830 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penCamera = NULL ; +#line 3831 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3832 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 3833 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ButtonsActions (paAction ); +#line 3834 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3837 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ActiveActions (paAction ); +#line 3840 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT tmSinceWounding = _pTimer -> CurrentTick () - m_tmWoundedTime ; +#line 3841 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmSinceWounding < 4.0f){ +#line 3843 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fDamageAmmount *= 1.0f - tmSinceWounding / 4.0f; +#line 3844 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 3846 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fDamageAmmount = 0.0f; +#line 3847 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3848 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3851 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::AutoActions(const CPlayerAction & pa) +#line 3852 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3854 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & (PLACT_FIRE | PLACT_USE | PLACT_COMPUTER )){ +#line 3855 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penCamera != NULL ){ +#line 3856 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * penOnBreak = ((CCamera &) * m_penCamera ) . m_penOnBreak ; +#line 3857 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penOnBreak != NULL ){ +#line 3858 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendToTarget (penOnBreak , EET_TRIGGER , this ); +#line 3859 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3860 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3861 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3863 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAction paAction = pa ; +#line 3865 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_vTranslation = FLOAT3D (0 , 0 , 0); +#line 3866 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_aRotation = ANGLE3D (0 , 0 , 0); +#line 3867 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_aViewRotation = ANGLE3D (0 , 0 , 0); +#line 3870 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_fAutoSpeed > 0){ +#line 3871 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vDelta = +#line 3872 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penActionMarker -> GetPlacement () . pl_PositionVector - +#line 3873 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlacement () . pl_PositionVector ; +#line 3874 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDistance = vDelta . Length (); +#line 3875 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fDistance > 0.1f){ +#line 3876 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vDelta /= fDistance ; +#line 3877 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ANGLE aDH = GetRelativeHeading (vDelta ); +#line 3880 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fSpeed = m_fAutoSpeed ; +#line 3881 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetActionMarker () -> m_paaAction == PAA_RUNANDSTOP ){ +#line 3883 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fSpeed = Min (fSpeed , fDistance / _pTimer -> TickQuantum ); +#line 3884 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3886 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(Abs (aDH ) > 5.0f){ +#line 3887 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fSpeed > m_fAutoSpeed - 0.1f){ +#line 3888 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aDH = Clamp (aDH , - 30.0f , 30.0f); +#line 3889 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3890 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_aRotation = ANGLE3D (aDH / _pTimer -> TickQuantum , 0 , 0); +#line 3891 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3893 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_vTranslation = FLOAT3D (0 , 0 , - fSpeed ); +#line 3894 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3895 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 3896 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_vTranslation = m_vAutoSpeed ; +#line 3897 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3899 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerActionMarker * ppam = GetActionMarker (); +#line 3900 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (ppam != NULL ); +#line 3901 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ppam -> m_paaAction == PAA_LOGO_FIRE_MINIGUN || ppam -> m_paaAction == PAA_LOGO_FIRE_INTROSE ) +#line 3902 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3903 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_tmMinigunAutoFireStart != - 1) +#line 3904 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3905 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT tmDelta = _pTimer -> CurrentTick () - m_tmMinigunAutoFireStart ; +#line 3906 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT aDH = 0.0f; +#line 3907 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT aDP = 0.0f; +#line 3908 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmDelta >= 0.0f && tmDelta <= 0.75f) +#line 3909 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3910 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aDH = 0.0f; +#line 3911 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3912 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(tmDelta >= 0.75f) +#line 3913 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3914 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDT = tmDelta - 0.75f; +#line 3915 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aDH = 1.0f * cos (fDT + PI / 2.0f); +#line 3916 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aDP = 0.5f * cos (fDT ); +#line 3917 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3918 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ppam -> m_paaAction == PAA_LOGO_FIRE_INTROSE ) +#line 3919 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3920 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fRatio = CalculateRatio (tmDelta , 0.25 , 5 , 0.1f , 0.1f); +#line 3921 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aDP = 2.0f * sin (tmDelta * 200.0f) * fRatio ; +#line 3922 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmDelta > 2.5f) +#line 3923 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3924 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aDP += (tmDelta - 2.5f) * 4.0f; +#line 3925 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3926 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3927 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_aRotation = ANGLE3D (aDH / _pTimer -> TickQuantum , aDP / _pTimer -> TickQuantum , 0); +#line 3928 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3929 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3932 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (m_ulFlags & PLF_AUTOMOVEMENTS )){ +#line 3933 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ActiveActions (paAction ); +#line 3934 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3935 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3937 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::GetLerpedWeaponPosition(FLOAT3D vRel,CPlacement3D & pl) +#line 3938 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3939 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pl = CPlacement3D (vRel , ANGLE3D (0 , 0 , 0)); +#line 3940 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plView ; +#line 3941 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_bDiscard3rdView = GetViewEntity () != this ; +#line 3942 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetLerpedAbsoluteViewPlacement (plView ); +#line 3943 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pl . RelativeToAbsolute (plView ); +#line 3944 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3946 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SpawnBubbles(INDEX ctBubbles) +#line 3947 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3948 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iBouble = 0;iBouble < ctBubbles ;iBouble ++) +#line 3949 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3950 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vRndRel = FLOAT3D ((FRnd () - 0.5f) * 0.25f , - 0.25f , - 0.5f + FRnd () / 10.0f); +#line 3951 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ANGLE3D aDummy = ANGLE3D (0 , 0 , 0); +#line 3952 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plMouth = CPlacement3D (vRndRel , aDummy ); +#line 3954 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plMouth . RelativeToAbsolute (en_plViewpoint ); +#line 3955 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plMouth . RelativeToAbsolute (GetPlacement ()); +#line 3956 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vRndSpd = FLOAT3D ((FRnd () - 0.5f) * 0.25f , (FRnd () - 0.5f) * 0.25f , (FRnd () - 0.5f) * 0.25f); +#line 3957 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AddBouble (plMouth . pl_PositionVector , vRndSpd ); +#line 3958 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3959 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3961 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::PlayPowerUpSound(void) { +#line 3962 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soPowerUpBeep . Set3DParameters (50.0f , 10.0f , 4.0f , 1.0f); +#line 3963 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soPowerUpBeep , SOUND_POWERUP_BEEP , SOF_3D | SOF_VOLUMETRIC | SOF_LOCAL ); +#line 3964 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 3966 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ActiveActions(const CPlayerAction & paAction) +#line 3967 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3969 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vTranslation = paAction . pa_vTranslation ; +#line 3971 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_fTranslationMultiplier && CheatsEnabled ()){ +#line 3972 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation *= cht_fTranslationMultiplier ; +#line 3973 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3976 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((CPlayerWeapons &) * m_penWeapons ) . m_iCurrentWeapon == WEAPON_KNIFE && +#line 3977 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +! GetSP () -> sp_bCooperative ){ +#line 3978 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation *= 1.3f; +#line 3979 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3982 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const TIME tmDelta = m_tmSeriousSpeed - _pTimer -> CurrentTick (); +#line 3983 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmDelta > 0 && m_fAutoSpeed == 0.0f){ +#line 3984 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation (1) *= 2.0f; +#line 3985 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation (3) *= 2.0f; +#line 3986 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3988 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_fAcceleration = plr_fAcceleration ; +#line 3989 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_fDeceleration = plr_fDeceleration ; +#line 3990 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! GetSP () -> sp_bCooperative ) +#line 3991 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 3992 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation (1) *= 1.35f; +#line 3993 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation (3) *= 1.35f; +#line 3995 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 3997 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CContentType & ctUp = GetWorld () -> wo_actContentTypes [ en_iUpContent ]; +#line 3998 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CContentType & ctDn = GetWorld () -> wo_actContentTypes [ en_iDnContent ]; +#line 3999 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlayerState pstWanted = PST_STAND ; +#line 4000 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bUpSwimable = (ctUp . ct_ulFlags & CTF_SWIMABLE ) && en_fImmersionFactor <= 0.99f; +#line 4001 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bDnSwimable = (ctDn . ct_ulFlags & CTF_SWIMABLE ) && en_fImmersionFactor >= 0.5f; +#line 4004 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bUpSwimable || bDnSwimable ){ +#line 4006 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_JUMPALLOWED ; +#line 4009 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(en_fImmersionFactor >= 0.99f || bUpSwimable ){ +#line 4011 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pstWanted = PST_DIVE ; +#line 4013 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4015 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pstWanted = PST_SWIM ; +#line 4016 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4018 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4020 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(en_penReference != NULL ){ +#line 4022 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fFallTime = 0.0f; +#line 4025 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4027 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fFallTime += _pTimer -> TickQuantum ; +#line 4028 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4030 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(vTranslation (2) < 0.1f){ +#line 4032 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_JUMPALLOWED ; +#line 4033 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4036 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_fFallTime >= 0.5f){ +#line 4038 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pstWanted = PST_FALL ; +#line 4040 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4042 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(vTranslation (2) < - 0.01f){ +#line 4044 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pstWanted = PST_CROUCH ; +#line 4046 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4048 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pstWanted = PST_STAND ; +#line 4049 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4050 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4051 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4055 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (GetPhysicsFlags () & EPF_TRANSLATEDBYGRAVITY )){ +#line 4056 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredRotation (paAction . pa_aRotation ); +#line 4057 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_STAND , AOF_LOOPING | AOF_NORESTART ); +#line 4058 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredTranslation (vTranslation ); +#line 4060 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4061 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlayerState pstOld = m_pstState ; +#line 4064 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pstWanted != m_pstState ){ +#line 4066 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +switch(pstWanted ){ +#line 4068 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PST_STAND : { +#line 4070 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ChangeCollisionBoxIndexNow (PLAYER_COLLISION_BOX_STAND )){ +#line 4071 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_PositionVector (2) = plr_fViewHeightStand ; +#line 4072 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_CROUCH ){ +#line 4073 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . Rise (); +#line 4074 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4075 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . Stand (); +#line 4076 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4077 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pstState = PST_STAND ; +#line 4078 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4079 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}break ; +#line 4081 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PST_CROUCH : { +#line 4083 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ChangeCollisionBoxIndexNow (PLAYER_COLLISION_BOX_CROUCH )){ +#line 4084 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pstState = PST_CROUCH ; +#line 4085 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_PositionVector (2) = plr_fViewHeightCrouch ; +#line 4086 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . Crouch (); +#line 4087 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4088 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}break ; +#line 4090 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PST_SWIM : { +#line 4092 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ChangeCollisionBoxIndexNow (PLAYER_COLLISION_BOX_SWIMSMALL )){ +#line 4093 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ChangeCollisionBoxIndexWhenPossible (PLAYER_COLLISION_BOX_SWIM ); +#line 4094 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pstState = PST_SWIM ; +#line 4095 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_PositionVector (2) = plr_fViewHeightSwim ; +#line 4096 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . Swim (); +#line 4097 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fSwimTime = _pTimer -> CurrentTick (); +#line 4098 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4099 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}break ; +#line 4101 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PST_DIVE : { +#line 4103 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ChangeCollisionBoxIndexNow (PLAYER_COLLISION_BOX_SWIMSMALL )){ +#line 4104 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ChangeCollisionBoxIndexWhenPossible (PLAYER_COLLISION_BOX_SWIM ); +#line 4105 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pstState = PST_DIVE ; +#line 4106 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_PositionVector (2) = plr_fViewHeightDive ; +#line 4107 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . Swim (); +#line 4108 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4109 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}break ; +#line 4111 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case PST_FALL : { +#line 4113 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ChangeCollisionBoxIndexNow (PLAYER_COLLISION_BOX_STAND )){ +#line 4114 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pstState = PST_FALL ; +#line 4115 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_PositionVector (2) = plr_fViewHeightStand ; +#line 4116 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . Fall (); +#line 4117 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4118 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}break ; +#line 4119 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4120 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4123 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState != pstOld ){ +#line 4125 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bWasInWater = (pstOld == PST_SWIM || pstOld == PST_DIVE ); +#line 4126 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bIsInWater = (m_pstState == PST_SWIM || m_pstState == PST_DIVE ); +#line 4128 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bIsInWater && ! bWasInWater ){ +#line 4129 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soBody , GenderSound (SOUND_WATER_ENTER ) , SOF_3D ); +#line 4131 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(! bIsInWater && bWasInWater ){ +#line 4132 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soBody , GenderSound (SOUND_WATER_LEAVE ) , SOF_3D ); +#line 4133 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmOutOfWater = _pTimer -> CurrentTick (); +#line 4136 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(bIsInWater ){ +#line 4138 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pstOld == PST_SWIM && m_pstState == PST_DIVE ){ +#line 4139 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soFootL , GenderSound (SOUND_DIVEIN ) , SOF_3D ); +#line 4140 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_PlayEffect ("DiveIn");} +#line 4141 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bMoveSoundLeft = TRUE ; +#line 4142 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMoveSound = _pTimer -> CurrentTick (); +#line 4144 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_pstState == PST_SWIM && pstOld == PST_DIVE ){ +#line 4145 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soFootL , GenderSound (SOUND_DIVEOUT ) , SOF_3D ); +#line 4146 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bMoveSoundLeft = TRUE ; +#line 4147 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMoveSound = _pTimer -> CurrentTick (); +#line 4148 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4149 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4151 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pstOld == PST_FALL && (m_pstState == PST_STAND || m_pstState == PST_CROUCH )){ +#line 4152 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soFootL , GenderSound (SOUND_LAND ) , SOF_3D ); +#line 4153 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_PlayEffect ("Land");} +#line 4154 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4156 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_DIVE ){ +#line 4157 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soLocalAmbientLoop . Set3DParameters (50.0f , 10.0f , 0.25f , 1.0f); +#line 4158 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soLocalAmbientLoop , SOUND_WATERAMBIENT , +#line 4159 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SOF_LOOP | SOF_3D | SOF_VOLUMETRIC | SOF_LOCAL ); +#line 4160 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(pstOld == PST_DIVE ){ +#line 4161 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soLocalAmbientLoop . Stop (); +#line 4162 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4163 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4165 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(en_tmJumped + _pTimer -> TickQuantum >= _pTimer -> CurrentTick () && +#line 4166 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_tmJumped <= _pTimer -> CurrentTick () && en_penReference == NULL ){ +#line 4168 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDefaultMouthPitch (); +#line 4169 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMouth , GenderSound (SOUND_JUMP ) , SOF_3D ); +#line 4170 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_PlayEffect ("Jump");} +#line 4172 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_JUMPALLOWED ; +#line 4173 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4176 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_SWIM || pstWanted == PST_SWIM +#line 4177 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +|| (pstWanted == PST_DIVE && m_pstState != pstWanted )){ +#line 4178 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_fDensity = 500.0f; +#line 4179 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4180 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_fDensity = 1000.0f; +#line 4181 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4183 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pTimer -> CurrentTick () >= m_tmNextAmbientOnce ) +#line 4184 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4185 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_DIVE ) +#line 4186 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4187 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soLocalAmbientOnce , SOUND_WATERBUBBLES , +#line 4188 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SOF_3D | SOF_VOLUMETRIC | SOF_LOCAL ); +#line 4189 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soLocalAmbientOnce . Set3DParameters (25.0f , 5.0f , 2.0f , Lerp (0.5f , 1.5f , FRnd ())); +#line 4190 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SpawnBubbles (5 + INDEX (FRnd () * 5)); +#line 4191 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4192 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmNextAmbientOnce = _pTimer -> CurrentTick () + 5.0f + FRnd (); +#line 4193 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4197 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_CROUCH ){ +#line 4199 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation /= 2.5f; +#line 4201 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation (2) = 0.0f; +#line 4202 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4205 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_DIVE ){ +#line 4207 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATmatrix3D mPitch ; +#line 4208 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +MakeRotationMatrixFast (mPitch , FLOAT3D (0 , en_plViewpoint . pl_OrientationAngle (2) , 0)); +#line 4209 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fZ = vTranslation (3); +#line 4210 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation (3) = 0.0f; +#line 4211 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation += FLOAT3D (0 , 0 , fZ ) * mPitch ; +#line 4213 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_pstState == PST_SWIM ){ +#line 4215 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATmatrix3D mPitch ; +#line 4216 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fPitch = en_plViewpoint . pl_OrientationAngle (2); +#line 4217 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fPitch > - 30.0f){ +#line 4218 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fPitch = 0; +#line 4219 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4220 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +MakeRotationMatrixFast (mPitch , FLOAT3D (0 , fPitch , 0)); +#line 4221 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fZ = vTranslation (3); +#line 4222 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation (3) = 0.0f; +#line 4223 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation += FLOAT3D (0 , 0 , fZ ) * mPitch ; +#line 4224 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4227 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_SWIM || m_pstState == PST_DIVE ){ +#line 4229 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation (2) *= 0.5f; +#line 4230 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4233 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_SWIM && _pTimer -> CurrentTick () < m_fSwimTime + 0.5f +#line 4234 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +|| _pTimer -> CurrentTick () < m_tmOutOfWater + 0.5f){ +#line 4236 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation (2) = 0; +#line 4238 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4243 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (m_ulFlags & PLF_JUMPALLOWED ) && vTranslation (2) > 0){ +#line 4244 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vTranslation (2) = 0.0f; +#line 4245 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4248 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredTranslation (vTranslation ); +#line 4251 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . Rotate_HPB (ANGLE3D ( +#line 4252 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(ANGLE) ((FLOAT) paAction . pa_aRotation (1) * _pTimer -> TickQuantum ) , +#line 4253 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(ANGLE) ((FLOAT) paAction . pa_aRotation (2) * _pTimer -> TickQuantum ) , +#line 4254 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(ANGLE) ((FLOAT) paAction . pa_aRotation (3) * _pTimer -> TickQuantum ))); +#line 4256 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RoundViewAngle (en_plViewpoint . pl_OrientationAngle (2) , PITCH_MAX ); +#line 4257 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RoundViewAngle (en_plViewpoint . pl_OrientationAngle (3) , BANKING_MAX ); +#line 4260 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(vTranslation . Length () > 0.1f){ +#line 4261 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredRotation (ANGLE3D (en_plViewpoint . pl_OrientationAngle (1) / _pTimer -> TickQuantum , 0.0f , 0.0f)); +#line 4262 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulFlags & PLF_VIEWROTATIONCHANGED ){ +#line 4263 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_VIEWROTATIONCHANGED ; +#line 4264 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATmatrix3D mViewRot ; +#line 4265 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +MakeRotationMatrixFast (mViewRot , ANGLE3D (en_plViewpoint . pl_OrientationAngle (1) , 0 , 0)); +#line 4266 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vTransRel = vTranslation * mViewRot ; +#line 4267 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredTranslation (vTransRel ); +#line 4268 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4269 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_OrientationAngle (1) = 0.0f; +#line 4272 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4273 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_VIEWROTATIONCHANGED ; +#line 4274 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 4275 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ANGLE aDiff = en_plViewpoint . pl_OrientationAngle (1) - HEADING_MAX ; +#line 4276 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(aDiff > 0.0f){ +#line 4277 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredRotation (ANGLE3D (aDiff / _pTimer -> TickQuantum , 0.0f , 0.0f)); +#line 4278 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4279 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aDiff = en_plViewpoint . pl_OrientationAngle (1) + HEADING_MAX ; +#line 4280 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(aDiff < 0.0f){ +#line 4281 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredRotation (ANGLE3D (aDiff / _pTimer -> TickQuantum , 0.0f , 0.0f)); +#line 4282 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4283 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RoundViewAngle (en_plViewpoint . pl_OrientationAngle (1) , HEADING_MAX ); +#line 4284 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4287 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fWantSpeed = en_vDesiredTranslationRelative . Length (); +#line 4288 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fGoesSpeed = en_vCurrentTranslationAbsolute . Length (); +#line 4289 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bOnGround = (m_pstState == PST_STAND ) || (m_pstState == PST_CROUCH ); +#line 4290 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bRunning = bOnGround && fWantSpeed > 5.0f && fGoesSpeed > 5.0f; +#line 4291 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bWalking = bOnGround && ! bRunning && fWantSpeed > 2.0f && fGoesSpeed > 2.0f; +#line 4292 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bSwimming = (m_pstState == PST_SWIM ) && fWantSpeed > 2.0f && fGoesSpeed > 2.0f; +#line 4293 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bDiving = (m_pstState == PST_DIVE ) && fWantSpeed > 2.0f && fGoesSpeed > 2.0f; +#line 4294 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 4295 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iSoundWalkL = SOUND_WALK_L ; +#line 4296 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iSoundWalkR = SOUND_WALK_R ; +#line 4297 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((ctDn . ct_ulFlags & CTF_SWIMABLE ) && en_fImmersionFactor >= 0.1f){ +#line 4298 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkL = SOUND_WATERWALK_L ; +#line 4299 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkR = SOUND_WATERWALK_R ; +#line 4300 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(en_pbpoStandOn != NULL && +#line 4301 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_pbpoStandOn -> bpo_bppProperties . bpp_ubSurfaceType == SURFACE_SAND ){ +#line 4302 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkL = SOUND_WALK_SAND_L ; +#line 4303 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkR = SOUND_WALK_SAND_R ; +#line 4304 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(en_pbpoStandOn != NULL && +#line 4305 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_pbpoStandOn -> bpo_bppProperties . bpp_ubSurfaceType == SURFACE_RED_SAND ){ +#line 4306 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkL = SOUND_WALK_SAND_L ; +#line 4307 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkR = SOUND_WALK_SAND_R ; +#line 4308 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(en_pbpoStandOn != NULL && +#line 4309 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(en_pbpoStandOn -> bpo_bppProperties . bpp_ubSurfaceType == SURFACE_GRASS || +#line 4310 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_pbpoStandOn -> bpo_bppProperties . bpp_ubSurfaceType == SURFACE_GRASS_SLIDING || +#line 4311 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_pbpoStandOn -> bpo_bppProperties . bpp_ubSurfaceType == SURFACE_GRASS_NOIMPACT )){ +#line 4312 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkL = SOUND_WALK_GRASS_L ; +#line 4313 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkR = SOUND_WALK_GRASS_R ; +#line 4314 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(en_pbpoStandOn != NULL && +#line 4315 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_pbpoStandOn -> bpo_bppProperties . bpp_ubSurfaceType == SURFACE_WOOD ){ +#line 4316 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkL = SOUND_WALK_WOOD_L ; +#line 4317 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkR = SOUND_WALK_WOOD_R ; +#line 4318 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(en_pbpoStandOn != NULL && +#line 4319 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_pbpoStandOn -> bpo_bppProperties . bpp_ubSurfaceType == SURFACE_SNOW ){ +#line 4320 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkL = SOUND_WALK_SNOW_L ; +#line 4321 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkR = SOUND_WALK_SNOW_R ; +#line 4322 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4323 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else { +#line 4324 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4325 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkL += m_iGender * GENDEROFFSET ; +#line 4326 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iSoundWalkR += m_iGender * GENDEROFFSET ; +#line 4327 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bRunning ){ +#line 4328 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmNow > m_tmMoveSound + plr_fRunSoundDelay ){ +#line 4329 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMoveSound = tmNow ; +#line 4330 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bMoveSoundLeft = ! m_bMoveSoundLeft ; +#line 4331 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_bMoveSoundLeft ){ +#line 4332 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soFootL , iSoundWalkL , SOF_3D ); +#line 4333 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4334 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soFootR , iSoundWalkR , SOF_3D ); +#line 4335 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4336 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4337 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(bWalking ){ +#line 4338 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmNow > m_tmMoveSound + plr_fWalkSoundDelay ){ +#line 4339 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMoveSound = tmNow ; +#line 4340 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bMoveSoundLeft = ! m_bMoveSoundLeft ; +#line 4341 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_bMoveSoundLeft ){ +#line 4342 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soFootL , iSoundWalkL , SOF_3D ); +#line 4343 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4344 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soFootR , iSoundWalkR , SOF_3D ); +#line 4345 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4346 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4347 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(bDiving ){ +#line 4348 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmNow > m_tmMoveSound + plr_fDiveSoundDelay ){ +#line 4349 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMoveSound = tmNow ; +#line 4350 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bMoveSoundLeft = ! m_bMoveSoundLeft ; +#line 4351 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_bMoveSoundLeft ){ +#line 4352 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soFootL , GenderSound (SOUND_DIVE_L ) , SOF_3D ); +#line 4353 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4354 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soFootR , GenderSound (SOUND_DIVE_R ) , SOF_3D ); +#line 4355 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4356 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4357 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(bSwimming ){ +#line 4358 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmNow > m_tmMoveSound + plr_fSwimSoundDelay ){ +#line 4359 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMoveSound = tmNow ; +#line 4360 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bMoveSoundLeft = ! m_bMoveSoundLeft ; +#line 4361 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_bMoveSoundLeft ){ +#line 4362 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soFootL , GenderSound (SOUND_SWIM_L ) , SOF_3D ); +#line 4363 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4364 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soFootR , GenderSound (SOUND_SWIM_R ) , SOF_3D ); +#line 4365 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4366 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4367 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4370 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME tmBreathDelay = tmNow - en_tmLastBreathed ; +#line 4371 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(en_tmMaxHoldBreath - tmBreathDelay < 20.0f){ +#line 4373 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_tmMouthSoundLast + 2.0f < tmNow ){ +#line 4374 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMouthSoundLast = tmNow ; +#line 4375 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetRandomMouthPitch (0.9f , 1.1f); +#line 4376 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMouth , GenderSound (SOUND_DROWN ) , SOF_3D ); +#line 4377 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4378 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4381 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . AnimatePlayer (); +#line 4382 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4383 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4386 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RoundViewAngle(ANGLE & aViewAngle,ANGLE aRound) { +#line 4387 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(aViewAngle > aRound ){ +#line 4388 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aViewAngle = aRound ; +#line 4389 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4390 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(aViewAngle < - aRound ){ +#line 4391 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aViewAngle = - aRound ; +#line 4392 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4393 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4396 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::DeathActions(const CPlayerAction & paAction) { +#line 4398 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penView != NULL ){ +#line 4399 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (IsPredicted () && m_penView -> IsPredicted () || IsPredictor () && m_penView -> IsPredictor () || ! IsPredicted () && ! m_penView -> IsPredicted () && ! IsPredictor () && ! m_penView -> IsPredictor ()); +#line 4400 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_PositionVector = FLOAT3D (0 , 1 , 0); +#line 4401 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_OrientationAngle += (ANGLE3D ( +#line 4402 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(ANGLE) ((FLOAT) paAction . pa_aRotation (1) * _pTimer -> TickQuantum ) , +#line 4403 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(ANGLE) ((FLOAT) paAction . pa_aRotation (2) * _pTimer -> TickQuantum ) , +#line 4404 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(ANGLE) ((FLOAT) paAction . pa_aRotation (3) * _pTimer -> TickQuantum ))); +#line 4405 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4408 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_iMayRespawn == 2 && (ulReleasedButtons & PLACT_FIRE ) && ! IsPredictor ()){ +#line 4410 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bSinglePlayer ){ +#line 4412 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pShell -> Execute ("gam_bQuickLoad=1;"); +#line 4414 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(! GetSP () -> sp_bCooperative ){ +#line 4416 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendEvent (EEnd ()); +#line 4418 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4420 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulLastButtons & PLACT_RELOAD ){ +#line 4422 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_RESPAWNINPLACE ; +#line 4423 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4425 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_ctCredits != 0){ +#line 4427 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_ctCredits == - 1 || GetSP () -> sp_ctCreditsLeft != 0){ +#line 4429 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_ctCredits != - 1){ +#line 4430 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CSessionProperties *) GetSP ()) -> sp_ctCreditsLeft --; +#line 4431 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4434 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS ("%s is riding the gun again\n") , GetPlayerName ()); +#line 4435 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendEvent (EEnd ()); +#line 4438 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_ctCredits > 0){ +#line 4439 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_ctCreditsLeft == 0){ +#line 4440 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS (" no more credits left!\n")); +#line 4441 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4442 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS (" %d credits left\n") , GetSP () -> sp_ctCreditsLeft ); +#line 4443 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4444 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4446 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4448 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS ("%s rests in peace - out of credits\n") , GetPlayerName ()); +#line 4449 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4450 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4451 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4452 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4454 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_iMayRespawn == 1 && ! (ulButtonsNow & PLACT_FIRE )){ +#line 4455 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iMayRespawn = 2; +#line 4456 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4457 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4461 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ButtonsActions(CPlayerAction & paAction) +#line 4462 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4464 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((ulNewButtons & PLACT_SELECT_WEAPON_MASK ) != 0){ +#line 4465 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESelectWeapon eSelect ; +#line 4466 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSelect . iWeapon = (ulNewButtons & PLACT_SELECT_WEAPON_MASK ) >> PLACT_SELECT_WEAPON_SHIFT ; +#line 4467 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (eSelect ); +#line 4468 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4471 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & PLACT_WEAPON_NEXT ){ +#line 4472 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((CPlayerWeapons &) * m_penWeapons ) . m_bSniping ){ +#line 4473 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ApplySniperZoom (0); +#line 4474 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(TRUE ){ +#line 4475 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESelectWeapon eSelect ; +#line 4476 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSelect . iWeapon = - 1; +#line 4477 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (eSelect ); +#line 4478 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4479 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4482 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & PLACT_WEAPON_PREV ){ +#line 4483 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((CPlayerWeapons &) * m_penWeapons ) . m_bSniping ){ +#line 4484 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ApplySniperZoom (1); +#line 4485 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(TRUE ){ +#line 4486 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESelectWeapon eSelect ; +#line 4487 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSelect . iWeapon = - 2; +#line 4488 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (eSelect ); +#line 4489 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4490 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4491 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & PLACT_WEAPON_FLIP ){ +#line 4492 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESelectWeapon eSelect ; +#line 4493 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSelect . iWeapon = - 3; +#line 4494 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (eSelect ); +#line 4495 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4498 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & PLACT_FIRE ){ +#line 4499 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (EFireWeapon ()); +#line 4500 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4502 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulReleasedButtons & PLACT_FIRE ){ +#line 4503 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (EReleaseWeapon ()); +#line 4504 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4506 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulReleasedButtons & PLACT_RELOAD ){ +#line 4507 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (EReloadWeapon ()); +#line 4508 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4510 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & PLACT_FIREBOMB ){ +#line 4511 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_iSeriousBombCount > 0 && m_tmSeriousBombFired + 4.0f < _pTimer -> CurrentTick ()){ +#line 4512 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iLastSeriousBombCount = m_iSeriousBombCount ; +#line 4513 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iSeriousBombCount --; +#line 4514 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmSeriousBombFired = _pTimer -> CurrentTick (); +#line 4516 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESeriousBomb esb ; +#line 4517 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +esb . penOwner = this ; +#line 4518 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntityPointer penBomb = CreateEntity (GetPlacement () , CLASS_SERIOUSBOMB ); +#line 4519 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penBomb -> Initialize (esb ); +#line 4520 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4521 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4526 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & PLACT_USE ){ +#line 4527 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((CPlayerWeapons &) * m_penWeapons ) . m_iCurrentWeapon == WEAPON_SNIPER ){ +#line 4528 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UsePressed (FALSE ); +#line 4529 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4530 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UsePressed (ulNewButtons & PLACT_COMPUTER ); +#line 4531 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4533 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(ulNewButtons & PLACT_SNIPER_USE && ((CPlayerWeapons &) * m_penWeapons ) . m_iCurrentWeapon == WEAPON_SNIPER ){ +#line 4534 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UsePressed (FALSE ); +#line 4536 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(ulNewButtons & PLACT_COMPUTER ){ +#line 4537 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ComputerPressed (); +#line 4538 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4541 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & PLACT_USE_HELD ){ +#line 4542 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bUseButtonHeld = TRUE ; +#line 4543 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4546 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulReleasedButtons & PLACT_USE_HELD ){ +#line 4547 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bUseButtonHeld = FALSE ; +#line 4548 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4551 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & PLACT_SNIPER_ZOOMIN ){ +#line 4552 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ApplySniperZoom (1); +#line 4553 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4556 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & PLACT_SNIPER_ZOOMOUT ){ +#line 4557 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ApplySniperZoom (0); +#line 4558 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4561 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulNewButtons & PLACT_3RD_PERSON_VIEW ){ +#line 4562 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ChangePlayerView (); +#line 4563 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4566 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ulButtonsNow & PLACT_CENTER_VIEW ){ +#line 4568 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +paAction . pa_aRotation (2) += Clamp (- en_plViewpoint . pl_OrientationAngle (2) / _pTimer -> TickQuantum , - 900.0f , + 900.0f); +#line 4569 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4570 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4572 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::ApplySniperZoom(BOOL bZoomIn) +#line 4573 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4575 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((CPlayerWeapons &) * m_penWeapons ) . m_iCurrentWeapon != WEAPON_SNIPER || +#line 4576 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . m_bSniping == FALSE ){ +#line 4577 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 4578 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4579 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bZoomChanged ; +#line 4580 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((CPlayerWeapons &) * m_penWeapons ) . SniperZoomDiscrete (bZoomIn , bZoomChanged )){ +#line 4581 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bZoomChanged ){ +#line 4582 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soSniperZoom , SOUND_SNIPER_QZOOM , SOF_3D ); +#line 4583 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4584 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_ISZOOMING ; +#line 4585 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4586 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else +#line 4587 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4588 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_ISZOOMING ; +#line 4589 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soSniperZoom , SOUND_SILENCE , SOF_3D ); +#line 4590 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_StopEffect ("SniperZoom");} +#line 4591 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4592 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4595 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL CPlayer::CheatsEnabled(void) +#line 4596 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4597 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return (GetSP () -> sp_ctMaxPlayers == 1 || GetSP () -> sp_bQuickTest ) && m_penActionMarker == NULL && ! _SE_DEMO ; +#line 4598 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4601 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::Cheats(void) +#line 4602 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4603 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bFlyOn = cht_bFly || cht_bGhost ; +#line 4605 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bIsFlying = ! (GetPhysicsFlags () & EPF_TRANSLATEDBYGRAVITY ); +#line 4606 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bFlyOn && ! bIsFlying ){ +#line 4607 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPhysicsFlags (GetPhysicsFlags () & ~ (EPF_TRANSLATEDBYGRAVITY | EPF_ORIENTEDBYGRAVITY )); +#line 4608 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 4609 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(! bFlyOn && bIsFlying ){ +#line 4610 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPhysicsFlags (GetPhysicsFlags () | EPF_TRANSLATEDBYGRAVITY | EPF_ORIENTEDBYGRAVITY ); +#line 4611 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 4612 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4615 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bIsGhost = ! (GetCollisionFlags () & ((ECBI_BRUSH | ECBI_MODEL ) << ECB_TEST )); +#line 4616 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_bGhost && ! bIsGhost ){ +#line 4617 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetCollisionFlags (GetCollisionFlags () & ~ ((ECBI_BRUSH | ECBI_MODEL ) << ECB_TEST )); +#line 4618 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(! cht_bGhost && bIsGhost ){ +#line 4619 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetCollisionFlags (GetCollisionFlags () | ((ECBI_BRUSH | ECBI_MODEL ) << ECB_TEST )); +#line 4620 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4623 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const TIME tmDelta = m_tmInvisibility - _pTimer -> CurrentTick (); +#line 4624 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_bInvisible || tmDelta > 0){ +#line 4625 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetFlags (GetFlags () | ENF_INVISIBLE ); +#line 4626 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4627 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetFlags (GetFlags () & ~ ENF_INVISIBLE ); +#line 4628 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4631 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_bGiveAll ){ +#line 4632 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cht_bGiveAll = FALSE ; +#line 4633 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . CheatGiveAll (); +#line 4634 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4636 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_bKillAll ){ +#line 4637 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cht_bKillAll = FALSE ; +#line 4638 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +KillAllEnemies (this ); +#line 4639 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4641 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_bOpen ){ +#line 4642 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cht_bOpen = FALSE ; +#line 4643 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . CheatOpen (); +#line 4644 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4646 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_bAllMessages ){ +#line 4647 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cht_bAllMessages = FALSE ; +#line 4648 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheatAllMessages (); +#line 4649 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4651 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_bRefresh ){ +#line 4652 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cht_bRefresh = FALSE ; +#line 4653 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetHealth (TopHealth ()); +#line 4654 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4655 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4664 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::GetLerpedAbsoluteViewPlacement(CPlacement3D & plView) { +#line 4665 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (m_ulFlags & PLF_INITIALIZED )){ +#line 4666 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plView = GetPlacement (); +#line 4667 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_bDiscard3rdView = FALSE ; +#line 4668 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 4669 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4671 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bSharpTurning = +#line 4672 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(GetSettings () -> ps_ulFlags & PSF_SHARPTURNING ) && +#line 4673 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pNetwork -> IsPlayerLocal ((CPlayer *) GetPredictionTail ()); +#line 4676 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fLerpFactor = _pTimer -> GetLerpFactor (); +#line 4677 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plView . Lerp (en_plLastViewpoint , en_plViewpoint , fLerpFactor ); +#line 4680 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . ChangeView (plView ); +#line 4682 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . BodyAndHeadOrientation (plView ); +#line 4685 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_iViewState == PVT_PLAYEREYES || _bDiscard3rdView ){ +#line 4686 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plPosLerped = GetLerpedPlacement (); +#line 4687 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bSharpTurning ){ +#line 4689 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * pen = (CPlayer *) GetPredictionTail (); +#line 4691 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulFlags & PLF_ISZOOMING ){ +#line 4692 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fRotationDamping = ((CPlayerWeapons &) * m_penWeapons ) . m_fSniperFOV / ((CPlayerWeapons &) * m_penWeapons ) . m_fSniperMaxFOV ; +#line 4693 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plView . pl_OrientationAngle = pen -> en_plViewpoint . pl_OrientationAngle + (pen -> m_aLocalRotation - pen -> m_aLastRotation ) * fRotationDamping ; +#line 4694 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4695 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plView . pl_OrientationAngle = pen -> en_plViewpoint . pl_OrientationAngle + (pen -> m_aLocalRotation - pen -> m_aLastRotation ); +#line 4696 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4698 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RoundViewAngle (plView . pl_OrientationAngle (2) , PITCH_MAX ); +#line 4699 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RoundViewAngle (plView . pl_OrientationAngle (3) , BANKING_MAX ); +#line 4704 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ANGLE3D aCurr = pen -> GetPlacement () . pl_OrientationAngle ; +#line 4705 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ANGLE3D aLast = pen -> en_plLastPlacement . pl_OrientationAngle ; +#line 4706 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ANGLE3D aDesired = pen -> en_aDesiredRotationRelative * _pTimer -> TickQuantum ; +#line 4707 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATmatrix3D mCurr ;MakeRotationMatrixFast (mCurr , aCurr ); +#line 4708 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATmatrix3D mLast ;MakeRotationMatrixFast (mLast , aLast ); +#line 4709 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATmatrix3D mDesired ;MakeRotationMatrixFast (mDesired , aDesired ); +#line 4710 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +mDesired = en_mRotation * (mDesired * ! en_mRotation ); +#line 4711 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATmatrix3D mForced = ! mDesired * mCurr * ! mLast ; +#line 4712 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ANGLE3D aForced ;DecomposeRotationMatrixNoSnap (aForced , mForced ); +#line 4713 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(aForced . MaxNorm () < 1E-2){ +#line 4714 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +aForced = ANGLE3D (0 , 0 , 0); +#line 4715 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4716 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATquat3D qForced ;qForced . FromEuler (aForced ); +#line 4717 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATquat3D qZero ;qZero . FromEuler (ANGLE3D (0 , 0 , 0)); +#line 4718 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATquat3D qLerped = Slerp (fLerpFactor , qZero , qForced ); +#line 4719 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATmatrix3D m ; +#line 4720 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +qLerped . ToMatrix (m ); +#line 4721 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m = m * mDesired * mLast ; +#line 4722 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +DecomposeRotationMatrixNoSnap (plPosLerped . pl_OrientationAngle , m ); +#line 4723 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4724 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plView . RelativeToAbsoluteSmooth (plPosLerped ); +#line 4726 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_iViewState == PVT_3RDPERSONVIEW ){ +#line 4727 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plView = m_pen3rdPersonView -> GetLerpedPlacement (); +#line 4729 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_iViewState == PVT_PLAYERAUTOVIEW ){ +#line 4730 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plView = m_penView -> GetLerpedPlacement (); +#line 4732 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4733 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERTALWAYS ("Unknown player view"); +#line 4734 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4735 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_bDiscard3rdView = FALSE ; +#line 4736 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4739 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * CPlayer::GetViewEntity(void) { +#line 4741 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_iViewState == PVT_PLAYEREYES ){ +#line 4742 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return this ; +#line 4744 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_iViewState == PVT_3RDPERSONVIEW ){ +#line 4745 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_ulFlags & PLF_ISZOOMING ){ +#line 4746 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return this ; +#line 4747 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4748 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((CPlayerView &) * m_pen3rdPersonView ) . m_fDistance > 2.0f){ +#line 4749 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return m_pen3rdPersonView ; +#line 4750 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4751 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return this ; +#line 4752 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4754 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_iViewState == PVT_PLAYERAUTOVIEW ){ +#line 4755 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(((CPlayerView &) * m_penView ) . m_fDistance > 2.0f){ +#line 4756 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return m_penView ; +#line 4757 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4758 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return this ; +#line 4759 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4761 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 4762 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERTALWAYS ("Unknown player view"); +#line 4763 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return NULL ; +#line 4764 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4765 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4767 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RenderChainsawParticles(BOOL bThird) +#line 4768 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4769 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fStretch = 1.0f; +#line 4770 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bThird ) +#line 4771 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4772 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fStretch = 0.4f; +#line 4773 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4775 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 4776 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iSpray = 0;iSpray < MAX_BULLET_SPRAYS ;iSpray ++) +#line 4777 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4778 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BulletSprayLaunchData & bsld = m_absldData [ iSpray ]; +#line 4779 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fLife = 1.25f; +#line 4780 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmNow > (bsld . bsld_tmLaunch + fLife )){continue ;} +#line 4781 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particles_BulletSpray (bsld . bsld_iRndBase , bsld . bsld_vPos , bsld . bsld_vG , +#line 4782 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bsld . bsld_eptType , bsld . bsld_tmLaunch , bsld . bsld_vStretch * fStretch , 1.0f); +#line 4783 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4786 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iGore = 0;iGore < MAX_GORE_SPRAYS ;iGore ++) +#line 4787 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4788 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GoreSprayLaunchData & gsld = m_agsldData [ iGore ]; +#line 4789 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fLife = 2.0f; +#line 4790 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmNow > (gsld . gsld_tmLaunch + fLife )){continue ;} +#line 4791 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vPos = gsld . gsld_vPos ; +#line 4792 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bThird ) +#line 4793 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4794 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vPos = gsld . gsld_v3rdPos ; +#line 4795 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4796 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particles_BloodSpray (gsld . gsld_sptType , vPos , gsld . gsld_vG , gsld . gsld_fGA , +#line 4797 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_boxHitted , gsld . gsld_vSpilDirection , +#line 4798 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +gsld . gsld_tmLaunch , gsld . gsld_fDamagePower * fStretch , gsld . gsld_colParticles ); +#line 4799 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4800 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4803 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RenderHUD(CPerspectiveProjection3D & prProjection,CDrawPort * pdp, +#line 4804 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vViewerLightDirection,COLOR colViewerLight,COLOR colViewerAmbient, +#line 4805 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bRenderWeapon,INDEX iEye) +#line 4806 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4807 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plViewOld = prProjection . ViewerPlacementR (); +#line 4808 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bSniping = ((CPlayerWeapons &) * m_penWeapons ) . m_bSniping ; +#line 4811 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bRenderModels = _pShell -> GetINDEX ("gfx_bRenderModels"); +#line 4812 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(hud_bShowWeapon && bRenderModels && ! bSniping ){ +#line 4814 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . RenderWeaponModel (prProjection , pdp , +#line 4815 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vViewerLightDirection , colViewerLight , colViewerAmbient , bRenderWeapon , iEye ); +#line 4816 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4819 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_iViewState == PVT_PLAYEREYES ) +#line 4820 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4821 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +prProjection . ViewerPlacementL () = plViewOld ; +#line 4822 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +prProjection . Prepare (); +#line 4823 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CAnyProjection3D apr ; +#line 4824 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +apr = prProjection ; +#line 4825 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Stereo_AdjustProjection (* apr , iEye , 1); +#line 4826 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particle_PrepareSystem (pdp , apr ); +#line 4827 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particle_PrepareEntity (2.0f , FALSE , FALSE , this ); +#line 4828 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderChainsawParticles (FALSE ); +#line 4829 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particle_EndSystem (); +#line 4830 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4833 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plView ; +#line 4834 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_iViewState == PVT_PLAYEREYES ){ +#line 4836 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plView = en_plViewpoint ; +#line 4837 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plView . RelativeToAbsolute (GetPlacement ()); +#line 4838 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_iViewState == PVT_3RDPERSONVIEW ){ +#line 4840 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plView = ((CPlayerView &) * m_pen3rdPersonView ) . GetPlacement (); +#line 4841 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4842 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! bSniping ){ +#line 4843 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . RenderCrosshair (prProjection , pdp , plView ); +#line 4844 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4847 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * pen = (CPlayer *) GetPredictionTail (); +#line 4849 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ULONG ulR = 255 , ulG = 0 , ulB = 0; +#line 4850 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ULONG ulA = pen -> m_fDamageAmmount * 5.0f; +#line 4853 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT tmSinceWounding = _pTimer -> CurrentTick () - pen -> m_tmWoundedTime ; +#line 4854 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmSinceWounding < 4.0f){ +#line 4856 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmSinceWounding < 0.001f){ulA = (ulA + 64) / 2;} +#line 4857 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4860 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ulA = ClampUp (ulA , (ULONG ) 224); +#line 4861 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_iViewState == PVT_PLAYEREYES ){ +#line 4862 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> dp_ulBlendingRA += ulR * ulA ; +#line 4863 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> dp_ulBlendingGA += ulG * ulA ; +#line 4864 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> dp_ulBlendingBA += ulB * ulA ; +#line 4865 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> dp_ulBlendingA += ulA ; +#line 4866 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4869 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4870 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +COLOR colGlare = GetWorldGlaring (); +#line 4871 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UBYTE ubR , ubG , ubB , ubA ; +#line 4872 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ColorToRGBA (colGlare , ubR , ubG , ubB , ubA ); +#line 4873 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ubA != 0){ +#line 4874 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> dp_ulBlendingRA += ULONG (ubR ) * ULONG (ubA ); +#line 4875 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> dp_ulBlendingGA += ULONG (ubG ) * ULONG (ubA ); +#line 4876 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> dp_ulBlendingBA += ULONG (ubB ) * ULONG (ubA ); +#line 4877 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> dp_ulBlendingA += ULONG (ubA ); +#line 4878 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4879 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4882 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pdp -> BlendScreen (); +#line 4885 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(hud_bShowInfo ){ +#line 4887 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bSnooping = FALSE ; +#line 4888 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * penHUDPlayer = this ; +#line 4889 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * penHUDOwner = this ; +#line 4891 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penHUDPlayer -> IsPredicted ()){ +#line 4892 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penHUDPlayer = (CPlayer *) penHUDPlayer -> GetPredictor (); +#line 4893 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4896 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerWeapons * pen = (CPlayerWeapons *) & * penHUDPlayer -> m_penWeapons ; +#line 4897 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME tmDelta = _pTimer -> CurrentTick () - pen -> m_tmSnoopingStarted ; +#line 4898 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(tmDelta < plr_tmSnoopingTime ){ +#line 4899 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (pen -> m_penTargeting != NULL ); +#line 4900 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penHUDPlayer = (CPlayer *) & * pen -> m_penTargeting ; +#line 4901 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bSnooping = TRUE ; +#line 4902 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4903 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +DrawHUD (penHUDPlayer , pdp , bSnooping , penHUDOwner ); +#line 4904 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4905 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4912 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * CPlayer::GetDeathmatchStartMarker(void) +#line 4913 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4915 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strPlayerStart = "Player Start - "; +#line 4916 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX ctMarkers = _pNetwork -> GetNumberOfEntitiesWithName (strPlayerStart ); +#line 4918 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ctMarkers == 0){ +#line 4920 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return NULL ; +#line 4921 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4923 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ctMarkers == 1){ +#line 4925 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return _pNetwork -> GetEntityWithName (strPlayerStart , 0); +#line 4926 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4930 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CStaticArray < MarkerDistance > amdMarkers ; +#line 4931 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +amdMarkers . New (ctMarkers ); +#line 4933 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{for(INDEX iMarker = 0;iMarker < ctMarkers ;iMarker ++){ +#line 4934 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +amdMarkers [ iMarker ] . md_ppm = (CPlayerMarker *) _pNetwork -> GetEntityWithName (strPlayerStart , iMarker ); +#line 4935 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(amdMarkers [ iMarker ] . md_ppm == NULL ){ +#line 4936 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return NULL ; +#line 4937 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4939 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fMinD = UpperLimit (0.0f); +#line 4940 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iPlayer = 0;iPlayer < GetMaxPlayers ();iPlayer ++){ +#line 4941 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * ppl = (CPlayer *) & * GetPlayerEntity (iPlayer ); +#line 4942 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ppl == NULL ){ +#line 4943 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +continue ; +#line 4944 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4945 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fD = +#line 4946 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(amdMarkers [ iMarker ] . md_ppm -> GetPlacement () . pl_PositionVector - +#line 4947 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ppl -> GetPlacement () . pl_PositionVector ) . Length (); +#line 4948 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fD < fMinD ){ +#line 4949 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +fMinD = fD ; +#line 4950 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4951 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4952 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +amdMarkers [ iMarker ] . md_fMinD = fMinD ; +#line 4953 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}} +#line 4956 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +qsort (& amdMarkers [ 0 ] , ctMarkers , sizeof (amdMarkers [ 0 ]) , & qsort_CompareMarkerDistance ); +#line 4957 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (amdMarkers [ 0 ] . md_fMinD >= amdMarkers [ ctMarkers - 1 ] . md_fMinD ); +#line 4959 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX ctFarMarkers = ctMarkers / 2; +#line 4960 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (ctFarMarkers > 0); +#line 4961 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iStartMarker = IRnd () % ctFarMarkers ; +#line 4963 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iMarker = iStartMarker ; +#line 4964 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FOREVER { +#line 4965 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pTimer -> CurrentTick () > amdMarkers [ iMarker ] . md_ppm -> m_tmLastSpawned + 1.0f){ +#line 4966 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 4967 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4968 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iMarker = (iMarker + 1) % ctMarkers ; +#line 4969 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iMarker == iStartMarker ){ +#line 4970 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 4971 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4972 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 4974 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return amdMarkers [ iMarker ] . md_ppm ; +#line 4975 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 4981 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::InitializePlayer() +#line 4982 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 4984 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 4985 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_PositionVector = FLOAT3D (0.0f , plr_fViewHeightStand , 0.0f); +#line 4986 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plLastViewpoint = en_plViewpoint ; +#line 4989 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= PLF_INITIALIZED | PLF_LEVELSTARTED | PLF_RESPAWNINPLACE ; +#line 4990 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fFallTime = 0.0f; +#line 4991 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pstState = PST_STAND ; +#line 4992 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fDamageAmmount = 0.0f; +#line 4993 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmWoundedTime = 0.0f; +#line 4994 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmInvisibility = 0.0f , +#line 4995 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmInvulnerability = 0.0f , +#line 4996 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmSeriousDamage = 0.0f , +#line 4997 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmSeriousSpeed = 0.0f , +#line 5000 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . Initialize (); +#line 5002 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerWeapons () -> SendEvent (EStart ()); +#line 5005 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particles_AfterBurner_Prepare (this ); +#line 5008 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 5009 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetCollisionFlags (ECF_MODEL | ((ECBI_PLAYER ) << ECB_IS )); +#line 5010 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 5012 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_STAND , AOF_LOOPING ); +#line 5013 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TeleportPlayer (WLT_FIXED ); +#line 5014 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 5017 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D CPlayer::GetTeleportingOffset(void) +#line 5018 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5020 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iPlayer = GetMyPlayerIndex (); +#line 5023 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const FLOAT fOffsetY = 0.1f; +#line 5024 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vOffsetRel = FLOAT3D (0 , fOffsetY , 0); +#line 5025 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bCooperative && ! GetSP () -> sp_bSinglePlayer ){ +#line 5026 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iRow = iPlayer / 4; +#line 5027 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iCol = iPlayer % 4; +#line 5028 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vOffsetRel = FLOAT3D (- 3.0f + iCol * 2.0f , fOffsetY , - 3.0f + iRow * 2.0f); +#line 5029 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5031 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return vOffsetRel ; +#line 5032 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 5035 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RemapLevelNames(INDEX & iLevel) +#line 5036 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5037 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +switch(iLevel ){ +#line 5038 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 10: +#line 5039 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 1; +#line 5040 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5041 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 11: +#line 5042 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 2; +#line 5043 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5044 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 12: +#line 5045 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 3; +#line 5046 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5047 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 13: +#line 5048 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 4; +#line 5049 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5050 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 14: +#line 5051 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 5; +#line 5052 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5053 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 15: +#line 5054 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 6; +#line 5055 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5056 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 21: +#line 5057 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 7; +#line 5058 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5059 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 22: +#line 5060 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 8; +#line 5061 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5062 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 23: +#line 5063 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 9; +#line 5064 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5065 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 24: +#line 5066 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 10; +#line 5067 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5068 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 31: +#line 5069 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 11; +#line 5070 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5071 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 32: +#line 5072 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 12; +#line 5073 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5074 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +case 33: +#line 5075 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = 13; +#line 5076 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5077 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +default : +#line 5078 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = - 1; +#line 5079 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +break ; +#line 5080 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5081 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 5084 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::TeleportPlayer(enum WorldLinkType EwltType) +#line 5085 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5086 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iLevel = - 1; +#line 5087 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strLevelName = GetWorld () -> wo_fnmFileName . FileName (); +#line 5090 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX u , v ; +#line 5091 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +u = v = - 1; +#line 5092 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strLevelName . ScanF ("%01d_%01d_" , & u , & v ); +#line 5093 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iLevel = u * 10 + v ; +#line 5095 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RemapLevelNames (iLevel ); +#line 5097 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iLevel > 0){ +#line 5098 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CSessionProperties *) GetSP ()) -> sp_ulLevelsMask |= 1 << (iLevel - 1); +#line 5099 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5102 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iPlayer = GetMyPlayerIndex (); +#line 5104 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plSet = GetPlacement (); +#line 5106 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Teleport (CPlacement3D (FLOAT3D (32000.0f + 100.0f * iPlayer , 32000.0f , 0) , ANGLE3D (0 , 0 , 0))); +#line 5108 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ForceCollisionBoxIndexChange (PLAYER_COLLISION_BOX_STAND ); +#line 5109 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_PositionVector (2) = plr_fViewHeightStand ; +#line 5110 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . m_bDisableAnimating = FALSE ; +#line 5111 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . Stand (); +#line 5112 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pstState = PST_STAND ; +#line 5115 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vOffsetRel = GetTeleportingOffset (); +#line 5118 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bSetHealth = FALSE ; +#line 5119 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bAdjustHealth = FALSE ; +#line 5120 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * pen = NULL ; +#line 5121 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bCooperative ){ +#line 5122 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(cht_iGoToMarker >= 0){ +#line 5124 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strPlayerStart ; +#line 5125 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strPlayerStart . PrintF ("Player Start - %d" , (INDEX) cht_iGoToMarker ); +#line 5126 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pen = _pNetwork -> GetEntityWithName (strPlayerStart , 0); +#line 5127 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pen -> SendEvent (ETrigger ()); +#line 5128 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cht_iGoToMarker = - 1; +#line 5129 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bSetHealth = TRUE ; +#line 5130 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bAdjustHealth = FALSE ; +#line 5132 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_penMainMusicHolder != NULL && ! (m_ulFlags & PLF_CHANGINGLEVEL )){ +#line 5133 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CMusicHolder * pmh = (CMusicHolder *) & * m_penMainMusicHolder ; +#line 5134 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pmh -> m_penRespawnMarker != NULL ){ +#line 5136 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pen = pmh -> m_penRespawnMarker ; +#line 5137 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bSetHealth = TRUE ; +#line 5138 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bAdjustHealth = FALSE ; +#line 5139 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5140 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5143 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pen == NULL && GetSP () -> sp_bQuickTest && m_strGroup == ""){ +#line 5145 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strPlayerStart ; +#line 5146 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strPlayerStart . PrintF ("Player Quick Start"); +#line 5147 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pen = _pNetwork -> GetEntityWithName (strPlayerStart , 0); +#line 5148 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bSetHealth = TRUE ; +#line 5149 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bAdjustHealth = FALSE ; +#line 5150 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5152 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pen == NULL ){ +#line 5154 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strPlayerStart ; +#line 5155 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strPlayerStart . PrintF ("Player Start - %s" , m_strGroup ); +#line 5156 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pen = _pNetwork -> GetEntityWithName (strPlayerStart , 0); +#line 5157 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_strGroup == ""){ +#line 5158 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bSetHealth = TRUE ; +#line 5159 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bAdjustHealth = FALSE ; +#line 5160 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5161 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(EwltType == WLT_FIXED ){ +#line 5162 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bSetHealth = FALSE ; +#line 5163 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bAdjustHealth = TRUE ; +#line 5164 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5165 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bSetHealth = FALSE ; +#line 5166 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bAdjustHealth = FALSE ; +#line 5167 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5168 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5169 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5171 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pen == NULL ){ +#line 5173 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strPlayerStart ; +#line 5174 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strPlayerStart . PrintF ("Player Start - "); +#line 5175 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pen = _pNetwork -> GetEntityWithName (strPlayerStart , 0); +#line 5176 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bSetHealth = TRUE ; +#line 5177 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bAdjustHealth = FALSE ; +#line 5178 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5179 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5180 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bSetHealth = TRUE ; +#line 5181 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bAdjustHealth = FALSE ; +#line 5183 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pen = GetDeathmatchStartMarker (); +#line 5184 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pen != NULL ){ +#line 5185 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerMarker &) * pen ) . m_tmLastSpawned = _pTimer -> CurrentTick (); +#line 5186 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5187 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5190 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if((m_ulFlags & PLF_RESPAWNINPLACE ) && pen != NULL && ! ((CPlayerMarker *) & * pen ) -> m_bNoRespawnInPlace ){ +#line 5191 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_RESPAWNINPLACE ; +#line 5193 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetHealth (TopHealth ()); +#line 5194 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iMana = GetSP () -> sp_iInitialMana ; +#line 5195 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fArmor = 0.0f; +#line 5197 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Teleport (CPlacement3D (m_vDied , m_aDied )); +#line 5200 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(pen != NULL ){ +#line 5202 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penMainMusicHolder != NULL ){ +#line 5203 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CMusicHolder * pmh = (CMusicHolder *) & * m_penMainMusicHolder ; +#line 5204 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pmh -> m_penRespawnMarker == NULL ){ +#line 5206 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pmh -> m_penRespawnMarker = pen ; +#line 5207 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5208 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5210 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerMarker & CpmStart = (CPlayerMarker &) * pen ; +#line 5212 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(bSetHealth ){ +#line 5213 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetHealth (CpmStart . m_fHealth / 100.0f * TopHealth ()); +#line 5214 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iMana = GetSP () -> sp_iInitialMana ; +#line 5215 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fArmor = CpmStart . m_fShield ; +#line 5216 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(bAdjustHealth ){ +#line 5217 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fHealth = GetHealth (); +#line 5218 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fTopHealth = TopHealth (); +#line 5219 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fHealth < fTopHealth ){ +#line 5220 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetHealth (ClampUp (fHealth + fTopHealth / 2.0f , fTopHealth )); +#line 5221 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5222 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5225 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(CpmStart . m_bStartInComputer && GetSP () -> sp_bSinglePlayer ){ +#line 5227 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){ +#line 5228 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cmp_ppenPlayer = this ; +#line 5229 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5230 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cmp_bInitialStart = TRUE ; +#line 5231 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5234 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CMessageHolder * penMessage = (CMessageHolder *) & * CpmStart . m_penMessage ; +#line 5236 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +while(penMessage != NULL && IsOfClass (penMessage , "MessageHolder")){ +#line 5237 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +const CTFileName & fnmMessage = penMessage -> m_fnmMessage ; +#line 5239 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! HasMessage (fnmMessage )){ +#line 5241 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ReceiveComputerMessage (fnmMessage , 0); +#line 5242 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5244 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penMessage = (CMessageHolder *) & * penMessage -> m_penNext ; +#line 5245 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5248 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! GetSP () -> sp_bCooperative ){ +#line 5249 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . InitializeWeapons (CpmStart . m_iGiveWeapons , 0 , 0 , +#line 5250 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CpmStart . m_fMaxAmmoRatio ); +#line 5251 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5252 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . InitializeWeapons (CpmStart . m_iGiveWeapons , CpmStart . m_iTakeWeapons , +#line 5253 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetSP () -> sp_bInfiniteAmmo ? 0 : CpmStart . m_iTakeAmmo , CpmStart . m_fMaxAmmoRatio ); +#line 5254 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5256 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(EwltType == WLT_RELATIVE ){ +#line 5257 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plSet . AbsoluteToRelative (_SwcWorldChange . plLink ); +#line 5258 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plSet . RelativeToAbsolute (CpmStart . GetPlacement ()); +#line 5259 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Teleport (plSet ); +#line 5261 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(EwltType == WLT_FIXED ){ +#line 5262 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D plNew = CpmStart . GetPlacement (); +#line 5263 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +vOffsetRel *= CpmStart . en_mRotation ; +#line 5264 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plNew . pl_PositionVector += vOffsetRel ; +#line 5265 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Teleport (plNew ); +#line 5267 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5268 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERTALWAYS ("Unknown world link type"); +#line 5269 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Teleport (CPlacement3D (FLOAT3D (0 , 0 , 0) + vOffsetRel , ANGLE3D (0 , 0 , 0))); +#line 5270 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5272 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(CpmStart . m_penTarget != NULL ){ +#line 5273 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendToTarget (CpmStart . m_penTarget , EET_TRIGGER , this ); +#line 5274 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5277 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5279 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetHealth (TopHealth ()); +#line 5280 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iMana = GetSP () -> sp_iInitialMana ; +#line 5281 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fArmor = 0.0f; +#line 5283 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . InitializeWeapons (0 , 0 , 0 , 0); +#line 5285 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Teleport (CPlacement3D (FLOAT3D (0 , 0 , 0) + vOffsetRel , ANGLE3D (0 , 0 , 0))); +#line 5286 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5288 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendEventInRange (ETeleport () , FLOATaabbox3D (GetPlacement () . pl_PositionVector , 200.0f)); +#line 5290 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ForceFullStop (); +#line 5293 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fMaxHealth = TopHealth (); +#line 5296 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bSinglePlayer && GetSP () -> sp_gmGameMode != CSessionProperties :: GM_FLYOVER ){ +#line 5297 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 5298 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pwsc != NULL && pwsc -> m_bNoSaveGame ){ +#line 5299 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +NOTHING ; +#line 5300 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5302 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pShell -> Execute ("gam_bQuickSave=1;"); +#line 5303 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5304 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5306 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (m_ulFlags & PLF_LEVELSTARTED )){ +#line 5307 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_LEVELSTARTED ; +#line 5308 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmLevelStarted = _pNetwork -> GetGameTime (); +#line 5309 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5311 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strDummy ; +#line 5312 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPlayerAppearance (GetModelObject () , NULL , strDummy , FALSE ); +#line 5313 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ValidateCharacter (); +#line 5314 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPlayerAppearance (& m_moRender , & en_pcCharacter , strDummy , FALSE ); +#line 5315 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ParseGender (strDummy ); +#line 5316 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerAnimator () -> SetWeapon (); +#line 5317 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_SYNCWEAPON ; +#line 5320 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SpawnTeleport (); +#line 5322 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SwitchToModel (); +#line 5323 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmSpawned = _pTimer -> CurrentTick (); +#line 5325 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_tmLastBreathed = _pTimer -> CurrentTick () + 0.1f; +#line 5326 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 5329 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RecordEndOfLevelData(void) +#line 5330 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5332 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (! m_bEndOfLevel ); +#line 5334 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmAnalyseEnd = 0; +#line 5335 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bPendingMessage = FALSE ; +#line 5336 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMessagePlay = 0; +#line 5338 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iMayRespawn = 0; +#line 5339 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bEndOfLevel = TRUE ; +#line 5341 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +time ((time_t *) & m_iEndTime ); +#line 5343 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME tmLevelTime = _pTimer -> CurrentTick () - m_tmLevelStarted ; +#line 5344 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_tmTime = tmLevelTime ; +#line 5345 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_tmTime += tmLevelTime ; +#line 5346 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fTimeDelta = ClampDn ((FLOAT) (floor (m_tmEstTime ) - floor (tmLevelTime )) , 0.0f); +#line 5347 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iTimeScore = floor (fTimeDelta * 100.0f); +#line 5348 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iScore += m_iTimeScore ; +#line 5349 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iScore += m_iTimeScore ; +#line 5352 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strStats ; +#line 5353 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +strStats . PrintF (TRANS ("%s\n Time: %s\n Score: %9d\n Kills: %03d/%03d\n Secrets: %02d/%02d\n") , +#line 5354 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TranslateConst (en_pwoWorld -> GetName () , 0) , TimeToString (tmLevelTime ) , +#line 5355 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iScore , +#line 5356 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iKills , m_psLevelTotal . ps_iKills , +#line 5357 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iSecrets , m_psLevelTotal . ps_iSecrets ); +#line 5358 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_strLevelStats += strStats ; +#line 5359 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 5362 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::SpawnTeleport(void) +#line 5363 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5365 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bSinglePlayer ){ +#line 5367 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 5368 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5369 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESpawnEffect ese ; +#line 5370 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 5371 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ese . betType = BET_TELEPORT ; +#line 5372 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ese . vNormal = FLOAT3D (0 , 1 , 0); +#line 5373 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATaabbox3D box ; +#line 5374 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetBoundingBox (box ); +#line 5375 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fEntitySize = box . Size () . MaxNorm () * 2; +#line 5376 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ese . vStretch = FLOAT3D (fEntitySize , fEntitySize , fEntitySize ); +#line 5377 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntityPointer penEffect = CreateEntity (GetPlacement () , CLASS_BASIC_EFFECT ); +#line 5378 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penEffect -> Initialize (ese ); +#line 5379 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 5384 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::RenderParticles(void) +#line 5385 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5386 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 5389 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particles_EmptyShells (this , m_asldData ); +#line 5391 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(Particle_GetViewer () == this ){ +#line 5392 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particles_ViewerLocal (this ); +#line 5393 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5394 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else +#line 5395 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5397 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RenderChainsawParticles (TRUE ); +#line 5399 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetFlags () & ENF_ALIVE ){ +#line 5400 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_tmSeriousDamage > tmNow && m_tmInvulnerability > tmNow ){ +#line 5401 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particles_ModelGlow (this , Max (m_tmSeriousDamage , m_tmInvulnerability ) , PT_STAR08 , 0.15f , 2 , 0.03f , 0xff00ff00); +#line 5402 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_tmInvulnerability > tmNow ){ +#line 5403 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particles_ModelGlow (this , m_tmInvulnerability , PT_STAR05 , 0.15f , 2 , 0.03f , 0x3333ff00); +#line 5404 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(m_tmSeriousDamage > tmNow ){ +#line 5405 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particles_ModelGlow (this , m_tmSeriousDamage , PT_STAR08 , 0.15f , 2 , 0.03f , 0xff777700); +#line 5406 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5407 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_tmSeriousSpeed > tmNow ){ +#line 5408 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particles_RunAfterBurner (this , m_tmSeriousSpeed , 0.3f , 0); +#line 5409 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5410 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! GetSP () -> sp_bCooperative ){ +#line 5411 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerWeapons * wpn = GetPlayerWeapons (); +#line 5412 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(wpn -> m_tmLastSniperFire == _pTimer -> CurrentTick ()) +#line 5413 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5414 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CAttachmentModelObject & amoBody = * GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ); +#line 5415 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATmatrix3D m ; +#line 5416 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +MakeRotationMatrix (m , amoBody . amo_plRelative . pl_OrientationAngle ); +#line 5417 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vSource = wpn -> m_vBulletSource + FLOAT3D (0.0f , 0.1f , - 0.4f) * GetRotationMatrix () * m ; +#line 5418 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particles_SniperResidue (this , vSource , wpn -> m_vBulletTarget ); +#line 5419 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5420 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5421 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5422 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5425 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_tmSpiritStart != 0.0f) +#line 5426 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5427 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Particles_Appearing (this , m_tmSpiritStart ); +#line 5428 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5429 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 5431 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::TeleportToAutoMarker(CPlayerActionMarker * ppam) +#line 5432 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5434 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bCooperative && ! GetSP () -> sp_bSinglePlayer ){ +#line 5436 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iPlayer = 0;iPlayer < GetMaxPlayers ();iPlayer ++){ +#line 5437 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * ppl = (CPlayer *) GetPlayerEntity (iPlayer ); +#line 5438 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ppl != NULL ){ +#line 5440 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D pl = ppam -> GetPlacement (); +#line 5441 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vOffsetRel = ppl -> GetTeleportingOffset (); +#line 5442 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pl . pl_PositionVector += vOffsetRel * ppam -> en_mRotation ; +#line 5443 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ppl -> Teleport (pl , FALSE ); +#line 5445 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ppl -> m_vDied = pl . pl_PositionVector ; +#line 5446 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ppl -> m_aDied = pl . pl_OrientationAngle ; +#line 5447 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5448 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5451 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5453 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D pl = ppam -> GetPlacement (); +#line 5454 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vOffsetRel = GetTeleportingOffset (); +#line 5455 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pl . pl_PositionVector += vOffsetRel * ppam -> en_mRotation ; +#line 5456 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Teleport (pl , FALSE ); +#line 5457 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5458 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} + +#line 5461 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CPlayer::CheckDeathForRespawnInPlace(EDeath eDeath) +#line 5462 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5464 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! GetSP () -> sp_bRespawnInPlace ){ +#line 5466 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return ; +#line 5467 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5469 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * penKiller = eDeath . eLastDamage . penInflictor ; +#line 5470 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsOfClass (penKiller , "Player") || IsDerivedFromClass (penKiller , "Enemy Base")){ +#line 5472 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_RESPAWNINPLACE ; +#line 5473 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_vDied = GetPlacement () . pl_PositionVector ; +#line 5474 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_aDied = GetPlacement () . pl_OrientationAngle ; +#line 5475 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5476 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +BOOL CPlayer:: +#line 5482 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Wounded(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_Wounded + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDamage, "CPlayer::Wounded expects 'EDamage' as input!"); const EDamage &eDamage = (const EDamage &)__eeInput; +#line 5483 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EVoid()); +#line 5483 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 5490 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +WorldChange(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_WorldChange + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::WorldChange expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5492 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bSinglePlayer ){ +#line 5494 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strDummy ("1"); +#line 5495 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SaveStringVar (GetWorld () -> wo_fnmFileName . NoExt () + ".vis" , strDummy ); +#line 5496 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5498 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FindMusicHolder (); +#line 5500 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_strGroup = _SwcWorldChange . strGroup ; +#line 5501 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TeleportPlayer ((WorldLinkType ) _SwcWorldChange . iType ); +#line 5503 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetupLightSource (); +#line 5506 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerWeapons * penWeapon = GetPlayerWeapons (); +#line 5507 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_fSniperFOVlast = penWeapon -> m_fSniperFOV = penWeapon -> m_fSniperMaxFOV ; +#line 5508 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_bSniping = FALSE ; +#line 5509 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_ISZOOMING ; +#line 5512 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soWeaponAmbient , SOUND_SILENCE , SOF_3D ); +#line 5515 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UpdateLevelStats (); +#line 5516 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_INITIALIZED ; +#line 5517 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_CHANGINGLEVEL ; +#line 5518 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EVoid()); +#line 5518 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 5521 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +WorldChangeDead(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_WorldChangeDead + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::WorldChangeDead expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5524 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_RESPAWNINPLACE ; +#line 5527 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bSinglePlayer ){ +#line 5529 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strDummy ("1"); +#line 5530 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SaveStringVar (GetWorld () -> wo_fnmFileName . NoExt () + ".vis" , strDummy ); +#line 5531 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5533 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FindMusicHolder (); +#line 5536 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_Rebirth, TRUE; +Jump(STATE_CURRENT, 0x01910008, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910008_WorldChangeDead_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_Rebirth, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01910009, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910009_WorldChangeDead_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910009 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 5539 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetupLightSource (); +#line 5542 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UpdateLevelStats (); +#line 5543 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_INITIALIZED ; +#line 5544 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_CHANGINGLEVEL ; +#line 5545 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EVoid()); +#line 5545 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 5552 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Death(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_Death + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDeath, "CPlayer::Death expects 'EDeath' as input!"); const EDeath &eDeath = (const EDeath &)__eeInput; +#line 5555 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (EReleaseWeapon ()); +#line 5557 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )) +#line 5558 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5559 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +IFeel_StopEffect ("ChainsawFire"); +#line 5560 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +IFeel_StopEffect ("FlamethrowerFire"); +#line 5561 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +IFeel_StopEffect ("ChainsawIdle"); +#line 5562 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +IFeel_StopEffect ("SniperZoom"); +#line 5563 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +IFeel_StopEffect ("Minigun_rotate"); +#line 5564 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5567 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerWeapons * penWeapon = GetPlayerWeapons (); +#line 5568 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_ISZOOMING ; +#line 5569 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_bSniping = FALSE ; +#line 5570 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_fSniperFOVlast = penWeapon -> m_fSniperFOV = penWeapon -> m_fSniperMaxFOV ; +#line 5573 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soSniperZoom , SOUND_SILENCE , SOF_3D ); +#line 5574 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soWeaponAmbient , SOUND_SILENCE , SOF_3D ); +#line 5577 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penWeapon -> m_aMiniGunLast = penWeapon -> m_aMiniGun ; +#line 5580 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bSinglePlayer || IsPredictor ()){ +#line 5582 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +NOTHING ; +#line 5584 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(GetSP () -> sp_bCooperative ){ +#line 5586 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PrintPlayerDeathMessage (this , eDeath ); +#line 5588 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheckDeathForRespawnInPlace (eDeath ); +#line 5590 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iDeaths += 1; +#line 5591 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iDeaths += 1; +#line 5593 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5595 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PrintPlayerDeathMessage (this , eDeath ); +#line 5597 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * penKiller = eDeath . eLastDamage . penInflictor ; +#line 5599 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * pplKillerPlayer = NULL ; +#line 5602 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penKiller != NULL ){ +#line 5604 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsOfClass (penKiller , "Player")){ +#line 5606 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penKiller != this ){ +#line 5607 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pplKillerPlayer = (CPlayer *) penKiller ; +#line 5608 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +EReceiveScore eScore ; +#line 5609 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eScore . iPoints = m_iMana ; +#line 5610 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eDeath . eLastDamage . penInflictor -> SendEvent (eScore ); +#line 5611 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eDeath . eLastDamage . penInflictor -> SendEvent (EKilledEnemy ()); +#line 5613 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5614 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iScore -= m_iMana ; +#line 5615 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iScore -= m_iMana ; +#line 5616 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iKills -= 1; +#line 5617 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iKills -= 1; +#line 5618 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5620 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5621 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iScore -= m_iMana ; +#line 5622 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iScore -= m_iMana ; +#line 5623 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iKills -= 1; +#line 5624 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iKills -= 1; +#line 5625 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5627 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5628 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iScore -= m_iMana ; +#line 5629 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iScore -= m_iMana ; +#line 5630 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iKills -= 1; +#line 5631 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iKills -= 1; +#line 5632 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5635 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! GetSP () -> sp_bUseFrags ){ +#line 5637 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pplKillerPlayer != NULL ){ +#line 5639 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS (" %s: +%d points\n") , pplKillerPlayer -> GetPlayerName () , m_iMana ); +#line 5641 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5643 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS (" %s: -%d points\n") , GetPlayerName () , m_iMana ); +#line 5644 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5645 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5648 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iDeaths += 1; +#line 5649 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iDeaths += 1; +#line 5650 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5653 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iLastViewState = m_iViewState ; +#line 5656 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetFlags (GetFlags () & ~ ENF_ALIVE ); +#line 5658 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 5659 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 5662 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . RemoveWeapon (); +#line 5664 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerWeapons () -> SendEvent (EStop ()); +#line 5667 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! GetSP () -> sp_bCooperative ){ +#line 5669 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerWeapons () -> DropWeapon (); +#line 5670 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5674 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iAnim1 ; +#line 5675 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iAnim2 ; +#line 5676 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_SWIM || m_pstState == PST_DIVE ){ +#line 5677 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim1 = PLAYER_ANIM_DEATH_UNDERWATER ; +#line 5678 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim2 = BODY_ANIM_DEATH_UNDERWATER ; +#line 5679 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(eDeath . eLastDamage . dmtType == DMT_SPIKESTAB ){ +#line 5680 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim1 = PLAYER_ANIM_DEATH_SPIKES ; +#line 5681 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim2 = BODY_ANIM_DEATH_SPIKES ; +#line 5682 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(eDeath . eLastDamage . dmtType == DMT_ABYSS ){ +#line 5683 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim1 = PLAYER_ANIM_ABYSSFALL ; +#line 5684 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim2 = BODY_ANIM_ABYSSFALL ; +#line 5685 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5686 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vFront ; +#line 5687 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetHeadingDirection (0 , vFront ); +#line 5688 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDamageDir = m_vDamage % vFront ; +#line 5689 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(fDamageDir < 0){ +#line 5690 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(Abs (fDamageDir ) < 10.0f){ +#line 5691 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim1 = PLAYER_ANIM_DEATH_EASYFALLBACK ; +#line 5692 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim2 = BODY_ANIM_DEATH_EASYFALLBACK ; +#line 5693 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5694 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim1 = PLAYER_ANIM_DEATH_BACK ; +#line 5695 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim2 = BODY_ANIM_DEATH_BACK ; +#line 5696 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5697 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5698 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(Abs (fDamageDir ) < 10.0f){ +#line 5699 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim1 = PLAYER_ANIM_DEATH_EASYFALLFORWARD ; +#line 5700 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim2 = BODY_ANIM_DEATH_EASYFALLFORWARD ; +#line 5701 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5702 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim1 = PLAYER_ANIM_DEATH_FORWARD ; +#line 5703 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +iAnim2 = BODY_ANIM_DEATH_FORWARD ; +#line 5704 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5705 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5706 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5707 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 5708 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (iAnim1 , 0); +#line 5709 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 5710 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (iAnim2 , 0); +#line 5713 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPhysicsFlags (EPF_MODEL_CORPSE ); +#line 5714 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetCollisionFlags (ECF_CORPSE ); +#line 5717 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_fDensity = 400.0f; +#line 5720 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pstState == PST_DIVE ){ +#line 5721 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDefaultMouthPitch (); +#line 5722 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMouth , GenderSound (SOUND_DEATHWATER ) , SOF_3D ); +#line 5723 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_PlayEffect ("DeathWater");} +#line 5724 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5725 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDefaultMouthPitch (); +#line 5726 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMouth , GenderSound (SOUND_DEATH ) , SOF_3D ); +#line 5727 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_PlayEffect ("Death");} +#line 5728 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5731 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (m_penView == NULL ); +#line 5732 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penView == NULL ){ +#line 5733 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penView = CreateEntity (GetPlacement () , CLASS_PLAYER_VIEW ); +#line 5734 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +EViewInit eInit ; +#line 5735 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eInit . penOwner = this ; +#line 5736 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eInit . penCamera = NULL ; +#line 5737 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eInit . vtView = VT_PLAYERDEATH ; +#line 5738 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eInit . bDeathFixed = eDeath . eLastDamage . dmtType == DMT_ABYSS ; +#line 5739 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penView -> Initialize (eInit ); +#line 5740 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5742 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ShouldBlowUp ()){ +#line 5743 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BlowUp (); +#line 5744 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5746 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +LeaveStain (TRUE ); +#line 5747 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5749 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iMayRespawn = 0; +#line 5751 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(1.2f); +Jump(STATE_CURRENT, 0x0191000b, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191000b_Death_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191000b +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 5754 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iViewState = PVT_PLAYERAUTOVIEW ; +#line 5755 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 5756 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; + +#line 5760 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iMayRespawn = 1; +#line 5761 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 5762 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDamage):{const EDamage&eDamage= (EDamage&)__eeInput; + +#line 5765 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(eDamage . dmtType == DMT_ABYSS ){ +#line 5766 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penView != NULL ){ +#line 5767 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerView *) & * m_penView ) -> m_bFixed = TRUE ; +#line 5768 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5769 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5771 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(ShouldBlowUp ()){ +#line 5773 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BlowUp (); +#line 5774 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5775 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 5776 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EEnd):{const EEnd&e= (EEnd&)__eeInput; + +#line 5782 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! IsPredictor ()){ +#line 5784 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UnsetTimer();Jump(STATE_CURRENT,0x0191000c, FALSE, EInternal());return TRUE; +#line 5785 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5786 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EAutoAction):{const EAutoAction&eAutoAction= (EAutoAction&)__eeInput; + +#line 5790 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bCooperative && ! GetSP () -> sp_bSinglePlayer ){ +#line 5792 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(eAutoAction . penFirstMarker != NULL && +#line 5793 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerActionMarker *) & * eAutoAction . penFirstMarker ) -> m_paaAction == PAA_TELEPORT ){ +#line 5795 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TeleportToAutoMarker ((CPlayerActionMarker *) & * eAutoAction . penFirstMarker ); +#line 5796 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5797 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5799 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 5800 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDisconnected):{const EDisconnected&e= (EDisconnected&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_EReceiveScore):{const EReceiveScore&e= (EReceiveScore&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_EKilledEnemy):{const EKilledEnemy&e= (EKilledEnemy&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_EPreLevelChange):{const EPreLevelChange&e= (EPreLevelChange&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_EPostLevelChange):{const EPostLevelChange&e= (EPostLevelChange&)__eeInput; +return FALSE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 5807 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}return TRUE;}BOOL CPlayer::H0x0191000c_Death_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191000c + +#line 5809 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,ERebirth ()); +#line 5809 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 5812 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TheEnd(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_TheEnd + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::TheEnd expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5814 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! _pNetwork -> IsPlayingDemo ()){ +#line 5816 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bSinglePlayer ){ +#line 5817 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pShell -> Execute ("gam_iRecordHighScore=0;"); +#line 5818 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5819 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5821 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_gdGameDifficulty == CSessionProperties :: GD_EXTREME ){ +#line 5823 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pShell -> Execute ("sam_bMentalActivated=1;"); +#line 5824 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5827 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (EReleaseWeapon ()); +#line 5830 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetFlags (GetFlags () & ~ ENF_ALIVE ); +#line 5832 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 5833 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 5836 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_STAND , 0); +#line 5837 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerAnimator &) * m_penAnimator ) . BodyAnimationTemplate ( +#line 5838 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BODY_ANIM_NORMALWALK , BODY_ANIM_COLT_STAND , BODY_ANIM_SHOTGUN_STAND , BODY_ANIM_MINIGUN_STAND , +#line 5839 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AOF_LOOPING | AOF_NORESTART ); +#line 5841 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 5844 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bEndOfGame = TRUE ; +#line 5845 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetGameEnd (); +#line 5847 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x0191000e, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191000e_TheEnd_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191000e +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EReceiveScore):{const EReceiveScore&e= (EReceiveScore&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_EKilledEnemy):{const EKilledEnemy&e= (EKilledEnemy&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_ECenterMessage):{const ECenterMessage&e= (ECenterMessage&)__eeInput; +return FALSE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 5853 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}return TRUE;}BOOL CPlayer::H0x0191000f_TheEnd_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191000f + ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 5859 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FirstInit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_FirstInit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::FirstInit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5861 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bUseButtonHeld = FALSE ; +#line 5864 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iViewState = m_iLastViewState ; +#line 5867 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penView != NULL ){ +#line 5868 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerView &) * m_penView ) . SendEvent (EEnd ()); +#line 5869 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penView = NULL ; +#line 5870 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5872 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FindMusicHolder (); +#line 5875 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UpdateLevelStats (); +#line 5878 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +InitializePlayer (); +#line 5881 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ReceiveComputerMessage (CTFILENAME ("Data\\Messages\\Statistics\\Statistics.txt") , CMF_READ ); +#line 5883 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSettings () -> ps_ulFlags & PSF_PREFER3RDPERSON ){ +#line 5884 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ChangePlayerView (); +#line 5885 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5887 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EVoid()); +#line 5887 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 5890 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Rebirth(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_Rebirth + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::Rebirth expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5892 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +bUseButtonHeld = FALSE ; +#line 5895 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iViewState = m_iLastViewState ; +#line 5897 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! (m_ulFlags & PLF_RESPAWNINPLACE )){ +#line 5898 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerWeapons () -> ClearWeapons (); +#line 5899 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5902 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penView != NULL ){ +#line 5903 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerView &) * m_penView ) . SendEvent (EEnd ()); +#line 5904 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penView = NULL ; +#line 5905 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5908 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntityPointer penFlame = GetChildOfClass ("Flame"); +#line 5909 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penFlame != NULL ) +#line 5910 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5912 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +EStopFlaming esf ; +#line 5913 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +esf . m_bNow = TRUE ; +#line 5914 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penFlame -> SendEvent (esf ); +#line 5915 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5917 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penView != NULL ){ +#line 5918 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerView &) * m_penView ) . SendEvent (EEnd ()); +#line 5919 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penView = NULL ; +#line 5920 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5922 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FindMusicHolder (); +#line 5925 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +InitializePlayer (); +#line 5927 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 5927 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 5932 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoGoToMarker(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_AutoGoToMarker + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::AutoGoToMarker expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5934 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ULONG ulFlags = AOF_LOOPING | AOF_NORESTART ; +#line 5936 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iAnim = GetModelObject () -> GetAnim (); +#line 5937 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iAnim != PLAYER_ANIM_STAND ) +#line 5938 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5939 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ulFlags |= AOF_SMOOTHCHANGE ; +#line 5940 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5942 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 5943 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . m_bAttacking = FALSE ; +#line 5944 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . BodyWalkAnimation (); +#line 5945 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_fAutoSpeed > plr_fSpeedForward / 2){ +#line 5946 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_RUN , ulFlags ); +#line 5947 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5948 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_NORMALWALK , ulFlags ); +#line 5949 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5952 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Jump(STATE_CURRENT,0x01910015, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910015_AutoGoToMarker_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910015 +if(!( +#line 5953 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(m_penActionMarker -> GetPlacement () . pl_PositionVector - +#line 5954 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlacement () . pl_PositionVector ) . Length () > 1.0f)){ Jump(STATE_CURRENT,0x01910016, FALSE, EInternal());return TRUE;} +#line 5956 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01910013, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910013_AutoGoToMarker_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910013 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910014, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910014_AutoGoToMarker_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910014 +;Jump(STATE_CURRENT,0x01910015, FALSE, EInternal());return TRUE; +#line 5957 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}BOOL CPlayer::H0x01910016_AutoGoToMarker_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910016 + +#line 5960 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 5960 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 5964 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoGoToMarkerAndStop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_AutoGoToMarkerAndStop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::AutoGoToMarkerAndStop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5966 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ULONG ulFlags = AOF_LOOPING | AOF_NORESTART ; +#line 5968 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX iAnim = GetModelObject () -> GetAnim (); +#line 5969 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(iAnim != PLAYER_ANIM_STAND ) +#line 5970 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 5971 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ulFlags |= AOF_SMOOTHCHANGE ; +#line 5972 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5974 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 5975 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . BodyWalkAnimation (); +#line 5976 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_fAutoSpeed > plr_fSpeedForward / 2){ +#line 5977 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_RUN , ulFlags ); +#line 5978 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 5979 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_NORMALWALK , ulFlags ); +#line 5980 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 5983 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Jump(STATE_CURRENT,0x0191001a, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x0191001a_AutoGoToMarkerAndStop_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191001a +if(!( +#line 5984 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(m_penActionMarker -> GetPlacement () . pl_PositionVector - +#line 5985 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlacement () . pl_PositionVector ) . Length () > m_fAutoSpeed * _pTimer -> TickQuantum * 2.00f)){ Jump(STATE_CURRENT,0x0191001b, FALSE, EInternal());return TRUE;} +#line 5987 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01910018, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910018_AutoGoToMarkerAndStop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910018 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910019, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910019_AutoGoToMarkerAndStop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910019 +;Jump(STATE_CURRENT,0x0191001a, FALSE, EInternal());return TRUE; +#line 5988 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}BOOL CPlayer::H0x0191001b_AutoGoToMarkerAndStop_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191001b + +#line 5990 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fAutoSpeed = 0.0f; +#line 5992 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 5993 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . BodyStillAnimation (); +#line 5994 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_STAND , AOF_LOOPING | AOF_NORESTART ); +#line 5997 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ForceFullStop (); +#line 6000 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 6000 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6004 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoUseItem(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_AutoUseItem + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::AutoUseItem expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 6008 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 6009 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . BodyPullItemAnimation (); +#line 6012 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(0.2f); +Jump(STATE_CURRENT, 0x0191001d, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191001d_AutoUseItem_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191001d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0191001e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191001e_AutoUseItem_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191001e +; +#line 6015 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerActionMarker * ppam = GetActionMarker (); +#line 6016 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsOfClass (ppam -> m_penItem , "KeyItem")){ +#line 6017 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moItem = ppam -> m_penItem -> GetModelObject () -> GetAttachmentModel (0) -> amo_moModelObject ; +#line 6018 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerAnimator () -> SetItem (& moItem ); +#line 6019 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6021 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(2.20f - 0.2f); +Jump(STATE_CURRENT, 0x0191001f, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191001f_AutoUseItem_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191001f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910020, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910020_AutoUseItem_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910020 +; +#line 6024 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 6025 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . BodyRemoveItem (); +#line 6027 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetActionMarker () -> m_penTrigger != NULL ){ +#line 6029 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendToTarget (GetActionMarker () -> m_penTrigger , EET_TRIGGER , this ); +#line 6030 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6033 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetActionMarker () -> m_penDoorController != NULL ){ +#line 6034 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +EPass ePass ; +#line 6035 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ePass . penOther = this ; +#line 6036 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetActionMarker () -> m_penDoorController -> SendEvent (ePass ); +#line 6037 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6039 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(3.25f - 2.20f); +Jump(STATE_CURRENT, 0x01910021, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910021_AutoUseItem_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910021 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910022, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910022_AutoUseItem_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910022 +; +#line 6041 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 6042 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . BodyRemoveItem (); +#line 6045 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 6045 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6049 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoPickItem(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_AutoPickItem + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::AutoPickItem expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 6053 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 6054 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . BodyPickItemAnimation (); +#line 6055 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_KEYLIFT , 0); +#line 6057 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(1.2f); +Jump(STATE_CURRENT, 0x01910024, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910024_AutoPickItem_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910024 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910025, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910025_AutoPickItem_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910025 +; +#line 6060 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetActionMarker () -> m_penTrigger != NULL ){ +#line 6062 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendToTarget (GetActionMarker () -> m_penTrigger , EET_TRIGGER , this ); +#line 6063 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6066 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerActionMarker * ppam = GetActionMarker (); +#line 6067 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsOfClass (ppam -> m_penItem , "KeyItem")){ +#line 6068 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moItem = ppam -> m_penItem -> GetModelObject () -> GetAttachmentModel (0) -> amo_moModelObject ; +#line 6069 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerAnimator () -> SetItem (& moItem ); +#line 6070 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +EPass ePass ; +#line 6071 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ePass . penOther = this ; +#line 6072 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ppam -> m_penItem -> SendEvent (ePass ); +#line 6073 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6075 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(3.6f - 1.2f + GetActionMarker () -> m_tmWait ); +Jump(STATE_CURRENT, 0x01910026, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910026_AutoPickItem_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910026 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910027, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910027_AutoPickItem_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910027 +; +#line 6077 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 6078 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . BodyRemoveItem (); +#line 6081 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 6081 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6084 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoFallDown(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_AutoFallDown + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::AutoFallDown expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 6086 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_BRIDGEFALLPOSE , 0); +#line 6087 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 6088 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (BODY_ANIM_BRIDGEFALLPOSE , 0); +#line 6090 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(GetActionMarker () -> m_tmWait ); +Jump(STATE_CURRENT, 0x01910029, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910029_AutoFallDown_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910029 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0191002a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191002a_AutoFallDown_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191002a +; +#line 6093 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 6093 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6096 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoFallToAbys(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_AutoFallToAbys + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::AutoFallToAbys expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 6098 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_ABYSSFALL , AOF_LOOPING ); +#line 6099 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 6100 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (BODY_ANIM_ABYSSFALL , AOF_LOOPING ); +#line 6102 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(GetActionMarker () -> m_tmWait ); +Jump(STATE_CURRENT, 0x0191002c, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191002c_AutoFallToAbys_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191002c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0191002d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191002d_AutoFallToAbys_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191002d +; +#line 6105 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 6105 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6109 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoLookAround(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_AutoLookAround + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::AutoLookAround expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 6111 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_BACKPEDAL , 0); +#line 6112 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_vAutoSpeed = FLOAT3D (0 , 0 , plr_fSpeedForward / 4 / 0.75f); +#line 6113 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 6114 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (BODY_ANIM_NORMALWALK , 0); +#line 6116 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(GetModelObject () -> GetCurrentAnimLength () / 2); +Jump(STATE_CURRENT, 0x0191002f, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191002f_AutoLookAround_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191002f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910030, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910030_AutoLookAround_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910030 +; +#line 6118 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_vAutoSpeed = FLOAT3D (0 , 0 , 0); +#line 6121 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_STAND , 0); +#line 6122 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 6123 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (BODY_ANIM_LOOKAROUND , 0); +#line 6124 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 6127 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(moBody . GetCurrentAnimLength () + 0.1f); +Jump(STATE_CURRENT, 0x01910031, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910031_AutoLookAround_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910031 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910032, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910032_AutoLookAround_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910032 +; +#line 6130 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 6130 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6133 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoTeleport(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_AutoTeleport + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::AutoTeleport expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 6136 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TeleportToAutoMarker (GetActionMarker ()); +#line 6139 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 6139 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6142 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoAppear(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_AutoAppear + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::AutoAppear expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 6145 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SwitchToEditorModel (); +#line 6148 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Teleport (GetActionMarker () -> GetPlacement ()); +#line 6150 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPhysicsFlags (GetPhysicsFlags () & ~ (EPF_TRANSLATEDBYGRAVITY | EPF_ORIENTEDBYGRAVITY )); +#line 6151 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_AUTOMOVEMENTS ; +#line 6152 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredRotation (ANGLE3D (60 , 0 , 0)); +#line 6153 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_SPAWNPOSE , AOF_LOOPING ); +#line 6154 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 6155 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (BODY_ANIM_SPAWNPOSE , AOF_LOOPING ); +#line 6158 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmSpiritStart = _pTimer -> CurrentTick (); +#line 6160 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(5); +Jump(STATE_CURRENT, 0x01910035, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910035_AutoAppear_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910035 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910036, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910036_AutoAppear_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910036 +; +#line 6163 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SwitchToModel (); +#line 6164 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmFadeStart = _pTimer -> CurrentTick (); +#line 6166 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(5); +Jump(STATE_CURRENT, 0x01910037, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910037_AutoAppear_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910037 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910038, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910038_AutoAppear_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910038 +; +#line 6168 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +COLOR colAlpha = GetModelObject () -> mo_colBlendColor ; +#line 6169 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetModelObject () -> mo_colBlendColor = colAlpha | 0xFF; +#line 6172 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPhysicsFlags (GetPhysicsFlags () | EPF_TRANSLATEDBYGRAVITY | EPF_ORIENTEDBYGRAVITY ); +#line 6173 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 6174 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_AUTOMOVEMENTS ; +#line 6177 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_SPAWN_FALLDOWN , 0); +#line 6178 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 6179 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (BODY_ANIM_SPAWN_FALLDOWN , 0); +#line 6181 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(GetModelObject () -> GetCurrentAnimLength ()); +Jump(STATE_CURRENT, 0x01910039, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910039_AutoAppear_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910039 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0191003a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191003a_AutoAppear_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191003a +; +#line 6184 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_SPAWN_GETUP , AOF_SMOOTHCHANGE ); +#line 6185 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 6186 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (BODY_ANIM_SPAWN_GETUP , AOF_SMOOTHCHANGE ); +#line 6188 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(GetModelObject () -> GetCurrentAnimLength ()); +Jump(STATE_CURRENT, 0x0191003b, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191003b_AutoAppear_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191003b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0191003c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191003c_AutoAppear_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191003c +; +#line 6191 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 6191 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6194 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TravellingInBeam(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_TravellingInBeam + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::TravellingInBeam expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 6197 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Teleport (GetActionMarker () -> GetPlacement ()); +#line 6199 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPhysicsFlags (GetPhysicsFlags () & ~ (EPF_TRANSLATEDBYGRAVITY | EPF_ORIENTEDBYGRAVITY )); +#line 6200 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_AUTOMOVEMENTS ; +#line 6201 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredRotation (ANGLE3D (60 , 0 , 0)); +#line 6202 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredTranslation (ANGLE3D (0 , 20.0f , 0)); +#line 6203 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_SPAWNPOSE , AOF_LOOPING ); +#line 6204 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 6205 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (BODY_ANIM_SPAWNPOSE , AOF_LOOPING ); +#line 6207 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(8.0f); +Jump(STATE_CURRENT, 0x0191003e, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191003e_TravellingInBeam_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191003e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0191003f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191003f_TravellingInBeam_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191003f +; +#line 6209 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SwitchToEditorModel (); +#line 6211 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 6211 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6214 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +LogoFireMinigun(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_LogoFireMinigun + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::LogoFireMinigun expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 6217 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D pl = GetActionMarker () -> GetPlacement (); +#line 6218 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pl . pl_PositionVector += FLOAT3D (0 , 0.01f , 0) * GetActionMarker () -> en_mRotation ; +#line 6219 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Teleport (pl ); +#line 6220 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_OrientationAngle (1) = 20.0f; +#line 6221 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plLastViewpoint . pl_OrientationAngle = en_plViewpoint . pl_OrientationAngle ; +#line 6224 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_INTRO , AOF_LOOPING ); +#line 6226 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMinigunAutoFireStart = _pTimer -> CurrentTick (); +#line 6229 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (EFireWeapon ()); +#line 6230 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(2.5f); +Jump(STATE_CURRENT, 0x01910041, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910041_LogoFireMinigun_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910041 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910042, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910042_LogoFireMinigun_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910042 +; +#line 6231 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (EReleaseWeapon ()); +#line 6234 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 6235 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (BODY_ANIM_MINIGUN_STAND , 0); +#line 6237 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x01910043, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910043_LogoFireMinigun_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910043 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910044, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910044_LogoFireMinigun_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910044 +; +#line 6240 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CWorldSettingsController * pwsc = NULL ; +#line 6242 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CBackgroundViewer * penBcgViewer = (CBackgroundViewer *) GetWorld () -> GetBackgroundViewer (); +#line 6243 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penBcgViewer != NULL ) +#line 6244 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 6245 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pwsc = (CWorldSettingsController *) & * penBcgViewer -> m_penWorldSettingsController ; +#line 6246 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pwsc -> m_tmShakeStarted = _pTimer -> CurrentTick (); +#line 6247 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pwsc -> m_vShakePos = GetPlacement () . pl_PositionVector ; +#line 6248 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pwsc -> m_fShakeFalloff = 250.0f; +#line 6249 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pwsc -> m_fShakeFade = 3.0f; +#line 6251 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pwsc -> m_fShakeIntensityZ = 0.1f * 2.0f; +#line 6252 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pwsc -> m_tmShakeFrequencyZ = 5.0f; +#line 6253 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pwsc -> m_fShakeIntensityY = 0.0f; +#line 6254 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pwsc -> m_fShakeIntensityB = 0.0f; +#line 6256 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +pwsc -> m_bShakeFadeIn = FALSE ; +#line 6264 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6267 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmMinigunAutoFireStart = - 1; +#line 6268 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(5.0f); +Jump(STATE_CURRENT, 0x01910045, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910045_LogoFireMinigun_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910045 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910046, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910046_LogoFireMinigun_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910046 +; +#line 6269 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +IFeel_StopEffect (NULL ); +#line 6270 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(5.0f); +Jump(STATE_CURRENT, 0x01910047, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910047_LogoFireMinigun_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910047 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910048, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910048_LogoFireMinigun_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910048 +; +#line 6272 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 6272 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6275 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoStoreWeapon(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_AutoStoreWeapon + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::AutoStoreWeapon expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 6278 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 6279 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . BodyAnimationTemplate (BODY_ANIM_WAIT , +#line 6280 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BODY_ANIM_COLT_REDRAWSLOW , BODY_ANIM_SHOTGUN_REDRAWSLOW , BODY_ANIM_MINIGUN_REDRAWSLOW , +#line 6281 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +0); +#line 6282 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(plan . m_fBodyAnimTime ); +Jump(STATE_CURRENT, 0x0191004a, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191004a_AutoStoreWeapon_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191004a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0191004b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191004b_AutoStoreWeapon_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191004b +; +#line 6284 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iAutoOrgWeapon = ((CPlayerWeapons &) * m_penWeapons ) . m_iCurrentWeapon ; +#line 6285 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . m_iCurrentWeapon = WEAPON_NONE ; +#line 6286 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . m_iWantedWeapon = WEAPON_NONE ; +#line 6287 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soWeaponAmbient . Stop (); +#line 6290 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerAnimator () -> SyncWeapon (); +#line 6292 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 6293 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . m_iWeaponLast = m_iAutoOrgWeapon ; +#line 6294 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . RemoveWeapon (); +#line 6295 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetPlayerAnimator () -> SyncWeapon (); +#line 6297 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . m_iCurrentWeapon = (WeaponType ) m_iAutoOrgWeapon ; +#line 6298 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . BodyAnimationTemplate (BODY_ANIM_WAIT , BODY_ANIM_COLT_DEACTIVATETOWALK , +#line 6299 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BODY_ANIM_SHOTGUN_DEACTIVATETOWALK , BODY_ANIM_MINIGUN_DEACTIVATETOWALK , AOF_SMOOTHCHANGE ); +#line 6300 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . m_iCurrentWeapon = WEAPON_NONE ; +#line 6302 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(plan . m_fBodyAnimTime ); +Jump(STATE_CURRENT, 0x0191004c, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191004c_AutoStoreWeapon_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191004c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0191004d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191004d_AutoStoreWeapon_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191004d +; +#line 6305 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EReturn ()); +#line 6305 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6309 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +DoAutoActions(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_DoAutoActions + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::DoAutoActions expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 6312 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_plViewpoint . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 6314 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 6315 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . m_bDisableAnimating = TRUE ; +#line 6318 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Jump(STATE_CURRENT,0x019100a2, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x019100a2_DoAutoActions_84(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019100a2 +if(!(m_penActionMarker != NULL && IsOfClass (m_penActionMarker , "PlayerActionMarker"))){ Jump(STATE_CURRENT,0x019100a3, FALSE, EInternal());return TRUE;} +#line 6321 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(!(GetActionMarker () -> m_paaAction == PAA_WAIT )){ Jump(STATE_CURRENT,0x019100a1, FALSE, EInternal());return TRUE;} +#line 6323 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 6324 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (BODY_ANIM_WAIT , AOF_NORESTART | AOF_LOOPING ); +#line 6326 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(GetActionMarker () -> m_tmWait ); +Jump(STATE_CURRENT, 0x0191004f, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191004f_DoAutoActions_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191004f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910050, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910050_DoAutoActions_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910050 +;Jump(STATE_CURRENT,0x019100a0, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x019100a1_DoAutoActions_83(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019100a1 +if(!(GetActionMarker () -> m_paaAction == PAA_STOPANDWAIT )){ Jump(STATE_CURRENT,0x0191009f, FALSE, EInternal());return TRUE;} +#line 6329 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +StartModelAnim (PLAYER_ANIM_STAND , 0); +#line 6330 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject & moBody = GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 6331 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +moBody . PlayAnim (BODY_ANIM_WAIT , AOF_NORESTART | AOF_LOOPING ); +#line 6333 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(GetActionMarker () -> m_tmWait ); +Jump(STATE_CURRENT, 0x01910051, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910051_DoAutoActions_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910051 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01910052, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910052_DoAutoActions_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910052 +;Jump(STATE_CURRENT,0x0191009e, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x0191009f_DoAutoActions_81(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191009f +if(!(GetActionMarker () -> m_paaAction == PAA_APPEARING )){ Jump(STATE_CURRENT,0x0191009d, FALSE, EInternal());return TRUE;} +#line 6337 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_AutoAppear, TRUE; +Jump(STATE_CURRENT, 0x01910053, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910053_DoAutoActions_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910053 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_AutoAppear, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01910054, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910054_DoAutoActions_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910054 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x0191009c, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x0191009d_DoAutoActions_79(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191009d +if(!(GetActionMarker () -> m_paaAction == PAA_TRAVELING_IN_BEAM )){ Jump(STATE_CURRENT,0x0191009b, FALSE, EInternal());return TRUE;} +#line 6339 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_TravellingInBeam, TRUE; +Jump(STATE_CURRENT, 0x01910055, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910055_DoAutoActions_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910055 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_TravellingInBeam, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01910056, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910056_DoAutoActions_08(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910056 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x0191009a, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x0191009b_DoAutoActions_77(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191009b +if(!(GetActionMarker () -> m_paaAction == PAA_INTROSE_SELECT_WEAPON )){ Jump(STATE_CURRENT,0x01910099, FALSE, EInternal());return TRUE;} +#line 6342 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESelectWeapon eSelect ; +#line 6343 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSelect . iWeapon = 1; +#line 6344 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (eSelect );Jump(STATE_CURRENT,0x01910098, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910099_DoAutoActions_75(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910099 +if(!(GetActionMarker () -> m_paaAction == PAA_LOGO_FIRE_INTROSE )){ Jump(STATE_CURRENT,0x01910097, FALSE, EInternal());return TRUE;} +#line 6346 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_LogoFireMinigun, TRUE; +Jump(STATE_CURRENT, 0x01910057, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910057_DoAutoActions_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910057 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_LogoFireMinigun, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01910058, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910058_DoAutoActions_10(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910058 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01910096, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910097_DoAutoActions_73(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910097 +if(!(GetActionMarker () -> m_paaAction == PAA_LOGO_FIRE_MINIGUN )){ Jump(STATE_CURRENT,0x01910095, FALSE, EInternal());return TRUE;} +#line 6348 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_LogoFireMinigun, TRUE; +Jump(STATE_CURRENT, 0x01910059, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910059_DoAutoActions_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910059 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_LogoFireMinigun, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0191005a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191005a_DoAutoActions_12(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191005a +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01910094, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910095_DoAutoActions_71(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910095 +if(!(GetActionMarker () -> m_paaAction == PAA_TELEPORT )){ Jump(STATE_CURRENT,0x01910093, FALSE, EInternal());return TRUE;} +#line 6351 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_AutoTeleport, TRUE; +Jump(STATE_CURRENT, 0x0191005b, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191005b_DoAutoActions_13(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191005b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_AutoTeleport, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0191005c, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191005c_DoAutoActions_14(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191005c +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01910092, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910093_DoAutoActions_69(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910093 +if(!(GetActionMarker () -> m_paaAction == PAA_WAITFOREVER )){ Jump(STATE_CURRENT,0x01910091, FALSE, EInternal());return TRUE;} +#line 6356 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x0191005d, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191005d_DoAutoActions_15(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191005d +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;default:{return FALSE;}ASSERT(FALSE);break; +#line 6359 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}return TRUE;}BOOL CPlayer::H0x0191005e_DoAutoActions_16(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191005e +Jump(STATE_CURRENT,0x01910090, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910091_DoAutoActions_67(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910091 +if(!(GetActionMarker () -> m_paaAction == PAA_STOREWEAPON )){ Jump(STATE_CURRENT,0x0191008f, FALSE, EInternal());return TRUE;} +#line 6362 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_AutoStoreWeapon, TRUE; +Jump(STATE_CURRENT, 0x0191005f, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191005f_DoAutoActions_17(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191005f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_AutoStoreWeapon, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01910060, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910060_DoAutoActions_18(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910060 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x0191008e, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x0191008f_DoAutoActions_65(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191008f +if(!(GetActionMarker () -> m_paaAction == PAA_DRAWWEAPON )){ Jump(STATE_CURRENT,0x0191008d, FALSE, EInternal());return TRUE;} +#line 6367 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESelectWeapon eSelect ; +#line 6368 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSelect . iWeapon = - 4; +#line 6369 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (eSelect );Jump(STATE_CURRENT,0x0191008c, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x0191008d_DoAutoActions_63(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191008d +if(!(GetActionMarker () -> m_paaAction == PAA_LOOKAROUND )){ Jump(STATE_CURRENT,0x0191008b, FALSE, EInternal());return TRUE;} +#line 6373 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_AutoLookAround, TRUE; +Jump(STATE_CURRENT, 0x01910061, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910061_DoAutoActions_19(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910061 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_AutoLookAround, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01910062, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910062_DoAutoActions_20(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910062 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x0191008a, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x0191008b_DoAutoActions_61(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191008b +if(!(GetActionMarker () -> m_paaAction == PAA_USEITEM )){ Jump(STATE_CURRENT,0x01910089, FALSE, EInternal());return TRUE;} +#line 6378 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_AutoUseItem, TRUE; +Jump(STATE_CURRENT, 0x01910063, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910063_DoAutoActions_21(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910063 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_AutoUseItem, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01910064, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910064_DoAutoActions_22(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910064 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01910088, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910089_DoAutoActions_59(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910089 +if(!(GetActionMarker () -> m_paaAction == PAA_PICKITEM )){ Jump(STATE_CURRENT,0x01910087, FALSE, EInternal());return TRUE;} +#line 6383 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_AutoPickItem, TRUE; +Jump(STATE_CURRENT, 0x01910065, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910065_DoAutoActions_23(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910065 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_AutoPickItem, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01910066, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910066_DoAutoActions_24(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910066 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01910086, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910087_DoAutoActions_57(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910087 +if(!(GetActionMarker () -> m_paaAction == PAA_FALLDOWN )){ Jump(STATE_CURRENT,0x01910085, FALSE, EInternal());return TRUE;} +#line 6388 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_AutoFallDown, TRUE; +Jump(STATE_CURRENT, 0x01910067, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910067_DoAutoActions_25(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910067 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_AutoFallDown, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01910068, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x01910068_DoAutoActions_26(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910068 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01910084, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910085_DoAutoActions_55(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910085 +if(!(GetActionMarker () -> m_paaAction == PAA_RELEASEPLAYER )){ Jump(STATE_CURRENT,0x01910083, FALSE, EInternal());return TRUE;} +#line 6392 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penCamera != NULL ){ +#line 6393 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CCamera *) & * m_penCamera ) -> m_bStopMoving = TRUE ; +#line 6394 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6395 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penCamera = NULL ; +#line 6397 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetPlayerWeapons () -> m_iCurrentWeapon == WEAPON_NONE ){ +#line 6399 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ESelectWeapon eSelect ; +#line 6400 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eSelect . iWeapon = - 4; +#line 6401 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (eSelect ); +#line 6402 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6404 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_SYNCWEAPON ; +#line 6405 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmSpiritStart = 0;Jump(STATE_CURRENT,0x01910082, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910083_DoAutoActions_53(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910083 +if(!(GetActionMarker () -> m_paaAction == PAA_STARTCOMPUTER )){ Jump(STATE_CURRENT,0x01910081, FALSE, EInternal());return TRUE;} +#line 6410 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this ) && GetSP () -> sp_bSinglePlayer ){ +#line 6411 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cmp_ppenPlayer = this ; +#line 6412 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cmp_bInitialStart = TRUE ; +#line 6413 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}Jump(STATE_CURRENT,0x01910080, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910081_DoAutoActions_51(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910081 +if(!(GetActionMarker () -> m_paaAction == PAA_STARTINTROSCROLL )){ Jump(STATE_CURRENT,0x0191007f, FALSE, EInternal());return TRUE;} +#line 6417 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pShell -> Execute ("sam_iStartCredits=1;");Jump(STATE_CURRENT,0x0191007e, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x0191007f_DoAutoActions_49(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191007f +if(!(GetActionMarker () -> m_paaAction == PAA_STARTCREDITS )){ Jump(STATE_CURRENT,0x0191007d, FALSE, EInternal());return TRUE;} +#line 6421 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pShell -> Execute ("sam_iStartCredits=2;");Jump(STATE_CURRENT,0x0191007c, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x0191007d_DoAutoActions_47(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191007d +if(!(GetActionMarker () -> m_paaAction == PAA_STOPSCROLLER )){ Jump(STATE_CURRENT,0x0191007b, FALSE, EInternal());return TRUE;} +#line 6425 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +_pShell -> Execute ("sam_iStartCredits=-1;");Jump(STATE_CURRENT,0x0191007a, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x0191007b_DoAutoActions_45(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191007b +if(!(GetActionMarker () -> m_paaAction == PAA_RUN )){ Jump(STATE_CURRENT,0x01910079, FALSE, EInternal());return TRUE;} +#line 6430 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fAutoSpeed = plr_fSpeedForward * GetActionMarker () -> m_fSpeed ; +#line 6431 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_AutoGoToMarker, TRUE; +Jump(STATE_CURRENT, 0x01910069, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x01910069_DoAutoActions_27(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910069 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_AutoGoToMarker, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0191006a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191006a_DoAutoActions_28(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191006a +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01910078, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910079_DoAutoActions_43(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910079 +if(!(GetActionMarker () -> m_paaAction == PAA_RUNANDSTOP )){ Jump(STATE_CURRENT,0x01910077, FALSE, EInternal());return TRUE;} +#line 6436 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fAutoSpeed = plr_fSpeedForward * GetActionMarker () -> m_fSpeed ; +#line 6437 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +STATE_CPlayer_AutoGoToMarkerAndStop, TRUE; +Jump(STATE_CURRENT, 0x0191006b, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191006b_DoAutoActions_29(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191006b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayer_AutoGoToMarkerAndStop, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0191006c, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayer::H0x0191006c_DoAutoActions_30(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191006c +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01910076, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910077_DoAutoActions_41(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910077 +if(!(GetActionMarker () -> m_paaAction == PAA_RECORDSTATS )){ Jump(STATE_CURRENT,0x01910075, FALSE, EInternal());return TRUE;} +#line 6442 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bSinglePlayer || GetSP () -> sp_bPlayEntireGame ){ +#line 6444 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmEstTime = GetActionMarker () -> m_tmWait ; +#line 6446 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +RecordEndOfLevelData (); +#line 6447 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 6448 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetGameEnd (); +#line 6449 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}Jump(STATE_CURRENT,0x01910074, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910075_DoAutoActions_39(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910075 +if(!(GetActionMarker () -> m_paaAction == PAA_SHOWSTATS )){ Jump(STATE_CURRENT,0x01910073, FALSE, EInternal());return TRUE;} +#line 6454 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(!(cmp_ppenPlayer == NULL && _pNetwork -> IsPlayerLocal (this ) && GetSP () -> sp_bSinglePlayer )){ Jump(STATE_CURRENT,0x01910071, FALSE, EInternal());return TRUE;} +#line 6455 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bEndOfLevel = TRUE ; +#line 6456 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +cmp_ppenPlayer = this ; +#line 6457 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_DONTRENDER ; +#line 6458 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Jump(STATE_CURRENT,0x0191006f, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x0191006f_DoAutoActions_33(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191006f +if(!(m_bEndOfLevel )){ Jump(STATE_CURRENT,0x01910070, FALSE, EInternal());return TRUE;} +#line 6459 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x0191006d, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x0191006d_DoAutoActions_31(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191006d +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x0191006e, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EReceiveScore):{const EReceiveScore&e= (EReceiveScore&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_EKilledEnemy):{const EKilledEnemy&e= (EKilledEnemy&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_ECenterMessage):{const ECenterMessage&e= (ECenterMessage&)__eeInput; +return FALSE;}ASSERT(FALSE);break;case(EVENTCODE_EPostLevelChange):{const EPostLevelChange&e= (EPostLevelChange&)__eeInput; + +#line 6465 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ! PLF_DONTRENDER ; +#line 6466 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_bEndOfLevel = FALSE ; +#line 6467 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return FALSE; +#line 6468 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 6470 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}return TRUE;}BOOL CPlayer::H0x0191006e_DoAutoActions_32(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191006e +Jump(STATE_CURRENT,0x0191006f, FALSE, EInternal());return TRUE; +#line 6471 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}BOOL CPlayer::H0x01910070_DoAutoActions_34(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910070 + +#line 6472 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ! PLF_DONTRENDER ;Jump(STATE_CURRENT,0x01910071, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910071_DoAutoActions_35(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910071 +Jump(STATE_CURRENT,0x01910072, FALSE, EInternal());return TRUE;}BOOL CPlayer::H0x01910073_DoAutoActions_37(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910073 +if(GetActionMarker () -> m_paaAction == PAA_ENDOFGAME ){ +#line 6478 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Jump(STATE_CURRENT, STATE_CPlayer_TheEnd, TRUE, EVoid());return TRUE; +#line 6479 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(GetActionMarker () -> m_paaAction == PAA_NOGRAVITY ){ +#line 6480 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPhysicsFlags (GetPhysicsFlags () & ~ (EPF_TRANSLATEDBYGRAVITY | EPF_ORIENTEDBYGRAVITY )); +#line 6481 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetActionMarker () -> GetParent () != NULL ) +#line 6482 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +{ +#line 6483 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetParent (GetActionMarker () -> GetParent ()); +#line 6484 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6485 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(GetActionMarker () -> m_paaAction == PAA_TURNONGRAVITY ){ +#line 6486 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPhysicsFlags (GetPhysicsFlags () | EPF_TRANSLATEDBYGRAVITY | EPF_ORIENTEDBYGRAVITY ); +#line 6487 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetParent (NULL ); +#line 6488 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6489 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +else if(TRUE ){ +#line 6490 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (FALSE ); +#line 6491 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}Jump(STATE_CURRENT,0x01910072, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910072_DoAutoActions_36(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910072 +Jump(STATE_CURRENT,0x01910074, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910074_DoAutoActions_38(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910074 +Jump(STATE_CURRENT,0x01910076, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910076_DoAutoActions_40(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910076 +Jump(STATE_CURRENT,0x01910078, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910078_DoAutoActions_42(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910078 +Jump(STATE_CURRENT,0x0191007a, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x0191007a_DoAutoActions_44(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191007a +Jump(STATE_CURRENT,0x0191007c, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x0191007c_DoAutoActions_46(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191007c +Jump(STATE_CURRENT,0x0191007e, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x0191007e_DoAutoActions_48(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191007e +Jump(STATE_CURRENT,0x01910080, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910080_DoAutoActions_50(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910080 +Jump(STATE_CURRENT,0x01910082, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910082_DoAutoActions_52(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910082 +Jump(STATE_CURRENT,0x01910084, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910084_DoAutoActions_54(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910084 +Jump(STATE_CURRENT,0x01910086, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910086_DoAutoActions_56(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910086 +Jump(STATE_CURRENT,0x01910088, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910088_DoAutoActions_58(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910088 +Jump(STATE_CURRENT,0x0191008a, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x0191008a_DoAutoActions_60(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191008a +Jump(STATE_CURRENT,0x0191008c, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x0191008c_DoAutoActions_62(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191008c +Jump(STATE_CURRENT,0x0191008e, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x0191008e_DoAutoActions_64(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191008e +Jump(STATE_CURRENT,0x01910090, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910090_DoAutoActions_66(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910090 +Jump(STATE_CURRENT,0x01910092, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910092_DoAutoActions_68(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910092 +Jump(STATE_CURRENT,0x01910094, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910094_DoAutoActions_70(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910094 +Jump(STATE_CURRENT,0x01910096, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910096_DoAutoActions_72(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910096 +Jump(STATE_CURRENT,0x01910098, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x01910098_DoAutoActions_74(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01910098 +Jump(STATE_CURRENT,0x0191009a, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x0191009a_DoAutoActions_76(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191009a +Jump(STATE_CURRENT,0x0191009c, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x0191009c_DoAutoActions_78(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191009c +Jump(STATE_CURRENT,0x0191009e, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x0191009e_DoAutoActions_80(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0191009e +Jump(STATE_CURRENT,0x019100a0, FALSE, EInternal());return TRUE;} +BOOL CPlayer::H0x019100a0_DoAutoActions_82(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019100a0 + +#line 6494 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetActionMarker () -> m_penTrigger != NULL && +#line 6495 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +GetActionMarker () -> m_paaAction != PAA_PICKITEM ){ +#line 6497 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SendToTarget (GetActionMarker () -> m_penTrigger , EET_TRIGGER , this ); +#line 6498 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6501 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penActionMarker = GetActionMarker () -> m_penTarget ;Jump(STATE_CURRENT,0x019100a2, FALSE, EInternal());return TRUE; +#line 6502 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}BOOL CPlayer::H0x019100a3_DoAutoActions_85(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019100a3 + +#line 6505 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_fAutoSpeed = 0.0f; +#line 6508 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penActionMarker = NULL ; +#line 6511 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * m_penAnimator ; +#line 6512 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +plan . m_bDisableAnimating = FALSE ; +#line 6515 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EVoid ()); +#line 6515 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayer:: +#line 6520 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayer_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayer::Main expects 'EVoid' as input!"); const EVoid &evoid = (const EVoid &)__eeInput; +#line 6523 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +time ((time_t *) & m_iStartTime ); +#line 6525 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ctUnreadMessages = 0; +#line 6526 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetFlags (GetFlags () | ENF_CROSSESLEVELS | ENF_NOTIFYLEVELCHANGE ); +#line 6527 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +InitAsEditorModel (); +#line 6530 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString strDummy ; +#line 6531 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPlayerAppearance (GetModelObject () , NULL , strDummy , FALSE ); +#line 6533 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ValidateCharacter (); +#line 6534 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetPlayerAppearance (& m_moRender , & en_pcCharacter , strDummy , FALSE ); +#line 6535 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ParseGender (strDummy ); +#line 6538 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetModelObject () -> GetData () == NULL ){ +#line 6540 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EVoid()); +#line 6540 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6541 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6545 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ModelChangeNotify (); +#line 6548 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAfter(0.2f); +Jump(STATE_CURRENT, 0x019100a4, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x019100a4_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019100a4 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x019100a5, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDisconnected):{const EDisconnected&e= (EDisconnected&)__eeInput; + +#line 6552 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Destroy (); +#line 6553 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EVoid()); +#line 6553 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6554 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 6555 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}return TRUE;}BOOL CPlayer::H0x019100a5_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019100a5 + +#line 6558 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsPredictor ()){ +#line 6559 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Destroy (); +#line 6560 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EVoid()); +#line 6560 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6561 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6564 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SwitchToModel (); +#line 6565 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_INITIALIZED ; +#line 6568 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_tmMaxHoldBreath = 60.0f; +#line 6569 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +en_fDensity = 1000.0f; +#line 6571 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ModelChangeNotify (); +#line 6574 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penWeapons = CreateEntity (GetPlacement () , CLASS_PLAYER_WEAPONS ); +#line 6575 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +EWeaponsInit eInitWeapons ; +#line 6576 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eInitWeapons . penOwner = this ; +#line 6577 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penWeapons -> Initialize (eInitWeapons ); +#line 6580 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penAnimator = CreateEntity (GetPlacement () , CLASS_PLAYER_ANIMATOR ); +#line 6581 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +EAnimatorInit eInitAnimator ; +#line 6582 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +eInitAnimator . penPlayer = this ; +#line 6583 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penAnimator -> Initialize (eInitAnimator ); +#line 6586 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soMouth . Set3DParameters (50.0f , 10.0f , 1.0f , 1.0f); +#line 6587 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soFootL . Set3DParameters (20.0f , 2.0f , 1.0f , 1.0f); +#line 6588 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soFootR . Set3DParameters (20.0f , 2.0f , 1.0f , 1.0f); +#line 6589 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soBody . Set3DParameters (25.0f , 5.0f , 1.0f , 1.0f); +#line 6590 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soMessage . Set3DParameters (25.0f , 5.0f , 1.0f , 1.0f); +#line 6591 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soSniperZoom . Set3DParameters (25.0f , 5.0f , 1.0f , 1.0f); +#line 6594 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetupLightSource (); +#line 6597 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +try { +#line 6598 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_aoLightAnimation . SetData_t (CTFILENAME ("Animations\\BasicEffects.ani")); +#line 6599 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}catch (char * strError ){ +#line 6600 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +WarningMessage (TRANS ("Cannot load Animations\\BasicEffects.ani: %s") , strError ); +#line 6601 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6602 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlayLightAnim (LIGHT_ANIM_NONE , 0); +#line 6604 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x019100a6, FALSE, EBegin());return TRUE;}BOOL CPlayer::H0x019100a6_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019100a6 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +Call(STATE_CURRENT, STATE_CPlayer_FirstInit, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ERebirth):{const ERebirth&e= (ERebirth&)__eeInput; +Call(STATE_CURRENT, STATE_CPlayer_Rebirth, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; +Call(STATE_CURRENT, STATE_CPlayer_Death, TRUE, eDeath );return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDamage):{const EDamage&eDamage= (EDamage&)__eeInput; +Call(STATE_CURRENT, STATE_CPlayer_Wounded, TRUE, eDamage );return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPreLevelChange):{const EPreLevelChange&e= (EPreLevelChange&)__eeInput; + +#line 6610 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_INITIALIZED ; +#line 6611 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags |= PLF_CHANGINGLEVEL ; +#line 6612 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_LEVELSTARTED ; +#line 6613 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6614 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EPostLevelChange):{const EPostLevelChange&e= (EPostLevelChange&)__eeInput; + +#line 6616 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(GetSP () -> sp_bSinglePlayer || (GetFlags () & ENF_ALIVE )){ +#line 6617 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Call(STATE_CURRENT, STATE_CPlayer_WorldChange, TRUE, EVoid());return TRUE; +#line 6618 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 6619 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Call(STATE_CURRENT, STATE_CPlayer_WorldChangeDead, TRUE, EVoid());return TRUE; +#line 6620 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6621 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETakingBreath):{const ETakingBreath&eTakingBreath= (ETakingBreath&)__eeInput; + +#line 6623 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDefaultMouthPitch (); +#line 6624 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(eTakingBreath . fBreathDelay < 0.2f){ +#line 6625 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMouth , GenderSound (SOUND_INHALE0 ) , SOF_3D ); +#line 6626 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else if(eTakingBreath . fBreathDelay < 0.8f){ +#line 6627 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMouth , GenderSound (SOUND_INHALE1 ) , SOF_3D ); +#line 6628 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}else { +#line 6629 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMouth , GenderSound (SOUND_INHALE2 ) , SOF_3D ); +#line 6630 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6631 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6632 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_ECameraStart):{const ECameraStart&eStart= (ECameraStart&)__eeInput; + +#line 6634 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penCamera = eStart . penCamera ; +#line 6636 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penActionMarker == NULL ){ +#line 6637 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 6638 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 6639 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6641 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . SendEvent (EReleaseWeapon ()); +#line 6642 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6643 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_ECameraStop):{const ECameraStop&eCameraStop= (ECameraStop&)__eeInput; + +#line 6645 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penCamera == eCameraStop . penCamera ){ +#line 6646 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penCamera = NULL ; +#line 6647 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6648 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6649 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_ECenterMessage):{const ECenterMessage&eMsg= (ECenterMessage&)__eeInput; + +#line 6651 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_strCenterMessage = eMsg . strMessage ; +#line 6652 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_tmCenterMessageEnd = _pTimer -> CurrentTick () + eMsg . tmLength ; +#line 6653 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(eMsg . mssSound == MSS_INFO ){ +#line 6654 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_soMessage . Set3DParameters (25.0f , 5.0f , 1.0f , 1.0f); +#line 6655 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMessage , SOUND_INFO , SOF_3D | SOF_VOLUMETRIC | SOF_LOCAL ); +#line 6656 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6657 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6658 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EComputerMessage):{const EComputerMessage&eMsg= (EComputerMessage&)__eeInput; + +#line 6660 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ReceiveComputerMessage (eMsg . fnmMessage , CMF_ANALYZE ); +#line 6661 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6662 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EVoiceMessage):{const EVoiceMessage&eMsg= (EVoiceMessage&)__eeInput; + +#line 6664 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SayVoiceMessage (eMsg . fnmMessage ); +#line 6665 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6666 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EAutoAction):{const EAutoAction&eAutoAction= (EAutoAction&)__eeInput; + +#line 6669 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penActionMarker = eAutoAction . penFirstMarker ; +#line 6671 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Call(STATE_CURRENT, STATE_CPlayer_DoAutoActions, TRUE, EVoid());return TRUE; +#line 6672 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReceiveScore):{const EReceiveScore&eScore= (EReceiveScore&)__eeInput; + +#line 6674 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iScore += eScore . iPoints ; +#line 6675 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iScore += eScore . iPoints ; +#line 6676 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_iMana += eScore . iPoints * GetSP () -> sp_fManaTransferFactor ; +#line 6677 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CheckHighScore (); +#line 6678 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6679 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EKilledEnemy):{const EKilledEnemy&e= (EKilledEnemy&)__eeInput; + +#line 6681 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iKills += 1; +#line 6682 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iKills += 1; +#line 6683 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6684 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_ESecretFound):{const ESecretFound&e= (ESecretFound&)__eeInput; + +#line 6686 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psLevelStats . ps_iSecrets += 1; +#line 6687 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_psGameStats . ps_iSecrets += 1; +#line 6688 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6689 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EWeaponChanged):{const EWeaponChanged&e= (EWeaponChanged&)__eeInput; + +#line 6692 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +((CPlayerWeapons &) * m_penWeapons ) . m_bSniping = FALSE ; +#line 6693 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_ulFlags &= ~ PLF_ISZOOMING ; +#line 6694 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soSniperZoom , SOUND_SILENCE , SOF_3D ); +#line 6695 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_StopEffect ("SniperZoom");} +#line 6696 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6697 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnd):{const EEnd&e= (EEnd&)__eeInput; + +#line 6700 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +ASSERT (FALSE ); +#line 6701 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6702 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDisconnected):{const EDisconnected&e= (EDisconnected&)__eeInput; + +#line 6706 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +UnsetTimer();Jump(STATE_CURRENT,0x019100a7, FALSE, EInternal());return TRUE; +#line 6707 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&eTouch= (ETouch&)__eeInput; + +#line 6710 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(IsOfClass (eTouch . penOther , "Bouncer")){ +#line 6711 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +JumpFromBouncer (this , eTouch . penOther ); +#line 6713 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SetDefaultMouthPitch (); +#line 6714 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +PlaySound (m_soMouth , GenderSound (SOUND_JUMP ) , SOF_3D ); +#line 6715 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(_pNetwork -> IsPlayerLocal (this )){IFeel_PlayEffect ("Jump");} +#line 6716 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6717 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; +#line 6718 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 6719 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +}return TRUE;}BOOL CPlayer::H0x019100a7_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019100a7 + +#line 6724 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(! IsPredictor () && m_ulKeys != 0){ +#line 6726 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * penNextPlayer = NULL ; +#line 6727 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +for(INDEX iPlayer = 0;iPlayer < GetMaxPlayers ();iPlayer ++){ +#line 6728 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayer * pen = (CPlayer *) & * GetPlayerEntity (iPlayer ); +#line 6729 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(pen != NULL && pen != this && (pen -> GetFlags () & ENF_ALIVE ) && ! (pen -> GetFlags () & ENF_DELETED )){ +#line 6730 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penNextPlayer = pen ; +#line 6731 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6732 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6735 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(penNextPlayer != NULL ){ +#line 6737 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPrintF (TRANS ("%s leaving, all keys transfered to %s\n") , +#line 6738 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +(const char *) m_strName , (const char *) penNextPlayer -> GetPlayerName ()); +#line 6739 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +penNextPlayer -> m_ulKeys |= m_ulKeys ; +#line 6740 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6741 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6744 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +SpawnTeleport (); +#line 6747 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penWeapons -> Destroy (); +#line 6748 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penAnimator -> Destroy (); +#line 6749 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_penView != NULL ){ +#line 6750 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_penView -> Destroy (); +#line 6751 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6752 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +if(m_pen3rdPersonView != NULL ){ +#line 6753 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +m_pen3rdPersonView -> Destroy (); +#line 6754 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +} +#line 6755 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Destroy (); +#line 6756 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Return(STATE_CURRENT,EVoid()); +#line 6756 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Player.es b/Sources/EntitiesMP/Player.es new file mode 100644 index 0000000..7707532 --- /dev/null +++ b/Sources/EntitiesMP/Player.es @@ -0,0 +1,6758 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +401 +%{ + +#include "StdH.h" +#include "GameMP/SEColors.h" + +#include +#include +#include + +#include "ModelsMP/Player/SeriousSam/Player.h" +#include "ModelsMP/Player/SeriousSam/Body.h" +#include "ModelsMP/Player/SeriousSam/Head.h" + +#include "EntitiesMP/PlayerMarker.h" +#include "EntitiesMP/PlayerWeapons.h" +#include "EntitiesMP/PlayerAnimator.h" +#include "EntitiesMP/PlayerView.h" +#include "EntitiesMP/MovingBrush.h" +#include "EntitiesMP/Switch.h" +#include "EntitiesMP/MessageHolder.h" +#include "EntitiesMP/Camera.h" +#include "EntitiesMP/WorldLink.h" +#include "EntitiesMP/HealthItem.h" +#include "EntitiesMP/ArmorItem.h" +#include "EntitiesMP/WeaponItem.h" +#include "EntitiesMP/AmmoItem.h" +#include "EntitiesMP/PowerUpItem.h" +#include "EntitiesMP/MessageItem.h" +#include "EntitiesMP/AmmoPack.h" +#include "EntitiesMP/KeyItem.h" +#include "EntitiesMP/MusicHolder.h" +#include "EntitiesMP/EnemyBase.h" +#include "EntitiesMP/PlayerActionMarker.h" +#include "EntitiesMP/BasicEffects.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/ScrollHolder.h" +#include "EntitiesMP/TextFXHolder.h" +#include "EntitiesMP/SeriousBomb.h" +#include "EntitiesMP/CreditsHolder.h" +#include "EntitiesMP/HudPicHolder.h" + +extern void JumpFromBouncer(CEntity *penToBounce, CEntity *penBouncer); +// from game +#define GRV_SHOWEXTRAS (1L<<0) // add extra stuff like console, weapon, pause + +#define GENDER_MALE 0 +#define GENDER_FEMALE 1 +#define GENDEROFFSET 100 // sound components for genders are offset by this value + +%} + +enum PlayerViewType { + 0 PVT_PLAYEREYES "", + 1 PVT_PLAYERAUTOVIEW "", + 2 PVT_SCENECAMERA "", + 3 PVT_3RDPERSONVIEW "", +}; + +enum PlayerState { + 0 PST_STAND "", + 1 PST_CROUCH "", + 2 PST_SWIM "", + 3 PST_DIVE "", + 4 PST_FALL "", +}; + +// event for starting cinematic camera sequence +event ECameraStart { + CEntityPointer penCamera, // the camera +}; + +// event for ending cinematic camera sequence +event ECameraStop { + CEntityPointer penCamera, // the camera +}; + + +// sent when needs to rebirth +event ERebirth { +}; + +// sent when player was disconnected from game +event EDisconnected { +}; + +// starts automatic player actions +event EAutoAction { + CEntityPointer penFirstMarker, +}; + +%{ +extern void DrawHUD( const CPlayer *penPlayerCurrent, CDrawPort *pdpCurrent, BOOL bSnooping, const CPlayer *penPlayerOwner); +extern void InitHUD(void); +extern void EndHUD(void); + +static CTimerValue _tvProbingLast; + +// used to render certain entities only for certain players (like picked items, etc.) +extern ULONG _ulPlayerRenderingMask = 0; + +// temporary BOOL used to discard calculating of 3rd view when calculating absolute view placement +BOOL _bDiscard3rdView=FALSE; + +#define NAME name + +const FLOAT _fBlowUpAmmount = 70.0f; + +// computer message adding flags +#define CMF_READ (1L<<0) +#define CMF_ANALYZE (1L<<1) + +struct MarkerDistance { +public: + FLOAT md_fMinD; + CPlayerMarker *md_ppm; + void Clear(void); +}; + +// export current player projection +CAnyProjection3D prPlayerProjection; + + +int qsort_CompareMarkerDistance(const void *pv0, const void *pv1) +{ + MarkerDistance &md0 = *(MarkerDistance*)pv0; + MarkerDistance &md1 = *(MarkerDistance*)pv1; + if( md0.md_fMinDmd1.md_fMinD) return -1; + else return 0; +} + +static inline FLOAT IntensityAtDistance( FLOAT fFallOff, FLOAT fHotSpot, FLOAT fDistance) +{ + // intensity is zero if further than fall-off range + if( fDistance>fFallOff) return 0.0f; + // intensity is maximum if closer than hot-spot range + if( fDistanceGetWorld()->wo_cenEntities, CEntity, iten) { + CEntity *pen = iten; + if (IsDerivedFromClass(pen, "Enemy Base") && !IsOfClass(pen, "Devil")) { + CEnemyBase *penEnemy = (CEnemyBase *)pen; + if (penEnemy->m_penEnemy==NULL) { + continue; + } + penKiller->InflictDirectDamage(pen, penKiller, DMT_BULLET, + penEnemy->GetHealth()+1, pen->GetPlacement().pl_PositionVector, FLOAT3D(0,1,0)); + } + }} +} + + +#define HEADING_MAX 45.0f +#define PITCH_MAX 90.0f +#define BANKING_MAX 45.0f + +// player flags +#define PLF_INITIALIZED (1UL<<0) // set when player entity is ready to function +#define PLF_VIEWROTATIONCHANGED (1UL<<1) // for adjusting view rotation separately from legs +#define PLF_JUMPALLOWED (1UL<<2) // if jumping is allowed +#define PLF_SYNCWEAPON (1UL<<3) // weapon model needs to be synchronized before rendering +#define PLF_AUTOMOVEMENTS (1UL<<4) // complete automatic control of movements +#define PLF_DONTRENDER (1UL<<5) // don't render view (used at end of level) +#define PLF_CHANGINGLEVEL (1UL<<6) // mark that we next are to appear at start of new level +#define PLF_APPLIEDACTION (1UL<<7) // used to detect when player is not connected +#define PLF_NOTCONNECTED (1UL<<8) // set if the player is not connected +#define PLF_LEVELSTARTED (1UL<<9) // marks that level start time was recorded +#define PLF_ISZOOMING (1UL<<10) // marks that player is zoomed in with the sniper +#define PLF_RESPAWNINPLACE (1UL<<11) // don't move to marker when respawning (for current death only) + +// defines representing flags used to fill player buttoned actions +#define PLACT_FIRE (1L<<0) +#define PLACT_RELOAD (1L<<1) +#define PLACT_WEAPON_NEXT (1L<<2) +#define PLACT_WEAPON_PREV (1L<<3) +#define PLACT_WEAPON_FLIP (1L<<4) +#define PLACT_USE (1L<<5) +#define PLACT_COMPUTER (1L<<6) +#define PLACT_3RD_PERSON_VIEW (1L<<7) +#define PLACT_CENTER_VIEW (1L<<8) +#define PLACT_USE_HELD (1L<<9) +#define PLACT_SNIPER_ZOOMIN (1L<<10) +#define PLACT_SNIPER_ZOOMOUT (1L<<11) +#define PLACT_SNIPER_USE (1L<<12) +#define PLACT_FIREBOMB (1L<<13) +#define PLACT_SELECT_WEAPON_SHIFT (14) +#define PLACT_SELECT_WEAPON_MASK (0x1FL<en_pcCharacter==pc) { + penThis = pen; + break; + } + } + // if not found + if (penThis==NULL) { + // do nothing + return; + } + + // accumulate local rotation + penThis->m_aLocalRotation +=paAction.pa_aRotation; + penThis->m_aLocalViewRotation+=paAction.pa_aViewRotation; + penThis->m_vLocalTranslation +=paAction.pa_vTranslation; + + // if prescanning + if (bPreScan) { + // no button checking + return; + } + + // add button movement/rotation/look actions to the axis actions + if(pctlCurrent.bMoveForward ) paAction.pa_vTranslation(3) -= plr_fSpeedForward; + if(pctlCurrent.bMoveBackward ) paAction.pa_vTranslation(3) += plr_fSpeedBackward; + if(pctlCurrent.bMoveLeft || pctlCurrent.bStrafe&&pctlCurrent.bTurnLeft) paAction.pa_vTranslation(1) -= plr_fSpeedSide; + if(pctlCurrent.bMoveRight || pctlCurrent.bStrafe&&pctlCurrent.bTurnRight) paAction.pa_vTranslation(1) += plr_fSpeedSide; + if(pctlCurrent.bMoveUp ) paAction.pa_vTranslation(2) += plr_fSpeedUp; + if(pctlCurrent.bMoveDown ) paAction.pa_vTranslation(2) -= plr_fSpeedUp; + + const FLOAT fQuantum = _pTimer->TickQuantum; + if(pctlCurrent.bTurnLeft && !pctlCurrent.bStrafe) penThis->m_aLocalRotation(1) += ctl_fButtonRotationSpeedH*fQuantum; + if(pctlCurrent.bTurnRight && !pctlCurrent.bStrafe) penThis->m_aLocalRotation(1) -= ctl_fButtonRotationSpeedH*fQuantum; + if(pctlCurrent.bTurnUp ) penThis->m_aLocalRotation(2) += ctl_fButtonRotationSpeedP*fQuantum; + if(pctlCurrent.bTurnDown ) penThis->m_aLocalRotation(2) -= ctl_fButtonRotationSpeedP*fQuantum; + if(pctlCurrent.bTurnBankingLeft ) penThis->m_aLocalRotation(3) += ctl_fButtonRotationSpeedB*fQuantum; + if(pctlCurrent.bTurnBankingRight ) penThis->m_aLocalRotation(3) -= ctl_fButtonRotationSpeedB*fQuantum; + + if(pctlCurrent.bLookLeft ) penThis->m_aLocalViewRotation(1) += ctl_fButtonRotationSpeedH*fQuantum; + if(pctlCurrent.bLookRight ) penThis->m_aLocalViewRotation(1) -= ctl_fButtonRotationSpeedH*fQuantum; + if(pctlCurrent.bLookUp ) penThis->m_aLocalViewRotation(2) += ctl_fButtonRotationSpeedP*fQuantum; + if(pctlCurrent.bLookDown ) penThis->m_aLocalViewRotation(2) -= ctl_fButtonRotationSpeedP*fQuantum; + if(pctlCurrent.bLookBankingLeft ) penThis->m_aLocalViewRotation(3) += ctl_fButtonRotationSpeedB*fQuantum; + if(pctlCurrent.bLookBankingRight ) penThis->m_aLocalViewRotation(3) -= ctl_fButtonRotationSpeedB*fQuantum; + + // use current accumulated rotation + paAction.pa_aRotation = penThis->m_aLocalRotation; + paAction.pa_aViewRotation = penThis->m_aLocalViewRotation; + //paAction.pa_vTranslation = penThis->m_vLocalTranslation; + + // if walking + if(pctlCurrent.bWalk) { + // make forward/backward and sidestep speeds slower + paAction.pa_vTranslation(3) /= 2.0f; + paAction.pa_vTranslation(1) /= 2.0f; + } + + // reset all button actions + paAction.pa_ulButtons = 0; + + // set weapon selection bits + for(INDEX i=1; ips_ulFlags&PSF_COMPSINGLECLICK)) { + // press both + paAction.pa_ulButtons |= PLACT_USE|PLACT_COMPUTER; + // if double-click is on + } else { + // if double click + if (_pTimer->GetRealTimeTick()<=_tmLastUseOrCompPressed+ctl_tmComputerDoubleClick) { + // computer pressed + paAction.pa_ulButtons |= PLACT_COMPUTER; + // if single click + } else { + // use pressed + paAction.pa_ulButtons |= PLACT_USE; + } + } + _tmLastUseOrCompPressed = _pTimer->GetRealTimeTick(); + } + // remember old userorcomp pressed state + pctlCurrent.bUseOrComputerLast = pctlCurrent.bUseOrComputer; +}; + +void CPlayer_Precache(void) +{ + CDLLEntityClass *pdec = &CPlayer_DLLClass; + + // precache view + extern void CPlayerView_Precache(void); + CPlayerView_Precache(); + + // precache all player sounds + pdec->PrecacheSound(SOUND_WATER_ENTER ); + pdec->PrecacheSound(SOUND_WATER_LEAVE ); + pdec->PrecacheSound(SOUND_WALK_L ); + pdec->PrecacheSound(SOUND_WALK_R ); + pdec->PrecacheSound(SOUND_WALK_SAND_L ); + pdec->PrecacheSound(SOUND_WALK_SAND_R ); + pdec->PrecacheSound(SOUND_SWIM_L ); + pdec->PrecacheSound(SOUND_SWIM_R ); + pdec->PrecacheSound(SOUND_DIVE_L ); + pdec->PrecacheSound(SOUND_DIVE_R ); + pdec->PrecacheSound(SOUND_DIVEIN ); + pdec->PrecacheSound(SOUND_DIVEOUT ); + pdec->PrecacheSound(SOUND_DROWN ); + pdec->PrecacheSound(SOUND_INHALE0 ); + pdec->PrecacheSound(SOUND_JUMP ); + pdec->PrecacheSound(SOUND_LAND ); + pdec->PrecacheSound(SOUND_WOUNDWEAK ); + pdec->PrecacheSound(SOUND_WOUNDMEDIUM ); + pdec->PrecacheSound(SOUND_WOUNDSTRONG ); + pdec->PrecacheSound(SOUND_WOUNDWATER ); + pdec->PrecacheSound(SOUND_DEATH ); + pdec->PrecacheSound(SOUND_DEATHWATER ); + pdec->PrecacheSound(SOUND_WATERAMBIENT ); + pdec->PrecacheSound(SOUND_WATERBUBBLES ); + pdec->PrecacheSound(SOUND_WATERWALK_L ); + pdec->PrecacheSound(SOUND_WATERWALK_R ); + pdec->PrecacheSound(SOUND_INHALE1 ); + pdec->PrecacheSound(SOUND_INHALE2 ); + pdec->PrecacheSound(SOUND_INFO ); + pdec->PrecacheSound(SOUND_WALK_GRASS_L ); + pdec->PrecacheSound(SOUND_WALK_GRASS_R ); + pdec->PrecacheSound(SOUND_WALK_WOOD_L ); + pdec->PrecacheSound(SOUND_WALK_WOOD_R ); + pdec->PrecacheSound(SOUND_WALK_SNOW_L ); + pdec->PrecacheSound(SOUND_WALK_SNOW_R ); +//pdec->PrecacheSound(SOUND_HIGHSCORE ); + pdec->PrecacheSound(SOUND_SNIPER_ZOOM ); + pdec->PrecacheSound(SOUND_SNIPER_QZOOM ); + pdec->PrecacheSound(SOUND_SILENCE ); + pdec->PrecacheSound(SOUND_POWERUP_BEEP ); + + pdec->PrecacheSound(SOUND_F_WATER_ENTER ); + pdec->PrecacheSound(SOUND_F_WATER_LEAVE ); + pdec->PrecacheSound(SOUND_F_WALK_L ); + pdec->PrecacheSound(SOUND_F_WALK_R ); + pdec->PrecacheSound(SOUND_F_WALK_SAND_L ); + pdec->PrecacheSound(SOUND_F_WALK_SAND_R ); + pdec->PrecacheSound(SOUND_F_SWIM_L ); + pdec->PrecacheSound(SOUND_F_SWIM_R ); + pdec->PrecacheSound(SOUND_F_DIVE_L ); + pdec->PrecacheSound(SOUND_F_DIVE_R ); + pdec->PrecacheSound(SOUND_F_DIVEIN ); + pdec->PrecacheSound(SOUND_F_DIVEOUT ); + pdec->PrecacheSound(SOUND_F_DROWN ); + pdec->PrecacheSound(SOUND_F_INHALE0 ); + pdec->PrecacheSound(SOUND_F_JUMP ); + pdec->PrecacheSound(SOUND_F_LAND ); + pdec->PrecacheSound(SOUND_F_WOUNDWEAK ); + pdec->PrecacheSound(SOUND_F_WOUNDMEDIUM ); + pdec->PrecacheSound(SOUND_F_WOUNDSTRONG ); + pdec->PrecacheSound(SOUND_F_WOUNDWATER ); + pdec->PrecacheSound(SOUND_F_DEATH ); + pdec->PrecacheSound(SOUND_F_DEATHWATER ); + pdec->PrecacheSound(SOUND_F_WATERWALK_L ); + pdec->PrecacheSound(SOUND_F_WATERWALK_R ); + pdec->PrecacheSound(SOUND_F_INHALE1 ); + pdec->PrecacheSound(SOUND_F_INHALE2 ); + pdec->PrecacheSound(SOUND_F_WALK_GRASS_L ); + pdec->PrecacheSound(SOUND_F_WALK_GRASS_R ); + pdec->PrecacheSound(SOUND_F_WALK_WOOD_L ); + pdec->PrecacheSound(SOUND_F_WALK_WOOD_R ); + pdec->PrecacheSound(SOUND_F_WALK_SNOW_L ); + pdec->PrecacheSound(SOUND_F_WALK_SNOW_R ); +//pdec->PrecacheSound(SOUND_F_HIGHSCORE ); + pdec->PrecacheSound(SOUND_BLOWUP ); + + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_TELEPORT); + pdec->PrecacheClass(CLASS_SERIOUSBOMB); + + pdec->PrecacheModel(MODEL_FLESH); + pdec->PrecacheModel(MODEL_FLESH_APPLE); + pdec->PrecacheModel(MODEL_FLESH_BANANA); + pdec->PrecacheModel(MODEL_FLESH_BURGER); + pdec->PrecacheTexture(TEXTURE_FLESH_RED); + pdec->PrecacheTexture(TEXTURE_FLESH_GREEN); + pdec->PrecacheTexture(TEXTURE_FLESH_APPLE); + pdec->PrecacheTexture(TEXTURE_FLESH_BANANA); + pdec->PrecacheTexture(TEXTURE_FLESH_BURGER); + pdec->PrecacheTexture(TEXTURE_FLESH_LOLLY); + pdec->PrecacheTexture(TEXTURE_FLESH_ORANGE); + + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSPILL); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODSTAINGROW); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BLOODEXPLODE); +} + +void CPlayer_OnInitClass(void) +{ + // clear current player controls + memset(&pctlCurrent, 0, sizeof(pctlCurrent)); + // declare player control variables + _pShell->DeclareSymbol("user INDEX ctl_bMoveForward;", &pctlCurrent.bMoveForward); + _pShell->DeclareSymbol("user INDEX ctl_bMoveBackward;", &pctlCurrent.bMoveBackward); + _pShell->DeclareSymbol("user INDEX ctl_bMoveLeft;", &pctlCurrent.bMoveLeft); + _pShell->DeclareSymbol("user INDEX ctl_bMoveRight;", &pctlCurrent.bMoveRight); + _pShell->DeclareSymbol("user INDEX ctl_bMoveUp;", &pctlCurrent.bMoveUp); + _pShell->DeclareSymbol("user INDEX ctl_bMoveDown;", &pctlCurrent.bMoveDown); + _pShell->DeclareSymbol("user INDEX ctl_bTurnLeft;", &pctlCurrent.bTurnLeft); + _pShell->DeclareSymbol("user INDEX ctl_bTurnRight;", &pctlCurrent.bTurnRight); + _pShell->DeclareSymbol("user INDEX ctl_bTurnUp;", &pctlCurrent.bTurnUp); + _pShell->DeclareSymbol("user INDEX ctl_bTurnDown;", &pctlCurrent.bTurnDown); + _pShell->DeclareSymbol("user INDEX ctl_bTurnBankingLeft;", &pctlCurrent.bTurnBankingLeft); + _pShell->DeclareSymbol("user INDEX ctl_bTurnBankingRight;", &pctlCurrent.bTurnBankingRight); + _pShell->DeclareSymbol("user INDEX ctl_bCenterView;", &pctlCurrent.bCenterView); + _pShell->DeclareSymbol("user INDEX ctl_bLookLeft;", &pctlCurrent.bLookLeft); + _pShell->DeclareSymbol("user INDEX ctl_bLookRight;", &pctlCurrent.bLookRight); + _pShell->DeclareSymbol("user INDEX ctl_bLookUp;", &pctlCurrent.bLookUp); + _pShell->DeclareSymbol("user INDEX ctl_bLookDown;", &pctlCurrent.bLookDown); + _pShell->DeclareSymbol("user INDEX ctl_bLookBankingLeft;", &pctlCurrent.bLookBankingLeft); + _pShell->DeclareSymbol("user INDEX ctl_bLookBankingRight;", &pctlCurrent.bLookBankingRight ); + _pShell->DeclareSymbol("user INDEX ctl_bWalk;", &pctlCurrent.bWalk); + _pShell->DeclareSymbol("user INDEX ctl_bStrafe;", &pctlCurrent.bStrafe); + _pShell->DeclareSymbol("user INDEX ctl_bFire;", &pctlCurrent.bFire); + _pShell->DeclareSymbol("user INDEX ctl_bReload;", &pctlCurrent.bReload); + _pShell->DeclareSymbol("user INDEX ctl_bUse;", &pctlCurrent.bUse); + _pShell->DeclareSymbol("user INDEX ctl_bComputer;", &pctlCurrent.bComputer); + _pShell->DeclareSymbol("user INDEX ctl_bUseOrComputer;", &pctlCurrent.bUseOrComputer); + _pShell->DeclareSymbol("user INDEX ctl_b3rdPersonView;", &pctlCurrent.b3rdPersonView); + _pShell->DeclareSymbol("user INDEX ctl_bWeaponNext;", &pctlCurrent.bWeaponNext); + _pShell->DeclareSymbol("user INDEX ctl_bWeaponPrev;", &pctlCurrent.bWeaponPrev); + _pShell->DeclareSymbol("user INDEX ctl_bWeaponFlip;", &pctlCurrent.bWeaponFlip); + _pShell->DeclareSymbol("user INDEX ctl_bSelectWeapon[30+1];", &pctlCurrent.bSelectWeapon); + _pShell->DeclareSymbol("persistent user FLOAT ctl_tmComputerDoubleClick;", &ctl_tmComputerDoubleClick); + _pShell->DeclareSymbol("persistent user FLOAT ctl_fButtonRotationSpeedH;", &ctl_fButtonRotationSpeedH); + _pShell->DeclareSymbol("persistent user FLOAT ctl_fButtonRotationSpeedP;", &ctl_fButtonRotationSpeedP); + _pShell->DeclareSymbol("persistent user FLOAT ctl_fButtonRotationSpeedB;", &ctl_fButtonRotationSpeedB); + _pShell->DeclareSymbol("persistent user FLOAT ctl_fAxisStrafingModifier;", &ctl_fAxisStrafingModifier); + //new + _pShell->DeclareSymbol("user INDEX ctl_bSniperZoomIn;", &pctlCurrent.bSniperZoomIn); + _pShell->DeclareSymbol("user INDEX ctl_bSniperZoomOut;", &pctlCurrent.bSniperZoomOut); + _pShell->DeclareSymbol("user INDEX ctl_bFireBomb;", &pctlCurrent.bFireBomb); + + _pShell->DeclareSymbol("user FLOAT plr_fSwimSoundDelay;", &plr_fSwimSoundDelay); + _pShell->DeclareSymbol("user FLOAT plr_fDiveSoundDelay;", &plr_fDiveSoundDelay); + _pShell->DeclareSymbol("user FLOAT plr_fWalkSoundDelay;", &plr_fWalkSoundDelay); + _pShell->DeclareSymbol("user FLOAT plr_fRunSoundDelay;", &plr_fRunSoundDelay); + + _pShell->DeclareSymbol("persistent user FLOAT cli_fPredictPlayersRange;",&cli_fPredictPlayersRange); + _pShell->DeclareSymbol("persistent user FLOAT cli_fPredictItemsRange;", &cli_fPredictItemsRange ); + _pShell->DeclareSymbol("persistent user FLOAT cli_tmPredictFoe;", &cli_tmPredictFoe ); + _pShell->DeclareSymbol("persistent user FLOAT cli_tmPredictAlly;", &cli_tmPredictAlly ); + _pShell->DeclareSymbol("persistent user FLOAT cli_tmPredictEnemy;", &cli_tmPredictEnemy ); + + _pShell->DeclareSymbol(" INDEX hud_bShowAll;", &hud_bShowAll); + _pShell->DeclareSymbol("user INDEX hud_bShowInfo;", &hud_bShowInfo); + _pShell->DeclareSymbol("user const FLOAT net_tmLatencyAvg;", &net_tmLatencyAvg); + _pShell->DeclareSymbol("persistent user INDEX hud_bShowLatency;", &hud_bShowLatency); + _pShell->DeclareSymbol("persistent user INDEX hud_iShowPlayers;", &hud_iShowPlayers); + _pShell->DeclareSymbol("persistent user INDEX hud_iSortPlayers;", &hud_iSortPlayers); + _pShell->DeclareSymbol("persistent user INDEX hud_bShowWeapon;", &hud_bShowWeapon); + _pShell->DeclareSymbol("persistent user INDEX hud_bShowMessages;",&hud_bShowMessages); + _pShell->DeclareSymbol("persistent user FLOAT hud_fScaling;", &hud_fScaling); + _pShell->DeclareSymbol("persistent user FLOAT hud_fOpacity;", &hud_fOpacity); + _pShell->DeclareSymbol("persistent user FLOAT hud_tmWeaponsOnScreen;", &hud_tmWeaponsOnScreen); + _pShell->DeclareSymbol("persistent user FLOAT hud_tmLatencySnapshot;", &hud_tmLatencySnapshot); + _pShell->DeclareSymbol("persistent user FLOAT plr_fBreathingStrength;", &plr_fBreathingStrength); + _pShell->DeclareSymbol("INDEX cht_bKillFinalBoss;", &cht_bKillFinalBoss); + _pShell->DeclareSymbol("INDEX cht_bDebugFinalBoss;", &cht_bDebugFinalBoss); + _pShell->DeclareSymbol("INDEX cht_bDumpFinalBossData;", &cht_bDumpFinalBossData); + _pShell->DeclareSymbol("INDEX cht_bDebugFinalBossAnimations;", &cht_bDebugFinalBossAnimations); + _pShell->DeclareSymbol("INDEX cht_bDumpPlayerShading;", &cht_bDumpPlayerShading); + _pShell->DeclareSymbol("persistent user INDEX hud_bShowMatchInfo;", &hud_bShowMatchInfo); + + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilSpeed[17];", &wpn_fRecoilSpeed); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilLimit[17];", &wpn_fRecoilLimit); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilDampUp[17];", &wpn_fRecoilDampUp); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilDampDn[17];", &wpn_fRecoilDampDn); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilOffset[17];", &wpn_fRecoilOffset); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilFactorP[17];", &wpn_fRecoilFactorP); + _pShell->DeclareSymbol("persistent user FLOAT wpn_fRecoilFactorZ[17];", &wpn_fRecoilFactorZ); + + // cheats + _pShell->DeclareSymbol("user INDEX cht_bGod;", &cht_bGod); + _pShell->DeclareSymbol("user INDEX cht_bFly;", &cht_bFly); + _pShell->DeclareSymbol("user INDEX cht_bGhost;", &cht_bGhost); + _pShell->DeclareSymbol("user INDEX cht_bInvisible;", &cht_bInvisible); + _pShell->DeclareSymbol("user INDEX cht_bGiveAll;", &cht_bGiveAll); + _pShell->DeclareSymbol("user INDEX cht_bKillAll;", &cht_bKillAll); + _pShell->DeclareSymbol("user INDEX cht_bOpen;", &cht_bOpen); + _pShell->DeclareSymbol("user INDEX cht_bAllMessages;", &cht_bAllMessages); + _pShell->DeclareSymbol("user FLOAT cht_fTranslationMultiplier ;", &cht_fTranslationMultiplier); + _pShell->DeclareSymbol("user INDEX cht_bRefresh;", &cht_bRefresh); + // this one is masqueraded cheat enable variable + _pShell->DeclareSymbol("INDEX cht_bEnable;", &cht_bEnable); + + // this cheat is always enabled + _pShell->DeclareSymbol("user INDEX cht_iGoToMarker;", &cht_iGoToMarker); + + // player speed and view parameters, not declared except in internal build + #if 0 + _pShell->DeclareSymbol("user FLOAT plr_fViewHeightStand;", &plr_fViewHeightStand); + _pShell->DeclareSymbol("user FLOAT plr_fViewHeightCrouch;",&plr_fViewHeightCrouch); + _pShell->DeclareSymbol("user FLOAT plr_fViewHeightSwim;", &plr_fViewHeightSwim); + _pShell->DeclareSymbol("user FLOAT plr_fViewHeightDive;", &plr_fViewHeightDive); + _pShell->DeclareSymbol("user FLOAT plr_fViewDampFactor;", &plr_fViewDampFactor); + _pShell->DeclareSymbol("user FLOAT plr_fViewDampLimitGroundUp;", &plr_fViewDampLimitGroundUp); + _pShell->DeclareSymbol("user FLOAT plr_fViewDampLimitGroundDn;", &plr_fViewDampLimitGroundDn); + _pShell->DeclareSymbol("user FLOAT plr_fViewDampLimitWater;", &plr_fViewDampLimitWater); + _pShell->DeclareSymbol("user FLOAT plr_fAcceleration;", &plr_fAcceleration); + _pShell->DeclareSymbol("user FLOAT plr_fDeceleration;", &plr_fDeceleration); + _pShell->DeclareSymbol("user FLOAT plr_fSpeedForward;", &plr_fSpeedForward); + _pShell->DeclareSymbol("user FLOAT plr_fSpeedBackward;", &plr_fSpeedBackward); + _pShell->DeclareSymbol("user FLOAT plr_fSpeedSide;", &plr_fSpeedSide); + _pShell->DeclareSymbol("user FLOAT plr_fSpeedUp;", &plr_fSpeedUp); + #endif + _pShell->DeclareSymbol("persistent user FLOAT plr_fFOV;", &plr_fFOV); + _pShell->DeclareSymbol("persistent user FLOAT plr_fFrontClipDistance;", &plr_fFrontClipDistance); + _pShell->DeclareSymbol("persistent user INDEX plr_bRenderPicked;", &plr_bRenderPicked); + _pShell->DeclareSymbol("persistent user INDEX plr_bRenderPickedParticles;", &plr_bRenderPickedParticles); + _pShell->DeclareSymbol("persistent user INDEX plr_bOnlySam;", &plr_bOnlySam); + _pShell->DeclareSymbol("persistent user INDEX ent_bReportBrokenChains;", &ent_bReportBrokenChains); + _pShell->DeclareSymbol("persistent user FLOAT ent_tmMentalIn ;", &ent_tmMentalIn ); + _pShell->DeclareSymbol("persistent user FLOAT ent_tmMentalOut ;", &ent_tmMentalOut ); + _pShell->DeclareSymbol("persistent user FLOAT ent_tmMentalFade;", &ent_tmMentalFade); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fEnvParticlesDensity;", &gfx_fEnvParticlesDensity); + _pShell->DeclareSymbol("persistent user FLOAT gfx_fEnvParticlesRange;", &gfx_fEnvParticlesRange); + + // player appearance interface + _pShell->DeclareSymbol("INDEX SetPlayerAppearance(INDEX, INDEX, INDEX, INDEX);", &SetPlayerAppearance); + + // call player weapons persistant variable initialization + extern void CPlayerWeapons_Init(void); + CPlayerWeapons_Init(); + + // initialize HUD + InitHUD(); + + // precache + CPlayer_Precache(); +} + +// clean up +void CPlayer_OnEndClass(void) +{ + EndHUD(); +} + +CTString GetDifficultyString(void) +{ + if (GetSP()->sp_bMental) { return TRANS("Mental"); } + + switch (GetSP()->sp_gdGameDifficulty) { + case CSessionProperties::GD_TOURIST: return TRANS("Tourist"); + case CSessionProperties::GD_EASY: return TRANS("Easy"); + default: + case CSessionProperties::GD_NORMAL: return TRANS("Normal"); + case CSessionProperties::GD_HARD: return TRANS("Hard"); + case CSessionProperties::GD_EXTREME: return TRANS("Serious"); + } +} +// armor & health constants getters + +FLOAT MaxArmor(void) +{ + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + return 300; + } else { + return 200; + } +} +FLOAT TopArmor(void) +{ + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + return 200; + } else { + return 100; + } +} +FLOAT MaxHealth(void) +{ + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + return 300; + } else { + return 200; + } +} +FLOAT TopHealth(void) +{ + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + return 200; + } else { + return 100; + } +} + +// info structure +static EntityInfo eiPlayerGround = { + EIBT_FLESH, 80.0f, + 0.0f, 1.7f, 0.0f, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; +static EntityInfo eiPlayerCrouch = { + EIBT_FLESH, 80.0f, + 0.0f, 1.2f, 0.0f, // source (eyes) + 0.0f, 0.7f, 0.0f, // target (body) +}; +static EntityInfo eiPlayerSwim = { + EIBT_FLESH, 40.0f, + 0.0f, 0.0f, 0.0f, // source (eyes) + 0.0f, 0.0f, 0.0f, // target (body) +}; + + +// animation light specific +#define LIGHT_ANIM_MINIGUN 2 +#define LIGHT_ANIM_TOMMYGUN 3 +#define LIGHT_ANIM_COLT_SHOTGUN 4 +#define LIGHT_ANIM_NONE 5 + +const char *NameForState(PlayerState pst) +{ + switch(pst) { + case PST_STAND: return "stand"; + case PST_CROUCH: return "crouch"; + case PST_FALL: return "fall"; + case PST_SWIM: return "swim"; + case PST_DIVE: return "dive"; + default: return "???"; + }; +} + + +// print explanation on how a player died +void PrintPlayerDeathMessage(CPlayer *ppl, const EDeath &eDeath) +{ + CTString strMyName = ppl->GetPlayerName(); + CEntity *penKiller = eDeath.eLastDamage.penInflictor; + // if killed by a valid entity + if (penKiller!=NULL) { + // if killed by a player + if (IsOfClass(penKiller, "Player")) { + // if not self + if (penKiller!=ppl) { + CTString strKillerName = ((CPlayer*)penKiller)->GetPlayerName(); + + if(eDeath.eLastDamage.dmtType==DMT_TELEPORT) { + CPrintF(TRANS("%s telefragged %s\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_CLOSERANGE) { + CPrintF(TRANS("%s cut %s into pieces\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_CHAINSAW) { + CPrintF(TRANS("%s cut %s into pieces\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_BULLET) { + CPrintF(TRANS("%s poured lead into %s\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_PROJECTILE || eDeath.eLastDamage.dmtType==DMT_EXPLOSION) { + CPrintF(TRANS("%s blew %s away\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_CANNONBALL) { + CPrintF(TRANS("%s smashed %s with a cannon\n"), strKillerName, strMyName); + } else if(eDeath.eLastDamage.dmtType==DMT_CANNONBALL_EXPLOSION) { + CPrintF(TRANS("%s nuked %s\n"), strKillerName, strMyName); + } else { + CPrintF(TRANS("%s killed %s\n"), strKillerName, strMyName); + } + } else { + // make message from damage type + switch(eDeath.eLastDamage.dmtType) { + case DMT_DROWNING: CPrintF(TRANS("%s drowned\n"), strMyName); break; + case DMT_BURNING: CPrintF(TRANS("%s burst into flames\n"), strMyName); break; + case DMT_SPIKESTAB: CPrintF(TRANS("%s fell into a spike-hole\n"), strMyName); break; + case DMT_FREEZING: CPrintF(TRANS("%s has frozen\n"), strMyName); break; + case DMT_ACID: CPrintF(TRANS("%s dissolved\n"), strMyName); break; + case DMT_PROJECTILE: + case DMT_EXPLOSION: + CPrintF(TRANS("%s blew himself away\n"), strMyName); break; + default: CPrintF(TRANS("%s has committed suicide\n"), strMyName); + } + } + // if killed by an enemy + } else if (IsDerivedFromClass(penKiller, "Enemy Base")) { + // check for telefrag first + if(eDeath.eLastDamage.dmtType==DMT_TELEPORT) { + CPrintF(TRANS("%s was telefragged\n"), strMyName); + return; + } + // describe how this enemy killed player + CPrintF("%s\n", (const char*)((CEnemyBase*)penKiller)->GetPlayerKillDescription(strMyName, eDeath)); + + // if killed by some other entity + } else { + // make message from damage type + switch(eDeath.eLastDamage.dmtType) { + case DMT_SPIKESTAB: CPrintF(TRANS("%s was pierced\n"), strMyName); break; + case DMT_BRUSH: CPrintF(TRANS("%s was squashed\n"), strMyName); break; + case DMT_ABYSS: CPrintF(TRANS("%s went over the edge\n"), strMyName); break; + case DMT_IMPACT: CPrintF(TRANS("%s swashed\n"), strMyName); break; + case DMT_HEAT: CPrintF(TRANS("%s stood in the sun for too long\n"), strMyName); break; + default: CPrintF(TRANS("%s passed away\n"), strMyName); + } + } + // if no entity pointer (shouldn't happen) + } else { + CPrintF(TRANS("%s is missing in action\n"), strMyName); + } +} + +%} + +class export CPlayer : CPlayerEntity { +name "Player"; +thumbnail ""; +features "ImplementsOnInitClass", "ImplementsOnEndClass", "CanBePredictable"; + +properties: + 1 CTString m_strName "Name" = "", + 2 COLOR m_ulLastButtons = 0x0, // buttons last pressed + 3 FLOAT m_fArmor = 0.0f, // armor + 4 CTString m_strGroup = "", // group name for world change + 5 INDEX m_ulKeys = 0, // mask for all picked-up keys + 6 FLOAT m_fMaxHealth = 1, // default health supply player can have + 7 INDEX m_ulFlags = 0, // various flags + + 16 CEntityPointer m_penWeapons, // player weapons + 17 CEntityPointer m_penAnimator, // player animator + 18 CEntityPointer m_penView, // player view + 19 CEntityPointer m_pen3rdPersonView, // player 3rd person view + 20 INDEX m_iViewState=PVT_PLAYEREYES, // view state + 21 INDEX m_iLastViewState=PVT_PLAYEREYES, // last view state + + 26 CAnimObject m_aoLightAnimation, // light animation object + 27 FLOAT m_fDamageAmmount = 0.0f, // how much was last wound + 28 FLOAT m_tmWoundedTime = 0.0f, // when was last wound + 29 FLOAT m_tmScreamTime = 0.0f, // when was last wound sound played + + 33 INDEX m_iGender = GENDER_MALE, // male/female offset in various tables + 34 enum PlayerState m_pstState = PST_STAND, // current player state + 35 FLOAT m_fFallTime = 0.0f, // time passed when falling + 36 FLOAT m_fSwimTime = 0.0f, // time when started swimming + 45 FLOAT m_tmOutOfWater = 0.0f, // time when got out of water last time + 37 FLOAT m_tmMoveSound = 0.0f, // last time move sound was played + 38 BOOL m_bMoveSoundLeft = TRUE, // left or right walk channel is current + 39 FLOAT m_tmNextAmbientOnce = 0.0f, // next time to play local ambient sound + 43 FLOAT m_tmMouthSoundLast = 0.0f, // time last played some repeating mouth sound + + 40 CEntityPointer m_penCamera, // camera for current cinematic sequence, or null + 41 CTString m_strCenterMessage="", // center message + 42 FLOAT m_tmCenterMessageEnd = 0.0f, // last time to show centered message + 48 BOOL m_bPendingMessage = FALSE, // message sound pending to be played + 47 FLOAT m_tmMessagePlay = 0.0f, // when to play the message sound + 49 FLOAT m_tmAnalyseEnd = 0.0f, // last time to show analysation + 50 BOOL m_bComputerInvoked = FALSE, // set if computer was invoked at least once + 57 FLOAT m_tmAnimateInbox = -100.0f, // show animation of inbox icon animation + + 44 CEntityPointer m_penMainMusicHolder, + + 51 FLOAT m_tmLastDamage = -1.0f, + 52 FLOAT m_fMaxDamageAmmount = 0.0f, + 53 FLOAT3D m_vDamage = FLOAT3D(0,0,0), + 54 FLOAT m_tmSpraySpawned = -1.0f, + 55 FLOAT m_fSprayDamage = 0.0f, + 56 CEntityPointer m_penSpray, + + // sounds + 60 CSoundObject m_soWeapon0, + 61 CSoundObject m_soWeapon1, + 62 CSoundObject m_soWeapon2, + 63 CSoundObject m_soWeapon3, + 64 CSoundObject m_soWeaponAmbient, + 65 CSoundObject m_soPowerUpBeep, + + 70 CSoundObject m_soMouth, // breating, yelling etc. + 71 CSoundObject m_soFootL, // walking etc. + 72 CSoundObject m_soFootR, + 73 CSoundObject m_soBody, // splashing etc. + 74 CSoundObject m_soLocalAmbientLoop, // local ambient that only this player hears + 75 CSoundObject m_soLocalAmbientOnce, // local ambient that only this player hears + 76 CSoundObject m_soMessage, // message sounds + 77 CSoundObject m_soHighScore, // high score sound + 78 CSoundObject m_soSpeech, // for quotes + 79 CSoundObject m_soSniperZoom, // for sniper zoom sound + + 81 INDEX m_iMana = 0, // current score worth for killed player + 94 FLOAT m_fManaFraction = 0.0f,// fractional part of mana, for slow increase with time + 84 INDEX m_iHighScore = 0, // internal hiscore for demo playing + 85 INDEX m_iBeatenHighScore = 0, // hiscore that was beaten + 89 FLOAT m_tmLatency = 0.0f, // player-server latency (in seconds) + // for latency averaging + 88 FLOAT m_tmLatencyLastAvg = 0.0f, + 87 FLOAT m_tmLatencyAvgSum = 0.0f, + 86 INDEX m_ctLatencyAvg = 0, + + 96 BOOL m_bEndOfLevel = FALSE, + 97 BOOL m_bEndOfGame = FALSE, + 98 INDEX m_iMayRespawn = 0, // must get to 2 to be able to respawn + 99 FLOAT m_tmSpawned = 0.0f, // when player was spawned + 100 FLOAT3D m_vDied = FLOAT3D(0,0,0), // where player died (for respawn in-place) + 101 FLOAT3D m_aDied = FLOAT3D(0,0,0), + + // statistics + 103 FLOAT m_tmEstTime = 0.0f, // time estimated for this level + 105 INDEX m_iTimeScore = 0, + 106 INDEX m_iStartTime = 0, // game start time (ansi c time_t type) + 107 INDEX m_iEndTime = 0, // game end time (ansi c time_t type) + 108 FLOAT m_tmLevelStarted = 0.0f, // game time when level started + 93 CTString m_strLevelStats = "", // detailed statistics for each level + + // auto action vars + 110 CEntityPointer m_penActionMarker, // current marker for auto actions + 111 FLOAT m_fAutoSpeed = 0.0f, // speed to go towards the marker + 112 INDEX m_iAutoOrgWeapon = 0, // original weapon for autoactions + 113 FLOAT3D m_vAutoSpeed = FLOAT3D(0,0,0), + 114 FLOAT m_tmSpiritStart = 0.0f, + 115 FLOAT m_tmFadeStart = 0.0f, + + // 'picked up' display vars + 120 FLOAT m_tmLastPicked = -10000.0f, // when something was last picked up + 121 CTString m_strPickedName = "", // name of item picked + 122 FLOAT m_fPickedAmmount = 0.0f, // total picked ammount + 123 FLOAT m_fPickedMana = 0.0f, // total picked mana + + // shaker values + 130 INDEX m_iLastHealth = 0, + 131 INDEX m_iLastArmor = 0, + 132 INDEX m_iLastAmmo = 0, + 135 FLOAT m_tmHealthChanged = -9, + 136 FLOAT m_tmArmorChanged = -9, + 137 FLOAT m_tmAmmoChanged = -9, + + 138 FLOAT m_tmMinigunAutoFireStart = -1.0f, + + 150 FLOAT3D m_vLastStain = FLOAT3D(0,0,0), // where last stain was left + + // for mouse lag elimination via prescanning + 151 ANGLE3D m_aLastRotation = FLOAT3D(0,0,0), + 152 ANGLE3D m_aLastViewRotation = FLOAT3D(0,0,0), + 153 FLOAT3D m_vLastTranslation = FLOAT3D(0,0,0), + 154 ANGLE3D m_aLocalRotation = FLOAT3D(0,0,0), + 155 ANGLE3D m_aLocalViewRotation = FLOAT3D(0,0,0), + 156 FLOAT3D m_vLocalTranslation = FLOAT3D(0,0,0), + + // powerups (DO NOT CHANGE ORDER!) - needed by HUD.cpp + 160 FLOAT m_tmInvisibility = 0.0f, + 161 FLOAT m_tmInvulnerability = 0.0f, + 162 FLOAT m_tmSeriousDamage = 0.0f, + 163 FLOAT m_tmSeriousSpeed = 0.0f, + 166 FLOAT m_tmInvisibilityMax = 30.0f, + 167 FLOAT m_tmInvulnerabilityMax = 30.0f, + 168 FLOAT m_tmSeriousDamageMax = 40.0f, + 169 FLOAT m_tmSeriousSpeedMax = 20.0f, + + 180 FLOAT m_tmChainShakeEnd = 0.0f, // used to determine when to stop shaking due to chainsaw damage + 181 FLOAT m_fChainShakeStrength = 1.0f, // strength of shaking + 182 FLOAT m_fChainShakeFreqMod = 1.0f, // shaking frequency modifier + 183 FLOAT m_fChainsawShakeDX = 0.0f, + 184 FLOAT m_fChainsawShakeDY = 0.0f, + + 190 INDEX m_iSeriousBombCount = 0, // ammount of serious bombs player owns + 191 INDEX m_iLastSeriousBombCount = 0, // ammount of serious bombs player had before firing + 192 FLOAT m_tmSeriousBombFired = -10.0f, // when the bomb was last fired + +{ + ShellLaunchData ShellLaunchData_array; // array of data describing flying empty shells + INDEX m_iFirstEmptySLD; // index of last added empty shell + + BulletSprayLaunchData BulletSprayLaunchData_array; // array of data describing flying bullet sprays + INDEX m_iFirstEmptyBSLD; // index of last added bullet spray + + GoreSprayLaunchData GoreSprayLaunchData_array; // array of data describing gore sprays + INDEX m_iFirstEmptyGSLD; // index of last added gore spray + + ULONG ulButtonsNow; ULONG ulButtonsBefore; + ULONG ulNewButtons; + ULONG ulReleasedButtons; + + BOOL bUseButtonHeld; + + // listener + CSoundListener sliSound; + // light + CLightSource m_lsLightSource; + + TIME m_tmPredict; // time to predict the entity to + + // all messages in the inbox + CDynamicStackArray m_acmiMessages; + INDEX m_ctUnreadMessages; + + // statistics + PlayerStats m_psLevelStats; + PlayerStats m_psLevelTotal; + PlayerStats m_psGameStats; + PlayerStats m_psGameTotal; + + CModelObject m_moRender; // model object to render - this one can be customized +} + +components: + 1 class CLASS_PLAYER_WEAPONS "Classes\\PlayerWeapons.ecl", + 2 class CLASS_PLAYER_ANIMATOR "Classes\\PlayerAnimator.ecl", + 3 class CLASS_PLAYER_VIEW "Classes\\PlayerView.ecl", + 4 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 5 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + 6 class CLASS_SERIOUSBOMB "Classes\\SeriousBomb.ecl", + +// gender specific sounds - make sure that offset is exactly 100 + 50 sound SOUND_WATER_ENTER "Sounds\\Player\\WaterEnter.wav", + 51 sound SOUND_WATER_LEAVE "Sounds\\Player\\WaterLeave.wav", + 52 sound SOUND_WALK_L "Sounds\\Player\\WalkL.wav", + 53 sound SOUND_WALK_R "Sounds\\Player\\WalkR.wav", + 54 sound SOUND_SWIM_L "Sounds\\Player\\SwimL.wav", + 55 sound SOUND_SWIM_R "Sounds\\Player\\SwimR.wav", + 56 sound SOUND_DIVE_L "Sounds\\Player\\Dive.wav", + 57 sound SOUND_DIVE_R "Sounds\\Player\\Dive.wav", + 58 sound SOUND_DIVEIN "Sounds\\Player\\DiveIn.wav", + 59 sound SOUND_DIVEOUT "Sounds\\Player\\DiveOut.wav", + 60 sound SOUND_DROWN "Sounds\\Player\\Drown.wav", + 61 sound SOUND_INHALE0 "Sounds\\Player\\Inhale00.wav", + 62 sound SOUND_JUMP "Sounds\\Player\\Jump.wav", + 63 sound SOUND_LAND "Sounds\\Player\\Land.wav", + 66 sound SOUND_DEATH "Sounds\\Player\\Death.wav", + 67 sound SOUND_DEATHWATER "Sounds\\Player\\DeathWater.wav", + 70 sound SOUND_WATERWALK_L "Sounds\\Player\\WalkWaterL.wav", + 71 sound SOUND_WATERWALK_R "Sounds\\Player\\WalkWaterR.wav", + 72 sound SOUND_INHALE1 "Sounds\\Player\\Inhale01.wav", + 73 sound SOUND_INHALE2 "Sounds\\Player\\Inhale02.wav", + 75 sound SOUND_WALK_SAND_L "Sounds\\Player\\WalkSandL.wav", + 76 sound SOUND_WALK_SAND_R "Sounds\\Player\\WalkSandR.wav", +//178 sound SOUND_HIGHSCORE "Sounds\\Player\\HighScore.wav", + 80 sound SOUND_WOUNDWEAK "Sounds\\Player\\WoundWeak.wav", + 81 sound SOUND_WOUNDMEDIUM "Sounds\\Player\\WoundMedium.wav", + 82 sound SOUND_WOUNDSTRONG "Sounds\\Player\\WoundStrong.wav", + 85 sound SOUND_WOUNDWATER "Sounds\\Player\\WoundWater.wav", + 86 sound SOUND_WALK_GRASS_L "SoundsMP\\Player\\WalkGrassL.wav", + 87 sound SOUND_WALK_GRASS_R "SoundsMP\\Player\\WalkGrassR.wav", + 88 sound SOUND_WALK_WOOD_L "SoundsMP\\Player\\WalkWoodL.wav", + 89 sound SOUND_WALK_WOOD_R "SoundsMP\\Player\\WalkWoodR.wav", + 90 sound SOUND_WALK_SNOW_L "SoundsMP\\Player\\WalkSnowL.wav", + 91 sound SOUND_WALK_SNOW_R "SoundsMP\\Player\\WalkSnowR.wav", + 92 sound SOUND_BLOWUP "SoundsMP\\Player\\BlowUp.wav", + + +150 sound SOUND_F_WATER_ENTER "SoundsMP\\Player\\Female\\WaterEnter.wav", +151 sound SOUND_F_WATER_LEAVE "SoundsMP\\Player\\Female\\WaterLeave.wav", +152 sound SOUND_F_WALK_L "SoundsMP\\Player\\Female\\WalkL.wav", +153 sound SOUND_F_WALK_R "SoundsMP\\Player\\Female\\WalkR.wav", +154 sound SOUND_F_SWIM_L "SoundsMP\\Player\\Female\\SwimL.wav", +155 sound SOUND_F_SWIM_R "SoundsMP\\Player\\Female\\SwimR.wav", +156 sound SOUND_F_DIVE_L "SoundsMP\\Player\\Female\\Dive.wav", +157 sound SOUND_F_DIVE_R "SoundsMP\\Player\\Female\\Dive.wav", +158 sound SOUND_F_DIVEIN "SoundsMP\\Player\\Female\\DiveIn.wav", +159 sound SOUND_F_DIVEOUT "SoundsMP\\Player\\Female\\DiveOut.wav", +160 sound SOUND_F_DROWN "SoundsMP\\Player\\Female\\Drown.wav", +161 sound SOUND_F_INHALE0 "SoundsMP\\Player\\Female\\Inhale00.wav", +162 sound SOUND_F_JUMP "SoundsMP\\Player\\Female\\Jump.wav", +163 sound SOUND_F_LAND "SoundsMP\\Player\\Female\\Land.wav", +166 sound SOUND_F_DEATH "SoundsMP\\Player\\Female\\Death.wav", +167 sound SOUND_F_DEATHWATER "SoundsMP\\Player\\Female\\DeathWater.wav", +170 sound SOUND_F_WATERWALK_L "SoundsMP\\Player\\Female\\WalkWaterL.wav", +171 sound SOUND_F_WATERWALK_R "SoundsMP\\Player\\Female\\WalkWaterR.wav", +172 sound SOUND_F_INHALE1 "SoundsMP\\Player\\Female\\Inhale01.wav", +173 sound SOUND_F_INHALE2 "SoundsMP\\Player\\Female\\Inhale02.wav", +175 sound SOUND_F_WALK_SAND_L "SoundsMP\\Player\\Female\\WalkSandL.wav", +176 sound SOUND_F_WALK_SAND_R "SoundsMP\\Player\\Female\\WalkSandR.wav", +// 78 sound SOUND_F_HIGHSCORE "SoundsMP\\Player\\Female\\HighScore.wav", +180 sound SOUND_F_WOUNDWEAK "SoundsMP\\Player\\Female\\WoundWeak.wav", +181 sound SOUND_F_WOUNDMEDIUM "SoundsMP\\Player\\Female\\WoundMedium.wav", +182 sound SOUND_F_WOUNDSTRONG "SoundsMP\\Player\\Female\\WoundStrong.wav", +185 sound SOUND_F_WOUNDWATER "SoundsMP\\Player\\Female\\WoundWater.wav", +186 sound SOUND_F_WALK_GRASS_L "SoundsMP\\Player\\Female\\WalkGrassL.wav", +187 sound SOUND_F_WALK_GRASS_R "SoundsMP\\Player\\Female\\WalkGrassR.wav", +188 sound SOUND_F_WALK_WOOD_L "SoundsMP\\Player\\Female\\WalkWoodL.wav", +189 sound SOUND_F_WALK_WOOD_R "SoundsMP\\Player\\Female\\WalkWoodR.wav", +190 sound SOUND_F_WALK_SNOW_L "SoundsMP\\Player\\Female\\WalkSnowL.wav", +191 sound SOUND_F_WALK_SNOW_R "SoundsMP\\Player\\Female\\WalkSnowR.wav", + +// gender-independent sounds +200 sound SOUND_SILENCE "Sounds\\Misc\\Silence.wav", +201 sound SOUND_SNIPER_ZOOM "ModelsMP\\Weapons\\Sniper\\Sounds\\Zoom.wav", +206 sound SOUND_SNIPER_QZOOM "ModelsMP\\Weapons\\Sniper\\Sounds\\QuickZoom.wav", +202 sound SOUND_INFO "Sounds\\Player\\Info.wav", +203 sound SOUND_WATERAMBIENT "Sounds\\Player\\Underwater.wav", +204 sound SOUND_WATERBUBBLES "Sounds\\Player\\Bubbles.wav", +205 sound SOUND_POWERUP_BEEP "SoundsMP\\Player\\PowerUpBeep.wav", + +// ************** FLESH PARTS ************** +210 model MODEL_FLESH "Models\\Effects\\Debris\\Flesh\\Flesh.mdl", +211 model MODEL_FLESH_APPLE "Models\\Effects\\Debris\\Fruits\\Apple.mdl", +212 model MODEL_FLESH_BANANA "Models\\Effects\\Debris\\Fruits\\Banana.mdl", +213 model MODEL_FLESH_BURGER "Models\\Effects\\Debris\\Fruits\\CheeseBurger.mdl", +214 model MODEL_FLESH_LOLLY "Models\\Effects\\Debris\\Fruits\\LollyPop.mdl", +215 model MODEL_FLESH_ORANGE "Models\\Effects\\Debris\\Fruits\\Orange.mdl", + +220 texture TEXTURE_FLESH_RED "Models\\Effects\\Debris\\Flesh\\FleshRed.tex", +221 texture TEXTURE_FLESH_GREEN "Models\\Effects\\Debris\\Flesh\\FleshGreen.tex", +222 texture TEXTURE_FLESH_APPLE "Models\\Effects\\Debris\\Fruits\\Apple.tex", +223 texture TEXTURE_FLESH_BANANA "Models\\Effects\\Debris\\Fruits\\Banana.tex", +224 texture TEXTURE_FLESH_BURGER "Models\\Effects\\Debris\\Fruits\\CheeseBurger.tex", +225 texture TEXTURE_FLESH_LOLLY "Models\\Effects\\Debris\\Fruits\\LollyPop.tex", +226 texture TEXTURE_FLESH_ORANGE "Models\\Effects\\Debris\\Fruits\\Orange.tex", + + +functions: + + INDEX GenderSound(INDEX iSound) + { + return iSound+m_iGender*GENDEROFFSET; + } + + void AddBouble( FLOAT3D vPos, FLOAT3D vSpeedRelative) + { + ShellLaunchData &sld = m_asldData[m_iFirstEmptySLD]; + sld.sld_vPos = vPos; + const FLOATmatrix3D &m = GetRotationMatrix(); + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + sld.sld_vUp = vUp; + sld.sld_vSpeed = vSpeedRelative*m; + sld.sld_tmLaunch = _pTimer->CurrentTick(); + sld.sld_estType = ESL_BUBBLE; + // move to next shell position + m_iFirstEmptySLD = (m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + + void ClearShellLaunchData( void) + { + // clear flying shells data array + m_iFirstEmptySLD = 0; + for( INDEX iShell=0; iShellCurrentTick(); + bsld.bsld_vStretch=vStretch; + // move to bullet spray position + m_iFirstEmptyBSLD = (m_iFirstEmptyBSLD+1) % MAX_BULLET_SPRAYS; + } + + void ClearBulletSprayLaunchData( void) + { + m_iFirstEmptyBSLD = 0; + for( INDEX iBulletSpray=0; iBulletSprayCurrentTick(); + gsld.gsld_colParticles = colParticles; + // move to bullet spray position + m_iFirstEmptyGSLD = (m_iFirstEmptyGSLD+1) % MAX_GORE_SPRAYS; + } + + void ClearGoreSprayLaunchData( void) + { + m_iFirstEmptyGSLD = 0; + for( INDEX iGoreSpray=0; iGoreSpraym_moRender); + m_psLevelStats = penOther->m_psLevelStats; + m_psLevelTotal = penOther->m_psLevelTotal; + m_psGameStats = penOther->m_psGameStats ; + m_psGameTotal = penOther->m_psGameTotal ; + + // if creating predictor + if (ulFlags©_PREDICTOR) + { + // copy positions of launched empty shells + memcpy( m_asldData, penOther->m_asldData, sizeof( m_asldData)); + m_iFirstEmptySLD = penOther->m_iFirstEmptySLD; + // all messages in the inbox + m_acmiMessages.Clear(); + m_ctUnreadMessages = 0; + //m_lsLightSource; + SetupLightSource(); //? is this ok !!!! + + // if normal copying + } else { + // copy messages + m_acmiMessages = penOther->m_acmiMessages; + m_ctUnreadMessages = penOther->m_ctUnreadMessages; + } + } + + // update smoothed (average latency) + void UpdateLatency(FLOAT tmLatencyNow) + { + TIME tmNow = _pTimer->GetHighPrecisionTimer().GetSeconds(); + + // if not enough time passed + if (tmNowIsPlayerLocal(this)) { + en_tmPing = m_tmLatency; + net_tmLatencyAvg = en_tmPing; + } + } + + // check character data for invalid values + void ValidateCharacter(void) + { + // if in single player or flyover + if (GetSP()->sp_bSinglePlayer) { + // always use default model + CPlayerSettings *pps = (CPlayerSettings *)en_pcCharacter.pc_aubAppearance; + memset(pps->ps_achModelFile, 0, sizeof(pps->ps_achModelFile)); + } + } + // parse gender from your name + void ParseGender(CTString &strName) + { + if (strName.RemovePrefix("#male#")) { + m_iGender = GENDER_MALE; + } else if (strName.RemovePrefix("#female#")) { + m_iGender = GENDER_FEMALE; + } else { + m_iGender = GENDER_MALE; + } + } + + void CheckHighScore(void) + { + // if not playing a demo + if (!_pNetwork->IsPlayingDemo()) { + // update our local high score with the external + if (plr_iHiScore>m_iHighScore) { + m_iHighScore = plr_iHiScore; + } + } + + // if current score is better than highscore + if (m_psGameStats.ps_iScore>m_iHighScore) { + // if it is a highscore greater than the last one beaten + if (m_iHighScore>m_iBeatenHighScore) { + // remember that it was beaten + m_iBeatenHighScore = m_iHighScore; + // tell that to player + m_soHighScore.Set3DParameters(25.0f, 5.0f, 1.0f, 1.0f); + //PlaySound(m_soHighScore, SOUND_HIGHSCORE, 0); !!!!####!!!! + } + } + } + + CTString GetPredictName(void) const + { + if (IsPredicted()) { + return "PREDICTED"; + } else if (IsPredictor()) { + return "predictor"; + } else if (GetFlags()&ENF_WILLBEPREDICTED){ + return "WILLBEPREDICTED"; + } else { + return "no prediction"; + } + } + /* Write to stream. */ + void Write_t( CTStream *ostr) // throw char * + { + CPlayerEntity::Write_t(ostr); + // save array of messages + ostr->WriteID_t("MSGS"); + INDEX ctMsg = m_acmiMessages.Count(); + (*ostr)<Write_t(&m_psLevelStats, sizeof(m_psLevelStats)); + ostr->Write_t(&m_psLevelTotal, sizeof(m_psLevelTotal)); + ostr->Write_t(&m_psGameStats , sizeof(m_psGameStats )); + ostr->Write_t(&m_psGameTotal , sizeof(m_psGameTotal )); + } + /* Read from stream. */ + void Read_t( CTStream *istr) // throw char * + { + CPlayerEntity::Read_t(istr); + // clear flying shells data array + ClearShellLaunchData(); + ClearBulletSprayLaunchData(); + ClearGoreSprayLaunchData(); + // load array of messages + istr->ExpectID_t("MSGS"); + INDEX ctMsg; + (*istr)>>ctMsg; + m_acmiMessages.Clear(); + m_ctUnreadMessages = 0; + if( ctMsg>0) { + m_acmiMessages.Push(ctMsg); + for(INDEX iMsg=0; iMsgRead_t(&m_psLevelStats, sizeof(m_psLevelStats)); + istr->Read_t(&m_psLevelTotal, sizeof(m_psLevelTotal)); + istr->Read_t(&m_psGameStats , sizeof(m_psGameStats )); + istr->Read_t(&m_psGameTotal , sizeof(m_psGameTotal )); + + // set your real appearance if possible + ValidateCharacter(); + CTString strDummy; + SetPlayerAppearance(&m_moRender, &en_pcCharacter, strDummy, /*bPreview=*/FALSE); + ParseGender(strDummy); + m_ulFlags |= PLF_SYNCWEAPON; + // setup light source + SetupLightSource(); + }; + + /* Get static light source information. */ + CLightSource *GetLightSource(void) + { + if (!IsPredictor()) { + return &m_lsLightSource; + } else { + return NULL; + } + }; + + // called by other entities to set time prediction parameter + void SetPredictionTime(TIME tmAdvance) // give time interval in advance to set + { + m_tmPredict = _pTimer->CurrentTick()+tmAdvance; + } + + // called by engine to get the upper time limit + TIME GetPredictionTime(void) // return moment in time up to which to predict this entity + { + return m_tmPredict; + } + + // get maximum allowed range for predicting this entity + FLOAT GetPredictionRange(void) + { + return cli_fPredictPlayersRange; + } + + // add to prediction any entities that this entity depends on + void AddDependentsToPrediction(void) + { + m_penWeapons->AddToPrediction(); + m_penAnimator->AddToPrediction(); + m_penView->AddToPrediction(); + m_pen3rdPersonView->AddToPrediction(); + } + + // get in-game time for statistics + TIME GetStatsInGameTimeLevel(void) + { + if(m_bEndOfLevel) { + return m_psLevelStats.ps_tmTime; + } else { + return _pNetwork->GetGameTime()-m_tmLevelStarted; + } + } + TIME GetStatsInGameTimeGame(void) + { + if(m_bEndOfLevel) { + return m_psGameStats.ps_tmTime; + } else { + return m_psGameStats.ps_tmTime + (_pNetwork->GetGameTime()-m_tmLevelStarted); + } + } + + FLOAT GetStatsRealWorldTime(void) + { + time_t timeNow; + if(m_bEndOfLevel) { + timeNow = m_iEndTime; + } else { + time(&timeNow); + } + return (FLOAT)difftime( timeNow, m_iStartTime); + } + + CTString GetStatsRealWorldStarted(void) + { + struct tm *newtime; + newtime = localtime((const time_t*)&m_iStartTime); + + setlocale(LC_ALL, ""); + CTString strTimeline; + char achTimeLine[256]; + strftime( achTimeLine, sizeof(achTimeLine)-1, "%a %x %H:%M", newtime); + strTimeline = achTimeLine; + setlocale(LC_ALL, "C"); + return strTimeline; + } + + // fill in player statistics + export void GetStats( CTString &strStats, const CompStatType csType, INDEX ctCharsPerRow) + { + + // get proper type of stats + if( csType==CST_SHORT) { + GetShortStats(strStats); + } else { + ASSERT(csType==CST_DETAIL); + + strStats = "\n"; + _ctAlignWidth = Min(ctCharsPerRow, INDEX(60)); + + if (GetSP()->sp_bCooperative) { + if (GetSP()->sp_bSinglePlayer) { + GetDetailStatsSP(strStats, 0); + } else { + GetDetailStatsCoop(strStats); + } + } else { + GetDetailStatsDM(strStats); + } + } + } + + // get short one-line statistics - used for savegame descriptions and similar + void GetShortStats(CTString &strStats) + { + strStats.PrintF( TRANS("%s %s Score: %d Kills: %d/%d"), + GetDifficultyString(), TimeToString(GetStatsInGameTimeLevel()), + m_psLevelStats.ps_iScore, m_psLevelStats.ps_iKills, m_psLevelTotal.ps_iKills); + } + + // get detailed statistics for deathmatch game + void GetDetailStatsDM(CTString &strStats) + { + extern INDEX SetAllPlayersStats( INDEX iSortKey); + extern CPlayer *_apenPlayers[NET_MAXGAMEPLAYERS]; + // determine type of game + const BOOL bFragMatch = GetSP()->sp_bUseFrags; + + // fill players table + const INDEX ctPlayers = SetAllPlayersStats(bFragMatch?5:3); // sort by frags or by score + + // get time elapsed since the game start + strStats+=AlignString(CTString(0, "^cFFFFFF%s:^r\n%s", TRANS("TIME"), TimeToString(_pNetwork->GetGameTime()))); + strStats+="\n"; + + // find maximum frags/score that one player has + INDEX iMaxFrags = LowerLimit(INDEX(0)); + INDEX iMaxScore = LowerLimit(INDEX(0)); + {for(INDEX iPlayer=0; iPlayerm_psLevelStats.ps_iKills); + iMaxScore = Max(iMaxScore, penPlayer->m_psLevelStats.ps_iScore); + }} + + // print game limits + const CSessionProperties &sp = *GetSP(); + if (sp.sp_iTimeLimit>0) { + FLOAT fTimeLeft = ClampDn(sp.sp_iTimeLimit*60.0f - _pNetwork->GetGameTime(), 0.0f); + strStats+=AlignString(CTString(0, "^cFFFFFF%s:^r\n%s", TRANS("TIME LEFT"), TimeToString(fTimeLeft))); + strStats+="\n"; + } + if (bFragMatch && sp.sp_iFragLimit>0) { + INDEX iFragsLeft = ClampDn(sp.sp_iFragLimit-iMaxFrags, INDEX(0)); + strStats+=AlignString(CTString(0, "^cFFFFFF%s:^r\n%d", TRANS("FRAGS LEFT"), iFragsLeft)); + strStats+="\n"; + } + if (!bFragMatch && sp.sp_iScoreLimit>0) { + INDEX iScoreLeft = ClampDn(sp.sp_iScoreLimit-iMaxScore, INDEX(0)); + strStats+=AlignString(CTString(0, "^cFFFFFF%s:^r\n%d", TRANS("SCORE LEFT"), iScoreLeft)); + strStats+="\n"; + } + strStats += "\n"; + + CTString strRank = TRANS("NO."); + CTString strFrag = bFragMatch ? TRANS("FRAGS"):TRANS("SCORE"); + CTString strPing = TRANS("PING"); + CTString strName = TRANS("PLAYER"); + INDEX ctRankChars = Max(strRank.Length(), INDEX(3)) ; + INDEX ctFragChars = Max(strFrag.Length(), INDEX(7)) ; + INDEX ctPingChars = Max(strPing.Length(), INDEX(5)) ; + INDEX ctNameChars = Max(strName.Length(), INDEX(20)); + + // header + strStats += "^cFFFFFF"; + strStats += PadStringRight(strRank, ctRankChars)+" "; + strStats += PadStringLeft (strFrag, ctFragChars)+" "; + strStats += PadStringLeft (strPing, ctPingChars)+" "; + strStats += PadStringRight(strName, ctNameChars)+" "; + strStats += "^r"; + strStats += "\n\n"; + {for(INDEX iPlayer=0; iPlayeren_tmPing*1000.0f); + INDEX iScore = bFragMatch ? penPlayer->m_psLevelStats.ps_iKills : penPlayer->m_psLevelStats.ps_iScore; + CTString strName = penPlayer->GetPlayerName(); + + strStats += PadStringRight(CTString(0, "%d", iPlayer+1), ctRankChars)+" "; + strStats += PadStringLeft (CTString(0, "%d", iScore), ctFragChars)+" "; + strStats += PadStringLeft (CTString(0, "%d", iPing), ctPingChars)+" "; + strStats += PadStringRight(strName, ctNameChars)+" "; + strStats += "\n"; + }} + } + + // get singleplayer statistics + void GetDetailStatsCoop(CTString &strStats) + { + // first put in your full stats + strStats += "^b"+CenterString(TRANS("YOUR STATS"))+"^r\n"; + strStats+="\n"; + GetDetailStatsSP(strStats, 1); + + // get stats from all players + extern INDEX SetAllPlayersStats( INDEX iSortKey); + extern CPlayer *_apenPlayers[NET_MAXGAMEPLAYERS]; + const INDEX ctPlayers = SetAllPlayersStats(3); // sort by score + + // for each player + PlayerStats psSquadLevel = PlayerStats(); + PlayerStats psSquadGame = PlayerStats(); + {for( INDEX iPlayer=0; iPlayerm_psLevelStats; + PlayerStats psGame = penPlayer->m_psGameStats ; + psSquadLevel.ps_iScore += psLevel.ps_iScore ; + psSquadLevel.ps_iKills += psLevel.ps_iKills ; + psSquadLevel.ps_iDeaths += psLevel.ps_iDeaths ; + psSquadLevel.ps_iSecrets += psLevel.ps_iSecrets ; + psSquadGame.ps_iScore += psGame.ps_iScore ; + psSquadGame.ps_iKills += psGame.ps_iKills ; + psSquadGame.ps_iDeaths += psGame.ps_iDeaths ; + psSquadGame.ps_iSecrets += psGame.ps_iSecrets ; + }} + + // add squad stats + strStats+="\n"; + strStats += "^b"+CenterString(TRANS("SQUAD TOTAL"))+"^r\n"; + strStats+="\n"; + strStats+=CTString(0, "^cFFFFFF%s^r", TranslateConst(en_pwoWorld->GetName(), 0)); + strStats+="\n"; + strStats+=AlignString(CTString(0, " %s:\n%d", TRANS("SCORE"), psSquadLevel.ps_iScore)); + strStats+="\n"; + strStats+=AlignString(CTString(0, " %s:\n%d", TRANS("DEATHS"), psSquadLevel.ps_iDeaths)); + strStats+="\n"; + strStats+=AlignString(CTString(0, " %s:\n%d/%d", TRANS("KILLS"), psSquadLevel.ps_iKills, m_psLevelTotal.ps_iKills)); + strStats+="\n"; + strStats+=AlignString(CTString(0, " %s:\n%d/%d", TRANS("SECRETS"), psSquadLevel.ps_iSecrets, m_psLevelTotal.ps_iSecrets)); + strStats+="\n"; + strStats+="\n"; + strStats+=CTString("^cFFFFFF")+TRANS("TOTAL")+"^r\n"; + strStats+=AlignString(CTString(0, " %s:\n%d", TRANS("SCORE"), psSquadGame.ps_iScore)); + strStats+="\n"; + strStats+=AlignString(CTString(0, " %s:\n%d", TRANS("DEATHS"), psSquadGame.ps_iDeaths)); + strStats+="\n"; + strStats+=AlignString(CTString(0, " %s:\n%d/%d", TRANS("KILLS"), psSquadGame.ps_iKills, m_psGameTotal.ps_iKills)); + strStats+="\n"; + strStats+=AlignString(CTString(0, " %s:\n%d/%d", TRANS("SECRETS"), psSquadGame.ps_iSecrets, m_psGameTotal.ps_iSecrets)); + strStats+="\n"; + strStats+="\n"; + + + strStats+="\n"; + strStats += "^b"+CenterString(TRANS("OTHER PLAYERS"))+"^r\n"; + strStats+="\n"; + + // for each player + {for(INDEX iPlayer=0; iPlayerGetPlayerName())+"^r\n\n"; + penPlayer->GetDetailStatsSP(strStats, 2); + strStats+="\n"; + }} + } + + // get singleplayer statistics + void GetDetailStatsSP(CTString &strStats, INDEX iCoopType) + { + if (iCoopType<=1) { + if (m_bEndOfGame) { + if (GetSP()->sp_gdGameDifficulty==CSessionProperties::GD_EXTREME) { + strStats+=TRANS("^f4SERIOUS GAME FINISHED,\nMENTAL MODE IS NOW ENABLED!^F\n\n"); + } else if (GetSP()->sp_bMental) { + strStats+=TRANS("^f4YOU HAVE MASTERED THE GAME!^F\n\n"); + } + } + } + + if (iCoopType<=1) { + // report total score info + strStats+=AlignString(CTString(0, "^cFFFFFF%s:^r\n%d", TRANS("TOTAL SCORE"), m_psGameStats.ps_iScore)); + strStats+="\n"; + strStats+=AlignString(CTString(0, "^cFFFFFF%s:^r\n%s", TRANS("DIFFICULTY"), GetDifficultyString())); + strStats+="\n"; + strStats+=AlignString(CTString(0, "^cFFFFFF%s:^r\n%s", TRANS("STARTED"), GetStatsRealWorldStarted())); + strStats+="\n"; + strStats+=AlignString(CTString(0, "^cFFFFFF%s:^r\n%s", TRANS("PLAYING TIME"), TimeToString(GetStatsRealWorldTime()))); + strStats+="\n"; + if( m_psGameStats.ps_iScore<=plr_iHiScore) { + strStats+=AlignString(CTString(0, "^cFFFFFF%s:^r\n%d", TRANS("HI-SCORE"), plr_iHiScore)); + } else { + strStats+=TRANS("YOU BEAT THE HI-SCORE!"); + } + strStats+="\n\n"; + } + + // report this level statistics + strStats+=CTString(0, "^cFFFFFF%s^r", TranslateConst(en_pwoWorld->GetName(), 0)); + strStats+="\n"; + if (iCoopType<=1) { + if( m_bEndOfLevel) { + strStats+=AlignString(CTString(0, " %s:\n%s", TRANS("ESTIMATED TIME"), TimeToString(m_tmEstTime))); + strStats+="\n"; + strStats+=AlignString(CTString(0, " %s:\n%d", TRANS("TIME BONUS"), m_iTimeScore)); + strStats+="\n"; + strStats+="\n"; + } +// } else { +// strStats+=CTString("^cFFFFFF")+TRANS("THIS LEVEL")+"^r\n"; + } + strStats+=AlignString(CTString(0, " %s:\n%d", TRANS("SCORE"), m_psLevelStats.ps_iScore)); + strStats+="\n"; + strStats+=AlignString(CTString(0, " %s:\n%d/%d", TRANS("KILLS"), m_psLevelStats.ps_iKills, m_psLevelTotal.ps_iKills)); + strStats+="\n"; + if (iCoopType>=1) { + strStats+=AlignString(CTString(0, " %s:\n%d", TRANS("DEATHS"), m_psLevelStats.ps_iDeaths, m_psLevelTotal.ps_iDeaths)); + strStats+="\n"; + } + strStats+=AlignString(CTString(0, " %s:\n%d/%d", TRANS("SECRETS"), m_psLevelStats.ps_iSecrets, m_psLevelTotal.ps_iSecrets)); + strStats+="\n"; + if (iCoopType<=1) { + strStats+=AlignString(CTString(0, " %s:\n%s", TRANS("TIME"), TimeToString(GetStatsInGameTimeLevel()))); + strStats+="\n"; + } + strStats+="\n"; + + // report total game statistics + strStats+=CTString("^cFFFFFF")+TRANS("TOTAL")+"^r"; + strStats+="\n"; + strStats+=AlignString(CTString(0, " %s:\n%d", TRANS("SCORE"), m_psGameStats.ps_iScore)); + strStats+="\n"; + strStats+=AlignString(CTString(0, " %s:\n%d/%d", TRANS("KILLS"), m_psGameStats.ps_iKills, m_psGameTotal.ps_iKills)); + strStats+="\n"; + if (iCoopType>=1) { + strStats+=AlignString(CTString(0, " %s:\n%d", TRANS("DEATHS"), m_psGameStats.ps_iDeaths, m_psGameTotal.ps_iDeaths)); + strStats+="\n"; + } + strStats+=AlignString(CTString(0, " %s:\n%d/%d", TRANS("SECRETS"), m_psGameStats.ps_iSecrets, m_psGameTotal.ps_iSecrets)); + strStats+="\n"; + if (iCoopType<=1) { + strStats+=AlignString(CTString(0, " %s:\n%s", TRANS("GAME TIME"), TimeToString(GetStatsInGameTimeGame()))); + strStats+="\n"; + } + strStats+="\n"; + + // set per level outputs + if (iCoopType<1) { + if(m_strLevelStats!="") { + strStats += CTString("^cFFFFFF")+TRANS("Per level statistics") +"^r\n\n" + m_strLevelStats; + } + } + } + + // provide info for GameAgent enumeration + void GetGameAgentPlayerInfo( INDEX iPlayer, CTString &strOut) + { + CTString strPlayerName = GetPlayerName(); + INDEX iLen = strlen(strPlayerName); + for(INDEX i=0; isp_bUseFrags) { + strKey.PrintF("frags_%d\x02%d\x03", iPlayer, m_psLevelStats.ps_iKills); + strOut+=strKey; + } else { + strKey.PrintF("frags_%d\x02%d\x03", iPlayer, m_psLevelStats.ps_iScore); + strOut+=strKey; + } + strKey.PrintF("ping_%d\x02%d\x03", iPlayer, INDEX(ceil(en_tmPing*1000.0f))); + strOut+=strKey; + }; + + // check if message is in inbox + BOOL HasMessage( const CTFileName &fnmMessage) + { + ULONG ulHash = fnmMessage.GetHash(); + INDEX ctMsg = m_acmiMessages.Count(); + for(INDEX iMsg=0; iMsgCurrentTick()+2.0f; + m_soMessage.Set3DParameters(25.0f, 5.0f, 1.0f, 1.0f); + PlaySound(m_soMessage, SOUND_INFO, SOF_3D|SOF_VOLUMETRIC|SOF_LOCAL); + } + } + + void SayVoiceMessage(const CTFileName &fnmMessage) + { + if (GetSettings()->ps_ulFlags&PSF_NOQUOTES) { + return; + } + SetSpeakMouthPitch(); + PlaySound( m_soSpeech, fnmMessage, SOF_3D|SOF_VOLUMETRIC); + } + + // receive all messages in one directory - cheat + void CheatAllMessagesDir(const CTString &strDir, ULONG ulFlags) + { + // list the directory + CDynamicStackArray afnmDir; + MakeDirList(afnmDir, strDir, "*.txt", DLI_RECURSIVE); + + // for each file in the directory + for (INDEX i=0; iCurrentTick() > m_tmLastPicked+PICKEDREPORT_TIME) { + // kill the name + m_strPickedName = ""; + // reset picked mana + m_fPickedMana = 0; + } + // if different than last picked + if (m_strPickedName!=strName) { + // remember name + m_strPickedName = strName; + // reset picked ammount + m_fPickedAmmount = 0; + } + // increase ammount + m_fPickedAmmount+=fAmmount; + m_tmLastPicked = _pTimer->CurrentTick(); + } + + // Setup light source + void SetupLightSource(void) + { + // setup light source + CLightSource lsNew; + lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC; + lsNew.ls_rHotSpot = 1.0f; + lsNew.ls_colColor = C_WHITE; + lsNew.ls_rFallOff = 2.5f; + lsNew.ls_plftLensFlare = NULL; + lsNew.ls_ubPolygonalMask = 0; + lsNew.ls_paoLightAnimation = &m_aoLightAnimation; + + m_lsLightSource.ls_penEntity = this; + m_lsLightSource.SetLightSource(lsNew); + }; + + // play light animation + void PlayLightAnim(INDEX iAnim, ULONG ulFlags) { + if (m_aoLightAnimation.GetData()!=NULL) { + m_aoLightAnimation.PlayAnim(iAnim, ulFlags); + } + }; + + + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + if( cht_bDumpPlayerShading) + { + ANGLE3D a3dHPB; + DirectionVectorToAngles(-vLightDirection, a3dHPB); + UBYTE ubAR, ubAG, ubAB; + UBYTE ubCR, ubCG, ubCB; + ColorToRGB(colAmbient, ubAR, ubAG, ubAB); + ColorToRGB(colLight, ubCR, ubCG, ubCB); + CPrintF("Ambient: %d,%d,%d, Color: %d,%d,%d, Direction HPB (%g,%g,%g)\n", + ubAR, ubAG, ubAB, ubCR, ubCG, ubCB, a3dHPB(1), a3dHPB(2), a3dHPB(3)); + } + + // make models at least a bit bright in deathmatch + if (!GetSP()->sp_bCooperative) { + UBYTE ubH, ubS, ubV; + ColorToHSV(colAmbient, ubH, ubS, ubV); + if (ubV<22) { + ubV = 22; + colAmbient = HSVToColor(ubH, ubS, ubV); + } + } + + return CPlayerEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + }; + + // get a different model object for rendering + CModelObject *GetModelForRendering(void) + { + // if not yet initialized + if(!(m_ulFlags&PLF_INITIALIZED)) { + // return base model + return GetModelObject(); + } + + // lerp player viewpoint + CPlacement3D plView; + plView.Lerp(en_plLastViewpoint, en_plViewpoint, _pTimer->GetLerpFactor()); + // body and head attachment animation + ((CPlayerAnimator&)*m_penAnimator).BodyAndHeadOrientation(plView); + ((CPlayerAnimator&)*m_penAnimator).OnPreRender(); + // synchronize your appearance with the default model + m_moRender.Synchronize(*GetModelObject()); + if (m_ulFlags&PLF_SYNCWEAPON) { + m_ulFlags &= ~PLF_SYNCWEAPON; + GetPlayerAnimator()->SyncWeapon(); + } + + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + + FLOAT fFading = 1.0f; + if (m_tmFadeStart!=0) { + FLOAT fFactor = (tmNow-m_tmFadeStart)/5.0f; + fFactor = Clamp(fFactor, 0.0f, 1.0f); + fFading*=fFactor; + } + + // if invunerable after spawning + FLOAT tmSpawnInvulnerability = GetSP()->sp_tmSpawnInvulnerability; + if (tmSpawnInvulnerability>0 && tmNow-m_tmSpawnedtmNow) { + FLOAT fIntensity=0.0f; + if((m_tmInvisibility-tmNow)<3.0f) + { + fIntensity = 0.5f-0.5f*cos((m_tmInvisibility-tmNow)*(6.0f*3.1415927f/3.0f)); + } + if (_ulPlayerRenderingMask == 1<GetEntityWithName("MusicHolder", 0); + } + } + + // update per-level stats + void UpdateLevelStats(void) + { + // clear stats for this level + m_psLevelStats = PlayerStats(); + + // get music holder + if (m_penMainMusicHolder==NULL) { + return; + } + CMusicHolder &mh = (CMusicHolder&)*m_penMainMusicHolder; + + // assure proper count enemies in current world + if (mh.m_ctEnemiesInWorld==0) { + mh.CountEnemies(); + } + // set totals for level and increment for game + m_psLevelTotal.ps_iKills = mh.m_ctEnemiesInWorld; + m_psGameTotal.ps_iKills += mh.m_ctEnemiesInWorld; + m_psLevelTotal.ps_iSecrets = mh.m_ctSecretsInWorld; + m_psGameTotal.ps_iSecrets += mh.m_ctSecretsInWorld; + } + + // check if there is fuss + BOOL IsFuss(void) + { + // if no music holder + if (m_penMainMusicHolder==NULL) { + // no fuss + return FALSE; + } + // if no enemies - no fuss + return ((CMusicHolder*)&*m_penMainMusicHolder)->m_cenFussMakers.Count()>0; + } + + void SetDefaultMouthPitch(void) + { + m_soMouth.Set3DParameters(50.0f, 10.0f, 1.0f, 1.0f); + } + void SetRandomMouthPitch(FLOAT fMin, FLOAT fMax) + { + m_soMouth.Set3DParameters(50.0f, 10.0f, 1.0f, Lerp(fMin, fMax, FRnd())); + } + void SetSpeakMouthPitch(void) + { + m_soSpeech.Set3DParameters(50.0f, 10.0f, 2.0f, 1.0f); + } + + // added: also shake view because of chainsaw firing + void ApplyShaking(CPlacement3D &plViewer) + { + // chainsaw shaking + FLOAT fT = _pTimer->GetLerpedCurrentTick(); + if (fTm_tmShakeStarted<0) { + return; + } + + TIME tm = _pTimer->GetLerpedCurrentTick()-pwsc->m_tmShakeStarted; + if (tm<0) { + return; + } + FLOAT fDistance = (plViewer.pl_PositionVector-pwsc->m_vShakePos).Length(); + FLOAT fIntensity = IntensityAtDistance(pwsc->m_fShakeFalloff, 0, fDistance); + FLOAT fShakeY, fShakeB, fShakeZ; + if (!pwsc->m_bShakeFadeIn) { + fShakeY = SinFast(tm*pwsc->m_tmShakeFrequencyY*360.0f)* + exp(-tm*(pwsc->m_fShakeFade))* + fIntensity*pwsc->m_fShakeIntensityY; + fShakeB = SinFast(tm*pwsc->m_tmShakeFrequencyB*360.0f)* + exp(-tm*(pwsc->m_fShakeFade))* + fIntensity*pwsc->m_fShakeIntensityB; + fShakeZ = SinFast(tm*pwsc->m_tmShakeFrequencyZ*360.0f)* + exp(-tm*(pwsc->m_fShakeFade))* + fIntensity*pwsc->m_fShakeIntensityZ; + } else { + FLOAT ootm = 1.0f/tm; + fShakeY = SinFast(tm*pwsc->m_tmShakeFrequencyY*360.0f)* + exp((tm-2)*ootm*(pwsc->m_fShakeFade))* + fIntensity*pwsc->m_fShakeIntensityY; + fShakeB = SinFast(tm*pwsc->m_tmShakeFrequencyB*360.0f)* + exp((tm-2)*ootm*(pwsc->m_fShakeFade))* + fIntensity*pwsc->m_fShakeIntensityB; + fShakeZ = SinFast(tm*pwsc->m_tmShakeFrequencyZ*360.0f)* + exp((tm-2)*ootm*(pwsc->m_fShakeFade))* + fIntensity*pwsc->m_fShakeIntensityZ; + } + plViewer.pl_PositionVector(2) += fShakeY; + plViewer.pl_PositionVector(3) += fShakeZ; + plViewer.pl_OrientationAngle(3) += fShakeB; + + } + + COLOR GetWorldGlaring(void) + { + CWorldSettingsController *pwsc = GetWSC(this); + if (pwsc==NULL || pwsc->m_tmGlaringStarted<0) { + return 0; + } + TIME tm = _pTimer->GetLerpedCurrentTick(); + FLOAT fRatio = CalculateRatio(tm, pwsc->m_tmGlaringStarted, pwsc->m_tmGlaringEnded, + pwsc->m_fGlaringFadeInRatio, pwsc->m_fGlaringFadeOutRatio); + COLOR colResult = (pwsc->m_colGlade&0xFFFFFF00)|(UBYTE(fRatio*255.0f)); + return colResult; + } + + void RenderScroll(CDrawPort *pdp) + { + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL && pwsc->m_penScrollHolder!=NULL) + { + CScrollHolder &sch = (CScrollHolder &) *pwsc->m_penScrollHolder; + sch.Credits_Render(&sch, pdp); + } + } + + void RenderCredits(CDrawPort *pdp) + { + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL && pwsc->m_penCreditsHolder!=NULL) + { + CCreditsHolder &cch = (CCreditsHolder &) *pwsc->m_penCreditsHolder; + cch.Credits_Render(&cch, pdp); + } + } + + void RenderTextFX(CDrawPort *pdp) + { + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL && pwsc->m_penTextFXHolder!=NULL) + { + CTextFXHolder &tfx = (CTextFXHolder &) *pwsc->m_penTextFXHolder; + tfx.TextFX_Render(&tfx, pdp); + } + } + + void RenderHudPicFX(CDrawPort *pdp) + { + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL && pwsc->m_penHudPicFXHolder!=NULL) + { + CHudPicHolder &hpfx = (CHudPicHolder &) *pwsc->m_penHudPicFXHolder; + hpfx.HudPic_Render(&hpfx, pdp); + } + } + +/************************************************************ + * RENDER GAME VIEW * + ************************************************************/ + + // setup viewing parameters for viewing from player or camera + void SetupView(CDrawPort *pdp, CAnyProjection3D &apr, CEntity *&penViewer, + CPlacement3D &plViewer, COLOR &colBlend, BOOL bCamera) + { + // read the exact placement of the view for this tick + GetLerpedAbsoluteViewPlacement(plViewer); + ASSERT(IsValidFloat(plViewer.pl_OrientationAngle(1))&&IsValidFloat(plViewer.pl_OrientationAngle(2))&&IsValidFloat(plViewer.pl_OrientationAngle(3)) ); + // get current entity that the player views from + penViewer = GetViewEntity(); + + INDEX iViewState = m_iViewState; + + if (m_penCamera!=NULL && bCamera) { + iViewState = PVT_SCENECAMERA; + plViewer = m_penCamera->GetLerpedPlacement(); + penViewer = m_penCamera; + } + + // init projection parameters + CPerspectiveProjection3D prPerspectiveProjection; + plr_fFOV = Clamp( plr_fFOV, 1.0f, 160.0f); + ANGLE aFOV = plr_fFOV; + // disable zoom in deathmatch + if (!GetSP()->sp_bCooperative) { + aFOV = 90.0f; + } + // if sniper active + if (((CPlayerWeapons&)*m_penWeapons).m_iCurrentWeapon==WEAPON_SNIPER) + { + aFOV = Lerp(((CPlayerWeapons&)*m_penWeapons).m_fSniperFOVlast, + ((CPlayerWeapons&)*m_penWeapons).m_fSniperFOV, + _pTimer->GetLerpFactor()); + } + + if (m_pstState==PST_DIVE && iViewState == PVT_PLAYEREYES) { + TIME tmNow = _pTimer->GetLerpedCurrentTick(); + aFOV+=sin(tmNow*0.79f)*2.0f; + } + ApplyShaking(plViewer); + + colBlend = 0; + if (iViewState == PVT_SCENECAMERA) { + CCamera *pcm = (CCamera*)&*m_penCamera; + prPerspectiveProjection.FOVL() = + Lerp(pcm->m_fLastFOV, pcm->m_fFOV, _pTimer->GetLerpFactor()); + if (pcm->m_tmDelta>0.001f) { + FLOAT fFactor = (_pTimer->GetLerpedCurrentTick()-pcm->m_tmAtMarker)/pcm->m_tmDelta; + fFactor = Clamp( fFactor, 0.0f, 1.0f); + colBlend = LerpColor( pcm->m_colFade0, pcm->m_colFade1, fFactor); + } else { + colBlend = pcm->m_colFade0; + } + } else { + prPerspectiveProjection.FOVL() = aFOV; + } + prPerspectiveProjection.ScreenBBoxL() = FLOATaabbox2D( + FLOAT2D(0.0f, 0.0f), + FLOAT2D((FLOAT)pdp->GetWidth(), (FLOAT)pdp->GetHeight()) + ); + // determine front clip plane + plr_fFrontClipDistance = Clamp( plr_fFrontClipDistance, 0.05f, 0.50f); + FLOAT fFCD = plr_fFrontClipDistance; + // adjust front clip plane if swimming + if( m_pstState==PST_SWIM && iViewState==PVT_PLAYEREYES) { fFCD *= 0.6666f; } + prPerspectiveProjection.FrontClipDistanceL() = fFCD; + prPerspectiveProjection.AspectRatioL() = 1.0f; + // set up viewer position + apr = prPerspectiveProjection; + apr->ViewerPlacementL() = plViewer; + apr->ObjectPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + prPlayerProjection = apr; + prPlayerProjection->Prepare(); + } + + // listen from a given viewer + void ListenFromEntity(CEntity *penListener, const CPlacement3D &plSound) + { + FLOATmatrix3D mRotation; + MakeRotationMatrixFast(mRotation, plSound.pl_OrientationAngle); + sliSound.sli_vPosition = plSound.pl_PositionVector; + sliSound.sli_mRotation = mRotation; + sliSound.sli_fVolume = 1.0f; + sliSound.sli_vSpeed = en_vCurrentTranslationAbsolute; + sliSound.sli_penEntity = penListener; + if (m_pstState == PST_DIVE) { + sliSound.sli_fFilter = 20.0f; + } else { + sliSound.sli_fFilter = 0.0f; + } + INDEX iEnv = 0; + + CBrushSector *pbsc = penListener->GetSectorFromPoint(plSound.pl_PositionVector); + + // for each sector around listener + if (pbsc!=NULL) { + iEnv = pbsc->GetEnvironmentType(); + } + + // get the environment + CEnvironmentType &et = GetWorld()->wo_aetEnvironmentTypes[iEnv]; + sliSound.sli_iEnvironmentType = et.et_iType; + sliSound.sli_fEnvironmentSize = et.et_fSize; + _pSound->Listen(sliSound); + } + + // render dummy view (not connected yet) + void RenderDummyView(CDrawPort *pdp) + { + // clear screen + pdp->Fill( C_BLACK|CT_OPAQUE); + + // if not single player + if (!GetSP()->sp_bSinglePlayer) { + // print a message + PIX pixDPWidth = pdp->GetWidth(); + PIX pixDPHeight = pdp->GetHeight(); + FLOAT fScale = (FLOAT)pixDPWidth/640.0f; + pdp->SetFont( _pfdDisplayFont); + pdp->SetTextScaling( fScale); + pdp->SetTextAspect( 1.0f); + CTString strMsg; + strMsg.PrintF(TRANS("%s connected"), GetPlayerName()); + pdp->PutTextCXY( strMsg, pixDPWidth*0.5f, pixDPHeight*0.5f, SE_COL_BLUE_NEUTRAL_LT|CT_OPAQUE); + } + } + + // render view from player + void RenderPlayerView(CDrawPort *pdp, BOOL bShowExtras) + { + + CAnyProjection3D apr; + CEntity *penViewer; + CPlacement3D plViewer; + COLOR colBlend; + + // for each eye + for (INDEX iEye=STEREO_LEFT; iEye<=(Stereo_IsEnabled()?STEREO_RIGHT:STEREO_LEFT); iEye++) { + + // setup view settings + SetupView(pdp, apr, penViewer, plViewer, colBlend, FALSE); + + // setup stereo rendering + Stereo_SetBuffer(iEye); + Stereo_AdjustProjection(*apr, iEye, 1); + + // render the view + ASSERT(IsValidFloat(plViewer.pl_OrientationAngle(1))&&IsValidFloat(plViewer.pl_OrientationAngle(2))&&IsValidFloat(plViewer.pl_OrientationAngle(3))); + _ulPlayerRenderingMask = 1<GetWidth(); + PIX pixDPHeight = pdp->GetHeight(); + FLOAT fScale = (FLOAT)pixDPWidth/640.0f; + + // print center message + if (_pTimer->CurrentTick()SetFont( _pfdDisplayFont); + pdp->SetTextScaling( fScale); + pdp->SetTextAspect( 1.0f); + pdp->PutTextCXY( m_strCenterMessage, pixDPWidth*0.5f, pixDPHeight*0.85f, C_WHITE|0xDD); + // print picked item + } else if (_pTimer->CurrentTick()SetFont( _pfdDisplayFont); + pdp->SetTextScaling( fScale); + pdp->SetTextAspect( 1.0f); + CTString strPicked; + if (m_fPickedAmmount==0) { + strPicked = m_strPickedName; + } else { + strPicked.PrintF("%s +%d", m_strPickedName, int(m_fPickedAmmount)); + } + pdp->PutTextCXY( strPicked, pixDPWidth*0.5f, pixDPHeight*0.82f, C_WHITE|0xDD); + if (!GetSP()->sp_bCooperative && !GetSP()->sp_bUseFrags && m_fPickedMana>=1) { + CTString strValue; + strValue.PrintF("%s +%d", TRANS("Value"), INDEX(m_fPickedMana)); + pdp->PutTextCXY( strValue, pixDPWidth*0.5f, pixDPHeight*0.85f, C_WHITE|0xDD); + } + } + + if (_pTimer->CurrentTick()SetFont( _pfdDisplayFont); + pdp->SetTextScaling( fScale); + pdp->SetTextAspect( 1.0f); + UBYTE ubA = int(sin(_pTimer->CurrentTick()*10.0f)*127+128); + pdp->PutTextCXY( TRANS("Analyzing..."), pixDPWidth*0.5f, pixDPHeight*0.2f, SE_COL_BLUE_NEUTRAL_LT|ubA); + } + } + + // render view from camera + void RenderCameraView(CDrawPort *pdp, BOOL bListen) + { + CDrawPort dpCamera; + CDrawPort *pdpCamera = pdp; + if (m_penCamera!=NULL && ((CCamera&)*m_penCamera).m_bWideScreen) { + pdp->MakeWideScreen(&dpCamera); + pdpCamera = &dpCamera; + } + + pdp->Unlock(); + pdpCamera->Lock(); + + CAnyProjection3D apr; + CEntity *penViewer; + CPlacement3D plViewer; + COLOR colBlend; + + // for each eye + for (INDEX iEye=STEREO_LEFT; iEye<=(Stereo_IsEnabled()?STEREO_RIGHT:STEREO_LEFT); iEye++) { + + // setup view settings + SetupView(pdpCamera, apr, penViewer, plViewer, colBlend, TRUE); + + // setup stereo rendering + Stereo_SetBuffer(iEye); + Stereo_AdjustProjection(*apr, iEye, 1); + + // render the view + ASSERT(IsValidFloat(plViewer.pl_OrientationAngle(1))&&IsValidFloat(plViewer.pl_OrientationAngle(2))&&IsValidFloat(plViewer.pl_OrientationAngle(3))); + _ulPlayerRenderingMask = 1<dp_ulBlendingRA += ULONG(ubR)*ULONG(ubA); + pdpCamera->dp_ulBlendingGA += ULONG(ubG)*ULONG(ubA); + pdpCamera->dp_ulBlendingBA += ULONG(ubB)*ULONG(ubA); + pdpCamera->dp_ulBlendingA += ULONG(ubA); + } + // do all queued screen blendings + pdpCamera->BlendScreen(); + } + + pdpCamera->Unlock(); + pdp->Lock(); + + // camera fading + if ((colBlend&CT_AMASK)!=0) { + pdp->Fill(colBlend); + } + + // print center message + if (_pTimer->CurrentTick()GetWidth(); + PIX pixDPHeight = pdp->GetHeight(); + FLOAT fScale = (FLOAT)pixDPWidth/640.0f; + pdp->SetFont( _pfdDisplayFont); + pdp->SetTextScaling( fScale); + pdp->SetTextAspect( 1.0f); + pdp->PutTextCXY( m_strCenterMessage, pixDPWidth*0.5f, pixDPHeight*0.85f, C_WHITE|0xDD); + } + } + + + void RenderGameView(CDrawPort *pdp, void *pvUserData) + { + BOOL bShowExtras = (ULONG(pvUserData)&GRV_SHOWEXTRAS); + pdp->Unlock(); + + // if not yet initialized + if(!(m_ulFlags&PLF_INITIALIZED) || (m_ulFlags&PLF_DONTRENDER)) { + // render dummy view on the right drawport + CDrawPort dpView(pdp, TRUE); + if(dpView.Lock()) { + RenderDummyView(&dpView); + dpView.Unlock(); + } + pdp->Lock(); + return; + } + + // if rendering real game view (not thumbnail, or similar) + if (pvUserData!=0) { + // if rendered a game view recently + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + if ((tvNow-_tvProbingLast).GetSeconds()<0.1) { + // allow probing + _pGfx->gl_bAllowProbing = TRUE; + } + _tvProbingLast = tvNow; + } + + //CPrintF("%s: render\n", GetPredictName()); + + // check for dualhead + BOOL bDualHead = + pdp->IsDualHead() && + GetSP()->sp_gmGameMode!=CSessionProperties::GM_FLYOVER && + m_penActionMarker==NULL; + + // if dualhead, or no camera active + if (bDualHead||m_penCamera==NULL) { + // make left player view + CDrawPort dpView(pdp, TRUE); + if(dpView.Lock()) { + // draw it + RenderPlayerView(&dpView, bShowExtras); + dpView.Unlock(); + } + } + + // if camera active + if (m_penCamera!=NULL) { + // make left or right camera view + CDrawPort dpView(pdp, m_penActionMarker!=NULL); + if(dpView.Lock()) { + // draw it, listen if not dualhead + RenderCameraView(&dpView, !bDualHead); + dpView.Unlock(); + } + // if camera is not active + } else { + // if dualhead + if (bDualHead) { + // render computer on secondary display + cmp_ppenDHPlayer = this; + } + } + // all done - lock back the original drawport + pdp->Lock(); + }; + + + + +/************************************************************ + * PRE/DO/POST MOVING * + ************************************************************/ + + // premoving for soft player up-down movement + void PreMoving(void) { + /*CPrintF("pos(%s): %g,%g,%g\n", GetPredictName(), + GetPlacement().pl_PositionVector(1), + GetPlacement().pl_PositionVector(2), + GetPlacement().pl_PositionVector(3)); + */ + + ((CPlayerAnimator&)*m_penAnimator).StoreLast(); + CPlayerEntity::PreMoving(); + }; + + // do moving + void DoMoving(void) { + CPlayerEntity::DoMoving(); + ((CPlayerAnimator&)*m_penAnimator).AnimateBanking(); + + if (m_penView!=NULL) { + ((CPlayerView&)*m_penView).DoMoving(); + } + if (m_pen3rdPersonView!=NULL) { + ((CPlayerView&)*m_pen3rdPersonView).DoMoving(); + } + }; + + + // postmoving for soft player up-down movement + void PostMoving(void) + { + CPlayerEntity::PostMoving(); + // never allow a player to be removed from the list of movers + en_ulFlags &= ~ENF_INRENDERING; + + ((CPlayerAnimator&)*m_penAnimator).AnimateSoftEyes(); + //((CPlayerAnimator&)*m_penAnimator).AnimateRecoilPitch(); + + // slowly increase mana with time, faster if player is not moving; (only if alive) + if (GetFlags()&ENF_ALIVE) + { + m_fManaFraction += + ClampDn( 1.0f-en_vCurrentTranslationAbsolute.Length()/20.0f, 0.0f) * 20.0f + * _pTimer->TickQuantum; + INDEX iNewMana = m_fManaFraction; + m_iMana += iNewMana; + m_fManaFraction -= iNewMana; + } + + // if in tourist mode + if (GetSP()->sp_gdGameDifficulty==CSessionProperties::GD_TOURIST && GetFlags()&ENF_ALIVE) { + // slowly increase health with time + FLOAT fHealth = GetHealth(); + FLOAT fTopHealth = TopHealth(); + if (fHealthTickQuantum, fTopHealth)); // one unit per second + } + } + + // update ray hit for weapon target + GetPlayerWeapons()->UpdateTargetingInfo(); + + if (m_pen3rdPersonView!=NULL) { + ((CPlayerView&)*m_pen3rdPersonView).PostMoving(); + } + if (m_penView!=NULL) { + ((CPlayerView&)*m_penView).PostMoving(); + } + + // if didn't have any action in this tick + if (!(m_ulFlags&PLF_APPLIEDACTION)) { + // means we are not connected + SetUnconnected(); + } + + // clear action indicator + m_ulFlags&=~PLF_APPLIEDACTION; + } + + // set player parameters for unconnected state (between the server loads and player reconnects) + void SetUnconnected(void) + { + if (m_ulFlags&PLF_NOTCONNECTED) { + return; + } + m_ulFlags |= PLF_NOTCONNECTED; + + // reset to a dummy state + ForceFullStop(); + SetPhysicsFlags(GetPhysicsFlags() & ~(EPF_TRANSLATEDBYGRAVITY|EPF_ORIENTEDBYGRAVITY)); + SetCollisionFlags(GetCollisionFlags() & ~((ECBI_BRUSH|ECBI_MODEL)<BodyAnimationTemplate( + BODY_ANIM_NORMALWALK, BODY_ANIM_COLT_STAND, BODY_ANIM_SHOTGUN_STAND, BODY_ANIM_MINIGUN_STAND, + AOF_LOOPING|AOF_NORESTART); + } + + // set player parameters for connected state + void SetConnected(void) + { + if (!(m_ulFlags&PLF_NOTCONNECTED)) { + return; + } + m_ulFlags &= ~PLF_NOTCONNECTED; + + SetPhysicsFlags(GetPhysicsFlags() | (EPF_TRANSLATEDBYGRAVITY|EPF_ORIENTEDBYGRAVITY)); + SetCollisionFlags(GetCollisionFlags() | ((ECBI_BRUSH|ECBI_MODEL)<0) { + CRC_AddFLOAT(ulCRC, m_fManaFraction); + } + CRC_AddFLOAT(ulCRC, m_fArmor); + } + + + // dump sync data to text file + void DumpSync_t(CTStream &strm, INDEX iExtensiveSyncCheck) // throw char * + { + CPlayerEntity::DumpSync_t(strm, iExtensiveSyncCheck); + strm.FPrintF_t("Score: %d\n", m_psLevelStats.ps_iScore); + strm.FPrintF_t("m_iMana: %d\n", m_iMana); + strm.FPrintF_t("m_fManaFraction: %g(%08x)\n", m_fManaFraction, (ULONG&)m_fManaFraction); + strm.FPrintF_t("m_fArmor: %g(%08x)\n", m_fArmor, (ULONG&)m_fArmor); + } + +/************************************************************ + * DAMAGE OVERRIDE (PLAYER HAS ARMOR) * + ************************************************************/ + + + // leave stain + virtual void LeaveStain( BOOL bGrow) + { + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + // get your size + FLOATaabbox3D box; + GetBoundingBox(box); + + // on plane + if( GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + // if near to polygon and away from last stain point + if( (vPoint-GetPlacement().pl_PositionVector).Length()<0.5f + && (m_vLastStain-vPoint).Length()>1.0f ) { + m_vLastStain = vPoint; + FLOAT fStretch = box.Size().Length(); + ese.colMuliplier = C_WHITE|CT_OPAQUE; + // stain + if (bGrow) { + ese.betType = BET_BLOODSTAINGROW; + ese.vStretch = FLOAT3D( fStretch*1.5f, fStretch*1.5f, 1.0f); + } else { + ese.betType = BET_BLOODSTAIN; + ese.vStretch = FLOAT3D( fStretch*0.75f, fStretch*0.75f, 1.0f); + } + ese.vNormal = FLOAT3D( vPlaneNormal); + ese.vDirection = FLOAT3D( 0, 0, 0); + FLOAT3D vPos = vPoint+ese.vNormal/50.0f*(FRnd()+0.5f); + CEntityPointer penEffect = CreateEntity( CPlacement3D(vPos, ANGLE3D(0,0,0)), CLASS_BASIC_EFFECT); + penEffect->Initialize(ese); + } + } + }; + + + void DamageImpact(enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // if exploded + if (GetRenderType()!=RT_MODEL) { + // do nothing + return; + } + + if (dmtType == DMT_ABYSS || dmtType == DMT_SPIKESTAB) { + return; + } + + fDamageAmmount = Clamp(fDamageAmmount, 0.0f, 5000.0f); + + FLOAT fKickDamage = fDamageAmmount; + if( (dmtType == DMT_EXPLOSION) || (dmtType == DMT_IMPACT) || (dmtType == DMT_CANNONBALL_EXPLOSION) ) + { + fKickDamage*=1.5; + } + if (dmtType==DMT_DROWNING || dmtType==DMT_CLOSERANGE) { + fKickDamage /= 10; + } + if (dmtType==DMT_CHAINSAW) + { + fKickDamage /= 10; + } + + // get passed time since last damage + TIME tmNow = _pTimer->CurrentTick(); + TIME tmDelta = tmNow-m_tmLastDamage; + m_tmLastDamage = tmNow; + + // fade damage out + if (tmDelta>=_pTimer->TickQuantum*3) { + m_vDamage=FLOAT3D(0,0,0); + } + // add new damage + FLOAT3D vDirectionFixed; + if (vDirection.ManhattanNorm()>0.5f) { + vDirectionFixed = vDirection; + } else { + vDirectionFixed = -en_vGravityDir; + } + FLOAT3D vDamageOld = m_vDamage; + m_vDamage+=(vDirectionFixed/*-en_vGravityDir/2*/)*fKickDamage; + + FLOAT fOldLen = vDamageOld.Length(); + FLOAT fNewLen = m_vDamage.Length(); + FLOAT fOldRootLen = Sqrt(fOldLen); + FLOAT fNewRootLen = Sqrt(fNewLen); + + FLOAT fMassFactor = 200.0f/((EntityInfo*)GetEntityInfo())->fMass; + + if( !(en_ulFlags & ENF_ALIVE)) + { + fMassFactor /= 3; + } + + switch( dmtType) + { + case DMT_CLOSERANGE: + case DMT_CHAINSAW: + case DMT_DROWNING: + case DMT_IMPACT: + case DMT_BRUSH: + case DMT_BURNING: + // do nothing + break; + default: + { + if(fOldLen != 0.0f) + { + // cancel last push + GiveImpulseTranslationAbsolute( -vDamageOld/fOldRootLen*fMassFactor); + } + + /* + FLOAT3D vImpuls = m_vDamage/fNewRootLen*fMassFactor; + CPrintF( "Applied absolute translation impuls: (%g%g%g)\n", + vImpuls(1),vImpuls(2),vImpuls(3));*/ + + // push it back + GiveImpulseTranslationAbsolute( m_vDamage/fNewRootLen*fMassFactor); + } + } + + if( m_fMaxDamageAmmountCurrentTick()-_pTimer->TickQuantum*8 || + m_fSprayDamage+fDamageAmmount>50.0f)) { + + // spawn blood spray + CPlacement3D plSpray = CPlacement3D( vHitPoint, ANGLE3D(0, 0, 0)); + m_penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + m_penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + + if( m_fMaxDamageAmmount > 10.0f) + { + eSpawnSpray.fDamagePower = 3.0f; + } + else if(m_fSprayDamage+fDamageAmmount>50.0f) + { + eSpawnSpray.fDamagePower = 2.0f; + } + else + { + eSpawnSpray.fDamagePower = 1.0f; + } + + eSpawnSpray.sptType = SPT_BLOOD; + eSpawnSpray.fSizeMultiplier = 1.0f; + + // setup direction of spray + FLOAT3D vHitPointRelative = vHitPoint - GetPlacement().pl_PositionVector; + FLOAT3D vReflectingNormal; + GetNormalComponent( vHitPointRelative, en_vGravityDir, vReflectingNormal); + vReflectingNormal.Normalize(); + + vReflectingNormal(1)/=5.0f; + + FLOAT3D vProjectedComponent = vReflectingNormal*(vDirection%vReflectingNormal); + FLOAT3D vSpilDirection = vDirection-vProjectedComponent*2.0f-en_vGravityDir*0.5f; + + eSpawnSpray.vDirection = vSpilDirection; + eSpawnSpray.penOwner = this; + + // initialize spray + m_penSpray->Initialize( eSpawnSpray); + m_tmSpraySpawned = _pTimer->CurrentTick(); + m_fSprayDamage = 0.0f; + m_fMaxDamageAmmount = 0.0f; + } + m_fSprayDamage+=fDamageAmmount; + } + + + /* Receive damage */ + void ReceiveDamage( CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // don't harm yourself with knife or with rocket in easy/tourist mode + if( penInflictor==this && (dmtType==DMT_CLOSERANGE || dmtType==DMT_CHAINSAW || + ((dmtType==DMT_EXPLOSION||dmtType==DMT_CANNONBALL_EXPLOSION||dmtType==DMT_PROJECTILE) && + GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY)) ) { + return; + } + + // if not connected + if (m_ulFlags&PLF_NOTCONNECTED) { + // noone can harm you + return; + } + + // god mode -> no one can harm you + if( cht_bGod && CheatsEnabled() ) { return; } + + // if invulnerable, nothing can harm you except telefrag or abyss + const TIME tmDelta = m_tmInvulnerability - _pTimer->CurrentTick(); + if( tmDelta>0 && dmtType!=DMT_ABYSS && dmtType!=DMT_TELEPORT) { return; } + + // if invunerable after spawning + FLOAT tmSpawnInvulnerability = GetSP()->sp_tmSpawnInvulnerability; + if (tmSpawnInvulnerability>0 && _pTimer->CurrentTick()-m_tmSpawnedsp_bFriendlyFire && GetSP()->sp_bCooperative) { + if (IsOfClass(penInflictor, "Player") && penInflictor!=this) { + return; + } + } + + // ignore heat damage if dead + if (dmtType==DMT_HEAT && !(GetFlags()&ENF_ALIVE)) { + return; + } + + // adjust for difficulty + FLOAT fDifficultyDamage = GetSP()->sp_fDamageStrength; + if( fDifficultyDamage<=1.0f || penInflictor!=this) { + fDamageAmmount *= fDifficultyDamage; + } + + // ignore zero damages + if (fDamageAmmount<=0) { + return; + } + + FLOAT fSubHealth, fSubArmor; + if( dmtType == DMT_DROWNING) { + // drowning + fSubHealth = fDamageAmmount; + } + else { + // damage and armor + fSubArmor = fDamageAmmount*2.0f/3.0f; // 2/3 on armor damage + fSubHealth = fDamageAmmount - fSubArmor; // 1/3 on health damage + m_fArmor -= fSubArmor; // decrease armor + if( m_fArmor<0) { // armor below zero -> add difference to health damage + fSubHealth -= m_fArmor; + m_fArmor = 0.0f; + } + } + + // if any damage + if( fSubHealth>0) { + // if camera is active + if (m_penCamera!=NULL) { + // if the camera has onbreak + CEntity *penOnBreak = ((CCamera&)*m_penCamera).m_penOnBreak; + if (penOnBreak!=NULL) { + // trigger it + SendToTarget(penOnBreak, EET_TRIGGER, this); + // if it doesn't + } else { + // just deactivate camera + m_penCamera = NULL; + } + } + + } + + // if the player is doing autoactions + if (m_penActionMarker!=NULL) { + // ignore all damage + return; + } + + DamageImpact(dmtType, fSubHealth, vHitPoint, vDirection); + + // receive damage + CPlayerEntity::ReceiveDamage( penInflictor, dmtType, fSubHealth, vHitPoint, vDirection); + + // red screen and hit translation + if( fDamageAmmount>1.0f) { +// !!!! this is obsolete, DamageImpact is used instead! + if( dmtType==DMT_EXPLOSION || dmtType==DMT_PROJECTILE || dmtType==DMT_BULLET + || dmtType==DMT_IMPACT || dmtType==DMT_CANNONBALL || dmtType==DMT_CANNONBALL_EXPLOSION) { +// GiveImpulseTranslationAbsolute( vDirection*(fDamageAmmount/7.5f) +// -en_vGravityDir*(fDamageAmmount/15.0f)); + } + if( GetFlags()&ENF_ALIVE) { + m_fDamageAmmount += fDamageAmmount; + m_tmWoundedTime = _pTimer->CurrentTick(); + } + } + + // yell (this hurts) + ESound eSound; + eSound.EsndtSound = SNDT_PLAYER; + eSound.penTarget = this; + SendEventInRange( eSound, FLOATaabbox3D( GetPlacement().pl_PositionVector, 10.0f)); + + // play hurting sound + if( dmtType==DMT_DROWNING) { + SetRandomMouthPitch( 0.9f, 1.1f); + PlaySound( m_soMouth, GenderSound(SOUND_DROWN), SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_PlayEffect("WoundWater");} + m_tmMouthSoundLast = _pTimer->CurrentTick(); + PlaySound( m_soLocalAmbientOnce, SOUND_WATERBUBBLES, SOF_3D|SOF_VOLUMETRIC|SOF_LOCAL); + m_soLocalAmbientOnce.Set3DParameters( 25.0f, 5.0f, 2.0f, Lerp(0.5f, 1.5f, FRnd()) ); + SpawnBubbles( 10+INDEX(FRnd()*10)); + } else if( m_fDamageAmmount>1.0f) { + // if not dead + if (GetFlags()&ENF_ALIVE) { + // determine corresponding sound + INDEX iSound; + char *strIFeel = NULL; + if( m_fDamageAmmount<5.0f) { + iSound = GenderSound(SOUND_WOUNDWEAK); + strIFeel = "WoundWeak"; + } + else if( m_fDamageAmmount<25.0f) { + iSound = GenderSound(SOUND_WOUNDMEDIUM); + strIFeel = "WoundMedium"; + } + else { + iSound = GenderSound(SOUND_WOUNDSTRONG); + strIFeel = "WoundStrong"; + } + if( m_pstState==PST_DIVE) { + iSound = GenderSound(SOUND_WOUNDWATER); + strIFeel = "WoundWater"; + } // override for diving + SetRandomMouthPitch( 0.9f, 1.1f); + // give some pause inbetween screaming + TIME tmNow = _pTimer->CurrentTick(); + if( (tmNow-m_tmScreamTime) > 1.0f) { + m_tmScreamTime = tmNow; + PlaySound( m_soMouth, iSound, SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_PlayEffect(strIFeel);} + } + } + } + }; + + // should this player blow up (spawn debris) + BOOL ShouldBlowUp(void) + { + // blow up if + return + // allowed + GetSP()->sp_bGibs && + // dead and + (GetHealth()<=0) && + // has received large enough damage lately and + (m_vDamage.Length() > _fBlowUpAmmount) && + // is not blown up already + GetRenderType()==RT_MODEL; + }; + + // spawn body parts + void BlowUp(void) + { + FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(_fBlowUpAmmount/m_vDamage.Length()); + vNormalizedDamage /= Sqrt(vNormalizedDamage.Length()); + vNormalizedDamage *= 0.75f; + + FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute); + const FLOAT fBlowUpSize = 2.0f; + + // readout blood type + const INDEX iBloodType = GetSP()->sp_iBlood; + // determine debris texture (color) + ULONG ulFleshTexture = TEXTURE_FLESH_GREEN; + ULONG ulFleshModel = MODEL_FLESH; + if( iBloodType==2) { ulFleshTexture = TEXTURE_FLESH_RED; } + // spawn debris + Debris_Begin( EIBT_FLESH, DPT_BLOODTRAIL, BET_BLOODSTAIN, fBlowUpSize, vNormalizedDamage, vBodySpeed, 1.0f, 0.0f); + for( INDEX iDebris=0; iDebris<4; iDebris++) { + // flowerpower mode? + if( iBloodType==3) { + switch( IRnd()%5) { + case 1: { ulFleshModel = MODEL_FLESH_APPLE; ulFleshTexture = TEXTURE_FLESH_APPLE; break; } + case 2: { ulFleshModel = MODEL_FLESH_BANANA; ulFleshTexture = TEXTURE_FLESH_BANANA; break; } + case 3: { ulFleshModel = MODEL_FLESH_BURGER; ulFleshTexture = TEXTURE_FLESH_BURGER; break; } + case 4: { ulFleshModel = MODEL_FLESH_LOLLY; ulFleshTexture = TEXTURE_FLESH_LOLLY; break; } + default: { ulFleshModel = MODEL_FLESH_ORANGE; ulFleshTexture = TEXTURE_FLESH_ORANGE; break; } + } + } + Debris_Spawn( this, this, ulFleshModel, ulFleshTexture, 0, 0, 0, IRnd()%4, 0.5f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + } + + // leave a stain beneath + LeaveStain(FALSE); + + PlaySound(m_soBody, SOUND_BLOWUP, SOF_3D); + + // hide yourself (must do this after spawning debris) + SwitchToEditorModel(); + + FLOAT fSpeedOrg = en_vCurrentTranslationAbsolute.Length(); + const FLOAT fSpeedMax = 30.0f; + if (fSpeedOrg>fSpeedMax) { + en_vCurrentTranslationAbsolute *= fSpeedMax/fSpeedOrg; + } + +// SetPhysicsFlags(EPF_MODEL_IMMATERIAL); +// SetCollisionFlags(ECF_IMMATERIAL); + }; + +/************************************************************ + * OVERRIDEN FUNCTIONS * + ************************************************************/ + /* Entity info */ + void *GetEntityInfo(void) + { + switch (m_pstState) { + case PST_STAND: case PST_FALL: + return &eiPlayerGround; + break; + case PST_CROUCH: + return &eiPlayerCrouch; + break; + case PST_SWIM: case PST_DIVE: + return &eiPlayerSwim; + break; + } + return &eiPlayerGround; + }; + + + /* Receive item */ + BOOL ReceiveItem(const CEntityEvent &ee) + { + // *********** HEALTH *********** + if( ee.ee_slEvent == EVENTCODE_EHealth) + { + // determine old and new health values + FLOAT fHealthOld = GetHealth(); + FLOAT fHealthNew = fHealthOld + ((EHealth&)ee).fHealth; + if( ((EHealth&)ee).bOverTopHealth) { + fHealthNew = ClampUp( fHealthNew, MaxHealth()); + } else { + fHealthNew = ClampUp( fHealthNew, TopHealth()); + } + + // if value can be changed + if( ceil(fHealthNew) > ceil(fHealthOld)) { + // receive it + SetHealth(fHealthNew); + ItemPicked( TRANS("Health"), ((EHealth&)ee).fHealth); + m_iMana += (INDEX)(((EHealth&)ee).fHealth); + m_fPickedMana += ((EHealth&)ee).fHealth; + return TRUE; + } + } + + // *********** ARMOR *********** + else if( ee.ee_slEvent == EVENTCODE_EArmor) + { + // determine old and new health values + FLOAT fArmorOld = m_fArmor; + FLOAT fArmorNew = fArmorOld + ((EArmor&)ee).fArmor; + if( ((EArmor&)ee).bOverTopArmor) { + fArmorNew = ClampUp( fArmorNew, MaxArmor()); + } else { + fArmorNew = ClampUp( fArmorNew, TopArmor()); + } + // if value can be changed + if( ceil(fArmorNew) > ceil(fArmorOld)) { + // receive it + m_fArmor = fArmorNew; + ItemPicked( TRANS("Armor"), ((EArmor&)ee).fArmor); + m_iMana += (INDEX)(((EArmor&)ee).fArmor); + m_fPickedMana += ((EArmor&)ee).fArmor; + return TRUE; + } + } + + // *********** MESSAGE *********** + else if (ee.ee_slEvent == EVENTCODE_EMessageItem) { + EMessageItem &eMI = (EMessageItem &)ee; + ReceiveComputerMessage(eMI.fnmMessage, CMF_ANALYZE); + ItemPicked(TRANS("Ancient papyrus"), 0); + return TRUE; + } + + // *********** WEAPON *********** + else if (ee.ee_slEvent == EVENTCODE_EWeaponItem) { + return ((CPlayerWeapons&)*m_penWeapons).ReceiveWeapon(ee); + } + + // *********** AMMO *********** + else if (ee.ee_slEvent == EVENTCODE_EAmmoItem) { + return ((CPlayerWeapons&)*m_penWeapons).ReceiveAmmo(ee); + } + + else if (ee.ee_slEvent == EVENTCODE_EAmmoPackItem) { + return ((CPlayerWeapons&)*m_penWeapons).ReceivePackAmmo(ee); + } + + // *********** KEYS *********** + else if (ee.ee_slEvent == EVENTCODE_EKey) { + // don't pick up key if in auto action mode + if (m_penActionMarker!=NULL) { + return FALSE; + } + // make key mask + ULONG ulKey = 1<sp_bCooperative && !GetSP()->sp_bSinglePlayer) { + CPrintF(TRANS("^cFFFFFF%s - %s^r\n"), GetPlayerName(), strKey); + } + return TRUE; + } + } + + // *********** POWERUPS *********** + else if( ee.ee_slEvent == EVENTCODE_EPowerUp) { + const FLOAT tmNow = _pTimer->CurrentTick(); + switch( ((EPowerUp&)ee).puitType) { + case PUIT_INVISIB : m_tmInvisibility = tmNow + m_tmInvisibilityMax; + ItemPicked(TRANS("^cABE3FFInvisibility"), 0); + return TRUE; + case PUIT_INVULNER: m_tmInvulnerability = tmNow + m_tmInvulnerabilityMax; + ItemPicked(TRANS("^c00B440Invulnerability"), 0); + return TRUE; + case PUIT_DAMAGE : m_tmSeriousDamage = tmNow + m_tmSeriousDamageMax; + ItemPicked(TRANS("^cFF0000Serious Damage!"), 0); + return TRUE; + case PUIT_SPEED : m_tmSeriousSpeed = tmNow + m_tmSeriousSpeedMax; + ItemPicked(TRANS("^cFF9400Serious Speed"), 0); + return TRUE; + case PUIT_BOMB : + m_iSeriousBombCount++; + ItemPicked(TRANS("^cFF0000Serious Bomb!"), 0); + //ItemPicked(TRANS("^cFF0000S^cFFFF00e^cFF0000r^cFFFF00i^cFF0000o^cFFFF00u^cFF0000s ^cFF0000B^cFFFF00o^cFF0000m^cFFFF00b!"), 0); + // send computer message + if (GetSP()->sp_bCooperative) { + EComputerMessage eMsg; + eMsg.fnmMessage = CTFILENAME("DataMP\\Messages\\Weapons\\seriousbomb.txt"); + this->SendEvent(eMsg); + } + return TRUE; + } + } + + // nothing picked + return FALSE; + }; + + + + // Change Player view + void ChangePlayerView() + { + // change from eyes to 3rd person + if (m_iViewState == PVT_PLAYEREYES) { + // spawn 3rd person view camera + ASSERT(m_pen3rdPersonView == NULL); + if (m_pen3rdPersonView == NULL) { + m_pen3rdPersonView = CreateEntity(GetPlacement(), CLASS_PLAYER_VIEW); + EViewInit eInit; + eInit.penOwner = this; + eInit.penCamera = NULL; + eInit.vtView = VT_3RDPERSONVIEW; + eInit.bDeathFixed = FALSE; + m_pen3rdPersonView ->Initialize(eInit); + } + + m_iViewState = PVT_3RDPERSONVIEW; + + // change from 3rd person to eyes + } else if (m_iViewState == PVT_3RDPERSONVIEW) { + m_iViewState = PVT_PLAYEREYES; + + // kill 3rd person view + if (m_pen3rdPersonView != NULL) { + ((CPlayerView&)*m_pen3rdPersonView).SendEvent(EEnd()); + m_pen3rdPersonView = NULL; + } + } + }; + + // if computer is pressed + void ComputerPressed(void) + { + // call computer if not holding sniper +// if (GetPlayerWeapons()->m_iCurrentWeapon!=WEAPON_SNIPER){ + if (cmp_ppenPlayer==NULL && _pNetwork->IsPlayerLocal(this)) { + cmp_ppenPlayer = this; + } + m_bComputerInvoked = TRUE; + // clear analyses message + m_tmAnalyseEnd = 0; + m_bPendingMessage = FALSE; + m_tmMessagePlay = 0; +// } + } + + + // if use is pressed + void UsePressed(BOOL bOrComputer) + { + // cast ray from weapon + CPlayerWeapons *penWeapons = GetPlayerWeapons(); + CEntity *pen = penWeapons->m_penRayHit; + BOOL bSomethingToUse = FALSE; + + // if hit + if (pen!=NULL) { + // check switch/messageholder relaying by moving brush + if (IsOfClass( pen, "Moving Brush")) { + if (((CMovingBrush&)*pen).m_penSwitch!=NULL) { + pen = ((CMovingBrush&)*pen).m_penSwitch; + } + } + + // if switch and near enough + if (IsOfClass( pen, "Switch") && penWeapons->m_fRayHitDistance < 2.0f) { + CSwitch &enSwitch = (CSwitch&)*pen; + // if switch is useable + if (enSwitch.m_bUseable) { + // send it a trigger event + SendToTarget(pen, EET_TRIGGER, this); + bSomethingToUse = TRUE; + } + } + + // if analyzable + if (IsOfClass( pen, "MessageHolder") + && penWeapons->m_fRayHitDistance<((CMessageHolder*)&*pen)->m_fDistance + && ((CMessageHolder*)&*pen)->m_bActive) { + const CTFileName &fnmMessage = ((CMessageHolder*)&*pen)->m_fnmMessage; + // if player doesn't have that message in database + if (!HasMessage(fnmMessage)) { + // add the message + ReceiveComputerMessage(fnmMessage, CMF_ANALYZE); + bSomethingToUse = TRUE; + } + } + } + // if nothing usable under cursor, and may call computer + if (!bSomethingToUse && bOrComputer) { + // call computer + ComputerPressed(); + } + else if (!bSomethingToUse) + { + CPlayerWeapons *penWeapon = GetPlayerWeapons(); + + // penWeapon->m_iWantedWeapon==WEAPON_SNIPER) => + // make sure that weapon transition is not in progress + if (penWeapon->m_iCurrentWeapon==WEAPON_SNIPER && + penWeapon->m_iWantedWeapon==WEAPON_SNIPER) { + if (m_ulFlags&PLF_ISZOOMING) { + m_ulFlags&=~PLF_ISZOOMING; + penWeapon->m_bSniping = FALSE; + penWeapon->m_fSniperFOVlast = penWeapon->m_fSniperFOV = penWeapon->m_fSniperMaxFOV; + PlaySound(m_soSniperZoom, SOUND_SILENCE, SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_StopEffect("SniperZoom");} + } + else { + penWeapon->m_bSniping = TRUE; + m_ulFlags|=PLF_ISZOOMING; + penWeapon->m_fSniperFOVlast = penWeapon->m_fSniperFOV = penWeapon->m_fMinimumZoomFOV; + PlaySound(m_soSniperZoom, SOUND_SNIPER_ZOOM, SOF_3D|SOF_LOOP); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_PlayEffect("SniperZoom");} + } + } + } + } + + +/************************************************************ + * PLAYER ACTIONS * + ************************************************************/ + void SetGameEnd(void) + { + _pNetwork->SetGameFinished(); + // start console for first player possible + for(INDEX iPlayer=0; iPlayerIsPlayerLocal(pen)) { + cmp_ppenPlayer = (CPlayer*)pen; + } + } + } + } + // check if game should be finished + void CheckGameEnd(void) + { + BOOL bFinished = FALSE; + // if time limit is out + INDEX iTimeLimit = GetSP()->sp_iTimeLimit; + if (iTimeLimit>0 && _pTimer->CurrentTick()>=iTimeLimit*60.0f) { + bFinished = TRUE; + } + // if frag limit is out + INDEX iFragLimit = GetSP()->sp_iFragLimit; + if (iFragLimit>0 && m_psLevelStats.ps_iKills>=iFragLimit) { + bFinished = TRUE; + } + // if score limit is out + INDEX iScoreLimit = GetSP()->sp_iScoreLimit; + if (iScoreLimit>0 && m_psLevelStats.ps_iScore>=iScoreLimit) { + bFinished = TRUE; + } + + if (bFinished) { + SetGameEnd(); + } + } + + // Preapply the action packet for local mouselag elimination + void PreapplyAction( const CPlayerAction &paAction) + { + } + + // Called to apply player action to player entity each tick. + void ApplyAction( const CPlayerAction &paOriginal, FLOAT tmLatency) + { + if(!(m_ulFlags&PLF_INITIALIZED)) { return; } +// CPrintF("---APPLY: %g\n", paOriginal.pa_aRotation(1)); + + // if was not connected + if (m_ulFlags&PLF_NOTCONNECTED) { + // set connected state + SetConnected(); + } + // mark that the player is connected + m_ulFlags |= PLF_APPLIEDACTION; + + // make a copy of action for adjustments + CPlayerAction paAction = paOriginal; + //CPrintF("applying(%s-%08x): %g\n", GetPredictName(), int(paAction.pa_llCreated), + // paAction.pa_vTranslation(3)); + + // calculate delta from last received actions + ANGLE3D aDeltaRotation = paAction.pa_aRotation -m_aLastRotation; + ANGLE3D aDeltaViewRotation = paAction.pa_aViewRotation-m_aLastViewRotation; + + if (m_ulFlags&PLF_ISZOOMING) { + FLOAT fRotationDamping = ((CPlayerWeapons &)*m_penWeapons).m_fSniperFOV/((CPlayerWeapons &)*m_penWeapons).m_fSniperMaxFOV; + aDeltaRotation *= fRotationDamping; + aDeltaViewRotation *= fRotationDamping; + } + //FLOAT3D vDeltaTranslation = paAction.pa_vTranslation -m_vLastTranslation; + m_aLastRotation = paAction.pa_aRotation; + m_aLastViewRotation = paAction.pa_aViewRotation; + //m_vLastTranslation = paAction.pa_vTranslation; + paAction.pa_aRotation = aDeltaRotation; + paAction.pa_aViewRotation = aDeltaViewRotation; + //paAction.pa_vTranslation = vDeltaTranslation; + + // adjust rotations per tick + paAction.pa_aRotation /= _pTimer->TickQuantum; + paAction.pa_aViewRotation /= _pTimer->TickQuantum; + + // adjust prediction for remote players only + CEntity *penMe = this; + if (IsPredictor()) { + penMe = penMe->GetPredicted(); + } + SetPredictable(!_pNetwork->IsPlayerLocal(penMe)); + + // check for end of game + if (!IsPredictor()) { + CheckGameEnd(); + } + + // limit speeds against abusing + paAction.pa_vTranslation(1) = Clamp( paAction.pa_vTranslation(1), -plr_fSpeedSide, plr_fSpeedSide); + paAction.pa_vTranslation(2) = Clamp( paAction.pa_vTranslation(2), -plr_fSpeedUp, plr_fSpeedUp); + paAction.pa_vTranslation(3) = Clamp( paAction.pa_vTranslation(3), -plr_fSpeedForward, plr_fSpeedBackward); + + // if speeds are like walking + if (Abs(paAction.pa_vTranslation(3))< plr_fSpeedForward/1.99f + &&Abs(paAction.pa_vTranslation(1))< plr_fSpeedSide/1.99f) { + // don't allow falling + en_fStepDnHeight = 1.5f; + + // if speeds are like running + } else { + // allow falling + en_fStepDnHeight = -1; + } + + // limit diagonal speed against abusing + FLOAT3D &v = paAction.pa_vTranslation; + FLOAT fDiag = Sqrt(v(1)*v(1)+v(3)*v(3)); + if (fDiag>0.01f) { + FLOAT fDiagLimited = Min(fDiag, plr_fSpeedForward); + FLOAT fFactor = fDiagLimited/fDiag; + v(1)*=fFactor; + v(3)*=fFactor; + } + + ulButtonsNow = paAction.pa_ulButtons; + ulButtonsBefore = m_ulLastButtons; + ulNewButtons = ulButtonsNow&~ulButtonsBefore; + ulReleasedButtons = (~ulButtonsNow)&(ulButtonsBefore); + + m_ulLastButtons = ulButtonsNow; // remember last buttons + en_plLastViewpoint = en_plViewpoint; // remember last view point for lerping + + // sniper zooming + CPlayerWeapons *penWeapon = GetPlayerWeapons(); + if (penWeapon->m_iCurrentWeapon == WEAPON_SNIPER) + { + if (bUseButtonHeld && m_ulFlags&PLF_ISZOOMING) + { + penWeapon->m_fSniperFOVlast = penWeapon->m_fSniperFOV; + penWeapon->m_fSniperFOV -= penWeapon->m_fSnipingZoomSpeed; + if (penWeapon->m_fSniperFOV < penWeapon->m_fSniperMinFOV) + { + penWeapon->m_fSniperFOVlast = penWeapon->m_fSniperFOV = penWeapon->m_fSniperMinFOV; + PlaySound(m_soSniperZoom, SOUND_SILENCE, SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_StopEffect("SniperZoom");} + } + } + if (ulReleasedButtons&PLACT_USE_HELD) + { + penWeapon->m_fSniperFOVlast = penWeapon->m_fSniperFOV; + PlaySound(m_soSniperZoom, SOUND_SILENCE, SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_StopEffect("SniperZoom");} + } + } + + // if alive + if (GetFlags() & ENF_ALIVE) { + // if not in auto-action mode + if (m_penActionMarker==NULL) { + // apply actions + AliveActions(paAction); + // if in auto-action mode + } else { + // do automatic actions + AutoActions(paAction); + } + // if not alive rotate camera view and rebirth on fire + } else { + DeathActions(paAction); + } + + if (Abs(_pTimer->CurrentTick()-m_tmAnalyseEnd)<_pTimer->TickQuantum*2) { + m_tmAnalyseEnd = 0; + m_bPendingMessage = TRUE; + m_tmMessagePlay = 0; + } + if (m_bPendingMessage && !IsFuss()) { + m_bPendingMessage = FALSE; + m_tmMessagePlay = _pTimer->CurrentTick()+1.0f; + m_tmAnimateInbox = _pTimer->CurrentTick(); + } + if (Abs(_pTimer->CurrentTick()-m_tmMessagePlay)<_pTimer->TickQuantum*2) { + m_bPendingMessage = FALSE; + m_tmAnalyseEnd = 0; + + if (!m_bComputerInvoked && GetSP()->sp_bSinglePlayer) { + PrintCenterMessage(this, this, + TRANS("Press USE to read the message!"), 5.0f, MSS_NONE); + } + } + + // wanna cheat a bit? + if (CheatsEnabled()) { + Cheats(); + } + + // if teleporting to marker (this cheat is enabled in all versions) + if (cht_iGoToMarker>0 && (GetFlags()&ENF_ALIVE)) { + // rebirth player, and it will teleport + m_iLastViewState = m_iViewState; + SendEvent(ERebirth()); + } + + // keep latency for eventual printout + UpdateLatency(tmLatency); + + // check if highscore has changed + CheckHighScore(); + }; + + + // Called when player is disconnected + void Disconnect(void) + { + // remember name + m_strName = GetPlayerName(); + // clear the character, so we don't get re-connected to same entity + en_pcCharacter = CPlayerCharacter(); + // make main loop exit + SendEvent(EDisconnected()); + }; + + // Called when player character is changed + void CharacterChanged(const CPlayerCharacter &pcNew) + { + // remember original character + CPlayerCharacter pcOrg = en_pcCharacter; + + // set the new character + en_pcCharacter = pcNew; + ValidateCharacter(); + + // if the name has changed + if (pcOrg.GetName()!=pcNew.GetName()) { + // report that + CPrintF(TRANS("%s is now known as %s\n"), + pcOrg.GetNameForPrinting(), pcNew.GetNameForPrinting()); + } + + // if the team has changed + if (pcOrg.GetTeam()!=pcNew.GetTeam()) { + // report that + CPrintF(TRANS("%s switched to team %s\n"), + pcNew.GetNameForPrinting(), pcNew.GetTeamForPrinting()); + } + + // if appearance changed + CPlayerSettings *ppsOrg = (CPlayerSettings *)pcOrg.pc_aubAppearance; + CPlayerSettings *ppsNew = (CPlayerSettings *)pcNew.pc_aubAppearance; + if (memcmp(ppsOrg->ps_achModelFile, ppsNew->ps_achModelFile, sizeof(ppsOrg->ps_achModelFile))!=0) { + // update your real appearance if possible + CTString strNewLook; + BOOL bSuccess = SetPlayerAppearance(&m_moRender, &en_pcCharacter, strNewLook, /*bPreview=*/FALSE); + // if succeeded + if (bSuccess) { + ParseGender(strNewLook); + // report that + CPrintF(TRANS("%s now appears as %s\n"), + pcNew.GetNameForPrinting(), strNewLook); + // if failed + } else { + // report that + CPrintF(TRANS("Cannot change appearance for %s: setting '%s' is unavailable\n"), + pcNew.GetNameForPrinting(), (const char*)ppsNew->GetModelFilename()); + } + // attach weapon to new appearance + GetPlayerAnimator()->SyncWeapon(); + } + + BOOL b3RDPersonOld = ppsOrg->ps_ulFlags&PSF_PREFER3RDPERSON; + BOOL b3RDPersonNew = ppsNew->ps_ulFlags&PSF_PREFER3RDPERSON; + if ((b3RDPersonOld && !b3RDPersonNew && m_iViewState==PVT_3RDPERSONVIEW) + ||(b3RDPersonNew && !b3RDPersonOld && m_iViewState==PVT_PLAYEREYES) ) { + ChangePlayerView(); + } + }; + + + // Alive actions + void AliveActions(const CPlayerAction &pa) + { + CPlayerAction paAction = pa; + + // if camera is active + if (m_penCamera!=NULL) { + // ignore keyboard/mouse/joystick commands + paAction.pa_vTranslation = FLOAT3D(0,0,0); + paAction.pa_aRotation = ANGLE3D(0,0,0); + paAction.pa_aViewRotation = ANGLE3D(0,0,0); + // if fire or use is pressed + if (ulNewButtons&(PLACT_FIRE|PLACT_USE)) { + // stop camera + m_penCamera=NULL; + } + } else { + ButtonsActions(paAction); + } + + // do the actions + ActiveActions(paAction); + + // if less than few seconds elapsed since last damage + FLOAT tmSinceWounding = _pTimer->CurrentTick() - m_tmWoundedTime; + if( tmSinceWounding<4.0f) { + // decrease damage ammount + m_fDamageAmmount *= 1.0f - tmSinceWounding/4.0f; + } else { + // reset damage ammount + m_fDamageAmmount = 0.0f; + } + } + + // Auto-actions + void AutoActions(const CPlayerAction &pa) + { + // if fire, use or computer is pressed + if (ulNewButtons&(PLACT_FIRE|PLACT_USE|PLACT_COMPUTER)) { + if (m_penCamera!=NULL) { + CEntity *penOnBreak = ((CCamera&)*m_penCamera).m_penOnBreak; + if (penOnBreak!=NULL) { + SendToTarget(penOnBreak, EET_TRIGGER, this); + } + } + } + + CPlayerAction paAction = pa; + // ignore keyboard/mouse/joystick commands + paAction.pa_vTranslation = FLOAT3D(0,0,0); + paAction.pa_aRotation = ANGLE3D(0,0,0); + paAction.pa_aViewRotation = ANGLE3D(0,0,0); + + // if moving towards the marker is enabled + if (m_fAutoSpeed>0) { + FLOAT3D vDelta = + m_penActionMarker->GetPlacement().pl_PositionVector- + GetPlacement().pl_PositionVector; + FLOAT fDistance = vDelta.Length(); + if (fDistance>0.1f) { + vDelta/=fDistance; + ANGLE aDH = GetRelativeHeading(vDelta); + + // if should hit the marker exactly + FLOAT fSpeed = m_fAutoSpeed; + if (GetActionMarker()->m_paaAction==PAA_RUNANDSTOP) { + // adjust speed + fSpeed = Min(fSpeed, fDistance/_pTimer->TickQuantum); + } + // adjust rotation + if (Abs(aDH)>5.0f) { + if (fSpeed>m_fAutoSpeed-0.1f) { + aDH = Clamp(aDH, -30.0f, 30.0f); + } + paAction.pa_aRotation = ANGLE3D(aDH/_pTimer->TickQuantum,0,0); + } + // set forward speed + paAction.pa_vTranslation = FLOAT3D(0,0,-fSpeed); + } + } else { + paAction.pa_vTranslation = m_vAutoSpeed; + } + + CPlayerActionMarker *ppam = GetActionMarker(); + ASSERT( ppam != NULL); + if( ppam->m_paaAction == PAA_LOGO_FIRE_MINIGUN || ppam->m_paaAction == PAA_LOGO_FIRE_INTROSE) + { + if( m_tmMinigunAutoFireStart != -1) + { + FLOAT tmDelta = _pTimer->CurrentTick()-m_tmMinigunAutoFireStart; + FLOAT aDH=0.0f; + FLOAT aDP=0.0f; + if( tmDelta>=0.0f && tmDelta<=0.75f) + { + aDH = 0.0f; + } + else if( tmDelta>=0.75f) + { + FLOAT fDT = tmDelta-0.75f; + aDH = 1.0f*cos(fDT+PI/2.0f); + aDP = 0.5f*cos(fDT); + } + if(ppam->m_paaAction == PAA_LOGO_FIRE_INTROSE) + { + FLOAT fRatio=CalculateRatio(tmDelta,0.25,5,0.1f,0.1f); + aDP=2.0f*sin(tmDelta*200.0f)*fRatio; + if(tmDelta>2.5f) + { + aDP+=(tmDelta-2.5f)*4.0f; + } + } + paAction.pa_aRotation = ANGLE3D(aDH/_pTimer->TickQuantum, aDP/_pTimer->TickQuantum,0); + } + } + + // do the actions + if (!(m_ulFlags&PLF_AUTOMOVEMENTS)) { + ActiveActions(paAction); + } + } + + void GetLerpedWeaponPosition( FLOAT3D vRel, CPlacement3D &pl) + { + pl = CPlacement3D( vRel, ANGLE3D(0,0,0)); + CPlacement3D plView; + _bDiscard3rdView=GetViewEntity()!=this; + GetLerpedAbsoluteViewPlacement(plView); + pl.RelativeToAbsolute( plView); + } + + void SpawnBubbles( INDEX ctBubbles) + { + for( INDEX iBouble=0; iBoublesp_bCooperative) { + vTranslation *= 1.3f; + } + + // enable faster moving (but not higher jumping!) if having SerousSpeed powerup + const TIME tmDelta = m_tmSeriousSpeed - _pTimer->CurrentTick(); + if( tmDelta>0 && m_fAutoSpeed==0.0f) { + vTranslation(1) *= 2.0f; + vTranslation(3) *= 2.0f; + } + + en_fAcceleration = plr_fAcceleration; + en_fDeceleration = plr_fDeceleration; + if( !GetSP()->sp_bCooperative) + { + vTranslation(1) *= 1.35f; + vTranslation(3) *= 1.35f; + //en_fDeceleration *= 0.8f; + } + + CContentType &ctUp = GetWorld()->wo_actContentTypes[en_iUpContent]; + CContentType &ctDn = GetWorld()->wo_actContentTypes[en_iDnContent]; + PlayerState pstWanted = PST_STAND; + BOOL bUpSwimable = (ctUp.ct_ulFlags&CTF_SWIMABLE) && en_fImmersionFactor<=0.99f; + BOOL bDnSwimable = (ctDn.ct_ulFlags&CTF_SWIMABLE) && en_fImmersionFactor>=0.5f; + + // if considerably inside swimable content + if (bUpSwimable || bDnSwimable) { + // allow jumping + m_ulFlags|=PLF_JUMPALLOWED; + //CPrintF("swimable %f", en_fImmersionFactor); + // if totaly inside + if (en_fImmersionFactor>=0.99f || bUpSwimable) { + // want to dive + pstWanted = PST_DIVE; + // if only partially inside + } else { + // want to swim + pstWanted = PST_SWIM; + } + // if not in swimable content + } else { + // if has reference + if (en_penReference!=NULL) { + // reset fall timer + m_fFallTime = 0.0f; + + // if no reference + } else { + // increase fall time + m_fFallTime += _pTimer->TickQuantum; + } + // if not wanting to jump + if (vTranslation(2)<0.1f) { + // allow jumping + m_ulFlags|=PLF_JUMPALLOWED; + } + + // if falling + if (m_fFallTime >= 0.5f) { + // wants to fall + pstWanted = PST_FALL; + // if not falling + } else { + // if holding down and really not in air + if (vTranslation(2)<-0.01f/* && m_fFallTime<0.5f*/) { + // wants to crouch + pstWanted = PST_CROUCH; + // if not holding down + } else { + // wants to stand + pstWanted = PST_STAND; + } + } + } + //CPrintF("c - %s w - %s", NameForState(m_pstState), NameForState(pstWanted)); + + // flying mode - rotate whole player + if (!(GetPhysicsFlags()&EPF_TRANSLATEDBYGRAVITY)) { + SetDesiredRotation(paAction.pa_aRotation); + StartModelAnim(PLAYER_ANIM_STAND, AOF_LOOPING|AOF_NORESTART); + SetDesiredTranslation(vTranslation); + // normal mode + } else { + PlayerState pstOld = m_pstState; + + // if different state needed + if (pstWanted!=m_pstState) { + // check state wanted + switch(pstWanted) { + // if wanting to stand + case PST_STAND: { + // if can stand here + if (ChangeCollisionBoxIndexNow(PLAYER_COLLISION_BOX_STAND)) { + en_plViewpoint.pl_PositionVector(2) = plr_fViewHeightStand; + if (m_pstState==PST_CROUCH) { + ((CPlayerAnimator&)*m_penAnimator).Rise(); + } else { + ((CPlayerAnimator&)*m_penAnimator).Stand(); + } + m_pstState = PST_STAND; + } + } break; + // if wanting to crouch + case PST_CROUCH: { + // if can crouch here + if (ChangeCollisionBoxIndexNow(PLAYER_COLLISION_BOX_CROUCH)) { + m_pstState = PST_CROUCH; + en_plViewpoint.pl_PositionVector(2) = plr_fViewHeightCrouch; + ((CPlayerAnimator&)*m_penAnimator).Crouch(); + } + } break; + // if wanting to swim + case PST_SWIM: { + // if can swim here + if (ChangeCollisionBoxIndexNow(PLAYER_COLLISION_BOX_SWIMSMALL)) { + ChangeCollisionBoxIndexWhenPossible(PLAYER_COLLISION_BOX_SWIM); + m_pstState = PST_SWIM; + en_plViewpoint.pl_PositionVector(2) = plr_fViewHeightSwim; + ((CPlayerAnimator&)*m_penAnimator).Swim(); + m_fSwimTime = _pTimer->CurrentTick(); + } + } break; + // if wanting to dive + case PST_DIVE: { + // if can dive here + if (ChangeCollisionBoxIndexNow(PLAYER_COLLISION_BOX_SWIMSMALL)) { + ChangeCollisionBoxIndexWhenPossible(PLAYER_COLLISION_BOX_SWIM); + m_pstState = PST_DIVE; + en_plViewpoint.pl_PositionVector(2) = plr_fViewHeightDive; + ((CPlayerAnimator&)*m_penAnimator).Swim(); + } + } break; + // if wanting to fall + case PST_FALL: { + // if can fall here + if (ChangeCollisionBoxIndexNow(PLAYER_COLLISION_BOX_STAND)) { + m_pstState = PST_FALL; + en_plViewpoint.pl_PositionVector(2) = plr_fViewHeightStand; + ((CPlayerAnimator&)*m_penAnimator).Fall(); + } + } break; + } + } + + // if state changed + if (m_pstState!=pstOld) { + // check water entering/leaving + BOOL bWasInWater = (pstOld==PST_SWIM||pstOld==PST_DIVE); + BOOL bIsInWater = (m_pstState==PST_SWIM||m_pstState==PST_DIVE); + // if entered water + if (bIsInWater && !bWasInWater) { + PlaySound(m_soBody, GenderSound(SOUND_WATER_ENTER), SOF_3D); + // if left water + } else if (!bIsInWater && bWasInWater) { + PlaySound(m_soBody, GenderSound(SOUND_WATER_LEAVE), SOF_3D); + m_tmOutOfWater = _pTimer->CurrentTick(); + //CPrintF("gotout "); + // if in water + } else if (bIsInWater) { + // if dived in + if (pstOld==PST_SWIM && m_pstState == PST_DIVE) { + PlaySound(m_soFootL, GenderSound(SOUND_DIVEIN), SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_PlayEffect("DiveIn");} + m_bMoveSoundLeft = TRUE; + m_tmMoveSound = _pTimer->CurrentTick(); + // if dived out + } else if (m_pstState==PST_SWIM && pstOld==PST_DIVE) { + PlaySound(m_soFootL, GenderSound(SOUND_DIVEOUT), SOF_3D); + m_bMoveSoundLeft = TRUE; + m_tmMoveSound = _pTimer->CurrentTick(); + } + } + // if just fell to ground + if (pstOld==PST_FALL && (m_pstState==PST_STAND||m_pstState==PST_CROUCH)) { + PlaySound(m_soFootL, GenderSound(SOUND_LAND), SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_PlayEffect("Land");} + } + // change ambience sounds + if (m_pstState==PST_DIVE) { + m_soLocalAmbientLoop.Set3DParameters(50.0f, 10.0f, 0.25f, 1.0f); + PlaySound(m_soLocalAmbientLoop, SOUND_WATERAMBIENT, + SOF_LOOP|SOF_3D|SOF_VOLUMETRIC|SOF_LOCAL); + } else if (pstOld==PST_DIVE) { + m_soLocalAmbientLoop.Stop(); + } + } + // if just jumped + if (en_tmJumped+_pTimer->TickQuantum>=_pTimer->CurrentTick() && + en_tmJumped<=_pTimer->CurrentTick() && en_penReference==NULL) { + // play jump sound + SetDefaultMouthPitch(); + PlaySound(m_soMouth, GenderSound(SOUND_JUMP), SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_PlayEffect("Jump");} + // disallow jumping + m_ulFlags&=~PLF_JUMPALLOWED; + } + + // set density + if (m_pstState == PST_SWIM || pstWanted == PST_SWIM + ||(pstWanted == PST_DIVE && m_pstState != pstWanted)) { + en_fDensity = 500.0f; // lower density than water + } else { + en_fDensity = 1000.0f; // same density as water + } + + if (_pTimer->CurrentTick()>=m_tmNextAmbientOnce) + { + if (m_pstState == PST_DIVE) + { + PlaySound(m_soLocalAmbientOnce, SOUND_WATERBUBBLES, + SOF_3D|SOF_VOLUMETRIC|SOF_LOCAL); + m_soLocalAmbientOnce.Set3DParameters(25.0f, 5.0f, 2.0f, Lerp(0.5f, 1.5f, FRnd()) ); + SpawnBubbles( 5+INDEX(FRnd()*5)); + } + m_tmNextAmbientOnce = _pTimer->CurrentTick()+5.0f+FRnd(); + } + + + // if crouching + if (m_pstState == PST_CROUCH) { + // go slower + vTranslation /= 2.5f; + // don't go down + vTranslation(2) = 0.0f; + } + + // if diving + if (m_pstState == PST_DIVE) { + // translate up/down with view pitch + FLOATmatrix3D mPitch; + MakeRotationMatrixFast(mPitch, FLOAT3D(0,en_plViewpoint.pl_OrientationAngle(2),0)); + FLOAT fZ = vTranslation(3); + vTranslation(3) = 0.0f; + vTranslation += FLOAT3D(0,0,fZ)*mPitch; + // if swimming + } else if (m_pstState == PST_SWIM) { + // translate down with view pitch if large + FLOATmatrix3D mPitch; + FLOAT fPitch = en_plViewpoint.pl_OrientationAngle(2); + if (fPitch>-30.0f) { + fPitch = 0; + } + MakeRotationMatrixFast(mPitch, FLOAT3D(0,fPitch,0)); + FLOAT fZ = vTranslation(3); + vTranslation(3) = 0.0f; + vTranslation += FLOAT3D(0,0,fZ)*mPitch; + } + + // if swimming or diving + if (m_pstState == PST_SWIM || m_pstState == PST_DIVE) { + // up/down is slower than on ground + vTranslation(2)*=0.5f; + } + + // if just started swimming + if (m_pstState == PST_SWIM && _pTimer->CurrentTick()CurrentTick()0) { + vTranslation(2) = 0.0f; + } + + // set translation + SetDesiredTranslation(vTranslation); + + // set pitch and banking from the normal rotation into the view rotation + en_plViewpoint.Rotate_HPB(ANGLE3D( + (ANGLE)((FLOAT)paAction.pa_aRotation(1)*_pTimer->TickQuantum), + (ANGLE)((FLOAT)paAction.pa_aRotation(2)*_pTimer->TickQuantum), + (ANGLE)((FLOAT)paAction.pa_aRotation(3)*_pTimer->TickQuantum))); + // pitch and banking boundaries + RoundViewAngle(en_plViewpoint.pl_OrientationAngle(2), PITCH_MAX); + RoundViewAngle(en_plViewpoint.pl_OrientationAngle(3), BANKING_MAX); + + // translation rotate player for heading + if (vTranslation.Length() > 0.1f) { + SetDesiredRotation(ANGLE3D(en_plViewpoint.pl_OrientationAngle(1)/_pTimer->TickQuantum, 0.0f, 0.0f)); + if (m_ulFlags&PLF_VIEWROTATIONCHANGED) { + m_ulFlags&=~PLF_VIEWROTATIONCHANGED; + FLOATmatrix3D mViewRot; + MakeRotationMatrixFast(mViewRot, ANGLE3D(en_plViewpoint.pl_OrientationAngle(1),0,0)); + FLOAT3D vTransRel = vTranslation*mViewRot; + SetDesiredTranslation(vTransRel); + } + en_plViewpoint.pl_OrientationAngle(1) = 0.0f; + + // rotate head, body and legs + } else { + m_ulFlags |= PLF_VIEWROTATIONCHANGED; + SetDesiredRotation(ANGLE3D(0.0f, 0.0f, 0.0f)); + ANGLE aDiff = en_plViewpoint.pl_OrientationAngle(1) - HEADING_MAX; + if (aDiff > 0.0f) { + SetDesiredRotation(ANGLE3D(aDiff/_pTimer->TickQuantum, 0.0f, 0.0f)); + } + aDiff = en_plViewpoint.pl_OrientationAngle(1) + HEADING_MAX; + if (aDiff < 0.0f) { + SetDesiredRotation(ANGLE3D(aDiff/_pTimer->TickQuantum, 0.0f, 0.0f)); + } + RoundViewAngle(en_plViewpoint.pl_OrientationAngle(1), HEADING_MAX); + } + + // play moving sounds + FLOAT fWantSpeed = en_vDesiredTranslationRelative.Length(); + FLOAT fGoesSpeed = en_vCurrentTranslationAbsolute.Length(); + BOOL bOnGround = (m_pstState == PST_STAND)||(m_pstState == PST_CROUCH); + BOOL bRunning = bOnGround && fWantSpeed>5.0f && fGoesSpeed>5.0f; + BOOL bWalking = bOnGround && !bRunning && fWantSpeed>2.0f && fGoesSpeed>2.0f; + BOOL bSwimming = (m_pstState == PST_SWIM) && fWantSpeed>2.0f && fGoesSpeed>2.0f; + BOOL bDiving = (m_pstState == PST_DIVE) && fWantSpeed>2.0f && fGoesSpeed>2.0f; + TIME tmNow = _pTimer->CurrentTick(); + INDEX iSoundWalkL = SOUND_WALK_L; + INDEX iSoundWalkR = SOUND_WALK_R; + if ((ctDn.ct_ulFlags&CTF_SWIMABLE) && en_fImmersionFactor>=0.1f) { + iSoundWalkL = SOUND_WATERWALK_L; + iSoundWalkR = SOUND_WATERWALK_R; + } else if (en_pbpoStandOn!=NULL && + en_pbpoStandOn->bpo_bppProperties.bpp_ubSurfaceType==SURFACE_SAND) { + iSoundWalkL = SOUND_WALK_SAND_L; + iSoundWalkR = SOUND_WALK_SAND_R; + } else if (en_pbpoStandOn!=NULL && + en_pbpoStandOn->bpo_bppProperties.bpp_ubSurfaceType==SURFACE_RED_SAND) { + iSoundWalkL = SOUND_WALK_SAND_L; + iSoundWalkR = SOUND_WALK_SAND_R; + } else if (en_pbpoStandOn!=NULL && + (en_pbpoStandOn->bpo_bppProperties.bpp_ubSurfaceType==SURFACE_GRASS || + en_pbpoStandOn->bpo_bppProperties.bpp_ubSurfaceType==SURFACE_GRASS_SLIDING || + en_pbpoStandOn->bpo_bppProperties.bpp_ubSurfaceType==SURFACE_GRASS_NOIMPACT )) { + iSoundWalkL = SOUND_WALK_GRASS_L; + iSoundWalkR = SOUND_WALK_GRASS_R; + } else if (en_pbpoStandOn!=NULL && + en_pbpoStandOn->bpo_bppProperties.bpp_ubSurfaceType==SURFACE_WOOD) { + iSoundWalkL = SOUND_WALK_WOOD_L; + iSoundWalkR = SOUND_WALK_WOOD_R; + } else if (en_pbpoStandOn!=NULL && + en_pbpoStandOn->bpo_bppProperties.bpp_ubSurfaceType==SURFACE_SNOW) { + iSoundWalkL = SOUND_WALK_SNOW_L; + iSoundWalkR = SOUND_WALK_SNOW_R; + } + else { + } + iSoundWalkL+=m_iGender*GENDEROFFSET; + iSoundWalkR+=m_iGender*GENDEROFFSET; + if (bRunning) { + if (tmNow>m_tmMoveSound+plr_fRunSoundDelay) { + m_tmMoveSound = tmNow; + m_bMoveSoundLeft = !m_bMoveSoundLeft; + if (m_bMoveSoundLeft) { + PlaySound(m_soFootL, iSoundWalkL, SOF_3D); + } else { + PlaySound(m_soFootR, iSoundWalkR, SOF_3D); + } + } + } else if (bWalking) { + if (tmNow>m_tmMoveSound+plr_fWalkSoundDelay) { + m_tmMoveSound = tmNow; + m_bMoveSoundLeft = !m_bMoveSoundLeft; + if (m_bMoveSoundLeft) { + PlaySound(m_soFootL, iSoundWalkL, SOF_3D); + } else { + PlaySound(m_soFootR, iSoundWalkR, SOF_3D); + } + } + } else if (bDiving) { + if (tmNow>m_tmMoveSound+plr_fDiveSoundDelay) { + m_tmMoveSound = tmNow; + m_bMoveSoundLeft = !m_bMoveSoundLeft; + if (m_bMoveSoundLeft) { + PlaySound(m_soFootL, GenderSound(SOUND_DIVE_L), SOF_3D); + } else { + PlaySound(m_soFootR, GenderSound(SOUND_DIVE_R), SOF_3D); + } + } + } else if (bSwimming) { + if (tmNow>m_tmMoveSound+plr_fSwimSoundDelay) { + m_tmMoveSound = tmNow; + m_bMoveSoundLeft = !m_bMoveSoundLeft; + if (m_bMoveSoundLeft) { + PlaySound(m_soFootL, GenderSound(SOUND_SWIM_L), SOF_3D); + } else { + PlaySound(m_soFootR, GenderSound(SOUND_SWIM_R), SOF_3D); + } + } + } + + // if player is almost out of air + TIME tmBreathDelay = tmNow-en_tmLastBreathed; + if (en_tmMaxHoldBreath-tmBreathDelay<20.0f) { + // play drowning sound once in a while + if (m_tmMouthSoundLast+2.0f aRound) { + aViewAngle = aRound; + } + if (aViewAngle < -aRound) { + aViewAngle = -aRound; + } + }; + + // Death actions + void DeathActions(const CPlayerAction &paAction) { + // set heading, pitch and banking from the normal rotation into the camera view rotation + if (m_penView!=NULL) { + ASSERT(IsPredicted()&&m_penView->IsPredicted()||IsPredictor()&&m_penView->IsPredictor()||!IsPredicted()&&!m_penView->IsPredicted()&&!IsPredictor()&&!m_penView->IsPredictor()); + en_plViewpoint.pl_PositionVector = FLOAT3D(0, 1, 0); + en_plViewpoint.pl_OrientationAngle += (ANGLE3D( + (ANGLE)((FLOAT)paAction.pa_aRotation(1)*_pTimer->TickQuantum), + (ANGLE)((FLOAT)paAction.pa_aRotation(2)*_pTimer->TickQuantum), + (ANGLE)((FLOAT)paAction.pa_aRotation(3)*_pTimer->TickQuantum))); + } + + // if death is finished and fire just released again and this is not a predictor + if (m_iMayRespawn==2 && (ulReleasedButtons&PLACT_FIRE) && !IsPredictor()) { + // if singleplayer + if( GetSP()->sp_bSinglePlayer) { + // load quick savegame + _pShell->Execute("gam_bQuickLoad=1;"); + // if deathmatch or similar + } else if( !GetSP()->sp_bCooperative) { + // rebirth + SendEvent(EEnd()); + // if cooperative + } else { + // if holding down reload button + if (m_ulLastButtons&PLACT_RELOAD) { + // forbid respawning in-place + m_ulFlags &= ~PLF_RESPAWNINPLACE; + } + // if playing on credits + if (GetSP()->sp_ctCredits!=0) { + // if playing on infinite credits or some credits left + if (GetSP()->sp_ctCredits==-1 || GetSP()->sp_ctCreditsLeft!=0) { + // decrement credits + if (GetSP()->sp_ctCredits!=-1) { + ((CSessionProperties*)GetSP())->sp_ctCreditsLeft--; + } + + // initiate respawn + CPrintF(TRANS("%s is riding the gun again\n"), GetPlayerName()); + SendEvent(EEnd()); + + // report number of credits left + if (GetSP()->sp_ctCredits>0) { + if (GetSP()->sp_ctCreditsLeft==0) { + CPrintF(TRANS(" no more credits left!\n")); + } else { + CPrintF(TRANS(" %d credits left\n"), GetSP()->sp_ctCreditsLeft); + } + } + // if no more credits left + } else { + // report that you cannot respawn + CPrintF(TRANS("%s rests in peace - out of credits\n"), GetPlayerName()); + } + } + } + } + // check fire released once after death + if (m_iMayRespawn==1 && !(ulButtonsNow&PLACT_FIRE)) { + m_iMayRespawn=2; + } + }; + + + // Buttons actions + void ButtonsActions( CPlayerAction &paAction) + { + // if selecting a new weapon select it + if((ulNewButtons&PLACT_SELECT_WEAPON_MASK)!=0) { + ESelectWeapon eSelect; + eSelect.iWeapon = (ulNewButtons&PLACT_SELECT_WEAPON_MASK)>>PLACT_SELECT_WEAPON_SHIFT; + ((CPlayerWeapons&)*m_penWeapons).SendEvent(eSelect); + } + + // next weapon zooms out when in sniping mode + if(ulNewButtons&PLACT_WEAPON_NEXT) { + if(((CPlayerWeapons&)*m_penWeapons).m_bSniping) { + ApplySniperZoom(0); + } else if (TRUE) { + ESelectWeapon eSelect; + eSelect.iWeapon = -1; + ((CPlayerWeapons&)*m_penWeapons).SendEvent(eSelect); + } + } + + // previous weapon zooms in when in sniping mode + if(ulNewButtons&PLACT_WEAPON_PREV) { + if(((CPlayerWeapons&)*m_penWeapons).m_bSniping) { + ApplySniperZoom(1); + } else if (TRUE) { + ESelectWeapon eSelect; + eSelect.iWeapon = -2; + ((CPlayerWeapons&)*m_penWeapons).SendEvent(eSelect); + } + } + if(ulNewButtons&PLACT_WEAPON_FLIP) { + ESelectWeapon eSelect; + eSelect.iWeapon = -3; + ((CPlayerWeapons&)*m_penWeapons).SendEvent(eSelect); + } + + // if fire is pressed + if (ulNewButtons&PLACT_FIRE) { + ((CPlayerWeapons&)*m_penWeapons).SendEvent(EFireWeapon()); + } + // if fire is released + if (ulReleasedButtons&PLACT_FIRE) { + ((CPlayerWeapons&)*m_penWeapons).SendEvent(EReleaseWeapon()); + } + // if reload is pressed + if (ulReleasedButtons&PLACT_RELOAD) { + ((CPlayerWeapons&)*m_penWeapons).SendEvent(EReloadWeapon()); + } + // if fire bomb is pressed + if (ulNewButtons&PLACT_FIREBOMB) { + if (m_iSeriousBombCount>0 && m_tmSeriousBombFired+4.0f<_pTimer->CurrentTick()) { + m_iLastSeriousBombCount = m_iSeriousBombCount; + m_iSeriousBombCount--; + m_tmSeriousBombFired = _pTimer->CurrentTick(); + + ESeriousBomb esb; + esb.penOwner = this; + CEntityPointer penBomb = CreateEntity(GetPlacement(), CLASS_SERIOUSBOMB); + penBomb->Initialize(esb); + } + } + + + + // if use is pressed + if (ulNewButtons&PLACT_USE) { + if (((CPlayerWeapons&)*m_penWeapons).m_iCurrentWeapon==WEAPON_SNIPER) { + UsePressed(FALSE); + } else { + UsePressed(ulNewButtons&PLACT_COMPUTER); + } + // if USE is not detected due to doubleclick and player is holding sniper + } else if (ulNewButtons&PLACT_SNIPER_USE && ((CPlayerWeapons&)*m_penWeapons).m_iCurrentWeapon==WEAPON_SNIPER) { + UsePressed(FALSE); + // if computer is pressed + } else if (ulNewButtons&PLACT_COMPUTER) { + ComputerPressed(); + } + + // if use is being held + if (ulNewButtons&PLACT_USE_HELD) { + bUseButtonHeld = TRUE; + } + + // if use is released + if (ulReleasedButtons&PLACT_USE_HELD) { + bUseButtonHeld = FALSE; + } + + // if sniper zoomin is pressed + if (ulNewButtons&PLACT_SNIPER_ZOOMIN) { + ApplySniperZoom(1); + } + + // if sniper zoomout is pressed + if (ulNewButtons&PLACT_SNIPER_ZOOMOUT) { + ApplySniperZoom(0); + } + + // if 3rd person view is pressed + if (ulNewButtons&PLACT_3RD_PERSON_VIEW) { + ChangePlayerView(); + } + + // apply center view + if( ulButtonsNow&PLACT_CENTER_VIEW) { + // center view with speed of 45 degrees per 1/20 seconds + paAction.pa_aRotation(2) += Clamp( -en_plViewpoint.pl_OrientationAngle(2)/_pTimer->TickQuantum, -900.0f, +900.0f); + } + }; + + void ApplySniperZoom( BOOL bZoomIn ) + { + // do nothing if not holding sniper and if not in sniping mode + if (((CPlayerWeapons&)*m_penWeapons).m_iCurrentWeapon!=WEAPON_SNIPER || + ((CPlayerWeapons&)*m_penWeapons).m_bSniping==FALSE) { + return; + } + BOOL bZoomChanged; + if (((CPlayerWeapons&)*m_penWeapons).SniperZoomDiscrete(bZoomIn, bZoomChanged)) { + if (bZoomChanged) { + PlaySound(m_soSniperZoom, SOUND_SNIPER_QZOOM, SOF_3D); + } + m_ulFlags|=PLF_ISZOOMING; + } + else + { + m_ulFlags&=~PLF_ISZOOMING; + PlaySound(m_soSniperZoom, SOUND_SILENCE, SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_StopEffect("SniperZoom");} + } + } + + // check if cheats can be active + BOOL CheatsEnabled(void) + { + return (GetSP()->sp_ctMaxPlayers==1||GetSP()->sp_bQuickTest) && m_penActionMarker==NULL && !_SE_DEMO; + } + + // Cheats + void Cheats(void) + { + BOOL bFlyOn = cht_bFly || cht_bGhost; + // fly mode + BOOL bIsFlying = !(GetPhysicsFlags() & EPF_TRANSLATEDBYGRAVITY); + if (bFlyOn && !bIsFlying) { + SetPhysicsFlags(GetPhysicsFlags() & ~(EPF_TRANSLATEDBYGRAVITY|EPF_ORIENTEDBYGRAVITY)); + en_plViewpoint.pl_OrientationAngle = ANGLE3D(0, 0, 0); + } else if (!bFlyOn && bIsFlying) { + SetPhysicsFlags(GetPhysicsFlags() | EPF_TRANSLATEDBYGRAVITY|EPF_ORIENTEDBYGRAVITY); + en_plViewpoint.pl_OrientationAngle = ANGLE3D(0, 0, 0); + } + + // ghost mode + BOOL bIsGhost = !(GetCollisionFlags() & ((ECBI_BRUSH|ECBI_MODEL)<CurrentTick(); + if (cht_bInvisible || tmDelta>0) { + SetFlags(GetFlags() | ENF_INVISIBLE); + } else { + SetFlags(GetFlags() & ~ENF_INVISIBLE); + } + + // cheat + if (cht_bGiveAll) { + cht_bGiveAll = FALSE; + ((CPlayerWeapons&)*m_penWeapons).CheatGiveAll(); + } + + if (cht_bKillAll) { + cht_bKillAll = FALSE; + KillAllEnemies(this); + } + + if (cht_bOpen) { + cht_bOpen = FALSE; + ((CPlayerWeapons&)*m_penWeapons).CheatOpen(); + } + + if (cht_bAllMessages) { + cht_bAllMessages = FALSE; + CheatAllMessages(); + } + + if (cht_bRefresh) { + cht_bRefresh = FALSE; + SetHealth(TopHealth()); + } + }; + + +/************************************************************ + * END OF PLAYER ACTIONS * + ************************************************************/ + + + // Get current placement that the player views from in absolute space. + void GetLerpedAbsoluteViewPlacement(CPlacement3D &plView) { + if (!(m_ulFlags&PLF_INITIALIZED)) { + plView = GetPlacement(); + _bDiscard3rdView=FALSE; + return; + } + + BOOL bSharpTurning = + (GetSettings()->ps_ulFlags&PSF_SHARPTURNING) && + _pNetwork->IsPlayerLocal((CPlayer*)GetPredictionTail()); + + // lerp player viewpoint + FLOAT fLerpFactor = _pTimer->GetLerpFactor(); + plView.Lerp(en_plLastViewpoint, en_plViewpoint, fLerpFactor); + + // moving banking and soft eyes + ((CPlayerAnimator&)*m_penAnimator).ChangeView(plView); + // body and head attachment animation + ((CPlayerAnimator&)*m_penAnimator).BodyAndHeadOrientation(plView); + + // return player eyes view + if (m_iViewState == PVT_PLAYEREYES || _bDiscard3rdView) { + CPlacement3D plPosLerped = GetLerpedPlacement(); + if (bSharpTurning) { + // get your prediction tail + CPlayer *pen = (CPlayer*)GetPredictionTail(); + // add local rotation + if (m_ulFlags&PLF_ISZOOMING) { + FLOAT fRotationDamping = ((CPlayerWeapons &)*m_penWeapons).m_fSniperFOV/((CPlayerWeapons &)*m_penWeapons).m_fSniperMaxFOV; + plView.pl_OrientationAngle = pen->en_plViewpoint.pl_OrientationAngle + (pen->m_aLocalRotation-pen->m_aLastRotation)*fRotationDamping; + } else { + plView.pl_OrientationAngle = pen->en_plViewpoint.pl_OrientationAngle + (pen->m_aLocalRotation-pen->m_aLastRotation); + } + // make sure it doesn't go out of limits + RoundViewAngle(plView.pl_OrientationAngle(2), PITCH_MAX); + RoundViewAngle(plView.pl_OrientationAngle(3), BANKING_MAX); + + // compensate for rotations that happen to the player without his/hers will + // (rotating brushes, weird gravities...) + // (these need to be lerped) + ANGLE3D aCurr = pen->GetPlacement().pl_OrientationAngle; + ANGLE3D aLast = pen->en_plLastPlacement.pl_OrientationAngle; + ANGLE3D aDesired = pen->en_aDesiredRotationRelative*_pTimer->TickQuantum; + FLOATmatrix3D mCurr; MakeRotationMatrixFast(mCurr, aCurr); + FLOATmatrix3D mLast; MakeRotationMatrixFast(mLast, aLast); + FLOATmatrix3D mDesired; MakeRotationMatrixFast(mDesired, aDesired); + mDesired = en_mRotation*(mDesired*!en_mRotation); + FLOATmatrix3D mForced = !mDesired*mCurr*!mLast; // = aCurr-aLast-aDesired; + ANGLE3D aForced; DecomposeRotationMatrixNoSnap(aForced, mForced); + if (aForced.MaxNorm()<1E-2) { + aForced = ANGLE3D(0,0,0); + } + FLOATquat3D qForced; qForced.FromEuler(aForced); + FLOATquat3D qZero; qZero.FromEuler(ANGLE3D(0,0,0)); + FLOATquat3D qLerped = Slerp(fLerpFactor, qZero, qForced); + FLOATmatrix3D m; + qLerped.ToMatrix(m); + m=m*mDesired*mLast; + DecomposeRotationMatrixNoSnap(plPosLerped.pl_OrientationAngle, m); + } + plView.RelativeToAbsoluteSmooth(plPosLerped); + // 3rd person view + } else if (m_iViewState == PVT_3RDPERSONVIEW) { + plView = m_pen3rdPersonView->GetLerpedPlacement(); + // camera view for player auto actions + } else if (m_iViewState == PVT_PLAYERAUTOVIEW) { + plView = m_penView->GetLerpedPlacement(); + // camera view for stored sequences + } else { + ASSERTALWAYS("Unknown player view"); + } + _bDiscard3rdView=FALSE; + }; + + // Get current entity that the player views from. + CEntity *GetViewEntity(void) { + // player eyes + if (m_iViewState == PVT_PLAYEREYES) { + return this; + // 3rd person view + } else if (m_iViewState == PVT_3RDPERSONVIEW) { + if (m_ulFlags&PLF_ISZOOMING) { + return this; + } + if (((CPlayerView&)*m_pen3rdPersonView).m_fDistance>2.0f) { + return m_pen3rdPersonView; + } else { + return this; + } + // camera + } else if (m_iViewState == PVT_PLAYERAUTOVIEW) { + if (((CPlayerView&)*m_penView).m_fDistance>2.0f) { + return m_penView; + } else { + return this; + } + // invalid view + } else { + ASSERTALWAYS("Unknown player view"); + return NULL; + } + }; + + void RenderChainsawParticles(BOOL bThird) + { + FLOAT fStretch=1.0f; + if( bThird) + { + fStretch=0.4f; + } + // render chainsaw cutting brush particles + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + for( INDEX iSpray=0; iSpray (bsld.bsld_tmLaunch+fLife)) { continue;} + Particles_BulletSpray(bsld.bsld_iRndBase, bsld.bsld_vPos, bsld.bsld_vG, + bsld.bsld_eptType, bsld.bsld_tmLaunch, bsld.bsld_vStretch*fStretch, 1.0f); + } + + // render chainsaw cutting model particles + for( INDEX iGore=0; iGore (gsld.gsld_tmLaunch+fLife)) { continue;} + FLOAT3D vPos=gsld.gsld_vPos; + if( bThird) + { + vPos=gsld.gsld_v3rdPos; + } + Particles_BloodSpray(gsld.gsld_sptType, vPos, gsld.gsld_vG, gsld.gsld_fGA, + gsld.gsld_boxHitted, gsld.gsld_vSpilDirection, + gsld.gsld_tmLaunch, gsld.gsld_fDamagePower*fStretch, gsld.gsld_colParticles); + } + } + + // Draw player interface on screen. + void RenderHUD( CPerspectiveProjection3D &prProjection, CDrawPort *pdp, + FLOAT3D vViewerLightDirection, COLOR colViewerLight, COLOR colViewerAmbient, + BOOL bRenderWeapon, INDEX iEye) + { + CPlacement3D plViewOld = prProjection.ViewerPlacementR(); + BOOL bSniping = ((CPlayerWeapons&)*m_penWeapons).m_bSniping; + // render weapon models if needed + // do not render weapon if sniping + BOOL bRenderModels = _pShell->GetINDEX("gfx_bRenderModels"); + if( hud_bShowWeapon && bRenderModels && !bSniping) { + // render weapons only if view is from player eyes + ((CPlayerWeapons&)*m_penWeapons).RenderWeaponModel(prProjection, pdp, + vViewerLightDirection, colViewerLight, colViewerAmbient, bRenderWeapon, iEye); + } + + // if is first person + if (m_iViewState == PVT_PLAYEREYES) + { + prProjection.ViewerPlacementL() = plViewOld; + prProjection.Prepare(); + CAnyProjection3D apr; + apr = prProjection; + Stereo_AdjustProjection(*apr, iEye, 1); + Particle_PrepareSystem(pdp, apr); + Particle_PrepareEntity( 2.0f, FALSE, FALSE, this); + RenderChainsawParticles(FALSE); + Particle_EndSystem(); + } + + // render crosshair if sniper zoom not active + CPlacement3D plView; + if (m_iViewState == PVT_PLAYEREYES) { + // player view + plView = en_plViewpoint; + plView.RelativeToAbsolute(GetPlacement()); + } else if (m_iViewState == PVT_3RDPERSONVIEW) { + // camera view + plView = ((CPlayerView&)*m_pen3rdPersonView).GetPlacement(); + } + if (!bSniping) { + ((CPlayerWeapons&)*m_penWeapons).RenderCrosshair(prProjection, pdp, plView); + } + + // get your prediction tail + CPlayer *pen = (CPlayer*)GetPredictionTail(); + // do screen blending + ULONG ulR=255, ulG=0, ulB=0; // red for wounding + ULONG ulA = pen->m_fDamageAmmount*5.0f; + + // if less than few seconds elapsed since last damage + FLOAT tmSinceWounding = _pTimer->CurrentTick() - pen->m_tmWoundedTime; + if( tmSinceWounding<4.0f) { + // decrease damage ammount + if( tmSinceWounding<0.001f) { ulA = (ulA+64)/2; } + } + + // add rest of blend ammount + ulA = ClampUp( ulA, (ULONG)224); + if (m_iViewState == PVT_PLAYEREYES) { + pdp->dp_ulBlendingRA += ulR*ulA; + pdp->dp_ulBlendingGA += ulG*ulA; + pdp->dp_ulBlendingBA += ulB*ulA; + pdp->dp_ulBlendingA += ulA; + } + + // add world glaring + { + COLOR colGlare = GetWorldGlaring(); + UBYTE ubR, ubG, ubB, ubA; + ColorToRGBA(colGlare, ubR, ubG, ubB, ubA); + if (ubA!=0) { + pdp->dp_ulBlendingRA += ULONG(ubR)*ULONG(ubA); + pdp->dp_ulBlendingGA += ULONG(ubG)*ULONG(ubA); + pdp->dp_ulBlendingBA += ULONG(ubB)*ULONG(ubA); + pdp->dp_ulBlendingA += ULONG(ubA); + } + } + + // do all queued screen blendings + pdp->BlendScreen(); + + // render status info line (if needed) + if( hud_bShowInfo) { + // get player or its predictor + BOOL bSnooping = FALSE; + CPlayer *penHUDPlayer = this; + CPlayer *penHUDOwner = this; + + if (penHUDPlayer->IsPredicted()) { + penHUDPlayer = (CPlayer *)penHUDPlayer->GetPredictor(); + } + + // check if snooping is needed + CPlayerWeapons *pen = (CPlayerWeapons*)&*penHUDPlayer->m_penWeapons; + TIME tmDelta = _pTimer->CurrentTick() - pen->m_tmSnoopingStarted; + if( tmDeltam_penTargeting!=NULL); + penHUDPlayer = (CPlayer*)&*pen->m_penTargeting; + bSnooping = TRUE; + } + DrawHUD( penHUDPlayer, pdp, bSnooping, penHUDOwner); + } + } + + +/************************************************************ + * SPECIAL FUNCTIONS * + ************************************************************/ + // try to find start marker for deathmatch (re)spawning + CEntity *GetDeathmatchStartMarker(void) + { + // get number of markers + CTString strPlayerStart = "Player Start - "; + INDEX ctMarkers = _pNetwork->GetNumberOfEntitiesWithName(strPlayerStart); + // if none + if (ctMarkers==0) { + // fail + return NULL; + } + // if only one + if (ctMarkers==1) { + // get that one + return _pNetwork->GetEntityWithName(strPlayerStart, 0); + } + // if at least two markers found... + + // create tables of markers and their distances from players + CStaticArray amdMarkers; + amdMarkers.New(ctMarkers); + // for each marker + {for(INDEX iMarker=0; iMarkerGetEntityWithName(strPlayerStart, iMarker); + if (amdMarkers[iMarker].md_ppm==NULL) { + return NULL; // (if there is any invalidity, fail completely) + } + // get min distance from any player + FLOAT fMinD = UpperLimit(0.0f); + for (INDEX iPlayer=0; iPlayerGetPlacement().pl_PositionVector- + ppl->GetPlacement().pl_PositionVector).Length(); + if (fD=amdMarkers[ctMarkers-1].md_fMinD); + // choose marker among one of the 50% farthest + INDEX ctFarMarkers = ctMarkers/2; + ASSERT(ctFarMarkers>0); + INDEX iStartMarker = IRnd()%ctFarMarkers; + // find first next marker that was not used lately + INDEX iMarker=iStartMarker; + FOREVER{ + if (_pTimer->CurrentTick()>amdMarkers[iMarker].md_ppm->m_tmLastSpawned+1.0f) { + break; + } + iMarker = (iMarker+1)%ctMarkers; + if (iMarker==iStartMarker) { + break; + } + } + // return that + return amdMarkers[iMarker].md_ppm; + } + +/************************************************************ + * INITIALIZE PLAYER * + ************************************************************/ + + void InitializePlayer() + { + // set viewpoint position inside the entity + en_plViewpoint.pl_OrientationAngle = ANGLE3D(0,0,0); + en_plViewpoint.pl_PositionVector = FLOAT3D(0.0f, plr_fViewHeightStand, 0.0f); + en_plLastViewpoint = en_plViewpoint; + + // clear properties + m_ulFlags &= PLF_INITIALIZED|PLF_LEVELSTARTED|PLF_RESPAWNINPLACE; // must not clear initialized flag + m_fFallTime = 0.0f; + m_pstState = PST_STAND; + m_fDamageAmmount = 0.0f; + m_tmWoundedTime = 0.0f; + m_tmInvisibility = 0.0f, + m_tmInvulnerability = 0.0f, + m_tmSeriousDamage = 0.0f, + m_tmSeriousSpeed = 0.0f, + + // initialize animator + ((CPlayerAnimator&)*m_penAnimator).Initialize(); + // restart weapons if needed + GetPlayerWeapons()->SendEvent(EStart()); + + // initialise last positions for particles + Particles_AfterBurner_Prepare(this); + + // set flags + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL|((ECBI_PLAYER)<sp_bCooperative && !GetSP()->sp_bSinglePlayer) { + INDEX iRow = iPlayer/4; + INDEX iCol = iPlayer%4; + vOffsetRel = FLOAT3D(-3.0f+iCol*2.0f, fOffsetY, -3.0f+iRow*2.0f); + } + + return vOffsetRel; + } + + + void RemapLevelNames(INDEX &iLevel) + { + switch(iLevel) { + case 10: + iLevel = 1; + break; + case 11: + iLevel = 2; + break; + case 12: + iLevel = 3; + break; + case 13: + iLevel = 4; + break; + case 14: + iLevel = 5; + break; + case 15: + iLevel = 6; + break; + case 21: + iLevel = 7; + break; + case 22: + iLevel = 8; + break; + case 23: + iLevel = 9; + break; + case 24: + iLevel = 10; + break; + case 31: + iLevel = 11; + break; + case 32: + iLevel = 12; + break; + case 33: + iLevel = 13; + break; + default: + iLevel = -1; + break; + } + } + + + void TeleportPlayer(enum WorldLinkType EwltType) + { + INDEX iLevel = -1; + CTString strLevelName = GetWorld()->wo_fnmFileName.FileName(); + + //strLevelName.ScanF("%02d_", &iLevel); + INDEX u, v; + u = v = -1; + strLevelName.ScanF("%01d_%01d_", &u, &v); + iLevel = u*10+v; + + RemapLevelNames(iLevel); + + if (iLevel>0) { + ((CSessionProperties*)GetSP())->sp_ulLevelsMask|=1<<(iLevel-1); + } + + // find player index + INDEX iPlayer = GetMyPlayerIndex(); + // player placement + CPlacement3D plSet = GetPlacement(); + // teleport in dummy space to avoid auto teleport frag + Teleport(CPlacement3D(FLOAT3D(32000.0f+100.0f*iPlayer, 32000.0f, 0), ANGLE3D(0, 0, 0))); + // force yourself to standing state + ForceCollisionBoxIndexChange(PLAYER_COLLISION_BOX_STAND); + en_plViewpoint.pl_PositionVector(2) = plr_fViewHeightStand; + ((CPlayerAnimator&)*m_penAnimator).m_bDisableAnimating = FALSE; + ((CPlayerAnimator&)*m_penAnimator).Stand(); + m_pstState = PST_STAND; + + // create offset from marker + FLOAT3D vOffsetRel = GetTeleportingOffset(); + + // no player start initially + BOOL bSetHealth = FALSE; // for getting health from marker + BOOL bAdjustHealth = FALSE; // for getting adjusting health to 50-100 interval + CEntity *pen = NULL; + if (GetSP()->sp_bCooperative) { + if (cht_iGoToMarker>=0) { + // try to find fast go marker + CTString strPlayerStart; + strPlayerStart.PrintF("Player Start - %d", (INDEX)cht_iGoToMarker); + pen = _pNetwork->GetEntityWithName(strPlayerStart, 0); + pen->SendEvent(ETrigger()); + cht_iGoToMarker = -1; + bSetHealth = TRUE; + bAdjustHealth = FALSE; + // if there is coop respawn marker + } else if (m_penMainMusicHolder!=NULL && !(m_ulFlags&PLF_CHANGINGLEVEL)) { + CMusicHolder *pmh = (CMusicHolder *)&*m_penMainMusicHolder; + if (pmh->m_penRespawnMarker!=NULL) { + // get it + pen = pmh->m_penRespawnMarker; + bSetHealth = TRUE; + bAdjustHealth = FALSE; + } + } + + // if quick start is enabled (in wed) + if (pen==NULL && GetSP()->sp_bQuickTest && m_strGroup=="") { + // try to find quick start marker + CTString strPlayerStart; + strPlayerStart.PrintF("Player Quick Start"); + pen = _pNetwork->GetEntityWithName(strPlayerStart, 0); + bSetHealth = TRUE; + bAdjustHealth = FALSE; + } + // if no start position yet + if (pen==NULL) { + // try to find normal start marker + CTString strPlayerStart; + strPlayerStart.PrintF("Player Start - %s", m_strGroup); + pen = _pNetwork->GetEntityWithName(strPlayerStart, 0); + if (m_strGroup=="") { + bSetHealth = TRUE; + bAdjustHealth = FALSE; + } else { + if (EwltType==WLT_FIXED) { + bSetHealth = FALSE; + bAdjustHealth = TRUE; + } else { + bSetHealth = FALSE; + bAdjustHealth = FALSE; + } + } + } + // if no start position yet + if (pen==NULL) { + // try to find normal start marker without group anyway + CTString strPlayerStart; + strPlayerStart.PrintF("Player Start - "); + pen = _pNetwork->GetEntityWithName(strPlayerStart, 0); + bSetHealth = TRUE; + bAdjustHealth = FALSE; + } + } else { + bSetHealth = TRUE; + bAdjustHealth = FALSE; + // try to find start marker by random + pen = GetDeathmatchStartMarker(); + if (pen!=NULL) { + ((CPlayerMarker&)*pen).m_tmLastSpawned = _pTimer->CurrentTick(); + } + } + + // if respawning in place + if ((m_ulFlags&PLF_RESPAWNINPLACE) && pen!=NULL && !((CPlayerMarker*)&*pen)->m_bNoRespawnInPlace) { + m_ulFlags &= ~PLF_RESPAWNINPLACE; + // set default params + SetHealth(TopHealth()); + m_iMana = GetSP()->sp_iInitialMana; + m_fArmor = 0.0f; + // teleport where you were when you were killed + Teleport(CPlacement3D(m_vDied, m_aDied)); + + // if start marker is found + } else if (pen!=NULL) { + // if there is no respawn marker yet + if (m_penMainMusicHolder!=NULL) { + CMusicHolder *pmh = (CMusicHolder *)&*m_penMainMusicHolder; + if (pmh->m_penRespawnMarker==NULL) { + // set it + pmh->m_penRespawnMarker = pen; + } + } + + CPlayerMarker &CpmStart = (CPlayerMarker&)*pen; + // set player characteristics + if (bSetHealth) { + SetHealth(CpmStart.m_fHealth/100.0f*TopHealth()); + m_iMana = GetSP()->sp_iInitialMana; + m_fArmor = CpmStart.m_fShield; + } else if (bAdjustHealth) { + FLOAT fHealth = GetHealth(); + FLOAT fTopHealth = TopHealth(); + if( fHealth < fTopHealth) { + SetHealth(ClampUp(fHealth+fTopHealth/2.0f, fTopHealth)); + } + } + + // if should start in computer + if (CpmStart.m_bStartInComputer && GetSP()->sp_bSinglePlayer) { + // mark that + if (_pNetwork->IsPlayerLocal(this)) { + cmp_ppenPlayer = this; + } + cmp_bInitialStart = TRUE; + } + + // start with first message linked to the marker + CMessageHolder *penMessage = (CMessageHolder *)&*CpmStart.m_penMessage; + // while there are some messages to add + while (penMessage!=NULL && IsOfClass(penMessage, "MessageHolder")) { + const CTFileName &fnmMessage = penMessage->m_fnmMessage; + // if player doesn't have that message in database + if (!HasMessage(fnmMessage)) { + // add the message + ReceiveComputerMessage(fnmMessage, 0); + } + // go to next message holder in list + penMessage = (CMessageHolder *)&*penMessage->m_penNext; + } + + // set weapons + if (!GetSP()->sp_bCooperative) { + ((CPlayerWeapons&)*m_penWeapons).InitializeWeapons(CpmStart.m_iGiveWeapons, 0, 0, + CpmStart.m_fMaxAmmoRatio); + } else { + ((CPlayerWeapons&)*m_penWeapons).InitializeWeapons(CpmStart.m_iGiveWeapons, CpmStart.m_iTakeWeapons, + GetSP()->sp_bInfiniteAmmo?0:CpmStart.m_iTakeAmmo, CpmStart.m_fMaxAmmoRatio); + } + // start position relative to link + if (EwltType == WLT_RELATIVE) { + plSet.AbsoluteToRelative(_SwcWorldChange.plLink); // relative to link position + plSet.RelativeToAbsolute(CpmStart.GetPlacement()); // absolute to start marker position + Teleport(plSet); + // fixed start position + } else if (EwltType == WLT_FIXED) { + CPlacement3D plNew = CpmStart.GetPlacement(); + vOffsetRel*=CpmStart.en_mRotation; + plNew.pl_PositionVector += vOffsetRel; + Teleport(plNew); + // error -> teleport to zero + } else { + ASSERTALWAYS("Unknown world link type"); + Teleport(CPlacement3D(FLOAT3D(0, 0, 0)+vOffsetRel, ANGLE3D(0, 0, 0))); + } + // if there is a start trigger target + if(CpmStart.m_penTarget!=NULL) { + SendToTarget(CpmStart.m_penTarget, EET_TRIGGER, this); + } + + // default start position + } else { + // set player characteristics + SetHealth(TopHealth()); + m_iMana = GetSP()->sp_iInitialMana; + m_fArmor = 0.0f; + // set weapons + ((CPlayerWeapons&)*m_penWeapons).InitializeWeapons(0, 0, 0, 0); + // start position + Teleport(CPlacement3D(FLOAT3D(0, 0, 0)+vOffsetRel, ANGLE3D(0, 0, 0))); + } + // send teleport event to all entities in range + SendEventInRange(ETeleport(), FLOATaabbox3D(GetPlacement().pl_PositionVector, 200.0f)); + // stop moving + ForceFullStop(); + + // remember maximum health + m_fMaxHealth = TopHealth(); + + // if in singleplayer mode + if (GetSP()->sp_bSinglePlayer && GetSP()->sp_gmGameMode!=CSessionProperties::GM_FLYOVER) { + CWorldSettingsController *pwsc = GetWSC(this); + if (pwsc!=NULL && pwsc->m_bNoSaveGame) { + NOTHING; + } else { + // save quick savegame + _pShell->Execute("gam_bQuickSave=1;"); + } + } + // remember level start time + if (!(m_ulFlags&PLF_LEVELSTARTED)) { + m_ulFlags |= PLF_LEVELSTARTED; + m_tmLevelStarted = _pNetwork->GetGameTime(); + } + // reset model appearance + CTString strDummy; + SetPlayerAppearance(GetModelObject(), NULL, strDummy, /*bPreview=*/FALSE); + ValidateCharacter(); + SetPlayerAppearance(&m_moRender, &en_pcCharacter, strDummy, /*bPreview=*/FALSE); + ParseGender(strDummy); + GetPlayerAnimator()->SetWeapon(); + m_ulFlags |= PLF_SYNCWEAPON; + + // spawn teleport effect + SpawnTeleport(); + // return from editor model (if was fragged into pieces) + SwitchToModel(); + m_tmSpawned = _pTimer->CurrentTick(); + + en_tmLastBreathed = _pTimer->CurrentTick()+0.1f; // do not take breath when spawned in air + }; + + // note: set estimated time in advance + void RecordEndOfLevelData(void) + { + // must not be called multiple times + ASSERT(!m_bEndOfLevel); + // clear analyses message + m_tmAnalyseEnd = 0; + m_bPendingMessage = FALSE; + m_tmMessagePlay = 0; + // mark end of level + m_iMayRespawn = 0; + m_bEndOfLevel = TRUE; + // remember end time + time((time_t*)&m_iEndTime); + // add time score + TIME tmLevelTime = _pTimer->CurrentTick()-m_tmLevelStarted; + m_psLevelStats.ps_tmTime = tmLevelTime; + m_psGameStats.ps_tmTime += tmLevelTime; + FLOAT fTimeDelta = ClampDn((FLOAT)(floor(m_tmEstTime)-floor(tmLevelTime)), 0.0f); + m_iTimeScore = floor(fTimeDelta*100.0f); + m_psLevelStats.ps_iScore+=m_iTimeScore; + m_psGameStats.ps_iScore+=m_iTimeScore; + + // record stats for this level and add to global table + CTString strStats; + strStats.PrintF(TRANS("%s\n Time: %s\n Score: %9d\n Kills: %03d/%03d\n Secrets: %02d/%02d\n"), + TranslateConst(en_pwoWorld->GetName(), 0), TimeToString(tmLevelTime), + m_psLevelStats.ps_iScore, + m_psLevelStats.ps_iKills, m_psLevelTotal.ps_iKills, + m_psLevelStats.ps_iSecrets, m_psLevelTotal.ps_iSecrets); + m_strLevelStats += strStats; + } + + // spawn teleport effect + void SpawnTeleport(void) + { + // if in singleplayer + if (GetSP()->sp_bSinglePlayer) { + // no spawn effects + return; + } + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_TELEPORT; + ese.vNormal = FLOAT3D(0,1,0); + FLOATaabbox3D box; + GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm()*2; + ese.vStretch = FLOAT3D(fEntitySize, fEntitySize, fEntitySize); + CEntityPointer penEffect = CreateEntity(GetPlacement(), CLASS_BASIC_EFFECT); + penEffect->Initialize(ese); + } + + + + // render particles + void RenderParticles(void) + { + FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + + // render empty shells + Particles_EmptyShells( this, m_asldData); + + if (Particle_GetViewer()==this) { + Particles_ViewerLocal(this); + } + else + { + // if is not first person + RenderChainsawParticles(TRUE); + // glowing powerups + if (GetFlags()&ENF_ALIVE){ + if (m_tmSeriousDamage>tmNow && m_tmInvulnerability>tmNow) { + Particles_ModelGlow(this, Max(m_tmSeriousDamage,m_tmInvulnerability),PT_STAR08, 0.15f, 2, 0.03f, 0xff00ff00); + } else if (m_tmInvulnerability>tmNow) { + Particles_ModelGlow(this, m_tmInvulnerability, PT_STAR05, 0.15f, 2, 0.03f, 0x3333ff00); + } else if (m_tmSeriousDamage>tmNow) { + Particles_ModelGlow(this, m_tmSeriousDamage, PT_STAR08, 0.15f, 2, 0.03f, 0xff777700); + } + if (m_tmSeriousSpeed>tmNow) { + Particles_RunAfterBurner(this, m_tmSeriousSpeed, 0.3f, 0); + } + if (!GetSP()->sp_bCooperative) { + CPlayerWeapons *wpn = GetPlayerWeapons(); + if (wpn->m_tmLastSniperFire == _pTimer->CurrentTick()) + { + CAttachmentModelObject &amoBody = *GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO); + FLOATmatrix3D m; + MakeRotationMatrix(m, amoBody.amo_plRelative.pl_OrientationAngle); + FLOAT3D vSource = wpn->m_vBulletSource + FLOAT3D(0.0f, 0.1f, -0.4f)*GetRotationMatrix()*m; + Particles_SniperResidue(this, vSource , wpn->m_vBulletTarget); + } + } + } + } + + // spirit particles + if( m_tmSpiritStart != 0.0f) + { + Particles_Appearing(this, m_tmSpiritStart); + } + } + + void TeleportToAutoMarker(CPlayerActionMarker *ppam) + { + // if we are in coop + if (GetSP()->sp_bCooperative && !GetSP()->sp_bSinglePlayer) { + // for each player + for(INDEX iPlayer=0; iPlayerGetPlacement(); + FLOAT3D vOffsetRel = ppl->GetTeleportingOffset(); + pl.pl_PositionVector += vOffsetRel*ppam->en_mRotation; + ppl->Teleport(pl, FALSE); + // remember new respawn place + ppl->m_vDied = pl.pl_PositionVector; + ppl->m_aDied = pl.pl_OrientationAngle; + } + } + + // otherwise + } else { + // put yourself at marker + CPlacement3D pl = ppam->GetPlacement(); + FLOAT3D vOffsetRel = GetTeleportingOffset(); + pl.pl_PositionVector += vOffsetRel*ppam->en_mRotation; + Teleport(pl, FALSE); + } + } + + // check whether this time we respawn in place or on marker + void CheckDeathForRespawnInPlace(EDeath eDeath) + { + // if respawning in place is not allowed + if (!GetSP()->sp_bRespawnInPlace) { + // skip further checks + return; + } + // if killed by a player or enemy + CEntity *penKiller = eDeath.eLastDamage.penInflictor; + if (IsOfClass(penKiller, "Player") || IsDerivedFromClass(penKiller, "Enemy Base")) { + // mark for respawning in place + m_ulFlags |= PLF_RESPAWNINPLACE; + m_vDied = GetPlacement().pl_PositionVector; + m_aDied = GetPlacement().pl_OrientationAngle; + } + } + +procedures: +/************************************************************ + * WOUNDED * + ************************************************************/ + Wounded(EDamage eDamage) { + return; + }; + + +/************************************************************ + * WORLD CHANGE * + ************************************************************/ + WorldChange() { + // if in single player + if (GetSP()->sp_bSinglePlayer) { + // mark world as visited + CTString strDummy("1"); + SaveStringVar(GetWorld()->wo_fnmFileName.NoExt()+".vis", strDummy); + } + // find music holder on new world + FindMusicHolder(); + // store group name + m_strGroup = _SwcWorldChange.strGroup; + TeleportPlayer((WorldLinkType)_SwcWorldChange.iType); + // setup light source + SetupLightSource(); + + // make sure we discontinue zooming + CPlayerWeapons *penWeapon = GetPlayerWeapons(); + penWeapon->m_fSniperFOVlast = penWeapon->m_fSniperFOV = penWeapon->m_fSniperMaxFOV; + penWeapon->m_bSniping=FALSE; + m_ulFlags&=~PLF_ISZOOMING; + + // turn off possible chainsaw engine sound + PlaySound(m_soWeaponAmbient, SOUND_SILENCE, SOF_3D); + + // update per-level stats + UpdateLevelStats(); + m_ulFlags |= PLF_INITIALIZED; + m_ulFlags &= ~PLF_CHANGINGLEVEL; + return; + }; + + WorldChangeDead() + { + // forbid respawning in-place when changing levels while dead + m_ulFlags &= ~PLF_RESPAWNINPLACE; + + // if in single player + if (GetSP()->sp_bSinglePlayer) { + // mark world as visited + CTString strDummy("1"); + SaveStringVar(GetWorld()->wo_fnmFileName.NoExt()+".vis", strDummy); + } + // find music holder on new world + FindMusicHolder(); + // store group name + + autocall Rebirth() EReturn; + + // setup light source + SetupLightSource(); + + // update per-level stats + UpdateLevelStats(); + m_ulFlags |= PLF_INITIALIZED; + m_ulFlags &= ~PLF_CHANGINGLEVEL; + return; + } + +/************************************************************ + * D E A T H * + ************************************************************/ + + Death(EDeath eDeath) + { + // stop firing when dead + ((CPlayerWeapons&)*m_penWeapons).SendEvent(EReleaseWeapon()); + // stop all looping ifeel effects + if(_pNetwork->IsPlayerLocal(this)) + { + IFeel_StopEffect("ChainsawFire"); + IFeel_StopEffect("FlamethrowerFire"); + IFeel_StopEffect("ChainsawIdle"); + IFeel_StopEffect("SniperZoom"); + IFeel_StopEffect("Minigun_rotate"); + } + + // make sure sniper zoom is stopped + CPlayerWeapons *penWeapon = GetPlayerWeapons(); + m_ulFlags&=~PLF_ISZOOMING; + penWeapon->m_bSniping = FALSE; + penWeapon->m_fSniperFOVlast = penWeapon->m_fSniperFOV = penWeapon->m_fSniperMaxFOV; + + // stop weapon sounds + PlaySound(m_soSniperZoom, SOUND_SILENCE, SOF_3D); + PlaySound(m_soWeaponAmbient, SOUND_SILENCE, SOF_3D); + + // stop rotating minigun + penWeapon->m_aMiniGunLast = penWeapon->m_aMiniGun; + + // if in single player, or if this is a predictor entity + if (GetSP()->sp_bSinglePlayer || IsPredictor()) { + // do not print anything + NOTHING; + // if in cooperative, but not single player + } else if (GetSP()->sp_bCooperative) { + // just print death message, no score updating + PrintPlayerDeathMessage(this, eDeath); + // check whether this time we respawn in place or on marker + CheckDeathForRespawnInPlace(eDeath); + // increase number of deaths + m_psLevelStats.ps_iDeaths += 1; + m_psGameStats.ps_iDeaths += 1; + // if not in cooperative, and not single player + } else { + // print death message + PrintPlayerDeathMessage(this, eDeath); + // get the killer pointer + CEntity *penKiller = eDeath.eLastDamage.penInflictor; + // initially, not killed by a player + CPlayer *pplKillerPlayer = NULL; + + // if killed by some entity + if (penKiller!=NULL) { + // if killed by player + if (IsOfClass(penKiller, "Player")) { + // if someone other then you + if (penKiller!=this) { + pplKillerPlayer = (CPlayer*)penKiller; + EReceiveScore eScore; + eScore.iPoints = m_iMana; + eDeath.eLastDamage.penInflictor->SendEvent(eScore); + eDeath.eLastDamage.penInflictor->SendEvent(EKilledEnemy()); + // if it was yourself + } else { + m_psLevelStats.ps_iScore -= m_iMana; + m_psGameStats.ps_iScore -= m_iMana; + m_psLevelStats.ps_iKills -= 1; + m_psGameStats.ps_iKills -= 1; + } + // if killed by non-player + } else { + m_psLevelStats.ps_iScore -= m_iMana; + m_psGameStats.ps_iScore -= m_iMana; + m_psLevelStats.ps_iKills -= 1; + m_psGameStats.ps_iKills -= 1; + } + // if killed by NULL (shouldn't happen, but anyway) + } else { + m_psLevelStats.ps_iScore -= m_iMana; + m_psGameStats.ps_iScore -= m_iMana; + m_psLevelStats.ps_iKills -= 1; + m_psGameStats.ps_iKills -= 1; + } + + // if playing scorematch + if (!GetSP()->sp_bUseFrags) { + // if killed by a player + if (pplKillerPlayer!=NULL) { + // print how much that player gained + CPrintF(TRANS(" %s: +%d points\n"), pplKillerPlayer->GetPlayerName(), m_iMana); + // if it was a suicide, or an accident + } else { + // print how much you lost + CPrintF(TRANS(" %s: -%d points\n"), GetPlayerName(), m_iMana); + } + } + + // increase number of deaths + m_psLevelStats.ps_iDeaths += 1; + m_psGameStats.ps_iDeaths += 1; + } + + // store last view + m_iLastViewState = m_iViewState; + + // mark player as death + SetFlags(GetFlags()&~ENF_ALIVE); + // stop player + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + SetDesiredRotation(ANGLE3D(0.0f, 0.0f, 0.0f)); + + // remove weapon from hand + ((CPlayerAnimator&)*m_penAnimator).RemoveWeapon(); + // kill weapon animations + GetPlayerWeapons()->SendEvent(EStop()); + + // if in deathmatch + if (!GetSP()->sp_bCooperative) { + // drop current weapon as item so others can pick it + GetPlayerWeapons()->DropWeapon(); + } + + + // play death + INDEX iAnim1; + INDEX iAnim2; + if (m_pstState == PST_SWIM || m_pstState == PST_DIVE) { + iAnim1 = PLAYER_ANIM_DEATH_UNDERWATER; + iAnim2 = BODY_ANIM_DEATH_UNDERWATER; + } else if (eDeath.eLastDamage.dmtType==DMT_SPIKESTAB) { + iAnim1 = PLAYER_ANIM_DEATH_SPIKES; + iAnim2 = BODY_ANIM_DEATH_SPIKES; + } else if (eDeath.eLastDamage.dmtType==DMT_ABYSS) { + iAnim1 = PLAYER_ANIM_ABYSSFALL; + iAnim2 = BODY_ANIM_ABYSSFALL; + } else { + FLOAT3D vFront; + GetHeadingDirection(0, vFront); + FLOAT fDamageDir = m_vDamage%vFront; + if (fDamageDir<0) { + if (Abs(fDamageDir)<10.0f) { + iAnim1 = PLAYER_ANIM_DEATH_EASYFALLBACK; + iAnim2 = BODY_ANIM_DEATH_EASYFALLBACK; + } else { + iAnim1 = PLAYER_ANIM_DEATH_BACK; + iAnim2 = BODY_ANIM_DEATH_BACK; + } + } else { + if (Abs(fDamageDir)<10.0f) { + iAnim1 = PLAYER_ANIM_DEATH_EASYFALLFORWARD; + iAnim2 = BODY_ANIM_DEATH_EASYFALLFORWARD; + } else { + iAnim1 = PLAYER_ANIM_DEATH_FORWARD; + iAnim2 = BODY_ANIM_DEATH_FORWARD; + } + } + } + en_plViewpoint.pl_OrientationAngle = ANGLE3D(0,0,0); + StartModelAnim(iAnim1, 0); + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(iAnim2, 0); + + // set physic flags + SetPhysicsFlags(EPF_MODEL_CORPSE); + SetCollisionFlags(ECF_CORPSE); + + // set density to float out of water + en_fDensity = 400.0f; + + // play sound + if (m_pstState==PST_DIVE) { + SetDefaultMouthPitch(); + PlaySound(m_soMouth, GenderSound(SOUND_DEATHWATER), SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_PlayEffect("DeathWater");} + } else { + SetDefaultMouthPitch(); + PlaySound(m_soMouth, GenderSound(SOUND_DEATH), SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_PlayEffect("Death");} + } + + // initialize death camera view + ASSERT(m_penView == NULL); + if (m_penView == NULL) { + m_penView = CreateEntity(GetPlacement(), CLASS_PLAYER_VIEW); + EViewInit eInit; + eInit.penOwner = this; + eInit.penCamera = NULL; + eInit.vtView = VT_PLAYERDEATH; + eInit.bDeathFixed = eDeath.eLastDamage.dmtType==DMT_ABYSS; + m_penView->Initialize(eInit); + } + + if (ShouldBlowUp()) { + BlowUp(); + } else { + // leave a stain beneath + LeaveStain(TRUE); + } + + m_iMayRespawn = 0; + // wait for anim of death + wait (1.2f) { + on (EBegin) : { + // set new view status + m_iViewState = PVT_PLAYERAUTOVIEW; + resume; + } + // when anim is finished + on (ETimer) : { + // allow respawning + m_iMayRespawn = 1; + resume; + } + // when damaged + on (EDamage eDamage) : { + if (eDamage.dmtType==DMT_ABYSS) { + if (m_penView!=NULL) { + ((CPlayerView*)&*m_penView)->m_bFixed = TRUE; + } + } + // if should blow up now (and not already blown up) + if (ShouldBlowUp()) { + // do it + BlowUp(); + } + resume; + } + on (EDeath) : { resume; } + // if player pressed fire + on (EEnd) : { + // NOTE: predictors must never respawn since player markers for respawning are not predicted + // if this is not predictor + if (!IsPredictor()) { + // stop waiting + stop; + } + } + // if autoaction is received + on (EAutoAction eAutoAction) : { + // if we are in coop + if (GetSP()->sp_bCooperative && !GetSP()->sp_bSinglePlayer) { + // if the marker is teleport marker + if (eAutoAction.penFirstMarker!=NULL && + ((CPlayerActionMarker*)&*eAutoAction.penFirstMarker)->m_paaAction == PAA_TELEPORT) { + // teleport there + TeleportToAutoMarker((CPlayerActionMarker*)&*eAutoAction.penFirstMarker); + } + } + // ignore the actions + resume; + } + on (EDisconnected) : { pass; } + on (EReceiveScore) : { pass; } + on (EKilledEnemy) : { pass; } + on (EPreLevelChange) : { pass; } + on (EPostLevelChange) : { pass; } + otherwise() : { resume; } + } + + return ERebirth(); + }; + + TheEnd() { + // if not playing demo + if (!_pNetwork->IsPlayingDemo()) { + // record high score in single player only + if (GetSP()->sp_bSinglePlayer) { + _pShell->Execute("gam_iRecordHighScore=0;"); + } + } + // if current difficulty is serious + if (GetSP()->sp_gdGameDifficulty==CSessionProperties::GD_EXTREME) { + // activate the mental mode + _pShell->Execute("sam_bMentalActivated=1;"); + } + + // stop firing when end + ((CPlayerWeapons&)*m_penWeapons).SendEvent(EReleaseWeapon()); + + // mark player as dead + SetFlags(GetFlags()&~ENF_ALIVE); + // stop player + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + SetDesiredRotation(ANGLE3D(0.0f, 0.0f, 0.0f)); + + // look straight + StartModelAnim(PLAYER_ANIM_STAND, 0); + ((CPlayerAnimator&)*m_penAnimator).BodyAnimationTemplate( + BODY_ANIM_NORMALWALK, BODY_ANIM_COLT_STAND, BODY_ANIM_SHOTGUN_STAND, BODY_ANIM_MINIGUN_STAND, + AOF_LOOPING|AOF_NORESTART); + + en_plViewpoint.pl_OrientationAngle = ANGLE3D(0,0,0); + + // call computer + m_bEndOfGame = TRUE; + SetGameEnd(); + + wait () { + on (EBegin) : { resume; } + on (EReceiveScore) : { pass; } + on (EKilledEnemy) : { pass; } + on (ECenterMessage) : { pass; } + otherwise() : { resume; } + } + }; + +/************************************************************ + * R E B I R T H * + ************************************************************/ + FirstInit() { + // clear use button and zoom flag + bUseButtonHeld = FALSE; + + // restore last view + m_iViewState = m_iLastViewState; + + // stop and kill camera + if (m_penView != NULL) { + ((CPlayerView&)*m_penView).SendEvent(EEnd()); + m_penView = NULL; + } + + FindMusicHolder(); + + // update per-level stats + UpdateLevelStats(); + + // initialize player (from PlayerMarker) + InitializePlayer(); + + // add statistics message + ReceiveComputerMessage(CTFILENAME("Data\\Messages\\Statistics\\Statistics.txt"), CMF_READ); + + if (GetSettings()->ps_ulFlags&PSF_PREFER3RDPERSON) { + ChangePlayerView(); + } + + return; + }; + + Rebirth() { + + bUseButtonHeld = FALSE; + + // restore last view + m_iViewState = m_iLastViewState; + // clear ammunition + if (!(m_ulFlags&PLF_RESPAWNINPLACE)) { + GetPlayerWeapons()->ClearWeapons(); + } + + // stop and kill camera + if (m_penView != NULL) { + ((CPlayerView&)*m_penView).SendEvent(EEnd()); + m_penView = NULL; + } + + // stop and kill flame + CEntityPointer penFlame = GetChildOfClass("Flame"); + if (penFlame!=NULL) + { + // send the event to stop burning + EStopFlaming esf; + esf.m_bNow=TRUE; + penFlame->SendEvent(esf); + } + + if (m_penView != NULL) { + ((CPlayerView&)*m_penView).SendEvent(EEnd()); + m_penView = NULL; + } + + FindMusicHolder(); + + // initialize player (from PlayerMarker) + InitializePlayer(); + + return EReturn(); + }; + + + // auto action - go to current marker + AutoGoToMarker(EVoid) + { + ULONG ulFlags = AOF_LOOPING|AOF_NORESTART; + + INDEX iAnim = GetModelObject()->GetAnim(); + if( iAnim!=PLAYER_ANIM_STAND) + { + ulFlags |= AOF_SMOOTHCHANGE; + } + + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.m_bAttacking = FALSE; + plan.BodyWalkAnimation(); + if (m_fAutoSpeed>plr_fSpeedForward/2) { + StartModelAnim(PLAYER_ANIM_RUN, ulFlags); + } else { + StartModelAnim(PLAYER_ANIM_NORMALWALK, ulFlags); + } + + // while not at marker + while ( + (m_penActionMarker->GetPlacement().pl_PositionVector- + GetPlacement().pl_PositionVector).Length()>1.0f) { + // wait a bit + autowait(_pTimer->TickQuantum); + } + + // return to auto-action loop + return EReturn(); + } + + // auto action - go to current marker and stop there + AutoGoToMarkerAndStop(EVoid) + { + ULONG ulFlags = AOF_LOOPING|AOF_NORESTART; + + INDEX iAnim = GetModelObject()->GetAnim(); + if( iAnim!=PLAYER_ANIM_STAND) + { + ulFlags |= AOF_SMOOTHCHANGE; + } + + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.BodyWalkAnimation(); + if (m_fAutoSpeed>plr_fSpeedForward/2) { + StartModelAnim(PLAYER_ANIM_RUN, ulFlags); + } else { + StartModelAnim(PLAYER_ANIM_NORMALWALK, ulFlags); + } + + // while not at marker + while ( + (m_penActionMarker->GetPlacement().pl_PositionVector- + GetPlacement().pl_PositionVector).Length()>m_fAutoSpeed*_pTimer->TickQuantum*2.00f) { + // wait a bit + autowait(_pTimer->TickQuantum); + } + // disable auto speed + m_fAutoSpeed = 0.0f; + + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.BodyStillAnimation(); + StartModelAnim(PLAYER_ANIM_STAND, AOF_LOOPING|AOF_NORESTART); + + // stop moving + ForceFullStop(); + + // return to auto-action loop + return EReturn(); + } + + // auto action - use an item + AutoUseItem(EVoid) + { + + // start pulling the item + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.BodyPullItemAnimation(); + //StartModelAnim(PLAYER_ANIM_STATUE_PULL, 0); + + autowait(0.2f); + + // item appears + CPlayerActionMarker *ppam = GetActionMarker(); + if (IsOfClass(ppam->m_penItem, "KeyItem")) { + CModelObject &moItem = ppam->m_penItem->GetModelObject()->GetAttachmentModel(0)->amo_moModelObject; + GetPlayerAnimator()->SetItem(&moItem); + } + + autowait(2.20f-0.2f); + + // the item is in place + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.BodyRemoveItem(); + // if marker points to a trigger + if (GetActionMarker()->m_penTrigger!=NULL) { + // trigger it + SendToTarget(GetActionMarker()->m_penTrigger, EET_TRIGGER, this); + } + + // fake that player has passed through the door controller + if (GetActionMarker()->m_penDoorController!=NULL) { + EPass ePass; + ePass.penOther = this; + GetActionMarker()->m_penDoorController->SendEvent(ePass); + } + + autowait(3.25f-2.20f); + + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.BodyRemoveItem(); + + // return to auto-action loop + return EReturn(); + } + + // auto action - pick an item + AutoPickItem(EVoid) + { + + // start pulling the item + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.BodyPickItemAnimation(); + StartModelAnim(PLAYER_ANIM_KEYLIFT, 0); + + autowait(1.2f); + + // if marker points to a trigger + if (GetActionMarker()->m_penTrigger!=NULL) { + // trigger it + SendToTarget(GetActionMarker()->m_penTrigger, EET_TRIGGER, this); + } + + // item appears + CPlayerActionMarker *ppam = GetActionMarker(); + if (IsOfClass(ppam->m_penItem, "KeyItem")) { + CModelObject &moItem = ppam->m_penItem->GetModelObject()->GetAttachmentModel(0)->amo_moModelObject; + GetPlayerAnimator()->SetItem(&moItem); + EPass ePass; + ePass.penOther = this; + ppam->m_penItem->SendEvent(ePass); + } + + autowait(3.6f-1.2f+GetActionMarker()->m_tmWait); + + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.BodyRemoveItem(); + + // return to auto-action loop + return EReturn(); + } + + AutoFallDown(EVoid) + { + StartModelAnim(PLAYER_ANIM_BRIDGEFALLPOSE, 0); + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(BODY_ANIM_BRIDGEFALLPOSE, 0); + + autowait(GetActionMarker()->m_tmWait); + + // return to auto-action loop + return EReturn(); + } + + AutoFallToAbys(EVoid) + { + StartModelAnim(PLAYER_ANIM_ABYSSFALL, AOF_LOOPING); + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(BODY_ANIM_ABYSSFALL, AOF_LOOPING); + + autowait(GetActionMarker()->m_tmWait); + + // return to auto-action loop + return EReturn(); + } + + // auto action - look around + AutoLookAround(EVoid) + { + StartModelAnim(PLAYER_ANIM_BACKPEDAL, 0); + m_vAutoSpeed = FLOAT3D(0,0,plr_fSpeedForward/4/0.75f); + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(BODY_ANIM_NORMALWALK, 0); + + autowait(GetModelObject()->GetCurrentAnimLength()/2); + + m_vAutoSpeed = FLOAT3D(0,0,0); + + // start looking around + StartModelAnim(PLAYER_ANIM_STAND, 0); + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(BODY_ANIM_LOOKAROUND, 0); + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + + // wait given time + autowait(moBody.GetCurrentAnimLength()+0.1f); + + // return to auto-action loop + return EReturn(); + } + + AutoTeleport(EVoid) + { + // teleport there + TeleportToAutoMarker(GetActionMarker()); + + // return to auto-action loop + return EReturn(); + } + + AutoAppear(EVoid) + { + // hide the model + SwitchToEditorModel(); + + // put it at marker + Teleport(GetActionMarker()->GetPlacement()); + // make it rotate in spawnpose + SetPhysicsFlags(GetPhysicsFlags() & ~(EPF_TRANSLATEDBYGRAVITY|EPF_ORIENTEDBYGRAVITY)); + m_ulFlags|=PLF_AUTOMOVEMENTS; + SetDesiredRotation(ANGLE3D(60,0,0)); + StartModelAnim(PLAYER_ANIM_SPAWNPOSE, AOF_LOOPING); + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(BODY_ANIM_SPAWNPOSE, AOF_LOOPING); + + // start stardust appearing + m_tmSpiritStart = _pTimer->CurrentTick(); + // wait till it appears + autowait(5); + + // start model appearing + SwitchToModel(); + m_tmFadeStart = _pTimer->CurrentTick(); + // wait till it appears + autowait(5); + // fixate full opacity + COLOR colAlpha = GetModelObject()->mo_colBlendColor; + GetModelObject()->mo_colBlendColor = colAlpha|0xFF; + + // put it to normal state + SetPhysicsFlags(GetPhysicsFlags() | EPF_TRANSLATEDBYGRAVITY|EPF_ORIENTEDBYGRAVITY); + SetDesiredRotation(ANGLE3D(0,0,0)); + m_ulFlags&=~PLF_AUTOMOVEMENTS; + + // play animation to fall down + StartModelAnim(PLAYER_ANIM_SPAWN_FALLDOWN, 0); + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(BODY_ANIM_SPAWN_FALLDOWN, 0); + + autowait(GetModelObject()->GetCurrentAnimLength()); + + // play animation to get up + StartModelAnim(PLAYER_ANIM_SPAWN_GETUP, AOF_SMOOTHCHANGE); + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(BODY_ANIM_SPAWN_GETUP, AOF_SMOOTHCHANGE); + + autowait(GetModelObject()->GetCurrentAnimLength()); + + // return to auto-action loop + return EReturn(); + } + + TravellingInBeam() + { + // put it at marker + Teleport(GetActionMarker()->GetPlacement()); + // make it rotate in spawnpose + SetPhysicsFlags(GetPhysicsFlags() & ~(EPF_TRANSLATEDBYGRAVITY|EPF_ORIENTEDBYGRAVITY)); + m_ulFlags|=PLF_AUTOMOVEMENTS; + SetDesiredRotation(ANGLE3D(60,0,0)); + SetDesiredTranslation(ANGLE3D(0,20.0f,0)); + StartModelAnim(PLAYER_ANIM_SPAWNPOSE, AOF_LOOPING); + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(BODY_ANIM_SPAWNPOSE, AOF_LOOPING); + // wait till it appears + autowait(8.0f); + // switch to model + SwitchToEditorModel(); + // return to auto-action loop + return EReturn(); + } + + LogoFireMinigun(EVoid) + { + // put it at marker + CPlacement3D pl = GetActionMarker()->GetPlacement(); + pl.pl_PositionVector += FLOAT3D(0, 0.01f, 0)*GetActionMarker()->en_mRotation; + Teleport(pl); + en_plViewpoint.pl_OrientationAngle(1) = 20.0f; + en_plLastViewpoint.pl_OrientationAngle = en_plViewpoint.pl_OrientationAngle; + + // stand in pose + StartModelAnim(PLAYER_ANIM_INTRO, AOF_LOOPING); + // remember time for rotating view start + m_tmMinigunAutoFireStart = _pTimer->CurrentTick(); + // wait some time for fade in and to look from left to right with out firing + //autowait(0.75f); + ((CPlayerWeapons&)*m_penWeapons).SendEvent(EFireWeapon()); + autowait(2.5f); + ((CPlayerWeapons&)*m_penWeapons).SendEvent(EReleaseWeapon()); + + // stop minigun shaking + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(BODY_ANIM_MINIGUN_STAND, 0); + + autowait(0.5f); + + // ---------- Apply shake + CWorldSettingsController *pwsc = NULL; + // obtain bcg viewer + CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) GetWorld()->GetBackgroundViewer(); + if( penBcgViewer != NULL) + { + pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController; + pwsc->m_tmShakeStarted = _pTimer->CurrentTick(); + pwsc->m_vShakePos = GetPlacement().pl_PositionVector; + pwsc->m_fShakeFalloff = 250.0f; + pwsc->m_fShakeFade = 3.0f; + + pwsc->m_fShakeIntensityZ = 0.1f*2.0f; + pwsc->m_tmShakeFrequencyZ = 5.0f; + pwsc->m_fShakeIntensityY = 0.0f; + pwsc->m_fShakeIntensityB = 0.0f; + + pwsc->m_bShakeFadeIn = FALSE; + + /* + pwsc->m_fShakeIntensityY = 0.1f*2.0f; + pwsc->m_tmShakeFrequencyY = 5.0f; + pwsc->m_fShakeIntensityB = 2.5f*1.5f; + pwsc->m_tmShakeFrequencyB = 7.2f; + */ + } + + // stop rotating body + m_tmMinigunAutoFireStart = -1; + autowait(5.0f); + IFeel_StopEffect(NULL); + autowait(5.0f); + + return EReturn(); + } + + AutoStoreWeapon(EVoid) + { + // store current weapon slowly + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.BodyAnimationTemplate(BODY_ANIM_WAIT, + BODY_ANIM_COLT_REDRAWSLOW, BODY_ANIM_SHOTGUN_REDRAWSLOW, BODY_ANIM_MINIGUN_REDRAWSLOW, + 0); + autowait(plan.m_fBodyAnimTime); + + m_iAutoOrgWeapon = ((CPlayerWeapons&)*m_penWeapons).m_iCurrentWeapon; + ((CPlayerWeapons&)*m_penWeapons).m_iCurrentWeapon = WEAPON_NONE; + ((CPlayerWeapons&)*m_penWeapons).m_iWantedWeapon = WEAPON_NONE; + m_soWeaponAmbient.Stop(); + + // sync apperances + GetPlayerAnimator()->SyncWeapon(); + // remove weapon attachment + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.m_iWeaponLast = m_iAutoOrgWeapon; + plan.RemoveWeapon(); + GetPlayerAnimator()->SyncWeapon(); + + ((CPlayerWeapons&)*m_penWeapons).m_iCurrentWeapon = (WeaponType) m_iAutoOrgWeapon; + plan.BodyAnimationTemplate(BODY_ANIM_WAIT, BODY_ANIM_COLT_DEACTIVATETOWALK, + BODY_ANIM_SHOTGUN_DEACTIVATETOWALK, BODY_ANIM_MINIGUN_DEACTIVATETOWALK, AOF_SMOOTHCHANGE); + ((CPlayerWeapons&)*m_penWeapons).m_iCurrentWeapon = WEAPON_NONE; + + autowait(plan.m_fBodyAnimTime); + + // return to auto-action loop + return EReturn(); + } + + // perform player auto actions + DoAutoActions(EVoid) + { + // don't look up/down + en_plViewpoint.pl_OrientationAngle = ANGLE3D(0,0,0); + // disable playeranimator animating + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.m_bDisableAnimating = TRUE; + + // while there is some marker + while (m_penActionMarker!=NULL && IsOfClass(m_penActionMarker, "PlayerActionMarker")) { + + // if should wait + if (GetActionMarker()->m_paaAction==PAA_WAIT) { + // play still anim + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(BODY_ANIM_WAIT, AOF_NORESTART|AOF_LOOPING); + // wait given time + autowait(GetActionMarker()->m_tmWait); + } else if (GetActionMarker()->m_paaAction==PAA_STOPANDWAIT) { + // play still anim + StartModelAnim(PLAYER_ANIM_STAND, 0); + CModelObject &moBody = GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(BODY_ANIM_WAIT, AOF_NORESTART|AOF_LOOPING); + // wait given time + autowait(GetActionMarker()->m_tmWait); + + // if should teleport here + } else if (GetActionMarker()->m_paaAction==PAA_APPEARING) { + autocall AutoAppear() EReturn; + } else if (GetActionMarker()->m_paaAction==PAA_TRAVELING_IN_BEAM) { + autocall TravellingInBeam() EReturn; + } else if (GetActionMarker()->m_paaAction==PAA_INTROSE_SELECT_WEAPON) { + // order playerweapons to select weapon + ESelectWeapon eSelect; + eSelect.iWeapon = 1; + ((CPlayerWeapons&)*m_penWeapons).SendEvent(eSelect); + } else if (GetActionMarker()->m_paaAction==PAA_LOGO_FIRE_INTROSE) { + autocall LogoFireMinigun() EReturn; + } else if (GetActionMarker()->m_paaAction==PAA_LOGO_FIRE_MINIGUN) { + autocall LogoFireMinigun() EReturn; + // if should appear here + } else if (GetActionMarker()->m_paaAction==PAA_TELEPORT) { + autocall AutoTeleport() EReturn; + + // if should wait for trigger + } else if (GetActionMarker()->m_paaAction==PAA_WAITFOREVER) { + // wait forever + wait() { + on (EBegin) : { resume; } + otherwise() : { pass; } + } + // if should store weapon + } else if (GetActionMarker()->m_paaAction==PAA_STOREWEAPON) { + autocall AutoStoreWeapon() EReturn; + + // if should draw weapon + } else if (GetActionMarker()->m_paaAction==PAA_DRAWWEAPON) { + // order playerweapons to select best weapon + ESelectWeapon eSelect; + eSelect.iWeapon = -4; + ((CPlayerWeapons&)*m_penWeapons).SendEvent(eSelect); + + // if should wait + } else if (GetActionMarker()->m_paaAction==PAA_LOOKAROUND) { + autocall AutoLookAround() EReturn; + + // if should use item + } else if (GetActionMarker()->m_paaAction==PAA_USEITEM) { + // use it + autocall AutoUseItem() EReturn; + + // if should pick item + } else if (GetActionMarker()->m_paaAction==PAA_PICKITEM) { + // pick it + autocall AutoPickItem() EReturn; + + // if falling from bridge + } else if (GetActionMarker()->m_paaAction==PAA_FALLDOWN) { + // fall + autocall AutoFallDown() EReturn; + + // if releasing player + } else if (GetActionMarker()->m_paaAction==PAA_RELEASEPLAYER) { + if (m_penCamera!=NULL) { + ((CCamera*)&*m_penCamera)->m_bStopMoving=TRUE; + } + m_penCamera = NULL; + // if currently not having any weapon in hand + if (GetPlayerWeapons()->m_iCurrentWeapon == WEAPON_NONE) { + // order playerweapons to select best weapon + ESelectWeapon eSelect; + eSelect.iWeapon = -4; + ((CPlayerWeapons&)*m_penWeapons).SendEvent(eSelect); + } + // sync weapon, just in case + m_ulFlags |= PLF_SYNCWEAPON; + m_tmSpiritStart = 0; + + // if start computer + } else if (GetActionMarker()->m_paaAction==PAA_STARTCOMPUTER) { + // mark that + if (_pNetwork->IsPlayerLocal(this) && GetSP()->sp_bSinglePlayer) { + cmp_ppenPlayer = this; + cmp_bInitialStart = TRUE; + } + + // if start introscroll + } else if (GetActionMarker()->m_paaAction==PAA_STARTINTROSCROLL) { + _pShell->Execute("sam_iStartCredits=1;"); + + // if start credits + } else if (GetActionMarker()->m_paaAction==PAA_STARTCREDITS) { + _pShell->Execute("sam_iStartCredits=2;"); + + // if stop scroller + } else if (GetActionMarker()->m_paaAction==PAA_STOPSCROLLER) { + _pShell->Execute("sam_iStartCredits=-1;"); + + // if should run to the marker + } else if (GetActionMarker()->m_paaAction==PAA_RUN) { + // go to it + m_fAutoSpeed = plr_fSpeedForward*GetActionMarker()->m_fSpeed; + autocall AutoGoToMarker() EReturn; + + // if should run to the marker and stop exactly there + } else if (GetActionMarker()->m_paaAction==PAA_RUNANDSTOP) { + // go to it + m_fAutoSpeed = plr_fSpeedForward*GetActionMarker()->m_fSpeed; + autocall AutoGoToMarkerAndStop() EReturn; + + // if should record end-of-level stats + } else if (GetActionMarker()->m_paaAction==PAA_RECORDSTATS) { + + if (GetSP()->sp_bSinglePlayer || GetSP()->sp_bPlayEntireGame) { + // remeber estimated time + m_tmEstTime = GetActionMarker()->m_tmWait; + // record stats + RecordEndOfLevelData(); + } else { + SetGameEnd(); + } + + // if should show statistics to the player + } else if (GetActionMarker()->m_paaAction==PAA_SHOWSTATS) { + // call computer + if (cmp_ppenPlayer==NULL && _pNetwork->IsPlayerLocal(this) && GetSP()->sp_bSinglePlayer) { + m_bEndOfLevel = TRUE; + cmp_ppenPlayer = this; + m_ulFlags|=PLF_DONTRENDER; + while(m_bEndOfLevel) { + wait(_pTimer->TickQuantum) { + on (ETimer) : { stop; } + on (EReceiveScore) : { pass; } + on (EKilledEnemy) : { pass; } + on (ECenterMessage) : { pass; } + on (EPostLevelChange) : { + m_ulFlags&=!PLF_DONTRENDER; + m_bEndOfLevel = FALSE; + pass; + } + otherwise() : { resume; } + } + } + m_ulFlags&=!PLF_DONTRENDER; + } + // if end of entire game + } else if (GetActionMarker()->m_paaAction==PAA_ENDOFGAME) { + + // record stats + jump TheEnd(); + } else if (GetActionMarker()->m_paaAction==PAA_NOGRAVITY) { + SetPhysicsFlags(GetPhysicsFlags() & ~(EPF_TRANSLATEDBYGRAVITY|EPF_ORIENTEDBYGRAVITY)); + if( GetActionMarker()->GetParent() != NULL) + { + SetParent(GetActionMarker()->GetParent()); + } + } else if (GetActionMarker()->m_paaAction==PAA_TURNONGRAVITY) { + SetPhysicsFlags(GetPhysicsFlags()|EPF_TRANSLATEDBYGRAVITY|EPF_ORIENTEDBYGRAVITY); + SetParent(NULL); + } + else if (TRUE) { + ASSERT(FALSE); + } + + // if marker points to a trigger + if (GetActionMarker()->m_penTrigger!=NULL && + GetActionMarker()->m_paaAction!=PAA_PICKITEM) { + // trigger it + SendToTarget(GetActionMarker()->m_penTrigger, EET_TRIGGER, this); + } + + // get next marker + m_penActionMarker = GetActionMarker()->m_penTarget; + } + + // disable auto speed + m_fAutoSpeed = 0.0f; + + // must clear marker, in case it was invalid + m_penActionMarker = NULL; + + // enable playeranimator animating + CPlayerAnimator &plan = (CPlayerAnimator&)*m_penAnimator; + plan.m_bDisableAnimating = FALSE; + + // return to main loop + return EVoid(); + } +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid evoid) + { + // remember start time + time((time_t*)&m_iStartTime); + + m_ctUnreadMessages = 0; + SetFlags(GetFlags()|ENF_CROSSESLEVELS|ENF_NOTIFYLEVELCHANGE); + InitAsEditorModel(); + + // set default model for physics etc + CTString strDummy; + SetPlayerAppearance(GetModelObject(), NULL, strDummy, /*bPreview=*/FALSE); + // set your real appearance if possible + ValidateCharacter(); + SetPlayerAppearance(&m_moRender, &en_pcCharacter, strDummy, /*bPreview=*/FALSE); + ParseGender(strDummy); + + // if unsuccessful + if (GetModelObject()->GetData()==NULL) { + // never proceed with initialization - player cannot work + return; + } + + //const FLOAT fSize = 2.1f/1.85f; + //GetModelObject()->StretchModel(FLOAT3D(fSize, fSize, fSize)); + ModelChangeNotify(); + + // wait a bit to allow other entities to start + wait(0.2f) { // this is 4 ticks, it has to be at least more than musicchanger for enemy counting + on (EBegin) : { resume; } + on (ETimer) : { stop; } + on (EDisconnected) : { + Destroy(); + return; + } + } + + // do not use predictor if not yet initialized + if (IsPredictor()) { // !!!!#### + Destroy(); + return; + } + + // appear + SwitchToModel(); + m_ulFlags|=PLF_INITIALIZED; + + // set initial vars + en_tmMaxHoldBreath = 60.0f; + en_fDensity = 1000.0f; // same density as water - to be able to dive freely + + ModelChangeNotify(); + + // spawn weapons + m_penWeapons = CreateEntity(GetPlacement(), CLASS_PLAYER_WEAPONS); + EWeaponsInit eInitWeapons; + eInitWeapons.penOwner = this; + m_penWeapons->Initialize(eInitWeapons); + + // spawn animator + m_penAnimator = CreateEntity(GetPlacement(), CLASS_PLAYER_ANIMATOR); + EAnimatorInit eInitAnimator; + eInitAnimator.penPlayer = this; + m_penAnimator->Initialize(eInitAnimator); + + // set sound default parameters + m_soMouth.Set3DParameters(50.0f, 10.0f, 1.0f, 1.0f); + m_soFootL.Set3DParameters(20.0f, 2.0f, 1.0f, 1.0f); + m_soFootR.Set3DParameters(20.0f, 2.0f, 1.0f, 1.0f); + m_soBody.Set3DParameters(25.0f, 5.0f, 1.0f, 1.0f); + m_soMessage.Set3DParameters(25.0f, 5.0f, 1.0f, 1.0f); + m_soSniperZoom.Set3DParameters(25.0f, 5.0f, 1.0f, 1.0f); + + // setup light source + SetupLightSource(); + + // set light animation if available + try { + m_aoLightAnimation.SetData_t(CTFILENAME("Animations\\BasicEffects.ani")); + } catch (char *strError) { + WarningMessage(TRANS("Cannot load Animations\\BasicEffects.ani: %s"), strError); + } + PlayLightAnim(LIGHT_ANIM_NONE, 0); + + wait() { + on (EBegin) : { call FirstInit(); } + on (ERebirth) : { call Rebirth(); } + on (EDeath eDeath) : { call Death(eDeath); } + on (EDamage eDamage) : { call Wounded(eDamage); } + on (EPreLevelChange) : { + m_ulFlags&=~PLF_INITIALIZED; + m_ulFlags|=PLF_CHANGINGLEVEL; + m_ulFlags &= ~PLF_LEVELSTARTED; + resume; + } + on (EPostLevelChange) : { + if (GetSP()->sp_bSinglePlayer || (GetFlags()&ENF_ALIVE)) { + call WorldChange(); + } else { + call WorldChangeDead(); + } + } + on (ETakingBreath eTakingBreath ) : { + SetDefaultMouthPitch(); + if (eTakingBreath.fBreathDelay<0.2f) { + PlaySound(m_soMouth, GenderSound(SOUND_INHALE0), SOF_3D); + } else if (eTakingBreath.fBreathDelay<0.8f) { + PlaySound(m_soMouth, GenderSound(SOUND_INHALE1), SOF_3D); + } else { + PlaySound(m_soMouth, GenderSound(SOUND_INHALE2), SOF_3D); + } + resume; + } + on (ECameraStart eStart) : { + m_penCamera = eStart.penCamera; + // stop player + if (m_penActionMarker==NULL) { + SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + SetDesiredRotation(ANGLE3D(0.0f, 0.0f, 0.0f)); + } + // stop firing + ((CPlayerWeapons&)*m_penWeapons).SendEvent(EReleaseWeapon()); + resume; + } + on (ECameraStop eCameraStop) : { + if (m_penCamera==eCameraStop.penCamera) { + m_penCamera = NULL; + } + resume; + } + on (ECenterMessage eMsg) : { + m_strCenterMessage = eMsg.strMessage; + m_tmCenterMessageEnd = _pTimer->CurrentTick()+eMsg.tmLength; + if (eMsg.mssSound==MSS_INFO) { + m_soMessage.Set3DParameters(25.0f, 5.0f, 1.0f, 1.0f); + PlaySound(m_soMessage, SOUND_INFO, SOF_3D|SOF_VOLUMETRIC|SOF_LOCAL); + } + resume; + } + on (EComputerMessage eMsg) : { + ReceiveComputerMessage(eMsg.fnmMessage, CMF_ANALYZE); + resume; + } + on (EVoiceMessage eMsg) : { + SayVoiceMessage(eMsg.fnmMessage); + resume; + } + on (EAutoAction eAutoAction) : { + // remember first marker + m_penActionMarker = eAutoAction.penFirstMarker; + // do the actions + call DoAutoActions(); + } + on (EReceiveScore eScore) : { + m_psLevelStats.ps_iScore += eScore.iPoints; + m_psGameStats.ps_iScore += eScore.iPoints; + m_iMana += eScore.iPoints*GetSP()->sp_fManaTransferFactor; + CheckHighScore(); + resume; + } + on (EKilledEnemy) : { + m_psLevelStats.ps_iKills += 1; + m_psGameStats.ps_iKills += 1; + resume; + } + on (ESecretFound) : { + m_psLevelStats.ps_iSecrets += 1; + m_psGameStats.ps_iSecrets += 1; + resume; + } + on (EWeaponChanged) : { + // make sure we discontinue zooming (even if not changing from sniper) + ((CPlayerWeapons&)*m_penWeapons).m_bSniping=FALSE; + m_ulFlags&=~PLF_ISZOOMING; + PlaySound(m_soSniperZoom, SOUND_SILENCE, SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_StopEffect("SniperZoom");} + resume; + } + // EEnd should not arrive here + on (EEnd) : { + ASSERT(FALSE); + resume; + } + // if player is disconnected + on (EDisconnected) : { + // exit the loop + stop; + } + // support for jumping using bouncers + on (ETouch eTouch) : { + if (IsOfClass(eTouch.penOther, "Bouncer")) { + JumpFromBouncer(this, eTouch.penOther); + // play jump sound + SetDefaultMouthPitch(); + PlaySound(m_soMouth, GenderSound(SOUND_JUMP), SOF_3D); + if(_pNetwork->IsPlayerLocal(this)) {IFeel_PlayEffect("Jump");} + } + resume; + } + } + + // we get here if the player is disconnected from the server + + // if we have some keys + if (!IsPredictor() && m_ulKeys!=0) { + // find first live player + CPlayer *penNextPlayer = NULL; + for(INDEX iPlayer=0; iPlayerGetFlags()&ENF_ALIVE) && !(pen->GetFlags()&ENF_DELETED) ) { + penNextPlayer = pen; + } + } + + // if any found + if (penNextPlayer!=NULL) { + // transfer keys to that player + CPrintF(TRANS("%s leaving, all keys transfered to %s\n"), + (const char*)m_strName, (const char*)penNextPlayer->GetPlayerName()); + penNextPlayer->m_ulKeys |= m_ulKeys; + } + } + + // spawn teleport effect + SpawnTeleport(); + + // cease to exist + m_penWeapons->Destroy(); + m_penAnimator->Destroy(); + if (m_penView!=NULL) { + m_penView->Destroy(); + } + if (m_pen3rdPersonView!=NULL) { + m_pen3rdPersonView->Destroy(); + } + Destroy(); + return; + }; +}; diff --git a/Sources/EntitiesMP/Player.h b/Sources/EntitiesMP/Player.h new file mode 100644 index 0000000..93761c4 --- /dev/null +++ b/Sources/EntitiesMP/Player.h @@ -0,0 +1,780 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Player_INCLUDED +#define _EntitiesMP_Player_INCLUDED 1 +extern DECL_DLL CEntityPropertyEnumType PlayerViewType_enum; +enum PlayerViewType { + PVT_PLAYEREYES = 0, + PVT_PLAYERAUTOVIEW = 1, + PVT_SCENECAMERA = 2, + PVT_3RDPERSONVIEW = 3, +}; +DECL_DLL inline void ClearToDefault(PlayerViewType &e) { e = (PlayerViewType)0; } ; +extern DECL_DLL CEntityPropertyEnumType PlayerState_enum; +enum PlayerState { + PST_STAND = 0, + PST_CROUCH = 1, + PST_SWIM = 2, + PST_DIVE = 3, + PST_FALL = 4, +}; +DECL_DLL inline void ClearToDefault(PlayerState &e) { e = (PlayerState)0; } ; +#define EVENTCODE_ECameraStart 0x01910000 +class DECL_DLL ECameraStart : public CEntityEvent { +public: +ECameraStart(); +CEntityEvent *MakeCopy(void); +CEntityPointer penCamera; +}; +DECL_DLL inline void ClearToDefault(ECameraStart &e) { e = ECameraStart(); } ; +#define EVENTCODE_ECameraStop 0x01910001 +class DECL_DLL ECameraStop : public CEntityEvent { +public: +ECameraStop(); +CEntityEvent *MakeCopy(void); +CEntityPointer penCamera; +}; +DECL_DLL inline void ClearToDefault(ECameraStop &e) { e = ECameraStop(); } ; +#define EVENTCODE_ERebirth 0x01910002 +class DECL_DLL ERebirth : public CEntityEvent { +public: +ERebirth(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(ERebirth &e) { e = ERebirth(); } ; +#define EVENTCODE_EDisconnected 0x01910003 +class DECL_DLL EDisconnected : public CEntityEvent { +public: +EDisconnected(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EDisconnected &e) { e = EDisconnected(); } ; +#define EVENTCODE_EAutoAction 0x01910004 +class DECL_DLL EAutoAction : public CEntityEvent { +public: +EAutoAction(); +CEntityEvent *MakeCopy(void); +CEntityPointer penFirstMarker; +}; +DECL_DLL inline void ClearToDefault(EAutoAction &e) { e = EAutoAction(); } ; +extern "C" DECL_DLL CDLLEntityClass CPlayer_DLLClass; +class DECL_DLL CPlayer : public CPlayerEntity { +public: +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + virtual void SetDefaultProperties(void); + CTString m_strName; + COLOR m_ulLastButtons; + FLOAT m_fArmor; + CTString m_strGroup; + INDEX m_ulKeys; + FLOAT m_fMaxHealth; + INDEX m_ulFlags; + CEntityPointer m_penWeapons; + CEntityPointer m_penAnimator; + CEntityPointer m_penView; + CEntityPointer m_pen3rdPersonView; + INDEX m_iViewState; + INDEX m_iLastViewState; + CAnimObject m_aoLightAnimation; + FLOAT m_fDamageAmmount; + FLOAT m_tmWoundedTime; + FLOAT m_tmScreamTime; + INDEX m_iGender; + enum PlayerState m_pstState; + FLOAT m_fFallTime; + FLOAT m_fSwimTime; + FLOAT m_tmOutOfWater; + FLOAT m_tmMoveSound; + BOOL m_bMoveSoundLeft; + FLOAT m_tmNextAmbientOnce; + FLOAT m_tmMouthSoundLast; + CEntityPointer m_penCamera; + CTString m_strCenterMessage; + FLOAT m_tmCenterMessageEnd; + BOOL m_bPendingMessage; + FLOAT m_tmMessagePlay; + FLOAT m_tmAnalyseEnd; + BOOL m_bComputerInvoked; + FLOAT m_tmAnimateInbox; + CEntityPointer m_penMainMusicHolder; + FLOAT m_tmLastDamage; + FLOAT m_fMaxDamageAmmount; + FLOAT3D m_vDamage; + FLOAT m_tmSpraySpawned; + FLOAT m_fSprayDamage; + CEntityPointer m_penSpray; + CSoundObject m_soWeapon0; + CSoundObject m_soWeapon1; + CSoundObject m_soWeapon2; + CSoundObject m_soWeapon3; + CSoundObject m_soWeaponAmbient; + CSoundObject m_soPowerUpBeep; + CSoundObject m_soMouth; + CSoundObject m_soFootL; + CSoundObject m_soFootR; + CSoundObject m_soBody; + CSoundObject m_soLocalAmbientLoop; + CSoundObject m_soLocalAmbientOnce; + CSoundObject m_soMessage; + CSoundObject m_soHighScore; + CSoundObject m_soSpeech; + CSoundObject m_soSniperZoom; + INDEX m_iMana; + FLOAT m_fManaFraction; + INDEX m_iHighScore; + INDEX m_iBeatenHighScore; + FLOAT m_tmLatency; + FLOAT m_tmLatencyLastAvg; + FLOAT m_tmLatencyAvgSum; + INDEX m_ctLatencyAvg; + BOOL m_bEndOfLevel; + BOOL m_bEndOfGame; + INDEX m_iMayRespawn; + FLOAT m_tmSpawned; + FLOAT3D m_vDied; + FLOAT3D m_aDied; + FLOAT m_tmEstTime; + INDEX m_iTimeScore; + INDEX m_iStartTime; + INDEX m_iEndTime; + FLOAT m_tmLevelStarted; + CTString m_strLevelStats; + CEntityPointer m_penActionMarker; + FLOAT m_fAutoSpeed; + INDEX m_iAutoOrgWeapon; + FLOAT3D m_vAutoSpeed; + FLOAT m_tmSpiritStart; + FLOAT m_tmFadeStart; + FLOAT m_tmLastPicked; + CTString m_strPickedName; + FLOAT m_fPickedAmmount; + FLOAT m_fPickedMana; + INDEX m_iLastHealth; + INDEX m_iLastArmor; + INDEX m_iLastAmmo; + FLOAT m_tmHealthChanged; + FLOAT m_tmArmorChanged; + FLOAT m_tmAmmoChanged; + FLOAT m_tmMinigunAutoFireStart; + FLOAT3D m_vLastStain; + ANGLE3D m_aLastRotation; + ANGLE3D m_aLastViewRotation; + FLOAT3D m_vLastTranslation; + ANGLE3D m_aLocalRotation; + ANGLE3D m_aLocalViewRotation; + FLOAT3D m_vLocalTranslation; + FLOAT m_tmInvisibility; + FLOAT m_tmInvulnerability; + FLOAT m_tmSeriousDamage; + FLOAT m_tmSeriousSpeed; + FLOAT m_tmInvisibilityMax; + FLOAT m_tmInvulnerabilityMax; + FLOAT m_tmSeriousDamageMax; + FLOAT m_tmSeriousSpeedMax; + FLOAT m_tmChainShakeEnd; + FLOAT m_fChainShakeStrength; + FLOAT m_fChainShakeFreqMod; + FLOAT m_fChainsawShakeDX; + FLOAT m_fChainsawShakeDY; + INDEX m_iSeriousBombCount; + INDEX m_iLastSeriousBombCount; + FLOAT m_tmSeriousBombFired; + CEntityPointer m_penPrediction; +ShellLaunchData ShellLaunchData_array; +INDEX m_iFirstEmptySLD; +BulletSprayLaunchData BulletSprayLaunchData_array; +INDEX m_iFirstEmptyBSLD; +GoreSprayLaunchData GoreSprayLaunchData_array; +INDEX m_iFirstEmptyGSLD; +ULONG ulButtonsNow; +ULONG ulButtonsBefore; +ULONG ulNewButtons; +ULONG ulReleasedButtons; +BOOL bUseButtonHeld; +CSoundListener sliSound; +CLightSource m_lsLightSource; +TIME m_tmPredict; +CDynamicStackArray < CCompMessageID > m_acmiMessages; +INDEX m_ctUnreadMessages; +PlayerStats m_psLevelStats; +PlayerStats m_psLevelTotal; +PlayerStats m_psGameStats; +PlayerStats m_psGameTotal; +CModelObject m_moRender; + +#line 1284 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +INDEX GenderSound(INDEX iSound); + +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void AddBouble(FLOAT3D vPos,FLOAT3D vSpeedRelative); + +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ClearShellLaunchData(void); + +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void AddBulletSpray(FLOAT3D vPos,EffectParticlesType eptType,FLOAT3D vStretch); + +#line 1326 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ClearBulletSprayLaunchData(void); + +#line 1335 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void AddGoreSpray(FLOAT3D vPos,FLOAT3D v3rdPos,SprayParticlesType sptType,FLOAT3D vSpilDirection, +#line 1336 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOATaabbox3D boxHitted,FLOAT fDamagePower,COLOR colParticles); + +#line 1353 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ClearGoreSprayLaunchData(void); + CPlayer(void); + +#line 1377 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +class CPlayerWeapons * GetPlayerWeapons(void); + +#line 1382 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +class CPlayerAnimator * GetPlayerAnimator(void); + +#line 1388 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlayerSettings * GetSettings(void); + void Copy(CEntity & enOther,ULONG ulFlags); + +#line 1424 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void UpdateLatency(FLOAT tmLatencyNow); + +#line 1451 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ValidateCharacter(void); + +#line 1461 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ParseGender(CTString & strName); + +#line 1472 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CheckHighScore(void); + +#line 1495 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString GetPredictName(void)const; + +#line 1508 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void Write_t(CTStream * ostr); + +#line 1524 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void Read_t(CTStream * istr); + +#line 1563 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CLightSource * GetLightSource(void); + +#line 1573 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SetPredictionTime(TIME tmAdvance); + +#line 1579 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME GetPredictionTime(void); + +#line 1585 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT GetPredictionRange(void); + +#line 1591 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void AddDependentsToPrediction(void); + +#line 1600 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME GetStatsInGameTimeLevel(void); + +#line 1608 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TIME GetStatsInGameTimeGame(void); + +#line 1617 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT GetStatsRealWorldTime(void); + +#line 1628 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CTString GetStatsRealWorldStarted(void); + void GetStats(CTString & strStats,const CompStatType csType,INDEX ctCharsPerRow); + +#line 1668 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void GetShortStats(CTString & strStats); + +#line 1676 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void GetDetailStatsDM(CTString & strStats); + +#line 1751 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void GetDetailStatsCoop(CTString & strStats); + +#line 1829 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void GetDetailStatsSP(CTString & strStats,INDEX iCoopType); + +#line 1917 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void GetGameAgentPlayerInfo(INDEX iPlayer,CTString & strOut); + +#line 1948 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL HasMessage(const CTFileName & fnmMessage); + +#line 1962 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ReceiveComputerMessage(const CTFileName & fnmMessage,ULONG ulFlags); + +#line 1984 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SayVoiceMessage(const CTFileName & fnmMessage); + +#line 1994 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CheatAllMessagesDir(const CTString & strDir,ULONG ulFlags); + +#line 2009 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CheatAllMessages(void); + +#line 2024 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ItemPicked(const CTString & strName,FLOAT fAmmount); + +#line 2046 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SetupLightSource(void); + +#line 2063 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void PlayLightAnim(INDEX iAnim,ULONG ulFlags); + +#line 2070 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 2098 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CModelObject * GetModelForRendering(void); + +#line 2168 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +class CPlayerActionMarker * GetActionMarker(void); + +#line 2173 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void FindMusicHolder(void); + +#line 2181 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void UpdateLevelStats(void); + +#line 2204 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL IsFuss(void); + +#line 2215 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SetDefaultMouthPitch(void); + +#line 2219 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SetRandomMouthPitch(FLOAT fMin,FLOAT fMax); + +#line 2223 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SetSpeakMouthPitch(void); + +#line 2229 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ApplyShaking(CPlacement3D & plViewer); + +#line 2282 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +COLOR GetWorldGlaring(void); + +#line 2295 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RenderScroll(CDrawPort * pdp); + +#line 2305 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RenderCredits(CDrawPort * pdp); + +#line 2315 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RenderTextFX(CDrawPort * pdp); + +#line 2325 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RenderHudPicFX(CDrawPort * pdp); + +#line 2340 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SetupView(CDrawPort * pdp,CAnyProjection3D & apr,CEntity * & penViewer, +#line 2341 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CPlacement3D & plViewer,COLOR & colBlend,BOOL bCamera); + +#line 2414 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ListenFromEntity(CEntity * penListener,const CPlacement3D & plSound); + +#line 2445 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RenderDummyView(CDrawPort * pdp); + +#line 2466 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RenderPlayerView(CDrawPort * pdp,BOOL bShowExtras); + +#line 2551 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RenderCameraView(CDrawPort * pdp,BOOL bListen); + +#line 2632 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RenderGameView(CDrawPort * pdp,void * pvUserData); + +#line 2708 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void PreMoving(void); + +#line 2720 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void DoMoving(void); + +#line 2734 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void PostMoving(void); + +#line 2785 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SetUnconnected(void); + +#line 2805 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SetConnected(void); + +#line 2817 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL IsConnected(void)const; + +#line 2823 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ChecksumForSync(ULONG & ulCRC,INDEX iExtensiveSyncCheck); + +#line 2836 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck); + +#line 2851 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +virtual void LeaveStain(BOOL bGrow); + +#line 2887 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void DamageImpact(enum DamageType dmtType, +#line 2888 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 3030 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 3031 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 3192 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL ShouldBlowUp(void); + +#line 3207 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void BlowUp(void); + +#line 3261 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void * GetEntityInfo(void); + +#line 3279 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL ReceiveItem(const CEntityEvent & ee); + +#line 3417 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ChangePlayerView(); + +#line 3448 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ComputerPressed(void); + +#line 3465 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void UsePressed(BOOL bOrComputer); + +#line 3540 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SetGameEnd(void); + +#line 3554 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CheckGameEnd(void); + +#line 3579 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void PreapplyAction(const CPlayerAction & paAction); + +#line 3584 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ApplyAction(const CPlayerAction & paOriginal,FLOAT tmLatency); + +#line 3750 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void Disconnect(void); + +#line 3761 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CharacterChanged(const CPlayerCharacter & pcNew); + +#line 3817 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void AliveActions(const CPlayerAction & pa); + +#line 3851 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void AutoActions(const CPlayerAction & pa); + +#line 3937 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void GetLerpedWeaponPosition(FLOAT3D vRel,CPlacement3D & pl); + +#line 3946 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SpawnBubbles(INDEX ctBubbles); + +#line 3961 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void PlayPowerUpSound(void); + +#line 3966 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ActiveActions(const CPlayerAction & paAction); + +#line 4386 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RoundViewAngle(ANGLE & aViewAngle,ANGLE aRound); + +#line 4396 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void DeathActions(const CPlayerAction & paAction); + +#line 4461 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ButtonsActions(CPlayerAction & paAction); + +#line 4572 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void ApplySniperZoom(BOOL bZoomIn); + +#line 4595 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL CheatsEnabled(void); + +#line 4601 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void Cheats(void); + +#line 4664 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void GetLerpedAbsoluteViewPlacement(CPlacement3D & plView); + +#line 4739 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * GetViewEntity(void); + +#line 4767 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RenderChainsawParticles(BOOL bThird); + +#line 4803 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RenderHUD(CPerspectiveProjection3D & prProjection,CDrawPort * pdp, +#line 4804 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D vViewerLightDirection,COLOR colViewerLight,COLOR colViewerAmbient, +#line 4805 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +BOOL bRenderWeapon,INDEX iEye); + +#line 4912 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +CEntity * GetDeathmatchStartMarker(void); + +#line 4981 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void InitializePlayer(); + +#line 5017 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FLOAT3D GetTeleportingOffset(void); + +#line 5035 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RemapLevelNames(INDEX & iLevel); + +#line 5084 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void TeleportPlayer(enum WorldLinkType EwltType); + +#line 5329 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RecordEndOfLevelData(void); + +#line 5362 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void SpawnTeleport(void); + +#line 5384 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void RenderParticles(void); + +#line 5431 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void TeleportToAutoMarker(CPlayerActionMarker * ppam); + +#line 5461 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +void CheckDeathForRespawnInPlace(EDeath eDeath); +#define STATE_CPlayer_Wounded 0x01910005 + BOOL +#line 5482 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Wounded(const CEntityEvent &__eeInput); +#define STATE_CPlayer_WorldChange 0x01910006 + BOOL +#line 5490 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +WorldChange(const CEntityEvent &__eeInput); +#define STATE_CPlayer_WorldChangeDead 0x01910007 + BOOL +#line 5521 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +WorldChangeDead(const CEntityEvent &__eeInput); + BOOL H0x01910008_WorldChangeDead_01(const CEntityEvent &__eeInput); + BOOL H0x01910009_WorldChangeDead_02(const CEntityEvent &__eeInput); +#define STATE_CPlayer_Death 0x0191000a + BOOL +#line 5552 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Death(const CEntityEvent &__eeInput); + BOOL H0x0191000b_Death_01(const CEntityEvent &__eeInput); + BOOL H0x0191000c_Death_02(const CEntityEvent &__eeInput); +#define STATE_CPlayer_TheEnd 0x0191000d + BOOL +#line 5812 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TheEnd(const CEntityEvent &__eeInput); + BOOL H0x0191000e_TheEnd_01(const CEntityEvent &__eeInput); + BOOL H0x0191000f_TheEnd_02(const CEntityEvent &__eeInput); +#define STATE_CPlayer_FirstInit 0x01910010 + BOOL +#line 5859 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FirstInit(const CEntityEvent &__eeInput); +#define STATE_CPlayer_Rebirth 0x01910011 + BOOL +#line 5890 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Rebirth(const CEntityEvent &__eeInput); +#define STATE_CPlayer_AutoGoToMarker 0x01910012 + BOOL +#line 5932 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoGoToMarker(const CEntityEvent &__eeInput); + BOOL H0x01910013_AutoGoToMarker_01(const CEntityEvent &__eeInput); + BOOL H0x01910014_AutoGoToMarker_02(const CEntityEvent &__eeInput); + BOOL H0x01910015_AutoGoToMarker_03(const CEntityEvent &__eeInput); + BOOL H0x01910016_AutoGoToMarker_04(const CEntityEvent &__eeInput); +#define STATE_CPlayer_AutoGoToMarkerAndStop 0x01910017 + BOOL +#line 5964 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoGoToMarkerAndStop(const CEntityEvent &__eeInput); + BOOL H0x01910018_AutoGoToMarkerAndStop_01(const CEntityEvent &__eeInput); + BOOL H0x01910019_AutoGoToMarkerAndStop_02(const CEntityEvent &__eeInput); + BOOL H0x0191001a_AutoGoToMarkerAndStop_03(const CEntityEvent &__eeInput); + BOOL H0x0191001b_AutoGoToMarkerAndStop_04(const CEntityEvent &__eeInput); +#define STATE_CPlayer_AutoUseItem 0x0191001c + BOOL +#line 6004 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoUseItem(const CEntityEvent &__eeInput); + BOOL H0x0191001d_AutoUseItem_01(const CEntityEvent &__eeInput); + BOOL H0x0191001e_AutoUseItem_02(const CEntityEvent &__eeInput); + BOOL H0x0191001f_AutoUseItem_03(const CEntityEvent &__eeInput); + BOOL H0x01910020_AutoUseItem_04(const CEntityEvent &__eeInput); + BOOL H0x01910021_AutoUseItem_05(const CEntityEvent &__eeInput); + BOOL H0x01910022_AutoUseItem_06(const CEntityEvent &__eeInput); +#define STATE_CPlayer_AutoPickItem 0x01910023 + BOOL +#line 6049 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoPickItem(const CEntityEvent &__eeInput); + BOOL H0x01910024_AutoPickItem_01(const CEntityEvent &__eeInput); + BOOL H0x01910025_AutoPickItem_02(const CEntityEvent &__eeInput); + BOOL H0x01910026_AutoPickItem_03(const CEntityEvent &__eeInput); + BOOL H0x01910027_AutoPickItem_04(const CEntityEvent &__eeInput); +#define STATE_CPlayer_AutoFallDown 0x01910028 + BOOL +#line 6084 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoFallDown(const CEntityEvent &__eeInput); + BOOL H0x01910029_AutoFallDown_01(const CEntityEvent &__eeInput); + BOOL H0x0191002a_AutoFallDown_02(const CEntityEvent &__eeInput); +#define STATE_CPlayer_AutoFallToAbys 0x0191002b + BOOL +#line 6096 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoFallToAbys(const CEntityEvent &__eeInput); + BOOL H0x0191002c_AutoFallToAbys_01(const CEntityEvent &__eeInput); + BOOL H0x0191002d_AutoFallToAbys_02(const CEntityEvent &__eeInput); +#define STATE_CPlayer_AutoLookAround 0x0191002e + BOOL +#line 6109 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoLookAround(const CEntityEvent &__eeInput); + BOOL H0x0191002f_AutoLookAround_01(const CEntityEvent &__eeInput); + BOOL H0x01910030_AutoLookAround_02(const CEntityEvent &__eeInput); + BOOL H0x01910031_AutoLookAround_03(const CEntityEvent &__eeInput); + BOOL H0x01910032_AutoLookAround_04(const CEntityEvent &__eeInput); +#define STATE_CPlayer_AutoTeleport 0x01910033 + BOOL +#line 6133 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoTeleport(const CEntityEvent &__eeInput); +#define STATE_CPlayer_AutoAppear 0x01910034 + BOOL +#line 6142 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoAppear(const CEntityEvent &__eeInput); + BOOL H0x01910035_AutoAppear_01(const CEntityEvent &__eeInput); + BOOL H0x01910036_AutoAppear_02(const CEntityEvent &__eeInput); + BOOL H0x01910037_AutoAppear_03(const CEntityEvent &__eeInput); + BOOL H0x01910038_AutoAppear_04(const CEntityEvent &__eeInput); + BOOL H0x01910039_AutoAppear_05(const CEntityEvent &__eeInput); + BOOL H0x0191003a_AutoAppear_06(const CEntityEvent &__eeInput); + BOOL H0x0191003b_AutoAppear_07(const CEntityEvent &__eeInput); + BOOL H0x0191003c_AutoAppear_08(const CEntityEvent &__eeInput); +#define STATE_CPlayer_TravellingInBeam 0x0191003d + BOOL +#line 6194 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TravellingInBeam(const CEntityEvent &__eeInput); + BOOL H0x0191003e_TravellingInBeam_01(const CEntityEvent &__eeInput); + BOOL H0x0191003f_TravellingInBeam_02(const CEntityEvent &__eeInput); +#define STATE_CPlayer_LogoFireMinigun 0x01910040 + BOOL +#line 6214 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +LogoFireMinigun(const CEntityEvent &__eeInput); + BOOL H0x01910041_LogoFireMinigun_01(const CEntityEvent &__eeInput); + BOOL H0x01910042_LogoFireMinigun_02(const CEntityEvent &__eeInput); + BOOL H0x01910043_LogoFireMinigun_03(const CEntityEvent &__eeInput); + BOOL H0x01910044_LogoFireMinigun_04(const CEntityEvent &__eeInput); + BOOL H0x01910045_LogoFireMinigun_05(const CEntityEvent &__eeInput); + BOOL H0x01910046_LogoFireMinigun_06(const CEntityEvent &__eeInput); + BOOL H0x01910047_LogoFireMinigun_07(const CEntityEvent &__eeInput); + BOOL H0x01910048_LogoFireMinigun_08(const CEntityEvent &__eeInput); +#define STATE_CPlayer_AutoStoreWeapon 0x01910049 + BOOL +#line 6275 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoStoreWeapon(const CEntityEvent &__eeInput); + BOOL H0x0191004a_AutoStoreWeapon_01(const CEntityEvent &__eeInput); + BOOL H0x0191004b_AutoStoreWeapon_02(const CEntityEvent &__eeInput); + BOOL H0x0191004c_AutoStoreWeapon_03(const CEntityEvent &__eeInput); + BOOL H0x0191004d_AutoStoreWeapon_04(const CEntityEvent &__eeInput); +#define STATE_CPlayer_DoAutoActions 0x0191004e + BOOL +#line 6309 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +DoAutoActions(const CEntityEvent &__eeInput); + BOOL H0x0191004f_DoAutoActions_01(const CEntityEvent &__eeInput); + BOOL H0x01910050_DoAutoActions_02(const CEntityEvent &__eeInput); + BOOL H0x01910051_DoAutoActions_03(const CEntityEvent &__eeInput); + BOOL H0x01910052_DoAutoActions_04(const CEntityEvent &__eeInput); + BOOL H0x01910053_DoAutoActions_05(const CEntityEvent &__eeInput); + BOOL H0x01910054_DoAutoActions_06(const CEntityEvent &__eeInput); + BOOL H0x01910055_DoAutoActions_07(const CEntityEvent &__eeInput); + BOOL H0x01910056_DoAutoActions_08(const CEntityEvent &__eeInput); + BOOL H0x01910057_DoAutoActions_09(const CEntityEvent &__eeInput); + BOOL H0x01910058_DoAutoActions_10(const CEntityEvent &__eeInput); + BOOL H0x01910059_DoAutoActions_11(const CEntityEvent &__eeInput); + BOOL H0x0191005a_DoAutoActions_12(const CEntityEvent &__eeInput); + BOOL H0x0191005b_DoAutoActions_13(const CEntityEvent &__eeInput); + BOOL H0x0191005c_DoAutoActions_14(const CEntityEvent &__eeInput); + BOOL H0x0191005d_DoAutoActions_15(const CEntityEvent &__eeInput); + BOOL H0x0191005e_DoAutoActions_16(const CEntityEvent &__eeInput); + BOOL H0x0191005f_DoAutoActions_17(const CEntityEvent &__eeInput); + BOOL H0x01910060_DoAutoActions_18(const CEntityEvent &__eeInput); + BOOL H0x01910061_DoAutoActions_19(const CEntityEvent &__eeInput); + BOOL H0x01910062_DoAutoActions_20(const CEntityEvent &__eeInput); + BOOL H0x01910063_DoAutoActions_21(const CEntityEvent &__eeInput); + BOOL H0x01910064_DoAutoActions_22(const CEntityEvent &__eeInput); + BOOL H0x01910065_DoAutoActions_23(const CEntityEvent &__eeInput); + BOOL H0x01910066_DoAutoActions_24(const CEntityEvent &__eeInput); + BOOL H0x01910067_DoAutoActions_25(const CEntityEvent &__eeInput); + BOOL H0x01910068_DoAutoActions_26(const CEntityEvent &__eeInput); + BOOL H0x01910069_DoAutoActions_27(const CEntityEvent &__eeInput); + BOOL H0x0191006a_DoAutoActions_28(const CEntityEvent &__eeInput); + BOOL H0x0191006b_DoAutoActions_29(const CEntityEvent &__eeInput); + BOOL H0x0191006c_DoAutoActions_30(const CEntityEvent &__eeInput); + BOOL H0x0191006d_DoAutoActions_31(const CEntityEvent &__eeInput); + BOOL H0x0191006e_DoAutoActions_32(const CEntityEvent &__eeInput); + BOOL H0x0191006f_DoAutoActions_33(const CEntityEvent &__eeInput); + BOOL H0x01910070_DoAutoActions_34(const CEntityEvent &__eeInput); + BOOL H0x01910071_DoAutoActions_35(const CEntityEvent &__eeInput); + BOOL H0x01910072_DoAutoActions_36(const CEntityEvent &__eeInput); + BOOL H0x01910073_DoAutoActions_37(const CEntityEvent &__eeInput); + BOOL H0x01910074_DoAutoActions_38(const CEntityEvent &__eeInput); + BOOL H0x01910075_DoAutoActions_39(const CEntityEvent &__eeInput); + BOOL H0x01910076_DoAutoActions_40(const CEntityEvent &__eeInput); + BOOL H0x01910077_DoAutoActions_41(const CEntityEvent &__eeInput); + BOOL H0x01910078_DoAutoActions_42(const CEntityEvent &__eeInput); + BOOL H0x01910079_DoAutoActions_43(const CEntityEvent &__eeInput); + BOOL H0x0191007a_DoAutoActions_44(const CEntityEvent &__eeInput); + BOOL H0x0191007b_DoAutoActions_45(const CEntityEvent &__eeInput); + BOOL H0x0191007c_DoAutoActions_46(const CEntityEvent &__eeInput); + BOOL H0x0191007d_DoAutoActions_47(const CEntityEvent &__eeInput); + BOOL H0x0191007e_DoAutoActions_48(const CEntityEvent &__eeInput); + BOOL H0x0191007f_DoAutoActions_49(const CEntityEvent &__eeInput); + BOOL H0x01910080_DoAutoActions_50(const CEntityEvent &__eeInput); + BOOL H0x01910081_DoAutoActions_51(const CEntityEvent &__eeInput); + BOOL H0x01910082_DoAutoActions_52(const CEntityEvent &__eeInput); + BOOL H0x01910083_DoAutoActions_53(const CEntityEvent &__eeInput); + BOOL H0x01910084_DoAutoActions_54(const CEntityEvent &__eeInput); + BOOL H0x01910085_DoAutoActions_55(const CEntityEvent &__eeInput); + BOOL H0x01910086_DoAutoActions_56(const CEntityEvent &__eeInput); + BOOL H0x01910087_DoAutoActions_57(const CEntityEvent &__eeInput); + BOOL H0x01910088_DoAutoActions_58(const CEntityEvent &__eeInput); + BOOL H0x01910089_DoAutoActions_59(const CEntityEvent &__eeInput); + BOOL H0x0191008a_DoAutoActions_60(const CEntityEvent &__eeInput); + BOOL H0x0191008b_DoAutoActions_61(const CEntityEvent &__eeInput); + BOOL H0x0191008c_DoAutoActions_62(const CEntityEvent &__eeInput); + BOOL H0x0191008d_DoAutoActions_63(const CEntityEvent &__eeInput); + BOOL H0x0191008e_DoAutoActions_64(const CEntityEvent &__eeInput); + BOOL H0x0191008f_DoAutoActions_65(const CEntityEvent &__eeInput); + BOOL H0x01910090_DoAutoActions_66(const CEntityEvent &__eeInput); + BOOL H0x01910091_DoAutoActions_67(const CEntityEvent &__eeInput); + BOOL H0x01910092_DoAutoActions_68(const CEntityEvent &__eeInput); + BOOL H0x01910093_DoAutoActions_69(const CEntityEvent &__eeInput); + BOOL H0x01910094_DoAutoActions_70(const CEntityEvent &__eeInput); + BOOL H0x01910095_DoAutoActions_71(const CEntityEvent &__eeInput); + BOOL H0x01910096_DoAutoActions_72(const CEntityEvent &__eeInput); + BOOL H0x01910097_DoAutoActions_73(const CEntityEvent &__eeInput); + BOOL H0x01910098_DoAutoActions_74(const CEntityEvent &__eeInput); + BOOL H0x01910099_DoAutoActions_75(const CEntityEvent &__eeInput); + BOOL H0x0191009a_DoAutoActions_76(const CEntityEvent &__eeInput); + BOOL H0x0191009b_DoAutoActions_77(const CEntityEvent &__eeInput); + BOOL H0x0191009c_DoAutoActions_78(const CEntityEvent &__eeInput); + BOOL H0x0191009d_DoAutoActions_79(const CEntityEvent &__eeInput); + BOOL H0x0191009e_DoAutoActions_80(const CEntityEvent &__eeInput); + BOOL H0x0191009f_DoAutoActions_81(const CEntityEvent &__eeInput); + BOOL H0x019100a0_DoAutoActions_82(const CEntityEvent &__eeInput); + BOOL H0x019100a1_DoAutoActions_83(const CEntityEvent &__eeInput); + BOOL H0x019100a2_DoAutoActions_84(const CEntityEvent &__eeInput); + BOOL H0x019100a3_DoAutoActions_85(const CEntityEvent &__eeInput); +#define STATE_CPlayer_Main 1 + BOOL +#line 6520 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x019100a4_Main_01(const CEntityEvent &__eeInput); + BOOL H0x019100a5_Main_02(const CEntityEvent &__eeInput); + BOOL H0x019100a6_Main_03(const CEntityEvent &__eeInput); + BOOL H0x019100a7_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Player_INCLUDED diff --git a/Sources/EntitiesMP/PlayerActionMarker.cpp b/Sources/EntitiesMP/PlayerActionMarker.cpp new file mode 100644 index 0000000..f83807a --- /dev/null +++ b/Sources/EntitiesMP/PlayerActionMarker.cpp @@ -0,0 +1,100 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" + +#include "StdH.h" + +#include +#include +void CPlayerActionMarker::SetDefaultProperties(void) { + m_paaAction = PAA_RUN ; + m_tmWait = 0.0f; + m_penDoorController = NULL; + m_penTrigger = NULL; + m_fSpeed = 1.0f; + m_penItem = NULL; + CMarker::SetDefaultProperties(); +} + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +const CTString & CPlayerActionMarker::GetDescription(void)const { +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +CTString strAction = PlayerAutoAction_enum . NameForValue (INDEX (m_paaAction )); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +if(m_penTarget == NULL ){ +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +((CTString &) m_strDescription ) . PrintF ("%s (%s)->" , m_strName , strAction ); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +}else { +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +((CTString &) m_strDescription ) . PrintF ("%s (%s)->%s" , m_strName , strAction , +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +m_penTarget -> GetName ()); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +} +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +return m_strDescription ; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +} + +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +BOOL CPlayerActionMarker::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +fnmMarkerClass = CTFILENAME ("Classes\\PlayerActionMarker.ecl"); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +strTargetProperty = "Target"; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +return TRUE ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +} + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +BOOL CPlayerActionMarker::HandleEvent(const CEntityEvent & ee) +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +{ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +if(ee . ee_slEvent == EVENTCODE_ETrigger ){ +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +ETrigger & eTrigger = (ETrigger &) ee ; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +if(IsDerivedFromClass (eTrigger . penCaused , "Player")){ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +EAutoAction eAutoAction ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +eAutoAction . penFirstMarker = this ; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +eTrigger . penCaused -> SendEvent (eAutoAction ); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +} +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +return TRUE ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +} +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +return FALSE ; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +} +BOOL CPlayerActionMarker:: +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerActionMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerActionMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +InitAsEditorModel (); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +SetModel (MODEL_MARKER ); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +m_tmWait = ClampDn (m_tmWait , 0.05f); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/PlayerActionMarker.es b/Sources/EntitiesMP/PlayerActionMarker.es new file mode 100644 index 0000000..ea1c960 --- /dev/null +++ b/Sources/EntitiesMP/PlayerActionMarker.es @@ -0,0 +1,112 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +407 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; +uses "EntitiesMP/Player"; + +enum PlayerAutoAction { + 1 PAA_RUN "Run", // run to this marker + 2 PAA_WAIT "Wait", // wait given time + 3 PAA_USEITEM "UseItem", // use some item here + 4 PAA_STOREWEAPON "StoreWeapon", // put current weapon away + 5 PAA_DRAWWEAPON "DrawWeapon", // put current weapon back in hand + 6 PAA_LOOKAROUND "LookAround", // wait given time and look around + 7 PAA_RUNANDSTOP "RunAndStop", // run to this marker and stop at it + 8 PAA_RECORDSTATS "RecordStats", // before end of level animation - record statistics + 9 PAA_ENDOFGAME "EndOfGame", // the game has ended - go to computer, then to menu + 10 PAA_SHOWSTATS "ShowStats", // after end of level animation - show statistics + 11 PAA_APPEARING "Appearing", // appearing with stardust effect + 12 PAA_WAITFOREVER "WaitForever", // wait trigger + 13 PAA_TELEPORT "Teleport", // teleport to new location + 14 PAA_PICKITEM "PickItem", // pick item + 15 PAA_FALLDOWN "FallDown", // falling from broken bridge + 16 PAA_FALLTOABYSS "FallToAbyss", // falling down into an abyss + 17 PAA_RELEASEPLAYER "ReleasePlayer", // return control to player from camera and similar + 18 PAA_STARTCOMPUTER "StartComputer", // invoke netricsa + 19 PAA_TRAVELING_IN_BEAM "TravelingInBeam", // traveling in space shpi beam + 20 PAA_LOGO_FIRE_MINIGUN "LogoFireMinigun", // fire minigun in logo sequence + 21 PAA_STARTCREDITS "StartCredits", // start credits printout + 22 PAA_STARTINTROSCROLL "StartIntroScroll", // start intro text scroll + 23 PAA_STOPSCROLLER "StopScroller", // stop intro scroll, or end-of-game credits + 24 PAA_NOGRAVITY "NoGravity", // deactivate gravity influence for player + 25 PAA_TURNONGRAVITY "TurnOnGravity", // turn on gravity + 26 PAA_LOGO_FIRE_INTROSE "SE Logo Fire", // for SE intro + 27 PAA_INTROSE_SELECT_WEAPON "SE Logo draw weapon", + 28 PAA_STOPANDWAIT "StopAndWait", // stop immediately and wait +}; + +class CPlayerActionMarker: CMarker { +name "PlayerActionMarker"; +thumbnail "Thumbnails\\PlayerActionMarker.tbn"; + +properties: + 1 enum PlayerAutoAction m_paaAction "Action" 'A' = PAA_RUN, // what to do here + 2 FLOAT m_tmWait "Wait" 'W' = 0.0f, // how long to wait (if wait action) + 3 CEntityPointer m_penDoorController "Door for item" 'D', // where to use the item (if use action) + 4 CEntityPointer m_penTrigger "Trigger" 'G', // triggered when player gets here + 5 FLOAT m_fSpeed "Speed" 'S' = 1.0f, // how fast to run towards marker + 6 CEntityPointer m_penItem "Item to pick" 'I', + +components: + 1 model MODEL_MARKER "Models\\Editor\\PlayerActionMarker.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\PlayerActionMarker.tex", + +functions: + const CTString &GetDescription(void) const { + CTString strAction = PlayerAutoAction_enum.NameForValue(INDEX(m_paaAction)); + if (m_penTarget==NULL) { + ((CTString&)m_strDescription).PrintF("%s (%s)->", m_strName, strAction); + } else { + ((CTString&)m_strDescription).PrintF("%s (%s)->%s", m_strName, strAction, + m_penTarget->GetName()); + } + return m_strDescription; + } + + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\PlayerActionMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + // if triggered + if (ee.ee_slEvent==EVENTCODE_ETrigger) { + ETrigger &eTrigger = (ETrigger &)ee; + // if triggered by a player + if( IsDerivedFromClass(eTrigger.penCaused, "Player")) { + // send it event to start auto actions from here + EAutoAction eAutoAction; + eAutoAction.penFirstMarker = this; + eTrigger.penCaused->SendEvent(eAutoAction); + } + return TRUE; + } + return FALSE; + } + + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + m_tmWait = ClampDn(m_tmWait, 0.05f); + + return; + } +}; + diff --git a/Sources/EntitiesMP/PlayerActionMarker.h b/Sources/EntitiesMP/PlayerActionMarker.h new file mode 100644 index 0000000..6cb3eed --- /dev/null +++ b/Sources/EntitiesMP/PlayerActionMarker.h @@ -0,0 +1,65 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_PlayerActionMarker_INCLUDED +#define _EntitiesMP_PlayerActionMarker_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType PlayerAutoAction_enum; +enum PlayerAutoAction { + PAA_RUN = 1, + PAA_WAIT = 2, + PAA_USEITEM = 3, + PAA_STOREWEAPON = 4, + PAA_DRAWWEAPON = 5, + PAA_LOOKAROUND = 6, + PAA_RUNANDSTOP = 7, + PAA_RECORDSTATS = 8, + PAA_ENDOFGAME = 9, + PAA_SHOWSTATS = 10, + PAA_APPEARING = 11, + PAA_WAITFOREVER = 12, + PAA_TELEPORT = 13, + PAA_PICKITEM = 14, + PAA_FALLDOWN = 15, + PAA_FALLTOABYSS = 16, + PAA_RELEASEPLAYER = 17, + PAA_STARTCOMPUTER = 18, + PAA_TRAVELING_IN_BEAM = 19, + PAA_LOGO_FIRE_MINIGUN = 20, + PAA_STARTCREDITS = 21, + PAA_STARTINTROSCROLL = 22, + PAA_STOPSCROLLER = 23, + PAA_NOGRAVITY = 24, + PAA_TURNONGRAVITY = 25, + PAA_LOGO_FIRE_INTROSE = 26, + PAA_INTROSE_SELECT_WEAPON = 27, + PAA_STOPANDWAIT = 28, +}; +DECL_DLL inline void ClearToDefault(PlayerAutoAction &e) { e = (PlayerAutoAction)0; } ; +extern "C" DECL_DLL CDLLEntityClass CPlayerActionMarker_DLLClass; +class CPlayerActionMarker : public CMarker { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum PlayerAutoAction m_paaAction; + FLOAT m_tmWait; + CEntityPointer m_penDoorController; + CEntityPointer m_penTrigger; + FLOAT m_fSpeed; + CEntityPointer m_penItem; + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +const CTString & GetDescription(void)const; + +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CPlayerActionMarker_Main 1 + BOOL +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_PlayerActionMarker_INCLUDED diff --git a/Sources/EntitiesMP/PlayerActionMarker_tables.h b/Sources/EntitiesMP/PlayerActionMarker_tables.h new file mode 100644 index 0000000..15b8a9e --- /dev/null +++ b/Sources/EntitiesMP/PlayerActionMarker_tables.h @@ -0,0 +1,72 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(PlayerAutoAction) + EP_ENUMVALUE(PAA_RUN, "Run"), + EP_ENUMVALUE(PAA_WAIT, "Wait"), + EP_ENUMVALUE(PAA_USEITEM, "UseItem"), + EP_ENUMVALUE(PAA_STOREWEAPON, "StoreWeapon"), + EP_ENUMVALUE(PAA_DRAWWEAPON, "DrawWeapon"), + EP_ENUMVALUE(PAA_LOOKAROUND, "LookAround"), + EP_ENUMVALUE(PAA_RUNANDSTOP, "RunAndStop"), + EP_ENUMVALUE(PAA_RECORDSTATS, "RecordStats"), + EP_ENUMVALUE(PAA_ENDOFGAME, "EndOfGame"), + EP_ENUMVALUE(PAA_SHOWSTATS, "ShowStats"), + EP_ENUMVALUE(PAA_APPEARING, "Appearing"), + EP_ENUMVALUE(PAA_WAITFOREVER, "WaitForever"), + EP_ENUMVALUE(PAA_TELEPORT, "Teleport"), + EP_ENUMVALUE(PAA_PICKITEM, "PickItem"), + EP_ENUMVALUE(PAA_FALLDOWN, "FallDown"), + EP_ENUMVALUE(PAA_FALLTOABYSS, "FallToAbyss"), + EP_ENUMVALUE(PAA_RELEASEPLAYER, "ReleasePlayer"), + EP_ENUMVALUE(PAA_STARTCOMPUTER, "StartComputer"), + EP_ENUMVALUE(PAA_TRAVELING_IN_BEAM, "TravelingInBeam"), + EP_ENUMVALUE(PAA_LOGO_FIRE_MINIGUN, "LogoFireMinigun"), + EP_ENUMVALUE(PAA_STARTCREDITS, "StartCredits"), + EP_ENUMVALUE(PAA_STARTINTROSCROLL, "StartIntroScroll"), + EP_ENUMVALUE(PAA_STOPSCROLLER, "StopScroller"), + EP_ENUMVALUE(PAA_NOGRAVITY, "NoGravity"), + EP_ENUMVALUE(PAA_TURNONGRAVITY, "TurnOnGravity"), + EP_ENUMVALUE(PAA_LOGO_FIRE_INTROSE, "SE Logo Fire"), + EP_ENUMVALUE(PAA_INTROSE_SELECT_WEAPON, "SE Logo draw weapon"), + EP_ENUMVALUE(PAA_STOPANDWAIT, "StopAndWait"), +EP_ENUMEND(PlayerAutoAction); + +#define ENTITYCLASS CPlayerActionMarker + +CEntityProperty CPlayerActionMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &PlayerAutoAction_enum, (0x00000197<<8)+1, offsetof(CPlayerActionMarker, m_paaAction), "Action", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000197<<8)+2, offsetof(CPlayerActionMarker, m_tmWait), "Wait", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000197<<8)+3, offsetof(CPlayerActionMarker, m_penDoorController), "Door for item", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000197<<8)+4, offsetof(CPlayerActionMarker, m_penTrigger), "Trigger", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000197<<8)+5, offsetof(CPlayerActionMarker, m_fSpeed), "Speed", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000197<<8)+6, offsetof(CPlayerActionMarker, m_penItem), "Item to pick", 'I', 0x7F0000FFUL, 0), +}; +#define CPlayerActionMarker_propertiesct ARRAYCOUNT(CPlayerActionMarker_properties) + +CEntityComponent CPlayerActionMarker_components[] = { +#define MODEL_MARKER ((0x00000197<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\PlayerActionMarker.mdl"), +#define TEXTURE_MARKER ((0x00000197<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\PlayerActionMarker.tex"), +}; +#define CPlayerActionMarker_componentsct ARRAYCOUNT(CPlayerActionMarker_components) + +CEventHandlerEntry CPlayerActionMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CPlayerActionMarker:: +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/PlayerActionMarker.es" +Main),DEBUGSTRING("CPlayerActionMarker::Main")}, +}; +#define CPlayerActionMarker_handlersct ARRAYCOUNT(CPlayerActionMarker_handlers) + +CEntity *CPlayerActionMarker_New(void) { return new CPlayerActionMarker; }; +void CPlayerActionMarker_OnInitClass(void) {}; +void CPlayerActionMarker_OnEndClass(void) {}; +void CPlayerActionMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPlayerActionMarker_OnWorldEnd(CWorld *pwo) {}; +void CPlayerActionMarker_OnWorldInit(CWorld *pwo) {}; +void CPlayerActionMarker_OnWorldTick(CWorld *pwo) {}; +void CPlayerActionMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPlayerActionMarker, CMarker, "PlayerActionMarker", "Thumbnails\\PlayerActionMarker.tbn", 0x00000197); +DECLARE_CTFILENAME(_fnmCPlayerActionMarker_tbn, "Thumbnails\\PlayerActionMarker.tbn"); diff --git a/Sources/EntitiesMP/PlayerAnimator.cpp b/Sources/EntitiesMP/PlayerAnimator.cpp new file mode 100644 index 0000000..7e81bcc --- /dev/null +++ b/Sources/EntitiesMP/PlayerAnimator.cpp @@ -0,0 +1,1963 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" + +#include "StdH.h" + +#include "ModelsMP/Player/SeriousSam/Player.h" +#include "ModelsMP/Player/SeriousSam/Body.h" +#include "ModelsMP/Player/SeriousSam/Head.h" + +#include "Models/Weapons/Knife/KnifeItem.h" +#include "Models/Weapons/Colt/ColtItem.h" +#include "Models/Weapons/Colt/ColtMain.h" +#include "Models/Weapons/SingleShotgun/SingleShotgunItem.h" +#include "Models/Weapons/SingleShotgun/Barrels.h" +#include "Models/Weapons/DoubleShotgun/DoubleShotgunItem.h" +#include "Models/Weapons/DoubleShotgun/Dshotgunbarrels.h" +#include "Models/Weapons/TommyGun/TommyGunItem.h" +#include "Models/Weapons/TommyGun/Body.h" +#include "Models/Weapons/MiniGun/MiniGunItem.h" +#include "Models/Weapons/MiniGun/Body.h" +#include "Models/Weapons/GrenadeLauncher/GrenadeLauncherItem.h" +#include "Models/Weapons/RocketLauncher/RocketLauncherItem.h" +#include "ModelsMP/Weapons/Sniper/SniperItem.h" +#include "ModelsMP/Weapons/Sniper/Sniper.h" +//#include "Models/Weapons/Pipebomb/StickItem.h" +#include "ModelsMP/Weapons/Flamer/FlamerItem.h" +#include "ModelsMP/Weapons/Flamer/Body.h" +//#include "ModelsMP/Weapons/Chainsaw/ChainsawItem.h" +#include "ModelsMP/Weapons/Chainsaw/ChainsawForPlayer.h" +#include "ModelsMP/Weapons/Chainsaw/BladeForPlayer.h" +#include "ModelsMP/Weapons/Chainsaw/Body.h" +#include "Models/Weapons/Laser/LaserItem.h" +//#include "Models/Weapons/GhostBuster/GhostBusterItem.h" +//#include "Models/Weapons/GhostBuster/Effect01.h" +#include "Models/Weapons/Cannon/Cannon.h" + +#include +#include +CEntityEvent *EAnimatorInit::MakeCopy(void) { CEntityEvent *peeCopy = new EAnimatorInit(*this); return peeCopy;} +EAnimatorInit::EAnimatorInit() : CEntityEvent(EVENTCODE_EAnimatorInit) {; + ClearToDefault(penPlayer); +}; +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" + +// animator action +enum AnimatorAction { + AA_JUMPDOWN = 0, + AA_CROUCH, + AA_RISE, + AA_PULLWEAPON, + AA_ATTACK, +}; + +// fire flare specific +#define FLARE_NONE 0 +#define FLARE_REMOVE 1 +#define FLARE_ADD 2 + + +extern FLOAT plr_fBreathingStrength; +extern FLOAT plr_fViewDampFactor; +extern FLOAT plr_fViewDampLimitGroundUp; +extern FLOAT plr_fViewDampLimitGroundDn; +extern FLOAT plr_fViewDampLimitWater; +extern FLOAT wpn_fRecoilSpeed[17]; +extern FLOAT wpn_fRecoilLimit[17]; +extern FLOAT wpn_fRecoilDampUp[17]; +extern FLOAT wpn_fRecoilDampDn[17]; +extern FLOAT wpn_fRecoilOffset[17]; +extern FLOAT wpn_fRecoilFactorP[17]; +extern FLOAT wpn_fRecoilFactorZ[17]; + + +void CPlayerAnimator_Precache(ULONG ulAvailable) +{ + CDLLEntityClass *pdec = &CPlayerAnimator_DLLClass; + + pdec->PrecacheTexture(TEX_REFL_BWRIPLES01 ); + pdec->PrecacheTexture(TEX_REFL_BWRIPLES02 ); + pdec->PrecacheTexture(TEX_REFL_LIGHTMETAL01 ); + pdec->PrecacheTexture(TEX_REFL_LIGHTBLUEMETAL01); + pdec->PrecacheTexture(TEX_REFL_DARKMETAL ); + pdec->PrecacheTexture(TEX_REFL_PURPLE01 ); + pdec->PrecacheTexture(TEX_SPEC_WEAK ); + pdec->PrecacheTexture(TEX_SPEC_MEDIUM ); + pdec->PrecacheTexture(TEX_SPEC_STRONG ); + pdec->PrecacheModel(MODEL_FLARE02); + pdec->PrecacheTexture(TEXTURE_FLARE02); + pdec->PrecacheModel(MODEL_GOLDAMON); + pdec->PrecacheTexture(TEXTURE_GOLDAMON); + pdec->PrecacheTexture(TEX_REFL_GOLD01); + pdec->PrecacheClass(CLASS_REMINDER); + + // precache shells that drop when firing + extern void CPlayerWeaponsEffects_Precache(void); + CPlayerWeaponsEffects_Precache(); + + // precache weapons player has + if ( ulAvailable&(1<<(WEAPON_KNIFE-1)) ) { + pdec->PrecacheModel(MODEL_KNIFE ); + pdec->PrecacheTexture(TEXTURE_KNIFE); + } + + if ( ulAvailable&(1<<(WEAPON_COLT-1)) ) { + pdec->PrecacheModel(MODEL_COLT ); + pdec->PrecacheModel(MODEL_COLTCOCK ); + pdec->PrecacheModel(MODEL_COLTMAIN ); + pdec->PrecacheModel(MODEL_COLTBULLETS ); + pdec->PrecacheTexture(TEXTURE_COLTMAIN ); + pdec->PrecacheTexture(TEXTURE_COLTBULLETS ); + pdec->PrecacheTexture(TEXTURE_COLTBULLETS ); + } + + if ( ulAvailable&(1<<(WEAPON_SINGLESHOTGUN-1)) ) { + pdec->PrecacheModel(MODEL_SINGLESHOTGUN ); + pdec->PrecacheModel(MODEL_SS_SLIDER ); + pdec->PrecacheModel(MODEL_SS_HANDLE ); + pdec->PrecacheModel(MODEL_SS_BARRELS ); + pdec->PrecacheTexture(TEXTURE_SS_HANDLE); + pdec->PrecacheTexture(TEXTURE_SS_BARRELS); + } + + if ( ulAvailable&(1<<(WEAPON_DOUBLESHOTGUN-1)) ) { + pdec->PrecacheModel(MODEL_DOUBLESHOTGUN ); + pdec->PrecacheModel(MODEL_DS_HANDLE ); + pdec->PrecacheModel(MODEL_DS_BARRELS ); + pdec->PrecacheModel(MODEL_DS_SWITCH ); + pdec->PrecacheTexture(TEXTURE_DS_HANDLE ); + pdec->PrecacheTexture(TEXTURE_DS_BARRELS ); + pdec->PrecacheTexture(TEXTURE_DS_SWITCH ); + } + + if ( ulAvailable&(1<<(WEAPON_TOMMYGUN-1)) ) { + pdec->PrecacheModel(MODEL_TOMMYGUN ); + pdec->PrecacheModel(MODEL_TG_BODY ); + pdec->PrecacheModel(MODEL_TG_SLIDER ); + pdec->PrecacheTexture(TEXTURE_TG_BODY ); + } + + if ( ulAvailable&(1<<(WEAPON_SNIPER-1)) ) { + pdec->PrecacheModel(MODEL_SNIPER ); + pdec->PrecacheModel(MODEL_SNIPER_BODY ); + pdec->PrecacheTexture(TEXTURE_SNIPER_BODY ); + } + + if ( ulAvailable&(1<<(WEAPON_MINIGUN-1)) ) { + pdec->PrecacheModel(MODEL_MINIGUN ); + pdec->PrecacheModel(MODEL_MG_BARRELS ); + pdec->PrecacheModel(MODEL_MG_BODY ); + pdec->PrecacheModel(MODEL_MG_ENGINE ); + pdec->PrecacheTexture(TEXTURE_MG_BODY ); + pdec->PrecacheTexture(TEXTURE_MG_BARRELS ); + } + + if ( ulAvailable&(1<<(WEAPON_ROCKETLAUNCHER-1)) ) { + pdec->PrecacheModel(MODEL_ROCKETLAUNCHER ); + pdec->PrecacheModel(MODEL_RL_BODY ); + pdec->PrecacheModel(MODEL_RL_ROTATINGPART ); + pdec->PrecacheModel(MODEL_RL_ROCKET ); + pdec->PrecacheTexture(TEXTURE_RL_BODY ); + pdec->PrecacheTexture(TEXTURE_RL_ROCKET); + pdec->PrecacheTexture(TEXTURE_RL_ROTATINGPART); + } + + if ( ulAvailable&(1<<(WEAPON_GRENADELAUNCHER-1)) ) { + pdec->PrecacheModel(MODEL_GRENADELAUNCHER ); + pdec->PrecacheModel(MODEL_GL_BODY ); + pdec->PrecacheModel(MODEL_GL_MOVINGPART ); + pdec->PrecacheModel(MODEL_GL_GRENADE ); + pdec->PrecacheTexture(TEXTURE_GL_BODY ); + pdec->PrecacheTexture(TEXTURE_GL_MOVINGPART ); + } + +/* + if ( ulAvailable&(1<<(WEAPON_PIPEBOMB-1)) ) { + pdec->PrecacheModel(MODEL_PIPEBOMB_STICK ); + pdec->PrecacheModel(MODEL_PB_BUTTON ); + pdec->PrecacheModel(MODEL_PB_SHIELD ); + pdec->PrecacheModel(MODEL_PB_STICK ); + pdec->PrecacheModel(MODEL_PB_BOMB ); + pdec->PrecacheTexture(TEXTURE_PB_STICK ); + pdec->PrecacheTexture(TEXTURE_PB_BOMB ); + } +*/ + if ( ulAvailable&(1<<(WEAPON_FLAMER-1)) ) { + pdec->PrecacheModel(MODEL_FLAMER ); + pdec->PrecacheModel(MODEL_FL_BODY ); + pdec->PrecacheModel(MODEL_FL_RESERVOIR); + pdec->PrecacheModel(MODEL_FL_FLAME ); + pdec->PrecacheTexture(TEXTURE_FL_BODY ); + pdec->PrecacheTexture(TEXTURE_FL_FLAME); + } + + if ( ulAvailable&(1<<(WEAPON_CHAINSAW-1)) ) { + pdec->PrecacheModel(MODEL_CHAINSAW ); + pdec->PrecacheModel(MODEL_CS_BODY ); + pdec->PrecacheModel(MODEL_CS_BLADE ); + pdec->PrecacheModel(MODEL_CS_TEETH ); + pdec->PrecacheTexture(TEXTURE_CS_BODY ); + pdec->PrecacheTexture(TEXTURE_CS_BLADE ); + pdec->PrecacheTexture(TEXTURE_CS_TEETH ); + } + + if ( ulAvailable&(1<<(WEAPON_LASER-1)) ) { + pdec->PrecacheModel(MODEL_LASER ); + pdec->PrecacheModel(MODEL_LS_BODY ); + pdec->PrecacheModel(MODEL_LS_BARREL ); + pdec->PrecacheTexture(TEXTURE_LS_BODY ); + pdec->PrecacheTexture(TEXTURE_LS_BARREL); + } +/* + if ( ulAvailable&(1<<(WEAPON_GHOSTBUSTER-1)) ) { + pdec->PrecacheModel(MODEL_GHOSTBUSTER ); + pdec->PrecacheModel(MODEL_GB_BODY ); + pdec->PrecacheModel(MODEL_GB_ROTATOR ); + pdec->PrecacheModel(MODEL_GB_EFFECT1 ); + pdec->PrecacheModel(MODEL_GB_EFFECT1FLARE ); + pdec->PrecacheTexture(TEXTURE_GB_ROTATOR ); + pdec->PrecacheTexture(TEXTURE_GB_BODY ); + pdec->PrecacheTexture(TEXTURE_GB_LIGHTNING); + pdec->PrecacheTexture(TEXTURE_GB_FLARE ); + } +*/ + if ( ulAvailable&(1<<(WEAPON_IRONCANNON-1)) /*|| + ulAvailable&(1<<(WEAPON_NUKECANNON-1)) */) { + pdec->PrecacheModel(MODEL_CANNON ); + pdec->PrecacheModel(MODEL_CN_BODY ); +// pdec->PrecacheModel(MODEL_CN_NUKEBOX); +// pdec->PrecacheModel(MODEL_CN_LIGHT); + pdec->PrecacheTexture(TEXTURE_CANNON); + } +} + +void CPlayerAnimator::SetDefaultProperties(void) { + m_penPlayer = NULL; + m_bReference = FALSE ; + m_fLastActionTime = 0.0f; + m_iContent = 0; + m_bWaitJumpAnim = FALSE ; + m_bCrouch = FALSE ; + m_iCrouchDownWait = FALSE ; + m_iRiseUpWait = FALSE ; + m_bChangeWeapon = FALSE ; + m_bSwim = FALSE ; + m_iFlare = FLARE_REMOVE ; + m_iSecondFlare = FLARE_REMOVE ; + m_bAttacking = FALSE ; + m_tmAttackingDue = -1.0f; + m_tmFlareAdded = -1.0f; + m_bDisableAnimating = FALSE ; + m_vLastPlayerPosition = FLOAT3D(0 , 0 , 0); + m_fEyesYLastOffset = 0.0f; + m_fEyesYOffset = 0.0f; + m_fEyesYSpeed = 0.0f; + m_fWeaponYLastOffset = 0.0f; + m_fWeaponYOffset = 0.0f; + m_fWeaponYSpeed = 0.0f; + m_bMoving = FALSE ; + m_fMoveLastBanking = 0.0f; + m_fMoveBanking = 0.0f; + m_iMovingSide = 0; + m_bSidestepBankingLeft = FALSE ; + m_bSidestepBankingRight = FALSE ; + m_fSidestepLastBanking = 0.0f; + m_fSidestepBanking = 0.0f; + m_iWeaponLast = -1; + m_fBodyAnimTime = -1.0f; + m_penPrediction = NULL; + CRationalEntity::SetDefaultProperties(); +} + +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::Read_t(CTStream * istr) +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +{ +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CRationalEntity :: Read_t (istr ); +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::Precache(void) +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +{ +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +INDEX iAvailableWeapons = ((CPlayerWeapons &) * (((CPlayer &) * m_penPlayer ) . m_penWeapons )) . m_iAvailableWeapons ; +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayerAnimator_Precache (iAvailableWeapons ); +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer * CPlayerAnimator::GetPlayer(void) +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +{ +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return ((CPlayer *) & * m_penPlayer ); +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CModelObject * CPlayerAnimator::GetBody(void) +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +{ +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CAttachmentModelObject * pamoBody = GetPlayer () -> GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ); +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pamoBody == NULL ){ +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return NULL ; +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return & pamoBody -> amo_moModelObject ; +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CModelObject * CPlayerAnimator::GetBodyRen(void) +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +{ +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CAttachmentModelObject * pamoBody = GetPlayer () -> m_moRender . GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ); +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pamoBody == NULL ){ +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return NULL ; +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return & pamoBody -> amo_moModelObject ; +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::SetComponents(CModelObject * mo,ULONG ulIDModel,ULONG ulIDTexture, +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture) { +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +mo -> SetData (GetModelDataForComponent (ulIDModel )); +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +mo -> mo_toTexture . SetData (GetTextureDataForComponent (ulIDTexture )); +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(ulIDReflectionTexture > 0){ +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +mo -> mo_toReflection . SetData (GetTextureDataForComponent (ulIDReflectionTexture )); +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +mo -> mo_toReflection . SetData (NULL ); +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(ulIDSpecularTexture > 0){ +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +mo -> mo_toSpecular . SetData (GetTextureDataForComponent (ulIDSpecularTexture )); +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +mo -> mo_toSpecular . SetData (NULL ); +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(ulIDBumpTexture > 0){ +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +mo -> mo_toBump . SetData (GetTextureDataForComponent (ulIDBumpTexture )); +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +mo -> mo_toBump . SetData (NULL ); +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ModelChangeNotify (); +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::AddAttachmentModel(CModelObject * mo,INDEX iAttachment,ULONG ulIDModel,ULONG ulIDTexture, +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture) { +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetComponents (& mo -> AddAttachmentModel (iAttachment ) -> amo_moModelObject , ulIDModel , +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ulIDTexture , ulIDReflectionTexture , ulIDSpecularTexture , ulIDBumpTexture ); +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::AddWeaponAttachment(INDEX iAttachment,ULONG ulIDModel,ULONG ulIDTexture, +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture) { +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddAttachmentModel (pmoModel , iAttachment , ulIDModel , ulIDTexture , +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ulIDReflectionTexture , ulIDSpecularTexture , ulIDBumpTexture ); +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::SetAttachment(INDEX iAttachment) { +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel = & (pmoModel -> GetAttachmentModel (iAttachment ) -> amo_moModelObject ); +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::SyncWeapon(void) +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +{ +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CModelObject * pmoBodyRen = GetBodyRen (); +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CModelObject * pmoBodyDef = GetBody (); +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +for(INDEX iWeapon = BODY_ATTACHMENT_COLT_RIGHT ;iWeapon <= BODY_ATTACHMENT_ITEM ;iWeapon ++){ +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CAttachmentModelObject * pamoWeapDef = pmoBodyDef -> GetAttachmentModel (iWeapon ); +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CAttachmentModelObject * pamoWeapRen = pmoBodyRen -> GetAttachmentModel (iWeapon ); +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pamoWeapRen == NULL && pamoWeapDef == NULL ){ +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +NOTHING ; +#line 534 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(pamoWeapRen != NULL && pamoWeapDef == NULL ){ +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +delete pamoWeapRen ; +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(pamoWeapRen == NULL && pamoWeapDef != NULL ){ +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoWeapRen = pmoBodyRen -> AddAttachmentModel (iWeapon ); +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoWeapRen -> amo_plRelative = pamoWeapDef -> amo_plRelative ; +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoWeapRen -> amo_moModelObject . Copy (pamoWeapDef -> amo_moModelObject ); +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoWeapRen -> amo_plRelative = pamoWeapDef -> amo_plRelative ; +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoWeapRen -> amo_moModelObject . Synchronize (pamoWeapDef -> amo_moModelObject ); +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::SetWeapon(void) { +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +INDEX iWeapon = ((CPlayerWeapons &) * (((CPlayer &) * m_penPlayer ) . m_penWeapons )) . m_iCurrentWeapon ; +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_iWeaponLast = iWeapon ; +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 559 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel = & (pl . GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ); +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +switch(iWeapon ){ +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_KNIFE : +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_KNIFE , MODEL_KNIFE , +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_KNIFE , TEX_REFL_BWRIPLES02 , TEX_SPEC_WEAK , 0); +#line 565 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_DOUBLECOLT : +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_COLT_LEFT , MODEL_COLT , TEXTURE_COLTMAIN , 0 , 0 , 0); +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_COLT_LEFT ); +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (COLTITEM_ATTACHMENT_BULLETS , MODEL_COLTBULLETS , +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_COLTBULLETS , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 573 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (COLTITEM_ATTACHMENT_COCK , MODEL_COLTCOCK , +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_COLTCOCK , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (COLTITEM_ATTACHMENT_BODY , MODEL_COLTMAIN , +#line 576 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_COLTMAIN , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (COLTITEM_ATTACHMENT_BODY ); +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (COLTMAIN_ATTACHMENT_FLARE , MODEL_FLARE02 , TEXTURE_FLARE02 , 0 , 0 , 0); +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel = & (pl . GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ); +#line 583 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_COLT : +#line 584 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_COLT_RIGHT , MODEL_COLT , TEXTURE_COLTMAIN , 0 , 0 , 0); +#line 585 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_COLT_RIGHT ); +#line 586 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (COLTITEM_ATTACHMENT_BULLETS , MODEL_COLTBULLETS , +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_COLTBULLETS , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (COLTITEM_ATTACHMENT_COCK , MODEL_COLTCOCK , +#line 589 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_COLTCOCK , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 590 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (COLTITEM_ATTACHMENT_BODY , MODEL_COLTMAIN , +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_COLTMAIN , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (COLTITEM_ATTACHMENT_BODY ); +#line 593 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (COLTMAIN_ATTACHMENT_FLARE , MODEL_FLARE02 , TEXTURE_FLARE02 , 0 , 0 , 0); +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SINGLESHOTGUN : +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_SINGLE_SHOTGUN , MODEL_SINGLESHOTGUN , TEXTURE_SS_HANDLE , 0 , 0 , 0); +#line 599 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_SINGLE_SHOTGUN ); +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (SINGLESHOTGUNITEM_ATTACHMENT_BARRELS , MODEL_SS_BARRELS , +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_SS_BARRELS , TEX_REFL_DARKMETAL , TEX_SPEC_WEAK , 0); +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (SINGLESHOTGUNITEM_ATTACHMENT_HANDLE , MODEL_SS_HANDLE , +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_SS_HANDLE , TEX_REFL_DARKMETAL , TEX_SPEC_MEDIUM , 0); +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (SINGLESHOTGUNITEM_ATTACHMENT_SLIDER , MODEL_SS_SLIDER , +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_SS_BARRELS , TEX_REFL_DARKMETAL , TEX_SPEC_MEDIUM , 0); +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (SINGLESHOTGUNITEM_ATTACHMENT_BARRELS ); +#line 607 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BARRELS_ATTACHMENT_FLARE , MODEL_FLARE02 , TEXTURE_FLARE02 , 0 , 0 , 0); +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 611 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_DOUBLESHOTGUN : +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_DOUBLE_SHOTGUN , MODEL_DOUBLESHOTGUN , TEXTURE_DS_HANDLE , 0 , 0 , 0); +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_DOUBLE_SHOTGUN ); +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (DOUBLESHOTGUNITEM_ATTACHMENT_BARRELS , MODEL_DS_BARRELS , +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_DS_BARRELS , TEX_REFL_BWRIPLES01 , TEX_SPEC_MEDIUM , 0); +#line 616 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (DOUBLESHOTGUNITEM_ATTACHMENT_HANDLE , MODEL_DS_HANDLE , +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_DS_HANDLE , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 618 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (DOUBLESHOTGUNITEM_ATTACHMENT_SWITCH , MODEL_DS_SWITCH , +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_DS_SWITCH , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (DOUBLESHOTGUNITEM_ATTACHMENT_BARRELS ); +#line 621 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (DSHOTGUNBARRELS_ATTACHMENT_FLARE , MODEL_FLARE02 , TEXTURE_FLARE02 , 0 , 0 , 0); +#line 622 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 626 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_TOMMYGUN : +#line 627 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_TOMMYGUN , MODEL_TOMMYGUN , TEXTURE_TG_BODY , 0 , 0 , 0); +#line 628 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_TOMMYGUN ); +#line 629 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (TOMMYGUNITEM_ATTACHMENT_BODY , MODEL_TG_BODY , TEXTURE_TG_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (TOMMYGUNITEM_ATTACHMENT_SLIDER , MODEL_TG_SLIDER , TEXTURE_TG_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 631 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (TOMMYGUNITEM_ATTACHMENT_BODY ); +#line 632 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_FLARE , MODEL_FLARE02 , TEXTURE_FLARE02 , 0 , 0 , 0); +#line 633 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SNIPER : +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_FLAMER , MODEL_SNIPER , TEXTURE_SNIPER_BODY , 0 , 0 , 0); +#line 638 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_FLAMER ); +#line 639 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (SNIPERITEM_ATTACHMENT_BODY , MODEL_SNIPER_BODY , TEXTURE_SNIPER_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 640 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (SNIPERITEM_ATTACHMENT_BODY ); +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_FLARE , MODEL_FLARE02 , TEXTURE_FLARE02 , 0 , 0 , 0); +#line 642 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 645 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_MINIGUN : +#line 646 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_MINIGUN , MODEL_MINIGUN , TEXTURE_MG_BODY , 0 , 0 , 0); +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_MINIGUN ); +#line 648 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (MINIGUNITEM_ATTACHMENT_BARRELS , MODEL_MG_BARRELS , TEXTURE_MG_BARRELS , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (MINIGUNITEM_ATTACHMENT_BODY , MODEL_MG_BODY , TEXTURE_MG_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 650 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (MINIGUNITEM_ATTACHMENT_ENGINE , MODEL_MG_ENGINE , TEXTURE_MG_BARRELS , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (MINIGUNITEM_ATTACHMENT_BODY ); +#line 652 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_FLARE , MODEL_FLARE02 , TEXTURE_FLARE02 , 0 , 0 , 0); +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 656 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_ROCKETLAUNCHER : +#line 657 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_ROCKET_LAUNCHER , MODEL_ROCKETLAUNCHER , TEXTURE_RL_BODY , 0 , 0 , 0); +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_ROCKET_LAUNCHER ); +#line 659 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_BODY , MODEL_RL_BODY , TEXTURE_RL_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 660 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_ROTATINGPART , MODEL_RL_ROTATINGPART , TEXTURE_RL_ROTATINGPART , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET1 , MODEL_RL_ROCKET , TEXTURE_RL_ROCKET , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET2 , MODEL_RL_ROCKET , TEXTURE_RL_ROCKET , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET3 , MODEL_RL_ROCKET , TEXTURE_RL_ROCKET , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 664 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET4 , MODEL_RL_ROCKET , TEXTURE_RL_ROCKET , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 665 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_GRENADELAUNCHER : +#line 669 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_GRENADE_LAUNCHER , MODEL_GRENADELAUNCHER , TEXTURE_GL_BODY , 0 , 0 , 0); +#line 670 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_GRENADE_LAUNCHER ); +#line 671 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (GRENADELAUNCHERITEM_ATTACHMENT_BODY , MODEL_GL_BODY , TEXTURE_GL_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 672 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (GRENADELAUNCHERITEM_ATTACHMENT_MOVING_PART , MODEL_GL_MOVINGPART , TEXTURE_GL_MOVINGPART , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 673 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (GRENADELAUNCHERITEM_ATTACHMENT_GRENADE , MODEL_GL_GRENADE , TEXTURE_GL_MOVINGPART , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 674 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 689 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_FLAMER : +#line 690 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_FLAMER , MODEL_FLAMER , TEXTURE_FL_BODY , 0 , 0 , 0); +#line 691 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_FLAMER ); +#line 692 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (FLAMERITEM_ATTACHMENT_BODY , MODEL_FL_BODY , TEXTURE_FL_BODY , TEX_REFL_BWRIPLES02 , TEX_SPEC_MEDIUM , 0); +#line 693 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (FLAMERITEM_ATTACHMENT_FUEL , MODEL_FL_RESERVOIR , TEXTURE_FL_FUELRESERVOIR , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 694 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (FLAMERITEM_ATTACHMENT_FLAME , MODEL_FL_FLAME , TEXTURE_FL_FLAME , 0 , 0 , 0); +#line 695 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 698 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_CHAINSAW : { +#line 699 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_MINIGUN , MODEL_CHAINSAW , TEXTURE_CS_BODY , 0 , 0 , 0); +#line 700 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_MINIGUN ); +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (CHAINSAWFORPLAYER_ATTACHMENT_CHAINSAW , MODEL_CS_BODY , TEXTURE_CS_BODY , TEX_REFL_BWRIPLES02 , TEX_SPEC_MEDIUM , 0); +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (CHAINSAWFORPLAYER_ATTACHMENT_BLADE , MODEL_CS_BLADE , TEXTURE_CS_BLADE , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 703 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CModelObject * pmo = pmoModel ; +#line 704 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (CHAINSAWFORPLAYER_ATTACHMENT_BLADE ); +#line 705 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BLADEFORPLAYER_ATTACHMENT_TEETH , MODEL_CS_TEETH , TEXTURE_CS_TEETH , 0 , 0 , 0); +#line 706 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ;} +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_LASER : +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_LASER , MODEL_LASER , TEXTURE_LS_BODY , 0 , 0 , 0); +#line 711 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_LASER ); +#line 712 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (LASERITEM_ATTACHMENT_BODY , MODEL_LS_BODY , TEXTURE_LS_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 713 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (LASERITEM_ATTACHMENT_LEFTUP , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (LASERITEM_ATTACHMENT_LEFTDOWN , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (LASERITEM_ATTACHMENT_RIGHTUP , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 716 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (LASERITEM_ATTACHMENT_RIGHTDOWN , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 745 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_IRONCANNON : +#line 747 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_CANNON , MODEL_CANNON , TEXTURE_CANNON , 0 , 0 , 0); +#line 748 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetAttachment (BODY_ATTACHMENT_CANNON ); +#line 749 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (CANNON_ATTACHMENT_BODY , MODEL_CN_BODY , TEXTURE_CANNON , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 752 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 753 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +default : +#line 754 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ASSERTALWAYS ("Unknown weapon."); +#line 755 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 757 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SyncWeapon (); +#line 758 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 761 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::SetItem(CModelObject * pmo) { +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel = & (GetPlayer () -> GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ); +#line 763 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AddWeaponAttachment (BODY_ATTACHMENT_ITEM , MODEL_GOLDAMON , +#line 764 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TEXTURE_GOLDAMON , TEX_REFL_GOLD01 , TEX_SPEC_MEDIUM , 0); +#line 765 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pmo != NULL ){ +#line 766 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 767 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CAttachmentModelObject * pamo = pl . GetModelObject () -> GetAttachmentModelList (PLAYER_ATTACHMENT_TORSO , BODY_ATTACHMENT_ITEM , - 1); +#line 768 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel = & (pamo -> amo_moModelObject ); +#line 769 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> Copy (* pmo ); +#line 770 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> StretchModel (FLOAT3D (1 , 1 , 1)); +#line 771 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamo -> amo_plRelative = CPlacement3D (FLOAT3D (0 , 0 , 0) , ANGLE3D (0 , 0 , 0)); +#line 772 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 774 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SyncWeapon (); +#line 775 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 778 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::SetBodyAnimation(INDEX iAnimation,ULONG ulFlags) { +#line 780 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bChangeWeapon ){return ;} +#line 782 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bAttacking ){return ;} +#line 784 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 785 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CModelObject & moBody = pl . GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 786 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +moBody . PlayAnim (iAnimation , ulFlags ); +#line 787 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fBodyAnimTime = moBody . GetAnimLength (iAnimation ); +#line 788 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 794 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::Initialize(void) { +#line 796 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bReference = TRUE ; +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bWaitJumpAnim = FALSE ; +#line 798 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bCrouch = FALSE ; +#line 799 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_iCrouchDownWait = 0; +#line 800 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_iRiseUpWait = 0; +#line 801 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bChangeWeapon = FALSE ; +#line 802 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSwim = FALSE ; +#line 803 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bAttacking = FALSE ; +#line 806 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fEyesYLastOffset = 0.0f; +#line 807 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fEyesYOffset = 0.0f; +#line 808 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fEyesYSpeed = 0.0f; +#line 809 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fWeaponYLastOffset = 0.0f; +#line 810 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fWeaponYOffset = 0.0f; +#line 811 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fWeaponYSpeed = 0.0f; +#line 817 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bMoving = FALSE ; +#line 818 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fMoveLastBanking = 0.0f; +#line 819 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fMoveBanking = 0.0f; +#line 820 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_iMovingSide = 0; +#line 821 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSidestepBankingLeft = FALSE ; +#line 822 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSidestepBankingRight = FALSE ; +#line 823 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fSidestepLastBanking = 0.0f; +#line 824 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fSidestepBanking = 0.0f; +#line 827 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetWeapon (); +#line 828 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetBodyAnimation (BODY_ANIM_COLT_STAND , AOF_LOOPING | AOF_NORESTART ); +#line 829 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 836 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::StoreLast(void) { +#line 837 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 838 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_vLastPlayerPosition = pl . GetPlacement () . pl_PositionVector ; +#line 839 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fEyesYLastOffset = m_fEyesYOffset ; +#line 840 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fWeaponYLastOffset = m_fWeaponYOffset ; +#line 842 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fMoveLastBanking = m_fMoveBanking ; +#line 843 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fSidestepLastBanking = m_fSidestepBanking ; +#line 844 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 847 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::AnimateBanking(void) { +#line 849 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bMoving ){ +#line 851 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_iMovingSide == 0){ +#line 852 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fMoveBanking += 0.35f; +#line 853 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_fMoveBanking > 1.0f){ +#line 854 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fMoveBanking = 1.0f; +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_iMovingSide = 1; +#line 856 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 858 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 859 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fMoveBanking -= 0.35f; +#line 860 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_fMoveBanking < - 1.0f){ +#line 861 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fMoveBanking = - 1.0f; +#line 862 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_iMovingSide = 0; +#line 863 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 864 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 865 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +const FLOAT fBankingSpeed = 0.4f; +#line 868 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bSidestepBankingLeft ){ +#line 869 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fSidestepBanking += fBankingSpeed ; +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_fSidestepBanking > 1.0f){m_fSidestepBanking = 1.0f;} +#line 871 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 873 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bSidestepBankingRight ){ +#line 874 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fSidestepBanking -= fBankingSpeed ; +#line 875 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_fSidestepBanking < - 1.0f){m_fSidestepBanking = - 1.0f;} +#line 876 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 879 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 881 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_fMoveBanking > 0.0f){ +#line 882 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fMoveBanking -= 0.1f; +#line 883 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_fMoveBanking < 0.0f){m_fMoveBanking = 0.0f;} +#line 884 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(m_fMoveBanking < 0.0f){ +#line 885 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fMoveBanking += 0.1f; +#line 886 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_fMoveBanking > 0.0f){m_fMoveBanking = 0.0f;} +#line 887 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 889 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_fSidestepBanking > 0.0f){ +#line 890 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fSidestepBanking -= 0.4f; +#line 891 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_fSidestepBanking < 0.0f){m_fSidestepBanking = 0.0f;} +#line 892 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(m_fSidestepBanking < 0.0f){ +#line 893 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fSidestepBanking += 0.4f; +#line 894 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_fSidestepBanking > 0.0f){m_fSidestepBanking = 0.0f;} +#line 895 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 896 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 898 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(GetPlayer () -> GetSettings () -> ps_ulFlags & PSF_NOBOBBING ){ +#line 899 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fSidestepBanking = m_fMoveBanking = 0.0f; +#line 900 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 901 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 904 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::AnimateSoftEyes(void) { +#line 905 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 907 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +FLOAT fRelY = (pl . GetPlacement () . pl_PositionVector - m_vLastPlayerPosition ) % +#line 908 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +FLOAT3D (pl . en_mRotation (1 , 2) , pl . en_mRotation (2 , 2) , pl . en_mRotation (3 , 2)); +#line 911 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pl . en_tmJumped > _pTimer -> CurrentTick () - 0.5f){ +#line 912 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +fRelY = ClampUp (fRelY , 0.0f); +#line 913 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 914 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fEyesYOffset -= fRelY ; +#line 915 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fWeaponYOffset -= ClampUp (fRelY , 0.0f); +#line 917 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +plr_fViewDampFactor = Clamp (plr_fViewDampFactor , 0.0f , 1.0f); +#line 918 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +plr_fViewDampLimitGroundUp = Clamp (plr_fViewDampLimitGroundUp , 0.0f , 2.0f); +#line 919 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +plr_fViewDampLimitGroundDn = Clamp (plr_fViewDampLimitGroundDn , 0.0f , 2.0f); +#line 920 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +plr_fViewDampLimitWater = Clamp (plr_fViewDampLimitWater , 0.0f , 2.0f); +#line 922 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fEyesYSpeed = (m_fEyesYSpeed - m_fEyesYOffset * plr_fViewDampFactor ) * (1.0f - plr_fViewDampFactor ); +#line 923 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fEyesYOffset += m_fEyesYSpeed ; +#line 925 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fWeaponYSpeed = (m_fWeaponYSpeed - m_fWeaponYOffset * plr_fViewDampFactor ) * (1.0f - plr_fViewDampFactor ); +#line 926 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fWeaponYOffset += m_fWeaponYSpeed ; +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bSwim ){ +#line 929 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fEyesYOffset = Clamp (m_fEyesYOffset , - plr_fViewDampLimitWater , + plr_fViewDampLimitWater ); +#line 930 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fWeaponYOffset = Clamp (m_fWeaponYOffset , - plr_fViewDampLimitWater , + plr_fViewDampLimitWater ); +#line 931 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 932 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fEyesYOffset = Clamp (m_fEyesYOffset , - plr_fViewDampLimitGroundDn , + plr_fViewDampLimitGroundUp ); +#line 933 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fWeaponYOffset = Clamp (m_fWeaponYOffset , - plr_fViewDampLimitGroundDn , + plr_fViewDampLimitGroundUp ); +#line 934 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 935 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::ChangeView(CPlacement3D & pl) { +#line 968 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +TIME tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 970 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(! (GetPlayer () -> GetSettings () -> ps_ulFlags & PSF_NOBOBBING )){ +#line 972 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +FLOAT fBanking = Lerp (m_fMoveLastBanking , m_fMoveBanking , _pTimer -> GetLerpFactor ()); +#line 973 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +fBanking = fBanking * fBanking * Sgn (fBanking ) * 0.25f; +#line 974 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +fBanking += Lerp (m_fSidestepLastBanking , m_fSidestepBanking , _pTimer -> GetLerpFactor ()); +#line 975 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +fBanking = Clamp (fBanking , - 5.0f , 5.0f); +#line 976 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . pl_OrientationAngle (3) += fBanking ; +#line 977 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 994 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bSwim ){ +#line 995 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . pl_OrientationAngle (1) += sin (tmNow * 0.9) * 2.0f; +#line 996 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . pl_OrientationAngle (2) += sin (tmNow * 1.7) * 2.0f; +#line 997 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . pl_OrientationAngle (3) += sin (tmNow * 2.5) * 2.0f; +#line 998 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1000 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +FLOAT fEyesOffsetY = Lerp (m_fEyesYLastOffset , m_fEyesYOffset , _pTimer -> GetLerpFactor ()); +#line 1001 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +fEyesOffsetY += sin (tmNow * 1.5) * 0.05f * plr_fBreathingStrength ; +#line 1002 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +fEyesOffsetY = Clamp (fEyesOffsetY , - 1.0f , 1.0f); +#line 1003 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . pl_PositionVector (2) += fEyesOffsetY ; +#line 1004 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1012 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::BodyAndHeadOrientation(CPlacement3D & plView) { +#line 1013 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1014 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CAttachmentModelObject * pamoBody = pl . GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ); +#line 1015 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ANGLE3D a = plView . pl_OrientationAngle ; +#line 1016 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(! (pl . GetFlags () & ENF_ALIVE )){ +#line 1017 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +a = ANGLE3D (0 , 0 , 0); +#line 1018 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1019 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoBody -> amo_plRelative . pl_OrientationAngle = a ; +#line 1020 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoBody -> amo_plRelative . pl_OrientationAngle (3) *= 4.0f; +#line 1022 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CAttachmentModelObject * pamoHead = (pamoBody -> amo_moModelObject ) . GetAttachmentModel (BODY_ATTACHMENT_HEAD ); +#line 1023 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoHead -> amo_plRelative . pl_OrientationAngle = a ; +#line 1024 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoHead -> amo_plRelative . pl_OrientationAngle (1) = 0.0f; +#line 1025 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoHead -> amo_plRelative . pl_OrientationAngle (2) = 0.0f; +#line 1026 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoHead -> amo_plRelative . pl_OrientationAngle (3) *= 4.0f; +#line 1029 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +const FLOAT fMaxBanking = 5.0f; +#line 1030 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoBody -> amo_plRelative . pl_OrientationAngle (3) = Clamp (pamoBody -> amo_plRelative . pl_OrientationAngle (3) , - fMaxBanking , fMaxBanking ); +#line 1031 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamoHead -> amo_plRelative . pl_OrientationAngle (3) = Clamp (pamoHead -> amo_plRelative . pl_OrientationAngle (3) , - fMaxBanking , fMaxBanking ); +#line 1032 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1035 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::AnimatePlayer(void) { +#line 1036 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bDisableAnimating ){ +#line 1037 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return ; +#line 1038 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1039 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1041 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +FLOAT3D vDesiredTranslation = pl . en_vDesiredTranslationRelative ; +#line 1042 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +FLOAT3D vCurrentTranslation = pl . en_vCurrentTranslationAbsolute * ! pl . en_mRotation ; +#line 1043 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ANGLE3D aDesiredRotation = pl . en_aDesiredRotationRelative ; +#line 1044 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ANGLE3D aCurrentRotation = pl . en_aCurrentRotationAbsolute ; +#line 1047 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(vDesiredTranslation . ManhattanNorm () > 0.01f +#line 1048 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +|| aDesiredRotation . ManhattanNorm () > 0.01f){ +#line 1050 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fLastActionTime = _pTimer -> CurrentTick (); +#line 1051 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1054 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bSwim ){ +#line 1055 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(vDesiredTranslation . Length () > 1.0f && vCurrentTranslation . Length () > 1.0f){ +#line 1056 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_SWIM , AOF_LOOPING | AOF_NORESTART ); +#line 1057 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 1058 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_SWIMIDLE , AOF_LOOPING | AOF_NORESTART ); +#line 1059 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1060 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1063 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 1065 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bReference ){ +#line 1067 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pl . en_tmJumped + _pTimer -> TickQuantum >= _pTimer -> CurrentTick () && +#line 1068 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . en_tmJumped <= _pTimer -> CurrentTick ()){ +#line 1069 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bReference = FALSE ; +#line 1070 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_JUMPSTART , AOF_NORESTART ); +#line 1071 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1072 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fLastActionTime = _pTimer -> CurrentTick (); +#line 1075 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(! m_bWaitJumpAnim && m_iCrouchDownWait == 0 && m_iRiseUpWait == 0){ +#line 1077 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(! m_bCrouch ){ +#line 1079 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(vDesiredTranslation . Length () > 5.0f && vCurrentTranslation . Length () > 5.0f){ +#line 1080 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(vCurrentTranslation (3) < 0){ +#line 1081 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_RUN , AOF_LOOPING | AOF_NORESTART ); +#line 1082 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 1083 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_BACKPEDALRUN , AOF_LOOPING | AOF_NORESTART ); +#line 1084 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1085 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fLastActionTime = _pTimer -> CurrentTick (); +#line 1088 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(vDesiredTranslation . Length () > 2.0f && vCurrentTranslation . Length () > 2.0f){ +#line 1089 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(vCurrentTranslation (3) < 0){ +#line 1090 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_NORMALWALK , AOF_LOOPING | AOF_NORESTART ); +#line 1091 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 1092 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_BACKPEDAL , AOF_LOOPING | AOF_NORESTART ); +#line 1093 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1094 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1095 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fLastActionTime = _pTimer -> CurrentTick (); +#line 1097 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(aDesiredRotation (1) > 0.5f){ +#line 1098 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_TURNLEFT , AOF_LOOPING | AOF_NORESTART ); +#line 1099 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1100 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fLastActionTime = _pTimer -> CurrentTick (); +#line 1102 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(aDesiredRotation (1) < - 0.5f){ +#line 1103 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_TURNRIGHT , AOF_LOOPING | AOF_NORESTART ); +#line 1104 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1105 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fLastActionTime = _pTimer -> CurrentTick (); +#line 1107 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 1108 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_STAND , AOF_LOOPING | AOF_NORESTART ); +#line 1109 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1110 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1112 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 1114 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(vDesiredTranslation . Length () > 2.0f && vCurrentTranslation . Length () > 2.0f){ +#line 1115 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(vCurrentTranslation (3) < 0){ +#line 1116 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_CROUCH_WALK , AOF_LOOPING | AOF_NORESTART ); +#line 1117 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 1118 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_CROUCH_WALKBACK , AOF_LOOPING | AOF_NORESTART ); +#line 1119 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1120 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1121 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fLastActionTime = _pTimer -> CurrentTick (); +#line 1123 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(aDesiredRotation (1) > 0.5f){ +#line 1124 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_CROUCH_TURNLEFT , AOF_LOOPING | AOF_NORESTART ); +#line 1125 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1126 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fLastActionTime = _pTimer -> CurrentTick (); +#line 1128 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(aDesiredRotation (1) < - 0.5f){ +#line 1129 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_CROUCH_TURNRIGHT , AOF_LOOPING | AOF_NORESTART ); +#line 1130 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1131 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fLastActionTime = _pTimer -> CurrentTick (); +#line 1133 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 1134 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_CROUCH_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 1135 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1136 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1137 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1139 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1142 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 1144 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pl . en_penReference != NULL ){ +#line 1145 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bReference = TRUE ; +#line 1146 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_JUMPEND , AOF_NORESTART ); +#line 1147 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyStillAnimation (); +#line 1148 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SpawnReminder (this , pl . GetModelObject () -> GetAnimLength (PLAYER_ANIM_JUMPEND ) , (INDEX) AA_JUMPDOWN ); +#line 1149 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bWaitJumpAnim = TRUE ; +#line 1150 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1151 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1152 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1155 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(_pTimer -> CurrentTick () - m_fLastActionTime > 10.0f){ +#line 1156 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fLastActionTime = _pTimer -> CurrentTick (); +#line 1157 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +((CPlayerWeapons &) * pl . m_penWeapons ) . SendEvent (EBoringWeapon ()); +#line 1158 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1162 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bReference != NULL && vDesiredTranslation . Length () > 1.0f && vCurrentTranslation . Length () > 1.0f){ +#line 1163 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bMoving = TRUE ; +#line 1165 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +FLOAT vSidestepSpeedDesired = vDesiredTranslation (1); +#line 1166 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +FLOAT vSidestepSpeedCurrent = vCurrentTranslation (1); +#line 1168 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(vSidestepSpeedDesired > 1.0f && vSidestepSpeedCurrent > 1.0f){ +#line 1169 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSidestepBankingRight = TRUE ; +#line 1170 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSidestepBankingLeft = FALSE ; +#line 1172 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(vSidestepSpeedDesired < - 1.0f && vSidestepSpeedCurrent < - 1.0f){ +#line 1173 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSidestepBankingLeft = TRUE ; +#line 1174 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSidestepBankingRight = FALSE ; +#line 1176 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 1177 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSidestepBankingLeft = FALSE ; +#line 1178 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSidestepBankingRight = FALSE ; +#line 1179 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1181 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else { +#line 1182 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bMoving = FALSE ; +#line 1183 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSidestepBankingLeft = FALSE ; +#line 1184 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSidestepBankingRight = FALSE ; +#line 1185 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1186 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1189 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::Crouch(void) { +#line 1190 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bDisableAnimating ){ +#line 1191 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return ; +#line 1192 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1193 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1194 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_CROUCH , AOF_NORESTART ); +#line 1195 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SpawnReminder (this , pl . GetModelObject () -> GetAnimLength (PLAYER_ANIM_CROUCH ) , (INDEX) AA_CROUCH ); +#line 1196 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_iCrouchDownWait ++; +#line 1197 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bCrouch = TRUE ; +#line 1198 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1201 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::Rise(void) { +#line 1202 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bDisableAnimating ){ +#line 1203 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return ; +#line 1204 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1205 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1206 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_RISE , AOF_NORESTART ); +#line 1207 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SpawnReminder (this , pl . GetModelObject () -> GetAnimLength (PLAYER_ANIM_RISE ) , (INDEX) AA_RISE ); +#line 1208 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_iRiseUpWait ++; +#line 1209 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bCrouch = FALSE ; +#line 1210 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1213 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::Fall(void) { +#line 1214 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bDisableAnimating ){ +#line 1215 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return ; +#line 1216 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1217 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1218 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_JUMPSTART , AOF_NORESTART ); +#line 1219 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(_pNetwork -> ga_ulDemoMinorVersion > 6){m_bCrouch = FALSE ;} +#line 1220 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bReference = FALSE ; +#line 1221 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1224 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::Swim(void) { +#line 1225 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bDisableAnimating ){ +#line 1226 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return ; +#line 1227 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1228 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1229 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_SWIM , AOF_LOOPING | AOF_NORESTART ); +#line 1230 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(_pNetwork -> ga_ulDemoMinorVersion > 2){m_bCrouch = FALSE ;} +#line 1231 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSwim = TRUE ; +#line 1232 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1235 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::Stand(void) { +#line 1236 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bDisableAnimating ){ +#line 1237 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return ; +#line 1238 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1239 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1240 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pl . StartModelAnim (PLAYER_ANIM_STAND , AOF_LOOPING | AOF_NORESTART ); +#line 1241 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(_pNetwork -> ga_ulDemoMinorVersion > 2){m_bCrouch = FALSE ;} +#line 1242 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bSwim = FALSE ; +#line 1243 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::FireAnimation(INDEX iAnim,ULONG ulFlags) { +#line 1247 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bSwim ){ +#line 1248 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +INDEX iWeapon = ((CPlayerWeapons &) * (((CPlayer &) * m_penPlayer ) . m_penWeapons )) . m_iCurrentWeapon ; +#line 1249 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +switch(iWeapon ){ +#line 1250 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_NONE : +#line 1251 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1252 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_KNIFE : case WEAPON_COLT : case WEAPON_DOUBLECOLT : +#line 1253 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +iAnim += BODY_ANIM_COLT_SWIM_STAND - BODY_ANIM_COLT_STAND ; +#line 1254 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1255 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SINGLESHOTGUN : case WEAPON_DOUBLESHOTGUN : case WEAPON_TOMMYGUN : +#line 1256 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SNIPER : case WEAPON_LASER : case WEAPON_FLAMER : +#line 1257 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +iAnim += BODY_ANIM_SHOTGUN_SWIM_STAND - BODY_ANIM_SHOTGUN_STAND ; +#line 1258 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1259 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_MINIGUN : case WEAPON_ROCKETLAUNCHER : case WEAPON_GRENADELAUNCHER : +#line 1260 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_IRONCANNON : case WEAPON_CHAINSAW : +#line 1261 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +iAnim += BODY_ANIM_MINIGUN_SWIM_STAND - BODY_ANIM_MINIGUN_STAND ; +#line 1262 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1263 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1264 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1265 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bAttacking = FALSE ; +#line 1266 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bChangeWeapon = FALSE ; +#line 1267 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetBodyAnimation (iAnim , ulFlags ); +#line 1268 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(! (ulFlags & AOF_LOOPING )){ +#line 1269 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SpawnReminder (this , m_fBodyAnimTime , (INDEX) AA_ATTACK ); +#line 1270 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_tmAttackingDue = _pTimer -> CurrentTick () + m_fBodyAnimTime ; +#line 1271 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1272 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bAttacking = TRUE ; +#line 1273 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1274 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::FireAnimationOff(void) { +#line 1275 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bAttacking = FALSE ; +#line 1276 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1284 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::BodyAnimationTemplate(INDEX iNone,INDEX iColt,INDEX iShotgun,INDEX iMinigun,ULONG ulFlags) { +#line 1285 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +INDEX iWeapon = ((CPlayerWeapons &) * (((CPlayer &) * m_penPlayer ) . m_penWeapons )) . m_iCurrentWeapon ; +#line 1286 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +switch(iWeapon ){ +#line 1287 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_NONE : +#line 1288 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetBodyAnimation (iNone , ulFlags ); +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1290 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_KNIFE : case WEAPON_COLT : case WEAPON_DOUBLECOLT : +#line 1291 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bSwim ){iColt += BODY_ANIM_COLT_SWIM_STAND - BODY_ANIM_COLT_STAND ;} +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetBodyAnimation (iColt , ulFlags ); +#line 1293 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1294 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SINGLESHOTGUN : case WEAPON_DOUBLESHOTGUN : case WEAPON_TOMMYGUN : +#line 1295 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SNIPER : case WEAPON_LASER : case WEAPON_FLAMER : +#line 1296 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bSwim ){iShotgun += BODY_ANIM_SHOTGUN_SWIM_STAND - BODY_ANIM_SHOTGUN_STAND ;} +#line 1297 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetBodyAnimation (iShotgun , ulFlags ); +#line 1298 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1299 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_MINIGUN : case WEAPON_ROCKETLAUNCHER : case WEAPON_GRENADELAUNCHER : +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_IRONCANNON : case WEAPON_CHAINSAW : +#line 1301 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(m_bSwim ){iMinigun += BODY_ANIM_MINIGUN_SWIM_STAND - BODY_ANIM_MINIGUN_STAND ;} +#line 1302 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetBodyAnimation (iMinigun , ulFlags ); +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1304 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +default : ASSERTALWAYS ("Player Animator - Unknown weapon"); +#line 1305 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1306 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1309 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::BodyWalkAnimation() { +#line 1310 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyAnimationTemplate (BODY_ANIM_NORMALWALK , +#line 1311 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BODY_ANIM_COLT_STAND , BODY_ANIM_SHOTGUN_STAND , BODY_ANIM_MINIGUN_STAND , +#line 1312 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AOF_LOOPING | AOF_NORESTART ); +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1316 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::BodyStillAnimation() { +#line 1317 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyAnimationTemplate (BODY_ANIM_WAIT , +#line 1318 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BODY_ANIM_COLT_STAND , BODY_ANIM_SHOTGUN_STAND , BODY_ANIM_MINIGUN_STAND , +#line 1319 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +AOF_LOOPING | AOF_NORESTART ); +#line 1320 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1323 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::BodyPushAnimation() { +#line 1324 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bAttacking = FALSE ; +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bChangeWeapon = FALSE ; +#line 1326 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyAnimationTemplate (BODY_ANIM_WAIT , +#line 1327 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BODY_ANIM_COLT_REDRAW , BODY_ANIM_SHOTGUN_REDRAW , BODY_ANIM_MINIGUN_REDRAW , 0); +#line 1328 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bChangeWeapon = TRUE ; +#line 1329 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1332 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::RemoveWeapon(void) +#line 1333 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +{ +#line 1334 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1335 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel = & (pl . GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ); +#line 1336 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +switch(m_iWeaponLast ){ +#line 1337 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_NONE : +#line 1338 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_KNIFE : +#line 1339 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_KNIFE ); +#line 1340 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1341 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_DOUBLECOLT : +#line 1342 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_COLT_LEFT ); +#line 1344 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel = & (pl . GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ); +#line 1345 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_COLT : +#line 1346 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_COLT_RIGHT ); +#line 1347 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1348 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SINGLESHOTGUN : +#line 1349 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_SINGLE_SHOTGUN ); +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1351 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_DOUBLESHOTGUN : +#line 1352 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_DOUBLE_SHOTGUN ); +#line 1353 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1354 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_TOMMYGUN : +#line 1355 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_TOMMYGUN ); +#line 1356 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1357 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SNIPER : +#line 1358 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_FLAMER ); +#line 1359 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1360 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_MINIGUN : +#line 1361 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_MINIGUN ); +#line 1362 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1363 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_ROCKETLAUNCHER : +#line 1364 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_ROCKET_LAUNCHER ); +#line 1365 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1366 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_GRENADELAUNCHER : +#line 1367 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_GRENADE_LAUNCHER ); +#line 1368 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1375 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_FLAMER : +#line 1376 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_FLAMER ); +#line 1377 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1378 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_CHAINSAW : +#line 1379 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_MINIGUN ); +#line 1380 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1381 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_LASER : +#line 1382 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_LASER ); +#line 1383 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1387 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_IRONCANNON : +#line 1389 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_CANNON ); +#line 1390 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1391 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +default : +#line 1392 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ASSERT (FALSE ); +#line 1393 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1395 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SyncWeapon (); +#line 1396 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::BodyPullAnimation() { +#line 1401 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +RemoveWeapon (); +#line 1404 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetWeapon (); +#line 1407 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bChangeWeapon = FALSE ; +#line 1408 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BodyAnimationTemplate (BODY_ANIM_WAIT , +#line 1409 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +BODY_ANIM_COLT_DRAW , BODY_ANIM_SHOTGUN_DRAW , BODY_ANIM_MINIGUN_DRAW , 0); +#line 1410 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +INDEX iWeapon = ((CPlayerWeapons &) * (((CPlayer &) * m_penPlayer ) . m_penWeapons )) . m_iCurrentWeapon ; +#line 1411 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(iWeapon != WEAPON_NONE ){ +#line 1412 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bChangeWeapon = TRUE ; +#line 1413 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SpawnReminder (this , m_fBodyAnimTime , (INDEX) AA_PULLWEAPON ); +#line 1414 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1416 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SyncWeapon (); +#line 1417 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1420 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::BodyPullItemAnimation() { +#line 1422 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +RemoveWeapon (); +#line 1425 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bChangeWeapon = FALSE ; +#line 1426 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetBodyAnimation (BODY_ANIM_STATUE_PULL , 0); +#line 1427 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bChangeWeapon = TRUE ; +#line 1428 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SpawnReminder (this , m_fBodyAnimTime , (INDEX) AA_PULLWEAPON ); +#line 1430 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SyncWeapon (); +#line 1431 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1434 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::BodyPickItemAnimation() { +#line 1436 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +RemoveWeapon (); +#line 1439 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bChangeWeapon = FALSE ; +#line 1440 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetBodyAnimation (BODY_ANIM_KEYLIFT , 0); +#line 1441 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_bChangeWeapon = TRUE ; +#line 1442 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SpawnReminder (this , m_fBodyAnimTime , (INDEX) AA_PULLWEAPON ); +#line 1444 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SyncWeapon (); +#line 1445 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1448 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::BodyRemoveItem() { +#line 1449 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1450 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel = & (pl . GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ); +#line 1451 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pmoModel -> RemoveAttachmentModel (BODY_ATTACHMENT_ITEM ); +#line 1453 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SyncWeapon (); +#line 1454 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1460 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::OnPreRender(void) { +#line 1461 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ControlFlareAttachment (); +#line 1464 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayerWeapons & plw = (CPlayerWeapons &) * (((CPlayer &) * m_penPlayer ) . m_penWeapons ); +#line 1465 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(plw . m_iCurrentWeapon == WEAPON_MINIGUN ){ +#line 1466 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ANGLE aAngle = Lerp (plw . m_aMiniGunLast , plw . m_aMiniGun , _pTimer -> GetLerpFactor ()); +#line 1468 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1469 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CAttachmentModelObject * pamo = pl . GetModelObject () -> GetAttachmentModelList ( +#line 1470 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +PLAYER_ATTACHMENT_TORSO , BODY_ATTACHMENT_MINIGUN , MINIGUNITEM_ATTACHMENT_BARRELS , - 1); +#line 1471 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pamo != NULL ){ +#line 1472 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamo -> amo_plRelative . pl_OrientationAngle (3) = aAngle ; +#line 1473 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1474 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1475 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1478 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::ShowFlare(INDEX iAttachWeapon,INDEX iAttachObject,INDEX iAttachFlare) { +#line 1479 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1480 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CAttachmentModelObject * pamo = pl . GetModelObject () -> GetAttachmentModelList ( +#line 1481 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +PLAYER_ATTACHMENT_TORSO , iAttachWeapon , iAttachObject , iAttachFlare , - 1); +#line 1482 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pamo != NULL ){ +#line 1483 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pamo -> amo_plRelative . pl_OrientationAngle (3) = (rand () * 360.0f) / RAND_MAX ; +#line 1484 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CModelObject & mo = pamo -> amo_moModelObject ; +#line 1485 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +mo . StretchModel (FLOAT3D (1 , 1 , 1)); +#line 1486 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1487 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1490 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::HideFlare(INDEX iAttachWeapon,INDEX iAttachObject,INDEX iAttachFlare) { +#line 1491 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1492 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CAttachmentModelObject * pamo = pl . GetModelObject () -> GetAttachmentModelList ( +#line 1493 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +PLAYER_ATTACHMENT_TORSO , iAttachWeapon , iAttachObject , iAttachFlare , - 1); +#line 1494 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pamo != NULL ){ +#line 1495 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CModelObject & mo = pamo -> amo_moModelObject ; +#line 1496 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +mo . StretchModel (FLOAT3D (0 , 0 , 0)); +#line 1497 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1498 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} + +#line 1501 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void CPlayerAnimator::ControlFlareAttachment(void) +#line 1502 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +{ +#line 1509 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayerAnimator * pen = (CPlayerAnimator *) GetPredictionTail (); +#line 1511 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +INDEX iWeapon = ((CPlayerWeapons &) * (((CPlayer &) * pen -> m_penPlayer ) . m_penWeapons )) . m_iCurrentWeapon ; +#line 1513 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(iWeapon == WEAPON_DOUBLECOLT ){ +#line 1515 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pen -> m_iSecondFlare == FLARE_ADD ){ +#line 1516 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pen -> m_iSecondFlare = FLARE_REMOVE ; +#line 1517 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ShowFlare (BODY_ATTACHMENT_COLT_LEFT , COLTITEM_ATTACHMENT_BODY , COLTMAIN_ATTACHMENT_FLARE ); +#line 1519 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(m_iSecondFlare == FLARE_REMOVE ){ +#line 1520 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +HideFlare (BODY_ATTACHMENT_COLT_LEFT , COLTITEM_ATTACHMENT_BODY , COLTMAIN_ATTACHMENT_FLARE ); +#line 1521 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1522 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1525 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +if(pen -> m_iFlare == FLARE_ADD ){ +#line 1526 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pen -> m_iFlare = FLARE_REMOVE ; +#line 1527 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +pen -> m_tmFlareAdded = _pTimer -> CurrentTick (); +#line 1528 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +switch(iWeapon ){ +#line 1529 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_DOUBLECOLT : case WEAPON_COLT : +#line 1530 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ShowFlare (BODY_ATTACHMENT_COLT_RIGHT , COLTITEM_ATTACHMENT_BODY , COLTMAIN_ATTACHMENT_FLARE ); +#line 1531 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1532 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SINGLESHOTGUN : +#line 1533 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ShowFlare (BODY_ATTACHMENT_SINGLE_SHOTGUN , SINGLESHOTGUNITEM_ATTACHMENT_BARRELS , BARRELS_ATTACHMENT_FLARE ); +#line 1534 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1535 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_DOUBLESHOTGUN : +#line 1536 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ShowFlare (BODY_ATTACHMENT_DOUBLE_SHOTGUN , DOUBLESHOTGUNITEM_ATTACHMENT_BARRELS , DSHOTGUNBARRELS_ATTACHMENT_FLARE ); +#line 1537 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1538 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_TOMMYGUN : +#line 1539 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ShowFlare (BODY_ATTACHMENT_TOMMYGUN , TOMMYGUNITEM_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE ); +#line 1540 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1541 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SNIPER : +#line 1542 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ShowFlare (BODY_ATTACHMENT_FLAMER , SNIPERITEM_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE ); +#line 1543 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1544 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_MINIGUN : +#line 1545 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ShowFlare (BODY_ATTACHMENT_MINIGUN , MINIGUNITEM_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE ); +#line 1546 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1547 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1549 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}else if(m_iFlare == FLARE_REMOVE && +#line 1550 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +_pTimer -> CurrentTick () > pen -> m_tmFlareAdded + _pTimer -> TickQuantum ){ +#line 1551 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +switch(iWeapon ){ +#line 1552 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_DOUBLECOLT : case WEAPON_COLT : +#line 1553 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +HideFlare (BODY_ATTACHMENT_COLT_RIGHT , COLTITEM_ATTACHMENT_BODY , COLTMAIN_ATTACHMENT_FLARE ); +#line 1554 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1555 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SINGLESHOTGUN : +#line 1556 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +HideFlare (BODY_ATTACHMENT_SINGLE_SHOTGUN , SINGLESHOTGUNITEM_ATTACHMENT_BARRELS , BARRELS_ATTACHMENT_FLARE ); +#line 1557 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1558 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_DOUBLESHOTGUN : +#line 1559 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +HideFlare (BODY_ATTACHMENT_DOUBLE_SHOTGUN , DOUBLESHOTGUNITEM_ATTACHMENT_BARRELS , DSHOTGUNBARRELS_ATTACHMENT_FLARE ); +#line 1560 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1561 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_TOMMYGUN : +#line 1562 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +HideFlare (BODY_ATTACHMENT_TOMMYGUN , TOMMYGUNITEM_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE ); +#line 1563 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1564 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_SNIPER : +#line 1565 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +HideFlare (BODY_ATTACHMENT_FLAMER , SNIPERITEM_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE ); +#line 1566 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1567 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case WEAPON_MINIGUN : +#line 1568 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +HideFlare (BODY_ATTACHMENT_MINIGUN , MINIGUNITEM_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE ); +#line 1569 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +break ; +#line 1570 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1571 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1572 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +BOOL CPlayerAnimator:: +#line 1580 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ReminderAction(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerAnimator_ReminderAction + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EReminder, "CPlayerAnimator::ReminderAction expects 'EReminder' as input!"); const EReminder &er = (const EReminder &)__eeInput; +#line 1581 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +switch(er . iValue ){ +#line 1582 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case AA_JUMPDOWN : m_bWaitJumpAnim = FALSE ;break ; +#line 1583 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case AA_CROUCH : m_iCrouchDownWait --;ASSERT (m_iCrouchDownWait >= 0);break ; +#line 1584 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case AA_RISE : m_iRiseUpWait --;ASSERT (m_iRiseUpWait >= 0);break ; +#line 1585 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case AA_PULLWEAPON : m_bChangeWeapon = FALSE ;break ; +#line 1586 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +case AA_ATTACK : if(m_tmAttackingDue <= _pTimer -> CurrentTick ()){m_bAttacking = FALSE ;}break ; +#line 1587 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +default : ASSERTALWAYS ("Animator - unknown reminder action."); +#line 1588 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +} +#line 1589 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +Return(STATE_CURRENT,EBegin ()); +#line 1589 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerAnimator:: +#line 1592 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerAnimator_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EAnimatorInit, "CPlayerAnimator::Main expects 'EAnimatorInit' as input!"); const EAnimatorInit &eInit = (const EAnimatorInit &)__eeInput; +#line 1594 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ASSERT (eInit . penPlayer != NULL ); +#line 1595 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_penPlayer = eInit . penPlayer ; +#line 1598 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +InitAsVoid (); +#line 1599 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetFlags (GetFlags () | ENF_CROSSESLEVELS ); +#line 1600 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 1601 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 1604 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +m_fLastActionTime = _pTimer -> CurrentTick (); +#line 1606 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01960002, FALSE, EBegin());return TRUE;}BOOL CPlayerAnimator::H0x01960002_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01960002 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EReminder):{const EReminder&er= (EReminder&)__eeInput; +Call(STATE_CURRENT, STATE_CPlayerAnimator_ReminderAction, TRUE, er );return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EEnd):{const EEnd&e= (EEnd&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01960003, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 1610 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +}return TRUE;}BOOL CPlayerAnimator::H0x01960003_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01960003 + +#line 1613 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +Destroy (); +#line 1615 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +Return(STATE_CURRENT,EVoid()); +#line 1615 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/PlayerAnimator.es b/Sources/EntitiesMP/PlayerAnimator.es new file mode 100644 index 0000000..4088626 --- /dev/null +++ b/Sources/EntitiesMP/PlayerAnimator.es @@ -0,0 +1,1618 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +406 +%{ +#include "StdH.h" + +#include "ModelsMP/Player/SeriousSam/Player.h" +#include "ModelsMP/Player/SeriousSam/Body.h" +#include "ModelsMP/Player/SeriousSam/Head.h" + +#include "Models/Weapons/Knife/KnifeItem.h" +#include "Models/Weapons/Colt/ColtItem.h" +#include "Models/Weapons/Colt/ColtMain.h" +#include "Models/Weapons/SingleShotgun/SingleShotgunItem.h" +#include "Models/Weapons/SingleShotgun/Barrels.h" +#include "Models/Weapons/DoubleShotgun/DoubleShotgunItem.h" +#include "Models/Weapons/DoubleShotgun/Dshotgunbarrels.h" +#include "Models/Weapons/TommyGun/TommyGunItem.h" +#include "Models/Weapons/TommyGun/Body.h" +#include "Models/Weapons/MiniGun/MiniGunItem.h" +#include "Models/Weapons/MiniGun/Body.h" +#include "Models/Weapons/GrenadeLauncher/GrenadeLauncherItem.h" +#include "Models/Weapons/RocketLauncher/RocketLauncherItem.h" +#include "ModelsMP/Weapons/Sniper/SniperItem.h" +#include "ModelsMP/Weapons/Sniper/Sniper.h" +//#include "Models/Weapons/Pipebomb/StickItem.h" +#include "ModelsMP/Weapons/Flamer/FlamerItem.h" +#include "ModelsMP/Weapons/Flamer/Body.h" +//#include "ModelsMP/Weapons/Chainsaw/ChainsawItem.h" +#include "ModelsMP/Weapons/Chainsaw/ChainsawForPlayer.h" +#include "ModelsMP/Weapons/Chainsaw/BladeForPlayer.h" +#include "ModelsMP/Weapons/Chainsaw/Body.h" +#include "Models/Weapons/Laser/LaserItem.h" +//#include "Models/Weapons/GhostBuster/GhostBusterItem.h" +//#include "Models/Weapons/GhostBuster/Effect01.h" +#include "Models/Weapons/Cannon/Cannon.h" +%} + +uses "EntitiesMP/Player"; +uses "EntitiesMP/PlayerWeapons"; + +// input parameter for animator +event EAnimatorInit { + CEntityPointer penPlayer, // player owns it +}; + +%{ +// animator action +enum AnimatorAction { + AA_JUMPDOWN = 0, + AA_CROUCH, + AA_RISE, + AA_PULLWEAPON, + AA_ATTACK, +}; + +// fire flare specific +#define FLARE_NONE 0 +#define FLARE_REMOVE 1 +#define FLARE_ADD 2 + + +extern FLOAT plr_fBreathingStrength; +extern FLOAT plr_fViewDampFactor; +extern FLOAT plr_fViewDampLimitGroundUp; +extern FLOAT plr_fViewDampLimitGroundDn; +extern FLOAT plr_fViewDampLimitWater; +extern FLOAT wpn_fRecoilSpeed[17]; +extern FLOAT wpn_fRecoilLimit[17]; +extern FLOAT wpn_fRecoilDampUp[17]; +extern FLOAT wpn_fRecoilDampDn[17]; +extern FLOAT wpn_fRecoilOffset[17]; +extern FLOAT wpn_fRecoilFactorP[17]; +extern FLOAT wpn_fRecoilFactorZ[17]; + + +void CPlayerAnimator_Precache(ULONG ulAvailable) +{ + CDLLEntityClass *pdec = &CPlayerAnimator_DLLClass; + + pdec->PrecacheTexture(TEX_REFL_BWRIPLES01 ); + pdec->PrecacheTexture(TEX_REFL_BWRIPLES02 ); + pdec->PrecacheTexture(TEX_REFL_LIGHTMETAL01 ); + pdec->PrecacheTexture(TEX_REFL_LIGHTBLUEMETAL01); + pdec->PrecacheTexture(TEX_REFL_DARKMETAL ); + pdec->PrecacheTexture(TEX_REFL_PURPLE01 ); + pdec->PrecacheTexture(TEX_SPEC_WEAK ); + pdec->PrecacheTexture(TEX_SPEC_MEDIUM ); + pdec->PrecacheTexture(TEX_SPEC_STRONG ); + pdec->PrecacheModel(MODEL_FLARE02); + pdec->PrecacheTexture(TEXTURE_FLARE02); + pdec->PrecacheModel(MODEL_GOLDAMON); + pdec->PrecacheTexture(TEXTURE_GOLDAMON); + pdec->PrecacheTexture(TEX_REFL_GOLD01); + pdec->PrecacheClass(CLASS_REMINDER); + + // precache shells that drop when firing + extern void CPlayerWeaponsEffects_Precache(void); + CPlayerWeaponsEffects_Precache(); + + // precache weapons player has + if ( ulAvailable&(1<<(WEAPON_KNIFE-1)) ) { + pdec->PrecacheModel(MODEL_KNIFE ); + pdec->PrecacheTexture(TEXTURE_KNIFE); + } + + if ( ulAvailable&(1<<(WEAPON_COLT-1)) ) { + pdec->PrecacheModel(MODEL_COLT ); + pdec->PrecacheModel(MODEL_COLTCOCK ); + pdec->PrecacheModel(MODEL_COLTMAIN ); + pdec->PrecacheModel(MODEL_COLTBULLETS ); + pdec->PrecacheTexture(TEXTURE_COLTMAIN ); + pdec->PrecacheTexture(TEXTURE_COLTBULLETS ); + pdec->PrecacheTexture(TEXTURE_COLTBULLETS ); + } + + if ( ulAvailable&(1<<(WEAPON_SINGLESHOTGUN-1)) ) { + pdec->PrecacheModel(MODEL_SINGLESHOTGUN ); + pdec->PrecacheModel(MODEL_SS_SLIDER ); + pdec->PrecacheModel(MODEL_SS_HANDLE ); + pdec->PrecacheModel(MODEL_SS_BARRELS ); + pdec->PrecacheTexture(TEXTURE_SS_HANDLE); + pdec->PrecacheTexture(TEXTURE_SS_BARRELS); + } + + if ( ulAvailable&(1<<(WEAPON_DOUBLESHOTGUN-1)) ) { + pdec->PrecacheModel(MODEL_DOUBLESHOTGUN ); + pdec->PrecacheModel(MODEL_DS_HANDLE ); + pdec->PrecacheModel(MODEL_DS_BARRELS ); + pdec->PrecacheModel(MODEL_DS_SWITCH ); + pdec->PrecacheTexture(TEXTURE_DS_HANDLE ); + pdec->PrecacheTexture(TEXTURE_DS_BARRELS ); + pdec->PrecacheTexture(TEXTURE_DS_SWITCH ); + } + + if ( ulAvailable&(1<<(WEAPON_TOMMYGUN-1)) ) { + pdec->PrecacheModel(MODEL_TOMMYGUN ); + pdec->PrecacheModel(MODEL_TG_BODY ); + pdec->PrecacheModel(MODEL_TG_SLIDER ); + pdec->PrecacheTexture(TEXTURE_TG_BODY ); + } + + if ( ulAvailable&(1<<(WEAPON_SNIPER-1)) ) { + pdec->PrecacheModel(MODEL_SNIPER ); + pdec->PrecacheModel(MODEL_SNIPER_BODY ); + pdec->PrecacheTexture(TEXTURE_SNIPER_BODY ); + } + + if ( ulAvailable&(1<<(WEAPON_MINIGUN-1)) ) { + pdec->PrecacheModel(MODEL_MINIGUN ); + pdec->PrecacheModel(MODEL_MG_BARRELS ); + pdec->PrecacheModel(MODEL_MG_BODY ); + pdec->PrecacheModel(MODEL_MG_ENGINE ); + pdec->PrecacheTexture(TEXTURE_MG_BODY ); + pdec->PrecacheTexture(TEXTURE_MG_BARRELS ); + } + + if ( ulAvailable&(1<<(WEAPON_ROCKETLAUNCHER-1)) ) { + pdec->PrecacheModel(MODEL_ROCKETLAUNCHER ); + pdec->PrecacheModel(MODEL_RL_BODY ); + pdec->PrecacheModel(MODEL_RL_ROTATINGPART ); + pdec->PrecacheModel(MODEL_RL_ROCKET ); + pdec->PrecacheTexture(TEXTURE_RL_BODY ); + pdec->PrecacheTexture(TEXTURE_RL_ROCKET); + pdec->PrecacheTexture(TEXTURE_RL_ROTATINGPART); + } + + if ( ulAvailable&(1<<(WEAPON_GRENADELAUNCHER-1)) ) { + pdec->PrecacheModel(MODEL_GRENADELAUNCHER ); + pdec->PrecacheModel(MODEL_GL_BODY ); + pdec->PrecacheModel(MODEL_GL_MOVINGPART ); + pdec->PrecacheModel(MODEL_GL_GRENADE ); + pdec->PrecacheTexture(TEXTURE_GL_BODY ); + pdec->PrecacheTexture(TEXTURE_GL_MOVINGPART ); + } + +/* + if ( ulAvailable&(1<<(WEAPON_PIPEBOMB-1)) ) { + pdec->PrecacheModel(MODEL_PIPEBOMB_STICK ); + pdec->PrecacheModel(MODEL_PB_BUTTON ); + pdec->PrecacheModel(MODEL_PB_SHIELD ); + pdec->PrecacheModel(MODEL_PB_STICK ); + pdec->PrecacheModel(MODEL_PB_BOMB ); + pdec->PrecacheTexture(TEXTURE_PB_STICK ); + pdec->PrecacheTexture(TEXTURE_PB_BOMB ); + } +*/ + if ( ulAvailable&(1<<(WEAPON_FLAMER-1)) ) { + pdec->PrecacheModel(MODEL_FLAMER ); + pdec->PrecacheModel(MODEL_FL_BODY ); + pdec->PrecacheModel(MODEL_FL_RESERVOIR); + pdec->PrecacheModel(MODEL_FL_FLAME ); + pdec->PrecacheTexture(TEXTURE_FL_BODY ); + pdec->PrecacheTexture(TEXTURE_FL_FLAME); + } + + if ( ulAvailable&(1<<(WEAPON_CHAINSAW-1)) ) { + pdec->PrecacheModel(MODEL_CHAINSAW ); + pdec->PrecacheModel(MODEL_CS_BODY ); + pdec->PrecacheModel(MODEL_CS_BLADE ); + pdec->PrecacheModel(MODEL_CS_TEETH ); + pdec->PrecacheTexture(TEXTURE_CS_BODY ); + pdec->PrecacheTexture(TEXTURE_CS_BLADE ); + pdec->PrecacheTexture(TEXTURE_CS_TEETH ); + } + + if ( ulAvailable&(1<<(WEAPON_LASER-1)) ) { + pdec->PrecacheModel(MODEL_LASER ); + pdec->PrecacheModel(MODEL_LS_BODY ); + pdec->PrecacheModel(MODEL_LS_BARREL ); + pdec->PrecacheTexture(TEXTURE_LS_BODY ); + pdec->PrecacheTexture(TEXTURE_LS_BARREL); + } +/* + if ( ulAvailable&(1<<(WEAPON_GHOSTBUSTER-1)) ) { + pdec->PrecacheModel(MODEL_GHOSTBUSTER ); + pdec->PrecacheModel(MODEL_GB_BODY ); + pdec->PrecacheModel(MODEL_GB_ROTATOR ); + pdec->PrecacheModel(MODEL_GB_EFFECT1 ); + pdec->PrecacheModel(MODEL_GB_EFFECT1FLARE ); + pdec->PrecacheTexture(TEXTURE_GB_ROTATOR ); + pdec->PrecacheTexture(TEXTURE_GB_BODY ); + pdec->PrecacheTexture(TEXTURE_GB_LIGHTNING); + pdec->PrecacheTexture(TEXTURE_GB_FLARE ); + } +*/ + if ( ulAvailable&(1<<(WEAPON_IRONCANNON-1)) /*|| + ulAvailable&(1<<(WEAPON_NUKECANNON-1)) */) { + pdec->PrecacheModel(MODEL_CANNON ); + pdec->PrecacheModel(MODEL_CN_BODY ); +// pdec->PrecacheModel(MODEL_CN_NUKEBOX); +// pdec->PrecacheModel(MODEL_CN_LIGHT); + pdec->PrecacheTexture(TEXTURE_CANNON); + } +} +%} + +class export CPlayerAnimator: CRationalEntity { +name "Player Animator"; +thumbnail ""; +features "CanBePredictable"; + +properties: + 1 CEntityPointer m_penPlayer, // player which owns it + + 5 BOOL m_bReference=FALSE, // player has reference (floor) + 6 FLOAT m_fLastActionTime = 0.0f, // last action time for boring weapon animations + 7 INDEX m_iContent = 0, // content type index + 8 BOOL m_bWaitJumpAnim = FALSE, // wait legs anim (for jump end) + 9 BOOL m_bCrouch = FALSE, // player crouch state + 10 BOOL m_iCrouchDownWait = FALSE, // wait for crouch down + 11 BOOL m_iRiseUpWait = FALSE, // wait for rise up + 12 BOOL m_bChangeWeapon = FALSE, // wait for weapon change + 13 BOOL m_bSwim = FALSE, // player in water + 14 INDEX m_iFlare = FLARE_REMOVE, // 0-none, 1-remove, 2-add + 15 INDEX m_iSecondFlare = FLARE_REMOVE, // 0-none, 1-remove, 2-add + 16 BOOL m_bAttacking = FALSE, // currently firing weapon/swinging knife + 19 FLOAT m_tmAttackingDue = -1.0f, // when firing animation is due + 17 FLOAT m_tmFlareAdded = -1.0f, // for better flare add/remove + 18 BOOL m_bDisableAnimating = FALSE, + +// player soft eyes on Y axis + 20 FLOAT3D m_vLastPlayerPosition = FLOAT3D(0,0,0), // last player position for eyes movement + 21 FLOAT m_fEyesYLastOffset = 0.0f, // eyes offset from player position + 22 FLOAT m_fEyesYOffset = 0.0f, + 23 FLOAT m_fEyesYSpeed = 0.0f, // eyes speed + 27 FLOAT m_fWeaponYLastOffset = 0.0f, // eyes offset from player position + 28 FLOAT m_fWeaponYOffset = 0.0f, + 29 FLOAT m_fWeaponYSpeed = 0.0f, // eyes speed + // recoil pitch +// 24 FLOAT m_fRecoilLastOffset = 0.0f, // eyes offset from player position +// 25 FLOAT m_fRecoilOffset = 0.0f, +// 26 FLOAT m_fRecoilSpeed = 0.0f, // eyes speed + +// player banking when moving + 30 BOOL m_bMoving = FALSE, + 31 FLOAT m_fMoveLastBanking = 0.0f, + 32 FLOAT m_fMoveBanking = 0.0f, + 33 BOOL m_iMovingSide = 0, + 34 BOOL m_bSidestepBankingLeft = FALSE, + 35 BOOL m_bSidestepBankingRight = FALSE, + 36 FLOAT m_fSidestepLastBanking = 0.0f, + 37 FLOAT m_fSidestepBanking = 0.0f, + 38 INDEX m_iWeaponLast = -1, + 39 FLOAT m_fBodyAnimTime = -1.0f, + +{ + CModelObject *pmoModel; +} + +components: + 1 class CLASS_REMINDER "Classes\\Reminder.ecl", +// ************** KNIFE ************** + 20 model MODEL_KNIFE "Models\\Weapons\\Knife\\KnifeItem.mdl", + 22 texture TEXTURE_KNIFE "Models\\Weapons\\Knife\\KnifeItem.tex", + +// ************** COLT ************** + 30 model MODEL_COLT "Models\\Weapons\\Colt\\ColtItem.mdl", + 31 model MODEL_COLTCOCK "Models\\Weapons\\Colt\\ColtCock.mdl", + 32 model MODEL_COLTMAIN "Models\\Weapons\\Colt\\ColtMain.mdl", + 33 model MODEL_COLTBULLETS "Models\\Weapons\\Colt\\ColtBullets.mdl", + 34 texture TEXTURE_COLTBULLETS "Models\\Weapons\\Colt\\ColtBullets.tex", + 35 texture TEXTURE_COLTMAIN "Models\\Weapons\\Colt\\ColtMain.tex", + 36 texture TEXTURE_COLTCOCK "Models\\Weapons\\Colt\\ColtCock.tex", + +// ************** SINGLE SHOTGUN ************ + 40 model MODEL_SINGLESHOTGUN "Models\\Weapons\\SingleShotgun\\SingleShotgunItem.mdl", + 41 model MODEL_SS_SLIDER "Models\\Weapons\\SingleShotgun\\Slider.mdl", + 42 model MODEL_SS_HANDLE "Models\\Weapons\\SingleShotgun\\Handle.mdl", + 43 model MODEL_SS_BARRELS "Models\\Weapons\\SingleShotgun\\Barrels.mdl", + 44 texture TEXTURE_SS_HANDLE "Models\\Weapons\\SingleShotgun\\Handle.tex", + 45 texture TEXTURE_SS_BARRELS "Models\\Weapons\\SingleShotgun\\Barrels.tex", + +// ************** DOUBLE SHOTGUN ************** + 50 model MODEL_DOUBLESHOTGUN "Models\\Weapons\\DoubleShotgun\\DoubleShotgunItem.mdl", + 51 model MODEL_DS_HANDLE "Models\\Weapons\\DoubleShotgun\\Dshotgunhandle.mdl", + 52 model MODEL_DS_BARRELS "Models\\Weapons\\DoubleShotgun\\Dshotgunbarrels.mdl", + 54 model MODEL_DS_SWITCH "Models\\Weapons\\DoubleShotgun\\Switch.mdl", + 56 texture TEXTURE_DS_HANDLE "Models\\Weapons\\DoubleShotgun\\Handle.tex", + 57 texture TEXTURE_DS_BARRELS "Models\\Weapons\\DoubleShotgun\\Barrels.tex", + 58 texture TEXTURE_DS_SWITCH "Models\\Weapons\\DoubleShotgun\\Switch.tex", + +// ************** TOMMYGUN ************** + 70 model MODEL_TOMMYGUN "Models\\Weapons\\TommyGun\\TommyGunItem.mdl", + 71 model MODEL_TG_BODY "Models\\Weapons\\TommyGun\\Body.mdl", + 72 model MODEL_TG_SLIDER "Models\\Weapons\\TommyGun\\Slider.mdl", + 73 texture TEXTURE_TG_BODY "Models\\Weapons\\TommyGun\\Body.tex", + +// ************** MINIGUN ************** + 80 model MODEL_MINIGUN "Models\\Weapons\\MiniGun\\MiniGunItem.mdl", + 81 model MODEL_MG_BARRELS "Models\\Weapons\\MiniGun\\Barrels.mdl", + 82 model MODEL_MG_BODY "Models\\Weapons\\MiniGun\\Body.mdl", + 83 model MODEL_MG_ENGINE "Models\\Weapons\\MiniGun\\Engine.mdl", + 84 texture TEXTURE_MG_BODY "Models\\Weapons\\MiniGun\\Body.tex", + 99 texture TEXTURE_MG_BARRELS "Models\\Weapons\\MiniGun\\Barrels.tex", + +// ************** ROCKET LAUNCHER ************** + 90 model MODEL_ROCKETLAUNCHER "Models\\Weapons\\RocketLauncher\\RocketLauncherItem.mdl", + 91 model MODEL_RL_BODY "Models\\Weapons\\RocketLauncher\\Body.mdl", + 92 texture TEXTURE_RL_BODY "Models\\Weapons\\RocketLauncher\\Body.tex", + 93 model MODEL_RL_ROTATINGPART "Models\\Weapons\\RocketLauncher\\RotatingPart.mdl", + 94 texture TEXTURE_RL_ROTATINGPART "Models\\Weapons\\RocketLauncher\\RotatingPart.tex", + 95 model MODEL_RL_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl", + 96 texture TEXTURE_RL_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex", + +// ************** GRENADE LAUNCHER ************** +100 model MODEL_GRENADELAUNCHER "Models\\Weapons\\GrenadeLauncher\\GrenadeLauncherItem.mdl", +101 model MODEL_GL_BODY "Models\\Weapons\\GrenadeLauncher\\Body.mdl", +102 model MODEL_GL_MOVINGPART "Models\\Weapons\\GrenadeLauncher\\MovingPipe.mdl", +103 model MODEL_GL_GRENADE "Models\\Weapons\\GrenadeLauncher\\GrenadeBack.mdl", +104 texture TEXTURE_GL_BODY "Models\\Weapons\\GrenadeLauncher\\Body.tex", +105 texture TEXTURE_GL_MOVINGPART "Models\\Weapons\\GrenadeLauncher\\MovingPipe.tex", + +// ************** SNIPER ************** +110 model MODEL_SNIPER "ModelsMP\\Weapons\\Sniper\\Sniper.mdl", +111 model MODEL_SNIPER_BODY "ModelsMP\\Weapons\\Sniper\\Body.mdl", +112 texture TEXTURE_SNIPER_BODY "ModelsMP\\Weapons\\Sniper\\Body.tex", + +/* +// ************** PIPEBOMB ************** +110 model MODEL_PIPEBOMB_STICK "Models\\Weapons\\Pipebomb\\StickItem.mdl", +112 model MODEL_PB_BUTTON "Models\\Weapons\\Pipebomb\\Button.mdl", +113 model MODEL_PB_SHIELD "Models\\Weapons\\Pipebomb\\Shield.mdl", +114 model MODEL_PB_STICK "Models\\Weapons\\Pipebomb\\Stick.mdl", +115 model MODEL_PB_BOMB "Models\\Weapons\\Pipebomb\\Bomb.mdl", +116 texture TEXTURE_PB_STICK "Models\\Weapons\\Pipebomb\\Stick.tex", +117 texture TEXTURE_PB_BOMB "Models\\Weapons\\Pipebomb\\Bomb.tex", +*/ + +// ************** FLAMER ************** +130 model MODEL_FLAMER "ModelsMP\\Weapons\\Flamer\\FlamerItem.mdl", +131 model MODEL_FL_BODY "ModelsMP\\Weapons\\Flamer\\Body.mdl", +132 model MODEL_FL_RESERVOIR "ModelsMP\\Weapons\\Flamer\\FuelReservoir.mdl", +133 model MODEL_FL_FLAME "ModelsMP\\Weapons\\Flamer\\Flame.mdl", +134 texture TEXTURE_FL_BODY "ModelsMP\\Weapons\\Flamer\\Body.tex", +135 texture TEXTURE_FL_FLAME "ModelsMP\\Effects\\Flame\\Flame.tex", +136 texture TEXTURE_FL_FUELRESERVOIR "ModelsMP\\Weapons\\Flamer\\FuelReservoir.tex", + +// ************** LASER ************** +140 model MODEL_LASER "Models\\Weapons\\Laser\\LaserItem.mdl", +141 model MODEL_LS_BODY "Models\\Weapons\\Laser\\Body.mdl", +142 model MODEL_LS_BARREL "Models\\Weapons\\Laser\\Barrel.mdl", +143 texture TEXTURE_LS_BODY "Models\\Weapons\\Laser\\Body.tex", +144 texture TEXTURE_LS_BARREL "Models\\Weapons\\Laser\\Barrel.tex", + +// ************** CHAINSAW ************** +150 model MODEL_CHAINSAW "ModelsMP\\Weapons\\Chainsaw\\ChainsawForPlayer.mdl", +151 model MODEL_CS_BODY "ModelsMP\\Weapons\\Chainsaw\\BodyForPlayer.mdl", +152 model MODEL_CS_BLADE "ModelsMP\\Weapons\\Chainsaw\\Blade.mdl", +153 model MODEL_CS_TEETH "ModelsMP\\Weapons\\Chainsaw\\Teeth.mdl", +154 texture TEXTURE_CS_BODY "ModelsMP\\Weapons\\Chainsaw\\Body.tex", +155 texture TEXTURE_CS_BLADE "ModelsMP\\Weapons\\Chainsaw\\Blade.tex", +156 texture TEXTURE_CS_TEETH "ModelsMP\\Weapons\\Chainsaw\\Teeth.tex", + +// ************** GHOSTBUSTER ************** +/* +150 model MODEL_GHOSTBUSTER "Models\\Weapons\\GhostBuster\\GhostBusterItem.mdl", +151 model MODEL_GB_BODY "Models\\Weapons\\GhostBuster\\Body.mdl", +152 model MODEL_GB_ROTATOR "Models\\Weapons\\GhostBuster\\Rotator.mdl", +153 model MODEL_GB_EFFECT1 "Models\\Weapons\\GhostBuster\\Effect01.mdl", +154 model MODEL_GB_EFFECT1FLARE "Models\\Weapons\\GhostBuster\\EffectFlare01.mdl", +155 texture TEXTURE_GB_ROTATOR "Models\\Weapons\\GhostBuster\\Rotator.tex", +156 texture TEXTURE_GB_BODY "Models\\Weapons\\GhostBuster\\Body.tex", +157 texture TEXTURE_GB_LIGHTNING "Models\\Weapons\\GhostBuster\\Lightning.tex", +158 texture TEXTURE_GB_FLARE "Models\\Weapons\\GhostBuster\\EffectFlare.tex", +*/ +// ************** CANNON ************** +170 model MODEL_CANNON "Models\\Weapons\\Cannon\\Cannon.mdl", +171 model MODEL_CN_BODY "Models\\Weapons\\Cannon\\Body.mdl", +173 texture TEXTURE_CANNON "Models\\Weapons\\Cannon\\Body.tex", +//174 model MODEL_CN_NUKEBOX "Models\\Weapons\\Cannon\\NukeBox.mdl", +//175 model MODEL_CN_LIGHT "Models\\Weapons\\Cannon\\Light.mdl", + +// ************** AMON STATUE ************** +180 model MODEL_GOLDAMON "Models\\Ages\\Egypt\\Gods\\Amon\\AmonGold.mdl", +181 texture TEXTURE_GOLDAMON "Models\\Ages\\Egypt\\Gods\\Amon\\AmonGold.tex", + +// ************** REFLECTIONS ************** +200 texture TEX_REFL_BWRIPLES01 "Models\\ReflectionTextures\\BWRiples01.tex", +201 texture TEX_REFL_BWRIPLES02 "Models\\ReflectionTextures\\BWRiples02.tex", +202 texture TEX_REFL_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex", +203 texture TEX_REFL_LIGHTBLUEMETAL01 "Models\\ReflectionTextures\\LightBlueMetal01.tex", +204 texture TEX_REFL_DARKMETAL "Models\\ReflectionTextures\\DarkMetal.tex", +205 texture TEX_REFL_PURPLE01 "Models\\ReflectionTextures\\Purple01.tex", +206 texture TEX_REFL_GOLD01 "Models\\ReflectionTextures\\Gold01.tex", + +// ************** SPECULAR ************** +210 texture TEX_SPEC_WEAK "Models\\SpecularTextures\\Weak.tex", +211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex", +212 texture TEX_SPEC_STRONG "Models\\SpecularTextures\\Strong.tex", + +// ************** FLARES ************** +250 model MODEL_FLARE02 "Models\\Effects\\Weapons\\Flare02\\Flare.mdl", +251 texture TEXTURE_FLARE02 "Models\\Effects\\Weapons\\Flare02\\Flare.tex", + + +functions: + + /* Read from stream. */ + void Read_t( CTStream *istr) // throw char * + { + CRationalEntity::Read_t(istr); + } + + void Precache(void) + { + INDEX iAvailableWeapons = ((CPlayerWeapons&)*(((CPlayer&)*m_penPlayer).m_penWeapons)).m_iAvailableWeapons; + CPlayerAnimator_Precache(iAvailableWeapons); + } + + CPlayer *GetPlayer(void) + { + return ((CPlayer*)&*m_penPlayer); + } + CModelObject *GetBody(void) + { + CAttachmentModelObject *pamoBody = GetPlayer()->GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO); + if (pamoBody==NULL) { + return NULL; + } + return &pamoBody->amo_moModelObject; + } + CModelObject *GetBodyRen(void) + { + CAttachmentModelObject *pamoBody = GetPlayer()->m_moRender.GetAttachmentModel(PLAYER_ATTACHMENT_TORSO); + if (pamoBody==NULL) { + return NULL; + } + return &pamoBody->amo_moModelObject; + } + + // Set components + void SetComponents(CModelObject *mo, ULONG ulIDModel, ULONG ulIDTexture, + ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture) { + // model data + mo->SetData(GetModelDataForComponent(ulIDModel)); + // texture data + mo->mo_toTexture.SetData(GetTextureDataForComponent(ulIDTexture)); + // reflection texture data + if (ulIDReflectionTexture>0) { + mo->mo_toReflection.SetData(GetTextureDataForComponent(ulIDReflectionTexture)); + } else { + mo->mo_toReflection.SetData(NULL); + } + // specular texture data + if (ulIDSpecularTexture>0) { + mo->mo_toSpecular.SetData(GetTextureDataForComponent(ulIDSpecularTexture)); + } else { + mo->mo_toSpecular.SetData(NULL); + } + // bump texture data + if (ulIDBumpTexture>0) { + mo->mo_toBump.SetData(GetTextureDataForComponent(ulIDBumpTexture)); + } else { + mo->mo_toBump.SetData(NULL); + } + ModelChangeNotify(); + }; + + // Add attachment model + void AddAttachmentModel(CModelObject *mo, INDEX iAttachment, ULONG ulIDModel, ULONG ulIDTexture, + ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture) { + SetComponents(&mo->AddAttachmentModel(iAttachment)->amo_moModelObject, ulIDModel, + ulIDTexture, ulIDReflectionTexture, ulIDSpecularTexture, ulIDBumpTexture); + }; + + // Add weapon attachment + void AddWeaponAttachment(INDEX iAttachment, ULONG ulIDModel, ULONG ulIDTexture, + ULONG ulIDReflectionTexture, ULONG ulIDSpecularTexture, ULONG ulIDBumpTexture) { + AddAttachmentModel(pmoModel, iAttachment, ulIDModel, ulIDTexture, + ulIDReflectionTexture, ulIDSpecularTexture, ulIDBumpTexture); + }; + + // set active attachment (model) + void SetAttachment(INDEX iAttachment) { + pmoModel = &(pmoModel->GetAttachmentModel(iAttachment)->amo_moModelObject); + }; + + // synchronize any possible weapon attachment(s) with default appearance + void SyncWeapon(void) + { + CModelObject *pmoBodyRen = GetBodyRen(); + CModelObject *pmoBodyDef = GetBody(); + // for each weapon attachment + for (INDEX iWeapon = BODY_ATTACHMENT_COLT_RIGHT; iWeapon<=BODY_ATTACHMENT_ITEM; iWeapon++) { + CAttachmentModelObject *pamoWeapDef = pmoBodyDef->GetAttachmentModel(iWeapon); + CAttachmentModelObject *pamoWeapRen = pmoBodyRen->GetAttachmentModel(iWeapon); + // if it doesn't exist in either + if (pamoWeapRen==NULL && pamoWeapDef==NULL) { + // just skip it + NOTHING; + + // if exists only in rendering model + } else if (pamoWeapRen!=NULL && pamoWeapDef==NULL) { + // remove it from rendering + delete pamoWeapRen; + + // if exists only in default + } else if (pamoWeapRen==NULL && pamoWeapDef!=NULL) { + // add it to rendering + pamoWeapRen = pmoBodyRen->AddAttachmentModel(iWeapon); + pamoWeapRen->amo_plRelative = pamoWeapDef->amo_plRelative; + pamoWeapRen->amo_moModelObject.Copy(pamoWeapDef->amo_moModelObject); + + // if exists in both + } else { + // just synchronize + pamoWeapRen->amo_plRelative = pamoWeapDef->amo_plRelative; + pamoWeapRen->amo_moModelObject.Synchronize(pamoWeapDef->amo_moModelObject); + } + } + } + + // set weapon + void SetWeapon(void) { + INDEX iWeapon = ((CPlayerWeapons&)*(((CPlayer&)*m_penPlayer).m_penWeapons)).m_iCurrentWeapon; + m_iWeaponLast = iWeapon; + CPlayer &pl = (CPlayer&)*m_penPlayer; + pmoModel = &(pl.GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject); + switch (iWeapon) { + // *********** KNIFE *********** + case WEAPON_KNIFE: + AddWeaponAttachment(BODY_ATTACHMENT_KNIFE, MODEL_KNIFE, + TEXTURE_KNIFE, TEX_REFL_BWRIPLES02, TEX_SPEC_WEAK, 0); + break; + + // *********** DOUBLE COLT *********** + case WEAPON_DOUBLECOLT: + AddWeaponAttachment(BODY_ATTACHMENT_COLT_LEFT, MODEL_COLT, TEXTURE_COLTMAIN, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_COLT_LEFT); + AddWeaponAttachment(COLTITEM_ATTACHMENT_BULLETS, MODEL_COLTBULLETS, + TEXTURE_COLTBULLETS, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(COLTITEM_ATTACHMENT_COCK, MODEL_COLTCOCK, + TEXTURE_COLTCOCK, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(COLTITEM_ATTACHMENT_BODY, MODEL_COLTMAIN, + TEXTURE_COLTMAIN, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + SetAttachment(COLTITEM_ATTACHMENT_BODY); + AddWeaponAttachment(COLTMAIN_ATTACHMENT_FLARE, MODEL_FLARE02, TEXTURE_FLARE02, 0, 0, 0); + // reset to player body + pmoModel = &(pl.GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject); + + // *********** COLT *********** + case WEAPON_COLT: + AddWeaponAttachment(BODY_ATTACHMENT_COLT_RIGHT, MODEL_COLT, TEXTURE_COLTMAIN, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_COLT_RIGHT); + AddWeaponAttachment(COLTITEM_ATTACHMENT_BULLETS, MODEL_COLTBULLETS, + TEXTURE_COLTBULLETS, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(COLTITEM_ATTACHMENT_COCK, MODEL_COLTCOCK, + TEXTURE_COLTCOCK, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(COLTITEM_ATTACHMENT_BODY, MODEL_COLTMAIN, + TEXTURE_COLTMAIN, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + SetAttachment(COLTITEM_ATTACHMENT_BODY); + AddWeaponAttachment(COLTMAIN_ATTACHMENT_FLARE, MODEL_FLARE02, TEXTURE_FLARE02, 0, 0, 0); + break; + + // *********** SINGLE SHOTGUN *********** + case WEAPON_SINGLESHOTGUN: + AddWeaponAttachment(BODY_ATTACHMENT_SINGLE_SHOTGUN, MODEL_SINGLESHOTGUN, TEXTURE_SS_HANDLE, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_SINGLE_SHOTGUN); + AddWeaponAttachment(SINGLESHOTGUNITEM_ATTACHMENT_BARRELS, MODEL_SS_BARRELS, + TEXTURE_SS_BARRELS, TEX_REFL_DARKMETAL, TEX_SPEC_WEAK, 0); + AddWeaponAttachment(SINGLESHOTGUNITEM_ATTACHMENT_HANDLE, MODEL_SS_HANDLE, + TEXTURE_SS_HANDLE, TEX_REFL_DARKMETAL, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(SINGLESHOTGUNITEM_ATTACHMENT_SLIDER, MODEL_SS_SLIDER, + TEXTURE_SS_BARRELS, TEX_REFL_DARKMETAL, TEX_SPEC_MEDIUM, 0); + SetAttachment(SINGLESHOTGUNITEM_ATTACHMENT_BARRELS); + AddWeaponAttachment(BARRELS_ATTACHMENT_FLARE, MODEL_FLARE02, TEXTURE_FLARE02, 0, 0, 0); + break; + + // *********** DOUBLE SHOTGUN *********** + case WEAPON_DOUBLESHOTGUN: + AddWeaponAttachment(BODY_ATTACHMENT_DOUBLE_SHOTGUN, MODEL_DOUBLESHOTGUN, TEXTURE_DS_HANDLE, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_DOUBLE_SHOTGUN); + AddWeaponAttachment(DOUBLESHOTGUNITEM_ATTACHMENT_BARRELS, MODEL_DS_BARRELS, + TEXTURE_DS_BARRELS, TEX_REFL_BWRIPLES01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(DOUBLESHOTGUNITEM_ATTACHMENT_HANDLE, MODEL_DS_HANDLE, + TEXTURE_DS_HANDLE, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(DOUBLESHOTGUNITEM_ATTACHMENT_SWITCH, MODEL_DS_SWITCH, + TEXTURE_DS_SWITCH, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + SetAttachment(DOUBLESHOTGUNITEM_ATTACHMENT_BARRELS); + AddWeaponAttachment(DSHOTGUNBARRELS_ATTACHMENT_FLARE, MODEL_FLARE02, TEXTURE_FLARE02, 0, 0, 0); + break; + + + // *********** TOMMYGUN *********** + case WEAPON_TOMMYGUN: + AddWeaponAttachment(BODY_ATTACHMENT_TOMMYGUN, MODEL_TOMMYGUN, TEXTURE_TG_BODY, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_TOMMYGUN); + AddWeaponAttachment(TOMMYGUNITEM_ATTACHMENT_BODY, MODEL_TG_BODY, TEXTURE_TG_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(TOMMYGUNITEM_ATTACHMENT_SLIDER, MODEL_TG_SLIDER, TEXTURE_TG_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + SetAttachment(TOMMYGUNITEM_ATTACHMENT_BODY); + AddWeaponAttachment(BODY_ATTACHMENT_FLARE, MODEL_FLARE02, TEXTURE_FLARE02, 0, 0, 0); + break; + + // *********** SNIPER *********** + case WEAPON_SNIPER: + AddWeaponAttachment(BODY_ATTACHMENT_FLAMER, MODEL_SNIPER, TEXTURE_SNIPER_BODY, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_FLAMER); + AddWeaponAttachment(SNIPERITEM_ATTACHMENT_BODY, MODEL_SNIPER_BODY, TEXTURE_SNIPER_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + SetAttachment(SNIPERITEM_ATTACHMENT_BODY); + AddWeaponAttachment(BODY_ATTACHMENT_FLARE, MODEL_FLARE02, TEXTURE_FLARE02, 0, 0, 0); + break; + + // *********** MINIGUN *********** + case WEAPON_MINIGUN: + AddWeaponAttachment(BODY_ATTACHMENT_MINIGUN, MODEL_MINIGUN, TEXTURE_MG_BODY, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_MINIGUN); + AddWeaponAttachment(MINIGUNITEM_ATTACHMENT_BARRELS, MODEL_MG_BARRELS, TEXTURE_MG_BARRELS, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(MINIGUNITEM_ATTACHMENT_BODY, MODEL_MG_BODY, TEXTURE_MG_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(MINIGUNITEM_ATTACHMENT_ENGINE, MODEL_MG_ENGINE, TEXTURE_MG_BARRELS, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + SetAttachment(MINIGUNITEM_ATTACHMENT_BODY); + AddWeaponAttachment(BODY_ATTACHMENT_FLARE, MODEL_FLARE02, TEXTURE_FLARE02, 0, 0, 0); + break; + + // *********** ROCKET LAUNCHER *********** + case WEAPON_ROCKETLAUNCHER: + AddWeaponAttachment(BODY_ATTACHMENT_ROCKET_LAUNCHER, MODEL_ROCKETLAUNCHER, TEXTURE_RL_BODY, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_ROCKET_LAUNCHER); + AddWeaponAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_BODY, MODEL_RL_BODY, TEXTURE_RL_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_ROTATINGPART, MODEL_RL_ROTATINGPART, TEXTURE_RL_ROTATINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET1, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET2, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET3, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET4, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + break; + + // *********** GRENADE LAUNCHER *********** + case WEAPON_GRENADELAUNCHER: + AddWeaponAttachment(BODY_ATTACHMENT_GRENADE_LAUNCHER, MODEL_GRENADELAUNCHER, TEXTURE_GL_BODY, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_GRENADE_LAUNCHER); + AddWeaponAttachment(GRENADELAUNCHERITEM_ATTACHMENT_BODY, MODEL_GL_BODY, TEXTURE_GL_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(GRENADELAUNCHERITEM_ATTACHMENT_MOVING_PART, MODEL_GL_MOVINGPART, TEXTURE_GL_MOVINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(GRENADELAUNCHERITEM_ATTACHMENT_GRENADE, MODEL_GL_GRENADE, TEXTURE_GL_MOVINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + break; + +/* // *********** PIPEBOMB *********** + case WEAPON_PIPEBOMB: + AddWeaponAttachment(BODY_ATTACHMENT_COLT_RIGHT, MODEL_PIPEBOMB_STICK, TEXTURE_PB_STICK, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_COLT_RIGHT); + AddWeaponAttachment(STICKITEM_ATTACHMENT_STICK, MODEL_PB_STICK, TEXTURE_PB_STICK, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(STICKITEM_ATTACHMENT_SHIELD, MODEL_PB_SHIELD, TEXTURE_PB_STICK, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(STICKITEM_ATTACHMENT_BUTTON, MODEL_PB_BUTTON, TEXTURE_PB_STICK, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + // reset to player body + pmoModel = &(pl.GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject); + AddWeaponAttachment(BODY_ATTACHMENT_COLT_LEFT, MODEL_PB_BOMB, TEXTURE_PB_BOMB, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + break; +*/ + // *********** FLAMER *********** + case WEAPON_FLAMER: + AddWeaponAttachment(BODY_ATTACHMENT_FLAMER, MODEL_FLAMER, TEXTURE_FL_BODY, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_FLAMER); + AddWeaponAttachment(FLAMERITEM_ATTACHMENT_BODY, MODEL_FL_BODY, TEXTURE_FL_BODY, TEX_REFL_BWRIPLES02, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(FLAMERITEM_ATTACHMENT_FUEL, MODEL_FL_RESERVOIR, TEXTURE_FL_FUELRESERVOIR, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(FLAMERITEM_ATTACHMENT_FLAME, MODEL_FL_FLAME, TEXTURE_FL_FLAME, 0, 0, 0); + break; + + // *********** CHAINSAW *********** + case WEAPON_CHAINSAW: { + AddWeaponAttachment(BODY_ATTACHMENT_MINIGUN, MODEL_CHAINSAW, TEXTURE_CS_BODY, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_MINIGUN); + AddWeaponAttachment(CHAINSAWFORPLAYER_ATTACHMENT_CHAINSAW, MODEL_CS_BODY, TEXTURE_CS_BODY, TEX_REFL_BWRIPLES02, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(CHAINSAWFORPLAYER_ATTACHMENT_BLADE, MODEL_CS_BLADE, TEXTURE_CS_BLADE, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + CModelObject *pmo = pmoModel; + SetAttachment(CHAINSAWFORPLAYER_ATTACHMENT_BLADE); + AddWeaponAttachment(BLADEFORPLAYER_ATTACHMENT_TEETH, MODEL_CS_TEETH, TEXTURE_CS_TEETH, 0, 0, 0); + break; } + + // *********** LASER *********** + case WEAPON_LASER: + AddWeaponAttachment(BODY_ATTACHMENT_LASER, MODEL_LASER, TEXTURE_LS_BODY, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_LASER); + AddWeaponAttachment(LASERITEM_ATTACHMENT_BODY, MODEL_LS_BODY, TEXTURE_LS_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(LASERITEM_ATTACHMENT_LEFTUP, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(LASERITEM_ATTACHMENT_LEFTDOWN, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(LASERITEM_ATTACHMENT_RIGHTUP, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(LASERITEM_ATTACHMENT_RIGHTDOWN, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + break; + +/* + // *********** GHOSTBUSTER *********** + case WEAPON_GHOSTBUSTER: { + AddWeaponAttachment(BODY_ATTACHMENT_LASER, MODEL_GHOSTBUSTER, TEXTURE_GB_BODY, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_LASER); + AddWeaponAttachment(GHOSTBUSTERITEM_ATTACHMENT_BODY, MODEL_GB_BODY, TEXTURE_GB_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(GHOSTBUSTERITEM_ATTACHMENT_ROTATOR, MODEL_GB_ROTATOR, TEXTURE_GB_ROTATOR, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddWeaponAttachment(GHOSTBUSTERITEM_ATTACHMENT_EFFECT01, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0); + AddWeaponAttachment(GHOSTBUSTERITEM_ATTACHMENT_EFFECT02, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0); + AddWeaponAttachment(GHOSTBUSTERITEM_ATTACHMENT_EFFECT03, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0); + AddWeaponAttachment(GHOSTBUSTERITEM_ATTACHMENT_EFFECT04, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0); + CModelObject *pmo = pmoModel; + SetAttachment(GHOSTBUSTERITEM_ATTACHMENT_EFFECT01); + AddWeaponAttachment(EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0); + pmoModel = pmo; + SetAttachment(GHOSTBUSTERITEM_ATTACHMENT_EFFECT02); + AddWeaponAttachment(EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0); + pmoModel = pmo; + SetAttachment(GHOSTBUSTERITEM_ATTACHMENT_EFFECT03); + AddWeaponAttachment(EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0); + pmoModel = pmo; + SetAttachment(GHOSTBUSTERITEM_ATTACHMENT_EFFECT04); + AddWeaponAttachment(EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0); + break; } +*/ + // *********** CANNON *********** + case WEAPON_IRONCANNON: +// case WEAPON_NUKECANNON: + AddWeaponAttachment(BODY_ATTACHMENT_CANNON, MODEL_CANNON, TEXTURE_CANNON, 0, 0, 0); + SetAttachment(BODY_ATTACHMENT_CANNON); + AddWeaponAttachment(CANNON_ATTACHMENT_BODY, MODEL_CN_BODY, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); +// AddWeaponAttachment(CANNON_ATTACHMENT_NUKEBOX, MODEL_CN_NUKEBOX, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); +// AddWeaponAttachment(CANNON_ATTACHMENT_LIGHT, MODEL_CN_LIGHT, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + break; + default: + ASSERTALWAYS("Unknown weapon."); + } + // sync apperances + SyncWeapon(); + }; + + // set item + void SetItem(CModelObject *pmo) { + pmoModel = &(GetPlayer()->GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject); + AddWeaponAttachment(BODY_ATTACHMENT_ITEM, MODEL_GOLDAMON, + TEXTURE_GOLDAMON, TEX_REFL_GOLD01, TEX_SPEC_MEDIUM, 0); + if (pmo!=NULL) { + CPlayer &pl = (CPlayer&)*m_penPlayer; + CAttachmentModelObject *pamo = pl.GetModelObject()->GetAttachmentModelList(PLAYER_ATTACHMENT_TORSO, BODY_ATTACHMENT_ITEM, -1); + pmoModel = &(pamo->amo_moModelObject); + pmoModel->Copy(*pmo); + pmoModel->StretchModel(FLOAT3D(1,1,1)); + pamo->amo_plRelative = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + } + // sync apperances + SyncWeapon(); + } + + // set player body animation + void SetBodyAnimation(INDEX iAnimation, ULONG ulFlags) { + // on weapon change skip anim + if (m_bChangeWeapon) { return; } + // on firing skip anim + if (m_bAttacking) { return; } + // play body anim + CPlayer &pl = (CPlayer&)*m_penPlayer; + CModelObject &moBody = pl.GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + moBody.PlayAnim(iAnimation, ulFlags); + m_fBodyAnimTime = moBody.GetAnimLength(iAnimation); // anim length + }; + + +/************************************************************ + * INITIALIZE * + ************************************************************/ + void Initialize(void) { + // set internal properties + m_bReference = TRUE; + m_bWaitJumpAnim = FALSE; + m_bCrouch = FALSE; + m_iCrouchDownWait = 0; + m_iRiseUpWait = 0; + m_bChangeWeapon = FALSE; + m_bSwim = FALSE; + m_bAttacking = FALSE; + + // clear eyes offsets + m_fEyesYLastOffset = 0.0f; + m_fEyesYOffset = 0.0f; + m_fEyesYSpeed = 0.0f; + m_fWeaponYLastOffset = 0.0f; + m_fWeaponYOffset = 0.0f; + m_fWeaponYSpeed = 0.0f; +// m_fRecoilLastOffset = 0.0f; +// m_fRecoilOffset = 0.0f; +// m_fRecoilSpeed = 0.0f; + + // clear moving banking + m_bMoving = FALSE; + m_fMoveLastBanking = 0.0f; + m_fMoveBanking = 0.0f; + m_iMovingSide = 0; + m_bSidestepBankingLeft = FALSE; + m_bSidestepBankingRight = FALSE; + m_fSidestepLastBanking = 0.0f; + m_fSidestepBanking = 0.0f; + + // weapon + SetWeapon(); + SetBodyAnimation(BODY_ANIM_COLT_STAND, AOF_LOOPING|AOF_NORESTART); + }; + + +/************************************************************ + * ANIMATE BANKING AND SOFT EYES * + ************************************************************/ + // store for lerping + void StoreLast(void) { + CPlayer &pl = (CPlayer&)*m_penPlayer; + m_vLastPlayerPosition = pl.GetPlacement().pl_PositionVector; // store last player position + m_fEyesYLastOffset = m_fEyesYOffset; // store last eyes offset + m_fWeaponYLastOffset = m_fWeaponYOffset; +// m_fRecoilLastOffset = m_fRecoilOffset; + m_fMoveLastBanking = m_fMoveBanking; // store last banking for lerping + m_fSidestepLastBanking = m_fSidestepBanking; + }; + + // animate banking + void AnimateBanking(void) { + // moving -> change banking + if (m_bMoving) { + // move banking left + if (m_iMovingSide == 0) { + m_fMoveBanking += 0.35f; + if (m_fMoveBanking > 1.0f) { + m_fMoveBanking = 1.0f; + m_iMovingSide = 1; + } + // move banking right + } else { + m_fMoveBanking -= 0.35f; + if (m_fMoveBanking < -1.0f) { + m_fMoveBanking = -1.0f; + m_iMovingSide = 0; + } + } + const FLOAT fBankingSpeed = 0.4f; + + // sidestep banking left + if (m_bSidestepBankingLeft) { + m_fSidestepBanking += fBankingSpeed; + if (m_fSidestepBanking > 1.0f) { m_fSidestepBanking = 1.0f; } + } + // sidestep banking right + if (m_bSidestepBankingRight) { + m_fSidestepBanking -= fBankingSpeed; + if (m_fSidestepBanking < -1.0f) { m_fSidestepBanking = -1.0f; } + } + + // restore banking + } else { + // move banking + if (m_fMoveBanking > 0.0f) { + m_fMoveBanking -= 0.1f; + if (m_fMoveBanking < 0.0f) { m_fMoveBanking = 0.0f; } + } else if (m_fMoveBanking < 0.0f) { + m_fMoveBanking += 0.1f; + if (m_fMoveBanking > 0.0f) { m_fMoveBanking = 0.0f; } + } + // sidestep banking + if (m_fSidestepBanking > 0.0f) { + m_fSidestepBanking -= 0.4f; + if (m_fSidestepBanking < 0.0f) { m_fSidestepBanking = 0.0f; } + } else if (m_fSidestepBanking < 0.0f) { + m_fSidestepBanking += 0.4f; + if (m_fSidestepBanking > 0.0f) { m_fSidestepBanking = 0.0f; } + } + } + + if (GetPlayer()->GetSettings()->ps_ulFlags&PSF_NOBOBBING) { + m_fSidestepBanking = m_fMoveBanking = 0.0f; + } + }; + + // animate soft eyes + void AnimateSoftEyes(void) { + CPlayer &pl = (CPlayer&)*m_penPlayer; + // find eyes offset and speed (differential formula realized in numerical mathematics) + FLOAT fRelY = (pl.GetPlacement().pl_PositionVector-m_vLastPlayerPosition) % + FLOAT3D(pl.en_mRotation(1, 2), pl.en_mRotation(2, 2), pl.en_mRotation(3, 2)); + + // if just jumped + if (pl.en_tmJumped>_pTimer->CurrentTick()-0.5f) { + fRelY = ClampUp(fRelY, 0.0f); + } + m_fEyesYOffset -= fRelY; + m_fWeaponYOffset -= ClampUp(fRelY, 0.0f); + + plr_fViewDampFactor = Clamp(plr_fViewDampFactor ,0.0f,1.0f); + plr_fViewDampLimitGroundUp = Clamp(plr_fViewDampLimitGroundUp ,0.0f,2.0f); + plr_fViewDampLimitGroundDn = Clamp(plr_fViewDampLimitGroundDn ,0.0f,2.0f); + plr_fViewDampLimitWater = Clamp(plr_fViewDampLimitWater ,0.0f,2.0f); + + m_fEyesYSpeed = (m_fEyesYSpeed - m_fEyesYOffset*plr_fViewDampFactor) * (1.0f-plr_fViewDampFactor); + m_fEyesYOffset += m_fEyesYSpeed; + + m_fWeaponYSpeed = (m_fWeaponYSpeed - m_fWeaponYOffset*plr_fViewDampFactor) * (1.0f-plr_fViewDampFactor); + m_fWeaponYOffset += m_fWeaponYSpeed; + + if (m_bSwim) { + m_fEyesYOffset = Clamp(m_fEyesYOffset, -plr_fViewDampLimitWater, +plr_fViewDampLimitWater); + m_fWeaponYOffset = Clamp(m_fWeaponYOffset, -plr_fViewDampLimitWater, +plr_fViewDampLimitWater); + } else { + m_fEyesYOffset = Clamp(m_fEyesYOffset, -plr_fViewDampLimitGroundDn, +plr_fViewDampLimitGroundUp); + m_fWeaponYOffset = Clamp(m_fWeaponYOffset, -plr_fViewDampLimitGroundDn, +plr_fViewDampLimitGroundUp); + } + }; + + /* + // animate view pitch (for recoil) + void AnimateRecoilPitch(void) + { + CPlayer &pl = (CPlayer&)*m_penPlayer; + INDEX iWeapon = ((CPlayerWeapons&)*pl.m_penWeapons).m_iCurrentWeapon; + + wpn_fRecoilDampUp[iWeapon] = Clamp(wpn_fRecoilDampUp[iWeapon],0.0f,1.0f); + wpn_fRecoilDampDn[iWeapon] = Clamp(wpn_fRecoilDampDn[iWeapon],0.0f,1.0f); + + FLOAT fDamp; + if (m_fRecoilSpeed>0) { + fDamp = wpn_fRecoilDampUp[iWeapon]; + } else { + fDamp = wpn_fRecoilDampDn[iWeapon]; + } + m_fRecoilSpeed = (m_fRecoilSpeed - m_fRecoilOffset*fDamp)* (1.0f-fDamp); + + m_fRecoilOffset += m_fRecoilSpeed; + + if (m_fRecoilOffset<0.0f) { + m_fRecoilOffset = 0.0f; + } + if (m_fRecoilOffset>wpn_fRecoilLimit[iWeapon]) { + m_fRecoilOffset = wpn_fRecoilLimit[iWeapon]; + m_fRecoilSpeed = 0.0f; + } + }; + */ + // change view + void ChangeView(CPlacement3D &pl) { + TIME tmNow = _pTimer->GetLerpedCurrentTick(); + + if (!(GetPlayer()->GetSettings()->ps_ulFlags&PSF_NOBOBBING)) { + // banking + FLOAT fBanking = Lerp(m_fMoveLastBanking, m_fMoveBanking, _pTimer->GetLerpFactor()); + fBanking = fBanking * fBanking * Sgn(fBanking) * 0.25f; + fBanking += Lerp(m_fSidestepLastBanking, m_fSidestepBanking, _pTimer->GetLerpFactor()); + fBanking = Clamp(fBanking, -5.0f, 5.0f); + pl.pl_OrientationAngle(3) += fBanking; + } + +/* + // recoil pitch + INDEX iWeapon = ((CPlayerWeapons&)*((CPlayer&)*m_penPlayer).m_penWeapons).m_iCurrentWeapon; + FLOAT fRecoil = Lerp(m_fRecoilLastOffset, m_fRecoilOffset, _pTimer->GetLerpFactor()); + FLOAT fRecoilP = wpn_fRecoilFactorP[iWeapon]*fRecoil; + pl.pl_OrientationAngle(2) += fRecoilP; + // adjust recoil pitch handle + FLOAT fRecoilH = wpn_fRecoilOffset[iWeapon]; + FLOAT fDY = fRecoilH*(1.0f-Cos(fRecoilP)); + FLOAT fDZ = fRecoilH*Sin(fRecoilP); + pl.pl_PositionVector(2)-=fDY; + pl.pl_PositionVector(3)+=fDZ+wpn_fRecoilFactorZ[iWeapon]*fRecoil; + */ + + // swimming + if (m_bSwim) { + pl.pl_OrientationAngle(1) += sin(tmNow*0.9)*2.0f; + pl.pl_OrientationAngle(2) += sin(tmNow*1.7)*2.0f; + pl.pl_OrientationAngle(3) += sin(tmNow*2.5)*2.0f; + } + // eyes up/down for jumping and breathing + FLOAT fEyesOffsetY = Lerp(m_fEyesYLastOffset, m_fEyesYOffset, _pTimer->GetLerpFactor()); + fEyesOffsetY+= sin(tmNow*1.5)*0.05f * plr_fBreathingStrength; + fEyesOffsetY = Clamp(fEyesOffsetY, -1.0f, 1.0f); + pl.pl_PositionVector(2) += fEyesOffsetY; + } + + + +/************************************************************ + * ANIMATE PLAYER * + ************************************************************/ + // body and head animation + void BodyAndHeadOrientation(CPlacement3D &plView) { + CPlayer &pl = (CPlayer&)*m_penPlayer; + CAttachmentModelObject *pamoBody = pl.GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO); + ANGLE3D a = plView.pl_OrientationAngle; + if (!(pl.GetFlags()&ENF_ALIVE)) { + a = ANGLE3D(0,0,0); + } + pamoBody->amo_plRelative.pl_OrientationAngle = a; + pamoBody->amo_plRelative.pl_OrientationAngle(3) *= 4.0f; + + CAttachmentModelObject *pamoHead = (pamoBody->amo_moModelObject).GetAttachmentModel(BODY_ATTACHMENT_HEAD); + pamoHead->amo_plRelative.pl_OrientationAngle = a; + pamoHead->amo_plRelative.pl_OrientationAngle(1) = 0.0f; + pamoHead->amo_plRelative.pl_OrientationAngle(2) = 0.0f; + pamoHead->amo_plRelative.pl_OrientationAngle(3) *= 4.0f; + + // forbid players from cheating by kissing their @$$ + const FLOAT fMaxBanking = 5.0f; + pamoBody->amo_plRelative.pl_OrientationAngle(3) = Clamp(pamoBody->amo_plRelative.pl_OrientationAngle(3), -fMaxBanking, fMaxBanking); + pamoHead->amo_plRelative.pl_OrientationAngle(3) = Clamp(pamoHead->amo_plRelative.pl_OrientationAngle(3), -fMaxBanking, fMaxBanking); + }; + + // animate player + void AnimatePlayer(void) { + if (m_bDisableAnimating) { + return; + } + CPlayer &pl = (CPlayer&)*m_penPlayer; + + FLOAT3D vDesiredTranslation = pl.en_vDesiredTranslationRelative; + FLOAT3D vCurrentTranslation = pl.en_vCurrentTranslationAbsolute * !pl.en_mRotation; + ANGLE3D aDesiredRotation = pl.en_aDesiredRotationRelative; + ANGLE3D aCurrentRotation = pl.en_aCurrentRotationAbsolute; + + // if player is moving + if (vDesiredTranslation.ManhattanNorm()>0.01f + ||aDesiredRotation.ManhattanNorm()>0.01f) { + // prevent idle weapon animations + m_fLastActionTime = _pTimer->CurrentTick(); + } + + // swimming + if (m_bSwim) { + if (vDesiredTranslation.Length()>1.0f && vCurrentTranslation.Length()>1.0f) { + pl.StartModelAnim(PLAYER_ANIM_SWIM, AOF_LOOPING|AOF_NORESTART); + } else { + pl.StartModelAnim(PLAYER_ANIM_SWIMIDLE, AOF_LOOPING|AOF_NORESTART); + } + BodyStillAnimation(); + + // stand + } else { + // has reference (floor) + if (m_bReference) { + // jump + if (pl.en_tmJumped+_pTimer->TickQuantum>=_pTimer->CurrentTick() && + pl.en_tmJumped<=_pTimer->CurrentTick()) { + m_bReference = FALSE; + pl.StartModelAnim(PLAYER_ANIM_JUMPSTART, AOF_NORESTART); + BodyStillAnimation(); + m_fLastActionTime = _pTimer->CurrentTick(); + + // not in jump anim and in stand mode change + } else if (!m_bWaitJumpAnim && m_iCrouchDownWait==0 && m_iRiseUpWait==0) { + // standing + if (!m_bCrouch) { + // running anim + if (vDesiredTranslation.Length()>5.0f && vCurrentTranslation.Length()>5.0f) { + if (vCurrentTranslation(3)<0) { + pl.StartModelAnim(PLAYER_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); + } else { + pl.StartModelAnim(PLAYER_ANIM_BACKPEDALRUN, AOF_LOOPING|AOF_NORESTART); + } + BodyStillAnimation(); + m_fLastActionTime = _pTimer->CurrentTick(); + // walking anim + } else if (vDesiredTranslation.Length()>2.0f && vCurrentTranslation.Length()>2.0f) { + if (vCurrentTranslation(3)<0) { + pl.StartModelAnim(PLAYER_ANIM_NORMALWALK, AOF_LOOPING|AOF_NORESTART); + } else { + pl.StartModelAnim(PLAYER_ANIM_BACKPEDAL, AOF_LOOPING|AOF_NORESTART); + } + BodyStillAnimation(); + m_fLastActionTime = _pTimer->CurrentTick(); + // left rotation anim + } else if (aDesiredRotation(1)>0.5f) { + pl.StartModelAnim(PLAYER_ANIM_TURNLEFT, AOF_LOOPING|AOF_NORESTART); + BodyStillAnimation(); + m_fLastActionTime = _pTimer->CurrentTick(); + // right rotation anim + } else if (aDesiredRotation(1)<-0.5f) { + pl.StartModelAnim(PLAYER_ANIM_TURNRIGHT, AOF_LOOPING|AOF_NORESTART); + BodyStillAnimation(); + m_fLastActionTime = _pTimer->CurrentTick(); + // standing anim + } else { + pl.StartModelAnim(PLAYER_ANIM_STAND, AOF_LOOPING|AOF_NORESTART); + BodyStillAnimation(); + } + // crouch + } else { + // walking anim + if (vDesiredTranslation.Length()>2.0f && vCurrentTranslation.Length()>2.0f) { + if (vCurrentTranslation(3)<0) { + pl.StartModelAnim(PLAYER_ANIM_CROUCH_WALK, AOF_LOOPING|AOF_NORESTART); + } else { + pl.StartModelAnim(PLAYER_ANIM_CROUCH_WALKBACK, AOF_LOOPING|AOF_NORESTART); + } + BodyStillAnimation(); + m_fLastActionTime = _pTimer->CurrentTick(); + // left rotation anim + } else if (aDesiredRotation(1)>0.5f) { + pl.StartModelAnim(PLAYER_ANIM_CROUCH_TURNLEFT, AOF_LOOPING|AOF_NORESTART); + BodyStillAnimation(); + m_fLastActionTime = _pTimer->CurrentTick(); + // right rotation anim + } else if (aDesiredRotation(1)<-0.5f) { + pl.StartModelAnim(PLAYER_ANIM_CROUCH_TURNRIGHT, AOF_LOOPING|AOF_NORESTART); + BodyStillAnimation(); + m_fLastActionTime = _pTimer->CurrentTick(); + // standing anim + } else { + pl.StartModelAnim(PLAYER_ANIM_CROUCH_IDLE, AOF_LOOPING|AOF_NORESTART); + BodyStillAnimation(); + } + } + + } + + // no reference (in air) + } else { + // touched reference + if (pl.en_penReference!=NULL) { + m_bReference = TRUE; + pl.StartModelAnim(PLAYER_ANIM_JUMPEND, AOF_NORESTART); + BodyStillAnimation(); + SpawnReminder(this, pl.GetModelObject()->GetAnimLength(PLAYER_ANIM_JUMPEND), (INDEX) AA_JUMPDOWN); + m_bWaitJumpAnim = TRUE; + } + } + } + + // boring weapon animation + if (_pTimer->CurrentTick()-m_fLastActionTime > 10.0f) { + m_fLastActionTime = _pTimer->CurrentTick(); + ((CPlayerWeapons&)*pl.m_penWeapons).SendEvent(EBoringWeapon()); + } + + // moving view change + // translating -> change banking + if (m_bReference != NULL && vDesiredTranslation.Length()>1.0f && vCurrentTranslation.Length()>1.0f) { + m_bMoving = TRUE; + // sidestep banking + FLOAT vSidestepSpeedDesired = vDesiredTranslation(1); + FLOAT vSidestepSpeedCurrent = vCurrentTranslation(1); + // right + if (vSidestepSpeedDesired>1.0f && vSidestepSpeedCurrent>1.0f) { + m_bSidestepBankingRight = TRUE; + m_bSidestepBankingLeft = FALSE; + // left + } else if (vSidestepSpeedDesired<-1.0f && vSidestepSpeedCurrent<-1.0f) { + m_bSidestepBankingLeft = TRUE; + m_bSidestepBankingRight = FALSE; + // none + } else { + m_bSidestepBankingLeft = FALSE; + m_bSidestepBankingRight = FALSE; + } + // in air (space) or not moving + } else { + m_bMoving = FALSE; + m_bSidestepBankingLeft = FALSE; + m_bSidestepBankingRight = FALSE; + } + }; + + // crouch + void Crouch(void) { + if (m_bDisableAnimating) { + return; + } + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.StartModelAnim(PLAYER_ANIM_CROUCH, AOF_NORESTART); + SpawnReminder(this, pl.GetModelObject()->GetAnimLength(PLAYER_ANIM_CROUCH), (INDEX) AA_CROUCH); + m_iCrouchDownWait++; + m_bCrouch = TRUE; + }; + + // rise + void Rise(void) { + if (m_bDisableAnimating) { + return; + } + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.StartModelAnim(PLAYER_ANIM_RISE, AOF_NORESTART); + SpawnReminder(this, pl.GetModelObject()->GetAnimLength(PLAYER_ANIM_RISE), (INDEX) AA_RISE); + m_iRiseUpWait++; + m_bCrouch = FALSE; + }; + + // fall + void Fall(void) { + if (m_bDisableAnimating) { + return; + } + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.StartModelAnim(PLAYER_ANIM_JUMPSTART, AOF_NORESTART); + if (_pNetwork->ga_ulDemoMinorVersion>6) { m_bCrouch = FALSE; } + m_bReference = FALSE; + }; + + // swim + void Swim(void) { + if (m_bDisableAnimating) { + return; + } + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.StartModelAnim(PLAYER_ANIM_SWIM, AOF_LOOPING|AOF_NORESTART); + if (_pNetwork->ga_ulDemoMinorVersion>2) { m_bCrouch = FALSE; } + m_bSwim = TRUE; + }; + + // stand + void Stand(void) { + if (m_bDisableAnimating) { + return; + } + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.StartModelAnim(PLAYER_ANIM_STAND, AOF_LOOPING|AOF_NORESTART); + if (_pNetwork->ga_ulDemoMinorVersion>2) { m_bCrouch = FALSE; } + m_bSwim = FALSE; + }; + + // fire/attack + void FireAnimation(INDEX iAnim, ULONG ulFlags) { + if (m_bSwim) { + INDEX iWeapon = ((CPlayerWeapons&)*(((CPlayer&)*m_penPlayer).m_penWeapons)).m_iCurrentWeapon; + switch (iWeapon) { + case WEAPON_NONE: + break; + case WEAPON_KNIFE: case WEAPON_COLT: case WEAPON_DOUBLECOLT: //case WEAPON_PIPEBOMB: + iAnim += BODY_ANIM_COLT_SWIM_STAND-BODY_ANIM_COLT_STAND; + break; + case WEAPON_SINGLESHOTGUN: case WEAPON_DOUBLESHOTGUN: case WEAPON_TOMMYGUN: + case WEAPON_SNIPER: case WEAPON_LASER: case WEAPON_FLAMER: //case WEAPON_GHOSTBUSTER: + iAnim += BODY_ANIM_SHOTGUN_SWIM_STAND-BODY_ANIM_SHOTGUN_STAND; + break; + case WEAPON_MINIGUN: case WEAPON_ROCKETLAUNCHER: case WEAPON_GRENADELAUNCHER: + case WEAPON_IRONCANNON: case WEAPON_CHAINSAW: // case WEAPON_NUKECANNON: + iAnim += BODY_ANIM_MINIGUN_SWIM_STAND-BODY_ANIM_MINIGUN_STAND; + break; + } + } + m_bAttacking = FALSE; + m_bChangeWeapon = FALSE; + SetBodyAnimation(iAnim, ulFlags); + if (!(ulFlags&AOF_LOOPING)) { + SpawnReminder(this, m_fBodyAnimTime, (INDEX) AA_ATTACK); + m_tmAttackingDue = _pTimer->CurrentTick()+m_fBodyAnimTime; + } + m_bAttacking = TRUE; + }; + void FireAnimationOff(void) { + m_bAttacking = FALSE; + }; + + + +/************************************************************ + * CHANGE BODY ANIMATION * + ************************************************************/ + // body animation template + void BodyAnimationTemplate(INDEX iNone, INDEX iColt, INDEX iShotgun, INDEX iMinigun, ULONG ulFlags) { + INDEX iWeapon = ((CPlayerWeapons&)*(((CPlayer&)*m_penPlayer).m_penWeapons)).m_iCurrentWeapon; + switch (iWeapon) { + case WEAPON_NONE: + SetBodyAnimation(iNone, ulFlags); + break; + case WEAPON_KNIFE: case WEAPON_COLT: case WEAPON_DOUBLECOLT: // case WEAPON_PIPEBOMB: + if (m_bSwim) { iColt += BODY_ANIM_COLT_SWIM_STAND-BODY_ANIM_COLT_STAND; } + SetBodyAnimation(iColt, ulFlags); + break; + case WEAPON_SINGLESHOTGUN: case WEAPON_DOUBLESHOTGUN: case WEAPON_TOMMYGUN: + case WEAPON_SNIPER: case WEAPON_LASER: case WEAPON_FLAMER: //case WEAPON_GHOSTBUSTER: + if (m_bSwim) { iShotgun += BODY_ANIM_SHOTGUN_SWIM_STAND-BODY_ANIM_SHOTGUN_STAND; } + SetBodyAnimation(iShotgun, ulFlags); + break; + case WEAPON_MINIGUN: case WEAPON_ROCKETLAUNCHER: case WEAPON_GRENADELAUNCHER: + case WEAPON_IRONCANNON: case WEAPON_CHAINSAW: // case WEAPON_NUKECANNON: + if (m_bSwim) { iMinigun+=BODY_ANIM_MINIGUN_SWIM_STAND-BODY_ANIM_MINIGUN_STAND; } + SetBodyAnimation(iMinigun, ulFlags); + break; + default: ASSERTALWAYS("Player Animator - Unknown weapon"); + } + }; + + // walk + void BodyWalkAnimation() { + BodyAnimationTemplate(BODY_ANIM_NORMALWALK, + BODY_ANIM_COLT_STAND, BODY_ANIM_SHOTGUN_STAND, BODY_ANIM_MINIGUN_STAND, + AOF_LOOPING|AOF_NORESTART); + }; + + // stand + void BodyStillAnimation() { + BodyAnimationTemplate(BODY_ANIM_WAIT, + BODY_ANIM_COLT_STAND, BODY_ANIM_SHOTGUN_STAND, BODY_ANIM_MINIGUN_STAND, + AOF_LOOPING|AOF_NORESTART); + }; + + // push weapon + void BodyPushAnimation() { + m_bAttacking = FALSE; + m_bChangeWeapon = FALSE; + BodyAnimationTemplate(BODY_ANIM_WAIT, + BODY_ANIM_COLT_REDRAW, BODY_ANIM_SHOTGUN_REDRAW, BODY_ANIM_MINIGUN_REDRAW, 0); + m_bChangeWeapon = TRUE; + }; + + // remove weapon attachment + void RemoveWeapon(void) + { + CPlayer &pl = (CPlayer&)*m_penPlayer; + pmoModel = &(pl.GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject); + switch (m_iWeaponLast) { + case WEAPON_NONE: + case WEAPON_KNIFE: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_KNIFE); + break; + case WEAPON_DOUBLECOLT: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_COLT_LEFT); + // reset to player body + pmoModel = &(pl.GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject); + case WEAPON_COLT: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_COLT_RIGHT); + break; + case WEAPON_SINGLESHOTGUN: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_SINGLE_SHOTGUN); + break; + case WEAPON_DOUBLESHOTGUN: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_DOUBLE_SHOTGUN); + break; + case WEAPON_TOMMYGUN: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_TOMMYGUN); + break; + case WEAPON_SNIPER: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_FLAMER); + break; + case WEAPON_MINIGUN: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_MINIGUN); + break; + case WEAPON_ROCKETLAUNCHER: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_ROCKET_LAUNCHER); + break; + case WEAPON_GRENADELAUNCHER: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_GRENADE_LAUNCHER); + break; +/* case WEAPON_PIPEBOMB: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_COLT_RIGHT); + // reset to player body + pmoModel = &(pl.GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject); + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_COLT_LEFT); + break; */ + case WEAPON_FLAMER: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_FLAMER); + break; + case WEAPON_CHAINSAW: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_MINIGUN); + break; + case WEAPON_LASER: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_LASER); + break; +/* case WEAPON_GHOSTBUSTER: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_LASER); + break; */ + case WEAPON_IRONCANNON: +// case WEAPON_NUKECANNON: + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_CANNON); + break; + default: + ASSERT(FALSE); + } + // sync apperances + SyncWeapon(); + } + + // pull weapon + void BodyPullAnimation() { + // remove old weapon + RemoveWeapon(); + + // set new weapon + SetWeapon(); + + // pull weapon + m_bChangeWeapon = FALSE; + BodyAnimationTemplate(BODY_ANIM_WAIT, + BODY_ANIM_COLT_DRAW, BODY_ANIM_SHOTGUN_DRAW, BODY_ANIM_MINIGUN_DRAW, 0); + INDEX iWeapon = ((CPlayerWeapons&)*(((CPlayer&)*m_penPlayer).m_penWeapons)).m_iCurrentWeapon; + if (iWeapon!=WEAPON_NONE) { + m_bChangeWeapon = TRUE; + SpawnReminder(this, m_fBodyAnimTime, (INDEX) AA_PULLWEAPON); + } + // sync apperances + SyncWeapon(); + }; + + // pull item + void BodyPullItemAnimation() { + // remove old weapon + RemoveWeapon(); + + // pull item + m_bChangeWeapon = FALSE; + SetBodyAnimation(BODY_ANIM_STATUE_PULL, 0); + m_bChangeWeapon = TRUE; + SpawnReminder(this, m_fBodyAnimTime, (INDEX) AA_PULLWEAPON); + // sync apperances + SyncWeapon(); + }; + + // pick item + void BodyPickItemAnimation() { + // remove old weapon + RemoveWeapon(); + + // pick item + m_bChangeWeapon = FALSE; + SetBodyAnimation(BODY_ANIM_KEYLIFT, 0); + m_bChangeWeapon = TRUE; + SpawnReminder(this, m_fBodyAnimTime, (INDEX) AA_PULLWEAPON); + // sync apperances + SyncWeapon(); + }; + + // remove item + void BodyRemoveItem() { + CPlayer &pl = (CPlayer&)*m_penPlayer; + pmoModel = &(pl.GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject); + pmoModel->RemoveAttachmentModel(BODY_ATTACHMENT_ITEM); + // sync apperances + SyncWeapon(); + }; + + +/************************************************************ + * FIRE FLARE * + ************************************************************/ + void OnPreRender(void) { + ControlFlareAttachment(); + + // Minigun Specific + CPlayerWeapons &plw = (CPlayerWeapons&)*(((CPlayer&)*m_penPlayer).m_penWeapons); + if (plw.m_iCurrentWeapon==WEAPON_MINIGUN) { + ANGLE aAngle = Lerp(plw.m_aMiniGunLast, plw.m_aMiniGun, _pTimer->GetLerpFactor()); + // rotate minigun barrels + CPlayer &pl = (CPlayer&)*m_penPlayer; + CAttachmentModelObject *pamo = pl.GetModelObject()->GetAttachmentModelList( + PLAYER_ATTACHMENT_TORSO, BODY_ATTACHMENT_MINIGUN, MINIGUNITEM_ATTACHMENT_BARRELS, -1); + if (pamo!=NULL) { + pamo->amo_plRelative.pl_OrientationAngle(3) = aAngle; + } + } + }; + + // show flare + void ShowFlare(INDEX iAttachWeapon, INDEX iAttachObject, INDEX iAttachFlare) { + CPlayer &pl = (CPlayer&)*m_penPlayer; + CAttachmentModelObject *pamo = pl.GetModelObject()->GetAttachmentModelList( + PLAYER_ATTACHMENT_TORSO, iAttachWeapon, iAttachObject, iAttachFlare, -1); + if (pamo!=NULL) { + pamo->amo_plRelative.pl_OrientationAngle(3) = (rand()*360.0f)/RAND_MAX; + CModelObject &mo = pamo->amo_moModelObject; + mo.StretchModel(FLOAT3D(1, 1, 1)); + } + }; + + // hide flare + void HideFlare(INDEX iAttachWeapon, INDEX iAttachObject, INDEX iAttachFlare) { + CPlayer &pl = (CPlayer&)*m_penPlayer; + CAttachmentModelObject *pamo = pl.GetModelObject()->GetAttachmentModelList( + PLAYER_ATTACHMENT_TORSO, iAttachWeapon, iAttachObject, iAttachFlare, -1); + if (pamo!=NULL) { + CModelObject &mo = pamo->amo_moModelObject; + mo.StretchModel(FLOAT3D(0, 0, 0)); + } + }; + + // flare attachment + void ControlFlareAttachment(void) + { +/* if(!IsPredictionHead()) { + return; + } + */ + + // get your prediction tail + CPlayerAnimator *pen = (CPlayerAnimator *)GetPredictionTail(); + + INDEX iWeapon = ((CPlayerWeapons&)*(((CPlayer&)*pen->m_penPlayer).m_penWeapons)).m_iCurrentWeapon; + // second colt only + if (iWeapon==WEAPON_DOUBLECOLT) { + // add flare + if (pen->m_iSecondFlare==FLARE_ADD) { + pen->m_iSecondFlare = FLARE_REMOVE; + ShowFlare(BODY_ATTACHMENT_COLT_LEFT, COLTITEM_ATTACHMENT_BODY, COLTMAIN_ATTACHMENT_FLARE); + // remove flare + } else if (m_iSecondFlare==FLARE_REMOVE) { + HideFlare(BODY_ATTACHMENT_COLT_LEFT, COLTITEM_ATTACHMENT_BODY, COLTMAIN_ATTACHMENT_FLARE); + } + } + + // add flare + if (pen->m_iFlare==FLARE_ADD) { + pen->m_iFlare = FLARE_REMOVE; + pen->m_tmFlareAdded = _pTimer->CurrentTick(); + switch(iWeapon) { + case WEAPON_DOUBLECOLT: case WEAPON_COLT: + ShowFlare(BODY_ATTACHMENT_COLT_RIGHT, COLTITEM_ATTACHMENT_BODY, COLTMAIN_ATTACHMENT_FLARE); + break; + case WEAPON_SINGLESHOTGUN: + ShowFlare(BODY_ATTACHMENT_SINGLE_SHOTGUN, SINGLESHOTGUNITEM_ATTACHMENT_BARRELS, BARRELS_ATTACHMENT_FLARE); + break; + case WEAPON_DOUBLESHOTGUN: + ShowFlare(BODY_ATTACHMENT_DOUBLE_SHOTGUN, DOUBLESHOTGUNITEM_ATTACHMENT_BARRELS, DSHOTGUNBARRELS_ATTACHMENT_FLARE); + break; + case WEAPON_TOMMYGUN: + ShowFlare(BODY_ATTACHMENT_TOMMYGUN, TOMMYGUNITEM_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE); + break; + case WEAPON_SNIPER: + ShowFlare(BODY_ATTACHMENT_FLAMER, SNIPERITEM_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE); + break; + case WEAPON_MINIGUN: + ShowFlare(BODY_ATTACHMENT_MINIGUN, MINIGUNITEM_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE); + break; + } + // remove + } else if (m_iFlare==FLARE_REMOVE && + _pTimer->CurrentTick()>pen->m_tmFlareAdded+_pTimer->TickQuantum) { + switch(iWeapon) { + case WEAPON_DOUBLECOLT: case WEAPON_COLT: + HideFlare(BODY_ATTACHMENT_COLT_RIGHT, COLTITEM_ATTACHMENT_BODY, COLTMAIN_ATTACHMENT_FLARE); + break; + case WEAPON_SINGLESHOTGUN: + HideFlare(BODY_ATTACHMENT_SINGLE_SHOTGUN, SINGLESHOTGUNITEM_ATTACHMENT_BARRELS, BARRELS_ATTACHMENT_FLARE); + break; + case WEAPON_DOUBLESHOTGUN: + HideFlare(BODY_ATTACHMENT_DOUBLE_SHOTGUN, DOUBLESHOTGUNITEM_ATTACHMENT_BARRELS, DSHOTGUNBARRELS_ATTACHMENT_FLARE); + break; + case WEAPON_TOMMYGUN: + HideFlare(BODY_ATTACHMENT_TOMMYGUN, TOMMYGUNITEM_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE); + break; + case WEAPON_SNIPER: + HideFlare(BODY_ATTACHMENT_FLAMER, SNIPERITEM_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE); + break; + case WEAPON_MINIGUN: + HideFlare(BODY_ATTACHMENT_MINIGUN, MINIGUNITEM_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE); + break; + } + } + }; + + + +/************************************************************ + * PROCEDURES * + ************************************************************/ +procedures: + ReminderAction(EReminder er) { + switch (er.iValue) { + case AA_JUMPDOWN: m_bWaitJumpAnim = FALSE; break; + case AA_CROUCH: m_iCrouchDownWait--; ASSERT(m_iCrouchDownWait>=0); break; + case AA_RISE: m_iRiseUpWait--; ASSERT(m_iRiseUpWait>=0); break; + case AA_PULLWEAPON: m_bChangeWeapon = FALSE; break; + case AA_ATTACK: if(m_tmAttackingDue<=_pTimer->CurrentTick()) { m_bAttacking = FALSE; } break; + default: ASSERTALWAYS("Animator - unknown reminder action."); + } + return EBegin(); + }; + + Main(EAnimatorInit eInit) { + // remember the initial parameters + ASSERT(eInit.penPlayer!=NULL); + m_penPlayer = eInit.penPlayer; + + // declare yourself as a void + InitAsVoid(); + SetFlags(GetFlags()|ENF_CROSSESLEVELS); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // last action time for boring weapon animation + m_fLastActionTime = _pTimer->CurrentTick(); + + wait() { + on (EBegin) : { resume; } + on (EReminder er) : { call ReminderAction(er); } + on (EEnd) : { stop; } + } + + // cease to exist + Destroy(); + + return; + }; +}; + diff --git a/Sources/EntitiesMP/PlayerAnimator.h b/Sources/EntitiesMP/PlayerAnimator.h new file mode 100644 index 0000000..515f0a6 --- /dev/null +++ b/Sources/EntitiesMP/PlayerAnimator.h @@ -0,0 +1,195 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_PlayerAnimator_INCLUDED +#define _EntitiesMP_PlayerAnimator_INCLUDED 1 +#include +#include +#define EVENTCODE_EAnimatorInit 0x01960000 +class DECL_DLL EAnimatorInit : public CEntityEvent { +public: +EAnimatorInit(); +CEntityEvent *MakeCopy(void); +CEntityPointer penPlayer; +}; +DECL_DLL inline void ClearToDefault(EAnimatorInit &e) { e = EAnimatorInit(); } ; +extern "C" DECL_DLL CDLLEntityClass CPlayerAnimator_DLLClass; +class DECL_DLL CPlayerAnimator : public CRationalEntity { +public: +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + virtual void SetDefaultProperties(void); + CEntityPointer m_penPlayer; + BOOL m_bReference; + FLOAT m_fLastActionTime; + INDEX m_iContent; + BOOL m_bWaitJumpAnim; + BOOL m_bCrouch; + BOOL m_iCrouchDownWait; + BOOL m_iRiseUpWait; + BOOL m_bChangeWeapon; + BOOL m_bSwim; + INDEX m_iFlare; + INDEX m_iSecondFlare; + BOOL m_bAttacking; + FLOAT m_tmAttackingDue; + FLOAT m_tmFlareAdded; + BOOL m_bDisableAnimating; + FLOAT3D m_vLastPlayerPosition; + FLOAT m_fEyesYLastOffset; + FLOAT m_fEyesYOffset; + FLOAT m_fEyesYSpeed; + FLOAT m_fWeaponYLastOffset; + FLOAT m_fWeaponYOffset; + FLOAT m_fWeaponYSpeed; + BOOL m_bMoving; + FLOAT m_fMoveLastBanking; + FLOAT m_fMoveBanking; + BOOL m_iMovingSide; + BOOL m_bSidestepBankingLeft; + BOOL m_bSidestepBankingRight; + FLOAT m_fSidestepLastBanking; + FLOAT m_fSidestepBanking; + INDEX m_iWeaponLast; + FLOAT m_fBodyAnimTime; + CEntityPointer m_penPrediction; +CModelObject * pmoModel; + +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void Read_t(CTStream * istr); + +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void Precache(void); + +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CPlayer * GetPlayer(void); + +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CModelObject * GetBody(void); + +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +CModelObject * GetBodyRen(void); + +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void SetComponents(CModelObject * mo,ULONG ulIDModel,ULONG ulIDTexture, +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture); + +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void AddAttachmentModel(CModelObject * mo,INDEX iAttachment,ULONG ulIDModel,ULONG ulIDTexture, +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture); + +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void AddWeaponAttachment(INDEX iAttachment,ULONG ulIDModel,ULONG ulIDTexture, +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ULONG ulIDReflectionTexture,ULONG ulIDSpecularTexture,ULONG ulIDBumpTexture); + +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void SetAttachment(INDEX iAttachment); + +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void SyncWeapon(void); + +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void SetWeapon(void); + +#line 761 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void SetItem(CModelObject * pmo); + +#line 778 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void SetBodyAnimation(INDEX iAnimation,ULONG ulFlags); + +#line 794 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void Initialize(void); + +#line 836 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void StoreLast(void); + +#line 847 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void AnimateBanking(void); + +#line 904 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void AnimateSoftEyes(void); + +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void ChangeView(CPlacement3D & pl); + +#line 1012 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void BodyAndHeadOrientation(CPlacement3D & plView); + +#line 1035 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void AnimatePlayer(void); + +#line 1189 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void Crouch(void); + +#line 1201 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void Rise(void); + +#line 1213 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void Fall(void); + +#line 1224 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void Swim(void); + +#line 1235 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void Stand(void); + +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void FireAnimation(INDEX iAnim,ULONG ulFlags); + +#line 1274 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void FireAnimationOff(void); + +#line 1284 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void BodyAnimationTemplate(INDEX iNone,INDEX iColt,INDEX iShotgun,INDEX iMinigun,ULONG ulFlags); + +#line 1309 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void BodyWalkAnimation(); + +#line 1316 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void BodyStillAnimation(); + +#line 1323 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void BodyPushAnimation(); + +#line 1332 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void RemoveWeapon(void); + +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void BodyPullAnimation(); + +#line 1420 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void BodyPullItemAnimation(); + +#line 1434 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void BodyPickItemAnimation(); + +#line 1448 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void BodyRemoveItem(); + +#line 1460 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void OnPreRender(void); + +#line 1478 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void ShowFlare(INDEX iAttachWeapon,INDEX iAttachObject,INDEX iAttachFlare); + +#line 1490 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void HideFlare(INDEX iAttachWeapon,INDEX iAttachObject,INDEX iAttachFlare); + +#line 1501 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +void ControlFlareAttachment(void); +#define STATE_CPlayerAnimator_ReminderAction 0x01960001 + BOOL +#line 1580 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ReminderAction(const CEntityEvent &__eeInput); +#define STATE_CPlayerAnimator_Main 1 + BOOL +#line 1592 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01960002_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01960003_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_PlayerAnimator_INCLUDED diff --git a/Sources/EntitiesMP/PlayerAnimator_tables.h b/Sources/EntitiesMP/PlayerAnimator_tables.h new file mode 100644 index 0000000..7c9bbb5 --- /dev/null +++ b/Sources/EntitiesMP/PlayerAnimator_tables.h @@ -0,0 +1,240 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CPlayerAnimator + +CEntityProperty CPlayerAnimator_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000196<<8)+1, offsetof(CPlayerAnimator, m_penPlayer), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+5, offsetof(CPlayerAnimator, m_bReference), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+6, offsetof(CPlayerAnimator, m_fLastActionTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000196<<8)+7, offsetof(CPlayerAnimator, m_iContent), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+8, offsetof(CPlayerAnimator, m_bWaitJumpAnim), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+9, offsetof(CPlayerAnimator, m_bCrouch), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+10, offsetof(CPlayerAnimator, m_iCrouchDownWait), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+11, offsetof(CPlayerAnimator, m_iRiseUpWait), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+12, offsetof(CPlayerAnimator, m_bChangeWeapon), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+13, offsetof(CPlayerAnimator, m_bSwim), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000196<<8)+14, offsetof(CPlayerAnimator, m_iFlare), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000196<<8)+15, offsetof(CPlayerAnimator, m_iSecondFlare), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+16, offsetof(CPlayerAnimator, m_bAttacking), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+19, offsetof(CPlayerAnimator, m_tmAttackingDue), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+17, offsetof(CPlayerAnimator, m_tmFlareAdded), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+18, offsetof(CPlayerAnimator, m_bDisableAnimating), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000196<<8)+20, offsetof(CPlayerAnimator, m_vLastPlayerPosition), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+21, offsetof(CPlayerAnimator, m_fEyesYLastOffset), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+22, offsetof(CPlayerAnimator, m_fEyesYOffset), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+23, offsetof(CPlayerAnimator, m_fEyesYSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+27, offsetof(CPlayerAnimator, m_fWeaponYLastOffset), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+28, offsetof(CPlayerAnimator, m_fWeaponYOffset), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+29, offsetof(CPlayerAnimator, m_fWeaponYSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+30, offsetof(CPlayerAnimator, m_bMoving), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+31, offsetof(CPlayerAnimator, m_fMoveLastBanking), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+32, offsetof(CPlayerAnimator, m_fMoveBanking), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+33, offsetof(CPlayerAnimator, m_iMovingSide), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+34, offsetof(CPlayerAnimator, m_bSidestepBankingLeft), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000196<<8)+35, offsetof(CPlayerAnimator, m_bSidestepBankingRight), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+36, offsetof(CPlayerAnimator, m_fSidestepLastBanking), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+37, offsetof(CPlayerAnimator, m_fSidestepBanking), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000196<<8)+38, offsetof(CPlayerAnimator, m_iWeaponLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000196<<8)+39, offsetof(CPlayerAnimator, m_fBodyAnimTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000196<<8)+255, offsetof(CPlayerAnimator, m_penPrediction), "", 0, 0, 0), +}; +#define CPlayerAnimator_propertiesct ARRAYCOUNT(CPlayerAnimator_properties) + +CEntityComponent CPlayerAnimator_components[] = { +#define CLASS_REMINDER ((0x00000196<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_REMINDER, "EFNM" "Classes\\Reminder.ecl"), +#define MODEL_KNIFE ((0x00000196<<8)+20) + CEntityComponent(ECT_MODEL, MODEL_KNIFE, "EFNM" "Models\\Weapons\\Knife\\KnifeItem.mdl"), +#define TEXTURE_KNIFE ((0x00000196<<8)+22) + CEntityComponent(ECT_TEXTURE, TEXTURE_KNIFE, "EFNM" "Models\\Weapons\\Knife\\KnifeItem.tex"), +#define MODEL_COLT ((0x00000196<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_COLT, "EFNM" "Models\\Weapons\\Colt\\ColtItem.mdl"), +#define MODEL_COLTCOCK ((0x00000196<<8)+31) + CEntityComponent(ECT_MODEL, MODEL_COLTCOCK, "EFNM" "Models\\Weapons\\Colt\\ColtCock.mdl"), +#define MODEL_COLTMAIN ((0x00000196<<8)+32) + CEntityComponent(ECT_MODEL, MODEL_COLTMAIN, "EFNM" "Models\\Weapons\\Colt\\ColtMain.mdl"), +#define MODEL_COLTBULLETS ((0x00000196<<8)+33) + CEntityComponent(ECT_MODEL, MODEL_COLTBULLETS, "EFNM" "Models\\Weapons\\Colt\\ColtBullets.mdl"), +#define TEXTURE_COLTBULLETS ((0x00000196<<8)+34) + CEntityComponent(ECT_TEXTURE, TEXTURE_COLTBULLETS, "EFNM" "Models\\Weapons\\Colt\\ColtBullets.tex"), +#define TEXTURE_COLTMAIN ((0x00000196<<8)+35) + CEntityComponent(ECT_TEXTURE, TEXTURE_COLTMAIN, "EFNM" "Models\\Weapons\\Colt\\ColtMain.tex"), +#define TEXTURE_COLTCOCK ((0x00000196<<8)+36) + CEntityComponent(ECT_TEXTURE, TEXTURE_COLTCOCK, "EFNM" "Models\\Weapons\\Colt\\ColtCock.tex"), +#define MODEL_SINGLESHOTGUN ((0x00000196<<8)+40) + CEntityComponent(ECT_MODEL, MODEL_SINGLESHOTGUN, "EFNM" "Models\\Weapons\\SingleShotgun\\SingleShotgunItem.mdl"), +#define MODEL_SS_SLIDER ((0x00000196<<8)+41) + CEntityComponent(ECT_MODEL, MODEL_SS_SLIDER, "EFNM" "Models\\Weapons\\SingleShotgun\\Slider.mdl"), +#define MODEL_SS_HANDLE ((0x00000196<<8)+42) + CEntityComponent(ECT_MODEL, MODEL_SS_HANDLE, "EFNM" "Models\\Weapons\\SingleShotgun\\Handle.mdl"), +#define MODEL_SS_BARRELS ((0x00000196<<8)+43) + CEntityComponent(ECT_MODEL, MODEL_SS_BARRELS, "EFNM" "Models\\Weapons\\SingleShotgun\\Barrels.mdl"), +#define TEXTURE_SS_HANDLE ((0x00000196<<8)+44) + CEntityComponent(ECT_TEXTURE, TEXTURE_SS_HANDLE, "EFNM" "Models\\Weapons\\SingleShotgun\\Handle.tex"), +#define TEXTURE_SS_BARRELS ((0x00000196<<8)+45) + CEntityComponent(ECT_TEXTURE, TEXTURE_SS_BARRELS, "EFNM" "Models\\Weapons\\SingleShotgun\\Barrels.tex"), +#define MODEL_DOUBLESHOTGUN ((0x00000196<<8)+50) + CEntityComponent(ECT_MODEL, MODEL_DOUBLESHOTGUN, "EFNM" "Models\\Weapons\\DoubleShotgun\\DoubleShotgunItem.mdl"), +#define MODEL_DS_HANDLE ((0x00000196<<8)+51) + CEntityComponent(ECT_MODEL, MODEL_DS_HANDLE, "EFNM" "Models\\Weapons\\DoubleShotgun\\Dshotgunhandle.mdl"), +#define MODEL_DS_BARRELS ((0x00000196<<8)+52) + CEntityComponent(ECT_MODEL, MODEL_DS_BARRELS, "EFNM" "Models\\Weapons\\DoubleShotgun\\Dshotgunbarrels.mdl"), +#define MODEL_DS_SWITCH ((0x00000196<<8)+54) + CEntityComponent(ECT_MODEL, MODEL_DS_SWITCH, "EFNM" "Models\\Weapons\\DoubleShotgun\\Switch.mdl"), +#define TEXTURE_DS_HANDLE ((0x00000196<<8)+56) + CEntityComponent(ECT_TEXTURE, TEXTURE_DS_HANDLE, "EFNM" "Models\\Weapons\\DoubleShotgun\\Handle.tex"), +#define TEXTURE_DS_BARRELS ((0x00000196<<8)+57) + CEntityComponent(ECT_TEXTURE, TEXTURE_DS_BARRELS, "EFNM" "Models\\Weapons\\DoubleShotgun\\Barrels.tex"), +#define TEXTURE_DS_SWITCH ((0x00000196<<8)+58) + CEntityComponent(ECT_TEXTURE, TEXTURE_DS_SWITCH, "EFNM" "Models\\Weapons\\DoubleShotgun\\Switch.tex"), +#define MODEL_TOMMYGUN ((0x00000196<<8)+70) + CEntityComponent(ECT_MODEL, MODEL_TOMMYGUN, "EFNM" "Models\\Weapons\\TommyGun\\TommyGunItem.mdl"), +#define MODEL_TG_BODY ((0x00000196<<8)+71) + CEntityComponent(ECT_MODEL, MODEL_TG_BODY, "EFNM" "Models\\Weapons\\TommyGun\\Body.mdl"), +#define MODEL_TG_SLIDER ((0x00000196<<8)+72) + CEntityComponent(ECT_MODEL, MODEL_TG_SLIDER, "EFNM" "Models\\Weapons\\TommyGun\\Slider.mdl"), +#define TEXTURE_TG_BODY ((0x00000196<<8)+73) + CEntityComponent(ECT_TEXTURE, TEXTURE_TG_BODY, "EFNM" "Models\\Weapons\\TommyGun\\Body.tex"), +#define MODEL_MINIGUN ((0x00000196<<8)+80) + CEntityComponent(ECT_MODEL, MODEL_MINIGUN, "EFNM" "Models\\Weapons\\MiniGun\\MiniGunItem.mdl"), +#define MODEL_MG_BARRELS ((0x00000196<<8)+81) + CEntityComponent(ECT_MODEL, MODEL_MG_BARRELS, "EFNM" "Models\\Weapons\\MiniGun\\Barrels.mdl"), +#define MODEL_MG_BODY ((0x00000196<<8)+82) + CEntityComponent(ECT_MODEL, MODEL_MG_BODY, "EFNM" "Models\\Weapons\\MiniGun\\Body.mdl"), +#define MODEL_MG_ENGINE ((0x00000196<<8)+83) + CEntityComponent(ECT_MODEL, MODEL_MG_ENGINE, "EFNM" "Models\\Weapons\\MiniGun\\Engine.mdl"), +#define TEXTURE_MG_BODY ((0x00000196<<8)+84) + CEntityComponent(ECT_TEXTURE, TEXTURE_MG_BODY, "EFNM" "Models\\Weapons\\MiniGun\\Body.tex"), +#define TEXTURE_MG_BARRELS ((0x00000196<<8)+99) + CEntityComponent(ECT_TEXTURE, TEXTURE_MG_BARRELS, "EFNM" "Models\\Weapons\\MiniGun\\Barrels.tex"), +#define MODEL_ROCKETLAUNCHER ((0x00000196<<8)+90) + CEntityComponent(ECT_MODEL, MODEL_ROCKETLAUNCHER, "EFNM" "Models\\Weapons\\RocketLauncher\\RocketLauncherItem.mdl"), +#define MODEL_RL_BODY ((0x00000196<<8)+91) + CEntityComponent(ECT_MODEL, MODEL_RL_BODY, "EFNM" "Models\\Weapons\\RocketLauncher\\Body.mdl"), +#define TEXTURE_RL_BODY ((0x00000196<<8)+92) + CEntityComponent(ECT_TEXTURE, TEXTURE_RL_BODY, "EFNM" "Models\\Weapons\\RocketLauncher\\Body.tex"), +#define MODEL_RL_ROTATINGPART ((0x00000196<<8)+93) + CEntityComponent(ECT_MODEL, MODEL_RL_ROTATINGPART, "EFNM" "Models\\Weapons\\RocketLauncher\\RotatingPart.mdl"), +#define TEXTURE_RL_ROTATINGPART ((0x00000196<<8)+94) + CEntityComponent(ECT_TEXTURE, TEXTURE_RL_ROTATINGPART, "EFNM" "Models\\Weapons\\RocketLauncher\\RotatingPart.tex"), +#define MODEL_RL_ROCKET ((0x00000196<<8)+95) + CEntityComponent(ECT_MODEL, MODEL_RL_ROCKET, "EFNM" "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl"), +#define TEXTURE_RL_ROCKET ((0x00000196<<8)+96) + CEntityComponent(ECT_TEXTURE, TEXTURE_RL_ROCKET, "EFNM" "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex"), +#define MODEL_GRENADELAUNCHER ((0x00000196<<8)+100) + CEntityComponent(ECT_MODEL, MODEL_GRENADELAUNCHER, "EFNM" "Models\\Weapons\\GrenadeLauncher\\GrenadeLauncherItem.mdl"), +#define MODEL_GL_BODY ((0x00000196<<8)+101) + CEntityComponent(ECT_MODEL, MODEL_GL_BODY, "EFNM" "Models\\Weapons\\GrenadeLauncher\\Body.mdl"), +#define MODEL_GL_MOVINGPART ((0x00000196<<8)+102) + CEntityComponent(ECT_MODEL, MODEL_GL_MOVINGPART, "EFNM" "Models\\Weapons\\GrenadeLauncher\\MovingPipe.mdl"), +#define MODEL_GL_GRENADE ((0x00000196<<8)+103) + CEntityComponent(ECT_MODEL, MODEL_GL_GRENADE, "EFNM" "Models\\Weapons\\GrenadeLauncher\\GrenadeBack.mdl"), +#define TEXTURE_GL_BODY ((0x00000196<<8)+104) + CEntityComponent(ECT_TEXTURE, TEXTURE_GL_BODY, "EFNM" "Models\\Weapons\\GrenadeLauncher\\Body.tex"), +#define TEXTURE_GL_MOVINGPART ((0x00000196<<8)+105) + CEntityComponent(ECT_TEXTURE, TEXTURE_GL_MOVINGPART, "EFNM" "Models\\Weapons\\GrenadeLauncher\\MovingPipe.tex"), +#define MODEL_SNIPER ((0x00000196<<8)+110) + CEntityComponent(ECT_MODEL, MODEL_SNIPER, "EFNM" "ModelsMP\\Weapons\\Sniper\\Sniper.mdl"), +#define MODEL_SNIPER_BODY ((0x00000196<<8)+111) + CEntityComponent(ECT_MODEL, MODEL_SNIPER_BODY, "EFNM" "ModelsMP\\Weapons\\Sniper\\Body.mdl"), +#define TEXTURE_SNIPER_BODY ((0x00000196<<8)+112) + CEntityComponent(ECT_TEXTURE, TEXTURE_SNIPER_BODY, "EFNM" "ModelsMP\\Weapons\\Sniper\\Body.tex"), +#define MODEL_FLAMER ((0x00000196<<8)+130) + CEntityComponent(ECT_MODEL, MODEL_FLAMER, "EFNM" "ModelsMP\\Weapons\\Flamer\\FlamerItem.mdl"), +#define MODEL_FL_BODY ((0x00000196<<8)+131) + CEntityComponent(ECT_MODEL, MODEL_FL_BODY, "EFNM" "ModelsMP\\Weapons\\Flamer\\Body.mdl"), +#define MODEL_FL_RESERVOIR ((0x00000196<<8)+132) + CEntityComponent(ECT_MODEL, MODEL_FL_RESERVOIR, "EFNM" "ModelsMP\\Weapons\\Flamer\\FuelReservoir.mdl"), +#define MODEL_FL_FLAME ((0x00000196<<8)+133) + CEntityComponent(ECT_MODEL, MODEL_FL_FLAME, "EFNM" "ModelsMP\\Weapons\\Flamer\\Flame.mdl"), +#define TEXTURE_FL_BODY ((0x00000196<<8)+134) + CEntityComponent(ECT_TEXTURE, TEXTURE_FL_BODY, "EFNM" "ModelsMP\\Weapons\\Flamer\\Body.tex"), +#define TEXTURE_FL_FLAME ((0x00000196<<8)+135) + CEntityComponent(ECT_TEXTURE, TEXTURE_FL_FLAME, "EFNM" "ModelsMP\\Effects\\Flame\\Flame.tex"), +#define TEXTURE_FL_FUELRESERVOIR ((0x00000196<<8)+136) + CEntityComponent(ECT_TEXTURE, TEXTURE_FL_FUELRESERVOIR, "EFNM" "ModelsMP\\Weapons\\Flamer\\FuelReservoir.tex"), +#define MODEL_LASER ((0x00000196<<8)+140) + CEntityComponent(ECT_MODEL, MODEL_LASER, "EFNM" "Models\\Weapons\\Laser\\LaserItem.mdl"), +#define MODEL_LS_BODY ((0x00000196<<8)+141) + CEntityComponent(ECT_MODEL, MODEL_LS_BODY, "EFNM" "Models\\Weapons\\Laser\\Body.mdl"), +#define MODEL_LS_BARREL ((0x00000196<<8)+142) + CEntityComponent(ECT_MODEL, MODEL_LS_BARREL, "EFNM" "Models\\Weapons\\Laser\\Barrel.mdl"), +#define TEXTURE_LS_BODY ((0x00000196<<8)+143) + CEntityComponent(ECT_TEXTURE, TEXTURE_LS_BODY, "EFNM" "Models\\Weapons\\Laser\\Body.tex"), +#define TEXTURE_LS_BARREL ((0x00000196<<8)+144) + CEntityComponent(ECT_TEXTURE, TEXTURE_LS_BARREL, "EFNM" "Models\\Weapons\\Laser\\Barrel.tex"), +#define MODEL_CHAINSAW ((0x00000196<<8)+150) + CEntityComponent(ECT_MODEL, MODEL_CHAINSAW, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\ChainsawForPlayer.mdl"), +#define MODEL_CS_BODY ((0x00000196<<8)+151) + CEntityComponent(ECT_MODEL, MODEL_CS_BODY, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\BodyForPlayer.mdl"), +#define MODEL_CS_BLADE ((0x00000196<<8)+152) + CEntityComponent(ECT_MODEL, MODEL_CS_BLADE, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Blade.mdl"), +#define MODEL_CS_TEETH ((0x00000196<<8)+153) + CEntityComponent(ECT_MODEL, MODEL_CS_TEETH, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Teeth.mdl"), +#define TEXTURE_CS_BODY ((0x00000196<<8)+154) + CEntityComponent(ECT_TEXTURE, TEXTURE_CS_BODY, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Body.tex"), +#define TEXTURE_CS_BLADE ((0x00000196<<8)+155) + CEntityComponent(ECT_TEXTURE, TEXTURE_CS_BLADE, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Blade.tex"), +#define TEXTURE_CS_TEETH ((0x00000196<<8)+156) + CEntityComponent(ECT_TEXTURE, TEXTURE_CS_TEETH, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Teeth.tex"), +#define MODEL_CANNON ((0x00000196<<8)+170) + CEntityComponent(ECT_MODEL, MODEL_CANNON, "EFNM" "Models\\Weapons\\Cannon\\Cannon.mdl"), +#define MODEL_CN_BODY ((0x00000196<<8)+171) + CEntityComponent(ECT_MODEL, MODEL_CN_BODY, "EFNM" "Models\\Weapons\\Cannon\\Body.mdl"), +#define TEXTURE_CANNON ((0x00000196<<8)+173) + CEntityComponent(ECT_TEXTURE, TEXTURE_CANNON, "EFNM" "Models\\Weapons\\Cannon\\Body.tex"), +#define MODEL_GOLDAMON ((0x00000196<<8)+180) + CEntityComponent(ECT_MODEL, MODEL_GOLDAMON, "EFNM" "Models\\Ages\\Egypt\\Gods\\Amon\\AmonGold.mdl"), +#define TEXTURE_GOLDAMON ((0x00000196<<8)+181) + CEntityComponent(ECT_TEXTURE, TEXTURE_GOLDAMON, "EFNM" "Models\\Ages\\Egypt\\Gods\\Amon\\AmonGold.tex"), +#define TEX_REFL_BWRIPLES01 ((0x00000196<<8)+200) + CEntityComponent(ECT_TEXTURE, TEX_REFL_BWRIPLES01, "EFNM" "Models\\ReflectionTextures\\BWRiples01.tex"), +#define TEX_REFL_BWRIPLES02 ((0x00000196<<8)+201) + CEntityComponent(ECT_TEXTURE, TEX_REFL_BWRIPLES02, "EFNM" "Models\\ReflectionTextures\\BWRiples02.tex"), +#define TEX_REFL_LIGHTMETAL01 ((0x00000196<<8)+202) + CEntityComponent(ECT_TEXTURE, TEX_REFL_LIGHTMETAL01, "EFNM" "Models\\ReflectionTextures\\LightMetal01.tex"), +#define TEX_REFL_LIGHTBLUEMETAL01 ((0x00000196<<8)+203) + CEntityComponent(ECT_TEXTURE, TEX_REFL_LIGHTBLUEMETAL01, "EFNM" "Models\\ReflectionTextures\\LightBlueMetal01.tex"), +#define TEX_REFL_DARKMETAL ((0x00000196<<8)+204) + CEntityComponent(ECT_TEXTURE, TEX_REFL_DARKMETAL, "EFNM" "Models\\ReflectionTextures\\DarkMetal.tex"), +#define TEX_REFL_PURPLE01 ((0x00000196<<8)+205) + CEntityComponent(ECT_TEXTURE, TEX_REFL_PURPLE01, "EFNM" "Models\\ReflectionTextures\\Purple01.tex"), +#define TEX_REFL_GOLD01 ((0x00000196<<8)+206) + CEntityComponent(ECT_TEXTURE, TEX_REFL_GOLD01, "EFNM" "Models\\ReflectionTextures\\Gold01.tex"), +#define TEX_SPEC_WEAK ((0x00000196<<8)+210) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_WEAK, "EFNM" "Models\\SpecularTextures\\Weak.tex"), +#define TEX_SPEC_MEDIUM ((0x00000196<<8)+211) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_MEDIUM, "EFNM" "Models\\SpecularTextures\\Medium.tex"), +#define TEX_SPEC_STRONG ((0x00000196<<8)+212) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_STRONG, "EFNM" "Models\\SpecularTextures\\Strong.tex"), +#define MODEL_FLARE02 ((0x00000196<<8)+250) + CEntityComponent(ECT_MODEL, MODEL_FLARE02, "EFNM" "Models\\Effects\\Weapons\\Flare02\\Flare.mdl"), +#define TEXTURE_FLARE02 ((0x00000196<<8)+251) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE02, "EFNM" "Models\\Effects\\Weapons\\Flare02\\Flare.tex"), +}; +#define CPlayerAnimator_componentsct ARRAYCOUNT(CPlayerAnimator_components) + +CEventHandlerEntry CPlayerAnimator_handlers[] = { + {0x01960001, -1, CEntity::pEventHandler(&CPlayerAnimator:: +#line 1580 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +ReminderAction),DEBUGSTRING("CPlayerAnimator::ReminderAction")}, + {1, -1, CEntity::pEventHandler(&CPlayerAnimator:: +#line 1592 "D:/SE1_GPL/Sources/EntitiesMP/PlayerAnimator.es" +Main),DEBUGSTRING("CPlayerAnimator::Main")}, + {0x01960002, -1, CEntity::pEventHandler(&CPlayerAnimator::H0x01960002_Main_01), DEBUGSTRING("CPlayerAnimator::H0x01960002_Main_01")}, + {0x01960003, -1, CEntity::pEventHandler(&CPlayerAnimator::H0x01960003_Main_02), DEBUGSTRING("CPlayerAnimator::H0x01960003_Main_02")}, +}; +#define CPlayerAnimator_handlersct ARRAYCOUNT(CPlayerAnimator_handlers) + +CEntity *CPlayerAnimator_New(void) { return new CPlayerAnimator; }; +void CPlayerAnimator_OnInitClass(void) {}; +void CPlayerAnimator_OnEndClass(void) {}; +void CPlayerAnimator_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPlayerAnimator_OnWorldEnd(CWorld *pwo) {}; +void CPlayerAnimator_OnWorldInit(CWorld *pwo) {}; +void CPlayerAnimator_OnWorldTick(CWorld *pwo) {}; +void CPlayerAnimator_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPlayerAnimator, CRationalEntity, "Player Animator", "", 0x00000196); +DECLARE_CTFILENAME(_fnmCPlayerAnimator_tbn, ""); diff --git a/Sources/EntitiesMP/PlayerMarker.cpp b/Sources/EntitiesMP/PlayerMarker.cpp new file mode 100644 index 0000000..957e149 --- /dev/null +++ b/Sources/EntitiesMP/PlayerMarker.cpp @@ -0,0 +1,116 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" + +#include "StdH.h" +#include "EntitiesMP/MusicHolder.h" + +#include +#include +#line 11 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" + + extern void CPlayerWeapons_Precache(ULONG ulAvailable); + +void CPlayerMarker::SetDefaultProperties(void) { + m_fHealth = 100.0f; + m_fShield = 0.0f; + m_iGiveWeapons = 0x1; + m_iTakeWeapons = 0x0; + m_strGroup = ""; + m_bQuickStart = FALSE ; + m_bStartInComputer = FALSE ; + m_penMessage = NULL; + m_fMaxAmmoRatio = 0.0f; + m_tmLastSpawned = -1000.0f; + m_iTakeAmmo = 0x0; + m_bNoRespawnInPlace = FALSE ; + CMarker::SetDefaultProperties(); +} + +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +void CPlayerMarker::Precache(void) { +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +if(m_iGiveWeapons > 1){ +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +CPlayerWeapons_Precache (m_iGiveWeapons ); +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +} +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +} + +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +BOOL CPlayerMarker::HandleEvent(const CEntityEvent & ee) { +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +if(ee . ee_slEvent == EVENTCODE_ETrigger ){ +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +CEntity * penMainMusicHolder = _pNetwork -> GetEntityWithName ("MusicHolder" , 0); +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +if(penMainMusicHolder == NULL || ! IsOfClass (penMainMusicHolder , "MusicHolder")){ +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +return TRUE ; +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +} +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +CMusicHolder * pmh = (CMusicHolder *) penMainMusicHolder ; +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +BOOL bNew = (pmh -> m_penRespawnMarker != this ); +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +pmh -> m_penRespawnMarker = this ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +CEntity * penCaused = ((ETrigger &) ee ) . penCaused ; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +if(bNew && +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +(GetSP () -> sp_bSinglePlayer && GetSP () -> sp_gmGameMode != CSessionProperties :: GM_FLYOVER ) +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +&& IsOfClass (penCaused , "Player")){ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +CPlayerSettings * pps = (CPlayerSettings *) (((CPlayerEntity *) penCaused ) -> en_pcCharacter . pc_aubAppearance ); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +if(pps -> ps_ulFlags & PSF_AUTOSAVE ){ +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +_pShell -> Execute ("gam_bQuickSave=1;"); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +} +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +} +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +return TRUE ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +} +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +return FALSE ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +} +BOOL CPlayerMarker:: +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +InitAsEditorModel (); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +SetModel (MODEL_MARKER ); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +if(m_bQuickStart ){ +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +m_strName . PrintF ("Player Quick Start"); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +}else { +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +m_strName . PrintF ("Player Start - %s" , m_strGroup ); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +} +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/PlayerMarker.es b/Sources/EntitiesMP/PlayerMarker.es new file mode 100644 index 0000000..18defb0 --- /dev/null +++ b/Sources/EntitiesMP/PlayerMarker.es @@ -0,0 +1,93 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +404 +%{ +#include "StdH.h" +#include "EntitiesMP/MusicHolder.h" +%} + +uses "EntitiesMP/Marker"; + +%{ + extern void CPlayerWeapons_Precache(ULONG ulAvailable); +%} + +class CPlayerMarker: CMarker { +name "Player Marker"; +thumbnail "Thumbnails\\PlayerMarker.tbn"; +features "IsImportant"; + +properties: + 1 FLOAT m_fHealth "Health" 'H' = 100.0f, + 2 FLOAT m_fShield "Shield" 'S' = 0.0f, + 3 INDEX m_iGiveWeapons "Give Weapons" 'W' = 0x1, + 4 INDEX m_iTakeWeapons "Take Weapons" = 0x0, + 5 CTString m_strGroup "Group" 'G' = "", + 6 BOOL m_bQuickStart "Quick start" 'Q' = FALSE, + 7 BOOL m_bStartInComputer "Start in computer" 'C' = FALSE, + 8 CEntityPointer m_penMessage "Message" 'M', + 9 FLOAT m_fMaxAmmoRatio "Max ammo ratio" 'A' = 0.0f, + 10 FLOAT m_tmLastSpawned = -1000.0f, // to avoid telefragging in deathmatch + 11 INDEX m_iTakeAmmo "Take Ammo" = 0x0, + 12 BOOL m_bNoRespawnInPlace "No Respawn In Place" 'R' = FALSE, + +components: + 1 model MODEL_MARKER "Models\\Editor\\PlayerStart.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\PlayerStart.tex", + +functions: + void Precache(void) { + if (m_iGiveWeapons>1) { + CPlayerWeapons_Precache(m_iGiveWeapons); + } + } + BOOL HandleEvent(const CEntityEvent &ee) { + if (ee.ee_slEvent == EVENTCODE_ETrigger) { + CEntity *penMainMusicHolder = _pNetwork->GetEntityWithName("MusicHolder", 0); + if (penMainMusicHolder==NULL || !IsOfClass(penMainMusicHolder, "MusicHolder")) { + return TRUE; + } + CMusicHolder *pmh = (CMusicHolder *)penMainMusicHolder; + BOOL bNew = (pmh->m_penRespawnMarker!=this); + pmh->m_penRespawnMarker = this; + + // if this is a new marker and we are in single player and the trigger originator is valid + CEntity *penCaused = ((ETrigger&)ee).penCaused; + if (bNew && + (GetSP()->sp_bSinglePlayer && GetSP()->sp_gmGameMode!=CSessionProperties::GM_FLYOVER) + && IsOfClass(penCaused, "Player")) { + // if the player wants auto-save + CPlayerSettings *pps = (CPlayerSettings *) (((CPlayerEntity*)penCaused)->en_pcCharacter.pc_aubAppearance); + if (pps->ps_ulFlags&PSF_AUTOSAVE) { + // save now + _pShell->Execute("gam_bQuickSave=1;"); + } + } + return TRUE; + } + + return FALSE; + }; + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + // set name + if (m_bQuickStart) { + m_strName.PrintF("Player Quick Start"); + } else { + m_strName.PrintF("Player Start - %s", m_strGroup); + } + + return; + } +}; + diff --git a/Sources/EntitiesMP/PlayerMarker.h b/Sources/EntitiesMP/PlayerMarker.h new file mode 100644 index 0000000..62c30b5 --- /dev/null +++ b/Sources/EntitiesMP/PlayerMarker.h @@ -0,0 +1,36 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_PlayerMarker_INCLUDED +#define _EntitiesMP_PlayerMarker_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CPlayerMarker_DLLClass; +class CPlayerMarker : public CMarker { +public: +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fHealth; + FLOAT m_fShield; + INDEX m_iGiveWeapons; + INDEX m_iTakeWeapons; + CTString m_strGroup; + BOOL m_bQuickStart; + BOOL m_bStartInComputer; + CEntityPointer m_penMessage; + FLOAT m_fMaxAmmoRatio; + FLOAT m_tmLastSpawned; + INDEX m_iTakeAmmo; + BOOL m_bNoRespawnInPlace; + +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +void Precache(void); + +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CPlayerMarker_Main 1 + BOOL +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_PlayerMarker_INCLUDED diff --git a/Sources/EntitiesMP/PlayerMarker_tables.h b/Sources/EntitiesMP/PlayerMarker_tables.h new file mode 100644 index 0000000..45c00d4 --- /dev/null +++ b/Sources/EntitiesMP/PlayerMarker_tables.h @@ -0,0 +1,47 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CPlayerMarker + +CEntityProperty CPlayerMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000194<<8)+1, offsetof(CPlayerMarker, m_fHealth), "Health", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000194<<8)+2, offsetof(CPlayerMarker, m_fShield), "Shield", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000194<<8)+3, offsetof(CPlayerMarker, m_iGiveWeapons), "Give Weapons", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000194<<8)+4, offsetof(CPlayerMarker, m_iTakeWeapons), "Take Weapons", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000194<<8)+5, offsetof(CPlayerMarker, m_strGroup), "Group", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000194<<8)+6, offsetof(CPlayerMarker, m_bQuickStart), "Quick start", 'Q', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000194<<8)+7, offsetof(CPlayerMarker, m_bStartInComputer), "Start in computer", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000194<<8)+8, offsetof(CPlayerMarker, m_penMessage), "Message", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000194<<8)+9, offsetof(CPlayerMarker, m_fMaxAmmoRatio), "Max ammo ratio", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000194<<8)+10, offsetof(CPlayerMarker, m_tmLastSpawned), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000194<<8)+11, offsetof(CPlayerMarker, m_iTakeAmmo), "Take Ammo", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000194<<8)+12, offsetof(CPlayerMarker, m_bNoRespawnInPlace), "No Respawn In Place", 'R', 0x7F0000FFUL, 0), +}; +#define CPlayerMarker_propertiesct ARRAYCOUNT(CPlayerMarker_properties) + +CEntityComponent CPlayerMarker_components[] = { +#define MODEL_MARKER ((0x00000194<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\PlayerStart.mdl"), +#define TEXTURE_MARKER ((0x00000194<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\PlayerStart.tex"), +}; +#define CPlayerMarker_componentsct ARRAYCOUNT(CPlayerMarker_components) + +CEventHandlerEntry CPlayerMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CPlayerMarker:: +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/PlayerMarker.es" +Main),DEBUGSTRING("CPlayerMarker::Main")}, +}; +#define CPlayerMarker_handlersct ARRAYCOUNT(CPlayerMarker_handlers) + +CEntity *CPlayerMarker_New(void) { return new CPlayerMarker; }; +void CPlayerMarker_OnInitClass(void) {}; +void CPlayerMarker_OnEndClass(void) {}; +void CPlayerMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPlayerMarker_OnWorldEnd(CWorld *pwo) {}; +void CPlayerMarker_OnWorldInit(CWorld *pwo) {}; +void CPlayerMarker_OnWorldTick(CWorld *pwo) {}; +void CPlayerMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPlayerMarker, CMarker, "Player Marker", "Thumbnails\\PlayerMarker.tbn", 0x00000194); +DECLARE_CTFILENAME(_fnmCPlayerMarker_tbn, "Thumbnails\\PlayerMarker.tbn"); diff --git a/Sources/EntitiesMP/PlayerView.cpp b/Sources/EntitiesMP/PlayerView.cpp new file mode 100644 index 0000000..7cc1b26 --- /dev/null +++ b/Sources/EntitiesMP/PlayerView.cpp @@ -0,0 +1,338 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" + +#include "StdH.h" +#include "EntitiesMP/Player.h" +#include "EntitiesMP/PlayerWeapons.h" + +#include +#include +CEntityEvent *EViewInit::MakeCopy(void) { CEntityEvent *peeCopy = new EViewInit(*this); return peeCopy;} +EViewInit::EViewInit() : CEntityEvent(EVENTCODE_EViewInit) {; + ClearToDefault(penOwner); + ClearToDefault(penCamera); + ClearToDefault(vtView); + ClearToDefault(bDeathFixed); +}; +#line 26 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" + + +void CPlayerView_Precache(void) +{ + CDLLEntityClass *pdec = &CPlayerView_DLLClass; + pdec->PrecacheModel(MODEL_MARKER); + pdec->PrecacheTexture(TEXTURE_MARKER); +} + + +void CPlayerView::SetDefaultProperties(void) { + m_penOwner = NULL; + m_iViewType = 0; + m_fDistance = 1.0f; + m_vZLast = FLOAT3D(0 , 0 , 0); + m_vTargetLast = FLOAT3D(0 , 0 , 0); + m_bFixed = FALSE ; + m_penPrediction = NULL; + CMovableEntity::SetDefaultProperties(); +} + +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void CPlayerView::AddDependentsToPrediction(void) +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +{ +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +m_penOwner -> AddToPrediction (); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} + +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void CPlayerView::PreMoving() {} + +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void CPlayerView::DoMoving() { +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +en_plLastPlacement = GetPlacement (); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void CPlayerView::PostMoving() +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +{ +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +SetCameraPosition (); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +CPlacement3D CPlayerView::GetLerpedPlacement(void)const +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +{ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT fLerpFactor ; +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +if(IsPredictor ()){ +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +fLerpFactor = _pTimer -> GetLerpFactor (); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +}else { +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +fLerpFactor = _pTimer -> GetLerpFactor2 (); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +return LerpPlacementsPrecise (en_plLastPlacement , en_plPlacement , fLerpFactor ); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} + +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void CPlayerView::RenderParticles(void) +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +{ +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +if(Particle_GetViewer () == this ){ +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +Particles_ViewerLocal (this ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void CPlayerView::SetCameraPosition() +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +{ +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT fDistance = 1.0f; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +CPlacement3D pl = ((CPlayerEntity &) * m_penOwner ) . en_plViewpoint ; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +BOOL bFollowCrossHair ; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +if(m_iViewType == VT_3RDPERSONVIEW ){ +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +pl . pl_OrientationAngle (2) -= 12.0f; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +pl . pl_PositionVector (2) += 1.0f; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +fDistance = 4.2f; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +bFollowCrossHair = TRUE ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +}else if(m_iViewType == VT_PLAYERDEATH ){ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +fDistance = 3.5f; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +bFollowCrossHair = FALSE ; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +pl . pl_OrientationAngle (3) = 0.0f; +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +pl . RelativeToAbsolute (m_penOwner -> GetPlacement ()); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT3D vBase ; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +EntityInfo * pei = (EntityInfo *) (m_penOwner -> GetEntityInfo ()); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +GetEntityInfoPosition (m_penOwner , pei -> vSourceCenter , vBase ); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOATmatrix3D m ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +MakeRotationMatrixFast (m , pl . pl_OrientationAngle ); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT3D vRight = m . GetColumn (1); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT3D vUp = m . GetColumn (2); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT3D vFront = m . GetColumn (3); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT3D vDest [ 5 ]; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vDest [ 0 ] = vBase + vFront * fDistance + vUp * 1.0f; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vDest [ 1 ] = vBase + vFront * fDistance - vUp * 1.0f; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vDest [ 2 ] = vBase + vFront * fDistance + vRight * 1.0f; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vDest [ 3 ] = vBase + vFront * fDistance - vRight * 1.0f; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vDest [ 4 ] = vBase + vFront * fDistance ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT fBack = 0; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +for(INDEX i = 0;i < 5;i ++){ +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +CCastRay crRay (m_penOwner , vBase , vDest [ i ]); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +crRay . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +GetWorld () -> CastRay (crRay ); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +if(crRay . cr_penHit != NULL ){ +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +fDistance = Min (fDistance , crRay . cr_fHitDistance - 0.5f); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +if(crRay . cr_pbpoBrushPolygon != NULL ){ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT3D vDir = (vDest [ i ] - vBase ) . Normalize (); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT fD = Abs (FLOAT3D (crRay . cr_pbpoBrushPolygon -> bpo_pbplPlane -> bpl_plAbsolute ) % vDir ) * 0.25f; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +fBack = Max (fBack , fD ); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +fDistance = ClampDn (fDistance - fBack , 0.0f); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +m_fDistance = fDistance ; +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vBase += vFront * fDistance ; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +CPlayerWeapons * ppw = ((CPlayer &) * m_penOwner ) . GetPlayerWeapons (); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +if(bFollowCrossHair ){ +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT3D vTarget = vBase - ppw -> m_vRayHit ; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT fLen = vTarget . Length (); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +if(fLen > 0.01){ +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vTarget /= fLen ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +}else { +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vTarget = FLOAT3D (0 , 1 , 0); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT3D vX ; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT3D vY = m . GetColumn (2); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +FLOAT3D vZ = vTarget ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vZ . Normalize (); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +if(Abs (vY % vZ ) > 0.9f){ +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vY = - m . GetColumn (3); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vX = vY * vZ ; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vX . Normalize (); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vY = vZ * vX ; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +vY . Normalize (); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +m_vZLast = vZ ; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +m (1 , 1) = vX (1);m (1 , 2) = vY (1);m (1 , 3) = vZ (1); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +m (2 , 1) = vX (2);m (2 , 2) = vY (2);m (2 , 3) = vZ (2); +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +m (3 , 1) = vX (3);m (3 , 2) = vY (3);m (3 , 3) = vZ (3); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +DecomposeRotationMatrixNoSnap (pl . pl_OrientationAngle , m ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +if(m_bFixed ){ +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +pl . pl_PositionVector = GetPlacement () . pl_PositionVector ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +pl . pl_OrientationAngle = ANGLE3D (0 , - 90 , 0); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +m_fDistance = (pl . pl_PositionVector - m_penOwner -> GetPlacement () . pl_PositionVector ) . Length (); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +MakeRotationMatrixFast (m , pl . pl_OrientationAngle ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +}else { +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +pl . pl_PositionVector = vBase ; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +SetPlacement_internal (pl , m , TRUE ); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +BOOL CPlayerView:: +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerView_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EViewInit, "CPlayerView::Main expects 'EViewInit' as input!"); const EViewInit &eInit = (const EViewInit &)__eeInput; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +ASSERT (eInit . penOwner != NULL ); +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +m_penOwner = eInit . penOwner ; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +m_iViewType = eInit . vtView ; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +m_bFixed = eInit . bDeathFixed ; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +ASSERT (IsOfClass (m_penOwner , "Player")); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +InitAsEditorModel (); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +SetFlags (GetFlags () | ENF_CROSSESLEVELS ); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL | EPF_MOVABLE ); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +SetModel (MODEL_MARKER ); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +if(m_iViewType == VT_PLAYERDEATH ){ +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +AddToMovers (); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +} +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +SendEvent (EStart ()); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01930001, FALSE, EBegin());return TRUE;}BOOL CPlayerView::H0x01930001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01930001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; + +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +SetCameraPosition (); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +en_plLastPlacement = GetPlacement (); +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +m_vTargetLast = ((CPlayer &) * m_penOwner ) . GetPlayerWeapons () -> m_vRayHit ; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +return TRUE; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnd):{const EEnd&e= (EEnd&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01930002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +}return TRUE;}BOOL CPlayerView::H0x01930002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01930002 + +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +Destroy (); +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +Return(STATE_CURRENT,EVoid()); +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/PlayerView.es b/Sources/EntitiesMP/PlayerView.es new file mode 100644 index 0000000..f91e920 --- /dev/null +++ b/Sources/EntitiesMP/PlayerView.es @@ -0,0 +1,289 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +403 +%{ +#include "StdH.h" +#include "EntitiesMP/Player.h" +#include "EntitiesMP/PlayerWeapons.h" +%} + + +enum ViewType { + 0 VT_PLAYERDEATH "", // player death + 1 VT_PLAYERREBIRTH "", // player rebirth (player is spawned) + 2 VT_CAMERA "", // camera view + 3 VT_3RDPERSONVIEW "", // 3rd person view +}; + +// input parameter for viewer +event EViewInit { + CEntityPointer penOwner, // who owns it + CEntityPointer penCamera, // first camera for camera view + enum ViewType vtView, // view type + BOOL bDeathFixed, +}; + +%{ + +void CPlayerView_Precache(void) +{ + CDLLEntityClass *pdec = &CPlayerView_DLLClass; + pdec->PrecacheModel(MODEL_MARKER); + pdec->PrecacheTexture(TEXTURE_MARKER); +} + +%} + +class export CPlayerView : CMovableEntity { +name "Player View"; +thumbnail ""; +features "CanBePredictable"; + +properties: + 1 CEntityPointer m_penOwner, // class which owns it + 2 INDEX m_iViewType=0, // view type + 3 FLOAT m_fDistance = 1.0f, // current distance + 4 FLOAT3D m_vZLast = FLOAT3D(0,0,0), + 5 FLOAT3D m_vTargetLast = FLOAT3D(0,0,0), + 6 BOOL m_bFixed = FALSE, // fixed view (player falling in abyss) + +components: + 1 model MODEL_MARKER "Models\\Editor\\Axis.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex" + +functions: + // add to prediction any entities that this entity depends on + void AddDependentsToPrediction(void) + { + m_penOwner->AddToPrediction(); + } + void PreMoving() {}; + void DoMoving() { + en_plLastPlacement = GetPlacement(); // remember old placement for lerping + }; + void PostMoving() + { + SetCameraPosition(); + } + CPlacement3D GetLerpedPlacement(void) const + { + FLOAT fLerpFactor; + if (IsPredictor()) { + fLerpFactor = _pTimer->GetLerpFactor(); + } else { + fLerpFactor = _pTimer->GetLerpFactor2(); + } + return LerpPlacementsPrecise(en_plLastPlacement, en_plPlacement, fLerpFactor); + //return CMovableEntity::GetLerpedPlacement(); + } + + // render particles + void RenderParticles(void) + { + if (Particle_GetViewer()==this) { + Particles_ViewerLocal(this); + } + } + + void SetCameraPosition() + { + // 3rd person view + FLOAT fDistance = 1.0f; + CPlacement3D pl = ((CPlayerEntity&) *m_penOwner).en_plViewpoint; + BOOL bFollowCrossHair; + + if (m_iViewType == VT_3RDPERSONVIEW) { + // little above player eyes so it can be seen where he is firing + pl.pl_OrientationAngle(2) -= 12.0f; //10.0f; + pl.pl_PositionVector(2) += 1.0f; + fDistance = 4.2f;//5.75f; + bFollowCrossHair = TRUE; + // death + } else if (m_iViewType == VT_PLAYERDEATH) { + fDistance = 3.5f; + bFollowCrossHair = FALSE; + } + + pl.pl_OrientationAngle(3) = 0.0f; + + // transform rotation angle + pl.RelativeToAbsolute(m_penOwner->GetPlacement()); + // make base placement to back out from + FLOAT3D vBase; + EntityInfo *pei= (EntityInfo*) (m_penOwner->GetEntityInfo()); + GetEntityInfoPosition(m_penOwner, pei->vSourceCenter, vBase); + + // create a set of rays to test + FLOATmatrix3D m; + MakeRotationMatrixFast(m, pl.pl_OrientationAngle); + FLOAT3D vRight = m.GetColumn(1); + FLOAT3D vUp = m.GetColumn(2); + FLOAT3D vFront = m.GetColumn(3); + + FLOAT3D vDest[5]; + vDest[0] = vBase+vFront*fDistance+vUp*1.0f; + vDest[1] = vBase+vFront*fDistance-vUp*1.0f; + vDest[2] = vBase+vFront*fDistance+vRight*1.0f; + vDest[3] = vBase+vFront*fDistance-vRight*1.0f; + vDest[4] = vBase+vFront*fDistance; + + FLOAT fBack = 0; + // for each ray + for (INDEX i=0; i<5; i++) { + // cast a ray to find if any brush is hit + CCastRay crRay( m_penOwner, vBase, vDest[i]); + crRay.cr_bHitTranslucentPortals = FALSE; + crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX; + GetWorld()->CastRay(crRay); + + // if hit something + if (crRay.cr_penHit!=NULL) { + // clamp distance + fDistance = Min(fDistance, crRay.cr_fHitDistance-0.5f); + // if hit polygon + if (crRay.cr_pbpoBrushPolygon!=NULL) { + // back off + FLOAT3D vDir = (vDest[i]-vBase).Normalize(); + FLOAT fD = Abs(FLOAT3D(crRay.cr_pbpoBrushPolygon->bpo_pbplPlane->bpl_plAbsolute)%vDir)*0.25f; + fBack = Max(fBack, fD); + } + } + + } + fDistance = ClampDn(fDistance-fBack, 0.0f); + m_fDistance = fDistance; + vBase += vFront*fDistance; + + CPlayerWeapons *ppw = ((CPlayer&) *m_penOwner).GetPlayerWeapons(); + if (bFollowCrossHair) { + FLOAT3D vTarget = vBase-ppw->m_vRayHit; + FLOAT fLen = vTarget.Length(); + if (fLen>0.01) { + vTarget/=fLen; + } else { + vTarget = FLOAT3D(0,1,0); + } + + FLOAT3D vX; + FLOAT3D vY = m.GetColumn(2); + FLOAT3D vZ = vTarget; + vZ.Normalize(); + + if (Abs(vY%vZ)>0.9f) { + vY = -m.GetColumn(3); + } + + vX = vY*vZ; + vX.Normalize(); + vY = vZ*vX; + vY.Normalize(); + m_vZLast = vZ; + + m(1,1) = vX(1); m(1,2) = vY(1); m(1,3) = vZ(1); + m(2,1) = vX(2); m(2,2) = vY(2); m(2,3) = vZ(2); + m(3,1) = vX(3); m(3,2) = vY(3); m(3,3) = vZ(3); + DecomposeRotationMatrixNoSnap(pl.pl_OrientationAngle, m); + } + + if (m_bFixed) { + pl.pl_PositionVector = GetPlacement().pl_PositionVector; + pl.pl_OrientationAngle = ANGLE3D(0,-90, 0); + m_fDistance = (pl.pl_PositionVector-m_penOwner->GetPlacement().pl_PositionVector).Length(); + MakeRotationMatrixFast(m, pl.pl_OrientationAngle); + } else { + pl.pl_PositionVector = vBase; + } + + // set camera placement + SetPlacement_internal(pl, m, TRUE); // TRUE = try to optimize for small movements + }; + + /*void SetCameraPosition() + { + // 3rd person view + FLOAT fDistance = 1.0f; + CPlacement3D pl = ((CPlayerEntity&) *m_penOwner).en_plViewpoint; + + pl.pl_PositionVector += FLOAT3D(tmp_af[4],tmp_af[5],tmp_af[6]); + pl.pl_OrientationAngle = ANGLE3D(0.0f, tmp_af[1], 0.0f); + fDistance = tmp_af[5]; + + // transform rotation angle + pl.RelativeToAbsolute(m_penOwner->GetPlacement()); + + // create a set ray to test + FLOATmatrix3D m; + MakeRotationMatrixFast(m, pl.pl_OrientationAngle); + FLOAT3D vRight = m.GetColumn(1); + FLOAT3D vUp = m.GetColumn(2); + FLOAT3D vFront = m.GetColumn(3); + + FLOAT3D vDest; + vDest = vFront*fDistance; + + //FLOAT fBack = 0; + /* + // cast a ray to find if any brush is hit + CCastRay crRay( m_penOwner, pl.pl_PositionVector, vDest); + crRay.cr_bHitTranslucentPortals = FALSE; + crRay.cr_ttHitModels = CCastRay::TT_NONE; + GetWorld()->CastRay(crRay); + + // if hit something + if (crRay.cr_penHit!=NULL) { + // clamp distance + fDistance = Min(fDistance, crRay.cr_fHitDistance-0.5f); + } + //pl.pl_PositionVector += FLOAT3D(0.0f, m_fDistance, 0.0f)*m; + */ + /* + m_fDistance = fDistance; + + // set camera placement + SetPlacement_internal(pl, m, TRUE); // TRUE = try to optimize for small movements + };*/ + + +procedures: + + Main(EViewInit eInit) { + // remember the initial parameters + ASSERT(eInit.penOwner!=NULL); + m_penOwner = eInit.penOwner; + m_iViewType = eInit.vtView; + m_bFixed = eInit.bDeathFixed; + ASSERT(IsOfClass(m_penOwner, "Player")); + + // init as model + InitAsEditorModel(); + SetFlags(GetFlags()|ENF_CROSSESLEVELS); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL|EPF_MOVABLE); + SetCollisionFlags(ECF_IMMATERIAL); + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + // add to movers list if needed + if (m_iViewType == VT_PLAYERDEATH) { + AddToMovers(); + } + + SendEvent(EStart()); + wait() { + on (EBegin) : { resume; } + on (EStart) : { + SetCameraPosition(); + en_plLastPlacement = GetPlacement(); // remember old placement for lerping + m_vTargetLast = ((CPlayer&) *m_penOwner).GetPlayerWeapons()->m_vRayHit; + resume; + }; + on (EEnd) : { stop; } + otherwise() : { resume; } + } + // cease to exist + Destroy(); + + return; + }; +}; + diff --git a/Sources/EntitiesMP/PlayerView.h b/Sources/EntitiesMP/PlayerView.h new file mode 100644 index 0000000..6a42e63 --- /dev/null +++ b/Sources/EntitiesMP/PlayerView.h @@ -0,0 +1,67 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_PlayerView_INCLUDED +#define _EntitiesMP_PlayerView_INCLUDED 1 +extern DECL_DLL CEntityPropertyEnumType ViewType_enum; +enum ViewType { + VT_PLAYERDEATH = 0, + VT_PLAYERREBIRTH = 1, + VT_CAMERA = 2, + VT_3RDPERSONVIEW = 3, +}; +DECL_DLL inline void ClearToDefault(ViewType &e) { e = (ViewType)0; } ; +#define EVENTCODE_EViewInit 0x01930000 +class DECL_DLL EViewInit : public CEntityEvent { +public: +EViewInit(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOwner; +CEntityPointer penCamera; +enum ViewType vtView; +BOOL bDeathFixed; +}; +DECL_DLL inline void ClearToDefault(EViewInit &e) { e = EViewInit(); } ; +extern "C" DECL_DLL CDLLEntityClass CPlayerView_DLLClass; +class DECL_DLL CPlayerView : public CMovableEntity { +public: +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + virtual void SetDefaultProperties(void); + CEntityPointer m_penOwner; + INDEX m_iViewType; + FLOAT m_fDistance; + FLOAT3D m_vZLast; + FLOAT3D m_vTargetLast; + BOOL m_bFixed; + CEntityPointer m_penPrediction; + +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void AddDependentsToPrediction(void); + +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void PreMoving(); + +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void DoMoving(); + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void PostMoving(); + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +CPlacement3D GetLerpedPlacement(void)const; + +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void RenderParticles(void); + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +void SetCameraPosition(); +#define STATE_CPlayerView_Main 1 + BOOL +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01930001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01930002_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_PlayerView_INCLUDED diff --git a/Sources/EntitiesMP/PlayerView_tables.h b/Sources/EntitiesMP/PlayerView_tables.h new file mode 100644 index 0000000..20881a0 --- /dev/null +++ b/Sources/EntitiesMP/PlayerView_tables.h @@ -0,0 +1,51 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(ViewType) + EP_ENUMVALUE(VT_PLAYERDEATH, ""), + EP_ENUMVALUE(VT_PLAYERREBIRTH, ""), + EP_ENUMVALUE(VT_CAMERA, ""), + EP_ENUMVALUE(VT_3RDPERSONVIEW, ""), +EP_ENUMEND(ViewType); + +#define ENTITYCLASS CPlayerView + +CEntityProperty CPlayerView_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000193<<8)+1, offsetof(CPlayerView, m_penOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000193<<8)+2, offsetof(CPlayerView, m_iViewType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000193<<8)+3, offsetof(CPlayerView, m_fDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000193<<8)+4, offsetof(CPlayerView, m_vZLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000193<<8)+5, offsetof(CPlayerView, m_vTargetLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000193<<8)+6, offsetof(CPlayerView, m_bFixed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000193<<8)+255, offsetof(CPlayerView, m_penPrediction), "", 0, 0, 0), +}; +#define CPlayerView_propertiesct ARRAYCOUNT(CPlayerView_properties) + +CEntityComponent CPlayerView_components[] = { +#define MODEL_MARKER ((0x00000193<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_MARKER ((0x00000193<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Vector.tex"), +}; +#define CPlayerView_componentsct ARRAYCOUNT(CPlayerView_components) + +CEventHandlerEntry CPlayerView_handlers[] = { + {1, -1, CEntity::pEventHandler(&CPlayerView:: +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/PlayerView.es" +Main),DEBUGSTRING("CPlayerView::Main")}, + {0x01930001, -1, CEntity::pEventHandler(&CPlayerView::H0x01930001_Main_01), DEBUGSTRING("CPlayerView::H0x01930001_Main_01")}, + {0x01930002, -1, CEntity::pEventHandler(&CPlayerView::H0x01930002_Main_02), DEBUGSTRING("CPlayerView::H0x01930002_Main_02")}, +}; +#define CPlayerView_handlersct ARRAYCOUNT(CPlayerView_handlers) + +CEntity *CPlayerView_New(void) { return new CPlayerView; }; +void CPlayerView_OnInitClass(void) {}; +void CPlayerView_OnEndClass(void) {}; +void CPlayerView_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPlayerView_OnWorldEnd(CWorld *pwo) {}; +void CPlayerView_OnWorldInit(CWorld *pwo) {}; +void CPlayerView_OnWorldTick(CWorld *pwo) {}; +void CPlayerView_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPlayerView, CMovableEntity, "Player View", "", 0x00000193); +DECLARE_CTFILENAME(_fnmCPlayerView_tbn, ""); diff --git a/Sources/EntitiesMP/PlayerWeapons.cpp b/Sources/EntitiesMP/PlayerWeapons.cpp new file mode 100644 index 0000000..538715b --- /dev/null +++ b/Sources/EntitiesMP/PlayerWeapons.cpp @@ -0,0 +1,7951 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" + +#include "StdH.h" +#include "GameMP/SEColors.h" + +#include + +#include "EntitiesMP/Player.h" +#include "EntitiesMP/Bullet.h" +#include "Models/Weapons/Knife/Knife.h" +#include "Models/Weapons/Knife/KnifeItem.h" +#include "Models/Weapons/Colt/Colt.h" +#include "Models/Weapons/Colt/ColtMain.h" +#include "Models/Weapons/SingleShotgun/SingleShotgun.h" +#include "Models/Weapons/SingleShotgun/Barrels.h" +#include "Models/Weapons/DoubleShotgun/DoubleShotgun.h" +#include "Models/Weapons/DoubleShotgun/Dshotgunbarrels.h" +#include "Models/Weapons/DoubleShotgun/HandWithAmmo.h" +#include "Models/Weapons/TommyGun/TommyGun.h" +#include "Models/Weapons/TommyGun/Body.h" +#include "Models/Weapons/MiniGun/MiniGun.h" +#include "Models/Weapons/MiniGun/Body.h" +#include "Models/Weapons/GrenadeLauncher/GrenadeLauncher.h" +#include "Models/Weapons/RocketLauncher/RocketLauncher.h" +#include "Models/Weapons/Laser/Laser.h" +#include "Models/Weapons/Laser/Barrel.h" +#include "Models/Weapons/Cannon/Cannon.h" +#include "Models/Weapons/Cannon/Body.h" +// Mission Pack weapons +#include "ModelsMP/Weapons/Sniper/Sniper.h" +#include "ModelsMP/Weapons/Sniper/Body.h" +#include "ModelsMP/Weapons/Flamer/Flamer.h" +#include "ModelsMP/Weapons/Flamer/Body.h" +#include "ModelsMP/Weapons/Flamer/FuelReservoir.h" +#include "ModelsMP/Weapons/Flamer/Flame.h" +#include "ModelsMP/Weapons/Chainsaw/Chainsaw.h" +#include "ModelsMP/Weapons/Chainsaw/ChainSawForPlayer.h" +#include "ModelsMP/Weapons/Chainsaw/Body.h" +#include "ModelsMP/Weapons/Chainsaw/Blade.h" +#include "ModelsMP/Weapons/Chainsaw/Teeth.h" + +// Mission Pack player body instead of the old one +#include "ModelsMP/Player/SeriousSam/Body.h" +#include "ModelsMP/Player/SeriousSam/Player.h" + +#include "EntitiesMP/Switch.h" +#include "EntitiesMP/PlayerView.h" +#include "EntitiesMP/PlayerAnimator.h" +#include "EntitiesMP/MovingBrush.h" +#include "EntitiesMP/MessageHolder.h" +#include "EntitiesMP/EnemyBase.h" +extern INDEX hud_bShowWeapon; + +extern const INDEX aiWeaponsRemap[19] = { 0, 1, 10, 2, 3, 4, 5, 6, 7, + 8, 9, 11, 13, 12, 14, 15, 16, 17, 18 }; + + +#include +#include +CEntityEvent *EWeaponsInit::MakeCopy(void) { CEntityEvent *peeCopy = new EWeaponsInit(*this); return peeCopy;} +EWeaponsInit::EWeaponsInit() : CEntityEvent(EVENTCODE_EWeaponsInit) {; + ClearToDefault(penOwner); +}; +CEntityEvent *ESelectWeapon::MakeCopy(void) { CEntityEvent *peeCopy = new ESelectWeapon(*this); return peeCopy;} +ESelectWeapon::ESelectWeapon() : CEntityEvent(EVENTCODE_ESelectWeapon) {; + ClearToDefault(iWeapon); +}; +CEntityEvent *EBoringWeapon::MakeCopy(void) { CEntityEvent *peeCopy = new EBoringWeapon(*this); return peeCopy;} +EBoringWeapon::EBoringWeapon() : CEntityEvent(EVENTCODE_EBoringWeapon) {; +}; +CEntityEvent *EFireWeapon::MakeCopy(void) { CEntityEvent *peeCopy = new EFireWeapon(*this); return peeCopy;} +EFireWeapon::EFireWeapon() : CEntityEvent(EVENTCODE_EFireWeapon) {; +}; +CEntityEvent *EReleaseWeapon::MakeCopy(void) { CEntityEvent *peeCopy = new EReleaseWeapon(*this); return peeCopy;} +EReleaseWeapon::EReleaseWeapon() : CEntityEvent(EVENTCODE_EReleaseWeapon) {; +}; +CEntityEvent *EReloadWeapon::MakeCopy(void) { CEntityEvent *peeCopy = new EReloadWeapon(*this); return peeCopy;} +EReloadWeapon::EReloadWeapon() : CEntityEvent(EVENTCODE_EReloadWeapon) {; +}; +CEntityEvent *EWeaponChanged::MakeCopy(void) { CEntityEvent *peeCopy = new EWeaponChanged(*this); return peeCopy;} +EWeaponChanged::EWeaponChanged() : CEntityEvent(EVENTCODE_EWeaponChanged) {; +}; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" + +// AVAILABLE WEAPON MASK +#define WEAPONS_ALLAVAILABLEMASK 0x3FFF + +/* +#if BUILD_TEST + #define WEAPONS_DISABLEDMASK (\ + (1<<(WEAPON_TOMMYGUN -1))|\ + (1<<(WEAPON_GRENADELAUNCHER-1))|\ + (1<<(WEAPON_PIPEBOMB -1))|\ + (1<<(WEAPON_FLAMER -1))|\ + (1<<(WEAPON_LASER -1))|\ + (1<<(WEAPON_GHOSTBUSTER -1))|\ + (1<<(WEAPON_IRONCANNON -1))|\ + (1<<(WEAPON_NUKECANNON -1))) +#else + #define WEAPONS_DISABLEDMASK (0) +#endif + */ + +#define MAX_WEAPONS 30 + + +// MiniGun specific +#define MINIGUN_STATIC 0 +#define MINIGUN_FIRE 1 +#define MINIGUN_SPINUP 2 +#define MINIGUN_SPINDOWN 3 + +#define MINIGUN_SPINUPTIME 0.5f +#define MINIGUN_SPINDNTIME 3.0f +#define MINIGUN_SPINUPSOUND 0.5f +#define MINIGUN_SPINDNSOUND 1.5f +#define MINIGUN_FULLSPEED 500.0f +#define MINIGUN_SPINUPACC (MINIGUN_FULLSPEED/MINIGUN_SPINUPTIME) +#define MINIGUN_SPINDNACC (MINIGUN_FULLSPEED/MINIGUN_SPINDNTIME) +#define MINIGUN_TICKTIME (_pTimer->TickQuantum) + +// chainsaw specific +#define CHAINSAW_UPDATETIME 0.05f + +// fire flare specific +#define FLARE_REMOVE 1 +#define FLARE_ADD 2 + +// animation light specific +#define LIGHT_ANIM_MINIGUN 2 +#define LIGHT_ANIM_TOMMYGUN 3 +#define LIGHT_ANIM_COLT_SHOTGUN 4 +#define LIGHT_ANIM_NONE 5 + + +// mana for ammo adjustment (multiplier) +#define MANA_AMMO (0.1f) + +// position of weapon model -- weapon 0 is never used +static FLOAT wpn_fH[MAX_WEAPONS+1]; +static FLOAT wpn_fP[MAX_WEAPONS+1]; +static FLOAT wpn_fB[MAX_WEAPONS+1]; +static FLOAT wpn_fX[MAX_WEAPONS+1]; +static FLOAT wpn_fY[MAX_WEAPONS+1]; +static FLOAT wpn_fZ[MAX_WEAPONS+1]; +static FLOAT wpn_fFOV[MAX_WEAPONS+1]; +static FLOAT wpn_fClip[MAX_WEAPONS+1]; +static FLOAT wpn_fFX[MAX_WEAPONS+1]; // firing source +static FLOAT wpn_fFY[MAX_WEAPONS+1]; +//static FLOAT wpn_fFZ[MAX_WEAPONS+1]; +static INDEX wpn_iCurrent; +extern FLOAT hud_tmWeaponsOnScreen; +extern FLOAT wpn_fRecoilSpeed[17]; +extern FLOAT wpn_fRecoilLimit[17]; +extern FLOAT wpn_fRecoilDampUp[17]; +extern FLOAT wpn_fRecoilDampDn[17]; +extern FLOAT wpn_fRecoilOffset[17]; +extern FLOAT wpn_fRecoilFactorP[17]; +extern FLOAT wpn_fRecoilFactorZ[17]; + +// bullet positions +static FLOAT afSingleShotgunPellets[] = +{ -0.3f,+0.1f, +0.0f,+0.1f, +0.3f,+0.1f, + -0.4f,-0.1f, -0.1f,-0.1f, +0.1f,-0.1f, +0.4f,-0.1f +}; +static FLOAT afDoubleShotgunPellets[] = +{ + -0.3f,+0.15f, +0.0f,+0.15f, +0.3f,+0.15f, + -0.4f,+0.05f, -0.1f,+0.05f, +0.1f,+0.05f, +0.4f,+0.05f, + -0.3f,-0.05f, +0.0f,-0.05f, +0.3f,-0.05f, + -0.4f,-0.15f, -0.1f,-0.15f, +0.1f,-0.15f, +0.4f,-0.15f +}; + +// sniper discrete zoom values - 4 (1x,2x,4x,6x) +// synchronize this with sniper properties (properties 233-237) +static INDEX iSniperDiscreteZoomLevels = 4; +static FLOAT afSniperZoom[] = +{ + 90.0f,1.0f, 53.1f, 2.0f, 28.0f,4.0f, 14.2f,6.0f, + //7.2f,8.0f, 3.56f,10.0f ,1.8f,12.0f +}; + +// crosshair console variables +static INDEX hud_bCrosshairFixed = FALSE; +static INDEX hud_bCrosshairColoring = TRUE; +static FLOAT hud_fCrosshairScale = 1.0f; +static FLOAT hud_fCrosshairOpacity = 1.0f; +static FLOAT hud_fCrosshairRatio = 0.5f; // max distance size ratio +// misc HUD vars +static INDEX hud_bShowPlayerName = TRUE; +static INDEX hud_bShowCoords = FALSE; +static FLOAT plr_tmSnoopingDelay = 1.0f; // seconds +extern FLOAT plr_tmSnoopingTime = 1.0f; // seconds + +// some static vars +static INDEX _iLastCrosshairType=-1; +static CTextureObject _toCrosshair; + +// must do this to keep dependency catcher happy +CTFileName fn1 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair1.tex"); +CTFileName fn2 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair2.tex"); +CTFileName fn3 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair3.tex"); +CTFileName fn4 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair4.tex"); +CTFileName fn5 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair5.tex"); +CTFileName fn6 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair6.tex"); +CTFileName fn7 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair7.tex"); + +void CPlayerWeapons_Precache(ULONG ulAvailable) +{ + CDLLEntityClass *pdec = &CPlayerWeapons_DLLClass; + + // precache general stuff always + pdec->PrecacheTexture(TEX_REFL_BWRIPLES01 ); + pdec->PrecacheTexture(TEX_REFL_BWRIPLES02 ); + pdec->PrecacheTexture(TEX_REFL_LIGHTMETAL01 ); + pdec->PrecacheTexture(TEX_REFL_LIGHTBLUEMETAL01); + pdec->PrecacheTexture(TEX_REFL_DARKMETAL ); + pdec->PrecacheTexture(TEX_REFL_PURPLE01 ); + pdec->PrecacheTexture(TEX_SPEC_WEAK ); + pdec->PrecacheTexture(TEX_SPEC_MEDIUM ); + pdec->PrecacheTexture(TEX_SPEC_STRONG ); + pdec->PrecacheTexture(TEXTURE_HAND ); + pdec->PrecacheTexture(TEXTURE_FLARE01 ); + pdec->PrecacheModel(MODEL_FLARE01); + pdec->PrecacheClass(CLASS_BULLET); + pdec->PrecacheSound(SOUND_SILENCE); + + // precache other weapons if available + if ( ulAvailable&(1<<(WEAPON_KNIFE-1)) ) { + pdec->PrecacheModel(MODEL_KNIFE ); + pdec->PrecacheModel(MODEL_KNIFEITEM ); + pdec->PrecacheTexture(TEXTURE_KNIFEITEM ); + pdec->PrecacheSound(SOUND_KNIFE_BACK ); + pdec->PrecacheSound(SOUND_KNIFE_HIGH ); + pdec->PrecacheSound(SOUND_KNIFE_LONG ); + pdec->PrecacheSound(SOUND_KNIFE_LOW ); + } + + if ( ulAvailable&(1<<(WEAPON_COLT-1)) ) { + pdec->PrecacheModel(MODEL_COLT ); + pdec->PrecacheModel(MODEL_COLTCOCK ); + pdec->PrecacheModel(MODEL_COLTMAIN ); + pdec->PrecacheModel(MODEL_COLTBULLETS ); + pdec->PrecacheTexture(TEXTURE_COLTMAIN ); + pdec->PrecacheTexture(TEXTURE_COLTCOCK ); + pdec->PrecacheTexture(TEXTURE_COLTBULLETS ); + pdec->PrecacheSound(SOUND_COLT_FIRE ); + pdec->PrecacheSound(SOUND_COLT_RELOAD ); + } + + if ( ulAvailable&(1<<(WEAPON_SINGLESHOTGUN-1)) ) { + pdec->PrecacheModel(MODEL_SINGLESHOTGUN ); + pdec->PrecacheModel(MODEL_SS_SLIDER ); + pdec->PrecacheModel(MODEL_SS_HANDLE ); + pdec->PrecacheModel(MODEL_SS_BARRELS ); + pdec->PrecacheTexture(TEXTURE_SS_HANDLE ); + pdec->PrecacheTexture(TEXTURE_SS_BARRELS ); + pdec->PrecacheSound(SOUND_SINGLESHOTGUN_FIRE); + } + + if ( ulAvailable&(1<<(WEAPON_DOUBLESHOTGUN-1)) ) { + pdec->PrecacheModel(MODEL_DOUBLESHOTGUN ); + pdec->PrecacheModel(MODEL_DS_HANDLE ); + pdec->PrecacheModel(MODEL_DS_BARRELS ); + pdec->PrecacheModel(MODEL_DS_AMMO ); + pdec->PrecacheModel(MODEL_DS_SWITCH ); + pdec->PrecacheModel(MODEL_DS_HANDWITHAMMO ); + pdec->PrecacheTexture(TEXTURE_DS_HANDLE ); + pdec->PrecacheTexture(TEXTURE_DS_BARRELS ); + pdec->PrecacheTexture(TEXTURE_DS_AMMO ); + pdec->PrecacheTexture(TEXTURE_DS_SWITCH ); + pdec->PrecacheSound(SOUND_DOUBLESHOTGUN_FIRE ); + pdec->PrecacheSound(SOUND_DOUBLESHOTGUN_RELOAD ); + } + + if ( ulAvailable&(1<<(WEAPON_TOMMYGUN-1)) ) { + pdec->PrecacheModel(MODEL_TOMMYGUN ); + pdec->PrecacheModel(MODEL_TG_BODY ); + pdec->PrecacheModel(MODEL_TG_SLIDER ); + pdec->PrecacheTexture(TEXTURE_TG_BODY ); + pdec->PrecacheSound(SOUND_TOMMYGUN_FIRE ); + } + + if ( ulAvailable&(1<<(WEAPON_SNIPER-1)) ) { + pdec->PrecacheModel(MODEL_SNIPER ); + pdec->PrecacheModel(MODEL_SNIPER_BODY ); + pdec->PrecacheTexture(TEXTURE_SNIPER_BODY ); + pdec->PrecacheSound(SOUND_SNIPER_FIRE ); + } + + if ( ulAvailable&(1<<(WEAPON_MINIGUN-1)) ) { + pdec->PrecacheModel(MODEL_MINIGUN ); + pdec->PrecacheModel(MODEL_MG_BARRELS ); + pdec->PrecacheModel(MODEL_MG_BODY ); + pdec->PrecacheModel(MODEL_MG_ENGINE ); + pdec->PrecacheTexture(TEXTURE_MG_BODY ); + pdec->PrecacheTexture(TEXTURE_MG_BARRELS ); + pdec->PrecacheSound(SOUND_MINIGUN_FIRE ); + pdec->PrecacheSound(SOUND_MINIGUN_ROTATE ); + pdec->PrecacheSound(SOUND_MINIGUN_SPINUP ); + pdec->PrecacheSound(SOUND_MINIGUN_SPINDOWN ); + pdec->PrecacheSound(SOUND_MINIGUN_CLICK ); + } + + if ( ulAvailable&(1<<(WEAPON_ROCKETLAUNCHER-1)) ) { + pdec->PrecacheModel(MODEL_ROCKETLAUNCHER ); + pdec->PrecacheModel(MODEL_RL_BODY ); + pdec->PrecacheModel(MODEL_RL_ROTATINGPART ); + pdec->PrecacheModel(MODEL_RL_ROCKET ); + pdec->PrecacheTexture(TEXTURE_RL_BODY ); + pdec->PrecacheTexture(TEXTURE_RL_ROCKET ); + pdec->PrecacheSound(SOUND_ROCKETLAUNCHER_FIRE); + pdec->PrecacheClass(CLASS_PROJECTILE, PRT_ROCKET); + } + + if ( ulAvailable&(1<<(WEAPON_GRENADELAUNCHER-1)) ) { + pdec->PrecacheModel(MODEL_GRENADELAUNCHER ); + pdec->PrecacheModel(MODEL_GL_BODY ); + pdec->PrecacheModel(MODEL_GL_MOVINGPART ); + pdec->PrecacheModel(MODEL_GL_GRENADE ); + pdec->PrecacheTexture(TEXTURE_GL_BODY ); + pdec->PrecacheTexture(TEXTURE_GL_MOVINGPART ); + pdec->PrecacheSound(SOUND_GRENADELAUNCHER_FIRE ); + pdec->PrecacheClass(CLASS_PROJECTILE, PRT_GRENADE); + } + +/* + if ( ulAvailable&(1<<(WEAPON_PIPEBOMB-1)) ) { + pdec->PrecacheModel(MODEL_PIPEBOMB_STICK ); + pdec->PrecacheModel(MODEL_PIPEBOMB_HAND ); + pdec->PrecacheModel(MODEL_PB_BUTTON ); + pdec->PrecacheModel(MODEL_PB_SHIELD ); + pdec->PrecacheModel(MODEL_PB_STICK ); + pdec->PrecacheModel(MODEL_PB_BOMB ); + pdec->PrecacheTexture(TEXTURE_PB_STICK ); + pdec->PrecacheTexture(TEXTURE_PB_BOMB ); + pdec->PrecacheSound(SOUND_PIPEBOMB_FIRE ); + pdec->PrecacheSound(SOUND_PIPEBOMB_OPEN ); + pdec->PrecacheSound(SOUND_PIPEBOMB_THROW ); + pdec->PrecacheClass(CLASS_PIPEBOMB); + } +*/ + if ( ulAvailable&(1<<(WEAPON_CHAINSAW-1))) { + pdec->PrecacheModel(MODEL_CHAINSAW ); + pdec->PrecacheModel(MODEL_CS_BODY ); + pdec->PrecacheModel(MODEL_CS_BLADE ); + pdec->PrecacheModel(MODEL_CS_TEETH ); + pdec->PrecacheTexture(TEXTURE_CS_BODY ); + pdec->PrecacheTexture(TEXTURE_CS_BLADE ); + pdec->PrecacheTexture(TEXTURE_CS_TEETH ); + pdec->PrecacheSound(SOUND_CS_FIRE ); + pdec->PrecacheSound(SOUND_CS_BEGINFIRE ); + pdec->PrecacheSound(SOUND_CS_ENDFIRE ); + pdec->PrecacheSound(SOUND_CS_BRINGUP ); + pdec->PrecacheSound(SOUND_CS_BRINGDOWN ); + pdec->PrecacheSound(SOUND_CS_IDLE ); + } + + if ( ulAvailable&(1<<(WEAPON_FLAMER-1)) ) { + pdec->PrecacheModel(MODEL_FLAMER ); + pdec->PrecacheModel(MODEL_FL_BODY ); + pdec->PrecacheModel(MODEL_FL_RESERVOIR); + pdec->PrecacheModel(MODEL_FL_FLAME ); + pdec->PrecacheTexture(TEXTURE_FL_BODY ); + pdec->PrecacheTexture(TEXTURE_FL_FLAME); + pdec->PrecacheTexture(TEXTURE_FL_FUELRESERVOIR); + pdec->PrecacheSound(SOUND_FL_FIRE ); + pdec->PrecacheSound(SOUND_FL_START ); + pdec->PrecacheSound(SOUND_FL_STOP ); + pdec->PrecacheClass(CLASS_PROJECTILE, PRT_FLAME); + } + + + if ( ulAvailable&(1<<(WEAPON_LASER-1)) ) { + pdec->PrecacheModel(MODEL_LASER ); + pdec->PrecacheModel(MODEL_LS_BODY ); + pdec->PrecacheModel(MODEL_LS_BARREL ); + pdec->PrecacheTexture(TEXTURE_LS_BODY ); + pdec->PrecacheTexture(TEXTURE_LS_BARREL); + pdec->PrecacheSound(SOUND_LASER_FIRE); + pdec->PrecacheClass(CLASS_PROJECTILE, PRT_LASER_RAY); + } +/* + if ( ulAvailable&(1<<(WEAPON_GHOSTBUSTER-1)) ) { + pdec->PrecacheModel(MODEL_GHOSTBUSTER ); + pdec->PrecacheModel(MODEL_GB_BODY ); + pdec->PrecacheModel(MODEL_GB_ROTATOR ); + pdec->PrecacheModel(MODEL_GB_EFFECT1 ); + pdec->PrecacheModel(MODEL_GB_EFFECT1FLARE ); + pdec->PrecacheTexture(TEXTURE_GB_ROTATOR ); + pdec->PrecacheTexture(TEXTURE_GB_BODY ); + pdec->PrecacheTexture(TEXTURE_GB_LIGHTNING); + pdec->PrecacheTexture(TEXTURE_GB_FLARE ); + pdec->PrecacheSound(SOUND_GB_FIRE ); + pdec->PrecacheClass(CLASS_GHOSTBUSTERRAY); + } + */ + if ( ulAvailable&(1<<(WEAPON_IRONCANNON-1)) /*|| + ulAvailable&(1<<(WEAPON_NUKECANNON-1))*/ ) { + pdec->PrecacheModel(MODEL_CANNON ); + pdec->PrecacheModel(MODEL_CN_BODY ); +// pdec->PrecacheModel(MODEL_CN_NUKEBOX); + pdec->PrecacheTexture(TEXTURE_CANNON); + pdec->PrecacheSound(SOUND_CANNON ); + pdec->PrecacheSound(SOUND_CANNON_PREPARE); + pdec->PrecacheClass(CLASS_CANNONBALL); + } + + // precache animator too + extern void CPlayerAnimator_Precache(ULONG ulAvailable); + CPlayerAnimator_Precache(ulAvailable); +} + +void CPlayerWeapons_Init(void) { + // declare weapon position controls + _pShell->DeclareSymbol("user INDEX wpn_iCurrent;", &wpn_iCurrent); + + #include "Common/WeaponPositions.h" + + // declare crosshair and its coordinates + _pShell->DeclareSymbol("persistent user INDEX hud_bCrosshairFixed;", &hud_bCrosshairFixed); + _pShell->DeclareSymbol("persistent user INDEX hud_bCrosshairColoring;", &hud_bCrosshairColoring); + _pShell->DeclareSymbol("persistent user FLOAT hud_fCrosshairScale;", &hud_fCrosshairScale); + _pShell->DeclareSymbol("persistent user FLOAT hud_fCrosshairRatio;", &hud_fCrosshairRatio); + _pShell->DeclareSymbol("persistent user FLOAT hud_fCrosshairOpacity;", &hud_fCrosshairOpacity); + + _pShell->DeclareSymbol("persistent user INDEX hud_bShowPlayerName;", &hud_bShowPlayerName); + _pShell->DeclareSymbol("persistent user INDEX hud_bShowCoords;", &hud_bShowCoords); + + _pShell->DeclareSymbol("persistent user FLOAT plr_tmSnoopingTime;", &plr_tmSnoopingTime); + _pShell->DeclareSymbol("persistent user FLOAT plr_tmSnoopingDelay;", &plr_tmSnoopingDelay); + + // precache base weapons + CPlayerWeapons_Precache(0x03); +} + +// weapons positions for raycasting and firing +/* +static FLOAT afKnifePos[4] = { -0.01f, 0.25f, 0.0f}; +static FLOAT afColtPos[4] = { -0.01f, 0.1f, 0.0f}; +static FLOAT afDoubleColtPos[4] = { -0.01f, 0.1f, 0.0f}; +static FLOAT afSingleShotgunPos[4] = { 0.0f, 0.1f, 0.0f}; +static FLOAT afDoubleShotgunPos[4] = { 0.0f, 0.1f, 0.0f}; +static FLOAT afTommygunPos[4] = { 0.0f, 0.1f, 0.0f}; +static FLOAT afMinigunPos[4] = { 0.0f, -0.075f, 0.0f}; +static FLOAT afRocketLauncherPos[4] = { -0.175f, 0.19f, -0.23f}; +static FLOAT afGrenadeLauncherPos[4] = { 0.0f, 0.16f, -1.42f}; +static FLOAT afPipebombPos[4] = { 0.01f, 0.04f, -0.44f}; +static FLOAT afFlamerPos[4] = { 0.0f, 0.18f, -0.62f}; +static FLOAT afLaserPos[4] = { 0.0f, -0.095f, -0.65f}; +static FLOAT afGhostBusterPos[4] = { 0.0f, 0.0f, -0.74f}; +static FLOAT afCannonPos[4] = { 0.0f, 0.0f, -0.74f}; +*/ + +// extra weapon positions for shells dropout +static FLOAT afSingleShotgunShellPos[3] = { 0.2f, 0.0f, -0.31f}; +static FLOAT afDoubleShotgunShellPos[3] = { 0.0f, 0.0f, -0.5f}; +static FLOAT afTommygunShellPos[3] = { 0.2f, 0.0f, -0.31f}; +static FLOAT afMinigunShellPos[3] = { 0.2f, 0.0f, -0.31f}; +static FLOAT afMinigunShellPos3rdView[3] = { 0.2f, 0.2f, -0.31f}; +static FLOAT afSniperShellPos[3] = { 0.2f, 0.0f, -0.15f}; + +static FLOAT afRightColtPipe[3] = { 0.07f, -0.05f, -0.26f}; +static FLOAT afSingleShotgunPipe[3] = { 0.2f, 0.0f, -1.25f}; +static FLOAT afDoubleShotgunPipe[3] = { 0.2f, 0.0f, -1.25f}; +static FLOAT afTommygunPipe[3] = { -0.06f, 0.1f, -0.6f}; +static FLOAT afMinigunPipe[3] = { -0.06f, 0.0f, -0.6f}; +static FLOAT afMinigunPipe3rdView[3] = { 0.25f, 0.3f, -2.5f}; + +//static FLOAT afLaserPos[4] = { 0.0f, -0.095f, -0.65f}; +//static FLOAT afLaser1Pos[4] = { -0.115f, -0.05f, -0.65f}; +//static FLOAT afLaser2Pos[4] = { 0.115f, -0.05f, -0.65f}; +//static FLOAT afLaser3Pos[4] = { -0.145f, -0.14f, -0.8f}; +//static FLOAT afLaser4Pos[4] = { 0.145f, -0.14f, -0.8f}; + +#define TM_START m_aMiniGun +#define F_OFFSET_CHG m_aMiniGunLast +#define F_TEMP m_aMiniGunSpeed + +// decrement ammo taking infinite ammo options in account +void DecAmmo(INDEX &ctAmmo, INDEX iDec = 1) +{ + if (!GetSP()->sp_bInfiniteAmmo) { + ctAmmo-=iDec; + } +} + +void CPlayerWeapons::SetDefaultProperties(void) { + m_penPlayer = NULL; + m_bFireWeapon = FALSE ; + m_bHasAmmo = FALSE ; + m_iCurrentWeapon = WEAPON_KNIFE ; + m_iWantedWeapon = WEAPON_KNIFE ; + m_iPreviousWeapon = WEAPON_KNIFE ; + m_iAvailableWeapons = 0x01; + m_bChangeWeapon = FALSE ; + m_bReloadWeapon = FALSE ; + m_bMirrorFire = FALSE ; + m_iAnim = 0; + m_fAnimWaitTime = 0.0f; + m_tmRangeSoundSpawned = 0.0f; + m_bSniperZoom = FALSE ; + m_fSniperFOV = 90.0f; + m_fSniperFOVlast = 90.0f; + m_strLastTarget = ""; + m_tmTargetingStarted = -99.0f; + m_tmLastTarget = -99.0f; + m_tmSnoopingStarted = -99.0f; + m_penTargeting = NULL; + m_moWeapon.SetData(NULL); +m_moWeapon.mo_toTexture.SetData(NULL); + m_moWeaponSecond.SetData(NULL); +m_moWeaponSecond.mo_toTexture.SetData(NULL); + m_tmWeaponChangeRequired = 0.0f; + m_penRayHit = NULL; + m_fRayHitDistance = 100.0f; + m_fEnemyHealth = 0.0f; + m_vRayHit = FLOAT3D(0 , 0 , 0); + m_vRayHitLast = FLOAT3D(0 , 0 , 0); + m_vBulletSource = FLOAT3D(0 , 0 , 0); + m_vBulletTarget = FLOAT3D(0 , 0 , 0); + m_iBullets = 0; + m_iMaxBullets = MAX_BULLETS ; + m_iShells = 0; + m_iMaxShells = MAX_SHELLS ; + m_iRockets = 0; + m_iMaxRockets = MAX_ROCKETS ; + m_iGrenades = 0; + m_iMaxGrenades = MAX_GRENADES ; + m_iNapalm = 0; + m_iMaxNapalm = MAX_NAPALM ; + m_iElectricity = 0; + m_iMaxElectricity = MAX_ELECTRICITY ; + m_iIronBalls = 0; + m_iMaxIronBalls = MAX_IRONBALLS ; + m_iSniperBullets = 0; + m_iMaxSniperBullets = MAX_SNIPERBULLETS ; + m_iKnifeStand = 1; + m_iColtBullets = 6; + m_aMiniGun = 0.0f; + m_aMiniGunLast = 0.0f; + m_aMiniGunSpeed = 0.0f; + m_iLastBulletPosition = FLOAT3D(32000.0f , 32000.0f , 32000.0f); + m_iBulletsOnFireStart = 0; + m_fSniperMaxFOV = 90.0f; + m_fSniperMinFOV = 14.2f; + m_fSnipingZoomSpeed = 2.0f; + m_bSniping = FALSE ; + m_fMinimumZoomFOV = 53.1f; + m_tmLastSniperFire = 0.0f; + m_penFlame = NULL; + m_iLaserBarrel = 0; + m_iFlare = FLARE_REMOVE ; + m_iSecondFlare = FLARE_REMOVE ; + m_fWeaponDrawPowerOld = 0; + m_fWeaponDrawPower = 0; + m_tmDrawStartTime = 0.0f; + m_tmFlamerStart = 1e6; + m_tmFlamerStop = 1e9; + m_tmLastChainsawSpray = 0.0f; + m_penPrediction = NULL; + CRationalEntity::SetDefaultProperties(); +} + +#line 830 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::AddDependentsToPrediction(void) +#line 831 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 832 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_penPlayer -> AddToPrediction (); +#line 835 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_penFlame -> AddToPrediction (); +#line 836 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 837 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::Precache(void) +#line 838 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 839 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayerWeapons_Precache (m_iAvailableWeapons ); +#line 840 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 841 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer * CPlayerWeapons::GetPlayer(void) +#line 842 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 843 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERT (m_penPlayer != NULL ); +#line 844 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return (CPlayer *) & * m_penPlayer ; +#line 845 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 846 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayerAnimator * CPlayerWeapons::GetAnimator(void) +#line 847 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 848 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERT (m_penPlayer != NULL ); +#line 849 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return ((CPlayerAnimator *) & * ((CPlayer &) * m_penPlayer ) . m_penAnimator ); +#line 850 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 852 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * CPlayerWeapons::GetChainSawTeeth(void) +#line 853 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 854 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer * ppl = GetPlayer (); +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(ppl == NULL ){return NULL ;} +#line 856 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmoPlayer = ppl -> GetModelObject (); +#line 857 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pmoPlayer == NULL ){return NULL ;} +#line 858 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CAttachmentModelObject * pamoTorso = pmoPlayer -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ); +#line 859 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pamoTorso == NULL ){return NULL ;} +#line 860 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CAttachmentModelObject * pamoChainSaw = pamoTorso -> amo_moModelObject . GetAttachmentModel (BODY_ATTACHMENT_MINIGUN ); +#line 861 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pamoChainSaw == NULL ){return NULL ;} +#line 862 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CAttachmentModelObject * pamoBlade = pamoChainSaw -> amo_moModelObject . GetAttachmentModel (CHAINSAWFORPLAYER_ATTACHMENT_BLADE ); +#line 863 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pamoBlade == NULL ){return NULL ;} +#line 864 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CAttachmentModelObject * pamoTeeth = pamoBlade -> amo_moModelObject . GetAttachmentModel (BLADE_ATTACHMENT_TEETH ); +#line 865 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pamoTeeth == NULL ){return NULL ;} +#line 866 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return & pamoTeeth -> amo_moModelObject ; +#line 867 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::DoRecoil(void) +#line 871 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 874 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 877 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL CPlayerWeapons::HoldingFire(void) +#line 878 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 879 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_bFireWeapon && ! m_bChangeWeapon ; +#line 880 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 884 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::RenderWeaponModel(CPerspectiveProjection3D & prProjection,CDrawPort * pdp, +#line 885 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vViewerLightDirection,COLOR colViewerLight,COLOR colViewerAmbient, +#line 886 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL bRender,INDEX iEye) +#line 887 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 888 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +_mrpModelRenderPrefs . SetRenderType (RT_TEXTURE | RT_SHADING_PHONG ); +#line 891 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ControlFlareAttachment (); +#line 893 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! bRender || m_iCurrentWeapon == WEAPON_NONE +#line 894 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +|| GetPlayer () -> GetSettings () -> ps_ulFlags & PSF_HIDEWEAPON ){return ;} +#line 897 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iWeaponData = m_iCurrentWeapon ; +#line 900 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fFOV = ((CPerspectiveProjection3D &) prProjection ) . FOVL (); +#line 901 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plView ; +#line 902 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plView = ((CPlayer &) * m_penPlayer ) . en_plViewpoint ; +#line 903 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plView . RelativeToAbsolute (m_penPlayer -> GetPlacement ()); +#line 906 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plWeapon ; +#line 907 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iCurrentWeapon == WEAPON_CHAINSAW ){ +#line 908 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer * plPlayer = (CPlayer *) & * m_penPlayer ; +#line 909 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plWeapon = CPlacement3D (FLOAT3D (wpn_fX [ iWeaponData ] + plPlayer -> m_fChainsawShakeDX * 0.35f , +#line 910 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fY [ iWeaponData ] + plPlayer -> m_fChainsawShakeDY * 0.35f , +#line 911 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fZ [ iWeaponData ]) , +#line 912 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ANGLE3D (AngleDeg (wpn_fH [ iWeaponData ]) , +#line 913 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AngleDeg (wpn_fP [ iWeaponData ]) , +#line 914 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AngleDeg (wpn_fB [ iWeaponData ]))); +#line 915 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 916 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plWeapon = CPlacement3D (FLOAT3D (wpn_fX [ iWeaponData ] , +#line 917 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fY [ iWeaponData ] , +#line 918 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fZ [ iWeaponData ]) , +#line 919 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ANGLE3D (AngleDeg (wpn_fH [ iWeaponData ]) , +#line 920 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AngleDeg (wpn_fP [ iWeaponData ]) , +#line 921 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AngleDeg (wpn_fB [ iWeaponData ]))); +#line 922 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 925 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +UBYTE ubLR , ubLG , ubLB , ubAR , ubAG , ubAB ; +#line 926 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ColorToRGB (colViewerLight , ubLR , ubLG , ubLB ); +#line 927 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ColorToRGB (colViewerAmbient , ubAR , ubAG , ubAB ); +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iMinDL = Min (Min (ubLR , ubLG ) , ubLB ) - 32; +#line 929 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iMinDA = Min (Min (ubAR , ubAG ) , ubAB ) - 32; +#line 930 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iMinDL < 0){ +#line 931 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ubLR = ClampUp (ubLR - iMinDL , (INDEX) 255); +#line 932 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ubLG = ClampUp (ubLG - iMinDL , (INDEX) 255); +#line 933 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ubLB = ClampUp (ubLB - iMinDL , (INDEX) 255); +#line 934 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 935 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iMinDA < 0){ +#line 936 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ubAR = ClampUp (ubAR - iMinDA , (INDEX) 255); +#line 937 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ubAG = ClampUp (ubAG - iMinDA , (INDEX) 255); +#line 938 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ubAB = ClampUp (ubAB - iMinDA , (INDEX) 255); +#line 939 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 940 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const COLOR colLight = RGBToColor (ubLR , ubLG , ubLB ); +#line 941 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const COLOR colAmbient = RGBToColor (ubAR , ubAG , ubAB ); +#line 942 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 944 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +UBYTE ubBlend = INVISIBILITY_ALPHA_LOCAL ; +#line 945 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT tmInvisibility = ((CPlayer *) & * m_penPlayer ) -> m_tmInvisibility ; +#line 948 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(tmInvisibility > tmNow ){ +#line 949 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fIntensity = 0.0f; +#line 950 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if((tmInvisibility - tmNow ) < 3.0f) +#line 951 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 952 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fIntensity = 0.5f - 0.5f * cos ((tmInvisibility - tmNow ) * (6.0f * 3.1415927f / 3.0f)); +#line 953 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ubBlend = (INDEX) (INVISIBILITY_ALPHA_LOCAL + (FLOAT) (254 - INVISIBILITY_ALPHA_LOCAL ) * fIntensity ); +#line 954 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 955 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 960 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iWeaponData == WEAPON_DOUBLECOLT || iWeaponData == WEAPON_DOUBLESHOTGUN ) +#line 961 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 963 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CRenderModel rmMain ; +#line 964 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPerspectiveProjection3D prMirror = prProjection ; +#line 965 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prMirror . ViewerPlacementL () = plView ; +#line 966 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prMirror . FrontClipDistanceL () = wpn_fClip [ iWeaponData ]; +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prMirror . DepthBufferNearL () = 0.0f; +#line 968 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prMirror . DepthBufferFarL () = 0.1f; +#line 969 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plWeaponMirror (FLOAT3D (wpn_fX [ iWeaponData ] , wpn_fY [ iWeaponData ] , wpn_fZ [ iWeaponData ]) , +#line 970 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ANGLE3D (AngleDeg (wpn_fH [ iWeaponData ]) , AngleDeg (wpn_fP [ iWeaponData ]) , +#line 971 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AngleDeg (wpn_fB [ iWeaponData ]))); +#line 972 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iWeaponData == WEAPON_DOUBLECOLT ){ +#line 973 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D mRotation ; +#line 974 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (mRotation , plView . pl_OrientationAngle ); +#line 975 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plWeaponMirror . pl_PositionVector (1) = - plWeaponMirror . pl_PositionVector (1); +#line 976 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plWeaponMirror . pl_OrientationAngle (1) = - plWeaponMirror . pl_OrientationAngle (1); +#line 977 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plWeaponMirror . pl_OrientationAngle (3) = - plWeaponMirror . pl_OrientationAngle (3); +#line 978 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 979 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPerspectiveProjection3D &) prMirror ) . FOVL () = AngleDeg (wpn_fFOV [ iWeaponData ]); +#line 980 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CAnyProjection3D apr ; +#line 981 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +apr = prMirror ; +#line 982 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Stereo_AdjustProjection (* apr , iEye , 0.1f); +#line 983 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BeginModelRenderingView (apr , pdp ); +#line 985 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponMovingOffset (plWeaponMirror . pl_PositionVector ); +#line 986 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plWeaponMirror . RelativeToAbsoluteSmooth (plView ); +#line 987 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . SetObjectPlacement (plWeaponMirror ); +#line 989 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . rm_colLight = colLight ; +#line 990 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . rm_colAmbient = colAmbient ; +#line 991 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . rm_vLightDirection = vViewerLightDirection ; +#line 992 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . rm_ulFlags |= RMF_WEAPON ; +#line 993 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(tmInvisibility > tmNow ){ +#line 994 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . rm_colBlend = (rmMain . rm_colBlend & 0xffffff00) | ubBlend ; +#line 995 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 997 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . SetupModelRendering (rmMain ); +#line 998 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . RenderModel (rmMain ); +#line 999 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EndModelRenderingView (); +#line 1000 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1003 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iWeaponData == WEAPON_MINIGUN ){RotateMinigun ();} +#line 1006 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CRenderModel rmMain ; +#line 1007 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prProjection . ViewerPlacementL () = plView ; +#line 1008 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prProjection . FrontClipDistanceL () = wpn_fClip [ iWeaponData ]; +#line 1009 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prProjection . DepthBufferNearL () = 0.0f; +#line 1010 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prProjection . DepthBufferFarL () = 0.1f; +#line 1011 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPerspectiveProjection3D &) prProjection ) . FOVL () = AngleDeg (wpn_fFOV [ iWeaponData ]); +#line 1013 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CAnyProjection3D apr ; +#line 1014 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +apr = prProjection ; +#line 1015 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Stereo_AdjustProjection (* apr , iEye , 0.1f); +#line 1016 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BeginModelRenderingView (apr , pdp ); +#line 1018 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponMovingOffset (plWeapon . pl_PositionVector ); +#line 1019 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plWeapon . RelativeToAbsoluteSmooth (plView ); +#line 1020 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . SetObjectPlacement (plWeapon ); +#line 1022 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . rm_colLight = colLight ; +#line 1023 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . rm_colAmbient = colAmbient ; +#line 1024 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . rm_vLightDirection = vViewerLightDirection ; +#line 1025 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . rm_ulFlags |= RMF_WEAPON ; +#line 1026 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(tmInvisibility > tmNow ){ +#line 1027 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +rmMain . rm_colBlend = (rmMain . rm_colBlend & 0xffffff00) | ubBlend ; +#line 1028 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1030 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . SetupModelRendering (rmMain ); +#line 1031 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . RenderModel (rmMain ); +#line 1050 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EndModelRenderingView (); +#line 1053 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPerspectiveProjection3D &) prProjection ) . FOVL () = fFOV ; +#line 1054 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1058 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::WeaponMovingOffset(FLOAT3D & plPos) +#line 1059 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1060 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * ((CPlayer &) * m_penPlayer ) . m_penAnimator ; +#line 1061 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fXOffset = Lerp (plan . m_fMoveLastBanking , plan . m_fMoveBanking , _pTimer -> GetLerpFactor ()) * - 0.02f; +#line 1062 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fYOffset = Lerp (plan . m_fWeaponYLastOffset , plan . m_fWeaponYOffset , _pTimer -> GetLerpFactor ()) * 0.15f; +#line 1063 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fYOffset += (fXOffset * fXOffset ) * 30.0f; +#line 1064 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos (1) += fXOffset ; +#line 1065 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos (2) += fYOffset ; +#line 1067 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iCurrentWeapon == WEAPON_GRENADELAUNCHER ) +#line 1068 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1070 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CAttachmentModelObject * amo = m_moWeapon . GetAttachmentModel (GRENADELAUNCHER_ATTACHMENT_MOVING_PART ); +#line 1071 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fLerpedMovement = Lerp (m_fWeaponDrawPowerOld , m_fWeaponDrawPower , _pTimer -> GetLerpFactor ()); +#line 1072 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +amo -> amo_plRelative . pl_PositionVector (3) = fLerpedMovement ; +#line 1073 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos (3) += fLerpedMovement / 2.0f; +#line 1074 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_tmDrawStartTime != 0.0f) +#line 1075 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1076 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT tmPassed = _pTimer -> GetLerpedCurrentTick () - m_tmDrawStartTime ; +#line 1077 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos (1) += Sin (tmPassed * 360.0f * 10) * 0.0125f * tmPassed / 6.0f; +#line 1078 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos (2) += Sin (tmPassed * 270.0f * 8) * 0.01f * tmPassed / 6.0f; +#line 1079 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1080 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1082 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else if((m_iCurrentWeapon == WEAPON_IRONCANNON ) +#line 1083 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +) +#line 1084 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1085 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fLerpedMovement = Lerp (m_fWeaponDrawPowerOld , m_fWeaponDrawPower , _pTimer -> GetLerpFactor ()); +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos (3) += fLerpedMovement ; +#line 1087 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_tmDrawStartTime != 0.0f) +#line 1088 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1089 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT tmPassed = _pTimer -> GetLerpedCurrentTick () - m_tmDrawStartTime ; +#line 1090 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos (1) += Sin (tmPassed * 360.0f * 10) * 0.0125f * tmPassed / 2.0f; +#line 1091 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos (2) += Sin (tmPassed * 270.0f * 8) * 0.01f * tmPassed / 2.0f; +#line 1092 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1093 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1094 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1097 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::CheckTargetPrediction(CEntity * penTarget) +#line 1098 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1100 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! penTarget -> IsPredictable ()){ +#line 1102 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return ; +#line 1103 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1105 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +extern FLOAT cli_tmPredictFoe ; +#line 1106 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +extern FLOAT cli_tmPredictAlly ; +#line 1107 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +extern FLOAT cli_tmPredictEnemy ; +#line 1110 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntity * penMe = GetPlayer (); +#line 1111 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsPredictor ()){ +#line 1112 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penMe = penMe -> GetPredicted (); +#line 1113 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1114 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntity * penYou = penTarget ; +#line 1115 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(penYou -> IsPredictor ()){ +#line 1116 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penYou = penYou -> GetPredicted (); +#line 1117 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1120 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (penYou , "Player")){ +#line 1122 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(GetSP () -> sp_bCooperative ){ +#line 1124 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(cli_tmPredictAlly > 0 && _pNetwork -> IsPlayerLocal (penMe )){ +#line 1126 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penYou -> SetPredictionTime (cli_tmPredictAlly ); +#line 1127 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1129 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1131 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(cli_tmPredictFoe > 0){ +#line 1133 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (penMe )){ +#line 1135 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penYou -> SetPredictionTime (cli_tmPredictFoe ); +#line 1136 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1138 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (penYou )){ +#line 1140 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penMe -> SetPredictionTime (cli_tmPredictFoe ); +#line 1141 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1142 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1143 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1144 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1146 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(cli_tmPredictEnemy > 0 && IsDerivedFromClass (penYou , "Enemy Base")){ +#line 1148 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (penMe )){ +#line 1150 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penYou -> SetPredictionTime (cli_tmPredictEnemy ); +#line 1151 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1152 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1153 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1154 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1157 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::UpdateTargetingInfo(void) +#line 1158 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1160 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plCrosshair ; +#line 1161 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fFX = wpn_fFX [ m_iCurrentWeapon ]; +#line 1162 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fFY = wpn_fFY [ m_iCurrentWeapon ]; +#line 1163 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(GetPlayer () -> m_iViewState == PVT_3RDPERSONVIEW ){ +#line 1164 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fFX = fFY = 0; +#line 1165 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1166 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (fFX , fFY , 0) , plCrosshair , FALSE ); +#line 1168 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CCastRay crRay (m_penPlayer , plCrosshair ); +#line 1169 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 1170 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +crRay . cr_bPhysical = FALSE ; +#line 1171 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +crRay . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ; +#line 1172 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetWorld () -> CastRay (crRay ); +#line 1174 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_vRayHitLast = m_vRayHit ; +#line 1175 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_vRayHit = crRay . cr_vHit ; +#line 1176 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_penRayHit = crRay . cr_penHit ; +#line 1177 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fRayHitDistance = crRay . cr_fHitDistance ; +#line 1178 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fEnemyHealth = 0.0f; +#line 1181 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 1182 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_penRayHit != NULL ) +#line 1183 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1184 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntity * pen = m_penRayHit ; +#line 1186 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pen -> GetFlags () & ENF_ALIVE ) +#line 1187 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1189 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CheckTargetPrediction (pen ); +#line 1192 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (pen , "Player")){ +#line 1194 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_tmTargetingStarted == 0){ +#line 1195 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_penTargeting = pen ; +#line 1196 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmTargetingStarted = tmNow ; +#line 1197 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1199 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fEnemyHealth = ((CPlayer *) pen ) -> GetHealth () / ((CPlayer *) pen ) -> m_fMaxHealth ; +#line 1200 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_strLastTarget . PrintF ("%s" , ((CPlayer *) pen ) -> GetPlayerName ()); +#line 1201 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(GetSP () -> sp_gmGameMode == CSessionProperties :: GM_SCOREMATCH ){ +#line 1203 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CTString strMana = ""; +#line 1204 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +strMana . PrintF (" (%d)" , ((CPlayer *) pen ) -> m_iMana ); +#line 1205 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_strLastTarget += strMana ; +#line 1206 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1207 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(hud_bShowPlayerName ){m_tmLastTarget = tmNow + 1.5f;} +#line 1208 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1210 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else { +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmTargetingStarted = 0; +#line 1213 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1215 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsDerivedFromClass (pen , "Enemy Base")){ +#line 1216 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fEnemyHealth = ((CEnemyBase *) pen ) -> GetHealth () / ((CEnemyBase *) pen ) -> m_fMaxHealth ; +#line 1217 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1219 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bFireWeapon ){m_tmTargetingStarted = 0;} +#line 1220 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1222 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else +#line 1223 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1225 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmTargetingStarted = 0; +#line 1228 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (pen , "Moving Brush") && ((CMovingBrush &) * pen ) . m_penSwitch != NULL ){ +#line 1229 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pen = ((CMovingBrush &) * pen ) . m_penSwitch ; +#line 1230 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1232 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (pen , "Switch") && m_fRayHitDistance < 2.0f){ +#line 1233 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CSwitch & enSwitch = (CSwitch &) * pen ; +#line 1235 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(enSwitch . m_bUseable ){ +#line 1237 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(enSwitch . m_strMessage != ""){m_strLastTarget = enSwitch . m_strMessage ;} +#line 1238 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else {m_strLastTarget = TRANS ("Use");} +#line 1239 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmLastTarget = tmNow + 0.5f; +#line 1240 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1241 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1243 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (pen , "MessageHolder") +#line 1244 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +&& m_fRayHitDistance < ((CMessageHolder *) & * pen ) -> m_fDistance +#line 1245 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +&& ((CMessageHolder *) & * pen ) -> m_bActive ){ +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const CTFileName & fnmMessage = ((CMessageHolder *) & * pen ) -> m_fnmMessage ; +#line 1248 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1249 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! pl . HasMessage (fnmMessage )){ +#line 1251 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_strLastTarget = TRANS ("Analyze"); +#line 1252 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmLastTarget = tmNow + 0.5f; +#line 1253 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1254 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1255 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1256 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1258 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else { +#line 1260 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmTargetingStarted = 0; +#line 1262 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vDir = crRay . cr_vTarget - crRay . cr_vOrigin ; +#line 1263 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDir . Normalize (); +#line 1264 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_vRayHit = crRay . cr_vOrigin + vDir * 50.0f; +#line 1265 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1268 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TIME tmDelta = tmNow - m_tmTargetingStarted ; +#line 1269 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_tmTargetingStarted > 0 && plr_tmSnoopingDelay > 0 && tmDelta > plr_tmSnoopingDelay ){ +#line 1270 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmSnoopingStarted = tmNow ; +#line 1271 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1272 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1277 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::RenderCrosshair(CProjection3D & prProjection,CDrawPort * pdp,CPlacement3D & plViewSource) +#line 1278 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1279 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iCrossHair = GetPlayer () -> GetSettings () -> ps_iCrossHairType + 1; +#line 1282 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iCrossHair <= 0){ +#line 1283 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iCrossHair = 0; +#line 1284 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +_iLastCrosshairType = 0; +#line 1285 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1288 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_iLastCrosshairType != iCrossHair ){ +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +_iLastCrosshairType = iCrossHair ; +#line 1290 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CTString fnCrosshair ; +#line 1291 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnCrosshair . PrintF ("Textures\\Interface\\Crosshairs\\Crosshair%d.tex" , iCrossHair ); +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +try { +#line 1294 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +_toCrosshair . SetData_t (fnCrosshair ); +#line 1295 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}catch (char * strError ){ +#line 1297 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPrintF (strError ); +#line 1298 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iCrossHair = 0; +#line 1299 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return ; +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1301 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1302 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +COLOR colCrosshair = C_WHITE ; +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 1306 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vOnScreen ; +#line 1307 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fDistance = m_fRayHitDistance ; +#line 1309 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT3D vRayHit = m_vRayHit ; +#line 1311 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_penRayHit != NULL ){ +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntity * pen = m_penRayHit ; +#line 1315 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prProjection . ViewerPlacementL () = plViewSource ; +#line 1316 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prProjection . ObjectPlacementL () = CPlacement3D (FLOAT3D (0.0f , 0.0f , 0.0f) , ANGLE3D (0 , 0 , 0)); +#line 1317 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prProjection . Prepare (); +#line 1318 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +prProjection . ProjectCoordinate (vRayHit , vOnScreen ); +#line 1320 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(hud_bCrosshairColoring && m_fEnemyHealth > 0){ +#line 1321 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_fEnemyHealth < 0.25f){colCrosshair = C_RED ;} +#line 1322 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else if(m_fEnemyHealth < 0.60f){colCrosshair = C_YELLOW ;} +#line 1323 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else {colCrosshair = C_GREEN ;} +#line 1324 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1327 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else +#line 1328 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1330 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vOnScreen (1) = (FLOAT) pdp -> GetWidth () * 0.5f; +#line 1331 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vOnScreen (2) = (FLOAT) pdp -> GetHeight () * 0.5f; +#line 1332 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fDistance = 100.0f; +#line 1333 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1336 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(hud_bCrosshairFixed || GetPlayer () -> m_iViewState == PVT_3RDPERSONVIEW ){ +#line 1338 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vOnScreen (1) = (FLOAT) pdp -> GetWidth () * 0.5f; +#line 1339 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vOnScreen (2) = (FLOAT) pdp -> GetHeight () * 0.5f; +#line 1341 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1344 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +hud_fCrosshairScale = Clamp (hud_fCrosshairScale , 0.1f , 2.0f); +#line 1345 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +hud_fCrosshairRatio = Clamp (hud_fCrosshairRatio , 0.1f , 1.0f); +#line 1346 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +hud_fCrosshairOpacity = Clamp (hud_fCrosshairOpacity , 0.1f , 1.0f); +#line 1347 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const ULONG ulAlpha = NormFloatToByte (hud_fCrosshairOpacity ); +#line 1349 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iCrossHair > 0){ +#line 1351 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fMinD = 1.0f; +#line 1352 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fMaxD = 100.0f; +#line 1353 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fDistance = Clamp (fDistance , fMinD , fMaxD ); +#line 1354 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fRatio = (fDistance - fMinD ) / (fMaxD - fMinD ); +#line 1355 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fMaxSize = (FLOAT) pdp -> GetWidth () / 640.0f; +#line 1356 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fMinSize = fMaxSize * hud_fCrosshairRatio ; +#line 1357 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fSize = 16 * Lerp (fMaxSize , fMinSize , fRatio ) * hud_fCrosshairScale ; +#line 1359 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fI0 = + (PIX ) vOnScreen (1) - fSize ; +#line 1360 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fI1 = + (PIX ) vOnScreen (1) + fSize ; +#line 1361 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fJ0 = - (PIX ) vOnScreen (2) - fSize + pdp -> GetHeight (); +#line 1362 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fJ1 = - (PIX ) vOnScreen (2) + fSize + pdp -> GetHeight (); +#line 1363 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pdp -> InitTexture (& _toCrosshair ); +#line 1364 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pdp -> AddTexture (fI0 , fJ0 , fI1 , fJ1 , colCrosshair | ulAlpha ); +#line 1365 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pdp -> FlushRenderingQueue (); +#line 1366 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TIME tmDelta = m_tmLastTarget - tmNow ; +#line 1370 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(tmDelta > 0){ +#line 1372 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SLONG slDPWidth = pdp -> GetWidth (); +#line 1373 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SLONG slDPHeight = pdp -> GetHeight (); +#line 1374 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fScaling = (FLOAT) slDPWidth / 640.0f; +#line 1376 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pdp -> SetFont (_pfdDisplayFont ); +#line 1377 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pdp -> SetTextScaling (fScaling ); +#line 1378 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pdp -> SetTextAspect (1.0f); +#line 1380 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ULONG ulA = (FLOAT) ulAlpha * Clamp (2 * tmDelta , 0.0f , 1.0f); +#line 1381 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pdp -> PutTextC (m_strLastTarget , slDPWidth * 0.5f , slDPHeight * 0.75f , SE_COL_BLUE_NEUTRAL | ulA ); +#line 1382 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1385 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(hud_bShowCoords ){ +#line 1386 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CTString strCoords ; +#line 1387 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SLONG slDPWidth = pdp -> GetWidth (); +#line 1388 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SLONG slDPHeight = pdp -> GetHeight (); +#line 1390 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pdp -> SetFont (_pfdDisplayFont ); +#line 1391 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pdp -> SetTextAspect (1.0f); +#line 1392 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pdp -> SetTextScaling ((FLOAT) slDPWidth / 640.0f); +#line 1394 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fMax = Max (Max (vRayHit (1) , vRayHit (2)) , vRayHit (3)); +#line 1395 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fMin = Min (Min (vRayHit (1) , vRayHit (2)) , vRayHit (3)); +#line 1396 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(fMax < + 100000 && fMin > - 100000){ +#line 1397 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +strCoords . PrintF ("%.0f,%.0f,%.0f" , vRayHit (1) , vRayHit (2) , vRayHit (3)); +#line 1398 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pdp -> PutTextC (strCoords , slDPWidth * 0.5f , slDPHeight * 0.10f , C_WHITE | CT_OPAQUE ); +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1400 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1401 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1409 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::ShowFlare(CModelObject & moWeapon,INDEX iAttachObject,INDEX iAttachFlare,FLOAT fSize) { +#line 1410 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo = & (moWeapon . GetAttachmentModel (iAttachObject ) -> amo_moModelObject ); +#line 1411 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CAttachmentModelObject * pamo = pmo -> GetAttachmentModel (iAttachFlare ); +#line 1412 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pamo -> amo_plRelative . pl_OrientationAngle (3) = (rand () * 360.0f) / RAND_MAX ; +#line 1413 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo = & (pamo -> amo_moModelObject ); +#line 1414 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo -> StretchModel (FLOAT3D (fSize , fSize , fSize )); +#line 1415 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1419 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::HideFlare(CModelObject & moWeapon,INDEX iAttachObject,INDEX iAttachFlare) { +#line 1420 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo = & (moWeapon . GetAttachmentModel (iAttachObject ) -> amo_moModelObject ); +#line 1421 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo = & (pmo -> GetAttachmentModel (iAttachFlare ) -> amo_moModelObject ); +#line 1422 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo -> StretchModel (FLOAT3D (0 , 0 , 0)); +#line 1423 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1425 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::SetFlare(INDEX iFlare,INDEX iAction) +#line 1426 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1428 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! IsPredictionHead ()){ +#line 1430 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return ; +#line 1431 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1434 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayerWeapons * pen = (CPlayerWeapons *) GetPredictionTail (); +#line 1435 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iFlare == 0){ +#line 1436 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pen -> m_iFlare = iAction ; +#line 1437 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pen -> GetPlayer () -> GetPlayerAnimator () -> m_iFlare = iAction ; +#line 1438 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1439 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pen -> m_iSecondFlare = iAction ; +#line 1440 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pen -> GetPlayer () -> GetPlayerAnimator () -> m_iSecondFlare = iAction ; +#line 1441 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1442 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1445 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::ControlFlareAttachment(void) { +#line 1454 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayerWeapons * pen = (CPlayerWeapons *) GetPredictionTail (); +#line 1456 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iCurrentWeapon == WEAPON_DOUBLECOLT ){ +#line 1458 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pen -> m_iSecondFlare == FLARE_ADD ){ +#line 1459 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pen -> m_iSecondFlare = FLARE_REMOVE ; +#line 1460 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShowFlare (m_moWeaponSecond , COLT_ATTACHMENT_COLT , COLTMAIN_ATTACHMENT_FLARE , 1.0f); +#line 1462 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(pen -> m_iSecondFlare == FLARE_REMOVE ){ +#line 1463 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +HideFlare (m_moWeaponSecond , COLT_ATTACHMENT_COLT , COLTMAIN_ATTACHMENT_FLARE ); +#line 1464 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1465 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1468 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pen -> m_iFlare == FLARE_ADD ){ +#line 1469 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pen -> m_iFlare = FLARE_REMOVE ; +#line 1470 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 1471 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : case WEAPON_COLT : +#line 1472 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShowFlare (m_moWeapon , COLT_ATTACHMENT_COLT , COLTMAIN_ATTACHMENT_FLARE , 0.75f); +#line 1473 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1474 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : +#line 1475 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShowFlare (m_moWeapon , SINGLESHOTGUN_ATTACHMENT_BARRELS , BARRELS_ATTACHMENT_FLARE , 1.0f); +#line 1476 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1477 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : +#line 1478 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShowFlare (m_moWeapon , DOUBLESHOTGUN_ATTACHMENT_BARRELS , DSHOTGUNBARRELS_ATTACHMENT_FLARE , 1.75f); +#line 1479 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1480 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : +#line 1481 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShowFlare (m_moWeapon , TOMMYGUN_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE , 0.5f); +#line 1482 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1483 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : +#line 1484 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShowFlare (m_moWeapon , SNIPER_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE , 0.5f); +#line 1485 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1486 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : +#line 1487 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShowFlare (m_moWeapon , MINIGUN_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE , 1.25f); +#line 1488 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1489 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1491 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(pen -> m_iFlare == FLARE_REMOVE ){ +#line 1492 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 1493 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : case WEAPON_COLT : +#line 1494 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +HideFlare (m_moWeapon , COLT_ATTACHMENT_COLT , COLTMAIN_ATTACHMENT_FLARE ); +#line 1495 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1496 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : +#line 1497 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +HideFlare (m_moWeapon , SINGLESHOTGUN_ATTACHMENT_BARRELS , BARRELS_ATTACHMENT_FLARE ); +#line 1498 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1499 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : +#line 1500 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +HideFlare (m_moWeapon , DOUBLESHOTGUN_ATTACHMENT_BARRELS , DSHOTGUNBARRELS_ATTACHMENT_FLARE ); +#line 1501 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1502 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : +#line 1503 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +HideFlare (m_moWeapon , TOMMYGUN_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE ); +#line 1504 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1505 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : +#line 1506 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +HideFlare (m_moWeapon , SNIPER_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE ); +#line 1507 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1508 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : +#line 1509 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +HideFlare (m_moWeapon , MINIGUN_ATTACHMENT_BODY , BODY_ATTACHMENT_FLARE ); +#line 1510 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1511 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1512 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1513 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERT (FALSE ); +#line 1514 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1515 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1519 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::PlayLightAnim(INDEX iAnim,ULONG ulFlags) { +#line 1520 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1521 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pl . m_aoLightAnimation . GetData () != NULL ){ +#line 1522 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_aoLightAnimation . PlayAnim (iAnim , ulFlags ); +#line 1523 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1524 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1528 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::SetCurrentWeaponModel(void) { +#line 1530 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 1531 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_NONE : +#line 1532 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1534 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : +#line 1535 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_KNIFE , TEXTURE_HAND , 0 , 0 , 0); +#line 1536 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , KNIFE_ATTACHMENT_KNIFEITEM , MODEL_KNIFEITEM , +#line 1537 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TEXTURE_KNIFEITEM , TEX_REFL_BWRIPLES02 , TEX_SPEC_WEAK , 0); +#line 1538 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (KNIFE_ANIM_WAIT1 , 0); +#line 1539 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1541 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : { +#line 1542 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeaponSecond , MODEL_COLT , TEXTURE_HAND , 0 , 0 , 0); +#line 1543 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeaponSecond , COLT_ATTACHMENT_BULLETS , MODEL_COLTBULLETS , TEXTURE_COLTBULLETS , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1544 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeaponSecond , COLT_ATTACHMENT_COCK , MODEL_COLTCOCK , TEXTURE_COLTCOCK , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1545 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeaponSecond , COLT_ATTACHMENT_COLT , MODEL_COLTMAIN , TEXTURE_COLTMAIN , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1546 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject & mo = m_moWeaponSecond . GetAttachmentModel (COLT_ATTACHMENT_COLT ) -> amo_moModelObject ; +#line 1547 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , mo , COLTMAIN_ATTACHMENT_FLARE , MODEL_FLARE01 , TEXTURE_FLARE01 , 0 , 0 , 0);} +#line 1548 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . StretchModel (FLOAT3D (- 1 , 1 , 1)); +#line 1549 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . PlayAnim (COLT_ANIM_WAIT1 , 0); +#line 1550 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_COLT : { +#line 1551 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_COLT , TEXTURE_HAND , 0 , 0 , 0); +#line 1552 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , COLT_ATTACHMENT_BULLETS , MODEL_COLTBULLETS , TEXTURE_COLTBULLETS , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1553 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , COLT_ATTACHMENT_COCK , MODEL_COLTCOCK , TEXTURE_COLTCOCK , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1554 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , COLT_ATTACHMENT_COLT , MODEL_COLTMAIN , TEXTURE_COLTMAIN , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1555 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject & mo = m_moWeapon . GetAttachmentModel (COLT_ATTACHMENT_COLT ) -> amo_moModelObject ; +#line 1556 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , mo , COLTMAIN_ATTACHMENT_FLARE , MODEL_FLARE01 , TEXTURE_FLARE01 , 0 , 0 , 0); +#line 1557 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (COLT_ANIM_WAIT1 , 0); +#line 1558 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 1559 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : { +#line 1560 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_SINGLESHOTGUN , TEXTURE_HAND , 0 , 0 , 0); +#line 1561 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , SINGLESHOTGUN_ATTACHMENT_BARRELS , MODEL_SS_BARRELS , TEXTURE_SS_BARRELS , TEX_REFL_DARKMETAL , TEX_SPEC_WEAK , 0); +#line 1562 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , SINGLESHOTGUN_ATTACHMENT_HANDLE , MODEL_SS_HANDLE , TEXTURE_SS_HANDLE , TEX_REFL_DARKMETAL , TEX_SPEC_MEDIUM , 0); +#line 1563 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , SINGLESHOTGUN_ATTACHMENT_SLIDER , MODEL_SS_SLIDER , TEXTURE_SS_BARRELS , TEX_REFL_DARKMETAL , TEX_SPEC_MEDIUM , 0); +#line 1564 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject & mo = m_moWeapon . GetAttachmentModel (SINGLESHOTGUN_ATTACHMENT_BARRELS ) -> amo_moModelObject ; +#line 1565 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , mo , BARRELS_ATTACHMENT_FLARE , MODEL_FLARE01 , TEXTURE_FLARE01 , 0 , 0 , 0); +#line 1566 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (SINGLESHOTGUN_ANIM_WAIT1 , 0); +#line 1567 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 1568 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : { +#line 1569 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_DOUBLESHOTGUN , TEXTURE_HAND , 0 , 0 , 0); +#line 1570 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , DOUBLESHOTGUN_ATTACHMENT_BARRELS , MODEL_DS_BARRELS , TEXTURE_DS_BARRELS , TEX_REFL_BWRIPLES01 , TEX_SPEC_MEDIUM , 0); +#line 1571 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , DOUBLESHOTGUN_ATTACHMENT_HANDLE , MODEL_DS_HANDLE , TEXTURE_DS_HANDLE , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1572 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , DOUBLESHOTGUN_ATTACHMENT_SWITCH , MODEL_DS_SWITCH , TEXTURE_DS_SWITCH , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1573 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , DOUBLESHOTGUN_ATTACHMENT_AMMO , MODEL_DS_AMMO , TEXTURE_DS_AMMO , 0 , 0 , 0); +#line 1574 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeaponSecond , MODEL_DS_HANDWITHAMMO , TEXTURE_HAND , 0 , 0 , 0); +#line 1575 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject & mo = m_moWeapon . GetAttachmentModel (DOUBLESHOTGUN_ATTACHMENT_BARRELS ) -> amo_moModelObject ; +#line 1576 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , mo , DSHOTGUNBARRELS_ATTACHMENT_FLARE , MODEL_FLARE01 , TEXTURE_FLARE01 , 0 , 0 , 0); +#line 1577 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . StretchModel (FLOAT3D (1 , 1 , 1)); +#line 1578 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (DOUBLESHOTGUN_ANIM_WAIT1 , 0); +#line 1579 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 1580 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : { +#line 1581 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_TOMMYGUN , TEXTURE_HAND , 0 , 0 , 0); +#line 1582 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , TOMMYGUN_ATTACHMENT_BODY , MODEL_TG_BODY , TEXTURE_TG_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1583 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , TOMMYGUN_ATTACHMENT_SLIDER , MODEL_TG_SLIDER , TEXTURE_TG_BODY , 0 , TEX_SPEC_MEDIUM , 0); +#line 1584 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject & mo = m_moWeapon . GetAttachmentModel (TOMMYGUN_ATTACHMENT_BODY ) -> amo_moModelObject ; +#line 1585 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , mo , BODY_ATTACHMENT_FLARE , MODEL_FLARE01 , TEXTURE_FLARE01 , 0 , 0 , 0); +#line 1586 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 1587 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : { +#line 1588 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_SNIPER , TEXTURE_SNIPER_BODY , 0 , 0 , 0); +#line 1589 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , SNIPER_ATTACHMENT_BODY , MODEL_SNIPER_BODY , TEXTURE_SNIPER_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1590 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject & mo = m_moWeapon . GetAttachmentModel (SNIPER_ATTACHMENT_BODY ) -> amo_moModelObject ; +#line 1591 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , mo , BODY_ATTACHMENT_FLARE , MODEL_FLARE01 , TEXTURE_FLARE01 , 0 , 0 , 0); +#line 1592 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 1593 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : { +#line 1594 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_MINIGUN , TEXTURE_HAND , 0 , 0 , 0); +#line 1595 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , MINIGUN_ATTACHMENT_BARRELS , MODEL_MG_BARRELS , TEXTURE_MG_BARRELS , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1596 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , MINIGUN_ATTACHMENT_BODY , MODEL_MG_BODY , TEXTURE_MG_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1597 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , MINIGUN_ATTACHMENT_ENGINE , MODEL_MG_ENGINE , TEXTURE_MG_BARRELS , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1598 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject & mo = m_moWeapon . GetAttachmentModel (MINIGUN_ATTACHMENT_BODY ) -> amo_moModelObject ; +#line 1599 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , mo , BODY_ATTACHMENT_FLARE , MODEL_FLARE01 , TEXTURE_FLARE01 , 0 , 0 , 0); +#line 1600 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 1601 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : +#line 1602 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_ROCKETLAUNCHER , TEXTURE_RL_BODY , 0 , 0 , 0); +#line 1603 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , ROCKETLAUNCHER_ATTACHMENT_BODY , MODEL_RL_BODY , TEXTURE_RL_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1604 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , ROCKETLAUNCHER_ATTACHMENT_ROTATINGPART , MODEL_RL_ROTATINGPART , TEXTURE_RL_ROTATINGPART , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1605 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , ROCKETLAUNCHER_ATTACHMENT_ROCKET1 , MODEL_RL_ROCKET , TEXTURE_RL_ROCKET , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1606 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , ROCKETLAUNCHER_ATTACHMENT_ROCKET2 , MODEL_RL_ROCKET , TEXTURE_RL_ROCKET , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1607 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , ROCKETLAUNCHER_ATTACHMENT_ROCKET3 , MODEL_RL_ROCKET , TEXTURE_RL_ROCKET , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1608 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1609 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : +#line 1610 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_GRENADELAUNCHER , TEXTURE_GL_BODY , 0 , 0 , 0); +#line 1611 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , GRENADELAUNCHER_ATTACHMENT_BODY , MODEL_GL_BODY , TEXTURE_GL_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1612 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , GRENADELAUNCHER_ATTACHMENT_MOVING_PART , MODEL_GL_MOVINGPART , TEXTURE_GL_MOVINGPART , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1613 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , GRENADELAUNCHER_ATTACHMENT_GRENADE , MODEL_GL_GRENADE , TEXTURE_GL_MOVINGPART , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1614 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1626 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : +#line 1627 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_FLAMER , TEXTURE_HAND , 0 , 0 , 0); +#line 1628 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , FLAMER_ATTACHMENT_BODY , MODEL_FL_BODY , TEXTURE_FL_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1629 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , FLAMER_ATTACHMENT_FUEL , MODEL_FL_RESERVOIR , TEXTURE_FL_FUELRESERVOIR , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1630 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , FLAMER_ATTACHMENT_FLAME , MODEL_FL_FLAME , TEXTURE_FL_FLAME , 0 , 0 , 0); +#line 1631 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1632 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_CHAINSAW : { +#line 1633 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_CHAINSAW , TEXTURE_HAND , 0 , 0 , 0); +#line 1634 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , CHAINSAW_ATTACHMENT_CHAINSAW , MODEL_CS_BODY , TEXTURE_CS_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1635 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , CHAINSAW_ATTACHMENT_BLADE , MODEL_CS_BLADE , TEXTURE_CS_BLADE , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1636 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo ; +#line 1637 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo = & (m_moWeapon . GetAttachmentModel (CHAINSAW_ATTACHMENT_BLADE ) -> amo_moModelObject ); +#line 1638 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , * pmo , BLADE_ATTACHMENT_TEETH , MODEL_CS_TEETH , TEXTURE_CS_TEETH , 0 , 0 , 0); +#line 1639 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 1640 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : +#line 1641 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_LASER , TEXTURE_HAND , 0 , 0 , 0); +#line 1642 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , LASER_ATTACHMENT_BODY , MODEL_LS_BODY , TEXTURE_LS_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1643 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , LASER_ATTACHMENT_LEFTUP , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1644 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , LASER_ATTACHMENT_LEFTDOWN , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1645 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , LASER_ATTACHMENT_RIGHTUP , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1646 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , LASER_ATTACHMENT_RIGHTDOWN , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1647 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1668 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : +#line 1670 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetComponents (this , m_moWeapon , MODEL_CANNON , TEXTURE_CANNON , 0 , 0 , 0); +#line 1671 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddAttachmentToModel (this , m_moWeapon , CANNON_ATTACHMENT_BODY , MODEL_CN_BODY , TEXTURE_CANNON , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1674 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1675 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1676 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1683 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::RotateMinigun(void) { +#line 1684 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ANGLE aAngle = Lerp (m_aMiniGunLast , m_aMiniGun , _pTimer -> GetLerpFactor ()); +#line 1686 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CAttachmentModelObject * amo = m_moWeapon . GetAttachmentModel (MINIGUN_ATTACHMENT_BARRELS ); +#line 1687 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +amo -> amo_plRelative . pl_OrientationAngle (3) = aAngle ; +#line 1688 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1697 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::CalcWeaponPosition3rdPersonView(FLOAT3D vPos,CPlacement3D & plPos,BOOL bResetZ) { +#line 1698 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 1700 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! m_bMirrorFire ){ +#line 1701 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector = FLOAT3D (wpn_fX [ m_iCurrentWeapon ] , wpn_fY [ m_iCurrentWeapon ] , +#line 1702 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fZ [ m_iCurrentWeapon ]); +#line 1703 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1704 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector = FLOAT3D (- wpn_fX [ m_iCurrentWeapon ] , wpn_fY [ m_iCurrentWeapon ] , +#line 1705 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fZ [ m_iCurrentWeapon ]); +#line 1706 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1708 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! m_bMirrorFire ){ +#line 1709 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0))); +#line 1710 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1711 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0))); +#line 1712 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1713 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (1) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1714 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (2) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1715 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (3) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1717 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(bResetZ ){ +#line 1718 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (3) = 0.0f; +#line 1719 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1722 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plView = ((CPlayer &) * m_penPlayer ) . en_plViewpoint ; +#line 1723 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plView . pl_PositionVector (2) = 1.25118f; +#line 1724 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (plView ); +#line 1725 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (m_penPlayer -> GetPlacement ()); +#line 1726 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1729 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::CalcWeaponPosition(FLOAT3D vPos,CPlacement3D & plPos,BOOL bResetZ) { +#line 1730 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 1732 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! m_bMirrorFire ){ +#line 1733 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector = FLOAT3D (wpn_fX [ m_iCurrentWeapon ] , wpn_fY [ m_iCurrentWeapon ] , +#line 1734 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fZ [ m_iCurrentWeapon ]); +#line 1735 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bSniping ){ +#line 1736 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 1737 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1738 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1739 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector = FLOAT3D (- wpn_fX [ m_iCurrentWeapon ] , wpn_fY [ m_iCurrentWeapon ] , +#line 1740 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fZ [ m_iCurrentWeapon ]); +#line 1741 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1743 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! m_bMirrorFire ){ +#line 1744 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0))); +#line 1745 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1746 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0))); +#line 1747 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1748 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (1) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1749 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (2) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1750 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (3) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1752 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(bResetZ ){ +#line 1753 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (3) = 0.0f; +#line 1754 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1757 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plView = ((CPlayer &) * m_penPlayer ) . en_plViewpoint ; +#line 1758 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plView . pl_PositionVector (2) += ((CPlayerAnimator &) * ((CPlayer &) * m_penPlayer ) . m_penAnimator ) . +#line 1759 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fEyesYOffset ; +#line 1760 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (plView ); +#line 1761 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (m_penPlayer -> GetPlacement ()); +#line 1762 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1765 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::CalcLerpedWeaponPosition(FLOAT3D vPos,CPlacement3D & plPos,BOOL bResetZ) +#line 1766 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1767 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 1769 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! m_bMirrorFire ){ +#line 1770 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector = FLOAT3D (wpn_fX [ m_iCurrentWeapon ] , wpn_fY [ m_iCurrentWeapon ] , +#line 1771 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fZ [ m_iCurrentWeapon ]); +#line 1772 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bSniping ){ +#line 1773 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 1774 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1775 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1776 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector = FLOAT3D (- wpn_fX [ m_iCurrentWeapon ] , wpn_fY [ m_iCurrentWeapon ] , +#line 1777 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fZ [ m_iCurrentWeapon ]); +#line 1778 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1780 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! m_bMirrorFire ){ +#line 1781 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0))); +#line 1782 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1783 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0))); +#line 1784 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1785 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (1) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1786 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (2) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1787 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (3) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1789 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(bResetZ ){ +#line 1790 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (3) = 0.0f; +#line 1791 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1794 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plRes ; +#line 1795 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetPlayer () -> GetLerpedWeaponPosition (plPos . pl_PositionVector , plRes ); +#line 1796 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos = plRes ; +#line 1797 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1800 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::CalcWeaponPositionImprecise(FLOAT3D vPos,CPlacement3D & plPos,BOOL bResetZ,FLOAT fImprecissionAngle) { +#line 1801 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_OrientationAngle = ANGLE3D ((FRnd () - 0.5f) * fImprecissionAngle , (FRnd () - 0.5f) * fImprecissionAngle , 0); +#line 1803 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! m_bMirrorFire ){ +#line 1804 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector = FLOAT3D (wpn_fX [ m_iCurrentWeapon ] , wpn_fY [ m_iCurrentWeapon ] , +#line 1805 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fZ [ m_iCurrentWeapon ]); +#line 1806 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bSniping ){ +#line 1807 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 1808 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1809 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1810 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector = FLOAT3D (- wpn_fX [ m_iCurrentWeapon ] , wpn_fY [ m_iCurrentWeapon ] , +#line 1811 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_fZ [ m_iCurrentWeapon ]); +#line 1812 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1814 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! m_bMirrorFire ){ +#line 1815 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0))); +#line 1816 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 1817 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (CPlacement3D (vPos , ANGLE3D (0 , 0 , 0))); +#line 1818 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1819 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (1) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1820 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (2) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1821 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (3) *= SinFast (wpn_fFOV [ m_iCurrentWeapon ] / 2) / SinFast (90.0f / 2); +#line 1823 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(bResetZ ){ +#line 1824 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . pl_PositionVector (3) = 0.0f; +#line 1825 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1828 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plView = ((CPlayer &) * m_penPlayer ) . en_plViewpoint ; +#line 1829 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plView . pl_PositionVector (2) += ((CPlayerAnimator &) * ((CPlayer &) * m_penPlayer ) . m_penAnimator ) . +#line 1830 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fEyesYOffset ; +#line 1831 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (plView ); +#line 1832 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plPos . RelativeToAbsoluteSmooth (m_penPlayer -> GetPlacement ()); +#line 1833 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1836 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::Setup3DSoundParameters(void) { +#line 1837 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 1840 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (50.0f , 5.0f , 1.0f , 1.0f); +#line 1841 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon1 . Set3DParameters (50.0f , 5.0f , 1.0f , 1.0f); +#line 1842 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon2 . Set3DParameters (50.0f , 5.0f , 1.0f , 1.0f); +#line 1843 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon3 . Set3DParameters (50.0f , 5.0f , 1.0f , 1.0f); +#line 1844 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeaponAmbient . Set3DParameters (30.0f , 3.0f , 0.0f , 1.0f); +#line 1845 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1853 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL CPlayerWeapons::CutWithKnife(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fWide,FLOAT fThickness,FLOAT fDamage) +#line 1854 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1856 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plKnife ; +#line 1857 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (fX , fY , 0) , plKnife , TRUE ); +#line 1860 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT3D & vBase = plKnife . pl_PositionVector ; +#line 1861 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D m ; +#line 1862 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (m , plKnife . pl_OrientationAngle ); +#line 1863 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vRight = m . GetColumn (1) * fWide ; +#line 1864 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp = m . GetColumn (2) * fWide ; +#line 1865 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vFront = - m . GetColumn (3) * fRange ; +#line 1867 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vDest [ 5 ]; +#line 1868 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDest [ 0 ] = vBase + vFront ; +#line 1869 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDest [ 1 ] = vBase + vFront + vUp ; +#line 1870 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDest [ 2 ] = vBase + vFront - vUp ; +#line 1871 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDest [ 3 ] = vBase + vFront + vRight ; +#line 1872 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDest [ 4 ] = vBase + vFront - vRight ; +#line 1874 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntity * penClosest = NULL ; +#line 1875 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fDistance = UpperLimit (0.0f); +#line 1876 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vHit ; +#line 1877 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vDir ; +#line 1879 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +for(INDEX i = 0;i < 5;i ++){ +#line 1881 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CCastRay crRay (m_penPlayer , vBase , vDest [ i ]); +#line 1882 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 1883 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +crRay . cr_fTestR = fThickness ; +#line 1884 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +crRay . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ; +#line 1885 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetWorld () -> CastRay (crRay ); +#line 1888 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(crRay . cr_penHit != NULL && crRay . cr_fHitDistance < fDistance ){ +#line 1889 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penClosest = crRay . cr_penHit ; +#line 1890 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fDistance = crRay . cr_fHitDistance ; +#line 1891 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDir = vDest [ i ] - vBase ; +#line 1892 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vHit = crRay . cr_vHit ; +#line 1894 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(i == 0){ +#line 1895 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(crRay . cr_penHit -> GetRenderType () == RT_BRUSH ) +#line 1896 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1897 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iSurfaceType = crRay . cr_pbpoBrushPolygon -> bpo_bppProperties . bpp_ubSurfaceType ; +#line 1898 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EffectParticlesType eptType = GetParticleEffectTypeForSurface (iSurfaceType ); +#line 1900 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vNormal = crRay . cr_pbpoBrushPolygon -> bpo_pbplPlane -> bpl_plAbsolute ; +#line 1901 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vReflected = vDir - vNormal * (2.0f * (vNormal % vDir )); +#line 1902 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . AddBulletSpray (vBase + vFront , eptType , vReflected ); +#line 1903 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1904 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else if(crRay . cr_penHit -> GetRenderType () == RT_MODEL ) +#line 1905 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1906 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL bRender = TRUE ; +#line 1907 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpillDir = - ((CPlayer &) * m_penPlayer ) . en_vGravityDir * 0.5f; +#line 1908 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SprayParticlesType sptType = SPT_NONE ; +#line 1909 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +COLOR colParticles = C_WHITE | CT_OPAQUE ; +#line 1910 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fPower = 4.0f; +#line 1911 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (crRay . cr_penHit , "ModelHolder2")) +#line 1912 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1913 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +bRender = FALSE ; +#line 1914 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelDestruction * penDestruction = ((CModelHolder2 &) * crRay . cr_penHit ) . GetDestruction (); +#line 1915 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(penDestruction != NULL ) +#line 1916 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1917 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +bRender = TRUE ; +#line 1918 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sptType = penDestruction -> m_sptType ; +#line 1919 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1920 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelHolder2 * pmh2 = (CModelHolder2 *) crRay . cr_penHit ; +#line 1921 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +colParticles = pmh2 -> m_colBurning ; +#line 1922 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1923 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATaabbox3D boxCutted = FLOATaabbox3D (FLOAT3D (0 , 0 , 0) , FLOAT3D (1 , 1 , 1)); +#line 1924 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(bRender ) +#line 1925 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1926 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +crRay . cr_penHit -> en_pmoModelObject -> GetCurrentFrameBBox (boxCutted ); +#line 1927 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . AddGoreSpray (vBase + vFront , vHit , sptType , +#line 1928 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vSpillDir , boxCutted , fPower , colParticles ); +#line 1929 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1930 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1932 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 1933 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1934 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1935 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1937 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(penClosest != NULL ){ +#line 1939 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! (GetSP () -> sp_bCooperative ) && IsOfClass (penClosest , "Player")){ +#line 1940 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vToTarget = penClosest -> GetPlacement () . pl_PositionVector - m_penPlayer -> GetPlacement () . pl_PositionVector ; +#line 1941 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vTargetHeading = FLOAT3D (0.0 , 0.0 , - 1.0f) * penClosest -> GetRotationMatrix (); +#line 1942 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vToTarget . Normalize ();vTargetHeading . Normalize (); +#line 1943 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(vToTarget % vTargetHeading > 0.64279) +#line 1944 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1945 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PrintCenterMessage (this , m_penPlayer , TRANS ("Backstab!") , 4.0f , MSS_NONE ); +#line 1946 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fDamage *= 4.0f; +#line 1947 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1948 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1949 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT fDamageMul = GetSeriousDamageMultiplier (m_penPlayer ); +#line 1950 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +InflictDirectDamage (penClosest , m_penPlayer , DMT_CLOSERANGE , fDamage * fDamageMul , vHit , vDir ); +#line 1951 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE ; +#line 1952 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 1953 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return FALSE ; +#line 1954 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 1958 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL CPlayerWeapons::CutWithChainsaw(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fWide,FLOAT fThickness,FLOAT fDamage) +#line 1959 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1961 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plKnife ; +#line 1962 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (fX , fY , 0) , plKnife , TRUE ); +#line 1965 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOAT3D & vBase = plKnife . pl_PositionVector ; +#line 1966 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D m ; +#line 1967 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (m , plKnife . pl_OrientationAngle ); +#line 1968 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vRight = m . GetColumn (1) * fWide ; +#line 1969 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp = m . GetColumn (2) * fWide ; +#line 1970 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vFront = - m . GetColumn (3) * fRange ; +#line 1972 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vDest [ 3 ]; +#line 1973 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDest [ 0 ] = vBase + vFront ; +#line 1974 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDest [ 1 ] = vBase + vFront + vRight ; +#line 1975 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDest [ 2 ] = vBase + vFront - vRight ; +#line 1977 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntity * penClosest = NULL ; +#line 1978 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fDistance = UpperLimit (0.0f); +#line 1979 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vHit ; +#line 1980 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vDir ; +#line 1982 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +for(INDEX i = 0;i < 3;i ++){ +#line 1984 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CCastRay crRay (m_penPlayer , vBase , vDest [ i ]); +#line 1985 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 1986 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +crRay . cr_fTestR = fThickness ; +#line 1987 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +crRay . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ; +#line 1988 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetWorld () -> CastRay (crRay ); +#line 1991 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(crRay . cr_penHit != NULL ) +#line 1992 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 1993 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penClosest = crRay . cr_penHit ; +#line 1994 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fDistance = crRay . cr_fHitDistance ; +#line 1995 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDir = vDest [ i ] - vBase ; +#line 1996 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vDir . Normalize (); +#line 1997 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vHit = crRay . cr_vHit ; +#line 1999 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(i == 0) +#line 2000 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2001 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(crRay . cr_penHit -> GetRenderType () == RT_BRUSH ) +#line 2002 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2003 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iSurfaceType = crRay . cr_pbpoBrushPolygon -> bpo_bppProperties . bpp_ubSurfaceType ; +#line 2004 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EffectParticlesType eptType = GetParticleEffectTypeForSurface (iSurfaceType ); +#line 2006 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vNormal = crRay . cr_pbpoBrushPolygon -> bpo_pbplPlane -> bpl_plAbsolute ; +#line 2007 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vReflected = vDir - vNormal * (2.0f * (vNormal % vDir )); +#line 2008 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . AddBulletSpray (vBase + vFront , eptType , vReflected ); +#line 2011 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . m_fChainShakeStrength = 0.85f; +#line 2012 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . m_fChainShakeFreqMod = 1.0f; +#line 2013 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . m_tmChainShakeEnd = _pTimer -> CurrentTick () + CHAINSAW_UPDATETIME * 1.5f; +#line 2015 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2016 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else if(crRay . cr_penHit -> GetRenderType () == RT_MODEL ) +#line 2017 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2018 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL bRender = TRUE ; +#line 2019 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpillDir = - ((CPlayer &) * m_penPlayer ) . en_vGravityDir * 0.5f; +#line 2020 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SprayParticlesType sptType = SPT_BLOOD ; +#line 2021 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +COLOR colParticles = C_WHITE | CT_OPAQUE ; +#line 2022 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! IsDerivedFromClass (crRay . cr_penHit , "Enemy Base")){ +#line 2023 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sptType = SPT_NONE ; +#line 2024 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2025 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fPower = 4.0f; +#line 2026 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (crRay . cr_penHit , "Boneman")){sptType = SPT_BONES ;fPower = 6.0f;} +#line 2027 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (crRay . cr_penHit , "Gizmo") || +#line 2028 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +IsOfClass (crRay . cr_penHit , "Beast")){sptType = SPT_SLIME ;fPower = 4.0f;} +#line 2029 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (crRay . cr_penHit , "Woman")){sptType = SPT_FEATHER ;fPower = 3.0f;} +#line 2030 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (crRay . cr_penHit , "Elemental")){sptType = SPT_LAVA_STONES ;fPower = 3.0f;} +#line 2031 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (crRay . cr_penHit , "Walker")){sptType = SPT_ELECTRICITY_SPARKS ;fPower = 30.0f;} +#line 2032 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (crRay . cr_penHit , "AirElemental")){sptType = SPT_AIRSPOUTS ;fPower = 6.0f;} +#line 2033 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (crRay . cr_penHit , "CannonRotating") || +#line 2034 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +IsOfClass (crRay . cr_penHit , "CannonStatic")){sptType = SPT_WOOD ;} +#line 2035 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (crRay . cr_penHit , "ModelHolder2")) +#line 2036 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2037 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +bRender = FALSE ; +#line 2038 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelDestruction * penDestruction = ((CModelHolder2 &) * crRay . cr_penHit ) . GetDestruction (); +#line 2039 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelHolder2 * pmh2 = (CModelHolder2 *) crRay . cr_penHit ; +#line 2040 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +colParticles = pmh2 -> m_colBurning ; +#line 2041 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(penDestruction != NULL ) +#line 2042 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2043 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +bRender = TRUE ; +#line 2044 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sptType = penDestruction -> m_sptType ; +#line 2045 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(sptType == SPT_COLOREDSTONE ) +#line 2046 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2047 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +colParticles = MulColors (colParticles , penDestruction -> m_colParticles ); +#line 2048 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2049 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2050 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2051 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATaabbox3D boxCutted = FLOATaabbox3D (FLOAT3D (0 , 0 , 0) , FLOAT3D (1 , 1 , 1)); +#line 2052 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(bRender && m_tmLastChainsawSpray + 0.2f < _pTimer -> CurrentTick ()) +#line 2053 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2054 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +crRay . cr_penHit -> en_pmoModelObject -> GetCurrentFrameBBox (boxCutted ); +#line 2055 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . AddGoreSpray (vBase + vFront , vHit , sptType , +#line 2056 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vSpillDir , boxCutted , fPower , colParticles ); +#line 2057 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmLastChainsawSpray = _pTimer -> CurrentTick (); +#line 2058 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2061 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . m_fChainShakeStrength = 1.1f; +#line 2062 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . m_fChainShakeFreqMod = 1.0f; +#line 2063 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . m_tmChainShakeEnd = _pTimer -> CurrentTick () + CHAINSAW_UPDATETIME * 1.5f; +#line 2065 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2066 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2068 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(crRay . cr_penHit -> GetRenderType () == RT_MODEL && crRay . cr_fHitDistance <= fDistance ) +#line 2069 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2071 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(i == 0) +#line 2072 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2074 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2075 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2076 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2077 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 2079 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . m_fChainShakeStrength = 0.1f; +#line 2080 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . m_fChainShakeFreqMod = 1.0f; +#line 2081 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . m_tmChainShakeEnd = _pTimer -> CurrentTick () + CHAINSAW_UPDATETIME * 1.5f; +#line 2082 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2083 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2085 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(penClosest != NULL ){ +#line 2086 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +InflictDirectDamage (penClosest , m_penPlayer , DMT_CHAINSAW , fDamage , vHit , vDir ); +#line 2087 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE ; +#line 2088 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2089 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return FALSE ; +#line 2090 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2093 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::PrepareSniperBullet(FLOAT fX,FLOAT fY,FLOAT fDamage,FLOAT fImprecission) { +#line 2095 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPositionImprecise (FLOAT3D (fX , fY , 0) , plBullet , TRUE , fImprecission ); +#line 2097 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penBullet = CreateEntity (plBullet , CLASS_BULLET ); +#line 2098 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_vBulletSource = plBullet . pl_PositionVector ; +#line 2100 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EBulletInit eInit ; +#line 2101 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eInit . penOwner = m_penPlayer ; +#line 2102 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eInit . fDamage = fDamage ; +#line 2103 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penBullet -> Initialize (eInit ); +#line 2104 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2107 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::PrepareBullet(FLOAT fX,FLOAT fY,FLOAT fDamage) { +#line 2109 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (fX , fY , 0) , plBullet , TRUE ); +#line 2111 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penBullet = CreateEntity (plBullet , CLASS_BULLET ); +#line 2113 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EBulletInit eInit ; +#line 2114 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eInit . penOwner = m_penPlayer ; +#line 2115 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eInit . fDamage = fDamage ; +#line 2116 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penBullet -> Initialize (eInit ); +#line 2117 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2120 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::FireSniperBullet(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fDamage,FLOAT fImprecission) { +#line 2121 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PrepareSniperBullet (fX , fY , fDamage , fImprecission ); +#line 2122 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . CalcTarget (fRange ); +#line 2123 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . m_fBulletSize = 0.1f; +#line 2125 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . LaunchBullet (TRUE , FALSE , TRUE ); +#line 2127 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(((CBullet &) * penBullet ) . m_vHitPoint != FLOAT3D (0.0f , 0.0f , 0.0f)){ +#line 2128 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_vBulletTarget = ((CBullet &) * penBullet ) . m_vHitPoint ; +#line 2129 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(TRUE ){ +#line 2130 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_vBulletTarget = m_vBulletSource + FLOAT3D (0.0f , 0.0f , - 500.0f) * ((CBullet &) * penBullet ) . GetRotationMatrix (); +#line 2132 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2146 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . DestroyBullet (); +#line 2147 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2150 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::FireOneBullet(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fDamage) { +#line 2151 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PrepareBullet (fX , fY , fDamage ); +#line 2152 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . CalcTarget (fRange ); +#line 2153 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . m_fBulletSize = 0.1f; +#line 2155 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . LaunchBullet (TRUE , FALSE , TRUE ); +#line 2156 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . DestroyBullet (); +#line 2157 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2160 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::FireBullets(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fDamage,INDEX iBullets, +#line 2161 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT * afPositions,FLOAT fStretch,FLOAT fJitter) { +#line 2162 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PrepareBullet (fX , fY , fDamage ); +#line 2163 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . CalcTarget (fRange ); +#line 2164 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . m_fBulletSize = GetSP () -> sp_bCooperative ? 0.1f : 0.3f; +#line 2166 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iSlug ; +#line 2167 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +for(iSlug = 0;iSlug < iBullets ;iSlug ++){ +#line 2169 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . CalcJitterTargetFixed ( +#line 2170 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +afPositions [ iSlug * 2 + 0 ] * fRange * fStretch , afPositions [ iSlug * 2 + 1 ] * fRange * fStretch , +#line 2171 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fJitter * fRange * fStretch ); +#line 2172 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . LaunchBullet (iSlug < 2 , FALSE , TRUE ); +#line 2173 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2174 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . DestroyBullet (); +#line 2175 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2178 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::FireMachineBullet(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fDamage, +#line 2179 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fJitter,FLOAT fBulletSize) +#line 2180 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2181 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fJitter *= fRange ; +#line 2182 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PrepareBullet (fX , fY , fDamage ); +#line 2183 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . CalcTarget (fRange ); +#line 2184 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . m_fBulletSize = fBulletSize ; +#line 2185 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . CalcJitterTarget (fJitter ); +#line 2186 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . LaunchBullet (TRUE , FALSE , TRUE ); +#line 2187 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CBullet &) * penBullet ) . DestroyBullet (); +#line 2188 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2191 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::FireGrenade(INDEX iPower) { +#line 2193 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plGrenade ; +#line 2194 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition ( +#line 2195 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D (wpn_fFX [ WEAPON_GRENADELAUNCHER ] , wpn_fFY [ WEAPON_GRENADELAUNCHER ] , 0) , +#line 2196 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plGrenade , TRUE ); +#line 2198 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntityPointer penGrenade = CreateEntity (plGrenade , CLASS_PROJECTILE ); +#line 2200 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ELaunchProjectile eLaunch ; +#line 2201 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . penLauncher = m_penPlayer ; +#line 2202 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . prtType = PRT_GRENADE ; +#line 2203 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . fSpeed = 20.0f + iPower * 5.0f; +#line 2204 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penGrenade -> Initialize (eLaunch ); +#line 2205 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2208 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::FireRocket(void) { +#line 2210 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plRocket ; +#line 2211 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition ( +#line 2212 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D (wpn_fFX [ WEAPON_ROCKETLAUNCHER ] , wpn_fFY [ WEAPON_ROCKETLAUNCHER ] , 0) , +#line 2213 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plRocket , TRUE ); +#line 2215 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntityPointer penRocket = CreateEntity (plRocket , CLASS_PROJECTILE ); +#line 2217 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ELaunchProjectile eLaunch ; +#line 2218 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . penLauncher = m_penPlayer ; +#line 2219 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . prtType = PRT_ROCKET ; +#line 2220 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penRocket -> Initialize (eLaunch ); +#line 2221 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2248 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::GetFlamerSourcePlacement(CPlacement3D & plSource,CPlacement3D & plInFrontOfPipe) { +#line 2249 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcLerpedWeaponPosition ( +#line 2250 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D (wpn_fFX [ WEAPON_FLAMER ] , wpn_fFY [ WEAPON_FLAMER ] , - 0.15f) , +#line 2251 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plSource , FALSE ); +#line 2252 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plInFrontOfPipe = plSource ; +#line 2253 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vFront ; +#line 2254 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AnglesToDirectionVector (plSource . pl_OrientationAngle , vFront ); +#line 2255 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plInFrontOfPipe . pl_PositionVector = plSource . pl_PositionVector + vFront * 1.0f; +#line 2256 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2259 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::FireFlame(void) { +#line 2261 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plFlame ; +#line 2263 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (wpn_fFX [ WEAPON_FLAMER ] , wpn_fFY [ WEAPON_FLAMER ] , - 0.15f) , plFlame , TRUE ); +#line 2266 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntityPointer penFlame = CreateEntity (plFlame , CLASS_PROJECTILE ); +#line 2268 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ELaunchProjectile eLaunch ; +#line 2269 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . penLauncher = m_penPlayer ; +#line 2270 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . prtType = PRT_FLAME ; +#line 2271 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penFlame -> Initialize (eLaunch ); +#line 2273 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_penFlame != NULL && ! (m_penFlame -> GetFlags () & ENF_DELETED )){ +#line 2274 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CProjectile &) * m_penFlame ) . m_penParticles = penFlame ; +#line 2275 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2277 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CProjectile &) * penFlame ) . m_penParticles = this ; +#line 2279 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_penFlame = penFlame ; +#line 2280 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2283 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::FireLaserRay(void) { +#line 2285 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plLaserRay ; +#line 2286 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fFX = wpn_fFX [ WEAPON_LASER ]; +#line 2287 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fFY = wpn_fFY [ WEAPON_LASER ]; +#line 2288 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fLUX = 0.0f; +#line 2289 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fRUX = 0.8f; +#line 2290 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fLUY = 0.0f; +#line 2291 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fRUY = 0.0f; +#line 2292 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fLDX = - 0.1f; +#line 2293 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fRDX = 0.9f; +#line 2294 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fLDY = - 0.3f; +#line 2295 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fRDY = - 0.3f; +#line 2296 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(((CPlayer *) & * m_penPlayer ) -> m_pstState == PST_CROUCH ){ +#line 2297 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fLDY = - 0.1f; +#line 2298 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fRDY = - 0.1f; +#line 2299 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2301 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iLaserBarrel ){ +#line 2302 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: +#line 2303 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (fFX + fLUX , fFY + fLUY , 0) , plLaserRay , TRUE ); +#line 2304 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2305 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: +#line 2306 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (fFX + fLDX , fFY + fLDY , 0) , plLaserRay , TRUE ); +#line 2307 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2308 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 2: +#line 2309 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (fFX + fRUX , fFY + fRUY , 0) , plLaserRay , TRUE ); +#line 2310 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2311 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 3: +#line 2312 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (fFX + fRDX , fFY + fRDY , 0) , plLaserRay , TRUE ); +#line 2313 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2314 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2316 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntityPointer penLaser = CreateEntity (plLaserRay , CLASS_PROJECTILE ); +#line 2318 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ELaunchProjectile eLaunch ; +#line 2319 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . penLauncher = m_penPlayer ; +#line 2320 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . prtType = PRT_LASER_RAY ; +#line 2321 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penLaser -> Initialize (eLaunch ); +#line 2322 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2343 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::FireCannonBall(INDEX iPower) +#line 2344 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2346 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plBall ; +#line 2347 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition ( +#line 2348 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D (wpn_fFX [ WEAPON_IRONCANNON ] , wpn_fFY [ WEAPON_IRONCANNON ] , 0) , +#line 2349 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plBall , TRUE ); +#line 2351 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntityPointer penBall = CreateEntity (plBall , CLASS_CANNONBALL ); +#line 2353 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ELaunchCannonBall eLaunch ; +#line 2354 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . penLauncher = m_penPlayer ; +#line 2355 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . fLaunchPower = 60.0f + iPower * 4.0f; +#line 2356 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . fSize = 3.0f; +#line 2364 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eLaunch . cbtType = CBT_IRON ; +#line 2366 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penBall -> Initialize (eLaunch ); +#line 2367 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2370 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::SpawnRangeSound(FLOAT fRange) +#line 2371 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2372 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pTimer -> CurrentTick () > m_tmRangeSoundSpawned + 0.5f){ +#line 2373 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmRangeSoundSpawned = _pTimer -> CurrentTick (); +#line 2374 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +:: SpawnRangeSound (m_penPlayer , m_penPlayer , SNDT_PLAYER , fRange ); +#line 2375 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2376 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2383 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::ClearWeapons(void) { +#line 2385 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAvailableWeapons = 0x03; +#line 2386 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iColtBullets = 6; +#line 2387 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iBullets = 0; +#line 2388 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iShells = 0; +#line 2389 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iRockets = 0; +#line 2390 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iGrenades = 0; +#line 2391 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iNapalm = 0; +#line 2392 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iElectricity = 0; +#line 2393 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iIronBalls = 0; +#line 2395 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iSniperBullets = 0; +#line 2396 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2398 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::ResetWeaponMovingOffset(void) +#line 2399 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2401 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPowerOld = m_fWeaponDrawPower = m_tmDrawStartTime = 0; +#line 2402 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2405 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::InitializeWeapons(INDEX iGiveWeapons,INDEX iTakeWeapons,INDEX iTakeAmmo,FLOAT fMaxAmmoRatio) +#line 2406 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2407 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ResetWeaponMovingOffset (); +#line 2409 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ULONG ulOldWeapons = m_iAvailableWeapons ; +#line 2411 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAvailableWeapons &= ~ iTakeWeapons ; +#line 2412 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAvailableWeapons |= 0x03 | iGiveWeapons ; +#line 2413 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAvailableWeapons &= WEAPONS_ALLAVAILABLEMASK ; +#line 2416 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ULONG ulNewWeapons = m_iAvailableWeapons & ~ ulOldWeapons ; +#line 2418 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +for(INDEX iWeapon = WEAPON_KNIFE ;iWeapon < WEAPON_LAST ;iWeapon ++){ +#line 2419 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(ulNewWeapons & (1 << (iWeapon - 1))){ +#line 2421 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddDefaultAmmoForWeapon (iWeapon , fMaxAmmoRatio ); +#line 2422 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2423 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2426 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fModifier = ClampDn (GetSP () -> sp_fAmmoQuantity , 1.0f); +#line 2427 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iMaxBullets = ClampUp ((INDEX) ceil (MAX_BULLETS * fModifier ) , INDEX (999)); +#line 2428 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iMaxShells = ClampUp ((INDEX) ceil (MAX_SHELLS * fModifier ) , INDEX (999)); +#line 2429 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iMaxRockets = ClampUp ((INDEX) ceil (MAX_ROCKETS * fModifier ) , INDEX (999)); +#line 2430 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iMaxGrenades = ClampUp ((INDEX) ceil (MAX_GRENADES * fModifier ) , INDEX (999)); +#line 2431 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iMaxNapalm = ClampUp ((INDEX) ceil (MAX_NAPALM * fModifier ) , INDEX (999)); +#line 2432 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iMaxElectricity = ClampUp ((INDEX) ceil (MAX_ELECTRICITY * fModifier ) , INDEX (999)); +#line 2434 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iMaxIronBalls = ClampUp ((INDEX) ceil (MAX_IRONBALLS * fModifier ) , INDEX (999)); +#line 2435 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iMaxSniperBullets = ClampUp ((INDEX) ceil (MAX_SNIPERBULLETS * fModifier ) , INDEX (999)); +#line 2438 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iTakeAmmo & (1 << AMMO_BULLETS )){m_iBullets = 0;} +#line 2439 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iTakeAmmo & (1 << AMMO_SHELLS )){m_iShells = 0;} +#line 2440 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iTakeAmmo & (1 << AMMO_ROCKETS )){m_iRockets = 0;} +#line 2441 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iTakeAmmo & (1 << AMMO_GRENADES )){m_iGrenades = 0;} +#line 2442 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iTakeAmmo & (1 << AMMO_NAPALM )){m_iNapalm = 0;} +#line 2443 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iTakeAmmo & (1 << AMMO_ELECTRICITY )){m_iElectricity = 0;} +#line 2445 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iTakeAmmo & (1 << AMMO_IRONBALLS )){m_iIronBalls = 0;} +#line 2446 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iTakeAmmo & (1 << AMMO_SNIPERBULLETS )){m_iSniperBullets = 0;} +#line 2449 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Precache (); +#line 2452 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGun = 0; +#line 2453 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunLast = 0; +#line 2454 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunSpeed = 0; +#line 2457 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SelectNewWeapon (); +#line 2458 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iCurrentWeapon = m_iWantedWeapon ; +#line 2459 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_iCurrent = m_iCurrentWeapon ; +#line 2460 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bChangeWeapon = FALSE ; +#line 2462 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetCurrentWeaponModel (); +#line 2463 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayDefaultAnim (); +#line 2465 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayerAnimator &) * ((CPlayer &) * m_penPlayer ) . m_penAnimator ) . RemoveWeapon (); +#line 2467 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayerAnimator &) * ((CPlayer &) * m_penPlayer ) . m_penAnimator ) . SetWeapon (); +#line 2468 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2471 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX CPlayerWeapons::GetAmmo(void) +#line 2472 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2473 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 2474 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : return 0; +#line 2475 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_COLT : return m_iColtBullets ; +#line 2476 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : return m_iColtBullets ; +#line 2477 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : return m_iShells ; +#line 2478 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : return m_iShells ; +#line 2479 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : return m_iBullets ; +#line 2480 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : return m_iBullets ; +#line 2481 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : return m_iRockets ; +#line 2482 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : return m_iGrenades ; +#line 2483 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : return m_iSniperBullets ; +#line 2484 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : return m_iNapalm ; +#line 2485 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_CHAINSAW : return 0; +#line 2486 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : return m_iElectricity ; +#line 2487 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : return m_iIronBalls ; +#line 2488 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2489 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return 0; +#line 2490 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2493 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX CPlayerWeapons::GetMaxAmmo(void) +#line 2494 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2495 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 2496 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : return 0; +#line 2497 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_COLT : return 6; +#line 2498 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : return 6; +#line 2499 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : return m_iMaxShells ; +#line 2500 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : return m_iMaxShells ; +#line 2501 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : return m_iMaxBullets ; +#line 2502 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : return m_iMaxBullets ; +#line 2503 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : return m_iMaxRockets ; +#line 2504 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : return m_iMaxGrenades ; +#line 2505 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : return m_iMaxSniperBullets ; +#line 2506 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : return m_iMaxNapalm ; +#line 2507 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_CHAINSAW : return m_iMaxNapalm ; +#line 2508 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : return m_iMaxElectricity ; +#line 2509 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : return m_iMaxIronBalls ; +#line 2510 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2511 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return 0; +#line 2512 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2514 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::CheatOpen(void) +#line 2515 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2516 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IsOfClass (m_penRayHit , "Moving Brush")){ +#line 2517 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_penRayHit -> SendEvent (ETrigger ()); +#line 2518 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2519 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2522 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::CheatGiveAll(void) { +#line 2524 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAvailableWeapons = WEAPONS_ALLAVAILABLEMASK ; +#line 2527 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iBullets = m_iMaxBullets ; +#line 2528 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iShells = m_iMaxShells ; +#line 2529 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iRockets = m_iMaxRockets ; +#line 2530 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iGrenades = m_iMaxGrenades ; +#line 2531 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iNapalm = m_iMaxNapalm ; +#line 2532 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iElectricity = m_iMaxElectricity ; +#line 2533 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iIronBalls = m_iMaxIronBalls ; +#line 2536 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iSniperBullets = m_iMaxSniperBullets ; +#line 2537 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Precache (); +#line 2538 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2541 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::AddManaToPlayer(INDEX iMana) +#line 2542 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2543 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . m_iMana += iMana ; +#line 2544 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . m_fPickedMana += iMana ; +#line 2545 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2553 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::ClampAllAmmo(void) +#line 2554 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2555 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iBullets = ClampUp (m_iBullets , m_iMaxBullets ); +#line 2556 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iShells = ClampUp (m_iShells , m_iMaxShells ); +#line 2557 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iRockets = ClampUp (m_iRockets , m_iMaxRockets ); +#line 2558 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iGrenades = ClampUp (m_iGrenades , m_iMaxGrenades ); +#line 2559 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iNapalm = ClampUp (m_iNapalm , m_iMaxNapalm ); +#line 2560 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iElectricity = ClampUp (m_iElectricity , m_iMaxElectricity ); +#line 2561 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iIronBalls = ClampUp (m_iIronBalls , m_iMaxIronBalls ); +#line 2563 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iSniperBullets = ClampUp (m_iSniperBullets , m_iMaxSniperBullets ); +#line 2564 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2567 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::AddDefaultAmmoForWeapon(INDEX iWeapon,FLOAT fMaxAmmoRatio) +#line 2568 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2569 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAmmoPicked ; +#line 2571 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(iWeapon ){ +#line 2573 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : +#line 2574 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_COLT : +#line 2575 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : +#line 2576 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2578 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : +#line 2579 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAmmoPicked = Max (10.0f , m_iMaxShells * fMaxAmmoRatio ); +#line 2580 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iShells += iAmmoPicked ; +#line 2581 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (iAmmoPicked * 70.0f * MANA_AMMO ); +#line 2582 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2583 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : +#line 2584 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAmmoPicked = Max (20.0f , m_iMaxShells * fMaxAmmoRatio ); +#line 2585 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iShells += iAmmoPicked ; +#line 2586 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (iAmmoPicked * 70.0f * MANA_AMMO ); +#line 2587 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2589 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : +#line 2590 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAmmoPicked = Max (50.0f , m_iMaxBullets * fMaxAmmoRatio ); +#line 2591 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iBullets += iAmmoPicked ; +#line 2592 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (iAmmoPicked * 10.0f * MANA_AMMO ); +#line 2593 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2594 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : +#line 2595 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAmmoPicked = Max (15.0f , m_iMaxSniperBullets * fMaxAmmoRatio ); +#line 2596 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iSniperBullets += iAmmoPicked ; +#line 2597 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (iAmmoPicked * 10.0f * MANA_AMMO ); +#line 2598 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2599 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : +#line 2600 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAmmoPicked = Max (100.0f , m_iMaxBullets * fMaxAmmoRatio ); +#line 2601 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iBullets += iAmmoPicked ; +#line 2602 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (iAmmoPicked * 10.0f * MANA_AMMO ); +#line 2603 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2605 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : +#line 2606 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAmmoPicked = Max (5.0f , m_iMaxRockets * fMaxAmmoRatio ); +#line 2607 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iRockets += iAmmoPicked ; +#line 2608 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (iAmmoPicked * 150.0f * MANA_AMMO ); +#line 2609 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2611 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : +#line 2612 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAmmoPicked = Max (5.0f , m_iMaxGrenades * fMaxAmmoRatio ); +#line 2613 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iGrenades += iAmmoPicked ; +#line 2614 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (iAmmoPicked * 100.0f * MANA_AMMO ); +#line 2615 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2629 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : +#line 2630 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAmmoPicked = Max (50.0f , m_iMaxElectricity * fMaxAmmoRatio ); +#line 2631 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iElectricity += iAmmoPicked ; +#line 2632 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (iAmmoPicked * 15.0f * MANA_AMMO ); +#line 2633 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2635 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : +#line 2637 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAmmoPicked = Max (1.0f , m_iMaxIronBalls * fMaxAmmoRatio ); +#line 2638 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iIronBalls += iAmmoPicked ; +#line 2639 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (iAmmoPicked * 700.0f * MANA_AMMO ); +#line 2640 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2648 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : +#line 2649 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAmmoPicked = Max (50.0f , m_iMaxNapalm * fMaxAmmoRatio ); +#line 2650 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iNapalm += iAmmoPicked ; +#line 2651 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (iAmmoPicked * 15.0f * MANA_AMMO ); +#line 2652 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2653 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_CHAINSAW : +#line 2657 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2659 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : +#line 2660 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("Uknown weapon type"); +#line 2661 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2662 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2665 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ClampAllAmmo (); +#line 2666 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2669 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::DropWeapon(void) +#line 2670 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2671 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CEntityPointer penWeapon = CreateEntity (GetPlayer () -> GetPlacement () , CLASS_WEAPONITEM ); +#line 2672 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CWeaponItem * pwi = (CWeaponItem *) & * penWeapon ; +#line 2674 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponItemType wit = WIT_COLT ; +#line 2675 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 2676 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : +#line 2677 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERT (FALSE ); +#line 2678 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : +#line 2679 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_COLT : +#line 2680 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : +#line 2681 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +NOTHING ;break ; +#line 2682 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : wit = WIT_SINGLESHOTGUN ;break ; +#line 2683 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : wit = WIT_DOUBLESHOTGUN ;break ; +#line 2684 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : wit = WIT_TOMMYGUN ;break ; +#line 2685 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : wit = WIT_SNIPER ;break ; +#line 2686 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : wit = WIT_MINIGUN ;break ; +#line 2687 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : wit = WIT_ROCKETLAUNCHER ;break ; +#line 2688 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : wit = WIT_GRENADELAUNCHER ;break ; +#line 2689 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : wit = WIT_FLAMER ;break ; +#line 2690 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_CHAINSAW : wit = WIT_CHAINSAW ;break ; +#line 2691 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : wit = WIT_LASER ;break ; +#line 2692 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : wit = WIT_CANNON ;break ; +#line 2693 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2695 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pwi -> m_EwitType = wit ; +#line 2696 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pwi -> m_bDropped = TRUE ; +#line 2697 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pwi -> CEntity :: Initialize (); +#line 2699 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOATmatrix3D & m = GetPlayer () -> GetRotationMatrix (); +#line 2700 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpeed = FLOAT3D (5.0f , 10.0f , - 7.5f); +#line 2701 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pwi -> GiveImpulseTranslationAbsolute (vSpeed * m ); +#line 2702 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2705 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL CPlayerWeapons::ReceiveWeapon(const CEntityEvent & ee) { +#line 2706 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERT (ee . ee_slEvent == EVENTCODE_EWeaponItem ); +#line 2708 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EWeaponItem & Ewi = (EWeaponItem &) ee ; +#line 2709 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX wit = Ewi . iWeapon ; +#line 2710 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(Ewi . iWeapon ){ +#line 2711 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_COLT : Ewi . iWeapon = WEAPON_COLT ;break ; +#line 2712 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_SINGLESHOTGUN : Ewi . iWeapon = WEAPON_SINGLESHOTGUN ;break ; +#line 2713 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_DOUBLESHOTGUN : Ewi . iWeapon = WEAPON_DOUBLESHOTGUN ;break ; +#line 2714 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_TOMMYGUN : Ewi . iWeapon = WEAPON_TOMMYGUN ;break ; +#line 2715 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_SNIPER : Ewi . iWeapon = WEAPON_SNIPER ;break ; +#line 2716 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_MINIGUN : Ewi . iWeapon = WEAPON_MINIGUN ;break ; +#line 2717 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_ROCKETLAUNCHER : Ewi . iWeapon = WEAPON_ROCKETLAUNCHER ;break ; +#line 2718 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_GRENADELAUNCHER : Ewi . iWeapon = WEAPON_GRENADELAUNCHER ;break ; +#line 2719 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_FLAMER : Ewi . iWeapon = WEAPON_FLAMER ;break ; +#line 2720 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_CHAINSAW : Ewi . iWeapon = WEAPON_CHAINSAW ;break ; +#line 2721 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_LASER : Ewi . iWeapon = WEAPON_LASER ;break ; +#line 2722 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_CANNON : Ewi . iWeapon = WEAPON_IRONCANNON ;break ; +#line 2723 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : +#line 2724 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("Uknown weapon type"); +#line 2725 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2728 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(Ewi . iWeapon == WEAPON_COLT && (m_iAvailableWeapons & (1 << (WEAPON_COLT - 1)))){ +#line 2729 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Ewi . iWeapon = WEAPON_DOUBLECOLT ; +#line 2730 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2732 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ULONG ulOldWeapons = m_iAvailableWeapons ; +#line 2733 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAvailableWeapons |= 1 << (Ewi . iWeapon - 1); +#line 2745 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Precache (); +#line 2747 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CTFileName fnmMsg ; +#line 2748 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(wit ){ +#line 2749 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_COLT : +#line 2750 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("Shofield .45 w/ TMAR") , 0); +#line 2751 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("Data\\Messages\\Weapons\\colt.txt"); +#line 2752 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2753 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_SINGLESHOTGUN : +#line 2754 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("12 Gauge Pump Action Shotgun") , 0); +#line 2755 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("Data\\Messages\\Weapons\\singleshotgun.txt"); +#line 2756 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2757 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_DOUBLESHOTGUN : +#line 2758 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("Double Barrel Coach Gun") , 0); +#line 2759 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("Data\\Messages\\Weapons\\doubleshotgun.txt"); +#line 2760 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2761 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_TOMMYGUN : +#line 2762 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("M1-A2 Tommygun") , 0); +#line 2763 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("Data\\Messages\\Weapons\\tommygun.txt"); +#line 2764 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2765 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_SNIPER : +#line 2766 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("RAPTOR 16mm Sniper") , 0); +#line 2767 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("DataMP\\Messages\\Weapons\\sniper.txt"); +#line 2768 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2769 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_MINIGUN : +#line 2770 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("XM214-A Minigun") , 0); +#line 2771 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("Data\\Messages\\Weapons\\minigun.txt"); +#line 2772 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2773 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_ROCKETLAUNCHER : +#line 2774 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("XPML21 Rocket Launcher") , 0); +#line 2775 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("Data\\Messages\\Weapons\\rocketlauncher.txt"); +#line 2776 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2777 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_GRENADELAUNCHER : +#line 2778 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("MKIII Grenade Launcher") , 0); +#line 2779 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("Data\\Messages\\Weapons\\grenadelauncher.txt"); +#line 2780 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2784 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_FLAMER : +#line 2785 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("XOP Flamethrower") , 0); +#line 2786 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("DataMP\\Messages\\Weapons\\flamer.txt"); +#line 2787 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2788 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_CHAINSAW : +#line 2789 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("'Bonecracker' P-LAH Chainsaw") , 0); +#line 2790 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("DataMP\\Messages\\Weapons\\chainsaw.txt"); +#line 2791 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2792 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_LASER : +#line 2793 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("XL2 Lasergun") , 0); +#line 2794 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("Data\\Messages\\Weapons\\laser.txt"); +#line 2795 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2799 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WIT_CANNON : +#line 2800 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("SBC Cannon") , 0); +#line 2801 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fnmMsg = CTFILENAME ("Data\\Messages\\Weapons\\cannon.txt"); +#line 2802 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2803 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : +#line 2804 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("Uknown weapon type"); +#line 2805 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2807 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(GetSP () -> sp_bCooperative ){ +#line 2808 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EComputerMessage eMsg ; +#line 2809 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +eMsg . fnmMessage = fnmMsg ; +#line 2810 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_penPlayer -> SendEvent (eMsg ); +#line 2811 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2814 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERT (Ewi . iAmmo == - 1); +#line 2816 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddDefaultAmmoForWeapon (Ewi . iWeapon , 0); +#line 2819 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL bAutoSelect = FALSE ; +#line 2820 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iSelectionSetting = GetPlayer () -> GetSettings () -> ps_iWeaponAutoSelect ; +#line 2821 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iSelectionSetting == PS_WAS_ALL ){ +#line 2822 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +bAutoSelect = TRUE ; +#line 2823 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(iSelectionSetting == PS_WAS_ONLYNEW ){ +#line 2824 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iAvailableWeapons & ~ ulOldWeapons ){ +#line 2825 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +bAutoSelect = TRUE ; +#line 2826 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2827 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(iSelectionSetting == PS_WAS_BETTER ){ +#line 2828 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(FindRemapedPos (m_iCurrentWeapon ) < FindRemapedPos ((WeaponType ) Ewi . iWeapon )){ +#line 2829 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +bAutoSelect = TRUE ; +#line 2830 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2831 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2832 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(bAutoSelect ){ +#line 2834 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(WeaponSelectOk ((WeaponType ) Ewi . iWeapon )){ +#line 2835 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SendEvent (EBegin ()); +#line 2836 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2837 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2839 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE ; +#line 2840 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2843 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL CPlayerWeapons::ReceiveAmmo(const CEntityEvent & ee) { +#line 2844 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERT (ee . ee_slEvent == EVENTCODE_EAmmoItem ); +#line 2847 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(GetSP () -> sp_bInfiniteAmmo ){ +#line 2850 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE ; +#line 2851 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2854 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EAmmoItem & Eai = (EAmmoItem &) ee ; +#line 2856 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(Eai . EaitType ){ +#line 2858 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case AIT_SHELLS : +#line 2859 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iShells >= m_iMaxShells ){m_iShells = m_iMaxShells ;return FALSE ;} +#line 2860 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iShells += Eai . iQuantity ; +#line 2861 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("Shells") , Eai . iQuantity ); +#line 2862 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (Eai . iQuantity * AV_SHELLS * MANA_AMMO ); +#line 2863 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2865 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case AIT_BULLETS : +#line 2866 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iBullets >= m_iMaxBullets ){m_iBullets = m_iMaxBullets ;return FALSE ;} +#line 2867 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iBullets += Eai . iQuantity ; +#line 2868 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("Bullets") , Eai . iQuantity ); +#line 2869 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (Eai . iQuantity * AV_BULLETS * MANA_AMMO ); +#line 2870 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2872 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case AIT_ROCKETS : +#line 2873 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iRockets >= m_iMaxRockets ){m_iRockets = m_iMaxRockets ;return FALSE ;} +#line 2874 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iRockets += Eai . iQuantity ; +#line 2875 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("Rockets") , Eai . iQuantity ); +#line 2876 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (Eai . iQuantity * AV_ROCKETS * MANA_AMMO ); +#line 2877 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2879 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case AIT_GRENADES : +#line 2880 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iGrenades >= m_iMaxGrenades ){m_iGrenades = m_iMaxGrenades ;return FALSE ;} +#line 2881 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iGrenades += Eai . iQuantity ; +#line 2882 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("Grenades") , Eai . iQuantity ); +#line 2883 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (Eai . iQuantity * AV_GRENADES * MANA_AMMO ); +#line 2884 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2886 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case AIT_ELECTRICITY : +#line 2887 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iElectricity >= m_iMaxElectricity ){m_iElectricity = m_iMaxElectricity ;return FALSE ;} +#line 2888 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iElectricity += Eai . iQuantity ; +#line 2889 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("Cells") , Eai . iQuantity ); +#line 2890 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (Eai . iQuantity * AV_ELECTRICITY * MANA_AMMO ); +#line 2891 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2899 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case AIT_IRONBALLS : +#line 2900 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iIronBalls >= m_iMaxIronBalls ){m_iIronBalls = m_iMaxIronBalls ;return FALSE ;} +#line 2901 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iIronBalls += Eai . iQuantity ; +#line 2902 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("Cannonballs") , Eai . iQuantity ); +#line 2903 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (Eai . iQuantity * AV_IRONBALLS * MANA_AMMO ); +#line 2904 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2905 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case AIT_NAPALM : +#line 2906 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iNapalm >= m_iMaxNapalm ){m_iNapalm = m_iMaxNapalm ;return FALSE ;} +#line 2907 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iNapalm += Eai . iQuantity ; +#line 2908 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("Napalm") , Eai . iQuantity ); +#line 2909 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (Eai . iQuantity * AV_NAPALM * MANA_AMMO ); +#line 2910 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2911 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case AIT_BACKPACK : +#line 2912 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iShells += 20 * GetSP () -> sp_fAmmoQuantity ; +#line 2913 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iBullets += 200 * GetSP () -> sp_fAmmoQuantity ; +#line 2914 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iRockets += 5 * GetSP () -> sp_fAmmoQuantity ; +#line 2915 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("Ammo pack") , 0); +#line 2916 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (100000000.0f * MANA_AMMO ); +#line 2917 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2918 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case AIT_SERIOUSPACK : +#line 2919 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iShells += MAX_SHELLS * GetSP () -> sp_fAmmoQuantity ; +#line 2920 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iBullets += MAX_BULLETS * GetSP () -> sp_fAmmoQuantity ; +#line 2921 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iGrenades += MAX_GRENADES * GetSP () -> sp_fAmmoQuantity ; +#line 2922 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iRockets += MAX_ROCKETS * GetSP () -> sp_fAmmoQuantity ; +#line 2923 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iElectricity += MAX_ELECTRICITY * GetSP () -> sp_fAmmoQuantity ; +#line 2924 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iIronBalls += MAX_IRONBALLS * GetSP () -> sp_fAmmoQuantity ; +#line 2926 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case AIT_SNIPERBULLETS : +#line 2927 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iSniperBullets >= m_iMaxSniperBullets ){m_iSniperBullets = m_iMaxSniperBullets ;return FALSE ;} +#line 2928 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iSniperBullets += Eai . iQuantity ; +#line 2929 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("Sniper bullets") , Eai . iQuantity ); +#line 2930 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (Eai . iQuantity * AV_SNIPERBULLETS * MANA_AMMO ); +#line 2931 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2934 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (TRANS ("All Ammo") , 0); +#line 2935 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +AddManaToPlayer (100000000.0f * MANA_AMMO ); +#line 2936 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 2938 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : +#line 2939 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("Uknown ammo type"); +#line 2940 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2943 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ClampAllAmmo (); +#line 2944 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE ; +#line 2945 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 2948 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL CPlayerWeapons::ReceivePackAmmo(const CEntityEvent & ee) +#line 2949 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2951 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(GetSP () -> sp_bInfiniteAmmo ){ +#line 2954 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE ; +#line 2955 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 2957 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERT (ee . ee_slEvent == EVENTCODE_EAmmoPackItem ); +#line 2958 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EAmmoPackItem & eapi = (EAmmoPackItem &) ee ; +#line 2959 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if((eapi . iShells > 0 && m_iShells < m_iMaxShells ) || +#line 2960 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(eapi . iBullets > 0 && m_iBullets < m_iMaxBullets ) || +#line 2961 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(eapi . iRockets > 0 && m_iRockets < m_iMaxRockets ) || +#line 2962 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(eapi . iGrenades > 0 && m_iGrenades < m_iMaxGrenades ) || +#line 2963 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(eapi . iNapalm > 0 && m_iNapalm < m_iMaxNapalm ) || +#line 2964 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(eapi . iElectricity > 0 && m_iElectricity < m_iMaxElectricity ) || +#line 2965 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(eapi . iIronBalls > 0 && m_iIronBalls < m_iMaxIronBalls ) || +#line 2966 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(eapi . iSniperBullets > 0 && m_iSniperBullets < m_iMaxSniperBullets )) +#line 2967 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2969 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iShells += eapi . iShells ; +#line 2970 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iBullets += eapi . iBullets ; +#line 2971 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iRockets += eapi . iRockets ; +#line 2972 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iGrenades += eapi . iGrenades ; +#line 2973 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iNapalm += eapi . iNapalm ; +#line 2974 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iElectricity += eapi . iElectricity ; +#line 2975 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iIronBalls += eapi . iIronBalls ; +#line 2976 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iSniperBullets += eapi . iSniperBullets ; +#line 2978 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ClampAllAmmo (); +#line 2981 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAmmoTypes = 0; +#line 2982 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CTString strMessage ; +#line 2983 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(eapi . iShells != 0){strMessage . PrintF ("%s %d %s," , strMessage , eapi . iShells , TRANS ("Shells"));iAmmoTypes ++;} +#line 2984 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(eapi . iBullets != 0){strMessage . PrintF ("%s %d %s," , strMessage , eapi . iBullets , TRANS ("Bullets"));iAmmoTypes ++;} +#line 2985 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(eapi . iRockets != 0){strMessage . PrintF ("%s %d %s," , strMessage , eapi . iRockets , TRANS ("Rockets"));iAmmoTypes ++;} +#line 2986 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(eapi . iGrenades != 0){strMessage . PrintF ("%s %d %s," , strMessage , eapi . iGrenades , TRANS ("Grenades"));iAmmoTypes ++;} +#line 2987 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(eapi . iNapalm != 0){strMessage . PrintF ("%s %d %s," , strMessage , eapi . iNapalm , TRANS ("Napalm"));iAmmoTypes ++;} +#line 2988 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(eapi . iElectricity != 0){strMessage . PrintF ("%s %d %s," , strMessage , eapi . iElectricity , TRANS ("Cells"));iAmmoTypes ++;} +#line 2989 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(eapi . iIronBalls != 0){strMessage . PrintF ("%s %d %s," , strMessage , eapi . iIronBalls , TRANS ("Cannonballs"));iAmmoTypes ++;} +#line 2990 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(eapi . iSniperBullets != 0){strMessage . PrintF ("%s %d %s," , strMessage , eapi . iSniperBullets , TRANS ("Sniper bullets"));iAmmoTypes ++;} +#line 2992 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iLen = strlen (strMessage ); +#line 2993 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iLen > 0 && strMessage [ iLen - 1 ] == ',') +#line 2994 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 2995 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +strMessage . DeleteChar (iLen - 1); +#line 2996 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}; +#line 2997 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iAmmoTypes > 4){ +#line 2998 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +strMessage . PrintF (TRANS ("Ammo pack")); +#line 2999 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}; +#line 3001 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayer &) * m_penPlayer ) . ItemPicked (strMessage , 0); +#line 3002 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE ; +#line 3003 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3004 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return FALSE ; +#line 3005 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3011 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType CPlayerWeapons::GetStrongerWeapon(INDEX iWeapon) { +#line 3012 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(iWeapon ){ +#line 3013 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: return WEAPON_CHAINSAW ; +#line 3014 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 2: return WEAPON_DOUBLECOLT ; +#line 3015 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 3: return WEAPON_DOUBLESHOTGUN ; +#line 3016 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 4: return WEAPON_MINIGUN ; +#line 3017 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 5: return WEAPON_ROCKETLAUNCHER ; +#line 3018 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 6: return WEAPON_FLAMER ; +#line 3019 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 7: return WEAPON_LASER ; +#line 3020 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 8: return WEAPON_IRONCANNON ; +#line 3021 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3022 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_NONE ; +#line 3023 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3026 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX CPlayerWeapons::GetSelectedWeapon(WeaponType EwtSelectedWeapon) { +#line 3027 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(EwtSelectedWeapon ){ +#line 3028 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : case WEAPON_CHAINSAW : return 1; +#line 3029 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_COLT : case WEAPON_DOUBLECOLT : return 2; +#line 3030 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : case WEAPON_DOUBLESHOTGUN : return 3; +#line 3031 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : case WEAPON_MINIGUN : return 4; +#line 3032 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : case WEAPON_GRENADELAUNCHER : return 5; +#line 3033 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : case WEAPON_SNIPER : return 6; +#line 3034 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : return 7; +#line 3035 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : return 8; +#line 3036 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3037 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return 0; +#line 3038 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3041 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType CPlayerWeapons::GetAltWeapon(WeaponType EwtWeapon) { +#line 3042 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(EwtWeapon ){ +#line 3043 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : return WEAPON_CHAINSAW ; +#line 3044 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_CHAINSAW : return WEAPON_KNIFE ; +#line 3045 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_COLT : return WEAPON_DOUBLECOLT ; +#line 3046 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : return WEAPON_COLT ; +#line 3047 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : return WEAPON_DOUBLESHOTGUN ; +#line 3048 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : return WEAPON_SINGLESHOTGUN ; +#line 3049 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : return WEAPON_MINIGUN ; +#line 3050 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : return WEAPON_TOMMYGUN ; +#line 3051 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : return WEAPON_GRENADELAUNCHER ; +#line 3052 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : return WEAPON_ROCKETLAUNCHER ; +#line 3053 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : return WEAPON_SNIPER ; +#line 3054 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : return WEAPON_FLAMER ; +#line 3055 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : return WEAPON_LASER ; +#line 3056 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : return WEAPON_IRONCANNON ; +#line 3057 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3058 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_NONE ; +#line 3059 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3062 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL CPlayerWeapons::WeaponSelectOk(WeaponType wtToTry) +#line 3063 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3065 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(((1 << (INDEX (wtToTry ) - 1)) & m_iAvailableWeapons ) +#line 3066 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +&& HasAmmo (wtToTry )){ +#line 3068 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(wtToTry != m_iCurrentWeapon ){ +#line 3071 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iWantedWeapon = wtToTry ; +#line 3072 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bChangeWeapon = TRUE ; +#line 3073 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3075 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE ; +#line 3077 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 3079 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return FALSE ; +#line 3080 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3081 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3083 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::SelectNewWeapon() +#line 3084 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3085 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 3086 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_NONE : +#line 3087 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : case WEAPON_COLT : case WEAPON_DOUBLECOLT : +#line 3088 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : case WEAPON_DOUBLESHOTGUN : +#line 3089 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : case WEAPON_MINIGUN : case WEAPON_SNIPER : +#line 3090 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_MINIGUN ) || +#line 3091 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_TOMMYGUN ) || +#line 3092 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_DOUBLESHOTGUN ) || +#line 3093 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_SINGLESHOTGUN ) || +#line 3094 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_DOUBLECOLT ) || +#line 3095 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_COLT ) || +#line 3096 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_KNIFE ); +#line 3097 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3098 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : +#line 3099 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_ROCKETLAUNCHER ) || +#line 3100 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_GRENADELAUNCHER ) || +#line 3101 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_MINIGUN ) || +#line 3102 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_TOMMYGUN ) || +#line 3103 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_DOUBLESHOTGUN ) || +#line 3104 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_SINGLESHOTGUN ) || +#line 3105 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_DOUBLECOLT ) || +#line 3106 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_COLT ) || +#line 3107 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_KNIFE ); +#line 3108 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3109 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : +#line 3110 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : +#line 3111 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_ROCKETLAUNCHER ) || +#line 3112 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_GRENADELAUNCHER ) || +#line 3113 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_MINIGUN ) || +#line 3114 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_TOMMYGUN ) || +#line 3115 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_DOUBLESHOTGUN ) || +#line 3116 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_SINGLESHOTGUN ) || +#line 3117 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_DOUBLECOLT ) || +#line 3118 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_COLT ) || +#line 3119 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_KNIFE ); +#line 3120 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3121 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : case WEAPON_FLAMER : case WEAPON_CHAINSAW : +#line 3122 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_LASER ) || +#line 3123 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_FLAMER ) || +#line 3124 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_MINIGUN ) || +#line 3125 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_TOMMYGUN ) || +#line 3126 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_DOUBLESHOTGUN ) || +#line 3127 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_SINGLESHOTGUN ) || +#line 3128 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_DOUBLECOLT ) || +#line 3129 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_COLT ) || +#line 3130 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_KNIFE ); +#line 3131 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3132 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : +#line 3133 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponSelectOk (WEAPON_KNIFE ); +#line 3134 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERT (FALSE ); +#line 3135 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3136 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3139 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL CPlayerWeapons::HasAmmo(WeaponType EwtWeapon) { +#line 3140 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(EwtWeapon ){ +#line 3141 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : case WEAPON_COLT : case WEAPON_DOUBLECOLT : return TRUE ; +#line 3142 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : return (m_iShells > 0); +#line 3143 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : return (m_iShells > 1); +#line 3144 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : return (m_iBullets > 0); +#line 3145 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : return (m_iSniperBullets > 0); +#line 3146 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : return (m_iBullets > 0); +#line 3147 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : return (m_iRockets > 0); +#line 3148 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : return (m_iGrenades > 0); +#line 3149 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : return (m_iNapalm > 0); +#line 3150 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_CHAINSAW : return TRUE ; +#line 3151 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : return (m_iElectricity > 0); +#line 3152 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : return (m_iIronBalls > 0); +#line 3153 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3154 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return FALSE ; +#line 3155 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3160 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::PlayDefaultAnim(void) { +#line 3161 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 3162 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_NONE : +#line 3163 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3164 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : +#line 3165 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iKnifeStand ){ +#line 3166 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: m_moWeapon . PlayAnim (KNIFE_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3167 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 3: m_moWeapon . PlayAnim (KNIFE_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3168 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : ASSERTALWAYS ("Unknown knife stand."); +#line 3169 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3170 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3171 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : +#line 3172 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . PlayAnim (COLT_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE ); +#line 3173 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_COLT : +#line 3174 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (COLT_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3175 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : +#line 3176 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (SINGLESHOTGUN_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3177 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : +#line 3178 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (DOUBLESHOTGUN_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3179 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : +#line 3180 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (TOMMYGUN_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3181 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : +#line 3182 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (SNIPER_ANIM_WAIT01 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3183 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : +#line 3184 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (MINIGUN_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3185 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : +#line 3186 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (ROCKETLAUNCHER_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3187 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : +#line 3188 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (GRENADELAUNCHER_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3197 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : +#line 3198 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (FLAMER_ANIM_WAIT01 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3199 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_CHAINSAW : +#line 3200 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (CHAINSAW_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3201 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : +#line 3202 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (LASER_ANIM_WAIT01 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3207 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : +#line 3209 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (CANNON_ANIM_WAIT01 , AOF_LOOPING | AOF_NORESTART | AOF_SMOOTHCHANGE );break ; +#line 3210 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : +#line 3211 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("Unknown weapon."); +#line 3212 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3213 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3218 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::KnifeBoring(void) { +#line 3220 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3221 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iKnifeStand ){ +#line 3222 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: iAnim = KNIFE_ANIM_WAIT1 ;break ; +#line 3223 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 3: iAnim = KNIFE_ANIM_WAIT1 ;break ; +#line 3224 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3225 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3226 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3227 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3229 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::ColtBoring(void) { +#line 3231 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3232 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(IRnd () % 2){ +#line 3233 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: iAnim = COLT_ANIM_WAIT3 ;break ; +#line 3234 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: iAnim = COLT_ANIM_WAIT4 ;break ; +#line 3235 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3236 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3237 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3238 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3240 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::DoubleColtBoring(void) { +#line 3242 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3243 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(IRnd () % 2){ +#line 3244 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: iAnim = COLT_ANIM_WAIT3 ;break ; +#line 3245 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: iAnim = COLT_ANIM_WAIT4 ;break ; +#line 3246 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3247 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(IRnd () & 1){ +#line 3248 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3249 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3250 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 3251 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3252 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeaponSecond . GetAnimLength (iAnim ); +#line 3253 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3254 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3256 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::SingleShotgunBoring(void) { +#line 3258 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3259 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(IRnd () % 2){ +#line 3260 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: iAnim = SINGLESHOTGUN_ANIM_WAIT2 ;break ; +#line 3261 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: iAnim = SINGLESHOTGUN_ANIM_WAIT3 ;break ; +#line 3262 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3263 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3264 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3265 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3267 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::DoubleShotgunBoring(void) { +#line 3269 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3270 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(IRnd () % 3){ +#line 3271 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: iAnim = DOUBLESHOTGUN_ANIM_WAIT2 ;break ; +#line 3272 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: iAnim = DOUBLESHOTGUN_ANIM_WAIT3 ;break ; +#line 3273 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 2: iAnim = DOUBLESHOTGUN_ANIM_WAIT4 ;break ; +#line 3274 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3275 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3276 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3277 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3279 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::TommyGunBoring(void) { +#line 3281 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3282 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(IRnd () % 2){ +#line 3283 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: iAnim = TOMMYGUN_ANIM_WAIT2 ;break ; +#line 3284 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: iAnim = TOMMYGUN_ANIM_WAIT3 ;break ; +#line 3285 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3286 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3287 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3288 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3290 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::SniperBoring(void) { +#line 3292 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3293 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAnim = SNIPER_ANIM_WAIT01 ; +#line 3294 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3295 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3296 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3298 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::MiniGunBoring(void) { +#line 3300 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3301 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(IRnd () % 3){ +#line 3302 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: iAnim = MINIGUN_ANIM_WAIT2 ;break ; +#line 3303 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: iAnim = MINIGUN_ANIM_WAIT3 ;break ; +#line 3304 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 2: iAnim = MINIGUN_ANIM_WAIT4 ;break ; +#line 3305 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3306 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3307 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3308 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3310 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::RocketLauncherBoring(void) { +#line 3312 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (ROCKETLAUNCHER_ANIM_WAIT2 , AOF_SMOOTHCHANGE ); +#line 3313 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (ROCKETLAUNCHER_ANIM_WAIT2 ); +#line 3314 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3316 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::GrenadeLauncherBoring(void) { +#line 3318 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (GRENADELAUNCHER_ANIM_WAIT2 , AOF_SMOOTHCHANGE ); +#line 3319 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (GRENADELAUNCHER_ANIM_WAIT2 ); +#line 3320 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3355 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::FlamerBoring(void) { +#line 3357 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3358 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(IRnd () % 4){ +#line 3359 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: iAnim = FLAMER_ANIM_WAIT02 ;break ; +#line 3360 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: iAnim = FLAMER_ANIM_WAIT03 ;break ; +#line 3361 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 2: iAnim = FLAMER_ANIM_WAIT04 ;break ; +#line 3362 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 3: iAnim = FLAMER_ANIM_WAIT05 ;break ; +#line 3363 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3364 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3365 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3366 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3368 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::ChainsawBoring(void) { +#line 3370 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3371 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(IRnd () % 3){ +#line 3372 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: iAnim = CHAINSAW_ANIM_WAIT2 ;break ; +#line 3373 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: iAnim = CHAINSAW_ANIM_WAIT3 ;break ; +#line 3374 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 2: iAnim = CHAINSAW_ANIM_WAIT4 ;break ; +#line 3375 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3376 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3377 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3378 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3380 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::LaserBoring(void) { +#line 3382 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3383 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iAnim = LASER_ANIM_WAIT02 ; +#line 3384 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3385 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3386 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3402 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CPlayerWeapons::CannonBoring(void) { +#line 3404 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 3405 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(IRnd () % 3){ +#line 3406 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: iAnim = CANNON_ANIM_WAIT02 ;break ; +#line 3407 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: iAnim = CANNON_ANIM_WAIT03 ;break ; +#line 3408 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 2: iAnim = CANNON_ANIM_WAIT04 ;break ; +#line 3409 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3410 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , AOF_SMOOTHCHANGE ); +#line 3411 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_moWeapon . GetAnimLength (iAnim ); +#line 3412 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3415 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType CPlayerWeapons::FindRemapedPos(WeaponType wt) +#line 3416 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3417 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +for(INDEX i = 0;i < 18;i ++) +#line 3418 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3419 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(aiWeaponsRemap [ i ] == wt ){ +#line 3420 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return (WeaponType ) i ; +#line 3421 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3422 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3423 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERT ("Non-existant weapon in remap array!"); +#line 3424 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return (WeaponType ) 0; +#line 3425 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3428 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType CPlayerWeapons::PrimaryToSecondary(WeaponType wt) +#line 3429 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3430 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(wt == WEAPON_CHAINSAW ){ +#line 3431 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_KNIFE ; +#line 3432 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(wt == WEAPON_DOUBLECOLT ){ +#line 3433 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_COLT ; +#line 3434 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(wt == WEAPON_DOUBLESHOTGUN ){ +#line 3435 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_SINGLESHOTGUN ; +#line 3436 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(wt == WEAPON_MINIGUN ){ +#line 3437 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_TOMMYGUN ; +#line 3438 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(wt == WEAPON_ROCKETLAUNCHER ){ +#line 3439 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_GRENADELAUNCHER ; +#line 3440 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(wt == WEAPON_SNIPER ){ +#line 3441 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_FLAMER ; +#line 3442 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 3443 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return wt ; +#line 3444 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3445 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3447 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType CPlayerWeapons::SecondaryToPrimary(WeaponType wt) +#line 3448 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3449 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(wt == WEAPON_KNIFE ){ +#line 3450 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_CHAINSAW ; +#line 3451 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(wt == WEAPON_COLT ){ +#line 3452 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_DOUBLECOLT ; +#line 3453 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(wt == WEAPON_SINGLESHOTGUN ){ +#line 3454 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_DOUBLESHOTGUN ; +#line 3455 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(wt == WEAPON_TOMMYGUN ){ +#line 3456 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_MINIGUN ; +#line 3457 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(wt == WEAPON_GRENADELAUNCHER ){ +#line 3458 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_ROCKETLAUNCHER ; +#line 3459 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(wt == WEAPON_FLAMER ){ +#line 3460 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return WEAPON_SNIPER ; +#line 3461 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 3462 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return wt ; +#line 3463 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3464 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3494 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType CPlayerWeapons::FindWeaponInDirection(INDEX iDir) +#line 3495 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3496 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX wtOrg = FindRemapedPos (m_iWantedWeapon ); +#line 3497 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX wti = wtOrg ; +#line 3498 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FOREVER { +#line 3499 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(INDEX &) wti += iDir ; +#line 3500 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(wti < 1){ +#line 3501 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wti = WEAPON_IRONCANNON ; +#line 3502 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3503 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(wti > 14){ +#line 3504 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wti = WEAPON_KNIFE ; +#line 3505 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3506 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(wti == wtOrg ){ +#line 3507 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3508 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3509 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType wt = (WeaponType ) aiWeaponsRemap [ wti ]; +#line 3510 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if((((1 << (wt - 1)) & m_iAvailableWeapons ) && HasAmmo (wt ))){ +#line 3511 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return wt ; +#line 3512 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3513 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3514 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_iWantedWeapon ; +#line 3515 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3518 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::SelectWeaponChange(INDEX iSelect) +#line 3519 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3520 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType EwtTemp ; +#line 3522 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmWeaponChangeRequired = _pTimer -> CurrentTick (); +#line 3525 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iSelect == 0){ +#line 3526 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bChangeWeapon = TRUE ; +#line 3527 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iWantedWeapon = WEAPON_NONE ; +#line 3528 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return ; +#line 3529 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3532 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iSelect == - 4){ +#line 3533 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SelectNewWeapon (); +#line 3534 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return ; +#line 3535 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3538 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iSelect == - 3){ +#line 3539 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EwtTemp = GetAltWeapon (m_iWantedWeapon ); +#line 3542 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(iSelect == - 2){ +#line 3543 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EwtTemp = FindWeaponInDirection (- 1); +#line 3546 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(iSelect == - 1){ +#line 3547 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EwtTemp = FindWeaponInDirection (+ 1); +#line 3550 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 3552 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iSelect == GetSelectedWeapon (m_iWantedWeapon )){ +#line 3553 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EwtTemp = GetAltWeapon (m_iWantedWeapon ); +#line 3556 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 3557 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EwtTemp = GetStrongerWeapon (iSelect ); +#line 3560 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! ((1 << (EwtTemp - 1)) & m_iAvailableWeapons ) || ! HasAmmo (EwtTemp )){ +#line 3561 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +EwtTemp = GetAltWeapon (EwtTemp ); +#line 3562 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3563 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3564 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3567 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL bChange = (((1 << (EwtTemp - 1)) & m_iAvailableWeapons ) && HasAmmo (EwtTemp )); +#line 3568 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(bChange ){ +#line 3569 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iWantedWeapon = EwtTemp ; +#line 3570 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bChangeWeapon = TRUE ; +#line 3571 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3572 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3576 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CPlayerWeapons::MinigunSmoke() +#line 3577 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3578 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! hud_bShowWeapon ) +#line 3579 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3580 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return ; +#line 3581 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3583 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 3584 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pl . m_pstState != PST_DIVE ) +#line 3585 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3586 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL b3rdPersonView = TRUE ; +#line 3587 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pl . m_penCamera == NULL && pl . m_pen3rdPersonView == NULL ) +#line 3588 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3589 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +b3rdPersonView = FALSE ; +#line 3590 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3592 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX ctBulletsFired = ClampUp (m_iBulletsOnFireStart - m_iBullets , INDEX (200)); +#line 3593 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +for(INDEX iSmoke = 0;iSmoke < ctBulletsFired / 10;iSmoke ++) +#line 3594 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3595 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData * psldSmoke = & pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 3596 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plPipe ; +#line 3597 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(b3rdPersonView ) +#line 3598 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3599 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition3rdPersonView (FLOAT3D (afMinigunPipe3rdView [ 0 ] , +#line 3600 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +afMinigunPipe3rdView [ 1 ] , afMinigunPipe3rdView [ 2 ]) , plPipe , FALSE ); +#line 3601 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3602 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else +#line 3603 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3604 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afMinigunPipe [ 0 ] , afMinigunPipe [ 1 ] , afMinigunPipe [ 2 ]) , plPipe , FALSE ); +#line 3605 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3606 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D m ; +#line 3607 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (m , plPipe . pl_OrientationAngle ); +#line 3608 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_vPos = plPipe . pl_PositionVector + pl . en_vCurrentTranslationAbsolute * iSmoke * _pTimer -> TickQuantum ; +#line 3609 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp (m (1 , 2) , m (2 , 2) , m (3 , 2)); +#line 3610 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_vUp = vUp ; +#line 3611 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_tmLaunch = _pTimer -> CurrentTick () + iSmoke * _pTimer -> TickQuantum ; +#line 3612 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_estType = ESL_BULLET_SMOKE ; +#line 3613 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_fSize = 0.75f + ctBulletsFired / 50.0f; +#line 3614 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpeedRelative = FLOAT3D (- 0.06f , FRnd () / 4.0f , - 0.06f); +#line 3615 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_vSpeed = vSpeedRelative * m + pl . en_vCurrentTranslationAbsolute ; +#line 3616 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 3617 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3618 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3619 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} + +#line 3621 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL CPlayerWeapons::SniperZoomDiscrete(INDEX iDirection,BOOL & bZoomChanged) +#line 3622 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 3623 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +bZoomChanged = FALSE ; +#line 3625 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(iDirection > 0){ +#line 3626 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +for(INDEX i = 0;i < iSniperDiscreteZoomLevels ;i ++){ +#line 3627 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(afSniperZoom [ 2 * i ] < m_fSniperFOV ){ +#line 3628 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fSniperFOV = afSniperZoom [ 2 * i ]; +#line 3629 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fSniperFOVlast = m_fSniperFOV ; +#line 3630 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +bZoomChanged = TRUE ; +#line 3631 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3632 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3633 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3635 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 3636 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +for(INDEX i = iSniperDiscreteZoomLevels ;i > 0;i --){ +#line 3637 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(afSniperZoom [ 2 * i ] > m_fSniperFOV ){ +#line 3638 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fSniperFOV = afSniperZoom [ 2 * i ]; +#line 3639 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fSniperFOVlast = m_fSniperFOV ; +#line 3640 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +bZoomChanged = TRUE ; +#line 3641 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3642 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3643 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3644 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3645 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_fSniperFOV < 90.0f){ +#line 3646 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bSniping = TRUE ; +#line 3647 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3648 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else { +#line 3649 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bSniping = FALSE ; +#line 3650 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3651 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return m_bSniping ; +#line 3652 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +BOOL CPlayerWeapons:: +#line 3658 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChangeWeapon(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_ChangeWeapon + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::ChangeWeapon expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3660 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iCurrentWeapon != m_iWantedWeapon ){ +#line 3661 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fSniperFOV = m_fSniperFOVlast = m_fSniperMaxFOV ; +#line 3662 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bSniping = FALSE ; +#line 3663 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_penPlayer -> SendEvent (EWeaponChanged ()); +#line 3664 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3666 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bChangeWeapon = FALSE ; +#line 3668 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iCurrentWeapon != m_iWantedWeapon )){ Jump(STATE_CURRENT,0x01920010, FALSE, EInternal());return TRUE;} +#line 3688 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iPreviousWeapon = m_iCurrentWeapon ; +#line 3689 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +STATE_CPlayerWeapons_PutDown, TRUE; +Jump(STATE_CURRENT, 0x01920008, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920008_ChangeWeapon_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayerWeapons_PutDown, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01920009, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920009_ChangeWeapon_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920009 +const EEnd&__e= (EEnd&)__eeInput; +; +#line 3691 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iCurrentWeapon = m_iWantedWeapon ; +#line 3693 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +wpn_iCurrent = m_iCurrentWeapon ; +#line 3694 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +STATE_CPlayerWeapons_BringUp, TRUE; +Jump(STATE_CURRENT, 0x0192000a, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192000a_ChangeWeapon_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayerWeapons_BringUp, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x0192000b, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192000b_ChangeWeapon_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192000b +const EEnd&__e= (EEnd&)__eeInput; +; +#line 3696 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iCurrentWeapon == WEAPON_CHAINSAW ){ +#line 3697 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 3698 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeaponAmbient . Set3DParameters (30.0f , 3.0f , 1.0f , 1.0f); +#line 3699 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeaponAmbient , SOUND_CS_IDLE , SOF_3D | SOF_VOLUMETRIC | SOF_LOOP | SOF_SMOOTHCHANGE ); +#line 3700 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("ChainsawIdle");} +#line 3701 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x0192000f, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920010_ChangeWeapon_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920010 +if(!(m_iWantedWeapon == WEAPON_KNIFE )){ Jump(STATE_CURRENT,0x0192000e, FALSE, EInternal());return TRUE;} +#line 3706 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmWeaponChangeRequired = 0.0f; +#line 3707 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +STATE_CPlayerWeapons_ChangeKnifeStand, TRUE; +Jump(STATE_CURRENT, 0x0192000c, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192000c_ChangeWeapon_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192000c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayerWeapons_ChangeKnifeStand, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x0192000d, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192000d_ChangeWeapon_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192000d +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x0192000e, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x0192000e_ChangeWeapon_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192000e +Jump(STATE_CURRENT,0x0192000f, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x0192000f_ChangeWeapon_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192000f + +#line 3715 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 3720 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PutDown(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_PutDown + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::PutDown expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3722 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 3723 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_NONE : +#line 3724 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3726 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : +#line 3727 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iKnifeStand == 1){ +#line 3728 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = KNIFE_ANIM_PULLOUT ; +#line 3729 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(m_iKnifeStand == 3){ +#line 3730 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = KNIFE_ANIM_PULLOUT ; +#line 3731 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3732 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3733 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : case WEAPON_COLT : +#line 3734 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = COLT_ANIM_DEACTIVATE ; +#line 3735 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3736 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : +#line 3737 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = SINGLESHOTGUN_ANIM_DEACTIVATE ; +#line 3738 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3739 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : +#line 3740 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = DOUBLESHOTGUN_ANIM_DEACTIVATE ; +#line 3741 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3742 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : +#line 3743 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = TOMMYGUN_ANIM_DEACTIVATE ; +#line 3744 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3745 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : +#line 3746 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = SNIPER_ANIM_DEACTIVATE ; +#line 3747 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3748 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : +#line 3749 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = MINIGUN_ANIM_DEACTIVATE ; +#line 3750 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3751 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : +#line 3752 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = ROCKETLAUNCHER_ANIM_DEACTIVATE ; +#line 3753 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3754 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : +#line 3755 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = GRENADELAUNCHER_ANIM_DEACTIVATE ; +#line 3756 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3760 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : +#line 3761 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = FLAMER_ANIM_DEACTIVATE ; +#line 3762 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3763 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_CHAINSAW : { +#line 3764 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 3765 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeaponAmbient , SOUND_CS_BRINGDOWN , SOF_3D | SOF_VOLUMETRIC | SOF_SMOOTHCHANGE ); +#line 3766 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_StopEffect ("ChainsawIdle");} +#line 3767 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = CHAINSAW_ANIM_DEACTIVATE ; +#line 3768 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 3769 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : +#line 3770 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = LASER_ANIM_DEACTIVATE ; +#line 3771 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3777 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : +#line 3779 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = CANNON_ANIM_DEACTIVATE ; +#line 3780 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3781 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : ASSERTALWAYS ("Unknown weapon."); +#line 3782 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3784 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * ((CPlayer &) * m_penPlayer ) . m_penAnimator ; +#line 3785 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plan . BodyPushAnimation (); +#line 3786 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iCurrentWeapon == WEAPON_NONE ){ +#line 3787 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 3787 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 3788 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3791 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iCurrentWeapon == WEAPON_COLT && m_iWantedWeapon == WEAPON_DOUBLECOLT ){ +#line 3792 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 3792 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 3793 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3796 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iCurrentWeapon == WEAPON_DOUBLECOLT ){ +#line 3797 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . PlayAnim (m_iAnim , 0); +#line 3798 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3801 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iCurrentWeapon == WEAPON_DOUBLECOLT && m_iWantedWeapon == WEAPON_COLT )){ Jump(STATE_CURRENT,0x01920014, FALSE, EInternal());return TRUE;} +#line 3802 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (m_iAnim )); +Jump(STATE_CURRENT, 0x01920012, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920012_PutDown_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920012 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920013, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920013_PutDown_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920013 +; +#line 3803 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 3803 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE;Jump(STATE_CURRENT,0x01920014, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920014_PutDown_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920014 + +#line 3817 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL bNowColt = m_iCurrentWeapon == WEAPON_COLT || m_iCurrentWeapon == WEAPON_DOUBLECOLT ; +#line 3818 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL bWantedColt = m_iWantedWeapon == WEAPON_COLT || m_iWantedWeapon == WEAPON_DOUBLECOLT ; +#line 3819 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(bNowColt && ! bWantedColt ){ +#line 3820 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iColtBullets = 6; +#line 3821 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3823 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (m_iAnim , 0); +#line 3824 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (m_iAnim )); +Jump(STATE_CURRENT, 0x01920015, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920015_PutDown_04(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920016, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920016_PutDown_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920016 +; +#line 3825 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 3825 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 3829 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BringUp(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_BringUp + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::BringUp expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3831 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ResetWeaponMovingOffset (); +#line 3833 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetCurrentWeaponModel (); +#line 3835 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 3836 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : +#line 3837 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = KNIFE_ANIM_PULL ; +#line 3838 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iKnifeStand = 1; +#line 3839 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3840 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_COLT : case WEAPON_DOUBLECOLT : +#line 3841 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = COLT_ANIM_ACTIVATE ; +#line 3842 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_REMOVE ); +#line 3843 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (1 , FLARE_REMOVE ); +#line 3844 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3845 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : +#line 3846 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = SINGLESHOTGUN_ANIM_ACTIVATE ; +#line 3847 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_REMOVE ); +#line 3848 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3849 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : +#line 3850 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = DOUBLESHOTGUN_ANIM_ACTIVATE ; +#line 3851 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_REMOVE ); +#line 3852 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3853 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : +#line 3854 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = TOMMYGUN_ANIM_ACTIVATE ; +#line 3855 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_REMOVE ); +#line 3856 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3857 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : +#line 3858 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = SNIPER_ANIM_ACTIVATE ; +#line 3859 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_REMOVE ); +#line 3860 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3861 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : { +#line 3862 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CAttachmentModelObject * amo = m_moWeapon . GetAttachmentModel (MINIGUN_ATTACHMENT_BARRELS ); +#line 3863 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunLast = m_aMiniGun = amo -> amo_plRelative . pl_OrientationAngle (3); +#line 3864 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = MINIGUN_ANIM_ACTIVATE ; +#line 3865 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_REMOVE ); +#line 3866 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 3867 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : +#line 3868 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = ROCKETLAUNCHER_ANIM_ACTIVATE ; +#line 3869 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3870 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : +#line 3871 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = GRENADELAUNCHER_ANIM_ACTIVATE ; +#line 3872 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3876 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : +#line 3877 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = FLAMER_ANIM_ACTIVATE ; +#line 3878 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3879 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_CHAINSAW : { +#line 3880 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = CHAINSAW_ANIM_ACTIVATE ; +#line 3881 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 3882 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeaponAmbient . Set3DParameters (30.0f , 3.0f , 1.0f , 1.0f); +#line 3883 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeaponAmbient , SOUND_CS_BRINGUP , SOF_3D | SOF_VOLUMETRIC | SOF_LOOP ); +#line 3884 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 3885 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : +#line 3886 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = LASER_ANIM_ACTIVATE ; +#line 3887 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3892 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : +#line 3894 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iAnim = CANNON_ANIM_ACTIVATE ; +#line 3895 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3896 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_NONE : +#line 3897 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 3898 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : ASSERTALWAYS ("Unknown weapon."); +#line 3899 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3901 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayerAnimator & plan = (CPlayerAnimator &) * ((CPlayer &) * m_penPlayer ) . m_penAnimator ; +#line 3902 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +plan . BodyPullAnimation (); +#line 3905 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iPreviousWeapon == WEAPON_DOUBLECOLT && m_iCurrentWeapon == WEAPON_COLT ){ +#line 3907 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmWeaponChangeRequired -= hud_tmWeaponsOnScreen / 2; +#line 3908 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 3908 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 3909 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3912 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iCurrentWeapon == WEAPON_DOUBLECOLT ){ +#line 3913 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . PlayAnim (m_iAnim , 0); +#line 3914 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3917 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iPreviousWeapon == WEAPON_COLT && m_iCurrentWeapon == WEAPON_DOUBLECOLT )){ Jump(STATE_CURRENT,0x0192001a, FALSE, EInternal());return TRUE;} +#line 3918 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (m_iAnim )); +Jump(STATE_CURRENT, 0x01920018, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920018_BringUp_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920018 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920019, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920019_BringUp_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920019 +; +#line 3920 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmWeaponChangeRequired -= hud_tmWeaponsOnScreen / 2; +#line 3921 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 3921 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE;Jump(STATE_CURRENT,0x0192001a, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x0192001a_BringUp_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192001a + +#line 3937 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (m_iAnim , 0); +#line 3938 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (m_iAnim )); +Jump(STATE_CURRENT, 0x0192001b, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192001b_BringUp_04(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192001b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0192001c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192001c_BringUp_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192001c +; +#line 3948 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmWeaponChangeRequired -= hud_tmWeaponsOnScreen / 2; +#line 3950 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 3950 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 3957 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3959 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 3960 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_SILENCE , SOF_3D | SOF_VOLUMETRIC ); +#line 3962 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmWeaponChangeRequired = 0; +#line 3964 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = TRUE ; +#line 3965 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bHasAmmo = HasAmmo (m_iCurrentWeapon ); +#line 3968 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! m_bHasAmmo ){ +#line 3969 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SelectNewWeapon (); +#line 3970 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE; +#line 3971 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 3974 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Setup3DSoundParameters (); +#line 3977 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iCurrentWeapon == WEAPON_MINIGUN )){ Jump(STATE_CURRENT,0x01920029, FALSE, EInternal());return TRUE;} +#line 3978 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_MiniGunSpinUp, TRUE, EVoid());return TRUE;Jump(STATE_CURRENT,0x01920028, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920029_Fire_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920029 +if(!(m_iCurrentWeapon == WEAPON_FLAMER )){ Jump(STATE_CURRENT,0x01920027, FALSE, EInternal());return TRUE;} +#line 3980 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_FlamerStart, TRUE, EVoid());return TRUE;Jump(STATE_CURRENT,0x01920026, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920027_Fire_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920027 +if(!(m_iCurrentWeapon == WEAPON_CHAINSAW )){ Jump(STATE_CURRENT,0x01920025, FALSE, EInternal());return TRUE;} +#line 3982 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_ChainsawFire, TRUE, EVoid());return TRUE;Jump(STATE_CURRENT,0x01920024, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920025_Fire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920025 +if(!(m_iCurrentWeapon == WEAPON_LASER )){ Jump(STATE_CURRENT,0x01920023, FALSE, EInternal());return TRUE;} +#line 3986 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_SHOTGUN_FIRESHORT , AOF_LOOPING );Jump(STATE_CURRENT,0x01920022, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920023_Fire_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920023 +if(!(m_iCurrentWeapon == WEAPON_TOMMYGUN )){ Jump(STATE_CURRENT,0x01920021, FALSE, EInternal());return TRUE;} +#line 3988 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +STATE_CPlayerWeapons_TommyGunStart, TRUE; +Jump(STATE_CURRENT, 0x0192001e, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192001e_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192001e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayerWeapons_TommyGunStart, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x0192001f, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192001f_Fire_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192001f +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x01920020, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920021_Fire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920021 +if((m_iCurrentWeapon == WEAPON_IRONCANNON )){ +#line 3990 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_CannonFireStart, TRUE, EVoid());return TRUE; +#line 3991 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x01920020, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x01920020_Fire_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920020 +Jump(STATE_CURRENT,0x01920022, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x01920022_Fire_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920022 +Jump(STATE_CURRENT,0x01920024, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x01920024_Fire_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920024 +Jump(STATE_CURRENT,0x01920026, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x01920026_Fire_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920026 +Jump(STATE_CURRENT,0x01920028, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x01920028_Fire_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920028 + +#line 3994 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iLastBulletPosition = FLOAT3D (32000.0f , 32000.0f , 32000.0f); +#line 3997 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iLaserBarrel = 0; +#line 3999 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT,0x0192002c, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x0192002c_Fire_15(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192002c +if(!(HoldingFire () && m_bHasAmmo )){ Jump(STATE_CURRENT,0x0192002d, FALSE, EInternal());return TRUE;} +#line 4001 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayerAnimator &) * ((CPlayer &) * m_penPlayer ) . m_penAnimator ) . m_fLastActionTime = _pTimer -> CurrentTick (); +#line 4002 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x0192002a, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192002a_Fire_13(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192002a +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 4005 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 4006 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : Call(STATE_CURRENT, STATE_CPlayerWeapons_SwingKnife, TRUE, EVoid());return TRUE;break ; +#line 4007 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_COLT : Call(STATE_CURRENT, STATE_CPlayerWeapons_FireColt, TRUE, EVoid());return TRUE;break ; +#line 4008 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : Call(STATE_CURRENT, STATE_CPlayerWeapons_FireDoubleColt, TRUE, EVoid());return TRUE;break ; +#line 4009 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : Call(STATE_CURRENT, STATE_CPlayerWeapons_FireSingleShotgun, TRUE, EVoid());return TRUE;break ; +#line 4010 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : Call(STATE_CURRENT, STATE_CPlayerWeapons_FireDoubleShotgun, TRUE, EVoid());return TRUE;break ; +#line 4011 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : Call(STATE_CURRENT, STATE_CPlayerWeapons_FireTommyGun, TRUE, EVoid());return TRUE;break ; +#line 4012 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : Call(STATE_CURRENT, STATE_CPlayerWeapons_FireSniper, TRUE, EVoid());return TRUE;break ; +#line 4013 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : Call(STATE_CURRENT, STATE_CPlayerWeapons_FireRocketLauncher, TRUE, EVoid());return TRUE;break ; +#line 4014 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : Call(STATE_CURRENT, STATE_CPlayerWeapons_FireGrenadeLauncher, TRUE, EVoid());return TRUE;break ; +#line 4015 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : Call(STATE_CURRENT, STATE_CPlayerWeapons_FireLaser, TRUE, EVoid());return TRUE;break ; +#line 4016 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : ASSERTALWAYS ("Unknown weapon."); +#line 4017 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4018 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 4019 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnd):{const EEnd&e= (EEnd&)__eeInput; + +#line 4021 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +UnsetTimer();Jump(STATE_CURRENT,0x0192002b, FALSE, EInternal());return TRUE; +#line 4022 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 4023 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}return TRUE;}BOOL CPlayerWeapons::H0x0192002b_Fire_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192002b +Jump(STATE_CURRENT,0x0192002c, FALSE, EInternal());return TRUE; +#line 4024 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}BOOL CPlayerWeapons::H0x0192002d_Fire_16(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192002d + +#line 4027 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 4028 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : {Jump(STATE_CURRENT, STATE_CPlayerWeapons_TommyGunStop, TRUE, EVoid());return TRUE;break ;} +#line 4029 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : {Jump(STATE_CURRENT, STATE_CPlayerWeapons_MiniGunSpinDown, TRUE, EVoid());return TRUE;break ;} +#line 4030 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : {Jump(STATE_CURRENT, STATE_CPlayerWeapons_FlamerStop, TRUE, EVoid());return TRUE;break ;} +#line 4032 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : { +#line 4033 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimationOff (); +#line 4034 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE; +#line 4035 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4036 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default :{Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE;} +#line 4037 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4042 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SwingKnife(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_SwingKnife + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::SwingKnife expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4043 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iSwing ; +#line 4046 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_KNIFE_ATTACK , 0); +#line 4048 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4050 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iKnifeStand ){ +#line 4051 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: +#line 4052 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iSwing = IRnd () % 2; +#line 4053 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(iSwing ){ +#line 4054 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: m_iAnim = KNIFE_ANIM_ATTACK01 ;m_fAnimWaitTime = 0.25f; +#line 4055 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_KNIFE_BACK , SOF_3D | SOF_VOLUMETRIC ); +#line 4056 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Knife_back");} +#line 4057 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 4058 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: m_iAnim = KNIFE_ANIM_ATTACK02 ;m_fAnimWaitTime = 0.35f; +#line 4059 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon1 , SOUND_KNIFE_BACK , SOF_3D | SOF_VOLUMETRIC ); +#line 4060 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Knife_back");} +#line 4061 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 4062 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4063 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 4064 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 3: +#line 4065 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +iSwing = IRnd () % 2; +#line 4066 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(iSwing ){ +#line 4067 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: m_iAnim = KNIFE_ANIM_ATTACK01 ;m_fAnimWaitTime = 0.50f; +#line 4068 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon1 , SOUND_KNIFE_BACK , SOF_3D | SOF_VOLUMETRIC ); +#line 4069 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Knife_back");} +#line 4070 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 4071 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: m_iAnim = KNIFE_ANIM_ATTACK02 ;m_fAnimWaitTime = 0.50f; +#line 4072 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon3 , SOUND_KNIFE_BACK , SOF_3D | SOF_VOLUMETRIC ); +#line 4073 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Knife_back");} +#line 4074 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 4075 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4076 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ; +#line 4077 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4078 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (m_iAnim , 0); +#line 4079 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(CutWithKnife (0 , 0 , 3.0f , 2.0f , 0.5f , ((GetSP () -> sp_bCooperative ) ? 100.0f : 50.0f)))){ Jump(STATE_CURRENT,0x01920037, FALSE, EInternal());return TRUE;} +#line 4080 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_fAnimWaitTime ); +Jump(STATE_CURRENT, 0x0192002f, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192002f_SwingKnife_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192002f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920030, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920030_SwingKnife_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920030 +;Jump(STATE_CURRENT,0x01920036, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920037_SwingKnife_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920037 +if(!(TRUE )){ Jump(STATE_CURRENT,0x01920035, FALSE, EInternal());return TRUE;} +#line 4082 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_fAnimWaitTime / 2); +Jump(STATE_CURRENT, 0x01920031, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920031_SwingKnife_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920031 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920032, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920032_SwingKnife_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920032 +; +#line 4083 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CutWithKnife (0 , 0 , 3.0f , 2.0f , 0.5f , ((GetSP () -> sp_bCooperative ) ? 100.0f : 50.0f)); +#line 4084 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_fAnimWaitTime / 2); +Jump(STATE_CURRENT, 0x01920033, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920033_SwingKnife_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920033 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920034, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920034_SwingKnife_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920034 +;Jump(STATE_CURRENT,0x01920035, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920035_SwingKnife_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920035 +Jump(STATE_CURRENT,0x01920036, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x01920036_SwingKnife_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920036 + +#line 4087 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_moWeapon . GetAnimLength (m_iAnim ) - m_fAnimWaitTime >= _pTimer -> TickQuantum )){ Jump(STATE_CURRENT,0x0192003a, FALSE, EInternal());return TRUE;} +#line 4088 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (m_iAnim ) - m_fAnimWaitTime ); +Jump(STATE_CURRENT, 0x01920038, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920038_SwingKnife_10(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920038 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920039, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920039_SwingKnife_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920039 +;Jump(STATE_CURRENT,0x0192003a, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x0192003a_SwingKnife_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192003a + +#line 4090 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4090 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4094 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireColt(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FireColt + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FireColt expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4095 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_COLT_FIRERIGHT , 0); +#line 4098 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireOneBullet (wpn_fFX [ WEAPON_COLT ] , wpn_fFY [ WEAPON_COLT ] , 500.0f , +#line 4099 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((GetSP () -> sp_bCooperative ) ? 10.0f : 20.0f)); +#line 4102 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Colt_fire");} +#line 4103 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DoRecoil (); +#line 4104 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (40.0f); +#line 4105 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iColtBullets --; +#line 4106 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_ADD ); +#line 4107 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_COLT_SHOTGUN , 0); +#line 4110 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4111 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_COLT_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 4126 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iAnim ; +#line 4127 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(IRnd () % 3){ +#line 4128 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: iAnim = COLT_ANIM_FIRE1 ;break ; +#line 4129 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: iAnim = COLT_ANIM_FIRE2 ;break ; +#line 4130 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 2: iAnim = COLT_ANIM_FIRE3 ;break ; +#line 4131 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4132 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (iAnim , 0); +#line 4133 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (iAnim ) - 0.05f); +Jump(STATE_CURRENT, 0x0192003c, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192003c_FireColt_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192003c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0192003d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192003d_FireColt_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192003d +; +#line 4134 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (COLT_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART ); +#line 4137 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iColtBullets == 0){ +#line 4138 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_ReloadColt, TRUE, EVoid());return TRUE; +#line 4139 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4140 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4140 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4144 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ReloadColt(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_ReloadColt + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::ReloadColt expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4145 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iColtBullets >= 6){ +#line 4146 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4146 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 4147 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4149 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4150 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon1 , SOUND_COLT_RELOAD , SOF_3D | SOF_VOLUMETRIC ); +#line 4152 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (COLT_ANIM_RELOAD , 0); +#line 4153 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Colt_reload");} +#line 4154 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (COLT_ANIM_RELOAD )); +Jump(STATE_CURRENT, 0x0192003f, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192003f_ReloadColt_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192003f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920040, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920040_ReloadColt_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920040 +; +#line 4155 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iColtBullets = 6; +#line 4156 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4156 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4160 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireDoubleColt(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FireDoubleColt + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FireDoubleColt expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4162 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_COLT_FIRERIGHT , 0); +#line 4163 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireOneBullet (wpn_fFX [ WEAPON_DOUBLECOLT ] , wpn_fFY [ WEAPON_DOUBLECOLT ] , 500.0f , 10.0f); +#line 4164 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Colt_fire");} +#line 4179 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DoRecoil (); +#line 4180 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (50.0f); +#line 4181 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iColtBullets --; +#line 4182 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_ADD ); +#line 4183 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_COLT_SHOTGUN , 0); +#line 4185 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & plSnd = (CPlayer &) * m_penPlayer ; +#line 4186 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (plSnd . m_soWeapon0 , SOUND_COLT_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 4189 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(IRnd () % 3){ +#line 4190 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: m_iAnim = COLT_ANIM_FIRE1 ;break ; +#line 4191 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: m_iAnim = COLT_ANIM_FIRE2 ;break ; +#line 4192 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 2: m_iAnim = COLT_ANIM_FIRE3 ;break ; +#line 4193 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4194 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (m_iAnim , 0); +#line 4195 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (m_iAnim ) / 2); +Jump(STATE_CURRENT, 0x01920042, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920042_FireDoubleColt_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920042 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920043, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920043_FireDoubleColt_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920043 +; +#line 4198 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_COLT_FIRELEFT , 0); +#line 4199 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bMirrorFire = TRUE ; +#line 4200 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireOneBullet (wpn_fFX [ WEAPON_DOUBLECOLT ] , wpn_fFY [ WEAPON_DOUBLECOLT ] , 500.0f , 10.0f); +#line 4201 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Colt_fire");} +#line 4216 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DoRecoil (); +#line 4217 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iSecondFlare = FLARE_ADD ; +#line 4218 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayerAnimator &) * ((CPlayer &) * m_penPlayer ) . m_penAnimator ) . m_iSecondFlare = FLARE_ADD ; +#line 4219 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_COLT_SHOTGUN , 0); +#line 4220 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bMirrorFire = FALSE ; +#line 4222 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4223 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon1 , SOUND_COLT_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 4225 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . PlayAnim (m_iAnim , 0); +#line 4226 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (m_iAnim ) / 2); +Jump(STATE_CURRENT, 0x01920044, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920044_FireDoubleColt_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920044 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920045, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920045_FireDoubleColt_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920045 +; +#line 4229 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iColtBullets == 0){ +#line 4230 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_ReloadDoubleColt, TRUE, EVoid());return TRUE; +#line 4231 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4232 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4232 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4236 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ReloadDoubleColt(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_ReloadDoubleColt + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::ReloadDoubleColt expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4237 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iColtBullets >= 6){ +#line 4238 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4238 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 4239 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4240 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (COLT_ANIM_RELOAD , 0); +#line 4242 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4243 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon2 , SOUND_COLT_RELOAD , SOF_3D | SOF_VOLUMETRIC ); +#line 4245 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (COLT_ANIM_RELOAD ) / 2); +Jump(STATE_CURRENT, 0x01920047, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920047_ReloadDoubleColt_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920047 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920048, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920048_ReloadDoubleColt_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920048 +; +#line 4247 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . PlayAnim (COLT_ANIM_RELOAD , 0); +#line 4249 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4250 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon3 , SOUND_COLT_RELOAD , SOF_3D | SOF_VOLUMETRIC ); +#line 4251 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Colt_reload");} +#line 4254 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (COLT_ANIM_RELOAD ) - 0.25f); +Jump(STATE_CURRENT, 0x01920049, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920049_ReloadDoubleColt_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920049 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0192004a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192004a_ReloadDoubleColt_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192004a +; +#line 4256 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iColtBullets = 6; +#line 4257 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4257 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4261 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireSingleShotgun(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FireSingleShotgun + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FireSingleShotgun expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4263 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iShells > 0)){ Jump(STATE_CURRENT,0x01920051, FALSE, EInternal());return TRUE;} +#line 4264 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_SHOTGUN_FIRELONG , 0); +#line 4265 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireBullets (wpn_fFX [ WEAPON_SINGLESHOTGUN ] , wpn_fFY [ WEAPON_SINGLESHOTGUN ] , +#line 4266 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +500.0f , 10.0f , 7 , afSingleShotgunPellets , 0.2f , 0.03f); +#line 4267 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DoRecoil (); +#line 4268 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (60.0f); +#line 4269 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Snglshotgun_fire");} +#line 4270 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DecAmmo (m_iShells , 1); +#line 4271 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_ADD ); +#line 4272 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_COLT_SHOTGUN , 0); +#line 4273 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (GetSP () -> sp_bCooperative ? SINGLESHOTGUN_ANIM_FIRE1 : SINGLESHOTGUN_ANIM_FIRE1FAST , 0); +#line 4275 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4276 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_SINGLESHOTGUN_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 4278 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(hud_bShowWeapon ) +#line 4279 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4280 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pl . m_pstState == PST_DIVE ) +#line 4281 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4283 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sldBubble = pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 4284 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plShell ; +#line 4285 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afSingleShotgunShellPos [ 0 ] , +#line 4286 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +afSingleShotgunShellPos [ 1 ] , afSingleShotgunShellPos [ 2 ]) , plShell , FALSE ); +#line 4287 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D m ; +#line 4288 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (m , plShell . pl_OrientationAngle ); +#line 4289 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp (m (1 , 2) , m (2 , 2) , m (3 , 2)); +#line 4290 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vPos = plShell . pl_PositionVector ; +#line 4291 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vUp = vUp ; +#line 4292 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 4293 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_estType = ESL_BUBBLE ; +#line 4294 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpeedRelative = FLOAT3D (0.3f , 0.0f , 0.0f); +#line 4295 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vSpeed = vSpeedRelative * m ; +#line 4296 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4297 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4298 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else +#line 4299 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4301 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sldPipe1 = pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 4302 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plPipe ; +#line 4303 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afSingleShotgunPipe [ 0 ] , afSingleShotgunPipe [ 1 ] , afSingleShotgunPipe [ 2 ]) , plPipe , FALSE ); +#line 4304 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D m ; +#line 4305 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (m , plPipe . pl_OrientationAngle ); +#line 4306 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp (m (1 , 2) , m (2 , 2) , m (3 , 2)); +#line 4307 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe1 . sld_vPos = plPipe . pl_PositionVector ; +#line 4308 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe1 . sld_vUp = vUp ; +#line 4309 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe1 . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 4310 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe1 . sld_estType = ESL_SHOTGUN_SMOKE ; +#line 4311 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpeedRelative = FLOAT3D (0 , 0.0f , - 12.5f); +#line 4312 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe1 . sld_vSpeed = vSpeedRelative * m ; +#line 4313 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4314 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4315 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4317 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(GetSP () -> sp_bCooperative ? 0.5f : 0.375); +Jump(STATE_CURRENT, 0x0192004c, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192004c_FireSingleShotgun_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192004c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0192004d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192004d_FireSingleShotgun_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192004d +; +#line 4321 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plShell ; +#line 4322 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afSingleShotgunShellPos [ 0 ] , afSingleShotgunShellPos [ 1 ] , afSingleShotgunShellPos [ 2 ]) , plShell , FALSE ); +#line 4324 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D mRot ; +#line 4325 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (mRot , plShell . pl_OrientationAngle ); +#line 4327 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(hud_bShowWeapon ) +#line 4328 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4329 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer * penPlayer = GetPlayer (); +#line 4330 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sld = penPlayer -> m_asldData [ penPlayer -> m_iFirstEmptySLD ]; +#line 4331 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vPos = plShell . pl_PositionVector ; +#line 4332 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpeedRelative = FLOAT3D (FRnd () + 2.0f , FRnd () + 5.0f , - FRnd () - 2.0f); +#line 4333 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vSpeed = vSpeedRelative * mRot ; +#line 4335 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOATmatrix3D & m = penPlayer -> GetRotationMatrix (); +#line 4336 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp (m (1 , 2) , m (2 , 2) , m (3 , 2)); +#line 4337 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vUp = vUp ; +#line 4338 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 4339 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_estType = ESL_SHOTGUN ; +#line 4341 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penPlayer -> m_iFirstEmptySLD = (penPlayer -> m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4342 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4345 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength ( +#line 4346 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(GetSP () -> sp_bCooperative ? SINGLESHOTGUN_ANIM_FIRE1 : SINGLESHOTGUN_ANIM_FIRE1FAST )) - +#line 4347 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(GetSP () -> sp_bCooperative ? 0.5f : 0.375f)); +Jump(STATE_CURRENT, 0x0192004e, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192004e_FireSingleShotgun_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192004e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0192004f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192004f_FireSingleShotgun_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192004f +; +#line 4349 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iShells <= 0){SelectNewWeapon ();}Jump(STATE_CURRENT,0x01920050, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920051_FireSingleShotgun_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920051 +{ +#line 4351 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("SingleShotgun - Auto weapon change not working."); +#line 4352 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = m_bHasAmmo = FALSE ; +#line 4353 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x01920050, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x01920050_FireSingleShotgun_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920050 + +#line 4354 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4354 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4358 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireDoubleShotgun(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FireDoubleShotgun + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FireDoubleShotgun expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4360 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iShells > 1)){ Jump(STATE_CURRENT,0x01920058, FALSE, EInternal());return TRUE;} +#line 4361 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_SHOTGUN_FIRELONG , 0); +#line 4362 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireBullets (wpn_fFX [ WEAPON_DOUBLESHOTGUN ] , wpn_fFY [ WEAPON_DOUBLESHOTGUN ] , +#line 4363 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +500.0f , 10.0f , 14 , afDoubleShotgunPellets , 0.3f , 0.03f); +#line 4364 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DoRecoil (); +#line 4365 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (70.0f); +#line 4366 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Dblshotgun_fire");} +#line 4367 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DecAmmo (m_iShells , 2); +#line 4368 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_ADD ); +#line 4369 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_COLT_SHOTGUN , 0); +#line 4370 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (GetSP () -> sp_bCooperative ? DOUBLESHOTGUN_ANIM_FIRE : DOUBLESHOTGUN_ANIM_FIREFAST , 0); +#line 4371 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeaponSecond . PlayAnim (GetSP () -> sp_bCooperative ? HANDWITHAMMO_ANIM_FIRE : HANDWITHAMMO_ANIM_FIREFAST , 0); +#line 4373 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4374 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (50.0f , 5.0f , 1.5f , 1.0f); +#line 4375 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_DOUBLESHOTGUN_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 4377 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(hud_bShowWeapon ) +#line 4378 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4379 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pl . m_pstState == PST_DIVE ) +#line 4380 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4382 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sldBubble1 = pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 4383 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plShell ; +#line 4384 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (- 0.11f , 0.1f , - 0.3f) , plShell , FALSE ); +#line 4387 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D m ; +#line 4388 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (m , plShell . pl_OrientationAngle ); +#line 4389 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp (m (1 , 2) , m (2 , 2) , m (3 , 2)); +#line 4390 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble1 . sld_vPos = plShell . pl_PositionVector ; +#line 4391 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble1 . sld_vUp = vUp ; +#line 4392 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble1 . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 4393 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble1 . sld_estType = ESL_BUBBLE ; +#line 4394 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpeedRelative = FLOAT3D (- 0.1f , 0.0f , 0.01f); +#line 4395 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble1 . sld_vSpeed = vSpeedRelative * m ; +#line 4396 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4397 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sldBubble2 = pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 4399 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble2 = sldBubble1 ; +#line 4400 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vSpeedRelative = FLOAT3D (0.1f , 0.0f , - 0.2f); +#line 4401 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble2 . sld_vSpeed = vSpeedRelative * m ; +#line 4402 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4403 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4404 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else +#line 4405 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4407 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sldPipe1 = pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 4408 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plPipe ; +#line 4409 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afDoubleShotgunPipe [ 0 ] , afDoubleShotgunPipe [ 1 ] , afDoubleShotgunPipe [ 2 ]) , plPipe , FALSE ); +#line 4410 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D m ; +#line 4411 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (m , plPipe . pl_OrientationAngle ); +#line 4412 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp (m (1 , 2) , m (2 , 2) , m (3 , 2)); +#line 4413 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe1 . sld_vPos = plPipe . pl_PositionVector ; +#line 4414 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe1 . sld_vUp = vUp ; +#line 4415 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe1 . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 4416 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe1 . sld_estType = ESL_SHOTGUN_SMOKE ; +#line 4417 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpeedRelative = FLOAT3D (- 1 , 0.0f , - 12.5f); +#line 4418 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe1 . sld_vSpeed = vSpeedRelative * m ; +#line 4419 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4421 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sldPipe2 = pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 4422 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe2 = sldPipe1 ; +#line 4423 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vSpeedRelative = FLOAT3D (1 , 0.0f , - 12.5f); +#line 4424 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldPipe2 . sld_vSpeed = vSpeedRelative * m ; +#line 4425 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4426 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4427 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4429 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(GetSP () -> sp_bCooperative ? 0.25f : 0.15f); +Jump(STATE_CURRENT, 0x01920053, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920053_FireDoubleShotgun_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920053 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920054, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920054_FireDoubleShotgun_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920054 +; +#line 4430 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iShells >= 2){ +#line 4431 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4432 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon1 , SOUND_DOUBLESHOTGUN_RELOAD , SOF_3D | SOF_VOLUMETRIC ); +#line 4433 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4434 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength ( +#line 4435 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(GetSP () -> sp_bCooperative ? DOUBLESHOTGUN_ANIM_FIRE : DOUBLESHOTGUN_ANIM_FIREFAST )) - +#line 4436 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(GetSP () -> sp_bCooperative ? 0.25f : 0.15f)); +Jump(STATE_CURRENT, 0x01920055, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920055_FireDoubleShotgun_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920055 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920056, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920056_FireDoubleShotgun_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920056 +; +#line 4438 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iShells <= 1){SelectNewWeapon ();}Jump(STATE_CURRENT,0x01920057, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920058_FireDoubleShotgun_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920058 +{ +#line 4440 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("DoubleShotgun - Auto weapon change not working."); +#line 4441 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = m_bHasAmmo = FALSE ; +#line 4442 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x01920057, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x01920057_FireDoubleShotgun_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920057 + +#line 4443 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4443 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4447 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TommyGunStart(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_TommyGunStart + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::TommyGunStart expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4448 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iBulletsOnFireStart = m_iBullets ; +#line 4449 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4450 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_SILENCE , SOF_3D | SOF_VOLUMETRIC ); +#line 4451 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (50.0f , 5.0f , 1.5f , 1.0f); +#line 4452 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_TOMMYGUN_FIRE , SOF_LOOP | SOF_3D | SOF_VOLUMETRIC ); +#line 4453 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_TOMMYGUN , AOF_LOOPING ); +#line 4454 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_SHOTGUN_FIRESHORT , AOF_LOOPING ); +#line 4455 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4455 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4458 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TommyGunStop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_TommyGunStop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::TommyGunStop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4460 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4461 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pl . m_pstState != PST_DIVE && hud_bShowWeapon ) +#line 4462 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4463 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX ctBulletsFired = ClampUp (m_iBulletsOnFireStart - m_iBullets , INDEX (100)); +#line 4464 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +for(INDEX iSmoke = 0;iSmoke < ctBulletsFired / 6.0;iSmoke ++) +#line 4465 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4466 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData * psldSmoke = & pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 4467 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plPipe ; +#line 4468 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afTommygunPipe [ 0 ] , afTommygunPipe [ 1 ] , afTommygunPipe [ 2 ]) , plPipe , FALSE ); +#line 4469 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D m ; +#line 4470 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (m , plPipe . pl_OrientationAngle ); +#line 4471 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_vPos = plPipe . pl_PositionVector + pl . en_vCurrentTranslationAbsolute * iSmoke * _pTimer -> TickQuantum ; +#line 4472 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp (m (1 , 2) , m (2 , 2) , m (3 , 2)); +#line 4473 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_vUp = vUp ; +#line 4474 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_tmLaunch = _pTimer -> CurrentTick () + iSmoke * _pTimer -> TickQuantum ; +#line 4475 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_estType = ESL_BULLET_SMOKE ; +#line 4476 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_fSize = 0.5f + ctBulletsFired / 75.0f; +#line 4477 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpeedRelative = FLOAT3D (- 0.06f , 0.0f , - 0.06f); +#line 4478 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +psldSmoke -> sld_vSpeed = vSpeedRelative * m + pl . en_vCurrentTranslationAbsolute ; +#line 4479 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4480 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4481 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4483 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (50.0f , 5.0f , 0.0f , 1.0f); +#line 4484 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_NONE , 0); +#line 4485 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimationOff (); +#line 4486 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4489 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireTommyGun(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FireTommyGun + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FireTommyGun expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4491 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iBullets > 0)){ Jump(STATE_CURRENT,0x0192005f, FALSE, EInternal());return TRUE;} +#line 4492 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireMachineBullet (wpn_fFX [ WEAPON_TOMMYGUN ] , wpn_fFY [ WEAPON_TOMMYGUN ] , +#line 4493 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +500.0f , 10.0f , ((GetSP () -> sp_bCooperative ) ? 0.01f : 0.03f) , +#line 4494 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((GetSP () -> sp_bCooperative ) ? 0.5f : 0.0f)); +#line 4495 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (50.0f); +#line 4496 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Tommygun_fire");} +#line 4497 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DecAmmo (m_iBullets , 1); +#line 4498 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_ADD ); +#line 4499 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (TOMMYGUN_ANIM_FIRE , AOF_LOOPING | AOF_NORESTART ); +#line 4502 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plShell ; +#line 4503 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afTommygunShellPos [ 0 ] , afTommygunShellPos [ 1 ] , afTommygunShellPos [ 2 ]) , plShell , FALSE ); +#line 4504 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D mRot ; +#line 4505 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (mRot , plShell . pl_OrientationAngle ); +#line 4507 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(hud_bShowWeapon ) +#line 4508 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4510 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = * GetPlayer (); +#line 4511 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sld = pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 4512 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vPos = plShell . pl_PositionVector ; +#line 4513 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpeedRelative = FLOAT3D (FRnd () + 2.0f , FRnd () + 5.0f , - FRnd () - 2.0f); +#line 4514 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOATmatrix3D & m = pl . GetRotationMatrix (); +#line 4515 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp (m (1 , 2) , m (2 , 2) , m (3 , 2)); +#line 4516 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vUp = vUp ; +#line 4517 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vSpeed = vSpeedRelative * mRot ; +#line 4518 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 4519 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_estType = ESL_BULLET ; +#line 4520 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4523 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pl . m_pstState == PST_DIVE ) +#line 4524 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4525 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sldBubble = pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 4526 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afTommygunShellPos [ 0 ] , afTommygunShellPos [ 1 ] , afTommygunShellPos [ 2 ]) , plShell , FALSE ); +#line 4527 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (mRot , plShell . pl_OrientationAngle ); +#line 4528 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vPos = plShell . pl_PositionVector ; +#line 4529 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vUp = vUp ; +#line 4530 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 4531 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_estType = ESL_BUBBLE ; +#line 4532 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vSpeedRelative = FLOAT3D (0.3f , 0.0f , 0.0f); +#line 4533 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vSpeed = vSpeedRelative * mRot ; +#line 4534 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4535 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4536 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4538 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x0192005c, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192005c_FireTommyGun_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192005c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0192005d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192005d_FireTommyGun_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192005d +; +#line 4540 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iBullets <= 0){SelectNewWeapon ();}Jump(STATE_CURRENT,0x0192005e, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x0192005f_FireTommyGun_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192005f +{ +#line 4542 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("TommyGun - Auto weapon change not working."); +#line 4543 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = m_bHasAmmo = FALSE ; +#line 4544 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x0192005e, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x0192005e_FireTommyGun_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192005e + +#line 4545 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4545 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4549 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireSniper(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FireSniper + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FireSniper expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4550 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iSniperBullets > 0)){ Jump(STATE_CURRENT,0x01920066, FALSE, EInternal());return TRUE;} +#line 4552 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bSniping ){ +#line 4553 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireSniperBullet (0.0f , 0.0f , 1500.0f , +#line 4554 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(GetSP () -> sp_bCooperative ) ? 300.0f : 90.0f , 0.0f); +#line 4555 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4556 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else { +#line 4557 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireSniperBullet (wpn_fFX [ WEAPON_SNIPER ] , wpn_fFY [ WEAPON_SNIPER ] , 1000.0f , +#line 4558 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +(GetSP () -> sp_bCooperative ) ? 75.0f : 30.0f , 5.0f); +#line 4559 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4560 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmLastSniperFire = _pTimer -> CurrentTick (); +#line 4562 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (50.0f); +#line 4563 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DecAmmo (m_iSniperBullets , 1); +#line 4564 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! m_bSniping ){ +#line 4565 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_ADD ); +#line 4566 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4567 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_COLT_SHOTGUN , 0); +#line 4570 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4571 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(GetSP () -> sp_bCooperative ){ +#line 4572 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (50.0f , 5.0f , 1.5f , 1.0f); +#line 4573 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(TRUE ){ +#line 4574 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (250.0f , 75.0f , 1.5f , 1.0f); +#line 4575 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4576 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_SNIPER_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 4577 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("SniperFire");} +#line 4580 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (SNIPER_ANIM_FIRE , 0); +#line 4582 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(1.0f); +Jump(STATE_CURRENT, 0x01920061, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920061_FireSniper_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920061 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920062, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920062_FireSniper_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920062 +; +#line 4585 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plShell ; +#line 4586 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afSniperShellPos [ 0 ] , afSniperShellPos [ 1 ] , afSniperShellPos [ 2 ]) , plShell , FALSE ); +#line 4587 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D mRot ; +#line 4588 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (mRot , plShell . pl_OrientationAngle ); +#line 4590 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(hud_bShowWeapon ) +#line 4591 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4592 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer * penPlayer = GetPlayer (); +#line 4593 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sld = penPlayer -> m_asldData [ penPlayer -> m_iFirstEmptySLD ]; +#line 4594 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vPos = plShell . pl_PositionVector ; +#line 4595 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpeedRelative = FLOAT3D (FRnd () + 2.0f , FRnd () + 5.0f , - FRnd () - 2.0f); +#line 4596 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vSpeed = vSpeedRelative * mRot ; +#line 4598 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOATmatrix3D & m = penPlayer -> GetRotationMatrix (); +#line 4599 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp (m (1 , 2) , m (2 , 2) , m (3 , 2)); +#line 4600 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vUp = vUp ; +#line 4601 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 4602 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_estType = ESL_BULLET ; +#line 4604 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penPlayer -> m_iFirstEmptySLD = (penPlayer -> m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4607 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(penPlayer -> m_pstState == PST_DIVE ) +#line 4608 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4609 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sldBubble = penPlayer -> m_asldData [ penPlayer -> m_iFirstEmptySLD ]; +#line 4610 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afTommygunShellPos [ 0 ] , afTommygunShellPos [ 1 ] , afTommygunShellPos [ 2 ]) , plShell , FALSE ); +#line 4611 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (mRot , plShell . pl_OrientationAngle ); +#line 4612 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vPos = plShell . pl_PositionVector ; +#line 4613 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vUp = vUp ; +#line 4614 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 4615 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_estType = ESL_BUBBLE ; +#line 4616 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vSpeedRelative = FLOAT3D (0.3f , 0.0f , 0.0f); +#line 4617 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vSpeed = vSpeedRelative * mRot ; +#line 4618 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +penPlayer -> m_iFirstEmptySLD = (penPlayer -> m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4619 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4620 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4622 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(1.35f - 1.0f); +Jump(STATE_CURRENT, 0x01920063, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920063_FireSniper_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920063 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920064, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920064_FireSniper_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920064 +; +#line 4625 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iSniperBullets <= 0){SelectNewWeapon ();}Jump(STATE_CURRENT,0x01920065, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920066_FireSniper_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920066 +{ +#line 4628 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("Sniper - Auto weapon change not working."); +#line 4629 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = m_bHasAmmo = FALSE ; +#line 4630 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x01920065, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x01920065_FireSniper_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920065 + +#line 4631 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4631 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4636 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MiniGunSpinUp(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_MiniGunSpinUp + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::MiniGunSpinUp expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4638 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (MINIGUN_ANIM_WAIT1 , AOF_LOOPING | AOF_NORESTART ); +#line 4640 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayerAnimator &) * ((CPlayer &) * m_penPlayer ) . m_penAnimator ) . m_fLastActionTime = _pTimer -> CurrentTick (); +#line 4642 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iLastBulletPosition = FLOAT3D (32000.0f , 32000.0f , 32000.0f); +#line 4643 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4645 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_SILENCE , SOF_3D | SOF_VOLUMETRIC ); +#line 4647 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (50.0f , 5.0f , 2.0f , 1.0f); +#line 4648 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon1 . Set3DParameters (50.0f , 5.0f , 1.0f , 1.0f); +#line 4649 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon2 . Set3DParameters (50.0f , 5.0f , 1.0f , 1.0f); +#line 4652 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon2 , SOUND_MINIGUN_CLICK , SOF_3D | SOF_VOLUMETRIC ); +#line 4653 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon1 , SOUND_MINIGUN_SPINUP , SOF_3D | SOF_VOLUMETRIC ); +#line 4655 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Minigun_rotateup");} +#line 4657 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT,0x0192006a, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x0192006a_MiniGunSpinUp_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192006a +if(!(m_aMiniGunSpeed < MINIGUN_FULLSPEED && HoldingFire ())){ Jump(STATE_CURRENT,0x0192006b, FALSE, EInternal());return TRUE;} +#line 4659 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(MINIGUN_TICKTIME ); +Jump(STATE_CURRENT, 0x01920068, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920068_MiniGunSpinUp_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920068 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920069, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920069_MiniGunSpinUp_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920069 +; +#line 4661 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunLast = m_aMiniGun ; +#line 4662 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGun += m_aMiniGunSpeed * MINIGUN_TICKTIME ; +#line 4663 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunSpeed += MINIGUN_SPINUPACC * MINIGUN_TICKTIME ;Jump(STATE_CURRENT,0x0192006a, FALSE, EInternal());return TRUE; +#line 4664 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}BOOL CPlayerWeapons::H0x0192006b_MiniGunSpinUp_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192006b + +#line 4666 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunSpeed = ClampUp (m_aMiniGunSpeed , MINIGUN_FULLSPEED ); +#line 4669 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! HoldingFire ()){ +#line 4671 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_MiniGunSpinDown, TRUE, EVoid());return TRUE; +#line 4672 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4674 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_MiniGunFire, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4677 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MiniGunFire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_MiniGunFire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::MiniGunFire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4679 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4680 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon1 , SOUND_MINIGUN_ROTATE , SOF_3D | SOF_LOOP | SOF_VOLUMETRIC | SOF_SMOOTHCHANGE ); +#line 4681 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Minigun_rotate");} +#line 4683 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(HoldingFire () && m_iBullets > 0){ +#line 4685 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_MINIGUN_FIRE , SOF_3D | SOF_LOOP | SOF_VOLUMETRIC ); +#line 4686 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_TOMMYGUN , AOF_LOOPING ); +#line 4687 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_MINIGUN_FIRESHORT , AOF_LOOPING ); +#line 4688 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4690 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iBulletsOnFireStart = m_iBullets ; +#line 4692 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT,0x0192006f, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x0192006f_MiniGunFire_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192006f +if(!(HoldingFire ())){ Jump(STATE_CURRENT,0x01920070, FALSE, EInternal());return TRUE;} +#line 4694 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(! m_bHasAmmo && m_iBullets > 0){ +#line 4695 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4696 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_MINIGUN_FIRE , SOF_3D | SOF_LOOP | SOF_VOLUMETRIC ); +#line 4697 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Minigun_fire");} +#line 4698 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_TOMMYGUN , AOF_LOOPING ); +#line 4699 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_MINIGUN_FIRESHORT , AOF_LOOPING ); +#line 4700 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bHasAmmo = TRUE ; +#line 4701 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4704 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iBullets > 0){ +#line 4706 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireMachineBullet (wpn_fFX [ WEAPON_MINIGUN ] , wpn_fFY [ WEAPON_MINIGUN ] , +#line 4707 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +750.0f , 10.0f , (GetSP () -> sp_bCooperative ) ? 0.01f : 0.03f , +#line 4708 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((GetSP () -> sp_bCooperative ) ? 0.5f : 0.0f)); +#line 4709 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DoRecoil (); +#line 4710 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (60.0f); +#line 4711 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DecAmmo (m_iBullets , 1); +#line 4712 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlare (0 , FLARE_ADD ); +#line 4715 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlacement3D plShell ; +#line 4718 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4719 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pl . m_penCamera == NULL && pl . m_pen3rdPersonView == NULL ) +#line 4720 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4721 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afMinigunShellPos [ 0 ] , afMinigunShellPos [ 1 ] , afMinigunShellPos [ 2 ]) , plShell , FALSE ); +#line 4722 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4724 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else +#line 4725 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4727 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition3rdPersonView (FLOAT3D (afMinigunShellPos3rdView [ 0 ] , +#line 4728 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +afMinigunShellPos3rdView [ 1 ] , afMinigunShellPos3rdView [ 2 ]) , plShell , FALSE ); +#line 4729 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4731 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOATmatrix3D mRot ; +#line 4732 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (mRot , plShell . pl_OrientationAngle ); +#line 4734 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(hud_bShowWeapon ) +#line 4735 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4736 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = * GetPlayer (); +#line 4737 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sld = pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 4738 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vPos = plShell . pl_PositionVector ; +#line 4739 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vSpeedRelative = FLOAT3D (FRnd () + 2.0f , FRnd () + 5.0f , - FRnd () - 2.0f); +#line 4740 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +const FLOATmatrix3D & m = pl . GetRotationMatrix (); +#line 4741 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vUp (m (1 , 2) , m (2 , 2) , m (3 , 2)); +#line 4742 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vUp = vUp ; +#line 4743 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_vSpeed = vSpeedRelative * mRot ; +#line 4744 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 4745 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sld . sld_estType = ESL_BULLET ; +#line 4747 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4750 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pl . m_pstState == PST_DIVE ) +#line 4751 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4752 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ShellLaunchData & sldBubble = pl . m_asldData [ pl . m_iFirstEmptySLD ]; +#line 4753 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CalcWeaponPosition (FLOAT3D (afMinigunShellPos [ 0 ] , afMinigunShellPos [ 1 ] , afMinigunShellPos [ 2 ]) , plShell , FALSE ); +#line 4754 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MakeRotationMatrixFast (mRot , plShell . pl_OrientationAngle ); +#line 4755 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vPos = plShell . pl_PositionVector ; +#line 4756 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vUp = vUp ; +#line 4757 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_tmLaunch = _pTimer -> CurrentTick (); +#line 4758 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_estType = ESL_BUBBLE ; +#line 4759 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +vSpeedRelative = FLOAT3D (0.3f , 0.0f , 0.0f); +#line 4760 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +sldBubble . sld_vSpeed = vSpeedRelative * mRot ; +#line 4761 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_iFirstEmptySLD = (pl . m_iFirstEmptySLD + 1) % MAX_FLYING_SHELLS ; +#line 4762 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4763 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4765 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else { +#line 4766 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bHasAmmo ) +#line 4767 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4768 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MinigunSmoke (); +#line 4769 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4771 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bHasAmmo = FALSE ; +#line 4772 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4773 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_SILENCE , SOF_3D | SOF_VOLUMETRIC ); +#line 4774 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_NONE , AOF_LOOPING ); +#line 4775 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimationOff (); +#line 4776 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4777 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(MINIGUN_TICKTIME ); +Jump(STATE_CURRENT, 0x0192006d, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192006d_MiniGunFire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192006d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0192006e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192006e_MiniGunFire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192006e +; +#line 4779 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunLast = m_aMiniGun ; +#line 4780 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGun += m_aMiniGunSpeed * MINIGUN_TICKTIME ;Jump(STATE_CURRENT,0x0192006f, FALSE, EInternal());return TRUE; +#line 4781 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}BOOL CPlayerWeapons::H0x01920070_MiniGunFire_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920070 + +#line 4783 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bHasAmmo ) +#line 4784 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4785 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MinigunSmoke (); +#line 4786 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4788 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimationOff (); +#line 4790 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4791 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (50.0f , 5.0f , 0.0f , 1.0f); +#line 4792 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_NONE , AOF_LOOPING ); +#line 4794 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_MiniGunSpinDown, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4797 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MiniGunSpinDown(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_MiniGunSpinDown + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::MiniGunSpinDown expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4798 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4800 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon3 , SOUND_MINIGUN_CLICK , SOF_3D | SOF_VOLUMETRIC ); +#line 4801 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon1 , SOUND_MINIGUN_SPINDOWN , SOF_3D | SOF_VOLUMETRIC | SOF_SMOOTHCHANGE ); +#line 4802 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_StopEffect ("Minigun_rotate");} +#line 4803 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Minigun_rotatedown");} +#line 4807 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT,0x01920074, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920074_MiniGunSpinDown_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920074 +if(!(m_aMiniGunSpeed > 0 && (! HoldingFire () || m_iBullets <= 0))){ Jump(STATE_CURRENT,0x01920075, FALSE, EInternal());return TRUE;} +#line 4808 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(MINIGUN_TICKTIME ); +Jump(STATE_CURRENT, 0x01920072, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920072_MiniGunSpinDown_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920072 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920073, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920073_MiniGunSpinDown_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920073 +; +#line 4810 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunLast = m_aMiniGun ; +#line 4811 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGun += m_aMiniGunSpeed * MINIGUN_TICKTIME ; +#line 4812 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunSpeed -= MINIGUN_SPINDNACC * MINIGUN_TICKTIME ; +#line 4814 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iBullets <= 0){ +#line 4815 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SelectNewWeapon (); +#line 4816 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4819 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bChangeWeapon ){ +#line 4821 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunSpeed = 0.0f; +#line 4822 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunLast = m_aMiniGun ; +#line 4823 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimationOff (); +#line 4824 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE; +#line 4825 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x01920074, FALSE, EInternal());return TRUE; +#line 4826 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}BOOL CPlayerWeapons::H0x01920075_MiniGunSpinDown_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920075 + +#line 4828 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunSpeed = ClampDn (m_aMiniGunSpeed , 0.0f); +#line 4829 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_aMiniGunLast = m_aMiniGun ; +#line 4832 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(HoldingFire () && m_iBullets > 0){ +#line 4834 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_MiniGunSpinUp, TRUE, EVoid());return TRUE; +#line 4835 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4838 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CPlayerAnimator &) * ((CPlayer &) * m_penPlayer ) . m_penAnimator ) . m_fLastActionTime = _pTimer -> CurrentTick (); +#line 4841 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iBullets <= 0)){ Jump(STATE_CURRENT,0x0192007a, FALSE, EInternal());return TRUE;} +#line 4843 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT,0x01920078, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920078_MiniGunSpinDown_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920078 +if(!(HoldingFire () && m_iBullets <= 0)){ Jump(STATE_CURRENT,0x01920079, FALSE, EInternal());return TRUE;} +#line 4844 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x01920076, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920076_MiniGunSpinDown_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920076 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920077, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920077_MiniGunSpinDown_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920077 +;Jump(STATE_CURRENT,0x01920078, FALSE, EInternal());return TRUE; +#line 4845 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}BOOL CPlayerWeapons::H0x01920079_MiniGunSpinDown_08(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920079 + +#line 4846 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iBullets <= 0){ +#line 4848 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SelectNewWeapon (); +#line 4849 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x0192007a, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x0192007a_MiniGunSpinDown_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192007a + +#line 4851 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4855 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireRocketLauncher(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FireRocketLauncher + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FireRocketLauncher expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4857 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iRockets > 0)){ Jump(STATE_CURRENT,0x01920081, FALSE, EInternal());return TRUE;} +#line 4858 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_MINIGUN_FIRELONG , 0); +#line 4859 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (ROCKETLAUNCHER_ANIM_FIRE , 0); +#line 4860 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireRocket (); +#line 4862 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DoRecoil (); +#line 4863 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (20.0f); +#line 4864 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Rocketlauncher_fire");} +#line 4865 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DecAmmo (m_iRockets , 1); +#line 4867 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4868 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pl . m_soWeapon0 . IsPlaying ()) +#line 4869 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4870 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon1 , SOUND_ROCKETLAUNCHER_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 4871 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4872 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else +#line 4873 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 4874 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_ROCKETLAUNCHER_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 4875 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 4877 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x0192007c, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192007c_FireRocketLauncher_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192007c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0192007d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192007d_FireRocketLauncher_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192007d +; +#line 4879 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo = & (m_moWeapon . GetAttachmentModel (ROCKETLAUNCHER_ATTACHMENT_ROCKET1 ) -> amo_moModelObject ); +#line 4880 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo -> StretchModel (FLOAT3D (0 , 0 , 0)); +#line 4882 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (ROCKETLAUNCHER_ANIM_FIRE ) - 0.05f); +Jump(STATE_CURRENT, 0x0192007e, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192007e_FireRocketLauncher_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192007e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0192007f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192007f_FireRocketLauncher_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192007f +; +#line 4884 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo = & (m_moWeapon . GetAttachmentModel (ROCKETLAUNCHER_ATTACHMENT_ROCKET1 ) -> amo_moModelObject ); +#line 4885 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo -> StretchModel (FLOAT3D (1 , 1 , 1)); +#line 4888 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iRockets <= 0){SelectNewWeapon ();}Jump(STATE_CURRENT,0x01920080, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920081_FireRocketLauncher_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920081 +{ +#line 4890 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("RocketLauncher - Auto weapon change not working."); +#line 4891 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = m_bHasAmmo = FALSE ; +#line 4892 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x01920080, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x01920080_FireRocketLauncher_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920080 + +#line 4893 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4893 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 4897 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireGrenadeLauncher(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FireGrenadeLauncher + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FireGrenadeLauncher expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 4899 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TM_START = _pTimer -> CurrentTick (); +#line 4901 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +F_TEMP = _pTimer -> CurrentTick (); +#line 4903 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +F_OFFSET_CHG = 0.0f; +#line 4904 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPower = 0.0f; +#line 4905 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmDrawStartTime = _pTimer -> CurrentTick (); +#line 4906 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT,0x01920085, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920085_FireGrenadeLauncher_03(const CEntityEvent &__eeInput) +#line 4907 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920085 +if(!(HoldingFire () && ((_pTimer -> CurrentTick () - TM_START ) < 0.75f))){ Jump(STATE_CURRENT,0x01920086, FALSE, EInternal());return TRUE;} +#line 4908 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01920083, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920083_FireGrenadeLauncher_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920083 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920084, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920084_FireGrenadeLauncher_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920084 +; +#line 4909 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iPower = INDEX ((_pTimer -> CurrentTick () - TM_START ) / _pTimer -> TickQuantum ); +#line 4910 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +F_OFFSET_CHG = 0.125f / (iPower + 2); +#line 4911 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPowerOld = m_fWeaponDrawPower ; +#line 4912 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPower += F_OFFSET_CHG ;Jump(STATE_CURRENT,0x01920085, FALSE, EInternal());return TRUE; +#line 4913 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}BOOL CPlayerWeapons::H0x01920086_FireGrenadeLauncher_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920086 + +#line 4914 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmDrawStartTime = 0.0f; +#line 4918 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iGrenades > 0)){ Jump(STATE_CURRENT,0x01920091, FALSE, EInternal());return TRUE;} +#line 4921 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iPower = INDEX ((_pTimer -> CurrentTick () - F_TEMP ) / _pTimer -> TickQuantum ); +#line 4922 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireGrenade (iPower ); +#line 4923 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (10.0f); +#line 4924 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Gnadelauncher");} +#line 4925 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DecAmmo (m_iGrenades , 1); +#line 4927 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 4928 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_GRENADELAUNCHER_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 4929 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_MINIGUN_FIRELONG , 0); +#line 4932 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TM_START = _pTimer -> CurrentTick (); +#line 4933 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPowerOld = m_fWeaponDrawPower ; +#line 4934 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT,0x01920089, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920089_FireGrenadeLauncher_07(const CEntityEvent &__eeInput) +#line 4935 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920089 +if(!(m_fWeaponDrawPower > 0.0f)){ Jump(STATE_CURRENT,0x0192008a, FALSE, EInternal());return TRUE;} +#line 4936 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01920087, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920087_FireGrenadeLauncher_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920087 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920088, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920088_FireGrenadeLauncher_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920088 +; +#line 4937 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPowerOld = m_fWeaponDrawPower ; +#line 4938 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPower -= F_OFFSET_CHG ; +#line 4939 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPower = ClampDn (m_fWeaponDrawPower , 0.0f); +#line 4940 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +F_OFFSET_CHG = F_OFFSET_CHG * 10;Jump(STATE_CURRENT,0x01920089, FALSE, EInternal());return TRUE; +#line 4941 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}BOOL CPlayerWeapons::H0x0192008a_FireGrenadeLauncher_08(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192008a + +#line 4944 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ResetWeaponMovingOffset (); +#line 4947 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iGrenades <= 0)){ Jump(STATE_CURRENT,0x0192008f, FALSE, EInternal());return TRUE;} +#line 4949 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SelectNewWeapon ();Jump(STATE_CURRENT,0x0192008e, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x0192008f_FireGrenadeLauncher_13(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192008f +if(!(TRUE )){ Jump(STATE_CURRENT,0x0192008d, FALSE, EInternal());return TRUE;} +#line 4953 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x0192008b, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192008b_FireGrenadeLauncher_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192008b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0192008c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192008c_FireGrenadeLauncher_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192008c +;Jump(STATE_CURRENT,0x0192008d, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x0192008d_FireGrenadeLauncher_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192008d +Jump(STATE_CURRENT,0x0192008e, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x0192008e_FireGrenadeLauncher_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192008e +Jump(STATE_CURRENT,0x01920090, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x01920091_FireGrenadeLauncher_15(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920091 +{ +#line 4956 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("GrenadeLauncher - Auto weapon change not working."); +#line 4957 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = m_bHasAmmo = FALSE ; +#line 4958 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x01920090, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x01920090_FireGrenadeLauncher_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920090 + +#line 4960 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 4960 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5042 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FlamerStart(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FlamerStart + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FlamerStart expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5043 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmFlamerStart = _pTimer -> CurrentTick (); +#line 5044 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmFlamerStop = 1e9; +#line 5046 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (FLAMER_ANIM_FIRESTART , 0); +#line 5047 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (FLAMER_ANIM_FIRESTART )); +Jump(STATE_CURRENT, 0x01920093, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920093_FlamerStart_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920093 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920094, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920094_FlamerStart_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920094 +; +#line 5049 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 5050 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (50.0f , 5.0f , 2.0f , 0.31f); +#line 5051 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon2 . Set3DParameters (50.0f , 5.0f , 2.0f , 0.3f); +#line 5052 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_FL_FIRE , SOF_3D | SOF_LOOP | SOF_VOLUMETRIC ); +#line 5053 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("FlamethrowerFire");} +#line 5054 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon2 , SOUND_FL_START , SOF_3D | SOF_VOLUMETRIC ); +#line 5055 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("FlamethrowerStart");} +#line 5056 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireFlame (); +#line 5057 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DecAmmo (m_iNapalm , 1); +#line 5058 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x01920095, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920095_FlamerStart_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920095 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920096, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920096_FlamerStart_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920096 +; +#line 5059 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_FlamerFire, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5062 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FlamerFire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FlamerFire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FlamerFire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5064 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT,0x0192009a, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x0192009a_FlamerFire_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192009a +if(!(HoldingFire () && m_iNapalm > 0)){ Jump(STATE_CURRENT,0x0192009b, FALSE, EInternal());return TRUE;} +#line 5066 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireFlame (); +#line 5067 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DecAmmo (m_iNapalm , 1); +#line 5068 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (30.0f); +#line 5069 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x01920098, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x01920098_FlamerFire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920098 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01920099, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x01920099_FlamerFire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01920099 +;Jump(STATE_CURRENT,0x0192009a, FALSE, EInternal());return TRUE; +#line 5070 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}BOOL CPlayerWeapons::H0x0192009b_FlamerFire_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192009b + +#line 5072 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iNapalm <= 0){ +#line 5073 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bHasAmmo = FALSE ; +#line 5074 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5076 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_FlamerStop, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5079 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FlamerStop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FlamerStop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FlamerStop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5080 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmFlamerStop = _pTimer -> CurrentTick (); +#line 5081 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 5082 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_FL_STOP , SOF_3D | SOF_VOLUMETRIC | SOF_SMOOTHCHANGE ); +#line 5083 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_StopEffect ("FlamethrowerFire");} +#line 5084 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("FlamethrowerStop");} +#line 5086 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireFlame (); +#line 5088 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_penFlame != NULL && ! (m_penFlame -> GetFlags () & ENF_DELETED )){ +#line 5089 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((CProjectile &) * m_penFlame ) . m_penParticles = NULL ; +#line 5090 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_penFlame = NULL ; +#line 5091 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5093 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (FLAMER_ANIM_FIREEND , 0); +#line 5094 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (FLAMER_ANIM_FIREEND )); +Jump(STATE_CURRENT, 0x0192009d, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x0192009d_FlamerStop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192009d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0192009e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x0192009e_FlamerStop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0192009e +; +#line 5096 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iNapalm <= 0){ +#line 5098 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SelectNewWeapon (); +#line 5099 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5100 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5104 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChainsawFire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_ChainsawFire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::ChainsawFire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5106 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 5109 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (50.0f , 5.0f , 1.5f , 1.0f); +#line 5110 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_CS_BEGINFIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 5111 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("ChainsawBeginFire");} +#line 5115 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (CHAINSAW_ANIM_WAIT2FIRE , 0); +#line 5116 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (CHAINSAW_ANIM_WAIT2FIRE ) - 0.05f); +Jump(STATE_CURRENT, 0x019200a0, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200a0_ChainsawFire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200a0 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x019200a1, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x019200a1_ChainsawFire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200a1 +; +#line 5118 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayerAnimator & pa = * GetAnimator (); +#line 5119 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pa . FireAnimation (BODY_ANIM_MINIGUN_FIRELONG , 0); +#line 5121 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmoTeeth = GetChainSawTeeth (); +#line 5122 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pmoTeeth != NULL ) +#line 5123 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 5124 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmoTeeth -> PlayAnim (TEETH_ANIM_ROTATE , AOF_LOOPING | AOF_NORESTART ); +#line 5125 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5128 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 5130 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeaponAmbient . Set3DParameters (30.0f , 3.0f , 0.5f , 1.0f); +#line 5132 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_CS_FIRE , SOF_3D | SOF_LOOP | SOF_VOLUMETRIC | SOF_SMOOTHCHANGE ); +#line 5133 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_StopEffect ("ChainsawIdle");} +#line 5134 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("ChainsawFire");} +#line 5136 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (CHAINSAW_ANIM_FIRE , AOF_LOOPING | AOF_NORESTART ); +#line 5139 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo1 = & (m_moWeapon . GetAttachmentModel (CHAINSAW_ATTACHMENT_BLADE ) -> amo_moModelObject ); +#line 5140 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo2 = & (pmo1 -> GetAttachmentModel (BLADE_ATTACHMENT_TEETH ) -> amo_moModelObject ); +#line 5141 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo2 -> PlayAnim (TEETH_ANIM_ROTATE , AOF_LOOPING ); +#line 5143 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT,0x019200a4, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x019200a4_ChainsawFire_05(const CEntityEvent &__eeInput) +#line 5144 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200a4 +if(!(HoldingFire ())){ Jump(STATE_CURRENT,0x019200a5, FALSE, EInternal());return TRUE;} +#line 5145 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(CHAINSAW_UPDATETIME ); +Jump(STATE_CURRENT, 0x019200a2, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200a2_ChainsawFire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200a2 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x019200a3, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x019200a3_ChainsawFire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200a3 +; +#line 5147 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CutWithChainsaw (0 , 0 , 3.0f , 2.0f , 1.0f , +#line 5148 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((GetSP () -> sp_bCooperative ) ? 200.0f : 250.0f) * CHAINSAW_UPDATETIME );Jump(STATE_CURRENT,0x019200a4, FALSE, EInternal());return TRUE; +#line 5150 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}BOOL CPlayerWeapons::H0x019200a5_ChainsawFire_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200a5 + +#line 5154 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 5155 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_CS_ENDFIRE , SOF_3D | SOF_VOLUMETRIC | SOF_SMOOTHCHANGE ); +#line 5156 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_StopEffect ("ChainsawFire");} +#line 5157 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("ChainsawEnd");} +#line 5158 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("ChainsawIdle");} +#line 5161 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeaponAmbient . Set3DParameters (30.0f , 3.0f , 1.0f , 1.0f); +#line 5163 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (CHAINSAW_ANIM_FIRE2WAIT , 0); +#line 5164 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (CHAINSAW_ANIM_FIRE2WAIT )); +Jump(STATE_CURRENT, 0x019200a6, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200a6_ChainsawFire_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200a6 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x019200a7, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x019200a7_ChainsawFire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200a7 +; +#line 5167 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo1 = & (m_moWeapon . GetAttachmentModel (CHAINSAW_ATTACHMENT_BLADE ) -> amo_moModelObject ); +#line 5168 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo2 = & (pmo1 -> GetAttachmentModel (BLADE_ATTACHMENT_TEETH ) -> amo_moModelObject ); +#line 5169 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo2 -> PlayAnim (TEETH_ANIM_DEFAULT , 0); +#line 5171 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmoTeeth = GetChainSawTeeth (); +#line 5172 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pmoTeeth != NULL ) +#line 5173 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 5174 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmoTeeth -> PlayAnim (TEETH_ANIM_DEFAULT , 0); +#line 5175 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5177 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5180 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChainsawBringUp(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_ChainsawBringUp + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::ChainsawBringUp expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5183 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (CHAINSAW_ANIM_FIRE2WAIT , 0); +#line 5184 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(m_moWeapon . GetAnimLength (CHAINSAW_ANIM_FIRE2WAIT )); +Jump(STATE_CURRENT, 0x019200a9, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200a9_ChainsawBringUp_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200a9 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x019200aa, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x019200aa_ChainsawBringUp_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200aa +; +#line 5185 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5189 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireLaser(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_FireLaser + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::FireLaser expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5191 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iElectricity > 0)){ Jump(STATE_CURRENT,0x019200af, FALSE, EInternal());return TRUE;} +#line 5192 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x019200ac, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200ac_FireLaser_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200ac +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x019200ad, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x019200ad_FireLaser_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200ad +; +#line 5193 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (LASER_ANIM_FIRE , AOF_LOOPING | AOF_NORESTART ); +#line 5194 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireLaserRay (); +#line 5195 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Laser_fire");} +#line 5196 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DecAmmo (m_iElectricity , 1); +#line 5198 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (20.0f); +#line 5199 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 5201 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iLaserBarrel ){ +#line 5202 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 0: { +#line 5203 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo = & (m_moWeapon . GetAttachmentModel (LASER_ATTACHMENT_LEFTUP ) -> amo_moModelObject ); +#line 5204 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo -> PlayAnim (BARREL_ANIM_FIRE , 0); +#line 5205 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_LASER_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 5206 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 5207 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 3: { +#line 5208 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo = & (m_moWeapon . GetAttachmentModel (LASER_ATTACHMENT_RIGHTDOWN ) -> amo_moModelObject ); +#line 5209 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo -> PlayAnim (BARREL_ANIM_FIRE , 0); +#line 5210 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon1 , SOUND_LASER_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 5211 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 5212 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 1: { +#line 5213 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo = & (m_moWeapon . GetAttachmentModel (LASER_ATTACHMENT_LEFTDOWN ) -> amo_moModelObject ); +#line 5214 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo -> PlayAnim (BARREL_ANIM_FIRE , 0); +#line 5215 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon2 , SOUND_LASER_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 5216 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 5217 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case 2: { +#line 5218 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo = & (m_moWeapon . GetAttachmentModel (LASER_ATTACHMENT_RIGHTUP ) -> amo_moModelObject ); +#line 5219 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pmo -> PlayAnim (BARREL_ANIM_FIRE , 0); +#line 5220 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon3 , SOUND_LASER_FIRE , SOF_3D | SOF_VOLUMETRIC ); +#line 5221 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +break ;} +#line 5222 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5224 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iLaserBarrel = (m_iLaserBarrel + 1) & 3; +#line 5226 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iElectricity <= 0){SelectNewWeapon ();}Jump(STATE_CURRENT,0x019200ae, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x019200af_FireLaser_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200af +{ +#line 5228 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("Laser - Auto weapon change not working."); +#line 5229 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = m_bHasAmmo = FALSE ; +#line 5230 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x019200ae, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x019200ae_FireLaser_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200ae + +#line 5231 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 5231 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5280 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CannonFireStart(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_CannonFireStart + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::CannonFireStart expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5282 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmDrawStartTime = _pTimer -> CurrentTick (); +#line 5283 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TM_START = _pTimer -> CurrentTick (); +#line 5284 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +F_OFFSET_CHG = 0.0f; +#line 5285 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPower = 0.0f; +#line 5286 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 5287 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iIronBalls & 1) +#line 5288 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 5289 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (50.0f , 5.0f , 3.0f , 1.0f); +#line 5290 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon0 , SOUND_CANNON_PREPARE , SOF_3D | SOF_VOLUMETRIC ); +#line 5291 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5292 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else +#line 5293 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 5294 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon1 . Set3DParameters (50.0f , 5.0f , 3.0f , 1.0f); +#line 5295 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon1 , SOUND_CANNON_PREPARE , SOF_3D | SOF_VOLUMETRIC ); +#line 5296 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5298 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Canon_prepare");} +#line 5299 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT,0x019200b3, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x019200b3_CannonFireStart_03(const CEntityEvent &__eeInput) +#line 5300 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200b3 +if(!(HoldingFire () && ((_pTimer -> CurrentTick () - TM_START ) < 1.0f))){ Jump(STATE_CURRENT,0x019200b4, FALSE, EInternal());return TRUE;} +#line 5301 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x019200b1, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200b1_CannonFireStart_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200b1 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x019200b2, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x019200b2_CannonFireStart_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200b2 +; +#line 5302 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iPower = INDEX ((_pTimer -> CurrentTick () - TM_START ) / _pTimer -> TickQuantum ); +#line 5303 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +F_OFFSET_CHG = 0.25f / (iPower + 2); +#line 5304 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPowerOld = m_fWeaponDrawPower ; +#line 5305 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPower += F_OFFSET_CHG ;Jump(STATE_CURRENT,0x019200b3, FALSE, EInternal());return TRUE; +#line 5306 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}BOOL CPlayerWeapons::H0x019200b4_CannonFireStart_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200b4 + +#line 5307 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_tmDrawStartTime = 0.0f; +#line 5308 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 5309 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iIronBalls & 1) +#line 5310 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 5312 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Set3DParameters (50.0f , 5.0f , 0.0f , 1.0f); +#line 5313 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5314 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else +#line 5315 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 5317 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon1 . Set3DParameters (50.0f , 5.0f , 0.0f , 1.0f); +#line 5318 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5321 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(((m_iIronBalls > 0) && (m_iCurrentWeapon == WEAPON_IRONCANNON )))){ Jump(STATE_CURRENT,0x019200ba, FALSE, EInternal());return TRUE;} +#line 5323 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX iPower = INDEX ((_pTimer -> CurrentTick () - TM_START ) / _pTimer -> TickQuantum ); +#line 5324 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +GetAnimator () -> FireAnimation (BODY_ANIM_MINIGUN_FIRELONG , 0); +#line 5326 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fRange , fFalloff ; +#line 5327 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(GetSP () -> sp_bCooperative ){ +#line 5328 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fRange = 100.0f; +#line 5329 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fFalloff = 25.0f; +#line 5330 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}else if(TRUE ){ +#line 5331 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fRange = 150.0f; +#line 5332 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +fFalloff = 30.0f; +#line 5333 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5336 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iIronBalls & 1) +#line 5337 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 5338 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon2 . Set3DParameters (fRange , fFalloff , 2.0f + iPower * 0.05f , 1.0f); +#line 5339 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon2 , SOUND_CANNON , SOF_3D | SOF_VOLUMETRIC ); +#line 5340 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5341 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +else +#line 5342 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 5343 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon3 . Set3DParameters (fRange , fFalloff , 2.0f + iPower * 0.05f , 1.0f); +#line 5344 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlaySound (pl . m_soWeapon3 , SOUND_CANNON , SOF_3D | SOF_VOLUMETRIC ); +#line 5345 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5347 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_moWeapon . PlayAnim (CANNON_ANIM_FIRE , 0); +#line 5348 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireCannonBall (iPower ); +#line 5350 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(_pNetwork -> IsPlayerLocal (m_penPlayer )){IFeel_PlayEffect ("Canon");} +#line 5351 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +DecAmmo (m_iIronBalls , 1); +#line 5353 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SpawnRangeSound (30.0f); +#line 5355 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TM_START = _pTimer -> CurrentTick (); +#line 5356 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPowerOld = m_fWeaponDrawPower ; +#line 5357 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT,0x019200b7, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x019200b7_CannonFireStart_07(const CEntityEvent &__eeInput) +#line 5359 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200b7 +if(!(m_fWeaponDrawPower > 0.0f || +#line 5358 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +((_pTimer -> CurrentTick () - TM_START ) < m_moWeapon . GetAnimLength (CANNON_ANIM_FIRE )))){ Jump(STATE_CURRENT,0x019200b8, FALSE, EInternal());return TRUE;} +#line 5360 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x019200b5, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200b5_CannonFireStart_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200b5 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x019200b6, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x019200b6_CannonFireStart_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200b6 +; +#line 5361 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPowerOld = m_fWeaponDrawPower ; +#line 5362 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPower -= F_OFFSET_CHG ; +#line 5363 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_fWeaponDrawPower = ClampDn (m_fWeaponDrawPower , 0.0f); +#line 5364 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +F_OFFSET_CHG = F_OFFSET_CHG * 2;Jump(STATE_CURRENT,0x019200b7, FALSE, EInternal());return TRUE; +#line 5365 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}BOOL CPlayerWeapons::H0x019200b8_CannonFireStart_08(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200b8 + +#line 5368 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ResetWeaponMovingOffset (); +#line 5371 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(((m_iIronBalls <= 0) && (m_iCurrentWeapon == WEAPON_IRONCANNON )) +#line 5372 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +) +#line 5373 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 5374 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SelectNewWeapon (); +#line 5375 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x019200b9, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x019200ba_CannonFireStart_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200ba + +#line 5378 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +{ +#line 5379 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERTALWAYS ("Cannon - Auto weapon change not working."); +#line 5380 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = m_bHasAmmo = FALSE ; +#line 5381 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}Jump(STATE_CURRENT,0x019200b9, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x019200b9_CannonFireStart_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200b9 + +#line 5382 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5389 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Reload(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_Reload + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::Reload expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5390 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bReloadWeapon = FALSE ; +#line 5393 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(m_iCurrentWeapon == WEAPON_COLT )){ Jump(STATE_CURRENT,0x019200c2, FALSE, EInternal());return TRUE;} +#line 5394 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +STATE_CPlayerWeapons_ReloadColt, TRUE; +Jump(STATE_CURRENT, 0x019200bc, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200bc_Reload_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200bc +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayerWeapons_ReloadColt, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x019200bd, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x019200bd_Reload_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200bd +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x019200c1, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x019200c2_Reload_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200c2 +if(!(m_iCurrentWeapon == WEAPON_DOUBLECOLT )){ Jump(STATE_CURRENT,0x019200c0, FALSE, EInternal());return TRUE;} +#line 5396 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +STATE_CPlayerWeapons_ReloadDoubleColt, TRUE; +Jump(STATE_CURRENT, 0x019200be, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200be_Reload_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200be +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayerWeapons_ReloadDoubleColt, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x019200bf, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x019200bf_Reload_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200bf +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x019200c0, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x019200c0_Reload_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200c0 +Jump(STATE_CURRENT,0x019200c1, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeapons::H0x019200c1_Reload_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200c1 + +#line 5401 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5408 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChangeKnifeStand(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_ChangeKnifeStand + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::ChangeKnifeStand expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5421 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 5421 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5424 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChangeToIronCannon(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_ChangeToIronCannon + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::ChangeToIronCannon expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5435 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iPreviousWeapon = m_iCurrentWeapon ; +#line 5436 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iCurrentWeapon = WEAPON_IRONCANNON ; +#line 5437 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_iWantedWeapon = m_iCurrentWeapon ; +#line 5439 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EEnd ()); +#line 5439 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5463 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BoringWeaponAnimation(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_BoringWeaponAnimation + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::BoringWeaponAnimation expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5465 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fWait = 0.0f; +#line 5466 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +switch(m_iCurrentWeapon ){ +#line 5467 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_KNIFE : fWait = KnifeBoring ();break ; +#line 5468 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_COLT : fWait = ColtBoring ();break ; +#line 5469 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLECOLT : fWait = DoubleColtBoring ();break ; +#line 5470 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SINGLESHOTGUN : fWait = SingleShotgunBoring ();break ; +#line 5471 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_DOUBLESHOTGUN : fWait = DoubleShotgunBoring ();break ; +#line 5472 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_TOMMYGUN : fWait = TommyGunBoring ();break ; +#line 5473 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_SNIPER : fWait = SniperBoring ();break ; +#line 5474 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_MINIGUN : fWait = MiniGunBoring ();break ; +#line 5475 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_ROCKETLAUNCHER : fWait = RocketLauncherBoring ();break ; +#line 5476 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_GRENADELAUNCHER : fWait = GrenadeLauncherBoring ();break ; +#line 5477 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_FLAMER : fWait = FlamerBoring ();break ; +#line 5478 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_CHAINSAW : fWait = ChainsawBoring ();break ; +#line 5479 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_LASER : fWait = LaserBoring ();break ; +#line 5480 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +case WEAPON_IRONCANNON : fWait = CannonBoring ();break ; +#line 5481 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +default : ASSERTALWAYS ("Unknown weapon."); +#line 5482 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5483 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(!(fWait > 0.0f)){ Jump(STATE_CURRENT,0x019200c8, FALSE, EInternal());return TRUE;}SetTimerAfter(fWait ); +Jump(STATE_CURRENT, 0x019200c6, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200c6_BoringWeaponAnimation_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200c6 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x019200c7, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeapons::H0x019200c7_BoringWeaponAnimation_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200c7 +;Jump(STATE_CURRENT,0x019200c8, FALSE, EInternal());return TRUE;}BOOL CPlayerWeapons::H0x019200c8_BoringWeaponAnimation_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200c8 + +#line 5485 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EBegin ()); +#line 5485 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5493 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Idle(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_Idle + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::Idle expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5495 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x019200ca, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200ca_Idle_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200ca +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 5498 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayDefaultAnim (); +#line 5501 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bChangeWeapon ){ +#line 5502 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_ChangeWeapon, TRUE, EVoid());return TRUE; +#line 5503 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5505 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bFireWeapon ){ +#line 5506 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Fire, TRUE, EVoid());return TRUE; +#line 5507 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5509 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bReloadWeapon ){ +#line 5510 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Reload, TRUE, EVoid());return TRUE; +#line 5511 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5512 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 5513 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;case(EVENTCODE_ESelectWeapon):{const ESelectWeapon&eSelect= (ESelectWeapon&)__eeInput; + +#line 5517 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SelectWeaponChange (eSelect . iWeapon ); +#line 5518 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_bChangeWeapon ){ +#line 5519 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_ChangeWeapon, TRUE, EVoid());return TRUE; +#line 5520 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5521 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 5522 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;case(EVENTCODE_EFireWeapon):{const EFireWeapon&e= (EFireWeapon&)__eeInput; + +#line 5525 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Fire, TRUE, EVoid());return TRUE; +#line 5526 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReloadWeapon):{const EReloadWeapon&e= (EReloadWeapon&)__eeInput; + +#line 5529 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Jump(STATE_CURRENT, STATE_CPlayerWeapons_Reload, TRUE, EVoid());return TRUE; +#line 5530 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;case(EVENTCODE_EBoringWeapon):{const EBoringWeapon&e= (EBoringWeapon&)__eeInput; + +#line 5533 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Call(STATE_CURRENT, STATE_CPlayerWeapons_BoringWeaponAnimation, TRUE, EVoid());return TRUE; +#line 5534 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 5535 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}return TRUE;}BOOL CPlayerWeapons::H0x019200cb_Idle_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200cb + ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5539 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Stopped(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_Stopped + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeapons::Stopped expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 5542 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(m_iCurrentWeapon == WEAPON_ROCKETLAUNCHER ){ +#line 5543 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * pmo = & (m_moWeapon . GetAttachmentModel (ROCKETLAUNCHER_ATTACHMENT_ROCKET1 ) -> amo_moModelObject ); +#line 5544 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +if(pmo ){pmo -> StretchModel (FLOAT3D (1 , 1 , 1));} +#line 5545 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +} +#line 5547 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ResetWeaponMovingOffset (); +#line 5548 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer & pl = (CPlayer &) * m_penPlayer ; +#line 5549 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon0 . Stop (); +#line 5550 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon1 . Stop (); +#line 5551 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon2 . Stop (); +#line 5552 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +pl . m_soWeapon3 . Stop (); +#line 5553 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayLightAnim (LIGHT_ANIM_NONE , 0); +#line 5554 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x019200cd, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200cd_Stopped_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200cd +switch(__eeInput.ee_slEvent){case(EVENTCODE_EPostLevelChange):{const EPostLevelChange&e= (EPostLevelChange&)__eeInput; +Return(STATE_CURRENT,EBegin ());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; +Return(STATE_CURRENT,EBegin ());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 5559 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}return TRUE;}BOOL CPlayerWeapons::H0x019200ce_Stopped_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200ce + ASSERT(FALSE); return TRUE;};BOOL CPlayerWeapons:: +#line 5567 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeapons_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EWeaponsInit, "CPlayerWeapons::Main expects 'EWeaponsInit' as input!"); const EWeaponsInit &eInit = (const EWeaponsInit &)__eeInput; +#line 5569 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ASSERT (eInit . penOwner != NULL ); +#line 5570 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_penPlayer = eInit . penOwner ; +#line 5573 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +InitAsVoid (); +#line 5574 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetFlags (GetFlags () | ENF_CROSSESLEVELS | ENF_NOTIFYLEVELCHANGE ); +#line 5575 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 5576 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 5579 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetCurrentWeaponModel (); +#line 5582 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PlayDefaultAnim (); +#line 5584 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x019200cf, FALSE, EBegin());return TRUE;}BOOL CPlayerWeapons::H0x019200cf_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200cf +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +Call(STATE_CURRENT, STATE_CPlayerWeapons_Idle, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ESelectWeapon):{const ESelectWeapon&eSelect= (ESelectWeapon&)__eeInput; + +#line 5588 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SelectWeaponChange (eSelect . iWeapon ); +#line 5589 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 5590 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;case(EVENTCODE_EPreLevelChange):{const EPreLevelChange&e= (EPreLevelChange&)__eeInput; + +#line 5594 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = FALSE ; +#line 5595 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Call(STATE_CURRENT, STATE_CPlayerWeapons_Stopped, TRUE, EVoid());return TRUE; +#line 5596 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 5597 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;case(EVENTCODE_EFireWeapon):{const EFireWeapon&e= (EFireWeapon&)__eeInput; + +#line 5600 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = TRUE ; +#line 5601 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 5602 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReleaseWeapon):{const EReleaseWeapon&e= (EReleaseWeapon&)__eeInput; + +#line 5605 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bFireWeapon = FALSE ; +#line 5606 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 5607 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReloadWeapon):{const EReloadWeapon&e= (EReloadWeapon&)__eeInput; + +#line 5610 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +m_bReloadWeapon = TRUE ; +#line 5611 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; +#line 5612 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; +Call(STATE_CURRENT, STATE_CPlayerWeapons_Stopped, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EEnd):{const EEnd&e= (EEnd&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x019200d0, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 5615 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +}return TRUE;}BOOL CPlayerWeapons::H0x019200d0_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x019200d0 + +#line 5618 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Destroy (); +#line 5619 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Return(STATE_CURRENT,EVoid()); +#line 5619 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/PlayerWeapons.es b/Sources/EntitiesMP/PlayerWeapons.es new file mode 100644 index 0000000..9de5b2b --- /dev/null +++ b/Sources/EntitiesMP/PlayerWeapons.es @@ -0,0 +1,5621 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +402 +%{ +#include "StdH.h" +#include "GameMP/SEColors.h" + +#include + +#include "EntitiesMP/Player.h" +#include "EntitiesMP/Bullet.h" +#include "Models/Weapons/Knife/Knife.h" +#include "Models/Weapons/Knife/KnifeItem.h" +#include "Models/Weapons/Colt/Colt.h" +#include "Models/Weapons/Colt/ColtMain.h" +#include "Models/Weapons/SingleShotgun/SingleShotgun.h" +#include "Models/Weapons/SingleShotgun/Barrels.h" +#include "Models/Weapons/DoubleShotgun/DoubleShotgun.h" +#include "Models/Weapons/DoubleShotgun/Dshotgunbarrels.h" +#include "Models/Weapons/DoubleShotgun/HandWithAmmo.h" +#include "Models/Weapons/TommyGun/TommyGun.h" +#include "Models/Weapons/TommyGun/Body.h" +#include "Models/Weapons/MiniGun/MiniGun.h" +#include "Models/Weapons/MiniGun/Body.h" +#include "Models/Weapons/GrenadeLauncher/GrenadeLauncher.h" +#include "Models/Weapons/RocketLauncher/RocketLauncher.h" +#include "Models/Weapons/Laser/Laser.h" +#include "Models/Weapons/Laser/Barrel.h" +#include "Models/Weapons/Cannon/Cannon.h" +#include "Models/Weapons/Cannon/Body.h" +// Mission Pack weapons +#include "ModelsMP/Weapons/Sniper/Sniper.h" +#include "ModelsMP/Weapons/Sniper/Body.h" +#include "ModelsMP/Weapons/Flamer/Flamer.h" +#include "ModelsMP/Weapons/Flamer/Body.h" +#include "ModelsMP/Weapons/Flamer/FuelReservoir.h" +#include "ModelsMP/Weapons/Flamer/Flame.h" +#include "ModelsMP/Weapons/Chainsaw/Chainsaw.h" +#include "ModelsMP/Weapons/Chainsaw/ChainSawForPlayer.h" +#include "ModelsMP/Weapons/Chainsaw/Body.h" +#include "ModelsMP/Weapons/Chainsaw/Blade.h" +#include "ModelsMP/Weapons/Chainsaw/Teeth.h" + +// Mission Pack player body instead of the old one +#include "ModelsMP/Player/SeriousSam/Body.h" +#include "ModelsMP/Player/SeriousSam/Player.h" + +#include "EntitiesMP/Switch.h" +#include "EntitiesMP/PlayerView.h" +#include "EntitiesMP/PlayerAnimator.h" +#include "EntitiesMP/MovingBrush.h" +#include "EntitiesMP/MessageHolder.h" +#include "EntitiesMP/EnemyBase.h" +extern INDEX hud_bShowWeapon; + +extern const INDEX aiWeaponsRemap[19] = { 0, 1, 10, 2, 3, 4, 5, 6, 7, + 8, 9, 11, 13, 12, 14, 15, 16, 17, 18 }; + +%} + +uses "EntitiesMP/Player"; +uses "EntitiesMP/PlayerWeaponsEffects"; +uses "EntitiesMP/Projectile"; +uses "EntitiesMP/Bullet"; +uses "EntitiesMP/BasicEffects"; +uses "EntitiesMP/WeaponItem"; +uses "EntitiesMP/AmmoItem"; +uses "EntitiesMP/AmmoPack"; +uses "EntitiesMP/ModelHolder2"; +//uses "EntitiesMP/Pipebomb"; +//uses "EntitiesMP/GhostBusterRay"; +uses "EntitiesMP/CannonBall"; + + +// input parameter for weapons +event EWeaponsInit { + CEntityPointer penOwner, // who owns it +}; + +// select weapon +event ESelectWeapon { + INDEX iWeapon, // weapon to select +}; + +// boring weapon animations +event EBoringWeapon {}; + +// fire weapon +event EFireWeapon {}; +// release weapon +event EReleaseWeapon {}; +// reload weapon +event EReloadWeapon {}; +// weapon changed - used to notify other entities +event EWeaponChanged {}; + +// weapons (do not change order! - needed by HUD.cpp) +enum WeaponType { + 0 WEAPON_NONE "", // don't consider this in WEAPONS_ALLAVAILABLEMASK + 1 WEAPON_KNIFE "", + 2 WEAPON_COLT "", + 3 WEAPON_DOUBLECOLT "", + 4 WEAPON_SINGLESHOTGUN "", + 5 WEAPON_DOUBLESHOTGUN "", + 6 WEAPON_TOMMYGUN "", + 7 WEAPON_MINIGUN "", + 8 WEAPON_ROCKETLAUNCHER "", + 9 WEAPON_GRENADELAUNCHER "", + 10 WEAPON_CHAINSAW "", + 11 WEAPON_FLAMER "", + 12 WEAPON_LASER "", + 13 WEAPON_SNIPER "", + 14 WEAPON_IRONCANNON "", + 15 WEAPON_LAST "", +}; // see 'WEAPONS_ALLAVAILABLEMASK' -> (11111111111111 == 0x3FFF) + +%{ +// AVAILABLE WEAPON MASK +#define WEAPONS_ALLAVAILABLEMASK 0x3FFF + +/* +#if BUILD_TEST + #define WEAPONS_DISABLEDMASK (\ + (1<<(WEAPON_TOMMYGUN -1))|\ + (1<<(WEAPON_GRENADELAUNCHER-1))|\ + (1<<(WEAPON_PIPEBOMB -1))|\ + (1<<(WEAPON_FLAMER -1))|\ + (1<<(WEAPON_LASER -1))|\ + (1<<(WEAPON_GHOSTBUSTER -1))|\ + (1<<(WEAPON_IRONCANNON -1))|\ + (1<<(WEAPON_NUKECANNON -1))) +#else + #define WEAPONS_DISABLEDMASK (0) +#endif + */ + +#define MAX_WEAPONS 30 + + +// MiniGun specific +#define MINIGUN_STATIC 0 +#define MINIGUN_FIRE 1 +#define MINIGUN_SPINUP 2 +#define MINIGUN_SPINDOWN 3 + +#define MINIGUN_SPINUPTIME 0.5f +#define MINIGUN_SPINDNTIME 3.0f +#define MINIGUN_SPINUPSOUND 0.5f +#define MINIGUN_SPINDNSOUND 1.5f +#define MINIGUN_FULLSPEED 500.0f +#define MINIGUN_SPINUPACC (MINIGUN_FULLSPEED/MINIGUN_SPINUPTIME) +#define MINIGUN_SPINDNACC (MINIGUN_FULLSPEED/MINIGUN_SPINDNTIME) +#define MINIGUN_TICKTIME (_pTimer->TickQuantum) + +// chainsaw specific +#define CHAINSAW_UPDATETIME 0.05f + +// fire flare specific +#define FLARE_REMOVE 1 +#define FLARE_ADD 2 + +// animation light specific +#define LIGHT_ANIM_MINIGUN 2 +#define LIGHT_ANIM_TOMMYGUN 3 +#define LIGHT_ANIM_COLT_SHOTGUN 4 +#define LIGHT_ANIM_NONE 5 + + +// mana for ammo adjustment (multiplier) +#define MANA_AMMO (0.1f) + +// position of weapon model -- weapon 0 is never used +static FLOAT wpn_fH[MAX_WEAPONS+1]; +static FLOAT wpn_fP[MAX_WEAPONS+1]; +static FLOAT wpn_fB[MAX_WEAPONS+1]; +static FLOAT wpn_fX[MAX_WEAPONS+1]; +static FLOAT wpn_fY[MAX_WEAPONS+1]; +static FLOAT wpn_fZ[MAX_WEAPONS+1]; +static FLOAT wpn_fFOV[MAX_WEAPONS+1]; +static FLOAT wpn_fClip[MAX_WEAPONS+1]; +static FLOAT wpn_fFX[MAX_WEAPONS+1]; // firing source +static FLOAT wpn_fFY[MAX_WEAPONS+1]; +//static FLOAT wpn_fFZ[MAX_WEAPONS+1]; +static INDEX wpn_iCurrent; +extern FLOAT hud_tmWeaponsOnScreen; +extern FLOAT wpn_fRecoilSpeed[17]; +extern FLOAT wpn_fRecoilLimit[17]; +extern FLOAT wpn_fRecoilDampUp[17]; +extern FLOAT wpn_fRecoilDampDn[17]; +extern FLOAT wpn_fRecoilOffset[17]; +extern FLOAT wpn_fRecoilFactorP[17]; +extern FLOAT wpn_fRecoilFactorZ[17]; + +// bullet positions +static FLOAT afSingleShotgunPellets[] = +{ -0.3f,+0.1f, +0.0f,+0.1f, +0.3f,+0.1f, + -0.4f,-0.1f, -0.1f,-0.1f, +0.1f,-0.1f, +0.4f,-0.1f +}; +static FLOAT afDoubleShotgunPellets[] = +{ + -0.3f,+0.15f, +0.0f,+0.15f, +0.3f,+0.15f, + -0.4f,+0.05f, -0.1f,+0.05f, +0.1f,+0.05f, +0.4f,+0.05f, + -0.3f,-0.05f, +0.0f,-0.05f, +0.3f,-0.05f, + -0.4f,-0.15f, -0.1f,-0.15f, +0.1f,-0.15f, +0.4f,-0.15f +}; + +// sniper discrete zoom values - 4 (1x,2x,4x,6x) +// synchronize this with sniper properties (properties 233-237) +static INDEX iSniperDiscreteZoomLevels = 4; +static FLOAT afSniperZoom[] = +{ + 90.0f,1.0f, 53.1f, 2.0f, 28.0f,4.0f, 14.2f,6.0f, + //7.2f,8.0f, 3.56f,10.0f ,1.8f,12.0f +}; + +// crosshair console variables +static INDEX hud_bCrosshairFixed = FALSE; +static INDEX hud_bCrosshairColoring = TRUE; +static FLOAT hud_fCrosshairScale = 1.0f; +static FLOAT hud_fCrosshairOpacity = 1.0f; +static FLOAT hud_fCrosshairRatio = 0.5f; // max distance size ratio +// misc HUD vars +static INDEX hud_bShowPlayerName = TRUE; +static INDEX hud_bShowCoords = FALSE; +static FLOAT plr_tmSnoopingDelay = 1.0f; // seconds +extern FLOAT plr_tmSnoopingTime = 1.0f; // seconds + +// some static vars +static INDEX _iLastCrosshairType=-1; +static CTextureObject _toCrosshair; + +// must do this to keep dependency catcher happy +CTFileName fn1 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair1.tex"); +CTFileName fn2 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair2.tex"); +CTFileName fn3 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair3.tex"); +CTFileName fn4 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair4.tex"); +CTFileName fn5 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair5.tex"); +CTFileName fn6 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair6.tex"); +CTFileName fn7 = CTFILENAME("Textures\\Interface\\Crosshairs\\Crosshair7.tex"); + +void CPlayerWeapons_Precache(ULONG ulAvailable) +{ + CDLLEntityClass *pdec = &CPlayerWeapons_DLLClass; + + // precache general stuff always + pdec->PrecacheTexture(TEX_REFL_BWRIPLES01 ); + pdec->PrecacheTexture(TEX_REFL_BWRIPLES02 ); + pdec->PrecacheTexture(TEX_REFL_LIGHTMETAL01 ); + pdec->PrecacheTexture(TEX_REFL_LIGHTBLUEMETAL01); + pdec->PrecacheTexture(TEX_REFL_DARKMETAL ); + pdec->PrecacheTexture(TEX_REFL_PURPLE01 ); + pdec->PrecacheTexture(TEX_SPEC_WEAK ); + pdec->PrecacheTexture(TEX_SPEC_MEDIUM ); + pdec->PrecacheTexture(TEX_SPEC_STRONG ); + pdec->PrecacheTexture(TEXTURE_HAND ); + pdec->PrecacheTexture(TEXTURE_FLARE01 ); + pdec->PrecacheModel(MODEL_FLARE01); + pdec->PrecacheClass(CLASS_BULLET); + pdec->PrecacheSound(SOUND_SILENCE); + + // precache other weapons if available + if ( ulAvailable&(1<<(WEAPON_KNIFE-1)) ) { + pdec->PrecacheModel(MODEL_KNIFE ); + pdec->PrecacheModel(MODEL_KNIFEITEM ); + pdec->PrecacheTexture(TEXTURE_KNIFEITEM ); + pdec->PrecacheSound(SOUND_KNIFE_BACK ); + pdec->PrecacheSound(SOUND_KNIFE_HIGH ); + pdec->PrecacheSound(SOUND_KNIFE_LONG ); + pdec->PrecacheSound(SOUND_KNIFE_LOW ); + } + + if ( ulAvailable&(1<<(WEAPON_COLT-1)) ) { + pdec->PrecacheModel(MODEL_COLT ); + pdec->PrecacheModel(MODEL_COLTCOCK ); + pdec->PrecacheModel(MODEL_COLTMAIN ); + pdec->PrecacheModel(MODEL_COLTBULLETS ); + pdec->PrecacheTexture(TEXTURE_COLTMAIN ); + pdec->PrecacheTexture(TEXTURE_COLTCOCK ); + pdec->PrecacheTexture(TEXTURE_COLTBULLETS ); + pdec->PrecacheSound(SOUND_COLT_FIRE ); + pdec->PrecacheSound(SOUND_COLT_RELOAD ); + } + + if ( ulAvailable&(1<<(WEAPON_SINGLESHOTGUN-1)) ) { + pdec->PrecacheModel(MODEL_SINGLESHOTGUN ); + pdec->PrecacheModel(MODEL_SS_SLIDER ); + pdec->PrecacheModel(MODEL_SS_HANDLE ); + pdec->PrecacheModel(MODEL_SS_BARRELS ); + pdec->PrecacheTexture(TEXTURE_SS_HANDLE ); + pdec->PrecacheTexture(TEXTURE_SS_BARRELS ); + pdec->PrecacheSound(SOUND_SINGLESHOTGUN_FIRE); + } + + if ( ulAvailable&(1<<(WEAPON_DOUBLESHOTGUN-1)) ) { + pdec->PrecacheModel(MODEL_DOUBLESHOTGUN ); + pdec->PrecacheModel(MODEL_DS_HANDLE ); + pdec->PrecacheModel(MODEL_DS_BARRELS ); + pdec->PrecacheModel(MODEL_DS_AMMO ); + pdec->PrecacheModel(MODEL_DS_SWITCH ); + pdec->PrecacheModel(MODEL_DS_HANDWITHAMMO ); + pdec->PrecacheTexture(TEXTURE_DS_HANDLE ); + pdec->PrecacheTexture(TEXTURE_DS_BARRELS ); + pdec->PrecacheTexture(TEXTURE_DS_AMMO ); + pdec->PrecacheTexture(TEXTURE_DS_SWITCH ); + pdec->PrecacheSound(SOUND_DOUBLESHOTGUN_FIRE ); + pdec->PrecacheSound(SOUND_DOUBLESHOTGUN_RELOAD ); + } + + if ( ulAvailable&(1<<(WEAPON_TOMMYGUN-1)) ) { + pdec->PrecacheModel(MODEL_TOMMYGUN ); + pdec->PrecacheModel(MODEL_TG_BODY ); + pdec->PrecacheModel(MODEL_TG_SLIDER ); + pdec->PrecacheTexture(TEXTURE_TG_BODY ); + pdec->PrecacheSound(SOUND_TOMMYGUN_FIRE ); + } + + if ( ulAvailable&(1<<(WEAPON_SNIPER-1)) ) { + pdec->PrecacheModel(MODEL_SNIPER ); + pdec->PrecacheModel(MODEL_SNIPER_BODY ); + pdec->PrecacheTexture(TEXTURE_SNIPER_BODY ); + pdec->PrecacheSound(SOUND_SNIPER_FIRE ); + } + + if ( ulAvailable&(1<<(WEAPON_MINIGUN-1)) ) { + pdec->PrecacheModel(MODEL_MINIGUN ); + pdec->PrecacheModel(MODEL_MG_BARRELS ); + pdec->PrecacheModel(MODEL_MG_BODY ); + pdec->PrecacheModel(MODEL_MG_ENGINE ); + pdec->PrecacheTexture(TEXTURE_MG_BODY ); + pdec->PrecacheTexture(TEXTURE_MG_BARRELS ); + pdec->PrecacheSound(SOUND_MINIGUN_FIRE ); + pdec->PrecacheSound(SOUND_MINIGUN_ROTATE ); + pdec->PrecacheSound(SOUND_MINIGUN_SPINUP ); + pdec->PrecacheSound(SOUND_MINIGUN_SPINDOWN ); + pdec->PrecacheSound(SOUND_MINIGUN_CLICK ); + } + + if ( ulAvailable&(1<<(WEAPON_ROCKETLAUNCHER-1)) ) { + pdec->PrecacheModel(MODEL_ROCKETLAUNCHER ); + pdec->PrecacheModel(MODEL_RL_BODY ); + pdec->PrecacheModel(MODEL_RL_ROTATINGPART ); + pdec->PrecacheModel(MODEL_RL_ROCKET ); + pdec->PrecacheTexture(TEXTURE_RL_BODY ); + pdec->PrecacheTexture(TEXTURE_RL_ROCKET ); + pdec->PrecacheSound(SOUND_ROCKETLAUNCHER_FIRE); + pdec->PrecacheClass(CLASS_PROJECTILE, PRT_ROCKET); + } + + if ( ulAvailable&(1<<(WEAPON_GRENADELAUNCHER-1)) ) { + pdec->PrecacheModel(MODEL_GRENADELAUNCHER ); + pdec->PrecacheModel(MODEL_GL_BODY ); + pdec->PrecacheModel(MODEL_GL_MOVINGPART ); + pdec->PrecacheModel(MODEL_GL_GRENADE ); + pdec->PrecacheTexture(TEXTURE_GL_BODY ); + pdec->PrecacheTexture(TEXTURE_GL_MOVINGPART ); + pdec->PrecacheSound(SOUND_GRENADELAUNCHER_FIRE ); + pdec->PrecacheClass(CLASS_PROJECTILE, PRT_GRENADE); + } + +/* + if ( ulAvailable&(1<<(WEAPON_PIPEBOMB-1)) ) { + pdec->PrecacheModel(MODEL_PIPEBOMB_STICK ); + pdec->PrecacheModel(MODEL_PIPEBOMB_HAND ); + pdec->PrecacheModel(MODEL_PB_BUTTON ); + pdec->PrecacheModel(MODEL_PB_SHIELD ); + pdec->PrecacheModel(MODEL_PB_STICK ); + pdec->PrecacheModel(MODEL_PB_BOMB ); + pdec->PrecacheTexture(TEXTURE_PB_STICK ); + pdec->PrecacheTexture(TEXTURE_PB_BOMB ); + pdec->PrecacheSound(SOUND_PIPEBOMB_FIRE ); + pdec->PrecacheSound(SOUND_PIPEBOMB_OPEN ); + pdec->PrecacheSound(SOUND_PIPEBOMB_THROW ); + pdec->PrecacheClass(CLASS_PIPEBOMB); + } +*/ + if ( ulAvailable&(1<<(WEAPON_CHAINSAW-1))) { + pdec->PrecacheModel(MODEL_CHAINSAW ); + pdec->PrecacheModel(MODEL_CS_BODY ); + pdec->PrecacheModel(MODEL_CS_BLADE ); + pdec->PrecacheModel(MODEL_CS_TEETH ); + pdec->PrecacheTexture(TEXTURE_CS_BODY ); + pdec->PrecacheTexture(TEXTURE_CS_BLADE ); + pdec->PrecacheTexture(TEXTURE_CS_TEETH ); + pdec->PrecacheSound(SOUND_CS_FIRE ); + pdec->PrecacheSound(SOUND_CS_BEGINFIRE ); + pdec->PrecacheSound(SOUND_CS_ENDFIRE ); + pdec->PrecacheSound(SOUND_CS_BRINGUP ); + pdec->PrecacheSound(SOUND_CS_BRINGDOWN ); + pdec->PrecacheSound(SOUND_CS_IDLE ); + } + + if ( ulAvailable&(1<<(WEAPON_FLAMER-1)) ) { + pdec->PrecacheModel(MODEL_FLAMER ); + pdec->PrecacheModel(MODEL_FL_BODY ); + pdec->PrecacheModel(MODEL_FL_RESERVOIR); + pdec->PrecacheModel(MODEL_FL_FLAME ); + pdec->PrecacheTexture(TEXTURE_FL_BODY ); + pdec->PrecacheTexture(TEXTURE_FL_FLAME); + pdec->PrecacheTexture(TEXTURE_FL_FUELRESERVOIR); + pdec->PrecacheSound(SOUND_FL_FIRE ); + pdec->PrecacheSound(SOUND_FL_START ); + pdec->PrecacheSound(SOUND_FL_STOP ); + pdec->PrecacheClass(CLASS_PROJECTILE, PRT_FLAME); + } + + + if ( ulAvailable&(1<<(WEAPON_LASER-1)) ) { + pdec->PrecacheModel(MODEL_LASER ); + pdec->PrecacheModel(MODEL_LS_BODY ); + pdec->PrecacheModel(MODEL_LS_BARREL ); + pdec->PrecacheTexture(TEXTURE_LS_BODY ); + pdec->PrecacheTexture(TEXTURE_LS_BARREL); + pdec->PrecacheSound(SOUND_LASER_FIRE); + pdec->PrecacheClass(CLASS_PROJECTILE, PRT_LASER_RAY); + } +/* + if ( ulAvailable&(1<<(WEAPON_GHOSTBUSTER-1)) ) { + pdec->PrecacheModel(MODEL_GHOSTBUSTER ); + pdec->PrecacheModel(MODEL_GB_BODY ); + pdec->PrecacheModel(MODEL_GB_ROTATOR ); + pdec->PrecacheModel(MODEL_GB_EFFECT1 ); + pdec->PrecacheModel(MODEL_GB_EFFECT1FLARE ); + pdec->PrecacheTexture(TEXTURE_GB_ROTATOR ); + pdec->PrecacheTexture(TEXTURE_GB_BODY ); + pdec->PrecacheTexture(TEXTURE_GB_LIGHTNING); + pdec->PrecacheTexture(TEXTURE_GB_FLARE ); + pdec->PrecacheSound(SOUND_GB_FIRE ); + pdec->PrecacheClass(CLASS_GHOSTBUSTERRAY); + } + */ + if ( ulAvailable&(1<<(WEAPON_IRONCANNON-1)) /*|| + ulAvailable&(1<<(WEAPON_NUKECANNON-1))*/ ) { + pdec->PrecacheModel(MODEL_CANNON ); + pdec->PrecacheModel(MODEL_CN_BODY ); +// pdec->PrecacheModel(MODEL_CN_NUKEBOX); + pdec->PrecacheTexture(TEXTURE_CANNON); + pdec->PrecacheSound(SOUND_CANNON ); + pdec->PrecacheSound(SOUND_CANNON_PREPARE); + pdec->PrecacheClass(CLASS_CANNONBALL); + } + + // precache animator too + extern void CPlayerAnimator_Precache(ULONG ulAvailable); + CPlayerAnimator_Precache(ulAvailable); +} + +void CPlayerWeapons_Init(void) { + // declare weapon position controls + _pShell->DeclareSymbol("user INDEX wpn_iCurrent;", &wpn_iCurrent); + + #include "Common/WeaponPositions.h" + + // declare crosshair and its coordinates + _pShell->DeclareSymbol("persistent user INDEX hud_bCrosshairFixed;", &hud_bCrosshairFixed); + _pShell->DeclareSymbol("persistent user INDEX hud_bCrosshairColoring;", &hud_bCrosshairColoring); + _pShell->DeclareSymbol("persistent user FLOAT hud_fCrosshairScale;", &hud_fCrosshairScale); + _pShell->DeclareSymbol("persistent user FLOAT hud_fCrosshairRatio;", &hud_fCrosshairRatio); + _pShell->DeclareSymbol("persistent user FLOAT hud_fCrosshairOpacity;", &hud_fCrosshairOpacity); + + _pShell->DeclareSymbol("persistent user INDEX hud_bShowPlayerName;", &hud_bShowPlayerName); + _pShell->DeclareSymbol("persistent user INDEX hud_bShowCoords;", &hud_bShowCoords); + + _pShell->DeclareSymbol("persistent user FLOAT plr_tmSnoopingTime;", &plr_tmSnoopingTime); + _pShell->DeclareSymbol("persistent user FLOAT plr_tmSnoopingDelay;", &plr_tmSnoopingDelay); + + // precache base weapons + CPlayerWeapons_Precache(0x03); +} + +// weapons positions for raycasting and firing +/* +static FLOAT afKnifePos[4] = { -0.01f, 0.25f, 0.0f}; +static FLOAT afColtPos[4] = { -0.01f, 0.1f, 0.0f}; +static FLOAT afDoubleColtPos[4] = { -0.01f, 0.1f, 0.0f}; +static FLOAT afSingleShotgunPos[4] = { 0.0f, 0.1f, 0.0f}; +static FLOAT afDoubleShotgunPos[4] = { 0.0f, 0.1f, 0.0f}; +static FLOAT afTommygunPos[4] = { 0.0f, 0.1f, 0.0f}; +static FLOAT afMinigunPos[4] = { 0.0f, -0.075f, 0.0f}; +static FLOAT afRocketLauncherPos[4] = { -0.175f, 0.19f, -0.23f}; +static FLOAT afGrenadeLauncherPos[4] = { 0.0f, 0.16f, -1.42f}; +static FLOAT afPipebombPos[4] = { 0.01f, 0.04f, -0.44f}; +static FLOAT afFlamerPos[4] = { 0.0f, 0.18f, -0.62f}; +static FLOAT afLaserPos[4] = { 0.0f, -0.095f, -0.65f}; +static FLOAT afGhostBusterPos[4] = { 0.0f, 0.0f, -0.74f}; +static FLOAT afCannonPos[4] = { 0.0f, 0.0f, -0.74f}; +*/ + +// extra weapon positions for shells dropout +static FLOAT afSingleShotgunShellPos[3] = { 0.2f, 0.0f, -0.31f}; +static FLOAT afDoubleShotgunShellPos[3] = { 0.0f, 0.0f, -0.5f}; +static FLOAT afTommygunShellPos[3] = { 0.2f, 0.0f, -0.31f}; +static FLOAT afMinigunShellPos[3] = { 0.2f, 0.0f, -0.31f}; +static FLOAT afMinigunShellPos3rdView[3] = { 0.2f, 0.2f, -0.31f}; +static FLOAT afSniperShellPos[3] = { 0.2f, 0.0f, -0.15f}; + +static FLOAT afRightColtPipe[3] = { 0.07f, -0.05f, -0.26f}; +static FLOAT afSingleShotgunPipe[3] = { 0.2f, 0.0f, -1.25f}; +static FLOAT afDoubleShotgunPipe[3] = { 0.2f, 0.0f, -1.25f}; +static FLOAT afTommygunPipe[3] = { -0.06f, 0.1f, -0.6f}; +static FLOAT afMinigunPipe[3] = { -0.06f, 0.0f, -0.6f}; +static FLOAT afMinigunPipe3rdView[3] = { 0.25f, 0.3f, -2.5f}; + +//static FLOAT afLaserPos[4] = { 0.0f, -0.095f, -0.65f}; +//static FLOAT afLaser1Pos[4] = { -0.115f, -0.05f, -0.65f}; +//static FLOAT afLaser2Pos[4] = { 0.115f, -0.05f, -0.65f}; +//static FLOAT afLaser3Pos[4] = { -0.145f, -0.14f, -0.8f}; +//static FLOAT afLaser4Pos[4] = { 0.145f, -0.14f, -0.8f}; + +#define TM_START m_aMiniGun +#define F_OFFSET_CHG m_aMiniGunLast +#define F_TEMP m_aMiniGunSpeed + +// decrement ammo taking infinite ammo options in account +void DecAmmo(INDEX &ctAmmo, INDEX iDec = 1) +{ + if (!GetSP()->sp_bInfiniteAmmo) { + ctAmmo-=iDec; + } +} +%} + +class export CPlayerWeapons : CRationalEntity { +name "Player Weapons"; +thumbnail ""; +features "CanBePredictable"; + +properties: + 1 CEntityPointer m_penPlayer, // player which owns it + 2 BOOL m_bFireWeapon = FALSE, // weapon is firing + 3 BOOL m_bHasAmmo = FALSE, // weapon has ammo + 4 enum WeaponType m_iCurrentWeapon = WEAPON_KNIFE, // currently active weapon (internal) + 5 enum WeaponType m_iWantedWeapon = WEAPON_KNIFE, // wanted weapon (internal) + 6 enum WeaponType m_iPreviousWeapon = WEAPON_KNIFE, // previous active weapon (internal) + 11 INDEX m_iAvailableWeapons = 0x01, // avaible weapons + 12 BOOL m_bChangeWeapon = FALSE, // change current weapon + 13 BOOL m_bReloadWeapon = FALSE, // reload weapon + 14 BOOL m_bMirrorFire = FALSE, // fire with mirror model + 15 INDEX m_iAnim = 0, // temporary anim variable + 16 FLOAT m_fAnimWaitTime = 0.0f, // animation wait time + 17 FLOAT m_tmRangeSoundSpawned = 0.0f, // for not spawning range sounds too often + 23 BOOL m_bSniperZoom = FALSE, // zoom sniper + 24 FLOAT m_fSniperFOV = 90.0f, // sniper FOV + 28 FLOAT m_fSniperFOVlast = 90.0f, // sniper FOV for lerping + + 18 CTString m_strLastTarget = "", // string for last target + 19 FLOAT m_tmTargetingStarted = -99.0f, // when targeting started + 20 FLOAT m_tmLastTarget = -99.0f, // when last target was seen + 21 FLOAT m_tmSnoopingStarted = -99.0f, // is player spying another player + 22 CEntityPointer m_penTargeting, // who is the target + + 25 CModelObject m_moWeapon, // current weapon model + 26 CModelObject m_moWeaponSecond, // current weapon second (additional) model + 27 FLOAT m_tmWeaponChangeRequired = 0.0f, // time when weapon change was required + + 30 CEntityPointer m_penRayHit, // entity hit by ray + 31 FLOAT m_fRayHitDistance = 100.0f, // distance from hit point + 32 FLOAT m_fEnemyHealth = 0.0f, // normalized health of enemy in target (for coloring of crosshair) + 33 FLOAT3D m_vRayHit = FLOAT3D(0,0,0), // coordinates where ray hit + 34 FLOAT3D m_vRayHitLast = FLOAT3D(0,0,0), // for lerping + 35 FLOAT3D m_vBulletSource = FLOAT3D(0,0,0), // bullet launch position remembered here + 36 FLOAT3D m_vBulletTarget = FLOAT3D(0,0,0), // bullet hit (if hit) position remembered here + + // ammo for all weapons + 40 INDEX m_iBullets = 0, + 41 INDEX m_iMaxBullets = MAX_BULLETS, + 42 INDEX m_iShells = 0, + 43 INDEX m_iMaxShells = MAX_SHELLS, + 44 INDEX m_iRockets = 0, + 45 INDEX m_iMaxRockets = MAX_ROCKETS, + 46 INDEX m_iGrenades = 0, + 47 INDEX m_iMaxGrenades = MAX_GRENADES, + 48 INDEX m_iNapalm = 0, + 49 INDEX m_iMaxNapalm = MAX_NAPALM, + 50 INDEX m_iElectricity = 0, + 51 INDEX m_iMaxElectricity = MAX_ELECTRICITY, + 52 INDEX m_iIronBalls = 0, + 53 INDEX m_iMaxIronBalls = MAX_IRONBALLS, +// 54 INDEX m_iNukeBalls = 0, +// 55 INDEX m_iMaxNukeBalls = MAX_NUKEBALLS, + 54 INDEX m_iSniperBullets = 0, + 55 INDEX m_iMaxSniperBullets = MAX_SNIPERBULLETS, + +// weapons specific +// knife +210 INDEX m_iKnifeStand = 1, +// colt +215 INDEX m_iColtBullets = 6, +// minigun +220 FLOAT m_aMiniGun = 0.0f, +221 FLOAT m_aMiniGunLast = 0.0f, +222 FLOAT m_aMiniGunSpeed = 0.0f, + +// lerped bullets fire +230 FLOAT3D m_iLastBulletPosition = FLOAT3D(32000.0f, 32000.0f, 32000.0f), +231 INDEX m_iBulletsOnFireStart = 0, +// sniper +233 FLOAT m_fSniperMaxFOV = 90.0f, +234 FLOAT m_fSniperMinFOV = 14.2f, +235 FLOAT m_fSnipingZoomSpeed = 2.0f, +236 BOOL m_bSniping = FALSE, +237 FLOAT m_fMinimumZoomFOV = 53.1f, +238 FLOAT m_tmLastSniperFire = 0.0f, +// pipebomb +//235 CEntityPointer m_penPipebomb, +//236 INDEX m_bPipeBombDropped = FALSE, +// flamer +240 CEntityPointer m_penFlame, +// laser +245 INDEX m_iLaserBarrel = 0, +// ghostbuster +//250 CEntityPointer m_penGhostBusterRay, +// fire flare +251 INDEX m_iFlare = FLARE_REMOVE, // 0-none, 1-remove, 2-add +252 INDEX m_iSecondFlare = FLARE_REMOVE, // 0-none, 1-remove, 2-add +// cannon +260 FLOAT m_fWeaponDrawPowerOld = 0, +261 FLOAT m_fWeaponDrawPower = 0, +262 FLOAT m_tmDrawStartTime = 0.0f, + +270 FLOAT m_tmFlamerStart=1e6, +271 FLOAT m_tmFlamerStop=1e9, +272 FLOAT m_tmLastChainsawSpray = 0.0f, + +{ + CEntity *penBullet; + CPlacement3D plBullet; + FLOAT3D vBulletDestination; +} + +components: + 1 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 2 class CLASS_BULLET "Classes\\Bullet.ecl", + 3 class CLASS_WEAPONEFFECT "Classes\\PlayerWeaponsEffects.ecl", + 4 class CLASS_PIPEBOMB "Classes\\Pipebomb.ecl", + 5 class CLASS_GHOSTBUSTERRAY "Classes\\GhostBusterRay.ecl", + 6 class CLASS_CANNONBALL "Classes\\CannonBall.ecl", + 7 class CLASS_WEAPONITEM "Classes\\WeaponItem.ecl", + 8 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + +// ************** HAND ************** + 10 texture TEXTURE_HAND "Models\\Weapons\\Hand.tex", + +// ************** KNIFE ************** + 20 model MODEL_KNIFEITEM "Models\\Weapons\\Knife\\KnifeItem.mdl", + 21 texture TEXTURE_KNIFEITEM "Models\\Weapons\\Knife\\KnifeItem.tex", + 22 model MODEL_KNIFE "Models\\Weapons\\Knife\\Knife.mdl", + 23 sound SOUND_KNIFE_BACK "Models\\Weapons\\Knife\\Sounds\\Back.wav", + 24 sound SOUND_KNIFE_HIGH "Models\\Weapons\\Knife\\Sounds\\High.wav", + 25 sound SOUND_KNIFE_LONG "Models\\Weapons\\Knife\\Sounds\\Long.wav", + 26 sound SOUND_KNIFE_LOW "Models\\Weapons\\Knife\\Sounds\\Low.wav", + +// ************** COLT ************** + 30 model MODEL_COLT "Models\\Weapons\\Colt\\Colt.mdl", + 31 model MODEL_COLTCOCK "Models\\Weapons\\Colt\\ColtCock.mdl", + 32 model MODEL_COLTMAIN "Models\\Weapons\\Colt\\ColtMain.mdl", + 33 model MODEL_COLTBULLETS "Models\\Weapons\\Colt\\ColtBullets.mdl", + 34 texture TEXTURE_COLTMAIN "Models\\Weapons\\Colt\\ColtMain.tex", + 35 texture TEXTURE_COLTCOCK "Models\\Weapons\\Colt\\ColtCock.tex", + 36 texture TEXTURE_COLTBULLETS "Models\\Weapons\\Colt\\ColtBullets.tex", + 37 sound SOUND_COLT_FIRE "Models\\Weapons\\Colt\\Sounds\\Fire.wav", + 38 sound SOUND_COLT_RELOAD "Models\\Weapons\\Colt\\Sounds\\Reload.wav", + +// ************** SINGLE SHOTGUN ************ + 40 model MODEL_SINGLESHOTGUN "Models\\Weapons\\SingleShotgun\\SingleShotgun.mdl", + 41 model MODEL_SS_SLIDER "Models\\Weapons\\SingleShotgun\\Slider.mdl", + 42 model MODEL_SS_HANDLE "Models\\Weapons\\SingleShotgun\\Handle.mdl", + 43 model MODEL_SS_BARRELS "Models\\Weapons\\SingleShotgun\\Barrels.mdl", + 44 texture TEXTURE_SS_HANDLE "Models\\Weapons\\SingleShotgun\\Handle.tex", + 45 texture TEXTURE_SS_BARRELS "Models\\Weapons\\SingleShotgun\\Barrels.tex", + 46 sound SOUND_SINGLESHOTGUN_FIRE "Models\\Weapons\\SingleShotgun\\Sounds\\_Fire.wav", + +// ************** DOUBLE SHOTGUN ************** + 50 model MODEL_DOUBLESHOTGUN "Models\\Weapons\\DoubleShotgun\\DoubleShotgun.mdl", + 51 model MODEL_DS_HANDLE "Models\\Weapons\\DoubleShotgun\\Dshotgunhandle.mdl", + 52 model MODEL_DS_BARRELS "Models\\Weapons\\DoubleShotgun\\Dshotgunbarrels.mdl", + 53 model MODEL_DS_AMMO "Models\\Weapons\\DoubleShotgun\\Ammo.mdl", + 54 model MODEL_DS_SWITCH "Models\\Weapons\\DoubleShotgun\\Switch.mdl", + 55 model MODEL_DS_HANDWITHAMMO "Models\\Weapons\\DoubleShotgun\\HandWithAmmo.mdl", + 56 texture TEXTURE_DS_HANDLE "Models\\Weapons\\DoubleShotgun\\Handle.tex", + 57 texture TEXTURE_DS_BARRELS "Models\\Weapons\\DoubleShotgun\\Barrels.tex", + 58 texture TEXTURE_DS_AMMO "Models\\Weapons\\DoubleShotgun\\Ammo.tex", + 59 texture TEXTURE_DS_SWITCH "Models\\Weapons\\DoubleShotgun\\Switch.tex", + 60 sound SOUND_DOUBLESHOTGUN_FIRE "Models\\Weapons\\DoubleShotgun\\Sounds\\Fire.wav", + 61 sound SOUND_DOUBLESHOTGUN_RELOAD "Models\\Weapons\\DoubleShotgun\\Sounds\\Reload.wav", + +// ************** TOMMYGUN ************** + 70 model MODEL_TOMMYGUN "Models\\Weapons\\TommyGun\\TommyGun.mdl", + 71 model MODEL_TG_BODY "Models\\Weapons\\TommyGun\\Body.mdl", + 72 model MODEL_TG_SLIDER "Models\\Weapons\\TommyGun\\Slider.mdl", + 73 texture TEXTURE_TG_BODY "Models\\Weapons\\TommyGun\\Body.tex", + 74 sound SOUND_TOMMYGUN_FIRE "Models\\Weapons\\TommyGun\\Sounds\\_Fire.wav", + +// ************** MINIGUN ************** + 80 model MODEL_MINIGUN "Models\\Weapons\\MiniGun\\MiniGun.mdl", + 81 model MODEL_MG_BARRELS "Models\\Weapons\\MiniGun\\Barrels.mdl", + 82 model MODEL_MG_BODY "Models\\Weapons\\MiniGun\\Body.mdl", + 83 model MODEL_MG_ENGINE "Models\\Weapons\\MiniGun\\Engine.mdl", + 84 texture TEXTURE_MG_BODY "Models\\Weapons\\MiniGun\\Body.tex", + 99 texture TEXTURE_MG_BARRELS "Models\\Weapons\\MiniGun\\Barrels.tex", + 85 sound SOUND_MINIGUN_FIRE "Models\\Weapons\\MiniGun\\Sounds\\Fire.wav", + 86 sound SOUND_MINIGUN_ROTATE "Models\\Weapons\\MiniGun\\Sounds\\Rotate.wav", + 87 sound SOUND_MINIGUN_SPINUP "Models\\Weapons\\MiniGun\\Sounds\\RotateUp.wav", + 88 sound SOUND_MINIGUN_SPINDOWN "Models\\Weapons\\MiniGun\\Sounds\\RotateDown.wav", + 89 sound SOUND_MINIGUN_CLICK "Models\\Weapons\\MiniGun\\Sounds\\Click.wav", + +// ************** ROCKET LAUNCHER ************** + 90 model MODEL_ROCKETLAUNCHER "Models\\Weapons\\RocketLauncher\\RocketLauncher.mdl", + 91 model MODEL_RL_BODY "Models\\Weapons\\RocketLauncher\\Body.mdl", + 92 texture TEXTURE_RL_BODY "Models\\Weapons\\RocketLauncher\\Body.tex", + 93 model MODEL_RL_ROTATINGPART "Models\\Weapons\\RocketLauncher\\RotatingPart.mdl", + 94 texture TEXTURE_RL_ROTATINGPART "Models\\Weapons\\RocketLauncher\\RotatingPart.tex", + 95 model MODEL_RL_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl", + 96 texture TEXTURE_RL_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex", + 97 sound SOUND_ROCKETLAUNCHER_FIRE "Models\\Weapons\\RocketLauncher\\Sounds\\_Fire.wav", + +// ************** GRENADE LAUNCHER ************** +100 model MODEL_GRENADELAUNCHER "Models\\Weapons\\GrenadeLauncher\\GrenadeLauncher.mdl", +101 model MODEL_GL_BODY "Models\\Weapons\\GrenadeLauncher\\Body.mdl", +102 model MODEL_GL_MOVINGPART "Models\\Weapons\\GrenadeLauncher\\MovingPipe.mdl", +103 model MODEL_GL_GRENADE "Models\\Weapons\\GrenadeLauncher\\GrenadeBack.mdl", +104 texture TEXTURE_GL_BODY "Models\\Weapons\\GrenadeLauncher\\Body.tex", +105 texture TEXTURE_GL_MOVINGPART "Models\\Weapons\\GrenadeLauncher\\MovingPipe.tex", +106 sound SOUND_GRENADELAUNCHER_FIRE "Models\\Weapons\\GrenadeLauncher\\Sounds\\_Fire.wav", + +// ************** SNIPER ************** +110 model MODEL_SNIPER "ModelsMP\\Weapons\\Sniper\\Sniper.mdl", +111 model MODEL_SNIPER_BODY "ModelsMP\\Weapons\\Sniper\\Body.mdl", +112 texture TEXTURE_SNIPER_BODY "ModelsMP\\Weapons\\Sniper\\Body.tex", +113 sound SOUND_SNIPER_FIRE "ModelsMP\\Weapons\\Sniper\\Sounds\\Fire.wav", +//114 sound SOUND_SNIPER_RELOAD "ModelsMP\\Weapons\\Sniper\\Sounds\\Reload.wav", +//115 sound SOUND_SNIPER_ZOOM "ModelsMP\\Weapons\\Sniper\\Sounds\\Zoom.wav", + +/* +// ************** PIPEBOMB ************** +110 model MODEL_PIPEBOMB_STICK "Models\\Weapons\\Pipebomb\\HandWithStick.mdl", +111 model MODEL_PIPEBOMB_HAND "Models\\Weapons\\Pipebomb\\HandWithBomb.mdl", +112 model MODEL_PB_BUTTON "Models\\Weapons\\Pipebomb\\Button.mdl", +113 model MODEL_PB_SHIELD "Models\\Weapons\\Pipebomb\\Shield.mdl", +114 model MODEL_PB_STICK "Models\\Weapons\\Pipebomb\\Stick.mdl", +115 model MODEL_PB_BOMB "Models\\Weapons\\Pipebomb\\Bomb.mdl", +116 texture TEXTURE_PB_STICK "Models\\Weapons\\Pipebomb\\Stick.tex", +117 texture TEXTURE_PB_BOMB "Models\\Weapons\\Pipebomb\\Bomb.tex", +118 sound SOUND_PIPEBOMB_FIRE "Models\\Weapons\\Pipebomb\\Sounds\\Fire.wav", +119 sound SOUND_PIPEBOMB_OPEN "Models\\Weapons\\Pipebomb\\Sounds\\Open.wav", +120 sound SOUND_PIPEBOMB_THROW "Models\\Weapons\\Pipebomb\\Sounds\\Throw.wav", +*/ +// ************** FLAMER ************** +130 model MODEL_FLAMER "ModelsMP\\Weapons\\Flamer\\Flamer.mdl", +131 model MODEL_FL_BODY "ModelsMP\\Weapons\\Flamer\\Body.mdl", +132 model MODEL_FL_RESERVOIR "ModelsMP\\Weapons\\Flamer\\FuelReservoir.mdl", +133 model MODEL_FL_FLAME "ModelsMP\\Weapons\\Flamer\\Flame.mdl", +134 texture TEXTURE_FL_BODY "ModelsMP\\Weapons\\Flamer\\Body.tex", +135 texture TEXTURE_FL_FLAME "ModelsMP\\Effects\\Flame\\Flame.tex", +136 sound SOUND_FL_FIRE "ModelsMP\\Weapons\\Flamer\\Sounds\\Fire.wav", +137 sound SOUND_FL_START "ModelsMP\\Weapons\\Flamer\\Sounds\\Start.wav", +138 sound SOUND_FL_STOP "ModelsMP\\Weapons\\Flamer\\Sounds\\Stop.wav", +139 texture TEXTURE_FL_FUELRESERVOIR "ModelsMP\\Weapons\\Flamer\\FuelReservoir.tex", + + +// ************** LASER ************** +140 model MODEL_LASER "Models\\Weapons\\Laser\\Laser.mdl", +141 model MODEL_LS_BODY "Models\\Weapons\\Laser\\Body.mdl", +142 model MODEL_LS_BARREL "Models\\Weapons\\Laser\\Barrel.mdl", +144 texture TEXTURE_LS_BODY "Models\\Weapons\\Laser\\Body.tex", +145 texture TEXTURE_LS_BARREL "Models\\Weapons\\Laser\\Barrel.tex", +146 sound SOUND_LASER_FIRE "Models\\Weapons\\Laser\\Sounds\\_Fire.wav", + + +// ************** CHAINSAW ************** +150 model MODEL_CHAINSAW "ModelsMP\\Weapons\\Chainsaw\\Chainsaw.mdl", +151 model MODEL_CS_BODY "ModelsMP\\Weapons\\Chainsaw\\Body.mdl", +152 model MODEL_CS_BLADE "ModelsMP\\Weapons\\Chainsaw\\Blade.mdl", +160 model MODEL_CS_TEETH "ModelsMP\\Weapons\\Chainsaw\\Teeth.mdl", +153 texture TEXTURE_CS_BODY "ModelsMP\\Weapons\\Chainsaw\\Body.tex", +154 texture TEXTURE_CS_BLADE "ModelsMP\\Weapons\\Chainsaw\\Blade.tex", +161 texture TEXTURE_CS_TEETH "ModelsMP\\Weapons\\Chainsaw\\Teeth.tex", +155 sound SOUND_CS_FIRE "ModelsMP\\Weapons\\Chainsaw\\Sounds\\Fire.wav", +156 sound SOUND_CS_BEGINFIRE "ModelsMP\\Weapons\\Chainsaw\\Sounds\\BeginFire.wav", +157 sound SOUND_CS_ENDFIRE "ModelsMP\\Weapons\\Chainsaw\\Sounds\\EndFire.wav", +158 sound SOUND_CS_BRINGUP "ModelsMP\\Weapons\\Chainsaw\\Sounds\\BringUp.wav", +159 sound SOUND_CS_IDLE "ModelsMP\\Weapons\\Chainsaw\\Sounds\\Idle.wav", +162 sound SOUND_CS_BRINGDOWN "ModelsMP\\Weapons\\Chainsaw\\Sounds\\BringDown.wav", + + +/* +// ************** GHOSTBUSTER ************** +150 model MODEL_GHOSTBUSTER "Models\\Weapons\\GhostBuster\\GhostBuster.mdl", +151 model MODEL_GB_BODY "Models\\Weapons\\GhostBuster\\Body.mdl", +152 model MODEL_GB_ROTATOR "Models\\Weapons\\GhostBuster\\Rotator.mdl", +153 model MODEL_GB_EFFECT1 "Models\\Weapons\\GhostBuster\\Effect01.mdl", +154 model MODEL_GB_EFFECT1FLARE "Models\\Weapons\\GhostBuster\\EffectFlare01.mdl", +155 texture TEXTURE_GB_ROTATOR "Models\\Weapons\\GhostBuster\\Rotator.tex", +156 texture TEXTURE_GB_BODY "Models\\Weapons\\GhostBuster\\Body.tex", +157 texture TEXTURE_GB_LIGHTNING "Models\\Weapons\\GhostBuster\\Lightning.tex", +158 texture TEXTURE_GB_FLARE "Models\\Weapons\\GhostBuster\\EffectFlare.tex", +159 sound SOUND_GB_FIRE "Models\\Weapons\\GhostBuster\\Sounds\\_Fire.wav", +*/ +// ************** CANNON ************** +170 model MODEL_CANNON "Models\\Weapons\\Cannon\\Cannon.mdl", +171 model MODEL_CN_BODY "Models\\Weapons\\Cannon\\Body.mdl", +//172 model MODEL_CN_NUKEBOX "Models\\Weapons\\Cannon\\NukeBox.mdl", +173 texture TEXTURE_CANNON "Models\\Weapons\\Cannon\\Body.tex", +174 sound SOUND_CANNON "Models\\Weapons\\Cannon\\Sounds\\Fire.wav", +175 sound SOUND_CANNON_PREPARE "Models\\Weapons\\Cannon\\Sounds\\Prepare.wav", +//175 model MODEL_CN_LIGHT "Models\\Weapons\\Cannon\\Light.mdl", + +// ************** REFLECTIONS ************** +200 texture TEX_REFL_BWRIPLES01 "Models\\ReflectionTextures\\BWRiples01.tex", +201 texture TEX_REFL_BWRIPLES02 "Models\\ReflectionTextures\\BWRiples02.tex", +202 texture TEX_REFL_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex", +203 texture TEX_REFL_LIGHTBLUEMETAL01 "Models\\ReflectionTextures\\LightBlueMetal01.tex", +204 texture TEX_REFL_DARKMETAL "Models\\ReflectionTextures\\DarkMetal.tex", +205 texture TEX_REFL_PURPLE01 "Models\\ReflectionTextures\\Purple01.tex", + +// ************** SPECULAR ************** +210 texture TEX_SPEC_WEAK "Models\\SpecularTextures\\Weak.tex", +211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex", +212 texture TEX_SPEC_STRONG "Models\\SpecularTextures\\Strong.tex", + +// ************** FLARES ************** +250 model MODEL_FLARE01 "Models\\Effects\\Weapons\\Flare01\\Flare.mdl", +251 texture TEXTURE_FLARE01 "Models\\Effects\\Weapons\\Flare01\\Flare.tex", + +280 sound SOUND_SILENCE "Sounds\\Misc\\Silence.wav", + + +functions: + + // add to prediction any entities that this entity depends on + void AddDependentsToPrediction(void) + { + m_penPlayer->AddToPrediction(); + //m_penPipebomb->AddToPrediction(); + //m_penGhostBusterRay->AddToPrediction(); + m_penFlame->AddToPrediction(); + } + void Precache(void) + { + CPlayerWeapons_Precache(m_iAvailableWeapons); + } + CPlayer *GetPlayer(void) + { + ASSERT(m_penPlayer!=NULL); + return (CPlayer *)&*m_penPlayer; + } + CPlayerAnimator *GetAnimator(void) + { + ASSERT(m_penPlayer!=NULL); + return ((CPlayerAnimator*)&*((CPlayer&)*m_penPlayer).m_penAnimator); + } + + CModelObject *GetChainSawTeeth(void) + { + CPlayer *ppl=GetPlayer(); + if(ppl==NULL) { return NULL;} + CModelObject *pmoPlayer = ppl->GetModelObject(); + if(pmoPlayer==NULL) { return NULL;} + CAttachmentModelObject *pamoTorso = pmoPlayer->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO); + if(pamoTorso==NULL) { return NULL;} + CAttachmentModelObject *pamoChainSaw = pamoTorso->amo_moModelObject.GetAttachmentModel(BODY_ATTACHMENT_MINIGUN); + if(pamoChainSaw==NULL) { return NULL;} + CAttachmentModelObject *pamoBlade = pamoChainSaw->amo_moModelObject.GetAttachmentModel(CHAINSAWFORPLAYER_ATTACHMENT_BLADE); + if(pamoBlade==NULL) { return NULL;} + CAttachmentModelObject *pamoTeeth = pamoBlade->amo_moModelObject.GetAttachmentModel(BLADE_ATTACHMENT_TEETH); + if(pamoTeeth==NULL) { return NULL;} + return &pamoTeeth->amo_moModelObject; + } + + // recoil + void DoRecoil(void) + { +// CPlayerAnimator &plan = (CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator; +// plan.m_fRecoilSpeed += wpn_fRecoilSpeed[m_iCurrentWeapon]; + } + + // + BOOL HoldingFire(void) + { + return m_bFireWeapon && !m_bChangeWeapon; + } + + + // render weapon model(s) + void RenderWeaponModel( CPerspectiveProjection3D &prProjection, CDrawPort *pdp, + FLOAT3D vViewerLightDirection, COLOR colViewerLight, COLOR colViewerAmbient, + BOOL bRender, INDEX iEye) + { + _mrpModelRenderPrefs.SetRenderType( RT_TEXTURE|RT_SHADING_PHONG); + + // flare attachment + ControlFlareAttachment(); + + if( !bRender || m_iCurrentWeapon==WEAPON_NONE + || GetPlayer()->GetSettings()->ps_ulFlags&PSF_HIDEWEAPON) { return; } + + // nuke and iron cannons have the same view settings + INDEX iWeaponData = m_iCurrentWeapon; + + // store FOV for Crosshair + const FLOAT fFOV = ((CPerspectiveProjection3D &)prProjection).FOVL(); + CPlacement3D plView; + plView = ((CPlayer&)*m_penPlayer).en_plViewpoint; + plView.RelativeToAbsolute(m_penPlayer->GetPlacement()); + + // added: chainsaw shaking + CPlacement3D plWeapon; + if (m_iCurrentWeapon==WEAPON_CHAINSAW) { + CPlayer *plPlayer = (CPlayer*)&*m_penPlayer; + plWeapon = CPlacement3D ( FLOAT3D(wpn_fX[iWeaponData]+plPlayer->m_fChainsawShakeDX*0.35f, + wpn_fY[iWeaponData]+plPlayer->m_fChainsawShakeDY*0.35f, + wpn_fZ[iWeaponData]), + ANGLE3D(AngleDeg(wpn_fH[iWeaponData]), + AngleDeg(wpn_fP[iWeaponData]), + AngleDeg(wpn_fB[iWeaponData]))); + } else { + plWeapon = CPlacement3D ( FLOAT3D(wpn_fX[iWeaponData], + wpn_fY[iWeaponData], + wpn_fZ[iWeaponData]), + ANGLE3D(AngleDeg(wpn_fH[iWeaponData]), + AngleDeg(wpn_fP[iWeaponData]), + AngleDeg(wpn_fB[iWeaponData]))); + } + + // make sure that weapon will be bright enough + UBYTE ubLR,ubLG,ubLB, ubAR,ubAG,ubAB; + ColorToRGB( colViewerLight, ubLR,ubLG,ubLB); + ColorToRGB( colViewerAmbient, ubAR,ubAG,ubAB); + INDEX iMinDL = Min( Min(ubLR,ubLG),ubLB) -32; + INDEX iMinDA = Min( Min(ubAR,ubAG),ubAB) -32; + if( iMinDL<0) { + ubLR = ClampUp( ubLR-iMinDL, (INDEX)255); + ubLG = ClampUp( ubLG-iMinDL, (INDEX)255); + ubLB = ClampUp( ubLB-iMinDL, (INDEX)255); + } + if( iMinDA<0) { + ubAR = ClampUp( ubAR-iMinDA, (INDEX)255); + ubAG = ClampUp( ubAG-iMinDA, (INDEX)255); + ubAB = ClampUp( ubAB-iMinDA, (INDEX)255); + } + const COLOR colLight = RGBToColor( ubLR,ubLG,ubLB); + const COLOR colAmbient = RGBToColor( ubAR,ubAG,ubAB); + const FLOAT tmNow = _pTimer->GetLerpedCurrentTick(); + + UBYTE ubBlend = INVISIBILITY_ALPHA_LOCAL; + FLOAT tmInvisibility = ((CPlayer *)&*m_penPlayer)->m_tmInvisibility; + //FLOAT tmSeriousDamage = ((CPlayer *)&*m_penPlayer)->m_tmSeriousDamage; + //FLOAT tmInvulnerability = ((CPlayer *)&*m_penPlayer)->m_tmInvulnerability; + if (tmInvisibility>tmNow) { + FLOAT fIntensity=0.0f; + if((tmInvisibility-tmNow)<3.0f) + { + fIntensity = 0.5f-0.5f*cos((tmInvisibility-tmNow)*(6.0f*3.1415927f/3.0f)); + ubBlend =(INDEX)(INVISIBILITY_ALPHA_LOCAL+(FLOAT)(254-INVISIBILITY_ALPHA_LOCAL)*fIntensity); + } + } + + // DRAW WEAPON MODEL + // Double colt - second colt in mirror + // Double shotgun - hand with ammo + if( iWeaponData==WEAPON_DOUBLECOLT|| iWeaponData==WEAPON_DOUBLESHOTGUN ) + { + // prepare render model structure and projection + CRenderModel rmMain; + CPerspectiveProjection3D prMirror = prProjection; + prMirror.ViewerPlacementL() = plView; + prMirror.FrontClipDistanceL() = wpn_fClip[iWeaponData]; + prMirror.DepthBufferNearL() = 0.0f; + prMirror.DepthBufferFarL() = 0.1f; + CPlacement3D plWeaponMirror( FLOAT3D(wpn_fX[iWeaponData], wpn_fY[iWeaponData], wpn_fZ[iWeaponData]), + ANGLE3D(AngleDeg(wpn_fH[iWeaponData]), AngleDeg(wpn_fP[iWeaponData]), + AngleDeg(wpn_fB[iWeaponData]))); + if( iWeaponData==WEAPON_DOUBLECOLT /*|| iWeaponData==WEAPON_PIPEBOMB*/) { + FLOATmatrix3D mRotation; + MakeRotationMatrixFast(mRotation, plView.pl_OrientationAngle); + plWeaponMirror.pl_PositionVector(1) = -plWeaponMirror.pl_PositionVector(1); + plWeaponMirror.pl_OrientationAngle(1) = -plWeaponMirror.pl_OrientationAngle(1); + plWeaponMirror.pl_OrientationAngle(3) = -plWeaponMirror.pl_OrientationAngle(3); + } + ((CPerspectiveProjection3D &)prMirror).FOVL() = AngleDeg(wpn_fFOV[iWeaponData]); + CAnyProjection3D apr; + apr = prMirror; + Stereo_AdjustProjection(*apr, iEye, 0.1f); + BeginModelRenderingView(apr, pdp); + + WeaponMovingOffset(plWeaponMirror.pl_PositionVector); + plWeaponMirror.RelativeToAbsoluteSmooth(plView); + rmMain.SetObjectPlacement(plWeaponMirror); + + rmMain.rm_colLight = colLight; + rmMain.rm_colAmbient = colAmbient; + rmMain.rm_vLightDirection = vViewerLightDirection; + rmMain.rm_ulFlags |= RMF_WEAPON; // TEMP: for Truform + if (tmInvisibility>tmNow) { + rmMain.rm_colBlend = (rmMain.rm_colBlend&0xffffff00)|ubBlend; + } + + m_moWeaponSecond.SetupModelRendering(rmMain); + m_moWeaponSecond.RenderModel(rmMain); + EndModelRenderingView(); + } + + // minigun specific (update rotation) + if( iWeaponData==WEAPON_MINIGUN) { RotateMinigun(); } + + // prepare render model structure + CRenderModel rmMain; + prProjection.ViewerPlacementL() = plView; + prProjection.FrontClipDistanceL() = wpn_fClip[iWeaponData]; + prProjection.DepthBufferNearL() = 0.0f; + prProjection.DepthBufferFarL() = 0.1f; + ((CPerspectiveProjection3D &)prProjection).FOVL() = AngleDeg(wpn_fFOV[iWeaponData]); + + CAnyProjection3D apr; + apr = prProjection; + Stereo_AdjustProjection(*apr, iEye, 0.1f); + BeginModelRenderingView(apr, pdp); + + WeaponMovingOffset(plWeapon.pl_PositionVector); + plWeapon.RelativeToAbsoluteSmooth(plView); + rmMain.SetObjectPlacement(plWeapon); + + rmMain.rm_colLight = colLight; + rmMain.rm_colAmbient = colAmbient; + rmMain.rm_vLightDirection = vViewerLightDirection; + rmMain.rm_ulFlags |= RMF_WEAPON; // TEMP: for Truform + if (tmInvisibility>tmNow) { + rmMain.rm_colBlend = (rmMain.rm_colBlend&0xffffff00)|ubBlend; + } + + m_moWeapon.SetupModelRendering(rmMain); + m_moWeapon.RenderModel(rmMain); + + /*if (tmSeriousDamage>tmNow && tmInvulnerability>tmNow) { + Particle_PrepareSystem(pdp, apr); + Particle_PrepareEntity( 1, 0, 0, NULL); + Particles_ModelGlow2(&m_moWeapon, plWeapon, Max(tmSeriousDamage, tmInvulnerability),PT_STAR08, 0.025f, 2, 0.01f, 0xff00ff00); + Particle_EndSystem(); + } else if (tmInvulnerability>tmNow) { + Particle_PrepareSystem(pdp, apr); + Particle_PrepareEntity( 1, 0, 0, NULL); + Particles_ModelGlow2(&m_moWeapon, plWeapon, tmInvulnerability, PT_STAR05, 0.025f, tmp_ai[1], 0.01f, 0x3333ff00); + Particle_EndSystem(); + } else if (tmSeriousDamage>tmNow) { + Particle_PrepareSystem(pdp, apr); + Particle_PrepareEntity( 1, 0, 0, NULL); + Particles_ModelGlow2(&m_moWeapon, plWeapon, tmSeriousDamage, PT_STAR08, 0.025f, 2, 0.01f, 0xff777700); + Particle_EndSystem(); + }*/ + + EndModelRenderingView(); + + // restore FOV for Crosshair + ((CPerspectiveProjection3D &)prProjection).FOVL() = fFOV; + }; + + + // Weapon moving offset + void WeaponMovingOffset(FLOAT3D &plPos) + { + CPlayerAnimator &plan = (CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator; + FLOAT fXOffset = Lerp(plan.m_fMoveLastBanking, plan.m_fMoveBanking, _pTimer->GetLerpFactor()) * -0.02f; + FLOAT fYOffset = Lerp(plan.m_fWeaponYLastOffset, plan.m_fWeaponYOffset, _pTimer->GetLerpFactor()) * 0.15f; + fYOffset += (fXOffset * fXOffset) * 30.0f; + plPos(1) += fXOffset; + plPos(2) += fYOffset; + // apply grenade launcher pumping + if( m_iCurrentWeapon == WEAPON_GRENADELAUNCHER) + { + // obtain moving part attachment + CAttachmentModelObject *amo = m_moWeapon.GetAttachmentModel(GRENADELAUNCHER_ATTACHMENT_MOVING_PART); + FLOAT fLerpedMovement = Lerp(m_fWeaponDrawPowerOld, m_fWeaponDrawPower, _pTimer->GetLerpFactor()); + amo->amo_plRelative.pl_PositionVector(3) = fLerpedMovement; + plPos(3) += fLerpedMovement/2.0f; + if( m_tmDrawStartTime != 0.0f) + { + FLOAT tmPassed = _pTimer->GetLerpedCurrentTick()-m_tmDrawStartTime; + plPos(1) += Sin(tmPassed*360.0f*10)*0.0125f*tmPassed/6.0f; + plPos(2) += Sin(tmPassed*270.0f*8)*0.01f*tmPassed/6.0f; + } + } + // apply cannon draw + else if( (m_iCurrentWeapon == WEAPON_IRONCANNON) /*|| + (m_iCurrentWeapon == WEAPON_NUKECANNON) */) + { + FLOAT fLerpedMovement = Lerp(m_fWeaponDrawPowerOld, m_fWeaponDrawPower, _pTimer->GetLerpFactor()); + plPos(3) += fLerpedMovement; + if( m_tmDrawStartTime != 0.0f) + { + FLOAT tmPassed = _pTimer->GetLerpedCurrentTick()-m_tmDrawStartTime; + plPos(1) += Sin(tmPassed*360.0f*10)*0.0125f*tmPassed/2.0f; + plPos(2) += Sin(tmPassed*270.0f*8)*0.01f*tmPassed/2.0f; + } + } + }; + + // check target for time prediction updating + void CheckTargetPrediction(CEntity *penTarget) + { + // if target is not predictable + if (!penTarget->IsPredictable()) { + // do nothing + return; + } + + extern FLOAT cli_tmPredictFoe; + extern FLOAT cli_tmPredictAlly; + extern FLOAT cli_tmPredictEnemy; + + // get your and target's bases for prediction + CEntity *penMe = GetPlayer(); + if (IsPredictor()) { + penMe = penMe->GetPredicted(); + } + CEntity *penYou = penTarget; + if (penYou->IsPredictor()) { + penYou = penYou->GetPredicted(); + } + + // if player + if (IsOfClass(penYou, "Player")) { + // if ally player + if (GetSP()->sp_bCooperative) { + // if ally prediction is on and this player is local + if (cli_tmPredictAlly>0 && _pNetwork->IsPlayerLocal(penMe)) { + // predict the ally + penYou->SetPredictionTime(cli_tmPredictAlly); + } + // if foe player + } else { + // if foe prediction is on + if (cli_tmPredictFoe>0) { + // if this player is local + if (_pNetwork->IsPlayerLocal(penMe)) { + // predict the foe + penYou->SetPredictionTime(cli_tmPredictFoe); + } + // if the target is local + if (_pNetwork->IsPlayerLocal(penYou)) { + // predict self + penMe->SetPredictionTime(cli_tmPredictFoe); + } + } + } + } else { + // if enemy prediction is on an it is an enemy + if( cli_tmPredictEnemy>0 && IsDerivedFromClass( penYou, "Enemy Base")) { + // if this player is local + if (_pNetwork->IsPlayerLocal(penMe)) { + // set enemy prediction time + penYou->SetPredictionTime(cli_tmPredictEnemy); + } + } + } + } + + // cast a ray from weapon + void UpdateTargetingInfo(void) + { + // crosshair start position from weapon + CPlacement3D plCrosshair; + FLOAT fFX = wpn_fFX[m_iCurrentWeapon]; // get weapon firing position + FLOAT fFY = wpn_fFY[m_iCurrentWeapon]; + if (GetPlayer()->m_iViewState == PVT_3RDPERSONVIEW) { + fFX = fFY = 0; + } + CalcWeaponPosition(FLOAT3D(fFX, fFY, 0), plCrosshair, FALSE); + // cast ray + CCastRay crRay( m_penPlayer, plCrosshair); + crRay.cr_bHitTranslucentPortals = FALSE; + crRay.cr_bPhysical = FALSE; + crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX; + GetWorld()->CastRay(crRay); + // store required cast ray results + m_vRayHitLast = m_vRayHit; // for lerping purposes + m_vRayHit = crRay.cr_vHit; + m_penRayHit = crRay.cr_penHit; + m_fRayHitDistance = crRay.cr_fHitDistance; + m_fEnemyHealth = 0.0f; + + // set some targeting properties (snooping and such...) + TIME tmNow = _pTimer->CurrentTick(); + if( m_penRayHit!=NULL) + { + CEntity *pen = m_penRayHit; + // if alive + if( pen->GetFlags()&ENF_ALIVE) + { + // check the target for time prediction updating + CheckTargetPrediction(pen); + + // if player + if( IsOfClass( pen, "Player")) { + // rememer when targeting begun + if( m_tmTargetingStarted==0) { + m_penTargeting = pen; + m_tmTargetingStarted = tmNow; + } + // keep player name, mana and health for eventual printout or coloring + m_fEnemyHealth = ((CPlayer*)pen)->GetHealth() / ((CPlayer*)pen)->m_fMaxHealth; + m_strLastTarget.PrintF( "%s", ((CPlayer*)pen)->GetPlayerName()); + if( GetSP()->sp_gmGameMode==CSessionProperties::GM_SCOREMATCH) { + // add mana to player name + CTString strMana=""; + strMana.PrintF( " (%d)", ((CPlayer*)pen)->m_iMana); + m_strLastTarget += strMana; + } + if( hud_bShowPlayerName) { m_tmLastTarget = tmNow+1.5f; } + } + // not targeting player + else { + // reset targeting + m_tmTargetingStarted = 0; + } + // keep enemy health for eventual crosshair coloring + if( IsDerivedFromClass( pen, "Enemy Base")) { + m_fEnemyHealth = ((CEnemyBase*)pen)->GetHealth() / ((CEnemyBase*)pen)->m_fMaxHealth; + } + // cannot snoop while firing + if( m_bFireWeapon) { m_tmTargetingStarted = 0; } + } + // if not alive + else + { + // not targeting player + m_tmTargetingStarted = 0; + + // check switch relaying by moving brush + if( IsOfClass( pen, "Moving Brush") && ((CMovingBrush&)*pen).m_penSwitch!=NULL) { + pen = ((CMovingBrush&)*pen).m_penSwitch; + } + // if switch and near enough + if( IsOfClass( pen, "Switch") && m_fRayHitDistance<2.0f) { + CSwitch &enSwitch = (CSwitch&)*pen; + // if switch is useable + if( enSwitch.m_bUseable) { + // show switch message + if( enSwitch.m_strMessage!="") { m_strLastTarget = enSwitch.m_strMessage; } + else { m_strLastTarget = TRANS("Use"); } + m_tmLastTarget = tmNow+0.5f; + } + } + // if analyzable + if( IsOfClass( pen, "MessageHolder") + && m_fRayHitDistance < ((CMessageHolder*)&*pen)->m_fDistance + && ((CMessageHolder*)&*pen)->m_bActive) { + const CTFileName &fnmMessage = ((CMessageHolder*)&*pen)->m_fnmMessage; + // if player doesn't have that message it database + CPlayer &pl = (CPlayer&)*m_penPlayer; + if( !pl.HasMessage(fnmMessage)) { + // show analyse message + m_strLastTarget = TRANS("Analyze"); + m_tmLastTarget = tmNow+0.5f; + } + } + } + } + // if didn't hit anything + else { + // not targeting player + m_tmTargetingStarted = 0; + // remember position ahead + FLOAT3D vDir = crRay.cr_vTarget-crRay.cr_vOrigin; + vDir.Normalize(); + m_vRayHit = crRay.cr_vOrigin+vDir*50.0f; + } + + // determine snooping time + TIME tmDelta = tmNow - m_tmTargetingStarted; + if( m_tmTargetingStarted>0 && plr_tmSnoopingDelay>0 && tmDelta>plr_tmSnoopingDelay) { + m_tmSnoopingStarted = tmNow; + } + } + + + + // Render Crosshair + void RenderCrosshair( CProjection3D &prProjection, CDrawPort *pdp, CPlacement3D &plViewSource) + { + INDEX iCrossHair = GetPlayer()->GetSettings()->ps_iCrossHairType+1; + + // adjust crosshair type + if( iCrossHair<=0) { + iCrossHair = 0; + _iLastCrosshairType = 0; + } + + // create new crosshair texture (if needed) + if( _iLastCrosshairType != iCrossHair) { + _iLastCrosshairType = iCrossHair; + CTString fnCrosshair; + fnCrosshair.PrintF( "Textures\\Interface\\Crosshairs\\Crosshair%d.tex", iCrossHair); + try { + // load new crosshair texture + _toCrosshair.SetData_t( fnCrosshair); + } catch( char *strError) { + // didn't make it! - reset crosshair + CPrintF( strError); + iCrossHair = 0; + return; + } + } + COLOR colCrosshair = C_WHITE; + TIME tmNow = _pTimer->CurrentTick(); + + // if hit anything + FLOAT3D vOnScreen; + FLOAT fDistance = m_fRayHitDistance; + //const FLOAT3D vRayHit = Lerp( m_vRayHitLast, m_vRayHit, _pTimer->GetLerpFactor()); + const FLOAT3D vRayHit = m_vRayHit; // lerping doesn't seem to work ??? + // if hit anything + if( m_penRayHit!=NULL) { + + CEntity *pen = m_penRayHit; + // do screen projection + prProjection.ViewerPlacementL() = plViewSource; + prProjection.ObjectPlacementL() = CPlacement3D( FLOAT3D(0.0f, 0.0f, 0.0f), ANGLE3D( 0, 0, 0)); + prProjection.Prepare(); + prProjection.ProjectCoordinate( vRayHit, vOnScreen); + // if required, show enemy health thru crosshair color + if( hud_bCrosshairColoring && m_fEnemyHealth>0) { + if( m_fEnemyHealth<0.25f) { colCrosshair = C_RED; } + else if( m_fEnemyHealth<0.60f) { colCrosshair = C_YELLOW; } + else { colCrosshair = C_GREEN; } + } + } + // if didn't hit anything + else + { + // far away in screen center + vOnScreen(1) = (FLOAT)pdp->GetWidth() *0.5f; + vOnScreen(2) = (FLOAT)pdp->GetHeight() *0.5f; + fDistance = 100.0f; + } + + // if croshair should be of fixed position + if( hud_bCrosshairFixed || GetPlayer()->m_iViewState == PVT_3RDPERSONVIEW) { + // reset it to screen center + vOnScreen(1) = (FLOAT)pdp->GetWidth() *0.5f; + vOnScreen(2) = (FLOAT)pdp->GetHeight() *0.5f; + //fDistance = 100.0f; + } + + // clamp console variables + hud_fCrosshairScale = Clamp( hud_fCrosshairScale, 0.1f, 2.0f); + hud_fCrosshairRatio = Clamp( hud_fCrosshairRatio, 0.1f, 1.0f); + hud_fCrosshairOpacity = Clamp( hud_fCrosshairOpacity, 0.1f, 1.0f); + const ULONG ulAlpha = NormFloatToByte( hud_fCrosshairOpacity); + // draw crosshair if needed + if( iCrossHair>0) { + // determine crosshair size + const FLOAT fMinD = 1.0f; + const FLOAT fMaxD = 100.0f; + fDistance = Clamp( fDistance, fMinD, fMaxD); + const FLOAT fRatio = (fDistance-fMinD) / (fMaxD-fMinD); + const FLOAT fMaxSize = (FLOAT)pdp->GetWidth() / 640.0f; + const FLOAT fMinSize = fMaxSize * hud_fCrosshairRatio; + const FLOAT fSize = 16 * Lerp( fMaxSize, fMinSize, fRatio) * hud_fCrosshairScale; + // draw crosshair + const FLOAT fI0 = + (PIX)vOnScreen(1) - fSize; + const FLOAT fI1 = + (PIX)vOnScreen(1) + fSize; + const FLOAT fJ0 = - (PIX)vOnScreen(2) - fSize +pdp->GetHeight(); + const FLOAT fJ1 = - (PIX)vOnScreen(2) + fSize +pdp->GetHeight(); + pdp->InitTexture( &_toCrosshair); + pdp->AddTexture( fI0, fJ0, fI1, fJ1, colCrosshair|ulAlpha); + pdp->FlushRenderingQueue(); + } + + // if there is still time + TIME tmDelta = m_tmLastTarget - tmNow; + if( tmDelta>0) { + // printout current target info + SLONG slDPWidth = pdp->GetWidth(); + SLONG slDPHeight = pdp->GetHeight(); + FLOAT fScaling = (FLOAT)slDPWidth/640.0f; + // set font and scale + pdp->SetFont( _pfdDisplayFont); + pdp->SetTextScaling( fScaling); + pdp->SetTextAspect( 1.0f); + // do faded printout + ULONG ulA = (FLOAT)ulAlpha * Clamp( 2*tmDelta, 0.0f, 1.0f); + pdp->PutTextC( m_strLastTarget, slDPWidth*0.5f, slDPHeight*0.75f, SE_COL_BLUE_NEUTRAL|ulA); + } + + // printout crosshair world coordinates if needed + if( hud_bShowCoords) { + CTString strCoords; + SLONG slDPWidth = pdp->GetWidth(); + SLONG slDPHeight = pdp->GetHeight(); + // set font and scale + pdp->SetFont( _pfdDisplayFont); + pdp->SetTextAspect( 1.0f); + pdp->SetTextScaling( (FLOAT)slDPWidth/640.0f); + // do printout only if coordinates are valid + const FLOAT fMax = Max( Max( vRayHit(1), vRayHit(2)), vRayHit(3)); + const FLOAT fMin = Min( Min( vRayHit(1), vRayHit(2)), vRayHit(3)); + if( fMax<+100000 && fMin>-100000) { + strCoords.PrintF( "%.0f,%.0f,%.0f", vRayHit(1), vRayHit(2), vRayHit(3)); + pdp->PutTextC( strCoords, slDPWidth*0.5f, slDPHeight*0.10f, C_WHITE|CT_OPAQUE); + } + } + }; + + + +/************************************************************ + * FIRE FLARE * + ************************************************************/ + // show flare + void ShowFlare(CModelObject &moWeapon, INDEX iAttachObject, INDEX iAttachFlare, FLOAT fSize) { + CModelObject *pmo = &(moWeapon.GetAttachmentModel(iAttachObject)->amo_moModelObject); + CAttachmentModelObject *pamo = pmo->GetAttachmentModel(iAttachFlare); + pamo->amo_plRelative.pl_OrientationAngle(3) = (rand()*360.0f)/RAND_MAX; + pmo = &(pamo->amo_moModelObject); + pmo->StretchModel(FLOAT3D(fSize, fSize, fSize)); + }; + + + // hide flare + void HideFlare(CModelObject &moWeapon, INDEX iAttachObject, INDEX iAttachFlare) { + CModelObject *pmo = &(moWeapon.GetAttachmentModel(iAttachObject)->amo_moModelObject); + pmo = &(pmo->GetAttachmentModel(iAttachFlare)->amo_moModelObject); + pmo->StretchModel(FLOAT3D(0, 0, 0)); + }; + + void SetFlare(INDEX iFlare, INDEX iAction) + { + // if not a prediction head + if (!IsPredictionHead()) { + // do nothing + return; + } + + // get your prediction tail + CPlayerWeapons *pen = (CPlayerWeapons*)GetPredictionTail(); + if (iFlare==0) { + pen->m_iFlare = iAction; + pen->GetPlayer()->GetPlayerAnimator()->m_iFlare = iAction; + } else { + pen->m_iSecondFlare = iAction; + pen->GetPlayer()->GetPlayerAnimator()->m_iSecondFlare = iAction; + } + } + + // flare attachment + void ControlFlareAttachment(void) { + // if not a prediction head +/* if (!IsPredictionHead()) { + // do nothing + return; + } + */ + + // get your prediction tail + CPlayerWeapons *pen = (CPlayerWeapons *)GetPredictionTail(); + // second colt only + if (m_iCurrentWeapon==WEAPON_DOUBLECOLT) { + // add flare + if (pen->m_iSecondFlare==FLARE_ADD) { + pen->m_iSecondFlare = FLARE_REMOVE; + ShowFlare(m_moWeaponSecond, COLT_ATTACHMENT_COLT, COLTMAIN_ATTACHMENT_FLARE, 1.0f); + // remove flare + } else if (pen->m_iSecondFlare==FLARE_REMOVE) { + HideFlare(m_moWeaponSecond, COLT_ATTACHMENT_COLT, COLTMAIN_ATTACHMENT_FLARE); + } + } + + // add flare + if (pen->m_iFlare==FLARE_ADD) { + pen->m_iFlare = FLARE_REMOVE; + switch(m_iCurrentWeapon) { + case WEAPON_DOUBLECOLT: case WEAPON_COLT: + ShowFlare(m_moWeapon, COLT_ATTACHMENT_COLT, COLTMAIN_ATTACHMENT_FLARE, 0.75f); + break; + case WEAPON_SINGLESHOTGUN: + ShowFlare(m_moWeapon, SINGLESHOTGUN_ATTACHMENT_BARRELS, BARRELS_ATTACHMENT_FLARE, 1.0f); + break; + case WEAPON_DOUBLESHOTGUN: + ShowFlare(m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_BARRELS, DSHOTGUNBARRELS_ATTACHMENT_FLARE, 1.75f); + break; + case WEAPON_TOMMYGUN: + ShowFlare(m_moWeapon, TOMMYGUN_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE, 0.5f); + break; + case WEAPON_SNIPER: + ShowFlare(m_moWeapon, SNIPER_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE, 0.5f); + break; + case WEAPON_MINIGUN: + ShowFlare(m_moWeapon, MINIGUN_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE, 1.25f); + break; + } + // remove + } else if (pen->m_iFlare==FLARE_REMOVE) { + switch(m_iCurrentWeapon) { + case WEAPON_DOUBLECOLT: case WEAPON_COLT: + HideFlare(m_moWeapon, COLT_ATTACHMENT_COLT, COLTMAIN_ATTACHMENT_FLARE); + break; + case WEAPON_SINGLESHOTGUN: + HideFlare(m_moWeapon, SINGLESHOTGUN_ATTACHMENT_BARRELS, BARRELS_ATTACHMENT_FLARE); + break; + case WEAPON_DOUBLESHOTGUN: + HideFlare(m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_BARRELS, DSHOTGUNBARRELS_ATTACHMENT_FLARE); + break; + case WEAPON_TOMMYGUN: + HideFlare(m_moWeapon, TOMMYGUN_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE); + break; + case WEAPON_SNIPER: + HideFlare(m_moWeapon, SNIPER_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE); + break; + case WEAPON_MINIGUN: + HideFlare(m_moWeapon, MINIGUN_ATTACHMENT_BODY, BODY_ATTACHMENT_FLARE); + break; + } + } else { + ASSERT(FALSE); + } + }; + + + // play light animation + void PlayLightAnim(INDEX iAnim, ULONG ulFlags) { + CPlayer &pl = (CPlayer&)*m_penPlayer; + if (pl.m_aoLightAnimation.GetData()!=NULL) { + pl.m_aoLightAnimation.PlayAnim(iAnim, ulFlags); + } + }; + + + // Set weapon model for current weapon. + void SetCurrentWeaponModel(void) { + // WARNING !!! ---> Order of attachment must be the same with order in RenderWeaponModel() + switch (m_iCurrentWeapon) { + case WEAPON_NONE: + break; + // knife + case WEAPON_KNIFE: + SetComponents(this, m_moWeapon, MODEL_KNIFE, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, KNIFE_ATTACHMENT_KNIFEITEM, MODEL_KNIFEITEM, + TEXTURE_KNIFEITEM, TEX_REFL_BWRIPLES02, TEX_SPEC_WEAK, 0); + m_moWeapon.PlayAnim(KNIFE_ANIM_WAIT1, 0); + break; + // colt + case WEAPON_DOUBLECOLT: { + SetComponents(this, m_moWeaponSecond, MODEL_COLT, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeaponSecond, COLT_ATTACHMENT_BULLETS, MODEL_COLTBULLETS, TEXTURE_COLTBULLETS, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeaponSecond, COLT_ATTACHMENT_COCK, MODEL_COLTCOCK, TEXTURE_COLTCOCK, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeaponSecond, COLT_ATTACHMENT_COLT, MODEL_COLTMAIN, TEXTURE_COLTMAIN, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + CModelObject &mo = m_moWeaponSecond.GetAttachmentModel(COLT_ATTACHMENT_COLT)->amo_moModelObject; + AddAttachmentToModel(this, mo, COLTMAIN_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0); } + m_moWeaponSecond.StretchModel(FLOAT3D(-1,1,1)); + m_moWeaponSecond.PlayAnim(COLT_ANIM_WAIT1, 0); + case WEAPON_COLT: { + SetComponents(this, m_moWeapon, MODEL_COLT, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, COLT_ATTACHMENT_BULLETS, MODEL_COLTBULLETS, TEXTURE_COLTBULLETS, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, COLT_ATTACHMENT_COCK, MODEL_COLTCOCK, TEXTURE_COLTCOCK, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, COLT_ATTACHMENT_COLT, MODEL_COLTMAIN, TEXTURE_COLTMAIN, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + CModelObject &mo = m_moWeapon.GetAttachmentModel(COLT_ATTACHMENT_COLT)->amo_moModelObject; + AddAttachmentToModel(this, mo, COLTMAIN_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0); + m_moWeapon.PlayAnim(COLT_ANIM_WAIT1, 0); + break; } + case WEAPON_SINGLESHOTGUN: { + SetComponents(this, m_moWeapon, MODEL_SINGLESHOTGUN, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, SINGLESHOTGUN_ATTACHMENT_BARRELS, MODEL_SS_BARRELS, TEXTURE_SS_BARRELS, TEX_REFL_DARKMETAL, TEX_SPEC_WEAK, 0); + AddAttachmentToModel(this, m_moWeapon, SINGLESHOTGUN_ATTACHMENT_HANDLE, MODEL_SS_HANDLE, TEXTURE_SS_HANDLE, TEX_REFL_DARKMETAL, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, SINGLESHOTGUN_ATTACHMENT_SLIDER, MODEL_SS_SLIDER, TEXTURE_SS_BARRELS, TEX_REFL_DARKMETAL, TEX_SPEC_MEDIUM, 0); + CModelObject &mo = m_moWeapon.GetAttachmentModel(SINGLESHOTGUN_ATTACHMENT_BARRELS)->amo_moModelObject; + AddAttachmentToModel(this, mo, BARRELS_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0); + m_moWeapon.PlayAnim(SINGLESHOTGUN_ANIM_WAIT1, 0); + break; } + case WEAPON_DOUBLESHOTGUN: { + SetComponents(this, m_moWeapon, MODEL_DOUBLESHOTGUN, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_BARRELS, MODEL_DS_BARRELS, TEXTURE_DS_BARRELS, TEX_REFL_BWRIPLES01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_HANDLE, MODEL_DS_HANDLE, TEXTURE_DS_HANDLE, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_SWITCH, MODEL_DS_SWITCH, TEXTURE_DS_SWITCH, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, DOUBLESHOTGUN_ATTACHMENT_AMMO, MODEL_DS_AMMO, TEXTURE_DS_AMMO, 0 ,0, 0); + SetComponents(this, m_moWeaponSecond, MODEL_DS_HANDWITHAMMO, TEXTURE_HAND, 0, 0, 0); + CModelObject &mo = m_moWeapon.GetAttachmentModel(DOUBLESHOTGUN_ATTACHMENT_BARRELS)->amo_moModelObject; + AddAttachmentToModel(this, mo, DSHOTGUNBARRELS_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0); + m_moWeaponSecond.StretchModel(FLOAT3D(1,1,1)); + m_moWeapon.PlayAnim(DOUBLESHOTGUN_ANIM_WAIT1, 0); + break; } + case WEAPON_TOMMYGUN: { + SetComponents(this, m_moWeapon, MODEL_TOMMYGUN, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, TOMMYGUN_ATTACHMENT_BODY, MODEL_TG_BODY, TEXTURE_TG_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, TOMMYGUN_ATTACHMENT_SLIDER, MODEL_TG_SLIDER, TEXTURE_TG_BODY, 0, TEX_SPEC_MEDIUM, 0); + CModelObject &mo = m_moWeapon.GetAttachmentModel(TOMMYGUN_ATTACHMENT_BODY)->amo_moModelObject; + AddAttachmentToModel(this, mo, BODY_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0); + break; } + case WEAPON_SNIPER: { + SetComponents(this, m_moWeapon, MODEL_SNIPER, TEXTURE_SNIPER_BODY, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, SNIPER_ATTACHMENT_BODY, MODEL_SNIPER_BODY, TEXTURE_SNIPER_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + CModelObject &mo = m_moWeapon.GetAttachmentModel(SNIPER_ATTACHMENT_BODY)->amo_moModelObject; + AddAttachmentToModel(this, mo, BODY_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0); + break; } + case WEAPON_MINIGUN: { + SetComponents(this, m_moWeapon, MODEL_MINIGUN, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, MINIGUN_ATTACHMENT_BARRELS, MODEL_MG_BARRELS, TEXTURE_MG_BARRELS, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, MINIGUN_ATTACHMENT_BODY, MODEL_MG_BODY, TEXTURE_MG_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, MINIGUN_ATTACHMENT_ENGINE, MODEL_MG_ENGINE, TEXTURE_MG_BARRELS, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + CModelObject &mo = m_moWeapon.GetAttachmentModel(MINIGUN_ATTACHMENT_BODY)->amo_moModelObject; + AddAttachmentToModel(this, mo, BODY_ATTACHMENT_FLARE, MODEL_FLARE01, TEXTURE_FLARE01, 0, 0, 0); + break; } + case WEAPON_ROCKETLAUNCHER: + SetComponents(this, m_moWeapon, MODEL_ROCKETLAUNCHER, TEXTURE_RL_BODY, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, ROCKETLAUNCHER_ATTACHMENT_BODY, MODEL_RL_BODY, TEXTURE_RL_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, ROCKETLAUNCHER_ATTACHMENT_ROTATINGPART, MODEL_RL_ROTATINGPART, TEXTURE_RL_ROTATINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, ROCKETLAUNCHER_ATTACHMENT_ROCKET1, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, ROCKETLAUNCHER_ATTACHMENT_ROCKET2, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, ROCKETLAUNCHER_ATTACHMENT_ROCKET3, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + break; + case WEAPON_GRENADELAUNCHER: + SetComponents(this, m_moWeapon, MODEL_GRENADELAUNCHER, TEXTURE_GL_BODY, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, GRENADELAUNCHER_ATTACHMENT_BODY, MODEL_GL_BODY, TEXTURE_GL_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, GRENADELAUNCHER_ATTACHMENT_MOVING_PART, MODEL_GL_MOVINGPART, TEXTURE_GL_MOVINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, GRENADELAUNCHER_ATTACHMENT_GRENADE, MODEL_GL_GRENADE, TEXTURE_GL_MOVINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + break; + /* + case WEAPON_PIPEBOMB: + SetComponents(this, m_moWeapon, MODEL_PIPEBOMB_HAND, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, HANDWITHBOMB_ATTACHMENT_BOMB, MODEL_PB_BOMB, TEXTURE_PB_BOMB, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + SetComponents(this, m_moWeaponSecond, MODEL_PIPEBOMB_STICK, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeaponSecond, HANDWITHSTICK_ATTACHMENT_STICK, MODEL_PB_STICK, TEXTURE_PB_STICK, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeaponSecond, HANDWITHSTICK_ATTACHMENT_SHIELD, MODEL_PB_SHIELD, TEXTURE_PB_STICK, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeaponSecond, HANDWITHSTICK_ATTACHMENT_BUTTON, MODEL_PB_BUTTON, TEXTURE_PB_STICK, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + m_moWeaponSecond.StretchModel(FLOAT3D(1,1,1)); + break; + */ + case WEAPON_FLAMER: + SetComponents(this, m_moWeapon, MODEL_FLAMER, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, FLAMER_ATTACHMENT_BODY, MODEL_FL_BODY, TEXTURE_FL_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, FLAMER_ATTACHMENT_FUEL, MODEL_FL_RESERVOIR, TEXTURE_FL_FUELRESERVOIR, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, FLAMER_ATTACHMENT_FLAME, MODEL_FL_FLAME, TEXTURE_FL_FLAME, 0, 0, 0); + break; + case WEAPON_CHAINSAW: { + SetComponents(this, m_moWeapon, MODEL_CHAINSAW, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, CHAINSAW_ATTACHMENT_CHAINSAW, MODEL_CS_BODY, TEXTURE_CS_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, CHAINSAW_ATTACHMENT_BLADE, MODEL_CS_BLADE, TEXTURE_CS_BLADE, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + CModelObject *pmo; + pmo = &(m_moWeapon.GetAttachmentModel(CHAINSAW_ATTACHMENT_BLADE)->amo_moModelObject); + AddAttachmentToModel(this, *pmo, BLADE_ATTACHMENT_TEETH, MODEL_CS_TEETH, TEXTURE_CS_TEETH, 0, 0, 0); + break; } + case WEAPON_LASER: + SetComponents(this, m_moWeapon, MODEL_LASER, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, LASER_ATTACHMENT_BODY, MODEL_LS_BODY, TEXTURE_LS_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, LASER_ATTACHMENT_LEFTUP, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, LASER_ATTACHMENT_LEFTDOWN, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, LASER_ATTACHMENT_RIGHTUP, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, LASER_ATTACHMENT_RIGHTDOWN, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + break; +/* + case WEAPON_GHOSTBUSTER: + SetComponents(this, m_moWeapon, MODEL_GHOSTBUSTER, TEXTURE_HAND, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_BODY, MODEL_GB_BODY, TEXTURE_GB_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_ROTATOR, MODEL_GB_ROTATOR, TEXTURE_GB_ROTATOR, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_EFFECT01, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_EFFECT02, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_EFFECT03, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, GHOSTBUSTER_ATTACHMENT_EFFECT04, MODEL_GB_EFFECT1, TEXTURE_GB_LIGHTNING, 0, 0, 0); + CModelObject *pmo; + pmo = &(m_moWeapon.GetAttachmentModel(GHOSTBUSTER_ATTACHMENT_EFFECT01)->amo_moModelObject); + AddAttachmentToModel(this, *pmo, EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0); + pmo = &(m_moWeapon.GetAttachmentModel(GHOSTBUSTER_ATTACHMENT_EFFECT02)->amo_moModelObject); + AddAttachmentToModel(this, *pmo, EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0); + pmo = &(m_moWeapon.GetAttachmentModel(GHOSTBUSTER_ATTACHMENT_EFFECT03)->amo_moModelObject); + AddAttachmentToModel(this, *pmo, EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0); + pmo = &(m_moWeapon.GetAttachmentModel(GHOSTBUSTER_ATTACHMENT_EFFECT04)->amo_moModelObject); + AddAttachmentToModel(this, *pmo, EFFECT01_ATTACHMENT_FLARE, MODEL_GB_EFFECT1FLARE, TEXTURE_GB_FLARE, 0, 0, 0); + break; + */ + case WEAPON_IRONCANNON: +// case WEAPON_NUKECANNON: + SetComponents(this, m_moWeapon, MODEL_CANNON, TEXTURE_CANNON, 0, 0, 0); + AddAttachmentToModel(this, m_moWeapon, CANNON_ATTACHMENT_BODY, MODEL_CN_BODY, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); +// AddAttachmentToModel(this, m_moWeapon, CANNON_ATTACHMENT_NUKEBOX, MODEL_CN_NUKEBOX, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); +// AddAttachmentToModel(this, m_moWeapon, CANNON_ATTACHMENT_LIGHT, MODEL_CN_LIGHT, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + break; + } + }; + + + + /* + * >>>--- ROTATE MINIGUN ---<<< + */ + void RotateMinigun(void) { + ANGLE aAngle = Lerp(m_aMiniGunLast, m_aMiniGun, _pTimer->GetLerpFactor()); + // rotate minigun barrels + CAttachmentModelObject *amo = m_moWeapon.GetAttachmentModel(MINIGUN_ATTACHMENT_BARRELS); + amo->amo_plRelative.pl_OrientationAngle(3) = aAngle; + }; + + + + /* + * >>>--- SUPPORT (COMMON) FUNCTIONS ---<<< + */ + + // calc weapon position for 3rd person view + void CalcWeaponPosition3rdPersonView(FLOAT3D vPos, CPlacement3D &plPos, BOOL bResetZ) { + plPos.pl_OrientationAngle = ANGLE3D(0, 0, 0); + // weapon handle + if (!m_bMirrorFire) { + plPos.pl_PositionVector = FLOAT3D( wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon], + wpn_fZ[m_iCurrentWeapon]); + } else { + plPos.pl_PositionVector = FLOAT3D( -wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon], + wpn_fZ[m_iCurrentWeapon]); + } + // weapon offset + if (!m_bMirrorFire) { + plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0))); + } else { + plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0))); + } + plPos.pl_PositionVector(1) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + plPos.pl_PositionVector(2) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + plPos.pl_PositionVector(3) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + + if (bResetZ) { + plPos.pl_PositionVector(3) = 0.0f; + } + + // player view and absolute position + CPlacement3D plView = ((CPlayer &)*m_penPlayer).en_plViewpoint; + plView.pl_PositionVector(2)= 1.25118f; + plPos.RelativeToAbsoluteSmooth(plView); + plPos.RelativeToAbsoluteSmooth(m_penPlayer->GetPlacement()); + }; + + // calc weapon position + void CalcWeaponPosition(FLOAT3D vPos, CPlacement3D &plPos, BOOL bResetZ) { + plPos.pl_OrientationAngle = ANGLE3D(0, 0, 0); + // weapon handle + if (!m_bMirrorFire) { + plPos.pl_PositionVector = FLOAT3D( wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon], + wpn_fZ[m_iCurrentWeapon]); + if (m_bSniping) { + plPos.pl_PositionVector = FLOAT3D( 0.0f, 0.0f, 0.0f ); + } + } else { + plPos.pl_PositionVector = FLOAT3D( -wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon], + wpn_fZ[m_iCurrentWeapon]); + } + // weapon offset + if (!m_bMirrorFire) { + plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0))); + } else { + plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0))); + } + plPos.pl_PositionVector(1) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + plPos.pl_PositionVector(2) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + plPos.pl_PositionVector(3) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + + if (bResetZ) { + plPos.pl_PositionVector(3) = 0.0f; + } + + // player view and absolute position + CPlacement3D plView = ((CPlayer &)*m_penPlayer).en_plViewpoint; + plView.pl_PositionVector(2)+= ((CPlayerAnimator&)*((CPlayer &)*m_penPlayer).m_penAnimator). + m_fEyesYOffset; + plPos.RelativeToAbsoluteSmooth(plView); + plPos.RelativeToAbsoluteSmooth(m_penPlayer->GetPlacement()); + }; + + // calc lerped weapon position + void CalcLerpedWeaponPosition(FLOAT3D vPos, CPlacement3D &plPos, BOOL bResetZ) + { + plPos.pl_OrientationAngle = ANGLE3D(0, 0, 0); + // weapon handle + if (!m_bMirrorFire) { + plPos.pl_PositionVector = FLOAT3D( wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon], + wpn_fZ[m_iCurrentWeapon]); + if (m_bSniping) { + plPos.pl_PositionVector = FLOAT3D( 0.0f, 0.0f, 0.0f ); + } + } else { + plPos.pl_PositionVector = FLOAT3D( -wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon], + wpn_fZ[m_iCurrentWeapon]); + } + // weapon offset + if (!m_bMirrorFire) { + plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0))); + } else { + plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0))); + } + plPos.pl_PositionVector(1) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + plPos.pl_PositionVector(2) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + plPos.pl_PositionVector(3) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + + if (bResetZ) { + plPos.pl_PositionVector(3) = 0.0f; + } + + // player view and absolute position + CPlacement3D plRes; + GetPlayer()->GetLerpedWeaponPosition( plPos.pl_PositionVector, plRes); + plPos=plRes; + }; + + // calc weapon position + void CalcWeaponPositionImprecise (FLOAT3D vPos, CPlacement3D &plPos, BOOL bResetZ, FLOAT fImprecissionAngle) { + plPos.pl_OrientationAngle = ANGLE3D((FRnd()-0.5f)*fImprecissionAngle, (FRnd()-0.5f)*fImprecissionAngle, 0); + // weapon handle + if (!m_bMirrorFire) { + plPos.pl_PositionVector = FLOAT3D( wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon], + wpn_fZ[m_iCurrentWeapon]); + if (m_bSniping) { + plPos.pl_PositionVector = FLOAT3D( 0.0f, 0.0f, 0.0f ); + } + } else { + plPos.pl_PositionVector = FLOAT3D( -wpn_fX[m_iCurrentWeapon], wpn_fY[m_iCurrentWeapon], + wpn_fZ[m_iCurrentWeapon]); + } + // weapon offset + if (!m_bMirrorFire) { + plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0))); + } else { + plPos.RelativeToAbsoluteSmooth(CPlacement3D(vPos, ANGLE3D(0, 0, 0))); + } + plPos.pl_PositionVector(1) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + plPos.pl_PositionVector(2) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + plPos.pl_PositionVector(3) *= SinFast(wpn_fFOV[m_iCurrentWeapon]/2) / SinFast(90.0f/2); + + if (bResetZ) { + plPos.pl_PositionVector(3) = 0.0f; + } + + // player view and absolute position + CPlacement3D plView = ((CPlayer &)*m_penPlayer).en_plViewpoint; + plView.pl_PositionVector(2)+= ((CPlayerAnimator&)*((CPlayer &)*m_penPlayer).m_penAnimator). + m_fEyesYOffset; + plPos.RelativeToAbsoluteSmooth(plView); + plPos.RelativeToAbsoluteSmooth(m_penPlayer->GetPlacement()); + }; + + // setup 3D sound parameters + void Setup3DSoundParameters(void) { + CPlayer &pl = (CPlayer&)*m_penPlayer; + + // initialize sound 3D parameters + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f); + pl.m_soWeapon1.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f); + pl.m_soWeapon2.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f); + pl.m_soWeapon3.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f); + pl.m_soWeaponAmbient.Set3DParameters(30.0f, 3.0f, 0.0f, 1.0f); + }; + + + /* + * >>>--- FIRE FUNCTIONS ---<<< + */ + + // cut in front of you with knife + BOOL CutWithKnife(FLOAT fX, FLOAT fY, FLOAT fRange, FLOAT fWide, FLOAT fThickness, FLOAT fDamage) + { + // knife start position + CPlacement3D plKnife; + CalcWeaponPosition(FLOAT3D(fX, fY, 0), plKnife, TRUE); + + // create a set of rays to test + const FLOAT3D &vBase = plKnife.pl_PositionVector; + FLOATmatrix3D m; + MakeRotationMatrixFast(m, plKnife.pl_OrientationAngle); + FLOAT3D vRight = m.GetColumn(1)*fWide; + FLOAT3D vUp = m.GetColumn(2)*fWide; + FLOAT3D vFront = -m.GetColumn(3)*fRange; + + FLOAT3D vDest[5]; + vDest[0] = vBase+vFront; + vDest[1] = vBase+vFront+vUp; + vDest[2] = vBase+vFront-vUp; + vDest[3] = vBase+vFront+vRight; + vDest[4] = vBase+vFront-vRight; + + CEntity *penClosest = NULL; + FLOAT fDistance = UpperLimit(0.0f); + FLOAT3D vHit; + FLOAT3D vDir; + // for each ray + for (INDEX i=0; i<5; i++) { + // cast a ray to find if any model + CCastRay crRay( m_penPlayer, vBase, vDest[i]); + crRay.cr_bHitTranslucentPortals = FALSE; + crRay.cr_fTestR = fThickness; + crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX; + GetWorld()->CastRay(crRay); + + // if hit something + if (crRay.cr_penHit!=NULL /*&& crRay.cr_penHit->GetRenderType()==RT_MODEL*/ && crRay.cr_fHitDistanceGetRenderType()==RT_BRUSH) + { + INDEX iSurfaceType=crRay.cr_pbpoBrushPolygon->bpo_bppProperties.bpp_ubSurfaceType; + EffectParticlesType eptType=GetParticleEffectTypeForSurface(iSurfaceType); + + FLOAT3D vNormal=crRay.cr_pbpoBrushPolygon->bpo_pbplPlane->bpl_plAbsolute; + FLOAT3D vReflected = vDir-vNormal*(2.0f*(vNormal%vDir)); + ((CPlayer&)*m_penPlayer).AddBulletSpray( vBase+vFront, eptType, vReflected); + } + else if(crRay.cr_penHit->GetRenderType()==RT_MODEL) + { + BOOL bRender=TRUE; + FLOAT3D vSpillDir=-((CPlayer&)*m_penPlayer).en_vGravityDir*0.5f; + SprayParticlesType sptType=SPT_NONE; + COLOR colParticles=C_WHITE|CT_OPAQUE; + FLOAT fPower=4.0f; + if( IsOfClass(crRay.cr_penHit, "ModelHolder2")) + { + bRender=FALSE; + CModelDestruction *penDestruction = ((CModelHolder2&)*crRay.cr_penHit).GetDestruction(); + if( penDestruction!=NULL) + { + bRender=TRUE; + sptType= penDestruction->m_sptType; + } + CModelHolder2 *pmh2=(CModelHolder2*)crRay.cr_penHit; + colParticles=pmh2->m_colBurning; + } + FLOATaabbox3D boxCutted=FLOATaabbox3D(FLOAT3D(0,0,0),FLOAT3D(1,1,1)); + if(bRender) + { + crRay.cr_penHit->en_pmoModelObject->GetCurrentFrameBBox( boxCutted); + ((CPlayer&)*m_penPlayer).AddGoreSpray( vBase+vFront, vHit, sptType, + vSpillDir, boxCutted, fPower, colParticles); + } + } + // don't search any more + break; + } + } + } + // if any model hit + if (penClosest!=NULL) { + // in deathmatches check for backstab + if (!(GetSP()->sp_bCooperative) && IsOfClass(penClosest, "Player")) { + FLOAT3D vToTarget = penClosest->GetPlacement().pl_PositionVector - m_penPlayer->GetPlacement().pl_PositionVector; + FLOAT3D vTargetHeading = FLOAT3D(0.0, 0.0, -1.0f)*penClosest->GetRotationMatrix(); + vToTarget.Normalize(); vTargetHeading.Normalize(); + if (vToTarget%vTargetHeading>0.64279) //CosFast(50.0f) + { + PrintCenterMessage(this, m_penPlayer, TRANS("Backstab!"), 4.0f, MSS_NONE); + fDamage *= 4.0f; + } + } + const FLOAT fDamageMul = GetSeriousDamageMultiplier(m_penPlayer); + InflictDirectDamage(penClosest, m_penPlayer, DMT_CLOSERANGE, fDamage*fDamageMul, vHit, vDir); + return TRUE; + } + return FALSE; + }; + + + // cut in front of you with the chainsaw + BOOL CutWithChainsaw(FLOAT fX, FLOAT fY, FLOAT fRange, FLOAT fWide, FLOAT fThickness, FLOAT fDamage) + { + // knife start position + CPlacement3D plKnife; + CalcWeaponPosition(FLOAT3D(fX, fY, 0), plKnife, TRUE); + + // create a set of rays to test + const FLOAT3D &vBase = plKnife.pl_PositionVector; + FLOATmatrix3D m; + MakeRotationMatrixFast(m, plKnife.pl_OrientationAngle); + FLOAT3D vRight = m.GetColumn(1)*fWide; + FLOAT3D vUp = m.GetColumn(2)*fWide; + FLOAT3D vFront = -m.GetColumn(3)*fRange; + + FLOAT3D vDest[3]; + vDest[0] = vBase+vFront; + vDest[1] = vBase+vFront+vRight; + vDest[2] = vBase+vFront-vRight; + + CEntity *penClosest = NULL; + FLOAT fDistance = UpperLimit(0.0f); + FLOAT3D vHit; + FLOAT3D vDir; + // for each ray + for (INDEX i=0; i<3; i++) { + // cast a ray to find if any model + CCastRay crRay( m_penPlayer, vBase, vDest[i]); + crRay.cr_bHitTranslucentPortals = FALSE; + crRay.cr_fTestR = fThickness; + crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX; + GetWorld()->CastRay(crRay); + + // if hit something + if (crRay.cr_penHit!=NULL) + { + penClosest = crRay.cr_penHit; + fDistance = crRay.cr_fHitDistance; + vDir = vDest[i]-vBase; + vDir.Normalize(); + vHit = crRay.cr_vHit; + + if(i==0) + { + if(crRay.cr_penHit->GetRenderType()==RT_BRUSH) + { + INDEX iSurfaceType=crRay.cr_pbpoBrushPolygon->bpo_bppProperties.bpp_ubSurfaceType; + EffectParticlesType eptType=GetParticleEffectTypeForSurface(iSurfaceType); + + FLOAT3D vNormal=crRay.cr_pbpoBrushPolygon->bpo_pbplPlane->bpl_plAbsolute; + FLOAT3D vReflected = vDir-vNormal*(2.0f*(vNormal%vDir)); + ((CPlayer&)*m_penPlayer).AddBulletSpray( vBase+vFront, eptType, vReflected); + + // shake view + ((CPlayer&)*m_penPlayer).m_fChainShakeStrength = 0.85f; + ((CPlayer&)*m_penPlayer).m_fChainShakeFreqMod = 1.0f; + ((CPlayer&)*m_penPlayer).m_tmChainShakeEnd = _pTimer->CurrentTick() + CHAINSAW_UPDATETIME*1.5f; + + } + else if(crRay.cr_penHit->GetRenderType()==RT_MODEL) + { + BOOL bRender=TRUE; + FLOAT3D vSpillDir=-((CPlayer&)*m_penPlayer).en_vGravityDir*0.5f; + SprayParticlesType sptType=SPT_BLOOD; + COLOR colParticles=C_WHITE|CT_OPAQUE; + if (!IsDerivedFromClass(crRay.cr_penHit, "Enemy Base")) { + sptType=SPT_NONE; + } + FLOAT fPower=4.0f; + if( IsOfClass(crRay.cr_penHit, "Boneman")) {sptType=SPT_BONES; fPower=6.0f;} + if( IsOfClass(crRay.cr_penHit, "Gizmo") || + IsOfClass(crRay.cr_penHit, "Beast")) {sptType=SPT_SLIME; fPower=4.0f;} + if( IsOfClass(crRay.cr_penHit, "Woman")) {sptType=SPT_FEATHER; fPower=3.0f;} + if( IsOfClass(crRay.cr_penHit, "Elemental")) {sptType=SPT_LAVA_STONES; fPower=3.0f;} + if( IsOfClass(crRay.cr_penHit, "Walker")) {sptType=SPT_ELECTRICITY_SPARKS; fPower=30.0f;} + if( IsOfClass(crRay.cr_penHit, "AirElemental")) {sptType=SPT_AIRSPOUTS; fPower=6.0f;} + if( IsOfClass(crRay.cr_penHit, "CannonRotating") || + IsOfClass(crRay.cr_penHit, "CannonStatic")) {sptType=SPT_WOOD;} + if( IsOfClass(crRay.cr_penHit, "ModelHolder2")) + { + bRender=FALSE; + CModelDestruction *penDestruction = ((CModelHolder2&)*crRay.cr_penHit).GetDestruction(); + CModelHolder2 *pmh2=(CModelHolder2*)crRay.cr_penHit; + colParticles=pmh2->m_colBurning; + if( penDestruction!=NULL) + { + bRender=TRUE; + sptType= penDestruction->m_sptType; + if(sptType==SPT_COLOREDSTONE) + { + colParticles=MulColors(colParticles,penDestruction->m_colParticles); + } + } + } + FLOATaabbox3D boxCutted=FLOATaabbox3D(FLOAT3D(0,0,0),FLOAT3D(1,1,1)); + if(bRender && m_tmLastChainsawSpray+0.2f<_pTimer->CurrentTick()) + { + crRay.cr_penHit->en_pmoModelObject->GetCurrentFrameBBox( boxCutted); + ((CPlayer&)*m_penPlayer).AddGoreSpray( vBase+vFront, vHit, sptType, + vSpillDir, boxCutted, fPower, colParticles); + m_tmLastChainsawSpray = _pTimer->CurrentTick(); + } + + // shake view + ((CPlayer&)*m_penPlayer).m_fChainShakeStrength = 1.1f; + ((CPlayer&)*m_penPlayer).m_fChainShakeFreqMod = 1.0f; + ((CPlayer&)*m_penPlayer).m_tmChainShakeEnd = _pTimer->CurrentTick() + CHAINSAW_UPDATETIME*1.5f; + + } + } + + if(crRay.cr_penHit->GetRenderType()==RT_MODEL && crRay.cr_fHitDistance<=fDistance) + { + // if this is primary ray + if (i==0) + { + // don't search any more + break; + } + } + } else { + // because we're firing, add just a slight shake + ((CPlayer&)*m_penPlayer).m_fChainShakeStrength = 0.1f; + ((CPlayer&)*m_penPlayer).m_fChainShakeFreqMod = 1.0f; + ((CPlayer&)*m_penPlayer).m_tmChainShakeEnd = _pTimer->CurrentTick() + CHAINSAW_UPDATETIME*1.5f; + } + } + // if any model hit + if (penClosest!=NULL) { + InflictDirectDamage(penClosest, m_penPlayer, DMT_CHAINSAW, fDamage, vHit, vDir); + return TRUE; + } + return FALSE; + }; + + // prepare Bullet + void PrepareSniperBullet(FLOAT fX, FLOAT fY, FLOAT fDamage, FLOAT fImprecission) { + // bullet start position + CalcWeaponPositionImprecise(FLOAT3D(fX, fY, 0), plBullet, TRUE, fImprecission); + // create bullet + penBullet = CreateEntity(plBullet, CLASS_BULLET); + m_vBulletSource = plBullet.pl_PositionVector; + // init bullet + EBulletInit eInit; + eInit.penOwner = m_penPlayer; + eInit.fDamage = fDamage; + penBullet->Initialize(eInit); + }; + + // prepare Bullet + void PrepareBullet(FLOAT fX, FLOAT fY, FLOAT fDamage) { + // bullet start position + CalcWeaponPosition(FLOAT3D(fX, fY, 0), plBullet, TRUE); + // create bullet + penBullet = CreateEntity(plBullet, CLASS_BULLET); + // init bullet + EBulletInit eInit; + eInit.penOwner = m_penPlayer; + eInit.fDamage = fDamage; + penBullet->Initialize(eInit); + }; + + // fire one bullet + void FireSniperBullet(FLOAT fX, FLOAT fY, FLOAT fRange, FLOAT fDamage, FLOAT fImprecission) { + PrepareSniperBullet(fX, fY, fDamage, fImprecission); + ((CBullet&)*penBullet).CalcTarget(fRange); + ((CBullet&)*penBullet).m_fBulletSize = 0.1f; + // launch bullet + ((CBullet&)*penBullet).LaunchBullet(TRUE, FALSE, TRUE); + + if (((CBullet&)*penBullet).m_vHitPoint != FLOAT3D(0.0f, 0.0f, 0.0f)) { + m_vBulletTarget = ((CBullet&)*penBullet).m_vHitPoint; + } else if (TRUE) { + m_vBulletTarget = m_vBulletSource + FLOAT3D(0.0f, 0.0f, -500.0f)*((CBullet&)*penBullet).GetRotationMatrix(); + + } + + // spawn bullet effect + /*ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_SNIPER_RESIDUE; + ese.vStretch = FLOAT3D(1.0f, 1.0f, 1.0f); + ese.vNormal = m_vBulletSource; + ese.vDirection = ((CBullet&)*penBullet).m_vHitPoint; + CPlacement3D pl = CPlacement3D(GetPlacement().pl_PositionVector, ANGLE3D(0.0f, 0.0f, 0.0f)); + CEntityPointer penFX = CreateEntity(pl, CLASS_BASIC_EFFECT); + penFX->Initialize(ese);*/ + + // bullet no longer needed + ((CBullet&)*penBullet).DestroyBullet(); + }; + + // fire one bullet + void FireOneBullet(FLOAT fX, FLOAT fY, FLOAT fRange, FLOAT fDamage) { + PrepareBullet(fX, fY, fDamage); + ((CBullet&)*penBullet).CalcTarget(fRange); + ((CBullet&)*penBullet).m_fBulletSize = 0.1f; + // launch bullet + ((CBullet&)*penBullet).LaunchBullet(TRUE, FALSE, TRUE); + ((CBullet&)*penBullet).DestroyBullet(); + }; + + // fire bullets (x offset is used for double shotgun) + void FireBullets(FLOAT fX, FLOAT fY, FLOAT fRange, FLOAT fDamage, INDEX iBullets, + FLOAT *afPositions, FLOAT fStretch, FLOAT fJitter) { + PrepareBullet(fX, fY, fDamage); + ((CBullet&)*penBullet).CalcTarget(fRange); + ((CBullet&)*penBullet).m_fBulletSize = GetSP()->sp_bCooperative ? 0.1f : 0.3f; + // launch slugs + INDEX iSlug; + for (iSlug=0; iSlugInitialize(eLaunch); + }; + + // fire rocket + void FireRocket(void) { + // rocket start position + CPlacement3D plRocket; + CalcWeaponPosition( + FLOAT3D(wpn_fFX[WEAPON_ROCKETLAUNCHER],wpn_fFY[WEAPON_ROCKETLAUNCHER], 0), + plRocket, TRUE); + // create rocket + CEntityPointer penRocket= CreateEntity(plRocket, CLASS_PROJECTILE); + // init and launch rocket + ELaunchProjectile eLaunch; + eLaunch.penLauncher = m_penPlayer; + eLaunch.prtType = PRT_ROCKET; + penRocket->Initialize(eLaunch); + }; + + /* + // drop pipebomb + void DropPipebomb(void) { + // pipebomb start position + CPlacement3D plPipebomb; + CalcWeaponPosition( + FLOAT3D(wpn_fFX[WEAPON_PIPEBOMB],wpn_fFY[WEAPON_PIPEBOMB], 0), + plPipebomb, TRUE); + // create pipebomb + CEntityPointer penPipebomb = CreateEntity(plPipebomb, CLASS_PIPEBOMB); + // init and drop pipebomb + EDropPipebomb eDrop; + eDrop.penLauncher = m_penPlayer; + if (((CPlayer&)*m_penPlayer).en_plViewpoint.pl_OrientationAngle(2) > 10.0f) { + eDrop.fSpeed = 30.0f; + } else if (((CPlayer&)*m_penPlayer).en_plViewpoint.pl_OrientationAngle(2) > -20.0f) { + eDrop.fSpeed = 20.0f; + } else { + eDrop.fSpeed = 5.0f; + } + penPipebomb->Initialize(eDrop); + m_penPipebomb = penPipebomb; + };*/ + + // flamer source + void GetFlamerSourcePlacement(CPlacement3D &plSource, CPlacement3D &plInFrontOfPipe) { + CalcLerpedWeaponPosition( + FLOAT3D(wpn_fFX[WEAPON_FLAMER],wpn_fFY[WEAPON_FLAMER], -0.15f), + plSource, FALSE); + plInFrontOfPipe=plSource; + FLOAT3D vFront; + AnglesToDirectionVector( plSource.pl_OrientationAngle, vFront); + plInFrontOfPipe.pl_PositionVector=plSource.pl_PositionVector+vFront*1.0f; + }; + + // fire flame + void FireFlame(void) { + // flame start position + CPlacement3D plFlame; + + CalcWeaponPosition(FLOAT3D(wpn_fFX[WEAPON_FLAMER],wpn_fFY[WEAPON_FLAMER], -0.15f), plFlame, TRUE); + + // create flame + CEntityPointer penFlame = CreateEntity(plFlame, CLASS_PROJECTILE); + // init and launch flame + ELaunchProjectile eLaunch; + eLaunch.penLauncher = m_penPlayer; + eLaunch.prtType = PRT_FLAME; + penFlame->Initialize(eLaunch); + // link last flame with this one (if not NULL or deleted) + if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) { + ((CProjectile&)*m_penFlame).m_penParticles = penFlame; + } + // link to player weapons + ((CProjectile&)*penFlame).m_penParticles = this; + // store last flame + m_penFlame = penFlame; + }; + + // fire laser ray + void FireLaserRay(void) { + // laser start position + CPlacement3D plLaserRay; + FLOAT fFX = wpn_fFX[WEAPON_LASER]; // get laser center position + FLOAT fFY = wpn_fFY[WEAPON_LASER]; + FLOAT fLUX = 0.0f; + FLOAT fRUX = 0.8f; + FLOAT fLUY = 0.0f; + FLOAT fRUY = 0.0f; + FLOAT fLDX = -0.1f; + FLOAT fRDX = 0.9f; + FLOAT fLDY = -0.3f; + FLOAT fRDY = -0.3f; + if (((CPlayer *)&*m_penPlayer)->m_pstState==PST_CROUCH) { + fLDY = -0.1f; + fRDY = -0.1f; + } + + switch(m_iLaserBarrel) { + case 0: // barrel lu (*o-oo) + CalcWeaponPosition(FLOAT3D(fFX+fLUX, fFY+fLUY, 0), plLaserRay, TRUE); + break; + case 1: // barrel ld (oo-*o) + CalcWeaponPosition(FLOAT3D(fFX+fLDX, fFY+fLDY, 0), plLaserRay, TRUE); + break; + case 2: // barrel ru (o*-oo) + CalcWeaponPosition(FLOAT3D(fFX+fRUX, fFY+fRUY, 0), plLaserRay, TRUE); + break; + case 3: // barrel rd (oo-o*) + CalcWeaponPosition(FLOAT3D(fFX+fRDX, fFY+fRDY, 0), plLaserRay, TRUE); + break; + } + // create laser projectile + CEntityPointer penLaser = CreateEntity(plLaserRay, CLASS_PROJECTILE); + // init and launch laser projectile + ELaunchProjectile eLaunch; + eLaunch.penLauncher = m_penPlayer; + eLaunch.prtType = PRT_LASER_RAY; + penLaser->Initialize(eLaunch); + }; + + /* + // ghostbuster source + void GetGhostBusterSourcePlacement(CPlacement3D &plSource) { + CalcWeaponPosition( + FLOAT3D(wpn_fFX[WEAPON_GHOSTBUSTER],wpn_fFY[WEAPON_GHOSTBUSTER], 0), + plSource, TRUE); + }; + + // fire ghost buster ray + void FireGhostBusterRay(void) { + // ray start position + CPlacement3D plRay; + GetGhostBusterSourcePlacement(plRay); + // fire ray + ((CGhostBusterRay&)*m_penGhostBusterRay).Fire(plRay); + }; + */ + + // fire cannon ball + void FireCannonBall(INDEX iPower) + { + // cannon ball start position + CPlacement3D plBall; + CalcWeaponPosition( + FLOAT3D(wpn_fFX[WEAPON_IRONCANNON],wpn_fFY[WEAPON_IRONCANNON], 0), + plBall, TRUE); + // create cannon ball + CEntityPointer penBall = CreateEntity(plBall, CLASS_CANNONBALL); + // init and launch cannon ball + ELaunchCannonBall eLaunch; + eLaunch.penLauncher = m_penPlayer; + eLaunch.fLaunchPower = 60.0f+iPower*4.0f; // ranges from 60-140 (since iPower can be max 20) + eLaunch.fSize = 3.0f; + /*if( m_iCurrentWeapon == WEAPON_NUKECANNON) + { + eLaunch.cbtType = CBT_NUKE; + } + else + { + */ + eLaunch.cbtType = CBT_IRON; +// } + penBall->Initialize(eLaunch); + }; + + // weapon sound when firing + void SpawnRangeSound( FLOAT fRange) + { + if( _pTimer->CurrentTick()>m_tmRangeSoundSpawned+0.5f) { + m_tmRangeSoundSpawned = _pTimer->CurrentTick(); + ::SpawnRangeSound( m_penPlayer, m_penPlayer, SNDT_PLAYER, fRange); + } + }; + + + /* + * >>>--- WEAPON INTERFACE FUNCTIONS ---<<< + */ + // clear weapons + void ClearWeapons(void) { + // give/take weapons + m_iAvailableWeapons = 0x03; + m_iColtBullets = 6; + m_iBullets = 0; + m_iShells = 0; + m_iRockets = 0; + m_iGrenades = 0; + m_iNapalm = 0; + m_iElectricity = 0; + m_iIronBalls = 0; +// m_iNukeBalls = 0; + m_iSniperBullets = 0; + }; + + void ResetWeaponMovingOffset(void) + { + // reset weapon draw offset + m_fWeaponDrawPowerOld = m_fWeaponDrawPower = m_tmDrawStartTime = 0; + } + + // initialize weapons + void InitializeWeapons(INDEX iGiveWeapons, INDEX iTakeWeapons, INDEX iTakeAmmo, FLOAT fMaxAmmoRatio) + { + ResetWeaponMovingOffset(); + // remember old weapons + ULONG ulOldWeapons = m_iAvailableWeapons; + // give/take weapons + m_iAvailableWeapons &= ~iTakeWeapons; + m_iAvailableWeapons |= 0x03|iGiveWeapons; + m_iAvailableWeapons &= WEAPONS_ALLAVAILABLEMASK; + // m_iAvailableWeapons &= ~WEAPONS_DISABLEDMASK; + // find which weapons are new + ULONG ulNewWeapons = m_iAvailableWeapons&~ulOldWeapons; + // for each new weapon + for(INDEX iWeapon=WEAPON_KNIFE; iWeaponsp_fAmmoQuantity, 1.0f); + m_iMaxBullets = ClampUp((INDEX) ceil(MAX_BULLETS*fModifier), INDEX(999)); + m_iMaxShells = ClampUp((INDEX) ceil(MAX_SHELLS*fModifier), INDEX(999)); + m_iMaxRockets = ClampUp((INDEX) ceil(MAX_ROCKETS*fModifier), INDEX(999)); + m_iMaxGrenades = ClampUp((INDEX) ceil(MAX_GRENADES*fModifier), INDEX(999)); + m_iMaxNapalm = ClampUp((INDEX) ceil(MAX_NAPALM*fModifier), INDEX(999)); + m_iMaxElectricity = ClampUp((INDEX) ceil(MAX_ELECTRICITY*fModifier), INDEX(999)); +// m_iMaxNukeBalls = ClampUp((INDEX) ceil(MAX_NUKEBALLS*fModifier), INDEX(999)); + m_iMaxIronBalls = ClampUp((INDEX) ceil(MAX_IRONBALLS*fModifier), INDEX(999)); + m_iMaxSniperBullets = ClampUp((INDEX) ceil(MAX_SNIPERBULLETS*fModifier), INDEX(999)); + + // take away ammo + if( iTakeAmmo & (1<SendEvent(ETrigger()); + } + } + + // cheat give all + void CheatGiveAll(void) { + // all weapons + m_iAvailableWeapons = WEAPONS_ALLAVAILABLEMASK; + // m_iAvailableWeapons &= ~WEAPONS_DISABLEDMASK; + // ammo for all weapons + m_iBullets = m_iMaxBullets; + m_iShells = m_iMaxShells; + m_iRockets = m_iMaxRockets; + m_iGrenades = m_iMaxGrenades; + m_iNapalm = m_iMaxNapalm; + m_iElectricity = m_iMaxElectricity; + m_iIronBalls = m_iMaxIronBalls; + //m_iNukeBalls = m_iMaxNukeBalls; + // precache eventual new weapons + m_iSniperBullets = m_iMaxSniperBullets; + Precache(); + }; + + // add a given amount of mana to the player + void AddManaToPlayer(INDEX iMana) + { + ((CPlayer&)*m_penPlayer).m_iMana += iMana; + ((CPlayer&)*m_penPlayer).m_fPickedMana += iMana; + } + + + /* + * >>>--- RECEIVE FUNCTIONS ---<<< + */ + + // clamp ammounts of all ammunition to maximum values + void ClampAllAmmo(void) + { + m_iBullets = ClampUp(m_iBullets, m_iMaxBullets); + m_iShells = ClampUp(m_iShells, m_iMaxShells); + m_iRockets = ClampUp(m_iRockets, m_iMaxRockets); + m_iGrenades = ClampUp(m_iGrenades, m_iMaxGrenades); + m_iNapalm = ClampUp(m_iNapalm, m_iMaxNapalm); + m_iElectricity = ClampUp(m_iElectricity, m_iMaxElectricity); + m_iIronBalls = ClampUp(m_iIronBalls, m_iMaxIronBalls); +// m_iNukeBalls = ClampUp(m_iNukeBalls, m_iMaxNukeBalls); + m_iSniperBullets = ClampUp(m_iSniperBullets, m_iMaxSniperBullets); + } + + // add default ammount of ammunition when receiving a weapon + void AddDefaultAmmoForWeapon(INDEX iWeapon, FLOAT fMaxAmmoRatio) + { + INDEX iAmmoPicked; + // add ammo + switch (iWeapon) { + // unlimited ammo + case WEAPON_KNIFE: + case WEAPON_COLT: + case WEAPON_DOUBLECOLT: + break; + // shells + case WEAPON_SINGLESHOTGUN: + iAmmoPicked = Max(10.0f, m_iMaxShells*fMaxAmmoRatio); + m_iShells += iAmmoPicked; + AddManaToPlayer(iAmmoPicked*70.0f*MANA_AMMO); + break; + case WEAPON_DOUBLESHOTGUN: + iAmmoPicked = Max(20.0f, m_iMaxShells*fMaxAmmoRatio); + m_iShells += iAmmoPicked; + AddManaToPlayer(iAmmoPicked*70.0f*MANA_AMMO); + break; + // bullets + case WEAPON_TOMMYGUN: + iAmmoPicked = Max(50.0f, m_iMaxBullets*fMaxAmmoRatio); + m_iBullets += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*10.0f*MANA_AMMO); + break; + case WEAPON_SNIPER: + iAmmoPicked = Max(15.0f, m_iMaxSniperBullets*fMaxAmmoRatio); + m_iSniperBullets += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*10.0f*MANA_AMMO); + break; + case WEAPON_MINIGUN: + iAmmoPicked = Max(100.0f, m_iMaxBullets*fMaxAmmoRatio); + m_iBullets += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*10.0f*MANA_AMMO); + break; + // rockets + case WEAPON_ROCKETLAUNCHER: + iAmmoPicked = Max(5.0f, m_iMaxRockets*fMaxAmmoRatio); + m_iRockets += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*150.0f*MANA_AMMO); + break; + // grenades + case WEAPON_GRENADELAUNCHER: + iAmmoPicked = Max(5.0f, m_iMaxGrenades*fMaxAmmoRatio); + m_iGrenades += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*100.0f*MANA_AMMO); + break; +/* + case WEAPON_PIPEBOMB: + iAmmoPicked = Max(5.0f, m_iMaxGrenades*fMaxAmmoRatio); + m_iGrenades += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*100.0f*MANA_AMMO); + break; + case WEAPON_GHOSTBUSTER: + iAmmoPicked = Max(100.0f, m_iMaxElectricity*fMaxAmmoRatio); + m_iElectricity += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*15.0f*MANA_AMMO); + break; + */ + // electricity + case WEAPON_LASER: + iAmmoPicked = Max(50.0f, m_iMaxElectricity*fMaxAmmoRatio); + m_iElectricity += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*15.0f*MANA_AMMO); + break; + // cannon balls + case WEAPON_IRONCANNON: + // for iron ball + iAmmoPicked = Max(1.0f, m_iMaxIronBalls*fMaxAmmoRatio); + m_iIronBalls += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*700.0f*MANA_AMMO); + break; +/* // for nuke ball + case WEAPON_NUKECANNON: + iAmmoPicked = Max(1.0f, m_iMaxNukeBalls*fMaxAmmoRatio); + m_iNukeBalls += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*1000.0f*MANA_AMMO); + break;*/ + // flamer // !!!! how much mana exactly? + case WEAPON_FLAMER: + iAmmoPicked = Max(50.0f, m_iMaxNapalm*fMaxAmmoRatio); + m_iNapalm += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*15.0f*MANA_AMMO); + break; + case WEAPON_CHAINSAW: + /*iAmmoPicked = Max(50.0f, m_iMaxNapalm*fMaxAmmoRatio); + m_iNapalm += iAmmoPicked; + AddManaToPlayer( iAmmoPicked*15.0f*MANA_AMMO);*/ + break; + // error + default: + ASSERTALWAYS("Uknown weapon type"); + break; + } + + // make sure we don't have more ammo than maximum + ClampAllAmmo(); + } + + // drop current weapon (in deathmatch) + void DropWeapon(void) + { + CEntityPointer penWeapon = CreateEntity(GetPlayer()->GetPlacement(), CLASS_WEAPONITEM); + CWeaponItem *pwi = (CWeaponItem*)&*penWeapon; + + WeaponItemType wit = WIT_COLT; + switch (m_iCurrentWeapon) { + default: + ASSERT(FALSE); + case WEAPON_KNIFE: + case WEAPON_COLT: + case WEAPON_DOUBLECOLT: + NOTHING; break; + case WEAPON_SINGLESHOTGUN: wit = WIT_SINGLESHOTGUN; break; + case WEAPON_DOUBLESHOTGUN: wit = WIT_DOUBLESHOTGUN; break; + case WEAPON_TOMMYGUN: wit = WIT_TOMMYGUN; break; + case WEAPON_SNIPER: wit = WIT_SNIPER; break; + case WEAPON_MINIGUN: wit = WIT_MINIGUN; break; + case WEAPON_ROCKETLAUNCHER: wit = WIT_ROCKETLAUNCHER; break; + case WEAPON_GRENADELAUNCHER: wit = WIT_GRENADELAUNCHER; break; + case WEAPON_FLAMER: wit = WIT_FLAMER; break; + case WEAPON_CHAINSAW: wit = WIT_CHAINSAW; break; + case WEAPON_LASER : wit = WIT_LASER; break; + case WEAPON_IRONCANNON : wit = WIT_CANNON; break; + } + + pwi->m_EwitType = wit; + pwi->m_bDropped = TRUE; + pwi->CEntity::Initialize(); + + const FLOATmatrix3D &m = GetPlayer()->GetRotationMatrix(); + FLOAT3D vSpeed = FLOAT3D( 5.0f, 10.0f, -7.5f); + pwi->GiveImpulseTranslationAbsolute(vSpeed*m); + } + + // receive weapon + BOOL ReceiveWeapon(const CEntityEvent &ee) { + ASSERT(ee.ee_slEvent == EVENTCODE_EWeaponItem); + + EWeaponItem &Ewi = (EWeaponItem&)ee; + INDEX wit = Ewi.iWeapon; + switch (Ewi.iWeapon) { + case WIT_COLT: Ewi.iWeapon = WEAPON_COLT; break; + case WIT_SINGLESHOTGUN: Ewi.iWeapon = WEAPON_SINGLESHOTGUN; break; + case WIT_DOUBLESHOTGUN: Ewi.iWeapon = WEAPON_DOUBLESHOTGUN; break; + case WIT_TOMMYGUN: Ewi.iWeapon = WEAPON_TOMMYGUN; break; + case WIT_SNIPER: Ewi.iWeapon = WEAPON_SNIPER; break; + case WIT_MINIGUN: Ewi.iWeapon = WEAPON_MINIGUN; break; + case WIT_ROCKETLAUNCHER: Ewi.iWeapon = WEAPON_ROCKETLAUNCHER; break; + case WIT_GRENADELAUNCHER: Ewi.iWeapon = WEAPON_GRENADELAUNCHER; break; + case WIT_FLAMER: Ewi.iWeapon = WEAPON_FLAMER; break; + case WIT_CHAINSAW: Ewi.iWeapon = WEAPON_CHAINSAW; break; + case WIT_LASER: Ewi.iWeapon = WEAPON_LASER; break; + case WIT_CANNON: Ewi.iWeapon = WEAPON_IRONCANNON; break; + default: + ASSERTALWAYS("Uknown weapon type"); + } + + // add weapon + if (Ewi.iWeapon==WEAPON_COLT && (m_iAvailableWeapons&(1<<(WEAPON_COLT-1)))) { + Ewi.iWeapon = WEAPON_DOUBLECOLT; + } + + ULONG ulOldWeapons = m_iAvailableWeapons; + m_iAvailableWeapons |= 1<<(Ewi.iWeapon-1); +// m_iAvailableWeapons &= ~WEAPONS_DISABLEDMASK; + +/* + if( Ewi.iWeapon == WEAPON_IRONCANNON) + { + m_iAvailableWeapons |= 1<<(WEAPON_NUKECANNON-1); + m_iAvailableWeapons &= ~WEAPONS_DISABLEDMASK; + } + */ + + // precache eventual new weapons + Precache(); + + CTFileName fnmMsg; + switch (wit) { + case WIT_COLT: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Shofield .45 w/ TMAR"), 0); + fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\colt.txt"); + break; + case WIT_SINGLESHOTGUN: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("12 Gauge Pump Action Shotgun"), 0); + fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\singleshotgun.txt"); + break; + case WIT_DOUBLESHOTGUN: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Double Barrel Coach Gun"), 0); + fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\doubleshotgun.txt"); + break; + case WIT_TOMMYGUN: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("M1-A2 Tommygun"), 0); + fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\tommygun.txt"); + break; + case WIT_SNIPER: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("RAPTOR 16mm Sniper"), 0); + fnmMsg = CTFILENAME("DataMP\\Messages\\Weapons\\sniper.txt"); + break; + case WIT_MINIGUN: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("XM214-A Minigun"), 0); + fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\minigun.txt"); + break; + case WIT_ROCKETLAUNCHER: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("XPML21 Rocket Launcher"), 0); + fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\rocketlauncher.txt"); + break; + case WIT_GRENADELAUNCHER: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("MKIII Grenade Launcher"), 0); + fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\grenadelauncher.txt"); + break; +// case WIT_PIPEBOMB: +// fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\pipebomb.txt"); +// break; + case WIT_FLAMER: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("XOP Flamethrower"), 0); + fnmMsg = CTFILENAME("DataMP\\Messages\\Weapons\\flamer.txt"); + break; + case WIT_CHAINSAW: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("'Bonecracker' P-LAH Chainsaw"), 0); + fnmMsg = CTFILENAME("DataMP\\Messages\\Weapons\\chainsaw.txt"); + break; + case WIT_LASER: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("XL2 Lasergun"), 0); + fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\laser.txt"); + break; +// case WIT_GHOSTBUSTER: +// fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\ghostbuster.txt"); +// break; + case WIT_CANNON: + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("SBC Cannon"), 0); + fnmMsg = CTFILENAME("Data\\Messages\\Weapons\\cannon.txt"); + break; + default: + ASSERTALWAYS("Uknown weapon type"); + } + // send computer message + if (GetSP()->sp_bCooperative) { + EComputerMessage eMsg; + eMsg.fnmMessage = fnmMsg; + m_penPlayer->SendEvent(eMsg); + } + + // must be -1 for default (still have to implement dropping weapons in deathmatch !!!!) + ASSERT(Ewi.iAmmo==-1); + // add the ammunition + AddDefaultAmmoForWeapon(Ewi.iWeapon, 0); + + // if this weapon should be auto selected + BOOL bAutoSelect = FALSE; + INDEX iSelectionSetting = GetPlayer()->GetSettings()->ps_iWeaponAutoSelect; + if (iSelectionSetting==PS_WAS_ALL) { + bAutoSelect = TRUE; + } else if (iSelectionSetting==PS_WAS_ONLYNEW) { + if (m_iAvailableWeapons&~ulOldWeapons) { + bAutoSelect = TRUE; + } + } else if (iSelectionSetting==PS_WAS_BETTER) { + if (FindRemapedPos(m_iCurrentWeapon)sp_bInfiniteAmmo) { + // pick all items anyway (items that exist in this mode are only those that + // trigger something when picked - so they must be picked) + return TRUE; + } + + + EAmmoItem &Eai = (EAmmoItem&)ee; + // add ammo + switch (Eai.EaitType) { + // shells + case AIT_SHELLS: + if (m_iShells>=m_iMaxShells) { m_iShells = m_iMaxShells; return FALSE; } + m_iShells += Eai.iQuantity; + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Shells"), Eai.iQuantity); + AddManaToPlayer(Eai.iQuantity*AV_SHELLS*MANA_AMMO); + break; + // bullets + case AIT_BULLETS: + if (m_iBullets>=m_iMaxBullets) { m_iBullets = m_iMaxBullets; return FALSE; } + m_iBullets += Eai.iQuantity; + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Bullets"), Eai.iQuantity); + AddManaToPlayer(Eai.iQuantity*AV_BULLETS *MANA_AMMO); + break; + // rockets + case AIT_ROCKETS: + if (m_iRockets>=m_iMaxRockets) { m_iRockets = m_iMaxRockets; return FALSE; } + m_iRockets += Eai.iQuantity; + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Rockets"), Eai.iQuantity); + AddManaToPlayer(Eai.iQuantity*AV_ROCKETS *MANA_AMMO); + break; + // grenades + case AIT_GRENADES: + if (m_iGrenades>=m_iMaxGrenades) { m_iGrenades = m_iMaxGrenades; return FALSE; } + m_iGrenades += Eai.iQuantity; + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Grenades"), Eai.iQuantity); + AddManaToPlayer(Eai.iQuantity*AV_GRENADES *MANA_AMMO); + break; + // electicity + case AIT_ELECTRICITY: + if (m_iElectricity>=m_iMaxElectricity) { m_iElectricity = m_iMaxElectricity; return FALSE; } + m_iElectricity += Eai.iQuantity; + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Cells"), Eai.iQuantity); + AddManaToPlayer(Eai.iQuantity*AV_ELECTRICITY *MANA_AMMO); + break; +/* // cannon balls + case AIT_NUKEBALL: + if (m_iNukeBalls>=m_iMaxNukeBalls) { m_iNukeBalls = m_iMaxNukeBalls; return FALSE; } + m_iNukeBalls+= Eai.iQuantity; + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Nuke ball"), Eai.iQuantity); + AddManaToPlayer(Eai.iQuantity*AV_NUKEBALLS *MANA_AMMO); + break;*/ + case AIT_IRONBALLS: + if (m_iIronBalls>=m_iMaxIronBalls) { m_iIronBalls = m_iMaxIronBalls; return FALSE; } + m_iIronBalls+= Eai.iQuantity; + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Cannonballs"), Eai.iQuantity); + AddManaToPlayer(Eai.iQuantity*AV_IRONBALLS *MANA_AMMO); + break; + case AIT_NAPALM: + if (m_iNapalm>=m_iMaxNapalm) { m_iNapalm = m_iMaxNapalm; return FALSE; } + m_iNapalm+= Eai.iQuantity; + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Napalm"), Eai.iQuantity); + AddManaToPlayer(Eai.iQuantity*AV_NAPALM*MANA_AMMO); + break; + case AIT_BACKPACK: + m_iShells += 20*GetSP()->sp_fAmmoQuantity; + m_iBullets += 200*GetSP()->sp_fAmmoQuantity; + m_iRockets += 5*GetSP()->sp_fAmmoQuantity; + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Ammo pack"), 0); + AddManaToPlayer(100000000.0f *MANA_AMMO); // adjust mana value!!!! + break; + case AIT_SERIOUSPACK: + m_iShells += MAX_SHELLS*GetSP()->sp_fAmmoQuantity; + m_iBullets += MAX_BULLETS*GetSP()->sp_fAmmoQuantity; + m_iGrenades += MAX_GRENADES*GetSP()->sp_fAmmoQuantity; + m_iRockets += MAX_ROCKETS*GetSP()->sp_fAmmoQuantity; + m_iElectricity += MAX_ELECTRICITY*GetSP()->sp_fAmmoQuantity; + m_iIronBalls += MAX_IRONBALLS*GetSP()->sp_fAmmoQuantity; +// m_iNukeBalls += MAX_NUKEBALLS*GetSP()->sp_fAmmoQuantity; + case AIT_SNIPERBULLETS: + if (m_iSniperBullets>=m_iMaxSniperBullets) { m_iSniperBullets = m_iMaxSniperBullets; return FALSE; } + m_iSniperBullets+= Eai.iQuantity; + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("Sniper bullets"), Eai.iQuantity); + AddManaToPlayer(Eai.iQuantity*AV_SNIPERBULLETS*MANA_AMMO); + break; + + + ((CPlayer&)*m_penPlayer).ItemPicked(TRANS("All Ammo"), 0); + AddManaToPlayer(100000000.0f *MANA_AMMO); // adjust mana value!!!! + break; + // error + default: + ASSERTALWAYS("Uknown ammo type"); + } + + // make sure we don't have more ammo than maximum + ClampAllAmmo(); + return TRUE; + }; + + // receive ammo + BOOL ReceivePackAmmo(const CEntityEvent &ee) + { + // if infinite ammo is on + if (GetSP()->sp_bInfiniteAmmo) { + // pick all items anyway (items that exist in this mode are only those that + // trigger something when picked - so they must be picked) + return TRUE; + } + + ASSERT(ee.ee_slEvent == EVENTCODE_EAmmoPackItem); + EAmmoPackItem &eapi = (EAmmoPackItem &)ee; + if( (eapi.iShells>0 && m_iShells0 && m_iBullets0 && m_iRockets0 && m_iGrenades0 && m_iNapalm0 && m_iElectricity0 && m_iIronBalls0 && m_iSniperBullets0 && strMessage[iLen-1]==',') + { + strMessage.DeleteChar(iLen-1); + }; + if( iAmmoTypes>4 ) { + strMessage.PrintF(TRANS("Ammo pack")); + }; + + ((CPlayer&)*m_penPlayer).ItemPicked(strMessage, 0); + return TRUE; + } + return FALSE; + } + + /* + * >>>--- WEAPON CHANGE FUNCTIONS ---<<< + */ + // get weapon from selected number + WeaponType GetStrongerWeapon(INDEX iWeapon) { + switch(iWeapon) { + case 1: return WEAPON_CHAINSAW; + case 2: return WEAPON_DOUBLECOLT; + case 3: return WEAPON_DOUBLESHOTGUN; + case 4: return WEAPON_MINIGUN; + case 5: return WEAPON_ROCKETLAUNCHER; + case 6: return WEAPON_FLAMER; + case 7: return WEAPON_LASER; + case 8: return WEAPON_IRONCANNON; + } + return WEAPON_NONE; + }; + + // get selected number for weapon + INDEX GetSelectedWeapon(WeaponType EwtSelectedWeapon) { + switch(EwtSelectedWeapon) { + case WEAPON_KNIFE: case WEAPON_CHAINSAW: return 1; + case WEAPON_COLT: case WEAPON_DOUBLECOLT: return 2; + case WEAPON_SINGLESHOTGUN: case WEAPON_DOUBLESHOTGUN: return 3; + case WEAPON_TOMMYGUN: case WEAPON_MINIGUN: return 4; + case WEAPON_ROCKETLAUNCHER: case WEAPON_GRENADELAUNCHER: return 5; + case WEAPON_FLAMER: case WEAPON_SNIPER: return 6; + case WEAPON_LASER: return 7; + case WEAPON_IRONCANNON: return 8; + } + return 0; + }; + + // get secondary weapon from selected one + WeaponType GetAltWeapon(WeaponType EwtWeapon) { + switch (EwtWeapon) { + case WEAPON_KNIFE: return WEAPON_CHAINSAW; + case WEAPON_CHAINSAW: return WEAPON_KNIFE; + case WEAPON_COLT: return WEAPON_DOUBLECOLT; + case WEAPON_DOUBLECOLT: return WEAPON_COLT; + case WEAPON_SINGLESHOTGUN: return WEAPON_DOUBLESHOTGUN; + case WEAPON_DOUBLESHOTGUN: return WEAPON_SINGLESHOTGUN; + case WEAPON_TOMMYGUN: return WEAPON_MINIGUN; + case WEAPON_MINIGUN: return WEAPON_TOMMYGUN; + case WEAPON_ROCKETLAUNCHER: return WEAPON_GRENADELAUNCHER; + case WEAPON_GRENADELAUNCHER: return WEAPON_ROCKETLAUNCHER; + case WEAPON_FLAMER: return WEAPON_SNIPER; + case WEAPON_SNIPER: return WEAPON_FLAMER; + case WEAPON_LASER: return WEAPON_LASER; + case WEAPON_IRONCANNON: return WEAPON_IRONCANNON; + } + return WEAPON_NONE; + }; + + // select new weapon if possible + BOOL WeaponSelectOk(WeaponType wtToTry) + { + // if player has weapon and has enough ammo + if (((1<<(INDEX(wtToTry)-1))&m_iAvailableWeapons) + &&HasAmmo(wtToTry)) { + // if different weapon + if (wtToTry!=m_iCurrentWeapon) { + // initiate change + //m_bHasAmmo = FALSE; + m_iWantedWeapon = wtToTry; + m_bChangeWeapon = TRUE; + } + // selection ok + return TRUE; + // if no weapon or not enough ammo + } else { + // selection not ok + return FALSE; + } + } + // select new weapon when no more ammo + void SelectNewWeapon() + { + switch (m_iCurrentWeapon) { + case WEAPON_NONE: + case WEAPON_KNIFE: case WEAPON_COLT: case WEAPON_DOUBLECOLT: + case WEAPON_SINGLESHOTGUN: case WEAPON_DOUBLESHOTGUN: + case WEAPON_TOMMYGUN: case WEAPON_MINIGUN: case WEAPON_SNIPER: + WeaponSelectOk(WEAPON_MINIGUN)|| + WeaponSelectOk(WEAPON_TOMMYGUN)|| + WeaponSelectOk(WEAPON_DOUBLESHOTGUN)|| + WeaponSelectOk(WEAPON_SINGLESHOTGUN)|| + WeaponSelectOk(WEAPON_DOUBLECOLT)|| + WeaponSelectOk(WEAPON_COLT)|| + WeaponSelectOk(WEAPON_KNIFE); + break; + case WEAPON_IRONCANNON: + WeaponSelectOk(WEAPON_ROCKETLAUNCHER)|| + WeaponSelectOk(WEAPON_GRENADELAUNCHER)|| + WeaponSelectOk(WEAPON_MINIGUN)|| + WeaponSelectOk(WEAPON_TOMMYGUN)|| + WeaponSelectOk(WEAPON_DOUBLESHOTGUN)|| + WeaponSelectOk(WEAPON_SINGLESHOTGUN)|| + WeaponSelectOk(WEAPON_DOUBLECOLT)|| + WeaponSelectOk(WEAPON_COLT)|| + WeaponSelectOk(WEAPON_KNIFE); + break; + case WEAPON_ROCKETLAUNCHER: + case WEAPON_GRENADELAUNCHER: + WeaponSelectOk(WEAPON_ROCKETLAUNCHER)|| + WeaponSelectOk(WEAPON_GRENADELAUNCHER)|| + WeaponSelectOk(WEAPON_MINIGUN)|| + WeaponSelectOk(WEAPON_TOMMYGUN)|| + WeaponSelectOk(WEAPON_DOUBLESHOTGUN)|| + WeaponSelectOk(WEAPON_SINGLESHOTGUN)|| + WeaponSelectOk(WEAPON_DOUBLECOLT)|| + WeaponSelectOk(WEAPON_COLT)|| + WeaponSelectOk(WEAPON_KNIFE); + break; + case WEAPON_LASER: case WEAPON_FLAMER: case WEAPON_CHAINSAW: + WeaponSelectOk(WEAPON_LASER)|| + WeaponSelectOk(WEAPON_FLAMER)|| + WeaponSelectOk(WEAPON_MINIGUN)|| + WeaponSelectOk(WEAPON_TOMMYGUN)|| + WeaponSelectOk(WEAPON_DOUBLESHOTGUN)|| + WeaponSelectOk(WEAPON_SINGLESHOTGUN)|| + WeaponSelectOk(WEAPON_DOUBLECOLT)|| + WeaponSelectOk(WEAPON_COLT)|| + WeaponSelectOk(WEAPON_KNIFE); + break; + default: + WeaponSelectOk(WEAPON_KNIFE); + ASSERT(FALSE); + } + }; + + // does weapon have ammo + BOOL HasAmmo(WeaponType EwtWeapon) { + switch (EwtWeapon) { + case WEAPON_KNIFE: case WEAPON_COLT: case WEAPON_DOUBLECOLT: return TRUE; + case WEAPON_SINGLESHOTGUN: return (m_iShells>0); + case WEAPON_DOUBLESHOTGUN: return (m_iShells>1); + case WEAPON_TOMMYGUN: return (m_iBullets>0); + case WEAPON_SNIPER: return (m_iSniperBullets>0); + case WEAPON_MINIGUN: return (m_iBullets>0); + case WEAPON_ROCKETLAUNCHER: return (m_iRockets>0); + case WEAPON_GRENADELAUNCHER: return (m_iGrenades>0); + case WEAPON_FLAMER: return (m_iNapalm>0); + case WEAPON_CHAINSAW: return TRUE; + case WEAPON_LASER: return (m_iElectricity>0); + case WEAPON_IRONCANNON: return (m_iIronBalls>0); + } + return FALSE; + }; + + /* + * >>>--- DEFAULT ANIM ---<<< + */ + void PlayDefaultAnim(void) { + switch(m_iCurrentWeapon) { + case WEAPON_NONE: + break; + case WEAPON_KNIFE: + switch (m_iKnifeStand) { + case 1: m_moWeapon.PlayAnim(KNIFE_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + case 3: m_moWeapon.PlayAnim(KNIFE_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + default: ASSERTALWAYS("Unknown knife stand."); + } + break; + case WEAPON_DOUBLECOLT: + m_moWeaponSecond.PlayAnim(COLT_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); + case WEAPON_COLT: + m_moWeapon.PlayAnim(COLT_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + case WEAPON_SINGLESHOTGUN: + m_moWeapon.PlayAnim(SINGLESHOTGUN_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + case WEAPON_DOUBLESHOTGUN: + m_moWeapon.PlayAnim(DOUBLESHOTGUN_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + case WEAPON_TOMMYGUN: + m_moWeapon.PlayAnim(TOMMYGUN_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + case WEAPON_SNIPER: + m_moWeapon.PlayAnim(SNIPER_ANIM_WAIT01, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + case WEAPON_MINIGUN: + m_moWeapon.PlayAnim(MINIGUN_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + case WEAPON_ROCKETLAUNCHER: + m_moWeapon.PlayAnim(ROCKETLAUNCHER_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + case WEAPON_GRENADELAUNCHER: + m_moWeapon.PlayAnim(GRENADELAUNCHER_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; +/* + case WEAPON_PIPEBOMB: + if (m_bPipeBombDropped) { + m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_STICKTHROWWAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + } else { + m_moWeapon.PlayAnim(HANDWITHBOMB_ANIM_BOMBWAIT2, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); + m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_STICKWAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + }*/ + case WEAPON_FLAMER: + m_moWeapon.PlayAnim(FLAMER_ANIM_WAIT01, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + case WEAPON_CHAINSAW: + m_moWeapon.PlayAnim(CHAINSAW_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + case WEAPON_LASER: + m_moWeapon.PlayAnim(LASER_ANIM_WAIT01, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; +/* + case WEAPON_GHOSTBUSTER: + m_moWeapon.PlayAnim(GHOSTBUSTER_ANIM_WAIT03, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + */ + case WEAPON_IRONCANNON: +// case WEAPON_NUKECANNON: + m_moWeapon.PlayAnim(CANNON_ANIM_WAIT01, AOF_LOOPING|AOF_NORESTART|AOF_SMOOTHCHANGE); break; + default: + ASSERTALWAYS("Unknown weapon."); + } + }; + + /* + * >>>--- WEAPON BORING ---<<< + */ + FLOAT KnifeBoring(void) { + // play boring anim + INDEX iAnim; + switch (m_iKnifeStand) { + case 1: iAnim = KNIFE_ANIM_WAIT1; break; + case 3: iAnim = KNIFE_ANIM_WAIT1; break; + } + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + + FLOAT ColtBoring(void) { + // play boring anim + INDEX iAnim; + switch (IRnd()%2) { + case 0: iAnim = COLT_ANIM_WAIT3; break; + case 1: iAnim = COLT_ANIM_WAIT4; break; + } + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + + FLOAT DoubleColtBoring(void) { + // play boring anim for one colt + INDEX iAnim; + switch (IRnd()%2) { + case 0: iAnim = COLT_ANIM_WAIT3; break; + case 1: iAnim = COLT_ANIM_WAIT4; break; + } + if (IRnd()&1) { + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + } else { + m_moWeaponSecond.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeaponSecond.GetAnimLength(iAnim); + } + }; + + FLOAT SingleShotgunBoring(void) { + // play boring anim + INDEX iAnim; + switch (IRnd()%2) { + case 0: iAnim = SINGLESHOTGUN_ANIM_WAIT2; break; + case 1: iAnim = SINGLESHOTGUN_ANIM_WAIT3; break; + } + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + + FLOAT DoubleShotgunBoring(void) { + // play boring anim + INDEX iAnim; + switch (IRnd()%3) { + case 0: iAnim = DOUBLESHOTGUN_ANIM_WAIT2; break; + case 1: iAnim = DOUBLESHOTGUN_ANIM_WAIT3; break; + case 2: iAnim = DOUBLESHOTGUN_ANIM_WAIT4; break; + } + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + + FLOAT TommyGunBoring(void) { + // play boring anim + INDEX iAnim; + switch (IRnd()%2) { + case 0: iAnim = TOMMYGUN_ANIM_WAIT2; break; + case 1: iAnim = TOMMYGUN_ANIM_WAIT3; break; + } + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + + FLOAT SniperBoring(void) { + // play boring anim + INDEX iAnim; + iAnim = SNIPER_ANIM_WAIT01; + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + + FLOAT MiniGunBoring(void) { + // play boring anim + INDEX iAnim; + switch (IRnd()%3) { + case 0: iAnim = MINIGUN_ANIM_WAIT2; break; + case 1: iAnim = MINIGUN_ANIM_WAIT3; break; + case 2: iAnim = MINIGUN_ANIM_WAIT4; break; + } + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + + FLOAT RocketLauncherBoring(void) { + // play boring anim + m_moWeapon.PlayAnim(ROCKETLAUNCHER_ANIM_WAIT2, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(ROCKETLAUNCHER_ANIM_WAIT2); + }; + + FLOAT GrenadeLauncherBoring(void) { + // play boring anim + m_moWeapon.PlayAnim(GRENADELAUNCHER_ANIM_WAIT2, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(GRENADELAUNCHER_ANIM_WAIT2); + }; + +/* + FLOAT PipeBombBoring(void) { + if (IRnd()&1 && !m_bPipeBombDropped) { + // play boring anim for hand with bomb + INDEX iAnim; + switch (IRnd()%4) { + case 0: iAnim = HANDWITHBOMB_ANIM_BOMBWAIT1; break; + case 1: iAnim = HANDWITHBOMB_ANIM_BOMBWAIT3; break; + case 2: iAnim = HANDWITHBOMB_ANIM_BOMBWAIT4; break; + case 3: iAnim = HANDWITHBOMB_ANIM_BOMBWAIT5; break; + } + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + } else { + // play boring anim for hand with stick + INDEX iAnimSecond; + if (m_bPipeBombDropped) { + switch (IRnd()%2) { + case 0: iAnimSecond = HANDWITHSTICK_ANIM_STICKTHROWWAIT2; break; + case 1: iAnimSecond = HANDWITHSTICK_ANIM_STICKTHROWWAIT3; break; + } + } else { + switch (IRnd()%3) { + case 0: iAnimSecond = HANDWITHSTICK_ANIM_STICKWAIT2; break; + case 1: iAnimSecond = HANDWITHSTICK_ANIM_STICKWAIT3; break; + case 2: iAnimSecond = HANDWITHSTICK_ANIM_STICKWAIT4; break; + } + } + m_moWeaponSecond.PlayAnim(iAnimSecond, AOF_SMOOTHCHANGE); + return m_moWeaponSecond.GetAnimLength(iAnimSecond); + } + };*/ + + FLOAT FlamerBoring(void) { + // play boring anim + INDEX iAnim; + switch (IRnd()%4) { + case 0: iAnim = FLAMER_ANIM_WAIT02; break; + case 1: iAnim = FLAMER_ANIM_WAIT03; break; + case 2: iAnim = FLAMER_ANIM_WAIT04; break; + case 3: iAnim = FLAMER_ANIM_WAIT05; break; + } + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + + FLOAT ChainsawBoring(void) { + // play boring anim + INDEX iAnim; + switch (IRnd()%3) { + case 0: iAnim = CHAINSAW_ANIM_WAIT2; break; + case 1: iAnim = CHAINSAW_ANIM_WAIT3; break; + case 2: iAnim = CHAINSAW_ANIM_WAIT4; break; + } + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + + FLOAT LaserBoring(void) { + // play boring anim + INDEX iAnim; + iAnim = LASER_ANIM_WAIT02; + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + + /* + FLOAT GhostBusterBoring(void) { + // play boring anim + INDEX iAnim; + switch (IRnd()%3) { + case 0: iAnim = GHOSTBUSTER_ANIM_WAIT01; break; + case 1: iAnim = GHOSTBUSTER_ANIM_WAIT02; break; + case 2: iAnim = GHOSTBUSTER_ANIM_WAIT04; break; + } + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + */ + + FLOAT CannonBoring(void) { + // play boring anim + INDEX iAnim; + switch (IRnd()%3) { + case 0: iAnim = CANNON_ANIM_WAIT02; break; + case 1: iAnim = CANNON_ANIM_WAIT03; break; + case 2: iAnim = CANNON_ANIM_WAIT04; break; + } + m_moWeapon.PlayAnim(iAnim, AOF_SMOOTHCHANGE); + return m_moWeapon.GetAnimLength(iAnim); + }; + + // find the weapon position in the remap array + WeaponType FindRemapedPos(WeaponType wt) + { + for (INDEX i=0; i<18; i++) + { + if (aiWeaponsRemap[i]==wt) { + return (WeaponType)i; + } + } + ASSERT("Non-existant weapon in remap array!"); + return (WeaponType)0; + } + + // get secondary weapon for a given primary weapon + WeaponType PrimaryToSecondary(WeaponType wt) + { + if (wt==WEAPON_CHAINSAW) { + return WEAPON_KNIFE; + } else if (wt==WEAPON_DOUBLECOLT) { + return WEAPON_COLT; + } else if (wt==WEAPON_DOUBLESHOTGUN) { + return WEAPON_SINGLESHOTGUN; + } else if (wt==WEAPON_MINIGUN) { + return WEAPON_TOMMYGUN; + } else if (wt==WEAPON_ROCKETLAUNCHER) { + return WEAPON_GRENADELAUNCHER; + } else if (wt==WEAPON_SNIPER) { + return WEAPON_FLAMER; + } else { + return wt; + } + } + // get primary weapon for a given secondary weapon + WeaponType SecondaryToPrimary(WeaponType wt) + { + if (wt==WEAPON_KNIFE) { + return WEAPON_CHAINSAW; + } else if (wt==WEAPON_COLT) { + return WEAPON_DOUBLECOLT; + } else if (wt==WEAPON_SINGLESHOTGUN) { + return WEAPON_DOUBLESHOTGUN; + } else if (wt==WEAPON_TOMMYGUN) { + return WEAPON_MINIGUN; + } else if (wt==WEAPON_GRENADELAUNCHER) { + return WEAPON_ROCKETLAUNCHER; + } else if (wt==WEAPON_FLAMER) { + return WEAPON_SNIPER; + } else { + return wt; + } + } + + /* + * >>>--- WEAPON CHANGE FUNCTIONS ---<<< + */ + + // find first possible weapon in given direction +/* WeaponType FindWeaponInDirection(INDEX iDir) + { + WeaponType wtOrg = (WeaponType)m_iWantedWeapon; + WeaponType wt = wtOrg; + FOREVER { + (INDEX&)wt += iDir; + if (wtWEAPON_IRONCANNON) { + wt = WEAPON_KNIFE; + } + if (wt==wtOrg) { + break; + } + if ( ( ((1<<(wt-1))&m_iAvailableWeapons) && HasAmmo(wt)) ) { + return wt; + } + } + return m_iWantedWeapon; + }*/ + + + WeaponType FindWeaponInDirection(INDEX iDir) + { + INDEX wtOrg = FindRemapedPos(m_iWantedWeapon); + INDEX wti = wtOrg; + FOREVER { + (INDEX&)wti += iDir; + if (wti<1) { + wti = WEAPON_IRONCANNON; + } + if (wti>14) { + wti = WEAPON_KNIFE; + } + if (wti==wtOrg) { + break; + } + WeaponType wt = (WeaponType) aiWeaponsRemap[wti]; + if ( ( ((1<<(wt-1))&m_iAvailableWeapons) && HasAmmo(wt)) ) { + return wt; + } + } + return m_iWantedWeapon; + } + + // select new weapon + void SelectWeaponChange(INDEX iSelect) + { + WeaponType EwtTemp; + // mark that weapon change is required + m_tmWeaponChangeRequired = _pTimer->CurrentTick(); + + // if storing current weapon + if (iSelect==0) { + m_bChangeWeapon = TRUE; + m_iWantedWeapon = WEAPON_NONE; + return; + } + + // if restoring best weapon + if (iSelect==-4) { + SelectNewWeapon() ; + return; + } + + // if flipping weapon + if (iSelect==-3) { + EwtTemp = GetAltWeapon(m_iWantedWeapon); + + // if selecting previous weapon + } else if (iSelect==-2) { + EwtTemp = FindWeaponInDirection(-1); + + // if selecting next weapon + } else if (iSelect==-1) { + EwtTemp = FindWeaponInDirection(+1); + + // if selecting directly + } else { + // flip current weapon + if (iSelect == GetSelectedWeapon(m_iWantedWeapon)) { + EwtTemp = GetAltWeapon(m_iWantedWeapon); + + // change to wanted weapon + } else { + EwtTemp = GetStrongerWeapon(iSelect); + + // if weapon don't exist or don't have ammo flip it + if ( !((1<<(EwtTemp-1))&m_iAvailableWeapons) || !HasAmmo(EwtTemp)) { + EwtTemp = GetAltWeapon(EwtTemp); + } + } + } + + // wanted weapon exist and has ammo + BOOL bChange = ( ((1<<(EwtTemp-1))&m_iAvailableWeapons) && HasAmmo(EwtTemp)); + if (bChange) { + m_iWantedWeapon = EwtTemp; + m_bChangeWeapon = TRUE; + } + }; + + + + void MinigunSmoke() + { + if( !hud_bShowWeapon) + { + return; + } + // smoke + CPlayer &pl = (CPlayer&)*m_penPlayer; + if( pl.m_pstState!=PST_DIVE) + { + BOOL b3rdPersonView = TRUE; + if(pl.m_penCamera==NULL && pl.m_pen3rdPersonView==NULL) + { + b3rdPersonView = FALSE; + } + + INDEX ctBulletsFired = ClampUp(m_iBulletsOnFireStart-m_iBullets, INDEX(200)); + for( INDEX iSmoke=0; iSmokesld_vPos = plPipe.pl_PositionVector+pl.en_vCurrentTranslationAbsolute*iSmoke*_pTimer->TickQuantum; + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + psldSmoke->sld_vUp = vUp; + psldSmoke->sld_tmLaunch = _pTimer->CurrentTick()+iSmoke*_pTimer->TickQuantum; + psldSmoke->sld_estType = ESL_BULLET_SMOKE; + psldSmoke->sld_fSize = 0.75f+ctBulletsFired/50.0f; + FLOAT3D vSpeedRelative = FLOAT3D(-0.06f, FRnd()/4.0f, -0.06f); + psldSmoke->sld_vSpeed = vSpeedRelative*m+pl.en_vCurrentTranslationAbsolute; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + } + }; + + BOOL SniperZoomDiscrete(INDEX iDirection, BOOL &bZoomChanged) + { + bZoomChanged = FALSE; + // zoom in one zoom level + if (iDirection>0) { + for (INDEX i=0; i0; i--) { + if (afSniperZoom[2*i]>m_fSniperFOV) { + m_fSniperFOV=afSniperZoom[2*i]; + m_fSniperFOVlast=m_fSniperFOV; + bZoomChanged = TRUE; + break; + } + } + } + if (m_fSniperFOV<90.0f) { + m_bSniping = TRUE; + } + else { + m_bSniping = FALSE; + } + return m_bSniping; + }; + +procedures: + /* + * >>>--- WEAPON CHANGE PROCEDURE ---<<< + */ + ChangeWeapon() { + // if really changing weapon, make sure sniping is off and notify owner of the change + if (m_iCurrentWeapon!=m_iWantedWeapon) { + m_fSniperFOV = m_fSniperFOVlast = m_fSniperMaxFOV; + m_bSniping = FALSE; + m_penPlayer->SendEvent(EWeaponChanged()); + } + // weapon is changed + m_bChangeWeapon = FALSE; + // if this is not current weapon change it + if (m_iCurrentWeapon!=m_iWantedWeapon) { +/* + // iron/nuke cannon changing is special + if( (m_iCurrentWeapon == WEAPON_IRONCANNON) && (m_iWantedWeapon == WEAPON_NUKECANNON) ) + { + autocall ChangeToNukeCannon() EEnd; + // mark that weapon change has ended + m_tmWeaponChangeRequired = 0.0f; + jump Idle(); + } + else if( (m_iCurrentWeapon == WEAPON_NUKECANNON) && (m_iWantedWeapon == WEAPON_IRONCANNON) ) + { + autocall ChangeToIronCannon() EEnd; + // mark that weapon change has ended + m_tmWeaponChangeRequired = 0.0f; + jump Idle(); + } + */ + + // store current weapon + m_iPreviousWeapon = m_iCurrentWeapon; + autocall PutDown() EEnd; + // set new weapon + m_iCurrentWeapon = m_iWantedWeapon; + // remember current weapon for console usage + wpn_iCurrent = m_iCurrentWeapon; + autocall BringUp() EEnd; + // start engine sound if chainsaw + if (m_iCurrentWeapon==WEAPON_CHAINSAW) { + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.m_soWeaponAmbient.Set3DParameters(30.0f, 3.0f, 1.0f, 1.0f); + PlaySound(pl.m_soWeaponAmbient, SOUND_CS_IDLE, SOF_3D|SOF_VOLUMETRIC|SOF_LOOP|SOF_SMOOTHCHANGE); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("ChainsawIdle");} + } + + // knife change stand + } else if (m_iWantedWeapon == WEAPON_KNIFE) { + // mark that weapon change has ended + m_tmWeaponChangeRequired = 0.0f; + autocall ChangeKnifeStand() EEnd; +/* // pipebomb reload + } else if (m_iWantedWeapon == WEAPON_PIPEBOMB) { + // mark that weapon change has ended + m_tmWeaponChangeRequired = 0.0f; + jump Reload(); + */ + } + jump Idle(); + }; + + + // put weapon down + PutDown() { + // start weapon put down animation + switch (m_iCurrentWeapon) { + case WEAPON_NONE: + break; + // knife have different stands + case WEAPON_KNIFE: + if (m_iKnifeStand==1) { + m_iAnim = KNIFE_ANIM_PULLOUT; + } else if (m_iKnifeStand==3) { + m_iAnim = KNIFE_ANIM_PULLOUT; + } + break; + case WEAPON_DOUBLECOLT: case WEAPON_COLT: + m_iAnim = COLT_ANIM_DEACTIVATE; + break; + case WEAPON_SINGLESHOTGUN: + m_iAnim = SINGLESHOTGUN_ANIM_DEACTIVATE; + break; + case WEAPON_DOUBLESHOTGUN: + m_iAnim = DOUBLESHOTGUN_ANIM_DEACTIVATE; + break; + case WEAPON_TOMMYGUN: + m_iAnim = TOMMYGUN_ANIM_DEACTIVATE; + break; + case WEAPON_SNIPER: + m_iAnim = SNIPER_ANIM_DEACTIVATE; + break; + case WEAPON_MINIGUN: + m_iAnim = MINIGUN_ANIM_DEACTIVATE; + break; + case WEAPON_ROCKETLAUNCHER: + m_iAnim = ROCKETLAUNCHER_ANIM_DEACTIVATE; + break; + case WEAPON_GRENADELAUNCHER: + m_iAnim = GRENADELAUNCHER_ANIM_DEACTIVATE; + break; +/* case WEAPON_PIPEBOMB: + m_iAnim = HANDWITHBOMB_ANIM_DEACTIVATE; + break;*/ + case WEAPON_FLAMER: + m_iAnim = FLAMER_ANIM_DEACTIVATE; + break; + case WEAPON_CHAINSAW: { + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeaponAmbient, SOUND_CS_BRINGDOWN, SOF_3D|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_StopEffect("ChainsawIdle");} + m_iAnim = CHAINSAW_ANIM_DEACTIVATE; + break; } + case WEAPON_LASER: + m_iAnim = LASER_ANIM_DEACTIVATE; + break; +/* + case WEAPON_GHOSTBUSTER: + m_iAnim = GHOSTBUSTER_ANIM_DEACTIVATE; + break; + */ + case WEAPON_IRONCANNON: +// case WEAPON_NUKECANNON: + m_iAnim = CANNON_ANIM_DEACTIVATE; + break; + default: ASSERTALWAYS("Unknown weapon."); + } + // start animator + CPlayerAnimator &plan = (CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator; + plan.BodyPushAnimation(); + if (m_iCurrentWeapon==WEAPON_NONE) { + return EEnd(); + } + + // --->>> COLT -> DOUBLE COLT SPECIFIC <<<--- + if (m_iCurrentWeapon==WEAPON_COLT && m_iWantedWeapon==WEAPON_DOUBLECOLT) { + return EEnd(); + } + + // --->>> DOUBLE COLT SPECIFIC <<<--- + if (m_iCurrentWeapon==WEAPON_DOUBLECOLT) { + m_moWeaponSecond.PlayAnim(m_iAnim, 0); + } + + // --->>> DOUBLE COLT -> COLT SPECIFIC <<<--- + if (m_iCurrentWeapon==WEAPON_DOUBLECOLT && m_iWantedWeapon==WEAPON_COLT) { + autowait(m_moWeapon.GetAnimLength(m_iAnim)); + return EEnd(); + } + +/* + // --->>> PIPEBOMB SPECIFIC <<<--- + if (m_iCurrentWeapon==WEAPON_PIPEBOMB) { + m_moWeapon.PlayAnim(m_iAnim, 0); + m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_DEACTIVATE, 0); + autowait(Max(m_moWeapon.GetAnimLength(m_iAnim), m_moWeaponSecond.GetAnimLength(HANDWITHSTICK_ANIM_DEACTIVATE))); + return EEnd(); + } +*/ + + // reload colts automagicaly when puting them away + BOOL bNowColt = m_iCurrentWeapon==WEAPON_COLT || m_iCurrentWeapon==WEAPON_DOUBLECOLT; + BOOL bWantedColt = m_iWantedWeapon==WEAPON_COLT || m_iWantedWeapon==WEAPON_DOUBLECOLT; + if (bNowColt&&!bWantedColt) { + m_iColtBullets = 6; + } + + m_moWeapon.PlayAnim(m_iAnim, 0); + autowait(m_moWeapon.GetAnimLength(m_iAnim)); + return EEnd(); + }; + + // bring up weapon + BringUp() { + // reset weapon draw offset + ResetWeaponMovingOffset(); + // set weapon model for current weapon + SetCurrentWeaponModel(); + // start current weapon bring up animation + switch (m_iCurrentWeapon) { + case WEAPON_KNIFE: + m_iAnim = KNIFE_ANIM_PULL; + m_iKnifeStand = 1; + break; + case WEAPON_COLT: case WEAPON_DOUBLECOLT: + m_iAnim = COLT_ANIM_ACTIVATE; + SetFlare(0, FLARE_REMOVE); + SetFlare(1, FLARE_REMOVE); + break; + case WEAPON_SINGLESHOTGUN: + m_iAnim = SINGLESHOTGUN_ANIM_ACTIVATE; + SetFlare(0, FLARE_REMOVE); + break; + case WEAPON_DOUBLESHOTGUN: + m_iAnim = DOUBLESHOTGUN_ANIM_ACTIVATE; + SetFlare(0, FLARE_REMOVE); + break; + case WEAPON_TOMMYGUN: + m_iAnim = TOMMYGUN_ANIM_ACTIVATE; + SetFlare(0, FLARE_REMOVE); + break; + case WEAPON_SNIPER: + m_iAnim = SNIPER_ANIM_ACTIVATE; + SetFlare(0, FLARE_REMOVE); + break; + case WEAPON_MINIGUN: { + CAttachmentModelObject *amo = m_moWeapon.GetAttachmentModel(MINIGUN_ATTACHMENT_BARRELS); + m_aMiniGunLast = m_aMiniGun = amo->amo_plRelative.pl_OrientationAngle(3); + m_iAnim = MINIGUN_ANIM_ACTIVATE; + SetFlare(0, FLARE_REMOVE); + break; } + case WEAPON_ROCKETLAUNCHER: + m_iAnim = ROCKETLAUNCHER_ANIM_ACTIVATE; + break; + case WEAPON_GRENADELAUNCHER: + m_iAnim = GRENADELAUNCHER_ANIM_ACTIVATE; + break; +/* case WEAPON_PIPEBOMB: + m_iAnim = HANDWITHBOMB_ANIM_ACTIVATE; + break;*/ + case WEAPON_FLAMER: + m_iAnim = FLAMER_ANIM_ACTIVATE; + break; + case WEAPON_CHAINSAW: { + m_iAnim = CHAINSAW_ANIM_ACTIVATE; + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.m_soWeaponAmbient.Set3DParameters(30.0f, 3.0f, 1.0f, 1.0f); + PlaySound(pl.m_soWeaponAmbient, SOUND_CS_BRINGUP, SOF_3D|SOF_VOLUMETRIC|SOF_LOOP); + break; } + case WEAPON_LASER: + m_iAnim = LASER_ANIM_ACTIVATE; + break; +/* case WEAPON_GHOSTBUSTER: + m_iAnim = GHOSTBUSTER_ANIM_ACTIVATE; + break; + */ + case WEAPON_IRONCANNON: +// case WEAPON_NUKECANNON: + m_iAnim = CANNON_ANIM_ACTIVATE; + break; + case WEAPON_NONE: + break; + default: ASSERTALWAYS("Unknown weapon."); + } + // start animator + CPlayerAnimator &plan = (CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator; + plan.BodyPullAnimation(); + + // --->>> DOUBLE COLT -> COLT SPECIFIC <<<--- + if (m_iPreviousWeapon==WEAPON_DOUBLECOLT && m_iCurrentWeapon==WEAPON_COLT) { + // mark that weapon change has ended + m_tmWeaponChangeRequired -= hud_tmWeaponsOnScreen/2; + return EEnd(); + } + + // --->>> DOUBLE COLT SPECIFIC <<<--- + if (m_iCurrentWeapon==WEAPON_DOUBLECOLT) { + m_moWeaponSecond.PlayAnim(m_iAnim, 0); + } + + // --->>> COLT -> COLT DOUBLE SPECIFIC <<<--- + if (m_iPreviousWeapon==WEAPON_COLT && m_iCurrentWeapon==WEAPON_DOUBLECOLT) { + autowait(m_moWeapon.GetAnimLength(m_iAnim)); + // mark that weapon change has ended + m_tmWeaponChangeRequired -= hud_tmWeaponsOnScreen/2; + return EEnd(); + } + + /* + // --->>> PIPEBOMB SPECIFIC <<<--- + if (m_iCurrentWeapon==WEAPON_PIPEBOMB) { + m_moWeapon.PlayAnim(m_iAnim, 0); + m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_ACTIVATE, 0); + autowait(Max(m_moWeapon.GetAnimLength(m_iAnim), m_moWeaponSecond.GetAnimLength(HANDWITHSTICK_ANIM_ACTIVATE))); + m_bPipeBombDropped = FALSE; + // mark that weapon change has ended + m_tmWeaponChangeRequired -= hud_tmWeaponsOnScreen/2; + return EEnd(); + } + */ + + m_moWeapon.PlayAnim(m_iAnim, 0); + autowait(m_moWeapon.GetAnimLength(m_iAnim)); + +/* + if( m_iCurrentWeapon == WEAPON_NUKECANNON) + { + autocall ChangeToNukeCannon() EEnd; + } + */ + + // mark that weapon change has ended + m_tmWeaponChangeRequired -= hud_tmWeaponsOnScreen/2; + + return EEnd(); + }; + + + /* + * >>>--- FIRE WEAPON ---<<< + */ + Fire() + { + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon0, SOUND_SILENCE, SOF_3D|SOF_VOLUMETRIC); // stop possible sounds + // force ending of weapon change + m_tmWeaponChangeRequired = 0; + + m_bFireWeapon = TRUE; + m_bHasAmmo = HasAmmo(m_iCurrentWeapon); + + // if has no ammo select new weapon + if (!m_bHasAmmo) { + SelectNewWeapon(); + jump Idle(); + } + + // setup 3D sound parameters + Setup3DSoundParameters(); + + // start weapon firing animation for continuous firing + if (m_iCurrentWeapon==WEAPON_MINIGUN) { + jump MiniGunSpinUp(); + } else if (m_iCurrentWeapon==WEAPON_FLAMER) { + jump FlamerStart(); + } else if (m_iCurrentWeapon==WEAPON_CHAINSAW) { + jump ChainsawFire(); +/* } else if (m_iCurrentWeapon==WEAPON_GHOSTBUSTER) { + autocall GhostBusterStart() EEnd; */ + } else if (m_iCurrentWeapon==WEAPON_LASER) { + GetAnimator()->FireAnimation(BODY_ANIM_SHOTGUN_FIRESHORT, AOF_LOOPING); + } else if (m_iCurrentWeapon==WEAPON_TOMMYGUN) { + autocall TommyGunStart() EEnd; + } else if ((m_iCurrentWeapon==WEAPON_IRONCANNON) /*|| (m_iCurrentWeapon==WEAPON_NUKECANNON)*/) { + jump CannonFireStart(); + } + + // clear last lerped bullet position + m_iLastBulletPosition = FLOAT3D(32000.0f, 32000.0f, 32000.0f); + + // reset laser barrel (to start shooting always from left up barrel) + m_iLaserBarrel = 0; + + while (HoldingFire() && m_bHasAmmo) { + // boring animation + ((CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator).m_fLastActionTime = _pTimer->CurrentTick(); + wait() { + on (EBegin) : { + // fire one shot + switch (m_iCurrentWeapon) { + case WEAPON_KNIFE: call SwingKnife(); break; + case WEAPON_COLT: call FireColt(); break; + case WEAPON_DOUBLECOLT: call FireDoubleColt(); break; + case WEAPON_SINGLESHOTGUN: call FireSingleShotgun(); break; + case WEAPON_DOUBLESHOTGUN: call FireDoubleShotgun(); break; + case WEAPON_TOMMYGUN: call FireTommyGun(); break; + case WEAPON_SNIPER: call FireSniper(); break; + case WEAPON_ROCKETLAUNCHER: call FireRocketLauncher(); break; + case WEAPON_GRENADELAUNCHER: call FireGrenadeLauncher(); break; + case WEAPON_LASER: call FireLaser(); break; + default: ASSERTALWAYS("Unknown weapon."); + } + resume; + } + on (EEnd) : { + stop; + } + } + } + + // stop weapon firing animation for continuous firing + switch (m_iCurrentWeapon) { + case WEAPON_TOMMYGUN: { jump TommyGunStop(); break; } + case WEAPON_MINIGUN: { jump MiniGunSpinDown(); break; } + case WEAPON_FLAMER: { jump FlamerStop(); break; } +// case WEAPON_GHOSTBUSTER: { jump GhostBusterStop(); break; } + case WEAPON_LASER: { + GetAnimator()->FireAnimationOff(); + jump Idle(); + } + default: { jump Idle(); } + } + }; + + + // ***************** SWING KNIFE ***************** + SwingKnife() { + INDEX iSwing; + + // animator swing + GetAnimator()->FireAnimation(BODY_ANIM_KNIFE_ATTACK, 0); + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + // depending on stand choose random attack + switch (m_iKnifeStand) { + case 1: + iSwing = IRnd()%2; + switch (iSwing) { + case 0: m_iAnim = KNIFE_ANIM_ATTACK01; m_fAnimWaitTime = 0.25f; + PlaySound(pl.m_soWeapon0, SOUND_KNIFE_BACK, SOF_3D|SOF_VOLUMETRIC); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Knife_back");} + break; + case 1: m_iAnim = KNIFE_ANIM_ATTACK02; m_fAnimWaitTime = 0.35f; + PlaySound(pl.m_soWeapon1, SOUND_KNIFE_BACK, SOF_3D|SOF_VOLUMETRIC); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Knife_back");} + break; + } + break; + case 3: + iSwing = IRnd()%2; + switch (iSwing) { + case 0: m_iAnim = KNIFE_ANIM_ATTACK01; m_fAnimWaitTime = 0.50f; + PlaySound(pl.m_soWeapon1, SOUND_KNIFE_BACK, SOF_3D|SOF_VOLUMETRIC); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Knife_back");} + break; + case 1: m_iAnim = KNIFE_ANIM_ATTACK02; m_fAnimWaitTime = 0.50f; + PlaySound(pl.m_soWeapon3, SOUND_KNIFE_BACK, SOF_3D|SOF_VOLUMETRIC); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Knife_back");} + break; + } + break; + } + m_moWeapon.PlayAnim(m_iAnim, 0); + if (CutWithKnife(0, 0, 3.0f, 2.0f, 0.5f, ((GetSP()->sp_bCooperative) ? 100.0f : 50.0f))) { + autowait(m_fAnimWaitTime); + } else if (TRUE) { + autowait(m_fAnimWaitTime/2); + CutWithKnife(0, 0, 3.0f, 2.0f, 0.5f, ((GetSP()->sp_bCooperative) ? 100.0f : 50.0f)); + autowait(m_fAnimWaitTime/2); + } + + if (m_moWeapon.GetAnimLength(m_iAnim)-m_fAnimWaitTime>=_pTimer->TickQuantum) { + autowait(m_moWeapon.GetAnimLength(m_iAnim)-m_fAnimWaitTime); + } + return EEnd(); + }; + + // ***************** FIRE COLT ***************** + FireColt() { + GetAnimator()->FireAnimation(BODY_ANIM_COLT_FIRERIGHT, 0); + + // fire bullet + FireOneBullet(wpn_fFX[WEAPON_COLT], wpn_fFY[WEAPON_COLT], 500.0f, + ((GetSP()->sp_bCooperative) ? 10.0f : 20.0f)); + + + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Colt_fire");} + DoRecoil(); + SpawnRangeSound(40.0f); + m_iColtBullets--; + SetFlare(0, FLARE_ADD); + PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0); + + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon0, SOUND_COLT_FIRE, SOF_3D|SOF_VOLUMETRIC); + + /* + if( pl.m_pstState!=PST_DIVE) + { + // smoke + ShellLaunchData &sldRight = pl.m_asldData[pl.m_iFirstEmptySLD]; + sldRight.sld_vPos = FLOAT3D(afRightColtPipe[0], afRightColtPipe[1], afRightColtPipe[2]); + sldRight.sld_tmLaunch = _pTimer->CurrentTick(); + sldRight.sld_estType = ESL_COLT_SMOKE; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + */ + + // random colt fire + INDEX iAnim; + switch (IRnd()%3) { + case 0: iAnim = COLT_ANIM_FIRE1; break; + case 1: iAnim = COLT_ANIM_FIRE2; break; + case 2: iAnim = COLT_ANIM_FIRE3; break; + } + m_moWeapon.PlayAnim(iAnim, 0); + autowait(m_moWeapon.GetAnimLength(iAnim)-0.05f); + m_moWeapon.PlayAnim(COLT_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART); + + // no more bullets in colt -> reload + if (m_iColtBullets == 0) { + jump ReloadColt(); + } + return EEnd(); + }; + + // reload colt + ReloadColt() { + if (m_iColtBullets>=6) { + return EEnd(); + } + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon1, SOUND_COLT_RELOAD, SOF_3D|SOF_VOLUMETRIC); + + m_moWeapon.PlayAnim(COLT_ANIM_RELOAD, 0); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Colt_reload");} + autowait(m_moWeapon.GetAnimLength(COLT_ANIM_RELOAD)); + m_iColtBullets = 6; + return EEnd(); + }; + + // ***************** FIRE DOUBLE COLT ***************** + FireDoubleColt() { + // fire first colt - one bullet less in colt + GetAnimator()->FireAnimation(BODY_ANIM_COLT_FIRERIGHT, 0); + FireOneBullet(wpn_fFX[WEAPON_DOUBLECOLT], wpn_fFY[WEAPON_DOUBLECOLT], 500.0f, 10.0f); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Colt_fire");} + + /* + CPlayer &pl1 = (CPlayer&)*m_penPlayer; + if( pl1.m_pstState!=PST_DIVE) + { + // smoke + ShellLaunchData &sldRight = pl1.m_asldData[pl1.m_iFirstEmptySLD]; + sldRight.sld_vPos = FLOAT3D(afRightColtPipe[0], afRightColtPipe[1], afRightColtPipe[2]); + sldRight.sld_tmLaunch = _pTimer->CurrentTick(); + sldRight.sld_estType = ESL_COLT_SMOKE; + pl1.m_iFirstEmptySLD = (pl1.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + */ + + DoRecoil(); + SpawnRangeSound(50.0f); + m_iColtBullets--; + SetFlare(0, FLARE_ADD); + PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0); + // sound + CPlayer &plSnd = (CPlayer&)*m_penPlayer; + PlaySound(plSnd.m_soWeapon0, SOUND_COLT_FIRE, SOF_3D|SOF_VOLUMETRIC); + + // random colt fire + switch (IRnd()%3) { + case 0: m_iAnim = COLT_ANIM_FIRE1; break; + case 1: m_iAnim = COLT_ANIM_FIRE2; break; + case 2: m_iAnim = COLT_ANIM_FIRE3; break; + } + m_moWeapon.PlayAnim(m_iAnim, 0); // play first colt anim + autowait(m_moWeapon.GetAnimLength(m_iAnim)/2); // wait half of the anim + + // fire second colt + GetAnimator()->FireAnimation(BODY_ANIM_COLT_FIRELEFT, 0); + m_bMirrorFire = TRUE; + FireOneBullet(wpn_fFX[WEAPON_DOUBLECOLT], wpn_fFY[WEAPON_DOUBLECOLT], 500.0f, 10.0f); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Colt_fire");} + + /* + CPlayer &pl2 = (CPlayer&)*m_penPlayer; + if( pl2.m_pstState!=PST_DIVE) + { + // smoke + ShellLaunchData &sldLeft = pl2.m_asldData[pl2.m_iFirstEmptySLD]; + sldLeft.sld_vPos = FLOAT3D(-afRightColtPipe[0], afRightColtPipe[1], afRightColtPipe[2]); + sldLeft.sld_tmLaunch = _pTimer->CurrentTick(); + sldLeft.sld_estType = ESL_COLT_SMOKE; + pl2.m_iFirstEmptySLD = (pl2.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + */ + + DoRecoil(); + m_iSecondFlare = FLARE_ADD; + ((CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator).m_iSecondFlare = FLARE_ADD; + PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0); + m_bMirrorFire = FALSE; + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon1, SOUND_COLT_FIRE, SOF_3D|SOF_VOLUMETRIC); + + m_moWeaponSecond.PlayAnim(m_iAnim, 0); + autowait(m_moWeapon.GetAnimLength(m_iAnim)/2); // wait half of the anim + + // no more bullets in colt -> reload + if (m_iColtBullets == 0) { + jump ReloadDoubleColt(); + } + return EEnd(); + }; + + // reload double colt + ReloadDoubleColt() { + if (m_iColtBullets>=6) { + return EEnd(); + } + m_moWeapon.PlayAnim(COLT_ANIM_RELOAD, 0); + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon2, SOUND_COLT_RELOAD, SOF_3D|SOF_VOLUMETRIC); + // wait half of reload time + autowait(m_moWeapon.GetAnimLength(COLT_ANIM_RELOAD)/2); + + m_moWeaponSecond.PlayAnim(COLT_ANIM_RELOAD, 0); + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon3, SOUND_COLT_RELOAD, SOF_3D|SOF_VOLUMETRIC); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Colt_reload");} + + // wait second halt minus half shortest fire animation + autowait(m_moWeapon.GetAnimLength(COLT_ANIM_RELOAD)-0.25f); + + m_iColtBullets = 6; + return EEnd(); + }; + + // ***************** FIRE SINGLESHOTGUN ***************** + FireSingleShotgun() { + // fire one shell + if (m_iShells>0) { + GetAnimator()->FireAnimation(BODY_ANIM_SHOTGUN_FIRELONG, 0); + FireBullets(wpn_fFX[WEAPON_SINGLESHOTGUN], wpn_fFY[WEAPON_SINGLESHOTGUN], + 500.0f, 10.0f, 7, afSingleShotgunPellets, 0.2f, 0.03f); + DoRecoil(); + SpawnRangeSound(60.0f); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Snglshotgun_fire");} + DecAmmo(m_iShells, 1); + SetFlare(0, FLARE_ADD); + PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0); + m_moWeapon.PlayAnim(GetSP()->sp_bCooperative ? SINGLESHOTGUN_ANIM_FIRE1 : SINGLESHOTGUN_ANIM_FIRE1FAST, 0); + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon0, SOUND_SINGLESHOTGUN_FIRE, SOF_3D|SOF_VOLUMETRIC); + + if( hud_bShowWeapon) + { + if( pl.m_pstState==PST_DIVE) + { + // bubble + ShellLaunchData &sldBubble = pl.m_asldData[pl.m_iFirstEmptySLD]; + CPlacement3D plShell; + CalcWeaponPosition(FLOAT3D(afSingleShotgunShellPos[0], + afSingleShotgunShellPos[1], afSingleShotgunShellPos[2]), plShell, FALSE); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, plShell.pl_OrientationAngle); + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + sldBubble.sld_vPos = plShell.pl_PositionVector; + sldBubble.sld_vUp = vUp; + sldBubble.sld_tmLaunch = _pTimer->CurrentTick(); + sldBubble.sld_estType = ESL_BUBBLE; + FLOAT3D vSpeedRelative = FLOAT3D(0.3f, 0.0f, 0.0f); + sldBubble.sld_vSpeed = vSpeedRelative*m; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + else + { + // smoke + ShellLaunchData &sldPipe1 = pl.m_asldData[pl.m_iFirstEmptySLD]; + CPlacement3D plPipe; + CalcWeaponPosition(FLOAT3D(afSingleShotgunPipe[0], afSingleShotgunPipe[1], afSingleShotgunPipe[2]), plPipe, FALSE); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, plPipe.pl_OrientationAngle); + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + sldPipe1.sld_vPos = plPipe.pl_PositionVector; + sldPipe1.sld_vUp = vUp; + sldPipe1.sld_tmLaunch = _pTimer->CurrentTick(); + sldPipe1.sld_estType = ESL_SHOTGUN_SMOKE; + FLOAT3D vSpeedRelative = FLOAT3D(0, 0.0f, -12.5f); + sldPipe1.sld_vSpeed = vSpeedRelative*m; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + } + + autowait(GetSP()->sp_bCooperative ? 0.5f : 0.375); + /* drop shell */ + + /* add one empty bullet shell */ + CPlacement3D plShell; + CalcWeaponPosition(FLOAT3D(afSingleShotgunShellPos[0], afSingleShotgunShellPos[1], afSingleShotgunShellPos[2]), plShell, FALSE); + + FLOATmatrix3D mRot; + MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle); + + if( hud_bShowWeapon) + { + CPlayer *penPlayer = GetPlayer(); + ShellLaunchData &sld = penPlayer->m_asldData[penPlayer->m_iFirstEmptySLD]; + sld.sld_vPos = plShell.pl_PositionVector; + FLOAT3D vSpeedRelative = FLOAT3D(FRnd()+2.0f, FRnd()+5.0f, -FRnd()-2.0f); + sld.sld_vSpeed = vSpeedRelative*mRot; + + const FLOATmatrix3D &m = penPlayer->GetRotationMatrix(); + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + sld.sld_vUp = vUp; + sld.sld_tmLaunch = _pTimer->CurrentTick(); + sld.sld_estType = ESL_SHOTGUN; + // move to next shell position + penPlayer->m_iFirstEmptySLD = (penPlayer->m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + + /* drop shell */ + autowait(m_moWeapon.GetAnimLength( + (GetSP()->sp_bCooperative ? SINGLESHOTGUN_ANIM_FIRE1:SINGLESHOTGUN_ANIM_FIRE1FAST) ) - + (GetSP()->sp_bCooperative ? 0.5f : 0.375f) ); + // no ammo -> change weapon + if (m_iShells<=0) { SelectNewWeapon(); } + } else { + ASSERTALWAYS("SingleShotgun - Auto weapon change not working."); + m_bFireWeapon = m_bHasAmmo = FALSE; + } + return EEnd(); + }; + + // ***************** FIRE DOUBLESHOTGUN ***************** + FireDoubleShotgun() { + // fire two shell + if (m_iShells>1) { + GetAnimator()->FireAnimation(BODY_ANIM_SHOTGUN_FIRELONG, 0); + FireBullets(wpn_fFX[WEAPON_DOUBLESHOTGUN], wpn_fFY[WEAPON_DOUBLESHOTGUN], + 500.0f, 10.0f, 14, afDoubleShotgunPellets, 0.3f, 0.03f); + DoRecoil(); + SpawnRangeSound(70.0f); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Dblshotgun_fire");} + DecAmmo(m_iShells, 2); + SetFlare(0, FLARE_ADD); + PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0); + m_moWeapon.PlayAnim(GetSP()->sp_bCooperative ? DOUBLESHOTGUN_ANIM_FIRE : DOUBLESHOTGUN_ANIM_FIREFAST, 0); + m_moWeaponSecond.PlayAnim(GetSP()->sp_bCooperative ? HANDWITHAMMO_ANIM_FIRE : HANDWITHAMMO_ANIM_FIREFAST, 0); + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.5f, 1.0f); // fire + PlaySound(pl.m_soWeapon0, SOUND_DOUBLESHOTGUN_FIRE, SOF_3D|SOF_VOLUMETRIC); + + if( hud_bShowWeapon) + { + if( pl.m_pstState==PST_DIVE) + { + // bubble (pipe 1) + ShellLaunchData &sldBubble1 = pl.m_asldData[pl.m_iFirstEmptySLD]; + CPlacement3D plShell; + CalcWeaponPosition(FLOAT3D(-0.11f, 0.1f, -0.3f), plShell, FALSE); + /*CalcWeaponPosition(FLOAT3D(afDoubleShotgunShellPos[0], + afDoubleShotgunShellPos[1], afDoubleShotgunShellPos[2]), plShell, FALSE);*/ + FLOATmatrix3D m; + MakeRotationMatrixFast(m, plShell.pl_OrientationAngle); + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + sldBubble1.sld_vPos = plShell.pl_PositionVector; + sldBubble1.sld_vUp = vUp; + sldBubble1.sld_tmLaunch = _pTimer->CurrentTick(); + sldBubble1.sld_estType = ESL_BUBBLE; + FLOAT3D vSpeedRelative = FLOAT3D(-0.1f, 0.0f, 0.01f); + sldBubble1.sld_vSpeed = vSpeedRelative*m; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + ShellLaunchData &sldBubble2 = pl.m_asldData[pl.m_iFirstEmptySLD]; + // bubble (pipe 2) + sldBubble2 = sldBubble1; + vSpeedRelative = FLOAT3D(0.1f, 0.0f, -0.2f); + sldBubble2.sld_vSpeed = vSpeedRelative*m; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + else + { + // smoke (pipe 1) + ShellLaunchData &sldPipe1 = pl.m_asldData[pl.m_iFirstEmptySLD]; + CPlacement3D plPipe; + CalcWeaponPosition(FLOAT3D(afDoubleShotgunPipe[0], afDoubleShotgunPipe[1], afDoubleShotgunPipe[2]), plPipe, FALSE); + FLOATmatrix3D m; + MakeRotationMatrixFast(m, plPipe.pl_OrientationAngle); + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + sldPipe1.sld_vPos = plPipe.pl_PositionVector; + sldPipe1.sld_vUp = vUp; + sldPipe1.sld_tmLaunch = _pTimer->CurrentTick(); + sldPipe1.sld_estType = ESL_SHOTGUN_SMOKE; + FLOAT3D vSpeedRelative = FLOAT3D(-1, 0.0f, -12.5f); + sldPipe1.sld_vSpeed = vSpeedRelative*m; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + // smoke (pipe 2) + ShellLaunchData &sldPipe2 = pl.m_asldData[pl.m_iFirstEmptySLD]; + sldPipe2 = sldPipe1; + vSpeedRelative = FLOAT3D(1, 0.0f, -12.5f); + sldPipe2.sld_vSpeed = vSpeedRelative*m; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + } + + autowait(GetSP()->sp_bCooperative ? 0.25f : 0.15f); + if (m_iShells>=2) { + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon1, SOUND_DOUBLESHOTGUN_RELOAD, SOF_3D|SOF_VOLUMETRIC); + } + autowait( m_moWeapon.GetAnimLength( + (GetSP()->sp_bCooperative ? DOUBLESHOTGUN_ANIM_FIRE : DOUBLESHOTGUN_ANIM_FIREFAST)) - + (GetSP()->sp_bCooperative ? 0.25f : 0.15f) ); + // no ammo -> change weapon + if (m_iShells<=1) { SelectNewWeapon(); } + } else { + ASSERTALWAYS("DoubleShotgun - Auto weapon change not working."); + m_bFireWeapon = m_bHasAmmo = FALSE; + } + return EEnd(); + }; + + // ***************** FIRE TOMMYGUN ***************** + TommyGunStart() { + m_iBulletsOnFireStart = m_iBullets; + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon0, SOUND_SILENCE, SOF_3D|SOF_VOLUMETRIC); // stop possible sounds + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.5f, 1.0f); // fire + PlaySound(pl.m_soWeapon0, SOUND_TOMMYGUN_FIRE, SOF_LOOP|SOF_3D|SOF_VOLUMETRIC); + PlayLightAnim(LIGHT_ANIM_TOMMYGUN, AOF_LOOPING); + GetAnimator()->FireAnimation(BODY_ANIM_SHOTGUN_FIRESHORT, AOF_LOOPING); + return EEnd(); + }; + + TommyGunStop() { + // smoke + CPlayer &pl = (CPlayer&)*m_penPlayer; + if( pl.m_pstState!=PST_DIVE && hud_bShowWeapon) + { + INDEX ctBulletsFired = ClampUp(m_iBulletsOnFireStart-m_iBullets, INDEX(100)); + for( INDEX iSmoke=0; iSmokesld_vPos = plPipe.pl_PositionVector+pl.en_vCurrentTranslationAbsolute*iSmoke*_pTimer->TickQuantum; + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + psldSmoke->sld_vUp = vUp; + psldSmoke->sld_tmLaunch = _pTimer->CurrentTick()+iSmoke*_pTimer->TickQuantum; + psldSmoke->sld_estType = ESL_BULLET_SMOKE; + psldSmoke->sld_fSize = 0.5f+ctBulletsFired/75.0f; + FLOAT3D vSpeedRelative = FLOAT3D(-0.06f, 0.0f, -0.06f); + psldSmoke->sld_vSpeed = vSpeedRelative*m+pl.en_vCurrentTranslationAbsolute; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + } + + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 0.0f, 1.0f); // mute fire + PlayLightAnim(LIGHT_ANIM_NONE, 0); + GetAnimator()->FireAnimationOff(); + jump Idle(); + }; + + FireTommyGun() { + // fire one bullet + if (m_iBullets>0) { + FireMachineBullet(wpn_fFX[WEAPON_TOMMYGUN], wpn_fFY[WEAPON_TOMMYGUN], + 500.0f, 10.0f, ((GetSP()->sp_bCooperative) ? 0.01f : 0.03f), + ((GetSP()->sp_bCooperative) ? 0.5f : 0.0f)); + SpawnRangeSound(50.0f); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Tommygun_fire");} + DecAmmo(m_iBullets, 1); + SetFlare(0, FLARE_ADD); + m_moWeapon.PlayAnim(TOMMYGUN_ANIM_FIRE, AOF_LOOPING|AOF_NORESTART); + + // firing FX + CPlacement3D plShell; + CalcWeaponPosition(FLOAT3D(afTommygunShellPos[0], afTommygunShellPos[1], afTommygunShellPos[2]), plShell, FALSE); + FLOATmatrix3D mRot; + MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle); + + if( hud_bShowWeapon) + { + // empty bullet shell + CPlayer &pl = *GetPlayer(); + ShellLaunchData &sld = pl.m_asldData[pl.m_iFirstEmptySLD]; + sld.sld_vPos = plShell.pl_PositionVector; + FLOAT3D vSpeedRelative = FLOAT3D(FRnd()+2.0f, FRnd()+5.0f, -FRnd()-2.0f); + const FLOATmatrix3D &m = pl.GetRotationMatrix(); + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + sld.sld_vUp = vUp; + sld.sld_vSpeed = vSpeedRelative*mRot; + sld.sld_tmLaunch = _pTimer->CurrentTick(); + sld.sld_estType = ESL_BULLET; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + + // bubble + if( pl.m_pstState==PST_DIVE) + { + ShellLaunchData &sldBubble = pl.m_asldData[pl.m_iFirstEmptySLD]; + CalcWeaponPosition(FLOAT3D(afTommygunShellPos[0], afTommygunShellPos[1], afTommygunShellPos[2]), plShell, FALSE); + MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle); + sldBubble.sld_vPos = plShell.pl_PositionVector; + sldBubble.sld_vUp = vUp; + sldBubble.sld_tmLaunch = _pTimer->CurrentTick(); + sldBubble.sld_estType = ESL_BUBBLE; + vSpeedRelative = FLOAT3D(0.3f, 0.0f, 0.0f); + sldBubble.sld_vSpeed = vSpeedRelative*mRot; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + } + + autowait(0.1f); + // no ammo -> change weapon + if (m_iBullets<=0) { SelectNewWeapon(); } + } else { + ASSERTALWAYS("TommyGun - Auto weapon change not working."); + m_bFireWeapon = m_bHasAmmo = FALSE; + } + return EEnd(); + }; + + // ***************** FIRE SNIPER ***************** + FireSniper() { + if (m_iSniperBullets>0) { + // fire one bullet + if (m_bSniping) { + FireSniperBullet(0.0f, 0.0f, 1500.0f, + (GetSP()->sp_bCooperative) ? 300.0f : 90.0f, 0.0f); + } + else { + FireSniperBullet(wpn_fFX[WEAPON_SNIPER], wpn_fFY[WEAPON_SNIPER], 1000.0f, + (GetSP()->sp_bCooperative) ? 75.0f : 30.0f, 5.0f); + } + m_tmLastSniperFire = _pTimer->CurrentTick(); + + SpawnRangeSound(50.0f); + DecAmmo(m_iSniperBullets, 1); + if (!m_bSniping) { + SetFlare(0, FLARE_ADD); + } + PlayLightAnim(LIGHT_ANIM_COLT_SHOTGUN, 0); + + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + if (GetSP()->sp_bCooperative) { + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.5f, 1.0f); + } else if (TRUE) { + pl.m_soWeapon0.Set3DParameters(250.0f, 75.0f, 1.5f, 1.0f); + } + PlaySound(pl.m_soWeapon0, SOUND_SNIPER_FIRE, SOF_3D|SOF_VOLUMETRIC); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("SniperFire");} + + // animation + m_moWeapon.PlayAnim(SNIPER_ANIM_FIRE, 0); + + autowait(1.0f); + + // firing FX + CPlacement3D plShell; + CalcWeaponPosition(FLOAT3D(afSniperShellPos[0], afSniperShellPos[1], afSniperShellPos[2]), plShell, FALSE); + FLOATmatrix3D mRot; + MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle); + + if( hud_bShowWeapon) + { + CPlayer *penPlayer = GetPlayer(); + ShellLaunchData &sld = penPlayer->m_asldData[penPlayer->m_iFirstEmptySLD]; + sld.sld_vPos = plShell.pl_PositionVector; + FLOAT3D vSpeedRelative = FLOAT3D(FRnd()+2.0f, FRnd()+5.0f, -FRnd()-2.0f); + sld.sld_vSpeed = vSpeedRelative*mRot; + + const FLOATmatrix3D &m = penPlayer->GetRotationMatrix(); + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + sld.sld_vUp = vUp; + sld.sld_tmLaunch = _pTimer->CurrentTick(); + sld.sld_estType = ESL_BULLET; + // move to next shell position + penPlayer->m_iFirstEmptySLD = (penPlayer->m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + + // bubble + if( penPlayer->m_pstState==PST_DIVE) + { + ShellLaunchData &sldBubble = penPlayer->m_asldData[penPlayer->m_iFirstEmptySLD]; + CalcWeaponPosition(FLOAT3D(afTommygunShellPos[0], afTommygunShellPos[1], afTommygunShellPos[2]), plShell, FALSE); + MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle); + sldBubble.sld_vPos = plShell.pl_PositionVector; + sldBubble.sld_vUp = vUp; + sldBubble.sld_tmLaunch = _pTimer->CurrentTick(); + sldBubble.sld_estType = ESL_BUBBLE; + vSpeedRelative = FLOAT3D(0.3f, 0.0f, 0.0f); + sldBubble.sld_vSpeed = vSpeedRelative*mRot; + penPlayer->m_iFirstEmptySLD = (penPlayer->m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + } + + autowait(1.35f - 1.0f); + + // no ammo -> change weapon + if (m_iSniperBullets<=0) { SelectNewWeapon(); } + } + else { + ASSERTALWAYS("Sniper - Auto weapon change not working."); + m_bFireWeapon = m_bHasAmmo = FALSE; + } + return EEnd(); + }; + + + // ***************** FIRE MINIGUN ***************** + MiniGunSpinUp() { + // steady anim + m_moWeapon.PlayAnim(MINIGUN_ANIM_WAIT1, AOF_LOOPING|AOF_NORESTART); + // no boring animation + ((CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator).m_fLastActionTime = _pTimer->CurrentTick(); + // clear last lerped bullet position + m_iLastBulletPosition = FLOAT3D(32000.0f, 32000.0f, 32000.0f); + CPlayer &pl = (CPlayer&)*m_penPlayer; + + PlaySound(pl.m_soWeapon0, SOUND_SILENCE, SOF_3D|SOF_VOLUMETRIC); // stop possible sounds + // initialize sound 3D parameters + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 2.0f, 1.0f); // fire + pl.m_soWeapon1.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f); // spinup/spindown/spin + pl.m_soWeapon2.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f); // turn on/off click + + // spin start sounds + PlaySound(pl.m_soWeapon2, SOUND_MINIGUN_CLICK, SOF_3D|SOF_VOLUMETRIC); + PlaySound(pl.m_soWeapon1, SOUND_MINIGUN_SPINUP, SOF_3D|SOF_VOLUMETRIC); + //pl.m_soWeapon1.SetOffset((m_aMiniGunSpeed/MINIGUN_FULLSPEED)*MINIGUN_SPINUPSOUND); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Minigun_rotateup");} + // while not at full speed and fire is held + while (m_aMiniGunSpeedIsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Minigun_rotate");} + // if firing + if(HoldingFire() && m_iBullets>0) { + // play fire sound + PlaySound(pl.m_soWeapon0, SOUND_MINIGUN_FIRE, SOF_3D|SOF_LOOP|SOF_VOLUMETRIC); + PlayLightAnim(LIGHT_ANIM_TOMMYGUN, AOF_LOOPING); + GetAnimator()->FireAnimation(BODY_ANIM_MINIGUN_FIRESHORT, AOF_LOOPING); + } + + m_iBulletsOnFireStart = m_iBullets; + // while holding fire + while (HoldingFire()) { + // check for ammo pickup during empty spinning + if (!m_bHasAmmo && m_iBullets>0) { + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon0, SOUND_MINIGUN_FIRE, SOF_3D|SOF_LOOP|SOF_VOLUMETRIC); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Minigun_fire");} + PlayLightAnim(LIGHT_ANIM_TOMMYGUN, AOF_LOOPING); + GetAnimator()->FireAnimation(BODY_ANIM_MINIGUN_FIRESHORT, AOF_LOOPING); + m_bHasAmmo = TRUE; + } + + // if has ammo + if (m_iBullets>0) { + // fire a bullet + FireMachineBullet(wpn_fFX[WEAPON_MINIGUN], wpn_fFY[WEAPON_MINIGUN], + 750.0f, 10.0f, (GetSP()->sp_bCooperative) ? 0.01f : 0.03f, + ( (GetSP()->sp_bCooperative) ? 0.5f : 0.0f)); + DoRecoil(); + SpawnRangeSound(60.0f); + DecAmmo(m_iBullets, 1); + SetFlare(0, FLARE_ADD); + + /* add one empty bullet shell */ + CPlacement3D plShell; + + // if 1st person view + CPlayer &pl = (CPlayer&)*m_penPlayer; + if(pl.m_penCamera==NULL && pl.m_pen3rdPersonView==NULL) + { + CalcWeaponPosition(FLOAT3D(afMinigunShellPos[0], afMinigunShellPos[1], afMinigunShellPos[2]), plShell, FALSE); + } + // if 3rd person view + else + { + /*CalcWeaponPosition3rdPersonView(FLOAT3D(tmp_af[0], tmp_af[1], tmp_af[2]), plShell, FALSE);*/ + CalcWeaponPosition3rdPersonView(FLOAT3D(afMinigunShellPos3rdView[0], + afMinigunShellPos3rdView[1], afMinigunShellPos3rdView[2]), plShell, FALSE); + } + + FLOATmatrix3D mRot; + MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle); + + if( hud_bShowWeapon) + { + CPlayer &pl = *GetPlayer(); + ShellLaunchData &sld = pl.m_asldData[pl.m_iFirstEmptySLD]; + sld.sld_vPos = plShell.pl_PositionVector; + FLOAT3D vSpeedRelative = FLOAT3D(FRnd()+2.0f, FRnd()+5.0f, -FRnd()-2.0f); + const FLOATmatrix3D &m = pl.GetRotationMatrix(); + FLOAT3D vUp( m(1,2), m(2,2), m(3,2)); + sld.sld_vUp = vUp; + sld.sld_vSpeed = vSpeedRelative*mRot; + sld.sld_tmLaunch = _pTimer->CurrentTick(); + sld.sld_estType = ESL_BULLET; + // move to next shell position + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + + // bubble + if( pl.m_pstState==PST_DIVE) + { + ShellLaunchData &sldBubble = pl.m_asldData[pl.m_iFirstEmptySLD]; + CalcWeaponPosition(FLOAT3D(afMinigunShellPos[0], afMinigunShellPos[1], afMinigunShellPos[2]), plShell, FALSE); + MakeRotationMatrixFast(mRot, plShell.pl_OrientationAngle); + sldBubble.sld_vPos = plShell.pl_PositionVector; + sldBubble.sld_vUp = vUp; + sldBubble.sld_tmLaunch = _pTimer->CurrentTick(); + sldBubble.sld_estType = ESL_BUBBLE; + vSpeedRelative = FLOAT3D(0.3f, 0.0f, 0.0f); + sldBubble.sld_vSpeed = vSpeedRelative*mRot; + pl.m_iFirstEmptySLD = (pl.m_iFirstEmptySLD+1) % MAX_FLYING_SHELLS; + } + } + // if no ammo + } else { + if( m_bHasAmmo) + { + MinigunSmoke(); + } + // stop fire sound + m_bHasAmmo = FALSE; + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon0, SOUND_SILENCE, SOF_3D|SOF_VOLUMETRIC); // stop possible sounds + PlayLightAnim(LIGHT_ANIM_NONE, AOF_LOOPING); + GetAnimator()->FireAnimationOff(); + } + autowait(MINIGUN_TICKTIME); + // spin + m_aMiniGunLast = m_aMiniGun; + m_aMiniGun+=m_aMiniGunSpeed*MINIGUN_TICKTIME; + } + + if( m_bHasAmmo) + { + MinigunSmoke(); + } + + GetAnimator()->FireAnimationOff(); + // stop fire sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 0.0f, 1.0f); // mute fire + PlayLightAnim(LIGHT_ANIM_NONE, AOF_LOOPING); + // start spin down + jump MiniGunSpinDown(); + } + + MiniGunSpinDown() { + CPlayer &pl = (CPlayer&)*m_penPlayer; + // spin down sounds + PlaySound(pl.m_soWeapon3, SOUND_MINIGUN_CLICK, SOF_3D|SOF_VOLUMETRIC); + PlaySound(pl.m_soWeapon1, SOUND_MINIGUN_SPINDOWN, SOF_3D|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_StopEffect("Minigun_rotate");} + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Minigun_rotatedown");} + //pl.m_soWeapon1.SetOffset((1-m_aMiniGunSpeed/MINIGUN_FULLSPEED)*MINIGUN_SPINDNSOUND); + + // while still spinning and should not fire + while ( m_aMiniGunSpeed>0 && (!HoldingFire() || m_iBullets<=0)) { + autowait(MINIGUN_TICKTIME); + // spin + m_aMiniGunLast = m_aMiniGun; + m_aMiniGun+=m_aMiniGunSpeed*MINIGUN_TICKTIME; + m_aMiniGunSpeed-=MINIGUN_SPINDNACC*MINIGUN_TICKTIME; + + if (m_iBullets<=0) { + SelectNewWeapon(); + } + + // if weapon should be changed + if (m_bChangeWeapon) { + // stop spinning immediately + m_aMiniGunSpeed = 0.0f; + m_aMiniGunLast = m_aMiniGun; + GetAnimator()->FireAnimationOff(); + jump Idle(); + } + } + // clamp some + m_aMiniGunSpeed = ClampDn( m_aMiniGunSpeed, 0.0f); + m_aMiniGunLast = m_aMiniGun; + + // if should fire + if (HoldingFire() && m_iBullets>0) { + // start spinup + jump MiniGunSpinUp(); + } + + // no boring animation + ((CPlayerAnimator&)*((CPlayer&)*m_penPlayer).m_penAnimator).m_fLastActionTime = _pTimer->CurrentTick(); + + // if out of ammo + if (m_iBullets<=0) { + // can wait without changing while holding fire - specific for movie sequence + while(HoldingFire() && m_iBullets<=0) { + autowait(0.1f); + } + if (m_iBullets<=0) { + // select new weapon + SelectNewWeapon(); + } + } + jump Idle(); + }; + + // ***************** FIRE ROCKETLAUNCHER ***************** + FireRocketLauncher() { + // fire one grenade + if (m_iRockets>0) { + GetAnimator()->FireAnimation(BODY_ANIM_MINIGUN_FIRELONG, 0); + m_moWeapon.PlayAnim(ROCKETLAUNCHER_ANIM_FIRE, 0); + FireRocket(); + + DoRecoil(); + SpawnRangeSound(20.0f); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Rocketlauncher_fire");} + DecAmmo(m_iRockets, 1); + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + if( pl.m_soWeapon0.IsPlaying()) + { + PlaySound(pl.m_soWeapon1, SOUND_ROCKETLAUNCHER_FIRE, SOF_3D|SOF_VOLUMETRIC); + } + else + { + PlaySound(pl.m_soWeapon0, SOUND_ROCKETLAUNCHER_FIRE, SOF_3D|SOF_VOLUMETRIC); + } + + autowait(0.05f); + + CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(ROCKETLAUNCHER_ATTACHMENT_ROCKET1)->amo_moModelObject); + pmo->StretchModel(FLOAT3D(0, 0, 0)); + + autowait(m_moWeapon.GetAnimLength(ROCKETLAUNCHER_ANIM_FIRE)-0.05f); + + CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(ROCKETLAUNCHER_ATTACHMENT_ROCKET1)->amo_moModelObject); + pmo->StretchModel(FLOAT3D(1, 1, 1)); + + // no ammo -> change weapon + if (m_iRockets<=0) { SelectNewWeapon(); } + } else { + ASSERTALWAYS("RocketLauncher - Auto weapon change not working."); + m_bFireWeapon = m_bHasAmmo = FALSE; + } + return EEnd(); + }; + + // ***************** FIRE GRENADELAUNCHER ***************** + FireGrenadeLauncher() + { + TM_START = _pTimer->CurrentTick(); + // remember time for spring release + F_TEMP = _pTimer->CurrentTick(); + + F_OFFSET_CHG = 0.0f; + m_fWeaponDrawPower = 0.0f; + m_tmDrawStartTime = _pTimer->CurrentTick(); + while (HoldingFire() && ((_pTimer->CurrentTick()-TM_START)<0.75f) ) + { + autowait(_pTimer->TickQuantum); + INDEX iPower = INDEX((_pTimer->CurrentTick()-TM_START)/_pTimer->TickQuantum); + F_OFFSET_CHG = 0.125f/(iPower+2); + m_fWeaponDrawPowerOld = m_fWeaponDrawPower; + m_fWeaponDrawPower += F_OFFSET_CHG; + } + m_tmDrawStartTime = 0.0f; + + + // release spring and fire one grenade + if (m_iGrenades>0) + { + // fire grenade + INDEX iPower = INDEX((_pTimer->CurrentTick()-F_TEMP)/_pTimer->TickQuantum); + FireGrenade( iPower); + SpawnRangeSound(10.0f); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Gnadelauncher");} + DecAmmo(m_iGrenades, 1); + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon0, SOUND_GRENADELAUNCHER_FIRE, SOF_3D|SOF_VOLUMETRIC); + GetAnimator()->FireAnimation(BODY_ANIM_MINIGUN_FIRELONG, 0); + + // release spring + TM_START = _pTimer->CurrentTick(); + m_fWeaponDrawPowerOld = m_fWeaponDrawPower; + while (m_fWeaponDrawPower>0.0f) + { + autowait(_pTimer->TickQuantum); + m_fWeaponDrawPowerOld = m_fWeaponDrawPower; + m_fWeaponDrawPower -= F_OFFSET_CHG; + m_fWeaponDrawPower = ClampDn( m_fWeaponDrawPower, 0.0f); + F_OFFSET_CHG = F_OFFSET_CHG*10; + } + + // reset moving part's offset + ResetWeaponMovingOffset(); + + // no ammo -> change weapon + if (m_iGrenades<=0) + { + SelectNewWeapon(); + } + else if( TRUE) + { + autowait(0.25f); + } + } else { + ASSERTALWAYS("GrenadeLauncher - Auto weapon change not working."); + m_bFireWeapon = m_bHasAmmo = FALSE; + } + + return EEnd(); + }; + +/* + // ***************** FIRE PIPEBOMB ***************** + FirePipeBomb() { + // drop one pipebomb + if (m_iGrenades>=0) { + // fire bomb + if (m_bPipeBombDropped) { + m_bPipeBombDropped = FALSE; + m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_STICKFIRE, 0); + autowait(0.35f); + // activate pipebomb + SendToTarget(m_penPipebomb, EET_START); + m_penPipebomb = NULL; + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon0, SOUND_PIPEBOMB_FIRE, SOF_3D|SOF_VOLUMETRIC); + // no ammo -> change weapon + if (m_iGrenades<=0) { + autowait(m_moWeaponSecond.GetAnimLength(HANDWITHSTICK_ANIM_STICKFIRE)-0.35f); + SelectNewWeapon(); + return EEnd(); + } + // get new bomb + AddAttachmentToModel(this, m_moWeapon, HANDWITHBOMB_ATTACHMENT_BOMB, MODEL_PB_BOMB, + TEXTURE_PB_BOMB, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + m_moWeapon.PlayAnim(HANDWITHBOMB_ANIM_ACTIVATE, 0); + autowait(m_moWeapon.GetAnimLength(HANDWITHBOMB_ANIM_ACTIVATE)); + + // drop bomb + } else if (TRUE) { + m_bPipeBombDropped = TRUE; + // low drop + if (((CPlayer&)*m_penPlayer).en_plViewpoint.pl_OrientationAngle(2) < -20.0f) { + m_moWeapon.PlayAnim(HANDWITHBOMB_ANIM_BOMBTHROW1 ,0); + // high drop + } else { + m_moWeapon.PlayAnim(HANDWITHBOMB_ANIM_BOMBTHROW2 ,0); + } + autowait(0.5f); + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon1, SOUND_PIPEBOMB_THROW, SOF_3D|SOF_VOLUMETRIC); + SpawnRangeSound(5.0f); + autowait(0.2f); + // drop bomb + DropPipebomb(); + DecAmmo(m_iGrenades, 1); + RemoveAttachmentFromModel(m_moWeapon, HANDWITHBOMB_ATTACHMENT_BOMB); + autowait(0.2f); + // open stick shield + m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_STICKTHROW ,0); + // sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon2, SOUND_PIPEBOMB_OPEN, SOF_3D|SOF_VOLUMETRIC); + autowait(m_moWeaponSecond.GetAnimLength(HANDWITHSTICK_ANIM_STICKTHROW)); + } + } else { + ASSERTALWAYS("Pipebomb - Auto weapon change not working."); + m_bFireWeapon = m_bHasAmmo = FALSE; + } + return EEnd(); + }; + + ReloadPipeBomb() { + if (m_bPipeBombDropped) { + m_bPipeBombDropped = FALSE; + // close stick + m_moWeaponSecond.PlayAnim(HANDWITHSTICK_ANIM_STICKRETURN, 0); + // get new bomb + AddAttachmentToModel(this, m_moWeapon, HANDWITHBOMB_ATTACHMENT_BOMB, MODEL_PB_BOMB, + TEXTURE_PB_BOMB, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + m_moWeapon.PlayAnim(HANDWITHBOMB_ANIM_ACTIVATE, 0); + autowait(m_moWeapon.GetAnimLength(HANDWITHBOMB_ANIM_ACTIVATE)); + } + + return EEnd(); + };*/ + + // ***************** FIRE FLAMER ***************** + FlamerStart() { + m_tmFlamerStart=_pTimer->CurrentTick(); + m_tmFlamerStop=1e9; + + m_moWeapon.PlayAnim(FLAMER_ANIM_FIRESTART, 0); + autowait(m_moWeapon.GetAnimLength(FLAMER_ANIM_FIRESTART)); + // play fire sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 2.0f, 0.31f); + pl.m_soWeapon2.Set3DParameters(50.0f, 5.0f, 2.0f, 0.3f); + PlaySound(pl.m_soWeapon0, SOUND_FL_FIRE, SOF_3D|SOF_LOOP|SOF_VOLUMETRIC); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("FlamethrowerFire");} + PlaySound(pl.m_soWeapon2, SOUND_FL_START, SOF_3D|SOF_VOLUMETRIC); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("FlamethrowerStart");} + FireFlame(); + DecAmmo(m_iNapalm, 1); + autowait(0.05f); + jump FlamerFire(); + }; + + FlamerFire() { + // while holding fire + while (HoldingFire() && m_iNapalm>0) { + // fire + FireFlame(); + DecAmmo(m_iNapalm, 1); + SpawnRangeSound(30.0f); + autowait(0.1f); + } + + if (m_iNapalm<=0) { + m_bHasAmmo = FALSE; + } + + jump FlamerStop(); + }; + + FlamerStop() { + m_tmFlamerStop=_pTimer->CurrentTick(); + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon0, SOUND_FL_STOP, SOF_3D|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_StopEffect("FlamethrowerFire");} + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("FlamethrowerStop");} + //PlaySound(pl.m_soWeapon1, SOUND_FL_STOP, SOF_3D|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE); + FireFlame(); + // link last flame with nothing (if not NULL or deleted) + if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) { + ((CProjectile&)*m_penFlame).m_penParticles = NULL; + m_penFlame = NULL; + } + + m_moWeapon.PlayAnim(FLAMER_ANIM_FIREEND, 0); + autowait(m_moWeapon.GetAnimLength(FLAMER_ANIM_FIREEND)); + + if (m_iNapalm<=0) { + // select new weapon + SelectNewWeapon(); + } + jump Idle(); + }; + + // ***************** FIRE CHAINSAW ***************** + ChainsawFire() { + + CPlayer &pl = (CPlayer&)*m_penPlayer; + + // set the firing sound level + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.5f, 1.0f); + PlaySound(pl.m_soWeapon0, SOUND_CS_BEGINFIRE, SOF_3D|SOF_VOLUMETRIC); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("ChainsawBeginFire");} + + + // bring the chainsaw down to cutting height (fire position) + m_moWeapon.PlayAnim(CHAINSAW_ANIM_WAIT2FIRE, 0); + autowait(m_moWeapon.GetAnimLength(CHAINSAW_ANIM_WAIT2FIRE)-0.05f); + + CPlayerAnimator &pa=*GetAnimator(); + pa.FireAnimation(BODY_ANIM_MINIGUN_FIRELONG, 0); + + CModelObject *pmoTeeth=GetChainSawTeeth(); + if( pmoTeeth!=NULL) + { + pmoTeeth->PlayAnim(TEETH_ANIM_ROTATE, AOF_LOOPING|AOF_NORESTART); + } + + // firing + CPlayer &pl = (CPlayer&)*m_penPlayer; + // mute the chainsaw engine sound + pl.m_soWeaponAmbient.Set3DParameters(30.0f, 3.0f, 0.5f, 1.0f); + + PlaySound(pl.m_soWeapon0, SOUND_CS_FIRE, SOF_3D|SOF_LOOP|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_StopEffect("ChainsawIdle");} + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("ChainsawFire");} + + m_moWeapon.PlayAnim(CHAINSAW_ANIM_FIRE, AOF_LOOPING|AOF_NORESTART); + + // start teeth rotation + CModelObject *pmo1 = &(m_moWeapon.GetAttachmentModel(CHAINSAW_ATTACHMENT_BLADE)->amo_moModelObject); + CModelObject *pmo2 = &(pmo1->GetAttachmentModel(BLADE_ATTACHMENT_TEETH)->amo_moModelObject); + pmo2->PlayAnim(TEETH_ANIM_ROTATE, AOF_LOOPING); + + while (HoldingFire())// && m_iNapalm>0) + { + autowait(CHAINSAW_UPDATETIME); + // 200 damage per second + CutWithChainsaw(0, 0, 3.0f, 2.0f, 1.0f, + ((GetSP()->sp_bCooperative) ? 200.0f : 250.0f)*CHAINSAW_UPDATETIME); + //DecAmmo(m_iNapalm, 1); + } + + // bring it back to idle position + + CPlayer &pl = (CPlayer&)*m_penPlayer; + PlaySound(pl.m_soWeapon0, SOUND_CS_ENDFIRE, SOF_3D|SOF_VOLUMETRIC|SOF_SMOOTHCHANGE); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_StopEffect("ChainsawFire");} + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("ChainsawEnd");} + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("ChainsawIdle");} +// PlaySound(pl.m_soWeapon0, SOUND_SILENCE, SOF_3D|SOF_VOLUMETRIC/*|SOF_SMOOTHCHANGE*/); + // restore volume to engine sound + pl.m_soWeaponAmbient.Set3DParameters(30.0f, 3.0f, 1.0f, 1.0f); + + m_moWeapon.PlayAnim(CHAINSAW_ANIM_FIRE2WAIT, 0); + autowait(m_moWeapon.GetAnimLength(CHAINSAW_ANIM_FIRE2WAIT)); + + // stop teeth rotation + CModelObject *pmo1 = &(m_moWeapon.GetAttachmentModel(CHAINSAW_ATTACHMENT_BLADE)->amo_moModelObject); + CModelObject *pmo2 = &(pmo1->GetAttachmentModel(BLADE_ATTACHMENT_TEETH)->amo_moModelObject); + pmo2->PlayAnim(TEETH_ANIM_DEFAULT, 0); + + CModelObject *pmoTeeth=GetChainSawTeeth(); + if( pmoTeeth!=NULL) + { + pmoTeeth->PlayAnim(TEETH_ANIM_DEFAULT, 0); + } + + jump Idle(); + }; + + ChainsawBringUp() + { + // bring it back to idle position + m_moWeapon.PlayAnim(CHAINSAW_ANIM_FIRE2WAIT, 0); + autowait(m_moWeapon.GetAnimLength(CHAINSAW_ANIM_FIRE2WAIT)); + jump Idle(); + } + + // ***************** FIRE LASER ***************** + FireLaser() { + // fire one cell + if (m_iElectricity>0) { + autowait(0.1f); + m_moWeapon.PlayAnim(LASER_ANIM_FIRE, AOF_LOOPING|AOF_NORESTART); + FireLaserRay(); + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Laser_fire");} + DecAmmo(m_iElectricity, 1); + // sound + SpawnRangeSound(20.0f); + CPlayer &pl = (CPlayer&)*m_penPlayer; + // activate barrel anim + switch(m_iLaserBarrel) { + case 0: { // barrel lu + CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(LASER_ATTACHMENT_LEFTUP)->amo_moModelObject); + pmo->PlayAnim(BARREL_ANIM_FIRE, 0); + PlaySound(pl.m_soWeapon0, SOUND_LASER_FIRE, SOF_3D|SOF_VOLUMETRIC); + break; } + case 3: { // barrel rd + CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(LASER_ATTACHMENT_RIGHTDOWN)->amo_moModelObject); + pmo->PlayAnim(BARREL_ANIM_FIRE, 0); + PlaySound(pl.m_soWeapon1, SOUND_LASER_FIRE, SOF_3D|SOF_VOLUMETRIC); + break; } + case 1: { // barrel ld + CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(LASER_ATTACHMENT_LEFTDOWN)->amo_moModelObject); + pmo->PlayAnim(BARREL_ANIM_FIRE, 0); + PlaySound(pl.m_soWeapon2, SOUND_LASER_FIRE, SOF_3D|SOF_VOLUMETRIC); + break; } + case 2: { // barrel ru + CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(LASER_ATTACHMENT_RIGHTUP)->amo_moModelObject); + pmo->PlayAnim(BARREL_ANIM_FIRE, 0); + PlaySound(pl.m_soWeapon3, SOUND_LASER_FIRE, SOF_3D|SOF_VOLUMETRIC); + break; } + } + // next barrel + m_iLaserBarrel = (m_iLaserBarrel+1)&3; + // no electricity -> change weapon + if (m_iElectricity<=0) { SelectNewWeapon(); } + } else { + ASSERTALWAYS("Laser - Auto weapon change not working."); + m_bFireWeapon = m_bHasAmmo = FALSE; + } + return EEnd(); + }; + + /* + // ***************** FIRE GHOSTBUSTER ***************** + GhostBusterStart() { + GetAnimator()->FireAnimation(BODY_ANIM_SHOTGUN_FIRESHORT, AOF_LOOPING); + // create ray + m_penGhostBusterRay = CreateEntity(GetPlacement(), CLASS_GHOSTBUSTERRAY); + EGhostBusterRay egbr; + egbr.penOwner = this; + m_penGhostBusterRay->Initialize(egbr); + // play anim + m_moWeapon.PlayAnim(GHOSTBUSTER_ANIM_FIRE, AOF_LOOPING|AOF_NORESTART); + // play fire sound + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 1.0f, 1.0f); // fire + PlaySound(pl.m_soWeapon0, SOUND_GB_FIRE, SOF_3D|SOF_LOOP|SOF_VOLUMETRIC); + return EEnd(); + }; + + GhostBusterStop() { + GetAnimator()->FireAnimationOff(); + // destroy ray + ((CGhostBusterRay&)*m_penGhostBusterRay).DestroyGhostBusterRay(); + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.m_soWeapon0.Stop(); + jump Idle(); + }; + + FireGhostBuster() { + // fire one cell + if (m_iElectricity>0) { + FireGhostBusterRay(); + DecAmmo(m_iElectricity, 1); + SpawnRangeSound(20.0f); + autowait(0.05f); + // no napalm -> change weapon + if (m_iElectricity<=0) { SelectNewWeapon(); } + } else { + ASSERTALWAYS("GhostBuster - Auto weapon change not working."); + m_bFireWeapon = m_bHasAmmo = FALSE; + } + return EEnd(); + }; + */ + + // ***************** FIRE CANNON ***************** + + CannonFireStart() + { + m_tmDrawStartTime = _pTimer->CurrentTick(); + TM_START = _pTimer->CurrentTick(); + F_OFFSET_CHG = 0.0f; + m_fWeaponDrawPower = 0.0f; + CPlayer &pl = (CPlayer&)*m_penPlayer; + if( m_iIronBalls&1) + { + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 3.0f, 1.0f); + PlaySound(pl.m_soWeapon0, SOUND_CANNON_PREPARE, SOF_3D|SOF_VOLUMETRIC); + } + else + { + pl.m_soWeapon1.Set3DParameters(50.0f, 5.0f, 3.0f, 1.0f); + PlaySound(pl.m_soWeapon1, SOUND_CANNON_PREPARE, SOF_3D|SOF_VOLUMETRIC); + } + + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Canon_prepare");} + while (HoldingFire() && ((_pTimer->CurrentTick()-TM_START)<1.0f) ) + { + autowait(_pTimer->TickQuantum); + INDEX iPower = INDEX((_pTimer->CurrentTick()-TM_START)/_pTimer->TickQuantum); + F_OFFSET_CHG = 0.25f/(iPower+2); + m_fWeaponDrawPowerOld = m_fWeaponDrawPower; + m_fWeaponDrawPower += F_OFFSET_CHG; + } + m_tmDrawStartTime = 0.0f; + CPlayer &pl = (CPlayer&)*m_penPlayer; + if( m_iIronBalls&1) + { + // turn off the sound + pl.m_soWeapon0.Set3DParameters(50.0f, 5.0f, 0.0f, 1.0f); + } + else + { + // turn off the sound + pl.m_soWeapon1.Set3DParameters(50.0f, 5.0f, 0.0f, 1.0f); + } + + // fire one ball + if ( ((m_iIronBalls>0) && (m_iCurrentWeapon == WEAPON_IRONCANNON)) ) + { + INDEX iPower = INDEX((_pTimer->CurrentTick()-TM_START)/_pTimer->TickQuantum); + GetAnimator()->FireAnimation(BODY_ANIM_MINIGUN_FIRELONG, 0); + + FLOAT fRange, fFalloff; + if (GetSP()->sp_bCooperative) { + fRange = 100.0f; + fFalloff = 25.0f; + } else if (TRUE) { + fRange = 150.0f; + fFalloff = 30.0f; + } + + // adjust volume of cannon firing acording to launch power + if( m_iIronBalls&1) + { + pl.m_soWeapon2.Set3DParameters(fRange, fFalloff, 2.0f+iPower*0.05f, 1.0f); + PlaySound(pl.m_soWeapon2, SOUND_CANNON, SOF_3D|SOF_VOLUMETRIC); + } + else + { + pl.m_soWeapon3.Set3DParameters(fRange, fFalloff, 2.0f+iPower*0.05f, 1.0f); + PlaySound(pl.m_soWeapon3, SOUND_CANNON, SOF_3D|SOF_VOLUMETRIC); + } + + m_moWeapon.PlayAnim(CANNON_ANIM_FIRE, 0); + FireCannonBall( iPower); + + if(_pNetwork->IsPlayerLocal(m_penPlayer)) {IFeel_PlayEffect("Canon");} + DecAmmo(m_iIronBalls, 1); + + SpawnRangeSound(30.0f); + + TM_START = _pTimer->CurrentTick(); + m_fWeaponDrawPowerOld = m_fWeaponDrawPower; + while (m_fWeaponDrawPower>0.0f || + ((_pTimer->CurrentTick()-TM_START)TickQuantum); + m_fWeaponDrawPowerOld = m_fWeaponDrawPower; + m_fWeaponDrawPower -= F_OFFSET_CHG; + m_fWeaponDrawPower = ClampDn( m_fWeaponDrawPower, 0.0f); + F_OFFSET_CHG = F_OFFSET_CHG*2; + } + + // reset moving part's offset + ResetWeaponMovingOffset(); + + // no cannon balls -> change weapon + if ( ((m_iIronBalls<=0) && (m_iCurrentWeapon == WEAPON_IRONCANNON) ) /*|| + ((m_iNukeBalls<=0) && (m_iCurrentWeapon == WEAPON_NUKECANNON) ) */) + { + SelectNewWeapon(); + } + } + else + { + ASSERTALWAYS("Cannon - Auto weapon change not working."); + m_bFireWeapon = m_bHasAmmo = FALSE; + } + jump Idle(); + }; + + + /* + * >>>--- RELOAD WEAPON ---<<< + */ + Reload() { + m_bReloadWeapon = FALSE; + + // reload + if (m_iCurrentWeapon == WEAPON_COLT) { + autocall ReloadColt() EEnd; + } else if (m_iCurrentWeapon == WEAPON_DOUBLECOLT) { + autocall ReloadDoubleColt() EEnd; +/* } else if (m_iCurrentWeapon == WEAPON_PIPEBOMB) { + autocall ReloadPipeBomb() EEnd;*/ + } + + jump Idle(); + }; + + + /* + * >>>--- KNIFE STAND CHANGE ---<<< + */ + ChangeKnifeStand(EVoid) { +/* if (m_iKnifeStand==1) { + // change from knife stand 1 to stand 3 + m_moWeapon.PlayAnim(KNIFE_ANIM_STAND1TOSTAND3, 0); + autowait(m_moWeapon.GetAnimLength(KNIFE_ANIM_STAND1TOSTAND3)); + m_iKnifeStand = 3; + } else if (m_iKnifeStand==3) { + // change from knife stand 3 to stand 1 + m_moWeapon.PlayAnim(KNIFE_ANIM_STAND3TOSTAND1, 0); + autowait(m_moWeapon.GetAnimLength(KNIFE_ANIM_STAND3TOSTAND1)); + m_iKnifeStand = 1; + } + */ + return EEnd(); + }; + + ChangeToIronCannon(EVoid) + { +/* CModelObject &moLight = m_moWeapon.GetAttachmentModel(CANNON_ATTACHMENT_LIGHT)->amo_moModelObject; + moLight.PlayAnim( LIGHT_ANIM_DOWN, 0); + autowait(moLight.GetAnimLength(LIGHT_ANIM_DOWN)); + + CModelObject &moNukeBox = m_moWeapon.GetAttachmentModel(CANNON_ATTACHMENT_NUKEBOX)->amo_moModelObject; + moNukeBox.PlayAnim( NUKEBOX_ANIM_CLOSE, 0); + autowait(moNukeBox.GetAnimLength(NUKEBOX_ANIM_CLOSE)); + */ + + m_iPreviousWeapon = m_iCurrentWeapon; + m_iCurrentWeapon = WEAPON_IRONCANNON; + m_iWantedWeapon = m_iCurrentWeapon; + + return EEnd(); + } + +/* ChangeToNukeCannon(EVoid) + { + CModelObject &moNukeBox = m_moWeapon.GetAttachmentModel(CANNON_ATTACHMENT_NUKEBOX)->amo_moModelObject; + moNukeBox.PlayAnim( NUKEBOX_ANIM_OPEN, 0); + autowait(moNukeBox.GetAnimLength(NUKEBOX_ANIM_OPEN)); + + CModelObject &moLight = m_moWeapon.GetAttachmentModel(CANNON_ATTACHMENT_LIGHT)->amo_moModelObject; + moLight.PlayAnim( LIGHT_ANIM_UP, 0); + autowait(moLight.GetAnimLength(LIGHT_ANIM_UP)); + + m_iPreviousWeapon = m_iCurrentWeapon; + m_iCurrentWeapon = WEAPON_NUKECANNON; + m_iWantedWeapon = m_iCurrentWeapon; + + return EEnd(); + }; +*/ + + /* + * >>>--- BORING WEAPON ANIMATION ---<<< + */ + BoringWeaponAnimation() { + // select new mode change animation + FLOAT fWait = 0.0f; + switch (m_iCurrentWeapon) { + case WEAPON_KNIFE: fWait = KnifeBoring(); break; + case WEAPON_COLT: fWait = ColtBoring(); break; + case WEAPON_DOUBLECOLT: fWait = DoubleColtBoring(); break; + case WEAPON_SINGLESHOTGUN: fWait = SingleShotgunBoring(); break; + case WEAPON_DOUBLESHOTGUN: fWait = DoubleShotgunBoring(); break; + case WEAPON_TOMMYGUN: fWait = TommyGunBoring(); break; + case WEAPON_SNIPER: fWait = SniperBoring(); break; + case WEAPON_MINIGUN: fWait = MiniGunBoring(); break; + case WEAPON_ROCKETLAUNCHER: fWait = RocketLauncherBoring(); break; + case WEAPON_GRENADELAUNCHER: fWait = GrenadeLauncherBoring(); break; + case WEAPON_FLAMER: fWait = FlamerBoring(); break; + case WEAPON_CHAINSAW: fWait = ChainsawBoring(); break; + case WEAPON_LASER: fWait = LaserBoring(); break; + case WEAPON_IRONCANNON: fWait = CannonBoring(); break; + default: ASSERTALWAYS("Unknown weapon."); + } + if (fWait > 0.0f) { autowait(fWait); } + + return EBegin(); + }; + + + + /* + * >>>--- NO WEAPON ACTION ---<<< + */ + Idle() { + + wait() { + on (EBegin) : { + // play default anim + PlayDefaultAnim(); + + // weapon changed + if (m_bChangeWeapon) { + jump ChangeWeapon(); + } + // fire pressed start firing + if (m_bFireWeapon) { + jump Fire(); + } + // reload pressed + if (m_bReloadWeapon) { + jump Reload(); + } + resume; + } + // select weapon + on (ESelectWeapon eSelect) : { + // try to change weapon + SelectWeaponChange(eSelect.iWeapon); + if (m_bChangeWeapon) { + jump ChangeWeapon(); + } + resume; + } + // fire pressed + on (EFireWeapon) : { + jump Fire(); + } + // reload pressed + on (EReloadWeapon) : { + jump Reload(); + } + // boring weapon animation + on (EBoringWeapon) : { + call BoringWeaponAnimation(); + } + } + }; + + // weapons wait here while player is dead, so that stupid animations wouldn't play + Stopped() + { + // make sure we restore all rockets if we are holding the rocket launcher + if (m_iCurrentWeapon==WEAPON_ROCKETLAUNCHER) { + CModelObject *pmo = &(m_moWeapon.GetAttachmentModel(ROCKETLAUNCHER_ATTACHMENT_ROCKET1)->amo_moModelObject); + if (pmo) { pmo->StretchModel(FLOAT3D(1, 1, 1)); } + } + // kill all possible sounds, animations, etc + ResetWeaponMovingOffset(); + CPlayer &pl = (CPlayer&)*m_penPlayer; + pl.m_soWeapon0.Stop(); + pl.m_soWeapon1.Stop(); + pl.m_soWeapon2.Stop(); + pl.m_soWeapon3.Stop(); + PlayLightAnim(LIGHT_ANIM_NONE, 0); + wait() { + // after level change + on (EPostLevelChange) : { return EBegin(); }; + on (EStart) : { return EBegin(); }; + otherwise() : { resume; }; + } + } + + + + /* + * >>>--- M A I N ---<<< + */ + Main(EWeaponsInit eInit) { + // remember the initial parameters + ASSERT(eInit.penOwner!=NULL); + m_penPlayer = eInit.penOwner; + + // declare yourself as a void + InitAsVoid(); + SetFlags(GetFlags()|ENF_CROSSESLEVELS|ENF_NOTIFYLEVELCHANGE); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set weapon model for current weapon + SetCurrentWeaponModel(); + + // play default anim + PlayDefaultAnim(); + + wait() { + on (EBegin) : { call Idle(); } + on (ESelectWeapon eSelect) : { + // try to change weapon + SelectWeaponChange(eSelect.iWeapon); + resume; + }; + // before level change + on (EPreLevelChange) : { + // stop everything + m_bFireWeapon = FALSE; + call Stopped(); + resume; + } + on (EFireWeapon) : { + // start firing + m_bFireWeapon = TRUE; + resume; + } + on (EReleaseWeapon) : { + // stop firing + m_bFireWeapon = FALSE; + resume; + } + on (EReloadWeapon) : { + // reload wepon + m_bReloadWeapon = TRUE; + resume; + } + on (EStop) : { call Stopped(); } + on (EEnd) : { stop; } + } + + // cease to exist + Destroy(); + return; + }; +}; diff --git a/Sources/EntitiesMP/PlayerWeapons.h b/Sources/EntitiesMP/PlayerWeapons.h new file mode 100644 index 0000000..8752cfd --- /dev/null +++ b/Sources/EntitiesMP/PlayerWeapons.h @@ -0,0 +1,725 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_PlayerWeapons_INCLUDED +#define _EntitiesMP_PlayerWeapons_INCLUDED 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define EVENTCODE_EWeaponsInit 0x01920000 +class DECL_DLL EWeaponsInit : public CEntityEvent { +public: +EWeaponsInit(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOwner; +}; +DECL_DLL inline void ClearToDefault(EWeaponsInit &e) { e = EWeaponsInit(); } ; +#define EVENTCODE_ESelectWeapon 0x01920001 +class DECL_DLL ESelectWeapon : public CEntityEvent { +public: +ESelectWeapon(); +CEntityEvent *MakeCopy(void); +INDEX iWeapon; +}; +DECL_DLL inline void ClearToDefault(ESelectWeapon &e) { e = ESelectWeapon(); } ; +#define EVENTCODE_EBoringWeapon 0x01920002 +class DECL_DLL EBoringWeapon : public CEntityEvent { +public: +EBoringWeapon(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EBoringWeapon &e) { e = EBoringWeapon(); } ; +#define EVENTCODE_EFireWeapon 0x01920003 +class DECL_DLL EFireWeapon : public CEntityEvent { +public: +EFireWeapon(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EFireWeapon &e) { e = EFireWeapon(); } ; +#define EVENTCODE_EReleaseWeapon 0x01920004 +class DECL_DLL EReleaseWeapon : public CEntityEvent { +public: +EReleaseWeapon(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EReleaseWeapon &e) { e = EReleaseWeapon(); } ; +#define EVENTCODE_EReloadWeapon 0x01920005 +class DECL_DLL EReloadWeapon : public CEntityEvent { +public: +EReloadWeapon(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EReloadWeapon &e) { e = EReloadWeapon(); } ; +#define EVENTCODE_EWeaponChanged 0x01920006 +class DECL_DLL EWeaponChanged : public CEntityEvent { +public: +EWeaponChanged(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EWeaponChanged &e) { e = EWeaponChanged(); } ; +extern DECL_DLL CEntityPropertyEnumType WeaponType_enum; +enum WeaponType { + WEAPON_NONE = 0, + WEAPON_KNIFE = 1, + WEAPON_COLT = 2, + WEAPON_DOUBLECOLT = 3, + WEAPON_SINGLESHOTGUN = 4, + WEAPON_DOUBLESHOTGUN = 5, + WEAPON_TOMMYGUN = 6, + WEAPON_MINIGUN = 7, + WEAPON_ROCKETLAUNCHER = 8, + WEAPON_GRENADELAUNCHER = 9, + WEAPON_CHAINSAW = 10, + WEAPON_FLAMER = 11, + WEAPON_LASER = 12, + WEAPON_SNIPER = 13, + WEAPON_IRONCANNON = 14, + WEAPON_LAST = 15, +}; +DECL_DLL inline void ClearToDefault(WeaponType &e) { e = (WeaponType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CPlayerWeapons_DLLClass; +class DECL_DLL CPlayerWeapons : public CRationalEntity { +public: +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + virtual void SetDefaultProperties(void); + CEntityPointer m_penPlayer; + BOOL m_bFireWeapon; + BOOL m_bHasAmmo; + enum WeaponType m_iCurrentWeapon; + enum WeaponType m_iWantedWeapon; + enum WeaponType m_iPreviousWeapon; + INDEX m_iAvailableWeapons; + BOOL m_bChangeWeapon; + BOOL m_bReloadWeapon; + BOOL m_bMirrorFire; + INDEX m_iAnim; + FLOAT m_fAnimWaitTime; + FLOAT m_tmRangeSoundSpawned; + BOOL m_bSniperZoom; + FLOAT m_fSniperFOV; + FLOAT m_fSniperFOVlast; + CTString m_strLastTarget; + FLOAT m_tmTargetingStarted; + FLOAT m_tmLastTarget; + FLOAT m_tmSnoopingStarted; + CEntityPointer m_penTargeting; + CModelObject m_moWeapon; + CModelObject m_moWeaponSecond; + FLOAT m_tmWeaponChangeRequired; + CEntityPointer m_penRayHit; + FLOAT m_fRayHitDistance; + FLOAT m_fEnemyHealth; + FLOAT3D m_vRayHit; + FLOAT3D m_vRayHitLast; + FLOAT3D m_vBulletSource; + FLOAT3D m_vBulletTarget; + INDEX m_iBullets; + INDEX m_iMaxBullets; + INDEX m_iShells; + INDEX m_iMaxShells; + INDEX m_iRockets; + INDEX m_iMaxRockets; + INDEX m_iGrenades; + INDEX m_iMaxGrenades; + INDEX m_iNapalm; + INDEX m_iMaxNapalm; + INDEX m_iElectricity; + INDEX m_iMaxElectricity; + INDEX m_iIronBalls; + INDEX m_iMaxIronBalls; + INDEX m_iSniperBullets; + INDEX m_iMaxSniperBullets; + INDEX m_iKnifeStand; + INDEX m_iColtBullets; + FLOAT m_aMiniGun; + FLOAT m_aMiniGunLast; + FLOAT m_aMiniGunSpeed; + FLOAT3D m_iLastBulletPosition; + INDEX m_iBulletsOnFireStart; + FLOAT m_fSniperMaxFOV; + FLOAT m_fSniperMinFOV; + FLOAT m_fSnipingZoomSpeed; + BOOL m_bSniping; + FLOAT m_fMinimumZoomFOV; + FLOAT m_tmLastSniperFire; + CEntityPointer m_penFlame; + INDEX m_iLaserBarrel; + INDEX m_iFlare; + INDEX m_iSecondFlare; + FLOAT m_fWeaponDrawPowerOld; + FLOAT m_fWeaponDrawPower; + FLOAT m_tmDrawStartTime; + FLOAT m_tmFlamerStart; + FLOAT m_tmFlamerStop; + FLOAT m_tmLastChainsawSpray; + CEntityPointer m_penPrediction; +CEntity * penBullet; +CPlacement3D plBullet; +FLOAT3D vBulletDestination; + +#line 830 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void AddDependentsToPrediction(void); + +#line 837 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void Precache(void); + +#line 841 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayer * GetPlayer(void); + +#line 846 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CPlayerAnimator * GetAnimator(void); + +#line 852 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CModelObject * GetChainSawTeeth(void); + +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void DoRecoil(void); + +#line 877 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL HoldingFire(void); + +#line 884 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void RenderWeaponModel(CPerspectiveProjection3D & prProjection,CDrawPort * pdp, +#line 885 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT3D vViewerLightDirection,COLOR colViewerLight,COLOR colViewerAmbient, +#line 886 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL bRender,INDEX iEye); + +#line 1058 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void WeaponMovingOffset(FLOAT3D & plPos); + +#line 1097 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CheckTargetPrediction(CEntity * penTarget); + +#line 1157 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void UpdateTargetingInfo(void); + +#line 1277 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void RenderCrosshair(CProjection3D & prProjection,CDrawPort * pdp,CPlacement3D & plViewSource); + +#line 1409 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void ShowFlare(CModelObject & moWeapon,INDEX iAttachObject,INDEX iAttachFlare,FLOAT fSize); + +#line 1419 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void HideFlare(CModelObject & moWeapon,INDEX iAttachObject,INDEX iAttachFlare); + +#line 1425 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void SetFlare(INDEX iFlare,INDEX iAction); + +#line 1445 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void ControlFlareAttachment(void); + +#line 1519 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void PlayLightAnim(INDEX iAnim,ULONG ulFlags); + +#line 1528 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void SetCurrentWeaponModel(void); + +#line 1683 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void RotateMinigun(void); + +#line 1697 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CalcWeaponPosition3rdPersonView(FLOAT3D vPos,CPlacement3D & plPos,BOOL bResetZ); + +#line 1729 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CalcWeaponPosition(FLOAT3D vPos,CPlacement3D & plPos,BOOL bResetZ); + +#line 1765 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CalcLerpedWeaponPosition(FLOAT3D vPos,CPlacement3D & plPos,BOOL bResetZ); + +#line 1800 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CalcWeaponPositionImprecise(FLOAT3D vPos,CPlacement3D & plPos,BOOL bResetZ,FLOAT fImprecissionAngle); + +#line 1836 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void Setup3DSoundParameters(void); + +#line 1853 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL CutWithKnife(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fWide,FLOAT fThickness,FLOAT fDamage); + +#line 1958 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL CutWithChainsaw(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fWide,FLOAT fThickness,FLOAT fDamage); + +#line 2093 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void PrepareSniperBullet(FLOAT fX,FLOAT fY,FLOAT fDamage,FLOAT fImprecission); + +#line 2107 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void PrepareBullet(FLOAT fX,FLOAT fY,FLOAT fDamage); + +#line 2120 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void FireSniperBullet(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fDamage,FLOAT fImprecission); + +#line 2150 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void FireOneBullet(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fDamage); + +#line 2160 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void FireBullets(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fDamage,INDEX iBullets, +#line 2161 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT * afPositions,FLOAT fStretch,FLOAT fJitter); + +#line 2178 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void FireMachineBullet(FLOAT fX,FLOAT fY,FLOAT fRange,FLOAT fDamage, +#line 2179 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT fJitter,FLOAT fBulletSize); + +#line 2191 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void FireGrenade(INDEX iPower); + +#line 2208 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void FireRocket(void); + +#line 2248 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void GetFlamerSourcePlacement(CPlacement3D & plSource,CPlacement3D & plInFrontOfPipe); + +#line 2259 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void FireFlame(void); + +#line 2283 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void FireLaserRay(void); + +#line 2343 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void FireCannonBall(INDEX iPower); + +#line 2370 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void SpawnRangeSound(FLOAT fRange); + +#line 2383 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void ClearWeapons(void); + +#line 2398 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void ResetWeaponMovingOffset(void); + +#line 2405 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void InitializeWeapons(INDEX iGiveWeapons,INDEX iTakeWeapons,INDEX iTakeAmmo,FLOAT fMaxAmmoRatio); + +#line 2471 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX GetAmmo(void); + +#line 2493 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX GetMaxAmmo(void); + +#line 2514 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CheatOpen(void); + +#line 2522 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void CheatGiveAll(void); + +#line 2541 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void AddManaToPlayer(INDEX iMana); + +#line 2553 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void ClampAllAmmo(void); + +#line 2567 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void AddDefaultAmmoForWeapon(INDEX iWeapon,FLOAT fMaxAmmoRatio); + +#line 2669 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void DropWeapon(void); + +#line 2705 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL ReceiveWeapon(const CEntityEvent & ee); + +#line 2843 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL ReceiveAmmo(const CEntityEvent & ee); + +#line 2948 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL ReceivePackAmmo(const CEntityEvent & ee); + +#line 3011 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType GetStrongerWeapon(INDEX iWeapon); + +#line 3026 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +INDEX GetSelectedWeapon(WeaponType EwtSelectedWeapon); + +#line 3041 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType GetAltWeapon(WeaponType EwtWeapon); + +#line 3062 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL WeaponSelectOk(WeaponType wtToTry); + +#line 3083 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void SelectNewWeapon(); + +#line 3139 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL HasAmmo(WeaponType EwtWeapon); + +#line 3160 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void PlayDefaultAnim(void); + +#line 3218 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT KnifeBoring(void); + +#line 3229 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT ColtBoring(void); + +#line 3240 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT DoubleColtBoring(void); + +#line 3256 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT SingleShotgunBoring(void); + +#line 3267 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT DoubleShotgunBoring(void); + +#line 3279 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT TommyGunBoring(void); + +#line 3290 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT SniperBoring(void); + +#line 3298 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT MiniGunBoring(void); + +#line 3310 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT RocketLauncherBoring(void); + +#line 3316 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT GrenadeLauncherBoring(void); + +#line 3355 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT FlamerBoring(void); + +#line 3368 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT ChainsawBoring(void); + +#line 3380 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT LaserBoring(void); + +#line 3402 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FLOAT CannonBoring(void); + +#line 3415 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType FindRemapedPos(WeaponType wt); + +#line 3428 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType PrimaryToSecondary(WeaponType wt); + +#line 3447 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType SecondaryToPrimary(WeaponType wt); + +#line 3494 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +WeaponType FindWeaponInDirection(INDEX iDir); + +#line 3518 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void SelectWeaponChange(INDEX iSelect); + +#line 3576 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +void MinigunSmoke(); + +#line 3621 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BOOL SniperZoomDiscrete(INDEX iDirection,BOOL & bZoomChanged); +#define STATE_CPlayerWeapons_ChangeWeapon 0x01920007 + BOOL +#line 3658 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChangeWeapon(const CEntityEvent &__eeInput); + BOOL H0x01920008_ChangeWeapon_01(const CEntityEvent &__eeInput); + BOOL H0x01920009_ChangeWeapon_02(const CEntityEvent &__eeInput); + BOOL H0x0192000a_ChangeWeapon_03(const CEntityEvent &__eeInput); + BOOL H0x0192000b_ChangeWeapon_04(const CEntityEvent &__eeInput); + BOOL H0x0192000c_ChangeWeapon_05(const CEntityEvent &__eeInput); + BOOL H0x0192000d_ChangeWeapon_06(const CEntityEvent &__eeInput); + BOOL H0x0192000e_ChangeWeapon_07(const CEntityEvent &__eeInput); + BOOL H0x0192000f_ChangeWeapon_08(const CEntityEvent &__eeInput); + BOOL H0x01920010_ChangeWeapon_09(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_PutDown 0x01920011 + BOOL +#line 3720 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PutDown(const CEntityEvent &__eeInput); + BOOL H0x01920012_PutDown_01(const CEntityEvent &__eeInput); + BOOL H0x01920013_PutDown_02(const CEntityEvent &__eeInput); + BOOL H0x01920014_PutDown_03(const CEntityEvent &__eeInput); + BOOL H0x01920015_PutDown_04(const CEntityEvent &__eeInput); + BOOL H0x01920016_PutDown_05(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_BringUp 0x01920017 + BOOL +#line 3829 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BringUp(const CEntityEvent &__eeInput); + BOOL H0x01920018_BringUp_01(const CEntityEvent &__eeInput); + BOOL H0x01920019_BringUp_02(const CEntityEvent &__eeInput); + BOOL H0x0192001a_BringUp_03(const CEntityEvent &__eeInput); + BOOL H0x0192001b_BringUp_04(const CEntityEvent &__eeInput); + BOOL H0x0192001c_BringUp_05(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_Fire 0x0192001d + BOOL +#line 3957 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x0192001e_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x0192001f_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x01920020_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x01920021_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x01920022_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x01920023_Fire_06(const CEntityEvent &__eeInput); + BOOL H0x01920024_Fire_07(const CEntityEvent &__eeInput); + BOOL H0x01920025_Fire_08(const CEntityEvent &__eeInput); + BOOL H0x01920026_Fire_09(const CEntityEvent &__eeInput); + BOOL H0x01920027_Fire_10(const CEntityEvent &__eeInput); + BOOL H0x01920028_Fire_11(const CEntityEvent &__eeInput); + BOOL H0x01920029_Fire_12(const CEntityEvent &__eeInput); + BOOL H0x0192002a_Fire_13(const CEntityEvent &__eeInput); + BOOL H0x0192002b_Fire_14(const CEntityEvent &__eeInput); + BOOL H0x0192002c_Fire_15(const CEntityEvent &__eeInput); + BOOL H0x0192002d_Fire_16(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_SwingKnife 0x0192002e + BOOL +#line 4042 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SwingKnife(const CEntityEvent &__eeInput); + BOOL H0x0192002f_SwingKnife_01(const CEntityEvent &__eeInput); + BOOL H0x01920030_SwingKnife_02(const CEntityEvent &__eeInput); + BOOL H0x01920031_SwingKnife_03(const CEntityEvent &__eeInput); + BOOL H0x01920032_SwingKnife_04(const CEntityEvent &__eeInput); + BOOL H0x01920033_SwingKnife_05(const CEntityEvent &__eeInput); + BOOL H0x01920034_SwingKnife_06(const CEntityEvent &__eeInput); + BOOL H0x01920035_SwingKnife_07(const CEntityEvent &__eeInput); + BOOL H0x01920036_SwingKnife_08(const CEntityEvent &__eeInput); + BOOL H0x01920037_SwingKnife_09(const CEntityEvent &__eeInput); + BOOL H0x01920038_SwingKnife_10(const CEntityEvent &__eeInput); + BOOL H0x01920039_SwingKnife_11(const CEntityEvent &__eeInput); + BOOL H0x0192003a_SwingKnife_12(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FireColt 0x0192003b + BOOL +#line 4094 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireColt(const CEntityEvent &__eeInput); + BOOL H0x0192003c_FireColt_01(const CEntityEvent &__eeInput); + BOOL H0x0192003d_FireColt_02(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_ReloadColt 0x0192003e + BOOL +#line 4144 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ReloadColt(const CEntityEvent &__eeInput); + BOOL H0x0192003f_ReloadColt_01(const CEntityEvent &__eeInput); + BOOL H0x01920040_ReloadColt_02(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FireDoubleColt 0x01920041 + BOOL +#line 4160 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireDoubleColt(const CEntityEvent &__eeInput); + BOOL H0x01920042_FireDoubleColt_01(const CEntityEvent &__eeInput); + BOOL H0x01920043_FireDoubleColt_02(const CEntityEvent &__eeInput); + BOOL H0x01920044_FireDoubleColt_03(const CEntityEvent &__eeInput); + BOOL H0x01920045_FireDoubleColt_04(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_ReloadDoubleColt 0x01920046 + BOOL +#line 4236 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ReloadDoubleColt(const CEntityEvent &__eeInput); + BOOL H0x01920047_ReloadDoubleColt_01(const CEntityEvent &__eeInput); + BOOL H0x01920048_ReloadDoubleColt_02(const CEntityEvent &__eeInput); + BOOL H0x01920049_ReloadDoubleColt_03(const CEntityEvent &__eeInput); + BOOL H0x0192004a_ReloadDoubleColt_04(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FireSingleShotgun 0x0192004b + BOOL +#line 4261 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireSingleShotgun(const CEntityEvent &__eeInput); + BOOL H0x0192004c_FireSingleShotgun_01(const CEntityEvent &__eeInput); + BOOL H0x0192004d_FireSingleShotgun_02(const CEntityEvent &__eeInput); + BOOL H0x0192004e_FireSingleShotgun_03(const CEntityEvent &__eeInput); + BOOL H0x0192004f_FireSingleShotgun_04(const CEntityEvent &__eeInput); + BOOL H0x01920050_FireSingleShotgun_05(const CEntityEvent &__eeInput); + BOOL H0x01920051_FireSingleShotgun_06(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FireDoubleShotgun 0x01920052 + BOOL +#line 4358 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireDoubleShotgun(const CEntityEvent &__eeInput); + BOOL H0x01920053_FireDoubleShotgun_01(const CEntityEvent &__eeInput); + BOOL H0x01920054_FireDoubleShotgun_02(const CEntityEvent &__eeInput); + BOOL H0x01920055_FireDoubleShotgun_03(const CEntityEvent &__eeInput); + BOOL H0x01920056_FireDoubleShotgun_04(const CEntityEvent &__eeInput); + BOOL H0x01920057_FireDoubleShotgun_05(const CEntityEvent &__eeInput); + BOOL H0x01920058_FireDoubleShotgun_06(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_TommyGunStart 0x01920059 + BOOL +#line 4447 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TommyGunStart(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_TommyGunStop 0x0192005a + BOOL +#line 4458 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TommyGunStop(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FireTommyGun 0x0192005b + BOOL +#line 4489 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireTommyGun(const CEntityEvent &__eeInput); + BOOL H0x0192005c_FireTommyGun_01(const CEntityEvent &__eeInput); + BOOL H0x0192005d_FireTommyGun_02(const CEntityEvent &__eeInput); + BOOL H0x0192005e_FireTommyGun_03(const CEntityEvent &__eeInput); + BOOL H0x0192005f_FireTommyGun_04(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FireSniper 0x01920060 + BOOL +#line 4549 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireSniper(const CEntityEvent &__eeInput); + BOOL H0x01920061_FireSniper_01(const CEntityEvent &__eeInput); + BOOL H0x01920062_FireSniper_02(const CEntityEvent &__eeInput); + BOOL H0x01920063_FireSniper_03(const CEntityEvent &__eeInput); + BOOL H0x01920064_FireSniper_04(const CEntityEvent &__eeInput); + BOOL H0x01920065_FireSniper_05(const CEntityEvent &__eeInput); + BOOL H0x01920066_FireSniper_06(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_MiniGunSpinUp 0x01920067 + BOOL +#line 4636 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MiniGunSpinUp(const CEntityEvent &__eeInput); + BOOL H0x01920068_MiniGunSpinUp_01(const CEntityEvent &__eeInput); + BOOL H0x01920069_MiniGunSpinUp_02(const CEntityEvent &__eeInput); + BOOL H0x0192006a_MiniGunSpinUp_03(const CEntityEvent &__eeInput); + BOOL H0x0192006b_MiniGunSpinUp_04(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_MiniGunFire 0x0192006c + BOOL +#line 4677 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MiniGunFire(const CEntityEvent &__eeInput); + BOOL H0x0192006d_MiniGunFire_01(const CEntityEvent &__eeInput); + BOOL H0x0192006e_MiniGunFire_02(const CEntityEvent &__eeInput); + BOOL H0x0192006f_MiniGunFire_03(const CEntityEvent &__eeInput); + BOOL H0x01920070_MiniGunFire_04(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_MiniGunSpinDown 0x01920071 + BOOL +#line 4797 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MiniGunSpinDown(const CEntityEvent &__eeInput); + BOOL H0x01920072_MiniGunSpinDown_01(const CEntityEvent &__eeInput); + BOOL H0x01920073_MiniGunSpinDown_02(const CEntityEvent &__eeInput); + BOOL H0x01920074_MiniGunSpinDown_03(const CEntityEvent &__eeInput); + BOOL H0x01920075_MiniGunSpinDown_04(const CEntityEvent &__eeInput); + BOOL H0x01920076_MiniGunSpinDown_05(const CEntityEvent &__eeInput); + BOOL H0x01920077_MiniGunSpinDown_06(const CEntityEvent &__eeInput); + BOOL H0x01920078_MiniGunSpinDown_07(const CEntityEvent &__eeInput); + BOOL H0x01920079_MiniGunSpinDown_08(const CEntityEvent &__eeInput); + BOOL H0x0192007a_MiniGunSpinDown_09(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FireRocketLauncher 0x0192007b + BOOL +#line 4855 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireRocketLauncher(const CEntityEvent &__eeInput); + BOOL H0x0192007c_FireRocketLauncher_01(const CEntityEvent &__eeInput); + BOOL H0x0192007d_FireRocketLauncher_02(const CEntityEvent &__eeInput); + BOOL H0x0192007e_FireRocketLauncher_03(const CEntityEvent &__eeInput); + BOOL H0x0192007f_FireRocketLauncher_04(const CEntityEvent &__eeInput); + BOOL H0x01920080_FireRocketLauncher_05(const CEntityEvent &__eeInput); + BOOL H0x01920081_FireRocketLauncher_06(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FireGrenadeLauncher 0x01920082 + BOOL +#line 4897 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireGrenadeLauncher(const CEntityEvent &__eeInput); + BOOL H0x01920083_FireGrenadeLauncher_01(const CEntityEvent &__eeInput); + BOOL H0x01920084_FireGrenadeLauncher_02(const CEntityEvent &__eeInput); + BOOL H0x01920085_FireGrenadeLauncher_03(const CEntityEvent &__eeInput); + BOOL H0x01920086_FireGrenadeLauncher_04(const CEntityEvent &__eeInput); + BOOL H0x01920087_FireGrenadeLauncher_05(const CEntityEvent &__eeInput); + BOOL H0x01920088_FireGrenadeLauncher_06(const CEntityEvent &__eeInput); + BOOL H0x01920089_FireGrenadeLauncher_07(const CEntityEvent &__eeInput); + BOOL H0x0192008a_FireGrenadeLauncher_08(const CEntityEvent &__eeInput); + BOOL H0x0192008b_FireGrenadeLauncher_09(const CEntityEvent &__eeInput); + BOOL H0x0192008c_FireGrenadeLauncher_10(const CEntityEvent &__eeInput); + BOOL H0x0192008d_FireGrenadeLauncher_11(const CEntityEvent &__eeInput); + BOOL H0x0192008e_FireGrenadeLauncher_12(const CEntityEvent &__eeInput); + BOOL H0x0192008f_FireGrenadeLauncher_13(const CEntityEvent &__eeInput); + BOOL H0x01920090_FireGrenadeLauncher_14(const CEntityEvent &__eeInput); + BOOL H0x01920091_FireGrenadeLauncher_15(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FlamerStart 0x01920092 + BOOL +#line 5042 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FlamerStart(const CEntityEvent &__eeInput); + BOOL H0x01920093_FlamerStart_01(const CEntityEvent &__eeInput); + BOOL H0x01920094_FlamerStart_02(const CEntityEvent &__eeInput); + BOOL H0x01920095_FlamerStart_03(const CEntityEvent &__eeInput); + BOOL H0x01920096_FlamerStart_04(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FlamerFire 0x01920097 + BOOL +#line 5062 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FlamerFire(const CEntityEvent &__eeInput); + BOOL H0x01920098_FlamerFire_01(const CEntityEvent &__eeInput); + BOOL H0x01920099_FlamerFire_02(const CEntityEvent &__eeInput); + BOOL H0x0192009a_FlamerFire_03(const CEntityEvent &__eeInput); + BOOL H0x0192009b_FlamerFire_04(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FlamerStop 0x0192009c + BOOL +#line 5079 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FlamerStop(const CEntityEvent &__eeInput); + BOOL H0x0192009d_FlamerStop_01(const CEntityEvent &__eeInput); + BOOL H0x0192009e_FlamerStop_02(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_ChainsawFire 0x0192009f + BOOL +#line 5104 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChainsawFire(const CEntityEvent &__eeInput); + BOOL H0x019200a0_ChainsawFire_01(const CEntityEvent &__eeInput); + BOOL H0x019200a1_ChainsawFire_02(const CEntityEvent &__eeInput); + BOOL H0x019200a2_ChainsawFire_03(const CEntityEvent &__eeInput); + BOOL H0x019200a3_ChainsawFire_04(const CEntityEvent &__eeInput); + BOOL H0x019200a4_ChainsawFire_05(const CEntityEvent &__eeInput); + BOOL H0x019200a5_ChainsawFire_06(const CEntityEvent &__eeInput); + BOOL H0x019200a6_ChainsawFire_07(const CEntityEvent &__eeInput); + BOOL H0x019200a7_ChainsawFire_08(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_ChainsawBringUp 0x019200a8 + BOOL +#line 5180 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChainsawBringUp(const CEntityEvent &__eeInput); + BOOL H0x019200a9_ChainsawBringUp_01(const CEntityEvent &__eeInput); + BOOL H0x019200aa_ChainsawBringUp_02(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_FireLaser 0x019200ab + BOOL +#line 5189 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireLaser(const CEntityEvent &__eeInput); + BOOL H0x019200ac_FireLaser_01(const CEntityEvent &__eeInput); + BOOL H0x019200ad_FireLaser_02(const CEntityEvent &__eeInput); + BOOL H0x019200ae_FireLaser_03(const CEntityEvent &__eeInput); + BOOL H0x019200af_FireLaser_04(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_CannonFireStart 0x019200b0 + BOOL +#line 5280 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CannonFireStart(const CEntityEvent &__eeInput); + BOOL H0x019200b1_CannonFireStart_01(const CEntityEvent &__eeInput); + BOOL H0x019200b2_CannonFireStart_02(const CEntityEvent &__eeInput); + BOOL H0x019200b3_CannonFireStart_03(const CEntityEvent &__eeInput); + BOOL H0x019200b4_CannonFireStart_04(const CEntityEvent &__eeInput); + BOOL H0x019200b5_CannonFireStart_05(const CEntityEvent &__eeInput); + BOOL H0x019200b6_CannonFireStart_06(const CEntityEvent &__eeInput); + BOOL H0x019200b7_CannonFireStart_07(const CEntityEvent &__eeInput); + BOOL H0x019200b8_CannonFireStart_08(const CEntityEvent &__eeInput); + BOOL H0x019200b9_CannonFireStart_09(const CEntityEvent &__eeInput); + BOOL H0x019200ba_CannonFireStart_10(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_Reload 0x019200bb + BOOL +#line 5389 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Reload(const CEntityEvent &__eeInput); + BOOL H0x019200bc_Reload_01(const CEntityEvent &__eeInput); + BOOL H0x019200bd_Reload_02(const CEntityEvent &__eeInput); + BOOL H0x019200be_Reload_03(const CEntityEvent &__eeInput); + BOOL H0x019200bf_Reload_04(const CEntityEvent &__eeInput); + BOOL H0x019200c0_Reload_05(const CEntityEvent &__eeInput); + BOOL H0x019200c1_Reload_06(const CEntityEvent &__eeInput); + BOOL H0x019200c2_Reload_07(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_ChangeKnifeStand 0x019200c3 + BOOL +#line 5408 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChangeKnifeStand(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_ChangeToIronCannon 0x019200c4 + BOOL +#line 5424 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChangeToIronCannon(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_BoringWeaponAnimation 0x019200c5 + BOOL +#line 5463 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BoringWeaponAnimation(const CEntityEvent &__eeInput); + BOOL H0x019200c6_BoringWeaponAnimation_01(const CEntityEvent &__eeInput); + BOOL H0x019200c7_BoringWeaponAnimation_02(const CEntityEvent &__eeInput); + BOOL H0x019200c8_BoringWeaponAnimation_03(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_Idle 0x019200c9 + BOOL +#line 5493 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Idle(const CEntityEvent &__eeInput); + BOOL H0x019200ca_Idle_01(const CEntityEvent &__eeInput); + BOOL H0x019200cb_Idle_02(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_Stopped 0x019200cc + BOOL +#line 5539 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Stopped(const CEntityEvent &__eeInput); + BOOL H0x019200cd_Stopped_01(const CEntityEvent &__eeInput); + BOOL H0x019200ce_Stopped_02(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeapons_Main 1 + BOOL +#line 5567 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x019200cf_Main_01(const CEntityEvent &__eeInput); + BOOL H0x019200d0_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_PlayerWeapons_INCLUDED diff --git a/Sources/EntitiesMP/PlayerWeaponsEffects.cpp b/Sources/EntitiesMP/PlayerWeaponsEffects.cpp new file mode 100644 index 0000000..ffa81c7 --- /dev/null +++ b/Sources/EntitiesMP/PlayerWeaponsEffects.cpp @@ -0,0 +1,172 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" + +#include "StdH.h" +#define EPF_MODEL_SHELL (EPF_ONBLOCK_BOUNCE|EPF_TRANSLATEDBYGRAVITY|EPF_MOVABLE) +#define ECF_MODEL_SHELL ( \ + ((ECBI_BRUSH|ECBI_MODEL_HOLDER)< +#include +CEntityEvent *EWeaponEffectInit::MakeCopy(void) { CEntityEvent *peeCopy = new EWeaponEffectInit(*this); return peeCopy;} +EWeaponEffectInit::EWeaponEffectInit() : CEntityEvent(EVENTCODE_EWeaponEffectInit) {; + ClearToDefault(penOwner); + ClearToDefault(EwetEffect); +}; +#line 25 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" + +void CPlayerWeaponsEffects_Precache(void) +{ + CDLLEntityClass *pdec = &CPlayerWeaponsEffects_DLLClass; + pdec->PrecacheModel(MODEL_SG_SHELL); + pdec->PrecacheTexture(TEXTURE_SG_SHELL); + pdec->PrecacheModel(MODEL_MG_SHELL); + pdec->PrecacheTexture(TEXTURE_MG_SHELL); +} + +void CPlayerWeaponsEffects::SetDefaultProperties(void) { + m_penOwner = NULL; + m_EwetEffect = WET_SHOTGUNSHELL ; + m_penPrediction = NULL; + CMovableEntity::SetDefaultProperties(); +} +BOOL CPlayerWeaponsEffects:: +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +ShotgunShell(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeaponsEffects_ShotgunShell + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeaponsEffects::ShotgunShell expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +InitAsModel (); +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetPhysicsFlags (EPF_MODEL_SHELL ); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetCollisionFlags (ECF_MODEL_SHELL ); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +GetModelObject () -> StretchModel (FLOAT3D (0.5f , 0.5f , 0.5f)); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetModel (MODEL_SG_SHELL ); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +ModelChangeNotify (); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetModelMainTexture (TEXTURE_SG_SHELL ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +LaunchAsFreeProjectile (FLOAT3D (FRnd () + 2.0f , FRnd () + 5.0f , - FRnd () - 2.0f) , (CMovableEntity *) & * m_penOwner ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetTimerAfter(1.5f); +Jump(STATE_CURRENT, 0x01950002, FALSE, EBegin());return TRUE;}BOOL CPlayerWeaponsEffects::H0x01950002_ShotgunShell_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01950002 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01950003, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeaponsEffects::H0x01950003_ShotgunShell_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01950003 +; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +Return(STATE_CURRENT,EEnd ()); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeaponsEffects:: +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +MachinegunShell(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeaponsEffects_MachinegunShell + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPlayerWeaponsEffects::MachinegunShell expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +InitAsModel (); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetPhysicsFlags (EPF_MODEL_SHELL ); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetCollisionFlags (ECF_MODEL_SHELL ); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +GetModelObject () -> StretchModel (FLOAT3D (0.5f , 0.5f , 0.5f)); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetModel (MODEL_MG_SHELL ); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +ModelChangeNotify (); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetModelMainTexture (TEXTURE_MG_SHELL ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +LaunchAsFreeProjectile (FLOAT3D (FRnd () + 2.0f , FRnd () + 5.0f , - FRnd () - 2.0f) , (CMovableEntity *) & * m_penOwner ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x01950005, FALSE, EBegin());return TRUE;}BOOL CPlayerWeaponsEffects::H0x01950005_MachinegunShell_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01950005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01950006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPlayerWeaponsEffects::H0x01950006_MachinegunShell_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01950006 +; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +Return(STATE_CURRENT,EEnd ()); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPlayerWeaponsEffects:: +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPlayerWeaponsEffects_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EWeaponEffectInit, "CPlayerWeaponsEffects::Main expects 'EWeaponEffectInit' as input!"); const EWeaponEffectInit &eInit = (const EWeaponEffectInit &)__eeInput; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +ASSERT (eInit . penOwner != NULL ); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +m_penOwner = eInit . penOwner ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +m_EwetEffect = eInit . EwetEffect ; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +SetPredictable (TRUE ); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +if(!(m_EwetEffect == WET_SHOTGUNSHELL )){ Jump(STATE_CURRENT,0x0195000e, FALSE, EInternal());return TRUE;} +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +STATE_CPlayerWeaponsEffects_ShotgunShell, TRUE; +Jump(STATE_CURRENT, 0x01950007, FALSE, EBegin());return TRUE;}BOOL CPlayerWeaponsEffects::H0x01950007_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01950007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayerWeaponsEffects_ShotgunShell, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01950008, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayerWeaponsEffects::H0x01950008_Main_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01950008 +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x0195000d, FALSE, EInternal());return TRUE;}BOOL CPlayerWeaponsEffects::H0x0195000e_Main_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0195000e +if(!(m_EwetEffect == WET_MACHINEGUNSHELL )){ Jump(STATE_CURRENT,0x0195000c, FALSE, EInternal());return TRUE;} +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +STATE_CPlayerWeaponsEffects_MachinegunShell, TRUE; +Jump(STATE_CURRENT, 0x01950009, FALSE, EBegin());return TRUE;}BOOL CPlayerWeaponsEffects::H0x01950009_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01950009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPlayerWeaponsEffects_MachinegunShell, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x0195000a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPlayerWeaponsEffects::H0x0195000a_Main_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0195000a +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x0195000b, FALSE, EInternal());return TRUE;}BOOL CPlayerWeaponsEffects::H0x0195000c_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0195000c +{ +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +ASSERTALWAYS ("Uknown weapon effect type"); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +}Jump(STATE_CURRENT,0x0195000b, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeaponsEffects::H0x0195000b_Main_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0195000b +Jump(STATE_CURRENT,0x0195000d, FALSE, EInternal());return TRUE;} +BOOL CPlayerWeaponsEffects::H0x0195000d_Main_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0195000d + +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +Destroy (); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +Return(STATE_CURRENT,EVoid()); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/PlayerWeaponsEffects.es b/Sources/EntitiesMP/PlayerWeaponsEffects.es new file mode 100644 index 0000000..d18d17b --- /dev/null +++ b/Sources/EntitiesMP/PlayerWeaponsEffects.es @@ -0,0 +1,110 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +405 +%{ +#include "StdH.h" +#define EPF_MODEL_SHELL (EPF_ONBLOCK_BOUNCE|EPF_TRANSLATEDBYGRAVITY|EPF_MOVABLE) +#define ECF_MODEL_SHELL ( \ + ((ECBI_BRUSH|ECBI_MODEL_HOLDER)<PrecacheModel(MODEL_SG_SHELL); + pdec->PrecacheTexture(TEXTURE_SG_SHELL); + pdec->PrecacheModel(MODEL_MG_SHELL); + pdec->PrecacheTexture(TEXTURE_MG_SHELL); +} +%} + +class CPlayerWeaponsEffects: CMovableEntity { +name "Player Weapons Effects"; +thumbnail ""; +features "CanBePredictable"; + +properties: + 1 CEntityPointer m_penOwner, // class which owns it + 2 enum WeaponEffectType m_EwetEffect = WET_SHOTGUNSHELL, // weapon effect type + +components: +// ************** SHOTGUN SHELL ************ + 1 model MODEL_SG_SHELL "Models\\Weapons\\SingleShotgun\\Shell\\Shell.mdl", + 2 texture TEXTURE_SG_SHELL "Models\\Weapons\\SingleShotgun\\Shell\\Shell.tex", +// ************** MACHINEGUN SHELL ************ + 3 model MODEL_MG_SHELL "Models\\Weapons\\Minigun\\Shell\\Shell.mdl", + 4 texture TEXTURE_MG_SHELL "Models\\Weapons\\Minigun\\Shell\\Shell.tex", + +functions: +procedures: + ShotgunShell(EVoid) { + // init as model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_SHELL); + SetCollisionFlags(ECF_MODEL_SHELL); + // set appearance + GetModelObject()->StretchModel(FLOAT3D(0.5f, 0.5f, 0.5f)); + SetModel(MODEL_SG_SHELL); + ModelChangeNotify(); + SetModelMainTexture(TEXTURE_SG_SHELL); + // speed + LaunchAsFreeProjectile(FLOAT3D(FRnd()+2.0f, FRnd()+5.0f, -FRnd()-2.0f), (CMovableEntity*)&*m_penOwner); + // wait a while + autowait(1.5f); + return EEnd(); + }; + MachinegunShell(EVoid) { + // init as model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_SHELL); + SetCollisionFlags(ECF_MODEL_SHELL); + // set appearance + GetModelObject()->StretchModel(FLOAT3D(0.5f, 0.5f, 0.5f)); + SetModel(MODEL_MG_SHELL); + ModelChangeNotify(); + SetModelMainTexture(TEXTURE_MG_SHELL); + // speed + LaunchAsFreeProjectile(FLOAT3D(FRnd()+2.0f, FRnd()+5.0f, -FRnd()-2.0f), (CMovableEntity*)&*m_penOwner); + // wait a while + autowait(0.5f); + return EEnd(); + }; + + Main(EWeaponEffectInit eInit) { + // remember the initial parameters + ASSERT(eInit.penOwner!=NULL); + m_penOwner = eInit.penOwner; + m_EwetEffect = eInit.EwetEffect; + SetFlags(GetFlags()|ENF_SEETHROUGH); + SetPredictable(TRUE); + + if (m_EwetEffect==WET_SHOTGUNSHELL) { + autocall ShotgunShell() EEnd; + } else if (m_EwetEffect==WET_MACHINEGUNSHELL) { + autocall MachinegunShell() EEnd; + } else { + ASSERTALWAYS("Uknown weapon effect type"); + } + + // cease to exist + Destroy(); + + return; + }; +}; + diff --git a/Sources/EntitiesMP/PlayerWeaponsEffects.h b/Sources/EntitiesMP/PlayerWeaponsEffects.h new file mode 100644 index 0000000..3b9903b --- /dev/null +++ b/Sources/EntitiesMP/PlayerWeaponsEffects.h @@ -0,0 +1,57 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_PlayerWeaponsEffects_INCLUDED +#define _EntitiesMP_PlayerWeaponsEffects_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType WeaponEffectType_enum; +enum WeaponEffectType { + WET_SHOTGUNSHELL = 0, + WET_MACHINEGUNSHELL = 1, +}; +DECL_DLL inline void ClearToDefault(WeaponEffectType &e) { e = (WeaponEffectType)0; } ; +#define EVENTCODE_EWeaponEffectInit 0x01950000 +class DECL_DLL EWeaponEffectInit : public CEntityEvent { +public: +EWeaponEffectInit(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOwner; +enum WeaponEffectType EwetEffect; +}; +DECL_DLL inline void ClearToDefault(EWeaponEffectInit &e) { e = EWeaponEffectInit(); } ; +extern "C" DECL_DLL CDLLEntityClass CPlayerWeaponsEffects_DLLClass; +class CPlayerWeaponsEffects : public CMovableEntity { +public: +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penOwner; + enum WeaponEffectType m_EwetEffect; + CEntityPointer m_penPrediction; +#define STATE_CPlayerWeaponsEffects_ShotgunShell 0x01950001 + BOOL +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +ShotgunShell(const CEntityEvent &__eeInput); + BOOL H0x01950002_ShotgunShell_01(const CEntityEvent &__eeInput); + BOOL H0x01950003_ShotgunShell_02(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeaponsEffects_MachinegunShell 0x01950004 + BOOL +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +MachinegunShell(const CEntityEvent &__eeInput); + BOOL H0x01950005_MachinegunShell_01(const CEntityEvent &__eeInput); + BOOL H0x01950006_MachinegunShell_02(const CEntityEvent &__eeInput); +#define STATE_CPlayerWeaponsEffects_Main 1 + BOOL +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01950007_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01950008_Main_02(const CEntityEvent &__eeInput); + BOOL H0x01950009_Main_03(const CEntityEvent &__eeInput); + BOOL H0x0195000a_Main_04(const CEntityEvent &__eeInput); + BOOL H0x0195000b_Main_05(const CEntityEvent &__eeInput); + BOOL H0x0195000c_Main_06(const CEntityEvent &__eeInput); + BOOL H0x0195000d_Main_07(const CEntityEvent &__eeInput); + BOOL H0x0195000e_Main_08(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_PlayerWeaponsEffects_INCLUDED diff --git a/Sources/EntitiesMP/PlayerWeaponsEffects_tables.h b/Sources/EntitiesMP/PlayerWeaponsEffects_tables.h new file mode 100644 index 0000000..6374641 --- /dev/null +++ b/Sources/EntitiesMP/PlayerWeaponsEffects_tables.h @@ -0,0 +1,65 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(WeaponEffectType) + EP_ENUMVALUE(WET_SHOTGUNSHELL, ""), + EP_ENUMVALUE(WET_MACHINEGUNSHELL, ""), +EP_ENUMEND(WeaponEffectType); + +#define ENTITYCLASS CPlayerWeaponsEffects + +CEntityProperty CPlayerWeaponsEffects_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000195<<8)+1, offsetof(CPlayerWeaponsEffects, m_penOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &WeaponEffectType_enum, (0x00000195<<8)+2, offsetof(CPlayerWeaponsEffects, m_EwetEffect), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000195<<8)+255, offsetof(CPlayerWeaponsEffects, m_penPrediction), "", 0, 0, 0), +}; +#define CPlayerWeaponsEffects_propertiesct ARRAYCOUNT(CPlayerWeaponsEffects_properties) + +CEntityComponent CPlayerWeaponsEffects_components[] = { +#define MODEL_SG_SHELL ((0x00000195<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_SG_SHELL, "EFNM" "Models\\Weapons\\SingleShotgun\\Shell\\Shell.mdl"), +#define TEXTURE_SG_SHELL ((0x00000195<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_SG_SHELL, "EFNM" "Models\\Weapons\\SingleShotgun\\Shell\\Shell.tex"), +#define MODEL_MG_SHELL ((0x00000195<<8)+3) + CEntityComponent(ECT_MODEL, MODEL_MG_SHELL, "EFNM" "Models\\Weapons\\Minigun\\Shell\\Shell.mdl"), +#define TEXTURE_MG_SHELL ((0x00000195<<8)+4) + CEntityComponent(ECT_TEXTURE, TEXTURE_MG_SHELL, "EFNM" "Models\\Weapons\\Minigun\\Shell\\Shell.tex"), +}; +#define CPlayerWeaponsEffects_componentsct ARRAYCOUNT(CPlayerWeaponsEffects_components) + +CEventHandlerEntry CPlayerWeaponsEffects_handlers[] = { + {0x01950001, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects:: +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +ShotgunShell),DEBUGSTRING("CPlayerWeaponsEffects::ShotgunShell")}, + {0x01950002, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x01950002_ShotgunShell_01), DEBUGSTRING("CPlayerWeaponsEffects::H0x01950002_ShotgunShell_01")}, + {0x01950003, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x01950003_ShotgunShell_02), DEBUGSTRING("CPlayerWeaponsEffects::H0x01950003_ShotgunShell_02")}, + {0x01950004, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects:: +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +MachinegunShell),DEBUGSTRING("CPlayerWeaponsEffects::MachinegunShell")}, + {0x01950005, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x01950005_MachinegunShell_01), DEBUGSTRING("CPlayerWeaponsEffects::H0x01950005_MachinegunShell_01")}, + {0x01950006, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x01950006_MachinegunShell_02), DEBUGSTRING("CPlayerWeaponsEffects::H0x01950006_MachinegunShell_02")}, + {1, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects:: +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeaponsEffects.es" +Main),DEBUGSTRING("CPlayerWeaponsEffects::Main")}, + {0x01950007, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x01950007_Main_01), DEBUGSTRING("CPlayerWeaponsEffects::H0x01950007_Main_01")}, + {0x01950008, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x01950008_Main_02), DEBUGSTRING("CPlayerWeaponsEffects::H0x01950008_Main_02")}, + {0x01950009, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x01950009_Main_03), DEBUGSTRING("CPlayerWeaponsEffects::H0x01950009_Main_03")}, + {0x0195000a, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x0195000a_Main_04), DEBUGSTRING("CPlayerWeaponsEffects::H0x0195000a_Main_04")}, + {0x0195000b, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x0195000b_Main_05), DEBUGSTRING("CPlayerWeaponsEffects::H0x0195000b_Main_05")}, + {0x0195000c, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x0195000c_Main_06), DEBUGSTRING("CPlayerWeaponsEffects::H0x0195000c_Main_06")}, + {0x0195000d, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x0195000d_Main_07), DEBUGSTRING("CPlayerWeaponsEffects::H0x0195000d_Main_07")}, + {0x0195000e, -1, CEntity::pEventHandler(&CPlayerWeaponsEffects::H0x0195000e_Main_08), DEBUGSTRING("CPlayerWeaponsEffects::H0x0195000e_Main_08")}, +}; +#define CPlayerWeaponsEffects_handlersct ARRAYCOUNT(CPlayerWeaponsEffects_handlers) + +CEntity *CPlayerWeaponsEffects_New(void) { return new CPlayerWeaponsEffects; }; +void CPlayerWeaponsEffects_OnInitClass(void) {}; +void CPlayerWeaponsEffects_OnEndClass(void) {}; +void CPlayerWeaponsEffects_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPlayerWeaponsEffects_OnWorldEnd(CWorld *pwo) {}; +void CPlayerWeaponsEffects_OnWorldInit(CWorld *pwo) {}; +void CPlayerWeaponsEffects_OnWorldTick(CWorld *pwo) {}; +void CPlayerWeaponsEffects_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPlayerWeaponsEffects, CMovableEntity, "Player Weapons Effects", "", 0x00000195); +DECLARE_CTFILENAME(_fnmCPlayerWeaponsEffects_tbn, ""); diff --git a/Sources/EntitiesMP/PlayerWeapons_tables.h b/Sources/EntitiesMP/PlayerWeapons_tables.h new file mode 100644 index 0000000..3808f35 --- /dev/null +++ b/Sources/EntitiesMP/PlayerWeapons_tables.h @@ -0,0 +1,639 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(WeaponType) + EP_ENUMVALUE(WEAPON_NONE, ""), + EP_ENUMVALUE(WEAPON_KNIFE, ""), + EP_ENUMVALUE(WEAPON_COLT, ""), + EP_ENUMVALUE(WEAPON_DOUBLECOLT, ""), + EP_ENUMVALUE(WEAPON_SINGLESHOTGUN, ""), + EP_ENUMVALUE(WEAPON_DOUBLESHOTGUN, ""), + EP_ENUMVALUE(WEAPON_TOMMYGUN, ""), + EP_ENUMVALUE(WEAPON_MINIGUN, ""), + EP_ENUMVALUE(WEAPON_ROCKETLAUNCHER, ""), + EP_ENUMVALUE(WEAPON_GRENADELAUNCHER, ""), + EP_ENUMVALUE(WEAPON_CHAINSAW, ""), + EP_ENUMVALUE(WEAPON_FLAMER, ""), + EP_ENUMVALUE(WEAPON_LASER, ""), + EP_ENUMVALUE(WEAPON_SNIPER, ""), + EP_ENUMVALUE(WEAPON_IRONCANNON, ""), + EP_ENUMVALUE(WEAPON_LAST, ""), +EP_ENUMEND(WeaponType); + +#define ENTITYCLASS CPlayerWeapons + +CEntityProperty CPlayerWeapons_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000192<<8)+1, offsetof(CPlayerWeapons, m_penPlayer), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000192<<8)+2, offsetof(CPlayerWeapons, m_bFireWeapon), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000192<<8)+3, offsetof(CPlayerWeapons, m_bHasAmmo), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &WeaponType_enum, (0x00000192<<8)+4, offsetof(CPlayerWeapons, m_iCurrentWeapon), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &WeaponType_enum, (0x00000192<<8)+5, offsetof(CPlayerWeapons, m_iWantedWeapon), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &WeaponType_enum, (0x00000192<<8)+6, offsetof(CPlayerWeapons, m_iPreviousWeapon), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+11, offsetof(CPlayerWeapons, m_iAvailableWeapons), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000192<<8)+12, offsetof(CPlayerWeapons, m_bChangeWeapon), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000192<<8)+13, offsetof(CPlayerWeapons, m_bReloadWeapon), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000192<<8)+14, offsetof(CPlayerWeapons, m_bMirrorFire), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+15, offsetof(CPlayerWeapons, m_iAnim), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+16, offsetof(CPlayerWeapons, m_fAnimWaitTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+17, offsetof(CPlayerWeapons, m_tmRangeSoundSpawned), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000192<<8)+23, offsetof(CPlayerWeapons, m_bSniperZoom), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+24, offsetof(CPlayerWeapons, m_fSniperFOV), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+28, offsetof(CPlayerWeapons, m_fSniperFOVlast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000192<<8)+18, offsetof(CPlayerWeapons, m_strLastTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+19, offsetof(CPlayerWeapons, m_tmTargetingStarted), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+20, offsetof(CPlayerWeapons, m_tmLastTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+21, offsetof(CPlayerWeapons, m_tmSnoopingStarted), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000192<<8)+22, offsetof(CPlayerWeapons, m_penTargeting), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_MODELOBJECT, NULL, (0x00000192<<8)+25, offsetof(CPlayerWeapons, m_moWeapon), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_MODELOBJECT, NULL, (0x00000192<<8)+26, offsetof(CPlayerWeapons, m_moWeaponSecond), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+27, offsetof(CPlayerWeapons, m_tmWeaponChangeRequired), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000192<<8)+30, offsetof(CPlayerWeapons, m_penRayHit), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+31, offsetof(CPlayerWeapons, m_fRayHitDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+32, offsetof(CPlayerWeapons, m_fEnemyHealth), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000192<<8)+33, offsetof(CPlayerWeapons, m_vRayHit), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000192<<8)+34, offsetof(CPlayerWeapons, m_vRayHitLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000192<<8)+35, offsetof(CPlayerWeapons, m_vBulletSource), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000192<<8)+36, offsetof(CPlayerWeapons, m_vBulletTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+40, offsetof(CPlayerWeapons, m_iBullets), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+41, offsetof(CPlayerWeapons, m_iMaxBullets), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+42, offsetof(CPlayerWeapons, m_iShells), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+43, offsetof(CPlayerWeapons, m_iMaxShells), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+44, offsetof(CPlayerWeapons, m_iRockets), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+45, offsetof(CPlayerWeapons, m_iMaxRockets), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+46, offsetof(CPlayerWeapons, m_iGrenades), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+47, offsetof(CPlayerWeapons, m_iMaxGrenades), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+48, offsetof(CPlayerWeapons, m_iNapalm), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+49, offsetof(CPlayerWeapons, m_iMaxNapalm), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+50, offsetof(CPlayerWeapons, m_iElectricity), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+51, offsetof(CPlayerWeapons, m_iMaxElectricity), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+52, offsetof(CPlayerWeapons, m_iIronBalls), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+53, offsetof(CPlayerWeapons, m_iMaxIronBalls), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+54, offsetof(CPlayerWeapons, m_iSniperBullets), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+55, offsetof(CPlayerWeapons, m_iMaxSniperBullets), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+210, offsetof(CPlayerWeapons, m_iKnifeStand), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+215, offsetof(CPlayerWeapons, m_iColtBullets), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+220, offsetof(CPlayerWeapons, m_aMiniGun), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+221, offsetof(CPlayerWeapons, m_aMiniGunLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+222, offsetof(CPlayerWeapons, m_aMiniGunSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000192<<8)+230, offsetof(CPlayerWeapons, m_iLastBulletPosition), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+231, offsetof(CPlayerWeapons, m_iBulletsOnFireStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+233, offsetof(CPlayerWeapons, m_fSniperMaxFOV), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+234, offsetof(CPlayerWeapons, m_fSniperMinFOV), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+235, offsetof(CPlayerWeapons, m_fSnipingZoomSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000192<<8)+236, offsetof(CPlayerWeapons, m_bSniping), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+237, offsetof(CPlayerWeapons, m_fMinimumZoomFOV), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+238, offsetof(CPlayerWeapons, m_tmLastSniperFire), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000192<<8)+240, offsetof(CPlayerWeapons, m_penFlame), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+245, offsetof(CPlayerWeapons, m_iLaserBarrel), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+251, offsetof(CPlayerWeapons, m_iFlare), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000192<<8)+252, offsetof(CPlayerWeapons, m_iSecondFlare), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+260, offsetof(CPlayerWeapons, m_fWeaponDrawPowerOld), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+261, offsetof(CPlayerWeapons, m_fWeaponDrawPower), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+262, offsetof(CPlayerWeapons, m_tmDrawStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+270, offsetof(CPlayerWeapons, m_tmFlamerStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+271, offsetof(CPlayerWeapons, m_tmFlamerStop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000192<<8)+272, offsetof(CPlayerWeapons, m_tmLastChainsawSpray), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000192<<8)+255, offsetof(CPlayerWeapons, m_penPrediction), "", 0, 0, 0), +}; +#define CPlayerWeapons_propertiesct ARRAYCOUNT(CPlayerWeapons_properties) + +CEntityComponent CPlayerWeapons_components[] = { +#define CLASS_PROJECTILE ((0x00000192<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_BULLET ((0x00000192<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BULLET, "EFNM" "Classes\\Bullet.ecl"), +#define CLASS_WEAPONEFFECT ((0x00000192<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_WEAPONEFFECT, "EFNM" "Classes\\PlayerWeaponsEffects.ecl"), +#define CLASS_PIPEBOMB ((0x00000192<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_PIPEBOMB, "EFNM" "Classes\\Pipebomb.ecl"), +#define CLASS_GHOSTBUSTERRAY ((0x00000192<<8)+5) + CEntityComponent(ECT_CLASS, CLASS_GHOSTBUSTERRAY, "EFNM" "Classes\\GhostBusterRay.ecl"), +#define CLASS_CANNONBALL ((0x00000192<<8)+6) + CEntityComponent(ECT_CLASS, CLASS_CANNONBALL, "EFNM" "Classes\\CannonBall.ecl"), +#define CLASS_WEAPONITEM ((0x00000192<<8)+7) + CEntityComponent(ECT_CLASS, CLASS_WEAPONITEM, "EFNM" "Classes\\WeaponItem.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000192<<8)+8) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define TEXTURE_HAND ((0x00000192<<8)+10) + CEntityComponent(ECT_TEXTURE, TEXTURE_HAND, "EFNM" "Models\\Weapons\\Hand.tex"), +#define MODEL_KNIFEITEM ((0x00000192<<8)+20) + CEntityComponent(ECT_MODEL, MODEL_KNIFEITEM, "EFNM" "Models\\Weapons\\Knife\\KnifeItem.mdl"), +#define TEXTURE_KNIFEITEM ((0x00000192<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_KNIFEITEM, "EFNM" "Models\\Weapons\\Knife\\KnifeItem.tex"), +#define MODEL_KNIFE ((0x00000192<<8)+22) + CEntityComponent(ECT_MODEL, MODEL_KNIFE, "EFNM" "Models\\Weapons\\Knife\\Knife.mdl"), +#define SOUND_KNIFE_BACK ((0x00000192<<8)+23) + CEntityComponent(ECT_SOUND, SOUND_KNIFE_BACK, "EFNM" "Models\\Weapons\\Knife\\Sounds\\Back.wav"), +#define SOUND_KNIFE_HIGH ((0x00000192<<8)+24) + CEntityComponent(ECT_SOUND, SOUND_KNIFE_HIGH, "EFNM" "Models\\Weapons\\Knife\\Sounds\\High.wav"), +#define SOUND_KNIFE_LONG ((0x00000192<<8)+25) + CEntityComponent(ECT_SOUND, SOUND_KNIFE_LONG, "EFNM" "Models\\Weapons\\Knife\\Sounds\\Long.wav"), +#define SOUND_KNIFE_LOW ((0x00000192<<8)+26) + CEntityComponent(ECT_SOUND, SOUND_KNIFE_LOW, "EFNM" "Models\\Weapons\\Knife\\Sounds\\Low.wav"), +#define MODEL_COLT ((0x00000192<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_COLT, "EFNM" "Models\\Weapons\\Colt\\Colt.mdl"), +#define MODEL_COLTCOCK ((0x00000192<<8)+31) + CEntityComponent(ECT_MODEL, MODEL_COLTCOCK, "EFNM" "Models\\Weapons\\Colt\\ColtCock.mdl"), +#define MODEL_COLTMAIN ((0x00000192<<8)+32) + CEntityComponent(ECT_MODEL, MODEL_COLTMAIN, "EFNM" "Models\\Weapons\\Colt\\ColtMain.mdl"), +#define MODEL_COLTBULLETS ((0x00000192<<8)+33) + CEntityComponent(ECT_MODEL, MODEL_COLTBULLETS, "EFNM" "Models\\Weapons\\Colt\\ColtBullets.mdl"), +#define TEXTURE_COLTMAIN ((0x00000192<<8)+34) + CEntityComponent(ECT_TEXTURE, TEXTURE_COLTMAIN, "EFNM" "Models\\Weapons\\Colt\\ColtMain.tex"), +#define TEXTURE_COLTCOCK ((0x00000192<<8)+35) + CEntityComponent(ECT_TEXTURE, TEXTURE_COLTCOCK, "EFNM" "Models\\Weapons\\Colt\\ColtCock.tex"), +#define TEXTURE_COLTBULLETS ((0x00000192<<8)+36) + CEntityComponent(ECT_TEXTURE, TEXTURE_COLTBULLETS, "EFNM" "Models\\Weapons\\Colt\\ColtBullets.tex"), +#define SOUND_COLT_FIRE ((0x00000192<<8)+37) + CEntityComponent(ECT_SOUND, SOUND_COLT_FIRE, "EFNM" "Models\\Weapons\\Colt\\Sounds\\Fire.wav"), +#define SOUND_COLT_RELOAD ((0x00000192<<8)+38) + CEntityComponent(ECT_SOUND, SOUND_COLT_RELOAD, "EFNM" "Models\\Weapons\\Colt\\Sounds\\Reload.wav"), +#define MODEL_SINGLESHOTGUN ((0x00000192<<8)+40) + CEntityComponent(ECT_MODEL, MODEL_SINGLESHOTGUN, "EFNM" "Models\\Weapons\\SingleShotgun\\SingleShotgun.mdl"), +#define MODEL_SS_SLIDER ((0x00000192<<8)+41) + CEntityComponent(ECT_MODEL, MODEL_SS_SLIDER, "EFNM" "Models\\Weapons\\SingleShotgun\\Slider.mdl"), +#define MODEL_SS_HANDLE ((0x00000192<<8)+42) + CEntityComponent(ECT_MODEL, MODEL_SS_HANDLE, "EFNM" "Models\\Weapons\\SingleShotgun\\Handle.mdl"), +#define MODEL_SS_BARRELS ((0x00000192<<8)+43) + CEntityComponent(ECT_MODEL, MODEL_SS_BARRELS, "EFNM" "Models\\Weapons\\SingleShotgun\\Barrels.mdl"), +#define TEXTURE_SS_HANDLE ((0x00000192<<8)+44) + CEntityComponent(ECT_TEXTURE, TEXTURE_SS_HANDLE, "EFNM" "Models\\Weapons\\SingleShotgun\\Handle.tex"), +#define TEXTURE_SS_BARRELS ((0x00000192<<8)+45) + CEntityComponent(ECT_TEXTURE, TEXTURE_SS_BARRELS, "EFNM" "Models\\Weapons\\SingleShotgun\\Barrels.tex"), +#define SOUND_SINGLESHOTGUN_FIRE ((0x00000192<<8)+46) + CEntityComponent(ECT_SOUND, SOUND_SINGLESHOTGUN_FIRE, "EFNM" "Models\\Weapons\\SingleShotgun\\Sounds\\_Fire.wav"), +#define MODEL_DOUBLESHOTGUN ((0x00000192<<8)+50) + CEntityComponent(ECT_MODEL, MODEL_DOUBLESHOTGUN, "EFNM" "Models\\Weapons\\DoubleShotgun\\DoubleShotgun.mdl"), +#define MODEL_DS_HANDLE ((0x00000192<<8)+51) + CEntityComponent(ECT_MODEL, MODEL_DS_HANDLE, "EFNM" "Models\\Weapons\\DoubleShotgun\\Dshotgunhandle.mdl"), +#define MODEL_DS_BARRELS ((0x00000192<<8)+52) + CEntityComponent(ECT_MODEL, MODEL_DS_BARRELS, "EFNM" "Models\\Weapons\\DoubleShotgun\\Dshotgunbarrels.mdl"), +#define MODEL_DS_AMMO ((0x00000192<<8)+53) + CEntityComponent(ECT_MODEL, MODEL_DS_AMMO, "EFNM" "Models\\Weapons\\DoubleShotgun\\Ammo.mdl"), +#define MODEL_DS_SWITCH ((0x00000192<<8)+54) + CEntityComponent(ECT_MODEL, MODEL_DS_SWITCH, "EFNM" "Models\\Weapons\\DoubleShotgun\\Switch.mdl"), +#define MODEL_DS_HANDWITHAMMO ((0x00000192<<8)+55) + CEntityComponent(ECT_MODEL, MODEL_DS_HANDWITHAMMO, "EFNM" "Models\\Weapons\\DoubleShotgun\\HandWithAmmo.mdl"), +#define TEXTURE_DS_HANDLE ((0x00000192<<8)+56) + CEntityComponent(ECT_TEXTURE, TEXTURE_DS_HANDLE, "EFNM" "Models\\Weapons\\DoubleShotgun\\Handle.tex"), +#define TEXTURE_DS_BARRELS ((0x00000192<<8)+57) + CEntityComponent(ECT_TEXTURE, TEXTURE_DS_BARRELS, "EFNM" "Models\\Weapons\\DoubleShotgun\\Barrels.tex"), +#define TEXTURE_DS_AMMO ((0x00000192<<8)+58) + CEntityComponent(ECT_TEXTURE, TEXTURE_DS_AMMO, "EFNM" "Models\\Weapons\\DoubleShotgun\\Ammo.tex"), +#define TEXTURE_DS_SWITCH ((0x00000192<<8)+59) + CEntityComponent(ECT_TEXTURE, TEXTURE_DS_SWITCH, "EFNM" "Models\\Weapons\\DoubleShotgun\\Switch.tex"), +#define SOUND_DOUBLESHOTGUN_FIRE ((0x00000192<<8)+60) + CEntityComponent(ECT_SOUND, SOUND_DOUBLESHOTGUN_FIRE, "EFNM" "Models\\Weapons\\DoubleShotgun\\Sounds\\Fire.wav"), +#define SOUND_DOUBLESHOTGUN_RELOAD ((0x00000192<<8)+61) + CEntityComponent(ECT_SOUND, SOUND_DOUBLESHOTGUN_RELOAD, "EFNM" "Models\\Weapons\\DoubleShotgun\\Sounds\\Reload.wav"), +#define MODEL_TOMMYGUN ((0x00000192<<8)+70) + CEntityComponent(ECT_MODEL, MODEL_TOMMYGUN, "EFNM" "Models\\Weapons\\TommyGun\\TommyGun.mdl"), +#define MODEL_TG_BODY ((0x00000192<<8)+71) + CEntityComponent(ECT_MODEL, MODEL_TG_BODY, "EFNM" "Models\\Weapons\\TommyGun\\Body.mdl"), +#define MODEL_TG_SLIDER ((0x00000192<<8)+72) + CEntityComponent(ECT_MODEL, MODEL_TG_SLIDER, "EFNM" "Models\\Weapons\\TommyGun\\Slider.mdl"), +#define TEXTURE_TG_BODY ((0x00000192<<8)+73) + CEntityComponent(ECT_TEXTURE, TEXTURE_TG_BODY, "EFNM" "Models\\Weapons\\TommyGun\\Body.tex"), +#define SOUND_TOMMYGUN_FIRE ((0x00000192<<8)+74) + CEntityComponent(ECT_SOUND, SOUND_TOMMYGUN_FIRE, "EFNM" "Models\\Weapons\\TommyGun\\Sounds\\_Fire.wav"), +#define MODEL_MINIGUN ((0x00000192<<8)+80) + CEntityComponent(ECT_MODEL, MODEL_MINIGUN, "EFNM" "Models\\Weapons\\MiniGun\\MiniGun.mdl"), +#define MODEL_MG_BARRELS ((0x00000192<<8)+81) + CEntityComponent(ECT_MODEL, MODEL_MG_BARRELS, "EFNM" "Models\\Weapons\\MiniGun\\Barrels.mdl"), +#define MODEL_MG_BODY ((0x00000192<<8)+82) + CEntityComponent(ECT_MODEL, MODEL_MG_BODY, "EFNM" "Models\\Weapons\\MiniGun\\Body.mdl"), +#define MODEL_MG_ENGINE ((0x00000192<<8)+83) + CEntityComponent(ECT_MODEL, MODEL_MG_ENGINE, "EFNM" "Models\\Weapons\\MiniGun\\Engine.mdl"), +#define TEXTURE_MG_BODY ((0x00000192<<8)+84) + CEntityComponent(ECT_TEXTURE, TEXTURE_MG_BODY, "EFNM" "Models\\Weapons\\MiniGun\\Body.tex"), +#define TEXTURE_MG_BARRELS ((0x00000192<<8)+99) + CEntityComponent(ECT_TEXTURE, TEXTURE_MG_BARRELS, "EFNM" "Models\\Weapons\\MiniGun\\Barrels.tex"), +#define SOUND_MINIGUN_FIRE ((0x00000192<<8)+85) + CEntityComponent(ECT_SOUND, SOUND_MINIGUN_FIRE, "EFNM" "Models\\Weapons\\MiniGun\\Sounds\\Fire.wav"), +#define SOUND_MINIGUN_ROTATE ((0x00000192<<8)+86) + CEntityComponent(ECT_SOUND, SOUND_MINIGUN_ROTATE, "EFNM" "Models\\Weapons\\MiniGun\\Sounds\\Rotate.wav"), +#define SOUND_MINIGUN_SPINUP ((0x00000192<<8)+87) + CEntityComponent(ECT_SOUND, SOUND_MINIGUN_SPINUP, "EFNM" "Models\\Weapons\\MiniGun\\Sounds\\RotateUp.wav"), +#define SOUND_MINIGUN_SPINDOWN ((0x00000192<<8)+88) + CEntityComponent(ECT_SOUND, SOUND_MINIGUN_SPINDOWN, "EFNM" "Models\\Weapons\\MiniGun\\Sounds\\RotateDown.wav"), +#define SOUND_MINIGUN_CLICK ((0x00000192<<8)+89) + CEntityComponent(ECT_SOUND, SOUND_MINIGUN_CLICK, "EFNM" "Models\\Weapons\\MiniGun\\Sounds\\Click.wav"), +#define MODEL_ROCKETLAUNCHER ((0x00000192<<8)+90) + CEntityComponent(ECT_MODEL, MODEL_ROCKETLAUNCHER, "EFNM" "Models\\Weapons\\RocketLauncher\\RocketLauncher.mdl"), +#define MODEL_RL_BODY ((0x00000192<<8)+91) + CEntityComponent(ECT_MODEL, MODEL_RL_BODY, "EFNM" "Models\\Weapons\\RocketLauncher\\Body.mdl"), +#define TEXTURE_RL_BODY ((0x00000192<<8)+92) + CEntityComponent(ECT_TEXTURE, TEXTURE_RL_BODY, "EFNM" "Models\\Weapons\\RocketLauncher\\Body.tex"), +#define MODEL_RL_ROTATINGPART ((0x00000192<<8)+93) + CEntityComponent(ECT_MODEL, MODEL_RL_ROTATINGPART, "EFNM" "Models\\Weapons\\RocketLauncher\\RotatingPart.mdl"), +#define TEXTURE_RL_ROTATINGPART ((0x00000192<<8)+94) + CEntityComponent(ECT_TEXTURE, TEXTURE_RL_ROTATINGPART, "EFNM" "Models\\Weapons\\RocketLauncher\\RotatingPart.tex"), +#define MODEL_RL_ROCKET ((0x00000192<<8)+95) + CEntityComponent(ECT_MODEL, MODEL_RL_ROCKET, "EFNM" "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl"), +#define TEXTURE_RL_ROCKET ((0x00000192<<8)+96) + CEntityComponent(ECT_TEXTURE, TEXTURE_RL_ROCKET, "EFNM" "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex"), +#define SOUND_ROCKETLAUNCHER_FIRE ((0x00000192<<8)+97) + CEntityComponent(ECT_SOUND, SOUND_ROCKETLAUNCHER_FIRE, "EFNM" "Models\\Weapons\\RocketLauncher\\Sounds\\_Fire.wav"), +#define MODEL_GRENADELAUNCHER ((0x00000192<<8)+100) + CEntityComponent(ECT_MODEL, MODEL_GRENADELAUNCHER, "EFNM" "Models\\Weapons\\GrenadeLauncher\\GrenadeLauncher.mdl"), +#define MODEL_GL_BODY ((0x00000192<<8)+101) + CEntityComponent(ECT_MODEL, MODEL_GL_BODY, "EFNM" "Models\\Weapons\\GrenadeLauncher\\Body.mdl"), +#define MODEL_GL_MOVINGPART ((0x00000192<<8)+102) + CEntityComponent(ECT_MODEL, MODEL_GL_MOVINGPART, "EFNM" "Models\\Weapons\\GrenadeLauncher\\MovingPipe.mdl"), +#define MODEL_GL_GRENADE ((0x00000192<<8)+103) + CEntityComponent(ECT_MODEL, MODEL_GL_GRENADE, "EFNM" "Models\\Weapons\\GrenadeLauncher\\GrenadeBack.mdl"), +#define TEXTURE_GL_BODY ((0x00000192<<8)+104) + CEntityComponent(ECT_TEXTURE, TEXTURE_GL_BODY, "EFNM" "Models\\Weapons\\GrenadeLauncher\\Body.tex"), +#define TEXTURE_GL_MOVINGPART ((0x00000192<<8)+105) + CEntityComponent(ECT_TEXTURE, TEXTURE_GL_MOVINGPART, "EFNM" "Models\\Weapons\\GrenadeLauncher\\MovingPipe.tex"), +#define SOUND_GRENADELAUNCHER_FIRE ((0x00000192<<8)+106) + CEntityComponent(ECT_SOUND, SOUND_GRENADELAUNCHER_FIRE, "EFNM" "Models\\Weapons\\GrenadeLauncher\\Sounds\\_Fire.wav"), +#define MODEL_SNIPER ((0x00000192<<8)+110) + CEntityComponent(ECT_MODEL, MODEL_SNIPER, "EFNM" "ModelsMP\\Weapons\\Sniper\\Sniper.mdl"), +#define MODEL_SNIPER_BODY ((0x00000192<<8)+111) + CEntityComponent(ECT_MODEL, MODEL_SNIPER_BODY, "EFNM" "ModelsMP\\Weapons\\Sniper\\Body.mdl"), +#define TEXTURE_SNIPER_BODY ((0x00000192<<8)+112) + CEntityComponent(ECT_TEXTURE, TEXTURE_SNIPER_BODY, "EFNM" "ModelsMP\\Weapons\\Sniper\\Body.tex"), +#define SOUND_SNIPER_FIRE ((0x00000192<<8)+113) + CEntityComponent(ECT_SOUND, SOUND_SNIPER_FIRE, "EFNM" "ModelsMP\\Weapons\\Sniper\\Sounds\\Fire.wav"), +#define MODEL_FLAMER ((0x00000192<<8)+130) + CEntityComponent(ECT_MODEL, MODEL_FLAMER, "EFNM" "ModelsMP\\Weapons\\Flamer\\Flamer.mdl"), +#define MODEL_FL_BODY ((0x00000192<<8)+131) + CEntityComponent(ECT_MODEL, MODEL_FL_BODY, "EFNM" "ModelsMP\\Weapons\\Flamer\\Body.mdl"), +#define MODEL_FL_RESERVOIR ((0x00000192<<8)+132) + CEntityComponent(ECT_MODEL, MODEL_FL_RESERVOIR, "EFNM" "ModelsMP\\Weapons\\Flamer\\FuelReservoir.mdl"), +#define MODEL_FL_FLAME ((0x00000192<<8)+133) + CEntityComponent(ECT_MODEL, MODEL_FL_FLAME, "EFNM" "ModelsMP\\Weapons\\Flamer\\Flame.mdl"), +#define TEXTURE_FL_BODY ((0x00000192<<8)+134) + CEntityComponent(ECT_TEXTURE, TEXTURE_FL_BODY, "EFNM" "ModelsMP\\Weapons\\Flamer\\Body.tex"), +#define TEXTURE_FL_FLAME ((0x00000192<<8)+135) + CEntityComponent(ECT_TEXTURE, TEXTURE_FL_FLAME, "EFNM" "ModelsMP\\Effects\\Flame\\Flame.tex"), +#define SOUND_FL_FIRE ((0x00000192<<8)+136) + CEntityComponent(ECT_SOUND, SOUND_FL_FIRE, "EFNM" "ModelsMP\\Weapons\\Flamer\\Sounds\\Fire.wav"), +#define SOUND_FL_START ((0x00000192<<8)+137) + CEntityComponent(ECT_SOUND, SOUND_FL_START, "EFNM" "ModelsMP\\Weapons\\Flamer\\Sounds\\Start.wav"), +#define SOUND_FL_STOP ((0x00000192<<8)+138) + CEntityComponent(ECT_SOUND, SOUND_FL_STOP, "EFNM" "ModelsMP\\Weapons\\Flamer\\Sounds\\Stop.wav"), +#define TEXTURE_FL_FUELRESERVOIR ((0x00000192<<8)+139) + CEntityComponent(ECT_TEXTURE, TEXTURE_FL_FUELRESERVOIR, "EFNM" "ModelsMP\\Weapons\\Flamer\\FuelReservoir.tex"), +#define MODEL_LASER ((0x00000192<<8)+140) + CEntityComponent(ECT_MODEL, MODEL_LASER, "EFNM" "Models\\Weapons\\Laser\\Laser.mdl"), +#define MODEL_LS_BODY ((0x00000192<<8)+141) + CEntityComponent(ECT_MODEL, MODEL_LS_BODY, "EFNM" "Models\\Weapons\\Laser\\Body.mdl"), +#define MODEL_LS_BARREL ((0x00000192<<8)+142) + CEntityComponent(ECT_MODEL, MODEL_LS_BARREL, "EFNM" "Models\\Weapons\\Laser\\Barrel.mdl"), +#define TEXTURE_LS_BODY ((0x00000192<<8)+144) + CEntityComponent(ECT_TEXTURE, TEXTURE_LS_BODY, "EFNM" "Models\\Weapons\\Laser\\Body.tex"), +#define TEXTURE_LS_BARREL ((0x00000192<<8)+145) + CEntityComponent(ECT_TEXTURE, TEXTURE_LS_BARREL, "EFNM" "Models\\Weapons\\Laser\\Barrel.tex"), +#define SOUND_LASER_FIRE ((0x00000192<<8)+146) + CEntityComponent(ECT_SOUND, SOUND_LASER_FIRE, "EFNM" "Models\\Weapons\\Laser\\Sounds\\_Fire.wav"), +#define MODEL_CHAINSAW ((0x00000192<<8)+150) + CEntityComponent(ECT_MODEL, MODEL_CHAINSAW, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Chainsaw.mdl"), +#define MODEL_CS_BODY ((0x00000192<<8)+151) + CEntityComponent(ECT_MODEL, MODEL_CS_BODY, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Body.mdl"), +#define MODEL_CS_BLADE ((0x00000192<<8)+152) + CEntityComponent(ECT_MODEL, MODEL_CS_BLADE, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Blade.mdl"), +#define MODEL_CS_TEETH ((0x00000192<<8)+160) + CEntityComponent(ECT_MODEL, MODEL_CS_TEETH, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Teeth.mdl"), +#define TEXTURE_CS_BODY ((0x00000192<<8)+153) + CEntityComponent(ECT_TEXTURE, TEXTURE_CS_BODY, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Body.tex"), +#define TEXTURE_CS_BLADE ((0x00000192<<8)+154) + CEntityComponent(ECT_TEXTURE, TEXTURE_CS_BLADE, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Blade.tex"), +#define TEXTURE_CS_TEETH ((0x00000192<<8)+161) + CEntityComponent(ECT_TEXTURE, TEXTURE_CS_TEETH, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Teeth.tex"), +#define SOUND_CS_FIRE ((0x00000192<<8)+155) + CEntityComponent(ECT_SOUND, SOUND_CS_FIRE, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Sounds\\Fire.wav"), +#define SOUND_CS_BEGINFIRE ((0x00000192<<8)+156) + CEntityComponent(ECT_SOUND, SOUND_CS_BEGINFIRE, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Sounds\\BeginFire.wav"), +#define SOUND_CS_ENDFIRE ((0x00000192<<8)+157) + CEntityComponent(ECT_SOUND, SOUND_CS_ENDFIRE, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Sounds\\EndFire.wav"), +#define SOUND_CS_BRINGUP ((0x00000192<<8)+158) + CEntityComponent(ECT_SOUND, SOUND_CS_BRINGUP, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Sounds\\BringUp.wav"), +#define SOUND_CS_IDLE ((0x00000192<<8)+159) + CEntityComponent(ECT_SOUND, SOUND_CS_IDLE, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Sounds\\Idle.wav"), +#define SOUND_CS_BRINGDOWN ((0x00000192<<8)+162) + CEntityComponent(ECT_SOUND, SOUND_CS_BRINGDOWN, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Sounds\\BringDown.wav"), +#define MODEL_CANNON ((0x00000192<<8)+170) + CEntityComponent(ECT_MODEL, MODEL_CANNON, "EFNM" "Models\\Weapons\\Cannon\\Cannon.mdl"), +#define MODEL_CN_BODY ((0x00000192<<8)+171) + CEntityComponent(ECT_MODEL, MODEL_CN_BODY, "EFNM" "Models\\Weapons\\Cannon\\Body.mdl"), +#define TEXTURE_CANNON ((0x00000192<<8)+173) + CEntityComponent(ECT_TEXTURE, TEXTURE_CANNON, "EFNM" "Models\\Weapons\\Cannon\\Body.tex"), +#define SOUND_CANNON ((0x00000192<<8)+174) + CEntityComponent(ECT_SOUND, SOUND_CANNON, "EFNM" "Models\\Weapons\\Cannon\\Sounds\\Fire.wav"), +#define SOUND_CANNON_PREPARE ((0x00000192<<8)+175) + CEntityComponent(ECT_SOUND, SOUND_CANNON_PREPARE, "EFNM" "Models\\Weapons\\Cannon\\Sounds\\Prepare.wav"), +#define TEX_REFL_BWRIPLES01 ((0x00000192<<8)+200) + CEntityComponent(ECT_TEXTURE, TEX_REFL_BWRIPLES01, "EFNM" "Models\\ReflectionTextures\\BWRiples01.tex"), +#define TEX_REFL_BWRIPLES02 ((0x00000192<<8)+201) + CEntityComponent(ECT_TEXTURE, TEX_REFL_BWRIPLES02, "EFNM" "Models\\ReflectionTextures\\BWRiples02.tex"), +#define TEX_REFL_LIGHTMETAL01 ((0x00000192<<8)+202) + CEntityComponent(ECT_TEXTURE, TEX_REFL_LIGHTMETAL01, "EFNM" "Models\\ReflectionTextures\\LightMetal01.tex"), +#define TEX_REFL_LIGHTBLUEMETAL01 ((0x00000192<<8)+203) + CEntityComponent(ECT_TEXTURE, TEX_REFL_LIGHTBLUEMETAL01, "EFNM" "Models\\ReflectionTextures\\LightBlueMetal01.tex"), +#define TEX_REFL_DARKMETAL ((0x00000192<<8)+204) + CEntityComponent(ECT_TEXTURE, TEX_REFL_DARKMETAL, "EFNM" "Models\\ReflectionTextures\\DarkMetal.tex"), +#define TEX_REFL_PURPLE01 ((0x00000192<<8)+205) + CEntityComponent(ECT_TEXTURE, TEX_REFL_PURPLE01, "EFNM" "Models\\ReflectionTextures\\Purple01.tex"), +#define TEX_SPEC_WEAK ((0x00000192<<8)+210) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_WEAK, "EFNM" "Models\\SpecularTextures\\Weak.tex"), +#define TEX_SPEC_MEDIUM ((0x00000192<<8)+211) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_MEDIUM, "EFNM" "Models\\SpecularTextures\\Medium.tex"), +#define TEX_SPEC_STRONG ((0x00000192<<8)+212) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_STRONG, "EFNM" "Models\\SpecularTextures\\Strong.tex"), +#define MODEL_FLARE01 ((0x00000192<<8)+250) + CEntityComponent(ECT_MODEL, MODEL_FLARE01, "EFNM" "Models\\Effects\\Weapons\\Flare01\\Flare.mdl"), +#define TEXTURE_FLARE01 ((0x00000192<<8)+251) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE01, "EFNM" "Models\\Effects\\Weapons\\Flare01\\Flare.tex"), +#define SOUND_SILENCE ((0x00000192<<8)+280) + CEntityComponent(ECT_SOUND, SOUND_SILENCE, "EFNM" "Sounds\\Misc\\Silence.wav"), +}; +#define CPlayerWeapons_componentsct ARRAYCOUNT(CPlayerWeapons_components) + +CEventHandlerEntry CPlayerWeapons_handlers[] = { + {0x01920007, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 3658 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChangeWeapon),DEBUGSTRING("CPlayerWeapons::ChangeWeapon")}, + {0x01920008, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920008_ChangeWeapon_01), DEBUGSTRING("CPlayerWeapons::H0x01920008_ChangeWeapon_01")}, + {0x01920009, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920009_ChangeWeapon_02), DEBUGSTRING("CPlayerWeapons::H0x01920009_ChangeWeapon_02")}, + {0x0192000a, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192000a_ChangeWeapon_03), DEBUGSTRING("CPlayerWeapons::H0x0192000a_ChangeWeapon_03")}, + {0x0192000b, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192000b_ChangeWeapon_04), DEBUGSTRING("CPlayerWeapons::H0x0192000b_ChangeWeapon_04")}, + {0x0192000c, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192000c_ChangeWeapon_05), DEBUGSTRING("CPlayerWeapons::H0x0192000c_ChangeWeapon_05")}, + {0x0192000d, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192000d_ChangeWeapon_06), DEBUGSTRING("CPlayerWeapons::H0x0192000d_ChangeWeapon_06")}, + {0x0192000e, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192000e_ChangeWeapon_07), DEBUGSTRING("CPlayerWeapons::H0x0192000e_ChangeWeapon_07")}, + {0x0192000f, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192000f_ChangeWeapon_08), DEBUGSTRING("CPlayerWeapons::H0x0192000f_ChangeWeapon_08")}, + {0x01920010, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920010_ChangeWeapon_09), DEBUGSTRING("CPlayerWeapons::H0x01920010_ChangeWeapon_09")}, + {0x01920011, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 3720 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +PutDown),DEBUGSTRING("CPlayerWeapons::PutDown")}, + {0x01920012, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920012_PutDown_01), DEBUGSTRING("CPlayerWeapons::H0x01920012_PutDown_01")}, + {0x01920013, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920013_PutDown_02), DEBUGSTRING("CPlayerWeapons::H0x01920013_PutDown_02")}, + {0x01920014, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920014_PutDown_03), DEBUGSTRING("CPlayerWeapons::H0x01920014_PutDown_03")}, + {0x01920015, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920015_PutDown_04), DEBUGSTRING("CPlayerWeapons::H0x01920015_PutDown_04")}, + {0x01920016, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920016_PutDown_05), DEBUGSTRING("CPlayerWeapons::H0x01920016_PutDown_05")}, + {0x01920017, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 3829 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BringUp),DEBUGSTRING("CPlayerWeapons::BringUp")}, + {0x01920018, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920018_BringUp_01), DEBUGSTRING("CPlayerWeapons::H0x01920018_BringUp_01")}, + {0x01920019, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920019_BringUp_02), DEBUGSTRING("CPlayerWeapons::H0x01920019_BringUp_02")}, + {0x0192001a, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192001a_BringUp_03), DEBUGSTRING("CPlayerWeapons::H0x0192001a_BringUp_03")}, + {0x0192001b, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192001b_BringUp_04), DEBUGSTRING("CPlayerWeapons::H0x0192001b_BringUp_04")}, + {0x0192001c, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192001c_BringUp_05), DEBUGSTRING("CPlayerWeapons::H0x0192001c_BringUp_05")}, + {0x0192001d, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 3957 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Fire),DEBUGSTRING("CPlayerWeapons::Fire")}, + {0x0192001e, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192001e_Fire_01), DEBUGSTRING("CPlayerWeapons::H0x0192001e_Fire_01")}, + {0x0192001f, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192001f_Fire_02), DEBUGSTRING("CPlayerWeapons::H0x0192001f_Fire_02")}, + {0x01920020, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920020_Fire_03), DEBUGSTRING("CPlayerWeapons::H0x01920020_Fire_03")}, + {0x01920021, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920021_Fire_04), DEBUGSTRING("CPlayerWeapons::H0x01920021_Fire_04")}, + {0x01920022, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920022_Fire_05), DEBUGSTRING("CPlayerWeapons::H0x01920022_Fire_05")}, + {0x01920023, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920023_Fire_06), DEBUGSTRING("CPlayerWeapons::H0x01920023_Fire_06")}, + {0x01920024, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920024_Fire_07), DEBUGSTRING("CPlayerWeapons::H0x01920024_Fire_07")}, + {0x01920025, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920025_Fire_08), DEBUGSTRING("CPlayerWeapons::H0x01920025_Fire_08")}, + {0x01920026, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920026_Fire_09), DEBUGSTRING("CPlayerWeapons::H0x01920026_Fire_09")}, + {0x01920027, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920027_Fire_10), DEBUGSTRING("CPlayerWeapons::H0x01920027_Fire_10")}, + {0x01920028, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920028_Fire_11), DEBUGSTRING("CPlayerWeapons::H0x01920028_Fire_11")}, + {0x01920029, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920029_Fire_12), DEBUGSTRING("CPlayerWeapons::H0x01920029_Fire_12")}, + {0x0192002a, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192002a_Fire_13), DEBUGSTRING("CPlayerWeapons::H0x0192002a_Fire_13")}, + {0x0192002b, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192002b_Fire_14), DEBUGSTRING("CPlayerWeapons::H0x0192002b_Fire_14")}, + {0x0192002c, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192002c_Fire_15), DEBUGSTRING("CPlayerWeapons::H0x0192002c_Fire_15")}, + {0x0192002d, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192002d_Fire_16), DEBUGSTRING("CPlayerWeapons::H0x0192002d_Fire_16")}, + {0x0192002e, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4042 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +SwingKnife),DEBUGSTRING("CPlayerWeapons::SwingKnife")}, + {0x0192002f, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192002f_SwingKnife_01), DEBUGSTRING("CPlayerWeapons::H0x0192002f_SwingKnife_01")}, + {0x01920030, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920030_SwingKnife_02), DEBUGSTRING("CPlayerWeapons::H0x01920030_SwingKnife_02")}, + {0x01920031, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920031_SwingKnife_03), DEBUGSTRING("CPlayerWeapons::H0x01920031_SwingKnife_03")}, + {0x01920032, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920032_SwingKnife_04), DEBUGSTRING("CPlayerWeapons::H0x01920032_SwingKnife_04")}, + {0x01920033, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920033_SwingKnife_05), DEBUGSTRING("CPlayerWeapons::H0x01920033_SwingKnife_05")}, + {0x01920034, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920034_SwingKnife_06), DEBUGSTRING("CPlayerWeapons::H0x01920034_SwingKnife_06")}, + {0x01920035, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920035_SwingKnife_07), DEBUGSTRING("CPlayerWeapons::H0x01920035_SwingKnife_07")}, + {0x01920036, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920036_SwingKnife_08), DEBUGSTRING("CPlayerWeapons::H0x01920036_SwingKnife_08")}, + {0x01920037, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920037_SwingKnife_09), DEBUGSTRING("CPlayerWeapons::H0x01920037_SwingKnife_09")}, + {0x01920038, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920038_SwingKnife_10), DEBUGSTRING("CPlayerWeapons::H0x01920038_SwingKnife_10")}, + {0x01920039, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920039_SwingKnife_11), DEBUGSTRING("CPlayerWeapons::H0x01920039_SwingKnife_11")}, + {0x0192003a, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192003a_SwingKnife_12), DEBUGSTRING("CPlayerWeapons::H0x0192003a_SwingKnife_12")}, + {0x0192003b, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4094 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireColt),DEBUGSTRING("CPlayerWeapons::FireColt")}, + {0x0192003c, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192003c_FireColt_01), DEBUGSTRING("CPlayerWeapons::H0x0192003c_FireColt_01")}, + {0x0192003d, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192003d_FireColt_02), DEBUGSTRING("CPlayerWeapons::H0x0192003d_FireColt_02")}, + {0x0192003e, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4144 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ReloadColt),DEBUGSTRING("CPlayerWeapons::ReloadColt")}, + {0x0192003f, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192003f_ReloadColt_01), DEBUGSTRING("CPlayerWeapons::H0x0192003f_ReloadColt_01")}, + {0x01920040, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920040_ReloadColt_02), DEBUGSTRING("CPlayerWeapons::H0x01920040_ReloadColt_02")}, + {0x01920041, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4160 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireDoubleColt),DEBUGSTRING("CPlayerWeapons::FireDoubleColt")}, + {0x01920042, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920042_FireDoubleColt_01), DEBUGSTRING("CPlayerWeapons::H0x01920042_FireDoubleColt_01")}, + {0x01920043, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920043_FireDoubleColt_02), DEBUGSTRING("CPlayerWeapons::H0x01920043_FireDoubleColt_02")}, + {0x01920044, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920044_FireDoubleColt_03), DEBUGSTRING("CPlayerWeapons::H0x01920044_FireDoubleColt_03")}, + {0x01920045, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920045_FireDoubleColt_04), DEBUGSTRING("CPlayerWeapons::H0x01920045_FireDoubleColt_04")}, + {0x01920046, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4236 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ReloadDoubleColt),DEBUGSTRING("CPlayerWeapons::ReloadDoubleColt")}, + {0x01920047, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920047_ReloadDoubleColt_01), DEBUGSTRING("CPlayerWeapons::H0x01920047_ReloadDoubleColt_01")}, + {0x01920048, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920048_ReloadDoubleColt_02), DEBUGSTRING("CPlayerWeapons::H0x01920048_ReloadDoubleColt_02")}, + {0x01920049, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920049_ReloadDoubleColt_03), DEBUGSTRING("CPlayerWeapons::H0x01920049_ReloadDoubleColt_03")}, + {0x0192004a, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192004a_ReloadDoubleColt_04), DEBUGSTRING("CPlayerWeapons::H0x0192004a_ReloadDoubleColt_04")}, + {0x0192004b, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4261 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireSingleShotgun),DEBUGSTRING("CPlayerWeapons::FireSingleShotgun")}, + {0x0192004c, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192004c_FireSingleShotgun_01), DEBUGSTRING("CPlayerWeapons::H0x0192004c_FireSingleShotgun_01")}, + {0x0192004d, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192004d_FireSingleShotgun_02), DEBUGSTRING("CPlayerWeapons::H0x0192004d_FireSingleShotgun_02")}, + {0x0192004e, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192004e_FireSingleShotgun_03), DEBUGSTRING("CPlayerWeapons::H0x0192004e_FireSingleShotgun_03")}, + {0x0192004f, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192004f_FireSingleShotgun_04), DEBUGSTRING("CPlayerWeapons::H0x0192004f_FireSingleShotgun_04")}, + {0x01920050, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920050_FireSingleShotgun_05), DEBUGSTRING("CPlayerWeapons::H0x01920050_FireSingleShotgun_05")}, + {0x01920051, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920051_FireSingleShotgun_06), DEBUGSTRING("CPlayerWeapons::H0x01920051_FireSingleShotgun_06")}, + {0x01920052, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4358 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireDoubleShotgun),DEBUGSTRING("CPlayerWeapons::FireDoubleShotgun")}, + {0x01920053, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920053_FireDoubleShotgun_01), DEBUGSTRING("CPlayerWeapons::H0x01920053_FireDoubleShotgun_01")}, + {0x01920054, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920054_FireDoubleShotgun_02), DEBUGSTRING("CPlayerWeapons::H0x01920054_FireDoubleShotgun_02")}, + {0x01920055, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920055_FireDoubleShotgun_03), DEBUGSTRING("CPlayerWeapons::H0x01920055_FireDoubleShotgun_03")}, + {0x01920056, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920056_FireDoubleShotgun_04), DEBUGSTRING("CPlayerWeapons::H0x01920056_FireDoubleShotgun_04")}, + {0x01920057, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920057_FireDoubleShotgun_05), DEBUGSTRING("CPlayerWeapons::H0x01920057_FireDoubleShotgun_05")}, + {0x01920058, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920058_FireDoubleShotgun_06), DEBUGSTRING("CPlayerWeapons::H0x01920058_FireDoubleShotgun_06")}, + {0x01920059, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4447 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TommyGunStart),DEBUGSTRING("CPlayerWeapons::TommyGunStart")}, + {0x0192005a, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4458 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +TommyGunStop),DEBUGSTRING("CPlayerWeapons::TommyGunStop")}, + {0x0192005b, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4489 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireTommyGun),DEBUGSTRING("CPlayerWeapons::FireTommyGun")}, + {0x0192005c, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192005c_FireTommyGun_01), DEBUGSTRING("CPlayerWeapons::H0x0192005c_FireTommyGun_01")}, + {0x0192005d, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192005d_FireTommyGun_02), DEBUGSTRING("CPlayerWeapons::H0x0192005d_FireTommyGun_02")}, + {0x0192005e, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192005e_FireTommyGun_03), DEBUGSTRING("CPlayerWeapons::H0x0192005e_FireTommyGun_03")}, + {0x0192005f, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192005f_FireTommyGun_04), DEBUGSTRING("CPlayerWeapons::H0x0192005f_FireTommyGun_04")}, + {0x01920060, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4549 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireSniper),DEBUGSTRING("CPlayerWeapons::FireSniper")}, + {0x01920061, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920061_FireSniper_01), DEBUGSTRING("CPlayerWeapons::H0x01920061_FireSniper_01")}, + {0x01920062, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920062_FireSniper_02), DEBUGSTRING("CPlayerWeapons::H0x01920062_FireSniper_02")}, + {0x01920063, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920063_FireSniper_03), DEBUGSTRING("CPlayerWeapons::H0x01920063_FireSniper_03")}, + {0x01920064, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920064_FireSniper_04), DEBUGSTRING("CPlayerWeapons::H0x01920064_FireSniper_04")}, + {0x01920065, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920065_FireSniper_05), DEBUGSTRING("CPlayerWeapons::H0x01920065_FireSniper_05")}, + {0x01920066, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920066_FireSniper_06), DEBUGSTRING("CPlayerWeapons::H0x01920066_FireSniper_06")}, + {0x01920067, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4636 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MiniGunSpinUp),DEBUGSTRING("CPlayerWeapons::MiniGunSpinUp")}, + {0x01920068, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920068_MiniGunSpinUp_01), DEBUGSTRING("CPlayerWeapons::H0x01920068_MiniGunSpinUp_01")}, + {0x01920069, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920069_MiniGunSpinUp_02), DEBUGSTRING("CPlayerWeapons::H0x01920069_MiniGunSpinUp_02")}, + {0x0192006a, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192006a_MiniGunSpinUp_03), DEBUGSTRING("CPlayerWeapons::H0x0192006a_MiniGunSpinUp_03")}, + {0x0192006b, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192006b_MiniGunSpinUp_04), DEBUGSTRING("CPlayerWeapons::H0x0192006b_MiniGunSpinUp_04")}, + {0x0192006c, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4677 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MiniGunFire),DEBUGSTRING("CPlayerWeapons::MiniGunFire")}, + {0x0192006d, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192006d_MiniGunFire_01), DEBUGSTRING("CPlayerWeapons::H0x0192006d_MiniGunFire_01")}, + {0x0192006e, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192006e_MiniGunFire_02), DEBUGSTRING("CPlayerWeapons::H0x0192006e_MiniGunFire_02")}, + {0x0192006f, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192006f_MiniGunFire_03), DEBUGSTRING("CPlayerWeapons::H0x0192006f_MiniGunFire_03")}, + {0x01920070, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920070_MiniGunFire_04), DEBUGSTRING("CPlayerWeapons::H0x01920070_MiniGunFire_04")}, + {0x01920071, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4797 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +MiniGunSpinDown),DEBUGSTRING("CPlayerWeapons::MiniGunSpinDown")}, + {0x01920072, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920072_MiniGunSpinDown_01), DEBUGSTRING("CPlayerWeapons::H0x01920072_MiniGunSpinDown_01")}, + {0x01920073, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920073_MiniGunSpinDown_02), DEBUGSTRING("CPlayerWeapons::H0x01920073_MiniGunSpinDown_02")}, + {0x01920074, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920074_MiniGunSpinDown_03), DEBUGSTRING("CPlayerWeapons::H0x01920074_MiniGunSpinDown_03")}, + {0x01920075, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920075_MiniGunSpinDown_04), DEBUGSTRING("CPlayerWeapons::H0x01920075_MiniGunSpinDown_04")}, + {0x01920076, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920076_MiniGunSpinDown_05), DEBUGSTRING("CPlayerWeapons::H0x01920076_MiniGunSpinDown_05")}, + {0x01920077, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920077_MiniGunSpinDown_06), DEBUGSTRING("CPlayerWeapons::H0x01920077_MiniGunSpinDown_06")}, + {0x01920078, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920078_MiniGunSpinDown_07), DEBUGSTRING("CPlayerWeapons::H0x01920078_MiniGunSpinDown_07")}, + {0x01920079, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920079_MiniGunSpinDown_08), DEBUGSTRING("CPlayerWeapons::H0x01920079_MiniGunSpinDown_08")}, + {0x0192007a, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192007a_MiniGunSpinDown_09), DEBUGSTRING("CPlayerWeapons::H0x0192007a_MiniGunSpinDown_09")}, + {0x0192007b, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4855 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireRocketLauncher),DEBUGSTRING("CPlayerWeapons::FireRocketLauncher")}, + {0x0192007c, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192007c_FireRocketLauncher_01), DEBUGSTRING("CPlayerWeapons::H0x0192007c_FireRocketLauncher_01")}, + {0x0192007d, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192007d_FireRocketLauncher_02), DEBUGSTRING("CPlayerWeapons::H0x0192007d_FireRocketLauncher_02")}, + {0x0192007e, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192007e_FireRocketLauncher_03), DEBUGSTRING("CPlayerWeapons::H0x0192007e_FireRocketLauncher_03")}, + {0x0192007f, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192007f_FireRocketLauncher_04), DEBUGSTRING("CPlayerWeapons::H0x0192007f_FireRocketLauncher_04")}, + {0x01920080, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920080_FireRocketLauncher_05), DEBUGSTRING("CPlayerWeapons::H0x01920080_FireRocketLauncher_05")}, + {0x01920081, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920081_FireRocketLauncher_06), DEBUGSTRING("CPlayerWeapons::H0x01920081_FireRocketLauncher_06")}, + {0x01920082, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 4897 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireGrenadeLauncher),DEBUGSTRING("CPlayerWeapons::FireGrenadeLauncher")}, + {0x01920083, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920083_FireGrenadeLauncher_01), DEBUGSTRING("CPlayerWeapons::H0x01920083_FireGrenadeLauncher_01")}, + {0x01920084, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920084_FireGrenadeLauncher_02), DEBUGSTRING("CPlayerWeapons::H0x01920084_FireGrenadeLauncher_02")}, + {0x01920085, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920085_FireGrenadeLauncher_03), DEBUGSTRING("CPlayerWeapons::H0x01920085_FireGrenadeLauncher_03")}, + {0x01920086, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920086_FireGrenadeLauncher_04), DEBUGSTRING("CPlayerWeapons::H0x01920086_FireGrenadeLauncher_04")}, + {0x01920087, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920087_FireGrenadeLauncher_05), DEBUGSTRING("CPlayerWeapons::H0x01920087_FireGrenadeLauncher_05")}, + {0x01920088, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920088_FireGrenadeLauncher_06), DEBUGSTRING("CPlayerWeapons::H0x01920088_FireGrenadeLauncher_06")}, + {0x01920089, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920089_FireGrenadeLauncher_07), DEBUGSTRING("CPlayerWeapons::H0x01920089_FireGrenadeLauncher_07")}, + {0x0192008a, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192008a_FireGrenadeLauncher_08), DEBUGSTRING("CPlayerWeapons::H0x0192008a_FireGrenadeLauncher_08")}, + {0x0192008b, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192008b_FireGrenadeLauncher_09), DEBUGSTRING("CPlayerWeapons::H0x0192008b_FireGrenadeLauncher_09")}, + {0x0192008c, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192008c_FireGrenadeLauncher_10), DEBUGSTRING("CPlayerWeapons::H0x0192008c_FireGrenadeLauncher_10")}, + {0x0192008d, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192008d_FireGrenadeLauncher_11), DEBUGSTRING("CPlayerWeapons::H0x0192008d_FireGrenadeLauncher_11")}, + {0x0192008e, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192008e_FireGrenadeLauncher_12), DEBUGSTRING("CPlayerWeapons::H0x0192008e_FireGrenadeLauncher_12")}, + {0x0192008f, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192008f_FireGrenadeLauncher_13), DEBUGSTRING("CPlayerWeapons::H0x0192008f_FireGrenadeLauncher_13")}, + {0x01920090, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920090_FireGrenadeLauncher_14), DEBUGSTRING("CPlayerWeapons::H0x01920090_FireGrenadeLauncher_14")}, + {0x01920091, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920091_FireGrenadeLauncher_15), DEBUGSTRING("CPlayerWeapons::H0x01920091_FireGrenadeLauncher_15")}, + {0x01920092, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5042 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FlamerStart),DEBUGSTRING("CPlayerWeapons::FlamerStart")}, + {0x01920093, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920093_FlamerStart_01), DEBUGSTRING("CPlayerWeapons::H0x01920093_FlamerStart_01")}, + {0x01920094, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920094_FlamerStart_02), DEBUGSTRING("CPlayerWeapons::H0x01920094_FlamerStart_02")}, + {0x01920095, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920095_FlamerStart_03), DEBUGSTRING("CPlayerWeapons::H0x01920095_FlamerStart_03")}, + {0x01920096, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920096_FlamerStart_04), DEBUGSTRING("CPlayerWeapons::H0x01920096_FlamerStart_04")}, + {0x01920097, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5062 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FlamerFire),DEBUGSTRING("CPlayerWeapons::FlamerFire")}, + {0x01920098, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920098_FlamerFire_01), DEBUGSTRING("CPlayerWeapons::H0x01920098_FlamerFire_01")}, + {0x01920099, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x01920099_FlamerFire_02), DEBUGSTRING("CPlayerWeapons::H0x01920099_FlamerFire_02")}, + {0x0192009a, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192009a_FlamerFire_03), DEBUGSTRING("CPlayerWeapons::H0x0192009a_FlamerFire_03")}, + {0x0192009b, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192009b_FlamerFire_04), DEBUGSTRING("CPlayerWeapons::H0x0192009b_FlamerFire_04")}, + {0x0192009c, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5079 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FlamerStop),DEBUGSTRING("CPlayerWeapons::FlamerStop")}, + {0x0192009d, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192009d_FlamerStop_01), DEBUGSTRING("CPlayerWeapons::H0x0192009d_FlamerStop_01")}, + {0x0192009e, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x0192009e_FlamerStop_02), DEBUGSTRING("CPlayerWeapons::H0x0192009e_FlamerStop_02")}, + {0x0192009f, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5104 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChainsawFire),DEBUGSTRING("CPlayerWeapons::ChainsawFire")}, + {0x019200a0, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200a0_ChainsawFire_01), DEBUGSTRING("CPlayerWeapons::H0x019200a0_ChainsawFire_01")}, + {0x019200a1, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200a1_ChainsawFire_02), DEBUGSTRING("CPlayerWeapons::H0x019200a1_ChainsawFire_02")}, + {0x019200a2, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200a2_ChainsawFire_03), DEBUGSTRING("CPlayerWeapons::H0x019200a2_ChainsawFire_03")}, + {0x019200a3, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200a3_ChainsawFire_04), DEBUGSTRING("CPlayerWeapons::H0x019200a3_ChainsawFire_04")}, + {0x019200a4, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200a4_ChainsawFire_05), DEBUGSTRING("CPlayerWeapons::H0x019200a4_ChainsawFire_05")}, + {0x019200a5, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200a5_ChainsawFire_06), DEBUGSTRING("CPlayerWeapons::H0x019200a5_ChainsawFire_06")}, + {0x019200a6, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200a6_ChainsawFire_07), DEBUGSTRING("CPlayerWeapons::H0x019200a6_ChainsawFire_07")}, + {0x019200a7, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200a7_ChainsawFire_08), DEBUGSTRING("CPlayerWeapons::H0x019200a7_ChainsawFire_08")}, + {0x019200a8, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5180 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChainsawBringUp),DEBUGSTRING("CPlayerWeapons::ChainsawBringUp")}, + {0x019200a9, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200a9_ChainsawBringUp_01), DEBUGSTRING("CPlayerWeapons::H0x019200a9_ChainsawBringUp_01")}, + {0x019200aa, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200aa_ChainsawBringUp_02), DEBUGSTRING("CPlayerWeapons::H0x019200aa_ChainsawBringUp_02")}, + {0x019200ab, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5189 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +FireLaser),DEBUGSTRING("CPlayerWeapons::FireLaser")}, + {0x019200ac, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200ac_FireLaser_01), DEBUGSTRING("CPlayerWeapons::H0x019200ac_FireLaser_01")}, + {0x019200ad, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200ad_FireLaser_02), DEBUGSTRING("CPlayerWeapons::H0x019200ad_FireLaser_02")}, + {0x019200ae, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200ae_FireLaser_03), DEBUGSTRING("CPlayerWeapons::H0x019200ae_FireLaser_03")}, + {0x019200af, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200af_FireLaser_04), DEBUGSTRING("CPlayerWeapons::H0x019200af_FireLaser_04")}, + {0x019200b0, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5280 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +CannonFireStart),DEBUGSTRING("CPlayerWeapons::CannonFireStart")}, + {0x019200b1, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200b1_CannonFireStart_01), DEBUGSTRING("CPlayerWeapons::H0x019200b1_CannonFireStart_01")}, + {0x019200b2, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200b2_CannonFireStart_02), DEBUGSTRING("CPlayerWeapons::H0x019200b2_CannonFireStart_02")}, + {0x019200b3, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200b3_CannonFireStart_03), DEBUGSTRING("CPlayerWeapons::H0x019200b3_CannonFireStart_03")}, + {0x019200b4, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200b4_CannonFireStart_04), DEBUGSTRING("CPlayerWeapons::H0x019200b4_CannonFireStart_04")}, + {0x019200b5, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200b5_CannonFireStart_05), DEBUGSTRING("CPlayerWeapons::H0x019200b5_CannonFireStart_05")}, + {0x019200b6, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200b6_CannonFireStart_06), DEBUGSTRING("CPlayerWeapons::H0x019200b6_CannonFireStart_06")}, + {0x019200b7, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200b7_CannonFireStart_07), DEBUGSTRING("CPlayerWeapons::H0x019200b7_CannonFireStart_07")}, + {0x019200b8, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200b8_CannonFireStart_08), DEBUGSTRING("CPlayerWeapons::H0x019200b8_CannonFireStart_08")}, + {0x019200b9, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200b9_CannonFireStart_09), DEBUGSTRING("CPlayerWeapons::H0x019200b9_CannonFireStart_09")}, + {0x019200ba, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200ba_CannonFireStart_10), DEBUGSTRING("CPlayerWeapons::H0x019200ba_CannonFireStart_10")}, + {0x019200bb, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5389 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Reload),DEBUGSTRING("CPlayerWeapons::Reload")}, + {0x019200bc, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200bc_Reload_01), DEBUGSTRING("CPlayerWeapons::H0x019200bc_Reload_01")}, + {0x019200bd, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200bd_Reload_02), DEBUGSTRING("CPlayerWeapons::H0x019200bd_Reload_02")}, + {0x019200be, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200be_Reload_03), DEBUGSTRING("CPlayerWeapons::H0x019200be_Reload_03")}, + {0x019200bf, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200bf_Reload_04), DEBUGSTRING("CPlayerWeapons::H0x019200bf_Reload_04")}, + {0x019200c0, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200c0_Reload_05), DEBUGSTRING("CPlayerWeapons::H0x019200c0_Reload_05")}, + {0x019200c1, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200c1_Reload_06), DEBUGSTRING("CPlayerWeapons::H0x019200c1_Reload_06")}, + {0x019200c2, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200c2_Reload_07), DEBUGSTRING("CPlayerWeapons::H0x019200c2_Reload_07")}, + {0x019200c3, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5408 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChangeKnifeStand),DEBUGSTRING("CPlayerWeapons::ChangeKnifeStand")}, + {0x019200c4, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5424 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +ChangeToIronCannon),DEBUGSTRING("CPlayerWeapons::ChangeToIronCannon")}, + {0x019200c5, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5463 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +BoringWeaponAnimation),DEBUGSTRING("CPlayerWeapons::BoringWeaponAnimation")}, + {0x019200c6, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200c6_BoringWeaponAnimation_01), DEBUGSTRING("CPlayerWeapons::H0x019200c6_BoringWeaponAnimation_01")}, + {0x019200c7, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200c7_BoringWeaponAnimation_02), DEBUGSTRING("CPlayerWeapons::H0x019200c7_BoringWeaponAnimation_02")}, + {0x019200c8, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200c8_BoringWeaponAnimation_03), DEBUGSTRING("CPlayerWeapons::H0x019200c8_BoringWeaponAnimation_03")}, + {0x019200c9, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5493 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Idle),DEBUGSTRING("CPlayerWeapons::Idle")}, + {0x019200ca, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200ca_Idle_01), DEBUGSTRING("CPlayerWeapons::H0x019200ca_Idle_01")}, + {0x019200cb, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200cb_Idle_02), DEBUGSTRING("CPlayerWeapons::H0x019200cb_Idle_02")}, + {0x019200cc, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5539 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Stopped),DEBUGSTRING("CPlayerWeapons::Stopped")}, + {0x019200cd, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200cd_Stopped_01), DEBUGSTRING("CPlayerWeapons::H0x019200cd_Stopped_01")}, + {0x019200ce, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200ce_Stopped_02), DEBUGSTRING("CPlayerWeapons::H0x019200ce_Stopped_02")}, + {1, -1, CEntity::pEventHandler(&CPlayerWeapons:: +#line 5567 "D:/SE1_GPL/Sources/EntitiesMP/PlayerWeapons.es" +Main),DEBUGSTRING("CPlayerWeapons::Main")}, + {0x019200cf, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200cf_Main_01), DEBUGSTRING("CPlayerWeapons::H0x019200cf_Main_01")}, + {0x019200d0, -1, CEntity::pEventHandler(&CPlayerWeapons::H0x019200d0_Main_02), DEBUGSTRING("CPlayerWeapons::H0x019200d0_Main_02")}, +}; +#define CPlayerWeapons_handlersct ARRAYCOUNT(CPlayerWeapons_handlers) + +CEntity *CPlayerWeapons_New(void) { return new CPlayerWeapons; }; +void CPlayerWeapons_OnInitClass(void) {}; +void CPlayerWeapons_OnEndClass(void) {}; +void CPlayerWeapons_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPlayerWeapons_OnWorldEnd(CWorld *pwo) {}; +void CPlayerWeapons_OnWorldInit(CWorld *pwo) {}; +void CPlayerWeapons_OnWorldTick(CWorld *pwo) {}; +void CPlayerWeapons_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPlayerWeapons, CRationalEntity, "Player Weapons", "", 0x00000192); +DECLARE_CTFILENAME(_fnmCPlayerWeapons_tbn, ""); diff --git a/Sources/EntitiesMP/Player_tables.h b/Sources/EntitiesMP/Player_tables.h new file mode 100644 index 0000000..bd6fe1a --- /dev/null +++ b/Sources/EntitiesMP/Player_tables.h @@ -0,0 +1,549 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(PlayerViewType) + EP_ENUMVALUE(PVT_PLAYEREYES, ""), + EP_ENUMVALUE(PVT_PLAYERAUTOVIEW, ""), + EP_ENUMVALUE(PVT_SCENECAMERA, ""), + EP_ENUMVALUE(PVT_3RDPERSONVIEW, ""), +EP_ENUMEND(PlayerViewType); + +EP_ENUMBEG(PlayerState) + EP_ENUMVALUE(PST_STAND, ""), + EP_ENUMVALUE(PST_CROUCH, ""), + EP_ENUMVALUE(PST_SWIM, ""), + EP_ENUMVALUE(PST_DIVE, ""), + EP_ENUMVALUE(PST_FALL, ""), +EP_ENUMEND(PlayerState); + +#define ENTITYCLASS CPlayer + +CEntityProperty CPlayer_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000191<<8)+1, offsetof(CPlayer, m_strName), "Name", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x00000191<<8)+2, offsetof(CPlayer, m_ulLastButtons), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+3, offsetof(CPlayer, m_fArmor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000191<<8)+4, offsetof(CPlayer, m_strGroup), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+5, offsetof(CPlayer, m_ulKeys), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+6, offsetof(CPlayer, m_fMaxHealth), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+7, offsetof(CPlayer, m_ulFlags), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000191<<8)+16, offsetof(CPlayer, m_penWeapons), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000191<<8)+17, offsetof(CPlayer, m_penAnimator), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000191<<8)+18, offsetof(CPlayer, m_penView), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000191<<8)+19, offsetof(CPlayer, m_pen3rdPersonView), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+20, offsetof(CPlayer, m_iViewState), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+21, offsetof(CPlayer, m_iLastViewState), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANIMOBJECT, NULL, (0x00000191<<8)+26, offsetof(CPlayer, m_aoLightAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+27, offsetof(CPlayer, m_fDamageAmmount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+28, offsetof(CPlayer, m_tmWoundedTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+29, offsetof(CPlayer, m_tmScreamTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+33, offsetof(CPlayer, m_iGender), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &PlayerState_enum, (0x00000191<<8)+34, offsetof(CPlayer, m_pstState), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+35, offsetof(CPlayer, m_fFallTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+36, offsetof(CPlayer, m_fSwimTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+45, offsetof(CPlayer, m_tmOutOfWater), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+37, offsetof(CPlayer, m_tmMoveSound), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000191<<8)+38, offsetof(CPlayer, m_bMoveSoundLeft), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+39, offsetof(CPlayer, m_tmNextAmbientOnce), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+43, offsetof(CPlayer, m_tmMouthSoundLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000191<<8)+40, offsetof(CPlayer, m_penCamera), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000191<<8)+41, offsetof(CPlayer, m_strCenterMessage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+42, offsetof(CPlayer, m_tmCenterMessageEnd), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000191<<8)+48, offsetof(CPlayer, m_bPendingMessage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+47, offsetof(CPlayer, m_tmMessagePlay), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+49, offsetof(CPlayer, m_tmAnalyseEnd), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000191<<8)+50, offsetof(CPlayer, m_bComputerInvoked), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+57, offsetof(CPlayer, m_tmAnimateInbox), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000191<<8)+44, offsetof(CPlayer, m_penMainMusicHolder), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+51, offsetof(CPlayer, m_tmLastDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+52, offsetof(CPlayer, m_fMaxDamageAmmount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000191<<8)+53, offsetof(CPlayer, m_vDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+54, offsetof(CPlayer, m_tmSpraySpawned), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+55, offsetof(CPlayer, m_fSprayDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000191<<8)+56, offsetof(CPlayer, m_penSpray), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+60, offsetof(CPlayer, m_soWeapon0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+61, offsetof(CPlayer, m_soWeapon1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+62, offsetof(CPlayer, m_soWeapon2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+63, offsetof(CPlayer, m_soWeapon3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+64, offsetof(CPlayer, m_soWeaponAmbient), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+65, offsetof(CPlayer, m_soPowerUpBeep), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+70, offsetof(CPlayer, m_soMouth), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+71, offsetof(CPlayer, m_soFootL), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+72, offsetof(CPlayer, m_soFootR), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+73, offsetof(CPlayer, m_soBody), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+74, offsetof(CPlayer, m_soLocalAmbientLoop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+75, offsetof(CPlayer, m_soLocalAmbientOnce), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+76, offsetof(CPlayer, m_soMessage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+77, offsetof(CPlayer, m_soHighScore), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+78, offsetof(CPlayer, m_soSpeech), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000191<<8)+79, offsetof(CPlayer, m_soSniperZoom), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+81, offsetof(CPlayer, m_iMana), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+94, offsetof(CPlayer, m_fManaFraction), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+84, offsetof(CPlayer, m_iHighScore), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+85, offsetof(CPlayer, m_iBeatenHighScore), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+89, offsetof(CPlayer, m_tmLatency), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+88, offsetof(CPlayer, m_tmLatencyLastAvg), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+87, offsetof(CPlayer, m_tmLatencyAvgSum), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+86, offsetof(CPlayer, m_ctLatencyAvg), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000191<<8)+96, offsetof(CPlayer, m_bEndOfLevel), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000191<<8)+97, offsetof(CPlayer, m_bEndOfGame), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+98, offsetof(CPlayer, m_iMayRespawn), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+99, offsetof(CPlayer, m_tmSpawned), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000191<<8)+100, offsetof(CPlayer, m_vDied), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000191<<8)+101, offsetof(CPlayer, m_aDied), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+103, offsetof(CPlayer, m_tmEstTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+105, offsetof(CPlayer, m_iTimeScore), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+106, offsetof(CPlayer, m_iStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+107, offsetof(CPlayer, m_iEndTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+108, offsetof(CPlayer, m_tmLevelStarted), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000191<<8)+93, offsetof(CPlayer, m_strLevelStats), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000191<<8)+110, offsetof(CPlayer, m_penActionMarker), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+111, offsetof(CPlayer, m_fAutoSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+112, offsetof(CPlayer, m_iAutoOrgWeapon), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000191<<8)+113, offsetof(CPlayer, m_vAutoSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+114, offsetof(CPlayer, m_tmSpiritStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+115, offsetof(CPlayer, m_tmFadeStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+120, offsetof(CPlayer, m_tmLastPicked), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000191<<8)+121, offsetof(CPlayer, m_strPickedName), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+122, offsetof(CPlayer, m_fPickedAmmount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+123, offsetof(CPlayer, m_fPickedMana), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+130, offsetof(CPlayer, m_iLastHealth), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+131, offsetof(CPlayer, m_iLastArmor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+132, offsetof(CPlayer, m_iLastAmmo), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+135, offsetof(CPlayer, m_tmHealthChanged), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+136, offsetof(CPlayer, m_tmArmorChanged), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+137, offsetof(CPlayer, m_tmAmmoChanged), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+138, offsetof(CPlayer, m_tmMinigunAutoFireStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000191<<8)+150, offsetof(CPlayer, m_vLastStain), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x00000191<<8)+151, offsetof(CPlayer, m_aLastRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x00000191<<8)+152, offsetof(CPlayer, m_aLastViewRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000191<<8)+153, offsetof(CPlayer, m_vLastTranslation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x00000191<<8)+154, offsetof(CPlayer, m_aLocalRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x00000191<<8)+155, offsetof(CPlayer, m_aLocalViewRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000191<<8)+156, offsetof(CPlayer, m_vLocalTranslation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+160, offsetof(CPlayer, m_tmInvisibility), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+161, offsetof(CPlayer, m_tmInvulnerability), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+162, offsetof(CPlayer, m_tmSeriousDamage), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+163, offsetof(CPlayer, m_tmSeriousSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+166, offsetof(CPlayer, m_tmInvisibilityMax), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+167, offsetof(CPlayer, m_tmInvulnerabilityMax), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+168, offsetof(CPlayer, m_tmSeriousDamageMax), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+169, offsetof(CPlayer, m_tmSeriousSpeedMax), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+180, offsetof(CPlayer, m_tmChainShakeEnd), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+181, offsetof(CPlayer, m_fChainShakeStrength), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+182, offsetof(CPlayer, m_fChainShakeFreqMod), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+183, offsetof(CPlayer, m_fChainsawShakeDX), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+184, offsetof(CPlayer, m_fChainsawShakeDY), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+190, offsetof(CPlayer, m_iSeriousBombCount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000191<<8)+191, offsetof(CPlayer, m_iLastSeriousBombCount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000191<<8)+192, offsetof(CPlayer, m_tmSeriousBombFired), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000191<<8)+255, offsetof(CPlayer, m_penPrediction), "", 0, 0, 0), +}; +#define CPlayer_propertiesct ARRAYCOUNT(CPlayer_properties) + +CEntityComponent CPlayer_components[] = { +#define CLASS_PLAYER_WEAPONS ((0x00000191<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_PLAYER_WEAPONS, "EFNM" "Classes\\PlayerWeapons.ecl"), +#define CLASS_PLAYER_ANIMATOR ((0x00000191<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_PLAYER_ANIMATOR, "EFNM" "Classes\\PlayerAnimator.ecl"), +#define CLASS_PLAYER_VIEW ((0x00000191<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PLAYER_VIEW, "EFNM" "Classes\\PlayerView.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000191<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_BLOOD_SPRAY ((0x00000191<<8)+5) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define CLASS_SERIOUSBOMB ((0x00000191<<8)+6) + CEntityComponent(ECT_CLASS, CLASS_SERIOUSBOMB, "EFNM" "Classes\\SeriousBomb.ecl"), +#define SOUND_WATER_ENTER ((0x00000191<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_WATER_ENTER, "EFNM" "Sounds\\Player\\WaterEnter.wav"), +#define SOUND_WATER_LEAVE ((0x00000191<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_WATER_LEAVE, "EFNM" "Sounds\\Player\\WaterLeave.wav"), +#define SOUND_WALK_L ((0x00000191<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_WALK_L, "EFNM" "Sounds\\Player\\WalkL.wav"), +#define SOUND_WALK_R ((0x00000191<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_WALK_R, "EFNM" "Sounds\\Player\\WalkR.wav"), +#define SOUND_SWIM_L ((0x00000191<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_SWIM_L, "EFNM" "Sounds\\Player\\SwimL.wav"), +#define SOUND_SWIM_R ((0x00000191<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_SWIM_R, "EFNM" "Sounds\\Player\\SwimR.wav"), +#define SOUND_DIVE_L ((0x00000191<<8)+56) + CEntityComponent(ECT_SOUND, SOUND_DIVE_L, "EFNM" "Sounds\\Player\\Dive.wav"), +#define SOUND_DIVE_R ((0x00000191<<8)+57) + CEntityComponent(ECT_SOUND, SOUND_DIVE_R, "EFNM" "Sounds\\Player\\Dive.wav"), +#define SOUND_DIVEIN ((0x00000191<<8)+58) + CEntityComponent(ECT_SOUND, SOUND_DIVEIN, "EFNM" "Sounds\\Player\\DiveIn.wav"), +#define SOUND_DIVEOUT ((0x00000191<<8)+59) + CEntityComponent(ECT_SOUND, SOUND_DIVEOUT, "EFNM" "Sounds\\Player\\DiveOut.wav"), +#define SOUND_DROWN ((0x00000191<<8)+60) + CEntityComponent(ECT_SOUND, SOUND_DROWN, "EFNM" "Sounds\\Player\\Drown.wav"), +#define SOUND_INHALE0 ((0x00000191<<8)+61) + CEntityComponent(ECT_SOUND, SOUND_INHALE0, "EFNM" "Sounds\\Player\\Inhale00.wav"), +#define SOUND_JUMP ((0x00000191<<8)+62) + CEntityComponent(ECT_SOUND, SOUND_JUMP, "EFNM" "Sounds\\Player\\Jump.wav"), +#define SOUND_LAND ((0x00000191<<8)+63) + CEntityComponent(ECT_SOUND, SOUND_LAND, "EFNM" "Sounds\\Player\\Land.wav"), +#define SOUND_DEATH ((0x00000191<<8)+66) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "Sounds\\Player\\Death.wav"), +#define SOUND_DEATHWATER ((0x00000191<<8)+67) + CEntityComponent(ECT_SOUND, SOUND_DEATHWATER, "EFNM" "Sounds\\Player\\DeathWater.wav"), +#define SOUND_WATERWALK_L ((0x00000191<<8)+70) + CEntityComponent(ECT_SOUND, SOUND_WATERWALK_L, "EFNM" "Sounds\\Player\\WalkWaterL.wav"), +#define SOUND_WATERWALK_R ((0x00000191<<8)+71) + CEntityComponent(ECT_SOUND, SOUND_WATERWALK_R, "EFNM" "Sounds\\Player\\WalkWaterR.wav"), +#define SOUND_INHALE1 ((0x00000191<<8)+72) + CEntityComponent(ECT_SOUND, SOUND_INHALE1, "EFNM" "Sounds\\Player\\Inhale01.wav"), +#define SOUND_INHALE2 ((0x00000191<<8)+73) + CEntityComponent(ECT_SOUND, SOUND_INHALE2, "EFNM" "Sounds\\Player\\Inhale02.wav"), +#define SOUND_WALK_SAND_L ((0x00000191<<8)+75) + CEntityComponent(ECT_SOUND, SOUND_WALK_SAND_L, "EFNM" "Sounds\\Player\\WalkSandL.wav"), +#define SOUND_WALK_SAND_R ((0x00000191<<8)+76) + CEntityComponent(ECT_SOUND, SOUND_WALK_SAND_R, "EFNM" "Sounds\\Player\\WalkSandR.wav"), +#define SOUND_WOUNDWEAK ((0x00000191<<8)+80) + CEntityComponent(ECT_SOUND, SOUND_WOUNDWEAK, "EFNM" "Sounds\\Player\\WoundWeak.wav"), +#define SOUND_WOUNDMEDIUM ((0x00000191<<8)+81) + CEntityComponent(ECT_SOUND, SOUND_WOUNDMEDIUM, "EFNM" "Sounds\\Player\\WoundMedium.wav"), +#define SOUND_WOUNDSTRONG ((0x00000191<<8)+82) + CEntityComponent(ECT_SOUND, SOUND_WOUNDSTRONG, "EFNM" "Sounds\\Player\\WoundStrong.wav"), +#define SOUND_WOUNDWATER ((0x00000191<<8)+85) + CEntityComponent(ECT_SOUND, SOUND_WOUNDWATER, "EFNM" "Sounds\\Player\\WoundWater.wav"), +#define SOUND_WALK_GRASS_L ((0x00000191<<8)+86) + CEntityComponent(ECT_SOUND, SOUND_WALK_GRASS_L, "EFNM" "SoundsMP\\Player\\WalkGrassL.wav"), +#define SOUND_WALK_GRASS_R ((0x00000191<<8)+87) + CEntityComponent(ECT_SOUND, SOUND_WALK_GRASS_R, "EFNM" "SoundsMP\\Player\\WalkGrassR.wav"), +#define SOUND_WALK_WOOD_L ((0x00000191<<8)+88) + CEntityComponent(ECT_SOUND, SOUND_WALK_WOOD_L, "EFNM" "SoundsMP\\Player\\WalkWoodL.wav"), +#define SOUND_WALK_WOOD_R ((0x00000191<<8)+89) + CEntityComponent(ECT_SOUND, SOUND_WALK_WOOD_R, "EFNM" "SoundsMP\\Player\\WalkWoodR.wav"), +#define SOUND_WALK_SNOW_L ((0x00000191<<8)+90) + CEntityComponent(ECT_SOUND, SOUND_WALK_SNOW_L, "EFNM" "SoundsMP\\Player\\WalkSnowL.wav"), +#define SOUND_WALK_SNOW_R ((0x00000191<<8)+91) + CEntityComponent(ECT_SOUND, SOUND_WALK_SNOW_R, "EFNM" "SoundsMP\\Player\\WalkSnowR.wav"), +#define SOUND_BLOWUP ((0x00000191<<8)+92) + CEntityComponent(ECT_SOUND, SOUND_BLOWUP, "EFNM" "SoundsMP\\Player\\BlowUp.wav"), +#define SOUND_F_WATER_ENTER ((0x00000191<<8)+150) + CEntityComponent(ECT_SOUND, SOUND_F_WATER_ENTER, "EFNM" "SoundsMP\\Player\\Female\\WaterEnter.wav"), +#define SOUND_F_WATER_LEAVE ((0x00000191<<8)+151) + CEntityComponent(ECT_SOUND, SOUND_F_WATER_LEAVE, "EFNM" "SoundsMP\\Player\\Female\\WaterLeave.wav"), +#define SOUND_F_WALK_L ((0x00000191<<8)+152) + CEntityComponent(ECT_SOUND, SOUND_F_WALK_L, "EFNM" "SoundsMP\\Player\\Female\\WalkL.wav"), +#define SOUND_F_WALK_R ((0x00000191<<8)+153) + CEntityComponent(ECT_SOUND, SOUND_F_WALK_R, "EFNM" "SoundsMP\\Player\\Female\\WalkR.wav"), +#define SOUND_F_SWIM_L ((0x00000191<<8)+154) + CEntityComponent(ECT_SOUND, SOUND_F_SWIM_L, "EFNM" "SoundsMP\\Player\\Female\\SwimL.wav"), +#define SOUND_F_SWIM_R ((0x00000191<<8)+155) + CEntityComponent(ECT_SOUND, SOUND_F_SWIM_R, "EFNM" "SoundsMP\\Player\\Female\\SwimR.wav"), +#define SOUND_F_DIVE_L ((0x00000191<<8)+156) + CEntityComponent(ECT_SOUND, SOUND_F_DIVE_L, "EFNM" "SoundsMP\\Player\\Female\\Dive.wav"), +#define SOUND_F_DIVE_R ((0x00000191<<8)+157) + CEntityComponent(ECT_SOUND, SOUND_F_DIVE_R, "EFNM" "SoundsMP\\Player\\Female\\Dive.wav"), +#define SOUND_F_DIVEIN ((0x00000191<<8)+158) + CEntityComponent(ECT_SOUND, SOUND_F_DIVEIN, "EFNM" "SoundsMP\\Player\\Female\\DiveIn.wav"), +#define SOUND_F_DIVEOUT ((0x00000191<<8)+159) + CEntityComponent(ECT_SOUND, SOUND_F_DIVEOUT, "EFNM" "SoundsMP\\Player\\Female\\DiveOut.wav"), +#define SOUND_F_DROWN ((0x00000191<<8)+160) + CEntityComponent(ECT_SOUND, SOUND_F_DROWN, "EFNM" "SoundsMP\\Player\\Female\\Drown.wav"), +#define SOUND_F_INHALE0 ((0x00000191<<8)+161) + CEntityComponent(ECT_SOUND, SOUND_F_INHALE0, "EFNM" "SoundsMP\\Player\\Female\\Inhale00.wav"), +#define SOUND_F_JUMP ((0x00000191<<8)+162) + CEntityComponent(ECT_SOUND, SOUND_F_JUMP, "EFNM" "SoundsMP\\Player\\Female\\Jump.wav"), +#define SOUND_F_LAND ((0x00000191<<8)+163) + CEntityComponent(ECT_SOUND, SOUND_F_LAND, "EFNM" "SoundsMP\\Player\\Female\\Land.wav"), +#define SOUND_F_DEATH ((0x00000191<<8)+166) + CEntityComponent(ECT_SOUND, SOUND_F_DEATH, "EFNM" "SoundsMP\\Player\\Female\\Death.wav"), +#define SOUND_F_DEATHWATER ((0x00000191<<8)+167) + CEntityComponent(ECT_SOUND, SOUND_F_DEATHWATER, "EFNM" "SoundsMP\\Player\\Female\\DeathWater.wav"), +#define SOUND_F_WATERWALK_L ((0x00000191<<8)+170) + CEntityComponent(ECT_SOUND, SOUND_F_WATERWALK_L, "EFNM" "SoundsMP\\Player\\Female\\WalkWaterL.wav"), +#define SOUND_F_WATERWALK_R ((0x00000191<<8)+171) + CEntityComponent(ECT_SOUND, SOUND_F_WATERWALK_R, "EFNM" "SoundsMP\\Player\\Female\\WalkWaterR.wav"), +#define SOUND_F_INHALE1 ((0x00000191<<8)+172) + CEntityComponent(ECT_SOUND, SOUND_F_INHALE1, "EFNM" "SoundsMP\\Player\\Female\\Inhale01.wav"), +#define SOUND_F_INHALE2 ((0x00000191<<8)+173) + CEntityComponent(ECT_SOUND, SOUND_F_INHALE2, "EFNM" "SoundsMP\\Player\\Female\\Inhale02.wav"), +#define SOUND_F_WALK_SAND_L ((0x00000191<<8)+175) + CEntityComponent(ECT_SOUND, SOUND_F_WALK_SAND_L, "EFNM" "SoundsMP\\Player\\Female\\WalkSandL.wav"), +#define SOUND_F_WALK_SAND_R ((0x00000191<<8)+176) + CEntityComponent(ECT_SOUND, SOUND_F_WALK_SAND_R, "EFNM" "SoundsMP\\Player\\Female\\WalkSandR.wav"), +#define SOUND_F_WOUNDWEAK ((0x00000191<<8)+180) + CEntityComponent(ECT_SOUND, SOUND_F_WOUNDWEAK, "EFNM" "SoundsMP\\Player\\Female\\WoundWeak.wav"), +#define SOUND_F_WOUNDMEDIUM ((0x00000191<<8)+181) + CEntityComponent(ECT_SOUND, SOUND_F_WOUNDMEDIUM, "EFNM" "SoundsMP\\Player\\Female\\WoundMedium.wav"), +#define SOUND_F_WOUNDSTRONG ((0x00000191<<8)+182) + CEntityComponent(ECT_SOUND, SOUND_F_WOUNDSTRONG, "EFNM" "SoundsMP\\Player\\Female\\WoundStrong.wav"), +#define SOUND_F_WOUNDWATER ((0x00000191<<8)+185) + CEntityComponent(ECT_SOUND, SOUND_F_WOUNDWATER, "EFNM" "SoundsMP\\Player\\Female\\WoundWater.wav"), +#define SOUND_F_WALK_GRASS_L ((0x00000191<<8)+186) + CEntityComponent(ECT_SOUND, SOUND_F_WALK_GRASS_L, "EFNM" "SoundsMP\\Player\\Female\\WalkGrassL.wav"), +#define SOUND_F_WALK_GRASS_R ((0x00000191<<8)+187) + CEntityComponent(ECT_SOUND, SOUND_F_WALK_GRASS_R, "EFNM" "SoundsMP\\Player\\Female\\WalkGrassR.wav"), +#define SOUND_F_WALK_WOOD_L ((0x00000191<<8)+188) + CEntityComponent(ECT_SOUND, SOUND_F_WALK_WOOD_L, "EFNM" "SoundsMP\\Player\\Female\\WalkWoodL.wav"), +#define SOUND_F_WALK_WOOD_R ((0x00000191<<8)+189) + CEntityComponent(ECT_SOUND, SOUND_F_WALK_WOOD_R, "EFNM" "SoundsMP\\Player\\Female\\WalkWoodR.wav"), +#define SOUND_F_WALK_SNOW_L ((0x00000191<<8)+190) + CEntityComponent(ECT_SOUND, SOUND_F_WALK_SNOW_L, "EFNM" "SoundsMP\\Player\\Female\\WalkSnowL.wav"), +#define SOUND_F_WALK_SNOW_R ((0x00000191<<8)+191) + CEntityComponent(ECT_SOUND, SOUND_F_WALK_SNOW_R, "EFNM" "SoundsMP\\Player\\Female\\WalkSnowR.wav"), +#define SOUND_SILENCE ((0x00000191<<8)+200) + CEntityComponent(ECT_SOUND, SOUND_SILENCE, "EFNM" "Sounds\\Misc\\Silence.wav"), +#define SOUND_SNIPER_ZOOM ((0x00000191<<8)+201) + CEntityComponent(ECT_SOUND, SOUND_SNIPER_ZOOM, "EFNM" "ModelsMP\\Weapons\\Sniper\\Sounds\\Zoom.wav"), +#define SOUND_SNIPER_QZOOM ((0x00000191<<8)+206) + CEntityComponent(ECT_SOUND, SOUND_SNIPER_QZOOM, "EFNM" "ModelsMP\\Weapons\\Sniper\\Sounds\\QuickZoom.wav"), +#define SOUND_INFO ((0x00000191<<8)+202) + CEntityComponent(ECT_SOUND, SOUND_INFO, "EFNM" "Sounds\\Player\\Info.wav"), +#define SOUND_WATERAMBIENT ((0x00000191<<8)+203) + CEntityComponent(ECT_SOUND, SOUND_WATERAMBIENT, "EFNM" "Sounds\\Player\\Underwater.wav"), +#define SOUND_WATERBUBBLES ((0x00000191<<8)+204) + CEntityComponent(ECT_SOUND, SOUND_WATERBUBBLES, "EFNM" "Sounds\\Player\\Bubbles.wav"), +#define SOUND_POWERUP_BEEP ((0x00000191<<8)+205) + CEntityComponent(ECT_SOUND, SOUND_POWERUP_BEEP, "EFNM" "SoundsMP\\Player\\PowerUpBeep.wav"), +#define MODEL_FLESH ((0x00000191<<8)+210) + CEntityComponent(ECT_MODEL, MODEL_FLESH, "EFNM" "Models\\Effects\\Debris\\Flesh\\Flesh.mdl"), +#define MODEL_FLESH_APPLE ((0x00000191<<8)+211) + CEntityComponent(ECT_MODEL, MODEL_FLESH_APPLE, "EFNM" "Models\\Effects\\Debris\\Fruits\\Apple.mdl"), +#define MODEL_FLESH_BANANA ((0x00000191<<8)+212) + CEntityComponent(ECT_MODEL, MODEL_FLESH_BANANA, "EFNM" "Models\\Effects\\Debris\\Fruits\\Banana.mdl"), +#define MODEL_FLESH_BURGER ((0x00000191<<8)+213) + CEntityComponent(ECT_MODEL, MODEL_FLESH_BURGER, "EFNM" "Models\\Effects\\Debris\\Fruits\\CheeseBurger.mdl"), +#define MODEL_FLESH_LOLLY ((0x00000191<<8)+214) + CEntityComponent(ECT_MODEL, MODEL_FLESH_LOLLY, "EFNM" "Models\\Effects\\Debris\\Fruits\\LollyPop.mdl"), +#define MODEL_FLESH_ORANGE ((0x00000191<<8)+215) + CEntityComponent(ECT_MODEL, MODEL_FLESH_ORANGE, "EFNM" "Models\\Effects\\Debris\\Fruits\\Orange.mdl"), +#define TEXTURE_FLESH_RED ((0x00000191<<8)+220) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_RED, "EFNM" "Models\\Effects\\Debris\\Flesh\\FleshRed.tex"), +#define TEXTURE_FLESH_GREEN ((0x00000191<<8)+221) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_GREEN, "EFNM" "Models\\Effects\\Debris\\Flesh\\FleshGreen.tex"), +#define TEXTURE_FLESH_APPLE ((0x00000191<<8)+222) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_APPLE, "EFNM" "Models\\Effects\\Debris\\Fruits\\Apple.tex"), +#define TEXTURE_FLESH_BANANA ((0x00000191<<8)+223) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_BANANA, "EFNM" "Models\\Effects\\Debris\\Fruits\\Banana.tex"), +#define TEXTURE_FLESH_BURGER ((0x00000191<<8)+224) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_BURGER, "EFNM" "Models\\Effects\\Debris\\Fruits\\CheeseBurger.tex"), +#define TEXTURE_FLESH_LOLLY ((0x00000191<<8)+225) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_LOLLY, "EFNM" "Models\\Effects\\Debris\\Fruits\\LollyPop.tex"), +#define TEXTURE_FLESH_ORANGE ((0x00000191<<8)+226) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLESH_ORANGE, "EFNM" "Models\\Effects\\Debris\\Fruits\\Orange.tex"), +}; +#define CPlayer_componentsct ARRAYCOUNT(CPlayer_components) + +CEventHandlerEntry CPlayer_handlers[] = { + {0x01910005, -1, CEntity::pEventHandler(&CPlayer:: +#line 5482 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Wounded),DEBUGSTRING("CPlayer::Wounded")}, + {0x01910006, -1, CEntity::pEventHandler(&CPlayer:: +#line 5490 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +WorldChange),DEBUGSTRING("CPlayer::WorldChange")}, + {0x01910007, -1, CEntity::pEventHandler(&CPlayer:: +#line 5521 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +WorldChangeDead),DEBUGSTRING("CPlayer::WorldChangeDead")}, + {0x01910008, -1, CEntity::pEventHandler(&CPlayer::H0x01910008_WorldChangeDead_01), DEBUGSTRING("CPlayer::H0x01910008_WorldChangeDead_01")}, + {0x01910009, -1, CEntity::pEventHandler(&CPlayer::H0x01910009_WorldChangeDead_02), DEBUGSTRING("CPlayer::H0x01910009_WorldChangeDead_02")}, + {0x0191000a, -1, CEntity::pEventHandler(&CPlayer:: +#line 5552 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Death),DEBUGSTRING("CPlayer::Death")}, + {0x0191000b, -1, CEntity::pEventHandler(&CPlayer::H0x0191000b_Death_01), DEBUGSTRING("CPlayer::H0x0191000b_Death_01")}, + {0x0191000c, -1, CEntity::pEventHandler(&CPlayer::H0x0191000c_Death_02), DEBUGSTRING("CPlayer::H0x0191000c_Death_02")}, + {0x0191000d, -1, CEntity::pEventHandler(&CPlayer:: +#line 5812 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TheEnd),DEBUGSTRING("CPlayer::TheEnd")}, + {0x0191000e, -1, CEntity::pEventHandler(&CPlayer::H0x0191000e_TheEnd_01), DEBUGSTRING("CPlayer::H0x0191000e_TheEnd_01")}, + {0x0191000f, -1, CEntity::pEventHandler(&CPlayer::H0x0191000f_TheEnd_02), DEBUGSTRING("CPlayer::H0x0191000f_TheEnd_02")}, + {0x01910010, -1, CEntity::pEventHandler(&CPlayer:: +#line 5859 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +FirstInit),DEBUGSTRING("CPlayer::FirstInit")}, + {0x01910011, -1, CEntity::pEventHandler(&CPlayer:: +#line 5890 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Rebirth),DEBUGSTRING("CPlayer::Rebirth")}, + {0x01910012, -1, CEntity::pEventHandler(&CPlayer:: +#line 5932 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoGoToMarker),DEBUGSTRING("CPlayer::AutoGoToMarker")}, + {0x01910013, -1, CEntity::pEventHandler(&CPlayer::H0x01910013_AutoGoToMarker_01), DEBUGSTRING("CPlayer::H0x01910013_AutoGoToMarker_01")}, + {0x01910014, -1, CEntity::pEventHandler(&CPlayer::H0x01910014_AutoGoToMarker_02), DEBUGSTRING("CPlayer::H0x01910014_AutoGoToMarker_02")}, + {0x01910015, -1, CEntity::pEventHandler(&CPlayer::H0x01910015_AutoGoToMarker_03), DEBUGSTRING("CPlayer::H0x01910015_AutoGoToMarker_03")}, + {0x01910016, -1, CEntity::pEventHandler(&CPlayer::H0x01910016_AutoGoToMarker_04), DEBUGSTRING("CPlayer::H0x01910016_AutoGoToMarker_04")}, + {0x01910017, -1, CEntity::pEventHandler(&CPlayer:: +#line 5964 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoGoToMarkerAndStop),DEBUGSTRING("CPlayer::AutoGoToMarkerAndStop")}, + {0x01910018, -1, CEntity::pEventHandler(&CPlayer::H0x01910018_AutoGoToMarkerAndStop_01), DEBUGSTRING("CPlayer::H0x01910018_AutoGoToMarkerAndStop_01")}, + {0x01910019, -1, CEntity::pEventHandler(&CPlayer::H0x01910019_AutoGoToMarkerAndStop_02), DEBUGSTRING("CPlayer::H0x01910019_AutoGoToMarkerAndStop_02")}, + {0x0191001a, -1, CEntity::pEventHandler(&CPlayer::H0x0191001a_AutoGoToMarkerAndStop_03), DEBUGSTRING("CPlayer::H0x0191001a_AutoGoToMarkerAndStop_03")}, + {0x0191001b, -1, CEntity::pEventHandler(&CPlayer::H0x0191001b_AutoGoToMarkerAndStop_04), DEBUGSTRING("CPlayer::H0x0191001b_AutoGoToMarkerAndStop_04")}, + {0x0191001c, -1, CEntity::pEventHandler(&CPlayer:: +#line 6004 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoUseItem),DEBUGSTRING("CPlayer::AutoUseItem")}, + {0x0191001d, -1, CEntity::pEventHandler(&CPlayer::H0x0191001d_AutoUseItem_01), DEBUGSTRING("CPlayer::H0x0191001d_AutoUseItem_01")}, + {0x0191001e, -1, CEntity::pEventHandler(&CPlayer::H0x0191001e_AutoUseItem_02), DEBUGSTRING("CPlayer::H0x0191001e_AutoUseItem_02")}, + {0x0191001f, -1, CEntity::pEventHandler(&CPlayer::H0x0191001f_AutoUseItem_03), DEBUGSTRING("CPlayer::H0x0191001f_AutoUseItem_03")}, + {0x01910020, -1, CEntity::pEventHandler(&CPlayer::H0x01910020_AutoUseItem_04), DEBUGSTRING("CPlayer::H0x01910020_AutoUseItem_04")}, + {0x01910021, -1, CEntity::pEventHandler(&CPlayer::H0x01910021_AutoUseItem_05), DEBUGSTRING("CPlayer::H0x01910021_AutoUseItem_05")}, + {0x01910022, -1, CEntity::pEventHandler(&CPlayer::H0x01910022_AutoUseItem_06), DEBUGSTRING("CPlayer::H0x01910022_AutoUseItem_06")}, + {0x01910023, -1, CEntity::pEventHandler(&CPlayer:: +#line 6049 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoPickItem),DEBUGSTRING("CPlayer::AutoPickItem")}, + {0x01910024, -1, CEntity::pEventHandler(&CPlayer::H0x01910024_AutoPickItem_01), DEBUGSTRING("CPlayer::H0x01910024_AutoPickItem_01")}, + {0x01910025, -1, CEntity::pEventHandler(&CPlayer::H0x01910025_AutoPickItem_02), DEBUGSTRING("CPlayer::H0x01910025_AutoPickItem_02")}, + {0x01910026, -1, CEntity::pEventHandler(&CPlayer::H0x01910026_AutoPickItem_03), DEBUGSTRING("CPlayer::H0x01910026_AutoPickItem_03")}, + {0x01910027, -1, CEntity::pEventHandler(&CPlayer::H0x01910027_AutoPickItem_04), DEBUGSTRING("CPlayer::H0x01910027_AutoPickItem_04")}, + {0x01910028, -1, CEntity::pEventHandler(&CPlayer:: +#line 6084 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoFallDown),DEBUGSTRING("CPlayer::AutoFallDown")}, + {0x01910029, -1, CEntity::pEventHandler(&CPlayer::H0x01910029_AutoFallDown_01), DEBUGSTRING("CPlayer::H0x01910029_AutoFallDown_01")}, + {0x0191002a, -1, CEntity::pEventHandler(&CPlayer::H0x0191002a_AutoFallDown_02), DEBUGSTRING("CPlayer::H0x0191002a_AutoFallDown_02")}, + {0x0191002b, -1, CEntity::pEventHandler(&CPlayer:: +#line 6096 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoFallToAbys),DEBUGSTRING("CPlayer::AutoFallToAbys")}, + {0x0191002c, -1, CEntity::pEventHandler(&CPlayer::H0x0191002c_AutoFallToAbys_01), DEBUGSTRING("CPlayer::H0x0191002c_AutoFallToAbys_01")}, + {0x0191002d, -1, CEntity::pEventHandler(&CPlayer::H0x0191002d_AutoFallToAbys_02), DEBUGSTRING("CPlayer::H0x0191002d_AutoFallToAbys_02")}, + {0x0191002e, -1, CEntity::pEventHandler(&CPlayer:: +#line 6109 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoLookAround),DEBUGSTRING("CPlayer::AutoLookAround")}, + {0x0191002f, -1, CEntity::pEventHandler(&CPlayer::H0x0191002f_AutoLookAround_01), DEBUGSTRING("CPlayer::H0x0191002f_AutoLookAround_01")}, + {0x01910030, -1, CEntity::pEventHandler(&CPlayer::H0x01910030_AutoLookAround_02), DEBUGSTRING("CPlayer::H0x01910030_AutoLookAround_02")}, + {0x01910031, -1, CEntity::pEventHandler(&CPlayer::H0x01910031_AutoLookAround_03), DEBUGSTRING("CPlayer::H0x01910031_AutoLookAround_03")}, + {0x01910032, -1, CEntity::pEventHandler(&CPlayer::H0x01910032_AutoLookAround_04), DEBUGSTRING("CPlayer::H0x01910032_AutoLookAround_04")}, + {0x01910033, -1, CEntity::pEventHandler(&CPlayer:: +#line 6133 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoTeleport),DEBUGSTRING("CPlayer::AutoTeleport")}, + {0x01910034, -1, CEntity::pEventHandler(&CPlayer:: +#line 6142 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoAppear),DEBUGSTRING("CPlayer::AutoAppear")}, + {0x01910035, -1, CEntity::pEventHandler(&CPlayer::H0x01910035_AutoAppear_01), DEBUGSTRING("CPlayer::H0x01910035_AutoAppear_01")}, + {0x01910036, -1, CEntity::pEventHandler(&CPlayer::H0x01910036_AutoAppear_02), DEBUGSTRING("CPlayer::H0x01910036_AutoAppear_02")}, + {0x01910037, -1, CEntity::pEventHandler(&CPlayer::H0x01910037_AutoAppear_03), DEBUGSTRING("CPlayer::H0x01910037_AutoAppear_03")}, + {0x01910038, -1, CEntity::pEventHandler(&CPlayer::H0x01910038_AutoAppear_04), DEBUGSTRING("CPlayer::H0x01910038_AutoAppear_04")}, + {0x01910039, -1, CEntity::pEventHandler(&CPlayer::H0x01910039_AutoAppear_05), DEBUGSTRING("CPlayer::H0x01910039_AutoAppear_05")}, + {0x0191003a, -1, CEntity::pEventHandler(&CPlayer::H0x0191003a_AutoAppear_06), DEBUGSTRING("CPlayer::H0x0191003a_AutoAppear_06")}, + {0x0191003b, -1, CEntity::pEventHandler(&CPlayer::H0x0191003b_AutoAppear_07), DEBUGSTRING("CPlayer::H0x0191003b_AutoAppear_07")}, + {0x0191003c, -1, CEntity::pEventHandler(&CPlayer::H0x0191003c_AutoAppear_08), DEBUGSTRING("CPlayer::H0x0191003c_AutoAppear_08")}, + {0x0191003d, -1, CEntity::pEventHandler(&CPlayer:: +#line 6194 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +TravellingInBeam),DEBUGSTRING("CPlayer::TravellingInBeam")}, + {0x0191003e, -1, CEntity::pEventHandler(&CPlayer::H0x0191003e_TravellingInBeam_01), DEBUGSTRING("CPlayer::H0x0191003e_TravellingInBeam_01")}, + {0x0191003f, -1, CEntity::pEventHandler(&CPlayer::H0x0191003f_TravellingInBeam_02), DEBUGSTRING("CPlayer::H0x0191003f_TravellingInBeam_02")}, + {0x01910040, -1, CEntity::pEventHandler(&CPlayer:: +#line 6214 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +LogoFireMinigun),DEBUGSTRING("CPlayer::LogoFireMinigun")}, + {0x01910041, -1, CEntity::pEventHandler(&CPlayer::H0x01910041_LogoFireMinigun_01), DEBUGSTRING("CPlayer::H0x01910041_LogoFireMinigun_01")}, + {0x01910042, -1, CEntity::pEventHandler(&CPlayer::H0x01910042_LogoFireMinigun_02), DEBUGSTRING("CPlayer::H0x01910042_LogoFireMinigun_02")}, + {0x01910043, -1, CEntity::pEventHandler(&CPlayer::H0x01910043_LogoFireMinigun_03), DEBUGSTRING("CPlayer::H0x01910043_LogoFireMinigun_03")}, + {0x01910044, -1, CEntity::pEventHandler(&CPlayer::H0x01910044_LogoFireMinigun_04), DEBUGSTRING("CPlayer::H0x01910044_LogoFireMinigun_04")}, + {0x01910045, -1, CEntity::pEventHandler(&CPlayer::H0x01910045_LogoFireMinigun_05), DEBUGSTRING("CPlayer::H0x01910045_LogoFireMinigun_05")}, + {0x01910046, -1, CEntity::pEventHandler(&CPlayer::H0x01910046_LogoFireMinigun_06), DEBUGSTRING("CPlayer::H0x01910046_LogoFireMinigun_06")}, + {0x01910047, -1, CEntity::pEventHandler(&CPlayer::H0x01910047_LogoFireMinigun_07), DEBUGSTRING("CPlayer::H0x01910047_LogoFireMinigun_07")}, + {0x01910048, -1, CEntity::pEventHandler(&CPlayer::H0x01910048_LogoFireMinigun_08), DEBUGSTRING("CPlayer::H0x01910048_LogoFireMinigun_08")}, + {0x01910049, -1, CEntity::pEventHandler(&CPlayer:: +#line 6275 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +AutoStoreWeapon),DEBUGSTRING("CPlayer::AutoStoreWeapon")}, + {0x0191004a, -1, CEntity::pEventHandler(&CPlayer::H0x0191004a_AutoStoreWeapon_01), DEBUGSTRING("CPlayer::H0x0191004a_AutoStoreWeapon_01")}, + {0x0191004b, -1, CEntity::pEventHandler(&CPlayer::H0x0191004b_AutoStoreWeapon_02), DEBUGSTRING("CPlayer::H0x0191004b_AutoStoreWeapon_02")}, + {0x0191004c, -1, CEntity::pEventHandler(&CPlayer::H0x0191004c_AutoStoreWeapon_03), DEBUGSTRING("CPlayer::H0x0191004c_AutoStoreWeapon_03")}, + {0x0191004d, -1, CEntity::pEventHandler(&CPlayer::H0x0191004d_AutoStoreWeapon_04), DEBUGSTRING("CPlayer::H0x0191004d_AutoStoreWeapon_04")}, + {0x0191004e, -1, CEntity::pEventHandler(&CPlayer:: +#line 6309 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +DoAutoActions),DEBUGSTRING("CPlayer::DoAutoActions")}, + {0x0191004f, -1, CEntity::pEventHandler(&CPlayer::H0x0191004f_DoAutoActions_01), DEBUGSTRING("CPlayer::H0x0191004f_DoAutoActions_01")}, + {0x01910050, -1, CEntity::pEventHandler(&CPlayer::H0x01910050_DoAutoActions_02), DEBUGSTRING("CPlayer::H0x01910050_DoAutoActions_02")}, + {0x01910051, -1, CEntity::pEventHandler(&CPlayer::H0x01910051_DoAutoActions_03), DEBUGSTRING("CPlayer::H0x01910051_DoAutoActions_03")}, + {0x01910052, -1, CEntity::pEventHandler(&CPlayer::H0x01910052_DoAutoActions_04), DEBUGSTRING("CPlayer::H0x01910052_DoAutoActions_04")}, + {0x01910053, -1, CEntity::pEventHandler(&CPlayer::H0x01910053_DoAutoActions_05), DEBUGSTRING("CPlayer::H0x01910053_DoAutoActions_05")}, + {0x01910054, -1, CEntity::pEventHandler(&CPlayer::H0x01910054_DoAutoActions_06), DEBUGSTRING("CPlayer::H0x01910054_DoAutoActions_06")}, + {0x01910055, -1, CEntity::pEventHandler(&CPlayer::H0x01910055_DoAutoActions_07), DEBUGSTRING("CPlayer::H0x01910055_DoAutoActions_07")}, + {0x01910056, -1, CEntity::pEventHandler(&CPlayer::H0x01910056_DoAutoActions_08), DEBUGSTRING("CPlayer::H0x01910056_DoAutoActions_08")}, + {0x01910057, -1, CEntity::pEventHandler(&CPlayer::H0x01910057_DoAutoActions_09), DEBUGSTRING("CPlayer::H0x01910057_DoAutoActions_09")}, + {0x01910058, -1, CEntity::pEventHandler(&CPlayer::H0x01910058_DoAutoActions_10), DEBUGSTRING("CPlayer::H0x01910058_DoAutoActions_10")}, + {0x01910059, -1, CEntity::pEventHandler(&CPlayer::H0x01910059_DoAutoActions_11), DEBUGSTRING("CPlayer::H0x01910059_DoAutoActions_11")}, + {0x0191005a, -1, CEntity::pEventHandler(&CPlayer::H0x0191005a_DoAutoActions_12), DEBUGSTRING("CPlayer::H0x0191005a_DoAutoActions_12")}, + {0x0191005b, -1, CEntity::pEventHandler(&CPlayer::H0x0191005b_DoAutoActions_13), DEBUGSTRING("CPlayer::H0x0191005b_DoAutoActions_13")}, + {0x0191005c, -1, CEntity::pEventHandler(&CPlayer::H0x0191005c_DoAutoActions_14), DEBUGSTRING("CPlayer::H0x0191005c_DoAutoActions_14")}, + {0x0191005d, -1, CEntity::pEventHandler(&CPlayer::H0x0191005d_DoAutoActions_15), DEBUGSTRING("CPlayer::H0x0191005d_DoAutoActions_15")}, + {0x0191005e, -1, CEntity::pEventHandler(&CPlayer::H0x0191005e_DoAutoActions_16), DEBUGSTRING("CPlayer::H0x0191005e_DoAutoActions_16")}, + {0x0191005f, -1, CEntity::pEventHandler(&CPlayer::H0x0191005f_DoAutoActions_17), DEBUGSTRING("CPlayer::H0x0191005f_DoAutoActions_17")}, + {0x01910060, -1, CEntity::pEventHandler(&CPlayer::H0x01910060_DoAutoActions_18), DEBUGSTRING("CPlayer::H0x01910060_DoAutoActions_18")}, + {0x01910061, -1, CEntity::pEventHandler(&CPlayer::H0x01910061_DoAutoActions_19), DEBUGSTRING("CPlayer::H0x01910061_DoAutoActions_19")}, + {0x01910062, -1, CEntity::pEventHandler(&CPlayer::H0x01910062_DoAutoActions_20), DEBUGSTRING("CPlayer::H0x01910062_DoAutoActions_20")}, + {0x01910063, -1, CEntity::pEventHandler(&CPlayer::H0x01910063_DoAutoActions_21), DEBUGSTRING("CPlayer::H0x01910063_DoAutoActions_21")}, + {0x01910064, -1, CEntity::pEventHandler(&CPlayer::H0x01910064_DoAutoActions_22), DEBUGSTRING("CPlayer::H0x01910064_DoAutoActions_22")}, + {0x01910065, -1, CEntity::pEventHandler(&CPlayer::H0x01910065_DoAutoActions_23), DEBUGSTRING("CPlayer::H0x01910065_DoAutoActions_23")}, + {0x01910066, -1, CEntity::pEventHandler(&CPlayer::H0x01910066_DoAutoActions_24), DEBUGSTRING("CPlayer::H0x01910066_DoAutoActions_24")}, + {0x01910067, -1, CEntity::pEventHandler(&CPlayer::H0x01910067_DoAutoActions_25), DEBUGSTRING("CPlayer::H0x01910067_DoAutoActions_25")}, + {0x01910068, -1, CEntity::pEventHandler(&CPlayer::H0x01910068_DoAutoActions_26), DEBUGSTRING("CPlayer::H0x01910068_DoAutoActions_26")}, + {0x01910069, -1, CEntity::pEventHandler(&CPlayer::H0x01910069_DoAutoActions_27), DEBUGSTRING("CPlayer::H0x01910069_DoAutoActions_27")}, + {0x0191006a, -1, CEntity::pEventHandler(&CPlayer::H0x0191006a_DoAutoActions_28), DEBUGSTRING("CPlayer::H0x0191006a_DoAutoActions_28")}, + {0x0191006b, -1, CEntity::pEventHandler(&CPlayer::H0x0191006b_DoAutoActions_29), DEBUGSTRING("CPlayer::H0x0191006b_DoAutoActions_29")}, + {0x0191006c, -1, CEntity::pEventHandler(&CPlayer::H0x0191006c_DoAutoActions_30), DEBUGSTRING("CPlayer::H0x0191006c_DoAutoActions_30")}, + {0x0191006d, -1, CEntity::pEventHandler(&CPlayer::H0x0191006d_DoAutoActions_31), DEBUGSTRING("CPlayer::H0x0191006d_DoAutoActions_31")}, + {0x0191006e, -1, CEntity::pEventHandler(&CPlayer::H0x0191006e_DoAutoActions_32), DEBUGSTRING("CPlayer::H0x0191006e_DoAutoActions_32")}, + {0x0191006f, -1, CEntity::pEventHandler(&CPlayer::H0x0191006f_DoAutoActions_33), DEBUGSTRING("CPlayer::H0x0191006f_DoAutoActions_33")}, + {0x01910070, -1, CEntity::pEventHandler(&CPlayer::H0x01910070_DoAutoActions_34), DEBUGSTRING("CPlayer::H0x01910070_DoAutoActions_34")}, + {0x01910071, -1, CEntity::pEventHandler(&CPlayer::H0x01910071_DoAutoActions_35), DEBUGSTRING("CPlayer::H0x01910071_DoAutoActions_35")}, + {0x01910072, -1, CEntity::pEventHandler(&CPlayer::H0x01910072_DoAutoActions_36), DEBUGSTRING("CPlayer::H0x01910072_DoAutoActions_36")}, + {0x01910073, -1, CEntity::pEventHandler(&CPlayer::H0x01910073_DoAutoActions_37), DEBUGSTRING("CPlayer::H0x01910073_DoAutoActions_37")}, + {0x01910074, -1, CEntity::pEventHandler(&CPlayer::H0x01910074_DoAutoActions_38), DEBUGSTRING("CPlayer::H0x01910074_DoAutoActions_38")}, + {0x01910075, -1, CEntity::pEventHandler(&CPlayer::H0x01910075_DoAutoActions_39), DEBUGSTRING("CPlayer::H0x01910075_DoAutoActions_39")}, + {0x01910076, -1, CEntity::pEventHandler(&CPlayer::H0x01910076_DoAutoActions_40), DEBUGSTRING("CPlayer::H0x01910076_DoAutoActions_40")}, + {0x01910077, -1, CEntity::pEventHandler(&CPlayer::H0x01910077_DoAutoActions_41), DEBUGSTRING("CPlayer::H0x01910077_DoAutoActions_41")}, + {0x01910078, -1, CEntity::pEventHandler(&CPlayer::H0x01910078_DoAutoActions_42), DEBUGSTRING("CPlayer::H0x01910078_DoAutoActions_42")}, + {0x01910079, -1, CEntity::pEventHandler(&CPlayer::H0x01910079_DoAutoActions_43), DEBUGSTRING("CPlayer::H0x01910079_DoAutoActions_43")}, + {0x0191007a, -1, CEntity::pEventHandler(&CPlayer::H0x0191007a_DoAutoActions_44), DEBUGSTRING("CPlayer::H0x0191007a_DoAutoActions_44")}, + {0x0191007b, -1, CEntity::pEventHandler(&CPlayer::H0x0191007b_DoAutoActions_45), DEBUGSTRING("CPlayer::H0x0191007b_DoAutoActions_45")}, + {0x0191007c, -1, CEntity::pEventHandler(&CPlayer::H0x0191007c_DoAutoActions_46), DEBUGSTRING("CPlayer::H0x0191007c_DoAutoActions_46")}, + {0x0191007d, -1, CEntity::pEventHandler(&CPlayer::H0x0191007d_DoAutoActions_47), DEBUGSTRING("CPlayer::H0x0191007d_DoAutoActions_47")}, + {0x0191007e, -1, CEntity::pEventHandler(&CPlayer::H0x0191007e_DoAutoActions_48), DEBUGSTRING("CPlayer::H0x0191007e_DoAutoActions_48")}, + {0x0191007f, -1, CEntity::pEventHandler(&CPlayer::H0x0191007f_DoAutoActions_49), DEBUGSTRING("CPlayer::H0x0191007f_DoAutoActions_49")}, + {0x01910080, -1, CEntity::pEventHandler(&CPlayer::H0x01910080_DoAutoActions_50), DEBUGSTRING("CPlayer::H0x01910080_DoAutoActions_50")}, + {0x01910081, -1, CEntity::pEventHandler(&CPlayer::H0x01910081_DoAutoActions_51), DEBUGSTRING("CPlayer::H0x01910081_DoAutoActions_51")}, + {0x01910082, -1, CEntity::pEventHandler(&CPlayer::H0x01910082_DoAutoActions_52), DEBUGSTRING("CPlayer::H0x01910082_DoAutoActions_52")}, + {0x01910083, -1, CEntity::pEventHandler(&CPlayer::H0x01910083_DoAutoActions_53), DEBUGSTRING("CPlayer::H0x01910083_DoAutoActions_53")}, + {0x01910084, -1, CEntity::pEventHandler(&CPlayer::H0x01910084_DoAutoActions_54), DEBUGSTRING("CPlayer::H0x01910084_DoAutoActions_54")}, + {0x01910085, -1, CEntity::pEventHandler(&CPlayer::H0x01910085_DoAutoActions_55), DEBUGSTRING("CPlayer::H0x01910085_DoAutoActions_55")}, + {0x01910086, -1, CEntity::pEventHandler(&CPlayer::H0x01910086_DoAutoActions_56), DEBUGSTRING("CPlayer::H0x01910086_DoAutoActions_56")}, + {0x01910087, -1, CEntity::pEventHandler(&CPlayer::H0x01910087_DoAutoActions_57), DEBUGSTRING("CPlayer::H0x01910087_DoAutoActions_57")}, + {0x01910088, -1, CEntity::pEventHandler(&CPlayer::H0x01910088_DoAutoActions_58), DEBUGSTRING("CPlayer::H0x01910088_DoAutoActions_58")}, + {0x01910089, -1, CEntity::pEventHandler(&CPlayer::H0x01910089_DoAutoActions_59), DEBUGSTRING("CPlayer::H0x01910089_DoAutoActions_59")}, + {0x0191008a, -1, CEntity::pEventHandler(&CPlayer::H0x0191008a_DoAutoActions_60), DEBUGSTRING("CPlayer::H0x0191008a_DoAutoActions_60")}, + {0x0191008b, -1, CEntity::pEventHandler(&CPlayer::H0x0191008b_DoAutoActions_61), DEBUGSTRING("CPlayer::H0x0191008b_DoAutoActions_61")}, + {0x0191008c, -1, CEntity::pEventHandler(&CPlayer::H0x0191008c_DoAutoActions_62), DEBUGSTRING("CPlayer::H0x0191008c_DoAutoActions_62")}, + {0x0191008d, -1, CEntity::pEventHandler(&CPlayer::H0x0191008d_DoAutoActions_63), DEBUGSTRING("CPlayer::H0x0191008d_DoAutoActions_63")}, + {0x0191008e, -1, CEntity::pEventHandler(&CPlayer::H0x0191008e_DoAutoActions_64), DEBUGSTRING("CPlayer::H0x0191008e_DoAutoActions_64")}, + {0x0191008f, -1, CEntity::pEventHandler(&CPlayer::H0x0191008f_DoAutoActions_65), DEBUGSTRING("CPlayer::H0x0191008f_DoAutoActions_65")}, + {0x01910090, -1, CEntity::pEventHandler(&CPlayer::H0x01910090_DoAutoActions_66), DEBUGSTRING("CPlayer::H0x01910090_DoAutoActions_66")}, + {0x01910091, -1, CEntity::pEventHandler(&CPlayer::H0x01910091_DoAutoActions_67), DEBUGSTRING("CPlayer::H0x01910091_DoAutoActions_67")}, + {0x01910092, -1, CEntity::pEventHandler(&CPlayer::H0x01910092_DoAutoActions_68), DEBUGSTRING("CPlayer::H0x01910092_DoAutoActions_68")}, + {0x01910093, -1, CEntity::pEventHandler(&CPlayer::H0x01910093_DoAutoActions_69), DEBUGSTRING("CPlayer::H0x01910093_DoAutoActions_69")}, + {0x01910094, -1, CEntity::pEventHandler(&CPlayer::H0x01910094_DoAutoActions_70), DEBUGSTRING("CPlayer::H0x01910094_DoAutoActions_70")}, + {0x01910095, -1, CEntity::pEventHandler(&CPlayer::H0x01910095_DoAutoActions_71), DEBUGSTRING("CPlayer::H0x01910095_DoAutoActions_71")}, + {0x01910096, -1, CEntity::pEventHandler(&CPlayer::H0x01910096_DoAutoActions_72), DEBUGSTRING("CPlayer::H0x01910096_DoAutoActions_72")}, + {0x01910097, -1, CEntity::pEventHandler(&CPlayer::H0x01910097_DoAutoActions_73), DEBUGSTRING("CPlayer::H0x01910097_DoAutoActions_73")}, + {0x01910098, -1, CEntity::pEventHandler(&CPlayer::H0x01910098_DoAutoActions_74), DEBUGSTRING("CPlayer::H0x01910098_DoAutoActions_74")}, + {0x01910099, -1, CEntity::pEventHandler(&CPlayer::H0x01910099_DoAutoActions_75), DEBUGSTRING("CPlayer::H0x01910099_DoAutoActions_75")}, + {0x0191009a, -1, CEntity::pEventHandler(&CPlayer::H0x0191009a_DoAutoActions_76), DEBUGSTRING("CPlayer::H0x0191009a_DoAutoActions_76")}, + {0x0191009b, -1, CEntity::pEventHandler(&CPlayer::H0x0191009b_DoAutoActions_77), DEBUGSTRING("CPlayer::H0x0191009b_DoAutoActions_77")}, + {0x0191009c, -1, CEntity::pEventHandler(&CPlayer::H0x0191009c_DoAutoActions_78), DEBUGSTRING("CPlayer::H0x0191009c_DoAutoActions_78")}, + {0x0191009d, -1, CEntity::pEventHandler(&CPlayer::H0x0191009d_DoAutoActions_79), DEBUGSTRING("CPlayer::H0x0191009d_DoAutoActions_79")}, + {0x0191009e, -1, CEntity::pEventHandler(&CPlayer::H0x0191009e_DoAutoActions_80), DEBUGSTRING("CPlayer::H0x0191009e_DoAutoActions_80")}, + {0x0191009f, -1, CEntity::pEventHandler(&CPlayer::H0x0191009f_DoAutoActions_81), DEBUGSTRING("CPlayer::H0x0191009f_DoAutoActions_81")}, + {0x019100a0, -1, CEntity::pEventHandler(&CPlayer::H0x019100a0_DoAutoActions_82), DEBUGSTRING("CPlayer::H0x019100a0_DoAutoActions_82")}, + {0x019100a1, -1, CEntity::pEventHandler(&CPlayer::H0x019100a1_DoAutoActions_83), DEBUGSTRING("CPlayer::H0x019100a1_DoAutoActions_83")}, + {0x019100a2, -1, CEntity::pEventHandler(&CPlayer::H0x019100a2_DoAutoActions_84), DEBUGSTRING("CPlayer::H0x019100a2_DoAutoActions_84")}, + {0x019100a3, -1, CEntity::pEventHandler(&CPlayer::H0x019100a3_DoAutoActions_85), DEBUGSTRING("CPlayer::H0x019100a3_DoAutoActions_85")}, + {1, -1, CEntity::pEventHandler(&CPlayer:: +#line 6520 "D:/SE1_GPL/Sources/EntitiesMP/Player.es" +Main),DEBUGSTRING("CPlayer::Main")}, + {0x019100a4, -1, CEntity::pEventHandler(&CPlayer::H0x019100a4_Main_01), DEBUGSTRING("CPlayer::H0x019100a4_Main_01")}, + {0x019100a5, -1, CEntity::pEventHandler(&CPlayer::H0x019100a5_Main_02), DEBUGSTRING("CPlayer::H0x019100a5_Main_02")}, + {0x019100a6, -1, CEntity::pEventHandler(&CPlayer::H0x019100a6_Main_03), DEBUGSTRING("CPlayer::H0x019100a6_Main_03")}, + {0x019100a7, -1, CEntity::pEventHandler(&CPlayer::H0x019100a7_Main_04), DEBUGSTRING("CPlayer::H0x019100a7_Main_04")}, +}; +#define CPlayer_handlersct ARRAYCOUNT(CPlayer_handlers) + +CEntity *CPlayer_New(void) { return new CPlayer; }; +void CPlayer_OnInitClass(void); +void CPlayer_OnEndClass(void); +void CPlayer_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPlayer_OnWorldEnd(CWorld *pwo) {}; +void CPlayer_OnWorldInit(CWorld *pwo) {}; +void CPlayer_OnWorldTick(CWorld *pwo) {}; +void CPlayer_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPlayer, CPlayerEntity, "Player", "", 0x00000191); +DECLARE_CTFILENAME(_fnmCPlayer_tbn, ""); diff --git a/Sources/EntitiesMP/PowerUpItem.cpp b/Sources/EntitiesMP/PowerUpItem.cpp new file mode 100644 index 0000000..28bae31 --- /dev/null +++ b/Sources/EntitiesMP/PowerUpItem.cpp @@ -0,0 +1,328 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" + +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" + +#include +#include +CEntityEvent *EPowerUp::MakeCopy(void) { CEntityEvent *peeCopy = new EPowerUp(*this); return peeCopy;} +EPowerUp::EPowerUp() : CEntityEvent(EVENTCODE_EPowerUp) {; + ClearToDefault(puitType); +}; +void CPowerUpItem::SetDefaultProperties(void) { + m_puitType = PUIT_INVULNER ; + CItem::SetDefaultProperties(); +} + +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +void CPowerUpItem::Precache(void) +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +{ +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +switch(m_puitType ){ +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_INVISIB : +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_INVULNER : +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_DAMAGE : +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_SPEED : +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +PrecacheSound (SOUND_PICKUP );break ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_BOMB : PrecacheSound (SOUND_BOMB );break ; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +BOOL CPowerUpItem::FillEntityStatistics(EntityStats * pes) +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +{ +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +pes -> es_strName = "PowerUp"; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +pes -> es_ctCount = 1; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +pes -> es_ctAmmount = 1; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +pes -> es_fValue = 0; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +pes -> es_iScore = 0; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +switch(m_puitType ){ +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_INVISIB : pes -> es_strName += " invisibility";break ; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_INVULNER : pes -> es_strName += " invulnerability";break ; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_DAMAGE : pes -> es_strName += " serious damage";break ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_SPEED : pes -> es_strName += " serious speed";break ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_BOMB : pes -> es_strName = "Serious Bomb!"; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +return TRUE ; +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} + +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +void CPowerUpItem::RenderParticles(void) +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +{ +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +if(GetRenderType () != CEntity :: RT_MODEL || GetSP () -> sp_gmGameMode > CSessionProperties :: GM_COOPERATIVE +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +|| ! ShowItemParticles ()){ +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +return ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +switch(m_puitType ){ +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_INVISIB : +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Particles_Stardust (this , 2.0f * 0.75f , 1.00f * 0.75f , PT_STAR08 , 320); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +break ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_INVULNER : +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Particles_Stardust (this , 2.0f * 0.75f , 1.00f * 0.75f , PT_STAR08 , 192); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +break ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_DAMAGE : +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Particles_Stardust (this , 1.0f * 0.75f , 0.75f * 0.75f , PT_STAR08 , 128); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +break ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_SPEED : +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Particles_Stardust (this , 1.0f * 0.75f , 0.75f * 0.75f , PT_STAR08 , 128); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +break ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_BOMB : +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Particles_Atomic (this , 2.0f * 0.75f , 2.0f * 0.95f , PT_STAR05 , 12); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +break ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} + +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +void CPowerUpItem::SetProperties(void) +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +{ +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +switch(m_puitType ) +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +{ +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_INVISIB : +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_BIG ); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 40.0f; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_strDescription . PrintF ("Invisibility"); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +AddItem (MODEL_INVISIB , TEXTURE_REFLECTION_METAL , 0 , TEXTURE_SPECULAR_STRONG , 0); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +StretchItem (FLOAT3D (1.0f * 0.75f , 1.0f * 0.75f , 1.0f * 0.75)); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +break ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_INVULNER : +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_BIG ); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 60.0f; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_strDescription . PrintF ("Invulnerability"); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +AddItem (MODEL_INVULNER , TEXTURE_REFLECTION_GOLD , TEXTURE_REFLECTION_METAL , TEXTURE_SPECULAR_MEDIUM , 0); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +StretchItem (FLOAT3D (1.0f * 0.75f , 1.0f * 0.75f , 1.0f * 0.75)); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +break ; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_DAMAGE : +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_BIG ); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 40.0f; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_strDescription . PrintF ("SeriousDamage"); +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +AddItem (MODEL_DAMAGE , TEXTURE_DAMAGE , 0 , TEXTURE_SPECULAR_STRONG , 0); +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +StretchItem (FLOAT3D (1.0f * 0.75f , 1.0f * 0.75f , 1.0f * 0.75)); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +break ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_SPEED : +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_BIG ); +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 40.0f; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_strDescription . PrintF ("SeriousSpeed"); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +AddItem (MODEL_SPEED , TEXTURE_SPEED , 0 , 0 , 0); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +StretchItem (FLOAT3D (1.0f * 0.75f , 1.0f * 0.75f , 1.0f * 0.75)); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +break ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_BOMB : +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +StartModelAnim (ITEMHOLDER_ANIM_SMALLOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_BIG ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 40.0f; +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_strDescription . PrintF ("Serious Bomb!"); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +AddItem (MODEL_BOMB , TEXTURE_BOMB , 0 , 0 , 0); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.2f , 0) , FLOAT3D (1 , 1 , 0.3f)); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +StretchItem (FLOAT3D (1.0f * 3.0f , 1.0f * 3.0f , 1.0f * 3.0)); +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +break ; +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +BOOL CPowerUpItem:: +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +ItemCollected(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPowerUpItem_ItemCollected + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EPass, "CPowerUpItem::ItemCollected expects 'EPass' as input!"); const EPass &epass = (const EPass &)__eeInput; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +ASSERT (epass . penOther != NULL ); +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +if(m_puitType == PUIT_BOMB ){ +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +if(IsOfClass (epass . penOther , "Player")){ +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +if(((CPlayer &) * epass . penOther ) . m_iSeriousBombCount >= 3){ +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Return(STATE_CURRENT,EVoid()); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +return TRUE; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +if(! (m_bPickupOnce || m_bRespawn )){ +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +BOOL bWasPicked = MarkPickedBy (epass . penOther ); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +if(bWasPicked ){ +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Return(STATE_CURRENT,EVoid()); +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +return TRUE; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +EPowerUp ePowerUp ; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +ePowerUp . puitType = m_puitType ; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +if(epass . penOther -> ReceiveItem (ePowerUp )){ +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +if(_pNetwork -> IsPlayerLocal (epass . penOther )) +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +{ +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +switch(m_puitType ) +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +{ +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_INVISIB : IFeel_PlayEffect ("PU_Invulnerability");break ; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_INVULNER : IFeel_PlayEffect ("PU_Invulnerability");break ; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_DAMAGE : IFeel_PlayEffect ("PU_Invulnerability");break ; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_SPEED : IFeel_PlayEffect ("PU_FastShoes");break ; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +case PUIT_BOMB : IFeel_PlayEffect ("PU_SeriousBomb");break ; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_soPick . Set3DParameters (50.0f , 1.0f , 2.0f , 1.0f); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +if(m_puitType == PUIT_BOMB ){ +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +PlaySound (m_soPick , SOUND_BOMB , SOF_3D ); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_fPickSoundLen = GetSoundLength (SOUND_BOMB ); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +}else if(TRUE ){ +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +PlaySound (m_soPick , SOUND_PICKUP , SOF_3D ); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +m_fPickSoundLen = GetSoundLength (SOUND_PICKUP ); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +if((m_bPickupOnce || m_bRespawn )){Jump(STATE_CURRENT, STATE_CItem_ItemReceived, FALSE, EVoid());return TRUE;} +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +} +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Return(STATE_CURRENT,EVoid()); +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPowerUpItem:: +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPowerUpItem_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPowerUpItem::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Initialize (); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +SetProperties (); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/PowerUpItem.es b/Sources/EntitiesMP/PowerUpItem.es new file mode 100644 index 0000000..54595cd --- /dev/null +++ b/Sources/EntitiesMP/PowerUpItem.es @@ -0,0 +1,252 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +808 +%{ +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" +%} + +uses "EntitiesMP/Item"; +uses "EntitiesMP/Player"; + +// health type +enum PowerUpItemType { + 0 PUIT_INVISIB "Invisibility", + 1 PUIT_INVULNER "Invulnerability", + 2 PUIT_DAMAGE "SeriousDamage", + 3 PUIT_SPEED "SeriousSpeed", + 4 PUIT_BOMB "SeriousBomb", +}; + +// event for sending through receive item +event EPowerUp { + enum PowerUpItemType puitType, +}; + +class CPowerUpItem : CItem +{ +name "PowerUp Item"; +thumbnail "Thumbnails\\PowerUpItem.tbn"; + +properties: + 1 enum PowerUpItemType m_puitType "Type" 'Y' = PUIT_INVULNER, +// 3 INDEX m_iSoundComponent = 0, + +components: + 0 class CLASS_BASE "Classes\\Item.ecl", + +// ********* INVISIBILITY ********* + 1 model MODEL_INVISIB "ModelsMP\\Items\\PowerUps\\Invisibility\\Invisibility.mdl", +// 2 texture TEXTURE_INVISIB "ModelsMP\\Items\\PowerUps\\Invisibility\\Invisibility.tex", + +// ********* INVULNERABILITY ********* + 10 model MODEL_INVULNER "ModelsMP\\Items\\PowerUps\\Invulnerability\\Invulnerability.mdl", +// 11 texture TEXTURE_INVULNER "ModelsMP\\Items\\PowerUps\\Invulnerability\\Invulnerability.tex", + +// ********* SERIOUS DAMAGE ********* + 20 model MODEL_DAMAGE "ModelsMP\\Items\\PowerUps\\SeriousDamage\\SeriousDamage.mdl", + 21 texture TEXTURE_DAMAGE "ModelsMP\\Items\\PowerUps\\SeriousDamage\\SeriousDamage.tex", + +// ********* SERIOUS SPEED ********* + 30 model MODEL_SPEED "ModelsMP\\Items\\PowerUps\\SeriousSpeed\\SeriousSpeed.mdl", + 31 texture TEXTURE_SPEED "ModelsMP\\Items\\PowerUps\\SeriousSpeed\\SeriousSpeed.tex", + +// ********* SERIOUS BOMB ********* + 40 model MODEL_BOMB "ModelsMP\\Items\\PowerUps\\SeriousBomb\\SeriousBomb.mdl", + 41 texture TEXTURE_BOMB "ModelsMP\\Items\\PowerUps\\SeriousBomb\\SeriousBomb.tex", + + // ********* MISC ********* + 50 texture TEXTURE_SPECULAR_STRONG "ModelsMP\\SpecularTextures\\Strong.tex", + 51 texture TEXTURE_SPECULAR_MEDIUM "ModelsMP\\SpecularTextures\\Medium.tex", + 52 texture TEXTURE_REFLECTION_METAL "ModelsMP\\ReflectionTextures\\LightMetal01.tex", + 53 texture TEXTURE_REFLECTION_GOLD "ModelsMP\\ReflectionTextures\\Gold01.tex", + 54 texture TEXTURE_REFLECTION_PUPLE "ModelsMP\\ReflectionTextures\\Purple01.tex", + 55 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex", + 56 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl", + +// ************** SOUNDS ************** +//301 sound SOUND_INVISIB "SoundsMP\\Items\\Invisibility.wav", +//302 sound SOUND_INVULNER "SoundsMP\\Items\\Invulnerability.wav", +//303 sound SOUND_DAMAGE "SoundsMP\\Items\\SeriousDamage.wav", +//304 sound SOUND_SPEED "SoundsMP\\Items\\SeriousSpeed.wav", +301 sound SOUND_PICKUP "SoundsMP\\Items\\PowerUp.wav", +305 sound SOUND_BOMB "SoundsMP\\Items\\SeriousBomb.wav", + +functions: + + void Precache(void) + { + switch( m_puitType) { + case PUIT_INVISIB : /*PrecacheSound(SOUND_INVISIB ); break;*/ + case PUIT_INVULNER: /*PrecacheSound(SOUND_INVULNER); break; */ + case PUIT_DAMAGE : /*PrecacheSound(SOUND_DAMAGE ); break;*/ + case PUIT_SPEED : /*PrecacheSound(SOUND_SPEED ); break;*/ + PrecacheSound(SOUND_PICKUP ); break; + case PUIT_BOMB : PrecacheSound(SOUND_BOMB ); break; + } + } + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + pes->es_strName = "PowerUp"; + pes->es_ctCount = 1; + pes->es_ctAmmount = 1; // !!!! + pes->es_fValue = 0; // !!!! + pes->es_iScore = 0;//m_iScore; + + switch( m_puitType) { + case PUIT_INVISIB : pes->es_strName += " invisibility"; break; + case PUIT_INVULNER: pes->es_strName += " invulnerability"; break; + case PUIT_DAMAGE : pes->es_strName += " serious damage"; break; + case PUIT_SPEED : pes->es_strName += " serious speed"; break; + case PUIT_BOMB : pes->es_strName = "Serious Bomb!"; + } + return TRUE; + } + + // render particles + void RenderParticles(void) + { + // no particles when not existing or in DM modes + if( GetRenderType()!=CEntity::RT_MODEL || GetSP()->sp_gmGameMode>CSessionProperties::GM_COOPERATIVE + || !ShowItemParticles()) { + return; + } + switch( m_puitType) { + case PUIT_INVISIB: + Particles_Stardust( this, 2.0f*0.75f, 1.00f*0.75f, PT_STAR08, 320); + break; + case PUIT_INVULNER: + Particles_Stardust( this, 2.0f*0.75f, 1.00f*0.75f, PT_STAR08, 192); + break; + case PUIT_DAMAGE: + Particles_Stardust( this, 1.0f*0.75f, 0.75f*0.75f, PT_STAR08, 128); + break; + case PUIT_SPEED: + Particles_Stardust( this, 1.0f*0.75f, 0.75f*0.75f, PT_STAR08, 128); + break; + case PUIT_BOMB: + Particles_Atomic(this, 2.0f*0.75f, 2.0f*0.95f, PT_STAR05, 12); + break; + } + } + + // set health properties depending on health type + void SetProperties(void) + { + switch( m_puitType) + { + case PUIT_INVISIB: + StartModelAnim( ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange( ITEMHOLDER_COLLISION_BOX_BIG); + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 40.0f; + m_strDescription.PrintF("Invisibility"); + AddItem( MODEL_INVISIB, TEXTURE_REFLECTION_METAL, 0, TEXTURE_SPECULAR_STRONG, 0); // set appearance + AddFlare( MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); // add flare + StretchItem( FLOAT3D(1.0f*0.75f, 1.0f*0.75f, 1.0f*0.75)); + break; + case PUIT_INVULNER: + StartModelAnim( ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange( ITEMHOLDER_COLLISION_BOX_BIG); + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 60.0f; + m_strDescription.PrintF("Invulnerability"); + AddItem( MODEL_INVULNER, TEXTURE_REFLECTION_GOLD, TEXTURE_REFLECTION_METAL, TEXTURE_SPECULAR_MEDIUM, 0); // set appearance + AddFlare( MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); // add flare + StretchItem( FLOAT3D(1.0f*0.75f, 1.0f*0.75f, 1.0f*0.75)); + break; + case PUIT_DAMAGE: + StartModelAnim( ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange( ITEMHOLDER_COLLISION_BOX_BIG); + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 40.0f; + m_strDescription.PrintF("SeriousDamage"); + AddItem( MODEL_DAMAGE, TEXTURE_DAMAGE, 0, TEXTURE_SPECULAR_STRONG, 0); // set appearance + AddFlare( MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); // add flare + StretchItem( FLOAT3D(1.0f*0.75f, 1.0f*0.75f, 1.0f*0.75)); + break; + case PUIT_SPEED: + StartModelAnim( ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange( ITEMHOLDER_COLLISION_BOX_BIG); + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 40.0f; + m_strDescription.PrintF("SeriousSpeed"); + AddItem( MODEL_SPEED, TEXTURE_SPEED, 0, 0, 0); // set appearance + AddFlare( MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); // add flare + StretchItem( FLOAT3D(1.0f*0.75f, 1.0f*0.75f, 1.0f*0.75)); + break; + case PUIT_BOMB: + StartModelAnim( ITEMHOLDER_ANIM_SMALLOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange( ITEMHOLDER_COLLISION_BOX_BIG); + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 40.0f; + m_strDescription.PrintF("Serious Bomb!"); + AddItem( MODEL_BOMB, TEXTURE_BOMB, 0, 0, 0); // set appearance + AddFlare( MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.2f,0), FLOAT3D(1,1,0.3f) ); // add flare + StretchItem( FLOAT3D(1.0f*3.0f, 1.0f*3.0f, 1.0f*3.0)); + break; + } + }; + + +procedures: + + ItemCollected( EPass epass) : CItem::ItemCollected + { + ASSERT( epass.penOther!=NULL); + + // don't pick up more bombs then you can carry + if (m_puitType == PUIT_BOMB) { + if (IsOfClass(epass.penOther, "Player")) { + if (((CPlayer &)*epass.penOther).m_iSeriousBombCount>=3) { + return; + } + } + } + + if( !(m_bPickupOnce||m_bRespawn)) { + // if already picked by this player + BOOL bWasPicked = MarkPickedBy(epass.penOther); + if( bWasPicked) { + // don't pick again + return; + } + } + + // send powerup to entity + EPowerUp ePowerUp; + ePowerUp.puitType = m_puitType; + // if powerup is received + if( epass.penOther->ReceiveItem(ePowerUp)) { + + if(_pNetwork->IsPlayerLocal(epass.penOther)) + { + switch (m_puitType) + { + case PUIT_INVISIB: IFeel_PlayEffect("PU_Invulnerability"); break; + case PUIT_INVULNER: IFeel_PlayEffect("PU_Invulnerability"); break; + case PUIT_DAMAGE: IFeel_PlayEffect("PU_Invulnerability"); break; + case PUIT_SPEED: IFeel_PlayEffect("PU_FastShoes"); break; + case PUIT_BOMB: IFeel_PlayEffect("PU_SeriousBomb"); break; + } + } + + // play the pickup sound + m_soPick.Set3DParameters( 50.0f, 1.0f, 2.0f, 1.0f); + if (m_puitType == PUIT_BOMB) { + PlaySound(m_soPick, SOUND_BOMB, SOF_3D); + m_fPickSoundLen = GetSoundLength(SOUND_BOMB); + } else if (TRUE) { + PlaySound(m_soPick, SOUND_PICKUP, SOF_3D); + m_fPickSoundLen = GetSoundLength(SOUND_PICKUP); + } + if( (m_bPickupOnce||m_bRespawn)) { jump CItem::ItemReceived(); } + } + return; + }; + + + Main() + { + Initialize(); // initialize base class + SetProperties(); // set properties + jump CItem::ItemLoop(); + }; +}; diff --git a/Sources/EntitiesMP/PowerUpItem.h b/Sources/EntitiesMP/PowerUpItem.h new file mode 100644 index 0000000..3983fc0 --- /dev/null +++ b/Sources/EntitiesMP/PowerUpItem.h @@ -0,0 +1,52 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_PowerUpItem_INCLUDED +#define _EntitiesMP_PowerUpItem_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType PowerUpItemType_enum; +enum PowerUpItemType { + PUIT_INVISIB = 0, + PUIT_INVULNER = 1, + PUIT_DAMAGE = 2, + PUIT_SPEED = 3, + PUIT_BOMB = 4, +}; +DECL_DLL inline void ClearToDefault(PowerUpItemType &e) { e = (PowerUpItemType)0; } ; +#define EVENTCODE_EPowerUp 0x03280000 +class DECL_DLL EPowerUp : public CEntityEvent { +public: +EPowerUp(); +CEntityEvent *MakeCopy(void); +enum PowerUpItemType puitType; +}; +DECL_DLL inline void ClearToDefault(EPowerUp &e) { e = EPowerUp(); } ; +extern "C" DECL_DLL CDLLEntityClass CPowerUpItem_DLLClass; +class CPowerUpItem : public CItem { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum PowerUpItemType m_puitType; + +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +void Precache(void); + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +void RenderParticles(void); + +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +void SetProperties(void); +#define STATE_CPowerUpItem_ItemCollected 0x03280001 + BOOL +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +ItemCollected(const CEntityEvent &__eeInput); +#define STATE_CPowerUpItem_Main 1 + BOOL +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_PowerUpItem_INCLUDED diff --git a/Sources/EntitiesMP/PowerUpItem_tables.h b/Sources/EntitiesMP/PowerUpItem_tables.h new file mode 100644 index 0000000..1d9e74d --- /dev/null +++ b/Sources/EntitiesMP/PowerUpItem_tables.h @@ -0,0 +1,79 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(PowerUpItemType) + EP_ENUMVALUE(PUIT_INVISIB, "Invisibility"), + EP_ENUMVALUE(PUIT_INVULNER, "Invulnerability"), + EP_ENUMVALUE(PUIT_DAMAGE, "SeriousDamage"), + EP_ENUMVALUE(PUIT_SPEED, "SeriousSpeed"), + EP_ENUMVALUE(PUIT_BOMB, "SeriousBomb"), +EP_ENUMEND(PowerUpItemType); + +#define ENTITYCLASS CPowerUpItem + +CEntityProperty CPowerUpItem_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &PowerUpItemType_enum, (0x00000328<<8)+1, offsetof(CPowerUpItem, m_puitType), "Type", 'Y', 0x7F0000FFUL, 0), +}; +#define CPowerUpItem_propertiesct ARRAYCOUNT(CPowerUpItem_properties) + +CEntityComponent CPowerUpItem_components[] = { +#define CLASS_BASE ((0x00000328<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\Item.ecl"), +#define MODEL_INVISIB ((0x00000328<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_INVISIB, "EFNM" "ModelsMP\\Items\\PowerUps\\Invisibility\\Invisibility.mdl"), +#define MODEL_INVULNER ((0x00000328<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_INVULNER, "EFNM" "ModelsMP\\Items\\PowerUps\\Invulnerability\\Invulnerability.mdl"), +#define MODEL_DAMAGE ((0x00000328<<8)+20) + CEntityComponent(ECT_MODEL, MODEL_DAMAGE, "EFNM" "ModelsMP\\Items\\PowerUps\\SeriousDamage\\SeriousDamage.mdl"), +#define TEXTURE_DAMAGE ((0x00000328<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_DAMAGE, "EFNM" "ModelsMP\\Items\\PowerUps\\SeriousDamage\\SeriousDamage.tex"), +#define MODEL_SPEED ((0x00000328<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_SPEED, "EFNM" "ModelsMP\\Items\\PowerUps\\SeriousSpeed\\SeriousSpeed.mdl"), +#define TEXTURE_SPEED ((0x00000328<<8)+31) + CEntityComponent(ECT_TEXTURE, TEXTURE_SPEED, "EFNM" "ModelsMP\\Items\\PowerUps\\SeriousSpeed\\SeriousSpeed.tex"), +#define MODEL_BOMB ((0x00000328<<8)+40) + CEntityComponent(ECT_MODEL, MODEL_BOMB, "EFNM" "ModelsMP\\Items\\PowerUps\\SeriousBomb\\SeriousBomb.mdl"), +#define TEXTURE_BOMB ((0x00000328<<8)+41) + CEntityComponent(ECT_TEXTURE, TEXTURE_BOMB, "EFNM" "ModelsMP\\Items\\PowerUps\\SeriousBomb\\SeriousBomb.tex"), +#define TEXTURE_SPECULAR_STRONG ((0x00000328<<8)+50) + CEntityComponent(ECT_TEXTURE, TEXTURE_SPECULAR_STRONG, "EFNM" "ModelsMP\\SpecularTextures\\Strong.tex"), +#define TEXTURE_SPECULAR_MEDIUM ((0x00000328<<8)+51) + CEntityComponent(ECT_TEXTURE, TEXTURE_SPECULAR_MEDIUM, "EFNM" "ModelsMP\\SpecularTextures\\Medium.tex"), +#define TEXTURE_REFLECTION_METAL ((0x00000328<<8)+52) + CEntityComponent(ECT_TEXTURE, TEXTURE_REFLECTION_METAL, "EFNM" "ModelsMP\\ReflectionTextures\\LightMetal01.tex"), +#define TEXTURE_REFLECTION_GOLD ((0x00000328<<8)+53) + CEntityComponent(ECT_TEXTURE, TEXTURE_REFLECTION_GOLD, "EFNM" "ModelsMP\\ReflectionTextures\\Gold01.tex"), +#define TEXTURE_REFLECTION_PUPLE ((0x00000328<<8)+54) + CEntityComponent(ECT_TEXTURE, TEXTURE_REFLECTION_PUPLE, "EFNM" "ModelsMP\\ReflectionTextures\\Purple01.tex"), +#define TEXTURE_FLARE ((0x00000328<<8)+55) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.tex"), +#define MODEL_FLARE ((0x00000328<<8)+56) + CEntityComponent(ECT_MODEL, MODEL_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.mdl"), +#define SOUND_PICKUP ((0x00000328<<8)+301) + CEntityComponent(ECT_SOUND, SOUND_PICKUP, "EFNM" "SoundsMP\\Items\\PowerUp.wav"), +#define SOUND_BOMB ((0x00000328<<8)+305) + CEntityComponent(ECT_SOUND, SOUND_BOMB, "EFNM" "SoundsMP\\Items\\SeriousBomb.wav"), +}; +#define CPowerUpItem_componentsct ARRAYCOUNT(CPowerUpItem_components) + +CEventHandlerEntry CPowerUpItem_handlers[] = { + {0x03280001, STATE_CItem_ItemCollected, CEntity::pEventHandler(&CPowerUpItem:: +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +ItemCollected),DEBUGSTRING("CPowerUpItem::ItemCollected")}, + {1, -1, CEntity::pEventHandler(&CPowerUpItem:: +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/PowerUpItem.es" +Main),DEBUGSTRING("CPowerUpItem::Main")}, +}; +#define CPowerUpItem_handlersct ARRAYCOUNT(CPowerUpItem_handlers) + +CEntity *CPowerUpItem_New(void) { return new CPowerUpItem; }; +void CPowerUpItem_OnInitClass(void) {}; +void CPowerUpItem_OnEndClass(void) {}; +void CPowerUpItem_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPowerUpItem_OnWorldEnd(CWorld *pwo) {}; +void CPowerUpItem_OnWorldInit(CWorld *pwo) {}; +void CPowerUpItem_OnWorldTick(CWorld *pwo) {}; +void CPowerUpItem_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPowerUpItem, CItem, "PowerUp Item", "Thumbnails\\PowerUpItem.tbn", 0x00000328); +DECLARE_CTFILENAME(_fnmCPowerUpItem_tbn, "Thumbnails\\PowerUpItem.tbn"); diff --git a/Sources/EntitiesMP/Projectile.cpp b/Sources/EntitiesMP/Projectile.cpp new file mode 100644 index 0000000..ec6c536 --- /dev/null +++ b/Sources/EntitiesMP/Projectile.cpp @@ -0,0 +1,5659 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" + +#include "StdH.h" +#include "Models/Weapons/Laser/Projectile/LaserProjectile.h" +#include "EntitiesMP/EnemyBase.h" +//#include "EntitiesMP/Dragonman.h" +#include "Models/Enemies/Elementals/Projectile/IcePyramid.h" +#include "Models/Enemies/ElementalLava/Projectile/LavaStone.h" +#include "Models/Enemies/ElementalLava/Projectile/LavaBomb.h" +#include "Models/Enemies/Headman/Projectile/Blade.h" +#include "Models/Enemies/Huanman/Projectile/Projectile.h" +#include "Models/Enemies/Cyborg/Projectile/LaserProjectile.h" + +#include "ModelsMP/Enemies/Grunt/Projectile/GruntProjectile.h" +#include "ModelsMP/Enemies/Guffy/Projectile/GuffyProjectile.h" + +#include "ModelsMP/Enemies/ExotechLarva/Weapons/PlasmaGun.h" + +#include "EntitiesMP/PlayerWeapons.h" +#include "EntitiesMP/Shooter.h" + +#define DEVIL_LASER_SPEED 100.0f +#define DEVIL_ROCKET_SPEED 60.0f + +#include +#include +CEntityEvent *ELaunchProjectile::MakeCopy(void) { CEntityEvent *peeCopy = new ELaunchProjectile(*this); return peeCopy;} +ELaunchProjectile::ELaunchProjectile() : CEntityEvent(EVENTCODE_ELaunchProjectile) {; + ClearToDefault(penLauncher); + ClearToDefault(prtType); + ClearToDefault(fSpeed); + ClearToDefault(fStretch); +}; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" + +#define DRAGONMAN_NORMAL 0 +#define DRAGONMAN_STRONG 1 + +#define ELEMENTAL_LARGE 2 +#define ELEMENTAL_BIG 1 +#define ELEMENTAL_NORMAL 0 + +#define ELEMENTAL_STONEMAN 0 +#define ELEMENTAL_LAVAMAN 1 +#define ELEMENTAL_ICEMAN 2 + +void CProjectile_OnInitClass(void) +{ +} + +void CProjectile_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + pdec->PrecacheTexture(TEX_REFL_BWRIPLES01); + pdec->PrecacheTexture(TEX_REFL_BWRIPLES02); + pdec->PrecacheTexture(TEX_REFL_LIGHTMETAL01); + pdec->PrecacheTexture(TEX_REFL_LIGHTBLUEMETAL01); + pdec->PrecacheTexture(TEX_REFL_DARKMETAL); + pdec->PrecacheTexture(TEX_REFL_PURPLE01); + + pdec->PrecacheTexture(TEX_SPEC_WEAK); + pdec->PrecacheTexture(TEX_SPEC_MEDIUM); + pdec->PrecacheTexture(TEX_SPEC_STRONG); + + switch ((ProjectileType)iUser) { + case PRT_ROCKET : + case PRT_WALKER_ROCKET : + case PRT_DEVIL_ROCKET : + pdec->PrecacheModel(MODEL_ROCKET ); + pdec->PrecacheTexture(TEXTURE_ROCKET); + pdec->PrecacheSound(SOUND_FLYING ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_ROCKET); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_ROCKET_PLANE); + break; + case PRT_GRENADE: + pdec->PrecacheModel(MODEL_GRENADE); + pdec->PrecacheTexture(TEXTURE_GRENADE); + pdec->PrecacheSound(SOUND_GRENADE_BOUNCE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE_PLANE); + break; + + case PRT_FLAME: + pdec->PrecacheModel(MODEL_FLAME); + pdec->PrecacheClass(CLASS_FLAME); + break; + + case PRT_LASER_RAY: + pdec->PrecacheModel(MODEL_LASER ); + pdec->PrecacheTexture(TEXTURE_GREEN_LASER ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LASERWAVE); + break; + + case PRT_GRUNT_PROJECTILE_SOL: + pdec->PrecacheModel(MODEL_GRUNT_PROJECTILE ); + pdec->PrecacheTexture(TEXTURE_GRUNT_PROJECTILE_01 ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LASERWAVE); + break; + + case PRT_GRUNT_PROJECTILE_COM: + pdec->PrecacheModel(MODEL_GRUNT_PROJECTILE ); + pdec->PrecacheTexture(TEXTURE_GRUNT_PROJECTILE_02 ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LASERWAVE); + break; + + case PRT_CATMAN_FIRE: + pdec->PrecacheModel(MODEL_CATMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_CATMAN_FIRE ); + break; + + case PRT_HEADMAN_FIRECRACKER: + pdec->PrecacheModel(MODEL_HEADMAN_FIRECRACKER ); + pdec->PrecacheTexture(TEXTURE_HEADMAN_FIRECRACKER ); + break; + case PRT_HEADMAN_ROCKETMAN: + pdec->PrecacheModel(MODEL_HEADMAN_BLADE ); + pdec->PrecacheTexture(TEXTURE_HEADMAN_BLADE ); + pdec->PrecacheModel(MODEL_HEADMAN_BLADE_FLAME ); + pdec->PrecacheTexture(TEXTURE_HEADMAN_BLADE_FLAME ); + break; + case PRT_HEADMAN_BOMBERMAN: + pdec->PrecacheModel(MODEL_HEADMAN_BOMB ); + pdec->PrecacheTexture(TEXTURE_HEADMAN_BOMB ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BOMB); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE_PLANE); + break; + + case PRT_BONEMAN_FIRE: + pdec->PrecacheModel(MODEL_BONEMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_BONEMAN_FIRE ); + break; + + case PRT_WOMAN_FIRE: + pdec->PrecacheModel(MODEL_WOMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_WOMAN_FIRE ); + break; + + case PRT_DRAGONMAN_FIRE: + case PRT_DRAGONMAN_STRONG_FIRE: + pdec->PrecacheModel(MODEL_DRAGONMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_DRAGONMAN_FIRE1 ); + pdec->PrecacheTexture(TEXTURE_DRAGONMAN_FIRE2 ); + break; + + case PRT_STONEMAN_FIRE: + case PRT_STONEMAN_BIG_FIRE: + case PRT_STONEMAN_LARGE_FIRE: + pdec->PrecacheModel(MODEL_ELEM_STONE ); + pdec->PrecacheTexture(TEXTURE_ELEM_STONE ); + break; + case PRT_LAVAMAN_BIG_BOMB: + case PRT_LAVAMAN_BOMB: + case PRT_LAVAMAN_STONE: + pdec->PrecacheModel(MODEL_ELEM_LAVA_STONE); + pdec->PrecacheModel(MODEL_ELEM_LAVA_STONE_FLARE); + pdec->PrecacheModel(MODEL_ELEM_LAVA_BOMB); + pdec->PrecacheModel(MODEL_ELEM_LAVA_BOMB_FLARE); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_STONE); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_STONE_FLARE ); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_BOMB); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_BOMB_FLARE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + pdec->PrecacheClass(CLASS_BLOOD_SPRAY); + break; + case PRT_METEOR: + pdec->PrecacheSound(SOUND_FLYING ); + pdec->PrecacheSound(SOUND_METEOR_BLAST ); + pdec->PrecacheModel(MODEL_ELEM_LAVA_BOMB); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_BOMB); + pdec->PrecacheClass(CLASS_BLOOD_SPRAY); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON); + + break; + + case PRT_ICEMAN_FIRE: + case PRT_ICEMAN_BIG_FIRE: + case PRT_ICEMAN_LARGE_FIRE: + pdec->PrecacheModel(MODEL_ELEM_ICE ); + pdec->PrecacheModel(MODEL_ELEM_ICE_FLARE ); + pdec->PrecacheTexture(TEXTURE_ELEM_ICE ); + //pdec->PrecacheTexture(TEXTURE_ELEM_ICE_FLARE); + break; + + case PRT_HUANMAN_FIRE: + pdec->PrecacheModel(MODEL_HUANMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_HUANMAN_FIRE ); + pdec->PrecacheModel(MODEL_HUANMAN_FLARE ); + pdec->PrecacheTexture(TEXTURE_HUANMAN_FLARE ); + break; + + case PRT_FISHMAN_FIRE: + pdec->PrecacheModel(MODEL_FISHMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_FISHMAN_FIRE ); + break; + + case PRT_MANTAMAN_FIRE: + pdec->PrecacheModel(MODEL_MANTAMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_MANTAMAN_FIRE ); + break; + + case PRT_DEVIL_LASER: + /* + pdec->PrecacheModel(MODEL_DEVIL_LASER ); + pdec->PrecacheTexture(TEXTURE_DEVIL_LASER ); + break; + */ + + case PRT_CYBORG_LASER: + case PRT_CYBORG_BOMB: + pdec->PrecacheModel(MODEL_CYBORG_LASER ); + pdec->PrecacheTexture(TEXTURE_CYBORG_LASER ); + pdec->PrecacheModel(MODEL_CYBORG_BOMB ); + pdec->PrecacheTexture(TEXTURE_CYBORG_BOMB ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BOMB); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE_PLANE); + break; + + case PRT_LAVA_COMET: + pdec->PrecacheModel(MODEL_ELEM_LAVA_STONE); + pdec->PrecacheModel(MODEL_ELEM_LAVA_STONE_FLARE); + pdec->PrecacheModel(MODEL_ELEM_LAVA_BOMB); + pdec->PrecacheModel(MODEL_ELEM_LAVA_BOMB_FLARE); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_STONE); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_STONE_FLARE ); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_BOMB); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_BOMB_FLARE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + pdec->PrecacheClass(CLASS_BLOOD_SPRAY); + pdec->PrecacheModel(MODEL_LAVA ); + pdec->PrecacheTexture(TEXTURE_LAVA ); + pdec->PrecacheModel(MODEL_LAVA_FLARE ); + pdec->PrecacheTexture(TEXTURE_LAVA_FLARE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + pdec->PrecacheClass(CLASS_BLOOD_SPRAY); + break; + case PRT_BEAST_PROJECTILE: + case PRT_BEAST_DEBRIS: + pdec->PrecacheSound(SOUND_BEAST_FLYING ); + pdec->PrecacheModel(MODEL_BEAST_FIRE); + pdec->PrecacheTexture(TEXTURE_BEAST_FIRE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON); + break; + case PRT_GUFFY_PROJECTILE: + pdec->PrecacheSound(SOUND_FLYING ); + pdec->PrecacheModel(MODEL_GUFFY_PROJECTILE ); + pdec->PrecacheTexture(TEXTURE_GUFFY_PROJECTILE ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_ROCKET ); + break; + case PRT_BEAST_BIG_PROJECTILE: + case PRT_DEVIL_GUIDED_PROJECTILE: + case PRT_BEAST_BIG_DEBRIS: + case PRT_SHOOTER_FIREBALL: + pdec->PrecacheSound(SOUND_BEAST_FLYING ); + pdec->PrecacheModel(MODEL_BEAST_FIRE); + pdec->PrecacheTexture(TEXTURE_BEAST_BIG_FIRE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LIGHT_CANNON); + break; + case PRT_DEMON_FIREBALL: + case PRT_DEMON_FIREBALL_DEBRIS: + pdec->PrecacheSound(SOUND_DEMON_FLYING ); + pdec->PrecacheModel(MODEL_DEMON_FIREBALL); + pdec->PrecacheTexture(TEXTURE_DEMON_FIREBALL); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LIGHT_CANNON); + break; + case PRT_LARVA_PLASMA: + pdec->PrecacheSound(SOUND_DEMON_FLYING ); + pdec->PrecacheModel(MODEL_LARVA_PLASMA); + pdec->PrecacheTexture(TEXTURE_LARVA_PLASMA); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LIGHT_CANNON); + break; + case PRT_LARVA_TAIL_PROJECTILE: + pdec->PrecacheSound(SOUND_LARVETTE ); + pdec->PrecacheModel(MODEL_LARVA_TAIL); + pdec->PrecacheTexture(TEXTURE_LARVA_TAIL); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON); + break; + case PRT_SHOOTER_WOODEN_DART: + pdec->PrecacheModel(MODEL_SHTR_WOODEN_DART); + pdec->PrecacheTexture(TEX_SHTR_WOODEN_DART); + break; + case PRT_SHOOTER_FLAME: + pdec->PrecacheModel(MODEL_FLAME); + pdec->PrecacheClass(CLASS_FLAME); + break; + case PRT_AIRELEMENTAL_WIND: + pdec->PrecacheModel(MODEL_WINDBLAST); + pdec->PrecacheTexture(TEXTURE_WINDBLAST); + break; + case PRT_AFTERBURNER_DEBRIS: + pdec->PrecacheModel(MODEL_MARKER); + pdec->PrecacheTexture(TEXTURE_MARKER); + break; + default: + ASSERT(FALSE); + } +} + +void CProjectile::SetDefaultProperties(void) { + m_penLauncher = NULL; + m_prtType = PRT_ROCKET ; + m_pmtMove = PMT_FLYING ; + m_penParticles = NULL; + m_penTarget = NULL; + m_penLastDamaged = NULL; + m_fSpeed = 0.0f; + m_fIgnoreTime = 0.0f; + m_fFlyTime = 0.0f; + m_fStartTime = 0.0f; + m_fDamageAmount = 0.0f; + m_fRangeDamageAmount = 0.0f; + m_fDamageHotSpotRange = 0.0f; + m_fDamageFallOffRange = 0.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE ; + m_bLightSource = FALSE ; + m_bCanHitHimself = FALSE ; + m_bCanBeDestroyed = FALSE ; + m_fWaitAfterDeath = 0.0f; + m_aRotateSpeed = 0.0f; + m_tmExpandBox = 0.0f; + m_tmInvisibility = 0.0f; + m_iRebounds = 0; + m_fStretch = 1.0f; + m_soEffect.SetOwner(this); +m_soEffect.Stop_internal(); + m_soExplosion.SetOwner(this); +m_soExplosion.Stop_internal(); + m_fGuidedMaxSpeedFactor = 30.0f; + bLockedOn = TRUE ; + m_bLeftFlame = FALSE ; + m_penPrediction = NULL; + CMovableModelEntity::SetDefaultProperties(); +} + +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::PreMoving(void) { +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_tmExpandBox > 0){ +#line 589 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(_pTimer -> CurrentTick () > m_fStartTime + m_tmExpandBox ){ +#line 590 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ChangeCollisionBoxIndexWhenPossible (1); +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0; +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 593 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CMovableModelEntity :: PreMoving (); +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::PostMoving(void) { +#line 599 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CMovableModelEntity :: PostMoving (); +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_prtType == PRT_FLAME || m_prtType == PRT_SHOOTER_FLAME ){ +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CContentType & ctDn = GetWorld () -> wo_actContentTypes [ en_iDnContent ]; +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(! (ctDn . ct_ulFlags & CTF_BREATHABLE_LUNGS )){ +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 607 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SendEvent (EEnd ()); +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 609 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::Read_t(CTStream * istr) +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CMovableModelEntity :: Read_t (istr ); +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_bLightSource ){ +#line 618 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetupLightSource (TRUE ); +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + void CProjectile::DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck) +#line 624 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CMovableModelEntity :: DumpSync_t (strm , iExtensiveSyncCheck ); +#line 626 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +strm . FPrintF_t ("projectile type: %d\n" , m_prtType ); +#line 627 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +strm . FPrintF_t ("launcher:"); +#line 628 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_penLauncher != NULL ){ +#line 629 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +strm . FPrintF_t ("id:%05d '%s'(%s) (%g, %g, %g)\n" , +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penLauncher -> en_ulID , +#line 631 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penLauncher -> GetName () , m_penLauncher -> GetClass () -> ec_pdecDLLClass -> dec_strName , +#line 632 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penLauncher -> GetPlacement () . pl_PositionVector (1) , +#line 633 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penLauncher -> GetPlacement () . pl_PositionVector (2) , +#line 634 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penLauncher -> GetPlacement () . pl_PositionVector (3)); +#line 635 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +strm . FPrintF_t ("\n"); +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 638 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CLightSource * CProjectile::GetLightSource(void) +#line 642 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 643 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_bLightSource && ! IsPredictor ()){ +#line 644 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return & m_lsLightSource ; +#line 645 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 646 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return NULL ; +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 648 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + void CProjectile::Copy(CEntity & enOther,ULONG ulFlags) +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 652 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CMovableModelEntity :: Copy (enOther , ulFlags ); +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CProjectile * penOther = (CProjectile *) (& enOther ); +#line 654 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(ulFlags & COPY_PREDICTOR ){ +#line 657 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 659 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL CProjectile::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 664 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CModelObject * pmo = GetModelObject (); +#line 665 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((pmo != NULL ) && (_pTimer -> GetLerpedCurrentTick () < (m_fStartTime + m_tmInvisibility ))) +#line 666 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pmo -> mo_colBlendColor = 0; +#line 669 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 670 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else +#line 671 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 673 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pmo -> mo_colBlendColor = C_WHITE | CT_OPAQUE ; +#line 674 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 675 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return CEntity :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 676 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 679 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::SetupLightSource(BOOL bLive) +#line 680 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 682 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CLightSource lsNew ; +#line 683 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_ulFlags = LSF_NONPERSISTENT | LSF_DYNAMIC ; +#line 684 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rHotSpot = 0.0f; +#line 685 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +switch(m_prtType ){ +#line 686 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_ROCKET : +#line 687 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_WALKER_ROCKET : +#line 688 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEVIL_ROCKET : +#line 689 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bLive ) +#line 690 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 691 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = 0xA0A080FF; +#line 692 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 693 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else +#line 694 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 695 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_BLACK | CT_OPAQUE ; +#line 696 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 697 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 5.0f; +#line 698 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = & _lftYellowStarRedRingFar ; +#line 699 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 700 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GUFFY_PROJECTILE : +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_BLUE ; +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 1.5f; +#line 703 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 704 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GRENADE : +#line 705 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = 0x2F1F0F00; +#line 706 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 2.0f; +#line 707 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rHotSpot = 0.2f; +#line 708 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = & _lftYellowStarRedRingFar ; +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_FLAME : +#line 711 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_dORANGE ; +#line 712 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 1.0f; +#line 713 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LASER_RAY : +#line 716 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_vdGREEN ; +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 1.5f; +#line 718 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 719 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GRUNT_PROJECTILE_SOL : +#line 721 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_vdRED ; +#line 722 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 1.5f; +#line 723 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 724 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 725 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GRUNT_PROJECTILE_COM : +#line 726 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_vdRED ; +#line 727 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 1.5f; +#line 728 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 729 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 730 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_CATMAN_FIRE : +#line 731 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_BLUE ; +#line 732 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 3.5f; +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = & _lftCatmanFireGlow ; +#line 734 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 735 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_FIRECRACKER : +#line 736 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_ORANGE ; +#line 737 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 1.5f; +#line 738 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 739 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 740 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_ROCKETMAN : +#line 741 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_YELLOW ; +#line 742 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 1.5f; +#line 743 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 744 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 745 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_WOMAN_FIRE : +#line 746 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_WHITE ; +#line 747 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 3.5f; +#line 748 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = & _lftCatmanFireGlow ; +#line 749 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 750 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DRAGONMAN_FIRE : +#line 751 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_YELLOW ; +#line 752 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 3.5f; +#line 753 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = & _lftProjectileYellowBubbleGlow ; +#line 754 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 755 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DRAGONMAN_STRONG_FIRE : +#line 756 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_RED ; +#line 757 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 3.5f; +#line 758 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = & _lftProjectileStarGlow ; +#line 759 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 760 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HUANMAN_FIRE : +#line 761 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_lBLUE ; +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 2.0f; +#line 763 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 764 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 765 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_FISHMAN_FIRE : +#line 766 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_lBLUE ; +#line 767 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 2.0f; +#line 768 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 769 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 770 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_MANTAMAN_FIRE : +#line 771 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_lBLUE ; +#line 772 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 2.0f; +#line 773 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 774 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 775 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_CYBORG_LASER : +#line 776 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_dBLUE ; +#line 777 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 1.5f; +#line 778 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 779 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 780 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEVIL_LASER : +#line 781 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_dBLUE ; +#line 782 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 5.0f; +#line 783 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = & _lftYellowStarRedRingFar ; +#line 784 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 785 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LARVA_PLASMA : +#line 786 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_dBLUE ; +#line 787 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 5.0f; +#line 788 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = & _lftCatmanFireGlow ; +#line 789 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 790 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_FIREBALL : +#line 791 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_dORANGE ; +#line 792 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 5.0f; +#line 793 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = & _lftYellowStarRedRingFar ; +#line 794 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 795 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_FLAME : +#line 796 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_colColor = C_dORANGE ; +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_rFallOff = 1.0f; +#line 798 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_plftLensFlare = NULL ; +#line 799 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 800 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +default : +#line 801 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ASSERTALWAYS ("Unknown light source"); +#line 802 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 803 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_ubPolygonalMask = 0; +#line 804 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +lsNew . ls_paoLightAnimation = NULL ; +#line 806 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_lsLightSource . ls_penEntity = this ; +#line 807 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 808 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 811 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::RenderParticles(void) { +#line 812 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +switch(m_prtType ){ +#line 813 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_ROCKET : +#line 814 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_WALKER_ROCKET : Particles_RocketTrail (this , 1.0f);break ; +#line 815 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEVIL_ROCKET : Particles_RocketTrail (this , 8.0f);break ; +#line 816 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GUFFY_PROJECTILE : break ; +#line 817 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GRENADE : { +#line 819 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeedRatio = en_vCurrentTranslationAbsolute . Length () / 140.0f; +#line 820 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_CannonBall (this , fSpeedRatio ); +#line 821 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 822 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 823 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_FLAME : { +#line 825 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fLeaderLiving , fFollowerLiving , fInFrontLiving ; +#line 826 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fInFrontLiving = 0.05f; +#line 827 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fLeaderLiving = _pTimer -> GetLerpedCurrentTick () - m_fStartTime ; +#line 829 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_penParticles != NULL && ! (m_penParticles -> GetFlags () & ENF_DELETED )){ +#line 830 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDirLeader = en_vCurrentTranslationAbsolute ; +#line 831 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +vDirLeader . Normalize (); +#line 833 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsOfClass (m_penParticles , "Projectile")) +#line 834 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 835 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CProjectile & prLast = (CProjectile &) * m_penParticles ; +#line 837 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsOfClass (prLast . m_penParticles , "Player Weapons")) +#line 838 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 839 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlayerWeapons & plw = (CPlayerWeapons &) * prLast . m_penParticles ; +#line 840 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(! (plw . GetPlayer () -> GetFlags () & ENF_ALIVE )) +#line 841 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 842 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return ; +#line 843 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 844 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plPipe , plInFrontOfPipe ; +#line 845 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CPlayerWeapons &) * prLast . m_penParticles ) . GetFlamerSourcePlacement (plPipe , plInFrontOfPipe ); +#line 846 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fFollowerLiving = _pTimer -> GetLerpedCurrentTick () - ((CProjectile &) * m_penParticles ) . m_fStartTime ; +#line 847 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDirPipeFront ; +#line 848 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +AnglesToDirectionVector (plInFrontOfPipe . pl_OrientationAngle , vDirPipeFront ); +#line 849 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +vDirPipeFront . Normalize (); +#line 850 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_FlameThrower (GetLerpedPlacement () , plInFrontOfPipe , +#line 851 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +vDirLeader , vDirPipeFront , +#line 852 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fLeaderLiving , fInFrontLiving , en_ulID , FALSE ); +#line 853 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else +#line 856 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 857 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fFollowerLiving = _pTimer -> GetLerpedCurrentTick () - ((CProjectile &) * m_penParticles ) . m_fStartTime ; +#line 858 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDirFollower = ((CMovableModelEntity *) (CEntity *) m_penParticles ) -> en_vCurrentTranslationAbsolute ; +#line 859 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +vDirFollower . Normalize (); +#line 860 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_FlameThrower (GetLerpedPlacement () , m_penParticles -> GetLerpedPlacement () , +#line 861 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +vDirLeader , vDirFollower , fLeaderLiving , fFollowerLiving , en_ulID , FALSE ); +#line 862 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 864 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else if(IsOfClass (m_penParticles , "Player Weapons")){ +#line 865 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlayerWeapons & plw = (CPlayerWeapons &) * m_penParticles ; +#line 866 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(! (plw . GetPlayer () -> GetFlags () & ENF_ALIVE )) +#line 867 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 868 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return ; +#line 869 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plPipe , plInFrontOfPipe ; +#line 871 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +plw . GetFlamerSourcePlacement (plPipe , plInFrontOfPipe ); +#line 872 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDirPipeFront ; +#line 873 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +AnglesToDirectionVector (plInFrontOfPipe . pl_OrientationAngle , vDirPipeFront ); +#line 874 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vViewDir ; +#line 875 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +AnglesToDirectionVector (plPipe . pl_OrientationAngle , vViewDir ); +#line 876 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDirFollower = vViewDir . Normalize (); +#line 884 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_FlameThrower (plInFrontOfPipe , plPipe , +#line 885 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +vDirPipeFront , vDirFollower , +#line 886 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fInFrontLiving , 0.0f , en_ulID , TRUE ); +#line 888 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_FlameThrowerStart (plPipe , plw . m_tmFlamerStart , plw . m_tmFlamerStop ); +#line 889 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 890 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 891 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 892 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 893 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_CATMAN_FIRE : Particles_RocketTrail (this , 1.0f);break ; +#line 894 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_FIRECRACKER : Particles_FirecrackerTrail (this );break ; +#line 895 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_ROCKETMAN : Particles_Fireball01Trail (this );break ; +#line 896 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_BOMBERMAN : Particles_BombTrail (this );break ; +#line 897 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVA_COMET : Particles_LavaTrail (this );break ; +#line 898 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVAMAN_BIG_BOMB : Particles_LavaBombTrail (this , 4.0f);break ; +#line 899 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVAMAN_BOMB : Particles_LavaBombTrail (this , 1.0f);break ; +#line 900 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_PROJECTILE : Particles_BeastProjectileTrail (this , 2.0f , 0.25f , 48);break ; +#line 901 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_BIG_PROJECTILE : +#line 902 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEMON_FIREBALL : +#line 903 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_BeastBigProjectileTrail (this , 4.0f , 0.25f , 0.0f , 64); +#line 904 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_AfterBurner (this , m_fStartTime , 1.0f); +#line 905 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 906 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEVIL_GUIDED_PROJECTILE : +#line 907 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_BeastBigProjectileTrail (this , 6.0f , 0.375f , 0.0f , 64); +#line 908 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 909 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_DEBRIS : Particles_BeastProjectileDebrisTrail (this , 0.20f);break ; +#line 910 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_BIG_DEBRIS : Particles_BeastProjectileDebrisTrail (this , 0.25f);break ; +#line 911 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_WOODEN_DART : Particles_RocketTrail (this , 0.25f);break ; +#line 912 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_FIREBALL : Particles_Fireball01Trail (this );break ; +#line 913 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_FLAME : { +#line 915 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fTimeElapsed , fParticlesTimeElapsed ; +#line 916 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fTimeElapsed = _pTimer -> GetLerpedCurrentTick () - m_fStartTime ; +#line 918 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_penParticles != NULL && ! (m_penParticles -> GetFlags () & ENF_DELETED )){ +#line 920 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsOfClass (m_penParticles , "Projectile")){ +#line 921 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fParticlesTimeElapsed = _pTimer -> GetLerpedCurrentTick () - ((CProjectile &) * m_penParticles ) . m_fStartTime ; +#line 922 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_ShooterFlame (GetLerpedPlacement () , m_penParticles -> GetLerpedPlacement () , +#line 923 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fTimeElapsed , fParticlesTimeElapsed ); +#line 924 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else if(IsOfClass (m_penParticles , "Shooter")){ +#line 925 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_ShooterFlame (GetLerpedPlacement () , +#line 926 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CShooter &) * m_penParticles ) . GetPlacement () , +#line 927 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fTimeElapsed , 0.0f); +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 929 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 930 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 931 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 932 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_METEOR : +#line 933 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_MeteorTrail (this , m_fStretch , 1.0f , en_vCurrentTranslationAbsolute ); +#line 934 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_AfterBurner (this , m_fStartTime , m_fStretch * 4.0f , 2); +#line 935 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 936 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_AFTERBURNER_DEBRIS : +#line 937 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_AfterBurner (this , m_fStartTime , m_fStretch ); +#line 938 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 939 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_AIRELEMENTAL_WIND : +#line 940 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_Windblast (this , m_fStretch / 4.0f , m_fStartTime + 3.0f); +#line 941 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 942 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 943 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 951 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::PlayerRocket(void) { +#line 953 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 954 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 955 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 956 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_ROCKET ); +#line 957 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_ROCKET ); +#line 959 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 960 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 962 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (20.0f , 2.0f , 1.0f , 1.0f); +#line 963 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_FLYING , SOF_3D | SOF_LOOP ); +#line 964 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 30.0f; +#line 965 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetSP () -> sp_bCooperative ) +#line 966 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 100.0f; +#line 968 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 50.0f; +#line 969 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 970 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else +#line 971 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 972 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 75.0f; +#line 973 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 75.0f; +#line 974 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 975 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 4.0f; +#line 976 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 8.0f; +#line 977 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 50.0f; +#line 978 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 979 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 980 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = TRUE ; +#line 981 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 982 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 1.125f; +#line 983 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 984 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.05f; +#line 985 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (5.0f); +#line 986 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 987 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 989 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::WalkerRocket(void) { +#line 991 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 992 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 993 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 994 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_ROCKET ); +#line 995 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_ROCKET ); +#line 997 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 998 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1000 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (20.0f , 2.0f , 1.0f , 1.0f); +#line 1001 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_FLYING , SOF_3D | SOF_LOOP ); +#line 1002 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 30.0f; +#line 1003 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetSP () -> sp_gdGameDifficulty <= CSessionProperties :: GD_EASY ){ +#line 1004 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 40.0f; +#line 1005 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 20.0f; +#line 1006 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 1007 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 100.0f; +#line 1008 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 50.0f; +#line 1009 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1010 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 4.0f; +#line 1011 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 8.0f; +#line 1012 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 50.0f; +#line 1013 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 1014 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 1015 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = TRUE ; +#line 1016 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 1017 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 1.125f; +#line 1018 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 1019 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.05f; +#line 1020 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (5.0f); +#line 1021 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 1022 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1024 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::WalkerRocketExplosion(void) { +#line 1025 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlayerRocketExplosion (); +#line 1026 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1028 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::PlayerRocketExplosion(void) { +#line 1029 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 1030 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vPoint ; +#line 1031 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOATplane3D vPlaneNormal ; +#line 1032 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceToEdge ; +#line 1035 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1036 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_ROCKET ; +#line 1037 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (1 , 1 , 1); +#line 1038 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1040 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsDerivedFromClass (m_penLauncher , "Player")){ +#line 1041 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnRangeSound (m_penLauncher , this , SNDT_PLAYER , m_fSoundRange ); +#line 1042 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1045 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_EXPLOSION_DEBRIS ; +#line 1046 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1049 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_EXPLOSION_SMOKE ; +#line 1050 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1053 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )){ +#line 1054 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f){ +#line 1056 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_EXPLOSIONSTAIN ; +#line 1057 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1058 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1060 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_SHOCKWAVE ; +#line 1061 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1062 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1064 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_ROCKET_PLANE ; +#line 1065 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1066 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint + ese . vNormal / 50.0f , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1067 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1068 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1069 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1072 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::PlayerGrenade(void) { +#line 1074 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1075 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_BOUNCING ); +#line 1076 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 1077 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_GRENADE ); +#line 1078 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_GRENADE ); +#line 1080 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsFreeProjectile (FLOAT3D (0.0f , 5.0f , - m_fSpeed ) , (CMovableEntity *) & * m_penLauncher ); +#line 1081 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , FRnd () * 120.0f + 120.0f , FRnd () * 250.0f - 125.0f)); +#line 1082 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +en_fBounceDampNormal = 0.75f; +#line 1083 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +en_fBounceDampParallel = 0.6f; +#line 1084 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +en_fJumpControlMultiplier = 0.0f; +#line 1085 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +en_fCollisionSpeedLimit = 45.0f; +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +en_fCollisionDamageFactor = 10.0f; +#line 1087 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 3.0f; +#line 1088 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 75.0f; +#line 1089 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 100.0f; +#line 1090 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 4.0f; +#line 1091 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 8.0f; +#line 1092 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 50.0f; +#line 1093 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 1094 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +en_fDeceleration = 25.0f; +#line 1095 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 1096 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = TRUE ; +#line 1097 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 1098 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1099 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (20.0f); +#line 1100 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_SLIDING ; +#line 1101 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.05f; +#line 1102 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 1103 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1105 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::PlayerGrenadeExplosion(void) { +#line 1106 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 1107 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vPoint ; +#line 1108 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOATplane3D vPlaneNormal ; +#line 1109 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceToEdge ; +#line 1112 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1113 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_GRENADE ; +#line 1114 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (1 , 1 , 1); +#line 1115 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1117 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsDerivedFromClass (m_penLauncher , "Player")){ +#line 1118 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnRangeSound (m_penLauncher , this , SNDT_PLAYER , m_fSoundRange ); +#line 1119 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1122 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )){ +#line 1123 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f){ +#line 1125 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_EXPLOSIONSTAIN ; +#line 1126 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1127 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1129 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_SHOCKWAVE ; +#line 1130 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1131 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1133 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_GRENADE_PLANE ; +#line 1134 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1135 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint + ese . vNormal / 50.0f , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1136 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1137 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1138 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1145 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::PlayerFlame(void) { +#line 1147 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsEditorModel (); +#line 1148 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_SLIDING & ~ EPF_TRANSLATEDBYGRAVITY & ~ EPF_ORIENTEDBYGRAVITY ); +#line 1150 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 1151 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 1152 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_FLAME ); +#line 1157 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CMovableEntity * penPlayer = (CMovableEntity *) (CEntity *) m_penLauncher ; +#line 1158 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDirection = penPlayer -> en_vCurrentTranslationAbsolute ; +#line 1159 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vFront = - GetRotationMatrix () . GetColumn (3); +#line 1160 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeedFwd = ClampDn (vDirection % vFront , 0.0f); +#line 1162 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - (25.0f + fSpeedFwd )) , penPlayer ); +#line 1163 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1164 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 1.0f; +#line 1165 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = (GetSP () -> sp_bCooperative ) ? 10.0f : 4.0f; +#line 1166 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1167 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1168 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 1169 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1170 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 1171 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.3f; +#line 1172 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 1173 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_SLIDING ; +#line 1174 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1181 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::PlayerLaserRay(void) { +#line 1183 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1184 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 1185 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 1186 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 1187 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_LASER ); +#line 1188 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CModelObject * pmo = GetModelObject (); +#line 1189 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(pmo != NULL ) +#line 1190 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1191 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pmo -> PlayAnim (LASERPROJECTILE_ANIM_GROW , 0); +#line 1192 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1193 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_GREEN_LASER ); +#line 1195 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 120.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1196 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1197 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 3.0f; +#line 1198 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 20.0f; +#line 1199 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1200 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1201 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 1202 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1203 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 1204 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1205 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 1207 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.025f; +#line 1208 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 1209 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1211 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::PlayerLaserWave(void) { +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 1213 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vPoint ; +#line 1214 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOATplane3D vPlaneNormal ; +#line 1215 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceToEdge ; +#line 1218 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )){ +#line 1219 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f){ +#line 1221 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_dRED | CT_OPAQUE ; +#line 1222 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_LASERWAVE ; +#line 1223 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1224 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1225 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1226 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1227 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1234 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::CatmanProjectile(void) { +#line 1236 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1237 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 1238 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 1239 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 1240 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_CATMAN_FIRE ); +#line 1241 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_CATMAN_FIRE ); +#line 1243 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 15.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1244 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1245 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 5.0f; +#line 1247 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1248 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1249 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 1250 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1251 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 1252 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1253 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 1254 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1261 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::HeadmanFirecracker(void) { +#line 1263 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1264 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_SLIDING ); +#line 1265 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 1266 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 1267 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_HEADMAN_FIRECRACKER ); +#line 1268 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_HEADMAN_FIRECRACKER ); +#line 1269 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (0.75f , 0.75f , 0.75f)); +#line 1270 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 1272 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 25.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1273 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , FRnd () * 20.0f - 10.0f)); +#line 1274 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 1275 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 4.0f; +#line 1276 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1277 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1278 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 1279 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1280 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 1281 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1282 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_SLIDING ; +#line 1283 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1285 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::HeadmanRocketman(void) { +#line 1287 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1288 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 1290 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 1291 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetComponents (this , * GetModelObject () , MODEL_HEADMAN_BLADE , TEXTURE_HEADMAN_BLADE , +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 1293 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +AddAttachmentToModel (this , * GetModelObject () , BLADE_ATTACHMENT_FLAME01 , +#line 1294 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +MODEL_HEADMAN_BLADE_FLAME , TEXTURE_HEADMAN_BLADE_FLAME , 0 , 0 , 0); +#line 1295 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +AddAttachmentToModel (this , * GetModelObject () , BLADE_ATTACHMENT_FLAME02 , +#line 1296 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +MODEL_HEADMAN_BLADE_FLAME , TEXTURE_HEADMAN_BLADE_FLAME , 0 , 0 , 0); +#line 1297 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +AddAttachmentToModel (this , * GetModelObject () , BLADE_ATTACHMENT_FLAME03 , +#line 1298 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +MODEL_HEADMAN_BLADE_FLAME , TEXTURE_HEADMAN_BLADE_FLAME , 0 , 0 , 0); +#line 1299 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (0.5f , 0.5f , 0.5f)); +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 1302 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1304 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 1305 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 5.0f; +#line 1306 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1307 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1308 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 1309 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1310 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 1311 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1312 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1315 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::HeadmanBomberman(void) { +#line 1317 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1318 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_BOUNCING ); +#line 1319 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 1320 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_HEADMAN_BOMB ); +#line 1321 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_HEADMAN_BOMB ); +#line 1324 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsFreeProjectile (FLOAT3D (0.0f , 0.0f , - m_fSpeed ) , (CMovableEntity *) & * m_penLauncher ); +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , FRnd () * 360.0f - 180.0f , FRnd () * 360.0f - 180.0f)); +#line 1326 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 2.5f; +#line 1327 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 1328 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 15.0f; +#line 1329 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 1.0f; +#line 1330 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 6.0f; +#line 1331 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 25.0f; +#line 1332 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 1333 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 1334 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = TRUE ; +#line 1335 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 1336 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1337 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (5.0f); +#line 1338 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 1339 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1341 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::HeadmanBombermanExplosion(void) { +#line 1342 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 1343 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vPoint ; +#line 1344 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOATplane3D vPlaneNormal ; +#line 1345 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceToEdge ; +#line 1348 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1349 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_BOMB ; +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (1.0f , 1.0f , 1.0f); +#line 1351 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1353 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )){ +#line 1354 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f){ +#line 1356 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_EXPLOSIONSTAIN ; +#line 1357 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1358 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1359 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_GRENADE_PLANE ; +#line 1360 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1361 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint + ese . vNormal / 50.0f , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1362 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1363 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1364 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1366 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::CyborgBombExplosion(void) +#line 1367 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1368 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vPoint ; +#line 1370 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOATplane3D vPlaneNormal ; +#line 1371 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceToEdge ; +#line 1374 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1375 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_BOMB ; +#line 1376 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (1.0f , 1.0f , 1.0f); +#line 1377 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1379 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )){ +#line 1380 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f){ +#line 1382 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_EXPLOSIONSTAIN ; +#line 1383 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1384 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1385 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_GRENADE_PLANE ; +#line 1386 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1387 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint + ese . vNormal / 50.0f , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1388 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1389 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1390 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1395 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::BonemanProjectile(void) { +#line 1397 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1398 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 1400 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 1401 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_BONEMAN_FIRE ); +#line 1402 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_BONEMAN_FIRE ); +#line 1404 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1405 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1406 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 1407 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 1408 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1409 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1410 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 1411 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1412 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 1413 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1414 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_SLIDING ; +#line 1415 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1422 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::WomanProjectile(void) { +#line 1424 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1425 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 1426 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 1427 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 1428 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_WOMAN_FIRE ); +#line 1429 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_WOMAN_FIRE ); +#line 1431 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1432 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1433 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 1434 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 8.0f; +#line 1435 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1436 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1437 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 1438 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1439 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 1440 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1441 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 1442 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1449 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::DragonmanProjectile(INDEX iType) { +#line 1451 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1452 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_ONBLOCK_SLIDE | EPF_PUSHABLE | EPF_MOVABLE ); +#line 1453 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 1454 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 1455 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_DRAGONMAN_FIRE ); +#line 1456 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(iType == DRAGONMAN_STRONG ){ +#line 1457 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_DRAGONMAN_FIRE2 ); +#line 1458 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 1459 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_DRAGONMAN_FIRE1 ); +#line 1460 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1462 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(iType == DRAGONMAN_STRONG ){ +#line 1463 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 40.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1464 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 14.0f; +#line 1465 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 1466 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1467 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 7.0f; +#line 1468 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1469 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1470 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 1471 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1472 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1473 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 1474 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1475 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 1476 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1477 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 1478 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1485 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::ElementalRock(INDEX iSize,INDEX iType) { +#line 1487 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1488 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_ONBLOCK_SLIDE | EPF_PUSHABLE | EPF_MOVABLE ); +#line 1489 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 1490 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +switch(iType ){ +#line 1491 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case ELEMENTAL_STONEMAN : +#line 1492 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_ELEM_STONE ); +#line 1493 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_ELEM_STONE ); +#line 1494 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 1495 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case ELEMENTAL_LAVAMAN : +#line 1496 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_ELEM_LAVA_STONE ); +#line 1497 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_ELEM_LAVA_STONE ); +#line 1498 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +AddAttachmentToModel (this , * GetModelObject () , LAVASTONE_ATTACHMENT_FLARE , +#line 1499 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +MODEL_ELEM_LAVA_STONE_FLARE , TEXTURE_ELEM_LAVA_STONE_FLARE , 0 , 0 , 0); +#line 1500 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 1501 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case ELEMENTAL_ICEMAN : +#line 1502 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_ELEM_ICE ); +#line 1503 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_ELEM_ICE ); +#line 1506 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 1507 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1508 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(iSize == ELEMENTAL_LARGE ){ +#line 1509 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (2.25f , 2.25f , 2.25f)); +#line 1510 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else if(iSize == ELEMENTAL_BIG ){ +#line 1511 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (0.75f , 0.75f , 0.75f)); +#line 1512 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 1513 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (0.4f , 0.4f , 0.4f)); +#line 1514 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1515 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 1517 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(iSize == ELEMENTAL_LARGE ){ +#line 1518 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 80.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1519 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 20.0f; +#line 1520 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (40.0f); +#line 1521 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else if(iSize == ELEMENTAL_BIG ){ +#line 1522 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 50.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1523 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 12.5f; +#line 1524 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (20.0f); +#line 1525 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 1526 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1527 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 7.0f; +#line 1528 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (10.0f); +#line 1529 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1530 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , FRnd () * 1800.0f - 900.0f)); +#line 1531 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +en_fCollisionSpeedLimit = 1000.0f; +#line 1532 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +en_fCollisionDamageFactor = 0.0f; +#line 1533 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 1534 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1535 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1536 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 1537 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1538 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 1539 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1540 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_SLIDING ; +#line 1541 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1543 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::LavaManBomb(void) +#line 1544 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1546 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1547 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_BOUNCING ); +#line 1548 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 1550 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_ELEM_LAVA_BOMB ); +#line 1551 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_ELEM_LAVA_BOMB ); +#line 1552 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +AddAttachmentToModel (this , * GetModelObject () , LAVABOMB_ATTACHMENT_FLARE , +#line 1553 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +MODEL_ELEM_LAVA_BOMB_FLARE , TEXTURE_ELEM_LAVA_BOMB_FLARE , 0 , 0 , 0); +#line 1555 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_prtType == PRT_LAVAMAN_BIG_BOMB ) +#line 1556 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1557 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (6.0f , 6.0f , 6.0f)); +#line 1558 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 20.0f; +#line 1559 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 10.0f; +#line 1560 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 7.5f; +#line 1561 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 15.0f; +#line 1562 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (30.0f); +#line 1563 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1564 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else if(m_prtType == PRT_LAVAMAN_BOMB ) +#line 1565 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1566 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (1.5f , 1.5f , 1.5f)); +#line 1567 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 1568 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 5.0f; +#line 1569 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 5.0f; +#line 1570 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 10.0f; +#line 1571 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (10.0f); +#line 1572 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1573 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 1576 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsFreeProjectile (FLOAT3D (0.0f , 0.0f , - m_fSpeed ) , (CMovableEntity *) & * m_penLauncher ); +#line 1577 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , FRnd () * 360.0f - 180.0f , 0.0f)); +#line 1578 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 20.0f; +#line 1579 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 50.0f; +#line 1580 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 1581 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 1582 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1583 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 1584 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 1585 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 4.0f; +#line 1588 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_prtType == PRT_LAVAMAN_BIG_BOMB ) +#line 1589 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1591 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 1592 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 1593 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 1594 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 1595 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 1596 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 4.0f; +#line 1597 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.5f; +#line 1598 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 1599 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = FLOAT3D (0 , - 0.5f , 0); +#line 1600 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 1601 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 1602 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1603 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1605 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::LavamanBombExplosion(void) +#line 1606 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1607 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 1608 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vPoint ; +#line 1609 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOATplane3D vPlaneNormal ; +#line 1610 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceToEdge ; +#line 1612 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )) +#line 1613 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1614 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f) +#line 1615 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1617 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1618 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_SHOCKWAVE ; +#line 1619 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1620 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1621 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1622 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1625 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1626 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_LIGHT_CANNON ; +#line 1627 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (4 , 4 , 4); +#line 1628 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1631 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 1632 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 1633 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 1634 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 1635 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 1636 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 4.0f; +#line 1637 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.5f; +#line 1638 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 1639 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = en_vCurrentTranslationAbsolute / 32.0f; +#line 1640 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 1641 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 1644 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +for(INDEX iDebris = 0;iDebris < 3 + IRnd () % 3;iDebris ++) +#line 1645 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1646 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fHeading = (FRnd () - 0.5f) * 180.0f; +#line 1647 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fPitch = 10.0f + FRnd () * 40.0f; +#line 1648 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeed = 10.0 + FRnd () * 50.0f; +#line 1651 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D pl = GetPlacement (); +#line 1652 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pl . pl_PositionVector (2) += 2.0f; +#line 1653 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pl . pl_OrientationAngle = m_penLauncher -> GetPlacement () . pl_OrientationAngle ; +#line 1654 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pl . pl_OrientationAngle (1) += AngleDeg (fHeading ); +#line 1655 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pl . pl_OrientationAngle (2) = AngleDeg (fPitch ); +#line 1657 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 1658 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ELaunchProjectile eLaunch ; +#line 1659 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . penLauncher = this ; +#line 1660 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . prtType = PRT_LAVAMAN_BOMB ; +#line 1661 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . fSpeed = fSpeed ; +#line 1662 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penProjectile -> Initialize (eLaunch ); +#line 1665 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = pl ; +#line 1666 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 1667 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (penProjectile ); +#line 1668 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 1669 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 1670 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 1.0f; +#line 1671 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.5f; +#line 1672 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 1673 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = FLOAT3D (0 , - 0.5f , 0); +#line 1674 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = penProjectile ; +#line 1675 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 1676 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1677 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1679 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::LavamanBombDebrisExplosion(void) +#line 1680 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1681 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 1682 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vPoint ; +#line 1683 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOATplane3D vPlaneNormal ; +#line 1684 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceToEdge ; +#line 1687 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )) +#line 1688 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1689 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f) +#line 1690 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1691 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1692 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_SHOCKWAVE ; +#line 1693 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 1694 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 1695 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1696 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1699 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1700 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_LIGHT_CANNON ; +#line 1701 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (2 , 2 , 2); +#line 1702 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1705 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 1706 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 1707 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 1708 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 1709 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 1710 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 4.0f; +#line 1711 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 2.0f; +#line 1712 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 1713 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = en_vCurrentTranslationAbsolute / 16.0f; +#line 1714 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 1715 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 1716 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1721 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::HuanmanProjectile(void) { +#line 1723 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1724 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 1725 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 1726 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 1727 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetComponents (this , * GetModelObject () , MODEL_HUANMAN_FIRE , TEXTURE_HUANMAN_FIRE , +#line 1728 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +TEX_REFL_LIGHTMETAL01 , TEX_SPEC_STRONG , 0); +#line 1729 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +AddAttachmentToModel (this , * GetModelObject () , PROJECTILE_ATTACHMENT_FLARE , +#line 1730 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +MODEL_HUANMAN_FLARE , TEXTURE_HUANMAN_FLARE , 0 , 0 , 0); +#line 1731 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (0.5f , 0.5f , 0.5f)); +#line 1732 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 1734 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1735 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1736 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 1737 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 1738 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1739 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1740 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 1741 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1742 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 1743 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1744 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 1745 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1750 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::BeastProjectile(void) { +#line 1752 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsDerivedFromClass (m_penLauncher , "Enemy Base")){ +#line 1753 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penTarget = ((CEnemyBase *) & * m_penLauncher ) -> m_penEnemy ; +#line 1754 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1756 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1757 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_FREE_FLYING ); +#line 1758 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 1760 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_BEAST_FIRE ); +#line 1761 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_BEAST_FIRE ); +#line 1762 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (1.5f , 1.5f , 1.5f)); +#line 1764 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 1766 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (20.0f , 2.0f , 1.0f , 1.0f); +#line 1767 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_BEAST_FLYING , SOF_3D | SOF_LOOP ); +#line 1769 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 60.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1770 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1771 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 10.0f; +#line 1772 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 1773 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1774 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1775 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 1776 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1777 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 1778 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1779 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_GUIDED ; +#line 1780 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fGuidedMaxSpeedFactor = 30.0f; +#line 1781 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_aRotateSpeed = 175.0f; +#line 1782 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (10.0f); +#line 1783 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1785 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::BeastBigProjectile(void) { +#line 1787 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsDerivedFromClass (m_penLauncher , "Enemy Base")){ +#line 1788 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penTarget = ((CEnemyBase *) & * m_penLauncher ) -> m_penEnemy ; +#line 1789 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1791 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1792 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_FREE_FLYING ); +#line 1793 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 1795 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_BEAST_FIRE ); +#line 1796 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_BEAST_BIG_FIRE ); +#line 1797 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (2.5f , 2.5f , 2.5f)); +#line 1799 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 1801 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (50.0f , 2.0f , 1.0f , 0.75f); +#line 1802 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_BEAST_FLYING , SOF_3D | SOF_LOOP ); +#line 1804 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 60.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 1805 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1806 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 10.0f; +#line 1807 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 20.0f; +#line 1808 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1809 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1810 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 1811 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1812 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 1813 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1814 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_GUIDED_FAST ; +#line 1815 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fGuidedMaxSpeedFactor = 90.0f; +#line 1816 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (10000.0f); +#line 1817 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_aRotateSpeed = 100.0f; +#line 1818 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1820 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::BeastDebris(void) +#line 1821 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1823 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1824 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_BOUNCING ); +#line 1825 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 1827 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_BEAST_FIRE ); +#line 1828 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (0.75f , 0.75f , 0.75f)); +#line 1829 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_BEAST_FIRE ); +#line 1830 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StartAnim (1 + (ULONG ) FRnd () * 5.0f); +#line 1832 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 1834 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsFreeProjectile (FLOAT3D (0.0f , 0.0f , - 20.0f) , (CMovableEntity *) & * m_penLauncher ); +#line 1835 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1836 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 10.0f; +#line 1837 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 0.0f; +#line 1838 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1839 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1840 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 1841 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1842 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 1843 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1844 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 1845 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (1.0f); +#line 1846 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_aRotateSpeed = 100.0f; +#line 1847 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1849 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::BeastBigDebris(void) +#line 1850 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1852 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 1853 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_BOUNCING ); +#line 1854 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 1856 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_BEAST_FIRE ); +#line 1857 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_BEAST_BIG_FIRE ); +#line 1858 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 1859 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StartAnim (1 + (ULONG ) FRnd () * 5.0f); +#line 1861 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 1863 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsFreeProjectile (FLOAT3D (0.0f , 0.0f , - 20.0f) , (CMovableEntity *) & * m_penLauncher ); +#line 1864 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 1865 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 10.0f; +#line 1866 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 0.0f; +#line 1867 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 1868 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 1869 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 1870 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 1871 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 1872 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 1873 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 1874 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (1.0f); +#line 1875 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_aRotateSpeed = 100.0f; +#line 1876 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1878 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::BeastDebrisExplosion(void) +#line 1879 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1881 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 1882 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_GREEN | CT_OPAQUE ; +#line 1883 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_LIGHT_CANNON ; +#line 1884 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (0.75 , 0.75 , 0.75); +#line 1885 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1888 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 1889 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 1890 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 1891 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 1892 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 1893 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 2.0f; +#line 1894 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.75f; +#line 1895 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_BEAST_PROJECTILE_SPRAY ; +#line 1896 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = en_vCurrentTranslationAbsolute / 64.0f; +#line 1897 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 1898 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 1899 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1901 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::BeastBigDebrisExplosion(void) +#line 1902 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1904 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 1905 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1906 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_LIGHT_CANNON ; +#line 1907 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (1 , 1 , 1); +#line 1908 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1911 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 1912 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 1913 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 1914 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 1915 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 1916 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 2.0f; +#line 1917 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 1.0f; +#line 1918 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 1919 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = en_vCurrentTranslationAbsolute / 64.0f; +#line 1920 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 1921 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 1922 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1924 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::BeastProjectileExplosion(void) +#line 1925 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1927 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 1928 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_GREEN | CT_OPAQUE ; +#line 1929 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_LIGHT_CANNON ; +#line 1930 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (1.25 , 1.25 , 1.25); +#line 1931 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1934 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 1935 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 1936 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 1937 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 1938 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 1939 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 2.0f; +#line 1940 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 1.0f; +#line 1941 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_BEAST_PROJECTILE_SPRAY ; +#line 1942 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = en_vCurrentTranslationAbsolute / 64.0f; +#line 1943 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 1944 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 1946 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fHeading = 20.0f + (FRnd () - 0.5f) * 60.0f; +#line 1948 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +for(INDEX iDebris = 0;iDebris < 2;iDebris ++) +#line 1949 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1950 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fPitch = 10.0f + FRnd () * 10.0f; +#line 1951 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeed = 5.0 + FRnd () * 20.0f; +#line 1954 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D pl = GetPlacement (); +#line 1955 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pl . pl_OrientationAngle (1) += AngleDeg (fHeading ); +#line 1957 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fHeading = - fHeading ; +#line 1958 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pl . pl_OrientationAngle (2) = AngleDeg (fPitch ); +#line 1960 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 1961 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ELaunchProjectile eLaunch ; +#line 1962 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . penLauncher = this ; +#line 1963 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . prtType = PRT_BEAST_DEBRIS ; +#line 1964 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . fSpeed = fSpeed ; +#line 1965 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penProjectile -> Initialize (eLaunch ); +#line 1968 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = pl ; +#line 1969 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 1970 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (penProjectile ); +#line 1971 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 1972 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 1973 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 0.5f; +#line 1974 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.25f; +#line 1975 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_BEAST_PROJECTILE_SPRAY ; +#line 1976 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = FLOAT3D (0 , - 0.5f , 0); +#line 1977 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = penProjectile ; +#line 1978 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 1979 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 1980 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 1982 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::BeastBigProjectileExplosion(void) +#line 1983 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 1985 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 1986 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1987 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_LIGHT_CANNON ; +#line 1988 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (2 , 2 , 2); +#line 1989 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 1992 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 1993 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 1994 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 1995 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 1996 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 1997 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 4.0f; +#line 1998 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.5f; +#line 1999 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 2000 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = en_vCurrentTranslationAbsolute / 32.0f; +#line 2001 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 2002 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 2005 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +for(INDEX iDebris = 0;iDebris < 3 + IRnd () % 2;iDebris ++) +#line 2006 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2007 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fHeading = (FRnd () - 0.5f) * 180.0f; +#line 2008 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fPitch = 10.0f + FRnd () * 40.0f; +#line 2009 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeed = 10.0 + FRnd () * 50.0f; +#line 2012 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D pl = GetPlacement (); +#line 2013 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pl . pl_OrientationAngle (1) += AngleDeg (fHeading ); +#line 2014 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pl . pl_OrientationAngle (2) += AngleDeg (fPitch ); +#line 2016 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 2017 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ELaunchProjectile eLaunch ; +#line 2018 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . penLauncher = this ; +#line 2019 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . prtType = PRT_BEAST_BIG_DEBRIS ; +#line 2020 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . fSpeed = fSpeed ; +#line 2021 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penProjectile -> Initialize (eLaunch ); +#line 2024 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = pl ; +#line 2025 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 2026 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (penProjectile ); +#line 2027 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 2028 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 2029 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 1.0f; +#line 2030 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.5f; +#line 2031 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 2032 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = FLOAT3D (0 , - 0.5f , 0); +#line 2033 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = penProjectile ; +#line 2034 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 2035 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2036 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2041 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::FishmanProjectile(void) { +#line 2043 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2044 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2045 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 2046 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 2047 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetComponents (this , * GetModelObject () , MODEL_FISHMAN_FIRE , TEXTURE_FISHMAN_FIRE , 0 , 0 , 0); +#line 2048 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2050 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2051 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2052 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 2053 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 5.0f; +#line 2054 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2055 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2056 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 2057 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2058 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2059 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2060 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2061 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2068 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::MantamanProjectile(void) { +#line 2070 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2071 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2072 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 2073 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 2074 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetComponents (this , * GetModelObject () , MODEL_MANTAMAN_FIRE , TEXTURE_MANTAMAN_FIRE , 0 , 0 , 0); +#line 2075 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2077 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 35.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2078 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2079 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 2080 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 7.0f; +#line 2081 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2082 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2083 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 2084 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2085 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2086 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2087 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2088 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2094 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::DevilLaser(void) { +#line 2096 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2097 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2098 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 2099 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 2100 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetComponents (this , * GetModelObject () , MODEL_CYBORG_LASER , TEXTURE_CYBORG_LASER , 0 , 0 , 0); +#line 2101 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (4.0f , 4.0f , 2.0f)); +#line 2102 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2104 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - DEVIL_LASER_SPEED ) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2105 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2106 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 2107 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 2108 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2109 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2110 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 2111 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2112 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2113 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2114 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2115 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2117 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::DevilRocket(void) { +#line 2119 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2120 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2121 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 2122 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_ROCKET ); +#line 2123 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_ROCKET ); +#line 2124 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (12.0f , 12.0f , 8.0f)); +#line 2125 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2127 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - DEVIL_ROCKET_SPEED ) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2128 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2130 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (100.0f , 2.0f , 1.0f , 1.0f); +#line 2131 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_FLYING , SOF_3D | SOF_LOOP ); +#line 2132 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 50.0f; +#line 2133 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 50.0f; +#line 2134 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 50.0f; +#line 2135 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 2.0f; +#line 2136 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 10.0f; +#line 2137 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 100.0f; +#line 2138 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 2139 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 2140 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = TRUE ; +#line 2141 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 2142 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 1.125f; +#line 2143 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 10000.0f; +#line 2144 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.05f; +#line 2145 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (25.0f); +#line 2146 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2147 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2149 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::DevilRocketExplosion(void) { +#line 2150 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 2151 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vPoint ; +#line 2152 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOATplane3D vPlaneNormal ; +#line 2153 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceToEdge ; +#line 2156 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 2157 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_GRENADE ; +#line 2158 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (2 , 2 , 2); +#line 2159 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 2161 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsDerivedFromClass (m_penLauncher , "Player")){ +#line 2162 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnRangeSound (m_penLauncher , this , SNDT_PLAYER , m_fSoundRange ); +#line 2163 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2166 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )){ +#line 2167 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f){ +#line 2169 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_EXPLOSIONSTAIN ; +#line 2170 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 2171 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (2 , 2 , 2); +#line 2172 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 2174 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_SHOCKWAVE ; +#line 2175 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 2176 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (2 , 2 , 2); +#line 2177 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 2179 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_GRENADE_PLANE ; +#line 2180 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 2181 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (2 , 2 , 2); +#line 2182 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint + ese . vNormal / 50.0f , ANGLE3D (0 , 0 , 0)) , ese ); +#line 2183 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2184 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2185 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2187 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::DevilGuidedProjectile(void) { +#line 2189 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsDerivedFromClass (m_penLauncher , "Enemy Base")){ +#line 2190 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penTarget = ((CEnemyBase *) & * m_penLauncher ) -> m_penEnemy ; +#line 2191 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2193 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2194 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_FREE_FLYING ); +#line 2195 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 2197 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_BEAST_FIRE ); +#line 2198 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_BEAST_BIG_FIRE ); +#line 2199 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (2.5f , 2.5f , 2.5f)); +#line 2200 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2202 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (250.0f , 2.0f , 1.0f , 0.75f); +#line 2203 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_FLYING , SOF_3D | SOF_LOOP ); +#line 2205 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 80.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2206 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2207 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 20.0f; +#line 2208 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 20.0f; +#line 2209 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2210 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2211 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 2212 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2213 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 2214 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2215 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_GUIDED ; +#line 2216 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fGuidedMaxSpeedFactor = 30.0f; +#line 2217 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (30.0f); +#line 2218 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_aRotateSpeed = 100.0f; +#line 2219 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2221 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::DevilGuidedProjectileExplosion(void) +#line 2222 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2224 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 2225 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 2226 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_LIGHT_CANNON ; +#line 2227 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (4 , 4 , 4); +#line 2228 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 2231 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 2232 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 2233 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 2234 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 2235 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 2236 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 8.0f; +#line 2237 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 1.0f; +#line 2238 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 2239 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = en_vCurrentTranslationAbsolute / 32.0f; +#line 2240 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 2241 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 2244 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +for(INDEX iDebris = 0;iDebris < 3 + IRnd () % 2;iDebris ++) +#line 2245 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2246 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fHeading = (FRnd () - 0.5f) * 180.0f; +#line 2247 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fPitch = 10.0f + FRnd () * 40.0f; +#line 2248 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeed = 10.0 + FRnd () * 50.0f; +#line 2251 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D pl = GetPlacement (); +#line 2252 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pl . pl_OrientationAngle (1) += AngleDeg (fHeading ); +#line 2253 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pl . pl_OrientationAngle (2) += AngleDeg (fPitch ); +#line 2255 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 2256 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ELaunchProjectile eLaunch ; +#line 2257 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . penLauncher = this ; +#line 2258 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . prtType = PRT_BEAST_BIG_DEBRIS ; +#line 2259 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eLaunch . fSpeed = fSpeed ; +#line 2260 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penProjectile -> Initialize (eLaunch ); +#line 2263 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = pl ; +#line 2264 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 2265 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (penProjectile ); +#line 2266 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 2267 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 2268 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 2.0f; +#line 2269 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 1.0f; +#line 2270 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 2271 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = FLOAT3D (0 , - 0.5f , 0); +#line 2272 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = penProjectile ; +#line 2273 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 2274 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2275 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2280 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::CyborgLaser(void) { +#line 2282 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2283 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2284 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 2285 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 2286 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetComponents (this , * GetModelObject () , MODEL_CYBORG_LASER , TEXTURE_CYBORG_LASER , 0 , 0 , 0); +#line 2287 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2289 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 60.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2290 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2291 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 4.0f; +#line 2292 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 5.0f; +#line 2293 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2294 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2295 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 2296 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2297 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2298 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2299 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2300 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2302 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::CyborgBomb(void) +#line 2303 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2305 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2306 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_BOUNCING ); +#line 2307 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 2308 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_CYBORG_BOMB ); +#line 2309 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_CYBORG_BOMB ); +#line 2310 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2312 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsFreeProjectile (FLOAT3D (0.0f , 0.0f , - m_fSpeed ) , (CMovableEntity *) & * m_penLauncher ); +#line 2313 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2314 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 2.5f; +#line 2315 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 2316 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 15.0f; +#line 2317 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 1.0f; +#line 2318 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 6.0f; +#line 2319 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 25.0f; +#line 2320 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 2321 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 2322 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = TRUE ; +#line 2323 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 2324 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2325 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (5.0f); +#line 2326 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2327 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2334 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::LavaBall(void) { +#line 2336 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2337 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_FALL ); +#line 2338 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 2339 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_LAVA ); +#line 2340 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_LAVA ); +#line 2341 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +AddAttachment (0 , MODEL_LAVA_FLARE , TEXTURE_LAVA_FLARE ); +#line 2344 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsFreeProjectile (FLOAT3D (0.0f , 0.0f , - m_fSpeed ) , (CMovableEntity *) & * m_penLauncher ); +#line 2345 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , FRnd () * 360.0f - 180.0f , FRnd () * 360.0f - 180.0f)); +#line 2346 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 2347 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 5.0f; +#line 2348 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 5.0f; +#line 2349 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 1.0f; +#line 2350 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 4.0f; +#line 2351 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2352 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 2353 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 2354 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2355 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2356 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2357 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2358 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2360 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::LavaBallExplosion(void) { +#line 2361 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 2362 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vPoint ; +#line 2363 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOATplane3D vPlaneNormal ; +#line 2364 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceToEdge ; +#line 2365 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )){ +#line 2366 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f){ +#line 2368 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 2369 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_SHOCKWAVE ; +#line 2370 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 2371 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 2372 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2373 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2374 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2380 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::GruntSoldierLaser(void) { +#line 2382 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2383 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2384 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 2385 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 2386 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_GRUNT_PROJECTILE ); +#line 2387 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CModelObject * pmo = GetModelObject (); +#line 2388 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(pmo != NULL ) +#line 2389 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2390 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pmo -> PlayAnim (GRUNTPROJECTILE_ANIM_DEFAULT , 0); +#line 2391 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2392 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_GRUNT_PROJECTILE_01 ); +#line 2394 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 45.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2395 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2396 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 3.0f; +#line 2397 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 2398 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2399 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2400 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 2401 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2402 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2403 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2404 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 2406 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.025f; +#line 2407 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2408 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2410 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::GruntCommanderLaser(void) { +#line 2412 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2413 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2414 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 2415 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 2416 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_GRUNT_PROJECTILE ); +#line 2417 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CModelObject * pmo = GetModelObject (); +#line 2418 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(pmo != NULL ) +#line 2419 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2420 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pmo -> PlayAnim (GRUNTPROJECTILE_ANIM_DEFAULT , 0); +#line 2421 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2422 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_GRUNT_PROJECTILE_02 ); +#line 2424 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 55.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2425 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2426 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 3.0f; +#line 2427 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 2428 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2429 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2430 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 2431 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2432 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2433 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2434 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 2436 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.025f; +#line 2437 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2438 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2445 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::GuffyProjectile(void) { +#line 2447 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2448 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2449 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 2450 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_GUFFY_PROJECTILE ); +#line 2451 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_GUFFY_PROJECTILE ); +#line 2452 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (1.0f , 1.0f , 1.0f)); +#line 2454 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CModelObject * pmo = GetModelObject (); +#line 2455 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(pmo != NULL ) +#line 2456 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2457 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +pmo -> PlayAnim (GUFFYPROJECTILE_ANIM_ROTATE01 , AOF_LOOPING ); +#line 2458 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2461 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 50.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2462 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2464 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (20.0f , 2.0f , 1.0f , 1.0f); +#line 2465 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_FLYING , SOF_3D | SOF_LOOP ); +#line 2466 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 30.0f; +#line 2467 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 2468 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 10.0f; +#line 2469 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 4.0f; +#line 2470 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 8.0f; +#line 2471 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 50.0f; +#line 2472 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 2473 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 2474 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2475 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2476 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 1.125f; +#line 2477 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 2478 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.05f; +#line 2479 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (10000.0f); +#line 2480 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2481 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2483 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::GuffyProjectileExplosion(void) { +#line 2484 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlayerRocketExplosion (); +#line 2485 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2492 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::DemonFireball(void) { +#line 2494 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsDerivedFromClass (m_penLauncher , "Enemy Base")){ +#line 2495 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penTarget = ((CEnemyBase *) & * m_penLauncher ) -> m_penEnemy ; +#line 2496 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2498 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2499 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_FREE_FLYING ); +#line 2500 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 2502 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_DEMON_FIREBALL ); +#line 2503 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_DEMON_FIREBALL ); +#line 2504 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (2.5f , 2.5f , 2.5f)); +#line 2506 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2508 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (50.0f , 2.0f , 1.0f , 0.75f); +#line 2509 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_BEAST_FLYING , SOF_3D | SOF_LOOP ); +#line 2511 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 100.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2512 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2513 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 12.0f; +#line 2514 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 20.0f; +#line 2515 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2516 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2517 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 2518 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2519 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 2520 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2521 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_GUIDED_FAST ; +#line 2522 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fGuidedMaxSpeedFactor = 90.0f; +#line 2523 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (10000.0f); +#line 2524 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_aRotateSpeed = 200.0f; +#line 2525 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2527 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::DemonFireballExplosion(void) +#line 2528 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2530 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 2531 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 2532 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_LIGHT_CANNON ; +#line 2533 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (2 , 2 , 2); +#line 2534 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 2537 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 2538 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 2539 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 2540 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 2541 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 2542 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 4.0f; +#line 2543 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.5f; +#line 2544 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 2545 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = en_vCurrentTranslationAbsolute / 32.0f; +#line 2546 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 2547 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 2548 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2554 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::LarvaPlasma(void) { +#line 2556 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2557 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2558 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 2559 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_LARVA_PLASMA_BALL ); +#line 2560 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_LARVA_PLASMA_BALL ); +#line 2561 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +AddAttachmentToModel (this , * GetModelObject () , PLASMAGUN_ATTACHMENT_PROJECTILE , +#line 2562 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +MODEL_LARVA_PLASMA , TEXTURE_LARVA_PLASMA , 0 , 0 , 0); +#line 2564 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (2.5f , 2.5f , 2.5f)); +#line 2565 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2568 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 60.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2569 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2571 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (20.0f , 2.0f , 1.0f , 1.0f); +#line 2572 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_FLYING , SOF_3D | SOF_LOOP ); +#line 2573 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 30.0f; +#line 2574 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetSP () -> sp_bCooperative ) +#line 2575 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2576 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 30.0f; +#line 2577 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 30.0f; +#line 2578 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2579 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else +#line 2580 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2581 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 25.0f; +#line 2582 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 25.0f; +#line 2583 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2584 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 4.0f; +#line 2585 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 8.0f; +#line 2586 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 50.0f; +#line 2587 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 2588 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 2589 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2590 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2591 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.05f; +#line 2592 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 2593 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.05f; +#line 2594 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (100.0f); +#line 2595 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_iRebounds = 4; +#line 2596 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING_REBOUNDING ; +#line 2597 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2599 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::LarvaPlasmaExplosion(void) { +#line 2601 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 2602 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 2603 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_LIGHT_CANNON ; +#line 2604 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (2 , 2 , 2); +#line 2605 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 2608 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 2609 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 2610 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 2611 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 2612 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 2613 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 1.0f; +#line 2614 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.25f; +#line 2615 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_PLASMA ; +#line 2616 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = FLOAT3D (0.0f , 2.5f , 0.0f); +#line 2617 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 2618 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 2619 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2621 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::LarvaTail(void) { +#line 2624 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsDerivedFromClass (m_penLauncher , "Enemy Base")){ +#line 2625 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penTarget = ((CEnemyBase *) & * m_penLauncher ) -> m_penEnemy ; +#line 2626 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2628 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2629 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_SLIDING ); +#line 2630 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 2632 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_LARVA_TAIL ); +#line 2633 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_LARVA_TAIL ); +#line 2634 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (4.0f , 4.0f , 4.0f)); +#line 2636 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2638 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (50.0f , 10.0f , 1.0f , 1.0f); +#line 2639 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_LARVETTE , SOF_3D | SOF_LOOP ); +#line 2641 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2642 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2643 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 12.0f; +#line 2644 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 2645 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2646 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2647 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 2648 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2649 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 2650 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2651 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_GUIDED_SLIDING ; +#line 2652 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_aRotateSpeed = 275.0f; +#line 2653 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (10.0f); +#line 2654 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2656 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::LarvaTailExplosion(void) { +#line 2657 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlayerRocketExplosion (); +#line 2658 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2665 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::WindBlast(void) { +#line 2667 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsEditorModel (); +#line 2668 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_SLIDING ); +#line 2669 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 2670 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 2671 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_WINDBLAST ); +#line 2672 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_WINDBLAST ); +#line 2673 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (3.0f , 3.0f , 3.0f)); +#line 2674 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2676 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 50.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2677 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2678 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 5.0f; +#line 2679 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 20.0f; +#line 2680 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2681 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2682 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 2683 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2684 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2685 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.0f; +#line 2686 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_SLIDING ; +#line 2687 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2693 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::Meteor() { +#line 2695 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2696 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2697 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 2699 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_ELEM_LAVA_BOMB ); +#line 2700 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_ELEM_LAVA_BOMB ); +#line 2704 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fStretch , m_fStretch , m_fStretch )); +#line 2705 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2707 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_AfterBurner_Prepare (this ); +#line 2710 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - m_fSpeed ) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2711 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2713 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (250.0f , 10.0f , 2.0f , 1.0f); +#line 2714 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_FLYING , SOF_3D | SOF_LOOP ); +#line 2715 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 30.0f; +#line 2716 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 100.0f; +#line 2717 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 100.0f; +#line 2718 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 15.0f; +#line 2719 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 30.0f; +#line 2720 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 100.0f; +#line 2721 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 2722 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 2723 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = TRUE ; +#line 2724 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2725 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = GetSoundLength (SOUND_METEOR_BLAST ) + 0.25f; +#line 2726 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 2727 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.05f; +#line 2728 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (100.0f); +#line 2729 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2730 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2732 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::MeteorExplosion() { +#line 2736 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 2737 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 2738 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 2739 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 2740 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 2741 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 4.0f; +#line 2742 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.5f; +#line 2743 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 2744 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = en_vCurrentTranslationAbsolute / 32.0f; +#line 2745 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 2746 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 2748 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnEffect ese ; +#line 2749 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vPoint ; +#line 2750 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOATplane3D vPlaneNormal ; +#line 2751 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceToEdge ; +#line 2754 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 2755 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_CANNON ; +#line 2756 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vStretch = FLOAT3D (5 , 5 , 5); +#line 2757 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 2759 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsDerivedFromClass (m_penLauncher , "Player")){ +#line 2760 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnRangeSound (m_penLauncher , this , SNDT_PLAYER , m_fSoundRange ); +#line 2761 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2764 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_EXPLOSION_DEBRIS ; +#line 2765 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 2768 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_EXPLOSION_SMOKE ; +#line 2769 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (GetPlacement () , ese ); +#line 2772 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetNearestPolygon (vPoint , vPlaneNormal , fDistanceToEdge )){ +#line 2773 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((vPoint - GetPlacement () . pl_PositionVector ) . Length () < 3.5f){ +#line 2775 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_EXPLOSIONSTAIN ; +#line 2776 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 2777 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 2779 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_SHOCKWAVE ; +#line 2780 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 2781 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint , ANGLE3D (0 , 0 , 0)) , ese ); +#line 2783 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . betType = BET_ROCKET_PLANE ; +#line 2784 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ese . vNormal = FLOAT3D (vPlaneNormal ); +#line 2785 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnEffect (CPlacement3D (vPoint + ese . vNormal / 50.0f , ANGLE3D (0 , 0 , 0)) , ese ); +#line 2786 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2787 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2788 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soExplosion . Set3DParameters (150.0f , 10.0f , 1.5f , 1.0f); +#line 2789 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soExplosion , SOUND_METEOR_BLAST , SOF_3D ); +#line 2790 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2797 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::ShooterWoodenDart(void) { +#line 2799 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2800 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2801 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 2802 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_SHTR_WOODEN_DART ); +#line 2803 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEX_SHTR_WOODEN_DART ); +#line 2806 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2807 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2811 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 10.0f; +#line 2812 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetSP () -> sp_gdGameDifficulty <= CSessionProperties :: GD_EASY ){ +#line 2813 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 5.0f; +#line 2814 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 2815 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 10.0f; +#line 2816 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2817 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2818 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 2819 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2820 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 2821 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 1.125f; +#line 2822 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 2823 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.05f; +#line 2824 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (5.0f); +#line 2825 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2826 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2828 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::ShooterWoodenDartExplosion() { +#line 2830 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 2831 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 2832 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 2833 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 2834 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 2835 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 0.5f; +#line 2836 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.1f; +#line 2837 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_WOOD ; +#line 2838 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = - en_vCurrentTranslationAbsolute / 32.0f; +#line 2839 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 2840 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 2841 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2843 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::ShooterFireball(void) { +#line 2845 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2846 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2847 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 2848 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_BEAST_FIRE ); +#line 2849 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_BEAST_BIG_FIRE ); +#line 2850 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetModelObject () -> StretchModel (FLOAT3D (0.25f , 0.25f , 0.25f)); +#line 2851 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ModelChangeNotify (); +#line 2854 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2855 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2859 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 10.0f; +#line 2860 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(GetSP () -> sp_gdGameDifficulty <= CSessionProperties :: GD_EASY ){ +#line 2861 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 7.5f; +#line 2862 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 2863 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 15.0f; +#line 2864 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2865 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2866 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 2867 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2868 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = TRUE ; +#line 2869 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.125f; +#line 2870 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmExpandBox = 0.1f; +#line 2871 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_tmInvisibility = 0.05f; +#line 2872 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetHealth (5.0f); +#line 2873 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2874 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2876 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::ShooterFireballExplosion() { +#line 2878 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CPlacement3D plSpray = GetPlacement (); +#line 2879 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 2880 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> SetParent (this ); +#line 2881 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESpawnSpray eSpawnSpray ; +#line 2882 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 2883 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fDamagePower = 1.0f; +#line 2884 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . fSizeMultiplier = 0.5f; +#line 2885 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . sptType = SPT_LAVA_STONES ; +#line 2886 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . vDirection = - en_vCurrentTranslationAbsolute / 32.0f; +#line 2887 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSpawnSpray . penOwner = this ; +#line 2888 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penSpray -> Initialize (eSpawnSpray ); +#line 2889 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2891 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::ShooterFlame(void) { +#line 2893 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsModel (); +#line 2894 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_PROJECTILE_FLYING ); +#line 2895 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_SOLID ); +#line 2896 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 2897 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_FLAME ); +#line 2899 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 10.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 2900 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , 0 , 0)); +#line 2901 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 1.0f; +#line 2902 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 3.0f; +#line 2903 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2904 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = FALSE ; +#line 2905 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = TRUE ; +#line 2906 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2907 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2908 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 0.3f; +#line 2909 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2910 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2912 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::AfterburnerDebris(void) +#line 2913 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2914 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_AfterBurner_Prepare (this ); +#line 2916 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InitAsEditorModel (); +#line 2917 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPhysicsFlags (EPF_MODEL_FALL ); +#line 2918 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 2919 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModel (MODEL_MARKER ); +#line 2920 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 2922 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +LaunchAsFreeProjectile (FLOAT3D (0.0f , 0.0f , - m_fSpeed ) , (CMovableEntity *) & * m_penLauncher ); +#line 2923 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (0 , FRnd () * 360.0f - 180.0f , FRnd () * 360.0f - 180.0f)); +#line 2924 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = 10.0f; +#line 2925 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageAmount = 0.0f; +#line 2926 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fRangeDamageAmount = 0.0f; +#line 2927 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageHotSpotRange = 0.0f; +#line 2928 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fDamageFallOffRange = 0.0f; +#line 2929 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSoundRange = 0.0f; +#line 2930 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bExplode = TRUE ; +#line 2931 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLightSource = FALSE ; +#line 2932 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanHitHimself = FALSE ; +#line 2933 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bCanBeDestroyed = FALSE ; +#line 2934 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fWaitAfterDeath = 2.0f; +#line 2935 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_pmtMove = PMT_FLYING ; +#line 2936 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 2944 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::ProjectileTouch(CEntityPointer penHit) +#line 2945 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2947 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileHit (); +#line 2950 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDirection ; +#line 2951 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fTransLen = en_vIntendedTranslation . Length (); +#line 2952 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(fTransLen > 0.5f) +#line 2953 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2954 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +vDirection = en_vIntendedTranslation / fTransLen ; +#line 2955 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2956 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else +#line 2957 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2958 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +vDirection = - en_vGravityDir ; +#line 2959 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2962 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +const FLOAT fDamageMul = GetSeriousDamageMultiplier (m_penLauncher ); +#line 2963 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if((m_prtType == PRT_FLAME || m_prtType == PRT_SHOOTER_FLAME ) && m_fWaitAfterDeath > 0.0f){ +#line 2965 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_penLastDamaged == penHit ){ +#line 2966 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return ; +#line 2967 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 2968 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penLastDamaged = penHit ; +#line 2969 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2972 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bSpawnFlame = TRUE ; +#line 2973 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bInflictDamage = TRUE ; +#line 2974 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(IsOfClass (penHit , "AirElemental")) +#line 2975 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2976 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bSpawnFlame = FALSE ; +#line 2977 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2979 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +EntityInfo * pei = (EntityInfo *) penHit -> GetEntityInfo (); +#line 2980 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(pei != NULL && pei -> Eeibt == EIBT_ICE ) +#line 2981 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2982 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bSpawnFlame = FALSE ; +#line 2983 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bInflictDamage = FALSE ; +#line 2984 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2986 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bSpawnFlame ) +#line 2987 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2988 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnFlame (m_penLauncher , penHit , GetPlacement () . pl_PositionVector ); +#line 2989 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2990 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bInflictDamage ) +#line 2991 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 2992 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InflictDirectDamage (penHit , m_penLauncher , DMT_BURNING , m_fDamageAmount * fDamageMul , +#line 2993 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetPlacement () . pl_PositionVector , vDirection ); +#line 2994 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 2997 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else if(m_prtType == PRT_AIRELEMENTAL_WIND ){ +#line 2998 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(penHit == m_penLastDamaged ){ +#line 2999 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return ; +#line 3000 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 3001 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penLastDamaged = penHit ; +#line 3002 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3003 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InflictDirectDamage (penHit , m_penLauncher , DMT_PROJECTILE , m_fDamageAmount * fDamageMul , +#line 3004 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetPlacement () . pl_PositionVector , vDirection ); +#line 3007 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 3008 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InflictDirectDamage (penHit , m_penLauncher , DMT_PROJECTILE , m_fDamageAmount * fDamageMul , +#line 3009 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetPlacement () . pl_PositionVector , vDirection ); +#line 3010 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3011 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 3015 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::ProjectileHit(void) +#line 3016 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3018 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_bExplode ){ +#line 3019 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +const FLOAT fDamageMul = GetSeriousDamageMultiplier (m_penLauncher ); +#line 3020 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +InflictRangeDamage (m_penLauncher , DMT_EXPLOSION , m_fRangeDamageAmount * fDamageMul , +#line 3021 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetPlacement () . pl_PositionVector , m_fDamageHotSpotRange , m_fDamageFallOffRange ); +#line 3022 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3024 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_fSoundRange > 0.0f && IsDerivedFromClass (m_penLauncher , "Player")) +#line 3025 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3026 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ESound eSound ; +#line 3027 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSound . EsndtSound = SNDT_EXPLOSION ; +#line 3028 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +eSound . penTarget = m_penLauncher ; +#line 3029 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SendEventInRange (eSound , FLOATaabbox3D (GetPlacement () . pl_PositionVector , m_fSoundRange )); +#line 3030 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3031 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 3035 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::SpawnEffect(const CPlacement3D & plEffect,const ESpawnEffect & eSpawnEffect) { +#line 3036 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntityPointer penEffect = CreateEntity (plEffect , CLASS_BASIC_EFFECT ); +#line 3037 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +penEffect -> Initialize (eSpawnEffect ); +#line 3038 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 3045 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::BounceSound(void) { +#line 3046 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +switch(m_prtType ){ +#line 3047 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GRENADE : +#line 3048 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(en_vCurrentTranslationAbsolute . Length () > 3.0f){ +#line 3049 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_soEffect . Set3DParameters (20.0f , 2.0f , 1.0f , 1.0f); +#line 3050 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +PlaySound (m_soEffect , SOUND_GRENADE_BOUNCE , SOF_3D ); +#line 3051 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3052 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 3053 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3054 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 3059 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE CProjectile::GetRotationSpeed(ANGLE aWantedAngle,ANGLE aRotateSpeed,FLOAT fWaitFrequency) +#line 3060 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3061 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE aResult ; +#line 3063 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(aWantedAngle < - aRotateSpeed * fWaitFrequency ) +#line 3064 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3066 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +aResult = - aRotateSpeed ; +#line 3067 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3069 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else if(aWantedAngle > aRotateSpeed * fWaitFrequency ) +#line 3070 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3072 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +aResult = + aRotateSpeed ; +#line 3073 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3075 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else +#line 3076 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3077 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +aResult = aWantedAngle / fWaitFrequency ; +#line 3078 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3079 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return aResult ; +#line 3080 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} + +#line 3084 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CProjectile::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 3085 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 3086 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3089 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_prtType == PRT_DEMON_FIREBALL && dmtType == DMT_CANNONBALL ) +#line 3090 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3091 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fDamageAmmount *= 10001.0f; +#line 3092 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3093 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_prtType == PRT_FLAME && IsOfClass (penInflictor , "Moving Brush")) +#line 3094 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3095 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Destroy (); +#line 3096 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3098 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CMovableModelEntity :: ReceiveDamage (penInflictor , +#line 3099 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 3100 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +BOOL CProjectile:: +#line 3107 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileFly(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CProjectile_ProjectileFly + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CProjectile::ProjectileFly expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3109 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntity * penObstacle ; +#line 3110 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(CheckForCollisionNow (0 , & penObstacle )){ +#line 3112 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (penObstacle ); +#line 3117 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3117 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3118 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3120 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetTimerAfter(m_fFlyTime ); +Jump(STATE_CURRENT, 0x01f50002, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f50002_ProjectileFly_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50002 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&epass= (EPass&)__eeInput; + +#line 3123 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bHit ; +#line 3125 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = epass . penOther != m_penLauncher || _pTimer -> CurrentTick () > m_fIgnoreTime ; +#line 3127 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! ((! m_bCanHitHimself && IsOfClass (epass . penOther , "Projectile") && +#line 3128 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CProjectile *) & * epass . penOther ) -> m_prtType == m_prtType )); +#line 3130 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! IsOfClass (epass . penOther , "Twister"); +#line 3131 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bHit ){ +#line 3132 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (epass . penOther ); +#line 3135 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50003, FALSE, EInternal());return TRUE; +#line 3136 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3137 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3138 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 3141 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fIgnoreTime = 0.0f; +#line 3143 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bHit ; +#line 3144 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = ! ((! m_bCanHitHimself && IsOfClass (etouch . penOther , "Projectile") && +#line 3145 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CProjectile *) & * etouch . penOther ) -> m_prtType == m_prtType )); +#line 3147 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bHit ){ +#line 3148 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (etouch . penOther ); +#line 3149 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50003, FALSE, EInternal());return TRUE; +#line 3150 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3151 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3152 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; + +#line 3154 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_bCanBeDestroyed ){ +#line 3155 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileHit (); +#line 3156 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50003, FALSE, EInternal());return TRUE; +#line 3157 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3158 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3159 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; + +#line 3161 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileHit (); +#line 3162 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50003, FALSE, EInternal());return TRUE; +#line 3163 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 3164 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}return TRUE;}BOOL CProjectile::H0x01f50003_ProjectileFly_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50003 + +#line 3165 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3165 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CProjectile:: +#line 3169 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileGuidedFly(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CProjectile_ProjectileGuidedFly + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CProjectile::ProjectileGuidedFly expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3171 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntity * penObstacle ; +#line 3172 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(CheckForCollisionNow (0 , & penObstacle )){ +#line 3174 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (penObstacle ); +#line 3175 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3175 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3176 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3178 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Jump(STATE_CURRENT,0x01f50007, FALSE, EInternal());return TRUE;}BOOL CProjectile::H0x01f50007_ProjectileGuidedFly_03(const CEntityEvent &__eeInput) +#line 3179 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50007 +if(!(_pTimer -> CurrentTick () < (m_fStartTime + m_fFlyTime ))){ Jump(STATE_CURRENT,0x01f50008, FALSE, EInternal());return TRUE;} +#line 3180 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fWaitFrequency = 0.1f; +#line 3188 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_penTarget != NULL ){ +#line 3190 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +EntityInfo * pei = (EntityInfo *) (m_penTarget -> GetEntityInfo ()); +#line 3191 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDesiredPosition ; +#line 3192 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetEntityInfoPosition (m_penTarget , pei -> vSourceCenter , vDesiredPosition ); +#line 3193 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDesiredDirection = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Normalize (); +#line 3195 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE aWantedHeading = GetRelativeHeading (vDesiredDirection ); +#line 3200 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE aHeading = GetRotationSpeed (aWantedHeading , m_aRotateSpeed , fWaitFrequency ); +#line 3203 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeedDecreasingFactor = ((180 - Abs (aWantedHeading )) / 180.0f); +#line 3205 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeedIncreasingFactor = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Length () / 100; +#line 3206 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fSpeedIncreasingFactor = ClampDn (fSpeedIncreasingFactor , 1.0f); +#line 3208 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fMaxSpeed = m_fGuidedMaxSpeedFactor * fSpeedIncreasingFactor ; +#line 3209 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fMinSpeedRatio = 0.5f; +#line 3210 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fWantedSpeed = fMaxSpeed * (fMinSpeedRatio + (1 - fMinSpeedRatio ) * fSpeedDecreasingFactor ); +#line 3212 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredTranslation (FLOAT3D (0 , 0 , - fWantedSpeed )); +#line 3215 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_aRotateSpeed = 75.0f * (1 + 0.5f * fSpeedDecreasingFactor ); +#line 3218 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceFactor = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Length () / 50.0; +#line 3219 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fDistanceFactor = ClampUp (fDistanceFactor , 4.0f); +#line 3220 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fRNDHeading = (FRnd () - 0.5f) * 180 * fDistanceFactor ; +#line 3221 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fRNDPitch = (FRnd () - 0.5f) * 90 * fDistanceFactor ; +#line 3224 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(Abs (aWantedHeading ) < 30.0f) +#line 3225 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3227 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE aWantedPitch = GetRelativePitch (vDesiredDirection ); +#line 3228 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE aPitch = GetRotationSpeed (aWantedPitch , m_aRotateSpeed * 1.5f , fWaitFrequency ); +#line 3230 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (aHeading + fRNDHeading , aPitch + fRNDPitch , 0)); +#line 3231 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3233 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else +#line 3234 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3235 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (aHeading , fDistanceFactor * 40 , 0)); +#line 3236 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3237 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3239 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetTimerAfter(fWaitFrequency ); +Jump(STATE_CURRENT, 0x01f50005, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f50005_ProjectileGuidedFly_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50005 +switch(__eeInput.ee_slEvent) +#line 3240 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&epass= (EPass&)__eeInput; + +#line 3243 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bHit ; +#line 3245 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = epass . penOther != m_penLauncher || _pTimer -> CurrentTick () > m_fIgnoreTime ; +#line 3247 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! ((! m_bCanHitHimself && IsOfClass (epass . penOther , "Projectile") && +#line 3248 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CProjectile *) & * epass . penOther ) -> m_prtType == m_prtType )); +#line 3250 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! IsOfClass (epass . penOther , "Twister"); +#line 3251 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bHit ){ +#line 3252 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (epass . penOther ); +#line 3253 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3253 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3254 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3255 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3256 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath): +#line 3258 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{const EDeath&e= (EDeath&)__eeInput; + +#line 3259 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_bCanBeDestroyed ) +#line 3260 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3261 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileHit (); +#line 3262 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3262 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3263 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3264 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3265 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer): +#line 3267 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{const ETimer&e= (ETimer&)__eeInput; + +#line 3268 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50006, FALSE, EInternal());return TRUE; +#line 3269 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 3270 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}return TRUE;}BOOL CProjectile::H0x01f50006_ProjectileGuidedFly_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50006 +Jump(STATE_CURRENT,0x01f50007, FALSE, EInternal());return TRUE; +#line 3271 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}BOOL CProjectile::H0x01f50008_ProjectileGuidedFly_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50008 + +#line 3272 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3272 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CProjectile:: +#line 3275 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileGuidedFastFly(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CProjectile_ProjectileGuidedFastFly + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CProjectile::ProjectileGuidedFastFly expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3277 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntity * penObstacle ; +#line 3278 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(CheckForCollisionNow (0 , & penObstacle )){ +#line 3280 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (penObstacle ); +#line 3281 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3281 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3282 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3284 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Jump(STATE_CURRENT,0x01f5000c, FALSE, EInternal());return TRUE;}BOOL CProjectile::H0x01f5000c_ProjectileGuidedFastFly_03(const CEntityEvent &__eeInput) +#line 3285 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5000c +if(!(_pTimer -> CurrentTick () < (m_fStartTime + m_fFlyTime ))){ Jump(STATE_CURRENT,0x01f5000d, FALSE, EInternal());return TRUE;} +#line 3286 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fWaitFrequency = 0.1f; +#line 3288 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_prtType == PRT_BEAST_BIG_PROJECTILE && +#line 3289 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +DistanceTo (this , m_penTarget ) < 20.0f && +#line 3290 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +(m_fStartTime + m_fFlyTime - _pTimer -> CurrentTick ()) > 1.5f) +#line 3291 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3292 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fFlyTime = _pTimer -> CurrentTick () - m_fStartTime + 1.5f; +#line 3293 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3294 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_penTarget != NULL ){ +#line 3296 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +EntityInfo * pei = (EntityInfo *) (m_penTarget -> GetEntityInfo ()); +#line 3297 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDesiredPosition ; +#line 3298 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetEntityInfoPosition (m_penTarget , pei -> vSourceCenter , vDesiredPosition ); +#line 3299 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDesiredDirection = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Normalize (); +#line 3301 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE aWantedHeading = GetRelativeHeading (vDesiredDirection ); +#line 3302 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE aHeading = GetRotationSpeed (aWantedHeading , 5.0f , fWaitFrequency ); +#line 3305 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeedDecreasingFactor = ((180 - Abs (aWantedHeading )) / 180.0f); +#line 3307 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeedIncreasingFactor = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Length () / 100; +#line 3308 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fSpeedIncreasingFactor = ClampDn (fSpeedIncreasingFactor , 1.0f); +#line 3310 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fMaxSpeed = m_fGuidedMaxSpeedFactor * fSpeedIncreasingFactor ; +#line 3311 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fMinSpeedRatio = 10.0f; +#line 3312 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fWantedSpeed = fMaxSpeed * (fMinSpeedRatio + (1 - fMinSpeedRatio ) * fSpeedDecreasingFactor ); +#line 3314 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredTranslation (FLOAT3D (0 , 0 , - fWantedSpeed )); +#line 3317 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_aRotateSpeed = 110.0f * (1 + 0.5f * fSpeedDecreasingFactor ); +#line 3320 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceFactor = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Length () / 50.0; +#line 3321 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fDistanceFactor = ClampUp (fDistanceFactor , 4.0f); +#line 3324 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(Abs (aWantedHeading ) < 30.0f) +#line 3325 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3326 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bLockedOn = TRUE ; +#line 3328 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE aWantedPitch = GetRelativePitch (vDesiredDirection ); +#line 3329 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE aPitch = GetRotationSpeed (aWantedPitch , m_aRotateSpeed * 1.5f , fWaitFrequency ); +#line 3331 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (aHeading , aPitch , 0)); +#line 3332 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3334 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else +#line 3335 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3336 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bLockedOn ) +#line 3337 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3338 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE3D aBankingUp ; +#line 3339 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +aBankingUp = GetPlacement () . pl_OrientationAngle ; +#line 3340 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +aBankingUp (3) = 0.0f; +#line 3341 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPlacement (CPlacement3D (GetPlacement () . pl_PositionVector , aBankingUp )); +#line 3342 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3343 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bLockedOn = FALSE ; +#line 3345 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (aHeading , 400 , 0)); +#line 3346 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3347 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3349 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetTimerAfter(fWaitFrequency ); +Jump(STATE_CURRENT, 0x01f5000a, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f5000a_ProjectileGuidedFastFly_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5000a +switch(__eeInput.ee_slEvent) +#line 3350 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 3354 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fIgnoreTime = 0.0f; +#line 3356 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bHit ; +#line 3357 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = ! ((! m_bCanHitHimself && IsOfClass (etouch . penOther , "Projectile") && +#line 3358 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CProjectile *) & * etouch . penOther ) -> m_prtType == m_prtType )); +#line 3359 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! IsOfClass (etouch . penOther , "Demon"); +#line 3360 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vTrans = en_vCurrentTranslationAbsolute ; +#line 3361 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= Abs (vTrans . Normalize () % FLOAT3D (etouch . plCollision )) > 0.35; +#line 3363 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bHit ){ +#line 3364 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (etouch . penOther ); +#line 3365 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3365 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3366 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3368 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3369 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&epass= (EPass&)__eeInput; + +#line 3371 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bHit ; +#line 3373 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = epass . penOther != m_penLauncher || _pTimer -> CurrentTick () > m_fIgnoreTime ; +#line 3375 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! ((! m_bCanHitHimself && IsOfClass (epass . penOther , "Projectile") && +#line 3376 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CProjectile *) & * epass . penOther ) -> m_prtType == m_prtType )); +#line 3378 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! IsOfClass (epass . penOther , "Twister"); +#line 3380 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! (m_prtType == PRT_DEMON_FIREBALL && IsOfClass (epass . penOther , "Projectile")); +#line 3381 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! (m_prtType == PRT_BEAST_BIG_PROJECTILE && IsOfClass (epass . penOther , "Projectile")); +#line 3383 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bHit ){ +#line 3384 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (epass . penOther ); +#line 3385 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3385 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3386 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3387 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3388 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath): +#line 3390 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{const EDeath&e= (EDeath&)__eeInput; + +#line 3391 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_bCanBeDestroyed ) +#line 3392 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3393 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileHit (); +#line 3394 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3394 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3395 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3396 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3397 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer): +#line 3399 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{const ETimer&e= (ETimer&)__eeInput; + +#line 3400 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f5000b, FALSE, EInternal());return TRUE; +#line 3401 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 3402 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}return TRUE;}BOOL CProjectile::H0x01f5000b_ProjectileGuidedFastFly_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5000b +Jump(STATE_CURRENT,0x01f5000c, FALSE, EInternal());return TRUE; +#line 3403 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}BOOL CProjectile::H0x01f5000d_ProjectileGuidedFastFly_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5000d + +#line 3404 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3404 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CProjectile:: +#line 3408 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileGuidedSlide(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CProjectile_ProjectileGuidedSlide + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CProjectile::ProjectileGuidedSlide expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3410 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntity * penObstacle ; +#line 3411 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(CheckForCollisionNow (0 , & penObstacle )){ +#line 3413 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (penObstacle ); +#line 3414 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3414 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3415 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3417 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Jump(STATE_CURRENT,0x01f50011, FALSE, EInternal());return TRUE;}BOOL CProjectile::H0x01f50011_ProjectileGuidedSlide_03(const CEntityEvent &__eeInput) +#line 3418 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50011 +if(!(_pTimer -> CurrentTick () < (m_fStartTime + m_fFlyTime ))){ Jump(STATE_CURRENT,0x01f50012, FALSE, EInternal());return TRUE;} +#line 3419 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fWaitFrequency = 0.1f; +#line 3420 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_penTarget != NULL ){ +#line 3422 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +EntityInfo * pei = (EntityInfo *) (m_penTarget -> GetEntityInfo ()); +#line 3423 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDesiredPosition ; +#line 3424 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +GetEntityInfoPosition (m_penTarget , pei -> vSourceCenter , vDesiredPosition ); +#line 3425 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT3D vDesiredDirection = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Normalize (); +#line 3427 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE aWantedHeading = GetRelativeHeading (vDesiredDirection ); +#line 3428 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE aHeading = GetRotationSpeed (aWantedHeading , m_aRotateSpeed , fWaitFrequency ); +#line 3431 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeedDecreasingFactor = ((180 - Abs (aWantedHeading )) / 180.0f); +#line 3433 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fSpeedIncreasingFactor = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Length () / 100; +#line 3434 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fSpeedIncreasingFactor = ClampDn (fSpeedIncreasingFactor , 1.0f); +#line 3436 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fMaxSpeed = 30.0f * fSpeedIncreasingFactor ; +#line 3437 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fMinSpeedRatio = 0.5f; +#line 3438 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fWantedSpeed = fMaxSpeed * (fMinSpeedRatio + (1 - fMinSpeedRatio ) * fSpeedDecreasingFactor ); +#line 3440 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredTranslation (FLOAT3D (0 , 0 , - fWantedSpeed )); +#line 3443 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_aRotateSpeed = 75.0f * (1 + 0.5f * fSpeedDecreasingFactor ); +#line 3446 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDistanceFactor = (vDesiredPosition - GetPlacement () . pl_PositionVector ) . Length () / 50.0; +#line 3447 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +fDistanceFactor = ClampUp (fDistanceFactor , 4.0f); +#line 3448 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fRNDHeading = (FRnd () - 0.5f) * 180 * fDistanceFactor ; +#line 3451 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(Abs (aWantedHeading ) < 30.0f) +#line 3452 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3454 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (aHeading + fRNDHeading , 0 , 0)); +#line 3455 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3457 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +else +#line 3458 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3459 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetDesiredRotation (ANGLE3D (aHeading , 0 , 0)); +#line 3460 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3461 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3463 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetTimerAfter(fWaitFrequency ); +Jump(STATE_CURRENT, 0x01f5000f, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f5000f_ProjectileGuidedSlide_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5000f +switch(__eeInput.ee_slEvent) +#line 3464 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&epass= (EPass&)__eeInput; + +#line 3467 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bHit ; +#line 3469 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = epass . penOther != m_penLauncher || _pTimer -> CurrentTick () > m_fIgnoreTime ; +#line 3471 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! ((! m_bCanHitHimself && IsOfClass (epass . penOther , "Projectile") && +#line 3472 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CProjectile *) & * epass . penOther ) -> m_prtType == m_prtType )); +#line 3474 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! IsOfClass (epass . penOther , "Twister"); +#line 3475 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bHit ){ +#line 3476 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (epass . penOther ); +#line 3477 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3477 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3478 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3479 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3480 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath): +#line 3482 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{const EDeath&e= (EDeath&)__eeInput; + +#line 3483 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_bCanBeDestroyed ) +#line 3484 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3485 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileHit (); +#line 3486 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3486 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3487 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3488 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3489 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer): +#line 3491 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{const ETimer&e= (ETimer&)__eeInput; + +#line 3492 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50010, FALSE, EInternal());return TRUE; +#line 3493 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 3494 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}return TRUE;}BOOL CProjectile::H0x01f50010_ProjectileGuidedSlide_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50010 +Jump(STATE_CURRENT,0x01f50011, FALSE, EInternal());return TRUE; +#line 3495 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}BOOL CProjectile::H0x01f50012_ProjectileGuidedSlide_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50012 + +#line 3496 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3496 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CProjectile:: +#line 3500 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileSlide(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CProjectile_ProjectileSlide + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CProjectile::ProjectileSlide expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3502 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntity * penObstacle ; +#line 3503 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(CheckForCollisionNow (0 , & penObstacle )){ +#line 3505 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (penObstacle ); +#line 3506 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3506 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3507 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3509 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetTimerAfter(m_fFlyTime ); +Jump(STATE_CURRENT, 0x01f50014, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f50014_ProjectileSlide_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50014 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&epass= (EPass&)__eeInput; + +#line 3512 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bHit ; +#line 3514 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = epass . penOther != m_penLauncher || _pTimer -> CurrentTick () > m_fIgnoreTime ; +#line 3516 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! ((! m_bCanHitHimself && IsOfClass (epass . penOther , "Projectile") && +#line 3517 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CProjectile *) & * epass . penOther ) -> m_prtType == m_prtType )); +#line 3519 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! IsOfClass (epass . penOther , "Twister"); +#line 3520 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(epass . penOther != m_penLauncher ){ +#line 3521 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = bHit ; +#line 3522 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3523 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bHit ){ +#line 3524 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (epass . penOther ); +#line 3526 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_prtType == PRT_FLAME && IsDerivedFromClass ((CEntity *) & * (epass . penOther ) , "Enemy Base")){ +#line 3527 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3528 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3530 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_prtType == PRT_AIRELEMENTAL_WIND && IsDerivedFromClass ((CEntity *) & * (epass . penOther ) , "MovableEntity")){ +#line 3531 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3532 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3534 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50015, FALSE, EInternal());return TRUE; +#line 3535 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3536 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3537 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 3540 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fIgnoreTime = 0.0f; +#line 3542 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bHit ; +#line 3543 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = ! (etouch . penOther -> GetRenderType () & RT_BRUSH ); +#line 3544 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_prtType == PRT_FLAME && ! bHit && ! m_bLeftFlame ) +#line 3545 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3546 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SpawnFlame (m_penLauncher , etouch . penOther , GetPlacement () . pl_PositionVector ); +#line 3547 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_bLeftFlame = TRUE ; +#line 3548 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3549 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(! bHit ){BounceSound ();} +#line 3551 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! ((! m_bCanHitHimself && IsOfClass (etouch . penOther , "Projectile") && +#line 3552 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CProjectile *) & * etouch . penOther ) -> m_prtType == m_prtType )); +#line 3553 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bHit ){ +#line 3554 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (etouch . penOther ); +#line 3555 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50015, FALSE, EInternal());return TRUE; +#line 3556 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3558 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(en_vCurrentTranslationAbsolute . Length () < 0.25f * en_vDesiredTranslationRelative . Length ()){ +#line 3559 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileHit (); +#line 3560 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50015, FALSE, EInternal());return TRUE; +#line 3561 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3562 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3563 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; + +#line 3565 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_bCanBeDestroyed ){ +#line 3566 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileHit (); +#line 3567 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50015, FALSE, EInternal());return TRUE; +#line 3568 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3569 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3570 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; + +#line 3572 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileHit (); +#line 3573 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50015, FALSE, EInternal());return TRUE; +#line 3574 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 3575 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}return TRUE;}BOOL CProjectile::H0x01f50015_ProjectileSlide_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50015 + +#line 3576 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3576 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CProjectile:: +#line 3580 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileFlyRebounding(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CProjectile_ProjectileFlyRebounding + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CProjectile::ProjectileFlyRebounding expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 3582 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CEntity * penObstacle ; +#line 3583 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(CheckForCollisionNow (0 , & penObstacle )){ +#line 3585 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (penObstacle ); +#line 3586 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3586 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3587 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3589 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetTimerAfter(m_fFlyTime ); +Jump(STATE_CURRENT, 0x01f50017, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f50017_ProjectileFlyRebounding_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50017 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&epass= (EPass&)__eeInput; + +#line 3592 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bHit ; +#line 3594 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = epass . penOther != m_penLauncher || _pTimer -> CurrentTick () > m_fIgnoreTime ; +#line 3596 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! ((! m_bCanHitHimself && IsOfClass (epass . penOther , "Projectile") && +#line 3597 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CProjectile *) & * epass . penOther ) -> m_prtType == m_prtType )); +#line 3599 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit &= ! IsOfClass (epass . penOther , "Twister"); +#line 3600 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bHit ){ +#line 3601 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (epass . penOther ); +#line 3602 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50018, FALSE, EInternal());return TRUE; +#line 3603 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3604 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3605 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 3608 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fIgnoreTime = 0.0f; +#line 3610 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL bHit ; +#line 3613 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = (etouch . penOther -> GetRenderType () == RT_BRUSH ); +#line 3615 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bHit && m_iRebounds > 0){ +#line 3617 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ReflectDirectionVectorByPlane (etouch . plCollision , en_vCurrentTranslationAbsolute ); +#line 3618 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ReflectRotationMatrixByPlane_cols (etouch . plCollision , en_mRotation ); +#line 3619 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_iRebounds --; +#line 3620 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}else { +#line 3622 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +bHit = ! ((! m_bCanHitHimself && IsOfClass (etouch . penOther , "Projectile") && +#line 3623 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +((CProjectile *) & * etouch . penOther ) -> m_prtType == m_prtType )); +#line 3625 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(bHit ){ +#line 3626 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileTouch (etouch . penOther ); +#line 3627 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50018, FALSE, EInternal());return TRUE; +#line 3628 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3629 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3630 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3631 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; + +#line 3633 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_bCanBeDestroyed ){ +#line 3634 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileHit (); +#line 3635 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50018, FALSE, EInternal());return TRUE; +#line 3636 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3637 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; +#line 3638 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; + +#line 3640 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileHit (); +#line 3641 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +UnsetTimer();Jump(STATE_CURRENT,0x01f50018, FALSE, EInternal());return TRUE; +#line 3642 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 3643 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +}return TRUE;}BOOL CProjectile::H0x01f50018_ProjectileFlyRebounding_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50018 + +#line 3644 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EEnd ()); +#line 3644 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CProjectile:: +#line 3648 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CProjectile_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_ELaunchProjectile, "CProjectile::Main expects 'ELaunchProjectile' as input!"); const ELaunchProjectile &eLaunch = (const ELaunchProjectile &)__eeInput; +#line 3650 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ASSERT (eLaunch . penLauncher != NULL ); +#line 3651 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penLauncher = eLaunch . penLauncher ; +#line 3652 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_prtType = eLaunch . prtType ; +#line 3653 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fSpeed = eLaunch . fSpeed ; +#line 3654 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fStretch = eLaunch . fStretch ; +#line 3655 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetPredictable (TRUE ); +#line 3657 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fIgnoreTime = _pTimer -> CurrentTick () + 1.0f; +#line 3658 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_penLastDamaged = NULL ; +#line 3660 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +switch(m_prtType ){ +#line 3661 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEVIL_ROCKET : +#line 3662 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_WALKER_ROCKET : +#line 3663 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_ROCKET : +#line 3664 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_WOODEN_DART : +#line 3665 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3666 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_RocketTrail_Prepare (this ); +#line 3667 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 3668 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3669 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GUFFY_PROJECTILE : break ; +#line 3670 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GRENADE : Particles_GrenadeTrail_Prepare (this );break ; +#line 3671 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_CATMAN_FIRE : Particles_RocketTrail_Prepare (this );break ; +#line 3672 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_FIRECRACKER : Particles_FirecrackerTrail_Prepare (this );break ; +#line 3673 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_ROCKETMAN : Particles_Fireball01Trail_Prepare (this );break ; +#line 3674 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_BOMBERMAN : Particles_BombTrail_Prepare (this );break ; +#line 3675 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVA_COMET : Particles_LavaTrail_Prepare (this );break ; +#line 3676 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVAMAN_BIG_BOMB : Particles_LavaBombTrail_Prepare (this );break ; +#line 3677 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVAMAN_BOMB : Particles_LavaBombTrail_Prepare (this );break ; +#line 3678 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_PROJECTILE : Particles_Fireball01Trail_Prepare (this );break ; +#line 3679 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_BIG_PROJECTILE : +#line 3680 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEVIL_GUIDED_PROJECTILE : +#line 3681 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEMON_FIREBALL : +#line 3683 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Particles_FirecrackerTrail_Prepare (this ); +#line 3684 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +break ; +#line 3685 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_FIREBALL : Particles_Fireball01Trail_Prepare (this );break ; +#line 3686 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3688 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +switch(m_prtType ) +#line 3689 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +{ +#line 3690 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_WALKER_ROCKET : WalkerRocket ();break ; +#line 3691 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_ROCKET : PlayerRocket ();break ; +#line 3692 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GRENADE : PlayerGrenade ();break ; +#line 3693 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_FLAME : PlayerFlame ();break ; +#line 3694 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LASER_RAY : PlayerLaserRay ();break ; +#line 3695 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_CATMAN_FIRE : CatmanProjectile ();break ; +#line 3696 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_FIRECRACKER : HeadmanFirecracker ();break ; +#line 3697 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_ROCKETMAN : HeadmanRocketman ();break ; +#line 3698 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_BOMBERMAN : HeadmanBomberman ();break ; +#line 3699 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BONEMAN_FIRE : BonemanProjectile ();break ; +#line 3700 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_WOMAN_FIRE : WomanProjectile ();break ; +#line 3701 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DRAGONMAN_FIRE : DragonmanProjectile (DRAGONMAN_NORMAL );break ; +#line 3702 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DRAGONMAN_STRONG_FIRE : DragonmanProjectile (DRAGONMAN_STRONG );break ; +#line 3703 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_STONEMAN_FIRE : ElementalRock (ELEMENTAL_NORMAL , ELEMENTAL_STONEMAN );break ; +#line 3704 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_STONEMAN_BIG_FIRE : ElementalRock (ELEMENTAL_BIG , ELEMENTAL_STONEMAN );break ; +#line 3705 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_STONEMAN_LARGE_FIRE : ElementalRock (ELEMENTAL_LARGE , ELEMENTAL_STONEMAN );break ; +#line 3706 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVAMAN_BIG_BOMB : LavaManBomb ();break ; +#line 3707 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVAMAN_BOMB : LavaManBomb ();break ; +#line 3708 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVAMAN_STONE : ElementalRock (ELEMENTAL_NORMAL , ELEMENTAL_LAVAMAN );break ; +#line 3709 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_ICEMAN_FIRE : ElementalRock (ELEMENTAL_NORMAL , ELEMENTAL_ICEMAN );break ; +#line 3710 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_ICEMAN_BIG_FIRE : ElementalRock (ELEMENTAL_BIG , ELEMENTAL_ICEMAN );break ; +#line 3711 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_ICEMAN_LARGE_FIRE : ElementalRock (ELEMENTAL_LARGE , ELEMENTAL_ICEMAN );break ; +#line 3712 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HUANMAN_FIRE : HuanmanProjectile ();break ; +#line 3713 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_FISHMAN_FIRE : FishmanProjectile ();break ; +#line 3714 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_MANTAMAN_FIRE : MantamanProjectile ();break ; +#line 3715 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_CYBORG_LASER : CyborgLaser ();break ; +#line 3716 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_CYBORG_BOMB : CyborgBomb ();break ; +#line 3717 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVA_COMET : LavaBall ();break ; +#line 3718 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_PROJECTILE : BeastProjectile ();break ; +#line 3719 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_BIG_PROJECTILE : BeastBigProjectile ();break ; +#line 3720 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_DEBRIS : BeastDebris ();break ; +#line 3721 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_BIG_DEBRIS : BeastBigDebris ();break ; +#line 3722 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEVIL_LASER : DevilLaser ();break ; +#line 3723 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEVIL_ROCKET : DevilRocket ();break ; +#line 3724 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEVIL_GUIDED_PROJECTILE : DevilGuidedProjectile ();break ; +#line 3725 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GRUNT_PROJECTILE_SOL : GruntSoldierLaser ();break ; +#line 3726 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GRUNT_PROJECTILE_COM : GruntCommanderLaser ();break ; +#line 3727 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GUFFY_PROJECTILE : GuffyProjectile ();break ; +#line 3728 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEMON_FIREBALL : DemonFireball ();break ; +#line 3729 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LARVA_PLASMA : LarvaPlasma ();break ; +#line 3730 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LARVA_TAIL_PROJECTILE : LarvaTail ();break ; +#line 3731 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_WOODEN_DART : ShooterWoodenDart ();break ; +#line 3732 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_FIREBALL : ShooterFireball ();break ; +#line 3733 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_FLAME : ShooterFlame ();break ; +#line 3734 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_AFTERBURNER_DEBRIS : AfterburnerDebris ();break ; +#line 3735 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_AIRELEMENTAL_WIND : WindBlast ();break ; +#line 3736 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_METEOR : Meteor ();break ; +#line 3737 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +default : ASSERTALWAYS ("Unknown projectile type"); +#line 3738 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3741 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_bLightSource ){SetupLightSource (TRUE );} +#line 3744 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +m_fStartTime = _pTimer -> CurrentTick (); +#line 3746 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(!(m_pmtMove == PMT_GUIDED )){ Jump(STATE_CURRENT,0x01f5002f, FALSE, EInternal());return TRUE;} +#line 3747 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +STATE_CProjectile_ProjectileGuidedFly, TRUE; +Jump(STATE_CURRENT, 0x01f50019, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f50019_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50019 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CProjectile_ProjectileGuidedFly, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01f5001a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CProjectile::H0x01f5001a_Main_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5001a +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x01f5002e, FALSE, EInternal());return TRUE;}BOOL CProjectile::H0x01f5002f_Main_23(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5002f +if(!(m_pmtMove == PMT_GUIDED_FAST )){ Jump(STATE_CURRENT,0x01f5002d, FALSE, EInternal());return TRUE;} +#line 3749 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +STATE_CProjectile_ProjectileGuidedFastFly, TRUE; +Jump(STATE_CURRENT, 0x01f5001b, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f5001b_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5001b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CProjectile_ProjectileGuidedFastFly, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01f5001c, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CProjectile::H0x01f5001c_Main_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5001c +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x01f5002c, FALSE, EInternal());return TRUE;}BOOL CProjectile::H0x01f5002d_Main_21(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5002d +if(!(m_pmtMove == PMT_FLYING )){ Jump(STATE_CURRENT,0x01f5002b, FALSE, EInternal());return TRUE;} +#line 3751 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +STATE_CProjectile_ProjectileFly, TRUE; +Jump(STATE_CURRENT, 0x01f5001d, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f5001d_Main_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5001d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CProjectile_ProjectileFly, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01f5001e, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CProjectile::H0x01f5001e_Main_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5001e +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x01f5002a, FALSE, EInternal());return TRUE;}BOOL CProjectile::H0x01f5002b_Main_19(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5002b +if(!(m_pmtMove == PMT_SLIDING )){ Jump(STATE_CURRENT,0x01f50029, FALSE, EInternal());return TRUE;} +#line 3753 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +STATE_CProjectile_ProjectileSlide, TRUE; +Jump(STATE_CURRENT, 0x01f5001f, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f5001f_Main_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5001f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CProjectile_ProjectileSlide, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01f50020, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CProjectile::H0x01f50020_Main_08(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50020 +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x01f50028, FALSE, EInternal());return TRUE;}BOOL CProjectile::H0x01f50029_Main_17(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50029 +if(!(m_pmtMove == PMT_FLYING_REBOUNDING )){ Jump(STATE_CURRENT,0x01f50027, FALSE, EInternal());return TRUE;} +#line 3755 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +STATE_CProjectile_ProjectileFlyRebounding, TRUE; +Jump(STATE_CURRENT, 0x01f50021, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f50021_Main_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50021 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CProjectile_ProjectileFlyRebounding, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01f50022, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CProjectile::H0x01f50022_Main_10(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50022 +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x01f50026, FALSE, EInternal());return TRUE;}BOOL CProjectile::H0x01f50027_Main_15(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50027 +if(!(m_pmtMove == PMT_GUIDED_SLIDING )){ Jump(STATE_CURRENT,0x01f50025, FALSE, EInternal());return TRUE;} +#line 3757 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +STATE_CProjectile_ProjectileGuidedSlide, TRUE; +Jump(STATE_CURRENT, 0x01f50023, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f50023_Main_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50023 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CProjectile_ProjectileGuidedSlide, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01f50024, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CProjectile::H0x01f50024_Main_12(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50024 +const EEnd&__e= (EEnd&)__eeInput; +;Jump(STATE_CURRENT,0x01f50025, FALSE, EInternal());return TRUE;}BOOL CProjectile::H0x01f50025_Main_13(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50025 +Jump(STATE_CURRENT,0x01f50026, FALSE, EInternal());return TRUE;} +BOOL CProjectile::H0x01f50026_Main_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50026 +Jump(STATE_CURRENT,0x01f50028, FALSE, EInternal());return TRUE;} +BOOL CProjectile::H0x01f50028_Main_16(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50028 +Jump(STATE_CURRENT,0x01f5002a, FALSE, EInternal());return TRUE;} +BOOL CProjectile::H0x01f5002a_Main_18(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5002a +Jump(STATE_CURRENT,0x01f5002c, FALSE, EInternal());return TRUE;} +BOOL CProjectile::H0x01f5002c_Main_20(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5002c +Jump(STATE_CURRENT,0x01f5002e, FALSE, EInternal());return TRUE;} +BOOL CProjectile::H0x01f5002e_Main_22(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f5002e + +#line 3761 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +switch(m_prtType ){ +#line 3762 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_WALKER_ROCKET : WalkerRocketExplosion ();break ; +#line 3763 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_ROCKET : PlayerRocketExplosion ();break ; +#line 3764 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GRENADE : PlayerGrenadeExplosion ();break ; +#line 3765 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LASER_RAY : PlayerLaserWave ();break ; +#line 3766 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_HEADMAN_BOMBERMAN : HeadmanBombermanExplosion ();break ; +#line 3767 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_CYBORG_BOMB : CyborgBombExplosion ();break ; +#line 3768 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVA_COMET : LavamanBombDebrisExplosion ();break ; +#line 3769 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVAMAN_BIG_BOMB : LavamanBombExplosion ();break ; +#line 3770 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LAVAMAN_BOMB : LavamanBombDebrisExplosion ();break ; +#line 3771 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_BIG_PROJECTILE : BeastBigProjectileExplosion ();break ; +#line 3772 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_PROJECTILE : BeastProjectileExplosion ();break ; +#line 3773 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_DEBRIS : BeastDebrisExplosion ();break ; +#line 3774 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_BEAST_BIG_DEBRIS : BeastBigDebrisExplosion ();break ; +#line 3775 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEVIL_ROCKET : DevilRocketExplosion ();break ; +#line 3776 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEVIL_GUIDED_PROJECTILE : DevilGuidedProjectileExplosion ();break ; +#line 3777 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_GUFFY_PROJECTILE : GuffyProjectileExplosion ();break ; +#line 3778 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_DEMON_FIREBALL : DemonFireballExplosion ();break ; +#line 3779 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LARVA_PLASMA : LarvaPlasmaExplosion ();break ; +#line 3780 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_LARVA_TAIL_PROJECTILE : LarvaTailExplosion ();break ; +#line 3781 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_WOODEN_DART : ShooterWoodenDartExplosion ();break ; +#line 3782 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_SHOOTER_FIREBALL : ShooterFireballExplosion ();break ; +#line 3783 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +case PRT_METEOR : MeteorExplosion ();break ; +#line 3784 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +} +#line 3787 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(!(m_fWaitAfterDeath > 0.0f)){ Jump(STATE_CURRENT,0x01f50032, FALSE, EInternal());return TRUE;} +#line 3788 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SwitchToEditorModel (); +#line 3789 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ForceFullStop (); +#line 3790 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 3792 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +if(m_bLightSource ){SetupLightSource (FALSE );} +#line 3793 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +SetTimerAfter(m_fWaitAfterDeath ); +Jump(STATE_CURRENT, 0x01f50030, FALSE, EBegin());return TRUE;}BOOL CProjectile::H0x01f50030_Main_24(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50030 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01f50031, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CProjectile::H0x01f50031_Main_25(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50031 +;Jump(STATE_CURRENT,0x01f50032, FALSE, EInternal());return TRUE;}BOOL CProjectile::H0x01f50032_Main_26(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01f50032 + +#line 3796 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Destroy (); +#line 3798 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Return(STATE_CURRENT,EVoid()); +#line 3798 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Projectile.es b/Sources/EntitiesMP/Projectile.es new file mode 100644 index 0000000..45dfecf --- /dev/null +++ b/Sources/EntitiesMP/Projectile.es @@ -0,0 +1,3800 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +501 +%{ +#include "StdH.h" +#include "Models/Weapons/Laser/Projectile/LaserProjectile.h" +#include "EntitiesMP/EnemyBase.h" +//#include "EntitiesMP/Dragonman.h" +#include "Models/Enemies/Elementals/Projectile/IcePyramid.h" +#include "Models/Enemies/ElementalLava/Projectile/LavaStone.h" +#include "Models/Enemies/ElementalLava/Projectile/LavaBomb.h" +#include "Models/Enemies/Headman/Projectile/Blade.h" +#include "Models/Enemies/Huanman/Projectile/Projectile.h" +#include "Models/Enemies/Cyborg/Projectile/LaserProjectile.h" + +#include "ModelsMP/Enemies/Grunt/Projectile/GruntProjectile.h" +#include "ModelsMP/Enemies/Guffy/Projectile/GuffyProjectile.h" + +#include "ModelsMP/Enemies/ExotechLarva/Weapons/PlasmaGun.h" + +#include "EntitiesMP/PlayerWeapons.h" +#include "EntitiesMP/Shooter.h" + +#define DEVIL_LASER_SPEED 100.0f +#define DEVIL_ROCKET_SPEED 60.0f +%} + +uses "EntitiesMP/BasicEffects"; +uses "EntitiesMP/Light"; +uses "EntitiesMP/Flame"; + +enum ProjectileType { + 0 PRT_ROCKET "Rocket", // player rocket + 1 PRT_GRENADE "Grenade", // player grenade + 2 PRT_FLAME "Flame", // player flamer flame + 3 PRT_LASER_RAY "Laser", // player laser ray + 4 PRT_WALKER_ROCKET "WalkerRocket", // walker rocket + + 10 PRT_CATMAN_FIRE "Catman", // catman fire + + 11 PRT_HEADMAN_FIRECRACKER "Firecracker", // headman firecracker + 12 PRT_HEADMAN_ROCKETMAN "Rocketman", // headman rocketman + 13 PRT_HEADMAN_BOMBERMAN "Bomberman", // headman bomberman + + 14 PRT_BONEMAN_FIRE "Boneman", // boneman fire + + 15 PRT_WOMAN_FIRE "Woman", // woman fire + + 16 PRT_DRAGONMAN_FIRE "Dragonman", // dragonman fire + 17 PRT_DRAGONMAN_STRONG_FIRE "Dragonman Strong", // dragonman strong fire + + 18 PRT_STONEMAN_FIRE "Stoneman", // stoneman fire rock + 19 PRT_STONEMAN_BIG_FIRE "Stoneman Big", // stoneman big fire rock + 20 PRT_STONEMAN_LARGE_FIRE "Stoneman Large", // stoneman large fire rock + 21 PRT_LAVAMAN_BIG_BOMB "Lavaman Big Bomb", // lavaman big bomb + 22 PRT_LAVAMAN_BOMB "Lavaman Bomb", // lavaman bomb + 23 PRT_LAVAMAN_STONE "Lavaman Stone", // lavaman rock projectile + 27 PRT_ICEMAN_FIRE "Iceman", // iceman ice cube + 28 PRT_ICEMAN_BIG_FIRE "Iceman Big", // iceman big ice cube + 29 PRT_ICEMAN_LARGE_FIRE "Iceman Large", // iceman large ice cube + + 41 PRT_HUANMAN_FIRE "Huanman", // huanman fire + + 42 PRT_FISHMAN_FIRE "Fishman", // fishman fire + + 43 PRT_MANTAMAN_FIRE "Mantaman", // mantaman fire + + 44 PRT_CYBORG_LASER "Cyborg Laser", // cyborg laser + 45 PRT_CYBORG_BOMB "Cyborg Bomb", // cyborg bomb + + 50 PRT_LAVA_COMET "Lava Comet", // lava comet + 51 PRT_BEAST_PROJECTILE "Beast Projectile", // beast projectile + 52 PRT_BEAST_BIG_PROJECTILE "Beast Big Projectile", // big beast projectile + 53 PRT_BEAST_DEBRIS "Beast Debris", // beast projectile's debris + 54 PRT_BEAST_BIG_DEBRIS "Beast Big Debris", // big beast projectile's debris + 55 PRT_DEVIL_LASER "Devil Laser", // devil laser + 56 PRT_DEVIL_ROCKET "Devil Rocket", // devil rocket + 57 PRT_DEVIL_GUIDED_PROJECTILE "Devil Guided Projectile", // devil guided projectile + 60 PRT_GRUNT_PROJECTILE_SOL "Grunt Soldier Laser", // grunt laser + 64 PRT_GRUNT_PROJECTILE_COM "Grunt Commander Laser", // grunt commander laser + 61 PRT_GUFFY_PROJECTILE "Guffy Projectile", // guffy rocket + 62 PRT_DEMON_FIREBALL "Demon Fireball", // demon fireball + 63 PRT_DEMON_FIREBALL_DEBRIS "Demon Fireball Debris", // demon fireball debris + 70 PRT_SHOOTER_WOODEN_DART "Shooter Wooden Dart", // shooter's wooden dart + 71 PRT_SHOOTER_FIREBALL "Shooter Fireball", // shooter's fireball + 72 PRT_SHOOTER_FLAME "Shooter Flame", // shooter's flame + 73 PRT_LARVA_PLASMA "ExotechLarva Plasma", //exotech larva plasma gun + 74 PRT_LARVA_TAIL_PROJECTILE "ExotechLarva Tail Projectile", //exotech larva tail projectile + 75 PRT_AIRELEMENTAL_WIND "Air Elemental Wind Blast", //air elemental wind blast + 76 PRT_AFTERBURNER_DEBRIS "Afterburner debris", + 77 PRT_METEOR "Meteor", +}; + +enum ProjectileMovingType { + 0 PMT_FLYING "", // flying through space + 1 PMT_SLIDING "", // sliding on floor + 2 PMT_GUIDED "", // guided projectile + 3 PMT_GUIDED_FAST "", // fast guided projectile + 4 PMT_FLYING_REBOUNDING "", // flying and rebounding from walls a few times + 5 PMT_GUIDED_SLIDING "", // sliding on floor and guided at the same time +}; + + +// input parameter for launching the projectile +event ELaunchProjectile { + CEntityPointer penLauncher, // who launched it + enum ProjectileType prtType, // type of projectile + FLOAT fSpeed, // optional - projectile speed (only for some projectiles) + FLOAT fStretch, // optional - projectile stretch (only for some projectiles) +}; + + +%{ +#define DRAGONMAN_NORMAL 0 +#define DRAGONMAN_STRONG 1 + +#define ELEMENTAL_LARGE 2 +#define ELEMENTAL_BIG 1 +#define ELEMENTAL_NORMAL 0 + +#define ELEMENTAL_STONEMAN 0 +#define ELEMENTAL_LAVAMAN 1 +#define ELEMENTAL_ICEMAN 2 + +void CProjectile_OnInitClass(void) +{ +} + +void CProjectile_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + pdec->PrecacheTexture(TEX_REFL_BWRIPLES01); + pdec->PrecacheTexture(TEX_REFL_BWRIPLES02); + pdec->PrecacheTexture(TEX_REFL_LIGHTMETAL01); + pdec->PrecacheTexture(TEX_REFL_LIGHTBLUEMETAL01); + pdec->PrecacheTexture(TEX_REFL_DARKMETAL); + pdec->PrecacheTexture(TEX_REFL_PURPLE01); + + pdec->PrecacheTexture(TEX_SPEC_WEAK); + pdec->PrecacheTexture(TEX_SPEC_MEDIUM); + pdec->PrecacheTexture(TEX_SPEC_STRONG); + + switch ((ProjectileType)iUser) { + case PRT_ROCKET : + case PRT_WALKER_ROCKET : + case PRT_DEVIL_ROCKET : + pdec->PrecacheModel(MODEL_ROCKET ); + pdec->PrecacheTexture(TEXTURE_ROCKET); + pdec->PrecacheSound(SOUND_FLYING ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_ROCKET); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_ROCKET_PLANE); + break; + case PRT_GRENADE: + pdec->PrecacheModel(MODEL_GRENADE); + pdec->PrecacheTexture(TEXTURE_GRENADE); + pdec->PrecacheSound(SOUND_GRENADE_BOUNCE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE_PLANE); + break; + + case PRT_FLAME: + pdec->PrecacheModel(MODEL_FLAME); + pdec->PrecacheClass(CLASS_FLAME); + break; + + case PRT_LASER_RAY: + pdec->PrecacheModel(MODEL_LASER ); + pdec->PrecacheTexture(TEXTURE_GREEN_LASER ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LASERWAVE); + break; + + case PRT_GRUNT_PROJECTILE_SOL: + pdec->PrecacheModel(MODEL_GRUNT_PROJECTILE ); + pdec->PrecacheTexture(TEXTURE_GRUNT_PROJECTILE_01 ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LASERWAVE); + break; + + case PRT_GRUNT_PROJECTILE_COM: + pdec->PrecacheModel(MODEL_GRUNT_PROJECTILE ); + pdec->PrecacheTexture(TEXTURE_GRUNT_PROJECTILE_02 ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LASERWAVE); + break; + + case PRT_CATMAN_FIRE: + pdec->PrecacheModel(MODEL_CATMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_CATMAN_FIRE ); + break; + + case PRT_HEADMAN_FIRECRACKER: + pdec->PrecacheModel(MODEL_HEADMAN_FIRECRACKER ); + pdec->PrecacheTexture(TEXTURE_HEADMAN_FIRECRACKER ); + break; + case PRT_HEADMAN_ROCKETMAN: + pdec->PrecacheModel(MODEL_HEADMAN_BLADE ); + pdec->PrecacheTexture(TEXTURE_HEADMAN_BLADE ); + pdec->PrecacheModel(MODEL_HEADMAN_BLADE_FLAME ); + pdec->PrecacheTexture(TEXTURE_HEADMAN_BLADE_FLAME ); + break; + case PRT_HEADMAN_BOMBERMAN: + pdec->PrecacheModel(MODEL_HEADMAN_BOMB ); + pdec->PrecacheTexture(TEXTURE_HEADMAN_BOMB ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BOMB); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE_PLANE); + break; + + case PRT_BONEMAN_FIRE: + pdec->PrecacheModel(MODEL_BONEMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_BONEMAN_FIRE ); + break; + + case PRT_WOMAN_FIRE: + pdec->PrecacheModel(MODEL_WOMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_WOMAN_FIRE ); + break; + + case PRT_DRAGONMAN_FIRE: + case PRT_DRAGONMAN_STRONG_FIRE: + pdec->PrecacheModel(MODEL_DRAGONMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_DRAGONMAN_FIRE1 ); + pdec->PrecacheTexture(TEXTURE_DRAGONMAN_FIRE2 ); + break; + + case PRT_STONEMAN_FIRE: + case PRT_STONEMAN_BIG_FIRE: + case PRT_STONEMAN_LARGE_FIRE: + pdec->PrecacheModel(MODEL_ELEM_STONE ); + pdec->PrecacheTexture(TEXTURE_ELEM_STONE ); + break; + case PRT_LAVAMAN_BIG_BOMB: + case PRT_LAVAMAN_BOMB: + case PRT_LAVAMAN_STONE: + pdec->PrecacheModel(MODEL_ELEM_LAVA_STONE); + pdec->PrecacheModel(MODEL_ELEM_LAVA_STONE_FLARE); + pdec->PrecacheModel(MODEL_ELEM_LAVA_BOMB); + pdec->PrecacheModel(MODEL_ELEM_LAVA_BOMB_FLARE); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_STONE); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_STONE_FLARE ); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_BOMB); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_BOMB_FLARE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + pdec->PrecacheClass(CLASS_BLOOD_SPRAY); + break; + case PRT_METEOR: + pdec->PrecacheSound(SOUND_FLYING ); + pdec->PrecacheSound(SOUND_METEOR_BLAST ); + pdec->PrecacheModel(MODEL_ELEM_LAVA_BOMB); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_BOMB); + pdec->PrecacheClass(CLASS_BLOOD_SPRAY); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON); + + break; + + case PRT_ICEMAN_FIRE: + case PRT_ICEMAN_BIG_FIRE: + case PRT_ICEMAN_LARGE_FIRE: + pdec->PrecacheModel(MODEL_ELEM_ICE ); + pdec->PrecacheModel(MODEL_ELEM_ICE_FLARE ); + pdec->PrecacheTexture(TEXTURE_ELEM_ICE ); + //pdec->PrecacheTexture(TEXTURE_ELEM_ICE_FLARE); + break; + + case PRT_HUANMAN_FIRE: + pdec->PrecacheModel(MODEL_HUANMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_HUANMAN_FIRE ); + pdec->PrecacheModel(MODEL_HUANMAN_FLARE ); + pdec->PrecacheTexture(TEXTURE_HUANMAN_FLARE ); + break; + + case PRT_FISHMAN_FIRE: + pdec->PrecacheModel(MODEL_FISHMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_FISHMAN_FIRE ); + break; + + case PRT_MANTAMAN_FIRE: + pdec->PrecacheModel(MODEL_MANTAMAN_FIRE ); + pdec->PrecacheTexture(TEXTURE_MANTAMAN_FIRE ); + break; + + case PRT_DEVIL_LASER: + /* + pdec->PrecacheModel(MODEL_DEVIL_LASER ); + pdec->PrecacheTexture(TEXTURE_DEVIL_LASER ); + break; + */ + + case PRT_CYBORG_LASER: + case PRT_CYBORG_BOMB: + pdec->PrecacheModel(MODEL_CYBORG_LASER ); + pdec->PrecacheTexture(TEXTURE_CYBORG_LASER ); + pdec->PrecacheModel(MODEL_CYBORG_BOMB ); + pdec->PrecacheTexture(TEXTURE_CYBORG_BOMB ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_BOMB); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_EXPLOSIONSTAIN); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_GRENADE_PLANE); + break; + + case PRT_LAVA_COMET: + pdec->PrecacheModel(MODEL_ELEM_LAVA_STONE); + pdec->PrecacheModel(MODEL_ELEM_LAVA_STONE_FLARE); + pdec->PrecacheModel(MODEL_ELEM_LAVA_BOMB); + pdec->PrecacheModel(MODEL_ELEM_LAVA_BOMB_FLARE); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_STONE); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_STONE_FLARE ); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_BOMB); + pdec->PrecacheTexture(TEXTURE_ELEM_LAVA_BOMB_FLARE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + pdec->PrecacheClass(CLASS_BLOOD_SPRAY); + pdec->PrecacheModel(MODEL_LAVA ); + pdec->PrecacheTexture(TEXTURE_LAVA ); + pdec->PrecacheModel(MODEL_LAVA_FLARE ); + pdec->PrecacheTexture(TEXTURE_LAVA_FLARE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_SHOCKWAVE); + pdec->PrecacheClass(CLASS_BLOOD_SPRAY); + break; + case PRT_BEAST_PROJECTILE: + case PRT_BEAST_DEBRIS: + pdec->PrecacheSound(SOUND_BEAST_FLYING ); + pdec->PrecacheModel(MODEL_BEAST_FIRE); + pdec->PrecacheTexture(TEXTURE_BEAST_FIRE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON); + break; + case PRT_GUFFY_PROJECTILE: + pdec->PrecacheSound(SOUND_FLYING ); + pdec->PrecacheModel(MODEL_GUFFY_PROJECTILE ); + pdec->PrecacheTexture(TEXTURE_GUFFY_PROJECTILE ); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_ROCKET ); + break; + case PRT_BEAST_BIG_PROJECTILE: + case PRT_DEVIL_GUIDED_PROJECTILE: + case PRT_BEAST_BIG_DEBRIS: + case PRT_SHOOTER_FIREBALL: + pdec->PrecacheSound(SOUND_BEAST_FLYING ); + pdec->PrecacheModel(MODEL_BEAST_FIRE); + pdec->PrecacheTexture(TEXTURE_BEAST_BIG_FIRE); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LIGHT_CANNON); + break; + case PRT_DEMON_FIREBALL: + case PRT_DEMON_FIREBALL_DEBRIS: + pdec->PrecacheSound(SOUND_DEMON_FLYING ); + pdec->PrecacheModel(MODEL_DEMON_FIREBALL); + pdec->PrecacheTexture(TEXTURE_DEMON_FIREBALL); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LIGHT_CANNON); + break; + case PRT_LARVA_PLASMA: + pdec->PrecacheSound(SOUND_DEMON_FLYING ); + pdec->PrecacheModel(MODEL_LARVA_PLASMA); + pdec->PrecacheTexture(TEXTURE_LARVA_PLASMA); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_LIGHT_CANNON); + break; + case PRT_LARVA_TAIL_PROJECTILE: + pdec->PrecacheSound(SOUND_LARVETTE ); + pdec->PrecacheModel(MODEL_LARVA_TAIL); + pdec->PrecacheTexture(TEXTURE_LARVA_TAIL); + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON); + break; + case PRT_SHOOTER_WOODEN_DART: + pdec->PrecacheModel(MODEL_SHTR_WOODEN_DART); + pdec->PrecacheTexture(TEX_SHTR_WOODEN_DART); + break; + case PRT_SHOOTER_FLAME: + pdec->PrecacheModel(MODEL_FLAME); + pdec->PrecacheClass(CLASS_FLAME); + break; + case PRT_AIRELEMENTAL_WIND: + pdec->PrecacheModel(MODEL_WINDBLAST); + pdec->PrecacheTexture(TEXTURE_WINDBLAST); + break; + case PRT_AFTERBURNER_DEBRIS: + pdec->PrecacheModel(MODEL_MARKER); + pdec->PrecacheTexture(TEXTURE_MARKER); + break; + default: + ASSERT(FALSE); + } +} +%} + + +class export CProjectile : CMovableModelEntity { +name "Projectile"; +thumbnail ""; +features "ImplementsOnInitClass", "ImplementsOnPrecache", "CanBePredictable"; + +properties: + 1 CEntityPointer m_penLauncher, // who lanuched it + 2 enum ProjectileType m_prtType = PRT_ROCKET, // type of the projectile + 3 enum ProjectileMovingType m_pmtMove = PMT_FLYING, // projectile moving type + 4 CEntityPointer m_penParticles, // another entity for particles + 5 CEntityPointer m_penTarget, // guided projectile's target + 6 CEntityPointer m_penLastDamaged, // last entity this projectile damaged + + 10 FLOAT m_fSpeed = 0.0f, // projectile speed (optional, only for some projectiles) + 11 FLOAT m_fIgnoreTime = 0.0f, // time when laucher will be ignored + 12 FLOAT m_fFlyTime = 0.0f, // fly time before explode/disappear + 13 FLOAT m_fStartTime = 0.0f, // start time when launched + 14 FLOAT m_fDamageAmount = 0.0f, // damage amount when hit something + 15 FLOAT m_fRangeDamageAmount = 0.0f, // range damage amount + 16 FLOAT m_fDamageHotSpotRange = 0.0f, // hot spot range damage for exploding projectile + 17 FLOAT m_fDamageFallOffRange = 0.0f, // fall off range damage for exploding projectile + 18 FLOAT m_fSoundRange = 0.0f, // sound range where explosion can be heard + 19 BOOL m_bExplode = FALSE, // explode -> range damage + 20 BOOL m_bLightSource = FALSE, // projectile is also light source + 21 BOOL m_bCanHitHimself = FALSE, // projectile can him himself + 22 BOOL m_bCanBeDestroyed = FALSE, // projectile can be destroyed from something else + 23 FLOAT m_fWaitAfterDeath = 0.0f, // wait after death for particles + 24 FLOAT m_aRotateSpeed = 0.0f, // speed of rotation for guided projectiles + 25 FLOAT m_tmExpandBox = 0.0f, // expand collision after a few seconds + 26 FLOAT m_tmInvisibility = 0.0f, // don't render before given time + 27 INDEX m_iRebounds = 0, // how many times to rebound + 28 FLOAT m_fStretch=1.0f, // stretch + + 30 CSoundObject m_soEffect, // sound channel + 31 CSoundObject m_soExplosion, // sound channel + + 35 FLOAT m_fGuidedMaxSpeedFactor = 30.0f, // speed factor for guided projectiles + + 50 BOOL bLockedOn = TRUE, + 51 BOOL m_bLeftFlame = FALSE, +{ + CLightSource m_lsLightSource; +} + +components: + 1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 2 class CLASS_LIGHT "Classes\\Light.ecl", + 3 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 4 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + +// ********* PLAYER ROCKET ********* + 5 model MODEL_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl", + 6 texture TEXTURE_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex", + 8 sound SOUND_FLYING "Sounds\\Weapons\\RocketFly.wav", + 9 sound SOUND_BEAST_FLYING "Sounds\\Weapons\\ProjectileFly.wav", + +// ********* PLAYER GRENADE ********* + 10 model MODEL_GRENADE "Models\\Weapons\\GrenadeLauncher\\Grenade\\Grenade.mdl", + 11 texture TEXTURE_GRENADE "Models\\Weapons\\GrenadeLauncher\\Grenade\\Grenade.tex", + 12 sound SOUND_GRENADE_BOUNCE "Models\\Weapons\\GrenadeLauncher\\Sounds\\Bounce.wav", + +// ********* PLAYER FLAME ********* + 15 model MODEL_FLAME "ModelsMP\\Weapons\\Flamer\\Projectile\\Invisible.mdl", + 16 class CLASS_FLAME "Classes\\Flame.ecl", + +// ********* CATMAN FIRE ********* + 20 model MODEL_CATMAN_FIRE "Models\\Enemies\\Catman\\Projectile\\Projectile.mdl", + 21 texture TEXTURE_CATMAN_FIRE "Models\\Enemies\\Catman\\Projectile\\Projectile.tex", + +// ********* HEADMAN FIRE ********* + 30 model MODEL_HEADMAN_FIRECRACKER "Models\\Enemies\\Headman\\Projectile\\FireCracker.mdl", + 31 texture TEXTURE_HEADMAN_FIRECRACKER "Models\\Enemies\\Headman\\Projectile\\Texture.tex", + 32 model MODEL_HEADMAN_BLADE "Models\\Enemies\\Headman\\Projectile\\Blade.mdl", + 33 texture TEXTURE_HEADMAN_BLADE "Models\\Enemies\\Headman\\Projectile\\Blade.tex", + 34 model MODEL_HEADMAN_BLADE_FLAME "Models\\Enemies\\Headman\\Projectile\\FireTrail.mdl", + 35 texture TEXTURE_HEADMAN_BLADE_FLAME "Models\\Enemies\\Headman\\Projectile\\FireTrail.tex", + 36 model MODEL_HEADMAN_BOMB "Models\\Enemies\\Headman\\Projectile\\Bomb.mdl", + 37 texture TEXTURE_HEADMAN_BOMB "Models\\Enemies\\Headman\\Projectile\\Bomb.tex", + +// ********* LAVA ********* + 40 model MODEL_LAVA "Models\\Effects\\Debris\\Lava01\\Lava.mdl", + 41 texture TEXTURE_LAVA "Models\\Effects\\Debris\\Lava01\\Lava.tex", + 42 model MODEL_LAVA_FLARE "Models\\Effects\\Debris\\Lava01\\LavaFlare.mdl", + 43 texture TEXTURE_LAVA_FLARE "Models\\Effects\\Debris\\Lava01\\Flare.tex", + +// ********* PLAYER LASER ********* + 50 model MODEL_LASER "Models\\Weapons\\Laser\\Projectile\\LaserProjectile.mdl", + 51 texture TEXTURE_GREEN_LASER "Models\\Weapons\\Laser\\Projectile\\LaserProjectile.tex", + 52 texture TEXTURE_BLUE_LASER "Models\\Weapons\\Laser\\Projectile\\LaserProjectileBlue.tex", + +// ********* BONEMAN FIRE ********* + 60 model MODEL_BONEMAN_FIRE "Models\\Enemies\\Boneman\\Projectile\\Projectile.mdl", + 61 texture TEXTURE_BONEMAN_FIRE "Models\\Enemies\\Boneman\\Projectile\\Projectile.tex", + +// ********* WOMAN FIRE ********* + 65 model MODEL_WOMAN_FIRE "Models\\Enemies\\Woman\\Projectile\\Projectile.mdl", + 66 texture TEXTURE_WOMAN_FIRE "Models\\Enemies\\Woman\\Projectile\\Projectile.tex", + +// ********* DRAGONMAN FIRE ********* + 70 model MODEL_DRAGONMAN_FIRE "Models\\Enemies\\Dragonman\\Projectile\\Projectile.mdl", + 71 texture TEXTURE_DRAGONMAN_FIRE1 "Models\\Enemies\\Dragonman\\Projectile\\Projectile1.tex", + 72 texture TEXTURE_DRAGONMAN_FIRE2 "Models\\Enemies\\Dragonman\\Projectile\\Projectile2.tex", + +// ********* ELEMENTAL FIRE ********* + 80 model MODEL_ELEM_STONE "Models\\Enemies\\Elementals\\Projectile\\Stone.mdl", + 81 model MODEL_ELEM_ICE "Models\\Enemies\\Elementals\\Projectile\\IcePyramid.mdl", + 82 model MODEL_ELEM_ICE_FLARE "Models\\Enemies\\Elementals\\Projectile\\IcePyramidFlare.mdl", + 83 model MODEL_ELEM_LAVA_BOMB "Models\\Enemies\\Elementals\\Projectile\\LavaBomb.mdl", + 84 model MODEL_ELEM_LAVA_BOMB_FLARE "Models\\Enemies\\Elementals\\Projectile\\LavaBombFlare.mdl", + 85 model MODEL_ELEM_LAVA_STONE "Models\\Enemies\\Elementals\\Projectile\\LavaStone.mdl", + 86 model MODEL_ELEM_LAVA_STONE_FLARE "Models\\Enemies\\Elementals\\Projectile\\LavaStoneFlare.mdl", + + 90 texture TEXTURE_ELEM_STONE "Models\\Enemies\\Elementals\\Projectile\\Stone.tex", + 91 texture TEXTURE_ELEM_ICE "Models\\Enemies\\Elementals\\Projectile\\IcePyramid.tex", + //92 texture TEXTURE_ELEM_ICE_FLARE "Textures\\Effects\\Flares\\03\\Flare06.tex", + 93 texture TEXTURE_ELEM_LAVA_BOMB "Models\\Enemies\\Elementals\\Projectile\\LavaBomb.tex", + 94 texture TEXTURE_ELEM_LAVA_BOMB_FLARE "Models\\Enemies\\Elementals\\Projectile\\LavaBombFlare.tex", + 95 texture TEXTURE_ELEM_LAVA_STONE "Models\\Enemies\\Elementals\\Projectile\\LavaStone.tex", + 96 texture TEXTURE_ELEM_LAVA_STONE_FLARE "Models\\Enemies\\Elementals\\Projectile\\LavaBombFlare.tex", + +// ********* HUANMAN FIRE ********* +105 model MODEL_HUANMAN_FIRE "Models\\Enemies\\Huanman\\Projectile\\Projectile.mdl", +106 texture TEXTURE_HUANMAN_FIRE "Models\\Enemies\\Huanman\\Projectile\\Projectile.tex", +107 model MODEL_HUANMAN_FLARE "Models\\Enemies\\Huanman\\Projectile\\Flare.mdl", +108 texture TEXTURE_HUANMAN_FLARE "Textures\\Effects\\Flares\\01\\WhiteRedRing66.tex", + +// ********* FISHMAN FIRE ********* +110 model MODEL_FISHMAN_FIRE "Models\\Enemies\\Fishman\\Projectile\\Projectile.mdl", +111 texture TEXTURE_FISHMAN_FIRE "Models\\Enemies\\Fishman\\Projectile\\Water.tex", + +// ********* FISHMAN FIRE ********* +120 model MODEL_MANTAMAN_FIRE "Models\\Enemies\\Mantaman\\Projectile\\Projectile.mdl", +121 texture TEXTURE_MANTAMAN_FIRE "Models\\Enemies\\Mantaman\\Projectile\\Water.tex", + +// ********* CYBORG FIRE ********* +130 model MODEL_CYBORG_LASER "Models\\Weapons\\Laser\\Projectile\\LaserProjectile.mdl", +132 texture TEXTURE_CYBORG_LASER "Models\\Weapons\\Laser\\Projectile\\LaserProjectileBlue.tex", +133 model MODEL_CYBORG_BOMB "Models\\Enemies\\Cyborg\\Projectile\\Projectile.mdl", +134 texture TEXTURE_CYBORG_BOMB "Models\\Enemies\\Cyborg\\Projectile\\Projectile.tex", + +// ********* GRUNT PROJECTILES ********* +135 model MODEL_GRUNT_PROJECTILE "ModelsMP\\Enemies\\Grunt\\Projectile\\GruntProjectile.mdl", +136 texture TEXTURE_GRUNT_PROJECTILE_01 "ModelsMP\\Enemies\\Grunt\\Projectile\\GruntProjectileSoldier.tex", +137 texture TEXTURE_GRUNT_PROJECTILE_02 "ModelsMP\\Enemies\\Grunt\\Projectile\\GruntProjectileCommander.tex", + +// ********* DEVIL FIRE ********* +/* +135 model MODEL_DEVIL_LASER "Models\\Enemies\\Devil\\Weapons\\DevilLaserProjectile.mdl", +136 texture TEXTURE_DEVIL_LASER "Models\\Enemies\\Devil\\Weapons\\DevilLaserProjectile.tex", +*/ + +// ********* BEAST FIRE ********* +140 model MODEL_BEAST_FIRE "Models\\Enemies\\Beast\\Projectile\\Projectile.mdl", +141 texture TEXTURE_BEAST_FIRE "Models\\Enemies\\Beast\\Projectile\\Projectile.tex", +142 texture TEXTURE_BEAST_BIG_FIRE "Models\\Enemies\\Beast\\Projectile\\ProjectileBig.tex", + +// ********* DEMON FIREBALL ********* +150 model MODEL_DEMON_FIREBALL "ModelsMP\\Enemies\\Demon\\Projectile\\Projectile.mdl", +151 texture TEXTURE_DEMON_FIREBALL "ModelsMP\\Enemies\\Demon\\Projectile\\Projectile.tex", +152 sound SOUND_DEMON_FLYING "SoundsMP\\Weapons\\ProjectileFly.wav", + +// ********** SHOOTERS ********** +160 model MODEL_SHTR_WOODEN_DART "ModelsMP\\Enemies\\Shooters\\Arrow01.mdl", +161 texture TEX_SHTR_WOODEN_DART "ModelsMP\\Enemies\\Shooters\\Arrow01.tex", + +// ********** GUFFY PROJECTILE ********** +170 model MODEL_GUFFY_PROJECTILE "ModelsMP\\Enemies\\Guffy\\Projectile\\GuffyProjectile.mdl", +171 texture TEXTURE_GUFFY_PROJECTILE "ModelsMP\\Enemies\\Guffy\\Projectile\\GuffyProjectile.tex", + +// ********** LARVA PROJECTILES ********** +172 model MODEL_LARVA_PLASMA "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\Projectile.mdl", +173 texture TEXTURE_LARVA_PLASMA "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\Projectile.tex", +174 model MODEL_LARVA_PLASMA_BALL "ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.mdl", +175 texture TEXTURE_LARVA_PLASMA_BALL "ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.tex", + +176 model MODEL_LARVA_TAIL "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\TailProjectile.mdl", +177 texture TEXTURE_LARVA_TAIL "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\TailProjectile.tex", +178 sound SOUND_LARVETTE "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\Squeak.wav", + +// ********** AIR ELEMENTAL WIND BLAST ********** +180 model MODEL_WINDBLAST "ModelsMP\\Enemies\\AirElemental\\Projectile\\WindBlast.mdl", +181 texture TEXTURE_WINDBLAST "ModelsMP\\Enemies\\AirElemental\\Projectile\\WindBlast.tex", + +// ****************** METEOR ****************** +185 sound SOUND_METEOR_BLAST "SoundsMP\\Weapons\\MeteorBlast.wav", + +// ************** REFLECTIONS ************** +200 texture TEX_REFL_BWRIPLES01 "Models\\ReflectionTextures\\BWRiples01.tex", +201 texture TEX_REFL_BWRIPLES02 "Models\\ReflectionTextures\\BWRiples02.tex", +202 texture TEX_REFL_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex", +203 texture TEX_REFL_LIGHTBLUEMETAL01 "Models\\ReflectionTextures\\LightBlueMetal01.tex", +204 texture TEX_REFL_DARKMETAL "Models\\ReflectionTextures\\DarkMetal.tex", +205 texture TEX_REFL_PURPLE01 "Models\\ReflectionTextures\\Purple01.tex", + +// ************** SPECULAR ************** +210 texture TEX_SPEC_WEAK "Models\\SpecularTextures\\Weak.tex", +211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex", +212 texture TEX_SPEC_STRONG "Models\\SpecularTextures\\Strong.tex", + +220 model MODEL_MARKER "Models\\Editor\\Axis.mdl", +221 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex" + +functions: + // premoving + void PreMoving(void) { + if (m_tmExpandBox>0) { + if (_pTimer->CurrentTick()>m_fStartTime+m_tmExpandBox) { + ChangeCollisionBoxIndexWhenPossible(1); + m_tmExpandBox = 0; + } + } + CMovableModelEntity::PreMoving(); + } + + // postmoving + void PostMoving(void) { + CMovableModelEntity::PostMoving(); + // if flamer flame + if (m_prtType==PRT_FLAME || m_prtType==PRT_SHOOTER_FLAME) { + // if came to water + CContentType &ctDn = GetWorld()->wo_actContentTypes[en_iDnContent]; + // stop existing + if (!(ctDn.ct_ulFlags&CTF_BREATHABLE_LUNGS)) { + m_fWaitAfterDeath = 0.0f; // immediate stop + SendEvent(EEnd()); + } + } + }; + + /* Read from stream. */ + void Read_t( CTStream *istr) // throw char * + { + CMovableModelEntity::Read_t(istr); + // setup light source + if( m_bLightSource) { + SetupLightSource(TRUE); + } + } + + // dump sync data to text file + export void DumpSync_t(CTStream &strm, INDEX iExtensiveSyncCheck) // throw char * + { + CMovableModelEntity ::DumpSync_t(strm, iExtensiveSyncCheck); + strm.FPrintF_t("projectile type: %d\n", m_prtType); + strm.FPrintF_t("launcher:"); + if (m_penLauncher!=NULL) { + strm.FPrintF_t("id:%05d '%s'(%s) (%g, %g, %g)\n", + m_penLauncher->en_ulID, + m_penLauncher->GetName(), m_penLauncher->GetClass()->ec_pdecDLLClass->dec_strName, + m_penLauncher->GetPlacement().pl_PositionVector(1), + m_penLauncher->GetPlacement().pl_PositionVector(2), + m_penLauncher->GetPlacement().pl_PositionVector(3)); + } else { + strm.FPrintF_t("\n"); + } + } + + /* Get static light source information. */ + CLightSource *GetLightSource(void) + { + if( m_bLightSource && !IsPredictor()) { + return &m_lsLightSource; + } else { + return NULL; + } + } + + export void Copy(CEntity &enOther, ULONG ulFlags) + { + CMovableModelEntity::Copy(enOther, ulFlags); + CProjectile *penOther = (CProjectile *)(&enOther); + if (ulFlags©_PREDICTOR) { + //m_lsLightSource; + //SetupLightSource(); //? is this ok !!!! + m_bLightSource = FALSE; + } + } + + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + // if time now is inside invisibility time, don't render model + CModelObject *pmo = GetModelObject(); + if ( (pmo != NULL) && (_pTimer->GetLerpedCurrentTick() < (m_fStartTime+m_tmInvisibility) ) ) + { + // make it invisible + pmo->mo_colBlendColor = 0; + } + else + { + // make it visible + pmo->mo_colBlendColor = C_WHITE|CT_OPAQUE; + } + return CEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + } + + // Setup light source + void SetupLightSource(BOOL bLive) + { + // setup light source + CLightSource lsNew; + lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC; + lsNew.ls_rHotSpot = 0.0f; + switch (m_prtType) { + case PRT_ROCKET: + case PRT_WALKER_ROCKET: + case PRT_DEVIL_ROCKET: + if( bLive) + { + lsNew.ls_colColor = 0xA0A080FF; + } + else + { + lsNew.ls_colColor = C_BLACK|CT_OPAQUE; + } + lsNew.ls_rFallOff = 5.0f; + lsNew.ls_plftLensFlare = &_lftYellowStarRedRingFar; + break; + case PRT_GUFFY_PROJECTILE: + lsNew.ls_colColor = C_BLUE; + lsNew.ls_rFallOff = 1.5f; + lsNew.ls_plftLensFlare = NULL; + case PRT_GRENADE: + lsNew.ls_colColor = 0x2F1F0F00; + lsNew.ls_rFallOff = 2.0f; + lsNew.ls_rHotSpot = 0.2f; + lsNew.ls_plftLensFlare = &_lftYellowStarRedRingFar; + break; + case PRT_FLAME: + lsNew.ls_colColor = C_dORANGE; + lsNew.ls_rFallOff = 1.0f; + lsNew.ls_plftLensFlare = NULL; + break; + case PRT_LASER_RAY: + lsNew.ls_colColor = C_vdGREEN; + lsNew.ls_rFallOff = 1.5f; + lsNew.ls_plftLensFlare = NULL; + break; + case PRT_GRUNT_PROJECTILE_SOL: + lsNew.ls_colColor = C_vdRED; + lsNew.ls_rFallOff = 1.5f; + lsNew.ls_plftLensFlare = NULL; + break; + case PRT_GRUNT_PROJECTILE_COM: + lsNew.ls_colColor = C_vdRED; + lsNew.ls_rFallOff = 1.5f; + lsNew.ls_plftLensFlare = NULL; + break; + case PRT_CATMAN_FIRE: + lsNew.ls_colColor = C_BLUE; + lsNew.ls_rFallOff = 3.5f; + lsNew.ls_plftLensFlare = &_lftCatmanFireGlow; + break; + case PRT_HEADMAN_FIRECRACKER: + lsNew.ls_colColor = C_ORANGE; + lsNew.ls_rFallOff = 1.5f; + lsNew.ls_plftLensFlare = NULL; + break; + case PRT_HEADMAN_ROCKETMAN: + lsNew.ls_colColor = C_YELLOW; + lsNew.ls_rFallOff = 1.5f; + lsNew.ls_plftLensFlare = NULL; + break; + case PRT_WOMAN_FIRE: + lsNew.ls_colColor = C_WHITE; + lsNew.ls_rFallOff = 3.5f; + lsNew.ls_plftLensFlare = &_lftCatmanFireGlow; + break; + case PRT_DRAGONMAN_FIRE: + lsNew.ls_colColor = C_YELLOW; + lsNew.ls_rFallOff = 3.5f; + lsNew.ls_plftLensFlare = &_lftProjectileYellowBubbleGlow; + break; + case PRT_DRAGONMAN_STRONG_FIRE: + lsNew.ls_colColor = C_RED; + lsNew.ls_rFallOff = 3.5f; + lsNew.ls_plftLensFlare = &_lftProjectileStarGlow; + break; + case PRT_HUANMAN_FIRE: + lsNew.ls_colColor = C_lBLUE; + lsNew.ls_rFallOff = 2.0f; + lsNew.ls_plftLensFlare = NULL; + break; + case PRT_FISHMAN_FIRE: + lsNew.ls_colColor = C_lBLUE; + lsNew.ls_rFallOff = 2.0f; + lsNew.ls_plftLensFlare = NULL; + break; + case PRT_MANTAMAN_FIRE: + lsNew.ls_colColor = C_lBLUE; + lsNew.ls_rFallOff = 2.0f; + lsNew.ls_plftLensFlare = NULL; + break; + case PRT_CYBORG_LASER: + lsNew.ls_colColor = C_dBLUE; + lsNew.ls_rFallOff = 1.5f; + lsNew.ls_plftLensFlare = NULL; + break; + case PRT_DEVIL_LASER: + lsNew.ls_colColor = C_dBLUE; + lsNew.ls_rFallOff = 5.0f; + lsNew.ls_plftLensFlare = &_lftYellowStarRedRingFar; + break; + case PRT_LARVA_PLASMA: + lsNew.ls_colColor = C_dBLUE; + lsNew.ls_rFallOff = 5.0f; + lsNew.ls_plftLensFlare = &_lftCatmanFireGlow; + break; + case PRT_SHOOTER_FIREBALL: + lsNew.ls_colColor = C_dORANGE; + lsNew.ls_rFallOff = 5.0f; + lsNew.ls_plftLensFlare = &_lftYellowStarRedRingFar; + break; + case PRT_SHOOTER_FLAME: + lsNew.ls_colColor = C_dORANGE; + lsNew.ls_rFallOff = 1.0f; + lsNew.ls_plftLensFlare = NULL; + break; + default: + ASSERTALWAYS("Unknown light source"); + } + lsNew.ls_ubPolygonalMask = 0; + lsNew.ls_paoLightAnimation = NULL; + + m_lsLightSource.ls_penEntity = this; + m_lsLightSource.SetLightSource(lsNew); + } + + // render particles + void RenderParticles(void) { + switch (m_prtType) { + case PRT_ROCKET: + case PRT_WALKER_ROCKET: Particles_RocketTrail(this, 1.0f); break; + case PRT_DEVIL_ROCKET: Particles_RocketTrail(this, 8.0f); break; + case PRT_GUFFY_PROJECTILE: break;// Particles_RocketTrail(this, 1.0f); break; + case PRT_GRENADE: { + //Particles_GrenadeTrail(this); + FLOAT fSpeedRatio = en_vCurrentTranslationAbsolute.Length()/140.0f; + Particles_CannonBall(this, fSpeedRatio); + break; + } + case PRT_FLAME: { + // elapsed time + FLOAT fLeaderLiving, fFollowerLiving, fInFrontLiving; + fInFrontLiving=0.05f; + fLeaderLiving = _pTimer->GetLerpedCurrentTick() - m_fStartTime; + // not NULL or deleted + if (m_penParticles!=NULL && !(m_penParticles->GetFlags()&ENF_DELETED)) { + FLOAT3D vDirLeader=en_vCurrentTranslationAbsolute; + vDirLeader.Normalize(); + // if last is not flame thrower pipe + if(IsOfClass(m_penParticles, "Projectile")) + { + CProjectile &prLast=(CProjectile &)*m_penParticles; + // if pre last is flame thrower pipe + if( IsOfClass(prLast.m_penParticles, "Player Weapons")) + { + CPlayerWeapons &plw=(CPlayerWeapons&)*prLast.m_penParticles; + if(!(plw.GetPlayer()->GetFlags()&ENF_ALIVE)) + { + return; + } + CPlacement3D plPipe, plInFrontOfPipe; + ((CPlayerWeapons&)*prLast.m_penParticles).GetFlamerSourcePlacement(plPipe, plInFrontOfPipe); + fFollowerLiving = _pTimer->GetLerpedCurrentTick() - ((CProjectile&)*m_penParticles).m_fStartTime; + FLOAT3D vDirPipeFront; + AnglesToDirectionVector( plInFrontOfPipe.pl_OrientationAngle, vDirPipeFront); + vDirPipeFront.Normalize(); + Particles_FlameThrower(GetLerpedPlacement(), plInFrontOfPipe, + vDirLeader, vDirPipeFront, + fLeaderLiving, fInFrontLiving, en_ulID, FALSE); + } + // draw particles with another projectile + else + { + fFollowerLiving = _pTimer->GetLerpedCurrentTick() - ((CProjectile&)*m_penParticles).m_fStartTime; + FLOAT3D vDirFollower = ((CMovableModelEntity*)(CEntity*)m_penParticles)->en_vCurrentTranslationAbsolute; + vDirFollower.Normalize(); + Particles_FlameThrower(GetLerpedPlacement(), m_penParticles->GetLerpedPlacement(), + vDirLeader, vDirFollower, fLeaderLiving, fFollowerLiving, en_ulID, FALSE); + } + // draw particles with player weapons + } else if (IsOfClass(m_penParticles, "Player Weapons")) { + CPlayerWeapons &plw=(CPlayerWeapons&)*m_penParticles; + if(!(plw.GetPlayer()->GetFlags()&ENF_ALIVE)) + { + return; + } + CPlacement3D plPipe, plInFrontOfPipe; + plw.GetFlamerSourcePlacement(plPipe, plInFrontOfPipe); + FLOAT3D vDirPipeFront; + AnglesToDirectionVector( plInFrontOfPipe.pl_OrientationAngle, vDirPipeFront); + FLOAT3D vViewDir; + AnglesToDirectionVector( plPipe.pl_OrientationAngle, vViewDir); + FLOAT3D vDirFollower = vViewDir.Normalize(); + + /* + Particles_FlameThrower(GetLerpedPlacement(), plPipe, + vDirLeader, vDirFollower, + fLeaderLiving, 0.0f, en_ulID, TRUE); + */ + + Particles_FlameThrower(plInFrontOfPipe, plPipe, + vDirPipeFront, vDirFollower, + fInFrontLiving, 0.0f, en_ulID, TRUE); + + Particles_FlameThrowerStart(plPipe, plw.m_tmFlamerStart, plw.m_tmFlamerStop); + } + } + break; + } + case PRT_CATMAN_FIRE: Particles_RocketTrail(this, 1.0f); break; + case PRT_HEADMAN_FIRECRACKER: Particles_FirecrackerTrail(this); break; + case PRT_HEADMAN_ROCKETMAN: Particles_Fireball01Trail(this); break; + case PRT_HEADMAN_BOMBERMAN: Particles_BombTrail(this); break; + case PRT_LAVA_COMET: Particles_LavaTrail(this); break; + case PRT_LAVAMAN_BIG_BOMB: Particles_LavaBombTrail(this, 4.0f); break; + case PRT_LAVAMAN_BOMB: Particles_LavaBombTrail(this, 1.0f); break; + case PRT_BEAST_PROJECTILE: Particles_BeastProjectileTrail( this, 2.0f, 0.25f, 48); break; + case PRT_BEAST_BIG_PROJECTILE: + case PRT_DEMON_FIREBALL: + Particles_BeastBigProjectileTrail( this, 4.0f, 0.25f, 0.0f, 64); + Particles_AfterBurner( this, m_fStartTime, 1.0f); + break; + case PRT_DEVIL_GUIDED_PROJECTILE: + Particles_BeastBigProjectileTrail( this, 6.0f, 0.375f, 0.0f, 64); + break; + case PRT_BEAST_DEBRIS: Particles_BeastProjectileDebrisTrail(this, 0.20f); break; + case PRT_BEAST_BIG_DEBRIS: Particles_BeastProjectileDebrisTrail(this, 0.25f); break; + case PRT_SHOOTER_WOODEN_DART: Particles_RocketTrail(this, 0.25f); break; + case PRT_SHOOTER_FIREBALL: Particles_Fireball01Trail(this); break; + case PRT_SHOOTER_FLAME: { + // elapsed time + FLOAT fTimeElapsed, fParticlesTimeElapsed; + fTimeElapsed = _pTimer->GetLerpedCurrentTick() - m_fStartTime; + // not NULL or deleted + if (m_penParticles!=NULL && !(m_penParticles->GetFlags()&ENF_DELETED)) { + // draw particles with another projectile + if (IsOfClass(m_penParticles, "Projectile")) { + fParticlesTimeElapsed = _pTimer->GetLerpedCurrentTick() - ((CProjectile&)*m_penParticles).m_fStartTime; + Particles_ShooterFlame(GetLerpedPlacement(), m_penParticles->GetLerpedPlacement(), + fTimeElapsed, fParticlesTimeElapsed); + } else if (IsOfClass(m_penParticles, "Shooter")) { + Particles_ShooterFlame(GetLerpedPlacement(), + ((CShooter&)*m_penParticles).GetPlacement(), + fTimeElapsed, 0.0f); + } + } + break; + } + case PRT_METEOR: + Particles_MeteorTrail(this, m_fStretch, 1.0f, en_vCurrentTranslationAbsolute); + Particles_AfterBurner(this, m_fStartTime, m_fStretch*4.0f, 2); + break; + case PRT_AFTERBURNER_DEBRIS: + Particles_AfterBurner(this, m_fStartTime, m_fStretch); + break; + case PRT_AIRELEMENTAL_WIND: + Particles_Windblast(this, m_fStretch/4.0f, m_fStartTime+3.0f); + break; + } + } + + + + +/************************************************************ + * PLAYER ROCKET / GRENADE * + ************************************************************/ +void PlayerRocket(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + SetModel(MODEL_ROCKET); + SetModelMainTexture(TEXTURE_ROCKET); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + // play the flying sound + m_soEffect.Set3DParameters(20.0f, 2.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_FLYING, SOF_3D|SOF_LOOP); + m_fFlyTime = 30.0f; + if( GetSP()->sp_bCooperative) + { + m_fDamageAmount = 100.0f; + m_fRangeDamageAmount = 50.0f; + } + else + { + m_fDamageAmount = 75.0f; + m_fRangeDamageAmount = 75.0f; + } + m_fDamageHotSpotRange = 4.0f; + m_fDamageFallOffRange = 8.0f; + m_fSoundRange = 50.0f; + m_bExplode = TRUE; + m_bLightSource = TRUE; + m_bCanHitHimself = TRUE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 1.125f; + m_tmExpandBox = 0.1f; + m_tmInvisibility = 0.05f; + SetHealth(5.0f); + m_pmtMove = PMT_FLYING; +}; + +void WalkerRocket(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + SetModel(MODEL_ROCKET); + SetModelMainTexture(TEXTURE_ROCKET); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + // play the flying sound + m_soEffect.Set3DParameters(20.0f, 2.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_FLYING, SOF_3D|SOF_LOOP); + m_fFlyTime = 30.0f; + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + m_fDamageAmount = 40.0f; + m_fRangeDamageAmount = 20.0f; + } else { + m_fDamageAmount = 100.0f; + m_fRangeDamageAmount = 50.0f; + } + m_fDamageHotSpotRange = 4.0f; + m_fDamageFallOffRange = 8.0f; + m_fSoundRange = 50.0f; + m_bExplode = TRUE; + m_bLightSource = TRUE; + m_bCanHitHimself = TRUE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 1.125f; + m_tmExpandBox = 0.1f; + m_tmInvisibility = 0.05f; + SetHealth(5.0f); + m_pmtMove = PMT_FLYING; +}; + +void WalkerRocketExplosion(void) { + PlayerRocketExplosion(); +} + +void PlayerRocketExplosion(void) { + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + // explosion + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_ROCKET; + ese.vStretch = FLOAT3D(1,1,1); + SpawnEffect(GetPlacement(), ese); + // spawn sound event in range + if( IsDerivedFromClass( m_penLauncher, "Player")) { + SpawnRangeSound( m_penLauncher, this, SNDT_PLAYER, m_fSoundRange); + } + + // explosion debris + ese.betType = BET_EXPLOSION_DEBRIS; + SpawnEffect(GetPlacement(), ese); + + // explosion smoke + ese.betType = BET_EXPLOSION_SMOKE; + SpawnEffect(GetPlacement(), ese); + + // on plane + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) { + // stain + ese.betType = BET_EXPLOSIONSTAIN; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // shock wave + ese.betType = BET_SHOCKWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // second explosion on plane + ese.betType = BET_ROCKET_PLANE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f, ANGLE3D(0, 0, 0)), ese); + } + } +}; + + +void PlayerGrenade(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_BOUNCING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + SetModel(MODEL_GRENADE); + SetModelMainTexture(TEXTURE_GRENADE); + // start moving + LaunchAsFreeProjectile(FLOAT3D(0.0f, 5.0f, -m_fSpeed), (CMovableEntity*)&*m_penLauncher); + SetDesiredRotation(ANGLE3D(0, FRnd()*120.0f+120.0f, FRnd()*250.0f-125.0f)); + en_fBounceDampNormal = 0.75f; + en_fBounceDampParallel = 0.6f; + en_fJumpControlMultiplier = 0.0f; + en_fCollisionSpeedLimit = 45.0f; + en_fCollisionDamageFactor = 10.0f; + m_fFlyTime = 3.0f; + m_fDamageAmount = 75.0f; + m_fRangeDamageAmount = 100.0f; + m_fDamageHotSpotRange = 4.0f; + m_fDamageFallOffRange = 8.0f; + m_fSoundRange = 50.0f; + m_bExplode = TRUE; + en_fDeceleration = 25.0f; + m_bLightSource = TRUE; + m_bCanHitHimself = TRUE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 0.0f; + SetHealth(20.0f); + m_pmtMove = PMT_SLIDING; + m_tmInvisibility = 0.05f; + m_tmExpandBox = 0.1f; +}; + +void PlayerGrenadeExplosion(void) { + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + // explosion + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_GRENADE; + ese.vStretch = FLOAT3D(1,1,1); + SpawnEffect(GetPlacement(), ese); + // spawn sound event in range + if( IsDerivedFromClass( m_penLauncher, "Player")) { + SpawnRangeSound( m_penLauncher, this, SNDT_PLAYER, m_fSoundRange); + } + + // on plane + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) { + // wall stain + ese.betType = BET_EXPLOSIONSTAIN; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // shock wave + ese.betType = BET_SHOCKWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // second explosion on plane + ese.betType = BET_GRENADE_PLANE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f, ANGLE3D(0, 0, 0)), ese); + } + } +}; + + + +/************************************************************ + * PLAYER FLAME * + ************************************************************/ +void PlayerFlame(void) { + // set appearance + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_SLIDING&~EPF_TRANSLATEDBYGRAVITY&~EPF_ORIENTEDBYGRAVITY); + //SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_FLAME); + //SetModel(MODEL_BEAST_FIRE); + //SetModelMainTexture(TEXTURE_ROCKET); + + // add player's forward velocity to flame + CMovableEntity *penPlayer = (CMovableEntity*)(CEntity*)m_penLauncher; + FLOAT3D vDirection = penPlayer->en_vCurrentTranslationAbsolute; + FLOAT3D vFront = -GetRotationMatrix().GetColumn(3); + FLOAT fSpeedFwd = ClampDn( vDirection%vFront, 0.0f); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -(25.0f+fSpeedFwd)), penPlayer); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 1.0f; + m_fDamageAmount = (GetSP()->sp_bCooperative) ? 10.0f : 4.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.3f; + m_tmExpandBox = 0.1f; + m_pmtMove = PMT_SLIDING; +}; + + + +/************************************************************ + * PLAYER LASER * + ************************************************************/ +void PlayerLaserRay(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_LASER); + CModelObject *pmo = GetModelObject(); + if(pmo != NULL) + { + pmo->PlayAnim( LASERPROJECTILE_ANIM_GROW, 0); + } + SetModelMainTexture(TEXTURE_GREEN_LASER); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -120.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 3.0f; + m_fDamageAmount = 20.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_tmExpandBox = 0.1f; + // time when laser ray becomes visible + m_tmInvisibility = 0.025f; + m_pmtMove = PMT_FLYING; +}; + +void PlayerLaserWave(void) { + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + // on plane + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) { + // shock wave + ese.colMuliplier = C_dRED|CT_OPAQUE; + ese.betType = BET_LASERWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + } + } +}; + + + +/************************************************************ + * CATMAN PROJECTILE * + ************************************************************/ +void CatmanProjectile(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_CATMAN_FIRE); + SetModelMainTexture(TEXTURE_CATMAN_FIRE); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -15.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 5.0f; + m_fDamageAmount = 5.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; +}; + + + +/************************************************************ + * HEADMAN PROJECTILE * + ************************************************************/ +void HeadmanFirecracker(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_SLIDING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_HEADMAN_FIRECRACKER); + SetModelMainTexture(TEXTURE_HEADMAN_FIRECRACKER); + GetModelObject()->StretchModel(FLOAT3D(0.75f, 0.75f, 0.75f)); + ModelChangeNotify(); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -25.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, FRnd()*20.0f-10.0f)); + m_fFlyTime = 5.0f; + m_fDamageAmount = 4.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_SLIDING; +}; + +void HeadmanRocketman(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetComponents(this, *GetModelObject(), MODEL_HEADMAN_BLADE, TEXTURE_HEADMAN_BLADE, + TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddAttachmentToModel(this, *GetModelObject(), BLADE_ATTACHMENT_FLAME01, + MODEL_HEADMAN_BLADE_FLAME, TEXTURE_HEADMAN_BLADE_FLAME, 0, 0, 0); + AddAttachmentToModel(this, *GetModelObject(), BLADE_ATTACHMENT_FLAME02, + MODEL_HEADMAN_BLADE_FLAME, TEXTURE_HEADMAN_BLADE_FLAME, 0, 0, 0); + AddAttachmentToModel(this, *GetModelObject(), BLADE_ATTACHMENT_FLAME03, + MODEL_HEADMAN_BLADE_FLAME, TEXTURE_HEADMAN_BLADE_FLAME, 0, 0, 0); + GetModelObject()->StretchModel(FLOAT3D(0.5f, 0.5f, 0.5f)); + ModelChangeNotify(); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 5.0f; + m_fDamageAmount = 5.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; +}; + +void HeadmanBomberman(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_BOUNCING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + SetModel(MODEL_HEADMAN_BOMB); + SetModelMainTexture(TEXTURE_HEADMAN_BOMB); + + // start moving + LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -m_fSpeed), (CMovableEntity*)&*m_penLauncher); + SetDesiredRotation(ANGLE3D(0, FRnd()*360.0f-180.0f, FRnd()*360.0f-180.0f)); + m_fFlyTime = 2.5f; + m_fDamageAmount = 10.0f; + m_fRangeDamageAmount = 15.0f; + m_fDamageHotSpotRange = 1.0f; + m_fDamageFallOffRange = 6.0f; + m_fSoundRange = 25.0f; + m_bExplode = TRUE; + m_bLightSource = FALSE; + m_bCanHitHimself = TRUE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 0.0f; + SetHealth(5.0f); + m_pmtMove = PMT_FLYING; +}; + +void HeadmanBombermanExplosion(void) { + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + // explosion + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_BOMB; + ese.vStretch = FLOAT3D(1.0f,1.0f,1.0f); + SpawnEffect(GetPlacement(), ese); + // on plane + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) { + // wall stain + ese.betType = BET_EXPLOSIONSTAIN; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + ese.betType = BET_GRENADE_PLANE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f, ANGLE3D(0, 0, 0)), ese); + } + } +}; + +void CyborgBombExplosion(void) +{ + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + // explosion + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_BOMB; + ese.vStretch = FLOAT3D(1.0f,1.0f,1.0f); + SpawnEffect(GetPlacement(), ese); + // on plane + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) { + // wall stain + ese.betType = BET_EXPLOSIONSTAIN; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + ese.betType = BET_GRENADE_PLANE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f, ANGLE3D(0, 0, 0)), ese); + } + } +}; + +/************************************************************ + * BONEMAN PROJECTILE * + ************************************************************/ +void BonemanProjectile(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_BONEMAN_FIRE); + SetModelMainTexture(TEXTURE_BONEMAN_FIRE); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 5.0f; + m_fDamageAmount = 10.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_SLIDING; +}; + + + +/************************************************************ + * WOMAN PROJECTILE * + ************************************************************/ +void WomanProjectile(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_WOMAN_FIRE); + SetModelMainTexture(TEXTURE_WOMAN_FIRE); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 5.0f; + m_fDamageAmount = 8.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; +}; + + + +/************************************************************ + * DRAGONMAN PROJECTILE * + ************************************************************/ +void DragonmanProjectile(INDEX iType) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_ONBLOCK_SLIDE|EPF_PUSHABLE|EPF_MOVABLE); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_DRAGONMAN_FIRE); + if (iType==DRAGONMAN_STRONG) { + SetModelMainTexture(TEXTURE_DRAGONMAN_FIRE2); + } else { + SetModelMainTexture(TEXTURE_DRAGONMAN_FIRE1); + } + // start moving + if (iType==DRAGONMAN_STRONG) { + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -40.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + m_fDamageAmount = 14.0f; + } else { + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + m_fDamageAmount = 7.0f; + } + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 5.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; +}; + + + +/************************************************************ + * ELEMENTAL PROJECTILE * + ************************************************************/ +void ElementalRock(INDEX iSize, INDEX iType) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_ONBLOCK_SLIDE|EPF_PUSHABLE|EPF_MOVABLE); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + switch (iType) { + case ELEMENTAL_STONEMAN: + SetModel(MODEL_ELEM_STONE); + SetModelMainTexture(TEXTURE_ELEM_STONE); + break; + case ELEMENTAL_LAVAMAN: + SetModel(MODEL_ELEM_LAVA_STONE); + SetModelMainTexture(TEXTURE_ELEM_LAVA_STONE); + AddAttachmentToModel(this, *GetModelObject(), LAVASTONE_ATTACHMENT_FLARE, + MODEL_ELEM_LAVA_STONE_FLARE, TEXTURE_ELEM_LAVA_STONE_FLARE, 0, 0, 0); + break; + case ELEMENTAL_ICEMAN: + SetModel(MODEL_ELEM_ICE); + SetModelMainTexture(TEXTURE_ELEM_ICE); + //AddAttachmentToModel(this, *GetModelObject(), ICEPYRAMID_ATTACHMENT_FLARE, + // MODEL_ELEM_ICE_FLARE, TEXTURE_ELEM_ICE_FLARE, 0, 0, 0); + break; + } + if (iSize==ELEMENTAL_LARGE) { + GetModelObject()->StretchModel(FLOAT3D(2.25f, 2.25f, 2.25f)); + } else if (iSize==ELEMENTAL_BIG) { + GetModelObject()->StretchModel(FLOAT3D(0.75f, 0.75f, 0.75f)); + } else { + GetModelObject()->StretchModel(FLOAT3D(0.4f, 0.4f, 0.4f)); + } + ModelChangeNotify(); + // start moving + if (iSize==ELEMENTAL_LARGE) { + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -80.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + m_fDamageAmount = 20.0f; + SetHealth(40.0f); + } else if (iSize==ELEMENTAL_BIG) { + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -50.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + m_fDamageAmount = 12.5f; + SetHealth(20.0f); + } else { + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + m_fDamageAmount = 7.0f; + SetHealth(10.0f); + } + SetDesiredRotation(ANGLE3D(0, 0, FRnd()*1800.0f-900.0f)); + en_fCollisionSpeedLimit = 1000.0f; + en_fCollisionDamageFactor = 0.0f; + m_fFlyTime = 5.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_SLIDING; +}; + +void LavaManBomb(void) +{ + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_BOUNCING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + + SetModel(MODEL_ELEM_LAVA_BOMB); + SetModelMainTexture(TEXTURE_ELEM_LAVA_BOMB); + AddAttachmentToModel(this, *GetModelObject(), LAVABOMB_ATTACHMENT_FLARE, + MODEL_ELEM_LAVA_BOMB_FLARE, TEXTURE_ELEM_LAVA_BOMB_FLARE, 0, 0, 0); + + if (m_prtType == PRT_LAVAMAN_BIG_BOMB) + { + GetModelObject()->StretchModel(FLOAT3D(6.0f, 6.0f, 6.0f)); + m_fDamageAmount = 20.0f; + m_fRangeDamageAmount = 10.0f; + m_fDamageHotSpotRange = 7.5f; + m_fDamageFallOffRange = 15.0f; + SetHealth(30.0f); + } + else if (m_prtType == PRT_LAVAMAN_BOMB) + { + GetModelObject()->StretchModel(FLOAT3D(1.5f, 1.5f, 1.5f)); + m_fDamageAmount = 10.0f; + m_fRangeDamageAmount = 5.0f; + m_fDamageHotSpotRange = 5.0f; + m_fDamageFallOffRange = 10.0f; + SetHealth(10.0f); + } + ModelChangeNotify(); + + // start moving + LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -m_fSpeed), (CMovableEntity*)&*m_penLauncher); + SetDesiredRotation(ANGLE3D(0, FRnd()*360.0f-180.0f, 0.0f)); + m_fFlyTime = 20.0f; + m_fSoundRange = 50.0f; + m_bExplode = TRUE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = TRUE; + m_pmtMove = PMT_FLYING; + m_fWaitAfterDeath = 4.0f; + + + if (m_prtType == PRT_LAVAMAN_BIG_BOMB) + { + // spawn particle debris + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 4.0f; + eSpawnSpray.fSizeMultiplier = 0.5f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = FLOAT3D(0,-0.5f,0); + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); + } +} + +void LavamanBombExplosion(void) +{ + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) + { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) + { + // shock wave + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_SHOCKWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + } + } + + // shock wave + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_LIGHT_CANNON; + ese.vStretch = FLOAT3D(4,4,4); + SpawnEffect(GetPlacement(), ese); + + // spawn particle debris + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 4.0f; + eSpawnSpray.fSizeMultiplier = 0.5f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = en_vCurrentTranslationAbsolute/32.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); + + // spawn smaller lava bombs + for( INDEX iDebris=0; iDebris<3+IRnd()%3; iDebris++) + { + FLOAT fHeading = (FRnd()-0.5f)*180.0f; + FLOAT fPitch = 10.0f+FRnd()*40.0f; + FLOAT fSpeed = 10.0+FRnd()*50.0f; + + // launch + CPlacement3D pl = GetPlacement(); + pl.pl_PositionVector(2) += 2.0f; + pl.pl_OrientationAngle = m_penLauncher->GetPlacement().pl_OrientationAngle; + pl.pl_OrientationAngle(1) += AngleDeg(fHeading); + pl.pl_OrientationAngle(2) = AngleDeg(fPitch); + + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_LAVAMAN_BOMB; + eLaunch.fSpeed = fSpeed; + penProjectile->Initialize(eLaunch); + + // spawn particle debris + CPlacement3D plSpray = pl; + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( penProjectile); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 1.0f; + eSpawnSpray.fSizeMultiplier = 0.5f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = FLOAT3D(0,-0.5f,0); + eSpawnSpray.penOwner = penProjectile; + penSpray->Initialize( eSpawnSpray); + } +}; + +void LavamanBombDebrisExplosion(void) +{ + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + // spawn shock wave + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) + { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) + { + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_SHOCKWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + } + } + + // spawn explosion + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_LIGHT_CANNON; + ese.vStretch = FLOAT3D(2,2,2); + SpawnEffect(GetPlacement(), ese); + + // spawn particle debris + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fSizeMultiplier = 4.0f; + eSpawnSpray.fDamagePower = 2.0f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = en_vCurrentTranslationAbsolute/16.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); +} + +/************************************************************ + * HUANMAN PROJECTILE * + ************************************************************/ +void HuanmanProjectile(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetComponents(this, *GetModelObject(), MODEL_HUANMAN_FIRE, TEXTURE_HUANMAN_FIRE, + TEX_REFL_LIGHTMETAL01, TEX_SPEC_STRONG, 0); + AddAttachmentToModel(this, *GetModelObject(), PROJECTILE_ATTACHMENT_FLARE, + MODEL_HUANMAN_FLARE, TEXTURE_HUANMAN_FLARE, 0, 0, 0); + GetModelObject()->StretchModel(FLOAT3D(0.5f, 0.5f, 0.5f)); + ModelChangeNotify(); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 5.0f; + m_fDamageAmount = 10.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; +}; + +/************************************************************ + * BEAST PROJECTILE * + ************************************************************/ +void BeastProjectile(void) { + // we need target for guied misile + if (IsDerivedFromClass(m_penLauncher, "Enemy Base")) { + m_penTarget = ((CEnemyBase *) &*m_penLauncher)->m_penEnemy; + } + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_FREE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + + SetModel(MODEL_BEAST_FIRE); + SetModelMainTexture(TEXTURE_BEAST_FIRE); + GetModelObject()->StretchModel(FLOAT3D(1.5f, 1.5f, 1.5f)); + + ModelChangeNotify(); + // play the flying sound + m_soEffect.Set3DParameters(20.0f, 2.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_BEAST_FLYING, SOF_3D|SOF_LOOP); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -60.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 10.0f; + m_fDamageAmount = 10.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_GUIDED; + m_fGuidedMaxSpeedFactor = 30.0f; + m_aRotateSpeed = 175.0f; + SetHealth(10.0f); +}; + +void BeastBigProjectile(void) { + // we need target for guided misile + if (IsDerivedFromClass(m_penLauncher, "Enemy Base")) { + m_penTarget = ((CEnemyBase *) &*m_penLauncher)->m_penEnemy; + } + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_FREE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + + SetModel(MODEL_BEAST_FIRE); + SetModelMainTexture(TEXTURE_BEAST_BIG_FIRE); + GetModelObject()->StretchModel(FLOAT3D(2.5f, 2.5f, 2.5f)); + + ModelChangeNotify(); + // play the flying sound + m_soEffect.Set3DParameters(50.0f, 2.0f, 1.0f, 0.75f); + PlaySound(m_soEffect, SOUND_BEAST_FLYING, SOF_3D|SOF_LOOP); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -60.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 10.0f; + m_fDamageAmount = 20.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_GUIDED_FAST; + m_fGuidedMaxSpeedFactor = 90.0f; + SetHealth(10000.0f); + m_aRotateSpeed = 100.0f; +}; + +void BeastDebris(void) +{ + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_BOUNCING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + + SetModel(MODEL_BEAST_FIRE); + GetModelObject()->StretchModel(FLOAT3D(0.75f, 0.75f, 0.75f)); + SetModelMainTexture(TEXTURE_BEAST_FIRE); + GetModelObject()->StartAnim(1+(ULONG)FRnd()*5.0f); + + ModelChangeNotify(); + // start moving + LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -20.0f), (CMovableEntity*)&*m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 10.0f; + m_fDamageAmount = 0.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; + SetHealth(1.0f); + m_aRotateSpeed = 100.0f; +}; + +void BeastBigDebris(void) +{ + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_BOUNCING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + + SetModel(MODEL_BEAST_FIRE); + SetModelMainTexture(TEXTURE_BEAST_BIG_FIRE); + GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f)); + GetModelObject()->StartAnim(1+(ULONG)FRnd()*5.0f); + + ModelChangeNotify(); + // start moving + LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -20.0f), (CMovableEntity*)&*m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 10.0f; + m_fDamageAmount = 0.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; + SetHealth(1.0f); + m_aRotateSpeed = 100.0f; +}; + +void BeastDebrisExplosion(void) +{ + // explosion + ESpawnEffect ese; + ese.colMuliplier = C_GREEN|CT_OPAQUE; + ese.betType = BET_LIGHT_CANNON; + ese.vStretch = FLOAT3D(0.75,0.75,0.75); + SpawnEffect(GetPlacement(), ese); + + // spawn particles + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 2.0f; + eSpawnSpray.fSizeMultiplier = 0.75f; + eSpawnSpray.sptType = SPT_BEAST_PROJECTILE_SPRAY; + eSpawnSpray.vDirection = en_vCurrentTranslationAbsolute/64.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); +} + +void BeastBigDebrisExplosion(void) +{ + // explosion + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_LIGHT_CANNON; + ese.vStretch = FLOAT3D(1,1,1); + SpawnEffect(GetPlacement(), ese); + + // spawn particles + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 2.0f; + eSpawnSpray.fSizeMultiplier = 1.0f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = en_vCurrentTranslationAbsolute/64.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); +} + +void BeastProjectileExplosion(void) +{ + // explosion + ESpawnEffect ese; + ese.colMuliplier = C_GREEN|CT_OPAQUE; + ese.betType = BET_LIGHT_CANNON; + ese.vStretch = FLOAT3D(1.25,1.25,1.25); + SpawnEffect(GetPlacement(), ese); + + // particles + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 2.0f; + eSpawnSpray.fSizeMultiplier = 1.0f; + eSpawnSpray.sptType = SPT_BEAST_PROJECTILE_SPRAY; + eSpawnSpray.vDirection = en_vCurrentTranslationAbsolute/64.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); + + FLOAT fHeading = 20.0f+(FRnd()-0.5f)*60.0f; + // debris + for( INDEX iDebris=0; iDebris<2; iDebris++) + { + FLOAT fPitch = 10.0f+FRnd()*10.0f; + FLOAT fSpeed = 5.0+FRnd()*20.0f; + + // launch + CPlacement3D pl = GetPlacement(); + pl.pl_OrientationAngle(1) += AngleDeg(fHeading); + // turn to other way + fHeading = -fHeading; + pl.pl_OrientationAngle(2) = AngleDeg(fPitch); + + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_BEAST_DEBRIS; + eLaunch.fSpeed = fSpeed; + penProjectile->Initialize(eLaunch); + + // spawn particle debris + CPlacement3D plSpray = pl; + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( penProjectile); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 0.5f; + eSpawnSpray.fSizeMultiplier = 0.25f; + eSpawnSpray.sptType = SPT_BEAST_PROJECTILE_SPRAY; + eSpawnSpray.vDirection = FLOAT3D(0,-0.5f,0); + eSpawnSpray.penOwner = penProjectile; + penSpray->Initialize( eSpawnSpray); + } +} + +void BeastBigProjectileExplosion(void) +{ + // explosion + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_LIGHT_CANNON; + ese.vStretch = FLOAT3D(2,2,2); + SpawnEffect(GetPlacement(), ese); + + // particles + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 4.0f; + eSpawnSpray.fSizeMultiplier = 0.5f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = en_vCurrentTranslationAbsolute/32.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); + + // debris + for( INDEX iDebris=0; iDebris<3+IRnd()%2; iDebris++) + { + FLOAT fHeading = (FRnd()-0.5f)*180.0f; + FLOAT fPitch = 10.0f+FRnd()*40.0f; + FLOAT fSpeed = 10.0+FRnd()*50.0f; + + // launch + CPlacement3D pl = GetPlacement(); + pl.pl_OrientationAngle(1) += AngleDeg(fHeading); + pl.pl_OrientationAngle(2) += AngleDeg(fPitch); + + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_BEAST_BIG_DEBRIS; + eLaunch.fSpeed = fSpeed; + penProjectile->Initialize(eLaunch); + + // spawn particle debris + CPlacement3D plSpray = pl; + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( penProjectile); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 1.0f; + eSpawnSpray.fSizeMultiplier = 0.5f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = FLOAT3D(0,-0.5f,0); + eSpawnSpray.penOwner = penProjectile; + penSpray->Initialize( eSpawnSpray); + } +} + +/************************************************************ + * FISHMAN PROJECTILE * + ************************************************************/ +void FishmanProjectile(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetComponents(this, *GetModelObject(), MODEL_FISHMAN_FIRE, TEXTURE_FISHMAN_FIRE, 0, 0, 0); + ModelChangeNotify(); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 5.0f; + m_fDamageAmount = 5.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; +}; + + + +/************************************************************ + * MANTAMAN PROJECTILE * + ************************************************************/ +void MantamanProjectile(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetComponents(this, *GetModelObject(), MODEL_MANTAMAN_FIRE, TEXTURE_MANTAMAN_FIRE, 0, 0, 0); + ModelChangeNotify(); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -35.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 5.0f; + m_fDamageAmount = 7.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; +}; + + +/************************************************************ + * DEVIL PROJECTILES * + ************************************************************/ +void DevilLaser(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetComponents(this, *GetModelObject(), MODEL_CYBORG_LASER, TEXTURE_CYBORG_LASER, 0, 0, 0); + GetModelObject()->StretchModel(FLOAT3D(4.0f, 4.0f, 2.0f)); + ModelChangeNotify(); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -DEVIL_LASER_SPEED), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 5.0f; + m_fDamageAmount = 10.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; +}; + +void DevilRocket(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + SetModel(MODEL_ROCKET); + SetModelMainTexture(TEXTURE_ROCKET); + GetModelObject()->StretchModel(FLOAT3D(12.0f, 12.0f, 8.0f)); + ModelChangeNotify(); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -DEVIL_ROCKET_SPEED), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + // play the flying sound + m_soEffect.Set3DParameters(100.0f, 2.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_FLYING, SOF_3D|SOF_LOOP); + m_fFlyTime = 50.0f; + m_fDamageAmount = 50.0f; + m_fRangeDamageAmount = 50.0f; + m_fDamageHotSpotRange = 2.0f; + m_fDamageFallOffRange = 10.0f; + m_fSoundRange = 100.0f; + m_bExplode = TRUE; + m_bLightSource = TRUE; + m_bCanHitHimself = TRUE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 1.125f; + m_tmExpandBox = 10000.0f; + m_tmInvisibility = 0.05f; + SetHealth(25.0f); + m_pmtMove = PMT_FLYING; +}; + +void DevilRocketExplosion(void) { + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + // explosion + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_GRENADE; + ese.vStretch = FLOAT3D(2,2,2); + SpawnEffect(GetPlacement(), ese); + // spawn sound event in range + if( IsDerivedFromClass( m_penLauncher, "Player")) { + SpawnRangeSound( m_penLauncher, this, SNDT_PLAYER, m_fSoundRange); + } + + // on plane + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) { + // stain + ese.betType = BET_EXPLOSIONSTAIN; + ese.vNormal = FLOAT3D(vPlaneNormal); + ese.vStretch = FLOAT3D(2,2,2); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // shock wave + ese.betType = BET_SHOCKWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + ese.vStretch = FLOAT3D(2,2,2); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // second explosion on plane + ese.betType = BET_GRENADE_PLANE; + ese.vNormal = FLOAT3D(vPlaneNormal); + ese.vStretch = FLOAT3D(2,2,2); + SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f, ANGLE3D(0, 0, 0)), ese); + } + } +}; + +void DevilGuidedProjectile(void) { + // we need target for guied misile + if (IsDerivedFromClass(m_penLauncher, "Enemy Base")) { + m_penTarget = ((CEnemyBase *) &*m_penLauncher)->m_penEnemy; + } + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_FREE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + + SetModel(MODEL_BEAST_FIRE); + SetModelMainTexture(TEXTURE_BEAST_BIG_FIRE); + GetModelObject()->StretchModel(FLOAT3D(2.5f, 2.5f, 2.5f)); + ModelChangeNotify(); + // play the flying sound + m_soEffect.Set3DParameters(250.0f, 2.0f, 1.0f, 0.75f); + PlaySound(m_soEffect, SOUND_FLYING, SOF_3D|SOF_LOOP); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -80.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 20.0f; + m_fDamageAmount = 20.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_GUIDED; + m_fGuidedMaxSpeedFactor = 30.0f; + SetHealth(30.0f); + m_aRotateSpeed = 100.0f; +}; + +void DevilGuidedProjectileExplosion(void) +{ + // explosion + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_LIGHT_CANNON; + ese.vStretch = FLOAT3D(4,4,4); + SpawnEffect(GetPlacement(), ese); + + // particles + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 8.0f; + eSpawnSpray.fSizeMultiplier = 1.0f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = en_vCurrentTranslationAbsolute/32.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); + + // debris + for( INDEX iDebris=0; iDebris<3+IRnd()%2; iDebris++) + { + FLOAT fHeading = (FRnd()-0.5f)*180.0f; + FLOAT fPitch = 10.0f+FRnd()*40.0f; + FLOAT fSpeed = 10.0+FRnd()*50.0f; + + // launch + CPlacement3D pl = GetPlacement(); + pl.pl_OrientationAngle(1) += AngleDeg(fHeading); + pl.pl_OrientationAngle(2) += AngleDeg(fPitch); + + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_BEAST_BIG_DEBRIS; + eLaunch.fSpeed = fSpeed; + penProjectile->Initialize(eLaunch); + + // spawn particle debris + CPlacement3D plSpray = pl; + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( penProjectile); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 2.0f; + eSpawnSpray.fSizeMultiplier = 1.0f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = FLOAT3D(0,-0.5f,0); + eSpawnSpray.penOwner = penProjectile; + penSpray->Initialize( eSpawnSpray); + } +} + +/************************************************************ + * CYBORG LASER / PROJECTILE * + ************************************************************/ +void CyborgLaser(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetComponents(this, *GetModelObject(), MODEL_CYBORG_LASER, TEXTURE_CYBORG_LASER, 0, 0, 0); + ModelChangeNotify(); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -60.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 4.0f; + m_fDamageAmount = 5.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; +}; + +void CyborgBomb(void) +{ + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_BOUNCING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + SetModel(MODEL_CYBORG_BOMB); + SetModelMainTexture(TEXTURE_CYBORG_BOMB); + ModelChangeNotify(); + // just freefall + LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -m_fSpeed), (CMovableEntity*)&*m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 2.5f; + m_fDamageAmount = 10.0f; + m_fRangeDamageAmount = 15.0f; + m_fDamageHotSpotRange = 1.0f; + m_fDamageFallOffRange = 6.0f; + m_fSoundRange = 25.0f; + m_bExplode = TRUE; + m_bLightSource = FALSE; + m_bCanHitHimself = TRUE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 0.0f; + SetHealth(5.0f); + m_pmtMove = PMT_FLYING; +}; + + + +/************************************************************ + * LAVA BALL * + ************************************************************/ +void LavaBall(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_FALL); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetModel(MODEL_LAVA); + SetModelMainTexture(TEXTURE_LAVA); + AddAttachment(0, MODEL_LAVA_FLARE, TEXTURE_LAVA_FLARE); + + // start moving + LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -m_fSpeed), (CMovableEntity*)&*m_penLauncher); + SetDesiredRotation(ANGLE3D(0, FRnd()*360.0f-180.0f, FRnd()*360.0f-180.0f)); + m_fFlyTime = 5.0f; + m_fDamageAmount = 5.0f; + m_fRangeDamageAmount = 5.0f; + m_fDamageHotSpotRange = 1.0f; + m_fDamageFallOffRange = 4.0f; + m_fSoundRange = 0.0f; + m_bExplode = TRUE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_FLYING; +}; + +void LavaBallExplosion(void) { + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) { + // shock wave + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_SHOCKWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + } + } +}; + +/************************************************************ + * G R U N T L A S E R * + ************************************************************/ + +void GruntSoldierLaser(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_GRUNT_PROJECTILE); + CModelObject *pmo = GetModelObject(); + if(pmo != NULL) + { + pmo->PlayAnim(GRUNTPROJECTILE_ANIM_DEFAULT, 0); + } + SetModelMainTexture(TEXTURE_GRUNT_PROJECTILE_01); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -45.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 3.0f; + m_fDamageAmount = 10.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_tmExpandBox = 0.1f; + // time when laser ray becomes visible + m_tmInvisibility = 0.025f; + m_pmtMove = PMT_FLYING; +}; + +void GruntCommanderLaser(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_GRUNT_PROJECTILE); + CModelObject *pmo = GetModelObject(); + if(pmo != NULL) + { + pmo->PlayAnim(GRUNTPROJECTILE_ANIM_DEFAULT, 0); + } + SetModelMainTexture(TEXTURE_GRUNT_PROJECTILE_02); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -55.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 3.0f; + m_fDamageAmount = 10.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_tmExpandBox = 0.1f; + // time when laser ray becomes visible + m_tmInvisibility = 0.025f; + m_pmtMove = PMT_FLYING; +}; + + +/************************************************************ + * G U F F Y R O C K E T * + ************************************************************/ + +void GuffyProjectile(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetModel(MODEL_GUFFY_PROJECTILE); + SetModelMainTexture(TEXTURE_GUFFY_PROJECTILE); + GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f)); + + CModelObject *pmo = GetModelObject(); + if(pmo != NULL) + { + pmo->PlayAnim(GUFFYPROJECTILE_ANIM_ROTATE01, AOF_LOOPING); + } + + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -50.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + // play the flying sound + m_soEffect.Set3DParameters(20.0f, 2.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_FLYING, SOF_3D|SOF_LOOP); + m_fFlyTime = 30.0f; + m_fDamageAmount = 10.0f; + m_fRangeDamageAmount = 10.0f; + m_fDamageHotSpotRange = 4.0f; + m_fDamageFallOffRange = 8.0f; + m_fSoundRange = 50.0f; + m_bExplode = TRUE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 1.125f; + m_tmExpandBox = 0.1f; + m_tmInvisibility = 0.05f; + SetHealth(10000.0f); + m_pmtMove = PMT_FLYING; +}; + +void GuffyProjectileExplosion(void) { + PlayerRocketExplosion(); +} + + +/************************************************************ + * D E M O N F I R E B A L L * + ************************************************************/ + +void DemonFireball(void) { + // we need target for guided misile + if (IsDerivedFromClass(m_penLauncher, "Enemy Base")) { + m_penTarget = ((CEnemyBase *) &*m_penLauncher)->m_penEnemy; + } + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_FREE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + + SetModel(MODEL_DEMON_FIREBALL); + SetModelMainTexture(TEXTURE_DEMON_FIREBALL); + GetModelObject()->StretchModel(FLOAT3D(2.5f, 2.5f, 2.5f)); + + ModelChangeNotify(); + // play the flying sound + m_soEffect.Set3DParameters(50.0f, 2.0f, 1.0f, 0.75f); + PlaySound(m_soEffect, SOUND_BEAST_FLYING, SOF_3D|SOF_LOOP); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -100.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 12.0f; + m_fDamageAmount = 20.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_GUIDED_FAST; + m_fGuidedMaxSpeedFactor = 90.0f; + SetHealth(10000.0f); + m_aRotateSpeed = 200.0f; +}; + +void DemonFireballExplosion(void) +{ + // explosion + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_LIGHT_CANNON; + ese.vStretch = FLOAT3D(2,2,2); + SpawnEffect(GetPlacement(), ese); + + // particles + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 4.0f; + eSpawnSpray.fSizeMultiplier = 0.5f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = en_vCurrentTranslationAbsolute/32.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); +} + +/************************************************************ + * L A R V A P R O J E C T I L E S * + ************************************************************/ + +void LarvaPlasma(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetModel(MODEL_LARVA_PLASMA_BALL); + SetModelMainTexture(TEXTURE_LARVA_PLASMA_BALL); + AddAttachmentToModel(this, *GetModelObject(), PLASMAGUN_ATTACHMENT_PROJECTILE, + MODEL_LARVA_PLASMA, TEXTURE_LARVA_PLASMA, 0, 0, 0); + + GetModelObject()->StretchModel(FLOAT3D(2.5f, 2.5f, 2.5f)); + ModelChangeNotify(); + + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -60.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + // play the flying sound + m_soEffect.Set3DParameters(20.0f, 2.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_FLYING, SOF_3D|SOF_LOOP); + m_fFlyTime = 30.0f; + if( GetSP()->sp_bCooperative) + { + m_fDamageAmount = 30.0f; + m_fRangeDamageAmount = 30.0f; + } + else + { + m_fDamageAmount = 25.0f; + m_fRangeDamageAmount = 25.0f; + } + m_fDamageHotSpotRange = 4.0f; + m_fDamageFallOffRange = 8.0f; + m_fSoundRange = 50.0f; + m_bExplode = TRUE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.05f; + m_tmExpandBox = 0.1f; + m_tmInvisibility = 0.05f; + SetHealth(100.0f); + m_iRebounds = 4; + m_pmtMove = PMT_FLYING_REBOUNDING; +} + +void LarvaPlasmaExplosion(void) { + // explosion + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_LIGHT_CANNON; + ese.vStretch = FLOAT3D(2,2,2); + SpawnEffect(GetPlacement(), ese); + + // particles + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 1.0f; + eSpawnSpray.fSizeMultiplier = 0.25f; + eSpawnSpray.sptType = SPT_PLASMA; + eSpawnSpray.vDirection = FLOAT3D(0.0f, 2.5f, 0.0f); + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); +} + +void LarvaTail(void) { + + // we need target for guied misile + if (IsDerivedFromClass(m_penLauncher, "Enemy Base")) { + m_penTarget = ((CEnemyBase *) &*m_penLauncher)->m_penEnemy; + } + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_SLIDING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + + SetModel(MODEL_LARVA_TAIL); + SetModelMainTexture(TEXTURE_LARVA_TAIL); + GetModelObject()->StretchModel(FLOAT3D(4.0f, 4.0f, 4.0f)); + + ModelChangeNotify(); + // play the flying sound + m_soEffect.Set3DParameters(50.0f, 10.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_LARVETTE, SOF_3D|SOF_LOOP); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 12.0f; + m_fDamageAmount = 10.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_GUIDED_SLIDING; + m_aRotateSpeed = 275.0f; + SetHealth(10.0f); +} + +void LarvaTailExplosion(void) { + PlayerRocketExplosion(); +} + + +/***************************************************************** + * A I R E L E M E N T A L P R O J E C T I L E S * + *****************************************************************/ + +void WindBlast(void) { + // set appearance + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_SLIDING); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_WINDBLAST); + SetModelMainTexture(TEXTURE_WINDBLAST); + GetModelObject()->StretchModel(FLOAT3D(3.0f, 3.0f, 3.0f)); + ModelChangeNotify(); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -50.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 5.0f; + m_fDamageAmount = 20.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.0f; + m_pmtMove = PMT_SLIDING; +} + +/************************************************************ + * M E T E O R * + ************************************************************/ + +void Meteor() { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + + SetModel(MODEL_ELEM_LAVA_BOMB); + SetModelMainTexture(TEXTURE_ELEM_LAVA_BOMB); + /*AddAttachmentToModel(this, *GetModelObject(), LAVABOMB_ATTACHMENT_FLARE, + MODEL_ELEM_LAVA_BOMB_FLARE, TEXTURE_ELEM_LAVA_BOMB_FLARE, 0, 0, 0);*/ + + GetModelObject()->StretchModel(FLOAT3D(m_fStretch, m_fStretch, m_fStretch)); + ModelChangeNotify(); + + Particles_AfterBurner_Prepare(this); + + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -m_fSpeed), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + // play the flying sound + m_soEffect.Set3DParameters(250.0f, 10.0f, 2.0f, 1.0f); + PlaySound(m_soEffect, SOUND_FLYING, SOF_3D|SOF_LOOP); + m_fFlyTime = 30.0f; + m_fDamageAmount = 100.0f; + m_fRangeDamageAmount = 100.0f; + m_fDamageHotSpotRange = 15.0f; + m_fDamageFallOffRange = 30.0f; + m_fSoundRange = 100.0f; + m_bExplode = TRUE; + m_bLightSource = FALSE; + m_bCanHitHimself = TRUE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = GetSoundLength(SOUND_METEOR_BLAST)+0.25f; + m_tmExpandBox = 0.1f; + m_tmInvisibility = 0.05f; + SetHealth(100.0f); + m_pmtMove = PMT_FLYING; +} + +void MeteorExplosion() { + //LavamanBombExplosion(); + //PlayerRocketExplosion(); + // spawn particle debris + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 4.0f; + eSpawnSpray.fSizeMultiplier = 0.5f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = en_vCurrentTranslationAbsolute/32.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); + + ESpawnEffect ese; + FLOAT3D vPoint; + FLOATplane3D vPlaneNormal; + FLOAT fDistanceToEdge; + + // explosion + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_CANNON; + ese.vStretch = FLOAT3D(5,5,5); + SpawnEffect(GetPlacement(), ese); + // spawn sound event in range + if( IsDerivedFromClass( m_penLauncher, "Player")) { + SpawnRangeSound( m_penLauncher, this, SNDT_PLAYER, m_fSoundRange); + } + + // explosion debris + ese.betType = BET_EXPLOSION_DEBRIS; + SpawnEffect(GetPlacement(), ese); + + // explosion smoke + ese.betType = BET_EXPLOSION_SMOKE; + SpawnEffect(GetPlacement(), ese); + + // on plane + if (GetNearestPolygon(vPoint, vPlaneNormal, fDistanceToEdge)) { + if ((vPoint-GetPlacement().pl_PositionVector).Length() < 3.5f) { + // stain + ese.betType = BET_EXPLOSIONSTAIN; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // shock wave + ese.betType = BET_SHOCKWAVE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint, ANGLE3D(0, 0, 0)), ese); + // second explosion on plane + ese.betType = BET_ROCKET_PLANE; + ese.vNormal = FLOAT3D(vPlaneNormal); + SpawnEffect(CPlacement3D(vPoint+ese.vNormal/50.0f, ANGLE3D(0, 0, 0)), ese); + } + } + m_soExplosion.Set3DParameters(150.0f, 10.0f, 1.5f, 1.0f); + PlaySound(m_soExplosion, SOUND_METEOR_BLAST, SOF_3D); +} + + +/************************************************************ + * S H O O T E R S * + ************************************************************/ + +void ShooterWoodenDart(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + SetModel(MODEL_SHTR_WOODEN_DART); + SetModelMainTexture(TEX_SHTR_WOODEN_DART); + + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + /*// play the flying sound + m_soEffect.Set3DParameters(20.0f, 2.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_FLYING, SOF_3D|SOF_LOOP);*/ + m_fFlyTime = 10.0f; + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + m_fDamageAmount = 5.0f; + } else { + m_fDamageAmount = 10.0f; + } + m_bExplode = FALSE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 1.125f; + m_tmExpandBox = 0.1f; + m_tmInvisibility = 0.05f; + SetHealth(5.0f); + m_pmtMove = PMT_FLYING; +}; + +void ShooterWoodenDartExplosion() { + // particles + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 0.5f; + eSpawnSpray.fSizeMultiplier = 0.1f; + eSpawnSpray.sptType = SPT_WOOD; + eSpawnSpray.vDirection = -en_vCurrentTranslationAbsolute/32.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); +}; + +void ShooterFireball(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + SetModel(MODEL_BEAST_FIRE); + SetModelMainTexture(TEXTURE_BEAST_BIG_FIRE); + GetModelObject()->StretchModel(FLOAT3D(0.25f, 0.25f, 0.25f)); + ModelChangeNotify(); + + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + /*// play the flying sound + m_soEffect.Set3DParameters(20.0f, 2.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_FLYING, SOF_3D|SOF_LOOP);*/ + m_fFlyTime = 10.0f; + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + m_fDamageAmount = 7.5f; + } else { + m_fDamageAmount = 15.0f; + } + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = TRUE; + m_fWaitAfterDeath = 0.125f; + m_tmExpandBox = 0.1f; + m_tmInvisibility = 0.05f; + SetHealth(5.0f); + m_pmtMove = PMT_FLYING; +}; + +void ShooterFireballExplosion() { + // particles + CPlacement3D plSpray = GetPlacement(); + CEntityPointer penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + penSpray->SetParent( this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + eSpawnSpray.fDamagePower = 1.0f; + eSpawnSpray.fSizeMultiplier = 0.5f; + eSpawnSpray.sptType = SPT_LAVA_STONES; + eSpawnSpray.vDirection = -en_vCurrentTranslationAbsolute/32.0f; + eSpawnSpray.penOwner = this; + penSpray->Initialize( eSpawnSpray); +}; + +void ShooterFlame(void) { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_PROJECTILE_FLYING); + SetCollisionFlags(ECF_PROJECTILE_SOLID); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_FLAME); + // start moving + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -10.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + SetDesiredRotation(ANGLE3D(0, 0, 0)); + m_fFlyTime = 1.0f; + m_fDamageAmount = 3.0f; + m_fSoundRange = 0.0f; + m_bExplode = FALSE; + m_bLightSource = TRUE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 0.3f; + m_pmtMove = PMT_FLYING; +}; + +void AfterburnerDebris(void) +{ + Particles_AfterBurner_Prepare(this); + // set appearance + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_FALL); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + // start moving + LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -m_fSpeed), (CMovableEntity*)&*m_penLauncher); + SetDesiredRotation(ANGLE3D(0, FRnd()*360.0f-180.0f, FRnd()*360.0f-180.0f)); + m_fFlyTime = 10.0f; + m_fDamageAmount = 0.0f; + m_fRangeDamageAmount = 0.0f; + m_fDamageHotSpotRange = 0.0f; + m_fDamageFallOffRange = 0.0f; + m_fSoundRange = 0.0f; + m_bExplode = TRUE; + m_bLightSource = FALSE; + m_bCanHitHimself = FALSE; + m_bCanBeDestroyed = FALSE; + m_fWaitAfterDeath = 2.0f; + m_pmtMove = PMT_FLYING; +} + + +/************************************************************ + * C O M M O N F U N C T I O N S * + ************************************************************/ + +// projectile touch his valid target +void ProjectileTouch(CEntityPointer penHit) +{ + // explode if needed + ProjectileHit(); + + // direct damage + FLOAT3D vDirection; + FLOAT fTransLen = en_vIntendedTranslation.Length(); + if( fTransLen>0.5f) + { + vDirection = en_vIntendedTranslation/fTransLen; + } + else + { + vDirection = -en_vGravityDir; + } + + // spawn flame + const FLOAT fDamageMul = GetSeriousDamageMultiplier(m_penLauncher); + if ((m_prtType==PRT_FLAME||m_prtType==PRT_SHOOTER_FLAME) && m_fWaitAfterDeath>0.0f) { + // don't burn the same entity twice while passing through it + if (m_penLastDamaged==penHit) { + return; + } else { + m_penLastDamaged=penHit; + } + + // don't spawn flame on AirElemental + BOOL bSpawnFlame=TRUE; + BOOL bInflictDamage=TRUE; + if (IsOfClass(penHit, "AirElemental")) + { + bSpawnFlame=FALSE; + } + + EntityInfo *pei=(EntityInfo *)penHit->GetEntityInfo(); + if(pei!=NULL && pei->Eeibt==EIBT_ICE) + { + bSpawnFlame=FALSE; + bInflictDamage=FALSE; + } + + if( bSpawnFlame) + { + SpawnFlame(m_penLauncher, penHit, GetPlacement().pl_PositionVector); + } + if(bInflictDamage) + { + InflictDirectDamage(penHit, m_penLauncher, DMT_BURNING, m_fDamageAmount*fDamageMul, + GetPlacement().pl_PositionVector, vDirection); + } + + // don't damage the same entity twice (wind blast) + } else if (m_prtType==PRT_AIRELEMENTAL_WIND) { + if (penHit==m_penLastDamaged) { + return; + } else { + m_penLastDamaged=penHit; + } + InflictDirectDamage(penHit, m_penLauncher, DMT_PROJECTILE, m_fDamageAmount*fDamageMul, + GetPlacement().pl_PositionVector, vDirection); + + // other projectiles + } else { + InflictDirectDamage(penHit, m_penLauncher, DMT_PROJECTILE, m_fDamageAmount*fDamageMul, + GetPlacement().pl_PositionVector, vDirection); + } +}; + + +// projectile hit (or time expired or can't move any more) +void ProjectileHit(void) +{ + // explode ... + if (m_bExplode) { + const FLOAT fDamageMul = GetSeriousDamageMultiplier(m_penLauncher); + InflictRangeDamage(m_penLauncher, DMT_EXPLOSION, m_fRangeDamageAmount*fDamageMul, + GetPlacement().pl_PositionVector, m_fDamageHotSpotRange, m_fDamageFallOffRange); + } + // sound event + if (m_fSoundRange>0.0f && IsDerivedFromClass( m_penLauncher, "Player")) + { + ESound eSound; + eSound.EsndtSound = SNDT_EXPLOSION; + eSound.penTarget = m_penLauncher; + SendEventInRange(eSound, FLOATaabbox3D(GetPlacement().pl_PositionVector, m_fSoundRange)); + } +}; + + +// spawn effect +void SpawnEffect(const CPlacement3D &plEffect, const ESpawnEffect &eSpawnEffect) { + CEntityPointer penEffect = CreateEntity(plEffect, CLASS_BASIC_EFFECT); + penEffect->Initialize(eSpawnEffect); +}; + + + +/************************************************************ + * S O U N D S * + ************************************************************/ +void BounceSound(void) { + switch (m_prtType) { + case PRT_GRENADE: + if (en_vCurrentTranslationAbsolute.Length() > 3.0f) { + m_soEffect.Set3DParameters(20.0f, 2.0f, 1.0f, 1.0f); + PlaySound(m_soEffect, SOUND_GRENADE_BOUNCE, SOF_3D); + } + break; + } +}; + + + +// Calculate current rotation speed to rich given orientation in future +ANGLE GetRotationSpeed(ANGLE aWantedAngle, ANGLE aRotateSpeed, FLOAT fWaitFrequency) +{ + ANGLE aResult; + // if desired position is smaller + if ( aWantedAngle<-aRotateSpeed*fWaitFrequency) + { + // start decreasing + aResult = -aRotateSpeed; + } + // if desired position is bigger + else if (aWantedAngle>aRotateSpeed*fWaitFrequency) + { + // start increasing + aResult = +aRotateSpeed; + } + // if desired position is more-less ahead + else + { + aResult = aWantedAngle/fWaitFrequency; + } + return aResult; +} + + +/* Receive damage */ +void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) +{ + + // cannonball immediately destroys demons fireball + if (m_prtType==PRT_DEMON_FIREBALL && dmtType==DMT_CANNONBALL) + { + fDamageAmmount*=10001.0f; + } + if (m_prtType==PRT_FLAME && IsOfClass(penInflictor, "Moving Brush")) + { + Destroy(); + } + + CMovableModelEntity::ReceiveDamage(penInflictor, + dmtType, fDamageAmmount, vHitPoint, vDirection); +} + +/************************************************************ + * P R O C E D U R E S * + ************************************************************/ +procedures: + // --->>> PROJECTILE FLY IN SPACE + ProjectileFly(EVoid) { + // if already inside some entity + CEntity *penObstacle; + if (CheckForCollisionNow(0, &penObstacle)) { + // explode now + ProjectileTouch(penObstacle); + // if flame, continue existing + /*if (m_prtType==PRT_FLAME && ((CEntity &)*&penObstacle).en_RenderType==RT_MODEL) { + resume; + }*/ + return EEnd(); + } + // fly loop + wait(m_fFlyTime) { + on (EBegin) : { resume; } + on (EPass epass) : { + BOOL bHit; + // ignore launcher within 1 second + bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime; + // ignore another projectile of same type + bHit &= !((!m_bCanHitHimself && IsOfClass(epass.penOther, "Projectile") && + ((CProjectile*)&*epass.penOther)->m_prtType==m_prtType)); + // ignore twister + bHit &= !IsOfClass(epass.penOther, "Twister"); + if (bHit) { + ProjectileTouch(epass.penOther); + // player flame passes through enemies + //if (m_prtType==PRT_FLAME && IsDerivedFromClass((CEntity *)&*(epass.penOther), "Enemy Base")) { resume; } + stop; + } + resume; + } + on (ETouch etouch) : { + // clear time limit for launcher + m_fIgnoreTime = 0.0f; + // ignore another projectile of same type + BOOL bHit; + bHit = !((!m_bCanHitHimself && IsOfClass(etouch.penOther, "Projectile") && + ((CProjectile*)&*etouch.penOther)->m_prtType==m_prtType)); + + if (bHit) { + ProjectileTouch(etouch.penOther); + stop; + } + resume; + } + on (EDeath) : { + if (m_bCanBeDestroyed) { + ProjectileHit(); + stop; + } + resume; + } + on (ETimer) : { + ProjectileHit(); + stop; + } + } + return EEnd(); + }; + + // --->>> GUIDED PROJECTILE FLY IN SPACE + ProjectileGuidedFly(EVoid) { + // if already inside some entity + CEntity *penObstacle; + if (CheckForCollisionNow(0, &penObstacle)) { + // explode now + ProjectileTouch(penObstacle); + return EEnd(); + } + // fly loop + while( _pTimer->CurrentTick()<(m_fStartTime+m_fFlyTime)) + { + FLOAT fWaitFrequency = 0.1f; + // beast big projectile destroys soon after passing near the player + /*if (m_prtType==PRT_BEAST_BIG_PROJECTILE && + DistanceTo(this, m_penTarget)<20.0f && + (m_fStartTime+m_fFlyTime-_pTimer->CurrentTick())>1.5f) + { + m_fFlyTime = _pTimer->CurrentTick() - m_fStartTime + 1.5f; + }*/ + if (m_penTarget!=NULL) { + // calculate desired position and angle + EntityInfo *pei= (EntityInfo*) (m_penTarget->GetEntityInfo()); + FLOAT3D vDesiredPosition; + GetEntityInfoPosition( m_penTarget, pei->vSourceCenter, vDesiredPosition); + FLOAT3D vDesiredDirection = (vDesiredPosition-GetPlacement().pl_PositionVector).Normalize(); + // for heading + ANGLE aWantedHeading = GetRelativeHeading( vDesiredDirection); + /*if (m_prtType==PRT_BEAST_BIG_PROJECTILE && m_fStartTime+m_fFlyTime-_pTimer->CurrentTick()<1.5f) + { + m_aRotateSpeed = 10.0f; + }*/ + ANGLE aHeading = GetRotationSpeed( aWantedHeading, m_aRotateSpeed, fWaitFrequency); + + // factor used to decrease speed of projectiles oriented opposite of its target + FLOAT fSpeedDecreasingFactor = ((180-Abs(aWantedHeading))/180.0f); + // factor used to increase speed when far away from target + FLOAT fSpeedIncreasingFactor = (vDesiredPosition-GetPlacement().pl_PositionVector).Length()/100; + fSpeedIncreasingFactor = ClampDn(fSpeedIncreasingFactor, 1.0f); + // decrease speed acodring to target's direction + FLOAT fMaxSpeed = m_fGuidedMaxSpeedFactor*fSpeedIncreasingFactor; + FLOAT fMinSpeedRatio = 0.5f; + FLOAT fWantedSpeed = fMaxSpeed*( fMinSpeedRatio+(1-fMinSpeedRatio)*fSpeedDecreasingFactor); + // adjust translation velocity + SetDesiredTranslation( FLOAT3D(0, 0, -fWantedSpeed)); + + // adjust rotation speed + m_aRotateSpeed = 75.0f*(1+0.5f*fSpeedDecreasingFactor); + + // calculate distance factor + FLOAT fDistanceFactor = (vDesiredPosition-GetPlacement().pl_PositionVector).Length()/50.0; + fDistanceFactor = ClampUp(fDistanceFactor, 4.0f); + FLOAT fRNDHeading = (FRnd()-0.5f)*180*fDistanceFactor; + FLOAT fRNDPitch = (FRnd()-0.5f)*90*fDistanceFactor; + + // if we are looking near direction of target + if( Abs( aWantedHeading) < 30.0f) + { + // calculate pitch speed + ANGLE aWantedPitch = GetRelativePitch( vDesiredDirection); + ANGLE aPitch = GetRotationSpeed( aWantedPitch, m_aRotateSpeed*1.5f, fWaitFrequency); + // adjust heading and pich + SetDesiredRotation(ANGLE3D(aHeading+fRNDHeading,aPitch+fRNDPitch,0)); + } + // just adjust heading + else + { + SetDesiredRotation(ANGLE3D(aHeading,fDistanceFactor*40,0)); + } + } + + wait( fWaitFrequency) + { + on (EBegin) : { resume; } + on (EPass epass) : { + BOOL bHit; + // ignore launcher within 1 second + bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime; + // ignore another projectile of same type + bHit &= !((!m_bCanHitHimself && IsOfClass(epass.penOther, "Projectile") && + ((CProjectile*)&*epass.penOther)->m_prtType==m_prtType)); + // ignore twister + bHit &= !IsOfClass(epass.penOther, "Twister"); + if (bHit) { + ProjectileTouch(epass.penOther); + return EEnd(); + } + resume; + } + on (EDeath) : + { + if (m_bCanBeDestroyed) + { + ProjectileHit(); + return EEnd(); + } + resume; + } + on (ETimer) : + { + stop; + } + } + } + return EEnd(); + }; + + ProjectileGuidedFastFly(EVoid) { + // if already inside some entity + CEntity *penObstacle; + if (CheckForCollisionNow(0, &penObstacle)) { + // explode now + ProjectileTouch(penObstacle); + return EEnd(); + } + // fly loop + while( _pTimer->CurrentTick()<(m_fStartTime+m_fFlyTime)) + { + FLOAT fWaitFrequency = 0.1f; + // beast big projectile destroys soon after passing near the player + if (m_prtType==PRT_BEAST_BIG_PROJECTILE && + DistanceTo(this, m_penTarget)<20.0f && + (m_fStartTime+m_fFlyTime-_pTimer->CurrentTick())>1.5f) + { + m_fFlyTime = _pTimer->CurrentTick() - m_fStartTime + 1.5f; + } + if (m_penTarget!=NULL) { + // calculate desired position and angle + EntityInfo *pei= (EntityInfo*) (m_penTarget->GetEntityInfo()); + FLOAT3D vDesiredPosition; + GetEntityInfoPosition( m_penTarget, pei->vSourceCenter, vDesiredPosition); + FLOAT3D vDesiredDirection = (vDesiredPosition-GetPlacement().pl_PositionVector).Normalize(); + // for heading + ANGLE aWantedHeading = GetRelativeHeading( vDesiredDirection); + ANGLE aHeading = GetRotationSpeed( aWantedHeading, 5.0f/*m_aRotateSpeed*/, fWaitFrequency); + + // factor used to decrease speed of projectiles oriented opposite of its target + FLOAT fSpeedDecreasingFactor = ((180-Abs(aWantedHeading))/180.0f); + // factor used to increase speed when far away from target + FLOAT fSpeedIncreasingFactor = (vDesiredPosition-GetPlacement().pl_PositionVector).Length()/100; + fSpeedIncreasingFactor = ClampDn(fSpeedIncreasingFactor, 1.0f); + // decrease speed acording to target's direction + FLOAT fMaxSpeed = m_fGuidedMaxSpeedFactor*fSpeedIncreasingFactor; + FLOAT fMinSpeedRatio = 10.0f; + FLOAT fWantedSpeed = fMaxSpeed*( fMinSpeedRatio+(1-fMinSpeedRatio)*fSpeedDecreasingFactor); + // adjust translation velocity + SetDesiredTranslation( FLOAT3D(0, 0, -fWantedSpeed)); + + // adjust rotation speed + m_aRotateSpeed = 110.0f*(1+0.5f*fSpeedDecreasingFactor); + + // calculate distance factor + FLOAT fDistanceFactor = (vDesiredPosition-GetPlacement().pl_PositionVector).Length()/50.0; + fDistanceFactor = ClampUp(fDistanceFactor, 4.0f); + + // if we are looking near direction of target + if( Abs( aWantedHeading) < 30.0f) + { + bLockedOn = TRUE; + // calculate pitch speed + ANGLE aWantedPitch = GetRelativePitch( vDesiredDirection); + ANGLE aPitch = GetRotationSpeed( aWantedPitch, m_aRotateSpeed*1.5f, fWaitFrequency); + // adjust heading and pitch + SetDesiredRotation(ANGLE3D(aHeading, aPitch, 0)); + } + // just adjust heading + else + { + if (bLockedOn) // we just missed the player + { + ANGLE3D aBankingUp; + aBankingUp = GetPlacement().pl_OrientationAngle; + aBankingUp(3) = 0.0f; + SetPlacement(CPlacement3D(GetPlacement().pl_PositionVector, aBankingUp)); + } + bLockedOn = FALSE; + //SetDesiredRotation(ANGLE3D(aHeading,fDistanceFactor*40,0)); + SetDesiredRotation(ANGLE3D(aHeading,400,0)); + } + } + + wait( fWaitFrequency) + { + on (EBegin) : { resume; } + on (ETouch etouch) : { + // clear time limit for launcher + m_fIgnoreTime = 0.0f; + // ignore itself and the demon + BOOL bHit; + bHit = !((!m_bCanHitHimself && IsOfClass(etouch.penOther, "Projectile") && + ((CProjectile*)&*etouch.penOther)->m_prtType==m_prtType)); + bHit &= !IsOfClass(etouch.penOther, "Demon"); + FLOAT3D vTrans = en_vCurrentTranslationAbsolute; + bHit &= Abs(vTrans.Normalize() % FLOAT3D(etouch.plCollision)) > 0.35; + + if (bHit) { + ProjectileTouch(etouch.penOther); + return EEnd(); + } + + resume; + } + on (EPass epass) : { + BOOL bHit; + // ignore launcher within 1 second + bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime; + // ignore another projectile of same type + bHit &= !((!m_bCanHitHimself && IsOfClass(epass.penOther, "Projectile") && + ((CProjectile*)&*epass.penOther)->m_prtType==m_prtType)); + // ignore twister + bHit &= !IsOfClass(epass.penOther, "Twister"); + // if demons projectile, ignore all other projectiles + bHit &= !(m_prtType==PRT_DEMON_FIREBALL && IsOfClass(epass.penOther, "Projectile")); + bHit &= !(m_prtType==PRT_BEAST_BIG_PROJECTILE && IsOfClass(epass.penOther, "Projectile")); + + if (bHit) { + ProjectileTouch(epass.penOther); + return EEnd(); + } + resume; + } + on (EDeath) : + { + if (m_bCanBeDestroyed) + { + ProjectileHit(); + return EEnd(); + } + resume; + } + on (ETimer) : + { + stop; + } + } + } + return EEnd(); + }; + + + ProjectileGuidedSlide(EVoid) { + // if already inside some entity + CEntity *penObstacle; + if (CheckForCollisionNow(0, &penObstacle)) { + // explode now + ProjectileTouch(penObstacle); + return EEnd(); + } + // fly loop + while( _pTimer->CurrentTick()<(m_fStartTime+m_fFlyTime)) + { + FLOAT fWaitFrequency = 0.1f; + if (m_penTarget!=NULL) { + // calculate desired position and angle + EntityInfo *pei= (EntityInfo*) (m_penTarget->GetEntityInfo()); + FLOAT3D vDesiredPosition; + GetEntityInfoPosition( m_penTarget, pei->vSourceCenter, vDesiredPosition); + FLOAT3D vDesiredDirection = (vDesiredPosition-GetPlacement().pl_PositionVector).Normalize(); + // for heading + ANGLE aWantedHeading = GetRelativeHeading( vDesiredDirection); + ANGLE aHeading = GetRotationSpeed( aWantedHeading, m_aRotateSpeed, fWaitFrequency); + + // factor used to decrease speed of projectiles oriented opposite of its target + FLOAT fSpeedDecreasingFactor = ((180-Abs(aWantedHeading))/180.0f); + // factor used to increase speed when far away from target + FLOAT fSpeedIncreasingFactor = (vDesiredPosition-GetPlacement().pl_PositionVector).Length()/100; + fSpeedIncreasingFactor = ClampDn(fSpeedIncreasingFactor, 1.0f); + // decrease speed acodring to target's direction + FLOAT fMaxSpeed = 30.0f*fSpeedIncreasingFactor; + FLOAT fMinSpeedRatio = 0.5f; + FLOAT fWantedSpeed = fMaxSpeed*( fMinSpeedRatio+(1-fMinSpeedRatio)*fSpeedDecreasingFactor); + // adjust translation velocity + SetDesiredTranslation( FLOAT3D(0, 0, -fWantedSpeed)); + + // adjust rotation speed + m_aRotateSpeed = 75.0f*(1+0.5f*fSpeedDecreasingFactor); + + // calculate distance factor + FLOAT fDistanceFactor = (vDesiredPosition-GetPlacement().pl_PositionVector).Length()/50.0; + fDistanceFactor = ClampUp(fDistanceFactor, 4.0f); + FLOAT fRNDHeading = (FRnd()-0.5f)*180*fDistanceFactor; + + // if we are looking near direction of target + if( Abs( aWantedHeading) < 30.0f) + { + // adjust heading and pich + SetDesiredRotation(ANGLE3D(aHeading+fRNDHeading,0,0)); + } + // just adjust heading + else + { + SetDesiredRotation(ANGLE3D(aHeading,0,0)); + } + } + + wait( fWaitFrequency) + { + on (EBegin) : { resume; } + on (EPass epass) : { + BOOL bHit; + // ignore launcher within 1 second + bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime; + // ignore another projectile of same type + bHit &= !((!m_bCanHitHimself && IsOfClass(epass.penOther, "Projectile") && + ((CProjectile*)&*epass.penOther)->m_prtType==m_prtType)); + // ignore twister + bHit &= !IsOfClass(epass.penOther, "Twister"); + if (bHit) { + ProjectileTouch(epass.penOther); + return EEnd(); + } + resume; + } + on (EDeath) : + { + if (m_bCanBeDestroyed) + { + ProjectileHit(); + return EEnd(); + } + resume; + } + on (ETimer) : + { + stop; + } + } + } + return EEnd(); + }; + + // --->>> PROJECTILE SLIDE ON BRUSH + ProjectileSlide(EVoid) { + // if already inside some entity + CEntity *penObstacle; + if (CheckForCollisionNow(0, &penObstacle)) { + // explode now + ProjectileTouch(penObstacle); + return EEnd(); + } + // fly loop + wait(m_fFlyTime) { + on (EBegin) : { resume; } + on (EPass epass) : { + BOOL bHit; + // ignore launcher within 1 second + bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime; + // ignore another projectile of same type + bHit &= !((!m_bCanHitHimself && IsOfClass(epass.penOther, "Projectile") && + ((CProjectile*)&*epass.penOther)->m_prtType==m_prtType)); + // ignore twister + bHit &= !IsOfClass(epass.penOther, "Twister"); + if (epass.penOther!=m_penLauncher) { + bHit = bHit ; + } + if (bHit) { + ProjectileTouch(epass.penOther); + // player flame passes through enemies + if (m_prtType==PRT_FLAME && IsDerivedFromClass((CEntity *)&*(epass.penOther), "Enemy Base")) { + resume; + } + // wind blast passes through movable entities + if (m_prtType==PRT_AIRELEMENTAL_WIND && IsDerivedFromClass((CEntity *)&*(epass.penOther), "MovableEntity")) { + resume; + } + + stop; + } + resume; + } + on (ETouch etouch) : { + // clear time limit for launcher + m_fIgnoreTime = 0.0f; + // ignore brushes + BOOL bHit; + bHit = !(etouch.penOther->GetRenderType() & RT_BRUSH); + if( m_prtType==PRT_FLAME && !bHit && !m_bLeftFlame) + { + SpawnFlame(m_penLauncher, etouch.penOther, GetPlacement().pl_PositionVector); + m_bLeftFlame=TRUE; + } + if (!bHit) { BounceSound(); } + // ignore another projectile of same type + bHit &= !((!m_bCanHitHimself && IsOfClass(etouch.penOther, "Projectile") && + ((CProjectile*)&*etouch.penOther)->m_prtType==m_prtType)); + if (bHit) { + ProjectileTouch(etouch.penOther); + stop; + } + // projectile is moving to slow (stuck somewhere) -> kill it + if (en_vCurrentTranslationAbsolute.Length() < 0.25f*en_vDesiredTranslationRelative.Length()) { + ProjectileHit(); + stop; + } + resume; + } + on (EDeath) : { + if (m_bCanBeDestroyed) { + ProjectileHit(); + stop; + } + resume; + } + on (ETimer) : { + ProjectileHit(); + stop; + } + } + return EEnd(); + }; + + // --->>> PROJECTILE FLY IN SPACE WITH REBOUNDING + ProjectileFlyRebounding(EVoid) { + // if already inside some entity + CEntity *penObstacle; + if (CheckForCollisionNow(0, &penObstacle)) { + // explode now + ProjectileTouch(penObstacle); + return EEnd(); + } + // fly loop + wait(m_fFlyTime) { + on (EBegin) : { resume; } + on (EPass epass) : { + BOOL bHit; + // ignore launcher within 1 second + bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime; + // ignore another projectile of same type + bHit &= !((!m_bCanHitHimself && IsOfClass(epass.penOther, "Projectile") && + ((CProjectile*)&*epass.penOther)->m_prtType==m_prtType)); + // ignore twister + bHit &= !IsOfClass(epass.penOther, "Twister"); + if (bHit) { + ProjectileTouch(epass.penOther); + stop; + } + resume; + } + on (ETouch etouch) : { + // clear time limit for launcher + m_fIgnoreTime = 0.0f; + + BOOL bHit; + + // if brush hit + bHit = (etouch.penOther->GetRenderType() == RT_BRUSH); + + if (bHit && m_iRebounds>0) { + //reverse direction + ReflectDirectionVectorByPlane(etouch.plCollision, en_vCurrentTranslationAbsolute); + ReflectRotationMatrixByPlane_cols(etouch.plCollision, en_mRotation); + m_iRebounds--; + } else { + // ignore another projectile of same type + bHit = !((!m_bCanHitHimself && IsOfClass(etouch.penOther, "Projectile") && + ((CProjectile*)&*etouch.penOther)->m_prtType==m_prtType)); + + if (bHit) { + ProjectileTouch(etouch.penOther); + stop; + } + } + resume; + } + on (EDeath) : { + if (m_bCanBeDestroyed) { + ProjectileHit(); + stop; + } + resume; + } + on (ETimer) : { + ProjectileHit(); + stop; + } + } + return EEnd(); + }; + + // --->>> MAIN + Main(ELaunchProjectile eLaunch) { + // remember the initial parameters + ASSERT(eLaunch.penLauncher!=NULL); + m_penLauncher = eLaunch.penLauncher; + m_prtType = eLaunch.prtType; + m_fSpeed = eLaunch.fSpeed; + m_fStretch=eLaunch.fStretch; + SetPredictable(TRUE); + // remember lauching time + m_fIgnoreTime = _pTimer->CurrentTick() + 1.0f; + m_penLastDamaged = NULL; + + switch (m_prtType) { + case PRT_DEVIL_ROCKET: + case PRT_WALKER_ROCKET: + case PRT_ROCKET: + case PRT_SHOOTER_WOODEN_DART: + { + Particles_RocketTrail_Prepare(this); + break; + } + case PRT_GUFFY_PROJECTILE: break; //Particles_RocketTrail_Prepare(this); break; + case PRT_GRENADE: Particles_GrenadeTrail_Prepare(this); break; + case PRT_CATMAN_FIRE: Particles_RocketTrail_Prepare(this); break; + case PRT_HEADMAN_FIRECRACKER: Particles_FirecrackerTrail_Prepare(this); break; + case PRT_HEADMAN_ROCKETMAN: Particles_Fireball01Trail_Prepare(this); break; + case PRT_HEADMAN_BOMBERMAN: Particles_BombTrail_Prepare(this); break; + case PRT_LAVA_COMET: Particles_LavaTrail_Prepare(this); break; + case PRT_LAVAMAN_BIG_BOMB: Particles_LavaBombTrail_Prepare(this); break; + case PRT_LAVAMAN_BOMB: Particles_LavaBombTrail_Prepare(this); break; + case PRT_BEAST_PROJECTILE: Particles_Fireball01Trail_Prepare(this); break; + case PRT_BEAST_BIG_PROJECTILE: + case PRT_DEVIL_GUIDED_PROJECTILE: + case PRT_DEMON_FIREBALL: + //case PRT_METEOR: + Particles_FirecrackerTrail_Prepare(this); + break; + case PRT_SHOOTER_FIREBALL: Particles_Fireball01Trail_Prepare(this); break; + } + // projectile initialization + switch (m_prtType) + { + case PRT_WALKER_ROCKET: WalkerRocket(); break; + case PRT_ROCKET: PlayerRocket(); break; + case PRT_GRENADE: PlayerGrenade(); break; + case PRT_FLAME: PlayerFlame(); break; + case PRT_LASER_RAY: PlayerLaserRay(); break; + case PRT_CATMAN_FIRE: CatmanProjectile(); break; + case PRT_HEADMAN_FIRECRACKER: HeadmanFirecracker(); break; + case PRT_HEADMAN_ROCKETMAN: HeadmanRocketman(); break; + case PRT_HEADMAN_BOMBERMAN: HeadmanBomberman(); break; + case PRT_BONEMAN_FIRE: BonemanProjectile(); break; + case PRT_WOMAN_FIRE: WomanProjectile(); break; + case PRT_DRAGONMAN_FIRE: DragonmanProjectile(DRAGONMAN_NORMAL); break; + case PRT_DRAGONMAN_STRONG_FIRE: DragonmanProjectile(DRAGONMAN_STRONG); break; + case PRT_STONEMAN_FIRE: ElementalRock(ELEMENTAL_NORMAL, ELEMENTAL_STONEMAN); break; + case PRT_STONEMAN_BIG_FIRE: ElementalRock(ELEMENTAL_BIG, ELEMENTAL_STONEMAN); break; + case PRT_STONEMAN_LARGE_FIRE: ElementalRock(ELEMENTAL_LARGE, ELEMENTAL_STONEMAN); break; + case PRT_LAVAMAN_BIG_BOMB: LavaManBomb(); break; + case PRT_LAVAMAN_BOMB: LavaManBomb(); break; + case PRT_LAVAMAN_STONE: ElementalRock(ELEMENTAL_NORMAL, ELEMENTAL_LAVAMAN); break; + case PRT_ICEMAN_FIRE: ElementalRock(ELEMENTAL_NORMAL, ELEMENTAL_ICEMAN); break; + case PRT_ICEMAN_BIG_FIRE: ElementalRock(ELEMENTAL_BIG, ELEMENTAL_ICEMAN); break; + case PRT_ICEMAN_LARGE_FIRE: ElementalRock(ELEMENTAL_LARGE, ELEMENTAL_ICEMAN); break; + case PRT_HUANMAN_FIRE: HuanmanProjectile(); break; + case PRT_FISHMAN_FIRE: FishmanProjectile(); break; + case PRT_MANTAMAN_FIRE: MantamanProjectile(); break; + case PRT_CYBORG_LASER: CyborgLaser(); break; + case PRT_CYBORG_BOMB: CyborgBomb(); break; + case PRT_LAVA_COMET: LavaBall(); break; + case PRT_BEAST_PROJECTILE: BeastProjectile(); break; + case PRT_BEAST_BIG_PROJECTILE: BeastBigProjectile(); break; + case PRT_BEAST_DEBRIS: BeastDebris(); break; + case PRT_BEAST_BIG_DEBRIS: BeastBigDebris(); break; + case PRT_DEVIL_LASER: DevilLaser(); break; + case PRT_DEVIL_ROCKET: DevilRocket(); break; + case PRT_DEVIL_GUIDED_PROJECTILE: DevilGuidedProjectile(); break; + case PRT_GRUNT_PROJECTILE_SOL: GruntSoldierLaser(); break; + case PRT_GRUNT_PROJECTILE_COM: GruntCommanderLaser(); break; + case PRT_GUFFY_PROJECTILE: GuffyProjectile(); break; + case PRT_DEMON_FIREBALL: DemonFireball(); break; + case PRT_LARVA_PLASMA: LarvaPlasma(); break; + case PRT_LARVA_TAIL_PROJECTILE: LarvaTail(); break; + case PRT_SHOOTER_WOODEN_DART: ShooterWoodenDart(); break; + case PRT_SHOOTER_FIREBALL: ShooterFireball(); break; + case PRT_SHOOTER_FLAME: ShooterFlame(); break; + case PRT_AFTERBURNER_DEBRIS: AfterburnerDebris(); break; + case PRT_AIRELEMENTAL_WIND: WindBlast(); break; + case PRT_METEOR: Meteor(); break; + default: ASSERTALWAYS("Unknown projectile type"); + } + + // setup light source + if (m_bLightSource) { SetupLightSource(TRUE); } + + // fly + m_fStartTime = _pTimer->CurrentTick(); + // if guided projectile + if( m_pmtMove == PMT_GUIDED) { + autocall ProjectileGuidedFly() EEnd; + } else if (m_pmtMove==PMT_GUIDED_FAST) { + autocall ProjectileGuidedFastFly() EEnd; + } else if (m_pmtMove==PMT_FLYING) { + autocall ProjectileFly() EEnd; + } else if (m_pmtMove==PMT_SLIDING) { + autocall ProjectileSlide() EEnd; + } else if (m_pmtMove==PMT_FLYING_REBOUNDING) { + autocall ProjectileFlyRebounding() EEnd; + } else if (m_pmtMove==PMT_GUIDED_SLIDING) { + autocall ProjectileGuidedSlide() EEnd; + } + + // projectile explosion + switch (m_prtType) { + case PRT_WALKER_ROCKET: WalkerRocketExplosion(); break; + case PRT_ROCKET: PlayerRocketExplosion(); break; + case PRT_GRENADE: PlayerGrenadeExplosion(); break; + case PRT_LASER_RAY: PlayerLaserWave(); break; + case PRT_HEADMAN_BOMBERMAN: HeadmanBombermanExplosion(); break; + case PRT_CYBORG_BOMB: CyborgBombExplosion(); break; + case PRT_LAVA_COMET: LavamanBombDebrisExplosion(); break; + case PRT_LAVAMAN_BIG_BOMB: LavamanBombExplosion(); break; + case PRT_LAVAMAN_BOMB: LavamanBombDebrisExplosion(); break; + case PRT_BEAST_BIG_PROJECTILE: BeastBigProjectileExplosion(); break; + case PRT_BEAST_PROJECTILE: BeastProjectileExplosion(); break; + case PRT_BEAST_DEBRIS: BeastDebrisExplosion(); break; + case PRT_BEAST_BIG_DEBRIS: BeastBigDebrisExplosion(); break; + case PRT_DEVIL_ROCKET: DevilRocketExplosion(); break; + case PRT_DEVIL_GUIDED_PROJECTILE: DevilGuidedProjectileExplosion(); break; + case PRT_GUFFY_PROJECTILE: GuffyProjectileExplosion(); break; + case PRT_DEMON_FIREBALL: DemonFireballExplosion(); break; + case PRT_LARVA_PLASMA: LarvaPlasmaExplosion(); break; + case PRT_LARVA_TAIL_PROJECTILE: LarvaTailExplosion(); break; + case PRT_SHOOTER_WOODEN_DART: ShooterWoodenDartExplosion(); break; + case PRT_SHOOTER_FIREBALL: ShooterFireballExplosion(); break; + case PRT_METEOR: MeteorExplosion(); break; + } + + // wait after death + if (m_fWaitAfterDeath>0.0f) { + SwitchToEditorModel(); + ForceFullStop(); + SetCollisionFlags(ECF_IMMATERIAL); + // kill light source + if (m_bLightSource) { SetupLightSource(FALSE); } + autowait(m_fWaitAfterDeath); + } + + Destroy(); + + return; + } +}; diff --git a/Sources/EntitiesMP/Projectile.h b/Sources/EntitiesMP/Projectile.h new file mode 100644 index 0000000..14679f0 --- /dev/null +++ b/Sources/EntitiesMP/Projectile.h @@ -0,0 +1,420 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Projectile_INCLUDED +#define _EntitiesMP_Projectile_INCLUDED 1 +#include +#include +#include +extern DECL_DLL CEntityPropertyEnumType ProjectileType_enum; +enum ProjectileType { + PRT_ROCKET = 0, + PRT_GRENADE = 1, + PRT_FLAME = 2, + PRT_LASER_RAY = 3, + PRT_WALKER_ROCKET = 4, + PRT_CATMAN_FIRE = 10, + PRT_HEADMAN_FIRECRACKER = 11, + PRT_HEADMAN_ROCKETMAN = 12, + PRT_HEADMAN_BOMBERMAN = 13, + PRT_BONEMAN_FIRE = 14, + PRT_WOMAN_FIRE = 15, + PRT_DRAGONMAN_FIRE = 16, + PRT_DRAGONMAN_STRONG_FIRE = 17, + PRT_STONEMAN_FIRE = 18, + PRT_STONEMAN_BIG_FIRE = 19, + PRT_STONEMAN_LARGE_FIRE = 20, + PRT_LAVAMAN_BIG_BOMB = 21, + PRT_LAVAMAN_BOMB = 22, + PRT_LAVAMAN_STONE = 23, + PRT_ICEMAN_FIRE = 27, + PRT_ICEMAN_BIG_FIRE = 28, + PRT_ICEMAN_LARGE_FIRE = 29, + PRT_HUANMAN_FIRE = 41, + PRT_FISHMAN_FIRE = 42, + PRT_MANTAMAN_FIRE = 43, + PRT_CYBORG_LASER = 44, + PRT_CYBORG_BOMB = 45, + PRT_LAVA_COMET = 50, + PRT_BEAST_PROJECTILE = 51, + PRT_BEAST_BIG_PROJECTILE = 52, + PRT_BEAST_DEBRIS = 53, + PRT_BEAST_BIG_DEBRIS = 54, + PRT_DEVIL_LASER = 55, + PRT_DEVIL_ROCKET = 56, + PRT_DEVIL_GUIDED_PROJECTILE = 57, + PRT_GRUNT_PROJECTILE_SOL = 60, + PRT_GRUNT_PROJECTILE_COM = 64, + PRT_GUFFY_PROJECTILE = 61, + PRT_DEMON_FIREBALL = 62, + PRT_DEMON_FIREBALL_DEBRIS = 63, + PRT_SHOOTER_WOODEN_DART = 70, + PRT_SHOOTER_FIREBALL = 71, + PRT_SHOOTER_FLAME = 72, + PRT_LARVA_PLASMA = 73, + PRT_LARVA_TAIL_PROJECTILE = 74, + PRT_AIRELEMENTAL_WIND = 75, + PRT_AFTERBURNER_DEBRIS = 76, + PRT_METEOR = 77, +}; +DECL_DLL inline void ClearToDefault(ProjectileType &e) { e = (ProjectileType)0; } ; +extern DECL_DLL CEntityPropertyEnumType ProjectileMovingType_enum; +enum ProjectileMovingType { + PMT_FLYING = 0, + PMT_SLIDING = 1, + PMT_GUIDED = 2, + PMT_GUIDED_FAST = 3, + PMT_FLYING_REBOUNDING = 4, + PMT_GUIDED_SLIDING = 5, +}; +DECL_DLL inline void ClearToDefault(ProjectileMovingType &e) { e = (ProjectileMovingType)0; } ; +#define EVENTCODE_ELaunchProjectile 0x01f50000 +class DECL_DLL ELaunchProjectile : public CEntityEvent { +public: +ELaunchProjectile(); +CEntityEvent *MakeCopy(void); +CEntityPointer penLauncher; +enum ProjectileType prtType; +FLOAT fSpeed; +FLOAT fStretch; +}; +DECL_DLL inline void ClearToDefault(ELaunchProjectile &e) { e = ELaunchProjectile(); } ; +extern "C" DECL_DLL CDLLEntityClass CProjectile_DLLClass; +class DECL_DLL CProjectile : public CMovableModelEntity { +public: +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + virtual void SetDefaultProperties(void); + CEntityPointer m_penLauncher; + enum ProjectileType m_prtType; + enum ProjectileMovingType m_pmtMove; + CEntityPointer m_penParticles; + CEntityPointer m_penTarget; + CEntityPointer m_penLastDamaged; + FLOAT m_fSpeed; + FLOAT m_fIgnoreTime; + FLOAT m_fFlyTime; + FLOAT m_fStartTime; + FLOAT m_fDamageAmount; + FLOAT m_fRangeDamageAmount; + FLOAT m_fDamageHotSpotRange; + FLOAT m_fDamageFallOffRange; + FLOAT m_fSoundRange; + BOOL m_bExplode; + BOOL m_bLightSource; + BOOL m_bCanHitHimself; + BOOL m_bCanBeDestroyed; + FLOAT m_fWaitAfterDeath; + FLOAT m_aRotateSpeed; + FLOAT m_tmExpandBox; + FLOAT m_tmInvisibility; + INDEX m_iRebounds; + FLOAT m_fStretch; + CSoundObject m_soEffect; + CSoundObject m_soExplosion; + FLOAT m_fGuidedMaxSpeedFactor; + BOOL bLockedOn; + BOOL m_bLeftFlame; + CEntityPointer m_penPrediction; +CLightSource m_lsLightSource; + +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void PreMoving(void); + +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void PostMoving(void); + +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void Read_t(CTStream * istr); + void DumpSync_t(CTStream & strm,INDEX iExtensiveSyncCheck); + +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +CLightSource * GetLightSource(void); + void Copy(CEntity & enOther,ULONG ulFlags); + +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 679 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void SetupLightSource(BOOL bLive); + +#line 811 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void RenderParticles(void); + +#line 951 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void PlayerRocket(void); + +#line 989 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void WalkerRocket(void); + +#line 1024 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void WalkerRocketExplosion(void); + +#line 1028 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void PlayerRocketExplosion(void); + +#line 1072 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void PlayerGrenade(void); + +#line 1105 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void PlayerGrenadeExplosion(void); + +#line 1145 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void PlayerFlame(void); + +#line 1181 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void PlayerLaserRay(void); + +#line 1211 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void PlayerLaserWave(void); + +#line 1234 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CatmanProjectile(void); + +#line 1261 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void HeadmanFirecracker(void); + +#line 1285 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void HeadmanRocketman(void); + +#line 1315 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void HeadmanBomberman(void); + +#line 1341 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void HeadmanBombermanExplosion(void); + +#line 1366 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CyborgBombExplosion(void); + +#line 1395 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void BonemanProjectile(void); + +#line 1422 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void WomanProjectile(void); + +#line 1449 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void DragonmanProjectile(INDEX iType); + +#line 1485 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void ElementalRock(INDEX iSize,INDEX iType); + +#line 1543 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void LavaManBomb(void); + +#line 1605 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void LavamanBombExplosion(void); + +#line 1679 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void LavamanBombDebrisExplosion(void); + +#line 1721 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void HuanmanProjectile(void); + +#line 1750 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void BeastProjectile(void); + +#line 1785 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void BeastBigProjectile(void); + +#line 1820 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void BeastDebris(void); + +#line 1849 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void BeastBigDebris(void); + +#line 1878 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void BeastDebrisExplosion(void); + +#line 1901 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void BeastBigDebrisExplosion(void); + +#line 1924 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void BeastProjectileExplosion(void); + +#line 1982 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void BeastBigProjectileExplosion(void); + +#line 2041 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void FishmanProjectile(void); + +#line 2068 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void MantamanProjectile(void); + +#line 2094 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void DevilLaser(void); + +#line 2117 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void DevilRocket(void); + +#line 2149 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void DevilRocketExplosion(void); + +#line 2187 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void DevilGuidedProjectile(void); + +#line 2221 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void DevilGuidedProjectileExplosion(void); + +#line 2280 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CyborgLaser(void); + +#line 2302 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void CyborgBomb(void); + +#line 2334 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void LavaBall(void); + +#line 2360 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void LavaBallExplosion(void); + +#line 2380 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void GruntSoldierLaser(void); + +#line 2410 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void GruntCommanderLaser(void); + +#line 2445 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void GuffyProjectile(void); + +#line 2483 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void GuffyProjectileExplosion(void); + +#line 2492 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void DemonFireball(void); + +#line 2527 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void DemonFireballExplosion(void); + +#line 2554 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void LarvaPlasma(void); + +#line 2599 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void LarvaPlasmaExplosion(void); + +#line 2621 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void LarvaTail(void); + +#line 2656 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void LarvaTailExplosion(void); + +#line 2665 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void WindBlast(void); + +#line 2693 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void Meteor(); + +#line 2732 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void MeteorExplosion(); + +#line 2797 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void ShooterWoodenDart(void); + +#line 2828 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void ShooterWoodenDartExplosion(); + +#line 2843 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void ShooterFireball(void); + +#line 2876 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void ShooterFireballExplosion(); + +#line 2891 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void ShooterFlame(void); + +#line 2912 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void AfterburnerDebris(void); + +#line 2944 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void ProjectileTouch(CEntityPointer penHit); + +#line 3015 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void ProjectileHit(void); + +#line 3035 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void SpawnEffect(const CPlacement3D & plEffect,const ESpawnEffect & eSpawnEffect); + +#line 3045 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void BounceSound(void); + +#line 3059 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ANGLE GetRotationSpeed(ANGLE aWantedAngle,ANGLE aRotateSpeed,FLOAT fWaitFrequency); + +#line 3084 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 3085 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); +#define STATE_CProjectile_ProjectileFly 0x01f50001 + BOOL +#line 3107 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileFly(const CEntityEvent &__eeInput); + BOOL H0x01f50002_ProjectileFly_01(const CEntityEvent &__eeInput); + BOOL H0x01f50003_ProjectileFly_02(const CEntityEvent &__eeInput); +#define STATE_CProjectile_ProjectileGuidedFly 0x01f50004 + BOOL +#line 3169 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileGuidedFly(const CEntityEvent &__eeInput); + BOOL H0x01f50005_ProjectileGuidedFly_01(const CEntityEvent &__eeInput); + BOOL H0x01f50006_ProjectileGuidedFly_02(const CEntityEvent &__eeInput); + BOOL H0x01f50007_ProjectileGuidedFly_03(const CEntityEvent &__eeInput); + BOOL H0x01f50008_ProjectileGuidedFly_04(const CEntityEvent &__eeInput); +#define STATE_CProjectile_ProjectileGuidedFastFly 0x01f50009 + BOOL +#line 3275 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileGuidedFastFly(const CEntityEvent &__eeInput); + BOOL H0x01f5000a_ProjectileGuidedFastFly_01(const CEntityEvent &__eeInput); + BOOL H0x01f5000b_ProjectileGuidedFastFly_02(const CEntityEvent &__eeInput); + BOOL H0x01f5000c_ProjectileGuidedFastFly_03(const CEntityEvent &__eeInput); + BOOL H0x01f5000d_ProjectileGuidedFastFly_04(const CEntityEvent &__eeInput); +#define STATE_CProjectile_ProjectileGuidedSlide 0x01f5000e + BOOL +#line 3408 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileGuidedSlide(const CEntityEvent &__eeInput); + BOOL H0x01f5000f_ProjectileGuidedSlide_01(const CEntityEvent &__eeInput); + BOOL H0x01f50010_ProjectileGuidedSlide_02(const CEntityEvent &__eeInput); + BOOL H0x01f50011_ProjectileGuidedSlide_03(const CEntityEvent &__eeInput); + BOOL H0x01f50012_ProjectileGuidedSlide_04(const CEntityEvent &__eeInput); +#define STATE_CProjectile_ProjectileSlide 0x01f50013 + BOOL +#line 3500 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileSlide(const CEntityEvent &__eeInput); + BOOL H0x01f50014_ProjectileSlide_01(const CEntityEvent &__eeInput); + BOOL H0x01f50015_ProjectileSlide_02(const CEntityEvent &__eeInput); +#define STATE_CProjectile_ProjectileFlyRebounding 0x01f50016 + BOOL +#line 3580 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileFlyRebounding(const CEntityEvent &__eeInput); + BOOL H0x01f50017_ProjectileFlyRebounding_01(const CEntityEvent &__eeInput); + BOOL H0x01f50018_ProjectileFlyRebounding_02(const CEntityEvent &__eeInput); +#define STATE_CProjectile_Main 1 + BOOL +#line 3648 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01f50019_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01f5001a_Main_02(const CEntityEvent &__eeInput); + BOOL H0x01f5001b_Main_03(const CEntityEvent &__eeInput); + BOOL H0x01f5001c_Main_04(const CEntityEvent &__eeInput); + BOOL H0x01f5001d_Main_05(const CEntityEvent &__eeInput); + BOOL H0x01f5001e_Main_06(const CEntityEvent &__eeInput); + BOOL H0x01f5001f_Main_07(const CEntityEvent &__eeInput); + BOOL H0x01f50020_Main_08(const CEntityEvent &__eeInput); + BOOL H0x01f50021_Main_09(const CEntityEvent &__eeInput); + BOOL H0x01f50022_Main_10(const CEntityEvent &__eeInput); + BOOL H0x01f50023_Main_11(const CEntityEvent &__eeInput); + BOOL H0x01f50024_Main_12(const CEntityEvent &__eeInput); + BOOL H0x01f50025_Main_13(const CEntityEvent &__eeInput); + BOOL H0x01f50026_Main_14(const CEntityEvent &__eeInput); + BOOL H0x01f50027_Main_15(const CEntityEvent &__eeInput); + BOOL H0x01f50028_Main_16(const CEntityEvent &__eeInput); + BOOL H0x01f50029_Main_17(const CEntityEvent &__eeInput); + BOOL H0x01f5002a_Main_18(const CEntityEvent &__eeInput); + BOOL H0x01f5002b_Main_19(const CEntityEvent &__eeInput); + BOOL H0x01f5002c_Main_20(const CEntityEvent &__eeInput); + BOOL H0x01f5002d_Main_21(const CEntityEvent &__eeInput); + BOOL H0x01f5002e_Main_22(const CEntityEvent &__eeInput); + BOOL H0x01f5002f_Main_23(const CEntityEvent &__eeInput); + BOOL H0x01f50030_Main_24(const CEntityEvent &__eeInput); + BOOL H0x01f50031_Main_25(const CEntityEvent &__eeInput); + BOOL H0x01f50032_Main_26(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Projectile_INCLUDED diff --git a/Sources/EntitiesMP/Projectile_tables.h b/Sources/EntitiesMP/Projectile_tables.h new file mode 100644 index 0000000..95a83a9 --- /dev/null +++ b/Sources/EntitiesMP/Projectile_tables.h @@ -0,0 +1,376 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(ProjectileType) + EP_ENUMVALUE(PRT_ROCKET, "Rocket"), + EP_ENUMVALUE(PRT_GRENADE, "Grenade"), + EP_ENUMVALUE(PRT_FLAME, "Flame"), + EP_ENUMVALUE(PRT_LASER_RAY, "Laser"), + EP_ENUMVALUE(PRT_WALKER_ROCKET, "WalkerRocket"), + EP_ENUMVALUE(PRT_CATMAN_FIRE, "Catman"), + EP_ENUMVALUE(PRT_HEADMAN_FIRECRACKER, "Firecracker"), + EP_ENUMVALUE(PRT_HEADMAN_ROCKETMAN, "Rocketman"), + EP_ENUMVALUE(PRT_HEADMAN_BOMBERMAN, "Bomberman"), + EP_ENUMVALUE(PRT_BONEMAN_FIRE, "Boneman"), + EP_ENUMVALUE(PRT_WOMAN_FIRE, "Woman"), + EP_ENUMVALUE(PRT_DRAGONMAN_FIRE, "Dragonman"), + EP_ENUMVALUE(PRT_DRAGONMAN_STRONG_FIRE, "Dragonman Strong"), + EP_ENUMVALUE(PRT_STONEMAN_FIRE, "Stoneman"), + EP_ENUMVALUE(PRT_STONEMAN_BIG_FIRE, "Stoneman Big"), + EP_ENUMVALUE(PRT_STONEMAN_LARGE_FIRE, "Stoneman Large"), + EP_ENUMVALUE(PRT_LAVAMAN_BIG_BOMB, "Lavaman Big Bomb"), + EP_ENUMVALUE(PRT_LAVAMAN_BOMB, "Lavaman Bomb"), + EP_ENUMVALUE(PRT_LAVAMAN_STONE, "Lavaman Stone"), + EP_ENUMVALUE(PRT_ICEMAN_FIRE, "Iceman"), + EP_ENUMVALUE(PRT_ICEMAN_BIG_FIRE, "Iceman Big"), + EP_ENUMVALUE(PRT_ICEMAN_LARGE_FIRE, "Iceman Large"), + EP_ENUMVALUE(PRT_HUANMAN_FIRE, "Huanman"), + EP_ENUMVALUE(PRT_FISHMAN_FIRE, "Fishman"), + EP_ENUMVALUE(PRT_MANTAMAN_FIRE, "Mantaman"), + EP_ENUMVALUE(PRT_CYBORG_LASER, "Cyborg Laser"), + EP_ENUMVALUE(PRT_CYBORG_BOMB, "Cyborg Bomb"), + EP_ENUMVALUE(PRT_LAVA_COMET, "Lava Comet"), + EP_ENUMVALUE(PRT_BEAST_PROJECTILE, "Beast Projectile"), + EP_ENUMVALUE(PRT_BEAST_BIG_PROJECTILE, "Beast Big Projectile"), + EP_ENUMVALUE(PRT_BEAST_DEBRIS, "Beast Debris"), + EP_ENUMVALUE(PRT_BEAST_BIG_DEBRIS, "Beast Big Debris"), + EP_ENUMVALUE(PRT_DEVIL_LASER, "Devil Laser"), + EP_ENUMVALUE(PRT_DEVIL_ROCKET, "Devil Rocket"), + EP_ENUMVALUE(PRT_DEVIL_GUIDED_PROJECTILE, "Devil Guided Projectile"), + EP_ENUMVALUE(PRT_GRUNT_PROJECTILE_SOL, "Grunt Soldier Laser"), + EP_ENUMVALUE(PRT_GRUNT_PROJECTILE_COM, "Grunt Commander Laser"), + EP_ENUMVALUE(PRT_GUFFY_PROJECTILE, "Guffy Projectile"), + EP_ENUMVALUE(PRT_DEMON_FIREBALL, "Demon Fireball"), + EP_ENUMVALUE(PRT_DEMON_FIREBALL_DEBRIS, "Demon Fireball Debris"), + EP_ENUMVALUE(PRT_SHOOTER_WOODEN_DART, "Shooter Wooden Dart"), + EP_ENUMVALUE(PRT_SHOOTER_FIREBALL, "Shooter Fireball"), + EP_ENUMVALUE(PRT_SHOOTER_FLAME, "Shooter Flame"), + EP_ENUMVALUE(PRT_LARVA_PLASMA, "ExotechLarva Plasma"), + EP_ENUMVALUE(PRT_LARVA_TAIL_PROJECTILE, "ExotechLarva Tail Projectile"), + EP_ENUMVALUE(PRT_AIRELEMENTAL_WIND, "Air Elemental Wind Blast"), + EP_ENUMVALUE(PRT_AFTERBURNER_DEBRIS, "Afterburner debris"), + EP_ENUMVALUE(PRT_METEOR, "Meteor"), +EP_ENUMEND(ProjectileType); + +EP_ENUMBEG(ProjectileMovingType) + EP_ENUMVALUE(PMT_FLYING, ""), + EP_ENUMVALUE(PMT_SLIDING, ""), + EP_ENUMVALUE(PMT_GUIDED, ""), + EP_ENUMVALUE(PMT_GUIDED_FAST, ""), + EP_ENUMVALUE(PMT_FLYING_REBOUNDING, ""), + EP_ENUMVALUE(PMT_GUIDED_SLIDING, ""), +EP_ENUMEND(ProjectileMovingType); + +#define ENTITYCLASS CProjectile + +CEntityProperty CProjectile_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001f5<<8)+1, offsetof(CProjectile, m_penLauncher), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &ProjectileType_enum, (0x000001f5<<8)+2, offsetof(CProjectile, m_prtType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &ProjectileMovingType_enum, (0x000001f5<<8)+3, offsetof(CProjectile, m_pmtMove), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001f5<<8)+4, offsetof(CProjectile, m_penParticles), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001f5<<8)+5, offsetof(CProjectile, m_penTarget), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001f5<<8)+6, offsetof(CProjectile, m_penLastDamaged), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+10, offsetof(CProjectile, m_fSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+11, offsetof(CProjectile, m_fIgnoreTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+12, offsetof(CProjectile, m_fFlyTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+13, offsetof(CProjectile, m_fStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+14, offsetof(CProjectile, m_fDamageAmount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+15, offsetof(CProjectile, m_fRangeDamageAmount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+16, offsetof(CProjectile, m_fDamageHotSpotRange), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+17, offsetof(CProjectile, m_fDamageFallOffRange), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+18, offsetof(CProjectile, m_fSoundRange), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001f5<<8)+19, offsetof(CProjectile, m_bExplode), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001f5<<8)+20, offsetof(CProjectile, m_bLightSource), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001f5<<8)+21, offsetof(CProjectile, m_bCanHitHimself), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001f5<<8)+22, offsetof(CProjectile, m_bCanBeDestroyed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+23, offsetof(CProjectile, m_fWaitAfterDeath), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+24, offsetof(CProjectile, m_aRotateSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+25, offsetof(CProjectile, m_tmExpandBox), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+26, offsetof(CProjectile, m_tmInvisibility), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000001f5<<8)+27, offsetof(CProjectile, m_iRebounds), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+28, offsetof(CProjectile, m_fStretch), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000001f5<<8)+30, offsetof(CProjectile, m_soEffect), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000001f5<<8)+31, offsetof(CProjectile, m_soExplosion), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001f5<<8)+35, offsetof(CProjectile, m_fGuidedMaxSpeedFactor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001f5<<8)+50, offsetof(CProjectile, bLockedOn), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001f5<<8)+51, offsetof(CProjectile, m_bLeftFlame), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001f5<<8)+255, offsetof(CProjectile, m_penPrediction), "", 0, 0, 0), +}; +#define CProjectile_propertiesct ARRAYCOUNT(CProjectile_properties) + +CEntityComponent CProjectile_components[] = { +#define CLASS_BASIC_EFFECT ((0x000001f5<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_LIGHT ((0x000001f5<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_LIGHT, "EFNM" "Classes\\Light.ecl"), +#define CLASS_PROJECTILE ((0x000001f5<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_BLOOD_SPRAY ((0x000001f5<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define MODEL_ROCKET ((0x000001f5<<8)+5) + CEntityComponent(ECT_MODEL, MODEL_ROCKET, "EFNM" "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl"), +#define TEXTURE_ROCKET ((0x000001f5<<8)+6) + CEntityComponent(ECT_TEXTURE, TEXTURE_ROCKET, "EFNM" "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex"), +#define SOUND_FLYING ((0x000001f5<<8)+8) + CEntityComponent(ECT_SOUND, SOUND_FLYING, "EFNM" "Sounds\\Weapons\\RocketFly.wav"), +#define SOUND_BEAST_FLYING ((0x000001f5<<8)+9) + CEntityComponent(ECT_SOUND, SOUND_BEAST_FLYING, "EFNM" "Sounds\\Weapons\\ProjectileFly.wav"), +#define MODEL_GRENADE ((0x000001f5<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_GRENADE, "EFNM" "Models\\Weapons\\GrenadeLauncher\\Grenade\\Grenade.mdl"), +#define TEXTURE_GRENADE ((0x000001f5<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_GRENADE, "EFNM" "Models\\Weapons\\GrenadeLauncher\\Grenade\\Grenade.tex"), +#define SOUND_GRENADE_BOUNCE ((0x000001f5<<8)+12) + CEntityComponent(ECT_SOUND, SOUND_GRENADE_BOUNCE, "EFNM" "Models\\Weapons\\GrenadeLauncher\\Sounds\\Bounce.wav"), +#define MODEL_FLAME ((0x000001f5<<8)+15) + CEntityComponent(ECT_MODEL, MODEL_FLAME, "EFNM" "ModelsMP\\Weapons\\Flamer\\Projectile\\Invisible.mdl"), +#define CLASS_FLAME ((0x000001f5<<8)+16) + CEntityComponent(ECT_CLASS, CLASS_FLAME, "EFNM" "Classes\\Flame.ecl"), +#define MODEL_CATMAN_FIRE ((0x000001f5<<8)+20) + CEntityComponent(ECT_MODEL, MODEL_CATMAN_FIRE, "EFNM" "Models\\Enemies\\Catman\\Projectile\\Projectile.mdl"), +#define TEXTURE_CATMAN_FIRE ((0x000001f5<<8)+21) + CEntityComponent(ECT_TEXTURE, TEXTURE_CATMAN_FIRE, "EFNM" "Models\\Enemies\\Catman\\Projectile\\Projectile.tex"), +#define MODEL_HEADMAN_FIRECRACKER ((0x000001f5<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_HEADMAN_FIRECRACKER, "EFNM" "Models\\Enemies\\Headman\\Projectile\\FireCracker.mdl"), +#define TEXTURE_HEADMAN_FIRECRACKER ((0x000001f5<<8)+31) + CEntityComponent(ECT_TEXTURE, TEXTURE_HEADMAN_FIRECRACKER, "EFNM" "Models\\Enemies\\Headman\\Projectile\\Texture.tex"), +#define MODEL_HEADMAN_BLADE ((0x000001f5<<8)+32) + CEntityComponent(ECT_MODEL, MODEL_HEADMAN_BLADE, "EFNM" "Models\\Enemies\\Headman\\Projectile\\Blade.mdl"), +#define TEXTURE_HEADMAN_BLADE ((0x000001f5<<8)+33) + CEntityComponent(ECT_TEXTURE, TEXTURE_HEADMAN_BLADE, "EFNM" "Models\\Enemies\\Headman\\Projectile\\Blade.tex"), +#define MODEL_HEADMAN_BLADE_FLAME ((0x000001f5<<8)+34) + CEntityComponent(ECT_MODEL, MODEL_HEADMAN_BLADE_FLAME, "EFNM" "Models\\Enemies\\Headman\\Projectile\\FireTrail.mdl"), +#define TEXTURE_HEADMAN_BLADE_FLAME ((0x000001f5<<8)+35) + CEntityComponent(ECT_TEXTURE, TEXTURE_HEADMAN_BLADE_FLAME, "EFNM" "Models\\Enemies\\Headman\\Projectile\\FireTrail.tex"), +#define MODEL_HEADMAN_BOMB ((0x000001f5<<8)+36) + CEntityComponent(ECT_MODEL, MODEL_HEADMAN_BOMB, "EFNM" "Models\\Enemies\\Headman\\Projectile\\Bomb.mdl"), +#define TEXTURE_HEADMAN_BOMB ((0x000001f5<<8)+37) + CEntityComponent(ECT_TEXTURE, TEXTURE_HEADMAN_BOMB, "EFNM" "Models\\Enemies\\Headman\\Projectile\\Bomb.tex"), +#define MODEL_LAVA ((0x000001f5<<8)+40) + CEntityComponent(ECT_MODEL, MODEL_LAVA, "EFNM" "Models\\Effects\\Debris\\Lava01\\Lava.mdl"), +#define TEXTURE_LAVA ((0x000001f5<<8)+41) + CEntityComponent(ECT_TEXTURE, TEXTURE_LAVA, "EFNM" "Models\\Effects\\Debris\\Lava01\\Lava.tex"), +#define MODEL_LAVA_FLARE ((0x000001f5<<8)+42) + CEntityComponent(ECT_MODEL, MODEL_LAVA_FLARE, "EFNM" "Models\\Effects\\Debris\\Lava01\\LavaFlare.mdl"), +#define TEXTURE_LAVA_FLARE ((0x000001f5<<8)+43) + CEntityComponent(ECT_TEXTURE, TEXTURE_LAVA_FLARE, "EFNM" "Models\\Effects\\Debris\\Lava01\\Flare.tex"), +#define MODEL_LASER ((0x000001f5<<8)+50) + CEntityComponent(ECT_MODEL, MODEL_LASER, "EFNM" "Models\\Weapons\\Laser\\Projectile\\LaserProjectile.mdl"), +#define TEXTURE_GREEN_LASER ((0x000001f5<<8)+51) + CEntityComponent(ECT_TEXTURE, TEXTURE_GREEN_LASER, "EFNM" "Models\\Weapons\\Laser\\Projectile\\LaserProjectile.tex"), +#define TEXTURE_BLUE_LASER ((0x000001f5<<8)+52) + CEntityComponent(ECT_TEXTURE, TEXTURE_BLUE_LASER, "EFNM" "Models\\Weapons\\Laser\\Projectile\\LaserProjectileBlue.tex"), +#define MODEL_BONEMAN_FIRE ((0x000001f5<<8)+60) + CEntityComponent(ECT_MODEL, MODEL_BONEMAN_FIRE, "EFNM" "Models\\Enemies\\Boneman\\Projectile\\Projectile.mdl"), +#define TEXTURE_BONEMAN_FIRE ((0x000001f5<<8)+61) + CEntityComponent(ECT_TEXTURE, TEXTURE_BONEMAN_FIRE, "EFNM" "Models\\Enemies\\Boneman\\Projectile\\Projectile.tex"), +#define MODEL_WOMAN_FIRE ((0x000001f5<<8)+65) + CEntityComponent(ECT_MODEL, MODEL_WOMAN_FIRE, "EFNM" "Models\\Enemies\\Woman\\Projectile\\Projectile.mdl"), +#define TEXTURE_WOMAN_FIRE ((0x000001f5<<8)+66) + CEntityComponent(ECT_TEXTURE, TEXTURE_WOMAN_FIRE, "EFNM" "Models\\Enemies\\Woman\\Projectile\\Projectile.tex"), +#define MODEL_DRAGONMAN_FIRE ((0x000001f5<<8)+70) + CEntityComponent(ECT_MODEL, MODEL_DRAGONMAN_FIRE, "EFNM" "Models\\Enemies\\Dragonman\\Projectile\\Projectile.mdl"), +#define TEXTURE_DRAGONMAN_FIRE1 ((0x000001f5<<8)+71) + CEntityComponent(ECT_TEXTURE, TEXTURE_DRAGONMAN_FIRE1, "EFNM" "Models\\Enemies\\Dragonman\\Projectile\\Projectile1.tex"), +#define TEXTURE_DRAGONMAN_FIRE2 ((0x000001f5<<8)+72) + CEntityComponent(ECT_TEXTURE, TEXTURE_DRAGONMAN_FIRE2, "EFNM" "Models\\Enemies\\Dragonman\\Projectile\\Projectile2.tex"), +#define MODEL_ELEM_STONE ((0x000001f5<<8)+80) + CEntityComponent(ECT_MODEL, MODEL_ELEM_STONE, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\Stone.mdl"), +#define MODEL_ELEM_ICE ((0x000001f5<<8)+81) + CEntityComponent(ECT_MODEL, MODEL_ELEM_ICE, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\IcePyramid.mdl"), +#define MODEL_ELEM_ICE_FLARE ((0x000001f5<<8)+82) + CEntityComponent(ECT_MODEL, MODEL_ELEM_ICE_FLARE, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\IcePyramidFlare.mdl"), +#define MODEL_ELEM_LAVA_BOMB ((0x000001f5<<8)+83) + CEntityComponent(ECT_MODEL, MODEL_ELEM_LAVA_BOMB, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\LavaBomb.mdl"), +#define MODEL_ELEM_LAVA_BOMB_FLARE ((0x000001f5<<8)+84) + CEntityComponent(ECT_MODEL, MODEL_ELEM_LAVA_BOMB_FLARE, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\LavaBombFlare.mdl"), +#define MODEL_ELEM_LAVA_STONE ((0x000001f5<<8)+85) + CEntityComponent(ECT_MODEL, MODEL_ELEM_LAVA_STONE, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\LavaStone.mdl"), +#define MODEL_ELEM_LAVA_STONE_FLARE ((0x000001f5<<8)+86) + CEntityComponent(ECT_MODEL, MODEL_ELEM_LAVA_STONE_FLARE, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\LavaStoneFlare.mdl"), +#define TEXTURE_ELEM_STONE ((0x000001f5<<8)+90) + CEntityComponent(ECT_TEXTURE, TEXTURE_ELEM_STONE, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\Stone.tex"), +#define TEXTURE_ELEM_ICE ((0x000001f5<<8)+91) + CEntityComponent(ECT_TEXTURE, TEXTURE_ELEM_ICE, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\IcePyramid.tex"), +#define TEXTURE_ELEM_LAVA_BOMB ((0x000001f5<<8)+93) + CEntityComponent(ECT_TEXTURE, TEXTURE_ELEM_LAVA_BOMB, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\LavaBomb.tex"), +#define TEXTURE_ELEM_LAVA_BOMB_FLARE ((0x000001f5<<8)+94) + CEntityComponent(ECT_TEXTURE, TEXTURE_ELEM_LAVA_BOMB_FLARE, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\LavaBombFlare.tex"), +#define TEXTURE_ELEM_LAVA_STONE ((0x000001f5<<8)+95) + CEntityComponent(ECT_TEXTURE, TEXTURE_ELEM_LAVA_STONE, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\LavaStone.tex"), +#define TEXTURE_ELEM_LAVA_STONE_FLARE ((0x000001f5<<8)+96) + CEntityComponent(ECT_TEXTURE, TEXTURE_ELEM_LAVA_STONE_FLARE, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\LavaBombFlare.tex"), +#define MODEL_HUANMAN_FIRE ((0x000001f5<<8)+105) + CEntityComponent(ECT_MODEL, MODEL_HUANMAN_FIRE, "EFNM" "Models\\Enemies\\Huanman\\Projectile\\Projectile.mdl"), +#define TEXTURE_HUANMAN_FIRE ((0x000001f5<<8)+106) + CEntityComponent(ECT_TEXTURE, TEXTURE_HUANMAN_FIRE, "EFNM" "Models\\Enemies\\Huanman\\Projectile\\Projectile.tex"), +#define MODEL_HUANMAN_FLARE ((0x000001f5<<8)+107) + CEntityComponent(ECT_MODEL, MODEL_HUANMAN_FLARE, "EFNM" "Models\\Enemies\\Huanman\\Projectile\\Flare.mdl"), +#define TEXTURE_HUANMAN_FLARE ((0x000001f5<<8)+108) + CEntityComponent(ECT_TEXTURE, TEXTURE_HUANMAN_FLARE, "EFNM" "Textures\\Effects\\Flares\\01\\WhiteRedRing66.tex"), +#define MODEL_FISHMAN_FIRE ((0x000001f5<<8)+110) + CEntityComponent(ECT_MODEL, MODEL_FISHMAN_FIRE, "EFNM" "Models\\Enemies\\Fishman\\Projectile\\Projectile.mdl"), +#define TEXTURE_FISHMAN_FIRE ((0x000001f5<<8)+111) + CEntityComponent(ECT_TEXTURE, TEXTURE_FISHMAN_FIRE, "EFNM" "Models\\Enemies\\Fishman\\Projectile\\Water.tex"), +#define MODEL_MANTAMAN_FIRE ((0x000001f5<<8)+120) + CEntityComponent(ECT_MODEL, MODEL_MANTAMAN_FIRE, "EFNM" "Models\\Enemies\\Mantaman\\Projectile\\Projectile.mdl"), +#define TEXTURE_MANTAMAN_FIRE ((0x000001f5<<8)+121) + CEntityComponent(ECT_TEXTURE, TEXTURE_MANTAMAN_FIRE, "EFNM" "Models\\Enemies\\Mantaman\\Projectile\\Water.tex"), +#define MODEL_CYBORG_LASER ((0x000001f5<<8)+130) + CEntityComponent(ECT_MODEL, MODEL_CYBORG_LASER, "EFNM" "Models\\Weapons\\Laser\\Projectile\\LaserProjectile.mdl"), +#define TEXTURE_CYBORG_LASER ((0x000001f5<<8)+132) + CEntityComponent(ECT_TEXTURE, TEXTURE_CYBORG_LASER, "EFNM" "Models\\Weapons\\Laser\\Projectile\\LaserProjectileBlue.tex"), +#define MODEL_CYBORG_BOMB ((0x000001f5<<8)+133) + CEntityComponent(ECT_MODEL, MODEL_CYBORG_BOMB, "EFNM" "Models\\Enemies\\Cyborg\\Projectile\\Projectile.mdl"), +#define TEXTURE_CYBORG_BOMB ((0x000001f5<<8)+134) + CEntityComponent(ECT_TEXTURE, TEXTURE_CYBORG_BOMB, "EFNM" "Models\\Enemies\\Cyborg\\Projectile\\Projectile.tex"), +#define MODEL_GRUNT_PROJECTILE ((0x000001f5<<8)+135) + CEntityComponent(ECT_MODEL, MODEL_GRUNT_PROJECTILE, "EFNM" "ModelsMP\\Enemies\\Grunt\\Projectile\\GruntProjectile.mdl"), +#define TEXTURE_GRUNT_PROJECTILE_01 ((0x000001f5<<8)+136) + CEntityComponent(ECT_TEXTURE, TEXTURE_GRUNT_PROJECTILE_01, "EFNM" "ModelsMP\\Enemies\\Grunt\\Projectile\\GruntProjectileSoldier.tex"), +#define TEXTURE_GRUNT_PROJECTILE_02 ((0x000001f5<<8)+137) + CEntityComponent(ECT_TEXTURE, TEXTURE_GRUNT_PROJECTILE_02, "EFNM" "ModelsMP\\Enemies\\Grunt\\Projectile\\GruntProjectileCommander.tex"), +#define MODEL_BEAST_FIRE ((0x000001f5<<8)+140) + CEntityComponent(ECT_MODEL, MODEL_BEAST_FIRE, "EFNM" "Models\\Enemies\\Beast\\Projectile\\Projectile.mdl"), +#define TEXTURE_BEAST_FIRE ((0x000001f5<<8)+141) + CEntityComponent(ECT_TEXTURE, TEXTURE_BEAST_FIRE, "EFNM" "Models\\Enemies\\Beast\\Projectile\\Projectile.tex"), +#define TEXTURE_BEAST_BIG_FIRE ((0x000001f5<<8)+142) + CEntityComponent(ECT_TEXTURE, TEXTURE_BEAST_BIG_FIRE, "EFNM" "Models\\Enemies\\Beast\\Projectile\\ProjectileBig.tex"), +#define MODEL_DEMON_FIREBALL ((0x000001f5<<8)+150) + CEntityComponent(ECT_MODEL, MODEL_DEMON_FIREBALL, "EFNM" "ModelsMP\\Enemies\\Demon\\Projectile\\Projectile.mdl"), +#define TEXTURE_DEMON_FIREBALL ((0x000001f5<<8)+151) + CEntityComponent(ECT_TEXTURE, TEXTURE_DEMON_FIREBALL, "EFNM" "ModelsMP\\Enemies\\Demon\\Projectile\\Projectile.tex"), +#define SOUND_DEMON_FLYING ((0x000001f5<<8)+152) + CEntityComponent(ECT_SOUND, SOUND_DEMON_FLYING, "EFNM" "SoundsMP\\Weapons\\ProjectileFly.wav"), +#define MODEL_SHTR_WOODEN_DART ((0x000001f5<<8)+160) + CEntityComponent(ECT_MODEL, MODEL_SHTR_WOODEN_DART, "EFNM" "ModelsMP\\Enemies\\Shooters\\Arrow01.mdl"), +#define TEX_SHTR_WOODEN_DART ((0x000001f5<<8)+161) + CEntityComponent(ECT_TEXTURE, TEX_SHTR_WOODEN_DART, "EFNM" "ModelsMP\\Enemies\\Shooters\\Arrow01.tex"), +#define MODEL_GUFFY_PROJECTILE ((0x000001f5<<8)+170) + CEntityComponent(ECT_MODEL, MODEL_GUFFY_PROJECTILE, "EFNM" "ModelsMP\\Enemies\\Guffy\\Projectile\\GuffyProjectile.mdl"), +#define TEXTURE_GUFFY_PROJECTILE ((0x000001f5<<8)+171) + CEntityComponent(ECT_TEXTURE, TEXTURE_GUFFY_PROJECTILE, "EFNM" "ModelsMP\\Enemies\\Guffy\\Projectile\\GuffyProjectile.tex"), +#define MODEL_LARVA_PLASMA ((0x000001f5<<8)+172) + CEntityComponent(ECT_MODEL, MODEL_LARVA_PLASMA, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\Projectile.mdl"), +#define TEXTURE_LARVA_PLASMA ((0x000001f5<<8)+173) + CEntityComponent(ECT_TEXTURE, TEXTURE_LARVA_PLASMA, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\Projectile.tex"), +#define MODEL_LARVA_PLASMA_BALL ((0x000001f5<<8)+174) + CEntityComponent(ECT_MODEL, MODEL_LARVA_PLASMA_BALL, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.mdl"), +#define TEXTURE_LARVA_PLASMA_BALL ((0x000001f5<<8)+175) + CEntityComponent(ECT_TEXTURE, TEXTURE_LARVA_PLASMA_BALL, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.tex"), +#define MODEL_LARVA_TAIL ((0x000001f5<<8)+176) + CEntityComponent(ECT_MODEL, MODEL_LARVA_TAIL, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\TailProjectile.mdl"), +#define TEXTURE_LARVA_TAIL ((0x000001f5<<8)+177) + CEntityComponent(ECT_TEXTURE, TEXTURE_LARVA_TAIL, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Projectile\\TailProjectile.tex"), +#define SOUND_LARVETTE ((0x000001f5<<8)+178) + CEntityComponent(ECT_SOUND, SOUND_LARVETTE, "EFNM" "ModelsMP\\Enemies\\ExotechLarva\\Sounds\\Squeak.wav"), +#define MODEL_WINDBLAST ((0x000001f5<<8)+180) + CEntityComponent(ECT_MODEL, MODEL_WINDBLAST, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Projectile\\WindBlast.mdl"), +#define TEXTURE_WINDBLAST ((0x000001f5<<8)+181) + CEntityComponent(ECT_TEXTURE, TEXTURE_WINDBLAST, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Projectile\\WindBlast.tex"), +#define SOUND_METEOR_BLAST ((0x000001f5<<8)+185) + CEntityComponent(ECT_SOUND, SOUND_METEOR_BLAST, "EFNM" "SoundsMP\\Weapons\\MeteorBlast.wav"), +#define TEX_REFL_BWRIPLES01 ((0x000001f5<<8)+200) + CEntityComponent(ECT_TEXTURE, TEX_REFL_BWRIPLES01, "EFNM" "Models\\ReflectionTextures\\BWRiples01.tex"), +#define TEX_REFL_BWRIPLES02 ((0x000001f5<<8)+201) + CEntityComponent(ECT_TEXTURE, TEX_REFL_BWRIPLES02, "EFNM" "Models\\ReflectionTextures\\BWRiples02.tex"), +#define TEX_REFL_LIGHTMETAL01 ((0x000001f5<<8)+202) + CEntityComponent(ECT_TEXTURE, TEX_REFL_LIGHTMETAL01, "EFNM" "Models\\ReflectionTextures\\LightMetal01.tex"), +#define TEX_REFL_LIGHTBLUEMETAL01 ((0x000001f5<<8)+203) + CEntityComponent(ECT_TEXTURE, TEX_REFL_LIGHTBLUEMETAL01, "EFNM" "Models\\ReflectionTextures\\LightBlueMetal01.tex"), +#define TEX_REFL_DARKMETAL ((0x000001f5<<8)+204) + CEntityComponent(ECT_TEXTURE, TEX_REFL_DARKMETAL, "EFNM" "Models\\ReflectionTextures\\DarkMetal.tex"), +#define TEX_REFL_PURPLE01 ((0x000001f5<<8)+205) + CEntityComponent(ECT_TEXTURE, TEX_REFL_PURPLE01, "EFNM" "Models\\ReflectionTextures\\Purple01.tex"), +#define TEX_SPEC_WEAK ((0x000001f5<<8)+210) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_WEAK, "EFNM" "Models\\SpecularTextures\\Weak.tex"), +#define TEX_SPEC_MEDIUM ((0x000001f5<<8)+211) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_MEDIUM, "EFNM" "Models\\SpecularTextures\\Medium.tex"), +#define TEX_SPEC_STRONG ((0x000001f5<<8)+212) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_STRONG, "EFNM" "Models\\SpecularTextures\\Strong.tex"), +#define MODEL_MARKER ((0x000001f5<<8)+220) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_MARKER ((0x000001f5<<8)+221) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Vector.tex"), +}; +#define CProjectile_componentsct ARRAYCOUNT(CProjectile_components) + +CEventHandlerEntry CProjectile_handlers[] = { + {0x01f50001, -1, CEntity::pEventHandler(&CProjectile:: +#line 3107 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileFly),DEBUGSTRING("CProjectile::ProjectileFly")}, + {0x01f50002, -1, CEntity::pEventHandler(&CProjectile::H0x01f50002_ProjectileFly_01), DEBUGSTRING("CProjectile::H0x01f50002_ProjectileFly_01")}, + {0x01f50003, -1, CEntity::pEventHandler(&CProjectile::H0x01f50003_ProjectileFly_02), DEBUGSTRING("CProjectile::H0x01f50003_ProjectileFly_02")}, + {0x01f50004, -1, CEntity::pEventHandler(&CProjectile:: +#line 3169 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileGuidedFly),DEBUGSTRING("CProjectile::ProjectileGuidedFly")}, + {0x01f50005, -1, CEntity::pEventHandler(&CProjectile::H0x01f50005_ProjectileGuidedFly_01), DEBUGSTRING("CProjectile::H0x01f50005_ProjectileGuidedFly_01")}, + {0x01f50006, -1, CEntity::pEventHandler(&CProjectile::H0x01f50006_ProjectileGuidedFly_02), DEBUGSTRING("CProjectile::H0x01f50006_ProjectileGuidedFly_02")}, + {0x01f50007, -1, CEntity::pEventHandler(&CProjectile::H0x01f50007_ProjectileGuidedFly_03), DEBUGSTRING("CProjectile::H0x01f50007_ProjectileGuidedFly_03")}, + {0x01f50008, -1, CEntity::pEventHandler(&CProjectile::H0x01f50008_ProjectileGuidedFly_04), DEBUGSTRING("CProjectile::H0x01f50008_ProjectileGuidedFly_04")}, + {0x01f50009, -1, CEntity::pEventHandler(&CProjectile:: +#line 3275 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileGuidedFastFly),DEBUGSTRING("CProjectile::ProjectileGuidedFastFly")}, + {0x01f5000a, -1, CEntity::pEventHandler(&CProjectile::H0x01f5000a_ProjectileGuidedFastFly_01), DEBUGSTRING("CProjectile::H0x01f5000a_ProjectileGuidedFastFly_01")}, + {0x01f5000b, -1, CEntity::pEventHandler(&CProjectile::H0x01f5000b_ProjectileGuidedFastFly_02), DEBUGSTRING("CProjectile::H0x01f5000b_ProjectileGuidedFastFly_02")}, + {0x01f5000c, -1, CEntity::pEventHandler(&CProjectile::H0x01f5000c_ProjectileGuidedFastFly_03), DEBUGSTRING("CProjectile::H0x01f5000c_ProjectileGuidedFastFly_03")}, + {0x01f5000d, -1, CEntity::pEventHandler(&CProjectile::H0x01f5000d_ProjectileGuidedFastFly_04), DEBUGSTRING("CProjectile::H0x01f5000d_ProjectileGuidedFastFly_04")}, + {0x01f5000e, -1, CEntity::pEventHandler(&CProjectile:: +#line 3408 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileGuidedSlide),DEBUGSTRING("CProjectile::ProjectileGuidedSlide")}, + {0x01f5000f, -1, CEntity::pEventHandler(&CProjectile::H0x01f5000f_ProjectileGuidedSlide_01), DEBUGSTRING("CProjectile::H0x01f5000f_ProjectileGuidedSlide_01")}, + {0x01f50010, -1, CEntity::pEventHandler(&CProjectile::H0x01f50010_ProjectileGuidedSlide_02), DEBUGSTRING("CProjectile::H0x01f50010_ProjectileGuidedSlide_02")}, + {0x01f50011, -1, CEntity::pEventHandler(&CProjectile::H0x01f50011_ProjectileGuidedSlide_03), DEBUGSTRING("CProjectile::H0x01f50011_ProjectileGuidedSlide_03")}, + {0x01f50012, -1, CEntity::pEventHandler(&CProjectile::H0x01f50012_ProjectileGuidedSlide_04), DEBUGSTRING("CProjectile::H0x01f50012_ProjectileGuidedSlide_04")}, + {0x01f50013, -1, CEntity::pEventHandler(&CProjectile:: +#line 3500 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileSlide),DEBUGSTRING("CProjectile::ProjectileSlide")}, + {0x01f50014, -1, CEntity::pEventHandler(&CProjectile::H0x01f50014_ProjectileSlide_01), DEBUGSTRING("CProjectile::H0x01f50014_ProjectileSlide_01")}, + {0x01f50015, -1, CEntity::pEventHandler(&CProjectile::H0x01f50015_ProjectileSlide_02), DEBUGSTRING("CProjectile::H0x01f50015_ProjectileSlide_02")}, + {0x01f50016, -1, CEntity::pEventHandler(&CProjectile:: +#line 3580 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +ProjectileFlyRebounding),DEBUGSTRING("CProjectile::ProjectileFlyRebounding")}, + {0x01f50017, -1, CEntity::pEventHandler(&CProjectile::H0x01f50017_ProjectileFlyRebounding_01), DEBUGSTRING("CProjectile::H0x01f50017_ProjectileFlyRebounding_01")}, + {0x01f50018, -1, CEntity::pEventHandler(&CProjectile::H0x01f50018_ProjectileFlyRebounding_02), DEBUGSTRING("CProjectile::H0x01f50018_ProjectileFlyRebounding_02")}, + {1, -1, CEntity::pEventHandler(&CProjectile:: +#line 3648 "D:/SE1_GPL/Sources/EntitiesMP/Projectile.es" +Main),DEBUGSTRING("CProjectile::Main")}, + {0x01f50019, -1, CEntity::pEventHandler(&CProjectile::H0x01f50019_Main_01), DEBUGSTRING("CProjectile::H0x01f50019_Main_01")}, + {0x01f5001a, -1, CEntity::pEventHandler(&CProjectile::H0x01f5001a_Main_02), DEBUGSTRING("CProjectile::H0x01f5001a_Main_02")}, + {0x01f5001b, -1, CEntity::pEventHandler(&CProjectile::H0x01f5001b_Main_03), DEBUGSTRING("CProjectile::H0x01f5001b_Main_03")}, + {0x01f5001c, -1, CEntity::pEventHandler(&CProjectile::H0x01f5001c_Main_04), DEBUGSTRING("CProjectile::H0x01f5001c_Main_04")}, + {0x01f5001d, -1, CEntity::pEventHandler(&CProjectile::H0x01f5001d_Main_05), DEBUGSTRING("CProjectile::H0x01f5001d_Main_05")}, + {0x01f5001e, -1, CEntity::pEventHandler(&CProjectile::H0x01f5001e_Main_06), DEBUGSTRING("CProjectile::H0x01f5001e_Main_06")}, + {0x01f5001f, -1, CEntity::pEventHandler(&CProjectile::H0x01f5001f_Main_07), DEBUGSTRING("CProjectile::H0x01f5001f_Main_07")}, + {0x01f50020, -1, CEntity::pEventHandler(&CProjectile::H0x01f50020_Main_08), DEBUGSTRING("CProjectile::H0x01f50020_Main_08")}, + {0x01f50021, -1, CEntity::pEventHandler(&CProjectile::H0x01f50021_Main_09), DEBUGSTRING("CProjectile::H0x01f50021_Main_09")}, + {0x01f50022, -1, CEntity::pEventHandler(&CProjectile::H0x01f50022_Main_10), DEBUGSTRING("CProjectile::H0x01f50022_Main_10")}, + {0x01f50023, -1, CEntity::pEventHandler(&CProjectile::H0x01f50023_Main_11), DEBUGSTRING("CProjectile::H0x01f50023_Main_11")}, + {0x01f50024, -1, CEntity::pEventHandler(&CProjectile::H0x01f50024_Main_12), DEBUGSTRING("CProjectile::H0x01f50024_Main_12")}, + {0x01f50025, -1, CEntity::pEventHandler(&CProjectile::H0x01f50025_Main_13), DEBUGSTRING("CProjectile::H0x01f50025_Main_13")}, + {0x01f50026, -1, CEntity::pEventHandler(&CProjectile::H0x01f50026_Main_14), DEBUGSTRING("CProjectile::H0x01f50026_Main_14")}, + {0x01f50027, -1, CEntity::pEventHandler(&CProjectile::H0x01f50027_Main_15), DEBUGSTRING("CProjectile::H0x01f50027_Main_15")}, + {0x01f50028, -1, CEntity::pEventHandler(&CProjectile::H0x01f50028_Main_16), DEBUGSTRING("CProjectile::H0x01f50028_Main_16")}, + {0x01f50029, -1, CEntity::pEventHandler(&CProjectile::H0x01f50029_Main_17), DEBUGSTRING("CProjectile::H0x01f50029_Main_17")}, + {0x01f5002a, -1, CEntity::pEventHandler(&CProjectile::H0x01f5002a_Main_18), DEBUGSTRING("CProjectile::H0x01f5002a_Main_18")}, + {0x01f5002b, -1, CEntity::pEventHandler(&CProjectile::H0x01f5002b_Main_19), DEBUGSTRING("CProjectile::H0x01f5002b_Main_19")}, + {0x01f5002c, -1, CEntity::pEventHandler(&CProjectile::H0x01f5002c_Main_20), DEBUGSTRING("CProjectile::H0x01f5002c_Main_20")}, + {0x01f5002d, -1, CEntity::pEventHandler(&CProjectile::H0x01f5002d_Main_21), DEBUGSTRING("CProjectile::H0x01f5002d_Main_21")}, + {0x01f5002e, -1, CEntity::pEventHandler(&CProjectile::H0x01f5002e_Main_22), DEBUGSTRING("CProjectile::H0x01f5002e_Main_22")}, + {0x01f5002f, -1, CEntity::pEventHandler(&CProjectile::H0x01f5002f_Main_23), DEBUGSTRING("CProjectile::H0x01f5002f_Main_23")}, + {0x01f50030, -1, CEntity::pEventHandler(&CProjectile::H0x01f50030_Main_24), DEBUGSTRING("CProjectile::H0x01f50030_Main_24")}, + {0x01f50031, -1, CEntity::pEventHandler(&CProjectile::H0x01f50031_Main_25), DEBUGSTRING("CProjectile::H0x01f50031_Main_25")}, + {0x01f50032, -1, CEntity::pEventHandler(&CProjectile::H0x01f50032_Main_26), DEBUGSTRING("CProjectile::H0x01f50032_Main_26")}, +}; +#define CProjectile_handlersct ARRAYCOUNT(CProjectile_handlers) + +CEntity *CProjectile_New(void) { return new CProjectile; }; +void CProjectile_OnInitClass(void); +void CProjectile_OnEndClass(void) {}; +void CProjectile_OnPrecache(CDLLEntityClass *pdec, INDEX iUser); +void CProjectile_OnWorldEnd(CWorld *pwo) {}; +void CProjectile_OnWorldInit(CWorld *pwo) {}; +void CProjectile_OnWorldTick(CWorld *pwo) {}; +void CProjectile_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CProjectile, CMovableModelEntity, "Projectile", "", 0x000001f5); +DECLARE_CTFILENAME(_fnmCProjectile_tbn, ""); diff --git a/Sources/EntitiesMP/PyramidSpaceShip.cpp b/Sources/EntitiesMP/PyramidSpaceShip.cpp new file mode 100644 index 0000000..6827fc4 --- /dev/null +++ b/Sources/EntitiesMP/PyramidSpaceShip.cpp @@ -0,0 +1,1680 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" + +#include "StdH.h" +#include "Models/CutSequences/SpaceShip/SpaceShip.h" +#include "Models/CutSequences/SpaceShip/Door.h" +#include "Models/CutSequences/SpaceShip/LightBeam.h" +#include "EntitiesMP/Effector.h" +#include "EntitiesMP/Light.h" + +#include +#include +CEntityEvent *EForcePathMarker::MakeCopy(void) { CEntityEvent *peeCopy = new EForcePathMarker(*this); return peeCopy;} +EForcePathMarker::EForcePathMarker() : CEntityEvent(EVENTCODE_EForcePathMarker) {; + ClearToDefault(penForcedPathMarker); +}; +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" + +#define STRETCH_X (200.0f*m_fStretch) +#define STRETCH_Y (100.0f*m_fStretch) +#define STRETCH_Z (200.0f*m_fStretch) +#define PSS_STRETCH (FLOAT3D(STRETCH_X, STRETCH_Y, STRETCH_Z)*m_fStretch) +#define SND_FALLOFF 1000.0f +#define SND_HOTSPOT 250.0f +#define SND_VOLUME 2.0f + +#define BIG_LIGHT_BEAM_LIFE_TIME (8.0f) +#define SMALL_FLARE_WAIT 2.0f +#define SMALL_FLARES_LIFE_TIME (BIG_LIGHT_BEAM_LIFE_TIME+SMALL_FLARE_WAIT) +#define SMALL_LIGHTNING_WAIT 1.5f +#define SMALL_LIGHTININGS_LIFE_TIME (SMALL_FLARES_LIFE_TIME+SMALL_LIGHTNING_WAIT) +#define BIG_FLARE_WAIT 1.0f +#define BIG_FLARE_LIFE_TIME (SMALL_LIGHTININGS_LIFE_TIME+BIG_FLARE_WAIT) + +#define BM_DX (0.414657f*STRETCH_X) +#define BM_DY (-1.72731f*STRETCH_Y) +#define BM_DZ (0.414657f*STRETCH_Z) +#define BM_FLARE_DY (-0.25f*STRETCH_Y) + +#define BM_MASTER_Y (-1.76648f*STRETCH_Y) + +void CPyramidSpaceShip::SetDefaultProperties(void) { + m_strName = "Pyramid Space Ship"; + m_fMovingSpeed = 0.0f; + m_penBeamHit = NULL; + m_penLightBeam = NULL; + m_tmBeamTime = -1.0f; + m_penHitPlaceFlare = NULL; + m_tmHitFlareTime = -1.0f; + m_iRingCounter = 0; + m_fRatio = 0.0f; + m_strDescription = ""; + m_epssState = PSSS_IDLE ; + m_fStretch = 1.0f; + m_bStopMoving = FALSE ; + m_penTarget = NULL; + m_penFlyAwayTarget = NULL; + m_penLast = NULL; + m_bMoving = FALSE ; + m_fRot = 0.0f; + m_fLastRotSpeed = 0.0f; + m_fRotSpeed = 0.0f; + m_bApplyDamageToHitted = TRUE ; + m_tmTemp = 0.0f; + m_tmAtMarker = 0.0f; + m_tmDelta = 0.0f; + m_vPNp0 = FLOAT3D(0 , 0 , 0); + m_vPNp1 = FLOAT3D(0 , 0 , 0); + m_vTNp0 = FLOAT3D(0 , 0 , 0); + m_vTNp1 = FLOAT3D(0 , 0 , 0); + m_qPNp0 = FLOATquat3D(0 , 0 , 0 , 0); + m_qPNp1 = FLOATquat3D(0 , 0 , 0 , 0); + m_qANp0 = FLOATquat3D(0 , 0 , 0 , 0); + m_qANp1 = FLOATquat3D(0 , 0 , 0 , 0); + m_fRotSpeedp0 = 0.0f; + m_fRotSpeedp1 = 0.0f; + m_fTRotSpeedp0 = 0.0f; + m_fTRotSpeedp1 = 0.0f; + m_soPlates.SetOwner(this); +m_soPlates.Stop_internal(); + m_soBeamMachine.SetOwner(this); +m_soBeamMachine.Stop_internal(); + m_soBeam.SetOwner(this); +m_soBeam.Stop_internal(); + m_soFlaresFX.SetOwner(this); +m_soFlaresFX.Stop_internal(); + m_bFireingDeactivatedBeam = FALSE ; + m_bImmediateAnimations = FALSE ; + m_fWaitAfterKillingBeam = 1.0f; + m_bInvisible = FALSE ; + CMovableModelEntity::SetDefaultProperties(); +} + +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::Precache(void) { +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheModel (MODEL_SPACESHIP ); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheModel (MODEL_BODY ); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheTexture (TEXTURE_BODY ); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheModel (MODEL_DOOR ); +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheTexture (TEXTURE_DOOR ); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheModel (MODEL_BEAMMACHINE ); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheTexture (TEXTURE_BEAMMACHINE ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheModel (MODEL_BEAMRIM ); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheModel (MODEL_SHIP_INSIDE ); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheTexture (TEXTURE_BEAMRIM ); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheClass (CLASS_EFFECTOR , ET_SIZING_RING_FLARE ); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheClass (CLASS_EFFECTOR , ET_SIZING_BIG_BLUE_FLARE ); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheClass (CLASS_EFFECTOR , ET_LIGHTNING ); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheClass (CLASS_EFFECTOR , ET_MOVING_RING ); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheSound (SOUND_PLATES ); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheSound (SOUND_BEAMMACHINE ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheSound (SOUND_BEAM ); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PrecacheSound (SOUND_WARMUP ); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +BOOL CPyramidSpaceShip::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(penTarget == NULL ) +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return FALSE ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(slPropertyOffset == offsetof (CPyramidSpaceShip , m_penTarget ) || +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +slPropertyOffset == offsetof (CPyramidSpaceShip , m_penFlyAwayTarget )) +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return (IsDerivedFromClass (penTarget , "Pyramid Space Ship Marker")); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE ; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +BOOL CPyramidSpaceShip::MovesByTargetedRoute(CTString & strTargetProperty)const +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +strTargetProperty = "Target"; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +BOOL CPyramidSpaceShip::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +fnmMarkerClass = CTFILENAME ("Classes\\PyramidSpaceShipMarker.ecl"); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +strTargetProperty = "Target"; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE ; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +const CTString & CPyramidSpaceShip::GetDescription(void)const +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_penTarget != NULL ){ +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , m_penTarget -> GetName ()); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}else { +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return m_strDescription ; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D CPyramidSpaceShip::GetLerpedPlacement(void)const +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return CMovableEntity :: GetLerpedPlacement (); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::PreMoving() +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +en_plLastPlacement = en_plPlacement ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::HideBeamMachine(void) +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_BEAM_RIM ) != NULL ) +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +RemoveAttachment (SPACESHIP_ATTACHMENT_BEAM_RIM ); +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_BEAM ) != NULL ) +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +RemoveAttachment (SPACESHIP_ATTACHMENT_BEAM ); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::ShowBeamMachine(void) +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_BEAM_RIM , MODEL_BEAMRIM , TEXTURE_BEAMRIM ); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_BEAM , MODEL_BEAMMACHINE , TEXTURE_BEAMMACHINE ); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_BEAM_RIM ) -> amo_moModelObject . StretchModel (PSS_STRETCH ); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_BEAM ) -> amo_moModelObject . StretchModel (PSS_STRETCH ); +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::InitializePathMoving(CPyramidSpaceShipMarker * penStartMarker) +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_penTarget = penStartMarker ; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_epssState = PSSS_MOVING ; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +INDEX ctMarkers = 1; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPyramidSpaceShipMarker * pcm0 = (CPyramidSpaceShipMarker *) & * m_penTarget ; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(pcm0 == NULL ) +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return ; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPyramidSpaceShipMarker * pcm = (CPyramidSpaceShipMarker *) & * pcm0 -> m_penTarget ; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +while(pcm != NULL && pcm -> m_penTarget != pcm0 ) +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +pcm = (CPyramidSpaceShipMarker *) & * pcm -> m_penTarget ; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(pcm == NULL ){ +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +WarningMessage ("Space ship path - broken link!"); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ctMarkers ++; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(ctMarkers > 500){ +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +WarningMessage ("Space ship path - invalid marker loop!"); +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return ; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(ctMarkers < 2){ +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +WarningMessage ("Space ship path requires at least 2 markers in order to work!"); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return ; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT tmCurrent = _pTimer -> CurrentTick (); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_tmAtMarker = tmCurrent ; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_tmDelta = 0.0f; +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_bStopMoving = FALSE ; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_penLast = pcm ; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ASSERT (pcm -> m_penTarget == m_penTarget ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_bMoving = TRUE ; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddToMovers (); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::DoMoving() +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(! m_bMoving ){ +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return ; +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT tmCurrent = _pTimer -> CurrentTick (); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +BOOL bLerping = TRUE ; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(tmCurrent > (m_tmAtMarker + m_tmDelta - _pTimer -> TickQuantum * 3 / 2)) +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPyramidSpaceShipMarker * pcmNm1 = & (CPyramidSpaceShipMarker &) * m_penLast ; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPyramidSpaceShipMarker * pcmNp0 = & (CPyramidSpaceShipMarker &) * m_penTarget ; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPyramidSpaceShipMarker * pcmNp1 = & (CPyramidSpaceShipMarker &) * pcmNp0 -> m_penTarget ; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPyramidSpaceShipMarker * pcmNp2 = & (CPyramidSpaceShipMarker &) * pcmNp1 -> m_penTarget ; +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(pcmNp0 -> m_penTrigger != NULL ){ +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SendToTarget (pcmNp0 -> m_penTrigger , EET_TRIGGER , NULL ); +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_penTarget = pcmNp1 ; +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_penLast = pcmNp0 ; +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPyramidSpaceShipMarker & cmNm1 = * pcmNm1 ; +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPyramidSpaceShipMarker & cmNp0 = * pcmNp0 ; +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPyramidSpaceShipMarker & cmNp1 = * pcmNp1 ; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPyramidSpaceShipMarker & cmNp2 = * pcmNp2 ; +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +const FLOAT3D & vPNm1 = cmNm1 . GetPlacement () . pl_PositionVector ; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +const FLOAT3D & vPNp0 = cmNp0 . GetPlacement () . pl_PositionVector ; +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +const FLOAT3D & vPNp1 = cmNp1 . GetPlacement () . pl_PositionVector ; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +const FLOAT3D & vPNp2 = cmNp2 . GetPlacement () . pl_PositionVector ; +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ANGLE3D aPNm1 = cmNm1 . GetPlacement () . pl_OrientationAngle ; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ANGLE3D aPNp0 = cmNp0 . GetPlacement () . pl_OrientationAngle ; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ANGLE3D aPNp1 = cmNp1 . GetPlacement () . pl_OrientationAngle ; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ANGLE3D aPNp2 = cmNp2 . GetPlacement () . pl_OrientationAngle ; +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fRotSpeedm1 = cmNm1 . m_fRotSpeed ; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fRotSpeedp0 = cmNp0 . m_fRotSpeed ; +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fRotSpeedp1 = cmNp1 . m_fRotSpeed ; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fRotSpeedp2 = cmNp2 . m_fRotSpeed ; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOATquat3D qPNm1 ;qPNm1 . FromEuler (aPNm1 ); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOATquat3D qPNp0 ;qPNp0 . FromEuler (aPNp0 ); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOATquat3D qPNp1 ;qPNp1 . FromEuler (aPNp1 ); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOATquat3D qPNp2 ;qPNp2 . FromEuler (aPNp2 ); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(qPNm1 % qPNp0 < 0){ +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +qPNp0 = - qPNp0 ; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(qPNp0 % qPNp1 < 0){ +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +qPNp1 = - qPNp1 ; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(qPNp1 % qPNp2 < 0){ +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +qPNp2 = - qPNp2 ; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_tmAtMarker = m_tmAtMarker + m_tmDelta ; +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_tmDelta = cmNp0 . m_fDeltaTime ; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_vPNp0 = vPNp0 ; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_vPNp1 = vPNp1 ; +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_fRotSpeedp0 = fRotSpeedp0 ; +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_fRotSpeedp1 = fRotSpeedp1 ; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_qPNp0 = qPNp0 ; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_qPNp1 = qPNp1 ; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT tmDNm1 = cmNm1 . m_fDeltaTime ; +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT tmDNp0 = cmNp0 . m_fDeltaTime ; +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT tmDNp1 = cmNp1 . m_fDeltaTime ; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fD0 = 2 * tmDNp0 / (tmDNm1 + tmDNp0 ); +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fD1 = 2 * tmDNp0 / (tmDNp0 + tmDNp1 ); +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fBNp0 = cmNp0 . m_fBias ; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fTNp0 = cmNp0 . m_fTension ; +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fCNp0 = cmNp0 . m_fContinuity ; +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fBNp1 = cmNp1 . m_fBias ; +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fTNp1 = cmNp1 . m_fTension ; +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fCNp1 = cmNp1 . m_fContinuity ; +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fF00 = (1 - fTNp0 ) * (1 - fCNp0 ) * (1 - fBNp0 ) / 2; +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fF01 = (1 - fTNp0 ) * (1 + fCNp0 ) * (1 + fBNp0 ) / 2; +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fF10 = (1 - fTNp1 ) * (1 + fCNp1 ) * (1 - fBNp1 ) / 2; +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fF11 = (1 - fTNp1 ) * (1 - fCNp1 ) * (1 + fBNp1 ) / 2; +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_vTNp0 = ((vPNp1 - vPNp0 ) * fF00 + (vPNp0 - vPNm1 ) * fF01 ) * fD0 ; +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_vTNp1 = ((vPNp2 - vPNp1 ) * fF10 + (vPNp1 - vPNp0 ) * fF11 ) * fD1 ; +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_fTRotSpeedp0 = ((fRotSpeedp1 - fRotSpeedp0 ) * fF00 + (fRotSpeedp0 - fRotSpeedm1 ) * fF01 ) * fD0 ; +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_fTRotSpeedp1 = ((fRotSpeedp2 - fRotSpeedp1 ) * fF10 + (fRotSpeedp1 - fRotSpeedp0 ) * fF11 ) * fD1 ; +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOATquat3D qTNp0 , qTNp1 ; +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +qTNp0 = (Log (qPNp0 . Inv () * qPNp1 ) * fF00 + Log (qPNm1 . Inv () * qPNp0 ) * fF01 ) * fD0 ; +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +qTNp1 = (Log (qPNp1 . Inv () * qPNp2 ) * fF10 + Log (qPNp0 . Inv () * qPNp1 ) * fF11 ) * fD1 ; +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_qANp0 = qPNp0 * Exp ((qTNp0 - Log (qPNp0 . Inv () * qPNp1 )) / 2); +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_qANp1 = qPNp1 * Exp ((Log (qPNp0 . Inv () * qPNp1 ) - qTNp1 ) / 2); +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(cmNp0 . m_bStopMoving && m_fRotSpeed == 0.0f){ +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_bStopMoving = TRUE ; +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fT = (tmCurrent - m_tmAtMarker ) / m_tmDelta ; +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fH0 = 2 * fT * fT * fT - 3 * fT * fT + 1; +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fH1 = - 2 * fT * fT * fT + 3 * fT * fT ; +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fH2 = fT * fT * fT - 2 * fT * fT + fT ; +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fH3 = fT * fT * fT - fT * fT ; +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT3D vPos = m_vPNp0 * fH0 + m_vPNp1 * fH1 + m_vTNp0 * fH2 + m_vTNp1 * fH3 ; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fRotSpeed = m_fRotSpeedp0 * fH0 + m_fRotSpeedp1 * fH1 + m_fTRotSpeedp0 * fH2 + m_fTRotSpeedp1 * fH3 ; +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOATquat3D qRot = Squad (fT , m_qPNp0 , m_qPNp1 , m_qANp0 , m_qANp1 ); +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOATmatrix3D mRotLocal ; +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +MakeRotationMatrixFast (mRotLocal , ANGLE3D (m_fRot , 0 , 0)); +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOATmatrix3D mRot ; +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +qRot . ToMatrix (mRot ); +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +mRot = mRotLocal * mRot ; +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +en_vNextPosition = vPos ; +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +en_mNextRotation = mRot ; +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CacheNearPolygons (); +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plNew ; +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plNew . pl_PositionVector = vPos ; +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +DecomposeRotationMatrixNoSnap (plNew . pl_OrientationAngle , mRot ); +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetPlacement_internal (plNew , mRot , TRUE ); +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(! bLerping ){ +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +en_plLastPlacement = en_plPlacement ; +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_fLastRotSpeed = m_fRotSpeed ; +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_fRotSpeed = fRotSpeed ; +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_fRot += m_fRotSpeed ; +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::PostMoving() +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(! m_bMoving ){ +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return ; +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(en_plpLastPositions != NULL ){ +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +en_plpLastPositions -> AddPosition (en_vNextPosition ); +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_bStopMoving ){ +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_bMoving = FALSE ; +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +en_ulFlags |= ENF_INRENDERING ; +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_epssState = PSSS_REACHED_DESTINATION ; +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +en_plLastPlacement = en_plPlacement ; +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::SpawnBeamMachineFlares(void) +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plSpaceShip = GetPlacement (); +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plFlare1 = CPlacement3D (FLOAT3D (BM_DX , BM_DY + BM_FLARE_DY , 0) , ANGLE3D (0 , 0 , 0)); +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plFlare2 = CPlacement3D (FLOAT3D (0 , BM_DY + BM_FLARE_DY , - BM_DZ ) , ANGLE3D (0 , 0 , 0)); +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plFlare3 = CPlacement3D (FLOAT3D (- BM_DX , BM_DY + BM_FLARE_DY , 0) , ANGLE3D (0 , 0 , 0)); +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plFlare4 = CPlacement3D (FLOAT3D (0 , BM_DY + BM_FLARE_DY , BM_DZ ) , ANGLE3D (0 , 0 , 0)); +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plFlare1 . RelativeToAbsolute (plSpaceShip ); +#line 453 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plFlare2 . RelativeToAbsolute (plSpaceShip ); +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plFlare3 . RelativeToAbsolute (plSpaceShip ); +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plFlare4 . RelativeToAbsolute (plSpaceShip ); +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CEntity * penFlare1 = CreateEntity (plFlare1 , CLASS_EFFECTOR ); +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CEntity * penFlare2 = CreateEntity (plFlare2 , CLASS_EFFECTOR ); +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CEntity * penFlare3 = CreateEntity (plFlare3 , CLASS_EFFECTOR ); +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CEntity * penFlare4 = CreateEntity (plFlare4 , CLASS_EFFECTOR ); +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ESpawnEffector eSpawnFlare ; +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnFlare . tmLifeTime = SMALL_FLARES_LIFE_TIME ; +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnFlare . tmLifeTime = 10.5f; +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnFlare . eetType = ET_SIZING_RING_FLARE ; +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penFlare1 -> Initialize (eSpawnFlare ); +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penFlare2 -> Initialize (eSpawnFlare ); +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penFlare3 -> Initialize (eSpawnFlare ); +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penFlare4 -> Initialize (eSpawnFlare ); +#line 471 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::SpawnBeamMachineMainFlare(void) +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plSpaceShip = GetPlacement (); +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plFlare = CPlacement3D (FLOAT3D (0 , BM_MASTER_Y + BM_FLARE_DY , 0) , ANGLE3D (0 , 0 , 0)); +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plFlare . RelativeToAbsolute (GetPlacement ()); +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CEntity * penFlare = CreateEntity (plFlare , CLASS_EFFECTOR ); +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ESpawnEffector eSpawnFlare ; +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnFlare . tmLifeTime = 20.0f; +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnFlare . fSize = 1.0f; +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnFlare . eetType = ET_SIZING_BIG_BLUE_FLARE ; +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penFlare -> Initialize (eSpawnFlare ); +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::ShowBeamMachineHitFlare(void) +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_penHitPlaceFlare != NULL && IsOfClass (m_penHitPlaceFlare , "ModelHolder2")) +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 491 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CModelObject * pmo = m_penHitPlaceFlare -> GetModelObject (); +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(pmo != NULL ) +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_penHitPlaceFlare -> SwitchToModel (); +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 496 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::HideBeamMachineHitFlare(void) +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_tmHitFlareTime = - 1; +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_penHitPlaceFlare != NULL && IsOfClass (m_penHitPlaceFlare , "ModelHolder2")) +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CModelObject * pmo = m_penHitPlaceFlare -> GetModelObject (); +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(pmo != NULL ) +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_penHitPlaceFlare -> SwitchToEditorModel (); +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +pmo -> mo_colBlendColor = C_WHITE | CT_OPAQUE ; +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::SpawnBeamMachineLightnings(void) +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plLightning1 = CPlacement3D (FLOAT3D (BM_DX , BM_DY , 0) , ANGLE3D (0 , 0 , 0)); +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plLightning2 = CPlacement3D (FLOAT3D (0 , BM_DY , - BM_DZ ) , ANGLE3D (0 , 0 , 0)); +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plLightning3 = CPlacement3D (FLOAT3D (- BM_DX , BM_DY , 0) , ANGLE3D (0 , 0 , 0)); +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plLightning4 = CPlacement3D (FLOAT3D (0 , BM_DY , BM_DZ ) , ANGLE3D (0 , 0 , 0)); +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plLightningDest = CPlacement3D (FLOAT3D (0 , BM_MASTER_Y , 0) , ANGLE3D (0 , 0 , 0)); +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plSpaceShip = GetPlacement (); +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plLightningDest . RelativeToAbsolute (plSpaceShip ); +#line 525 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plLightning1 . RelativeToAbsolute (plSpaceShip ); +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plLightning2 . RelativeToAbsolute (plSpaceShip ); +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plLightning3 . RelativeToAbsolute (plSpaceShip ); +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plLightning4 . RelativeToAbsolute (plSpaceShip ); +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CEntity * penLightning1 = CreateEntity (plLightning1 , CLASS_EFFECTOR ); +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CEntity * penLightning2 = CreateEntity (plLightning2 , CLASS_EFFECTOR ); +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CEntity * penLightning3 = CreateEntity (plLightning3 , CLASS_EFFECTOR ); +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CEntity * penLightning4 = CreateEntity (plLightning4 , CLASS_EFFECTOR ); +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ESpawnEffector eSpawnLightning ; +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnLightning . eetType = ET_LIGHTNING ; +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnLightning . tmLifeTime = SMALL_LIGHTININGS_LIFE_TIME ; +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnLightning . vDestination = plLightningDest . pl_PositionVector ; +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnLightning . fSize = 16.0f; +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnLightning . ctCount = 16; +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penLightning1 -> Initialize (eSpawnLightning ); +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penLightning2 -> Initialize (eSpawnLightning ); +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penLightning3 -> Initialize (eSpawnLightning ); +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penLightning4 -> Initialize (eSpawnLightning ); +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::SpawnBeamMachineMainLightning(void) +#line 549 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT3D vDestination = GetPlacement () . pl_PositionVector + FLOAT3D (0 , BM_MASTER_Y , 0); +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plSource = CPlacement3D (vDestination , ANGLE3D (0 , 0 , 0)); +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_penBeamHit != NULL ) +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +plSource . pl_PositionVector = m_penBeamHit -> GetPlacement () . pl_PositionVector ; +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CEntity * penEffector = CreateEntity (plSource , CLASS_EFFECTOR ); +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ESpawnEffector eSpawnEffector ; +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnEffector . eetType = ET_LIGHTNING ; +#line 559 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnEffector . tmLifeTime = BIG_LIGHT_BEAM_LIFE_TIME ; +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnEffector . vDestination = vDestination ; +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnEffector . fSize = 32.0f; +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnEffector . ctCount = 32; +#line 563 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penEffector -> Initialize (eSpawnEffector ); +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 565 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::SpawnMovingRing(void) +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_penBeamHit != NULL ) +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT3D vStart = GetPlacement () . pl_PositionVector + FLOAT3D (0 , BM_MASTER_Y , 0); +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D plSource = CPlacement3D (vStart , ANGLE3D (0 , 0 , 0)); +#line 573 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT3D vHitPlace = m_penBeamHit -> GetPlacement () . pl_PositionVector ; +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CEntity * penEffector = CreateEntity (plSource , CLASS_EFFECTOR ); +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ESpawnEffector eSpawnEffector ; +#line 576 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnEffector . eetType = ET_MOVING_RING ; +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnEffector . tmLifeTime = BIG_LIGHT_BEAM_LIFE_TIME ; +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnEffector . vDestination = vHitPlace + FLOAT3D (0.0f , 0.0f , 0.0f); +#line 579 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnEffector . fSize = 16.0f; +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eSpawnEffector . ctCount = 2; +#line 581 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penEffector -> Initialize (eSpawnEffector ); +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 583 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 585 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::TurnOnLightBeam(void) +#line 586 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_penLightBeam != NULL && IsOfClass (m_penLightBeam , "ModelHolder2")) +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 589 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CModelObject * pmo = m_penLightBeam -> GetModelObject (); +#line 590 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_penLightBeam -> SwitchToModel (); +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +pmo -> mo_colBlendColor = C_WHITE | CT_OPAQUE ; +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 593 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void CPyramidSpaceShip::TurnOffLightBeam(void) +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_tmBeamTime = - 1.0f; +#line 599 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_penLightBeam != NULL && IsOfClass (m_penLightBeam , "ModelHolder2")) +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_penLightBeam -> SwitchToEditorModel (); +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CModelObject * pmo = m_penLightBeam -> GetModelObject (); +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} + +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +BOOL CPyramidSpaceShip::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) +#line 607 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fBeamRatio = 1.0f; +#line 611 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_penLightBeam != NULL && IsOfClass (m_penLightBeam , "ModelHolder2")) +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CModelObject * pmo = m_penLightBeam -> GetModelObject (); +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(pmo != NULL ) +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 616 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_tmBeamTime > - 1.0f) +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 618 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fT = _pTimer -> CurrentTick () - m_tmBeamTime ; +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +fBeamRatio = 1.0f - ClampUp (fT / 2.0f , 1.0f); +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +UBYTE ub = UBYTE (255.0f * fBeamRatio ); +#line 621 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +COLOR col = RGBAToColor (ub , ub , ub , ub ); +#line 622 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +pmo -> mo_colBlendColor = col ; +#line 623 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 624 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 628 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_penHitPlaceFlare != NULL && IsOfClass (m_penHitPlaceFlare , "ModelHolder2")) +#line 629 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CModelObject * pmo = m_penHitPlaceFlare -> GetModelObject (); +#line 631 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(pmo != NULL ) +#line 632 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 633 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_tmHitFlareTime > - 1.0f) +#line 634 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 635 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fT = _pTimer -> CurrentTick () - m_tmHitFlareTime ; +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fRatio = (Sin (fT * 2000) * 0.5f + 0.5f) * (Sin (fT * 1333) * 0.5f + 0.5f); +#line 646 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +UBYTE ub = UBYTE ((200 + 55 * fRatio ) * fBeamRatio ); +#line 648 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +COLOR col = RGBAToColor (ub , ub , ub , ub ); +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +pmo -> mo_colBlendColor = col ; +#line 650 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 652 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return FALSE ; +#line 654 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +BOOL CPyramidSpaceShip:: +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +MPIntro(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPyramidSpaceShip_MPIntro + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPyramidSpaceShip::MPIntro expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 660 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SwitchToModel (); +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_bImmediateAnimations = TRUE ; +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +STATE_CPyramidSpaceShip_OpenDoors, TRUE; +Jump(STATE_CURRENT, 0x02610002, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x02610002_MPIntro_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610002 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPyramidSpaceShip_OpenDoors, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x02610003, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x02610003_MPIntro_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610003 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +STATE_CPyramidSpaceShip_FireLightBeam, TRUE; +Jump(STATE_CURRENT, 0x02610004, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x02610004_MPIntro_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPyramidSpaceShip_FireLightBeam, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x02610005, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x02610005_MPIntro_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610005 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 664 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_epssState = PSSS_BEAM_DEACTIVATED ; +#line 665 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAfter(m_fWaitAfterKillingBeam ); +Jump(STATE_CURRENT, 0x02610006, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x02610006_MPIntro_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02610007, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x02610007_MPIntro_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610007 +; +#line 666 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +STATE_CPyramidSpaceShip_FireLightBeam, TRUE; +Jump(STATE_CURRENT, 0x02610008, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x02610008_MPIntro_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPyramidSpaceShip_FireLightBeam, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x02610009, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x02610009_MPIntro_08(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610009 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 667 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_bImmediateAnimations = FALSE ; +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +STATE_CPyramidSpaceShip_CloseDoors, TRUE; +Jump(STATE_CURRENT, 0x0261000a, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x0261000a_MPIntro_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CPyramidSpaceShip_CloseDoors, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0261000b, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x0261000b_MPIntro_10(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261000b +const EReturn&__e= (EReturn&)__eeInput; +; +#line 669 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Return(STATE_CURRENT,EReturn ()); +#line 669 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPyramidSpaceShip:: +#line 673 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +OpenDoors(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPyramidSpaceShip_OpenDoors + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPyramidSpaceShip::OpenDoors expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 676 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_SHIPINSIDE ) == NULL ) +#line 677 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 679 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_SHIPINSIDE , MODEL_SHIP_INSIDE , TEXTURE_BODY ); +#line 680 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> StretchModel (PSS_STRETCH ); +#line 681 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 682 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ShowBeamMachine (); +#line 684 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(! m_bImmediateAnimations ) +#line 685 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 686 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PlaySound (m_soPlates , SOUND_PLATES , SOF_3D ); +#line 687 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR1 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPENING , 0); +#line 688 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR2 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPENING , 0); +#line 689 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR3 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPENING , 0); +#line 690 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR4 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPENING , 0); +#line 691 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR5 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPENING , 0); +#line 692 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR6 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPENING , 0); +#line 693 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR7 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPENING , 0); +#line 694 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR8 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPENING , 0); +#line 695 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 696 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +else +#line 697 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 698 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR1 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPEN , 0); +#line 699 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR2 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPEN , 0); +#line 700 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR3 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPEN , 0); +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR4 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPEN , 0); +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR5 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPEN , 0); +#line 703 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR6 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPEN , 0); +#line 704 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR7 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPEN , 0); +#line 705 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR8 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_OPEN , 0); +#line 706 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FOREACHINLIST (CEntity , en_lnInParent , en_lhChildren , iten ) +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 711 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(IsOfClass (iten , "Light")) +#line 712 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 713 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(iten -> GetName () == "Pulsating") +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CLight * penLight = (CLight *) & * iten ; +#line 716 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +EChangeAnim eChange ; +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eChange . iLightAnim = 3; +#line 718 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eChange . bLightLoop = TRUE ; +#line 719 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penLight -> SendEvent (eChange ); +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 721 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +else if(iten -> GetName () == "Motors") +#line 722 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 723 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CLight * penLight = (CLight *) & * iten ; +#line 724 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +EChangeAnim eChange ; +#line 725 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eChange . iLightAnim = 4; +#line 726 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +eChange . bLightLoop = TRUE ; +#line 727 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +penLight -> SendEvent (eChange ); +#line 728 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 729 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 730 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 732 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_epssState = PSSS_KILLING_BEAM_FIREING ; +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Return(STATE_CURRENT,EReturn ()); +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPyramidSpaceShip:: +#line 736 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CloseDoors(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPyramidSpaceShip_CloseDoors + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPyramidSpaceShip::CloseDoors expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 738 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_epssState = PSSS_DOORS_CLOSED ; +#line 740 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(!(GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_SHIPINSIDE ) != NULL )){ Jump(STATE_CURRENT,0x02610010, FALSE, EInternal());return TRUE;} +#line 742 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PlaySound (m_soPlates , SOUND_PLATES , SOF_3D ); +#line 743 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR1 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_CLOSING , 0); +#line 744 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR2 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_CLOSING , 0); +#line 745 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR3 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_CLOSING , 0); +#line 746 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR4 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_CLOSING , 0); +#line 747 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR5 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_CLOSING , 0); +#line 748 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR6 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_CLOSING , 0); +#line 749 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR7 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_CLOSING , 0); +#line 750 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR8 ) -> amo_moModelObject . PlayAnim (DOOR_ANIM_CLOSING , 0); +#line 752 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAfter(GetModelObject () -> GetAttachmentModel (SPACESHIP_ATTACHMENT_DOOR1 ) -> amo_moModelObject . GetAnimLength (DOOR_ANIM_CLOSING )); +Jump(STATE_CURRENT, 0x0261000e, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x0261000e_CloseDoors_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0261000f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x0261000f_CloseDoors_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261000f +; +#line 754 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +RemoveAttachment (SPACESHIP_ATTACHMENT_SHIPINSIDE );Jump(STATE_CURRENT,0x02610010, FALSE, EInternal());return TRUE;}BOOL CPyramidSpaceShip::H0x02610010_CloseDoors_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610010 + +#line 757 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +HideBeamMachine (); +#line 758 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +InitializePathMoving ((CPyramidSpaceShipMarker *) & * m_penFlyAwayTarget ); +#line 759 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Return(STATE_CURRENT,EReturn ()); +#line 759 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPyramidSpaceShip:: +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FireLightBeam(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPyramidSpaceShip_FireLightBeam + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPyramidSpaceShip::FireLightBeam expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 764 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_epssState == PSSS_DOORS_CLOSED ) +#line 765 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 766 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Return(STATE_CURRENT,EVoid()); +#line 766 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; +#line 767 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 769 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_epssState == PSSS_BEAM_DEACTIVATED ) +#line 770 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 771 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_bFireingDeactivatedBeam = TRUE ; +#line 772 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 774 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(!(! m_bImmediateAnimations )){ Jump(STATE_CURRENT,0x02610015, FALSE, EInternal());return TRUE;} +#line 776 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PlaySound (m_soBeamMachine , SOUND_BEAMMACHINE , SOF_3D ); +#line 777 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> PlayAnim (SPACESHIP_ANIM_OPENING , 0); +#line 778 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (SPACESHIP_ANIM_OPENING )); +Jump(STATE_CURRENT, 0x02610012, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x02610012_FireLightBeam_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610012 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02610013, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x02610013_FireLightBeam_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610013 +;Jump(STATE_CURRENT,0x02610014, FALSE, EInternal());return TRUE;}BOOL CPyramidSpaceShip::H0x02610015_FireLightBeam_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610015 + +#line 781 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 782 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> PlayAnim (SPACESHIP_ANIM_OPEN , 0); +#line 783 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}Jump(STATE_CURRENT,0x02610014, FALSE, EInternal());return TRUE;} +BOOL CPyramidSpaceShip::H0x02610014_FireLightBeam_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610014 + +#line 785 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(!(! m_bImmediateAnimations )){ Jump(STATE_CURRENT,0x02610019, FALSE, EInternal());return TRUE;} +#line 787 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PlaySound (m_soBeamMachine , SOUND_WARMUP , SOF_3D ); +#line 788 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SpawnBeamMachineFlares (); +#line 789 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAfter(SMALL_FLARE_WAIT ); +Jump(STATE_CURRENT, 0x02610016, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x02610016_FireLightBeam_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610016 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02610017, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x02610017_FireLightBeam_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610017 +;Jump(STATE_CURRENT,0x02610018, FALSE, EInternal());return TRUE;}BOOL CPyramidSpaceShip::H0x02610019_FireLightBeam_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610019 + +#line 792 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 793 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SpawnBeamMachineFlares (); +#line 794 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}Jump(STATE_CURRENT,0x02610018, FALSE, EInternal());return TRUE;} +BOOL CPyramidSpaceShip::H0x02610018_FireLightBeam_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610018 + +#line 796 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SpawnBeamMachineLightnings (); +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(!(! m_bImmediateAnimations )){ Jump(STATE_CURRENT,0x0261001c, FALSE, EInternal());return TRUE;} +#line 799 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAfter(SMALL_LIGHTNING_WAIT ); +Jump(STATE_CURRENT, 0x0261001a, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x0261001a_FireLightBeam_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261001a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0261001b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x0261001b_FireLightBeam_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261001b +;Jump(STATE_CURRENT,0x0261001c, FALSE, EInternal());return TRUE;}BOOL CPyramidSpaceShip::H0x0261001c_FireLightBeam_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261001c + +#line 802 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SpawnBeamMachineMainFlare (); +#line 803 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(!(! m_bImmediateAnimations )){ Jump(STATE_CURRENT,0x0261001f, FALSE, EInternal());return TRUE;} +#line 805 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAfter(BIG_FLARE_WAIT ); +Jump(STATE_CURRENT, 0x0261001d, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x0261001d_FireLightBeam_12(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261001d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0261001e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x0261001e_FireLightBeam_13(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261001e +;Jump(STATE_CURRENT,0x0261001f, FALSE, EInternal());return TRUE;}BOOL CPyramidSpaceShip::H0x0261001f_FireLightBeam_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261001f + +#line 809 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +TurnOnLightBeam (); +#line 810 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(! m_bFireingDeactivatedBeam ) +#line 811 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 812 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SpawnBeamMachineMainLightning (); +#line 813 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 815 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_soBeam . Set3DParameters (SND_FALLOFF , SND_HOTSPOT , SND_VOLUME , 1.0f); +#line 816 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PlaySound (m_soBeam , SOUND_BEAM , SOF_3D | SOF_LOOP ); +#line 817 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ShowBeamMachineHitFlare (); +#line 818 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_tmHitFlareTime = _pTimer -> CurrentTick (); +#line 820 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_iRingCounter = 0; +#line 821 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Jump(STATE_CURRENT,0x02610024, FALSE, EInternal());return TRUE;}BOOL CPyramidSpaceShip::H0x02610024_FireLightBeam_19(const CEntityEvent &__eeInput) +#line 822 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610024 +if(!(_pTimer -> CurrentTick () < m_tmHitFlareTime + BIG_LIGHT_BEAM_LIFE_TIME )){ Jump(STATE_CURRENT,0x02610025, FALSE, EInternal());return TRUE;} +#line 824 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_iRingCounter < 16) +#line 825 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 826 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SpawnMovingRing (); +#line 827 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_iRingCounter ++; +#line 828 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 831 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_tmTemp = _pTimer -> CurrentTick (); +#line 832 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Jump(STATE_CURRENT,0x02610022, FALSE, EInternal());return TRUE;}BOOL CPyramidSpaceShip::H0x02610022_FireLightBeam_17(const CEntityEvent &__eeInput) +#line 833 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610022 +if(!(_pTimer -> CurrentTick () < m_tmTemp + 0.49f)){ Jump(STATE_CURRENT,0x02610023, FALSE, EInternal());return TRUE;} +#line 834 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x02610020, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x02610020_FireLightBeam_15(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610020 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02610021, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x02610021_FireLightBeam_16(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610021 +; +#line 836 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_penBeamHit != NULL && ! m_bFireingDeactivatedBeam ) +#line 837 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 839 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT3D vSource = GetPlacement () . pl_PositionVector + FLOAT3D (0 , BM_MASTER_Y , 0); +#line 840 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT3D vDestination = m_penBeamHit -> GetPlacement () . pl_PositionVector ; +#line 841 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CCastRay crRay (this , vSource , vDestination ); +#line 842 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 843 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +crRay . cr_bPhysical = FALSE ; +#line 844 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +crRay . cr_ttHitModels = CCastRay :: TT_COLLISIONBOX ; +#line 845 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +crRay . cr_fTestR = 16.0f; +#line 846 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetWorld () -> CastRay (crRay ); +#line 849 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(crRay . cr_penHit != NULL ) +#line 850 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 851 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +InflictDirectDamage (crRay . cr_penHit , this , DMT_BULLET , +#line 852 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +10000.0f / GetGameDamageMultiplier () * _pTimer -> TickQuantum / 0.5f / 16.0f , +#line 853 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT3D (0 , 0 , 0) , (vSource - vDestination ) . Normalize ()); +#line 854 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +crRay . cr_penHit -> SendEvent (EHitBySpaceShipBeam ()); +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 856 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}Jump(STATE_CURRENT,0x02610022, FALSE, EInternal());return TRUE; +#line 857 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}BOOL CPyramidSpaceShip::H0x02610023_FireLightBeam_18(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610023 +Jump(STATE_CURRENT,0x02610024, FALSE, EInternal());return TRUE; +#line 858 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}BOOL CPyramidSpaceShip::H0x02610025_FireLightBeam_20(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610025 + +#line 860 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_tmBeamTime = _pTimer -> CurrentTick (); +#line 861 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Jump(STATE_CURRENT,0x02610028, FALSE, EInternal());return TRUE;}BOOL CPyramidSpaceShip::H0x02610028_FireLightBeam_23(const CEntityEvent &__eeInput) +#line 862 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610028 +if(!(_pTimer -> CurrentTick () < m_tmBeamTime + 2.0f)){ Jump(STATE_CURRENT,0x02610029, FALSE, EInternal());return TRUE;} +#line 863 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x02610026, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x02610026_FireLightBeam_21(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610026 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02610027, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x02610027_FireLightBeam_22(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610027 +; +#line 864 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT tmNow = _pTimer -> CurrentTick (); +#line 865 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FLOAT fRatio = CalculateRatio (tmNow , m_tmBeamTime , m_tmBeamTime + 2.0f , 0 , 1.0f); +#line 866 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_soBeam . Set3DParameters (SND_FALLOFF , SND_HOTSPOT , fRatio * SND_VOLUME , 1.0f);Jump(STATE_CURRENT,0x02610028, FALSE, EInternal());return TRUE; +#line 867 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}BOOL CPyramidSpaceShip::H0x02610029_FireLightBeam_24(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610029 + +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +TurnOffLightBeam (); +#line 871 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +HideBeamMachineHitFlare (); +#line 874 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAfter(2.0f); +Jump(STATE_CURRENT, 0x0261002a, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x0261002a_FireLightBeam_25(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261002a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0261002b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x0261002b_FireLightBeam_26(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261002b +; +#line 876 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> PlayAnim (SPACESHIP_ANIM_CLOSING , 0); +#line 877 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PlaySound (m_soBeamMachine , SOUND_BEAMMACHINE , SOF_3D ); +#line 878 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (SPACESHIP_ANIM_CLOSING )); +Jump(STATE_CURRENT, 0x0261002c, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x0261002c_FireLightBeam_27(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261002c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0261002d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x0261002d_FireLightBeam_28(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261002d +; +#line 880 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_tmHitFlareTime = - 1.0f; +#line 881 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_tmBeamTime = - 1.0f; +#line 883 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_bFireingDeactivatedBeam ) +#line 884 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 885 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Jump(STATE_CURRENT, STATE_CPyramidSpaceShip_CloseDoors, TRUE, EVoid());return TRUE; +#line 886 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 887 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Return(STATE_CURRENT,EReturn ()); +#line 887 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CPyramidSpaceShip:: +#line 890 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPyramidSpaceShip_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPyramidSpaceShip::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 892 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +InitAsEditorModel (); +#line 894 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL | EPF_MOVABLE ); +#line 895 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetCollisionFlags (ECF_MODEL_HOLDER ); +#line 897 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_bImmediateAnimations = FALSE ; +#line 898 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +en_fAcceleration = 1e6f; +#line 899 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +en_fDeceleration = 1e6f; +#line 901 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_soBeam . Set3DParameters (SND_FALLOFF , SND_HOTSPOT , SND_VOLUME , 1.0f); +#line 902 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_soBeamMachine . Set3DParameters (SND_FALLOFF , SND_HOTSPOT , SND_VOLUME / 2.0f , 1.0f); +#line 903 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_soPlates . Set3DParameters (SND_FALLOFF , SND_HOTSPOT , SND_VOLUME / 2.0f , 1.0f); +#line 904 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_soFlaresFX . Set3DParameters (SND_FALLOFF , SND_HOTSPOT , SND_VOLUME , 1.0f); +#line 907 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetModel (MODEL_SPACESHIP ); +#line 908 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetModelMainTexture (TEXTURE_BODY ); +#line 909 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_BODY , MODEL_BODY , TEXTURE_BODY ); +#line 910 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_DOOR1 , MODEL_DOOR , TEXTURE_DOOR ); +#line 911 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_DOOR2 , MODEL_DOOR , TEXTURE_DOOR ); +#line 912 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_DOOR3 , MODEL_DOOR , TEXTURE_DOOR ); +#line 913 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_DOOR4 , MODEL_DOOR , TEXTURE_DOOR ); +#line 914 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_DOOR5 , MODEL_DOOR , TEXTURE_DOOR ); +#line 915 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_DOOR6 , MODEL_DOOR , TEXTURE_DOOR ); +#line 916 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_DOOR7 , MODEL_DOOR , TEXTURE_DOOR ); +#line 917 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +AddAttachment (SPACESHIP_ATTACHMENT_DOOR8 , MODEL_DOOR , TEXTURE_DOOR ); +#line 919 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +GetModelObject () -> StretchModel (PSS_STRETCH ); +#line 920 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +ModelChangeNotify (); +#line 921 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_bMoving = FALSE ; +#line 922 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_epssState = PSSS_IDLE ; +#line 923 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_bFireingDeactivatedBeam = FALSE ; +#line 925 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x0261002e, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x0261002e_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261002e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0261002f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CPyramidSpaceShip::H0x0261002f_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0261002f +; +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +TurnOffLightBeam (); +#line 930 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +HideBeamMachineHitFlare (); +#line 933 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x02610030, FALSE, EBegin());return TRUE;}BOOL CPyramidSpaceShip::H0x02610030_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610030 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EActivate): +#line 935 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{const EActivate&e= (EActivate&)__eeInput; + +#line 936 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(! m_bInvisible ) +#line 937 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 938 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +SwitchToModel (); +#line 939 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 940 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +InitializePathMoving ((CPyramidSpaceShipMarker *) & * m_penTarget ); +#line 941 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; +#line 942 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger): +#line 944 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{const ETrigger&e= (ETrigger&)__eeInput; + +#line 945 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_epssState == PSSS_IDLE ) +#line 946 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 948 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 949 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +else if(m_epssState == PSSS_KILLING_BEAM_FIREING ) +#line 950 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 951 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Call(STATE_CURRENT, STATE_CPyramidSpaceShip_FireLightBeam, TRUE, EVoid());return TRUE; +#line 952 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 953 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +else if(m_epssState == PSSS_BEAM_DEACTIVATED ) +#line 954 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 955 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Call(STATE_CURRENT, STATE_CPyramidSpaceShip_FireLightBeam, TRUE, EVoid());return TRUE; +#line 956 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 957 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +else if(m_epssState == PSSS_REACHED_DESTINATION ) +#line 958 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 959 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Call(STATE_CURRENT, STATE_CPyramidSpaceShip_OpenDoors, TRUE, EVoid());return TRUE; +#line 960 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 961 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; +#line 962 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}ASSERT(FALSE);break;case(EVENTCODE_EForcePathMarker): +#line 964 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{const EForcePathMarker&eForcePathMarker= (EForcePathMarker&)__eeInput; + +#line 965 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +if(m_epssState != PSSS_IDLE ) +#line 966 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{ +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_penTarget = eForcePathMarker . penForcedPathMarker ; +#line 968 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +InitializePathMoving ((CPyramidSpaceShipMarker *) & * m_penTarget ); +#line 969 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +} +#line 970 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; +#line 971 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnvironmentStart): +#line 973 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{const EEnvironmentStart&e= (EEnvironmentStart&)__eeInput; + +#line 974 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Call(STATE_CURRENT, STATE_CPyramidSpaceShip_MPIntro, TRUE, EVoid());return TRUE; +#line 975 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; +#line 976 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnvironmentStop): +#line 978 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{const EEnvironmentStop&e= (EEnvironmentStop&)__eeInput; + +#line 979 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_bMoving = FALSE ; +#line 980 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +PostMoving (); +#line 981 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; +#line 982 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate): +#line 984 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 985 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +m_epssState = PSSS_BEAM_DEACTIVATED ; +#line 986 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; +#line 987 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn): +#line 989 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +{const EReturn&e= (EReturn&)__eeInput; + +#line 990 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; +#line 991 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 992 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +}return TRUE;}BOOL CPyramidSpaceShip::H0x02610031_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02610031 + +#line 994 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Destroy (); +#line 995 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Return(STATE_CURRENT,EVoid()); +#line 995 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/PyramidSpaceShip.es b/Sources/EntitiesMP/PyramidSpaceShip.es new file mode 100644 index 0000000..79834a3 --- /dev/null +++ b/Sources/EntitiesMP/PyramidSpaceShip.es @@ -0,0 +1,997 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +609 +%{ +#include "StdH.h" +#include "Models/CutSequences/SpaceShip/SpaceShip.h" +#include "Models/CutSequences/SpaceShip/Door.h" +#include "Models/CutSequences/SpaceShip/LightBeam.h" +#include "EntitiesMP/Effector.h" +#include "EntitiesMP/Light.h" +%} + +uses "EntitiesMP/PyramidSpaceShipMarker"; + +enum PSSState { + 0 PSSS_IDLE "Idle", // idle + 1 PSSS_MOVING "Moving", // process of moving trough markers + 2 PSSS_REACHED_DESTINATION "Reached destination", // process of turning on + 3 PSSS_KILLING_BEAM_FIREING "Killing beam fireing", // killing beam fireing + 4 PSSS_BEAM_DEACTIVATED "Killing beam deactivated", // killing beam gas been deactivated, wait to pick up Sam + 5 PSSS_DOORS_CLOSED "Doors closed", // doors closed +}; + +event EForcePathMarker { + CEntityPointer penForcedPathMarker, +}; + +%{ +#define STRETCH_X (200.0f*m_fStretch) +#define STRETCH_Y (100.0f*m_fStretch) +#define STRETCH_Z (200.0f*m_fStretch) +#define PSS_STRETCH (FLOAT3D(STRETCH_X, STRETCH_Y, STRETCH_Z)*m_fStretch) +#define SND_FALLOFF 1000.0f +#define SND_HOTSPOT 250.0f +#define SND_VOLUME 2.0f + +#define BIG_LIGHT_BEAM_LIFE_TIME (8.0f) +#define SMALL_FLARE_WAIT 2.0f +#define SMALL_FLARES_LIFE_TIME (BIG_LIGHT_BEAM_LIFE_TIME+SMALL_FLARE_WAIT) +#define SMALL_LIGHTNING_WAIT 1.5f +#define SMALL_LIGHTININGS_LIFE_TIME (SMALL_FLARES_LIFE_TIME+SMALL_LIGHTNING_WAIT) +#define BIG_FLARE_WAIT 1.0f +#define BIG_FLARE_LIFE_TIME (SMALL_LIGHTININGS_LIFE_TIME+BIG_FLARE_WAIT) + +#define BM_DX (0.414657f*STRETCH_X) +#define BM_DY (-1.72731f*STRETCH_Y) +#define BM_DZ (0.414657f*STRETCH_Z) +#define BM_FLARE_DY (-0.25f*STRETCH_Y) + +#define BM_MASTER_Y (-1.76648f*STRETCH_Y) +%} + +class CPyramidSpaceShip: CMovableModelEntity { +name "PyramidSpaceShip"; +thumbnail "Thumbnails\\PyramidSpaceShip.tbn"; +features "HasName", "IsTargetable"; +properties: + 1 CTString m_strName "Name" 'N' = "Pyramid Space Ship", // name + 3 FLOAT m_fMovingSpeed = 0.0f, // current speed + 5 CEntityPointer m_penBeamHit "Beam hit target marker" 'T', // target point for light beam + 6 CEntityPointer m_penLightBeam "Beam model holder" 'B', // light beam model holder + 7 FLOAT m_tmBeamTime =-1.0f, // light beam time var + 8 CEntityPointer m_penHitPlaceFlare "Hit place flare" 'H', // hit place model holder + 9 FLOAT m_tmHitFlareTime =-1.0f, // light beam hit flare time var + 10 FLOAT m_iRingCounter = 0, // ring counter + 11 FLOAT m_fRatio =0.0f, // misc ratio + 12 CTString m_strDescription = "", // description + 13 enum PSSState m_epssState = PSSS_IDLE, // current state + 14 FLOAT m_fStretch "Stretch" 'S' = 1.0f, // stretch factor + // path properties + 20 BOOL m_bStopMoving = FALSE, // stop moving on next marker + 21 CEntityPointer m_penTarget "Target" 'T' COLOR(C_lBLUE|0xFF), // next path target + 29 CEntityPointer m_penFlyAwayTarget "Fly away path marker" COLOR(C_lBLUE|0xFF), // fly away path marker + 22 CEntityPointer m_penLast, // previous marker + 23 BOOL m_bMoving = FALSE, // set while moving + 24 FLOAT m_fRot = 0.0f, // current rotation + 25 FLOAT m_fLastRotSpeed = 0.0f, // last speed rotation + 26 FLOAT m_fRotSpeed = 0.0f, // current speed rotation + 27 BOOL m_bApplyDamageToHitted = TRUE, // if damage should be applied + 28 FLOAT m_tmTemp = 0.0f, // temporary time var + + 30 FLOAT m_tmAtMarker = 0.0f, // time when current marker was reached + 31 FLOAT m_tmDelta = 0.0f, // time to reach next marker + 32 FLOAT3D m_vPNp0 = FLOAT3D(0,0,0), + 33 FLOAT3D m_vPNp1 = FLOAT3D(0,0,0), + 34 FLOAT3D m_vTNp0 = FLOAT3D(0,0,0), + 35 FLOAT3D m_vTNp1 = FLOAT3D(0,0,0), + 36 FLOATquat3D m_qPNp0 = FLOATquat3D(0,0,0,0), + 37 FLOATquat3D m_qPNp1 = FLOATquat3D(0,0,0,0), + 38 FLOATquat3D m_qANp0 = FLOATquat3D(0,0,0,0), + 39 FLOATquat3D m_qANp1 = FLOATquat3D(0,0,0,0), + 40 FLOAT m_fRotSpeedp0 = 0.0f, + 41 FLOAT m_fRotSpeedp1 = 0.0f, + 42 FLOAT m_fTRotSpeedp0 = 0.0f, + 43 FLOAT m_fTRotSpeedp1 = 0.0f, + + 50 CSoundObject m_soPlates, + 51 CSoundObject m_soBeamMachine, + 52 CSoundObject m_soBeam, + 53 CSoundObject m_soFlaresFX, + 54 BOOL m_bFireingDeactivatedBeam=FALSE, + 55 BOOL m_bImmediateAnimations=FALSE, + 56 FLOAT m_fWaitAfterKillingBeam "Wait after auto killing beam" 'W' = 1.0f, + + 60 BOOL m_bInvisible "Invisible" 'I' = FALSE, + +components: + 1 model MODEL_SPACESHIP "Models\\CutSequences\\SpaceShip\\SpaceShip.mdl", + 2 model MODEL_BODY "Models\\CutSequences\\SpaceShip\\Body.mdl", + 3 texture TEXTURE_BODY "Models\\CutSequences\\SpaceShip\\Body.tex", + 4 model MODEL_DOOR "Models\\CutSequences\\SpaceShip\\Door.mdl", + 5 texture TEXTURE_DOOR "Models\\CutSequences\\SpaceShip\\Door.tex", + 6 model MODEL_BEAMMACHINE "Models\\CutSequences\\SpaceShip\\BeamMachine.mdl", + 7 texture TEXTURE_BEAMMACHINE "Models\\CutSequences\\SpaceShip\\BeamMachine.tex", + 8 model MODEL_BEAMRIM "Models\\CutSequences\\SpaceShip\\BeamMachineRim.mdl", + 9 texture TEXTURE_BEAMRIM "Models\\CutSequences\\SpaceShip\\BeamMachineRim.tex", + 10 class CLASS_EFFECTOR "Classes\\Effector.ecl", + 11 model MODEL_SHIP_INSIDE "Models\\CutSequences\\SpaceShip\\Fillin.mdl", + 20 sound SOUND_PLATES "Sounds\\CutSequences\\SpaceShip\\SSPlates.wav", + 21 sound SOUND_BEAMMACHINE "Sounds\\CutSequences\\SpaceShip\\SSProbe.wav", + 22 sound SOUND_BEAM "Sounds\\CutSequences\\SpaceShip\\LaserBeam.wav", + 23 sound SOUND_WARMUP "Sounds\\CutSequences\\SpaceShip\\Warmup.wav", + +functions: + void Precache(void) { + PrecacheModel (MODEL_SPACESHIP ); + PrecacheModel (MODEL_BODY ); + PrecacheTexture (TEXTURE_BODY ); + PrecacheModel (MODEL_DOOR ); + PrecacheTexture (TEXTURE_DOOR ); + PrecacheModel (MODEL_BEAMMACHINE ); + PrecacheTexture (TEXTURE_BEAMMACHINE ); + PrecacheModel (MODEL_BEAMRIM ); + PrecacheModel (MODEL_SHIP_INSIDE ); + PrecacheTexture (TEXTURE_BEAMRIM ); + PrecacheClass (CLASS_EFFECTOR, ET_SIZING_RING_FLARE); + PrecacheClass (CLASS_EFFECTOR, ET_SIZING_BIG_BLUE_FLARE); + PrecacheClass (CLASS_EFFECTOR, ET_LIGHTNING); + PrecacheClass (CLASS_EFFECTOR, ET_MOVING_RING); + PrecacheSound (SOUND_PLATES ); + PrecacheSound (SOUND_BEAMMACHINE ); + PrecacheSound (SOUND_BEAM ); + PrecacheSound (SOUND_WARMUP ); + } + + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if(penTarget==NULL) + { + return FALSE; + } + if( slPropertyOffset==offsetof(CPyramidSpaceShip, m_penTarget) || + slPropertyOffset==offsetof(CPyramidSpaceShip, m_penFlyAwayTarget)) + { + return( IsDerivedFromClass(penTarget, "Pyramid Space Ship Marker")); + } + return TRUE; + } + + // Check if entity is moved on a route set up by its targets + BOOL MovesByTargetedRoute( CTString &strTargetProperty) const + { + strTargetProperty = "Target"; + return TRUE; + } + + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker( CTFileName &fnmMarkerClass, CTString &strTargetProperty) const + { + fnmMarkerClass = CTFILENAME("Classes\\PyramidSpaceShipMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + + // returns description + const CTString &GetDescription(void) const + { + if (m_penTarget!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", m_penTarget->GetName()); + } else { + ((CTString&)m_strDescription).PrintF("->"); + } + return m_strDescription; + } + + + CPlacement3D GetLerpedPlacement(void) const + { + return CMovableEntity::GetLerpedPlacement(); + } + + void PreMoving() + { + // remember old placement for lerping + en_plLastPlacement = en_plPlacement; + } + + void HideBeamMachine(void) + { + if(GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_BEAM_RIM) != NULL) + { + RemoveAttachment(SPACESHIP_ATTACHMENT_BEAM_RIM); + } + if(GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_BEAM) != NULL) + { + RemoveAttachment(SPACESHIP_ATTACHMENT_BEAM); + } + } + + void ShowBeamMachine(void) + { + AddAttachment(SPACESHIP_ATTACHMENT_BEAM_RIM, MODEL_BEAMRIM, TEXTURE_BEAMRIM); + AddAttachment(SPACESHIP_ATTACHMENT_BEAM, MODEL_BEAMMACHINE, TEXTURE_BEAMMACHINE); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_BEAM_RIM)->amo_moModelObject.StretchModel(PSS_STRETCH); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_BEAM)->amo_moModelObject.StretchModel(PSS_STRETCH); + } + + void InitializePathMoving( CPyramidSpaceShipMarker *penStartMarker) + { + // set as current + m_penTarget = penStartMarker; + + m_epssState = PSSS_MOVING; + // check all markers for correct type and numbers + INDEX ctMarkers=1; + CPyramidSpaceShipMarker *pcm0 = (CPyramidSpaceShipMarker*)&*m_penTarget; + if( pcm0 == NULL) + { + return; + } + CPyramidSpaceShipMarker *pcm = (CPyramidSpaceShipMarker*)&*pcm0->m_penTarget; + // loop thru markers + while( pcm!=NULL && pcm->m_penTarget!=pcm0) + { + pcm = (CPyramidSpaceShipMarker*)&*pcm->m_penTarget; + if (pcm==NULL) { + WarningMessage( "Space ship path - broken link!"); + return; + } + ctMarkers++; + if (ctMarkers>500) { + WarningMessage( "Space ship path - invalid marker loop!"); + return; + } + } + // check if we have enough markers to do smooth interpolation + if( ctMarkers<2) { + WarningMessage( "Space ship path requires at least 2 markers in order to work!"); + return; + } + + // prepare internal variables + FLOAT tmCurrent = _pTimer->CurrentTick(); + m_tmAtMarker = tmCurrent; + m_tmDelta = 0.0f; + m_bStopMoving = FALSE; + m_penLast = pcm; // keep last marker + ASSERT( pcm->m_penTarget == m_penTarget); + m_bMoving = TRUE; + AddToMovers(); + } + + void DoMoving() + { + if (!m_bMoving) { + return; + } + // read current tick + FLOAT tmCurrent = _pTimer->CurrentTick(); + // lerping is initially enabled + BOOL bLerping = TRUE; + + // if we hit a marker + if( tmCurrent > (m_tmAtMarker+m_tmDelta - _pTimer->TickQuantum*3/2)) + { + // get markers + CPyramidSpaceShipMarker *pcmNm1 = &(CPyramidSpaceShipMarker&)*m_penLast; + CPyramidSpaceShipMarker *pcmNp0 = &(CPyramidSpaceShipMarker&)*m_penTarget; + CPyramidSpaceShipMarker *pcmNp1 = &(CPyramidSpaceShipMarker&)*pcmNp0->m_penTarget; + CPyramidSpaceShipMarker *pcmNp2 = &(CPyramidSpaceShipMarker&)*pcmNp1->m_penTarget; + + // if there is a trigger at the hit marker + if (pcmNp0->m_penTrigger!=NULL) { + // trigger it + SendToTarget(pcmNp0->m_penTrigger, EET_TRIGGER, NULL); + } + + // update markers for next interval + m_penTarget = pcmNp1; + m_penLast = pcmNp0; + + // get markers + CPyramidSpaceShipMarker &cmNm1 = *pcmNm1; + CPyramidSpaceShipMarker &cmNp0 = *pcmNp0; + CPyramidSpaceShipMarker &cmNp1 = *pcmNp1; + CPyramidSpaceShipMarker &cmNp2 = *pcmNp2; + + // get positions from four markers + const FLOAT3D &vPNm1 = cmNm1.GetPlacement().pl_PositionVector; + const FLOAT3D &vPNp0 = cmNp0.GetPlacement().pl_PositionVector; + const FLOAT3D &vPNp1 = cmNp1.GetPlacement().pl_PositionVector; + const FLOAT3D &vPNp2 = cmNp2.GetPlacement().pl_PositionVector; + ANGLE3D aPNm1 = cmNm1.GetPlacement().pl_OrientationAngle; + ANGLE3D aPNp0 = cmNp0.GetPlacement().pl_OrientationAngle; + ANGLE3D aPNp1 = cmNp1.GetPlacement().pl_OrientationAngle; + ANGLE3D aPNp2 = cmNp2.GetPlacement().pl_OrientationAngle; + FLOAT fRotSpeedm1 = cmNm1.m_fRotSpeed; + FLOAT fRotSpeedp0 = cmNp0.m_fRotSpeed; + FLOAT fRotSpeedp1 = cmNp1.m_fRotSpeed; + FLOAT fRotSpeedp2 = cmNp2.m_fRotSpeed; + + // find quaternions for rotations + FLOATquat3D qPNm1; qPNm1.FromEuler(aPNm1); + FLOATquat3D qPNp0; qPNp0.FromEuler(aPNp0); + FLOATquat3D qPNp1; qPNp1.FromEuler(aPNp1); + FLOATquat3D qPNp2; qPNp2.FromEuler(aPNp2); + + // make all angles between quaternion pairs acute + if( qPNm1%qPNp0<0 ) { + qPNp0 = -qPNp0; + } + if( qPNp0%qPNp1<0 ) { + qPNp1 = -qPNp1; + } + if( qPNp1%qPNp2<0 ) { + qPNp2 = -qPNp2; + } + + // update time and position + m_tmAtMarker = m_tmAtMarker+m_tmDelta; + m_tmDelta = cmNp0.m_fDeltaTime; + m_vPNp0 = vPNp0; + m_vPNp1 = vPNp1; + m_fRotSpeedp0 = fRotSpeedp0; + m_fRotSpeedp1 = fRotSpeedp1; + m_qPNp0 = qPNp0; + m_qPNp1 = qPNp1; + + // determine delta time multipliers + FLOAT tmDNm1 = cmNm1.m_fDeltaTime; + FLOAT tmDNp0 = cmNp0.m_fDeltaTime; + FLOAT tmDNp1 = cmNp1.m_fDeltaTime; + FLOAT fD0 = 2*tmDNp0 / (tmDNm1+tmDNp0); + FLOAT fD1 = 2*tmDNp0 / (tmDNp0+tmDNp1); + + // determine biases, tensions and continuities + FLOAT fBNp0 = cmNp0.m_fBias; + FLOAT fTNp0 = cmNp0.m_fTension; + FLOAT fCNp0 = cmNp0.m_fContinuity; + FLOAT fBNp1 = cmNp1.m_fBias; + FLOAT fTNp1 = cmNp1.m_fTension; + FLOAT fCNp1 = cmNp1.m_fContinuity; + + FLOAT fF00 = (1-fTNp0)*(1-fCNp0)*(1-fBNp0) / 2; + FLOAT fF01 = (1-fTNp0)*(1+fCNp0)*(1+fBNp0) / 2; + FLOAT fF10 = (1-fTNp1)*(1+fCNp1)*(1-fBNp1) / 2; + FLOAT fF11 = (1-fTNp1)*(1-fCNp1)*(1+fBNp1) / 2; + + // find tangents for translation + m_vTNp0 = ( (vPNp1-vPNp0) * fF00 + (vPNp0-vPNm1) * fF01) * fD0; + m_vTNp1 = ( (vPNp2-vPNp1) * fF10 + (vPNp1-vPNp0) * fF11) * fD1; + + // find tangents for moving speed + m_fTRotSpeedp0 = ( (fRotSpeedp1-fRotSpeedp0) * fF00 + (fRotSpeedp0-fRotSpeedm1) * fF01) * fD0; + m_fTRotSpeedp1 = ( (fRotSpeedp2-fRotSpeedp1) * fF10 + (fRotSpeedp1-fRotSpeedp0) * fF11) * fD1; + + // find tangents for rotation + FLOATquat3D qTNp0, qTNp1; + qTNp0 = ( Log(qPNp0.Inv()*qPNp1) * fF00 + Log(qPNm1.Inv()*qPNp0) * fF01) * fD0; + qTNp1 = ( Log(qPNp1.Inv()*qPNp2) * fF10 + Log(qPNp0.Inv()*qPNp1) * fF11) * fD1; + + // find squad parameters + m_qANp0 = qPNp0*Exp( (qTNp0 - Log(qPNp0.Inv()*qPNp1))/2 ); + m_qANp1 = qPNp1*Exp( (Log(qPNp0.Inv()*qPNp1) - qTNp1)/2 ); + + // check for stop moving + if( cmNp0.m_bStopMoving && m_fRotSpeed==0.0f) { + m_bStopMoving = TRUE; + } + } + + // calculate the parameter value and hermit basis + FLOAT fT = (tmCurrent - m_tmAtMarker) / m_tmDelta; + FLOAT fH0 = 2*fT*fT*fT - 3*fT*fT + 1; + FLOAT fH1 = -2*fT*fT*fT + 3*fT*fT; + FLOAT fH2 = fT*fT*fT - 2*fT*fT + fT; + FLOAT fH3 = fT*fT*fT - fT*fT; + + // interpolate position, rotation and fov + FLOAT3D vPos = m_vPNp0*fH0 + m_vPNp1*fH1 + m_vTNp0*fH2 + m_vTNp1*fH3; + FLOAT fRotSpeed = m_fRotSpeedp0*fH0 + m_fRotSpeedp1*fH1 + m_fTRotSpeedp0*fH2 + m_fTRotSpeedp1*fH3; + FLOATquat3D qRot = Squad(fT, m_qPNp0, m_qPNp1, m_qANp0, m_qANp1); + FLOATmatrix3D mRotLocal; + MakeRotationMatrixFast(mRotLocal, ANGLE3D(m_fRot,0,0)); + FLOATmatrix3D mRot; + qRot.ToMatrix(mRot); + mRot = mRotLocal*mRot; + + // just cache near polygons for various engine needs + en_vNextPosition = vPos; + en_mNextRotation = mRot; + CacheNearPolygons(); + + // set new placement + CPlacement3D plNew; + plNew.pl_PositionVector = vPos; + DecomposeRotationMatrixNoSnap(plNew.pl_OrientationAngle, mRot); + SetPlacement_internal(plNew, mRot, TRUE); + // if lerping is disabled + if (!bLerping) { + // make last placement same as this one + en_plLastPlacement = en_plPlacement; + } + // set new speed + m_fLastRotSpeed = m_fRotSpeed; + m_fRotSpeed = fRotSpeed; + m_fRot += m_fRotSpeed; + } + + + void PostMoving() + { + if (!m_bMoving) { + return; + } + + // remember new position for particles + if (en_plpLastPositions!=NULL) { + en_plpLastPositions->AddPosition(en_vNextPosition); + } + + // + if( m_bStopMoving) { + m_bMoving = FALSE; + // mark for removing from list of movers + en_ulFlags |= ENF_INRENDERING; + m_epssState = PSSS_REACHED_DESTINATION; + // remember old placement for lerping + en_plLastPlacement = en_plPlacement; + } + } + + void SpawnBeamMachineFlares(void) + { + // spawn small beam machine flares + CPlacement3D plSpaceShip = GetPlacement(); + CPlacement3D plFlare1 = CPlacement3D( FLOAT3D( BM_DX, BM_DY+BM_FLARE_DY, 0), ANGLE3D(0,0,0)); + CPlacement3D plFlare2 = CPlacement3D( FLOAT3D( 0, BM_DY+BM_FLARE_DY, -BM_DZ), ANGLE3D(0,0,0)); + CPlacement3D plFlare3 = CPlacement3D( FLOAT3D( -BM_DX, BM_DY+BM_FLARE_DY, 0), ANGLE3D(0,0,0)); + CPlacement3D plFlare4 = CPlacement3D( FLOAT3D( 0, BM_DY+BM_FLARE_DY, BM_DZ), ANGLE3D(0,0,0)); + + plFlare1.RelativeToAbsolute(plSpaceShip); + plFlare2.RelativeToAbsolute(plSpaceShip); + plFlare3.RelativeToAbsolute(plSpaceShip); + plFlare4.RelativeToAbsolute(plSpaceShip); + + CEntity *penFlare1 = CreateEntity( plFlare1, CLASS_EFFECTOR); + CEntity *penFlare2 = CreateEntity( plFlare2, CLASS_EFFECTOR); + CEntity *penFlare3 = CreateEntity( plFlare3, CLASS_EFFECTOR); + CEntity *penFlare4 = CreateEntity( plFlare4, CLASS_EFFECTOR); + + ESpawnEffector eSpawnFlare; + eSpawnFlare.tmLifeTime = SMALL_FLARES_LIFE_TIME; + eSpawnFlare.tmLifeTime = 10.5f; + eSpawnFlare.eetType = ET_SIZING_RING_FLARE; + + penFlare1->Initialize( eSpawnFlare); + penFlare2->Initialize( eSpawnFlare); + penFlare3->Initialize( eSpawnFlare); + penFlare4->Initialize( eSpawnFlare); + } + + void SpawnBeamMachineMainFlare(void) + { + // spawn main flare + CPlacement3D plSpaceShip = GetPlacement(); + CPlacement3D plFlare = CPlacement3D( FLOAT3D(0, BM_MASTER_Y+BM_FLARE_DY, 0), ANGLE3D(0,0,0)); + plFlare.RelativeToAbsolute(GetPlacement()); + CEntity *penFlare = CreateEntity( plFlare, CLASS_EFFECTOR); + ESpawnEffector eSpawnFlare; + eSpawnFlare.tmLifeTime = 20.0f; + eSpawnFlare.fSize = 1.0f; + eSpawnFlare.eetType = ET_SIZING_BIG_BLUE_FLARE; + penFlare->Initialize( eSpawnFlare); + } + + void ShowBeamMachineHitFlare(void) + { + if( m_penHitPlaceFlare!=NULL && IsOfClass(m_penHitPlaceFlare, "ModelHolder2") ) + { + CModelObject *pmo = m_penHitPlaceFlare->GetModelObject(); + if( pmo != NULL) + { + m_penHitPlaceFlare->SwitchToModel(); + } + } + } + + void HideBeamMachineHitFlare(void) + { + m_tmHitFlareTime = -1; + if( m_penHitPlaceFlare!=NULL && IsOfClass(m_penHitPlaceFlare, "ModelHolder2") ) + { + CModelObject *pmo = m_penHitPlaceFlare->GetModelObject(); + if( pmo != NULL) + { + m_penHitPlaceFlare->SwitchToEditorModel(); + pmo->mo_colBlendColor = C_WHITE|CT_OPAQUE; + } + } + } + + void SpawnBeamMachineLightnings(void) + { + // spawn beam lightnings + CPlacement3D plLightning1 = CPlacement3D( FLOAT3D(BM_DX, BM_DY, 0), ANGLE3D(0,0,0)); + CPlacement3D plLightning2 = CPlacement3D( FLOAT3D(0, BM_DY, -BM_DZ), ANGLE3D(0,0,0)); + CPlacement3D plLightning3 = CPlacement3D( FLOAT3D(-BM_DX, BM_DY, 0), ANGLE3D(0,0,0)); + CPlacement3D plLightning4 = CPlacement3D( FLOAT3D(0, BM_DY, BM_DZ), ANGLE3D(0,0,0)); + + CPlacement3D plLightningDest = CPlacement3D( FLOAT3D(0, BM_MASTER_Y, 0), ANGLE3D(0,0,0)); + CPlacement3D plSpaceShip = GetPlacement(); + plLightningDest.RelativeToAbsolute(plSpaceShip); + + plLightning1.RelativeToAbsolute(plSpaceShip); + plLightning2.RelativeToAbsolute(plSpaceShip); + plLightning3.RelativeToAbsolute(plSpaceShip); + plLightning4.RelativeToAbsolute(plSpaceShip); + + CEntity *penLightning1 = CreateEntity( plLightning1, CLASS_EFFECTOR); + CEntity *penLightning2 = CreateEntity( plLightning2, CLASS_EFFECTOR); + CEntity *penLightning3 = CreateEntity( plLightning3, CLASS_EFFECTOR); + CEntity *penLightning4 = CreateEntity( plLightning4, CLASS_EFFECTOR); + + ESpawnEffector eSpawnLightning; + eSpawnLightning.eetType = ET_LIGHTNING; + eSpawnLightning.tmLifeTime = SMALL_LIGHTININGS_LIFE_TIME; + eSpawnLightning.vDestination = plLightningDest.pl_PositionVector; + eSpawnLightning.fSize = 16.0f; + eSpawnLightning.ctCount = 16; + + penLightning1->Initialize( eSpawnLightning); + penLightning2->Initialize( eSpawnLightning); + penLightning3->Initialize( eSpawnLightning); + penLightning4->Initialize( eSpawnLightning); + } + + void SpawnBeamMachineMainLightning(void) + { + // spawn main lightning + FLOAT3D vDestination = GetPlacement().pl_PositionVector + FLOAT3D( 0, BM_MASTER_Y, 0); + CPlacement3D plSource = CPlacement3D( vDestination, ANGLE3D(0,0,0)); + if( m_penBeamHit != NULL) + { + plSource.pl_PositionVector = m_penBeamHit->GetPlacement().pl_PositionVector; + CEntity *penEffector = CreateEntity( plSource, CLASS_EFFECTOR); + ESpawnEffector eSpawnEffector; + eSpawnEffector.eetType = ET_LIGHTNING; + eSpawnEffector.tmLifeTime = BIG_LIGHT_BEAM_LIFE_TIME; + eSpawnEffector.vDestination = vDestination; + eSpawnEffector.fSize = 32.0f; + eSpawnEffector.ctCount = 32; + penEffector->Initialize( eSpawnEffector); + } + } + + void SpawnMovingRing(void) + { + if( m_penBeamHit != NULL) + { + FLOAT3D vStart = GetPlacement().pl_PositionVector + FLOAT3D( 0, BM_MASTER_Y, 0); + CPlacement3D plSource = CPlacement3D( vStart, ANGLE3D(0,0,0)); + FLOAT3D vHitPlace = m_penBeamHit->GetPlacement().pl_PositionVector; + CEntity *penEffector = CreateEntity( plSource, CLASS_EFFECTOR); + ESpawnEffector eSpawnEffector; + eSpawnEffector.eetType = ET_MOVING_RING; + eSpawnEffector.tmLifeTime = BIG_LIGHT_BEAM_LIFE_TIME; + eSpawnEffector.vDestination = vHitPlace+FLOAT3D(0.0f, 0.0f, 0.0f); + eSpawnEffector.fSize = 16.0f; + eSpawnEffector.ctCount = 2; + penEffector->Initialize( eSpawnEffector); + } + } + + void TurnOnLightBeam(void) + { + if( m_penLightBeam!=NULL && IsOfClass(m_penLightBeam, "ModelHolder2") ) + { + CModelObject *pmo = m_penLightBeam->GetModelObject(); + m_penLightBeam->SwitchToModel(); + pmo->mo_colBlendColor = C_WHITE|CT_OPAQUE; + } + } + + void TurnOffLightBeam(void) + { + m_tmBeamTime=-1.0f; + + if( m_penLightBeam!=NULL && IsOfClass(m_penLightBeam, "ModelHolder2") ) + { + m_penLightBeam->SwitchToEditorModel(); + CModelObject *pmo = m_penLightBeam->GetModelObject(); + } + } + + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) + { + FLOAT fBeamRatio = 1.0f; + + // light beam + if( m_penLightBeam!=NULL && IsOfClass(m_penLightBeam, "ModelHolder2") ) + { + CModelObject *pmo = m_penLightBeam->GetModelObject(); + if( pmo != NULL) + { + if( m_tmBeamTime>-1.0f) + { + FLOAT fT = _pTimer->CurrentTick()-m_tmBeamTime; + fBeamRatio = 1.0f-ClampUp(fT/2.0f, 1.0f); + UBYTE ub = UBYTE (255.0f*fBeamRatio); + COLOR col = RGBAToColor(ub,ub,ub,ub); + pmo->mo_colBlendColor = col; + } + } + } + + // hit flare + if( m_penHitPlaceFlare!=NULL && IsOfClass(m_penHitPlaceFlare, "ModelHolder2") ) + { + CModelObject *pmo = m_penHitPlaceFlare->GetModelObject(); + if( pmo != NULL) + { + if( m_tmHitFlareTime>-1.0f) + { + FLOAT fT = _pTimer->CurrentTick()-m_tmHitFlareTime; + FLOAT fRatio = (Sin(fT*2000)*0.5f+0.5f)*(Sin(fT*1333)*0.5f+0.5f); + /*if(fRatio>0.5f) + { + fRatio=0.0f; + } + else + { + fRatio=1.0f; + }*/ + + UBYTE ub = UBYTE((200+55*fRatio)*fBeamRatio); + //ub = 255; + COLOR col = RGBAToColor(ub,ub,ub,ub); + pmo->mo_colBlendColor = col; + } + } + } + return FALSE; + }; + +procedures: + + MPIntro() + { + SwitchToModel(); + m_bImmediateAnimations=TRUE; + autocall OpenDoors() EReturn; + autocall FireLightBeam() EReturn; + m_epssState = PSSS_BEAM_DEACTIVATED; + autowait(m_fWaitAfterKillingBeam); + autocall FireLightBeam() EReturn; + m_bImmediateAnimations=FALSE; + autocall CloseDoors() EReturn; + return EReturn(); + } + + + OpenDoors() + { + // if ship inside not yet added + if( GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_SHIPINSIDE) == NULL) + { + // add it + AddAttachment( SPACESHIP_ATTACHMENT_SHIPINSIDE, MODEL_SHIP_INSIDE, TEXTURE_BODY); + GetModelObject()->StretchModel(PSS_STRETCH); + } + ShowBeamMachine(); + + if( !m_bImmediateAnimations) + { + PlaySound( m_soPlates, SOUND_PLATES, SOF_3D); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR1)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPENING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR2)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPENING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR3)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPENING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR4)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPENING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR5)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPENING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR6)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPENING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR7)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPENING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR8)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPENING, 0); + } + else + { + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR1)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPEN, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR2)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPEN, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR3)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPEN, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR4)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPEN, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR5)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPEN, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR6)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPEN, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR7)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPEN, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR8)->amo_moModelObject.PlayAnim(DOOR_ANIM_OPEN, 0); + } + + // all children lights named pulsating should pulsate + FOREACHINLIST( CEntity, en_lnInParent, en_lhChildren, iten) + { + if( IsOfClass(iten, "Light")) + { + if( iten->GetName() == "Pulsating") + { + CLight *penLight = (CLight *) &*iten; + EChangeAnim eChange; + eChange.iLightAnim=3; + eChange.bLightLoop=TRUE; + penLight->SendEvent(eChange); + } + else if( iten->GetName() == "Motors") + { + CLight *penLight = (CLight *) &*iten; + EChangeAnim eChange; + eChange.iLightAnim=4; + eChange.bLightLoop=TRUE; + penLight->SendEvent(eChange); + } + } + } + + m_epssState = PSSS_KILLING_BEAM_FIREING; + return EReturn(); + } + + CloseDoors() + { + m_epssState=PSSS_DOORS_CLOSED; + // if ship inside attachment added + if( GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_SHIPINSIDE) != NULL) + { + PlaySound( m_soPlates, SOUND_PLATES, SOF_3D); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR1)->amo_moModelObject.PlayAnim(DOOR_ANIM_CLOSING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR2)->amo_moModelObject.PlayAnim(DOOR_ANIM_CLOSING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR3)->amo_moModelObject.PlayAnim(DOOR_ANIM_CLOSING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR4)->amo_moModelObject.PlayAnim(DOOR_ANIM_CLOSING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR5)->amo_moModelObject.PlayAnim(DOOR_ANIM_CLOSING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR6)->amo_moModelObject.PlayAnim(DOOR_ANIM_CLOSING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR7)->amo_moModelObject.PlayAnim(DOOR_ANIM_CLOSING, 0); + GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR8)->amo_moModelObject.PlayAnim(DOOR_ANIM_CLOSING, 0); + + autowait( GetModelObject()->GetAttachmentModel( SPACESHIP_ATTACHMENT_DOOR1)->amo_moModelObject.GetAnimLength(DOOR_ANIM_CLOSING)); + // remove ship inside attachment + RemoveAttachment( SPACESHIP_ATTACHMENT_SHIPINSIDE); + } + + HideBeamMachine(); + InitializePathMoving( (CPyramidSpaceShipMarker*)&*m_penFlyAwayTarget); + return EReturn(); + } + + FireLightBeam() + { + if(m_epssState==PSSS_DOORS_CLOSED) + { + return; + } + + if(m_epssState==PSSS_BEAM_DEACTIVATED) + { + m_bFireingDeactivatedBeam=TRUE; + } + + if( !m_bImmediateAnimations) + { + PlaySound( m_soBeamMachine, SOUND_BEAMMACHINE, SOF_3D); + GetModelObject()->PlayAnim(SPACESHIP_ANIM_OPENING, 0); + autowait( GetModelObject()->GetAnimLength(SPACESHIP_ANIM_OPENING)); + } + else + { + GetModelObject()->PlayAnim(SPACESHIP_ANIM_OPEN, 0); + } + + if( !m_bImmediateAnimations) + { + PlaySound( m_soBeamMachine, SOUND_WARMUP, SOF_3D); + SpawnBeamMachineFlares(); + autowait( SMALL_FLARE_WAIT); + } + else + { + SpawnBeamMachineFlares(); + } + + SpawnBeamMachineLightnings(); + if( !m_bImmediateAnimations) + { + autowait( SMALL_LIGHTNING_WAIT); + } + + SpawnBeamMachineMainFlare(); + if( !m_bImmediateAnimations) + { + autowait( BIG_FLARE_WAIT); + } + + // turn on light beam + TurnOnLightBeam(); + if(!m_bFireingDeactivatedBeam) + { + SpawnBeamMachineMainLightning(); + } + + m_soBeam.Set3DParameters(SND_FALLOFF, SND_HOTSPOT, SND_VOLUME, 1.0f); + PlaySound( m_soBeam, SOUND_BEAM, SOF_3D|SOF_LOOP); + ShowBeamMachineHitFlare(); + m_tmHitFlareTime = _pTimer->CurrentTick(); + + m_iRingCounter = 0; + while(_pTimer->CurrentTick()CurrentTick(); + while( _pTimer->CurrentTick() < m_tmTemp+0.49f) + { + autowait(_pTimer->TickQuantum); + // cast ray for possible damage + if( m_penBeamHit != NULL && !m_bFireingDeactivatedBeam) + { + // cast ray + FLOAT3D vSource = GetPlacement().pl_PositionVector + FLOAT3D( 0, BM_MASTER_Y, 0); + FLOAT3D vDestination = m_penBeamHit->GetPlacement().pl_PositionVector; + CCastRay crRay( this, vSource, vDestination); + crRay.cr_bHitTranslucentPortals = FALSE; + crRay.cr_bPhysical = FALSE; + crRay.cr_ttHitModels = CCastRay::TT_COLLISIONBOX; + crRay.cr_fTestR = 16.0f; + GetWorld()->CastRay(crRay); + + // if entity is hit + if( crRay.cr_penHit != NULL) + { + InflictDirectDamage( crRay.cr_penHit, this, DMT_BULLET, + 10000.0f/GetGameDamageMultiplier()*_pTimer->TickQuantum/0.5f/16.0f, + FLOAT3D(0, 0, 0), (vSource-vDestination).Normalize()); + crRay.cr_penHit->SendEvent( EHitBySpaceShipBeam()); + } + } + } + } + + m_tmBeamTime = _pTimer->CurrentTick(); + while(_pTimer->CurrentTick()TickQuantum); + FLOAT tmNow = _pTimer->CurrentTick(); + FLOAT fRatio = CalculateRatio(tmNow, m_tmBeamTime, m_tmBeamTime+2.0f, 0, 1.0f); + m_soBeam.Set3DParameters(SND_FALLOFF, SND_HOTSPOT, fRatio*SND_VOLUME, 1.0f); + } + + // turn off light beam + TurnOffLightBeam(); + HideBeamMachineHitFlare(); + + // little pause + autowait( 2.0f); + + GetModelObject()->PlayAnim(SPACESHIP_ANIM_CLOSING, 0); + PlaySound( m_soBeamMachine, SOUND_BEAMMACHINE, SOF_3D); + autowait( GetModelObject()->GetAnimLength(SPACESHIP_ANIM_CLOSING)); + + m_tmHitFlareTime = -1.0f; + m_tmBeamTime = -1.0f; + + if(m_bFireingDeactivatedBeam) + { + jump CloseDoors(); + } + return EReturn(); + } + + Main() { + // declare yourself as a model + InitAsEditorModel(); + //InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL|EPF_MOVABLE); + SetCollisionFlags(ECF_MODEL_HOLDER); + + m_bImmediateAnimations=FALSE; + en_fAcceleration = 1e6f; + en_fDeceleration = 1e6f; + + m_soBeam.Set3DParameters(SND_FALLOFF, SND_HOTSPOT, SND_VOLUME, 1.0f); + m_soBeamMachine.Set3DParameters(SND_FALLOFF, SND_HOTSPOT, SND_VOLUME/2.0f, 1.0f); + m_soPlates.Set3DParameters(SND_FALLOFF, SND_HOTSPOT, SND_VOLUME/2.0f, 1.0f); + m_soFlaresFX.Set3DParameters(SND_FALLOFF, SND_HOTSPOT, SND_VOLUME, 1.0f); + + // set appearance + SetModel(MODEL_SPACESHIP); + SetModelMainTexture(TEXTURE_BODY); + AddAttachment(SPACESHIP_ATTACHMENT_BODY, MODEL_BODY, TEXTURE_BODY); + AddAttachment(SPACESHIP_ATTACHMENT_DOOR1, MODEL_DOOR, TEXTURE_DOOR); + AddAttachment(SPACESHIP_ATTACHMENT_DOOR2, MODEL_DOOR, TEXTURE_DOOR); + AddAttachment(SPACESHIP_ATTACHMENT_DOOR3, MODEL_DOOR, TEXTURE_DOOR); + AddAttachment(SPACESHIP_ATTACHMENT_DOOR4, MODEL_DOOR, TEXTURE_DOOR); + AddAttachment(SPACESHIP_ATTACHMENT_DOOR5, MODEL_DOOR, TEXTURE_DOOR); + AddAttachment(SPACESHIP_ATTACHMENT_DOOR6, MODEL_DOOR, TEXTURE_DOOR); + AddAttachment(SPACESHIP_ATTACHMENT_DOOR7, MODEL_DOOR, TEXTURE_DOOR); + AddAttachment(SPACESHIP_ATTACHMENT_DOOR8, MODEL_DOOR, TEXTURE_DOOR); + + GetModelObject()->StretchModel(PSS_STRETCH); + ModelChangeNotify(); + m_bMoving = FALSE; + m_epssState = PSSS_IDLE; + m_bFireingDeactivatedBeam=FALSE; + + autowait( 0.25f); + + // turn off light beam + TurnOffLightBeam(); + // turn off light beam hit flare + HideBeamMachineHitFlare(); + + // start moving + wait() { + on( EActivate): + { + if( !m_bInvisible) + { + SwitchToModel(); + } + InitializePathMoving((CPyramidSpaceShipMarker*)&*m_penTarget); + resume; + } + on( ETrigger): + { + if(m_epssState == PSSS_IDLE) + { + // ignore all triggs + } + else if( m_epssState==PSSS_KILLING_BEAM_FIREING) + { + call FireLightBeam(); + } + else if(m_epssState==PSSS_BEAM_DEACTIVATED) + { + call FireLightBeam(); + } + else if(m_epssState == PSSS_REACHED_DESTINATION) + { + call OpenDoors(); + } + resume; + } + on (EForcePathMarker eForcePathMarker): + { + if(m_epssState != PSSS_IDLE) + { + m_penTarget = eForcePathMarker.penForcedPathMarker; + InitializePathMoving((CPyramidSpaceShipMarker*)&*m_penTarget); + } + resume; + } + on( EEnvironmentStart): + { + call MPIntro(); + resume; + } + on( EEnvironmentStop): + { + m_bMoving = FALSE; + PostMoving(); + resume; + } + on( EDeactivate): + { + m_epssState = PSSS_BEAM_DEACTIVATED; + resume; + } + on( EReturn): + { + resume; + } + } + + Destroy(); + return; + } +}; diff --git a/Sources/EntitiesMP/PyramidSpaceShip.h b/Sources/EntitiesMP/PyramidSpaceShip.h new file mode 100644 index 0000000..958b1c4 --- /dev/null +++ b/Sources/EntitiesMP/PyramidSpaceShip.h @@ -0,0 +1,208 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_PyramidSpaceShip_INCLUDED +#define _EntitiesMP_PyramidSpaceShip_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType PSSState_enum; +enum PSSState { + PSSS_IDLE = 0, + PSSS_MOVING = 1, + PSSS_REACHED_DESTINATION = 2, + PSSS_KILLING_BEAM_FIREING = 3, + PSSS_BEAM_DEACTIVATED = 4, + PSSS_DOORS_CLOSED = 5, +}; +DECL_DLL inline void ClearToDefault(PSSState &e) { e = (PSSState)0; } ; +#define EVENTCODE_EForcePathMarker 0x02610000 +class DECL_DLL EForcePathMarker : public CEntityEvent { +public: +EForcePathMarker(); +CEntityEvent *MakeCopy(void); +CEntityPointer penForcedPathMarker; +}; +DECL_DLL inline void ClearToDefault(EForcePathMarker &e) { e = EForcePathMarker(); } ; +extern "C" DECL_DLL CDLLEntityClass CPyramidSpaceShip_DLLClass; +class CPyramidSpaceShip : public CMovableModelEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + FLOAT m_fMovingSpeed; + CEntityPointer m_penBeamHit; + CEntityPointer m_penLightBeam; + FLOAT m_tmBeamTime; + CEntityPointer m_penHitPlaceFlare; + FLOAT m_tmHitFlareTime; + FLOAT m_iRingCounter; + FLOAT m_fRatio; + CTString m_strDescription; + enum PSSState m_epssState; + FLOAT m_fStretch; + BOOL m_bStopMoving; + CEntityPointer m_penTarget; + CEntityPointer m_penFlyAwayTarget; + CEntityPointer m_penLast; + BOOL m_bMoving; + FLOAT m_fRot; + FLOAT m_fLastRotSpeed; + FLOAT m_fRotSpeed; + BOOL m_bApplyDamageToHitted; + FLOAT m_tmTemp; + FLOAT m_tmAtMarker; + FLOAT m_tmDelta; + FLOAT3D m_vPNp0; + FLOAT3D m_vPNp1; + FLOAT3D m_vTNp0; + FLOAT3D m_vTNp1; + FLOATquat3D m_qPNp0; + FLOATquat3D m_qPNp1; + FLOATquat3D m_qANp0; + FLOATquat3D m_qANp1; + FLOAT m_fRotSpeedp0; + FLOAT m_fRotSpeedp1; + FLOAT m_fTRotSpeedp0; + FLOAT m_fTRotSpeedp1; + CSoundObject m_soPlates; + CSoundObject m_soBeamMachine; + CSoundObject m_soBeam; + CSoundObject m_soFlaresFX; + BOOL m_bFireingDeactivatedBeam; + BOOL m_bImmediateAnimations; + FLOAT m_fWaitAfterKillingBeam; + BOOL m_bInvisible; + +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void Precache(void); + +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +const CTString & GetDescription(void)const; + +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CPlacement3D GetLerpedPlacement(void)const; + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void PreMoving(); + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void HideBeamMachine(void); + +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void ShowBeamMachine(void); + +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void InitializePathMoving(CPyramidSpaceShipMarker * penStartMarker); + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void DoMoving(); + +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void PostMoving(); + +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void SpawnBeamMachineFlares(void); + +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void SpawnBeamMachineMainFlare(void); + +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void ShowBeamMachineHitFlare(void); + +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void HideBeamMachineHitFlare(void); + +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void SpawnBeamMachineLightnings(void); + +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void SpawnBeamMachineMainLightning(void); + +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void SpawnMovingRing(void); + +#line 585 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void TurnOnLightBeam(void); + +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +void TurnOffLightBeam(void); + +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); +#define STATE_CPyramidSpaceShip_MPIntro 0x02610001 + BOOL +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +MPIntro(const CEntityEvent &__eeInput); + BOOL H0x02610002_MPIntro_01(const CEntityEvent &__eeInput); + BOOL H0x02610003_MPIntro_02(const CEntityEvent &__eeInput); + BOOL H0x02610004_MPIntro_03(const CEntityEvent &__eeInput); + BOOL H0x02610005_MPIntro_04(const CEntityEvent &__eeInput); + BOOL H0x02610006_MPIntro_05(const CEntityEvent &__eeInput); + BOOL H0x02610007_MPIntro_06(const CEntityEvent &__eeInput); + BOOL H0x02610008_MPIntro_07(const CEntityEvent &__eeInput); + BOOL H0x02610009_MPIntro_08(const CEntityEvent &__eeInput); + BOOL H0x0261000a_MPIntro_09(const CEntityEvent &__eeInput); + BOOL H0x0261000b_MPIntro_10(const CEntityEvent &__eeInput); +#define STATE_CPyramidSpaceShip_OpenDoors 0x0261000c + BOOL +#line 673 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +OpenDoors(const CEntityEvent &__eeInput); +#define STATE_CPyramidSpaceShip_CloseDoors 0x0261000d + BOOL +#line 736 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CloseDoors(const CEntityEvent &__eeInput); + BOOL H0x0261000e_CloseDoors_01(const CEntityEvent &__eeInput); + BOOL H0x0261000f_CloseDoors_02(const CEntityEvent &__eeInput); + BOOL H0x02610010_CloseDoors_03(const CEntityEvent &__eeInput); +#define STATE_CPyramidSpaceShip_FireLightBeam 0x02610011 + BOOL +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FireLightBeam(const CEntityEvent &__eeInput); + BOOL H0x02610012_FireLightBeam_01(const CEntityEvent &__eeInput); + BOOL H0x02610013_FireLightBeam_02(const CEntityEvent &__eeInput); + BOOL H0x02610014_FireLightBeam_03(const CEntityEvent &__eeInput); + BOOL H0x02610015_FireLightBeam_04(const CEntityEvent &__eeInput); + BOOL H0x02610016_FireLightBeam_05(const CEntityEvent &__eeInput); + BOOL H0x02610017_FireLightBeam_06(const CEntityEvent &__eeInput); + BOOL H0x02610018_FireLightBeam_07(const CEntityEvent &__eeInput); + BOOL H0x02610019_FireLightBeam_08(const CEntityEvent &__eeInput); + BOOL H0x0261001a_FireLightBeam_09(const CEntityEvent &__eeInput); + BOOL H0x0261001b_FireLightBeam_10(const CEntityEvent &__eeInput); + BOOL H0x0261001c_FireLightBeam_11(const CEntityEvent &__eeInput); + BOOL H0x0261001d_FireLightBeam_12(const CEntityEvent &__eeInput); + BOOL H0x0261001e_FireLightBeam_13(const CEntityEvent &__eeInput); + BOOL H0x0261001f_FireLightBeam_14(const CEntityEvent &__eeInput); + BOOL H0x02610020_FireLightBeam_15(const CEntityEvent &__eeInput); + BOOL H0x02610021_FireLightBeam_16(const CEntityEvent &__eeInput); + BOOL H0x02610022_FireLightBeam_17(const CEntityEvent &__eeInput); + BOOL H0x02610023_FireLightBeam_18(const CEntityEvent &__eeInput); + BOOL H0x02610024_FireLightBeam_19(const CEntityEvent &__eeInput); + BOOL H0x02610025_FireLightBeam_20(const CEntityEvent &__eeInput); + BOOL H0x02610026_FireLightBeam_21(const CEntityEvent &__eeInput); + BOOL H0x02610027_FireLightBeam_22(const CEntityEvent &__eeInput); + BOOL H0x02610028_FireLightBeam_23(const CEntityEvent &__eeInput); + BOOL H0x02610029_FireLightBeam_24(const CEntityEvent &__eeInput); + BOOL H0x0261002a_FireLightBeam_25(const CEntityEvent &__eeInput); + BOOL H0x0261002b_FireLightBeam_26(const CEntityEvent &__eeInput); + BOOL H0x0261002c_FireLightBeam_27(const CEntityEvent &__eeInput); + BOOL H0x0261002d_FireLightBeam_28(const CEntityEvent &__eeInput); +#define STATE_CPyramidSpaceShip_Main 1 + BOOL +#line 890 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x0261002e_Main_01(const CEntityEvent &__eeInput); + BOOL H0x0261002f_Main_02(const CEntityEvent &__eeInput); + BOOL H0x02610030_Main_03(const CEntityEvent &__eeInput); + BOOL H0x02610031_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_PyramidSpaceShip_INCLUDED diff --git a/Sources/EntitiesMP/PyramidSpaceShipMarker.cpp b/Sources/EntitiesMP/PyramidSpaceShipMarker.cpp new file mode 100644 index 0000000..ad0c08d --- /dev/null +++ b/Sources/EntitiesMP/PyramidSpaceShipMarker.cpp @@ -0,0 +1,131 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" + +#include "StdH.h" +#include "EntitiesMP/PyramidSpaceShip.h" + +#include +#include +void CPyramidSpaceShipMarker::SetDefaultProperties(void) { + m_fDeltaTime = 5.0f; + m_fBias = 0.0f; + m_fTension = 0.0f; + m_fContinuity = 0.0f; + m_bStopMoving = FALSE ; + m_penTrigger = NULL; + m_fRotSpeed = 0.0f; + m_penSpaceShip = NULL; + CMarker::SetDefaultProperties(); +} + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +BOOL CPyramidSpaceShipMarker::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +{ +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +if(penTarget == NULL ) +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +{ +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +return FALSE ; +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +} +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +if(slPropertyOffset == offsetof (CPyramidSpaceShipMarker , m_penTarget )) +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +{ +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +return (IsDerivedFromClass (penTarget , "Pyramid Space Ship Marker") || +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +IsDerivedFromClass (penTarget , "PyramidSpaceShip")); +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +} +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +return TRUE ; +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +} + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +BOOL CPyramidSpaceShipMarker::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +{ +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +fnmMarkerClass = CTFILENAME ("Classes\\PyramidSpaceShipMarker.ecl"); +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +strTargetProperty = "Target"; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +return TRUE ; +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +} + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +BOOL CPyramidSpaceShipMarker::HandleEvent(const CEntityEvent & ee) +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +{ +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +if(ee . ee_slEvent == EVENTCODE_ETrigger ) +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +{ +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +if(m_penSpaceShip != NULL && m_penTarget != NULL ) +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +{ +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +EForcePathMarker eForcePathMarker ; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +eForcePathMarker . penForcedPathMarker = m_penTarget ; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +m_penSpaceShip -> SendEvent (eForcePathMarker ); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +return TRUE ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +} +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +} +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +return FALSE ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +} +BOOL CPyramidSpaceShipMarker:: +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CPyramidSpaceShipMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CPyramidSpaceShipMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +m_fDeltaTime = ClampDn (m_fDeltaTime , 0.001f); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +m_fBias = Clamp (m_fBias , - 1.0f , + 1.0f); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +m_fTension = Clamp (m_fTension , - 1.0f , + 1.0f); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +m_fContinuity = Clamp (m_fContinuity , - 1.0f , + 1.0f); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +InitAsEditorModel (); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +SetModel (MODEL_MARKER ); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +GetModelObject () -> StretchModel (FLOAT3D (4 , 4 , 4)); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +ModelChangeNotify (); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +if(m_penTarget != NULL && ! IsOfClass (m_penTarget , "Pyramid Space Ship Marker")){ +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +WarningMessage ("Entity '%s' is not of Pyramid Space Ship Marker class!" , m_penTarget ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +m_penTarget = NULL ; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +} +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/PyramidSpaceShipMarker.es b/Sources/EntitiesMP/PyramidSpaceShipMarker.es new file mode 100644 index 0000000..032abb3 --- /dev/null +++ b/Sources/EntitiesMP/PyramidSpaceShipMarker.es @@ -0,0 +1,102 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +610 +%{ +#include "StdH.h" +#include "EntitiesMP/PyramidSpaceShip.h" +%} + +uses "EntitiesMP/Marker"; + +class CPyramidSpaceShipMarker: CMarker +{ +name "Pyramid Space Ship Marker"; +thumbnail "Thumbnails\\PyramidSpaceShipMarker.tbn"; + +properties: + + 1 FLOAT m_fDeltaTime "Delta time" 'D' = 5.0f, + 2 FLOAT m_fBias "Bias" 'B' = 0.0f, + 3 FLOAT m_fTension "Tension" 'E' = 0.0f, + 4 FLOAT m_fContinuity "Continuity" 'C' = 0.0f, + 5 BOOL m_bStopMoving "Stop moving" 'O' = FALSE, + 6 CEntityPointer m_penTrigger "Trigger" 'G', // PyramidSpaceShip triggers when at this marker + 7 FLOAT m_fRotSpeed "Rotation speed" 'R' = 0.0f, // current speed of rotation + 8 CEntityPointer m_penSpaceShip "Space ship" 'S', // pointer to PyramidSpaceShip, for forcing next path marker + +components: + + 1 model MODEL_MARKER "Models\\Editor\\Axis.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Vector.tex" + + +functions: + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if(penTarget==NULL) + { + return FALSE; + } + if(slPropertyOffset == offsetof(CPyramidSpaceShipMarker, m_penTarget)) + { + return( IsDerivedFromClass(penTarget, "Pyramid Space Ship Marker") || + IsDerivedFromClass(penTarget, "PyramidSpaceShip") ); + } + return TRUE; + } + + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker( CTFileName &fnmMarkerClass, CTString &strTargetProperty) const + { + fnmMarkerClass = CTFILENAME("Classes\\PyramidSpaceShipMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + if (ee.ee_slEvent==EVENTCODE_ETrigger) + { + if(m_penSpaceShip!=NULL && m_penTarget!=NULL) + { + EForcePathMarker eForcePathMarker; + eForcePathMarker.penForcedPathMarker = m_penTarget; + m_penSpaceShip->SendEvent(eForcePathMarker); + return TRUE; + } + } + return FALSE; + } + +procedures: + + Main() + { + // clamp parameters + m_fDeltaTime = ClampDn( m_fDeltaTime, 0.001f); + m_fBias = Clamp( m_fBias, -1.0f, +1.0f); + m_fTension = Clamp( m_fTension, -1.0f, +1.0f); + m_fContinuity = Clamp( m_fContinuity, -1.0f, +1.0f); + + // init model + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + GetModelObject()->StretchModel(FLOAT3D(4,4,4)); + ModelChangeNotify(); + + if( m_penTarget!=NULL && !IsOfClass( m_penTarget, "Pyramid Space Ship Marker")) { + WarningMessage( "Entity '%s' is not of Pyramid Space Ship Marker class!", m_penTarget); + m_penTarget = NULL; + } + + return; + } + +}; + diff --git a/Sources/EntitiesMP/PyramidSpaceShipMarker.h b/Sources/EntitiesMP/PyramidSpaceShipMarker.h new file mode 100644 index 0000000..646409b --- /dev/null +++ b/Sources/EntitiesMP/PyramidSpaceShipMarker.h @@ -0,0 +1,34 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_PyramidSpaceShipMarker_INCLUDED +#define _EntitiesMP_PyramidSpaceShipMarker_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CPyramidSpaceShipMarker_DLLClass; +class CPyramidSpaceShipMarker : public CMarker { +public: + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fDeltaTime; + FLOAT m_fBias; + FLOAT m_fTension; + FLOAT m_fContinuity; + BOOL m_bStopMoving; + CEntityPointer m_penTrigger; + FLOAT m_fRotSpeed; + CEntityPointer m_penSpaceShip; + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CPyramidSpaceShipMarker_Main 1 + BOOL +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_PyramidSpaceShipMarker_INCLUDED diff --git a/Sources/EntitiesMP/PyramidSpaceShipMarker_tables.h b/Sources/EntitiesMP/PyramidSpaceShipMarker_tables.h new file mode 100644 index 0000000..a2bf51a --- /dev/null +++ b/Sources/EntitiesMP/PyramidSpaceShipMarker_tables.h @@ -0,0 +1,43 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CPyramidSpaceShipMarker + +CEntityProperty CPyramidSpaceShipMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000262<<8)+1, offsetof(CPyramidSpaceShipMarker, m_fDeltaTime), "Delta time", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000262<<8)+2, offsetof(CPyramidSpaceShipMarker, m_fBias), "Bias", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000262<<8)+3, offsetof(CPyramidSpaceShipMarker, m_fTension), "Tension", 'E', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000262<<8)+4, offsetof(CPyramidSpaceShipMarker, m_fContinuity), "Continuity", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000262<<8)+5, offsetof(CPyramidSpaceShipMarker, m_bStopMoving), "Stop moving", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000262<<8)+6, offsetof(CPyramidSpaceShipMarker, m_penTrigger), "Trigger", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000262<<8)+7, offsetof(CPyramidSpaceShipMarker, m_fRotSpeed), "Rotation speed", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000262<<8)+8, offsetof(CPyramidSpaceShipMarker, m_penSpaceShip), "Space ship", 'S', 0x7F0000FFUL, 0), +}; +#define CPyramidSpaceShipMarker_propertiesct ARRAYCOUNT(CPyramidSpaceShipMarker_properties) + +CEntityComponent CPyramidSpaceShipMarker_components[] = { +#define MODEL_MARKER ((0x00000262<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Axis.mdl"), +#define TEXTURE_MARKER ((0x00000262<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Vector.tex"), +}; +#define CPyramidSpaceShipMarker_componentsct ARRAYCOUNT(CPyramidSpaceShipMarker_components) + +CEventHandlerEntry CPyramidSpaceShipMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CPyramidSpaceShipMarker:: +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShipMarker.es" +Main),DEBUGSTRING("CPyramidSpaceShipMarker::Main")}, +}; +#define CPyramidSpaceShipMarker_handlersct ARRAYCOUNT(CPyramidSpaceShipMarker_handlers) + +CEntity *CPyramidSpaceShipMarker_New(void) { return new CPyramidSpaceShipMarker; }; +void CPyramidSpaceShipMarker_OnInitClass(void) {}; +void CPyramidSpaceShipMarker_OnEndClass(void) {}; +void CPyramidSpaceShipMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPyramidSpaceShipMarker_OnWorldEnd(CWorld *pwo) {}; +void CPyramidSpaceShipMarker_OnWorldInit(CWorld *pwo) {}; +void CPyramidSpaceShipMarker_OnWorldTick(CWorld *pwo) {}; +void CPyramidSpaceShipMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPyramidSpaceShipMarker, CMarker, "Pyramid Space Ship Marker", "Thumbnails\\PyramidSpaceShipMarker.tbn", 0x00000262); +DECLARE_CTFILENAME(_fnmCPyramidSpaceShipMarker_tbn, "Thumbnails\\PyramidSpaceShipMarker.tbn"); diff --git a/Sources/EntitiesMP/PyramidSpaceShip_tables.h b/Sources/EntitiesMP/PyramidSpaceShip_tables.h new file mode 100644 index 0000000..706b272 --- /dev/null +++ b/Sources/EntitiesMP/PyramidSpaceShip_tables.h @@ -0,0 +1,171 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(PSSState) + EP_ENUMVALUE(PSSS_IDLE, "Idle"), + EP_ENUMVALUE(PSSS_MOVING, "Moving"), + EP_ENUMVALUE(PSSS_REACHED_DESTINATION, "Reached destination"), + EP_ENUMVALUE(PSSS_KILLING_BEAM_FIREING, "Killing beam fireing"), + EP_ENUMVALUE(PSSS_BEAM_DEACTIVATED, "Killing beam deactivated"), + EP_ENUMVALUE(PSSS_DOORS_CLOSED, "Doors closed"), +EP_ENUMEND(PSSState); + +#define ENTITYCLASS CPyramidSpaceShip + +CEntityProperty CPyramidSpaceShip_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000261<<8)+1, offsetof(CPyramidSpaceShip, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+3, offsetof(CPyramidSpaceShip, m_fMovingSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000261<<8)+5, offsetof(CPyramidSpaceShip, m_penBeamHit), "Beam hit target marker", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000261<<8)+6, offsetof(CPyramidSpaceShip, m_penLightBeam), "Beam model holder", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+7, offsetof(CPyramidSpaceShip, m_tmBeamTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000261<<8)+8, offsetof(CPyramidSpaceShip, m_penHitPlaceFlare), "Hit place flare", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+9, offsetof(CPyramidSpaceShip, m_tmHitFlareTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+10, offsetof(CPyramidSpaceShip, m_iRingCounter), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+11, offsetof(CPyramidSpaceShip, m_fRatio), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000261<<8)+12, offsetof(CPyramidSpaceShip, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &PSSState_enum, (0x00000261<<8)+13, offsetof(CPyramidSpaceShip, m_epssState), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+14, offsetof(CPyramidSpaceShip, m_fStretch), "Stretch", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000261<<8)+20, offsetof(CPyramidSpaceShip, m_bStopMoving), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000261<<8)+21, offsetof(CPyramidSpaceShip, m_penTarget), "Target", 'T', C_lBLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000261<<8)+29, offsetof(CPyramidSpaceShip, m_penFlyAwayTarget), "Fly away path marker", 0, C_lBLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000261<<8)+22, offsetof(CPyramidSpaceShip, m_penLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000261<<8)+23, offsetof(CPyramidSpaceShip, m_bMoving), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+24, offsetof(CPyramidSpaceShip, m_fRot), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+25, offsetof(CPyramidSpaceShip, m_fLastRotSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+26, offsetof(CPyramidSpaceShip, m_fRotSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000261<<8)+27, offsetof(CPyramidSpaceShip, m_bApplyDamageToHitted), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+28, offsetof(CPyramidSpaceShip, m_tmTemp), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+30, offsetof(CPyramidSpaceShip, m_tmAtMarker), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+31, offsetof(CPyramidSpaceShip, m_tmDelta), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000261<<8)+32, offsetof(CPyramidSpaceShip, m_vPNp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000261<<8)+33, offsetof(CPyramidSpaceShip, m_vPNp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000261<<8)+34, offsetof(CPyramidSpaceShip, m_vTNp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x00000261<<8)+35, offsetof(CPyramidSpaceShip, m_vTNp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATQUAT3D, NULL, (0x00000261<<8)+36, offsetof(CPyramidSpaceShip, m_qPNp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATQUAT3D, NULL, (0x00000261<<8)+37, offsetof(CPyramidSpaceShip, m_qPNp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATQUAT3D, NULL, (0x00000261<<8)+38, offsetof(CPyramidSpaceShip, m_qANp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATQUAT3D, NULL, (0x00000261<<8)+39, offsetof(CPyramidSpaceShip, m_qANp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+40, offsetof(CPyramidSpaceShip, m_fRotSpeedp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+41, offsetof(CPyramidSpaceShip, m_fRotSpeedp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+42, offsetof(CPyramidSpaceShip, m_fTRotSpeedp0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+43, offsetof(CPyramidSpaceShip, m_fTRotSpeedp1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000261<<8)+50, offsetof(CPyramidSpaceShip, m_soPlates), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000261<<8)+51, offsetof(CPyramidSpaceShip, m_soBeamMachine), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000261<<8)+52, offsetof(CPyramidSpaceShip, m_soBeam), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000261<<8)+53, offsetof(CPyramidSpaceShip, m_soFlaresFX), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000261<<8)+54, offsetof(CPyramidSpaceShip, m_bFireingDeactivatedBeam), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000261<<8)+55, offsetof(CPyramidSpaceShip, m_bImmediateAnimations), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000261<<8)+56, offsetof(CPyramidSpaceShip, m_fWaitAfterKillingBeam), "Wait after auto killing beam", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000261<<8)+60, offsetof(CPyramidSpaceShip, m_bInvisible), "Invisible", 'I', 0x7F0000FFUL, 0), +}; +#define CPyramidSpaceShip_propertiesct ARRAYCOUNT(CPyramidSpaceShip_properties) + +CEntityComponent CPyramidSpaceShip_components[] = { +#define MODEL_SPACESHIP ((0x00000261<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_SPACESHIP, "EFNM" "Models\\CutSequences\\SpaceShip\\SpaceShip.mdl"), +#define MODEL_BODY ((0x00000261<<8)+2) + CEntityComponent(ECT_MODEL, MODEL_BODY, "EFNM" "Models\\CutSequences\\SpaceShip\\Body.mdl"), +#define TEXTURE_BODY ((0x00000261<<8)+3) + CEntityComponent(ECT_TEXTURE, TEXTURE_BODY, "EFNM" "Models\\CutSequences\\SpaceShip\\Body.tex"), +#define MODEL_DOOR ((0x00000261<<8)+4) + CEntityComponent(ECT_MODEL, MODEL_DOOR, "EFNM" "Models\\CutSequences\\SpaceShip\\Door.mdl"), +#define TEXTURE_DOOR ((0x00000261<<8)+5) + CEntityComponent(ECT_TEXTURE, TEXTURE_DOOR, "EFNM" "Models\\CutSequences\\SpaceShip\\Door.tex"), +#define MODEL_BEAMMACHINE ((0x00000261<<8)+6) + CEntityComponent(ECT_MODEL, MODEL_BEAMMACHINE, "EFNM" "Models\\CutSequences\\SpaceShip\\BeamMachine.mdl"), +#define TEXTURE_BEAMMACHINE ((0x00000261<<8)+7) + CEntityComponent(ECT_TEXTURE, TEXTURE_BEAMMACHINE, "EFNM" "Models\\CutSequences\\SpaceShip\\BeamMachine.tex"), +#define MODEL_BEAMRIM ((0x00000261<<8)+8) + CEntityComponent(ECT_MODEL, MODEL_BEAMRIM, "EFNM" "Models\\CutSequences\\SpaceShip\\BeamMachineRim.mdl"), +#define TEXTURE_BEAMRIM ((0x00000261<<8)+9) + CEntityComponent(ECT_TEXTURE, TEXTURE_BEAMRIM, "EFNM" "Models\\CutSequences\\SpaceShip\\BeamMachineRim.tex"), +#define CLASS_EFFECTOR ((0x00000261<<8)+10) + CEntityComponent(ECT_CLASS, CLASS_EFFECTOR, "EFNM" "Classes\\Effector.ecl"), +#define MODEL_SHIP_INSIDE ((0x00000261<<8)+11) + CEntityComponent(ECT_MODEL, MODEL_SHIP_INSIDE, "EFNM" "Models\\CutSequences\\SpaceShip\\Fillin.mdl"), +#define SOUND_PLATES ((0x00000261<<8)+20) + CEntityComponent(ECT_SOUND, SOUND_PLATES, "EFNM" "Sounds\\CutSequences\\SpaceShip\\SSPlates.wav"), +#define SOUND_BEAMMACHINE ((0x00000261<<8)+21) + CEntityComponent(ECT_SOUND, SOUND_BEAMMACHINE, "EFNM" "Sounds\\CutSequences\\SpaceShip\\SSProbe.wav"), +#define SOUND_BEAM ((0x00000261<<8)+22) + CEntityComponent(ECT_SOUND, SOUND_BEAM, "EFNM" "Sounds\\CutSequences\\SpaceShip\\LaserBeam.wav"), +#define SOUND_WARMUP ((0x00000261<<8)+23) + CEntityComponent(ECT_SOUND, SOUND_WARMUP, "EFNM" "Sounds\\CutSequences\\SpaceShip\\Warmup.wav"), +}; +#define CPyramidSpaceShip_componentsct ARRAYCOUNT(CPyramidSpaceShip_components) + +CEventHandlerEntry CPyramidSpaceShip_handlers[] = { + {0x02610001, -1, CEntity::pEventHandler(&CPyramidSpaceShip:: +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +MPIntro),DEBUGSTRING("CPyramidSpaceShip::MPIntro")}, + {0x02610002, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610002_MPIntro_01), DEBUGSTRING("CPyramidSpaceShip::H0x02610002_MPIntro_01")}, + {0x02610003, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610003_MPIntro_02), DEBUGSTRING("CPyramidSpaceShip::H0x02610003_MPIntro_02")}, + {0x02610004, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610004_MPIntro_03), DEBUGSTRING("CPyramidSpaceShip::H0x02610004_MPIntro_03")}, + {0x02610005, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610005_MPIntro_04), DEBUGSTRING("CPyramidSpaceShip::H0x02610005_MPIntro_04")}, + {0x02610006, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610006_MPIntro_05), DEBUGSTRING("CPyramidSpaceShip::H0x02610006_MPIntro_05")}, + {0x02610007, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610007_MPIntro_06), DEBUGSTRING("CPyramidSpaceShip::H0x02610007_MPIntro_06")}, + {0x02610008, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610008_MPIntro_07), DEBUGSTRING("CPyramidSpaceShip::H0x02610008_MPIntro_07")}, + {0x02610009, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610009_MPIntro_08), DEBUGSTRING("CPyramidSpaceShip::H0x02610009_MPIntro_08")}, + {0x0261000a, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261000a_MPIntro_09), DEBUGSTRING("CPyramidSpaceShip::H0x0261000a_MPIntro_09")}, + {0x0261000b, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261000b_MPIntro_10), DEBUGSTRING("CPyramidSpaceShip::H0x0261000b_MPIntro_10")}, + {0x0261000c, -1, CEntity::pEventHandler(&CPyramidSpaceShip:: +#line 673 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +OpenDoors),DEBUGSTRING("CPyramidSpaceShip::OpenDoors")}, + {0x0261000d, -1, CEntity::pEventHandler(&CPyramidSpaceShip:: +#line 736 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +CloseDoors),DEBUGSTRING("CPyramidSpaceShip::CloseDoors")}, + {0x0261000e, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261000e_CloseDoors_01), DEBUGSTRING("CPyramidSpaceShip::H0x0261000e_CloseDoors_01")}, + {0x0261000f, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261000f_CloseDoors_02), DEBUGSTRING("CPyramidSpaceShip::H0x0261000f_CloseDoors_02")}, + {0x02610010, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610010_CloseDoors_03), DEBUGSTRING("CPyramidSpaceShip::H0x02610010_CloseDoors_03")}, + {0x02610011, -1, CEntity::pEventHandler(&CPyramidSpaceShip:: +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +FireLightBeam),DEBUGSTRING("CPyramidSpaceShip::FireLightBeam")}, + {0x02610012, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610012_FireLightBeam_01), DEBUGSTRING("CPyramidSpaceShip::H0x02610012_FireLightBeam_01")}, + {0x02610013, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610013_FireLightBeam_02), DEBUGSTRING("CPyramidSpaceShip::H0x02610013_FireLightBeam_02")}, + {0x02610014, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610014_FireLightBeam_03), DEBUGSTRING("CPyramidSpaceShip::H0x02610014_FireLightBeam_03")}, + {0x02610015, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610015_FireLightBeam_04), DEBUGSTRING("CPyramidSpaceShip::H0x02610015_FireLightBeam_04")}, + {0x02610016, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610016_FireLightBeam_05), DEBUGSTRING("CPyramidSpaceShip::H0x02610016_FireLightBeam_05")}, + {0x02610017, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610017_FireLightBeam_06), DEBUGSTRING("CPyramidSpaceShip::H0x02610017_FireLightBeam_06")}, + {0x02610018, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610018_FireLightBeam_07), DEBUGSTRING("CPyramidSpaceShip::H0x02610018_FireLightBeam_07")}, + {0x02610019, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610019_FireLightBeam_08), DEBUGSTRING("CPyramidSpaceShip::H0x02610019_FireLightBeam_08")}, + {0x0261001a, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261001a_FireLightBeam_09), DEBUGSTRING("CPyramidSpaceShip::H0x0261001a_FireLightBeam_09")}, + {0x0261001b, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261001b_FireLightBeam_10), DEBUGSTRING("CPyramidSpaceShip::H0x0261001b_FireLightBeam_10")}, + {0x0261001c, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261001c_FireLightBeam_11), DEBUGSTRING("CPyramidSpaceShip::H0x0261001c_FireLightBeam_11")}, + {0x0261001d, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261001d_FireLightBeam_12), DEBUGSTRING("CPyramidSpaceShip::H0x0261001d_FireLightBeam_12")}, + {0x0261001e, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261001e_FireLightBeam_13), DEBUGSTRING("CPyramidSpaceShip::H0x0261001e_FireLightBeam_13")}, + {0x0261001f, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261001f_FireLightBeam_14), DEBUGSTRING("CPyramidSpaceShip::H0x0261001f_FireLightBeam_14")}, + {0x02610020, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610020_FireLightBeam_15), DEBUGSTRING("CPyramidSpaceShip::H0x02610020_FireLightBeam_15")}, + {0x02610021, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610021_FireLightBeam_16), DEBUGSTRING("CPyramidSpaceShip::H0x02610021_FireLightBeam_16")}, + {0x02610022, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610022_FireLightBeam_17), DEBUGSTRING("CPyramidSpaceShip::H0x02610022_FireLightBeam_17")}, + {0x02610023, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610023_FireLightBeam_18), DEBUGSTRING("CPyramidSpaceShip::H0x02610023_FireLightBeam_18")}, + {0x02610024, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610024_FireLightBeam_19), DEBUGSTRING("CPyramidSpaceShip::H0x02610024_FireLightBeam_19")}, + {0x02610025, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610025_FireLightBeam_20), DEBUGSTRING("CPyramidSpaceShip::H0x02610025_FireLightBeam_20")}, + {0x02610026, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610026_FireLightBeam_21), DEBUGSTRING("CPyramidSpaceShip::H0x02610026_FireLightBeam_21")}, + {0x02610027, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610027_FireLightBeam_22), DEBUGSTRING("CPyramidSpaceShip::H0x02610027_FireLightBeam_22")}, + {0x02610028, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610028_FireLightBeam_23), DEBUGSTRING("CPyramidSpaceShip::H0x02610028_FireLightBeam_23")}, + {0x02610029, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610029_FireLightBeam_24), DEBUGSTRING("CPyramidSpaceShip::H0x02610029_FireLightBeam_24")}, + {0x0261002a, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261002a_FireLightBeam_25), DEBUGSTRING("CPyramidSpaceShip::H0x0261002a_FireLightBeam_25")}, + {0x0261002b, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261002b_FireLightBeam_26), DEBUGSTRING("CPyramidSpaceShip::H0x0261002b_FireLightBeam_26")}, + {0x0261002c, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261002c_FireLightBeam_27), DEBUGSTRING("CPyramidSpaceShip::H0x0261002c_FireLightBeam_27")}, + {0x0261002d, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261002d_FireLightBeam_28), DEBUGSTRING("CPyramidSpaceShip::H0x0261002d_FireLightBeam_28")}, + {1, -1, CEntity::pEventHandler(&CPyramidSpaceShip:: +#line 890 "D:/SE1_GPL/Sources/EntitiesMP/PyramidSpaceShip.es" +Main),DEBUGSTRING("CPyramidSpaceShip::Main")}, + {0x0261002e, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261002e_Main_01), DEBUGSTRING("CPyramidSpaceShip::H0x0261002e_Main_01")}, + {0x0261002f, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x0261002f_Main_02), DEBUGSTRING("CPyramidSpaceShip::H0x0261002f_Main_02")}, + {0x02610030, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610030_Main_03), DEBUGSTRING("CPyramidSpaceShip::H0x02610030_Main_03")}, + {0x02610031, -1, CEntity::pEventHandler(&CPyramidSpaceShip::H0x02610031_Main_04), DEBUGSTRING("CPyramidSpaceShip::H0x02610031_Main_04")}, +}; +#define CPyramidSpaceShip_handlersct ARRAYCOUNT(CPyramidSpaceShip_handlers) + +CEntity *CPyramidSpaceShip_New(void) { return new CPyramidSpaceShip; }; +void CPyramidSpaceShip_OnInitClass(void) {}; +void CPyramidSpaceShip_OnEndClass(void) {}; +void CPyramidSpaceShip_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CPyramidSpaceShip_OnWorldEnd(CWorld *pwo) {}; +void CPyramidSpaceShip_OnWorldInit(CWorld *pwo) {}; +void CPyramidSpaceShip_OnWorldTick(CWorld *pwo) {}; +void CPyramidSpaceShip_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CPyramidSpaceShip, CMovableModelEntity, "PyramidSpaceShip", "Thumbnails\\PyramidSpaceShip.tbn", 0x00000261); +DECLARE_CTFILENAME(_fnmCPyramidSpaceShip_tbn, "Thumbnails\\PyramidSpaceShip.tbn"); diff --git a/Sources/EntitiesMP/Reminder.cpp b/Sources/EntitiesMP/Reminder.cpp new file mode 100644 index 0000000..6ec8e48 --- /dev/null +++ b/Sources/EntitiesMP/Reminder.cpp @@ -0,0 +1,74 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *EReminderInit::MakeCopy(void) { CEntityEvent *peeCopy = new EReminderInit(*this); return peeCopy;} +EReminderInit::EReminderInit() : CEntityEvent(EVENTCODE_EReminderInit) {; + ClearToDefault(penOwner); + ClearToDefault(fWaitTime); + ClearToDefault(iValue); +}; +void CReminder::SetDefaultProperties(void) { + m_penOwner = NULL; + m_fWaitTime = 0.0f; + m_iValue = 0; + CRationalEntity::SetDefaultProperties(); +} +BOOL CReminder:: +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CReminder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EReminderInit, "CReminder::Main expects 'EReminderInit' as input!"); const EReminderInit &eri = (const EReminderInit &)__eeInput; +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +ASSERT (eri . penOwner != NULL ); +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +m_penOwner = eri . penOwner ; +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +m_fWaitTime = eri . fWaitTime ; +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +m_iValue = eri . iValue ; +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +InitAsVoid (); +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +if(!(m_fWaitTime > 0.0f)){ Jump(STATE_CURRENT,0x02bf0003, FALSE, EInternal());return TRUE;} +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +SetTimerAfter(m_fWaitTime ); +Jump(STATE_CURRENT, 0x02bf0001, FALSE, EBegin());return TRUE;}BOOL CReminder::H0x02bf0001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bf0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02bf0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CReminder::H0x02bf0002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bf0002 +; +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +EReminder er ; +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +er . iValue = m_iValue ; +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +if(m_penOwner != NULL ){ +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +m_penOwner -> SendEvent (er ); +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +}Jump(STATE_CURRENT,0x02bf0003, FALSE, EInternal());return TRUE;}BOOL CReminder::H0x02bf0003_Main_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bf0003 + +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +Destroy (); +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +Return(STATE_CURRENT,EVoid()); +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Reminder.es b/Sources/EntitiesMP/Reminder.es new file mode 100644 index 0000000..7fe6a50 --- /dev/null +++ b/Sources/EntitiesMP/Reminder.es @@ -0,0 +1,54 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +703 +%{ +#include "StdH.h" +%} + +// input parameter for timer +event EReminderInit { + CEntityPointer penOwner, // who owns it + FLOAT fWaitTime, // wait time + INDEX iValue, // reminder event value +}; + +class export CReminder : CRationalEntity { +name "Reminder"; +thumbnail ""; + +properties: + 1 CEntityPointer m_penOwner, // entity which owns it + 2 FLOAT m_fWaitTime = 0.0f, // wait time + 3 INDEX m_iValue = 0, // reminder event value + +components: +functions: +procedures: + Main(EReminderInit eri) { + // remember the initial parameters + ASSERT(eri.penOwner!=NULL); + m_penOwner = eri.penOwner; + m_fWaitTime = eri.fWaitTime; + m_iValue = eri.iValue; + + // init as nothing + InitAsVoid(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // wait + if (m_fWaitTime > 0.0f) { + autowait(m_fWaitTime); + EReminder er; + er.iValue = m_iValue; + if (m_penOwner!=NULL) { + m_penOwner->SendEvent(er); + } + } + + // cease to exist + Destroy(); + + return; + }; +}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Reminder.h b/Sources/EntitiesMP/Reminder.h new file mode 100644 index 0000000..1331891 --- /dev/null +++ b/Sources/EntitiesMP/Reminder.h @@ -0,0 +1,32 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Reminder_INCLUDED +#define _EntitiesMP_Reminder_INCLUDED 1 +#define EVENTCODE_EReminderInit 0x02bf0000 +class DECL_DLL EReminderInit : public CEntityEvent { +public: +EReminderInit(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOwner; +FLOAT fWaitTime; +INDEX iValue; +}; +DECL_DLL inline void ClearToDefault(EReminderInit &e) { e = EReminderInit(); } ; +extern "C" DECL_DLL CDLLEntityClass CReminder_DLLClass; +class DECL_DLL CReminder : public CRationalEntity { +public: + virtual void SetDefaultProperties(void); + CEntityPointer m_penOwner; + FLOAT m_fWaitTime; + INDEX m_iValue; +#define STATE_CReminder_Main 1 + BOOL +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x02bf0001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x02bf0002_Main_02(const CEntityEvent &__eeInput); + BOOL H0x02bf0003_Main_03(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Reminder_INCLUDED diff --git a/Sources/EntitiesMP/Reminder_tables.h b/Sources/EntitiesMP/Reminder_tables.h new file mode 100644 index 0000000..e263793 --- /dev/null +++ b/Sources/EntitiesMP/Reminder_tables.h @@ -0,0 +1,39 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CReminder + +CEntityProperty CReminder_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000002bf<<8)+1, offsetof(CReminder, m_penOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000002bf<<8)+2, offsetof(CReminder, m_fWaitTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000002bf<<8)+3, offsetof(CReminder, m_iValue), "", 0, 0, 0), +}; +#define CReminder_propertiesct ARRAYCOUNT(CReminder_properties) + +CEntityComponent CReminder_components[] = { + CEntityComponent() +}; +#define CReminder_componentsct 0 + + +CEventHandlerEntry CReminder_handlers[] = { + {1, -1, CEntity::pEventHandler(&CReminder:: +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/Reminder.es" +Main),DEBUGSTRING("CReminder::Main")}, + {0x02bf0001, -1, CEntity::pEventHandler(&CReminder::H0x02bf0001_Main_01), DEBUGSTRING("CReminder::H0x02bf0001_Main_01")}, + {0x02bf0002, -1, CEntity::pEventHandler(&CReminder::H0x02bf0002_Main_02), DEBUGSTRING("CReminder::H0x02bf0002_Main_02")}, + {0x02bf0003, -1, CEntity::pEventHandler(&CReminder::H0x02bf0003_Main_03), DEBUGSTRING("CReminder::H0x02bf0003_Main_03")}, +}; +#define CReminder_handlersct ARRAYCOUNT(CReminder_handlers) + +CEntity *CReminder_New(void) { return new CReminder; }; +void CReminder_OnInitClass(void) {}; +void CReminder_OnEndClass(void) {}; +void CReminder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CReminder_OnWorldEnd(CWorld *pwo) {}; +void CReminder_OnWorldInit(CWorld *pwo) {}; +void CReminder_OnWorldTick(CWorld *pwo) {}; +void CReminder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CReminder, CRationalEntity, "Reminder", "", 0x000002bf); +DECLARE_CTFILENAME(_fnmCReminder_tbn, ""); diff --git a/Sources/EntitiesMP/RollingStone.cpp b/Sources/EntitiesMP/RollingStone.cpp new file mode 100644 index 0000000..ebdae64 --- /dev/null +++ b/Sources/EntitiesMP/RollingStone.cpp @@ -0,0 +1,460 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" + +#include "StdH.h" + +#include +#include +void CRollingStone::SetDefaultProperties(void) { + m_fBounce = 0.5f; + m_fHealth = 400.0f; + m_fDamage = 1000.0f; + m_bFixedDamage = FALSE ; + m_fStretch = 1.0f; + m_fDeceleration = 0.9f; + m_fStartSpeed = 50.0f; + m_vStartDir = ANGLE3D(0 , 0 , 0); + m_penDeathTarget = NULL; + m_soBounce0.SetOwner(this); +m_soBounce0.Stop_internal(); + m_soBounce1.SetOwner(this); +m_soBounce1.Stop_internal(); + m_soBounce2.SetOwner(this); +m_soBounce2.Stop_internal(); + m_soBounce3.SetOwner(this); +m_soBounce3.Stop_internal(); + m_soBounce4.SetOwner(this); +m_soBounce4.Stop_internal(); + m_iNextChannel = 0; + m_soRoll.SetOwner(this); +m_soRoll.Stop_internal(); + m_bRollPlaying = FALSE ; + m_qA = FLOATquat3D(0 , 1 , 0 , 0); + m_qALast = FLOATquat3D(0 , 1 , 0 , 0); + m_fASpeed = 0.0f; + m_vR = FLOAT3D(0 , 0 , 1); + CMovableModelEntity::SetDefaultProperties(); +} + +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void CRollingStone::Precache(void) +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +{ +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +PrecacheClass (CLASS_DEBRIS ); +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +PrecacheModel (MODEL_STONE ); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +PrecacheTexture (TEXTURE_STONE ); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +PrecacheSound (SOUND_BOUNCE ); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +PrecacheSound (SOUND_ROLL ); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void CRollingStone::PostMoving() { +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +CMovableModelEntity :: PostMoving (); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(en_penReference != NULL ){ +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +AdjustSpeeds (en_vReferencePlane ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +}else { +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_qALast = m_qA ; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOATquat3D qRot ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +qRot . FromAxisAngle (m_vR , m_fASpeed * _pTimer -> TickQuantum * PI / 180); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOATmatrix3D mRot ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +qRot . ToMatrix (mRot ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_qA = qRot * m_qA ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(en_ulFlags & ENF_INRENDERING ){ +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_qALast = m_qA ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} + +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void CRollingStone::AdjustMipFactor(FLOAT & fMipFactor) +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +{ +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +fMipFactor = 0; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOATquat3D qA ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +qA = Slerp (_pTimer -> GetLerpFactor () , m_qALast , m_qA ); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOATmatrix3D mA ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +qA . ToMatrix (mA ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +ANGLE3D vA ; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +DecomposeRotationMatrixNoSnap (vA , mA ); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +CAttachmentModelObject * amo = GetModelObject () -> GetAttachmentModel (0); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +amo -> amo_plRelative . pl_OrientationAngle = vA ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} + +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void CRollingStone::AdjustSpeedOnOneAxis(FLOAT & fTraNow,FLOAT & aRotNow,BOOL bRolling) +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +{ +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fR = 4.0f * m_fStretch ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fTraNew = (2 * aRotNow * fR + 5 * fTraNow ) / 7; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT aRotNew = fTraNew / fR ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +fTraNow = fTraNew ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +aRotNow = aRotNew ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void CRollingStone::AdjustSpeeds(const FLOAT3D & vPlane) +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +{ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(en_vCurrentTranslationAbsolute . Length () < 1.0f && m_fASpeed < 1.0f){ +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +en_vCurrentTranslationAbsolute = FLOAT3D (0 , 0 , 0); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_fASpeed = 0.0f; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +RollSound (0.0f); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +return ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT3D vTranslationNormal ; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT3D vTranslationParallel ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +GetParallelAndNormalComponents (en_vCurrentTranslationAbsolute , vPlane , vTranslationNormal , vTranslationParallel ); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +BOOL bRolling = vTranslationNormal . Length () < 0.1f; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(bRolling ){ +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fSpeedTra = vTranslationParallel . Length (); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +RollSound (fSpeedTra ); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +}else { +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +RollSound (0); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT3D vRotFromRot = m_vR ; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT3D vTraFromRot = vPlane * vRotFromRot ; +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +vTraFromRot . Normalize (); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fTraFromRot = 0; +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fRotFromRot = m_fASpeed * PI / 180.0f; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT3D vTraFromTra = vTranslationParallel ; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fTraFromTra = vTraFromTra . Length (); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT3D vRotFromTra = FLOAT3D (1 , 0 , 0); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fRotFromTra = 0; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(fTraFromTra > 0.001f){ +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +vTraFromTra /= fTraFromTra ; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +vRotFromTra = vTraFromTra * vPlane ; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +vRotFromTra . Normalize (); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(Abs (fRotFromRot ) > 0.01f){ +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +AdjustSpeedOnOneAxis (fTraFromRot , fRotFromRot , bRolling ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(Abs (fTraFromTra ) > 0.01f){ +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +AdjustSpeedOnOneAxis (fTraFromTra , fRotFromTra , bRolling ); +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOATquat3D qTra ; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +qTra . FromAxisAngle (vRotFromTra , fRotFromTra ); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOATquat3D qRot ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +qRot . FromAxisAngle (vRotFromRot , fRotFromRot ); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOATquat3D q = qRot * qTra ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT3D vSpeed = vTraFromTra * fTraFromTra + vTraFromRot * fTraFromRot ; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +en_vCurrentTranslationAbsolute = vTranslationNormal + vSpeed ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +q . ToAxisAngle (m_vR , m_fASpeed ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_fASpeed *= 180 / PI ; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} + +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void CRollingStone::BounceSound(FLOAT fSpeed) { +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fHitStrength = fSpeed * fSpeed ; +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fVolume = fHitStrength / 20.0f; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +fVolume = Clamp (fVolume , 0.0f , 2.0f); +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fPitch = Lerp (0.2f , 1.0f , Clamp (fHitStrength / 100 , 0.0f , 1.0f)); +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(fVolume < 0.1f){ +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +return ; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +CSoundObject & so = (& m_soBounce0 ) [ m_iNextChannel ]; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_iNextChannel = (m_iNextChannel + 1) % 5; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +so . Set3DParameters (200.0f * m_fStretch , 100.0f * m_fStretch , fVolume , fPitch ); +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +PlaySound (so , SOUND_BOUNCE , SOF_3D ); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} + +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void CRollingStone::RollSound(FLOAT fSpeed) +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +{ +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fHitStrength = fSpeed * fSpeed * m_fStretch * m_fStretch * m_fStretch ; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fVolume = fHitStrength / 20.0f; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +fVolume = Clamp (fVolume , 0.0f , 1.0f); +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fPitch = Lerp (0.2f , 1.0f , Clamp (fHitStrength / 100 , 0.0f , 1.0f)); +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(fVolume < 0.1f){ +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(m_bRollPlaying ){ +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_soRoll . Stop (); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_bRollPlaying = FALSE ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +return ; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_soRoll . Set3DParameters (200.0f * m_fStretch , 100.0f * m_fStretch , fVolume , fPitch ); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(! m_bRollPlaying ){ +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +PlaySound (m_soRoll , SOUND_ROLL , SOF_3D | SOF_LOOP ); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_bRollPlaying = TRUE ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +BOOL CRollingStone:: +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CRollingStone_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CRollingStone::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +InitAsModel (); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +SetPhysicsFlags (EPF_ONBLOCK_BOUNCE | EPF_PUSHABLE | EPF_MOVABLE | EPF_TRANSLATEDBYGRAVITY ); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +SetCollisionFlags (ECF_MODEL ); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +SetModel (MODEL_ROLLINGSTONE ); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +SetModelMainTexture (TEXTURE_ROLLINGSTONE ); +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +AddAttachmentToModel (this , * GetModelObject () , 0 , MODEL_STONESPHERE , TEXTURE_ROLLINGSTONE , 0 , 0 , TEXTURE_DETAIL ); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fStretch , m_fStretch , m_fStretch )); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +ModelChangeNotify (); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +en_fBounceDampNormal = m_fBounce ; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +en_fBounceDampParallel = m_fBounce ; +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +en_fAcceleration = en_fDeceleration = m_fDeceleration ; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +en_fCollisionSpeedLimit = 45.0f; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +en_fCollisionDamageFactor = 10.0f; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +SetPlacement (CPlacement3D (GetPlacement () . pl_PositionVector , ANGLE3D (0 , 0 , 0))); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_qA = FLOATquat3D (0 , 1 , 0 , 0); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +m_qALast = FLOATquat3D (0 , 1 , 0 , 0); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x025c0000, FALSE, EBegin());return TRUE;}BOOL CRollingStone::H0x025c0000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025c0000 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x025c0001, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CRollingStone::H0x025c0001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025c0001 +; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +SetHealth (m_fHealth ); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +AddToMovers (); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x025c0002, FALSE, EBegin());return TRUE;}BOOL CRollingStone::H0x025c0002_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025c0002 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; + +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT3D v ; +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +AnglesToDirectionVector (m_vStartDir , v ); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +GiveImpulseTranslationAbsolute (v * m_fStartSpeed ); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +return TRUE; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch): +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +{const ETouch&eTouch= (ETouch&)__eeInput; + +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(! m_bFixedDamage ) +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +{ +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fDamageFactor = en_vCurrentTranslationAbsolute . Length () / 10.0f; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fAppliedDamage = fDamageFactor * m_fDamage ; +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +InflictDirectDamage (eTouch . penOther , this , DMT_CANNONBALL , fAppliedDamage , +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +eTouch . penOther -> GetPlacement () . pl_PositionVector , eTouch . plCollision ); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +else +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +{ +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(en_vCurrentTranslationAbsolute . Length () != 0.0f) +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +{ +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +InflictDirectDamage (eTouch . penOther , this , DMT_CANNONBALL , m_fDamage , +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +eTouch . penOther -> GetPlacement () . pl_PositionVector , eTouch . plCollision ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +AdjustSpeeds (eTouch . plCollision ); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(eTouch . penOther -> GetRenderType () & RT_BRUSH ) +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +{ +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +BounceSound (((FLOAT3D &) eTouch . plCollision ) % en_vCurrentTranslationAbsolute ); +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fImpactSpeed = en_vCurrentTranslationAbsolute % (- (FLOAT3D &) eTouch . plCollision ); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +if(fImpactSpeed > 1000) +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +{ +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +ReceiveDamage (eTouch . penOther , DMT_IMPACT , m_fHealth * 2.0f , +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT3D (0 , 0 , 0) , FLOAT3D (0 , 0 , 0)); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +return TRUE; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +SendToTarget (m_penDeathTarget , EET_TRIGGER , eDeath . eLastDamage . penInflictor ); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOATaabbox3D box ; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +GetBoundingBox (box ); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT fEntitySize = box . Size () . MaxNorm (); +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +Debris_Begin (EIBT_ROCK , DPT_NONE , BET_NONE , fEntitySize , FLOAT3D (1.0f , 2.0f , 3.0f) , FLOAT3D (0 , 0 , 0) , 1.0f , 0.0f); +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +for(INDEX iDebris = 0;iDebris < 12;iDebris ++){ +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +Debris_Spawn (this , this , MODEL_STONE , TEXTURE_STONE , 0 , 0 , 0 , IRnd () % 4 , 0.15f , +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +FLOAT3D (FRnd () * 0.8f + 0.1f , FRnd () * 0.8f + 0.1f , FRnd () * 0.8f + 0.1f)); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +} +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +Destroy (); +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +UnsetTimer();Jump(STATE_CURRENT,0x025c0003, FALSE, EInternal());return TRUE; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +}return TRUE;}BOOL CRollingStone::H0x025c0003_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025c0003 + +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +Destroy (); +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +Return(STATE_CURRENT,EVoid()); +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/RollingStone.es b/Sources/EntitiesMP/RollingStone.es new file mode 100644 index 0000000..0d65524 --- /dev/null +++ b/Sources/EntitiesMP/RollingStone.es @@ -0,0 +1,345 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +604 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Debris"; + +class CRollingStone: CMovableModelEntity { +name "RollingStone"; +thumbnail "Thumbnails\\RollingStone.tbn"; +features "IsTargetable"; +properties: + 1 FLOAT m_fBounce "Bounce" 'B' = 0.5f, + 2 FLOAT m_fHealth "Health" 'H' = 400.0f, + 3 FLOAT m_fDamage "Damage" 'D' = 1000.0f, + 4 BOOL m_bFixedDamage "Fixed damage" 'F' = FALSE, + 5 FLOAT m_fStretch "Stretch" 'S' = 1.0f, + 6 FLOAT m_fDeceleration "Deceleration" = 0.9f, + 7 FLOAT m_fStartSpeed "Start Speed" 'Z' = 50.0f, + 8 ANGLE3D m_vStartDir "Start Direction" 'A' = ANGLE3D(0,0,0), + 9 CEntityPointer m_penDeathTarget "Death target" 'T', + + // sound channels for bouncing sound + 20 CSoundObject m_soBounce0, + 21 CSoundObject m_soBounce1, + 22 CSoundObject m_soBounce2, + 23 CSoundObject m_soBounce3, + 24 CSoundObject m_soBounce4, + 30 INDEX m_iNextChannel = 0, // next channel to play sound on + 31 CSoundObject m_soRoll, + 32 BOOL m_bRollPlaying = FALSE, + + // internal vars + 40 FLOATquat3D m_qA = FLOATquat3D(0, 1, 0, 0), + 41 FLOATquat3D m_qALast = FLOATquat3D(0, 1, 0, 0), + 42 FLOAT m_fASpeed = 0.0f, + 43 FLOAT3D m_vR = FLOAT3D(0,0,1), + +components: + 1 model MODEL_ROLLINGSTONE "Models\\Ages\\Egypt\\Traps\\RollingStone\\RollingStone.mdl", + 2 model MODEL_STONESPHERE "Models\\Ages\\Egypt\\Traps\\RollingStone\\Stone.mdl", + 3 texture TEXTURE_ROLLINGSTONE "Models\\Ages\\Egypt\\Traps\\RollingStone\\Stone.tex", + 5 texture TEXTURE_DETAIL "Models\\Ages\\Egypt\\Traps\\RollingStone\\Detail.tex", +// ************** STONE PARTS ************** + 14 model MODEL_STONE "Models\\Effects\\Debris\\Stone\\Stone.mdl", + 15 texture TEXTURE_STONE "Models\\Effects\\Debris\\Stone\\Stone.tex", + 16 class CLASS_DEBRIS "Classes\\Debris.ecl", + 4 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 20 sound SOUND_BOUNCE "Sounds\\Misc\\RollingStone.wav", + 21 sound SOUND_ROLL "Sounds\\Misc\\RollingStoneEnvironment.wav", + +functions: + void Precache(void) + { + PrecacheClass(CLASS_DEBRIS); + PrecacheModel(MODEL_STONE); + PrecacheTexture(TEXTURE_STONE); + PrecacheSound(SOUND_BOUNCE); + PrecacheSound(SOUND_ROLL); + } + void PostMoving() { + CMovableModelEntity::PostMoving(); + + // if touching floor + if (en_penReference!=NULL) { + // adjust rotation and translation speeds + AdjustSpeeds(en_vReferencePlane); + //CPrintF("adjusting\n"); + } else { + //CPrintF("not adjusting\n"); + } +// m_fASpeed *= m_fDeceleration; + + m_qALast = m_qA; + + FLOATquat3D qRot; + qRot.FromAxisAngle(m_vR, m_fASpeed*_pTimer->TickQuantum*PI/180); + FLOATmatrix3D mRot; + qRot.ToMatrix(mRot); + m_qA = qRot*m_qA; + if (en_ulFlags&ENF_INRENDERING) { + m_qALast = m_qA; + } + } + + /* Adjust model mip factor if needed. */ + void AdjustMipFactor(FLOAT &fMipFactor) + { + fMipFactor = 0;// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + FLOATquat3D qA; + qA = Slerp(_pTimer->GetLerpFactor(), m_qALast, m_qA); + + FLOATmatrix3D mA; + qA.ToMatrix(mA); + ANGLE3D vA; + DecomposeRotationMatrixNoSnap(vA, mA); + + CAttachmentModelObject *amo = GetModelObject()->GetAttachmentModel(0); + amo->amo_plRelative.pl_OrientationAngle = vA; + } + + void AdjustSpeedOnOneAxis(FLOAT &fTraNow, FLOAT &aRotNow, BOOL bRolling) + { + // calculate new rotation and translation to make them synchronized + // NOTE: formulae used: + // momentum of the ball : I = 2*m*r^2/5 + // velocity and rotation syncronized: w*r = v + // sum of impulses is constant: w1/r*I+v1*m = w2/r*I+v2*m + // this yields: v2 = (2*r*w1+5*v1)/7 + FLOAT fR = 4.0f*m_fStretch; // size of original sphere model (4m) times stretch + + FLOAT fTraNew = (2*aRotNow*fR+5*fTraNow)/7; + FLOAT aRotNew = fTraNew/fR; + + fTraNow = fTraNew; + aRotNow = aRotNew; + } + + // adjust rotation and translation speeds + void AdjustSpeeds(const FLOAT3D &vPlane) + { + // if going too slow in translation and rotation + if (en_vCurrentTranslationAbsolute.Length()<1.0f && m_fASpeed<1.0f) { + // just stop + en_vCurrentTranslationAbsolute = FLOAT3D(0,0,0); + m_fASpeed = 0.0f; + RollSound(0.0f); + return; + } + + // decompose speed to components regarding the plane + FLOAT3D vTranslationNormal; + FLOAT3D vTranslationParallel; + GetParallelAndNormalComponents(en_vCurrentTranslationAbsolute, vPlane, vTranslationNormal, vTranslationParallel); + + // check if rolling + BOOL bRolling = vTranslationNormal.Length()<0.1f; + // if rolling + if (bRolling) { + // get rotation direction from speed, if possible + FLOAT fSpeedTra = vTranslationParallel.Length(); +/* if (fSpeedTra>0.01f) { + m_vR = (vTranslationParallel/fSpeedTra)*vPlane; + }*/ + RollSound(fSpeedTra); + } else { + RollSound(0); + } + + + // --- find original axes and values + + // what is caused by rotation + FLOAT3D vRotFromRot = m_vR; + FLOAT3D vTraFromRot = vPlane*vRotFromRot; + vTraFromRot.Normalize(); + + FLOAT fTraFromRot = 0; + FLOAT fRotFromRot = m_fASpeed*PI/180.0f; + + // what is caused by translation + FLOAT3D vTraFromTra = vTranslationParallel; + FLOAT fTraFromTra = vTraFromTra.Length(); + FLOAT3D vRotFromTra = FLOAT3D(1,0,0); + FLOAT fRotFromTra = 0; + if (fTraFromTra>0.001f) { + vTraFromTra/=fTraFromTra; + vRotFromTra = vTraFromTra*vPlane; + vRotFromTra.Normalize(); + } + + // if there is any rotation + if (Abs(fRotFromRot)>0.01f) { + // adjust on rotation axis + AdjustSpeedOnOneAxis(fTraFromRot, fRotFromRot, bRolling); + } + // if there is any translation + if (Abs(fTraFromTra)>0.01f) { + // adjust on translation axis + AdjustSpeedOnOneAxis(fTraFromTra, fRotFromTra, bRolling); + } + + // put the speeds back together + FLOATquat3D qTra; + qTra.FromAxisAngle(vRotFromTra, fRotFromTra); + FLOATquat3D qRot; + qRot.FromAxisAngle(vRotFromRot, fRotFromRot); + FLOATquat3D q = qRot*qTra; + FLOAT3D vSpeed = vTraFromTra*fTraFromTra + vTraFromRot*fTraFromRot; + + // set the new speeds + en_vCurrentTranslationAbsolute = vTranslationNormal+vSpeed; + q.ToAxisAngle(m_vR, m_fASpeed); + m_fASpeed *= 180/PI; + } + +/************************************************************ + * S O U N D S * + ************************************************************/ +void BounceSound(FLOAT fSpeed) { + FLOAT fHitStrength = fSpeed*fSpeed; + + FLOAT fVolume = fHitStrength/20.0f; + //CPrintF("bounce %g->%g\n", fHitStrength, fVolume); + fVolume = Clamp( fVolume, 0.0f, 2.0f); + //FLOAT fVolume = Clamp(fHitStrength*5E-3f, 0.0f, 2.0f); + FLOAT fPitch = Lerp(0.2f, 1.0f, Clamp(fHitStrength/100, 0.0f, 1.0f)); + if (fVolume<0.1f) { + return; + } + CSoundObject &so = (&m_soBounce0)[m_iNextChannel]; + m_iNextChannel = (m_iNextChannel+1)%5; + so.Set3DParameters(200.0f*m_fStretch, 100.0f*m_fStretch, fVolume, fPitch); + PlaySound(so, SOUND_BOUNCE, SOF_3D); +}; + +void RollSound(FLOAT fSpeed) +{ + FLOAT fHitStrength = fSpeed*fSpeed*m_fStretch*m_fStretch*m_fStretch; + + FLOAT fVolume = fHitStrength/20.0f; + fVolume = Clamp( fVolume, 0.0f, 1.0f); + FLOAT fPitch = Lerp(0.2f, 1.0f, Clamp(fHitStrength/100, 0.0f, 1.0f)); + if (fVolume<0.1f) { + if (m_bRollPlaying) { + m_soRoll.Stop(); + m_bRollPlaying = FALSE; + } + return; + } + m_soRoll.Set3DParameters(200.0f*m_fStretch, 100.0f*m_fStretch, fVolume, fPitch); + + if (!m_bRollPlaying) { + PlaySound(m_soRoll, SOUND_ROLL, SOF_3D|SOF_LOOP); + m_bRollPlaying = TRUE; + } +} + +procedures: + + Main() + { + // set appearance + InitAsModel(); + SetPhysicsFlags(EPF_ONBLOCK_BOUNCE|EPF_PUSHABLE|EPF_MOVABLE|EPF_TRANSLATEDBYGRAVITY); + SetCollisionFlags(ECF_MODEL); + SetModel(MODEL_ROLLINGSTONE); + SetModelMainTexture(TEXTURE_ROLLINGSTONE); + AddAttachmentToModel(this, *GetModelObject(), 0, MODEL_STONESPHERE, TEXTURE_ROLLINGSTONE, 0, 0, TEXTURE_DETAIL); + + GetModelObject()->StretchModel( FLOAT3D(m_fStretch, m_fStretch, m_fStretch)); + ModelChangeNotify(); + + en_fBounceDampNormal = m_fBounce; + en_fBounceDampParallel = m_fBounce; + en_fAcceleration = en_fDeceleration = m_fDeceleration; + en_fCollisionSpeedLimit = 45.0f; + en_fCollisionDamageFactor = 10.0f; + + SetPlacement(CPlacement3D(GetPlacement().pl_PositionVector, ANGLE3D(0,0,0))); + m_qA = FLOATquat3D(0, 1, 0, 0); + m_qALast= FLOATquat3D(0, 1, 0, 0); + + autowait(0.1f); + + SetHealth( m_fHealth); + AddToMovers(); + + wait() { + on (ETrigger) : { + FLOAT3D v; + AnglesToDirectionVector(m_vStartDir, v); + GiveImpulseTranslationAbsolute(v*m_fStartSpeed); + //CPrintF("triggered\n"); + resume; + } + on (ETouch eTouch) : + { + + //CPrintF("touched\n"); + + if( !m_bFixedDamage) + { + FLOAT fDamageFactor = en_vCurrentTranslationAbsolute.Length()/10.0f; + FLOAT fAppliedDamage = fDamageFactor*m_fDamage; + // inflict damage + InflictDirectDamage( eTouch.penOther, this, DMT_CANNONBALL, fAppliedDamage, + eTouch.penOther->GetPlacement().pl_PositionVector, eTouch.plCollision); + } + else + { + if(en_vCurrentTranslationAbsolute.Length() != 0.0f) + { + // inflict damage + InflictDirectDamage( eTouch.penOther, this, DMT_CANNONBALL, m_fDamage, + eTouch.penOther->GetPlacement().pl_PositionVector, eTouch.plCollision); + } + } + + // adjust rotation and translation speeds + AdjustSpeeds(eTouch.plCollision); + + // if touched a brush + if (eTouch.penOther->GetRenderType() & RT_BRUSH) + { + BounceSound(((FLOAT3D&)eTouch.plCollision) % en_vCurrentTranslationAbsolute); + // calculate speed along impact normal + FLOAT fImpactSpeed = en_vCurrentTranslationAbsolute% (-(FLOAT3D&)eTouch.plCollision); + + // if strong collision + if( fImpactSpeed > 1000) + { + // receive artificial impact damage + ReceiveDamage(eTouch.penOther, DMT_IMPACT, m_fHealth*2.0f, + FLOAT3D(0,0,0), FLOAT3D(0,0,0)); + } + } + resume; + } + on (EDeath eDeath) : { + SendToTarget(m_penDeathTarget, EET_TRIGGER, eDeath.eLastDamage.penInflictor); + // get your size + FLOATaabbox3D box; + GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm(); + + Debris_Begin(EIBT_ROCK, DPT_NONE, BET_NONE, fEntitySize, FLOAT3D(1.0f,2.0f,3.0f), FLOAT3D(0,0,0), 1.0f, 0.0f); + for(INDEX iDebris = 0; iDebris<12; iDebris++) { + Debris_Spawn(this, this, MODEL_STONE, TEXTURE_STONE, 0, 0, 0, IRnd()%4, 0.15f, + FLOAT3D(FRnd()*0.8f+0.1f, FRnd()*0.8f+0.1f, FRnd()*0.8f+0.1f)); + } + Destroy(); + stop; + } + } + + // cease to exist + Destroy(); + + return; + } +}; diff --git a/Sources/EntitiesMP/RollingStone.h b/Sources/EntitiesMP/RollingStone.h new file mode 100644 index 0000000..d019d75 --- /dev/null +++ b/Sources/EntitiesMP/RollingStone.h @@ -0,0 +1,64 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_RollingStone_INCLUDED +#define _EntitiesMP_RollingStone_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CRollingStone_DLLClass; +class CRollingStone : public CMovableModelEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fBounce; + FLOAT m_fHealth; + FLOAT m_fDamage; + BOOL m_bFixedDamage; + FLOAT m_fStretch; + FLOAT m_fDeceleration; + FLOAT m_fStartSpeed; + ANGLE3D m_vStartDir; + CEntityPointer m_penDeathTarget; + CSoundObject m_soBounce0; + CSoundObject m_soBounce1; + CSoundObject m_soBounce2; + CSoundObject m_soBounce3; + CSoundObject m_soBounce4; + INDEX m_iNextChannel; + CSoundObject m_soRoll; + BOOL m_bRollPlaying; + FLOATquat3D m_qA; + FLOATquat3D m_qALast; + FLOAT m_fASpeed; + FLOAT3D m_vR; + +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void Precache(void); + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void PostMoving(); + +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void AdjustMipFactor(FLOAT & fMipFactor); + +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void AdjustSpeedOnOneAxis(FLOAT & fTraNow,FLOAT & aRotNow,BOOL bRolling); + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void AdjustSpeeds(const FLOAT3D & vPlane); + +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void BounceSound(FLOAT fSpeed); + +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +void RollSound(FLOAT fSpeed); +#define STATE_CRollingStone_Main 1 + BOOL +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x025c0000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x025c0001_Main_02(const CEntityEvent &__eeInput); + BOOL H0x025c0002_Main_03(const CEntityEvent &__eeInput); + BOOL H0x025c0003_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_RollingStone_INCLUDED diff --git a/Sources/EntitiesMP/RollingStone_tables.h b/Sources/EntitiesMP/RollingStone_tables.h new file mode 100644 index 0000000..95f5cdc --- /dev/null +++ b/Sources/EntitiesMP/RollingStone_tables.h @@ -0,0 +1,76 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CRollingStone + +CEntityProperty CRollingStone_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025c<<8)+1, offsetof(CRollingStone, m_fBounce), "Bounce", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025c<<8)+2, offsetof(CRollingStone, m_fHealth), "Health", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025c<<8)+3, offsetof(CRollingStone, m_fDamage), "Damage", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000025c<<8)+4, offsetof(CRollingStone, m_bFixedDamage), "Fixed damage", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025c<<8)+5, offsetof(CRollingStone, m_fStretch), "Stretch", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025c<<8)+6, offsetof(CRollingStone, m_fDeceleration), "Deceleration", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025c<<8)+7, offsetof(CRollingStone, m_fStartSpeed), "Start Speed", 'Z', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANGLE3D, NULL, (0x0000025c<<8)+8, offsetof(CRollingStone, m_vStartDir), "Start Direction", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025c<<8)+9, offsetof(CRollingStone, m_penDeathTarget), "Death target", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000025c<<8)+20, offsetof(CRollingStone, m_soBounce0), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000025c<<8)+21, offsetof(CRollingStone, m_soBounce1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000025c<<8)+22, offsetof(CRollingStone, m_soBounce2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000025c<<8)+23, offsetof(CRollingStone, m_soBounce3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000025c<<8)+24, offsetof(CRollingStone, m_soBounce4), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000025c<<8)+30, offsetof(CRollingStone, m_iNextChannel), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000025c<<8)+31, offsetof(CRollingStone, m_soRoll), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000025c<<8)+32, offsetof(CRollingStone, m_bRollPlaying), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATQUAT3D, NULL, (0x0000025c<<8)+40, offsetof(CRollingStone, m_qA), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOATQUAT3D, NULL, (0x0000025c<<8)+41, offsetof(CRollingStone, m_qALast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025c<<8)+42, offsetof(CRollingStone, m_fASpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000025c<<8)+43, offsetof(CRollingStone, m_vR), "", 0, 0, 0), +}; +#define CRollingStone_propertiesct ARRAYCOUNT(CRollingStone_properties) + +CEntityComponent CRollingStone_components[] = { +#define MODEL_ROLLINGSTONE ((0x0000025c<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_ROLLINGSTONE, "EFNM" "Models\\Ages\\Egypt\\Traps\\RollingStone\\RollingStone.mdl"), +#define MODEL_STONESPHERE ((0x0000025c<<8)+2) + CEntityComponent(ECT_MODEL, MODEL_STONESPHERE, "EFNM" "Models\\Ages\\Egypt\\Traps\\RollingStone\\Stone.mdl"), +#define TEXTURE_ROLLINGSTONE ((0x0000025c<<8)+3) + CEntityComponent(ECT_TEXTURE, TEXTURE_ROLLINGSTONE, "EFNM" "Models\\Ages\\Egypt\\Traps\\RollingStone\\Stone.tex"), +#define TEXTURE_DETAIL ((0x0000025c<<8)+5) + CEntityComponent(ECT_TEXTURE, TEXTURE_DETAIL, "EFNM" "Models\\Ages\\Egypt\\Traps\\RollingStone\\Detail.tex"), +#define MODEL_STONE ((0x0000025c<<8)+14) + CEntityComponent(ECT_MODEL, MODEL_STONE, "EFNM" "Models\\Effects\\Debris\\Stone\\Stone.mdl"), +#define TEXTURE_STONE ((0x0000025c<<8)+15) + CEntityComponent(ECT_TEXTURE, TEXTURE_STONE, "EFNM" "Models\\Effects\\Debris\\Stone\\Stone.tex"), +#define CLASS_DEBRIS ((0x0000025c<<8)+16) + CEntityComponent(ECT_CLASS, CLASS_DEBRIS, "EFNM" "Classes\\Debris.ecl"), +#define CLASS_BASIC_EFFECT ((0x0000025c<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define SOUND_BOUNCE ((0x0000025c<<8)+20) + CEntityComponent(ECT_SOUND, SOUND_BOUNCE, "EFNM" "Sounds\\Misc\\RollingStone.wav"), +#define SOUND_ROLL ((0x0000025c<<8)+21) + CEntityComponent(ECT_SOUND, SOUND_ROLL, "EFNM" "Sounds\\Misc\\RollingStoneEnvironment.wav"), +}; +#define CRollingStone_componentsct ARRAYCOUNT(CRollingStone_components) + +CEventHandlerEntry CRollingStone_handlers[] = { + {1, -1, CEntity::pEventHandler(&CRollingStone:: +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/RollingStone.es" +Main),DEBUGSTRING("CRollingStone::Main")}, + {0x025c0000, -1, CEntity::pEventHandler(&CRollingStone::H0x025c0000_Main_01), DEBUGSTRING("CRollingStone::H0x025c0000_Main_01")}, + {0x025c0001, -1, CEntity::pEventHandler(&CRollingStone::H0x025c0001_Main_02), DEBUGSTRING("CRollingStone::H0x025c0001_Main_02")}, + {0x025c0002, -1, CEntity::pEventHandler(&CRollingStone::H0x025c0002_Main_03), DEBUGSTRING("CRollingStone::H0x025c0002_Main_03")}, + {0x025c0003, -1, CEntity::pEventHandler(&CRollingStone::H0x025c0003_Main_04), DEBUGSTRING("CRollingStone::H0x025c0003_Main_04")}, +}; +#define CRollingStone_handlersct ARRAYCOUNT(CRollingStone_handlers) + +CEntity *CRollingStone_New(void) { return new CRollingStone; }; +void CRollingStone_OnInitClass(void) {}; +void CRollingStone_OnEndClass(void) {}; +void CRollingStone_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CRollingStone_OnWorldEnd(CWorld *pwo) {}; +void CRollingStone_OnWorldInit(CWorld *pwo) {}; +void CRollingStone_OnWorldTick(CWorld *pwo) {}; +void CRollingStone_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CRollingStone, CMovableModelEntity, "RollingStone", "Thumbnails\\RollingStone.tbn", 0x0000025c); +DECLARE_CTFILENAME(_fnmCRollingStone_tbn, "Thumbnails\\RollingStone.tbn"); diff --git a/Sources/EntitiesMP/Santa.cpp b/Sources/EntitiesMP/Santa.cpp new file mode 100644 index 0000000..0da0a50 --- /dev/null +++ b/Sources/EntitiesMP/Santa.cpp @@ -0,0 +1,349 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" + +#include "StdH.h" +#include "ModelsMP/Player/SeriousSam/Player.h" +#include "ModelsMP/Player/SeriousSam/Body.h" +#include "ModelsMP/Player/SeriousSam/Head.h" + +#include +#include +#line 13 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" + +// info structure +static EntityInfo eiSanta = { + EIBT_AIR, 100.0f, + 0, 1.6f, 0, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; + +void CSanta::SetDefaultProperties(void) { + m_tmLastSpawnTime = -10000.0f; + m_tmMinSpawnInterval = 1.0f; + m_fSantaHealth = 100.0f; + m_soRunning.SetOwner(this); +m_soRunning.Stop_internal(); + m_bRunSoundPlaying = FALSE ; + m_penTemplate0 = NULL; + m_penTemplate1 = NULL; + m_penTemplate2 = NULL; + m_penTemplate3 = NULL; + m_penTemplate4 = NULL; + CEnemyBase::SetDefaultProperties(); +} + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::Precache(void) { +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +CEnemyBase :: Precache (); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +PrecacheSound (SOUND_RUN ); +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +PrecacheSound (SOUND_WOUND ); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +PrecacheSound (SOUND_DEATH ); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + const CTFileName & CSanta::GetComputerMessageName(void)const { +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +static CTFileName fnm ; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return fnm ; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void * CSanta::GetEntityInfo(void) { +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return & eiSanta ; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::ActivateRunningSound(void) +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +{ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +if(! m_bRunSoundPlaying ){ +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +PlaySound (m_soRunning , SOUND_RUN , SOF_3D | SOF_LOOP ); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_bRunSoundPlaying = TRUE ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::DeactivateRunningSound(void) +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +{ +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_soRunning . Stop (); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_bRunSoundPlaying = FALSE ; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +BOOL CSanta::HandleEvent(const CEntityEvent & ee) +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +{ +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +if(ee . ee_slEvent == EVENTCODE_ETouch || ee . ee_slEvent == EVENTCODE_EDamage ){ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return TRUE ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return CEnemyBase :: HandleEvent (ee ); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +{ +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +CMovableModelEntity :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +if(_pTimer -> CurrentTick () - m_tmLastSpawnTime < m_tmMinSpawnInterval ){ +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +WoundSound (); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_tmLastSpawnTime = _pTimer -> CurrentTick (); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +INDEX ctTemplates = 0; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +if(m_penTemplate0 != NULL ){ctTemplates ++;} +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +if(m_penTemplate1 != NULL ){ctTemplates ++;} +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +if(m_penTemplate2 != NULL ){ctTemplates ++;} +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +if(m_penTemplate3 != NULL ){ctTemplates ++;} +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +if(m_penTemplate4 != NULL ){ctTemplates ++;} +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +if(ctTemplates == 0){ +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +INDEX iTemplate = IRnd () % ctTemplates ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +CEntity * penItem = (& m_penTemplate0 ) [ iTemplate ]; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +if(penItem == NULL || (penItem -> GetFlags () & ENF_DELETED )){ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return ; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +CEntity * penSpawned = GetWorld () -> CopyEntityInWorld (* penItem , +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +CPlacement3D (FLOAT3D (- 32000.0f + FRnd () * 200.0f , - 32000.0f + FRnd () * 200.0f , 0) , ANGLE3D (0 , 0 , 0))); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +CPlacement3D pl = GetPlacement (); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +pl . pl_PositionVector += GetRotationMatrix () . GetColumn (2) * 1.5f; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +penSpawned -> Teleport (pl , FALSE ); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::LeaveStain(BOOL bGrow) +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +{ +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +INDEX CSanta::AnimForDamage(FLOAT fDamage) { +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return 0; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +INDEX CSanta::AnimForDeath(void) { +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return 0; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::DeathNotify(void) { +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +SwitchToEditorModel (); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +SetCollisionFlags (ECF_MODEL ); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +DeactivateRunningSound (); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +CModelObject * CSanta::GetBody(void) +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +{ +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return & GetModelObject () -> GetAttachmentModel (PLAYER_ATTACHMENT_TORSO ) -> amo_moModelObject ; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::StandingAnim(void) { +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::WalkingAnim(void) { +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +ActivateRunningSound (); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::RunningAnim(void) { +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +ActivateRunningSound (); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::RotatingAnim(void) { +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +ActivateRunningSound (); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::IdleSound(void) { +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::SightSound(void) { +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::WoundSound(void) { +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::DeathSound(void) { +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} + +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void CSanta::EnemyPostInit(void) +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +{ +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_soSound . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +} +BOOL CSanta:: +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSanta_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSanta::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Return(STATE_CURRENT,EReturn ()); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSanta:: +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSanta_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSanta::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Return(STATE_CURRENT,EReturn ()); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSanta:: +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSanta_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSanta::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +InitAsModel (); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +SetCollisionFlags (ECF_MODEL ); +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +en_tmMaxHoldBreath = 25.0f; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +en_fDensity = 3000.0f; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +CTString strDummy ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +extern BOOL SetPlayerAppearance_internal (CModelObject * pmo , const CTFileName & fnmAMC , CTString & strName , BOOL bPreview ); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +SetPlayerAppearance_internal (GetModelObject () , CTFILENAME ("ModelsMP\\CutSequences\\Santa\\Santa.amc") , strDummy , FALSE ); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +SetHealth (m_fSantaHealth ); +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fMaxHealth = m_fSantaHealth ; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fDamageWounded = 1E10f; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fBlowUpAmount = 1E10f; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fBodyParts = 30; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fAttackDistance = 150.0f; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fCloseDistance = 5.0f; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fStopDistance = 4.5f; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fAttackFireTime = 0.5f; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fCloseFireTime = 1.0f; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fIgnoreRange = 300.0f; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_iScore = 1000; +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fWalkSpeed = (FRnd () + 1.5f) * 1.5f; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 20.0f + 550.0f); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fAttackRunSpeed = FRnd () * 1.5f + 4.5f; +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50.0f + 275.0f); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_fCloseRunSpeed = FRnd () * 1.5f + 4.5f; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50.0f + 275.0f); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +CEnemyBase :: SizeModel (); +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_soRunning . Set3DParameters (500.0f , 50.0f , 1.0f , 1.0f); +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +m_bRunSoundPlaying = FALSE ; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Santa.es b/Sources/EntitiesMP/Santa.es new file mode 100644 index 0000000..fc1ee72 --- /dev/null +++ b/Sources/EntitiesMP/Santa.es @@ -0,0 +1,271 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +355 +%{ +#include "StdH.h" +#include "ModelsMP/Player/SeriousSam/Player.h" +#include "ModelsMP/Player/SeriousSam/Body.h" +#include "ModelsMP/Player/SeriousSam/Head.h" +%} + +uses "EntitiesMP/EnemyBase"; + +%{ +// info structure +static EntityInfo eiSanta = { + EIBT_AIR, 100.0f, + 0, 1.6f, 0, // source (eyes) + 0.0f, 1.0f, 0.0f, // target (body) +}; +%} + + +class CSanta : CEnemyBase { +name "Santa"; +thumbnail "Thumbnails\\Santa.tbn"; + +properties: + 1 FLOAT m_tmLastSpawnTime = -10000.0f, + 2 FLOAT m_tmMinSpawnInterval "Min spawn interval" = 1.0f, + 3 FLOAT m_fSantaHealth "Santa Health" = 100.0f, + 4 CSoundObject m_soRunning, // for running sound + 5 BOOL m_bRunSoundPlaying = FALSE, + + 10 CEntityPointer m_penTemplate0 "Item template 0", + 11 CEntityPointer m_penTemplate1 "Item template 1", + 12 CEntityPointer m_penTemplate2 "Item template 2", + 13 CEntityPointer m_penTemplate3 "Item template 3", + 14 CEntityPointer m_penTemplate4 "Item template 4", + +components: + 0 class CLASS_BASE "Classes\\EnemyBase.ecl", + +// ************** SOUNDS ************** + 50 sound SOUND_RUN "ModelsMP\\CutSequences\\Santa\\Sounds\\Running.wav", + 51 sound SOUND_WOUND "ModelsMP\\CutSequences\\Santa\\Sounds\\Wound.wav", + 52 sound SOUND_DEATH "ModelsMP\\CutSequences\\Santa\\Sounds\\Death.wav", + +functions: + void Precache(void) { + CEnemyBase::Precache(); + PrecacheSound(SOUND_RUN ); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_DEATH); + }; + + virtual const CTFileName &GetComputerMessageName(void) const { + //static DECLARE_CTFILENAME(fnm, "DataMP\\Messages\\Enemies\\Santa.txt"); + static CTFileName fnm; + return fnm; + }; + + /* Entity info */ + void *GetEntityInfo(void) { + return &eiSanta; + }; + + // running sounds + void ActivateRunningSound(void) + { + if (!m_bRunSoundPlaying) { + PlaySound(m_soRunning, SOUND_RUN, SOF_3D|SOF_LOOP); + m_bRunSoundPlaying = TRUE; + } + } + void DeactivateRunningSound(void) + { + m_soRunning.Stop(); + m_bRunSoundPlaying = FALSE; + } + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + // ignore touching, damaging... + if (ee.ee_slEvent==EVENTCODE_ETouch || ee.ee_slEvent==EVENTCODE_EDamage) { + return TRUE; + } + + return CEnemyBase::HandleEvent(ee); + } + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // skip base enemy damage handling + CMovableModelEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + + // if not enough time passed since lst item spawning + if (_pTimer->CurrentTick()-m_tmLastSpawnTimeCurrentTick(); + // choose an item to spawn + INDEX ctTemplates = 0; + if (m_penTemplate0!=NULL) { ctTemplates++; } + if (m_penTemplate1!=NULL) { ctTemplates++; } + if (m_penTemplate2!=NULL) { ctTemplates++; } + if (m_penTemplate3!=NULL) { ctTemplates++; } + if (m_penTemplate4!=NULL) { ctTemplates++; } + if (ctTemplates==0) { + return; + } + INDEX iTemplate = IRnd()%ctTemplates; + CEntity *penItem = (&m_penTemplate0)[iTemplate]; + + // if the target doesn't exist, or is destroyed + if (penItem==NULL || (penItem->GetFlags()&ENF_DELETED)) { + // do nothing + return; + } + + CEntity *penSpawned = GetWorld()->CopyEntityInWorld( *penItem, + CPlacement3D(FLOAT3D(-32000.0f+FRnd()*200.0f, -32000.0f+FRnd()*200.0f, 0), ANGLE3D(0, 0, 0)) ); + + // teleport back + CPlacement3D pl = GetPlacement(); + pl.pl_PositionVector += GetRotationMatrix().GetColumn(2)*1.5f; // a bit up in the air + penSpawned->Teleport(pl, FALSE); + }; + + void LeaveStain( BOOL bGrow) + { + } + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { +// StartModelAnim(iAnim, 0); + return 0; + }; + + // death + INDEX AnimForDeath(void) { +// StartModelAnim(iAnim, 0); + return 0; + }; + + void DeathNotify(void) { + SwitchToEditorModel(); +// ChangeCollisionBoxIndexWhenPossible(PLAYER_COLLISION_BOX_DEATH); + SetCollisionFlags(ECF_MODEL); + DeactivateRunningSound(); + }; + + CModelObject *GetBody(void) + { + return &GetModelObject()->GetAttachmentModel(PLAYER_ATTACHMENT_TORSO)->amo_moModelObject; + } + +// virtual anim functions + void StandingAnim(void) { +// StartModelAnim(PLAYER_ANIM_STAND, AOF_LOOPING|AOF_NORESTART); +// GetBody()->PlayAnim(BODY_ANIM_WAIT, AOF_LOOPING|AOF_NORESTART); + }; + void WalkingAnim(void) { + ActivateRunningSound(); +// StartModelAnim(PLAYER_ANIM_NORMALWALK, AOF_LOOPING|AOF_NORESTART); +// GetBody()->PlayAnim(BODY_ANIM_NORMALWALK, AOF_LOOPING|AOF_NORESTART); + }; + void RunningAnim(void) { + ActivateRunningSound(); +// StartModelAnim(PLAYER_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); +// GetBody()->PlayAnim(BODY_ANIM_NORMALWALK, AOF_LOOPING|AOF_NORESTART); + }; + void RotatingAnim(void) { + ActivateRunningSound(); +// StartModelAnim(BODY_ANIM_NORMALWALK, AOF_LOOPING|AOF_NORESTART); +// GetBody()->PlayAnim(BODY_ANIM_NORMALWALK, AOF_LOOPING|AOF_NORESTART); + }; + + // virtual sound functions + void IdleSound(void) { +// PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { +// PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + // set sound default parameters + m_soSound.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + }; + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + // shoot + Fire(EVoid) : CEnemyBase::Fire{ + return EReturn(); + }; + + // hit enemy + Hit(EVoid) : CEnemyBase::Hit { + return EReturn(); + }; + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + en_tmMaxHoldBreath = 25.0f; + en_fDensity = 3000.0f; + + // set your appearance + CTString strDummy; + extern BOOL SetPlayerAppearance_internal(CModelObject *pmo, const CTFileName &fnmAMC, CTString &strName, BOOL bPreview); + SetPlayerAppearance_internal(GetModelObject(), CTFILENAME("ModelsMP\\CutSequences\\Santa\\Santa.amc"), strDummy, /*bPreview=*/FALSE); + + SetHealth(m_fSantaHealth); + m_fMaxHealth = m_fSantaHealth; + // damage/explode properties + m_fDamageWounded = 1E10f; + m_fBlowUpAmount = 1E10f; + m_fBodyParts = 30; + // setup attack distances + m_fAttackDistance = 150.0f; + m_fCloseDistance = 5.0f; + m_fStopDistance = 4.5f; + m_fAttackFireTime = 0.5f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 300.0f; + m_iScore = 1000; + // setup moving speed + m_fWalkSpeed = (FRnd() + 1.5f)*1.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*20.0f + 550.0f); + m_fAttackRunSpeed = FRnd()*1.5f + 4.5f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50.0f + 275.0f); + m_fCloseRunSpeed = FRnd()*1.5f + 4.5f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50.0f + 275.0f); + + // set stretch factors for height and width + CEnemyBase::SizeModel(); + m_soRunning.Set3DParameters(500.0f, 50.0f, 1.0f, 1.0f); + m_bRunSoundPlaying = FALSE; + // continue behavior in base class + jump CEnemyBase::MainLoop(); + + }; +}; diff --git a/Sources/EntitiesMP/Santa.h b/Sources/EntitiesMP/Santa.h new file mode 100644 index 0000000..0c326fd --- /dev/null +++ b/Sources/EntitiesMP/Santa.h @@ -0,0 +1,100 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Santa_INCLUDED +#define _EntitiesMP_Santa_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CSanta_DLLClass; +class CSanta : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_tmLastSpawnTime; + FLOAT m_tmMinSpawnInterval; + FLOAT m_fSantaHealth; + CSoundObject m_soRunning; + BOOL m_bRunSoundPlaying; + CEntityPointer m_penTemplate0; + CEntityPointer m_penTemplate1; + CEntityPointer m_penTemplate2; + CEntityPointer m_penTemplate3; + CEntityPointer m_penTemplate4; + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void Precache(void); + +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void * GetEntityInfo(void); + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void ActivateRunningSound(void); + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void DeactivateRunningSound(void); + +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +BOOL HandleEvent(const CEntityEvent & ee); + +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void LeaveStain(BOOL bGrow); + +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +INDEX AnimForDeath(void); + +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void DeathNotify(void); + +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +CModelObject * GetBody(void); + +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void StandingAnim(void); + +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void WalkingAnim(void); + +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void RunningAnim(void); + +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void RotatingAnim(void); + +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void IdleSound(void); + +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void SightSound(void); + +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void WoundSound(void); + +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void DeathSound(void); + +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +void EnemyPostInit(void); +#define STATE_CSanta_Fire 0x01630000 + BOOL +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Fire(const CEntityEvent &__eeInput); +#define STATE_CSanta_Hit 0x01630001 + BOOL +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Hit(const CEntityEvent &__eeInput); +#define STATE_CSanta_Main 1 + BOOL +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Santa_INCLUDED diff --git a/Sources/EntitiesMP/Santa_tables.h b/Sources/EntitiesMP/Santa_tables.h new file mode 100644 index 0000000..8c0a732 --- /dev/null +++ b/Sources/EntitiesMP/Santa_tables.h @@ -0,0 +1,55 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CSanta + +CEntityProperty CSanta_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000163<<8)+1, offsetof(CSanta, m_tmLastSpawnTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000163<<8)+2, offsetof(CSanta, m_tmMinSpawnInterval), "Min spawn interval", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000163<<8)+3, offsetof(CSanta, m_fSantaHealth), "Santa Health", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000163<<8)+4, offsetof(CSanta, m_soRunning), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000163<<8)+5, offsetof(CSanta, m_bRunSoundPlaying), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000163<<8)+10, offsetof(CSanta, m_penTemplate0), "Item template 0", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000163<<8)+11, offsetof(CSanta, m_penTemplate1), "Item template 1", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000163<<8)+12, offsetof(CSanta, m_penTemplate2), "Item template 2", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000163<<8)+13, offsetof(CSanta, m_penTemplate3), "Item template 3", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000163<<8)+14, offsetof(CSanta, m_penTemplate4), "Item template 4", 0, 0x7F0000FFUL, 0), +}; +#define CSanta_propertiesct ARRAYCOUNT(CSanta_properties) + +CEntityComponent CSanta_components[] = { +#define CLASS_BASE ((0x00000163<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define SOUND_RUN ((0x00000163<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_RUN, "EFNM" "ModelsMP\\CutSequences\\Santa\\Sounds\\Running.wav"), +#define SOUND_WOUND ((0x00000163<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "ModelsMP\\CutSequences\\Santa\\Sounds\\Wound.wav"), +#define SOUND_DEATH ((0x00000163<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "ModelsMP\\CutSequences\\Santa\\Sounds\\Death.wav"), +}; +#define CSanta_componentsct ARRAYCOUNT(CSanta_components) + +CEventHandlerEntry CSanta_handlers[] = { + {0x01630000, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CSanta:: +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Fire),DEBUGSTRING("CSanta::Fire")}, + {0x01630001, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CSanta:: +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Hit),DEBUGSTRING("CSanta::Hit")}, + {1, -1, CEntity::pEventHandler(&CSanta:: +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Santa.es" +Main),DEBUGSTRING("CSanta::Main")}, +}; +#define CSanta_handlersct ARRAYCOUNT(CSanta_handlers) + +CEntity *CSanta_New(void) { return new CSanta; }; +void CSanta_OnInitClass(void) {}; +void CSanta_OnEndClass(void) {}; +void CSanta_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CSanta_OnWorldEnd(CWorld *pwo) {}; +void CSanta_OnWorldInit(CWorld *pwo) {}; +void CSanta_OnWorldTick(CWorld *pwo) {}; +void CSanta_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CSanta, CEnemyBase, "Santa", "Thumbnails\\Santa.tbn", 0x00000163); +DECLARE_CTFILENAME(_fnmCSanta_tbn, "Thumbnails\\Santa.tbn"); diff --git a/Sources/EntitiesMP/Scorpman.cpp b/Sources/EntitiesMP/Scorpman.cpp new file mode 100644 index 0000000..eb4c249 --- /dev/null +++ b/Sources/EntitiesMP/Scorpman.cpp @@ -0,0 +1,998 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" + +#include "StdH.h" +#include "Models/Enemies/Scorpman/Scorpman.h" +#include "Models/Enemies/Scorpman/Gun.h" + +#include +#include +#line 21 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" + +#define GUN_X 0.375f +#define GUN_Y 0.6f +#define GUN_Z -1.85f +#define STRETCH_SOLDIER 2 +#define STRETCH_GENERAL 3 +#define STRETCH_MONSTER 4 +// info structure +static EntityInfo eiScorpman = { + EIBT_FLESH, 1000.0f, + 0, 1.6f*STRETCH_SOLDIER, 0, // source (eyes) + 0.0f, 1.0f*STRETCH_SOLDIER, 0.0f, // target (body) +}; + +static EntityInfo eiScorpmanGeneral = { + EIBT_FLESH, 1500.0f, + 0, 1.6f*STRETCH_GENERAL, 0, // source (eyes) + 0.0f, 1.0f*STRETCH_GENERAL, 0.0f, // target (body) +}; + +static EntityInfo eiScorpmanMonster = { + EIBT_FLESH, 2000.0f, + 0, 1.6f*STRETCH_MONSTER, 0, // source (eyes) + 0.0f, 1.0f*STRETCH_MONSTER, 0.0f, // target (body) +}; +#define LIGHT_ANIM_FIRE 3 +#define LIGHT_ANIM_NONE 5 + +void CScorpman::SetDefaultProperties(void) { + m_smtType = SMT_SOLDIER ; + m_bFireBulletCount = 0; + m_iSpawnEffect = 0; + m_fFireTime = 0.0f; + m_aoLightAnimation.SetData(NULL); + + m_bSleeping = FALSE ; + CEnemyBase::SetDefaultProperties(); +} + CTString CScorpman::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +{ +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CTString str ; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(eDeath . eLastDamage . dmtType == DMT_CLOSERANGE ){ +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +str . PrintF (TRANS ("%s was stabbed by an Arachnoid") , strPlayerName ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}else { +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +str . PrintF (TRANS ("An Arachnoid poured lead into %s") , strPlayerName ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return str ; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::Precache(void) { +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CEnemyBase :: Precache (); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PrecacheModel (MODEL_FLARE ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PrecacheSound (SOUND_IDLE ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PrecacheSound (SOUND_SIGHT ); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PrecacheSound (SOUND_WOUND ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PrecacheSound (SOUND_FIRE ); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PrecacheSound (SOUND_KICK ); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PrecacheSound (SOUND_DEATH ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::Read_t(CTStream * istr) { +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CEnemyBase :: Read_t (istr ); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetupLightSource (); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +BOOL CScorpman::FillEntityStatistics(EntityStats * pes) +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +{ +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CEnemyBase :: FillEntityStatistics (pes ); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +switch(m_smtType ){ +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_MONSTER : {pes -> es_strName += " Monster";}break ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_GENERAL : {pes -> es_strName += " General";}break ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_SOLDIER : {pes -> es_strName += " Soldier";}break ; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return TRUE ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + const CTFileName & CScorpman::GetComputerMessageName(void)const { +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +static DECLARE_CTFILENAME (fnmGeneral , "Data\\Messages\\Enemies\\ScorpmanGeneral.txt"); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +static DECLARE_CTFILENAME (fnmSoldier , "Data\\Messages\\Enemies\\ScorpmanSoldier.txt"); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +switch(m_smtType ){ +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +default : ASSERT (FALSE ); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_MONSTER : +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_GENERAL : return fnmGeneral ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_SOLDIER : return fnmSoldier ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CLightSource * CScorpman::GetLightSource(void) { +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(! IsPredictor ()){ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return & m_lsLightSource ; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}else { +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return NULL ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +BOOL CScorpman::ForcesCannonballToExplode(void) +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +{ +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(m_smtType != SMT_SOLDIER ){ +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return TRUE ; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return CEnemyBase :: ForcesCannonballToExplode (); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::SetupLightSource(void) { +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CLightSource lsNew ; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +lsNew . ls_ulFlags = LSF_NONPERSISTENT | LSF_DYNAMIC ; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +lsNew . ls_rHotSpot = 2.0f; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +lsNew . ls_rFallOff = 8.0f; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +lsNew . ls_colColor = RGBToColor (128 , 128 , 128); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +lsNew . ls_plftLensFlare = NULL ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +lsNew . ls_ubPolygonalMask = 0; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +lsNew . ls_paoLightAnimation = & m_aoLightAnimation ; +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_lsLightSource . ls_penEntity = this ; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::PlayLightAnim(INDEX iAnim,ULONG ulFlags) { +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(m_aoLightAnimation . GetData () != NULL ){ +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_aoLightAnimation . PlayAnim (iAnim , ulFlags ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::MinigunOn(void) +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +{ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PlayLightAnim (LIGHT_ANIM_FIRE , AOF_LOOPING ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CModelObject * pmoGun = & GetModelObject () -> GetAttachmentModel (SCORPMAN_ATTACHMENT_MINIGUN ) -> +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +amo_moModelObject ; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +pmoGun -> PlayAnim (GUN_ANIM_FIRE , AOF_LOOPING ); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +AddAttachmentToModel (this , * pmoGun , GUN_ATTACHMENT_FLAME , MODEL_FLARE , TEXTURE_GUN , 0 , 0 , 0); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +switch(m_smtType ){ +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_SOLDIER : pmoGun -> StretchModel (FLOAT3D (2.0f , 2.0f , 2.0f));break ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_GENERAL : pmoGun -> StretchModel (FLOAT3D (3.0f , 3.0f , 3.0f));break ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_MONSTER : pmoGun -> StretchModel (FLOAT3D (4.0f , 4.0f , 4.0f));break ; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::MinigunOff(void) +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +{ +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PlayLightAnim (LIGHT_ANIM_NONE , 0); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CModelObject * pmoGun = & GetModelObject () -> GetAttachmentModel (SCORPMAN_ATTACHMENT_MINIGUN ) -> +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +amo_moModelObject ; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +pmoGun -> PlayAnim (GUN_ANIM_IDLE , AOF_LOOPING ); +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +pmoGun -> RemoveAttachmentModel (GUN_ATTACHMENT_FLAME ); +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void * CScorpman::GetEntityInfo(void) { +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(m_smtType == SMT_MONSTER ){ +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return & eiScorpmanMonster ; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}else if(m_smtType == SMT_GENERAL ){ +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return & eiScorpmanGeneral ; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}else { +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return & eiScorpman ; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +{ +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(! IsOfClass (penInflictor , "Scorpman")){ +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +INDEX CScorpman::AnimForDamage(FLOAT fDamage) { +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +INDEX iAnim ; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +switch(IRnd () % 3){ +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case 0: iAnim = SCORPMAN_ANIM_WOUND01 ;break ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case 1: iAnim = SCORPMAN_ANIM_WOUND02 ;break ; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case 2: iAnim = SCORPMAN_ANIM_WOUND03 ;break ; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +default : ASSERTALWAYS ("Scorpman unknown damage"); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (iAnim , 0); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +MinigunOff (); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return iAnim ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +INDEX CScorpman::AnimForDeath(void) { +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_DEATH , 0); +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +MinigunOff (); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return SCORPMAN_ANIM_DEATH ; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +FLOAT CScorpman::WaitForDust(FLOAT3D & vStretch) { +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(GetModelObject () -> GetAnim () == SCORPMAN_ANIM_DEATH ) +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +{ +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +vStretch = FLOAT3D (1 , 1 , 1) * 1.5f; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return 1.3f; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return - 1.0f; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::DeathNotify(void) { +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +ChangeCollisionBoxIndexWhenPossible (SCORPMAN_COLLISION_BOX_DEATH ); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetCollisionFlags (ECF_MODEL ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::StandingAnim(void) { +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::WalkingAnim(void) { +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_WALK , AOF_LOOPING | AOF_NORESTART ); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::RunningAnim(void) { +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_WALK , AOF_LOOPING | AOF_NORESTART ); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::RotatingAnim(void) { +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_WALK , AOF_LOOPING | AOF_NORESTART ); +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::IdleSound(void) { +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::SightSound(void) { +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::WoundSound(void) { +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::DeathSound(void) { +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +BOOL CScorpman::CanFireAtPlayer(void) +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +{ +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +FLOAT3D vSource , vTarget ; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +GetPositionCastRay (this , m_penEnemy , vSource , vTarget ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CPlacement3D plBullet ; +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . pl_PositionVector = FLOAT3D (GUN_X , GUN_Y , 0); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(m_smtType == SMT_MONSTER ){ +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . pl_PositionVector *= STRETCH_MONSTER ; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}else if(m_smtType == SMT_GENERAL ){ +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . pl_PositionVector *= STRETCH_GENERAL ; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}else { +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . pl_PositionVector *= STRETCH_SOLDIER ; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . RelativeToAbsolute (GetPlacement ()); +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +vSource = plBullet . pl_PositionVector ; +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CCastRay crRay (this , vSource , vTarget ); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +crRay . cr_ttHitModels = CCastRay :: TT_NONE ; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +crRay . cr_bHitTranslucentPortals = FALSE ; +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +en_pwoWorld -> CastRay (crRay ); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return (crRay . cr_penHit == NULL ); +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::PrepareBullet(FLOAT fDamage) { +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CPlacement3D plBullet ; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . pl_OrientationAngle = ANGLE3D (0 , 0 , 0); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . pl_PositionVector = FLOAT3D (GUN_X , GUN_Y , 0); +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(m_smtType == SMT_MONSTER ){ +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . pl_PositionVector *= STRETCH_MONSTER ; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}else if(m_smtType == SMT_GENERAL ){ +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . pl_PositionVector *= STRETCH_GENERAL ; +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}else { +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . pl_PositionVector *= STRETCH_SOLDIER ; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +plBullet . RelativeToAbsolute (GetPlacement ()); +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +penBullet = CreateEntity (plBullet , CLASS_BULLET ); +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +EBulletInit eInit ; +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +eInit . penOwner = this ; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +eInit . fDamage = fDamage ; +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +penBullet -> Initialize (eInit ); +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::FireBullet(void) { +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_bFireBulletCount ++; +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(m_bFireBulletCount > 1){m_bFireBulletCount = 0;} +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(m_bFireBulletCount == 1){return ;} +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PrepareBullet (3.0f); +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +((CBullet &) * penBullet ) . CalcTarget (m_penEnemy , 250); +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +((CBullet &) * penBullet ) . CalcJitterTarget (10); +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +((CBullet &) * penBullet ) . LaunchBullet (TRUE , TRUE , TRUE ); +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +((CBullet &) * penBullet ) . DestroyBullet (); +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} + +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void CScorpman::EnemyPostInit(void) +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +{ +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_soSound . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +BOOL CScorpman:: +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CScorpman_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CScorpman::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(! CanFireAtPlayer ()){ +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Return(STATE_CURRENT,EReturn ()); +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return TRUE; +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +switch(m_smtType ){ +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_MONSTER : +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fDamageConfused = 200; +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fFireTime = 8.0f; +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +break ; +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_GENERAL : +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fDamageConfused = 100; +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fFireTime = 4.0f; +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +break ; +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_SOLDIER : +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fDamageConfused = 50; +#line 391 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fFireTime = 2.0f; +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +break ; +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(GetSP () -> sp_gdGameDifficulty <= CSessionProperties :: GD_EASY ){ +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fFireTime *= 0.5f; +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_STANDTOFIRE , 0); +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fLockOnEnemyTime = GetModelObject () -> GetAnimLength (SCORPMAN_ANIM_STANDTOFIRE ) + 0.5f + FRnd () / 3; +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +STATE_CEnemyBase_LockOnEnemy, FALSE; +Jump(STATE_CURRENT, 0x01320001, FALSE, EBegin());return TRUE;}BOOL CScorpman::H0x01320001_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_LockOnEnemy, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01320002, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CScorpman::H0x01320002_Fire_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320002 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_iSpawnEffect = 0; +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fFireTime += _pTimer -> CurrentTick (); +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_bFireBulletCount = 0; +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D | SOF_LOOP ); +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +MinigunOn (); +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Jump(STATE_CURRENT,0x01320005, FALSE, EInternal());return TRUE;}BOOL CScorpman::H0x01320005_Fire_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320005 +if(!(m_fFireTime > _pTimer -> CurrentTick ())){ Jump(STATE_CURRENT,0x01320006, FALSE, EInternal());return TRUE;} +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fMoveFrequency = 0.1f; +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetTimerAfter(m_fMoveFrequency ); +Jump(STATE_CURRENT, 0x01320003, FALSE, EBegin());return TRUE;}BOOL CScorpman::H0x01320003_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320003 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +AddToFuss (); +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +FireBullet (); +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_vDesiredPosition = m_penEnemy -> GetPlacement () . pl_PositionVector ; +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(! IsInPlaneFrustum (m_penEnemy , CosFast (5.0f))){ +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fMoveSpeed = 0.0f; +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_aRotateSpeed = 4000.0f; +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_WALK_AND_FIRE , AOF_LOOPING | AOF_NORESTART ); +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}else { +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fMoveSpeed = 0.0f; +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_aRotateSpeed = 0.0f; +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_FIRE_MINIGUN , AOF_LOOPING | AOF_NORESTART ); +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetDesiredMovement (); +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return TRUE; +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01320004, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}return TRUE;}BOOL CScorpman::H0x01320004_Fire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320004 +Jump(STATE_CURRENT,0x01320005, FALSE, EInternal());return TRUE; +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}BOOL CScorpman::H0x01320006_Fire_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320006 + +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_soSound . Stop (); +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +MinigunOff (); +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fShootTime = _pTimer -> CurrentTick () + m_fAttackFireTime * (1.0f + FRnd () / 3.0f); +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_FIRETOSTAND , 0); +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (SCORPMAN_ANIM_FIRETOSTAND )); +Jump(STATE_CURRENT, 0x01320007, FALSE, EBegin());return TRUE;}BOOL CScorpman::H0x01320007_Fire_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01320008, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CScorpman::H0x01320008_Fire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320008 +; +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +MaybeSwitchToAnotherPlayer (); +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Return(STATE_CURRENT,EReturn ()); +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CScorpman:: +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CScorpman_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CScorpman::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_SPIKEHIT , 0); +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x0132000a, FALSE, EBegin());return TRUE;}BOOL CScorpman::H0x0132000a_Hit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0132000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0132000b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CScorpman::H0x0132000b_Hit_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0132000b +; +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PlaySound (m_soSound , SOUND_KICK , SOF_3D ); +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(CalcDist (m_penEnemy ) < m_fCloseDistance ){ +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +vDirection . Normalize (); +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(m_smtType == SMT_MONSTER ){ +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 80.0f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}else if(m_smtType == SMT_GENERAL ){ +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 40.0f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}else { +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 20.0f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetTimerAfter(0.3f); +Jump(STATE_CURRENT, 0x0132000c, FALSE, EBegin());return TRUE;}BOOL CScorpman::H0x0132000c_Hit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0132000c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0132000d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CScorpman::H0x0132000d_Hit_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0132000d +; +#line 469 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +MaybeSwitchToAnotherPlayer (); +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Return(STATE_CURRENT,EReturn ()); +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CScorpman:: +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Sleep(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CScorpman_Sleep + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CScorpman::Sleep expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_SLEEP , AOF_LOOPING ); +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x0132000f, FALSE, EBegin());return TRUE;}BOOL CScorpman::H0x0132000f_Sleep_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0132000f +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetTargetSoft (eTrigger . penCaused ); +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Jump(STATE_CURRENT, STATE_CScorpman_WakeUp, TRUE, EVoid());return TRUE; +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDamage):{const EDamage&eDamage= (EDamage&)__eeInput; + +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Jump(STATE_CURRENT, STATE_CScorpman_WakeUp, TRUE, EVoid());return TRUE; +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}ASSERT(FALSE);break;default:{ +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return TRUE; +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}ASSERT(FALSE);break; +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}return TRUE;}BOOL CScorpman::H0x01320010_Sleep_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320010 + ASSERT(FALSE); return TRUE;};BOOL CScorpman:: +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +WakeUp(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CScorpman_WakeUp + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CScorpman::WakeUp expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SightSound (); +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +StartModelAnim (SCORPMAN_ANIM_WAKEUP , 0); +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetTimerAfter(GetModelObject () -> GetCurrentAnimLength ()); +Jump(STATE_CURRENT, 0x01320012, FALSE, EBegin());return TRUE;}BOOL CScorpman::H0x01320012_WakeUp_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320012 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01320013, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CScorpman::H0x01320013_WakeUp_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320013 +; +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SendToTarget (m_penDeathTarget , m_eetDeathType ); +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Return(STATE_CURRENT,EReturn ()); +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CScorpman:: +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PreMainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CScorpman_PreMainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CScorpman::PreMainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(!(m_bSleeping )){ Jump(STATE_CURRENT,0x01320017, FALSE, EInternal());return TRUE;} +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_bSleeping = FALSE ; +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01320015, FALSE, EBegin());return TRUE;}BOOL CScorpman::H0x01320015_PreMainLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320015 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Call(STATE_CURRENT, STATE_CScorpman_Sleep, TRUE, EVoid());return TRUE; +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; + +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +UnsetTimer();Jump(STATE_CURRENT,0x01320016, FALSE, EInternal());return TRUE; +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&eDeath= (EDeath&)__eeInput; + +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Die, FALSE, eDeath );return TRUE; +#line 528 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}return TRUE;}BOOL CScorpman::H0x01320016_PreMainLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320016 +Jump(STATE_CURRENT,0x01320017, FALSE, EInternal());return TRUE;}BOOL CScorpman::H0x01320017_PreMainLoop_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01320017 + +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Return(STATE_CURRENT,EReturn ()); +#line 531 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CScorpman:: +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CScorpman_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CScorpman::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +if(m_smtType == SMT_MONSTER ){ +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_smtType = SMT_GENERAL ; +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +InitAsModel (); +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetCollisionFlags (ECF_MODEL ); +#line 546 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +en_tmMaxHoldBreath = 25.0f; +#line 548 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +en_fDensity = 3000.0f; +#line 551 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetModel (MODEL_SCORPMAN ); +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +switch(m_smtType ){ +#line 553 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_SOLDIER : +#line 555 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetModelMainTexture (TEXTURE_SOLDIER ); +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetModelSpecularTexture (TEXTURE_SPECULAR ); +#line 557 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetHealth (300.0f); +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fMaxHealth = 300.0f; +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fDamageWounded = 200.0f; +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fBlowUpAmount = 1E10f; +#line 562 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fBodyParts = 30; +#line 564 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fAttackDistance = 200.0f; +#line 565 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fCloseDistance = 5.0f; +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fStopDistance = 4.5f; +#line 567 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fAttackFireTime = 0.5f; +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fCloseFireTime = 1.0f; +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fIgnoreRange = 350.0f; +#line 570 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_iScore = 1000; +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +break ; +#line 573 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_GENERAL : +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetModelMainTexture (TEXTURE_GENERAL ); +#line 576 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetModelSpecularTexture (TEXTURE_SPECULAR ); +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetHealth (600.0f); +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fMaxHealth = 600.0f; +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fDamageWounded = 400.0f; +#line 581 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fBlowUpAmount = 1E10f; +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fBodyParts = 30; +#line 584 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fAttackDistance = 200.0f; +#line 585 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fCloseDistance = 5.0f; +#line 586 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fStopDistance = 4.5f; +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fAttackFireTime = 2.0f; +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fCloseFireTime = 1.0f; +#line 589 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fIgnoreRange = 350.0f; +#line 590 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_iScore = 5000; +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +break ; +#line 593 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_MONSTER : +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetModelMainTexture (TEXTURE_GENERAL ); +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetModelSpecularTexture (TEXTURE_SPECULAR ); +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetHealth (1200.0f); +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fMaxHealth = 1200.0f; +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fDamageWounded = 800.0f; +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fBlowUpAmount = 1E10f; +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fBodyParts = 60; +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fAttackDistance = 250.0f; +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fCloseDistance = 11.0f; +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fStopDistance = 9.0f; +#line 607 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fAttackFireTime = 2.0f; +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fCloseFireTime = 1.0f; +#line 609 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fIgnoreRange = 500.0f; +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_iScore = 10000; +#line 611 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +break ; +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +AddAttachment (SCORPMAN_ATTACHMENT_MINIGUN , MODEL_GUN , TEXTURE_GUN ); +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +switch(m_smtType ){ +#line 618 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_SOLDIER : GetModelObject () -> StretchModel (FLOAT3D (1.0f , 1.0f , 1.0f) * STRETCH_SOLDIER );break ; +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_GENERAL : GetModelObject () -> StretchModel (FLOAT3D (1.0f , 1.0f , 1.0f) * STRETCH_GENERAL );break ; +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +case SMT_MONSTER : GetModelObject () -> StretchModel (FLOAT3D (1.0f , 1.0f , 1.0f) * STRETCH_MONSTER );break ; +#line 621 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 623 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +ModelChangeNotify (); +#line 626 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fWalkSpeed = FRnd () + 1.5f; +#line 627 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 20.0f + 550.0f); +#line 628 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fAttackRunSpeed = FRnd () * 1.5f + 4.5f; +#line 629 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_aAttackRotateSpeed = AngleDeg (FRnd () * 50.0f + 275.0f); +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_fCloseRunSpeed = FRnd () * 1.5f + 4.5f; +#line 631 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50.0f + 275.0f); +#line 634 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CEnemyBase :: SizeModel (); +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +SetupLightSource (); +#line 638 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +try { +#line 639 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +m_aoLightAnimation . SetData_t (CTFILENAME ("Animations\\BasicEffects.ani")); +#line 640 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +}catch (char * strError ){ +#line 641 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +WarningMessage (TRANS ("Cannot load Animations\\BasicEffects.ani: %s") , strError ); +#line 642 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +} +#line 643 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +MinigunOff (); +#line 646 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Scorpman.es b/Sources/EntitiesMP/Scorpman.es new file mode 100644 index 0000000..b0ec978 --- /dev/null +++ b/Sources/EntitiesMP/Scorpman.es @@ -0,0 +1,649 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +306 +%{ +#include "StdH.h" +#include "Models/Enemies/Scorpman/Scorpman.h" +#include "Models/Enemies/Scorpman/Gun.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/Bullet"; +uses "EntitiesMP/Reminder"; + +enum ScorpmanType { + 0 SMT_SOLDIER "Soldier", + 1 SMT_GENERAL "General", + 2 SMT_MONSTER "Obsolete", +}; + + +%{ +#define GUN_X 0.375f +#define GUN_Y 0.6f +#define GUN_Z -1.85f +#define STRETCH_SOLDIER 2 +#define STRETCH_GENERAL 3 +#define STRETCH_MONSTER 4 +// info structure +static EntityInfo eiScorpman = { + EIBT_FLESH, 1000.0f, + 0, 1.6f*STRETCH_SOLDIER, 0, // source (eyes) + 0.0f, 1.0f*STRETCH_SOLDIER, 0.0f, // target (body) +}; + +static EntityInfo eiScorpmanGeneral = { + EIBT_FLESH, 1500.0f, + 0, 1.6f*STRETCH_GENERAL, 0, // source (eyes) + 0.0f, 1.0f*STRETCH_GENERAL, 0.0f, // target (body) +}; + +static EntityInfo eiScorpmanMonster = { + EIBT_FLESH, 2000.0f, + 0, 1.6f*STRETCH_MONSTER, 0, // source (eyes) + 0.0f, 1.0f*STRETCH_MONSTER, 0.0f, // target (body) +}; +#define LIGHT_ANIM_FIRE 3 +#define LIGHT_ANIM_NONE 5 +%} + + +class CScorpman : CEnemyBase { +name "Scorpman"; +thumbnail "Thumbnails\\Scorpman.tbn"; + +properties: + 1 enum ScorpmanType m_smtType "Type" 'Y' = SMT_SOLDIER, + 2 INDEX m_bFireBulletCount = 0, // fire bullet binary divider + 3 INDEX m_iSpawnEffect = 0, // counter for spawn effect every 'x' times + 4 FLOAT m_fFireTime = 0.0f, // time to fire bullets + 5 CAnimObject m_aoLightAnimation, // light animation object + 6 BOOL m_bSleeping "Sleeping" 'S' = FALSE, // set to make scorpman sleep initally + +{ + CEntity *penBullet; // bullet + CLightSource m_lsLightSource; +} + +components: + 0 class CLASS_BASE "Classes\\EnemyBase.ecl", + 1 class CLASS_BULLET "Classes\\Bullet.ecl", + 5 model MODEL_SCORPMAN "Models\\Enemies\\Scorpman\\Scorpman.mdl", + 6 texture TEXTURE_SOLDIER "Models\\Enemies\\Scorpman\\Soldier.tex", + 7 texture TEXTURE_GENERAL "Models\\Enemies\\Scorpman\\General.tex", +// 8 texture TEXTURE_MONSTER "Models\\Enemies\\Scorpman\\Monster.tex", + 12 texture TEXTURE_SPECULAR "Models\\SpecularTextures\\Medium.tex", + 9 model MODEL_GUN "Models\\Enemies\\Scorpman\\Gun.mdl", + 10 model MODEL_FLARE "Models\\Enemies\\Scorpman\\Flare.mdl", + 11 texture TEXTURE_GUN "Models\\Enemies\\Scorpman\\Gun.tex", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "Models\\Enemies\\Scorpman\\Sounds\\Idle.wav", + 51 sound SOUND_SIGHT "Models\\Enemies\\Scorpman\\Sounds\\Sight.wav", + 52 sound SOUND_WOUND "Models\\Enemies\\Scorpman\\Sounds\\Wound.wav", + 53 sound SOUND_FIRE "Models\\Enemies\\Scorpman\\Sounds\\Fire.wav", + 54 sound SOUND_KICK "Models\\Enemies\\Scorpman\\Sounds\\Kick.wav", + 55 sound SOUND_DEATH "Models\\Enemies\\Scorpman\\Sounds\\Death.wav", + +functions: + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + if (eDeath.eLastDamage.dmtType==DMT_CLOSERANGE) { + str.PrintF(TRANS("%s was stabbed by an Arachnoid"), strPlayerName); + } else { + str.PrintF(TRANS("An Arachnoid poured lead into %s"), strPlayerName); + } + return str; + } + void Precache(void) { + CEnemyBase::Precache(); + PrecacheModel(MODEL_FLARE); + PrecacheSound(SOUND_IDLE ); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_FIRE ); + PrecacheSound(SOUND_KICK ); + PrecacheSound(SOUND_DEATH); + }; + + /* Read from stream. */ + void Read_t( CTStream *istr) { // throw char * + CEnemyBase::Read_t(istr); + + // setup light source + SetupLightSource(); + } + + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + CEnemyBase::FillEntityStatistics(pes); + switch(m_smtType) { + case SMT_MONSTER: { pes->es_strName+=" Monster"; } break; + case SMT_GENERAL: { pes->es_strName+=" General"; } break; + case SMT_SOLDIER: { pes->es_strName+=" Soldier"; } break; + } + return TRUE; + } + + virtual const CTFileName &GetComputerMessageName(void) const { + //static DECLARE_CTFILENAME(fnmMonster, "Data\\Messages\\Enemies\\ScorpmanMonster.txt"); + static DECLARE_CTFILENAME(fnmGeneral, "Data\\Messages\\Enemies\\ScorpmanGeneral.txt"); + static DECLARE_CTFILENAME(fnmSoldier, "Data\\Messages\\Enemies\\ScorpmanSoldier.txt"); + switch(m_smtType) { + default: ASSERT(FALSE); + case SMT_MONSTER: //return fnmMonster; + case SMT_GENERAL: return fnmGeneral; + case SMT_SOLDIER: return fnmSoldier; + } + }; + + /* Get static light source information. */ + CLightSource *GetLightSource(void) { + if (!IsPredictor()) { + return &m_lsLightSource; + } else { + return NULL; + } + } + + BOOL ForcesCannonballToExplode(void) + { + if (m_smtType!=SMT_SOLDIER) { + return TRUE; + } + return CEnemyBase::ForcesCannonballToExplode(); + } + + // Setup light source + void SetupLightSource(void) { + // setup light source + CLightSource lsNew; + lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC; + lsNew.ls_rHotSpot = 2.0f; + lsNew.ls_rFallOff = 8.0f; + lsNew.ls_colColor = RGBToColor(128, 128, 128); + lsNew.ls_plftLensFlare = NULL; + lsNew.ls_ubPolygonalMask = 0; + lsNew.ls_paoLightAnimation = &m_aoLightAnimation; + + m_lsLightSource.ls_penEntity = this; + m_lsLightSource.SetLightSource(lsNew); + } + // play light animation + void PlayLightAnim(INDEX iAnim, ULONG ulFlags) { + if (m_aoLightAnimation.GetData()!=NULL) { + m_aoLightAnimation.PlayAnim(iAnim, ulFlags); + } + }; + + // fire minigun on/off + void MinigunOn(void) + { + PlayLightAnim(LIGHT_ANIM_FIRE, AOF_LOOPING); + CModelObject *pmoGun = &GetModelObject()->GetAttachmentModel(SCORPMAN_ATTACHMENT_MINIGUN)-> + amo_moModelObject; + pmoGun->PlayAnim(GUN_ANIM_FIRE, AOF_LOOPING); + AddAttachmentToModel(this, *pmoGun, GUN_ATTACHMENT_FLAME, MODEL_FLARE, TEXTURE_GUN, 0, 0, 0); + switch (m_smtType) { + case SMT_SOLDIER: pmoGun->StretchModel(FLOAT3D(2.0f, 2.0f, 2.0f)); break; + case SMT_GENERAL: pmoGun->StretchModel(FLOAT3D(3.0f, 3.0f, 3.0f)); break; + case SMT_MONSTER: pmoGun->StretchModel(FLOAT3D(4.0f, 4.0f, 4.0f)); break; + } + } + void MinigunOff(void) + { + PlayLightAnim(LIGHT_ANIM_NONE, 0); + CModelObject *pmoGun = &GetModelObject()->GetAttachmentModel(SCORPMAN_ATTACHMENT_MINIGUN)-> + amo_moModelObject; + pmoGun->PlayAnim(GUN_ANIM_IDLE, AOF_LOOPING); + pmoGun->RemoveAttachmentModel(GUN_ATTACHMENT_FLAME); + } + /* Entity info */ + void *GetEntityInfo(void) { + if (m_smtType == SMT_MONSTER) { + return &eiScorpmanMonster; + } else if (m_smtType == SMT_GENERAL) { + return &eiScorpmanGeneral; + } else { + return &eiScorpman; + } + }; + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // scorpman can't harm scorpman + if (!IsOfClass(penInflictor, "Scorpman")) { + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + }; + + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim; + switch (IRnd()%3) { + case 0: iAnim = SCORPMAN_ANIM_WOUND01; break; + case 1: iAnim = SCORPMAN_ANIM_WOUND02; break; + case 2: iAnim = SCORPMAN_ANIM_WOUND03; break; + default: ASSERTALWAYS("Scorpman unknown damage"); + } + StartModelAnim(iAnim, 0); + MinigunOff(); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + StartModelAnim(SCORPMAN_ANIM_DEATH, 0); + MinigunOff(); + return SCORPMAN_ANIM_DEATH; + }; + + FLOAT WaitForDust(FLOAT3D &vStretch) { + if(GetModelObject()->GetAnim()==SCORPMAN_ANIM_DEATH) + { + vStretch=FLOAT3D(1,1,1)*1.5f; + return 1.3f; + } + return -1.0f; + }; + + void DeathNotify(void) { + ChangeCollisionBoxIndexWhenPossible(SCORPMAN_COLLISION_BOX_DEATH); + SetCollisionFlags(ECF_MODEL); + }; + + // virtual anim functions + void StandingAnim(void) { + StartModelAnim(SCORPMAN_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + void WalkingAnim(void) { + StartModelAnim(SCORPMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART); + }; + void RunningAnim(void) { + StartModelAnim(SCORPMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART); + }; + void RotatingAnim(void) { + StartModelAnim(SCORPMAN_ANIM_WALK, AOF_LOOPING|AOF_NORESTART); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + +/************************************************************ + * FIRE BULLET / RAIL * + ************************************************************/ + BOOL CanFireAtPlayer(void) + { + // get ray source and target + FLOAT3D vSource, vTarget; + GetPositionCastRay(this, m_penEnemy, vSource, vTarget); + + // bullet start position + CPlacement3D plBullet; + plBullet.pl_OrientationAngle = ANGLE3D(0,0,0); + plBullet.pl_PositionVector = FLOAT3D(GUN_X, GUN_Y, 0); + // offset are changed according to stretch factor + if (m_smtType == SMT_MONSTER) { + plBullet.pl_PositionVector*=STRETCH_MONSTER; + } else if (m_smtType == SMT_GENERAL) { + plBullet.pl_PositionVector*=STRETCH_GENERAL; + } else { + plBullet.pl_PositionVector*=STRETCH_SOLDIER; + } + plBullet.RelativeToAbsolute(GetPlacement()); + vSource = plBullet.pl_PositionVector; + + // cast the ray + CCastRay crRay(this, vSource, vTarget); + crRay.cr_ttHitModels = CCastRay::TT_NONE; // check for brushes only + crRay.cr_bHitTranslucentPortals = FALSE; + en_pwoWorld->CastRay(crRay); + + // if hit nothing (no brush) the entity can be seen + return (crRay.cr_penHit==NULL); + } + + void PrepareBullet(FLOAT fDamage) { + // bullet start position + CPlacement3D plBullet; + plBullet.pl_OrientationAngle = ANGLE3D(0,0,0); + plBullet.pl_PositionVector = FLOAT3D(GUN_X, GUN_Y, 0); + // offset are changed according to stretch factor + if (m_smtType == SMT_MONSTER) { + plBullet.pl_PositionVector*=STRETCH_MONSTER; + } else if (m_smtType == SMT_GENERAL) { + plBullet.pl_PositionVector*=STRETCH_GENERAL; + } else { + plBullet.pl_PositionVector*=STRETCH_SOLDIER; + } + plBullet.RelativeToAbsolute(GetPlacement()); + // create bullet + penBullet = CreateEntity(plBullet, CLASS_BULLET); + // init bullet + EBulletInit eInit; + eInit.penOwner = this; + eInit.fDamage = fDamage; + penBullet->Initialize(eInit); + }; + + // fire bullet + void FireBullet(void) { + // binary divide counter + m_bFireBulletCount++; + if (m_bFireBulletCount>1) { m_bFireBulletCount = 0; } + if (m_bFireBulletCount==1) { return; } + // bullet + PrepareBullet(3.0f); + ((CBullet&)*penBullet).CalcTarget(m_penEnemy, 250); + ((CBullet&)*penBullet).CalcJitterTarget(10); + ((CBullet&)*penBullet).LaunchBullet( TRUE, TRUE, TRUE); + ((CBullet&)*penBullet).DestroyBullet(); + }; + + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + // set sound default parameters + m_soSound.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + }; + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + // shoot + Fire(EVoid) : CEnemyBase::Fire{ + if (!CanFireAtPlayer()) { + return EReturn(); + } + + // confused amount + switch (m_smtType) { + case SMT_MONSTER: + m_fDamageConfused = 200; + m_fFireTime = 8.0f; + break; + case SMT_GENERAL: + m_fDamageConfused = 100; + m_fFireTime = 4.0f; + break; + case SMT_SOLDIER: + m_fDamageConfused = 50; + m_fFireTime = 2.0f; + break; + } + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + m_fFireTime *= 0.5f; + } + // to fire + StartModelAnim(SCORPMAN_ANIM_STANDTOFIRE, 0); + m_fLockOnEnemyTime = GetModelObject()->GetAnimLength(SCORPMAN_ANIM_STANDTOFIRE) + 0.5f + FRnd()/3; + autocall CEnemyBase::LockOnEnemy() EReturn; + + // fire + m_iSpawnEffect = 0; // effect every 'x' frames + m_fFireTime += _pTimer->CurrentTick(); + m_bFireBulletCount = 0; + PlaySound(m_soSound, SOUND_FIRE, SOF_3D|SOF_LOOP); + MinigunOn(); + + while (m_fFireTime > _pTimer->CurrentTick()) { + m_fMoveFrequency = 0.1f; + wait(m_fMoveFrequency) { + on (EBegin) : { + // make fuss + AddToFuss(); + // fire bullet + FireBullet(); + m_vDesiredPosition = m_penEnemy->GetPlacement().pl_PositionVector; + // rotate to enemy + if (!IsInPlaneFrustum(m_penEnemy, CosFast(5.0f))) { + m_fMoveSpeed = 0.0f; + m_aRotateSpeed = 4000.0f; + StartModelAnim(SCORPMAN_ANIM_WALK_AND_FIRE, AOF_LOOPING|AOF_NORESTART); + // stand in place + } else { + m_fMoveSpeed = 0.0f; + m_aRotateSpeed = 0.0f; + StartModelAnim(SCORPMAN_ANIM_FIRE_MINIGUN, AOF_LOOPING|AOF_NORESTART); + } + // adjust direction and speed + SetDesiredMovement(); + resume; + } + on (ETimer) : { stop; } + } + } + m_soSound.Stop(); + MinigunOff(); + // set next shoot time + m_fShootTime = _pTimer->CurrentTick() + m_fAttackFireTime*(1.0f + FRnd()/3.0f); + + // from fire + StartModelAnim(SCORPMAN_ANIM_FIRETOSTAND, 0); + autowait(GetModelObject()->GetAnimLength(SCORPMAN_ANIM_FIRETOSTAND)); + + MaybeSwitchToAnotherPlayer(); + + // shoot completed + return EReturn(); + }; + + // hit enemy + Hit(EVoid) : CEnemyBase::Hit { + // close attack + StartModelAnim(SCORPMAN_ANIM_SPIKEHIT, 0); + autowait(0.5f); + PlaySound(m_soSound, SOUND_KICK, SOF_3D); + if (CalcDist(m_penEnemy) < m_fCloseDistance) { + FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.Normalize(); + if (m_smtType == SMT_MONSTER) { + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 80.0f, FLOAT3D(0, 0, 0), vDirection); + } else if (m_smtType == SMT_GENERAL) { + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 40.0f, FLOAT3D(0, 0, 0), vDirection); + } else { + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 20.0f, FLOAT3D(0, 0, 0), vDirection); + } + } + autowait(0.3f); + MaybeSwitchToAnotherPlayer(); + return EReturn(); + }; + + Sleep(EVoid) + { + // start sleeping anim + StartModelAnim(SCORPMAN_ANIM_SLEEP, AOF_LOOPING); + // repeat + wait() { + // if triggered + on(ETrigger eTrigger) : { + // remember enemy + SetTargetSoft(eTrigger.penCaused); + // wake up + jump WakeUp(); + } + // if damaged + on(EDamage eDamage) : { + // wake up + jump WakeUp(); + } + otherwise() : { + resume; + } + } + } + + WakeUp(EVoid) + { + // wakeup anim + SightSound(); + StartModelAnim(SCORPMAN_ANIM_WAKEUP, 0); + autowait(GetModelObject()->GetCurrentAnimLength()); + + // trigger your target + SendToTarget(m_penDeathTarget, m_eetDeathType); + // proceed with normal functioning + return EReturn(); + } + + // overridable called before main enemy loop actually begins + PreMainLoop(EVoid) : CEnemyBase::PreMainLoop + { + // if sleeping + if (m_bSleeping) { + m_bSleeping = FALSE; + // go to sleep until waken up + wait() { + on (EBegin) : { + call Sleep(); + } + on (EReturn) : { + stop; + }; + // if dead + on(EDeath eDeath) : { + // die + jump CEnemyBase::Die(eDeath); + } + } + } + return EReturn(); + } + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + if (m_smtType==SMT_MONSTER) { + m_smtType=SMT_GENERAL; + } + + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + en_tmMaxHoldBreath = 25.0f; + en_fDensity = 3000.0f; + + // set your appearance + SetModel(MODEL_SCORPMAN); + switch (m_smtType) { + case SMT_SOLDIER: + // set your texture + SetModelMainTexture(TEXTURE_SOLDIER); + SetModelSpecularTexture(TEXTURE_SPECULAR); + SetHealth(300.0f); + m_fMaxHealth = 300.0f; + // damage/explode properties + m_fDamageWounded = 200.0f; + m_fBlowUpAmount = 1E10f; + m_fBodyParts = 30; + // setup attack distances + m_fAttackDistance = 200.0f; + m_fCloseDistance = 5.0f; + m_fStopDistance = 4.5f; + m_fAttackFireTime = 0.5f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 350.0f; + m_iScore = 1000; + break; + + case SMT_GENERAL: + // set your texture + SetModelMainTexture(TEXTURE_GENERAL); + SetModelSpecularTexture(TEXTURE_SPECULAR); + SetHealth(600.0f); + m_fMaxHealth = 600.0f; + // damage/explode properties + m_fDamageWounded = 400.0f; + m_fBlowUpAmount = 1E10f; + m_fBodyParts = 30; + // setup attack distances + m_fAttackDistance = 200.0f; + m_fCloseDistance = 5.0f; + m_fStopDistance = 4.5f; + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 350.0f; + m_iScore = 5000; + break; + + case SMT_MONSTER: + // set your texture + SetModelMainTexture(TEXTURE_GENERAL); + SetModelSpecularTexture(TEXTURE_SPECULAR); + SetHealth(1200.0f); + m_fMaxHealth = 1200.0f; + // damage/explode properties + m_fDamageWounded = 800.0f; + m_fBlowUpAmount = 1E10f; + m_fBodyParts = 60; + // setup attack distances + m_fAttackDistance = 250.0f; + m_fCloseDistance = 11.0f; + m_fStopDistance = 9.0f; + m_fAttackFireTime = 2.0f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 500.0f; + m_iScore = 10000; + break; + } + + AddAttachment(SCORPMAN_ATTACHMENT_MINIGUN, MODEL_GUN, TEXTURE_GUN); + + // set stretch factors for height and width - MUST BE DONE BEFORE SETTING MODEL! + switch (m_smtType) { + case SMT_SOLDIER: GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f)*STRETCH_SOLDIER); break; + case SMT_GENERAL: GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f)*STRETCH_GENERAL); break; + case SMT_MONSTER: GetModelObject()->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f)*STRETCH_MONSTER); break; + } + + ModelChangeNotify(); + + // setup moving speed + m_fWalkSpeed = FRnd() + 1.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*20.0f + 550.0f); + m_fAttackRunSpeed = FRnd()*1.5f + 4.5f; + m_aAttackRotateSpeed = AngleDeg(FRnd()*50.0f + 275.0f); + m_fCloseRunSpeed = FRnd()*1.5f + 4.5f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50.0f + 275.0f); + + // set stretch factors for height and width + CEnemyBase::SizeModel(); + // setup light source + SetupLightSource(); + // set light animation if available + try { + m_aoLightAnimation.SetData_t(CTFILENAME("Animations\\BasicEffects.ani")); + } catch (char *strError) { + WarningMessage(TRANS("Cannot load Animations\\BasicEffects.ani: %s"), strError); + } + MinigunOff(); + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + + }; +}; diff --git a/Sources/EntitiesMP/Scorpman.h b/Sources/EntitiesMP/Scorpman.h new file mode 100644 index 0000000..ce1ec42 --- /dev/null +++ b/Sources/EntitiesMP/Scorpman.h @@ -0,0 +1,162 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Scorpman_INCLUDED +#define _EntitiesMP_Scorpman_INCLUDED 1 +#include +#include +#include +extern DECL_DLL CEntityPropertyEnumType ScorpmanType_enum; +enum ScorpmanType { + SMT_SOLDIER = 0, + SMT_GENERAL = 1, + SMT_MONSTER = 2, +}; +DECL_DLL inline void ClearToDefault(ScorpmanType &e) { e = (ScorpmanType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CScorpman_DLLClass; +class CScorpman : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum ScorpmanType m_smtType; + INDEX m_bFireBulletCount; + INDEX m_iSpawnEffect; + FLOAT m_fFireTime; + CAnimObject m_aoLightAnimation; + BOOL m_bSleeping; +CEntity * penBullet; +CLightSource m_lsLightSource; + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void Precache(void); + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void Read_t(CTStream * istr); + +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +CLightSource * GetLightSource(void); + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +BOOL ForcesCannonballToExplode(void); + +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void SetupLightSource(void); + +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void PlayLightAnim(INDEX iAnim,ULONG ulFlags); + +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void MinigunOn(void); + +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void MinigunOff(void); + +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void * GetEntityInfo(void); + +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +INDEX AnimForDeath(void); + +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void DeathNotify(void); + +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void StandingAnim(void); + +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void WalkingAnim(void); + +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void RunningAnim(void); + +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void RotatingAnim(void); + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void IdleSound(void); + +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void SightSound(void); + +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void WoundSound(void); + +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void DeathSound(void); + +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +BOOL CanFireAtPlayer(void); + +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void PrepareBullet(FLOAT fDamage); + +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void FireBullet(void); + +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +void EnemyPostInit(void); +#define STATE_CScorpman_Fire 0x01320000 + BOOL +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x01320001_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x01320002_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x01320003_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x01320004_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x01320005_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x01320006_Fire_06(const CEntityEvent &__eeInput); + BOOL H0x01320007_Fire_07(const CEntityEvent &__eeInput); + BOOL H0x01320008_Fire_08(const CEntityEvent &__eeInput); +#define STATE_CScorpman_Hit 0x01320009 + BOOL +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Hit(const CEntityEvent &__eeInput); + BOOL H0x0132000a_Hit_01(const CEntityEvent &__eeInput); + BOOL H0x0132000b_Hit_02(const CEntityEvent &__eeInput); + BOOL H0x0132000c_Hit_03(const CEntityEvent &__eeInput); + BOOL H0x0132000d_Hit_04(const CEntityEvent &__eeInput); +#define STATE_CScorpman_Sleep 0x0132000e + BOOL +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Sleep(const CEntityEvent &__eeInput); + BOOL H0x0132000f_Sleep_01(const CEntityEvent &__eeInput); + BOOL H0x01320010_Sleep_02(const CEntityEvent &__eeInput); +#define STATE_CScorpman_WakeUp 0x01320011 + BOOL +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +WakeUp(const CEntityEvent &__eeInput); + BOOL H0x01320012_WakeUp_01(const CEntityEvent &__eeInput); + BOOL H0x01320013_WakeUp_02(const CEntityEvent &__eeInput); +#define STATE_CScorpman_PreMainLoop 0x01320014 + BOOL +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PreMainLoop(const CEntityEvent &__eeInput); + BOOL H0x01320015_PreMainLoop_01(const CEntityEvent &__eeInput); + BOOL H0x01320016_PreMainLoop_02(const CEntityEvent &__eeInput); + BOOL H0x01320017_PreMainLoop_03(const CEntityEvent &__eeInput); +#define STATE_CScorpman_Main 1 + BOOL +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Scorpman_INCLUDED diff --git a/Sources/EntitiesMP/Scorpman_tables.h b/Sources/EntitiesMP/Scorpman_tables.h new file mode 100644 index 0000000..18f8449 --- /dev/null +++ b/Sources/EntitiesMP/Scorpman_tables.h @@ -0,0 +1,107 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(ScorpmanType) + EP_ENUMVALUE(SMT_SOLDIER, "Soldier"), + EP_ENUMVALUE(SMT_GENERAL, "General"), + EP_ENUMVALUE(SMT_MONSTER, "Obsolete"), +EP_ENUMEND(ScorpmanType); + +#define ENTITYCLASS CScorpman + +CEntityProperty CScorpman_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &ScorpmanType_enum, (0x00000132<<8)+1, offsetof(CScorpman, m_smtType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000132<<8)+2, offsetof(CScorpman, m_bFireBulletCount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000132<<8)+3, offsetof(CScorpman, m_iSpawnEffect), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000132<<8)+4, offsetof(CScorpman, m_fFireTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ANIMOBJECT, NULL, (0x00000132<<8)+5, offsetof(CScorpman, m_aoLightAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000132<<8)+6, offsetof(CScorpman, m_bSleeping), "Sleeping", 'S', 0x7F0000FFUL, 0), +}; +#define CScorpman_propertiesct ARRAYCOUNT(CScorpman_properties) + +CEntityComponent CScorpman_components[] = { +#define CLASS_BASE ((0x00000132<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_BULLET ((0x00000132<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BULLET, "EFNM" "Classes\\Bullet.ecl"), +#define MODEL_SCORPMAN ((0x00000132<<8)+5) + CEntityComponent(ECT_MODEL, MODEL_SCORPMAN, "EFNM" "Models\\Enemies\\Scorpman\\Scorpman.mdl"), +#define TEXTURE_SOLDIER ((0x00000132<<8)+6) + CEntityComponent(ECT_TEXTURE, TEXTURE_SOLDIER, "EFNM" "Models\\Enemies\\Scorpman\\Soldier.tex"), +#define TEXTURE_GENERAL ((0x00000132<<8)+7) + CEntityComponent(ECT_TEXTURE, TEXTURE_GENERAL, "EFNM" "Models\\Enemies\\Scorpman\\General.tex"), +#define TEXTURE_SPECULAR ((0x00000132<<8)+12) + CEntityComponent(ECT_TEXTURE, TEXTURE_SPECULAR, "EFNM" "Models\\SpecularTextures\\Medium.tex"), +#define MODEL_GUN ((0x00000132<<8)+9) + CEntityComponent(ECT_MODEL, MODEL_GUN, "EFNM" "Models\\Enemies\\Scorpman\\Gun.mdl"), +#define MODEL_FLARE ((0x00000132<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_FLARE, "EFNM" "Models\\Enemies\\Scorpman\\Flare.mdl"), +#define TEXTURE_GUN ((0x00000132<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_GUN, "EFNM" "Models\\Enemies\\Scorpman\\Gun.tex"), +#define SOUND_IDLE ((0x00000132<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "Models\\Enemies\\Scorpman\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000132<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "Models\\Enemies\\Scorpman\\Sounds\\Sight.wav"), +#define SOUND_WOUND ((0x00000132<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "Models\\Enemies\\Scorpman\\Sounds\\Wound.wav"), +#define SOUND_FIRE ((0x00000132<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_FIRE, "EFNM" "Models\\Enemies\\Scorpman\\Sounds\\Fire.wav"), +#define SOUND_KICK ((0x00000132<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_KICK, "EFNM" "Models\\Enemies\\Scorpman\\Sounds\\Kick.wav"), +#define SOUND_DEATH ((0x00000132<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "Models\\Enemies\\Scorpman\\Sounds\\Death.wav"), +}; +#define CScorpman_componentsct ARRAYCOUNT(CScorpman_components) + +CEventHandlerEntry CScorpman_handlers[] = { + {0x01320000, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CScorpman:: +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Fire),DEBUGSTRING("CScorpman::Fire")}, + {0x01320001, -1, CEntity::pEventHandler(&CScorpman::H0x01320001_Fire_01), DEBUGSTRING("CScorpman::H0x01320001_Fire_01")}, + {0x01320002, -1, CEntity::pEventHandler(&CScorpman::H0x01320002_Fire_02), DEBUGSTRING("CScorpman::H0x01320002_Fire_02")}, + {0x01320003, -1, CEntity::pEventHandler(&CScorpman::H0x01320003_Fire_03), DEBUGSTRING("CScorpman::H0x01320003_Fire_03")}, + {0x01320004, -1, CEntity::pEventHandler(&CScorpman::H0x01320004_Fire_04), DEBUGSTRING("CScorpman::H0x01320004_Fire_04")}, + {0x01320005, -1, CEntity::pEventHandler(&CScorpman::H0x01320005_Fire_05), DEBUGSTRING("CScorpman::H0x01320005_Fire_05")}, + {0x01320006, -1, CEntity::pEventHandler(&CScorpman::H0x01320006_Fire_06), DEBUGSTRING("CScorpman::H0x01320006_Fire_06")}, + {0x01320007, -1, CEntity::pEventHandler(&CScorpman::H0x01320007_Fire_07), DEBUGSTRING("CScorpman::H0x01320007_Fire_07")}, + {0x01320008, -1, CEntity::pEventHandler(&CScorpman::H0x01320008_Fire_08), DEBUGSTRING("CScorpman::H0x01320008_Fire_08")}, + {0x01320009, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CScorpman:: +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Hit),DEBUGSTRING("CScorpman::Hit")}, + {0x0132000a, -1, CEntity::pEventHandler(&CScorpman::H0x0132000a_Hit_01), DEBUGSTRING("CScorpman::H0x0132000a_Hit_01")}, + {0x0132000b, -1, CEntity::pEventHandler(&CScorpman::H0x0132000b_Hit_02), DEBUGSTRING("CScorpman::H0x0132000b_Hit_02")}, + {0x0132000c, -1, CEntity::pEventHandler(&CScorpman::H0x0132000c_Hit_03), DEBUGSTRING("CScorpman::H0x0132000c_Hit_03")}, + {0x0132000d, -1, CEntity::pEventHandler(&CScorpman::H0x0132000d_Hit_04), DEBUGSTRING("CScorpman::H0x0132000d_Hit_04")}, + {0x0132000e, -1, CEntity::pEventHandler(&CScorpman:: +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Sleep),DEBUGSTRING("CScorpman::Sleep")}, + {0x0132000f, -1, CEntity::pEventHandler(&CScorpman::H0x0132000f_Sleep_01), DEBUGSTRING("CScorpman::H0x0132000f_Sleep_01")}, + {0x01320010, -1, CEntity::pEventHandler(&CScorpman::H0x01320010_Sleep_02), DEBUGSTRING("CScorpman::H0x01320010_Sleep_02")}, + {0x01320011, -1, CEntity::pEventHandler(&CScorpman:: +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +WakeUp),DEBUGSTRING("CScorpman::WakeUp")}, + {0x01320012, -1, CEntity::pEventHandler(&CScorpman::H0x01320012_WakeUp_01), DEBUGSTRING("CScorpman::H0x01320012_WakeUp_01")}, + {0x01320013, -1, CEntity::pEventHandler(&CScorpman::H0x01320013_WakeUp_02), DEBUGSTRING("CScorpman::H0x01320013_WakeUp_02")}, + {0x01320014, STATE_CEnemyBase_PreMainLoop, CEntity::pEventHandler(&CScorpman:: +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +PreMainLoop),DEBUGSTRING("CScorpman::PreMainLoop")}, + {0x01320015, -1, CEntity::pEventHandler(&CScorpman::H0x01320015_PreMainLoop_01), DEBUGSTRING("CScorpman::H0x01320015_PreMainLoop_01")}, + {0x01320016, -1, CEntity::pEventHandler(&CScorpman::H0x01320016_PreMainLoop_02), DEBUGSTRING("CScorpman::H0x01320016_PreMainLoop_02")}, + {0x01320017, -1, CEntity::pEventHandler(&CScorpman::H0x01320017_PreMainLoop_03), DEBUGSTRING("CScorpman::H0x01320017_PreMainLoop_03")}, + {1, -1, CEntity::pEventHandler(&CScorpman:: +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/Scorpman.es" +Main),DEBUGSTRING("CScorpman::Main")}, +}; +#define CScorpman_handlersct ARRAYCOUNT(CScorpman_handlers) + +CEntity *CScorpman_New(void) { return new CScorpman; }; +void CScorpman_OnInitClass(void) {}; +void CScorpman_OnEndClass(void) {}; +void CScorpman_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CScorpman_OnWorldEnd(CWorld *pwo) {}; +void CScorpman_OnWorldInit(CWorld *pwo) {}; +void CScorpman_OnWorldTick(CWorld *pwo) {}; +void CScorpman_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CScorpman, CEnemyBase, "Scorpman", "Thumbnails\\Scorpman.tbn", 0x00000132); +DECLARE_CTFILENAME(_fnmCScorpman_tbn, "Thumbnails\\Scorpman.tbn"); diff --git a/Sources/EntitiesMP/ScrollHolder.cpp b/Sources/EntitiesMP/ScrollHolder.cpp new file mode 100644 index 0000000..4384dc2 --- /dev/null +++ b/Sources/EntitiesMP/ScrollHolder.cpp @@ -0,0 +1,413 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" + +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" + +#include +#include +#line 10 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" + +#define CT_LINESONSCREEN 18 // this number must be fixed due to desinchronisation in different resolutions +static CStaticStackArray _astrCredits; +static CTFileName _fnLastLoaded; + +void CScrollHolder::SetDefaultProperties(void) { + m_strName = "Scroll holder"; + m_strDescription = ""; + m_fnmMessage = CTString(""); + m_fMyTimer = 0.0f; + m_fMyTimerLast = 0.0f; + m_fSpeed = 1.0f; + m_penEndCreditsTrigger = NULL; + m_bDataError = FALSE ; + CRationalEntity::SetDefaultProperties(); +} + +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +const CTString & CScrollHolder::GetDescription(void)const { +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +((CTString &) m_strDescription ) . PrintF ("%s" , m_fnmMessage . FileName ()); +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return m_strDescription ; +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} + CScrollHolder::CScrollHolder(void) +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +bDataLoaded = FALSE ; +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} + +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +BOOL CScrollHolder::ReloadData(void) +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +m_bDataError = FALSE ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +if(! Credits_On (m_fnmMessage )) +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +Credits_Off (); +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return FALSE ; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return TRUE ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +BOOL CScrollHolder::LoadOneFile(const CTFileName & fnm) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +if(fnm == ""){return FALSE ;} +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +try +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +CTFileStream strm ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +strm . Open_t (fnm ); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +INDEX ctLines = 0; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +while(! strm . AtEOF ()) +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +CTString strLine ; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +strm . GetLine_t (strLine ); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +ctLines ++; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +strm . SetPos_t (0); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +CTString * astr = _astrCredits . Push (ctLines ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +for(INDEX iLine = 0;iLine < ctLines && ! strm . AtEOF ();iLine ++) +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +strm . GetLine_t (astr [ iLine ]); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +strm . Close (); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return TRUE ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +catch (char * strError ) +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +CPrintF ("%s\n" , strError ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return FALSE ; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +_fnLastLoaded = fnm ; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +BOOL CScrollHolder::Credits_On(CTFileName fnScrollText) +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +_astrCredits . PopAll (); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return LoadOneFile (fnScrollText ); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} + +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +void CScrollHolder::Credits_Off(void) +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +_astrCredits . Clear (); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} + +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +FLOAT CScrollHolder::Credits_Render(CScrollHolder * penThis,CDrawPort * pdp) +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +if(m_bDataError ){return 0;} +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +if(! bDataLoaded ){ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +if(! ReloadData ()){ +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +m_bDataError = TRUE ; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return 0; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +bDataLoaded = TRUE ; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return 1; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +PIX pixW = 0; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +PIX pixH = 0; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +PIX pixJ = 0; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +FLOAT fResolutionScaling ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +PIX pixLineHeight ; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +CTString strEmpty ; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +FLOAT fTime = Lerp (m_fMyTimerLast , m_fMyTimer , _pTimer -> GetLerpFactor ()); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +CDrawPort * pdpCurr = pdp ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pdp -> Unlock (); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pdpCurr -> Lock (); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pixW = pdpCurr -> GetWidth (); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pixH = pdpCurr -> GetHeight (); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +fResolutionScaling = (FLOAT) pixH / 360.0f; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pdpCurr -> SetFont (_pfdDisplayFont ); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pixLineHeight = floor (20 * fResolutionScaling ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +const FLOAT fLinesPerSecond = penThis -> m_fSpeed ; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +FLOAT fOffset = fTime * fLinesPerSecond ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +INDEX ctLinesOnScreen = pixH / pixLineHeight ; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +INDEX iLine1 = fOffset ; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pixJ = iLine1 * pixLineHeight - fOffset * pixLineHeight ; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +iLine1 -= ctLinesOnScreen ; +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +INDEX ctLines = _astrCredits . Count (); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +BOOL bOver = TRUE ; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +for(INDEX i = iLine1 ;i < iLine1 + ctLinesOnScreen + 1;i ++){ +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +CTString * pstr = & strEmpty ; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +INDEX iLine = i ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +if(iLine >= 0 && iLine < ctLines ){ +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pstr = & _astrCredits [ iLine ]; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +bOver = FALSE ; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pdp -> SetFont (_pfdDisplayFont ); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pdp -> SetTextScaling (fResolutionScaling ); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pdp -> SetTextAspect (1.0f); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pdp -> PutTextC (* pstr , pixW / 2 , pixJ , C_WHITE | 255); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pixJ += pixLineHeight ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pdpCurr -> Unlock (); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pdp -> Lock (); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +if(bOver ){ +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return 0; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +}else if(ctLines - iLine1 < ctLinesOnScreen ){ +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return FLOAT (ctLines - iLine1 ) / ctLinesOnScreen ; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +}else { +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return 1; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +BOOL CScrollHolder:: +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +WaitScrollingToEnd(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CScrollHolder_WaitScrollingToEnd + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CScrollHolder::WaitScrollingToEnd expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +Jump(STATE_CURRENT,0x00ee0003, FALSE, EInternal());return TRUE;}BOOL CScrollHolder::H0x00ee0003_WaitScrollingToEnd_03(const CEntityEvent &__eeInput) +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ee0003 +if(!(m_fMyTimer < (_astrCredits . Count () + CT_LINESONSCREEN ) * m_fSpeed )){ Jump(STATE_CURRENT,0x00ee0004, FALSE, EInternal());return TRUE;} +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x00ee0001, FALSE, EBegin());return TRUE;}BOOL CScrollHolder::H0x00ee0001_WaitScrollingToEnd_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ee0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00ee0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CScrollHolder::H0x00ee0002_WaitScrollingToEnd_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ee0002 +; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +m_fMyTimerLast = m_fMyTimer ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +m_fMyTimer += _pTimer -> TickQuantum / _pNetwork -> GetRealTimeFactor ();Jump(STATE_CURRENT,0x00ee0003, FALSE, EInternal());return TRUE; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +}BOOL CScrollHolder::H0x00ee0004_WaitScrollingToEnd_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ee0004 + +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +Return(STATE_CURRENT,EStop ()); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CScrollHolder:: +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CScrollHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CScrollHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +InitAsEditorModel (); +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +SetModel (MODEL_MARKER ); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x00ee0005, FALSE, EBegin());return TRUE;}BOOL CScrollHolder::H0x00ee0005_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ee0005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00ee0006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CScrollHolder::H0x00ee0006_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ee0006 +; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +if(! Credits_On (m_fnmMessage )) +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +Credits_Off (); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return TRUE; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +m_bDataError = FALSE ; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00ee0007, FALSE, EBegin());return TRUE;}BOOL CScrollHolder::H0x00ee0007_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ee0007 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EStart): +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{const EStart&eStart= (EStart&)__eeInput; + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +if(pwsc != NULL ) +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +m_fMyTimer = 0; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +m_fMyTimerLast = 0; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +EScroll escr ; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +escr . bStart = TRUE ; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +escr . penSender = this ; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pwsc -> SendEvent (escr ); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +Call(STATE_CURRENT, STATE_CScrollHolder_WaitScrollingToEnd, TRUE, EVoid());return TRUE; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop): +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{const EStop&eStop= (EStop&)__eeInput; + +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +if(pwsc != NULL ) +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +{ +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +EScroll escr ; +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +escr . bStart = FALSE ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +escr . penSender = this ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +pwsc -> SendEvent (escr ); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +UnsetTimer();Jump(STATE_CURRENT,0x00ee0008, FALSE, EInternal());return TRUE; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +}return TRUE;}BOOL CScrollHolder::H0x00ee0008_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ee0008 + +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +Credits_Off (); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +if(m_penEndCreditsTrigger ){ +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +SendToTarget (m_penEndCreditsTrigger , EET_TRIGGER , FixupCausedToPlayer (this , NULL , FALSE )); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +} +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ScrollHolder.es b/Sources/EntitiesMP/ScrollHolder.es new file mode 100644 index 0000000..e2fe72e --- /dev/null +++ b/Sources/EntitiesMP/ScrollHolder.es @@ -0,0 +1,251 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +238 +%{ +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" +%} + +%{ +#define CT_LINESONSCREEN 18 // this number must be fixed due to desinchronisation in different resolutions +static CStaticStackArray _astrCredits; +static CTFileName _fnLastLoaded; +%} + +class CScrollHolder: CRationalEntity { +name "ScrollHolder"; +thumbnail "Thumbnails\\ScrollHolder.tbn"; +features "IsTargetable", "HasName", "IsImportant"; + +properties: + + 1 CTString m_strName "Name" 'N' = "Scroll holder", + 2 CTString m_strDescription = "", + 3 CTFileName m_fnmMessage "Scroll Text" 'T' = CTString(""), + 4 FLOAT m_fMyTimer = 0.0f, // time when started + 6 FLOAT m_fMyTimerLast = 0.0f, + 5 FLOAT m_fSpeed = 1.0f, + 15 CEntityPointer m_penEndCreditsTrigger "EndScroll trigger", + + 20 BOOL m_bDataError = FALSE, + { + BOOL bDataLoaded; + } + + +components: + 1 model MODEL_MARKER "Models\\Editor\\MessageHolder.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\MessageHolder.tex" + +functions: + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("%s", m_fnmMessage.FileName()); + return m_strDescription; + } + + void CScrollHolder(void) + { + bDataLoaded = FALSE; + } + + BOOL ReloadData(void) + { + m_bDataError = FALSE; + if (!Credits_On(m_fnmMessage)) + { + Credits_Off(); + return FALSE; + } + return TRUE; + } + + BOOL LoadOneFile(const CTFileName &fnm) + { + if(fnm=="") { return FALSE; } + try + { + // open the file + CTFileStream strm; + strm.Open_t(fnm); + + // count number of lines + INDEX ctLines = 0; + while(!strm.AtEOF()) + { + CTString strLine; + strm.GetLine_t(strLine); + ctLines++; + } + strm.SetPos_t(0); + + // allocate that much + CTString *astr = _astrCredits.Push(ctLines); + // load all lines + for(INDEX iLine = 0; iLineGetLerpFactor()); + CDrawPort *pdpCurr=pdp; + + pdp->Unlock(); + pdpCurr->Lock(); + + + pixW = pdpCurr->GetWidth(); + pixH = pdpCurr->GetHeight(); + fResolutionScaling = (FLOAT)pixH / 360.0f; + pdpCurr->SetFont( _pfdDisplayFont); + pixLineHeight = floor(20*fResolutionScaling); + + const FLOAT fLinesPerSecond = penThis->m_fSpeed; + FLOAT fOffset = fTime*fLinesPerSecond; + INDEX ctLinesOnScreen = pixH/pixLineHeight; + INDEX iLine1 = fOffset; + + pixJ = iLine1*pixLineHeight-fOffset*pixLineHeight; + iLine1-=ctLinesOnScreen; + + INDEX ctLines = _astrCredits.Count(); + BOOL bOver = TRUE; + + for (INDEX i = iLine1; i=0 && iLineSetFont( _pfdDisplayFont); + pdp->SetTextScaling( fResolutionScaling); + pdp->SetTextAspect( 1.0f); + pdp->PutTextC( *pstr, pixW/2, pixJ, C_WHITE|255); + pixJ+=pixLineHeight; + } + + pdpCurr->Unlock(); + pdp->Lock(); + + if (bOver) { + return 0; + } else if (ctLines-iLine1TickQuantum); + m_fMyTimerLast = m_fMyTimer; + m_fMyTimer+=_pTimer->TickQuantum/_pNetwork->GetRealTimeFactor(); + } + return EStop(); + } + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + autowait(0.05f); + + if( !Credits_On(m_fnmMessage)) + { + Credits_Off(); + return; + } + m_bDataError = FALSE; + + wait() { + on (EStart eStart): + { + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL) + { + m_fMyTimer = 0; + m_fMyTimerLast = 0; + EScroll escr; + escr.bStart=TRUE; + escr.penSender=this; + pwsc->SendEvent(escr); + } + call WaitScrollingToEnd(); + } + on (EStop eStop): + { + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL) + { + EScroll escr; + escr.bStart=FALSE; + escr.penSender=this; + pwsc->SendEvent(escr); + } + stop; + } + } + Credits_Off(); + if (m_penEndCreditsTrigger) { + SendToTarget(m_penEndCreditsTrigger, EET_TRIGGER, FixupCausedToPlayer(this, NULL, FALSE)); + } + return; + } +}; + diff --git a/Sources/EntitiesMP/ScrollHolder.h b/Sources/EntitiesMP/ScrollHolder.h new file mode 100644 index 0000000..0f3aa55 --- /dev/null +++ b/Sources/EntitiesMP/ScrollHolder.h @@ -0,0 +1,59 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ScrollHolder_INCLUDED +#define _EntitiesMP_ScrollHolder_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CScrollHolder_DLLClass; +class CScrollHolder : public CRationalEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CTFileName m_fnmMessage; + FLOAT m_fMyTimer; + FLOAT m_fMyTimerLast; + FLOAT m_fSpeed; + CEntityPointer m_penEndCreditsTrigger; + BOOL m_bDataError; +BOOL bDataLoaded; + +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +const CTString & GetDescription(void)const; + CScrollHolder(void); + +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +BOOL ReloadData(void); + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +BOOL LoadOneFile(const CTFileName & fnm); + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +BOOL Credits_On(CTFileName fnScrollText); + +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +void Credits_Off(void); + +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +FLOAT Credits_Render(CScrollHolder * penThis,CDrawPort * pdp); +#define STATE_CScrollHolder_WaitScrollingToEnd 0x00ee0000 + BOOL +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +WaitScrollingToEnd(const CEntityEvent &__eeInput); + BOOL H0x00ee0001_WaitScrollingToEnd_01(const CEntityEvent &__eeInput); + BOOL H0x00ee0002_WaitScrollingToEnd_02(const CEntityEvent &__eeInput); + BOOL H0x00ee0003_WaitScrollingToEnd_03(const CEntityEvent &__eeInput); + BOOL H0x00ee0004_WaitScrollingToEnd_04(const CEntityEvent &__eeInput); +#define STATE_CScrollHolder_Main 1 + BOOL +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00ee0005_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00ee0006_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00ee0007_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00ee0008_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ScrollHolder_INCLUDED diff --git a/Sources/EntitiesMP/ScrollHolder_tables.h b/Sources/EntitiesMP/ScrollHolder_tables.h new file mode 100644 index 0000000..d86afd0 --- /dev/null +++ b/Sources/EntitiesMP/ScrollHolder_tables.h @@ -0,0 +1,54 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CScrollHolder + +CEntityProperty CScrollHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ee<<8)+1, offsetof(CScrollHolder, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ee<<8)+2, offsetof(CScrollHolder, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000ee<<8)+3, offsetof(CScrollHolder, m_fnmMessage), "Scroll Text", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ee<<8)+4, offsetof(CScrollHolder, m_fMyTimer), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ee<<8)+6, offsetof(CScrollHolder, m_fMyTimerLast), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ee<<8)+5, offsetof(CScrollHolder, m_fSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000ee<<8)+15, offsetof(CScrollHolder, m_penEndCreditsTrigger), "EndScroll trigger", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000ee<<8)+20, offsetof(CScrollHolder, m_bDataError), "", 0, 0, 0), +}; +#define CScrollHolder_propertiesct ARRAYCOUNT(CScrollHolder_properties) + +CEntityComponent CScrollHolder_components[] = { +#define MODEL_MARKER ((0x000000ee<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\MessageHolder.mdl"), +#define TEXTURE_MARKER ((0x000000ee<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\MessageHolder.tex"), +}; +#define CScrollHolder_componentsct ARRAYCOUNT(CScrollHolder_components) + +CEventHandlerEntry CScrollHolder_handlers[] = { + {0x00ee0000, -1, CEntity::pEventHandler(&CScrollHolder:: +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +WaitScrollingToEnd),DEBUGSTRING("CScrollHolder::WaitScrollingToEnd")}, + {0x00ee0001, -1, CEntity::pEventHandler(&CScrollHolder::H0x00ee0001_WaitScrollingToEnd_01), DEBUGSTRING("CScrollHolder::H0x00ee0001_WaitScrollingToEnd_01")}, + {0x00ee0002, -1, CEntity::pEventHandler(&CScrollHolder::H0x00ee0002_WaitScrollingToEnd_02), DEBUGSTRING("CScrollHolder::H0x00ee0002_WaitScrollingToEnd_02")}, + {0x00ee0003, -1, CEntity::pEventHandler(&CScrollHolder::H0x00ee0003_WaitScrollingToEnd_03), DEBUGSTRING("CScrollHolder::H0x00ee0003_WaitScrollingToEnd_03")}, + {0x00ee0004, -1, CEntity::pEventHandler(&CScrollHolder::H0x00ee0004_WaitScrollingToEnd_04), DEBUGSTRING("CScrollHolder::H0x00ee0004_WaitScrollingToEnd_04")}, + {1, -1, CEntity::pEventHandler(&CScrollHolder:: +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/ScrollHolder.es" +Main),DEBUGSTRING("CScrollHolder::Main")}, + {0x00ee0005, -1, CEntity::pEventHandler(&CScrollHolder::H0x00ee0005_Main_01), DEBUGSTRING("CScrollHolder::H0x00ee0005_Main_01")}, + {0x00ee0006, -1, CEntity::pEventHandler(&CScrollHolder::H0x00ee0006_Main_02), DEBUGSTRING("CScrollHolder::H0x00ee0006_Main_02")}, + {0x00ee0007, -1, CEntity::pEventHandler(&CScrollHolder::H0x00ee0007_Main_03), DEBUGSTRING("CScrollHolder::H0x00ee0007_Main_03")}, + {0x00ee0008, -1, CEntity::pEventHandler(&CScrollHolder::H0x00ee0008_Main_04), DEBUGSTRING("CScrollHolder::H0x00ee0008_Main_04")}, +}; +#define CScrollHolder_handlersct ARRAYCOUNT(CScrollHolder_handlers) + +CEntity *CScrollHolder_New(void) { return new CScrollHolder; }; +void CScrollHolder_OnInitClass(void) {}; +void CScrollHolder_OnEndClass(void) {}; +void CScrollHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CScrollHolder_OnWorldEnd(CWorld *pwo) {}; +void CScrollHolder_OnWorldInit(CWorld *pwo) {}; +void CScrollHolder_OnWorldTick(CWorld *pwo) {}; +void CScrollHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CScrollHolder, CRationalEntity, "ScrollHolder", "Thumbnails\\ScrollHolder.tbn", 0x000000ee); +DECLARE_CTFILENAME(_fnmCScrollHolder_tbn, "Thumbnails\\ScrollHolder.tbn"); diff --git a/Sources/EntitiesMP/SeriousBomb.cpp b/Sources/EntitiesMP/SeriousBomb.cpp new file mode 100644 index 0000000..5b5e984 --- /dev/null +++ b/Sources/EntitiesMP/SeriousBomb.cpp @@ -0,0 +1,185 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" + +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/EnemyBase.h" + +#include +#include +CEntityEvent *ESeriousBomb::MakeCopy(void) { CEntityEvent *peeCopy = new ESeriousBomb(*this); return peeCopy;} +ESeriousBomb::ESeriousBomb() : CEntityEvent(EVENTCODE_ESeriousBomb) {; + ClearToDefault(penOwner); +}; +#line 16 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" + +void CSeriousBomb_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + pdec-> PrecacheSound(SOUND_BLOW); +}; + +void CSeriousBomb::SetDefaultProperties(void) { + m_penOwner = NULL; + m_soBlow.SetOwner(this); +m_soBlow.Stop_internal(); + CRationalEntity::SetDefaultProperties(); +} + +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +void CSeriousBomb::ShakeItBaby(FLOAT tmShaketime,FLOAT fPower,FLOAT fFade,BOOL bFadeIn) +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +{ +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +if(pwsc != NULL ){ +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_tmShakeStarted = tmShaketime ; +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_vShakePos = GetPlacement () . pl_PositionVector ; +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_fShakeFalloff = 450.0f; +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_fShakeFade = fFade ; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_fShakeIntensityZ = 0; +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_tmShakeFrequencyZ = 5.0f; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_fShakeIntensityY = 0.1f * fPower ; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_tmShakeFrequencyY = 5.0f; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_fShakeIntensityB = 2.5f * fPower ; +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_tmShakeFrequencyB = 7.2f; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_bShakeFadeIn = bFadeIn ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +} +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +} + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +void CSeriousBomb::Glare(FLOAT fStart,FLOAT fEnd,FLOAT fFinR,FLOAT fFoutR) +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +{ +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +if(pwsc != NULL ) +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +{ +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_colGlade = C_WHITE ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_tmGlaringStarted = _pTimer -> CurrentTick () + fStart ; +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_tmGlaringEnded = pwsc -> m_tmGlaringStarted + fEnd ; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_fGlaringFadeInRatio = fFinR ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +pwsc -> m_fGlaringFadeOutRatio = fFoutR ; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +} +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +} + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +void CSeriousBomb::ExplodeBomb(void) +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +{ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +{FOREACHINDYNAMICCONTAINER (this -> GetWorld () -> wo_cenEntities , CEntity , iten ){ +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +CEntity * pen = iten ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +if(IsDerivedFromClass (pen , "Enemy Base")){ +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +CEnemyBase * penEnemy = (CEnemyBase *) pen ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +if(penEnemy -> m_bBoss == TRUE || DistanceTo (this , penEnemy ) > 250.0f){ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +continue ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +} +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +this -> InflictDirectDamage (pen , this , DMT_EXPLOSION , penEnemy -> GetHealth () + 100.0f , pen -> GetPlacement () . pl_PositionVector , FLOAT3D (0 , 1 , 0)); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +} +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +}} +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +} +BOOL CSeriousBomb:: +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSeriousBomb_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_ESeriousBomb, "CSeriousBomb::Main expects 'ESeriousBomb' as input!"); const ESeriousBomb &esb = (const ESeriousBomb &)__eeInput; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +InitAsVoid (); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +if(!(esb . penOwner )){ Jump(STATE_CURRENT,0x01620007, FALSE, EInternal());return TRUE;} +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +m_penOwner = esb . penOwner ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +m_soBlow . Set3DParameters (500.0f , 250.0f , 3.0f , 1.0f); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +PlaySound (m_soBlow , SOUND_BLOW , SOF_3D ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +if(_pNetwork -> IsPlayerLocal (m_penOwner )){IFeel_PlayEffect ("SeriousBombBlow");} +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +Glare (1.0f , 2.8f , 0.3f , 0.3f); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +ShakeItBaby (_pTimer -> CurrentTick () , 4.0f , 1.0f , TRUE ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +SetTimerAfter(1.5f); +Jump(STATE_CURRENT, 0x01620001, FALSE, EBegin());return TRUE;}BOOL CSeriousBomb::H0x01620001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01620001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01620002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSeriousBomb::H0x01620002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01620002 +; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +ShakeItBaby (_pTimer -> CurrentTick () , 8.0f , 2.0f , FALSE ); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +ExplodeBomb (); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x01620003, FALSE, EBegin());return TRUE;}BOOL CSeriousBomb::H0x01620003_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01620003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01620004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSeriousBomb::H0x01620004_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01620004 +; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +ExplodeBomb (); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +SetTimerAfter(1.75f); +Jump(STATE_CURRENT, 0x01620005, FALSE, EBegin());return TRUE;}BOOL CSeriousBomb::H0x01620005_Main_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01620005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01620006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSeriousBomb::H0x01620006_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01620006 +;Jump(STATE_CURRENT,0x01620007, FALSE, EInternal());return TRUE;}BOOL CSeriousBomb::H0x01620007_Main_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01620007 + +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +Destroy (); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +Return(STATE_CURRENT,EVoid()); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/SeriousBomb.es b/Sources/EntitiesMP/SeriousBomb.es new file mode 100644 index 0000000..a0d4bc4 --- /dev/null +++ b/Sources/EntitiesMP/SeriousBomb.es @@ -0,0 +1,126 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +354 +%{ +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/EnemyBase.h" +%} + +// event for initialisation +event ESeriousBomb { + CEntityPointer penOwner, +}; + +%{ +void CSeriousBomb_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + pdec-> PrecacheSound(SOUND_BLOW); +}; +%} + +class CSeriousBomb : CRationalEntity { +name "Serious Bomb"; +thumbnail ""; +features "ImplementsOnPrecache"; + +properties: + 1 CEntityPointer m_penOwner, // entity which owns it + 20 CSoundObject m_soBlow, + +components: + + //0 class CLASS_BASE "Classes\\Item.ecl", + + //1 model MODEL_BOMB "ModelsMP\\Items\\PowerUps\\SeriousBomb\\SeriousBomb.mdl", + //2 texture TEXTURE_BOMB "ModelsMP\\Items\\PowerUps\\SeriousBomb\\SeriousBomb.tex", + + 100 sound SOUND_BLOW "SoundsMP\\Weapons\\SeriousBombBlow.wav", + + +functions: + + void ShakeItBaby(FLOAT tmShaketime, FLOAT fPower, FLOAT fFade, BOOL bFadeIn) + { + CWorldSettingsController *pwsc = GetWSC(this); + if (pwsc!=NULL) { + pwsc->m_tmShakeStarted = tmShaketime; + pwsc->m_vShakePos = GetPlacement().pl_PositionVector; + pwsc->m_fShakeFalloff = 450.0f; + pwsc->m_fShakeFade = fFade; + + pwsc->m_fShakeIntensityZ = 0; + pwsc->m_tmShakeFrequencyZ = 5.0f; + pwsc->m_fShakeIntensityY = 0.1f*fPower; + pwsc->m_tmShakeFrequencyY = 5.0f; + pwsc->m_fShakeIntensityB = 2.5f*fPower; + pwsc->m_tmShakeFrequencyB = 7.2f; + + pwsc->m_bShakeFadeIn = bFadeIn; + } + } + + void Glare(FLOAT fStart, FLOAT fEnd, FLOAT fFinR, FLOAT fFoutR) + { + CWorldSettingsController *pwsc = GetWSC(this); + if (pwsc!=NULL) + { + pwsc->m_colGlade=C_WHITE; + pwsc->m_tmGlaringStarted = _pTimer->CurrentTick()+fStart; + pwsc->m_tmGlaringEnded = pwsc->m_tmGlaringStarted+fEnd; + pwsc->m_fGlaringFadeInRatio = fFinR; + pwsc->m_fGlaringFadeOutRatio = fFoutR; + } + } + + + void ExplodeBomb( void ) + { + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(this->GetWorld()->wo_cenEntities, CEntity, iten) { + CEntity *pen = iten; + if (IsDerivedFromClass(pen, "Enemy Base")) { + CEnemyBase *penEnemy = (CEnemyBase *)pen; + if (penEnemy->m_bBoss==TRUE || DistanceTo(this, penEnemy)>250.0f) { + continue; + } + this->InflictDirectDamage(pen, this, DMT_EXPLOSION, penEnemy->GetHealth()+100.0f, pen->GetPlacement().pl_PositionVector, FLOAT3D(0,1,0)); + } + }} + } + +procedures: + + Main(ESeriousBomb esb) + { + InitAsVoid(); + + if (esb.penOwner) { + m_penOwner = esb.penOwner; + + m_soBlow.Set3DParameters(500.0f, 250.0f, 3.0f, 1.0f); + PlaySound(m_soBlow, SOUND_BLOW, SOF_3D); + if(_pNetwork->IsPlayerLocal(m_penOwner)) {IFeel_PlayEffect("SeriousBombBlow");} + + //Glare(tmp_af[5], tmp_af[6], tmp_af[7], tmp_af[8]); + Glare(1.0f, 2.8f, 0.3f, 0.3f); + + ShakeItBaby(_pTimer->CurrentTick(), 4.0f, 1.0f, TRUE); + autowait(1.5f); + + // fading shake + ShakeItBaby(_pTimer->CurrentTick(), 8.0f, 2.0f, FALSE); + + // explode bomb twicejust to be sure + ExplodeBomb(); + autowait(0.25f); + ExplodeBomb(); + autowait(1.75f); + + } + Destroy(); + return; + }; + +}; diff --git a/Sources/EntitiesMP/SeriousBomb.h b/Sources/EntitiesMP/SeriousBomb.h new file mode 100644 index 0000000..e559729 --- /dev/null +++ b/Sources/EntitiesMP/SeriousBomb.h @@ -0,0 +1,42 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_SeriousBomb_INCLUDED +#define _EntitiesMP_SeriousBomb_INCLUDED 1 +#define EVENTCODE_ESeriousBomb 0x01620000 +class DECL_DLL ESeriousBomb : public CEntityEvent { +public: +ESeriousBomb(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOwner; +}; +DECL_DLL inline void ClearToDefault(ESeriousBomb &e) { e = ESeriousBomb(); } ; +extern "C" DECL_DLL CDLLEntityClass CSeriousBomb_DLLClass; +class CSeriousBomb : public CRationalEntity { +public: + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penOwner; + CSoundObject m_soBlow; + +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +void ShakeItBaby(FLOAT tmShaketime,FLOAT fPower,FLOAT fFade,BOOL bFadeIn); + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +void Glare(FLOAT fStart,FLOAT fEnd,FLOAT fFinR,FLOAT fFoutR); + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +void ExplodeBomb(void); +#define STATE_CSeriousBomb_Main 1 + BOOL +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01620001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01620002_Main_02(const CEntityEvent &__eeInput); + BOOL H0x01620003_Main_03(const CEntityEvent &__eeInput); + BOOL H0x01620004_Main_04(const CEntityEvent &__eeInput); + BOOL H0x01620005_Main_05(const CEntityEvent &__eeInput); + BOOL H0x01620006_Main_06(const CEntityEvent &__eeInput); + BOOL H0x01620007_Main_07(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_SeriousBomb_INCLUDED diff --git a/Sources/EntitiesMP/SeriousBomb_tables.h b/Sources/EntitiesMP/SeriousBomb_tables.h new file mode 100644 index 0000000..22950f4 --- /dev/null +++ b/Sources/EntitiesMP/SeriousBomb_tables.h @@ -0,0 +1,42 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CSeriousBomb + +CEntityProperty CSeriousBomb_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000162<<8)+1, offsetof(CSeriousBomb, m_penOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000162<<8)+20, offsetof(CSeriousBomb, m_soBlow), "", 0, 0, 0), +}; +#define CSeriousBomb_propertiesct ARRAYCOUNT(CSeriousBomb_properties) + +CEntityComponent CSeriousBomb_components[] = { +#define SOUND_BLOW ((0x00000162<<8)+100) + CEntityComponent(ECT_SOUND, SOUND_BLOW, "EFNM" "SoundsMP\\Weapons\\SeriousBombBlow.wav"), +}; +#define CSeriousBomb_componentsct ARRAYCOUNT(CSeriousBomb_components) + +CEventHandlerEntry CSeriousBomb_handlers[] = { + {1, -1, CEntity::pEventHandler(&CSeriousBomb:: +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/SeriousBomb.es" +Main),DEBUGSTRING("CSeriousBomb::Main")}, + {0x01620001, -1, CEntity::pEventHandler(&CSeriousBomb::H0x01620001_Main_01), DEBUGSTRING("CSeriousBomb::H0x01620001_Main_01")}, + {0x01620002, -1, CEntity::pEventHandler(&CSeriousBomb::H0x01620002_Main_02), DEBUGSTRING("CSeriousBomb::H0x01620002_Main_02")}, + {0x01620003, -1, CEntity::pEventHandler(&CSeriousBomb::H0x01620003_Main_03), DEBUGSTRING("CSeriousBomb::H0x01620003_Main_03")}, + {0x01620004, -1, CEntity::pEventHandler(&CSeriousBomb::H0x01620004_Main_04), DEBUGSTRING("CSeriousBomb::H0x01620004_Main_04")}, + {0x01620005, -1, CEntity::pEventHandler(&CSeriousBomb::H0x01620005_Main_05), DEBUGSTRING("CSeriousBomb::H0x01620005_Main_05")}, + {0x01620006, -1, CEntity::pEventHandler(&CSeriousBomb::H0x01620006_Main_06), DEBUGSTRING("CSeriousBomb::H0x01620006_Main_06")}, + {0x01620007, -1, CEntity::pEventHandler(&CSeriousBomb::H0x01620007_Main_07), DEBUGSTRING("CSeriousBomb::H0x01620007_Main_07")}, +}; +#define CSeriousBomb_handlersct ARRAYCOUNT(CSeriousBomb_handlers) + +CEntity *CSeriousBomb_New(void) { return new CSeriousBomb; }; +void CSeriousBomb_OnInitClass(void) {}; +void CSeriousBomb_OnEndClass(void) {}; +void CSeriousBomb_OnPrecache(CDLLEntityClass *pdec, INDEX iUser); +void CSeriousBomb_OnWorldEnd(CWorld *pwo) {}; +void CSeriousBomb_OnWorldInit(CWorld *pwo) {}; +void CSeriousBomb_OnWorldTick(CWorld *pwo) {}; +void CSeriousBomb_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CSeriousBomb, CRationalEntity, "Serious Bomb", "", 0x00000162); +DECLARE_CTFILENAME(_fnmCSeriousBomb_tbn, ""); diff --git a/Sources/EntitiesMP/Ship.cpp b/Sources/EntitiesMP/Ship.cpp new file mode 100644 index 0000000..f921e84 --- /dev/null +++ b/Sources/EntitiesMP/Ship.cpp @@ -0,0 +1,497 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *EHarbor::MakeCopy(void) { CEntityEvent *peeCopy = new EHarbor(*this); return peeCopy;} +EHarbor::EHarbor() : CEntityEvent(EVENTCODE_EHarbor) {; +}; +#line 13 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" + + +// adjust angular velocity +ANGLE AdjustRotationSpeed(ANGLE aDiference, ANGLE aMaxSpeed) +{ + aDiference = NormalizeAngle(aDiference); + aDiference = Clamp(aDiference, -aMaxSpeed, +aMaxSpeed); + return aDiference; +} + + +void CShip::SetDefaultProperties(void) { + m_strName = "Ship"; + m_strDescription = ""; + m_penTarget = NULL; + m_fSpeed = 10.0f; + m_fRotation = 30.0f; + m_fRockingV = 10.0f; + m_fRockingA = 10.0f; + m_fAcceleration = 10.0f; + m_bMoving = TRUE ; + m_fRockSign = 1.0f; + m_fLastTargetDistance = UpperLimit(0.0f); + m_penSail = NULL; + m_iSailUpAnim = 0; + m_iSailDownAnim = 0; + m_iSailSailAnim = 0; + m_iSailWaveingAnim = 0; + m_fOriginalRockingV = 0.0f; + m_fOriginalRockingA = 0.0f; + m_fNextRockingV = 0.0f; + m_fNextRockingA = 0.0f; + m_tmRockingChange = 1; + m_tmRockingChangeStart = -1; + CMovableBrushEntity::SetDefaultProperties(); +} + +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +BOOL CShip::MovesByTargetedRoute(CTString & strTargetProperty)const { +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +strTargetProperty = "Target"; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return TRUE ; +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} + +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +BOOL CShip::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +fnmMarkerClass = CTFILENAME ("Classes\\ShipMarker.ecl"); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +strTargetProperty = "Target"; +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return TRUE ; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} + +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +const CTString & CShip::GetDescription(void)const { +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(m_penTarget != NULL ){ +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , m_penTarget -> GetName ()); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return m_strDescription ; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +CAnimData * CShip::GetAnimData(SLONG slPropertyOffset) +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +{ +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if((slPropertyOffset == offsetof (CShip , m_iSailUpAnim ) +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +|| slPropertyOffset == offsetof (CShip , m_iSailDownAnim ) +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +|| slPropertyOffset == offsetof (CShip , m_iSailSailAnim ) +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +|| slPropertyOffset == offsetof (CShip , m_iSailWaveingAnim )) +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +&& m_penSail != NULL ){ +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return m_penSail -> GetModelObject () -> GetData (); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}else { +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return CEntity :: GetAnimData (slPropertyOffset ); +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} + +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +void CShip::SetMovingSpeeds(void) +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +{ +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(! m_bMoving || m_penTarget == NULL ){ +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetDesiredRotation (ANGLE3D (0 , 0 , GetRockingSpeed ())); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return ; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +CShipMarker * penTarget = (CShipMarker *) (CEntity *) m_penTarget ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +const CPlacement3D & plThis = GetPlacement (); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +const FLOAT3D & vTarget = penTarget -> GetPlacement () . pl_PositionVector ; +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +const FLOAT3D & vNow = plThis . pl_PositionVector ; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +FLOAT3D vDirection = vTarget - vNow ; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +FLOAT fTargetDistance = vDirection . Length (); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(fTargetDistance < m_fSpeed * 5 * _pTimer -> TickQuantum ){ +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +NextMarker (); +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return ; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +vDirection /= fTargetDistance ; +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +ANGLE3D aAngle ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +DirectionVectorToAngles (vDirection , aAngle ); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +aAngle -= plThis . pl_OrientationAngle ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +aAngle (1) = AdjustRotationSpeed (aAngle (1) , m_fRotation ); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +aAngle (2) = 0; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +aAngle (3) = GetRockingSpeed (); +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetDesiredRotation (aAngle ); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetDesiredTranslation (FLOAT3D (0 , 0 , - m_fSpeed )); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +en_fAcceleration = m_fAcceleration ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +en_fDeceleration = m_fAcceleration ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} + +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +ANGLE CShip::GetRockingSpeed(void) +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +{ +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +TIME tmSinceChangeStarted = _pTimer -> CurrentTick () - m_tmRockingChangeStart ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(tmSinceChangeStarted < m_tmRockingChange ){ +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +FLOAT fFactor = tmSinceChangeStarted / m_tmRockingChange ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fRockingV = Lerp (m_fOriginalRockingV , m_fNextRockingV , fFactor ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fRockingA = Lerp (m_fOriginalRockingA , m_fNextRockingA , fFactor ); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(m_fRockingV == 0){ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return 0; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +ANGLE aAngle = GetPlacement () . pl_OrientationAngle (3); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +ANGLE aRotation = Sqrt (m_fRockingA * m_fRockingA - aAngle * aAngle ) * m_fRockingV ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(aRotation < 2 && aAngle * m_fRockSign > 0){ +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fRockSign = - m_fRockSign ; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}; +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(aRotation < 2){ +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +aRotation = 2; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +aRotation *= m_fRockSign ; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return aRotation ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +void CShip::NextMarker(void) +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +{ +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +CShipMarker * penTarget = (CShipMarker *) (CEntity *) m_penTarget ; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +CShipMarker * penNextTarget = (CShipMarker *) (CEntity *) penTarget -> m_penTarget ; +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(penTarget -> m_bHarbor ){ +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +StopSailing (); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SendEvent (EHarbor ()); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(penNextTarget == NULL ){ +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +StopSailing (); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +FLOAT fSpeed = penTarget -> m_fSpeed ; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(fSpeed >= 0){ +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fSpeed = fSpeed ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +FLOAT fRotation = penTarget -> m_fRotation ; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(fRotation >= 0){ +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fRotation = fRotation ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +FLOAT fAcceleration = penTarget -> m_fAcceleration ; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(fAcceleration >= 0){ +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fAcceleration = fAcceleration ; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fOriginalRockingV = m_fRockingV ; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fOriginalRockingA = m_fRockingA ; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +FLOAT fRockingV = penTarget -> m_fRockingV ; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(fRockingV >= 0){ +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fNextRockingV = fRockingV ; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}else { +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fNextRockingV = m_fRockingV ; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +FLOAT fRockingA = penTarget -> m_fRockingA ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(fRockingA >= 0){ +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fNextRockingA = fRockingA ; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}else { +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_fNextRockingA = m_fRockingA ; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_tmRockingChange = penTarget -> m_tmRockingChange ; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_tmRockingChangeStart = _pTimer -> CurrentTick (); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_penTarget = penNextTarget ; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetMovingSpeeds (); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} + +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +void CShip::StartSailing() +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +{ +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_bMoving = TRUE ; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetMovingSpeeds (); +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} + +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +void CShip::StopSailing(void) +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +{ +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_bMoving = FALSE ; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetDesiredRotation (ANGLE3D (0 , 0 , GetDesiredRotation () (3))); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetDesiredTranslation (FLOAT3D (0 , 0 , 0)); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} + +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +void CShip::PreMoving(void) { +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetMovingSpeeds (); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +CMovableBrushEntity :: PreMoving (); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +BOOL CShip:: +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Sail(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CShip_Sail + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CShip::Sail expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_penSail -> GetModelObject () -> PlayAnim (m_iSailDownAnim , 0); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetTimerAfter(m_penSail -> GetModelObject () -> GetAnimLength (m_iSailDownAnim )); +Jump(STATE_CURRENT, 0x00670002, FALSE, EBegin());return TRUE;}BOOL CShip::H0x00670002_Sail_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00670002 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00670003, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CShip::H0x00670003_Sail_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00670003 +; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_penSail -> GetModelObject () -> PlayAnim (m_iSailWaveingAnim , AOF_LOOPING ); +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00670004, FALSE, EBegin());return TRUE;}BOOL CShip::H0x00670004_Sail_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00670004 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&eTouch= (ETouch&)__eeInput; + +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(IsDerivedFromClass (eTouch . penOther , "PlayerEntity")){ +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +UnsetTimer();Jump(STATE_CURRENT,0x00670005, FALSE, EInternal());return TRUE; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; + +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +UnsetTimer();Jump(STATE_CURRENT,0x00670005, FALSE, EInternal());return TRUE; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}return TRUE;}BOOL CShip::H0x00670005_Sail_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00670005 + +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_penSail -> GetModelObject () -> PlayAnim (m_iSailSailAnim , 0); +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +StartSailing (); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00670006, FALSE, EBegin());return TRUE;}BOOL CShip::H0x00670006_Sail_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00670006 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EHarbor):{const EHarbor&e= (EHarbor&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x00670007, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}return TRUE;}BOOL CShip::H0x00670007_Sail_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00670007 + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Jump(STATE_CURRENT, STATE_CShip_Harbor, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CShip:: +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Harbor(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CShip_Harbor + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CShip::Harbor expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_penSail -> GetModelObject () -> PlayAnim (m_iSailUpAnim , 0); +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00670009, FALSE, EBegin());return TRUE;}BOOL CShip::H0x00670009_Harbor_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00670009 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x0067000a, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}return TRUE;}BOOL CShip::H0x0067000a_Harbor_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0067000a + +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Jump(STATE_CURRENT, STATE_CShip_Sail, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CShip:: +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CShip_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CShip::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +InitAsBrush (); +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetPhysicsFlags (EPF_BRUSH_MOVING & ~ (EPF_ABSOLUTETRANSLATE | EPF_NOACCELERATION )); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetCollisionFlags (ECF_BRUSH ); +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +ForceFullStop (); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(m_penTarget != NULL && ! IsOfClass (m_penTarget , "Ship Marker")){ +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +WarningMessage ("Target '%s' is not of ShipMarker class!" , m_penTarget -> GetName ()); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_penTarget = NULL ; +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(m_penSail != NULL && m_penSail -> GetRenderType () != RT_MODEL ){ +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +WarningMessage ("Sail '%s' is not a model!" , m_penSail -> GetName ()); +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +m_penSail = NULL ; +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x0067000b, FALSE, EBegin());return TRUE;}BOOL CShip::H0x0067000b_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0067000b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0067000c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CShip::H0x0067000c_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0067000c +; +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +if(m_penSail == NULL ){ +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +WarningMessage ("Ship will not work without a valid sail!"); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Return(STATE_CURRENT,EVoid()); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return TRUE; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +} +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x0067000d, FALSE, EBegin());return TRUE;}BOOL CShip::H0x0067000d_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0067000d +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Call(STATE_CURRENT, STATE_CShip_Sail, TRUE, EVoid());return TRUE; +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}ASSERT(FALSE);break;case(EVENTCODE_EBlock):{const EBlock&eBlock= (EBlock&)__eeInput; + +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +InflictDirectDamage (eBlock . penOther , this , DMT_BRUSH , 10.0f , +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +FLOAT3D (0.0f , 0.0f , 0.0f) , (FLOAT3D &) eBlock . plCollision ); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +return TRUE; +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +}return TRUE;}BOOL CShip::H0x0067000e_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0067000e + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Ship.es b/Sources/EntitiesMP/Ship.es new file mode 100644 index 0000000..e49b0b0 --- /dev/null +++ b/Sources/EntitiesMP/Ship.es @@ -0,0 +1,339 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +103 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/ShipMarker"; + +event EHarbor { +}; + +%{ + +// adjust angular velocity +ANGLE AdjustRotationSpeed(ANGLE aDiference, ANGLE aMaxSpeed) +{ + aDiference = NormalizeAngle(aDiference); + aDiference = Clamp(aDiference, -aMaxSpeed, +aMaxSpeed); + return aDiference; +} + +%} + +class CShip : CMovableBrushEntity { +name "Ship"; +thumbnail "Thumbnails\\Ship.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "Ship", + 2 CTString m_strDescription = "", + + 3 CEntityPointer m_penTarget "Target" 'T', + 4 FLOAT m_fSpeed "Speed [m/s]" 'S' = 10.0f, + 5 FLOAT m_fRotation "Rotation [deg/s]" 'R' = 30.0f, + 6 FLOAT m_fRockingV "Rocking V" 'V' = 10.0f, + 7 FLOAT m_fRockingA "Rocking A" 'A' = 10.0f, + 8 FLOAT m_fAcceleration "Acceleration" 'C' = 10.0f, + + 10 BOOL m_bMoving = TRUE, + 11 FLOAT m_fRockSign = 1.0f, + 12 FLOAT m_fLastTargetDistance = UpperLimit(0.0f), + + 20 CEntityPointer m_penSail "Sail" 'L', + 21 ANIMATION m_iSailUpAnim "Sail roll-up anim"=0, + 22 ANIMATION m_iSailDownAnim "Sail roll-down anim"=0, + 23 ANIMATION m_iSailSailAnim "Sail sailing anim"=0, + 24 ANIMATION m_iSailWaveingAnim "Sail wawing anim"=0, + + 30 FLOAT m_fOriginalRockingV = 0.0f, + 31 FLOAT m_fOriginalRockingA = 0.0f, + 32 FLOAT m_fNextRockingV = 0.0f, + 33 FLOAT m_fNextRockingA = 0.0f, + 34 FLOAT m_tmRockingChange=1, // how many second to change rocking parameters + 35 FLOAT m_tmRockingChangeStart=-1, // when changing of rocking parameters has started +components: +functions: + /* Check if entity is moved on a route set up by its targets. */ + BOOL MovesByTargetedRoute(CTString &strTargetProperty) const { + strTargetProperty = "Target"; + return TRUE; + }; + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\ShipMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("->"); + if (m_penTarget!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", m_penTarget->GetName()); + } + return m_strDescription; + } + /* Get anim data for given animation property - return NULL for none. */ + CAnimData *GetAnimData(SLONG slPropertyOffset) + { + if((slPropertyOffset==offsetof(CShip, m_iSailUpAnim) + ||slPropertyOffset==offsetof(CShip, m_iSailDownAnim) + ||slPropertyOffset==offsetof(CShip, m_iSailSailAnim) + ||slPropertyOffset==offsetof(CShip, m_iSailWaveingAnim)) + &&m_penSail!=NULL) { + return m_penSail->GetModelObject()->GetData(); + } else { + return CEntity::GetAnimData(slPropertyOffset); + } + }; + + // calculate velocities towards marker + void SetMovingSpeeds(void) + { + // if the brush should not be moving, or there is no target + if (!m_bMoving || m_penTarget==NULL) { + // just rock + SetDesiredRotation(ANGLE3D(0,0,GetRockingSpeed())); + return; + } + + CShipMarker *penTarget = (CShipMarker *)(CEntity*)m_penTarget; + const CPlacement3D &plThis = GetPlacement(); + + // get direction to target + const FLOAT3D &vTarget = penTarget->GetPlacement().pl_PositionVector; + const FLOAT3D &vNow = plThis.pl_PositionVector; + FLOAT3D vDirection = vTarget-vNow; + FLOAT fTargetDistance = vDirection.Length(); + // if got close enough + if (fTargetDistanceTickQuantum) { + // switch to next marker + NextMarker(); + return; + } + + vDirection/=fTargetDistance; + ANGLE3D aAngle; + DirectionVectorToAngles(vDirection, aAngle); + aAngle-=plThis.pl_OrientationAngle; + aAngle(1) = AdjustRotationSpeed(aAngle(1), m_fRotation); + aAngle(2) = 0; + aAngle(3) = GetRockingSpeed(); + + SetDesiredRotation(aAngle); + + // set speed + SetDesiredTranslation(FLOAT3D(0,0,-m_fSpeed)); + + en_fAcceleration = m_fAcceleration; + en_fDeceleration = m_fAcceleration; + } + + // calculate rocking velocity + ANGLE GetRockingSpeed(void) + { + // if rocking changing time has not passed + TIME tmSinceChangeStarted = _pTimer->CurrentTick()-m_tmRockingChangeStart; + if (tmSinceChangeStarted0) { + m_fRockSign = -m_fRockSign; + }; + + if (aRotation<2) { + aRotation = 2; + } + aRotation *=m_fRockSign; + + return aRotation; + } + + // switch to next marker + void NextMarker(void) + { + // get next marker + CShipMarker *penTarget = (CShipMarker *)(CEntity*)m_penTarget; + CShipMarker *penNextTarget = (CShipMarker *)(CEntity*)penTarget->m_penTarget; + + // if this marker is harbor + if (penTarget->m_bHarbor) { + // stop + StopSailing(); + // start being in harbor + SendEvent(EHarbor()); + } + + // if got to end + if (penNextTarget==NULL) { + // stop + StopSailing(); + return; + } + + // get properties from marker + FLOAT fSpeed = penTarget->m_fSpeed; + if (fSpeed>=0) { + m_fSpeed = fSpeed; + } + FLOAT fRotation = penTarget->m_fRotation; + if (fRotation>=0) { + m_fRotation = fRotation; + } + FLOAT fAcceleration = penTarget->m_fAcceleration; + if (fAcceleration>=0) { + m_fAcceleration = fAcceleration; + } + + m_fOriginalRockingV = m_fRockingV; + m_fOriginalRockingA = m_fRockingA; + + FLOAT fRockingV = penTarget->m_fRockingV; + if (fRockingV>=0) { + m_fNextRockingV = fRockingV; + } else { + m_fNextRockingV = m_fRockingV; + } + FLOAT fRockingA = penTarget->m_fRockingA; + if (fRockingA>=0) { + m_fNextRockingA = fRockingA; + } else { + m_fNextRockingA = m_fRockingA; + } + m_tmRockingChange = penTarget->m_tmRockingChange; + m_tmRockingChangeStart = _pTimer->CurrentTick(); + + // remember next marker as current target + m_penTarget = penNextTarget; + SetMovingSpeeds(); + } + + void StartSailing() + { + m_bMoving = TRUE; + // calculate velocities towards marker + SetMovingSpeeds(); + } + + void StopSailing(void) + { + m_bMoving = FALSE; + SetDesiredRotation(ANGLE3D(0,0,GetDesiredRotation()(3))); + SetDesiredTranslation(FLOAT3D(0,0,0)); + } + + // do moving + void PreMoving(void) { + // calculate velocities towards marker + SetMovingSpeeds(); + CMovableBrushEntity::PreMoving(); + }; + +procedures: + Sail() { + // roll the sail down + m_penSail->GetModelObject()->PlayAnim(m_iSailDownAnim, 0); + autowait(m_penSail->GetModelObject()->GetAnimLength(m_iSailDownAnim)); + // start sail waveing + m_penSail->GetModelObject()->PlayAnim(m_iSailWaveingAnim, AOF_LOOPING); + + // wait until touched by a player or started + wait() { + on (EBegin) : { resume; } + on (ETouch eTouch) : { + if (IsDerivedFromClass(eTouch.penOther, "PlayerEntity")) { + stop; + } + } + on (EStart) : { + stop; + } + } + + // blow the sail up + m_penSail->GetModelObject()->PlayAnim(m_iSailSailAnim, 0); + + // start moving + StartSailing(); + // sail until we come to harbor + wait() { + on (EBegin) : { resume; } + on (EHarbor) : { stop; } + } + + // stay in harbor + jump Harbor(); + } + Harbor() { + // roll the sail up + m_penSail->GetModelObject()->PlayAnim(m_iSailUpAnim, 0); + + // stay in harbor until we are triggered + wait() { + on (EBegin) : { resume; } + on (ETrigger) : { stop; } + } + // start sailing + jump Sail(); + } + + + Main() { + // declare yourself as a brush + InitAsBrush(); + SetPhysicsFlags(EPF_BRUSH_MOVING&~(EPF_ABSOLUTETRANSLATE|EPF_NOACCELERATION)); + SetCollisionFlags(ECF_BRUSH); + + // stop moving brush + ForceFullStop(); + + // assure valid target + if (m_penTarget!=NULL && !IsOfClass(m_penTarget, "Ship Marker")) { + WarningMessage("Target '%s' is not of ShipMarker class!", m_penTarget->GetName()); + m_penTarget = NULL; + } + // assure valid sail + if (m_penSail!=NULL && m_penSail->GetRenderType()!=RT_MODEL) { + WarningMessage("Sail '%s' is not a model!", m_penSail->GetName()); + m_penSail = NULL; + } + + // wait until game starts + autowait(0.1f); + + // if sail is not valid + if (m_penSail==NULL) { + // don't continue + WarningMessage("Ship will not work without a valid sail!"); + return; + } + + // forever + wait() { + // on the beginning + on (EBegin) : { + // start sailing + call Sail(); + } + + // move is obstructed + on (EBlock eBlock) : { + // inflict damage to entity that block brush + InflictDirectDamage(eBlock.penOther, this, DMT_BRUSH, 10.0f, + FLOAT3D(0.0f,0.0f,0.0f), (FLOAT3D &)eBlock.plCollision); + resume; + } + } + } +}; diff --git a/Sources/EntitiesMP/Ship.h b/Sources/EntitiesMP/Ship.h new file mode 100644 index 0000000..b23eb03 --- /dev/null +++ b/Sources/EntitiesMP/Ship.h @@ -0,0 +1,98 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Ship_INCLUDED +#define _EntitiesMP_Ship_INCLUDED 1 +#include +#define EVENTCODE_EHarbor 0x00670000 +class DECL_DLL EHarbor : public CEntityEvent { +public: +EHarbor(); +CEntityEvent *MakeCopy(void); +}; +DECL_DLL inline void ClearToDefault(EHarbor &e) { e = EHarbor(); } ; +extern "C" DECL_DLL CDLLEntityClass CShip_DLLClass; +class CShip : public CMovableBrushEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CEntityPointer m_penTarget; + FLOAT m_fSpeed; + FLOAT m_fRotation; + FLOAT m_fRockingV; + FLOAT m_fRockingA; + FLOAT m_fAcceleration; + BOOL m_bMoving; + FLOAT m_fRockSign; + FLOAT m_fLastTargetDistance; + CEntityPointer m_penSail; + ANIMATION m_iSailUpAnim; + ANIMATION m_iSailDownAnim; + ANIMATION m_iSailSailAnim; + ANIMATION m_iSailWaveingAnim; + FLOAT m_fOriginalRockingV; + FLOAT m_fOriginalRockingA; + FLOAT m_fNextRockingV; + FLOAT m_fNextRockingA; + FLOAT m_tmRockingChange; + FLOAT m_tmRockingChangeStart; + +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +const CTString & GetDescription(void)const; + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +CAnimData * GetAnimData(SLONG slPropertyOffset); + +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +void SetMovingSpeeds(void); + +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +ANGLE GetRockingSpeed(void); + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +void NextMarker(void); + +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +void StartSailing(); + +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +void StopSailing(void); + +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +void PreMoving(void); +#define STATE_CShip_Sail 0x00670001 + BOOL +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Sail(const CEntityEvent &__eeInput); + BOOL H0x00670002_Sail_01(const CEntityEvent &__eeInput); + BOOL H0x00670003_Sail_02(const CEntityEvent &__eeInput); + BOOL H0x00670004_Sail_03(const CEntityEvent &__eeInput); + BOOL H0x00670005_Sail_04(const CEntityEvent &__eeInput); + BOOL H0x00670006_Sail_05(const CEntityEvent &__eeInput); + BOOL H0x00670007_Sail_06(const CEntityEvent &__eeInput); +#define STATE_CShip_Harbor 0x00670008 + BOOL +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Harbor(const CEntityEvent &__eeInput); + BOOL H0x00670009_Harbor_01(const CEntityEvent &__eeInput); + BOOL H0x0067000a_Harbor_02(const CEntityEvent &__eeInput); +#define STATE_CShip_Main 1 + BOOL +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x0067000b_Main_01(const CEntityEvent &__eeInput); + BOOL H0x0067000c_Main_02(const CEntityEvent &__eeInput); + BOOL H0x0067000d_Main_03(const CEntityEvent &__eeInput); + BOOL H0x0067000e_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Ship_INCLUDED diff --git a/Sources/EntitiesMP/ShipMarker.cpp b/Sources/EntitiesMP/ShipMarker.cpp new file mode 100644 index 0000000..fd037f2 --- /dev/null +++ b/Sources/EntitiesMP/ShipMarker.cpp @@ -0,0 +1,51 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" + +#include "StdH.h" + +#include +#include +void CShipMarker::SetDefaultProperties(void) { + m_bHarbor = FALSE ; + m_fSpeed = -1.0f; + m_fRotation = -1.0f; + m_fAcceleration = 10.0f; + m_fRockingV = -1.0f; + m_fRockingA = -1.0f; + m_tmRockingChange = 3.0f; + CMarker::SetDefaultProperties(); +} + +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +BOOL CShipMarker::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +fnmMarkerClass = CTFILENAME ("Classes\\ShipMarker.ecl"); +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +strTargetProperty = "Target"; +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +return TRUE ; +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +} +BOOL CShipMarker:: +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CShipMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CShipMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +InitAsEditorModel (); +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +SetModel (MODEL_MARKER ); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/ShipMarker.es b/Sources/EntitiesMP/ShipMarker.es new file mode 100644 index 0000000..a62ce23 --- /dev/null +++ b/Sources/EntitiesMP/ShipMarker.es @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +104 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; + +class CShipMarker: CMarker { +name "Ship Marker"; +thumbnail "Thumbnails\\ShipMarker.tbn"; + +properties: + 1 BOOL m_bHarbor "Harbor" 'H' = FALSE, + 2 FLOAT m_fSpeed "Speed [m/s]" 'S' = -1.0f, + 3 FLOAT m_fRotation "Rotation [deg/s]" 'R' = -1.0f, + 4 FLOAT m_fAcceleration "Acceleration" 'C' = 10.0f, + 5 FLOAT m_fRockingV "Rocking V" 'V' = -1.0f, + 6 FLOAT m_fRockingA "Rocking A" 'A' = -1.0f, + 7 FLOAT m_tmRockingChange "Rocking Change Time" = 3.0f, + +components: + 1 model MODEL_MARKER "Models\\Editor\\ShipMarker.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\ShipMarker.tex" + +functions: + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\ShipMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + return; + } +}; + diff --git a/Sources/EntitiesMP/ShipMarker.h b/Sources/EntitiesMP/ShipMarker.h new file mode 100644 index 0000000..f72267b --- /dev/null +++ b/Sources/EntitiesMP/ShipMarker.h @@ -0,0 +1,27 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_ShipMarker_INCLUDED +#define _EntitiesMP_ShipMarker_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CShipMarker_DLLClass; +class CShipMarker : public CMarker { +public: + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bHarbor; + FLOAT m_fSpeed; + FLOAT m_fRotation; + FLOAT m_fAcceleration; + FLOAT m_fRockingV; + FLOAT m_fRockingA; + FLOAT m_tmRockingChange; + +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; +#define STATE_CShipMarker_Main 1 + BOOL +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_ShipMarker_INCLUDED diff --git a/Sources/EntitiesMP/ShipMarker_tables.h b/Sources/EntitiesMP/ShipMarker_tables.h new file mode 100644 index 0000000..2bb9bb5 --- /dev/null +++ b/Sources/EntitiesMP/ShipMarker_tables.h @@ -0,0 +1,42 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CShipMarker + +CEntityProperty CShipMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000068<<8)+1, offsetof(CShipMarker, m_bHarbor), "Harbor", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000068<<8)+2, offsetof(CShipMarker, m_fSpeed), "Speed [m/s]", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000068<<8)+3, offsetof(CShipMarker, m_fRotation), "Rotation [deg/s]", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000068<<8)+4, offsetof(CShipMarker, m_fAcceleration), "Acceleration", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000068<<8)+5, offsetof(CShipMarker, m_fRockingV), "Rocking V", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000068<<8)+6, offsetof(CShipMarker, m_fRockingA), "Rocking A", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000068<<8)+7, offsetof(CShipMarker, m_tmRockingChange), "Rocking Change Time", 0, 0x7F0000FFUL, 0), +}; +#define CShipMarker_propertiesct ARRAYCOUNT(CShipMarker_properties) + +CEntityComponent CShipMarker_components[] = { +#define MODEL_MARKER ((0x00000068<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\ShipMarker.mdl"), +#define TEXTURE_MARKER ((0x00000068<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\ShipMarker.tex"), +}; +#define CShipMarker_componentsct ARRAYCOUNT(CShipMarker_components) + +CEventHandlerEntry CShipMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CShipMarker:: +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/ShipMarker.es" +Main),DEBUGSTRING("CShipMarker::Main")}, +}; +#define CShipMarker_handlersct ARRAYCOUNT(CShipMarker_handlers) + +CEntity *CShipMarker_New(void) { return new CShipMarker; }; +void CShipMarker_OnInitClass(void) {}; +void CShipMarker_OnEndClass(void) {}; +void CShipMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CShipMarker_OnWorldEnd(CWorld *pwo) {}; +void CShipMarker_OnWorldInit(CWorld *pwo) {}; +void CShipMarker_OnWorldTick(CWorld *pwo) {}; +void CShipMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CShipMarker, CMarker, "Ship Marker", "Thumbnails\\ShipMarker.tbn", 0x00000068); +DECLARE_CTFILENAME(_fnmCShipMarker_tbn, "Thumbnails\\ShipMarker.tbn"); diff --git a/Sources/EntitiesMP/Ship_tables.h b/Sources/EntitiesMP/Ship_tables.h new file mode 100644 index 0000000..3b209f2 --- /dev/null +++ b/Sources/EntitiesMP/Ship_tables.h @@ -0,0 +1,73 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CShip + +CEntityProperty CShip_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000067<<8)+1, offsetof(CShip, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000067<<8)+2, offsetof(CShip, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000067<<8)+3, offsetof(CShip, m_penTarget), "Target", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+4, offsetof(CShip, m_fSpeed), "Speed [m/s]", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+5, offsetof(CShip, m_fRotation), "Rotation [deg/s]", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+6, offsetof(CShip, m_fRockingV), "Rocking V", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+7, offsetof(CShip, m_fRockingA), "Rocking A", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+8, offsetof(CShip, m_fAcceleration), "Acceleration", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000067<<8)+10, offsetof(CShip, m_bMoving), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+11, offsetof(CShip, m_fRockSign), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+12, offsetof(CShip, m_fLastTargetDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000067<<8)+20, offsetof(CShip, m_penSail), "Sail", 'L', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000067<<8)+21, offsetof(CShip, m_iSailUpAnim), "Sail roll-up anim", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000067<<8)+22, offsetof(CShip, m_iSailDownAnim), "Sail roll-down anim", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000067<<8)+23, offsetof(CShip, m_iSailSailAnim), "Sail sailing anim", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000067<<8)+24, offsetof(CShip, m_iSailWaveingAnim), "Sail wawing anim", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+30, offsetof(CShip, m_fOriginalRockingV), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+31, offsetof(CShip, m_fOriginalRockingA), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+32, offsetof(CShip, m_fNextRockingV), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+33, offsetof(CShip, m_fNextRockingA), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+34, offsetof(CShip, m_tmRockingChange), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000067<<8)+35, offsetof(CShip, m_tmRockingChangeStart), "", 0, 0, 0), +}; +#define CShip_propertiesct ARRAYCOUNT(CShip_properties) + +CEntityComponent CShip_components[] = { + CEntityComponent() +}; +#define CShip_componentsct 0 + + +CEventHandlerEntry CShip_handlers[] = { + {0x00670001, -1, CEntity::pEventHandler(&CShip:: +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Sail),DEBUGSTRING("CShip::Sail")}, + {0x00670002, -1, CEntity::pEventHandler(&CShip::H0x00670002_Sail_01), DEBUGSTRING("CShip::H0x00670002_Sail_01")}, + {0x00670003, -1, CEntity::pEventHandler(&CShip::H0x00670003_Sail_02), DEBUGSTRING("CShip::H0x00670003_Sail_02")}, + {0x00670004, -1, CEntity::pEventHandler(&CShip::H0x00670004_Sail_03), DEBUGSTRING("CShip::H0x00670004_Sail_03")}, + {0x00670005, -1, CEntity::pEventHandler(&CShip::H0x00670005_Sail_04), DEBUGSTRING("CShip::H0x00670005_Sail_04")}, + {0x00670006, -1, CEntity::pEventHandler(&CShip::H0x00670006_Sail_05), DEBUGSTRING("CShip::H0x00670006_Sail_05")}, + {0x00670007, -1, CEntity::pEventHandler(&CShip::H0x00670007_Sail_06), DEBUGSTRING("CShip::H0x00670007_Sail_06")}, + {0x00670008, -1, CEntity::pEventHandler(&CShip:: +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Harbor),DEBUGSTRING("CShip::Harbor")}, + {0x00670009, -1, CEntity::pEventHandler(&CShip::H0x00670009_Harbor_01), DEBUGSTRING("CShip::H0x00670009_Harbor_01")}, + {0x0067000a, -1, CEntity::pEventHandler(&CShip::H0x0067000a_Harbor_02), DEBUGSTRING("CShip::H0x0067000a_Harbor_02")}, + {1, -1, CEntity::pEventHandler(&CShip:: +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Ship.es" +Main),DEBUGSTRING("CShip::Main")}, + {0x0067000b, -1, CEntity::pEventHandler(&CShip::H0x0067000b_Main_01), DEBUGSTRING("CShip::H0x0067000b_Main_01")}, + {0x0067000c, -1, CEntity::pEventHandler(&CShip::H0x0067000c_Main_02), DEBUGSTRING("CShip::H0x0067000c_Main_02")}, + {0x0067000d, -1, CEntity::pEventHandler(&CShip::H0x0067000d_Main_03), DEBUGSTRING("CShip::H0x0067000d_Main_03")}, + {0x0067000e, -1, CEntity::pEventHandler(&CShip::H0x0067000e_Main_04), DEBUGSTRING("CShip::H0x0067000e_Main_04")}, +}; +#define CShip_handlersct ARRAYCOUNT(CShip_handlers) + +CEntity *CShip_New(void) { return new CShip; }; +void CShip_OnInitClass(void) {}; +void CShip_OnEndClass(void) {}; +void CShip_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CShip_OnWorldEnd(CWorld *pwo) {}; +void CShip_OnWorldInit(CWorld *pwo) {}; +void CShip_OnWorldTick(CWorld *pwo) {}; +void CShip_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CShip, CMovableBrushEntity, "Ship", "Thumbnails\\Ship.tbn", 0x00000067); +DECLARE_CTFILENAME(_fnmCShip_tbn, "Thumbnails\\Ship.tbn"); diff --git a/Sources/EntitiesMP/Shooter.cpp b/Sources/EntitiesMP/Shooter.cpp new file mode 100644 index 0000000..66ba763 --- /dev/null +++ b/Sources/EntitiesMP/Shooter.cpp @@ -0,0 +1,583 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" + +#include "StdH.h" + +#include +#include +void CShooter::SetDefaultProperties(void) { + m_fShootingPeriod = 1.0f; + m_sftType = SFT_WOODEN_DART ; + m_fHealth = 0.0f; + m_fCannonBallSize = 1.0f; + m_fCannonBallPower = 10.0f; + m_iModelPreFireAnimation = 0; + m_iTexturePreFireAnimation = 0; + m_iModelPostFireAnimation = 0; + m_iTexturePostFireAnimation = 0; + m_fFlameBurstDuration = 1.0f; + m_fRndBeginWait = 0.0f; + m_penSoundLaunch = NULL; + m_soLaunch.SetOwner(this); +m_soLaunch.Stop_internal(); + m_penFlame = NULL; + m_bFiring = FALSE ; + m_bIndestructable = FALSE ; + m_tmFlameStart = 0.0f; + CModelHolder2::SetDefaultProperties(); +} + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void CShooter::Precache(void) { +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CModelHolder2 :: Precache (); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +PrecacheClass (CLASS_PROJECTILE , PRT_SHOOTER_WOODEN_DART ); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +PrecacheClass (CLASS_PROJECTILE , PRT_SHOOTER_FIREBALL ); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +PrecacheClass (CLASS_CANNONBALL ); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} + +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void CShooter::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +{ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(! m_bIndestructable && ! IsOfClass (penInflictor , "Shooter")){ +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(m_tmSpraySpawned <= _pTimer -> CurrentTick () - _pTimer -> TickQuantum * 8 +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +&& m_penDestruction != NULL ){ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CModelDestruction * penDestruction = GetDestruction (); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CPlacement3D plSpray = CPlacement3D (vHitPoint , ANGLE3D (0 , 0 , 0)); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_penSpray = CreateEntity (plSpray , CLASS_BLOOD_SPRAY ); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_penSpray -> SetParent (this ); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ESpawnSpray eSpawnSpray ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eSpawnSpray . colBurnColor = C_WHITE | CT_OPAQUE ; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(fDamageAmmount > 50.0f){ +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eSpawnSpray . fDamagePower = 3.0f; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}else if(fDamageAmmount > 25.0f){ +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eSpawnSpray . fDamagePower = 2.0f; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}else { +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eSpawnSpray . fDamagePower = 1.0f; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eSpawnSpray . sptType = penDestruction -> m_sptType ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eSpawnSpray . fSizeMultiplier = 1.0f; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FLOAT3D vDn (- en_mRotation (1 , 2) , - en_mRotation (2 , 2) , - en_mRotation (3 , 2)); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FLOAT3D vHitPointRelative = vHitPoint - GetPlacement () . pl_PositionVector ; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FLOAT3D vReflectingNormal ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +GetNormalComponent (vHitPointRelative , vDn , vReflectingNormal ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +vReflectingNormal . Normalize (); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +vReflectingNormal (1) /= 5.0f; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FLOAT3D vProjectedComponent = vReflectingNormal * (vDirection % vReflectingNormal ); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FLOAT3D vSpilDirection = vDirection - vProjectedComponent * 2.0f - vDn * 0.5f; +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eSpawnSpray . vDirection = vSpilDirection ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eSpawnSpray . penOwner = this ; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_penSpray -> Initialize (eSpawnSpray ); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_tmSpraySpawned = _pTimer -> CurrentTick (); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CRationalEntity :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void CShooter::RenderParticles(void) +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +{ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(m_sftType == SFT_FIRE ){ +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CModelHolder2 :: RenderParticles (); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CAnimData * CShooter::GetAnimData(SLONG slPropertyOffset) +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +{ +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(slPropertyOffset == offsetof (CShooter , m_iModelPreFireAnimation ) || +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +slPropertyOffset == offsetof (CShooter , m_iModelPostFireAnimation )){ +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return GetModelObject () -> GetData (); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}else if(slPropertyOffset == offsetof (CShooter , m_iTexturePreFireAnimation ) || +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +slPropertyOffset == offsetof (CShooter , m_iTexturePostFireAnimation )){ +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return GetModelObject () -> mo_toTexture . GetData (); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}else { +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return CModelHolder2 :: GetAnimData (slPropertyOffset ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} + +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CEntity * CShooter::ShootProjectile(enum ProjectileType pt,FLOAT3D & vOffset,ANGLE3D & aOffset) { +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CPlacement3D pl ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +pl = GetPlacement (); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CEntityPointer penProjectile = CreateEntity (pl , CLASS_PROJECTILE ); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ELaunchProjectile eLaunch ; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . penLauncher = this ; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . prtType = pt ; +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +penProjectile -> Initialize (eLaunch ); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return penProjectile ; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void CShooter::FireFlame(void) { +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CPlacement3D plFlame ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +plFlame = GetPlacement (); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FLOAT3D vNormDir ; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +AnglesToDirectionVector (plFlame . pl_OrientationAngle , vNormDir ); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +plFlame . pl_PositionVector += vNormDir * 0.1f; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CEntityPointer penFlame = CreateEntity (plFlame , CLASS_PROJECTILE ); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ELaunchProjectile eLaunch ; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . penLauncher = this ; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . prtType = PRT_SHOOTER_FLAME ; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +penFlame -> Initialize (eLaunch ); +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(m_penFlame != NULL && ! (m_penFlame -> GetFlags () & ENF_DELETED )){ +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +((CProjectile &) * m_penFlame ) . m_penParticles = penFlame ; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +((CProjectile &) * penFlame ) . m_penParticles = this ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_penFlame = penFlame ; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} + +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void CShooter::StopFlame(void) { +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +((CProjectile &) * m_penFlame ) . m_penParticles = NULL ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} + +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void CShooter::PlayFireSound(void) { +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(m_penSoundLaunch != NULL ){ +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CSoundHolder & sh = (CSoundHolder &) * m_penSoundLaunch ; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_soLaunch . Set3DParameters (FLOAT (sh . m_rFallOffRange ) , FLOAT (sh . m_rHotSpotRange ) , sh . m_fVolume , 1.0f); +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +PlaySound (m_soLaunch , sh . m_fnSound , sh . m_iPlayType ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} + +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void CShooter::ShootCannonball() +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +{ +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CPlacement3D plBall = GetPlacement (); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CEntityPointer penBall = CreateEntity (plBall , CLASS_CANNONBALL ); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ELaunchCannonBall eLaunch ; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . penLauncher = this ; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . fLaunchPower = 10.0f + m_fCannonBallPower ; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . cbtType = CBT_IRON ; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . fSize = m_fCannonBallSize ; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +penBall -> Initialize (eLaunch ); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} + +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void CShooter::ShootFireball() +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +{ +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CPlacement3D plBall = GetPlacement (); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CEntityPointer penBall = CreateEntity (plBall , CLASS_CANNONBALL ); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ELaunchCannonBall eLaunch ; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . penLauncher = this ; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . fLaunchPower = 10.0f + m_fCannonBallPower ; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . cbtType = CBT_IRON ; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +eLaunch . fSize = m_fCannonBallSize ; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +penBall -> Initialize (eLaunch ); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +BOOL CShooter:: +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FireOnce(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CShooter_FireOnce + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CShooter::FireOnce expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(m_sftType == SFT_FIRE ){Jump(STATE_CURRENT, STATE_CShooter_FlameBurst, TRUE, EVoid());return TRUE;} +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +PlayFireSound (); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +GetModelObject () -> PlayAnim (m_iModelPreFireAnimation , 0); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +GetModelObject () -> mo_toTexture . PlayAnim (m_iTexturePreFireAnimation , 0); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (m_iModelPreFireAnimation )); +Jump(STATE_CURRENT, 0x01590001, FALSE, EBegin());return TRUE;}BOOL CShooter::H0x01590001_FireOnce_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01590002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CShooter::H0x01590002_FireOnce_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590002 +; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +switch(m_sftType ){ +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +case SFT_WOODEN_DART : +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ShootProjectile (PRT_SHOOTER_WOODEN_DART , FLOAT3D (0.0f , 0.0f , 0.0f) , ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +break ; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +case SFT_GAS : +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +break ; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +case SFT_IRONBALL : +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ShootCannonball (); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +break ; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +case SFT_FIREBALL : +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ShootProjectile (PRT_SHOOTER_FIREBALL , FLOAT3D (0.0f , 0.0f , 0.0f) , ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +break ; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +GetModelObject () -> PlayAnim (m_iModelPostFireAnimation , 0); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +GetModelObject () -> mo_toTexture . PlayAnim (m_iTexturePostFireAnimation , 0); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (m_iModelPostFireAnimation )); +Jump(STATE_CURRENT, 0x01590003, FALSE, EBegin());return TRUE;}BOOL CShooter::H0x01590003_FireOnce_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01590004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CShooter::H0x01590004_FireOnce_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590004 +; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Return(STATE_CURRENT,EEnd ()); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CShooter:: +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FireContinuous(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CShooter_FireContinuous + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CShooter::FireContinuous expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(!(m_fRndBeginWait > 0.0f)){ Jump(STATE_CURRENT,0x01590008, FALSE, EInternal());return TRUE;} +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FLOAT fRndWait = FRnd () * m_fRndBeginWait + 0.05; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +SetTimerAfter(fRndWait ); +Jump(STATE_CURRENT, 0x01590006, FALSE, EBegin());return TRUE;}BOOL CShooter::H0x01590006_FireContinuous_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01590007, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CShooter::H0x01590007_FireContinuous_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590007 +;Jump(STATE_CURRENT,0x01590008, FALSE, EInternal());return TRUE;}BOOL CShooter::H0x01590008_FireContinuous_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590008 + +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Jump(STATE_CURRENT,0x0159000d, FALSE, EInternal());return TRUE;}BOOL CShooter::H0x0159000d_FireContinuous_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000d +if(!(m_bFiring )){ Jump(STATE_CURRENT,0x0159000e, FALSE, EInternal());return TRUE;} +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +STATE_CShooter_FireOnce, TRUE; +Jump(STATE_CURRENT, 0x01590009, FALSE, EBegin());return TRUE;}BOOL CShooter::H0x01590009_FireContinuous_04(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CShooter_FireOnce, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x0159000a, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CShooter::H0x0159000a_FireContinuous_05(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000a +const EEnd&__e= (EEnd&)__eeInput; +; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +SetTimerAfter(m_fShootingPeriod ); +Jump(STATE_CURRENT, 0x0159000b, FALSE, EBegin());return TRUE;}BOOL CShooter::H0x0159000b_FireContinuous_06(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0159000c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CShooter::H0x0159000c_FireContinuous_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000c +;Jump(STATE_CURRENT,0x0159000d, FALSE, EInternal());return TRUE; +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}BOOL CShooter::H0x0159000e_FireContinuous_09(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0159000e + +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Return(STATE_CURRENT,EReturn ()); +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CShooter:: +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FlameBurst(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CShooter_FlameBurst + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CShooter::FlameBurst expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +PlayFireSound (); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_penFlame = NULL ; +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_tmFlameStart = _pTimer -> CurrentTick (); +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Jump(STATE_CURRENT,0x01590012, FALSE, EInternal());return TRUE;}BOOL CShooter::H0x01590012_FlameBurst_03(const CEntityEvent &__eeInput) +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590012 +if(!(_pTimer -> CurrentTick () < m_tmFlameStart + m_fFlameBurstDuration )){ Jump(STATE_CURRENT,0x01590013, FALSE, EInternal());return TRUE;} +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x01590010, FALSE, EBegin());return TRUE;}BOOL CShooter::H0x01590010_FlameBurst_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590010 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01590011, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CShooter::H0x01590011_FlameBurst_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590011 +; +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FireFlame ();Jump(STATE_CURRENT,0x01590012, FALSE, EInternal());return TRUE; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}BOOL CShooter::H0x01590013_FlameBurst_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590013 + +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +StopFlame (); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Return(STATE_CURRENT,EEnd ()); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CShooter:: +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +MainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CShooter_MainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CShooter::MainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01590015, FALSE, EBegin());return TRUE;}BOOL CShooter::H0x01590015_MainLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590015 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return TRUE; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; + +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(! m_bFiring ){ +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Call(STATE_CURRENT, STATE_CShooter_FireOnce, TRUE, EVoid());return TRUE; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}else { +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return TRUE; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}ASSERT(FALSE);break;case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_bFiring = TRUE ; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Call(STATE_CURRENT, STATE_CShooter_FireContinuous, TRUE, EVoid());return TRUE; +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_bFiring = FALSE ; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return TRUE; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; + +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(m_penDestruction != NULL ){ +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Jump(STATE_CURRENT, STATE_CModelHolder2_Die, FALSE, EVoid());return TRUE; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}else { +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Destroy (); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Return(STATE_CURRENT,EVoid()); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return TRUE; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; + +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return TRUE; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}return TRUE;}BOOL CShooter::H0x01590016_MainLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590016 + ASSERT(FALSE); return TRUE;};BOOL CShooter:: +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CShooter_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CShooter::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CModelHolder2 :: InitModelHolder (); +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(m_fHealth > 0.0f){ +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +SetHealth (m_fHealth ); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_bIndestructable = FALSE ; +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +}else { +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +SetHealth (10000.0f); +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_bIndestructable = TRUE ; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ClampUp (m_fCannonBallSize , 10.0f); +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ClampDn (m_fCannonBallSize , 0.1f); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ClampUp (m_fCannonBallPower , 100.0f); +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +ClampDn (m_fCannonBallPower , 0.0f); +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(m_penSoundLaunch != NULL && ! IsOfClass (m_penSoundLaunch , "SoundHolder")){ +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +WarningMessage ("Entity '%s' is not of class SoundHolder!" , m_penSoundLaunch ); +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_penSoundLaunch = NULL ; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +if(m_penDestruction != NULL && ! IsOfClass (m_penDestruction , "ModelDestruction")){ +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +WarningMessage ("Entity '%s' is not of class ModelDestruction!" , m_penDestruction ); +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +m_penDestruction = NULL ; +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +} +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01590017, FALSE, EBegin());return TRUE;}BOOL CShooter::H0x01590017_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590017 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01590018, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CShooter::H0x01590018_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01590018 +; +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Jump(STATE_CURRENT, STATE_CShooter_MainLoop, TRUE, EVoid());return TRUE; +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Return(STATE_CURRENT,EVoid()); +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Shooter.es b/Sources/EntitiesMP/Shooter.es new file mode 100644 index 0000000..ba1e8cc --- /dev/null +++ b/Sources/EntitiesMP/Shooter.es @@ -0,0 +1,360 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +345 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/ModelHolder2"; +uses "EntitiesMP/Projectile"; +uses "EntitiesMP/SoundHolder"; +uses "EntitiesMP/BloodSpray"; +uses "EntitiesMP/CannonBall"; + +enum FireType { + 0 SFT_WOODEN_DART "Wooden dart", + 1 SFT_FIRE "Fire", + 2 SFT_GAS "-none-", + 3 SFT_IRONBALL "Ironball", + 4 SFT_FIREBALL "Fireball", +}; + +class CShooter: CModelHolder2 { +name "Shooter"; +thumbnail "Thumbnails\\Shooter.tbn"; +features "HasName", "IsTargetable"; + +properties: + + 2 FLOAT m_fShootingPeriod "Shooting Period" = 1.0f, + 5 enum FireType m_sftType "Type" 'Y' = SFT_WOODEN_DART, + 7 FLOAT m_fHealth "Health" = 0.0f, + 8 FLOAT m_fCannonBallSize "Cannon/fire ball size" = 1.0f, + 9 FLOAT m_fCannonBallPower "Cannon/fire ball power" = 10.0f, + 10 ANIMATION m_iModelPreFireAnimation "Model pre-fire animation" = 0, + 11 ANIMATION m_iTexturePreFireAnimation "Texture pre-fire animation" = 0, + 12 ANIMATION m_iModelPostFireAnimation "Model post-fire animation" = 0, + 13 ANIMATION m_iTexturePostFireAnimation "Texture post-fire animation" = 0, + 14 FLOAT m_fFlameBurstDuration "Flame burst duration" = 1.0f, + 15 FLOAT m_fRndBeginWait "Random begin wait time" = 0.0f, + + 20 CEntityPointer m_penSoundLaunch "Sound launch", // sound when firing + 21 CSoundObject m_soLaunch, + + 30 CEntityPointer m_penFlame, + //internal: + + 50 BOOL m_bFiring = FALSE, + 51 BOOL m_bIndestructable = FALSE, + + 60 FLOAT m_tmFlameStart = 0.0f, + +components: + 1 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 2 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + 3 class CLASS_CANNONBALL "Classes\\CannonBall.ecl", + +functions: + + void Precache(void) { + CModelHolder2::Precache(); + PrecacheClass(CLASS_PROJECTILE, PRT_SHOOTER_WOODEN_DART); + PrecacheClass(CLASS_PROJECTILE, PRT_SHOOTER_FIREBALL); + PrecacheClass(CLASS_CANNONBALL); + }; + + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // receive damage if not indestructable, and shooter can't hurt another shooter + if (!m_bIndestructable && !IsOfClass(penInflictor, "Shooter")) { + if (m_tmSpraySpawned<=_pTimer->CurrentTick()-_pTimer->TickQuantum*8 + && m_penDestruction!=NULL) { + + CModelDestruction *penDestruction = GetDestruction(); + + // spawn blood spray + CPlacement3D plSpray = CPlacement3D( vHitPoint, ANGLE3D(0, 0, 0)); + m_penSpray = CreateEntity( plSpray, CLASS_BLOOD_SPRAY); + m_penSpray->SetParent(this); + ESpawnSpray eSpawnSpray; + eSpawnSpray.colBurnColor=C_WHITE|CT_OPAQUE; + + // adjust spray power + if( fDamageAmmount > 50.0f) { + eSpawnSpray.fDamagePower = 3.0f; + } else if(fDamageAmmount > 25.0f ) { + eSpawnSpray.fDamagePower = 2.0f; + } else { + eSpawnSpray.fDamagePower = 1.0f; + } + + // remember spray type + eSpawnSpray.sptType = penDestruction->m_sptType; + eSpawnSpray.fSizeMultiplier = 1.0f; + + // get your down vector (simulates gravity) + FLOAT3D vDn(-en_mRotation(1,2), -en_mRotation(2,2), -en_mRotation(3,2)); + + // setup direction of spray + FLOAT3D vHitPointRelative = vHitPoint - GetPlacement().pl_PositionVector; + FLOAT3D vReflectingNormal; + GetNormalComponent( vHitPointRelative, vDn, vReflectingNormal); + vReflectingNormal.Normalize(); + + vReflectingNormal(1)/=5.0f; + + FLOAT3D vProjectedComponent = vReflectingNormal*(vDirection%vReflectingNormal); + FLOAT3D vSpilDirection = vDirection-vProjectedComponent*2.0f-vDn*0.5f; + + eSpawnSpray.vDirection = vSpilDirection; + eSpawnSpray.penOwner = this; + + // initialize spray + m_penSpray->Initialize( eSpawnSpray); + m_tmSpraySpawned = _pTimer->CurrentTick(); + } + + CRationalEntity::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + } + + // render particles + void RenderParticles(void) + { + // fire particles + if (m_sftType==SFT_FIRE) { + } + CModelHolder2::RenderParticles(); + } + + /* Get anim data for given animation property - return NULL for none. */ + CAnimData *GetAnimData(SLONG slPropertyOffset) + { + if (slPropertyOffset==offsetof(CShooter, m_iModelPreFireAnimation) || + slPropertyOffset==offsetof(CShooter, m_iModelPostFireAnimation)) { + return GetModelObject()->GetData(); + } else if (slPropertyOffset==offsetof(CShooter, m_iTexturePreFireAnimation) || + slPropertyOffset==offsetof(CShooter, m_iTexturePostFireAnimation)) { + return GetModelObject()->mo_toTexture.GetData(); + } else { + return CModelHolder2::GetAnimData(slPropertyOffset); + } + } + + // shoot projectile on enemy + CEntity *ShootProjectile(enum ProjectileType pt, FLOAT3D &vOffset, ANGLE3D &aOffset) { + // launch + CPlacement3D pl; + pl = GetPlacement(); + CEntityPointer penProjectile = CreateEntity(pl, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = pt; + penProjectile->Initialize(eLaunch); + + return penProjectile; + }; + + // fire flame + void FireFlame(void) { + // flame start position + CPlacement3D plFlame; + plFlame = GetPlacement(); + + FLOAT3D vNormDir; + AnglesToDirectionVector(plFlame.pl_OrientationAngle, vNormDir); + plFlame.pl_PositionVector += vNormDir*0.1f; + + // create flame + CEntityPointer penFlame = CreateEntity(plFlame, CLASS_PROJECTILE); + // init and launch flame + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_SHOOTER_FLAME; + penFlame->Initialize(eLaunch); + // link last flame with this one (if not NULL or deleted) + if (m_penFlame!=NULL && !(m_penFlame->GetFlags()&ENF_DELETED)) { + ((CProjectile&)*m_penFlame).m_penParticles = penFlame; + } + // link to this + ((CProjectile&)*penFlame).m_penParticles = this; + // store last flame + m_penFlame = penFlame; + }; + + void StopFlame(void) { + ((CProjectile&)*m_penFlame).m_penParticles = NULL; + //m_penFlame = NULL; + } + + void PlayFireSound(void) { + // if sound entity exists + if (m_penSoundLaunch!=NULL) { + CSoundHolder &sh = (CSoundHolder&)*m_penSoundLaunch; + m_soLaunch.Set3DParameters(FLOAT(sh.m_rFallOffRange), FLOAT(sh.m_rHotSpotRange), sh.m_fVolume, 1.0f); + PlaySound(m_soLaunch, sh.m_fnSound, sh.m_iPlayType); + } + }; + + void ShootCannonball() + { + // cannon ball start position + CPlacement3D plBall = GetPlacement(); + // create cannon ball + CEntityPointer penBall = CreateEntity(plBall, CLASS_CANNONBALL); + // init and launch cannon ball + ELaunchCannonBall eLaunch; + eLaunch.penLauncher = this; + eLaunch.fLaunchPower = 10.0f+m_fCannonBallPower; // ranges from 50-150 (since iPower can be max 100) + eLaunch.cbtType = CBT_IRON; + eLaunch.fSize = m_fCannonBallSize; + penBall->Initialize(eLaunch); + }; + + void ShootFireball() + { + // cannon ball start position + CPlacement3D plBall = GetPlacement(); + // create cannon ball + CEntityPointer penBall = CreateEntity(plBall, CLASS_CANNONBALL); + // init and launch cannon ball + ELaunchCannonBall eLaunch; + eLaunch.penLauncher = this; + eLaunch.fLaunchPower = 10.0f+m_fCannonBallPower; // ranges from 50-150 (since iPower can be max 100) + eLaunch.cbtType = CBT_IRON; + eLaunch.fSize = m_fCannonBallSize; + penBall->Initialize(eLaunch); + }; + +procedures: + + FireOnce() + { + if (m_sftType==SFT_FIRE) { jump FlameBurst(); } + + PlayFireSound(); + + GetModelObject()->PlayAnim(m_iModelPreFireAnimation, 0); + GetModelObject()->mo_toTexture.PlayAnim(m_iTexturePreFireAnimation, 0); + autowait(GetModelObject()->GetAnimLength(m_iModelPreFireAnimation)); + + switch (m_sftType) { + case SFT_WOODEN_DART: + ShootProjectile(PRT_SHOOTER_WOODEN_DART, FLOAT3D (0.0f, 0.0f, 0.0f), ANGLE3D (0.0f, 0.0f, 0.0f)); + break; + case SFT_GAS: + break; + case SFT_IRONBALL: + ShootCannonball(); + break; + case SFT_FIREBALL: + ShootProjectile(PRT_SHOOTER_FIREBALL, FLOAT3D (0.0f, 0.0f, 0.0f), ANGLE3D (0.0f, 0.0f, 0.0f)); + break; + } + + GetModelObject()->PlayAnim(m_iModelPostFireAnimation, 0); + GetModelObject()->mo_toTexture.PlayAnim(m_iTexturePostFireAnimation, 0); + autowait(GetModelObject()->GetAnimLength(m_iModelPostFireAnimation)); + + return EEnd(); + } + + FireContinuous() { + + // possible random wait + if (m_fRndBeginWait>0.0f) + { + FLOAT fRndWait = FRnd()*m_fRndBeginWait+0.05; + autowait(fRndWait); + } + + while(m_bFiring) { + autocall FireOnce() EEnd; + autowait(m_fShootingPeriod); + } + return EReturn(); + }; + + FlameBurst() { + PlayFireSound(); + m_penFlame = NULL; + m_tmFlameStart = _pTimer->CurrentTick(); + while(_pTimer->CurrentTick( ) < m_tmFlameStart + m_fFlameBurstDuration) + { + // wait a bit and fire + autowait(0.05f); + FireFlame(); + } + StopFlame(); + return EEnd(); + }; + + MainLoop() { + //main loop + wait() { + on (EBegin) : { + resume; + } + on (ETrigger) : { + if (!m_bFiring) { + call FireOnce(); + } else { + resume; + } + } + on (EActivate) : { + m_bFiring = TRUE; + call FireContinuous(); + } + on (EDeactivate) : { + m_bFiring = FALSE; + resume; + } + on (EDeath) : { + if (m_penDestruction!=NULL) { + jump CModelHolder2::Die(); + } else { + Destroy(); + return; + } + } + on (EReturn) : { + resume; + } + } + }; + + Main() { + // init as model + CModelHolder2::InitModelHolder(); + + if (m_fHealth>0.0f) { + SetHealth(m_fHealth); + m_bIndestructable = FALSE; + } else { + SetHealth(10000.0f); + m_bIndestructable = TRUE; + } + + ClampUp(m_fCannonBallSize, 10.0f); + ClampDn(m_fCannonBallSize, 0.1f); + ClampUp(m_fCannonBallPower, 100.0f); + ClampDn(m_fCannonBallPower, 0.0f); + + if (m_penSoundLaunch!=NULL && !IsOfClass(m_penSoundLaunch, "SoundHolder")) { + WarningMessage( "Entity '%s' is not of class SoundHolder!", m_penSoundLaunch); + m_penSoundLaunch=NULL; + } + if (m_penDestruction!=NULL && !IsOfClass(m_penDestruction, "ModelDestruction")) { + WarningMessage( "Entity '%s' is not of class ModelDestruction!", m_penDestruction); + m_penDestruction=NULL; + } + + autowait(_pTimer->TickQuantum); + + jump MainLoop(); + + return; + }; +}; diff --git a/Sources/EntitiesMP/Shooter.h b/Sources/EntitiesMP/Shooter.h new file mode 100644 index 0000000..9479853 --- /dev/null +++ b/Sources/EntitiesMP/Shooter.h @@ -0,0 +1,118 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Shooter_INCLUDED +#define _EntitiesMP_Shooter_INCLUDED 1 +#include +#include +#include +#include +#include +extern DECL_DLL CEntityPropertyEnumType FireType_enum; +enum FireType { + SFT_WOODEN_DART = 0, + SFT_FIRE = 1, + SFT_GAS = 2, + SFT_IRONBALL = 3, + SFT_FIREBALL = 4, +}; +DECL_DLL inline void ClearToDefault(FireType &e) { e = (FireType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CShooter_DLLClass; +class CShooter : public CModelHolder2 { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fShootingPeriod; + enum FireType m_sftType; + FLOAT m_fHealth; + FLOAT m_fCannonBallSize; + FLOAT m_fCannonBallPower; + ANIMATION m_iModelPreFireAnimation; + ANIMATION m_iTexturePreFireAnimation; + ANIMATION m_iModelPostFireAnimation; + ANIMATION m_iTexturePostFireAnimation; + FLOAT m_fFlameBurstDuration; + FLOAT m_fRndBeginWait; + CEntityPointer m_penSoundLaunch; + CSoundObject m_soLaunch; + CEntityPointer m_penFlame; + BOOL m_bFiring; + BOOL m_bIndestructable; + FLOAT m_tmFlameStart; + +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void Precache(void); + +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void RenderParticles(void); + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CAnimData * GetAnimData(SLONG slPropertyOffset); + +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +CEntity * ShootProjectile(enum ProjectileType pt,FLOAT3D & vOffset,ANGLE3D & aOffset); + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void FireFlame(void); + +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void StopFlame(void); + +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void PlayFireSound(void); + +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void ShootCannonball(); + +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +void ShootFireball(); +#define STATE_CShooter_FireOnce 0x01590000 + BOOL +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FireOnce(const CEntityEvent &__eeInput); + BOOL H0x01590001_FireOnce_01(const CEntityEvent &__eeInput); + BOOL H0x01590002_FireOnce_02(const CEntityEvent &__eeInput); + BOOL H0x01590003_FireOnce_03(const CEntityEvent &__eeInput); + BOOL H0x01590004_FireOnce_04(const CEntityEvent &__eeInput); +#define STATE_CShooter_FireContinuous 0x01590005 + BOOL +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FireContinuous(const CEntityEvent &__eeInput); + BOOL H0x01590006_FireContinuous_01(const CEntityEvent &__eeInput); + BOOL H0x01590007_FireContinuous_02(const CEntityEvent &__eeInput); + BOOL H0x01590008_FireContinuous_03(const CEntityEvent &__eeInput); + BOOL H0x01590009_FireContinuous_04(const CEntityEvent &__eeInput); + BOOL H0x0159000a_FireContinuous_05(const CEntityEvent &__eeInput); + BOOL H0x0159000b_FireContinuous_06(const CEntityEvent &__eeInput); + BOOL H0x0159000c_FireContinuous_07(const CEntityEvent &__eeInput); + BOOL H0x0159000d_FireContinuous_08(const CEntityEvent &__eeInput); + BOOL H0x0159000e_FireContinuous_09(const CEntityEvent &__eeInput); +#define STATE_CShooter_FlameBurst 0x0159000f + BOOL +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FlameBurst(const CEntityEvent &__eeInput); + BOOL H0x01590010_FlameBurst_01(const CEntityEvent &__eeInput); + BOOL H0x01590011_FlameBurst_02(const CEntityEvent &__eeInput); + BOOL H0x01590012_FlameBurst_03(const CEntityEvent &__eeInput); + BOOL H0x01590013_FlameBurst_04(const CEntityEvent &__eeInput); +#define STATE_CShooter_MainLoop 0x01590014 + BOOL +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +MainLoop(const CEntityEvent &__eeInput); + BOOL H0x01590015_MainLoop_01(const CEntityEvent &__eeInput); + BOOL H0x01590016_MainLoop_02(const CEntityEvent &__eeInput); +#define STATE_CShooter_Main 1 + BOOL +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01590017_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01590018_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Shooter_INCLUDED diff --git a/Sources/EntitiesMP/Shooter_tables.h b/Sources/EntitiesMP/Shooter_tables.h new file mode 100644 index 0000000..c7b7b1a --- /dev/null +++ b/Sources/EntitiesMP/Shooter_tables.h @@ -0,0 +1,95 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(FireType) + EP_ENUMVALUE(SFT_WOODEN_DART, "Wooden dart"), + EP_ENUMVALUE(SFT_FIRE, "Fire"), + EP_ENUMVALUE(SFT_GAS, "-none-"), + EP_ENUMVALUE(SFT_IRONBALL, "Ironball"), + EP_ENUMVALUE(SFT_FIREBALL, "Fireball"), +EP_ENUMEND(FireType); + +#define ENTITYCLASS CShooter + +CEntityProperty CShooter_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+2, offsetof(CShooter, m_fShootingPeriod), "Shooting Period", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &FireType_enum, (0x00000159<<8)+5, offsetof(CShooter, m_sftType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+7, offsetof(CShooter, m_fHealth), "Health", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+8, offsetof(CShooter, m_fCannonBallSize), "Cannon/fire ball size", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+9, offsetof(CShooter, m_fCannonBallPower), "Cannon/fire ball power", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000159<<8)+10, offsetof(CShooter, m_iModelPreFireAnimation), "Model pre-fire animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000159<<8)+11, offsetof(CShooter, m_iTexturePreFireAnimation), "Texture pre-fire animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000159<<8)+12, offsetof(CShooter, m_iModelPostFireAnimation), "Model post-fire animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x00000159<<8)+13, offsetof(CShooter, m_iTexturePostFireAnimation), "Texture post-fire animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+14, offsetof(CShooter, m_fFlameBurstDuration), "Flame burst duration", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+15, offsetof(CShooter, m_fRndBeginWait), "Random begin wait time", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000159<<8)+20, offsetof(CShooter, m_penSoundLaunch), "Sound launch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000159<<8)+21, offsetof(CShooter, m_soLaunch), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000159<<8)+30, offsetof(CShooter, m_penFlame), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000159<<8)+50, offsetof(CShooter, m_bFiring), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000159<<8)+51, offsetof(CShooter, m_bIndestructable), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000159<<8)+60, offsetof(CShooter, m_tmFlameStart), "", 0, 0, 0), +}; +#define CShooter_propertiesct ARRAYCOUNT(CShooter_properties) + +CEntityComponent CShooter_components[] = { +#define CLASS_PROJECTILE ((0x00000159<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_BLOOD_SPRAY ((0x00000159<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define CLASS_CANNONBALL ((0x00000159<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_CANNONBALL, "EFNM" "Classes\\CannonBall.ecl"), +}; +#define CShooter_componentsct ARRAYCOUNT(CShooter_components) + +CEventHandlerEntry CShooter_handlers[] = { + {0x01590000, -1, CEntity::pEventHandler(&CShooter:: +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FireOnce),DEBUGSTRING("CShooter::FireOnce")}, + {0x01590001, -1, CEntity::pEventHandler(&CShooter::H0x01590001_FireOnce_01), DEBUGSTRING("CShooter::H0x01590001_FireOnce_01")}, + {0x01590002, -1, CEntity::pEventHandler(&CShooter::H0x01590002_FireOnce_02), DEBUGSTRING("CShooter::H0x01590002_FireOnce_02")}, + {0x01590003, -1, CEntity::pEventHandler(&CShooter::H0x01590003_FireOnce_03), DEBUGSTRING("CShooter::H0x01590003_FireOnce_03")}, + {0x01590004, -1, CEntity::pEventHandler(&CShooter::H0x01590004_FireOnce_04), DEBUGSTRING("CShooter::H0x01590004_FireOnce_04")}, + {0x01590005, -1, CEntity::pEventHandler(&CShooter:: +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FireContinuous),DEBUGSTRING("CShooter::FireContinuous")}, + {0x01590006, -1, CEntity::pEventHandler(&CShooter::H0x01590006_FireContinuous_01), DEBUGSTRING("CShooter::H0x01590006_FireContinuous_01")}, + {0x01590007, -1, CEntity::pEventHandler(&CShooter::H0x01590007_FireContinuous_02), DEBUGSTRING("CShooter::H0x01590007_FireContinuous_02")}, + {0x01590008, -1, CEntity::pEventHandler(&CShooter::H0x01590008_FireContinuous_03), DEBUGSTRING("CShooter::H0x01590008_FireContinuous_03")}, + {0x01590009, -1, CEntity::pEventHandler(&CShooter::H0x01590009_FireContinuous_04), DEBUGSTRING("CShooter::H0x01590009_FireContinuous_04")}, + {0x0159000a, -1, CEntity::pEventHandler(&CShooter::H0x0159000a_FireContinuous_05), DEBUGSTRING("CShooter::H0x0159000a_FireContinuous_05")}, + {0x0159000b, -1, CEntity::pEventHandler(&CShooter::H0x0159000b_FireContinuous_06), DEBUGSTRING("CShooter::H0x0159000b_FireContinuous_06")}, + {0x0159000c, -1, CEntity::pEventHandler(&CShooter::H0x0159000c_FireContinuous_07), DEBUGSTRING("CShooter::H0x0159000c_FireContinuous_07")}, + {0x0159000d, -1, CEntity::pEventHandler(&CShooter::H0x0159000d_FireContinuous_08), DEBUGSTRING("CShooter::H0x0159000d_FireContinuous_08")}, + {0x0159000e, -1, CEntity::pEventHandler(&CShooter::H0x0159000e_FireContinuous_09), DEBUGSTRING("CShooter::H0x0159000e_FireContinuous_09")}, + {0x0159000f, -1, CEntity::pEventHandler(&CShooter:: +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +FlameBurst),DEBUGSTRING("CShooter::FlameBurst")}, + {0x01590010, -1, CEntity::pEventHandler(&CShooter::H0x01590010_FlameBurst_01), DEBUGSTRING("CShooter::H0x01590010_FlameBurst_01")}, + {0x01590011, -1, CEntity::pEventHandler(&CShooter::H0x01590011_FlameBurst_02), DEBUGSTRING("CShooter::H0x01590011_FlameBurst_02")}, + {0x01590012, -1, CEntity::pEventHandler(&CShooter::H0x01590012_FlameBurst_03), DEBUGSTRING("CShooter::H0x01590012_FlameBurst_03")}, + {0x01590013, -1, CEntity::pEventHandler(&CShooter::H0x01590013_FlameBurst_04), DEBUGSTRING("CShooter::H0x01590013_FlameBurst_04")}, + {0x01590014, -1, CEntity::pEventHandler(&CShooter:: +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +MainLoop),DEBUGSTRING("CShooter::MainLoop")}, + {0x01590015, -1, CEntity::pEventHandler(&CShooter::H0x01590015_MainLoop_01), DEBUGSTRING("CShooter::H0x01590015_MainLoop_01")}, + {0x01590016, -1, CEntity::pEventHandler(&CShooter::H0x01590016_MainLoop_02), DEBUGSTRING("CShooter::H0x01590016_MainLoop_02")}, + {1, -1, CEntity::pEventHandler(&CShooter:: +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Shooter.es" +Main),DEBUGSTRING("CShooter::Main")}, + {0x01590017, -1, CEntity::pEventHandler(&CShooter::H0x01590017_Main_01), DEBUGSTRING("CShooter::H0x01590017_Main_01")}, + {0x01590018, -1, CEntity::pEventHandler(&CShooter::H0x01590018_Main_02), DEBUGSTRING("CShooter::H0x01590018_Main_02")}, +}; +#define CShooter_handlersct ARRAYCOUNT(CShooter_handlers) + +CEntity *CShooter_New(void) { return new CShooter; }; +void CShooter_OnInitClass(void) {}; +void CShooter_OnEndClass(void) {}; +void CShooter_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CShooter_OnWorldEnd(CWorld *pwo) {}; +void CShooter_OnWorldInit(CWorld *pwo) {}; +void CShooter_OnWorldTick(CWorld *pwo) {}; +void CShooter_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CShooter, CModelHolder2, "Shooter", "Thumbnails\\Shooter.tbn", 0x00000159); +DECLARE_CTFILENAME(_fnmCShooter_tbn, "Thumbnails\\Shooter.tbn"); diff --git a/Sources/EntitiesMP/SoundHolder.cpp b/Sources/EntitiesMP/SoundHolder.cpp new file mode 100644 index 0000000..1eda1c3 --- /dev/null +++ b/Sources/EntitiesMP/SoundHolder.cpp @@ -0,0 +1,189 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 7 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" + +#include "StdH.h" + +#include +#include +void CSoundHolder::SetDefaultProperties(void) { + m_fnSound = CTFILENAME("Sounds\\Default.wav"); + m_rFallOffRange = 100.0f; + m_rHotSpotRange = 50.0f; + m_fVolume = 1.0f; + m_bLoop = TRUE ; + m_bSurround = FALSE ; + m_bVolumetric = TRUE ; + m_strName = ""; + m_strDescription = ""; + m_bAutoStart = FALSE ; + m_iPlayType = 0; + m_soSound.SetOwner(this); +m_soSound.Stop_internal(); + m_bDestroyable = FALSE ; + CRationalEntity::SetDefaultProperties(); +} + +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +void CSoundHolder::Precache(void) +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +{ +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +m_aps . Precache (m_fnSound ); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +} + +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +void CSoundHolder::MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX) +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +{ +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +m_rFallOffRange *= fStretch ; +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +m_rHotSpotRange *= fStretch ; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +} + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +SLONG CSoundHolder::GetUsedMemory(void) +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +{ +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +SLONG slUsedMemory = sizeof (CSoundHolder ) - sizeof (CRationalEntity ) + CRationalEntity :: GetUsedMemory (); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +slUsedMemory += m_strName . Length (); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +slUsedMemory += m_strDescription . Length (); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +slUsedMemory += m_fnSound . Length (); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +slUsedMemory += 1 * sizeof (CSoundObject); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +return slUsedMemory ; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +} +BOOL CSoundHolder:: +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSoundHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSoundHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +if(m_rHotSpotRange < 0.0f){m_rHotSpotRange = 0.0f;} +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +if(m_rFallOffRange < m_rHotSpotRange ){m_rFallOffRange = m_rHotSpotRange ;} +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +if(m_fVolume < FLOAT (SL_VOLUME_MIN )){m_fVolume = FLOAT (SL_VOLUME_MIN );} +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +if(m_fVolume > FLOAT (SL_VOLUME_MAX )){m_fVolume = FLOAT (SL_VOLUME_MAX );} +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +m_iPlayType = SOF_3D ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +if(m_bLoop ){m_iPlayType |= SOF_LOOP ;} +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +if(m_bSurround ){m_iPlayType |= SOF_SURROUND ;} +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +if(m_bVolumetric ){m_iPlayType |= SOF_VOLUMETRIC ;} +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +InitAsEditorModel (); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +const float SOUND_MINSIZE = 1.0f; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +FLOAT fFactor = Log2 (m_rFallOffRange ) * SOUND_MINSIZE ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +if(fFactor < SOUND_MINSIZE ){ +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +fFactor = SOUND_MINSIZE ; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +} +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +GetModelObject () -> mo_Stretch = FLOAT3D (fFactor , fFactor , fFactor ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +SetModel (MODEL_MARKER ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +m_strDescription . PrintF ("%s" , (CTString &) m_fnSound . FileName ()); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +if(!(_pTimer -> CurrentTick () <= 0.1f)){ Jump(STATE_CURRENT,0x00cc0002, FALSE, EInternal());return TRUE;} +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x00cc0000, FALSE, EBegin());return TRUE;}BOOL CSoundHolder::H0x00cc0000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cc0000 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00cc0001, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSoundHolder::H0x00cc0001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cc0001 +;Jump(STATE_CURRENT,0x00cc0002, FALSE, EInternal());return TRUE;}BOOL CSoundHolder::H0x00cc0002_Main_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cc0002 + +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00cc0003, FALSE, EBegin());return TRUE;}BOOL CSoundHolder::H0x00cc0003_Main_04(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cc0003 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +if(m_bAutoStart ){ +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +m_soSound . Set3DParameters (FLOAT (m_rFallOffRange ) , FLOAT (m_rHotSpotRange ) , m_fVolume , 1.0f); +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +PlaySound (m_soSound , m_fnSound , m_iPlayType ); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +} +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +return TRUE; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; + +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +m_soSound . Set3DParameters (FLOAT (m_rFallOffRange ) , FLOAT (m_rHotSpotRange ) , m_fVolume , 1.0f); +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +PlaySound (m_soSound , m_fnSound , m_iPlayType ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +return TRUE; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +m_soSound . Stop (); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +return TRUE; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_ERangeModelDestruction):{const ERangeModelDestruction&e= (ERangeModelDestruction&)__eeInput; + +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +if(m_bDestroyable ){ +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +m_soSound . Stop (); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +} +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +Return(STATE_CURRENT,TRUE ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +return TRUE; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnd):{const EEnd&e= (EEnd&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x00cc0004, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +}return TRUE;}BOOL CSoundHolder::H0x00cc0004_Main_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cc0004 + +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +Destroy (); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/SoundHolder.es b/Sources/EntitiesMP/SoundHolder.es new file mode 100644 index 0000000..f9a2545 --- /dev/null +++ b/Sources/EntitiesMP/SoundHolder.es @@ -0,0 +1,156 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +/* + * Sound Holder. + */ +204 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/ModelDestruction"; + +class CSoundHolder : CRationalEntity { +name "SoundHolder"; +thumbnail "Thumbnails\\SoundHolder.tbn"; +features "HasName", "HasDescription", "IsTargetable"; + + +properties: + + 1 CTFileName m_fnSound "Sound" 'S' = CTFILENAME("Sounds\\Default.wav"), // sound + 2 RANGE m_rFallOffRange "Fall-off" 'F' = 100.0f, + 3 RANGE m_rHotSpotRange "Hot-spot" 'H' = 50.0f, + 4 FLOAT m_fVolume "Volume" 'V' = 1.0f, + 6 BOOL m_bLoop "Looping" 'L' = TRUE, + 7 BOOL m_bSurround "Surround" 'R' = FALSE, + 8 BOOL m_bVolumetric "Volumetric" 'O' = TRUE, + 9 CTString m_strName "Name" 'N' = "", + 10 CTString m_strDescription = "", + 11 BOOL m_bAutoStart "Auto start" 'A' = FALSE, // auto start (environment sounds) + 12 INDEX m_iPlayType = 0, + 13 CSoundObject m_soSound, // sound channel + 14 BOOL m_bDestroyable "Destroyable" 'Q' = FALSE, + + { + CAutoPrecacheSound m_aps; + } + + +components: + + 1 model MODEL_MARKER "Models\\Editor\\SoundHolder.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\SoundHolder.tex" + + +functions: + + void Precache(void) + { + m_aps.Precache(m_fnSound); + } + + // apply mirror and stretch to the entity + void MirrorAndStretch(FLOAT fStretch, BOOL bMirrorX) + { + // stretch its ranges + m_rFallOffRange*=fStretch; + m_rHotSpotRange*=fStretch; + //(void)bMirrorX; // no mirror for sounds + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CSoundHolder) - sizeof(CRationalEntity) + CRationalEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strName.Length(); + slUsedMemory += m_strDescription.Length(); + slUsedMemory += m_fnSound.Length(); + slUsedMemory += 1* sizeof(CSoundObject); + return slUsedMemory; + } + + + +procedures: + + Main(EVoid) + { + // validate range + if (m_rHotSpotRange<0.0f) { m_rHotSpotRange = 0.0f; } + if (m_rFallOffRangeFLOAT(SL_VOLUME_MAX)) { m_fVolume = FLOAT(SL_VOLUME_MAX); } + + // determine play type + m_iPlayType = SOF_3D; + if (m_bLoop) { m_iPlayType |= SOF_LOOP; } + if (m_bSurround) { m_iPlayType |= SOF_SURROUND; } + if (m_bVolumetric) { m_iPlayType |= SOF_VOLUMETRIC; } + + // init as model + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set stretch factors - MUST BE DONE BEFORE SETTING MODEL! + const float SOUND_MINSIZE=1.0f; + FLOAT fFactor = Log2(m_rFallOffRange)*SOUND_MINSIZE; + if (fFactormo_Stretch = FLOAT3D( fFactor, fFactor, fFactor); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + m_strDescription.PrintF("%s", (CTString&)m_fnSound.FileName()); + + // wait for a while to play sound -> Sound Can Be Spawned + if( _pTimer->CurrentTick()<=0.1f) + { + autowait(0.5f); + } + + wait() { + // auto play sound + on (EBegin) : { + if (m_bAutoStart) { + m_soSound.Set3DParameters(FLOAT(m_rFallOffRange), FLOAT(m_rHotSpotRange), m_fVolume, 1.0f); + PlaySound(m_soSound, m_fnSound, m_iPlayType); + } + resume; + } + // play sound + on (EStart) : { + m_soSound.Set3DParameters(FLOAT(m_rFallOffRange), FLOAT(m_rHotSpotRange), m_fVolume, 1.0f); + PlaySound(m_soSound, m_fnSound, m_iPlayType); + resume; + } + // stop playing sound + on (EStop) : { + m_soSound.Stop(); + resume; + } + // when someone in range is destroyed + on (ERangeModelDestruction) : { + // if range destruction is enabled + if (m_bDestroyable) { + // stop playing + m_soSound.Stop(); + } + return TRUE; + } + on (EEnd) : { stop; } + } + + // cease to exist + Destroy(); + return; + } +}; diff --git a/Sources/EntitiesMP/SoundHolder.h b/Sources/EntitiesMP/SoundHolder.h new file mode 100644 index 0000000..783f8ed --- /dev/null +++ b/Sources/EntitiesMP/SoundHolder.h @@ -0,0 +1,48 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_SoundHolder_INCLUDED +#define _EntitiesMP_SoundHolder_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CSoundHolder_DLLClass; +class CSoundHolder : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual const CTString &GetDescription(void) const { return m_strDescription; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTFileName m_fnSound; + RANGE m_rFallOffRange; + RANGE m_rHotSpotRange; + FLOAT m_fVolume; + BOOL m_bLoop; + BOOL m_bSurround; + BOOL m_bVolumetric; + CTString m_strName; + CTString m_strDescription; + BOOL m_bAutoStart; + INDEX m_iPlayType; + CSoundObject m_soSound; + BOOL m_bDestroyable; +CAutoPrecacheSound m_aps; + +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +void Precache(void); + +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +void MirrorAndStretch(FLOAT fStretch,BOOL bMirrorX); + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +SLONG GetUsedMemory(void); +#define STATE_CSoundHolder_Main 1 + BOOL +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00cc0000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00cc0001_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00cc0002_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00cc0003_Main_04(const CEntityEvent &__eeInput); + BOOL H0x00cc0004_Main_05(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_SoundHolder_INCLUDED diff --git a/Sources/EntitiesMP/SoundHolder_tables.h b/Sources/EntitiesMP/SoundHolder_tables.h new file mode 100644 index 0000000..6aab498 --- /dev/null +++ b/Sources/EntitiesMP/SoundHolder_tables.h @@ -0,0 +1,53 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CSoundHolder + +CEntityProperty CSoundHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000cc<<8)+1, offsetof(CSoundHolder, m_fnSound), "Sound", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x000000cc<<8)+2, offsetof(CSoundHolder, m_rFallOffRange), "Fall-off", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x000000cc<<8)+3, offsetof(CSoundHolder, m_rHotSpotRange), "Hot-spot", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000cc<<8)+4, offsetof(CSoundHolder, m_fVolume), "Volume", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cc<<8)+6, offsetof(CSoundHolder, m_bLoop), "Looping", 'L', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cc<<8)+7, offsetof(CSoundHolder, m_bSurround), "Surround", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cc<<8)+8, offsetof(CSoundHolder, m_bVolumetric), "Volumetric", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000cc<<8)+9, offsetof(CSoundHolder, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000cc<<8)+10, offsetof(CSoundHolder, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cc<<8)+11, offsetof(CSoundHolder, m_bAutoStart), "Auto start", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000cc<<8)+12, offsetof(CSoundHolder, m_iPlayType), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000000cc<<8)+13, offsetof(CSoundHolder, m_soSound), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cc<<8)+14, offsetof(CSoundHolder, m_bDestroyable), "Destroyable", 'Q', 0x7F0000FFUL, 0), +}; +#define CSoundHolder_propertiesct ARRAYCOUNT(CSoundHolder_properties) + +CEntityComponent CSoundHolder_components[] = { +#define MODEL_MARKER ((0x000000cc<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\SoundHolder.mdl"), +#define TEXTURE_MARKER ((0x000000cc<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\SoundHolder.tex"), +}; +#define CSoundHolder_componentsct ARRAYCOUNT(CSoundHolder_components) + +CEventHandlerEntry CSoundHolder_handlers[] = { + {1, -1, CEntity::pEventHandler(&CSoundHolder:: +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/SoundHolder.es" +Main),DEBUGSTRING("CSoundHolder::Main")}, + {0x00cc0000, -1, CEntity::pEventHandler(&CSoundHolder::H0x00cc0000_Main_01), DEBUGSTRING("CSoundHolder::H0x00cc0000_Main_01")}, + {0x00cc0001, -1, CEntity::pEventHandler(&CSoundHolder::H0x00cc0001_Main_02), DEBUGSTRING("CSoundHolder::H0x00cc0001_Main_02")}, + {0x00cc0002, -1, CEntity::pEventHandler(&CSoundHolder::H0x00cc0002_Main_03), DEBUGSTRING("CSoundHolder::H0x00cc0002_Main_03")}, + {0x00cc0003, -1, CEntity::pEventHandler(&CSoundHolder::H0x00cc0003_Main_04), DEBUGSTRING("CSoundHolder::H0x00cc0003_Main_04")}, + {0x00cc0004, -1, CEntity::pEventHandler(&CSoundHolder::H0x00cc0004_Main_05), DEBUGSTRING("CSoundHolder::H0x00cc0004_Main_05")}, +}; +#define CSoundHolder_handlersct ARRAYCOUNT(CSoundHolder_handlers) + +CEntity *CSoundHolder_New(void) { return new CSoundHolder; }; +void CSoundHolder_OnInitClass(void) {}; +void CSoundHolder_OnEndClass(void) {}; +void CSoundHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CSoundHolder_OnWorldEnd(CWorld *pwo) {}; +void CSoundHolder_OnWorldInit(CWorld *pwo) {}; +void CSoundHolder_OnWorldTick(CWorld *pwo) {}; +void CSoundHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CSoundHolder, CRationalEntity, "SoundHolder", "Thumbnails\\SoundHolder.tbn", 0x000000cc); +DECLARE_CTFILENAME(_fnmCSoundHolder_tbn, "Thumbnails\\SoundHolder.tbn"); diff --git a/Sources/EntitiesMP/SpawnerProjectile.cpp b/Sources/EntitiesMP/SpawnerProjectile.cpp new file mode 100644 index 0000000..9ffb8ae --- /dev/null +++ b/Sources/EntitiesMP/SpawnerProjectile.cpp @@ -0,0 +1,208 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" + +#include "StdH.h" + +#define ECF_SPAWNERPROJECTILE ( \ + ((ECBI_BRUSH)< +#include +CEntityEvent *ESpawnerProjectile::MakeCopy(void) { CEntityEvent *peeCopy = new ESpawnerProjectile(*this); return peeCopy;} +ESpawnerProjectile::ESpawnerProjectile() : CEntityEvent(EVENTCODE_ESpawnerProjectile) {; + ClearToDefault(penOwner); + ClearToDefault(penTemplate); +}; +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" + +void CSpawnerProjectile_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + pdec->PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON); + pdec->PrecacheModel(MODEL_INVISIBLE); +}; + +void CSpawnerProjectile::SetDefaultProperties(void) { + m_penOwner = NULL; + m_penTemplate = NULL; + m_fSize = 0.0f; + m_fTimeAdjust = 0.0f; + m_bExploding = FALSE ; + m_fExplosionDuration = 0.25f; + m_tmExplosionBegin = 0.0f; + m_tmSpawn = 0.0f; + CMovableModelEntity::SetDefaultProperties(); +} + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +void CSpawnerProjectile::SpawnEntity() +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +{ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +CEntity * pen = NULL ; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +pen = GetWorld () -> CopyEntityInWorld (* m_penTemplate , +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +CPlacement3D (FLOAT3D (- 32000.0f + FRnd () * 200.0f , - 32000.0f + FRnd () * 200.0f , 0) , ANGLE3D (0 , 0 , 0))); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +pen -> End (); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +CEnemyBase * peb = ((CEnemyBase *) pen ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +peb -> m_bTemplate = FALSE ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +pen -> Initialize (); +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +FLOAT fEntityR = 0; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +if(pen -> en_pciCollisionInfo != NULL ){ +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +fEntityR = pen -> en_pciCollisionInfo -> GetMaxFloorRadius (); +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +} +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +pen -> Teleport (GetPlacement () , FALSE ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +CEnemyBase & penMonster = (CEnemyBase &) * pen ; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +if(penMonster . m_penTacticsHolder != NULL ){ +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +if(IsOfClass (penMonster . m_penTacticsHolder , "TacticsHolder")){ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +penMonster . StartTacticsNow (); +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +} +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +} +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +} + +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +void CSpawnerProjectile::Explode(void) +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +{ +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +CPlacement3D plExplosion = GetPlacement (); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +CEntityPointer penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +ESpawnEffect eSpawnEffect ; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +eSpawnEffect . betType = BET_BOMB ; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +eSpawnEffect . vStretch = FLOAT3D (1.0f , 1.0f , 1.0f); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +eSpawnEffect . betType = BET_EXPLOSION_DEBRIS ; +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +CEntityPointer penExplosionDebris = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +penExplosionDebris -> Initialize (eSpawnEffect ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +eSpawnEffect . betType = BET_EXPLOSION_SMOKE ; +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +CEntityPointer penExplosionSmoke = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +penExplosionSmoke -> Initialize (eSpawnEffect ); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +} + +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +void CSpawnerProjectile::RenderParticles(void) { +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +Particles_AfterBurner (this , m_tmSpawn , 1.0f , 1); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +if(m_bExploding ) +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +{ +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +} +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +} +BOOL CSpawnerProjectile:: +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSpawnerProjectile_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_ESpawnerProjectile, "CSpawnerProjectile::Main expects 'ESpawnerProjectile' as input!"); const ESpawnerProjectile &esp = (const ESpawnerProjectile &)__eeInput; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +ASSERT (esp . penOwner != NULL ); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +ASSERT (esp . penTemplate != NULL ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +ASSERT (IsDerivedFromClass (esp . penTemplate , "Enemy Base")); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +m_penOwner = esp . penOwner ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +m_penTemplate = esp . penTemplate ; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +m_fTimeAdjust = FRnd () * 5.0f; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +EntityInfo * pei = (EntityInfo *) (m_penTemplate -> GetEntityInfo ()); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +m_fSize = pei -> vSourceCenter [ 1 ] * 0.2f; +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +m_tmSpawn = _pTimer -> CurrentTick (); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +InitAsModel (); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +SetPhysicsFlags (EPF_SPAWNERPROJECTILE ); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +SetCollisionFlags (ECF_SPAWNERPROJECTILE ); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +SetModel (MODEL_INVISIBLE ); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +Particles_AfterBurner_Prepare (this ); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x01fb0001, FALSE, EBegin());return TRUE;}BOOL CSpawnerProjectile::H0x01fb0001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&et= (ETouch&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01fb0002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +}return TRUE;}BOOL CSpawnerProjectile::H0x01fb0002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0002 + +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +m_bExploding = TRUE ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +m_tmExplosionBegin = _pTimer -> CurrentTick (); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +SpawnEntity (); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +Explode (); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +SwitchToEditorModel (); +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +SetTimerAfter(4.0f); +Jump(STATE_CURRENT, 0x01fb0003, FALSE, EBegin());return TRUE;}BOOL CSpawnerProjectile::H0x01fb0003_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fb0004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSpawnerProjectile::H0x01fb0004_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0004 +; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +Destroy (); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +Return(STATE_CURRENT,EVoid()); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/SpawnerProjectile.es b/Sources/EntitiesMP/SpawnerProjectile.es new file mode 100644 index 0000000..65bb86c --- /dev/null +++ b/Sources/EntitiesMP/SpawnerProjectile.es @@ -0,0 +1,182 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +507 +%{ +#include "StdH.h" + +#define ECF_SPAWNERPROJECTILE ( \ + ((ECBI_BRUSH)<PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON); + pdec->PrecacheModel(MODEL_INVISIBLE); +}; +%} + +class CSpawnerProjectile : CMovableModelEntity { + name "SpawnerProjectile"; + thumbnail ""; + features "ImplementsOnPrecache"; + +properties: + 1 CEntityPointer m_penOwner, // entity which owns it + 2 CEntityPointer m_penTemplate, // entity which owns it + 4 FLOAT m_fSize = 0.0f, // for particle rendering + 5 FLOAT m_fTimeAdjust = 0.0f, // for particle rendering + 6 BOOL m_bExploding = FALSE, + 7 FLOAT m_fExplosionDuration = 0.25f, // how long to explode + 8 FLOAT m_tmExplosionBegin = 0.0f, // explosion beginning time + 9 FLOAT m_tmSpawn = 0.0f, // for particle rendering + +components: + + 1 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 10 model MODEL_INVISIBLE "ModelsMP\\Enemies\\Summoner\\SpawnerProjectile\\Invisible.mdl", + +functions: + + void SpawnEntity() + { + CEntity *pen = NULL; + // copy template entity + pen = GetWorld()->CopyEntityInWorld( *m_penTemplate, + CPlacement3D(FLOAT3D(-32000.0f+FRnd()*200.0f, -32000.0f+FRnd()*200.0f, 0), ANGLE3D(0, 0, 0)) ); + + // change needed properties + pen->End(); + + CEnemyBase *peb = ((CEnemyBase*)pen); + peb->m_bTemplate = FALSE; + pen->Initialize(); + + // adjust circle radii to account for enemy size + FLOAT fEntityR = 0; + if (pen->en_pciCollisionInfo!=NULL) { + fEntityR = pen->en_pciCollisionInfo->GetMaxFloorRadius(); + } + + // teleport back + pen->Teleport(GetPlacement(), FALSE); + + // initialize tactics + CEnemyBase &penMonster = (CEnemyBase &)*pen; + + if (penMonster.m_penTacticsHolder != NULL) { + if (IsOfClass(penMonster.m_penTacticsHolder, "TacticsHolder")) { + penMonster.StartTacticsNow(); + } + } + + }; + + void Explode(void) + { + // spawn explosion + CPlacement3D plExplosion = GetPlacement(); + CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_BOMB; + eSpawnEffect.vStretch = FLOAT3D(1.0f,1.0f,1.0f); + penExplosion->Initialize(eSpawnEffect); + + // explosion debris + eSpawnEffect.betType = BET_EXPLOSION_DEBRIS; + CEntityPointer penExplosionDebris = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosionDebris->Initialize(eSpawnEffect); + + // explosion smoke + eSpawnEffect.betType = BET_EXPLOSION_SMOKE; + CEntityPointer penExplosionSmoke = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosionSmoke->Initialize(eSpawnEffect); + + /* + // spawn smoke effect + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_CANNON; + ese.vStretch = FLOAT3D(1.0f, 1.0f, 1.0f); + CEntityPointer penEffect = CreateEntity(this->GetPlacement(), CLASS_BASIC_EFFECT); + penEffect->Initialize(ese); + */ + }; + + void RenderParticles(void) { + Particles_AfterBurner( this, m_tmSpawn, 1.0f, 1); + if (m_bExploding) + { + //Particles_SummonerProjectileExplode( this, m_fSize, m_tmExplosionBegin, m_fExplosionDuration, m_fTimeAdjust ); + } + } + + /************************************************************ + * P R O C E D U R E S * + ************************************************************/ +procedures: + + // --->>> MAIN + Main(ESpawnerProjectile esp) { + // remember the initial parameters + ASSERT(esp.penOwner!=NULL); + ASSERT(esp.penTemplate!=NULL); + ASSERT(IsDerivedFromClass(esp.penTemplate, "Enemy Base")); + m_penOwner = esp.penOwner; + m_penTemplate = esp.penTemplate; + + m_fTimeAdjust = FRnd()*5.0f; + EntityInfo *pei = (EntityInfo*) (m_penTemplate->GetEntityInfo()); + m_fSize = pei->vSourceCenter[1]*0.2f; + + m_tmSpawn=_pTimer->CurrentTick(); + + // initialization + InitAsModel(); + SetPhysicsFlags(EPF_SPAWNERPROJECTILE); + SetCollisionFlags(ECF_SPAWNERPROJECTILE); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_INVISIBLE); + + Particles_AfterBurner_Prepare(this); + + // loop untill touched something + wait() { + on (EBegin) : { resume; } + on (ETouch et) : { stop; } + otherwise (): { resume; } + } + + m_bExploding = TRUE; + m_tmExplosionBegin = _pTimer->CurrentTick(); + + // wait for explosion to end and spawn the monster in the middle + SpawnEntity(); + + Explode(); + + SwitchToEditorModel(); + autowait(4.0f); + Destroy(); + + return; + } +}; diff --git a/Sources/EntitiesMP/SpawnerProjectile.h b/Sources/EntitiesMP/SpawnerProjectile.h new file mode 100644 index 0000000..d622c66 --- /dev/null +++ b/Sources/EntitiesMP/SpawnerProjectile.h @@ -0,0 +1,48 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_SpawnerProjectile_INCLUDED +#define _EntitiesMP_SpawnerProjectile_INCLUDED 1 +#include +#include +#define EVENTCODE_ESpawnerProjectile 0x01fb0000 +class DECL_DLL ESpawnerProjectile : public CEntityEvent { +public: +ESpawnerProjectile(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOwner; +CEntityPointer penTemplate; +}; +DECL_DLL inline void ClearToDefault(ESpawnerProjectile &e) { e = ESpawnerProjectile(); } ; +extern "C" DECL_DLL CDLLEntityClass CSpawnerProjectile_DLLClass; +class CSpawnerProjectile : public CMovableModelEntity { +public: + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penOwner; + CEntityPointer m_penTemplate; + FLOAT m_fSize; + FLOAT m_fTimeAdjust; + BOOL m_bExploding; + FLOAT m_fExplosionDuration; + FLOAT m_tmExplosionBegin; + FLOAT m_tmSpawn; + +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +void SpawnEntity(); + +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +void Explode(void); + +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +void RenderParticles(void); +#define STATE_CSpawnerProjectile_Main 1 + BOOL +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01fb0001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01fb0002_Main_02(const CEntityEvent &__eeInput); + BOOL H0x01fb0003_Main_03(const CEntityEvent &__eeInput); + BOOL H0x01fb0004_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_SpawnerProjectile_INCLUDED diff --git a/Sources/EntitiesMP/SpawnerProjectile_tables.h b/Sources/EntitiesMP/SpawnerProjectile_tables.h new file mode 100644 index 0000000..49151a8 --- /dev/null +++ b/Sources/EntitiesMP/SpawnerProjectile_tables.h @@ -0,0 +1,47 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CSpawnerProjectile + +CEntityProperty CSpawnerProjectile_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001fb<<8)+1, offsetof(CSpawnerProjectile, m_penOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001fb<<8)+2, offsetof(CSpawnerProjectile, m_penTemplate), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+4, offsetof(CSpawnerProjectile, m_fSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+5, offsetof(CSpawnerProjectile, m_fTimeAdjust), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001fb<<8)+6, offsetof(CSpawnerProjectile, m_bExploding), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+7, offsetof(CSpawnerProjectile, m_fExplosionDuration), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+8, offsetof(CSpawnerProjectile, m_tmExplosionBegin), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+9, offsetof(CSpawnerProjectile, m_tmSpawn), "", 0, 0, 0), +}; +#define CSpawnerProjectile_propertiesct ARRAYCOUNT(CSpawnerProjectile_properties) + +CEntityComponent CSpawnerProjectile_components[] = { +#define CLASS_BASIC_EFFECT ((0x000001fb<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define MODEL_INVISIBLE ((0x000001fb<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_INVISIBLE, "EFNM" "ModelsMP\\Enemies\\Summoner\\SpawnerProjectile\\Invisible.mdl"), +}; +#define CSpawnerProjectile_componentsct ARRAYCOUNT(CSpawnerProjectile_components) + +CEventHandlerEntry CSpawnerProjectile_handlers[] = { + {1, -1, CEntity::pEventHandler(&CSpawnerProjectile:: +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/SpawnerProjectile.es" +Main),DEBUGSTRING("CSpawnerProjectile::Main")}, + {0x01fb0001, -1, CEntity::pEventHandler(&CSpawnerProjectile::H0x01fb0001_Main_01), DEBUGSTRING("CSpawnerProjectile::H0x01fb0001_Main_01")}, + {0x01fb0002, -1, CEntity::pEventHandler(&CSpawnerProjectile::H0x01fb0002_Main_02), DEBUGSTRING("CSpawnerProjectile::H0x01fb0002_Main_02")}, + {0x01fb0003, -1, CEntity::pEventHandler(&CSpawnerProjectile::H0x01fb0003_Main_03), DEBUGSTRING("CSpawnerProjectile::H0x01fb0003_Main_03")}, + {0x01fb0004, -1, CEntity::pEventHandler(&CSpawnerProjectile::H0x01fb0004_Main_04), DEBUGSTRING("CSpawnerProjectile::H0x01fb0004_Main_04")}, +}; +#define CSpawnerProjectile_handlersct ARRAYCOUNT(CSpawnerProjectile_handlers) + +CEntity *CSpawnerProjectile_New(void) { return new CSpawnerProjectile; }; +void CSpawnerProjectile_OnInitClass(void) {}; +void CSpawnerProjectile_OnEndClass(void) {}; +void CSpawnerProjectile_OnPrecache(CDLLEntityClass *pdec, INDEX iUser); +void CSpawnerProjectile_OnWorldEnd(CWorld *pwo) {}; +void CSpawnerProjectile_OnWorldInit(CWorld *pwo) {}; +void CSpawnerProjectile_OnWorldTick(CWorld *pwo) {}; +void CSpawnerProjectile_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CSpawnerProjectile, CMovableModelEntity, "SpawnerProjectile", "", 0x000001fb); +DECLARE_CTFILENAME(_fnmCSpawnerProjectile_tbn, ""); diff --git a/Sources/EntitiesMP/Spinner.cpp b/Sources/EntitiesMP/Spinner.cpp new file mode 100644 index 0000000..fa3f876 --- /dev/null +++ b/Sources/EntitiesMP/Spinner.cpp @@ -0,0 +1,188 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *ESpinnerInit::MakeCopy(void) { CEntityEvent *peeCopy = new ESpinnerInit(*this); return peeCopy;} +ESpinnerInit::ESpinnerInit() : CEntityEvent(EVENTCODE_ESpinnerInit) {; + ClearToDefault(penParent); + ClearToDefault(penTwister); + ClearToDefault(vRotationAngle); + ClearToDefault(tmSpinTime); + ClearToDefault(fUpSpeed); + ClearToDefault(bImpulse); + ClearToDefault(tmImpulseDuration); +}; +void CSpinner::SetDefaultProperties(void) { + m_penParent = NULL; + m_aSpinRotation = FLOAT3D(0.0f , 0.0f , 0.0f); + m_vSpeed = FLOAT3D(0.0f , 0.0f , 0.0f); + m_tmExpire = 0.0f; + m_vLastSpeed = FLOAT3D(0.0f , 0.0f , 0.0f); + m_bImpulse = FALSE ; + m_tmWaitAfterImpulse = 0.0f; + m_tmSpawn = 0.0f; + m_vSpinSpeed = FLOAT3D(0.0f , 0.0f , 0.0f); + CRationalEntity::SetDefaultProperties(); +} +BOOL CSpinner:: +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSpinner_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_ESpinnerInit, "CSpinner::Main expects 'ESpinnerInit' as input!"); const ESpinnerInit &esi = (const ESpinnerInit &)__eeInput; +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +if((! (esi . penParent -> GetPhysicsFlags () & EPF_MOVABLE )) || +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +(esi . penParent == NULL ) || (esi . penParent == NULL )) +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +{ +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +Destroy (); +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +Return(STATE_CURRENT,EVoid()); +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +return TRUE; +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +} +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +ASSERT (esi . penParent != NULL ); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +ASSERT (esi . penTwister != NULL ); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +CTwister & penTwister = (CTwister &) * esi . penTwister ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +CMovableEntity & penParent = (CMovableEntity &) * esi . penParent ; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_penParent = esi . penParent ; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_aSpinRotation = esi . vRotationAngle ; +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_bImpulse = esi . bImpulse ; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +if(m_bImpulse ){ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_tmWaitAfterImpulse = esi . tmSpinTime - esi . tmImpulseDuration ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +if(m_tmWaitAfterImpulse <= 0.0f){m_tmWaitAfterImpulse = 0.01f;} +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +} +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_vSpinSpeed = ((CMovableEntity &) * m_penParent ) . en_vCurrentTranslationAbsolute ; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_vSpinSpeed = FLOAT3D (0.0f , 0.0f , m_vSpinSpeed . Length ()); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +InitAsVoid (); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +if(! m_bImpulse ){ +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_tmExpire = _pTimer -> CurrentTick () + esi . tmSpinTime ; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +}else { +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_tmExpire = _pTimer -> CurrentTick () + esi . tmImpulseDuration ; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +} +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_tmSpawn = _pTimer -> CurrentTick (); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_vSpeed = FLOAT3D (penTwister . en_mRotation (1 , 2) , penTwister . en_mRotation (2 , 2) , penTwister . en_mRotation (3 , 2)) * esi . fUpSpeed ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +ANGLE3D aRnd ; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +FLOATmatrix3D m ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +aRnd (1) = FRnd () * 360.0f;aRnd (2) = FRnd () * 30.0f;aRnd (3) = 0.0f; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +MakeRotationMatrixFast (m , aRnd ); +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_vSpeed = m_vSpeed * m ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +Jump(STATE_CURRENT,0x015c0003, FALSE, EInternal());return TRUE;}BOOL CSpinner::H0x015c0003_Main_03(const CEntityEvent &__eeInput) +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015c0003 +if(!(_pTimer -> CurrentTick () < m_tmExpire )){ Jump(STATE_CURRENT,0x015c0004, FALSE, EInternal());return TRUE;} +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +if(m_penParent -> GetFlags () & ENF_DELETED ){ +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +Destroy (); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +Return(STATE_CURRENT,EVoid()); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +return TRUE; +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +} +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +if(((CMovableEntity &) * m_penParent ) . en_vCurrentTranslationAbsolute != m_vLastSpeed || +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +((CMovableEntity &) * m_penParent ) . en_vCurrentTranslationAbsolute == FLOAT3D (0.0f , 0.0f , 0.0f)){ +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +((CMovableEntity &) * m_penParent ) . en_vCurrentTranslationAbsolute += m_vSpeed ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +m_vLastSpeed = ((CMovableEntity &) * m_penParent ) . en_vCurrentTranslationAbsolute ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +}else { +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +((CMovableEntity &) * m_penParent ) . SetDesiredTranslation (m_vSpinSpeed ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +} +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +if(! m_bImpulse ){ +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +((CMovableEntity &) * m_penParent ) . en_aDesiredRotationRelative = m_aSpinRotation ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +} +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x015c0001, FALSE, EBegin());return TRUE;}BOOL CSpinner::H0x015c0001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015c0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015c0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSpinner::H0x015c0002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015c0002 +;Jump(STATE_CURRENT,0x015c0003, FALSE, EInternal());return TRUE; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +}BOOL CSpinner::H0x015c0004_Main_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015c0004 + +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +((CMovableEntity &) * m_penParent ) . en_aDesiredRotationRelative = ANGLE3D (0.0f , 0.0f , 0.0f); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +if(!(m_bImpulse )){ Jump(STATE_CURRENT,0x015c0007, FALSE, EInternal());return TRUE;} +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +((CMovableEntity &) * m_penParent ) . SetDesiredTranslation (FLOAT3D (0.0f , 0.0f , 0.0f)); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +SetTimerAfter(m_tmWaitAfterImpulse ); +Jump(STATE_CURRENT, 0x015c0005, FALSE, EBegin());return TRUE;}BOOL CSpinner::H0x015c0005_Main_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015c0005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015c0006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSpinner::H0x015c0006_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015c0006 +;Jump(STATE_CURRENT,0x015c0007, FALSE, EInternal());return TRUE;}BOOL CSpinner::H0x015c0007_Main_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015c0007 + +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +Destroy (); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +Return(STATE_CURRENT,EVoid()); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Spinner.es b/Sources/EntitiesMP/Spinner.es new file mode 100644 index 0000000..97bda65 --- /dev/null +++ b/Sources/EntitiesMP/Spinner.es @@ -0,0 +1,128 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +348 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Twister"; + +// input parameter for timer +event ESpinnerInit { + CEntityPointer penParent, // who owns it + CEntityPointer penTwister, // twister who spawned this + FLOAT3D vRotationAngle, // rotation angle + FLOAT tmSpinTime, // spin time + FLOAT fUpSpeed, // up multiply speed + // for player impulse: + BOOL bImpulse, // one time only spin + FLOAT tmImpulseDuration, // impulse duration +}; + +class export CSpinner : CRationalEntity { + name "Spinner"; + thumbnail ""; + +properties: + 1 CEntityPointer m_penParent, // entity which owns it + 2 FLOAT3D m_aSpinRotation = FLOAT3D(0.0f, 0.0f, 0.0f), + 3 FLOAT3D m_vSpeed = FLOAT3D(0.0f, 0.0f, 0.0f), + 4 FLOAT m_tmExpire = 0.0f, + 5 FLOAT3D m_vLastSpeed = FLOAT3D(0.0f, 0.0f, 0.0f), + 6 BOOL m_bImpulse = FALSE, + 7 FLOAT m_tmWaitAfterImpulse = 0.0f, // wait after impulse + + 10 FLOAT m_tmSpawn = 0.0f, + 11 FLOAT3D m_vSpinSpeed = FLOAT3D(0.0f, 0.0f, 0.0f), + +components: +functions: +procedures: + Main(ESpinnerInit esi) { + + // check some parameters + if ((!(esi.penParent->GetPhysicsFlags()&EPF_MOVABLE)) || + (esi.penParent==NULL) || (esi.penParent==NULL)) + { + Destroy(); + return; + } + ASSERT(esi.penParent!=NULL); + ASSERT(esi.penTwister!=NULL); + + // remember the initial parameters + CTwister &penTwister = (CTwister &)*esi.penTwister; + CMovableEntity &penParent = (CMovableEntity &)*esi.penParent; + m_penParent = esi.penParent; + m_aSpinRotation = esi.vRotationAngle; + m_bImpulse = esi.bImpulse; + if (m_bImpulse) { + m_tmWaitAfterImpulse = esi.tmSpinTime - esi.tmImpulseDuration; + if (m_tmWaitAfterImpulse<=0.0f) { m_tmWaitAfterImpulse = 0.01f; } + } + + m_vSpinSpeed = ((CMovableEntity&)*m_penParent).en_vCurrentTranslationAbsolute; + m_vSpinSpeed = FLOAT3D(0.0f, 0.0f, m_vSpinSpeed.Length()); + + // init as nothing + InitAsVoid(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + if (!m_bImpulse) { + m_tmExpire = _pTimer->CurrentTick() + esi.tmSpinTime; + } else { + m_tmExpire = _pTimer->CurrentTick() + esi.tmImpulseDuration; + } + m_tmSpawn = _pTimer->CurrentTick(); + + // throw target parameters + m_vSpeed = FLOAT3D(penTwister.en_mRotation(1, 2), penTwister.en_mRotation(2, 2), penTwister.en_mRotation(3, 2)) * esi.fUpSpeed; + + // give absolute speed some randomness + ANGLE3D aRnd; + FLOATmatrix3D m; + aRnd(1) = FRnd()*360.0f; aRnd(2) = FRnd()*30.0f; aRnd(3) = 0.0f; + MakeRotationMatrixFast(m, aRnd); + m_vSpeed = m_vSpeed*m; + + //each tick until the m_tmExpire, reinitialise spin + while (_pTimer->CurrentTick()GetFlags()&ENF_DELETED) { + Destroy(); + return; + } + + if (((CMovableEntity&)*m_penParent).en_vCurrentTranslationAbsolute!=m_vLastSpeed || + ((CMovableEntity&)*m_penParent).en_vCurrentTranslationAbsolute==FLOAT3D(0.0f, 0.0f, 0.0f)) { + // give absolute speed + ((CMovableEntity&)*m_penParent).en_vCurrentTranslationAbsolute += m_vSpeed; + m_vLastSpeed = ((CMovableEntity&)*m_penParent).en_vCurrentTranslationAbsolute; + } else { + // give it some speed + ((CMovableEntity&)*m_penParent).SetDesiredTranslation(m_vSpinSpeed); + } + + // spin entity if not impulse + if (!m_bImpulse) { + ((CMovableEntity&)*m_penParent).en_aDesiredRotationRelative = m_aSpinRotation; + } + autowait (_pTimer->TickQuantum); + } + // stop spinning the parent entity + ((CMovableEntity&)*m_penParent).en_aDesiredRotationRelative = ANGLE3D(0.0f, 0.0f, 0.0f); + + // wait if necessary and stop the up translation if player + if (m_bImpulse) { + ((CMovableEntity&)*m_penParent).SetDesiredTranslation(FLOAT3D(0.0f, 0.0f, 0.0f)); + autowait(m_tmWaitAfterImpulse); + } + + // cease to exist + Destroy(); + + return; + }; +}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Spinner.h b/Sources/EntitiesMP/Spinner.h new file mode 100644 index 0000000..b08ba88 --- /dev/null +++ b/Sources/EntitiesMP/Spinner.h @@ -0,0 +1,47 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Spinner_INCLUDED +#define _EntitiesMP_Spinner_INCLUDED 1 +#include +#define EVENTCODE_ESpinnerInit 0x015c0000 +class DECL_DLL ESpinnerInit : public CEntityEvent { +public: +ESpinnerInit(); +CEntityEvent *MakeCopy(void); +CEntityPointer penParent; +CEntityPointer penTwister; +FLOAT3D vRotationAngle; +FLOAT tmSpinTime; +FLOAT fUpSpeed; +BOOL bImpulse; +FLOAT tmImpulseDuration; +}; +DECL_DLL inline void ClearToDefault(ESpinnerInit &e) { e = ESpinnerInit(); } ; +extern "C" DECL_DLL CDLLEntityClass CSpinner_DLLClass; +class DECL_DLL CSpinner : public CRationalEntity { +public: + virtual void SetDefaultProperties(void); + CEntityPointer m_penParent; + FLOAT3D m_aSpinRotation; + FLOAT3D m_vSpeed; + FLOAT m_tmExpire; + FLOAT3D m_vLastSpeed; + BOOL m_bImpulse; + FLOAT m_tmWaitAfterImpulse; + FLOAT m_tmSpawn; + FLOAT3D m_vSpinSpeed; +#define STATE_CSpinner_Main 1 + BOOL +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x015c0001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x015c0002_Main_02(const CEntityEvent &__eeInput); + BOOL H0x015c0003_Main_03(const CEntityEvent &__eeInput); + BOOL H0x015c0004_Main_04(const CEntityEvent &__eeInput); + BOOL H0x015c0005_Main_05(const CEntityEvent &__eeInput); + BOOL H0x015c0006_Main_06(const CEntityEvent &__eeInput); + BOOL H0x015c0007_Main_07(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Spinner_INCLUDED diff --git a/Sources/EntitiesMP/Spinner_tables.h b/Sources/EntitiesMP/Spinner_tables.h new file mode 100644 index 0000000..df70ca2 --- /dev/null +++ b/Sources/EntitiesMP/Spinner_tables.h @@ -0,0 +1,49 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CSpinner + +CEntityProperty CSpinner_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015c<<8)+1, offsetof(CSpinner, m_penParent), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015c<<8)+2, offsetof(CSpinner, m_aSpinRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015c<<8)+3, offsetof(CSpinner, m_vSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015c<<8)+4, offsetof(CSpinner, m_tmExpire), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015c<<8)+5, offsetof(CSpinner, m_vLastSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015c<<8)+6, offsetof(CSpinner, m_bImpulse), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015c<<8)+7, offsetof(CSpinner, m_tmWaitAfterImpulse), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015c<<8)+10, offsetof(CSpinner, m_tmSpawn), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015c<<8)+11, offsetof(CSpinner, m_vSpinSpeed), "", 0, 0, 0), +}; +#define CSpinner_propertiesct ARRAYCOUNT(CSpinner_properties) + +CEntityComponent CSpinner_components[] = { + CEntityComponent() +}; +#define CSpinner_componentsct 0 + + +CEventHandlerEntry CSpinner_handlers[] = { + {1, -1, CEntity::pEventHandler(&CSpinner:: +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/Spinner.es" +Main),DEBUGSTRING("CSpinner::Main")}, + {0x015c0001, -1, CEntity::pEventHandler(&CSpinner::H0x015c0001_Main_01), DEBUGSTRING("CSpinner::H0x015c0001_Main_01")}, + {0x015c0002, -1, CEntity::pEventHandler(&CSpinner::H0x015c0002_Main_02), DEBUGSTRING("CSpinner::H0x015c0002_Main_02")}, + {0x015c0003, -1, CEntity::pEventHandler(&CSpinner::H0x015c0003_Main_03), DEBUGSTRING("CSpinner::H0x015c0003_Main_03")}, + {0x015c0004, -1, CEntity::pEventHandler(&CSpinner::H0x015c0004_Main_04), DEBUGSTRING("CSpinner::H0x015c0004_Main_04")}, + {0x015c0005, -1, CEntity::pEventHandler(&CSpinner::H0x015c0005_Main_05), DEBUGSTRING("CSpinner::H0x015c0005_Main_05")}, + {0x015c0006, -1, CEntity::pEventHandler(&CSpinner::H0x015c0006_Main_06), DEBUGSTRING("CSpinner::H0x015c0006_Main_06")}, + {0x015c0007, -1, CEntity::pEventHandler(&CSpinner::H0x015c0007_Main_07), DEBUGSTRING("CSpinner::H0x015c0007_Main_07")}, +}; +#define CSpinner_handlersct ARRAYCOUNT(CSpinner_handlers) + +CEntity *CSpinner_New(void) { return new CSpinner; }; +void CSpinner_OnInitClass(void) {}; +void CSpinner_OnEndClass(void) {}; +void CSpinner_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CSpinner_OnWorldEnd(CWorld *pwo) {}; +void CSpinner_OnWorldInit(CWorld *pwo) {}; +void CSpinner_OnWorldTick(CWorld *pwo) {}; +void CSpinner_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CSpinner, CRationalEntity, "Spinner", "", 0x0000015c); +DECLARE_CTFILENAME(_fnmCSpinner_tbn, ""); diff --git a/Sources/EntitiesMP/StdH/StdH.cpp b/Sources/EntitiesMP/StdH/StdH.cpp new file mode 100644 index 0000000..95c0896 --- /dev/null +++ b/Sources/EntitiesMP/StdH/StdH.cpp @@ -0,0 +1,3 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdH.h" diff --git a/Sources/EntitiesMP/StdH/StdH.h b/Sources/EntitiesMP/StdH/StdH.h new file mode 100644 index 0000000..9eabb5b --- /dev/null +++ b/Sources/EntitiesMP/StdH/StdH.h @@ -0,0 +1,21 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include +#include +#include + +/* rcg10042001 protect against Visual C-isms. */ +#ifdef _MSC_VER +#define DECL_DLL _declspec(dllexport) +#endif + +#ifdef PLATFORM_UNIX +#define DECL_DLL +#endif + +#include "..\Global.h" +#include "..\Common\Flags.h" +#include "..\Common\Common.h" +#include "..\Common\Particles.h" +#include "..\Common\EmanatingParticles.h" +#include "..\Common\GameInterface.h" diff --git a/Sources/EntitiesMP/StormController.cpp b/Sources/EntitiesMP/StormController.cpp new file mode 100644 index 0000000..ff66bc8 --- /dev/null +++ b/Sources/EntitiesMP/StormController.cpp @@ -0,0 +1,483 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" + +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/Lightning.h" + +#include +#include +void CStormController::SetDefaultProperties(void) { + m_penwsc = NULL; + m_strName = "Storm controller"; + m_fNextLightningDelay = 0.0f; + m_bStormOn = FALSE ; + m_fNextLightningStrike = 0.0f; + m_penLightning00 = NULL; + m_penLightning01 = NULL; + m_penLightning02 = NULL; + m_penLightning03 = NULL; + m_penLightning04 = NULL; + m_penLightning05 = NULL; + m_penLightning06 = NULL; + m_penLightning07 = NULL; + m_penLightning08 = NULL; + m_penLightning09 = NULL; + m_penLightning10 = NULL; + m_penLightning11 = NULL; + m_penLightning12 = NULL; + m_penLightning13 = NULL; + m_penLightning14 = NULL; + m_penLightning15 = NULL; + m_penLightning16 = NULL; + m_penLightning17 = NULL; + m_penLightning18 = NULL; + m_penLightning19 = NULL; + m_tmStormAppearTime = 10.0f; + m_tmStormDisappearTime = 10.0f; + m_fFirstLightningDelay = 10.0f; + m_fMaxLightningPeriod = 10.0f; + m_fMinLightningPeriod = 1.0f; + m_fMaxStormPowerTime = 120.0f; + m_colBlendStart = COLOR(C_WHITE | CT_TRANSPARENT ); + m_colBlendStop = COLOR(C_WHITE | CT_OPAQUE ); + m_colShadeStart = COLOR(C_WHITE | CT_OPAQUE ); + m_colShadeStop = COLOR(C_GRAY | CT_OPAQUE ); + CRationalEntity::SetDefaultProperties(); +} + +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +void CStormController::CheckOneLightningTarget(CEntityPointer & pen) +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(pen != NULL && ! IsOfClass (pen , "Lightning")) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +WarningMessage ("Target '%s' is not of class Lightning!" , pen -> GetName ()); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +pen = NULL ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} + +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +INDEX CStormController::GetLightningsCount(void)const +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning00 == NULL ){return 0;}; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning01 == NULL ){return 1;}; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning02 == NULL ){return 2;}; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning03 == NULL ){return 3;}; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning04 == NULL ){return 4;}; +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning05 == NULL ){return 5;}; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning06 == NULL ){return 6;}; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning07 == NULL ){return 7;}; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning08 == NULL ){return 8;}; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning09 == NULL ){return 9;}; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning10 == NULL ){return 10;}; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning11 == NULL ){return 11;}; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning12 == NULL ){return 12;}; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning13 == NULL ){return 13;}; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning14 == NULL ){return 14;}; +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning15 == NULL ){return 15;}; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning16 == NULL ){return 16;}; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning17 == NULL ){return 17;}; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penLightning18 == NULL ){return 18;}; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +return 20; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} +BOOL CStormController:: +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Storm(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CStormController_Storm + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CStormController::Storm expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +SetTimerAfter(10.0f); +Jump(STATE_CURRENT, 0x025e0001, FALSE, EBegin());return TRUE;}BOOL CStormController::H0x025e0001_Storm_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x025e0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CStormController::H0x025e0002_Storm_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e0002 +; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +m_fNextLightningStrike = m_tmStormAppearTime + m_fFirstLightningDelay ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Jump(STATE_CURRENT, STATE_CStormController_StormInternal, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CStormController:: +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +StormInternal(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CStormController_StormInternal + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CStormController::StormInternal expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Jump(STATE_CURRENT,0x025e000a, FALSE, EInternal());return TRUE;}BOOL CStormController::H0x025e000a_StormInternal_07(const CEntityEvent &__eeInput) +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e000a +if(!(m_bStormOn && +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +_pTimer -> CurrentTick () < ((CWorldSettingsController *) & * m_penwsc ) -> m_tmStormEnd + m_tmStormDisappearTime )){ Jump(STATE_CURRENT,0x025e000b, FALSE, EInternal());return TRUE;} +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Jump(STATE_CURRENT,0x025e0006, FALSE, EInternal());return TRUE;}BOOL CStormController::H0x025e0006_StormInternal_03(const CEntityEvent &__eeInput) +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e0006 +if(!(_pTimer -> CurrentTick () < m_fNextLightningStrike && +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +_pTimer -> CurrentTick () < ((CWorldSettingsController *) & * m_penwsc ) -> m_tmStormEnd + m_tmStormDisappearTime && +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +m_bStormOn )){ Jump(STATE_CURRENT,0x025e0007, FALSE, EInternal());return TRUE;} +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x025e0004, FALSE, EBegin());return TRUE;}BOOL CStormController::H0x025e0004_StormInternal_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e0004 +switch(__eeInput.ee_slEvent) +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{case(EVENTCODE_EBegin): +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{const EBegin&e= (EBegin&)__eeInput; + +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +return TRUE; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}ASSERT(FALSE);break;case(EVENTCODE_EEnvironmentStop): +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{const EEnvironmentStop&e= (EEnvironmentStop&)__eeInput; + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +m_fNextLightningStrike += 1.0f; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +return TRUE; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x025e0005, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}return TRUE;}BOOL CStormController::H0x025e0005_StormInternal_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e0005 +Jump(STATE_CURRENT,0x025e0006, FALSE, EInternal());return TRUE; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}BOOL CStormController::H0x025e0007_StormInternal_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e0007 + +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x025e0008, FALSE, EBegin());return TRUE;}BOOL CStormController::H0x025e0008_StormInternal_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e0008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x025e0009, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CStormController::H0x025e0009_StormInternal_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e0009 +; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +FLOAT fLightningStart = ((CWorldSettingsController *) & * m_penwsc ) -> m_tmStormStart + m_fFirstLightningDelay ; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +FLOAT fLightningMax = fLightningStart + m_fMaxStormPowerTime ; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +FLOAT fRatio ; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(_pTimer -> CurrentTick () > ((CWorldSettingsController *) & * m_penwsc ) -> m_tmStormEnd - m_tmStormDisappearTime ) +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +m_bStormOn = FALSE ; +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +else +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(_pTimer -> CurrentTick () < fLightningMax ) +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +fRatio = CalculateRatio (_pTimer -> CurrentTick () , fLightningStart , fLightningMax , 1.0f , 0.0f); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +else +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +fRatio = 1; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +FLOAT tmPeriod = (m_fMaxLightningPeriod - m_fMinLightningPeriod ) * (1.0f - fRatio ); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +FLOAT fNextLighting = m_fMinLightningPeriod + tmPeriod * (1.0f + (FRnd () - 0.5f) * 0.25f); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +m_fNextLightningStrike = _pTimer -> CurrentTick () + fNextLighting ; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +INDEX ctLightnings = GetLightningsCount (); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(ctLightnings != 0) +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CLightning * penLightning = (CLightning *) & * (& m_penLightning00 ) [ IRnd () % ctLightnings ]; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +SendToTarget (penLightning , EET_TRIGGER ); +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}Jump(STATE_CURRENT,0x025e000a, FALSE, EInternal());return TRUE; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}BOOL CStormController::H0x025e000b_StormInternal_08(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e000b + +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +m_bStormOn = FALSE ; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Return(STATE_CURRENT,EReturn ()); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CStormController:: +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CStormController_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CStormController::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning00 ); +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning01 ); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning02 ); +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning03 ); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning04 ); +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning05 ); +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning06 ); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning07 ); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning08 ); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning09 ); +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning10 ); +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning11 ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning12 ); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning13 ); +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning14 ); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning15 ); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning16 ); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning17 ); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning18 ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CheckOneLightningTarget (m_penLightning19 ); +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +InitAsEditorModel (); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +SetModel (MODEL_STORM_CONTROLLER ); +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +SetModelMainTexture (TEXTURE_STORM_CONTROLLER ); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x025e000c, FALSE, EBegin());return TRUE;}BOOL CStormController::H0x025e000c_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e000c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x025e000d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CStormController::H0x025e000d_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e000d +; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CBackgroundViewer * penBcgViewer = (CBackgroundViewer *) GetWorld () -> GetBackgroundViewer (); +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(penBcgViewer == NULL ) +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Return(STATE_CURRENT,EVoid()); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +return TRUE; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +m_penwsc = penBcgViewer -> m_penWorldSettingsController ; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_penwsc == NULL ) +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Return(STATE_CURRENT,EVoid()); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +return TRUE; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(! IsOfClass (m_penwsc , "WorldSettingsController")) +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Return(STATE_CURRENT,EVoid()); +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +return TRUE; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +CWorldSettingsController * pwsc = (CWorldSettingsController *) & * m_penwsc ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +pwsc -> m_colBlendStart = m_colBlendStart ; +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +pwsc -> m_colBlendStop = m_colBlendStop ; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +pwsc -> m_colShadeStart = m_colShadeStart ; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +pwsc -> m_colShadeStop = m_colShadeStop ; +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +pwsc -> m_tmStormAppearTime = m_tmStormAppearTime ; +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +pwsc -> m_tmStormDisappearTime = m_tmStormDisappearTime ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +m_bStormOn = FALSE ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Jump(STATE_CURRENT,0x025e0010, FALSE, EInternal());return TRUE;}BOOL CStormController::H0x025e0010_Main_05(const CEntityEvent &__eeInput) +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e0010 +if(!(TRUE )){ Jump(STATE_CURRENT,0x025e0011, FALSE, EInternal());return TRUE;} +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x025e000e, FALSE, EBegin());return TRUE;}BOOL CStormController::H0x025e000e_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e000e +switch(__eeInput.ee_slEvent) +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{case(EVENTCODE_EEnvironmentStart): +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{const EEnvironmentStart&eEnvironmentStart= (EEnvironmentStart&)__eeInput; + +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +((CWorldSettingsController *) & * m_penwsc ) -> m_tmStormStart = tmNow - m_tmStormAppearTime ; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +((CWorldSettingsController *) & * m_penwsc ) -> m_tmStormEnd = 1e6; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +m_bStormOn = TRUE ; +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +m_fNextLightningStrike = _pTimer -> CurrentTick () + 2.0f; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Call(STATE_CURRENT, STATE_CStormController_StormInternal, TRUE, EVoid());return TRUE; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +return TRUE; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart): +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{const EStart&eStart= (EStart&)__eeInput; + +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(! m_bStormOn ) +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +((CWorldSettingsController *) & * m_penwsc ) -> m_tmStormStart = tmNow ; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +((CWorldSettingsController *) & * m_penwsc ) -> m_tmStormEnd = 1e6; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +m_bStormOn = TRUE ; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Call(STATE_CURRENT, STATE_CStormController_Storm, TRUE, EVoid());return TRUE; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +return TRUE; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop): +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{const EStop&eStop= (EStop&)__eeInput; + +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +if(m_bStormOn ) +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +TIME tmNow = _pTimer -> CurrentTick (); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +((CWorldSettingsController *) & * m_penwsc ) -> m_tmStormEnd = tmNow ; +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +} +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +return TRUE; +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}ASSERT(FALSE);break;default: +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +{ +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +return TRUE; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}ASSERT(FALSE);break; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}return TRUE;}BOOL CStormController::H0x025e000f_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e000f +;Jump(STATE_CURRENT,0x025e0010, FALSE, EInternal());return TRUE; +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +}BOOL CStormController::H0x025e0011_Main_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x025e0011 + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/StormController.es b/Sources/EntitiesMP/StormController.es new file mode 100644 index 0000000..08f53e0 --- /dev/null +++ b/Sources/EntitiesMP/StormController.es @@ -0,0 +1,282 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +606 +%{ +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/Lightning.h" +%} + +class CStormController: CRationalEntity { +name "Storm controller"; +thumbnail "Thumbnails\\StormController.tbn"; +features "IsTargetable", "HasName"; + +properties: + 1 CEntityPointer m_penwsc, // ptr to world settings controller + 2 CTString m_strName "Name" 'N' = "Storm controller", // class name + 3 FLOAT m_fNextLightningDelay = 0.0f, + 4 BOOL m_bStormOn = FALSE, + 5 FLOAT m_fNextLightningStrike = 0.0f, + 10 CEntityPointer m_penLightning00 "Lightning 1" 'T' COLOR(C_MAGENTA|0xFF), // lightning + 11 CEntityPointer m_penLightning01 "Lightning 2" 'Y' COLOR(C_MAGENTA|0xFF), // lightning + 12 CEntityPointer m_penLightning02 "Lightning 3" 'U' COLOR(C_MAGENTA|0xFF), // lightning + 13 CEntityPointer m_penLightning03 "Lightning 4" 'I' COLOR(C_MAGENTA|0xFF), // lightning + 14 CEntityPointer m_penLightning04 "Lightning 5" 'O' COLOR(C_MAGENTA|0xFF), // lightning + 15 CEntityPointer m_penLightning05 "Lightning 6" 'P' COLOR(C_MAGENTA|0xFF), // lightning + 16 CEntityPointer m_penLightning06 "Lightning 7" COLOR(C_MAGENTA|0xFF), // lightning + 17 CEntityPointer m_penLightning07 "Lightning 8" COLOR(C_MAGENTA|0xFF), // lightning + 18 CEntityPointer m_penLightning08 "Lightning 9" COLOR(C_MAGENTA|0xFF), // lightning + 19 CEntityPointer m_penLightning09 "Lightning 10" COLOR(C_MAGENTA|0xFF), // lightning + 20 CEntityPointer m_penLightning10 "Lightning 11" COLOR(C_MAGENTA|0xFF), // lightning + 21 CEntityPointer m_penLightning11 "Lightning 12" COLOR(C_MAGENTA|0xFF), // lightning + 22 CEntityPointer m_penLightning12 "Lightning 13" COLOR(C_MAGENTA|0xFF), // lightning + 23 CEntityPointer m_penLightning13 "Lightning 14" COLOR(C_MAGENTA|0xFF), // lightning + 24 CEntityPointer m_penLightning14 "Lightning 15" COLOR(C_MAGENTA|0xFF), // lightning + 25 CEntityPointer m_penLightning15 "Lightning 16" COLOR(C_MAGENTA|0xFF), // lightning + 26 CEntityPointer m_penLightning16 "Lightning 17" COLOR(C_MAGENTA|0xFF), // lightning + 27 CEntityPointer m_penLightning17 "Lightning 18" COLOR(C_MAGENTA|0xFF), // lightning + 28 CEntityPointer m_penLightning18 "Lightning 19" COLOR(C_MAGENTA|0xFF), // lightning + 29 CEntityPointer m_penLightning19 "Lightning 20" COLOR(C_MAGENTA|0xFF), // lightning + + 40 FLOAT m_tmStormAppearTime "Storm appear time" = 10.0f, + 41 FLOAT m_tmStormDisappearTime "Storm disappear time" = 10.0f, + 42 FLOAT m_fFirstLightningDelay "First lightning delay" = 10.0f, + 43 FLOAT m_fMaxLightningPeriod "Max lightning period" = 10.0f, + 44 FLOAT m_fMinLightningPeriod "Min lightning period" = 1.0f, + 45 FLOAT m_fMaxStormPowerTime "Max storm power time" = 120.0f, + + 50 COLOR m_colBlendStart "Color blend start" 'B' = COLOR(C_WHITE|CT_TRANSPARENT), + 51 COLOR m_colBlendStop "Color blend stop" = COLOR(C_WHITE|CT_OPAQUE), + 52 COLOR m_colShadeStart "Color shade start" 'S' = COLOR(C_WHITE|CT_OPAQUE), + 53 COLOR m_colShadeStop "Color shade stop" = COLOR(C_GRAY|CT_OPAQUE), + +components: + 1 model MODEL_STORM_CONTROLLER "Models\\Editor\\StormController.mdl", + 2 texture TEXTURE_STORM_CONTROLLER "Models\\Editor\\StormController.tex" + +functions: + // check if one lightning target is valid + void CheckOneLightningTarget(CEntityPointer &pen) + { + if (pen!=NULL && !IsOfClass(pen, "Lightning")) + { + WarningMessage("Target '%s' is not of class Lightning!", pen->GetName()); + pen=NULL; + } + } + + // get number of lightnings set by user + INDEX GetLightningsCount(void) const + { + // note: only first N that are no NULL are used + if (m_penLightning00==NULL) { return 0; }; + if (m_penLightning01==NULL) { return 1; }; + if (m_penLightning02==NULL) { return 2; }; + if (m_penLightning03==NULL) { return 3; }; + if (m_penLightning04==NULL) { return 4; }; + if (m_penLightning05==NULL) { return 5; }; + if (m_penLightning06==NULL) { return 6; }; + if (m_penLightning07==NULL) { return 7; }; + if (m_penLightning08==NULL) { return 8; }; + if (m_penLightning09==NULL) { return 9; }; + if (m_penLightning10==NULL) { return 10; }; + if (m_penLightning11==NULL) { return 11; }; + if (m_penLightning12==NULL) { return 12; }; + if (m_penLightning13==NULL) { return 13; }; + if (m_penLightning14==NULL) { return 14; }; + if (m_penLightning15==NULL) { return 15; }; + if (m_penLightning16==NULL) { return 16; }; + if (m_penLightning17==NULL) { return 17; }; + if (m_penLightning18==NULL) { return 18; }; + return 20; + } + +procedures: + Storm() + { + // wait before first lightning + autowait( 10.0f); + m_fNextLightningStrike = m_tmStormAppearTime+m_fFirstLightningDelay; + jump StormInternal(); + } + + StormInternal() + { + while(m_bStormOn && + _pTimer->CurrentTick()<((CWorldSettingsController *)&*m_penwsc)->m_tmStormEnd+m_tmStormDisappearTime) + { + while( _pTimer->CurrentTick()CurrentTick()<((CWorldSettingsController *)&*m_penwsc)->m_tmStormEnd+m_tmStormDisappearTime && + m_bStormOn) + { + // wait until next lightning + wait(_pTimer->TickQuantum) + { + on (EBegin) : + { + resume; + } + on (EEnvironmentStop) : + { + m_fNextLightningStrike+=1.0f; + resume; + } + on (ETimer) : { stop; } + } + } + autowait(_pTimer->TickQuantum); + + // calculate next lightning strike time + FLOAT fLightningStart=((CWorldSettingsController *)&*m_penwsc)->m_tmStormStart+m_fFirstLightningDelay; + FLOAT fLightningMax=fLightningStart+m_fMaxStormPowerTime; + FLOAT fRatio; + // if storm is finished + if(_pTimer->CurrentTick()>((CWorldSettingsController *)&*m_penwsc)->m_tmStormEnd-m_tmStormDisappearTime) + { + m_bStormOn = FALSE; + } + else + { + // fade in + if (_pTimer->CurrentTick()CurrentTick(), fLightningStart, fLightningMax, 1.0f, 0.0f); + } + // max storm power + else + { + fRatio=1; + } + FLOAT tmPeriod=(m_fMaxLightningPeriod-m_fMinLightningPeriod)*(1.0f-fRatio); + FLOAT fNextLighting=m_fMinLightningPeriod+tmPeriod*(1.0f+(FRnd()-0.5f)*0.25f); + m_fNextLightningStrike = _pTimer->CurrentTick()+fNextLighting; + + // choose random lightning + INDEX ctLightnings = GetLightningsCount(); + // if there are some lightnings + if (ctLightnings!=0) + { + // choose by random + CLightning *penLightning = (CLightning *) &*(&m_penLightning00)[IRnd()%ctLightnings]; + SendToTarget(penLightning, EET_TRIGGER); + } + } + } + m_bStormOn = FALSE; + return EReturn(); + } + + Main(EVoid) + { + // check lightning targets + CheckOneLightningTarget( m_penLightning00); + CheckOneLightningTarget( m_penLightning01); + CheckOneLightningTarget( m_penLightning02); + CheckOneLightningTarget( m_penLightning03); + CheckOneLightningTarget( m_penLightning04); + CheckOneLightningTarget( m_penLightning05); + CheckOneLightningTarget( m_penLightning06); + CheckOneLightningTarget( m_penLightning07); + CheckOneLightningTarget( m_penLightning08); + CheckOneLightningTarget( m_penLightning09); + CheckOneLightningTarget( m_penLightning10); + CheckOneLightningTarget( m_penLightning11); + CheckOneLightningTarget( m_penLightning12); + CheckOneLightningTarget( m_penLightning13); + CheckOneLightningTarget( m_penLightning14); + CheckOneLightningTarget( m_penLightning15); + CheckOneLightningTarget( m_penLightning16); + CheckOneLightningTarget( m_penLightning17); + CheckOneLightningTarget( m_penLightning18); + CheckOneLightningTarget( m_penLightning19); + + // set appearance + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_STORM_CONTROLLER); + SetModelMainTexture(TEXTURE_STORM_CONTROLLER); + + // spawn in world editor + autowait(0.1f); + + // obtain bcg viewer entity + CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) GetWorld()->GetBackgroundViewer(); + if( penBcgViewer == NULL) + { + // don't do anything + return; + } + + // obtain world settings controller + m_penwsc = penBcgViewer->m_penWorldSettingsController; + if( m_penwsc == NULL) + { + // don't do anything + return; + } + + // must be world settings controller entity + if (!IsOfClass(m_penwsc, "WorldSettingsController")) + { + // don't do anything + return; + } + + CWorldSettingsController *pwsc=(CWorldSettingsController *)&*m_penwsc; + pwsc->m_colBlendStart = m_colBlendStart; + pwsc->m_colBlendStop = m_colBlendStop; + pwsc->m_colShadeStart = m_colShadeStart; + pwsc->m_colShadeStop = m_colShadeStop; + pwsc->m_tmStormAppearTime = m_tmStormAppearTime; + pwsc->m_tmStormDisappearTime = m_tmStormDisappearTime; + + m_bStormOn = FALSE; + while (TRUE) + { + wait() + { + // immediate storm now + on (EEnvironmentStart eEnvironmentStart) : + { + TIME tmNow = _pTimer->CurrentTick(); + ((CWorldSettingsController *)&*m_penwsc)->m_tmStormStart = tmNow-m_tmStormAppearTime; + ((CWorldSettingsController *)&*m_penwsc)->m_tmStormEnd = 1e6; + m_bStormOn = TRUE; + m_fNextLightningStrike=_pTimer->CurrentTick()+2.0f; + call StormInternal(); + resume; + } + on (EStart eStart) : + { + if( !m_bStormOn) + { + TIME tmNow = _pTimer->CurrentTick(); + ((CWorldSettingsController *)&*m_penwsc)->m_tmStormStart = tmNow; + ((CWorldSettingsController *)&*m_penwsc)->m_tmStormEnd = 1e6; + m_bStormOn = TRUE; + call Storm(); + } + resume; + } + on (EStop eStop) : + { + if( m_bStormOn) + { + TIME tmNow = _pTimer->CurrentTick(); + ((CWorldSettingsController *)&*m_penwsc)->m_tmStormEnd = tmNow; + } + resume; + } + otherwise() : + { + resume; + }; + }; + } + } +}; diff --git a/Sources/EntitiesMP/StormController.h b/Sources/EntitiesMP/StormController.h new file mode 100644 index 0000000..67dc3e4 --- /dev/null +++ b/Sources/EntitiesMP/StormController.h @@ -0,0 +1,83 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_StormController_INCLUDED +#define _EntitiesMP_StormController_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CStormController_DLLClass; +class CStormController : public CRationalEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penwsc; + CTString m_strName; + FLOAT m_fNextLightningDelay; + BOOL m_bStormOn; + FLOAT m_fNextLightningStrike; + CEntityPointer m_penLightning00; + CEntityPointer m_penLightning01; + CEntityPointer m_penLightning02; + CEntityPointer m_penLightning03; + CEntityPointer m_penLightning04; + CEntityPointer m_penLightning05; + CEntityPointer m_penLightning06; + CEntityPointer m_penLightning07; + CEntityPointer m_penLightning08; + CEntityPointer m_penLightning09; + CEntityPointer m_penLightning10; + CEntityPointer m_penLightning11; + CEntityPointer m_penLightning12; + CEntityPointer m_penLightning13; + CEntityPointer m_penLightning14; + CEntityPointer m_penLightning15; + CEntityPointer m_penLightning16; + CEntityPointer m_penLightning17; + CEntityPointer m_penLightning18; + CEntityPointer m_penLightning19; + FLOAT m_tmStormAppearTime; + FLOAT m_tmStormDisappearTime; + FLOAT m_fFirstLightningDelay; + FLOAT m_fMaxLightningPeriod; + FLOAT m_fMinLightningPeriod; + FLOAT m_fMaxStormPowerTime; + COLOR m_colBlendStart; + COLOR m_colBlendStop; + COLOR m_colShadeStart; + COLOR m_colShadeStop; + +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +void CheckOneLightningTarget(CEntityPointer & pen); + +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +INDEX GetLightningsCount(void)const; +#define STATE_CStormController_Storm 0x025e0000 + BOOL +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Storm(const CEntityEvent &__eeInput); + BOOL H0x025e0001_Storm_01(const CEntityEvent &__eeInput); + BOOL H0x025e0002_Storm_02(const CEntityEvent &__eeInput); +#define STATE_CStormController_StormInternal 0x025e0003 + BOOL +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +StormInternal(const CEntityEvent &__eeInput); + BOOL H0x025e0004_StormInternal_01(const CEntityEvent &__eeInput); + BOOL H0x025e0005_StormInternal_02(const CEntityEvent &__eeInput); + BOOL H0x025e0006_StormInternal_03(const CEntityEvent &__eeInput); + BOOL H0x025e0007_StormInternal_04(const CEntityEvent &__eeInput); + BOOL H0x025e0008_StormInternal_05(const CEntityEvent &__eeInput); + BOOL H0x025e0009_StormInternal_06(const CEntityEvent &__eeInput); + BOOL H0x025e000a_StormInternal_07(const CEntityEvent &__eeInput); + BOOL H0x025e000b_StormInternal_08(const CEntityEvent &__eeInput); +#define STATE_CStormController_Main 1 + BOOL +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x025e000c_Main_01(const CEntityEvent &__eeInput); + BOOL H0x025e000d_Main_02(const CEntityEvent &__eeInput); + BOOL H0x025e000e_Main_03(const CEntityEvent &__eeInput); + BOOL H0x025e000f_Main_04(const CEntityEvent &__eeInput); + BOOL H0x025e0010_Main_05(const CEntityEvent &__eeInput); + BOOL H0x025e0011_Main_06(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_StormController_INCLUDED diff --git a/Sources/EntitiesMP/StormController_tables.h b/Sources/EntitiesMP/StormController_tables.h new file mode 100644 index 0000000..57189d5 --- /dev/null +++ b/Sources/EntitiesMP/StormController_tables.h @@ -0,0 +1,92 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CStormController + +CEntityProperty CStormController_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+1, offsetof(CStormController, m_penwsc), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x0000025e<<8)+2, offsetof(CStormController, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025e<<8)+3, offsetof(CStormController, m_fNextLightningDelay), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000025e<<8)+4, offsetof(CStormController, m_bStormOn), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025e<<8)+5, offsetof(CStormController, m_fNextLightningStrike), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+10, offsetof(CStormController, m_penLightning00), "Lightning 1", 'T', C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+11, offsetof(CStormController, m_penLightning01), "Lightning 2", 'Y', C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+12, offsetof(CStormController, m_penLightning02), "Lightning 3", 'U', C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+13, offsetof(CStormController, m_penLightning03), "Lightning 4", 'I', C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+14, offsetof(CStormController, m_penLightning04), "Lightning 5", 'O', C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+15, offsetof(CStormController, m_penLightning05), "Lightning 6", 'P', C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+16, offsetof(CStormController, m_penLightning06), "Lightning 7", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+17, offsetof(CStormController, m_penLightning07), "Lightning 8", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+18, offsetof(CStormController, m_penLightning08), "Lightning 9", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+19, offsetof(CStormController, m_penLightning09), "Lightning 10", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+20, offsetof(CStormController, m_penLightning10), "Lightning 11", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+21, offsetof(CStormController, m_penLightning11), "Lightning 12", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+22, offsetof(CStormController, m_penLightning12), "Lightning 13", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+23, offsetof(CStormController, m_penLightning13), "Lightning 14", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+24, offsetof(CStormController, m_penLightning14), "Lightning 15", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+25, offsetof(CStormController, m_penLightning15), "Lightning 16", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+26, offsetof(CStormController, m_penLightning16), "Lightning 17", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+27, offsetof(CStormController, m_penLightning17), "Lightning 18", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+28, offsetof(CStormController, m_penLightning18), "Lightning 19", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025e<<8)+29, offsetof(CStormController, m_penLightning19), "Lightning 20", 0, C_MAGENTA | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025e<<8)+40, offsetof(CStormController, m_tmStormAppearTime), "Storm appear time", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025e<<8)+41, offsetof(CStormController, m_tmStormDisappearTime), "Storm disappear time", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025e<<8)+42, offsetof(CStormController, m_fFirstLightningDelay), "First lightning delay", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025e<<8)+43, offsetof(CStormController, m_fMaxLightningPeriod), "Max lightning period", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025e<<8)+44, offsetof(CStormController, m_fMinLightningPeriod), "Min lightning period", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025e<<8)+45, offsetof(CStormController, m_fMaxStormPowerTime), "Max storm power time", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025e<<8)+50, offsetof(CStormController, m_colBlendStart), "Color blend start", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025e<<8)+51, offsetof(CStormController, m_colBlendStop), "Color blend stop", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025e<<8)+52, offsetof(CStormController, m_colShadeStart), "Color shade start", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025e<<8)+53, offsetof(CStormController, m_colShadeStop), "Color shade stop", 0, 0x7F0000FFUL, 0), +}; +#define CStormController_propertiesct ARRAYCOUNT(CStormController_properties) + +CEntityComponent CStormController_components[] = { +#define MODEL_STORM_CONTROLLER ((0x0000025e<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_STORM_CONTROLLER, "EFNM" "Models\\Editor\\StormController.mdl"), +#define TEXTURE_STORM_CONTROLLER ((0x0000025e<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_STORM_CONTROLLER, "EFNM" "Models\\Editor\\StormController.tex"), +}; +#define CStormController_componentsct ARRAYCOUNT(CStormController_components) + +CEventHandlerEntry CStormController_handlers[] = { + {0x025e0000, -1, CEntity::pEventHandler(&CStormController:: +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Storm),DEBUGSTRING("CStormController::Storm")}, + {0x025e0001, -1, CEntity::pEventHandler(&CStormController::H0x025e0001_Storm_01), DEBUGSTRING("CStormController::H0x025e0001_Storm_01")}, + {0x025e0002, -1, CEntity::pEventHandler(&CStormController::H0x025e0002_Storm_02), DEBUGSTRING("CStormController::H0x025e0002_Storm_02")}, + {0x025e0003, -1, CEntity::pEventHandler(&CStormController:: +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +StormInternal),DEBUGSTRING("CStormController::StormInternal")}, + {0x025e0004, -1, CEntity::pEventHandler(&CStormController::H0x025e0004_StormInternal_01), DEBUGSTRING("CStormController::H0x025e0004_StormInternal_01")}, + {0x025e0005, -1, CEntity::pEventHandler(&CStormController::H0x025e0005_StormInternal_02), DEBUGSTRING("CStormController::H0x025e0005_StormInternal_02")}, + {0x025e0006, -1, CEntity::pEventHandler(&CStormController::H0x025e0006_StormInternal_03), DEBUGSTRING("CStormController::H0x025e0006_StormInternal_03")}, + {0x025e0007, -1, CEntity::pEventHandler(&CStormController::H0x025e0007_StormInternal_04), DEBUGSTRING("CStormController::H0x025e0007_StormInternal_04")}, + {0x025e0008, -1, CEntity::pEventHandler(&CStormController::H0x025e0008_StormInternal_05), DEBUGSTRING("CStormController::H0x025e0008_StormInternal_05")}, + {0x025e0009, -1, CEntity::pEventHandler(&CStormController::H0x025e0009_StormInternal_06), DEBUGSTRING("CStormController::H0x025e0009_StormInternal_06")}, + {0x025e000a, -1, CEntity::pEventHandler(&CStormController::H0x025e000a_StormInternal_07), DEBUGSTRING("CStormController::H0x025e000a_StormInternal_07")}, + {0x025e000b, -1, CEntity::pEventHandler(&CStormController::H0x025e000b_StormInternal_08), DEBUGSTRING("CStormController::H0x025e000b_StormInternal_08")}, + {1, -1, CEntity::pEventHandler(&CStormController:: +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/StormController.es" +Main),DEBUGSTRING("CStormController::Main")}, + {0x025e000c, -1, CEntity::pEventHandler(&CStormController::H0x025e000c_Main_01), DEBUGSTRING("CStormController::H0x025e000c_Main_01")}, + {0x025e000d, -1, CEntity::pEventHandler(&CStormController::H0x025e000d_Main_02), DEBUGSTRING("CStormController::H0x025e000d_Main_02")}, + {0x025e000e, -1, CEntity::pEventHandler(&CStormController::H0x025e000e_Main_03), DEBUGSTRING("CStormController::H0x025e000e_Main_03")}, + {0x025e000f, -1, CEntity::pEventHandler(&CStormController::H0x025e000f_Main_04), DEBUGSTRING("CStormController::H0x025e000f_Main_04")}, + {0x025e0010, -1, CEntity::pEventHandler(&CStormController::H0x025e0010_Main_05), DEBUGSTRING("CStormController::H0x025e0010_Main_05")}, + {0x025e0011, -1, CEntity::pEventHandler(&CStormController::H0x025e0011_Main_06), DEBUGSTRING("CStormController::H0x025e0011_Main_06")}, +}; +#define CStormController_handlersct ARRAYCOUNT(CStormController_handlers) + +CEntity *CStormController_New(void) { return new CStormController; }; +void CStormController_OnInitClass(void) {}; +void CStormController_OnEndClass(void) {}; +void CStormController_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CStormController_OnWorldEnd(CWorld *pwo) {}; +void CStormController_OnWorldInit(CWorld *pwo) {}; +void CStormController_OnWorldTick(CWorld *pwo) {}; +void CStormController_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CStormController, CRationalEntity, "Storm controller", "Thumbnails\\StormController.tbn", 0x0000025e); +DECLARE_CTFILENAME(_fnmCStormController_tbn, "Thumbnails\\StormController.tbn"); diff --git a/Sources/EntitiesMP/Summoner.cpp b/Sources/EntitiesMP/Summoner.cpp new file mode 100644 index 0000000..8a9821a --- /dev/null +++ b/Sources/EntitiesMP/Summoner.cpp @@ -0,0 +1,2123 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" + +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "ModelsMP/Enemies/Summoner/Summoner.h" +#include "ModelsMP/Enemies/Summoner/Staff.h" +#include "EntitiesMP/Effector.h" + +#include +#include +CEntityEvent *ESummonerTeleport::MakeCopy(void) { CEntityEvent *peeCopy = new ESummonerTeleport(*this); return peeCopy;} +ESummonerTeleport::ESummonerTeleport() : CEntityEvent(EVENTCODE_ESummonerTeleport) {; + ClearToDefault(fWait); +}; +#line 23 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" + +#define RAND_05 (FLOAT(rand())/RAND_MAX-0.5f) +#define SUMMONER_SIZE 7.0f +#define TM_WAIT_BEFORE_FIRE 1.9f +#define SUMMONER_HEALTH 15000.0f +// info structure +static EntityInfo eiSummoner = { + EIBT_FLESH, 1500.0f, + 0.0f, 1.7f*SUMMONER_SIZE, 0.0f, + 0.0f, 1.0f*SUMMONER_SIZE, 0.0f, +}; + +//#define FIREPOS_ARMS FLOAT3D(-0.22f, 1.63f, 0.96f) +#define FIREPOS_ARMS FLOAT3D(0.131292f, 1.61069f, -0.314068f) + +#define SUMMONER_MAX_SS 6 + // hlth grp1 grp2 grp3 +INDEX aiSpawnScheme[SUMMONER_MAX_SS][7] = {100, 4,7, 0,0, 0,0, + 90, 3,5, 2,4, 0,0, + 70, 3,4, 3,4, 0,0, + 50, 1,3, 3,5, 1,1, + 30, 1,2, 2,3, 2,2, + 15, 1,1, 2,4, 2,3 }; +#define SUMMONER_TEMP_PER_GROUP 6 + +void CSummoner::SetDefaultProperties(void) { + m_bInvulnerable = FALSE ; + m_penBeginDeathTarget = NULL; + m_penEndDeathTarget = NULL; + m_penExplodeDeathTarget = NULL; + m_bShouldTeleport = FALSE ; + m_fFirePeriod = 3.0f; + m_fImmaterialDuration = 5.0f; + m_fCorporealDuration = 5.0f; + m_tmMaterializationTime = 0.0f; + m_fStretch = SUMMONER_SIZE ; + m_iSize = 1; + m_penControlArea = NULL; + m_iGroup01Count = 0; + m_penGroup01Template01 = NULL; + m_penGroup01Template02 = NULL; + m_penGroup01Template03 = NULL; + m_penGroup01Template04 = NULL; + m_penGroup01Template05 = NULL; + m_penGroup01Template06 = NULL; + m_iGroup02Count = 0; + m_penGroup02Template01 = NULL; + m_penGroup02Template02 = NULL; + m_penGroup02Template03 = NULL; + m_penGroup02Template04 = NULL; + m_penGroup02Template05 = NULL; + m_penGroup02Template06 = NULL; + m_iGroup03Count = 0; + m_penGroup03Template01 = NULL; + m_penGroup03Template02 = NULL; + m_penGroup03Template03 = NULL; + m_penGroup03Template04 = NULL; + m_penGroup03Template05 = NULL; + m_penGroup03Template06 = NULL; + m_penTeleportMarker = NULL; + m_iTeleportMarkers = 0; + m_penSpawnMarker = NULL; + m_iSpawnMarkers = 0; + m_fTeleportWaitTime = 0.0f; + m_fFuss = 0.0f; + m_iEnemyCount = 0; + m_fMaxCurrentFuss = 0.0f; + m_fMaxBeginFuss = 10000.0f; + m_fMaxEndFuss = 60000.0f; + m_iSpawnScheme = 0; + m_bFireOK = TRUE ; + m_bFiredThisTurn = FALSE ; + m_fDamageSinceLastSpawn = 0.0f; + m_bExploded = FALSE ; + m_bDying = FALSE ; + m_tmDeathBegin = 0.0f; + m_fDeathDuration = 0.0f; + m_penDeathInflictor = NULL; + m_penKiller = NULL; + m_vDeathPosition = FLOAT3D(0.0f , 0.0f , 0.0f); + m_penDeathMarker = NULL; + m_iIndex = 0; + m_iTaunt = 0; + m_tmParticlesDisappearStart = -1e6; + m_tmLastAnimation = 0.0f; + m_soExplosion.SetOwner(this); +m_soExplosion.Stop_internal(); + m_soSound.SetOwner(this); +m_soSound.Stop_internal(); + m_soChant.SetOwner(this); +m_soChant.Stop_internal(); + m_soTeleport.SetOwner(this); +m_soTeleport.Stop_internal(); + CEnemyBase::SetDefaultProperties(); +} + +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::Read_t(CTStream * istr) +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEnemyBase :: Read_t (istr ); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_emEmiter . Read_t (* istr ); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::Write_t(CTStream * istr) +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEnemyBase :: Write_t (istr ); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_emEmiter . Write_t (* istr ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +BOOL CSummoner::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(slPropertyOffset >= offsetof (CSummoner , m_penGroup01Template01 ) && +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +slPropertyOffset <= offsetof (CSummoner , m_penGroup03Template06 )) +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(IsDerivedFromClass (penTarget , "Enemy Base")){ +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(((CEnemyBase &) * penTarget ) . m_bTemplate ){ +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE ; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else { +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE ; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else { +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE ; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(slPropertyOffset == offsetof (CSummoner , m_penControlArea )) +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(IsDerivedFromClass (penTarget , "AreaMarker")){ +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE ; +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else { +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE ; +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(slPropertyOffset == offsetof (CSummoner , m_penSpawnMarker )) +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(IsDerivedFromClass (penTarget , "Enemy Marker")){ +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE ; +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else { +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE ; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(slPropertyOffset == offsetof (CSummoner , m_penTeleportMarker ) || +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +slPropertyOffset == offsetof (CSummoner , m_penDeathMarker )) +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(IsDerivedFromClass (penTarget , "SummonerMarker")){ +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else { +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE ; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return CEntity :: IsTargetValid (slPropertyOffset , penTarget ); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +BOOL CSummoner::DoSafetyChecks(void) { +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_penSpawnMarker == NULL ){ +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +WarningMessage ("No valid Spawn Marker for Summoner boss! Destroying boss..."); +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE ; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_penTeleportMarker == NULL ){ +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +WarningMessage ("No valid Teleport Marker for Summoner boss! Destroying boss..."); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE ; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_penDeathMarker == NULL ){ +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +WarningMessage ("No valid Death Marker for Summoner boss! Destroying boss..."); +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE ; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_penControlArea == NULL ){ +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +WarningMessage ("No valid Area Marker for Summoner boss! Destroying boss..."); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE ; +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_iGroup01Count < 1 || m_iGroup02Count < 1 || m_iGroup03Count < 1) +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +WarningMessage ("At least one template in each group required! Destroying boss..."); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE ; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE ; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + CTString CSummoner::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CTString str ; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +str . PrintF (TRANS ("The Summoner unsummoned %s") , strPlayerName ); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return str ; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + const CTFileName & CSummoner::GetComputerMessageName(void)const { +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +static DECLARE_CTFILENAME (fnm , "DataMP\\Messages\\Enemies\\Summoner.txt"); +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return fnm ; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::Precache(void) +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEnemyBase :: Precache (); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheClass (CLASS_BLOOD_SPRAY ); +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheClass (CLASS_SPAWNER_PROJECTILE ); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheClass (CLASS_BASIC_EFFECT , BET_CANNON ); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheModel (MODEL_SUMMONER ); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheModel (MODEL_STAFF ); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheTexture (TEXTURE_SUMMONER ); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheTexture (TEXTURE_STAFF ); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheModel (MODEL_DEBRIS01 ); +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheModel (MODEL_DEBRIS02 ); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheModel (MODEL_DEBRIS03 ); +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheModel (MODEL_DEBRIS_FLESH ); +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheTexture (TEXTURE_DEBRIS_FLESH ); +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheSound (SOUND_LAUGH ); +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheSound (SOUND_EXPLODE ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheSound (SOUND_TREMORS ); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheSound (SOUND_DEATH ); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheSound (SOUND_LASTWORDS ); +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheSound (SOUND_FIRE ); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheSound (SOUND_CHIMES ); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheSound (SOUND_MATERIALIZE ); +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheSound (SOUND_TELEPORT ); +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX i = SOUND_TAUNT01 ;i <= SOUND_TAUNTLAST ;i ++){ +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrecacheSound (i ); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void * CSummoner::GetEntityInfo(void) { +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return & eiSummoner ; +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CMusicHolder * CSummoner::GetMusicHolder() +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntity * penMusicHolder ; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penMusicHolder = _pNetwork -> GetEntityWithName ("MusicHolder" , 0); +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return (CMusicHolder *) & * penMusicHolder ; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +BOOL CSummoner::DistanceToAllPlayersGreaterThen(FLOAT fDistance) +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX ctMaxPlayers = GetMaxPlayers (); +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntity * penPlayer ; +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX i = 0;i < ctMaxPlayers ;i ++){ +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penPlayer = GetPlayerEntity (i ); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(penPlayer ){ +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(DistanceTo (this , penPlayer ) < fDistance ){ +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE ; +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE ; +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::ShakeItBaby(FLOAT tmShaketime,FLOAT fPower,BOOL bFadeIn) +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(pwsc != NULL ){ +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pwsc -> m_tmShakeStarted = tmShaketime ; +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pwsc -> m_vShakePos = GetPlacement () . pl_PositionVector ; +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pwsc -> m_fShakeFalloff = 450.0f; +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pwsc -> m_fShakeFade = 3.0f; +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pwsc -> m_fShakeIntensityZ = 0; +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pwsc -> m_tmShakeFrequencyZ = 5.0f; +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pwsc -> m_fShakeIntensityY = 0.1f * fPower ; +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pwsc -> m_tmShakeFrequencyY = 5.0f; +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pwsc -> m_fShakeIntensityB = 2.5f * fPower ; +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pwsc -> m_tmShakeFrequencyB = 7.2f; +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pwsc -> m_bShakeFadeIn = bFadeIn ; +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::ChangeEnemyNumberForAllPlayers(INDEX iDelta) +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX ctMaxPlayers = GetMaxPlayers (); +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntity * penPlayer ; +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX i = 0;i < ctMaxPlayers ;i ++){ +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penPlayer = GetPlayerEntity (i ); +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(penPlayer ){ +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +((CPlayer &) * penPlayer ) . m_psLevelTotal . ps_iKills += iDelta ; +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +((CPlayer &) * penPlayer ) . m_psGameTotal . ps_iKills += iDelta ; +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_bInvulnerable ){ +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return ; +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 392 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(! IsOfClass (penInflictor , "Player")){ +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return ; +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(dmtType == DMT_TELEPORT ) +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return ; +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(dmtType == DMT_CANNONBALL ) +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +fDamageAmmount *= 0.5f; +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fOldHealth = GetHealth (); +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fNewHealth = GetHealth (); +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fDamageSinceLastSpawn += fOldHealth - fNewHealth ; +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX i = 0;i < SUMMONER_MAX_SS ;i ++){ +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fHealth = (FLOAT) aiSpawnScheme [ i ] [ 0 ] * m_fMaxHealth / 100.0f; +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(fHealth <= fOldHealth && fHealth > fNewHealth ) +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iSpawnScheme = i ; +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fMaxCurrentFuss = (1.0f - (GetHealth () / m_fMaxHealth )) * (m_fMaxEndFuss - m_fMaxBeginFuss ) + m_fMaxBeginFuss ; +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_colBurning = COLOR (C_WHITE | CT_OPAQUE ); +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::StandingAnimFight(void) { +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::StandingAnim(void) { +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::WalkingAnim(void) { +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::RunningAnim(void) { +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +WalkingAnim (); +#line 456 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::RotatingAnim(void) { +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +WalkingAnim (); +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::IdleSound(void) { +#line 472 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D CSummoner::AcquireTarget() +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEnemyMarker * marker ; +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +marker = & ((CEnemyMarker &) * m_penSpawnMarker ); +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iMarker = IRnd () % m_iSpawnMarkers ; +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +while(iMarker > 0) +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +marker = & ((CEnemyMarker &) * marker -> m_penTarget ); +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iMarker --; +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vTarget = marker -> GetPlacement () . pl_PositionVector ; +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fR = FRnd () * marker -> m_fMarkerRange ; +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fA = FRnd () * 360.0f; +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vTarget += FLOAT3D (CosFast (fA ) * fR , 0.05f , SinFast (fA ) * fR ); +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return vTarget ; +#line 491 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::LaunchMonster(FLOAT3D vTarget,CEntity * penTemplate) +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ASSERT (penTemplate != NULL ); +#line 497 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vFirePos = FIREPOS_ARMS * m_fStretch ; +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vShooting = GetPlacement () . pl_PositionVector + vFirePos * GetRotationMatrix (); +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fLaunchSpeed ; +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fRelativeHdg ; +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fPitch = FRnd () * 10.0f + 25.0f; +#line 504 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CPlacement3D pl ; +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CalculateAngularLaunchParams (vShooting , 0.0f , vTarget , +#line 506 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D (0.0f , 0.0f , 0.0f) , fPitch , fLaunchSpeed , fRelativeHdg ); +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PrepareFreeFlyingProjectile (pl , vTarget , vFirePos , ANGLE3D (fRelativeHdg , fPitch , 0.0f)); +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ESpawnerProjectile esp ; +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer penSProjectile = CreateEntity (pl , CLASS_SPAWNER_PROJECTILE ); +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +esp . penOwner = this ; +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +esp . penTemplate = penTemplate ; +#line 514 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penSProjectile -> Initialize (esp ); +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +((CMovableEntity &) * penSProjectile ) . LaunchAsFreeProjectile (FLOAT3D (0.0f , 0.0f , - fLaunchSpeed ) , (CMovableEntity *) (CEntity *) this ); +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT CSummoner::FussModifier(INDEX iEnemyCount) { +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return (0.995 + 0.005 * pow (m_iEnemyCount , 2.8)); +#line 521 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::RecalculateFuss(void) +#line 524 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOATaabbox3D box ; +#line 527 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +((CAreaMarker &) * m_penControlArea ) . GetAreaBox (box ); +#line 529 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +static CStaticStackArray < CEntity * > apenNearEntities ; +#line 530 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +GetWorld () -> FindEntitiesNearBox (box , apenNearEntities ); +#line 532 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX m_iEnemyCount = 0; +#line 533 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fFuss = 0.0f; +#line 535 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX i = 0;i < apenNearEntities . Count ();i ++) +#line 536 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 537 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(IsDerivedFromClass (apenNearEntities [ i ] , "Enemy Base") && +#line 538 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +! IsOfClass (apenNearEntities [ i ] , "Summoner")){ +#line 539 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(! ((CEnemyBase &) * apenNearEntities [ i ]) . m_bTemplate && +#line 540 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +apenNearEntities [ i ] -> GetFlags () & ENF_ALIVE ){ +#line 541 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fFuss += ((CEnemyBase &) * apenNearEntities [ i ]) . m_iScore ; +#line 542 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iEnemyCount ++; +#line 543 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 544 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 545 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 547 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fFuss *= FussModifier (m_iEnemyCount ); +#line 550 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_fFuss > m_fMaxCurrentFuss ){ +#line 552 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bFireOK = FALSE ; +#line 554 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else if(m_fFuss < 0.4 * m_fMaxCurrentFuss ){ +#line 556 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bFireOK = TRUE ; +#line 558 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else if(m_fDamageSinceLastSpawn > 0.07f * m_fMaxHealth ){ +#line 560 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bFireOK = TRUE ; +#line 561 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 565 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return ; +#line 566 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::CountEnemiesAndScoreValue(INDEX & iEnemies,FLOAT & fScore) +#line 569 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 571 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOATaabbox3D box ; +#line 572 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +((CAreaMarker &) * m_penControlArea ) . GetAreaBox (box ); +#line 574 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +static CStaticStackArray < CEntity * > apenNearEntities ; +#line 575 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +GetWorld () -> FindEntitiesNearBox (box , apenNearEntities ); +#line 577 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iEnemies = 0; +#line 578 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +fScore = 0.0f; +#line 580 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX i = 0;i < apenNearEntities . Count ();i ++) +#line 581 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 582 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(IsDerivedFromClass (apenNearEntities [ i ] , "Enemy Base") && +#line 583 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +! IsOfClass (apenNearEntities [ i ] , "Summoner")){ +#line 584 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(! ((CEnemyBase &) * apenNearEntities [ i ]) . m_bTemplate && +#line 585 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +apenNearEntities [ i ] -> GetFlags () & ENF_ALIVE ){ +#line 586 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +fScore += ((CEnemyBase &) * apenNearEntities [ i ]) . m_iScore ; +#line 587 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iEnemies ++; +#line 588 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 589 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 590 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 591 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return ; +#line 592 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEnemyBase * CSummoner::GetRandomTemplate(INDEX iGroup) +#line 595 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 596 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer * pen ; +#line 597 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iCount ; +#line 598 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(iGroup == 0){ +#line 599 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pen = & m_penGroup01Template01 ; +#line 600 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iCount = IRnd () % m_iGroup01Count + 1; +#line 601 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else if(iGroup == 1){ +#line 602 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pen = & m_penGroup02Template01 ; +#line 603 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iCount = IRnd () % m_iGroup02Count + 1; +#line 604 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else if(iGroup == 2){ +#line 605 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pen = & m_penGroup03Template01 ; +#line 606 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iCount = IRnd () % m_iGroup03Count + 1; +#line 607 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else { +#line 608 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ASSERT ("Invalid group!"); +#line 609 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 610 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ASSERT (iCount > 0); +#line 612 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX i = - 1; +#line 613 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +while(iCount > 0) +#line 614 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 615 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +i ++; +#line 616 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +while(& * pen [ i ] == NULL ){ +#line 617 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +i ++; +#line 618 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 619 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iCount --; +#line 620 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 621 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ASSERT (& (CEnemyBase &) * pen [ i ] != NULL ); +#line 622 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return & (CEnemyBase &) * pen [ i ]; +#line 623 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::DisappearEffect(void) +#line 626 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 627 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CPlacement3D plFX = GetPlacement (); +#line 628 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ESpawnEffect ese ; +#line 629 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 630 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . vStretch = FLOAT3D (3 , 3 , 3); +#line 631 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . vNormal = FLOAT3D (0 , 1 , 0); +#line 632 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . betType = BET_DUST_FALL ; +#line 633 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX iSmoke = 0;iSmoke < 3;iSmoke ++) +#line 634 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 635 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CPlacement3D plSmoke = plFX ; +#line 636 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +plSmoke . pl_PositionVector += FLOAT3D (0 , iSmoke * 4 + 4.0f , 0); +#line 637 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer penFX = CreateEntity (plSmoke , CLASS_BASIC_EFFECT ); +#line 638 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penFX -> Initialize (ese ); +#line 639 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 647 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::SpawnTeleportEffect(void) +#line 650 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 651 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ESpawnEffect ese ; +#line 652 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . colMuliplier = C_lMAGENTA | CT_OPAQUE ; +#line 653 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . vStretch = FLOAT3D (5 , 5 , 5); +#line 654 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . vNormal = FLOAT3D (0 , 1 , 0); +#line 657 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . betType = BET_EXPLOSION_DEBRIS ; +#line 658 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CPlacement3D plFX = GetPlacement (); +#line 659 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer penFX = CreateEntity (plFX , CLASS_BASIC_EFFECT ); +#line 660 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penFX -> Initialize (ese ); +#line 661 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . colMuliplier = C_MAGENTA | CT_OPAQUE ; +#line 662 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer penFX2 = CreateEntity (plFX , CLASS_BASIC_EFFECT ); +#line 663 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penFX2 -> Initialize (ese ); +#line 664 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . colMuliplier = C_lCYAN | CT_OPAQUE ; +#line 665 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer penFX3 = CreateEntity (plFX , CLASS_BASIC_EFFECT ); +#line 666 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penFX3 -> Initialize (ese ); +#line 667 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . betType = BET_CANNON ; +#line 668 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ese . colMuliplier = C_CYAN | CT_OPAQUE ; +#line 669 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer penFX4 = CreateEntity (plFX , CLASS_BASIC_EFFECT ); +#line 670 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penFX4 -> Initialize (ese ); +#line 679 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ESpawnEffector eLightning ; +#line 680 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eLightning . eetType = ET_LIGHTNING ; +#line 681 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eLightning . tmLifeTime = 0.5f; +#line 682 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eLightning . fSize = 24; +#line 683 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eLightning . ctCount = 32; +#line 685 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntity * penLightning = CreateEntity (plFX , CLASS_EFFECTOR ); +#line 686 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ANGLE3D angRnd = ANGLE3D ( +#line 687 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +0.0f , +#line 688 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +90.0f + (FRnd () - 0.5f) * 30.0f , +#line 689 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +(FRnd () - 0.5f) * 30.0f); +#line 691 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vRndDir ; +#line 692 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +AnglesToDirectionVector (angRnd , vRndDir ); +#line 693 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vDest = plFX . pl_PositionVector ; +#line 694 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vDest += vRndDir * 512.0f; +#line 695 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eLightning . vDestination = vDest ; +#line 696 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penLightning -> Initialize (eLightning ); +#line 697 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 699 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::KillAllEnemiesInArea(EDeath eDeath) +#line 700 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 701 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +EDeath eDeath2 ; +#line 702 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOATaabbox3D box ; +#line 703 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +((CAreaMarker &) * m_penControlArea ) . GetAreaBox (box ); +#line 705 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +static CStaticStackArray < CEntity * > apenNearEntities ; +#line 706 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +GetWorld () -> FindEntitiesNearBox (box , apenNearEntities ); +#line 708 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX i = 0;i < apenNearEntities . Count ();i ++) +#line 709 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 710 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(IsDerivedFromClass (apenNearEntities [ i ] , "Enemy Base") && +#line 711 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +! IsOfClass (apenNearEntities [ i ] , "Summoner")){ +#line 712 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(! ((CEnemyBase &) * apenNearEntities [ i ]) . m_bTemplate && +#line 713 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +apenNearEntities [ i ] -> GetFlags () & ENF_ALIVE ){ +#line 714 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eDeath2 . eLastDamage . penInflictor = eDeath . eLastDamage . penInflictor ; +#line 715 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eDeath2 . eLastDamage . vDirection = apenNearEntities [ i ] -> GetPlacement () . pl_PositionVector ; +#line 716 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eDeath2 . eLastDamage . vHitPoint = eDeath2 . eLastDamage . vDirection ; +#line 717 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eDeath2 . eLastDamage . fAmount = 10000.0f; +#line 718 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eDeath2 . eLastDamage . dmtType = DMT_CLOSERANGE ; +#line 719 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +apenNearEntities [ i ] -> SendEvent (eDeath ); +#line 720 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 721 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 723 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CMusicHolder * penMusicHolder = GetMusicHolder (); +#line 724 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(IsOfClass (apenNearEntities [ i ] , "SpawnerProjectile")){ +#line 725 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CPlacement3D pl ; +#line 726 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pl . pl_OrientationAngle = ANGLE3D (0.0f , 0.0f , 0.0f); +#line 727 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pl . pl_PositionVector = apenNearEntities [ i ] -> GetPlacement () . pl_PositionVector ; +#line 728 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer penExplosion = CreateEntity (pl , CLASS_BASIC_EFFECT ); +#line 729 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ESpawnEffect eSpawnEffect ; +#line 730 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 731 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eSpawnEffect . betType = BET_CANNON ; +#line 732 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eSpawnEffect . vStretch = FLOAT3D (2.0f , 2.0f , 2.0f); +#line 733 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 734 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +apenNearEntities [ i ] -> Destroy (); +#line 736 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(penMusicHolder != NULL ){ +#line 737 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penMusicHolder -> m_ctEnemiesInWorld --; +#line 738 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 739 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ChangeEnemyNumberForAllPlayers (- 1); +#line 740 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 741 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 742 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} + +#line 744 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CSummoner::RenderParticles(void) +#line 745 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 746 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT tmNow = _pTimer -> CurrentTick (); +#line 747 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(tmNow > m_tmParticlesDisappearStart && tmNow < m_tmParticlesDisappearStart + 4.0f) +#line 748 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 749 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Particles_SummonerDisappear (this , m_tmParticlesDisappearStart ); +#line 750 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 752 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(tmNow > m_tmLastAnimation ) +#line 753 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 754 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX ctInterpolations = 2; +#line 756 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(! m_bInvulnerable && ! m_bExploded && GetHealth () > 0) +#line 757 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 758 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX iInter = 0;iInter < ctInterpolations ;iInter ++) +#line 759 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 761 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOATmatrix3D mEn = GetRotationMatrix (); +#line 762 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOATmatrix3D mRot ; +#line 763 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vPos ; +#line 764 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT tmBirth = tmNow + iInter * _pTimer -> TickQuantum / ctInterpolations ; +#line 766 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fLife = 2.5f; +#line 767 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fCone = 360.0f; +#line 768 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fStretch = 1.0f; +#line 769 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fRotSpeed = 360.0f; +#line 770 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +COLOR col = C_lYELLOW | CT_OPAQUE ; +#line 772 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +MakeRotationMatrixFast (mRot , ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 773 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vPos = FLOAT3D (0.0f , 0.0f , 0.0f); +#line 774 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +GetModelObject () -> GetAttachmentTransformations (SUMMONER_ATTACHMENT_STAFF , mRot , vPos , FALSE ); +#line 776 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CAttachmentModelObject * pamo = GetModelObject () -> GetAttachmentModel (SUMMONER_ATTACHMENT_STAFF ); +#line 777 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pamo -> amo_moModelObject . GetAttachmentTransformations (STAFF_ATTACHMENT_PARTICLES , mRot , vPos , TRUE ); +#line 778 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vPos = GetPlacement () . pl_PositionVector + vPos * GetRotationMatrix (); +#line 780 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vSpeed = FLOAT3D (0.1f + RAND_05 , 0.1f + RAND_05 , - 1.0f - RAND_05 ); +#line 781 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vSpeed = vSpeed . Normalize () * 8.0f; +#line 782 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_emEmiter . AddParticle (vPos , vSpeed * mRot * mEn , RAND_05 * 360.0f , fRotSpeed , tmBirth , fLife , fStretch , col ); +#line 783 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 784 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 786 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_emEmiter . em_vG = m_emEmiter . GetGravity (this ); +#line 787 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_emEmiter . em_vG /= 2.0f; +#line 788 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_emEmiter . AnimateParticles (); +#line 789 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_tmLastAnimation = tmNow ; +#line 790 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 791 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_emEmiter . RenderParticles (); +#line 792 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +BOOL CSummoner:: +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +InitiateTeleport(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSummoner_InitiateTeleport + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSummoner::InitiateTeleport expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 799 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bInvulnerable = TRUE ; +#line 800 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_VANISHING , 0); +#line 803 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT tmNow = _pTimer -> CurrentTick (); +#line 804 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_tmParticlesDisappearStart = tmNow ; +#line 806 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soSound , SOUND_TELEPORT , SOF_3D ); +#line 808 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (SUMMONER_ANIM_VANISHING ) - 0.2f); +Jump(STATE_CURRENT, 0x015b0002, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0002_InitiateTeleport_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0002 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0003, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0003_InitiateTeleport_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0003 +; +#line 809 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Jump(STATE_CURRENT, STATE_CSummoner_Immaterial, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSummoner:: +#line 812 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSummoner_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSummoner::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 815 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(!(! m_bFiredThisTurn )){ Jump(STATE_CURRENT,0x015b0012, FALSE, EInternal());return TRUE;} +#line 817 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(!(m_bFireOK )){ Jump(STATE_CURRENT,0x015b0011, FALSE, EInternal());return TRUE;} +#line 819 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iTaunt = SOUND_TAUNT01 + m_iTaunt % (SOUND_TAUNTLAST - SOUND_TAUNT01 + 1); +#line 820 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soChant , iTaunt , SOF_3D ); +#line 821 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iTaunt ++; +#line 823 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_MAGICATTACK , SOF_SMOOTHCHANGE ); +#line 826 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(TM_WAIT_BEFORE_FIRE ); +Jump(STATE_CURRENT, 0x015b0005, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0005_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0006_Fire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0006 +; +#line 827 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D ); +#line 829 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX i , j ; +#line 830 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vTarget ; +#line 831 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fTotalSpawnedScore = 0.0f; +#line 832 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iTotalSpawnedCount = 0; +#line 833 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iEnemyCount ; +#line 834 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fScore ; +#line 835 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CountEnemiesAndScoreValue (iEnemyCount , fScore ); +#line 837 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CMusicHolder * penMusicHolder = GetMusicHolder (); +#line 839 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fTmpFuss = 0.0f; +#line 842 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(i = 0;i < 3;i ++){ +#line 843 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iMin = aiSpawnScheme [ m_iSpawnScheme ] [ i * 2 + 1 ]; +#line 844 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iMax = aiSpawnScheme [ m_iSpawnScheme ] [ i * 2 + 2 ]; +#line 845 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ASSERT (iMin <= iMax ); +#line 846 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iToSpawn ; +#line 847 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iToSpawn = iMin + IRnd () % (iMax - iMin + 1); +#line 848 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(j = 0;j < iToSpawn ;j ++){ +#line 849 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEnemyBase * penTemplate = GetRandomTemplate (i ); +#line 850 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vTarget = AcquireTarget (); +#line 851 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +LaunchMonster (vTarget , penTemplate ); +#line 852 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +fTotalSpawnedScore += penTemplate -> m_iScore ; +#line 853 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iTotalSpawnedCount ++; +#line 855 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(penMusicHolder != NULL ){ +#line 856 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penMusicHolder -> m_ctEnemiesInWorld ++; +#line 857 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 858 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ChangeEnemyNumberForAllPlayers (+ 1); +#line 860 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +fTmpFuss = (fTotalSpawnedScore + fScore ) * FussModifier (iTotalSpawnedCount + iEnemyCount ); +#line 861 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(fTmpFuss > m_fMaxCurrentFuss ){ +#line 862 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +break ; +#line 863 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 864 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 865 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 867 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fDamageSinceLastSpawn = 0.0f; +#line 870 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (SUMMONER_ANIM_MAGICATTACK ) - TM_WAIT_BEFORE_FIRE ); +Jump(STATE_CURRENT, 0x015b0007, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0007_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0008, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0008_Fire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0008 +; +#line 873 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_IDLE , SOF_SMOOTHCHANGE ); +#line 876 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ESummonerTeleport est ; +#line 877 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +est . fWait = FRnd () * 1.0f + 3.0f; +#line 878 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SendEvent (est );Jump(STATE_CURRENT,0x015b0010, FALSE, EInternal());return TRUE;}BOOL CSummoner::H0x015b0011_Fire_13(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0011 +if(!(TRUE )){ Jump(STATE_CURRENT,0x015b000f, FALSE, EInternal());return TRUE;} +#line 882 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soExplosion , SOUND_LAUGH , SOF_3D ); +#line 883 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(1.0f); +Jump(STATE_CURRENT, 0x015b0009, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0009_Fire_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b000a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b000a_Fire_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000a +; +#line 884 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_MAGICATTACK , SOF_SMOOTHCHANGE ); +#line 886 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iTaunt = SOUND_TAUNT01 + m_iTaunt % (SOUND_TAUNTLAST - SOUND_TAUNT01 + 1); +#line 887 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soChant , iTaunt , SOF_3D ); +#line 888 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iTaunt ++; +#line 891 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(TM_WAIT_BEFORE_FIRE ); +Jump(STATE_CURRENT, 0x015b000b, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b000b_Fire_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b000c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b000c_Fire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000c +; +#line 892 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D ); +#line 894 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iEnemyCount ; +#line 895 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fScore ; +#line 896 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CountEnemiesAndScoreValue (iEnemyCount , fScore ); +#line 897 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fToSpawn ; +#line 899 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iScheme ; +#line 901 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX i = 0;i < 3;i ++){ +#line 902 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(aiSpawnScheme [ m_iSpawnScheme ] [ i * 2 + 2 ] > 0){ +#line 903 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iScheme = i ; +#line 904 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 905 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 907 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_iSpawnScheme > 3){ +#line 908 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iEnemyCount += (m_iSpawnScheme - 3); +#line 909 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 911 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(iEnemyCount < 6){ +#line 912 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +fToSpawn = (6.0 - (FLOAT) iEnemyCount ) / 2.0f; +#line 913 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else { +#line 914 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +fToSpawn = 1.0f; +#line 915 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 916 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iToSpawn = ceilf (fToSpawn ); +#line 918 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CMusicHolder * penMusicHolder = GetMusicHolder (); +#line 921 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX j = 0;j < iToSpawn ;j ++){ +#line 922 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEnemyBase * penTemplate = GetRandomTemplate (iScheme ); +#line 923 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vTarget = AcquireTarget (); +#line 924 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +LaunchMonster (vTarget , penTemplate ); +#line 926 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(penMusicHolder != NULL ){ +#line 927 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penMusicHolder -> m_ctEnemiesInWorld ++; +#line 928 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 929 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ChangeEnemyNumberForAllPlayers (+ 1); +#line 930 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 933 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ESummonerTeleport est ; +#line 934 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +est . fWait = FRnd () * 1.0f + 3.0f; +#line 935 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SendEvent (est ); +#line 937 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(1.0f); +Jump(STATE_CURRENT, 0x015b000d, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b000d_Fire_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b000e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b000e_Fire_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000e +;Jump(STATE_CURRENT,0x015b000f, FALSE, EInternal());return TRUE;}BOOL CSummoner::H0x015b000f_Fire_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b000f +Jump(STATE_CURRENT,0x015b0010, FALSE, EInternal());return TRUE;} +BOOL CSummoner::H0x015b0010_Fire_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0010 + +#line 941 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bFiredThisTurn = TRUE ;Jump(STATE_CURRENT,0x015b0012, FALSE, EInternal());return TRUE;}BOOL CSummoner::H0x015b0012_Fire_14(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0012 + +#line 944 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Return(STATE_CURRENT,EReturn ()); +#line 944 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSummoner:: +#line 947 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSummoner_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSummoner::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 948 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Jump(STATE_CURRENT, STATE_CSummoner_Fire, TRUE, EVoid());return TRUE; +#line 949 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Return(STATE_CURRENT,EReturn ()); +#line 949 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSummoner:: +#line 956 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Die(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSummoner_Die + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EDeath, "CSummoner::Die expects 'EDeath' as input!"); const EDeath &eDeath = (const EDeath &)__eeInput; +#line 959 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bDying = TRUE ; +#line 961 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_penDeathInflictor = eDeath . eLastDamage . penInflictor ; +#line 964 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_penKiller = m_penDeathInflictor ; +#line 965 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_penKiller == NULL || ! IsOfClass (m_penKiller , "Player")){ +#line 966 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_penKiller = m_penEnemy ; +#line 967 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 969 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_penKiller == NULL || ! IsOfClass (m_penKiller , "Player")){ +#line 970 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_penKiller = FixupCausedToPlayer (this , m_penKiller , FALSE ); +#line 971 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 974 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetDesiredRotation (ANGLE3D (0.0f , 0.0f , 0.0f)); +#line 976 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +KillAllEnemiesInArea (eDeath ); +#line 978 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_CHANTING , SOF_SMOOTHCHANGE ); +#line 979 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soExplosion , SOUND_LASTWORDS , SOF_3D ); +#line 980 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(4.0f); +Jump(STATE_CURRENT, 0x015b0015, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0015_Die_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0016, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0016_Die_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0016 +; +#line 982 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +STATE_CSummoner_TeleportToDeathMarker, TRUE; +Jump(STATE_CURRENT, 0x015b0017, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0017_Die_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0017 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CSummoner_TeleportToDeathMarker, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x015b0018, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0018_Die_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0018 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 985 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +EDeath eDeath ; +#line 986 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eDeath . eLastDamage . penInflictor = m_penDeathInflictor ; +#line 987 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +KillAllEnemiesInArea (eDeath ); +#line 990 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ShakeItBaby (_pTimer -> CurrentTick () , 0.25f , TRUE ); +#line 991 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soExplosion , SOUND_TREMORS , SOF_3D ); +#line 993 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_vDeathPosition = GetPlacement () . pl_PositionVector ; +#line 996 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_penBeginDeathTarget != NULL ){ +#line 997 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SendToTarget (m_penBeginDeathTarget , EET_TRIGGER , m_penKiller ); +#line 998 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1000 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 1001 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_DEATHBLOW , SOF_SMOOTHCHANGE ); +#line 1002 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (SUMMONER_ANIM_DEATHBLOW ) - 0.25f); +Jump(STATE_CURRENT, 0x015b0019, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0019_Die_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0019 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b001a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b001a_Die_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b001a +; +#line 1005 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SwitchToEditorModel (); +#line 1008 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CPlacement3D plStars ; +#line 1009 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +plStars = GetPlacement (); +#line 1010 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ESpawnEffect eSpawnEffect ; +#line 1011 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eSpawnEffect . betType = BET_SUMMONERSTAREXPLOSION ; +#line 1012 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1013 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer penStars = CreateEntity (plStars , CLASS_BASIC_EFFECT ); +#line 1014 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penStars -> Initialize (eSpawnEffect ); +#line 1016 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_tmDeathBegin = _pTimer -> CurrentTick (); +#line 1017 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fDeathDuration = 12.0f; +#line 1018 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bExploded = TRUE ; +#line 1019 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ShakeItBaby (_pTimer -> CurrentTick () , 5.0f , FALSE ); +#line 1021 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soExplosion , SOUND_EXPLODE , SOF_3D ); +#line 1024 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Debris_Begin (EIBT_FLESH , DPT_BLOODTRAIL , BET_BLOODSTAIN , 1.0f , +#line 1025 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D (0.0f , 10.0f , 0.0f) , FLOAT3D (0.0f , 0.0f , 0.0f) , 5.0f , 2.0f); +#line 1026 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(INDEX i = 0;i < 15;i ++){ +#line 1028 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vSpeed = FLOAT3D (0.3f + FRnd () * 0.1f , 1.0f + FRnd () * 0.5f , 0.3f + FRnd () * 0.1f) * 1.5f * m_fStretch ; +#line 1029 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vPos = vSpeed + GetPlacement () . pl_PositionVector ; +#line 1030 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ANGLE3D aAng = ANGLE3D (FRnd () * 360.0f , FRnd () * 360.0f , FRnd () * 360.0f); +#line 1032 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vSpeed . Normalize (); +#line 1033 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vSpeed (2) *= vSpeed (2); +#line 1035 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CPlacement3D plPos = CPlacement3D (vPos , aAng ); +#line 1037 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +switch(i % 3){ +#line 1038 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +case 0: +#line 1039 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Debris_Spawn_Independent (this , this , MODEL_DEBRIS01 , TEXTURE_SUMMONER , 0 , 0 , 0 , 0 , m_fStretch , +#line 1040 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +plPos , vSpeed * 70.0f , aAng ); +#line 1041 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Debris_Spawn_Independent (this , this , MODEL_DEBRIS_FLESH , TEXTURE_DEBRIS_FLESH , 0 , 0 , 0 , 0 , m_fStretch * 0.33f , +#line 1042 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +plPos , vSpeed * 70.0f , aAng ); +#line 1043 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +break ; +#line 1044 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +case 1: +#line 1045 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Debris_Spawn_Independent (this , this , MODEL_DEBRIS02 , TEXTURE_SUMMONER , 0 , 0 , 0 , 0 , m_fStretch , +#line 1046 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +plPos , vSpeed * 70.0f , aAng ); +#line 1047 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Debris_Spawn_Independent (this , this , MODEL_DEBRIS_FLESH , TEXTURE_DEBRIS_FLESH , 0 , 0 , 0 , 0 , m_fStretch * 0.33f , +#line 1048 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +plPos , vSpeed * 70.0f , aAng ); +#line 1049 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +break ; +#line 1050 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +case 2: +#line 1051 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Debris_Spawn_Independent (this , this , MODEL_DEBRIS03 , TEXTURE_SUMMONER , 0 , 0 , 0 , 0 , m_fStretch , +#line 1052 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +plPos , vSpeed * 70.0f , aAng ); +#line 1053 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Debris_Spawn_Independent (this , this , MODEL_DEBRIS_FLESH , TEXTURE_DEBRIS_FLESH , 0 , 0 , 0 , 0 , m_fStretch * 0.33f , +#line 1054 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +plPos , vSpeed * 70.0f , aAng ); +#line 1055 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +break ; +#line 1056 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1057 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1060 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_penExplodeDeathTarget != NULL ){ +#line 1061 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SendToTarget (m_penExplodeDeathTarget , EET_TRIGGER , m_penKiller ); +#line 1062 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1068 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soSound , SOUND_CHIMES , SOF_3D ); +#line 1070 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iIndex = 20; +#line 1071 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Jump(STATE_CURRENT,0x015b001d, FALSE, EInternal());return TRUE;}BOOL CSummoner::H0x015b001d_Die_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b001d +if(!((m_iIndex --) > 1)){ Jump(STATE_CURRENT,0x015b001e, FALSE, EInternal());return TRUE;} +#line 1072 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CPlacement3D plExplosion ; +#line 1073 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +plExplosion . pl_OrientationAngle = ANGLE3D (0.0f , 0.0f , 0.0f); +#line 1074 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +plExplosion . pl_PositionVector = FLOAT3D (0.3f + FRnd () * 0.1f , 1.0f + FRnd () * 0.5f , 0.3f + FRnd () * 0.1f) * m_fStretch ; +#line 1075 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +plExplosion . pl_PositionVector += GetPlacement () . pl_PositionVector ; +#line 1076 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ESpawnEffect eSpawnEffect ; +#line 1077 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eSpawnEffect . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 1078 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eSpawnEffect . betType = BET_CANNON ; +#line 1079 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fSize = (m_fStretch * m_iIndex ) * 0.333f; +#line 1080 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eSpawnEffect . vStretch = FLOAT3D (fSize , fSize , fSize ); +#line 1081 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer penExplosion = CreateEntity (plExplosion , CLASS_BASIC_EFFECT ); +#line 1082 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penExplosion -> Initialize (eSpawnEffect ); +#line 1084 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ShakeItBaby (_pTimer -> CurrentTick () , m_iIndex / 4.0f , FALSE ); +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(0.05f + FRnd () * 0.2f); +Jump(STATE_CURRENT, 0x015b001b, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b001b_Die_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b001b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b001c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b001c_Die_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b001c +;Jump(STATE_CURRENT,0x015b001d, FALSE, EInternal());return TRUE; +#line 1087 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}BOOL CSummoner::H0x015b001e_Die_10(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b001e + +#line 1089 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(m_fDeathDuration ); +Jump(STATE_CURRENT, 0x015b001f, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b001f_Die_11(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b001f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0020, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0020_Die_12(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0020 +; +#line 1092 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_penEndDeathTarget != NULL ){ +#line 1093 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SendToTarget (m_penEndDeathTarget , EET_TRIGGER , m_penKiller ); +#line 1094 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1096 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +EDeath eDeath ; +#line 1097 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +eDeath . eLastDamage . penInflictor = m_penDeathInflictor ; +#line 1098 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_Die, FALSE, eDeath );return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSummoner:: +#line 1101 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +TeleportToDeathMarker(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSummoner_TeleportToDeathMarker + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSummoner::TeleportToDeathMarker expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1104 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bInvulnerable = TRUE ; +#line 1106 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_VANISHING , SOF_SMOOTHCHANGE ); +#line 1107 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (SUMMONER_ANIM_VANISHING )); +Jump(STATE_CURRENT, 0x015b0022, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0022_TeleportToDeathMarker_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0022 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0023, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0023_TeleportToDeathMarker_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0023 +; +#line 1110 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +DisappearEffect (); +#line 1111 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SwitchToEditorModel (); +#line 1112 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 1115 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer penFlame = GetChildOfClass ("Flame"); +#line 1116 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(penFlame != NULL ){ +#line 1117 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penFlame -> Destroy (); +#line 1118 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1121 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(2.0f); +Jump(STATE_CURRENT, 0x015b0024, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0024_TeleportToDeathMarker_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0024 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0025, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0025_TeleportToDeathMarker_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0025 +; +#line 1123 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CPlacement3D pl ; +#line 1124 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pl . pl_PositionVector = m_penDeathMarker -> GetPlacement () . pl_PositionVector ; +#line 1125 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vToPlayer ; +#line 1126 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_penEnemy != NULL ){ +#line 1127 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vToPlayer = m_penEnemy -> GetPlacement () . pl_PositionVector - pl . pl_PositionVector ; +#line 1128 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else { +#line 1129 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vToPlayer = m_vPlayerSpotted - pl . pl_PositionVector ; +#line 1130 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1131 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vToPlayer . Normalize (); +#line 1132 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +DirectionVectorToAngles (vToPlayer , pl . pl_OrientationAngle ); +#line 1133 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Teleport (pl ); +#line 1136 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SpawnTeleportEffect (); +#line 1138 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(0.5f); +Jump(STATE_CURRENT, 0x015b0026, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0026_TeleportToDeathMarker_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0026 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0027, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0027_TeleportToDeathMarker_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0027 +; +#line 1139 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SwitchToModel (); +#line 1140 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetCollisionFlags (ECF_MODEL ); +#line 1142 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bInvulnerable = FALSE ; +#line 1144 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_APPEARING , SOF_SMOOTHCHANGE ); +#line 1145 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (SUMMONER_ANIM_APPEARING )); +Jump(STATE_CURRENT, 0x015b0028, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0028_TeleportToDeathMarker_07(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0028 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0029, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0029_TeleportToDeathMarker_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0029 +; +#line 1147 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Return(STATE_CURRENT,EReturn ()); +#line 1147 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSummoner:: +#line 1150 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +BossAppear(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSummoner_BossAppear + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSummoner::BossAppear expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1152 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Return(STATE_CURRENT,EReturn ()); +#line 1152 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSummoner:: +#line 1156 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PreMainLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSummoner_PreMainLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSummoner::PreMainLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1158 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +STATE_CSummoner_BossAppear, TRUE; +Jump(STATE_CURRENT, 0x015b002c, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b002c_PreMainLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b002c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CSummoner_BossAppear, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x015b002d, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b002d_PreMainLoop_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b002d +const EReturn&__e= (EReturn&)__eeInput; +; +#line 1159 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Return(STATE_CURRENT,EReturn ()); +#line 1159 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSummoner:: +#line 1162 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Immaterial(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSummoner_Immaterial + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSummoner::Immaterial expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1165 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +DisappearEffect (); +#line 1166 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SwitchToEditorModel (); +#line 1167 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 1170 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer penFlame = GetChildOfClass ("Flame"); +#line 1171 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(penFlame != NULL ){ +#line 1172 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +penFlame -> Destroy (); +#line 1173 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1176 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(m_fImmaterialDuration + FRnd () * 2.0f - 1.0f); +Jump(STATE_CURRENT, 0x015b002f, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b002f_Immaterial_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b002f +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0030, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0030_Immaterial_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0030 +; +#line 1178 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iMaxTries = 10; +#line 1179 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vTarget ; +#line 1181 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +do{ +#line 1182 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CSummonerMarker * marker = & ((CSummonerMarker &) * m_penTeleportMarker ); +#line 1183 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX iMarker = IRnd () % m_iTeleportMarkers ; +#line 1184 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +while(iMarker > 0){ +#line 1185 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +marker = & ((CSummonerMarker &) * marker -> m_penTarget ); +#line 1186 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +iMarker --; +#line 1187 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1188 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vTarget = marker -> GetPlacement () . pl_PositionVector ; +#line 1189 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fR = FRnd () * marker -> m_fMarkerRange ; +#line 1190 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fA = FRnd () * 360.0f; +#line 1191 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vTarget += FLOAT3D (CosFast (fA ) * fR , 0.05f , SinFast (fA ) * fR ); +#line 1192 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}while(! DistanceToAllPlayersGreaterThen (1.0f) || (iMaxTries --) < 1); +#line 1194 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CPlacement3D pl ; +#line 1195 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pl . pl_PositionVector = vTarget ; +#line 1196 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D vToPlayer ; +#line 1197 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(m_penEnemy != NULL ){ +#line 1198 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vToPlayer = m_penEnemy -> GetPlacement () . pl_PositionVector - vTarget ; +#line 1199 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else { +#line 1200 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vToPlayer = m_vPlayerSpotted - vTarget ; +#line 1201 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1202 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +vToPlayer . Normalize (); +#line 1203 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +DirectionVectorToAngles (vToPlayer , pl . pl_OrientationAngle ); +#line 1204 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Teleport (pl ); +#line 1207 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SpawnTeleportEffect (); +#line 1208 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SwitchToModel (); +#line 1209 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetCollisionFlags (ECF_MODEL ); +#line 1211 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bShouldTeleport = FALSE ; +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_tmMaterializationTime = _pTimer -> CurrentTick (); +#line 1213 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bFiredThisTurn = FALSE ; +#line 1215 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bInvulnerable = FALSE ; +#line 1217 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soTeleport , SOUND_MATERIALIZE , SOF_3D ); +#line 1219 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_APPEARING , SOF_SMOOTHCHANGE ); +#line 1220 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (SUMMONER_ANIM_APPEARING )); +Jump(STATE_CURRENT, 0x015b0031, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0031_Immaterial_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0031 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0032, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0032_Immaterial_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0032 +; +#line 1222 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SendEvent (EBegin ()); +#line 1223 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Return(STATE_CURRENT,EReturn ()); +#line 1223 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSummoner:: +#line 1227 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SummonerLoop(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSummoner_SummonerLoop + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSummoner::SummonerLoop expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1229 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SpawnReminder (this , 1.0f , 128); +#line 1230 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x015b0034, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0034_SummonerLoop_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0034 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin): +#line 1232 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{const EBegin&e= (EBegin&)__eeInput; + +#line 1233 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Call(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; +#line 1234 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReminder): +#line 1236 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{const EReminder&er= (EReminder&)__eeInput; + +#line 1238 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(er . iValue == 128){ +#line 1239 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +RecalculateFuss (); +#line 1241 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(_pTimer -> CurrentTick () > m_tmMaterializationTime + m_fCorporealDuration ){ +#line 1242 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bShouldTeleport = TRUE ; +#line 1243 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1245 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SpawnReminder (this , 1.0f , 128); +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else if(er . iValue == 129 && ! m_bDying ){ +#line 1247 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Call(STATE_CURRENT, STATE_CSummoner_InitiateTeleport, TRUE, EVoid());return TRUE; +#line 1248 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}else if(TRUE ){ +#line 1249 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return FALSE; +#line 1250 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1251 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE; +#line 1252 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}ASSERT(FALSE);break;case(EVENTCODE_ESummonerTeleport): +#line 1255 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{const ESummonerTeleport&est= (ESummonerTeleport&)__eeInput; + +#line 1257 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SpawnReminder (this , est . fWait , 129); +#line 1258 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE; +#line 1259 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}ASSERT(FALSE);break;default:{ +#line 1261 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE; +#line 1262 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}ASSERT(FALSE);break; +#line 1263 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}return TRUE;}BOOL CSummoner::H0x015b0035_SummonerLoop_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0035 + ASSERT(FALSE); return TRUE;};BOOL CSummoner:: +#line 1269 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSummoner_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSummoner::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 1272 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +InitAsEditorModel (); +#line 1274 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 1275 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 1276 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 1278 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +en_fDensity = 10000.0f; +#line 1279 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fDamageWounded = 1e6f; +#line 1281 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_sptType = SPT_BLOOD ; +#line 1282 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bBoss = TRUE ; +#line 1283 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetHealth (SUMMONER_HEALTH ); +#line 1284 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fMaxHealth = SUMMONER_HEALTH ; +#line 1285 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fBodyParts = 0; +#line 1287 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fWalkSpeed = 0.0f; +#line 1288 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_aWalkRotateSpeed = AngleDeg (270.0f); +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fAttackRunSpeed = 0.0f; +#line 1290 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_aAttackRotateSpeed = AngleDeg (270.0f); +#line 1291 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fCloseRunSpeed = 0.0f; +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_aCloseRotateSpeed = AngleDeg (270.0f); +#line 1294 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fAttackDistance = 500.0f; +#line 1295 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fCloseDistance = 50.0f; +#line 1296 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fStopDistance = 500.0f; +#line 1297 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fIgnoreRange = 600.0f; +#line 1298 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iScore = 1000000; +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fAttackFireTime = m_fFirePeriod ; +#line 1301 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fCloseFireTime = m_fFirePeriod ; +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 1304 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StandingAnim (); +#line 1308 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetComponents (this , * GetModelObject () , MODEL_SUMMONER , TEXTURE_SUMMONER , 0 , 0 , 0); +#line 1309 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +AddAttachmentToModel (this , * GetModelObject () , SUMMONER_ATTACHMENT_STAFF , MODEL_STAFF , TEXTURE_STAFF , 0 , 0 , 0); +#line 1310 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fStretch , m_fStretch , m_fStretch )); +#line 1311 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +ModelChangeNotify (); +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +AddToMovers (); +#line 1315 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x015b0036, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0036_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0036 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b0037, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b0037_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0037 +; +#line 1317 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_emEmiter . Initialize (this ); +#line 1318 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_emEmiter . em_etType = ET_SUMMONER_STAFF ; +#line 1321 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +INDEX i ; +#line 1322 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEntityPointer * pen ; +#line 1323 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iGroup01Count = 0; +#line 1324 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pen = & m_penGroup01Template01 ; +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(i = 0;i < SUMMONER_TEMP_PER_GROUP ;i ++){ +#line 1326 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(& * pen [ i ] != NULL ){m_iGroup01Count ++;} +#line 1327 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1328 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iGroup02Count = 0; +#line 1329 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pen = & m_penGroup02Template01 ; +#line 1330 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(i = 0;i < SUMMONER_TEMP_PER_GROUP ;i ++){ +#line 1331 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(& * pen [ i ] != NULL ){m_iGroup02Count ++;} +#line 1332 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1333 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iGroup03Count = 0; +#line 1334 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +pen = & m_penGroup03Template01 ; +#line 1335 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +for(i = 0;i < SUMMONER_TEMP_PER_GROUP ;i ++){ +#line 1336 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(& * pen [ i ] != NULL ){m_iGroup03Count ++;} +#line 1337 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1339 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +if(! DoSafetyChecks ()){ +#line 1340 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Destroy (); +#line 1341 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Return(STATE_CURRENT,EVoid()); +#line 1341 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +return TRUE; +#line 1342 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1345 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEnemyMarker * it ; +#line 1346 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iSpawnMarkers = 1; +#line 1347 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +it = & ((CEnemyMarker &) * m_penSpawnMarker ); +#line 1348 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +while(it -> m_penTarget != NULL ) +#line 1349 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +it = & ((CEnemyMarker &) * it -> m_penTarget ); +#line 1351 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iSpawnMarkers ++; +#line 1352 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1355 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iTeleportMarkers = 1; +#line 1356 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +it = & ((CEnemyMarker &) * m_penTeleportMarker ); +#line 1357 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +while(it -> m_penTarget != NULL ) +#line 1358 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +{ +#line 1359 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +it = & ((CEnemyMarker &) * it -> m_penTarget ); +#line 1360 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iTeleportMarkers ++; +#line 1361 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +} +#line 1363 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iSpawnScheme = 0; +#line 1364 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fMaxCurrentFuss = m_fMaxBeginFuss ; +#line 1365 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bDying = FALSE ; +#line 1366 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_tmDeathBegin = 0.0f; +#line 1367 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_fDeathDuration = 0.0f; +#line 1368 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bInvulnerable = TRUE ; +#line 1369 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bExploded = FALSE ; +#line 1372 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x015b0038, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b0038_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0038 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x015b0039, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 1376 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +}return TRUE;}BOOL CSummoner::H0x015b0039_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b0039 + +#line 1378 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_soExplosion . Set3DParameters (1500.0f , 1000.0f , 2.0f , 1.0f); +#line 1379 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_soSound . Set3DParameters (1500.0f , 1000.0f , 2.0f , 1.0f); +#line 1380 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_soChant . Set3DParameters (1500.0f , 1000.0f , 2.0f , 1.0f); +#line 1381 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_soTeleport . Set3DParameters (1500.0f , 1000.0f , 3.0f , 1.0f); +#line 1382 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_iTaunt = 0; +#line 1386 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SpawnTeleportEffect (); +#line 1387 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SwitchToModel (); +#line 1388 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_bInvulnerable = FALSE ; +#line 1389 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetCollisionFlags (ECF_MODEL ); +#line 1391 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PlaySound (m_soTeleport , SOUND_MATERIALIZE , SOF_3D ); +#line 1393 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +StartModelAnim (SUMMONER_ANIM_APPEARING , SOF_SMOOTHCHANGE ); +#line 1394 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (SUMMONER_ANIM_APPEARING )); +Jump(STATE_CURRENT, 0x015b003a, FALSE, EBegin());return TRUE;}BOOL CSummoner::H0x015b003a_Main_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b003a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x015b003b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CSummoner::H0x015b003b_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x015b003b +; +#line 1396 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +m_tmMaterializationTime = _pTimer -> CurrentTick (); +#line 1399 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Jump(STATE_CURRENT, STATE_CSummoner_SummonerLoop, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Summoner.es b/Sources/EntitiesMP/Summoner.es new file mode 100644 index 0000000..5273e76 --- /dev/null +++ b/Sources/EntitiesMP/Summoner.es @@ -0,0 +1,1402 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +347 +%{ +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "ModelsMP/Enemies/Summoner/Summoner.h" +#include "ModelsMP/Enemies/Summoner/Staff.h" +#include "EntitiesMP/Effector.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/SpawnerProjectile"; +uses "EntitiesMP/AreaMarker"; +uses "EntitiesMP/SummonerMarker"; +uses "EntitiesMP/Player"; + +event ESummonerTeleport { + FLOAT fWait, +}; + +%{ +#define RAND_05 (FLOAT(rand())/RAND_MAX-0.5f) +#define SUMMONER_SIZE 7.0f +#define TM_WAIT_BEFORE_FIRE 1.9f +#define SUMMONER_HEALTH 15000.0f +// info structure +static EntityInfo eiSummoner = { + EIBT_FLESH, 1500.0f, + 0.0f, 1.7f*SUMMONER_SIZE, 0.0f, + 0.0f, 1.0f*SUMMONER_SIZE, 0.0f, +}; + +//#define FIREPOS_ARMS FLOAT3D(-0.22f, 1.63f, 0.96f) +#define FIREPOS_ARMS FLOAT3D(0.131292f, 1.61069f, -0.314068f) + +#define SUMMONER_MAX_SS 6 + // hlth grp1 grp2 grp3 +INDEX aiSpawnScheme[SUMMONER_MAX_SS][7] = {100, 4,7, 0,0, 0,0, + 90, 3,5, 2,4, 0,0, + 70, 3,4, 3,4, 0,0, + 50, 1,3, 3,5, 1,1, + 30, 1,2, 2,3, 2,2, + 15, 1,1, 2,4, 2,3 }; +#define SUMMONER_TEMP_PER_GROUP 6 +%} + + +class CSummoner : CEnemyBase { +name "Summoner"; +thumbnail "Thumbnails\\Summoner.tbn"; + +properties: + + 1 BOOL m_bInvulnerable = FALSE, // can we be hurt? + 2 CEntityPointer m_penBeginDeathTarget "Sum. Begin Death Target", + 3 CEntityPointer m_penEndDeathTarget "Sum. End Death Target", + 4 CEntityPointer m_penExplodeDeathTarget "Sum. Explode Target", + 5 BOOL m_bShouldTeleport = FALSE, // are we allowed to teleport? + 6 FLOAT m_fFirePeriod = 3.0f, + 7 FLOAT m_fImmaterialDuration "Sum. Immaterial Duration" = 5.0f, // how long to stay immaterial + 8 FLOAT m_fCorporealDuration "Sum. Corporeal Duration" = 5.0f, // how long to stay material + 9 FLOAT m_tmMaterializationTime = 0.0f, // when we materialized + + 10 FLOAT m_fStretch "Sum. Stretch" = SUMMONER_SIZE, + 11 INDEX m_iSize = 1, // how big it is (gets bigger when harmed) + 12 CEntityPointer m_penControlArea "Sum. Control Area", + + // NOTE: if number of templates per group changes, you MUST change the + // SUMMONER_TEMP_PER_GROUP #definition at the beginning of the file + 20 INDEX m_iGroup01Count = 0, + 21 CEntityPointer m_penGroup01Template01 "Sum. Group01 Template01", + 22 CEntityPointer m_penGroup01Template02 "Sum. Group01 Template02", + 23 CEntityPointer m_penGroup01Template03 "Sum. Group01 Template03", + 24 CEntityPointer m_penGroup01Template04 "Sum. Group01 Template04", + 25 CEntityPointer m_penGroup01Template05 "Sum. Group01 Template05", + 26 CEntityPointer m_penGroup01Template06 "Sum. Group01 Template06", + + 30 INDEX m_iGroup02Count = 0, + 31 CEntityPointer m_penGroup02Template01 "Sum. Group02 Template01", + 32 CEntityPointer m_penGroup02Template02 "Sum. Group02 Template02", + 33 CEntityPointer m_penGroup02Template03 "Sum. Group02 Template03", + 34 CEntityPointer m_penGroup02Template04 "Sum. Group02 Template04", + 35 CEntityPointer m_penGroup02Template05 "Sum. Group02 Template05", + 36 CEntityPointer m_penGroup02Template06 "Sum. Group02 Template06", + + 40 INDEX m_iGroup03Count = 0, + 41 CEntityPointer m_penGroup03Template01 "Sum. Group03 Template01", + 42 CEntityPointer m_penGroup03Template02 "Sum. Group03 Template02", + 43 CEntityPointer m_penGroup03Template03 "Sum. Group03 Template03", + 44 CEntityPointer m_penGroup03Template04 "Sum. Group03 Template04", + 45 CEntityPointer m_penGroup03Template05 "Sum. Group03 Template05", + 46 CEntityPointer m_penGroup03Template06 "Sum. Group03 Template06", + + 60 CEntityPointer m_penTeleportMarker "Sum. Teleport marker", + 61 INDEX m_iTeleportMarkers = 0, // number of teleport markers + 65 CEntityPointer m_penSpawnMarker "Sum. Enemy spawn marker", + 66 INDEX m_iSpawnMarkers = 0, // number of spawn markers + 67 FLOAT m_fTeleportWaitTime = 0.0f, // internal + + 70 FLOAT m_fFuss = 0.0f, // value of all enemies scores summed up + 78 INDEX m_iEnemyCount = 0, // how many enemies in the area + 71 FLOAT m_fMaxCurrentFuss = 0.0f, + 72 FLOAT m_fMaxBeginFuss "Sum. Max Begin Fuss" = 10000.0f, + 73 FLOAT m_fMaxEndFuss "Sum. Max End Fuss" = 60000.0f, + 75 INDEX m_iSpawnScheme = 0, + 76 BOOL m_bFireOK = TRUE, + 79 BOOL m_bFiredThisTurn = FALSE, + 77 FLOAT m_fDamageSinceLastSpawn = 0.0f, + + 88 BOOL m_bExploded = FALSE, // still alive and embodied + 90 BOOL m_bDying = FALSE, // set when dying + 92 FLOAT m_tmDeathBegin = 0.0f, + 93 FLOAT m_fDeathDuration = 0.0f, + 94 CEntityPointer m_penDeathInflictor, + 111 CEntityPointer m_penKiller, + // internal variables + 95 FLOAT3D m_vDeathPosition = FLOAT3D(0.0f, 0.0f, 0.0f), + 96 CEntityPointer m_penDeathMarker "Sum. Death marker", + 100 INDEX m_iIndex = 0, // temp. index + + 102 INDEX m_iTaunt = 0, // index of currently active taunt + + 110 FLOAT m_tmParticlesDisappearStart=-1e6, + + 120 FLOAT m_tmLastAnimation=0.0f, + + 150 CSoundObject m_soExplosion, + 151 CSoundObject m_soSound, + 152 CSoundObject m_soChant, + 153 CSoundObject m_soTeleport, + +{ + CEmiter m_emEmiter; +} + +components: + 0 class CLASS_BASE "Classes\\EnemyBase.ecl", + 1 class CLASS_BLOOD_SPRAY "Classes\\BloodSpray.ecl", + 2 class CLASS_SPAWNER_PROJECTILE "Classes\\SpawnerProjectile.ecl", + 3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + 4 class CLASS_EFFECTOR "Classes\\Effector.ecl", + +// ************** MAIN MODEL ************** + + 10 model MODEL_SUMMONER "ModelsMP\\Enemies\\Summoner\\Summoner.mdl", + 11 texture TEXTURE_SUMMONER "ModelsMP\\Enemies\\Summoner\\Summoner.tex", + 12 model MODEL_STAFF "ModelsMP\\Enemies\\Summoner\\Staff.mdl", + 13 texture TEXTURE_STAFF "ModelsMP\\Enemies\\Summoner\\Staff.tex", + + 16 model MODEL_DEBRIS01 "ModelsMP\\Enemies\\Summoner\\Debris\\Cloth01.mdl", + 17 model MODEL_DEBRIS02 "ModelsMP\\Enemies\\Summoner\\Debris\\Cloth02.mdl", + 18 model MODEL_DEBRIS03 "ModelsMP\\Enemies\\Summoner\\Debris\\Cloth03.mdl", + 19 model MODEL_DEBRIS_FLESH "Models\\Effects\\Debris\\Flesh\\Flesh.mdl", + 20 texture TEXTURE_DEBRIS_FLESH "Models\\Effects\\Debris\\Flesh\\FleshRed.tex", + + +// ************** SOUNDS ************** +//200 sound SOUND_IDLE "ModelsMP\\Enemies\\Summoner\\Sounds\\Idle.wav", +101 sound SOUND_LAUGH "ModelsMP\\Enemies\\Summoner\\Sounds\\Laugh.wav", +102 sound SOUND_EXPLODE "ModelsMP\\Enemies\\Summoner\\Sounds\\Explode.wav", +103 sound SOUND_TREMORS "ModelsMP\\Enemies\\Summoner\\Sounds\\Tremors.wav", +104 sound SOUND_DEATH "ModelsMP\\Enemies\\Summoner\\Sounds\\Death.wav", +105 sound SOUND_LASTWORDS "ModelsMP\\Enemies\\Summoner\\Sounds\\LastWords.wav", +106 sound SOUND_FIRE "ModelsMP\\Enemies\\Summoner\\Sounds\\Fire.wav", +108 sound SOUND_CHIMES "ModelsMP\\Enemies\\Summoner\\Sounds\\Chimes.wav", +107 sound SOUND_MATERIALIZE "ModelsMP\\Enemies\\Summoner\\Sounds\\Materialize.wav", +109 sound SOUND_TELEPORT "ModelsMP\\Enemies\\Summoner\\Sounds\\Teleport.wav", + +// ***** TAUNTS ****** +150 sound SOUND_TAUNT01 "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote03.wav", +151 sound SOUND_TAUNT02 "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote05.wav", +152 sound SOUND_TAUNT03 "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote07.wav", +153 sound SOUND_TAUNT04 "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote08.wav", +154 sound SOUND_TAUNT05 "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote10.wav", +155 sound SOUND_TAUNT06 "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote11.wav", +156 sound SOUND_TAUNT07 "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote14.wav", +157 sound SOUND_TAUNT08 "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote15.wav", +158 sound SOUND_TAUNTLAST "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote16.wav", + +functions: + void Read_t( CTStream *istr) // throw char * + { + CEnemyBase::Read_t(istr); + m_emEmiter.Read_t(*istr); + } + + void Write_t( CTStream *istr) // throw char * + { + CEnemyBase::Write_t(istr); + m_emEmiter.Write_t(*istr); + } + + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if ( slPropertyOffset >= offsetof(CSummoner, m_penGroup01Template01) && + slPropertyOffset <= offsetof(CSummoner, m_penGroup03Template06)) + { + if (IsDerivedFromClass(penTarget, "Enemy Base")) { + if (((CEnemyBase &)*penTarget).m_bTemplate) { + return TRUE; + } else { + return FALSE; + } + } else { + return FALSE; + } + } + if( slPropertyOffset == offsetof(CSummoner, m_penControlArea)) + { + if (IsDerivedFromClass(penTarget, "AreaMarker")) { + return TRUE; + } else { + return FALSE; + } + } + if( slPropertyOffset == offsetof(CSummoner, m_penSpawnMarker)) + { + if (IsDerivedFromClass(penTarget, "Enemy Marker")) { + return TRUE; + } else { + return FALSE; + } + } + if( slPropertyOffset == offsetof(CSummoner, m_penTeleportMarker) || + slPropertyOffset == offsetof(CSummoner, m_penDeathMarker)) + { + if (IsDerivedFromClass(penTarget, "SummonerMarker")) { + return TRUE; + } else { + return FALSE; + } + } + return CEntity::IsTargetValid(slPropertyOffset, penTarget); + } + + + BOOL DoSafetyChecks(void) { + + if (m_penSpawnMarker==NULL) { + WarningMessage( "No valid Spawn Marker for Summoner boss! Destroying boss..."); + return FALSE; + } + if (m_penTeleportMarker==NULL) { + WarningMessage( "No valid Teleport Marker for Summoner boss! Destroying boss..."); + return FALSE; + } + if (m_penDeathMarker==NULL) { + WarningMessage( "No valid Death Marker for Summoner boss! Destroying boss..."); + return FALSE; + } + if (m_penControlArea==NULL) { + WarningMessage( "No valid Area Marker for Summoner boss! Destroying boss..."); + return FALSE; + } + if (m_iGroup01Count<1 || m_iGroup02Count<1 || m_iGroup03Count<1) + { + WarningMessage( "At least one template in each group required! Destroying boss..."); + return FALSE; + } + return TRUE; + } + + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("The Summoner unsummoned %s"), strPlayerName); + return str; + } + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnm, "DataMP\\Messages\\Enemies\\Summoner.txt"); + return fnm; + }; + + void Precache(void) + { + CEnemyBase::Precache(); + + PrecacheClass(CLASS_BLOOD_SPRAY ); + PrecacheClass(CLASS_SPAWNER_PROJECTILE ); + + PrecacheClass(CLASS_BASIC_EFFECT, BET_CANNON ); + + PrecacheModel(MODEL_SUMMONER ); + PrecacheModel(MODEL_STAFF ); + PrecacheTexture(TEXTURE_SUMMONER ); + PrecacheTexture(TEXTURE_STAFF ); + + PrecacheModel(MODEL_DEBRIS01 ); + PrecacheModel(MODEL_DEBRIS02 ); + PrecacheModel(MODEL_DEBRIS03 ); + PrecacheModel(MODEL_DEBRIS_FLESH ); + PrecacheTexture(TEXTURE_DEBRIS_FLESH ); + + PrecacheSound(SOUND_LAUGH ); + PrecacheSound(SOUND_EXPLODE ); + PrecacheSound(SOUND_TREMORS ); + PrecacheSound(SOUND_DEATH ); + PrecacheSound(SOUND_LASTWORDS ); + PrecacheSound(SOUND_FIRE ); + PrecacheSound(SOUND_CHIMES ); + PrecacheSound(SOUND_MATERIALIZE ); + PrecacheSound(SOUND_TELEPORT ); + + for (INDEX i=SOUND_TAUNT01; i<=SOUND_TAUNTLAST; i++) { + PrecacheSound(i); + } + + }; + + + // Entity info + void *GetEntityInfo(void) { + return &eiSummoner; + }; + + CMusicHolder *GetMusicHolder() + { + CEntity *penMusicHolder; + penMusicHolder = _pNetwork->GetEntityWithName("MusicHolder", 0); + return (CMusicHolder *)&*penMusicHolder; + } + + BOOL DistanceToAllPlayersGreaterThen(FLOAT fDistance) + { + // find actual number of players + INDEX ctMaxPlayers = GetMaxPlayers(); + CEntity *penPlayer; + + for(INDEX i=0; im_tmShakeStarted = tmShaketime; + pwsc->m_vShakePos = GetPlacement().pl_PositionVector; + pwsc->m_fShakeFalloff = 450.0f; + pwsc->m_fShakeFade = 3.0f; + + pwsc->m_fShakeIntensityZ = 0; + pwsc->m_tmShakeFrequencyZ = 5.0f; + pwsc->m_fShakeIntensityY = 0.1f*fPower; + pwsc->m_tmShakeFrequencyY = 5.0f; + pwsc->m_fShakeIntensityB = 2.5f*fPower; + pwsc->m_tmShakeFrequencyB = 7.2f; + + pwsc->m_bShakeFadeIn = bFadeIn; + } + } + + void ChangeEnemyNumberForAllPlayers(INDEX iDelta) + { + // find actual number of players + INDEX ctMaxPlayers = GetMaxPlayers(); + CEntity *penPlayer; + + for(INDEX i=0; ifNewHealth) + { + m_iSpawnScheme = i; + } + } + + // adjust fuss + m_fMaxCurrentFuss = (1.0f-(GetHealth()/m_fMaxHealth))*(m_fMaxEndFuss-m_fMaxBeginFuss)+m_fMaxBeginFuss; + + // bosses don't darken when burning + m_colBurning=COLOR(C_WHITE|CT_OPAQUE); + + }; + + + // damage anim + /*INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim; + iAnim = SUMMONER_ANIM_WOUND; + StartModelAnim(iAnim, 0); + return iAnim; + };*/ + + void StandingAnimFight(void) { + StartModelAnim(SUMMONER_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + + // virtual anim functions + void StandingAnim(void) { + StartModelAnim(SUMMONER_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + + void WalkingAnim(void) { + StartModelAnim(SUMMONER_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + }; + + void RunningAnim(void) { + WalkingAnim(); + }; + + void RotatingAnim(void) { + WalkingAnim(); + }; + + /*INDEX AnimForDeath(void) { + INDEX iAnim; + iAnim = SUMMONER_ANIM_DEATH; + StartModelAnim(iAnim, 0); + return iAnim; + };*/ + + // virtual sound functions + void IdleSound(void) { + //PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + + FLOAT3D AcquireTarget() + { + CEnemyMarker *marker; + marker = &((CEnemyMarker &)*m_penSpawnMarker); + + INDEX iMarker = IRnd()%m_iSpawnMarkers; + + while (iMarker>0) + { + marker = &((CEnemyMarker &)*marker->m_penTarget); + iMarker--; + } + FLOAT3D vTarget = marker->GetPlacement().pl_PositionVector; + FLOAT fR = FRnd()*marker->m_fMarkerRange; + FLOAT fA = FRnd()*360.0f; + vTarget += FLOAT3D(CosFast(fA)*fR, 0.05f, SinFast(fA)*fR); + return vTarget; + }; + + void LaunchMonster(FLOAT3D vTarget, CEntity *penTemplate) + { + ASSERT(penTemplate!=NULL); + // calculate parameters for predicted angular launch curve + FLOAT3D vFirePos = FIREPOS_ARMS*m_fStretch; + FLOAT3D vShooting = GetPlacement().pl_PositionVector + vFirePos*GetRotationMatrix(); + FLOAT fLaunchSpeed; + FLOAT fRelativeHdg; + //FLOAT fPitch = FRnd()*30.0f - 5.0f; + FLOAT fPitch = FRnd()*10.0f + 25.0f; + + CPlacement3D pl; + CalculateAngularLaunchParams( vShooting, 0.0f, vTarget, + FLOAT3D(0.0f, 0.0f, 0.0f), fPitch, fLaunchSpeed, fRelativeHdg); + + PrepareFreeFlyingProjectile(pl, vTarget, vFirePos, ANGLE3D( fRelativeHdg, fPitch, 0.0f)); + + ESpawnerProjectile esp; + CEntityPointer penSProjectile = CreateEntity(pl, CLASS_SPAWNER_PROJECTILE); + esp.penOwner = this; + esp.penTemplate = penTemplate; + penSProjectile->Initialize(esp); + + ((CMovableEntity &)*penSProjectile).LaunchAsFreeProjectile(FLOAT3D(0.0f, 0.0f, -fLaunchSpeed), (CMovableEntity*)(CEntity*)this); + } + + FLOAT FussModifier(INDEX iEnemyCount) { + return (0.995 + 0.005 * pow(m_iEnemyCount , 2.8)); + } + + void RecalculateFuss(void) + { + // get area box + FLOATaabbox3D box; + ((CAreaMarker &)*m_penControlArea).GetAreaBox(box); + + static CStaticStackArray apenNearEntities; + GetWorld()->FindEntitiesNearBox(box, apenNearEntities); + + INDEX m_iEnemyCount = 0; + m_fFuss = 0.0f; + + for (INDEX i=0; iGetFlags()&ENF_ALIVE) { + m_fFuss += ((CEnemyBase &)*apenNearEntities[i]).m_iScore; + m_iEnemyCount ++; + } + } + } + + m_fFuss *= FussModifier(m_iEnemyCount); + + // if too much fuss, make disable firing + if (m_fFuss>m_fMaxCurrentFuss) { +//CPrintF("FIRE DISABLED -> too much fuss\n"); + m_bFireOK = FALSE; + // enable firing only when very little fuss + } else if (m_fFuss<0.4*m_fMaxCurrentFuss) { +//CPrintF("FIRE ENABLE -> fuss more then %f\n", 0.4*m_fMaxCurrentFuss); + m_bFireOK = TRUE; + // but if significant damage since last spawn, enable firing anyway + } else if (m_fDamageSinceLastSpawn>0.07f*m_fMaxHealth) { +//CPrintF("FIRE ENABLED -> much damagesincelastspawn - %f\n", m_fDamageSinceLastSpawn); + m_bFireOK = TRUE; + } + +//CPrintF("Fuss = %f/%f (%d enemies) at %f\n", m_fFuss, m_fMaxCurrentFuss, m_iEnemyCount, _pTimer->CurrentTick()); +//CPrintF("health: %f, scheme: %i\n", GetHealth(), m_iSpawnScheme); + return; + } + + void CountEnemiesAndScoreValue(INDEX& iEnemies, FLOAT& fScore) + { + // get area box + FLOATaabbox3D box; + ((CAreaMarker &)*m_penControlArea).GetAreaBox(box); + + static CStaticStackArray apenNearEntities; + GetWorld()->FindEntitiesNearBox(box, apenNearEntities); + + iEnemies = 0; + fScore = 0.0f; + + for (INDEX i=0; iGetFlags()&ENF_ALIVE) { + fScore += ((CEnemyBase &)*apenNearEntities[i]).m_iScore; + iEnemies ++; + } + } + } + return; + } + + CEnemyBase *GetRandomTemplate (INDEX iGroup) + { + CEntityPointer *pen; + INDEX iCount; + if (iGroup == 0) { + pen = &m_penGroup01Template01; + iCount = IRnd()%m_iGroup01Count+1; + } else if (iGroup == 1) { + pen = &m_penGroup02Template01; + iCount = IRnd()%m_iGroup02Count+1; + } else if (iGroup == 2) { + pen = &m_penGroup03Template01; + iCount = IRnd()%m_iGroup03Count+1; + } else { + ASSERT("Invalid group!"); + } + ASSERT(iCount>0); + + INDEX i=-1; + while (iCount>0) + { + i++; + while (&*pen[i]==NULL) { + i++; + } + iCount--; + } + ASSERT (&(CEnemyBase &)*pen[i]!=NULL); + return &(CEnemyBase &)*pen[i]; + } + + void DisappearEffect(void) + { + CPlacement3D plFX=GetPlacement(); + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.vStretch = FLOAT3D(3,3,3); + ese.vNormal = FLOAT3D(0,1,0); + ese.betType = BET_DUST_FALL; + for( INDEX iSmoke=0; iSmoke<3; iSmoke++) + { + CPlacement3D plSmoke=plFX; + plSmoke.pl_PositionVector+=FLOAT3D(0,iSmoke*4+4.0f,0); + CEntityPointer penFX = CreateEntity(plSmoke, CLASS_BASIC_EFFECT); + penFX->Initialize(ese); + } + + /* + // growing swirl + ese.betType = BET_DISAPPEAR_DUST; + penFX = CreateEntity(plFX, CLASS_BASIC_EFFECT); + penFX->Initialize(ese); + */ + } + + void SpawnTeleportEffect(void) + { + ESpawnEffect ese; + ese.colMuliplier = C_lMAGENTA|CT_OPAQUE; + ese.vStretch = FLOAT3D(5,5,5); + ese.vNormal = FLOAT3D(0,1,0); + + // explosion debris + ese.betType = BET_EXPLOSION_DEBRIS; + CPlacement3D plFX=GetPlacement(); + CEntityPointer penFX = CreateEntity(plFX, CLASS_BASIC_EFFECT); + penFX->Initialize(ese); + ese.colMuliplier = C_MAGENTA|CT_OPAQUE; + CEntityPointer penFX2 = CreateEntity(plFX, CLASS_BASIC_EFFECT); + penFX2->Initialize(ese); + ese.colMuliplier = C_lCYAN|CT_OPAQUE; + CEntityPointer penFX3 = CreateEntity(plFX, CLASS_BASIC_EFFECT); + penFX3->Initialize(ese); + ese.betType = BET_CANNON; + ese.colMuliplier = C_CYAN|CT_OPAQUE; + CEntityPointer penFX4 = CreateEntity(plFX, CLASS_BASIC_EFFECT); + penFX4->Initialize(ese); + + // explosion smoke + /* + ese.betType = BET_EXPLOSION_SMOKE; + penFX = CreateEntity(plFX, CLASS_BASIC_EFFECT); + penFX->Initialize(ese); + */ + + ESpawnEffector eLightning; + eLightning.eetType = ET_LIGHTNING; + eLightning.tmLifeTime = 0.5f; + eLightning.fSize = 24; + eLightning.ctCount = 32; + + CEntity *penLightning = CreateEntity( plFX, CLASS_EFFECTOR); + ANGLE3D angRnd=ANGLE3D( + 0.0f, + 90.0f+(FRnd()-0.5f)*30.0f, + (FRnd()-0.5f)*30.0f); + + FLOAT3D vRndDir; + AnglesToDirectionVector(angRnd, vRndDir); + FLOAT3D vDest=plFX.pl_PositionVector; + vDest+=vRndDir*512.0f; + eLightning.vDestination = vDest; + penLightning->Initialize( eLightning); + } + + void KillAllEnemiesInArea(EDeath eDeath) + { + EDeath eDeath2; + FLOATaabbox3D box; + ((CAreaMarker &)*m_penControlArea).GetAreaBox(box); + + static CStaticStackArray apenNearEntities; + GetWorld()->FindEntitiesNearBox(box, apenNearEntities); + + for (INDEX i=0; iGetFlags()&ENF_ALIVE) { + eDeath2.eLastDamage.penInflictor = eDeath.eLastDamage.penInflictor; + eDeath2.eLastDamage.vDirection = apenNearEntities[i]->GetPlacement().pl_PositionVector; + eDeath2.eLastDamage.vHitPoint = eDeath2.eLastDamage.vDirection; + eDeath2.eLastDamage.fAmount = 10000.0f; + eDeath2.eLastDamage.dmtType = DMT_CLOSERANGE; + apenNearEntities[i]->SendEvent(eDeath); + } + } + + CMusicHolder *penMusicHolder = GetMusicHolder(); + if (IsOfClass(apenNearEntities[i],"SpawnerProjectile")) { + CPlacement3D pl; + pl.pl_OrientationAngle = ANGLE3D(0.0f, 0.0f, 0.0f); + pl.pl_PositionVector = apenNearEntities[i]->GetPlacement().pl_PositionVector; + CEntityPointer penExplosion = CreateEntity(pl, CLASS_BASIC_EFFECT); + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNON; + eSpawnEffect.vStretch = FLOAT3D(2.0f, 2.0f, 2.0f); + penExplosion->Initialize(eSpawnEffect); + apenNearEntities[i]->Destroy(); + // decrease the number of spawned enemies for those that haven't been born + if (penMusicHolder!=NULL) { + penMusicHolder->m_ctEnemiesInWorld--; + } + ChangeEnemyNumberForAllPlayers(-1); + } + } + } + + void RenderParticles(void) + { + FLOAT tmNow = _pTimer->CurrentTick(); + if( tmNow>m_tmParticlesDisappearStart && tmNowm_tmLastAnimation) + { + INDEX ctInterpolations=2; + // if invisible or dead don't add new sparks + if(!m_bInvulnerable && !m_bExploded && GetHealth()>0) + { + for( INDEX iInter=0; iInterTickQuantum/ctInterpolations; + // head + FLOAT fLife=2.5f; + FLOAT fCone=360.0f; + FLOAT fStretch=1.0f; + FLOAT fRotSpeed=360.0f; + COLOR col=C_lYELLOW|CT_OPAQUE; + + MakeRotationMatrixFast(mRot, ANGLE3D(0.0f, 0.0f, 0.0f)); + vPos=FLOAT3D(0.0f, 0.0f, 0.0f); + GetModelObject()->GetAttachmentTransformations(SUMMONER_ATTACHMENT_STAFF, mRot, vPos, FALSE); + // next in hierarchy + CAttachmentModelObject *pamo = GetModelObject()->GetAttachmentModel(SUMMONER_ATTACHMENT_STAFF); + pamo->amo_moModelObject.GetAttachmentTransformations( STAFF_ATTACHMENT_PARTICLES, mRot, vPos, TRUE); + vPos=GetPlacement().pl_PositionVector+vPos*GetRotationMatrix(); + + FLOAT3D vSpeed=FLOAT3D( 0.1f+RAND_05, 0.1f+RAND_05, -1.0f-RAND_05); + vSpeed=vSpeed.Normalize()*8.0f; + m_emEmiter.AddParticle(vPos, vSpeed*mRot*mEn, RAND_05*360.0f, fRotSpeed, tmBirth, fLife, fStretch, col); + } + } + + m_emEmiter.em_vG=m_emEmiter.GetGravity(this); + m_emEmiter.em_vG/=2.0f; + m_emEmiter.AnimateParticles(); + m_tmLastAnimation=tmNow; + } + m_emEmiter.RenderParticles(); + } + + +procedures: + + InitiateTeleport() + { + m_bInvulnerable = TRUE; + StartModelAnim(SUMMONER_ANIM_VANISHING, 0); + + // start disappear particles + FLOAT tmNow = _pTimer->CurrentTick(); + m_tmParticlesDisappearStart=tmNow; + + PlaySound(m_soSound, SOUND_TELEPORT, SOF_3D); + + autowait(GetModelObject()->GetAnimLength(SUMMONER_ANIM_VANISHING)-0.2f); + jump Immaterial(); + } + + Fire(EVoid) : CEnemyBase::Fire { + + // if not allready fired + if (!m_bFiredThisTurn) { + // if not too much fuss, we can really fire + if (m_bFireOK) { + + INDEX iTaunt = SOUND_TAUNT01 + m_iTaunt%(SOUND_TAUNTLAST-SOUND_TAUNT01+1); + PlaySound(m_soChant, iTaunt, SOF_3D); + m_iTaunt++; + + StartModelAnim(SUMMONER_ANIM_MAGICATTACK, SOF_SMOOTHCHANGE); + + //wait to get into spawner emitting position + autowait(TM_WAIT_BEFORE_FIRE); + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + + INDEX i,j; + FLOAT3D vTarget; + FLOAT fTotalSpawnedScore = 0.0f; + INDEX iTotalSpawnedCount = 0; + INDEX iEnemyCount; + FLOAT fScore; + CountEnemiesAndScoreValue(iEnemyCount, fScore); + + CMusicHolder *penMusicHolder = GetMusicHolder(); + + FLOAT fTmpFuss = 0.0f; + + // for each group in current spawn scheme + for (i=0; i<3; i++) { + INDEX iMin = aiSpawnScheme[m_iSpawnScheme][i*2+1]; + INDEX iMax = aiSpawnScheme[m_iSpawnScheme][i*2+2]; + ASSERT(iMin<=iMax); + INDEX iToSpawn; + iToSpawn = iMin + IRnd()%(iMax - iMin + 1); + for (j=0; jm_iScore; + iTotalSpawnedCount++; + // increase the number of spawned enemies in music holder + if (penMusicHolder!=NULL) { + penMusicHolder->m_ctEnemiesInWorld++; + } + ChangeEnemyNumberForAllPlayers(+1); + // stop spawning if too much fuss or too many enemies + fTmpFuss = (fTotalSpawnedScore+fScore)*FussModifier(iTotalSpawnedCount+iEnemyCount); + if (fTmpFuss>m_fMaxCurrentFuss) { + break; + } + } + } + + m_fDamageSinceLastSpawn = 0.0f; + + //wait for firing animation to stop + autowait(GetModelObject()->GetAnimLength(SUMMONER_ANIM_MAGICATTACK)-TM_WAIT_BEFORE_FIRE); + + // stand a while + StartModelAnim(SUMMONER_ANIM_IDLE, SOF_SMOOTHCHANGE); + + // teleport by sending an event to ourselves + ESummonerTeleport est; + est.fWait = FRnd()*1.0f+3.0f; + SendEvent(est); + // if too much fuss, just laugh and initiate teleport + } else if (TRUE) { + + PlaySound(m_soExplosion, SOUND_LAUGH, SOF_3D); + autowait(1.0f); + StartModelAnim(SUMMONER_ANIM_MAGICATTACK, SOF_SMOOTHCHANGE); + + INDEX iTaunt = SOUND_TAUNT01 + m_iTaunt%(SOUND_TAUNTLAST-SOUND_TAUNT01+1); + PlaySound(m_soChant, iTaunt, SOF_3D); + m_iTaunt++; + + //wait to get into spawner emitting position + autowait(TM_WAIT_BEFORE_FIRE); + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + + INDEX iEnemyCount; + FLOAT fScore; + CountEnemiesAndScoreValue(iEnemyCount, fScore); + FLOAT fToSpawn; + + INDEX iScheme; + // find last active scheme + for (INDEX i=0; i<3; i++) { + if (aiSpawnScheme[m_iSpawnScheme][i*2+2]>0) { + iScheme = i; + } + } + + if (m_iSpawnScheme>3) { + iEnemyCount += (m_iSpawnScheme-3); + } + + if (iEnemyCount<6) { + fToSpawn = (6.0 - (FLOAT)iEnemyCount)/2.0f; + } else { + fToSpawn = 1.0f; + } + INDEX iToSpawn = ceilf(fToSpawn); + + CMusicHolder *penMusicHolder = GetMusicHolder(); +//CPrintF("spawning %d from %d group\n", iToSpawn, iScheme); + // spawn + for (INDEX j=0; jm_ctEnemiesInWorld++; + } + ChangeEnemyNumberForAllPlayers(+1); + } + + // teleport by sending an event to ourselves + ESummonerTeleport est; + est.fWait = FRnd()*1.0f+3.0f; + SendEvent(est); + // laugh + autowait(1.0f); + + } + + m_bFiredThisTurn = TRUE; + } + + return EReturn(); + }; + + Hit(EVoid) : CEnemyBase::Hit { + jump Fire(); + return EReturn(); + }; + +/************************************************************ + * D E A T H * + ************************************************************/ + + Die(EDeath eDeath) : CEnemyBase::Die + { + + m_bDying = TRUE; + + m_penDeathInflictor = eDeath.eLastDamage.penInflictor; + + // find the one who killed, or other best suitable player + m_penKiller = m_penDeathInflictor; + if (m_penKiller ==NULL || !IsOfClass(m_penKiller, "Player")) { + m_penKiller = m_penEnemy; + } + + if (m_penKiller==NULL || !IsOfClass(m_penKiller, "Player")) { + m_penKiller = FixupCausedToPlayer(this, m_penKiller, /*bWarning=*/FALSE); + } + + // stop rotations + SetDesiredRotation(ANGLE3D(0.0f, 0.0f, 0.0f)); + // first kill off all enemies inside the control area + KillAllEnemiesInArea(eDeath); + + StartModelAnim(SUMMONER_ANIM_CHANTING, SOF_SMOOTHCHANGE); + PlaySound(m_soExplosion, SOUND_LASTWORDS, SOF_3D); + autowait(4.0f); + + autocall TeleportToDeathMarker() EReturn; + + // do this once more, just in case anything survived + EDeath eDeath; + eDeath.eLastDamage.penInflictor = m_penDeathInflictor; + KillAllEnemiesInArea(eDeath); + + // slowly start shaking + ShakeItBaby(_pTimer->CurrentTick(), 0.25f, TRUE); + PlaySound(m_soExplosion, SOUND_TREMORS, SOF_3D); + + m_vDeathPosition = GetPlacement().pl_PositionVector; + + // notify possible targets of beginning of the death sequence + if (m_penBeginDeathTarget!=NULL) { + SendToTarget(m_penBeginDeathTarget, EET_TRIGGER, m_penKiller); + } + + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + StartModelAnim(SUMMONER_ANIM_DEATHBLOW, SOF_SMOOTHCHANGE); + autowait(GetModelObject()->GetAnimLength(SUMMONER_ANIM_DEATHBLOW)-0.25f); + + // hide model + SwitchToEditorModel(); + + // start death starts + CPlacement3D plStars; + plStars = GetPlacement(); + ESpawnEffect eSpawnEffect; + eSpawnEffect.betType = BET_SUMMONERSTAREXPLOSION; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + CEntityPointer penStars = CreateEntity(plStars, CLASS_BASIC_EFFECT); + penStars->Initialize(eSpawnEffect); + + m_tmDeathBegin = _pTimer->CurrentTick(); + m_fDeathDuration = 12.0f; + m_bExploded = TRUE; + ShakeItBaby(_pTimer->CurrentTick(), 5.0f, FALSE); + + PlaySound(m_soExplosion, SOUND_EXPLODE, SOF_3D); + + // spawn debris + Debris_Begin(EIBT_FLESH, DPT_BLOODTRAIL, BET_BLOODSTAIN, 1.0f, + FLOAT3D(0.0f, 10.0f, 0.0f), FLOAT3D(0.0f, 0.0f, 0.0f), 5.0f, 2.0f); + for (INDEX i=0; i<15; i++) { + + FLOAT3D vSpeed = FLOAT3D(0.3f+FRnd()*0.1f, 1.0f+FRnd()*0.5f, 0.3f+FRnd()*0.1f)*1.5f*m_fStretch; + FLOAT3D vPos = vSpeed + GetPlacement().pl_PositionVector; + ANGLE3D aAng = ANGLE3D(FRnd()*360.0f, FRnd()*360.0f, FRnd()*360.0f); + + vSpeed.Normalize(); + vSpeed(2) *= vSpeed(2); + + CPlacement3D plPos = CPlacement3D (vPos, aAng); + + switch(i%3) { + case 0: + Debris_Spawn_Independent(this, this, MODEL_DEBRIS01, TEXTURE_SUMMONER, 0, 0, 0, 0, m_fStretch, + plPos, vSpeed*70.0f, aAng); + Debris_Spawn_Independent(this, this, MODEL_DEBRIS_FLESH, TEXTURE_DEBRIS_FLESH , 0, 0, 0, 0, m_fStretch*0.33f, + plPos, vSpeed*70.0f, aAng); + break; + case 1: + Debris_Spawn_Independent(this, this, MODEL_DEBRIS02, TEXTURE_SUMMONER, 0, 0, 0, 0, m_fStretch, + plPos, vSpeed*70.0f, aAng); + Debris_Spawn_Independent(this, this, MODEL_DEBRIS_FLESH, TEXTURE_DEBRIS_FLESH , 0, 0, 0, 0, m_fStretch*0.33f, + plPos, vSpeed*70.0f, aAng); + break; + case 2: + Debris_Spawn_Independent(this, this, MODEL_DEBRIS03, TEXTURE_SUMMONER, 0, 0, 0, 0, m_fStretch, + plPos, vSpeed*70.0f, aAng); + Debris_Spawn_Independent(this, this, MODEL_DEBRIS_FLESH, TEXTURE_DEBRIS_FLESH , 0, 0, 0, 0, m_fStretch*0.33f, + plPos, vSpeed*70.0f, aAng); + break; + } + } + + // notify possible targets of end of the death sequence + if (m_penExplodeDeathTarget!=NULL) { + SendToTarget(m_penExplodeDeathTarget, EET_TRIGGER, m_penKiller); + } + + // turn off collision and physics + //SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + //SetCollisionFlags(ECF_IMMATERIAL); + + PlaySound(m_soSound, SOUND_CHIMES, SOF_3D); + + m_iIndex = 20; + while ((m_iIndex--)>1) { + CPlacement3D plExplosion; + plExplosion.pl_OrientationAngle = ANGLE3D(0.0f, 0.0f, 0.0f); + plExplosion.pl_PositionVector = FLOAT3D(0.3f+FRnd()*0.1f, 1.0f+FRnd()*0.5f, 0.3f+FRnd()*0.1f)*m_fStretch; + plExplosion.pl_PositionVector += GetPlacement().pl_PositionVector; + ESpawnEffect eSpawnEffect; + eSpawnEffect.colMuliplier = C_WHITE|CT_OPAQUE; + eSpawnEffect.betType = BET_CANNON; + FLOAT fSize = (m_fStretch*m_iIndex)*0.333f; + eSpawnEffect.vStretch = FLOAT3D(fSize, fSize, fSize); + CEntityPointer penExplosion = CreateEntity(plExplosion, CLASS_BASIC_EFFECT); + penExplosion->Initialize(eSpawnEffect); + + ShakeItBaby(_pTimer->CurrentTick(), m_iIndex/4.0f, FALSE); + + autowait(0.05f + FRnd()*0.2f); + } + + autowait(m_fDeathDuration); + + // notify possible targets of end of the death sequence + if (m_penEndDeathTarget!=NULL) { + SendToTarget(m_penEndDeathTarget, EET_TRIGGER, m_penKiller); + } + + EDeath eDeath; + eDeath.eLastDamage.penInflictor = m_penDeathInflictor; + jump CEnemyBase::Die(eDeath); + } + + TeleportToDeathMarker(EVoid) + { + + m_bInvulnerable = TRUE; + + StartModelAnim(SUMMONER_ANIM_VANISHING, SOF_SMOOTHCHANGE); + autowait(GetModelObject()->GetAnimLength(SUMMONER_ANIM_VANISHING)); + + // hide model + DisappearEffect(); + SwitchToEditorModel(); + SetCollisionFlags(ECF_IMMATERIAL); + + // destroy possible flames + CEntityPointer penFlame = GetChildOfClass("Flame"); + if (penFlame!=NULL) { + penFlame->Destroy(); + } + + // wait a little bit + autowait(2.0f); + + CPlacement3D pl; + pl.pl_PositionVector = m_penDeathMarker->GetPlacement().pl_PositionVector; + FLOAT3D vToPlayer; + if (m_penEnemy!=NULL) { + vToPlayer = m_penEnemy->GetPlacement().pl_PositionVector - pl.pl_PositionVector; + } else { + vToPlayer = m_vPlayerSpotted - pl.pl_PositionVector; + } + vToPlayer.Normalize(); + DirectionVectorToAngles(vToPlayer, pl.pl_OrientationAngle); + Teleport(pl); + + // show model + SpawnTeleportEffect(); + + autowait(0.5f); + SwitchToModel(); + SetCollisionFlags(ECF_MODEL); + + m_bInvulnerable = FALSE; + + StartModelAnim(SUMMONER_ANIM_APPEARING, SOF_SMOOTHCHANGE); + autowait(GetModelObject()->GetAnimLength(SUMMONER_ANIM_APPEARING)); + + return EReturn(); + } + + BossAppear(EVoid) + { + return EReturn(); + } + + // overridable called before main enemy loop actually begins + PreMainLoop(EVoid) : CEnemyBase::PreMainLoop + { + autocall BossAppear() EReturn; + return EReturn(); + } + + Immaterial() { + + // hide model + DisappearEffect(); + SwitchToEditorModel(); + SetCollisionFlags(ECF_IMMATERIAL); + + // destroy possible flames + CEntityPointer penFlame = GetChildOfClass("Flame"); + if (penFlame!=NULL) { + penFlame->Destroy(); + } + + // wait required time + autowait(m_fImmaterialDuration+FRnd()*2.0f-1.0f); + + INDEX iMaxTries = 10; + FLOAT3D vTarget; + // move to a new position + do { + CSummonerMarker *marker = &((CSummonerMarker &)*m_penTeleportMarker); + INDEX iMarker = IRnd()%m_iTeleportMarkers; + while (iMarker>0) { + marker = &((CSummonerMarker &)*marker->m_penTarget); + iMarker--; + } + vTarget = marker->GetPlacement().pl_PositionVector; + FLOAT fR = FRnd()*marker->m_fMarkerRange; + FLOAT fA = FRnd()*360.0f; + vTarget += FLOAT3D(CosFast(fA)*fR, 0.05f, SinFast(fA)*fR); + } while (!DistanceToAllPlayersGreaterThen(1.0f) || (iMaxTries--)<1); + + CPlacement3D pl; + pl.pl_PositionVector = vTarget; + FLOAT3D vToPlayer; + if (m_penEnemy!=NULL) { + vToPlayer = m_penEnemy->GetPlacement().pl_PositionVector - vTarget; + } else { + vToPlayer = m_vPlayerSpotted - vTarget; + } + vToPlayer.Normalize(); + DirectionVectorToAngles(vToPlayer, pl.pl_OrientationAngle); + Teleport(pl); + + // show model + SpawnTeleportEffect(); + SwitchToModel(); + SetCollisionFlags(ECF_MODEL); + + m_bShouldTeleport = FALSE; + m_tmMaterializationTime = _pTimer->CurrentTick(); + m_bFiredThisTurn = FALSE; + + m_bInvulnerable = FALSE; + + PlaySound(m_soTeleport, SOUND_MATERIALIZE, SOF_3D); + + StartModelAnim(SUMMONER_ANIM_APPEARING, SOF_SMOOTHCHANGE); + autowait(GetModelObject()->GetAnimLength(SUMMONER_ANIM_APPEARING)); + + SendEvent(EBegin()); + return EReturn(); + + } + + SummonerLoop() { + // spawn a 1sec reminder + SpawnReminder(this, 1.0f, 128); + wait () { + on (EBegin) : + { + call CEnemyBase::MainLoop(); + } + on (EReminder er) : + { + // pass all reminders but the 128 one + if (er.iValue==128) { + RecalculateFuss(); + // see if we have to teleport + if (_pTimer->CurrentTick()>m_tmMaterializationTime+m_fCorporealDuration) { + m_bShouldTeleport = TRUE; + } + // spawn the reminder again so that we return here + SpawnReminder(this, 1.0f, 128); + } else if (er.iValue==129 && !m_bDying) { + call InitiateTeleport(); + } else if (TRUE) { + pass; + } + resume; + } + // we want to teleport in near future + on (ESummonerTeleport est) : + { + //m_fTeleportWaitTime = est.fWait; + SpawnReminder(this, est.fWait, 129); + resume; + } + otherwise () : { + resume; + } + } + } + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + + // declare yourself as a model + InitAsEditorModel(); + + SetPhysicsFlags(EPF_MODEL_WALKING); + SetCollisionFlags(ECF_IMMATERIAL); + SetFlags(GetFlags()|ENF_ALIVE); + + en_fDensity = 10000.0f; + m_fDamageWounded = 1e6f; + + m_sptType = SPT_BLOOD; + m_bBoss = TRUE; + SetHealth(SUMMONER_HEALTH); + m_fMaxHealth = SUMMONER_HEALTH; + m_fBodyParts = 0; + // setup moving speed + m_fWalkSpeed = 0.0f; + m_aWalkRotateSpeed = AngleDeg(270.0f); + m_fAttackRunSpeed = 0.0f; + m_aAttackRotateSpeed = AngleDeg(270.0f); + m_fCloseRunSpeed = 0.0f; + m_aCloseRotateSpeed = AngleDeg(270.0f); + // setup attack distances + m_fAttackDistance = 500.0f; + m_fCloseDistance = 50.0f; + m_fStopDistance = 500.0f; + m_fIgnoreRange = 600.0f; + m_iScore = 1000000; + // setup attack times + m_fAttackFireTime = m_fFirePeriod; + m_fCloseFireTime = m_fFirePeriod; + + SetPhysicsFlags(EPF_MODEL_WALKING); + StandingAnim(); + + // set your appearance + //m_fStretch = SIZE; + SetComponents(this, *GetModelObject(), MODEL_SUMMONER, TEXTURE_SUMMONER, 0, 0, 0); + AddAttachmentToModel(this, *GetModelObject(), SUMMONER_ATTACHMENT_STAFF, MODEL_STAFF, TEXTURE_STAFF, 0, 0, 0); + GetModelObject()->StretchModel(FLOAT3D(m_fStretch, m_fStretch, m_fStretch )); + ModelChangeNotify(); + + AddToMovers(); + + autowait(_pTimer->TickQuantum); + + m_emEmiter.Initialize(this); + m_emEmiter.em_etType=ET_SUMMONER_STAFF; + + // count templates by groups + INDEX i; + CEntityPointer *pen; + m_iGroup01Count = 0; + pen = &m_penGroup01Template01; + for (i=0; im_penTarget!=NULL) + { + it = &((CEnemyMarker &)*it->m_penTarget); + m_iSpawnMarkers ++; + } + + // count teleport markers + m_iTeleportMarkers = 1; + it = &((CEnemyMarker &)*m_penTeleportMarker); + while (it->m_penTarget!=NULL) + { + it = &((CEnemyMarker &)*it->m_penTarget); + m_iTeleportMarkers ++; + } + + m_iSpawnScheme = 0; + m_fMaxCurrentFuss = m_fMaxBeginFuss; + m_bDying = FALSE; + m_tmDeathBegin = 0.0f; + m_fDeathDuration = 0.0f; + m_bInvulnerable = TRUE; + m_bExploded = FALSE; + + // wait to be triggered + wait() { + on (EBegin) : { resume; } + on (ETrigger) : { stop; } + otherwise (): { resume; } + } + + m_soExplosion.Set3DParameters(1500.0f, 1000.0f, 2.0f, 1.0f); + m_soSound.Set3DParameters(1500.0f, 1000.0f, 2.0f, 1.0f); + m_soChant.Set3DParameters(1500.0f, 1000.0f, 2.0f, 1.0f); + m_soTeleport.Set3DParameters(1500.0f, 1000.0f, 3.0f, 1.0f); + m_iTaunt = 0; + + //PlaySound(m_soSound, SOUND_APPEAR, SOF_3D); + // teleport in + SpawnTeleportEffect(); + SwitchToModel(); + m_bInvulnerable = FALSE; + SetCollisionFlags(ECF_MODEL); + + PlaySound(m_soTeleport, SOUND_MATERIALIZE, SOF_3D); + + StartModelAnim(SUMMONER_ANIM_APPEARING, SOF_SMOOTHCHANGE); + autowait(GetModelObject()->GetAnimLength(SUMMONER_ANIM_APPEARING)); + + m_tmMaterializationTime = _pTimer->CurrentTick(); + + // one state under base class to intercept some events + jump SummonerLoop(); + //jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Summoner.h b/Sources/EntitiesMP/Summoner.h new file mode 100644 index 0000000..f95c77f --- /dev/null +++ b/Sources/EntitiesMP/Summoner.h @@ -0,0 +1,268 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Summoner_INCLUDED +#define _EntitiesMP_Summoner_INCLUDED 1 +#include +#include +#include +#include +#include +#define EVENTCODE_ESummonerTeleport 0x015b0000 +class DECL_DLL ESummonerTeleport : public CEntityEvent { +public: +ESummonerTeleport(); +CEntityEvent *MakeCopy(void); +FLOAT fWait; +}; +DECL_DLL inline void ClearToDefault(ESummonerTeleport &e) { e = ESummonerTeleport(); } ; +extern "C" DECL_DLL CDLLEntityClass CSummoner_DLLClass; +class CSummoner : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bInvulnerable; + CEntityPointer m_penBeginDeathTarget; + CEntityPointer m_penEndDeathTarget; + CEntityPointer m_penExplodeDeathTarget; + BOOL m_bShouldTeleport; + FLOAT m_fFirePeriod; + FLOAT m_fImmaterialDuration; + FLOAT m_fCorporealDuration; + FLOAT m_tmMaterializationTime; + FLOAT m_fStretch; + INDEX m_iSize; + CEntityPointer m_penControlArea; + INDEX m_iGroup01Count; + CEntityPointer m_penGroup01Template01; + CEntityPointer m_penGroup01Template02; + CEntityPointer m_penGroup01Template03; + CEntityPointer m_penGroup01Template04; + CEntityPointer m_penGroup01Template05; + CEntityPointer m_penGroup01Template06; + INDEX m_iGroup02Count; + CEntityPointer m_penGroup02Template01; + CEntityPointer m_penGroup02Template02; + CEntityPointer m_penGroup02Template03; + CEntityPointer m_penGroup02Template04; + CEntityPointer m_penGroup02Template05; + CEntityPointer m_penGroup02Template06; + INDEX m_iGroup03Count; + CEntityPointer m_penGroup03Template01; + CEntityPointer m_penGroup03Template02; + CEntityPointer m_penGroup03Template03; + CEntityPointer m_penGroup03Template04; + CEntityPointer m_penGroup03Template05; + CEntityPointer m_penGroup03Template06; + CEntityPointer m_penTeleportMarker; + INDEX m_iTeleportMarkers; + CEntityPointer m_penSpawnMarker; + INDEX m_iSpawnMarkers; + FLOAT m_fTeleportWaitTime; + FLOAT m_fFuss; + INDEX m_iEnemyCount; + FLOAT m_fMaxCurrentFuss; + FLOAT m_fMaxBeginFuss; + FLOAT m_fMaxEndFuss; + INDEX m_iSpawnScheme; + BOOL m_bFireOK; + BOOL m_bFiredThisTurn; + FLOAT m_fDamageSinceLastSpawn; + BOOL m_bExploded; + BOOL m_bDying; + FLOAT m_tmDeathBegin; + FLOAT m_fDeathDuration; + CEntityPointer m_penDeathInflictor; + CEntityPointer m_penKiller; + FLOAT3D m_vDeathPosition; + CEntityPointer m_penDeathMarker; + INDEX m_iIndex; + INDEX m_iTaunt; + FLOAT m_tmParticlesDisappearStart; + FLOAT m_tmLastAnimation; + CSoundObject m_soExplosion; + CSoundObject m_soSound; + CSoundObject m_soChant; + CSoundObject m_soTeleport; +CEmiter m_emEmiter; + +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void Read_t(CTStream * istr); + +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void Write_t(CTStream * istr); + +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +BOOL DoSafetyChecks(void); + +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void Precache(void); + +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void * GetEntityInfo(void); + +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CMusicHolder * GetMusicHolder(); + +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +BOOL DistanceToAllPlayersGreaterThen(FLOAT fDistance); + +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void ShakeItBaby(FLOAT tmShaketime,FLOAT fPower,BOOL bFadeIn); + +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void ChangeEnemyNumberForAllPlayers(INDEX iDelta); + +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void StandingAnimFight(void); + +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void StandingAnim(void); + +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void WalkingAnim(void); + +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void RunningAnim(void); + +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void RotatingAnim(void); + +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void IdleSound(void); + +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT3D AcquireTarget(); + +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void LaunchMonster(FLOAT3D vTarget,CEntity * penTemplate); + +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +FLOAT FussModifier(INDEX iEnemyCount); + +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void RecalculateFuss(void); + +#line 568 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void CountEnemiesAndScoreValue(INDEX & iEnemies,FLOAT & fScore); + +#line 594 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +CEnemyBase * GetRandomTemplate(INDEX iGroup); + +#line 625 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void DisappearEffect(void); + +#line 649 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void SpawnTeleportEffect(void); + +#line 699 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void KillAllEnemiesInArea(EDeath eDeath); + +#line 744 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +void RenderParticles(void); +#define STATE_CSummoner_InitiateTeleport 0x015b0001 + BOOL +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +InitiateTeleport(const CEntityEvent &__eeInput); + BOOL H0x015b0002_InitiateTeleport_01(const CEntityEvent &__eeInput); + BOOL H0x015b0003_InitiateTeleport_02(const CEntityEvent &__eeInput); +#define STATE_CSummoner_Fire 0x015b0004 + BOOL +#line 812 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x015b0005_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x015b0006_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x015b0007_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x015b0008_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x015b0009_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x015b000a_Fire_06(const CEntityEvent &__eeInput); + BOOL H0x015b000b_Fire_07(const CEntityEvent &__eeInput); + BOOL H0x015b000c_Fire_08(const CEntityEvent &__eeInput); + BOOL H0x015b000d_Fire_09(const CEntityEvent &__eeInput); + BOOL H0x015b000e_Fire_10(const CEntityEvent &__eeInput); + BOOL H0x015b000f_Fire_11(const CEntityEvent &__eeInput); + BOOL H0x015b0010_Fire_12(const CEntityEvent &__eeInput); + BOOL H0x015b0011_Fire_13(const CEntityEvent &__eeInput); + BOOL H0x015b0012_Fire_14(const CEntityEvent &__eeInput); +#define STATE_CSummoner_Hit 0x015b0013 + BOOL +#line 947 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Hit(const CEntityEvent &__eeInput); +#define STATE_CSummoner_Die 0x015b0014 + BOOL +#line 956 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Die(const CEntityEvent &__eeInput); + BOOL H0x015b0015_Die_01(const CEntityEvent &__eeInput); + BOOL H0x015b0016_Die_02(const CEntityEvent &__eeInput); + BOOL H0x015b0017_Die_03(const CEntityEvent &__eeInput); + BOOL H0x015b0018_Die_04(const CEntityEvent &__eeInput); + BOOL H0x015b0019_Die_05(const CEntityEvent &__eeInput); + BOOL H0x015b001a_Die_06(const CEntityEvent &__eeInput); + BOOL H0x015b001b_Die_07(const CEntityEvent &__eeInput); + BOOL H0x015b001c_Die_08(const CEntityEvent &__eeInput); + BOOL H0x015b001d_Die_09(const CEntityEvent &__eeInput); + BOOL H0x015b001e_Die_10(const CEntityEvent &__eeInput); + BOOL H0x015b001f_Die_11(const CEntityEvent &__eeInput); + BOOL H0x015b0020_Die_12(const CEntityEvent &__eeInput); +#define STATE_CSummoner_TeleportToDeathMarker 0x015b0021 + BOOL +#line 1101 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +TeleportToDeathMarker(const CEntityEvent &__eeInput); + BOOL H0x015b0022_TeleportToDeathMarker_01(const CEntityEvent &__eeInput); + BOOL H0x015b0023_TeleportToDeathMarker_02(const CEntityEvent &__eeInput); + BOOL H0x015b0024_TeleportToDeathMarker_03(const CEntityEvent &__eeInput); + BOOL H0x015b0025_TeleportToDeathMarker_04(const CEntityEvent &__eeInput); + BOOL H0x015b0026_TeleportToDeathMarker_05(const CEntityEvent &__eeInput); + BOOL H0x015b0027_TeleportToDeathMarker_06(const CEntityEvent &__eeInput); + BOOL H0x015b0028_TeleportToDeathMarker_07(const CEntityEvent &__eeInput); + BOOL H0x015b0029_TeleportToDeathMarker_08(const CEntityEvent &__eeInput); +#define STATE_CSummoner_BossAppear 0x015b002a + BOOL +#line 1150 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +BossAppear(const CEntityEvent &__eeInput); +#define STATE_CSummoner_PreMainLoop 0x015b002b + BOOL +#line 1156 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PreMainLoop(const CEntityEvent &__eeInput); + BOOL H0x015b002c_PreMainLoop_01(const CEntityEvent &__eeInput); + BOOL H0x015b002d_PreMainLoop_02(const CEntityEvent &__eeInput); +#define STATE_CSummoner_Immaterial 0x015b002e + BOOL +#line 1162 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Immaterial(const CEntityEvent &__eeInput); + BOOL H0x015b002f_Immaterial_01(const CEntityEvent &__eeInput); + BOOL H0x015b0030_Immaterial_02(const CEntityEvent &__eeInput); + BOOL H0x015b0031_Immaterial_03(const CEntityEvent &__eeInput); + BOOL H0x015b0032_Immaterial_04(const CEntityEvent &__eeInput); +#define STATE_CSummoner_SummonerLoop 0x015b0033 + BOOL +#line 1227 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SummonerLoop(const CEntityEvent &__eeInput); + BOOL H0x015b0034_SummonerLoop_01(const CEntityEvent &__eeInput); + BOOL H0x015b0035_SummonerLoop_02(const CEntityEvent &__eeInput); +#define STATE_CSummoner_Main 1 + BOOL +#line 1269 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x015b0036_Main_01(const CEntityEvent &__eeInput); + BOOL H0x015b0037_Main_02(const CEntityEvent &__eeInput); + BOOL H0x015b0038_Main_03(const CEntityEvent &__eeInput); + BOOL H0x015b0039_Main_04(const CEntityEvent &__eeInput); + BOOL H0x015b003a_Main_05(const CEntityEvent &__eeInput); + BOOL H0x015b003b_Main_06(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Summoner_INCLUDED diff --git a/Sources/EntitiesMP/SummonerMarker.cpp b/Sources/EntitiesMP/SummonerMarker.cpp new file mode 100644 index 0000000..56a25ef --- /dev/null +++ b/Sources/EntitiesMP/SummonerMarker.cpp @@ -0,0 +1,75 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" + +#include "StdH.h" + +#include +#include +void CSummonerMarker::SetDefaultProperties(void) { + m_strName = "SummonerMarker"; + m_strDescription = "SummonerMarker"; + m_fMarkerRange = 0.0f; + CMarker::SetDefaultProperties(); +} + +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +BOOL CSummonerMarker::MovesByTargetedRoute(CTString & strTargetProperty)const { +#line 28 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +strTargetProperty = "Target"; +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +return TRUE ; +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +} + +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +BOOL CSummonerMarker::DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const { +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +fnmMarkerClass = CTFILENAME ("Classes\\SummonerMarker.ecl"); +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +strTargetProperty = "Target"; +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +return TRUE ; +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +} + +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +BOOL CSummonerMarker::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +{ +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +if(slPropertyOffset == offsetof (CSummonerMarker , m_penTarget )) +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +{ +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +if(IsOfClass (penTarget , "SummonerMarker")){return TRUE ;} +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +else {return FALSE ;} +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +} +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +return CEntity :: IsTargetValid (slPropertyOffset , penTarget ); +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +} +BOOL CSummonerMarker:: +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSummonerMarker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSummonerMarker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +InitAsEditorModel (); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +SetModel (MODEL_SUMMONERMARKER ); +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +SetModelMainTexture (TEXTURE_SUMMONERMARKER ); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +Return(STATE_CURRENT,EVoid()); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/SummonerMarker.es b/Sources/EntitiesMP/SummonerMarker.es new file mode 100644 index 0000000..6ff1d50 --- /dev/null +++ b/Sources/EntitiesMP/SummonerMarker.es @@ -0,0 +1,63 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +350 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; + +class CSummonerMarker: CMarker { +name "SummonerMarker"; +thumbnail "Thumbnails\\EnemyMarker.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "SummonerMarker", + 2 CTString m_strDescription = "SummonerMarker", + 3 RANGE m_fMarkerRange "Marker Range" 'M' = 0.0f, // range around marker (markers don't have to be hit directly) + +components: + 1 model MODEL_SUMMONERMARKER "Models\\Editor\\EnemyMarker.mdl", + 2 texture TEXTURE_SUMMONERMARKER "Models\\Editor\\BoundingBox.tex" + +functions: + + /* Check if entity is moved on a route set up by its targets. */ + BOOL MovesByTargetedRoute(CTString &strTargetProperty) const { + strTargetProperty = "Target"; + return TRUE; + }; + + /* Check if entity can drop marker for making linked route. */ + BOOL DropsMarker(CTFileName &fnmMarkerClass, CTString &strTargetProperty) const { + fnmMarkerClass = CTFILENAME("Classes\\SummonerMarker.ecl"); + strTargetProperty = "Target"; + return TRUE; + } + + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if( slPropertyOffset == offsetof(CSummonerMarker, m_penTarget)) + { + if (IsOfClass(penTarget, "SummonerMarker")) { return TRUE; } + else { return FALSE; } + } + return CEntity::IsTargetValid(slPropertyOffset, penTarget); + } + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_SUMMONERMARKER); + SetModelMainTexture(TEXTURE_SUMMONERMARKER); + + return; + } +}; + diff --git a/Sources/EntitiesMP/SummonerMarker.h b/Sources/EntitiesMP/SummonerMarker.h new file mode 100644 index 0000000..5a9ee6d --- /dev/null +++ b/Sources/EntitiesMP/SummonerMarker.h @@ -0,0 +1,31 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_SummonerMarker_INCLUDED +#define _EntitiesMP_SummonerMarker_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CSummonerMarker_DLLClass; +class CSummonerMarker : public CMarker { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + RANGE m_fMarkerRange; + +#line 27 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +BOOL MovesByTargetedRoute(CTString & strTargetProperty)const; + +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +BOOL DropsMarker(CTFileName & fnmMarkerClass,CTString & strTargetProperty)const; + +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); +#define STATE_CSummonerMarker_Main 1 + BOOL +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_SummonerMarker_INCLUDED diff --git a/Sources/EntitiesMP/SummonerMarker_tables.h b/Sources/EntitiesMP/SummonerMarker_tables.h new file mode 100644 index 0000000..f1f6141 --- /dev/null +++ b/Sources/EntitiesMP/SummonerMarker_tables.h @@ -0,0 +1,38 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CSummonerMarker + +CEntityProperty CSummonerMarker_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x0000015e<<8)+1, offsetof(CSummonerMarker, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x0000015e<<8)+2, offsetof(CSummonerMarker, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x0000015e<<8)+3, offsetof(CSummonerMarker, m_fMarkerRange), "Marker Range", 'M', 0x7F0000FFUL, 0), +}; +#define CSummonerMarker_propertiesct ARRAYCOUNT(CSummonerMarker_properties) + +CEntityComponent CSummonerMarker_components[] = { +#define MODEL_SUMMONERMARKER ((0x0000015e<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_SUMMONERMARKER, "EFNM" "Models\\Editor\\EnemyMarker.mdl"), +#define TEXTURE_SUMMONERMARKER ((0x0000015e<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_SUMMONERMARKER, "EFNM" "Models\\Editor\\BoundingBox.tex"), +}; +#define CSummonerMarker_componentsct ARRAYCOUNT(CSummonerMarker_components) + +CEventHandlerEntry CSummonerMarker_handlers[] = { + {1, -1, CEntity::pEventHandler(&CSummonerMarker:: +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/SummonerMarker.es" +Main),DEBUGSTRING("CSummonerMarker::Main")}, +}; +#define CSummonerMarker_handlersct ARRAYCOUNT(CSummonerMarker_handlers) + +CEntity *CSummonerMarker_New(void) { return new CSummonerMarker; }; +void CSummonerMarker_OnInitClass(void) {}; +void CSummonerMarker_OnEndClass(void) {}; +void CSummonerMarker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CSummonerMarker_OnWorldEnd(CWorld *pwo) {}; +void CSummonerMarker_OnWorldInit(CWorld *pwo) {}; +void CSummonerMarker_OnWorldTick(CWorld *pwo) {}; +void CSummonerMarker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CSummonerMarker, CMarker, "SummonerMarker", "Thumbnails\\EnemyMarker.tbn", 0x0000015e); +DECLARE_CTFILENAME(_fnmCSummonerMarker_tbn, "Thumbnails\\EnemyMarker.tbn"); diff --git a/Sources/EntitiesMP/Summoner_tables.h b/Sources/EntitiesMP/Summoner_tables.h new file mode 100644 index 0000000..809e883 --- /dev/null +++ b/Sources/EntitiesMP/Summoner_tables.h @@ -0,0 +1,235 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CSummoner + +CEntityProperty CSummoner_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015b<<8)+1, offsetof(CSummoner, m_bInvulnerable), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+2, offsetof(CSummoner, m_penBeginDeathTarget), "Sum. Begin Death Target", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+3, offsetof(CSummoner, m_penEndDeathTarget), "Sum. End Death Target", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+4, offsetof(CSummoner, m_penExplodeDeathTarget), "Sum. Explode Target", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015b<<8)+5, offsetof(CSummoner, m_bShouldTeleport), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+6, offsetof(CSummoner, m_fFirePeriod), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+7, offsetof(CSummoner, m_fImmaterialDuration), "Sum. Immaterial Duration", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+8, offsetof(CSummoner, m_fCorporealDuration), "Sum. Corporeal Duration", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+9, offsetof(CSummoner, m_tmMaterializationTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+10, offsetof(CSummoner, m_fStretch), "Sum. Stretch", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+11, offsetof(CSummoner, m_iSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+12, offsetof(CSummoner, m_penControlArea), "Sum. Control Area", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+20, offsetof(CSummoner, m_iGroup01Count), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+21, offsetof(CSummoner, m_penGroup01Template01), "Sum. Group01 Template01", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+22, offsetof(CSummoner, m_penGroup01Template02), "Sum. Group01 Template02", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+23, offsetof(CSummoner, m_penGroup01Template03), "Sum. Group01 Template03", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+24, offsetof(CSummoner, m_penGroup01Template04), "Sum. Group01 Template04", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+25, offsetof(CSummoner, m_penGroup01Template05), "Sum. Group01 Template05", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+26, offsetof(CSummoner, m_penGroup01Template06), "Sum. Group01 Template06", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+30, offsetof(CSummoner, m_iGroup02Count), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+31, offsetof(CSummoner, m_penGroup02Template01), "Sum. Group02 Template01", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+32, offsetof(CSummoner, m_penGroup02Template02), "Sum. Group02 Template02", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+33, offsetof(CSummoner, m_penGroup02Template03), "Sum. Group02 Template03", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+34, offsetof(CSummoner, m_penGroup02Template04), "Sum. Group02 Template04", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+35, offsetof(CSummoner, m_penGroup02Template05), "Sum. Group02 Template05", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+36, offsetof(CSummoner, m_penGroup02Template06), "Sum. Group02 Template06", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+40, offsetof(CSummoner, m_iGroup03Count), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+41, offsetof(CSummoner, m_penGroup03Template01), "Sum. Group03 Template01", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+42, offsetof(CSummoner, m_penGroup03Template02), "Sum. Group03 Template02", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+43, offsetof(CSummoner, m_penGroup03Template03), "Sum. Group03 Template03", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+44, offsetof(CSummoner, m_penGroup03Template04), "Sum. Group03 Template04", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+45, offsetof(CSummoner, m_penGroup03Template05), "Sum. Group03 Template05", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+46, offsetof(CSummoner, m_penGroup03Template06), "Sum. Group03 Template06", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+60, offsetof(CSummoner, m_penTeleportMarker), "Sum. Teleport marker", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+61, offsetof(CSummoner, m_iTeleportMarkers), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+65, offsetof(CSummoner, m_penSpawnMarker), "Sum. Enemy spawn marker", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+66, offsetof(CSummoner, m_iSpawnMarkers), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+67, offsetof(CSummoner, m_fTeleportWaitTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+70, offsetof(CSummoner, m_fFuss), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+78, offsetof(CSummoner, m_iEnemyCount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+71, offsetof(CSummoner, m_fMaxCurrentFuss), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+72, offsetof(CSummoner, m_fMaxBeginFuss), "Sum. Max Begin Fuss", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+73, offsetof(CSummoner, m_fMaxEndFuss), "Sum. Max End Fuss", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+75, offsetof(CSummoner, m_iSpawnScheme), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015b<<8)+76, offsetof(CSummoner, m_bFireOK), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015b<<8)+79, offsetof(CSummoner, m_bFiredThisTurn), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+77, offsetof(CSummoner, m_fDamageSinceLastSpawn), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015b<<8)+88, offsetof(CSummoner, m_bExploded), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000015b<<8)+90, offsetof(CSummoner, m_bDying), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+92, offsetof(CSummoner, m_tmDeathBegin), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+93, offsetof(CSummoner, m_fDeathDuration), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+94, offsetof(CSummoner, m_penDeathInflictor), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+111, offsetof(CSummoner, m_penKiller), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000015b<<8)+95, offsetof(CSummoner, m_vDeathPosition), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000015b<<8)+96, offsetof(CSummoner, m_penDeathMarker), "Sum. Death marker", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+100, offsetof(CSummoner, m_iIndex), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x0000015b<<8)+102, offsetof(CSummoner, m_iTaunt), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+110, offsetof(CSummoner, m_tmParticlesDisappearStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000015b<<8)+120, offsetof(CSummoner, m_tmLastAnimation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015b<<8)+150, offsetof(CSummoner, m_soExplosion), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015b<<8)+151, offsetof(CSummoner, m_soSound), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015b<<8)+152, offsetof(CSummoner, m_soChant), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x0000015b<<8)+153, offsetof(CSummoner, m_soTeleport), "", 0, 0, 0), +}; +#define CSummoner_propertiesct ARRAYCOUNT(CSummoner_properties) + +CEntityComponent CSummoner_components[] = { +#define CLASS_BASE ((0x0000015b<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_BLOOD_SPRAY ((0x0000015b<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_BLOOD_SPRAY, "EFNM" "Classes\\BloodSpray.ecl"), +#define CLASS_SPAWNER_PROJECTILE ((0x0000015b<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_SPAWNER_PROJECTILE, "EFNM" "Classes\\SpawnerProjectile.ecl"), +#define CLASS_BASIC_EFFECT ((0x0000015b<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define CLASS_EFFECTOR ((0x0000015b<<8)+4) + CEntityComponent(ECT_CLASS, CLASS_EFFECTOR, "EFNM" "Classes\\Effector.ecl"), +#define MODEL_SUMMONER ((0x0000015b<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_SUMMONER, "EFNM" "ModelsMP\\Enemies\\Summoner\\Summoner.mdl"), +#define TEXTURE_SUMMONER ((0x0000015b<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_SUMMONER, "EFNM" "ModelsMP\\Enemies\\Summoner\\Summoner.tex"), +#define MODEL_STAFF ((0x0000015b<<8)+12) + CEntityComponent(ECT_MODEL, MODEL_STAFF, "EFNM" "ModelsMP\\Enemies\\Summoner\\Staff.mdl"), +#define TEXTURE_STAFF ((0x0000015b<<8)+13) + CEntityComponent(ECT_TEXTURE, TEXTURE_STAFF, "EFNM" "ModelsMP\\Enemies\\Summoner\\Staff.tex"), +#define MODEL_DEBRIS01 ((0x0000015b<<8)+16) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS01, "EFNM" "ModelsMP\\Enemies\\Summoner\\Debris\\Cloth01.mdl"), +#define MODEL_DEBRIS02 ((0x0000015b<<8)+17) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS02, "EFNM" "ModelsMP\\Enemies\\Summoner\\Debris\\Cloth02.mdl"), +#define MODEL_DEBRIS03 ((0x0000015b<<8)+18) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS03, "EFNM" "ModelsMP\\Enemies\\Summoner\\Debris\\Cloth03.mdl"), +#define MODEL_DEBRIS_FLESH ((0x0000015b<<8)+19) + CEntityComponent(ECT_MODEL, MODEL_DEBRIS_FLESH, "EFNM" "Models\\Effects\\Debris\\Flesh\\Flesh.mdl"), +#define TEXTURE_DEBRIS_FLESH ((0x0000015b<<8)+20) + CEntityComponent(ECT_TEXTURE, TEXTURE_DEBRIS_FLESH, "EFNM" "Models\\Effects\\Debris\\Flesh\\FleshRed.tex"), +#define SOUND_LAUGH ((0x0000015b<<8)+101) + CEntityComponent(ECT_SOUND, SOUND_LAUGH, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Laugh.wav"), +#define SOUND_EXPLODE ((0x0000015b<<8)+102) + CEntityComponent(ECT_SOUND, SOUND_EXPLODE, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Explode.wav"), +#define SOUND_TREMORS ((0x0000015b<<8)+103) + CEntityComponent(ECT_SOUND, SOUND_TREMORS, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Tremors.wav"), +#define SOUND_DEATH ((0x0000015b<<8)+104) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Death.wav"), +#define SOUND_LASTWORDS ((0x0000015b<<8)+105) + CEntityComponent(ECT_SOUND, SOUND_LASTWORDS, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\LastWords.wav"), +#define SOUND_FIRE ((0x0000015b<<8)+106) + CEntityComponent(ECT_SOUND, SOUND_FIRE, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Fire.wav"), +#define SOUND_CHIMES ((0x0000015b<<8)+108) + CEntityComponent(ECT_SOUND, SOUND_CHIMES, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Chimes.wav"), +#define SOUND_MATERIALIZE ((0x0000015b<<8)+107) + CEntityComponent(ECT_SOUND, SOUND_MATERIALIZE, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Materialize.wav"), +#define SOUND_TELEPORT ((0x0000015b<<8)+109) + CEntityComponent(ECT_SOUND, SOUND_TELEPORT, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Teleport.wav"), +#define SOUND_TAUNT01 ((0x0000015b<<8)+150) + CEntityComponent(ECT_SOUND, SOUND_TAUNT01, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote03.wav"), +#define SOUND_TAUNT02 ((0x0000015b<<8)+151) + CEntityComponent(ECT_SOUND, SOUND_TAUNT02, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote05.wav"), +#define SOUND_TAUNT03 ((0x0000015b<<8)+152) + CEntityComponent(ECT_SOUND, SOUND_TAUNT03, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote07.wav"), +#define SOUND_TAUNT04 ((0x0000015b<<8)+153) + CEntityComponent(ECT_SOUND, SOUND_TAUNT04, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote08.wav"), +#define SOUND_TAUNT05 ((0x0000015b<<8)+154) + CEntityComponent(ECT_SOUND, SOUND_TAUNT05, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote10.wav"), +#define SOUND_TAUNT06 ((0x0000015b<<8)+155) + CEntityComponent(ECT_SOUND, SOUND_TAUNT06, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote11.wav"), +#define SOUND_TAUNT07 ((0x0000015b<<8)+156) + CEntityComponent(ECT_SOUND, SOUND_TAUNT07, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote14.wav"), +#define SOUND_TAUNT08 ((0x0000015b<<8)+157) + CEntityComponent(ECT_SOUND, SOUND_TAUNT08, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote15.wav"), +#define SOUND_TAUNTLAST ((0x0000015b<<8)+158) + CEntityComponent(ECT_SOUND, SOUND_TAUNTLAST, "EFNM" "ModelsMP\\Enemies\\Summoner\\Sounds\\Quote16.wav"), +}; +#define CSummoner_componentsct ARRAYCOUNT(CSummoner_components) + +CEventHandlerEntry CSummoner_handlers[] = { + {0x015b0001, -1, CEntity::pEventHandler(&CSummoner:: +#line 797 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +InitiateTeleport),DEBUGSTRING("CSummoner::InitiateTeleport")}, + {0x015b0002, -1, CEntity::pEventHandler(&CSummoner::H0x015b0002_InitiateTeleport_01), DEBUGSTRING("CSummoner::H0x015b0002_InitiateTeleport_01")}, + {0x015b0003, -1, CEntity::pEventHandler(&CSummoner::H0x015b0003_InitiateTeleport_02), DEBUGSTRING("CSummoner::H0x015b0003_InitiateTeleport_02")}, + {0x015b0004, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CSummoner:: +#line 812 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Fire),DEBUGSTRING("CSummoner::Fire")}, + {0x015b0005, -1, CEntity::pEventHandler(&CSummoner::H0x015b0005_Fire_01), DEBUGSTRING("CSummoner::H0x015b0005_Fire_01")}, + {0x015b0006, -1, CEntity::pEventHandler(&CSummoner::H0x015b0006_Fire_02), DEBUGSTRING("CSummoner::H0x015b0006_Fire_02")}, + {0x015b0007, -1, CEntity::pEventHandler(&CSummoner::H0x015b0007_Fire_03), DEBUGSTRING("CSummoner::H0x015b0007_Fire_03")}, + {0x015b0008, -1, CEntity::pEventHandler(&CSummoner::H0x015b0008_Fire_04), DEBUGSTRING("CSummoner::H0x015b0008_Fire_04")}, + {0x015b0009, -1, CEntity::pEventHandler(&CSummoner::H0x015b0009_Fire_05), DEBUGSTRING("CSummoner::H0x015b0009_Fire_05")}, + {0x015b000a, -1, CEntity::pEventHandler(&CSummoner::H0x015b000a_Fire_06), DEBUGSTRING("CSummoner::H0x015b000a_Fire_06")}, + {0x015b000b, -1, CEntity::pEventHandler(&CSummoner::H0x015b000b_Fire_07), DEBUGSTRING("CSummoner::H0x015b000b_Fire_07")}, + {0x015b000c, -1, CEntity::pEventHandler(&CSummoner::H0x015b000c_Fire_08), DEBUGSTRING("CSummoner::H0x015b000c_Fire_08")}, + {0x015b000d, -1, CEntity::pEventHandler(&CSummoner::H0x015b000d_Fire_09), DEBUGSTRING("CSummoner::H0x015b000d_Fire_09")}, + {0x015b000e, -1, CEntity::pEventHandler(&CSummoner::H0x015b000e_Fire_10), DEBUGSTRING("CSummoner::H0x015b000e_Fire_10")}, + {0x015b000f, -1, CEntity::pEventHandler(&CSummoner::H0x015b000f_Fire_11), DEBUGSTRING("CSummoner::H0x015b000f_Fire_11")}, + {0x015b0010, -1, CEntity::pEventHandler(&CSummoner::H0x015b0010_Fire_12), DEBUGSTRING("CSummoner::H0x015b0010_Fire_12")}, + {0x015b0011, -1, CEntity::pEventHandler(&CSummoner::H0x015b0011_Fire_13), DEBUGSTRING("CSummoner::H0x015b0011_Fire_13")}, + {0x015b0012, -1, CEntity::pEventHandler(&CSummoner::H0x015b0012_Fire_14), DEBUGSTRING("CSummoner::H0x015b0012_Fire_14")}, + {0x015b0013, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CSummoner:: +#line 947 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Hit),DEBUGSTRING("CSummoner::Hit")}, + {0x015b0014, STATE_CEnemyBase_Die, CEntity::pEventHandler(&CSummoner:: +#line 956 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Die),DEBUGSTRING("CSummoner::Die")}, + {0x015b0015, -1, CEntity::pEventHandler(&CSummoner::H0x015b0015_Die_01), DEBUGSTRING("CSummoner::H0x015b0015_Die_01")}, + {0x015b0016, -1, CEntity::pEventHandler(&CSummoner::H0x015b0016_Die_02), DEBUGSTRING("CSummoner::H0x015b0016_Die_02")}, + {0x015b0017, -1, CEntity::pEventHandler(&CSummoner::H0x015b0017_Die_03), DEBUGSTRING("CSummoner::H0x015b0017_Die_03")}, + {0x015b0018, -1, CEntity::pEventHandler(&CSummoner::H0x015b0018_Die_04), DEBUGSTRING("CSummoner::H0x015b0018_Die_04")}, + {0x015b0019, -1, CEntity::pEventHandler(&CSummoner::H0x015b0019_Die_05), DEBUGSTRING("CSummoner::H0x015b0019_Die_05")}, + {0x015b001a, -1, CEntity::pEventHandler(&CSummoner::H0x015b001a_Die_06), DEBUGSTRING("CSummoner::H0x015b001a_Die_06")}, + {0x015b001b, -1, CEntity::pEventHandler(&CSummoner::H0x015b001b_Die_07), DEBUGSTRING("CSummoner::H0x015b001b_Die_07")}, + {0x015b001c, -1, CEntity::pEventHandler(&CSummoner::H0x015b001c_Die_08), DEBUGSTRING("CSummoner::H0x015b001c_Die_08")}, + {0x015b001d, -1, CEntity::pEventHandler(&CSummoner::H0x015b001d_Die_09), DEBUGSTRING("CSummoner::H0x015b001d_Die_09")}, + {0x015b001e, -1, CEntity::pEventHandler(&CSummoner::H0x015b001e_Die_10), DEBUGSTRING("CSummoner::H0x015b001e_Die_10")}, + {0x015b001f, -1, CEntity::pEventHandler(&CSummoner::H0x015b001f_Die_11), DEBUGSTRING("CSummoner::H0x015b001f_Die_11")}, + {0x015b0020, -1, CEntity::pEventHandler(&CSummoner::H0x015b0020_Die_12), DEBUGSTRING("CSummoner::H0x015b0020_Die_12")}, + {0x015b0021, -1, CEntity::pEventHandler(&CSummoner:: +#line 1101 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +TeleportToDeathMarker),DEBUGSTRING("CSummoner::TeleportToDeathMarker")}, + {0x015b0022, -1, CEntity::pEventHandler(&CSummoner::H0x015b0022_TeleportToDeathMarker_01), DEBUGSTRING("CSummoner::H0x015b0022_TeleportToDeathMarker_01")}, + {0x015b0023, -1, CEntity::pEventHandler(&CSummoner::H0x015b0023_TeleportToDeathMarker_02), DEBUGSTRING("CSummoner::H0x015b0023_TeleportToDeathMarker_02")}, + {0x015b0024, -1, CEntity::pEventHandler(&CSummoner::H0x015b0024_TeleportToDeathMarker_03), DEBUGSTRING("CSummoner::H0x015b0024_TeleportToDeathMarker_03")}, + {0x015b0025, -1, CEntity::pEventHandler(&CSummoner::H0x015b0025_TeleportToDeathMarker_04), DEBUGSTRING("CSummoner::H0x015b0025_TeleportToDeathMarker_04")}, + {0x015b0026, -1, CEntity::pEventHandler(&CSummoner::H0x015b0026_TeleportToDeathMarker_05), DEBUGSTRING("CSummoner::H0x015b0026_TeleportToDeathMarker_05")}, + {0x015b0027, -1, CEntity::pEventHandler(&CSummoner::H0x015b0027_TeleportToDeathMarker_06), DEBUGSTRING("CSummoner::H0x015b0027_TeleportToDeathMarker_06")}, + {0x015b0028, -1, CEntity::pEventHandler(&CSummoner::H0x015b0028_TeleportToDeathMarker_07), DEBUGSTRING("CSummoner::H0x015b0028_TeleportToDeathMarker_07")}, + {0x015b0029, -1, CEntity::pEventHandler(&CSummoner::H0x015b0029_TeleportToDeathMarker_08), DEBUGSTRING("CSummoner::H0x015b0029_TeleportToDeathMarker_08")}, + {0x015b002a, -1, CEntity::pEventHandler(&CSummoner:: +#line 1150 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +BossAppear),DEBUGSTRING("CSummoner::BossAppear")}, + {0x015b002b, STATE_CEnemyBase_PreMainLoop, CEntity::pEventHandler(&CSummoner:: +#line 1156 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +PreMainLoop),DEBUGSTRING("CSummoner::PreMainLoop")}, + {0x015b002c, -1, CEntity::pEventHandler(&CSummoner::H0x015b002c_PreMainLoop_01), DEBUGSTRING("CSummoner::H0x015b002c_PreMainLoop_01")}, + {0x015b002d, -1, CEntity::pEventHandler(&CSummoner::H0x015b002d_PreMainLoop_02), DEBUGSTRING("CSummoner::H0x015b002d_PreMainLoop_02")}, + {0x015b002e, -1, CEntity::pEventHandler(&CSummoner:: +#line 1162 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Immaterial),DEBUGSTRING("CSummoner::Immaterial")}, + {0x015b002f, -1, CEntity::pEventHandler(&CSummoner::H0x015b002f_Immaterial_01), DEBUGSTRING("CSummoner::H0x015b002f_Immaterial_01")}, + {0x015b0030, -1, CEntity::pEventHandler(&CSummoner::H0x015b0030_Immaterial_02), DEBUGSTRING("CSummoner::H0x015b0030_Immaterial_02")}, + {0x015b0031, -1, CEntity::pEventHandler(&CSummoner::H0x015b0031_Immaterial_03), DEBUGSTRING("CSummoner::H0x015b0031_Immaterial_03")}, + {0x015b0032, -1, CEntity::pEventHandler(&CSummoner::H0x015b0032_Immaterial_04), DEBUGSTRING("CSummoner::H0x015b0032_Immaterial_04")}, + {0x015b0033, -1, CEntity::pEventHandler(&CSummoner:: +#line 1227 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +SummonerLoop),DEBUGSTRING("CSummoner::SummonerLoop")}, + {0x015b0034, -1, CEntity::pEventHandler(&CSummoner::H0x015b0034_SummonerLoop_01), DEBUGSTRING("CSummoner::H0x015b0034_SummonerLoop_01")}, + {0x015b0035, -1, CEntity::pEventHandler(&CSummoner::H0x015b0035_SummonerLoop_02), DEBUGSTRING("CSummoner::H0x015b0035_SummonerLoop_02")}, + {1, -1, CEntity::pEventHandler(&CSummoner:: +#line 1269 "D:/SE1_GPL/Sources/EntitiesMP/Summoner.es" +Main),DEBUGSTRING("CSummoner::Main")}, + {0x015b0036, -1, CEntity::pEventHandler(&CSummoner::H0x015b0036_Main_01), DEBUGSTRING("CSummoner::H0x015b0036_Main_01")}, + {0x015b0037, -1, CEntity::pEventHandler(&CSummoner::H0x015b0037_Main_02), DEBUGSTRING("CSummoner::H0x015b0037_Main_02")}, + {0x015b0038, -1, CEntity::pEventHandler(&CSummoner::H0x015b0038_Main_03), DEBUGSTRING("CSummoner::H0x015b0038_Main_03")}, + {0x015b0039, -1, CEntity::pEventHandler(&CSummoner::H0x015b0039_Main_04), DEBUGSTRING("CSummoner::H0x015b0039_Main_04")}, + {0x015b003a, -1, CEntity::pEventHandler(&CSummoner::H0x015b003a_Main_05), DEBUGSTRING("CSummoner::H0x015b003a_Main_05")}, + {0x015b003b, -1, CEntity::pEventHandler(&CSummoner::H0x015b003b_Main_06), DEBUGSTRING("CSummoner::H0x015b003b_Main_06")}, +}; +#define CSummoner_handlersct ARRAYCOUNT(CSummoner_handlers) + +CEntity *CSummoner_New(void) { return new CSummoner; }; +void CSummoner_OnInitClass(void) {}; +void CSummoner_OnEndClass(void) {}; +void CSummoner_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CSummoner_OnWorldEnd(CWorld *pwo) {}; +void CSummoner_OnWorldInit(CWorld *pwo) {}; +void CSummoner_OnWorldTick(CWorld *pwo) {}; +void CSummoner_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CSummoner, CEnemyBase, "Summoner", "Thumbnails\\Summoner.tbn", 0x0000015b); +DECLARE_CTFILENAME(_fnmCSummoner_tbn, "Thumbnails\\Summoner.tbn"); diff --git a/Sources/EntitiesMP/Switch.cpp b/Sources/EntitiesMP/Switch.cpp new file mode 100644 index 0000000..c330254 --- /dev/null +++ b/Sources/EntitiesMP/Switch.cpp @@ -0,0 +1,333 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" + +#include "StdH.h" + +#include +#include +void CSwitch::SetDefaultProperties(void) { + m_iModelONAnimation = 0; + m_iTextureONAnimation = 0; + m_iModelOFFAnimation = 0; + m_iTextureOFFAnimation = 0; + m_penTarget = NULL; + m_eetEvent = EET_START ; + m_eetOffEvent = EET_IGNORE ; + m_penOffTarget = NULL; + m_swtType = SWT_ONOFF ; + m_strMessage = ""; + m_bSwitchON = FALSE ; + m_penCaused = NULL; + m_bUseable = FALSE ; + m_bInvisible = FALSE ; + CModelHolder2::SetDefaultProperties(); +} + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +CAnimData * CSwitch::GetAnimData(SLONG slPropertyOffset) +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +{ +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(slPropertyOffset == offsetof (CSwitch , m_iModelONAnimation ) || +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +slPropertyOffset == offsetof (CSwitch , m_iModelOFFAnimation )){ +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return GetModelObject () -> GetData (); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}else if(slPropertyOffset == offsetof (CSwitch , m_iTextureONAnimation ) || +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +slPropertyOffset == offsetof (CSwitch , m_iTextureOFFAnimation )){ +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return GetModelObject () -> mo_toTexture . GetData (); +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}else { +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return CModelHolder2 :: GetAnimData (slPropertyOffset ); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +BOOL CSwitch::CanReactOnEntity(CEntity * pen) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +{ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(pen == NULL ){ +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return FALSE ; +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(! (pen -> GetFlags () & ENF_ALIVE )){ +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return FALSE ; +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return TRUE ; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SLONG CSwitch::GetUsedMemory(void) +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +{ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SLONG slUsedMemory = sizeof (CSwitch ) - sizeof (CModelHolder2 ) + CModelHolder2 :: GetUsedMemory (); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +slUsedMemory += m_strMessage . Length (); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return slUsedMemory ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +BOOL CSwitch:: +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SwitchON(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSwitch_SwitchON + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSwitch::SwitchON expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(m_bSwitchON ){ +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Return(STATE_CURRENT,EVoid()); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return TRUE; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +GetModelObject () -> PlayAnim (m_iModelONAnimation , 0); +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +GetModelObject () -> mo_toTexture . PlayAnim (m_iTextureONAnimation , 0); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bSwitchON = TRUE ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SendToTarget (m_penTarget , m_eetEvent , m_penCaused ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (m_iModelONAnimation )); +Jump(STATE_CURRENT, 0x00d10001, FALSE, EBegin());return TRUE;}BOOL CSwitch::H0x00d10001_SwitchON_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d10001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x00d10002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +return FALSE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}return TRUE;}BOOL CSwitch::H0x00d10002_SwitchON_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d10002 + +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Return(STATE_CURRENT,EReturn ()); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSwitch:: +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SwitchOFF(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSwitch_SwitchOFF + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSwitch::SwitchOFF expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(! m_bSwitchON ){ +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Return(STATE_CURRENT,EVoid()); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return TRUE; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +GetModelObject () -> PlayAnim (m_iModelOFFAnimation , 0); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +GetModelObject () -> mo_toTexture . PlayAnim (m_iTextureOFFAnimation , 0); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bSwitchON = FALSE ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(m_penOffTarget != NULL ) +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +{ +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SendToTarget (m_penOffTarget , m_eetOffEvent , m_penCaused ); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +else +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +{ +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SendToTarget (m_penTarget , m_eetOffEvent , m_penCaused ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (m_iModelOFFAnimation )); +Jump(STATE_CURRENT, 0x00d10004, FALSE, EBegin());return TRUE;}BOOL CSwitch::H0x00d10004_SwitchOFF_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d10004 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x00d10005, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +return FALSE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}return TRUE;}BOOL CSwitch::H0x00d10005_SwitchOFF_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d10005 + +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Return(STATE_CURRENT,EReturn ()); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CSwitch:: +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +MainLoop_Once(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSwitch_MainLoop_Once + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSwitch::MainLoop_Once expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bUseable = TRUE ; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00d10007, FALSE, EBegin());return TRUE;}BOOL CSwitch::H0x00d10007_MainLoop_Once_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d10007 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(CanReactOnEntity (eTrigger . penCaused ) && m_bUseable ){ +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bUseable = FALSE ; +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_penCaused = eTrigger . penCaused ; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Call(STATE_CURRENT, STATE_CSwitch_SwitchON, TRUE, EVoid());return TRUE; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; + +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bUseable = FALSE ; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Call(STATE_CURRENT, STATE_CSwitch_SwitchON, TRUE, EVoid());return TRUE; +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bUseable = FALSE ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Call(STATE_CURRENT, STATE_CSwitch_SwitchOFF, TRUE, EVoid());return TRUE; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; + +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bUseable = ! m_bSwitchON ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return TRUE; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}return TRUE;}BOOL CSwitch::H0x00d10008_MainLoop_Once_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d10008 + ASSERT(FALSE); return TRUE;};BOOL CSwitch:: +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +MainLoop_OnOff(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSwitch_MainLoop_OnOff + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSwitch::MainLoop_OnOff expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bUseable = TRUE ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00d1000a, FALSE, EBegin());return TRUE;}BOOL CSwitch::H0x00d1000a_MainLoop_OnOff_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d1000a +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(CanReactOnEntity (eTrigger . penCaused ) && m_bUseable ){ +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bUseable = FALSE ; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_penCaused = eTrigger . penCaused ; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(m_bSwitchON ){ +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Call(STATE_CURRENT, STATE_CSwitch_SwitchOFF, TRUE, EVoid());return TRUE; +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}else { +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Call(STATE_CURRENT, STATE_CSwitch_SwitchON, TRUE, EVoid());return TRUE; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; + +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bUseable = FALSE ; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Call(STATE_CURRENT, STATE_CSwitch_SwitchON, TRUE, EVoid());return TRUE; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bUseable = FALSE ; +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Call(STATE_CURRENT, STATE_CSwitch_SwitchOFF, TRUE, EVoid());return TRUE; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; + +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(m_penDestruction != NULL ){ +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Jump(STATE_CURRENT, STATE_CModelHolder2_Die, FALSE, EVoid());return TRUE; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return TRUE; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn):{const EReturn&e= (EReturn&)__eeInput; + +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +m_bUseable = TRUE ; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return TRUE; +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}return TRUE;}BOOL CSwitch::H0x00d1000b_MainLoop_OnOff_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00d1000b + ASSERT(FALSE); return TRUE;};BOOL CSwitch:: +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CSwitch_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CSwitch::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +CModelHolder2 :: InitModelHolder (); +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(m_bInvisible ){ +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SwitchToEditorModel (); +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +if(m_swtType == SWT_ONCE ){ +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Jump(STATE_CURRENT, STATE_CSwitch_MainLoop_Once, TRUE, EVoid());return TRUE; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +}else { +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Jump(STATE_CURRENT, STATE_CSwitch_MainLoop_OnOff, TRUE, EVoid());return TRUE; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +} +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Return(STATE_CURRENT,EVoid()); +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Switch.es b/Sources/EntitiesMP/Switch.es new file mode 100644 index 0000000..2a68f5d --- /dev/null +++ b/Sources/EntitiesMP/Switch.es @@ -0,0 +1,231 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +209 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/ModelHolder2"; + +enum SwitchType { + 0 SWT_ONCE "Once", + 1 SWT_ONOFF "On/Off", +}; + +class CSwitch: CModelHolder2 { +name "Switch"; +thumbnail "Thumbnails\\Switch.tbn"; +features "HasName", "HasTarget", "IsTargetable"; + + +properties: + + 4 ANIMATION m_iModelONAnimation "Model ON animation" 'D' = 0, + 5 ANIMATION m_iTextureONAnimation "Texture ON animation" = 0, + 6 ANIMATION m_iModelOFFAnimation "Model OFF animation" 'G' = 0, + 7 ANIMATION m_iTextureOFFAnimation "Texture OFF animation" = 0, + + 10 CEntityPointer m_penTarget "ON-OFF Target" 'T' COLOR(C_dBLUE|0xFF), // send event to entity + 11 enum EventEType m_eetEvent "ON Event type" 'U' = EET_START, // type of event to send + 12 enum EventEType m_eetOffEvent "OFF Event type" 'I' = EET_IGNORE, // type of event to send + 13 CEntityPointer m_penOffTarget "OFF Target" COLOR(C_dBLUE|0xFF), // off target, if not null recives off event + + 18 enum SwitchType m_swtType "Type" 'Y' = SWT_ONOFF, + 19 CTString m_strMessage "Message" 'M' = "", + + // internal -> do not use + 20 BOOL m_bSwitchON = FALSE, + 21 CEntityPointer m_penCaused, // who triggered it last time + 22 BOOL m_bUseable = FALSE, // set while the switch can be triggered + 23 BOOL m_bInvisible "Invisible" = FALSE, // make it editor model + + +components: + + +functions: + + /* Get anim data for given animation property - return NULL for none. */ + CAnimData *GetAnimData(SLONG slPropertyOffset) + { + if (slPropertyOffset==offsetof(CSwitch, m_iModelONAnimation) || + slPropertyOffset==offsetof(CSwitch, m_iModelOFFAnimation)) { + return GetModelObject()->GetData(); + } else if (slPropertyOffset==offsetof(CSwitch, m_iTextureONAnimation) || + slPropertyOffset==offsetof(CSwitch, m_iTextureOFFAnimation)) { + return GetModelObject()->mo_toTexture.GetData(); + } else { + return CModelHolder2::GetAnimData(slPropertyOffset); + } + } + + // test if this door reacts on this entity + BOOL CanReactOnEntity(CEntity *pen) + { + if (pen==NULL) { + return FALSE; + } + // never react on non-live or dead entities + if (!(pen->GetFlags()&ENF_ALIVE)) { + return FALSE; + } + + return TRUE; + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CSwitch) - sizeof(CModelHolder2) + CModelHolder2::GetUsedMemory(); + // add some more + slUsedMemory += m_strMessage.Length(); + return slUsedMemory; + } + + + +procedures: + + + // turn the switch on + SwitchON() { + // if already on + if (m_bSwitchON) { + // do nothing + return; + } + // switch ON + GetModelObject()->PlayAnim(m_iModelONAnimation, 0); + GetModelObject()->mo_toTexture.PlayAnim(m_iTextureONAnimation, 0); + m_bSwitchON = TRUE; + // send event to target + SendToTarget(m_penTarget, m_eetEvent, m_penCaused); + // wait for anim end + wait(GetModelObject()->GetAnimLength(m_iModelONAnimation)) { + on (EBegin) : { resume; } on (ETimer) : { stop; } on (EDeath) : { pass; } otherwise(): { resume; } + } + + return EReturn(); // to notify that can be usable + }; + + // turn the switch off + SwitchOFF() { + // if already off + if (!m_bSwitchON) { + // do nothing + return; + } + // switch off + GetModelObject()->PlayAnim(m_iModelOFFAnimation, 0); + GetModelObject()->mo_toTexture.PlayAnim(m_iTextureOFFAnimation, 0); + m_bSwitchON = FALSE; + // if exists off target + if(m_penOffTarget!=NULL) + { + SendToTarget(m_penOffTarget, m_eetOffEvent, m_penCaused); + } + else + { + // send off event to target + SendToTarget(m_penTarget, m_eetOffEvent, m_penCaused); + } + // wait for anim end + wait(GetModelObject()->GetAnimLength(m_iModelOFFAnimation)) { + on (EBegin) : { resume; } on (ETimer) : { stop; } on (EDeath) : { pass; } otherwise(): { resume; } + } + + return EReturn(); // to notify that can be usable + }; + + MainLoop_Once() { + m_bUseable = TRUE; + + //main loop + wait() { + // trigger event -> change switch + on (ETrigger eTrigger) : { + if (CanReactOnEntity(eTrigger.penCaused) && m_bUseable) { + m_bUseable = FALSE; + m_penCaused = eTrigger.penCaused; + call SwitchON(); + } + } + // start -> switch ON + on (EStart) : { + m_bUseable = FALSE; + call SwitchON(); + } + // stop -> switch OFF + on (EStop) : { + m_bUseable = FALSE; + call SwitchOFF(); + } + on (EReturn) : { + m_bUseable = !m_bSwitchON; + resume; + } + } + }; + + MainLoop_OnOff() { + m_bUseable = TRUE; + + //main loop + wait() { + // trigger event -> change switch + on (ETrigger eTrigger) : { + if (CanReactOnEntity(eTrigger.penCaused) && m_bUseable) { + m_bUseable = FALSE; + m_penCaused = eTrigger.penCaused; + // if switch is ON make it OFF + if (m_bSwitchON) { + call SwitchOFF(); + // else if switch is OFF make it ON + } else { + call SwitchON(); + } + } + } + // start -> switch ON + on (EStart) : { + m_bUseable = FALSE; + call SwitchON(); + } + // stop -> switch OFF + on (EStop) : { + m_bUseable = FALSE; + call SwitchOFF(); + } + // when dead + on(EDeath): { + if (m_penDestruction!=NULL) { + jump CModelHolder2::Die(); + } + resume; + } + on (EReturn) : { + m_bUseable = TRUE; + resume; + } + } + }; + + Main() { + // init as model + CModelHolder2::InitModelHolder(); + + if (m_bInvisible) { + SwitchToEditorModel(); + } + + if (m_swtType==SWT_ONCE) { + jump MainLoop_Once(); + } else { + jump MainLoop_OnOff(); + } + + return; + }; +}; diff --git a/Sources/EntitiesMP/Switch.h b/Sources/EntitiesMP/Switch.h new file mode 100644 index 0000000..73ffe71 --- /dev/null +++ b/Sources/EntitiesMP/Switch.h @@ -0,0 +1,73 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Switch_INCLUDED +#define _EntitiesMP_Switch_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType SwitchType_enum; +enum SwitchType { + SWT_ONCE = 0, + SWT_ONOFF = 1, +}; +DECL_DLL inline void ClearToDefault(SwitchType &e) { e = (SwitchType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CSwitch_DLLClass; +class CSwitch : public CModelHolder2 { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual CEntity *GetTarget(void) const { return m_penTarget; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + ANIMATION m_iModelONAnimation; + ANIMATION m_iTextureONAnimation; + ANIMATION m_iModelOFFAnimation; + ANIMATION m_iTextureOFFAnimation; + CEntityPointer m_penTarget; + enum EventEType m_eetEvent; + enum EventEType m_eetOffEvent; + CEntityPointer m_penOffTarget; + enum SwitchType m_swtType; + CTString m_strMessage; + BOOL m_bSwitchON; + CEntityPointer m_penCaused; + BOOL m_bUseable; + BOOL m_bInvisible; + +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +CAnimData * GetAnimData(SLONG slPropertyOffset); + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +BOOL CanReactOnEntity(CEntity * pen); + +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SLONG GetUsedMemory(void); +#define STATE_CSwitch_SwitchON 0x00d10000 + BOOL +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SwitchON(const CEntityEvent &__eeInput); + BOOL H0x00d10001_SwitchON_01(const CEntityEvent &__eeInput); + BOOL H0x00d10002_SwitchON_02(const CEntityEvent &__eeInput); +#define STATE_CSwitch_SwitchOFF 0x00d10003 + BOOL +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SwitchOFF(const CEntityEvent &__eeInput); + BOOL H0x00d10004_SwitchOFF_01(const CEntityEvent &__eeInput); + BOOL H0x00d10005_SwitchOFF_02(const CEntityEvent &__eeInput); +#define STATE_CSwitch_MainLoop_Once 0x00d10006 + BOOL +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +MainLoop_Once(const CEntityEvent &__eeInput); + BOOL H0x00d10007_MainLoop_Once_01(const CEntityEvent &__eeInput); + BOOL H0x00d10008_MainLoop_Once_02(const CEntityEvent &__eeInput); +#define STATE_CSwitch_MainLoop_OnOff 0x00d10009 + BOOL +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +MainLoop_OnOff(const CEntityEvent &__eeInput); + BOOL H0x00d1000a_MainLoop_OnOff_01(const CEntityEvent &__eeInput); + BOOL H0x00d1000b_MainLoop_OnOff_02(const CEntityEvent &__eeInput); +#define STATE_CSwitch_Main 1 + BOOL +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Switch_INCLUDED diff --git a/Sources/EntitiesMP/Switch_tables.h b/Sources/EntitiesMP/Switch_tables.h new file mode 100644 index 0000000..d4e85a1 --- /dev/null +++ b/Sources/EntitiesMP/Switch_tables.h @@ -0,0 +1,72 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(SwitchType) + EP_ENUMVALUE(SWT_ONCE, "Once"), + EP_ENUMVALUE(SWT_ONOFF, "On/Off"), +EP_ENUMEND(SwitchType); + +#define ENTITYCLASS CSwitch + +CEntityProperty CSwitch_properties[] = { + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000d1<<8)+4, offsetof(CSwitch, m_iModelONAnimation), "Model ON animation", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000d1<<8)+5, offsetof(CSwitch, m_iTextureONAnimation), "Texture ON animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000d1<<8)+6, offsetof(CSwitch, m_iModelOFFAnimation), "Model OFF animation", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ANIMATION, NULL, (0x000000d1<<8)+7, offsetof(CSwitch, m_iTextureOFFAnimation), "Texture OFF animation", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d1<<8)+10, offsetof(CSwitch, m_penTarget), "ON-OFF Target", 'T', C_dBLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000d1<<8)+11, offsetof(CSwitch, m_eetEvent), "ON Event type", 'U', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000d1<<8)+12, offsetof(CSwitch, m_eetOffEvent), "OFF Event type", 'I', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d1<<8)+13, offsetof(CSwitch, m_penOffTarget), "OFF Target", 0, C_dBLUE | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &SwitchType_enum, (0x000000d1<<8)+18, offsetof(CSwitch, m_swtType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000d1<<8)+19, offsetof(CSwitch, m_strMessage), "Message", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d1<<8)+20, offsetof(CSwitch, m_bSwitchON), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000d1<<8)+21, offsetof(CSwitch, m_penCaused), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d1<<8)+22, offsetof(CSwitch, m_bUseable), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d1<<8)+23, offsetof(CSwitch, m_bInvisible), "Invisible", 0, 0x7F0000FFUL, 0), +}; +#define CSwitch_propertiesct ARRAYCOUNT(CSwitch_properties) + +CEntityComponent CSwitch_components[] = { + CEntityComponent() +}; +#define CSwitch_componentsct 0 + + +CEventHandlerEntry CSwitch_handlers[] = { + {0x00d10000, -1, CEntity::pEventHandler(&CSwitch:: +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SwitchON),DEBUGSTRING("CSwitch::SwitchON")}, + {0x00d10001, -1, CEntity::pEventHandler(&CSwitch::H0x00d10001_SwitchON_01), DEBUGSTRING("CSwitch::H0x00d10001_SwitchON_01")}, + {0x00d10002, -1, CEntity::pEventHandler(&CSwitch::H0x00d10002_SwitchON_02), DEBUGSTRING("CSwitch::H0x00d10002_SwitchON_02")}, + {0x00d10003, -1, CEntity::pEventHandler(&CSwitch:: +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +SwitchOFF),DEBUGSTRING("CSwitch::SwitchOFF")}, + {0x00d10004, -1, CEntity::pEventHandler(&CSwitch::H0x00d10004_SwitchOFF_01), DEBUGSTRING("CSwitch::H0x00d10004_SwitchOFF_01")}, + {0x00d10005, -1, CEntity::pEventHandler(&CSwitch::H0x00d10005_SwitchOFF_02), DEBUGSTRING("CSwitch::H0x00d10005_SwitchOFF_02")}, + {0x00d10006, -1, CEntity::pEventHandler(&CSwitch:: +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +MainLoop_Once),DEBUGSTRING("CSwitch::MainLoop_Once")}, + {0x00d10007, -1, CEntity::pEventHandler(&CSwitch::H0x00d10007_MainLoop_Once_01), DEBUGSTRING("CSwitch::H0x00d10007_MainLoop_Once_01")}, + {0x00d10008, -1, CEntity::pEventHandler(&CSwitch::H0x00d10008_MainLoop_Once_02), DEBUGSTRING("CSwitch::H0x00d10008_MainLoop_Once_02")}, + {0x00d10009, -1, CEntity::pEventHandler(&CSwitch:: +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +MainLoop_OnOff),DEBUGSTRING("CSwitch::MainLoop_OnOff")}, + {0x00d1000a, -1, CEntity::pEventHandler(&CSwitch::H0x00d1000a_MainLoop_OnOff_01), DEBUGSTRING("CSwitch::H0x00d1000a_MainLoop_OnOff_01")}, + {0x00d1000b, -1, CEntity::pEventHandler(&CSwitch::H0x00d1000b_MainLoop_OnOff_02), DEBUGSTRING("CSwitch::H0x00d1000b_MainLoop_OnOff_02")}, + {1, -1, CEntity::pEventHandler(&CSwitch:: +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Switch.es" +Main),DEBUGSTRING("CSwitch::Main")}, +}; +#define CSwitch_handlersct ARRAYCOUNT(CSwitch_handlers) + +CEntity *CSwitch_New(void) { return new CSwitch; }; +void CSwitch_OnInitClass(void) {}; +void CSwitch_OnEndClass(void) {}; +void CSwitch_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CSwitch_OnWorldEnd(CWorld *pwo) {}; +void CSwitch_OnWorldInit(CWorld *pwo) {}; +void CSwitch_OnWorldTick(CWorld *pwo) {}; +void CSwitch_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CSwitch, CModelHolder2, "Switch", "Thumbnails\\Switch.tbn", 0x000000d1); +DECLARE_CTFILENAME(_fnmCSwitch_tbn, "Thumbnails\\Switch.tbn"); diff --git a/Sources/EntitiesMP/TacticsChanger.cpp b/Sources/EntitiesMP/TacticsChanger.cpp new file mode 100644 index 0000000..71703c9 --- /dev/null +++ b/Sources/EntitiesMP/TacticsChanger.cpp @@ -0,0 +1,121 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" + +#include "StdH.h" +#include "TacticsHolder.h" + +#include +#include +void CTacticsChanger::SetDefaultProperties(void) { + m_strName = "TacticsChanger"; + m_strDescription = ""; + m_tctType = TCT_NONE ; + m_fParam1 = 0.0f; + m_fParam2 = 0.0f; + m_fParam3 = 0.0f; + m_fParam4 = 0.0f; + m_fParam5 = 0.0f; + m_penTacticsHolder = NULL; + CRationalEntity::SetDefaultProperties(); +} + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +const CTString & CTacticsChanger::GetDescription(void)const { +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +return m_strDescription ; +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +} +BOOL CTacticsChanger:: +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTacticsChanger_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTacticsChanger::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +InitAsEditorModel (); +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +SetModel (MODEL_MANAGER ); +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +SetModelMainTexture (TEXTURE_MANAGER ); +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00ec0000, FALSE, EBegin());return TRUE;}BOOL CTacticsChanger::H0x00ec0000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ec0000 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00ec0001, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTacticsChanger::H0x00ec0001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ec0001 +; +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +Jump(STATE_CURRENT,0x00ec0006, FALSE, EInternal());return TRUE;}BOOL CTacticsChanger::H0x00ec0006_Main_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ec0006 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00ec0007, FALSE, EInternal());return TRUE;} +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00ec0002, FALSE, EBegin());return TRUE;}BOOL CTacticsChanger::H0x00ec0002_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ec0002 +switch(__eeInput.ee_slEvent) +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +{case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; + +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +if(m_penTacticsHolder != NULL ){ +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +CTacticsHolder * penTactics = & (CTacticsHolder &) * m_penTacticsHolder ; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +penTactics -> m_tctType = m_tctType ; +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +penTactics -> m_fParam1 = m_fParam1 ; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +penTactics -> m_fParam2 = m_fParam2 ; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +penTactics -> m_fParam3 = m_fParam3 ; +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +penTactics -> m_fParam4 = m_fParam4 ; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +penTactics -> m_fParam5 = m_fParam5 ; +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +penTactics -> m_tmLastActivation = _pTimer -> CurrentTick (); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +} +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +UnsetTimer();Jump(STATE_CURRENT,0x00ec0003, FALSE, EInternal());return TRUE; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +}ASSERT(FALSE);break;default:{ +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +return TRUE; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +}ASSERT(FALSE);break; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +}return TRUE;}BOOL CTacticsChanger::H0x00ec0003_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ec0003 +; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00ec0004, FALSE, EBegin());return TRUE;}BOOL CTacticsChanger::H0x00ec0004_Main_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ec0004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00ec0005, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTacticsChanger::H0x00ec0005_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ec0005 +;Jump(STATE_CURRENT,0x00ec0006, FALSE, EInternal());return TRUE; +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +}BOOL CTacticsChanger::H0x00ec0007_Main_08(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ec0007 + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/TacticsChanger.es b/Sources/EntitiesMP/TacticsChanger.es new file mode 100644 index 0000000..b262ff8 --- /dev/null +++ b/Sources/EntitiesMP/TacticsChanger.es @@ -0,0 +1,76 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +236 +%{ +#include "StdH.h" +#include "TacticsHolder.h" +%} + +class CTacticsChanger : CRationalEntity { +name "TacticsChanger"; +thumbnail "Thumbnails\\TacticsChanger.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "TacticsChanger", + 2 CTString m_strDescription = "", + + 10 enum TacticType m_tctType "Type" 'Y' = TCT_NONE, // tactic type + 11 FLOAT m_fParam1 "Parameter 1" 'D' = 0.0f, // parameter 1 + 12 FLOAT m_fParam2 "Parameter 2" 'F' = 0.0f, // parameter 2 + 13 FLOAT m_fParam3 "Parameter 3" 'G' = 0.0f, // parameter 3 + 14 FLOAT m_fParam4 "Parameter 4" 'H' = 0.0f, // parameter 4 + 15 FLOAT m_fParam5 "Parameter 5" 'J' = 0.0f, // parameter 5 +/*16 BOOL m_bRetryOnBlock "Retry tactic when blocked" = FALSE, + 17 INDEX m_bRetryCount "Number of retries" = 1, */ + 18 CEntityPointer m_penTacticsHolder "Tactics holder" 'H', + + +components: + 1 model MODEL_MANAGER "ModelsMP\\Editor\\TacticsChanger.mdl", + 2 texture TEXTURE_MANAGER "ModelsMP\\Editor\\TacticsChanger.tex" + +functions: + const CTString &GetDescription(void) const { + return m_strDescription; + } + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MANAGER); + SetModelMainTexture(TEXTURE_MANAGER); + + autowait(0.1f); + + while(TRUE) { + wait() + { + on (ETrigger) : { + if (m_penTacticsHolder!=NULL) { + CTacticsHolder *penTactics = &(CTacticsHolder &)*m_penTacticsHolder; + penTactics->m_tctType = m_tctType; + penTactics->m_fParam1 = m_fParam1; + penTactics->m_fParam2 = m_fParam2; + penTactics->m_fParam3 = m_fParam3; + penTactics->m_fParam4 = m_fParam4; + penTactics->m_fParam5 = m_fParam5; + penTactics->m_tmLastActivation = _pTimer->CurrentTick(); + } + stop; + } + otherwise() : { + resume; + } + }; + + // wait a bit to recover + autowait(0.1f); + } + } +}; diff --git a/Sources/EntitiesMP/TacticsChanger.h b/Sources/EntitiesMP/TacticsChanger.h new file mode 100644 index 0000000..800e14d --- /dev/null +++ b/Sources/EntitiesMP/TacticsChanger.h @@ -0,0 +1,38 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_TacticsChanger_INCLUDED +#define _EntitiesMP_TacticsChanger_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CTacticsChanger_DLLClass; +class CTacticsChanger : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + enum TacticType m_tctType; + FLOAT m_fParam1; + FLOAT m_fParam2; + FLOAT m_fParam3; + FLOAT m_fParam4; + FLOAT m_fParam5; + CEntityPointer m_penTacticsHolder; + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +const CTString & GetDescription(void)const; +#define STATE_CTacticsChanger_Main 1 + BOOL +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00ec0000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00ec0001_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00ec0002_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00ec0003_Main_04(const CEntityEvent &__eeInput); + BOOL H0x00ec0004_Main_05(const CEntityEvent &__eeInput); + BOOL H0x00ec0005_Main_06(const CEntityEvent &__eeInput); + BOOL H0x00ec0006_Main_07(const CEntityEvent &__eeInput); + BOOL H0x00ec0007_Main_08(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_TacticsChanger_INCLUDED diff --git a/Sources/EntitiesMP/TacticsChanger_tables.h b/Sources/EntitiesMP/TacticsChanger_tables.h new file mode 100644 index 0000000..07b015e --- /dev/null +++ b/Sources/EntitiesMP/TacticsChanger_tables.h @@ -0,0 +1,52 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CTacticsChanger + +CEntityProperty CTacticsChanger_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ec<<8)+1, offsetof(CTacticsChanger, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ec<<8)+2, offsetof(CTacticsChanger, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &TacticType_enum, (0x000000ec<<8)+10, offsetof(CTacticsChanger, m_tctType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ec<<8)+11, offsetof(CTacticsChanger, m_fParam1), "Parameter 1", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ec<<8)+12, offsetof(CTacticsChanger, m_fParam2), "Parameter 2", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ec<<8)+13, offsetof(CTacticsChanger, m_fParam3), "Parameter 3", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ec<<8)+14, offsetof(CTacticsChanger, m_fParam4), "Parameter 4", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ec<<8)+15, offsetof(CTacticsChanger, m_fParam5), "Parameter 5", 'J', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000ec<<8)+18, offsetof(CTacticsChanger, m_penTacticsHolder), "Tactics holder", 'H', 0x7F0000FFUL, 0), +}; +#define CTacticsChanger_propertiesct ARRAYCOUNT(CTacticsChanger_properties) + +CEntityComponent CTacticsChanger_components[] = { +#define MODEL_MANAGER ((0x000000ec<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MANAGER, "EFNM" "ModelsMP\\Editor\\TacticsChanger.mdl"), +#define TEXTURE_MANAGER ((0x000000ec<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MANAGER, "EFNM" "ModelsMP\\Editor\\TacticsChanger.tex"), +}; +#define CTacticsChanger_componentsct ARRAYCOUNT(CTacticsChanger_components) + +CEventHandlerEntry CTacticsChanger_handlers[] = { + {1, -1, CEntity::pEventHandler(&CTacticsChanger:: +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/TacticsChanger.es" +Main),DEBUGSTRING("CTacticsChanger::Main")}, + {0x00ec0000, -1, CEntity::pEventHandler(&CTacticsChanger::H0x00ec0000_Main_01), DEBUGSTRING("CTacticsChanger::H0x00ec0000_Main_01")}, + {0x00ec0001, -1, CEntity::pEventHandler(&CTacticsChanger::H0x00ec0001_Main_02), DEBUGSTRING("CTacticsChanger::H0x00ec0001_Main_02")}, + {0x00ec0002, -1, CEntity::pEventHandler(&CTacticsChanger::H0x00ec0002_Main_03), DEBUGSTRING("CTacticsChanger::H0x00ec0002_Main_03")}, + {0x00ec0003, -1, CEntity::pEventHandler(&CTacticsChanger::H0x00ec0003_Main_04), DEBUGSTRING("CTacticsChanger::H0x00ec0003_Main_04")}, + {0x00ec0004, -1, CEntity::pEventHandler(&CTacticsChanger::H0x00ec0004_Main_05), DEBUGSTRING("CTacticsChanger::H0x00ec0004_Main_05")}, + {0x00ec0005, -1, CEntity::pEventHandler(&CTacticsChanger::H0x00ec0005_Main_06), DEBUGSTRING("CTacticsChanger::H0x00ec0005_Main_06")}, + {0x00ec0006, -1, CEntity::pEventHandler(&CTacticsChanger::H0x00ec0006_Main_07), DEBUGSTRING("CTacticsChanger::H0x00ec0006_Main_07")}, + {0x00ec0007, -1, CEntity::pEventHandler(&CTacticsChanger::H0x00ec0007_Main_08), DEBUGSTRING("CTacticsChanger::H0x00ec0007_Main_08")}, +}; +#define CTacticsChanger_handlersct ARRAYCOUNT(CTacticsChanger_handlers) + +CEntity *CTacticsChanger_New(void) { return new CTacticsChanger; }; +void CTacticsChanger_OnInitClass(void) {}; +void CTacticsChanger_OnEndClass(void) {}; +void CTacticsChanger_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CTacticsChanger_OnWorldEnd(CWorld *pwo) {}; +void CTacticsChanger_OnWorldInit(CWorld *pwo) {}; +void CTacticsChanger_OnWorldTick(CWorld *pwo) {}; +void CTacticsChanger_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CTacticsChanger, CRationalEntity, "TacticsChanger", "Thumbnails\\TacticsChanger.tbn", 0x000000ec); +DECLARE_CTFILENAME(_fnmCTacticsChanger_tbn, "Thumbnails\\TacticsChanger.tbn"); diff --git a/Sources/EntitiesMP/TacticsHolder.cpp b/Sources/EntitiesMP/TacticsHolder.cpp new file mode 100644 index 0000000..dd333c3 --- /dev/null +++ b/Sources/EntitiesMP/TacticsHolder.cpp @@ -0,0 +1,92 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" + +#include "StdH.h" + +#include +#include +void CTacticsHolder::SetDefaultProperties(void) { + m_strName = "TacticsHolder"; + m_strDescription = ""; + m_tctType = TCT_NONE ; + m_fParam1 = 0.0f; + m_fParam2 = 0.0f; + m_fParam3 = 0.0f; + m_fParam4 = 0.0f; + m_fParam5 = 0.0f; + m_tmLastActivation = 0.0f; + CRationalEntity::SetDefaultProperties(); +} + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +const CTString & CTacticsHolder::GetDescription(void)const { +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +return m_strDescription ; +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +} +BOOL CTacticsHolder:: +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTacticsHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTacticsHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +InitAsEditorModel (); +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +SetModel (MODEL_MANAGER ); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +SetModelMainTexture (TEXTURE_MANAGER ); +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +Jump(STATE_CURRENT,0x00eb0004, FALSE, EInternal());return TRUE;}BOOL CTacticsHolder::H0x00eb0004_Main_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00eb0004 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00eb0005, FALSE, EInternal());return TRUE;} +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00eb0000, FALSE, EBegin());return TRUE;}BOOL CTacticsHolder::H0x00eb0000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00eb0000 +switch(__eeInput.ee_slEvent) +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +{case(EVENTCODE_ETrigger):{const ETrigger&e= (ETrigger&)__eeInput; + +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +m_tmLastActivation = _pTimer -> CurrentTick (); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +UnsetTimer();Jump(STATE_CURRENT,0x00eb0001, FALSE, EInternal());return TRUE; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +}ASSERT(FALSE);break;default:{ +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +return TRUE; +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +}ASSERT(FALSE);break; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +}return TRUE;}BOOL CTacticsHolder::H0x00eb0001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00eb0001 +; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00eb0002, FALSE, EBegin());return TRUE;}BOOL CTacticsHolder::H0x00eb0002_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00eb0002 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00eb0003, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTacticsHolder::H0x00eb0003_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00eb0003 +;Jump(STATE_CURRENT,0x00eb0004, FALSE, EInternal());return TRUE; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +}BOOL CTacticsHolder::H0x00eb0005_Main_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00eb0005 + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/TacticsHolder.es b/Sources/EntitiesMP/TacticsHolder.es new file mode 100644 index 0000000..f50df19 --- /dev/null +++ b/Sources/EntitiesMP/TacticsHolder.es @@ -0,0 +1,72 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +235 +%{ +#include "StdH.h" +%} + + +enum TacticType { + 0 TCT_NONE "None", + 1 TCT_DAMP_ANGLE_STRIFE "Damp angle strafe", + 2 TCT_PARALLEL_RANDOM_DISTANCE "Parallel random distance", + 3 TCT_STATIC_RANDOM_V_DISTANCE "Static random V distance", +}; + +class CTacticsHolder : CRationalEntity { +name "TacticsHolder"; +thumbnail "Thumbnails\\TacticsHolder.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "TacticsHolder", + 2 CTString m_strDescription = "", + + 10 enum TacticType m_tctType "Type" 'Y' = TCT_NONE, // tactic type + 11 FLOAT m_fParam1 "Parameter 1" 'D' = 0.0f, // parameter 1 + 12 FLOAT m_fParam2 "Parameter 2" 'F' = 0.0f, // parameter 2 + 13 FLOAT m_fParam3 "Parameter 3" 'G' = 0.0f, // parameter 3 + 14 FLOAT m_fParam4 "Parameter 4" 'H' = 0.0f, // parameter 4 + 15 FLOAT m_fParam5 "Parameter 5" 'J' = 0.0f, // parameter 5 + /*16 BOOL m_bRetryOnBlock "Retry tactic when blocked" = FALSE, + 17 INDEX m_bRetryCount "Number of retries" = 1,*/ + + 20 FLOAT m_tmLastActivation = 0.0f, // internal - the last time when manager was triggered + +components: + 1 model MODEL_MANAGER "ModelsMP\\Editor\\TacticsHolder.mdl", + 2 texture TEXTURE_MANAGER "ModelsMP\\Editor\\TacticsHolder.tex" + +functions: + const CTString &GetDescription(void) const { + return m_strDescription; + } + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MANAGER); + SetModelMainTexture(TEXTURE_MANAGER); + + while(TRUE) { + wait() + { + on (ETrigger) : { + m_tmLastActivation = _pTimer->CurrentTick(); + stop; + } + otherwise() : { + resume; + } + }; + + // wait a bit to recover + autowait(0.1f); + } + } +}; diff --git a/Sources/EntitiesMP/TacticsHolder.h b/Sources/EntitiesMP/TacticsHolder.h new file mode 100644 index 0000000..f261b01 --- /dev/null +++ b/Sources/EntitiesMP/TacticsHolder.h @@ -0,0 +1,44 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_TacticsHolder_INCLUDED +#define _EntitiesMP_TacticsHolder_INCLUDED 1 +extern DECL_DLL CEntityPropertyEnumType TacticType_enum; +enum TacticType { + TCT_NONE = 0, + TCT_DAMP_ANGLE_STRIFE = 1, + TCT_PARALLEL_RANDOM_DISTANCE = 2, + TCT_STATIC_RANDOM_V_DISTANCE = 3, +}; +DECL_DLL inline void ClearToDefault(TacticType &e) { e = (TacticType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CTacticsHolder_DLLClass; +class CTacticsHolder : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + enum TacticType m_tctType; + FLOAT m_fParam1; + FLOAT m_fParam2; + FLOAT m_fParam3; + FLOAT m_fParam4; + FLOAT m_fParam5; + FLOAT m_tmLastActivation; + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +const CTString & GetDescription(void)const; +#define STATE_CTacticsHolder_Main 1 + BOOL +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00eb0000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00eb0001_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00eb0002_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00eb0003_Main_04(const CEntityEvent &__eeInput); + BOOL H0x00eb0004_Main_05(const CEntityEvent &__eeInput); + BOOL H0x00eb0005_Main_06(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_TacticsHolder_INCLUDED diff --git a/Sources/EntitiesMP/TacticsHolder_tables.h b/Sources/EntitiesMP/TacticsHolder_tables.h new file mode 100644 index 0000000..8c4c557 --- /dev/null +++ b/Sources/EntitiesMP/TacticsHolder_tables.h @@ -0,0 +1,57 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(TacticType) + EP_ENUMVALUE(TCT_NONE, "None"), + EP_ENUMVALUE(TCT_DAMP_ANGLE_STRIFE, "Damp angle strafe"), + EP_ENUMVALUE(TCT_PARALLEL_RANDOM_DISTANCE, "Parallel random distance"), + EP_ENUMVALUE(TCT_STATIC_RANDOM_V_DISTANCE, "Static random V distance"), +EP_ENUMEND(TacticType); + +#define ENTITYCLASS CTacticsHolder + +CEntityProperty CTacticsHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000eb<<8)+1, offsetof(CTacticsHolder, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000eb<<8)+2, offsetof(CTacticsHolder, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &TacticType_enum, (0x000000eb<<8)+10, offsetof(CTacticsHolder, m_tctType), "Type", 'Y', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000eb<<8)+11, offsetof(CTacticsHolder, m_fParam1), "Parameter 1", 'D', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000eb<<8)+12, offsetof(CTacticsHolder, m_fParam2), "Parameter 2", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000eb<<8)+13, offsetof(CTacticsHolder, m_fParam3), "Parameter 3", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000eb<<8)+14, offsetof(CTacticsHolder, m_fParam4), "Parameter 4", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000eb<<8)+15, offsetof(CTacticsHolder, m_fParam5), "Parameter 5", 'J', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000eb<<8)+20, offsetof(CTacticsHolder, m_tmLastActivation), "", 0, 0, 0), +}; +#define CTacticsHolder_propertiesct ARRAYCOUNT(CTacticsHolder_properties) + +CEntityComponent CTacticsHolder_components[] = { +#define MODEL_MANAGER ((0x000000eb<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MANAGER, "EFNM" "ModelsMP\\Editor\\TacticsHolder.mdl"), +#define TEXTURE_MANAGER ((0x000000eb<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MANAGER, "EFNM" "ModelsMP\\Editor\\TacticsHolder.tex"), +}; +#define CTacticsHolder_componentsct ARRAYCOUNT(CTacticsHolder_components) + +CEventHandlerEntry CTacticsHolder_handlers[] = { + {1, -1, CEntity::pEventHandler(&CTacticsHolder:: +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/TacticsHolder.es" +Main),DEBUGSTRING("CTacticsHolder::Main")}, + {0x00eb0000, -1, CEntity::pEventHandler(&CTacticsHolder::H0x00eb0000_Main_01), DEBUGSTRING("CTacticsHolder::H0x00eb0000_Main_01")}, + {0x00eb0001, -1, CEntity::pEventHandler(&CTacticsHolder::H0x00eb0001_Main_02), DEBUGSTRING("CTacticsHolder::H0x00eb0001_Main_02")}, + {0x00eb0002, -1, CEntity::pEventHandler(&CTacticsHolder::H0x00eb0002_Main_03), DEBUGSTRING("CTacticsHolder::H0x00eb0002_Main_03")}, + {0x00eb0003, -1, CEntity::pEventHandler(&CTacticsHolder::H0x00eb0003_Main_04), DEBUGSTRING("CTacticsHolder::H0x00eb0003_Main_04")}, + {0x00eb0004, -1, CEntity::pEventHandler(&CTacticsHolder::H0x00eb0004_Main_05), DEBUGSTRING("CTacticsHolder::H0x00eb0004_Main_05")}, + {0x00eb0005, -1, CEntity::pEventHandler(&CTacticsHolder::H0x00eb0005_Main_06), DEBUGSTRING("CTacticsHolder::H0x00eb0005_Main_06")}, +}; +#define CTacticsHolder_handlersct ARRAYCOUNT(CTacticsHolder_handlers) + +CEntity *CTacticsHolder_New(void) { return new CTacticsHolder; }; +void CTacticsHolder_OnInitClass(void) {}; +void CTacticsHolder_OnEndClass(void) {}; +void CTacticsHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CTacticsHolder_OnWorldEnd(CWorld *pwo) {}; +void CTacticsHolder_OnWorldInit(CWorld *pwo) {}; +void CTacticsHolder_OnWorldTick(CWorld *pwo) {}; +void CTacticsHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CTacticsHolder, CRationalEntity, "TacticsHolder", "Thumbnails\\TacticsHolder.tbn", 0x000000eb); +DECLARE_CTFILENAME(_fnmCTacticsHolder_tbn, "Thumbnails\\TacticsHolder.tbn"); diff --git a/Sources/EntitiesMP/Teleport.cpp b/Sources/EntitiesMP/Teleport.cpp new file mode 100644 index 0000000..cb5bf61 --- /dev/null +++ b/Sources/EntitiesMP/Teleport.cpp @@ -0,0 +1,185 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" + +#include "StdH.h" + +#include +#include +void CTeleport::SetDefaultProperties(void) { + m_strName = "Teleport"; + m_strDescription = ""; + m_penTarget = NULL; + m_fWidth = 2.0f; + m_fHeight = 3.0f; + m_bActive = TRUE ; + m_bPlayersOnly = TRUE ; + m_bForceStop = FALSE ; + CRationalEntity::SetDefaultProperties(); +} + +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +const CTString & CTeleport::GetDescription(void)const { +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +((CTString &) m_strDescription ) . PrintF ("->"); +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +if(m_penTarget != NULL ){ +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +((CTString &) m_strDescription ) . PrintF ("->%s" , m_penTarget -> GetName ()); +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +} +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +return m_strDescription ; +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +} + +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +void CTeleport::TeleportEntity(CEntity * pen,const CPlacement3D & pl) +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +{ +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +pen -> Teleport (pl ); +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +ESpawnEffect ese ; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +ese . betType = BET_TELEPORT ; +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +ese . vNormal = FLOAT3D (0 , 1 , 0); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +FLOATaabbox3D box ; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +pen -> GetBoundingBox (box ); +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +FLOAT fEntitySize = box . Size () . MaxNorm () * 2; +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +ese . vStretch = FLOAT3D (fEntitySize , fEntitySize , fEntitySize ); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +CEntityPointer penEffect = CreateEntity (pl , CLASS_BASIC_EFFECT ); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +penEffect -> Initialize (ese ); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +} + +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +SLONG CTeleport::GetUsedMemory(void) +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +{ +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +SLONG slUsedMemory = sizeof (CTeleport ) - sizeof (CRationalEntity ) + CRationalEntity :: GetUsedMemory (); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +slUsedMemory += m_strName . Length (); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +slUsedMemory += m_strDescription . Length (); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +return slUsedMemory ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +} +BOOL CTeleport:: +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTeleport_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTeleport::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +InitAsEditorModel (); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +SetCollisionFlags (ECF_TOUCHMODEL ); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +if(m_fHeight < m_fWidth ) +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +{ +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +m_fHeight = m_fWidth ; +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +} +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fWidth , m_fHeight , m_fWidth )); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +SetModel (MODEL_TELEPORT ); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +ModelChangeNotify (); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +SetModelMainTexture (TEXTURE_TELEPORT ); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +Jump(STATE_CURRENT,0x00db0004, FALSE, EInternal());return TRUE;}BOOL CTeleport::H0x00db0004_Main_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00db0004 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00db0005, FALSE, EInternal());return TRUE;} +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00db0000, FALSE, EBegin());return TRUE;}BOOL CTeleport::H0x00db0000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00db0000 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EPass):{const EPass&ePass= (EPass&)__eeInput; + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +if(m_penTarget != NULL && m_bActive ){ +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +if(m_bPlayersOnly && ! IsOfClass (ePass . penOther , "Player")){ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +return TRUE; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +} +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +TeleportEntity (ePass . penOther , m_penTarget -> GetPlacement ()); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +if(m_bForceStop && (ePass . penOther -> GetPhysicsFlags () & EPF_MOVABLE )){ +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +((CMovableEntity *) & * ePass . penOther ) -> ForceFullStop (); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +} +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +UnsetTimer();Jump(STATE_CURRENT,0x00db0001, FALSE, EInternal());return TRUE; +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +} +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +return TRUE; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +}ASSERT(FALSE);break;case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +m_bActive = TRUE ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +return TRUE; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +m_bActive = FALSE ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +return TRUE; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +}ASSERT(FALSE);break;default:{ +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +return TRUE; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +}ASSERT(FALSE);break; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +}return TRUE;}BOOL CTeleport::H0x00db0001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00db0001 +; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00db0002, FALSE, EBegin());return TRUE;}BOOL CTeleport::H0x00db0002_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00db0002 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00db0003, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTeleport::H0x00db0003_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00db0003 +;Jump(STATE_CURRENT,0x00db0004, FALSE, EInternal());return TRUE; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +}BOOL CTeleport::H0x00db0005_Main_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00db0005 + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Teleport.es b/Sources/EntitiesMP/Teleport.es new file mode 100644 index 0000000..39f7219 --- /dev/null +++ b/Sources/EntitiesMP/Teleport.es @@ -0,0 +1,131 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +219 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/BasicEffects"; + +class CTeleport : CRationalEntity { +name "Teleport"; +thumbnail "Thumbnails\\Teleport.tbn"; +features "HasName", "HasTarget", "IsTargetable", "IsImportant"; + + +properties: + + 1 CTString m_strName "Name" 'N' = "Teleport", + 3 CTString m_strDescription = "", + 2 CEntityPointer m_penTarget "Target" 'T' COLOR(C_BROWN|0xFF), + 4 FLOAT m_fWidth "Width" 'W' = 2.0f, + 5 FLOAT m_fHeight "Height" 'H' = 3.0f, + 6 BOOL m_bActive "Active" 'A' = TRUE, + 7 BOOL m_bPlayersOnly "Players only" 'P' = TRUE, + 8 BOOL m_bForceStop "Force stop" 'F' = FALSE, + + +components: + + 1 model MODEL_TELEPORT "Models\\Editor\\Teleport.mdl", + 2 texture TEXTURE_TELEPORT "Models\\Editor\\Teleport.tex", + 3 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + + +functions: + + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("->"); + if (m_penTarget!=NULL) { + ((CTString&)m_strDescription).PrintF("->%s", m_penTarget->GetName()); + } + return m_strDescription; + } + + void TeleportEntity(CEntity *pen, const CPlacement3D &pl) + { + // teleport back + pen->Teleport(pl); + + // spawn teleport effect + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.betType = BET_TELEPORT; + ese.vNormal = FLOAT3D(0,1,0); + FLOATaabbox3D box; + pen->GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm()*2; + ese.vStretch = FLOAT3D(fEntitySize, fEntitySize, fEntitySize); + CEntityPointer penEffect = CreateEntity(pl, CLASS_BASIC_EFFECT); + penEffect->Initialize(ese); + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CTeleport) - sizeof(CRationalEntity) + CRationalEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strName.Length(); + slUsedMemory += m_strDescription.Length(); + return slUsedMemory; + } + + +procedures: + + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_TOUCHMODEL); + + // correct height so teleport could collide as sphere + if(m_fHeightStretchModel(FLOAT3D(m_fWidth, m_fHeight, m_fWidth)); + SetModel(MODEL_TELEPORT); + ModelChangeNotify(); + SetModelMainTexture(TEXTURE_TELEPORT); + + while (TRUE) { + // wait to someone enter and teleport it + wait() { + on (EPass ePass) : { + if (m_penTarget!=NULL && m_bActive) { + if (m_bPlayersOnly && !IsOfClass(ePass.penOther, "Player")) { + resume; + } + TeleportEntity(ePass.penOther, m_penTarget->GetPlacement()); + if (m_bForceStop && (ePass.penOther->GetPhysicsFlags()&EPF_MOVABLE) ) { + ((CMovableEntity*)&*ePass.penOther)->ForceFullStop(); + } + stop; + } + resume; + } + on (EActivate) : { + m_bActive = TRUE; + resume; + } + on (EDeactivate) : { + m_bActive = FALSE; + resume; + } + otherwise() : { + resume; + }; + }; + + // wait a bit to recover + autowait(0.1f); + } + } +}; + diff --git a/Sources/EntitiesMP/Teleport.h b/Sources/EntitiesMP/Teleport.h new file mode 100644 index 0000000..805d079 --- /dev/null +++ b/Sources/EntitiesMP/Teleport.h @@ -0,0 +1,44 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Teleport_INCLUDED +#define _EntitiesMP_Teleport_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CTeleport_DLLClass; +class CTeleport : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual CEntity *GetTarget(void) const { return m_penTarget; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CEntityPointer m_penTarget; + FLOAT m_fWidth; + FLOAT m_fHeight; + BOOL m_bActive; + BOOL m_bPlayersOnly; + BOOL m_bForceStop; + +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +const CTString & GetDescription(void)const; + +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +void TeleportEntity(CEntity * pen,const CPlacement3D & pl); + +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +SLONG GetUsedMemory(void); +#define STATE_CTeleport_Main 1 + BOOL +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00db0000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00db0001_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00db0002_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00db0003_Main_04(const CEntityEvent &__eeInput); + BOOL H0x00db0004_Main_05(const CEntityEvent &__eeInput); + BOOL H0x00db0005_Main_06(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Teleport_INCLUDED diff --git a/Sources/EntitiesMP/Teleport_tables.h b/Sources/EntitiesMP/Teleport_tables.h new file mode 100644 index 0000000..6efc9a9 --- /dev/null +++ b/Sources/EntitiesMP/Teleport_tables.h @@ -0,0 +1,51 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CTeleport + +CEntityProperty CTeleport_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000db<<8)+1, offsetof(CTeleport, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000db<<8)+3, offsetof(CTeleport, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000db<<8)+2, offsetof(CTeleport, m_penTarget), "Target", 'T', C_BROWN | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000db<<8)+4, offsetof(CTeleport, m_fWidth), "Width", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000db<<8)+5, offsetof(CTeleport, m_fHeight), "Height", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000db<<8)+6, offsetof(CTeleport, m_bActive), "Active", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000db<<8)+7, offsetof(CTeleport, m_bPlayersOnly), "Players only", 'P', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000db<<8)+8, offsetof(CTeleport, m_bForceStop), "Force stop", 'F', 0x7F0000FFUL, 0), +}; +#define CTeleport_propertiesct ARRAYCOUNT(CTeleport_properties) + +CEntityComponent CTeleport_components[] = { +#define MODEL_TELEPORT ((0x000000db<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_TELEPORT, "EFNM" "Models\\Editor\\Teleport.mdl"), +#define TEXTURE_TELEPORT ((0x000000db<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_TELEPORT, "EFNM" "Models\\Editor\\Teleport.tex"), +#define CLASS_BASIC_EFFECT ((0x000000db<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +}; +#define CTeleport_componentsct ARRAYCOUNT(CTeleport_components) + +CEventHandlerEntry CTeleport_handlers[] = { + {1, -1, CEntity::pEventHandler(&CTeleport:: +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Teleport.es" +Main),DEBUGSTRING("CTeleport::Main")}, + {0x00db0000, -1, CEntity::pEventHandler(&CTeleport::H0x00db0000_Main_01), DEBUGSTRING("CTeleport::H0x00db0000_Main_01")}, + {0x00db0001, -1, CEntity::pEventHandler(&CTeleport::H0x00db0001_Main_02), DEBUGSTRING("CTeleport::H0x00db0001_Main_02")}, + {0x00db0002, -1, CEntity::pEventHandler(&CTeleport::H0x00db0002_Main_03), DEBUGSTRING("CTeleport::H0x00db0002_Main_03")}, + {0x00db0003, -1, CEntity::pEventHandler(&CTeleport::H0x00db0003_Main_04), DEBUGSTRING("CTeleport::H0x00db0003_Main_04")}, + {0x00db0004, -1, CEntity::pEventHandler(&CTeleport::H0x00db0004_Main_05), DEBUGSTRING("CTeleport::H0x00db0004_Main_05")}, + {0x00db0005, -1, CEntity::pEventHandler(&CTeleport::H0x00db0005_Main_06), DEBUGSTRING("CTeleport::H0x00db0005_Main_06")}, +}; +#define CTeleport_handlersct ARRAYCOUNT(CTeleport_handlers) + +CEntity *CTeleport_New(void) { return new CTeleport; }; +void CTeleport_OnInitClass(void) {}; +void CTeleport_OnEndClass(void) {}; +void CTeleport_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CTeleport_OnWorldEnd(CWorld *pwo) {}; +void CTeleport_OnWorldInit(CWorld *pwo) {}; +void CTeleport_OnWorldTick(CWorld *pwo) {}; +void CTeleport_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CTeleport, CRationalEntity, "Teleport", "Thumbnails\\Teleport.tbn", 0x000000db); +DECLARE_CTFILENAME(_fnmCTeleport_tbn, "Thumbnails\\Teleport.tbn"); diff --git a/Sources/EntitiesMP/Terrain.cpp b/Sources/EntitiesMP/Terrain.cpp new file mode 100644 index 0000000..5a61361 --- /dev/null +++ b/Sources/EntitiesMP/Terrain.cpp @@ -0,0 +1,30 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Terrain.es" + +#include "StdH.h" +#include + +#include +#include +void CTerrainEntity::SetDefaultProperties(void) { + CEntity::SetDefaultProperties(); +} +BOOL CTerrainEntity:: +#line 17 "D:/SE1_GPL/Sources/EntitiesMP/Terrain.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTerrainEntity_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTerrainEntity::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 20 "D:/SE1_GPL/Sources/EntitiesMP/Terrain.es" +InitAsTerrain (); +#line 21 "D:/SE1_GPL/Sources/EntitiesMP/Terrain.es" +TerrainChangeNotify (); +#line 22 "D:/SE1_GPL/Sources/EntitiesMP/Terrain.es" +SetCollisionFlags (ECF_BRUSH ); +#line 23 "D:/SE1_GPL/Sources/EntitiesMP/Terrain.es" +Return(STATE_CURRENT,EVoid()); +#line 23 "D:/SE1_GPL/Sources/EntitiesMP/Terrain.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Terrain.es b/Sources/EntitiesMP/Terrain.es new file mode 100644 index 0000000..23fb7ed --- /dev/null +++ b/Sources/EntitiesMP/Terrain.es @@ -0,0 +1,27 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +108 +%{ +#include "StdH.h" +#include +%} + +class CTerrainEntity : CEntity { +name "Terrain"; +thumbnail "Thumbnails\\Terrain.tbn"; + +properties: +components: +functions: +procedures: + Main() + { + // Init entity as terrain + InitAsTerrain(); + TerrainChangeNotify(); + SetCollisionFlags(ECF_BRUSH); + return; + } +}; + + diff --git a/Sources/EntitiesMP/Terrain.h b/Sources/EntitiesMP/Terrain.h new file mode 100644 index 0000000..062b219 --- /dev/null +++ b/Sources/EntitiesMP/Terrain.h @@ -0,0 +1,16 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Terrain_INCLUDED +#define _EntitiesMP_Terrain_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CTerrainEntity_DLLClass; +class CTerrainEntity : public CEntity { +public: + DECL_DLL virtual void SetDefaultProperties(void); +#define STATE_CTerrainEntity_Main 1 + BOOL +#line 17 "D:/SE1_GPL/Sources/EntitiesMP/Terrain.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Terrain_INCLUDED diff --git a/Sources/EntitiesMP/Terrain_tables.h b/Sources/EntitiesMP/Terrain_tables.h new file mode 100644 index 0000000..3eb6e82 --- /dev/null +++ b/Sources/EntitiesMP/Terrain_tables.h @@ -0,0 +1,35 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CTerrainEntity + +CEntityProperty CTerrainEntity_properties[] = { + CEntityProperty() +}; +#define CTerrainEntity_propertiesct 0 + + +CEntityComponent CTerrainEntity_components[] = { + CEntityComponent() +}; +#define CTerrainEntity_componentsct 0 + + +CEventHandlerEntry CTerrainEntity_handlers[] = { + {1, -1, CEntity::pEventHandler(&CTerrainEntity:: +#line 17 "D:/SE1_GPL/Sources/EntitiesMP/Terrain.es" +Main),DEBUGSTRING("CTerrainEntity::Main")}, +}; +#define CTerrainEntity_handlersct ARRAYCOUNT(CTerrainEntity_handlers) + +CEntity *CTerrainEntity_New(void) { return new CTerrainEntity; }; +void CTerrainEntity_OnInitClass(void) {}; +void CTerrainEntity_OnEndClass(void) {}; +void CTerrainEntity_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CTerrainEntity_OnWorldEnd(CWorld *pwo) {}; +void CTerrainEntity_OnWorldInit(CWorld *pwo) {}; +void CTerrainEntity_OnWorldTick(CWorld *pwo) {}; +void CTerrainEntity_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CTerrainEntity, CEntity, "Terrain", "Thumbnails\\Terrain.tbn", 0x0000006c); +DECLARE_CTFILENAME(_fnmCTerrainEntity_tbn, "Thumbnails\\Terrain.tbn"); diff --git a/Sources/EntitiesMP/TextFXHolder.cpp b/Sources/EntitiesMP/TextFXHolder.cpp new file mode 100644 index 0000000..3b49a45 --- /dev/null +++ b/Sources/EntitiesMP/TextFXHolder.cpp @@ -0,0 +1,426 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" + +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" + +#include +#include +#line 10 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" + +static CStaticStackArray _astrLines; +static CTFileName _fnLastLoaded; + +void CTextFXHolder::SetDefaultProperties(void) { + m_strName = "Text FX holder"; + m_strDescription = ""; + m_fnmMessage = CTString(""); + m_tmFadeInStart = 1e6; + m_tmFadeOutStart = 1e6; + m_tmFadeInLen = 0.5f; + m_tmFadeOutLen = 0.5f; + m_tmAutoFadeOut = -1.0f; + m_bDataError = FALSE ; + CRationalEntity::SetDefaultProperties(); +} + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +const CTString & CTextFXHolder::GetDescription(void)const { +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +((CTString &) m_strDescription ) . PrintF ("%s" , m_fnmMessage . FileName ()); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return m_strDescription ; +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} + CTextFXHolder::CTextFXHolder(void) +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +bDataLoaded = FALSE ; +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} + +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +BOOL CTextFXHolder::ReloadData(void) +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +m_bDataError = FALSE ; +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(! Text_On (m_fnmMessage )) +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Text_Off (); +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return FALSE ; +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return TRUE ; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} + +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +BOOL CTextFXHolder::LoadOneFile(const CTFileName & fnm) +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(fnm == ""){return FALSE ;} +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +try +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +CTFileStream strm ; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +strm . Open_t (fnm ); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +INDEX ctLines = 0; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +while(! strm . AtEOF ()) +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +CTString strLine ; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +strm . GetLine_t (strLine ); +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +ctLines ++; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +strm . SetPos_t (0); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +CTString * astr = _astrLines . Push (ctLines ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +for(INDEX iLine = 0;iLine < ctLines && ! strm . AtEOF ();iLine ++) +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +strm . GetLine_t (astr [ iLine ]); +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +strm . Close (); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return TRUE ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +catch (char * strError ) +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +CPrintF ("%s\n" , strError ); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return FALSE ; +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +_fnLastLoaded = fnm ; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} + +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +BOOL CTextFXHolder::Text_On(CTFileName fnText) +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +_astrLines . PopAll (); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return LoadOneFile (fnText ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} + +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +void CTextFXHolder::Text_Off(void) +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +_astrLines . Clear (); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +FLOAT CTextFXHolder::TextFX_Render(CTextFXHolder * penThis,CDrawPort * pdp) +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(m_bDataError ){return 0;} +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(! bDataLoaded ){ +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(! ReloadData ()){ +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +m_bDataError = TRUE ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return 0; +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +bDataLoaded = TRUE ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return 1; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +FLOAT fNow = _pTimer -> CurrentTick (); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(fNow < m_tmFadeInStart ){return 0;} +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(fNow > m_tmFadeOutStart + m_tmFadeOutLen ){return 0;} +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +PIX pixW = 0; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +PIX pixH = 0; +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +PIX pixJ = 0; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +FLOAT fResolutionScaling ; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +PIX pixLineHeight ; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +CTString strEmpty ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +CDrawPort * pdpCurr = pdp ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pdp -> Unlock (); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pdpCurr -> Lock (); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pixW = pdpCurr -> GetWidth (); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pixH = pdpCurr -> GetHeight (); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +fResolutionScaling = (FLOAT) pixH / 360.0f; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pdpCurr -> SetFont (_pfdDisplayFont ); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pixLineHeight = floor (20 * fResolutionScaling ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +INDEX ctMaxLinesOnScreen = pixH / pixLineHeight ; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +INDEX ctLines = ClampUp (_astrLines . Count () , ctMaxLinesOnScreen ); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pixJ = PIX (pixH / 2 - ctLines / 2.0f * pixLineHeight ); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +for(INDEX iLine = 0;iLine < ctLines ;iLine ++) +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +CTString * pstr = & _astrLines [ iLine ]; +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pdp -> SetFont (_pfdDisplayFont ); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pdp -> SetTextScaling (fResolutionScaling ); +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pdp -> SetTextAspect (1.0f); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +FLOAT fRatio = 1.0f; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(fNow > m_tmFadeOutStart ) +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +fRatio = CalculateRatio (fNow , m_tmFadeOutStart , m_tmFadeOutStart + m_tmFadeOutLen , 0 , 1); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(fNow < m_tmFadeInStart + m_tmFadeInLen ) +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +fRatio = CalculateRatio (fNow , m_tmFadeInStart , m_tmFadeInStart + m_tmFadeInLen , 1 , 0); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +UBYTE ubA = ClampUp (UBYTE (fRatio * 255.0f) , UBYTE (255)); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pdp -> PutTextC (* pstr , pixW / 2 , pixJ , C_WHITE | ubA ); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pixJ += pixLineHeight ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pdpCurr -> Unlock (); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pdp -> Lock (); +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return 1; +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +BOOL CTextFXHolder:: +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +WaitAndFadeOut(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTextFXHolder_WaitAndFadeOut + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTextFXHolder::WaitAndFadeOut expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +SetTimerAfter(m_tmAutoFadeOut ); +Jump(STATE_CURRENT, 0x00ef0001, FALSE, EBegin());return TRUE;}BOOL CTextFXHolder::H0x00ef0001_WaitAndFadeOut_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ef0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00ef0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTextFXHolder::H0x00ef0002_WaitAndFadeOut_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ef0002 +; +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Jump(STATE_CURRENT, STATE_CTextFXHolder_ApplyFadeOut, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CTextFXHolder:: +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +ApplyFadeOut(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTextFXHolder_ApplyFadeOut + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTextFXHolder::ApplyFadeOut expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +m_tmFadeOutStart = _pTimer -> CurrentTick (); +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(!(pwsc != NULL )){ Jump(STATE_CURRENT,0x00ef0006, FALSE, EInternal());return TRUE;} +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +SetTimerAfter(m_tmFadeOutLen ); +Jump(STATE_CURRENT, 0x00ef0004, FALSE, EBegin());return TRUE;}BOOL CTextFXHolder::H0x00ef0004_ApplyFadeOut_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ef0004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00ef0005, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTextFXHolder::H0x00ef0005_ApplyFadeOut_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ef0005 +; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +ETextFX etfx ; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +etfx . bStart = FALSE ; +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +etfx . penSender = this ; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pwsc -> SendEvent (etfx );Jump(STATE_CURRENT,0x00ef0006, FALSE, EInternal());return TRUE;}BOOL CTextFXHolder::H0x00ef0006_ApplyFadeOut_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ef0006 + +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Return(STATE_CURRENT,EReturn ()); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CTextFXHolder:: +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTextFXHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTextFXHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +InitAsEditorModel (); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +SetModel (MODEL_MARKER ); +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x00ef0007, FALSE, EBegin());return TRUE;}BOOL CTextFXHolder::H0x00ef0007_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ef0007 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00ef0008, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTextFXHolder::H0x00ef0008_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ef0008 +; +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(! Text_On (m_fnmMessage )) +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Text_Off (); +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return TRUE; +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +m_bDataError = FALSE ; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00ef0009, FALSE, EBegin());return TRUE;}BOOL CTextFXHolder::H0x00ef0009_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ef0009 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin): +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{const EBegin&e= (EBegin&)__eeInput; + +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return TRUE; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart): +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{const EStart&eStart= (EStart&)__eeInput; + +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +CWorldSettingsController * pwsc = GetWSC (this ); +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(pwsc != NULL ) +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +m_tmFadeInStart = _pTimer -> CurrentTick (); +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +ETextFX etfx ; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +etfx . bStart = TRUE ; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +etfx . penSender = this ; +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +pwsc -> SendEvent (etfx ); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +if(m_tmAutoFadeOut != - 1) +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{ +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Call(STATE_CURRENT, STATE_CTextFXHolder_WaitAndFadeOut, TRUE, EVoid());return TRUE; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +} +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return TRUE; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop): +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{const EStop&eStop= (EStop&)__eeInput; + +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Call(STATE_CURRENT, STATE_CTextFXHolder_ApplyFadeOut, TRUE, EVoid());return TRUE; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return TRUE; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn): +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +{const EReturn&e= (EReturn&)__eeInput; + +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return TRUE; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +}return TRUE;}BOOL CTextFXHolder::H0x00ef000a_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ef000a + +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Text_Off (); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/TextFXHolder.es b/Sources/EntitiesMP/TextFXHolder.es new file mode 100644 index 0000000..70debaa --- /dev/null +++ b/Sources/EntitiesMP/TextFXHolder.es @@ -0,0 +1,257 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +239 +%{ +#include "StdH.h" +#include "EntitiesMP/WorldSettingsController.h" +#include "EntitiesMP/BackgroundViewer.h" +%} + +%{ +static CStaticStackArray _astrLines; +static CTFileName _fnLastLoaded; +%} + +class CTextFXHolder: CRationalEntity { +name "TextFXHolder"; +thumbnail "Thumbnails\\TextFXHodler.tbn"; +features "IsTargetable", "HasName", "IsImportant"; + +properties: + + 1 CTString m_strName "Name" 'N' = "Text FX holder", + 2 CTString m_strDescription = "", + 3 CTFileName m_fnmMessage "Text file" 'T' = CTString(""), + 4 FLOAT m_tmFadeInStart = 1e6, + 5 FLOAT m_tmFadeOutStart = 1e6, + 6 FLOAT m_tmFadeInLen "Fade in time" 'I' = 0.5f, + 7 FLOAT m_tmFadeOutLen "Fade out time" 'O' = 0.5f, + 8 FLOAT m_tmAutoFadeOut "Auto fade out time" 'A' = -1.0f, + + 20 BOOL m_bDataError = FALSE, + { + BOOL bDataLoaded; + } + +components: + 1 model MODEL_MARKER "Models\\Editor\\MessageHolder.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\MessageHolder.tex" + +functions: + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("%s", m_fnmMessage.FileName()); + return m_strDescription; + } + + void CTextFXHolder(void) + { + bDataLoaded = FALSE; + } + + BOOL ReloadData(void) + { + m_bDataError = FALSE; + if (!Text_On(m_fnmMessage)) + { + Text_Off(); + return FALSE; + } + return TRUE; + } + + BOOL LoadOneFile(const CTFileName &fnm) + { + if(fnm=="") { return FALSE; } + try + { + // open the file + CTFileStream strm; + strm.Open_t(fnm); + + // count number of lines + INDEX ctLines = 0; + while(!strm.AtEOF()) + { + CTString strLine; + strm.GetLine_t(strLine); + ctLines++; + } + strm.SetPos_t(0); + + // allocate that much + CTString *astr = _astrLines.Push(ctLines); + // load all lines + for(INDEX iLine = 0; iLineCurrentTick(); + if( fNowm_tmFadeOutStart+m_tmFadeOutLen) { return 0;} + + PIX pixW = 0; + PIX pixH = 0; + PIX pixJ = 0; + FLOAT fResolutionScaling; + PIX pixLineHeight; + CTString strEmpty; + + CDrawPort *pdpCurr=pdp; + pdp->Unlock(); + pdpCurr->Lock(); + + pixW = pdpCurr->GetWidth(); + pixH = pdpCurr->GetHeight(); + fResolutionScaling = (FLOAT)pixH / 360.0f; + pdpCurr->SetFont( _pfdDisplayFont); + pixLineHeight = floor(20*fResolutionScaling); + + INDEX ctMaxLinesOnScreen = pixH/pixLineHeight; + INDEX ctLines=ClampUp(_astrLines.Count(), ctMaxLinesOnScreen); + + pixJ = PIX(pixH/2-ctLines/2.0f*pixLineHeight); + for (INDEX iLine = 0; iLineSetFont( _pfdDisplayFont); + pdp->SetTextScaling( fResolutionScaling); + pdp->SetTextAspect( 1.0f); + FLOAT fRatio=1.0f; + if( fNow>m_tmFadeOutStart) + { + fRatio=CalculateRatio(fNow, m_tmFadeOutStart, m_tmFadeOutStart+m_tmFadeOutLen, 0, 1); + } + if( fNowPutTextC( *pstr, pixW/2, pixJ, C_WHITE|ubA); + pixJ+=pixLineHeight; + } + + pdpCurr->Unlock(); + pdp->Lock(); + + return 1; + } + + +procedures: + + WaitAndFadeOut(EVoid) + { + autowait( m_tmAutoFadeOut); + jump ApplyFadeOut(); + } + + ApplyFadeOut(EVoid) + { + m_tmFadeOutStart = _pTimer->CurrentTick(); + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL) + { + autowait(m_tmFadeOutLen); + CWorldSettingsController *pwsc = GetWSC(this); + ETextFX etfx; + etfx.bStart=FALSE; + etfx.penSender=this; + pwsc->SendEvent(etfx); + } + return EReturn(); + } + + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + autowait(0.05f); + + if( !Text_On(m_fnmMessage)) + { + Text_Off(); + return; + } + m_bDataError = FALSE; + + wait() { + on (EBegin): + { + resume; + } + on (EStart eStart): + { + CWorldSettingsController *pwsc = GetWSC(this); + if( pwsc!=NULL) + { + m_tmFadeInStart = _pTimer->CurrentTick(); + ETextFX etfx; + etfx.bStart=TRUE; + etfx.penSender=this; + pwsc->SendEvent(etfx); + if( m_tmAutoFadeOut!=-1) + { + call WaitAndFadeOut(); + } + } + resume; + } + on (EStop eStop): + { + call ApplyFadeOut(); + resume; + } + on (EReturn): + { + resume; + } + } + Text_Off(); + return; + } +}; + diff --git a/Sources/EntitiesMP/TextFXHolder.h b/Sources/EntitiesMP/TextFXHolder.h new file mode 100644 index 0000000..919ddc4 --- /dev/null +++ b/Sources/EntitiesMP/TextFXHolder.h @@ -0,0 +1,65 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_TextFXHolder_INCLUDED +#define _EntitiesMP_TextFXHolder_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CTextFXHolder_DLLClass; +class CTextFXHolder : public CRationalEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CTFileName m_fnmMessage; + FLOAT m_tmFadeInStart; + FLOAT m_tmFadeOutStart; + FLOAT m_tmFadeInLen; + FLOAT m_tmFadeOutLen; + FLOAT m_tmAutoFadeOut; + BOOL m_bDataError; +BOOL bDataLoaded; + +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +const CTString & GetDescription(void)const; + CTextFXHolder(void); + +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +BOOL ReloadData(void); + +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +BOOL LoadOneFile(const CTFileName & fnm); + +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +BOOL Text_On(CTFileName fnText); + +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +void Text_Off(void); + +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +FLOAT TextFX_Render(CTextFXHolder * penThis,CDrawPort * pdp); +#define STATE_CTextFXHolder_WaitAndFadeOut 0x00ef0000 + BOOL +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +WaitAndFadeOut(const CEntityEvent &__eeInput); + BOOL H0x00ef0001_WaitAndFadeOut_01(const CEntityEvent &__eeInput); + BOOL H0x00ef0002_WaitAndFadeOut_02(const CEntityEvent &__eeInput); +#define STATE_CTextFXHolder_ApplyFadeOut 0x00ef0003 + BOOL +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +ApplyFadeOut(const CEntityEvent &__eeInput); + BOOL H0x00ef0004_ApplyFadeOut_01(const CEntityEvent &__eeInput); + BOOL H0x00ef0005_ApplyFadeOut_02(const CEntityEvent &__eeInput); + BOOL H0x00ef0006_ApplyFadeOut_03(const CEntityEvent &__eeInput); +#define STATE_CTextFXHolder_Main 1 + BOOL +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00ef0007_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00ef0008_Main_02(const CEntityEvent &__eeInput); + BOOL H0x00ef0009_Main_03(const CEntityEvent &__eeInput); + BOOL H0x00ef000a_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_TextFXHolder_INCLUDED diff --git a/Sources/EntitiesMP/TextFXHolder_tables.h b/Sources/EntitiesMP/TextFXHolder_tables.h new file mode 100644 index 0000000..bc2c845 --- /dev/null +++ b/Sources/EntitiesMP/TextFXHolder_tables.h @@ -0,0 +1,59 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CTextFXHolder + +CEntityProperty CTextFXHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ef<<8)+1, offsetof(CTextFXHolder, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000ef<<8)+2, offsetof(CTextFXHolder, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000ef<<8)+3, offsetof(CTextFXHolder, m_fnmMessage), "Text file", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ef<<8)+4, offsetof(CTextFXHolder, m_tmFadeInStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ef<<8)+5, offsetof(CTextFXHolder, m_tmFadeOutStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ef<<8)+6, offsetof(CTextFXHolder, m_tmFadeInLen), "Fade in time", 'I', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ef<<8)+7, offsetof(CTextFXHolder, m_tmFadeOutLen), "Fade out time", 'O', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000ef<<8)+8, offsetof(CTextFXHolder, m_tmAutoFadeOut), "Auto fade out time", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000ef<<8)+20, offsetof(CTextFXHolder, m_bDataError), "", 0, 0, 0), +}; +#define CTextFXHolder_propertiesct ARRAYCOUNT(CTextFXHolder_properties) + +CEntityComponent CTextFXHolder_components[] = { +#define MODEL_MARKER ((0x000000ef<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\MessageHolder.mdl"), +#define TEXTURE_MARKER ((0x000000ef<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\MessageHolder.tex"), +}; +#define CTextFXHolder_componentsct ARRAYCOUNT(CTextFXHolder_components) + +CEventHandlerEntry CTextFXHolder_handlers[] = { + {0x00ef0000, -1, CEntity::pEventHandler(&CTextFXHolder:: +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +WaitAndFadeOut),DEBUGSTRING("CTextFXHolder::WaitAndFadeOut")}, + {0x00ef0001, -1, CEntity::pEventHandler(&CTextFXHolder::H0x00ef0001_WaitAndFadeOut_01), DEBUGSTRING("CTextFXHolder::H0x00ef0001_WaitAndFadeOut_01")}, + {0x00ef0002, -1, CEntity::pEventHandler(&CTextFXHolder::H0x00ef0002_WaitAndFadeOut_02), DEBUGSTRING("CTextFXHolder::H0x00ef0002_WaitAndFadeOut_02")}, + {0x00ef0003, -1, CEntity::pEventHandler(&CTextFXHolder:: +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +ApplyFadeOut),DEBUGSTRING("CTextFXHolder::ApplyFadeOut")}, + {0x00ef0004, -1, CEntity::pEventHandler(&CTextFXHolder::H0x00ef0004_ApplyFadeOut_01), DEBUGSTRING("CTextFXHolder::H0x00ef0004_ApplyFadeOut_01")}, + {0x00ef0005, -1, CEntity::pEventHandler(&CTextFXHolder::H0x00ef0005_ApplyFadeOut_02), DEBUGSTRING("CTextFXHolder::H0x00ef0005_ApplyFadeOut_02")}, + {0x00ef0006, -1, CEntity::pEventHandler(&CTextFXHolder::H0x00ef0006_ApplyFadeOut_03), DEBUGSTRING("CTextFXHolder::H0x00ef0006_ApplyFadeOut_03")}, + {1, -1, CEntity::pEventHandler(&CTextFXHolder:: +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/TextFXHolder.es" +Main),DEBUGSTRING("CTextFXHolder::Main")}, + {0x00ef0007, -1, CEntity::pEventHandler(&CTextFXHolder::H0x00ef0007_Main_01), DEBUGSTRING("CTextFXHolder::H0x00ef0007_Main_01")}, + {0x00ef0008, -1, CEntity::pEventHandler(&CTextFXHolder::H0x00ef0008_Main_02), DEBUGSTRING("CTextFXHolder::H0x00ef0008_Main_02")}, + {0x00ef0009, -1, CEntity::pEventHandler(&CTextFXHolder::H0x00ef0009_Main_03), DEBUGSTRING("CTextFXHolder::H0x00ef0009_Main_03")}, + {0x00ef000a, -1, CEntity::pEventHandler(&CTextFXHolder::H0x00ef000a_Main_04), DEBUGSTRING("CTextFXHolder::H0x00ef000a_Main_04")}, +}; +#define CTextFXHolder_handlersct ARRAYCOUNT(CTextFXHolder_handlers) + +CEntity *CTextFXHolder_New(void) { return new CTextFXHolder; }; +void CTextFXHolder_OnInitClass(void) {}; +void CTextFXHolder_OnEndClass(void) {}; +void CTextFXHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CTextFXHolder_OnWorldEnd(CWorld *pwo) {}; +void CTextFXHolder_OnWorldInit(CWorld *pwo) {}; +void CTextFXHolder_OnWorldTick(CWorld *pwo) {}; +void CTextFXHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CTextFXHolder, CRationalEntity, "TextFXHolder", "Thumbnails\\TextFXHodler.tbn", 0x000000ef); +DECLARE_CTFILENAME(_fnmCTextFXHolder_tbn, "Thumbnails\\TextFXHodler.tbn"); diff --git a/Sources/EntitiesMP/TimeController.cpp b/Sources/EntitiesMP/TimeController.cpp new file mode 100644 index 0000000..7dbf5c1 --- /dev/null +++ b/Sources/EntitiesMP/TimeController.cpp @@ -0,0 +1,211 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" + +#include "StdH.h" + +#include +#include +void CTimeController::SetDefaultProperties(void) { + m_fTimeStretch = 1.0f; + m_tmFadeIn = 0.25f; + m_tmInterval = -1.0f; + m_bAbsolute = TRUE ; + m_fMyTimer = 0.0f; + m_tmStretchChangeStart = 0.0f; + m_strName = "Time controller"; + m_fOldTimeStretch = 0.0f; + m_fNewTimeStretch = 0.0f; + CRationalEntity::SetDefaultProperties(); +} +BOOL CTimeController:: +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +ChangeTimeStretch(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTimeController_ChangeTimeStretch + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTimeController::ChangeTimeStretch expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +m_fMyTimer = 0.0f; +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +Jump(STATE_CURRENT,0x02650003, FALSE, EInternal());return TRUE;}BOOL CTimeController::H0x02650003_ChangeTimeStretch_03(const CEntityEvent &__eeInput) +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +{ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650003 +if(!(m_fMyTimer < m_tmFadeIn - _pTimer -> TickQuantum / 2.0f)){ Jump(STATE_CURRENT,0x02650004, FALSE, EInternal());return TRUE;} +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +SetTimerAfter(_pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x02650001, FALSE, EBegin());return TRUE;}BOOL CTimeController::H0x02650001_ChangeTimeStretch_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02650002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTimeController::H0x02650002_ChangeTimeStretch_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650002 +; +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +m_fMyTimer += _pTimer -> TickQuantum / _pNetwork -> GetRealTimeFactor (); +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +FLOAT fNewStretch = Lerp (m_fOldTimeStretch , m_fNewTimeStretch , Clamp (m_fMyTimer / m_tmFadeIn , 0.0f , 1.0f)); +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +_pNetwork -> SetRealTimeFactor (fNewStretch );Jump(STATE_CURRENT,0x02650003, FALSE, EInternal());return TRUE; +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +}BOOL CTimeController::H0x02650004_ChangeTimeStretch_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650004 + +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +_pNetwork -> SetRealTimeFactor (m_fNewTimeStretch ); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +Return(STATE_CURRENT,EReturn ()); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CTimeController:: +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +ApplyTimeStretch(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTimeController_ApplyTimeStretch + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTimeController::ApplyTimeStretch expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +STATE_CTimeController_ChangeTimeStretch, TRUE; +Jump(STATE_CURRENT, 0x02650006, FALSE, EBegin());return TRUE;}BOOL CTimeController::H0x02650006_ApplyTimeStretch_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CTimeController_ChangeTimeStretch, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x02650007, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CTimeController::H0x02650007_ApplyTimeStretch_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650007 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +if(!(m_tmInterval > 0)){ Jump(STATE_CURRENT,0x0265000c, FALSE, EInternal());return TRUE;} +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +SetTimerAfter(m_tmInterval ); +Jump(STATE_CURRENT, 0x02650008, FALSE, EBegin());return TRUE;}BOOL CTimeController::H0x02650008_ApplyTimeStretch_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650008 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02650009, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTimeController::H0x02650009_ApplyTimeStretch_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650009 +; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +STATE_CTimeController_ResetTimeStretch, TRUE; +Jump(STATE_CURRENT, 0x0265000a, FALSE, EBegin());return TRUE;}BOOL CTimeController::H0x0265000a_ApplyTimeStretch_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0265000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CTimeController_ResetTimeStretch, TRUE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0265000b, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CTimeController::H0x0265000b_ApplyTimeStretch_06(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0265000b +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x0265000c, FALSE, EInternal());return TRUE;}BOOL CTimeController::H0x0265000c_ApplyTimeStretch_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0265000c + +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +Return(STATE_CURRENT,EReturn ()); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CTimeController:: +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +ResetTimeStretch(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTimeController_ResetTimeStretch + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTimeController::ResetTimeStretch expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +if(_pNetwork -> GetRealTimeFactor () == 1){Return(STATE_CURRENT,EReturn ());return TRUE;}; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +m_fOldTimeStretch = _pNetwork -> GetRealTimeFactor (); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +m_fNewTimeStretch = 1.0f; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +STATE_CTimeController_ChangeTimeStretch, TRUE; +Jump(STATE_CURRENT, 0x0265000e, FALSE, EBegin());return TRUE;}BOOL CTimeController::H0x0265000e_ResetTimeStretch_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0265000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CTimeController_ChangeTimeStretch, TRUE, EVoid ());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0265000f, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CTimeController::H0x0265000f_ResetTimeStretch_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0265000f +const EReturn&__e= (EReturn&)__eeInput; +; +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +Return(STATE_CURRENT,EReturn ()); +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CTimeController:: +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTimeController_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTimeController::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +InitAsEditorModel (); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +SetModel (MODEL_TIME_CONTROLLER ); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +SetModelMainTexture (TEXTURE_TIME_CONTROLLER ); +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x02650010, FALSE, EBegin());return TRUE;}BOOL CTimeController::H0x02650010_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650010 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x02650011, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTimeController::H0x02650011_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650011 +; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x02650012, FALSE, EBegin());return TRUE;}BOOL CTimeController::H0x02650012_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650012 +switch(__eeInput.ee_slEvent) +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +{case(EVENTCODE_EBegin): +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +{const EBegin&e= (EBegin&)__eeInput; + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +return TRUE; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart): +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +{const EStart&eStart= (EStart&)__eeInput; + +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +m_fOldTimeStretch = _pNetwork -> GetRealTimeFactor (); +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +m_fNewTimeStretch = m_fTimeStretch ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +Call(STATE_CURRENT, STATE_CTimeController_ApplyTimeStretch, TRUE, EVoid());return TRUE; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +return TRUE; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStop): +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +{const EStop&e= (EStop&)__eeInput; + +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +_pNetwork -> SetRealTimeFactor (1.0f); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +return TRUE; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReturn): +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +{const EReturn&e= (EReturn&)__eeInput; + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +return TRUE; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +}return TRUE;}BOOL CTimeController::H0x02650013_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02650013 + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/TimeController.es b/Sources/EntitiesMP/TimeController.es new file mode 100644 index 0000000..37de197 --- /dev/null +++ b/Sources/EntitiesMP/TimeController.es @@ -0,0 +1,105 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +613 +%{ +#include "StdH.h" +%} + +class CTimeController: CRationalEntity { +name "TimeController"; +thumbnail "Thumbnails\\TimeController.tbn"; +features "IsTargetable", "HasName", "IsImportant"; + +properties: + 1 FLOAT m_fTimeStretch "Time speed" = 1.0f, + 2 FLOAT m_tmFadeIn "Fade in time" = 0.25f, + 3 FLOAT m_tmInterval "Auto clear stretch after..." = -1.0f, + 4 BOOL m_bAbsolute "Absolute" = TRUE, + 5 FLOAT m_fMyTimer=0.0f, + 6 FLOAT m_tmStretchChangeStart=0.0f, + 7 CTString m_strName "Name" 'N' = "Time controller", + 8 FLOAT m_fOldTimeStretch=0.0f, + 9 FLOAT m_fNewTimeStretch=0.0f, + +components: + 1 model MODEL_TIME_CONTROLLER "ModelsMP\\Editor\\TimeControler.mdl", + 2 texture TEXTURE_TIME_CONTROLLER "ModelsMP\\Editor\\TimeController.tex" + +functions: + +procedures: + + ChangeTimeStretch(EVoid) + { + m_fMyTimer=0.0f; + while( m_fMyTimerTickQuantum/2.0f) + { + autowait(_pTimer->TickQuantum); + m_fMyTimer+=_pTimer->TickQuantum/_pNetwork->GetRealTimeFactor(); + FLOAT fNewStretch=Lerp(m_fOldTimeStretch, m_fNewTimeStretch, Clamp(m_fMyTimer/m_tmFadeIn, 0.0f, 1.0f)); + _pNetwork->SetRealTimeFactor(fNewStretch); + } + _pNetwork->SetRealTimeFactor(m_fNewTimeStretch); + return EReturn(); + } + + ApplyTimeStretch(EVoid) + { + autocall ChangeTimeStretch() EReturn; + if( m_tmInterval>0) + { + autowait(m_tmInterval); + autocall ResetTimeStretch() EReturn; + } + return EReturn(); + } + + ResetTimeStretch(EVoid) + { + if(_pNetwork->GetRealTimeFactor()==1) {return EReturn(); }; + m_fOldTimeStretch=_pNetwork->GetRealTimeFactor(); + m_fNewTimeStretch=1.0f; + autocall ChangeTimeStretch(EVoid()) EReturn; + return EReturn(); + } + + Main(EVoid) + { + // set appearance + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_TIME_CONTROLLER); + SetModelMainTexture(TEXTURE_TIME_CONTROLLER); + + // spawn in world editor + autowait(0.1f); + + wait() + { + on (EBegin) : + { + resume; + } + // immediate + on (EStart eStart) : + { + m_fOldTimeStretch=_pNetwork->GetRealTimeFactor(); + m_fNewTimeStretch=m_fTimeStretch; + call ApplyTimeStretch(); + resume; + } + on (EStop) : + { + _pNetwork->SetRealTimeFactor(1.0f); + resume; + } + on (EReturn) : + { + resume; + } + } + } +}; diff --git a/Sources/EntitiesMP/TimeController.h b/Sources/EntitiesMP/TimeController.h new file mode 100644 index 0000000..c3b5495 --- /dev/null +++ b/Sources/EntitiesMP/TimeController.h @@ -0,0 +1,57 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_TimeController_INCLUDED +#define _EntitiesMP_TimeController_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CTimeController_DLLClass; +class CTimeController : public CRationalEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_fTimeStretch; + FLOAT m_tmFadeIn; + FLOAT m_tmInterval; + BOOL m_bAbsolute; + FLOAT m_fMyTimer; + FLOAT m_tmStretchChangeStart; + CTString m_strName; + FLOAT m_fOldTimeStretch; + FLOAT m_fNewTimeStretch; +#define STATE_CTimeController_ChangeTimeStretch 0x02650000 + BOOL +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +ChangeTimeStretch(const CEntityEvent &__eeInput); + BOOL H0x02650001_ChangeTimeStretch_01(const CEntityEvent &__eeInput); + BOOL H0x02650002_ChangeTimeStretch_02(const CEntityEvent &__eeInput); + BOOL H0x02650003_ChangeTimeStretch_03(const CEntityEvent &__eeInput); + BOOL H0x02650004_ChangeTimeStretch_04(const CEntityEvent &__eeInput); +#define STATE_CTimeController_ApplyTimeStretch 0x02650005 + BOOL +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +ApplyTimeStretch(const CEntityEvent &__eeInput); + BOOL H0x02650006_ApplyTimeStretch_01(const CEntityEvent &__eeInput); + BOOL H0x02650007_ApplyTimeStretch_02(const CEntityEvent &__eeInput); + BOOL H0x02650008_ApplyTimeStretch_03(const CEntityEvent &__eeInput); + BOOL H0x02650009_ApplyTimeStretch_04(const CEntityEvent &__eeInput); + BOOL H0x0265000a_ApplyTimeStretch_05(const CEntityEvent &__eeInput); + BOOL H0x0265000b_ApplyTimeStretch_06(const CEntityEvent &__eeInput); + BOOL H0x0265000c_ApplyTimeStretch_07(const CEntityEvent &__eeInput); +#define STATE_CTimeController_ResetTimeStretch 0x0265000d + BOOL +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +ResetTimeStretch(const CEntityEvent &__eeInput); + BOOL H0x0265000e_ResetTimeStretch_01(const CEntityEvent &__eeInput); + BOOL H0x0265000f_ResetTimeStretch_02(const CEntityEvent &__eeInput); +#define STATE_CTimeController_Main 1 + BOOL +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x02650010_Main_01(const CEntityEvent &__eeInput); + BOOL H0x02650011_Main_02(const CEntityEvent &__eeInput); + BOOL H0x02650012_Main_03(const CEntityEvent &__eeInput); + BOOL H0x02650013_Main_04(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_TimeController_INCLUDED diff --git a/Sources/EntitiesMP/TimeController_tables.h b/Sources/EntitiesMP/TimeController_tables.h new file mode 100644 index 0000000..97026c4 --- /dev/null +++ b/Sources/EntitiesMP/TimeController_tables.h @@ -0,0 +1,70 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CTimeController + +CEntityProperty CTimeController_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000265<<8)+1, offsetof(CTimeController, m_fTimeStretch), "Time speed", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000265<<8)+2, offsetof(CTimeController, m_tmFadeIn), "Fade in time", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000265<<8)+3, offsetof(CTimeController, m_tmInterval), "Auto clear stretch after...", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000265<<8)+4, offsetof(CTimeController, m_bAbsolute), "Absolute", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000265<<8)+5, offsetof(CTimeController, m_fMyTimer), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000265<<8)+6, offsetof(CTimeController, m_tmStretchChangeStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000265<<8)+7, offsetof(CTimeController, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000265<<8)+8, offsetof(CTimeController, m_fOldTimeStretch), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000265<<8)+9, offsetof(CTimeController, m_fNewTimeStretch), "", 0, 0, 0), +}; +#define CTimeController_propertiesct ARRAYCOUNT(CTimeController_properties) + +CEntityComponent CTimeController_components[] = { +#define MODEL_TIME_CONTROLLER ((0x00000265<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_TIME_CONTROLLER, "EFNM" "ModelsMP\\Editor\\TimeControler.mdl"), +#define TEXTURE_TIME_CONTROLLER ((0x00000265<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_TIME_CONTROLLER, "EFNM" "ModelsMP\\Editor\\TimeController.tex"), +}; +#define CTimeController_componentsct ARRAYCOUNT(CTimeController_components) + +CEventHandlerEntry CTimeController_handlers[] = { + {0x02650000, -1, CEntity::pEventHandler(&CTimeController:: +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +ChangeTimeStretch),DEBUGSTRING("CTimeController::ChangeTimeStretch")}, + {0x02650001, -1, CEntity::pEventHandler(&CTimeController::H0x02650001_ChangeTimeStretch_01), DEBUGSTRING("CTimeController::H0x02650001_ChangeTimeStretch_01")}, + {0x02650002, -1, CEntity::pEventHandler(&CTimeController::H0x02650002_ChangeTimeStretch_02), DEBUGSTRING("CTimeController::H0x02650002_ChangeTimeStretch_02")}, + {0x02650003, -1, CEntity::pEventHandler(&CTimeController::H0x02650003_ChangeTimeStretch_03), DEBUGSTRING("CTimeController::H0x02650003_ChangeTimeStretch_03")}, + {0x02650004, -1, CEntity::pEventHandler(&CTimeController::H0x02650004_ChangeTimeStretch_04), DEBUGSTRING("CTimeController::H0x02650004_ChangeTimeStretch_04")}, + {0x02650005, -1, CEntity::pEventHandler(&CTimeController:: +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +ApplyTimeStretch),DEBUGSTRING("CTimeController::ApplyTimeStretch")}, + {0x02650006, -1, CEntity::pEventHandler(&CTimeController::H0x02650006_ApplyTimeStretch_01), DEBUGSTRING("CTimeController::H0x02650006_ApplyTimeStretch_01")}, + {0x02650007, -1, CEntity::pEventHandler(&CTimeController::H0x02650007_ApplyTimeStretch_02), DEBUGSTRING("CTimeController::H0x02650007_ApplyTimeStretch_02")}, + {0x02650008, -1, CEntity::pEventHandler(&CTimeController::H0x02650008_ApplyTimeStretch_03), DEBUGSTRING("CTimeController::H0x02650008_ApplyTimeStretch_03")}, + {0x02650009, -1, CEntity::pEventHandler(&CTimeController::H0x02650009_ApplyTimeStretch_04), DEBUGSTRING("CTimeController::H0x02650009_ApplyTimeStretch_04")}, + {0x0265000a, -1, CEntity::pEventHandler(&CTimeController::H0x0265000a_ApplyTimeStretch_05), DEBUGSTRING("CTimeController::H0x0265000a_ApplyTimeStretch_05")}, + {0x0265000b, -1, CEntity::pEventHandler(&CTimeController::H0x0265000b_ApplyTimeStretch_06), DEBUGSTRING("CTimeController::H0x0265000b_ApplyTimeStretch_06")}, + {0x0265000c, -1, CEntity::pEventHandler(&CTimeController::H0x0265000c_ApplyTimeStretch_07), DEBUGSTRING("CTimeController::H0x0265000c_ApplyTimeStretch_07")}, + {0x0265000d, -1, CEntity::pEventHandler(&CTimeController:: +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +ResetTimeStretch),DEBUGSTRING("CTimeController::ResetTimeStretch")}, + {0x0265000e, -1, CEntity::pEventHandler(&CTimeController::H0x0265000e_ResetTimeStretch_01), DEBUGSTRING("CTimeController::H0x0265000e_ResetTimeStretch_01")}, + {0x0265000f, -1, CEntity::pEventHandler(&CTimeController::H0x0265000f_ResetTimeStretch_02), DEBUGSTRING("CTimeController::H0x0265000f_ResetTimeStretch_02")}, + {1, -1, CEntity::pEventHandler(&CTimeController:: +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/TimeController.es" +Main),DEBUGSTRING("CTimeController::Main")}, + {0x02650010, -1, CEntity::pEventHandler(&CTimeController::H0x02650010_Main_01), DEBUGSTRING("CTimeController::H0x02650010_Main_01")}, + {0x02650011, -1, CEntity::pEventHandler(&CTimeController::H0x02650011_Main_02), DEBUGSTRING("CTimeController::H0x02650011_Main_02")}, + {0x02650012, -1, CEntity::pEventHandler(&CTimeController::H0x02650012_Main_03), DEBUGSTRING("CTimeController::H0x02650012_Main_03")}, + {0x02650013, -1, CEntity::pEventHandler(&CTimeController::H0x02650013_Main_04), DEBUGSTRING("CTimeController::H0x02650013_Main_04")}, +}; +#define CTimeController_handlersct ARRAYCOUNT(CTimeController_handlers) + +CEntity *CTimeController_New(void) { return new CTimeController; }; +void CTimeController_OnInitClass(void) {}; +void CTimeController_OnEndClass(void) {}; +void CTimeController_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CTimeController_OnWorldEnd(CWorld *pwo) {}; +void CTimeController_OnWorldInit(CWorld *pwo) {}; +void CTimeController_OnWorldTick(CWorld *pwo) {}; +void CTimeController_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CTimeController, CRationalEntity, "TimeController", "Thumbnails\\TimeController.tbn", 0x00000265); +DECLARE_CTFILENAME(_fnmCTimeController_tbn, "Thumbnails\\TimeController.tbn"); diff --git a/Sources/EntitiesMP/TouchField.cpp b/Sources/EntitiesMP/TouchField.cpp new file mode 100644 index 0000000..8aa2282 --- /dev/null +++ b/Sources/EntitiesMP/TouchField.cpp @@ -0,0 +1,246 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" + +#include "StdH.h" +#include "EntitiesMP/Projectile.h" + +#include +#include +#line 9 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" + + +BOOL ConsiderAll(CEntity*pen) +{ + return TRUE; +} +BOOL ConsiderPlayers(CEntity*pen) +{ + return IsDerivedFromClass(pen, "Player"); +} + +void CTouchField::SetDefaultProperties(void) { + m_strName = "Touch Field"; + m_penEnter = NULL; + m_eetEnter = EET_TRIGGER ; + m_penExit = NULL; + m_eetExit = EET_TRIGGER ; + m_bActive = TRUE ; + m_bPlayersOnly = TRUE ; + m_tmExitCheck = 0.0f; + m_bBlockNonPlayers = FALSE ; + m_penLastIn = NULL; + CRationalEntity::SetDefaultProperties(); +} + +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +void CTouchField::SetupFieldSettings(void) +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +{ +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +m_fsField . fs_toTexture . SetData (GetTextureDataForComponent (TEXTURE_FIELD )); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +m_fsField . fs_colColor = C_WHITE | CT_OPAQUE ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +CFieldSettings * CTouchField::GetFieldSettings(void) { +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +if(m_fsField . fs_toTexture . GetData () == NULL ){ +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +SetupFieldSettings (); +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +return & m_fsField ; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} + +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +SLONG CTouchField::GetUsedMemory(void) +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +{ +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +SLONG slUsedMemory = sizeof (CTouchField ) - sizeof (CRationalEntity ) + CRationalEntity :: GetUsedMemory (); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +slUsedMemory += m_strName . Length (); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +return slUsedMemory ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} +BOOL CTouchField:: +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +WaitingEntry(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTouchField_WaitingEntry + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTouchField::WaitingEntry expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +m_bActive = TRUE ; +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00ce0001, FALSE, EBegin());return TRUE;}BOOL CTouchField::H0x00ce0001_WaitingEntry_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ce0001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; +Jump(STATE_CURRENT, STATE_CTouchField_Frozen, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&ep= (EPass&)__eeInput; + +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +if(m_bBlockNonPlayers && IsOfClass (ep . penOther , "Projectile")) +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +{ +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +if(! IsOfClass (((CProjectile *) & * ep . penOther ) -> m_penLauncher , "Player")){ +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +EPass epass ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +epass . penOther = this ; +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +ep . penOther -> SendEvent (epass ); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +if(m_bPlayersOnly && ! IsDerivedFromClass (ep . penOther , "Player")){ +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +return TRUE; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +SendToTarget (m_penEnter , m_eetEnter , ep . penOther ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +if(m_tmExitCheck > 0){ +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +m_penLastIn = ep . penOther ; +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +Jump(STATE_CURRENT, STATE_CTouchField_WaitingExit, TRUE, EVoid());return TRUE; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +return TRUE; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +}return TRUE;}BOOL CTouchField::H0x00ce0002_WaitingEntry_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ce0002 + ASSERT(FALSE); return TRUE;};BOOL CTouchField:: +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +WaitingExit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTouchField_WaitingExit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTouchField::WaitingExit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +Jump(STATE_CURRENT,0x00ce0006, FALSE, EInternal());return TRUE;}BOOL CTouchField::H0x00ce0006_WaitingExit_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ce0006 +if(!(TRUE )){ Jump(STATE_CURRENT,0x00ce0007, FALSE, EInternal());return TRUE;} +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +SetTimerAfter(m_tmExitCheck ); +Jump(STATE_CURRENT, 0x00ce0004, FALSE, EBegin());return TRUE;}BOOL CTouchField::H0x00ce0004_WaitingExit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ce0004 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; +Jump(STATE_CURRENT, STATE_CTouchField_Frozen, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; + +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +CEntity * penNewIn ; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +if(m_bPlayersOnly ){ +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +penNewIn = TouchingEntity (ConsiderPlayers , m_penLastIn ); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +}else { +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +penNewIn = TouchingEntity (ConsiderAll , m_penLastIn ); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +if(penNewIn == NULL ){ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +SendToTarget (m_penExit , m_eetExit , m_penLastIn ); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +Jump(STATE_CURRENT, STATE_CTouchField_WaitingEntry, TRUE, EVoid());return TRUE; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +m_penLastIn = penNewIn ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +UnsetTimer();Jump(STATE_CURRENT,0x00ce0005, FALSE, EInternal());return TRUE; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +}return TRUE;}BOOL CTouchField::H0x00ce0005_WaitingExit_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ce0005 +Jump(STATE_CURRENT,0x00ce0006, FALSE, EInternal());return TRUE; +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +}BOOL CTouchField::H0x00ce0007_WaitingExit_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ce0007 + ASSERT(FALSE); return TRUE;};BOOL CTouchField:: +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +Frozen(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTouchField_Frozen + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTouchField::Frozen expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +m_bActive = FALSE ; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00ce0009, FALSE, EBegin());return TRUE;}BOOL CTouchField::H0x00ce0009_Frozen_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ce0009 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; +Jump(STATE_CURRENT, STATE_CTouchField_WaitingEntry, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +}return TRUE;}BOOL CTouchField::H0x00ce000a_Frozen_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00ce000a + ASSERT(FALSE); return TRUE;};BOOL CTouchField:: +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTouchField_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTouchField::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +InitAsFieldBrush (); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +SetPhysicsFlags (EPF_BRUSH_FIXED ); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +if(! m_bBlockNonPlayers ){ +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +SetCollisionFlags (((ECBI_MODEL ) << ECB_TEST ) | ((ECBI_BRUSH ) << ECB_IS ) | ((ECBI_MODEL ) << ECB_PASS )); +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +}else { +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +SetCollisionFlags (((ECBI_MODEL | ECBI_PLAYER | ECBI_PROJECTILE_SOLID | ECBI_PROJECTILE_MAGIC ) << ECB_TEST ) +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +| ((ECBI_BRUSH ) << ECB_IS ) | ((ECBI_PLAYER | ECBI_PROJECTILE_SOLID | ECBI_PROJECTILE_MAGIC ) << ECB_PASS )); +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +if(m_bActive ){ +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +Jump(STATE_CURRENT, STATE_CTouchField_WaitingEntry, TRUE, EVoid());return TRUE; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +}else { +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +Jump(STATE_CURRENT, STATE_CTouchField_Frozen, TRUE, EVoid());return TRUE; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +} +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +Return(STATE_CURRENT,EVoid()); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/TouchField.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/TouchField.es b/Sources/EntitiesMP/TouchField.es new file mode 100644 index 0000000..b1c219f --- /dev/null +++ b/Sources/EntitiesMP/TouchField.es @@ -0,0 +1,174 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +206 +%{ +#include "StdH.h" +#include "EntitiesMP/Projectile.h" +%} + +%{ + +BOOL ConsiderAll(CEntity*pen) +{ + return TRUE; +} +BOOL ConsiderPlayers(CEntity*pen) +{ + return IsDerivedFromClass(pen, "Player"); +} +%} + +class CTouchField: CRationalEntity { +name "Touch Field"; +thumbnail "Thumbnails\\TouchField.tbn"; +features "HasName", "IsTargetable"; + +properties: + + 1 CTString m_strName "Name" 'N' = "Touch Field", // class name + 2 CEntityPointer m_penEnter "Enter Target" 'T' COLOR(C_BROWN|0xFF), // target to send event to + 3 enum EventEType m_eetEnter "Enter Event" 'E' = EET_TRIGGER, // event to send on enter + 7 CEntityPointer m_penExit "Exit Target" COLOR(C_dRED|0xFF), // target to send event to + 8 enum EventEType m_eetExit "Exit Event" = EET_TRIGGER, // event to send on exit + 4 BOOL m_bActive "Active" 'A' = TRUE, // is field active + 5 BOOL m_bPlayersOnly "Players only" 'P' = TRUE, // reacts only on players + 6 FLOAT m_tmExitCheck "Exit check time" 'X' = 0.0f, // how often to check for exit + 9 BOOL m_bBlockNonPlayers "Block non-players" 'B' = FALSE, // everything except players cannot pass + + 100 CEntityPointer m_penLastIn, +{ + CFieldSettings m_fsField; +} + + +components: + + 1 texture TEXTURE_FIELD "Models\\Editor\\CollisionBox.tex", + + +functions: + + void SetupFieldSettings(void) + { + m_fsField.fs_toTexture.SetData(GetTextureDataForComponent(TEXTURE_FIELD)); + m_fsField.fs_colColor = C_WHITE|CT_OPAQUE; + } + + CFieldSettings *GetFieldSettings(void) { + if (m_fsField.fs_toTexture.GetData()==NULL) { + SetupFieldSettings(); + } + return &m_fsField; + }; + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CTouchField) - sizeof(CRationalEntity) + CRationalEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strName.Length(); + return slUsedMemory; + } + + +procedures: + + // field is active + WaitingEntry() { + m_bActive = TRUE; + wait() { + on (EBegin) : { resume; } + on (EDeactivate) : { jump Frozen(); } + // when someone passes the polygons + on (EPass ep) : { + + // stop enemy projectiles if blocks non players + if (m_bBlockNonPlayers && IsOfClass(ep.penOther, "Projectile")) + { + if (!IsOfClass(((CProjectile *)&*ep.penOther)->m_penLauncher, "Player")) { + EPass epass; + epass.penOther = this; + ep.penOther->SendEvent(epass); + } + } + + // if should react only on players and not player, + if (m_bPlayersOnly && !IsDerivedFromClass(ep.penOther, "Player")) { + // ignore + resume; + } + + // send event + SendToTarget(m_penEnter, m_eetEnter, ep.penOther); + // if checking for exit + if (m_tmExitCheck>0) { + // remember who entered + m_penLastIn = ep.penOther; + // wait for exit + jump WaitingExit(); + } + resume; + } + } + }; + + // waiting for entity to exit + WaitingExit() { + while(TRUE) { + // wait + wait(m_tmExitCheck) { + on (EBegin) : { resume; } + on (EDeactivate) : { jump Frozen(); } + on (ETimer) : { + // check for entities inside + CEntity *penNewIn; + if (m_bPlayersOnly) { + penNewIn = TouchingEntity(ConsiderPlayers, m_penLastIn); + } else { + penNewIn = TouchingEntity(ConsiderAll, m_penLastIn); + } + // if there are no entities in anymore + if (penNewIn==NULL) { + // send event + SendToTarget(m_penExit, m_eetExit, m_penLastIn); + // wait new entry + jump WaitingEntry(); + } + m_penLastIn = penNewIn; + stop; + } + } + } + }; + + // field is frozen + Frozen() { + m_bActive = FALSE; + wait() { + on (EBegin) : { resume; } + on (EActivate) : { jump WaitingEntry(); } + } + }; + + // main initialization + Main(EVoid) { + InitAsFieldBrush(); + SetPhysicsFlags(EPF_BRUSH_FIXED); + if ( !m_bBlockNonPlayers ) { + SetCollisionFlags( ((ECBI_MODEL)< +#include +void CTrigger::SetDefaultProperties(void) { + m_strName = "Trigger"; + m_penTarget1 = NULL; + m_penTarget2 = NULL; + m_penTarget3 = NULL; + m_penTarget4 = NULL; + m_penTarget5 = NULL; + m_penTarget6 = NULL; + m_penTarget7 = NULL; + m_penTarget8 = NULL; + m_penTarget9 = NULL; + m_penTarget10 = NULL; + m_eetEvent1 = EET_TRIGGER ; + m_eetEvent2 = EET_TRIGGER ; + m_eetEvent3 = EET_TRIGGER ; + m_eetEvent4 = EET_TRIGGER ; + m_eetEvent5 = EET_TRIGGER ; + m_eetEvent6 = EET_TRIGGER ; + m_eetEvent7 = EET_TRIGGER ; + m_eetEvent8 = EET_TRIGGER ; + m_eetEvent9 = EET_TRIGGER ; + m_eetEvent10 = EET_TRIGGER ; + m_strMessage = ""; + m_fMessageTime = 3.0f; + m_mssMessageSound = MSS_NONE ; + m_fScore = 0.0f; + m_fWaitTime = 0.0f; + m_bAutoStart = FALSE ; + m_iCount = 1; + m_bUseCount = FALSE ; + m_bReuseCount = FALSE ; + m_bTellCount = FALSE ; + m_bActive = TRUE ; + m_fSendRange = 1.0f; + m_eetRange = EET_IGNORE ; + m_iCountTmp = 0; + m_penCaused = NULL; + m_ctMaxTrigs = -1; + CRationalEntity::SetDefaultProperties(); +} + +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +CEntity * CTrigger::GetTarget(void)const +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +{ +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +return m_penTarget1 ; +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} + +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SLONG CTrigger::GetUsedMemory(void) +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +{ +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SLONG slUsedMemory = sizeof (CTrigger ) - sizeof (CRationalEntity ) + CRationalEntity :: GetUsedMemory (); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +slUsedMemory += m_strMessage . Length (); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +slUsedMemory += m_strName . Length (); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +slUsedMemory += 1 * sizeof (CSoundObject); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +return slUsedMemory ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +BOOL CTrigger:: +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendEventToTargets(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTrigger_SendEventToTargets + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTrigger::SendEventToTargets expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(!(m_fWaitTime > 0.0f)){ Jump(STATE_CURRENT,0x00cd0003, FALSE, EInternal());return TRUE;} +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SetTimerAfter(m_fWaitTime ); +Jump(STATE_CURRENT, 0x00cd0001, FALSE, EBegin());return TRUE;}BOOL CTrigger::H0x00cd0001_SendEventToTargets_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd0001 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x00cd0002, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; +return FALSE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}return TRUE;}BOOL CTrigger::H0x00cd0002_SendEventToTargets_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd0002 +Jump(STATE_CURRENT,0x00cd0003, FALSE, EInternal());return TRUE;}BOOL CTrigger::H0x00cd0003_SendEventToTargets_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd0003 + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendToTarget (m_penTarget1 , m_eetEvent1 , m_penCaused ); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendToTarget (m_penTarget2 , m_eetEvent2 , m_penCaused ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendToTarget (m_penTarget3 , m_eetEvent3 , m_penCaused ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendToTarget (m_penTarget4 , m_eetEvent4 , m_penCaused ); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendToTarget (m_penTarget5 , m_eetEvent5 , m_penCaused ); +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendToTarget (m_penTarget6 , m_eetEvent6 , m_penCaused ); +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendToTarget (m_penTarget7 , m_eetEvent7 , m_penCaused ); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendToTarget (m_penTarget8 , m_eetEvent8 , m_penCaused ); +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendToTarget (m_penTarget9 , m_eetEvent9 , m_penCaused ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendToTarget (m_penTarget10 , m_eetEvent10 , m_penCaused ); +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(m_eetRange != EET_IGNORE ){ +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendInRange (this , m_eetRange , FLOATaabbox3D (GetPlacement () . pl_PositionVector , m_fSendRange )); +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(m_fScore > 0){ +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +CEntity * penCaused = FixupCausedToPlayer (this , m_penCaused ); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(penCaused != NULL ){ +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +EReceiveScore eScore ; +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +eScore . iPoints = m_fScore ; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +penCaused -> SendEvent (eScore ); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +penCaused -> SendEvent (ESecretFound ()); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +m_fScore = 0; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(m_strMessage != ""){ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +PrintCenterMessage (this , m_penCaused , +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +TranslateConst (m_strMessage ) , +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +m_fMessageTime , m_mssMessageSound ); +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(m_ctMaxTrigs > 0) +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +{ +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +m_ctMaxTrigs -= 1; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(m_ctMaxTrigs <= 0) +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +{ +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Destroy (); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Return(STATE_CURRENT,EVoid()); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CTrigger:: +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Active(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTrigger_Active + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTrigger::Active expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +ASSERT (m_bActive ); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +m_iCountTmp = m_iCount ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00cd0005, FALSE, EBegin());return TRUE;}BOOL CTrigger::H0x00cd0005_Active_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd0005 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(m_bAutoStart ){ +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Call(STATE_CURRENT, STATE_CTrigger_SendEventToTargets, TRUE, EVoid());return TRUE; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +return TRUE; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&eStart= (EStart&)__eeInput; + +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendToTarget (this , EET_TRIGGER , eStart . penCaused ); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +return TRUE; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +m_penCaused = eTrigger . penCaused ; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(m_bUseCount ){ +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(m_iCountTmp > 0){ +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +m_iCountTmp --; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(m_iCountTmp < 1){ +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(m_bReuseCount ){ +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +m_iCountTmp = m_iCount ; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}else { +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +m_iCountTmp = 0; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Call(STATE_CURRENT, STATE_CTrigger_SendEventToTargets, TRUE, EVoid());return TRUE; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}else if(m_bTellCount ){ +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +CTString strRemaining ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +strRemaining . PrintF (TRANS ("%d more to go...") , m_iCountTmp ); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +PrintCenterMessage (this , m_penCaused , strRemaining , 3.0f , MSS_INFO ); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}else { +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Call(STATE_CURRENT, STATE_CTrigger_SendEventToTargets, TRUE, EVoid());return TRUE; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +return TRUE; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +m_bActive = FALSE ; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Jump(STATE_CURRENT, STATE_CTrigger_Inactive, TRUE, EVoid());return TRUE; +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}return TRUE;}BOOL CTrigger::H0x00cd0006_Active_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd0006 + ASSERT(FALSE); return TRUE;};BOOL CTrigger:: +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Inactive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTrigger_Inactive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTrigger::Inactive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +ASSERT (! m_bActive ); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Jump(STATE_CURRENT,0x00cd000c, FALSE, EInternal());return TRUE;}BOOL CTrigger::H0x00cd000c_Inactive_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd000c +if(!(TRUE )){ Jump(STATE_CURRENT,0x00cd000d, FALSE, EInternal());return TRUE;} +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00cd0008, FALSE, EBegin());return TRUE;}BOOL CTrigger::H0x00cd0008_Inactive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd0008 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +m_bActive = TRUE ; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Jump(STATE_CURRENT, STATE_CTrigger_Active, TRUE, EVoid());return TRUE; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}ASSERT(FALSE);break;default:{ +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +return TRUE; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}ASSERT(FALSE);break; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}return TRUE;}BOOL CTrigger::H0x00cd0009_Inactive_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd0009 +; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00cd000a, FALSE, EBegin());return TRUE;}BOOL CTrigger::H0x00cd000a_Inactive_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd000a +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00cd000b, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTrigger::H0x00cd000b_Inactive_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd000b +;Jump(STATE_CURRENT,0x00cd000c, FALSE, EInternal());return TRUE; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}BOOL CTrigger::H0x00cd000d_Inactive_06(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd000d + ASSERT(FALSE); return TRUE;};BOOL CTrigger:: +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTrigger_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CTrigger::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +InitAsEditorModel (); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SetModel (MODEL_MARKER ); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +m_fSendRange = ClampDn (m_fSendRange , 0.01f); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x00cd000e, FALSE, EBegin());return TRUE;}BOOL CTrigger::H0x00cd000e_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x00cd000f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTrigger::H0x00cd000f_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00cd000f +; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +if(m_bActive ){ +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Jump(STATE_CURRENT, STATE_CTrigger_Active, TRUE, EVoid());return TRUE; +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +}else { +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Jump(STATE_CURRENT, STATE_CTrigger_Inactive, TRUE, EVoid());return TRUE; +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +} +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Destroy (); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Return(STATE_CURRENT,EVoid()); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Trigger.es b/Sources/EntitiesMP/Trigger.es new file mode 100644 index 0000000..69dce4c --- /dev/null +++ b/Sources/EntitiesMP/Trigger.es @@ -0,0 +1,258 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +205 +%{ +#include "StdH.h" +extern INDEX ent_bReportBrokenChains; +%} + +class CTrigger: CRationalEntity { +name "Trigger"; +thumbnail "Thumbnails\\Trigger.tbn"; +features "HasName", "IsTargetable"; + +properties: + + 1 CTString m_strName "Name" 'N' = "Trigger", // class name + + 3 CEntityPointer m_penTarget1 "Target 01" 'T' COLOR(C_RED|0xFF), // send event to entity + 4 CEntityPointer m_penTarget2 "Target 02" 'Y' COLOR(C_RED|0xFF), + 5 CEntityPointer m_penTarget3 "Target 03" 'U' COLOR(C_RED|0xFF), + 6 CEntityPointer m_penTarget4 "Target 04" 'I' COLOR(C_RED|0xFF), + 7 CEntityPointer m_penTarget5 "Target 05" 'O' COLOR(C_RED|0xFF), + 20 CEntityPointer m_penTarget6 "Target 06" COLOR(C_RED|0xFF), + 21 CEntityPointer m_penTarget7 "Target 07" COLOR(C_RED|0xFF), + 22 CEntityPointer m_penTarget8 "Target 08" COLOR(C_RED|0xFF), + 23 CEntityPointer m_penTarget9 "Target 09" COLOR(C_RED|0xFF), + 24 CEntityPointer m_penTarget10 "Target 10" COLOR(C_RED|0xFF), + 8 enum EventEType m_eetEvent1 "Event type Target 01" 'G' = EET_TRIGGER, // type of event to send + 9 enum EventEType m_eetEvent2 "Event type Target 02" 'H' = EET_TRIGGER, + 10 enum EventEType m_eetEvent3 "Event type Target 03" 'J' = EET_TRIGGER, + 11 enum EventEType m_eetEvent4 "Event type Target 04" 'K' = EET_TRIGGER, + 12 enum EventEType m_eetEvent5 "Event type Target 05" 'L' = EET_TRIGGER, + 50 enum EventEType m_eetEvent6 "Event type Target 06" = EET_TRIGGER, + 51 enum EventEType m_eetEvent7 "Event type Target 07" = EET_TRIGGER, + 52 enum EventEType m_eetEvent8 "Event type Target 08" = EET_TRIGGER, + 53 enum EventEType m_eetEvent9 "Event type Target 09" = EET_TRIGGER, + 54 enum EventEType m_eetEvent10 "Event type Target 10" = EET_TRIGGER, + 13 CTStringTrans m_strMessage "Message" 'M' = "", // message + 14 FLOAT m_fMessageTime "Message time" = 3.0f, // how long is message on screen + 15 enum MessageSound m_mssMessageSound "Message sound" = MSS_NONE, // message sound + 16 FLOAT m_fScore "Score" 'S' = 0.0f, + + 30 FLOAT m_fWaitTime "Wait" 'W' = 0.0f, // wait before send events + 31 BOOL m_bAutoStart "Auto start" 'A' = FALSE, // trigger auto starts + 32 INDEX m_iCount "Count" 'C' = 1, // count before send events + 33 BOOL m_bUseCount "Count use" = FALSE, // use count to send events + 34 BOOL m_bReuseCount "Count reuse" = FALSE, // reuse counter after reaching 0 + 35 BOOL m_bTellCount "Count tell" = FALSE, // tell remaining count to player + 36 BOOL m_bActive "Active" 'V' = TRUE, // starts in active/inactive state + 37 RANGE m_fSendRange "Send Range" 'R' = 1.0f, // for sending event in range + 38 enum EventEType m_eetRange "Event type Range" = EET_IGNORE, // type of event to send in range + + 40 INDEX m_iCountTmp = 0, // use count value to determine when to send events + 41 CEntityPointer m_penCaused, // who touched it last time + 42 INDEX m_ctMaxTrigs "Max trigs" 'X' = -1, // how many times could trig + + +components: + + 1 model MODEL_MARKER "Models\\Editor\\Trigger.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\Camera.tex" + + +functions: + + // get target 1 (there is no property 'm_penTarget') + CEntity *GetTarget(void) const + { + return m_penTarget1; + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CTrigger) - sizeof(CRationalEntity) + CRationalEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strMessage.Length(); + slUsedMemory += m_strName.Length(); + slUsedMemory += 1* sizeof(CSoundObject); + return slUsedMemory; + } + + + +procedures: + + SendEventToTargets() { + // if needed wait some time before event is send + if (m_fWaitTime > 0.0f) { + wait (m_fWaitTime) { + on (EBegin) : { resume; } + on (ETimer) : { stop; } + on (EDeactivate) : { pass; } + otherwise(): { resume; } + } + } + + // send event to all targets + SendToTarget(m_penTarget1, m_eetEvent1, m_penCaused); + SendToTarget(m_penTarget2, m_eetEvent2, m_penCaused); + SendToTarget(m_penTarget3, m_eetEvent3, m_penCaused); + SendToTarget(m_penTarget4, m_eetEvent4, m_penCaused); + SendToTarget(m_penTarget5, m_eetEvent5, m_penCaused); + SendToTarget(m_penTarget6, m_eetEvent6, m_penCaused); + SendToTarget(m_penTarget7, m_eetEvent7, m_penCaused); + SendToTarget(m_penTarget8, m_eetEvent8, m_penCaused); + SendToTarget(m_penTarget9, m_eetEvent9, m_penCaused); + SendToTarget(m_penTarget10, m_eetEvent10, m_penCaused); + + // if there is event to send in range + if (m_eetRange!=EET_IGNORE) { + // send in range also + SendInRange(this, m_eetRange, FLOATaabbox3D(GetPlacement().pl_PositionVector, m_fSendRange)); + } + + // if trigger gives score + if (m_fScore>0) { + CEntity *penCaused = FixupCausedToPlayer(this, m_penCaused); + + // if we have causer + if (penCaused!=NULL) { + // send the score + EReceiveScore eScore; + eScore.iPoints = m_fScore; + penCaused->SendEvent(eScore); + penCaused->SendEvent(ESecretFound()); + } + + // kill score to never be reported again + m_fScore = 0; + } + if (m_strMessage!="") { + PrintCenterMessage(this, m_penCaused, + TranslateConst(m_strMessage), + m_fMessageTime, m_mssMessageSound); + } + + // if max trig count is used for counting + if(m_ctMaxTrigs > 0) + { + // decrease count + m_ctMaxTrigs-=1; + // if we trigged max times + if( m_ctMaxTrigs <= 0) + { + // cease to exist + Destroy(); + } + } + return; + }; + + Active() { + ASSERT(m_bActive); + // store count start value + m_iCountTmp = m_iCount; + + //main loop + wait() { + on (EBegin) : { + // if auto start send event on init + if (m_bAutoStart) { + call SendEventToTargets(); + } + resume; + } + // re-roots start events as triggers + on (EStart eStart) : { + SendToTarget(this, EET_TRIGGER, eStart.penCaused); + resume; + } + // cascade trigger + on (ETrigger eTrigger) : { + m_penCaused = eTrigger.penCaused; + // if using count + if (m_bUseCount) { + // count reach lowest value + if (m_iCountTmp > 0) { + // decrease count + m_iCountTmp--; + // send event if count is less than one (is zero) + if (m_iCountTmp < 1) { + if (m_bReuseCount) { + m_iCountTmp = m_iCount; + } else { + m_iCountTmp = 0; + } + call SendEventToTargets(); + } else if (m_bTellCount) { + CTString strRemaining; + strRemaining.PrintF(TRANS("%d more to go..."), m_iCountTmp); + PrintCenterMessage(this, m_penCaused, strRemaining, 3.0f, MSS_INFO); + } + } + // else send event + } else { + call SendEventToTargets(); + } + resume; + } + // if deactivated + on (EDeactivate) : { + // go to inactive state + m_bActive = FALSE; + jump Inactive(); + } + } + }; + Inactive() { + ASSERT(!m_bActive); + while (TRUE) { + // wait + wait() { + // if activated + on (EActivate) : { + // go to active state + m_bActive = TRUE; + jump Active(); + } + otherwise() : { + resume; + }; + }; + + // wait a bit to recover + autowait(0.1f); + } + } + + Main() { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + + m_fSendRange = ClampDn(m_fSendRange, 0.01f); + + // spawn in world editor + autowait(0.1f); + + // go into active or inactive state + if (m_bActive) { + jump Active(); + } else { + jump Inactive(); + } + + // cease to exist + Destroy(); + + return; + }; +}; diff --git a/Sources/EntitiesMP/Trigger.h b/Sources/EntitiesMP/Trigger.h new file mode 100644 index 0000000..78645a2 --- /dev/null +++ b/Sources/EntitiesMP/Trigger.h @@ -0,0 +1,86 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Trigger_INCLUDED +#define _EntitiesMP_Trigger_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CTrigger_DLLClass; +class CTrigger : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CEntityPointer m_penTarget1; + CEntityPointer m_penTarget2; + CEntityPointer m_penTarget3; + CEntityPointer m_penTarget4; + CEntityPointer m_penTarget5; + CEntityPointer m_penTarget6; + CEntityPointer m_penTarget7; + CEntityPointer m_penTarget8; + CEntityPointer m_penTarget9; + CEntityPointer m_penTarget10; + enum EventEType m_eetEvent1; + enum EventEType m_eetEvent2; + enum EventEType m_eetEvent3; + enum EventEType m_eetEvent4; + enum EventEType m_eetEvent5; + enum EventEType m_eetEvent6; + enum EventEType m_eetEvent7; + enum EventEType m_eetEvent8; + enum EventEType m_eetEvent9; + enum EventEType m_eetEvent10; + CTStringTrans m_strMessage; + FLOAT m_fMessageTime; + enum MessageSound m_mssMessageSound; + FLOAT m_fScore; + FLOAT m_fWaitTime; + BOOL m_bAutoStart; + INDEX m_iCount; + BOOL m_bUseCount; + BOOL m_bReuseCount; + BOOL m_bTellCount; + BOOL m_bActive; + RANGE m_fSendRange; + enum EventEType m_eetRange; + INDEX m_iCountTmp; + CEntityPointer m_penCaused; + INDEX m_ctMaxTrigs; + +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +CEntity * GetTarget(void)const; + +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SLONG GetUsedMemory(void); +#define STATE_CTrigger_SendEventToTargets 0x00cd0000 + BOOL +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendEventToTargets(const CEntityEvent &__eeInput); + BOOL H0x00cd0001_SendEventToTargets_01(const CEntityEvent &__eeInput); + BOOL H0x00cd0002_SendEventToTargets_02(const CEntityEvent &__eeInput); + BOOL H0x00cd0003_SendEventToTargets_03(const CEntityEvent &__eeInput); +#define STATE_CTrigger_Active 0x00cd0004 + BOOL +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Active(const CEntityEvent &__eeInput); + BOOL H0x00cd0005_Active_01(const CEntityEvent &__eeInput); + BOOL H0x00cd0006_Active_02(const CEntityEvent &__eeInput); +#define STATE_CTrigger_Inactive 0x00cd0007 + BOOL +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Inactive(const CEntityEvent &__eeInput); + BOOL H0x00cd0008_Inactive_01(const CEntityEvent &__eeInput); + BOOL H0x00cd0009_Inactive_02(const CEntityEvent &__eeInput); + BOOL H0x00cd000a_Inactive_03(const CEntityEvent &__eeInput); + BOOL H0x00cd000b_Inactive_04(const CEntityEvent &__eeInput); + BOOL H0x00cd000c_Inactive_05(const CEntityEvent &__eeInput); + BOOL H0x00cd000d_Inactive_06(const CEntityEvent &__eeInput); +#define STATE_CTrigger_Main 1 + BOOL +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00cd000e_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00cd000f_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Trigger_INCLUDED diff --git a/Sources/EntitiesMP/Trigger_tables.h b/Sources/EntitiesMP/Trigger_tables.h new file mode 100644 index 0000000..a7b3b31 --- /dev/null +++ b/Sources/EntitiesMP/Trigger_tables.h @@ -0,0 +1,94 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CTrigger + +CEntityProperty CTrigger_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000cd<<8)+1, offsetof(CTrigger, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000cd<<8)+3, offsetof(CTrigger, m_penTarget1), "Target 01", 'T', C_RED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000cd<<8)+4, offsetof(CTrigger, m_penTarget2), "Target 02", 'Y', C_RED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000cd<<8)+5, offsetof(CTrigger, m_penTarget3), "Target 03", 'U', C_RED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000cd<<8)+6, offsetof(CTrigger, m_penTarget4), "Target 04", 'I', C_RED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000cd<<8)+7, offsetof(CTrigger, m_penTarget5), "Target 05", 'O', C_RED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000cd<<8)+20, offsetof(CTrigger, m_penTarget6), "Target 06", 0, C_RED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000cd<<8)+21, offsetof(CTrigger, m_penTarget7), "Target 07", 0, C_RED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000cd<<8)+22, offsetof(CTrigger, m_penTarget8), "Target 08", 0, C_RED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000cd<<8)+23, offsetof(CTrigger, m_penTarget9), "Target 09", 0, C_RED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000cd<<8)+24, offsetof(CTrigger, m_penTarget10), "Target 10", 0, C_RED | 0xFF, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000cd<<8)+8, offsetof(CTrigger, m_eetEvent1), "Event type Target 01", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000cd<<8)+9, offsetof(CTrigger, m_eetEvent2), "Event type Target 02", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000cd<<8)+10, offsetof(CTrigger, m_eetEvent3), "Event type Target 03", 'J', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000cd<<8)+11, offsetof(CTrigger, m_eetEvent4), "Event type Target 04", 'K', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000cd<<8)+12, offsetof(CTrigger, m_eetEvent5), "Event type Target 05", 'L', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000cd<<8)+50, offsetof(CTrigger, m_eetEvent6), "Event type Target 06", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000cd<<8)+51, offsetof(CTrigger, m_eetEvent7), "Event type Target 07", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000cd<<8)+52, offsetof(CTrigger, m_eetEvent8), "Event type Target 08", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000cd<<8)+53, offsetof(CTrigger, m_eetEvent9), "Event type Target 09", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000cd<<8)+54, offsetof(CTrigger, m_eetEvent10), "Event type Target 10", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRINGTRANS, NULL, (0x000000cd<<8)+13, offsetof(CTrigger, m_strMessage), "Message", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000cd<<8)+14, offsetof(CTrigger, m_fMessageTime), "Message time", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &MessageSound_enum, (0x000000cd<<8)+15, offsetof(CTrigger, m_mssMessageSound), "Message sound", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000cd<<8)+16, offsetof(CTrigger, m_fScore), "Score", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000000cd<<8)+30, offsetof(CTrigger, m_fWaitTime), "Wait", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cd<<8)+31, offsetof(CTrigger, m_bAutoStart), "Auto start", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000cd<<8)+32, offsetof(CTrigger, m_iCount), "Count", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cd<<8)+33, offsetof(CTrigger, m_bUseCount), "Count use", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cd<<8)+34, offsetof(CTrigger, m_bReuseCount), "Count reuse", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cd<<8)+35, offsetof(CTrigger, m_bTellCount), "Count tell", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000cd<<8)+36, offsetof(CTrigger, m_bActive), "Active", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x000000cd<<8)+37, offsetof(CTrigger, m_fSendRange), "Send Range", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &EventEType_enum, (0x000000cd<<8)+38, offsetof(CTrigger, m_eetRange), "Event type Range", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000cd<<8)+40, offsetof(CTrigger, m_iCountTmp), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000000cd<<8)+41, offsetof(CTrigger, m_penCaused), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000cd<<8)+42, offsetof(CTrigger, m_ctMaxTrigs), "Max trigs", 'X', 0x7F0000FFUL, 0), +}; +#define CTrigger_propertiesct ARRAYCOUNT(CTrigger_properties) + +CEntityComponent CTrigger_components[] = { +#define MODEL_MARKER ((0x000000cd<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\Trigger.mdl"), +#define TEXTURE_MARKER ((0x000000cd<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\Camera.tex"), +}; +#define CTrigger_componentsct ARRAYCOUNT(CTrigger_components) + +CEventHandlerEntry CTrigger_handlers[] = { + {0x00cd0000, -1, CEntity::pEventHandler(&CTrigger:: +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +SendEventToTargets),DEBUGSTRING("CTrigger::SendEventToTargets")}, + {0x00cd0001, -1, CEntity::pEventHandler(&CTrigger::H0x00cd0001_SendEventToTargets_01), DEBUGSTRING("CTrigger::H0x00cd0001_SendEventToTargets_01")}, + {0x00cd0002, -1, CEntity::pEventHandler(&CTrigger::H0x00cd0002_SendEventToTargets_02), DEBUGSTRING("CTrigger::H0x00cd0002_SendEventToTargets_02")}, + {0x00cd0003, -1, CEntity::pEventHandler(&CTrigger::H0x00cd0003_SendEventToTargets_03), DEBUGSTRING("CTrigger::H0x00cd0003_SendEventToTargets_03")}, + {0x00cd0004, -1, CEntity::pEventHandler(&CTrigger:: +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Active),DEBUGSTRING("CTrigger::Active")}, + {0x00cd0005, -1, CEntity::pEventHandler(&CTrigger::H0x00cd0005_Active_01), DEBUGSTRING("CTrigger::H0x00cd0005_Active_01")}, + {0x00cd0006, -1, CEntity::pEventHandler(&CTrigger::H0x00cd0006_Active_02), DEBUGSTRING("CTrigger::H0x00cd0006_Active_02")}, + {0x00cd0007, -1, CEntity::pEventHandler(&CTrigger:: +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Inactive),DEBUGSTRING("CTrigger::Inactive")}, + {0x00cd0008, -1, CEntity::pEventHandler(&CTrigger::H0x00cd0008_Inactive_01), DEBUGSTRING("CTrigger::H0x00cd0008_Inactive_01")}, + {0x00cd0009, -1, CEntity::pEventHandler(&CTrigger::H0x00cd0009_Inactive_02), DEBUGSTRING("CTrigger::H0x00cd0009_Inactive_02")}, + {0x00cd000a, -1, CEntity::pEventHandler(&CTrigger::H0x00cd000a_Inactive_03), DEBUGSTRING("CTrigger::H0x00cd000a_Inactive_03")}, + {0x00cd000b, -1, CEntity::pEventHandler(&CTrigger::H0x00cd000b_Inactive_04), DEBUGSTRING("CTrigger::H0x00cd000b_Inactive_04")}, + {0x00cd000c, -1, CEntity::pEventHandler(&CTrigger::H0x00cd000c_Inactive_05), DEBUGSTRING("CTrigger::H0x00cd000c_Inactive_05")}, + {0x00cd000d, -1, CEntity::pEventHandler(&CTrigger::H0x00cd000d_Inactive_06), DEBUGSTRING("CTrigger::H0x00cd000d_Inactive_06")}, + {1, -1, CEntity::pEventHandler(&CTrigger:: +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Trigger.es" +Main),DEBUGSTRING("CTrigger::Main")}, + {0x00cd000e, -1, CEntity::pEventHandler(&CTrigger::H0x00cd000e_Main_01), DEBUGSTRING("CTrigger::H0x00cd000e_Main_01")}, + {0x00cd000f, -1, CEntity::pEventHandler(&CTrigger::H0x00cd000f_Main_02), DEBUGSTRING("CTrigger::H0x00cd000f_Main_02")}, +}; +#define CTrigger_handlersct ARRAYCOUNT(CTrigger_handlers) + +CEntity *CTrigger_New(void) { return new CTrigger; }; +void CTrigger_OnInitClass(void) {}; +void CTrigger_OnEndClass(void) {}; +void CTrigger_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CTrigger_OnWorldEnd(CWorld *pwo) {}; +void CTrigger_OnWorldInit(CWorld *pwo) {}; +void CTrigger_OnWorldTick(CWorld *pwo) {}; +void CTrigger_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CTrigger, CRationalEntity, "Trigger", "Thumbnails\\Trigger.tbn", 0x000000cd); +DECLARE_CTFILENAME(_fnmCTrigger_tbn, "Thumbnails\\Trigger.tbn"); diff --git a/Sources/EntitiesMP/Twister.cpp b/Sources/EntitiesMP/Twister.cpp new file mode 100644 index 0000000..67827c6 --- /dev/null +++ b/Sources/EntitiesMP/Twister.cpp @@ -0,0 +1,475 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/AirElemental/Twister.h" + +#define ECF_TWISTER ( \ + ((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)< +#include +CEntityEvent *ETwister::MakeCopy(void) { CEntityEvent *peeCopy = new ETwister(*this); return peeCopy;} +ETwister::ETwister() : CEntityEvent(EVENTCODE_ETwister) {; + ClearToDefault(penOwner); + ClearToDefault(fSize); + ClearToDefault(fDuration); + ClearToDefault(sgnSpinDir); + ClearToDefault(bGrow); + ClearToDefault(bMovingAllowed); +}; +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" + +static EntityInfo eiTwister = { + EIBT_AIR, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.75f, 0.0f, +}; + + +#define MOVE_FREQUENCY 0.1f +#define ROTATE_SPEED 10000.0f +#define MOVE_SPEED 7.5f + +void CTwister_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) +{ + pdec->PrecacheClass(CLASS_SPINNER); + pdec->PrecacheModel(MODEL_TWISTER); + pdec->PrecacheTexture(TEXTURE_TWISTER); + pdec->PrecacheSound(SOUND_SPIN); +} + +void CTwister::SetDefaultProperties(void) { + m_penOwner = NULL; + m_fSize = 1.0f; + m_vSpeed = FLOAT3D(0 , 0 , 0); + m_sgnSpinDir = 1; + m_bGrow = TRUE ; + m_tmLastMove = 0.0f; + m_aSpeedRotation = FLOAT3D(0 , 0 , 0); + m_bMoving = FALSE ; + m_bMovingAllowed = TRUE ; + m_vDesiredPosition = FLOAT3D(0 , 0 , 0); + m_vDesiredAngle = FLOAT3D(0 , 0 , 0); + m_fStopTime = 0.0f; + m_fActionRadius = 0.0f; + m_fActionTime = 0.0f; + m_fDiffMultiply = 0.0f; + m_fUpMultiply = 0.0f; + m_bFadeOut = FALSE ; + m_fFadeStartTime = 1e6; + m_fFadeTime = 2.0f; + m_fStartTime = 0.0f; + m_soSpin.SetOwner(this); +m_soSpin.Stop_internal(); + CMovableModelEntity::SetDefaultProperties(); +} + +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +void * CTwister::GetEntityInfo(void) { +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +return & eiTwister ; +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} + +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +void CTwister::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +{ +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +return ; +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} + +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +void CTwister::RenderParticles(void) +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +{ +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(m_bMovingAllowed ) +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +{ +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +Particles_Twister (this , m_fSize / 15.0f , m_fStartTime , m_fFadeStartTime , 1.0f); +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +else +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +{ +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +CEntity * penParent = GetParent (); +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +FLOAT fStretch = 1.0f; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(penParent != NULL ) +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +{ +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +CAirElemental * penAir = (CAirElemental *) penParent ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +FLOAT fStretchRatio = penAir -> GetCurrentStretchRatio (); +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +fStretch = 1.0f + (fStretchRatio ) * 6.0f; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +Particles_Twister (this , m_fSize / 15.0f * fStretch , m_fStartTime , m_fFadeStartTime , 0.5f * fStretch ); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +BOOL CTwister::AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient) { +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(m_bFadeOut ){ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +FLOAT fTimeRemain = m_fFadeStartTime + m_fFadeTime - _pTimer -> CurrentTick (); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(fTimeRemain < 0.0f){fTimeRemain = 0.0f;} +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +COLOR colAlpha = GetModelObject () -> mo_colBlendColor ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +colAlpha = (colAlpha & 0xffffff00) + (COLOR (fTimeRemain / m_fFadeTime * 0xff) & 0xff); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +GetModelObject () -> mo_colBlendColor = colAlpha ; +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +return CMovableModelEntity :: AdjustShadingParameters (vLightDirection , colLight , colAmbient ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} + +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +void CTwister::SpinEntity(CEntity * pen) { +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(IsOfClass (pen , "AirElemental") || IsOfClass (pen , "Twister") +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +|| IsDerivedFromClass (pen , "Item")){ +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +return ; +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(IsOfClass (pen , "Projectile")){ +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(((CProjectile *) & * pen ) -> m_prtType == PRT_AIRELEMENTAL_WIND ) +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +{ +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +return ; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(pen -> GetPhysicsFlags () & EPF_MOVABLE ){ +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +BOOL bNoSpinner = TRUE ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +{FOREACHINLIST (CEntity , en_lnInParent , pen -> en_lhChildren , iten ){ +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(IsOfClass (iten , "Spinner")) +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +{ +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +bNoSpinner = FALSE ; +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +return ; +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +}} +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(bNoSpinner ){ +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +ESpinnerInit esi ; +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +CEntityPointer penSpinner ; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . penParent = pen ; +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . penTwister = this ; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . bImpulse = FALSE ; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(IsOfClass (pen , "Projectile")) +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +{ +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +switch(((CProjectile &) * pen ) . m_prtType ){ +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +case PRT_GRENADE : +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +case PRT_HEADMAN_BOMBERMAN : +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +case PRT_DEMON_FIREBALL : +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +case PRT_SHOOTER_FIREBALL : +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +case PRT_BEAST_PROJECTILE : +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +case PRT_BEAST_BIG_PROJECTILE : +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +case PRT_LAVA_COMET : +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . tmSpinTime = 2.5f; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . vRotationAngle = ANGLE3D (- m_sgnSpinDir * 250.0f , 0 , 0); +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . fUpSpeed = m_fDiffMultiply * 0.75; +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +break ; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +default : +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . tmSpinTime = 1.5f; +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . vRotationAngle = ANGLE3D (- m_sgnSpinDir * 180.0f , 0 , 0); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . fUpSpeed = m_fDiffMultiply / 5.0f; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +break ; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +}else if(IsOfClass (pen , "Cannon ball")){ +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . tmSpinTime = 0.2f; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . vRotationAngle = ANGLE3D (- m_sgnSpinDir * 500.0f , 0 , 0); +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . fUpSpeed = m_fDiffMultiply * 3.0f; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +}else if(IsOfClass (pen , "Player")){ +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . tmSpinTime = 3.0f; +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . vRotationAngle = ANGLE3D (- m_sgnSpinDir * 220.0f , 0 , 0); +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . bImpulse = TRUE ; +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . fUpSpeed = m_fDiffMultiply * (0.4f + FRnd () * 0.4f); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . tmImpulseDuration = 1.4f + FRnd () * 0.5f; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +}else { +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . tmSpinTime = 0.5f; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . vRotationAngle = ANGLE3D (- m_sgnSpinDir * 180.0f , 0 , 0); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +esi . fUpSpeed = m_fDiffMultiply ; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +penSpinner = CreateEntity (pen -> GetPlacement () , CLASS_SPINNER ); +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +penSpinner -> Initialize (esi ); +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +penSpinner -> SetParent (pen ); +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +FLOAT3D vDirection ; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +AnglesToDirectionVector (GetPlacement () . pl_OrientationAngle , vDirection ); +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +InflictDirectDamage (pen , m_penOwner , DMT_IMPACT , 2.0f , GetPlacement () . pl_PositionVector , vDirection ); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} + +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +void CTwister::PreMoving(void) { +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(m_bMoving ){ +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +FLOATmatrix3D m ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +ANGLE3D aRotation ; +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +aRotation = m_aSpeedRotation * (_pTimer -> CurrentTick () - m_tmLastMove ); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +MakeRotationMatrix (m , aRotation ); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_vSpeed = m_vSpeed * m ; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SetDesiredTranslation (m_vSpeed ); +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_tmLastMove = _pTimer -> CurrentTick (); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +CMovableModelEntity :: PreMoving (); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +BOOL CTwister:: +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CTwister_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_ETwister, "CTwister::Main expects 'ETwister' as input!"); const ETwister &et = (const ETwister &)__eeInput; +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +ASSERT (et . penOwner != NULL ); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_penOwner = et . penOwner ; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_sgnSpinDir = et . sgnSpinDir ; +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(m_sgnSpinDir == 0){m_sgnSpinDir = 1;}; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_fSize = et . fSize ; +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_fStopTime = _pTimer -> CurrentTick () + et . fDuration ; +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_bGrow = et . bGrow ; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_bMovingAllowed = et . bMovingAllowed ; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +InitAsEditorModel (); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SetPhysicsFlags (EPF_TWISTER ); +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SetCollisionFlags (ECF_TWISTER ); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SetModel (MODEL_TWISTER ); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SetModelMainTexture (TEXTURE_TWISTER ); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_fActionRadius = pow (m_fSize , 0.33333f) * 10.0f; +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_fActionTime = m_fActionRadius ; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_fUpMultiply = m_fActionRadius / 2.0f; +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_fDiffMultiply = sqrt (m_fSize ); +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +GetModelObject () -> StretchModel (FLOAT3D (m_fSize , m_fSize , m_fSize )); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +ModelChangeNotify (); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_fStartTime = _pTimer -> CurrentTick (); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SetTimerAfter(FRnd () * 0.25f); +Jump(STATE_CURRENT, 0x01fb0001, FALSE, EBegin());return TRUE;}BOOL CTwister::H0x01fb0001_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fb0002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTwister::H0x01fb0002_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0002 +; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_soSpin . Set3DParameters (50.0f , 10.0f , 1.0f , 1.0f); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +PlaySound (m_soSpin , SOUND_SPIN , SOF_3D | SOF_LOOP ); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SetDesiredRotation (ANGLE3D (m_sgnSpinDir * (FRnd () * 50.0f + 50.0f) , 0.0f , 0.0f)); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(m_bGrow ){ +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +StartModelAnim (TWISTER_ANIM_GROWING , AOF_SMOOTHCHANGE | AOF_NORESTART ); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (TWISTER_ANIM_GROWING )); +Jump(STATE_CURRENT, 0x01fb0003, FALSE, EBegin());return TRUE;}BOOL CTwister::H0x01fb0003_Main_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fb0004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTwister::H0x01fb0004_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0004 +; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +FLOAT fR = FRndIn (5.0f , 10.0f); +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +FLOAT fA = FRnd () * 360.0f; +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_vSpeed = FLOAT3D (CosFast (fA ) * fR , 0 , SinFast (fA ) * fR ); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_bMoving = m_bMovingAllowed ; +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +Jump(STATE_CURRENT,0x01fb0007, FALSE, EInternal());return TRUE;}BOOL CTwister::H0x01fb0007_Main_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0007 +if(!(_pTimer -> CurrentTick () < m_fStopTime )){ Jump(STATE_CURRENT,0x01fb0008, FALSE, EInternal());return TRUE;} +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +FLOAT fMoveTime = FRndIn (2.0f , 4.0f); +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_aSpeedRotation = FLOAT3D (FRndIn (8.0f , 16.0f) , 0.0f , 0.0f); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_tmLastMove = _pTimer -> CurrentTick (); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SetTimerAfter(fMoveTime ); +Jump(STATE_CURRENT, 0x01fb0005, FALSE, EBegin());return TRUE;}BOOL CTwister::H0x01fb0005_Main_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0005 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01fb0006, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&ep= (EPass&)__eeInput; + +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +if(ep . penOther -> GetRenderType () & RT_MODEL && +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +ep . penOther -> GetPhysicsFlags () & EPF_MOVABLE && +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +! IsOfClass (ep . penOther , "Twister")){ +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SpinEntity (ep . penOther ); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +} +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +return TRUE; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +}return TRUE;}BOOL CTwister::H0x01fb0006_Main_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0006 +Jump(STATE_CURRENT,0x01fb0007, FALSE, EInternal());return TRUE; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +}BOOL CTwister::H0x01fb0008_Main_08(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0008 + +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_fFadeStartTime = _pTimer -> CurrentTick (); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_bFadeOut = TRUE ; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +m_fFadeTime = 2.0f; +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +SetTimerAfter(m_fFadeTime ); +Jump(STATE_CURRENT, 0x01fb0009, FALSE, EBegin());return TRUE;}BOOL CTwister::H0x01fb0009_Main_09(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb0009 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01fb000a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CTwister::H0x01fb000a_Main_10(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fb000a +; +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +Destroy (); +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +Return(STATE_CURRENT,EVoid()); +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Twister.es b/Sources/EntitiesMP/Twister.es new file mode 100644 index 0000000..2e8c4a6 --- /dev/null +++ b/Sources/EntitiesMP/Twister.es @@ -0,0 +1,335 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +507 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/AirElemental/Twister.h" + +#define ECF_TWISTER ( \ + ((ECBI_BRUSH|ECBI_MODEL|ECBI_CORPSE|ECBI_ITEM|ECBI_PROJECTILE_MAGIC|ECBI_PROJECTILE_SOLID)<PrecacheClass(CLASS_SPINNER); + pdec->PrecacheModel(MODEL_TWISTER); + pdec->PrecacheTexture(TEXTURE_TWISTER); + pdec->PrecacheSound(SOUND_SPIN); +} +%} + +class CTwister : CMovableModelEntity { +name "Twister"; +thumbnail ""; +features "ImplementsOnPrecache"; + +properties: + 1 CEntityPointer m_penOwner, // entity which owns it + 2 FLOAT m_fSize = 1.0f, // size + 3 FLOAT3D m_vSpeed = FLOAT3D(0,0,0), // current speed + 4 INDEX m_sgnSpinDir = 1, // spin clockwise + 5 BOOL m_bGrow = TRUE, // grow to full size? + 6 FLOAT m_tmLastMove = 0.0f, // when moving has started + 7 FLOAT3D m_aSpeedRotation = FLOAT3D(0,0,0), + 8 BOOL m_bMoving = FALSE, + 9 BOOL m_bMovingAllowed = TRUE, + + // internal -> do not use + 10 FLOAT3D m_vDesiredPosition = FLOAT3D(0,0,0), + 11 FLOAT3D m_vDesiredAngle = FLOAT3D(0,0,0), + 12 FLOAT m_fStopTime = 0.0f, + 13 FLOAT m_fActionRadius = 0.0f, + 14 FLOAT m_fActionTime = 0.0f, + 15 FLOAT m_fDiffMultiply = 0.0f, + 16 FLOAT m_fUpMultiply = 0.0f, + 20 BOOL m_bFadeOut = FALSE, + 21 FLOAT m_fFadeStartTime = 1e6, + 22 FLOAT m_fFadeTime = 2.0f, + 23 FLOAT m_fStartTime = 0.0f, + + 50 CSoundObject m_soSpin, // sound channel for spinning + +components: + + 1 class CLASS_SPINNER "Classes\\Spinner.ecl", + + 10 model MODEL_TWISTER "ModelsMP\\Enemies\\AirElemental\\Twister.mdl", + 11 texture TEXTURE_TWISTER "ModelsMP\\Enemies\\AirElemental\\Twister.tex", + +200 sound SOUND_SPIN "ModelsMP\\Enemies\\AirElemental\\Sounds\\TwisterSpin.wav", + +functions: + /* Entity info */ + void *GetEntityInfo(void) { + return &eiTwister; + }; + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + return; + }; + + // render burning particles + void RenderParticles(void) + { + if(m_bMovingAllowed) + { + Particles_Twister(this, m_fSize/15.0f, m_fStartTime, m_fFadeStartTime, 1.0f); + } + else + { + CEntity *penParent=GetParent(); + FLOAT fStretch=1.0f; + if(penParent!=NULL) + { + CAirElemental *penAir=(CAirElemental *)penParent; + FLOAT fStretchRatio=penAir->GetCurrentStretchRatio(); + fStretch=1.0f+(fStretchRatio)*6.0f; + } + Particles_Twister(this, m_fSize/15.0f*fStretch, m_fStartTime, m_fFadeStartTime, 0.5f*fStretch); + } + } + +/************************************************************ + * FADE OUT & MOVING * + ************************************************************/ + BOOL AdjustShadingParameters(FLOAT3D &vLightDirection, COLOR &colLight, COLOR &colAmbient) { + // fading out + if (m_bFadeOut) { + FLOAT fTimeRemain = m_fFadeStartTime + m_fFadeTime - _pTimer->CurrentTick(); + if (fTimeRemain < 0.0f) { fTimeRemain = 0.0f; } + COLOR colAlpha = GetModelObject()->mo_colBlendColor; + colAlpha = (colAlpha&0xffffff00) + (COLOR(fTimeRemain/m_fFadeTime*0xff)&0xff); + GetModelObject()->mo_colBlendColor = colAlpha; + } + return CMovableModelEntity::AdjustShadingParameters(vLightDirection, colLight, colAmbient); + }; + + +/************************************************************ + * ATTACK SPECIFIC * + ************************************************************/ + + void SpinEntity(CEntity *pen) { + + // don't spin air elemental and other twisters and any items + if (IsOfClass(pen, "AirElemental") || IsOfClass(pen, "Twister") + || IsDerivedFromClass(pen, "Item")) { + return; + } + // don't spin air elementals wind blast + if (IsOfClass(pen, "Projectile")) { + if (((CProjectile *)&*pen)->m_prtType==PRT_AIRELEMENTAL_WIND) + { + return; + } + } + + + + if (pen->GetPhysicsFlags()&EPF_MOVABLE) { + // if any other spinner affects the target, skip this spinner + BOOL bNoSpinner = TRUE; + {FOREACHINLIST( CEntity, en_lnInParent, pen->en_lhChildren, iten) { + if (IsOfClass(iten, "Spinner")) + { + bNoSpinner = FALSE; + return; + } + }} + if (bNoSpinner) { + ESpinnerInit esi; + CEntityPointer penSpinner; + esi.penParent = pen; + esi.penTwister = this; + esi.bImpulse = FALSE; + + // spin projectiles a bit longer but not so high + if (IsOfClass(pen, "Projectile")) + { + switch(((CProjectile &)*pen).m_prtType) { + case PRT_GRENADE: + case PRT_HEADMAN_BOMBERMAN: + case PRT_DEMON_FIREBALL: + case PRT_SHOOTER_FIREBALL: + case PRT_BEAST_PROJECTILE: + case PRT_BEAST_BIG_PROJECTILE: + case PRT_LAVA_COMET: + esi.tmSpinTime = 2.5f; + esi.vRotationAngle = ANGLE3D(-m_sgnSpinDir*250.0f, 0, 0); + esi.fUpSpeed = m_fDiffMultiply*0.75; + break; + default: + esi.tmSpinTime = 1.5f; + esi.vRotationAngle = ANGLE3D(-m_sgnSpinDir*180.0f, 0, 0); + esi.fUpSpeed = m_fDiffMultiply/5.0f; + break; + } + // cannon ball - short but powerfull + } else if (IsOfClass(pen, "Cannon ball")){ + esi.tmSpinTime = 0.2f; + esi.vRotationAngle = ANGLE3D(-m_sgnSpinDir*500.0f, 0, 0); + esi.fUpSpeed = m_fDiffMultiply*3.0f; + // don't take it easy with players + } else if (IsOfClass(pen, "Player")){ + esi.tmSpinTime = 3.0f; + esi.vRotationAngle = ANGLE3D(-m_sgnSpinDir*220.0f, 0, 0); + esi.bImpulse = TRUE; + esi.fUpSpeed = m_fDiffMultiply*(0.4f + FRnd()*0.4f); + esi.tmImpulseDuration = 1.4f + FRnd()*0.5f; + // everything else + } else { + esi.tmSpinTime = 0.5f; + esi.vRotationAngle = ANGLE3D(-m_sgnSpinDir*180.0f, 0, 0); + esi.fUpSpeed = m_fDiffMultiply; + } + penSpinner = CreateEntity(pen->GetPlacement(), CLASS_SPINNER); + penSpinner->Initialize(esi); + penSpinner->SetParent(pen); + } + // damage + FLOAT3D vDirection; + AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, vDirection); + InflictDirectDamage(pen, m_penOwner, DMT_IMPACT, 2.0f, GetPlacement().pl_PositionVector, vDirection); + } + + }; + + void PreMoving(void) { + // moving - rotate speed direction + if (m_bMoving) { + FLOATmatrix3D m; + ANGLE3D aRotation; + aRotation = m_aSpeedRotation*(_pTimer->CurrentTick()-m_tmLastMove); + MakeRotationMatrix(m, aRotation); + m_vSpeed = m_vSpeed*m; + SetDesiredTranslation(m_vSpeed); + m_tmLastMove = _pTimer->CurrentTick(); + } + CMovableModelEntity::PreMoving(); + }; + + +/************************************************************ + * P R O C E D U R E S * + ************************************************************/ +procedures: + // --->>> MAIN + Main(ETwister et) { + // remember the initial parameters + ASSERT(et.penOwner!=NULL); + m_penOwner = et.penOwner; + m_sgnSpinDir = et.sgnSpinDir; + if (m_sgnSpinDir==0) { m_sgnSpinDir=1; }; + m_fSize = et.fSize; + m_fStopTime = _pTimer->CurrentTick() + et.fDuration; + m_bGrow = et.bGrow; + m_bMovingAllowed = et.bMovingAllowed; + + // initialization + InitAsEditorModel(); + SetPhysicsFlags(EPF_TWISTER); + SetCollisionFlags(ECF_TWISTER); + SetFlags(GetFlags() | ENF_SEETHROUGH); + SetModel(MODEL_TWISTER); + SetModelMainTexture(TEXTURE_TWISTER); + + // some twister parameters + m_fActionRadius = pow(m_fSize, 0.33333f)*10.0f; + m_fActionTime = m_fActionRadius; + m_fUpMultiply = m_fActionRadius/2.0f; + m_fDiffMultiply = sqrt(m_fSize); + GetModelObject()->StretchModel(FLOAT3D(m_fSize, m_fSize, m_fSize)); + ModelChangeNotify(); + + m_fStartTime=_pTimer->CurrentTick(); + + //wait for some randome time + autowait(FRnd()*0.25f); + + m_soSpin.Set3DParameters(50.0f, 10.0f, 1.0f, 1.0f); + PlaySound(m_soSpin, SOUND_SPIN, SOF_3D|SOF_LOOP); + + // immediately rotate + SetDesiredRotation(ANGLE3D(m_sgnSpinDir*(FRnd()*50.0f+50.0f), 0.0f, 0.0f)); + + if (m_bGrow) { + StartModelAnim(TWISTER_ANIM_GROWING, AOF_SMOOTHCHANGE|AOF_NORESTART); + } + autowait(GetModelObject()->GetAnimLength(TWISTER_ANIM_GROWING)); + + // beginning random speed + FLOAT fR = FRndIn(5.0f, 10.0f); + FLOAT fA = FRnd()*360.0f; + m_vSpeed = FLOAT3D(CosFast(fA)*fR, 0, SinFast(fA)*fR); + m_bMoving = m_bMovingAllowed; + + // move in range + while(_pTimer->CurrentTick() < m_fStopTime) { + FLOAT fMoveTime = FRndIn(2.0f, 4.0f); + m_aSpeedRotation = FLOAT3D(FRndIn(8.0f, 16.0f), 0.0f, 0.0f); + m_tmLastMove = _pTimer->CurrentTick(); + // NOTE: fMoveTime will cause the twister to stop existing + // a bit later then the m_fStopTime, but what the heck? + wait(fMoveTime) { + on (EBegin) : { resume; } + on (ETimer) : { stop; } + on (EPass ep) : { + if (ep.penOther->GetRenderType()&RT_MODEL && + ep.penOther->GetPhysicsFlags()&EPF_MOVABLE && + !IsOfClass(ep.penOther, "Twister")) { + SpinEntity(ep.penOther); + } + resume; + } + } + } + + // fade out + m_fFadeStartTime = _pTimer->CurrentTick(); + m_bFadeOut = TRUE; + m_fFadeTime = 2.0f; + autowait(m_fFadeTime); + + // cease to exist + Destroy(); + + return; + } +}; diff --git a/Sources/EntitiesMP/Twister.h b/Sources/EntitiesMP/Twister.h new file mode 100644 index 0000000..7e1a34f --- /dev/null +++ b/Sources/EntitiesMP/Twister.h @@ -0,0 +1,83 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Twister_INCLUDED +#define _EntitiesMP_Twister_INCLUDED 1 +#include +#include +#include +#define EVENTCODE_ETwister 0x01fb0000 +class DECL_DLL ETwister : public CEntityEvent { +public: +ETwister(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOwner; +FLOAT fSize; +FLOAT fDuration; +INDEX sgnSpinDir; +BOOL bGrow; +BOOL bMovingAllowed; +}; +DECL_DLL inline void ClearToDefault(ETwister &e) { e = ETwister(); } ; +extern "C" DECL_DLL CDLLEntityClass CTwister_DLLClass; +class CTwister : public CMovableModelEntity { +public: + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penOwner; + FLOAT m_fSize; + FLOAT3D m_vSpeed; + INDEX m_sgnSpinDir; + BOOL m_bGrow; + FLOAT m_tmLastMove; + FLOAT3D m_aSpeedRotation; + BOOL m_bMoving; + BOOL m_bMovingAllowed; + FLOAT3D m_vDesiredPosition; + FLOAT3D m_vDesiredAngle; + FLOAT m_fStopTime; + FLOAT m_fActionRadius; + FLOAT m_fActionTime; + FLOAT m_fDiffMultiply; + FLOAT m_fUpMultiply; + BOOL m_bFadeOut; + FLOAT m_fFadeStartTime; + FLOAT m_fFadeTime; + FLOAT m_fStartTime; + CSoundObject m_soSpin; + +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +void * GetEntityInfo(void); + +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +void RenderParticles(void); + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +BOOL AdjustShadingParameters(FLOAT3D & vLightDirection,COLOR & colLight,COLOR & colAmbient); + +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +void SpinEntity(CEntity * pen); + +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +void PreMoving(void); +#define STATE_CTwister_Main 1 + BOOL +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01fb0001_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01fb0002_Main_02(const CEntityEvent &__eeInput); + BOOL H0x01fb0003_Main_03(const CEntityEvent &__eeInput); + BOOL H0x01fb0004_Main_04(const CEntityEvent &__eeInput); + BOOL H0x01fb0005_Main_05(const CEntityEvent &__eeInput); + BOOL H0x01fb0006_Main_06(const CEntityEvent &__eeInput); + BOOL H0x01fb0007_Main_07(const CEntityEvent &__eeInput); + BOOL H0x01fb0008_Main_08(const CEntityEvent &__eeInput); + BOOL H0x01fb0009_Main_09(const CEntityEvent &__eeInput); + BOOL H0x01fb000a_Main_10(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Twister_INCLUDED diff --git a/Sources/EntitiesMP/Twister_tables.h b/Sources/EntitiesMP/Twister_tables.h new file mode 100644 index 0000000..d6e4b4f --- /dev/null +++ b/Sources/EntitiesMP/Twister_tables.h @@ -0,0 +1,70 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CTwister + +CEntityProperty CTwister_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001fb<<8)+1, offsetof(CTwister, m_penOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+2, offsetof(CTwister, m_fSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001fb<<8)+3, offsetof(CTwister, m_vSpeed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000001fb<<8)+4, offsetof(CTwister, m_sgnSpinDir), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001fb<<8)+5, offsetof(CTwister, m_bGrow), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+6, offsetof(CTwister, m_tmLastMove), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001fb<<8)+7, offsetof(CTwister, m_aSpeedRotation), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001fb<<8)+8, offsetof(CTwister, m_bMoving), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001fb<<8)+9, offsetof(CTwister, m_bMovingAllowed), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001fb<<8)+10, offsetof(CTwister, m_vDesiredPosition), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x000001fb<<8)+11, offsetof(CTwister, m_vDesiredAngle), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+12, offsetof(CTwister, m_fStopTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+13, offsetof(CTwister, m_fActionRadius), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+14, offsetof(CTwister, m_fActionTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+15, offsetof(CTwister, m_fDiffMultiply), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+16, offsetof(CTwister, m_fUpMultiply), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000001fb<<8)+20, offsetof(CTwister, m_bFadeOut), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+21, offsetof(CTwister, m_fFadeStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+22, offsetof(CTwister, m_fFadeTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fb<<8)+23, offsetof(CTwister, m_fStartTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x000001fb<<8)+50, offsetof(CTwister, m_soSpin), "", 0, 0, 0), +}; +#define CTwister_propertiesct ARRAYCOUNT(CTwister_properties) + +CEntityComponent CTwister_components[] = { +#define CLASS_SPINNER ((0x000001fb<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_SPINNER, "EFNM" "Classes\\Spinner.ecl"), +#define MODEL_TWISTER ((0x000001fb<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_TWISTER, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Twister.mdl"), +#define TEXTURE_TWISTER ((0x000001fb<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_TWISTER, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Twister.tex"), +#define SOUND_SPIN ((0x000001fb<<8)+200) + CEntityComponent(ECT_SOUND, SOUND_SPIN, "EFNM" "ModelsMP\\Enemies\\AirElemental\\Sounds\\TwisterSpin.wav"), +}; +#define CTwister_componentsct ARRAYCOUNT(CTwister_components) + +CEventHandlerEntry CTwister_handlers[] = { + {1, -1, CEntity::pEventHandler(&CTwister:: +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Twister.es" +Main),DEBUGSTRING("CTwister::Main")}, + {0x01fb0001, -1, CEntity::pEventHandler(&CTwister::H0x01fb0001_Main_01), DEBUGSTRING("CTwister::H0x01fb0001_Main_01")}, + {0x01fb0002, -1, CEntity::pEventHandler(&CTwister::H0x01fb0002_Main_02), DEBUGSTRING("CTwister::H0x01fb0002_Main_02")}, + {0x01fb0003, -1, CEntity::pEventHandler(&CTwister::H0x01fb0003_Main_03), DEBUGSTRING("CTwister::H0x01fb0003_Main_03")}, + {0x01fb0004, -1, CEntity::pEventHandler(&CTwister::H0x01fb0004_Main_04), DEBUGSTRING("CTwister::H0x01fb0004_Main_04")}, + {0x01fb0005, -1, CEntity::pEventHandler(&CTwister::H0x01fb0005_Main_05), DEBUGSTRING("CTwister::H0x01fb0005_Main_05")}, + {0x01fb0006, -1, CEntity::pEventHandler(&CTwister::H0x01fb0006_Main_06), DEBUGSTRING("CTwister::H0x01fb0006_Main_06")}, + {0x01fb0007, -1, CEntity::pEventHandler(&CTwister::H0x01fb0007_Main_07), DEBUGSTRING("CTwister::H0x01fb0007_Main_07")}, + {0x01fb0008, -1, CEntity::pEventHandler(&CTwister::H0x01fb0008_Main_08), DEBUGSTRING("CTwister::H0x01fb0008_Main_08")}, + {0x01fb0009, -1, CEntity::pEventHandler(&CTwister::H0x01fb0009_Main_09), DEBUGSTRING("CTwister::H0x01fb0009_Main_09")}, + {0x01fb000a, -1, CEntity::pEventHandler(&CTwister::H0x01fb000a_Main_10), DEBUGSTRING("CTwister::H0x01fb000a_Main_10")}, +}; +#define CTwister_handlersct ARRAYCOUNT(CTwister_handlers) + +CEntity *CTwister_New(void) { return new CTwister; }; +void CTwister_OnInitClass(void) {}; +void CTwister_OnEndClass(void) {}; +void CTwister_OnPrecache(CDLLEntityClass *pdec, INDEX iUser); +void CTwister_OnWorldEnd(CWorld *pwo) {}; +void CTwister_OnWorldInit(CWorld *pwo) {}; +void CTwister_OnWorldTick(CWorld *pwo) {}; +void CTwister_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CTwister, CMovableModelEntity, "Twister", "", 0x000001fb); +DECLARE_CTFILENAME(_fnmCTwister_tbn, ""); diff --git a/Sources/EntitiesMP/VoiceHolder.cpp b/Sources/EntitiesMP/VoiceHolder.cpp new file mode 100644 index 0000000..efc0e3d --- /dev/null +++ b/Sources/EntitiesMP/VoiceHolder.cpp @@ -0,0 +1,116 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" + +#include "StdH.h" +extern INDEX ent_bReportBrokenChains; + +#include +#include +void CVoiceHolder::SetDefaultProperties(void) { + m_strName = "VoiceHolder"; + m_strDescription = ""; + m_fnmMessage = CTString(""); + m_bActive = TRUE ; + m_ctMaxTrigs = 1; + CRationalEntity::SetDefaultProperties(); +} + +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +void CVoiceHolder::Precache(void) +#line 30 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +{ +#line 31 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +m_aps . Precache (m_fnmMessage ); +#line 32 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +} + +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +const CTString & CVoiceHolder::GetDescription(void)const { +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +((CTString &) m_strDescription ) . PrintF ("%s" , m_fnmMessage . FileName ()); +#line 35 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +return m_strDescription ; +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +} +BOOL CVoiceHolder:: +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CVoiceHolder_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CVoiceHolder::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +InitAsEditorModel (); +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +SetModel (MODEL_MARKER ); +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +SetModelMainTexture (TEXTURE_MARKER ); +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x00e70000, FALSE, EBegin());return TRUE;}BOOL CVoiceHolder::H0x00e70000_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e70000 +switch(__eeInput.ee_slEvent){case(EVENTCODE_ETrigger):{const ETrigger&eTrigger= (ETrigger&)__eeInput; + +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +if(! m_bActive ){ +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +return TRUE; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +} +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +CEntity * penCaused = FixupCausedToPlayer (this , eTrigger . penCaused ); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +EVoiceMessage eMsg ; +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +eMsg . fnmMessage = m_fnmMessage ; +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +penCaused -> SendEvent (eMsg ); +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +if(m_ctMaxTrigs > 0){ +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +m_ctMaxTrigs -= 1; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +if(m_ctMaxTrigs <= 0){ +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +Destroy (); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +UnsetTimer();Jump(STATE_CURRENT,0x00e70001, FALSE, EInternal());return TRUE; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +} +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +} +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +return TRUE; +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +m_bActive = TRUE ; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +return TRUE; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeactivate):{const EDeactivate&e= (EDeactivate&)__eeInput; + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +m_bActive = FALSE ; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +return TRUE; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +}return TRUE;}BOOL CVoiceHolder::H0x00e70001_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x00e70001 + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +Return(STATE_CURRENT,EVoid()); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/VoiceHolder.es b/Sources/EntitiesMP/VoiceHolder.es new file mode 100644 index 0000000..8845661 --- /dev/null +++ b/Sources/EntitiesMP/VoiceHolder.es @@ -0,0 +1,82 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +231 +%{ +#include "StdH.h" +extern INDEX ent_bReportBrokenChains; +%} + +class CVoiceHolder : CRationalEntity { +name "VoiceHolder"; +thumbnail "Thumbnails\\VoiceHolder.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CTString m_strName "Name" 'N' = "VoiceHolder", + 3 CTString m_strDescription = "", + 2 CTFileName m_fnmMessage "Message" 'M' = CTString(""), + 5 BOOL m_bActive "Active" 'A' = TRUE, + 6 INDEX m_ctMaxTrigs "Max trigs" 'X' = 1, // how many times could trig + + { + CAutoPrecacheSound m_aps; + } +components: + 1 model MODEL_MARKER "Models\\Editor\\VoiceHolder.mdl", + 2 texture TEXTURE_MARKER "Models\\Editor\\VoiceHolder.tex" + +functions: + void Precache(void) + { + m_aps.Precache(m_fnmMessage); + } + const CTString &GetDescription(void) const { + ((CTString&)m_strDescription).PrintF("%s", m_fnmMessage.FileName()); + return m_strDescription; + } + +procedures: + Main() + { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_MARKER); + SetModelMainTexture(TEXTURE_MARKER); + wait() { + on (ETrigger eTrigger): { + if (!m_bActive) { + resume; + } + CEntity *penCaused = FixupCausedToPlayer(this, eTrigger.penCaused); + EVoiceMessage eMsg; + eMsg.fnmMessage = m_fnmMessage; + penCaused->SendEvent(eMsg); + // if max trig count is used for counting + if(m_ctMaxTrigs > 0) { + // decrease count + m_ctMaxTrigs-=1; + // if we trigged max times + if( m_ctMaxTrigs <= 0) { + // cease to exist + Destroy(); + stop; + } + } + resume; + } + on (EActivate): { + m_bActive = TRUE; + resume; + } + on (EDeactivate): { + m_bActive = FALSE; + resume; + } + } + return; + } +}; + diff --git a/Sources/EntitiesMP/VoiceHolder.h b/Sources/EntitiesMP/VoiceHolder.h new file mode 100644 index 0000000..11ef425 --- /dev/null +++ b/Sources/EntitiesMP/VoiceHolder.h @@ -0,0 +1,32 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_VoiceHolder_INCLUDED +#define _EntitiesMP_VoiceHolder_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CVoiceHolder_DLLClass; +class CVoiceHolder : public CRationalEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsTargetable(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + CTFileName m_fnmMessage; + BOOL m_bActive; + INDEX m_ctMaxTrigs; +CAutoPrecacheSound m_aps; + +#line 29 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +void Precache(void); + +#line 33 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +const CTString & GetDescription(void)const; +#define STATE_CVoiceHolder_Main 1 + BOOL +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x00e70000_Main_01(const CEntityEvent &__eeInput); + BOOL H0x00e70001_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_VoiceHolder_INCLUDED diff --git a/Sources/EntitiesMP/VoiceHolder_tables.h b/Sources/EntitiesMP/VoiceHolder_tables.h new file mode 100644 index 0000000..d38bda1 --- /dev/null +++ b/Sources/EntitiesMP/VoiceHolder_tables.h @@ -0,0 +1,42 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CVoiceHolder + +CEntityProperty CVoiceHolder_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e7<<8)+1, offsetof(CVoiceHolder, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000e7<<8)+3, offsetof(CVoiceHolder, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FILENAME, NULL, (0x000000e7<<8)+2, offsetof(CVoiceHolder, m_fnmMessage), "Message", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000e7<<8)+5, offsetof(CVoiceHolder, m_bActive), "Active", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000000e7<<8)+6, offsetof(CVoiceHolder, m_ctMaxTrigs), "Max trigs", 'X', 0x7F0000FFUL, 0), +}; +#define CVoiceHolder_propertiesct ARRAYCOUNT(CVoiceHolder_properties) + +CEntityComponent CVoiceHolder_components[] = { +#define MODEL_MARKER ((0x000000e7<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_MARKER, "EFNM" "Models\\Editor\\VoiceHolder.mdl"), +#define TEXTURE_MARKER ((0x000000e7<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_MARKER, "EFNM" "Models\\Editor\\VoiceHolder.tex"), +}; +#define CVoiceHolder_componentsct ARRAYCOUNT(CVoiceHolder_components) + +CEventHandlerEntry CVoiceHolder_handlers[] = { + {1, -1, CEntity::pEventHandler(&CVoiceHolder:: +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/VoiceHolder.es" +Main),DEBUGSTRING("CVoiceHolder::Main")}, + {0x00e70000, -1, CEntity::pEventHandler(&CVoiceHolder::H0x00e70000_Main_01), DEBUGSTRING("CVoiceHolder::H0x00e70000_Main_01")}, + {0x00e70001, -1, CEntity::pEventHandler(&CVoiceHolder::H0x00e70001_Main_02), DEBUGSTRING("CVoiceHolder::H0x00e70001_Main_02")}, +}; +#define CVoiceHolder_handlersct ARRAYCOUNT(CVoiceHolder_handlers) + +CEntity *CVoiceHolder_New(void) { return new CVoiceHolder; }; +void CVoiceHolder_OnInitClass(void) {}; +void CVoiceHolder_OnEndClass(void) {}; +void CVoiceHolder_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CVoiceHolder_OnWorldEnd(CWorld *pwo) {}; +void CVoiceHolder_OnWorldInit(CWorld *pwo) {}; +void CVoiceHolder_OnWorldTick(CWorld *pwo) {}; +void CVoiceHolder_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CVoiceHolder, CRationalEntity, "VoiceHolder", "Thumbnails\\VoiceHolder.tbn", 0x000000e7); +DECLARE_CTFILENAME(_fnmCVoiceHolder_tbn, "Thumbnails\\VoiceHolder.tbn"); diff --git a/Sources/EntitiesMP/Walker.cpp b/Sources/EntitiesMP/Walker.cpp new file mode 100644 index 0000000..bce63e9 --- /dev/null +++ b/Sources/EntitiesMP/Walker.cpp @@ -0,0 +1,786 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" + +#include "StdH.h" +#include "Models/Enemies/Walker/Walker.h" + +#include +#include +#line 17 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" + +// info structure +static EntityInfo eiWalker = { + EIBT_FLESH, 1000.0f, + 0.0f, 5.4f, 0.0f, + 0.0f, 4.5f, 0.0f, +}; + +#define SIZE_SOLDIER (0.5f) +#define SIZE_SERGEANT (1.0f) +#define FIRE_LEFT_ARM FLOAT3D(-2.5f, 5.0f, 0.0f) +#define FIRE_RIGHT_ARM FLOAT3D(+2.5f, 5.0f, 0.0f) +#define FIRE_DEATH_LEFT FLOAT3D( 0.0f, 7.0f, -2.0f) +#define FIRE_DEATH_RIGHT FLOAT3D(3.75f, 4.2f, -2.5f) + +#define WALKERSOUND(soundname) ((m_EwcChar==WLC_SOLDIER)? (SOUND_SOLDIER_##soundname) : (SOUND_SERGEANT_##soundname)) + +void CWalker::SetDefaultProperties(void) { + m_EwcChar = WLC_SOLDIER ; + m_iLoopCounter = 0; + m_fSize = 1.0f; + m_bWalkSoundPlaying = FALSE ; + m_fThreatDistance = 5.0f; + m_soFeet.SetOwner(this); +m_soFeet.Stop_internal(); + m_soFire1.SetOwner(this); +m_soFire1.Stop_internal(); + m_soFire2.SetOwner(this); +m_soFire2.Stop_internal(); + m_soFire3.SetOwner(this); +m_soFire3.Stop_internal(); + m_soFire4.SetOwner(this); +m_soFire4.Stop_internal(); + CEnemyBase::SetDefaultProperties(); +} + CTString CWalker::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CTString str ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +str . PrintF (TRANS ("A Biomech blew %s away") , strPlayerName ); +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +return str ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + const CTFileName & CWalker::GetComputerMessageName(void)const { +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +static DECLARE_CTFILENAME (fnmSoldier , "Data\\Messages\\Enemies\\WalkerSmall.txt"); +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +static DECLARE_CTFILENAME (fnmSergeant , "Data\\Messages\\Enemies\\WalkerBig.txt"); +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +switch(m_EwcChar ){ +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +default : ASSERT (FALSE ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +case WLC_SOLDIER : return fnmSoldier ; +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +case WLC_SERGEANT : return fnmSergeant ; +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +FLOAT CWalker::GetThreatDistance(void) +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +return m_fThreatDistance ; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +BOOL CWalker::ForcesCannonballToExplode(void) +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(m_EwcChar == WLC_SERGEANT ){ +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +return TRUE ; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +return CEnemyBase :: ForcesCannonballToExplode (); +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::Precache(void) { +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CEnemyBase :: Precache (); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheModel (MODEL_WALKER ); +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(m_EwcChar == WLC_SOLDIER ) +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheSound (SOUND_SOLDIER_IDLE ); +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheSound (SOUND_SOLDIER_SIGHT ); +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheSound (SOUND_SOLDIER_DEATH ); +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheSound (SOUND_SOLDIER_FIRE_LASER ); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheSound (SOUND_SOLDIER_WALK ); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheTexture (TEXTURE_WALKER_SOLDIER ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheModel (MODEL_LASER ); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheTexture (TEXTURE_LASER ); +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheClass (CLASS_PROJECTILE , PRT_CYBORG_LASER ); +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +else +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheSound (SOUND_SERGEANT_IDLE ); +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheSound (SOUND_SERGEANT_SIGHT ); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheSound (SOUND_SERGEANT_DEATH ); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheSound (SOUND_SERGEANT_FIRE_ROCKET ); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheSound (SOUND_SERGEANT_WALK ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheTexture (TEXTURE_WALKER_SERGEANT ); +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheModel (MODEL_ROCKETLAUNCHER ); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheTexture (TEXTURE_ROCKETLAUNCHER ); +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PrecacheClass (CLASS_PROJECTILE , PRT_WALKER_ROCKET ); +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void * CWalker::GetEntityInfo(void) { +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +return & eiWalker ; +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +FLOAT CWalker::GetCrushHealth(void) +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(m_EwcChar == WLC_SERGEANT ){ +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +return 100.0f; +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +return 0.0f; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(dmtType == DMT_BULLET && fDamageAmmount > 100.0f) +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +fDamageAmmount *= 0.666f; +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(! IsOfClass (penInflictor , "Walker") || +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +((CWalker *) penInflictor ) -> m_EwcChar != m_EwcChar ){ +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::StandingAnim(void) { +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +DeactivateWalkingSound (); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StartModelAnim (WALKER_ANIM_STAND01 , AOF_LOOPING | AOF_NORESTART ); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::StandingAnimFight(void) +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +DeactivateWalkingSound (); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StartModelAnim (WALKER_ANIM_IDLEFIGHT , AOF_LOOPING | AOF_NORESTART ); +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::WalkingAnim(void) { +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ActivateWalkingSound (); +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(m_EwcChar == WLC_SERGEANT ){ +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StartModelAnim (WALKER_ANIM_WALKBIG , AOF_LOOPING | AOF_NORESTART ); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else { +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StartModelAnim (WALKER_ANIM_WALK , AOF_LOOPING | AOF_NORESTART ); +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::RunningAnim(void) { +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +WalkingAnim (); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::RotatingAnim(void) { +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +WalkingAnim (); +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::IdleSound(void) { +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soSound , WALKERSOUND (IDLE ) , SOF_3D ); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::SightSound(void) { +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soSound , WALKERSOUND (SIGHT ) , SOF_3D ); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::DeathSound(void) { +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soSound , WALKERSOUND (DEATH ) , SOF_3D ); +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::ActivateWalkingSound(void) +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(! m_bWalkSoundPlaying ){ +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soFeet , WALKERSOUND (WALK ) , SOF_3D | SOF_LOOP ); +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_bWalkSoundPlaying = TRUE ; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::DeactivateWalkingSound(void) +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_soFeet . Stop (); +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_bWalkSoundPlaying = FALSE ; +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::FireDeathRocket(FLOAT3D & vPos) { +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CPlacement3D plRocket ; +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +plRocket . pl_PositionVector = vPos ; +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +plRocket . pl_OrientationAngle = ANGLE3D (0 , - 5.0f - FRnd () * 10.0f , 0); +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +plRocket . RelativeToAbsolute (GetPlacement ()); +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CEntityPointer penProjectile = CreateEntity (plRocket , CLASS_PROJECTILE ); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ELaunchProjectile eLaunch ; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +eLaunch . penLauncher = this ; +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +eLaunch . prtType = PRT_WALKER_ROCKET ; +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +penProjectile -> Initialize (eLaunch ); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::FireDeathLaser(FLOAT3D & vPos) { +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CPlacement3D plLaser ; +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +plLaser . pl_PositionVector = vPos ; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +plLaser . pl_OrientationAngle = ANGLE3D (0 , - 5.0f - FRnd () * 10.0f , 0); +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +plLaser . RelativeToAbsolute (GetPlacement ()); +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CEntityPointer penProjectile = CreateEntity (plLaser , CLASS_PROJECTILE ); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ELaunchProjectile eLaunch ; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +eLaunch . penLauncher = this ; +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +eLaunch . prtType = PRT_CYBORG_LASER ; +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +penProjectile -> Initialize (eLaunch ); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} + +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void CWalker::EnemyPostInit(void) +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_soSound . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_soFeet . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_soFire1 . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_soFire2 . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_soFire3 . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_soFire4 . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +BOOL CWalker:: +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Fire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWalker_Fire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWalker::Fire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +DeactivateWalkingSound (); +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StartModelAnim (WALKER_ANIM_TOFIRE , 0); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fLockOnEnemyTime = GetModelObject () -> GetAnimLength (WALKER_ANIM_TOFIRE ); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +STATE_CEnemyBase_LockOnEnemy, FALSE; +Jump(STATE_CURRENT, 0x01440001, FALSE, EBegin());return TRUE;}BOOL CWalker::H0x01440001_Fire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_LockOnEnemy, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01440002, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CWalker::H0x01440002_Fire_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440002 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(!(m_EwcChar == WLC_SERGEANT )){ Jump(STATE_CURRENT,0x01440005, FALSE, EInternal());return TRUE;} +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StartModelAnim (WALKER_ANIM_FIRERIGHT , AOF_LOOPING ); +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ShootProjectile (PRT_WALKER_ROCKET , FIRE_RIGHT_ARM * m_fSize , ANGLE3D (0 , 0 , 0)); +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soFire1 , SOUND_SERGEANT_FIRE_ROCKET , SOF_3D ); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(GetSP () -> sp_gdGameDifficulty <= CSessionProperties :: GD_EASY ){ +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fLockOnEnemyTime = 1.0f; +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else { +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fLockOnEnemyTime = 0.5f; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +STATE_CEnemyBase_LockOnEnemy, FALSE; +Jump(STATE_CURRENT, 0x01440003, FALSE, EBegin());return TRUE;}BOOL CWalker::H0x01440003_Fire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_LockOnEnemy, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01440004, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CWalker::H0x01440004_Fire_04(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440004 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StartModelAnim (WALKER_ANIM_FIRELEFT , AOF_LOOPING ); +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ShootProjectile (PRT_WALKER_ROCKET , FIRE_LEFT_ARM * m_fSize , ANGLE3D (0 , 0 , 0)); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soFire2 , SOUND_SERGEANT_FIRE_ROCKET , SOF_3D );Jump(STATE_CURRENT,0x01440005, FALSE, EInternal());return TRUE;}BOOL CWalker::H0x01440005_Fire_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440005 + +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(!(m_EwcChar == WLC_SOLDIER )){ Jump(STATE_CURRENT,0x0144000b, FALSE, EInternal());return TRUE;} +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(GetSP () -> sp_gdGameDifficulty <= CSessionProperties :: GD_EASY ){ +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_iLoopCounter = 4; +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else { +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_iLoopCounter = 8; +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Jump(STATE_CURRENT,0x01440009, FALSE, EInternal());return TRUE;}BOOL CWalker::H0x01440009_Fire_09(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440009 +if(!(m_iLoopCounter > 0)){ Jump(STATE_CURRENT,0x0144000a, FALSE, EInternal());return TRUE;} +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(m_iLoopCounter % 2){ +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StartModelAnim (WALKER_ANIM_FIRELEFT , AOF_LOOPING ); +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ShootProjectile (PRT_CYBORG_LASER , FIRE_LEFT_ARM * m_fSize , ANGLE3D (0 , 0 , 0)); +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else { +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StartModelAnim (WALKER_ANIM_FIRERIGHT , AOF_LOOPING ); +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ShootProjectile (PRT_CYBORG_LASER , FIRE_RIGHT_ARM * m_fSize , ANGLE3D (0 , 0 , 0)); +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +INDEX iChannel = m_iLoopCounter % 4; +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(iChannel == 0){ +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soFire1 , SOUND_SOLDIER_FIRE_LASER , SOF_3D ); +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else if(iChannel == 1){ +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soFire2 , SOUND_SOLDIER_FIRE_LASER , SOF_3D ); +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else if(iChannel == 2){ +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soFire3 , SOUND_SOLDIER_FIRE_LASER , SOF_3D ); +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else if(iChannel == 3){ +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soFire4 , SOUND_SOLDIER_FIRE_LASER , SOF_3D ); +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(!(m_iLoopCounter > 1)){ Jump(STATE_CURRENT,0x01440008, FALSE, EInternal());return TRUE;} +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(GetSP () -> sp_gdGameDifficulty <= CSessionProperties :: GD_EASY ){ +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fLockOnEnemyTime = 0.4f; +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else { +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fLockOnEnemyTime = 0.1f; +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +STATE_CEnemyBase_LockOnEnemy, FALSE; +Jump(STATE_CURRENT, 0x01440006, FALSE, EBegin());return TRUE;}BOOL CWalker::H0x01440006_Fire_06(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440006 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_LockOnEnemy, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01440007, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CWalker::H0x01440007_Fire_07(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440007 +const EReturn&__e= (EReturn&)__eeInput; +;Jump(STATE_CURRENT,0x01440008, FALSE, EInternal());return TRUE;}BOOL CWalker::H0x01440008_Fire_08(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440008 + +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_iLoopCounter --;Jump(STATE_CURRENT,0x01440009, FALSE, EInternal());return TRUE; +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}BOOL CWalker::H0x0144000a_Fire_10(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0144000a +Jump(STATE_CURRENT,0x0144000b, FALSE, EInternal());return TRUE;}BOOL CWalker::H0x0144000b_Fire_11(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0144000b + +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StopMoving (); +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +MaybeSwitchToAnotherPlayer (); +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StartModelAnim (WALKER_ANIM_FROMFIRE , 0); +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetTimerAfter(GetModelObject () -> GetAnimLength (WALKER_ANIM_FROMFIRE )); +Jump(STATE_CURRENT, 0x0144000c, FALSE, EBegin());return TRUE;}BOOL CWalker::H0x0144000c_Fire_12(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0144000c +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0144000d, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWalker::H0x0144000d_Fire_13(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0144000d +; +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StandingAnimFight (); +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetTimerAfter(FRnd () * 0.1f + 0.1f); +Jump(STATE_CURRENT, 0x0144000e, FALSE, EBegin());return TRUE;}BOOL CWalker::H0x0144000e_Fire_14(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0144000e +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0144000f, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWalker::H0x0144000f_Fire_15(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0144000f +; +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Return(STATE_CURRENT,EReturn ()); +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWalker:: +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Death(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWalker_Death + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWalker::Death expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StopMoving (); +#line 397 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +DeathSound (); +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +DeactivateWalkingSound (); +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetCollisionFlags (ECF_MODEL ); +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetFlags (GetFlags () | ENF_SEETHROUGH ); +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ChangeCollisionBoxIndexWhenPossible (WALKER_COLLISION_BOX_DEATH ); +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StartModelAnim (WALKER_ANIM_DEATH , 0); +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetTimerAfter(0.9f); +Jump(STATE_CURRENT, 0x01440011, FALSE, EBegin());return TRUE;}BOOL CWalker::H0x01440011_Death_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440011 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01440012, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWalker::H0x01440012_Death_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440012 +; +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(m_EwcChar == WLC_SERGEANT ){ +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(IRnd () & 1){ +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +FireDeathRocket (FIRE_DEATH_RIGHT * m_fSize ); +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else { +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +FireDeathRocket (FIRE_DEATH_LEFT * m_fSize ); +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soSound , SOUND_SERGEANT_FIRE_ROCKET , SOF_3D ); +#line 419 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(m_EwcChar == WLC_SOLDIER ){ +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(IRnd () & 1){ +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +FireDeathLaser (FIRE_DEATH_RIGHT * m_fSize ); +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else { +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +FireDeathLaser (FIRE_DEATH_LEFT * m_fSize ); +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 426 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +PlaySound (m_soFire2 , SOUND_SOLDIER_FIRE_LASER , SOF_3D ); +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetTimerAfter(0.25f); +Jump(STATE_CURRENT, 0x01440013, FALSE, EBegin());return TRUE;}BOOL CWalker::H0x01440013_Death_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440013 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01440014, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWalker::H0x01440014_Death_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440014 +; +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +FLOAT fStretch = 2.0f; +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(m_EwcChar == WLC_SERGEANT ) +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +{ +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +fStretch = 4.0f; +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CPlacement3D plFX = GetPlacement (); +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ESpawnEffect ese ; +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ese . colMuliplier = C_WHITE | CT_OPAQUE ; +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ese . vStretch = FLOAT3D (1.5 , 1 , 1) * fStretch ; +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ese . vNormal = FLOAT3D (0 , 1 , 0); +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ese . betType = BET_DUST_FALL ; +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CPlacement3D plSmoke = plFX ; +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +plSmoke . pl_PositionVector += FLOAT3D (0 , 0.35f * ese . vStretch (2) , 0); +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CEntityPointer penFX = CreateEntity (plSmoke , CLASS_BASIC_EFFECT ); +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +penFX -> Initialize (ese ); +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetTimerAfter(0.35f); +Jump(STATE_CURRENT, 0x01440015, FALSE, EBegin());return TRUE;}BOOL CWalker::H0x01440015_Death_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440015 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01440016, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWalker::H0x01440016_Death_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01440016 +; +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Return(STATE_CURRENT,EEnd ()); +#line 449 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWalker:: +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWalker_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWalker::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +InitAsModel (); +#line 458 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 459 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetCollisionFlags (ECF_MODEL ); +#line 460 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 461 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(m_EwcChar == WLC_SERGEANT ){ +#line 462 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetHealth (750.0f); +#line 463 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fMaxHealth = 750.0f; +#line 464 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else { +#line 465 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetHealth (150.0f); +#line 466 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fMaxHealth = 150.0f; +#line 467 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 468 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +en_fDensity = 3000.0f; +#line 470 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_sptType = SPT_ELECTRICITY_SPARKS ; +#line 473 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetModel (MODEL_WALKER ); +#line 474 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(m_EwcChar == WLC_SERGEANT ){ +#line 475 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fSize = 1.0f; +#line 476 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetModelMainTexture (TEXTURE_WALKER_SERGEANT ); +#line 477 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +AddAttachment (WALKER_ATTACHMENT_ROCKETLAUNCHER_LT , MODEL_ROCKETLAUNCHER , TEXTURE_ROCKETLAUNCHER ); +#line 478 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +AddAttachment (WALKER_ATTACHMENT_ROCKETLAUNCHER_RT , MODEL_ROCKETLAUNCHER , TEXTURE_ROCKETLAUNCHER ); +#line 479 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +GetModelObject () -> StretchModel (FLOAT3D (1 , 1 , 1)); +#line 480 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ModelChangeNotify (); +#line 481 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CModelObject * pmoRight = & GetModelObject () -> GetAttachmentModel (WALKER_ATTACHMENT_ROCKETLAUNCHER_RT ) -> amo_moModelObject ; +#line 482 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +pmoRight -> StretchModel (FLOAT3D (- 1 , 1 , 1)); +#line 483 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fBlowUpAmount = 1E10f; +#line 484 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_iScore = 7500; +#line 485 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fThreatDistance = 15; +#line 486 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +}else { +#line 487 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fSize = 0.5f; +#line 488 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +SetModelMainTexture (TEXTURE_WALKER_SOLDIER ); +#line 489 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +AddAttachment (WALKER_ATTACHMENT_LASER_LT , MODEL_LASER , TEXTURE_LASER ); +#line 490 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +AddAttachment (WALKER_ATTACHMENT_LASER_RT , MODEL_LASER , TEXTURE_LASER ); +#line 491 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +GetModelObject () -> StretchModel (FLOAT3D (0.5f , 0.5f , 0.5f)); +#line 492 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +ModelChangeNotify (); +#line 493 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +CModelObject * pmoRight = & GetModelObject () -> GetAttachmentModel (WALKER_ATTACHMENT_LASER_RT ) -> amo_moModelObject ; +#line 494 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +pmoRight -> StretchModel (FLOAT3D (- 0.5f , 0.5f , 0.5f)); +#line 495 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fBlowUpAmount = 1E10f; +#line 498 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_iScore = 2000; +#line 499 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fThreatDistance = 5; +#line 500 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 501 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +if(m_fStepHeight == - 1){ +#line 502 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fStepHeight = 4.0f; +#line 503 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +} +#line 505 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +StandingAnim (); +#line 507 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fWalkSpeed = FRnd () * 1.5f + 9.0f; +#line 508 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 50.0f + 500.0f); +#line 509 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fAttackRunSpeed = m_fWalkSpeed ; +#line 510 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_aAttackRotateSpeed = m_aWalkRotateSpeed / 2; +#line 511 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fCloseRunSpeed = m_fWalkSpeed ; +#line 512 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_aCloseRotateSpeed = m_aWalkRotateSpeed / 2; +#line 513 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fWalkSpeed /= 2.0f; +#line 515 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fAttackDistance = 150.0f; +#line 516 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fCloseDistance = 0.0f; +#line 517 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fStopDistance = 15.0f; +#line 518 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fAttackFireTime = 3.0f; +#line 519 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fCloseFireTime = 1.0f; +#line 520 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fIgnoreRange = 300.0f; +#line 522 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fBodyParts = 8; +#line 523 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +m_fDamageWounded = 100000.0f; +#line 526 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Jump(STATE_CURRENT, STATE_CEnemyBase_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Walker.es b/Sources/EntitiesMP/Walker.es new file mode 100644 index 0000000..c31c94d --- /dev/null +++ b/Sources/EntitiesMP/Walker.es @@ -0,0 +1,528 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +324 +%{ +#include "StdH.h" +#include "Models/Enemies/Walker/Walker.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/Projectile"; + +enum WalkerChar { + 0 WLC_SOLDIER "Soldier", // soldier + 1 WLC_SERGEANT "Sergeant", // sergeant +}; + +%{ +// info structure +static EntityInfo eiWalker = { + EIBT_FLESH, 1000.0f, + 0.0f, 5.4f, 0.0f, + 0.0f, 4.5f, 0.0f, +}; + +#define SIZE_SOLDIER (0.5f) +#define SIZE_SERGEANT (1.0f) +#define FIRE_LEFT_ARM FLOAT3D(-2.5f, 5.0f, 0.0f) +#define FIRE_RIGHT_ARM FLOAT3D(+2.5f, 5.0f, 0.0f) +#define FIRE_DEATH_LEFT FLOAT3D( 0.0f, 7.0f, -2.0f) +#define FIRE_DEATH_RIGHT FLOAT3D(3.75f, 4.2f, -2.5f) + +#define WALKERSOUND(soundname) ((m_EwcChar==WLC_SOLDIER)? (SOUND_SOLDIER_##soundname) : (SOUND_SERGEANT_##soundname)) +%} + + +class CWalker : CEnemyBase { +name "Walker"; +thumbnail "Thumbnails\\Walker.tbn"; + +properties: + 1 enum WalkerChar m_EwcChar "Character" 'C' = WLC_SOLDIER, + 2 INDEX m_iLoopCounter = 0, + 3 FLOAT m_fSize = 1.0f, + 4 BOOL m_bWalkSoundPlaying = FALSE, + 5 FLOAT m_fThreatDistance = 5.0f, + + 10 CSoundObject m_soFeet, + 11 CSoundObject m_soFire1, + 12 CSoundObject m_soFire2, + 13 CSoundObject m_soFire3, + 14 CSoundObject m_soFire4, + +components: + 0 class CLASS_BASE "Classes\\EnemyBase.ecl", + 1 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 2 class CLASS_BASIC_EFFECT "Classes\\BasicEffect.ecl", + + 10 model MODEL_WALKER "Models\\Enemies\\Walker\\Walker.mdl", + 11 texture TEXTURE_WALKER_SOLDIER "Models\\Enemies\\Walker\\Walker02.tex", + 12 texture TEXTURE_WALKER_SERGEANT "Models\\Enemies\\Walker\\Walker01.tex", + 14 model MODEL_LASER "Models\\Enemies\\Walker\\Laser.mdl", + 15 texture TEXTURE_LASER "Models\\Enemies\\Walker\\Laser.tex", + 16 model MODEL_ROCKETLAUNCHER "Models\\Enemies\\Walker\\RocketLauncher.mdl", + 17 texture TEXTURE_ROCKETLAUNCHER "Models\\Enemies\\Walker\\RocketLauncher.tex", + +// ************** SOUNDS ************** + 50 sound SOUND_SOLDIER_IDLE "Models\\Enemies\\Walker\\Sounds\\Soldier\\Idle.wav", + 51 sound SOUND_SOLDIER_SIGHT "Models\\Enemies\\Walker\\Sounds\\Soldier\\Sight.wav", + 53 sound SOUND_SOLDIER_FIRE_LASER "Models\\Enemies\\Walker\\Sounds\\Soldier\\Fire.wav", + 54 sound SOUND_SOLDIER_DEATH "Models\\Enemies\\Walker\\Sounds\\Soldier\\Death.wav", + 55 sound SOUND_SOLDIER_WALK "Models\\Enemies\\Walker\\Sounds\\Soldier\\Walk.wav", + + 60 sound SOUND_SERGEANT_IDLE "Models\\Enemies\\Walker\\Sounds\\Sergeant\\Idle.wav", + 61 sound SOUND_SERGEANT_SIGHT "Models\\Enemies\\Walker\\Sounds\\Sergeant\\Sight.wav", + 63 sound SOUND_SERGEANT_FIRE_ROCKET "Models\\Enemies\\Walker\\Sounds\\Sergeant\\Fire.wav", + 64 sound SOUND_SERGEANT_DEATH "Models\\Enemies\\Walker\\Sounds\\Sergeant\\Death.wav", + 65 sound SOUND_SERGEANT_WALK "Models\\Enemies\\Walker\\Sounds\\Sergeant\\Walk.wav", + + /* + 70 model MODEL_WALKER_HEAD1 "Models\\Enemies\\Walker\\Debris\\Head.mdl", + 71 model MODEL_WALKER_HEAD2 "Models\\Enemies\\Walker\\Debris\\Head2.mdl", + 72 model MODEL_WALKER_LEG "Models\\Enemies\\Walker\\Debris\\Leg.mdl", + */ + +functions: + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("A Biomech blew %s away"), strPlayerName); + return str; + } + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnmSoldier, "Data\\Messages\\Enemies\\WalkerSmall.txt"); + static DECLARE_CTFILENAME(fnmSergeant, "Data\\Messages\\Enemies\\WalkerBig.txt"); + switch(m_EwcChar) { + default: ASSERT(FALSE); + case WLC_SOLDIER: return fnmSoldier; + case WLC_SERGEANT: return fnmSergeant; + } + } + // overridable function to get range for switching to another player + FLOAT GetThreatDistance(void) + { + return m_fThreatDistance; + } + + BOOL ForcesCannonballToExplode(void) + { + if (m_EwcChar==WLC_SERGEANT) { + return TRUE; + } + return CEnemyBase::ForcesCannonballToExplode(); + } + + void Precache(void) { + CEnemyBase::Precache(); + + PrecacheModel(MODEL_WALKER); + + if (m_EwcChar==WLC_SOLDIER) + { + // sounds + PrecacheSound(SOUND_SOLDIER_IDLE ); + PrecacheSound(SOUND_SOLDIER_SIGHT); + PrecacheSound(SOUND_SOLDIER_DEATH); + PrecacheSound(SOUND_SOLDIER_FIRE_LASER); + PrecacheSound(SOUND_SOLDIER_WALK); + // model's texture + PrecacheTexture(TEXTURE_WALKER_SOLDIER); + // weapon + PrecacheModel(MODEL_LASER); + PrecacheTexture(TEXTURE_LASER); + // projectile + PrecacheClass(CLASS_PROJECTILE, PRT_CYBORG_LASER); + } + else + { + // sounds + PrecacheSound(SOUND_SERGEANT_IDLE); + PrecacheSound(SOUND_SERGEANT_SIGHT); + PrecacheSound(SOUND_SERGEANT_DEATH); + PrecacheSound(SOUND_SERGEANT_FIRE_ROCKET); + PrecacheSound(SOUND_SERGEANT_WALK); + // model's texture + PrecacheTexture(TEXTURE_WALKER_SERGEANT); + // weapon + PrecacheModel(MODEL_ROCKETLAUNCHER); + PrecacheTexture(TEXTURE_ROCKETLAUNCHER); + // projectile + PrecacheClass(CLASS_PROJECTILE, PRT_WALKER_ROCKET); + } + }; + /* Entity info */ + void *GetEntityInfo(void) { + return &eiWalker; + }; + + FLOAT GetCrushHealth(void) + { + if (m_EwcChar==WLC_SERGEANT) { + return 100.0f; + } + return 0.0f; + } + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + + // take less damage from heavy bullets (e.g. sniper) + if(dmtType==DMT_BULLET && fDamageAmmount>100.0f) + { + fDamageAmmount*=0.666f; + } + + // walker can't harm walker + if (!IsOfClass(penInflictor, "Walker") || + ((CWalker*)penInflictor)->m_EwcChar!=m_EwcChar) { + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + }; + + + // virtual anim functions + void StandingAnim(void) { + DeactivateWalkingSound(); + StartModelAnim(WALKER_ANIM_STAND01, AOF_LOOPING|AOF_NORESTART); + }; + void StandingAnimFight(void) + { + DeactivateWalkingSound(); + StartModelAnim(WALKER_ANIM_IDLEFIGHT, AOF_LOOPING|AOF_NORESTART); + } + void WalkingAnim(void) { + ActivateWalkingSound(); + if (m_EwcChar==WLC_SERGEANT) { + StartModelAnim(WALKER_ANIM_WALKBIG, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(WALKER_ANIM_WALK, AOF_LOOPING|AOF_NORESTART); + } + }; + void RunningAnim(void) { + WalkingAnim(); + }; + void RotatingAnim(void) { + WalkingAnim(); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, WALKERSOUND(IDLE), SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, WALKERSOUND(SIGHT), SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, WALKERSOUND(DEATH), SOF_3D); + }; + + // walking sounds + void ActivateWalkingSound(void) + { + if (!m_bWalkSoundPlaying) { + PlaySound(m_soFeet, WALKERSOUND(WALK), SOF_3D|SOF_LOOP); + m_bWalkSoundPlaying = TRUE; + } + } + void DeactivateWalkingSound(void) + { + m_soFeet.Stop(); + m_bWalkSoundPlaying = FALSE; + } + + // fire death rocket + void FireDeathRocket(FLOAT3D &vPos) { + CPlacement3D plRocket; + plRocket.pl_PositionVector = vPos; + plRocket.pl_OrientationAngle = ANGLE3D(0, -5.0f-FRnd()*10.0f, 0); + plRocket.RelativeToAbsolute(GetPlacement()); + CEntityPointer penProjectile = CreateEntity(plRocket, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_WALKER_ROCKET; + penProjectile->Initialize(eLaunch); + }; + // fire death laser + void FireDeathLaser(FLOAT3D &vPos) { + CPlacement3D plLaser; + plLaser.pl_PositionVector = vPos; + plLaser.pl_OrientationAngle = ANGLE3D(0, -5.0f-FRnd()*10.0f, 0); + plLaser.RelativeToAbsolute(GetPlacement()); + CEntityPointer penProjectile = CreateEntity(plLaser, CLASS_PROJECTILE); + ELaunchProjectile eLaunch; + eLaunch.penLauncher = this; + eLaunch.prtType = PRT_CYBORG_LASER; + penProjectile->Initialize(eLaunch); + }; + + + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + // set sound default parameters + m_soSound.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + m_soFeet.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + m_soFire1.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + m_soFire2.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + m_soFire3.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + m_soFire4.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + }; + +/************************************************************ + * BLOW UP FUNCTIONS * + ************************************************************/ + // spawn body parts +/* void BlowUp(void) + { + // get your size + FLOATaabbox3D box; + GetBoundingBox(box); + FLOAT fEntitySize = box.Size().MaxNorm(); + + FLOAT3D vNormalizedDamage = m_vDamage-m_vDamage*(m_fBlowUpAmount/m_vDamage.Length()); + vNormalizedDamage /= Sqrt(vNormalizedDamage.Length()); + + vNormalizedDamage *= 0.75f; + FLOAT3D vBodySpeed = en_vCurrentTranslationAbsolute-en_vGravityDir*(en_vGravityDir%en_vCurrentTranslationAbsolute); + + // spawn debris + Debris_Begin(EIBT_FLESH, DPT_NONE, BET_NONE, fEntitySize, vNormalizedDamage, vBodySpeed, 5.0f, 2.0f); + Debris_Spawn(this, this, MODEL_WALKER_HEAD1, TEXTURE_WALKER_SOLDIER, 0, 0, 0, 0, 0.1250f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_WALKER_HEAD2, TEXTURE_WALKER_SOLDIER, 0, 0, 0, 0, 0.125f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_WALKER_LEG, TEXTURE_WALKER_SOLDIER, 0, 0, 0, 0, 0.125f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + Debris_Spawn(this, this, MODEL_WALKER_LEG, TEXTURE_WALKER_SOLDIER, 0, 0, 0, 0, 0.125f, + FLOAT3D(FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f, FRnd()*0.6f+0.2f)); + + // hide yourself (must do this after spawning debris) + SwitchToEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + };*/ + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + Fire(EVoid) : CEnemyBase::Fire { + DeactivateWalkingSound(); + // to fire + StartModelAnim(WALKER_ANIM_TOFIRE, 0); + m_fLockOnEnemyTime = GetModelObject()->GetAnimLength(WALKER_ANIM_TOFIRE); + autocall CEnemyBase::LockOnEnemy() EReturn; + + // sergeant 4 rockets + if (m_EwcChar==WLC_SERGEANT) { + StartModelAnim(WALKER_ANIM_FIRERIGHT, AOF_LOOPING); + ShootProjectile(PRT_WALKER_ROCKET, FIRE_RIGHT_ARM*m_fSize, ANGLE3D(0, 0, 0)); + PlaySound(m_soFire1, SOUND_SERGEANT_FIRE_ROCKET, SOF_3D); + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + m_fLockOnEnemyTime = 1.0f; + } else { + m_fLockOnEnemyTime = 0.5f; + } + autocall CEnemyBase::LockOnEnemy() EReturn; + StartModelAnim(WALKER_ANIM_FIRELEFT, AOF_LOOPING); + ShootProjectile(PRT_WALKER_ROCKET, FIRE_LEFT_ARM*m_fSize, ANGLE3D(0, 0, 0)); + PlaySound(m_soFire2, SOUND_SERGEANT_FIRE_ROCKET, SOF_3D); + +// m_fLockOnEnemyTime = 0.25f; +// autocall CEnemyBase::LockOnEnemy() EReturn; + } + if (m_EwcChar==WLC_SOLDIER) { + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + m_iLoopCounter = 4; + } else { + m_iLoopCounter = 8; + } + while(m_iLoopCounter>0) { + if (m_iLoopCounter%2) { + StartModelAnim(WALKER_ANIM_FIRELEFT, AOF_LOOPING); + ShootProjectile(PRT_CYBORG_LASER, FIRE_LEFT_ARM*m_fSize, ANGLE3D(0, 0, 0)); + } else { + StartModelAnim(WALKER_ANIM_FIRERIGHT, AOF_LOOPING); + ShootProjectile(PRT_CYBORG_LASER, FIRE_RIGHT_ARM*m_fSize, ANGLE3D(0, 0, 0)); + } + INDEX iChannel = m_iLoopCounter%4; + if (iChannel==0) { + PlaySound(m_soFire1, SOUND_SOLDIER_FIRE_LASER, SOF_3D); + } else if (iChannel==1) { + PlaySound(m_soFire2, SOUND_SOLDIER_FIRE_LASER, SOF_3D); + } else if (iChannel==2) { + PlaySound(m_soFire3, SOUND_SOLDIER_FIRE_LASER, SOF_3D); + } else if (iChannel==3) { + PlaySound(m_soFire4, SOUND_SOLDIER_FIRE_LASER, SOF_3D); + } + if (m_iLoopCounter>1) { + if (GetSP()->sp_gdGameDifficulty<=CSessionProperties::GD_EASY) { + m_fLockOnEnemyTime = 0.4f; + } else { + m_fLockOnEnemyTime = 0.1f; + } + autocall CEnemyBase::LockOnEnemy() EReturn; + } + m_iLoopCounter--; + } + } + StopMoving(); + + MaybeSwitchToAnotherPlayer(); + + // from fire + StartModelAnim(WALKER_ANIM_FROMFIRE, 0); + autowait(GetModelObject()->GetAnimLength(WALKER_ANIM_FROMFIRE)); + + // wait for a while + StandingAnimFight(); + autowait(FRnd()*0.1f+0.1f); + + return EReturn(); + }; + + + +/************************************************************ + * D E A T H * + ************************************************************/ + Death(EVoid) : CEnemyBase::Death { + // stop moving + StopMoving(); + DeathSound(); // death sound + DeactivateWalkingSound(); + + // set physic flags + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags() | ENF_SEETHROUGH); + + // death notify (change collision box) + ChangeCollisionBoxIndexWhenPossible(WALKER_COLLISION_BOX_DEATH); + + // start death anim + StartModelAnim(WALKER_ANIM_DEATH, 0); + autowait(0.9f); + + // one rocket/laser from left or right arm + if (m_EwcChar==WLC_SERGEANT) { + if (IRnd()&1) { + FireDeathRocket(FIRE_DEATH_RIGHT*m_fSize); + } else { + FireDeathRocket(FIRE_DEATH_LEFT*m_fSize); + } + PlaySound(m_soSound, SOUND_SERGEANT_FIRE_ROCKET, SOF_3D); + } + if (m_EwcChar==WLC_SOLDIER) { + if (IRnd()&1) { + FireDeathLaser(FIRE_DEATH_RIGHT*m_fSize); + } else { + FireDeathLaser(FIRE_DEATH_LEFT*m_fSize); + } + PlaySound(m_soFire2, SOUND_SOLDIER_FIRE_LASER, SOF_3D); + } + autowait(0.25f); + + FLOAT fStretch=2.0f; + if (m_EwcChar==WLC_SERGEANT) + { + fStretch=4.0f; + } + // spawn dust effect + CPlacement3D plFX=GetPlacement(); + ESpawnEffect ese; + ese.colMuliplier = C_WHITE|CT_OPAQUE; + ese.vStretch = FLOAT3D(1.5,1,1)*fStretch; + ese.vNormal = FLOAT3D(0,1,0); + ese.betType = BET_DUST_FALL; + CPlacement3D plSmoke=plFX; + plSmoke.pl_PositionVector+=FLOAT3D(0,0.35f*ese.vStretch(2),0); + CEntityPointer penFX = CreateEntity(plSmoke, CLASS_BASIC_EFFECT); + penFX->Initialize(ese); + + autowait(0.35f); + + return EEnd(); + }; + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + if (m_EwcChar==WLC_SERGEANT) { + SetHealth(750.0f); + m_fMaxHealth = 750.0f; + } else { + SetHealth(150.0f); + m_fMaxHealth = 150.0f; + } + en_fDensity = 3000.0f; + + m_sptType = SPT_ELECTRICITY_SPARKS; + + // set your appearance + SetModel(MODEL_WALKER); + if (m_EwcChar==WLC_SERGEANT) { + m_fSize = 1.0f; + SetModelMainTexture(TEXTURE_WALKER_SERGEANT); + AddAttachment(WALKER_ATTACHMENT_ROCKETLAUNCHER_LT, MODEL_ROCKETLAUNCHER, TEXTURE_ROCKETLAUNCHER); + AddAttachment(WALKER_ATTACHMENT_ROCKETLAUNCHER_RT, MODEL_ROCKETLAUNCHER, TEXTURE_ROCKETLAUNCHER); + GetModelObject()->StretchModel(FLOAT3D(1,1,1)); + ModelChangeNotify(); + CModelObject *pmoRight = &GetModelObject()->GetAttachmentModel(WALKER_ATTACHMENT_ROCKETLAUNCHER_RT)->amo_moModelObject; + pmoRight->StretchModel(FLOAT3D(-1,1,1)); + m_fBlowUpAmount = 1E10f; + m_iScore = 7500; + m_fThreatDistance = 15; + } else { + m_fSize = 0.5f; + SetModelMainTexture(TEXTURE_WALKER_SOLDIER); + AddAttachment(WALKER_ATTACHMENT_LASER_LT, MODEL_LASER, TEXTURE_LASER); + AddAttachment(WALKER_ATTACHMENT_LASER_RT, MODEL_LASER, TEXTURE_LASER); + GetModelObject()->StretchModel(FLOAT3D(0.5f,0.5f,0.5f)); + ModelChangeNotify(); + CModelObject *pmoRight = &GetModelObject()->GetAttachmentModel(WALKER_ATTACHMENT_LASER_RT)->amo_moModelObject; + pmoRight->StretchModel(FLOAT3D(-0.5f,0.5f,0.5f)); + m_fBlowUpAmount = 1E10f; + //m_fBlowUpAmount = 100.0f; + //m_bRobotBlowup = TRUE; + m_iScore = 2000; + m_fThreatDistance = 5; + } + if (m_fStepHeight==-1) { + m_fStepHeight = 4.0f; + } + + StandingAnim(); + // setup moving speed + m_fWalkSpeed = FRnd()*1.5f + 9.0f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*50.0f + 500.0f); + m_fAttackRunSpeed = m_fWalkSpeed; + m_aAttackRotateSpeed = m_aWalkRotateSpeed/2; + m_fCloseRunSpeed = m_fWalkSpeed; + m_aCloseRotateSpeed = m_aWalkRotateSpeed/2; + m_fWalkSpeed/=2.0f; + // setup attack distances + m_fAttackDistance = 150.0f; + m_fCloseDistance = 0.0f; + m_fStopDistance = 15.0f; + m_fAttackFireTime = 3.0f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 300.0f; + // damage/explode properties + m_fBodyParts = 8; + m_fDamageWounded = 100000.0f; + + // continue behavior in base class + jump CEnemyBase::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Walker.h b/Sources/EntitiesMP/Walker.h new file mode 100644 index 0000000..0835d04 --- /dev/null +++ b/Sources/EntitiesMP/Walker.h @@ -0,0 +1,128 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Walker_INCLUDED +#define _EntitiesMP_Walker_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType WalkerChar_enum; +enum WalkerChar { + WLC_SOLDIER = 0, + WLC_SERGEANT = 1, +}; +DECL_DLL inline void ClearToDefault(WalkerChar &e) { e = (WalkerChar)0; } ; +extern "C" DECL_DLL CDLLEntityClass CWalker_DLLClass; +class CWalker : public CEnemyBase { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum WalkerChar m_EwcChar; + INDEX m_iLoopCounter; + FLOAT m_fSize; + BOOL m_bWalkSoundPlaying; + FLOAT m_fThreatDistance; + CSoundObject m_soFeet; + CSoundObject m_soFire1; + CSoundObject m_soFire2; + CSoundObject m_soFire3; + CSoundObject m_soFire4; + +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +FLOAT GetThreatDistance(void); + +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +BOOL ForcesCannonballToExplode(void); + +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void Precache(void); + +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void * GetEntityInfo(void); + +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +FLOAT GetCrushHealth(void); + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void StandingAnim(void); + +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void StandingAnimFight(void); + +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void WalkingAnim(void); + +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void RunningAnim(void); + +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void RotatingAnim(void); + +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void IdleSound(void); + +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void SightSound(void); + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void DeathSound(void); + +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void ActivateWalkingSound(void); + +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void DeactivateWalkingSound(void); + +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void FireDeathRocket(FLOAT3D & vPos); + +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void FireDeathLaser(FLOAT3D & vPos); + +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +void EnemyPostInit(void); +#define STATE_CWalker_Fire 0x01440000 + BOOL +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Fire(const CEntityEvent &__eeInput); + BOOL H0x01440001_Fire_01(const CEntityEvent &__eeInput); + BOOL H0x01440002_Fire_02(const CEntityEvent &__eeInput); + BOOL H0x01440003_Fire_03(const CEntityEvent &__eeInput); + BOOL H0x01440004_Fire_04(const CEntityEvent &__eeInput); + BOOL H0x01440005_Fire_05(const CEntityEvent &__eeInput); + BOOL H0x01440006_Fire_06(const CEntityEvent &__eeInput); + BOOL H0x01440007_Fire_07(const CEntityEvent &__eeInput); + BOOL H0x01440008_Fire_08(const CEntityEvent &__eeInput); + BOOL H0x01440009_Fire_09(const CEntityEvent &__eeInput); + BOOL H0x0144000a_Fire_10(const CEntityEvent &__eeInput); + BOOL H0x0144000b_Fire_11(const CEntityEvent &__eeInput); + BOOL H0x0144000c_Fire_12(const CEntityEvent &__eeInput); + BOOL H0x0144000d_Fire_13(const CEntityEvent &__eeInput); + BOOL H0x0144000e_Fire_14(const CEntityEvent &__eeInput); + BOOL H0x0144000f_Fire_15(const CEntityEvent &__eeInput); +#define STATE_CWalker_Death 0x01440010 + BOOL +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Death(const CEntityEvent &__eeInput); + BOOL H0x01440011_Death_01(const CEntityEvent &__eeInput); + BOOL H0x01440012_Death_02(const CEntityEvent &__eeInput); + BOOL H0x01440013_Death_03(const CEntityEvent &__eeInput); + BOOL H0x01440014_Death_04(const CEntityEvent &__eeInput); + BOOL H0x01440015_Death_05(const CEntityEvent &__eeInput); + BOOL H0x01440016_Death_06(const CEntityEvent &__eeInput); +#define STATE_CWalker_Main 1 + BOOL +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Walker_INCLUDED diff --git a/Sources/EntitiesMP/Walker_tables.h b/Sources/EntitiesMP/Walker_tables.h new file mode 100644 index 0000000..2a9405d --- /dev/null +++ b/Sources/EntitiesMP/Walker_tables.h @@ -0,0 +1,113 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(WalkerChar) + EP_ENUMVALUE(WLC_SOLDIER, "Soldier"), + EP_ENUMVALUE(WLC_SERGEANT, "Sergeant"), +EP_ENUMEND(WalkerChar); + +#define ENTITYCLASS CWalker + +CEntityProperty CWalker_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &WalkerChar_enum, (0x00000144<<8)+1, offsetof(CWalker, m_EwcChar), "Character", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x00000144<<8)+2, offsetof(CWalker, m_iLoopCounter), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000144<<8)+3, offsetof(CWalker, m_fSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000144<<8)+4, offsetof(CWalker, m_bWalkSoundPlaying), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000144<<8)+5, offsetof(CWalker, m_fThreatDistance), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000144<<8)+10, offsetof(CWalker, m_soFeet), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000144<<8)+11, offsetof(CWalker, m_soFire1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000144<<8)+12, offsetof(CWalker, m_soFire2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000144<<8)+13, offsetof(CWalker, m_soFire3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000144<<8)+14, offsetof(CWalker, m_soFire4), "", 0, 0, 0), +}; +#define CWalker_propertiesct ARRAYCOUNT(CWalker_properties) + +CEntityComponent CWalker_components[] = { +#define CLASS_BASE ((0x00000144<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyBase.ecl"), +#define CLASS_PROJECTILE ((0x00000144<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_BASIC_EFFECT ((0x00000144<<8)+2) + CEntityComponent(ECT_CLASS, CLASS_BASIC_EFFECT, "EFNM" "Classes\\BasicEffect.ecl"), +#define MODEL_WALKER ((0x00000144<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_WALKER, "EFNM" "Models\\Enemies\\Walker\\Walker.mdl"), +#define TEXTURE_WALKER_SOLDIER ((0x00000144<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_WALKER_SOLDIER, "EFNM" "Models\\Enemies\\Walker\\Walker02.tex"), +#define TEXTURE_WALKER_SERGEANT ((0x00000144<<8)+12) + CEntityComponent(ECT_TEXTURE, TEXTURE_WALKER_SERGEANT, "EFNM" "Models\\Enemies\\Walker\\Walker01.tex"), +#define MODEL_LASER ((0x00000144<<8)+14) + CEntityComponent(ECT_MODEL, MODEL_LASER, "EFNM" "Models\\Enemies\\Walker\\Laser.mdl"), +#define TEXTURE_LASER ((0x00000144<<8)+15) + CEntityComponent(ECT_TEXTURE, TEXTURE_LASER, "EFNM" "Models\\Enemies\\Walker\\Laser.tex"), +#define MODEL_ROCKETLAUNCHER ((0x00000144<<8)+16) + CEntityComponent(ECT_MODEL, MODEL_ROCKETLAUNCHER, "EFNM" "Models\\Enemies\\Walker\\RocketLauncher.mdl"), +#define TEXTURE_ROCKETLAUNCHER ((0x00000144<<8)+17) + CEntityComponent(ECT_TEXTURE, TEXTURE_ROCKETLAUNCHER, "EFNM" "Models\\Enemies\\Walker\\RocketLauncher.tex"), +#define SOUND_SOLDIER_IDLE ((0x00000144<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_SOLDIER_IDLE, "EFNM" "Models\\Enemies\\Walker\\Sounds\\Soldier\\Idle.wav"), +#define SOUND_SOLDIER_SIGHT ((0x00000144<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_SOLDIER_SIGHT, "EFNM" "Models\\Enemies\\Walker\\Sounds\\Soldier\\Sight.wav"), +#define SOUND_SOLDIER_FIRE_LASER ((0x00000144<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_SOLDIER_FIRE_LASER, "EFNM" "Models\\Enemies\\Walker\\Sounds\\Soldier\\Fire.wav"), +#define SOUND_SOLDIER_DEATH ((0x00000144<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_SOLDIER_DEATH, "EFNM" "Models\\Enemies\\Walker\\Sounds\\Soldier\\Death.wav"), +#define SOUND_SOLDIER_WALK ((0x00000144<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_SOLDIER_WALK, "EFNM" "Models\\Enemies\\Walker\\Sounds\\Soldier\\Walk.wav"), +#define SOUND_SERGEANT_IDLE ((0x00000144<<8)+60) + CEntityComponent(ECT_SOUND, SOUND_SERGEANT_IDLE, "EFNM" "Models\\Enemies\\Walker\\Sounds\\Sergeant\\Idle.wav"), +#define SOUND_SERGEANT_SIGHT ((0x00000144<<8)+61) + CEntityComponent(ECT_SOUND, SOUND_SERGEANT_SIGHT, "EFNM" "Models\\Enemies\\Walker\\Sounds\\Sergeant\\Sight.wav"), +#define SOUND_SERGEANT_FIRE_ROCKET ((0x00000144<<8)+63) + CEntityComponent(ECT_SOUND, SOUND_SERGEANT_FIRE_ROCKET, "EFNM" "Models\\Enemies\\Walker\\Sounds\\Sergeant\\Fire.wav"), +#define SOUND_SERGEANT_DEATH ((0x00000144<<8)+64) + CEntityComponent(ECT_SOUND, SOUND_SERGEANT_DEATH, "EFNM" "Models\\Enemies\\Walker\\Sounds\\Sergeant\\Death.wav"), +#define SOUND_SERGEANT_WALK ((0x00000144<<8)+65) + CEntityComponent(ECT_SOUND, SOUND_SERGEANT_WALK, "EFNM" "Models\\Enemies\\Walker\\Sounds\\Sergeant\\Walk.wav"), +}; +#define CWalker_componentsct ARRAYCOUNT(CWalker_components) + +CEventHandlerEntry CWalker_handlers[] = { + {0x01440000, STATE_CEnemyBase_Fire, CEntity::pEventHandler(&CWalker:: +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Fire),DEBUGSTRING("CWalker::Fire")}, + {0x01440001, -1, CEntity::pEventHandler(&CWalker::H0x01440001_Fire_01), DEBUGSTRING("CWalker::H0x01440001_Fire_01")}, + {0x01440002, -1, CEntity::pEventHandler(&CWalker::H0x01440002_Fire_02), DEBUGSTRING("CWalker::H0x01440002_Fire_02")}, + {0x01440003, -1, CEntity::pEventHandler(&CWalker::H0x01440003_Fire_03), DEBUGSTRING("CWalker::H0x01440003_Fire_03")}, + {0x01440004, -1, CEntity::pEventHandler(&CWalker::H0x01440004_Fire_04), DEBUGSTRING("CWalker::H0x01440004_Fire_04")}, + {0x01440005, -1, CEntity::pEventHandler(&CWalker::H0x01440005_Fire_05), DEBUGSTRING("CWalker::H0x01440005_Fire_05")}, + {0x01440006, -1, CEntity::pEventHandler(&CWalker::H0x01440006_Fire_06), DEBUGSTRING("CWalker::H0x01440006_Fire_06")}, + {0x01440007, -1, CEntity::pEventHandler(&CWalker::H0x01440007_Fire_07), DEBUGSTRING("CWalker::H0x01440007_Fire_07")}, + {0x01440008, -1, CEntity::pEventHandler(&CWalker::H0x01440008_Fire_08), DEBUGSTRING("CWalker::H0x01440008_Fire_08")}, + {0x01440009, -1, CEntity::pEventHandler(&CWalker::H0x01440009_Fire_09), DEBUGSTRING("CWalker::H0x01440009_Fire_09")}, + {0x0144000a, -1, CEntity::pEventHandler(&CWalker::H0x0144000a_Fire_10), DEBUGSTRING("CWalker::H0x0144000a_Fire_10")}, + {0x0144000b, -1, CEntity::pEventHandler(&CWalker::H0x0144000b_Fire_11), DEBUGSTRING("CWalker::H0x0144000b_Fire_11")}, + {0x0144000c, -1, CEntity::pEventHandler(&CWalker::H0x0144000c_Fire_12), DEBUGSTRING("CWalker::H0x0144000c_Fire_12")}, + {0x0144000d, -1, CEntity::pEventHandler(&CWalker::H0x0144000d_Fire_13), DEBUGSTRING("CWalker::H0x0144000d_Fire_13")}, + {0x0144000e, -1, CEntity::pEventHandler(&CWalker::H0x0144000e_Fire_14), DEBUGSTRING("CWalker::H0x0144000e_Fire_14")}, + {0x0144000f, -1, CEntity::pEventHandler(&CWalker::H0x0144000f_Fire_15), DEBUGSTRING("CWalker::H0x0144000f_Fire_15")}, + {0x01440010, STATE_CEnemyBase_Death, CEntity::pEventHandler(&CWalker:: +#line 394 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Death),DEBUGSTRING("CWalker::Death")}, + {0x01440011, -1, CEntity::pEventHandler(&CWalker::H0x01440011_Death_01), DEBUGSTRING("CWalker::H0x01440011_Death_01")}, + {0x01440012, -1, CEntity::pEventHandler(&CWalker::H0x01440012_Death_02), DEBUGSTRING("CWalker::H0x01440012_Death_02")}, + {0x01440013, -1, CEntity::pEventHandler(&CWalker::H0x01440013_Death_03), DEBUGSTRING("CWalker::H0x01440013_Death_03")}, + {0x01440014, -1, CEntity::pEventHandler(&CWalker::H0x01440014_Death_04), DEBUGSTRING("CWalker::H0x01440014_Death_04")}, + {0x01440015, -1, CEntity::pEventHandler(&CWalker::H0x01440015_Death_05), DEBUGSTRING("CWalker::H0x01440015_Death_05")}, + {0x01440016, -1, CEntity::pEventHandler(&CWalker::H0x01440016_Death_06), DEBUGSTRING("CWalker::H0x01440016_Death_06")}, + {1, -1, CEntity::pEventHandler(&CWalker:: +#line 455 "D:/SE1_GPL/Sources/EntitiesMP/Walker.es" +Main),DEBUGSTRING("CWalker::Main")}, +}; +#define CWalker_handlersct ARRAYCOUNT(CWalker_handlers) + +CEntity *CWalker_New(void) { return new CWalker; }; +void CWalker_OnInitClass(void) {}; +void CWalker_OnEndClass(void) {}; +void CWalker_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CWalker_OnWorldEnd(CWorld *pwo) {}; +void CWalker_OnWorldInit(CWorld *pwo) {}; +void CWalker_OnWorldTick(CWorld *pwo) {}; +void CWalker_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CWalker, CEnemyBase, "Walker", "Thumbnails\\Walker.tbn", 0x00000144); +DECLARE_CTFILENAME(_fnmCWalker_tbn, "Thumbnails\\Walker.tbn"); diff --git a/Sources/EntitiesMP/WatchPlayers.cpp b/Sources/EntitiesMP/WatchPlayers.cpp new file mode 100644 index 0000000..f68fa56 --- /dev/null +++ b/Sources/EntitiesMP/WatchPlayers.cpp @@ -0,0 +1,271 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" + +#include "StdH.h" + +#include +#include +void CWatchPlayers::SetDefaultProperties(void) { + m_penOwner = NULL; + m_penFar = NULL; + m_fWaitTime = 0.1f; + m_fDistance = 100.0f; + m_bRangeWatcher = TRUE ; + m_eetEventClose = EET_TRIGGER ; + m_eetEventFar = EET_ENVIRONMENTSTOP ; + m_penCurrentWatch = NULL; + m_bActive = TRUE ; + m_strName = ""; + CRationalEntity::SetDefaultProperties(); +} + +#line 34 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +BOOL CWatchPlayers::IsAnyPlayerClose(void) { +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +FLOAT fClosest = 100000.0f; +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +FLOAT fDistance ; +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +m_penCurrentWatch = NULL ; +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +for(INDEX iPlayer = 0;iPlayer < GetMaxPlayers ();iPlayer ++){ +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +CEntity * penPlayer = GetPlayerEntity (iPlayer ); +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +if(penPlayer != NULL && penPlayer -> GetFlags () & ENF_ALIVE && ! (penPlayer -> GetFlags () & ENF_INVISIBLE )){ +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +fDistance = 100000.0f; +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +if(m_bRangeWatcher ){ +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +fDistance = (penPlayer -> GetPlacement () . pl_PositionVector - +#line 49 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +GetPlacement () . pl_PositionVector ) . Length (); +#line 50 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}else { +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +if(m_penOwner != NULL ){ +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +fDistance = (penPlayer -> GetPlacement () . pl_PositionVector - +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +m_penOwner -> GetPlacement () . pl_PositionVector ) . Length (); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +if(fDistance < fClosest ){ +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +fClosest = fDistance ; +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +m_penCurrentWatch = penPlayer ; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +return (fClosest < m_fDistance ); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} + +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +void CWatchPlayers::SendCloseEvent(void) { +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +if(m_bRangeWatcher && m_penOwner == NULL ){ +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}else { +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SendToTarget (m_penOwner , m_eetEventClose , m_penCurrentWatch ); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +void CWatchPlayers::SendFarEvent(void) { +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +if(m_bRangeWatcher && m_penOwner == NULL ){ +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}else { +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +if(m_penFar != NULL ){ +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SendToTarget (m_penFar , m_eetEventFar ); +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}else { +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SendToTarget (m_penOwner , m_eetEventFar ); +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +BOOL CWatchPlayers:: +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWatchPlayers_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWatchPlayers::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +InitAsEditorModel (); +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SetModel (MODEL_WATCHPLAYERS ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SetModelMainTexture (TEXTURE_WATCHPLAYERS ); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +if(m_fWaitTime < 0.1f){ +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +m_fWaitTime = 0.1f; +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +if(m_bActive ){ +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +Jump(STATE_CURRENT, STATE_CWatchPlayers_Active, TRUE, EVoid());return TRUE; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}else { +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +Jump(STATE_CURRENT, STATE_CWatchPlayers_Inactive, TRUE, EVoid());return TRUE; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} ASSERT(FALSE); return TRUE;};BOOL CWatchPlayers:: +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +Active(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWatchPlayers_Active + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWatchPlayers::Active expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +STATE_CWatchPlayers_FarWatch, TRUE; +Jump(STATE_CURRENT, 0x02be0001, FALSE, EBegin());return TRUE;}BOOL CWatchPlayers::H0x02be0001_Active_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be0001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CWatchPlayers_FarWatch, TRUE, EVoid());return TRUE;case EVENTCODE_EDeactivate: Jump(STATE_CURRENT,0x02be0002, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CWatchPlayers::H0x02be0002_Active_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be0002 +const EDeactivate&__e= (EDeactivate&)__eeInput; +; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +Jump(STATE_CURRENT, STATE_CWatchPlayers_Inactive, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWatchPlayers:: +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +Inactive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWatchPlayers_Inactive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWatchPlayers::Inactive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x02be0004, FALSE, EBegin());return TRUE;}BOOL CWatchPlayers::H0x02be0004_Inactive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be0004 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EActivate):{const EActivate&e= (EActivate&)__eeInput; + +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +UnsetTimer();Jump(STATE_CURRENT,0x02be0005, FALSE, EInternal());return TRUE; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}ASSERT(FALSE);break;default:{ +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +return TRUE; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}ASSERT(FALSE);break; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}return TRUE;}BOOL CWatchPlayers::H0x02be0005_Inactive_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be0005 + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +Jump(STATE_CURRENT, STATE_CWatchPlayers_Active, TRUE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWatchPlayers:: +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +CloseWatch(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWatchPlayers_CloseWatch + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWatchPlayers::CloseWatch expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +Jump(STATE_CURRENT,0x02be0009, FALSE, EInternal());return TRUE;}BOOL CWatchPlayers::H0x02be0009_CloseWatch_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be0009 +if(!(TRUE )){ Jump(STATE_CURRENT,0x02be000a, FALSE, EInternal());return TRUE;} +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SetTimerAfter(m_fWaitTime ); +Jump(STATE_CURRENT, 0x02be0007, FALSE, EBegin());return TRUE;}BOOL CWatchPlayers::H0x02be0007_CloseWatch_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be0007 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +if(! IsAnyPlayerClose ()){ +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SendFarEvent (); +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +Jump(STATE_CURRENT, STATE_CWatchPlayers_FarWatch, TRUE, EVoid());return TRUE; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +return TRUE; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x02be0008, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}return TRUE;}BOOL CWatchPlayers::H0x02be0008_CloseWatch_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be0008 +Jump(STATE_CURRENT,0x02be0009, FALSE, EInternal());return TRUE; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}BOOL CWatchPlayers::H0x02be000a_CloseWatch_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be000a + ASSERT(FALSE); return TRUE;};BOOL CWatchPlayers:: +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +FarWatch(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWatchPlayers_FarWatch + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWatchPlayers::FarWatch expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +Jump(STATE_CURRENT,0x02be000e, FALSE, EInternal());return TRUE;}BOOL CWatchPlayers::H0x02be000e_FarWatch_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be000e +if(!(TRUE )){ Jump(STATE_CURRENT,0x02be000f, FALSE, EInternal());return TRUE;} +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SetTimerAfter(m_fWaitTime ); +Jump(STATE_CURRENT, 0x02be000c, FALSE, EBegin());return TRUE;}BOOL CWatchPlayers::H0x02be000c_FarWatch_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be000c +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +if(IsAnyPlayerClose ()){ +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +SendCloseEvent (); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +Jump(STATE_CURRENT, STATE_CWatchPlayers_CloseWatch, TRUE, EVoid());return TRUE; +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +} +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +return TRUE; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x02be000d, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}return TRUE;}BOOL CWatchPlayers::H0x02be000d_FarWatch_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be000d +Jump(STATE_CURRENT,0x02be000e, FALSE, EInternal());return TRUE; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/WatchPlayers.es" +}BOOL CWatchPlayers::H0x02be000f_FarWatch_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02be000f + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/WatchPlayers.es b/Sources/EntitiesMP/WatchPlayers.es new file mode 100644 index 0000000..d6faa52 --- /dev/null +++ b/Sources/EntitiesMP/WatchPlayers.es @@ -0,0 +1,168 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +702 +%{ +#include "StdH.h" +%} + +class CWatchPlayers: CRationalEntity { +name "Watch Players"; +thumbnail "Thumbnails\\WatchPlayers.tbn"; +features "HasName", "IsTargetable"; + +properties: + 1 CEntityPointer m_penOwner "Owner/Target" 'O' COLOR(C_dBROWN|0xFF), // entity which owns it / target + 10 CEntityPointer m_penFar "Far Target" 'F' COLOR(C_BLACK|0xFF), // entity which owns it / target + 2 FLOAT m_fWaitTime "Wait time" 'W' = 0.1f, // watch time + 3 RANGE m_fDistance "Watch distance" 'D' = 100.0f, // distance when player is seen + 4 BOOL m_bRangeWatcher "Range watcher" 'R' = TRUE, // range watcher + 5 enum EventEType m_eetEventClose "Close Event type" 'T' = EET_TRIGGER, // type of event to send + 6 enum EventEType m_eetEventFar "Far Event type" 'Y' = EET_ENVIRONMENTSTOP, // type of event to send + 7 CEntityPointer m_penCurrentWatch, + 8 BOOL m_bActive "Active" 'A' = TRUE, + 9 CTString m_strName "Name" 'N' = "", + +components: + 1 model MODEL_WATCHPLAYERS "Models\\Editor\\WatchPlayers.mdl", + 2 texture TEXTURE_WATCHPLAYERS "Models\\Editor\\WatchPlayers.tex" + +functions: +/************************************************************ + * USER FUNCTIONS * + ************************************************************/ + // check if any player is close + BOOL IsAnyPlayerClose(void) { + // far enough to not move at all + FLOAT fClosest = 100000.0f; + FLOAT fDistance; + + m_penCurrentWatch = NULL; + // for all players + for (INDEX iPlayer=0; iPlayerGetFlags()&ENF_ALIVE && !(penPlayer->GetFlags()&ENF_INVISIBLE)) { + fDistance = 100000.0f; + if (m_bRangeWatcher) { + // calculate distance to player from wathcer + fDistance = (penPlayer->GetPlacement().pl_PositionVector- + GetPlacement().pl_PositionVector).Length(); + } else { + if (m_penOwner!=NULL) { + // calculate distance to player from owner + fDistance = (penPlayer->GetPlacement().pl_PositionVector- + m_penOwner->GetPlacement().pl_PositionVector).Length(); + } + } + if (fDistance +#include +CEntityEvent *EWatcherInit::MakeCopy(void) { CEntityEvent *peeCopy = new EWatcherInit(*this); return peeCopy;} +EWatcherInit::EWatcherInit() : CEntityEvent(EVENTCODE_EWatcherInit) {; + ClearToDefault(penOwner); +}; +CEntityEvent *EWatch::MakeCopy(void) { CEntityEvent *peeCopy = new EWatch(*this); return peeCopy;} +EWatch::EWatch() : CEntityEvent(EVENTCODE_EWatch) {; + ClearToDefault(penSeen); +}; +void CWatcher::SetDefaultProperties(void) { + m_penOwner = NULL; + m_tmDelay = 5.0f; + m_fClosestPlayer = UpperLimit(0.0f); + m_iPlayerToCheck = 0; + m_penPrediction = NULL; + CRationalEntity::SetDefaultProperties(); +} + +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +class CEnemyBase * CWatcher::GetOwner(void) +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{ +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +ASSERT (m_penOwner != NULL ); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return (CEnemyBase *) & * m_penOwner ; +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} + +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +INDEX CWatcher::GetRandomPlayer(void) +#line 48 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{ +#line 51 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +INDEX ctMaxPlayers = GetMaxPlayers (); +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +INDEX ctActivePlayers = 0; +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{for(INDEX i = 0;i < ctMaxPlayers ;i ++){ +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(GetPlayerEntity (i ) != NULL ){ +#line 56 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +ctActivePlayers ++; +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +}} +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(ctActivePlayers == 0){ +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return 0; +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +INDEX iChosenActivePlayer = IRnd () % ctActivePlayers ; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +INDEX iActivePlayer = 0; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{for(INDEX i = 0;i < ctMaxPlayers ;i ++){ +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(GetPlayerEntity (i ) != NULL ){ +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(iActivePlayer == iChosenActivePlayer ){ +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return i ; +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +iActivePlayer ++; +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +}} +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +ASSERT (FALSE ); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return 0; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} + +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * CWatcher::FindClosestPlayer(void) +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{ +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * penClosestPlayer = NULL ; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fClosestPlayer = UpperLimit (0.0f); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +for(INDEX iPlayer = 0;iPlayer < GetMaxPlayers ();iPlayer ++){ +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * penPlayer = GetPlayerEntity (iPlayer ); +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(penPlayer != NULL && penPlayer -> GetFlags () & ENF_ALIVE && ! (penPlayer -> GetFlags () & ENF_INVISIBLE )){ +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fDistance = +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +(penPlayer -> GetPlacement () . pl_PositionVector - m_penOwner -> GetPlacement () . pl_PositionVector ) . Length (); +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(fDistance < fClosestPlayer ){ +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +fClosestPlayer = fDistance ; +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +penClosestPlayer = penPlayer ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(penClosestPlayer == NULL ){ +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +fClosestPlayer = 10.0f; +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_fClosestPlayer = fClosestPlayer ; +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return penClosestPlayer ; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} + +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +void CWatcher::SendWatchEvent(CEntity * penPlayer) +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{ +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +EWatch eWatch ; +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +eWatch . penSeen = penPlayer ; +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_penOwner -> SendEvent (eWatch ); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +void CWatcher::CheckIfPlayerVisible(void) +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{ +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(GetOwner () -> m_bBlind ){ +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return ; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +INDEX ctPlayers = GetMaxPlayers (); +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * penPlayer = NULL ; +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_iPlayerToCheck = (m_iPlayerToCheck + 1) % ctPlayers ; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +INDEX iFirstChecked = m_iPlayerToCheck ; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FOREVER { +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +penPlayer = GetPlayerEntity (m_iPlayerToCheck ); +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(penPlayer != NULL ){ +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +break ; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_iPlayerToCheck ++; +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_iPlayerToCheck %= ctPlayers ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(m_iPlayerToCheck == iFirstChecked ){ +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return ; +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(! (penPlayer -> GetFlags () & ENF_ALIVE ) || (penPlayer -> GetFlags () & ENF_INVISIBLE )){ +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return ; +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(GetOwner () -> SeeEntity (penPlayer , Cos (GetOwner () -> m_fViewAngle / 2.0f))){ +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +SendWatchEvent (penPlayer ); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} + +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +void CWatcher::SetWatchDelays(void) +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{ +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +const FLOAT tmMinDelay = 0.1f; +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +const FLOAT tmSeeDelay = 5.0f; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +const FLOAT tmTick = _pTimer -> TickQuantum ; +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fSeeDistance = GetOwner () -> m_fIgnoreRange ; +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fNearDistance = Min (GetOwner () -> m_fStopDistance , GetOwner () -> m_fCloseDistance ); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(m_fClosestPlayer <= fNearDistance ){ +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_tmDelay = tmMinDelay ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +}else { +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_tmDelay = tmMinDelay + +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +(m_fClosestPlayer - fNearDistance ) * (tmSeeDelay - tmMinDelay ) / (fSeeDistance - fNearDistance ); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_tmDelay = floor (m_tmDelay / tmTick ) * tmTick ; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} + +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +void CWatcher::Watch(void) +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{ +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fOrgDistance = m_fClosestPlayer ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * penClosest = FindClosestPlayer (); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fSeeDistance = GetOwner () -> m_fIgnoreRange ; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fStopDistance = Max (fSeeDistance * 1.5f , GetOwner () -> m_fActivityRange ); +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(fOrgDistance < fStopDistance && m_fClosestPlayer >= fStopDistance ){ +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_penOwner -> SendEvent (EStop ()); +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +}else if(fOrgDistance >= fStopDistance && m_fClosestPlayer < fStopDistance ){ +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_penOwner -> SendEvent (EStart ()); +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 208 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(m_fClosestPlayer < fSeeDistance ){ +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CheckIfPlayerVisible (); +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fSenseRange = GetOwner () -> m_fSenseRange ; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(penClosest != NULL && fSenseRange > 0 && m_fClosestPlayer < fSenseRange ){ +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +SendWatchEvent (penClosest ); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +SetWatchDelays (); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} + +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * CWatcher::CheckCloserPlayer(CEntity * penCurrentTarget,FLOAT fRange) +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{ +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(GetOwner () -> m_bBlind ){ +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return NULL ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * penClosestPlayer = NULL ; +#line 234 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fClosestPlayer = +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +(penCurrentTarget -> GetPlacement () . pl_PositionVector - m_penOwner -> GetPlacement () . pl_PositionVector ) . Length (); +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +fClosestPlayer = Min (fClosestPlayer , fRange ); +#line 239 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +for(INDEX iPlayer = 0;iPlayer < GetMaxPlayers ();iPlayer ++){ +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * penPlayer = GetPlayerEntity (iPlayer ); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(penPlayer == NULL || penPlayer == penCurrentTarget ){ +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +continue ; +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if((penPlayer -> GetFlags () & ENF_ALIVE ) && ! (penPlayer -> GetFlags () & ENF_INVISIBLE )){ +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fDistance = +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +(penPlayer -> GetPlacement () . pl_PositionVector - m_penOwner -> GetPlacement () . pl_PositionVector ) . Length (); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(fDistance < fClosestPlayer && +#line 251 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +GetOwner () -> SeeEntity (penPlayer , Cos (GetOwner () -> m_fViewAngle / 2.0f))){ +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +fClosestPlayer = fDistance ; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +penClosestPlayer = penPlayer ; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return penClosestPlayer ; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * CWatcher::CheckAnotherPlayer(CEntity * penCurrentTarget) +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{ +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(GetOwner () -> m_bBlind || penCurrentTarget == NULL ){ +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return NULL ; +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * penClosestPlayer = NULL ; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fCurrentDistance = +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +(penCurrentTarget -> GetPlacement () . pl_PositionVector - m_penOwner -> GetPlacement () . pl_PositionVector ) . Length (); +#line 275 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fRange = fCurrentDistance * 1.5f; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +INDEX iOffset = GetRandomPlayer (); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +INDEX ctPlayers = GetMaxPlayers (); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +for(INDEX iPlayer = 0;iPlayer < ctPlayers ;iPlayer ++){ +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * penPlayer = GetPlayerEntity ((iPlayer + iOffset ) % ctPlayers ); +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(penPlayer == NULL || penPlayer == penCurrentTarget ){ +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +continue ; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if((penPlayer -> GetFlags () & ENF_ALIVE ) && ! (penPlayer -> GetFlags () & ENF_INVISIBLE )){ +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +FLOAT fDistance = +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +(penPlayer -> GetPlacement () . pl_PositionVector - m_penOwner -> GetPlacement () . pl_PositionVector ) . Length (); +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(fDistance < fRange && +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +GetOwner () -> SeeEntity (penPlayer , Cos (GetOwner () -> m_fViewAngle / 2.0f))){ +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return penPlayer ; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return penCurrentTarget ; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} + +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +SLONG CWatcher::GetUsedMemory(void) +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +{ +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return (sizeof (CWatcher ) - sizeof (CRationalEntity ) + CRationalEntity :: GetUsedMemory ()); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +BOOL CWatcher:: +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Active(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWatcher_Active + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWatcher::Active expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Jump(STATE_CURRENT,0x02bc0005, FALSE, EInternal());return TRUE;}BOOL CWatcher::H0x02bc0005_Active_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bc0005 +if(!(TRUE )){ Jump(STATE_CURRENT,0x02bc0006, FALSE, EInternal());return TRUE;} +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Watch (); +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +SetTimerAfter(m_tmDelay ); +Jump(STATE_CURRENT, 0x02bc0003, FALSE, EBegin());return TRUE;}BOOL CWatcher::H0x02bc0003_Active_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bc0003 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x02bc0004, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStop):{const EStop&e= (EStop&)__eeInput; +Jump(STATE_CURRENT, STATE_CWatcher_Inactive, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x02bc0004, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETeleport):{const ETeleport&e= (ETeleport&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x02bc0004, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 331 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +}return TRUE;}BOOL CWatcher::H0x02bc0004_Active_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bc0004 +Jump(STATE_CURRENT,0x02bc0005, FALSE, EInternal());return TRUE; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +}BOOL CWatcher::H0x02bc0006_Active_04(const CEntityEvent &__eeInput) { +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bc0006 + ASSERT(FALSE); return TRUE;};BOOL CWatcher:: +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Inactive(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWatcher_Inactive + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWatcher::Inactive expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x02bc0008, FALSE, EBegin());return TRUE;}BOOL CWatcher::H0x02bc0008_Inactive_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bc0008 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EStart):{const EStart&e= (EStart&)__eeInput; +Jump(STATE_CURRENT, STATE_CWatcher_Active, TRUE, EVoid());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +}return TRUE;}BOOL CWatcher::H0x02bc0009_Inactive_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bc0009 + ASSERT(FALSE); return TRUE;};BOOL CWatcher:: +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Dummy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWatcher_Dummy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWatcher::Dummy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x02bc000b, FALSE, EBegin());return TRUE;}BOOL CWatcher::H0x02bc000b_Dummy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bc000b +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;default:{return TRUE;}ASSERT(FALSE);break; +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +}return TRUE;}BOOL CWatcher::H0x02bc000c_Dummy_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bc000c +; ASSERT(FALSE); return TRUE;};BOOL CWatcher:: +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWatcher_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EWatcherInit, "CWatcher::Main expects 'EWatcherInit' as input!"); const EWatcherInit &eInit = (const EWatcherInit &)__eeInput; +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +ASSERT (eInit . penOwner != NULL ); +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_penOwner = eInit . penOwner ; +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +InitAsVoid (); +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +if(GetSP () -> sp_gmGameMode == CSessionProperties :: GM_FLYOVER ){ +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Jump(STATE_CURRENT, STATE_CWatcher_Dummy, TRUE, EVoid());return TRUE; +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +} +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +m_iPlayerToCheck = GetRandomPlayer () - 1; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +STATE_CWatcher_Inactive, TRUE; +Jump(STATE_CURRENT, 0x02bc000d, FALSE, EBegin());return TRUE;}BOOL CWatcher::H0x02bc000d_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bc000d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CWatcher_Inactive, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x02bc000e, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CWatcher::H0x02bc000e_Main_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x02bc000e +const EEnd&__e= (EEnd&)__eeInput; +; +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Destroy (); +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Return(STATE_CURRENT,EVoid()); +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Watcher.es b/Sources/EntitiesMP/Watcher.es new file mode 100644 index 0000000..dea8a42 --- /dev/null +++ b/Sources/EntitiesMP/Watcher.es @@ -0,0 +1,382 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +700 +%{ +#include "StdH.h" + +#include "EntitiesMP/EnemyBase.h" +%} + +// input parameter for watcher +event EWatcherInit { + CEntityPointer penOwner, // who owns it +}; + +// entity is seen +event EWatch { + CEntityPointer penSeen, +}; + +class export CWatcher : CRationalEntity { +name "Watcher"; +thumbnail ""; +features "CanBePredictable"; + + +properties: + + 1 CEntityPointer m_penOwner, // entity which owns it + 2 FLOAT m_tmDelay = 5.0f, // delay between checking moments - set depending on distance of closest player + + 20 FLOAT m_fClosestPlayer = UpperLimit(0.0f), // distance from closest player to owner of this watcher + 21 INDEX m_iPlayerToCheck = 0, // sequence number for checking next player in each turn + + +components: + + +functions: + + class CEnemyBase *GetOwner(void) + { + ASSERT(m_penOwner!=NULL); + return (CEnemyBase*)&*m_penOwner; + } + + // find one player number by random + INDEX GetRandomPlayer(void) + { +// CPrintF("Getting random number... "); + // get maximum number of players in game + INDEX ctMaxPlayers = GetMaxPlayers(); + // find actual number of players + INDEX ctActivePlayers = 0; + {for(INDEX i=0; iGetFlags()&ENF_ALIVE && !(penPlayer->GetFlags()&ENF_INVISIBLE)) { + // calculate distance to player + FLOAT fDistance = + (penPlayer->GetPlacement().pl_PositionVector-m_penOwner->GetPlacement().pl_PositionVector).Length(); + // update if closer + if (fDistanceSendEvent(eWatch); + } + + void CheckIfPlayerVisible(void) + { + // if the owner is blind + if( GetOwner()->m_bBlind) { + // don't even bother checking + return; + } + + // get maximum number of players in game + INDEX ctPlayers = GetMaxPlayers(); + // find first one after current sequence + CEntity *penPlayer = NULL; + m_iPlayerToCheck = (m_iPlayerToCheck+1)%ctPlayers; + INDEX iFirstChecked = m_iPlayerToCheck; + FOREVER { + penPlayer = GetPlayerEntity(m_iPlayerToCheck); + if (penPlayer!=NULL) { + break; + } + m_iPlayerToCheck++; + m_iPlayerToCheck%=ctPlayers; + if (m_iPlayerToCheck==iFirstChecked) { + return; // we get here if there are no players at all + } + } + + // if this one is dead or invisible + if (!(penPlayer->GetFlags()&ENF_ALIVE) || (penPlayer->GetFlags()&ENF_INVISIBLE)) { + // do nothing + return; + } + + // if inside view angle and visible + if (GetOwner()->SeeEntity(penPlayer, Cos(GetOwner()->m_fViewAngle/2.0f))) { + // send event to owner + SendWatchEvent(penPlayer); + } + }; + + // set new watch time + void SetWatchDelays(void) + { + const FLOAT tmMinDelay = 0.1f; // delay at closest distance + const FLOAT tmSeeDelay = 5.0f; // delay at see distance + const FLOAT tmTick = _pTimer->TickQuantum; + FLOAT fSeeDistance = GetOwner()->m_fIgnoreRange; + FLOAT fNearDistance = Min(GetOwner()->m_fStopDistance, GetOwner()->m_fCloseDistance); + + // if closer than near distance + if (m_fClosestPlayer<=fNearDistance) { + // always use minimum delay + m_tmDelay = tmMinDelay; + // if further than near distance + } else { + // interpolate between near and see + m_tmDelay = tmMinDelay+ + (m_fClosestPlayer-fNearDistance)*(tmSeeDelay-tmMinDelay)/(fSeeDistance-fNearDistance); + // round to nearest tick + m_tmDelay = floor(m_tmDelay/tmTick)*tmTick; + } + }; + + // watch + void Watch(void) + { + // remember original distance + FLOAT fOrgDistance = m_fClosestPlayer; + + // find closest player + CEntity *penClosest = FindClosestPlayer(); + + FLOAT fSeeDistance = GetOwner()->m_fIgnoreRange; + FLOAT fStopDistance = Max(fSeeDistance*1.5f, GetOwner()->m_fActivityRange); + + // if players exited enemy's scope + if (fOrgDistance=fStopDistance) { + // stop owner + m_penOwner->SendEvent(EStop()); + // if players entered enemy's scope + } else if (fOrgDistance>=fStopDistance && m_fClosestPlayerSendEvent(EStart()); + } + + // if the closest player is close enough to be seen + if (m_fClosestPlayerm_fSenseRange; + if (penClosest!=NULL && fSenseRange>0 && m_fClosestPlayerm_bBlind) { + // don't even bother checking + return NULL; + } + + CEntity *penClosestPlayer = NULL; + FLOAT fClosestPlayer = + (penCurrentTarget->GetPlacement().pl_PositionVector-m_penOwner->GetPlacement().pl_PositionVector).Length(); + fClosestPlayer = Min(fClosestPlayer, fRange); // this is maximum considered range + + // for all other players + for (INDEX iPlayer=0; iPlayerGetFlags()&ENF_ALIVE) && !(penPlayer->GetFlags()&ENF_INVISIBLE)) { + // calculate distance to player + FLOAT fDistance = + (penPlayer->GetPlacement().pl_PositionVector-m_penOwner->GetPlacement().pl_PositionVector).Length(); + // if closer than current and you can see him + if (fDistanceSeeEntity(penPlayer, Cos(GetOwner()->m_fViewAngle/2.0f))) { + // update + fClosestPlayer = fDistance; + penClosestPlayer = penPlayer; + } + } + } + + return penClosestPlayer; + } + + // this is called directly from enemybase to attack multiple players (for really big enemies) + CEntity *CheckAnotherPlayer(CEntity *penCurrentTarget) + { + // if the owner is blind, or no current target + if( GetOwner()->m_bBlind || penCurrentTarget==NULL) { + // don't even check + return NULL; + } + + // get allowed distance + CEntity *penClosestPlayer = NULL; + FLOAT fCurrentDistance = + (penCurrentTarget->GetPlacement().pl_PositionVector-m_penOwner->GetPlacement().pl_PositionVector).Length(); + FLOAT fRange = fCurrentDistance*1.5f; + + // find a random offset to start searching + INDEX iOffset = GetRandomPlayer(); + + // for all other players + INDEX ctPlayers = GetMaxPlayers(); + for (INDEX iPlayer=0; iPlayerGetFlags()&ENF_ALIVE) && !(penPlayer->GetFlags()&ENF_INVISIBLE)) { + // calculate distance to player + FLOAT fDistance = + (penPlayer->GetPlacement().pl_PositionVector-m_penOwner->GetPlacement().pl_PositionVector).Length(); + // if inside allowed range and visible + if (fDistanceSeeEntity(penPlayer, Cos(GetOwner()->m_fViewAngle/2.0f))) { + // attack that one + return penPlayer; + } + } + } + + return penCurrentTarget; + } + + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + return( sizeof(CWatcher) - sizeof(CRationalEntity) + CRationalEntity::GetUsedMemory()); + } + + +procedures: + + + // watching + Active() { + // repeat + while (TRUE) { + // check all players + Watch(); + // wait for given delay + wait(m_tmDelay) { + on (EBegin) : { resume; } + on (ETimer) : { stop; } + // stop looking + on (EStop) : { jump Inactive(); } + // force re-checking if receiving start or teleport + on (EStart) : { stop; } + on (ETeleport) : { stop; } + } + } + }; + + // not watching + Inactive(EVoid) { + wait() { + on (EBegin) : { resume; } + on (EStart) : { jump Active(); } + } + }; + + // dummy mode + Dummy(EVoid) + { + // ignores all events forever + wait() { + on (EBegin) : { resume; } + otherwise() : { resume; }; + }; + } + + Main(EWatcherInit eInit) { + // remember the initial parameters + ASSERT(eInit.penOwner!=NULL); + m_penOwner = eInit.penOwner; + + // init as nothing + InitAsVoid(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // if in flyover game mode + if (GetSP()->sp_gmGameMode == CSessionProperties::GM_FLYOVER) { + // go to dummy mode + jump Dummy(); + // NOTE: must not destroy self, because owner has a pointer + } + + // generate random number of player to check next + // (to provide even distribution of enemies among players) + m_iPlayerToCheck = GetRandomPlayer()-1; + + // start in disabled state + autocall Inactive() EEnd; + + // cease to exist + Destroy(); + + return; + }; +}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Watcher.h b/Sources/EntitiesMP/Watcher.h new file mode 100644 index 0000000..99ae554 --- /dev/null +++ b/Sources/EntitiesMP/Watcher.h @@ -0,0 +1,91 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Watcher_INCLUDED +#define _EntitiesMP_Watcher_INCLUDED 1 +#define EVENTCODE_EWatcherInit 0x02bc0000 +class DECL_DLL EWatcherInit : public CEntityEvent { +public: +EWatcherInit(); +CEntityEvent *MakeCopy(void); +CEntityPointer penOwner; +}; +DECL_DLL inline void ClearToDefault(EWatcherInit &e) { e = EWatcherInit(); } ; +#define EVENTCODE_EWatch 0x02bc0001 +class DECL_DLL EWatch : public CEntityEvent { +public: +EWatch(); +CEntityEvent *MakeCopy(void); +CEntityPointer penSeen; +}; +DECL_DLL inline void ClearToDefault(EWatch &e) { e = EWatch(); } ; +extern "C" DECL_DLL CDLLEntityClass CWatcher_DLLClass; +class DECL_DLL CWatcher : public CRationalEntity { +public: +virtual CEntity *GetPredictionPair(void) { return m_penPrediction; }; +virtual void SetPredictionPair(CEntity *penPair) { m_penPrediction = penPair; }; + virtual void SetDefaultProperties(void); + CEntityPointer m_penOwner; + FLOAT m_tmDelay; + FLOAT m_fClosestPlayer; + INDEX m_iPlayerToCheck; + CEntityPointer m_penPrediction; + +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +class CEnemyBase * GetOwner(void); + +#line 47 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +INDEX GetRandomPlayer(void); + +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * FindClosestPlayer(void); + +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +void SendWatchEvent(CEntity * penPlayer); + +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +void CheckIfPlayerVisible(void); + +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +void SetWatchDelays(void); + +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +void Watch(void); + +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * CheckCloserPlayer(CEntity * penCurrentTarget,FLOAT fRange); + +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +CEntity * CheckAnotherPlayer(CEntity * penCurrentTarget); + +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +SLONG GetUsedMemory(void); +#define STATE_CWatcher_Active 0x02bc0002 + BOOL +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Active(const CEntityEvent &__eeInput); + BOOL H0x02bc0003_Active_01(const CEntityEvent &__eeInput); + BOOL H0x02bc0004_Active_02(const CEntityEvent &__eeInput); + BOOL H0x02bc0005_Active_03(const CEntityEvent &__eeInput); + BOOL H0x02bc0006_Active_04(const CEntityEvent &__eeInput); +#define STATE_CWatcher_Inactive 0x02bc0007 + BOOL +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Inactive(const CEntityEvent &__eeInput); + BOOL H0x02bc0008_Inactive_01(const CEntityEvent &__eeInput); + BOOL H0x02bc0009_Inactive_02(const CEntityEvent &__eeInput); +#define STATE_CWatcher_Dummy 0x02bc000a + BOOL +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Dummy(const CEntityEvent &__eeInput); + BOOL H0x02bc000b_Dummy_01(const CEntityEvent &__eeInput); + BOOL H0x02bc000c_Dummy_02(const CEntityEvent &__eeInput); +#define STATE_CWatcher_Main 1 + BOOL +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x02bc000d_Main_01(const CEntityEvent &__eeInput); + BOOL H0x02bc000e_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Watcher_INCLUDED diff --git a/Sources/EntitiesMP/Watcher_tables.h b/Sources/EntitiesMP/Watcher_tables.h new file mode 100644 index 0000000..468872b --- /dev/null +++ b/Sources/EntitiesMP/Watcher_tables.h @@ -0,0 +1,57 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CWatcher + +CEntityProperty CWatcher_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000002bc<<8)+1, offsetof(CWatcher, m_penOwner), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000002bc<<8)+2, offsetof(CWatcher, m_tmDelay), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000002bc<<8)+20, offsetof(CWatcher, m_fClosestPlayer), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_INDEX, NULL, (0x000002bc<<8)+21, offsetof(CWatcher, m_iPlayerToCheck), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000002bc<<8)+255, offsetof(CWatcher, m_penPrediction), "", 0, 0, 0), +}; +#define CWatcher_propertiesct ARRAYCOUNT(CWatcher_properties) + +CEntityComponent CWatcher_components[] = { + CEntityComponent() +}; +#define CWatcher_componentsct 0 + + +CEventHandlerEntry CWatcher_handlers[] = { + {0x02bc0002, -1, CEntity::pEventHandler(&CWatcher:: +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Active),DEBUGSTRING("CWatcher::Active")}, + {0x02bc0003, -1, CEntity::pEventHandler(&CWatcher::H0x02bc0003_Active_01), DEBUGSTRING("CWatcher::H0x02bc0003_Active_01")}, + {0x02bc0004, -1, CEntity::pEventHandler(&CWatcher::H0x02bc0004_Active_02), DEBUGSTRING("CWatcher::H0x02bc0004_Active_02")}, + {0x02bc0005, -1, CEntity::pEventHandler(&CWatcher::H0x02bc0005_Active_03), DEBUGSTRING("CWatcher::H0x02bc0005_Active_03")}, + {0x02bc0006, -1, CEntity::pEventHandler(&CWatcher::H0x02bc0006_Active_04), DEBUGSTRING("CWatcher::H0x02bc0006_Active_04")}, + {0x02bc0007, -1, CEntity::pEventHandler(&CWatcher:: +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Inactive),DEBUGSTRING("CWatcher::Inactive")}, + {0x02bc0008, -1, CEntity::pEventHandler(&CWatcher::H0x02bc0008_Inactive_01), DEBUGSTRING("CWatcher::H0x02bc0008_Inactive_01")}, + {0x02bc0009, -1, CEntity::pEventHandler(&CWatcher::H0x02bc0009_Inactive_02), DEBUGSTRING("CWatcher::H0x02bc0009_Inactive_02")}, + {0x02bc000a, -1, CEntity::pEventHandler(&CWatcher:: +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Dummy),DEBUGSTRING("CWatcher::Dummy")}, + {0x02bc000b, -1, CEntity::pEventHandler(&CWatcher::H0x02bc000b_Dummy_01), DEBUGSTRING("CWatcher::H0x02bc000b_Dummy_01")}, + {0x02bc000c, -1, CEntity::pEventHandler(&CWatcher::H0x02bc000c_Dummy_02), DEBUGSTRING("CWatcher::H0x02bc000c_Dummy_02")}, + {1, -1, CEntity::pEventHandler(&CWatcher:: +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Watcher.es" +Main),DEBUGSTRING("CWatcher::Main")}, + {0x02bc000d, -1, CEntity::pEventHandler(&CWatcher::H0x02bc000d_Main_01), DEBUGSTRING("CWatcher::H0x02bc000d_Main_01")}, + {0x02bc000e, -1, CEntity::pEventHandler(&CWatcher::H0x02bc000e_Main_02), DEBUGSTRING("CWatcher::H0x02bc000e_Main_02")}, +}; +#define CWatcher_handlersct ARRAYCOUNT(CWatcher_handlers) + +CEntity *CWatcher_New(void) { return new CWatcher; }; +void CWatcher_OnInitClass(void) {}; +void CWatcher_OnEndClass(void) {}; +void CWatcher_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CWatcher_OnWorldEnd(CWorld *pwo) {}; +void CWatcher_OnWorldInit(CWorld *pwo) {}; +void CWatcher_OnWorldTick(CWorld *pwo) {}; +void CWatcher_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CWatcher, CRationalEntity, "Watcher", "", 0x000002bc); +DECLARE_CTFILENAME(_fnmCWatcher_tbn, ""); diff --git a/Sources/EntitiesMP/Water.cpp b/Sources/EntitiesMP/Water.cpp new file mode 100644 index 0000000..bd1bcd8 --- /dev/null +++ b/Sources/EntitiesMP/Water.cpp @@ -0,0 +1,258 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" + +#include "StdH.h" + +#include +#include +CEntityEvent *EWater::MakeCopy(void) { CEntityEvent *peeCopy = new EWater(*this); return peeCopy;} +EWater::EWater() : CEntityEvent(EVENTCODE_EWater) {; + ClearToDefault(penLauncher); + ClearToDefault(EwsSize); +}; +#line 24 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" + +#define FLY_TIME 5.0f + +void CWater::SetDefaultProperties(void) { + m_penLauncher = NULL; + m_EwsSize = WTS_SMALL ; + m_fDamageAmount = 0.0f; + m_fIgnoreTime = 0.0f; + m_fPushAwayFactor = 0.0f; + CMovableModelEntity::SetDefaultProperties(); +} + +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +void CWater::Read_t(CTStream * istr) +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +{ +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +CRationalEntity :: Read_t (istr ); +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +SetupLightSource (); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +} + +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +CLightSource * CWater::GetLightSource(void) +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +{ +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +if(! IsPredictor ()){ +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +return & m_lsLightSource ; +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +}else { +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +return NULL ; +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +} +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +} + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +void CWater::SetupLightSource(void) +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +{ +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +CLightSource lsNew ; +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +lsNew . ls_ulFlags = LSF_NONPERSISTENT | LSF_DYNAMIC ; +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +lsNew . ls_colColor = C_lBLUE ; +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +lsNew . ls_rFallOff = 1.0f; +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +lsNew . ls_rHotSpot = 0.2f; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +lsNew . ls_plftLensFlare = NULL ; +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +lsNew . ls_ubPolygonalMask = 0; +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +lsNew . ls_paoLightAnimation = NULL ; +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_lsLightSource . ls_penEntity = this ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_lsLightSource . SetLightSource (lsNew ); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +} + +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +void CWater::RenderParticles(void) { +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +} + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +void CWater::WaterTouch(CEntityPointer penHit) { +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +FLOAT3D vDirection ; +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +AnglesToDirectionVector (GetPlacement () . pl_OrientationAngle , vDirection ); +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +InflictDirectDamage (penHit , m_penLauncher , DMT_PROJECTILE , m_fDamageAmount , +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +GetPlacement () . pl_PositionVector , vDirection ); +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +FLOAT3D vSpeed ; +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +GetHeadingDirection (0.0f , vSpeed ); +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +vSpeed = vSpeed * m_fPushAwayFactor ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +KickEntity (penHit , vSpeed ); +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +} +BOOL CWater:: +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +WaterFly(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWater_WaterFly + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWater::WaterFly expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +SetTimerAfter(FLY_TIME ); +Jump(STATE_CURRENT, 0x01fc0002, FALSE, EBegin());return TRUE;}BOOL CWater::H0x01fc0002_WaterFly_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fc0002 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; +return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_EPass):{const EPass&epass= (EPass&)__eeInput; + +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +BOOL bHit ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +bHit = epass . penOther != m_penLauncher || _pTimer -> CurrentTick () > m_fIgnoreTime ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +bHit &= ! (IsOfClass (epass . penOther , "Water")); +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +if(bHit ){ +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +WaterTouch (epass . penOther ); +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +UnsetTimer();Jump(STATE_CURRENT,0x01fc0003, FALSE, EInternal());return TRUE; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +} +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +return TRUE; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +}ASSERT(FALSE);break;case(EVENTCODE_ETouch):{const ETouch&etouch= (ETouch&)__eeInput; + +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_fIgnoreTime = 0.0f; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +BOOL bHit ; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +bHit = ! (etouch . penOther -> GetRenderType () & RT_BRUSH ); +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +bHit &= ! (IsOfClass (etouch . penOther , "Water")); +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +if(bHit ){ +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +WaterTouch (etouch . penOther ); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +UnsetTimer();Jump(STATE_CURRENT,0x01fc0003, FALSE, EInternal());return TRUE; +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +} +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +if(en_vCurrentTranslationAbsolute . Length () < 0.25f * en_vDesiredTranslationRelative . Length ()){ +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +UnsetTimer();Jump(STATE_CURRENT,0x01fc0003, FALSE, EInternal());return TRUE; +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +} +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +return TRUE; +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +}ASSERT(FALSE);break;case(EVENTCODE_EDeath):{const EDeath&e= (EDeath&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01fc0003, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;case(EVENTCODE_ETimer):{const ETimer&e= (ETimer&)__eeInput; +UnsetTimer();Jump(STATE_CURRENT,0x01fc0003, FALSE, EInternal());return TRUE;}ASSERT(FALSE);break;default: return FALSE; break; +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +}return TRUE;}BOOL CWater::H0x01fc0003_WaterFly_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fc0003 + +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +Return(STATE_CURRENT,EEnd ()); +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWater:: +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWater_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EWater, "CWater::Main expects 'EWater' as input!"); const EWater &ew = (const EWater &)__eeInput; +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +ASSERT (ew . penLauncher != NULL ); +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_penLauncher = ew . penLauncher ; +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_EwsSize = ew . EwsSize ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +InitAsModel (); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +SetPhysicsFlags (EPF_ONBLOCK_SLIDE | EPF_PUSHABLE | EPF_MOVABLE ); +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +SetCollisionFlags (ECF_PROJECTILE_MAGIC ); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +SetComponents (this , * GetModelObject () , MODEL_WATER , TEXTURE_WATER , 0 , TEX_SPEC_STRONG , 0); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +switch(m_EwsSize ){ +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +case WTS_SMALL : +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_fDamageAmount = 10.0f; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_fPushAwayFactor = 10.0f; +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 30.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +break ; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +case WTS_BIG : +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_fDamageAmount = 20.0f; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_fPushAwayFactor = 20.0f; +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +GetModelObject () -> StretchModel (FLOAT3D (4.0f , 4.0f , 4.0f)); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 50.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +break ; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +case WTS_LARGE : +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_fDamageAmount = 40.0f; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_fPushAwayFactor = 40.0f; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +GetModelObject () -> StretchModel (FLOAT3D (16.0f , 16.0f , 16.0f)); +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +LaunchAsPropelledProjectile (FLOAT3D (0.0f , 0.0f , - 80.0f) , (CMovableEntity *) (CEntity *) m_penLauncher ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +break ; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +} +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +ModelChangeNotify (); +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +SetupLightSource (); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +m_fIgnoreTime = _pTimer -> CurrentTick () + 1.0f; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +STATE_CWater_WaterFly, TRUE; +Jump(STATE_CURRENT, 0x01fc0004, FALSE, EBegin());return TRUE;}BOOL CWater::H0x01fc0004_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fc0004 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CWater_WaterFly, TRUE, EVoid());return TRUE;case EVENTCODE_EEnd: Jump(STATE_CURRENT,0x01fc0005, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CWater::H0x01fc0005_Main_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01fc0005 +const EEnd&__e= (EEnd&)__eeInput; +; +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +Destroy (); +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +Return(STATE_CURRENT,EVoid()); +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Water.es b/Sources/EntitiesMP/Water.es new file mode 100644 index 0000000..21a7099 --- /dev/null +++ b/Sources/EntitiesMP/Water.es @@ -0,0 +1,211 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +508 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Light"; + +enum WaterSize { + 0 WTS_SMALL "", // small water + 1 WTS_BIG "", // big water + 2 WTS_LARGE "", // large water +}; + + +// input parameter for water +event EWater { + CEntityPointer penLauncher, // entity which launch it + enum WaterSize EwsSize, // water size +}; + + +%{ +#define FLY_TIME 5.0f +%} + +class CWater : CMovableModelEntity { +name "Water"; +thumbnail ""; + +properties: + 1 CEntityPointer m_penLauncher, // entity which launch it + 2 enum WaterSize m_EwsSize = WTS_SMALL, // water size (type) + + // internal -> do not use + 10 FLOAT m_fDamageAmount = 0.0f, // water hit damage + 11 FLOAT m_fIgnoreTime = 0.0f, // time when laucher will be ignored + 12 FLOAT m_fPushAwayFactor = 0.0f, // push away on hit + +{ + CLightSource m_lsLightSource; +} + + +components: + 1 class CLASS_LIGHT "Classes\\Light.ecl", + +// ********* WATER ********* + 10 model MODEL_WATER "Models\\Enemies\\Elementals\\Projectile\\WaterDrop.mdl", + 11 texture TEXTURE_WATER "Models\\Enemies\\Elementals\\WaterManFX.tex", + +// ************** SPECULAR ************** +210 texture TEX_SPEC_WEAK "Models\\SpecularTextures\\Weak.tex", +211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex", +212 texture TEX_SPEC_STRONG "Models\\SpecularTextures\\Strong.tex", + + + +functions: + /* Read from stream. */ + void Read_t( CTStream *istr) // throw char * + { + CRationalEntity::Read_t(istr); + SetupLightSource(); + }; + + /* Get static light source information. */ + CLightSource *GetLightSource(void) + { + if (!IsPredictor()) { + return &m_lsLightSource; + } else { + return NULL; + } + }; + + // Setup light source + void SetupLightSource(void) + { + // setup light source + CLightSource lsNew; + lsNew.ls_ulFlags = LSF_NONPERSISTENT|LSF_DYNAMIC; + lsNew.ls_colColor = C_lBLUE; + lsNew.ls_rFallOff = 1.0f; + lsNew.ls_rHotSpot = 0.2f; + lsNew.ls_plftLensFlare = NULL; + lsNew.ls_ubPolygonalMask = 0; + lsNew.ls_paoLightAnimation = NULL; + + m_lsLightSource.ls_penEntity = this; + m_lsLightSource.SetLightSource(lsNew); + }; + + // render particles + void RenderParticles(void) { + }; + + + // water touch his valid target + void WaterTouch(CEntityPointer penHit) { + // direct damage + FLOAT3D vDirection; + AnglesToDirectionVector(GetPlacement().pl_OrientationAngle, vDirection); + InflictDirectDamage(penHit, m_penLauncher, DMT_PROJECTILE, m_fDamageAmount, + GetPlacement().pl_PositionVector, vDirection); + // push target away + FLOAT3D vSpeed; + GetHeadingDirection(0.0f, vSpeed); + vSpeed = vSpeed * m_fPushAwayFactor; + KickEntity(penHit, vSpeed); + }; + + + +/************************************************************ + * P R O C E D U R E S * + ************************************************************/ +procedures: + // --->>> PROJECTILE SLIDE ON BRUSH + WaterFly(EVoid) { + // fly loop + wait(FLY_TIME) { + on (EBegin) : { resume; } + on (EPass epass) : { + BOOL bHit; + // ignore launcher within 1 second + bHit = epass.penOther!=m_penLauncher || _pTimer->CurrentTick()>m_fIgnoreTime; + // ignore water + bHit &= !(IsOfClass(epass.penOther, "Water")); + if (bHit) { + WaterTouch(epass.penOther); + stop; + } + resume; + } + on (ETouch etouch) : { + // clear time limit for launcher + m_fIgnoreTime = 0.0f; + // ignore brushes + BOOL bHit; + bHit = !(etouch.penOther->GetRenderType() & RT_BRUSH); + // ignore another projectile of same type + bHit &= !(IsOfClass(etouch.penOther, "Water")); + if (bHit) { + WaterTouch(etouch.penOther); + stop; + } + // water is moving to slow (stuck somewhere) -> kill it + if (en_vCurrentTranslationAbsolute.Length() < 0.25f*en_vDesiredTranslationRelative.Length()) { + stop; + } + resume; + } + on (EDeath) : { stop; } + on (ETimer) : { stop; } + } + return EEnd(); + }; + + + // --->>> MAIN + Main(EWater ew) { + // remember the initial parameters + ASSERT(ew.penLauncher!=NULL); + m_penLauncher = ew.penLauncher; + m_EwsSize = ew.EwsSize; + + // initialization + InitAsModel(); + SetPhysicsFlags(EPF_ONBLOCK_SLIDE|EPF_PUSHABLE|EPF_MOVABLE); + SetCollisionFlags(ECF_PROJECTILE_MAGIC); + SetComponents(this, *GetModelObject(), MODEL_WATER, TEXTURE_WATER, 0, TEX_SPEC_STRONG, 0); + + // setup + switch(m_EwsSize) { + case WTS_SMALL: + m_fDamageAmount = 10.0f; + m_fPushAwayFactor = 10.0f; + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -30.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + break; + case WTS_BIG: + m_fDamageAmount = 20.0f; + m_fPushAwayFactor = 20.0f; + GetModelObject()->StretchModel(FLOAT3D(4.0f, 4.0f, 4.0f)); + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -50.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + break; + case WTS_LARGE: + m_fDamageAmount = 40.0f; + m_fPushAwayFactor = 40.0f; + GetModelObject()->StretchModel(FLOAT3D(16.0f, 16.0f, 16.0f)); + LaunchAsPropelledProjectile(FLOAT3D(0.0f, 0.0f, -80.0f), (CMovableEntity*)(CEntity*)m_penLauncher); + break; + } + ModelChangeNotify(); + + // setup light source + SetupLightSource(); + + // remember lauching time + m_fIgnoreTime = _pTimer->CurrentTick() + 1.0f; + + // fly + autocall WaterFly() EEnd; + + // cease to exist + Destroy(); + + return; + } +}; diff --git a/Sources/EntitiesMP/Water.h b/Sources/EntitiesMP/Water.h new file mode 100644 index 0000000..a08b9d5 --- /dev/null +++ b/Sources/EntitiesMP/Water.h @@ -0,0 +1,62 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Water_INCLUDED +#define _EntitiesMP_Water_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType WaterSize_enum; +enum WaterSize { + WTS_SMALL = 0, + WTS_BIG = 1, + WTS_LARGE = 2, +}; +DECL_DLL inline void ClearToDefault(WaterSize &e) { e = (WaterSize)0; } ; +#define EVENTCODE_EWater 0x01fc0000 +class DECL_DLL EWater : public CEntityEvent { +public: +EWater(); +CEntityEvent *MakeCopy(void); +CEntityPointer penLauncher; +enum WaterSize EwsSize; +}; +DECL_DLL inline void ClearToDefault(EWater &e) { e = EWater(); } ; +extern "C" DECL_DLL CDLLEntityClass CWater_DLLClass; +class CWater : public CMovableModelEntity { +public: + DECL_DLL virtual void SetDefaultProperties(void); + CEntityPointer m_penLauncher; + enum WaterSize m_EwsSize; + FLOAT m_fDamageAmount; + FLOAT m_fIgnoreTime; + FLOAT m_fPushAwayFactor; +CLightSource m_lsLightSource; + +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +void Read_t(CTStream * istr); + +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +CLightSource * GetLightSource(void); + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +void SetupLightSource(void); + +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +void RenderParticles(void); + +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +void WaterTouch(CEntityPointer penHit); +#define STATE_CWater_WaterFly 0x01fc0001 + BOOL +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +WaterFly(const CEntityEvent &__eeInput); + BOOL H0x01fc0002_WaterFly_01(const CEntityEvent &__eeInput); + BOOL H0x01fc0003_WaterFly_02(const CEntityEvent &__eeInput); +#define STATE_CWater_Main 1 + BOOL +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x01fc0004_Main_01(const CEntityEvent &__eeInput); + BOOL H0x01fc0005_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Water_INCLUDED diff --git a/Sources/EntitiesMP/Water_tables.h b/Sources/EntitiesMP/Water_tables.h new file mode 100644 index 0000000..e6e8d9f --- /dev/null +++ b/Sources/EntitiesMP/Water_tables.h @@ -0,0 +1,61 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(WaterSize) + EP_ENUMVALUE(WTS_SMALL, ""), + EP_ENUMVALUE(WTS_BIG, ""), + EP_ENUMVALUE(WTS_LARGE, ""), +EP_ENUMEND(WaterSize); + +#define ENTITYCLASS CWater + +CEntityProperty CWater_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x000001fc<<8)+1, offsetof(CWater, m_penLauncher), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &WaterSize_enum, (0x000001fc<<8)+2, offsetof(CWater, m_EwsSize), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fc<<8)+10, offsetof(CWater, m_fDamageAmount), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fc<<8)+11, offsetof(CWater, m_fIgnoreTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x000001fc<<8)+12, offsetof(CWater, m_fPushAwayFactor), "", 0, 0, 0), +}; +#define CWater_propertiesct ARRAYCOUNT(CWater_properties) + +CEntityComponent CWater_components[] = { +#define CLASS_LIGHT ((0x000001fc<<8)+1) + CEntityComponent(ECT_CLASS, CLASS_LIGHT, "EFNM" "Classes\\Light.ecl"), +#define MODEL_WATER ((0x000001fc<<8)+10) + CEntityComponent(ECT_MODEL, MODEL_WATER, "EFNM" "Models\\Enemies\\Elementals\\Projectile\\WaterDrop.mdl"), +#define TEXTURE_WATER ((0x000001fc<<8)+11) + CEntityComponent(ECT_TEXTURE, TEXTURE_WATER, "EFNM" "Models\\Enemies\\Elementals\\WaterManFX.tex"), +#define TEX_SPEC_WEAK ((0x000001fc<<8)+210) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_WEAK, "EFNM" "Models\\SpecularTextures\\Weak.tex"), +#define TEX_SPEC_MEDIUM ((0x000001fc<<8)+211) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_MEDIUM, "EFNM" "Models\\SpecularTextures\\Medium.tex"), +#define TEX_SPEC_STRONG ((0x000001fc<<8)+212) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_STRONG, "EFNM" "Models\\SpecularTextures\\Strong.tex"), +}; +#define CWater_componentsct ARRAYCOUNT(CWater_components) + +CEventHandlerEntry CWater_handlers[] = { + {0x01fc0001, -1, CEntity::pEventHandler(&CWater:: +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +WaterFly),DEBUGSTRING("CWater::WaterFly")}, + {0x01fc0002, -1, CEntity::pEventHandler(&CWater::H0x01fc0002_WaterFly_01), DEBUGSTRING("CWater::H0x01fc0002_WaterFly_01")}, + {0x01fc0003, -1, CEntity::pEventHandler(&CWater::H0x01fc0003_WaterFly_02), DEBUGSTRING("CWater::H0x01fc0003_WaterFly_02")}, + {1, -1, CEntity::pEventHandler(&CWater:: +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Water.es" +Main),DEBUGSTRING("CWater::Main")}, + {0x01fc0004, -1, CEntity::pEventHandler(&CWater::H0x01fc0004_Main_01), DEBUGSTRING("CWater::H0x01fc0004_Main_01")}, + {0x01fc0005, -1, CEntity::pEventHandler(&CWater::H0x01fc0005_Main_02), DEBUGSTRING("CWater::H0x01fc0005_Main_02")}, +}; +#define CWater_handlersct ARRAYCOUNT(CWater_handlers) + +CEntity *CWater_New(void) { return new CWater; }; +void CWater_OnInitClass(void) {}; +void CWater_OnEndClass(void) {}; +void CWater_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CWater_OnWorldEnd(CWorld *pwo) {}; +void CWater_OnWorldInit(CWorld *pwo) {}; +void CWater_OnWorldTick(CWorld *pwo) {}; +void CWater_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CWater, CMovableModelEntity, "Water", "", 0x000001fc); +DECLARE_CTFILENAME(_fnmCWater_tbn, ""); diff --git a/Sources/EntitiesMP/WeaponItem.cpp b/Sources/EntitiesMP/WeaponItem.cpp new file mode 100644 index 0000000..53ecfa4 --- /dev/null +++ b/Sources/EntitiesMP/WeaponItem.cpp @@ -0,0 +1,502 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" + +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" +#include "Models/Weapons/Colt/ColtItem.h" +#include "Models/Weapons/SingleShotgun/SingleShotgunItem.h" +#include "Models/Weapons/DoubleShotgun/DoubleShotgunItem.h" +#include "Models/Weapons/TommyGun/TommyGunItem.h" +#include "Models/Weapons/MiniGun/MiniGunItem.h" +#include "Models/Weapons/GrenadeLauncher/GrenadeLauncherItem.h" +#include "Models/Weapons/RocketLauncher/RocketLauncherItem.h" +#include "ModelsMP/Weapons/Sniper/SniperItem.h" +#include "ModelsMP/Weapons/Sniper/Body.h" +#include "ModelsMP/Weapons/Flamer/FlamerItem.h" +#include "ModelsMP/Weapons/Chainsaw/ChainsawItem.h" +#include "ModelsMP/Weapons/Chainsaw/BladeForPlayer.h" +#include "Models/Weapons/Laser/LaserItem.h" +#include "Models/Weapons/Cannon/Cannon.h" + +#include "EntitiesMP/PlayerWeapons.h" + + +#include +#include +CEntityEvent *EWeaponItem::MakeCopy(void) { CEntityEvent *peeCopy = new EWeaponItem(*this); return peeCopy;} +EWeaponItem::EWeaponItem() : CEntityEvent(EVENTCODE_EWeaponItem) {; + ClearToDefault(iWeapon); + ClearToDefault(iAmmo); + ClearToDefault(bDropped); +}; +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" + +extern void CPlayerWeapons_Precache(ULONG ulAvailable); + +void CWeaponItem::SetDefaultProperties(void) { + m_EwitType = WIT_COLT ; + CItem::SetDefaultProperties(); +} + +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +void CWeaponItem::Precache(void) { +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +PrecacheSound (SOUND_PICK ); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +switch(m_EwitType ){ +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_COLT : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_COLT ) - 1));break ; +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_SINGLESHOTGUN : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_SINGLESHOTGUN ) - 1));break ; +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_DOUBLESHOTGUN : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_DOUBLESHOTGUN ) - 1));break ; +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_TOMMYGUN : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_TOMMYGUN ) - 1));break ; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_MINIGUN : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_MINIGUN ) - 1));break ; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_ROCKETLAUNCHER : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_ROCKETLAUNCHER ) - 1));break ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_GRENADELAUNCHER : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_GRENADELAUNCHER ) - 1));break ; +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_SNIPER : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_SNIPER ) - 1));break ; +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_FLAMER : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_FLAMER ) - 1));break ; +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_CHAINSAW : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_CHAINSAW ) - 1));break ; +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_LASER : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_LASER ) - 1));break ; +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_CANNON : CPlayerWeapons_Precache (1 << (INDEX (WEAPON_IRONCANNON ) - 1));break ; +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +BOOL CWeaponItem::FillEntityStatistics(EntityStats * pes) +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +{ +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +pes -> es_strName = m_strDescription ; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +pes -> es_ctCount = 1; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +pes -> es_ctAmmount = 1; +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +pes -> es_fValue = 1; +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +pes -> es_iScore = 0; +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +return TRUE ; +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} + +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +void CWeaponItem::RenderParticles(void) { +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +if(GetRenderType () != CEntity :: RT_MODEL || GetSP () -> sp_gmGameMode > CSessionProperties :: GM_COOPERATIVE +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +|| ! ShowItemParticles ()) +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +{ +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +return ; +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +switch(m_EwitType ){ +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_COLT : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_SINGLESHOTGUN : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_DOUBLESHOTGUN : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_TOMMYGUN : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_MINIGUN : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_ROCKETLAUNCHER : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_GRENADELAUNCHER : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_SNIPER : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_FLAMER : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_CHAINSAW : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 227 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_LASER : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_GHOSTBUSTER : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_CANNON : Particles_Atomic (this , 1.5f , 1.5f , PT_STAR07 , 12);break ; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} + +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +void CWeaponItem::SetProperties(void) +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +{ +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +BOOL bDM = FALSE ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +FLOAT3D vDMStretch = FLOAT3D (2.0f , 2.0f , 2.0f); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +switch(m_EwitType ){ +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_COLT : +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Colt"); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_COLT , TEXTURE_COLTMAIN , 0 , 0 , 0); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (COLTITEM_ATTACHMENT_BULLETS , MODEL_COLTBULLETS , TEXTURE_COLTBULLETS , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 247 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (COLTITEM_ATTACHMENT_COCK , MODEL_COLTCOCK , TEXTURE_COLTCOCK , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (COLTITEM_ATTACHMENT_BODY , MODEL_COLTMAIN , TEXTURE_COLTMAIN , TEX_REFL_LIGHTBLUEMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : FLOAT3D (4.5f , 4.5f , 4.5f)); +#line 250 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ; +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_SINGLESHOTGUN : +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Single Shotgun"); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_SINGLESHOTGUN , TEXTURE_SS_HANDLE , 0 , 0 , 0); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (SINGLESHOTGUNITEM_ATTACHMENT_BARRELS , MODEL_SS_BARRELS , TEXTURE_SS_BARRELS , TEX_REFL_DARKMETAL , TEX_SPEC_WEAK , 0); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (SINGLESHOTGUNITEM_ATTACHMENT_HANDLE , MODEL_SS_HANDLE , TEXTURE_SS_HANDLE , TEX_REFL_DARKMETAL , TEX_SPEC_MEDIUM , 0); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (SINGLESHOTGUNITEM_ATTACHMENT_SLIDER , MODEL_SS_SLIDER , TEXTURE_SS_BARRELS , TEX_REFL_DARKMETAL , TEX_SPEC_MEDIUM , 0); +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : (FLOAT3D (3.5f , 3.5f , 3.5f))); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ; +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_DOUBLESHOTGUN : +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Double Shotgun"); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_DOUBLESHOTGUN , TEXTURE_DS_HANDLE , 0 , 0 , 0); +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (DOUBLESHOTGUNITEM_ATTACHMENT_BARRELS , MODEL_DS_BARRELS , TEXTURE_DS_BARRELS , TEX_REFL_BWRIPLES01 , TEX_SPEC_MEDIUM , 0); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (DOUBLESHOTGUNITEM_ATTACHMENT_HANDLE , MODEL_DS_HANDLE , TEXTURE_DS_HANDLE , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (DOUBLESHOTGUNITEM_ATTACHMENT_SWITCH , MODEL_DS_SWITCH , TEXTURE_DS_SWITCH , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : (FLOAT3D (3.0f , 3.0f , 3.0f))); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ; +#line 276 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_TOMMYGUN : +#line 277 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Tommygun"); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_TOMMYGUN , TEXTURE_TG_BODY , 0 , 0 , 0); +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (TOMMYGUNITEM_ATTACHMENT_BODY , MODEL_TG_BODY , TEXTURE_TG_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (TOMMYGUNITEM_ATTACHMENT_SLIDER , MODEL_TG_SLIDER , TEXTURE_TG_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 282 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : (FLOAT3D (3.0f , 3.0f , 3.0f))); +#line 283 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_MINIGUN : +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Minigun"); +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_MINIGUN , TEXTURE_MG_BODY , 0 , 0 , 0); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (MINIGUNITEM_ATTACHMENT_BARRELS , MODEL_MG_BARRELS , TEXTURE_MG_BARRELS , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (MINIGUNITEM_ATTACHMENT_BODY , MODEL_MG_BODY , TEXTURE_MG_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (MINIGUNITEM_ATTACHMENT_ENGINE , MODEL_MG_ENGINE , TEXTURE_MG_BARRELS , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : (FLOAT3D (1.75f , 1.75f , 1.75f))); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ; +#line 297 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_ROCKETLAUNCHER : +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Rocket launcher"); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_ROCKETLAUNCHER , TEXTURE_RL_BODY , 0 , 0 , 0); +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_BODY , MODEL_RL_BODY , TEXTURE_RL_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_ROTATINGPART , MODEL_RL_ROTATINGPART , TEXTURE_RL_ROTATINGPART , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET1 , MODEL_RL_ROCKET , TEXTURE_RL_ROCKET , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET2 , MODEL_RL_ROCKET , TEXTURE_RL_ROCKET , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET3 , MODEL_RL_ROCKET , TEXTURE_RL_ROCKET , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET4 , MODEL_RL_ROCKET , TEXTURE_RL_ROCKET , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : (FLOAT3D (2.5f , 2.5f , 2.5f))); +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_GRENADELAUNCHER : +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Grenade launcher"); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_GRENADELAUNCHER , TEXTURE_GL_BODY , 0 , 0 , 0); +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (GRENADELAUNCHERITEM_ATTACHMENT_BODY , MODEL_GL_BODY , TEXTURE_GL_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (GRENADELAUNCHERITEM_ATTACHMENT_MOVING_PART , MODEL_GL_MOVINGPART , TEXTURE_GL_MOVINGPART , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (GRENADELAUNCHERITEM_ATTACHMENT_GRENADE , MODEL_GL_GRENADE , TEXTURE_GL_MOVINGPART , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : (FLOAT3D (2.5f , 2.5f , 2.5f))); +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_SNIPER : +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Sniper"); +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_SNIPER , TEXTURE_SNIPER_BODY , 0 , 0 , 0); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (SNIPERITEM_ATTACHMENT_BODY , MODEL_SNIPER_BODY , TEXTURE_SNIPER_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +SetItemAttachmentAnim (SNIPERITEM_ATTACHMENT_BODY , BODY_ANIM_FORITEM1 ); +#line 328 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : (FLOAT3D (3.0f , 3.0f , 3.0f))); +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ; +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_FLAMER : +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Flamer"); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_FLAMER , TEXTURE_FL_BODY , 0 , 0 , 0); +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (FLAMERITEM_ATTACHMENT_BODY , MODEL_FL_BODY , +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +TEXTURE_FL_BODY , TEX_REFL_BWRIPLES02 , TEX_SPEC_MEDIUM , 0); +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (FLAMERITEM_ATTACHMENT_FUEL , MODEL_FL_RESERVOIR , +#line 339 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +TEXTURE_FL_FUELRESERVOIR , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 340 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (FLAMERITEM_ATTACHMENT_FLAME , MODEL_FL_FLAME , +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +TEXTURE_FL_FLAME , 0 , 0 , 0); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : (FLOAT3D (2.5f , 2.5f , 2.5f))); +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ; +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_CHAINSAW : { +#line 347 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Chainsaw"); +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_CHAINSAW , TEXTURE_CS_BODY , 0 , 0 , 0); +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (CHAINSAWITEM_ATTACHMENT_CHAINSAW , MODEL_CS_BODY , TEXTURE_CS_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 351 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (CHAINSAWITEM_ATTACHMENT_BLADE , MODEL_CS_BLADE , TEXTURE_CS_BLADE , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 352 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +CModelObject * pmoMain , * pmo ; +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +pmoMain = & (GetModelObject () -> GetAttachmentModel (ITEMHOLDER_ATTACHMENT_ITEM ) -> amo_moModelObject ); +#line 354 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +pmo = & (pmoMain -> GetAttachmentModel (CHAINSAWITEM_ATTACHMENT_BLADE ) -> amo_moModelObject ); +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddAttachmentToModel (this , * pmo , BLADEFORPLAYER_ATTACHMENT_TEETH , MODEL_CS_TEETH , TEXTURE_CS_TEETH , 0 , 0 , 0); +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : (FLOAT3D (2.0f , 2.0f , 2.0f))); +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ;} +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_LASER : +#line 362 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 10.0f; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Laser"); +#line 364 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_LASER , TEXTURE_LS_BODY , 0 , 0 , 0); +#line 365 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (LASERITEM_ATTACHMENT_BODY , MODEL_LS_BODY , TEXTURE_LS_BODY , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (LASERITEM_ATTACHMENT_LEFTUP , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (LASERITEM_ATTACHMENT_LEFTDOWN , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 368 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (LASERITEM_ATTACHMENT_RIGHTUP , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 369 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (LASERITEM_ATTACHMENT_RIGHTDOWN , MODEL_LS_BARREL , TEXTURE_LS_BARREL , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : (FLOAT3D (2.5f , 2.5f , 2.5f))); +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ; +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +case WIT_CANNON : +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fRespawnTime = (m_fCustomRespawnTime > 0) ? m_fCustomRespawnTime : 30.0f; +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_strDescription . PrintF ("Cannon"); +#line 377 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItem (MODEL_CANNON , TEXTURE_CANNON , 0 , 0 , 0); +#line 378 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddItemAttachment (CANNON_ATTACHMENT_BODY , MODEL_CN_BODY , TEXTURE_CANNON , TEX_REFL_LIGHTMETAL01 , TEX_SPEC_MEDIUM , 0); +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StretchItem (bDM ? vDMStretch : (FLOAT3D (3.0f , 3.0f , 3.0f))); +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +break ; +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} +#line 385 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +AddFlare (MODEL_FLARE , TEXTURE_FLARE , FLOAT3D (0 , 0.6f , 0) , FLOAT3D (3 , 3 , 0.3f)); +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} +BOOL CWeaponItem:: +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +ItemCollected(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWeaponItem_ItemCollected + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EPass, "CWeaponItem::ItemCollected expects 'EPass' as input!"); const EPass &epass = (const EPass &)__eeInput; +#line 390 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +ASSERT (epass . penOther != NULL ); +#line 393 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +if(GetSP () -> sp_bWeaponsStay && ! (m_bPickupOnce || m_bRespawn )){ +#line 395 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +BOOL bWasPicked = MarkPickedBy (epass . penOther ); +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +if(bWasPicked ){ +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +Return(STATE_CURRENT,EVoid()); +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +return TRUE; +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +EWeaponItem eWeapon ; +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +eWeapon . iWeapon = m_EwitType ; +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +eWeapon . iAmmo = - 1; +#line 406 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +eWeapon . bDropped = m_bDropped ; +#line 408 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +if(epass . penOther -> ReceiveItem (eWeapon )){ +#line 409 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +if(_pNetwork -> IsPlayerLocal (epass . penOther )){IFeel_PlayEffect ("PU_Weapon");} +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_soPick . Set3DParameters (50.0f , 1.0f , 1.0f , 1.0f); +#line 412 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +PlaySound (m_soPick , SOUND_PICK , SOF_3D ); +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_fPickSoundLen = GetSoundLength (SOUND_PICK ); +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +if(! GetSP () -> sp_bWeaponsStay || m_bDropped || (m_bPickupOnce || m_bRespawn )){ +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemReceived, FALSE, EVoid());return TRUE; +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +Return(STATE_CURRENT,EVoid()); +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWeaponItem:: +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWeaponItem_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWeaponItem::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +if(m_EwitType == WIT_GHOSTBUSTER ){ +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +m_EwitType = WIT_LASER ; +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +} +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +Initialize (); +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +StartModelAnim (ITEMHOLDER_ANIM_BIGOSCILATION , AOF_LOOPING | AOF_NORESTART ); +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +ForceCollisionBoxIndexChange (ITEMHOLDER_COLLISION_BOX_BIG ); +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +SetProperties (); +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +if(!(! m_bDropped )){ Jump(STATE_CURRENT,0x03220006, FALSE, EInternal());return TRUE;} +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +Jump(STATE_CURRENT, STATE_CItem_ItemLoop, FALSE, EVoid());return TRUE;Jump(STATE_CURRENT,0x03220005, FALSE, EInternal());return TRUE;}BOOL CWeaponItem::H0x03220006_Main_05(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03220006 +if(!(TRUE )){ Jump(STATE_CURRENT,0x03220004, FALSE, EInternal());return TRUE;} +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +SetTimerAt(THINKTIME_NEVER); +Jump(STATE_CURRENT, 0x03220002, FALSE, EBegin());return TRUE;}BOOL CWeaponItem::H0x03220002_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x03220002 +switch(__eeInput.ee_slEvent){case(EVENTCODE_EBegin):{const EBegin&e= (EBegin&)__eeInput; + +#line 437 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +SpawnReminder (this , m_fRespawnTime , 0); +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +Call(STATE_CURRENT, STATE_CItem_ItemLoop, FALSE, EVoid());return TRUE; +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +}ASSERT(FALSE);break;case(EVENTCODE_EReminder):{const EReminder&e= (EReminder&)__eeInput; + +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +SendEvent (EEnd ()); +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +return TRUE; +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +}ASSERT(FALSE);break;default: return FALSE; break; +#line 444 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +}return TRUE;}BOOL CWeaponItem::H0x03220003_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03220003 +Jump(STATE_CURRENT,0x03220004, FALSE, EInternal());return TRUE;}BOOL CWeaponItem::H0x03220004_Main_03(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03220004 +Jump(STATE_CURRENT,0x03220005, FALSE, EInternal());return TRUE;} +BOOL CWeaponItem::H0x03220005_Main_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x03220005 + ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/WeaponItem.es b/Sources/EntitiesMP/WeaponItem.es new file mode 100644 index 0000000..21aba69 --- /dev/null +++ b/Sources/EntitiesMP/WeaponItem.es @@ -0,0 +1,447 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +802 +%{ +#include "StdH.h" +#include "Models/Items/ItemHolder/ItemHolder.h" +#include "Models/Weapons/Colt/ColtItem.h" +#include "Models/Weapons/SingleShotgun/SingleShotgunItem.h" +#include "Models/Weapons/DoubleShotgun/DoubleShotgunItem.h" +#include "Models/Weapons/TommyGun/TommyGunItem.h" +#include "Models/Weapons/MiniGun/MiniGunItem.h" +#include "Models/Weapons/GrenadeLauncher/GrenadeLauncherItem.h" +#include "Models/Weapons/RocketLauncher/RocketLauncherItem.h" +#include "ModelsMP/Weapons/Sniper/SniperItem.h" +#include "ModelsMP/Weapons/Sniper/Body.h" +#include "ModelsMP/Weapons/Flamer/FlamerItem.h" +#include "ModelsMP/Weapons/Chainsaw/ChainsawItem.h" +#include "ModelsMP/Weapons/Chainsaw/BladeForPlayer.h" +#include "Models/Weapons/Laser/LaserItem.h" +#include "Models/Weapons/Cannon/Cannon.h" + +#include "EntitiesMP/PlayerWeapons.h" + +%} + +uses "EntitiesMP/Item"; + +// weapon type +enum WeaponItemType { + 1 WIT_COLT "Colt", + 2 WIT_SINGLESHOTGUN "Single shotgun", + 3 WIT_DOUBLESHOTGUN "Double shotgun", + 4 WIT_TOMMYGUN "Tommygun", + 5 WIT_MINIGUN "Minigun", + 6 WIT_ROCKETLAUNCHER "Rocket launcher", + 7 WIT_GRENADELAUNCHER "Grenade launcher", + 8 WIT_SNIPER "Sniper", + 9 WIT_FLAMER "Flamer", + 10 WIT_LASER "Laser", + 11 WIT_CHAINSAW "Chainsaw", + 12 WIT_CANNON "Cannon", + 13 WIT_GHOSTBUSTER "obsolete", +}; + +// event for sending through receive item +event EWeaponItem { + INDEX iWeapon, // weapon collected + INDEX iAmmo, // weapon ammo (used only for leaving weapons, -1 for deafult ammount) + BOOL bDropped, // for dropped weapons (can be picked even if weapons stay) +}; + +%{ +extern void CPlayerWeapons_Precache(ULONG ulAvailable); +%} + + +class CWeaponItem : CItem { +name "Weapon Item"; +thumbnail "Thumbnails\\WeaponItem.tbn"; + +properties: + 1 enum WeaponItemType m_EwitType "Type" 'Y' = WIT_COLT, // weapon + +components: + 0 class CLASS_BASE "Classes\\Item.ecl", + +// ************** COLT ************** + 30 model MODEL_COLT "Models\\Weapons\\Colt\\ColtItem.mdl", + 31 model MODEL_COLTCOCK "Models\\Weapons\\Colt\\ColtCock.mdl", + 32 model MODEL_COLTMAIN "Models\\Weapons\\Colt\\ColtMain.mdl", + 33 model MODEL_COLTBULLETS "Models\\Weapons\\Colt\\ColtBullets.mdl", + 34 texture TEXTURE_COLTMAIN "Models\\Weapons\\Colt\\ColtMain.tex", + 35 texture TEXTURE_COLTCOCK "Models\\Weapons\\Colt\\ColtCock.tex", + 36 texture TEXTURE_COLTBULLETS "Models\\Weapons\\Colt\\ColtBullets.tex", + +// ************** SINGLE SHOTGUN ************ + 40 model MODEL_SINGLESHOTGUN "Models\\Weapons\\SingleShotgun\\SingleShotgunItem.mdl", + 41 model MODEL_SS_SLIDER "Models\\Weapons\\SingleShotgun\\Slider.mdl", + 42 model MODEL_SS_HANDLE "Models\\Weapons\\SingleShotgun\\Handle.mdl", + 43 model MODEL_SS_BARRELS "Models\\Weapons\\SingleShotgun\\Barrels.mdl", + 44 texture TEXTURE_SS_HANDLE "Models\\Weapons\\SingleShotgun\\Handle.tex", + 45 texture TEXTURE_SS_BARRELS "Models\\Weapons\\SingleShotgun\\Barrels.tex", + +// ************** DOUBLE SHOTGUN ************** + 50 model MODEL_DOUBLESHOTGUN "Models\\Weapons\\DoubleShotgun\\DoubleShotgunItem.mdl", + 51 model MODEL_DS_HANDLE "Models\\Weapons\\DoubleShotgun\\Dshotgunhandle.mdl", + 52 model MODEL_DS_BARRELS "Models\\Weapons\\DoubleShotgun\\Dshotgunbarrels.mdl", + 54 model MODEL_DS_SWITCH "Models\\Weapons\\DoubleShotgun\\Switch.mdl", + 56 texture TEXTURE_DS_HANDLE "Models\\Weapons\\DoubleShotgun\\Handle.tex", + 57 texture TEXTURE_DS_BARRELS "Models\\Weapons\\DoubleShotgun\\Barrels.tex", + 58 texture TEXTURE_DS_SWITCH "Models\\Weapons\\DoubleShotgun\\Switch.tex", + +// ************** TOMMYGUN ************** + 70 model MODEL_TOMMYGUN "Models\\Weapons\\TommyGun\\TommyGunItem.mdl", + 71 model MODEL_TG_BODY "Models\\Weapons\\TommyGun\\Body.mdl", + 72 model MODEL_TG_SLIDER "Models\\Weapons\\TommyGun\\Slider.mdl", + 73 texture TEXTURE_TG_BODY "Models\\Weapons\\TommyGun\\Body.tex", + +// ************** MINIGUN ************** + 80 model MODEL_MINIGUN "Models\\Weapons\\MiniGun\\MiniGunItem.mdl", + 81 model MODEL_MG_BARRELS "Models\\Weapons\\MiniGun\\Barrels.mdl", + 82 model MODEL_MG_BODY "Models\\Weapons\\MiniGun\\Body.mdl", + 83 model MODEL_MG_ENGINE "Models\\Weapons\\MiniGun\\Engine.mdl", + 84 texture TEXTURE_MG_BODY "Models\\Weapons\\MiniGun\\Body.tex", + 99 texture TEXTURE_MG_BARRELS "Models\\Weapons\\MiniGun\\Barrels.tex", + +// ************** ROCKET LAUNCHER ************** + 90 model MODEL_ROCKETLAUNCHER "Models\\Weapons\\RocketLauncher\\RocketLauncherItem.mdl", + 91 model MODEL_RL_BODY "Models\\Weapons\\RocketLauncher\\Body.mdl", + 92 texture TEXTURE_RL_BODY "Models\\Weapons\\RocketLauncher\\Body.tex", + 93 model MODEL_RL_ROTATINGPART "Models\\Weapons\\RocketLauncher\\RotatingPart.mdl", + 94 texture TEXTURE_RL_ROTATINGPART "Models\\Weapons\\RocketLauncher\\RotatingPart.tex", + 95 model MODEL_RL_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl", + 96 texture TEXTURE_RL_ROCKET "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex", + +// ************** GRENADE LAUNCHER ************** +100 model MODEL_GRENADELAUNCHER "Models\\Weapons\\GrenadeLauncher\\GrenadeLauncherItem.mdl", +101 model MODEL_GL_BODY "Models\\Weapons\\GrenadeLauncher\\Body.mdl", +102 model MODEL_GL_MOVINGPART "Models\\Weapons\\GrenadeLauncher\\MovingPipe.mdl", +103 model MODEL_GL_GRENADE "Models\\Weapons\\GrenadeLauncher\\GrenadeBack.mdl", +104 texture TEXTURE_GL_BODY "Models\\Weapons\\GrenadeLauncher\\Body.tex", +105 texture TEXTURE_GL_MOVINGPART "Models\\Weapons\\GrenadeLauncher\\MovingPipe.tex", + +// ************** SNIPER ************** +110 model MODEL_SNIPER "ModelsMP\\Weapons\\Sniper\\Sniper.mdl", +111 model MODEL_SNIPER_BODY "ModelsMP\\Weapons\\Sniper\\Body.mdl", +112 texture TEXTURE_SNIPER_BODY "ModelsMP\\Weapons\\Sniper\\Body.tex", + +// ************** FLAMER ************** +130 model MODEL_FLAMER "ModelsMP\\Weapons\\Flamer\\FlamerItem.mdl", +131 model MODEL_FL_BODY "ModelsMP\\Weapons\\Flamer\\Body.mdl", +132 model MODEL_FL_RESERVOIR "ModelsMP\\Weapons\\Flamer\\FuelReservoir.mdl", +133 model MODEL_FL_FLAME "ModelsMP\\Weapons\\Flamer\\Flame.mdl", +134 texture TEXTURE_FL_BODY "ModelsMP\\Weapons\\Flamer\\Body.tex", +135 texture TEXTURE_FL_FLAME "ModelsMP\\Effects\\Flame\\Flame.tex", +136 texture TEXTURE_FL_FUELRESERVOIR "ModelsMP\\Weapons\\Flamer\\FuelReservoir.tex", + +// ************** LASER ************** +140 model MODEL_LASER "Models\\Weapons\\Laser\\LaserItem.mdl", +141 model MODEL_LS_BODY "Models\\Weapons\\Laser\\Body.mdl", +142 model MODEL_LS_BARREL "Models\\Weapons\\Laser\\Barrel.mdl", +143 texture TEXTURE_LS_BODY "Models\\Weapons\\Laser\\Body.tex", +144 texture TEXTURE_LS_BARREL "Models\\Weapons\\Laser\\Barrel.tex", + +// ************** CHAINSAW ************** +150 model MODEL_CHAINSAW "ModelsMP\\Weapons\\Chainsaw\\ChainsawItem.mdl", +151 model MODEL_CS_BODY "ModelsMP\\Weapons\\Chainsaw\\Body.mdl", +152 model MODEL_CS_BLADE "ModelsMP\\Weapons\\Chainsaw\\Blade.mdl", +153 model MODEL_CS_TEETH "ModelsMP\\Weapons\\Chainsaw\\Teeth.mdl", +154 texture TEXTURE_CS_BODY "ModelsMP\\Weapons\\Chainsaw\\Body.tex", +155 texture TEXTURE_CS_BLADE "ModelsMP\\Weapons\\Chainsaw\\Blade.tex", +156 texture TEXTURE_CS_TEETH "ModelsMP\\Weapons\\Chainsaw\\Teeth.tex", + +// ************** CANNON ************** +170 model MODEL_CANNON "Models\\Weapons\\Cannon\\Cannon.mdl", +171 model MODEL_CN_BODY "Models\\Weapons\\Cannon\\Body.mdl", +173 texture TEXTURE_CANNON "Models\\Weapons\\Cannon\\Body.tex", + +// ************** FLARE FOR EFFECT ************** +190 texture TEXTURE_FLARE "Models\\Items\\Flares\\Flare.tex", +191 model MODEL_FLARE "Models\\Items\\Flares\\Flare.mdl", + +// ************** REFLECTIONS ************** +200 texture TEX_REFL_BWRIPLES01 "Models\\ReflectionTextures\\BWRiples01.tex", +201 texture TEX_REFL_BWRIPLES02 "Models\\ReflectionTextures\\BWRiples02.tex", +202 texture TEX_REFL_LIGHTMETAL01 "Models\\ReflectionTextures\\LightMetal01.tex", +203 texture TEX_REFL_LIGHTBLUEMETAL01 "Models\\ReflectionTextures\\LightBlueMetal01.tex", +204 texture TEX_REFL_DARKMETAL "Models\\ReflectionTextures\\DarkMetal.tex", +205 texture TEX_REFL_PURPLE01 "Models\\ReflectionTextures\\Purple01.tex", + +// ************** SPECULAR ************** +210 texture TEX_SPEC_WEAK "Models\\SpecularTextures\\Weak.tex", +211 texture TEX_SPEC_MEDIUM "Models\\SpecularTextures\\Medium.tex", +212 texture TEX_SPEC_STRONG "Models\\SpecularTextures\\Strong.tex", + +// ************** SOUNDS ************** +213 sound SOUND_PICK "Sounds\\Items\\Weapon.wav", + +functions: + void Precache(void) { + PrecacheSound(SOUND_PICK); + switch (m_EwitType) { + case WIT_COLT: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_COLT )-1)); break; + case WIT_SINGLESHOTGUN: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_SINGLESHOTGUN )-1)); break; + case WIT_DOUBLESHOTGUN: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_DOUBLESHOTGUN )-1)); break; + case WIT_TOMMYGUN: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_TOMMYGUN )-1)); break; + case WIT_MINIGUN: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_MINIGUN )-1)); break; + case WIT_ROCKETLAUNCHER: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_ROCKETLAUNCHER )-1)); break; + case WIT_GRENADELAUNCHER: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_GRENADELAUNCHER)-1)); break; + case WIT_SNIPER: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_SNIPER )-1)); break; + case WIT_FLAMER: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_FLAMER )-1)); break; + case WIT_CHAINSAW: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_CHAINSAW )-1)); break; + case WIT_LASER: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_LASER )-1)); break; + case WIT_CANNON: CPlayerWeapons_Precache(1<<(INDEX(WEAPON_IRONCANNON )-1)); break; + } + } + /* Fill in entity statistics - for AI purposes only */ + BOOL FillEntityStatistics(EntityStats *pes) + { + pes->es_strName = m_strDescription; + pes->es_ctCount = 1; + pes->es_ctAmmount = 1; + pes->es_fValue = 1; + pes->es_iScore = 0;//m_iScore; + return TRUE; + } + + // render particles + void RenderParticles(void) { + // no particles when not existing or in DM modes + if (GetRenderType()!=CEntity::RT_MODEL || GetSP()->sp_gmGameMode>CSessionProperties::GM_COOPERATIVE + || !ShowItemParticles()) + { + return; + } + switch (m_EwitType) { + case WIT_COLT: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_SINGLESHOTGUN: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_DOUBLESHOTGUN: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_TOMMYGUN: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_MINIGUN: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_ROCKETLAUNCHER: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_GRENADELAUNCHER: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_SNIPER: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_FLAMER: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_CHAINSAW: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_LASER: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_GHOSTBUSTER: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + case WIT_CANNON: Particles_Atomic(this, 1.5f, 1.5f, PT_STAR07, 12); break; + } + } + + + // set weapon properties depending on weapon type + void SetProperties(void) + { + BOOL bDM = FALSE;//m_bRespawn || m_bDropped; + FLOAT3D vDMStretch = FLOAT3D( 2.0f, 2.0f, 2.0f); + + switch (m_EwitType) { + // *********** COLT *********** + case WIT_COLT: + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Colt"); + AddItem(MODEL_COLT, TEXTURE_COLTMAIN, 0, 0, 0); + AddItemAttachment(COLTITEM_ATTACHMENT_BULLETS, MODEL_COLTBULLETS, TEXTURE_COLTBULLETS, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(COLTITEM_ATTACHMENT_COCK, MODEL_COLTCOCK, TEXTURE_COLTCOCK, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(COLTITEM_ATTACHMENT_BODY, MODEL_COLTMAIN, TEXTURE_COLTMAIN, TEX_REFL_LIGHTBLUEMETAL01, TEX_SPEC_MEDIUM, 0); + StretchItem( bDM ? vDMStretch : FLOAT3D(4.5f, 4.5f, 4.5f)); + break; + + // *********** SINGLE SHOTGUN *********** + case WIT_SINGLESHOTGUN: + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Single Shotgun"); + AddItem(MODEL_SINGLESHOTGUN, TEXTURE_SS_HANDLE, 0, 0, 0); + AddItemAttachment(SINGLESHOTGUNITEM_ATTACHMENT_BARRELS, MODEL_SS_BARRELS, TEXTURE_SS_BARRELS, TEX_REFL_DARKMETAL, TEX_SPEC_WEAK, 0); + AddItemAttachment(SINGLESHOTGUNITEM_ATTACHMENT_HANDLE, MODEL_SS_HANDLE, TEXTURE_SS_HANDLE, TEX_REFL_DARKMETAL, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(SINGLESHOTGUNITEM_ATTACHMENT_SLIDER, MODEL_SS_SLIDER, TEXTURE_SS_BARRELS, TEX_REFL_DARKMETAL, TEX_SPEC_MEDIUM, 0); + StretchItem( bDM ? vDMStretch : (FLOAT3D(3.5f, 3.5f, 3.5f)) ); + break; + + // *********** DOUBLE SHOTGUN *********** + case WIT_DOUBLESHOTGUN: + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Double Shotgun"); + AddItem(MODEL_DOUBLESHOTGUN, TEXTURE_DS_HANDLE, 0, 0, 0); + AddItemAttachment(DOUBLESHOTGUNITEM_ATTACHMENT_BARRELS, MODEL_DS_BARRELS, TEXTURE_DS_BARRELS, TEX_REFL_BWRIPLES01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(DOUBLESHOTGUNITEM_ATTACHMENT_HANDLE, MODEL_DS_HANDLE, TEXTURE_DS_HANDLE, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(DOUBLESHOTGUNITEM_ATTACHMENT_SWITCH, MODEL_DS_SWITCH, TEXTURE_DS_SWITCH, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + StretchItem( bDM ? vDMStretch : (FLOAT3D(3.0f, 3.0f, 3.0f))); + break; + + + // *********** TOMMYGUN *********** + case WIT_TOMMYGUN: + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Tommygun"); + AddItem(MODEL_TOMMYGUN, TEXTURE_TG_BODY, 0, 0, 0); + AddItemAttachment(TOMMYGUNITEM_ATTACHMENT_BODY, MODEL_TG_BODY, TEXTURE_TG_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(TOMMYGUNITEM_ATTACHMENT_SLIDER, MODEL_TG_SLIDER, TEXTURE_TG_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + StretchItem( bDM ? vDMStretch : (FLOAT3D(3.0f, 3.0f, 3.0f))); + break; + + // *********** MINIGUN *********** + case WIT_MINIGUN: + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Minigun"); + AddItem(MODEL_MINIGUN, TEXTURE_MG_BODY, 0, 0, 0); + AddItemAttachment(MINIGUNITEM_ATTACHMENT_BARRELS, MODEL_MG_BARRELS, TEXTURE_MG_BARRELS, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(MINIGUNITEM_ATTACHMENT_BODY, MODEL_MG_BODY, TEXTURE_MG_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(MINIGUNITEM_ATTACHMENT_ENGINE, MODEL_MG_ENGINE, TEXTURE_MG_BARRELS, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + StretchItem( bDM ? vDMStretch : (FLOAT3D(1.75f, 1.75f, 1.75f))); + break; + + // *********** ROCKET LAUNCHER *********** + case WIT_ROCKETLAUNCHER: + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Rocket launcher"); + AddItem(MODEL_ROCKETLAUNCHER, TEXTURE_RL_BODY, 0, 0, 0); + AddItemAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_BODY, MODEL_RL_BODY, TEXTURE_RL_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_ROTATINGPART, MODEL_RL_ROTATINGPART, TEXTURE_RL_ROTATINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET1, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET2, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET3, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET4, MODEL_RL_ROCKET, TEXTURE_RL_ROCKET, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + StretchItem( bDM ? vDMStretch : (FLOAT3D(2.5f, 2.5f, 2.5f))); + break; + + // *********** GRENADE LAUNCHER *********** + case WIT_GRENADELAUNCHER: + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Grenade launcher"); + AddItem(MODEL_GRENADELAUNCHER, TEXTURE_GL_BODY, 0, 0, 0); + AddItemAttachment(GRENADELAUNCHERITEM_ATTACHMENT_BODY, MODEL_GL_BODY, TEXTURE_GL_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(GRENADELAUNCHERITEM_ATTACHMENT_MOVING_PART, MODEL_GL_MOVINGPART, TEXTURE_GL_MOVINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(GRENADELAUNCHERITEM_ATTACHMENT_GRENADE, MODEL_GL_GRENADE, TEXTURE_GL_MOVINGPART, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + StretchItem( bDM ? vDMStretch : (FLOAT3D(2.5f, 2.5f, 2.5f))); + break; + + // *********** SNIPER *********** + case WIT_SNIPER: + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Sniper"); + AddItem(MODEL_SNIPER, TEXTURE_SNIPER_BODY, 0, 0, 0); + AddItemAttachment(SNIPERITEM_ATTACHMENT_BODY, MODEL_SNIPER_BODY, TEXTURE_SNIPER_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + SetItemAttachmentAnim(SNIPERITEM_ATTACHMENT_BODY, BODY_ANIM_FORITEM1); + StretchItem( bDM ? vDMStretch : (FLOAT3D(3.0f, 3.0f, 3.0f))); + break; + + // *********** FLAMER *********** + case WIT_FLAMER: + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Flamer"); + AddItem(MODEL_FLAMER, TEXTURE_FL_BODY, 0, 0, 0); + AddItemAttachment(FLAMERITEM_ATTACHMENT_BODY, MODEL_FL_BODY, + TEXTURE_FL_BODY, TEX_REFL_BWRIPLES02, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(FLAMERITEM_ATTACHMENT_FUEL, MODEL_FL_RESERVOIR, + TEXTURE_FL_FUELRESERVOIR, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(FLAMERITEM_ATTACHMENT_FLAME, MODEL_FL_FLAME, + TEXTURE_FL_FLAME, 0, 0, 0); + StretchItem( bDM ? vDMStretch : (FLOAT3D(2.5f, 2.5f, 2.5f))); + break; + + // *********** CHAINSAW *********** + case WIT_CHAINSAW: { + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Chainsaw"); + AddItem(MODEL_CHAINSAW, TEXTURE_CS_BODY, 0, 0, 0); + AddItemAttachment(CHAINSAWITEM_ATTACHMENT_CHAINSAW, MODEL_CS_BODY, TEXTURE_CS_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(CHAINSAWITEM_ATTACHMENT_BLADE, MODEL_CS_BLADE, TEXTURE_CS_BLADE, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + CModelObject *pmoMain, *pmo; + pmoMain = &(GetModelObject()->GetAttachmentModel(ITEMHOLDER_ATTACHMENT_ITEM)->amo_moModelObject); + pmo = &(pmoMain->GetAttachmentModel(CHAINSAWITEM_ATTACHMENT_BLADE)->amo_moModelObject); + AddAttachmentToModel(this, *pmo, BLADEFORPLAYER_ATTACHMENT_TEETH, MODEL_CS_TEETH, TEXTURE_CS_TEETH, 0, 0, 0); + + StretchItem( bDM ? vDMStretch : (FLOAT3D(2.0f, 2.0f, 2.0f))); + break; } + + // *********** LASER *********** + case WIT_LASER: + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 10.0f; + m_strDescription.PrintF("Laser"); + AddItem(MODEL_LASER, TEXTURE_LS_BODY, 0, 0, 0); + AddItemAttachment(LASERITEM_ATTACHMENT_BODY, MODEL_LS_BODY, TEXTURE_LS_BODY, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(LASERITEM_ATTACHMENT_LEFTUP, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(LASERITEM_ATTACHMENT_LEFTDOWN, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(LASERITEM_ATTACHMENT_RIGHTUP, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + AddItemAttachment(LASERITEM_ATTACHMENT_RIGHTDOWN, MODEL_LS_BARREL, TEXTURE_LS_BARREL, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + StretchItem( bDM ? vDMStretch : (FLOAT3D(2.5f, 2.5f, 2.5f))); + break; + + // *********** CANNON *********** + case WIT_CANNON: + m_fRespawnTime = (m_fCustomRespawnTime>0) ? m_fCustomRespawnTime : 30.0f; + m_strDescription.PrintF("Cannon"); + AddItem(MODEL_CANNON, TEXTURE_CANNON, 0, 0, 0); + AddItemAttachment(CANNON_ATTACHMENT_BODY, MODEL_CN_BODY, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); +// AddItemAttachment(CANNON_ATTACHMENT_NUKEBOX, MODEL_CN_NUKEBOX, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); +// AddItemAttachment(CANNON_ATTACHMENT_LIGHT, MODEL_CN_LIGHT, TEXTURE_CANNON, TEX_REFL_LIGHTMETAL01, TEX_SPEC_MEDIUM, 0); + StretchItem( bDM ? vDMStretch : (FLOAT3D(3.0f, 3.0f, 3.0f))); + break; + } + // add flare + AddFlare(MODEL_FLARE, TEXTURE_FLARE, FLOAT3D(0,0.6f,0), FLOAT3D(3,3,0.3f) ); +}; + +procedures: + ItemCollected(EPass epass) : CItem::ItemCollected { + ASSERT(epass.penOther!=NULL); + + // if weapons stays + if (GetSP()->sp_bWeaponsStay && !(m_bPickupOnce||m_bRespawn)) { + // if already picked by this player + BOOL bWasPicked = MarkPickedBy(epass.penOther); + if (bWasPicked) { + // don't pick again + return; + } + } + + // send weapon to entity + EWeaponItem eWeapon; + eWeapon.iWeapon = m_EwitType; + eWeapon.iAmmo = -1; // use default ammo amount + eWeapon.bDropped = m_bDropped; + // if weapon is received + if (epass.penOther->ReceiveItem(eWeapon)) { + if(_pNetwork->IsPlayerLocal(epass.penOther)) {IFeel_PlayEffect("PU_Weapon");} + // play the pickup sound + m_soPick.Set3DParameters(50.0f, 1.0f, 1.0f, 1.0f); + PlaySound(m_soPick, SOUND_PICK, SOF_3D); + m_fPickSoundLen = GetSoundLength(SOUND_PICK); + if (!GetSP()->sp_bWeaponsStay || m_bDropped || (m_bPickupOnce||m_bRespawn)) { + jump CItem::ItemReceived(); + } + } + return; + }; + + Main() + { + if ( m_EwitType==WIT_GHOSTBUSTER) { + m_EwitType=WIT_LASER; + } + + Initialize(); // initialize base class + StartModelAnim(ITEMHOLDER_ANIM_BIGOSCILATION, AOF_LOOPING|AOF_NORESTART); + ForceCollisionBoxIndexChange(ITEMHOLDER_COLLISION_BOX_BIG); + SetProperties(); // set properties + + if (!m_bDropped) { + jump CItem::ItemLoop(); + } else if (TRUE) { + wait() { + on (EBegin) : { + SpawnReminder(this, m_fRespawnTime, 0); + call CItem::ItemLoop(); + } + on (EReminder) : { + SendEvent(EEnd()); + resume; + } + } + } + }; +}; diff --git a/Sources/EntitiesMP/WeaponItem.h b/Sources/EntitiesMP/WeaponItem.h new file mode 100644 index 0000000..9d644c0 --- /dev/null +++ b/Sources/EntitiesMP/WeaponItem.h @@ -0,0 +1,66 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_WeaponItem_INCLUDED +#define _EntitiesMP_WeaponItem_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType WeaponItemType_enum; +enum WeaponItemType { + WIT_COLT = 1, + WIT_SINGLESHOTGUN = 2, + WIT_DOUBLESHOTGUN = 3, + WIT_TOMMYGUN = 4, + WIT_MINIGUN = 5, + WIT_ROCKETLAUNCHER = 6, + WIT_GRENADELAUNCHER = 7, + WIT_SNIPER = 8, + WIT_FLAMER = 9, + WIT_LASER = 10, + WIT_CHAINSAW = 11, + WIT_CANNON = 12, + WIT_GHOSTBUSTER = 13, +}; +DECL_DLL inline void ClearToDefault(WeaponItemType &e) { e = (WeaponItemType)0; } ; +#define EVENTCODE_EWeaponItem 0x03220000 +class DECL_DLL EWeaponItem : public CEntityEvent { +public: +EWeaponItem(); +CEntityEvent *MakeCopy(void); +INDEX iWeapon; +INDEX iAmmo; +BOOL bDropped; +}; +DECL_DLL inline void ClearToDefault(EWeaponItem &e) { e = EWeaponItem(); } ; +extern "C" DECL_DLL CDLLEntityClass CWeaponItem_DLLClass; +class CWeaponItem : public CItem { +public: + DECL_DLL virtual void SetDefaultProperties(void); + enum WeaponItemType m_EwitType; + +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +void Precache(void); + +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +BOOL FillEntityStatistics(EntityStats * pes); + +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +void RenderParticles(void); + +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +void SetProperties(void); +#define STATE_CWeaponItem_ItemCollected 0x03220001 + BOOL +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +ItemCollected(const CEntityEvent &__eeInput); +#define STATE_CWeaponItem_Main 1 + BOOL +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x03220002_Main_01(const CEntityEvent &__eeInput); + BOOL H0x03220003_Main_02(const CEntityEvent &__eeInput); + BOOL H0x03220004_Main_03(const CEntityEvent &__eeInput); + BOOL H0x03220005_Main_04(const CEntityEvent &__eeInput); + BOOL H0x03220006_Main_05(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_WeaponItem_INCLUDED diff --git a/Sources/EntitiesMP/WeaponItem_tables.h b/Sources/EntitiesMP/WeaponItem_tables.h new file mode 100644 index 0000000..a3511ae --- /dev/null +++ b/Sources/EntitiesMP/WeaponItem_tables.h @@ -0,0 +1,218 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(WeaponItemType) + EP_ENUMVALUE(WIT_COLT, "Colt"), + EP_ENUMVALUE(WIT_SINGLESHOTGUN, "Single shotgun"), + EP_ENUMVALUE(WIT_DOUBLESHOTGUN, "Double shotgun"), + EP_ENUMVALUE(WIT_TOMMYGUN, "Tommygun"), + EP_ENUMVALUE(WIT_MINIGUN, "Minigun"), + EP_ENUMVALUE(WIT_ROCKETLAUNCHER, "Rocket launcher"), + EP_ENUMVALUE(WIT_GRENADELAUNCHER, "Grenade launcher"), + EP_ENUMVALUE(WIT_SNIPER, "Sniper"), + EP_ENUMVALUE(WIT_FLAMER, "Flamer"), + EP_ENUMVALUE(WIT_LASER, "Laser"), + EP_ENUMVALUE(WIT_CHAINSAW, "Chainsaw"), + EP_ENUMVALUE(WIT_CANNON, "Cannon"), + EP_ENUMVALUE(WIT_GHOSTBUSTER, "obsolete"), +EP_ENUMEND(WeaponItemType); + +#define ENTITYCLASS CWeaponItem + +CEntityProperty CWeaponItem_properties[] = { + CEntityProperty(CEntityProperty::EPT_ENUM, &WeaponItemType_enum, (0x00000322<<8)+1, offsetof(CWeaponItem, m_EwitType), "Type", 'Y', 0x7F0000FFUL, 0), +}; +#define CWeaponItem_propertiesct ARRAYCOUNT(CWeaponItem_properties) + +CEntityComponent CWeaponItem_components[] = { +#define CLASS_BASE ((0x00000322<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\Item.ecl"), +#define MODEL_COLT ((0x00000322<<8)+30) + CEntityComponent(ECT_MODEL, MODEL_COLT, "EFNM" "Models\\Weapons\\Colt\\ColtItem.mdl"), +#define MODEL_COLTCOCK ((0x00000322<<8)+31) + CEntityComponent(ECT_MODEL, MODEL_COLTCOCK, "EFNM" "Models\\Weapons\\Colt\\ColtCock.mdl"), +#define MODEL_COLTMAIN ((0x00000322<<8)+32) + CEntityComponent(ECT_MODEL, MODEL_COLTMAIN, "EFNM" "Models\\Weapons\\Colt\\ColtMain.mdl"), +#define MODEL_COLTBULLETS ((0x00000322<<8)+33) + CEntityComponent(ECT_MODEL, MODEL_COLTBULLETS, "EFNM" "Models\\Weapons\\Colt\\ColtBullets.mdl"), +#define TEXTURE_COLTMAIN ((0x00000322<<8)+34) + CEntityComponent(ECT_TEXTURE, TEXTURE_COLTMAIN, "EFNM" "Models\\Weapons\\Colt\\ColtMain.tex"), +#define TEXTURE_COLTCOCK ((0x00000322<<8)+35) + CEntityComponent(ECT_TEXTURE, TEXTURE_COLTCOCK, "EFNM" "Models\\Weapons\\Colt\\ColtCock.tex"), +#define TEXTURE_COLTBULLETS ((0x00000322<<8)+36) + CEntityComponent(ECT_TEXTURE, TEXTURE_COLTBULLETS, "EFNM" "Models\\Weapons\\Colt\\ColtBullets.tex"), +#define MODEL_SINGLESHOTGUN ((0x00000322<<8)+40) + CEntityComponent(ECT_MODEL, MODEL_SINGLESHOTGUN, "EFNM" "Models\\Weapons\\SingleShotgun\\SingleShotgunItem.mdl"), +#define MODEL_SS_SLIDER ((0x00000322<<8)+41) + CEntityComponent(ECT_MODEL, MODEL_SS_SLIDER, "EFNM" "Models\\Weapons\\SingleShotgun\\Slider.mdl"), +#define MODEL_SS_HANDLE ((0x00000322<<8)+42) + CEntityComponent(ECT_MODEL, MODEL_SS_HANDLE, "EFNM" "Models\\Weapons\\SingleShotgun\\Handle.mdl"), +#define MODEL_SS_BARRELS ((0x00000322<<8)+43) + CEntityComponent(ECT_MODEL, MODEL_SS_BARRELS, "EFNM" "Models\\Weapons\\SingleShotgun\\Barrels.mdl"), +#define TEXTURE_SS_HANDLE ((0x00000322<<8)+44) + CEntityComponent(ECT_TEXTURE, TEXTURE_SS_HANDLE, "EFNM" "Models\\Weapons\\SingleShotgun\\Handle.tex"), +#define TEXTURE_SS_BARRELS ((0x00000322<<8)+45) + CEntityComponent(ECT_TEXTURE, TEXTURE_SS_BARRELS, "EFNM" "Models\\Weapons\\SingleShotgun\\Barrels.tex"), +#define MODEL_DOUBLESHOTGUN ((0x00000322<<8)+50) + CEntityComponent(ECT_MODEL, MODEL_DOUBLESHOTGUN, "EFNM" "Models\\Weapons\\DoubleShotgun\\DoubleShotgunItem.mdl"), +#define MODEL_DS_HANDLE ((0x00000322<<8)+51) + CEntityComponent(ECT_MODEL, MODEL_DS_HANDLE, "EFNM" "Models\\Weapons\\DoubleShotgun\\Dshotgunhandle.mdl"), +#define MODEL_DS_BARRELS ((0x00000322<<8)+52) + CEntityComponent(ECT_MODEL, MODEL_DS_BARRELS, "EFNM" "Models\\Weapons\\DoubleShotgun\\Dshotgunbarrels.mdl"), +#define MODEL_DS_SWITCH ((0x00000322<<8)+54) + CEntityComponent(ECT_MODEL, MODEL_DS_SWITCH, "EFNM" "Models\\Weapons\\DoubleShotgun\\Switch.mdl"), +#define TEXTURE_DS_HANDLE ((0x00000322<<8)+56) + CEntityComponent(ECT_TEXTURE, TEXTURE_DS_HANDLE, "EFNM" "Models\\Weapons\\DoubleShotgun\\Handle.tex"), +#define TEXTURE_DS_BARRELS ((0x00000322<<8)+57) + CEntityComponent(ECT_TEXTURE, TEXTURE_DS_BARRELS, "EFNM" "Models\\Weapons\\DoubleShotgun\\Barrels.tex"), +#define TEXTURE_DS_SWITCH ((0x00000322<<8)+58) + CEntityComponent(ECT_TEXTURE, TEXTURE_DS_SWITCH, "EFNM" "Models\\Weapons\\DoubleShotgun\\Switch.tex"), +#define MODEL_TOMMYGUN ((0x00000322<<8)+70) + CEntityComponent(ECT_MODEL, MODEL_TOMMYGUN, "EFNM" "Models\\Weapons\\TommyGun\\TommyGunItem.mdl"), +#define MODEL_TG_BODY ((0x00000322<<8)+71) + CEntityComponent(ECT_MODEL, MODEL_TG_BODY, "EFNM" "Models\\Weapons\\TommyGun\\Body.mdl"), +#define MODEL_TG_SLIDER ((0x00000322<<8)+72) + CEntityComponent(ECT_MODEL, MODEL_TG_SLIDER, "EFNM" "Models\\Weapons\\TommyGun\\Slider.mdl"), +#define TEXTURE_TG_BODY ((0x00000322<<8)+73) + CEntityComponent(ECT_TEXTURE, TEXTURE_TG_BODY, "EFNM" "Models\\Weapons\\TommyGun\\Body.tex"), +#define MODEL_MINIGUN ((0x00000322<<8)+80) + CEntityComponent(ECT_MODEL, MODEL_MINIGUN, "EFNM" "Models\\Weapons\\MiniGun\\MiniGunItem.mdl"), +#define MODEL_MG_BARRELS ((0x00000322<<8)+81) + CEntityComponent(ECT_MODEL, MODEL_MG_BARRELS, "EFNM" "Models\\Weapons\\MiniGun\\Barrels.mdl"), +#define MODEL_MG_BODY ((0x00000322<<8)+82) + CEntityComponent(ECT_MODEL, MODEL_MG_BODY, "EFNM" "Models\\Weapons\\MiniGun\\Body.mdl"), +#define MODEL_MG_ENGINE ((0x00000322<<8)+83) + CEntityComponent(ECT_MODEL, MODEL_MG_ENGINE, "EFNM" "Models\\Weapons\\MiniGun\\Engine.mdl"), +#define TEXTURE_MG_BODY ((0x00000322<<8)+84) + CEntityComponent(ECT_TEXTURE, TEXTURE_MG_BODY, "EFNM" "Models\\Weapons\\MiniGun\\Body.tex"), +#define TEXTURE_MG_BARRELS ((0x00000322<<8)+99) + CEntityComponent(ECT_TEXTURE, TEXTURE_MG_BARRELS, "EFNM" "Models\\Weapons\\MiniGun\\Barrels.tex"), +#define MODEL_ROCKETLAUNCHER ((0x00000322<<8)+90) + CEntityComponent(ECT_MODEL, MODEL_ROCKETLAUNCHER, "EFNM" "Models\\Weapons\\RocketLauncher\\RocketLauncherItem.mdl"), +#define MODEL_RL_BODY ((0x00000322<<8)+91) + CEntityComponent(ECT_MODEL, MODEL_RL_BODY, "EFNM" "Models\\Weapons\\RocketLauncher\\Body.mdl"), +#define TEXTURE_RL_BODY ((0x00000322<<8)+92) + CEntityComponent(ECT_TEXTURE, TEXTURE_RL_BODY, "EFNM" "Models\\Weapons\\RocketLauncher\\Body.tex"), +#define MODEL_RL_ROTATINGPART ((0x00000322<<8)+93) + CEntityComponent(ECT_MODEL, MODEL_RL_ROTATINGPART, "EFNM" "Models\\Weapons\\RocketLauncher\\RotatingPart.mdl"), +#define TEXTURE_RL_ROTATINGPART ((0x00000322<<8)+94) + CEntityComponent(ECT_TEXTURE, TEXTURE_RL_ROTATINGPART, "EFNM" "Models\\Weapons\\RocketLauncher\\RotatingPart.tex"), +#define MODEL_RL_ROCKET ((0x00000322<<8)+95) + CEntityComponent(ECT_MODEL, MODEL_RL_ROCKET, "EFNM" "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl"), +#define TEXTURE_RL_ROCKET ((0x00000322<<8)+96) + CEntityComponent(ECT_TEXTURE, TEXTURE_RL_ROCKET, "EFNM" "Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex"), +#define MODEL_GRENADELAUNCHER ((0x00000322<<8)+100) + CEntityComponent(ECT_MODEL, MODEL_GRENADELAUNCHER, "EFNM" "Models\\Weapons\\GrenadeLauncher\\GrenadeLauncherItem.mdl"), +#define MODEL_GL_BODY ((0x00000322<<8)+101) + CEntityComponent(ECT_MODEL, MODEL_GL_BODY, "EFNM" "Models\\Weapons\\GrenadeLauncher\\Body.mdl"), +#define MODEL_GL_MOVINGPART ((0x00000322<<8)+102) + CEntityComponent(ECT_MODEL, MODEL_GL_MOVINGPART, "EFNM" "Models\\Weapons\\GrenadeLauncher\\MovingPipe.mdl"), +#define MODEL_GL_GRENADE ((0x00000322<<8)+103) + CEntityComponent(ECT_MODEL, MODEL_GL_GRENADE, "EFNM" "Models\\Weapons\\GrenadeLauncher\\GrenadeBack.mdl"), +#define TEXTURE_GL_BODY ((0x00000322<<8)+104) + CEntityComponent(ECT_TEXTURE, TEXTURE_GL_BODY, "EFNM" "Models\\Weapons\\GrenadeLauncher\\Body.tex"), +#define TEXTURE_GL_MOVINGPART ((0x00000322<<8)+105) + CEntityComponent(ECT_TEXTURE, TEXTURE_GL_MOVINGPART, "EFNM" "Models\\Weapons\\GrenadeLauncher\\MovingPipe.tex"), +#define MODEL_SNIPER ((0x00000322<<8)+110) + CEntityComponent(ECT_MODEL, MODEL_SNIPER, "EFNM" "ModelsMP\\Weapons\\Sniper\\Sniper.mdl"), +#define MODEL_SNIPER_BODY ((0x00000322<<8)+111) + CEntityComponent(ECT_MODEL, MODEL_SNIPER_BODY, "EFNM" "ModelsMP\\Weapons\\Sniper\\Body.mdl"), +#define TEXTURE_SNIPER_BODY ((0x00000322<<8)+112) + CEntityComponent(ECT_TEXTURE, TEXTURE_SNIPER_BODY, "EFNM" "ModelsMP\\Weapons\\Sniper\\Body.tex"), +#define MODEL_FLAMER ((0x00000322<<8)+130) + CEntityComponent(ECT_MODEL, MODEL_FLAMER, "EFNM" "ModelsMP\\Weapons\\Flamer\\FlamerItem.mdl"), +#define MODEL_FL_BODY ((0x00000322<<8)+131) + CEntityComponent(ECT_MODEL, MODEL_FL_BODY, "EFNM" "ModelsMP\\Weapons\\Flamer\\Body.mdl"), +#define MODEL_FL_RESERVOIR ((0x00000322<<8)+132) + CEntityComponent(ECT_MODEL, MODEL_FL_RESERVOIR, "EFNM" "ModelsMP\\Weapons\\Flamer\\FuelReservoir.mdl"), +#define MODEL_FL_FLAME ((0x00000322<<8)+133) + CEntityComponent(ECT_MODEL, MODEL_FL_FLAME, "EFNM" "ModelsMP\\Weapons\\Flamer\\Flame.mdl"), +#define TEXTURE_FL_BODY ((0x00000322<<8)+134) + CEntityComponent(ECT_TEXTURE, TEXTURE_FL_BODY, "EFNM" "ModelsMP\\Weapons\\Flamer\\Body.tex"), +#define TEXTURE_FL_FLAME ((0x00000322<<8)+135) + CEntityComponent(ECT_TEXTURE, TEXTURE_FL_FLAME, "EFNM" "ModelsMP\\Effects\\Flame\\Flame.tex"), +#define TEXTURE_FL_FUELRESERVOIR ((0x00000322<<8)+136) + CEntityComponent(ECT_TEXTURE, TEXTURE_FL_FUELRESERVOIR, "EFNM" "ModelsMP\\Weapons\\Flamer\\FuelReservoir.tex"), +#define MODEL_LASER ((0x00000322<<8)+140) + CEntityComponent(ECT_MODEL, MODEL_LASER, "EFNM" "Models\\Weapons\\Laser\\LaserItem.mdl"), +#define MODEL_LS_BODY ((0x00000322<<8)+141) + CEntityComponent(ECT_MODEL, MODEL_LS_BODY, "EFNM" "Models\\Weapons\\Laser\\Body.mdl"), +#define MODEL_LS_BARREL ((0x00000322<<8)+142) + CEntityComponent(ECT_MODEL, MODEL_LS_BARREL, "EFNM" "Models\\Weapons\\Laser\\Barrel.mdl"), +#define TEXTURE_LS_BODY ((0x00000322<<8)+143) + CEntityComponent(ECT_TEXTURE, TEXTURE_LS_BODY, "EFNM" "Models\\Weapons\\Laser\\Body.tex"), +#define TEXTURE_LS_BARREL ((0x00000322<<8)+144) + CEntityComponent(ECT_TEXTURE, TEXTURE_LS_BARREL, "EFNM" "Models\\Weapons\\Laser\\Barrel.tex"), +#define MODEL_CHAINSAW ((0x00000322<<8)+150) + CEntityComponent(ECT_MODEL, MODEL_CHAINSAW, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\ChainsawItem.mdl"), +#define MODEL_CS_BODY ((0x00000322<<8)+151) + CEntityComponent(ECT_MODEL, MODEL_CS_BODY, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Body.mdl"), +#define MODEL_CS_BLADE ((0x00000322<<8)+152) + CEntityComponent(ECT_MODEL, MODEL_CS_BLADE, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Blade.mdl"), +#define MODEL_CS_TEETH ((0x00000322<<8)+153) + CEntityComponent(ECT_MODEL, MODEL_CS_TEETH, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Teeth.mdl"), +#define TEXTURE_CS_BODY ((0x00000322<<8)+154) + CEntityComponent(ECT_TEXTURE, TEXTURE_CS_BODY, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Body.tex"), +#define TEXTURE_CS_BLADE ((0x00000322<<8)+155) + CEntityComponent(ECT_TEXTURE, TEXTURE_CS_BLADE, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Blade.tex"), +#define TEXTURE_CS_TEETH ((0x00000322<<8)+156) + CEntityComponent(ECT_TEXTURE, TEXTURE_CS_TEETH, "EFNM" "ModelsMP\\Weapons\\Chainsaw\\Teeth.tex"), +#define MODEL_CANNON ((0x00000322<<8)+170) + CEntityComponent(ECT_MODEL, MODEL_CANNON, "EFNM" "Models\\Weapons\\Cannon\\Cannon.mdl"), +#define MODEL_CN_BODY ((0x00000322<<8)+171) + CEntityComponent(ECT_MODEL, MODEL_CN_BODY, "EFNM" "Models\\Weapons\\Cannon\\Body.mdl"), +#define TEXTURE_CANNON ((0x00000322<<8)+173) + CEntityComponent(ECT_TEXTURE, TEXTURE_CANNON, "EFNM" "Models\\Weapons\\Cannon\\Body.tex"), +#define TEXTURE_FLARE ((0x00000322<<8)+190) + CEntityComponent(ECT_TEXTURE, TEXTURE_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.tex"), +#define MODEL_FLARE ((0x00000322<<8)+191) + CEntityComponent(ECT_MODEL, MODEL_FLARE, "EFNM" "Models\\Items\\Flares\\Flare.mdl"), +#define TEX_REFL_BWRIPLES01 ((0x00000322<<8)+200) + CEntityComponent(ECT_TEXTURE, TEX_REFL_BWRIPLES01, "EFNM" "Models\\ReflectionTextures\\BWRiples01.tex"), +#define TEX_REFL_BWRIPLES02 ((0x00000322<<8)+201) + CEntityComponent(ECT_TEXTURE, TEX_REFL_BWRIPLES02, "EFNM" "Models\\ReflectionTextures\\BWRiples02.tex"), +#define TEX_REFL_LIGHTMETAL01 ((0x00000322<<8)+202) + CEntityComponent(ECT_TEXTURE, TEX_REFL_LIGHTMETAL01, "EFNM" "Models\\ReflectionTextures\\LightMetal01.tex"), +#define TEX_REFL_LIGHTBLUEMETAL01 ((0x00000322<<8)+203) + CEntityComponent(ECT_TEXTURE, TEX_REFL_LIGHTBLUEMETAL01, "EFNM" "Models\\ReflectionTextures\\LightBlueMetal01.tex"), +#define TEX_REFL_DARKMETAL ((0x00000322<<8)+204) + CEntityComponent(ECT_TEXTURE, TEX_REFL_DARKMETAL, "EFNM" "Models\\ReflectionTextures\\DarkMetal.tex"), +#define TEX_REFL_PURPLE01 ((0x00000322<<8)+205) + CEntityComponent(ECT_TEXTURE, TEX_REFL_PURPLE01, "EFNM" "Models\\ReflectionTextures\\Purple01.tex"), +#define TEX_SPEC_WEAK ((0x00000322<<8)+210) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_WEAK, "EFNM" "Models\\SpecularTextures\\Weak.tex"), +#define TEX_SPEC_MEDIUM ((0x00000322<<8)+211) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_MEDIUM, "EFNM" "Models\\SpecularTextures\\Medium.tex"), +#define TEX_SPEC_STRONG ((0x00000322<<8)+212) + CEntityComponent(ECT_TEXTURE, TEX_SPEC_STRONG, "EFNM" "Models\\SpecularTextures\\Strong.tex"), +#define SOUND_PICK ((0x00000322<<8)+213) + CEntityComponent(ECT_SOUND, SOUND_PICK, "EFNM" "Sounds\\Items\\Weapon.wav"), +}; +#define CWeaponItem_componentsct ARRAYCOUNT(CWeaponItem_components) + +CEventHandlerEntry CWeaponItem_handlers[] = { + {0x03220001, STATE_CItem_ItemCollected, CEntity::pEventHandler(&CWeaponItem:: +#line 389 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +ItemCollected),DEBUGSTRING("CWeaponItem::ItemCollected")}, + {1, -1, CEntity::pEventHandler(&CWeaponItem:: +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/WeaponItem.es" +Main),DEBUGSTRING("CWeaponItem::Main")}, + {0x03220002, -1, CEntity::pEventHandler(&CWeaponItem::H0x03220002_Main_01), DEBUGSTRING("CWeaponItem::H0x03220002_Main_01")}, + {0x03220003, -1, CEntity::pEventHandler(&CWeaponItem::H0x03220003_Main_02), DEBUGSTRING("CWeaponItem::H0x03220003_Main_02")}, + {0x03220004, -1, CEntity::pEventHandler(&CWeaponItem::H0x03220004_Main_03), DEBUGSTRING("CWeaponItem::H0x03220004_Main_03")}, + {0x03220005, -1, CEntity::pEventHandler(&CWeaponItem::H0x03220005_Main_04), DEBUGSTRING("CWeaponItem::H0x03220005_Main_04")}, + {0x03220006, -1, CEntity::pEventHandler(&CWeaponItem::H0x03220006_Main_05), DEBUGSTRING("CWeaponItem::H0x03220006_Main_05")}, +}; +#define CWeaponItem_handlersct ARRAYCOUNT(CWeaponItem_handlers) + +CEntity *CWeaponItem_New(void) { return new CWeaponItem; }; +void CWeaponItem_OnInitClass(void) {}; +void CWeaponItem_OnEndClass(void) {}; +void CWeaponItem_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CWeaponItem_OnWorldEnd(CWorld *pwo) {}; +void CWeaponItem_OnWorldInit(CWorld *pwo) {}; +void CWeaponItem_OnWorldTick(CWorld *pwo) {}; +void CWeaponItem_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CWeaponItem, CItem, "Weapon Item", "Thumbnails\\WeaponItem.tbn", 0x00000322); +DECLARE_CTFILENAME(_fnmCWeaponItem_tbn, "Thumbnails\\WeaponItem.tbn"); diff --git a/Sources/EntitiesMP/Werebull.cpp b/Sources/EntitiesMP/Werebull.cpp new file mode 100644 index 0000000..7081ca2 --- /dev/null +++ b/Sources/EntitiesMP/Werebull.cpp @@ -0,0 +1,496 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" + +#include "StdH.h" +#include "Models/Enemies/Werebull/Werebull.h" + +#include +#include +#line 17 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" + +// info structure +static EntityInfo eiWerebull = { + EIBT_FLESH, 500.0f, + 0.0f, 3.0f, 0.0f, // source (eyes) + 0.0f, 1.5f, 0.0f, // target (body) +}; + +#define HIT_DISTANCE 5.0f + +void CWerebull::SetDefaultProperties(void) { + m_bRunAttack = FALSE ; + m_bHornHit = FALSE ; + m_penLastTouched = NULL; + m_soFeet.SetOwner(this); +m_soFeet.Stop_internal(); + m_bRunSoundPlaying = FALSE ; + CEnemyRunInto::SetDefaultProperties(); +} + CTString CWerebull::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +{ +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +CTString str ; +#line 60 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +str . PrintF (TRANS ("Sirian werebull sent %s flying") , strPlayerName ); +#line 61 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +return str ; +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::Precache(void) { +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +CEnemyBase :: Precache (); +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PrecacheSound (SOUND_IDLE ); +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PrecacheSound (SOUND_SIGHT ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PrecacheSound (SOUND_KICKHORN ); +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PrecacheSound (SOUND_IMPACT ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PrecacheSound (SOUND_DEATH ); +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PrecacheSound (SOUND_RUN ); +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void * CWerebull::GetEntityInfo(void) { +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +return & eiWerebull ; +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT CWerebull::GetCrushHealth(void) +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +{ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +return 60.0f; +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + const CTFileName & CWerebull::GetComputerMessageName(void)const { +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +static DECLARE_CTFILENAME (fnm , "Data\\Messages\\Enemies\\Bull.txt"); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +return fnm ; +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::RenderParticles(void) +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +{ +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +Particles_RunningDust (this ); +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +CEnemyBase :: RenderParticles (); +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +{ +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(! IsOfClass (penInflictor , "Werebull")){ +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +CEnemyBase :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::AdjustDifficulty(void) +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +{ +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +INDEX CWerebull::AnimForDeath(void) { +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +INDEX iAnim ; +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(en_vCurrentTranslationAbsolute . Length () > 5.0f){ +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +iAnim = WEREBULL_ANIM_DEATHRUN ; +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +}else { +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +iAnim = WEREBULL_ANIM_DEATH ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +StartModelAnim (iAnim , 0); +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +DeactivateRunningSound (); +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +return iAnim ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT CWerebull::WaitForDust(FLOAT3D & vStretch) { +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(GetModelObject () -> GetAnim () == WEREBULL_ANIM_DEATHRUN ) +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +{ +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +vStretch = FLOAT3D (1 , 1 , 2) * 2.0f; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +return 0.6f; +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +else if(GetModelObject () -> GetAnim () == WEREBULL_ANIM_DEATH ) +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +{ +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +vStretch = FLOAT3D (1 , 1 , 2) * 2.0f; +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +return 0.7f; +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +return - 1.0f; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::DeathNotify() { +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +ChangeCollisionBoxIndexWhenPossible (WEREBULL_COLLISION_BOX_DEATH ); +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +SetCollisionFlags (ECF_MODEL ); +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::StandingAnim(void) { +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +StartModelAnim (WEREBULL_ANIM_IDLE , AOF_LOOPING | AOF_NORESTART ); +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +DeactivateRunningSound (); +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::WalkingAnim(void) { +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +StartModelAnim (WEREBULL_ANIM_WALK , AOF_LOOPING | AOF_NORESTART ); +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +DeactivateRunningSound (); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::RunningAnim(void) { +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +StartModelAnim (WEREBULL_ANIM_RUN , AOF_LOOPING | AOF_NORESTART ); +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +ActivateRunningSound (); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::RotatingAnim(void) { +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +StartModelAnim (WEREBULL_ANIM_RUN , AOF_LOOPING | AOF_NORESTART ); +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +ActivateRunningSound (); +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::IdleSound(void) { +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::SightSound(void) { +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::WoundSound(void) { +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::DeathSound(void) { +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::ActivateRunningSound(void) +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +{ +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(! m_bRunSoundPlaying ){ +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PlaySound (m_soFeet , SOUND_RUN , SOF_3D | SOF_LOOP ); +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_bRunSoundPlaying = TRUE ; +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::DeactivateRunningSound(void) +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +{ +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_soFeet . Stop (); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_bRunSoundPlaying = FALSE ; +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::LiveEntityTouched(ETouch etouch) { +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(m_penLastTouched != etouch . penOther || _pTimer -> CurrentTick () >= m_fLastTouchedTime + 0.25f){ +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT3D vDirection = en_vCurrentTranslationAbsolute ; +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +vDirection . Normalize (); +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +ANGLE aHitAngle = FLOAT3D (etouch . plCollision ) % vDirection ; +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(aHitAngle < 0.0f){ +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(! IsOfSameClass (this , etouch . penOther )){ +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +IncreaseKickedMass (etouch . penOther ); +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PlaySound (m_soSound , SOUND_IMPACT , SOF_3D ); +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_penLastTouched = etouch . penOther ; +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fLastTouchedTime = _pTimer -> CurrentTick (); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +vDirection . Normalize (); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +InflictDirectDamage (etouch . penOther , this , DMT_CLOSERANGE , - aHitAngle * 40.0f , +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT3D (0 , 0 , 0) , vDirection ); +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT3D vSpeed = - FLOAT3D (etouch . plCollision ); +#line 218 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +vSpeed = vSpeed * 10.0f; +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +const FLOATmatrix3D & m = GetRotationMatrix (); +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT3D vSpeedRel = vSpeed * ! m ; +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(vSpeedRel (1) < - 0.1f){ +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +vSpeedRel (1) -= 15.0f; +#line 223 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +}else { +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +vSpeedRel (1) += 15.0f; +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +vSpeedRel (2) = 15.0f; +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +vSpeed = vSpeedRel * m ; +#line 229 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +KickEntity (etouch . penOther , vSpeed ); +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +BOOL CWerebull::HigherMass(void) { +#line 236 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +return (m_fMassKicked > 500.0f); +#line 237 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} + +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void CWerebull::EnemyPostInit(void) +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +{ +#line 243 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_soFeet . Set3DParameters (500.0f , 50.0f , 1.0f , 1.0f); +#line 244 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_bRunSoundPlaying = FALSE ; +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_soSound . Set3DParameters (160.0f , 50.0f , 1.0f , 1.0f); +#line 246 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} +BOOL CWerebull:: +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +Hit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWerebull_Hit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWerebull::Hit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 254 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(!(CalcDist (m_penEnemy ) < HIT_DISTANCE )){ Jump(STATE_CURRENT,0x01330007, FALSE, EInternal());return TRUE;} +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +StartModelAnim (WEREBULL_ANIM_ATTACKHORNS , 0); +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +DeactivateRunningSound (); +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_bHornHit = FALSE ; +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +SetTimerAfter(0.4f); +Jump(STATE_CURRENT, 0x01330001, FALSE, EBegin());return TRUE;}BOOL CWerebull::H0x01330001_Hit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01330001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01330002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWerebull::H0x01330002_Hit_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01330002 +; +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +PlaySound (m_soSound , SOUND_KICKHORN , SOF_3D ); +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(CalcDist (m_penEnemy ) < HIT_DISTANCE ){m_bHornHit = TRUE ;} +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x01330003, FALSE, EBegin());return TRUE;}BOOL CWerebull::H0x01330003_Hit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01330003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01330004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWerebull::H0x01330004_Hit_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01330004 +; +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(CalcDist (m_penEnemy ) < HIT_DISTANCE ){m_bHornHit = TRUE ;} +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +SetTimerAfter(0.1f); +Jump(STATE_CURRENT, 0x01330005, FALSE, EBegin());return TRUE;}BOOL CWerebull::H0x01330005_Hit_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01330005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01330006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWerebull::H0x01330006_Hit_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01330006 +; +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(CalcDist (m_penEnemy ) < HIT_DISTANCE ){m_bHornHit = TRUE ;} +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(m_bHornHit ){ +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT3D vDirection = m_penEnemy -> GetPlacement () . pl_PositionVector - GetPlacement () . pl_PositionVector ; +#line 268 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +vDirection . Normalize (); +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +InflictDirectDamage (m_penEnemy , this , DMT_CLOSERANGE , 20.0f , FLOAT3D (0 , 0 , 0) , vDirection ); +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT3D vSpeed ; +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +GetPitchDirection (AngleDeg (90.0f) , vSpeed ); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +vSpeed = vSpeed * 10.0f; +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +KickEntity (m_penEnemy , vSpeed ); +#line 274 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +}Jump(STATE_CURRENT,0x01330007, FALSE, EInternal());return TRUE;}BOOL CWerebull::H0x01330007_Hit_07(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01330007 + +#line 278 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fShootTime = _pTimer -> CurrentTick () + 0.5f; +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +Return(STATE_CURRENT,EReturn ()); +#line 279 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWerebull:: +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWerebull_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWerebull::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +InitAsModel (); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +SetPhysicsFlags (EPF_MODEL_WALKING ); +#line 291 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +SetCollisionFlags (ECF_MODEL ); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 293 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +SetHealth (250.0f); +#line 294 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fMaxHealth = 250.0f; +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +en_fDensity = 2000.0f; +#line 298 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +SetModel (MODEL_WEREBULL ); +#line 300 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +SetModelMainTexture (TEXTURE_WEREBULL_SUMMER ); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +StandingAnim (); +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fWalkSpeed = FRnd () + 2.5f; +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_aWalkRotateSpeed = AngleDeg (FRnd () * 25.0f + 45.0f); +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fAttackRunSpeed = FRnd () * 5.0f + 22.5f; +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fAttackRotateRunInto = AngleDeg (FRnd () * 60 + 100.0f); +#line 310 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_aAttackRotateSpeed = m_fAttackRotateRunInto ; +#line 311 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fCloseRunSpeed = FRnd () * 5.0f + 15.0f; +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_aCloseRotateSpeed = AngleDeg (FRnd () * 50 + 500.0f); +#line 314 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fAttackDistance = 100.0f; +#line 315 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fCloseDistance = 7.0f; +#line 316 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fStopDistance = 0.0f; +#line 317 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fAttackFireTime = 0.05f; +#line 318 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fCloseFireTime = 1.0f; +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fIgnoreRange = 250.0f; +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fBlowUpAmount = 1E10f; +#line 322 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fBodyParts = 12; +#line 323 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fDamageWounded = 100000.0f; +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_iScore = 2000; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +if(m_fStepHeight == - 1){ +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +m_fStepHeight = 4.0f; +#line 327 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +} +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +Particles_RunningDust_Prepare (this ); +#line 332 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +Jump(STATE_CURRENT, STATE_CEnemyRunInto_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Werebull.es b/Sources/EntitiesMP/Werebull.es new file mode 100644 index 0000000..ad764cf --- /dev/null +++ b/Sources/EntitiesMP/Werebull.es @@ -0,0 +1,334 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +307 +%{ +#include "StdH.h" +#include "Models/Enemies/Werebull/Werebull.h" +%} + +uses "EntitiesMP/EnemyBase"; +uses "EntitiesMP/EnemyRunInto"; + +enum BullChar { + 0 BUC_SUMMER "Summer", + 1 BUC_WINTER "Winter", +}; + +%{ +// info structure +static EntityInfo eiWerebull = { + EIBT_FLESH, 500.0f, + 0.0f, 3.0f, 0.0f, // source (eyes) + 0.0f, 1.5f, 0.0f, // target (body) +}; + +#define HIT_DISTANCE 5.0f +%} + + +class CWerebull : CEnemyRunInto { +name "Werebull"; +thumbnail "Thumbnails\\Werebull.tbn"; + +properties: + 1 BOOL m_bRunAttack = FALSE, // run attack (attack local) + 2 BOOL m_bHornHit = FALSE, // close attack local + 3 CEntityPointer m_penLastTouched, // last touched + 4 CSoundObject m_soFeet, // for running sound + 5 BOOL m_bRunSoundPlaying = FALSE, +// 6 enum BullChar m_bcChar "Character" 'C' = BUC_SUMMER, // character + +components: + 0 class CLASS_BASE "Classes\\EnemyRunInto.ecl", + 1 model MODEL_WEREBULL "Models\\Enemies\\Werebull\\Werebull.mdl", + 2 texture TEXTURE_WEREBULL_SUMMER "Models\\Enemies\\Werebull\\Werebull.tex", +// 3 texture TEXTURE_WEREBULL_WINTER "Models\\Enemies\\Werebull\\Werebull2.tex", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "Models\\Enemies\\Werebull\\Sounds\\Idle.wav", + 51 sound SOUND_SIGHT "Models\\Enemies\\Werebull\\Sounds\\Sight.wav", + 53 sound SOUND_KICKHORN "Models\\Enemies\\Werebull\\Sounds\\KickHorn.wav", + 54 sound SOUND_IMPACT "Models\\Enemies\\Werebull\\Sounds\\Impact.wav", + 55 sound SOUND_DEATH "Models\\Enemies\\Werebull\\Sounds\\Death.wav", + 56 sound SOUND_RUN "Models\\Enemies\\Werebull\\Sounds\\Run.wav", + +functions: + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + str.PrintF(TRANS("Sirian werebull sent %s flying"), strPlayerName); + return str; + } + + void Precache(void) { + CEnemyBase::Precache(); + PrecacheSound(SOUND_IDLE ); + PrecacheSound(SOUND_SIGHT ); + PrecacheSound(SOUND_KICKHORN); + PrecacheSound(SOUND_IMPACT ); + PrecacheSound(SOUND_DEATH ); + PrecacheSound(SOUND_RUN ); + }; + + /* Entity info */ + void *GetEntityInfo(void) { + return &eiWerebull; + }; + + FLOAT GetCrushHealth(void) + { + return 60.0f; + } + + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnm, "Data\\Messages\\Enemies\\Bull.txt"); + return fnm; + }; + + // render particles + void RenderParticles(void) + { + Particles_RunningDust(this); + CEnemyBase::RenderParticles(); + } + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // werebull can't harm werebull + if (!IsOfClass(penInflictor, "Werebull")) { + CEnemyBase::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + }; + + void AdjustDifficulty(void) + { + // bull must not change its speed at different difficulties + } + + // death + INDEX AnimForDeath(void) { + INDEX iAnim; + if (en_vCurrentTranslationAbsolute.Length()>5.0f) { + iAnim = WEREBULL_ANIM_DEATHRUN; + } else { + iAnim = WEREBULL_ANIM_DEATH; + } + StartModelAnim(iAnim, 0); + DeactivateRunningSound(); + return iAnim; + }; + + FLOAT WaitForDust(FLOAT3D &vStretch) { + if(GetModelObject()->GetAnim()==WEREBULL_ANIM_DEATHRUN) + { + vStretch=FLOAT3D(1,1,2)*2.0f; + return 0.6f; + } + else if(GetModelObject()->GetAnim()==WEREBULL_ANIM_DEATH) + { + vStretch=FLOAT3D(1,1,2)*2.0f; + return 0.7f; + } + return -1.0f; + }; + + void DeathNotify() { + ChangeCollisionBoxIndexWhenPossible(WEREBULL_COLLISION_BOX_DEATH); + SetCollisionFlags(ECF_MODEL); + }; + + // virtual anim functions + void StandingAnim(void) { + StartModelAnim(WEREBULL_ANIM_IDLE, AOF_LOOPING|AOF_NORESTART); + DeactivateRunningSound(); + }; + void WalkingAnim(void) { + StartModelAnim(WEREBULL_ANIM_WALK, AOF_LOOPING|AOF_NORESTART); + DeactivateRunningSound(); + }; + void RunningAnim(void) { + StartModelAnim(WEREBULL_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); + ActivateRunningSound(); + }; + void RotatingAnim(void) { + StartModelAnim(WEREBULL_ANIM_RUN, AOF_LOOPING|AOF_NORESTART); + //DeactivateRunningSound(); + ActivateRunningSound(); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + + // running sounds + void ActivateRunningSound(void) + { + if (!m_bRunSoundPlaying) { + PlaySound(m_soFeet, SOUND_RUN, SOF_3D|SOF_LOOP); + m_bRunSoundPlaying = TRUE; + } + } + void DeactivateRunningSound(void) + { + m_soFeet.Stop(); + m_bRunSoundPlaying = FALSE; + } + + +/************************************************************ + * ATTACK FUNCTIONS * + ************************************************************/ + // touched another live entity + void LiveEntityTouched(ETouch etouch) { + if (m_penLastTouched!=etouch.penOther || _pTimer->CurrentTick()>=m_fLastTouchedTime+0.25f) { + // hit angle + FLOAT3D vDirection = en_vCurrentTranslationAbsolute; + vDirection.Normalize(); + ANGLE aHitAngle = FLOAT3D(etouch.plCollision)%vDirection; + // only hit target in front of you + if (aHitAngle < 0.0f) { + // increase mass - only if not another bull + if (!IsOfSameClass(this, etouch.penOther)) { + IncreaseKickedMass(etouch.penOther); + } + PlaySound(m_soSound, SOUND_IMPACT, SOF_3D); + // store last touched + m_penLastTouched = etouch.penOther; + m_fLastTouchedTime = _pTimer->CurrentTick(); + // damage + FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.Normalize(); + InflictDirectDamage(etouch.penOther, this, DMT_CLOSERANGE, -aHitAngle*40.0f, + FLOAT3D(0, 0, 0), vDirection); + // kick touched entity + FLOAT3D vSpeed = -FLOAT3D(etouch.plCollision); + vSpeed = vSpeed*10.0f; + const FLOATmatrix3D &m = GetRotationMatrix(); + FLOAT3D vSpeedRel = vSpeed*!m; + if (vSpeedRel(1)<-0.1f) { + vSpeedRel(1)-=15.0f; + } else { + vSpeedRel(1)+=15.0f; + } + vSpeedRel(2)=15.0f; + + vSpeed = vSpeedRel*m; + KickEntity(etouch.penOther, vSpeed); + } + } + }; + + // touched entity with higher mass + BOOL HigherMass(void) { + return (m_fMassKicked > 500.0f); + }; + + // adjust sound and watcher parameters here if needed + void EnemyPostInit(void) + { + // set sound default parameters + m_soFeet.Set3DParameters(500.0f, 50.0f, 1.0f, 1.0f); + m_bRunSoundPlaying = FALSE; + m_soSound.Set3DParameters(160.0f, 50.0f, 1.0f, 1.0f); + }; + +procedures: +/************************************************************ + * A T T A C K E N E M Y * + ************************************************************/ + // hit enemy + Hit(EVoid) : CEnemyBase::Hit { + if (CalcDist(m_penEnemy) < HIT_DISTANCE) { + // attack with horns + StartModelAnim(WEREBULL_ANIM_ATTACKHORNS, 0); + DeactivateRunningSound(); + m_bHornHit = FALSE; + autowait(0.4f); + PlaySound(m_soSound, SOUND_KICKHORN, SOF_3D); + if (CalcDist(m_penEnemy) < HIT_DISTANCE) { m_bHornHit = TRUE; } + autowait(0.1f); + if (CalcDist(m_penEnemy) < HIT_DISTANCE) { m_bHornHit = TRUE; } + autowait(0.1f); + if (CalcDist(m_penEnemy) < HIT_DISTANCE) { m_bHornHit = TRUE; } + if (m_bHornHit) { + FLOAT3D vDirection = m_penEnemy->GetPlacement().pl_PositionVector-GetPlacement().pl_PositionVector; + vDirection.Normalize(); + InflictDirectDamage(m_penEnemy, this, DMT_CLOSERANGE, 20.0f, FLOAT3D(0, 0, 0), vDirection); + FLOAT3D vSpeed; + GetPitchDirection(AngleDeg(90.0f), vSpeed); + vSpeed = vSpeed * 10.0f; + KickEntity(m_penEnemy, vSpeed); + } + } + + // run to enemy + m_fShootTime = _pTimer->CurrentTick() + 0.5f; + return EReturn(); + }; + + + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + SetHealth(250.0f); + m_fMaxHealth = 250.0f; + en_fDensity = 2000.0f; + + // set your appearance + SetModel(MODEL_WEREBULL); +// if (m_bcChar==BUC_SUMMER) { + SetModelMainTexture(TEXTURE_WEREBULL_SUMMER); +// } else { +// SetModelMainTexture(TEXTURE_WEREBULL_WINTER); +// } + StandingAnim(); + // setup moving speed + m_fWalkSpeed = FRnd() + 2.5f; + m_aWalkRotateSpeed = AngleDeg(FRnd()*25.0f + 45.0f); + m_fAttackRunSpeed = FRnd()*5.0f + 22.5f; + m_fAttackRotateRunInto = AngleDeg(FRnd()*60 + 100.0f); + m_aAttackRotateSpeed = m_fAttackRotateRunInto; + m_fCloseRunSpeed = FRnd()*5.0f + 15.0f; + m_aCloseRotateSpeed = AngleDeg(FRnd()*50 + 500.0f); + // setup attack distances + m_fAttackDistance = 100.0f; + m_fCloseDistance = 7.0f; + m_fStopDistance = 0.0f; + m_fAttackFireTime = 0.05f; + m_fCloseFireTime = 1.0f; + m_fIgnoreRange = 250.0f; + // damage/explode properties + m_fBlowUpAmount = 1E10f; + m_fBodyParts = 12; + m_fDamageWounded = 100000.0f; + m_iScore = 2000; + if (m_fStepHeight==-1) { + m_fStepHeight = 4.0f; + } + + Particles_RunningDust_Prepare(this); + + // continue behavior in base class + jump CEnemyRunInto::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Werebull.h b/Sources/EntitiesMP/Werebull.h new file mode 100644 index 0000000..c87fd0a --- /dev/null +++ b/Sources/EntitiesMP/Werebull.h @@ -0,0 +1,114 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Werebull_INCLUDED +#define _EntitiesMP_Werebull_INCLUDED 1 +#include +#include +extern DECL_DLL CEntityPropertyEnumType BullChar_enum; +enum BullChar { + BUC_SUMMER = 0, + BUC_WINTER = 1, +}; +DECL_DLL inline void ClearToDefault(BullChar &e) { e = (BullChar)0; } ; +extern "C" DECL_DLL CDLLEntityClass CWerebull_DLLClass; +class CWerebull : public CEnemyRunInto { +public: + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bRunAttack; + BOOL m_bHornHit; + CEntityPointer m_penLastTouched; + CSoundObject m_soFeet; + BOOL m_bRunSoundPlaying; + +#line 57 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void Precache(void); + +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void * GetEntityInfo(void); + +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT GetCrushHealth(void); + +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void RenderParticles(void); + +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void AdjustDifficulty(void); + +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +INDEX AnimForDeath(void); + +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void DeathNotify(); + +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void StandingAnim(void); + +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void WalkingAnim(void); + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void RunningAnim(void); + +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void RotatingAnim(void); + +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void IdleSound(void); + +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void SightSound(void); + +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void WoundSound(void); + +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void DeathSound(void); + +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void ActivateRunningSound(void); + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void DeactivateRunningSound(void); + +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void LiveEntityTouched(ETouch etouch); + +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +BOOL HigherMass(void); + +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +void EnemyPostInit(void); +#define STATE_CWerebull_Hit 0x01330000 + BOOL +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +Hit(const CEntityEvent &__eeInput); + BOOL H0x01330001_Hit_01(const CEntityEvent &__eeInput); + BOOL H0x01330002_Hit_02(const CEntityEvent &__eeInput); + BOOL H0x01330003_Hit_03(const CEntityEvent &__eeInput); + BOOL H0x01330004_Hit_04(const CEntityEvent &__eeInput); + BOOL H0x01330005_Hit_05(const CEntityEvent &__eeInput); + BOOL H0x01330006_Hit_06(const CEntityEvent &__eeInput); + BOOL H0x01330007_Hit_07(const CEntityEvent &__eeInput); +#define STATE_CWerebull_Main 1 + BOOL +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Werebull_INCLUDED diff --git a/Sources/EntitiesMP/Werebull_tables.h b/Sources/EntitiesMP/Werebull_tables.h new file mode 100644 index 0000000..65a8721 --- /dev/null +++ b/Sources/EntitiesMP/Werebull_tables.h @@ -0,0 +1,69 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(BullChar) + EP_ENUMVALUE(BUC_SUMMER, "Summer"), + EP_ENUMVALUE(BUC_WINTER, "Winter"), +EP_ENUMEND(BullChar); + +#define ENTITYCLASS CWerebull + +CEntityProperty CWerebull_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000133<<8)+1, offsetof(CWerebull, m_bRunAttack), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000133<<8)+2, offsetof(CWerebull, m_bHornHit), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000133<<8)+3, offsetof(CWerebull, m_penLastTouched), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_SOUNDOBJECT, NULL, (0x00000133<<8)+4, offsetof(CWerebull, m_soFeet), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000133<<8)+5, offsetof(CWerebull, m_bRunSoundPlaying), "", 0, 0, 0), +}; +#define CWerebull_propertiesct ARRAYCOUNT(CWerebull_properties) + +CEntityComponent CWerebull_components[] = { +#define CLASS_BASE ((0x00000133<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyRunInto.ecl"), +#define MODEL_WEREBULL ((0x00000133<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_WEREBULL, "EFNM" "Models\\Enemies\\Werebull\\Werebull.mdl"), +#define TEXTURE_WEREBULL_SUMMER ((0x00000133<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_WEREBULL_SUMMER, "EFNM" "Models\\Enemies\\Werebull\\Werebull.tex"), +#define SOUND_IDLE ((0x00000133<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "Models\\Enemies\\Werebull\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000133<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "Models\\Enemies\\Werebull\\Sounds\\Sight.wav"), +#define SOUND_KICKHORN ((0x00000133<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_KICKHORN, "EFNM" "Models\\Enemies\\Werebull\\Sounds\\KickHorn.wav"), +#define SOUND_IMPACT ((0x00000133<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_IMPACT, "EFNM" "Models\\Enemies\\Werebull\\Sounds\\Impact.wav"), +#define SOUND_DEATH ((0x00000133<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "Models\\Enemies\\Werebull\\Sounds\\Death.wav"), +#define SOUND_RUN ((0x00000133<<8)+56) + CEntityComponent(ECT_SOUND, SOUND_RUN, "EFNM" "Models\\Enemies\\Werebull\\Sounds\\Run.wav"), +}; +#define CWerebull_componentsct ARRAYCOUNT(CWerebull_components) + +CEventHandlerEntry CWerebull_handlers[] = { + {0x01330000, STATE_CEnemyBase_Hit, CEntity::pEventHandler(&CWerebull:: +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +Hit),DEBUGSTRING("CWerebull::Hit")}, + {0x01330001, -1, CEntity::pEventHandler(&CWerebull::H0x01330001_Hit_01), DEBUGSTRING("CWerebull::H0x01330001_Hit_01")}, + {0x01330002, -1, CEntity::pEventHandler(&CWerebull::H0x01330002_Hit_02), DEBUGSTRING("CWerebull::H0x01330002_Hit_02")}, + {0x01330003, -1, CEntity::pEventHandler(&CWerebull::H0x01330003_Hit_03), DEBUGSTRING("CWerebull::H0x01330003_Hit_03")}, + {0x01330004, -1, CEntity::pEventHandler(&CWerebull::H0x01330004_Hit_04), DEBUGSTRING("CWerebull::H0x01330004_Hit_04")}, + {0x01330005, -1, CEntity::pEventHandler(&CWerebull::H0x01330005_Hit_05), DEBUGSTRING("CWerebull::H0x01330005_Hit_05")}, + {0x01330006, -1, CEntity::pEventHandler(&CWerebull::H0x01330006_Hit_06), DEBUGSTRING("CWerebull::H0x01330006_Hit_06")}, + {0x01330007, -1, CEntity::pEventHandler(&CWerebull::H0x01330007_Hit_07), DEBUGSTRING("CWerebull::H0x01330007_Hit_07")}, + {1, -1, CEntity::pEventHandler(&CWerebull:: +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Werebull.es" +Main),DEBUGSTRING("CWerebull::Main")}, +}; +#define CWerebull_handlersct ARRAYCOUNT(CWerebull_handlers) + +CEntity *CWerebull_New(void) { return new CWerebull; }; +void CWerebull_OnInitClass(void) {}; +void CWerebull_OnEndClass(void) {}; +void CWerebull_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CWerebull_OnWorldEnd(CWorld *pwo) {}; +void CWerebull_OnWorldInit(CWorld *pwo) {}; +void CWerebull_OnWorldTick(CWorld *pwo) {}; +void CWerebull_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CWerebull, CEnemyRunInto, "Werebull", "Thumbnails\\Werebull.tbn", 0x00000133); +DECLARE_CTFILENAME(_fnmCWerebull_tbn, "Thumbnails\\Werebull.tbn"); diff --git a/Sources/EntitiesMP/Woman.cpp b/Sources/EntitiesMP/Woman.cpp new file mode 100644 index 0000000..08ffe12 --- /dev/null +++ b/Sources/EntitiesMP/Woman.cpp @@ -0,0 +1,784 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" + +#include "StdH.h" +#include "ModelsMP/Enemies/Woman/Woman.h" +#include "Models/Enemies/Headman/Headman.h" +#include "EntitiesMP/Headman.h" + +#include +#include +#line 13 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" + +// info structure +static EntityInfo eiWomanStand = { + EIBT_FLESH, 100.0f, + 0.0f, 1.55f, 0.0f, + 0.0f, 1.0f, 0.0f, +}; +static EntityInfo eiWomanFly = { + EIBT_FLESH, 80.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, +}; + +#define FIRE_AIR FLOAT3D(0.0f, 0.25f, -0.65f) +#define FIRE_GROUND FLOAT3D(0.0f, 1.3f, -0.5f) +#define KAMIKAZE_ATTACH FLOAT3D(0.0f, -0.43f, -0.28f) + +void CWoman::SetDefaultProperties(void) { + m_bKamikazeCarrier = FALSE ; + m_rKamikazeDropDistance = 40.0f; + m_bKamikazeAttached = FALSE ; + CEnemyFly::SetDefaultProperties(); +} + CTString CWoman::GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath) +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +{ +#line 65 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CTString str ; +#line 66 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(eDeath . eLastDamage . dmtType == DMT_CLOSERANGE ){ +#line 67 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +str . PrintF (TRANS ("%s was beaten by a Scythian Harpy") , strPlayerName ); +#line 68 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +}else { +#line 69 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +str . PrintF (TRANS ("A Scythian Harpy got %s spellbound") , strPlayerName ); +#line 70 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 71 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return str ; +#line 72 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + const CTFileName & CWoman::GetComputerMessageName(void)const { +#line 74 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +static DECLARE_CTFILENAME (fnm , "Data\\Messages\\Enemies\\Woman.txt"); +#line 75 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return fnm ; +#line 76 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::Precache(void) { +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CEnemyBase :: Precache (); +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PrecacheSound (SOUND_IDLE ); +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PrecacheSound (SOUND_SIGHT ); +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PrecacheSound (SOUND_WOUND ); +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PrecacheSound (SOUND_FIRE ); +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PrecacheSound (SOUND_KICK ); +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PrecacheSound (SOUND_DEATH ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PrecacheClass (CLASS_PROJECTILE , PRT_WOMAN_FIRE ); +#line 86 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void * CWoman::GetEntityInfo(void) { +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(m_bInAir ){ +#line 91 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return & eiWomanFly ; +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +}else { +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return & eiWomanStand ; +#line 94 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection) +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +{ +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(! IsOfClass (penInflictor , "Woman")){ +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CEnemyFly :: ReceiveDamage (penInflictor , dmtType , fDamageAmmount , vHitPoint , vDirection ); +#line 104 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +INDEX CWoman::AnimForDamage(FLOAT fDamage) { +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +INDEX iAnim ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(m_bInAir ){ +#line 112 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +iAnim = WOMAN_ANIM_AIRWOUND02 ; +#line 113 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +}else { +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +iAnim = WOMAN_ANIM_GROUNDWOUND04 ; +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (iAnim , 0); +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return iAnim ; +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +INDEX CWoman::AnimForDeath(void) { +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +INDEX iAnim ; +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(m_bInAir ){ +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +iAnim = WOMAN_ANIM_AIRDEATH ; +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +}else { +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +iAnim = WOMAN_ANIM_GROUNDDEATH01 ; +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (iAnim , 0); +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return iAnim ; +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FLOAT CWoman::WaitForDust(FLOAT3D & vStretch) { +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(GetModelObject () -> GetAnim () == WOMAN_ANIM_AIRDEATH ) +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +{ +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +vStretch = FLOAT3D (1 , 1 , 2) * 1.0f; +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return 0.6f; +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +else if(GetModelObject () -> GetAnim () == WOMAN_ANIM_GROUNDDEATH01 ) +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +{ +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +vStretch = FLOAT3D (1 , 1 , 2) * 0.75f; +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return 0.525f; +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return - 1.0f; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::DeathNotify(void) { +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +ChangeCollisionBoxIndexWhenPossible (WOMAN_COLLISION_BOX_DEATH ); +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +en_fDensity = 500.0f; +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::StandingAnim(void) { +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(m_bInAir ){ +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_AIRSTAND , AOF_LOOPING | AOF_NORESTART ); +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +}else { +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_GROUNDSTAND , AOF_LOOPING | AOF_NORESTART ); +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::WalkingAnim(void) { +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(m_bInAir ){ +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_AIRFLY , AOF_LOOPING | AOF_NORESTART ); +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +}else { +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_GROUNDWALK , AOF_LOOPING | AOF_NORESTART ); +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::RunningAnim(void) { +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(m_bInAir ){ +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_AIRFLY , AOF_LOOPING | AOF_NORESTART ); +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +}else { +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_GROUNDRUN , AOF_LOOPING | AOF_NORESTART ); +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::RotatingAnim(void) { +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(m_bInAir ){ +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_AIRFLY , AOF_LOOPING | AOF_NORESTART ); +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +}else { +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_GROUNDWALK , AOF_LOOPING | AOF_NORESTART ); +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FLOAT CWoman::AirToGroundAnim(void) { +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_AIRTOGROUND , 0); +#line 182 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return (GetModelObject () -> GetAnimLength (WOMAN_ANIM_AIRTOGROUND )); +#line 183 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FLOAT CWoman::GroundToAirAnim(void) { +#line 185 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_GROUNDTOAIR , 0); +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return (GetModelObject () -> GetAnimLength (WOMAN_ANIM_GROUNDTOAIR )); +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::ChangeCollisionToAir() { +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +ChangeCollisionBoxIndexWhenPossible (WOMAN_COLLISION_BOX_AIR ); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::ChangeCollisionToGround() { +#line 192 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +ChangeCollisionBoxIndexWhenPossible (WOMAN_COLLISION_BOX_GROUND ); +#line 193 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::IdleSound(void) { +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PlaySound (m_soSound , SOUND_IDLE , SOF_3D ); +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::SightSound(void) { +#line 200 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PlaySound (m_soSound , SOUND_SIGHT , SOF_3D ); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::WoundSound(void) { +#line 203 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PlaySound (m_soSound , SOUND_WOUND , SOF_3D ); +#line 204 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::DeathSound(void) { +#line 206 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PlaySound (m_soSound , SOUND_DEATH , SOF_3D ); +#line 207 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::AttachKamikaze() +#line 210 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +{ +#line 211 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +AddAttachmentToModel (this , * GetModelObject () , WOMAN_ATTACHMENT_KAMIKAZE , MODEL_HEADMAN , TEXTURE_HEADMAN , 0 , 0 , 0); +#line 212 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CModelObject & amo = GetModelObject () -> GetAttachmentModel (WOMAN_ATTACHMENT_KAMIKAZE ) -> amo_moModelObject ; +#line 213 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +AddAttachmentToModel (this , amo , HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND , MODEL_BOMB , TEXTURE_BOMB , 0 , 0 , 0); +#line 214 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +AddAttachmentToModel (this , amo , HEADMAN_ATTACHMENT_BOMB_LEFT_HAND , MODEL_BOMB , TEXTURE_BOMB , 0 , 0 , 0); +#line 215 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +amo . PlayAnim (HEADMAN_ANIM_KAMIKAZE_ATTACK , AOF_LOOPING ); +#line 216 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_bKamikazeAttached = TRUE ; +#line 217 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::RemoveKamikaze() +#line 220 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +{ +#line 221 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +RemoveAttachmentFromModel (* GetModelObject () , WOMAN_ATTACHMENT_KAMIKAZE ); +#line 222 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::DropKamikaze() +#line 225 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +{ +#line 226 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(! m_bKamikazeAttached ){return ;} +#line 228 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CEntity * pen = NULL ; +#line 230 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CPlacement3D pl ; +#line 231 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +pl = GetPlacement (); +#line 232 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +pl . pl_PositionVector += KAMIKAZE_ATTACH * GetRotationMatrix (); +#line 233 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +pen = CreateEntity (pl , CLASS_HEADMAN ); +#line 235 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +((CHeadman *) & * pen ) -> m_hdtType = HDT_KAMIKAZE ; +#line 238 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +pen -> End (); +#line 240 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CEnemyBase * peb = ((CEnemyBase *) pen ); +#line 241 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +peb -> m_bTemplate = FALSE ; +#line 242 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +pen -> Initialize (); +#line 245 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_bKamikazeAttached = FALSE ; +#line 248 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +RemoveKamikaze (); +#line 249 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::PreMoving() { +#line 253 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(m_bKamikazeAttached && m_bKamikazeCarrier ){ +#line 255 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +INDEX ctMaxPlayers = GetMaxPlayers (); +#line 256 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CEntity * penPlayer ; +#line 257 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +for(INDEX i = 0;i < ctMaxPlayers ;i ++){ +#line 258 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +penPlayer = GetPlayerEntity (i ); +#line 259 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(penPlayer != NULL ){ +#line 260 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(DistanceTo (this , penPlayer ) < m_rKamikazeDropDistance && IsVisible (penPlayer )){ +#line 261 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +DropKamikaze (); +#line 262 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 263 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 264 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 265 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 266 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CEnemyFly :: PreMoving (); +#line 267 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} + +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void CWoman::BlowUp(void) +#line 270 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +{ +#line 271 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +DropKamikaze (); +#line 272 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CEnemyFly :: BlowUp (); +#line 273 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +BOOL CWoman:: +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FlyFire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWoman_FlyFire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWoman::FlyFire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 281 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(m_bKamikazeAttached ){Return(STATE_CURRENT,EReturn ());return TRUE;} +#line 284 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_AIRATTACK02 , 0); +#line 285 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetTimerAfter(0.6f); +Jump(STATE_CURRENT, 0x01400001, FALSE, EBegin());return TRUE;}BOOL CWoman::H0x01400001_FlyFire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400001 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01400002, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWoman::H0x01400002_FlyFire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400002 +; +#line 286 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +ShootProjectile (PRT_WOMAN_FIRE , FIRE_AIR , ANGLE3D (0 , 0 , 0)); +#line 287 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D ); +#line 288 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetTimerAfter(0.6f); +Jump(STATE_CURRENT, 0x01400003, FALSE, EBegin());return TRUE;}BOOL CWoman::H0x01400003_FlyFire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400003 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01400004, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWoman::H0x01400004_FlyFire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400004 +; +#line 289 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StandingAnim (); +#line 290 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetTimerAfter(FRnd () / 2 + _pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01400005, FALSE, EBegin());return TRUE;}BOOL CWoman::H0x01400005_FlyFire_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400005 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01400006, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWoman::H0x01400006_FlyFire_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400006 +; +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Return(STATE_CURRENT,EReturn ()); +#line 292 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWoman:: +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FlyHit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWoman_FlyHit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWoman::FlyHit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 296 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(m_bKamikazeAttached ){Return(STATE_CURRENT,EReturn ());return TRUE;} +#line 299 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(CalcDist (m_penEnemy ) <= 5.0f){ +#line 301 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CMovableEntity * pen = (CMovableEntity *) & * m_penEnemy ; +#line 302 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +CContentType & ctDn = pen -> en_pwoWorld -> wo_actContentTypes [ pen -> en_iDnContent ]; +#line 303 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +BOOL bEnemySwimming = ! (ctDn . ct_ulFlags & CTF_BREATHABLE_LUNGS ); +#line 304 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(bEnemySwimming ){ +#line 305 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Jump(STATE_CURRENT, STATE_CWoman_FlyFire, TRUE, EVoid());return TRUE; +#line 306 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +}else { +#line 307 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Jump(STATE_CURRENT, STATE_CWoman_FlyOnEnemy, TRUE, EVoid());return TRUE; +#line 308 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 309 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 312 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fShootTime = _pTimer -> CurrentTick () + 0.25f; +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Return(STATE_CURRENT,EReturn ()); +#line 313 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWoman:: +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Death(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWoman_Death + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWoman::Death expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 320 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +DropKamikaze (); +#line 321 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Jump(STATE_CURRENT, STATE_CEnemyFly_Death, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWoman:: +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +AirToGround(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWoman_AirToGround + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWoman::AirToGround expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 325 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +DropKamikaze (); +#line 326 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Jump(STATE_CURRENT, STATE_CEnemyFly_AirToGround, FALSE, EVoid ());return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWoman:: +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FlyOnEnemy(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWoman_FlyOnEnemy + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWoman::FlyOnEnemy expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 330 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_AIRATTACK01 , 0); +#line 333 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FLOAT3D vDir = PlayerDestinationPos (); +#line 334 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +vDir = (vDir - GetPlacement () . pl_PositionVector ) . Normalize (); +#line 335 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +vDir *= ! GetRotationMatrix (); +#line 336 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +vDir *= m_fFlyCloseRunSpeed * 1.9f; +#line 337 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetDesiredTranslation (vDir ); +#line 338 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PlaySound (m_soSound , SOUND_KICK , SOF_3D ); +#line 341 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SpawnReminder (this , 0.9f , 0); +#line 342 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_iChargeHitAnimation = WOMAN_ANIM_AIRATTACK01 ; +#line 343 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fChargeHitDamage = 20.0f; +#line 344 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fChargeHitAngle = 0.0f; +#line 345 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fChargeHitSpeed = 10.0f; +#line 346 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +STATE_CEnemyBase_ChargeHitEnemy, FALSE; +Jump(STATE_CURRENT, 0x0140000b, FALSE, EBegin());return TRUE;}BOOL CWoman::H0x0140000b_FlyOnEnemy_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0140000b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_ChargeHitEnemy, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x0140000c, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CWoman::H0x0140000c_FlyOnEnemy_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x0140000c +const EReturn&__e= (EReturn&)__eeInput; +; +#line 348 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StandingAnim (); +#line 349 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetTimerAfter(0.3f); +Jump(STATE_CURRENT, 0x0140000d, FALSE, EBegin());return TRUE;}BOOL CWoman::H0x0140000d_FlyOnEnemy_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0140000d +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0140000e, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWoman::H0x0140000e_FlyOnEnemy_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0140000e +; +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Return(STATE_CURRENT,EReturn ()); +#line 350 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWoman:: +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +GroundFire(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWoman_GroundFire + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWoman::GroundFire expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 355 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_GROUNDATTACK02 , 0); +#line 356 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetTimerAfter(0.3f); +Jump(STATE_CURRENT, 0x01400010, FALSE, EBegin());return TRUE;}BOOL CWoman::H0x01400010_GroundFire_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400010 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01400011, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWoman::H0x01400011_GroundFire_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400011 +; +#line 357 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +ShootProjectile (PRT_WOMAN_FIRE , FIRE_GROUND , ANGLE3D (0 , 0 , 0)); +#line 358 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PlaySound (m_soSound , SOUND_FIRE , SOF_3D ); +#line 359 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetTimerAfter(0.3f); +Jump(STATE_CURRENT, 0x01400012, FALSE, EBegin());return TRUE;}BOOL CWoman::H0x01400012_GroundFire_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400012 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01400013, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWoman::H0x01400013_GroundFire_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400013 +; +#line 360 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StandingAnim (); +#line 361 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetTimerAfter(FRnd () / 2 + _pTimer -> TickQuantum ); +Jump(STATE_CURRENT, 0x01400014, FALSE, EBegin());return TRUE;}BOOL CWoman::H0x01400014_GroundFire_05(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400014 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x01400015, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWoman::H0x01400015_GroundFire_06(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400015 +; +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Return(STATE_CURRENT,EReturn ()); +#line 363 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWoman:: +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +GroundHit(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWoman_GroundHit + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWoman::GroundHit expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 367 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StartModelAnim (WOMAN_ANIM_GROUNDATTACK01 , 0); +#line 370 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FLOAT3D vDir = (m_penEnemy -> GetPlacement () . pl_PositionVector - +#line 371 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +GetPlacement () . pl_PositionVector ) . Normalize (); +#line 372 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +vDir *= ! GetRotationMatrix (); +#line 373 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +vDir *= m_fCloseRunSpeed * 1.75f; +#line 374 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +vDir (2) = 2.5f; +#line 375 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetDesiredTranslation (vDir ); +#line 376 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +PlaySound (m_soSound , SOUND_KICK , SOF_3D ); +#line 379 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SpawnReminder (this , 0.9f , 0); +#line 380 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_iChargeHitAnimation = WOMAN_ANIM_GROUNDATTACK01 ; +#line 381 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fChargeHitDamage = 20.0f; +#line 382 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fChargeHitAngle = 0.0f; +#line 383 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fChargeHitSpeed = 10.0f; +#line 384 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +STATE_CEnemyBase_ChargeHitEnemy, FALSE; +Jump(STATE_CURRENT, 0x01400017, FALSE, EBegin());return TRUE;}BOOL CWoman::H0x01400017_GroundHit_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400017 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: Call(STATE_CURRENT, STATE_CEnemyBase_ChargeHitEnemy, FALSE, EVoid());return TRUE;case EVENTCODE_EReturn: Jump(STATE_CURRENT,0x01400018, FALSE, __eeInput); return TRUE;default: return FALSE; }}BOOL CWoman::H0x01400018_GroundHit_02(const CEntityEvent &__eeInput){ +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400018 +const EReturn&__e= (EReturn&)__eeInput; +; +#line 386 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +StandingAnim (); +#line 387 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetTimerAfter(0.3f); +Jump(STATE_CURRENT, 0x01400019, FALSE, EBegin());return TRUE;}BOOL CWoman::H0x01400019_GroundHit_03(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x01400019 +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0140001a, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWoman::H0x0140001a_GroundHit_04(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0140001a +; +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Return(STATE_CURRENT,EReturn ()); +#line 388 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +return TRUE; ASSERT(FALSE); return TRUE;};BOOL CWoman:: +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWoman_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWoman::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 398 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +InitAsModel (); +#line 399 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetPhysicsFlags (EPF_MODEL_WALKING | EPF_HASLUNGS ); +#line 400 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetCollisionFlags (ECF_MODEL ); +#line 401 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetFlags (GetFlags () | ENF_ALIVE ); +#line 402 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetHealth (100.0f); +#line 403 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fMaxHealth = 100.0f; +#line 404 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +en_tmMaxHoldBreath = 5.0f; +#line 405 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +en_fDensity = 2000.0f; +#line 407 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_sptType = SPT_FEATHER ; +#line 410 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetModel (MODEL_WOMAN ); +#line 411 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetModelMainTexture (TEXTURE_WOMAN ); +#line 413 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fWalkSpeed = FRnd () + 1.5f; +#line 414 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_aWalkRotateSpeed = FRnd () * 10.0f + 25.0f; +#line 415 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fAttackRunSpeed = FRnd () * 2.0f + 9.0f; +#line 416 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_aAttackRotateSpeed = FRnd () * 50 + 245.0f; +#line 417 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fCloseRunSpeed = FRnd () * 2.0f + 4.0f; +#line 418 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_aCloseRotateSpeed = FRnd () * 50 + 245.0f; +#line 420 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fAttackDistance = 50.0f; +#line 421 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fCloseDistance = 5.0f; +#line 422 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fStopDistance = 0.0f; +#line 423 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fAttackFireTime = 3.0f; +#line 424 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fCloseFireTime = 2.0f; +#line 425 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fIgnoreRange = 200.0f; +#line 427 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fFlyWalkSpeed = FRnd () / 2 + 1.0f; +#line 428 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_aFlyWalkRotateSpeed = FRnd () * 10.0f + 25.0f; +#line 429 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fFlyAttackRunSpeed = FRnd () * 2.0f + 10.0f; +#line 430 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_aFlyAttackRotateSpeed = FRnd () * 25 + 150.0f; +#line 431 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fFlyCloseRunSpeed = FRnd () * 2.0f + 10.0f; +#line 432 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_aFlyCloseRotateSpeed = FRnd () * 50 + 500.0f; +#line 433 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fGroundToAirSpeed = m_fFlyCloseRunSpeed ; +#line 434 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fAirToGroundSpeed = m_fFlyCloseRunSpeed ; +#line 435 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fAirToGroundMin = 0.1f; +#line 436 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fAirToGroundMax = 0.1f; +#line 438 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fFlyAttackDistance = 50.0f; +#line 439 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fFlyCloseDistance = 12.5f; +#line 440 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fFlyStopDistance = 0.0f; +#line 441 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fFlyAttackFireTime = 3.0f; +#line 442 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fFlyCloseFireTime = 2.0f; +#line 443 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fFlyIgnoreRange = 200.0f; +#line 445 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fBlowUpAmount = 100.0f; +#line 446 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fBodyParts = 4; +#line 447 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_fDamageWounded = 20.0f; +#line 448 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +m_iScore = 1000; +#line 450 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +if(m_bKamikazeCarrier ){ +#line 451 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +AttachKamikaze (); +#line 452 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +} +#line 454 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +SetTimerAfter(0.05f); +Jump(STATE_CURRENT, 0x0140001b, FALSE, EBegin());return TRUE;}BOOL CWoman::H0x0140001b_Main_01(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT 0x0140001b +switch(__eeInput.ee_slEvent) {case EVENTCODE_EBegin: return TRUE;case EVENTCODE_ETimer: Jump(STATE_CURRENT,0x0140001c, FALSE, EInternal()); return TRUE;default: return FALSE; }}BOOL CWoman::H0x0140001c_Main_02(const CEntityEvent &__eeInput){ +ASSERT(__eeInput.ee_slEvent==EVENTCODE_EInternal); +#undef STATE_CURRENT +#define STATE_CURRENT 0x0140001c +; +#line 457 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Jump(STATE_CURRENT, STATE_CEnemyFly_MainLoop, FALSE, EVoid());return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/Woman.es b/Sources/EntitiesMP/Woman.es new file mode 100644 index 0000000..26221ca --- /dev/null +++ b/Sources/EntitiesMP/Woman.es @@ -0,0 +1,459 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +320 +%{ +#include "StdH.h" +#include "ModelsMP/Enemies/Woman/Woman.h" +#include "Models/Enemies/Headman/Headman.h" +#include "EntitiesMP/Headman.h" +%} + +uses "EntitiesMP/EnemyFly"; + +%{ +// info structure +static EntityInfo eiWomanStand = { + EIBT_FLESH, 100.0f, + 0.0f, 1.55f, 0.0f, + 0.0f, 1.0f, 0.0f, +}; +static EntityInfo eiWomanFly = { + EIBT_FLESH, 80.0f, + 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, +}; + +#define FIRE_AIR FLOAT3D(0.0f, 0.25f, -0.65f) +#define FIRE_GROUND FLOAT3D(0.0f, 1.3f, -0.5f) +#define KAMIKAZE_ATTACH FLOAT3D(0.0f, -0.43f, -0.28f) +%} + + +class CWoman : CEnemyFly { +name "Woman"; +thumbnail "Thumbnails\\Woman.tbn"; + +properties: + + 10 BOOL m_bKamikazeCarrier "Kamikaze Carrier" = FALSE, + 11 RANGE m_rKamikazeDropDistance "Kamikaze Drop Range" = 40.0f, + 20 BOOL m_bKamikazeAttached = FALSE, + +components: + 0 class CLASS_BASE "Classes\\EnemyFly.ecl", + 1 model MODEL_WOMAN "ModelsMP\\Enemies\\Woman\\Woman.mdl", + 2 texture TEXTURE_WOMAN "Models\\Enemies\\Woman\\Woman.tex", + 3 class CLASS_PROJECTILE "Classes\\Projectile.ecl", + 5 class CLASS_HEADMAN "Classes\\Headman.ecl", + 7 model MODEL_HEADMAN "Models\\Enemies\\Headman\\Headman.mdl", + 8 texture TEXTURE_HEADMAN "Models\\Enemies\\Headman\\Kamikaze.tex", + 9 model MODEL_BOMB "Models\\Enemies\\Headman\\Projectile\\Bomb.mdl", + 10 texture TEXTURE_BOMB "Models\\Enemies\\Headman\\Projectile\\Bomb.tex", + +// ************** SOUNDS ************** + 50 sound SOUND_IDLE "Models\\Enemies\\Woman\\Sounds\\Idle.wav", + 51 sound SOUND_SIGHT "Models\\Enemies\\Woman\\Sounds\\Sight.wav", + 52 sound SOUND_WOUND "Models\\Enemies\\Woman\\Sounds\\Wound.wav", + 53 sound SOUND_FIRE "Models\\Enemies\\Woman\\Sounds\\Fire.wav", + 54 sound SOUND_KICK "Models\\Enemies\\Woman\\Sounds\\Kick.wav", + 55 sound SOUND_DEATH "Models\\Enemies\\Woman\\Sounds\\Death.wav", + +functions: + // describe how this enemy killed player + virtual CTString GetPlayerKillDescription(const CTString &strPlayerName, const EDeath &eDeath) + { + CTString str; + if (eDeath.eLastDamage.dmtType==DMT_CLOSERANGE) { + str.PrintF(TRANS("%s was beaten by a Scythian Harpy"), strPlayerName); + } else { + str.PrintF(TRANS("A Scythian Harpy got %s spellbound"), strPlayerName); + } + return str; + } + virtual const CTFileName &GetComputerMessageName(void) const { + static DECLARE_CTFILENAME(fnm, "Data\\Messages\\Enemies\\Woman.txt"); + return fnm; + } + void Precache(void) { + CEnemyBase::Precache(); + PrecacheSound(SOUND_IDLE ); + PrecacheSound(SOUND_SIGHT); + PrecacheSound(SOUND_WOUND); + PrecacheSound(SOUND_FIRE ); + PrecacheSound(SOUND_KICK ); + PrecacheSound(SOUND_DEATH); + PrecacheClass(CLASS_PROJECTILE, PRT_WOMAN_FIRE); + }; + + /* Entity info */ + void *GetEntityInfo(void) { + if (m_bInAir) { + return &eiWomanFly; + } else { + return &eiWomanStand; + } + }; + + /* Receive damage */ + void ReceiveDamage(CEntity *penInflictor, enum DamageType dmtType, + FLOAT fDamageAmmount, const FLOAT3D &vHitPoint, const FLOAT3D &vDirection) + { + // woman can't harm woman + if (!IsOfClass(penInflictor, "Woman")) { + CEnemyFly::ReceiveDamage(penInflictor, dmtType, fDamageAmmount, vHitPoint, vDirection); + } + }; + + + // damage anim + INDEX AnimForDamage(FLOAT fDamage) { + INDEX iAnim; + if (m_bInAir) { + iAnim = WOMAN_ANIM_AIRWOUND02; + } else { + iAnim = WOMAN_ANIM_GROUNDWOUND04; + } + StartModelAnim(iAnim, 0); + return iAnim; + }; + + // death + INDEX AnimForDeath(void) { + INDEX iAnim; + if (m_bInAir) { + iAnim = WOMAN_ANIM_AIRDEATH; + } else { + iAnim = WOMAN_ANIM_GROUNDDEATH01; + } + StartModelAnim(iAnim, 0); + return iAnim; + }; + + FLOAT WaitForDust(FLOAT3D &vStretch) { + if(GetModelObject()->GetAnim()==WOMAN_ANIM_AIRDEATH) + { + vStretch=FLOAT3D(1,1,2)*1.0f; + return 0.6f; + } + else if(GetModelObject()->GetAnim()==WOMAN_ANIM_GROUNDDEATH01) + { + vStretch=FLOAT3D(1,1,2)*0.75f; + return 0.525f; + } + return -1.0f; + }; + + void DeathNotify(void) { + ChangeCollisionBoxIndexWhenPossible(WOMAN_COLLISION_BOX_DEATH); + en_fDensity = 500.0f; + }; + + // virtual anim functions + void StandingAnim(void) { + if (m_bInAir) { + StartModelAnim(WOMAN_ANIM_AIRSTAND, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(WOMAN_ANIM_GROUNDSTAND, AOF_LOOPING|AOF_NORESTART); + } + }; + void WalkingAnim(void) { + if (m_bInAir) { + StartModelAnim(WOMAN_ANIM_AIRFLY, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(WOMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART); + } + }; + void RunningAnim(void) { + if (m_bInAir) { + StartModelAnim(WOMAN_ANIM_AIRFLY, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(WOMAN_ANIM_GROUNDRUN, AOF_LOOPING|AOF_NORESTART); + } + }; + void RotatingAnim(void) { + if (m_bInAir) { + StartModelAnim(WOMAN_ANIM_AIRFLY, AOF_LOOPING|AOF_NORESTART); + } else { + StartModelAnim(WOMAN_ANIM_GROUNDWALK, AOF_LOOPING|AOF_NORESTART); + } + }; + FLOAT AirToGroundAnim(void) { + StartModelAnim(WOMAN_ANIM_AIRTOGROUND, 0); + return(GetModelObject()->GetAnimLength(WOMAN_ANIM_AIRTOGROUND)); + }; + FLOAT GroundToAirAnim(void) { + StartModelAnim(WOMAN_ANIM_GROUNDTOAIR, 0); + return(GetModelObject()->GetAnimLength(WOMAN_ANIM_GROUNDTOAIR)); + }; + void ChangeCollisionToAir() { + ChangeCollisionBoxIndexWhenPossible(WOMAN_COLLISION_BOX_AIR); + }; + void ChangeCollisionToGround() { + ChangeCollisionBoxIndexWhenPossible(WOMAN_COLLISION_BOX_GROUND); + }; + + // virtual sound functions + void IdleSound(void) { + PlaySound(m_soSound, SOUND_IDLE, SOF_3D); + }; + void SightSound(void) { + PlaySound(m_soSound, SOUND_SIGHT, SOF_3D); + }; + void WoundSound(void) { + PlaySound(m_soSound, SOUND_WOUND, SOF_3D); + }; + void DeathSound(void) { + PlaySound(m_soSound, SOUND_DEATH, SOF_3D); + }; + + void AttachKamikaze() + { + AddAttachmentToModel(this, *GetModelObject(), WOMAN_ATTACHMENT_KAMIKAZE, MODEL_HEADMAN, TEXTURE_HEADMAN, 0, 0, 0); + CModelObject &amo = GetModelObject()->GetAttachmentModel(WOMAN_ATTACHMENT_KAMIKAZE)->amo_moModelObject; + AddAttachmentToModel(this, amo, HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND, MODEL_BOMB, TEXTURE_BOMB, 0, 0, 0); + AddAttachmentToModel(this, amo, HEADMAN_ATTACHMENT_BOMB_LEFT_HAND, MODEL_BOMB, TEXTURE_BOMB, 0, 0, 0); + amo.PlayAnim(HEADMAN_ANIM_KAMIKAZE_ATTACK, AOF_LOOPING); + m_bKamikazeAttached = TRUE; + } + + void RemoveKamikaze() + { + RemoveAttachmentFromModel(*GetModelObject(), WOMAN_ATTACHMENT_KAMIKAZE); + } + + void DropKamikaze() + { + if (!m_bKamikazeAttached) { return; } + + CEntity *pen = NULL; + + CPlacement3D pl; + pl = GetPlacement(); + pl.pl_PositionVector += KAMIKAZE_ATTACH*GetRotationMatrix(); + pen = CreateEntity(pl, CLASS_HEADMAN); + + ((CHeadman *)&*pen)->m_hdtType = HDT_KAMIKAZE; + + // change needed properties + pen->End(); + + CEnemyBase *peb = ((CEnemyBase*)pen); + peb->m_bTemplate = FALSE; + pen->Initialize(); + + // mark that we don't have the kamikaze any more + m_bKamikazeAttached = FALSE; + + // deattach the kamikaze model + RemoveKamikaze(); + } + + + void PreMoving() { + if (m_bKamikazeAttached && m_bKamikazeCarrier) { + // see if any of players are close enough to drop the kamikaze + INDEX ctMaxPlayers = GetMaxPlayers(); + CEntity *penPlayer; + for(INDEX i=0; iTickQuantum); + + return EReturn(); + }; + + FlyHit(EVoid) : CEnemyFly::FlyHit { + if (m_bKamikazeAttached) { return EReturn(); } + + // if enemy near + if (CalcDist(m_penEnemy) <= 5.0f) { + // if enemy is not in water + CMovableEntity *pen = (CMovableEntity *)&*m_penEnemy; + CContentType &ctDn = pen->en_pwoWorld->wo_actContentTypes[pen->en_iDnContent]; + BOOL bEnemySwimming = !(ctDn.ct_ulFlags&CTF_BREATHABLE_LUNGS); + if (bEnemySwimming) { + jump FlyFire(); + } else { + jump FlyOnEnemy(); + } + } + + // run to enemy + m_fShootTime = _pTimer->CurrentTick() + 0.25f; + return EReturn(); + }; + +/************************************************************ + * D E A T H * + ************************************************************/ + Death(EVoid) : CEnemyFly::Death { + DropKamikaze(); + jump CEnemyFly::Death(); + }; + + AirToGround(EVoid) : CEnemyFly::AirToGround { + DropKamikaze(); + jump CEnemyFly::AirToGround(EVoid()); + }; + + FlyOnEnemy(EVoid) { + StartModelAnim(WOMAN_ANIM_AIRATTACK01, 0); + + // jump + FLOAT3D vDir = PlayerDestinationPos(); + vDir = (vDir - GetPlacement().pl_PositionVector).Normalize(); + vDir *= !GetRotationMatrix(); + vDir *= m_fFlyCloseRunSpeed*1.9f; + SetDesiredTranslation(vDir); + PlaySound(m_soSound, SOUND_KICK, SOF_3D); + + // animation - IGNORE DAMAGE WOUND - + SpawnReminder(this, 0.9f, 0); + m_iChargeHitAnimation = WOMAN_ANIM_AIRATTACK01; + m_fChargeHitDamage = 20.0f; + m_fChargeHitAngle = 0.0f; + m_fChargeHitSpeed = 10.0f; + autocall CEnemyBase::ChargeHitEnemy() EReturn; + + StandingAnim(); + autowait(0.3f); + return EReturn(); + } + + GroundFire(EVoid) : CEnemyFly::GroundFire { + // fire projectile + StartModelAnim(WOMAN_ANIM_GROUNDATTACK02, 0); + autowait(0.3f); + ShootProjectile(PRT_WOMAN_FIRE, FIRE_GROUND, ANGLE3D(0, 0, 0)); + PlaySound(m_soSound, SOUND_FIRE, SOF_3D); + autowait(0.3f); + StandingAnim(); + autowait(FRnd()/2 + _pTimer->TickQuantum); + + return EReturn(); + }; + + GroundHit(EVoid) : CEnemyFly::GroundHit { + StartModelAnim(WOMAN_ANIM_GROUNDATTACK01, 0); + + // jump + FLOAT3D vDir = (m_penEnemy->GetPlacement().pl_PositionVector - + GetPlacement().pl_PositionVector).Normalize(); + vDir *= !GetRotationMatrix(); + vDir *= m_fCloseRunSpeed*1.75f; + vDir(2) = 2.5f; + SetDesiredTranslation(vDir); + PlaySound(m_soSound, SOUND_KICK, SOF_3D); + + // animation - IGNORE DAMAGE WOUND - + SpawnReminder(this, 0.9f, 0); + m_iChargeHitAnimation = WOMAN_ANIM_GROUNDATTACK01; + m_fChargeHitDamage = 20.0f; + m_fChargeHitAngle = 0.0f; + m_fChargeHitSpeed = 10.0f; + autocall CEnemyBase::ChargeHitEnemy() EReturn; + + StandingAnim(); + autowait(0.3f); + return EReturn(); + }; + + + +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + // declare yourself as a model + InitAsModel(); + SetPhysicsFlags(EPF_MODEL_WALKING|EPF_HASLUNGS); + SetCollisionFlags(ECF_MODEL); + SetFlags(GetFlags()|ENF_ALIVE); + SetHealth(100.0f); + m_fMaxHealth = 100.0f; + en_tmMaxHoldBreath = 5.0f; + en_fDensity = 2000.0f; + + m_sptType = SPT_FEATHER; + + // set your appearance + SetModel(MODEL_WOMAN); + SetModelMainTexture(TEXTURE_WOMAN); + // setup moving speed + m_fWalkSpeed = FRnd() + 1.5f; + m_aWalkRotateSpeed = FRnd()*10.0f + 25.0f; + m_fAttackRunSpeed = FRnd()*2.0f + 9.0f; + m_aAttackRotateSpeed = FRnd()*50 + 245.0f; + m_fCloseRunSpeed = FRnd()*2.0f + 4.0f; + m_aCloseRotateSpeed = FRnd()*50 + 245.0f; + // setup attack distances + m_fAttackDistance = 50.0f; + m_fCloseDistance = 5.0f; + m_fStopDistance = 0.0f; + m_fAttackFireTime = 3.0f; + m_fCloseFireTime = 2.0f; + m_fIgnoreRange = 200.0f; + // fly moving properties + m_fFlyWalkSpeed = FRnd()/2 + 1.0f; + m_aFlyWalkRotateSpeed = FRnd()*10.0f + 25.0f; + m_fFlyAttackRunSpeed = FRnd()*2.0f + 10.0f; + m_aFlyAttackRotateSpeed = FRnd()*25 + 150.0f; + m_fFlyCloseRunSpeed = FRnd()*2.0f + 10.0f; + m_aFlyCloseRotateSpeed = FRnd()*50 + 500.0f; + m_fGroundToAirSpeed = m_fFlyCloseRunSpeed; + m_fAirToGroundSpeed = m_fFlyCloseRunSpeed; + m_fAirToGroundMin = 0.1f; + m_fAirToGroundMax = 0.1f; + // attack properties - CAN BE SET + m_fFlyAttackDistance = 50.0f; + m_fFlyCloseDistance = 12.5f; + m_fFlyStopDistance = 0.0f; + m_fFlyAttackFireTime = 3.0f; + m_fFlyCloseFireTime = 2.0f; + m_fFlyIgnoreRange = 200.0f; + // damage/explode properties + m_fBlowUpAmount = 100.0f; + m_fBodyParts = 4; + m_fDamageWounded = 20.0f; + m_iScore = 1000; + + if (m_bKamikazeCarrier) { + AttachKamikaze(); + } + + autowait(0.05f); + + // continue behavior in base class + jump CEnemyFly::MainLoop(); + }; +}; diff --git a/Sources/EntitiesMP/Woman.h b/Sources/EntitiesMP/Woman.h new file mode 100644 index 0000000..9b938f5 --- /dev/null +++ b/Sources/EntitiesMP/Woman.h @@ -0,0 +1,150 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_Woman_INCLUDED +#define _EntitiesMP_Woman_INCLUDED 1 +#include +extern "C" DECL_DLL CDLLEntityClass CWoman_DLLClass; +class CWoman : public CEnemyFly { +public: + DECL_DLL virtual void SetDefaultProperties(void); + BOOL m_bKamikazeCarrier; + RANGE m_rKamikazeDropDistance; + BOOL m_bKamikazeAttached; + +#line 63 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +virtual CTString GetPlayerKillDescription(const CTString & strPlayerName,const EDeath & eDeath); + +#line 73 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +virtual const CTFileName & GetComputerMessageName(void)const; + +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void Precache(void); + +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void * GetEntityInfo(void); + +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void ReceiveDamage(CEntity * penInflictor,enum DamageType dmtType, +#line 99 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FLOAT fDamageAmmount,const FLOAT3D & vHitPoint,const FLOAT3D & vDirection); + +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +INDEX AnimForDamage(FLOAT fDamage); + +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +INDEX AnimForDeath(void); + +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FLOAT WaitForDust(FLOAT3D & vStretch); + +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void DeathNotify(void); + +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void StandingAnim(void); + +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void WalkingAnim(void); + +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void RunningAnim(void); + +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void RotatingAnim(void); + +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FLOAT AirToGroundAnim(void); + +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FLOAT GroundToAirAnim(void); + +#line 188 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void ChangeCollisionToAir(); + +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void ChangeCollisionToGround(); + +#line 196 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void IdleSound(void); + +#line 199 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void SightSound(void); + +#line 202 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void WoundSound(void); + +#line 205 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void DeathSound(void); + +#line 209 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void AttachKamikaze(); + +#line 219 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void RemoveKamikaze(); + +#line 224 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void DropKamikaze(); + +#line 252 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void PreMoving(); + +#line 269 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +void BlowUp(void); +#define STATE_CWoman_FlyFire 0x01400000 + BOOL +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FlyFire(const CEntityEvent &__eeInput); + BOOL H0x01400001_FlyFire_01(const CEntityEvent &__eeInput); + BOOL H0x01400002_FlyFire_02(const CEntityEvent &__eeInput); + BOOL H0x01400003_FlyFire_03(const CEntityEvent &__eeInput); + BOOL H0x01400004_FlyFire_04(const CEntityEvent &__eeInput); + BOOL H0x01400005_FlyFire_05(const CEntityEvent &__eeInput); + BOOL H0x01400006_FlyFire_06(const CEntityEvent &__eeInput); +#define STATE_CWoman_FlyHit 0x01400007 + BOOL +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FlyHit(const CEntityEvent &__eeInput); +#define STATE_CWoman_Death 0x01400008 + BOOL +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Death(const CEntityEvent &__eeInput); +#define STATE_CWoman_AirToGround 0x01400009 + BOOL +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +AirToGround(const CEntityEvent &__eeInput); +#define STATE_CWoman_FlyOnEnemy 0x0140000a + BOOL +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FlyOnEnemy(const CEntityEvent &__eeInput); + BOOL H0x0140000b_FlyOnEnemy_01(const CEntityEvent &__eeInput); + BOOL H0x0140000c_FlyOnEnemy_02(const CEntityEvent &__eeInput); + BOOL H0x0140000d_FlyOnEnemy_03(const CEntityEvent &__eeInput); + BOOL H0x0140000e_FlyOnEnemy_04(const CEntityEvent &__eeInput); +#define STATE_CWoman_GroundFire 0x0140000f + BOOL +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +GroundFire(const CEntityEvent &__eeInput); + BOOL H0x01400010_GroundFire_01(const CEntityEvent &__eeInput); + BOOL H0x01400011_GroundFire_02(const CEntityEvent &__eeInput); + BOOL H0x01400012_GroundFire_03(const CEntityEvent &__eeInput); + BOOL H0x01400013_GroundFire_04(const CEntityEvent &__eeInput); + BOOL H0x01400014_GroundFire_05(const CEntityEvent &__eeInput); + BOOL H0x01400015_GroundFire_06(const CEntityEvent &__eeInput); +#define STATE_CWoman_GroundHit 0x01400016 + BOOL +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +GroundHit(const CEntityEvent &__eeInput); + BOOL H0x01400017_GroundHit_01(const CEntityEvent &__eeInput); + BOOL H0x01400018_GroundHit_02(const CEntityEvent &__eeInput); + BOOL H0x01400019_GroundHit_03(const CEntityEvent &__eeInput); + BOOL H0x0140001a_GroundHit_04(const CEntityEvent &__eeInput); +#define STATE_CWoman_Main 1 + BOOL +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Main(const CEntityEvent &__eeInput); + BOOL H0x0140001b_Main_01(const CEntityEvent &__eeInput); + BOOL H0x0140001c_Main_02(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_Woman_INCLUDED diff --git a/Sources/EntitiesMP/Woman_tables.h b/Sources/EntitiesMP/Woman_tables.h new file mode 100644 index 0000000..3aba4c4 --- /dev/null +++ b/Sources/EntitiesMP/Woman_tables.h @@ -0,0 +1,107 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CWoman + +CEntityProperty CWoman_properties[] = { + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000140<<8)+10, offsetof(CWoman, m_bKamikazeCarrier), "Kamikaze Carrier", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_RANGE, NULL, (0x00000140<<8)+11, offsetof(CWoman, m_rKamikazeDropDistance), "Kamikaze Drop Range", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000140<<8)+20, offsetof(CWoman, m_bKamikazeAttached), "", 0, 0, 0), +}; +#define CWoman_propertiesct ARRAYCOUNT(CWoman_properties) + +CEntityComponent CWoman_components[] = { +#define CLASS_BASE ((0x00000140<<8)+0) + CEntityComponent(ECT_CLASS, CLASS_BASE, "EFNM" "Classes\\EnemyFly.ecl"), +#define MODEL_WOMAN ((0x00000140<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_WOMAN, "EFNM" "ModelsMP\\Enemies\\Woman\\Woman.mdl"), +#define TEXTURE_WOMAN ((0x00000140<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_WOMAN, "EFNM" "Models\\Enemies\\Woman\\Woman.tex"), +#define CLASS_PROJECTILE ((0x00000140<<8)+3) + CEntityComponent(ECT_CLASS, CLASS_PROJECTILE, "EFNM" "Classes\\Projectile.ecl"), +#define CLASS_HEADMAN ((0x00000140<<8)+5) + CEntityComponent(ECT_CLASS, CLASS_HEADMAN, "EFNM" "Classes\\Headman.ecl"), +#define MODEL_HEADMAN ((0x00000140<<8)+7) + CEntityComponent(ECT_MODEL, MODEL_HEADMAN, "EFNM" "Models\\Enemies\\Headman\\Headman.mdl"), +#define TEXTURE_HEADMAN ((0x00000140<<8)+8) + CEntityComponent(ECT_TEXTURE, TEXTURE_HEADMAN, "EFNM" "Models\\Enemies\\Headman\\Kamikaze.tex"), +#define MODEL_BOMB ((0x00000140<<8)+9) + CEntityComponent(ECT_MODEL, MODEL_BOMB, "EFNM" "Models\\Enemies\\Headman\\Projectile\\Bomb.mdl"), +#define TEXTURE_BOMB ((0x00000140<<8)+10) + CEntityComponent(ECT_TEXTURE, TEXTURE_BOMB, "EFNM" "Models\\Enemies\\Headman\\Projectile\\Bomb.tex"), +#define SOUND_IDLE ((0x00000140<<8)+50) + CEntityComponent(ECT_SOUND, SOUND_IDLE, "EFNM" "Models\\Enemies\\Woman\\Sounds\\Idle.wav"), +#define SOUND_SIGHT ((0x00000140<<8)+51) + CEntityComponent(ECT_SOUND, SOUND_SIGHT, "EFNM" "Models\\Enemies\\Woman\\Sounds\\Sight.wav"), +#define SOUND_WOUND ((0x00000140<<8)+52) + CEntityComponent(ECT_SOUND, SOUND_WOUND, "EFNM" "Models\\Enemies\\Woman\\Sounds\\Wound.wav"), +#define SOUND_FIRE ((0x00000140<<8)+53) + CEntityComponent(ECT_SOUND, SOUND_FIRE, "EFNM" "Models\\Enemies\\Woman\\Sounds\\Fire.wav"), +#define SOUND_KICK ((0x00000140<<8)+54) + CEntityComponent(ECT_SOUND, SOUND_KICK, "EFNM" "Models\\Enemies\\Woman\\Sounds\\Kick.wav"), +#define SOUND_DEATH ((0x00000140<<8)+55) + CEntityComponent(ECT_SOUND, SOUND_DEATH, "EFNM" "Models\\Enemies\\Woman\\Sounds\\Death.wav"), +}; +#define CWoman_componentsct ARRAYCOUNT(CWoman_components) + +CEventHandlerEntry CWoman_handlers[] = { + {0x01400000, STATE_CEnemyFly_FlyFire, CEntity::pEventHandler(&CWoman:: +#line 280 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FlyFire),DEBUGSTRING("CWoman::FlyFire")}, + {0x01400001, -1, CEntity::pEventHandler(&CWoman::H0x01400001_FlyFire_01), DEBUGSTRING("CWoman::H0x01400001_FlyFire_01")}, + {0x01400002, -1, CEntity::pEventHandler(&CWoman::H0x01400002_FlyFire_02), DEBUGSTRING("CWoman::H0x01400002_FlyFire_02")}, + {0x01400003, -1, CEntity::pEventHandler(&CWoman::H0x01400003_FlyFire_03), DEBUGSTRING("CWoman::H0x01400003_FlyFire_03")}, + {0x01400004, -1, CEntity::pEventHandler(&CWoman::H0x01400004_FlyFire_04), DEBUGSTRING("CWoman::H0x01400004_FlyFire_04")}, + {0x01400005, -1, CEntity::pEventHandler(&CWoman::H0x01400005_FlyFire_05), DEBUGSTRING("CWoman::H0x01400005_FlyFire_05")}, + {0x01400006, -1, CEntity::pEventHandler(&CWoman::H0x01400006_FlyFire_06), DEBUGSTRING("CWoman::H0x01400006_FlyFire_06")}, + {0x01400007, STATE_CEnemyFly_FlyHit, CEntity::pEventHandler(&CWoman:: +#line 295 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FlyHit),DEBUGSTRING("CWoman::FlyHit")}, + {0x01400008, STATE_CEnemyFly_Death, CEntity::pEventHandler(&CWoman:: +#line 319 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Death),DEBUGSTRING("CWoman::Death")}, + {0x01400009, STATE_CEnemyFly_AirToGround, CEntity::pEventHandler(&CWoman:: +#line 324 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +AirToGround),DEBUGSTRING("CWoman::AirToGround")}, + {0x0140000a, -1, CEntity::pEventHandler(&CWoman:: +#line 329 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +FlyOnEnemy),DEBUGSTRING("CWoman::FlyOnEnemy")}, + {0x0140000b, -1, CEntity::pEventHandler(&CWoman::H0x0140000b_FlyOnEnemy_01), DEBUGSTRING("CWoman::H0x0140000b_FlyOnEnemy_01")}, + {0x0140000c, -1, CEntity::pEventHandler(&CWoman::H0x0140000c_FlyOnEnemy_02), DEBUGSTRING("CWoman::H0x0140000c_FlyOnEnemy_02")}, + {0x0140000d, -1, CEntity::pEventHandler(&CWoman::H0x0140000d_FlyOnEnemy_03), DEBUGSTRING("CWoman::H0x0140000d_FlyOnEnemy_03")}, + {0x0140000e, -1, CEntity::pEventHandler(&CWoman::H0x0140000e_FlyOnEnemy_04), DEBUGSTRING("CWoman::H0x0140000e_FlyOnEnemy_04")}, + {0x0140000f, STATE_CEnemyFly_GroundFire, CEntity::pEventHandler(&CWoman:: +#line 353 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +GroundFire),DEBUGSTRING("CWoman::GroundFire")}, + {0x01400010, -1, CEntity::pEventHandler(&CWoman::H0x01400010_GroundFire_01), DEBUGSTRING("CWoman::H0x01400010_GroundFire_01")}, + {0x01400011, -1, CEntity::pEventHandler(&CWoman::H0x01400011_GroundFire_02), DEBUGSTRING("CWoman::H0x01400011_GroundFire_02")}, + {0x01400012, -1, CEntity::pEventHandler(&CWoman::H0x01400012_GroundFire_03), DEBUGSTRING("CWoman::H0x01400012_GroundFire_03")}, + {0x01400013, -1, CEntity::pEventHandler(&CWoman::H0x01400013_GroundFire_04), DEBUGSTRING("CWoman::H0x01400013_GroundFire_04")}, + {0x01400014, -1, CEntity::pEventHandler(&CWoman::H0x01400014_GroundFire_05), DEBUGSTRING("CWoman::H0x01400014_GroundFire_05")}, + {0x01400015, -1, CEntity::pEventHandler(&CWoman::H0x01400015_GroundFire_06), DEBUGSTRING("CWoman::H0x01400015_GroundFire_06")}, + {0x01400016, STATE_CEnemyFly_GroundHit, CEntity::pEventHandler(&CWoman:: +#line 366 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +GroundHit),DEBUGSTRING("CWoman::GroundHit")}, + {0x01400017, -1, CEntity::pEventHandler(&CWoman::H0x01400017_GroundHit_01), DEBUGSTRING("CWoman::H0x01400017_GroundHit_01")}, + {0x01400018, -1, CEntity::pEventHandler(&CWoman::H0x01400018_GroundHit_02), DEBUGSTRING("CWoman::H0x01400018_GroundHit_02")}, + {0x01400019, -1, CEntity::pEventHandler(&CWoman::H0x01400019_GroundHit_03), DEBUGSTRING("CWoman::H0x01400019_GroundHit_03")}, + {0x0140001a, -1, CEntity::pEventHandler(&CWoman::H0x0140001a_GroundHit_04), DEBUGSTRING("CWoman::H0x0140001a_GroundHit_04")}, + {1, -1, CEntity::pEventHandler(&CWoman:: +#line 396 "D:/SE1_GPL/Sources/EntitiesMP/Woman.es" +Main),DEBUGSTRING("CWoman::Main")}, + {0x0140001b, -1, CEntity::pEventHandler(&CWoman::H0x0140001b_Main_01), DEBUGSTRING("CWoman::H0x0140001b_Main_01")}, + {0x0140001c, -1, CEntity::pEventHandler(&CWoman::H0x0140001c_Main_02), DEBUGSTRING("CWoman::H0x0140001c_Main_02")}, +}; +#define CWoman_handlersct ARRAYCOUNT(CWoman_handlers) + +CEntity *CWoman_New(void) { return new CWoman; }; +void CWoman_OnInitClass(void) {}; +void CWoman_OnEndClass(void) {}; +void CWoman_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CWoman_OnWorldEnd(CWorld *pwo) {}; +void CWoman_OnWorldInit(CWorld *pwo) {}; +void CWoman_OnWorldTick(CWorld *pwo) {}; +void CWoman_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CWoman, CEnemyFly, "Woman", "Thumbnails\\Woman.tbn", 0x00000140); +DECLARE_CTFILENAME(_fnmCWoman_tbn, "Thumbnails\\Woman.tbn"); diff --git a/Sources/EntitiesMP/WorldBase.cpp b/Sources/EntitiesMP/WorldBase.cpp new file mode 100644 index 0000000..beeb356 --- /dev/null +++ b/Sources/EntitiesMP/WorldBase.cpp @@ -0,0 +1,1577 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" + +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +// for error checking: +#include "EntitiesMP/SoundHolder.h" + +#include +#include +#line 17 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" + + +inline void Clear(EntityStats &es) {es.es_strName.Clear();}; +static CDynamicArray _aes; +static CAnimObject _aoLightningColor; + +EntityStats *FindStats(const CTString &strName) +{ + {FOREACHINDYNAMICARRAY(_aes, EntityStats, ites) { + EntityStats &es = *ites; + if (es.es_strName==strName) { + return &es; + } + }} + return NULL; +} + +static void MakeWorldStatistics(void) +{ + // get the world pointer + CWorld *pwo = (CWorld *)_pShell->GetINDEX("pwoCurrentWorld"); + // if there is no current world + if (pwo==NULL) { + CPrintF("No current world.\n"); + return; + } + + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(pwo->wo_cenEntities, CEntity, iten) { + // get its stats + EntityStats esCurrent; + BOOL bHasStats = iten->FillEntityStatistics(&esCurrent); + // if no stats + if (!bHasStats) { + // skip it + continue; + } + + // find existing stats with same name + EntityStats *pesOld = FindStats(esCurrent.es_strName); + // if such stats exists + if (pesOld!=NULL) { + // update the existing stats + pesOld->es_ctCount += esCurrent.es_ctCount; + pesOld->es_ctAmmount += esCurrent.es_ctAmmount*esCurrent.es_ctCount; + pesOld->es_fValue += esCurrent.es_fValue*esCurrent.es_ctCount; + pesOld->es_iScore += esCurrent.es_iScore*esCurrent.es_ctCount; + // if this a new name + } else { + // create new stats + EntityStats &esNew = *_aes.New(); + esNew.es_strName = esCurrent.es_strName; + esNew.es_ctCount = esCurrent.es_ctCount; + esNew.es_ctAmmount = esCurrent.es_ctAmmount*esCurrent.es_ctCount; + esNew.es_fValue = esCurrent.es_fValue*esCurrent.es_ctCount; + esNew.es_iScore = esCurrent.es_iScore*esCurrent.es_ctCount; + } + }} + + // dump all stats + try { + CTFileStream strm; + CTFileName fnm = CTString("Temp\\Statistics.txt"); + strm.Create_t(fnm); + CTString strLine; + strLine.PrintF("%-40s: %8s %8s %10s %10s", + "name", "count", "ammount", "health", "score"); + strm.PutLine_t(strLine); + {FOREACHINDYNAMICARRAY(_aes, EntityStats, ites) { + EntityStats &es = *ites; + CTString strLine; + strLine.PrintF("%-40s: %8d %8d %10g %10d", + es.es_strName, es.es_ctCount, es.es_ctAmmount, es.es_fValue, es.es_iScore); + strm.PutLine_t(strLine); + }} + CPrintF("Dumped to '%s'\n", CTString(fnm)); + } catch (char *strError) { + CPrintF("Error: %s\n", strError); + } + + _aes.Clear(); +} + +static void ReoptimizeAllBrushes(void) +{ + // get the world pointer + CWorld *pwo = (CWorld *)_pShell->GetINDEX("pwoCurrentWorld"); + // if there is no current world + if (pwo==NULL) { + CPrintF("No current world.\n"); + return; + } + + // for each brush in the world + FOREACHINDYNAMICARRAY(pwo->wo_baBrushes.ba_abrBrushes, CBrush3D, itbr) { + CBrush3D &br=*itbr; + // for each mip in the brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, itbr->br_lhBrushMips, itbm) { + // reoptimize it + itbm->Reoptimize(); + } + } + CPrintF("All brushes reoptimized.\n"); +} + +static void DoLevelSafetyChecks() +{ + + BOOL bWorldSettingsControllerExists = FALSE; + + CPrintF("\n**** BEGIN Level safety checking ****\n\n"); + + // get the world pointer + CWorld *pwo = (CWorld *)_pShell->GetINDEX("pwoCurrentWorld"); + // if there is no current world + if (pwo==NULL) { + CPrintF("Error - no current world.\n"); + return; + } + + CPrintF("STEP 1 - Checking model holders...\n"); + // for model holder in the world; + {FOREACHINDYNAMICCONTAINER(pwo->wo_cenEntities, CEntity, iten) { + if (IsOfClass(iten, "ModelHolder2")) { + CModelHolder2 *mh = (CModelHolder2*)&*iten; + FLOAT3D vPos = mh->GetPlacement().pl_PositionVector; + if (mh->m_penDestruction == NULL) { + CPrintF(" model holder '%s' at (%2.2f, %2.2f, %2.2f) has no destruction\n", mh->m_strName, vPos(1), vPos(2), vPos(3)); + } + } + }} + + CPrintF("STEP 2 - Checking sound holders...\n"); + // for each sound holder in the world + {FOREACHINDYNAMICCONTAINER(pwo->wo_cenEntities, CEntity, iten) { + if (IsOfClass(iten, "SoundHolder")) { + CSoundHolder *sh = (CSoundHolder *)&*iten; + FLOAT3D vPos = sh->GetPlacement().pl_PositionVector; + if (sh->m_fnSound == CTFILENAME("Sounds\\Default.wav")) { + CPrintF(" sound holder '%s' at (%2.2f, %2.2f, %2.2f) has default sound!\n", sh->m_strName, vPos(1), vPos(2), vPos(3)); + } + } + }} + + + CPrintF("STEP 3 - Checking other important entities...\n"); + CWorldSettingsController *pwsc = NULL; + class CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) pwo->GetBackgroundViewer(); + if( penBcgViewer != NULL) { + // obtain world settings controller + pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController; + } + + if (pwsc!=NULL) { + CPrintF("\n OK! World settings controller exists!\n"); + } else { + CPrintF("\n ERROR! World settings controller does not exist (or isn't connected to the background viewer)!\n"); + } + + CPrintF("\n**** END Level safety checking ****\n"); + +} + +void SetPyramidPlateActivateAlpha(CWorld *pwo, INDEX iBlending, + TIME tmActivated, TIME tmDeactivated, BOOL bPulsate) +{ + TIME tmNow = _pTimer->CurrentTick(); + TIME tmStop = 2.0f; + FLOAT fRatio; + + // get alpha + if( tmNow>tmDeactivated) + { + // if plate is deactivated + if( tmNow>tmDeactivated+tmStop) + { + fRatio = 0; + } + // if fading out + else + { + fRatio = CalculateRatio(tmNow, tmDeactivated, tmDeactivated+tmStop, 0.0f, 1.0f); + } + } + else if( tmNow>tmActivated) + { + // if full visible + if( tmNow>tmActivated+tmStop) + { + fRatio = 1; + } + else + { + // fade in + fRatio = CalculateRatio(tmNow, tmActivated, tmActivated+tmStop, 1.0f, 0.0f); + } + } + // not yet activated + else + { + fRatio = 0; + } + FLOAT fSinFactor = 1.0f; + if( bPulsate) + { + fSinFactor = Sin((tmNow-tmActivated) * 720.0f)*0.5f+0.5f; + } + + UBYTE ub = UBYTE( fRatio*fSinFactor*255.0f); + // apply blend or add + if( pwo->wo_atbTextureBlendings[iBlending].tb_ubBlendingType == STXF_BLEND_ALPHA) + { + pwo->wo_atbTextureBlendings[iBlending].tb_colMultiply = C_WHITE|ub; + } + else if( pwo->wo_atbTextureBlendings[iBlending].tb_ubBlendingType == STXF_BLEND_ADD) + { + pwo->wo_atbTextureBlendings[iBlending].tb_colMultiply = RGBAToColor(ub,ub,ub,255); + } +} + +void SetPyramidMorphRoomAlpha(CWorld *pwo, INDEX iBlending, TIME tmActivated) +{ + TIME tmNow = _pTimer->CurrentTick(); + TIME tmDelta = tmNow-tmActivated; + FLOAT fRatio; + FLOAT tmAppear=10.0f; + + if( tmNow<=tmActivated) { return;} + + // get alpha + if( tmNow>=tmActivated+tmAppear) + { + fRatio = 1; + } + else + { + fRatio = CalculateRatio(tmNow, tmActivated, tmActivated+tmAppear, 1.0f, 0.0f); + } + + FLOAT fSinFactor = Sin(-90+tmDelta*90*(1.0f+tmDelta/tmAppear*4))*0.5f+0.5f; + //FLOAT fSinFactor = Sin(-90+90*tmDelta)*0.5f+0.5f; + //UBYTE ub = fSinFactor*255.0f; + UBYTE ub = UBYTE((fRatio+(1.0f-fRatio)*fSinFactor)*255.0f); + + // apply blend or add + if( pwo->wo_atbTextureBlendings[iBlending].tb_ubBlendingType == STXF_BLEND_ALPHA) + { + pwo->wo_atbTextureBlendings[iBlending].tb_colMultiply = C_WHITE|ub; + } + else if( pwo->wo_atbTextureBlendings[iBlending].tb_ubBlendingType == STXF_BLEND_ADD) + { + pwo->wo_atbTextureBlendings[iBlending].tb_colMultiply = RGBAToColor(ub,ub,ub,255); + } +} + +void CWorldBase_OnWorldInit(CWorld *pwo) +{ + pwo->wo_attTextureTransformations[0].tt_strName = "None"; + pwo->wo_attTextureTransformations[1].tt_strName = "R Extremly Slow"; + pwo->wo_attTextureTransformations[2].tt_strName = "R Very Slow"; + pwo->wo_attTextureTransformations[3].tt_strName = "R Slow"; + pwo->wo_attTextureTransformations[4].tt_strName = "R Medium"; + pwo->wo_attTextureTransformations[5].tt_strName = "R Fast"; + pwo->wo_attTextureTransformations[6].tt_strName = "R Very Fast"; + pwo->wo_attTextureTransformations[7].tt_strName = "R Extremly Fast"; + + pwo->wo_attTextureTransformations[8].tt_strName = "Dummy 1"; + pwo->wo_attTextureTransformations[9].tt_strName = "Dummy 2"; + pwo->wo_attTextureTransformations[10].tt_strName = "Dummy 3"; + + pwo->wo_attTextureTransformations[11].tt_strName = "Water movement extremly slow"; + pwo->wo_attTextureTransformations[12].tt_strName = "Water movement very slow"; + pwo->wo_attTextureTransformations[13].tt_strName = "Water movement slow"; + pwo->wo_attTextureTransformations[14].tt_strName = "Water movement normal"; + pwo->wo_attTextureTransformations[15].tt_strName = "Water movement fast"; + + pwo->wo_attTextureTransformations[16].tt_strName = "Stormy sky appearing"; + + pwo->wo_attTextureTransformations[17].tt_strName = "Rotation Left 1"; + pwo->wo_attTextureTransformations[18].tt_strName = "Rotation Left 2"; + pwo->wo_attTextureTransformations[19].tt_strName = "Rotation Left 3"; + pwo->wo_attTextureTransformations[20].tt_strName = "Rotation Left 4"; + pwo->wo_attTextureTransformations[21].tt_strName = "Rotation Left 5"; + pwo->wo_attTextureTransformations[22].tt_strName = "Rotation Left 6"; + pwo->wo_attTextureTransformations[23].tt_strName = "Rotation Left 7"; + pwo->wo_attTextureTransformations[24].tt_strName = "Rotation Left 8"; + pwo->wo_attTextureTransformations[25].tt_strName = "Rotation Left 9"; + pwo->wo_attTextureTransformations[26].tt_strName = "Rotation Left 10"; + + pwo->wo_attTextureTransformations[27].tt_strName = "Rotation Right 1"; + pwo->wo_attTextureTransformations[28].tt_strName = "Rotation Right 2"; + pwo->wo_attTextureTransformations[29].tt_strName = "Rotation Right 3"; + pwo->wo_attTextureTransformations[30].tt_strName = "Rotation Right 4"; + pwo->wo_attTextureTransformations[31].tt_strName = "Rotation Right 5"; + pwo->wo_attTextureTransformations[32].tt_strName = "Rotation Right 6"; + pwo->wo_attTextureTransformations[33].tt_strName = "Rotation Right 7"; + pwo->wo_attTextureTransformations[34].tt_strName = "Rotation Right 8"; + pwo->wo_attTextureTransformations[35].tt_strName = "Rotation Right 9"; + pwo->wo_attTextureTransformations[36].tt_strName = "Rotation Right 10"; + + pwo->wo_attTextureTransformations[37].tt_strName = "D Extremly Slow"; + pwo->wo_attTextureTransformations[38].tt_strName = "D Very Slow"; + pwo->wo_attTextureTransformations[39].tt_strName = "D Slow"; + pwo->wo_attTextureTransformations[40].tt_strName = "D Medium"; + pwo->wo_attTextureTransformations[41].tt_strName = "D Fast"; + pwo->wo_attTextureTransformations[42].tt_strName = "D Very Fast"; + pwo->wo_attTextureTransformations[43].tt_strName = "D Extremly Fast"; + pwo->wo_attTextureTransformations[44].tt_strName = "D Super Fast"; + pwo->wo_attTextureTransformations[45].tt_strName = "D Abnormaly Fast"; + +// static + pwo->wo_atbTextureBlendings[0].tb_strName = "Opaque"; + pwo->wo_atbTextureBlendings[0].tb_ubBlendingType = STXF_BLEND_OPAQUE; + + pwo->wo_atbTextureBlendings[1].tb_strName = "Shade"; + pwo->wo_atbTextureBlendings[1].tb_ubBlendingType = STXF_BLEND_SHADE; + + pwo->wo_atbTextureBlendings[2].tb_strName = "Blend"; + pwo->wo_atbTextureBlendings[2].tb_ubBlendingType = STXF_BLEND_ALPHA; + + pwo->wo_atbTextureBlendings[3].tb_strName = "Add"; + pwo->wo_atbTextureBlendings[3].tb_ubBlendingType = STXF_BLEND_ADD; +// pulsating + pwo->wo_atbTextureBlendings[4].tb_strName = "Shade pulsating"; + pwo->wo_atbTextureBlendings[4].tb_ubBlendingType = STXF_BLEND_SHADE; + pwo->wo_atbTextureBlendings[4].tb_colMultiply = 0x808080FF; + + pwo->wo_atbTextureBlendings[5].tb_strName = "Blend pulsating full"; + pwo->wo_atbTextureBlendings[5].tb_ubBlendingType = STXF_BLEND_ALPHA; + pwo->wo_atbTextureBlendings[5].tb_colMultiply = C_WHITE|0x80; + + pwo->wo_atbTextureBlendings[6].tb_strName = "Add pulsating"; + pwo->wo_atbTextureBlendings[6].tb_ubBlendingType = STXF_BLEND_ADD; + pwo->wo_atbTextureBlendings[6].tb_colMultiply = 0x808080FF; + + pwo->wo_atbTextureBlendings[7].tb_strName = "Blend pulsating half"; + pwo->wo_atbTextureBlendings[7].tb_ubBlendingType = STXF_BLEND_ALPHA; + pwo->wo_atbTextureBlendings[7].tb_colMultiply = C_WHITE|0xC0; + + pwo->wo_atbTextureBlendings[8].tb_strName = "Wsc blend"; + pwo->wo_atbTextureBlendings[8].tb_ubBlendingType = STXF_BLEND_ALPHA; + pwo->wo_atbTextureBlendings[8].tb_colMultiply = C_WHITE|0x00; + + pwo->wo_atbTextureBlendings[9].tb_strName = "Wsc shade"; + pwo->wo_atbTextureBlendings[9].tb_ubBlendingType = STXF_BLEND_SHADE; + pwo->wo_atbTextureBlendings[9].tb_colMultiply = C_WHITE|0xFF; + + pwo->wo_atbTextureBlendings[10].tb_strName = "Pyramid plate appearing"; + pwo->wo_atbTextureBlendings[10].tb_ubBlendingType = STXF_BLEND_ALPHA; + pwo->wo_atbTextureBlendings[10].tb_colMultiply = C_WHITE|0x00; + + pwo->wo_atbTextureBlendings[11].tb_strName = "Activated plate 1"; + pwo->wo_atbTextureBlendings[11].tb_ubBlendingType = STXF_BLEND_ADD; + pwo->wo_atbTextureBlendings[11].tb_colMultiply = C_BLACK|CT_OPAQUE; + + pwo->wo_atbTextureBlendings[12].tb_strName = "Activated plate 2"; + pwo->wo_atbTextureBlendings[12].tb_ubBlendingType = STXF_BLEND_ADD; + pwo->wo_atbTextureBlendings[12].tb_colMultiply = C_BLACK|CT_OPAQUE; + + pwo->wo_atbTextureBlendings[13].tb_strName = "Activated plate 3"; + pwo->wo_atbTextureBlendings[13].tb_ubBlendingType = STXF_BLEND_ADD; + pwo->wo_atbTextureBlendings[13].tb_colMultiply = C_BLACK|CT_OPAQUE; + + pwo->wo_atbTextureBlendings[14].tb_strName = "Activated plate 4"; + pwo->wo_atbTextureBlendings[14].tb_ubBlendingType = STXF_BLEND_ADD; + pwo->wo_atbTextureBlendings[14].tb_colMultiply = C_BLACK|CT_OPAQUE; + + pwo->wo_atbTextureBlendings[15].tb_strName = "Activate pyramid morph room"; + pwo->wo_atbTextureBlendings[15].tb_ubBlendingType = STXF_BLEND_ALPHA; + pwo->wo_atbTextureBlendings[15].tb_colMultiply = C_WHITE|0x00; + + pwo->wo_aitIlluminationTypes[0].it_strName = "None"; + pwo->wo_aitIlluminationTypes[1].it_strName = "Vitraj 1"; + pwo->wo_aitIlluminationTypes[2].it_strName = "Vitraj 2"; + pwo->wo_aitIlluminationTypes[3].it_strName = "Vitraj 3"; + pwo->wo_aitIlluminationTypes[4].it_strName = "Lava 1"; + pwo->wo_aitIlluminationTypes[5].it_strName = "Lava 2"; + pwo->wo_aitIlluminationTypes[6].it_strName = "Lava 3"; + pwo->wo_aitIlluminationTypes[7].it_strName = "Misc 1"; + pwo->wo_aitIlluminationTypes[8].it_strName = "Misc 2"; + pwo->wo_aitIlluminationTypes[9].it_strName = "Misc 3"; + + // surfaces + + pwo->wo_astSurfaceTypes[0].st_strName = "Standard"; + pwo->wo_astSurfaceTypes[0].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[0].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[0].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[0].st_fClimbSlopeCos = Cos(45.0f); + + pwo->wo_astSurfaceTypes[1].st_strName = "Ice"; + pwo->wo_astSurfaceTypes[1].st_fFriction = 0.045f; + pwo->wo_astSurfaceTypes[1].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[1].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[1].st_fClimbSlopeCos = Cos(5.0f); + + pwo->wo_astSurfaceTypes[2].st_strName = "Standard - no step"; + pwo->wo_astSurfaceTypes[2].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[2].st_fStairsHeight = -0.2f; + pwo->wo_astSurfaceTypes[2].st_fJumpSlopeCos = Cos(10.0f); + pwo->wo_astSurfaceTypes[2].st_fClimbSlopeCos = Cos(10.0f); + + pwo->wo_astSurfaceTypes[3].st_strName = "Standard - high stairs"; + pwo->wo_astSurfaceTypes[3].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[3].st_fStairsHeight = 2.0f; + pwo->wo_astSurfaceTypes[3].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[3].st_fClimbSlopeCos = Cos(45.0f); + + pwo->wo_astSurfaceTypes[4].st_strName = "Ice climbable slope"; + pwo->wo_astSurfaceTypes[4].st_fFriction = 0.05f; + pwo->wo_astSurfaceTypes[4].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[4].st_fJumpSlopeCos = Cos(15.0f); + pwo->wo_astSurfaceTypes[4].st_fClimbSlopeCos = Cos(15.0f); + + pwo->wo_astSurfaceTypes[5].st_strName = "Ice sliding slope"; + pwo->wo_astSurfaceTypes[5].st_fFriction = 0.001f; + pwo->wo_astSurfaceTypes[5].st_fStairsHeight = 0.0f; + pwo->wo_astSurfaceTypes[5].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[5].st_fClimbSlopeCos = Cos(5.0f); + + pwo->wo_astSurfaceTypes[6].st_strName = "Ice less sliding"; + pwo->wo_astSurfaceTypes[6].st_fFriction = 0.06f; + pwo->wo_astSurfaceTypes[6].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[6].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[6].st_fClimbSlopeCos = Cos(5.0f); + + pwo->wo_astSurfaceTypes[7].st_strName = "Roller coaster"; + pwo->wo_astSurfaceTypes[7].st_fFriction = 0.1f; + pwo->wo_astSurfaceTypes[7].st_fStairsHeight = 0.0f; + pwo->wo_astSurfaceTypes[7].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[7].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[7].st_ulFlags = STF_SLIDEDOWNSLOPE; + + pwo->wo_astSurfaceTypes[8].st_strName = "Lava"; + pwo->wo_astSurfaceTypes[8].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[8].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[8].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[8].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[8].st_iWalkDamageType = DMT_BURNING; + pwo->wo_astSurfaceTypes[8].st_fWalkDamageAmount = 2.0f; + pwo->wo_astSurfaceTypes[8].st_tmWalkDamageFrequency = 0.5f; + + ASSERT(9==SURFACE_SAND); + pwo->wo_astSurfaceTypes[9].st_strName = "Sand"; + pwo->wo_astSurfaceTypes[9].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[9].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[9].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[9].st_fClimbSlopeCos = Cos(45.0f); + + pwo->wo_astSurfaceTypes[10].st_strName = "Clibamble Slope"; + pwo->wo_astSurfaceTypes[10].st_fFriction = 2.0f; + pwo->wo_astSurfaceTypes[10].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[10].st_fJumpSlopeCos = Cos(60.0f); + pwo->wo_astSurfaceTypes[10].st_fClimbSlopeCos = Cos(60.0f); + + pwo->wo_astSurfaceTypes[11].st_strName = "Standard - no impact"; + pwo->wo_astSurfaceTypes[11].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[11].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[11].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[11].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[11].st_ulFlags = STF_NOIMPACT; + + ASSERT(12==SURFACE_WATER); + pwo->wo_astSurfaceTypes[12].st_strName = "Water"; + pwo->wo_astSurfaceTypes[12].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[12].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[12].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[12].st_fClimbSlopeCos = Cos(45.0f); + + ASSERT(13==SURFACE_RED_SAND); + pwo->wo_astSurfaceTypes[13].st_strName = "Red sand"; + pwo->wo_astSurfaceTypes[13].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[13].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[13].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[13].st_fClimbSlopeCos = Cos(45.0f); + + pwo->wo_astSurfaceTypes[14].st_strName = "Ice sliding slope no impact"; + pwo->wo_astSurfaceTypes[14].st_fFriction = 0.001f; + pwo->wo_astSurfaceTypes[14].st_fStairsHeight = 0.0f; + pwo->wo_astSurfaceTypes[14].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[14].st_fClimbSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[14].st_ulFlags = STF_NOIMPACT; + + pwo->wo_astSurfaceTypes[15].st_strName = "Roller coaster no impact"; + pwo->wo_astSurfaceTypes[15].st_fFriction = 0.1f; + pwo->wo_astSurfaceTypes[15].st_fStairsHeight = 0.0f; + pwo->wo_astSurfaceTypes[15].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[15].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[15].st_ulFlags = STF_SLIDEDOWNSLOPE | STF_NOIMPACT; + + pwo->wo_astSurfaceTypes[16].st_strName = "Standard - high stairs no impact"; + pwo->wo_astSurfaceTypes[16].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[16].st_fStairsHeight = 2.0f; + pwo->wo_astSurfaceTypes[16].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[16].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[16].st_ulFlags = STF_NOIMPACT; + + ASSERT(17==SURFACE_GRASS); + pwo->wo_astSurfaceTypes[17].st_strName = "Grass"; + pwo->wo_astSurfaceTypes[17].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[17].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[17].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[17].st_fClimbSlopeCos = Cos(45.0f); + + ASSERT(18==SURFACE_WOOD); + pwo->wo_astSurfaceTypes[18].st_strName = "Wood"; + pwo->wo_astSurfaceTypes[18].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[18].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[18].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[18].st_fClimbSlopeCos = Cos(45.0f); + + ASSERT(19==SURFACE_GRASS_SLIDING); + pwo->wo_astSurfaceTypes[19].st_strName = "Grass sliding"; + pwo->wo_astSurfaceTypes[19].st_fFriction = 0.1f; + pwo->wo_astSurfaceTypes[19].st_fStairsHeight = 0.0f; + pwo->wo_astSurfaceTypes[19].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[19].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[19].st_ulFlags = STF_SLIDEDOWNSLOPE; + + ASSERT(20==SURFACE_GRASS_NOIMPACT); + pwo->wo_astSurfaceTypes[20].st_strName = "Grass no impact"; + pwo->wo_astSurfaceTypes[20].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[20].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[20].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[20].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[20].st_ulFlags = STF_NOIMPACT; + + ASSERT(21==SURFACE_SNOW); + pwo->wo_astSurfaceTypes[21].st_strName = "Snow"; + pwo->wo_astSurfaceTypes[21].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[21].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[21].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[21].st_fClimbSlopeCos = Cos(45.0f); + + // contents + pwo->wo_actContentTypes[0].ct_strName = "Air"; + pwo->wo_actContentTypes[0].ct_fDensity = 0.0f; + pwo->wo_actContentTypes[0].ct_fFluidFriction = 0.0f; + pwo->wo_actContentTypes[0].ct_fControlMultiplier = 1.0f; + pwo->wo_actContentTypes[0].ct_fSpeedMultiplier = 1.0f; + pwo->wo_actContentTypes[0].ct_fDrowningDamageAmount = 10.0f; + pwo->wo_actContentTypes[0].ct_tmDrowningDamageDelay = 1.0f; + pwo->wo_actContentTypes[0].ct_ulFlags = CTF_FLYABLE|CTF_BREATHABLE_LUNGS; + + pwo->wo_actContentTypes[1].ct_strName = "Water"; + pwo->wo_actContentTypes[1].ct_fDensity = 1000.0f; + pwo->wo_actContentTypes[1].ct_fFluidFriction = 0.0f; + pwo->wo_actContentTypes[1].ct_fControlMultiplier = 2.0f; + pwo->wo_actContentTypes[1].ct_fSpeedMultiplier = 0.75f; + pwo->wo_actContentTypes[1].ct_fDrowningDamageAmount = 10.0f; + pwo->wo_actContentTypes[1].ct_tmDrowningDamageDelay = 1.0f; + pwo->wo_actContentTypes[1].ct_ulFlags = CTF_BREATHABLE_GILLS|CTF_SWIMABLE|CTF_FADESPINNING; + + pwo->wo_actContentTypes[2].ct_strName = "Lava"; + pwo->wo_actContentTypes[2].ct_fDensity = 800.0f; + pwo->wo_actContentTypes[2].ct_fFluidFriction = 1.0f; + pwo->wo_actContentTypes[2].ct_fControlMultiplier = 2.0f; + pwo->wo_actContentTypes[2].ct_fSpeedMultiplier = 0.5f; + pwo->wo_actContentTypes[2].ct_fDrowningDamageAmount = 0.0f; + pwo->wo_actContentTypes[2].ct_tmDrowningDamageDelay = 1.0f; + pwo->wo_actContentTypes[2].ct_iSwimDamageType = DMT_BURNING; + pwo->wo_actContentTypes[2].ct_fSwimDamageAmount = 50.0f; + pwo->wo_actContentTypes[2].ct_tmSwimDamageFrequency = 0.25f; + pwo->wo_actContentTypes[2].ct_ulFlags = CTF_FADESPINNING; + + pwo->wo_actContentTypes[3].ct_strName = "Cold Water"; + pwo->wo_actContentTypes[3].ct_fDensity = 1000.0f; + pwo->wo_actContentTypes[3].ct_fFluidFriction = 0.0f; + pwo->wo_actContentTypes[3].ct_fControlMultiplier = 2.0f; + pwo->wo_actContentTypes[3].ct_fSpeedMultiplier = 0.75f; + pwo->wo_actContentTypes[3].ct_fDrowningDamageAmount = 10.0f; + pwo->wo_actContentTypes[3].ct_tmDrowningDamageDelay = 1.0f; + pwo->wo_actContentTypes[3].ct_iSwimDamageType = DMT_FREEZING; + pwo->wo_actContentTypes[3].ct_fSwimDamageAmount = 1.0f; + pwo->wo_actContentTypes[3].ct_tmSwimDamageDelay = 5.0f; + pwo->wo_actContentTypes[3].ct_tmSwimDamageFrequency = 1.0f; + pwo->wo_actContentTypes[3].ct_ulFlags = CTF_BREATHABLE_GILLS|CTF_SWIMABLE|CTF_FADESPINNING; + + pwo->wo_actContentTypes[4].ct_strName = "Spikes"; + pwo->wo_actContentTypes[4].ct_fDensity = 500.0f; + pwo->wo_actContentTypes[4].ct_fFluidFriction = 0.5f; + pwo->wo_actContentTypes[4].ct_fControlMultiplier = 1.0f; + pwo->wo_actContentTypes[4].ct_fSpeedMultiplier = 0.75f; + pwo->wo_actContentTypes[4].ct_iKillDamageType = DMT_SPIKESTAB; + pwo->wo_actContentTypes[4].ct_fKillImmersion = 0.5f; + pwo->wo_actContentTypes[4].ct_ulFlags = CTF_BREATHABLE_LUNGS|CTF_FADESPINNING; + + pwo->wo_actContentTypes[5].ct_strName = "Desert heat"; + pwo->wo_actContentTypes[5].ct_fDensity = 0.0f; + pwo->wo_actContentTypes[5].ct_fFluidFriction = 0.0f; + pwo->wo_actContentTypes[5].ct_fControlMultiplier = 1.0f; + pwo->wo_actContentTypes[5].ct_fSpeedMultiplier = 1.0f; + pwo->wo_actContentTypes[5].ct_iSwimDamageType = DMT_HEAT; + pwo->wo_actContentTypes[5].ct_fSwimDamageAmount = 10.0f; + pwo->wo_actContentTypes[5].ct_tmSwimDamageDelay = 10.0f; + pwo->wo_actContentTypes[5].ct_tmSwimDamageFrequency = 2.0f; + pwo->wo_actContentTypes[5].ct_ulFlags = CTF_FLYABLE|CTF_BREATHABLE_LUNGS; + + pwo->wo_actContentTypes[6].ct_strName = "Lava (-10HP/SEC)"; + pwo->wo_actContentTypes[6].ct_fDensity = 1000.0f; + pwo->wo_actContentTypes[6].ct_fFluidFriction = 0.0f; + pwo->wo_actContentTypes[6].ct_fControlMultiplier = 2.0f; + pwo->wo_actContentTypes[6].ct_fSpeedMultiplier = 0.75f; + pwo->wo_actContentTypes[6].ct_fDrowningDamageAmount = 0.0f; + pwo->wo_actContentTypes[6].ct_tmDrowningDamageDelay = 1.0f; + pwo->wo_actContentTypes[6].ct_iSwimDamageType = DMT_BURNING; + pwo->wo_actContentTypes[6].ct_fSwimDamageAmount = 5.0f; + pwo->wo_actContentTypes[6].ct_tmSwimDamageFrequency = 0.5f; + pwo->wo_actContentTypes[6].ct_ulFlags = CTF_SWIMABLE|CTF_FADESPINNING; + + // environments + pwo->wo_aetEnvironmentTypes[ 0].et_strName = "Normal"; + pwo->wo_aetEnvironmentTypes[ 0].et_iType = 1; + pwo->wo_aetEnvironmentTypes[ 0].et_fSize = 1.4f; + + pwo->wo_aetEnvironmentTypes[ 1].et_strName = "Generic"; + pwo->wo_aetEnvironmentTypes[ 1].et_iType = 0; + pwo->wo_aetEnvironmentTypes[ 1].et_fSize = 7.5f; + + pwo->wo_aetEnvironmentTypes[ 2].et_strName = "Small room"; + pwo->wo_aetEnvironmentTypes[ 2].et_iType = EAX_ENVIRONMENT_LIVINGROOM; + pwo->wo_aetEnvironmentTypes[ 2].et_fSize = 2.5f; + + pwo->wo_aetEnvironmentTypes[ 3].et_strName = "Medium room"; + pwo->wo_aetEnvironmentTypes[ 3].et_iType = EAX_ENVIRONMENT_STONEROOM; + pwo->wo_aetEnvironmentTypes[ 3].et_fSize = 11.6f; + + pwo->wo_aetEnvironmentTypes[ 4].et_strName = "Big room"; + pwo->wo_aetEnvironmentTypes[ 4].et_iType = EAX_ENVIRONMENT_AUDITORIUM; + pwo->wo_aetEnvironmentTypes[ 4].et_fSize = 21.6f; + + pwo->wo_aetEnvironmentTypes[ 5].et_strName = "Corridor"; + pwo->wo_aetEnvironmentTypes[ 5].et_iType = EAX_ENVIRONMENT_HALLWAY; + pwo->wo_aetEnvironmentTypes[ 5].et_fSize = 1.8f; + + pwo->wo_aetEnvironmentTypes[ 6].et_strName = "Arena"; + pwo->wo_aetEnvironmentTypes[ 6].et_iType = EAX_ENVIRONMENT_ARENA; + pwo->wo_aetEnvironmentTypes[ 6].et_fSize = 36.2f; + + pwo->wo_aetEnvironmentTypes[ 7].et_strName = "Long corridor"; + pwo->wo_aetEnvironmentTypes[ 7].et_iType = EAX_ENVIRONMENT_STONECORRIDOR; + pwo->wo_aetEnvironmentTypes[ 7].et_fSize = 13.5f; + + pwo->wo_aetEnvironmentTypes[ 8].et_strName = "Small canyon"; + pwo->wo_aetEnvironmentTypes[ 8].et_iType = EAX_ENVIRONMENT_QUARRY; + pwo->wo_aetEnvironmentTypes[ 8].et_fSize = 17.5f; + + pwo->wo_aetEnvironmentTypes[ 9].et_strName = "Big canyon"; + pwo->wo_aetEnvironmentTypes[ 9].et_iType = EAX_ENVIRONMENT_MOUNTAINS; + pwo->wo_aetEnvironmentTypes[ 9].et_fSize = 100.0f; + + pwo->wo_aetEnvironmentTypes[10].et_strName = "Open space"; + pwo->wo_aetEnvironmentTypes[10].et_iType = EAX_ENVIRONMENT_PLAIN; + pwo->wo_aetEnvironmentTypes[10].et_fSize = 42.5f; + + pwo->wo_aetEnvironmentTypes[11].et_strName = "Cave"; + pwo->wo_aetEnvironmentTypes[11].et_iType = EAX_ENVIRONMENT_CAVE; + pwo->wo_aetEnvironmentTypes[11].et_fSize = 14.6f; + + pwo->wo_aetEnvironmentTypes[12].et_strName = "Sewers"; + pwo->wo_aetEnvironmentTypes[12].et_iType = EAX_ENVIRONMENT_SEWERPIPE; + pwo->wo_aetEnvironmentTypes[12].et_fSize = 1.7f; + + pwo->wo_aetEnvironmentTypes[13].et_strName = "Underwater"; + pwo->wo_aetEnvironmentTypes[13].et_iType = EAX_ENVIRONMENT_UNDERWATER; + pwo->wo_aetEnvironmentTypes[13].et_fSize = 1.8f; + + // declare console variables + _pShell->DeclareSymbol("user void MakeWorldStatistics(void);", &MakeWorldStatistics); + _pShell->DeclareSymbol("user void ReoptimizeAllBrushes(void);", &ReoptimizeAllBrushes); + _pShell->DeclareSymbol("user void DoLevelSafetyChecks(void);", &DoLevelSafetyChecks); +} + +void CWorldBase_OnWorldRender(CWorld *pwo) +{ + // get current tick + TIME tmNow = _pTimer->GetLerpedCurrentTick(); + // wrap time to prevent texture coordinates to get unprecise + tmNow = fmod(tmNow, 600.0f); // (wrap every 10 minutes) + +// transformations + // right + pwo->wo_attTextureTransformations[1].tt_mdTransformation.md_fUOffset= 128/1024.0f*tmNow; + pwo->wo_attTextureTransformations[2].tt_mdTransformation.md_fUOffset= 256/1024.0f*tmNow; + pwo->wo_attTextureTransformations[3].tt_mdTransformation.md_fUOffset= 512/1024.0f*tmNow; + pwo->wo_attTextureTransformations[4].tt_mdTransformation.md_fUOffset=1024/1024.0f*tmNow; + pwo->wo_attTextureTransformations[5].tt_mdTransformation.md_fUOffset=2048/1024.0f*tmNow; + pwo->wo_attTextureTransformations[6].tt_mdTransformation.md_fUOffset=4096/1024.0f*tmNow; + pwo->wo_attTextureTransformations[7].tt_mdTransformation.md_fUOffset=8192/1024.0f*tmNow; + + // down + pwo->wo_attTextureTransformations[37].tt_mdTransformation.md_fVOffset= 128/1024.0f*tmNow; + pwo->wo_attTextureTransformations[38].tt_mdTransformation.md_fVOffset= 256/1024.0f*tmNow; + pwo->wo_attTextureTransformations[39].tt_mdTransformation.md_fVOffset= 512/1024.0f*tmNow; + pwo->wo_attTextureTransformations[40].tt_mdTransformation.md_fVOffset=1024/1024.0f*tmNow; + pwo->wo_attTextureTransformations[41].tt_mdTransformation.md_fVOffset=2048/1024.0f*tmNow; + pwo->wo_attTextureTransformations[42].tt_mdTransformation.md_fVOffset=4096/1024.0f*tmNow; + pwo->wo_attTextureTransformations[43].tt_mdTransformation.md_fVOffset=8192/1024.0f*tmNow; + pwo->wo_attTextureTransformations[44].tt_mdTransformation.md_fVOffset=8192*2/1024.0f*tmNow; + pwo->wo_attTextureTransformations[45].tt_mdTransformation.md_fVOffset=8192*4/1024.0f*tmNow; + + CMappingDefinitionUI mdui; + mdui.mdui_fUStretch = 1.0f; + mdui.mdui_fVStretch = 1.0f; + mdui.mdui_fUOffset = 0.0f; + mdui.mdui_fVOffset = 0.0f; + // rotations left + mdui.mdui_aURotation = 8192*1/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*1/1024.0f*tmNow; + pwo->wo_attTextureTransformations[17].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*2/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*2/1024.0f*tmNow; + pwo->wo_attTextureTransformations[18].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*4/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*4/1024.0f*tmNow; + pwo->wo_attTextureTransformations[19].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*8/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*8/1024.0f*tmNow; + pwo->wo_attTextureTransformations[20].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*16/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*16/1024.0f*tmNow; + pwo->wo_attTextureTransformations[21].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*32/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*32/1024.0f*tmNow; + pwo->wo_attTextureTransformations[22].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*64/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*64/1024.0f*tmNow; + pwo->wo_attTextureTransformations[23].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*128/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*128/1024.0f*tmNow; + pwo->wo_attTextureTransformations[24].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*256/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*256/1024.0f*tmNow; + pwo->wo_attTextureTransformations[25].tt_mdTransformation.FromUI(mdui); + // rotations right + mdui.mdui_aURotation = -8192*1/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*1/1024.0f*tmNow; + pwo->wo_attTextureTransformations[27].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*2/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*2/1024.0f*tmNow; + pwo->wo_attTextureTransformations[28].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*4/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*4/1024.0f*tmNow; + pwo->wo_attTextureTransformations[29].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*8/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*8/1024.0f*tmNow; + pwo->wo_attTextureTransformations[30].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*16/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*16/1024.0f*tmNow; + pwo->wo_attTextureTransformations[31].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*32/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*32/1024.0f*tmNow; + pwo->wo_attTextureTransformations[32].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*64/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*64/1024.0f*tmNow; + pwo->wo_attTextureTransformations[33].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*128/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*128/1024.0f*tmNow; + pwo->wo_attTextureTransformations[34].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*256/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*256/1024.0f*tmNow; + pwo->wo_attTextureTransformations[35].tt_mdTransformation.FromUI(mdui); +// blendings + FLOAT f = Abs(Sin(tmNow*AngleDeg(180.0f))); + pwo->wo_atbTextureBlendings[4].tb_colMultiply = RGBAToColor(f*255, f*255, f*255, 255); + pwo->wo_atbTextureBlendings[5].tb_colMultiply = C_WHITE|UBYTE(255*f); + pwo->wo_atbTextureBlendings[6].tb_colMultiply = RGBAToColor(f*255, f*255, f*255, 255); + pwo->wo_atbTextureBlendings[7].tb_colMultiply = C_WHITE|UBYTE(255*Lerp(0.5f, 1.0f, f)); + + pwo->wo_attTextureTransformations[11].tt_mdTransformation.md_fUOffset=Sin( tmNow*22)/30; + pwo->wo_attTextureTransformations[11].tt_mdTransformation.md_fVOffset=Cos( tmNow*26)/35; + + pwo->wo_attTextureTransformations[12].tt_mdTransformation.md_fUOffset=Sin( tmNow*32)/10; + pwo->wo_attTextureTransformations[12].tt_mdTransformation.md_fVOffset=Cos( tmNow*22)/15; + + pwo->wo_attTextureTransformations[13].tt_mdTransformation.md_fUOffset=Sin( tmNow*15)/7; + pwo->wo_attTextureTransformations[13].tt_mdTransformation.md_fVOffset=Cos( tmNow*25)/8; + + pwo->wo_attTextureTransformations[14].tt_mdTransformation.md_fUOffset=Sin( tmNow*32)/3; + pwo->wo_attTextureTransformations[14].tt_mdTransformation.md_fVOffset=Cos( tmNow*22)/3; + + pwo->wo_attTextureTransformations[15].tt_mdTransformation.md_fUOffset=Sin( tmNow*15); + pwo->wo_attTextureTransformations[15].tt_mdTransformation.md_fVOffset=Cos( tmNow*25); + + // ----------- Obtain world settings controller + CWorldSettingsController *pwsc = NULL; + // obtain bcg viewer + CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) pwo->GetBackgroundViewer(); + if( penBcgViewer != NULL) + { + // obtain world settings controller + pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController; + } + + // ***** Storm effects + // if world settings controller is valid + if( pwsc != NULL) + { + FLOAT fStormFactor = pwsc->GetStormFactor(); + COLOR colBlend = LerpColor( pwsc->m_colBlendStart, pwsc->m_colBlendStop, fStormFactor); + pwo->wo_atbTextureBlendings[8].tb_colMultiply = colBlend; + + // set world polygon shading multiplier + COLOR colShade = LerpColor( pwsc->m_colShadeStart, pwsc->m_colShadeStop, fStormFactor); + + // apply lightning FX + if( pwsc->m_tmLightningStart != -1) + { + FLOAT tmLightningLife = tmNow-pwsc->m_tmLightningStart; + _aoLightningColor.ao_tmAnimStart = pwsc->m_tmLightningStart; + COLOR colLightning = _aoLightningColor.GetFrame(); + // calculate lightning power factor + UBYTE ub = UBYTE( pwsc->m_fLightningPower*255); + COLOR colFactor = RGBToColor( ub, ub, ub) | CT_OPAQUE; + colLightning = MulColors( colLightning, colFactor); + colShade = AddColors( colShade, colLightning); + } + pwo->wo_atbTextureBlendings[9].tb_colMultiply = colShade; + } + + // ***** Pyramid blending effects + // if world settings controller is valid + if( pwsc != NULL) + { + // set alpha values for switch-controlled pyramid plate activating + SetPyramidPlateActivateAlpha(pwo, 10, pwsc->m_tmPyramidPlatesStart, 1e6, FALSE); + SetPyramidPlateActivateAlpha(pwo, 11, pwsc->m_tmActivatedPlate1, pwsc->m_tmDeactivatedPlate1, TRUE); + SetPyramidPlateActivateAlpha(pwo, 12, pwsc->m_tmActivatedPlate2, pwsc->m_tmDeactivatedPlate2, TRUE); + SetPyramidPlateActivateAlpha(pwo, 13, pwsc->m_tmActivatedPlate3, pwsc->m_tmDeactivatedPlate3, TRUE); + SetPyramidPlateActivateAlpha(pwo, 14, pwsc->m_tmActivatedPlate4, pwsc->m_tmDeactivatedPlate4, TRUE); + // pyramid morph room + SetPyramidMorphRoomAlpha(pwo, 15, pwsc->m_tmPyramidMorphRoomActivated); + } +}; + +void CWorldBase_OnInitClass(void) +{ + // init particle effects + InitParticles(); + try + { + // setup simple model shadow texture + _toSimpleModelShadow.SetData_t( CTFILENAME("Textures\\Effects\\Shadow\\SimpleModelShadow.tex")); + _aoLightningColor.SetData_t( CTFILENAME("Animations\\Lightning.ani")); + // we will use first animation in .ani file for lightning + _aoLightningColor.PlayAnim(0, AOF_NORESTART); + } + catch(char *strError) + { + FatalError(TRANS("Cannot load shadow texture: \n%s"), strError); + } +} + +void CWorldBase_OnEndClass(void) +{ + // close particle effects + CloseParticles(); +} + +class CFixedForce { +public: + CTString ff_strName; + class CForceStrength ff_fsGravity; + class CForceStrength ff_fsField; + + inline CFixedForce(CTString strName, + FLOAT3D vDirection, + FLOAT fAcceleration, + FLOAT fVelocity) + { + ff_strName = strName; + ff_fsGravity.fs_vDirection =vDirection; + ff_fsGravity.fs_fAcceleration =fAcceleration; + ff_fsGravity.fs_fVelocity =fVelocity; + } + +}; + +static CFixedForce affFixedForces[] = +{ + CFixedForce ("Normal D", FLOAT3D( 0,-1, 0), 30, 70), + CFixedForce ("Normal U", FLOAT3D( 0,+1, 0), 30, 70), + CFixedForce ("Normal N", FLOAT3D( 0, 0,-1), 30, 70), + CFixedForce ("Normal S", FLOAT3D( 0, 0,+1), 30, 70), + CFixedForce ("Normal E", FLOAT3D(-1, 0, 0), 30, 70), + CFixedForce ("Normal W", FLOAT3D(+1, 0, 0), 30, 70), + CFixedForce ("ZeroG", FLOAT3D(+1, 0, 0), 0, 0), + CFixedForce ("Unused", FLOAT3D(+1, 0, 0), 0, 0), + CFixedForce ("Unused", FLOAT3D(+1, 0, 0), 0, 0), + CFixedForce ("Unused", FLOAT3D(+1, 0, 0), 0, 0), +}; +static INDEX ctFixedForces = ARRAYCOUNT(affFixedForces); +extern void GetDefaultForce(INDEX iForce, const FLOAT3D &vPoint, + CForceStrength &fsGravity, CForceStrength &fsField) +{ + if (iForce= ulFirst ) && (slPropertyOffset <= ulLast )){ +#line 1024 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return (IsDerivedFromClass (penTarget , strClass )); +#line 1025 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1028 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +ulFirst = offsetof (CWorldBase , m_penGravity0 ); +#line 1029 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +ulLast = offsetof (CWorldBase , m_penGravity9 ); +#line 1030 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if((slPropertyOffset >= ulFirst ) && (slPropertyOffset <= ulLast )){ +#line 1031 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return +#line 1032 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +IsDerivedFromClass (penTarget , "Gravity Marker") || +#line 1033 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +IsDerivedFromClass (penTarget , "Gravity Router"); +#line 1034 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1037 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +ulFirst = offsetof (CWorldBase , m_penMirror0 ); +#line 1038 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +ulLast = offsetof (CWorldBase , m_penMirror4 ); +#line 1039 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +strClass = "Mirror Marker"; +#line 1040 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if((slPropertyOffset >= ulFirst ) && (slPropertyOffset <= ulLast )){ +#line 1041 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return (IsDerivedFromClass (penTarget , strClass )); +#line 1042 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1045 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +ulFirst = offsetof (CWorldBase , m_penFog0 ); +#line 1046 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +ulLast = offsetof (CWorldBase , m_penFog9 ); +#line 1047 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +strClass = "Fog Marker"; +#line 1048 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if((slPropertyOffset >= ulFirst ) && (slPropertyOffset <= ulLast )){ +#line 1049 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return (IsDerivedFromClass (penTarget , strClass )); +#line 1050 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1053 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +ulFirst = offsetof (CWorldBase , m_penHaze0 ); +#line 1054 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +ulLast = offsetof (CWorldBase , m_penHaze4 ); +#line 1055 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +strClass = "Haze Marker"; +#line 1056 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if((slPropertyOffset >= ulFirst ) && (slPropertyOffset <= ulLast )){ +#line 1057 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return (IsDerivedFromClass (penTarget , strClass )); +#line 1058 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1060 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return CEntity :: IsTargetValid (slPropertyOffset , penTarget ); +#line 1061 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1064 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +const CTString & CWorldBase::GetForceName(INDEX iForce) +#line 1065 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1066 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +static const CTString strDummyName (""); +#line 1067 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +static const CTString strMarkerUnused ("Marker not set"); +#line 1068 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctGravityMarkers = & m_penGravity9 - & m_penGravity0 + 1; +#line 1070 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iForce < ctFixedForces ){ +#line 1071 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return affFixedForces [ iForce ] . ff_strName ; +#line 1072 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +}else { +#line 1073 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iForce - ctFixedForces <= ctGravityMarkers ){ +#line 1074 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CEntity * pen = & * (& m_penGravity0 ) [ iForce - ctFixedForces ]; +#line 1075 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(pen != NULL ){ +#line 1076 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return pen -> GetForceName (0); +#line 1077 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +}else { +#line 1078 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return strMarkerUnused ; +#line 1079 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1081 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1082 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return strDummyName ; +#line 1083 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1084 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +void CWorldBase::GetForce(INDEX iForce,const FLOAT3D & vPoint, +#line 1087 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CForceStrength & fsGravity,CForceStrength & fsField) +#line 1088 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1089 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctGravityMarkers = & m_penGravity9 - & m_penGravity0 + 1; +#line 1090 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iForce < ctFixedForces ){ +#line 1091 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +fsGravity = affFixedForces [ iForce ] . ff_fsGravity ; +#line 1092 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +}else { +#line 1093 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iForce - ctFixedForces < ctGravityMarkers ){ +#line 1094 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CEntity * pen = & * (& m_penGravity0 ) [ iForce - ctFixedForces ]; +#line 1095 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(pen != NULL ){ +#line 1096 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +pen -> GetForce (0 , vPoint , fsGravity , fsField ); +#line 1097 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return ; +#line 1098 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1099 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1100 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +fsGravity . fs_fAcceleration = 30; +#line 1101 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +fsGravity . fs_fVelocity = 70; +#line 1102 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +fsGravity . fs_vDirection = FLOAT3D (1 , 0 , 0); +#line 1103 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1104 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +fsField . fs_fAcceleration = 0; +#line 1105 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +fsField . fs_fVelocity = 0; +#line 1106 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1109 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CEntity * CWorldBase::GetForceController(INDEX iForce) +#line 1110 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1111 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctGravityMarkers = & m_penGravity9 - & m_penGravity0 + 1; +#line 1112 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iForce < ctFixedForces ){ +#line 1113 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return NULL ; +#line 1114 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +}else { +#line 1115 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iForce - ctFixedForces < ctGravityMarkers ){ +#line 1116 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CEntity * pen = & * (& m_penGravity0 ) [ iForce - ctFixedForces ]; +#line 1117 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(pen != NULL ){ +#line 1118 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return pen -> GetForceController (0); +#line 1119 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1120 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1121 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1122 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return NULL ; +#line 1123 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1125 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +const CTString & CWorldBase::GetFogName(INDEX iFog) +#line 1126 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1127 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctFogMarkers = & m_penFog9 - & m_penFog0 + 1; +#line 1128 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +static const CTString strDummyName (""); +#line 1129 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +static const CTString strMarkerUnused ("Marker not set"); +#line 1130 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iFog < ctFogMarkers ){ +#line 1131 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CFogMarker * pfm = (CFogMarker *) & * (& m_penFog0 ) [ iFog ]; +#line 1132 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(pfm != NULL ){ +#line 1133 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return pfm -> GetFogName (); +#line 1134 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +}else { +#line 1135 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return strMarkerUnused ; +#line 1136 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1137 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1138 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return strDummyName ; +#line 1139 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1141 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +BOOL CWorldBase::GetFog(INDEX iFog,class CFogParameters & fpFog) +#line 1142 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1143 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctFogMarkers = & m_penFog8 - & m_penFog0 + 1; +#line 1144 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iFog < ctFogMarkers ){ +#line 1145 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CFogMarker * pfm = (CFogMarker *) & * (& m_penFog0 ) [ iFog ]; +#line 1146 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(pfm != NULL ){ +#line 1147 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +pfm -> GetFog (fpFog ); +#line 1148 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return TRUE ; +#line 1149 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1150 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1151 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return FALSE ; +#line 1152 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1155 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +const CTString & CWorldBase::GetHazeName(INDEX iHaze) +#line 1156 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1157 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctHazeMarkers = & m_penHaze4 - & m_penHaze0 + 1; +#line 1158 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +static const CTString strDummyName (""); +#line 1159 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +static const CTString strMarkerUnused ("Marker not set"); +#line 1160 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iHaze < ctHazeMarkers ){ +#line 1161 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CHazeMarker * pfm = (CHazeMarker *) & * (& m_penHaze0 ) [ iHaze ]; +#line 1162 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(pfm != NULL ){ +#line 1163 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return pfm -> GetHazeName (); +#line 1164 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +}else { +#line 1165 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return strMarkerUnused ; +#line 1166 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1167 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1168 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return strDummyName ; +#line 1169 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1172 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +BOOL CWorldBase::GetHaze(INDEX iHaze,class CHazeParameters & hpHaze,FLOAT3D & vViewDir) +#line 1173 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1174 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctHazeMarkers = & m_penHaze4 - & m_penHaze0 + 1; +#line 1175 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iHaze < ctHazeMarkers ){ +#line 1176 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CHazeMarker * phm = (CHazeMarker *) & * (& m_penHaze0 ) [ iHaze ]; +#line 1177 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(phm != NULL ){ +#line 1178 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +phm -> GetHaze (hpHaze , vViewDir ); +#line 1179 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return TRUE ; +#line 1180 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1181 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1182 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return FALSE ; +#line 1183 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1186 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +const CTString & CWorldBase::GetMirrorName(INDEX iMirror) +#line 1187 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1188 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +static const CTString strDummyName (""); +#line 1189 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +static const CTString strMarkerUnused ("Marker not set"); +#line 1190 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iMirror == 0){ +#line 1191 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return strDummyName ; +#line 1192 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1194 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +switch(iMirror ){ +#line 1195 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +case 1: {static const CTString str ("std mirror 1");return str ;};break ; +#line 1196 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +case 2: {static const CTString str ("std mirror 2");return str ;};break ; +#line 1197 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +case 3: {static const CTString str ("std mirror 3");return str ;};break ; +#line 1198 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +case 4: {static const CTString str ("std mirror 4");return str ;};break ; +#line 1199 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +case 5: {static const CTString str ("std mirror 5");return str ;};break ; +#line 1200 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +case 6: {static const CTString str ("std mirror 6");return str ;};break ; +#line 1201 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +case 7: {static const CTString str ("std mirror 7");return str ;};break ; +#line 1202 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +case 8: {static const CTString str ("std mirror 8");return str ;};break ; +#line 1203 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +default :{ +#line 1204 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +iMirror -= 9; +#line 1205 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctMirrorMarkers = & m_penMirror4 - & m_penMirror0 + 1; +#line 1206 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iMirror < ctMirrorMarkers ){ +#line 1207 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CMirrorMarker * pfm = (CMirrorMarker *) & * (& m_penMirror0 ) [ iMirror ]; +#line 1208 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(pfm != NULL ){ +#line 1209 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return pfm -> GetMirrorName (); +#line 1210 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +}else { +#line 1211 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return strMarkerUnused ; +#line 1212 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1213 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1214 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1215 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1216 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return strDummyName ; +#line 1217 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1220 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +BOOL CWorldBase::GetMirror(INDEX iMirror,class CMirrorParameters & mpMirror) +#line 1221 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1222 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iMirror == 0){ +#line 1223 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return FALSE ; +#line 1224 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1225 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iMirror >= 1 && iMirror <= 8){ +#line 1226 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +mpMirror . mp_ulFlags = 0; +#line 1227 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return TRUE ; +#line 1228 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1229 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +iMirror -= 9; +#line 1230 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctMirrorMarkers = & m_penMirror4 - & m_penMirror0 + 1; +#line 1231 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iMirror < ctMirrorMarkers ){ +#line 1232 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CMirrorMarker * pmm = (CMirrorMarker *) & * (& m_penMirror0 ) [ iMirror ]; +#line 1233 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(pmm != NULL ){ +#line 1234 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +pmm -> GetMirror (mpMirror ); +#line 1235 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return TRUE ; +#line 1236 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1237 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1238 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return FALSE ; +#line 1239 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1242 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +const CTString & CWorldBase::GetGradientName(INDEX iGradient) +#line 1243 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1244 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctGradientMarkers = & m_penGradient19 - & m_penGradient0 + 1; +#line 1245 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +static const CTString strDummyName (""); +#line 1246 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +static const CTString strMarkerUnused ("Marker not set"); +#line 1247 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(iGradient < ctGradientMarkers ){ +#line 1248 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CGradientMarker * pgm = (CGradientMarker *) & * (& m_penGradient0 ) [ iGradient ]; +#line 1249 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(pgm != NULL ){ +#line 1250 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return pgm -> GetGradientName (); +#line 1251 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +}else { +#line 1252 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return strMarkerUnused ; +#line 1253 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1254 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1255 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return strDummyName ; +#line 1256 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1258 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +void CWorldBase::UncacheShadowsForGradient(class CGradientMarker * penDiscard) +#line 1259 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1260 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctGradientMarkers = & m_penGradient19 - & m_penGradient0 + 1; +#line 1261 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +for(INDEX iGradient = 0;iGradient < ctGradientMarkers ;iGradient ++) +#line 1262 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1263 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CGradientMarker * pgm = (CGradientMarker *) & * (& m_penGradient0 ) [ iGradient ]; +#line 1264 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(pgm == penDiscard ) +#line 1265 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1266 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CEntity :: UncacheShadowsForGradient (iGradient + 1); +#line 1267 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1268 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1269 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1272 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +BOOL CWorldBase::GetGradient(INDEX iGradient,class CGradientParameters & fpGradient) +#line 1273 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1274 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +INDEX ctGradientMarkers = & m_penGradient19 - & m_penGradient0 + 1; +#line 1275 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if((iGradient < ctGradientMarkers ) && (iGradient > 0)){ +#line 1276 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CGradientMarker * pgm = (CGradientMarker *) & * (& m_penGradient0 ) [ iGradient - 1 ]; +#line 1277 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(pgm != NULL ){ +#line 1278 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return pgm -> GetGradient (0 , fpGradient ); +#line 1279 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1280 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1281 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return FALSE ; +#line 1282 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1285 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +BOOL CWorldBase::HandleEvent(const CEntityEvent & ee) +#line 1286 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1288 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(ee . ee_slEvent == EVENTCODE_EFirstWorldBase ){ +#line 1289 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SetFlags (GetFlags () | ENF_ZONING ); +#line 1290 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +m_bZoning = TRUE ; +#line 1291 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SetFlags (GetFlags () | ENF_ANCHORED ); +#line 1292 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +m_bAnchored = TRUE ; +#line 1293 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return TRUE ; +#line 1294 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1295 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return FALSE ; +#line 1296 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SLONG CWorldBase::GetUsedMemory(void) +#line 1301 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1303 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SLONG slUsedMemory = sizeof (CWorldBase ) - sizeof (CEntity ) + CEntity :: GetUsedMemory (); +#line 1305 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +slUsedMemory += m_strName . Length (); +#line 1306 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +slUsedMemory += m_strDescription . Length (); +#line 1307 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return slUsedMemory ; +#line 1308 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} + +#line 1312 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +FLOAT CWorldBase::GetOpacity(void) +#line 1313 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +{ +#line 1314 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return m_fOpacity ; +#line 1315 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +BOOL CWorldBase:: +#line 1322 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWorldBase_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWorldBase::Main expects 'EVoid' as input!"); const EVoid &evoid = (const EVoid &)__eeInput; +#line 1325 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +InitAsBrush (); +#line 1326 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SetPhysicsFlags (EPF_BRUSH_FIXED ); +#line 1327 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SetCollisionFlags (ECF_BRUSH ); +#line 1330 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(m_bZoning ){ +#line 1331 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +m_strDescription = "zoning"; +#line 1332 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SetFlags (GetFlags () | ENF_ZONING ); +#line 1333 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +}else { +#line 1334 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +m_strDescription = "non zoning"; +#line 1335 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SetFlags (GetFlags () & ~ ENF_ZONING ); +#line 1336 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1339 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(m_bBackground ){ +#line 1340 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +m_strDescription += " background"; +#line 1341 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SetFlags (GetFlags () | ENF_BACKGROUND ); +#line 1342 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +}else { +#line 1343 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SetFlags (GetFlags () & ~ ENF_BACKGROUND ); +#line 1344 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1347 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +if(m_bAnchored ){ +#line 1348 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +m_strDescription += " anchored"; +#line 1349 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SetFlags (GetFlags () | ENF_ANCHORED ); +#line 1350 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +}else { +#line 1351 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SetFlags (GetFlags () & ~ ENF_ANCHORED ); +#line 1352 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +} +#line 1354 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +Return(STATE_CURRENT,EVoid()); +#line 1354 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/WorldBase.es b/Sources/EntitiesMP/WorldBase.es new file mode 100644 index 0000000..5bc20d1 --- /dev/null +++ b/Sources/EntitiesMP/WorldBase.es @@ -0,0 +1,1356 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +100 +%{ +#include "StdH.h" +#include "EntitiesMP/BackgroundViewer.h" +#include "EntitiesMP/WorldSettingsController.h" +// for error checking: +#include "EntitiesMP/SoundHolder.h" +%} + +uses "EntitiesMP\FogMarker"; +uses "EntitiesMP\HazeMarker"; +uses "EntitiesMP\MirrorMarker"; +uses "EntitiesMP\GradientMarker"; + +%{ + +inline void Clear(EntityStats &es) {es.es_strName.Clear();}; +static CDynamicArray _aes; +static CAnimObject _aoLightningColor; + +EntityStats *FindStats(const CTString &strName) +{ + {FOREACHINDYNAMICARRAY(_aes, EntityStats, ites) { + EntityStats &es = *ites; + if (es.es_strName==strName) { + return &es; + } + }} + return NULL; +} + +static void MakeWorldStatistics(void) +{ + // get the world pointer + CWorld *pwo = (CWorld *)_pShell->GetINDEX("pwoCurrentWorld"); + // if there is no current world + if (pwo==NULL) { + CPrintF("No current world.\n"); + return; + } + + // for each entity in the world + {FOREACHINDYNAMICCONTAINER(pwo->wo_cenEntities, CEntity, iten) { + // get its stats + EntityStats esCurrent; + BOOL bHasStats = iten->FillEntityStatistics(&esCurrent); + // if no stats + if (!bHasStats) { + // skip it + continue; + } + + // find existing stats with same name + EntityStats *pesOld = FindStats(esCurrent.es_strName); + // if such stats exists + if (pesOld!=NULL) { + // update the existing stats + pesOld->es_ctCount += esCurrent.es_ctCount; + pesOld->es_ctAmmount += esCurrent.es_ctAmmount*esCurrent.es_ctCount; + pesOld->es_fValue += esCurrent.es_fValue*esCurrent.es_ctCount; + pesOld->es_iScore += esCurrent.es_iScore*esCurrent.es_ctCount; + // if this a new name + } else { + // create new stats + EntityStats &esNew = *_aes.New(); + esNew.es_strName = esCurrent.es_strName; + esNew.es_ctCount = esCurrent.es_ctCount; + esNew.es_ctAmmount = esCurrent.es_ctAmmount*esCurrent.es_ctCount; + esNew.es_fValue = esCurrent.es_fValue*esCurrent.es_ctCount; + esNew.es_iScore = esCurrent.es_iScore*esCurrent.es_ctCount; + } + }} + + // dump all stats + try { + CTFileStream strm; + CTFileName fnm = CTString("Temp\\Statistics.txt"); + strm.Create_t(fnm); + CTString strLine; + strLine.PrintF("%-40s: %8s %8s %10s %10s", + "name", "count", "ammount", "health", "score"); + strm.PutLine_t(strLine); + {FOREACHINDYNAMICARRAY(_aes, EntityStats, ites) { + EntityStats &es = *ites; + CTString strLine; + strLine.PrintF("%-40s: %8d %8d %10g %10d", + es.es_strName, es.es_ctCount, es.es_ctAmmount, es.es_fValue, es.es_iScore); + strm.PutLine_t(strLine); + }} + CPrintF("Dumped to '%s'\n", CTString(fnm)); + } catch (char *strError) { + CPrintF("Error: %s\n", strError); + } + + _aes.Clear(); +} + +static void ReoptimizeAllBrushes(void) +{ + // get the world pointer + CWorld *pwo = (CWorld *)_pShell->GetINDEX("pwoCurrentWorld"); + // if there is no current world + if (pwo==NULL) { + CPrintF("No current world.\n"); + return; + } + + // for each brush in the world + FOREACHINDYNAMICARRAY(pwo->wo_baBrushes.ba_abrBrushes, CBrush3D, itbr) { + CBrush3D &br=*itbr; + // for each mip in the brush + FOREACHINLIST(CBrushMip, bm_lnInBrush, itbr->br_lhBrushMips, itbm) { + // reoptimize it + itbm->Reoptimize(); + } + } + CPrintF("All brushes reoptimized.\n"); +} + +static void DoLevelSafetyChecks() +{ + + BOOL bWorldSettingsControllerExists = FALSE; + + CPrintF("\n**** BEGIN Level safety checking ****\n\n"); + + // get the world pointer + CWorld *pwo = (CWorld *)_pShell->GetINDEX("pwoCurrentWorld"); + // if there is no current world + if (pwo==NULL) { + CPrintF("Error - no current world.\n"); + return; + } + + CPrintF("STEP 1 - Checking model holders...\n"); + // for model holder in the world; + {FOREACHINDYNAMICCONTAINER(pwo->wo_cenEntities, CEntity, iten) { + if (IsOfClass(iten, "ModelHolder2")) { + CModelHolder2 *mh = (CModelHolder2*)&*iten; + FLOAT3D vPos = mh->GetPlacement().pl_PositionVector; + if (mh->m_penDestruction == NULL) { + CPrintF(" model holder '%s' at (%2.2f, %2.2f, %2.2f) has no destruction\n", mh->m_strName, vPos(1), vPos(2), vPos(3)); + } + } + }} + + CPrintF("STEP 2 - Checking sound holders...\n"); + // for each sound holder in the world + {FOREACHINDYNAMICCONTAINER(pwo->wo_cenEntities, CEntity, iten) { + if (IsOfClass(iten, "SoundHolder")) { + CSoundHolder *sh = (CSoundHolder *)&*iten; + FLOAT3D vPos = sh->GetPlacement().pl_PositionVector; + if (sh->m_fnSound == CTFILENAME("Sounds\\Default.wav")) { + CPrintF(" sound holder '%s' at (%2.2f, %2.2f, %2.2f) has default sound!\n", sh->m_strName, vPos(1), vPos(2), vPos(3)); + } + } + }} + + + CPrintF("STEP 3 - Checking other important entities...\n"); + CWorldSettingsController *pwsc = NULL; + class CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) pwo->GetBackgroundViewer(); + if( penBcgViewer != NULL) { + // obtain world settings controller + pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController; + } + + if (pwsc!=NULL) { + CPrintF("\n OK! World settings controller exists!\n"); + } else { + CPrintF("\n ERROR! World settings controller does not exist (or isn't connected to the background viewer)!\n"); + } + + CPrintF("\n**** END Level safety checking ****\n"); + +} + +void SetPyramidPlateActivateAlpha(CWorld *pwo, INDEX iBlending, + TIME tmActivated, TIME tmDeactivated, BOOL bPulsate) +{ + TIME tmNow = _pTimer->CurrentTick(); + TIME tmStop = 2.0f; + FLOAT fRatio; + + // get alpha + if( tmNow>tmDeactivated) + { + // if plate is deactivated + if( tmNow>tmDeactivated+tmStop) + { + fRatio = 0; + } + // if fading out + else + { + fRatio = CalculateRatio(tmNow, tmDeactivated, tmDeactivated+tmStop, 0.0f, 1.0f); + } + } + else if( tmNow>tmActivated) + { + // if full visible + if( tmNow>tmActivated+tmStop) + { + fRatio = 1; + } + else + { + // fade in + fRatio = CalculateRatio(tmNow, tmActivated, tmActivated+tmStop, 1.0f, 0.0f); + } + } + // not yet activated + else + { + fRatio = 0; + } + FLOAT fSinFactor = 1.0f; + if( bPulsate) + { + fSinFactor = Sin((tmNow-tmActivated) * 720.0f)*0.5f+0.5f; + } + + UBYTE ub = UBYTE( fRatio*fSinFactor*255.0f); + // apply blend or add + if( pwo->wo_atbTextureBlendings[iBlending].tb_ubBlendingType == STXF_BLEND_ALPHA) + { + pwo->wo_atbTextureBlendings[iBlending].tb_colMultiply = C_WHITE|ub; + } + else if( pwo->wo_atbTextureBlendings[iBlending].tb_ubBlendingType == STXF_BLEND_ADD) + { + pwo->wo_atbTextureBlendings[iBlending].tb_colMultiply = RGBAToColor(ub,ub,ub,255); + } +} + +void SetPyramidMorphRoomAlpha(CWorld *pwo, INDEX iBlending, TIME tmActivated) +{ + TIME tmNow = _pTimer->CurrentTick(); + TIME tmDelta = tmNow-tmActivated; + FLOAT fRatio; + FLOAT tmAppear=10.0f; + + if( tmNow<=tmActivated) { return;} + + // get alpha + if( tmNow>=tmActivated+tmAppear) + { + fRatio = 1; + } + else + { + fRatio = CalculateRatio(tmNow, tmActivated, tmActivated+tmAppear, 1.0f, 0.0f); + } + + FLOAT fSinFactor = Sin(-90+tmDelta*90*(1.0f+tmDelta/tmAppear*4))*0.5f+0.5f; + //FLOAT fSinFactor = Sin(-90+90*tmDelta)*0.5f+0.5f; + //UBYTE ub = fSinFactor*255.0f; + UBYTE ub = UBYTE((fRatio+(1.0f-fRatio)*fSinFactor)*255.0f); + + // apply blend or add + if( pwo->wo_atbTextureBlendings[iBlending].tb_ubBlendingType == STXF_BLEND_ALPHA) + { + pwo->wo_atbTextureBlendings[iBlending].tb_colMultiply = C_WHITE|ub; + } + else if( pwo->wo_atbTextureBlendings[iBlending].tb_ubBlendingType == STXF_BLEND_ADD) + { + pwo->wo_atbTextureBlendings[iBlending].tb_colMultiply = RGBAToColor(ub,ub,ub,255); + } +} + +void CWorldBase_OnWorldInit(CWorld *pwo) +{ + pwo->wo_attTextureTransformations[0].tt_strName = "None"; + pwo->wo_attTextureTransformations[1].tt_strName = "R Extremly Slow"; + pwo->wo_attTextureTransformations[2].tt_strName = "R Very Slow"; + pwo->wo_attTextureTransformations[3].tt_strName = "R Slow"; + pwo->wo_attTextureTransformations[4].tt_strName = "R Medium"; + pwo->wo_attTextureTransformations[5].tt_strName = "R Fast"; + pwo->wo_attTextureTransformations[6].tt_strName = "R Very Fast"; + pwo->wo_attTextureTransformations[7].tt_strName = "R Extremly Fast"; + + pwo->wo_attTextureTransformations[8].tt_strName = "Dummy 1"; + pwo->wo_attTextureTransformations[9].tt_strName = "Dummy 2"; + pwo->wo_attTextureTransformations[10].tt_strName = "Dummy 3"; + + pwo->wo_attTextureTransformations[11].tt_strName = "Water movement extremly slow"; + pwo->wo_attTextureTransformations[12].tt_strName = "Water movement very slow"; + pwo->wo_attTextureTransformations[13].tt_strName = "Water movement slow"; + pwo->wo_attTextureTransformations[14].tt_strName = "Water movement normal"; + pwo->wo_attTextureTransformations[15].tt_strName = "Water movement fast"; + + pwo->wo_attTextureTransformations[16].tt_strName = "Stormy sky appearing"; + + pwo->wo_attTextureTransformations[17].tt_strName = "Rotation Left 1"; + pwo->wo_attTextureTransformations[18].tt_strName = "Rotation Left 2"; + pwo->wo_attTextureTransformations[19].tt_strName = "Rotation Left 3"; + pwo->wo_attTextureTransformations[20].tt_strName = "Rotation Left 4"; + pwo->wo_attTextureTransformations[21].tt_strName = "Rotation Left 5"; + pwo->wo_attTextureTransformations[22].tt_strName = "Rotation Left 6"; + pwo->wo_attTextureTransformations[23].tt_strName = "Rotation Left 7"; + pwo->wo_attTextureTransformations[24].tt_strName = "Rotation Left 8"; + pwo->wo_attTextureTransformations[25].tt_strName = "Rotation Left 9"; + pwo->wo_attTextureTransformations[26].tt_strName = "Rotation Left 10"; + + pwo->wo_attTextureTransformations[27].tt_strName = "Rotation Right 1"; + pwo->wo_attTextureTransformations[28].tt_strName = "Rotation Right 2"; + pwo->wo_attTextureTransformations[29].tt_strName = "Rotation Right 3"; + pwo->wo_attTextureTransformations[30].tt_strName = "Rotation Right 4"; + pwo->wo_attTextureTransformations[31].tt_strName = "Rotation Right 5"; + pwo->wo_attTextureTransformations[32].tt_strName = "Rotation Right 6"; + pwo->wo_attTextureTransformations[33].tt_strName = "Rotation Right 7"; + pwo->wo_attTextureTransformations[34].tt_strName = "Rotation Right 8"; + pwo->wo_attTextureTransformations[35].tt_strName = "Rotation Right 9"; + pwo->wo_attTextureTransformations[36].tt_strName = "Rotation Right 10"; + + pwo->wo_attTextureTransformations[37].tt_strName = "D Extremly Slow"; + pwo->wo_attTextureTransformations[38].tt_strName = "D Very Slow"; + pwo->wo_attTextureTransformations[39].tt_strName = "D Slow"; + pwo->wo_attTextureTransformations[40].tt_strName = "D Medium"; + pwo->wo_attTextureTransformations[41].tt_strName = "D Fast"; + pwo->wo_attTextureTransformations[42].tt_strName = "D Very Fast"; + pwo->wo_attTextureTransformations[43].tt_strName = "D Extremly Fast"; + pwo->wo_attTextureTransformations[44].tt_strName = "D Super Fast"; + pwo->wo_attTextureTransformations[45].tt_strName = "D Abnormaly Fast"; + +// static + pwo->wo_atbTextureBlendings[0].tb_strName = "Opaque"; + pwo->wo_atbTextureBlendings[0].tb_ubBlendingType = STXF_BLEND_OPAQUE; + + pwo->wo_atbTextureBlendings[1].tb_strName = "Shade"; + pwo->wo_atbTextureBlendings[1].tb_ubBlendingType = STXF_BLEND_SHADE; + + pwo->wo_atbTextureBlendings[2].tb_strName = "Blend"; + pwo->wo_atbTextureBlendings[2].tb_ubBlendingType = STXF_BLEND_ALPHA; + + pwo->wo_atbTextureBlendings[3].tb_strName = "Add"; + pwo->wo_atbTextureBlendings[3].tb_ubBlendingType = STXF_BLEND_ADD; +// pulsating + pwo->wo_atbTextureBlendings[4].tb_strName = "Shade pulsating"; + pwo->wo_atbTextureBlendings[4].tb_ubBlendingType = STXF_BLEND_SHADE; + pwo->wo_atbTextureBlendings[4].tb_colMultiply = 0x808080FF; + + pwo->wo_atbTextureBlendings[5].tb_strName = "Blend pulsating full"; + pwo->wo_atbTextureBlendings[5].tb_ubBlendingType = STXF_BLEND_ALPHA; + pwo->wo_atbTextureBlendings[5].tb_colMultiply = C_WHITE|0x80; + + pwo->wo_atbTextureBlendings[6].tb_strName = "Add pulsating"; + pwo->wo_atbTextureBlendings[6].tb_ubBlendingType = STXF_BLEND_ADD; + pwo->wo_atbTextureBlendings[6].tb_colMultiply = 0x808080FF; + + pwo->wo_atbTextureBlendings[7].tb_strName = "Blend pulsating half"; + pwo->wo_atbTextureBlendings[7].tb_ubBlendingType = STXF_BLEND_ALPHA; + pwo->wo_atbTextureBlendings[7].tb_colMultiply = C_WHITE|0xC0; + + pwo->wo_atbTextureBlendings[8].tb_strName = "Wsc blend"; + pwo->wo_atbTextureBlendings[8].tb_ubBlendingType = STXF_BLEND_ALPHA; + pwo->wo_atbTextureBlendings[8].tb_colMultiply = C_WHITE|0x00; + + pwo->wo_atbTextureBlendings[9].tb_strName = "Wsc shade"; + pwo->wo_atbTextureBlendings[9].tb_ubBlendingType = STXF_BLEND_SHADE; + pwo->wo_atbTextureBlendings[9].tb_colMultiply = C_WHITE|0xFF; + + pwo->wo_atbTextureBlendings[10].tb_strName = "Pyramid plate appearing"; + pwo->wo_atbTextureBlendings[10].tb_ubBlendingType = STXF_BLEND_ALPHA; + pwo->wo_atbTextureBlendings[10].tb_colMultiply = C_WHITE|0x00; + + pwo->wo_atbTextureBlendings[11].tb_strName = "Activated plate 1"; + pwo->wo_atbTextureBlendings[11].tb_ubBlendingType = STXF_BLEND_ADD; + pwo->wo_atbTextureBlendings[11].tb_colMultiply = C_BLACK|CT_OPAQUE; + + pwo->wo_atbTextureBlendings[12].tb_strName = "Activated plate 2"; + pwo->wo_atbTextureBlendings[12].tb_ubBlendingType = STXF_BLEND_ADD; + pwo->wo_atbTextureBlendings[12].tb_colMultiply = C_BLACK|CT_OPAQUE; + + pwo->wo_atbTextureBlendings[13].tb_strName = "Activated plate 3"; + pwo->wo_atbTextureBlendings[13].tb_ubBlendingType = STXF_BLEND_ADD; + pwo->wo_atbTextureBlendings[13].tb_colMultiply = C_BLACK|CT_OPAQUE; + + pwo->wo_atbTextureBlendings[14].tb_strName = "Activated plate 4"; + pwo->wo_atbTextureBlendings[14].tb_ubBlendingType = STXF_BLEND_ADD; + pwo->wo_atbTextureBlendings[14].tb_colMultiply = C_BLACK|CT_OPAQUE; + + pwo->wo_atbTextureBlendings[15].tb_strName = "Activate pyramid morph room"; + pwo->wo_atbTextureBlendings[15].tb_ubBlendingType = STXF_BLEND_ALPHA; + pwo->wo_atbTextureBlendings[15].tb_colMultiply = C_WHITE|0x00; + + pwo->wo_aitIlluminationTypes[0].it_strName = "None"; + pwo->wo_aitIlluminationTypes[1].it_strName = "Vitraj 1"; + pwo->wo_aitIlluminationTypes[2].it_strName = "Vitraj 2"; + pwo->wo_aitIlluminationTypes[3].it_strName = "Vitraj 3"; + pwo->wo_aitIlluminationTypes[4].it_strName = "Lava 1"; + pwo->wo_aitIlluminationTypes[5].it_strName = "Lava 2"; + pwo->wo_aitIlluminationTypes[6].it_strName = "Lava 3"; + pwo->wo_aitIlluminationTypes[7].it_strName = "Misc 1"; + pwo->wo_aitIlluminationTypes[8].it_strName = "Misc 2"; + pwo->wo_aitIlluminationTypes[9].it_strName = "Misc 3"; + + // surfaces + + pwo->wo_astSurfaceTypes[0].st_strName = "Standard"; + pwo->wo_astSurfaceTypes[0].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[0].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[0].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[0].st_fClimbSlopeCos = Cos(45.0f); + + pwo->wo_astSurfaceTypes[1].st_strName = "Ice"; + pwo->wo_astSurfaceTypes[1].st_fFriction = 0.045f; + pwo->wo_astSurfaceTypes[1].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[1].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[1].st_fClimbSlopeCos = Cos(5.0f); + + pwo->wo_astSurfaceTypes[2].st_strName = "Standard - no step"; + pwo->wo_astSurfaceTypes[2].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[2].st_fStairsHeight = -0.2f; + pwo->wo_astSurfaceTypes[2].st_fJumpSlopeCos = Cos(10.0f); + pwo->wo_astSurfaceTypes[2].st_fClimbSlopeCos = Cos(10.0f); + + pwo->wo_astSurfaceTypes[3].st_strName = "Standard - high stairs"; + pwo->wo_astSurfaceTypes[3].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[3].st_fStairsHeight = 2.0f; + pwo->wo_astSurfaceTypes[3].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[3].st_fClimbSlopeCos = Cos(45.0f); + + pwo->wo_astSurfaceTypes[4].st_strName = "Ice climbable slope"; + pwo->wo_astSurfaceTypes[4].st_fFriction = 0.05f; + pwo->wo_astSurfaceTypes[4].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[4].st_fJumpSlopeCos = Cos(15.0f); + pwo->wo_astSurfaceTypes[4].st_fClimbSlopeCos = Cos(15.0f); + + pwo->wo_astSurfaceTypes[5].st_strName = "Ice sliding slope"; + pwo->wo_astSurfaceTypes[5].st_fFriction = 0.001f; + pwo->wo_astSurfaceTypes[5].st_fStairsHeight = 0.0f; + pwo->wo_astSurfaceTypes[5].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[5].st_fClimbSlopeCos = Cos(5.0f); + + pwo->wo_astSurfaceTypes[6].st_strName = "Ice less sliding"; + pwo->wo_astSurfaceTypes[6].st_fFriction = 0.06f; + pwo->wo_astSurfaceTypes[6].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[6].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[6].st_fClimbSlopeCos = Cos(5.0f); + + pwo->wo_astSurfaceTypes[7].st_strName = "Roller coaster"; + pwo->wo_astSurfaceTypes[7].st_fFriction = 0.1f; + pwo->wo_astSurfaceTypes[7].st_fStairsHeight = 0.0f; + pwo->wo_astSurfaceTypes[7].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[7].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[7].st_ulFlags = STF_SLIDEDOWNSLOPE; + + pwo->wo_astSurfaceTypes[8].st_strName = "Lava"; + pwo->wo_astSurfaceTypes[8].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[8].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[8].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[8].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[8].st_iWalkDamageType = DMT_BURNING; + pwo->wo_astSurfaceTypes[8].st_fWalkDamageAmount = 2.0f; + pwo->wo_astSurfaceTypes[8].st_tmWalkDamageFrequency = 0.5f; + + ASSERT(9==SURFACE_SAND); + pwo->wo_astSurfaceTypes[9].st_strName = "Sand"; + pwo->wo_astSurfaceTypes[9].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[9].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[9].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[9].st_fClimbSlopeCos = Cos(45.0f); + + pwo->wo_astSurfaceTypes[10].st_strName = "Clibamble Slope"; + pwo->wo_astSurfaceTypes[10].st_fFriction = 2.0f; + pwo->wo_astSurfaceTypes[10].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[10].st_fJumpSlopeCos = Cos(60.0f); + pwo->wo_astSurfaceTypes[10].st_fClimbSlopeCos = Cos(60.0f); + + pwo->wo_astSurfaceTypes[11].st_strName = "Standard - no impact"; + pwo->wo_astSurfaceTypes[11].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[11].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[11].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[11].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[11].st_ulFlags = STF_NOIMPACT; + + ASSERT(12==SURFACE_WATER); + pwo->wo_astSurfaceTypes[12].st_strName = "Water"; + pwo->wo_astSurfaceTypes[12].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[12].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[12].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[12].st_fClimbSlopeCos = Cos(45.0f); + + ASSERT(13==SURFACE_RED_SAND); + pwo->wo_astSurfaceTypes[13].st_strName = "Red sand"; + pwo->wo_astSurfaceTypes[13].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[13].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[13].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[13].st_fClimbSlopeCos = Cos(45.0f); + + pwo->wo_astSurfaceTypes[14].st_strName = "Ice sliding slope no impact"; + pwo->wo_astSurfaceTypes[14].st_fFriction = 0.001f; + pwo->wo_astSurfaceTypes[14].st_fStairsHeight = 0.0f; + pwo->wo_astSurfaceTypes[14].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[14].st_fClimbSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[14].st_ulFlags = STF_NOIMPACT; + + pwo->wo_astSurfaceTypes[15].st_strName = "Roller coaster no impact"; + pwo->wo_astSurfaceTypes[15].st_fFriction = 0.1f; + pwo->wo_astSurfaceTypes[15].st_fStairsHeight = 0.0f; + pwo->wo_astSurfaceTypes[15].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[15].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[15].st_ulFlags = STF_SLIDEDOWNSLOPE | STF_NOIMPACT; + + pwo->wo_astSurfaceTypes[16].st_strName = "Standard - high stairs no impact"; + pwo->wo_astSurfaceTypes[16].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[16].st_fStairsHeight = 2.0f; + pwo->wo_astSurfaceTypes[16].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[16].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[16].st_ulFlags = STF_NOIMPACT; + + ASSERT(17==SURFACE_GRASS); + pwo->wo_astSurfaceTypes[17].st_strName = "Grass"; + pwo->wo_astSurfaceTypes[17].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[17].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[17].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[17].st_fClimbSlopeCos = Cos(45.0f); + + ASSERT(18==SURFACE_WOOD); + pwo->wo_astSurfaceTypes[18].st_strName = "Wood"; + pwo->wo_astSurfaceTypes[18].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[18].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[18].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[18].st_fClimbSlopeCos = Cos(45.0f); + + ASSERT(19==SURFACE_GRASS_SLIDING); + pwo->wo_astSurfaceTypes[19].st_strName = "Grass sliding"; + pwo->wo_astSurfaceTypes[19].st_fFriction = 0.1f; + pwo->wo_astSurfaceTypes[19].st_fStairsHeight = 0.0f; + pwo->wo_astSurfaceTypes[19].st_fJumpSlopeCos = Cos(5.0f); + pwo->wo_astSurfaceTypes[19].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[19].st_ulFlags = STF_SLIDEDOWNSLOPE; + + ASSERT(20==SURFACE_GRASS_NOIMPACT); + pwo->wo_astSurfaceTypes[20].st_strName = "Grass no impact"; + pwo->wo_astSurfaceTypes[20].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[20].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[20].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[20].st_fClimbSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[20].st_ulFlags = STF_NOIMPACT; + + ASSERT(21==SURFACE_SNOW); + pwo->wo_astSurfaceTypes[21].st_strName = "Snow"; + pwo->wo_astSurfaceTypes[21].st_fFriction = 1.0f; + pwo->wo_astSurfaceTypes[21].st_fStairsHeight = 1.0f; + pwo->wo_astSurfaceTypes[21].st_fJumpSlopeCos = Cos(45.0f); + pwo->wo_astSurfaceTypes[21].st_fClimbSlopeCos = Cos(45.0f); + + // contents + pwo->wo_actContentTypes[0].ct_strName = "Air"; + pwo->wo_actContentTypes[0].ct_fDensity = 0.0f; + pwo->wo_actContentTypes[0].ct_fFluidFriction = 0.0f; + pwo->wo_actContentTypes[0].ct_fControlMultiplier = 1.0f; + pwo->wo_actContentTypes[0].ct_fSpeedMultiplier = 1.0f; + pwo->wo_actContentTypes[0].ct_fDrowningDamageAmount = 10.0f; + pwo->wo_actContentTypes[0].ct_tmDrowningDamageDelay = 1.0f; + pwo->wo_actContentTypes[0].ct_ulFlags = CTF_FLYABLE|CTF_BREATHABLE_LUNGS; + + pwo->wo_actContentTypes[1].ct_strName = "Water"; + pwo->wo_actContentTypes[1].ct_fDensity = 1000.0f; + pwo->wo_actContentTypes[1].ct_fFluidFriction = 0.0f; + pwo->wo_actContentTypes[1].ct_fControlMultiplier = 2.0f; + pwo->wo_actContentTypes[1].ct_fSpeedMultiplier = 0.75f; + pwo->wo_actContentTypes[1].ct_fDrowningDamageAmount = 10.0f; + pwo->wo_actContentTypes[1].ct_tmDrowningDamageDelay = 1.0f; + pwo->wo_actContentTypes[1].ct_ulFlags = CTF_BREATHABLE_GILLS|CTF_SWIMABLE|CTF_FADESPINNING; + + pwo->wo_actContentTypes[2].ct_strName = "Lava"; + pwo->wo_actContentTypes[2].ct_fDensity = 800.0f; + pwo->wo_actContentTypes[2].ct_fFluidFriction = 1.0f; + pwo->wo_actContentTypes[2].ct_fControlMultiplier = 2.0f; + pwo->wo_actContentTypes[2].ct_fSpeedMultiplier = 0.5f; + pwo->wo_actContentTypes[2].ct_fDrowningDamageAmount = 0.0f; + pwo->wo_actContentTypes[2].ct_tmDrowningDamageDelay = 1.0f; + pwo->wo_actContentTypes[2].ct_iSwimDamageType = DMT_BURNING; + pwo->wo_actContentTypes[2].ct_fSwimDamageAmount = 50.0f; + pwo->wo_actContentTypes[2].ct_tmSwimDamageFrequency = 0.25f; + pwo->wo_actContentTypes[2].ct_ulFlags = CTF_FADESPINNING; + + pwo->wo_actContentTypes[3].ct_strName = "Cold Water"; + pwo->wo_actContentTypes[3].ct_fDensity = 1000.0f; + pwo->wo_actContentTypes[3].ct_fFluidFriction = 0.0f; + pwo->wo_actContentTypes[3].ct_fControlMultiplier = 2.0f; + pwo->wo_actContentTypes[3].ct_fSpeedMultiplier = 0.75f; + pwo->wo_actContentTypes[3].ct_fDrowningDamageAmount = 10.0f; + pwo->wo_actContentTypes[3].ct_tmDrowningDamageDelay = 1.0f; + pwo->wo_actContentTypes[3].ct_iSwimDamageType = DMT_FREEZING; + pwo->wo_actContentTypes[3].ct_fSwimDamageAmount = 1.0f; + pwo->wo_actContentTypes[3].ct_tmSwimDamageDelay = 5.0f; + pwo->wo_actContentTypes[3].ct_tmSwimDamageFrequency = 1.0f; + pwo->wo_actContentTypes[3].ct_ulFlags = CTF_BREATHABLE_GILLS|CTF_SWIMABLE|CTF_FADESPINNING; + + pwo->wo_actContentTypes[4].ct_strName = "Spikes"; + pwo->wo_actContentTypes[4].ct_fDensity = 500.0f; + pwo->wo_actContentTypes[4].ct_fFluidFriction = 0.5f; + pwo->wo_actContentTypes[4].ct_fControlMultiplier = 1.0f; + pwo->wo_actContentTypes[4].ct_fSpeedMultiplier = 0.75f; + pwo->wo_actContentTypes[4].ct_iKillDamageType = DMT_SPIKESTAB; + pwo->wo_actContentTypes[4].ct_fKillImmersion = 0.5f; + pwo->wo_actContentTypes[4].ct_ulFlags = CTF_BREATHABLE_LUNGS|CTF_FADESPINNING; + + pwo->wo_actContentTypes[5].ct_strName = "Desert heat"; + pwo->wo_actContentTypes[5].ct_fDensity = 0.0f; + pwo->wo_actContentTypes[5].ct_fFluidFriction = 0.0f; + pwo->wo_actContentTypes[5].ct_fControlMultiplier = 1.0f; + pwo->wo_actContentTypes[5].ct_fSpeedMultiplier = 1.0f; + pwo->wo_actContentTypes[5].ct_iSwimDamageType = DMT_HEAT; + pwo->wo_actContentTypes[5].ct_fSwimDamageAmount = 10.0f; + pwo->wo_actContentTypes[5].ct_tmSwimDamageDelay = 10.0f; + pwo->wo_actContentTypes[5].ct_tmSwimDamageFrequency = 2.0f; + pwo->wo_actContentTypes[5].ct_ulFlags = CTF_FLYABLE|CTF_BREATHABLE_LUNGS; + + pwo->wo_actContentTypes[6].ct_strName = "Lava (-10HP/SEC)"; + pwo->wo_actContentTypes[6].ct_fDensity = 1000.0f; + pwo->wo_actContentTypes[6].ct_fFluidFriction = 0.0f; + pwo->wo_actContentTypes[6].ct_fControlMultiplier = 2.0f; + pwo->wo_actContentTypes[6].ct_fSpeedMultiplier = 0.75f; + pwo->wo_actContentTypes[6].ct_fDrowningDamageAmount = 0.0f; + pwo->wo_actContentTypes[6].ct_tmDrowningDamageDelay = 1.0f; + pwo->wo_actContentTypes[6].ct_iSwimDamageType = DMT_BURNING; + pwo->wo_actContentTypes[6].ct_fSwimDamageAmount = 5.0f; + pwo->wo_actContentTypes[6].ct_tmSwimDamageFrequency = 0.5f; + pwo->wo_actContentTypes[6].ct_ulFlags = CTF_SWIMABLE|CTF_FADESPINNING; + + // environments + pwo->wo_aetEnvironmentTypes[ 0].et_strName = "Normal"; + pwo->wo_aetEnvironmentTypes[ 0].et_iType = 1; + pwo->wo_aetEnvironmentTypes[ 0].et_fSize = 1.4f; + + pwo->wo_aetEnvironmentTypes[ 1].et_strName = "Generic"; + pwo->wo_aetEnvironmentTypes[ 1].et_iType = 0; + pwo->wo_aetEnvironmentTypes[ 1].et_fSize = 7.5f; + + pwo->wo_aetEnvironmentTypes[ 2].et_strName = "Small room"; + pwo->wo_aetEnvironmentTypes[ 2].et_iType = EAX_ENVIRONMENT_LIVINGROOM; + pwo->wo_aetEnvironmentTypes[ 2].et_fSize = 2.5f; + + pwo->wo_aetEnvironmentTypes[ 3].et_strName = "Medium room"; + pwo->wo_aetEnvironmentTypes[ 3].et_iType = EAX_ENVIRONMENT_STONEROOM; + pwo->wo_aetEnvironmentTypes[ 3].et_fSize = 11.6f; + + pwo->wo_aetEnvironmentTypes[ 4].et_strName = "Big room"; + pwo->wo_aetEnvironmentTypes[ 4].et_iType = EAX_ENVIRONMENT_AUDITORIUM; + pwo->wo_aetEnvironmentTypes[ 4].et_fSize = 21.6f; + + pwo->wo_aetEnvironmentTypes[ 5].et_strName = "Corridor"; + pwo->wo_aetEnvironmentTypes[ 5].et_iType = EAX_ENVIRONMENT_HALLWAY; + pwo->wo_aetEnvironmentTypes[ 5].et_fSize = 1.8f; + + pwo->wo_aetEnvironmentTypes[ 6].et_strName = "Arena"; + pwo->wo_aetEnvironmentTypes[ 6].et_iType = EAX_ENVIRONMENT_ARENA; + pwo->wo_aetEnvironmentTypes[ 6].et_fSize = 36.2f; + + pwo->wo_aetEnvironmentTypes[ 7].et_strName = "Long corridor"; + pwo->wo_aetEnvironmentTypes[ 7].et_iType = EAX_ENVIRONMENT_STONECORRIDOR; + pwo->wo_aetEnvironmentTypes[ 7].et_fSize = 13.5f; + + pwo->wo_aetEnvironmentTypes[ 8].et_strName = "Small canyon"; + pwo->wo_aetEnvironmentTypes[ 8].et_iType = EAX_ENVIRONMENT_QUARRY; + pwo->wo_aetEnvironmentTypes[ 8].et_fSize = 17.5f; + + pwo->wo_aetEnvironmentTypes[ 9].et_strName = "Big canyon"; + pwo->wo_aetEnvironmentTypes[ 9].et_iType = EAX_ENVIRONMENT_MOUNTAINS; + pwo->wo_aetEnvironmentTypes[ 9].et_fSize = 100.0f; + + pwo->wo_aetEnvironmentTypes[10].et_strName = "Open space"; + pwo->wo_aetEnvironmentTypes[10].et_iType = EAX_ENVIRONMENT_PLAIN; + pwo->wo_aetEnvironmentTypes[10].et_fSize = 42.5f; + + pwo->wo_aetEnvironmentTypes[11].et_strName = "Cave"; + pwo->wo_aetEnvironmentTypes[11].et_iType = EAX_ENVIRONMENT_CAVE; + pwo->wo_aetEnvironmentTypes[11].et_fSize = 14.6f; + + pwo->wo_aetEnvironmentTypes[12].et_strName = "Sewers"; + pwo->wo_aetEnvironmentTypes[12].et_iType = EAX_ENVIRONMENT_SEWERPIPE; + pwo->wo_aetEnvironmentTypes[12].et_fSize = 1.7f; + + pwo->wo_aetEnvironmentTypes[13].et_strName = "Underwater"; + pwo->wo_aetEnvironmentTypes[13].et_iType = EAX_ENVIRONMENT_UNDERWATER; + pwo->wo_aetEnvironmentTypes[13].et_fSize = 1.8f; + + // declare console variables + _pShell->DeclareSymbol("user void MakeWorldStatistics(void);", &MakeWorldStatistics); + _pShell->DeclareSymbol("user void ReoptimizeAllBrushes(void);", &ReoptimizeAllBrushes); + _pShell->DeclareSymbol("user void DoLevelSafetyChecks(void);", &DoLevelSafetyChecks); +} + +void CWorldBase_OnWorldRender(CWorld *pwo) +{ + // get current tick + TIME tmNow = _pTimer->GetLerpedCurrentTick(); + // wrap time to prevent texture coordinates to get unprecise + tmNow = fmod(tmNow, 600.0f); // (wrap every 10 minutes) + +// transformations + // right + pwo->wo_attTextureTransformations[1].tt_mdTransformation.md_fUOffset= 128/1024.0f*tmNow; + pwo->wo_attTextureTransformations[2].tt_mdTransformation.md_fUOffset= 256/1024.0f*tmNow; + pwo->wo_attTextureTransformations[3].tt_mdTransformation.md_fUOffset= 512/1024.0f*tmNow; + pwo->wo_attTextureTransformations[4].tt_mdTransformation.md_fUOffset=1024/1024.0f*tmNow; + pwo->wo_attTextureTransformations[5].tt_mdTransformation.md_fUOffset=2048/1024.0f*tmNow; + pwo->wo_attTextureTransformations[6].tt_mdTransformation.md_fUOffset=4096/1024.0f*tmNow; + pwo->wo_attTextureTransformations[7].tt_mdTransformation.md_fUOffset=8192/1024.0f*tmNow; + + // down + pwo->wo_attTextureTransformations[37].tt_mdTransformation.md_fVOffset= 128/1024.0f*tmNow; + pwo->wo_attTextureTransformations[38].tt_mdTransformation.md_fVOffset= 256/1024.0f*tmNow; + pwo->wo_attTextureTransformations[39].tt_mdTransformation.md_fVOffset= 512/1024.0f*tmNow; + pwo->wo_attTextureTransformations[40].tt_mdTransformation.md_fVOffset=1024/1024.0f*tmNow; + pwo->wo_attTextureTransformations[41].tt_mdTransformation.md_fVOffset=2048/1024.0f*tmNow; + pwo->wo_attTextureTransformations[42].tt_mdTransformation.md_fVOffset=4096/1024.0f*tmNow; + pwo->wo_attTextureTransformations[43].tt_mdTransformation.md_fVOffset=8192/1024.0f*tmNow; + pwo->wo_attTextureTransformations[44].tt_mdTransformation.md_fVOffset=8192*2/1024.0f*tmNow; + pwo->wo_attTextureTransformations[45].tt_mdTransformation.md_fVOffset=8192*4/1024.0f*tmNow; + + CMappingDefinitionUI mdui; + mdui.mdui_fUStretch = 1.0f; + mdui.mdui_fVStretch = 1.0f; + mdui.mdui_fUOffset = 0.0f; + mdui.mdui_fVOffset = 0.0f; + // rotations left + mdui.mdui_aURotation = 8192*1/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*1/1024.0f*tmNow; + pwo->wo_attTextureTransformations[17].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*2/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*2/1024.0f*tmNow; + pwo->wo_attTextureTransformations[18].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*4/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*4/1024.0f*tmNow; + pwo->wo_attTextureTransformations[19].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*8/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*8/1024.0f*tmNow; + pwo->wo_attTextureTransformations[20].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*16/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*16/1024.0f*tmNow; + pwo->wo_attTextureTransformations[21].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*32/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*32/1024.0f*tmNow; + pwo->wo_attTextureTransformations[22].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*64/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*64/1024.0f*tmNow; + pwo->wo_attTextureTransformations[23].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*128/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*128/1024.0f*tmNow; + pwo->wo_attTextureTransformations[24].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = 8192*256/1024.0f*tmNow; + mdui.mdui_aVRotation = 8192*256/1024.0f*tmNow; + pwo->wo_attTextureTransformations[25].tt_mdTransformation.FromUI(mdui); + // rotations right + mdui.mdui_aURotation = -8192*1/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*1/1024.0f*tmNow; + pwo->wo_attTextureTransformations[27].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*2/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*2/1024.0f*tmNow; + pwo->wo_attTextureTransformations[28].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*4/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*4/1024.0f*tmNow; + pwo->wo_attTextureTransformations[29].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*8/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*8/1024.0f*tmNow; + pwo->wo_attTextureTransformations[30].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*16/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*16/1024.0f*tmNow; + pwo->wo_attTextureTransformations[31].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*32/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*32/1024.0f*tmNow; + pwo->wo_attTextureTransformations[32].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*64/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*64/1024.0f*tmNow; + pwo->wo_attTextureTransformations[33].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*128/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*128/1024.0f*tmNow; + pwo->wo_attTextureTransformations[34].tt_mdTransformation.FromUI(mdui); + mdui.mdui_aURotation = -8192*256/1024.0f*tmNow; + mdui.mdui_aVRotation = -8192*256/1024.0f*tmNow; + pwo->wo_attTextureTransformations[35].tt_mdTransformation.FromUI(mdui); +// blendings + FLOAT f = Abs(Sin(tmNow*AngleDeg(180.0f))); + pwo->wo_atbTextureBlendings[4].tb_colMultiply = RGBAToColor(f*255, f*255, f*255, 255); + pwo->wo_atbTextureBlendings[5].tb_colMultiply = C_WHITE|UBYTE(255*f); + pwo->wo_atbTextureBlendings[6].tb_colMultiply = RGBAToColor(f*255, f*255, f*255, 255); + pwo->wo_atbTextureBlendings[7].tb_colMultiply = C_WHITE|UBYTE(255*Lerp(0.5f, 1.0f, f)); + + pwo->wo_attTextureTransformations[11].tt_mdTransformation.md_fUOffset=Sin( tmNow*22)/30; + pwo->wo_attTextureTransformations[11].tt_mdTransformation.md_fVOffset=Cos( tmNow*26)/35; + + pwo->wo_attTextureTransformations[12].tt_mdTransformation.md_fUOffset=Sin( tmNow*32)/10; + pwo->wo_attTextureTransformations[12].tt_mdTransformation.md_fVOffset=Cos( tmNow*22)/15; + + pwo->wo_attTextureTransformations[13].tt_mdTransformation.md_fUOffset=Sin( tmNow*15)/7; + pwo->wo_attTextureTransformations[13].tt_mdTransformation.md_fVOffset=Cos( tmNow*25)/8; + + pwo->wo_attTextureTransformations[14].tt_mdTransformation.md_fUOffset=Sin( tmNow*32)/3; + pwo->wo_attTextureTransformations[14].tt_mdTransformation.md_fVOffset=Cos( tmNow*22)/3; + + pwo->wo_attTextureTransformations[15].tt_mdTransformation.md_fUOffset=Sin( tmNow*15); + pwo->wo_attTextureTransformations[15].tt_mdTransformation.md_fVOffset=Cos( tmNow*25); + + // ----------- Obtain world settings controller + CWorldSettingsController *pwsc = NULL; + // obtain bcg viewer + CBackgroundViewer *penBcgViewer = (CBackgroundViewer *) pwo->GetBackgroundViewer(); + if( penBcgViewer != NULL) + { + // obtain world settings controller + pwsc = (CWorldSettingsController *) &*penBcgViewer->m_penWorldSettingsController; + } + + // ***** Storm effects + // if world settings controller is valid + if( pwsc != NULL) + { + FLOAT fStormFactor = pwsc->GetStormFactor(); + COLOR colBlend = LerpColor( pwsc->m_colBlendStart, pwsc->m_colBlendStop, fStormFactor); + pwo->wo_atbTextureBlendings[8].tb_colMultiply = colBlend; + + // set world polygon shading multiplier + COLOR colShade = LerpColor( pwsc->m_colShadeStart, pwsc->m_colShadeStop, fStormFactor); + + // apply lightning FX + if( pwsc->m_tmLightningStart != -1) + { + FLOAT tmLightningLife = tmNow-pwsc->m_tmLightningStart; + _aoLightningColor.ao_tmAnimStart = pwsc->m_tmLightningStart; + COLOR colLightning = _aoLightningColor.GetFrame(); + // calculate lightning power factor + UBYTE ub = UBYTE( pwsc->m_fLightningPower*255); + COLOR colFactor = RGBToColor( ub, ub, ub) | CT_OPAQUE; + colLightning = MulColors( colLightning, colFactor); + colShade = AddColors( colShade, colLightning); + } + pwo->wo_atbTextureBlendings[9].tb_colMultiply = colShade; + } + + // ***** Pyramid blending effects + // if world settings controller is valid + if( pwsc != NULL) + { + // set alpha values for switch-controlled pyramid plate activating + SetPyramidPlateActivateAlpha(pwo, 10, pwsc->m_tmPyramidPlatesStart, 1e6, FALSE); + SetPyramidPlateActivateAlpha(pwo, 11, pwsc->m_tmActivatedPlate1, pwsc->m_tmDeactivatedPlate1, TRUE); + SetPyramidPlateActivateAlpha(pwo, 12, pwsc->m_tmActivatedPlate2, pwsc->m_tmDeactivatedPlate2, TRUE); + SetPyramidPlateActivateAlpha(pwo, 13, pwsc->m_tmActivatedPlate3, pwsc->m_tmDeactivatedPlate3, TRUE); + SetPyramidPlateActivateAlpha(pwo, 14, pwsc->m_tmActivatedPlate4, pwsc->m_tmDeactivatedPlate4, TRUE); + // pyramid morph room + SetPyramidMorphRoomAlpha(pwo, 15, pwsc->m_tmPyramidMorphRoomActivated); + } +}; + +void CWorldBase_OnInitClass(void) +{ + // init particle effects + InitParticles(); + try + { + // setup simple model shadow texture + _toSimpleModelShadow.SetData_t( CTFILENAME("Textures\\Effects\\Shadow\\SimpleModelShadow.tex")); + _aoLightningColor.SetData_t( CTFILENAME("Animations\\Lightning.ani")); + // we will use first animation in .ani file for lightning + _aoLightningColor.PlayAnim(0, AOF_NORESTART); + } + catch(char *strError) + { + FatalError(TRANS("Cannot load shadow texture: \n%s"), strError); + } +} + +void CWorldBase_OnEndClass(void) +{ + // close particle effects + CloseParticles(); +} + +class CFixedForce { +public: + CTString ff_strName; + class CForceStrength ff_fsGravity; + class CForceStrength ff_fsField; + + inline CFixedForce(CTString strName, + FLOAT3D vDirection, + FLOAT fAcceleration, + FLOAT fVelocity) + { + ff_strName = strName; + ff_fsGravity.fs_vDirection =vDirection; + ff_fsGravity.fs_fAcceleration =fAcceleration; + ff_fsGravity.fs_fVelocity =fVelocity; + } + +}; + +static CFixedForce affFixedForces[] = +{ + CFixedForce ("Normal D", FLOAT3D( 0,-1, 0), 30, 70), + CFixedForce ("Normal U", FLOAT3D( 0,+1, 0), 30, 70), + CFixedForce ("Normal N", FLOAT3D( 0, 0,-1), 30, 70), + CFixedForce ("Normal S", FLOAT3D( 0, 0,+1), 30, 70), + CFixedForce ("Normal E", FLOAT3D(-1, 0, 0), 30, 70), + CFixedForce ("Normal W", FLOAT3D(+1, 0, 0), 30, 70), + CFixedForce ("ZeroG", FLOAT3D(+1, 0, 0), 0, 0), + CFixedForce ("Unused", FLOAT3D(+1, 0, 0), 0, 0), + CFixedForce ("Unused", FLOAT3D(+1, 0, 0), 0, 0), + CFixedForce ("Unused", FLOAT3D(+1, 0, 0), 0, 0), +}; +static INDEX ctFixedForces = ARRAYCOUNT(affFixedForces); +extern void GetDefaultForce(INDEX iForce, const FLOAT3D &vPoint, + CForceStrength &fsGravity, CForceStrength &fsField) +{ + if (iForce=ulFirst) && (slPropertyOffset<=ulLast) ) { + return (IsDerivedFromClass(penTarget, strClass)); + } + + // if gravity marker + ulFirst = offsetof(CWorldBase, m_penGravity0); + ulLast = offsetof(CWorldBase, m_penGravity9); + if( (slPropertyOffset>=ulFirst) && (slPropertyOffset<=ulLast) ) { + return + IsDerivedFromClass(penTarget, "Gravity Marker")|| + IsDerivedFromClass(penTarget, "Gravity Router"); + } + + // if mirror marker + ulFirst = offsetof(CWorldBase, m_penMirror0); + ulLast = offsetof(CWorldBase, m_penMirror4); + strClass = "Mirror Marker"; + if( (slPropertyOffset>=ulFirst) && (slPropertyOffset<=ulLast) ) { + return (IsDerivedFromClass(penTarget, strClass)); + } + + // if fog marker + ulFirst = offsetof(CWorldBase, m_penFog0); + ulLast = offsetof(CWorldBase, m_penFog9); + strClass = "Fog Marker"; + if( (slPropertyOffset>=ulFirst) && (slPropertyOffset<=ulLast) ) { + return (IsDerivedFromClass(penTarget, strClass)); + } + + // if haze marker + ulFirst = offsetof(CWorldBase, m_penHaze0); + ulLast = offsetof(CWorldBase, m_penHaze4); + strClass = "Haze Marker"; + if( (slPropertyOffset>=ulFirst) && (slPropertyOffset<=ulLast) ) { + return (IsDerivedFromClass(penTarget, strClass)); + } + + return CEntity::IsTargetValid(slPropertyOffset, penTarget); + } + + /* Get force type name, return empty string if not used. */ + const CTString &GetForceName(INDEX iForce) + { + static const CTString strDummyName(""); + static const CTString strMarkerUnused("Marker not set"); + INDEX ctGravityMarkers = &m_penGravity9-&m_penGravity0+1; + + if (iForceGetForceName(0); + } else { + return strMarkerUnused; + } + + } + return strDummyName; + } + } + /* Get force in given point. */ + void GetForce(INDEX iForce, const FLOAT3D &vPoint, + CForceStrength &fsGravity, CForceStrength &fsField) + { + INDEX ctGravityMarkers = &m_penGravity9-&m_penGravity0+1; + if (iForceGetForce(0, vPoint, fsGravity, fsField); + return; + } + } + fsGravity.fs_fAcceleration = 30; + fsGravity.fs_fVelocity = 70; + fsGravity.fs_vDirection = FLOAT3D(1,0,0); + } + fsField.fs_fAcceleration = 0; + fsField.fs_fVelocity = 0; + } + + /* Get entity that controls the force, used for change notification checking. */ + CEntity *GetForceController(INDEX iForce) + { + INDEX ctGravityMarkers = &m_penGravity9-&m_penGravity0+1; + if (iForceGetForceController(0); + } + } + } + return NULL; + } + /* Get fog type name, return empty string if not used. */ + const CTString &GetFogName(INDEX iFog) + { + INDEX ctFogMarkers = &m_penFog9-&m_penFog0+1; + static const CTString strDummyName(""); + static const CTString strMarkerUnused("Marker not set"); + if (iFogGetFogName(); + } else { + return strMarkerUnused; + } + } + return strDummyName; + } + /* Get fog, return FALSE for none. */ + BOOL GetFog(INDEX iFog, class CFogParameters &fpFog) + { + INDEX ctFogMarkers = &m_penFog8-&m_penFog0+1; + if (iFogGetFog(fpFog); + return TRUE; + } + } + return FALSE; + } + + /* Get haze type name, return empty string if not used. */ + const CTString &GetHazeName(INDEX iHaze) + { + INDEX ctHazeMarkers = &m_penHaze4-&m_penHaze0+1; + static const CTString strDummyName(""); + static const CTString strMarkerUnused("Marker not set"); + if (iHazeGetHazeName(); + } else { + return strMarkerUnused; + } + } + return strDummyName; + } + + /* Get haze, return FALSE for none. */ + BOOL GetHaze(INDEX iHaze, class CHazeParameters &hpHaze, FLOAT3D &vViewDir) + { + INDEX ctHazeMarkers = &m_penHaze4-&m_penHaze0+1; + if (iHazeGetHaze(hpHaze, vViewDir); + return TRUE; + } + } + return FALSE; + } + + /* Get mirror type name, return empty string if not used. */ + const CTString &GetMirrorName(INDEX iMirror) + { + static const CTString strDummyName(""); + static const CTString strMarkerUnused("Marker not set"); + if (iMirror==0) { + return strDummyName; + } + + switch (iMirror) { + case 1: { static const CTString str("std mirror 1"); return str; }; break; + case 2: { static const CTString str("std mirror 2"); return str; }; break; + case 3: { static const CTString str("std mirror 3"); return str; }; break; + case 4: { static const CTString str("std mirror 4"); return str; }; break; + case 5: { static const CTString str("std mirror 5"); return str; }; break; + case 6: { static const CTString str("std mirror 6"); return str; }; break; + case 7: { static const CTString str("std mirror 7"); return str; }; break; + case 8: { static const CTString str("std mirror 8"); return str; }; break; + default: { + iMirror-=9; + INDEX ctMirrorMarkers = &m_penMirror4-&m_penMirror0+1; + if (iMirrorGetMirrorName(); + } else { + return strMarkerUnused; + } + } + } + } + return strDummyName; + } + + /* Get mirror, return FALSE for none. */ + BOOL GetMirror(INDEX iMirror, class CMirrorParameters &mpMirror) + { + if (iMirror==0) { + return FALSE; + } + if (iMirror>=1 && iMirror<=8) { + mpMirror.mp_ulFlags = 0; + return TRUE; + } + iMirror-=9; + INDEX ctMirrorMarkers = &m_penMirror4-&m_penMirror0+1; + if (iMirrorGetMirror(mpMirror); + return TRUE; + } + } + return FALSE; + } + + /* Get gradient type name, return empty string if not used. */ + const CTString &GetGradientName(INDEX iGradient) + { + INDEX ctGradientMarkers = &m_penGradient19-&m_penGradient0+1; + static const CTString strDummyName(""); + static const CTString strMarkerUnused("Marker not set"); + if (iGradientGetGradientName(); + } else { + return strMarkerUnused; + } + } + return strDummyName; + } + /* Uncache shadows for given gradient */ + void UncacheShadowsForGradient(class CGradientMarker *penDiscard) + { + INDEX ctGradientMarkers = &m_penGradient19-&m_penGradient0+1; + for( INDEX iGradient=0; iGradient0) ){ + CGradientMarker *pgm = (CGradientMarker *)&*(&m_penGradient0)[iGradient-1]; + if (pgm != NULL) { + return pgm->GetGradient(0, fpGradient); + } + } + return FALSE; + } + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + // when someone in range is destroyed + if (ee.ee_slEvent==EVENTCODE_EFirstWorldBase) { + SetFlags(GetFlags()|ENF_ZONING); + m_bZoning = TRUE; + SetFlags(GetFlags()|ENF_ANCHORED); + m_bAnchored = TRUE; + return TRUE; + } + return FALSE; + } + + + // returns bytes of memory used by this object + SLONG GetUsedMemory(void) + { + // initial + SLONG slUsedMemory = sizeof(CWorldBase) - sizeof(CEntity) + CEntity::GetUsedMemory(); + // add some more + slUsedMemory += m_strName.Length(); + slUsedMemory += m_strDescription.Length(); + return slUsedMemory; + } + + + // return opacity of the brush + FLOAT GetOpacity(void) + { + return m_fOpacity; + } + + + +procedures: + + + Main(EVoid evoid) + { + // declare yourself as a brush + InitAsBrush(); + SetPhysicsFlags(EPF_BRUSH_FIXED); + SetCollisionFlags(ECF_BRUSH); + + // set zoning + if( m_bZoning) { + m_strDescription = "zoning"; + SetFlags(GetFlags()|ENF_ZONING); + } else { + m_strDescription = "non zoning"; + SetFlags(GetFlags()&~ENF_ZONING); + } + + // set background + if( m_bBackground) { + m_strDescription += " background"; + SetFlags(GetFlags()|ENF_BACKGROUND); + } else { + SetFlags(GetFlags()&~ENF_BACKGROUND); + } + + // set anchor for SEd + if( m_bAnchored) { + m_strDescription += " anchored"; + SetFlags(GetFlags()|ENF_ANCHORED); + } else { + SetFlags(GetFlags()&~ENF_ANCHORED); + } + + return; + } +}; diff --git a/Sources/EntitiesMP/WorldBase.h b/Sources/EntitiesMP/WorldBase.h new file mode 100644 index 0000000..91c1f51 --- /dev/null +++ b/Sources/EntitiesMP/WorldBase.h @@ -0,0 +1,133 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_WorldBase_INCLUDED +#define _EntitiesMP_WorldBase_INCLUDED 1 +#include +#include +#include +#include +extern "C" DECL_DLL CDLLEntityClass CWorldBase_DLLClass; +class CWorldBase : public CEntity { +public: +virtual const CTString &GetName(void) const { return m_strName; }; +virtual const CTString &GetDescription(void) const { return m_strDescription; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strName; + CTString m_strDescription; + BOOL m_bZoning; + BOOL m_bBackground; + BOOL m_bAnchored; + CEntityPointer m_penGravity0; + CEntityPointer m_penGravity1; + CEntityPointer m_penGravity2; + CEntityPointer m_penGravity3; + CEntityPointer m_penGravity4; + CEntityPointer m_penGravity5; + CEntityPointer m_penGravity6; + CEntityPointer m_penGravity7; + CEntityPointer m_penGravity8; + CEntityPointer m_penGravity9; + CEntityPointer m_penFog0; + CEntityPointer m_penFog1; + CEntityPointer m_penFog2; + CEntityPointer m_penFog3; + CEntityPointer m_penFog4; + CEntityPointer m_penFog5; + CEntityPointer m_penFog6; + CEntityPointer m_penFog7; + CEntityPointer m_penFog8; + CEntityPointer m_penFog9; + CEntityPointer m_penHaze0; + CEntityPointer m_penHaze1; + CEntityPointer m_penHaze2; + CEntityPointer m_penHaze3; + CEntityPointer m_penHaze4; + CEntityPointer m_penMirror0; + CEntityPointer m_penMirror1; + CEntityPointer m_penMirror2; + CEntityPointer m_penMirror3; + CEntityPointer m_penMirror4; + CEntityPointer m_penGradient0; + CEntityPointer m_penGradient1; + CEntityPointer m_penGradient2; + CEntityPointer m_penGradient3; + CEntityPointer m_penGradient4; + CEntityPointer m_penGradient5; + CEntityPointer m_penGradient6; + CEntityPointer m_penGradient7; + CEntityPointer m_penGradient8; + CEntityPointer m_penGradient9; + CEntityPointer m_penGradient10; + CEntityPointer m_penGradient11; + CEntityPointer m_penGradient12; + CEntityPointer m_penGradient13; + CEntityPointer m_penGradient14; + CEntityPointer m_penGradient15; + CEntityPointer m_penGradient16; + CEntityPointer m_penGradient17; + CEntityPointer m_penGradient18; + CEntityPointer m_penGradient19; + ULONG m_cbClassificationBits; + ULONG m_vbVisibilityBits; + FLOAT m_fOpacity; + +#line 1003 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +ULONG GetVisTweaks(void); + +#line 1009 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 1064 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +const CTString & GetForceName(INDEX iForce); + +#line 1086 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +void GetForce(INDEX iForce,const FLOAT3D & vPoint, +#line 1087 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CForceStrength & fsGravity,CForceStrength & fsField); + +#line 1109 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +CEntity * GetForceController(INDEX iForce); + +#line 1125 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +const CTString & GetFogName(INDEX iFog); + +#line 1141 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +BOOL GetFog(INDEX iFog,class CFogParameters & fpFog); + +#line 1155 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +const CTString & GetHazeName(INDEX iHaze); + +#line 1172 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +BOOL GetHaze(INDEX iHaze,class CHazeParameters & hpHaze,FLOAT3D & vViewDir); + +#line 1186 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +const CTString & GetMirrorName(INDEX iMirror); + +#line 1220 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +BOOL GetMirror(INDEX iMirror,class CMirrorParameters & mpMirror); + +#line 1242 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +const CTString & GetGradientName(INDEX iGradient); + +#line 1258 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +void UncacheShadowsForGradient(class CGradientMarker * penDiscard); + +#line 1272 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +BOOL GetGradient(INDEX iGradient,class CGradientParameters & fpGradient); + +#line 1285 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +BOOL HandleEvent(const CEntityEvent & ee); + +#line 1300 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +SLONG GetUsedMemory(void); + +#line 1312 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +FLOAT GetOpacity(void); +#define STATE_CWorldBase_Main 1 + BOOL +#line 1322 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_WorldBase_INCLUDED diff --git a/Sources/EntitiesMP/WorldBase_tables.h b/Sources/EntitiesMP/WorldBase_tables.h new file mode 100644 index 0000000..f6dceab --- /dev/null +++ b/Sources/EntitiesMP/WorldBase_tables.h @@ -0,0 +1,91 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CWorldBase + +CEntityProperty CWorldBase_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000064<<8)+1, offsetof(CWorldBase, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x00000064<<8)+3, offsetof(CWorldBase, m_strDescription), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000064<<8)+2, offsetof(CWorldBase, m_bZoning), "Zoning", 'Z', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000064<<8)+4, offsetof(CWorldBase, m_bBackground), "Background", 'B', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x00000064<<8)+5, offsetof(CWorldBase, m_bAnchored), "Anchored", 'A', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+10, offsetof(CWorldBase, m_penGravity0), "Gravity 0", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+11, offsetof(CWorldBase, m_penGravity1), "Gravity 1", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+12, offsetof(CWorldBase, m_penGravity2), "Gravity 2", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+13, offsetof(CWorldBase, m_penGravity3), "Gravity 3", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+14, offsetof(CWorldBase, m_penGravity4), "Gravity 4", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+15, offsetof(CWorldBase, m_penGravity5), "Gravity 5", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+16, offsetof(CWorldBase, m_penGravity6), "Gravity 6", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+17, offsetof(CWorldBase, m_penGravity7), "Gravity 7", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+18, offsetof(CWorldBase, m_penGravity8), "Gravity 8", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+19, offsetof(CWorldBase, m_penGravity9), "Gravity 9", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+20, offsetof(CWorldBase, m_penFog0), "Fog 0", 'F', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+21, offsetof(CWorldBase, m_penFog1), "Fog 1", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+22, offsetof(CWorldBase, m_penFog2), "Fog 2", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+23, offsetof(CWorldBase, m_penFog3), "Fog 3", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+24, offsetof(CWorldBase, m_penFog4), "Fog 4", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+25, offsetof(CWorldBase, m_penFog5), "Fog 5", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+26, offsetof(CWorldBase, m_penFog6), "Fog 6", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+27, offsetof(CWorldBase, m_penFog7), "Fog 7", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+28, offsetof(CWorldBase, m_penFog8), "Fog 8", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+29, offsetof(CWorldBase, m_penFog9), "Fog 9", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+30, offsetof(CWorldBase, m_penHaze0), "Haze 0", 'H', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+31, offsetof(CWorldBase, m_penHaze1), "Haze 1", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+32, offsetof(CWorldBase, m_penHaze2), "Haze 2", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+33, offsetof(CWorldBase, m_penHaze3), "Haze 3", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+34, offsetof(CWorldBase, m_penHaze4), "Haze 4", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+40, offsetof(CWorldBase, m_penMirror0), "Mirror 0", 'M', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+41, offsetof(CWorldBase, m_penMirror1), "Mirror 1", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+42, offsetof(CWorldBase, m_penMirror2), "Mirror 2", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+43, offsetof(CWorldBase, m_penMirror3), "Mirror 3", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+44, offsetof(CWorldBase, m_penMirror4), "Mirror 4", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+50, offsetof(CWorldBase, m_penGradient0), "Gradient 0", 'R', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+51, offsetof(CWorldBase, m_penGradient1), "Gradient 1", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+52, offsetof(CWorldBase, m_penGradient2), "Gradient 2", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+53, offsetof(CWorldBase, m_penGradient3), "Gradient 3", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+54, offsetof(CWorldBase, m_penGradient4), "Gradient 4", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+55, offsetof(CWorldBase, m_penGradient5), "Gradient 5", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+56, offsetof(CWorldBase, m_penGradient6), "Gradient 6", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+57, offsetof(CWorldBase, m_penGradient7), "Gradient 7", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+58, offsetof(CWorldBase, m_penGradient8), "Gradient 8", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+59, offsetof(CWorldBase, m_penGradient9), "Gradient 9", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+60, offsetof(CWorldBase, m_penGradient10), "Gradient 10", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+61, offsetof(CWorldBase, m_penGradient11), "Gradient 11", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+62, offsetof(CWorldBase, m_penGradient12), "Gradient 12", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+63, offsetof(CWorldBase, m_penGradient13), "Gradient 13", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+64, offsetof(CWorldBase, m_penGradient14), "Gradient 14", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+65, offsetof(CWorldBase, m_penGradient15), "Gradient 15", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+66, offsetof(CWorldBase, m_penGradient16), "Gradient 16", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+67, offsetof(CWorldBase, m_penGradient17), "Gradient 17", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+68, offsetof(CWorldBase, m_penGradient18), "Gradient 18", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x00000064<<8)+69, offsetof(CWorldBase, m_penGradient19), "Gradient 19", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLAGS, &ClasificationBits_enum, (0x00000064<<8)+80, offsetof(CWorldBase, m_cbClassificationBits), "Clasification bits", 'C', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLAGS, &VisibilityBits_enum, (0x00000064<<8)+81, offsetof(CWorldBase, m_vbVisibilityBits), "Visibility bits", 'V', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x00000064<<8)+99, offsetof(CWorldBase, m_fOpacity), "Opacity", 0, 0x7F0000FFUL, 0), +}; +#define CWorldBase_propertiesct ARRAYCOUNT(CWorldBase_properties) + +CEntityComponent CWorldBase_components[] = { + CEntityComponent() +}; +#define CWorldBase_componentsct 0 + + +CEventHandlerEntry CWorldBase_handlers[] = { + {1, -1, CEntity::pEventHandler(&CWorldBase:: +#line 1322 "D:/SE1_GPL/Sources/EntitiesMP/WorldBase.es" +Main),DEBUGSTRING("CWorldBase::Main")}, +}; +#define CWorldBase_handlersct ARRAYCOUNT(CWorldBase_handlers) + +CEntity *CWorldBase_New(void) { return new CWorldBase; }; +void CWorldBase_OnInitClass(void); +void CWorldBase_OnEndClass(void); +void CWorldBase_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CWorldBase_OnWorldEnd(CWorld *pwo) {}; +void CWorldBase_OnWorldInit(CWorld *pwo); +void CWorldBase_OnWorldTick(CWorld *pwo) {}; +void CWorldBase_OnWorldRender(CWorld *pwo); +ENTITY_CLASSDEFINITION(CWorldBase, CEntity, "WorldBase", "Thumbnails\\WorldBase.tbn", 0x00000064); +DECLARE_CTFILENAME(_fnmCWorldBase_tbn, "Thumbnails\\WorldBase.tbn"); diff --git a/Sources/EntitiesMP/WorldLink.cpp b/Sources/EntitiesMP/WorldLink.cpp new file mode 100644 index 0000000..5554b8d --- /dev/null +++ b/Sources/EntitiesMP/WorldLink.cpp @@ -0,0 +1,62 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" + +#include "StdH.h" + +#include +#include +void CWorldLink::SetDefaultProperties(void) { + m_strGroup = ""; + m_strWorld = ""; + m_bStoreWorld = FALSE ; + m_EwltType = WLT_RELATIVE ; + CMarker::SetDefaultProperties(); +} + +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +BOOL CWorldLink::HandleEvent(const CEntityEvent & ee) { +#line 37 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +if(ee . ee_slEvent == EVENTCODE_ETrigger ){ +#line 38 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +ETrigger & eTrigger = (ETrigger &) ee ; +#line 39 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +_SwcWorldChange . strGroup = m_strGroup ; +#line 40 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +_SwcWorldChange . plLink = GetPlacement (); +#line 41 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +_SwcWorldChange . iType = (INDEX) m_EwltType ; +#line 42 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +_pNetwork -> ChangeLevel (m_strWorld , m_bStoreWorld , 0); +#line 43 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +return TRUE ; +#line 44 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +} +#line 45 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +return FALSE ; +#line 46 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +} +BOOL CWorldLink:: +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWorldLink_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWorldLink::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 53 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +InitAsEditorModel (); +#line 54 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 55 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 58 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +SetModel (MODEL_WORLDLINK ); +#line 59 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +SetModelMainTexture (TEXTURE_WORLDLINK ); +#line 62 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +m_strName . PrintF ("World link - %s" , m_strGroup ); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +Return(STATE_CURRENT,EVoid()); +#line 64 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/WorldLink.es b/Sources/EntitiesMP/WorldLink.es new file mode 100644 index 0000000..d0ca120 --- /dev/null +++ b/Sources/EntitiesMP/WorldLink.es @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +214 +%{ +#include "StdH.h" +%} + +uses "EntitiesMP/Marker"; + +// world link +enum WorldLinkType { + 1 WLT_FIXED "Fixed", // fixed link + 2 WLT_RELATIVE "Relative", // relative link +}; + +class CWorldLink : CMarker { +name "World link"; +thumbnail "Thumbnails\\WorldLink.tbn"; +features "IsImportant"; + +properties: + 1 CTString m_strGroup "Group" 'G' = "", + 2 CTFileNameNoDep m_strWorld "World" 'W' = "", + 3 BOOL m_bStoreWorld "Store world" 'S' = FALSE, + 4 enum WorldLinkType m_EwltType "Type" 'Y' = WLT_RELATIVE, + +components: + 1 model MODEL_WORLDLINK "Models\\Editor\\WorldLink.mdl", + 2 texture TEXTURE_WORLDLINK "Models\\Editor\\WorldLink.tex" + + +functions: +/************************************************************ + * START EVENT * + ************************************************************/ + BOOL HandleEvent(const CEntityEvent &ee) { + if (ee.ee_slEvent == EVENTCODE_ETrigger) { + ETrigger &eTrigger = (ETrigger &)ee; + _SwcWorldChange.strGroup = m_strGroup; // group name + _SwcWorldChange.plLink = GetPlacement(); // link placement + _SwcWorldChange.iType = (INDEX)m_EwltType; // type + _pNetwork->ChangeLevel(m_strWorld, m_bStoreWorld, 0); + return TRUE; + } + return FALSE; + }; + +procedures: +/************************************************************ + * M A I N * + ************************************************************/ + Main(EVoid) { + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_WORLDLINK); + SetModelMainTexture(TEXTURE_WORLDLINK); + + // set name + m_strName.PrintF("World link - %s", m_strGroup); + + return; + } +}; diff --git a/Sources/EntitiesMP/WorldLink.h b/Sources/EntitiesMP/WorldLink.h new file mode 100644 index 0000000..8819a46 --- /dev/null +++ b/Sources/EntitiesMP/WorldLink.h @@ -0,0 +1,31 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_WorldLink_INCLUDED +#define _EntitiesMP_WorldLink_INCLUDED 1 +#include +extern DECL_DLL CEntityPropertyEnumType WorldLinkType_enum; +enum WorldLinkType { + WLT_FIXED = 1, + WLT_RELATIVE = 2, +}; +DECL_DLL inline void ClearToDefault(WorldLinkType &e) { e = (WorldLinkType)0; } ; +extern "C" DECL_DLL CDLLEntityClass CWorldLink_DLLClass; +class CWorldLink : public CMarker { +public: +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + CTString m_strGroup; + CTFileNameNoDep m_strWorld; + BOOL m_bStoreWorld; + enum WorldLinkType m_EwltType; + +#line 36 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CWorldLink_Main 1 + BOOL +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_WorldLink_INCLUDED diff --git a/Sources/EntitiesMP/WorldLink_tables.h b/Sources/EntitiesMP/WorldLink_tables.h new file mode 100644 index 0000000..d5498cd --- /dev/null +++ b/Sources/EntitiesMP/WorldLink_tables.h @@ -0,0 +1,44 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +EP_ENUMBEG(WorldLinkType) + EP_ENUMVALUE(WLT_FIXED, "Fixed"), + EP_ENUMVALUE(WLT_RELATIVE, "Relative"), +EP_ENUMEND(WorldLinkType); + +#define ENTITYCLASS CWorldLink + +CEntityProperty CWorldLink_properties[] = { + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x000000d6<<8)+1, offsetof(CWorldLink, m_strGroup), "Group", 'G', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FILENAMENODEP, NULL, (0x000000d6<<8)+2, offsetof(CWorldLink, m_strWorld), "World", 'W', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x000000d6<<8)+3, offsetof(CWorldLink, m_bStoreWorld), "Store world", 'S', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_ENUM, &WorldLinkType_enum, (0x000000d6<<8)+4, offsetof(CWorldLink, m_EwltType), "Type", 'Y', 0x7F0000FFUL, 0), +}; +#define CWorldLink_propertiesct ARRAYCOUNT(CWorldLink_properties) + +CEntityComponent CWorldLink_components[] = { +#define MODEL_WORLDLINK ((0x000000d6<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_WORLDLINK, "EFNM" "Models\\Editor\\WorldLink.mdl"), +#define TEXTURE_WORLDLINK ((0x000000d6<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_WORLDLINK, "EFNM" "Models\\Editor\\WorldLink.tex"), +}; +#define CWorldLink_componentsct ARRAYCOUNT(CWorldLink_components) + +CEventHandlerEntry CWorldLink_handlers[] = { + {1, -1, CEntity::pEventHandler(&CWorldLink:: +#line 52 "D:/SE1_GPL/Sources/EntitiesMP/WorldLink.es" +Main),DEBUGSTRING("CWorldLink::Main")}, +}; +#define CWorldLink_handlersct ARRAYCOUNT(CWorldLink_handlers) + +CEntity *CWorldLink_New(void) { return new CWorldLink; }; +void CWorldLink_OnInitClass(void) {}; +void CWorldLink_OnEndClass(void) {}; +void CWorldLink_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CWorldLink_OnWorldEnd(CWorld *pwo) {}; +void CWorldLink_OnWorldInit(CWorld *pwo) {}; +void CWorldLink_OnWorldTick(CWorld *pwo) {}; +void CWorldLink_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CWorldLink, CMarker, "World link", "Thumbnails\\WorldLink.tbn", 0x000000d6); +DECLARE_CTFILENAME(_fnmCWorldLink_tbn, "Thumbnails\\WorldLink.tbn"); diff --git a/Sources/EntitiesMP/WorldSettingsController.cpp b/Sources/EntitiesMP/WorldSettingsController.cpp new file mode 100644 index 0000000..483d894 --- /dev/null +++ b/Sources/EntitiesMP/WorldSettingsController.cpp @@ -0,0 +1,284 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#line 4 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" + +#include "StdH.h" + +#include +#include +void CWorldSettingsController::SetDefaultProperties(void) { + m_tmStormStart = -1.0f; + m_strName = "World settings controller"; + m_tmLightningStart = -1.0f; + m_fLightningPower = 1.0f; + m_tmStormEnd = -1.0f; + m_tmPyramidPlatesStart = 1e6; + m_tmActivatedPlate1 = 1e6; + m_tmDeactivatedPlate1 = 1e6; + m_tmActivatedPlate2 = 1e6; + m_tmDeactivatedPlate2 = 1e6; + m_tmActivatedPlate3 = 1e6; + m_tmDeactivatedPlate3 = 1e6; + m_tmActivatedPlate4 = 1e6; + m_tmDeactivatedPlate4 = 1e6; + m_tmPyramidMorphRoomActivated = 1e6; + m_tmShakeStarted = -1.0f; + m_vShakePos = FLOAT3D(0 , 0 , 0); + m_fShakeFalloff = 100.0f; + m_fShakeFade = 1.0f; + m_fShakeIntensityY = 1.0f; + m_tmShakeFrequencyY = 1.0f; + m_fShakeIntensityB = 1.0f; + m_tmShakeFrequencyB = 1.0f; + m_fShakeIntensityZ = 1.0f; + m_tmShakeFrequencyZ = 1.0f; + m_bShakeFadeIn = FALSE ; + m_penEnvPartHolder = NULL; + m_bNoSaveGame = FALSE ; + m_tmGlaringStarted = -1.0f; + m_tmGlaringEnded = -1.0f; + m_fGlaringFadeInRatio = 0.1f; + m_fGlaringFadeOutRatio = 0.1f; + m_colGlade = COLOR(C_WHITE | CT_TRANSPARENT ); + m_colBlendStart = COLOR(C_WHITE | CT_TRANSPARENT ); + m_colBlendStop = COLOR(C_WHITE | CT_OPAQUE ); + m_colShadeStart = COLOR(C_WHITE | CT_OPAQUE ); + m_colShadeStop = COLOR(C_GRAY | CT_OPAQUE ); + m_bApplyShadingToModels = FALSE ; + m_tmStormAppearTime = 10.0f; + m_tmStormDisappearTime = 10.0f; + m_penScrollHolder = NULL; + m_penTextFXHolder = NULL; + m_penCreditsHolder = NULL; + m_penHudPicFXHolder = NULL; + CEntity::SetDefaultProperties(); +} + +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +BOOL CWorldSettingsController::IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget) +#line 78 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 79 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(slPropertyOffset == offsetof (CWorldSettingsController , m_penEnvPartHolder )) +#line 80 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 81 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(IsOfClass (penTarget , "EnvironmentParticlesHolder")){return TRUE ;} +#line 82 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +else {return FALSE ;} +#line 83 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 84 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +return CEntity :: IsTargetValid (slPropertyOffset , penTarget ); +#line 85 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} + +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +FLOAT CWorldSettingsController::GetStormFactor(void) +#line 88 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 89 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +FLOAT fStormFactor = 0.0f; +#line 90 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +TIME tmNow = _pTimer -> GetLerpedCurrentTick (); +#line 92 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(tmNow > m_tmStormStart && tmNow < m_tmStormEnd + m_tmStormDisappearTime ) +#line 93 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 95 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(tmNow > m_tmStormStart + m_tmStormAppearTime && tmNow < m_tmStormEnd ) +#line 96 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 97 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +fStormFactor = 1.0f; +#line 98 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 100 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +else if(tmNow > m_tmStormEnd ) +#line 101 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 102 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +fStormFactor = 1.0f - (tmNow - m_tmStormEnd ) / m_tmStormDisappearTime ; +#line 103 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 105 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +else +#line 106 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 107 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +fStormFactor = (tmNow - m_tmStormStart ) / m_tmStormAppearTime ; +#line 108 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 109 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 110 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +return fStormFactor ; +#line 111 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} + +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +BOOL CWorldSettingsController::HandleEvent(const CEntityEvent & ee) +#line 115 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 116 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(ee . ee_slEvent == EVENTCODE_EScroll ) +#line 117 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 118 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +EScroll escr = ((EScroll &) ee ); +#line 119 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(escr . bStart ) +#line 120 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 121 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_penScrollHolder = escr . penSender ; +#line 122 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 123 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +else +#line 124 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 125 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(m_penScrollHolder == escr . penSender ) +#line 126 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 127 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_penScrollHolder = NULL ; +#line 128 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 129 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 130 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +return TRUE ; +#line 131 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 132 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(ee . ee_slEvent == EVENTCODE_ETextFX ) +#line 133 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 134 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +ETextFX etfx = ((ETextFX &) ee ); +#line 135 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(etfx . bStart ) +#line 136 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 137 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_penTextFXHolder = etfx . penSender ; +#line 138 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 139 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +else +#line 140 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 141 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(m_penTextFXHolder == etfx . penSender ) +#line 142 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 143 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_penTextFXHolder = NULL ; +#line 144 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 145 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 146 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +return TRUE ; +#line 147 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 148 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(ee . ee_slEvent == EVENTCODE_EHudPicFX ) +#line 149 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 150 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +EHudPicFX ehpfx = ((EHudPicFX &) ee ); +#line 151 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(ehpfx . bStart ) +#line 152 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 153 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_penHudPicFXHolder = ehpfx . penSender ; +#line 154 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 155 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +else +#line 156 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 157 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(m_penHudPicFXHolder == ehpfx . penSender ) +#line 158 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 159 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_penHudPicFXHolder = NULL ; +#line 160 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 161 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 162 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +return TRUE ; +#line 163 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 164 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(ee . ee_slEvent == EVENTCODE_ECredits ) +#line 165 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 166 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +ECredits ecr = ((ECredits &) ee ); +#line 167 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(ecr . bStart ) +#line 168 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 169 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_penCreditsHolder = ecr . penSender ; +#line 170 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 171 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +else +#line 172 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 173 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +if(m_penCreditsHolder == ecr . penSender ) +#line 174 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +{ +#line 175 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_penCreditsHolder = NULL ; +#line 176 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 177 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 178 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +return TRUE ; +#line 179 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +#line 180 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +return FALSE ; +#line 181 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +} +BOOL CWorldSettingsController:: +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +Main(const CEntityEvent &__eeInput) { +#undef STATE_CURRENT +#define STATE_CURRENT STATE_CWorldSettingsController_Main + ASSERTMSG(__eeInput.ee_slEvent==EVENTCODE_EVoid, "CWorldSettingsController::Main expects 'EVoid' as input!"); const EVoid &e = (const EVoid &)__eeInput; +#line 186 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_penScrollHolder = NULL ; +#line 187 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_penTextFXHolder = NULL ; +#line 189 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +InitAsEditorModel (); +#line 190 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +SetPhysicsFlags (EPF_MODEL_IMMATERIAL ); +#line 191 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +SetCollisionFlags (ECF_IMMATERIAL ); +#line 194 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +SetModel (MODEL_WORLD_SETTINGS_CONTROLLER ); +#line 195 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +SetModelMainTexture (TEXTURE_WORLD_SETTINGS_CONTROLLER ); +#line 197 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_tmStormStart = 1e5 - 1.0f; +#line 198 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +m_tmStormEnd = 1e5; +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +Return(STATE_CURRENT,EVoid()); +#line 201 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +return TRUE; ASSERT(FALSE); return TRUE;}; \ No newline at end of file diff --git a/Sources/EntitiesMP/WorldSettingsController.es b/Sources/EntitiesMP/WorldSettingsController.es new file mode 100644 index 0000000..deceb30 --- /dev/null +++ b/Sources/EntitiesMP/WorldSettingsController.es @@ -0,0 +1,203 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +605 +%{ +#include "StdH.h" +%} + +class CWorldSettingsController: CEntity { +name "WorldSettingsController"; +thumbnail "Thumbnails\\WorldSettingsController.tbn"; +features "IsTargetable", "HasName", "IsImportant"; + +properties: + 1 FLOAT m_tmStormStart = -1.0f, // storm start time + 2 CTString m_strName "Name" 'N' = "World settings controller", // class name + 3 FLOAT m_tmLightningStart = -1.0f, // lightning start time + 4 FLOAT m_fLightningPower = 1.0f, // lightning power + 5 FLOAT m_tmStormEnd = -1.0f, // storm end time + 6 FLOAT m_tmPyramidPlatesStart = 1e6, // time when pyramid plates blend started + 7 FLOAT m_tmActivatedPlate1 = 1e6, // time when plate 1 has been activated + 8 FLOAT m_tmDeactivatedPlate1 = 1e6, // time when plate 1 has been deactivated + 9 FLOAT m_tmActivatedPlate2 = 1e6, // time when plate 2 has been activated + 10 FLOAT m_tmDeactivatedPlate2 = 1e6, // time when plate 2 has been deactivated + 11 FLOAT m_tmActivatedPlate3 = 1e6, // time when plate 3 has been activated + 12 FLOAT m_tmDeactivatedPlate3 = 1e6, // time when plate 3 has been deactivated + 13 FLOAT m_tmActivatedPlate4 = 1e6, // time when plate 4 has been activated + 14 FLOAT m_tmDeactivatedPlate4 = 1e6, // time when plate 4 has been deactivated + 15 FLOAT m_tmPyramidMorphRoomActivated = 1e6, // time when pyramid morph room has been activated + + 20 FLOAT m_tmShakeStarted = -1.0f, // time when shaking started + 21 FLOAT3D m_vShakePos = FLOAT3D(0,0,0), // shake position + 22 FLOAT m_fShakeFalloff = 100.0f, // fall off with distance + 23 FLOAT m_fShakeFade = 1.0f, // fall off with time + 24 FLOAT m_fShakeIntensityY = 1.0f, // shake strength + 25 FLOAT m_tmShakeFrequencyY = 1.0f, // shake strength + 26 FLOAT m_fShakeIntensityB = 1.0f, // shake strength + 27 FLOAT m_tmShakeFrequencyB = 1.0f, // shake strength + 31 FLOAT m_fShakeIntensityZ = 1.0f, // shake strength + 32 FLOAT m_tmShakeFrequencyZ = 1.0f, // shake strength + 33 BOOL m_bShakeFadeIn = FALSE, // TRUE = intensify over time, FALSE = start immediately and falloff + + 28 CEntityPointer m_penEnvPartHolder "Environment Particles Holder" 'T', + 29 BOOL m_bNoSaveGame "No QuickSave on level start"= FALSE, // TRUE means no quicksave will be made when starting this level + //28 CTFileName m_fnHeightMap "Height map" 'R' = CTString(""), + //29 CModelObject m_moHeightMapHolder, + //30 FLOATaabbox3D m_boxHeightMap "Height map box" 'B' = FLOATaabbox3D(FLOAT3D(0,0,0), FLOAT3D(1,1,1)), + + 41 FLOAT m_tmGlaringStarted = -1.0f, // glaring start time + 42 FLOAT m_tmGlaringEnded = -1.0f, // glaring end time + 43 FLOAT m_fGlaringFadeInRatio = 0.1f, // glaring fade in ratio + 44 FLOAT m_fGlaringFadeOutRatio = 0.1f, // glaring fade out ratio + 45 COLOR m_colGlade = COLOR(C_WHITE|CT_TRANSPARENT), + + 50 COLOR m_colBlendStart = COLOR(C_WHITE|CT_TRANSPARENT), + 51 COLOR m_colBlendStop = COLOR(C_WHITE|CT_OPAQUE), + 52 COLOR m_colShadeStart = COLOR(C_WHITE|CT_OPAQUE), + 53 COLOR m_colShadeStop = COLOR(C_GRAY|CT_OPAQUE), + + 55 BOOL m_bApplyShadingToModels "Apply shading to models" = FALSE, + + //60 FLOAT m_tmRainStart = -1.0f, // Rain start time + //61 FLOAT m_tmRainEnd = -1.0f, // Rain end time + 62 FLOAT m_tmStormAppearTime = 10.0f, + 63 FLOAT m_tmStormDisappearTime = 10.0f, + + 70 CEntityPointer m_penScrollHolder, + 71 CEntityPointer m_penTextFXHolder, + 72 CEntityPointer m_penCreditsHolder, + 73 CEntityPointer m_penHudPicFXHolder, + +components: + 1 model MODEL_WORLD_SETTINGS_CONTROLLER "Models\\Editor\\WorldSettingsController.mdl", + 2 texture TEXTURE_WORLD_SETTINGS_CONTROLLER "Models\\Editor\\WorldSettingsController.tex" + +functions: + + BOOL IsTargetValid(SLONG slPropertyOffset, CEntity *penTarget) + { + if( slPropertyOffset == offsetof(CWorldSettingsController, m_penEnvPartHolder)) + { + if (IsOfClass(penTarget, "EnvironmentParticlesHolder")) { return TRUE; } + else { return FALSE; } + } + return CEntity::IsTargetValid(slPropertyOffset, penTarget); + } + + FLOAT GetStormFactor(void) + { + FLOAT fStormFactor = 0.0f; + TIME tmNow = _pTimer->GetLerpedCurrentTick(); + // if we have storm + if( tmNow>m_tmStormStart && tmNowm_tmStormStart+m_tmStormAppearTime && tmNowm_tmStormEnd) + { + fStormFactor = 1.0f-(tmNow-m_tmStormEnd)/m_tmStormDisappearTime; + } + // storm is turning on + else + { + fStormFactor = (tmNow-m_tmStormStart)/m_tmStormAppearTime; + } + } + return fStormFactor; + } + + /* Handle an event, return false if the event is not handled. */ + BOOL HandleEvent(const CEntityEvent &ee) + { + if( ee.ee_slEvent==EVENTCODE_EScroll) + { + EScroll escr = ((EScroll &) ee); + if( escr.bStart) + { + m_penScrollHolder=escr.penSender; + } + else + { + if( m_penScrollHolder==escr.penSender) + { + m_penScrollHolder=NULL; + } + } + return TRUE; + } + if( ee.ee_slEvent==EVENTCODE_ETextFX) + { + ETextFX etfx = ((ETextFX &) ee); + if( etfx.bStart) + { + m_penTextFXHolder=etfx.penSender; + } + else + { + if( m_penTextFXHolder==etfx.penSender) + { + m_penTextFXHolder=NULL; + } + } + return TRUE; + } + if( ee.ee_slEvent==EVENTCODE_EHudPicFX) + { + EHudPicFX ehpfx = ((EHudPicFX &) ee); + if( ehpfx.bStart) + { + m_penHudPicFXHolder=ehpfx.penSender; + } + else + { + if( m_penHudPicFXHolder==ehpfx.penSender) + { + m_penHudPicFXHolder=NULL; + } + } + return TRUE; + } + if( ee.ee_slEvent==EVENTCODE_ECredits) + { + ECredits ecr = ((ECredits &) ee); + if( ecr.bStart) + { + m_penCreditsHolder=ecr.penSender; + } + else + { + if( m_penCreditsHolder==ecr.penSender) + { + m_penCreditsHolder=NULL; + } + } + return TRUE; + } + return FALSE; + } + +procedures: + Main(EVoid) + { + m_penScrollHolder=NULL; + m_penTextFXHolder=NULL; + // set appearance + InitAsEditorModel(); + SetPhysicsFlags(EPF_MODEL_IMMATERIAL); + SetCollisionFlags(ECF_IMMATERIAL); + + // set appearance + SetModel(MODEL_WORLD_SETTINGS_CONTROLLER); + SetModelMainTexture(TEXTURE_WORLD_SETTINGS_CONTROLLER); + + m_tmStormStart = 1e5-1.0f; + m_tmStormEnd = 1e5; + + // do nothing + return; + } +}; diff --git a/Sources/EntitiesMP/WorldSettingsController.h b/Sources/EntitiesMP/WorldSettingsController.h new file mode 100644 index 0000000..4e510ea --- /dev/null +++ b/Sources/EntitiesMP/WorldSettingsController.h @@ -0,0 +1,72 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#ifndef _EntitiesMP_WorldSettingsController_INCLUDED +#define _EntitiesMP_WorldSettingsController_INCLUDED 1 +extern "C" DECL_DLL CDLLEntityClass CWorldSettingsController_DLLClass; +class CWorldSettingsController : public CEntity { +public: +virtual BOOL IsTargetable(void) const { return TRUE; }; +virtual const CTString &GetName(void) const { return m_strName; }; +virtual BOOL IsImportant(void) const { return TRUE; }; + DECL_DLL virtual void SetDefaultProperties(void); + FLOAT m_tmStormStart; + CTString m_strName; + FLOAT m_tmLightningStart; + FLOAT m_fLightningPower; + FLOAT m_tmStormEnd; + FLOAT m_tmPyramidPlatesStart; + FLOAT m_tmActivatedPlate1; + FLOAT m_tmDeactivatedPlate1; + FLOAT m_tmActivatedPlate2; + FLOAT m_tmDeactivatedPlate2; + FLOAT m_tmActivatedPlate3; + FLOAT m_tmDeactivatedPlate3; + FLOAT m_tmActivatedPlate4; + FLOAT m_tmDeactivatedPlate4; + FLOAT m_tmPyramidMorphRoomActivated; + FLOAT m_tmShakeStarted; + FLOAT3D m_vShakePos; + FLOAT m_fShakeFalloff; + FLOAT m_fShakeFade; + FLOAT m_fShakeIntensityY; + FLOAT m_tmShakeFrequencyY; + FLOAT m_fShakeIntensityB; + FLOAT m_tmShakeFrequencyB; + FLOAT m_fShakeIntensityZ; + FLOAT m_tmShakeFrequencyZ; + BOOL m_bShakeFadeIn; + CEntityPointer m_penEnvPartHolder; + BOOL m_bNoSaveGame; + FLOAT m_tmGlaringStarted; + FLOAT m_tmGlaringEnded; + FLOAT m_fGlaringFadeInRatio; + FLOAT m_fGlaringFadeOutRatio; + COLOR m_colGlade; + COLOR m_colBlendStart; + COLOR m_colBlendStop; + COLOR m_colShadeStart; + COLOR m_colShadeStop; + BOOL m_bApplyShadingToModels; + FLOAT m_tmStormAppearTime; + FLOAT m_tmStormDisappearTime; + CEntityPointer m_penScrollHolder; + CEntityPointer m_penTextFXHolder; + CEntityPointer m_penCreditsHolder; + CEntityPointer m_penHudPicFXHolder; + +#line 77 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +BOOL IsTargetValid(SLONG slPropertyOffset,CEntity * penTarget); + +#line 87 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +FLOAT GetStormFactor(void); + +#line 114 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +BOOL HandleEvent(const CEntityEvent & ee); +#define STATE_CWorldSettingsController_Main 1 + BOOL +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +Main(const CEntityEvent &__eeInput); +}; +#endif // _EntitiesMP_WorldSettingsController_INCLUDED diff --git a/Sources/EntitiesMP/WorldSettingsController_tables.h b/Sources/EntitiesMP/WorldSettingsController_tables.h new file mode 100644 index 0000000..f0249b2 --- /dev/null +++ b/Sources/EntitiesMP/WorldSettingsController_tables.h @@ -0,0 +1,79 @@ +/* + * This file is generated by Entity Class Compiler, (c) CroTeam 1997-98 + */ + +#define ENTITYCLASS CWorldSettingsController + +CEntityProperty CWorldSettingsController_properties[] = { + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+1, offsetof(CWorldSettingsController, m_tmStormStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_STRING, NULL, (0x0000025d<<8)+2, offsetof(CWorldSettingsController, m_strName), "Name", 'N', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+3, offsetof(CWorldSettingsController, m_tmLightningStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+4, offsetof(CWorldSettingsController, m_fLightningPower), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+5, offsetof(CWorldSettingsController, m_tmStormEnd), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+6, offsetof(CWorldSettingsController, m_tmPyramidPlatesStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+7, offsetof(CWorldSettingsController, m_tmActivatedPlate1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+8, offsetof(CWorldSettingsController, m_tmDeactivatedPlate1), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+9, offsetof(CWorldSettingsController, m_tmActivatedPlate2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+10, offsetof(CWorldSettingsController, m_tmDeactivatedPlate2), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+11, offsetof(CWorldSettingsController, m_tmActivatedPlate3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+12, offsetof(CWorldSettingsController, m_tmDeactivatedPlate3), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+13, offsetof(CWorldSettingsController, m_tmActivatedPlate4), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+14, offsetof(CWorldSettingsController, m_tmDeactivatedPlate4), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+15, offsetof(CWorldSettingsController, m_tmPyramidMorphRoomActivated), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+20, offsetof(CWorldSettingsController, m_tmShakeStarted), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT3D, NULL, (0x0000025d<<8)+21, offsetof(CWorldSettingsController, m_vShakePos), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+22, offsetof(CWorldSettingsController, m_fShakeFalloff), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+23, offsetof(CWorldSettingsController, m_fShakeFade), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+24, offsetof(CWorldSettingsController, m_fShakeIntensityY), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+25, offsetof(CWorldSettingsController, m_tmShakeFrequencyY), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+26, offsetof(CWorldSettingsController, m_fShakeIntensityB), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+27, offsetof(CWorldSettingsController, m_tmShakeFrequencyB), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+31, offsetof(CWorldSettingsController, m_fShakeIntensityZ), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+32, offsetof(CWorldSettingsController, m_tmShakeFrequencyZ), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000025d<<8)+33, offsetof(CWorldSettingsController, m_bShakeFadeIn), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025d<<8)+28, offsetof(CWorldSettingsController, m_penEnvPartHolder), "Environment Particles Holder", 'T', 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000025d<<8)+29, offsetof(CWorldSettingsController, m_bNoSaveGame), "No QuickSave on level start", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+41, offsetof(CWorldSettingsController, m_tmGlaringStarted), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+42, offsetof(CWorldSettingsController, m_tmGlaringEnded), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+43, offsetof(CWorldSettingsController, m_fGlaringFadeInRatio), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+44, offsetof(CWorldSettingsController, m_fGlaringFadeOutRatio), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025d<<8)+45, offsetof(CWorldSettingsController, m_colGlade), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025d<<8)+50, offsetof(CWorldSettingsController, m_colBlendStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025d<<8)+51, offsetof(CWorldSettingsController, m_colBlendStop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025d<<8)+52, offsetof(CWorldSettingsController, m_colShadeStart), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_COLOR, NULL, (0x0000025d<<8)+53, offsetof(CWorldSettingsController, m_colShadeStop), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_BOOL, NULL, (0x0000025d<<8)+55, offsetof(CWorldSettingsController, m_bApplyShadingToModels), "Apply shading to models", 0, 0x7F0000FFUL, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+62, offsetof(CWorldSettingsController, m_tmStormAppearTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_FLOAT, NULL, (0x0000025d<<8)+63, offsetof(CWorldSettingsController, m_tmStormDisappearTime), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025d<<8)+70, offsetof(CWorldSettingsController, m_penScrollHolder), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025d<<8)+71, offsetof(CWorldSettingsController, m_penTextFXHolder), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025d<<8)+72, offsetof(CWorldSettingsController, m_penCreditsHolder), "", 0, 0, 0), + CEntityProperty(CEntityProperty::EPT_ENTITYPTR, NULL, (0x0000025d<<8)+73, offsetof(CWorldSettingsController, m_penHudPicFXHolder), "", 0, 0, 0), +}; +#define CWorldSettingsController_propertiesct ARRAYCOUNT(CWorldSettingsController_properties) + +CEntityComponent CWorldSettingsController_components[] = { +#define MODEL_WORLD_SETTINGS_CONTROLLER ((0x0000025d<<8)+1) + CEntityComponent(ECT_MODEL, MODEL_WORLD_SETTINGS_CONTROLLER, "EFNM" "Models\\Editor\\WorldSettingsController.mdl"), +#define TEXTURE_WORLD_SETTINGS_CONTROLLER ((0x0000025d<<8)+2) + CEntityComponent(ECT_TEXTURE, TEXTURE_WORLD_SETTINGS_CONTROLLER, "EFNM" "Models\\Editor\\WorldSettingsController.tex"), +}; +#define CWorldSettingsController_componentsct ARRAYCOUNT(CWorldSettingsController_components) + +CEventHandlerEntry CWorldSettingsController_handlers[] = { + {1, -1, CEntity::pEventHandler(&CWorldSettingsController:: +#line 184 "D:/SE1_GPL/Sources/EntitiesMP/WorldSettingsController.es" +Main),DEBUGSTRING("CWorldSettingsController::Main")}, +}; +#define CWorldSettingsController_handlersct ARRAYCOUNT(CWorldSettingsController_handlers) + +CEntity *CWorldSettingsController_New(void) { return new CWorldSettingsController; }; +void CWorldSettingsController_OnInitClass(void) {}; +void CWorldSettingsController_OnEndClass(void) {}; +void CWorldSettingsController_OnPrecache(CDLLEntityClass *pdec, INDEX iUser) {}; +void CWorldSettingsController_OnWorldEnd(CWorld *pwo) {}; +void CWorldSettingsController_OnWorldInit(CWorld *pwo) {}; +void CWorldSettingsController_OnWorldTick(CWorld *pwo) {}; +void CWorldSettingsController_OnWorldRender(CWorld *pwo) {}; +ENTITY_CLASSDEFINITION(CWorldSettingsController, CEntity, "WorldSettingsController", "Thumbnails\\WorldSettingsController.tbn", 0x0000025d); +DECLARE_CTFILENAME(_fnmCWorldSettingsController_tbn, "Thumbnails\\WorldSettingsController.tbn"); diff --git a/Sources/GameGUIMP/ActionsListControl.cpp b/Sources/GameGUIMP/ActionsListControl.cpp new file mode 100644 index 0000000..51abc1e --- /dev/null +++ b/Sources/GameGUIMP/ActionsListControl.cpp @@ -0,0 +1,185 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// ActionsListControl.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CActionsListControl + +CActionsListControl::CActionsListControl() +{ +} + +CActionsListControl::~CActionsListControl() +{ +} + + +BEGIN_MESSAGE_MAP(CActionsListControl, CListCtrl) + //{{AFX_MSG_MAP(CActionsListControl) + ON_WM_LBUTTONDOWN() + ON_WM_KEYUP() + ON_WM_KEYDOWN() + ON_WM_SETFOCUS() + ON_WM_KILLFOCUS() + ON_WM_CONTEXTMENU() + ON_COMMAND(ID_BUTTON_ACTION_ADD, OnButtonActionAdd) + ON_COMMAND(ID_BUTTON_ACTION_EDIT, OnButtonActionEdit) + ON_COMMAND(ID_BUTTON_ACTION_REMOVE, OnButtonActionRemove) + ON_UPDATE_COMMAND_UI(ID_BUTTON_ACTION_EDIT, OnUpdateButtonActionEdit) + ON_UPDATE_COMMAND_UI(ID_BUTTON_ACTION_REMOVE, OnUpdateButtonActionRemove) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CActionsListControl message handlers + +void CActionsListControl::OnLButtonDown(UINT nFlags, CPoint point) +{ + // get no of items + INDEX iButtonsCt = ((CDlgPlayerControls *)GetParent())->m_listButtonActions.GetItemCount(); + // get no of items + for( INDEX iListItem=0; iListItemm_listButtonActions.SetItemState( iListItem, 0, LVIS_FOCUSED|LVIS_SELECTED|LVIS_DROPHILITED); + } + + CListCtrl::OnLButtonDown(nFlags, point); + + /* + // select wanted item + ((CDlgPlayerControls *)GetParent())->m_listButtonActions.SetItemState( iSelectedButton+1, + LVIS_FOCUSED|LVIS_SELECTED|LVIS_DROPHILITED, LVIS_FOCUSED|LVIS_SELECTED|LVIS_DROPHILITED); + ((CDlgPlayerControls *)GetParent())->m_listButtonActions.EnsureVisible( iSelectedButton+1, FALSE); + ((CDlgPlayerControls *)GetParent())->m_listButtonActions.SetFocus(); + */ + ((CDlgPlayerControls *)GetParent())->SetFirstAndSecondButtonNames(); +} + +void CActionsListControl::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + CListCtrl::OnKeyUp(nChar, nRepCnt, nFlags); + ((CDlgPlayerControls *)GetParent())->SetFirstAndSecondButtonNames(); +} + +void CActionsListControl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags); + ((CDlgPlayerControls *)GetParent())->SetFirstAndSecondButtonNames(); +} + + +void CActionsListControl::OnSetFocus(CWnd* pOldWnd) +{ + // get selected action + INDEX iSelectedAction = GetNextItem( -1, LVIS_SELECTED); + // if none is selected (initial state) + if( iSelectedAction == -1) + { + iSelectedAction = 0; + SetItemState( iSelectedAction, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); + } + else + { + // clear hilighted state + SetItemState( iSelectedAction, 0, LVIS_DROPHILITED); + } + + CListCtrl::OnSetFocus(pOldWnd); +} + +void CActionsListControl::OnKillFocus(CWnd* pNewWnd) +{ + CListCtrl::OnKillFocus(pNewWnd); + + // get selected action + INDEX iSelectedAction = GetNextItem( -1, LVNI_SELECTED); + // set hilighted state + SetItemState( iSelectedAction, LVIS_DROPHILITED, LVIS_DROPHILITED); +} + + +BOOL CActionsListControl::PreTranslateMessage(MSG* pMsg) +{ + // if return pressed + if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN) + { + ((CDlgPlayerControls *)GetParent())->m_editFirstControl.SetFocus(); + // don't translate messages + return TRUE; + } + return CListCtrl::PreTranslateMessage(pMsg); +} + +void CActionsListControl::OnContextMenu(CWnd* pWnd, CPoint point) +{ + CMenu menu; + if( menu.LoadMenu( IDR_BUTTON_ACTION_POPUP)) + { + CMenu* pPopup = menu.GetSubMenu(0); + ASSERT(pPopup != NULL); + pPopup->TrackPopupMenu( TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_LEFTALIGN, + point.x, point.y, this); + } +} + + +void CActionsListControl::OnButtonActionAdd() +{ + CDlgPlayerControls *pDlg = (CDlgPlayerControls *)GetParent(); + // create new button action + CButtonAction *pbaAddedButtonAction = &pDlg->m_ctrlControls.AddButtonAction(); + // call edit button dialog + CDlgEditButtonAction dlgEditButtonAction( pbaAddedButtonAction); + dlgEditButtonAction.DoModal(); + // refresh list of button actions + pDlg->FillActionsList(); +} + +void CActionsListControl::OnButtonActionEdit() +{ + // obtain selected button action + CButtonAction *pbaToEdit = ((CDlgPlayerControls *)GetParent())->GetSelectedButtonAction(); + ASSERT( pbaToEdit != NULL); + + // call edit button dialog + CDlgEditButtonAction dlgEditButtonAction( pbaToEdit); + dlgEditButtonAction.DoModal(); + + // refresh list of button actions + ((CDlgPlayerControls *)GetParent())->FillActionsList(); +} + +void CActionsListControl::OnButtonActionRemove() +{ + // obtain selected button action + CButtonAction *pbaToRemove = ((CDlgPlayerControls *)GetParent())->GetSelectedButtonAction(); + ASSERT( pbaToRemove != NULL); + ((CDlgPlayerControls *)GetParent())->m_ctrlControls.RemoveButtonAction( *pbaToRemove); + + // refresh list of button actions + ((CDlgPlayerControls *)GetParent())->FillActionsList(); +} + +void CActionsListControl::OnUpdateButtonActionEdit(CCmdUI* pCmdUI) +{ + // obtain selected button action + CButtonAction *pbaToEdit = ((CDlgPlayerControls *)GetParent())->GetSelectedButtonAction(); + pCmdUI->Enable( pbaToEdit != NULL); +} + +void CActionsListControl::OnUpdateButtonActionRemove(CCmdUI* pCmdUI) +{ + // obtain selected button action + CButtonAction *pbaToEdit = ((CDlgPlayerControls *)GetParent())->GetSelectedButtonAction(); + pCmdUI->Enable( pbaToEdit != NULL); +} diff --git a/Sources/GameGUIMP/ActionsListControl.h b/Sources/GameGUIMP/ActionsListControl.h new file mode 100644 index 0000000..7285bfe --- /dev/null +++ b/Sources/GameGUIMP/ActionsListControl.h @@ -0,0 +1,56 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// ActionsListControl.h : header file +// + +#ifndef ACTIONSLISTCONTROL_H +#define ACTIONSLISTCONTROL_H 1 + +///////////////////////////////////////////////////////////////////////////// +// CActionsListControl window + +class CActionsListControl : public CListCtrl +{ +// Construction +public: + CActionsListControl(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CActionsListControl) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CActionsListControl(); + + // Generated message map functions +//protected: +public: + //{{AFX_MSG(CActionsListControl) + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnSetFocus(CWnd* pOldWnd); + afx_msg void OnKillFocus(CWnd* pNewWnd); + afx_msg void OnContextMenu(CWnd* pWnd, CPoint point); + afx_msg void OnButtonActionAdd(); + afx_msg void OnButtonActionEdit(); + afx_msg void OnButtonActionRemove(); + afx_msg void OnUpdateButtonActionEdit(CCmdUI* pCmdUI); + afx_msg void OnUpdateButtonActionRemove(CCmdUI* pCmdUI); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +#endif // ACTIONSLISTCONTROL_H 1 diff --git a/Sources/GameGUIMP/AxisListCtrl.cpp b/Sources/GameGUIMP/AxisListCtrl.cpp new file mode 100644 index 0000000..be96b7f --- /dev/null +++ b/Sources/GameGUIMP/AxisListCtrl.cpp @@ -0,0 +1,107 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// AxisListCtrl.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CAxisListCtrl + +CAxisListCtrl::CAxisListCtrl() +{ +} + +CAxisListCtrl::~CAxisListCtrl() +{ +} + + +BEGIN_MESSAGE_MAP(CAxisListCtrl, CListCtrl) + //{{AFX_MSG_MAP(CAxisListCtrl) + ON_WM_LBUTTONDOWN() + ON_WM_KEYUP() + ON_WM_KEYDOWN() + ON_WM_SETFOCUS() + ON_WM_KILLFOCUS() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CAxisListCtrl message handlers + +void CAxisListCtrl::OnLButtonDown(UINT nFlags, CPoint point) +{ + // remember current state of controler's attributes + ((CDlgPlayerControls *)GetParent())->UpdateData( TRUE); + CListCtrl::OnLButtonDown(nFlags, point); + // set state of new controler's attributes + ((CDlgPlayerControls *)GetParent())->UpdateData(FALSE); +} + +void CAxisListCtrl::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // remember current state of controler's attributes + ((CDlgPlayerControls *)GetParent())->UpdateData( TRUE); + CListCtrl::OnKeyUp(nChar, nRepCnt, nFlags); + // set state of new controler's attributes + ((CDlgPlayerControls *)GetParent())->UpdateData(FALSE); +} + +void CAxisListCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // remember current state of controler's attributes + ((CDlgPlayerControls *)GetParent())->UpdateData( TRUE); + CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags); + // set state of new controler's attributes + ((CDlgPlayerControls *)GetParent())->UpdateData(FALSE); +} + + +void CAxisListCtrl::OnSetFocus(CWnd* pOldWnd) +{ + // get selected action + INDEX iSelectedAction = GetNextItem( -1, LVNI_DROPHILITED); + // if none is selected (initial state) + if( iSelectedAction == -1) + { + iSelectedAction = 0; + SetItemState( iSelectedAction, LVIS_FOCUSED|LVIS_SELECTED, LVIS_FOCUSED|LVIS_SELECTED); + } + else + { + // clear hilighted state + SetItemState( iSelectedAction, 0, LVIS_DROPHILITED); + } + + CListCtrl::OnSetFocus(pOldWnd); +} + +void CAxisListCtrl::OnKillFocus(CWnd* pNewWnd) +{ + CListCtrl::OnKillFocus(pNewWnd); + + // get selected action + INDEX iSelectedAction = GetNextItem( -1, LVNI_SELECTED); + // set hilighted state + SetItemState( iSelectedAction, LVIS_DROPHILITED, LVIS_DROPHILITED); +} + +BOOL CAxisListCtrl::PreTranslateMessage(MSG* pMsg) +{ + // if return pressed + if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN) + { + ((CDlgPlayerControls *)GetParent())->m_comboControlerAxis.SetFocus(); + // don't translate messages + return TRUE; + } + return CListCtrl::PreTranslateMessage(pMsg); +} diff --git a/Sources/GameGUIMP/AxisListCtrl.h b/Sources/GameGUIMP/AxisListCtrl.h new file mode 100644 index 0000000..7dc3a71 --- /dev/null +++ b/Sources/GameGUIMP/AxisListCtrl.h @@ -0,0 +1,49 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// AxisListCtrl.h : header file +// + +#ifndef AXISLISTCTRL_H +#define AXISLISTCTRL_H 1 + +///////////////////////////////////////////////////////////////////////////// +// CAxisListCtrl window + +class CAxisListCtrl : public CListCtrl +{ +// Construction +public: + CAxisListCtrl(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAxisListCtrl) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CAxisListCtrl(); + + // Generated message map functions +protected: + //{{AFX_MSG(CAxisListCtrl) + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnSetFocus(CWnd* pOldWnd); + afx_msg void OnKillFocus(CWnd* pNewWnd); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +#endif // AXISLISTCTRL_H \ No newline at end of file diff --git a/Sources/GameGUIMP/ConsoleSymbolsCombo.cpp b/Sources/GameGUIMP/ConsoleSymbolsCombo.cpp new file mode 100644 index 0000000..dcb93d3 --- /dev/null +++ b/Sources/GameGUIMP/ConsoleSymbolsCombo.cpp @@ -0,0 +1,77 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// ConsoleSymbolsCombo.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CConsoleSymbolsCombo + +CConsoleSymbolsCombo::CConsoleSymbolsCombo() +{ +} + +CConsoleSymbolsCombo::~CConsoleSymbolsCombo() +{ +} + + +BEGIN_MESSAGE_MAP(CConsoleSymbolsCombo, CComboBox) + //{{AFX_MSG_MAP(CConsoleSymbolsCombo) + ON_CONTROL_REFLECT(CBN_SELCHANGE, OnSelchange) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CConsoleSymbolsCombo message handlers + +BOOL CConsoleSymbolsCombo::PreTranslateMessage(MSG* pMsg) +{ + if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN) + { + INDEX iSelectedSymbol = GetCurSel(); + // if there is a valid player selected + if( iSelectedSymbol != LB_ERR) + { + CString strSelectedSymbolW; + GetLBText( iSelectedSymbol, strSelectedSymbolW); + CTString strSelectedSymbol = CStringA(strSelectedSymbolW); + + INDEX ctLetters = strlen(strSelectedSymbol); + char achrSelectedSymbol[ 256]; + sprintf( achrSelectedSymbol, strSelectedSymbol); + if( achrSelectedSymbol[ ctLetters-1] == ']') + { + for( INDEX iLetter=ctLetters-2; iLetter>0; iLetter--) + { + ASSERT( iLetter>0); + if( ((char *)achrSelectedSymbol)[ iLetter] == '[') + { + achrSelectedSymbol[ iLetter+1] = ']'; + achrSelectedSymbol[ iLetter+2] = 0; + strSelectedSymbol = achrSelectedSymbol; + break; + } + } + } + + ((CDlgConsole *)GetParent())->m_ctrlEditConsole.ReplaceSel( CString(strSelectedSymbol), TRUE); + ((CDlgConsole *)GetParent())->m_ctrlEditConsole.SetFocus(); + return TRUE; + } + } + return CComboBox::PreTranslateMessage(pMsg); +} + +void CConsoleSymbolsCombo::OnSelchange() +{ + ShowDropDown( TRUE); +} diff --git a/Sources/GameGUIMP/ConsoleSymbolsCombo.h b/Sources/GameGUIMP/ConsoleSymbolsCombo.h new file mode 100644 index 0000000..ea10bca --- /dev/null +++ b/Sources/GameGUIMP/ConsoleSymbolsCombo.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#if !defined(AFX_CONSOLESYMBOLSCOMBO_H__E417EA91_1B23_11D2_834D_004095812ACC__INCLUDED_) +#define AFX_CONSOLESYMBOLSCOMBO_H__E417EA91_1B23_11D2_834D_004095812ACC__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// ConsoleSymbolsCombo.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CConsoleSymbolsCombo window + +class CConsoleSymbolsCombo : public CComboBox +{ +// Construction +public: + CConsoleSymbolsCombo(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CConsoleSymbolsCombo) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CConsoleSymbolsCombo(); + + // Generated message map functions +protected: + //{{AFX_MSG(CConsoleSymbolsCombo) + afx_msg void OnSelchange(); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CONSOLESYMBOLSCOMBO_H__E417EA91_1B23_11D2_834D_004095812ACC__INCLUDED_) diff --git a/Sources/GameGUIMP/DlgAudioQuality.cpp b/Sources/GameGUIMP/DlgAudioQuality.cpp new file mode 100644 index 0000000..a3e2f2a --- /dev/null +++ b/Sources/GameGUIMP/DlgAudioQuality.cpp @@ -0,0 +1,77 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgAudioQuality.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgAudioQuality dialog + + +CDlgAudioQuality::CDlgAudioQuality(CWnd* pParent /*=NULL*/) + : CDialog(CDlgAudioQuality::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgAudioQuality) + m_iAudioQualityRadio = -1; + m_bUseDirectSound3D = FALSE; + //}}AFX_DATA_INIT +} + + +void CDlgAudioQuality::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + + // if dialog is recieving data + if( pDX->m_bSaveAndValidate == FALSE) + { + // set current state of audio quality radio button +/* switch( Flesh.gm_aqAudioQuality) + { + case CGame::AQ_LOW:{ m_iAudioQualityRadio = 0; break; } + case CGame::AQ_MEDIUM:{ m_iAudioQualityRadio = 1; break; } + case CGame::AQ_HIGH:{ m_iAudioQualityRadio = 2; break; } + default:{ ASSERTALWAYS( "Illegal audio quality value found!"); } + } + */ + m_bUseDirectSound3D = FALSE; + } + + //{{AFX_DATA_MAP(CDlgAudioQuality) + DDX_Radio(pDX, IDC_AUDIO_QUALITY_LOW, m_iAudioQualityRadio); + DDX_Check(pDX, IDC_USE_DSOUND3D, m_bUseDirectSound3D); + //}}AFX_DATA_MAP + + // if dialog is giving data + if( pDX->m_bSaveAndValidate != FALSE) + { + // apply selected state of audio quality radio button +/* switch( m_iAudioQualityRadio) + { + case 0:{ Flesh.gm_aqAudioQuality = CGame::AQ_LOW; break; } + case 1:{ Flesh.gm_aqAudioQuality = CGame::AQ_MEDIUM; break; } + case 2:{ Flesh.gm_aqAudioQuality = CGame::AQ_HIGH; break; } + default:{ ASSERTALWAYS( "Illegal audio quality radio value found!"); } + } + */ + //Flesh.gm_bUseDirectSound3D = m_bUseDirectSound3D; + } +} + + +BEGIN_MESSAGE_MAP(CDlgAudioQuality, CDialog) + //{{AFX_MSG_MAP(CDlgAudioQuality) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgAudioQuality message handlers diff --git a/Sources/GameGUIMP/DlgAudioQuality.h b/Sources/GameGUIMP/DlgAudioQuality.h new file mode 100644 index 0000000..dd7e59b --- /dev/null +++ b/Sources/GameGUIMP/DlgAudioQuality.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgAudioQuality.h : header file +// +#ifndef DLGAUDIOQUALITY_H +#define DLGAUDIOQUALITY_H 1 + +///////////////////////////////////////////////////////////////////////////// +// CDlgAudioQuality dialog + +class CDlgAudioQuality : public CDialog +{ +// Construction +public: + CDlgAudioQuality(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDlgAudioQuality) + enum { IDD = IDD_AUDIO_QUALITY }; + int m_iAudioQualityRadio; + BOOL m_bUseDirectSound3D; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgAudioQuality) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgAudioQuality) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; +#endif // DLGAUDIOQUALITY_H \ No newline at end of file diff --git a/Sources/GameGUIMP/DlgConsole.cpp b/Sources/GameGUIMP/DlgConsole.cpp new file mode 100644 index 0000000..63390e0 --- /dev/null +++ b/Sources/GameGUIMP/DlgConsole.cpp @@ -0,0 +1,113 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgConsole.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgConsole dialog + +CDlgConsole::CDlgConsole(CWnd* pParent /*=NULL*/) + : CDialog(CDlgConsole::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgConsole) + m_strConsoleOutput = _T(""); + //}}AFX_DATA_INIT +} + + +void CDlgConsole::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + + //{{AFX_DATA_MAP(CDlgConsole) + DDX_Control(pDX, IDC_CONSOLE_SYMBOLS, m_ctrConsoleSymbolsCombo); + DDX_Control(pDX, IDC_CONSOLE_INPUT, m_ctrlEditConsole); + DDX_Text(pDX, IDC_CONSOLE_OUTPUT, m_strConsoleOutput); + //}}AFX_DATA_MAP + + // if dialog is reciving data + if( pDX->m_bSaveAndValidate == FALSE) + { + //m_strConsoleOutput = "Default output string"; +// m_strConsoleOutput = _pConsole->GetBuffer(); + m_ctrlEditConsole.SetTextFromConsole(); + } +} + + +BEGIN_MESSAGE_MAP(CDlgConsole, CDialog) + //{{AFX_MSG_MAP(CDlgConsole) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgConsole message handlers + +BOOL CDlgConsole::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // set default console text + //m_ctrlEditConsole.SetWindowText( "Default input string"); + m_ctrlEditConsole.SetWindowText( CString(_pGame->gam_strConsoleInputBuffer)); + + /* + // create application windows font for console + LOGFONT logFont; + CFont fntFont; + memset(&logFont, 0, sizeof(logFont)); + if (!::GetSystemMetrics(SM_DBCSENABLED)) + { + logFont.lfHeight = -11; + logFont.lfWeight = FW_REGULAR; + logFont.lfPitchAndFamily = FF_ROMAN|FIXED_PITCH; + logFont.lfOrientation = 10; + logFont.lfQuality = PROOF_QUALITY; + logFont.lfItalic = TRUE; + // prepare default font name + CString strDefaultFont; + strDefaultFont.LoadString(IDS_DEFAULT_ARIAL); + lstrcpy(logFont.lfFaceName, strDefaultFont); + // try to create font + if( !fntFont.CreateFontIndirect(&logFont)) + TRACE0("Could Not create font for console\n"); + } + else + { + fntFont.Attach(::GetStockObject(SYSTEM_FONT)); + } + m_ctrlEditConsole.SetFont( &fntFont); + */ + + // fill symbols combo box + m_ctrConsoleSymbolsCombo.ResetContent(); + // for each of symbols in the shell + FOREACHINDYNAMICARRAY(_pShell->sh_assSymbols, CShellSymbol, itss) + { + // if it is not visible to user + if (!(itss->ss_ulFlags&SSF_USER)) { + // skip it + continue; + } + // get completion name for that symbol + CTString strSymbol = itss->GetCompletionString(); + // add string to console + m_ctrConsoleSymbolsCombo.AddString( CString(strSymbol)); + } + // select first combo member + m_ctrConsoleSymbolsCombo.SetCurSel( 0); + + m_ctrlEditConsole.SetSel( -1, 60000); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/Sources/GameGUIMP/DlgConsole.h b/Sources/GameGUIMP/DlgConsole.h new file mode 100644 index 0000000..7653b05 --- /dev/null +++ b/Sources/GameGUIMP/DlgConsole.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#if !defined(AFX_DLGCONSOLE_H__833B8175_E923_11D1_82A7_000000000000__INCLUDED_) +#define AFX_DLGCONSOLE_H__833B8175_E923_11D1_82A7_000000000000__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// DlgConsole.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgConsole dialog + +class CDlgConsole : public CDialog +{ +// Construction +public: + CDlgConsole(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDlgConsole) + enum { IDD = IDD_CONSOLE }; + CConsoleSymbolsCombo m_ctrConsoleSymbolsCombo; + CEditConsole m_ctrlEditConsole; + CString m_strConsoleOutput; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgConsole) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgConsole) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGCONSOLE_H__833B8175_E923_11D1_82A7_000000000000__INCLUDED_) diff --git a/Sources/GameGUIMP/DlgEditButtonAction.cpp b/Sources/GameGUIMP/DlgEditButtonAction.cpp new file mode 100644 index 0000000..f01925e --- /dev/null +++ b/Sources/GameGUIMP/DlgEditButtonAction.cpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgEditButtonAction.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgEditButtonAction dialog + + +CDlgEditButtonAction::CDlgEditButtonAction(CButtonAction *pbaButtonAction, + CWnd* pParent /*=NULL*/) + : CDialog(CDlgEditButtonAction::IDD, pParent) +{ + // remember button action that is edited + m_pbaButtonAction = pbaButtonAction; + + //{{AFX_DATA_INIT(CDlgEditButtonAction) + m_strButtonActionName = _T(""); + m_strButtonDownCommand = _T(""); + m_strButtonUpCommand = _T(""); + //}}AFX_DATA_INIT +} + + +void CDlgEditButtonAction::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + // if dialog is recieving data + if( pDX->m_bSaveAndValidate == FALSE) + { + m_strButtonActionName = m_pbaButtonAction->ba_strName; + m_strButtonDownCommand = m_pbaButtonAction->ba_strCommandLineWhenPressed; + m_strButtonUpCommand = m_pbaButtonAction->ba_strCommandLineWhenReleased; + } + + //{{AFX_DATA_MAP(CDlgEditButtonAction) + DDX_Text(pDX, IDC_BUTTON_ACTION_NAME, m_strButtonActionName); + DDX_Text(pDX, IDC_BUTTON_DOWN_COMMAND, m_strButtonDownCommand); + DDX_Text(pDX, IDC_BUTTON_UP_COMMAND, m_strButtonUpCommand); + //}}AFX_DATA_MAP + + // if dialog is giving data + if( pDX->m_bSaveAndValidate != FALSE) + { + m_pbaButtonAction->ba_strName = m_strButtonActionName; + m_pbaButtonAction->ba_strCommandLineWhenPressed = m_strButtonDownCommand; + m_pbaButtonAction->ba_strCommandLineWhenReleased = m_strButtonUpCommand; + } +} + + +BEGIN_MESSAGE_MAP(CDlgEditButtonAction, CDialog) + //{{AFX_MSG_MAP(CDlgEditButtonAction) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgEditButtonAction message handlers diff --git a/Sources/GameGUIMP/DlgEditButtonAction.h b/Sources/GameGUIMP/DlgEditButtonAction.h new file mode 100644 index 0000000..ac89302 --- /dev/null +++ b/Sources/GameGUIMP/DlgEditButtonAction.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#if !defined(AFX_DLGEDITBUTTONACTION_H__3BD6B3E1_EE74_11D1_9AC2_00409580357B__INCLUDED_) +#define AFX_DLGEDITBUTTONACTION_H__3BD6B3E1_EE74_11D1_9AC2_00409580357B__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// DlgEditButtonAction.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgEditButtonAction dialog + +class CDlgEditButtonAction : public CDialog +{ +// Construction +public: + CButtonAction *m_pbaButtonAction; + CDlgEditButtonAction(CButtonAction *pbaButtonAction, CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDlgEditButtonAction) + enum { IDD = IDD_EDIT_BUTTON_ACTION }; + CString m_strButtonActionName; + CString m_strButtonDownCommand; + CString m_strButtonUpCommand; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgEditButtonAction) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgEditButtonAction) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGEDITBUTTONACTION_H__3BD6B3E1_EE74_11D1_9AC2_00409580357B__INCLUDED_) diff --git a/Sources/GameGUIMP/DlgPlayerAppearance.cpp b/Sources/GameGUIMP/DlgPlayerAppearance.cpp new file mode 100644 index 0000000..6495206 --- /dev/null +++ b/Sources/GameGUIMP/DlgPlayerAppearance.cpp @@ -0,0 +1,47 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgPlayerAppearance.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgPlayerAppearance dialog + + +CDlgPlayerAppearance::CDlgPlayerAppearance(CPlayerCharacter &pcPlayerCharacter, + CWnd* pParent /*=NULL*/) + : CDialog(CDlgPlayerAppearance::IDD, pParent) +{ + // make a copy of player's appearance, we will change it + m_pcPlayerCharacter = pcPlayerCharacter; + //{{AFX_DATA_INIT(CDlgPlayerAppearance) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CDlgPlayerAppearance::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDlgPlayerAppearance) + DDX_Control(pDX, IDC_AVAILABLE_APPEARANCES, m_comboAvailableAppearances); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDlgPlayerAppearance, CDialog) + //{{AFX_MSG_MAP(CDlgPlayerAppearance) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgPlayerAppearance message handlers diff --git a/Sources/GameGUIMP/DlgPlayerAppearance.h b/Sources/GameGUIMP/DlgPlayerAppearance.h new file mode 100644 index 0000000..ac49b4a --- /dev/null +++ b/Sources/GameGUIMP/DlgPlayerAppearance.h @@ -0,0 +1,41 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgPlayerAppearance.h : header file +// +#ifndef DLGPLAYERAPPEARANCE_H +#define DLGPLAYERAPPEARANCE_H 1 + +///////////////////////////////////////////////////////////////////////////// +// CDlgPlayerAppearance dialog + +class CDlgPlayerAppearance : public CDialog +{ +// Construction +public: + CPlayerCharacter m_pcPlayerCharacter; + CDlgPlayerAppearance(CPlayerCharacter &pcPlayerCharacter, CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDlgPlayerAppearance) + enum { IDD = IDD_PLAYER_APPEARANCE }; + CComboBox m_comboAvailableAppearances; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgPlayerAppearance) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgPlayerAppearance) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; +#endif // DLGPLAYERAPPEARANCE_H \ No newline at end of file diff --git a/Sources/GameGUIMP/DlgPlayerControls.cpp b/Sources/GameGUIMP/DlgPlayerControls.cpp new file mode 100644 index 0000000..c165f89 --- /dev/null +++ b/Sources/GameGUIMP/DlgPlayerControls.cpp @@ -0,0 +1,620 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgPlayerControls.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgPlayerControls dialog + +CDlgPlayerControls::CDlgPlayerControls(CControls &ctrlControls, CWnd* pParent /*=NULL*/) +: CDialog(CDlgPlayerControls::IDD, pParent), m_ctrlControls(_pGame->gm_ctrlControlsExtra) +{ + // make copy of the controls, we will change them + m_ctrlControls = ctrlControls; + + //{{AFX_DATA_INIT(CDlgPlayerControls) + m_bInvertControler = FALSE; + m_iRelativeAbsoluteType = -1; + m_strPressNewButton = _T(""); + //}}AFX_DATA_INIT +} + + +void CDlgPlayerControls::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + + INDEX iSelectedAxis = -1; + BOOL bEnableControls; + + // if list control window is created + if( IsWindow(m_listAxisActions.m_hWnd)) + { + // if dialog is recieving data + if( pDX->m_bSaveAndValidate == FALSE) + { + iSelectedAxis = m_listAxisActions.GetNextItem( -1, LVNI_SELECTED); + if( iSelectedAxis != -1) + { + // enable combo control + m_comboControlerAxis.EnableWindow(); + // get curently mounted controler description + CTString strControlerName = m_listAxisActions.GetItemText( iSelectedAxis, 1); + // find in combo currently selected mounted axis + int iComboEntry = m_comboControlerAxis.FindStringExact( -1, strControlerName); + // and select it + m_comboControlerAxis.SetCurSel( iComboEntry); + // if axis none is selected, disable sensitivity and other additional controls for axis + if( m_ctrlControls.ctrl_aaAxisActions[ iSelectedAxis].aa_iAxisAction == AXIS_NONE) + { + // disable controls for defining controler's attributes + bEnableControls = FALSE; + } + else + { + // enable controls for defining controler's attributes + bEnableControls = TRUE; + // and get sensitivity slider state + m_sliderControlerSensitivity.SetPos( + m_ctrlControls.ctrl_aaAxisActions[ iSelectedAxis].aa_fSensitivity / + (100/SENSITIVITY_SLIDER_POSITIONS) ); + // get state of invert axis check box + m_bInvertControler = m_ctrlControls.ctrl_aaAxisActions[ iSelectedAxis].aa_bInvert; + // get radio value (relative/absolute type of controler) + if( m_ctrlControls.ctrl_aaAxisActions[ iSelectedAxis].aa_bRelativeControler) + { + m_iRelativeAbsoluteType = 0; + } + else + { + m_iRelativeAbsoluteType = 1; + } + } + } + else + { + // disable combo control + m_comboControlerAxis.EnableWindow( FALSE); + // disable controls for defining controler's attributes + bEnableControls = FALSE; + } + m_sliderControlerSensitivity.EnableWindow( bEnableControls); + GetDlgItem( IDC_INVERT_CONTROLER)->EnableWindow( bEnableControls); + GetDlgItem( IDC_RELATIVE_ABSOLUTE_TYPE)->EnableWindow( bEnableControls); + GetDlgItem( IDC_CONTROLER_SENSITIVITY)->EnableWindow( bEnableControls); + GetDlgItem( IDC_ABSOLUTE_RADIO)->EnableWindow(bEnableControls); + GetDlgItem( IDC_CONTROLER_TYPE_T)->EnableWindow(bEnableControls); + GetDlgItem( IDC_CONTROLER_SENSITIVITY_T)->EnableWindow(bEnableControls); + } + } + + //{{AFX_DATA_MAP(CDlgPlayerControls) + DDX_Control(pDX, IDC_AXIS_ACTIONS_LIST, m_listAxisActions); + DDX_Control(pDX, IDC_BUTTON_ACTIONS_LIST, m_listButtonActions); + DDX_Control(pDX, IDC_EDIT_SECOND_CONTROL, m_editSecondControl); + DDX_Control(pDX, IDC_EDIT_FIRST_CONTROL, m_editFirstControl); + DDX_Control(pDX, IDC_CONTROLER_SENSITIVITY, m_sliderControlerSensitivity); + DDX_Control(pDX, IDC_CONTROLER_AXIS, m_comboControlerAxis); + DDX_Check(pDX, IDC_INVERT_CONTROLER, m_bInvertControler); + DDX_Radio(pDX, IDC_RELATIVE_ABSOLUTE_TYPE, m_iRelativeAbsoluteType); + DDX_Text(pDX, IDC_PRESS_MESSAGE, m_strPressNewButton); + //}}AFX_DATA_MAP + + // if dialog is giving data + if( pDX->m_bSaveAndValidate != FALSE) + { + iSelectedAxis = m_listAxisActions.GetNextItem( -1, LVNI_SELECTED); + // if there is valid selection + if( iSelectedAxis != -1) + { + // apply check box + m_ctrlControls.ctrl_aaAxisActions[ iSelectedAxis].aa_bInvert = m_bInvertControler; + // apply relative/absolute radio + if( m_iRelativeAbsoluteType == 0) + { + m_ctrlControls.ctrl_aaAxisActions[ iSelectedAxis].aa_bRelativeControler = TRUE; + } + else + { + m_ctrlControls.ctrl_aaAxisActions[ iSelectedAxis].aa_bRelativeControler = FALSE; + } + // apply sensitivity slider value + m_ctrlControls.ctrl_aaAxisActions[ iSelectedAxis].aa_fSensitivity = + m_sliderControlerSensitivity.GetPos() * (100/SENSITIVITY_SLIDER_POSITIONS); + } + } +} + + +BEGIN_MESSAGE_MAP(CDlgPlayerControls, CDialog) + //{{AFX_MSG_MAP(CDlgPlayerControls) + ON_EN_SETFOCUS(IDC_EDIT_FIRST_CONTROL, OnSetfocusEditFirstControl) + ON_EN_SETFOCUS(IDC_EDIT_SECOND_CONTROL, OnSetfocusEditSecondControl) + ON_BN_CLICKED(ID_FIRST_CONTROL_NONE, OnFirstControlNone) + ON_BN_CLICKED(ID_SECOND_CONTROL_NONE, OnSecondControlNone) + ON_BN_CLICKED(ID_DEFAULT, OnDefault) + ON_CBN_SELCHANGE(IDC_CONTROLER_AXIS, OnSelchangeControlerAxis) + ON_BN_CLICKED(ID_MOVE_CONTROL_UP, OnMoveControlUp) + ON_BN_CLICKED(ID_MOVE_CONTROL_DOWN, OnMoveControlDown) + ON_BN_CLICKED(ID_BUTTON_ACTION_ADD, OnButtonActionAdd) + ON_BN_CLICKED(ID_BUTTON_ACTION_EDIT, OnButtonActionEdit) + ON_BN_CLICKED(ID_BUTTON_ACTION_REMOVE, OnButtonActionRemove) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgPlayerControls message handlers + +void CDlgPlayerControls::FillActionsList(void) +{ + // get selected item + INDEX iDefaultSelected = m_listButtonActions.GetNextItem( -1, LVNI_SELECTED); + + // empty list containing actions + m_listButtonActions.DeleteAllItems(); + + // one item to serve for all actions and mounted buttons + LV_ITEM itItem; + // all items will be of text type + itItem.mask = LVIF_TEXT; + // index for automatic counting of added items + INDEX ctItemsAdded = 0; + // now add all button actions + FOREACHINLIST( CButtonAction, ba_lnNode, m_ctrlControls.ctrl_lhButtonActions, itButtonAction) + { + // macro for adding single button action into list control + itItem.iItem = ctItemsAdded; + itItem.iSubItem = 0; + itItem.pszText = (char *)(const char *) itButtonAction->ba_strName; + m_listButtonActions.InsertItem( &itItem); + itItem.iSubItem = 1; + itItem.pszText = (char *)(const char *)_pInput->GetButtonName( itButtonAction->ba_iFirstKey); + m_listButtonActions.SetItem( &itItem); + itItem.iSubItem = 2; + itItem.pszText = (char *)(const char *)_pInput->GetButtonName( itButtonAction->ba_iSecondKey); + m_listButtonActions.SetItem( &itItem); + ctItemsAdded++; + } + + + // try to select same item that was selected before refresh list + if( iDefaultSelected != -1) + { + // select wanted item + m_listButtonActions.SetItemState( iDefaultSelected, + LVIS_FOCUSED|LVIS_SELECTED|LVIS_DROPHILITED, LVIS_FOCUSED|LVIS_SELECTED|LVIS_DROPHILITED); + m_listButtonActions.EnsureVisible( iDefaultSelected, FALSE); + } +} + +void CDlgPlayerControls::FillAxisList(void) +{ + // get selected item + INDEX iDefaultSelected = m_listAxisActions.GetNextItem( -1, LVNI_SELECTED); + + // empty list containing actions + m_listAxisActions.DeleteAllItems(); + + // one item to serve for all actions and mounted buttons + LV_ITEM itItem; + // all items will be of text type + itItem.mask = LVIF_TEXT; + // now add all axis actions + for(INDEX iAxis = 0; iAxisgm_astrAxisNames[iAxis]; + m_listAxisActions.InsertItem( &itItem); + itItem.iSubItem = 1; + itItem.pszText = (char *)(const char *)_pInput->GetAxisName( + m_ctrlControls.ctrl_aaAxisActions[iAxis].aa_iAxisAction); + m_listAxisActions.SetItem( &itItem); + } + + // try to select same item that was selected before refresh list + if( iDefaultSelected != -1) + { + m_listAxisActions.SetItemState( iDefaultSelected, + LVIS_FOCUSED|LVIS_SELECTED|LVIS_DROPHILITED, LVIS_FOCUSED|LVIS_SELECTED|LVIS_DROPHILITED); + m_listAxisActions.EnsureVisible( iDefaultSelected, FALSE); + } +} + +// percentage of action's list control window width used for action names +#define BUTTON_ACTION_NAME_PERCENTAGE 50 +#define AXIS_ACTION_NAME_PERCENTAGE 50 + +BOOL CDlgPlayerControls::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // initialize controler sensitivity + m_sliderControlerSensitivity.SetRange( 1, SENSITIVITY_SLIDER_POSITIONS); + m_sliderControlerSensitivity.SetTicFreq( 1); + + // get action list control's width in pixels + CRect rectListControl; + m_listButtonActions.GetClientRect( rectListControl); + // insert column for action names + INDEX iMainColumnWidth = rectListControl.Width()*BUTTON_ACTION_NAME_PERCENTAGE/100; + m_listButtonActions.InsertColumn( 0, "Button action", LVCFMT_LEFT, iMainColumnWidth); + // insert first control column + INDEX iFirstSubColumnWidth = (rectListControl.Width()*(100-BUTTON_ACTION_NAME_PERCENTAGE)/2)/100; + m_listButtonActions.InsertColumn( 1, "First", LVCFMT_LEFT, iFirstSubColumnWidth); + // insert second control column + INDEX iSecondSubColumnWidth = + rectListControl.Width()-iMainColumnWidth-iFirstSubColumnWidth - 16; + m_listButtonActions.InsertColumn( 2, "Second", LVCFMT_LEFT, iSecondSubColumnWidth); + + // add all actions into actions list + FillActionsList(); + + // get axis action list control's width in pixels + m_listAxisActions.GetClientRect( rectListControl); + // insert column for axis action names + iMainColumnWidth = rectListControl.Width()*AXIS_ACTION_NAME_PERCENTAGE/100; + m_listAxisActions.InsertColumn( 0, "Axis action", LVCFMT_LEFT, iMainColumnWidth); + // insert mounting controls column + INDEX iAxisMouterNameWidth = rectListControl.Width()*(100-AXIS_ACTION_NAME_PERCENTAGE)/100-1; + m_listAxisActions.InsertColumn( 1, "Current controler", LVCFMT_LEFT, iAxisMouterNameWidth); + + // add all available axis into axis list + FillAxisList(); + + // for all possible axis mounting controlers + for( INDEX iAxis=0; iAxis<_pInput->GetAvailableAxisCount(); iAxis++) + { + m_comboControlerAxis.AddString( _pInput->GetAxisName( iAxis)); + } + + return TRUE; +} + +void CDlgPlayerControls::SetFirstAndSecondButtonNames(void) +{ + BOOL bEnablePressKeyControls; + CButtonAction *pbaCurrent = GetSelectedButtonAction(); + if( pbaCurrent != NULL) + { + // type first currently mounted button's name + m_editFirstControl.SetWindowText( (char *)(const char *) + _pInput->GetButtonName( pbaCurrent->ba_iFirstKey) ); + // type second currently mounted button's name + m_editSecondControl.SetWindowText( (char *)(const char *) + _pInput->GetButtonName( pbaCurrent->ba_iSecondKey) ); + // enable edit key and "none" controls + bEnablePressKeyControls = TRUE; + } + else + { + bEnablePressKeyControls = FALSE; + } + // enable/disable press key controls (edit boxes and "none" buttons) + m_editFirstControl.EnableWindow( bEnablePressKeyControls); + m_editSecondControl.EnableWindow( bEnablePressKeyControls); + GetDlgItem( ID_FIRST_CONTROL_NONE)->EnableWindow( bEnablePressKeyControls); + GetDlgItem( ID_SECOND_CONTROL_NONE)->EnableWindow( bEnablePressKeyControls); +} + +void CDlgPlayerControls::ActivatePressKey( char *strFirstOrSecond) +{ + // get selected action + m_iSelectedAction = m_listButtonActions.GetNextItem( -1, LVNI_SELECTED); + // if there is valid selection + if( m_iSelectedAction == -1) + { + // activate actions list + m_listButtonActions.SetFocus(); + return; + } + + // leave left mouse button ! + while( (GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0) NOTHING; + + char achrMessage[ 256]; + // prepare message + sprintf( achrMessage, "Press new %s button for action:\n\"%s\"", strFirstOrSecond, + m_listButtonActions.GetItemText( m_iSelectedAction, 0)); + // set message string to dialog + m_strPressNewButton = achrMessage; + // activate string in text control + UpdateData( FALSE); + + // enable application + AfxGetMainWnd()->EnableWindow(); + AfxGetMainWnd()->SetActiveWindow(); + + // enable direct input + _pInput->EnableInput(m_hWnd); + // initial reading of all available inputs + _pInput->GetInput(FALSE); + // as long as direct input is enabled + while( _pInput->IsInputEnabled()) + { + // for all possible buttons + for( INDEX iButton=0; iButton<_pInput->GetAvailableButtonsCount(); iButton++) + { + // if pressed + if( _pInput->GetButtonState( iButton) + || (iButton==KID_MOUSE1 && (GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0) + || (iButton==KID_MOUSE2 && (GetAsyncKeyState(VK_RBUTTON) & 0x8000) != 0) + || (iButton==KID_MOUSE3 && (GetAsyncKeyState(VK_MBUTTON) & 0x8000) != 0)) + { + // disable direct input + _pInput->DisableInput(); + // if new button is mounted allready, set owner's action mounting to "key none" + FOREACHINLIST( CButtonAction, ba_lnNode, m_ctrlControls.ctrl_lhButtonActions, itButtonAction) + { + if( itButtonAction->ba_iFirstKey == iButton) itButtonAction->ba_iFirstKey = KID_NONE; + if( itButtonAction->ba_iSecondKey == iButton) itButtonAction->ba_iSecondKey = KID_NONE; + } + + CButtonAction *pbaCurrent = GetSelectedButtonAction(); + if( pbaCurrent != NULL) + { + if( strFirstOrSecond == CTString("first") ) + { + pbaCurrent->ba_iFirstKey = iButton; + } + else + { + pbaCurrent->ba_iSecondKey = iButton; + } + } + // refresh list control + FillActionsList(); + // refresh first button edit control + SetFirstAndSecondButtonNames(); + + // disable application + AfxGetMainWnd()->EnableWindow( FALSE); + // activate dialog + SetActiveWindow(); + EnableWindow(); + // activate actions list + m_listButtonActions.SetFocus(); + // prevent reselecting edit control + MSG message; + // peek and remove all mouse messages from message queue + while( PeekMessage( &message, m_hWnd, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE)) NOTHING; + // peek and remove all keyboard messages from message queue + while( PeekMessage( &message, m_hWnd, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) NOTHING; + } + } + } + ASSERT( !_pInput->IsInputEnabled()); + // try to select same item that was selected before key binding + if( m_iSelectedAction != -1) + { + m_listButtonActions.SetItemState( m_iSelectedAction, + LVIS_FOCUSED|LVIS_SELECTED|LVIS_DROPHILITED, LVIS_FOCUSED|LVIS_SELECTED|LVIS_DROPHILITED); + m_listButtonActions.EnsureVisible( m_iSelectedAction, FALSE); + } + // delete press button message + m_strPressNewButton = ""; + // notice change + UpdateData( FALSE); +} + +void CDlgPlayerControls::OnSetfocusEditFirstControl() +{ + // activates press key behaviour (rather complicated one) for first button + ActivatePressKey( "first"); +} + +void CDlgPlayerControls::OnSetfocusEditSecondControl() +{ + // activates press key behaviour (rather complicated one) for second button + ActivatePressKey( "second"); +} + +CButtonAction *CDlgPlayerControls::GetSelectedButtonAction() +{ + // get selected action + m_iSelectedAction = m_listButtonActions.GetNextItem( -1, LVNI_SELECTED); + // if there is valid selection + if( m_iSelectedAction != -1) + { + INDEX iCurrent = 0; + FOREACHINLIST( CButtonAction, ba_lnNode, m_ctrlControls.ctrl_lhButtonActions, itButtonAction) + { + if( iCurrent == m_iSelectedAction) return itButtonAction; + iCurrent++; + } + } + return NULL; +} + +void CDlgPlayerControls::OnFirstControlNone() +{ + CButtonAction *pbaCurrent = GetSelectedButtonAction(); + if( pbaCurrent != NULL) + { + // set none action key + pbaCurrent->ba_iFirstKey = KID_NONE; + // refresh list control + FillActionsList(); + // refresh first button edit control + SetFirstAndSecondButtonNames(); + // activate actions list + m_listButtonActions.SetFocus(); + } +} + +void CDlgPlayerControls::OnSecondControlNone() +{ + CButtonAction *pbaCurrent = GetSelectedButtonAction(); + if( pbaCurrent != NULL) + { + // set none action key + pbaCurrent->ba_iSecondKey = KID_NONE; + // refresh list control + FillActionsList(); + // refresh first button edit control + SetFirstAndSecondButtonNames(); + // activate actions list + m_listButtonActions.SetFocus(); + } +} + +void CDlgPlayerControls::OnDefault() +{ + // switch controls to default + m_ctrlControls.SwitchToDefaults(); + + + // refresh list control + FillActionsList(); + // refresh first button edit control + SetFirstAndSecondButtonNames(); + // activate actions list + m_listButtonActions.SetFocus(); + + // refresh axis list + FillAxisList(); + // set axis attributes + UpdateData( FALSE); +} + +void CDlgPlayerControls::OnSelchangeControlerAxis() +{ + // get newly selected controler axis + INDEX iNewControler = m_comboControlerAxis.GetCurSel(); + // must be valid + ASSERT( iNewControler != CB_ERR); + + // get selected item + INDEX iActiveAxis = m_listAxisActions.GetNextItem( -1, LVNI_SELECTED); + // change mounting controler for selected axis + m_ctrlControls.ctrl_aaAxisActions[ iActiveAxis].aa_iAxisAction = iNewControler; + // refresh axis list control + FillAxisList(); + + // pickup current values of controler attributes + UpdateData( TRUE); + // refresh axis-conected controls (dialog recives data) + UpdateData( FALSE); +} + +void CDlgPlayerControls::OnMoveControlUp() +{ + // get selected item + INDEX iSelectedButton = m_listButtonActions.GetNextItem( -1, LVNI_SELECTED); + if( iSelectedButton == 0) return; + // find member to move up + INDEX iCurrent = 0; + CButtonAction *pbaButtonToMove = NULL; + + {FOREACHINLIST( CButtonAction, ba_lnNode, m_ctrlControls.ctrl_lhButtonActions, itButtonAction) + { + if( iCurrent == iSelectedButton) + { + // remove it from list + itButtonAction->ba_lnNode.Remove(); + pbaButtonToMove = &itButtonAction.Current(); + break; + } + iCurrent++; + }} + ASSERT( pbaButtonToMove != NULL); + + // insert removed member again but before its predcessor + iCurrent = 0; + {FOREACHINLIST( CButtonAction, ba_lnNode, m_ctrlControls.ctrl_lhButtonActions, itButtonAction) + { + if( iCurrent == (iSelectedButton-1) ) + { + itButtonAction->ba_lnNode.AddBefore( pbaButtonToMove->ba_lnNode); + break; + } + iCurrent++; + }} + // refresh list control + FillActionsList(); + // get no of items + INDEX iButtonsCt = m_listButtonActions.GetItemCount(); + // get no of items + for( INDEX iListItem=0; iListItem= (iButtonsCt-1) ) return; + // find member to move down + INDEX iCurrent = 0; + CButtonAction *pbaButtonToMove = NULL; + {FOREACHINLIST( CButtonAction, ba_lnNode, m_ctrlControls.ctrl_lhButtonActions, itButtonAction) + { + if( iCurrent == iSelectedButton) + { + // remove it from list + itButtonAction->ba_lnNode.Remove(); + pbaButtonToMove = &itButtonAction.Current(); + break; + } + iCurrent++; + }} + ASSERT( pbaButtonToMove != NULL); + + // insert removed member again but before its predcessor + iCurrent = 0; + {FOREACHINLIST( CButtonAction, ba_lnNode, m_ctrlControls.ctrl_lhButtonActions, itButtonAction) + { + if( iCurrent == (iSelectedButton) ) + { + itButtonAction->ba_lnNode.AddAfter( pbaButtonToMove->ba_lnNode); + break; + } + iCurrent++; + }} + // refresh list control + FillActionsList(); + // get no of items + for( INDEX iListItem=0; iListItemm_bSaveAndValidate != FALSE) + { + // get selected player + INDEX iSelectedPlayer = m_listAvailablePlayers.GetCurSel(); + ASSERT( iSelectedPlayer != LB_ERR); + // remember selected player + _pGame->gm_iWEDSinglePlayer = iSelectedPlayer; + + // get selected controls + INDEX iSelectedControls = m_listAvailableControls.GetCurSel(); + ASSERT( iSelectedControls != LB_ERR); + // remember selected controls +// _pGame->gm_apiPlayerInfo[iSelectedPlayer].pi_iControls = iSelectedControls; + } +} + + +BEGIN_MESSAGE_MAP(CDlgPlayerSettings, CDialog) + //{{AFX_MSG_MAP(CDlgPlayerSettings) + ON_BN_CLICKED(IDC_PLAYER_APPEARANCE, OnPlayerAppearance) + ON_BN_CLICKED(IDC_EDIT_CONTROLS, OnEditControls) + ON_BN_CLICKED(IDC_RENAME_CONTROLS, OnRenameControls) + ON_BN_CLICKED(IDC_RENAME_PLAYER, OnRenamePlayer) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgPlayerSettings message handlers + +void CDlgPlayerSettings::OnPlayerAppearance() +{ + return; + /* + CPlayerInfo plPlayerInfo; + // get selected player + INDEX iSelectedPlayer = m_listAvailablePlayers.GetCurSel(); + ASSERT( iSelectedPlayer != LB_ERR); + + CTFileName fnPlayerName; + fnPlayerName.PrintF( "%sPlayers\\Player%d.plr", iSelectedPlayer); + try + { + // load it from the file + plPlayerInfo.Load_t( fnPlayerName); + // call player appearance dialog + CDlgPlayerAppearance dlgPlayerAppearance( plPlayerInfo.pi_pcPlayerCharacter); + // if user wants to change player's appearance + if( dlgPlayerAppearance.DoModal() == IDOK) + { + // set new appearance + plPlayerInfo.pi_pcPlayerCharacter = dlgPlayerAppearance.m_pcPlayerCharacter; + // and save new player's attributes + plPlayerInfo.Save_t( fnPlayerName); + // reload players and controls + _pGame->LoadPlayersAndControls(); + } + } + catch (char *strError) + { + AfxMessageBox( strError); + } + */ +} + +void CDlgPlayerSettings::InitPlayersAndControlsLists(void) +{ + if( !::IsWindow( m_listAvailablePlayers.m_hWnd)) return; + m_listAvailablePlayers.ResetContent(); + m_listAvailableControls.ResetContent(); + + // fill players and controls lists + for( INDEX iPC=0; iPC<8; iPC++) + { + CTString strPlayer = _pGame->gm_apcPlayers[ iPC].pc_strName; + m_listAvailablePlayers.AddString( strPlayer); + //CTString strControls = _pGame->gm_actrlControls[ iPC].ctrl_strName; + m_listAvailableControls.AddString( "dummy"); + } + m_listAvailableControls.SetCurSel( 0); + m_listAvailablePlayers.SetCurSel( 0); +} + +BOOL CDlgPlayerSettings::OnInitDialog() +{ + CDialog::OnInitDialog(); + InitPlayersAndControlsLists(); + return TRUE; +} + +void CDlgPlayerSettings::OnEditControls() +{ + CControls &ctrlControls = _pGame->gm_ctrlControlsExtra; + // try to + try + { + // get selected controls + INDEX iSelectedControls = m_listAvailableControls.GetCurSel(); + ASSERT( iSelectedControls != LB_ERR); + CTFileName fnControlsName; + fnControlsName.PrintF( "Controls\\Controls%d.ctl", iSelectedControls); + // load it from the file + ctrlControls.Load_t( fnControlsName); + + // call controls dialog + CDlgPlayerControls dlgControls( ctrlControls); + // if user wants to change controls + if( dlgControls.DoModal() == IDOK) + { + // set new controls + ctrlControls = dlgControls.m_ctrlControls; + // depending on axis attributes and type (rotation or translation), calculates axis + // influence factors for all axis actions + ctrlControls.CalculateInfluencesForAllAxis(); + // save new controls + ctrlControls.Save_t( fnControlsName); + // reload players and controls + _pGame->LoadPlayersAndControls(); + } + } + catch (char *strError) + { + AfxMessageBox( strError); + return; + } +} + +void CDlgPlayerSettings::OnRenameControls() +{ + CDlgRenameControls dlgRename; + // get selected controls + INDEX iSelectedControls = m_listAvailableControls.GetCurSel(); + ASSERT( iSelectedControls != LB_ERR); + +// CTString strName = _pGame->gm_actrlControls[ iSelectedControls].ctrl_strName; + dlgRename.m_strName = "dummy"; + // if new file properly edited and ok pressed + if( (dlgRename.DoModal() == IDOK) && + (strlen( dlgRename.m_strName) != 0) ) + { +// _pGame->gm_actrlControls[ iSelectedControls].ctrl_strName = dlgRename.m_strName; + // save players and controls + _pGame->SavePlayersAndControls(); + InitPlayersAndControlsLists(); + } +} + +void CDlgPlayerSettings::OnRenamePlayer() +{ + CDlgRenameControls dlgRename; + // get selected controls + INDEX iSelectedPlayer = m_listAvailablePlayers.GetCurSel(); + ASSERT( iSelectedPlayer != LB_ERR); + + CTString strName = _pGame->gm_apcPlayers[ iSelectedPlayer].pc_strName; + dlgRename.m_strName = strName; + // if new file properly edited and ok pressed + if( (dlgRename.DoModal() == IDOK) && + (strlen( dlgRename.m_strName) != 0) ) + { + _pGame->gm_apcPlayers[ iSelectedPlayer].pc_strName = dlgRename.m_strName; + // save players and controls + _pGame->SavePlayersAndControls(); + InitPlayersAndControlsLists(); + } +} diff --git a/Sources/GameGUIMP/DlgPlayerSettings.h b/Sources/GameGUIMP/DlgPlayerSettings.h new file mode 100644 index 0000000..543c55e --- /dev/null +++ b/Sources/GameGUIMP/DlgPlayerSettings.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgPlayerSettings.h : header file +// +#ifndef DLGPLAYERSETTINGS_H +#define DLGPLAYERSETTINGS_H 1 + +///////////////////////////////////////////////////////////////////////////// +// CDlgPlayerSettings dialog + +class CDlgPlayerControls; + +class CDlgPlayerSettings : public CDialog +{ +// Construction +public: + CDlgPlayerSettings(CWnd* pParent = NULL); // standard constructor + void InitPlayersAndControlsLists(void); + +// Dialog Data + //{{AFX_DATA(CDlgPlayerSettings) + enum { IDD = IDD_SETTINGS_PLAYERS }; + CListBox m_listAvailableControls; + CListBox m_listAvailablePlayers; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgPlayerSettings) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +public: + + // Generated message map functions + //{{AFX_MSG(CDlgPlayerSettings) + afx_msg void OnPlayerAppearance(); + virtual BOOL OnInitDialog(); + afx_msg void OnEditControls(); + afx_msg void OnRenameControls(); + afx_msg void OnRenamePlayer(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; +#endif // DLGPLAYERSETTINGS_H diff --git a/Sources/GameGUIMP/DlgRenameControls.cpp b/Sources/GameGUIMP/DlgRenameControls.cpp new file mode 100644 index 0000000..7fd5b79 --- /dev/null +++ b/Sources/GameGUIMP/DlgRenameControls.cpp @@ -0,0 +1,44 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgRenameControls.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgRenameControls dialog + + +CDlgRenameControls::CDlgRenameControls(CWnd* pParent /*=NULL*/) + : CDialog(CDlgRenameControls::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgRenameControls) + m_strName = _T(""); + //}}AFX_DATA_INIT +} + + +void CDlgRenameControls::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDlgRenameControls) + DDX_Text(pDX, IDC_EDIT_CONTROLS_NAME, m_strName); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDlgRenameControls, CDialog) + //{{AFX_MSG_MAP(CDlgRenameControls) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgRenameControls message handlers diff --git a/Sources/GameGUIMP/DlgRenameControls.h b/Sources/GameGUIMP/DlgRenameControls.h new file mode 100644 index 0000000..be8be93 --- /dev/null +++ b/Sources/GameGUIMP/DlgRenameControls.h @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#if !defined(AFX_DLGRENAMECONTROLS_H__3F147D64_39B2_11D2_8383_004095812ACC__INCLUDED_) +#define AFX_DLGRENAMECONTROLS_H__3F147D64_39B2_11D2_8383_004095812ACC__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// DlgRenameControls.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgRenameControls dialog + +class CDlgRenameControls : public CDialog +{ +// Construction +public: + CDlgRenameControls(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDlgRenameControls) + enum { IDD = IDD_RENAME_CONTROLS }; + CString m_strName; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgRenameControls) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgRenameControls) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGRENAMECONTROLS_H__3F147D64_39B2_11D2_8383_004095812ACC__INCLUDED_) diff --git a/Sources/GameGUIMP/DlgSelectPlayer.cpp b/Sources/GameGUIMP/DlgSelectPlayer.cpp new file mode 100644 index 0000000..e53017e --- /dev/null +++ b/Sources/GameGUIMP/DlgSelectPlayer.cpp @@ -0,0 +1,96 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgSelectPlayer.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgSelectPlayer dialog + + +CDlgSelectPlayer::CDlgSelectPlayer(CWnd* pParent /*=NULL*/) + : CDialog(CDlgSelectPlayer::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgSelectPlayer) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CDlgSelectPlayer::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDlgSelectPlayer) + DDX_Control(pDX, IDC_COMBO_AVAILABLE_CONTROLS, m_comboAvailableControls); + DDX_Control(pDX, IDC_COMBO_AVAILABLE_PLAYERS, m_comboAvailablePlayers); + //}}AFX_DATA_MAP + + // if dialog is giving data + if( pDX->m_bSaveAndValidate != FALSE) + { + INDEX iSelectedPlayer = m_comboAvailablePlayers.GetCurSel(); + INDEX iSelectedControls = m_comboAvailableControls.GetCurSel(); + // if there is no player selected + if( (iSelectedPlayer == CB_ERR) || ( iSelectedControls == CB_ERR) ) + { + // end dialog as if user pressed escape key + EndDialog( IDCANCEL); + } + else + { + _pGame->gm_iWEDSinglePlayer = iSelectedPlayer; + _pGame->SavePlayersAndControls(); + } + } +} + + +BEGIN_MESSAGE_MAP(CDlgSelectPlayer, CDialog) + //{{AFX_MSG_MAP(CDlgSelectPlayer) + ON_CBN_SELCHANGE(IDC_COMBO_AVAILABLE_PLAYERS, OnSelchangeComboAvailablePlayers) + ON_CBN_SELCHANGE(IDC_COMBO_AVAILABLE_CONTROLS, OnSelchangeComboAvailableControls) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgSelectPlayer message handlers + +BOOL CDlgSelectPlayer::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // fill players and controls combo boxes + for( INDEX iPC=0; iPC<8; iPC++) + { + CTString strPlayer = _pGame->gm_apcPlayers[ iPC].pc_strName; + m_comboAvailablePlayers.AddString( strPlayer); +// CTString strControls = _pGame->gm_actrlControls[ iPC].ctrl_strName; + m_comboAvailableControls.AddString( "dummy"); + } + m_comboAvailablePlayers.SetCurSel( _pGame->gm_iWEDSinglePlayer); + m_comboAvailableControls.SetCurSel( _pGame->gm_iWEDSinglePlayer); + + return TRUE; +} + +void CDlgSelectPlayer::OnSelchangeComboAvailablePlayers() +{ + INDEX iSelectedPlayer = m_comboAvailablePlayers.GetCurSel(); + if( iSelectedPlayer == CB_ERR) return; + m_comboAvailableControls.SetCurSel( iSelectedPlayer); +} + +void CDlgSelectPlayer::OnSelchangeComboAvailableControls() +{ + INDEX iSelectedPlayer = m_comboAvailablePlayers.GetCurSel(); + if( iSelectedPlayer == CB_ERR) return; + INDEX iSelectedControls = m_comboAvailableControls.GetCurSel(); +} diff --git a/Sources/GameGUIMP/DlgSelectPlayer.h b/Sources/GameGUIMP/DlgSelectPlayer.h new file mode 100644 index 0000000..38645d4 --- /dev/null +++ b/Sources/GameGUIMP/DlgSelectPlayer.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#if !defined(AFX_DLGSELECTPLAYER_H__FCDE2F73_3A65_11D2_8384_004095812ACC__INCLUDED_) +#define AFX_DLGSELECTPLAYER_H__FCDE2F73_3A65_11D2_8384_004095812ACC__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// DlgSelectPlayer.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDlgSelectPlayer dialog + +class CDlgSelectPlayer : public CDialog +{ +// Construction +public: + CDlgSelectPlayer(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDlgSelectPlayer) + enum { IDD = IDD_SELECT_PLAYER }; + CComboBox m_comboAvailablePlayers; + CComboBox m_comboAvailableControls; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgSelectPlayer) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgSelectPlayer) + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeComboAvailablePlayers(); + afx_msg void OnSelchangeComboAvailableControls(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DLGSELECTPLAYER_H__FCDE2F73_3A65_11D2_8384_004095812ACC__INCLUDED_) diff --git a/Sources/GameGUIMP/DlgVideoQuality.cpp b/Sources/GameGUIMP/DlgVideoQuality.cpp new file mode 100644 index 0000000..1806710 --- /dev/null +++ b/Sources/GameGUIMP/DlgVideoQuality.cpp @@ -0,0 +1,109 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgVideoQuality.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CDlgVideoQuality dialog + + +CDlgVideoQuality::CDlgVideoQuality(CWnd* pParent /*=NULL*/) + : CDialog(CDlgVideoQuality::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDlgVideoQuality) + m_radioObjectShadowQuality = -1; + m_radioTextureQuality = -1; + m_radioWorldShadowQuality = -1; + //}}AFX_DATA_INIT +} + + +void CDlgVideoQuality::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + + // if dialog is recieving data + if( pDX->m_bSaveAndValidate == FALSE) + { + // set current state of texture quality radio button +/* switch( Flesh.gm_tqTextureQuality) + { + case CGame::TQ_LOW: { m_radioTextureQuality = 0; break; } + case CGame::TQ_MEDIUM: { m_radioTextureQuality = 1; break; } + case CGame::TQ_HIGH: { m_radioTextureQuality = 2; break; } + default: { ASSERTALWAYS( "Illegal texture quality value found!"); } + } + // set current state of object shadow quality radio button + switch( Flesh.gm_osqObjectShadowQuality) + { + case CGame::OSQ_OFF: { m_radioObjectShadowQuality = 0; break; } + case CGame::OSQ_LOW: { m_radioObjectShadowQuality = 1; break; } + case CGame::OSQ_HIGH: { m_radioObjectShadowQuality = 2; break; } + default: { ASSERTALWAYS( "Illegal object shadow quality value found!"); } + } + // set current state of world shadow quality radio button + switch( Flesh.gm_wsqWorldShadowQuality) + { + case CGame::WSQ_LOW: { m_radioWorldShadowQuality = 0; break; } + case CGame::WSQ_MEDIUM: { m_radioWorldShadowQuality = 1; break; } + case CGame::WSQ_HIGH: { m_radioWorldShadowQuality = 2; break; } + default: { ASSERTALWAYS( "Illegal world shadow quality value found!"); } + } + */ + } + + //{{AFX_DATA_MAP(CDlgVideoQuality) + DDX_Radio(pDX, IDC_OBJECT_SHADOW_QUALITY, m_radioObjectShadowQuality); + DDX_Radio(pDX, IDC_TEXTURE_QUALITY, m_radioTextureQuality); + DDX_Radio(pDX, IDC_WORLD_SHADOW_QUALITY, m_radioWorldShadowQuality); + //}}AFX_DATA_MAP + + // if dialog is giving data + if( pDX->m_bSaveAndValidate != FALSE) + { + // pick up states of texture quality radio button +/* switch( m_radioTextureQuality) + { + case 0: { Flesh.gm_tqTextureQuality = CGame::TQ_LOW; break; } + case 1: { Flesh.gm_tqTextureQuality = CGame::TQ_MEDIUM; break; } + case 2: { Flesh.gm_tqTextureQuality = CGame::TQ_HIGH; break; } + default: { ASSERTALWAYS( "Illegal texture quality radio value found!"); } + } + // pick up states of object shadow quality radio button + switch( m_radioObjectShadowQuality) + { + case 0: { Flesh.gm_osqObjectShadowQuality = CGame::OSQ_OFF; break; } + case 1: { Flesh.gm_osqObjectShadowQuality = CGame::OSQ_LOW; break; } + case 2: { Flesh.gm_osqObjectShadowQuality = CGame::OSQ_HIGH; break; } + default: { ASSERTALWAYS( "Illegal object shadow quality radio value found!"); } + } + // pick up states of world shadow quality radio button + switch( m_radioWorldShadowQuality) + { + case 0: { Flesh.gm_wsqWorldShadowQuality = CGame::WSQ_LOW; break; } + case 1: { Flesh.gm_wsqWorldShadowQuality = CGame::WSQ_MEDIUM; break; } + case 2: { Flesh.gm_wsqWorldShadowQuality = CGame::WSQ_HIGH; break; } + default: { ASSERTALWAYS( "Illegal world shadow quality radio value found!"); } + } + */ + } +} + + +BEGIN_MESSAGE_MAP(CDlgVideoQuality, CDialog) + //{{AFX_MSG_MAP(CDlgVideoQuality) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDlgVideoQuality message handlers diff --git a/Sources/GameGUIMP/DlgVideoQuality.h b/Sources/GameGUIMP/DlgVideoQuality.h new file mode 100644 index 0000000..c5f61ea --- /dev/null +++ b/Sources/GameGUIMP/DlgVideoQuality.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// DlgVideoQuality.h : header file +// +#ifndef DLGVIDEOQUALITY_H +#define DLGVIDEOQUALITY_H 1 + +///////////////////////////////////////////////////////////////////////////// +// CDlgVideoQuality dialog + +class CDlgVideoQuality : public CDialog +{ +// Construction +public: + CDlgVideoQuality(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDlgVideoQuality) + enum { IDD = IDD_VIDEO_QUALITY }; + int m_radioObjectShadowQuality; + int m_radioTextureQuality; + int m_radioWorldShadowQuality; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDlgVideoQuality) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDlgVideoQuality) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; +#endif // DLGVIDEOQUALITY_H \ No newline at end of file diff --git a/Sources/GameGUIMP/EditConsole.cpp b/Sources/GameGUIMP/EditConsole.cpp new file mode 100644 index 0000000..d022667 --- /dev/null +++ b/Sources/GameGUIMP/EditConsole.cpp @@ -0,0 +1,101 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// EditConsole.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CEditConsole + +CEditConsole::CEditConsole() +{ +} + +CEditConsole::~CEditConsole() +{ +} + + +BEGIN_MESSAGE_MAP(CEditConsole, CEdit) + //{{AFX_MSG_MAP(CEditConsole) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CEditConsole message handlers + +void CEditConsole::SetTextFromConsole(void) +{ + INDEX ctLines = _pConsole->con_ctLines; + INDEX ctChars = _pConsole->con_ctLines; + // allocate new string with double line ends + char *strNew = (char*)AllocMemory(ctLines*(ctChars+2)+1); + const char *strString = _pConsole->GetBuffer(); + char *pch = strNew; + // convert '\n' to '\r''\n' + while(*strString!=0) { + if (*strString=='\n') { + *pch++='\r'; + *pch++='\n'; + strString++; + } + *pch++ = *strString++; + } + *pch = 0; + + CDlgConsole *pdlgParent = (CDlgConsole *) GetParent(); + CEdit *pwndOutput = (CEdit *) pdlgParent->GetDlgItem( IDC_CONSOLE_OUTPUT); + pwndOutput->SetWindowText( CString(strNew)); + pwndOutput->LineScroll(ctLines-1); + + FreeMemory(strNew); +} + +BOOL CEditConsole::PreTranslateMessage(MSG* pMsg) +{ + BOOL bCtrl = (GetKeyState( VK_CONTROL) & 128) != 0; + if(pMsg->message==WM_KEYDOWN && pMsg->wParam==VK_RETURN) + { + // obtain current line index + INDEX iCurrentLine = LineFromChar(-1); + INDEX ctLinesEdited = GetLineCount(); + // obtain char offset of current line in whole edit string + INDEX iCharOffset = LineFromChar(iCurrentLine); + if( !bCtrl && (iCharOffset != -1) ) + { + // extract string to execute + wchar_t achrToExecute[ 1024]; + INDEX ctLetters = GetLine( iCurrentLine, achrToExecute, 1023); + // set EOF delimiter + achrToExecute[ ctLetters] = 0; + CTString strToExecute = CStringA(achrToExecute); + CPrintF( ">%s\n", strToExecute); + if( ((const char*)strToExecute)[strlen(strToExecute)-1] != ';') + { + strToExecute += ";"; + } + _pShell->Execute(strToExecute); + // set new text for output window + SetTextFromConsole(); + // remember input text into console input buffer + CString sHistory; + GetWindowText(sHistory); + _pGame->gam_strConsoleInputBuffer = CStringA(sHistory); + } + // if Ctrl is not pressed and current line is not last line, "swallow return" + if( !bCtrl && (ctLinesEdited-1 != iCurrentLine) ) + { + return TRUE; + } + } + + return CEdit::PreTranslateMessage(pMsg); +} diff --git a/Sources/GameGUIMP/EditConsole.h b/Sources/GameGUIMP/EditConsole.h new file mode 100644 index 0000000..cf0b111 --- /dev/null +++ b/Sources/GameGUIMP/EditConsole.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#if !defined(AFX_EDITCONSOLE_H__833B8174_E923_11D1_82A7_000000000000__INCLUDED_) +#define AFX_EDITCONSOLE_H__833B8174_E923_11D1_82A7_000000000000__INCLUDED_ + +#if _MSC_VER >= 1000 +#pragma once +#endif // _MSC_VER >= 1000 +// EditConsole.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CEditConsole window + +class CEditConsole : public CEdit +{ +// Construction +public: + CEditConsole(); + +// Attributes +public: + +// Operations +public: + void SetTextFromConsole(void); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CEditConsole) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CEditConsole(); + + // Generated message map functions +protected: + //{{AFX_MSG(CEditConsole) + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Developer Studio will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EDITCONSOLE_H__833B8174_E923_11D1_82A7_000000000000__INCLUDED_) diff --git a/Sources/GameGUIMP/GameGUI.cpp b/Sources/GameGUIMP/GameGUI.cpp new file mode 100644 index 0000000..9976eae --- /dev/null +++ b/Sources/GameGUIMP/GameGUI.cpp @@ -0,0 +1,174 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// GameGUI.cpp : Defines the entry point for the DLL application. +// + +#include "stdafx.h" + +#ifdef _DEBUG + #define GAMEGUI_DLL_NAME "GameGUIMPD.dll" +#else + #define GAMEGUI_DLL_NAME "GameGUIMP.dll" +#endif + +extern CGame *_pGame = NULL; +// global game object +CGameGUI _GameGUI; + +static struct GameGUI_interface _Interface; + +// initialize game and load settings +void Initialize(const CTFileName &fnGameSettings) +{ + try { + #ifndef NDEBUG + #define GAMEDLL "Bin\\Debug\\GameMPD.dll" + #else + #define GAMEDLL "Bin\\GameMP.dll" + #endif + CTFileName fnmExpanded; + ExpandFilePath(EFP_READ, CTString(GAMEDLL), fnmExpanded); + HMODULE hGame = LoadLibraryA(fnmExpanded); + if (hGame==NULL) { + ThrowF_t("%s", GetWindowsError(GetLastError())); + } + CGame* (*GAME_Create)(void) = (CGame* (*)(void))GetProcAddress(hGame, "GAME_Create"); + if (GAME_Create==NULL) { + ThrowF_t("%s", GetWindowsError(GetLastError())); + } + _pGame = GAME_Create(); + + } catch (char *strError) { + FatalError("%s", strError); + } + // init game - this will load persistent symbols + _pGame->Initialize(fnGameSettings); + +} +// save settings and cleanup +void End(void) +{ + _pGame->End(); +} + +// run a quicktest game from within editor +void QuickTest(const CTFileName &fnMapName, CDrawPort *pdpDrawport, CViewPort *pvpViewport) +{ + _pGame->QuickTest(fnMapName, pdpDrawport, pvpViewport); +} + +// show console window +void OnInvokeConsole(void) +{ + _GameGUI.OnInvokeConsole(); +} + +// adjust players and controls +void OnPlayerSettings(void) +{ + _GameGUI.OnPlayerSettings(); +} + +// adjust audio settings +void OnAudioQuality(void) +{ + _GameGUI.OnAudioQuality(); +} + +// adjust video settings +void OnVideoQuality(void) +{ + _GameGUI.OnVideoQuality(); +} + +// select current active player and controls +void OnSelectPlayerAndControls(void) +{ + _GameGUI.OnSelectPlayerAndControls(); +} + +extern "C" _declspec(dllexport) struct GameGUI_interface *GAMEGUI_Create(void) +{ + _Interface.Initialize = ::Initialize ; + _Interface.End = ::End ; + _Interface.QuickTest = ::QuickTest ; + _Interface.OnInvokeConsole = ::OnInvokeConsole ; + _Interface.OnPlayerSettings = ::OnPlayerSettings ; + _Interface.OnAudioQuality = ::OnAudioQuality ; + _Interface.OnVideoQuality = ::OnVideoQuality ; + _Interface.OnSelectPlayerAndControls = ::OnSelectPlayerAndControls ; + + return &_Interface; +} + +static int iDialogResult; + +#define CALL_DIALOG( class_name, dlg_name) \ + try { \ + _pGame->Load_t(); \ + } \ + catch( char *pError) { \ + (void) pError; \ + } \ + HANDLE hOldResource = AfxGetResourceHandle(); \ + class_name dlg_name; \ + AfxSetResourceHandle( GetModuleHandleA(GAMEGUI_DLL_NAME) ); \ + iDialogResult = dlg_name.DoModal(); \ + AfxSetResourceHandle( (HINSTANCE) hOldResource); \ + if( iDialogResult == IDOK) \ + try { \ + _pGame->Save_t(); \ + } \ + catch( char *pError) { \ + AfxMessageBox( CString(pError)); \ + iDialogResult = IDCANCEL; \ + } + +/* + We cannot use dllmain if using MFC. + See MSDN article "Regular DLLs Dynamically Linked to MFC" if initialization is needed. + +BOOL APIENTRY DllMain( HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} +*/ + +///////////////////////////////////////////////////////////////////////////// +// global routines called trough game's application menu + +void CGameGUI::OnInvokeConsole(void) +{ + CALL_DIALOG( CDlgConsole, dlgConsole); +} + +void CGameGUI::OnPlayerSettings(void) +{ + //CALL_DIALOG( CDlgPlayerSettings, dlgPlayerSettings); +} + +void CGameGUI::OnAudioQuality(void) +{ + CALL_DIALOG( CDlgAudioQuality, dlgAudioQuality); +} + +void CGameGUI::OnVideoQuality(void) +{ + CALL_DIALOG( CDlgVideoQuality, dlgVideoQuality); +} + +void CGameGUI::OnSelectPlayerAndControls(void) +{ + //CALL_DIALOG( CDlgSelectPlayer, dlgSelectPlayerAndControls); +} diff --git a/Sources/GameGUIMP/GameGUI.h b/Sources/GameGUIMP/GameGUI.h new file mode 100644 index 0000000..fcab869 --- /dev/null +++ b/Sources/GameGUIMP/GameGUI.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include + +// This class is exported from the GameGUI.dll +class CGameGUI { +public: + // functions called from World Editor + __declspec(dllexport) static void OnInvokeConsole(void); + __declspec(dllexport) static void OnPlayerSettings(void); + __declspec(dllexport) static void OnAudioQuality(void); + __declspec(dllexport) static void OnVideoQuality(void); + __declspec(dllexport) static void OnSelectPlayerAndControls(void); +}; + +// global game gui object +extern CGameGUI _GameGUI; diff --git a/Sources/GameGUIMP/GameGUI.rc b/Sources/GameGUIMP/GameGUI.rc new file mode 100644 index 0000000..1a54c62 --- /dev/null +++ b/Sources/GameGUIMP/GameGUI.rc @@ -0,0 +1,547 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "#define _AFX_NO_SPLITTER_RESOURCES\r\n" + "#define _AFX_NO_OLE_RESOURCES\r\n" + "#define _AFX_NO_TRACKER_RESOURCES\r\n" + "#define _AFX_NO_PROPERTY_RESOURCES\r\n" + "\r\n" + "#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n" + "#ifdef _WIN32\r\n" + "LANGUAGE 9, 1\r\n" + "#pragma code_page(1252)\r\n" + "#endif\r\n" + "#include ""res\\Game.rc2"" // non-Microsoft Visual C++ edited resources\r\n" + "#include ""afxres.rc"" // Standard components\r\n" + "#endif\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,0,0,1 + PRODUCTVERSION 1,0,0,1 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904B0" + BEGIN + VALUE "CompanyName", "\0" + VALUE "FileDescription", "GAME DLL\0" + VALUE "FileVersion", "1, 0, 0, 1\0" + VALUE "InternalName", "GAME\0" + VALUE "LegalCopyright", "Copyright © 1997\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "GAME.DLL\0" + VALUE "ProductName", "GAME Dynamic Link Library\0" + VALUE "ProductVersion", "1, 0, 0, 1\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_SINGLE_PLAYER_NEW DIALOG DISCARDABLE 0, 0, 277, 134 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Single player game settings" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Player to play with:",IDC_STATIC,7,12,68,8 + COMBOBOX ID_AVAILABLE_PLAYERS,75,8,195,83,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Dificulty level:",IDC_STATIC,7,42,63,8 + CONTROL "&Easy",IDC_DIFICULTY_LEVEL,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,75,42,50,8 + CONTROL "&Normal",IDC_SINGLE_NORMAL,"Button",BS_AUTORADIOBUTTON, + 75,52,50,8 + CONTROL "&Hard",IDC_SINGLE_HARD,"Button",BS_AUTORADIOBUTTON,75, + 62,50,8 + CONTROL "E&xtreme",IDC_SINGLE_EXTREME,"Button", + BS_AUTORADIOBUTTON,75,72,50,8 + DEFPUSHBUTTON "OK",IDOK,157,113,50,14 + PUSHBUTTON "Cancel",IDCANCEL,220,113,50,14 + PUSHBUTTON "&Browse...",IDC_CHOOSE_LEVEL,220,85,50,13 + LTEXT "&World to play:",IDC_STATIC,7,90,68,8 + LTEXT "C:\\FLESH\\WORLDS\\EGYPT01.WLD",IDC_LEVEL_NAME,75,90, + 142,8 + LTEXT "Controls to play with:",IDC_STATIC,7,28,68,8 + COMBOBOX ID_AVAILABLE_CONTROLS,75,24,195,83,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP +END + +IDD_VIDEO_QUALITY DIALOG DISCARDABLE 0, 0, 296, 87 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Video quality" +FONT 8, "MS Sans Serif" +BEGIN + LTEXT "Texture quality:",IDC_STATIC,101,9,94,8 + CONTROL "Low",IDC_TEXTURE_QUALITY,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,101,22,94,8 + CONTROL "Normal",IDC_TEXTURE_QUALITY_NORMAL,"Button", + BS_AUTORADIOBUTTON,101,32,94,8 + CONTROL "High",IDC_TEXTURE_QUALITY_HIGH,"Button", + BS_AUTORADIOBUTTON,101,42,94,8 + LTEXT "Object shadow quality:",IDC_STATIC,195,9,94,8 + CONTROL "Off",IDC_OBJECT_SHADOW_QUALITY,"Button", + BS_AUTORADIOBUTTON | WS_GROUP,195,22,94,8 + CONTROL "Low",IDC_OBJECT_SHADOW_QUALITY_LOW,"Button", + BS_AUTORADIOBUTTON,195,32,94,8 + CONTROL "High",IDC_OBJECT_SHADOW_QUALITY_HIGH,"Button", + BS_AUTORADIOBUTTON,195,42,94,8 + LTEXT "World shadow quality:",IDC_STATIC,7,9,94,8 + CONTROL "Low",IDC_WORLD_SHADOW_QUALITY,"Button", + BS_AUTORADIOBUTTON | WS_GROUP,7,22,94,8 + CONTROL "Normal",IDC_WORLD_SHADOW_QUALITY_NORMAL,"Button", + BS_AUTORADIOBUTTON,7,32,94,8 + CONTROL "High",IDC_WORLD_SHADOW_QUALITY_HIGH,"Button", + BS_AUTORADIOBUTTON,7,42,94,8 + DEFPUSHBUTTON "OK",IDOK,181,66,50,14 + PUSHBUTTON "Cancel",IDCANCEL,239,66,50,14 +END + +IDD_AUDIO_QUALITY DIALOG DISCARDABLE 0, 0, 257, 65 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Audio quality" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,139,44,50,14 + PUSHBUTTON "Cancel",IDCANCEL,200,44,50,14 + LTEXT "Audio quality:",-1,7,12,93,8 + CONTROL "&Low",IDC_AUDIO_QUALITY_LOW,"Button",BS_AUTORADIOBUTTON | + WS_GROUP,100,12,50,8 + CONTROL "&Normal",IDC_AUDIO_QUALITY_NORMAL,"Button", + BS_AUTORADIOBUTTON,150,12,50,8 + CONTROL "&High",IDC_AUDIO_QUALITY_HIGH,"Button", + BS_AUTORADIOBUTTON,200,12,50,8 + CONTROL "Use Direct Sound &3D",IDC_USE_DSOUND3D,"Button", + BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,7,28,102,8 +END + +IDD_SETTINGS_PLAYERS DIALOG DISCARDABLE 0, 0, 315, 212 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Players and controls" +FONT 8, "MS Sans Serif" +BEGIN + PUSHBUTTON "&Appearance",IDC_PLAYER_APPEARANCE,11,18,57,14 + PUSHBUTTON "&Rename",IDC_RENAME_PLAYER,11,37,57,14 + CTEXT "Players",IDC_STATIC,74,8,234,8 + LISTBOX IDC_AVAILABLE_PLAYERS,74,18,234,74,LBS_NOINTEGRALHEIGHT | + WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "&Edit",IDC_EDIT_CONTROLS,11,106,57,14 + PUSHBUTTON "Re&name",IDC_RENAME_CONTROLS,11,125,57,14 + CTEXT "Controls",IDC_STATIC,74,96,234,8 + LISTBOX IDC_AVAILABLE_CONTROLS,74,106,234,74, + LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP + DEFPUSHBUTTON "OK",IDOK,258,191,50,14 +END + +IDD_PLAYER_CONTROLS DIALOG DISCARDABLE 0, 0, 386, 260 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Player controls" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "List3",IDC_BUTTON_ACTIONS_LIST,"SysListView32", + LVS_REPORT | LVS_SINGLESEL | LVS_NOSORTHEADER | + WS_BORDER | WS_TABSTOP,8,13,231,80 + DEFPUSHBUTTON "OK",IDOK,269,239,50,14 + CTEXT "",IDC_PRESS_MESSAGE,244,16,132,19 + CTEXT "First control:",IDC_STATIC,254,47,68,8 + EDITTEXT IDC_EDIT_FIRST_CONTROL,249,55,79,13,ES_AUTOHSCROLL | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "None",ID_FIRST_CONTROL_NONE,332,55,44,12,WS_DISABLED | + NOT WS_TABSTOP + CTEXT "Second control:",IDC_STATIC,254,72,68,8 + EDITTEXT IDC_EDIT_SECOND_CONTROL,249,80,79,13,ES_AUTOHSCROLL | + WS_DISABLED | NOT WS_TABSTOP + PUSHBUTTON "None",ID_SECOND_CONTROL_NONE,332,80,44,12,WS_DISABLED | + NOT WS_TABSTOP + PUSHBUTTON "&Down",ID_MOVE_CONTROL_DOWN,8,95,35,12,BS_CENTER + PUSHBUTTON "&Up",ID_MOVE_CONTROL_UP,48,95,35,12 + PUSHBUTTON "&Edit",ID_BUTTON_ACTION_EDIT,105,95,41,12 + PUSHBUTTON "&Add",ID_BUTTON_ACTION_ADD,151,95,41,12 + PUSHBUTTON "&Remove",ID_BUTTON_ACTION_REMOVE,198,95,41,12 + CONTROL "List1",IDC_AXIS_ACTIONS_LIST,"SysListView32",LVS_REPORT | + LVS_SINGLESEL | LVS_NOSORTHEADER | WS_BORDER | + WS_TABSTOP,8,120,231,91 + CTEXT "Available axis-type controlers:",IDC_STATIC,2,212,237,8 + COMBOBOX IDC_CONTROLER_AXIS,8,220,231,90,CBS_DROPDOWNLIST | + WS_DISABLED | WS_VSCROLL | WS_TABSTOP + CONTROL "&Invert controler input:",IDC_INVERT_CONTROLER,"Button", + BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_DISABLED | WS_TABSTOP, + 250,126,83,10 + LTEXT "Controler type:",IDC_CONTROLER_TYPE_T,250,144,58,8, + WS_DISABLED + CONTROL "&Relative controler",IDC_RELATIVE_ABSOLUTE_TYPE,"Button", + BS_AUTORADIOBUTTON | WS_DISABLED | WS_GROUP,308,144,68,8 + CONTROL "&Absolute controler",IDC_ABSOLUTE_RADIO,"Button", + BS_AUTORADIOBUTTON | WS_DISABLED,308,154,68,8 + CTEXT "Controler sensitivity",IDC_CONTROLER_SENSITIVITY_T,250, + 176,126,8,WS_DISABLED + CONTROL "Slider1",IDC_CONTROLER_SENSITIVITY,"msctls_trackbar32", + TBS_AUTOTICKS | WS_DISABLED | WS_TABSTOP,250,184,126,26 + PUSHBUTTON "Default",ID_DEFAULT,212,239,50,14 + PUSHBUTTON "Cancel",IDCANCEL,326,239,50,14 + GROUPBOX "Button controls",IDC_STATIC,2,3,382,106,BS_CENTER + GROUPBOX "Axis controls",IDC_STATIC,2,110,382,126,BS_CENTER +END + +IDD_PLAYER_APPEARANCE DIALOG DISCARDABLE 0, 0, 234, 164 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Player appearance" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,117,143,50,14 + PUSHBUTTON "Cancel",IDCANCEL,177,143,50,14 + COMBOBOX IDC_AVAILABLE_APPEARANCES,91,7,136,82,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP + LTEXT "Available appearances:",IDC_STATIC,7,11,84,8 +END + +IDD_CONSOLE DIALOG DISCARDABLE 0, 0, 443, 286 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Console" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_CONSOLE_INPUT,7,193,429,86,ES_MULTILINE | + ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_WANTRETURN | + WS_VSCROLL | WS_HSCROLL + EDITTEXT IDC_CONSOLE_OUTPUT,7,7,429,169,ES_MULTILINE | + ES_AUTOVSCROLL | ES_AUTOHSCROLL | ES_READONLY | + WS_VSCROLL | WS_HSCROLL + LTEXT "Available symols:",IDC_STATIC,7,181,69,8 + COMBOBOX IDC_CONSOLE_SYMBOLS,76,179,360,108,CBS_DROPDOWNLIST | + CBS_SORT | WS_VSCROLL | WS_TABSTOP +END + +IDD_EDIT_BUTTON_ACTION DIALOG DISCARDABLE 0, 0, 398, 153 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Button action" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,273,132,50,14 + PUSHBUTTON "Cancel",IDCANCEL,341,132,50,14 + LTEXT "Button action name:",IDC_STATIC,7,14,111,8 + EDITTEXT IDC_BUTTON_ACTION_NAME,118,10,87,12,ES_AUTOHSCROLL + LTEXT "Command line for button down:",IDC_STATIC,7,33,111,8 + EDITTEXT IDC_BUTTON_DOWN_COMMAND,118,27,273,46,ES_MULTILINE | + ES_AUTOHSCROLL + LTEXT "Command line for button up:",IDC_STATIC,7,83,111,8 + EDITTEXT IDC_BUTTON_UP_COMMAND,118,77,273,46,ES_MULTILINE | + ES_AUTOHSCROLL +END + +IDD_RENAME_CONTROLS DIALOG DISCARDABLE 0, 0, 183, 58 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Rename" +FONT 8, "MS Sans Serif" +BEGIN + EDITTEXT IDC_EDIT_CONTROLS_NAME,51,12,124,12,ES_AUTOHSCROLL + DEFPUSHBUTTON "OK",IDOK,66,37,50,14 + PUSHBUTTON "Cancel",IDCANCEL,126,37,50,14 + LTEXT "New name:",IDC_STATIC,7,16,42,8 +END + +IDD_SELECT_PLAYER DIALOG DISCARDABLE 0, 0, 272, 81 +STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Select player and controls for testing game" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,157,60,50,14 + PUSHBUTTON "Cancel",IDCANCEL,215,60,50,14 + LTEXT "Available players:",IDC_STATIC,7,17,72,8 + COMBOBOX IDC_COMBO_AVAILABLE_PLAYERS,79,13,186,100, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "Player's controls:",IDC_STATIC,7,36,72,8 + COMBOBOX IDC_COMBO_AVAILABLE_CONTROLS,79,32,186,100, + CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_SINGLE_PLAYER_NEW, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 270 + VERTGUIDE, 75 + TOPMARGIN, 7 + BOTTOMMARGIN, 127 + HORZGUIDE, 20 + HORZGUIDE, 36 + HORZGUIDE, 50 + HORZGUIDE, 60 + HORZGUIDE, 70 + HORZGUIDE, 80 + HORZGUIDE, 98 + END + + IDD_VIDEO_QUALITY, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 289 + VERTGUIDE, 101 + VERTGUIDE, 195 + VERTGUIDE, 289 + TOPMARGIN, 7 + BOTTOMMARGIN, 80 + HORZGUIDE, 17 + HORZGUIDE, 30 + HORZGUIDE, 40 + HORZGUIDE, 50 + END + + IDD_AUDIO_QUALITY, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 250 + VERTGUIDE, 100 + VERTGUIDE, 150 + VERTGUIDE, 200 + TOPMARGIN, 7 + BOTTOMMARGIN, 58 + HORZGUIDE, 20 + HORZGUIDE, 36 + END + + IDD_SETTINGS_PLAYERS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 308 + VERTGUIDE, 64 + VERTGUIDE, 74 + TOPMARGIN, 7 + BOTTOMMARGIN, 205 + HORZGUIDE, 18 + HORZGUIDE, 38 + HORZGUIDE, 58 + HORZGUIDE, 106 + HORZGUIDE, 126 + HORZGUIDE, 146 + HORZGUIDE, 166 + HORZGUIDE, 180 + END + + IDD_PLAYER_CONTROLS, DIALOG + BEGIN + LEFTMARGIN, 2 + RIGHTMARGIN, 384 + VERTGUIDE, 8 + VERTGUIDE, 169 + VERTGUIDE, 177 + VERTGUIDE, 239 + VERTGUIDE, 250 + VERTGUIDE, 288 + VERTGUIDE, 308 + VERTGUIDE, 376 + TOPMARGIN, 7 + BOTTOMMARGIN, 253 + HORZGUIDE, 24 + HORZGUIDE, 35 + HORZGUIDE, 55 + HORZGUIDE, 80 + HORZGUIDE, 93 + HORZGUIDE, 101 + HORZGUIDE, 120 + HORZGUIDE, 136 + HORZGUIDE, 152 + HORZGUIDE, 162 + HORZGUIDE, 184 + HORZGUIDE, 220 + END + + IDD_PLAYER_APPEARANCE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 227 + VERTGUIDE, 91 + TOPMARGIN, 7 + BOTTOMMARGIN, 157 + HORZGUIDE, 19 + END + + IDD_CONSOLE, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 436 + VERTGUIDE, 76 + VERTGUIDE, 303 + TOPMARGIN, 7 + BOTTOMMARGIN, 279 + HORZGUIDE, 176 + HORZGUIDE, 185 + HORZGUIDE, 193 + END + + IDD_EDIT_BUTTON_ACTION, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 391 + VERTGUIDE, 118 + TOPMARGIN, 7 + BOTTOMMARGIN, 146 + HORZGUIDE, 22 + HORZGUIDE, 39 + END + + IDD_RENAME_CONTROLS, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 176 + VERTGUIDE, 85 + TOPMARGIN, 7 + BOTTOMMARGIN, 51 + HORZGUIDE, 24 + END + + IDD_SELECT_PLAYER, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 265 + VERTGUIDE, 79 + TOPMARGIN, 7 + BOTTOMMARGIN, 74 + HORZGUIDE, 25 + HORZGUIDE, 44 + END +END +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_BUTTON_ACTION_POPUP MENU DISCARDABLE +BEGIN + POPUP "Main" + BEGIN + MENUITEM "Edit", ID_BUTTON_ACTION_EDIT + MENUITEM "Add", ID_BUTTON_ACTION_ADD + MENUITEM "Remove", ID_BUTTON_ACTION_REMOVE + END +END + + +///////////////////////////////////////////////////////////////////////////// +// +// Bitmap +// + +IDB_CURSOR_UP BITMAP DISCARDABLE "cursor_u.bmp" +IDB_CURSOR_DOWN BITMAP DISCARDABLE "bmp00001.bmp" + +///////////////////////////////////////////////////////////////////////////// +// +// String Table +// + +STRINGTABLE DISCARDABLE +BEGIN + IDS_DEFAULT_ARIAL "Arial" +END + +STRINGTABLE DISCARDABLE +BEGIN + ID_BUTTON_ACTION_EDIT "Edit button action\nEdit button action" + ID_BUTTON_ACTION_ADD "Add button action\nAdd button action" + ID_BUTTON_ACTION_REMOVE "Remove button action\nRemove button action" +END + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// +#define _AFX_NO_SPLITTER_RESOURCES +#define _AFX_NO_OLE_RESOURCES +#define _AFX_NO_TRACKER_RESOURCES +#define _AFX_NO_PROPERTY_RESOURCES + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE 9, 1 +#pragma code_page(1252) +#endif +#include "res\Game.rc2" // non-Microsoft Visual C++ edited resources +#include "afxres.rc" // Standard components +#endif +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Sources/GameGUIMP/GameGUIMP.clw b/Sources/GameGUIMP/GameGUIMP.clw new file mode 100644 index 0000000..49a6dfa --- /dev/null +++ b/Sources/GameGUIMP/GameGUIMP.clw @@ -0,0 +1,519 @@ +; CLW file contains information for the MFC ClassWizard + +[General Info] +Version=1 +ClassCount=28 +Class1=CGameApp +LastClass=CDlgSelectPlayer +NewFileInclude2=#include "Game.h" +ResourceCount=16 +NewFileInclude1=#include "stdafx.h" +Resource1=IDD_MULTIPLAYER_JOIN +Class2=CEditConsole +LastTemplate=CDialog +Class3=CDlgSinglePlayerNew +Class4=CDlgSinglePlayerNewGame +Resource2=IDD_SELECT_PROVIDER_ON_JOIN +Resource3=IDD_VIDEO_QUALITY +Resource4=IDD_CREATE_PLAYER +Resource5=IDD_MULTIPLAYER_OPEN_LOCAL_PLAYERS +Resource6=IDD_SETTINGS_PLAYERS +Resource7=IDD_MULTIPLAYER_NEW +Resource8=IDD_CONSOLE +Resource9=IDD_RENAME_CONTROLS +Class5=CDlgAudioQuality +Class6=CDlgCreatePlayer +Class7=CDlgMultiplayerJoinGame +Class8=CDlgNewMultiplayerGame +Class9=CLocalPlayersList +Class10=CDlgPlayerAppearance +Class11=CDlgPlayerControls +Class12=CDlgPlayerSettings +Class13=CDlgVideoQuality +Class14=CPressKeyEditControl +Class15=CActionsListControl +Class16=CAxisListCtrl +Class17=CPressKeyWnd +Class18=CPressKeyFullScreenWnd +Class19=CDlgPressNewButtonMessage +Class20=CPlayerSettingsPlayerList +Resource10=IDD_SINGLE_PLAYER_NEW +Class21=CDlgMultiplayerOpenLocalPlayers +Resource11=IDD_SELECT_PLAYER +Class22=CDlgSelectProviderOnJoin +Class23=CDlgConsole +Resource12=IDD_AUDIO_QUALITY +Resource13=IDD_PLAYER_CONTROLS +Class24=CDlgEditButtonAction +Class25=CConsoleSymbolsCombo +Class26=CPlayerSettingsControlsList +Resource14=IDD_PLAYER_APPEARANCE +Class27=CDlgRenameControls +Resource15=IDD_EDIT_BUTTON_ACTION +Class28=CDlgSelectPlayer +Resource16=IDR_BUTTON_ACTION_POPUP + +[CLS:CGameApp] +Type=0 +HeaderFile=Game.h +ImplementationFile=Game.cpp +Filter=N + +[DLG:IDD_SINGLE_PLAYER_NEW] +Type=1 +Class=CDlgSinglePlayerNewGame +ControlCount=14 +Control1=IDC_STATIC,static,1342308352 +Control2=ID_AVAILABLE_PLAYERS,combobox,1344340227 +Control3=IDC_STATIC,static,1342308352 +Control4=IDC_DIFICULTY_LEVEL,button,1342308361 +Control5=IDC_SINGLE_NORMAL,button,1342177289 +Control6=IDC_SINGLE_HARD,button,1342177289 +Control7=IDC_SINGLE_EXTREME,button,1342177289 +Control8=IDOK,button,1342242817 +Control9=IDCANCEL,button,1342242816 +Control10=IDC_CHOOSE_LEVEL,button,1342242816 +Control11=IDC_STATIC,static,1342308352 +Control12=IDC_LEVEL_NAME,static,1342308352 +Control13=IDC_STATIC,static,1342308352 +Control14=ID_AVAILABLE_CONTROLS,combobox,1344340227 + +[CLS:CDlgSinglePlayerNew] +Type=0 +HeaderFile=DlgSinglePlayerNew.h +ImplementationFile=DlgSinglePlayerNew.cpp +BaseClass=CDialog +Filter=D +LastObject=CDlgSinglePlayerNew + +[CLS:CDlgSinglePlayerNewGame] +Type=0 +HeaderFile=dlgsingleplayernewgame.h +ImplementationFile=dlgsingleplayernewgame.cpp +BaseClass=CDialog +LastObject=ID_AVAILABLE_PLAYERS +Filter=D +VirtualFilter=dWC + +[DLG:IDD_MULTIPLAYER_NEW] +Type=1 +Class=CDlgNewMultiplayerGame +ControlCount=29 +Control1=IDOK,button,1342242817 +Control2=IDCANCEL,button,1342242816 +Control3=IDC_STATIC,static,1342308352 +Control4=IDC_LEVEL_NAME,static,1342308352 +Control5=IDC_CHOOSE_LEVEL,button,1342242816 +Control6=IDC_STATIC,static,1342308352 +Control7=IDC_PROVIDERS,combobox,1344339971 +Control8=IDC_STATIC,static,1342308352 +Control9=IDC_SESSION_NAME,edit,1350631552 +Control10=IDC_STATIC,static,1342308352 +Control11=IDC_GAME_TYPE,combobox,1344339971 +Control12=IDC_TEAM_PLAY,button,1342242851 +Control13=IDC_STATIC,static,1342308352 +Control14=IDC_MULTIPLAYER_EASY,button,1342373897 +Control15=IDC_MULTIPLAYER_NORMAL,button,1342177289 +Control16=IDC_MULTIPLAYER_HARD,button,1342177289 +Control17=IDC_MULTIPLAYER_EXTREME,button,1342177289 +Control18=IDC_STATIC,static,1342308352 +Control19=IDC_FRAG_LIMIT,edit,1350639744 +Control20=IDC_SPIN_FRAG_LIMIT,msctls_updown32,1342177463 +Control21=IDC_STATIC,static,1342308352 +Control22=IDC_TIME_LIMIT,edit,1350639744 +Control23=IDC_SPIN_TIME_LIMIT,msctls_updown32,1342177463 +Control24=IDC_STATIC,static,1342308353 +Control25=IDC_LOCAL_PLAYERS,listbox,1352745299 +Control26=IDC_STATIC,static,1342308352 +Control27=IDC_MAX_PLAYERS,edit,1350639744 +Control28=IDC_SPIN_MAX_PLAYERS,msctls_updown32,1342177463 +Control29=IDC_DUMMY_LIST,listbox,1218511107 + +[DLG:IDD_VIDEO_QUALITY] +Type=1 +Class=CDlgVideoQuality +ControlCount=14 +Control1=IDC_STATIC,static,1342308352 +Control2=IDC_TEXTURE_QUALITY,button,1342308361 +Control3=IDC_TEXTURE_QUALITY_NORMAL,button,1342177289 +Control4=IDC_TEXTURE_QUALITY_HIGH,button,1342177289 +Control5=IDC_STATIC,static,1342308352 +Control6=IDC_OBJECT_SHADOW_QUALITY,button,1342308361 +Control7=IDC_OBJECT_SHADOW_QUALITY_LOW,button,1342177289 +Control8=IDC_OBJECT_SHADOW_QUALITY_HIGH,button,1342177289 +Control9=IDC_STATIC,static,1342308352 +Control10=IDC_WORLD_SHADOW_QUALITY,button,1342308361 +Control11=IDC_WORLD_SHADOW_QUALITY_NORMAL,button,1342177289 +Control12=IDC_WORLD_SHADOW_QUALITY_HIGH,button,1342177289 +Control13=IDOK,button,1342242817 +Control14=IDCANCEL,button,1342242816 + +[DLG:IDD_AUDIO_QUALITY] +Type=1 +Class=CDlgAudioQuality +ControlCount=7 +Control1=IDOK,button,1342242817 +Control2=IDCANCEL,button,1342242816 +Control3=65535,static,1342308352 +Control4=IDC_AUDIO_QUALITY_LOW,button,1342308361 +Control5=IDC_AUDIO_QUALITY_NORMAL,button,1342177289 +Control6=IDC_AUDIO_QUALITY_HIGH,button,1342177289 +Control7=IDC_USE_DSOUND3D,button,1342242851 + +[DLG:IDD_MULTIPLAYER_JOIN] +Type=1 +Class=CDlgMultiplayerJoinGame +ControlCount=7 +Control1=IDOK,button,1342242817 +Control2=IDCANCEL,button,1342242816 +Control3=IDC_SESSION_LIST,listbox,1352728835 +Control4=IDC_LOCAL_PLAYERS,listbox,1352745299 +Control5=IDC_STATIC,static,1342308353 +Control6=IDC_STATIC,static,1342308353 +Control7=IDC_DUMMY_LIST,listbox,1218511107 + +[DLG:IDD_SETTINGS_PLAYERS] +Type=1 +Class=CDlgPlayerSettings +ControlCount=9 +Control1=IDC_RENAME_PLAYER,button,1342242816 +Control2=IDC_PLAYER_APPEARANCE,button,1342242816 +Control3=IDC_AVAILABLE_PLAYERS,listbox,1352728833 +Control4=IDC_RENAME_CONTROLS,button,1342242816 +Control5=IDC_EDIT_CONTROLS,button,1342242816 +Control6=IDC_AVAILABLE_CONTROLS,listbox,1352728833 +Control7=IDC_STATIC,static,1342308353 +Control8=IDOK,button,1342242817 +Control9=IDC_STATIC,static,1342308353 + +[DLG:IDD_CREATE_PLAYER] +Type=1 +Class=CDlgCreatePlayer +ControlCount=4 +Control1=IDC_EDIT_PLAYER_NAME,edit,1350631552 +Control2=IDOK,button,1342242817 +Control3=IDCANCEL,button,1342242816 +Control4=IDC_STATIC,static,1342308352 + +[DLG:IDD_PLAYER_CONTROLS] +Type=1 +Class=CDlgPlayerControls +ControlCount=27 +Control1=IDC_BUTTON_ACTIONS_LIST,SysListView32,1350664197 +Control2=IDOK,button,1342242817 +Control3=IDC_PRESS_MESSAGE,static,1342308353 +Control4=IDC_STATIC,static,1342308353 +Control5=IDC_EDIT_FIRST_CONTROL,edit,1484783744 +Control6=ID_FIRST_CONTROL_NONE,button,1476395008 +Control7=IDC_STATIC,static,1342308353 +Control8=IDC_EDIT_SECOND_CONTROL,edit,1484783744 +Control9=ID_SECOND_CONTROL_NONE,button,1476395008 +Control10=ID_MOVE_CONTROL_DOWN,button,1342243584 +Control11=ID_MOVE_CONTROL_UP,button,1342242816 +Control12=ID_BUTTON_ACTION_EDIT,button,1342242816 +Control13=ID_BUTTON_ACTION_ADD,button,1342242816 +Control14=ID_BUTTON_ACTION_REMOVE,button,1342242816 +Control15=IDC_AXIS_ACTIONS_LIST,SysListView32,1350664197 +Control16=IDC_STATIC,static,1342308353 +Control17=IDC_CONTROLER_AXIS,combobox,1478557699 +Control18=IDC_INVERT_CONTROLER,button,1476460579 +Control19=IDC_CONTROLER_TYPE_T,static,1476526080 +Control20=IDC_RELATIVE_ABSOLUTE_TYPE,button,1476526089 +Control21=IDC_ABSOLUTE_RADIO,button,1476395017 +Control22=IDC_CONTROLER_SENSITIVITY_T,static,1476526081 +Control23=IDC_CONTROLER_SENSITIVITY,msctls_trackbar32,1476460545 +Control24=ID_DEFAULT,button,1342242816 +Control25=IDCANCEL,button,1342242816 +Control26=IDC_STATIC,button,1342178055 +Control27=IDC_STATIC,button,1342178055 + +[DLG:IDD_PLAYER_APPEARANCE] +Type=1 +Class=CDlgPlayerAppearance +ControlCount=4 +Control1=IDOK,button,1342242817 +Control2=IDCANCEL,button,1342242816 +Control3=IDC_AVAILABLE_APPEARANCES,combobox,1344340227 +Control4=IDC_STATIC,static,1342308352 + +[CLS:CDlgAudioQuality] +Type=0 +HeaderFile=DlgAudioQuality.h +ImplementationFile=DlgAudioQuality.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC + +[CLS:CDlgCreatePlayer] +Type=0 +HeaderFile=DlgCreatePlayer.h +ImplementationFile=DlgCreatePlayer.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC + +[CLS:CDlgMultiplayerJoinGame] +Type=0 +HeaderFile=DlgMultiplayerJoinGame.h +ImplementationFile=DlgMultiplayerJoinGame.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=CDlgMultiplayerJoinGame + +[CLS:CDlgNewMultiplayerGame] +Type=0 +HeaderFile=DlgNewMultiplayerGame.h +ImplementationFile=DlgNewMultiplayerGame.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=CDlgNewMultiplayerGame + +[CLS:CLocalPlayersList] +Type=0 +HeaderFile=LocalPlayersList.h +ImplementationFile=LocalPlayersList.cpp +BaseClass=CListBox +Filter=W + +[CLS:CDlgPlayerAppearance] +Type=0 +HeaderFile=DlgPlayerAppearance.h +ImplementationFile=DlgPlayerAppearance.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC + +[CLS:CDlgPlayerControls] +Type=0 +HeaderFile=DlgPlayerControls.h +ImplementationFile=DlgPlayerControls.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=IDC_CONTROLER_SENSITIVITY_T + +[CLS:CDlgPlayerSettings] +Type=0 +HeaderFile=DlgPlayerSettings.h +ImplementationFile=DlgPlayerSettings.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=IDC_RENAME_PLAYER + +[CLS:CDlgVideoQuality] +Type=0 +HeaderFile=DlgVideoQuality.h +ImplementationFile=DlgVideoQuality.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC + +[CLS:CPressKeyEditControl] +Type=0 +HeaderFile=PressKeyEditControl.h +ImplementationFile=PressKeyEditControl.cpp +BaseClass=CEdit +Filter=W +LastObject=CPressKeyEditControl +VirtualFilter=WC + +[CLS:CActionsListControl] +Type=0 +HeaderFile=ActionsListControl.h +ImplementationFile=ActionsListControl.cpp +BaseClass=CListCtrl +Filter=W +VirtualFilter=FWC +LastObject=CActionsListControl + +[CLS:CAxisListCtrl] +Type=0 +HeaderFile=AxisListCtrl.h +ImplementationFile=AxisListCtrl.cpp +BaseClass=CListCtrl +Filter=W +VirtualFilter=FWC + +[CLS:CPressKeyWnd] +Type=0 +HeaderFile=PressKeyWnd.h +ImplementationFile=PressKeyWnd.cpp +BaseClass=generic CWnd +Filter=W +LastObject=CPressKeyWnd + +[CLS:CPressKeyFullScreenWnd] +Type=0 +HeaderFile=PressKeyFullScreenWnd.h +ImplementationFile=PressKeyFullScreenWnd.cpp +BaseClass=generic CWnd +Filter=W +LastObject=CPressKeyFullScreenWnd + +[CLS:CDlgPressNewButtonMessage] +Type=0 +HeaderFile=DlgPressNewButtonMessage.h +ImplementationFile=DlgPressNewButtonMessage.cpp +BaseClass=CDialog +Filter=D +LastObject=CDlgPressNewButtonMessage +VirtualFilter=dWC + +[CLS:CPlayerSettingsPlayerList] +Type=0 +HeaderFile=PlayerSettingsPlayerList.h +ImplementationFile=PlayerSettingsPlayerList.cpp +BaseClass=CListBox +Filter=W +VirtualFilter=bWC + +[DLG:IDD_MULTIPLAYER_OPEN_LOCAL_PLAYERS] +Type=1 +Class=CDlgMultiplayerOpenLocalPlayers +ControlCount=5 +Control1=IDC_LOCAL_PLAYERS,listbox,1352745299 +Control2=IDOK,button,1342242817 +Control3=IDCANCEL,button,1342242816 +Control4=IDC_STATIC,static,1342308353 +Control5=IDC_DUMMY_LIST,listbox,1218511107 + +[CLS:CDlgMultiplayerOpenLocalPlayers] +Type=0 +HeaderFile=DlgMultiplayerOpenLocalPlayers.h +ImplementationFile=DlgMultiplayerOpenLocalPlayers.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=IDC_AVAILABLE_PROVIDERS + +[DLG:IDD_SELECT_PROVIDER_ON_JOIN] +Type=1 +Class=CDlgSelectProviderOnJoin +ControlCount=3 +Control1=IDC_AVAILABLE_PROVIDERS,listbox,1352728835 +Control2=IDOK,button,1342242817 +Control3=IDCANCEL,button,1342242816 + +[CLS:CDlgSelectProviderOnJoin] +Type=0 +HeaderFile=DlgSelectProviderOnJoin.h +ImplementationFile=DlgSelectProviderOnJoin.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC + +[CLS:CEditConsole] +Type=0 +HeaderFile=EditConsole.h +ImplementationFile=EditConsole.cpp +BaseClass=CEdit +Filter=W +LastObject=CEditConsole +VirtualFilter=WC + +[DLG:IDD_CONSOLE] +Type=1 +Class=CDlgConsole +ControlCount=4 +Control1=IDC_CONSOLE_INPUT,edit,1353781444 +Control2=IDC_CONSOLE_OUTPUT,edit,1353779396 +Control3=IDC_STATIC,static,1342308352 +Control4=IDC_CONSOLE_SYMBOLS,combobox,1344340227 + +[CLS:CDlgConsole] +Type=0 +HeaderFile=DlgConsole.h +ImplementationFile=DlgConsole.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=CDlgConsole + +[MNU:IDR_BUTTON_ACTION_POPUP] +Type=1 +Class=? +Command1=ID_BUTTON_ACTION_EDIT +Command2=ID_BUTTON_ACTION_ADD +Command3=ID_BUTTON_ACTION_REMOVE +CommandCount=3 + +[DLG:IDD_EDIT_BUTTON_ACTION] +Type=1 +Class=CDlgEditButtonAction +ControlCount=8 +Control1=IDOK,button,1342242817 +Control2=IDCANCEL,button,1342242816 +Control3=IDC_STATIC,static,1342308352 +Control4=IDC_BUTTON_ACTION_NAME,edit,1350631552 +Control5=IDC_STATIC,static,1342308352 +Control6=IDC_BUTTON_DOWN_COMMAND,edit,1350631556 +Control7=IDC_STATIC,static,1342308352 +Control8=IDC_BUTTON_UP_COMMAND,edit,1350631556 + +[CLS:CDlgEditButtonAction] +Type=0 +HeaderFile=DlgEditButtonAction.h +ImplementationFile=DlgEditButtonAction.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC + +[CLS:CConsoleSymbolsCombo] +Type=0 +HeaderFile=ConsoleSymbolsCombo.h +ImplementationFile=ConsoleSymbolsCombo.cpp +BaseClass=CComboBox +Filter=W +LastObject=CConsoleSymbolsCombo +VirtualFilter=cWC + +[CLS:CPlayerSettingsControlsList] +Type=0 +HeaderFile=PlayerSettingsControlsList.h +ImplementationFile=PlayerSettingsControlsList.cpp +BaseClass=CListBox +Filter=W +VirtualFilter=bWC +LastObject=CPlayerSettingsControlsList + +[DLG:IDD_RENAME_CONTROLS] +Type=1 +Class=CDlgRenameControls +ControlCount=4 +Control1=IDC_EDIT_CONTROLS_NAME,edit,1350631552 +Control2=IDOK,button,1342242817 +Control3=IDCANCEL,button,1342242816 +Control4=IDC_STATIC,static,1342308352 + +[CLS:CDlgRenameControls] +Type=0 +HeaderFile=DlgRenameControls.h +ImplementationFile=DlgRenameControls.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=CDlgRenameControls + +[DLG:IDD_SELECT_PLAYER] +Type=1 +Class=CDlgSelectPlayer +ControlCount=6 +Control1=IDOK,button,1342242817 +Control2=IDCANCEL,button,1342242816 +Control3=IDC_STATIC,static,1342308352 +Control4=IDC_COMBO_AVAILABLE_PLAYERS,combobox,1344339971 +Control5=IDC_STATIC,static,1342308352 +Control6=IDC_COMBO_AVAILABLE_CONTROLS,combobox,1344339971 + +[CLS:CDlgSelectPlayer] +Type=0 +HeaderFile=DlgSelectPlayer.h +ImplementationFile=DlgSelectPlayer.cpp +BaseClass=CDialog +Filter=D +VirtualFilter=dWC +LastObject=IDC_COMBO_AVAILABLE_CONTROLS + diff --git a/Sources/GameGUIMP/GameGUIMP.vcxproj b/Sources/GameGUIMP/GameGUIMP.vcxproj new file mode 100644 index 0000000..db0ff9d --- /dev/null +++ b/Sources/GameGUIMP/GameGUIMP.vcxproj @@ -0,0 +1,255 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Template + Win32 + + + + + + + + MFCProj + {3EC2357F-FA36-9DF7-FFC4-AF9C03777DBE} + + + + Application + v120 + Unicode + + + DynamicLibrary + Dynamic + Unicode + v120 + + + DynamicLibrary + Dynamic + Unicode + v120 + + + + + + + + + + + + + + + + + + Debug\ + Debug\ + false + $(ProjectName)D + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin\Debug;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + Release\ + Release\ + false + $(SolutionDir);$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Include;$(IncludePath) + $(SolutionDir)..\Bin;$(SolutionDir)..\Tools.Win32\Libraries\DX8SDK\Lib;$(LibraryPath) + + + + MultiThreadedDebugDLL + Default + false + Disabled + true + Level3 + true + WIN32;_DEBUG;_WINDOWS;_USRDLL;GAMEGUI_EXPORTS;_WINDLL;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Debug\ + .\Debug\GameGUIMP.pch + Use + stdafx.h + .\Debug\ + .\Debug\ + EnableFastChecks + 4996;4333 + + + true + _DEBUG;%(PreprocessorDefinitions) + .\Debug\GameGUIMP.tlb + true + Win32 + + + 0x0409 + _DEBUG;%(PreprocessorDefinitions) + + + true + .\Debug\GameGUIMP.bsc + + + true + true + true + Console + Debug/GameGUIMPD.dll + .\Debug\GameGUIMPD.lib + true + + + copy Debug\$(TargetName).dll $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).map $(SolutionDir)..\Bin\Debug\ >nul +copy Debug\$(TargetName).lib $(SolutionDir)..\Bin\Debug\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin\Debug + $(ENGINE_DIR)\Bin\Debug\$(InputName).dll;%(Outputs) + + + + + MultiThreadedDLL + OnlyExplicitInline + false + MaxSpeed + true + Level3 + Speed + true + false + WIN32;NDEBUG;_WINDOWS;_USRDLL;GAMEGUI_EXPORTS;_WINDLL;DIRECT3D_VERSION=0x0800;%(PreprocessorDefinitions) + .\Release\ + .\Release\GameGUIMP.pch + Use + stdafx.h + .\Release\ + .\Release\ + 4996;4333 + + + true + NDEBUG;%(PreprocessorDefinitions) + .\Release\GameGUIMP.tlb + true + Win32 + + + 0x0409 + NDEBUG;%(PreprocessorDefinitions) + + + true + .\Release\GameGUIMP.bsc + + + true + true + true + Console + .\Release\GameGUIMP.dll + .\Release\GameGUIMP.lib + true + + + copy Release\$(TargetName).dll $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).map $(SolutionDir)..\Bin\ >nul +copy Release\$(TargetName).lib $(SolutionDir)..\Bin\ >nul + Copying %(Filename) binaries to $(ENGINE_DIR)\Bin + $(ENGINE_DIR)\Bin\$(InputName).dll;%(Outputs) + + + + + true + true + + + true + true + + + + + + true + true + + + + true + true + + + true + true + + + true + true + + + true + true + + + + + + + + Create + stdafx.h + Create + stdafx.h + + + + + + + + + + + + + + + + + + + + + + + + + + + Document + + + + + + + + + + \ No newline at end of file diff --git a/Sources/GameGUIMP/GameGUIMP.vcxproj.filters b/Sources/GameGUIMP/GameGUIMP.vcxproj.filters new file mode 100644 index 0000000..3f7eb3b --- /dev/null +++ b/Sources/GameGUIMP/GameGUIMP.vcxproj.filters @@ -0,0 +1,146 @@ + + + + + {57ee4002-9b18-4970-aac2-03fd1ec3f9af} + cpp;c;cxx;rc;def;r;odl;idl;hpj;bat + + + {b23fc2b2-efbd-4362-9c97-81faf33d2cfd} + h;hpp;hxx;hm;inl + + + {a0a9770c-fb58-4289-aaf8-68788e19abf9} + ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe + + + {a705b770-faa3-4caf-9ab9-bba0444a333b} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + + + Resource Files + + + Resource Files + + + Wizard Files + + + + \ No newline at end of file diff --git a/Sources/GameGUIMP/GameGUIMP.vcxproj.user b/Sources/GameGUIMP/GameGUIMP.vcxproj.user new file mode 100644 index 0000000..ace9a86 --- /dev/null +++ b/Sources/GameGUIMP/GameGUIMP.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/Sources/GameGUIMP/LocalPlayersList.cpp b/Sources/GameGUIMP/LocalPlayersList.cpp new file mode 100644 index 0000000..fc7f57b --- /dev/null +++ b/Sources/GameGUIMP/LocalPlayersList.cpp @@ -0,0 +1,34 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// LocalPlayersList.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CLocalPlayersList + +CLocalPlayersList::CLocalPlayersList() +{ +} + +CLocalPlayersList::~CLocalPlayersList() +{ +} + + +BEGIN_MESSAGE_MAP(CLocalPlayersList, CCheckListBox) + //{{AFX_MSG_MAP(CLocalPlayersList) + // NOTE - the ClassWizard will add and remove mapping macros here. + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLocalPlayersList message handlers diff --git a/Sources/GameGUIMP/LocalPlayersList.h b/Sources/GameGUIMP/LocalPlayersList.h new file mode 100644 index 0000000..7073c2c --- /dev/null +++ b/Sources/GameGUIMP/LocalPlayersList.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// LocalPlayersList.h : header file +// +#ifndef LOCALPLAYERSLIST_H +#define LOCALPLAYERSLIST_H 1 + +///////////////////////////////////////////////////////////////////////////// +// CLocalPlayersList window + +class CLocalPlayersList : public CCheckListBox +{ +// Construction +public: + CLocalPlayersList(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLocalPlayersList) + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CLocalPlayersList(); + + // Generated message map functions +protected: + //{{AFX_MSG(CLocalPlayersList) + // NOTE - the ClassWizard will add and remove member functions here. + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +#endif // LOCALPLAYERSLIST_H \ No newline at end of file diff --git a/Sources/GameGUIMP/PressKeyEditControl.cpp b/Sources/GameGUIMP/PressKeyEditControl.cpp new file mode 100644 index 0000000..c10a369 --- /dev/null +++ b/Sources/GameGUIMP/PressKeyEditControl.cpp @@ -0,0 +1,62 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// PressKeyEditControl.cpp : implementation file +// + +#include "stdafx.h" + +#ifdef _DEBUG +#undef new +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CPressKeyEditControl + +CPressKeyEditControl::CPressKeyEditControl() +{ +} + +CPressKeyEditControl::~CPressKeyEditControl() +{ +} + + +BEGIN_MESSAGE_MAP(CPressKeyEditControl, CEdit) + //{{AFX_MSG_MAP(CPressKeyEditControl) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPressKeyEditControl message handlers + + +BOOL CPressKeyEditControl::PreTranslateMessage(MSG* pMsg) +{ + // if direct input is curently on + if( _pInput->IsInputEnabled()) + { + // and if we caught alt key message + if( pMsg->message==WM_SYSKEYDOWN) + { + // get key data + int lKeyData = pMsg->lParam; + // test if it is ghost Alt-F4 situation + if( lKeyData & (1L<<29)) + { + // don't continue translating the message + return TRUE; + } + } + // test if game is paused, stop messages otherwise let messages trough + if (pMsg->message==WM_KEYDOWN) + { + // direct input is enabled, so don't translate messages + return TRUE; + } + } + + return CEdit::PreTranslateMessage(pMsg); +} diff --git a/Sources/GameGUIMP/PressKeyEditControl.h b/Sources/GameGUIMP/PressKeyEditControl.h new file mode 100644 index 0000000..2f769b8 --- /dev/null +++ b/Sources/GameGUIMP/PressKeyEditControl.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// PressKeyEditControl.h : header file +// +#ifndef PRESSKEYEDITCONTROL_H +#define PRESSKEYEDITCONTROL_H 1 + +///////////////////////////////////////////////////////////////////////////// +// CPressKeyEditControl window + +class CPressKeyEditControl : public CEdit +{ +// Construction +public: + CPressKeyEditControl(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPressKeyEditControl) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CPressKeyEditControl(); + + // Generated message map functions +protected: + //{{AFX_MSG(CPressKeyEditControl) + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// +#endif // PRESSKEYEDITCONTROL_H 1 diff --git a/Sources/GameGUIMP/ReadMe.txt b/Sources/GameGUIMP/ReadMe.txt new file mode 100644 index 0000000..6bb8268 --- /dev/null +++ b/Sources/GameGUIMP/ReadMe.txt @@ -0,0 +1,37 @@ +======================================================================== + DYNAMIC LINK LIBRARY : GameGUI +======================================================================== + + +AppWizard has created this GameGUI DLL for you. + +This file contains a summary of what you will find in each of the files that +make up your GameGUI application. + +GameGUI.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +GameGUI.cpp + This is the main DLL source file. + +GameGUI.h + This file contains your DLL exports. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named GameGUI.pch and a precompiled types file named StdAfx.obj. + + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + + +///////////////////////////////////////////////////////////////////////////// diff --git a/Sources/GameGUIMP/StdAfx.cpp b/Sources/GameGUIMP/StdAfx.cpp new file mode 100644 index 0000000..f7a7b80 --- /dev/null +++ b/Sources/GameGUIMP/StdAfx.cpp @@ -0,0 +1,10 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// stdafx.cpp : source file that includes just the standard includes +// GameGUI.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/Sources/GameGUIMP/StdAfx.h b/Sources/GameGUIMP/StdAfx.h new file mode 100644 index 0000000..3bbfac3 --- /dev/null +++ b/Sources/GameGUIMP/StdAfx.h @@ -0,0 +1,57 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions + +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC OLE classes +#include // MFC OLE dialog classes +#include // MFC OLE automation classes +#endif // _AFX_NO_OLE_SUPPORT + + +#ifndef _AFX_NO_DB_SUPPORT +#include // MFC ODBC database classes +#endif // _AFX_NO_DB_SUPPORT + +#ifndef _AFX_NO_DAO_SUPPORT +#include // MFC DAO database classes +#endif // _AFX_NO_DAO_SUPPORT + +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +#include +#include +#include +#include + +extern class CGame *_pGame; + +///////////////////////////////////////////////////////////////////////////// + +#include "resource.h" +#include "ConsoleSymbolsCombo.h" +#include "ActionsListControl.h" +#include "AxisListCtrl.h" +#include "EditConsole.h" +#include "LocalPlayersList.h" +#include "PressKeyEditControl.h" +#include "DlgSelectPlayer.h" +#include "DlgRenameControls.h" +#include "DlgAudioQuality.h" +#include "DlgPlayerAppearance.h" +#include "DlgPlayerControls.h" +#include "DlgPlayerSettings.h" +#include "DlgVideoQuality.h" +#include "DlgConsole.h" +#include "DlgEditButtonAction.h" diff --git a/Sources/GameGUIMP/bmp00001.bmp b/Sources/GameGUIMP/bmp00001.bmp new file mode 100644 index 0000000..04dda2e Binary files /dev/null and b/Sources/GameGUIMP/bmp00001.bmp differ diff --git a/Sources/GameGUIMP/cursor_u.bmp b/Sources/GameGUIMP/cursor_u.bmp new file mode 100644 index 0000000..b81c4f1 Binary files /dev/null and b/Sources/GameGUIMP/cursor_u.bmp differ diff --git a/Sources/GameGUIMP/res/Game.rc2 b/Sources/GameGUIMP/res/Game.rc2 new file mode 100644 index 0000000..e8d7f94 --- /dev/null +++ b/Sources/GameGUIMP/res/Game.rc2 @@ -0,0 +1,13 @@ +// +// GAME.RC2 - resources Microsoft Visual C++ does not edit directly +// + +#ifdef APSTUDIO_INVOKED + #error this file is not editable by Microsoft Visual C++ +#endif //APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// Add manually edited resources here... + +///////////////////////////////////////////////////////////////////////////// diff --git a/Sources/GameGUIMP/resource.h b/Sources/GameGUIMP/resource.h new file mode 100644 index 0000000..091b9ab --- /dev/null +++ b/Sources/GameGUIMP/resource.h @@ -0,0 +1,119 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by Game.rc +// +#define IDS_DEFAULT_ARIAL 1 +#define ID_FIRST_CONTROL_NONE 3 +#define ID_SECOND_CONTROL_NONE 4 +#define ID_DEFAULT 5 +#define ID_MOVE_CONTROL_DOWN 6 +#define ID_MOVE_CONTROL_UP 7 +#define IDD_SINGLE_PLAYER_NEW 129 +#define IDD_MULTIPLAYER_NEW 130 +#define IDD_VIDEO_QUALITY 131 +#define IDD_AUDIO_QUALITY 132 +#define IDD_MULTIPLAYER_JOIN 133 +#define IDD_SETTINGS_PLAYERS 134 +#define IDD_CREATE_PLAYER 135 +#define IDD_PLAYER_CONTROLS 136 +#define IDD_PLAYER_APPEARANCE 137 +#define IDD_MULTIPLAYER_OPEN_LOCAL_PLAYERS 138 +#define IDD_SELECT_PROVIDER_ON_JOIN 139 +#define IDD_CONSOLE 140 +#define IDR_BUTTON_ACTION_POPUP 141 +#define IDD_EDIT_BUTTON_ACTION 142 +#define IDD_RENAME_CONTROLS 143 +#define IDB_CURSOR_UP 144 +#define IDB_CURSOR_DOWN 145 +#define IDD_SELECT_PLAYER 177 +#define ID_AVAILABLE_PLAYERS 1000 +#define IDC_DIFICULTY_LEVEL 1001 +#define IDC_SESSION_NAME 1002 +#define IDC_SINGLE_NORMAL 1002 +#define IDC_SINGLE_HARD 1003 +#define IDC_PROVIDERS 1004 +#define IDC_SINGLE_EXTREME 1004 +#define IDC_MULTIPLAYER_NORMAL 1005 +#define ID_AVAILABLE_CONTROLS 1005 +#define IDC_MULTIPLAYER_EXTREME 1006 +#define IDC_CHOOSE_LEVEL 1007 +#define IDC_GAME_TYPE 1008 +#define IDC_MULTIPLAYER_EASY 1009 +#define IDC_MULTIPLAYER_HARD 1010 +#define IDC_TEAM_PLAY 1011 +#define IDC_LEVEL_NAME 1012 +#define IDC_FRAG_LIMIT 1013 +#define IDC_TIME_LIMIT 1014 +#define IDC_MAX_PLAYERS 1015 +#define IDC_SPIN_FRAG_LIMIT 1018 +#define IDC_SPIN_TIME_LIMIT 1019 +#define IDC_LOCAL_PLAYERS 1020 +#define IDC_TEXTURE_QUALITY 1021 +#define IDC_SPIN_MAX_PLAYERS 1021 +#define IDC_TEXTURE_QUALITY_NORMAL 1022 +#define IDC_TEXTURE_QUALITY_HIGH 1023 +#define IDC_AUDIO_QUALITY_LOW 1024 +#define IDC_OBJECT_SHADOW_QUALITY 1024 +#define IDC_OBJECT_SHADOW_QUALITY_LOW 1025 +#define IDC_AUDIO_QUALITY_NORMAL 1025 +#define IDC_OBJECT_SHADOW_QUALITY_HIGH 1026 +#define IDC_AUDIO_QUALITY_HIGH 1026 +#define IDC_AVAILABLE_PLAYERS 1027 +#define IDC_AVAILABLE_CONTROLS 1028 +#define IDC_PLAYER_CREATE 1029 +#define IDC_EDIT_PLAYER_NAME 1030 +#define IDC_PLAYER_DELETE 1030 +#define IDC_WORLD_SHADOW_QUALITY 1030 +#define IDC_WORLD_SHADOW_QUALITY_NORMAL 1031 +#define IDC_EDIT_SECOND_CONTROL 1031 +#define IDC_PLAYER_CONTROLS 1031 +#define IDC_EDIT_CONTROLS 1031 +#define IDC_WORLD_SHADOW_QUALITY_HIGH 1032 +#define IDC_BUTTON_ACTIONS_LIST 1032 +#define IDC_PLAYER_APPEARANCE 1032 +#define IDC_COPY_PLAYER_CONTROLS 1033 +#define IDC_NEW_CONTROLS 1033 +#define IDC_PASTE_PLAYER_CONTROLS 1034 +#define IDC_DELETE_CONTROLS 1034 +#define IDC_CONTROLER_AXIS 1035 +#define IDC_RENAME_CONTROLS 1035 +#define IDC_INVERT_CONTROLER 1036 +#define IDC_RENAME_PLAYER 1036 +#define IDC_RELATIVE_ABSOLUTE_TYPE 1037 +#define IDC_ABSOLUTE_RADIO 1038 +#define IDC_CONTROLER_SENSITIVITY 1039 +#define IDC_EDIT_FIRST_CONTROL 1040 +#define IDC_AVAILABLE_APPEARANCES 1041 +#define IDC_SESSION_LIST 1042 +#define IDC_USE_DSOUND3D 1044 +#define IDC_AXIS_ACTIONS_LIST 1046 +#define IDC_PRESS_MESSAGE 1047 +#define IDC_CONTROLER_TYPE_T 1048 +#define IDC_CONTROLER_SENSITIVITY_T 1049 +#define IDC_DUMMY_LIST 1050 +#define IDC_AVAILABLE_PROVIDERS 1051 +#define IDC_CONSOLE_INPUT 1052 +#define IDC_CONSOLE_OUTPUT 1053 +#define IDC_BUTTON_ACTION_NAME 1054 +#define IDC_BUTTON_DOWN_COMMAND 1055 +#define IDC_BUTTON_UP_COMMAND 1056 +#define IDC_CONSOLE_SYMBOLS 1058 +#define IDC_EDIT_CONTROLS_NAME 1059 +#define IDC_COMBO_AVAILABLE_PLAYERS 1109 +#define IDC_COMBO_AVAILABLE_CONTROLS 1110 +#define ID_BUTTON_ACTION_EDIT 32772 +#define ID_BUTTON_ACTION_ADD 32773 +#define ID_BUTTON_ACTION_REMOVE 32774 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 147 +#define _APS_NEXT_COMMAND_VALUE 32776 +#define _APS_NEXT_CONTROL_VALUE 1060 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/Sources/GameMP/Camera.cpp b/Sources/GameMP/Camera.cpp new file mode 100644 index 0000000..0ea87fa --- /dev/null +++ b/Sources/GameMP/Camera.cpp @@ -0,0 +1,221 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "stdafx.h" +#include "Camera.h" + +class CCameraPos { +public: + TIME cp_tmTick; + FLOAT cp_fSpeed; + FLOAT3D cp_vPos; + ANGLE3D cp_aRot; + ANGLE cp_aFOV; +}; + +BOOL _bCameraOn=FALSE; +CTFileStream _strScript; +BOOL _bInitialized; +FLOAT _fStartTime; +CCameraPos _cp0; +CCameraPos _cp1; +CCameraPos _cp; + +// camera control +extern INDEX cam_bRecord = FALSE; +static INDEX cam_bMoveForward = FALSE; +static INDEX cam_bMoveBackward = FALSE; +static INDEX cam_bMoveLeft = FALSE; +static INDEX cam_bMoveRight = FALSE; +static INDEX cam_bMoveUp = FALSE; +static INDEX cam_bMoveDown = FALSE; +static INDEX cam_bTurnBankingLeft = FALSE; +static INDEX cam_bTurnBankingRight = FALSE; +static INDEX cam_bZoomIn = FALSE; +static INDEX cam_bZoomOut = FALSE; +static INDEX cam_bZoomDefault = FALSE; +static INDEX cam_bResetToPlayer = FALSE; +static INDEX cam_bSnapshot = FALSE; +static INDEX cam_fSpeed = 1.0f; + +// camera functions +void CAM_Init(void) +{ + _pShell->DeclareSymbol("user INDEX cam_bRecord;", &cam_bRecord); + _pShell->DeclareSymbol("user INDEX cam_bMoveForward;", &cam_bMoveForward); + _pShell->DeclareSymbol("user INDEX cam_bMoveBackward;", &cam_bMoveBackward); + _pShell->DeclareSymbol("user INDEX cam_bMoveLeft;", &cam_bMoveLeft); + _pShell->DeclareSymbol("user INDEX cam_bMoveRight;", &cam_bMoveRight); + _pShell->DeclareSymbol("user INDEX cam_bMoveUp;", &cam_bMoveUp); + _pShell->DeclareSymbol("user INDEX cam_bMoveDown;", &cam_bMoveDown); + _pShell->DeclareSymbol("user INDEX cam_bTurnBankingLeft;", &cam_bTurnBankingLeft); + _pShell->DeclareSymbol("user INDEX cam_bTurnBankingRight;", &cam_bTurnBankingRight); + _pShell->DeclareSymbol("user INDEX cam_bZoomIn;", &cam_bZoomIn); + _pShell->DeclareSymbol("user INDEX cam_bZoomOut;", &cam_bZoomOut); + _pShell->DeclareSymbol("user INDEX cam_bZoomDefault;", &cam_bZoomDefault); + _pShell->DeclareSymbol("user INDEX cam_bSnapshot;", &cam_bSnapshot); + _pShell->DeclareSymbol("user INDEX cam_bResetToPlayer;", &cam_bResetToPlayer); + _pShell->DeclareSymbol("user INDEX cam_fSpeed;", &cam_fSpeed); +} + +BOOL CAM_IsOn(void) +{ + return _bCameraOn; +} + +void ReadPos(CCameraPos &cp) +{ + try { + CTString strLine; + _strScript.GetLine_t(strLine); + strLine.ScanF("%g: %g: %g %g %g:%g %g %g:%g", + &cp.cp_tmTick, + &cp.cp_fSpeed, + &cp.cp_vPos(1), &cp.cp_vPos(2), &cp.cp_vPos(3), + &cp.cp_aRot(1), &cp.cp_aRot(2), &cp.cp_aRot(3), + &cp.cp_aFOV); + + } catch (char *strError) { + CPrintF("Camera: %s\n", strError); + } +} +void WritePos(CCameraPos &cp) +{ + try { + CTString strLine; + strLine.PrintF("%g: %g: %g %g %g:%g %g %g:%g", + _pTimer->GetLerpedCurrentTick()-_fStartTime, + 1.0f, + cp.cp_vPos(1), cp.cp_vPos(2), cp.cp_vPos(3), + cp.cp_aRot(1), cp.cp_aRot(2), cp.cp_aRot(3), + cp.cp_aFOV); + _strScript.PutLine_t(strLine); + + } catch (char *strError) { + CPrintF("Camera: %s\n", strError); + } +} +void SetSpeed(FLOAT fSpeed) +{ + CTString str; + str.PrintF("dem_fRealTimeFactor = %g;", fSpeed); + _pShell->Execute(str); +} + +void CAM_Start(const CTFileName &fnmDemo) +{ + _bCameraOn = FALSE; + CTFileName fnmScript = fnmDemo.NoExt()+".ini"; + if( cam_bRecord) { + try { + _strScript.Create_t(fnmScript); + } catch(char *strError) { + CPrintF("Camera: %s\n", strError); + return; + }; + _cp.cp_vPos = FLOAT3D(0,0,0); + _cp.cp_aRot = ANGLE3D(0,0,0); + _cp.cp_aFOV = 90.0f; + _cp.cp_fSpeed = 1; + _cp.cp_tmTick = 0.0f; + } else { + try { + _strScript.Open_t(fnmScript); + } catch(char *strError) { + (void)strError; + return; + }; + } + _bCameraOn = TRUE; + _bInitialized = FALSE; +} +void CAM_Stop(void) +{ + if (_bCameraOn) { + _strScript.Close(); + } + _bCameraOn = FALSE; +} + +void CAM_Render(CEntity *pen, CDrawPort *pdp) +{ + if( cam_bRecord) { + if (!_bInitialized) { + _bInitialized = TRUE; + SetSpeed(1.0f); + _fStartTime = _pTimer->CurrentTick(); + } + FLOATmatrix3D m; + MakeRotationMatrixFast(m, _cp.cp_aRot); + FLOAT3D vX, vY, vZ; + vX(1) = m(1,1); vX(2) = m(2,1); vX(3) = m(3,1); + vY(1) = m(1,2); vY(2) = m(2,2); vY(3) = m(3,2); + vZ(1) = m(1,3); vZ(2) = m(2,3); vZ(3) = m(3,3); + + _cp.cp_aRot(1)-=_pInput->GetAxisValue(MOUSE_X_AXIS)*0.5f; + _cp.cp_aRot(2)-=_pInput->GetAxisValue(MOUSE_Y_AXIS)*0.5f; + + if( cam_bMoveForward) { _cp.cp_vPos -= vZ *cam_fSpeed; }; + if( cam_bMoveBackward) { _cp.cp_vPos += vZ *cam_fSpeed; }; + if( cam_bMoveLeft) { _cp.cp_vPos -= vX *cam_fSpeed; }; + if( cam_bMoveRight) { _cp.cp_vPos += vX *cam_fSpeed; }; + if( cam_bMoveUp) { _cp.cp_vPos += vY *cam_fSpeed; }; + if( cam_bMoveDown) { _cp.cp_vPos -= vY *cam_fSpeed; }; + if( cam_bTurnBankingLeft) { _cp.cp_aRot(3) += 10.0f; }; + if( cam_bTurnBankingRight) { _cp.cp_aRot(3) -= 10.0f; }; + if( cam_bZoomIn) { _cp.cp_aFOV -= 1.0f; }; + if( cam_bZoomOut) { _cp.cp_aFOV += 1.0f; }; + if( cam_bZoomDefault) { _cp.cp_aFOV = 90.0f; }; + Clamp( _cp.cp_aFOV, 10.0f, 150.0f); + + if( cam_bResetToPlayer) { + _cp.cp_vPos = pen->GetPlacement().pl_PositionVector; + _cp.cp_aRot = pen->GetPlacement().pl_OrientationAngle; + } + + if( cam_bSnapshot) { + cam_bSnapshot = FALSE; + WritePos(_cp); + } + + } else { + if (!_bInitialized) { + _bInitialized = TRUE; + ReadPos(_cp0); + ReadPos(_cp1); + SetSpeed(_cp0.cp_fSpeed); + _fStartTime = _pTimer->CurrentTick(); + } + TIME tmNow = _pTimer->GetLerpedCurrentTick()-_fStartTime; + if (tmNow>_cp1.cp_tmTick) { + _cp0 = _cp1; + ReadPos(_cp1); + SetSpeed(_cp0.cp_fSpeed); + } + FLOAT fRatio = (tmNow-_cp0.cp_tmTick)/(_cp1.cp_tmTick-_cp0.cp_tmTick); + + _cp.cp_vPos = Lerp(_cp0.cp_vPos, _cp1.cp_vPos, fRatio); + _cp.cp_aRot = Lerp(_cp0.cp_aRot, _cp1.cp_aRot, fRatio); + _cp.cp_aFOV = Lerp(_cp0.cp_aFOV, _cp1.cp_aFOV, fRatio); + } + + CPlacement3D plCamera; + plCamera.pl_PositionVector = _cp.cp_vPos; + plCamera.pl_OrientationAngle = _cp.cp_aRot; + + // init projection parameters + CPerspectiveProjection3D prPerspectiveProjection; + prPerspectiveProjection.FOVL() = _cp.cp_aFOV; + prPerspectiveProjection.ScreenBBoxL() = FLOATaabbox2D( + FLOAT2D(0.0f, 0.0f), FLOAT2D((float)pdp->GetWidth(), (float)pdp->GetHeight()) + ); + prPerspectiveProjection.AspectRatioL() = 1.0f; + prPerspectiveProjection.FrontClipDistanceL() = 0.3f; + + CAnyProjection3D prProjection; + prProjection = prPerspectiveProjection; + + // set up viewer position + prProjection->ViewerPlacementL() = plCamera; + // render the view + RenderView(*pen->en_pwoWorld, *(CEntity*)NULL, prProjection, *pdp); +} diff --git a/Sources/GameMP/Camera.h b/Sources/GameMP/Camera.h new file mode 100644 index 0000000..5cc4a06 --- /dev/null +++ b/Sources/GameMP/Camera.h @@ -0,0 +1,7 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +void CAM_Init(void); +void CAM_Start(const CTFileName &fnmDemo); +void CAM_Stop(void); +BOOL CAM_IsOn(void); +void CAM_Render(CEntity *pen, CDrawPort *pdp); diff --git a/Sources/GameMP/CompMessage.cpp b/Sources/GameMP/CompMessage.cpp new file mode 100644 index 0000000..fabb6e6 --- /dev/null +++ b/Sources/GameMP/CompMessage.cpp @@ -0,0 +1,218 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdAfx.h" + +#include "CompMessage.h" +extern CTString _strStatsDetails; + +CCompMessage::CCompMessage(void) +{ + Clear(); +} +void CCompMessage::Clear(void) +{ + UnprepareMessage(); + cm_fnmFileName.Clear(); + cm_pcmiOriginal = NULL; + cm_bRead = FALSE; +} + +// constructs message with a filename +void CCompMessage::SetMessage(CCompMessageID *pcmi) +{ + cm_fnmFileName = pcmi->cmi_fnmFileName; + cm_bRead = pcmi->cmi_bRead; + cm_pcmiOriginal = pcmi; +} + +// load a message from file +void CCompMessage::Load_t(void) +{ + // if already loaded + if (cm_bLoaded) { + // do nothing + return; + } + // open file + CTFileStream strm; + strm.Open_t(cm_fnmFileName); + // read subject line + strm.ExpectKeyword_t("SUBJECT\r\n"); + strm.GetLine_t(cm_strSubject); + // rea image type + strm.ExpectKeyword_t("IMAGE\r\n"); + CTString strImage; + strm.GetLine_t(strImage); + if (strImage=="none") { + cm_itImage = IT_NONE; + } else if (strImage=="statistics") { + cm_itImage = IT_STATISTICS; + } else if (strImage=="picture") { + cm_itImage = IT_PICTURE; + cm_fnmPicture.ReadFromText_t(strm); + } else if (strImage=="model") { + cm_itImage = IT_MODEL; + cm_strModel.ReadFromText_t(strm, ""); + } else { + throw TRANS("Unknown image type!"); + } + // read text until end of file + strm.ExpectKeyword_t("TEXT\r\n"); + cm_strText.ReadUntilEOF_t(strm); + cm_ctFormattedWidth = 0; + cm_ctFormattedLines = 0; + cm_strFormattedText = ""; + cm_bLoaded = TRUE; +} + +// format message for given line width +void CCompMessage::Format(INDEX ctCharsPerLine) +{ + // if already formatted in needed size + if (cm_ctFormattedWidth == ctCharsPerLine) { + // do nothing + return; + } + // remember width + cm_ctFormattedWidth = ctCharsPerLine; + + // get text + const char *strText = cm_strText; + if (strncmp(strText, "$STAT", 5)==0) { + strText = _strStatsDetails; + cm_strFormattedText = strText; + cm_ctFormattedLines = 1; + for (INDEX i=0; ictCharsPerLine) { + // start backtracking + const char *pchSrcBck = pchSrc-1; + char *pchDstBck = pchDst-1; + // while not start of row and not space + while (pchSrcBck>pchSrc-ctChars && *pchSrcBck!=' ') { + // go one char back + pchSrcBck--; + pchDstBck--; + } + // if start of row hit (cannot word-wrap) + if (pchSrcBckcmi_bRead = TRUE; +} + +// get one formatted line +CTString CCompMessage::GetLine(INDEX iLine) +{ + const char *strText = cm_strFormattedText; + // find first line + INDEX i = 0; + while (iAddAttachmentModel(iPosition); + ASSERT(pamo!=NULL); + pamo->amo_moModelObject.SetData_t(fnmModel); + pamo->amo_moModelObject.PlayAnim(iAnim, AOF_LOOPING); + pamo->amo_moModelObject.mo_toTexture.SetData_t(fnmTexture); + pamo->amo_moModelObject.mo_toReflection.SetData_t(fnmReflection); + pamo->amo_moModelObject.mo_toSpecular.SetData_t(fnmSpecular); + return &pamo->amo_moModelObject; +} + +extern void SetupCompModel_t(const CTString &strName) +{ + CModelObject *pmo = &_moModel; + _aRotation = ANGLE3D(0,0,0); + _bHasFloor = FALSE; + _fFloorY = 0.0f; + _fFOV = 90.0f; + _vLightDir = FLOAT3D( -0.2f, -0.2f, -0.2f); + _colLight = C_GRAY; + _colAmbient = C_vdGRAY; + _iParticleType = PARTICLES_NONE; + _moFloor.SetData_t(CTFILENAME("ModelsMP\\Computer\\Floor.mdl")); + _moFloor.mo_toTexture.SetData_t(CTFILENAME("Models\\Computer\\Floor.tex")); + pmo->mo_colBlendColor = 0xFFFFFFFF; + if (strName=="Rocketman") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Headman\\Headman.mdl")); + pmo->PlayAnim(HEADMAN_ANIM_COMPUTERKAMIKAZE, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Headman\\Rocketman.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-1.0,-1.75), ANGLE3D(210,0,0)); + + AddAttachment_t(pmo, HEADMAN_ATTACHMENT_HEAD, + CTFILENAME("Models\\Enemies\\Headman\\Head.mdl"), 0, + CTFILENAME("Models\\Enemies\\Headman\\Head.tex")); + AddAttachment_t(pmo, HEADMAN_ATTACHMENT_ROCKET_LAUNCHER, + CTFILENAME("Models\\Enemies\\Headman\\RocketLauncher.mdl"), 0, + CTFILENAME("Models\\Enemies\\Headman\\RocketLauncher.tex")); + pmo->StretchModel(FLOAT3D(1.25f,1.25f,1.25f)); + _bHasFloor = TRUE; + + } else if (strName=="Firecracker") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Headman\\Headman.mdl")); + pmo->PlayAnim(HEADMAN_ANIM_COMPUTERKAMIKAZE, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Headman\\Firecracker.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-1.0,-1.75), ANGLE3D(210,0,0)); + + AddAttachment_t(pmo, HEADMAN_ATTACHMENT_HEAD, + CTFILENAME("Models\\Enemies\\Headman\\FirecrackerHead.mdl"), 0, + CTFILENAME("Models\\Enemies\\Headman\\FirecrackerHead.tex")); + AddAttachment_t(pmo, HEADMAN_ATTACHMENT_CHAINSAW, + CTFILENAME("Models\\Enemies\\Headman\\Chainsaw.mdl"), 0, + CTFILENAME("Models\\Enemies\\Headman\\Chainsaw.tex")); + pmo->StretchModel(FLOAT3D(1.25f,1.25f,1.25f)); + _bHasFloor = TRUE; + + } else if (strName=="Bomberman") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Headman\\Headman.mdl")); + pmo->PlayAnim(HEADMAN_ANIM_COMPUTERKAMIKAZE, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Headman\\Bomberman.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-1.0,-1.75), ANGLE3D(210,0,0)); + + AddAttachment_t(pmo, HEADMAN_ATTACHMENT_HEAD, + CTFILENAME("Models\\Enemies\\Headman\\Head.mdl"), 0, + CTFILENAME("Models\\Enemies\\Headman\\Head.tex")); + pmo->StretchModel(FLOAT3D(1.25f,1.25f,1.25f)); + _bHasFloor = TRUE; + + } else if (strName=="Kamikaze") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Headman\\Headman.mdl")); + pmo->PlayAnim(HEADMAN_ANIM_COMPUTERKAMIKAZE, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Headman\\Kamikaze.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-1.0,-1.75), ANGLE3D(210,0,0)); + + AddAttachment_t(pmo, HEADMAN_ATTACHMENT_BOMB_RIGHT_HAND, + CTFILENAME("Models\\Enemies\\Headman\\Projectile\\Bomb.mdl"), 0, + CTFILENAME("Models\\Enemies\\Headman\\Projectile\\Bomb.tex")); + AddAttachment_t(pmo, HEADMAN_ATTACHMENT_BOMB_LEFT_HAND, + CTFILENAME("Models\\Enemies\\Headman\\Projectile\\Bomb.mdl"), 0, + CTFILENAME("Models\\Enemies\\Headman\\Projectile\\Bomb.tex")); + pmo->StretchModel(FLOAT3D(1.25f,1.25f,1.25f)); + _bHasFloor = TRUE; + + } else if (strName=="EyemanPurple") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Eyeman\\Eyeman.mdl")); + pmo->PlayAnim(EYEMAN_ANIM_WALK, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Eyeman\\Eyeman4.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-0.9f,-1.5), ANGLE3D(210,0,0)); + pmo->StretchModel(FLOAT3D(1,1,1)); + _bHasFloor = TRUE; + + } else if (strName=="EyemanGreen") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Eyeman\\Eyeman.mdl")); + pmo->PlayAnim(EYEMAN_ANIM_WALK, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Eyeman\\Eyeman5.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-1.2f,-2.0), ANGLE3D(210,0,0)); + pmo->StretchModel(FLOAT3D(1.3f, 1.3f, 1.3f)); + _bHasFloor = TRUE; + + } else if (strName=="Boneman") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Boneman\\Boneman.mdl")); + pmo->PlayAnim(BONEMAN_ANIM_WALKCOMPUTER, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Boneman\\Boneman.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-1.0f,-3.0), ANGLE3D(210,0,0)); + pmo->StretchModel(FLOAT3D(1,1,1)); + _bHasFloor = TRUE; + + } else if (strName=="Bull") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Werebull\\Werebull.mdl")); + pmo->PlayAnim(WEREBULL_ANIM_WALK, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Werebull\\Werebull.tex")); + _plModel = CPlacement3D(FLOAT3D(0.0f,-1.5f,-4.0), ANGLE3D(-110,0,0)); + pmo->StretchModel(FLOAT3D(1,1,1)); + _bHasFloor = TRUE; + + } else if (strName=="ScorpmanSoldier") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Scorpman\\Scorpman.mdl")); + pmo->mo_toSpecular.SetData_t(CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + pmo->PlayAnim(SCORPMAN_ANIM_WALK, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Scorpman\\Soldier.tex")); +// _plModel = CPlacement3D(FLOAT3D(0+0.2f*2,-2,-13), ANGLE3D(150,0,0)); +// _fFOV = 30; + _plModel = CPlacement3D(FLOAT3D(0+0.5f*3,-3.0f,-7.0)*2/3, ANGLE3D(135,0,0)); + _vLightDir = FLOAT3D( 0.2f, -0.2f, -0.2f); + _colLight = C_lGRAY; + _colAmbient = C_vdGRAY; + + AddAttachment_t(pmo, SCORPMAN_ATTACHMENT_MINIGUN, + CTFILENAME("Models\\Enemies\\Scorpman\\Gun.mdl"), 0, + CTFILENAME("Models\\Enemies\\Scorpman\\Gun.tex")); + + pmo->StretchModel(FLOAT3D(2.0f,2.0f,2.0f)); + _bHasFloor = TRUE; + + } else if (strName=="ScorpmanGeneral") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Scorpman\\Scorpman.mdl")); + pmo->PlayAnim(SCORPMAN_ANIM_WALK, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Scorpman\\General.tex")); + pmo->mo_toSpecular.SetData_t(CTFILENAME("Models\\SpecularTextures\\Medium.tex")); +// _plModel = CPlacement3D(FLOAT3D(0+0.2f*3,-4,-19), ANGLE3D(150,0,0)); +// _fFOV = 30; + _plModel = CPlacement3D(FLOAT3D(0+0.5f*3,-3.0f,-7.0), ANGLE3D(135,0,0)); + _vLightDir = FLOAT3D( 0.2f, -0.2f, -0.2f); + _colLight = C_lGRAY; + _colAmbient = C_vdGRAY; + + AddAttachment_t(pmo, SCORPMAN_ATTACHMENT_MINIGUN, + CTFILENAME("Models\\Enemies\\Scorpman\\Gun.mdl"), 0, + CTFILENAME("Models\\Enemies\\Scorpman\\Gun.tex")); + + pmo->StretchModel(FLOAT3D(3.0f,3.0f,3.0f)); + _bHasFloor = TRUE; + + } else if (strName=="WalkerSmall") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Walker\\Walker.mdl")); + pmo->PlayAnim(WALKER_ANIM_WALKBIG, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Walker\\Walker02.tex")); + AddAttachment_t(pmo, WALKER_ATTACHMENT_ROCKETLAUNCHER_LT, + CTFILENAME("Models\\Enemies\\Walker\\RocketLauncher.mdl"), 0, + CTFILENAME("Models\\Enemies\\Walker\\RocketLauncher.tex"), + CTFILENAME(""), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, WALKER_ATTACHMENT_ROCKETLAUNCHER_RT, + CTFILENAME("Models\\Enemies\\Walker\\RocketLauncher.mdl"), 0, + CTFILENAME("Models\\Enemies\\Walker\\RocketLauncher.tex"), + CTFILENAME(""), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-2.0f,-5.0), ANGLE3D(210,0,0)); + pmo->StretchModel(FLOAT3D(0.5,0.5,0.5)); + _bHasFloor = TRUE; + _colLight = C_lGRAY; + _colAmbient = C_vdGRAY; + + } else if (strName=="WalkerBig") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Walker\\Walker.mdl")); + pmo->PlayAnim(WALKER_ANIM_WALKBIG, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Walker\\Walker01.tex")); + AddAttachment_t(pmo, WALKER_ATTACHMENT_ROCKETLAUNCHER_LT, + CTFILENAME("Models\\Enemies\\Walker\\RocketLauncher.mdl"), 0, + CTFILENAME("Models\\Enemies\\Walker\\RocketLauncher.tex"), + CTFILENAME(""), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, WALKER_ATTACHMENT_ROCKETLAUNCHER_RT, + CTFILENAME("Models\\Enemies\\Walker\\RocketLauncher.mdl"), 0, + CTFILENAME("Models\\Enemies\\Walker\\RocketLauncher.tex"), + CTFILENAME(""), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-4.0f,-10.0), ANGLE3D(210,0,0)); + pmo->StretchModel(FLOAT3D(1,1,1)); + _bHasFloor = TRUE; + + } else if (strName=="Woman") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Woman\\Woman.mdl")); + pmo->PlayAnim(WOMAN_ANIM_AIRSTAND, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Woman\\Woman.tex")); + _plModel = CPlacement3D(FLOAT3D(0,0.0f,-2.0), ANGLE3D(210,30,0)); + pmo->StretchModel(FLOAT3D(1,1,1)); + _bHasFloor = TRUE; + _fFloorY = -1.5f; + + } else if (strName=="Gizmo") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Gizmo\\Gizmo.mdl")); + pmo->PlayAnim(GIZMO_ANIM_IDLE, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Gizmo\\Gizmo.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-0.5f,-1.2f), ANGLE3D(150,0,0)); + pmo->StretchModel(FLOAT3D(1,1,1)); + _fFloorY = 0.0f; + _bHasFloor = TRUE; + + } else if (strName=="Fish") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Fish\\Fish.mdl")); + pmo->PlayAnim(FISH_ANIM_IDLE, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Fish\\Fish1.tex")); + pmo->mo_toSpecular.SetData_t(CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + _plModel = CPlacement3D(FLOAT3D(-0.2f,-0.5f,-3.0), ANGLE3D(250,0,0)); + pmo->StretchModel(FLOAT3D(1,1,1)); + _bHasFloor = TRUE; + _fFloorY = -1.0f; + + } else if (strName=="BeastNormal") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Beast\\Beast.mdl")); + pmo->PlayAnim(BEAST_ANIM_IDLECOMPUTER, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Beast\\Beast.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-2.0f,-6.0), ANGLE3D(170,0,0)); + pmo->StretchModel(FLOAT3D(2,2,2)); + _bHasFloor = TRUE; + + } else if (strName=="BeastBig") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Beast\\Beast.mdl")); + pmo->PlayAnim(BEAST_ANIM_IDLECOMPUTER, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Beast\\BeastBig.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-6.5f,-18.0), ANGLE3D(170,0,0)); + + //_plModel = CPlacement3D(FLOAT3D(tmp_af[5],tmp_af[6],tmp_af[7]), ANGLE3D(tmp_af[8],0,0)); + //_fFOV = tmp_af[9]; + //CPrintF("%f %f %f : %f : %f\n", tmp_af[5],tmp_af[6],tmp_af[7], tmp_af[8], tmp_af[9]); + + pmo->StretchModel(FLOAT3D(6,6,6)); + _bHasFloor = TRUE; + + } else if (strName=="ElementalLava") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\ElementalLava\\ElementalLava.mdl")); + pmo->PlayAnim(ELEMENTALLAVA_ANIM_WALKCOMPUTER, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\ElementalLava\\Lava04Fx.tex")); + pmo->mo_toBump.SetData_t(CTFILENAME("Models\\Enemies\\ElementalLava\\Detail.tex")); + AddAttachment_t(pmo, ELEMENTALLAVA_ATTACHMENT_BODY_FLARE, + CTFILENAME("Models\\Enemies\\ElementalLava\\BodyFlare.mdl"), 0, + CTFILENAME("Models\\Enemies\\ElementalLava\\Flare.tex")); + AddAttachment_t(pmo, ELEMENTALLAVA_ATTACHMENT_RIGHT_HAND_FLARE, + CTFILENAME("Models\\Enemies\\ElementalLava\\HandFlare.mdl"), 0, + CTFILENAME("Models\\Enemies\\ElementalLava\\Flare.tex")); + AddAttachment_t(pmo, ELEMENTALLAVA_ATTACHMENT_LEFT_HAND_FLARE, + CTFILENAME("Models\\Enemies\\ElementalLava\\HandFlare.mdl"), 0, + CTFILENAME("Models\\Enemies\\ElementalLava\\Flare.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-5.0f,-8.0), ANGLE3D(150,0,0)); + pmo->StretchModel(FLOAT3D(4,4,4)); + _bHasFloor = TRUE; + + _iParticleType = PARTICLES_LAVA_ELEMENTAL; + + } else if (strName=="Devil") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Devil\\Devil.mdl")); + pmo->PlayAnim(DEVIL_ANIM_WALK, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Enemies\\Devil\\Devil.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-12.0f,-25.0), ANGLE3D(150,0,0)); + pmo->StretchModel(FLOAT3D(12,12,12)); + _bHasFloor = TRUE; + + } else if (strName=="Guffy") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Enemies\\Guffy\\Guffy.mdl")); + pmo->PlayAnim(GUFFY_ANIM_IDLE, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Enemies\\Guffy\\Guffy.tex")); + AddAttachment_t(pmo, GUFFY_ATTACHMENT_GUNRIGHT, + CTFILENAME("ModelsMP\\Enemies\\Guffy\\Gun.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\Guffy\\Gun.tex")); + AddAttachment_t(pmo, GUFFY_ATTACHMENT_GUNLEFT, + CTFILENAME("ModelsMP\\Enemies\\Guffy\\Gun.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\Guffy\\Gun.tex")); + CModelObject *pmoRight = &pmo->GetAttachmentModel(GUFFY_ATTACHMENT_GUNRIGHT)->amo_moModelObject; + pmoRight->StretchModel(FLOAT3D(-1,1,1)); + _plModel = CPlacement3D(FLOAT3D(0.0f,-2.0f,-5.75f), ANGLE3D(210,0,0)); + _fFOV = 70.0f; + + _vLightDir = FLOAT3D( -0.1f, -0.1f, -0.175f); + + //_plModel = CPlacement3D(FLOAT3D(tmp_af[5],tmp_af[6],tmp_af[7]), ANGLE3D(tmp_af[8],0,0)); + //_fFOV = tmp_af[9]; + //CPrintF("%f %f %f : %f : %f\n", tmp_af[5],tmp_af[6],tmp_af[7], tmp_af[8], tmp_af[9]); + + + pmo->StretchModel(FLOAT3D(1.5f, 1.5f, 1.5f)); + _bHasFloor = TRUE; + + } else if (strName=="GruntSoldier") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Enemies\\Grunt\\Grunt.mdl")); + pmo->PlayAnim(GRUNT_ANIM_IDLEPATROL, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Enemies\\Grunt\\Soldier.tex")); + AddAttachment_t(pmo, GRUNT_ATTACHMENT_GUN_SMALL, + CTFILENAME("ModelsMP\\Enemies\\Grunt\\Gun.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\Grunt\\Gun.tex")); + _plModel = CPlacement3D(FLOAT3D(0.0f,-1.5f,-3.7f), ANGLE3D(165.0f,0.0f,0.0f)); + _fFOV = 70.0f; + + _vLightDir = FLOAT3D( -0.1f, -0.2f, -0.2f); + //_vLightDir = FLOAT3D( tmp_af[2], tmp_af[3], tmp_af[4]); + + pmo->StretchModel(FLOAT3D(1.2f, 1.2f, 1.2f)); + _fFloorY = 0.0f; + _bHasFloor = TRUE; + + } else if (strName=="GruntCommander") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Enemies\\Grunt\\Grunt.mdl")); + pmo->PlayAnim(GRUNT_ANIM_IDLEPATROL, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Enemies\\Grunt\\Commander.tex")); + AddAttachment_t(pmo, GRUNT_ATTACHMENT_GUN_COMMANDER, + CTFILENAME("ModelsMP\\Enemies\\Grunt\\Gun_Commander.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\Grunt\\Gun_Commander.tex")); + _plModel = CPlacement3D(FLOAT3D(0.0f,-1.65f,-3.9f), ANGLE3D(165.0f,0.0f,0.0f)); + _fFOV = 70.0f; + + _vLightDir = FLOAT3D( -0.1f, -0.2f, -0.2f); + + pmo->StretchModel(FLOAT3D(1.4f, 1.4f, 1.4f)); + _fFloorY = 0.0f; + _bHasFloor = TRUE; + + } else if (strName=="Demon") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Enemies\\Demon\\Demon.mdl")); + pmo->PlayAnim(DEMON_ANIM_IDLE, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Enemies\\Demon\\Demon.tex")); + _plModel = CPlacement3D(FLOAT3D(0.0f, -1.25f, -2.25f), ANGLE3D(160.0f, 0.0f, 0.0f)); + + pmo->StretchModel(FLOAT3D(1.4f, 1.4f, 1.4f)); + _fFloorY = 0.0f; + _bHasFloor = TRUE; + + } else if (strName=="Chainsaw Freak") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Enemies\\ChainsawFreak\\Freak.mdl")); + pmo->PlayAnim(FREAK_ANIM_IDLE, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Enemies\\ChainsawFreak\\Freak.tex")); + AddAttachment_t(pmo, FREAK_ATTACHMENT_CHAINSAW, + CTFILENAME("ModelsMP\\Enemies\\ChainsawFreak\\Saw.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\ChainsawFreak\\Saw.tex")); + + _plModel = CPlacement3D(FLOAT3D(-0.25f, -2.0f, -3.75f), ANGLE3D(200.0f, 0.0f, 0.0f)); + + pmo->StretchModel(FLOAT3D(1.4f, 1.4f, 1.4f)); + _fFloorY = 0.0f; + _bHasFloor = TRUE; + + } else if (strName=="Cannon Static") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Enemies\\CannonStatic\\Turret.mdl")); + pmo->PlayAnim(TURRET_ANIM_DEFAULT, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Enemies\\CannonStatic\\Turret.tex")); + AddAttachment_t(pmo, TURRET_ATTACHMENT_CANNON, + CTFILENAME("ModelsMP\\Enemies\\CannonStatic\\Cannon.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\CannonStatic\\Cannon.tex")); + CAttachmentModelObject *pmoMuzzle = pmo->GetAttachmentModel(TURRET_ATTACHMENT_CANNON); + pmoMuzzle->amo_plRelative.pl_OrientationAngle(2) = 10.0f; + + _plModel = CPlacement3D(FLOAT3D(0.4f, -1.0f, -2.75), ANGLE3D(125.0f, 0.0f, 0.0f)); + + pmo->StretchModel(FLOAT3D(1.4f, 1.4f, 1.4f)); + _fFloorY = 0.0f; + _bHasFloor = TRUE; + + } else if (strName=="Cannon Rotating") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Enemies\\CannonRotating\\Turret.mdl")); + pmo->PlayAnim(TURRET_ANIM_DEFAULT, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Enemies\\CannonRotating\\Turret.tex")); + AddAttachment_t(pmo, TURRET_ATTACHMENT_ROTATORHEADING, + CTFILENAME("ModelsMP\\Enemies\\CannonRotating\\RotatingMechanism.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\CannonRotating\\RotatingMechanism.tex")); + CModelObject *pmoRotator = &pmo->GetAttachmentModel(TURRET_ATTACHMENT_ROTATORHEADING)->amo_moModelObject; + AddAttachment_t(pmoRotator, ROTATINGMECHANISM_ATTACHMENT_CANNON, + CTFILENAME("ModelsMP\\Enemies\\CannonStatic\\Cannon.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\CannonStatic\\Cannon.tex")); + CAttachmentModelObject *pmoMuzzle = pmoRotator->GetAttachmentModel(ROTATINGMECHANISM_ATTACHMENT_CANNON); + pmoMuzzle->amo_plRelative.pl_OrientationAngle(2) = 10.0f; + + _plModel = CPlacement3D(FLOAT3D(0.4f, -1.0f, -2.75f), ANGLE3D(125.0f, 0.0f, 0.0f)); + + pmo->StretchModel(FLOAT3D(1.4f, 1.4f, 1.4f)); + _fFloorY = 0.0f; + _bHasFloor = TRUE; + + } else if (strName=="Summoner") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Enemies\\Summoner\\Summoner.mdl")); + pmo->PlayAnim(SUMMONER_ANIM_IDLE, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Enemies\\Summoner\\Summoner.tex")); + pmo->mo_toBump.SetData_t(CTFILENAME("TexturesMP\\Detail\\Crumples04.tex")); + AddAttachment_t(pmo, SUMMONER_ATTACHMENT_STAFF, + CTFILENAME("ModelsMP\\Enemies\\Summoner\\Staff.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\Summoner\\Staff.tex")); + + _plModel = CPlacement3D(FLOAT3D(0.25f, -7.0f, -31.0f), ANGLE3D(160.0f, 0.0f, 0.0f)); + _fFOV = 50.0f; + _vLightDir = FLOAT3D( 0.1f, -0.3f, -0.2f); + + pmo->StretchModel(FLOAT3D(7.0f, 7.0f, 7.0f)); + _fFloorY = 0.0f; + _bHasFloor = TRUE; + + } else if (strName=="Exotech Larva") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Body.mdl")); + pmo->PlayAnim(BODY_ANIM_IDLECOMPUTER, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Body.tex")); + pmo->StretchModel(FLOAT3D(1.0f, 1.0f, 1.0f)); + CModelObject *pmoAtt; + // left side + AddAttachment_t(pmo, BODY_ATTACHMENT_ARM_LEFT, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Arm.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Arm.tex")); + pmoAtt = &pmo->GetAttachmentModel(BODY_ATTACHMENT_ARM_LEFT)->amo_moModelObject; + AddAttachment_t(pmoAtt, ARM_ATTACHMENT_PLASMAGUN, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.tex")); + // right side + AddAttachment_t(pmo, BODY_ATTACHMENT_ARM_RIGHT, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Arm.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Arm.tex")); + pmoAtt = &pmo->GetAttachmentModel(BODY_ATTACHMENT_ARM_RIGHT)->amo_moModelObject; + pmoAtt->StretchModel(FLOAT3D(-1,1,1)); + AddAttachment_t(pmoAtt, ARM_ATTACHMENT_PLASMAGUN, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Weapons\\PlasmaGun.tex")); + CModelObject *pmoAtt2; + pmoAtt2 = &pmoAtt->GetAttachmentModel(ARM_ATTACHMENT_PLASMAGUN)->amo_moModelObject; + pmoAtt2->StretchModel(FLOAT3D(-1,1,1)); + // blades + AddAttachment_t(pmo, BODY_ATTACHMENT_BACKARMS, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\BackArms.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Body.tex")); + CModelObject *pmoAtt3; + pmoAtt3 = &pmo->GetAttachmentModel(BODY_ATTACHMENT_BACKARMS)->amo_moModelObject; + pmoAtt3->PlayAnim(BACKARMS_ANIM_ACTIVE, AOF_LOOPING); + // holder + AddAttachment_t(pmo, BODY_ATTACHMENT_EXOTECHLARVA, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\ExotechLarva.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\ExotechLarva.tex")); + pmoAtt = &pmo->GetAttachmentModel(BODY_ATTACHMENT_EXOTECHLARVA)->amo_moModelObject; + AddAttachment_t(pmoAtt, EXOTECHLARVA_ATTACHMENT_BEAM, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\Beam.mdl"), 0, + CTFILENAME("ModelsMP\\Effects\\Laser\\Laser.tex")); + AddAttachment_t(pmoAtt, EXOTECHLARVA_ATTACHMENT_ENERGYBEAMS, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\EnergyBeams.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\EnergyBeams.tex")); + AddAttachment_t(pmoAtt, EXOTECHLARVA_ATTACHMENT_FLARE, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\EffectFlare.mdl"), 0, + CTFILENAME("ModelsMP\\Enemies\\ExotechLarva\\EffectFlare.tex")); + + _plModel = CPlacement3D(FLOAT3D(0.5f, -8.0f, -21.0f), ANGLE3D(165.0f, 0.0f, 0.0f)); + _fFOV = 70.0f; + + _aRotation = ANGLE3D( 10.0f, 0, 0 ); + _vLightDir = FLOAT3D( -0.1f, -0.2f, -0.2f); + + pmo->StretchModelRelative(FLOAT3D(2.5f, 2.5f, 2.5f)); + //pmo->StretchModel(FLOAT3D(2.5f, 2.5f, 2.5f)); + _fFloorY = -2.0f; + _bHasFloor = TRUE; + + } else if (strName=="Air Elemental") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Enemies\\AirElemental\\Elemental.mdl")); + pmo->PlayAnim(ELEMENTAL_ANIM_IDLE, AOF_LOOPING); + pmo->mo_colBlendColor = 0; + + _plModel = CPlacement3D(FLOAT3D(-1.0f, -13.0f, -52.0f), ANGLE3D(170.0f, 0.0f, 0.0f)); + _fFOV = 50.0f; + + //_plModel = CPlacement3D(FLOAT3D(tmp_af[5],tmp_af[6],tmp_af[7]), ANGLE3D(tmp_af[8],0,0)); + //_fFOV = tmp_af[9]; + //CPrintF("%f %f %f : %f : %f\n", tmp_af[5],tmp_af[6],tmp_af[7], tmp_af[8], tmp_af[9]); + //_vLightDir = FLOAT3D( tmp_af[2], tmp_af[3], tmp_af[4]); + + pmo->StretchModel(FLOAT3D(14.0f, 14.0f, 14.0f)); + _fFloorY = -2.0f; + _bHasFloor = TRUE; + + _iParticleType = PARTICLES_AIR_ELEMENTAL; + + } else if (strName=="BeastHuge") { + pmo->SetData_t(CTFILENAME("Models\\Enemies\\Beast\\Beast.mdl")); + pmo->PlayAnim(BEAST_ANIM_IDLECOMPUTER, AOF_LOOPING); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Enemies\\Beast\\BeastBiggest.tex")); + + _plModel = CPlacement3D(FLOAT3D(-0.5f, -12.0f, -30.0f), ANGLE3D(170.0f, 0.0f, 0.0f)); + _vLightDir = FLOAT3D( -0.1f, -0.3f, -0.2f); + + pmo->StretchModel(FLOAT3D(11.0f, 11.0f, 11.0f)); + _fFloorY = 0.0f; + _bHasFloor = TRUE; + + } else if (strName=="Knife") { + pmo->SetData_t(CTFILENAME("Models\\Weapons\\Knife\\KnifeItem.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Weapons\\Knife\\KnifeItem.tex")); + pmo->PlayAnim(KNIFEITEM_ANIM_COMPUTER, AOF_LOOPING); + _plModel = CPlacement3D(FLOAT3D(0,-0.5f,-2.0), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + + pmo->StretchModel(FLOAT3D(4,4,4)); + _bHasFloor = TRUE; + _fFloorY = -1.0f; + + } else if (strName=="Colt") { + pmo->SetData_t(CTFILENAME("Models\\Weapons\\Colt\\ColtItem.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Weapons\\Colt\\ColtMain.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-0.5f,-2.0), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + + AddAttachment_t(pmo, COLTITEM_ATTACHMENT_BULLETS, + CTFILENAME("Models\\Weapons\\Colt\\ColtBullets.mdl"), 0, + CTFILENAME("Models\\Weapons\\Colt\\ColtBullets.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightBlueMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, COLTITEM_ATTACHMENT_COCK, + CTFILENAME("Models\\Weapons\\Colt\\ColtCock.mdl"), 0, + CTFILENAME("Models\\Weapons\\Colt\\ColtCock.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightBlueMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, COLTITEM_ATTACHMENT_BODY, + CTFILENAME("Models\\Weapons\\Colt\\ColtMain.mdl"), 0, + CTFILENAME("Models\\Weapons\\Colt\\ColtMain.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightBlueMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + pmo->StretchModel(FLOAT3D(4,4,4)); + _bHasFloor = TRUE; + _fFloorY = -1.0f; + + } else if (strName=="SingleShotgun") { + pmo->SetData_t(CTFILENAME("Models\\Weapons\\SingleShotgun\\SingleShotgunItem.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Weapons\\SingleShotgun\\Handle.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-0.5f,-3.0), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + + AddAttachment_t(pmo, SINGLESHOTGUNITEM_ATTACHMENT_BARRELS, + CTFILENAME("Models\\Weapons\\SingleShotgun\\Barrels.mdl"), 0, + CTFILENAME("Models\\Weapons\\SingleShotgun\\Barrels.tex"), + CTFILENAME("Models\\ReflectionTextures\\DarkMetal.tex"), + CTFILENAME("Models\\SpecularTextures\\Weak.tex")); + AddAttachment_t(pmo, SINGLESHOTGUNITEM_ATTACHMENT_HANDLE, + CTFILENAME("Models\\Weapons\\SingleShotgun\\Handle.mdl"), 0, + CTFILENAME("Models\\Weapons\\SingleShotgun\\Handle.tex"), + CTFILENAME("Models\\ReflectionTextures\\DarkMetal.tex"), + CTFILENAME("Models\\SpecularTextures\\Weak.tex")); + AddAttachment_t(pmo, SINGLESHOTGUNITEM_ATTACHMENT_SLIDER, + CTFILENAME("Models\\Weapons\\SingleShotgun\\Slider.mdl"), 0, + CTFILENAME("Models\\Weapons\\SingleShotgun\\Barrels.tex"), + CTFILENAME("Models\\ReflectionTextures\\DarkMetal.tex"), + CTFILENAME("Models\\SpecularTextures\\Weak.tex")); + pmo->StretchModel(FLOAT3D(3.5,3.5,3.5)); + _bHasFloor = TRUE; + _fFloorY = -1.0f; + + } else if (strName=="DoubleShotgun") { + pmo->SetData_t(CTFILENAME("Models\\Weapons\\DoubleShotgun\\DoubleShotgunItem.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Weapons\\DoubleShotgun\\Handle.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-0.5f,-4.0), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + + AddAttachment_t(pmo, DOUBLESHOTGUNITEM_ATTACHMENT_BARRELS, + CTFILENAME("Models\\Weapons\\DoubleShotgun\\DshotgunBarrels.mdl"), 0, + CTFILENAME("Models\\Weapons\\DoubleShotgun\\Barrels.tex"), + CTFILENAME("Models\\ReflectionTextures\\BWRiples01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, DOUBLESHOTGUNITEM_ATTACHMENT_HANDLE, + CTFILENAME("Models\\Weapons\\DoubleShotgun\\DshotgunHandle.mdl"), 0, + CTFILENAME("Models\\Weapons\\DoubleShotgun\\Handle.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, DOUBLESHOTGUNITEM_ATTACHMENT_SWITCH, + CTFILENAME("Models\\Weapons\\DoubleShotgun\\Switch.mdl"), 0, + CTFILENAME("Models\\Weapons\\DoubleShotgun\\Switch.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + pmo->StretchModel(FLOAT3D(3.0,3.0,3.0)); + _bHasFloor = TRUE; + _fFloorY = -1.0f; + + } else if (strName=="Tommygun") { + pmo->SetData_t(CTFILENAME("Models\\Weapons\\Tommygun\\TommygunItem.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Weapons\\Tommygun\\Body.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-0.8f,-1.8f), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + + AddAttachment_t(pmo, TOMMYGUNITEM_ATTACHMENT_BODY, + CTFILENAME("Models\\Weapons\\Tommygun\\Body.mdl"), 0, + CTFILENAME("Models\\Weapons\\Tommygun\\Body.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, TOMMYGUNITEM_ATTACHMENT_SLIDER, + CTFILENAME("Models\\Weapons\\Tommygun\\Slider.mdl"), 0, + CTFILENAME("Models\\Weapons\\Tommygun\\Body.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + pmo->StretchModel(FLOAT3D(2.0,2.0,2.0)); + _bHasFloor = TRUE; + _fFloorY = -0.5f; + + } else if (strName=="Sniper") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Weapons\\Sniper\\Sniper.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Weapons\\Sniper\\Body.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-0.4f,-4.0f), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + _fFOV = 50.0f; + _vLightDir = FLOAT3D( -0.1f, -0.2f, -0.2f); + + AddAttachment_t(pmo, SNIPERITEM_ATTACHMENT_BODY, + CTFILENAME("ModelsMP\\Weapons\\Sniper\\Body.mdl"), 0, + CTFILENAME("ModelsMP\\Weapons\\Sniper\\Body.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + pmo->StretchModel(FLOAT3D(1.5,1.5,1.5)); + _bHasFloor = TRUE; + _fFloorY = -0.5f; + + } else if (strName=="ChainSaw") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Weapons\\Chainsaw\\ChainsawItem.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Weapons\\Chainsaw\\Body.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-0.4f,-3.0f), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + _fFOV = 60.0f; + _vLightDir = FLOAT3D( -0.1f, -0.2f, -0.2f); + + AddAttachment_t(pmo, CHAINSAWITEM_ATTACHMENT_CHAINSAW, + CTFILENAME("ModelsMP\\Weapons\\Chainsaw\\BodyForPlayer.mdl"), 0, + CTFILENAME("ModelsMP\\Weapons\\Chainsaw\\Body.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, CHAINSAWITEM_ATTACHMENT_BLADE, + CTFILENAME("ModelsMP\\Weapons\\Chainsaw\\Blade.mdl"), 0, + CTFILENAME("ModelsMP\\Weapons\\Chainsaw\\Blade.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + CAttachmentModelObject *amo = pmo->GetAttachmentModel(CHAINSAWITEM_ATTACHMENT_BLADE); + AddAttachment_t(pmo, BLADEFORPLAYER_ATTACHMENT_TEETH, + CTFILENAME("ModelsMP\\Weapons\\Chainsaw\\Teeth.mdl"), 0, + CTFILENAME("ModelsMP\\Weapons\\Chainsaw\\Teeth.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + + pmo->StretchModel(FLOAT3D(1.0,1.0,1.0)); + _bHasFloor = TRUE; + _fFloorY = -0.5f; + + } else if (strName=="Flamer") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Weapons\\Flamer\\FlamerItem.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Weapons\\Flamer\\Body.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-0.4f,-2.2f), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + _fFOV = 70.0f; + _vLightDir = FLOAT3D( -0.1f, -0.2f, -0.2f); + + AddAttachment_t(pmo, FLAMERITEM_ATTACHMENT_BODY, + CTFILENAME("ModelsMP\\Weapons\\Flamer\\Body.mdl"), 0, + CTFILENAME("ModelsMP\\Weapons\\Flamer\\Body.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, FLAMERITEM_ATTACHMENT_FUEL, + CTFILENAME("ModelsMP\\Weapons\\Flamer\\FuelReservoir.mdl"), 0, + CTFILENAME("ModelsMP\\Weapons\\Flamer\\FuelReservoir.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + pmo->StretchModel(FLOAT3D(1.5,1.5,1.5)); + _bHasFloor = TRUE; + _fFloorY = -0.5f; + + } else if (strName=="serious bomb") { + pmo->SetData_t(CTFILENAME("ModelsMP\\Items\\PowerUps\\SeriousBomb\\SeriousBomb.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("ModelsMP\\Items\\PowerUps\\SeriousBomb\\SeriousBomb.tex")); + + _plModel = CPlacement3D(FLOAT3D(0.0f, -1.0f, -6.0f), ANGLE3D(0,-10.0f,0)); + _aRotation = ANGLE3D(60,0,0); + _fFOV = 40.0f; + /*_plModel = CPlacement3D(FLOAT3D(tmp_af[5],tmp_af[6],tmp_af[7]), ANGLE3D(0,tmp_af[8],0)); + _fFOV = tmp_af[9]; + CPrintF("%f %f %f : %f : %f\n", tmp_af[5],tmp_af[6],tmp_af[7], tmp_af[8], tmp_af[9]);*/ + + pmo->StretchModel(FLOAT3D(3.0f, 3.0f, 3.0f)); + _bHasFloor = TRUE; + _fFloorY = 0.0f; + + } else if (strName=="Minigun") { + pmo->SetData_t(CTFILENAME("Models\\Weapons\\Minigun\\MinigunItem.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Weapons\\Minigun\\Minigun.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-0.5f,-3.75f), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + + AddAttachment_t(pmo, MINIGUNITEM_ATTACHMENT_BARRELS, + CTFILENAME("Models\\Weapons\\Minigun\\Barrels.mdl"), 0, + CTFILENAME("Models\\Weapons\\Minigun\\Barrels.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, MINIGUNITEM_ATTACHMENT_BODY, + CTFILENAME("Models\\Weapons\\Minigun\\Body.mdl"), 0, + CTFILENAME("Models\\Weapons\\Minigun\\Body.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, MINIGUNITEM_ATTACHMENT_ENGINE, + CTFILENAME("Models\\Weapons\\Minigun\\Engine.mdl"), 0, + CTFILENAME("Models\\Weapons\\Minigun\\Barrels.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + pmo->StretchModel(FLOAT3D(1.75,1.75,1.75)); + _bHasFloor = TRUE; + _fFloorY = -1.0f; + + } else if (strName=="RocketLauncher") { + pmo->SetData_t(CTFILENAME("Models\\Weapons\\RocketLauncher\\RocketLauncherItem.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Weapons\\RocketLauncher\\Body.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-1.0f,-3.0), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + + AddAttachment_t(pmo, ROCKETLAUNCHERITEM_ATTACHMENT_BODY, + CTFILENAME("Models\\Weapons\\RocketLauncher\\Body.mdl"), 0, + CTFILENAME("Models\\Weapons\\RocketLauncher\\Body.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, ROCKETLAUNCHERITEM_ATTACHMENT_ROTATINGPART, + CTFILENAME("Models\\Weapons\\RocketLauncher\\RotatingPart.mdl"), 0, + CTFILENAME("Models\\Weapons\\RocketLauncher\\RotatingPart.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET1, + CTFILENAME("Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl"), 0, + CTFILENAME("Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET2, + CTFILENAME("Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl"), 0, + CTFILENAME("Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET3, + CTFILENAME("Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl"), 0, + CTFILENAME("Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, ROCKETLAUNCHERITEM_ATTACHMENT_ROCKET4, + CTFILENAME("Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.mdl"), 0, + CTFILENAME("Models\\Weapons\\RocketLauncher\\Projectile\\Rocket.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + pmo->StretchModel(FLOAT3D(2.5,2.5,2.5)); + _bHasFloor = TRUE; + _fFloorY = -1.0f; + + } else if (strName=="GrenadeLauncher") { + pmo->SetData_t(CTFILENAME("Models\\Weapons\\GrenadeLauncher\\GrenadeLauncherItem.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Weapons\\GrenadeLauncher\\Body.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-1.0f,-4.0), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + + AddAttachment_t(pmo, GRENADELAUNCHERITEM_ATTACHMENT_BODY, + CTFILENAME("Models\\Weapons\\GrenadeLauncher\\Body.mdl"), 0, + CTFILENAME("Models\\Weapons\\GrenadeLauncher\\Body.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, GRENADELAUNCHERITEM_ATTACHMENT_MOVING_PART, + CTFILENAME("Models\\Weapons\\GrenadeLauncher\\MovingPipe.mdl"), 0, + CTFILENAME("Models\\Weapons\\GrenadeLauncher\\MovingPipe.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, GRENADELAUNCHERITEM_ATTACHMENT_GRENADE, + CTFILENAME("Models\\Weapons\\GrenadeLauncher\\GrenadeBack.mdl"), 0, + CTFILENAME("Models\\Weapons\\GrenadeLauncher\\MovingPipe.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + pmo->StretchModel(FLOAT3D(2.5,2.5,2.5)); + _bHasFloor = TRUE; + _fFloorY = -1.0f; + + } else if (strName=="Laser") { + pmo->SetData_t(CTFILENAME("Models\\Weapons\\Laser\\LaserItem.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Weapons\\Laser\\Body.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-1.0f,-3.0), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + + AddAttachment_t(pmo, LASERITEM_ATTACHMENT_BODY, + CTFILENAME("Models\\Weapons\\Laser\\Body.mdl"), 0, + CTFILENAME("Models\\Weapons\\Laser\\Body.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, LASERITEM_ATTACHMENT_LEFTUP, + CTFILENAME("Models\\Weapons\\Laser\\Barrel.mdl"), 0, + CTFILENAME("Models\\Weapons\\Laser\\Barrel.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, LASERITEM_ATTACHMENT_LEFTDOWN, + CTFILENAME("Models\\Weapons\\Laser\\Barrel.mdl"), 0, + CTFILENAME("Models\\Weapons\\Laser\\Barrel.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, LASERITEM_ATTACHMENT_RIGHTUP, + CTFILENAME("Models\\Weapons\\Laser\\Barrel.mdl"), 0, + CTFILENAME("Models\\Weapons\\Laser\\Barrel.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + AddAttachment_t(pmo, LASERITEM_ATTACHMENT_RIGHTDOWN, + CTFILENAME("Models\\Weapons\\Laser\\Barrel.mdl"), 0, + CTFILENAME("Models\\Weapons\\Laser\\Barrel.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + pmo->StretchModel(FLOAT3D(2.5,2.5,2.5)); + _bHasFloor = TRUE; + _fFloorY = -1.0f; + + } else if (strName=="Cannon") { + pmo->SetData_t(CTFILENAME("Models\\Weapons\\Cannon\\Cannon.mdl")); + pmo->mo_toTexture.SetData_t(CTFILENAME("Models\\Weapons\\Cannon\\Body.tex")); + _plModel = CPlacement3D(FLOAT3D(0,-1.0f,-3.0), ANGLE3D(0,10,0)); + _aRotation = ANGLE3D(100,0,0); + + AddAttachment_t(pmo, CANNON_ATTACHMENT_BODY, + CTFILENAME("Models\\Weapons\\Cannon\\Body.mdl"), 0, + CTFILENAME("Models\\Weapons\\Cannon\\Body.tex"), + CTFILENAME("Models\\ReflectionTextures\\LightMetal01.tex"), + CTFILENAME("Models\\SpecularTextures\\Medium.tex")); + pmo->StretchModel(FLOAT3D(2.5,2.5,2.5)); + _bHasFloor = TRUE; + _fFloorY = -1.0f; + + } else { + ThrowF_t(TRANS("Unknown model '%s'"), strName); + } +} + +void RenderMessageModel(CDrawPort *pdp, const CTString &strModel) +{ + // if new model + if (_strLastModel!=strModel) { + _strLastModel=strModel; + _bModelOK = FALSE; + // try to + try { + // load model + SetupCompModel_t(strModel); + _bModelOK = TRUE; + // if failed + } catch(char *strError) { + // report error + CPrintF("Cannot setup model '%s':\n%s\n", strModel, strError); + // do nothing + return; + } + } + + // if model is not loaded ok + if (!_bModelOK) { + // do nothing + return; + } + + // for each eye + for (INDEX iEye=STEREO_LEFT; iEye<=(Stereo_IsEnabled()?STEREO_RIGHT:STEREO_LEFT); iEye++) { + // prepare projection + CRenderModel rm; + CPerspectiveProjection3D pr; + pr.FOVL() = AngleDeg(_fFOV); + pr.ScreenBBoxL() = FLOATaabbox2D( + FLOAT2D(0.0f, 0.0f), + FLOAT2D((float)pdp->GetWidth(), (float)pdp->GetHeight()) + ); + pr.AspectRatioL() = 1.0f; + pr.FrontClipDistanceL() = 0.3f; + pr.ViewerPlacementL() = CPlacement3D(FLOAT3D(0,0,0), ANGLE3D(0,0,0)); + + // setup stereo rendering + Stereo_SetBuffer(iEye); + Stereo_AdjustProjection(pr, iEye, 0.16f); + + pdp->FillZBuffer(1.0f); + + // initialize rendering + CAnyProjection3D apr; + apr = pr; + BeginModelRenderingView(apr, pdp); + rm.rm_vLightDirection = _vLightDir; + const FLOAT fDistance = 1+ 10*(1/(_fMsgAppearFade+0.01) - 1/(1+0.01)); + + // if model needs floor + if( _bHasFloor) { + // set floor's position + CPlacement3D pl = _plModel; + pl.pl_OrientationAngle = ANGLE3D(0,0,0); + pl.pl_PositionVector = _plModel.pl_PositionVector; + pl.pl_PositionVector(2) += _fFloorY; + pl.pl_PositionVector(3) *= fDistance; + rm.SetObjectPlacement(pl); + // render the floor + rm.rm_colLight = C_WHITE; + rm.rm_colAmbient = C_WHITE; + rm.rm_fDistanceFactor = -999; + _moFloor.SetupModelRendering(rm); + _moFloor.RenderModel(rm); + } + + // set model's position + CPlacement3D pl; + pl.pl_OrientationAngle = _plModel.pl_OrientationAngle + _aRotation*_pTimer->GetLerpedCurrentTick(); + pl.pl_PositionVector = _plModel.pl_PositionVector; + pl.pl_PositionVector(3) *= fDistance / pdp->dp_fWideAdjustment; + rm.SetObjectPlacement(pl); + + // render the model + rm.rm_colLight = _colLight; + rm.rm_colAmbient = _colAmbient; + rm.rm_fDistanceFactor = -999; // force highest mip disregarding stretch factors + _moModel.SetupModelRendering(rm); + FLOATplane3D plFloorPlane = FLOATplane3D( FLOAT3D( 0.0f, 1.0f, 0.0f), _plModel.pl_PositionVector(2)+_fFloorY); + CPlacement3D plLightPlacement = CPlacement3D( _plModel.pl_PositionVector + + rm.rm_vLightDirection * _plModel.pl_PositionVector(3) *5, ANGLE3D(0,0,0)); + _moModel.RenderShadow( rm, plLightPlacement, 200.0f, 200.0f, 1.0f, plFloorPlane); + _moModel.RenderModel(rm); + + // render particles + if (_iParticleType!=PARTICLES_NONE) { + Particle_PrepareSystem(pdp, apr); + Particle_PrepareEntity( 1, 0, 0, NULL); + switch(_iParticleType) { + case PARTICLES_AIR_ELEMENTAL: + Particles_AirElemental_Comp(&_moModel, 1.0f, 1.0f, pl); + break; + case PARTICLES_LAVA_ELEMENTAL: + Particles_Burning_Comp(&_moModel, 0.25f, pl); + break; + } + Particle_EndSystem(); + } + + EndModelRenderingView(); + } + Stereo_SetBuffer(STEREO_BOTH); +} diff --git a/Sources/GameMP/Computer.cpp b/Sources/GameMP/Computer.cpp new file mode 100644 index 0000000..c84e37c --- /dev/null +++ b/Sources/GameMP/Computer.cpp @@ -0,0 +1,1315 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdAfx.h" +#include "LCDDrawing.h" +#include "CompMessage.h" + +extern CGame *_pGame; + +static const FLOAT tmComputerFade = 1.0f; // how many seconds it takes computer to fade in/out +static FLOAT fComputerFadeValue = 0.0f; // faded value of computer (0..1) +static CTimerValue tvComputerLast; +static CTimerValue _tvMessageAppear; +static CPlayer *_ppenPlayer = NULL; +extern FLOAT _fMsgAppearFade = 0.0f; +extern FLOAT _fMsgAppearDelta = 0.0f; + +// player statistics are set here +extern CTString _strStatsDetails = ""; + +// mouse cursor position +static PIX2D _vpixMouse; +static PIX2D _vpixExternMouse; +static PIX _pixSliderDragJ = -1; +static PIX _iSliderDragLine = -1; +static PIX _bSliderDragText = FALSE; +// font metrics +static PIX _pixCharSizeI = 1; +static PIX _pixCharSizeJ = 1; +static PIX _pixCharSize2I = 1; +static PIX _pixCharSize2J = 1; + +static PIX _pixMarginI = 1; +static PIX _pixMarginJ = 1; +// general geometry data +static FLOAT _fScaling = 1; +static FLOAT _fScaling2 = 1; +static PIX _pixSizeI=0; +static PIX _pixSizeJ=0; +static PIXaabbox2D _boxTitle; +static PIXaabbox2D _boxExit; +static PIXaabbox2D _boxMsgList; +static PIXaabbox2D _boxMsgText; +static PIXaabbox2D _boxMsgImage; +static PIXaabbox2D _boxButton[CMT_COUNT]; +static INDEX _ctMessagesOnScreen = 5; +static INDEX _ctTextLinesOnScreen = 20; +static INDEX _ctTextCharsPerRow = 20; + +// position of the message list +static INDEX _iFirstMessageOnScreen = -1; +static INDEX _iWantedFirstMessageOnScreen = 0; +static INDEX _iLastActiveMessage = -1; +static INDEX _iActiveMessage = 0; + +// message type selected in the buttons list +static enum CompMsgType _cmtCurrentType = (enum CompMsgType)-1; +static enum CompMsgType _cmtWantedType = CMT_INFORMATION; + +// current scroll position of message text +static INDEX _iTextLineOnScreen = 0; + +// message list cache for messages of current type +static CStaticStackArray _acmMessages; + +// message image data +static CTextureObject _toPicture; + +// text/graphics colors +static COLOR _colLight; +static COLOR _colMedium; +static COLOR _colDark; +static COLOR _colBoxes; + +static void SetFont1(CDrawPort *pdp) +{ + pdp->SetFont(_pfdConsoleFont); + pdp->SetTextScaling(_fScaling); + pdp->SetTextAspect(1.0f); +} + +static void SetFont2(CDrawPort *pdp) +{ + pdp->SetFont(_pfdDisplayFont); + pdp->SetTextScaling(_fScaling2); + pdp->SetTextAspect(1.0f); +} + +static COLOR MouseOverColor(const PIXaabbox2D &box, COLOR colNone, + COLOR colOff, COLOR colOn) +{ + if (box>=_vpixMouse) { + return LCDBlinkingColor(colOff, colOn); + } else { + return colNone; + } +} + +static PIXaabbox2D GetMsgListBox(INDEX i) +{ + PIX pixI0 = _boxMsgList.Min()(1)+_pixMarginI; + PIX pixI1 = _boxMsgList.Max()(1)-_pixMarginI*3; + PIX pixJ0 = _boxMsgList.Min()(2)+_pixMarginJ; + PIX pixDJ = _pixCharSizeJ; + return PIXaabbox2D( + PIX2D(pixI0, pixJ0+pixDJ*i), + PIX2D(pixI1, pixJ0+pixDJ*(i+1)-1)); +} + +static PIXaabbox2D GetSliderBox(INDEX iFirst, INDEX iVisible, INDEX iTotal, + PIXaabbox2D boxFull) +{ + FLOAT fSize = ClampUp(FLOAT(iVisible)/iTotal, 1.0f); + PIX pixFull = boxFull.Size()(2); + PIX pixSize = PIX(pixFull*fSize); + pixSize = ClampDn(pixSize, boxFull.Size()(1)); + PIX pixTop = pixFull*(FLOAT(iFirst)/iTotal)+boxFull.Min()(2); + PIX pixI0 = boxFull.Min()(1); + PIX pixI1 = boxFull.Max()(1); + return PIXaabbox2D(PIX2D(pixI0, pixTop), PIX2D(pixI1, pixTop+pixSize)); +} + +static INDEX SliderPixToIndex(PIX pixOffset, INDEX iVisible, INDEX iTotal, PIXaabbox2D boxFull) +{ + FLOAT fSize = ClampUp(FLOAT(iVisible)/iTotal, 1.0f); + PIX pixFull = boxFull.Size()(2); + PIX pixSize = PIX(pixFull*fSize); + if (pixSize>=boxFull.Size()(2)) { + return 0; + } + return (iTotal*pixOffset)/pixFull; +} + +static PIXaabbox2D GetTextSliderSpace(void) +{ + PIX pixSizeI = _boxMsgText.Size()(1); + PIX pixSizeJ = _boxMsgText.Size()(2); + + PIX pixSliderSizeI = _pixMarginI*2; + if (pixSliderSizeI<5) { + pixSliderSizeI=5; + } + return PIXaabbox2D( + PIX2D(pixSizeI-pixSliderSizeI, _pixMarginJ*4), + PIX2D(pixSizeI, pixSizeJ)); +} + +static PIXaabbox2D GetMsgSliderSpace(void) +{ + PIX pixSizeI = _boxMsgList.Size()(1); + PIX pixSizeJ = _boxMsgList.Size()(2); + + PIX pixSliderSizeI = _pixMarginI*2; + if (pixSliderSizeI<5) { + pixSliderSizeI=5; + } + return PIXaabbox2D( + PIX2D(pixSizeI-pixSliderSizeI, 0), + PIX2D(pixSizeI, pixSizeJ)); +} + +static PIXaabbox2D GetTextSliderBox(void) +{ + if (_iActiveMessage>=_acmMessages.Count()) { + return PIXaabbox2D(); + } + INDEX ctTextLines = _acmMessages[_iActiveMessage].cm_ctFormattedLines; + PIX pixSizeI = _boxMsgText.Size()(1); + PIX pixSizeJ = _boxMsgText.Size()(2); + return GetSliderBox( + _iTextLineOnScreen, _ctTextLinesOnScreen, ctTextLines, GetTextSliderSpace()); +} + +static PIXaabbox2D GetMsgSliderBox(void) +{ + INDEX ctLines = _acmMessages.Count(); + PIX pixSizeI = _boxMsgList.Size()(1); + PIX pixSizeJ = _boxMsgList.Size()(2); + return GetSliderBox( + _iFirstMessageOnScreen, _ctMessagesOnScreen, ctLines, GetMsgSliderSpace()); +} + +// syncronize message list scrolling to show active message +void SyncScrollWithActive(void) +{ + if (_iActiveMessage<_iFirstMessageOnScreen) { + _iWantedFirstMessageOnScreen = _iActiveMessage; + } + if (_iActiveMessage>_iFirstMessageOnScreen+_ctMessagesOnScreen-1) { + _iWantedFirstMessageOnScreen = _iActiveMessage-_ctMessagesOnScreen+1; + } +} + +// select next unread message +static void NextUnreadMessage(void) +{ + INDEX i=_iActiveMessage; + FOREVER { + i++; + if (i>=_acmMessages.Count()) { + i = 0; + } + if (i==_iActiveMessage) { + return; + } + if (!_acmMessages[i].cm_bRead) { + _iActiveMessage = i; + SyncScrollWithActive(); + return; + } + } +} + +// select last unread message, or last message if all read +void LastUnreadMessage(void) +{ + BOOL bFound = FALSE; + for(_iActiveMessage=_acmMessages.Count()-1; _iActiveMessage>=0; _iActiveMessage--) { + if (!_acmMessages[_iActiveMessage].cm_bRead) { + bFound = TRUE; + break; + } + } + if (!bFound) { + _iActiveMessage = ClampDn(_acmMessages.Count()-1, 0); + } + SyncScrollWithActive(); +} + +// go to next/previous message +void PrevMessage(void) +{ + if (_iActiveMessage<_acmMessages.Count()==0) { + return; + } + _iActiveMessage--; + if (_iActiveMessage<0) { + _iActiveMessage = 0; + } + SyncScrollWithActive(); +} + +void NextMessage(void) +{ + if (_iActiveMessage<_acmMessages.Count()==0) { + return; + } + _iActiveMessage++; + if (_iActiveMessage>=_acmMessages.Count()) { + _iActiveMessage = _acmMessages.Count()-1; + } + SyncScrollWithActive(); +} + +void MessagesUpDn(INDEX ctLines) +{ + INDEX ctMessages = _acmMessages.Count(); + _iWantedFirstMessageOnScreen += ctLines; + INDEX iMaxFirst = ClampDn(0L, ctMessages-_ctMessagesOnScreen); + _iWantedFirstMessageOnScreen = Clamp(_iWantedFirstMessageOnScreen, 0L, iMaxFirst); + _iActiveMessage = Clamp(_iActiveMessage, + _iWantedFirstMessageOnScreen, + _iWantedFirstMessageOnScreen+_ctMessagesOnScreen-1L); +} + +void SelectMessage(INDEX i) +{ + if (_acmMessages.Count()==0) { + return; + } + _iActiveMessage = i; + if (_iActiveMessage<0) { + _iActiveMessage = 0; + } + if (_iActiveMessage>=_acmMessages.Count()) { + _iActiveMessage = _acmMessages.Count()-1; + } + SyncScrollWithActive(); +} + +// scroll message text +void MessageTextUp(INDEX ctLines) +{ + _iTextLineOnScreen-=ctLines; + if (_iTextLineOnScreen<0) { + _iTextLineOnScreen = 0; + } +} +void MessageTextDn(INDEX ctLines) +{ + // if no message do nothing + if (_iActiveMessage<_acmMessages.Count()==0) { + return; + } + // find text lines count + _acmMessages[_iActiveMessage].PrepareMessage(_ctTextCharsPerRow); + INDEX ctTextLines = _acmMessages[_iActiveMessage].cm_ctFormattedLines; + // calculate maximum value for first visible line + INDEX iFirstLine = ctTextLines-_ctTextLinesOnScreen; + if (iFirstLine<0) { + iFirstLine = 0; + } + + // increment + _iTextLineOnScreen+=ctLines; + if (_iTextLineOnScreen>iFirstLine) { + _iTextLineOnScreen = iFirstLine; + } +} + +void MessageTextUpDn(INDEX ctLines) +{ + if (ctLines>0) { + MessageTextDn(ctLines); + } else if (ctLines<0) { + MessageTextUp(-ctLines); + } +} + +// mark current message as read +void MarkCurrentRead(void) +{ + if (_iActiveMessage>=_acmMessages.Count()) { + return; + } + // if running in background + if (_pGame->gm_csComputerState == CS_ONINBACKGROUND) { + // do nothing + return; + } + ASSERT(_ppenPlayer!=NULL); + if (_ppenPlayer==NULL) { + return; + } + // if already read + if (_acmMessages[_iActiveMessage].cm_bRead) { + // do nothing + return; + } + // mark as read + _ppenPlayer->m_ctUnreadMessages--; + _acmMessages[_iActiveMessage].MarkRead(); +} + +// update scroll position for message list +static void UpdateFirstOnScreen(void) +{ + if (_iFirstMessageOnScreen==_iWantedFirstMessageOnScreen) { + return; + } + _iFirstMessageOnScreen=_iWantedFirstMessageOnScreen; + ASSERT( + _iFirstMessageOnScreen>=0&& + _iFirstMessageOnScreen<=_acmMessages.Count()); + _iFirstMessageOnScreen = Clamp(_iFirstMessageOnScreen, INDEX(0), _acmMessages.Count()); + + // for each message + for(INDEX i=0; i<_acmMessages.Count(); i++) { + CCompMessage &cm = _acmMessages[i]; + // if on screen + if (i>=_iWantedFirstMessageOnScreen + &&i<_iWantedFirstMessageOnScreen+_ctMessagesOnScreen) { + // load + cm.PrepareMessage(_ctTextCharsPerRow); + // if not on screen + } else { + // unload + cm.UnprepareMessage(); + } + } +} + +// update current active message category +static void UpdateType(BOOL bForce=FALSE) +{ + if (_cmtCurrentType==_cmtWantedType && !bForce) { + return; + } + + // cleare message cache + _acmMessages.Clear(); + // for each player's message + CDynamicStackArray &acmiMsgs = _ppenPlayer->m_acmiMessages; + for(INDEX i=0; iExecute("FreeUnusedStock();"); // make sure user doesn't overflow memory + _iTextLineOnScreen = 0; + _iLastActiveMessage=_iActiveMessage; + _tvMessageAppear = _pTimer->GetHighPrecisionTimer(); + } + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + _fMsgAppearDelta = (tvNow-_tvMessageAppear).GetSeconds(); + + if (fComputerFadeValue<0.99f) { + _tvMessageAppear = _pTimer->GetHighPrecisionTimer(); + _fMsgAppearDelta = 0.0f; + } + _fMsgAppearFade = Clamp(_fMsgAppearDelta/0.5f, 0.0f,1.0f); +} + +// update screen geometry +static void UpdateSize(CDrawPort *pdp) +{ + // get screen size + PIX pixSizeI = pdp->GetWidth(); + PIX pixSizeJ = pdp->GetHeight(); + + // remember new size + _pixSizeI = pixSizeI; + _pixSizeJ = pixSizeJ; + + // determine scaling + _fScaling = 1.0f; + _fScaling2 = 1.0f; + if (pixSizeJ<384) { + _fScaling = 1.0f; + _fScaling2 = pixSizeJ/480.0f; + } + + // remember font size + CFontData *pfd = _pfdConsoleFont; + _pixCharSizeI = pfd->fd_pixCharWidth + pfd->fd_pixCharSpacing; + _pixCharSizeJ = pfd->fd_pixCharHeight + pfd->fd_pixLineSpacing; + _pixCharSize2I = _pixCharSizeI*_fScaling2; + _pixCharSize2J = _pixCharSizeJ*_fScaling2; + _pixCharSizeI = _pixCharSizeI*_fScaling; + _pixCharSizeJ = _pixCharSizeJ*_fScaling; + + _pixMarginI = 5*_fScaling2; + _pixMarginJ = 5*_fScaling2; + PIX pixBoxMarginI = 10*_fScaling2; + PIX pixBoxMarginJ = 10*_fScaling2; + + PIX pixJ0Dn = pixBoxMarginJ; + PIX pixJ1Up = pixJ0Dn+_pixCharSize2J+_pixMarginI*2; + PIX pixJ1Dn = pixJ1Up+pixBoxMarginJ; + PIX pixJ2Up = pixJ1Dn+_pixCharSize2J*6*2+pixBoxMarginJ; + PIX pixJ2Dn = pixJ2Up+pixBoxMarginJ; + PIX pixJ3Up = _pixSizeJ-pixBoxMarginJ; + + PIX pixI0Rt = pixBoxMarginI; + PIX pixI1Lt = pixI0Rt+_pixCharSize2I*20+pixBoxMarginI; + PIX pixI1Rt = pixI1Lt+pixBoxMarginI; + PIX pixI2Lt = _pixSizeI/2-pixBoxMarginI/2; + PIX pixI2Rt = _pixSizeI/2+pixBoxMarginI/2; + PIX pixI4Lt = _pixSizeI-pixBoxMarginI; + PIX pixI3Rt = pixI4Lt-pixBoxMarginI*2-_pixCharSize2I*10; + PIX pixI3Lt = pixI3Rt-pixBoxMarginI; + + // calculate box sizes + _boxTitle = PIXaabbox2D( PIX2D(0, pixJ0Dn-1), PIX2D(pixI3Lt, pixJ1Up)); + _boxExit = PIXaabbox2D( PIX2D( pixI3Rt, pixJ0Dn-1), PIX2D(_pixSizeI, pixJ1Up)); + PIX pixD = 5; + PIX pixH = (pixJ2Up-pixJ1Dn-pixD*(CMT_COUNT-1))/CMT_COUNT; + INDEX i; + for( i=0; isp_bCooperative) { + _boxMsgText = PIXaabbox2D( PIX2D(pixI2Rt, pixJ2Dn), PIX2D(pixI4Lt, pixJ3Up)); + _boxMsgImage= PIXaabbox2D( PIX2D(pixI0Rt, pixJ2Dn), PIX2D(pixI2Lt, pixJ3Up)); + } else { + _boxMsgText = PIXaabbox2D( PIX2D(pixI0Rt, pixJ2Dn), PIX2D(pixI4Lt, pixJ3Up)); + _boxMsgImage= PIXaabbox2D(); + } + + FLOAT fSlideSpeed = Max(_pixSizeI, _pixSizeJ*2L); + FLOAT fGroup0 = ClampDn((1-fComputerFadeValue)*fSlideSpeed-_pixSizeJ, 0.0f); + FLOAT fGroup1 = (1-fComputerFadeValue)*fSlideSpeed; + // animate box positions + _boxTitle -= PIX2D( fGroup1, 0); + _boxExit += PIX2D( fGroup1, 0); + for( i=0; iLCDRenderCompGrid(); + LCDRenderClouds2(); + LCDScreenBoxOpenLeft(_colBoxes); + + SetFont2(&dpButton); + + // count messages + INDEX ctTotal=0; + INDEX ctRead=0; + CDynamicStackArray &acmiMsgs = _ppenPlayer->m_acmiMessages; + {for(INDEX i=0; iGetPlayerName()); + pdp->PutText( strTitle, _pixMarginI*3, _pixMarginJ-2*_fScaling2+1, _colMedium); +} + +// print exit button +void PrintExit(CDrawPort *pdp) +{ + SetFont2(pdp); + pdp->PutTextR( TRANS("Exit"), _boxExit.Size()(1)-_pixMarginI*3, _pixMarginJ-2*_fScaling2+1, + MouseOverColor(_boxExit, _colMedium, _colDark, _colLight)); +} + +// print list of messages +void PrintMessageList(CDrawPort *pdp) +{ + PIX pixTextX = _pixMarginI; + PIX pixYLine = _pixMarginJ; + SetFont1(pdp); + + INDEX iFirst = _iFirstMessageOnScreen; + INDEX iLast = Min(INDEX(_iFirstMessageOnScreen+_ctMessagesOnScreen), _acmMessages.Count())-1; + if (iFirst>iLast) { + pdp->PutText( TRANS("no messages"), pixTextX, pixYLine, _colDark); + } + for(INDEX i=iFirst; i<=iLast; i++) { + COLOR col = _colMedium; + if (_acmMessages[i].cm_bRead) { + col = _colDark; + } + if (i==_iActiveMessage) { + col = _colLight; + } + if (GetMsgListBox(i-_iFirstMessageOnScreen)>=_vpixMouse) { + col = LCDBlinkingColor(_colLight, _colMedium); + } + pdp->PutText( _acmMessages[i].cm_strSubject, pixTextX, pixYLine, col); + pixYLine+=_pixCharSizeJ; + } + + PIXaabbox2D boxSliderSpace = GetMsgSliderSpace(); + LCDDrawBox(0,0,boxSliderSpace, _colBoxes); + PIXaabbox2D boxSlider = GetMsgSliderBox(); + COLOR col = _colBoxes; + PIXaabbox2D boxSliderTrans = boxSlider; + boxSliderTrans+=_boxMsgList.Min(); + if (boxSliderTrans>=_vpixMouse) { + col = LCDBlinkingColor(_colLight, _colDark); + } + pdp->Fill( boxSlider.Min()(1)+2, boxSlider.Min()(2)+2, + boxSlider.Size()(1)-4, boxSlider.Size()(2)-4, col); +} + +// print text of current message +void PrintMessageText(CDrawPort *pdp) +{ + if (_acmMessages.Count()==0 || + _iActiveMessage>=_acmMessages.Count()|| + fComputerFadeValue<0.99f) { + return; + } + + SetFont2(pdp); + + // print subject + CTString strSubject0; + CTString strSubject1; + CTString strSubject2; + //strSubject.PrintF("%g", _fMsgAppearFade); + const char *strSubject = _acmMessages[_iActiveMessage].cm_strSubject; + INDEX ctSubjectLen = strlen(strSubject); + INDEX ctToPrint = int(_fMsgAppearDelta*20.0f); + for (INDEX iChar=0; iCharctToPrint) { + NOTHING; + } else if (iChar==ctToPrint) { + strSubject2+=strChar; + } else if (iChar==ctToPrint-1) { + strSubject1+=strChar; + } else { + strSubject0+=strChar; + } + } + PIX pixWidth0 = pdp->GetTextWidth(strSubject0); + PIX pixWidth1 = pdp->GetTextWidth(strSubject1); + pdp->PutText(strSubject0, _pixMarginI, _pixMarginJ-1, _colMedium); + pdp->PutText(strSubject1, _pixMarginI+pixWidth0, _pixMarginJ-1, LerpColor( _colLight, _colMedium, 0.5f)); + pdp->PutText(strSubject2, _pixMarginI+pixWidth0+pixWidth1, _pixMarginJ-1, _colLight); + + pdp->DrawLine(0, PIX(_pixMarginJ*4), _boxMsgText.Size()(1), PIX(_pixMarginJ*4), _colBoxes); + + // fill in fresh player statistics + if (strncmp(_acmMessages[_iActiveMessage].cm_strText, "$STAT", 5)==0) { + _ppenPlayer->GetStats(_strStatsDetails, CST_DETAIL, _ctTextCharsPerRow); + _acmMessages[_iActiveMessage].cm_ctFormattedWidth = 0; + } + // format text + _acmMessages[_iActiveMessage].PrepareMessage(_ctTextCharsPerRow); + + SetFont1(pdp); + INDEX ctLineToPrint = int(_fMsgAppearDelta*20.0f); + // print it + PIX pixJ = _pixMarginJ*4; + for (INDEX iLine = _iTextLineOnScreen; + iLine<_iTextLineOnScreen+_ctTextLinesOnScreen; + iLine++) { + INDEX iPrintLine = iLine-_iTextLineOnScreen; + if (iPrintLine>ctLineToPrint) { + continue; + } + COLOR col = LerpColor( _colLight, _colMedium, Clamp( FLOAT(ctLineToPrint-iPrintLine)/3, 0.0f, 1.0f)); + pdp->PutText(_acmMessages[_iActiveMessage].GetLine(iLine), + _pixMarginI, pixJ, col); + pixJ+=_pixCharSizeJ; + } + + PIXaabbox2D boxSliderSpace = GetTextSliderSpace(); + LCDDrawBox(0,0,boxSliderSpace, _colBoxes); + PIXaabbox2D boxSlider = GetTextSliderBox(); + COLOR col = _colBoxes; + PIXaabbox2D boxSliderTrans = boxSlider; + boxSliderTrans+=_boxMsgText.Min(); + if (boxSliderTrans>=_vpixMouse) { + col = LCDBlinkingColor(_colLight, _colDark); + } + pdp->Fill( boxSlider.Min()(1)+2, boxSlider.Min()(2)+2, + boxSlider.Size()(1)-4, boxSlider.Size()(2)-4, col); +} + + +void RenderMessagePicture(CDrawPort *pdp) +{ + CCompMessage &cm = _acmMessages[_iActiveMessage]; + // try to + try { + // load image + _toPicture.SetData_t(cm.cm_fnmPicture); + ((CTextureData*)_toPicture.GetData())->Force(TEX_CONSTANT); + // if failed + } catch(char *strError) { + // report error + CPrintF("Cannot load '%s':\n%s\n", (CTString&)cm.cm_fnmPicture, strError); + // do nothing + return; + } + + // get image and box sizes + PIX pixImgSizeI = _toPicture.GetWidth(); + PIX pixImgSizeJ = _toPicture.GetHeight(); + PIXaabbox2D boxPic(PIX2D(_pixMarginI, _pixMarginJ), + PIX2D(_boxMsgImage.Size()(1)-_pixMarginI, _boxMsgImage.Size()(2)-_pixMarginJ)); + PIX pixBoxSizeI = boxPic.Size()(1); + PIX pixBoxSizeJ = boxPic.Size()(2); + PIX pixCenterI = _boxMsgImage.Size()(1)/2; + PIX pixCenterJ = _boxMsgImage.Size()(2)/2; + // find image stretch to fit in box + FLOAT fStretch = Min(FLOAT(pixBoxSizeI)/pixImgSizeI, FLOAT(pixBoxSizeJ)/pixImgSizeJ); + // draw the image + pdp->PutTexture(&_toPicture, + PIXaabbox2D( + PIX2D(pixCenterI-pixImgSizeI*fStretch/2, pixCenterJ-pixImgSizeJ*fStretch/2), + PIX2D(pixCenterI+pixImgSizeI*fStretch/2, pixCenterJ+pixImgSizeJ*fStretch/2))); +} + + +void RenderMessageStats(CDrawPort *pdp) +{ + CSessionProperties *psp = (CSessionProperties *)_pNetwork->GetSessionProperties(); + ULONG ulLevelMask = psp->sp_ulLevelsMask; + INDEX iLevel = -1; + if (psp->sp_bCooperative) { + extern void RenderMap( CDrawPort *pdp, ULONG ulLevelMask, CProgressHookInfo *pphi); + if (pdp->Lock()) { + // get sizes + PIX pixSizeI = pdp->GetWidth(); + PIX pixSizeJ = pdp->GetHeight(); + // clear bcg + pdp->Fill( 1, 1, pixSizeI-2, pixSizeJ-2, C_BLACK|CT_OPAQUE); + // render the map if not fading + COLOR colFade = LCDFadedColor(C_WHITE|255); + if( (colFade&255) == 255) { + RenderMap( pdp, ulLevelMask, NULL); + } + pdp->Unlock(); + } + } +} + + +extern void RenderMessageModel(CDrawPort *pdp, const CTString &strModel); + +// draw image of current message +void RenderMessageImage(CDrawPort *pdp) +{ + if (!GetSP()->sp_bCooperative) { + return; + } + // if no message + if (_acmMessages.Count()==0 || fComputerFadeValue<0.99f) { + // render empty + LCDRenderClouds2(); + LCDScreenBox(_colBoxes); + return; + } + CCompMessage &cm = _acmMessages[_iActiveMessage]; + + if (cm.cm_itImage == CCompMessage::IT_STATISTICS) { + _pGame->LCDRenderCompGrid(); + } + LCDRenderClouds2(); + LCDScreenBox(_colBoxes); + + // if no image + if (cm.cm_itImage == CCompMessage::IT_NONE) { + // do nothing + return; + } else if (cm.cm_itImage == CCompMessage::IT_PICTURE) { + RenderMessagePicture(pdp); + } else if (cm.cm_itImage == CCompMessage::IT_STATISTICS) { + RenderMessageStats(pdp); + } else if (cm.cm_itImage == CCompMessage::IT_MODEL) { + RenderMessageModel(pdp, cm.cm_strModel); + } else { + ASSERT(FALSE); + } +} + +// find first group with some unread message +static BOOL FindGroupWithUnread(void) +{ + CDynamicStackArray &acmiMsgs = _ppenPlayer->m_acmiMessages; + for(INDEX i=acmiMsgs.Count()-1; i>=0; i--) { + CCompMessageID &cmi = acmiMsgs[i]; + // if it unread + if (!cmi.cmi_bRead) { + _cmtWantedType = cmi.cmi_cmtType; + return TRUE; + } + } + // if none found, select statistics + _cmtWantedType = CMT_STATISTICS; + return FALSE; +} + +static void ComputerOn(void) +{ + // init button names + _astrButtonTexts[CMT_INFORMATION ] = TRANS("tactical data"); + _astrButtonTexts[CMT_BACKGROUND ] = TRANS("strategic data"); + _astrButtonTexts[CMT_WEAPONS ] = TRANS("weapons"); + _astrButtonTexts[CMT_ENEMIES ] = TRANS("enemies"); + _astrButtonTexts[CMT_STATISTICS ] = TRANS("statistics"); + + _iFirstMessageOnScreen = -1; + _iWantedFirstMessageOnScreen = 0; + _iActiveMessage = 0; + _cmtCurrentType = (enum CompMsgType)-1; + _cmtWantedType = CMT_INFORMATION; + _acmMessages.Clear(); + + ASSERT(_ppenPlayer!=NULL); + if (_ppenPlayer==NULL) { + return; + } + + // fill in player statistics + _ppenPlayer->GetStats(_strStatsDetails, CST_DETAIL, _ctTextCharsPerRow); + + // if end of level + if (_ppenPlayer!=NULL && _ppenPlayer->m_bEndOfLevel || _pNetwork->IsGameFinished()) { + // select statistics + _cmtWantedType = CMT_STATISTICS; + // if not end of level + } else { + // find group with some unread messages + FindGroupWithUnread(); + } +} + +static void ComputerOff(void) +{ + _acmMessages.Clear(); + _pShell->Execute("FreeUnusedStock();"); +} + +static void ExitRequested(void) +{ + // if end of game + if (_ppenPlayer!=NULL && _ppenPlayer->m_bEndOfGame || _pNetwork->IsGameFinished()) { + // if in single player + if (GetSP()->sp_bSinglePlayer) { + // request app to show high score + _pShell->Execute("sam_bMenuHiScore=1;"); + } + // hard turn off + _pGame->gm_csComputerState = CS_OFF; + fComputerFadeValue = 0.0f; + ComputerOff(); + cmp_ppenPlayer = NULL; + // stop current game + _pGame->StopGame(); + // if not end of level + } else { + // if can be rendered on second display + if (cmp_ppenDHPlayer!=NULL) { + // clear pressed keys + _pInput->ClearInput(); + // just switch to background fast + _pGame->gm_csComputerState = CS_ONINBACKGROUND; + cmp_ppenPlayer = NULL; + // if no second display + } else { + // start turning off + _pGame->gm_csComputerState = CS_TURNINGOFF; + } + } + // turn off end of level for player + if (_ppenPlayer!=NULL) { + _ppenPlayer->m_bEndOfLevel = FALSE; + } +} + +void CGame::ComputerMouseMove(PIX pixX, PIX pixY) +{ + _vpixMouse(1) += pixX-_vpixExternMouse(1); + _vpixMouse(2) += pixY-_vpixExternMouse(2); + _vpixExternMouse(1) = pixX; + _vpixExternMouse(2) = pixY; + + // if dragging + if (_pixSliderDragJ>=0) { + PIX pixDelta = _vpixMouse(2)-_pixSliderDragJ; + + if (_bSliderDragText) { + if (_iActiveMessage<_acmMessages.Count()) { + INDEX ctTextLines = _acmMessages[_iActiveMessage].cm_ctFormattedLines; + INDEX iWantedLine = _iSliderDragLine+ + SliderPixToIndex(pixDelta, _ctTextLinesOnScreen, ctTextLines, GetTextSliderSpace()); + MessageTextUpDn(iWantedLine-_iTextLineOnScreen); + } + } else { + INDEX ctLines = _acmMessages.Count(); + INDEX iWantedLine = _iSliderDragLine+ + SliderPixToIndex(pixDelta, _ctMessagesOnScreen, ctLines, GetMsgSliderSpace()); + MessagesUpDn(iWantedLine-_iFirstMessageOnScreen); + } + } +} + + +void CGame::ComputerKeyDown(MSG msg) +{ + static BOOL bRDown = FALSE; + // if computer is not active + if (_pGame->gm_csComputerState!=CS_ON && _pGame->gm_csComputerState!=CS_TURNINGON) { + // do nothing + return; + } + + // if escape pressed + if (msg.message==WM_KEYDOWN && msg.wParam==VK_ESCAPE) { + ExitRequested(); + } + + // if right mouse pressed + if (msg.message==WM_RBUTTONDOWN || msg.message==WM_RBUTTONDBLCLK) { + bRDown = TRUE; + } + // if right mouse released + if (bRDown && msg.message==WM_RBUTTONUP) { + bRDown = FALSE; + // mark current message as read + MarkCurrentRead(); + // find a group with first unread message + BOOL bHasUnread = FindGroupWithUnread(); + // if some + if (bHasUnread) { + // select first unread message in it + NextUnreadMessage(); + } else { + ExitRequested(); + } + } + + if (msg.message==WM_KEYDOWN) { + switch (msg.wParam) { + // change message types on number keys + case '1': _cmtWantedType = CMT_INFORMATION ; return; + case '2': _cmtWantedType = CMT_WEAPONS ; return; + case '3': _cmtWantedType = CMT_ENEMIES ; return; + case '4': _cmtWantedType = CMT_BACKGROUND ; return; + case '5': _cmtWantedType = CMT_STATISTICS ; return; + // go to next unread + case 'U': + case VK_SPACE: + NextUnreadMessage(); return; + // scroll message list + case 219: PrevMessage(); return; + case 221: NextMessage(); return; + // mark current message as read and go to next + case VK_RETURN: MarkCurrentRead(); NextUnreadMessage(); return; + // scroll message text + case VK_UP: MessageTextUp(1); return; + case VK_DOWN: MessageTextDn(1); return; + case VK_PRIOR:MessageTextUp(_ctTextLinesOnScreen-1); return; + case VK_NEXT: MessageTextDn(_ctTextLinesOnScreen-1); return; + }; + } + + // if left mouse pressed + if (msg.message==WM_LBUTTONDOWN || msg.message==WM_LBUTTONDBLCLK) { + BOOL bOverMsgSlider = FALSE; + // if over slider + {PIXaabbox2D boxSlider = GetTextSliderBox(); + PIXaabbox2D boxSliderTrans = boxSlider; + boxSliderTrans+=_boxMsgText.Min(); + if (boxSliderTrans>=_vpixMouse) { + bOverMsgSlider = TRUE; + // start dragging + _bSliderDragText = TRUE; + _pixSliderDragJ=_vpixMouse(2); + _iSliderDragLine = _iTextLineOnScreen; + }} + + // if over slider + {PIXaabbox2D boxSlider = GetMsgSliderBox(); + PIXaabbox2D boxSliderTrans = boxSlider; + boxSliderTrans+=_boxMsgList.Min(); + if (boxSliderTrans>=_vpixMouse) { + // start dragging + _bSliderDragText = FALSE; + _pixSliderDragJ=_vpixMouse(2); + _iSliderDragLine = _iFirstMessageOnScreen; + }} + // if over some button + {for(INDEX i=0; i=_vpixMouse) { + // switch to that message type + _cmtWantedType = (CompMsgType)i; + } + }} + // if over some message + {for(INDEX i=0; i<_ctMessagesOnScreen; i++) { + if (GetMsgListBox(i)>=_vpixMouse && !bOverMsgSlider) { + // switch to that message + SelectMessage(_iFirstMessageOnScreen+i); + } + }} + } + + // if left mouse released + if (msg.message==WM_LBUTTONUP) { + // stop dragging + _pixSliderDragJ=-1; + // if over exit + if (_boxExit>=_vpixMouse) { + // exit + ExitRequested(); + } + } +} + +void CGame::ComputerRender(CDrawPort *pdp) +{ + // if playing a demo + if (_pNetwork->IsPlayingDemo()) { + // never call computer + cmp_ppenPlayer = NULL; + } + + // disable netricsa for non-local players + if (cmp_ppenPlayer!=NULL && !_pNetwork->IsPlayerLocal(cmp_ppenPlayer)) { + cmp_ppenPlayer = NULL; + } + if (cmp_ppenDHPlayer!=NULL && !_pNetwork->IsPlayerLocal(cmp_ppenDHPlayer)) { + cmp_ppenDHPlayer = NULL; + } + if (cmp_ppenDHPlayer!=NULL && !pdp->IsDualHead()) { + cmp_ppenDHPlayer = NULL; + } + + // initially - no player + _ppenPlayer=NULL; + + // if player calls computer + if (cmp_ppenPlayer!=NULL) { + // use that player + _ppenPlayer = cmp_ppenPlayer; + // if computer is on in background + if (_pGame->gm_csComputerState==CS_ONINBACKGROUND) { + // just toggle to on + _pGame->gm_csComputerState=CS_ON; + // find group with some unread messages + FindGroupWithUnread(); + // force reinit + _cmtCurrentType = (enum CompMsgType)-1; + } + // if using dualhead to render computer on second display + } else if (cmp_ppenDHPlayer!=NULL) { + // use that player + _ppenPlayer = cmp_ppenDHPlayer; + // clear dualhead request - it has to be reinitialized every frame + cmp_ppenDHPlayer = NULL; + + // if viewing statistics + if (_cmtWantedType == CMT_STATISTICS) { + // fill in fresh player statistics + _ppenPlayer->GetStats(_strStatsDetails, CST_DETAIL, _ctTextCharsPerRow); + // force updating + UpdateType(TRUE); + } + + // if computer is not on or on in background + if (_pGame->gm_csComputerState!=CS_ON && _pGame->gm_csComputerState!=CS_ONINBACKGROUND) { + // switch on fast + ComputerOn(); + fComputerFadeValue = 1.0f; + _pGame->gm_csComputerState = CS_ONINBACKGROUND; + cmp_bInitialStart = FALSE; // end of eventual initial start + } + + // if should update to new message + if (cmp_bUpdateInBackground) { + cmp_bUpdateInBackground = FALSE; + FindGroupWithUnread(); + // force reinit + _cmtCurrentType = (enum CompMsgType)-1; + } + } + + // if no player + if (_ppenPlayer==NULL) { + // make sure computer is off + _pGame->gm_csComputerState=CS_OFF; + // do nothing more + return; + } + + // if computer is not active + if (_pGame->gm_csComputerState==CS_OFF) { + // just remember time + tvComputerLast = _pTimer->GetHighPrecisionTimer(); + // if a player wants computer + if (_ppenPlayer!=NULL) { + // start turning on + _pGame->gm_csComputerState=CS_TURNINGON; + ComputerOn(); + } else { + return; + } + } + + // calculate up-down speed to be independent of refresh speed + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + CTimerValue tvDelta = tvNow - tvComputerLast; + tvComputerLast = tvNow; + FLOAT fFadeSpeed = (FLOAT)(tvDelta.GetSeconds() / tmComputerFade); + + // if computer is dropping down + if( _pGame->gm_csComputerState==CS_TURNINGON) { + // move it down + fComputerFadeValue += fFadeSpeed; + // if finished moving + if( fComputerFadeValue>1.0f) { + // stop + fComputerFadeValue = 1.0f; + _pGame->gm_csComputerState = CS_ON; + cmp_bInitialStart = FALSE; // end of eventual initial start + } + } + // if computer is pulling up + if( _pGame->gm_csComputerState==CS_TURNINGOFF) { + // move it up + fComputerFadeValue -= fFadeSpeed; + // if finished moving + if( fComputerFadeValue<0.0f) { + // stop + fComputerFadeValue = 0.0f; + _pGame->gm_csComputerState = CS_OFF; + ComputerOff(); + cmp_ppenPlayer = NULL; + // exit computer + return; + } + } + + // safety check -> do not proceed if no player + if (_ppenPlayer==NULL) { + return; + } + + // lock drawport + CDrawPort dpComp(pdp, FALSE); + if(!dpComp.Lock()) { + // do nothing + return; + } + + // if in fullscreen + CDisplayMode dmCurrent; + _pGfx->GetCurrentDisplayMode(dmCurrent); + if (dmCurrent.IsFullScreen() && dmCurrent.IsDualHead()) { + // clamp mouse pointer + _vpixMouse(1) = Clamp(_vpixMouse(1), 0L, dpComp.GetWidth()); + _vpixMouse(2) = Clamp(_vpixMouse(2), 0L, dpComp.GetHeight()); + // if in window + } else { + // use same mouse pointer as windows + _vpixMouse = _vpixExternMouse; + // if dualhead + if (dpComp.dp_MinI>0) { + // offset by half screen + _vpixMouse(1) -= dpComp.GetWidth(); + } + // if widescreen + if (dpComp.dp_MinJ>0) { + // offset by screen top + _vpixMouse(2) -= dpComp.dp_MinJ; + } + } + + TIME tmOld = _pTimer->CurrentTick(); + FLOAT fLerpOld = _pTimer->GetLerpFactor(); + + FLOAT fSec = tvNow.GetSeconds(); + TIME tmTick = floor(fSec/_pTimer->TickQuantum)*_pTimer->TickQuantum; + FLOAT fLerp = (fSec-tmTick)/_pTimer->TickQuantum; + _pTimer->SetCurrentTick(tmTick); + _pTimer->SetLerp(fLerp); + + LCDPrepare(1.0f);//ClampUp(fComputerFadeValue*10,1.0f)); + LCDSetDrawport(&dpComp); + // if initial start + if (cmp_bInitialStart) { + // do not allow game to show through + dpComp.Fill(C_BLACK|255); + // if normal start + } else { + // fade over game view + dpComp.Fill(LCDFadedColor(C_BLACK|255)); + } + dpComp.FillZBuffer(1.0f); + + // update screen geometry + UpdateSize(&dpComp); + // update scroll positions + UpdateType(); + UpdateFirstOnScreen(); + // check for message change + UpdateMessageAppearing(); + // mark current message as read + MarkCurrentRead(); + + // get current time and alpha value + FLOAT tmNow = (FLOAT)tvNow.GetSeconds(); + ULONG ulA = NormFloatToByte(fComputerFadeValue); + + _colLight = LCDFadedColor(C_WHITE|255); + _colMedium = LCDFadedColor(SE_COL_BLUE_LIGHT|255); + _colDark = LCDFadedColor(LerpColor(SE_COL_BLUE_DARK, SE_COL_BLUE_LIGHT, 0.5f)|255); + _colBoxes = LCDFadedColor(LerpColor(SE_COL_BLUE_DARK, SE_COL_BLUE_LIGHT, 0.5f)|255); + + // background + LCDRenderCloudsForComp(); +// dpComp.DrawLine( 0, pixSizeJ-1, pixSizeI, pixSizeJ-1, C_GREEN|ulA); + + // all done + dpComp.Unlock(); + + // print title + CDrawPort dpTitle(&dpComp, _boxTitle); + if (dpTitle.Lock()) { + LCDSetDrawport(&dpTitle); + LCDRenderCompGrid(); + LCDRenderClouds2(); + LCDScreenBoxOpenLeft(_colBoxes); + PrintTitle(&dpTitle); + dpTitle.Unlock(); + } + + // print exit button + CDrawPort dpExit(&dpComp, _boxExit); + if (dpExit.Lock()) { + LCDSetDrawport(&dpExit); + LCDRenderCompGrid(); + LCDRenderClouds2(); + LCDScreenBoxOpenRight(_colBoxes); + PrintExit(&dpExit); + dpExit.Unlock(); + } + + // print buttons + for (INDEX i=0; igm_csComputerState != CS_ONINBACKGROUND) { + if (dpComp.Lock()) { + LCDSetDrawport(&dpComp); + LCDDrawPointer(_vpixMouse(1), _vpixMouse(2)); + dpComp.Unlock(); + } + } + + _pTimer->SetCurrentTick(tmOld); + _pTimer->SetLerp(fLerpOld); +} + +void CGame::ComputerForceOff() +{ + cmp_ppenPlayer=NULL; + cmp_ppenDHPlayer=NULL; + _pGame->gm_csComputerState = CS_OFF; + fComputerFadeValue = 0.0f; + _ppenPlayer = NULL; +} diff --git a/Sources/GameMP/Computer.h b/Sources/GameMP/Computer.h new file mode 100644 index 0000000..1a53b22 --- /dev/null +++ b/Sources/GameMP/Computer.h @@ -0,0 +1,2 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + diff --git a/Sources/GameMP/Console.cpp b/Sources/GameMP/Console.cpp new file mode 100644 index 0000000..4e1dfd8 --- /dev/null +++ b/Sources/GameMP/Console.cpp @@ -0,0 +1,552 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +#include "StdAfx.h" +#include "LCDDrawing.h" + +extern CGame *_pGame; + +// console variables +static const FLOAT tmConsoleFade = 0.0f; // how many seconds it takes console to fade in/out +static FLOAT fConsoleFadeValue = 0.0f; // faded value of console (0..1) +static CTimerValue tvConsoleLast; + +static CTString strConsole; +static CTString strInputHistory = "\n"; +static CTString strEditingLine; +static CTString strExpandStart; +static CTString strLastExpanded; +static CTString strCurrentLine; +static BOOL bLastExpandedFound; +static INDEX iSymbolOffset; +static INDEX iHistoryLine=0; +static INDEX iCursorPos=0; +static INDEX ctConsoleLinesOnScreen; + +static INDEX con_iFirstLine = 1; +extern FLOAT con_fHeightFactor; +extern FLOAT con_tmLastLines; + +// find a line with given number in a multi-line string counting from end of string +BOOL GetLineCountBackward(const char *pchrStringStart, const char *pchrStringEnd, + INDEX iBackwardLine, CTString &strResult) +{ + // start at the end of string + const char *pchrCurrent = pchrStringEnd; + INDEX ctLinesDone=0; + + // while line of given number is not found + while(ctLinesDone!=iBackwardLine) { + // go one character back + pchrCurrent--; + // if got before start of string + if (pchrCurrent < pchrStringStart) { + // line is not found + return FALSE; + } + // if at line break + if(*pchrCurrent == '\n') { + // count lines + ctLinesDone++; + } + } + // check that pointer is not outside range + ASSERT(pchrCurrent>=pchrStringStart && pchrCurrentgm_csConsoleState==CS_OFF) { + con_iFirstLine = 1; + tvConsoleLast = _pTimer->GetHighPrecisionTimer(); + return; + } + + // get console height + con_fHeightFactor = Clamp( con_fHeightFactor, 0.1f, 1.0f); + FLOAT fHeightFactor = con_fHeightFactor; + if( !gm_bGameOn) fHeightFactor = 0.9f; + + // calculate up-down speed to be independent of refresh speed + CTimerValue tvNow = _pTimer->GetHighPrecisionTimer(); + CTimerValue tvDelta = tvNow - tvConsoleLast; + tvConsoleLast = tvNow; + FLOAT fFadeSpeed = (FLOAT)(tvDelta.GetSeconds() / tmConsoleFade); + + // if console is dropping down + if( _pGame->gm_csConsoleState==CS_TURNINGON) { + // move it down + fConsoleFadeValue += fFadeSpeed; + // if finished moving + if( fConsoleFadeValue>1.0f) { + // stop + fConsoleFadeValue = 1.0f; + _pGame->gm_csConsoleState = CS_ON; + } + } + // if console is pulling up + if( _pGame->gm_csConsoleState==CS_TURNINGOFF) { + // move it up + fConsoleFadeValue -= fFadeSpeed; + // if finished moving + if( fConsoleFadeValue<0.0f) { + // stop + fConsoleFadeValue = 0.0f; + _pGame->gm_csConsoleState = CS_OFF; + // if not in network + if (!_pNetwork->IsNetworkEnabled()) { + // don't show last lines on screen after exiting console + CON_DiscardLastLineTimes(); + } + return; + } + } + + if (_pGame->gm_csConsoleState==CS_TALK) { + fHeightFactor = 0.1f; + fConsoleFadeValue = 1.0f; + } + + // calculate size of console box so that it covers upper half of the screen + FLOAT fHeight = ClampUp( fHeightFactor*fConsoleFadeValue*2, fHeightFactor); + CDrawPort dpConsole( pdp, 0.0f, 0.0f, 1.0f, fHeight); + // lock drawport + if( !dpConsole.Lock()) return; + + LCDPrepare(fConsoleFadeValue); + LCDSetDrawport(&dpConsole); + dpConsole.Fill(LCDFadedColor(C_BLACK|225)); + + PIX pixSizeI = dpConsole.GetWidth(); + PIX pixSizeJ = dpConsole.GetHeight(); + COLOR colLight = LCDFadedColor(C_WHITE|255); + COLOR colDark = LCDFadedColor(SE_COL_BLUE_LIGHT|255); + INDEX iBackwardLine = con_iFirstLine; + if( iBackwardLine>1) Swap( colLight, colDark); + PIX pixLineSpacing = _pfdConsoleFont->fd_pixCharHeight + _pfdConsoleFont->fd_pixLineSpacing; + + LCDRenderCloudsForComp(); + //LCDRenderGrid(); + LCDRenderClouds2(); + dpConsole.DrawLine( 0, pixSizeJ-1, pixSizeI, pixSizeJ-1, LCDFadedColor(SE_COL_BLUE_NEUTRAL|255)); + const COLOR colFill = (colDark & ~CT_AMASK) | 0x2F; + dpConsole.Fill( 0, pixSizeJ-pixLineSpacing*1.6f, pixSizeI, pixLineSpacing*1.6f, colFill); + + // setup font + PIX pixTextX = (PIX)(dpConsole.GetWidth()*0.01f); + PIX pixYLine = dpConsole.GetHeight()-14; + dpConsole.SetFont( _pfdConsoleFont); + + // print editing line of text + dpConsole.SetTextMode(-1); + CTString strPrompt; + if (_pGame->gm_csConsoleState == CS_TALK) { + strPrompt = TRANS("say: "); + } else { + strPrompt = "=> "; + } + CTString strLineOnScreen = strPrompt + strEditingLine; + dpConsole.PutText( strLineOnScreen, pixTextX, pixYLine, colLight); + dpConsole.SetTextMode(+1); + + // add blinking cursor + if( ((ULONG)(_pTimer->GetRealTimeTick()*2)) & 1) { + CTString strCursor="_"; + FLOAT fTextScalingX = dpConsole.dp_fTextScaling * dpConsole.dp_fTextAspect; + PIX pixCellSize = _pfdConsoleFont->fd_pixCharWidth * fTextScalingX + dpConsole.dp_pixTextCharSpacing; + PIX pixCursorX = pixTextX + (iCursorPos+strlen(strPrompt))*pixCellSize; + dpConsole.PutText( strCursor, pixCursorX, pixYLine+2, colDark); + } + + // render previous outputs + con_iFirstLine = ClampDn( con_iFirstLine, 1L); + pixYLine -= (PIX)(pixLineSpacing * 1.333f); + ctConsoleLinesOnScreen = pixYLine/pixLineSpacing; + while( pixYLine >= 0) { + CTString strLineOnScreen = CON_GetLastLine(iBackwardLine); + dpConsole.PutText( strLineOnScreen, pixTextX, pixYLine, colDark); + iBackwardLine++; + pixYLine -= pixLineSpacing; + } + + // all done + dpConsole.Unlock(); +} + + +// print last few lines from console to top of screen +void CGame::ConsolePrintLastLines(CDrawPort *pdp) +{ + // get number of lines to print + con_tmLastLines = Clamp( con_tmLastLines, 1.0f, 10.0f); + INDEX ctLines = CON_NumberOfLinesAfter( _pTimer->GetRealTimeTick() - con_tmLastLines); + // if no lines left to print, just skip it + if( ctLines==0) return; + + // setup font + _pfdConsoleFont->SetFixedWidth(); + pdp->SetFont( _pfdConsoleFont); + PIX pixCharHeight = _pfdConsoleFont->GetHeight() -1; + // put some filter underneath for easier reading + pdp->Fill( 0, 0, pdp->GetWidth(), pixCharHeight*ctLines, C_BLACK|128); + // for each line + for( INDEX iLine=0; iLinePutText( strLine, 0, pixCharHeight*(ctLines-iLine-1), SE_COL_BLUE_LIGHT|255); + } +} + + +static void Key_Backspace( BOOL bShift, BOOL bRight) +{ + // do nothing if string is empty + INDEX ctChars = strlen(strEditingLine); + if( ctChars==0) return; + + if( bRight && iCursorPos0) { // BACKSPACE key + if( bShift) { // delete to start of line + strEditingLine.TrimLeft(ctChars-iCursorPos); + iCursorPos=0; + } else { // delete only one char + strEditingLine.DeleteChar(iCursorPos-1); + iCursorPos--; + } + } +} + + +static void Key_ArrowUp(void) +{ + CTString strSlash = "/"; + CTString strHistoryLine; + if( iHistoryLine==0) strCurrentLine = strEditingLine; + INDEX iCurrentHistoryLine = iHistoryLine; + do { + // determine previous line in history + iCurrentHistoryLine++; + const char *pchrHistoryStart = (const char*)strInputHistory; + const char *pchrHistoryEnd = pchrHistoryStart +strlen( strInputHistory) -1; + // we reach top of history, if line doesn't exist in history + if( !GetLineCountBackward( pchrHistoryStart, pchrHistoryEnd, iCurrentHistoryLine, strHistoryLine)) return; + } while( strCurrentLine!="" && + strnicmp( strHistoryLine, strCurrentLine, Min(strlen(strHistoryLine), strlen(strCurrentLine)))!=0 && + strnicmp( strHistoryLine, strSlash+strCurrentLine, Min(strlen(strHistoryLine), strlen(strCurrentLine)+1))!=0); + // set new editing line + iHistoryLine = iCurrentHistoryLine; + strEditingLine = strHistoryLine; + iCursorPos = strlen(strEditingLine); +} + + +static void Key_ArrowDown(void) +{ + CTString strSlash = "/"; + CTString strHistoryLine; + if( iHistoryLine==0) strCurrentLine = strEditingLine; + INDEX iCurrentHistoryLine = iHistoryLine; + while( iCurrentHistoryLine>1) { + iCurrentHistoryLine--; + const char *pchrHistoryStart = (const char *) strInputHistory; + const char *pchrHistoryEnd = pchrHistoryStart +strlen(strInputHistory) -1; + // line must exist in history + BOOL bExists = GetLineCountBackward( pchrHistoryStart, pchrHistoryEnd, iCurrentHistoryLine, strHistoryLine); + ASSERT( bExists); + // set new editing line + if( strCurrentLine=="" || + strnicmp( strHistoryLine, strCurrentLine, Min(strlen(strHistoryLine), strlen(strCurrentLine))) ==0 || + strnicmp( strHistoryLine, strSlash+strCurrentLine, Min(strlen(strHistoryLine), strlen(strCurrentLine)+1))==0) { + iHistoryLine = iCurrentHistoryLine; + strEditingLine = strHistoryLine; + iCursorPos = strlen(strEditingLine); + return; + } + } +} + +void DoCheat(const CTString &strCommand, const CTString &strVar) +{ + _pShell->SetINDEX(strVar, !_pShell->GetINDEX(strVar)); + BOOL bNew = _pShell->GetINDEX(strVar); + CPrintF("%s: %s\n", strCommand, bNew?"ON":"OFF"); +} + +static void Key_Return(void) +{ + // ignore keydown return (keyup will be handled) - because of key bind to return + //if( _pGame->gm_csConsoleState==CS_TALK) return; + + // clear editing line from whitespaces + strEditingLine.TrimSpacesLeft(); + strEditingLine.TrimSpacesRight(); + // reset display position + con_iFirstLine = 1; + + // ignore empty lines + if( strEditingLine=="" || strEditingLine=="/") { + strEditingLine = ""; + iCursorPos = 0; + return; + } + + // add to history + strInputHistory += strEditingLine +"\r\n"; + iHistoryLine = 0; + + // check for cheats + #define CHEAT_PREFIX "please" + if (strEditingLine.HasPrefix(CHEAT_PREFIX) || strEditingLine.HasPrefix("/" CHEAT_PREFIX)) { + strEditingLine.RemovePrefix(CHEAT_PREFIX); + strEditingLine.RemovePrefix("/ " CHEAT_PREFIX ); + strEditingLine.TrimSpacesLeft(); + if (strEditingLine=="god") { + DoCheat(strEditingLine, "cht_bGod"); + + } else if (strEditingLine=="giveall") { + DoCheat(strEditingLine, "cht_bGiveAll"); + + } else if (strEditingLine=="killall") { + DoCheat(strEditingLine, "cht_bKillAll"); + + } else if (strEditingLine=="open") { + DoCheat(strEditingLine, "cht_bOpen"); + + } else if (strEditingLine=="tellall") { + DoCheat(strEditingLine, "cht_bAllMessages"); + + } else if (strEditingLine=="fly") { + DoCheat(strEditingLine, "cht_bFly"); + + } else if (strEditingLine=="ghost") { + DoCheat(strEditingLine, "cht_bGhost"); + + } else if (strEditingLine=="invisible") { + DoCheat(strEditingLine, "cht_bInvisible"); + + } else if (strEditingLine=="refresh") { + DoCheat(strEditingLine, "cht_bRefresh"); + } else { + CPrintF("sorry?\n"); + } + // parse editing line + } else if( strEditingLine[0]=='/') { + // add to output and execute + CPrintF( "-> %s\n", strEditingLine); + strEditingLine+=";"; + _pShell->Execute(strEditingLine+1); + } + else if( !_pGame->gm_bGameOn) { + // add to output and execute + CPrintF( "-> %s\n", strEditingLine); + strEditingLine+=";"; + _pShell->Execute(strEditingLine); + } + else { + // just send chat + _pNetwork->SendChat(-1, -1, strEditingLine); + } + + // reset editing line + strEditingLine = ""; + iCursorPos = 0; +} + + +// find first character that is not part of a symbol, backwards +char *strrnonsym(const char *strString) +{ + const char *pch = strString+strlen(strString)-1; + while( pch>=strString) { + char ch = *pch; + if( !isalnum(ch) && ch!='_') return (char*)pch; + pch--; + } + return NULL; +} + + +static void Key_Tab( BOOL bShift) +{ + // clear editing line from whitespaces + strEditingLine.TrimSpacesLeft(); + strEditingLine.TrimSpacesRight(); + // eventualy prepend the command like with '/' + if (strEditingLine[0]!='/') strEditingLine = CTString("/")+strEditingLine; + + // find symbol letter typed so far + CTString strSymbol; + CTString strLastThatCanBeExpanded; + if( strLastExpanded == "") { + strExpandStart = strEditingLine; + iSymbolOffset = 0; + char *pcLastSymbol = strrnonsym( strEditingLine); + // remember symbol text and offset inside editing line + if( pcLastSymbol!=NULL) { + strExpandStart = pcLastSymbol+1; + iSymbolOffset = (INDEX)(pcLastSymbol+1 - (const char*)strEditingLine); + } + // printout all symbols that matches (if not only one, and not TAB only) + INDEX ctSymbolsFound=0; + BOOL bFirstFound = FALSE; + CTString strLastMatched; + {FOREACHINDYNAMICARRAY( _pShell->sh_assSymbols, CShellSymbol, itss) { + // TAB only pressd? + if( strExpandStart=="") break; + // get completion name if current symbol is for user + if( !(itss->ss_ulFlags&SSF_USER)) continue; + strSymbol = itss->GetCompletionString(); + // if this symbol can be expanded + if( strnicmp( strSymbol, strExpandStart, Min(strlen(strSymbol),strlen(strExpandStart))) == 0) { + // can we print last found symbol ? + if( strLastMatched!="") { + if( !bFirstFound) CPrintF( " -\n"); + CPrintF( " %s\n", strLastMatched); + bFirstFound = TRUE; + } + strLastMatched = strSymbol; + ctSymbolsFound++; + } + }} + // print last symbol + if( ctSymbolsFound>1) CPrintF( " %s\n", strLastMatched); + } + + // for each of symbols in the shell + bLastExpandedFound = FALSE; + BOOL bTabSymbolFound = FALSE; + {FOREACHINDYNAMICARRAY( _pShell->sh_assSymbols, CShellSymbol, itss) + { + // skip if it is not visible to user + if( !(itss->ss_ulFlags&SSF_USER)) continue; + // get completion name for that symbol + strSymbol = itss->GetCompletionString(); + + // if this symbol can be expanded + if( strnicmp( strSymbol, strExpandStart, Min(strlen(strSymbol),strlen(strExpandStart))) == 0) + { + // at least one symbol is found, so tab will work + bTabSymbolFound = TRUE; + // if this is first time we are doing this + if( strLastExpanded == "") { + // remember symbol as last expanded and set it as current + strLastExpanded = strSymbol; + break; + } + // if last expanded was already found, set this symbol as result and remember it as last expanded + if( bLastExpandedFound) { + strLastExpanded = strSymbol; + break; + } + // if last expanded was not found yet, check if this one is last expanded + if( stricmp( strLastExpanded, strSymbol) == 0) { + // if looping backward (Shift+Tab) + if( bShift) { + // if we can loop backwards + if( strLastThatCanBeExpanded != "") { + strLastExpanded = strLastThatCanBeExpanded; + break; + // act like no symbols are found + } else { + bTabSymbolFound = FALSE; + break; + } + } + // if so, mark it + bLastExpandedFound = TRUE; + } + // remember current as last that can be expanded (for loopbing back) + strLastThatCanBeExpanded = strSymbol; + } + }} + // if symbol was found + if( bTabSymbolFound) { + // set it in current editing line + *((char*)(const char*)strEditingLine +iSymbolOffset) = '\0'; + strEditingLine += strLastExpanded; + } + iCursorPos = strlen(strEditingLine); +} + + +static void Key_PgUp( BOOL bShift) +{ + if( bShift) con_iFirstLine += ctConsoleLinesOnScreen; + else con_iFirstLine++; +} + + +static void Key_PgDn( BOOL bShift) +{ + if( bShift) con_iFirstLine -= ctConsoleLinesOnScreen; + else con_iFirstLine--; + con_iFirstLine = ClampDn( con_iFirstLine, 1L); +} + + +void CGame::ConsoleKeyDown( MSG msg) +{ + // if console is off + if (_pGame->gm_csConsoleState==CS_OFF || _pGame->gm_csConsoleState==CS_TURNINGOFF) { + // do nothing + return; + } + BOOL bShift = GetKeyState(VK_SHIFT) & 0x8000; + switch( msg.wParam) { + case VK_RETURN: Key_Return(); break; + case VK_UP: Key_ArrowUp(); break; + case VK_DOWN: Key_ArrowDown(); break; + case VK_TAB: Key_Tab(bShift); break; + case VK_PRIOR: Key_PgUp(bShift); break; + case VK_NEXT: Key_PgDn(bShift); break; + case VK_BACK: Key_Backspace(bShift, FALSE); break; + case VK_DELETE: Key_Backspace(bShift, TRUE); break; + case VK_LEFT: if( iCursorPos > 0) iCursorPos--; break; + case VK_RIGHT: if( iCursorPos < strlen(strEditingLine)) iCursorPos++; break; + case VK_HOME: iCursorPos = 0; break; + case VK_END: iCursorPos = strlen(strEditingLine); break; + } +} + + +void CGame::ConsoleChar( MSG msg) +{ + // if console is off, do nothing + if (_pGame->gm_csConsoleState==CS_OFF) return; + + // for all keys except tab and shift, discard last found tab browsing symbol + char chrKey = msg.wParam; + if( msg.wParam!=VK_TAB && msg.wParam!=VK_SHIFT) strLastExpanded = ""; + + // if key with letter pressed + if( isprint(chrKey) && chrKey!='`') { + // insert it to editing line + strEditingLine.InsertChar( iCursorPos, chrKey); + iCursorPos++; + // reset history line + iHistoryLine = 0; + } +} + diff --git a/Sources/GameMP/Controls.cpp b/Sources/GameMP/Controls.cpp new file mode 100644 index 0000000..a11aec8 --- /dev/null +++ b/Sources/GameMP/Controls.cpp @@ -0,0 +1,413 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +/* + * Game library + * Copyright (c) 1997-1999, CroTeam. All rights reserved. + */ + +#include "stdafx.h" + +extern CGame *_pGame; + +/* + * Default constructor + */ +CControls::CControls(void) +{ + // buttons are all none anyway (empty list) + // switch axes actions to defaults + SwitchAxesToDefaults(); +} + +/* + * Default destructor + */ +CControls::~CControls(void) +{ + // for each action in the original list + FORDELETELIST(CButtonAction, ba_lnNode, ctrl_lhButtonActions, itButtonAction) + { + // delete button action + delete( &*itButtonAction); + } +} + +// Assignment operator. +CControls &CControls::operator=(CControls &ctrlOriginal) +{ + // remove old button actions + {FORDELETELIST(CButtonAction, ba_lnNode, ctrl_lhButtonActions, itButtonAction) { + delete &*itButtonAction; + }} + // for each action in the original list + {FOREACHINLIST(CButtonAction, ba_lnNode, ctrlOriginal.ctrl_lhButtonActions, itButtonAction) { + // create and copy button action + AddButtonAction() = *itButtonAction; + }} + + // for all axis-type actions + for( INDEX iAxisAction=0; iAxisActionGetButtonName( iButton) == strKeyName) return iButton; + } + return KID_NONE; +} + +CTString ReadTextLine(CTStream &strm, const CTString &strKeyword, BOOL bTranslate) +{ + CTString strLine; + strm.GetLine_t(strLine); + strLine.TrimSpacesLeft(); + if (!strLine.RemovePrefix(strKeyword)) { + return "???"; + } + strLine.TrimSpacesLeft(); + if (bTranslate) { + strLine.RemovePrefix("TTRS"); + } + strLine.TrimSpacesLeft(); + strLine.TrimSpacesRight(); + + return strLine; +} + +void CControls::Load_t( CTFileName fnFile) +{ + char achrLine[ 1024]; + char achrName[ 1024]; + char achrID[ 1024]; + char achrActionName[ 1024]; + + // open script file for reading + CTFileStream strmFile; + strmFile.Open_t( fnFile); + + // if file can be opened for reading remove old button actions + {FORDELETELIST(CButtonAction, ba_lnNode, ctrl_lhButtonActions, itButtonAction) { + delete &*itButtonAction; + }} + + do + { + achrLine[0] = 0; + achrID[0] = 0; + strmFile.GetLine_t( achrLine, 1024); + sscanf( achrLine, "%s", achrID); + // if name + if( CTString( achrID) == "Name") { + // name is obsolete, just skip it + sscanf( achrLine, "%*[^\"]\"%1024[^\"]\"", achrName); + + // if this is button action + } else if( CTString( achrID) == "Button") { + // create and read button action + CButtonAction &baNew = AddButtonAction(); + baNew.ba_strName = ReadTextLine(strmFile, "Name:", TRUE); + + baNew.ba_iFirstKey = DIKForName( ReadTextLine(strmFile, "Key1:", FALSE)); + baNew.ba_iSecondKey = DIKForName( ReadTextLine(strmFile, "Key2:", FALSE)); + + baNew.ba_strCommandLineWhenPressed = ReadTextLine(strmFile, "Pressed:", FALSE); + baNew.ba_strCommandLineWhenReleased = ReadTextLine(strmFile, "Released:", FALSE); + + // if this is axis action + } else if( CTString( achrID) == "Axis") { + char achrAxis[ 1024]; + achrAxis[ 0] = 0; + char achrIfInverted[ 1024]; + achrIfInverted[ 0] = 0; + char achrIfRelative[ 1024]; + achrIfRelative[ 0] = 0; + char achrIfSmooth[ 1024]; + achrIfSmooth[ 0] = 0; + achrActionName[ 0] = 0; + FLOAT fSensitivity = 50; + FLOAT fDeadZone = 0; + sscanf( achrLine, "%*[^\"]\"%1024[^\"]\"%*[^\"]\"%1024[^\"]\" %g %g %1024s %1024s", + achrActionName, achrAxis, &fSensitivity, &fDeadZone, achrIfInverted, achrIfRelative, achrIfSmooth); + // find action axis + INDEX iActionAxisNo = -1; + {for( INDEX iAxis=0; iAxisgm_astrAxisNames[iAxis]) == achrActionName) + { + iActionAxisNo = iAxis; + break; + } + }} + // find controller axis + INDEX iCtrlAxisNo = -1; + {for( INDEX iAxis=0; iAxisGetAxisName( iAxis) == achrAxis) + { + iCtrlAxisNo = iAxis; + break; + } + }} + // if valid axis found + if( iActionAxisNo!=-1 && iCtrlAxisNo!=-1) { + // set it + ctrl_aaAxisActions[ iActionAxisNo].aa_iAxisAction = iCtrlAxisNo; + ctrl_aaAxisActions[ iActionAxisNo].aa_fSensitivity = fSensitivity; + ctrl_aaAxisActions[ iActionAxisNo].aa_fDeadZone = fDeadZone; + ctrl_aaAxisActions[ iActionAxisNo].aa_bInvert = ( CTString( "Inverted") == achrIfInverted); + ctrl_aaAxisActions[ iActionAxisNo].aa_bRelativeControler = ( CTString( "Relative") == achrIfRelative); + ctrl_aaAxisActions[ iActionAxisNo].aa_bSmooth = ( CTString( "Smooth") == achrIfRelative); + } + // read global parameters + } else if( CTString( achrID) == "GlobalInvertLook") { + ctrl_bInvertLook = TRUE; + } else if( CTString( achrID) == "GlobalDontInvertLook") { + ctrl_bInvertLook = FALSE; + } else if( CTString( achrID) == "GlobalSmoothAxes") { + ctrl_bSmoothAxes = TRUE; + } else if( CTString( achrID) == "GlobalDontSmoothAxes") { + ctrl_bSmoothAxes = FALSE; + } else if( CTString( achrID) == "GlobalSensitivity") { + sscanf( achrLine, "GlobalSensitivity %g", &ctrl_fSensitivity); + } + } + while( !strmFile.AtEOF()); + +/* + // search for talk button + BOOL bHasTalk = FALSE; + BOOL bHasT = FALSE; + FOREACHINLIST( CButtonAction, ba_lnNode, ctrl_lhButtonActions, itba) { + CButtonAction &ba = *itba; + if (ba.ba_strName=="Talk") { + bHasTalk = TRUE; + } + if (ba.ba_iFirstKey==KID_T) { + bHasT = TRUE; + } + if (ba.ba_iSecondKey==KID_T) { + bHasT = TRUE; + } + } + // if talk button not found + if (!bHasTalk) { + // add it + CButtonAction &baNew = AddButtonAction(); + baNew.ba_strName = "Talk"; + baNew.ba_iFirstKey = KID_NONE; + baNew.ba_iSecondKey = KID_NONE; + baNew.ba_strCommandLineWhenPressed = " con_bTalk=1;"; + baNew.ba_strCommandLineWhenReleased = ""; + // if T key is not bound to anything + if (!bHasT) { + // bind it to talk + baNew.ba_iFirstKey = KID_T; + // if we couldn't bind it + } else { + // put it to the top of the list + baNew.ba_lnNode.Remove(); + ctrl_lhButtonActions.AddHead(baNew.ba_lnNode); + } + } + */ + + CalculateInfluencesForAllAxis(); +} + +void CControls::Save_t( CTFileName fnFile) +{ + CTString strLine; + // create file + CTFileStream strmFile; + strmFile.Create_t( fnFile, CTStream::CM_TEXT); + + // write button actions + FOREACHINLIST( CButtonAction, ba_lnNode, ctrl_lhButtonActions, itba) + { + strLine.PrintF("Button\n Name: TTRS %s\n Key1: %s\n Key2: %s", + itba->ba_strName, + _pInput->GetButtonName( itba->ba_iFirstKey), + _pInput->GetButtonName( itba->ba_iSecondKey) ); + strmFile.PutLine_t( strLine); + + // export pressed command + strLine.PrintF(" Pressed: %s", itba->ba_strCommandLineWhenPressed); + {for( INDEX iLetter = 0; strLine[ iLetter] != 0; iLetter++) + { + // delete EOL-s + if( (strLine[ iLetter] == 0x0d) || (strLine[ iLetter] == 0x0a) ) + { + ((char*)(const char*)strLine)[ iLetter] = ' '; + } + }} + strmFile.PutLine_t( strLine); + + // export released command + strLine.PrintF(" Released: %s", itba->ba_strCommandLineWhenReleased); + {for( INDEX iLetter = 0; strLine[ iLetter] != 0; iLetter++) + { + // delete EOL-s + if( (strLine[ iLetter] == 0x0d) || (strLine[ iLetter] == 0x0a) ) + { + ((char*)(const char*)strLine)[ iLetter] = ' '; + } + }} + strmFile.PutLine_t( strLine); + } + // write axis actions + for( INDEX iAxis=0; iAxisgm_astrAxisNames[iAxis], + _pInput->GetAxisName(ctrl_aaAxisActions[iAxis].aa_iAxisAction), + ctrl_aaAxisActions[ iAxis].aa_fSensitivity, + ctrl_aaAxisActions[ iAxis].aa_fDeadZone, + strIfInverted, + strIfRelative, + strIfSmooth); + strmFile.PutLine_t( strLine); + } + + // write global parameters + if (ctrl_bInvertLook) { + strmFile.PutLine_t( "GlobalInvertLook"); + } else { + strmFile.PutLine_t( "GlobalDontInvertLook"); + } + if (ctrl_bSmoothAxes) { + strmFile.PutLine_t( "GlobalSmoothAxes"); + } else { + strmFile.PutLine_t( "GlobalDontSmoothAxes"); + } + strmFile.FPrintF_t("GlobalSensitivity %g\n", ctrl_fSensitivity); +} + +// check if these controls use any joystick +BOOL CControls::UsesJoystick(void) +{ + // for each button + FOREACHINLIST( CButtonAction, ba_lnNode, ctrl_lhButtonActions, itba) { + CButtonAction &ba = *itba; + if (ba.ba_iFirstKey>=FIRST_JOYBUTTON || ba.ba_iSecondKey>=FIRST_JOYBUTTON) { + return TRUE; + } + } + + // write axis actions + for( INDEX iAxis=0; iAxis=FIRST_JOYAXIS) { + return TRUE; + } + } + + return FALSE; +} + diff --git a/Sources/GameMP/Game.cpp b/Sources/GameMP/Game.cpp new file mode 100644 index 0000000..d374a8a --- /dev/null +++ b/Sources/GameMP/Game.cpp @@ -0,0 +1,3001 @@ +/* Copyright (c) 2002-2012 Croteam Ltd. All rights reserved. */ + +// Game.cpp : Defines the initialization routines for the DLL. +// + +#include "stdafx.h" +#include "Game.h" +#include // for _mkdir() +#include +#include +#include +#include +#include +#include +#include +#include "Camera.h" +#include "LCDDrawing.h" + +extern FLOAT con_fHeightFactor = 0.5f; +extern FLOAT con_tmLastLines = 5.0f; +extern INDEX con_bTalk = 0; +CTimerValue _tvMenuQuickSave(0I64); + +// used filenames +CTFileName fnmPersistentSymbols = CTString("Scripts\\PersistentSymbols.ini"); +CTFileName fnmStartupScript = CTString("Scripts\\Game_startup.ini"); +CTFileName fnmConsoleHistory = CTString("Temp\\ConsoleHistory.txt"); +CTFileName fnmCommonControls = CTString("Controls\\System\\Common.ctl"); + +// force dependency for player class +DECLARE_CTFILENAME( fnmPlayerClass, "Classes\\Player.ecl"); + +#define MAX_HIGHSCORENAME 16 +#define MAX_HIGHSCORETABLESIZE ((MAX_HIGHSCORENAME+1+sizeof(INDEX)*4)*HIGHSCORE_COUNT)*2 +UBYTE _aubHighScoreBuffer[MAX_HIGHSCORETABLESIZE]; +UBYTE _aubHighScorePacked[MAX_HIGHSCORETABLESIZE]; + +// controls used for all commands not belonging to any particular player +static CControls _ctrlCommonControls; + +// array for keeping all frames' times +static CStaticStackArray